Here is the code:
Interrupt: ;4242h
push bc
push de
push hl
push af
; interrupt stuff
;Note that I am using push/pop instead of the exx and ex af,af'
;instructions so that I can use shadow registers for other
;intensive routines
; Tasks to handle:
; Sound ?
; LCD refreshing, if a specific flag is set
; Key ports
call GetKey
ld hl,843Fh ;valid for the 83+/84+ calcs. This is where the OS stores its key values, too
ld (hl),a
inc l
cp (hl)
jr z,LoadSameKey
ld (hl),a
inc l
ld (hl),128
jp KeysUpdated
LoadSameKey:
inc l
dec (hl)
jr z,ReloadKey
xor a
jp KeysUpdated
ReloadKey:
ld (hl),32
KeysUpdated:
inc l
ld (hl),a ;key debounced
bit mapmode,(iy+textflags)
jr z,mapupdated
ld hl,8000h ;this is where I have an LUT to store the current sprite frames and timers
AnimUpdLoop:
dec (hl)
jr nz,NextAnimUpd
inc l
set drawmap,(iy+asmflags)
ld bc,Tiledata
ld e,(hl)
ld d,0 ;DE is the tile number
ex de,hl
add hl,hl
inc l
add hl,hl ;tile data is 4 bytes, .dw loc \ .db new \ .db time
add hl,bc
ld a,(hl)
ld (de),a
dec e
ld l,a
ld h,0
add hl,hl
inc l
add hl,hl
inc l
add hl,bc
ld a,(hl)
ld (de),a
ex de,hl
NextAnimUpd:
inc l
inc l
jr nz,AnimUpdLoop
MapUpdated:
bit forcedkey,(iy+asmflags)
jr z,EndInterrupt
;code for key macros
EndInterrupt:
bit drawmap,(iy+asmflags)
call nz,Tilemap
bit lcdupdate,(iy+asmflags)
call nz,UpdateLCD
ld a,8
out (3),a
ld a,10
out (3),a
ld a,15
out (3),a
pop af
pop hl
pop de
pop bc
ei
ret
TileMap:
res lcdupdate,(iy+asmflags)
ld hl,(yoffset)
ld (ycur),hl
ex de,hl
ld bc,(mapwidth)
call DE_Times_BC
ld de,(tilemapdata)
add hl,de
ld de,(xoffset)
add hl,de
ld (tileptr),hl
ld hl,(mapwidth)
ld bc,-12
add hl,bc ;amount to add to pointer every Y increment
ld (adjust),hl
xor a
ld (y),a
yloop:
xor a
ld (x),a
ld hl,(xoffset)
ld (xcur),hl
xloop:
ld hl,(xcur)
ld bc,(mapwidth)
or a
sbc hl,bc
jr c,$+7
ld hl,blacktile
jr drawtile
ld hl,(ycur)
ld bc,(mapheight)
or a
sbc hl,bc
jr c,$+7
ld hl,blacktile
jr drawtile
loadtile:
ld hl,(tileptr)
ld e,(hl)
ld d,0
ld hl,curframe
add hl,de
add hl,de
inc hl
ld e,(hl)
ld d,0
ex de,hl
add hl,hl
add hl,hl
ld de,tiledata
add hl,de
ld e,(hl)
inc hl
ld d,(hl)
ex de,hl
drawtile:
;HL points to the sprite
ex de,hl
ld a,(y)
add a,a \ add a,a
add a,a \ add a,a
ld c,a
ld b,0
ld h,b \ ld l,c
add hl,hl
add hl,bc
add hl,hl
ld bc,(DrawBufPtr)
add hl,bc
ld a,(x)
add a,l
ld l,a
jr nc,$+3
inc h
;HL points to where it gets drawn
;DE is the sprite layer
ld bc,12
ld a,8
ex de,hl ; 32
ldi ;128
ex de,hl ; 32
add hl,bc ; 88
inc c ; 32
dec a ; 32
jr nz,$-7 ; 91
;now we need to increment X,tileptr,xcur
ld hl,(tileptr)
inc hl
ld (tileptr),hl
ld hl,(xcur)
inc hl
ld (xcur),hl
ld a,(x)
inc a
ld (x),a
cp 12
jp nz,xloop
ld hl,(tileptr)
ld bc,(adjust)
add hl,bc
ld (tileptr),hl
ld hl,(ycur)
inc hl
ld (ycur),hl
ld a,(y)
inc a
ld (y),a
cp 8
jp nz,yloop
UpdateLCD: ;(chooses monochrome or 3-level gray based on a flag)
ld hl,(primarybufptr)
bit gray,(iy+asmflags)
jr z,monochrome
exx
ld hl,89F0h+asmflags ;89F0h is where the OS keeps IY
ld a,(hl)
ld bc,256*graybitmask+55h
xor b
ld (hl),a
and b
jr z,$+4
rlc c
ld de,12
ld hl,(secondarybufptr)
exx
ld de,12
ld a,20h
col3:
out (16),a
ex af,af'
ld b,40h
row3:
exx ;4
ld a,(hl) ;7
and c ;8
rlc c ;8
add hl,de ;11
exx ;4
or (hl) ;7
add hl,de ;11
bit rvideo,(iy+asmflags) ;23
jr z,$+3 \ cpl ;11
out (17),a ;11
djnz row3 ;13
dec h
dec h
dec h
inc hl
exx
dec h
dec h
dec h
inc hl
exx
in a,(16) \ rlca \ jr c,$-3
ex af,af'
inc a
cp 2Ch
jr nz,col3
ret
monochrome:
ld de,11
ld a,20h
col:
out (16),a
push af
ld bc,4011h
row:
in a,(16) \ rlca \ jr c,$-3
outi
add hl,de
jr nz,row
in a,(16) \ rlca \ jr c,$-3
pop af
inc a
dec h
dec h
dec h
inc l
cp 2Ch
jr nz,col
res lcdupdate,(iy+asmflags)
ret
;===============================================================
GetKey:
;===============================================================
;Outputs:
; a is a value from 0 to 56 that is the keypress
; bc is also the key press
; d has a bit reset, the rest are set (this is the last key group tested)
; e is a divided by by 8
; hl is not modified
;===============================================================
ld bc,0 ;010000 ;10
ld de,$7FFF ;11FF7F ;10
KeyLoop: ;
rlc d ;CB02 ;8
ld a,d ;7A ;4
out (1),a ;D301 ;12
inc e ;1C ;4
sub 7Fh ;D67F ;7
ret z ;C8 ;5|11
nop ;00 ;4
in a,(1) ;DB01 ;12
inc a ;3C ;4
jr z,KeyLoop ;28EC ;7|12
dec a ;3D ;4
inc c ;0C ;4
rra ;1F ;4
jr c,$-2 ;38FC ;7|12
ld a,e ;7B ;4
rlca \ rlca \ rlca;070707 ;12
add a,c ;81 ;4
ld c,a ;4F ;4
ret ;C9 ;10
The code I have for setting up the animation LUT (for the tile number and timer) is in this routine:
loadtestmap:
ld hl,23
ld (mapwidth),hl
ld l,13
ld (mapheight),hl
ld l,0
ld (xoffset),hl
ld (yoffset),hl
ld (ymapcoord),hl
ld (xmapcoord),hl
ld h,80h ;HL = 8000h, this code loads the 128 tiles and their counters are all set to 1. The next interrupt sets them to 0, and updates them accordingly.
xor a
ld (hl),1
inc l
ld (hl),a
inc a
inc l
jr nz,$-6
ld hl,testmap
ld (tilemapdata),hl
set mapmode,(iy+textflags)
ret