Friday, January 1, 2010

Crash Boom Bang!

Ever tried disrupting the last droid on ship to smithereens and entering lift when the explosion was still going on? Not? Good. That would have crashed the game right there. Very annoying, especially if you had just quadrupled your all time high score...

What are the changes of someone completing a ship and entering lift before deck is shut down? I don't know, but I managed to do so! Then I reproduced it on purpose to make sure there is a bug. Now I have to hunt it down.

Edit: Found it! It's the same bug which causes "pacifist takeover" (not shooting any droids - except with disruptor!) crash randomly at the same point. In Time is of the Essence I gave you the code for play are top split. In Irq_118() I use this to stabilize raster regardless of how many sprites are over the split:

lda $dc04 ; [1,15] ([2,15] if NTSC/Drean)
eor #$0f ; [14,0] ([13,0])
sta .j3+1
.j3 bpl *+2 ; jump into the delay code
; entering at offset 0 delays 16 cycles,
; entering at offset 14 delays 2 cycles
; OP_CMP_IMM is opcode for CMP #immediate (2 cycles),
; OP_CMP_ZP is opcode for COM $zeropage (3 cycles)
cmp #OP_CMP_ZP

Guess what happens if CIA timer underflows before the interrupt code is executed? It will jump randomly forward and CPU ends in la-la land. Unfortunately there is some code which needs to be run with interrupts disabled, and if top split is delayed because of it... BOOM!

The solution? I can use software semaphore to protect shared resources and avoif disabling interrupts. Nice and clean solution, but why should I do that when I can kludge around the problem by waiting for raster position after the split before disabling IRQ... "bit $d012; bpl *-3; sei" fixes the bug.