mirror of
https://github.com/cc65/cc65.git
synced 2024-08-17 19:29:12 +00:00
1484 lines
22 KiB
PHP
1484 lines
22 KiB
PHP
;
|
|
; Generic Atari graphics driver
|
|
;
|
|
|
|
.macpack longbranch
|
|
|
|
; ******************************************************************************
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; Header. Includes jump table and constants.
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.segment "JUMPTABLE"
|
|
|
|
; Header
|
|
|
|
.byte $74, $67, $69 ; "tgi"
|
|
.byte TGI_API_VERSION ; TGI API version number
|
|
.word x_res ; X resolution
|
|
.word y_res ; Y resolution
|
|
.byte colors ; Number of drawing colors
|
|
.byte pages ; Number of screens available
|
|
.byte 8 ; System font X size
|
|
.byte 8 ; System font Y size
|
|
.word aspect ; Aspect ratio
|
|
.byte 0 ; TGI driver flags
|
|
|
|
; Function table
|
|
|
|
.addr INSTALL
|
|
.addr UNINSTALL
|
|
.addr INIT
|
|
.addr DONE
|
|
.addr GETERROR
|
|
.addr CONTROL
|
|
.addr CLEAR
|
|
.addr SETVIEWPAGE
|
|
.addr SETDRAWPAGE
|
|
.addr SETCOLOR
|
|
.addr SETPALETTE
|
|
.addr GETPALETTE
|
|
.addr GETDEFPALETTE
|
|
.addr SETPIXEL
|
|
.addr GETPIXEL
|
|
.addr LINE
|
|
.addr BAR
|
|
.addr TEXTSTYLE
|
|
.addr OUTTEXT
|
|
.addr 0 ; IRQ entry is unused
|
|
|
|
; ******************************************************************************
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; Parameters
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
x1 := ptr1
|
|
y1 := ptr2
|
|
x2 := ptr3
|
|
y2 := ptr4
|
|
radius := tmp1
|
|
|
|
; ******************************************************************************
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; Global variables
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
sptr := regsave + 2
|
|
|
|
.bss
|
|
error:
|
|
.res 1 ; Error code
|
|
|
|
.if ::grmode = 9 || ::grmode = 11
|
|
palette = default_palette
|
|
.else
|
|
palette:
|
|
.res colors ; The current palette
|
|
.endif
|
|
|
|
mask:
|
|
.res 1 ; Current pixel mask
|
|
griocb:
|
|
.res 1 ; IOCB channel number for graphics
|
|
|
|
.if pages = 2
|
|
p0scr:
|
|
.res 1 ; High byte of screen address for screen page 0
|
|
p0dls:
|
|
.res 1 ; High byte of display list address for screen page 0
|
|
; Page 1's addresses are 8K higher
|
|
.endif
|
|
|
|
.data
|
|
mag_x:
|
|
.byte 1 ; Horizontal text scaling factor
|
|
mag_y:
|
|
.byte 1 ; Vertical text scaling factor
|
|
mag_x8:
|
|
.word 8 ; Horizontal text scaling factor * 8
|
|
mag_y8:
|
|
.word 8 ; Vertical text scaling factor * 8
|
|
text_dir:
|
|
.byte 0 ; Text direction,
|
|
|
|
.code
|
|
|
|
; ******************************************************************************
|
|
|
|
.macro put_pixel
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; Put a pixel at (sptr),y using x as the bit mask offset
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
lda (sptr),y
|
|
eor mask
|
|
and mask_table,x
|
|
eor (sptr),y
|
|
sta (sptr),y
|
|
.endmacro
|
|
|
|
; ******************************************************************************
|
|
|
|
.rodata
|
|
screen_device:
|
|
.byte "S:",$9B ; Device code for screen
|
|
screen_device_length := * - screen_device
|
|
|
|
.code
|
|
|
|
.proc INIT
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; INIT: Switch to graphics mode
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
|
|
.code
|
|
; Initialize drawing color
|
|
|
|
.if ::ppb = 8
|
|
ldx #$FF
|
|
.elseif ::ppb = 4
|
|
ldx #$55
|
|
.elseif ::ppb = 2
|
|
ldx #$11
|
|
.endif
|
|
|
|
stx mask
|
|
|
|
; Find a free IOCB
|
|
lda #$70
|
|
search: tax
|
|
ldy ICHID,x
|
|
cpy #$FF
|
|
beq found
|
|
sub #$10
|
|
bcs search
|
|
|
|
; Not enough resources available (free IOCB or memory)
|
|
; enter with C cleared!
|
|
nores: lda #TGI_ERR_NO_RES
|
|
bcc exit
|
|
|
|
found: ; Check if enough RAM is available
|
|
lda #0
|
|
sub #<mem_needed
|
|
tay
|
|
lda RAMTOP
|
|
sbc #>mem_needed
|
|
cmp APPMHI + 1
|
|
bcc nores
|
|
bne switch
|
|
cpy APPMHI
|
|
bcc nores ; not enough memory
|
|
|
|
; Switch into graphics mode
|
|
switch: lda #OPEN
|
|
sta ICCOM,x
|
|
lda #OPNIN | OPNOT
|
|
sta ICAX1,x
|
|
lda #::grmode
|
|
sta ICAX2,x
|
|
lda #<screen_device
|
|
sta ICBAL,x
|
|
lda #>screen_device
|
|
sta ICBAH,x
|
|
lda #<screen_device_length
|
|
sta ICBLL,x
|
|
lda #>screen_device_length
|
|
sta ICBLH,x
|
|
jsr CIOV
|
|
|
|
.if ::pages = 2
|
|
; Reserve 8K of high memory
|
|
lda RAMTOP
|
|
sub #32
|
|
sta RAMTOP
|
|
; Close and reopen graphics
|
|
lda #CLOSE
|
|
sta ICCOM,x
|
|
jsr CIOV
|
|
; Reopen graphics
|
|
lda #OPEN
|
|
sta ICCOM,x
|
|
lda #OPNIN | OPNOT
|
|
sta ICAX1,x
|
|
lda #::grmode
|
|
sta ICAX2,x
|
|
lda #<screen_device
|
|
sta ICBAL,x
|
|
lda #>screen_device
|
|
sta ICBAH,x
|
|
lda #<screen_device_length
|
|
sta ICBLL,x
|
|
lda #>screen_device_length
|
|
sta ICBLH,x
|
|
jsr CIOV
|
|
; Save screen pointers
|
|
lda SAVMSC + 1
|
|
sta p0scr
|
|
lda SDLSTH
|
|
sta p0dls
|
|
.endif ; ::pages = 2
|
|
|
|
stx griocb
|
|
|
|
; Reset the error code and return
|
|
lda #TGI_ERR_OK
|
|
exit: sta error
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc DONE
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; DONE: Switch back to text mode
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
|
|
.if ::pages = 2
|
|
; Free 8K of high memory
|
|
lda RAMTOP
|
|
add #32
|
|
sta RAMTOP
|
|
.endif
|
|
|
|
; Clear griocb
|
|
lda #$FF
|
|
ldx griocb
|
|
sta griocb
|
|
|
|
; Close the S: device
|
|
lda #CLOSE
|
|
sta ICCOM,x
|
|
jsr CIOV
|
|
|
|
; Reopen it in Graphics 0
|
|
lda #OPEN
|
|
sta ICCOM,x
|
|
lda #OPNIN | OPNOT
|
|
sta ICAX1,x
|
|
lda #0
|
|
sta ICAX2,x
|
|
lda #<screen_device
|
|
sta ICBAL,x
|
|
lda #>screen_device
|
|
sta ICBAH,x
|
|
lda #<screen_device_length
|
|
sta ICBLL,x
|
|
lda #>screen_device_length
|
|
sta ICBLH,x
|
|
jsr CIOV
|
|
|
|
; Now close it again; we don't need it anymore :)
|
|
lda #CLOSE
|
|
sta ICCOM,x
|
|
jmp CIOV
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc GETERROR
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; GETERROR: Return the error code in A and clear it
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
ldx #TGI_ERR_OK
|
|
lda error
|
|
stx error
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc CLEAR
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; CLEAR: Clear the screen
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
; Load the screen address in sptr
|
|
lda SAVMSC
|
|
sta sptr
|
|
lda SAVMSC + 1
|
|
sta sptr + 1
|
|
|
|
; Fill with zero
|
|
lda #0
|
|
tay
|
|
|
|
.if >::scrsize > 0
|
|
; Clear full pages if any
|
|
ldx #>::scrsize
|
|
loop1: sta (sptr),y
|
|
iny
|
|
bne loop1
|
|
inc sptr + 1
|
|
dex
|
|
bne loop1
|
|
.endif
|
|
|
|
.if <::scrsize > 0
|
|
; Clear the rest, if any
|
|
loop2: sta (sptr),y
|
|
iny
|
|
cpy #<::scrsize
|
|
bne loop2
|
|
.endif
|
|
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc GETPALETTE
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; GETPALETTE: Return the current palette in A/X
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
lda #<palette
|
|
ldx #>palette
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc GETDEFPALETTE
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; GETDEFPALETTE: Return the default palette in A/X
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
lda #<default_palette
|
|
ldx #>default_palette
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc SETCOLOR
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; SETCOLOR: Set the drawing color (in A)
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
tax
|
|
|
|
.if ::grmode = 9
|
|
; Map colors like this: 0 -> 0, 1 -> 15, 2 -> 1, 3 -> 2 etc.
|
|
beq cont
|
|
cpx #1
|
|
bne map
|
|
ldx #16
|
|
map: dex
|
|
cont:
|
|
.endif
|
|
|
|
lda masks,x
|
|
sta mask
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc CALC
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; CALC: Calculate the screen address
|
|
; in
|
|
; x1 (ptr1) x coordinate
|
|
; y1 (ptr2) y coordinate
|
|
; out
|
|
; sptr + y screen address
|
|
; x bit mask index
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.bss
|
|
temp: .res 1
|
|
.code
|
|
; calculate line offset
|
|
lda y1 + 1
|
|
sta temp
|
|
lda y1
|
|
|
|
.if ::x_res / ::ppb = 40
|
|
yrep = 3
|
|
.elseif ::x_res / ::ppb = 20
|
|
yrep = 2
|
|
.elseif ::x_res / ::ppb = 10
|
|
yrep = 1
|
|
.endif
|
|
|
|
.repeat yrep
|
|
asl a
|
|
rol temp
|
|
.endrepeat
|
|
|
|
sta sptr
|
|
ldx temp
|
|
stx sptr + 1
|
|
|
|
.repeat 2
|
|
asl a
|
|
rol temp
|
|
.endrepeat
|
|
|
|
add sptr
|
|
sta sptr
|
|
lda temp
|
|
adc sptr + 1
|
|
sta sptr + 1
|
|
|
|
; calculate bit mask offset
|
|
lda x1
|
|
and #ppb - 1
|
|
tax
|
|
|
|
; calculate row offset
|
|
lda x1 + 1
|
|
sta temp
|
|
lda x1
|
|
|
|
.if ::ppb = 8
|
|
xrep = 3
|
|
.elseif ::ppb = 4
|
|
xrep = 2
|
|
.elseif ::ppb = 2
|
|
xrep = 1
|
|
.endif
|
|
|
|
.repeat xrep
|
|
lsr temp
|
|
ror a
|
|
.endrepeat
|
|
|
|
tay
|
|
|
|
; sptr += SAVMSC
|
|
lda SAVMSC
|
|
add sptr
|
|
sta sptr
|
|
lda SAVMSC + 1
|
|
adc sptr + 1
|
|
sta sptr + 1
|
|
|
|
; We're done!
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc SETPIXEL
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; Draw one pixel at x1, y1
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
jsr CALC
|
|
put_pixel
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc GETPIXEL
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; GETPIXEL: Read the color value of a pixel and return it in A/X
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
jsr CALC
|
|
lda (sptr),y
|
|
and mask_table,x
|
|
|
|
.if ::ppb = 8
|
|
beq zero
|
|
lda #1
|
|
zero: ldx #0
|
|
rts
|
|
.elseif ::ppb = 4
|
|
loop: cpx #3
|
|
beq done4
|
|
lsr a
|
|
lsr a
|
|
inx
|
|
bne loop
|
|
done4: and #$03
|
|
ldx #0
|
|
rts
|
|
.elseif ::ppb = 2
|
|
dex
|
|
bne shift
|
|
and #$0F
|
|
jmp exit
|
|
shift: lsr a
|
|
lsr a
|
|
lsr a
|
|
lsr a
|
|
|
|
exit:
|
|
|
|
.if ::grmode = 9
|
|
; Mode 9 mapping
|
|
; Map colors like this: 0 -> 0, 15 -> 1, 2 -> 3, 3 -> 4 etc.
|
|
beq done9
|
|
cmp #15
|
|
bne map9
|
|
lda #0
|
|
map9: add #1
|
|
done9:
|
|
.endif
|
|
|
|
.if ::grmode = 10
|
|
; Mode 10 mapping
|
|
; Map out of range colors like this:
|
|
; 9 -> 8
|
|
; 10 -> 8
|
|
; 11 -> 8
|
|
; 12 -> 0
|
|
; 13 -> 1
|
|
; 14 -> 2
|
|
; 15 -> 3
|
|
cmp #9
|
|
bcc done10
|
|
sub #12
|
|
bcs done10
|
|
lda #8
|
|
done10:
|
|
.endif ; ::grmode = 10
|
|
|
|
; Done!
|
|
ldx #0
|
|
rts
|
|
.endif ; ::ppb = 2
|
|
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc LINE
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; LINE: Draw a line from x1,y1 to x2,y2
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.ifdef USE_CIO_LINE
|
|
|
|
; position ptr1, ptr2
|
|
lda x1
|
|
sta OLDCOL
|
|
lda x1 + 1
|
|
sta OLDCOL + 1
|
|
lda y1
|
|
sta OLDROW
|
|
; plot
|
|
jsr SETPIXEL
|
|
; position ptr3,ptr4
|
|
lda x2
|
|
sta COLCRS
|
|
lda x2 + 1
|
|
sta COLCRS + 1
|
|
lda y2
|
|
sta ROWCRS
|
|
; drawto
|
|
ldx griocb
|
|
lda #DRAWLN
|
|
sta ICCOM,x
|
|
lda mask
|
|
|
|
.if ::grmode = 10
|
|
and #$0f
|
|
.else
|
|
and #colors - 1
|
|
.endif
|
|
|
|
sta ATACHR
|
|
jmp CIOV
|
|
|
|
.else ; USE_CIO_LINE
|
|
|
|
; locals
|
|
|
|
dx := sreg
|
|
dy := y1
|
|
dx2 := x2
|
|
dy2 := y2
|
|
iy := tmp1
|
|
err := tmp3
|
|
|
|
.code
|
|
; dx = x2 - x1
|
|
lda x2
|
|
sub x1
|
|
sta dx
|
|
lda x2 + 1
|
|
sbc x1 + 1
|
|
sta dx + 1
|
|
; if dx is positive, no problem
|
|
bcs dx_positive
|
|
|
|
; if dx is negative, swap x1,y1 with x2,y2
|
|
lda x1 ; x1 <-> x2, low byte
|
|
ldx x2
|
|
sta x2
|
|
stx x1
|
|
lda x1 + 1 ; x1 <-> x2, high byte
|
|
ldx x2 + 1
|
|
sta x2 + 1
|
|
stx x1 + 1
|
|
lda y1 ; y1 <-> y2, low byte
|
|
ldx y2
|
|
sta y2
|
|
stx y1
|
|
lda y1 + 1 ; y1 <-> y2, high byte
|
|
ldx y2 + 1
|
|
sta y2 + 1
|
|
stx y1 + 1
|
|
; Calculate again
|
|
jmp LINE
|
|
|
|
dx_positive:
|
|
; Calculate coords
|
|
jsr CALC
|
|
|
|
; dy = y2 - y1
|
|
lda y2
|
|
sub y1
|
|
sta dy
|
|
lda y2 + 1
|
|
sbc y1 + 1
|
|
sta dy + 1
|
|
|
|
; if dy is negative
|
|
bcs dy_positive
|
|
; dy = -dy
|
|
lda #0
|
|
sub dy
|
|
sta dy
|
|
lda #0
|
|
sbc dy + 1
|
|
sta dy + 1
|
|
; iy = -row_size
|
|
lda #<(65536 - x_res / ppb)
|
|
sta iy
|
|
lda #>(65536 - x_res / ppb)
|
|
sta iy + 1
|
|
bne skip_iy_1 ; always
|
|
|
|
dy_positive:
|
|
; iy = row_size
|
|
lda #<(x_res / ppb)
|
|
sta iy
|
|
lda #>(x_res / ppb)
|
|
sta iy + 1
|
|
skip_iy_1:
|
|
|
|
; dx2 = dx * 2
|
|
lda dx
|
|
asl a
|
|
sta dx2
|
|
lda dx + 1
|
|
rol a
|
|
sta dx2 + 1
|
|
|
|
; dy2 = dy * 2
|
|
lda dy
|
|
asl a
|
|
sta dy2
|
|
lda dy + 1
|
|
rol a
|
|
sta dy2 + 1
|
|
|
|
; if dx >= dy
|
|
lda dx
|
|
cmp dy
|
|
lda dx + 1
|
|
sbc dy + 1
|
|
bcc dy_major
|
|
|
|
; dx is the major axis
|
|
|
|
; err = dy2 - dx
|
|
lda dy2
|
|
sub dx
|
|
sta err
|
|
lda dy2 + 1
|
|
sbc dx + 1
|
|
sta err + 1
|
|
|
|
.scope
|
|
loop: ; main loop
|
|
put_pixel
|
|
; if err >= 0
|
|
lda err + 1
|
|
bmi err_neg
|
|
; err -= dx2
|
|
lda err
|
|
sub dx2
|
|
sta err
|
|
lda err + 1
|
|
sbc dx2 + 1
|
|
sta err + 1
|
|
; move_vertical (iy)
|
|
lda sptr
|
|
add iy
|
|
sta sptr
|
|
lda sptr + 1
|
|
adc iy + 1
|
|
sta sptr + 1
|
|
err_neg:
|
|
; err += dy2
|
|
lda err
|
|
add dy2
|
|
sta err
|
|
lda err + 1
|
|
adc dy2 + 1
|
|
sta err + 1
|
|
; move_right
|
|
inx
|
|
cpx #ppb
|
|
bne end_move
|
|
ldx #0
|
|
iny
|
|
bne end_move
|
|
inc sptr + 1
|
|
end_move:
|
|
; loop while dx-- >= 0
|
|
lda dx
|
|
ora dx + 1
|
|
beq exit
|
|
dec dx
|
|
lda dx
|
|
cmp #$FF
|
|
bne loop
|
|
dec dx + 1
|
|
jmp loop
|
|
exit: rts
|
|
.endscope
|
|
|
|
dy_major:
|
|
; dy is the major axis
|
|
|
|
; err = dx2 - dy;
|
|
lda dx2
|
|
sub dy
|
|
sta err
|
|
lda dx2 + 1
|
|
sbc dy + 1
|
|
sta err + 1
|
|
|
|
.scope
|
|
loop: ; main loop
|
|
put_pixel
|
|
; if err >= 0
|
|
lda err + 1
|
|
bmi end_move
|
|
; err -= dy2
|
|
lda err
|
|
sub dy2
|
|
sta err
|
|
lda err + 1
|
|
sbc dy2 + 1
|
|
sta err + 1
|
|
; move_right
|
|
inx
|
|
cpx #ppb
|
|
bne end_move
|
|
ldx #0
|
|
iny
|
|
bne end_move
|
|
inc sptr + 1
|
|
end_move:
|
|
; err += dx2
|
|
lda err
|
|
add dx2
|
|
sta err
|
|
lda err + 1
|
|
adc dx2 + 1
|
|
sta err + 1
|
|
; move_vertical(iy)
|
|
lda sptr
|
|
add iy
|
|
sta sptr
|
|
lda sptr + 1
|
|
adc iy + 1
|
|
sta sptr + 1
|
|
; loop while dy-- >= 0
|
|
lda dy
|
|
ora dy + 1
|
|
beq exit
|
|
dec dy
|
|
lda dy
|
|
cmp #$FF
|
|
bne loop
|
|
dec dy + 1
|
|
jmp loop
|
|
exit: rts
|
|
.endscope
|
|
.endif ; USE_CIO_LINE
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc clipped_bar
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; Clip and draw bar, this function will disappear when text clipping
|
|
; will be done int the TGI kernel
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
lda y1 + 1
|
|
bne off
|
|
lda y1
|
|
cmp #y_res
|
|
bcs off
|
|
|
|
lda x1 + 1
|
|
|
|
.if >(::x_res - 1) > 0
|
|
cmp #>x_res
|
|
bcc check2
|
|
.endif
|
|
|
|
bne off
|
|
lda x1
|
|
cmp #<x_res
|
|
bcc check2
|
|
off: rts
|
|
|
|
check2: lda y2 + 1
|
|
bne off
|
|
lda y2
|
|
cmp #y_res
|
|
bcs off
|
|
|
|
lda x2 + 1
|
|
|
|
.if >(::x_res - 1) > 0
|
|
cmp #>x_res
|
|
bcc BAR
|
|
.endif
|
|
|
|
bne off
|
|
lda x2
|
|
cmp #<x_res
|
|
bcs off
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc BAR
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; BAR: Draw a filled rectangle with the corners at x1,y1,x2,y2
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
; locals
|
|
lmem := sreg
|
|
.bss
|
|
lmask: .res 1
|
|
rmask: .res 1
|
|
dy: .res 1
|
|
dx: .res 1
|
|
fmask: .res 1
|
|
.code
|
|
; dy = y2 - y1 + 1
|
|
lda y2
|
|
sub y1
|
|
sta dy
|
|
inc dy
|
|
; Calculate upper left corner
|
|
jsr CALC
|
|
; Save the values
|
|
tya
|
|
add sptr
|
|
sta lmem
|
|
lda sptr + 1
|
|
adc #0
|
|
sta lmem + 1
|
|
lda bar_table,x
|
|
sta lmask
|
|
; Calculate upper right corner
|
|
lda x2
|
|
sta x1
|
|
|
|
.if >(::x_res - 1) > 0
|
|
lda x2 + 1
|
|
sta x1 + 1
|
|
.endif
|
|
|
|
jsr CALC
|
|
; Save the values
|
|
tya
|
|
add sptr
|
|
sta sptr
|
|
bcc skips
|
|
inc sptr + 1
|
|
skips: inx
|
|
lda bar_table,x
|
|
eor #$FF
|
|
sta rmask
|
|
; Calculate memory difference between x1 and x2
|
|
lda sptr
|
|
sub lmem
|
|
sta dx
|
|
loop: ; Main loop
|
|
ldy #0
|
|
ldx dx
|
|
beq same
|
|
; Left
|
|
lda (lmem),y
|
|
eor mask
|
|
and lmask
|
|
eor (lmem),y
|
|
sta (lmem),y
|
|
iny
|
|
; Between
|
|
lda mask
|
|
jmp next
|
|
btwn: sta (lmem),y
|
|
iny
|
|
next: dex
|
|
bne btwn
|
|
; Right
|
|
lda (lmem),y
|
|
eor mask
|
|
and rmask
|
|
eor (lmem),y
|
|
sta (lmem),y
|
|
jmp cont
|
|
same: ; Same byte
|
|
lda lmask
|
|
and rmask
|
|
sta fmask
|
|
lda (lmem),y
|
|
eor mask
|
|
and fmask
|
|
eor (lmem),y
|
|
sta (lmem),y
|
|
cont: ; Go to next row
|
|
lda lmem
|
|
add #<(x_res / ppb)
|
|
sta lmem
|
|
bcc skipm
|
|
inc lmem + 1
|
|
skipm: ; Loop while --dy > 0
|
|
dec dy
|
|
bne loop
|
|
|
|
rts
|
|
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc TEXTSTYLE
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; TEXTSTYLE: Set text style. Scale factors in X and Y and direction in A
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
stx mag_x
|
|
sty mag_y
|
|
; Save text direction in bit 8 so that we can use BIT instruction later
|
|
lsr a
|
|
ror a
|
|
sta text_dir
|
|
; Save 8 * scaling factors
|
|
lda #0
|
|
sta mag_x8 + 1
|
|
sta mag_y8 + 1
|
|
; Save 8 * mag_x
|
|
txa
|
|
|
|
.repeat 3
|
|
asl a
|
|
rol mag_x8 + 1
|
|
.endrepeat
|
|
|
|
sta mag_x8
|
|
; Save 8 * mag_y
|
|
tya
|
|
|
|
.repeat 3
|
|
asl a
|
|
rol mag_y8 + 1
|
|
.endrepeat
|
|
|
|
sta mag_y8
|
|
; Done!
|
|
rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc OUTTEXT
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; OUTTEXT: Draw text at x1, y1. String is in ptr3
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
; locals
|
|
string := tmp1
|
|
cols := tmp3
|
|
pixels := tmp4
|
|
font := regsave
|
|
.rodata
|
|
ataint: .byte 64,0,32,96
|
|
.bss
|
|
rows: .res 1
|
|
|
|
.if >(::x_res - 1) > 0
|
|
oldx1: .res 2
|
|
oldx2: .res 2
|
|
.else
|
|
oldx1: .res 1
|
|
oldx2: .res 1
|
|
.endif
|
|
|
|
oldy1: .res 1
|
|
oldy2: .res 1
|
|
inv: .res 1
|
|
|
|
.code
|
|
; Don't draw zero sized characters
|
|
lda mag_x
|
|
ora mag_y
|
|
bne not0
|
|
rts
|
|
|
|
not0: ; Save string address, ptr3 is needed by BAR
|
|
lda ptr3
|
|
sta string
|
|
lda ptr3 + 1
|
|
sta string + 1
|
|
|
|
bit text_dir
|
|
bmi vert
|
|
|
|
; Calculate x2
|
|
lda mag_x
|
|
sub #1
|
|
add x1
|
|
sta x2
|
|
|
|
.if >(::x_res - 1) > 0
|
|
lda x1 + 1
|
|
adc #0
|
|
sta x2 + 1
|
|
.else
|
|
lda #0
|
|
sta x2 + 1
|
|
.endif
|
|
|
|
; Calculate y2 and adjust y1
|
|
dec y1
|
|
lda y1
|
|
sta y2
|
|
sub mag_y
|
|
add #1
|
|
sta y1
|
|
lda #0
|
|
sta y2 + 1
|
|
|
|
jmp while
|
|
|
|
; Calculate for vertical text
|
|
vert: lda x1
|
|
sub #1
|
|
sta x2
|
|
lda x1 + 1
|
|
sbc #0
|
|
sta x2 + 1
|
|
lda x1
|
|
sub mag_y
|
|
sta x1
|
|
lda x1 + 1
|
|
sbc #0
|
|
sta x1 + 1
|
|
|
|
lda mag_x
|
|
sub #1
|
|
add y1
|
|
sta y2
|
|
lda #0
|
|
sta y2 + 1
|
|
jmp while
|
|
|
|
; Main loop
|
|
loop: inc string
|
|
bne skiph
|
|
inc string + 1
|
|
skiph: ; Save coords
|
|
bit text_dir
|
|
bmi scvert
|
|
|
|
ldx y1
|
|
stx oldy1
|
|
ldx y2
|
|
stx oldy2
|
|
jmp draw
|
|
|
|
scvert: ldx x1
|
|
stx oldx1
|
|
ldx x2
|
|
stx oldx2
|
|
|
|
.if >(::x_res - 1) > 0
|
|
ldx x1 + 1
|
|
stx oldx1 + 1
|
|
ldx x2 + 1
|
|
stx oldx2 + 1
|
|
.endif
|
|
|
|
; Draw one character
|
|
; Convert to ANTIC code
|
|
draw: tay
|
|
rol a
|
|
rol a
|
|
rol a
|
|
rol a
|
|
and #3
|
|
tax
|
|
tya
|
|
and #$9f
|
|
ora ataint,x
|
|
; Save and clear inverse video bit
|
|
sta inv
|
|
and #$7F
|
|
; Calculate font data address
|
|
sta font
|
|
lda #0
|
|
sta font + 1
|
|
|
|
.repeat 3
|
|
asl font
|
|
rol a
|
|
.endrepeat
|
|
|
|
adc CHBAS
|
|
sta font + 1
|
|
; Save old coords
|
|
bit text_dir
|
|
bpl hor
|
|
lda y1
|
|
sta oldy1
|
|
lda y2
|
|
sta oldy2
|
|
jmp cont
|
|
hor: lda x1
|
|
sta oldx1
|
|
lda x2
|
|
sta oldx2
|
|
|
|
.if >(::x_res - 1) > 0
|
|
lda x1 + 1
|
|
sta oldx1 + 1
|
|
lda x2 + 1
|
|
sta oldx2 + 1
|
|
.endif
|
|
|
|
; Get glyph pixels
|
|
cont: ldy #7
|
|
; Put one row of the glyph
|
|
putrow: sty rows
|
|
lda (font),y
|
|
bit inv
|
|
bpl noinv
|
|
eor #$FF
|
|
noinv: sta pixels
|
|
lda #7
|
|
sta cols
|
|
; Put one column of the row
|
|
putcol: asl pixels
|
|
bcc next_col
|
|
lda x1
|
|
pha
|
|
lda x1 + 1
|
|
pha
|
|
jsr clipped_bar
|
|
pla
|
|
sta x1 + 1
|
|
pla
|
|
sta x1
|
|
next_col:
|
|
; Go to next column
|
|
; increase x coords
|
|
bit text_dir
|
|
bmi vertinc
|
|
|
|
lda mag_x
|
|
add x1
|
|
sta x1
|
|
bcc L1
|
|
inc x1 + 1
|
|
L1: lda mag_x
|
|
add x2
|
|
sta x2
|
|
bcc L2
|
|
inc x2 + 1
|
|
jmp L2
|
|
|
|
vertinc:
|
|
lda y1
|
|
sub mag_x
|
|
sta y1
|
|
lda y2
|
|
sub mag_x
|
|
sta y2
|
|
L2:
|
|
dec cols
|
|
bpl putcol
|
|
next_row:
|
|
; Go to next row
|
|
bit text_dir
|
|
bmi verty
|
|
|
|
lda y1
|
|
sub mag_y
|
|
sta y1
|
|
bcs L3
|
|
dec y1 + 1
|
|
L3: lda y2
|
|
sub mag_y
|
|
sta y2
|
|
bcs L6
|
|
dec y2 + 1
|
|
L4: jmp L6
|
|
|
|
verty: lda x1
|
|
sub mag_y
|
|
sta x1
|
|
bcs L5
|
|
dec x1 + 1
|
|
L5: lda x2
|
|
sub mag_y
|
|
sta x2
|
|
bcs L6
|
|
dec x2 + 1
|
|
L6:
|
|
; Restore old values
|
|
bit text_dir
|
|
bpl reshor
|
|
lda oldy1
|
|
sta y1
|
|
lda oldy2
|
|
sta y2
|
|
jmp nextrow
|
|
reshor: lda oldx1
|
|
sta x1
|
|
lda oldx2
|
|
sta x2
|
|
|
|
.if >(::x_res - 1) > 0
|
|
lda oldx1 + 1
|
|
sta x1 + 1
|
|
lda oldx2 + 1
|
|
sta x2 + 1
|
|
.endif
|
|
|
|
; Next row
|
|
nextrow:
|
|
ldy rows
|
|
dey
|
|
jpl putrow
|
|
|
|
; Restore coords
|
|
bit text_dir
|
|
bmi resvert
|
|
|
|
ldx oldy1
|
|
stx y1
|
|
ldx oldy2
|
|
stx y2
|
|
ldx #0
|
|
stx y1 + 1
|
|
stx y2 + 1
|
|
|
|
lda mag_x8
|
|
add x1
|
|
sta x1
|
|
lda mag_x8 + 1
|
|
adc x1 + 1
|
|
sta x1 + 1
|
|
lda mag_x8
|
|
add x2
|
|
sta x2
|
|
lda mag_x8 + 1
|
|
adc x2 + 1
|
|
sta x2 + 1
|
|
|
|
jmp while
|
|
|
|
resvert:
|
|
ldx oldx1
|
|
stx x1
|
|
ldx oldx2
|
|
stx x2
|
|
|
|
.if >(::x_res - 1) > 0
|
|
ldx oldx1 + 1
|
|
stx x1 + 1
|
|
ldx oldx2 + 1
|
|
stx x2 + 1
|
|
.endif
|
|
|
|
lda y1
|
|
sub mag_x8
|
|
sta y1
|
|
lda y1 +1
|
|
sbc mag_x8 + 1
|
|
sta y1 + 1
|
|
lda y2
|
|
sub mag_x8
|
|
sta y2
|
|
lda y2 +1
|
|
sbc mag_x8 + 1
|
|
sta y2 + 1
|
|
|
|
; End of loop
|
|
while: ldy #0
|
|
lda (string),y
|
|
jne loop ; Check for null character
|
|
rts
|
|
|
|
.endproc
|
|
|
|
.if pages = 2
|
|
; ******************************************************************************
|
|
|
|
.proc SETVIEWPAGE
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; SETVIEWPAGE, page in A
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
tax
|
|
beq cont
|
|
lda #32
|
|
|
|
cont: add p0dls
|
|
cmp SDLSTH
|
|
beq done ; We're already in the desired page
|
|
|
|
ldx RTCLOK + 2
|
|
sta SDLSTH
|
|
|
|
; Wait until next VBLANK
|
|
wait: cpx RTCLOK + 2
|
|
beq wait
|
|
|
|
; Done
|
|
done: rts
|
|
.endproc
|
|
|
|
; ******************************************************************************
|
|
|
|
.proc SETDRAWPAGE
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; SETDRAWPAGE, page in A
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
.code
|
|
tax
|
|
beq cont
|
|
lda #32
|
|
cont: add p0scr
|
|
sta SAVMSC + 1
|
|
rts
|
|
.endproc
|
|
.endif
|
|
|
|
; ******************************************************************************
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; Unimplemented functions that require an error code
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
CONTROL:
|
|
lda #TGI_ERR_INV_FUNC
|
|
sta error
|
|
; fall through
|
|
|
|
; ******************************************************************************
|
|
|
|
; ----------------------------------------------------------------------
|
|
;
|
|
; Unimplemented functions that don't require an error code
|
|
;
|
|
; ----------------------------------------------------------------------
|
|
|
|
INSTALL:
|
|
UNINSTALL:
|
|
|
|
.if pages = 1
|
|
SETVIEWPAGE:
|
|
SETDRAWPAGE:
|
|
.endif
|
|
|
|
rts
|