|
Post by dshadoff on Apr 30, 2019 1:39:38 GMT
...Can you even use a mouse and MB128 together ? (i.e. does any game work in this configuration ?) ...And as for the MB128 + multitap, the MB128 would need to be plugged into the PC Engine, with the multitap plugged into it... I hope that people weren't trying it the other way around (it wouldn't work due to the protocol).
|
|
gilbot
Punkic Cyborg
Posts: 137
|
Post by gilbot on Apr 30, 2019 3:05:32 GMT
Yes. I think most of Koei's simulation games work with both the mouse and the MB128 (possibly A-III too). Princess Maker 2 should work too, as this game supports nearly all add-ons. Also, Magicool. It has a bug that the MB128 cannot be used together with the multitap (you can save games to the MB128 but the game would freeze loading them) but I think mouse+MB128 is okay.
|
|
|
Post by elmer on Apr 30, 2019 4:19:57 GMT
From my tests, the boot/reset command sequence should only be needed if the wakeup/detect sequence fails (in order to unjam the MB128). ... I don't know if there's anything special about running the wakeup sequence 256 times in a row, the way that the boot/reset code does. Perhaps there's a counter in the ASIC ... or perhaps I just got lucky and that was enough data reads/writes to finish off the data that I was reading and terminate the read/write normally. That should be pretty easy to test. I finally ran another test on this, now that I can load up to 128KB from the MB128 in a single call ... and my earlier finding was spectacularly *wrong*! The mb128_boot/mb128_reset sequence is totally bogus in those functions. Maybe it has another use, for some undefined purpose, but it definitely does not get any special detection by the MB128. If you request a transfer of 128KB-1 bytes, then the MB128 is not going to stop transferring and release the joypad until you've read/written 128KB-1 bytes of data. There is no shortcut.
|
|
|
Post by dshadoff on Apr 30, 2019 4:28:13 GMT
The mb128_boot/mb128_reset sequence is totally bogus in those functions. Maybe it has another use, for some undefined purpose, but it definitely does not get any special detection by the MB128. If you request a transfer of 128KB-1 bytes, then the MB128 is not going to stop transferring and release the joypad until you've read/written 128KB-1 bytes of data. There is no shortcut. That's what I was expecting. Any "in-transit" transfer will be depleted by enough transmissions of any type (0xA8, boot, whatever), and most will re-sync quickly with an 0xA8 once the transfer is over. This is a probable reason why they didn't bother trying to go for a larger sector size - jams become intractable.
|
|
|
Post by elmer on Apr 30, 2019 22:07:45 GMT
...Can you even use a mouse and MB128 together ? (i.e. does any game work in this configuration ?) Yep, the combination is fine in theory. Early games, like Lemmings, had a really janky method of detecting the mouse that might have interfered with the MB128. Theoretically, I currently believe that you *should* be able to support an MB128, multitap, more than one mouse, and a 6-button joypad all plugged-in together ... but the code to do so would be rather ugly! As another note, I've finally realized what the function that Mooz calls mb128_reset is actually for. It's really just the standalone function (to run at bootup) to detect that an MB128 is plugged into the console. The single-bit read is there so that the MB128 goes back to sleep cleanly afterwards, all primed and ready to wakeup when it's used later on. You can't use what Mooz calls mb128_detect to do that, because your next joypad read would be misinterpreted as an attempt to write data to the MB128. The whole extended wakeup retry-count at the beginning of an mb128_boot is just there as an attempt to unjam the MB128 if you didn't complete a previous read/write properly. The Private EyeDol game never ever calls reset/detect routine.
|
|
|
Post by dshadoff on Apr 30, 2019 22:45:50 GMT
The single-bit read is there so that the MB128 goes back to sleep cleanly afterwards, all primed and ready to wakeup when it's used later on. You can't use what Mooz calls mb128_detect to do that, because your next joypad read would be misinterpreted as an attempt to write data to the MB128. This makes sense.
|
|
|
Post by elmer on May 2, 2019 2:49:49 GMT
*FINALLY* ... Here's a company that actually knows how to write assembly language code ...
From Koei's Genghis Khan, here's their MB128/Save-Kun inner-loops ...
; ; Send Bits to MB128 ;
$81:601B txa ; 8A $81:601C and #$01 ; 29 01 $81:601E sta $1000 ; 8D 00 10 - RWCLK hi 13 cycles $81:6021 nop ; EA $81:6022 nop ; EA $81:6023 nop ; EA $81:6024 ora #$02 ; 09 02 $81:6026 sta $1000 ; 8D 00 10 - RWCLK lo 30 cycles $81:6029 pha ; 48 $81:602A txa ; 8A $81:602B lsr a ; 4A $81:602C tax ; AA $81:602D pla ; 68 $81:602E and #$FD ; 29 FD $81:6030 dey ; 88 $81:6031 bne $601B ; D0 E8
$81:6033 nop ; EA $81:6034 nop ; EA $81:6035 stz $1000 ; 9C 00 10 $81:6038 rts ; 60
; ; Recv Byte from MB128 ;
$81:6039 ldy #$08 ; A0 08
$81:603B lda #$02 ; A9 02 $81:603D sta $1000 ; 8D 00 10 - RWCLK lo 29 cycles $81:6040 pha ; 48 $81:6041 pla ; 68 $81:6042 nop ; EA $81:6043 lda $1000 ; AD 00 10 $81:6046 ror a ; 6A $81:6047 sax ; 22 $81:6048 ror a ; 6A $81:6049 sax ; 22 $81:604A stz $1000 ; 9C 00 10 - RWCLK hi 13 cycles $81:604D dey ; 88 $81:604E bne $603B ; D0 EB $81:6050 rts ; 60
|
|
mooz
Deep Blooper
Posts: 29
|
Post by mooz on May 3, 2019 8:44:37 GMT
Note that the code in the doc, is a kind of synthesis of the code I extracted from Shin Megami Tensei, Emerald Dragoon and Tadaima Yusha Boshuuchuu. I'll update the doc and code sample as soon as possible (which unfortunately means 'not before June'). Anyway as it's hosted on Github, if you can't wait for an update, fork it and send me wrathful push requests
|
|
|
Post by elmer on May 3, 2019 20:18:51 GMT
Anyway as it's hosted on Github, if you can't wait for an update, fork it and send me wrathful push requests I'm not having a go at you ... I'm sorry if you thought that. You've done an excellent job in trying to forensically figure out how to use the MB128 from the clues in the code that you've looked at, and your publicly-available documentation has been a huge time-saver in trying to figure out what it going on (just as it was with your conversion of KRIKzz's edio.c into assembly language for the SD card routines). AIII, Princess Maker 2 and Vasteel 2 all use basically the same code as the examples that you've looked at. It's not until Private EyeDol that I could see something a bit more-efficient in its access. Then Koei's code in Genghis Khan finally confirms that the MB128 really is edge-triggered and not level-triggered, and that you can remove one of the three writes/delays in the other games' code, which is what I expected from the MSM6389's datasheet, and from my own tests. Koei's code also shows that the MB128/Save-Kun hardware is normally operated with a 6us-per-bit cycle, 4us RWCLK-lo, and 2us RWCLK-hi. All good information that you couldn't really have gleaned from the code in the other games. As for your github documentation ... I absolutely *hate* doing pretty documentation, so I'm afraid that I'll leave that up to you. I've documented my findings here, as has dshadoff , and I tend to heavily-comment the source-code that I write ... that's my preferred way to do things. For instance, here's the section at the top of my current source ... ; *************************************************************************** ; *************************************************************************** ; ; The MB128 is built around an MSM6389 1Mbit (128KByte) serial memory chip. ; ; That memory chip is accessed by the PC Engine one bit at a time, through ; the joypad port. ; ; The MB128 normally allows the joypad port's signals to directly pass ; through to any attached joypad/mouse/multitap devices. ; ; When it detects a specific "wakeup" sequence on the joypad port, it takes ; control of the port and locks-out the other devices. ; ; You then send the MB128 a command, and when the command is finished, the ; MB128 releases the joypad port, and waits for the next "wakeup" sequence. ; ; ; The MB128 only responds to two commands, READ BITS and WRITE BITS. ; ; READ BITS ; ; 1 <addr> <size> ... MB128 then sends <data> ... PCE sends 3 zero-bits. ; ; WRITE BITS ; ; 0 <addr> <size> ... MB128 then receives <data> ... PCE sends 5 zero-bits. ; ; <addr> is a 10-bit value, in 128-byte increments within the 1Mbit range. ; ; The code actually uses an 8-bit value of nominal 512-byte "sectors". ; ; <size> is a 20-bit value, as the # of bits to transfer. ; ; The code actually uses an 8-bit value of nominal 512-byte "sectors". ; ; <addr>, <size>, and <data> are all little-endian values, sent and received ; low-bit first. ; ; The final bits of each command that the PCE sends seem designed to flush ; out the MB128's internal shift-registers, and to prepare the MB128's ; sequence-detector for the next "wakeup" sequence. ; ; *************************************************************************** ; ***************************************************************************
|
|
mooz
Deep Blooper
Posts: 29
|
Post by mooz on May 5, 2019 21:43:48 GMT
I'm not having a go at you ... I'm sorry if you thought that. Not at all I was just saying that as a kind of disclaimer for people hopping into the train. About the doc, maybe I'll switch to some markdown/textbook-thingy that let me integrate wavedrom diagrams.
|
|
|
Post by dshadoff on May 20, 2019 14:44:58 GMT
Then Koei's code in Genghis Khan finally confirms that the MB128 really is edge-triggered and not level-triggered, and that you can remove one of the three writes/delays in the other games' code, which is what I expected from the MSM6389's datasheet, and from my own tests. Koei's code also shows that the MB128/Save-Kun hardware is normally operated with a 6us-per-bit cycle, 4us RWCLK-lo, and 2us RWCLK-hi. This is true, but I think I should add a few points: Yes, it is edge-triggered, and it would seem that it is driven by the transition from 0 to 1 on the CLK (normally RESET) line... (though one could argue the opposite for certain scenarios). But because of electrical distortion during transmission, they wanted to make sure that the DATA line had settled before this transition took place. Seeing the oscilloscope reading that I posted in the Personal Projects thread on this subject, this is a good measure, but 9 cycles is way more than adequate for this (perhaps 2 cycles would be sufficient to cover all cases, and in most cases it may not even be necessary). I wouldn't say that the MB128 is normally operated with 2us high and 4us low; the (memory chip) datasheet states that the full cycle must be at least 4.0us, and the enable must be at least 3.0us. Since the sense of this line is active-low, we have speculated that it is either (a) anti-sense from the PCE-driven CLK line, or synthetically-created by the custom chip. But in any case, the measurements (duration of high, and duration of complete cycle) should be considered minimums. With respect to the comments, the following should be added: When the PCE is sending '0' bits, the reason can be one of the following: 1) actually sending a '0' to the unit 2) simply clocking a read request, where data is expected to return from the unit 3) apparently flushing the shift registers in the custom chip. Note that the 3 last trailing bits on the end of the READ and WRITE functions appear to be flushing the shift registers. HOWEVER, the WRITE function actually 5 bits - the first 2 of these appear to be data sent back from the MB128 unit to the PCE, and as far as I can tell, always show as {'1', '0'}. Emerald Dragon appears to validate writes by checking the second of these as being '0'. The hardware unit appears to have no specific organization by bit, byte or sector. These are all software-based conventions. - When storing or retrieving bytes, lowest-bit first - 'sectors' at 512 bytes -> this is just a handy convention used for the programs to interoperate, (though Princess Maker doesn't play well). In addition, the first 1024 bytes (2 'sectors') are used as a directory, and the directory makes reference to various 'sectors'.
|
|
|
Post by dshadoff on May 20, 2019 15:47:45 GMT
The directory format is definitely based on the concept of sectors, but Princess Maker doesn't play well (and had an "o-wabi" apology included as a paper note for this very reason). Fresh format (Emerald Dragon) shows this at the beginning of the directory area: 32 00 02 00 D2 D3 D8 CD DE B0 ED 31 32 38 00 00 Mooz has kindly already documented this for us here: pcedev.blockos.org/viewtopic.php?f=5&t=98&start=10#p777(However, I'd call bytes #3 & 4 (values 02 00) to be 'next available sector'.) When I format with Princess Maker, it shows this instead: 30 06 00 00 D2 D3 D8 CD DE B0 ED 31 32 38 00 00 Note that the next available sector is '00'. When you add entries, this different 0-relative / 2-relative numbering system continues, so this is a clear problem for Princess Maker. The other difference of opinion between Princess Maker and Emerald Dragon is the BRAM formatting: - When using "copy all" in Princess Maker, it does a raw copy of 8KB of BRAM (including the "HUBM" header). - When doing the same from Emerald Dragon, it copies only the portion in use (i.e. only 600 bytes if that's all that is needed), and trims off the "HUBM" header and probably BRAM storage size pointer. The 'owabi' apology related to Princess Maker formatting says something like this: "1. When you're about to use the MB128 for the first time, or after removing power from it for over 10 minutes, or if the screen shows "Format", please format it." "2. Once the MB128 is formatted by Private Eye Dol, but with nothing else saved in it, the following games will not be able to save: Nobunaga no Yabō - Bushō Fūun Roku Nobunaga no Yabō - Zenkoku Ban Aoki Ōkami to Shiroki Mejika Sangokushi III In addition, due to the same condition, the following games will state "not enough memory" **but as load and save will work** please start the game as-is: A.III The Atlas" (Note: In the phrase above where I put "**...**", I am not 100% certain whether it actually says that it will work... )
|
|
|
Post by elmer on May 20, 2019 17:58:46 GMT
But because of electrical distortion during transmission, they wanted to make sure that the DATA line had settled before this transition took place. Seeing the oscilloscope reading that I posted in the Personal Projects thread on this subject, this is a good measure, but 9 cycles is way more than adequate for this (perhaps 2 cycles would be sufficient to cover all cases, and in most cases it may not even be necessary). I wouldn't say that the MB128 is normally operated with 2us high and 4us low; the (memory chip) datasheet states that the full cycle must be at least 4.0us, and the enable must be at least 3.0us. Since the sense of this line is active-low, we have speculated that it is either (a) anti-sense from the PCE-driven CLK line, or synthetically-created by the custom chip. But in any case, the measurements (duration of high, and duration of complete cycle) should be considered minimums. Sure, I'll happily agree that I should have said "could be operated" instead of "normally operated". Pretty-much every game that I've looked at is slower than 6us for the total cycle, even though the internal memory chip is designed to operate on a 4us minimum cycle. What we absolutely don't know, are the internal delays in the custom ASICs, and the safety-margin that the hardware engineers allowed for the signal rise and fall due to capacitance along the signal path. What we *do* know (from their code), is that Koei, the designer and manufacturer of the least-sophisticated of the two MB128-compatible devices (just look at the pictures of the boards), was running their PCE code using a 6us cycle, 2us high and 4us low ... i.e. they allowed for 1us of "slop" on each transition. Looking at their code, they could have made it faster if they had wanted to, but they didn't for some reason. Now, Private EyeDol runs with a longer total cycle time, but with < 3us low (overclocking the MSM6389), and it works fine on my MB128. Presumably it also runs OK on the Save Kun, but I don't have one to test. The thing is ... I don't see any reason to vary from Koei's 6us/2u/4us cycle, it's already the overall-fastest of the MB128 code that I've looked at, and it's working fine on my MB128. Since I'm doing forensic programming work to make compatible software, and not the hardware-clone work that you're doing, I'm happy to stick with my "safe" timings. Note that the 3 last trailing bits on the end of the READ and WRITE functions appear to be flushing the shift registers. HOWEVER, the WRITE function actually 5 bits - the first 2 of these appear to be data sent back from the MB128 unit to the PCE, and as far as I can tell, always show as {'1', '0'}. Emerald Dragon appears to validate writes by checking the second of these as being '0'. Private EyeDol definitely doesn't check those reads bits, and there's absolutely nothing in the MSM6389 documentation to even suggest what they could be. My personal speculation is that the ED code is trying to detect if the MB128 is releasing the joypad port and going back to "sleep" at the end of the write ... which it does after all the bits in the write have been transferred, and as-far-as-I-can-tell, does *before* the last 5 bits of the read/write that we're speculating are there to flush its internal buffers. So, if my speculation is correct, the 1st read-bit in ED would be looking at the data line from the MB128 ... and the 2nd read-bit (if the port has been released) would come from the connected-joypad (in its reset state). If I'm right, then the two reads are fairly pointless since you're going to want to read the entire data back after the write anyway to verify that there wasn't a single-bit loss in the transfer. The data verify will allow you to detect a "stuck" MB128 and then recover.
|
|
|
Post by elmer on May 20, 2019 18:38:45 GMT
The other difference of opinion between Princess Maker and Emerald Dragon is the BRAM formatting: - When using "copy all" in Princess Maker, it does a raw copy of 8KB of BRAM (including the "HUBM" header). - When doing the same from Emerald Dragon, it copies only the portion in use (i.e. only 600 bytes if that's all that is needed), and trims off the "HUBM" header and probably BRAM storage size pointer. Both games use different names for their BRAM saves, so neither game sees the other game's BRAM saves, and won't try to read/write to them. It's little bit of an annoyance to users, but it isn't going to cause any problems. The thing that is going to cause problems (at some point), is ED's attempt to save memory on the MB128 in that way. Professional developers have it drummed into their heads early-on ... always create the save-file at its *maximum* size, right from the start, or else users will get pissed when they suddenly find out that they can't save their game because the file just got a bit larger and there's no room left on the Memory Card/MB128. ED's method would have failed the standards-check by all of the console manufacturers (from the 5th gen onwards). For example, if you save a freshly formatted BRAM image to the MB128, then ED's code will put it in a single sector. Add a bunch of saves to your BRAM, and use ED to save it to the MB128, and suddenly the same save-slot needs 2,3,or 4 sectors. This also gets into a discussion of the MB128's directory and file contents. In the regular 2KB of BRAM, when you delete a file, the System Card code shuffles all of the remaining files around in BRAM so that the free space is always contiguous at the end of BRAM. Because the MB128 has a "lot" of memory, and it is relatively slow to read/write, it doesn't seem to do that (in Private EyeDol's code). When you delete a file, the entries in the directory are shuffled around to be contiguous ... but the file data itself isn't moved at all. This leaves an empty fragment of unused sectors in the MB128's file-system. When you create a file (in Private EyeDol's code), it will scan the directory and put your new file into one of those fragements, if it can find one, rather than put it at the end of the file space.
|
|
|
Post by dshadoff on May 20, 2019 19:56:11 GMT
I agree that Emerald Dragon doesn't work well for fragmentation reasons. I'm sure they weren't thinking about that (unless there's some kind of built-in defrag function (not likely).
I didn't know that Private Eye Dol did a scan for free space... but I am wary of the fact that they are using a 2-relative numbering system and everybody else is using 0-relative. I worry that they'd wipe out somebody else's saves.
|
|