# HG changeset patch # User John Tsiombikas # Date 1453166708 -7200 # Node ID 34ec0f897aa34276f994085a335b4549a1678261 interrupt handler works diff -r 000000000000 -r 34ec0f897aa3 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Tue Jan 19 03:25:08 2016 +0200 @@ -0,0 +1,10 @@ +tap = test.tap + +ASFLAGS = --alocal + +$(tap): test.asm + pasmo $(ASFLAGS) --tapbas $< $@ + +.PHONY: run +run: $(tap) + fuse-sdl $(tap) diff -r 000000000000 -r 34ec0f897aa3 test.asm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test.asm Tue Jan 19 03:25:08 2016 +0200 @@ -0,0 +1,95 @@ +org $8000 + +fb_addr equ $4000 +attr_addr equ $5800 + +prog_test: + call setup_intr + + ld a, 2 + out (254), a + +drawloop: + call clear_scr + jp drawloop + +clear_scr: + ld a, $ff + ld hl, fb_addr + ld b, 192 +_LY: ld c, 32 +_LX: ld (hl), a + inc hl + dec c + jr nz, _LX + dec b + jr nz, _LY + ret + +; ------ setup interrupt handler ------ +; ok this needs explaining or I will forget it later... +; in interrupt mode 2: +; - I register has the IVT base address (high byte for the jump) +; - data bus has the vector index (low byte for the jump) +; (1) IVT must be 256-byte aligned (addr: xx00h) +; also the IVT should not be in ULA-contended memory +; (2) IVT should be above 4000h +; also it would be a good idea to avoid putting the IVT somewhere which can be +; paged out on 128k models +; (3) IVT shouldn't extend beyond c000h (?) +; finally, and this is the awesome bit, the data bus of the spectrum is +; floating during the interrupt request... which leads us to +; (4) we must populate the entire IVT with the same interrupt address +; (5) we must use an interrupt address with identical low and high bytes +; (6) we need 257 bytes for the IVT +; +; with those facts in mind the code below: +; - uses BE00h to BF01h (inclusive) for the IVT +; - a trampoline jump opcode is placed at BDBDh to jump to intr +; - the address BDBDh is then populated throughout the IVT (bd, 257 times) +; ------------------------------------- + +ivt_addr equ $be00 ; c000 - 512 (we need 257 bytes headroom) +intr_tramp_addr equ $bdbd +jp_opcode equ $c3 + +setup_intr: + di + ld ix, ivt_addr + push ix + pop af ; a contains high byte of the ivt address + ld i, a + ld c, 0 + ld hl, intr_tramp_addr + push hl + pop af ; a contains high byte of the trampoline address +_Livt: ld (ix), a + inc ix + dec c + jr nz, _Livt + ld (ix), a ; final odd high byte of the address + ; at $bdbd setup the jump to our interrupt routine + ld ix, $bdbd + ld (ix), jp_opcode + ld bc, intr + ld (ix+1), c + ld (ix+2), b + ; done + im 2 + ei + ret + +intr: + push af + ld a, (border) + inc a + out (254), a + ld (border), a + pop af + ei + reti + +border defb 1 +nframe defw 0 + +end prog_test