zx_asmtest

annotate test.asm @ 0:34ec0f897aa3

interrupt handler works
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 19 Jan 2016 03:25:08 +0200
parents
children f975431190f6
rev   line source
nuclear@0 1 org $8000
nuclear@0 2
nuclear@0 3 fb_addr equ $4000
nuclear@0 4 attr_addr equ $5800
nuclear@0 5
nuclear@0 6 prog_test:
nuclear@0 7 call setup_intr
nuclear@0 8
nuclear@0 9 ld a, 2
nuclear@0 10 out (254), a
nuclear@0 11
nuclear@0 12 drawloop:
nuclear@0 13 call clear_scr
nuclear@0 14 jp drawloop
nuclear@0 15
nuclear@0 16 clear_scr:
nuclear@0 17 ld a, $ff
nuclear@0 18 ld hl, fb_addr
nuclear@0 19 ld b, 192
nuclear@0 20 _LY: ld c, 32
nuclear@0 21 _LX: ld (hl), a
nuclear@0 22 inc hl
nuclear@0 23 dec c
nuclear@0 24 jr nz, _LX
nuclear@0 25 dec b
nuclear@0 26 jr nz, _LY
nuclear@0 27 ret
nuclear@0 28
nuclear@0 29 ; ------ setup interrupt handler ------
nuclear@0 30 ; ok this needs explaining or I will forget it later...
nuclear@0 31 ; in interrupt mode 2:
nuclear@0 32 ; - I register has the IVT base address (high byte for the jump)
nuclear@0 33 ; - data bus has the vector index (low byte for the jump)
nuclear@0 34 ; (1) IVT must be 256-byte aligned (addr: xx00h)
nuclear@0 35 ; also the IVT should not be in ULA-contended memory
nuclear@0 36 ; (2) IVT should be above 4000h
nuclear@0 37 ; also it would be a good idea to avoid putting the IVT somewhere which can be
nuclear@0 38 ; paged out on 128k models
nuclear@0 39 ; (3) IVT shouldn't extend beyond c000h (?)
nuclear@0 40 ; finally, and this is the awesome bit, the data bus of the spectrum is
nuclear@0 41 ; floating during the interrupt request... which leads us to
nuclear@0 42 ; (4) we must populate the entire IVT with the same interrupt address
nuclear@0 43 ; (5) we must use an interrupt address with identical low and high bytes
nuclear@0 44 ; (6) we need 257 bytes for the IVT
nuclear@0 45 ;
nuclear@0 46 ; with those facts in mind the code below:
nuclear@0 47 ; - uses BE00h to BF01h (inclusive) for the IVT
nuclear@0 48 ; - a trampoline jump opcode is placed at BDBDh to jump to intr
nuclear@0 49 ; - the address BDBDh is then populated throughout the IVT (bd, 257 times)
nuclear@0 50 ; -------------------------------------
nuclear@0 51
nuclear@0 52 ivt_addr equ $be00 ; c000 - 512 (we need 257 bytes headroom)
nuclear@0 53 intr_tramp_addr equ $bdbd
nuclear@0 54 jp_opcode equ $c3
nuclear@0 55
nuclear@0 56 setup_intr:
nuclear@0 57 di
nuclear@0 58 ld ix, ivt_addr
nuclear@0 59 push ix
nuclear@0 60 pop af ; a contains high byte of the ivt address
nuclear@0 61 ld i, a
nuclear@0 62 ld c, 0
nuclear@0 63 ld hl, intr_tramp_addr
nuclear@0 64 push hl
nuclear@0 65 pop af ; a contains high byte of the trampoline address
nuclear@0 66 _Livt: ld (ix), a
nuclear@0 67 inc ix
nuclear@0 68 dec c
nuclear@0 69 jr nz, _Livt
nuclear@0 70 ld (ix), a ; final odd high byte of the address
nuclear@0 71 ; at $bdbd setup the jump to our interrupt routine
nuclear@0 72 ld ix, $bdbd
nuclear@0 73 ld (ix), jp_opcode
nuclear@0 74 ld bc, intr
nuclear@0 75 ld (ix+1), c
nuclear@0 76 ld (ix+2), b
nuclear@0 77 ; done
nuclear@0 78 im 2
nuclear@0 79 ei
nuclear@0 80 ret
nuclear@0 81
nuclear@0 82 intr:
nuclear@0 83 push af
nuclear@0 84 ld a, (border)
nuclear@0 85 inc a
nuclear@0 86 out (254), a
nuclear@0 87 ld (border), a
nuclear@0 88 pop af
nuclear@0 89 ei
nuclear@0 90 reti
nuclear@0 91
nuclear@0 92 border defb 1
nuclear@0 93 nframe defw 0
nuclear@0 94
nuclear@0 95 end prog_test