What's new

WIP: Knight's Chance Multi-Slot Attract Mode Fix

lithy

Student
Joined
Nov 8, 2024
Messages
60
Reaction score
116
Location
Pittsburgh, PA
Background: (Unimportant, blah, blah, blah) So I had decided that I wanted to learn just the tiniest little bit about looking at/reading/understanding some of the assembly code behind the games. I have no real background in anything that would make me assume that even the basics would be easy for me. I assume a 5 minute task for the right person might take me 5 weeks. I chose the smallest project I had interest in, patching Knight's Chance so that the attract mode advances to the next slot in a Neo Geo multislot board like the 'official' games do. I have cabs and I like to leave attract modes cycling and Knight's Chance has a great little attract mode, it's a shame that I never leave it in the cabinet because it ends up just repeating itself.

Goal (Small): Modify Knight's Chance P1 rom to allow the game to cycle in a multi slot Neo board. I have a paid digital copy and a bootleg cart. I have a Backbit cart that I should be able to use to test a modified P-rom with the ultimate goal to replace the P1 eprom on my bootleg cart. DONE!

FIX: in a hex editor on the P1 rom at $AB8, change the string from 4E B9 00 01 B2 D0 to 4E F9 00 C0 04 44

It is byteswapped so it will read B9 4E 01 00 D0 B2 and you will change that to F9 4E C0 00 44 04

Save and replace the P1 rom. This change has not been extensively tested but seems to work, please post it you find it causes any issues.


Goal (Medium): Knight's Chance also doesn't seem to show the Neo Geo splash screen, modify to show Neo Geo splash

Goal (Large): Knight's Chance only shows High Scores at the Game Over conclusion of playing a game. Might be nice to at the very least rotate through one of the 4 high score screens during an attract cycle. The hold on the title screen is somewhat lengthy, it could take some of the time from that hold away so as not extend the length of each cycle further.

Mostly, this thread is just a place where I can 'work out loud'. Of course any suggestions or help are appreciated. I already got an assist from @nauman here, along with the smart suggestion to start a thread.
 
Last edited:
What I have managed so far was to start to try to understand how this table controlled the slot selection mechanic


$10FD81BIOS_SYSRET_STATUSbyteBIOSInternal value which stores the function code that SYSTEM_RETURN will call.
  • 0 : Init bram/select valid game for eye-catcher
  • 1 : Set the EL-LED to the correct value
  • 2 : Switch to the next slot, relaunch eye-catcher
  • 3 : After a gameover, save the playtime for bookeeping, switch to DEMO mode, reset the workbackup ram
  • 4 : Switch next slot (select p1 pressed)
  • 5 : Switch to previous slot (select p2 pressed)
  • 6 : Called after a coin deposit, does nothing

Then I decided to use Metal Slug just because I already had the rom for a comparison.

Here is what Metal Slug is doing at that bit with my notes on what the game doing at each watchpoint.
Code:
HBMAME debugger version 0.245.25 (2025-05-10)
Currently targeting mslug (Metal Slug - Super Vehicle-001)
>wpset 10FD81,1,w,wpdata !=0
Watchpoint 1 set
Stopped at watchpoint 1 writing 5555 to 10FD80 (PC=C13160) - Booting
Stopped at watchpoint 1 writing AAAA to 10FD80 (PC=C13184) - Booting
Stopped at watchpoint 1 writing FD80 to 10FD80 (PC=C131A6) - Booting
Stopped at watchpoint 1 writing 01 to 10FD81 (PC=C113D2) - Neo Geo Splash (#1: SYS_INT1, jump to system ROM, C11646/$C00438, #2: SYSRETURN, C113D2/$C00444
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C11432) - Begin attract mode (title, demo, high scores)
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C1149A) - Attract mode ends
Stopped at watchpoint 1 writing 01 to 10FD81 (PC=C114BC) - Neo Geo Splash (kept for being sent to this by a different line, after this next attract mode to start is same as before)
Stopped at watchpoint 1 writing 06 to 10FD81 (PC=C11892) - Coin add break
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C114FC) - Game Start compulsion begins
Stopped at watchpoint 1 writing 03 to 10FD81 (PC=C1176E) - Game Start, through to game over
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C11460) - Relaunch attract mode after game over

And here is what Knight's Chance is doing at the same bit also with my notes
Code:
HBMAME debugger version 0.245.25 (2025-05-10)
Currently targeting knightsch (Knight's Chance)
>wpset 10FD81,1,w,wpdata !=0
Stopped at watchpoint 1 writing 5555 to 10FD80 (PC=C13160) - Booting
Stopped at watchpoint 1 writing AAAA to 10FD80 (PC=C13184) - Booting
Stopped at watchpoint 1 writing FD80 to 10FD80 (PC=C131A6) - Booting
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C11418) - Begin attract mode (Neobitz logo, demo, title)
Stopped at watchpoint 1 writing 06 to 10FD81 (PC=C11892) - Coin add break
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C114FC) - Game Start compulsion begins
Stopped at watchpoint 1 writing 03 to 10FD81 (PC=C1176E) - Game Start, through to game over
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C11460) - Relaunch attract mode after game over

So, differences...Metal Slug writes another 2 at the end of the attract mode, I am not sure why it might do this since the bit doesn't seem to change during the attract mode, but it is a difference. Knight's Chance also never writes a 1 for the Neo Geo splash screen. nauman showed me that Knight's Chance is never sent back to C00444 where it would read the 2 and be able to move to the next slot.
 
What I need to figure out now, insert the jmp back to C00444 at the end of the Knight's Chance attract mode as suggested by nauman

So...how do I figure how what instruction is ending the attract mode and looping it back around to the beginning? I've determined that from a fresh boot of the game through one attract mode cycle lasts around 4500 frames (screen goes black on frame 4497, 2014 copyright disappears on frame 4498, neobitz logo begins to appear on frame 4532.

These instructions are right after the first write of the bios status, is the jsr to $c12390 the start of the attract mode? If so can I maybe find the end of the attract mode where it send it back to $c12390 again?

Code:
C11418  move.b  #$2, ($a81,A5)                              1B7C 0002 0A81
 C1141E  jsr     ($f70,PC) ; ($c12390)                       4EBA 0F70
I did find that the instructions change from frame 4497 to 4498, so that would seem to be the break.

4497 takes this break, 4498 does not
000220 bmi $228 6B06
 
Last edited:
I really like your energy to learn more :)

So.. i spent a few hours this morning analyzing the game and I can now be bold enough to promise that the issue can be resolved with a small patch.
Tried to upload a gif showing this but my knowledge does not lay in video/uploading so you just have to believe me :D

Since you are open to learn, I will support you in this journey but not tell you straight away how to do it.
While no method of debugging is wrong, I would encourage you to use a decompiler like Ghidra to see more into what assembly instructions are actually executing. With that help, you can then use Mame to set breakpoints since the address-space is very static compare to software for Windows etc.

Here is some brief instructions how to get going with Ghidra:
  • Swap the endian of the rom:
    Code:
     dd if=kc_p1_mod.rom of=kc_p1_mod.rom.bigendian conv=swap
  • Open the swapped binary in Ghidra, choose a default 68k cpu. Since the game actually starts a offset 0, we do not need to add a memory map, but add the following if you want to:
1754128257117.png


Next, you want to identify a entry-point, which in this case is the USER-function that is always placed at 0x122 on the cartridge. this is a jump-instruction so we have to follow it to the real function. If you end up in the correct location you are going to see the following (but minus the names I added for myself):
1754128809225.png


And I am gonna leave you here for now and say... don't give up. Take a break, but never give up :)

A final tip on the way, the same address you see on the left can be used in Mame with
Code:
bpset 0x0000026c
To modify the binary I used HxD, but again, use the tools you like, these are just my choices.
 
What I have managed so far was to start to try to understand how this table controlled the slot selection mechanic


$10FD81BIOS_SYSRET_STATUSbyteBIOSInternal value which stores the function code that SYSTEM_RETURN will call.
  • 0 : Init bram/select valid game for eye-catcher
  • 1 : Set the EL-LED to the correct value
  • 2 : Switch to the next slot, relaunch eye-catcher
  • 3 : After a gameover, save the playtime for bookeeping, switch to DEMO mode, reset the workbackup ram
  • 4 : Switch next slot (select p1 pressed)
  • 5 : Switch to previous slot (select p2 pressed)
  • 6 : Called after a coin deposit, does nothing

Then I decided to use Metal Slug just because I already had the rom for a comparison.

Here is what Metal Slug is doing at that bit with my notes on what the game doing at each watchpoint.
Code:
HBMAME debugger version 0.245.25 (2025-05-10)
Currently targeting mslug (Metal Slug - Super Vehicle-001)
>wpset 10FD81,1,w,wpdata !=0
Watchpoint 1 set
Stopped at watchpoint 1 writing 5555 to 10FD80 (PC=C13160) - Booting
Stopped at watchpoint 1 writing AAAA to 10FD80 (PC=C13184) - Booting
Stopped at watchpoint 1 writing FD80 to 10FD80 (PC=C131A6) - Booting
Stopped at watchpoint 1 writing 01 to 10FD81 (PC=C113D2) - Neo Geo Splash (#1: SYS_INT1, jump to system ROM, C11646/$C00438, #2: SYSRETURN, C113D2/$C00444
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C11432) - Begin attract mode (title, demo, high scores)
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C1149A) - Attract mode ends
Stopped at watchpoint 1 writing 01 to 10FD81 (PC=C114BC) - Neo Geo Splash (kept for being sent to this by a different line, after this next attract mode to start is same as before)
Stopped at watchpoint 1 writing 06 to 10FD81 (PC=C11892) - Coin add break
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C114FC) - Game Start compulsion begins
Stopped at watchpoint 1 writing 03 to 10FD81 (PC=C1176E) - Game Start, through to game over
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C11460) - Relaunch attract mode after game over

And here is what Knight's Chance is doing at the same bit also with my notes
Code:
HBMAME debugger version 0.245.25 (2025-05-10)
Currently targeting knightsch (Knight's Chance)
>wpset 10FD81,1,w,wpdata !=0
Stopped at watchpoint 1 writing 5555 to 10FD80 (PC=C13160) - Booting
Stopped at watchpoint 1 writing AAAA to 10FD80 (PC=C13184) - Booting
Stopped at watchpoint 1 writing FD80 to 10FD80 (PC=C131A6) - Booting
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C11418) - Begin attract mode (Neobitz logo, demo, title)
Stopped at watchpoint 1 writing 06 to 10FD81 (PC=C11892) - Coin add break
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C114FC) - Game Start compulsion begins
Stopped at watchpoint 1 writing 03 to 10FD81 (PC=C1176E) - Game Start, through to game over
Stopped at watchpoint 1 writing 02 to 10FD81 (PC=C11460) - Relaunch attract mode after game over

So, differences...Metal Slug writes another 2 at the end of the attract mode, I am not sure why it might do this since the bit doesn't seem to change during the attract mode, but it is a difference. Knight's Chance also never writes a 1 for the Neo Geo splash screen. nauman showed me that Knight's Chance is never sent back to C00444 where it would read the 2 and be able to move to the next slot.
Just a quick tip when reading this debug. If you see PC=Cxxxxx, that is, starting with a 'C', that is actually mapped to the Neo Geo memory map shown here
So.. 'C' is equal "System ROM", which is the BIOS. If you saw a PC starting with a 0 you would know it is the P-ROM writing/reading, which is the game/cartridge.

Neither game is modifying this memory space, and that is expected since this value is an BIOS internal registry to keep up with the 'next step' of actions.
The main issue with Knights Chance is that it never returns the execution to the BIOS, and therefor this value is never 'used", even if it is correct.
 
Neither game is modifying this memory space, and that is expected since this value is an BIOS internal registry to keep up with the 'next step' of actions.
The main issue with Knights Chance is that it never returns the execution to the BIOS, and therefor this value is never 'used", even if it is correct.

The part above hit me while I laid in bed last night and I was just coming back to post it! You obviously explained it in your post in the Final Vendetta thread but I just didn't quite comprehend it late last night when I put up my posts. But now understanding that what I was seeing as Metal Slug 'writing' a 2 again to $10FD81 at the end of the attract mode (and thinking it was the game rom doing this even though it was already set to 2) instead was the game rom sending control back to the system rom (jumping to c00444), then once there, the bios writes the bit and then checks it. Anything I'm still missing?

I appreciate the no spoilers (for now at least lol ;)). Hopefully you won't get bored while I fumble around. And thanks so much for the tools suggestions, I have family in town for a couple days so might not have time to stare at it but I will definitely come back and give it some more attention.
 
No stress from my end :)

You have the core principles correct about the usage of 0x10FD81. The documentation is a bit confusing due to the fact that BIOS_SYSRET_STATUS is used for multiple and different types of loops in the BIOS. For simplicity you can assume it is correct (since the game never changes it anyway) and only focus on the game code itself. Once you grasp the overall structure of execution I believe you will also find the solution pretty quickly.
 
Ok had just a few minutes to make some progress at least in following in your footsteps.

I had to go searching for a way to byteswap on Windows, because unless I'm a dum dum and not understanding where you were executing that swap command, dd seems to not be available for Windows. I found a program that works in any case and then was able to load a byteswapped p1 into Ghidra and looking for instruction line 00000122 which is just a jump to 0000025C.

Over at 25C, I get a series of instructions that looks close to your screenshot without the labels, however it isn't parsing a few instruction lines the same way as yours (26E-279). Is that maybe just because I haven't defined the label addresses like you did?

recreated.png
 
Great job so far! Yes, dd is for Linux but it is also well known so I figured you probably would find a solution if you ran Windows :)

What a decompiler does is a wild guess on what the data is. If you run "Disassemble" or "D", it will try to parse it as an instruction which it is not.
The row 0x268 is an address + offset which it reads and then jumps to (the address at that place) at 0x26c. The offset starts at 0x26e, which is also where your instructions gone weird.
If you mark 0x26e and press "C" and then press "P", you will then create a pointer instead, which is the correct value to be parsed.

"(A0)" == read the value/address at A0 and then jump to it.

To debug this in Mame you can place a "bpset 0x26c", look at the A0 value and then use F11 to single step forward to see where it jumps to. Also look at D0 since that is the offset to 0x26e.
 
Ok, feel like I might need a push in the right direction, still wasn't quite sure where it must be sending the attract mode back to repeat. I have some ideas checked, and learning how to read a little more of what the code is doing.

First and unrelated, the byte at $114 is 02 and does not seem to be set during booting up or written at any point. I believe this is saying the system should do nothing for an eyecatcher rather than having the system handle the eyecatcher (byte= 00) or the game handle its own eyecatcher (byte=01). Which makes me think the Neobitz logo is handled as part of the Demo mode and not as a separate eyecatcher but I'm not sure. If I want to reinstate the typical Neo Geo splash screen, I guess that is where I'd have to start, but looks like the game needs sprite and fix data to use the system's eyecatcher which I don't know if Knight's Chance has.

Ok, so I was looking at $12E which is the DEMO_END routine, but that seems to be for any interrupt of the attract mode (coin added or select game button pressed). It does not seem to use this when the attract mode ends and restarts just by time.

Next I was looking at how the game handles BIOS_USER_REQUEST at $10FDAE. But it seems like it writes a 02 byte during boot up then reads it to call for attract mode, but then doesn't read or write it again at the end of the attract mode before restarting. It also writes 01 twice during boot up to BIOS_USER_MODE at $10FDAF. It reads this from a few locations throughout the attract mode, but doesn't rewrite it either once it loops around.

So my best guess so far is that I should be looking at $10FD80, BIOS_SYSTEM_MODE. Wiki says it is 00 when BIOS wants VBLANK (System mode) and 80 when Game wants VBLANK (Game mode). If I'm looking to find a spot to jmp back to SYSTEM_RETURN ($C00444), then I've narrowed down to this as a possibility. During boot it writes 00 (actually 02 for $10FD81) just before the Neobitz logo, then it writes 80 (82 with $10FD81) just before the attract mode starts.

Then at the end of attract mode, it writes 02 again from $716, before showing the Neobitz logo again.

Code:
01B15A  move.w  #$ff, (A0)                                  30BC 00FF
01B15E  dbra    D0, $1b15a                                  51C8 FFFA
...
01B15A  move.w  #$ff, (A0)                                  30BC 00FF
01B15E  dbra    D0, $1b15a                                  51C8 FFFA
01B162  rts                                                 4E75
000702  move.b  #$b, $320000.l                              13FC 000B 0032 0000
00070A  movea.l #$10fd80, A0                                207C 0010 FD80
000710  move.b  (A0), D0                                    1010
000712  eori.b  #$80, D0                                    0A00 0080
000716  move.b  D0, (A0)                                    1080
000718  lea     $1d9e.l, A3                                 47F9 0000 1D9E
00071E  jsr     (A3)                                        4E93

The first two lines are repeated in a long loop prior to advancing but I just left them in twice to show it is repeating, so what I think I roughly understand this string to be doing.
-$01B15A and $01B15E acting as a counter (decrement D0 and branch back to $01B15 if not equal to -1) possibly for how long to run the attract mode?
-Then when the timer ends, it allows it to advance to $01B162 and RTSes back to $702.
-From there, it writes a $B value to $320000, not sure what this is, but possibly REG_STATUS_A
-Then writes address $10FD80 to A0
Then moves the value in A0 (FF82) to D0
-eori.b instruction takes 80 and FF82 and reconciles them to FF02 saved in D0 (I think I understand this is a binary comparison 1&0=1, 0&1=1, 1&1=0, 0&0=0)
-Then writes D0 (FF02) to the A0 address $10FD80
-Then puts the address $1D9E into A3
-Then jumps to subroutine at A3 address ($1D9E)

Does it make sense to redirect a 'jsr' from here to a new subroutine that includes a SYSTEM_RETURN, particularly at $718/$71E?

I haven't looked too far yet at what $1D9E is doing, but I assume it is instructions for the reinitializing the Neobitz splash screen now that $10FD80 is 02 again.

This seems like a too long post already, so I'll leave it here.
 
Last edited:
I enjoy reading about your progress. You are not far off by the looks of it :)

The function getting called at 0x1b144 is a loop, with a counter like you said, reseting the fixed layer of the VRAM. This is pretty normal to see running each frame if this layer has a lot of movement. Some would probably say it is wasteful but well... it doesn't slow anything down in this case anyway.

0x10FD80 is a signal for both game and BIOS to give the other party a chance to back off safely when code is running in a sort of limbo regarding who is actually running the code from now on. I guess the most clear case of usage is in system_io() where the BIOS ignore some checks if the game is not running yet. Why keep track of "player start"-button and compulsion timer when the game is not even active and so on.
To be honest, I have a little hard time understanding why they flip this bit at 0x712 but I wouldn't read much into it.

This is a psudo-version in C:
Code:
*(uint8_t *)0x10FD80 = (*(uint8_t *)0x10FD80) ^ 0x80;
Key take is that it reads a byte and flips the left most bit from 0 -> 1 and 1 -> 0

Okey, a lot of progress but what is next?
I believe you would benefit from identifying how the attract-mode loops around in different stages and why it doesn't move on.
Don't be shy and change the code at 0x718 and see what happens. Just save the original somewhere and modify a copy until it breaks :)
Sometimes you must see what happens to realize what the code really does.

One suggestion would be to replace an instruction with '4E71' which is a NOP-instruction. The only thing it does is moving on to the next instruction which is the same thing as erasing code without breaking it (well, semi-true at least :D). If you replace 0x71E with a NOP, you would run the game without this functions and hopefully see something different happening on the screen. Maybe it then becomes obvious what the functions was doing.

A way of debugging is placing multiple breakpoints at different levels to see when it actually hits. If something never hits this point until a screen is shifted, well then you know everything above is only for handling the screens before.

Here are two small spoilers that I hope give away enough information to move further, if you choose to read them that is ;)

I named 0x1d9e to "update_credit_value" since it reads some internal BIOS values for credit and freeplay and later on adds a string to the screen.

0x100000 is what keeps the loop going, but what changes its value? Press 's' and search for the memory hex 100000 to see where it is used and where it is changed. While it doesn't answer the main question, it is still a key feature to understand and you might stumble upon another key feature of the code while at it.

About the side quest about the eyecatcher, 0x114 is a static variable in the cartridge and it will never change. If this is 0, the BIOS will run the normal 'Neo Geo' screen from its own code. If it is 1, the BIOS will set BIOS_USER_REQUEST == 1 (Boot animation) and then call USER(). The Knights Chance does really not wanna handle an eye-catcher because the code only loops back to SYSTEM_RETURN() straight away. Value of 1 wouldn't do much and 2 ignores everything.

If you change 0x272 to point to a free space in the rom, add some assembly code for a nice eye-catcher, change 0x114 to 1, it will then run your eyecatcher.
 
Ok, I reviewed locations where it was reading $100000 and found that $a9a tests the data there every frame but only during the title screen portion of the attract mode. Figuring that might be the timer controlling the 'end' of the attract mode, I looked at what was there.

Code:
 000A9A  tst.l   $100000.l                                   4AB9 0010 0000
 000AA0  bne     $aaa                                        6608
 000AA2  cmpa.w  #$0, A2                                     B4FC 0000
 000AA6  beq     $9f4                                        6700 FF4C
 000AAA  cmpa.w  #$0, A2                                     B4FC 0000
 000AAE  beq     $aca                                        671A
 000AB0  move.b  #$f, $320000.l                              13FC 000F 0032 0000
 000AB8  jsr     $1b2d0.l                                    4EB9 0001 B2D0

So it tests $100000 over and over (I admit I have no idea yet what it is doing each time :)) until it is happy and then does a break to $aaa, I set a breakpoint to check $aaa and found it only hits it one time from bootup all the way through attract right as it loops over. So just since the lengths were the same, I decided to swap the next JSR at AB8 to a JMP to C00444. I assumed that if I was skipping something useful in the code after that, well... it is going to be resstarting the game from the beginning anyway...so probably be ok? lol

So yeah no idea if this is the best thing to do, but it seems to work when I put the patched prom into the file and load it with my backbit cart, it advances to the next slot in a 2 slot at the end of attract mode and back again from the other game and the game seems to still be playing ok.

So now I'm curious if I got to the same place as you!
 
Well done making it work :)

Let walk through a few things.

Code:
 000A9A  tst.l   $100000.l                                   4AB9 0010 0000
 000AA0  bne     $aaa                                        6608
This checks if the 4 byte value at 0x100000 is 0. If it is not 0 then it branch to location 0xAAA.
The value 0x100000 is only changed when bit 1 in the memory 0x10FDB4 (BIOS_START_FLAG) is set, which only happens when start button is pressed and there is enough credits to play.

At 0xAAA location it now tests if it should restart the attract-playlist or move forward. And this is where I started debugging my version.
If we can make it always move forward instead of looping back, the code will then return to SYSTEM_RETURN.

This assumption was based on the start where it actually looks like it should be returning at some point to 0x2E4 and then call SYSTEM_RETURN.
Code:
                             DEMO
        0000028a 4e b9 00        jsr        FUN_000002a4.l                                                                  undefined FUN_000002a4()
                 00 02 a4
        00000290 4e f9 00        jmp        FUN_000002de.l                                                                  undefined FUN_000002de()
                 00 02 de
...
        000002de 4e b9 00        jsr        FUN_00000558.l                                                                  undefined FUN_00000558()
                 00 05 58
        000002e4 4e f9 00        jmp        BIOS_SYSTEM_RETURN.l
                 c0 04 44

What I tried was the code below but that made it just start the game, which was.. not what I was expecting. This made me worried that it maybe just had one starting point and the fix would be way more complex.
Code:
        00000ac6 60 00 fc 24     bra.w      ATTRACT_START
->
        00000ac6 4E 71           NOP
        00000ac8 4E 71           NOP

So instead of trying to honor the rest of the code I decided to change the following:
Code:
        00000ac6 60 00 fc 24     bra.w      ATTRACT_START
->
        00000ac6 4e f9 00        jmp        LAB_00c00444.l
                 c0 04 44

If you look closely you would find that this fix is actually erasing some of the code after this jump instruction because it is more wide than a branch. Didn't care that much if it broke other parts since I was just aiming to see if the return was fixing the flow. I really thought this would break some internal logic in the title-screen/compulsion-timer but as it turns out, it just worked (as far as my limited test showed) despite the ugly break in the flow.

To be honest, I didn't bother debugging further since I was just curious how the game worked and if it would be feasible to fix :)
Was overthinking a solution a bit by copy the 0xAB8 function somewhere and replace the end with a jump to SYSTEM_RETURN instead of a RTS, but this function is something I later named "wait_for_vblank" so yeah, your fix by replacing this call with SYSTEM_RETURN is probably a better version since it would only skip a frame anyway and doesn't modify any code/logic further down.

Again, good job and the important thing I hope you take from this is that you gained knowledge of how parts work, added a fix of your own and if it works, well... it is then a good fix! :)

About the eyecatcher, an interesting side-effect by not using the build-in eyecatcher is that a multi-slot system (with original BIOS) will always jump over to the first cartridge using the build-in eye-catcher, which makes the Knight's Chance never to show up first, even if it is in the first slot.
If you run Mame with these options "-cart1 nam1975 -cart2 knightsc -cart3 mslug" you would see that Metal Slug would boot first, even if two games (with no default eyecatcher) are in the slots before. Anyway, just an interesting thing I found and wouldn't apply to Blackbit or other multi-cartridges since they load games differently.
 
Back
Top