News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: Dragon Warrior III MMC5 Bankswitch Help  (Read 1192 times)

Dracula X

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
    • My YouTube Page for ROM hacking
Dragon Warrior III MMC5 Bankswitch Help
« on: October 19, 2019, 08:00:40 pm »
Here's what the code looks like:

Location: $3FFA1 & $7FFA1
Code: [Select]
1F:FF91: 8D D5 06  STA $06D5 = #$01
 1F:FF94: 48        PHA
 1F:FF95: AD C8 06  LDA $06C8 = #$00
 1F:FF98: 29 EF     AND #$EF
 1F:FF9A: 8D C8 06  STA $06C8 = #$00
 1F:FF9D: 68        PLA
 1F:FF9E: 48        PHA
 1F:FF9F: 29 10     AND #$10
 1F:FFA1: 0D C8 06  ORA $06C8 = #$00
 1F:FFA4: 8D C8 06  STA $06C8 = #$00
 1F:FFA7: 68        PLA
 1F:FFA8: 29 0F     AND #$0F
 1F:FFAA: EA        NOP
 1F:FFAB: EA        NOP
>1F:FFAC: 8D FF FF  STA $FFFF = #$E8
 1F:FFAF: 4A        LSR
 1F:FFB0: 8D FF FF  STA $FFFF = #$E8
 1F:FFB3: 4A        LSR
 1F:FFB4: 8D FF FF  STA $FFFF = #$E8
 1F:FFB7: 4A        LSR
 1F:FFB8: 8D FF FF  STA $FFFF = #$E8
 1F:FFBB: 4A        LSR
 1F:FFBC: 8D FF FF  STA $FFFF = #$E8

Bankswitch code:
Code: [Select]
bankswitch:
asl
ora #$80
sta $5115
lda #$00
rts

When I add the code at $FFAC, the game will not work but if I put the code at $FF94, the game will work.
So do I need to delete the code or keep them there after $FFA3?

« Last Edit: October 19, 2019, 08:32:54 pm by Dracula X »
I do not do other games that have already been done.

Disch

  • Hero Member
  • *****
  • Posts: 2744
  • NES Junkie
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #1 on: October 19, 2019, 09:19:18 pm »
"Location: $3FFA1 & $7FFA1"

$7FFA1?

So this ROM has 512K PRG?

512K is too big for MMC1 usually, which means in order to make this work the game must be using SUROM (or something similar), which means PRG swapping is split between two registers:

$FFFF (or really anything in the $E000-FFFF range) gets the low 4 bits
$BFFF (or really anything in the $A000-BFFF range) gets the 5th bit

The code at $FF95 seems to be preserving the 5th bit, presumably so it can be written to $BFFF later.

Which means your view of the original bankswapping code is likely incomplete.  Does this code eventually write to $BFFF?  Or does it jump somewhere that does?  I would set a breakpoints on writes to $BFFF and see what code is calling it and when.



But just going on what I see here:

Easy case:  IF $3Cxxx and $7Cxxx banks are 100% identical

If this is the case, $3Cxxx doesn't need to be used at all and can be scrapped.  These banks had to be duplicated on MMC1 because of a weird swapping quirk ... but on MMC5 you don't have that quirk so you don't have to worry about it.

You can wipe the $3Cxxx bank clean and use it as free space.  And the $7Cxxx bank can be your "fixed" bank.

Harder case:  $3Cxxx and $7Cxxx have some stuff that is not 100% identical

This is trickier because it means the game might be relying on the weird swapping quirk, which means you have to simulate it with MMC5.

(note:  I am going to operate on the assumption that the game writes to $BFFF either immediately before or immediately after this bankswap code to apply the 5th bit.  Double check that to make sure.  If it doesn't, this is even HARDER)

The 5th bit not only selects the page for the $8000-BFFF range, but it ALSO swaps out the "fixed" bank at the $C000-FFFF range.  This means that on MMC5, you'll also have to swap out the $C000-FFFF range according to that bit (the $3Cxxx bank when the bit is zero, $7Cxxx when it's one)



In both cases

In both cases, the manipulation the game is doing with $06C8 may or may not be necessary with MMC5 (not possible to tell from just this code).  I would leave that code in to be safe -- having it there can't hurt.  Then I would jump to your 'bankswitch' routine at $FFAA ... but the AND at $FFA8 needs to be changed to AND #$1F, otherwise you're dropping the 5th bit.

Also, any time the original game writes to $BFFF, you can either rip that code out entirely (if it's only be accessed from your bankswitch routine), or replace it with an appropriate call to your bankswitch routine (if it's being accessed from anywhere else).  $BFFF writes have PRG swapping implications, so you can't ignore them entirely, but I strongly suspect the game is only writing there as part of this bankswitch routine.

abw

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #2 on: October 20, 2019, 12:05:16 am »
When I add the code at $FFAC, the game will not work but if I put the code at $FF94, the game will work.
$FFAC is also an entry point to the bankswap routine (from $E914), so only making changes at $FF94 is probably not the right thing to do.

So this ROM has 512K PRG?
[...]
Does this code eventually write to $BFFF?
[...]
Harder case:  $3Cxxx and $7Cxxx have some stuff that is not 100% identical
Yup, Dragon Warrior III is 512K PRG, and you're absolutely right about the bankswap routine continuing on to write to $BFFF. $3Cxxx and $7Cxxx differ a fair bit, and it looks like there's an extra complication due to some IRQ code (coming from a BRK, incidentally) that ends up reading parts of the bankswap code as data; if it comes across an opcode whose low nybble is $7 or $F, then the IRQ handler branches off to code that is normally never called, so any replacement code might need to be contorted a bit to avoid certain opcodes. If you're interested, a read breakpoint on $FF91-$FFAA should fire when changing maps.

Disch

  • Hero Member
  • *****
  • Posts: 2744
  • NES Junkie
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #3 on: October 20, 2019, 01:12:23 am »
If $FFAC is an alternate entry point, that complicates things quite a bit.  FFAC is after the game masks out the low 4 bits, which means that the code at E914 might be doing some kind of "local swap" (swapping from just within the same 256K block).


With this new info, I don't feel confident in any solution I've presented.  I think a more thorough examining of all the bankswapping code needs to be done in order to properly reproduce it with MMC5.


But I'm too lazy to actually disassemble the game myself, so I'll only respond to code posted here.   :P


EDIT:

Quote
it looks like there's an extra complication due to some IRQ code (coming from a BRK, incidentally) that ends up reading parts of the bankswap code as data; if it comes across an opcode whose low nybble is $7 or $F, then the IRQ handler branches off to code that is normally never called, so any replacement code might need to be contorted a bit to avoid certain opcodes.

Is it pulling the address to the bankswap code off the stack?

I've seen code that does something like that before... since MMC1 regs have to be written serially, an interrupt happening in the middle of your write sequence could really screw the pooch, so the game will check the return address on the stack and make adjustments.

If that is in fact what the game is doing, then the code that checks the bankswap routine can probably just be ripped out entirely because MMC5 wouldn't need that kind of correction.  And honestly I can't imagine why else the game would examine it's own code.
« Last Edit: October 20, 2019, 01:26:55 am by Disch »

Dracula X

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
    • My YouTube Page for ROM hacking
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #4 on: October 20, 2019, 01:21:33 am »
Thanks for a lot of info here! I got the bankswitch code to work at $7Cxxx - $FFAC by changing AND #$0F to AND #$1F. I'm still working on this tricky part in $3Cxxx while I start the game, the game will freeze.
I do not do other games that have already been done.

abw

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #5 on: October 20, 2019, 04:51:57 pm »
If $FFAC is an alternate entry point, that complicates things quite a bit.
[...]
But I'm too lazy to actually disassemble the game myself, so I'll only respond to code posted here.   :P
Yeah, I'm not sure how far down the rabbit hole I really want to go on this one, but parts of it are a little bit interesting, so... $FF94 is also an entry point, and I'm not 100% sure there aren't more - FCEUX's CDL says the majority of bytes from bank $1F ($7Cxxx) were used while $1F was loaded into RAM $8000-$BFFF, which is somewhat complicating my static analysis; apologies for any $[8-B]xxx vs. $[C-F]xxx errors or missing targetting data.

Here's the call to $FFAC:
Code: [Select]
; external control flow target (from $0D:$BBC5)
0x03E91A|$0F:$E90A:48      PHA       
0x03E91B|$0F:$E90B:AD C8 06 LDA $06C8 
0x03E91E|$0F:$E90E:29 EF    AND #$EF   
0x03E920|$0F:$E910:8D C8 06 STA $06C8 
0x03E923|$0F:$E913:68      PLA       
0x03E924|$0F:$E914:4C AC FF JMP $FFAC 
And the code that calls that code (looks like an infinite loop, so maybe it's relying on IRQ or the differences between banks $0F and $1F):
Code: [Select]
; control flow target (from $BBC8)
0x037BD0|$0D:$BBC0:AD D5 06 LDA $06D5 
0x037BD3|$0D:$BBC3:09 10    ORA #$10   
; call to code in a different bank ($0F:$E90A)
0x037BD5|$0D:$BBC5:20 0A E9 JSR $E90A 
0x037BD8|$0D:$BBC8:4C C0 BB JMP $BBC0 
For completeness, here's the entire bankswap routine:
Code: [Select]
; control flow target (from $C173, $C1B9, $C4C2, $C538, $C56E, $C57F, $C59A, $C5B9, $C5D6, $C5F5, $C60B, $C61B, $CCCB, $CCDF, $CCF9, $CD01, $CD09, $CD0F, $CD17, $CD1D, $CD28, $CD33, $CD3B, $CD41, $CD4A, $CDFE, $CE0D, $D0F3, $D1FC, $D320, $D329, $D462, $D587, $D929, $D937, $D9C8, $DA60, $DA82, $DAD8, $DAF9, $DB0B, $E25E, $E3B0, $E46B, $E6C5, $E6DB, $E8D7, $EB9F, $EBA9, $EC86, $EC96, $ECA1, $ECAE, $ECB6, $ED3C, $F931, $FD07, $FE25, $FE2D, $FF81)
; external control flow target (from $16:$8014, $1F:$C538, $1F:$C61B, $1F:$E81B, $1F:$E8D7, $1F:$E900, $1F:$EBD0)
0x03FFA1|$0F:$FF91:8D D5 06 STA $06D5 
; control flow target (from $C983, $C99C, $C9C0)
; external control flow target (from $1F:$C983, $1F:$C996, $1F:$C99C, $1F:$C9C0)
0x03FFA4|$0F:$FF94:48      PHA       
0x03FFA5|$0F:$FF95:AD C8 06 LDA $06C8 
0x03FFA8|$0F:$FF98:29 EF    AND #$EF   
0x03FFAA|$0F:$FF9A:8D C8 06 STA $06C8 
0x03FFAD|$0F:$FF9D:68      PLA       
0x03FFAE|$0F:$FF9E:48      PHA       
0x03FFAF|$0F:$FF9F:29 10    AND #$10   
0x03FFB1|$0F:$FFA1:0D C8 06 ORA $06C8 
0x03FFB4|$0F:$FFA4:8D C8 06 STA $06C8 
0x03FFB7|$0F:$FFA7:68      PLA       
0x03FFB8|$0F:$FFA8:29 0F    AND #$0F   
0x03FFBA|$0F:$FFAA:EA      NOP       
0x03FFBB|$0F:$FFAB:EA      NOP       
; control flow target (from $E914)
0x03FFBC|$0F:$FFAC:8D FF FF STA $FFFF 
0x03FFBF|$0F:$FFAF:4A      LSR       
0x03FFC0|$0F:$FFB0:8D FF FF STA $FFFF 
0x03FFC3|$0F:$FFB3:4A      LSR       
0x03FFC4|$0F:$FFB4:8D FF FF STA $FFFF 
0x03FFC7|$0F:$FFB7:4A      LSR       
0x03FFC8|$0F:$FFB8:8D FF FF STA $FFFF 
0x03FFCB|$0F:$FFBB:4A      LSR       
0x03FFCC|$0F:$FFBC:8D FF FF STA $FFFF 
0x03FFCF|$0F:$FFBF:AD C8 06 LDA $06C8 
0x03FFD2|$0F:$FFC2:8D FF BF STA $BFFF 
0x03FFD5|$0F:$FFC5:4A      LSR       
0x03FFD6|$0F:$FFC6:8D FF BF STA $BFFF 
0x03FFD9|$0F:$FFC9:4A      LSR       
0x03FFDA|$0F:$FFCA:8D FF BF STA $BFFF 
0x03FFDD|$0F:$FFCD:4A      LSR       
0x03FFDE|$0F:$FFCE:8D FF BF STA $BFFF 
0x03FFE1|$0F:$FFD1:4A      LSR       
0x03FFE2|$0F:$FFD2:8D FF BF STA $BFFF 
0x03FFE5|$0F:$FFD5:EA      NOP       
0x03FFE6|$0F:$FFD6:EA      NOP       
0x03FFE7|$0F:$FFD7:60      RTS       

Is it pulling the address to the bankswap code off the stack?

I've seen code that does something like that before... since MMC1 regs have to be written serially, an interrupt happening in the middle of your write sequence could really screw the pooch, so the game will check the return address on the stack and make adjustments.

If that is in fact what the game is doing, then the code that checks the bankswap routine can probably just be ripped out entirely because MMC5 wouldn't need that kind of correction.  And honestly I can't imagine why else the game would examine it's own code.
The IRQ handler does check to see whether its return address is in the range [$FFAB..$FFD5) and handles that case specially; I haven't gone through the code to see what it's doing, but adjusting for an interrupted bankswap sounds like a very plausible explanation. After the $FFAB - $FFD4 and non-$FFAB - $FFD4 paths rejoin, however, it checks the low 4 bits of the opcode at the return address and does different stuff if they're #$07 or #$0F; that's the part that seems weird to me:
Code: [Select]
; IRQ vector is $C96C
0x07C97C|$1F:$C96C:48      PHA       
0x07C97D|$1F:$C96D:98      TYA       
0x07C97E|$1F:$C96E:48      PHA       
0x07C97F|$1F:$C96F:8A      TXA       
0x07C980|$1F:$C970:48      PHA       
0x07C981|$1F:$C971:A9 10    LDA #$10   
0x07C983|$1F:$C973:25 1B    AND $1B   
0x07C985|$1F:$C975:D0 07    BNE $C97E 
0x07C987|$1F:$C977:A9 00    LDA #$00   
0x07C989|$1F:$C979:85 33    STA $33   
; call to code in a different bank ($0F:$CA5C)
0x07C98B|$1F:$C97B:20 5C CA JSR $CA5C 
; control flow target (from $8975)
0x07C98E|$1F:$C97E:EE DF FF INC $FFDF 
0x07C991|$1F:$C981:A9 1E    LDA #$1E   
; call to code in a different bank ($0F:$FF94)
0x07C993|$1F:$C983:20 94 FF JSR $FF94 
0x07C996|$1F:$C986:A9 10    LDA #$10   
; call to code in a different bank ($0F:$C665)
0x07C998|$1F:$C988:20 65 C6 JSR $C665 
0x07C99B|$1F:$C98B:A9 10    LDA #$10   
; call to code in a different bank ($0F:$C665)
0x07C99D|$1F:$C98D:20 65 C6 JSR $C665 
0x07C9A0|$1F:$C990:20 00 80 JSR $8000 
0x07C9A3|$1F:$C993:AD D5 06 LDA $06D5 
; call to code in a different bank ($0F:$FF94)
0x07C9A6|$1F:$C996:20 94 FF JSR $FF94 
0x07C9A9|$1F:$C999:AD D5 06 LDA $06D5 
; call to code in a different bank ($0F:$FF94)
0x07C9AC|$1F:$C99C:20 94 FF JSR $FF94 
0x07C9AF|$1F:$C99F:EE D2 06 INC $06D2 
; checking return address in the range [$FFAB..$FFD5)
0x07C9B2|$1F:$C9A2:BA      TSX       
0x07C9B3|$1F:$C9A3:BD 06 01 LDA $0106,X
0x07C9B6|$1F:$C9A6:C9 FF    CMP #$FF   
0x07C9B8|$1F:$C9A8:D0 19    BNE $C9C3 
0x07C9BA|$1F:$C9AA:BD 05 01 LDA $0105,X
0x07C9BD|$1F:$C9AD:C9 AB    CMP #$AB   
0x07C9BF|$1F:$C9AF:90 12    BCC $C9C3 
0x07C9C1|$1F:$C9B1:C9 D5    CMP #$D5   
0x07C9C3|$1F:$C9B3:B0 0E    BCS $C9C3 
0x07C9C5|$1F:$C9B5:A9 D5    LDA #$D5   
0x07C9C7|$1F:$C9B7:9D 05 01 STA $0105,X
; call to code in a different bank ($0F:$C9EA)
0x07C9CA|$1F:$C9BA:20 EA C9 JSR $C9EA 
0x07C9CD|$1F:$C9BD:AD D5 06 LDA $06D5 
; call to code in a different bank ($0F:$FF94)
0x07C9D0|$1F:$C9C0:20 94 FF JSR $FF94 
; control flow target (from $C9A8, $C9AF, $C9B3)
; both paths rejoin here
0x07C9D3|$1F:$C9C3:BA      TSX       
0x07C9D4|$1F:$C9C4:BD 06 01 LDA $0106,X
0x07C9D7|$1F:$C9C7:85 A2    STA $A2   
0x07C9D9|$1F:$C9C9:BD 05 01 LDA $0105,X
0x07C9DC|$1F:$C9CC:85 A1    STA $A1   
0x07C9DE|$1F:$C9CE:A0 00    LDY #$00   
0x07C9E0|$1F:$C9D0:B1 A1    LDA ($A1),Y
0x07C9E2|$1F:$C9D2:29 0F    AND #$0F   ; AND #$07 would have eliminated the need to CMP #$0F :p
0x07C9E4|$1F:$C9D4:C9 07    CMP #$07   
0x07C9E6|$1F:$C9D6:F0 0A    BEQ $C9E2 
0x07C9E8|$1F:$C9D8:C9 0F    CMP #$0F   
0x07C9EA|$1F:$C9DA:F0 06    BEQ $C9E2 
0x07C9EC|$1F:$C9DC:68      PLA       
0x07C9ED|$1F:$C9DD:AA      TAX       
0x07C9EE|$1F:$C9DE:68      PLA       
0x07C9EF|$1F:$C9DF:A8      TAY       
0x07C9F0|$1F:$C9E0:68      PLA       
0x07C9F1|$1F:$C9E1:40      RTI       

; over the course of an entire playthrough, this code was never logged:
0x03C9F2|$0F:$C9E2:68      PLA       
0x03C9F3|$0F:$C9E3:AA      TAX       
0x03C9F4|$0F:$C9E4:68      PLA       
0x03C9F5|$0F:$C9E5:A8      TAY       
0x03C9F6|$0F:$C9E6:68      PLA       
0x03C9F7|$0F:$C9E7:4C 64 E8 JMP $E864  ; $E864 does get executed by other callers, though

Disch

  • Hero Member
  • *****
  • Posts: 2744
  • NES Junkie
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #6 on: October 20, 2019, 07:17:26 pm »
Quote
it checks the low 4 bits of the opcode at the return address and does different stuff if they're #$07 or #$0F; that's the part that seems weird to me:

Yeah that is very weird.

A quick look at the 6502 instruction matrix shows that there are no [official] opcodes that end in 7 or F, so it's not surprising that block of code never ran.

You said the game uses BRK, so my only guess here is that this is ATTEMPTING to examine the BRK parameter byte (although it's doing that incorrectly).  Or... the game puts ANOTHER data byte after the filler byte that it'll skip over before RTI'ing.  That's a stretch, though.

In any case, this doesn't seem like something worth worrying about, and should be safe to ignore.  It is interesting though!


Quote
...the full bankswap routine...

Yeah, okay, so if code is jumping directly to FFAC then it is definitely doing a local swap.... which complicates things.

Assuming the entry points to this routine are only as listed, here's my stab at a complete MMC5 replacement routine, which requires no additional changes to any other section of code.

Code: [Select]

; Starting at 3FFBC (all code above can be unchanged from the original)
;   NOTE:  This includes "undoing" my previous recommendation of changing the AND to 1F
;      but I guess that doesn't really matter since we AND again shortly anyway
; This would also have to be duplicated at 7FFBC
;
; This also assumes you're in 16k PRG swap mode ($01 written to $5100)

EOR $06C8               ; use EOR magic to extract 5th bit from 06C8
AND #$0F                ;   without using additional RAM
EOR $06C8

AND #$1F                ; only care about 5 bit page number
ASL A                   ; double for MMC5
ORA #$80                ; set 'we want ROM' bit
STA $5115               ; swap $8000-BFFF page

LDA $06C8               ; get 5th bit (desired 256K block)
AND #$10                ; isolate it
ORA #$4F                ; last page in 256K block, also set 'we want ROM' bit
ASL A                   ; double it for MMC5
STA $5117               ; swap $C000-FFFF page

RTS

Dracula X

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
    • My YouTube Page for ROM hacking
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #7 on: October 20, 2019, 07:42:44 pm »
Thank you very much, Disch! The code works!
Thank you for your help too, abw!
« Last Edit: October 20, 2019, 09:19:09 pm by Dracula X »
I do not do other games that have already been done.

abw

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #8 on: October 20, 2019, 10:21:20 pm »
Hmm, after looking at this a little more carefully, I need to recant a couple of things. The IRQ vector is really $E864 and the NMI vector is $C96C, and closer examination of the trace log I was looking at earlier shows that the BRK I mentioned was actually being interrupted by NMI right after $FF91, which is awfully close to the danger zone.

Or... the game puts ANOTHER data byte after the filler byte that it'll skip over before RTI'ing.  That's a stretch, though.
As it happens, that appears to be exactly what's going on - the CDL from my playthrough logged around 1500 separate BRKs, and (assuming I can grep properly, because I sure wasn't going to do a visual examination) every single one of those BRKs is followed by 2 bytes of data, and every single one of those second bytes ends in $7 or $F. So... in combination with your excellent observation about no 6502 opcode ending in $7 or $F (or $3 or $B, I now see), I'm thinking this is more about detecting BRK/NMI hijacking than anything to do with the mapper operations?

Thank you for your help too, abw!
No worries, I was just in a position where I could do a quick sanity check!

Disch

  • Hero Member
  • *****
  • Posts: 2744
  • NES Junkie
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #9 on: October 21, 2019, 01:40:28 pm »
Quote
more about detecting BRK/NMI hijacking than anything to do with the mapper operations?

Ah.  That could be it!

Although couldn't it just check the B flag on the stack?  Or is that not set for a hijack?

Dracula X

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
    • My YouTube Page for ROM hacking
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #10 on: October 21, 2019, 09:00:48 pm »
I'm actually finished converting the mapper, I just want to make sure that is the main bank swapping is in at $3cxxx or $7cxxx? I'll be testing the game out for glitches as well.
« Last Edit: October 21, 2019, 09:11:31 pm by Dracula X »
I do not do other games that have already been done.

abw

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #11 on: October 21, 2019, 09:22:49 pm »
Although couldn't it just check the B flag on the stack?  Or is that not set for a hijack?
I'm not sure - I've never had a reason to dig this deep into this area of the hardware details before! nesdev indicates that the hijack happens *after* the B flag on the stack gets set, but this code is definitely playing games with the stack; as a couple of examples, the IRQ handler pops P before jumping to functions (which appear to be shared with non-IRQ code) that end with RTS, or pulls P, does stuff that modifies it, then pushes it, which among other things would force B on the stack to be set and thus make it unreliable for NMI vs. BRK detection. I haven't caught the NMI handler doing that one yet, but I haven't traced through all the code it's capable of calling either.

I'm actually finished converting the mapper, I just want to make sure that is the main bank swapping is in at $3cxxx or $7cxxx? I'll be testing the game out for glitches as well.
In the original game, they are both the main bank swapping routine.

Disch

  • Hero Member
  • *****
  • Posts: 2744
  • NES Junkie
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #12 on: October 21, 2019, 10:01:06 pm »
Yeah the nesdev wiki suggests that the B flag is a reliable test, as a hijack only changes which vector the CPU jumps to.

Quote
but this code is definitely playing games with the stack; as a couple of examples, the IRQ handler pops P before jumping to functions (which appear to be shared with non-IRQ code) that end with RTS

AH!

This actually makes a bit more sense.

If the BRK handler is using non-interrupt code, that allows it to exit with an RTS instead of an RTI.  And the RTS will increment the PC after popping it off the stack (effectively skipping the extra data byte) -- as long as the status byte is popped manually.

That plus the popping and repushing of status makes this seem a lot more reasonable.

Dracula X

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
    • My YouTube Page for ROM hacking
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #13 on: October 21, 2019, 10:14:07 pm »
Quote
In the original game, they are both the main bank swapping routine.
Thanks!

I also fixed the bug that I ran into as well.
I do not do other games that have already been done.

abw

  • Sr. Member
  • ****
  • Posts: 298
    • View Profile
Re: Dragon Warrior III MMC5 Bankswitch Help
« Reply #14 on: October 22, 2019, 08:21:16 pm »
AH!

This actually makes a bit more sense.

If the BRK handler is using non-interrupt code, that allows it to exit with an RTS instead of an RTI.  And the RTS will increment the PC after popping it off the stack (effectively skipping the extra data byte) -- as long as the status byte is popped manually.

That plus the popping and repushing of status makes this seem a lot more reasonable.
It sounds like we've got plausible explanations for all the weird bits now, so I'm willing to call this case closed :D.