; _____ _ _ __ __ _
; / ____| | | (_) \ \ / / | |
; | | __ _ __ __ _ _ __ | |__ _ ___ ___ \ \ /\ / /___ _ __ __| |___
; | | |_ | '__/ _` | '_ \| '_ \| |/ __/ __| \ \/ \/ // _ \| '__/ _` / __|
; | |__| | | | (_| | |_) | | | | | (__\__ \ \ /\ /| (_) | | | (_| \__ \
; \_____|_| \__,_| .__/|_| |_|_|\___|___/ \/ \/ \___/|_| \__,_|___/
; | |
; |_|
; graphics related commands
; GMODE ( gmode -- )
_gmode mov *stack+,r8 ; pop gmode
ci r8,0 ; 40 column mode?
jeq s40col ; jump if yes
ci r8,1 ; 32 column mode?
jeq s32col ; jump if yes
ci r8,2 ; 80 column mode?
jeq s80col ; jump if yes
; otherwise illegal graphics mode selected,
; so fall through to 40 column mode...
s40col li r2,col40d ; vdp register data for 40 column mode
jmp ldvdpr ; go load the vdp registers
s32col li r2,col32d ; vdp register data for 32 column mode
jmp ldvdpr ; go load the vdp registers
s80col li r2,col80d ; vdp register data for 80 column mode
; load the vdp registers
ldvdpr mov r2,r7 ; save address for later
movb *r2+,r1 ; number of registers to load
sra r1,8 ; move the count to the low byte
clr r0 ; start with register 0
ldvdpl movb *r2+,r0 ; get register data in r0 MSB
swpb r0 ; swap it over
bl @_vwtr ; write the register
swpb r0 ; swap it back again
inc r0 ; add 1 to register
dec r1 ; finished?
jne ldvdpl ; repeat if not
; set XMAX...
movb *r2,r0 ; get xmax
sra r0,8 ; move to low byte
mov r0,@xmax ; set xmax
inct r7 ; point to vdp r1 data
movb *r7,@>83d4 ; write vdp r1 to >83d4
movb *r7,@VDPR1 ; save copy
; now clear the screen...
mov @xmax,r1 ; calculate the character count
li r0,24 ; according to the...
mpy r0,r1 ; ...text mode
clr r0 ; screen address
li r1,>2000 ; space character
bl @vsbwmi ; wipe screen
clr @scrX ; zero x coordinate
clr @scrY ; zero y coordinate
ci r8,1 ; was 32 column mode selected?
jne gmodex ; if not, then exit
; load colour table for pattern mode...
li r0,>380 ; color table
li r1,>f000 ; white on transparent
li r2,16 ; count
bl @vsbwmi ; load colour table
; initialise sprite attribute list...
li r0,>303 ; address of colour byte
clr r1 ; transparent colour
li r2,32 ; 32 sprites
dovdp2 bl @_vsbw0 ; write to sprite
ai r0,4 ; move to next sprite
dec r2 ; decrement count
jne dovdp2 ; repeat if not finished
gmodex jmp gexit
col40d ; register count and data
byte 8,>00,>f0,>00,>0e,>01,>06,>00,>f4
byte 40 ; XMAX
col32d ; register count and data
byte 8,>00,>e0,>00,>0e,>01,>06,>02,>f4
byte 32 ; XMAX
col80d ; register count and data
byte 15,>04,>70,>03,>e8,>01,>06,>00,>f4,>88,>00,>00,>00,>94,>10,>00
byte 80 ; XMAX
even
; HCHAR ( y x ascii count -- )
_hchar bl @get4 ; get parameters from stack and calculate
; screen address
bl @_vsbwm ; write to screen
gexit b @retB0
; VCHAR ( y x ascii count -- )
_vchar bl @get4 ; get parameters from stack and calculate
; screen address
li r6,24 ; row count
mpy @xmax,r6 ; max visible address+1 (in r7)
dec r7 ; correct max visible (we count from 0)
mov @xmax,r6 ; get xmax in a register
vchar1 bl @_vsbw ; write a character
a r6,r0 ; move down one line
c r0,r7 ; gone off end of screen?
jle vchar2 ; skip if not
s r7,r0 ; reduce address
vchar2 dec r2 ; decrement count
jne vchar1 ; repeat if not finished
jmp gexit
; GCHAR ( y x -- ascii )
_gchar bl @get2 ; get y & x from stack
mpy @xmax,r6 ; compute y
a r7,r0 ; compute screen address
clr r1 ; use r1 for byte operations
bl @_vsbr ; read byte from vdp
swpb r1 ; move byte to lsb
dect stack ; make space on stack
mov r1,*stack ; place on stack as 16 bit word
jmp gexit
; DCHAR ( address count ascii -- )
; Equivalent to CALL CHAR in BASIC.
; Used to define a character.
; Moves count words from address to ascii address in VDP memory
_dchar bl @sget3 ; get 3 parameters
mov r9,r9 ; if count=0 then...
jeq gexit ; ...just exit
mov r8,r0 ; ascii
sla r0,3 ; multiply by 8
ai r0,>800 ; add pattern table offset
mov r10,r1 ; source address
mov r9,r2 ; count
sla r2,1 ; convert from words to bytes
bl @_vmbw ; write to vdp
jmp gexit
; SPRITE ( sprite y x ascii color -- )
; sprite attribute list begins at 6*80h=300h
_sprit bl @sget5 ; get 5 parameters
dec r9 ; correct for screen to char alignment
sla r10,2 ; multiply sprite by 4 (offset into SAL)
li r11,sal ; address of SAL in CPU ram
li r0,>300 ; address of SAL in VDP ram
a r10,r11 ; add offset to cpu addr according to
; sprite number
mov r11,r1 ; cpu source for vmbw
a r10,r0 ; destination address for vmbw
swpb r6 ; rotate colour
swpb r7 ; rotate ascii
swpb r8 ; rotate x
swpb r9 ; rotate y
movb r9,*r11+ ; move y to cpu buffer
movb r8,*r11+ ; move x to cpu buffer
movb r7,*r11+ ; move ascii to cpu buffer
movb r6,*r11+ ; move colour to cpu buffer
li r2,4
bl @_vmbw ; copy entry from SAL to appropriate sprite
; address in VDP
sprtx b @retB0
; COINC ( tolerance spr1 spr2 -- flag )
; check for coincidence between sprite spr1 and spr2. If both the horizontal
; and vertical difference between the two sprites is < tolerance then the
; sprites are considered to be in coincidence with each other and flag shall be
; true, otherwise it shall be false.
_coinc mov @bank1_,@retbnk ; return to bank 1 if taking interrupt
limi 2 ; let interrupts run
limi 0
mov *stack+,r2 ; get spr2
mov *stack+,r1 ; get spr1
movb @>837b,r0 ; get vdp status register (ed/as pg. 405)
andi r0,>2000 ; check collision bits
jeq miss ; if NO sprites are in collision then
; don't do the rest of the test.
; some sprites are in collision, so....
sla r1,2 ; spr1 * 4
sla r2,2 ; spr2 * 4
li r6,sal ; address of sprite attribute list
a r6,r1