![]() |
![]() |
#101 | |
Registered User
Join Date: May 2018
Location: Ireland
Posts: 691
|
Quote:
|
|
![]() |
![]() |
#102 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
![]() Well, I can kinda try to give an idea of what I'm doing here (briefly). I have MAME running Black Tiger, which I have put into the test screens. 1) Run MAME debug (mame.exe -debug blktiger) 2) in the debug window console, type bp 1b4 3) Hit f5 4) When the breakpoint at $1b4 is hit, type pc=1ac in the debug window console and hit enter 5) Hit Alt+Enter to make the game screen into a window and resize it somewhat small 6) Hit F5. You're in the test screen In order to get to the screens I'm using to identify sprites, you have to simulate the service buttons. The mame service button does not work in debug; but you can use a key sequence to get through the screens. 7) press both the "1" and "2" keys on your keyboard at the same time (not on the numeric keypad... the normal "1" and "2" keys. This combo cycles you through the various test screens. Press it twice and you'll get to a screen like this. The object test, which is the sprite test. This view of the sprite test can be useful, as it puts a tile index next to each piece of a sprite. I find the combined view to be more useful. 8) Click the left CTRL button and the sprites will come together. There's still a sprite index along the top and sides... (continued) |
|
![]() |
![]() |
#103 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
The left and right keys on your keyboard control the palette and whether or not the sprite tiles are flipped. Hit the left key and your palette cycles up to 7 If you go past a palette value of 7, you get to 8 (which is the same palette as 0 only the tile is flipped horizontally) So if we want the same color as palette 3 but flipped, cycle to object test 0B Anyway... if we want to find sprites in the code, we use the two index values. The first one comes from the table... (below) the second comes from the object test number (which is the sprite attr) EX: 03 0b would be the upper left tile of this character: Black Tiger's code refers to sprites like this... by the upper left index of the sprite... and then the code extrapolates the rest (add 1 to the tile number for the second tile, add 7 to get one row down, add 1 for the bottom right tile for a sprite that is 2x2 tiles... like the player sprite). If you want to look for sprites other than the main character, hit the left ALT button. This takes you to the next page of sprites. Seems that in Black Tiger, only every other "page" has sprite tiles. Since I want to look for the Orc character, I'll hit the button 4 times to get an object test of 40: Now I want the ORC, so I use the up and down arrow keys to look through the sprite page... That palette looks wrong, so use the left arrow key to get to the brown orc Anyway... knowing this, you can look through the source code for these codes. Just find a character in the sprite object test, find the tile number and sprite attr number and do a search. I want to see if the brown orc (facing left) is in the code, so I search for "80 45" in the source code. Lo and behold, I find it. Now I can start figuring out what the sequence in the code does... (cont'd at some point) Last edited by chadderack; 10 August 2021 at 17:02. |
![]() |
![]() |
#104 |
J.M.D - Bedroom Musician
Join Date: Apr 2014
Location: los angeles,ca
Posts: 3,596
|
I Have the idea that tiles are flipped via software to save RAM so you might not find right oriented characters
|
![]() |
![]() |
#105 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
Here's an example... one of the brown orcs walks back and forth. Notice that the sprite attribute goes from 45 to 4D (45 | 0x8)... meaning that the character turned around. So far in code I've found references to the player, the goblins (purple/orange), the Orcs (brown so far only), the skeletons (including skull throwing), the orange dragon, the pots with prizes in them, holes in the wall with prizes and a few others. There's something to find each time. |
|
![]() |
![]() |
#106 |
J.M.D - Bedroom Musician
Join Date: Apr 2014
Location: los angeles,ca
Posts: 3,596
|
Just checking the pulse of the project ^^ By the way i did not found Black Tiger to be supported by Hoot but maybe someone can prove me wrong - and the VGM player option (with all those command line) is so darn alien to me - i need to dust off my lua
|
![]() |
![]() |
#107 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
![]() Quote:
Found a lot of the data around the old man who sells you things. I'd forgotten that they had misspelled "Skull" as "Scull" ![]() I've found all the functions that set up all the enemies as well as the different versions of the old man Code:
OLD_MAN_ACTIONS_JMP_TBL XREF[1]: ram:5fc7(*) ram:5fcd dd 5f dw OldManAwardsPlayer100PointsAndZenny ram:5fcf 08 60 dw OldManOpensShopToPlayer ram:5fd1 25 60 dw OldManAwardsPlayerMoreVitality ram:5fd3 4b 60 dw OldManAwardsPlayerMoreTime ram:5fd5 78 60 dw OldManGivesAdviceSpinningScull ram:5fd7 97 60 dw OldManGivesPlayerGratitude ram:5fd9 a8 60 dw OldManGivesAdviceSeekHiddenSymbols ram:5fdb 08 60 dw OldManOpensShopToPlayer ;ETC... PURCHASE_SELECTION_JUMP_TABLE XREF[1]: CheckPlayerMakesPurchaseSelectio ram:6660 fe 67 dw CheckPlayerMakesPurchaseSelection::Maybe_BuyBu row 1 col 5 ram:6662 78 66 dw Maybe_PurchaseItemTopRow01 ram:6664 7c 66 dw Maybe_PurchaseItemTopRow02 ram:6666 80 66 dw Maybe_PurchaseItemTopRow03 ram:6668 84 66 dw Maybe_PurchaseItemTopRow04 ram:666a e0 66 dw Maybe_PurchaseItemBottomRow01 ram:666c e4 66 dw Maybe_PurchaseItemBottomRow02 ram:666e e8 66 dw Maybe_PurchaseItemBottomRow03 ram:6670 ec 66 dw Maybe_PurchaseItemBottomRow04 ram:6672 4c 67 dw PurchaseKeyFor30Zenny ram:6674 87 67 dw PurchasePotionFor150Zenny ram:6676 0a 68 dw CheckPlayerMakesPurchaseSelection::maybe_remov Last edited by chadderack; 18 August 2021 at 21:05. |
|
![]() |
![]() |
#108 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
And now after a little more work... you see how the pseudo "code" is transformed:
Code:
PURCHASE_SELECTION_JUMP_TABLE XREF[1]: CheckPlayerMakesPurchaseSelectio ram:6660 fe 67 dw CheckPlayerMakesPurchaseSelection::update_time row 1 col 5 ram:6662 78 66 dw PurchaseWeaponLevel01 ram:6664 7c 66 dw PurchaseWeaponLevel02 ram:6666 80 66 dw PurchaseWeaponLevel03 ram:6668 84 66 dw PurchaseWeaponLevel04 ram:666a e0 66 dw PurchaseArmorLevel01 ram:666c e4 66 dw PurchaseArmorLevel02 ram:666e e8 66 dw PurchaseArmorLevel03 ram:6670 ec 66 dw PurchaseArmorLevel04 ram:6672 4c 67 dw PurchaseKeyFor30Zenny ram:6674 87 67 dw PurchasePotionFor150Zenny ram:6676 0a 68 dw CheckPlayerMakesPurchaseSelection::time_to_sho |
![]() |
![]() |
#109 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Anyone wanting to follow along or try their hand at Ghidra... I just put the project on GitHub. I won't be accepting pull requests for now, but you can check it out if you like.
https://github.com/admiral68/gh_black_tiger |
![]() |
![]() |
#110 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
A lot of good progress.
Finding vertical blank code as well as the way that Black Tiger does delays. That stuff was sort of tricky to work out; but it will help figure out a whole lot more of the game. It seems like I'm always finding things I'm not looking for. I started looking for how the game managed when a player is poisoned, and ended up finding a ton of other unrelated stuff first. To recap--I am attempting to reverse engineer Black Tiger to discover what amounts to a high-level flow chart of the game rules. If I had to guess, I'd say there's still probably a couple more weeks of this before we get to anything resembling a "flow chart" for all of Black Tiger's game rules... probably longer than that. Any work directly on the Amiga will not probably happen for about a month (at best). |
![]() |
![]() |
#111 | |
CaptainM68K-SPS France
|
Quote:
![]() |
|
![]() |
![]() |
#112 |
J.M.D - Bedroom Musician
Join Date: Apr 2014
Location: los angeles,ca
Posts: 3,596
|
I anticipate will go for three channels tunes because i tried in the past to do some Black tiger music in two and tose for purists might not sound too good, unless otherwise requested
Usually for ease of access purpose i try to put together interactions in the same mod file so for each level we might have: main tune dungeon tune boss tune store tune game over Then despite will probably need to recreate instruments using Deflemask as much as i can do and use around maybe 200k for all the chords, will have purists telling me is NOT identical to the arcade, darn -_- is ok if i replace with dark metal sepultura style for an alternative soundtrack??? :P Last edited by saimon69; 23 August 2021 at 18:39. |
![]() |
![]() |
#113 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
![]() Why not have a Black Tiger Amiga port fork version that does nothing but dark metal sepultura style ![]() If you want to dig into the Yamaha synthesis code, the relevant MAME code (in C/C++) is in these files: https://github.com/mamedev/mame/blob.../sound/ymopn.h https://github.com/mamedev/mame/blob...mfm/src/ymfm.h https://github.com/mamedev/mame/blob.../src/ymfm_fm.h https://github.com/mamedev/mame/blob...src/ymfm_opn.h https://github.com/mamedev/mame/blob...c/ymfm_adpcm.h https://github.com/mamedev/mame/blob...nd/ymfm_mame.h https://github.com/mamedev/mame/blob...src/ymfm_ssg.h https://github.com/mamedev/mame/blob...c/ymfm_ssg.cpp At some point I was going to build a version of MAME just to debug the sound synthesis engine. In Black Tiger there are 64 unique sounds/music, not including the blank/stop sounds Here are some notes if you want to start on the Sound ROM: Code:
//snippets of code mixed with other stuff //LOCATIONS OF VARIOUS SOUNDS ON THE SOUND ROM: 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 GAS_JET_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 //********************************************************* // YM2203 DEVICE //********************************************************* DEFINE_DEVICE_TYPE(YM2203, ym2203_device, "ym2203", "YM2203 OPN") //------------------------------------------------- // ym2203_device - constructor //------------------------------------------------- ym2203_device::ym2203_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ymfm_ssg_device_base<ymfm::ym2203>(mconfig, tag, owner, clock, YM2203) { } //------------------------------------------------- // device_start - start of emulation //------------------------------------------------- void ym2203_device::device_start() { // set our target output fidelity m_chip.set_fidelity(SSG_FIDELITY); // call our parent parent::device_start(); } |
|
![]() |
![]() |
#114 |
J.M.D - Bedroom Musician
Join Date: Apr 2014
Location: los angeles,ca
Posts: 3,596
|
My C skills are darn low -_-
If the ROM was supported by hoot i would simply have channels muted one at the time and record to wav file so to import the sample in milkytracker and adapt it However i was just ranting because have several remakes of soundtrack going on and not sure any of those projects will be terminated by the dev (like Robocop in example) - and those take a discrete time to make [ Show youtube player ] for what concerns alternate soundtrack, i can do good stuff if left full freedom! [ Show youtube player ] Have someone tell me they dislike funk on a game music but this for me is bringing the 70s Martial arts movie feeling! Last edited by saimon69; 23 August 2021 at 20:51. |
![]() |
![]() |
#115 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
I think for any development project, creating tools might be important. For something high level like "Black Tiger Music Sounds" => "Amiga port" you kind of have to create a high level abstraction of what you need to do. If it were me, this is how I'd approach it: 1) Rip YM2203 data from sound rom 2) Interpret YM2203 data: find instruments, etc... 3) Put each sound/song into an intermediate format 4) Translate that intermediate format into something protracker can play on the Amiga hardware Seeing those high level tasks, I believe creating a tool to do the first two jobs would be ideal... maybe the first three. I'm a C#/Java (really anything) developer, so I can quickly create a utility app that will do those three jobs. With the sound data in an intermediate format, it can be re-input into ProTracker format. The reason I favor sound synthesis instead of using WAVs is that WAVs (on the Amiga, at least) take up huge amounts of room. Sound synthesis takes up relatively little, and we have the Paula chip to do it for us. (Paula, right? Not Agnes or Denise? ![]() Dealing with storage/loading issues will be a separate problem to solve ![]() |
|
![]() |
![]() |
#116 | |
J.M.D - Bedroom Musician
Join Date: Apr 2014
Location: los angeles,ca
Posts: 3,596
|
Quote:
Last edited by saimon69; 23 August 2021 at 21:55. |
|
![]() |
![]() |
#117 | |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Quote:
|
|
![]() |
![]() |
#118 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Small update just to illustrate how things are going.
I don't think we need to get much further than this with the functions I'm reversing. Even a new coder could tell what this function does. This is how I'd like to get all of the defined functions in the Ghidra project. Then we'll be ready to move forward with the port. Code:
************************************************************** * FUNCTION * ************************************************************** undefined CongealBlueGoop() undefined A:1 <RETURN> CongealBlueGoop XREF[1]: Bank04::ad24(*) Bank04::aaf4 af XOR A Bank04::aaf5 dd b6 01 OR (IX+SPRITE_X_HI) Bank04::aaf8 20 12 JR NZ,too_far_away Bank04::aafa 3a 02 f4 LD A,(PLAYER_WEAPON_X_POS) Bank04::aafd c6 50 ADD A,0x50 Bank04::aaff dd 96 02 SUB (IX+SPRITE_X_LO) Bank04::ab02 fe a0 CP 0xa0 Bank04::ab04 30 06 JR NC,too_far_away Bank04::ab06 21 26 ad LD HL,BLUE_GOOP_CONGEALS = Bank04::ab09 c3 06 30 JP Maybe_HandleInanimateSprites::start too_far_away XREF[2]: Bank04::aaf8(j), Bank04::ab04(j) Bank04::ab0c 21 1e ad LD HL,BLUE_GOOP_SUSPENDED = Bank04::ab0f c3 06 30 JP Maybe_HandleInanimateSprites::start |
![]() |
![]() |
#119 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
Hey saimon69,
So for the last two days I've been reading up and gathering information on the sound stuff... ranging from PMD to MML to .M to VGM to YM2203 to AY files to HOOT, to HVR... you name it. I've found some vgz files that someone had converted from the original source... but it was an incomplete list. Sorry to say that the vgm format is probably too "big" for my purposes; the files tend to take up too much room. However, the original "data" seems to not take up much room at all. The Level 1 music, for instance, is only 1106 bytes long. That's fantastic; so I'd like to either eventually implement something for the Amiga that interprets the same "code" and patch data (replacing pointers, etc) the same way. I'd like to be able to find a standalone player that will play the music data "as is" from the sound rom itself. If the code to do that was open source--so much the better! Following instructions from this page (and related), I was able to make HOOT load up a test .M file and play it. It was the level 1 music data from Black Tiger. Unfortunately I don't understand the .M file spec, which means I'm probably not putting all the data in the correct spots... and the tune plays back at a really low pitch. I'm guessing that I need patches defined somewhere in the .M file. If you or someone you know has the .M (OPN) file spec and could share that with me, that would be great. I would love to simply be able to find all of the needed data to play a song or sound and hand-edit a binary .m file to create a proper .m file. Or if there's a tool that does that, so much the better ![]() ... In general news, the reversing continues. I'm to the point where pretty much all the sprite data has been tagged with fairly accurate names... and many more functions have been named much better. Certain parts of the game code are really starting to resemble more English than gibberish. I'm starting to see how the animation frames for a character are interleaved with decision points, where the code will run a function (pointer) for each character during an animation sequence. Based on what happens in the function, it can either loop back to the beginning of an animation sequence, or switch. If the sequence switches, you'll notice in code that the animation "bookmark" (or the pointer to the current animation frame byte) will move forward past the next few bytes. ;pseudo z80 code INC HL INC HL INC HL So the character animation is less like real "AI" and more like a "scripted" AI, which has decision points every few frames. |
![]() |
![]() |
#120 |
Registered User
Join Date: Jul 2021
Location: Sandy, UT
Age: 55
Posts: 230
|
ETA: Just found this, and it looks pretty good.
https://gitlab.com/bunnylin/supersak...er/doc/pmd.txt If anyone (in the meantime) has better information about the .m file format (specifically) please let me know. Thanks! |
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
![]() |
||||
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 |
|
|