base:stable_raster_routine
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | base:stable_raster_routine [2015-04-17 04:34] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ======= STABLE RASTER ROUTINE ======= | ||
+ | A Raster Stabbing routine using the double IRQ principle. Insert this code after you have pushed your registers onto the stack inside your IRQ code. The routine doesen' | ||
+ | |||
+ | Other Interrupts, $d012 = #$ff, Sprites, Badline and Badline-1 = fuckup. | ||
+ | |||
+ | If you have the KERNAL banked in, you need to modify the IRQ-Vectors. | ||
+ | |||
+ | |||
+ | Kickassembler format | ||
+ | |||
+ | < | ||
+ | // | ||
+ | // Raster Stabilizing Code | ||
+ | // | ||
+ | // A Raster Compare IRQ is triggered on cycle 0 on the current $d012 line | ||
+ | // The MPU needs to finish it's current OP code before starting the Interrupt Handler, | ||
+ | // meaning a 0 -> 7 cycles delay depending on OP code. | ||
+ | // Then a 7 cycle delay is spendt invoking the Interrupt Handler (Push SR/PC to stack++) | ||
+ | // Then 13 cycles for storing registers (pha, txa, pha, tya, pha) | ||
+ | |||
+ | // CYCLECOUNT: [20 -> 27] cycles after Raster IRQ occurred. | ||
+ | |||
+ | // Set up Wedge IRQ vector | ||
+ | lda #< | ||
+ | sta $fffe | ||
+ | lda #> | ||
+ | sta $ffff | ||
+ | |||
+ | // Set the Raster IRQ to trigger on the next Raster line | ||
+ | inc $d012 | ||
+ | |||
+ | // Acknowlege current Raster IRQ | ||
+ | lda #$01 | ||
+ | sta $d019 | ||
+ | |||
+ | // Store current Stack Pointer (will be messed up when the next IRQ occurs) | ||
+ | tsx | ||
+ | |||
+ | // Allow IRQ to happen (Remeber the Interupt flag is set by the Interrupt Handler). | ||
+ | cli | ||
+ | |||
+ | // Execute NOPs untill the raster line changes and the Raster IRQ triggers | ||
+ | NOP | ||
+ | NOP | ||
+ | NOP | ||
+ | NOP | ||
+ | NOP | ||
+ | NOP | ||
+ | NOP | ||
+ | NOP | ||
+ | // Add one extra nop for 65 cycle NTSC machines | ||
+ | |||
+ | // CYCLECOUNT: [64 -> 71] | ||
+ | |||
+ | WedgeIRQ: | ||
+ | // At this point the next Raster Compare IRQ has triggered and the jitter is max 1 cycle. | ||
+ | // CYCLECOUNT: [7 -> 8] (7 cycles for the interrupt handler + [0 -> 1] cycle Jitter for the NOP) | ||
+ | |||
+ | // Restore previous Stack Pointer (ignore the last Stack Manipulation by the IRQ) | ||
+ | txs | ||
+ | |||
+ | // PAL-63 | ||
+ | // | ||
+ | ldx #$08 // ldx #$08 // ldx #$09 | ||
+ | dex // dex // dex | ||
+ | bne *-1 // bne *-1 // bne *-1 | ||
+ | bit $00 // nop | ||
+ | // nop | ||
+ | |||
+ | // Check if $d012 is incremented and rectify with an aditional cycle if neccessary | ||
+ | lda $d012 | ||
+ | cmp $d012 // <- critical instruction (ZERO-Flag will indicate if Jitter = 0 or 1) | ||
+ | |||
+ | // CYCLECOUNT: [61 -> 62] <- Will not work if this timing is wrong | ||
+ | |||
+ | // cmp $d012 is originally a 5 cycle instruction but due to piplining tech. the | ||
+ | // 5th cycle responsible for calculating the result is executed simultaniously | ||
+ | // with the next OP fetch cycle (first cycle of beq *+2). | ||
+ | |||
+ | // Add one cycle if $d012 wasn't incremented (Jitter / ZERO-Flag = 0) | ||
+ | beq *+2 | ||
+ | |||
+ | // Stable code | ||
+ | | ||
+ | </ | ||
+ | |||
+ | Don't forget to set up the next IRQ-Vector before exiting the IRQ. | ||
+ | |||
+ | If you want to make it more simple, you could store this as a pseudo or macro (STABILIZE) and just: | ||
+ | |||
+ | < | ||
+ | IRQ_Begin: | ||
+ | pha | ||
+ | txa | ||
+ | pha | ||
+ | tya | ||
+ | pha | ||
+ | :STABILIZE | ||
+ | | ||
+ | // | ||
+ | | ||
+ | lda #< | ||
+ | sta $fffe | ||
+ | lda #> | ||
+ | sta $ffff | ||
+ | lda #$01 | ||
+ | sta $d019 | ||
+ | pla | ||
+ | tay | ||
+ | pla | ||
+ | tax | ||
+ | pla | ||
+ | rti | ||
+ | |||
+ | </ | ||
+ | |||
+ | TWW/ |
base/stable_raster_routine.txt · Last modified: 2015-04-17 04:34 by 127.0.0.1