ChaosCabbage / crazy-gameboy-video-experiments

Messing around with some video effects on the gameboy.
5 stars 1 forks source link

Playing with optimizations #2

Open slembcke opened 6 years ago

slembcke commented 6 years ago

More of a chat than an issue, but github doesn't really have such a feature. Anyway, I was playing with your code to get a feel for GB dev in a working project that does something non-trivial. Yours seemed like fun, so I started poking around at the interrupt code.

The first think I tried was simplifying the interrupt vectors: https://github.com/ChaosCabbage/crazy-gameboy-video-experiments/blob/9e71ff6c9dcd421364af7405718c5c2d87239413/src/interrupts.asm#L9

I figured out how to shorten the interrupt vector -> int_CallPointer -> interrupt function chain quite a bit like this:

int_InterruptRoutine: MACRO
    push hl ; Interrupt function responsible for popping.
    ld  hl, \1
    ld a, [hl+]
    ld h, [hl]
    ld l, a
    jp hl ; Tail call.
ENDM

That removes a call/ret pair and shortens the loading of the function pointer so it's small enough to fit directly into the interrupt vector area. It also preserves the hl register, but the interrupt function is responsible to pop it.

Having previously done some NES dev, I dug through a lot of the cc65 source, and they did something clever that could be applied as an alternative: https://github.com/cc65/cc65/blob/master/libsrc/runtime/jmpvec.s

Just a jump instruction placed in RAM so it can be patched. Jump to that, and then jump to your interrupt function. Not quite as clean without cc65's data segment feature though.

Anyway, thanks for sharing the code. It was fun to dig through. Feel free to close, ignore, or whatever this issue. :p

slembcke commented 6 years ago

Oops. I take that back. My routine also clobbers the A register. So I implemented the jump vector version because why not. Relevant parts look like this:

int_InterruptRoutine: MACRO
    jp \1 ; Jump to the jump vector. (ex: int_VBlankFunc)
    ENDM

int_VBlankFunc::
    DS 3 ; RAM function that just jumps to the actual function.
; ... etc

; Now sets the RAM function to a jp n16 instruction.
int_SetCallbackFunc: MACRO
    ld hl, \1
    ld a, $C3 ; jp n16
    ld [hl+], a
    ld a, low(\2)
    ld [hl+], a
    ld a, high(\2)
    ld [hl], a
    ENDM

Anyway, cheers!

ChaosCabbage commented 6 years ago

Oops, gotta watch those registers!

I remember struggling with how to do the interrupts, and ended up working back from how I might have done it in C. I'll admit I'm a complete beginner with assembly. Your suggestion looks good! I'll have to get back into writing this.

I'm glad you found the code interesting; wouldn't have expected it 😄 Cheers!