07 August 2021, 14:11 | #81 | ||||
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
That's the approach I've always thought was best--because there's likely things a coder has never seen in the arcade version. Hidden rooms? Hidden levels? That kind of thing.
Quote:
Quote:
EX: (pseudo code) 01 02 04 06 ENEMY_TYPE_1 = 01 ; maybe the ape-like brute character ENEMY_DECISION_TYPE = 02 ; 02 means either follow or flee ENEMY_DECISION = 04; follow COUNTER = 06; for the next 6 moves I'll have to decipher how that part works to decode the AI stuff. I do see a lot of structures in the code that look similar. Quote:
Quote:
.... Here's a morsel from the audiocpu. I've found the individual sounds... some of which I've never heard before. There are a few fanfare sounds that never seem to play (and they don't seem to be called in code either). What finding the sounds did was allow me to not just find the functions in the maincpu... I traced those back into the audiocpu and single stepped through the code after triggering each sound from the maincpu. I don't know whether the format is direct wav samples or instructions or combinations of lookups into wav tables yet... but I know where the sounds are Code:
SOUNDS_TABLE XREF[1]: Maybe_PlaySoundEffect:020e(*) ram:0dc1 00 ff dw FF00h Sound 0: FF stops music playing ram:0dc3 49 0e dw PLAYER_LOSES_VITALITY_SOUND = 8Fh ram:0dc5 9e 0e dw PLAYER_DEATH_SOUND = 8Fh ram:0dc7 7f 0f dw ENEMY_INJURED_BLOOP_SOUND = CFh ram:0dc9 d4 0f dw ENEMY_DEFEATED_SOUND = CFh ram:0dcb fe 0f dw ITEM_TAKEN_SOUND = 88h ram:0dcd 7b 10 dw PLAYER_TAKES_ZENNY_COIN_SOUND = 88h ram:0dcf f5 10 dw FIRE_PILLAR_WARNING_SOUND = 88h ram:0dd1 5e 11 dw POT_BREAKS_REVEALS_COIN_SOUND = C8h ram:0dd3 c7 11 dw FIRE_PILLAR_SOUND = C8h ram:0dd5 08 12 dw SMALL_EXPLOSION_SOUND = C8h ram:0dd7 32 12 dw WEAPON_CLASH_METALLIC_BATTLE_SOUND = 88h ram:0dd9 84 12 dw KILL_BAT_SOUND = C8h ram:0ddb ae 12 dw PLAYER_EARNS_EXTRA_LIFE_SOUND = 8Fh ram:0ddd 64 13 dw POT_BREAKS_SOUND = 88h ram:0ddf bc 13 dw PLAYER_DISCOVERS_TREASURE_SOUND = C8h ram:0de1 86 14 dw BIG_BOSS_HIT_SOUND 10 ram:0de3 b0 14 dw TIME_EXPIRING_SOUND = 81h ram:0de5 ee 14 dw PLAYER_GETS_ITEM_FROM_OLD_MAN_SOUND = 88h ram:0de7 cc 15 dw BOOM_EXPLOSION_SOUND = C8h ram:0de9 0d 16 dw UNKNOWN_ALARM_SOUND = 81h ram:0deb 4e 16 dw IMPACT_SOUND = C8h ram:0ded 78 16 dw CLASH_SPINNING_COIN_SOUND = C8h ram:0def a2 16 dw PLAYER_LOSES_ARMOR_SOUND = 8Fh ram:0df1 08 17 dw MICHELIN_MAN_FIREBREATHING_SOUND = C8h ram:0df3 35 17 dw FIRETHROWER_TAUNT_SOUND = C8h ram:0df5 b2 17 dw PLAYER_CLIMB_SOUND = 88h ram:0df7 c8 17 dw FLAIL_EMPTY_HIT_SOUND = 88h ram:0df9 de 17 dw PLAYER_LANDS_ON_PLATFORM_SOUND = 88h ram:0dfb 1c 18 dw PLAYER_ASCENDS_DURING_CUTSCENE_SOUND = 88h ram:0dfd 32 18 dw PLAYER_GRABS_LADDER_SOUND = 88h ram:0dff 01 ff dw FF01h 1f: stops playing music ram:0e01 10 1b dw COIN_OR_CREDIT_ADDED_SOUND = 4Fh O ram:0e03 8c 1b dw LEVEL_1_MUSIC Level 1 music ram:0e05 de 1f dw LEVEL_2_MUSIC = 06h ram:0e07 ef 23 dw LEVEL_3_MUSIC = 06h ram:0e09 b7 27 dw LEVEL_4_MUSIC = 06h ram:0e0b 27 2d dw LEVEL_5_MUSIC = 06h ram:0e0d 07 32 dw LEVEL_6_MUSIC = 06h ram:0e0f c4 35 dw LEVEL_7_MUSIC = 06h ram:0e11 7c 3a dw LEVEL_8_MUSIC Level 8 music ram:0e13 cb 3f dw BOSS_MUSIC_01 = 06h ram:0e15 f5 41 dw FIGHT_DRAGON_MUSIC_01 = 06h ram:0e17 8b 44 dw FIGHT_DRAGON_MUSIC_02 = 06h ram:0e19 70 47 dw OLD_MAN_SHOP_MUSIC = 06h ram:0e1b 7e 49 dw DUNGEON_MUSIC_01 = 06h ram:0e1d 96 4b dw ENTER_INITIALS_MUSIC = 06h ram:0e1f 9d 51 dw AFTER_ENTER_INITIALS_MUSIC = 06h ram:0e21 82 52 dw INTRO_MUSIC 30 ram:0e23 48 54 dw GAME_OVER_MUSIC = 06h ram:0e25 13 55 dw SUCCESSFULLY_FINISH_LEVEL_MUSIC = 06h ram:0e27 fa 55 dw FINISH_LEVEL_8_MUSIC = 06h ram:0e29 a4 5e dw CONTINUE_MUSIC = 06h ram:0e2b 51 60 dw MAYBE_PERFECT_BONUS_MUSIC = 06h ram:0e2d d2 60 dw UNKNOWN_FANFARE_MUSIC = 06h ram:0e2f 6d 61 dw UNKNOWN_FANFARE_MUSIC_02 = 06h ram:0e31 04 ff dw FF04h 38 stops music playing ram:0e33 36 62 dw UNKNOWN_FANFARE_MUSIC_03 = 06h ram:0e35 5c 18 dw FLAIL_HIT_SOUND = 88h ram:0e37 86 18 dw FALLING_SOUND = C1h ram:0e39 9c 18 dw BOUNCING_SOUND_(LOOPS) = C1h ram:0e3b c9 18 dw OLD_MAN_TALKING_SOUND = C8h ram:0e3d 57 19 dw OLD_MAN_TALKING_SOUND_02 = C8h ram:0e3f a9 19 dw DRAGON_DIE_SOUND = 90h ram:0e41 90 1a dw MAYBE_BLOCK_BOUNCE_UP_SOUND 40 ram:0e43 ba 1a dw FALLING_SOUND_02 = C8h ram:0e45 d0 1a dw BOSS_HIT_SOUND = C8h ram:0e47 e6 1a dw DRAGON_SPEW_FIRE_SOUND 43 might be the last sound |
||||
07 August 2021, 17:29 | #82 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,164
|
you've not chosen the simplest game to remake. Good luck. And nice work so far.
|
07 August 2021, 17:56 | #83 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
Little update ... seems the sprite drawing routine (in z80 opcodes) isn't even being emulated by MAME. I've been looking all over for it. Seems MAME does its own sprite drawing routine for some machines, I guess, because it is emulating some sort of hardware that will immediately blit directly to the screen. So I've been running through the MAME debugger looking for something that was never there. The gfx1-gfx3 roms (holding all of the graphics) are never directly referenced (it seems) by the maincpu code, which makes sense. They probably have the motherboard wired to check a vector on some address (In Black Tiger it might be E140 and E142) which then would cause a routine to read from the gfx chips directly to the screen. The reason I was able to pick up changes to the screen in the debugger was that drawing text and drawing backgrounds DOES seem to be emulated fully by MAME... meaning that the original opcodes on the Z80 maincpu are run and emulated, which seems to have the effect of loading tile maps and text. The same isn't true for the sprites, which seem to not be emulated (for the reason explained above). The only real problem this presents is that I can't tell exactly what Z80 code puts the player on screen, for example. On a real Black Tiger machine, the maincpu probably puts a vector in the TILE/SPRITE queue (at E100) and then the hardware (with the motherboard configured as I explained) takes over. I may not be able to find functions in the Z80 code using the sprites. The sounds, however, have given me quite a lot of the labels for the functions. I can probably fully reverse the source. |
|
07 August 2021, 18:51 | #84 |
Registered User
Join Date: May 2018
Location: Ireland
Posts: 672
|
I would be very surprised if the emulation is not referencing the sprites somewhere(as it loads the roms) as the z80 needs both initialize the HW with sprite locations and to tell the HW to move them, maybe taking 2 snapshots 1 second apart and doing a diff on the hex might reveal something?
As you say, the gfx chip(s) might just be reading from a memory location and updating accordingly but still needing updates to those values by Z80. |
07 August 2021, 19:31 | #85 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
I just checked through the entire MAME source and found: https://github.com/mamedev/mame/blob...o/blktiger.cpp (previously I was just looking at ~/driver/blktiger.cpp) This shows how the sprite structures are read. Seems they live at $FE00 ~ $FFFF in RAM. When MAME emulates the vertical blank (high), it redraws the screen and this is how the screen is structured (in 4 layers) Code:
bitmap.fill(1023, cliprect); if (m_bgon) (m_screen_layout ? m_bg_tilemap8x4 : m_bg_tilemap4x8)->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER1, 0); if (m_objon) draw_sprites(bitmap, cliprect); if (m_bgon) (m_screen_layout ? m_bg_tilemap8x4 : m_bg_tilemap4x8)->draw(screen, bitmap, cliprect, TILEMAP_DRAW_LAYER0, 0); if (m_chon) m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0); The background and text are directly updated by the emulated Z80 code. Sprites are being done in MAME, indirectly replacing whatever hardware (soldering/etc) on the Black Tiger motherboard. It does help a bit in describing the 4-byte structures that describe each sprite. However I'm not sure how the gfx emulator loads the Black Tiger sprite roms. Since I'm not re-implementing sprites the way Black Tiger (arcade) does, it doesn't matter. What does matter (for reversing the game logic) is knowing what sprite data structures will draw what on the screen. Then I can label the structures as "player sprite data" and so forth. It looks like this: Code:
SPRITE STRUCTURE (in Z80 src code): Byte 0 | Byte 1 | Byte 2 | Byte 3 ----------------------------------------- (tile/sp) attrib y pos x pos index attrib = palette = bits 0-2; flip tile (sprite piece) horiz = bit 3 attrib bit 4 => if set, subtract 256 from x pos attrib bits 5-7 => index |=( (attrib & E0) << 3) |
|
07 August 2021, 20:01 | #86 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Ok, now we're getting somewhere.
Now that I understand how sprites work, I was able to use the sprite ram area to put four sprite structures together like this: Code:
INDEX/ATTR/Y/X 03 08 10 00 ; upper body. attr =8 => flipped tile 02 08 10 10 ; upper body. attr =8 => flipped tile, 16 (10h) pixels to the right 0b 08 20 00 ; lower body. attr =8 => flipped tile; 16 (10h) pixels down from upper body 0a 08 20 10 ; lower body. attr =8 => flipped tile; 16 (10h) pixels down from upper body, 16 (10h) pixels to the right Again, I won't use this scheme on the Amiga hardware; I'm just going to use this understanding to reverse engineer the existing code (find data structures, which will help naming all of the functions). |
07 August 2021, 20:17 | #87 |
Registered User
Join Date: May 2018
Location: Ireland
Posts: 672
|
Excellent, great work
Quite enjoying reading the progress analysing from arcade roms with MAME |
08 August 2021, 03:25 | #88 | |
CaptainM68K-SPS France
|
Quote:
|
|
08 August 2021, 13:20 | #89 | ||
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
Quote:
... This is what I'm able to do right now... finding all of the player animations. Labeling those should help labeling the functions where they are referenced. Still a bit of work to do. Code:
PLAYER_ANIMATION_OFFSET_TABLE_02+1 XREF[2,1]: FUN_Bank08__8126:81fa(*), PLAYER_ANIMATION_OFFSET_TABLE_02 FUN_Bank08__8126:820c(R), FUN_Bank08__8126:820e(R) Bank08::9698 ac 96 dw PLAYER_LEVEL_1_NO_ARMOR_WALKING_AND_KNEELING_T = 9730h Bank08::969a b8 96 dw PLAYER_LEVEL_1_NO_ARMOR_FIGHTING_TABLE_01 = 97F0h Bank08::969c c4 96 dw WORD_Bank08__96c4 = 98B0h Bank08::969e d0 96 dw WORD_Bank08__96d0 = 9970h Bank08::96a0 e8 96 dw WORD_Bank08__96e8 = 99D0h Bank08::96a2 dc 96 dw WORD_Bank08__96dc = 9A30h Bank08::96a4 f4 96 dw WORD_Bank08__96f4 = 9A90h Bank08::96a6 00 97 dw WORD_Bank08__9700 = 9B20h Bank08::96a8 0c 97 dw WORD_Bank08__970c = 9B80h Bank08::96aa 18 97 dw WORD_Bank08__9718 = 9BE0h PLAYER_LEVEL_1_NO_ARMOR_WALKING_AND_KNEELING_T XREF[1]: Bank08::9698(*) Bank08::96ac 30 97 dw PLAYER_LEVEL_1_NO_ARMOR_WALKING_RIGHT = C6h Bank08::96ae 60 97 dw PLAYER_LEVEL_1_NO_ARMOR_CROUCHING_RIGHT = B2h Bank08::96b0 90 97 dw PLAYER_LEVEL_1_NO_ARMOR_CROUCHING_LEFT = B2h Bank08::96b2 90 97 dw PLAYER_LEVEL_1_NO_ARMOR_CROUCHING_LEFT = B2h Bank08::96b4 c0 97 dw PLAYER_LEVEL_1_NO_ARMOR_WALKING_LEFT = C6h Bank08::96b6 90 97 dw PLAYER_LEVEL_1_NO_ARMOR_CROUCHING_LEFT = B2h PLAYER_LEVEL_1_NO_ARMOR_FIGHTING_TABLE_01 XREF[1]: Bank08::969a(*) Bank08::96b8 f0 97 dw PLAYER_LEVEL_1_NO_ARMOR_FIGHTING_RIGHT_POS_1 = D2h Bank08::96ba 20 98 dw PLAYER_LEVEL_1_NO_ARMOR_FIGHTING_CROUCH_RIGHT_01 = B4h Bank08::96bc 50 98 dw PLAYER_LEVEL_1_NO_ARMOR_FIGHTING_CROUCH_LEFT_01 = B4h Bank08::96be 50 98 dw PLAYER_LEVEL_1_NO_ARMOR_FIGHTING_CROUCH_LEFT_01 = B4h Bank08::96c0 80 98 dw PLAYER_LEVEL_1_NO_ARMOR_FIGHTING_LEFT_POS_1 = D2h Bank08::96c2 50 98 dw PLAYER_LEVEL_1_NO_ARMOR_FIGHTING_CROUCH_LEFT_01 = B4h |
||
08 August 2021, 13:44 | #90 | |
CaptainM68K-SPS France
|
Quote:
|
|
08 August 2021, 14:50 | #91 |
Registered User
Join Date: May 2018
Location: Ireland
Posts: 672
|
Yes, that would be cool, based on the Arcade hardware it could help with proper Amiga versions of 1943, Side Arms, Commando etc.
|
08 August 2021, 14:51 | #92 |
CaptainM68K-SPS France
|
|
08 August 2021, 16:31 | #93 |
Registered User
Join Date: May 2018
Location: Ireland
Posts: 672
|
Not sure if useful or not and maybe you already checked it, but the cheat XML for blacktiger shows the memory addresses for level select, infinite time etc.
Setting watchpoints on the addresses should provide some useful info. Format of xml is described @ http://www.mamecheat.co.uk/forums/viewtopic.php?t=3768 i.e. Code:
maincpu = The address space that the address exists in. "maincpu" is the most commonly wanted, but as seen above, not always. p = Type of memory. p=RAM, m=ROM, o=ROM ??? ROM cheats aren't my thing, but p is usually what you want. b = Width of value being plugged. b=byte (0x00), w=word (0x0000), d=double (0x00000000), q=quad (0x0000000000000000) FF022F = Address. Have fun with Midway machines. They use a very unusual system which I don't like much. 99 = The value being plugged in. (Hexidecimal) Code:
<mamecheat version="1"> <cheat desc="Infinite Lives"> <script state="run"> <action>maincpu.pb@F3A0=09</action> </script> </cheat> <cheat desc="Infinite Time"> <script state="run"> <action>maincpu.pb@F3B1=3B</action> </script> </cheat> <cheat desc="Infinite Shield"> <script state="run"> <action>maincpu.pb@F3AD=06</action> </script> </cheat> <cheat desc="Infinite Money"> <script state="run"> <action>maincpu.pb@F3A8=FF</action> </script> </cheat> <cheat desc="Infinite Potions"> <script state="run"> <action>maincpu.pb@F3B0=09</action> </script> </cheat> <cheat desc="Infinite Keys"> <script state="run"> <action>maincpu.pb@F3AB=09</action> </script> </cheat> <cheat desc="Invincibility"> <comment>Falling down holes kills!</comment> <script state="run"> <action>maincpu.pb@E905=01</action> <action>maincpu.pb@F424=0F</action> </script> </cheat> <cheat desc="Always have the Best weapon"> <script state="run"> <action>maincpu.pb@F3AC=04</action> </script> </cheat> <cheat desc="Select starting level"> <parameter min="1" max="8" step="1"/> <script state="run"> <action condition="(maincpu.pb@F3A1==00)">maincpu.pb@F3A1=(param-1)</action> </script> </cheat> </mamecheat> <!-- Cheat file downloaded from http://www.mamecheat.co.uk, see cheat.txt for list of contributors. --> |
08 August 2021, 16:59 | #94 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
Cheers! ETA: Actually I have some of those variables mapped already... and they check out. I wasn't aware of a couple of them, but I'll add their labels to the Ghidra project. |
|
08 August 2021, 17:59 | #95 |
Registered User
Join Date: May 2018
Location: Ireland
Posts: 672
|
|
09 August 2021, 19:12 | #96 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
For those wanting an extended explanation of my process (so more Z80 based arcade games can be ported) at some point I'll try to do a mcgeezer or Photon of Scoopex type YouTube series to explain how to reverse those ROMs using Ghidra and other tools. (This will probably be down the road a bit)
... A lot of good progress; but I've got a lot to do. I'm not stuck at all in terms of finding structures and labeling things. Here's a sampling of what I've done lately. This is for the demon character (the Level 4 boss, not the guy who throws fire) It's all about labeling things, then going back and finding reference to those labels and thinking about what the function might do. When you see the "Maybe_" prefix on a function name, it's a guess. Once I step through the code or it becomes obvious, I remove the prefix For this llsting, you see clusters of 5 bytes. These describe an animation frame. I believe the first value is a duration value (ex: 4). The rest of the values are definitely the (first) sprite tile index (in the sprite), the attribute (including palette and 3 msbs of the tile index), the x offset and the y offset. So 04, 6a, aa, 00, fd means: Code:
Keep this frame on screen for 4 vertical blanks Tile 6a + (a0 from attr) Palette 2 (from aa) Reversed (aa & 0x8) -- so the demon is facing right, not left delta x=0 (keep x value) delta y=fd (-3... move up 3 pixels for this frame) Roughly (sprite IDs): a6 -> b0 -> b2 -> b0 -> a6 -> b0 -> b2 -> b0 (etc) The sequence seems to describe the character flapping his wings and rising (not moving along X at all) Code:
FLYING_DEMON_RIGHT_ANIMATION_03 XREF[1]: Maybe_HandleDemon:a069(*) Bank02::a48a 04 a6 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a48f 04 b0 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a494 04 b2 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a499 04 b0 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a49e 04 a6 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a4a3 04 b0 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a4a8 04 b2 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a4ad 04 b0 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a4b2 04 a6 aa dnw_char if 0, ks death animation. If FF, 00 fd Bank02::a4b7 00 ?? 00h Bank02::a4b8 4b a0 dw Maybe_HandleDemon FLYING_DEMON_ANIMATION_TABLE_01+1 XREF[2,1]: FUN_Bank02__a0a9:a0d5(*), FLYING_DEMON_ANIMATION_TABLE_01 FUN_Bank02__a0a9:a0d9(R), FUN_Bank02__a0a9:a0db(R) Bank02::a4ba da a4 dw dnw_character_anim_frame_Bank02__a4da = Last edited by chadderack; 09 August 2021 at 19:52. |
09 August 2021, 21:58 | #97 |
CaptainM68K-SPS France
|
I'm sure now that capcom used a tool able to animate the sprite visually on screen, and then save the whole pattern as an array for use in game. Like a computerized puppet theater.
|
09 August 2021, 22:27 | #98 |
J.M.D - Bedroom Musician
Join Date: Apr 2014
Location: los angeles,ca
Posts: 3,519
|
We had a similar system for Powder where could group sprites, assign basic movement or even memorized patterns, so i confirm that might be possible
|
09 August 2021, 23:20 | #99 | |
Registered User
Join Date: May 2018
Location: Ireland
Posts: 672
|
Quote:
If it would help things i could easily write tools to use these patterns(if we know what they are) to generate some sort of Amiga compatable abstraction, essentially a transformation layer if possible. Last edited by lmimmfn; 09 August 2021 at 23:32. |
|
10 August 2021, 00:22 | #100 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
The thing about this is discovering any pattern.
Some of the data structures have function pointers embedded in them. I just found the orange dragon (level 6?) and there's a ton of frames and information. Each dragon seems to have two entire tile blocks to itself. 2 of the 8 that are used for sprites are just the three dragons (Level 3, Level 6, Level 8) (with the different palettes). One quarter of the sprite tiles are dragon! It's quite possible that the structure layout for each game is different (and even each sprite). Have patience; we're going to get to the higher-level language brick by brick |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Black Tiger | anata | project.Maptapper | 1 | 19 September 2013 07:24 |
Mace vs. Black Tiger | Kodoichi | Nostalgia & memories | 35 | 13 April 2011 13:32 |
Black Tiger | Uncle Micko | support.Games | 6 | 07 October 2007 03:13 |
Black Tiger NES | NfernalNfluence | Retrogaming General Discussion | 3 | 08 May 2007 15:48 |
[Fixed] Black Tiger dev. | haynor666 | HOL data problems | 2 | 08 July 2003 08:41 |
|
|