Great Swordsman (not to be confused with Hiro Protagonist) is a Taito arcade game where you engage in various styles of sword play ranging from fencing to samurai combat.
The game firmware is comprised of Z80 EPROMs, AA-013, AA-016, and AA-017. The EPROM is easy as Z80 architecture is well understood and EPROMs are trivial to extract. However, little was known about the last three. Collectively though they handle things like getting player inputs, reading DIP switches, and tracking coins.
Previous decapping showed that AA-013 is an Intel D8741A.
Unfortunately it was received with severe damage which discouraged us from looking at it.
We then decapped AA-016 (#8) and AA-017 (#9) which are both NEC D8041AH. Fortunately neither NEC D8041AH nor Intel 8741A have protection schemes, so in theory we can simply read the data out. Unfortunately we were unable to activate the test interface. After some analysis we suspected that the algorithm we tried to dump them with (as 8741 IIRC) might have over-voltaged EA and damaged them. More on that later.
The game firmware is comprised of Z80 EPROMs, AA-013, AA-016, and AA-017. The EPROM is easy as Z80 architecture is well understood and EPROMs are trivial to extract. However, little was known about the last three. Collectively though they handle things like getting player inputs, reading DIP switches, and tracking coins.
Previous decapping showed that AA-013 is an Intel D8741A.
Unfortunately it was received with severe damage which discouraged us from looking at it.
We then decapped AA-016 (#8) and AA-017 (#9) which are both NEC D8041AH. Fortunately neither NEC D8041AH nor Intel 8741A have protection schemes, so in theory we can simply read the data out. Unfortunately we were unable to activate the test interface. After some analysis we suspected that the algorithm we tried to dump them with (as 8741 IIRC) might have over-voltaged EA and damaged them. More on that later.
Unfortunately the EPROM based 8741A is difficult to read as is. But D8041AH are contact ROMs which traditionally we've been reasonably successful with (example). So we attempted to visually read them but got a lot of errors. It was hard to read the bits and attempting to disassemble them resulted in something only vaguely reassembling a valid program.
With these extra sets, the first priority was to analyze the test interface and assess if it was healthy. We used small test currents to characterize the ESD diodes on sample chips and compared them to 8741A and 8041AH chips from Great Swordsman. This showed the chips from Great Swordsman consistently have different responses on EA pins vs samples, indicating this pin was likely intentionally damaged to prevent read out.
This may have been a common practice at one time as commercial systems from companies like RunFei have a "special protect" option that does exactly this. We've also seen it on other chips like the NEC D8748D EA pin shown above
So a few options. One is that we may be able to repair or bypass the blown pad. Repair would be easier if we had FIB access but this isn't easily available. We could bypass it but there were misc complications at the time and this wasn't seriously considered. We do however plan on attempting this for AA-013.
That said we figured there was a chance that the test interface *might* still work even if it was damaged. To our surprise we managed to get a plausible dump out of one of the new AA-016s! The interface only worked once or twice and then rapidly deteriorated. Unfortunately due to the test interface instability and some disassembly errors we weren't confident we had a good dump. Finally it didn't remotely match our earlier attempts to decode the mask ROM into binaries. This gave us low confidence that the EPROM dump was correct.
So anyway we at least had an answer: the test interface is not reliable and probably wont't yield anything more. So we decided to revisit brute force ROM capture by photographing bits. How could we improve the accuracy? Let's say the existing capture has about 100 bad bits out of 8192 => about 1% error rate. This means that if you took two of these captures, the expected number of bad bits is about 8192 * 0.01 * 0.01 = 0.8. So while it might not be perfect (say a few bit errors might be expected), it would drastically improve the accuracy to something usable.
With this in mind, few weeks ago we decapped the second ROM set as C031 (AA-016) and C032 (AA-017). And for one reason or another the contrast was considerably better!
We then asked the community to help convert these images into bits. This was broadcast here on this blog, on twitter, and on mameworld. We suggested using rompar, a specialized tool for this task, although in general it wasn't easy enough for people to setup. There is an open ticket about easier Windows support which the rompar team has been working on addressing.
That said, we got a combination of submissions in rompar, typed as .txt files, or even as colorful spreadsheets (AA-017 above, other images are AA-016).
That said, we got a combination of submissions in rompar, typed as .txt files, or even as colorful spreadsheets (AA-017 above, other images are AA-016).
One lesson learned is that we should have aligned all of the image sets (or at least C031 and C032). This would have made some of the post processing easier as sometimes we were trying to resolve bits by comparing several different image sets.
Anyway, once we got around 3 submits for each set we did a cursory inspection on each set to gauge the submission quality. If the submission is reasonable (say 99%+ accurate), we then add it to the submission pool. Then all of the locations in the pool that didn't fully agree with the entire ROM pool are flagged for review and displayed in rompar. After reviewing these we got ROMs that we think are probably within a few bits of being correct.
D8041AH datasheet
00000000 04 08 00 83 00 00 00 83 15 23 f0 90 85 95 22 14 |………#….“.|
Here you can at 0x0000 (reset) there's JMP 0x008 which skips over the reset of the vector table. Similarly there's RET on the other vectors to basically ignore them.
With that in mind, here's the start of our old AA-016 microscope based submit:
00000000 40 d9 96 a9 fa 03 1f aa e8 a8 04 13 04 d8 04 e0 |@...............|
Hmm there are some 4's in there, but doesn't really look valid. For comparison though, here is the AA-016 EPROM submit:
00000000 04 08 00 83 00 00 00 83 15 23 f0 90 85 95 22 14 |.........#....".|
With that in mind, here's the start of our old AA-016 microscope based submit:
00000000 40 d9 96 a9 fa 03 1f aa e8 a8 04 13 04 d8 04 e0 |@...............|
00000000 04 08 00 83 00 00 00 83 15 23 f0 90 85 95 22 14 |.........#....".|
Aha! This looks much better. So we started thinking: maybe the ROM decoding script doesn't really work? It is producing mostly valid disassembly, but maybe we missed something? The scheme was relatively complicated and its entirely possible something was missed.
So after some munging, we came up with a new physical address space layout. Now AA-016 starts with:
So after some munging, we came up with a new physical address space layout. Now AA-016 starts with:
00000000 04 08 00 83 00 00 00 83 15 23 f0 90 85 95 22 14 |.........#....".|
Aha! Now this matches the EPROM dump. In fact we verified against the original EPROM dump and decided it is 100% accurate.
But there's still one more problem: if the EPROM dump is good, why didn't it disassemble properly? Why did we get told the submitted dump was unusable? First, the unusable dump was probably someone talking about the earlier AA-016 dump vs the newer EPROM dump. Second, although we tried several ways to disassemble the dumps (notably MAME, Ghidra, but also some others), they generally were biased towards MCS-48 (classic 8048) and not some of the finer points of UPI-41, the family D8041AH is from. One source described it as “The 8042 and 8041 is code compatible with the 8048, except that there are no external program memory instructions, and that data bus register instructions have been added.” For example, Ghidra 8048 gave:
CODE:0008 15 DIS I
CODE:0009 23 f0 MOV A,#0xf0
CODE:000b 90 MOVX @R0,A
CODE:000c 85 CLR F0
CODE:000d 95 CPL F0
CODE:000e 22 ?? 22h "
MAME mcs48 gave:
unidasm -arch mcs48 great_swordsman_aa-016_ d8041ah_decap-c031.bin
...
0:008: 15 dis i
0:009: 23 f0 mov a,#$F0
0:00b: 90 movx @r0,a
0:00c: 85 clr f0
0:00d: 95 sel an1
0:00e: 22 illegal
But really should have been upi41:
unidasm -arch upi41 great_swordsman_aa-016_d8041ah_decap-c031.bin
...
008: 15 dis i
009: 23 f0 mov a,#$F0
00b: 90 mov sts,a
00c: 85 clr f0
00d: 95 sel an1
00e: 22 in a,dbb
Which looks good!
So to summarize, the hurdles were:
Finally, there were a lot of people that helped with this project. Some of them include:
But there's still one more problem: if the EPROM dump is good, why didn't it disassemble properly? Why did we get told the submitted dump was unusable? First, the unusable dump was probably someone talking about the earlier AA-016 dump vs the newer EPROM dump. Second, although we tried several ways to disassemble the dumps (notably MAME, Ghidra, but also some others), they generally were biased towards MCS-48 (classic 8048) and not some of the finer points of UPI-41, the family D8041AH is from. One source described it as “The 8042 and 8041 is code compatible with the 8048, except that there are no external program memory instructions, and that data bus register instructions have been added.” For example, Ghidra 8048 gave:
CODE:0008 15 DIS I
CODE:0009 23 f0 MOV A,#0xf0
CODE:000b 90 MOVX @R0,A
CODE:000c 85 CLR F0
CODE:000d 95 CPL F0
CODE:000e 22 ?? 22h "
MAME mcs48 gave:
unidasm -arch mcs48 great_swordsman_aa-016_
...
0:008: 15 dis i
0:009: 23 f0 mov a,#$F0
0:00b: 90 movx @r0,a
0:00c: 85 clr f0
0:00d: 95 sel an1
0:00e: 22 illegal
But really should have been upi41:
unidasm -arch upi41 great_swordsman_aa-016_d8041ah_decap-c031.bin
...
008: 15 dis i
009: 23 f0 mov a,#$F0
00b: 90 mov sts,a
00c: 85 clr f0
00d: 95 sel an1
00e: 22 in a,dbb
So to summarize, the hurdles were:
- Intentionally damaged test interface
- Possibly unintentionally damaged test interface
- Noisy microscope images
- Not using the right disassembler
- Getting people to look at the data
- Incorrect address decoding
Finally, there were a lot of people that helped with this project. Some of them include:
- Our Patreon contributors
- STARRIDER: chips, ROM capture
- rompar team (John McMaster et al): software support
- EdHunter: ROM layout decoding
- Guru: logistics
- Smitdogg: logistics
- f205v: ROM capture
- sadikyo: ROM capture
- belegdol: ROM capture
Enjoy this post? Please support us on Patreon or follow us on Twitter! Note: with the Indiegogo campaign over we unfortunately don't currently have a way to accept one time donations.
The proper disassembly for this snippet is:
ReplyDeletedis i
mov a,#$F0
mov sts,a ;status register - only in UPI41 family
clr f0
cpl f0 ;f0=1
in a,dbb ;data bus
I recommend to use the Avocet Simulator (from 80s) which support the 8741 device.
However MCS-48 code can be effectively obfuscated...