zx_asmtest

annotate test.asm @ 2:f975431190f6

moving ship
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 20 Jan 2016 07:13:20 +0200
parents 34ec0f897aa3
children 6da763b8592c
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@2 12 call clear_scr
nuclear@2 13
nuclear@0 14 drawloop:
nuclear@2 15 ld b, 0
nuclear@2 16 ld a, (py)
nuclear@2 17 ld c, a
nuclear@2 18 push bc
nuclear@2 19 ld a, (px)
nuclear@2 20 ld c, a
nuclear@2 21 push bc
nuclear@2 22 call erase_blk
nuclear@2 23 pop bc
nuclear@2 24 pop bc
nuclear@2 25
nuclear@2 26 ld hl, sprite
nuclear@2 27 push hl
nuclear@2 28 ld b, 0
nuclear@2 29 ld a, (ny)
nuclear@2 30 ld (py), a
nuclear@2 31 ld c, a
nuclear@2 32 push bc
nuclear@2 33 ld a, (nx)
nuclear@2 34 ld (px), a
nuclear@2 35 ld c, a
nuclear@2 36 push bc
nuclear@2 37 call draw_sprite
nuclear@2 38 pop bc
nuclear@2 39 pop bc
nuclear@2 40 pop bc
nuclear@2 41
nuclear@2 42 _endfrm:
nuclear@2 43 ld a, 2
nuclear@2 44 out (254), a
nuclear@2 45
nuclear@2 46 halt
nuclear@0 47 jp drawloop
nuclear@0 48
nuclear@2 49 px defb 16
nuclear@2 50 py defb 12
nuclear@2 51 nx defb 16
nuclear@2 52 ny defb 12
nuclear@2 53
nuclear@2 54 inp_left:
nuclear@2 55 ld a, (px)
nuclear@2 56 cp 0
nuclear@2 57 ret z
nuclear@2 58 dec a
nuclear@2 59 ld (nx), a
nuclear@2 60 ret
nuclear@2 61
nuclear@2 62 inp_right:
nuclear@2 63 ld a, (px)
nuclear@2 64 cp 31
nuclear@2 65 ret z
nuclear@2 66 inc a
nuclear@2 67 ld (nx), a
nuclear@2 68 ret
nuclear@2 69
nuclear@2 70 inp_up:
nuclear@2 71 ld a, (py)
nuclear@2 72 cp 0
nuclear@2 73 ret z
nuclear@2 74 dec a
nuclear@2 75 ld (ny), a
nuclear@2 76 ret
nuclear@2 77
nuclear@2 78 inp_down:
nuclear@2 79 ld a, (py)
nuclear@2 80 cp 23
nuclear@2 81 ret z
nuclear@2 82 inc a
nuclear@2 83 ld (ny), a
nuclear@2 84 ret
nuclear@2 85
nuclear@2 86 inp_fire: ; TODO
nuclear@2 87 ret
nuclear@2 88
nuclear@0 89 clear_scr:
nuclear@0 90 ld a, $ff
nuclear@0 91 ld hl, fb_addr
nuclear@0 92 ld b, 192
nuclear@2 93 _ly: ld c, 32
nuclear@2 94 _lx: ld (hl), a
nuclear@0 95 inc hl
nuclear@0 96 dec c
nuclear@2 97 jr nz, _lx
nuclear@0 98 dec b
nuclear@2 99 jr nz, _ly
nuclear@2 100 ret
nuclear@2 101
nuclear@2 102 erase_blk:
nuclear@2 103 ld ix, 2
nuclear@2 104 add ix, sp
nuclear@2 105 ld c, (ix)
nuclear@2 106 ld b, (ix + 2)
nuclear@2 107
nuclear@2 108 call calc_blk_addr
nuclear@2 109
nuclear@2 110 ld c, 8
nuclear@2 111 ld a, $ff
nuclear@2 112 _loop: ld (de), a
nuclear@2 113 inc d
nuclear@2 114 dec c
nuclear@2 115 jr nz, _loop
nuclear@2 116 ret
nuclear@2 117
nuclear@2 118
nuclear@2 119 draw_sprite:
nuclear@2 120 ld ix, 2
nuclear@2 121 add ix, sp ; skip ret addr
nuclear@2 122 ld c, (ix) ; c <- x
nuclear@2 123 ld b, (ix + 2) ; b <- y
nuclear@2 124 ld l, (ix + 4) ; hl <- sprite address
nuclear@2 125 ld h, (ix + 5)
nuclear@2 126
nuclear@2 127 call calc_blk_addr
nuclear@2 128
nuclear@2 129 ld c, 8
nuclear@2 130 _loop: ld a, (hl)
nuclear@2 131 ld (de), a
nuclear@2 132 inc hl
nuclear@2 133 inc d
nuclear@2 134 dec c
nuclear@2 135 jr nz, _loop
nuclear@2 136 ret
nuclear@2 137
nuclear@2 138 ; expects X -> c, Y -> b, returns in de
nuclear@2 139 calc_blk_addr:
nuclear@2 140 push af
nuclear@2 141 sla b
nuclear@2 142 sla b ; change from blocks to pixels
nuclear@2 143 sla b
nuclear@2 144 ; construct low address byte -> e
nuclear@2 145 ld a, b ; start with Y
nuclear@2 146 sla a
nuclear@2 147 sla a
nuclear@2 148 and $e0 ; keep top 3 bits
nuclear@2 149 ld e, a ; move into e
nuclear@2 150 ld a, c ; a <- X
nuclear@2 151 and $1f ; keep low 5 bits
nuclear@2 152 or e ; combine with Y bits
nuclear@2 153 ld e, a ; move the result back to e
nuclear@2 154 ; construct high address byte -> d
nuclear@2 155 ld a, b ; start with Y again
nuclear@2 156 sra a
nuclear@2 157 sra a
nuclear@2 158 sra a
nuclear@2 159 and $18 ; keep bits 3 and 4
nuclear@2 160 ld d, a ; keep it in d
nuclear@2 161 ld a, b ; grap Y one more time
nuclear@2 162 and $7 ; keep low 3 bits of Y in a
nuclear@2 163 or d ; combine with Y6-Y7
nuclear@2 164 ld bc, fb_addr
nuclear@2 165 or b ; combine with high byte of fb address
nuclear@2 166 ld d, a ; move result back to d
nuclear@2 167 pop af
nuclear@2 168 ret
nuclear@2 169
nuclear@2 170
nuclear@2 171 ; port | keys
nuclear@2 172 ; ------+--------------------------
nuclear@2 173 ; 32766 | B, N, M, SymbShift, Space
nuclear@2 174 ; 64510 | T, R, E, W, Q
nuclear@2 175 ; 65022 | G, F, D, S, A
nuclear@2 176 scan_keys:
nuclear@2 177 ld bc, 65022 ; check ASD
nuclear@2 178 in a, (c)
nuclear@2 179 rra
nuclear@2 180 push af
nuclear@2 181 call nc, inp_left
nuclear@2 182 pop af
nuclear@2 183 rra
nuclear@2 184 push af
nuclear@2 185 call nc, inp_down
nuclear@2 186 pop af
nuclear@2 187 rra
nuclear@2 188 call nc, inp_right
nuclear@2 189
nuclear@2 190 ld bc, 64510 ; check W
nuclear@2 191 in a, (c)
nuclear@2 192 rra ; skip Q
nuclear@2 193 rra
nuclear@2 194 call nc, inp_up
nuclear@2 195
nuclear@2 196 ld bc, 32766 ; check space
nuclear@2 197 in a, (c)
nuclear@2 198 rra
nuclear@2 199 call nc, inp_fire
nuclear@0 200 ret
nuclear@0 201
nuclear@0 202 ; ------ setup interrupt handler ------
nuclear@0 203 ; ok this needs explaining or I will forget it later...
nuclear@0 204 ; in interrupt mode 2:
nuclear@0 205 ; - I register has the IVT base address (high byte for the jump)
nuclear@0 206 ; - data bus has the vector index (low byte for the jump)
nuclear@0 207 ; (1) IVT must be 256-byte aligned (addr: xx00h)
nuclear@0 208 ; also the IVT should not be in ULA-contended memory
nuclear@2 209 ; (2) IVT should be above 8000h
nuclear@0 210 ; also it would be a good idea to avoid putting the IVT somewhere which can be
nuclear@0 211 ; paged out on 128k models
nuclear@0 212 ; (3) IVT shouldn't extend beyond c000h (?)
nuclear@2 213 ; finally, and this is the awesome bit, the data bus of the spectrum contains
nuclear@2 214 ; garbage during the interrupt request... which leads us to
nuclear@0 215 ; (4) we must populate the entire IVT with the same interrupt address
nuclear@0 216 ; (5) we must use an interrupt address with identical low and high bytes
nuclear@0 217 ; (6) we need 257 bytes for the IVT
nuclear@0 218 ;
nuclear@0 219 ; with those facts in mind the code below:
nuclear@0 220 ; - uses BE00h to BF01h (inclusive) for the IVT
nuclear@0 221 ; - a trampoline jump opcode is placed at BDBDh to jump to intr
nuclear@0 222 ; - the address BDBDh is then populated throughout the IVT (bd, 257 times)
nuclear@0 223 ; -------------------------------------
nuclear@0 224
nuclear@0 225 ivt_addr equ $be00 ; c000 - 512 (we need 257 bytes headroom)
nuclear@0 226 intr_tramp_addr equ $bdbd
nuclear@0 227 jp_opcode equ $c3
nuclear@0 228
nuclear@0 229 setup_intr:
nuclear@0 230 di
nuclear@0 231 ld ix, ivt_addr
nuclear@0 232 push ix
nuclear@0 233 pop af ; a contains high byte of the ivt address
nuclear@0 234 ld i, a
nuclear@0 235 ld c, 0
nuclear@0 236 ld hl, intr_tramp_addr
nuclear@0 237 push hl
nuclear@0 238 pop af ; a contains high byte of the trampoline address
nuclear@2 239 _livt: ld (ix), a
nuclear@0 240 inc ix
nuclear@0 241 dec c
nuclear@2 242 jr nz, _livt
nuclear@0 243 ld (ix), a ; final odd high byte of the address
nuclear@0 244 ; at $bdbd setup the jump to our interrupt routine
nuclear@0 245 ld ix, $bdbd
nuclear@0 246 ld (ix), jp_opcode
nuclear@0 247 ld bc, intr
nuclear@0 248 ld (ix+1), c
nuclear@0 249 ld (ix+2), b
nuclear@0 250 ; done
nuclear@0 251 im 2
nuclear@0 252 ei
nuclear@0 253 ret
nuclear@0 254
nuclear@0 255 intr:
nuclear@2 256 exx
nuclear@2 257 ex af, af'
nuclear@2 258
nuclear@2 259 ld a, 1
nuclear@0 260 out (254), a
nuclear@2 261
nuclear@2 262 call scan_keys
nuclear@2 263 ex af, af'
nuclear@2 264 exx
nuclear@0 265 ei
nuclear@0 266 reti
nuclear@0 267
nuclear@0 268 border defb 1
nuclear@0 269 nframe defw 0
nuclear@0 270
nuclear@2 271 sprite defb %11100111
nuclear@2 272 defb %10000001
nuclear@2 273 defb %11000011
nuclear@2 274 defb %10000001
nuclear@2 275 defb %00000000
nuclear@2 276 defb %00011000
nuclear@2 277 defb %00111100
nuclear@2 278 defb %01111110
nuclear@2 279
nuclear@0 280 end prog_test