don't click here

Sonic Pocket Adventure's Debug Mode

Discussion in 'Engineering & Reverse Engineering' started by SANiK, Jan 23, 2011.

Thread Status:
Not open for further replies.
  1. Sik

    Sik

    Sik is pronounced as "seek", not as "sick". Tech Member
    6,718
    1
    0
    being an asshole =P
    I was looking in the debug sound test and noticed something... Where the hell is BGM 0026 MSP_EME used?
     
  2. nineko

    nineko

    I am the Holy Cat Tech Member
    6,298
    475
    63
    italy
    You might try to compare it to ValleyBell's vgm pack, even though it seems to use different indexes (26 is labeled as the 1-up tune in his pack).
     
  3. ValleyBell

    ValleyBell

    Tech Member
    246
    25
    28
    researching PC-98/X68000 sound drivers
    I ever wanted to get the debug mode enabled. Great find!

    For the vgm pack I used this sound test
    [​IMG]
    BGM 0026 MSP_EME is used during the Special Ending.
    Listen to 30b - 33 Special Ending (with SFX).vgm at 0:15.
     
  4. SGR

    SGR

    Give me the gams. Member
    Anyone else getting crashes in NeoPop at the end of the level when you enable debug?
     
  5. Jaseman

    Jaseman

    The programmer has a nap! Hold out! Programmer! Member
    954
    1
    18
    How'd you get to that soundtest? My MP3 rip I had to do via a different one.
     
  6. JaxTH

    JaxTH

    Pudding Deity Oldbie
    10,355
    586
    93
    Los Angeles
    Jack shit.
    Why is there an "eject" button?
     
  7. Maybe that's how you get out of the sound test screen?
     
  8. ValleyBell

    ValleyBell

    Tech Member
    246
    25
    28
    researching PC-98/X68000 sound drivers
    I used some guides to collect enough puzzle pieces to complete three puzzles (as the wiki says here).
    I did this with NeoPop and copied the battery save into a save state of MESS.

    The "eject"-button is used to get out of the menu.
     
  9. SANiK

    SANiK

    Tech Member
    413
    0
    16
    If you want the short story:
    It's a NeoPop core simulation BIOS bug. NeoPop's core is used in a lot of NGPC emulators, but I have posted the bugfix to the multi-emu Mednafen's boards since it's the most active.

    If you want a temporary fix for the bug then open up the Sonic Pocket Adventure rom in a hex editor, and change the 0xF0 at 0x3769C to 0x10.
    This should the stop the crashing for that case only.

    If you want the long story:
    The NGPC has several system functions in the BIOS that can be accessed via the following assembly code:
    Code (Text):
    1. LDF 3
    2. LD w, #some function number here#
    3. SWI 1
    NeoPop simulates the BIOS and SWI call in C once it detects it, and what it does for SWI #1 is that it takes w, multiplies it by 4, and adds it to 0xFFFE00 to get the address of the interrupt to execute. Then it jumps there.

    This is the NeoPop code for that in TLCS900h_interpret_single.c
    Code (Text):
    1. //===== SWI num
    2. void sngSWI()
    3. {
    4.     cycles = 16;
    5.  
    6.     switch(first & 7)
    7.  
    8.     {
    9.  
    10.         //System Call
    11.     case 1: push32(pc);    
    12. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc = loadL(0xFFFE00 + (rCodeB(0x31) << 2));
    13. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
    14.  
    15. &nbsp;&nbsp;&nbsp;&nbsp;case 3: interrupt(0);&nbsp;&nbsp;&nbsp;&nbsp;//SWI 3
    16. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
    17.  
    18. &nbsp;&nbsp;&nbsp;&nbsp;case 4:&nbsp;&nbsp;&nbsp;&nbsp;interrupt(1);&nbsp;&nbsp;&nbsp;&nbsp;//SWI 4
    19. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
    20.  
    21. &nbsp;&nbsp;&nbsp;&nbsp;case 5: interrupt(2);&nbsp;&nbsp;&nbsp;&nbsp;//SWI 5
    22. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
    23.  
    24. &nbsp;&nbsp;&nbsp;&nbsp;case 6: interrupt(3);&nbsp;&nbsp;&nbsp;&nbsp;//SWI 6
    25. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
    26.  
    27. &nbsp;&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;instruction_error("SWI %d is not valid.", first & 7);
    28. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
    29.  
    30. &nbsp;&nbsp;&nbsp;&nbsp;}
    31.  
    32. }
    The problem area is pc = loadL(0xFFFE00 + (rCodeB(0x31) << 2));
    rCodeB(0x31) is NeoPop's way of referring to the 8-bit register w in bank 3.

    This is the code that causes the crash in the Sonic Pocket Adventure rom when debug is on:
    Code (Text):
    1. 0x237693: POP XDE, prevPC: 0xFF6FD8
    2. 0x237694: CP RA3,0, prevPC: 0x237693
    3. 0x237697: JR NZ,0x237677, prevPC: 0x237694
    4. 0x237699: LD RW3,0xF0, prevPC: 0x237697
    5. 0x23769D: LD RBC3,0x000C, prevPC: 0x237699
    6. 0x2376A2: LD XHL3,XDE, prevPC: 0x23769D
    7. 0x2376A5: SWI 1, prevPC: 0x2376A2
    8. CRASH!
    9.  
    10. //SWI 1 trying to go to address 0x010001C0, CRASH!
    We can see at 0x2376A SWI #1 is called, so why does it crash and why does it try to go to 0x010001C0?

    If we look above the SWI #1 instruction to see what w is set to, we see:
    LD RW3,0xF0
    That loads register w in bank 3 with 0xF0.

    What NeoPop does in SWI #1 is that it takes w which is 0xF0, multiplies it by 4 (which is what the << 2 does in the C code), and adds it to 0xFFFE00.
    This gives you the bad address 0x010001C0 or 0x1C0 if we ignore the top byte.

    I found a homebrew interrupt routine that implements SWI 1 as:
    Code (Text):
    1. ldf 3
    2. push XIX
    3. and w,1F
    4. add w,w
    5. add w,w
    6. ld XIX,0x00FFFE00
    7. ld XIX,(XIX+W)
    8. call XIX
    9. pop XIX
    10. reti
    Notice how it Ands w with 0x1F before multiplying it by 4 (via the two adds)? This is something NeoPop does not do.
    Obviously this is why NeoPop crashes. NeoPop was using 0xF0 stored in w when it should be doing (w & 0x1F) to get 0x10 instead of 0xF0.

    So the reason Debug mode crashes is because it is a NeoPop emulator bug. To fix it, you would have to recompile the emulator and change in the above mentioned function from: pc = loadL(0xFFFE00 + (rCodeB(0x31) << 2)); to pc = loadL(0xFFFE00 + ((rCodeB(0x31) & 0x1F) << 2));
     
  10. SGR

    SGR

    Give me the gams. Member
    I'll give this a try. I'll try option #2 if I encounter anything else.
     
Thread Status:
Not open for further replies.