This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

JumpEngine

JumpEngine
by on (#107378)
I'm running into some strange issues with my code.
I came across the following code in the SMB1 source:
Code:
JumpEngine:
       asl          ;shift bit from contents of A
       tay
       pla          ;pull saved return address from stack
       sta $04      ;save to indirect
       pla
       sta $05
       iny
       lda ($04),y  ;load pointer from indirect
       sta $06      ;note that if an RTS is performed in next routine
       iny          ;it will return to the execution before the sub
       lda ($04),y  ;that called this routine
       sta $07
       jmp ($06)    ;jump to the address we loaded


I have tried integrating it into my project. I want to use it as a
way to handle control flow. Here's what my source looks like in my
controller handler:

Code:
; when button a is pressed
   LDA #0 ; start with first routine
   JSR JumpEngine
   .dw TestSound1
   .dw TestSound2


The test sound routines simply play a c note in different ocatives.
The sound triggers, but here is what my stack looks like afterwards:

Image

It seems to be caught in an infinite loop. I'm not sure exactly how that
can be. I've written small demos using 6502 Macro Assembler. I've plugged
in the same code and it works fine.

I'm using asm6. Everything else is just a ported NerdyNights tutorial.
Is there any way to assess what went wrong?
Re: JumpEngine
by on (#107381)
This code has no way to find the address of the jump table, so it assumes you saved a 16-bit value at address 4 and 5. So if you want to use this code, you need to store the address of the jump table there.

Also, don't use explicitly numbered addresses for RAM addresses, use symbols for everything.
Re: JumpEngine
by on (#107382)
Dwedit wrote:
This code has no way to find the address of the jump table, so it assumes you saved a 16-bit value at address 4 and 5.

No it doesn't, it uses the return address as the address for the jump table, which is why the addresses are defined right after the JSR.
Re: JumpEngine
by on (#107383)
tokumaru wrote:
Dwedit wrote:
This code has no way to find the address of the jump table, so it assumes you saved a 16-bit value at address 4 and 5.

No it doesn't, it uses the return address as the address for the jump table, which is why the addresses are defined right after the JSR.


So why doesn't it work?
Re: JumpEngine
by on (#107384)
What do TestSound1 and 2 do? JumpEngine eats the first address on the stack to return to, so unless this routine itself was JSR'd to....
Re: JumpEngine
by on (#107385)
I didn't see any TSX in there, so I assumed it had no way to read the return address. Looks like I goofed.
Re: JumpEngine
by on (#107387)
lidnariq wrote:
What do TestSound1 and 2 do? JumpEngine eats the first address on the stack to return to, so unless this routine itself was JSR'd to....


I'm calling the JumpEngine routine from my control handler. It is run during NMI.
Is it possible that it isn't completing the jump before the next NMI is called?
And no, the code isn't JSR'd to, unless you consider the JSR to the control handler itself.

I've read about pushing the registers on the stack at the beginning of NMI and then pulling
them and restoring them before RTI. Would that be the culprit here?
Re: JumpEngine
by on (#107388)
johnnystarr wrote:
And no, the code isn't JSR'd to, unless you consider the JSR to the control handler itself.
That's probably the problem.

Your code should be something like
Code:
    JSR make_returnable
    whatever happens next

make_returnable:
    JSR JumpEngine
    .word Routine

Routine:
    blah
    RTS



Quote:
I've read about pushing the registers on the stack at the beginning of NMI and then pulling
them and restoring them before RTI. Would that be the culprit here?
Well, if you're not, and the non-NMI program does anything ever, you should add that anyway.

edit: had changed half of a label name without changing all of its instantations
Re: JumpEngine
by on (#107389)
Sounds like a good time to setup breakpoints and step through the code carefully.
Re: JumpEngine
by on (#107390)
The code effects a jump to an address selected from
a table that's inlined. the table is indexed by (the
contents of) a. You would presumably do something like
Code:
 lda index
 jsr SELECT_TARGET
 .
 .


SELECT_TARGET
 jsr JUMPENGINE
 target0
 target1
 target2
 etc,

if the targets return with rts

But the jsr JUMPENGINE is in effect just a jump through the table.
Re: JumpEngine
by on (#107393)
Yup, it was the registers alright. I imagine that A was being modified somewhere and the JumpEngine
was hoping off to who-knows-where.

I added the push/pulls to the NMI and everything works well.

I do need to breakpoint my code, but I haven't yet figured that out with my emulator.
Any suggestions on which emulator is best to debug?
Re: JumpEngine
by on (#107394)
Quote:
Any suggestions on which emulator is best to debug?


My vote: NintendulatorDX viewtopic.php?t=6773

Note: This requires you use ca65 for source-level debugging.
Re: JumpEngine
by on (#107422)
My vote: NESICIDE. Mostly because it functions as an IDE and debugger in one.

(Though I must confessed I haven't tried Nintendulator DX. Has anyone tried debugging in both of these long enough to provide a fair comparison? :)