Help with fceux again....
Moderator: Moderators
Re: Help with fceux again....
I don't know why you can't reproduce any of your crashes in Mesen, because your game crashed for me in Mesen when I tried. But I keep suggesting to please enable all of the developer options in the top half of that Emulation menu. Specifically, set "Default power on state for RAM" to "Random Values" and check every option from "Randomize power-on state for mappers" to "Enable PAL black borders (when running in PAL/Dendy mode)". This will help you find problems. Some of these options are more strict than real hardware, but if your game works with the option enabled, it should work on hardware, too.
Your Mesen build is also 6 months old, so you might want to consider downloading a new build, which should have improvements. Mesen gets frequent updates, so it's worth getting new versions.
Your Mesen build is also 6 months old, so you might want to consider downloading a new build, which should have improvements. Mesen gets frequent updates, so it's worth getting new versions.
Re: Help with fceux again....
kk thx for the tip
Finally , for you guys, SAFE NMI's :D
IT did fixed alot of small glitches, I do think its crashing less. Ty all for your insight. Was not Easy to do since I have alot of separated nmi's and jumps oustide and inside back, some RTI as well. I had to restore the registers at different places for all the transitions to work perfectly.
Looks like this now:
Some restore registers are not there, there are somewhere else. Irrelevant to post here. Any how, enjoy this version , should crash much much more lesss. Actually I've just reached ten times in a row the village with fceux without crashing.
Please let me know
again, thank you all for your insights
Looks like this now:
Some restore registers are not there, there are somewhere else. Irrelevant to post here. Any how, enjoy this version , should crash much much more lesss. Actually I've just reached ten times in a row the village with fceux without crashing.
Please let me know



Code: Select all
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NMI:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Backup A, X, Y registers
PHA ; Push A to the stack
TXA ; Transfer X to A
PHA ; Push X (now in A) to the stack
TYA ; Transfer Y to A
PHA ; Push Y (now in A) to the stack
SwitchBank #%11000111,#11
LDA #$01
STA XNMI_ACTIVE_FLAG
;Disable sound IRQ (set the corresponding bit)
LDA #%11000000
STA APU_PAD2
LDA XNMI_LEVEL
CMP #$01
BEQ NMI_LEVEL1
LDA XNMI_LEVEL
CMP #$02
BNE :+
JMP NMI_LEVEL2_RESET
:
LDA XNMI_LEVEL
CMP #$03
BNE :+
JMP NMI_VILLAGE_RESET
:
LDA XNMI_LEVEL
CMP #$FF
BNE :+
JMP NMI_OVERWORLD_RESET
:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NMI_RESET_LEVEL1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INC frame_counter ; Increment the frame counter
INC sound_frame_counter ; Increment the counter every NMI
INC RANDOM_SEED
INC MUSIC_COUNTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
JSR DCPM_SAFETY_QUADREAD_P1
JSR CHECK_CONTROLLER_STARTUP
JSR LEVEL_CHECK_NMI ; Jump to LEVEL_CHECK_NMI subroutine,
LDA XLEVEL ; Load the value of XLVL into the accumulator
CMP #$01 ; Compare XCHAPTER with 1
BEQ JUMP_LEVEL1_BABY ; If XCHAPTER == 1, branch to ISSUE_BREAK
;Set up sprite DMA transfer
LDA #$02
STA APU_SPR_DMA
PLA ; Pull Y from the stack
TAY ; Restore Y
PLA ; Pull X from the stack
TAX ; Restore X
PLA ; Pull A from the stack
RTI
JUMP_LEVEL1_BABY:
JMP RESET_LEVEL1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NMI_LEVEL1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INC frame_counter ; Increment the frame counter
INC sound_frame_counter ; Increment the counter every NMI
INC RANDOM_SEED
INC MUSIC_COUNTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDA TEXTBOX_CLEAR_FLAG
CMP #$01
BNE :+
JSR WRITE_LINE_CLEAR
LDA #$00
STA TEXTBOX_CLEAR_FLAG
:
JSR ENNEMY3_ROUTINES ; the main textbox for this guy
;Set up sprite DMA transfer
LDA #$02
STA APU_SPR_DMA
PHA
JSR GRASS_N_ROCK_DOOR
PLA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
JSR HEARTS_CHECK ; MUST BE RUN BEFORE textbox in case p1 loose a heart while reading one.
LDA TEXTBOX_ACTIVATED
CMP #1
BNE :+ ; If TEXTBOX_ACTIVATED ≠ 1, skip execution
JSR LOAD_INSTRUCTION_TEXTBOX ; the instruction textbox at the begining
JSR LOAD_SECRET_TEXTBOX ; the secret message
:
JSR CHECK_GRAVITY_ENNEMY1
JSR CHECK_GRAVITY_SWORD
JSR SPRITES_SWITCHBANK_R4
JSR TAKE_FEATHER_P1 ;waiting to be picked up , textbox also
JSR TAKE_SWORD_P1
JSR get_sprite0_attributes
JSR UPDATE_OAM_SPRITE0
LDX #00
STX temp
JSR OFFSET_BACKGROUND_HORIZONTAL ; sprite 0 hit.
JSR SCROLL
JSR GRAVITY
JSR CHECK_SWORD_DIRECTION
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
JSR ORDER121 ; super jump
JSR CHECK_RANDOM_MOVE_ENNEMY1
JSR JUMP_CHECK
JSR DCPM_SAFETY_QUADREAD_P1
JSR CONTROLLERS
JSR CHECK_USE_BUTTON
JSR MOVE_ENNEMY3
JSR MOVE_ENNEMY2
JSR SPRITE_ENNEMY2
JSR UPDATE_DELAY_TEXTBOX
;metasprites for various objects
JSR METASPRITES
;OAM CLEAR + SLOT SHUFFLE
JSR OAM
;update for the delay between letters and phrases when reading a textbox
LDA #$00
STA XNMI_ACTIVE_FLAG
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Restore A, X, Y registers
PLA ; Pull Y from the stack
TAY ; Restore Y
PLA ; Pull X from the stack
TAX ; Restore X
PLA ; Pull A from the stack
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RTI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NMI_LEVEL2_RESET:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDA XLEVEL ; Load the value of XLVL into the accumulator
CMP #$02 ; Compare XLEVEL
BEQ NMI_LEVEL2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INC frame_counter ; Increment the frame counter
INC sound_frame_counter ; Increment the counter every NMI
INC RANDOM_SEED
INC MUSIC_COUNTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set Control Register PPU_MASK, the ppu mask register
LDA #%00001110 ; Enable background rendering (Bit 3 set) ; ENABLE sprite rendering (Bit 4 cleared)
STA PPU_MASK ; Write to PPU Mask Register PPU_MASK ; Enable full screen (Bits 1 and 2 set)
JSR DCPM_SAFETY_QUADREAD_P1
JSR CHECK_CONTROLLER_STARTUP
JSR LEVEL_CHECK_NMI
LDA XLEVEL ; Load the value of XLVL into the accumulator
CMP #$02 ; Compare XLEVEL
BEQ JUMP_LEVEL2_BABY ; If XCHAPTER == 1, branch to ISSUE_BREAK
PLA ; Pull Y from the stack
TAY ; Restore Y
PLA ; Pull X from the stack
TAX ; Restore X
PLA ; Pull A from the stack
RTI
JUMP_LEVEL2_BABY:
JMP RESET_LEVEL2
;;;;;;;;;;;;;;;;;;;
NMI_LEVEL2:
;;;;;;;;;;;;;;;;;
JSR HEARTS_CHECK ; MUST BE RUN BEFORE textbox in case p1 loose a heart while reading one.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INC frame_counter ; Increment the frame counter
INC sound_frame_counter ; Increment the counter every NMI
INC RANDOM_SEED
INC MUSIC_COUNTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Set up sprite DMA transfer
LDA #$02
STA APU_SPR_DMA
; kill all ennemy 4 to open door
JSR SPRITES_SWITCHBANK_R4
JSR CHECK_VOLCANO_DOOR
JSR CHECK_GRAVITY_ENNEMY1
JSR CHECK_GRAVITY_SWORD
JSR CHECK_USE_BUTTON
PHA
JSR get_sprite0_attributes
JSR UPDATE_OAM_SPRITE0
PLA
LDA XCHAPTER
CMP #$07 ;level 2 cave
BEQ :+
LDX SHADOW_8000+1 ;the bank we are currently using in the level at r0
STX temp
JSR OFFSET_BACKGROUND_HORIZONTAL ; sprite 0 hit.
:
JSR SCROLL
JSR GRAVITY
JSR CHECK_SWORD_DIRECTION
JSR ORDER121 ; super jump
JSR CHECK_RANDOM_MOVE_ENNEMY1
JSR JUMP_CHECK
JSR DCPM_SAFETY_QUADREAD_P1
JSR CONTROLLERS
JSR ENNEMY4_ROUTINES
JSR ROUTINE_TELEPORTER
JSR ROUTINE_FLAMME_BOSS
JSR CALL_MOVE_DOWN
;metasprites for various objects
JSR METASPRITES
;OAM CLEAR + SLOT SHUFFLE
JSR OAM
LDA #$00
STA XNMI_ACTIVE_FLAG
; Restore A, X, Y registers
PLA ; Restore Y
TAY
PLA ; Restore X
TAX
PLA ; Restore A
;;;;;;;;;;;;;
RTI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NMI_OVERWORLD_RESET:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDA XLEVEL ; Load the value of XLVL into the accumulator
CMP #$FF ; Compare XLEVEL
BEQ NMI_OVERWORLD
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INC frame_counter ; Increment the frame counter
INC sound_frame_counter ; Increment the counter every NMI
INC RANDOM_SEED
INC MUSIC_COUNTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set Control Register PPU_MASK, the ppu mask register
LDA #%00001110 ; Enable background rendering (Bit 3 set) ; ENABLE sprite rendering (Bit 4 cleared)
STA PPU_MASK ; Write to PPU Mask Register PPU_MASK ; Enable full screen (Bits 1 and 2 set)
JSR DCPM_SAFETY_QUADREAD_P1
JSR CHECK_CONTROLLER_STARTUP
JSR LEVEL_CHECK_NMI
LDA XLEVEL ; Load the value of XLVL into the accumulator
CMP #$FF ; Compare XLEVEL
BEQ JUMP_OVERWORLD_BABY ; If XCHAPTER == 1, branch to ISSUE_BREAK
PLA ; Restore Y
TAY
PLA ; Restore X
TAX
PLA ; Restore A
RTI
JUMP_OVERWORLD_BABY:
JMP RESET_OVERWORLD
;;;;;;;;;;;;;;;;;;
NMI_OVERWORLD:
;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INC frame_counter ; Increment the frame counter
INC sound_frame_counter ; Increment the counter every NMI
INC RANDOM_SEED
INC MUSIC_COUNTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
JSR CALL_CHECK_TILE_INDEX ;live fetch the tile indexes around p1
; Set initial scroll to 0 for the static status bar
LDA #$00
STA PPU_SCROLL ; Horizontal scroll
STA PPU_SCROLL ; Vertical scroll
LDA #$02
STA APU_SPR_DMA
JSR SPRITES_SWITCHBANK_R4
JSR CHECK_USE_BUTTON_OVERWORLD
PHA
JSR get_sprite0_attributes
JSR UPDATE_OAM_SPRITE0
PLA
JSR DCPM_SAFETY_QUADREAD_P1
JSR CONTROLLERS
JSR METASPRITES
;OAM CLEAR + SLOT SHUFFLE
JSR OAM
PLA ; Pull Y
TAY
PLA ; Pull X
TAX
PLA
RTI
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NMI_VILLAGE_RESET:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDA XLEVEL ; Load the value of XLVL into the accumulator
CMP #$03 ; Compare XLEVEL
BEQ NMI_VILLAGE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INC frame_counter ; Increment the frame counter
INC sound_frame_counter ; Increment the counter every NMI
INC RANDOM_SEED
INC MUSIC_COUNTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set Control Register PPU_MASK, the ppu mask register
LDA #%00001110 ; Enable background rendering (Bit 3 set) ; ENABLE sprite rendering (Bit 4 cleared)
STA PPU_MASK ; Write to PPU Mask Register PPU_MASK ; Enable full screen (Bits 1 and 2 set)
JSR DCPM_SAFETY_QUADREAD_P1
JSR CHECK_CONTROLLER_STARTUP
JSR LEVEL_CHECK_NMI
LDA XLEVEL ; Load the value of XLVL into the accumulator
CMP #03 ; Compare XLEVEL
BEQ JUMP_VILLAGE_BABY ; If XCHAPTER == 1, branch to ISSUE_BREAK
PLA ; Pull Y
TAY
PLA ; Pull X
TAX
PLA
RTI
JUMP_VILLAGE_BABY:
JMP RESET_VILLAGE
;;;;;;;;;;;;;;;;;;
NMI_VILLAGE:
;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INC frame_counter ; Increment the frame counter
INC sound_frame_counter ; Increment the counter every NMI
INC RANDOM_SEED
INC MUSIC_COUNTER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
JSR CALL_CHECK_TILE_INDEX ;live fetch the tile indexes around p1
; Set initial scroll to 0 for the static status bar
LDA #$00
STA PPU_SCROLL ; Horizontal scroll
STA PPU_SCROLL ; Vertical scroll
LDA #$02
STA APU_SPR_DMA
JSR SPRITES_SWITCHBANK_R4
JSR CHECK_USE_BUTTON_OVERWORLD
PHA
JSR get_sprite0_attributes
JSR UPDATE_OAM_SPRITE0
PLA
JSR DCPM_SAFETY_QUADREAD_P1
JSR CONTROLLERS
JSR routines_TOWNER
JSR METASPRITES
;OAM CLEAR + SLOT SHUFFLE
JSR OAM
PLA ; Pull Y
TAY
PLA ; Pull X
TAX
PLA
RTI
;;;;;;;;;;;;;;;;;;;;
IRQ:
;;;;;;;;;;;;;;;;;;;;
; Save registers
PHA
TXA
PHA
TYA
PHA
JSR RANDOM_GENERATOR
LDA XLEVEL ; Load the value of XLVL into the accumulator
CMP #$01 ; Compare XCHAPTER with 1
BEQ IRQ_LEVEL1
CMP #$02
BEQ IRQ_LEVEL2
CMP #$03
BEQ IRQ_LEVEL3
CMP #$FF
BEQ IRQ_LEVEL3
JMP IRQ_END
IRQ_LEVEL1:
IRQ_LEVEL2:
IRQ_LEVEL3:
JSR CalculatePPUAddress
JSR CHECK_BORDER_COLLISION_P1
JSR COL_detector_bottom
JSR COL_detector_top
JSR COL_detector_left
JSR COL_detector_right
INC variable_X
IRQ_END:
; Handle the IRQ logic here (e.g., scroll split, sprite updates)
lda #$80
sta $E000 ; Acknowledge IRQ
lda #$80
sta $E001 ; Re-enable IRQs
; Restore registers
PLA
TAY
PLA
TAX
PLA
RTI
Re: Finally , for you guys, SAFE NMI's :D
Code: Select all
;Disable sound IRQ (set the corresponding bit)
LDA #%11000000
STA APU_PAD2
Code: Select all
LDA XNMI_LEVEL
CMP #$01
BEQ NMI_LEVEL1
LDA XNMI_LEVEL
CMP #$02
BNE :+
JMP NMI_LEVEL2_RESET
:
LDA XNMI_LEVEL
CMP #$03
BNE :+
JMP NMI_VILLAGE_RESET
:
LDA XNMI_LEVEL
CMP #$FF
BNE :+
JMP NMI_OVERWORLD_RESET
An indirect jump (like JMP (xxxx)) would be faster than doing many comparisons, but if an indirect jump is done improperly or done with corrupted memory, it can crash the program.
All tasks that involve the PPU (including sprite DMA and scrolling) should happen before any controller or sound code is run. PPU tasks are subject to a strict time limit, and controller and sound code is not.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: Finally , for you guys, SAFE NMI's :D
If you're just blindly jumping into a pointer, things could certainly go poorly if you forget to initialize it, but if you initialize it on-demand from a table then it should be safer. There's also the option of (ab)using the stack (i.e. pushing the desired adjusted NMI address onto the stack and then performing RTS). Either way should also be faster than checking them sequentially, and since NMI time is extremely precious, you don't want to waste it by performing a linear "if level 1, elseif level 2, elseif level 3, elseif level 4, etc." (since the last level will end up getting less time).
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.
P.S. If you don't get this note, let me know and I'll write you another.
Re: Finally , for you guys, SAFE NMI's :D
kk will sleep on that . ty again .
you can feel the difference in stability thou ?
you can feel the difference in stability thou ?
Re: Finally , for you guys, SAFE NMI's :D
i like youre idea of (absuing) the stack and going straight to the desired level .
i would need to tell the stack how ? and when , like at the end of every nmi ?
i would need to tell the stack how ? and when , like at the end of every nmi ?
Re: Help with fceux again....
We got requests to merge some of these threads together, so I've done so. I apologize for the inconvenience, but keeping very similar or same-topic discussion in fewer threads is really preferred. (For what it's worth, people said that they appreciate your enthusiasm. :) )
I'm glad the code is more stable now; it certainly looks like it should be more reliable now with the changes you've made.
I'm glad the code is more stable now; it certainly looks like it should be more reliable now with the changes you've made.
Finally a safe NMI !
dont wory be happy. will probably be the last . Fceux looks safe now. The whole thing was my OMA and the way i was doing my register. Now it looks sharp.
Re: Finally , for you guys, SAFE NMI's :D
Would not recommend using stack for an indirect jump, it takes more instructions than just a single indirect jump.
Code would look something like this:
ldx index
lda jumpTableLow,X ;address stored in the jump table must have 1 subtracted to use an RTS trick
pha
lda jumpTableHigh,X
pha
rts
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: Finally , for you guys, SAFE NMI's :D
Not only it does take the same # of instructions, but it is shorter, and has the advantage to not require temporary memory locations as they are automatically allocated on the stack.Dwedit wrote: ↑Wed Apr 16, 2025 2:40 pm Would not recommend using stack for an indirect jump, it takes more instructions than just a single indirect jump.
Code would look something like this:
ldx index
lda jumpTableLow,X ;address stored in the jump table must have 1 subtracted to use an RTS trick
pha
lda jumpTableHigh,X
pha
rts
"Standard" solution, assuming the Temp variable is in ZP.
Code: Select all
; SIZE TIME
ldx index ; 2 3
lda jumpTableLow, X ; 3 4+
sta Temp ; 2 3
lda JumpTableHigh, X ; 3 4+
sta Temp+1 ; 2 3
jmp [Temp] ; 3 5
; TOTAL 15 26+
Code: Select all
; SIZE TIME
ldx index ; 2 3
lda jumpTableLow, X ; 3 4+
pha ; 1 3
lda JumpTableHigh, X ; 3 4+
pha ; 1 3
rts ; 1 6
; TOTAL 11 27+
Totally agree, it's better to have the various topics about the development of "The Huns" merged, and I absolutely love the OP's enthusiasm, while mine went off along the years...We got requests to merge some of these threads together, so I've done so. I apologize for the inconvenience, but keeping very similar or same-topic discussion in fewer threads is really preferred. (For what it's worth, people said that they appreciate your enthusiasm.)

Last edited by Bregalad on Thu Apr 17, 2025 1:56 am, edited 1 time in total.
Useless, lumbering half-wits don't scare us.
Re: Help with fceux again....
I was referring to an single indirect jump instruction to an address that was already calculated, not one that's being generated during NMI time.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Re: Help with fceux again....
OK, I get it, no point to fetch the pointer every frame.
You can also have three RAM slots with "$4C $xx $xx" and modify the adress directly, then JSR there. This should be even more straightforward than an in direct JMP.
Useless, lumbering half-wits don't scare us.
Re: Help with fceux again....
So instead of using straight comparison like I do at the begnining of the nmi,
I use a table containing the adresses of the needed nmi ? The way im building thing , im gunna go from nmi to nmi, depending which location in the game I am. I think I will have no choice to when I have to much nmi. I'm almost there ( 128 i believe is the distance for the way im doing it ).
Now Its hard to calculate the address. I usually use jmp. Except for the ram, its easy to know what address. But for a specific point in my nmi, eeeew.
thats gunna be hard.
I use a table containing the adresses of the needed nmi ? The way im building thing , im gunna go from nmi to nmi, depending which location in the game I am. I think I will have no choice to when I have to much nmi. I'm almost there ( 128 i believe is the distance for the way im doing it ).
Now Its hard to calculate the address. I usually use jmp. Except for the ram, its easy to know what address. But for a specific point in my nmi, eeeew.
thats gunna be hard.
Re: Help with fceux again....
I don't know why you need so many different NMI handlers, most games are able to function with a unified handler.
But if you really feel like multiple NMIs is the way to go, you can just have a 16-bit variable in RAM hold the address of the current NMI handler, and then at the very beginning of the NMI you do an indirect jump to that address: jmp (NMIHandler)
You can change that address whenever you reach an area that requires a new handler (there's no need to set the address every frame if nothing is overwriting it):
Just be careful to not let an NMI fire between updating the lower byte and the upper byte, because the address will be invalid and the program will most likely crash. You can guarantee that no NMI will fire either by disabling NMIs altogether while changing the address, or changing it shortly after an NMI fires.
But if you really feel like multiple NMIs is the way to go, you can just have a 16-bit variable in RAM hold the address of the current NMI handler, and then at the very beginning of the NMI you do an indirect jump to that address: jmp (NMIHandler)
You can change that address whenever you reach an area that requires a new handler (there's no need to set the address every frame if nothing is overwriting it):
Code: Select all
lda #<NMIHandler87
sta NmiHandler+0
lda #>NMIHandler87
sta NMIHandler+1