a3driverutil/Drivers/grafix.s

2413 lines
60 KiB
ArmAsm

;==============================================================
;SOS GRAPHICS DRIVER
;(C) Apple Computer, Inc., 1983 v1.3
; - edited 3/24/86 to 8/31/86 by Erik Olbrys CIS 71236,1245
;==============================================================
.feature labels_without_colons
.setcpu "6502"
.reloc
;
;driver comment field
;this is put in the TEXT segment so we can get the lenght and output it ok
;
.segment "TEXT"
.word $FFFF ;Comment follows..
.word $0039 ;$39 bytes long
.byte "Copyright (C) 1983 Apple Computer, Inc. Graphics Driver."
;
;Driver code part
;this is put in the DATA segement
;
.segment "DATA"
DEVTYPE = $62 ;Character device, read/write
SUBTYPE = $01 ;Device subtype
MANID = $01 ;Manufacturer ID - Apple Inc.
RELEASE = $1300 ;Release number in BCD format
;-------------------
;N-WAY SWITCH MACRO
;SWITCH [index], [bounds], adrs_table, [*]
;-------------------
.MACRO SWITCH index,bounds,adrs_table ;,noexec ;See SOS Reference
.IFNBLANK index ;If PARM1 is present,
LDA index ; load A with switch index
.ENDIF
.IFNBLANK bounds ;If PARM2 is present,
CMP #bounds+1 ; perform bounds checking
BCS @110 ; on switch index
.ENDIF
ASL A ;Multiply by 2 for table index
TAY
LDA adrs_table+1,Y ;Get switch address from table
PHA ; and push onto Stack
LDA adrs_table,Y
PHA
; .IF noexec <> "*" ;If PARM4 is omitted,
RTS ; exit to code
; .ENDIF
@110 .ENDMACRO
;--------------------
;INCREMENT WORD MACRO
;--------------------
.MACRO INW inword
INC inword ;Increment low-order
BNE @210 ;If 'Carry',
INC inword+1 ; increment high-order
@210 .ENDMACRO
;------------------------------
;INCREMENT 3-BYTE ADDRESS MACRO
;------------------------------
.MACRO INCADR addr
INC addr
BNE @310
INC addr+1
BNE @310 ;Bank overflow?
LDX #$80 ;Yes
STX addr+1
INC addr+1+$1400 ;Increment X-byte
@310 .ENDMACRO
.PROC GRAFIX
;---------------
;GENERAL EQUATES
;---------------
TRUE = $80
FALSE = $00
BITON0 = $01
BITON1 = $02
BITON2 = $04
BITON3 = $08
BITON4 = $10
BITON5 = $20
BITON6 = $40
BITON7 = $80
;-----------------------------
;SOS GLOBAL DATA & SUBROUTINES
;-----------------------------
SCR_MODE = $1906
MEM_FLAG = $1907 ;amount of mem reserved for grafix
SYSERR = $1928 ;report error to system
;----------------------------
;SOS DEVICE HANDLER INTERFACE
;----------------------------
SOSINT = $C0
REQCODE = SOSINT+0 ;SOS request code
BUFFER = SOSINT+2 ;Buffer pointer
REQCNT = SOSINT+4 ;Requested count/byte count
CTLSTAT = SOSINT+2 ;Control/status code
CSLIST = SOSINT+3 ;Control/status list pointer
RETPTR = SOSINT+8 ;Returned count pointer
;--------------------
;HARDWARE I/O ADDRESS
;--------------------
SETBW = $C050 ;black & white on
SETCOL = $C051 ;color on
COLM40 = $C052 ;set 40 columns
COLM80 = $C053 ;set 80 columns
LOWSCR = $C054 ;set page one
HISCR = $C055 ;set page two
TEXT = $C056 ;set text mode
HIRES = $C057 ;set hires grafix mode
;---------------
;SOS ERROR CODES
;---------------
XREQCODE = $20 ;invalid request code
XCTLCODE = $21 ;invalid control/status code
XCTLPARAM = $22 ;invalid control/status param
XNOTOPEN = $23 ;device not open
XNOTAVAIL = $24 ;device not available
XNORESRC = $25 ;resource not available
XBADOP = $26 ;invalid operation
XBADMEM = $30 ;insufficient amount of memory alocated
;-----------------
;ZERO PAGE EQUATES
;-----------------
ZPC9 = $C9
ZPCA = $CA
ZPCB = $CB
ZPCC = $CC
ZPCD = $CD
ZPCE = $CE
ZPCF = $CF
ZPD0 = $D0
ZPD1 = $D1
ZPD2 = $D2
ZPD3 = $D3
ZPD4 = $D4
ZPD5 = $D5
ZPD6 = $D6
ZPD7 = $D7
ZPD8 = $D8
ZPD9 = $D9
ZPDA = $DA
ZPDB = $DB
ZPDC = $DC
ZPDD = $DD
ZPDE = $DE
ZPDF = $DF
ZPE0 = $E0
ZPE1 = $E1
ZPE2 = $E2
ZPE3 = $E3
ZPE4 = $E4
ZPE5 = $E5
ZPE6 = $E6
ZPE7 = $E7
ZPE8 = $E8
ZPE9 = $E9
ZPEA = $EA
ZPEB = $EB
ZPEC = $EC
ZPED = $ED
ZPEE = $EE
ZPEF = $EF
ZPF0 = $F0
ZPF1 = $F1
ZPF2 = $F2
ZPF3 = $F3
ZPF4 = $F4
ZPF5 = $F5
ZPF6 = $F6
ZPF7 = $F7
ZPF8 = $F8
ZPF9 = $F9
ZPFA = $FA
ZPFB = $FB
ZPFC = $FC
ZPFD = $FD
ZPFE = $FE
ZPFF = $FF
; ---------------------------
; Device Identification res
; ---------------------------
DIB .word 0000 ; link
.word START ; entry point
.byte 07 ; name len
.byte ".GRAFIX " ; device name
.byte TRUE ; status -- active
.byte FALSE ; slot -- N/A
.byte 00 ; unit #
.byte DEVTYPE ; type
.byte SUBTYPE ; subtype
.byte 00 ; reserved for future use
.word 0000 ; # res s -- none
.word MANID ; man id -- Apple Inc.
.word RELEASE ; ver # -- 1.30
CNFBLK .word $0096 ; DCB length
DCB .byte $00 ;graphics mode
.byte $00 ;transfer mode
.word $0000 ;cursor x-position
.word $0000 ; y-position
.word $0000 ;viewport left edge
.word $0117 ; right edge:= 279.
.word $0000 ; bottom edge
.word $00BF ; top edge:= 191.
.byte $0F ;pencolor:= white
.byte $00 ;fillcolor:= black
.word $0C00 ;Character font address
.byte $00 ; address X-Byte
.byte $07 ;character cell bit width
.byte $08 ;character cell bit height
.byte $80 ; "Not currently used" (but it IS used)
COLT2 .res 8,$00 ; Color operator table
.res 8,$11
.res 8,$22
.res 8,$33
.res 8,$44
.res 8,$55
.res 8,$66
.res 8,$77
.res 8,$88
.res 8,$99
.res 8,$AA
.res 8,$BB
.res 8,$CC
.res 8,$DD
.res 8,$EE
.res 8,$FF
DCB_LN = *-DCB
L00F5 .res $0E,$00 ;some storage space
; duplicate DCB -- used when restoring configuration
CNTL_PARAM .byte $00
GMODE .byte $00 ;graphics mode
XFMODE .byte $00 ;transfer mode
XPOS .word $0000 ;cursor x-position
YPOS .word $0000 ; y-position
VPORT_L .word $0000 ;viewport left edge
VPORT_R .word $0117 ; right edge = 279.
VPORT_B .word $0000 ; bottom edge
VPORT_T .word $00BF ; top edge = 191.
PN_COL .byte $0F ;pencolor = white
F_COL .byte $00 ;fillcolor = black
FONT .word $0C00 ;Character font address
FONT_XB .byte $00 ; address X-Byte
FWIDTH .byte $07 ;character cell bit width
FHEIGHT .byte $08 ;character cell bit height
NOT_USED .byte $80 ; "Not currently used"
COL_TAB .res 8,$00 ; Color operator table
.res 8,$11
.res 8,$22
.res 8,$33
.res 8,$44
.res 8,$55
.res 8,$66
.res 8,$77
.res 8,$88
.res 8,$99
.res 8,$AA
.res 8,$BB
.res 8,$CC
.res 8,$DD
.res 8,$EE
.res 8,$FF
.byte "(C) 1980 Apple Computer"
OPENFLG .byte 00 ;open/close flag
L01B2 .byte 00 ;base addr-hi temp
L01B3 .byte 00 ;alt base addr-hi temp
BYT_OFF .word 0008 ;byte offset of a font character
L01B6 .byte 00 ; \
L01B7 .byte 00 ; bit pattern used
L01B8 .byte 00 ; in CLRVIEW
L01B9 .byte 00 ; /
CHR_TEMP .byte 00
CHR_INDX .byte 00 ;input buffer byte count
CHR_BUFF .res $20, 00 ;input buffer - copied from the D_WRITE buffer
WIDTH_B .byte 01 ;byte width of font character
L01DD .byte 00, 00, 00, 00, 00, 07, 00, 08, 00
L01E6 .byte 00, 00
L01E8 .byte 00
MVR_LO .byte $17, $17, $2F, $8B ;max viewport right, low byte (indexed)
MVT_LO .byte $BF ;max viewport top, low byte
MVR_HI .byte $01, $01, $02, $00 ;max viewport right, high byte
MVT_HI .byte $00 ;max viewport top, high byte
L01F3 .byte 00, 00, 01, 01, 02, 02, 03, 03, 00, 00, 01
L01FE .byte 01, 02, 02, 03, 03, 00, 00, 01, 01, 02, 02, 03, 03
L020B .byte $00,$80,$00,$80,$00,$80,$00,$80 ;base addr lo-byte, by y coord
.byte $28,$A8,$28,$A8,$28,$A8,$28,$A8
.byte $50,$D0,$50,$D0,$50,$D0,$50,$D0
L0223 .byte $20,$20,$20,$20,$40,$60,$60,$60 ;base addr hi-byte, by GMODE
;required-memory bits for gmodes 0..7 -- must be =< val in $1907 (MEM_FLAG)
; also doubles as alternate base-address_hi
REQD_MEM .byte $20,$40,$40,$40,$40,$80,$80,$80
L0233 .byte $00,$01,$1E,$60,$00,$07,$78
L023A .byte $0F,$70,$00,$03,$3C,$40,$00,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F
.byte $01,$02,$04,$08,$10,$20,$40,$80
L0250 .byte $15,$0E,$07,$00
L0254 .byte $0E,$0E,$1C,$07
L0258 .byte $03
L0259 .byte $04
L025A .byte $1C
START SWITCH REQCODE, 8, REQSW
BADREQ LDA #XREQCODE ;switch fell through -
JSR SYSERR ; Invalids request code error
NOTOPEN LDA #XNOTOPEN ;Graphics driver not open error
JSR SYSERR
REQSW = * ; dispatch table
.word D_READ-1
.word D_WRITE-1
.word D_STATUS-1
.word D_CONTRL-1
.word BADREQ-1 ;not implemented
.word BADREQ-1 ;not implemented
.word D_OPEN-1
.word D_CLOSE-1
.word D_INIT-1
D_INIT LDA #FALSE
STA OPENFLG ;set it as closed
RTS
D_OPEN BIT OPENFLG ;is it already open?
BPL @1
LDA #XNOTAVAIL ;yep -- it's not available,
JSR SYSERR ; complain, never returns
@1 JSR CONT0 ;initilize device
LDA #TRUE ;set it as open
STA OPENFLG
RTS
D_CLOSE ASL OPENFLG ;close it
BCS @1
JMP NOTOPEN ;but it's not open! complain
@1 RTS
D_STATUS BIT OPENFLG ;is it open?
BMI @1
JMP NOTOPEN
@1 SWITCH CTLSTAT, 2, STATSW
DST_ERR LDA #XCTLCODE ;invalid status code
JSR SYSERR
STATSW .word STAT0-1 ;NOP
.word STAT1-1 ;preserve status table
.word STAT2-1 ;unknown
STAT0 RTS ;nop
STAT1 LDY #$00 ;preserve status table
LDA (CSLIST),Y
CMP #DCB_LN
BCS @3
LDA #XCTLPARAM
JSR SYSERR
@3 LDA #DCB_LN
STA (CSLIST),Y
TAY
@4 LDA CNTL_PARAM,Y
STA (CSLIST),Y
DEY
BNE @4
RTS
STAT2 LDY #$00 ;Return newline status
LDA #$00 ; always =0, only satisfying the proper
STA (CSLIST),Y ; character count will terminate an input,
RTS ; as opposed to terminating at newline char
D_CONTRL BIT OPENFLG ;is it open?
BMI @1
JMP NOTOPEN
@1 SWITCH CTLSTAT, 2, CNTLSW
@2 JMP DST_ERR
CNTLSW .word CONT0-1 ;Device reset
.word CONT1-1 ;Restore status table
.word CONT2-1 ;NOP
CONT0 JSR L03A1 ;Reset
LDX #DCB_LN
@3 LDA CNFBLK+1,X
STA CNTL_PARAM,X
DEX
BNE @3
JSR L03C9
JSR L03BE
RTS
CONT1 LDY #$00 ;Restore status table
LDA (CSLIST),Y
CMP #DCB_LN
BEQ @4
LDA #XCTLPARAM
JSR SYSERR
@4 JSR L03A1
LDY #DCB_LN
@5 LDA (CSLIST),Y
DEY
STA CNTL_PARAM+1,Y
BNE @5
JSR L03C9
JSR L03BE
RTS
CONT2 RTS ;nop
D_READ BIT OPENFLG ;check if it's open
BMI @1
JMP NOTOPEN
@1 JSR L03A1 ;set up things
LDA XPOS+1 ;is XPOS<0000?
BMI @3 ; br if so
LDX ZPD5 ;is XPOS>MAX_VIEWPORT_RIGHT?
LDA MVR_LO,X
CMP XPOS
LDA MVR_HI,X
SBC XPOS+1
BCC @3 ; br if so
LDA YPOS+1 ;is YPOS<0000?
BMI @3 ; br if so
LDA MVT_LO ;is YPOS>MAX_VIEWPORT_TOP?
CMP YPOS
LDA MVT_HI
SBC YPOS+1
BCC @3 ; br if so
LDA YPOS
JSR CALCBASE ;calc base addr
LDA XPOS
LDY XPOS+1
JSR CALCBYTE ;calc byte offset
JSR L10CB ;read color at pen position
ORA #$40 ;add 64 (it's within screen boundaries)
@2 LDY #$00 ;put char into read buffer
STA (BUFFER),Y
STY RETPTR+1
INY
STY RETPTR ;RETPTR:=$0001
JMP L03BE ;reset & leave
@3 LDA #BITON7 ;flag that pen is out of screen boundary
BNE @2 ;always
L03A1 LDX #$0E ;setup things: restore stuff to zpage
@1 LDA L00F5,X
STA ZPCA,X
DEX
BPL @1
LDX #$35
LDA #$00
@2 STA ZPC9+$1401,X
DEX
BPL @2
LDA #$8F ;X-BYTE for graphics
STA ZPCA+$1401
STA ZPCC+$1401
RTS
L03BE LDX #$0E ;reset things: save stuff from zpage
@1 LDA ZPCA,X
STA L00F5,X
DEX
BPL @1
RTS
; Verify Grafix parms (?) -- lots of jumps to here
L03C9 LDA GMODE ;filter and check out GRAFIXMODE
AND #$07
STA GMODE
TAY
AND #$03 ;filter out page bit (page 1/page 2)
STA ZPD5
TAX
LDA L0223,Y ;base addr hi-byte
STA L01B2
LDA REQD_MEM,Y
STA L01B3
LDA #$00
STA L01E6
STA L01E8
LDA #$F0
STA ZPD0
LDA F_COL ;check out FILL COLOR
ASL A
ASL A
ASL A
ASL A ;times 16
ORA F_COL ;copies low nybble into hi nybble
PHA
BEQ @1 ;branch if fill color is black
CPX #$03 ;X-reg contains GMODE
BEQ @2 ;br if GMODE=3 (140x192 full color)
DEX
TXA
BEQ @1
LDA #$FF
@1 LDX #$03
@2 TAY
LSR A
STA L01B6,X
TYA
ROR A
TAY
DEX
BPL @2
PLA
LDX ZPD5
DEX
BNE @3
STA L01B7
STA L01B9
@3 LDX #$00
STX ZPD6
STX ZPD7
STX ZPD8
LDA XFMODE ;check out transfer mode
AND #$07
STA XFMODE ;filter it
LSR A
ROR ZPD6
LSR A
ROR ZPD6
BIT ZPD6
BVC @4
BPL @4
EOR #$01
@4 LSR A
ROR ZPD7
LDA #$FF ;check out the color table
LDX #$7F
@5 LDY #$08
@6 CMP COL_TAB,X
BNE @7
DEX
DEY
BNE @6
SEC
SBC #$11
BCS @5
BCC @8 ;always
@7 LDA ZPD7
ORA #$40
STA ZPD7
@8 LDA #$00 ;check out the font
LDX #$09
@9 STA WIDTH_B,X ;width_b .. width_b+9 := 00
DEX
BPL @9
STA BYT_OFF ;set both to zero
STA BYT_OFF+1
LDA FONT_XB
STA ZPD3+$1401
LDA FONT+1 ;check if the font is the system font
CMP #$0C
BNE @10 ;is hi-byte = $0C?, br if not
LDA FONT_XB
BNE @10 ;is x-byte = $00, br if not
STA ZPD8
BNE @11 ;never branches, why is this here? bug?
LDX #$07 ;it's the system font (00:0C00), set it up
STX FWIDTH ;width := 7
INX
STX FHEIGHT ;height := 8
JMP @11
@10 LDA NOT_USED
STA ZPD8
@11 LDX FWIDTH
BEQ @12
DEX
TXA
LSR A
LSR A
LSR A
TAX
INX ;(FWIDTH-1) div 8 +1
STX WIDTH_B ; width of font in bytes
@12 LDX FHEIGHT
BEQ @14
@13 CLC ;calculate total # of bytes of
LDA WIDTH_B ; a single character
ADC BYT_OFF
STA BYT_OFF
LDA BYT_OFF+1
ADC #$00
STA BYT_OFF+1
DEX
BNE @13 ;BYT_OFF=FHEIGHT * WIDTH_B
@14 LDX #$06 ;check out the viewport definitions
L15 LDA VPORT_L+1,X
BPL @16 ;if it's negative, set it to zero
LDA #$00
STA VPORT_L,X
STA VPORT_L+1,X ;set viewport left, right, top, bott := 0000
@16 DEX
DEX
BPL L15 ;loop back
LDX #$06
LDY #$04
@17 LDA MVR_LO,Y ;is vport set beyond max size of the screen
CMP VPORT_L,X ; for this grafix mode?
LDA MVR_HI,Y
SBC VPORT_L+1,X
BCS @18
LDA MVR_LO,Y ;Yes, so set it to the max allowed
STA VPORT_L,X
LDA MVR_HI,Y
STA VPORT_L+1,X
@18 DEX
DEX
BMI @19
CPX #$04
BCS @17
LDY ZPD5
BCC @17
@19 LDX #$04
@20 LDA VPORT_R,X
CMP VPORT_L,X
LDA VPORT_R+1,X
SBC VPORT_L+1,X ;check if left & right are reversed
BCS @21 ; branch if they're OK
LDY VPORT_L,X ; otherwise, turn them around the right way
LDA VPORT_R,X
STA VPORT_L,X
TYA
STA VPORT_R,X
LDY VPORT_L+1,X
LDA VPORT_R+1,X
STA VPORT_L+1,X
TYA
STA VPORT_R+1,X
@21 DEX
DEX
DEX
DEX
BPL @20
BIT SCR_MODE
BVC @29
BMI @22
LDA $01FE ;;;;;L01FE this seems like a bug as these are absolute addresses!
AND #$DF
STA $01FE ;;;;;L01FE
JMP @29
@22 LDA $01FE ;;;;;L01FE
ORA #$20
STA $01FE ;;;;;L01FE
LDA SCR_MODE
LSR A
BCS @23
BIT SETBW ;turn on the B&W mode
BCC @24 ; always
@23 BIT SETCOL ;turn on the color mode
@24 LSR A
BCS @25
BIT COLM40 ;40 column mode
BCC @26 ; always
@25 BIT COLM80 ;80 column mode
@26 LSR A
BCS @27
BIT LOWSCR ;page one
BCC @28 ; always
@27 BIT HISCR ;page two
@28 BIT HIRES ;turn on the graphics screen
@29 RTS
D_WRITE BIT OPENFLG ;but are we open?
BMI @1 ; br if open
JMP NOTOPEN
@1 LDX GMODE
LDA MEM_FLAG ;memory allocation flag byte
CMP REQD_MEM,X ;see if proper amt of mem is allocated
BCS @2 ; br if OK
LDA #XBADMEM ;sorry, not enough memory for this mode
JSR SYSERR ; report the problem & leave
@2 JSR L03A1
LDA #$00
STA RETPTR
STA RETPTR+1
@3 LDA RETPTR+1 ;check if all the chars in
CMP REQCNT+1 ; this DßWRITE call have been
BCC @4 ; carefully scrutinized.
LDA RETPTR
CMP REQCNT ; If all finished, jump out, otherwise
BCC @4 ; branch down a few bytes.
JMP L03BE
@4 LDY #$00
LDA (BUFFER),Y ;get the next character in the buffer
INCADR BUFFER ;increment the address pointer to the next byte
INW RETPTR ;increment the # of bytes handled
JSR @5 ;check out the current character
JMP @3 ;loop back for the next character
@5 LDX CHR_TEMP
BEQ @7 ;br if a call is not currently being processed
LDY CHR_INDX ;load the index
STA CHR_BUFF-1,Y ;note: first byte stored at CHR_BUFF
INY ;incr index
TYA
CMP CALL_LEN,X ;Are all the bytes in this call present?
BCS @6 ; br if all present
STY CHR_INDX ;otherwise, store index,
RTS ; and get some more bytes
@6 LDA CHR_TEMP ;all chars present, process call
LDY #$00 ; ...but first, reset some things
STY CHR_TEMP ; for the next time around
STY CHR_INDX ;clear index & temp
JMP CON_CHR ;now -- handle the call
@7 CMP #$20 ;is it a control character?
BCC @8 ; br if so
JMP L0618 ;nope -- print the char onto the screen
@8 TAX
LDA CALL_LEN,X ;get parm length for this call
BEQ @9 ; br if this isn't a valid call -- i.e. NOP
STX CHR_TEMP ;store the cntrl char here
CMP #$01 ;parm length=1?
BEQ @6 ; br if call doesn't have any parms (go to it!)
LDA #$01
STA CHR_INDX ;initially put a one here -- used for indexing
@9 RTS
; This list contains the total length (in bytes) of each control
; character call, including the control character itself.
; Ex.: chr(00) -- 0 bytes (nop)
; chr(03) -- 6 bytes (char_set)
CALL_LEN .byte $00,$01,$09,$06,$0E,$00,$00,$00 ;chr( 0)..chr( 7)
.byte $00,$00,$01,$00,$00,$01,$01,$01 ;chr( 8)..chr(15)
.byte $02,$01,$06,$02,$02,$02,$00,$00 ;chr(16)..chr(23)
.byte $05,$05,$05,$00,$01,$00,$00,$00 ;chr(24)..chr(31)
; set up to put a character on the graphics screen
L0618 CMP #$A0
BCS @1 ; br is char >= $A0
CMP #$80
BCC @1 ; br if char < $80
AND #$7F ;clear hi-bit
@1 LDX FWIDTH ;copy font info into temp locations
STX L01DD+5
LDX FHEIGHT
STX L01DD+7
LDX #$00
STX L01DD+6
STX L01DD+8
LDX FONT ;copy font addrs into z-page locations
STX ZPD3
LDX FONT+1
STX ZPD4
LDX FONT_XB
STX ZPD3+$1401
TAX
BEQ @4
@2 CLC
LDA ZPD3 ;set up addr of font character
ADC BYT_OFF ;char_addr:= base_addr + (char# * byte_offset)
STA ZPD3
LDA ZPD4
ADC BYT_OFF+1
STA ZPD4
BCC @3
INC ZPD3+$1401
INC ZPD3+$1401
@3 DEX
BNE @2
@4 JSR PUTres ;put font char on screen
CLC ;update X & Y position after
LDA XPOS ; putting char on screen
ADC FWIDTH
STA XPOS
LDA XPOS+1
ADC #$00
STA XPOS+1
RTS
; Handle those control characters....
CON_CHR SWITCH ,,CHARS
CHARS .word CHR_NOP-1
.word RSTVIEW-1 ;01 Reset Viewport
.word SETVIEW-1 ;02 Set Viewport
.word CHARSET-1 ;03 Character Set
.word DRAWBLK-1 ;04 Drawres
.word CHR_NOP-1
.word CHR_NOP-1
.word CHR_NOP-1
.word CHR_NOP-1
.word CHR_NOP-1
.word MOV_PDN-1 ;10. Move Pen Down (LF)
.word CHR_NOP-1
.word CHR_NOP-1
.word RET_PEN-1 ;13. Return Pen (CR)
.word SCRNOFF-1 ;14. Turn Graphics Screen Off
.word SCRN_ON-1 ;15. Turn Graphics Screen On
.word SETMODE-1 ;16. Set Graphics Mode
.word RSTCOLT-1 ;17. Reset Color Operator Table
.word SETCOLT-1 ;18. Set Color Operator Table
.word SETPCOL-1 ;19. Set Pen Color
.word SETFCOL-1 ;20. Set Fill Color
.word SETXMOD-1 ;21. Set Transfer Mode
.word CHR_NOP-1
.word CHR_NOP-1
.word LINE_TO-1 ;24. Draw Line to X,Y
.word DOT_AT-1 ;25. Plot Point at X,Y
.word MOVE_TO-1 ;26. Move Pen to X,Y
.word CHR_NOP-1
.word CLRVIEW-1 ;28. Clear Viewport
.word CHR_NOP-1
.word CHR_NOP-1
.word CHR_NOP-1
CHR_NOP RTS
SETMODE LDA CHR_BUFF ;set graphics mode
STA GMODE
JMP L03C9
SETXMOD LDA CHR_BUFF ;set transfer mode
STA XFMODE
JMP L03C9
SCRNOFF LDA GMODE ;turn screen off
AND #$07
ORA #$40
STA SCR_MODE
JMP L03C9
SCRN_ON LDA GMODE ;enable graphics mode
AND #$07
ORA #$C0
STA SCR_MODE
JMP L03C9
MOV_PDN SEC ;move pen down (LF)
LDA YPOS ;subtract font height from the
SBC FHEIGHT ; current x,y position
STA YPOS
LDA YPOS+1
SBC #$00
STA YPOS+1
RTS
RET_PEN LDA VPORT_L ;return pen (CR)
STA XPOS ;set x position to the left
LDA VPORT_L+1 ; viewport edge
STA XPOS+1
RTS
CHARSET LDX #$04 ;character set
@1 LDA CHR_BUFF,X ;store chacter set address
STA FONT,X
DEX
BPL @1
JMP L03C9
RSTVIEW LDX ZPD5 ;reset viewport
LDA #$00
STA VPORT_L
STA VPORT_L+1
STA VPORT_B
STA VPORT_B+1 ;left & bottom := 0
LDA MVR_LO,X
STA VPORT_R ;viewport-right := max right value
LDA MVR_HI,X
STA VPORT_R+1
LDA MVT_LO ;viewport-top := max top value
STA VPORT_T
LDA MVT_HI
STA VPORT_T+1
RTS
SETVIEW LDX #$08 ;set viewport
@1 LDA CHR_BUFF-1,X
STA VPORT_L-1,X
DEX
BNE @1
JMP L03C9
RSTCOLT LDX #$7F ;reset color table
@1 LDA COLT2,X
STA COL_TAB,X
DEX
BPL @1
JMP L03C9
SETCOLT LDA CHR_BUFF+4 ;set color table
AND #$0F
STA CHR_BUFF+4
ASL A
ASL A
ASL A
ASL A
ORA CHR_BUFF+4
STA CHR_BUFF+4
CLV
LDX #$0F
LDA CHR_BUFF
@1 ASL A
BCC @7
PHA
LDY #$0F
LDA CHR_BUFF+2
@2 ASL A
BCC @5
PHA
STY CHR_BUFF
TXA
PHA
ASL A
ASL A
ASL A
LSR CHR_BUFF
ORA CHR_BUFF
TAX
LDA COL_TAB,X
EOR CHR_BUFF+4
BCS @3
AND #$0F
BCC @4
@3 AND #$F0
@4 EOR CHR_BUFF+4
STA COL_TAB,X
PLA
TAX
PLA
@5 DEY
BMI @6
CPY #$07
BNE @2
LDA CHR_BUFF+3
BVC @2
@6 PLA
@7 DEX
BMI @8
CPX #$07
BNE @1
LDA CHR_BUFF+1
BVC @1
@8 JMP L03C9
SETPCOL LDA CHR_BUFF ;set pen color
AND #$0F
STA PN_COL
RTS
SETFCOL LDA CHR_BUFF ;set fill color
AND #$0F
STA F_COL
JMP L03C9
MOVE_TO LDX #$03 ;move to
@1 LDA CHR_BUFF,X
STA XPOS,X
DEX
BPL @1
RTS
DOT_AT LDX #$03 ;dot at
@1 LDA CHR_BUFF,X
STA XPOS,X
STA ZPF5,X ; ZPF5..ZPF8
STA ZPF0,X ; ZPF0..ZPF3
DEX
BPL @1
JSR L0C21 ;out of bounds?
BCS @2 ;yep. Don't bother displaying it
JMP L0F9D ;Display it
@2 RTS
LINE_TO LDX #$03 ;line to
@1 LDA XPOS,X
STA ZPF0,X ; ZPF0..ZPF3
LDA CHR_BUFF,X
STA XPOS,X
STA ZPF5,X ; ZPF5..ZPF8
DEX
BPL @1
JSR L0C21
BCS @2
JSR L0F9D
JMP L0F02
@2 RTS
CLRVIEW LDX #$0A ;clear viewport
@1 LDA ZPCA,X
PHA
DEX
BPL @1
LDA #$F0
STA L01E6
LDA VPORT_T
JSR CALCBASE ;calc base addr
SEC
LDA VPORT_T
SBC VPORT_B
STA ZPE8
INC ZPE8
LDA #$00
STA ZPF5
STA ZPF6
LDA VPORT_L
LDY VPORT_L+1
JSR CALCBYTE ;calc byte offset
STA ZPF2
LDX ZPD5
CPX #$03
BEQ @2
LDA #$0F
STA ZPD0
@2 LDX #$04
@3 LDA ZPCE,X
STA ZPE9,X
DEX
BPL @3
LDA ZPD7
ORA ZPD6
BEQ @5
CLC
LDA VPORT_L
SBC VPORT_R
STA ZPF3
LDA VPORT_L+1
SBC VPORT_R+1
STA ZPF4
DEC ZPF3
BNE @4
DEC ZPF4
@4 JMP CL19 ; (@19)
@5 STX ZPF3
STX ZPF4
LDA ZPCF
LDX ZPD5
CPX #$03
BNE @6
EOR #$0F
@6 CMP #$02
JSR CL29 ; (@29)
BEQ @9
INC ZPF2
AND #$03
LSR A
BNE @7
INC ZPF2
@7 ROL A
JSR CL30 ; (@30)
EOR #$FF
STA ZPF3
TXA
LDX #$15
CMP #$03
BNE @8
LDX #$07
@8 DEX
DEC ZPF3
LDA L023A,X
CMP ZPCF
BNE @8
LDA L0233,X
CMP ZPD0
BNE @8
@9 LDA VPORT_R
LDY VPORT_R+1
JSR CALCBYTE ;calc byte offset
STA ZPF7
LDX ZPD5
CPX #$02
BEQ @10
SEC
ROR ZPD2
@10 CPX #$03
BCC @11
LDA ZPD0
CMP #$78
JMP @12
@11 LDA ZPCF
CMP #$40
@12 JSR CL29 ; (@29)
EOR #$07
TAY
BNE @13
INC ZPF7
BPL @14
@13 AND #$02
BNE @14
DEC ZPF7
@14 TYA
BEQ @16
AND #$03
JSR CL30 ; (@30)
STA ZPF6
TXA
LDX #$0D
CMP #$03
BNE @15
LDX #$FF
@15 INX
INC ZPF6
LDA L023A,X
CMP ZPCF
BNE @15
LDA L0233,X
CMP ZPD0
BNE @15
@16 SEC
LDA ZPF7
SBC ZPF2
BMI @17
LSR A
STA ZPF5
BNE CL19 ; (@19)
SEC
LDA ZPF3
BCS @18
@17 LDA ZPF3
LDX ZPD5
ADC L0254,X
@18 SBC ZPF6
STA ZPF3
LDA #$00
STA ZPF6
CL19 LDX #$04
@20 LDA ZPF3,X
STA ZPEE,X
LDA ZPE9,X
STA ZPCE,X
DEX
BPL @20
TAY
@21 INC ZPEE
BNE @22
INC ZPEF
BNE @22
JMP @23
@22 JSR L09B6
JMP @21
@23 DEC ZPF0
BMI @25
LDX #$00
@24 LDA L01B6,X
STA (ZPCA),Y
LDA L01B7,X
STA (ZPCC),Y
INY
INX
INX
CPX #$02
BEQ @24
BNE @23 ;always
@25 STY ZPCE
DEC ZPF1
BMI @26
JSR L09B6
JMP @25
@26 DEC ZPE8
BEQ @27
JSR L0E16
JMP CL19
@27 LDX #$00
@28 PLA
STA ZPCA,X
INX
CPX #$0B
BNE @28
LDA #$00
STA L01E6
RTS
CL29 ROL A
ROR ZPCE
ROL A
ROL ZPD2
ROL A
AND #$07
RTS
CL30 TAY
CPX #$02
BEQ @31
LDY #$03
BCS @31
CMP #$02
BCS @31
DEY
@31 LDA L0250,Y
RTS
L09B6 JSR L0FAA
JSR L0EA7
RTS
DRAWBLK LDA ZPD8
PHA
LDA NOT_USED
STA ZPD8
LDX #$09
@1 LDA WIDTH_B,X
PHA
LDA CHR_BUFF+3,X
STA WIDTH_B,X
DEX
BPL @1
LDA CHR_BUFF
STA ZPD3
LDA CHR_BUFF+1
STA ZPD4
LDA CHR_BUFF+2
STA ZPD3+$1401
JSR PUTres ;put res onto graphics screen
LDX #$00
@2 PLA
STA WIDTH_B,X
INX
CPX #$0A
BCC @2
PLA
STA ZPD8
RTS
; =====================================================================
;
; HARDWARE SPECIFIC CODES FOLLOWS....
;
; =====================================================================
PUTres ;put character/res onto graphics screen
LDX #$03
LDA #$F0
STA L01E8
@4 LDA XPOS,X
STA ZPF5,X
DEX
BPL @4
SEC
LDA VPORT_L
SBC ZPF5
STA ZPD9
LDA VPORT_L+1
SBC ZPF6
STA ZPDA
BMI @5
SEC
LDA L01DD+5
SBC ZPD9
STA L01DD+5
LDA L01DD+6
SBC ZPDA
STA L01DD+6
BMI @7
LDA VPORT_L
STA ZPF5
LDA VPORT_L+1
STA ZPF6
BIT ZPD8
BPL @5
CLC
LDA L01DD+1
ADC ZPD9
STA L01DD+1
LDA L01DD+2
ADC ZPDA
STA L01DD+2 ;(L01DD+1):=(L01DD+1)+ZPD9
@5 CLC
LDA ZPF5
ADC L01DD+5
STA ZPD9
LDA ZPF6
ADC L01DD+6
STA ZPDA
SEC
LDA ZPD9
SBC VPORT_R
STA ZPD9
LDA ZPDA
SBC VPORT_R+1
STA ZPDA
BMI @8
INC L01DD+5
BNE @6
INC L01DD+6
@6 SEC
LDA L01DD+5
SBC ZPD9
STA L01DD+5
LDA L01DD+6
SBC ZPDA
STA L01DD+6
BPL @8
@7 RTS
@8 SEC
LDA ZPF7
SBC VPORT_T
STA ZPD9
LDA ZPF8
SBC VPORT_T+1
STA ZPDA
BMI @10
SEC
LDA L01DD+7
SBC ZPD9
STA L01DD+7
LDA L01DD+8
SBC ZPDA
STA L01DD+8
BMI @7
BNE @9
LDA L01DD+7
BEQ @7
@9 LDA VPORT_T
STA ZPF7
LDA VPORT_T+1
STA ZPF8
CLC
LDA L01DD+3
ADC ZPD9
STA L01DD+3
LDA L01DD+4
ADC ZPDA
STA L01DD+4
@10 SEC
LDA ZPF7
SBC VPORT_B
STA ZPE8
LDA ZPF8
SBC VPORT_B+1
STA ZPE9
BMI @7
SEC
LDA ZPF7
SBC L01DD+7
STA ZPD9
LDA ZPF8
SBC L01DD+8
STA ZPDA
SEC
LDA ZPD9
SBC VPORT_B
STA ZPD9
LDA ZPDA
SBC VPORT_B+1
STA ZPDA
BPL @11
INC ZPE8
BNE @12
@11 SEC
LDA ZPE8
SBC ZPD9
STA ZPE8
LDA ZPE9
SBC ZPDA
STA ZPE9
@12 LDX #$0A
@13 LDA ZPCA,X
PHA
DEX
BPL @13
LDA ZPF7
JSR CALCBASE ;calc base addr
LDA ZPF5
LDY ZPF6
JSR CALCBYTE ;calc byte offset
LDX #$04
@14 LDA ZPCE,X
STA ZPE9,X
DEX
BPL @14
CLC
LDA L01DD+1
ADC L01DD+5
STA ZPD9
LDA L01DD+2
ADC L01DD+6
STA ZPDA
LDA L01DD+1
AND #$07
STA ZPEF
LDA ZPD9
AND #$07
STA ZPF1
LDA L01DD+1
ROR L01DD+2
ROR A
ROR L01DD+2
ROR A
ROR L01DD+2
ROR A
STA ZPEE
LDA ZPD9
ROR ZPDA
ROR A
ROR ZPDA
ROR A
ROR ZPDA
ROR A
STA ZPF0
DB15 LDA L01DD+3
BNE @16
LDA L01DD+4
BEQ @18
@16 CLC
LDA ZPD3
ADC WIDTH_B
STA ZPD3
LDA ZPD4
ADC L01DD
STA ZPD4
BCC @17
INC ZPD3+$1401
INC ZPD3+$1401
@17 LDA L01DD+3
SEC
SBC #$01
STA L01DD+3
LDA L01DD+4
SBC #$00
STA L01DD+4
JMP DB15
@18 LDX #$04
@19 LDA ZPE9,X
STA ZPCE,X
DEX
BPL @19
LDY ZPEE
STY ZPF2
LDA (ZPD3),Y
LDX #$00
@20 CPX ZPEF
BEQ @21
ASL A
INX
BNE @20
@21 STA ZPF4
@22 STX ZPF3
CPX ZPF1
BNE @23
LDA ZPF2
CMP ZPF0
BEQ @27
@23 LDY ZPCE
BIT ZPD8
BMI @24
LSR ZPF4
BPL @25
@24 ASL ZPF4
@25 LDA #$00
BCS @26
LDA #$F0
@26 STA L01E6
JSR L09B6
LDX ZPF3
INX
CPX #$08
BNE @22
LDX #$00
INC ZPF2
LDY ZPF2
LDA (ZPD3),Y
STA ZPF4
JMP @22
@27 DEC ZPE8
BEQ @29
JSR L0E16
CLC
LDA ZPD3
ADC WIDTH_B
STA ZPD3
LDA ZPD4
ADC L01DD
STA ZPD4
BCC @28
INC ZPD3+$1401
INC ZPD3+$1401
@28 JMP @18
@29 LDX #$00
@30 PLA
STA ZPCA,X
INX
CPX #$0B
BNE @30
LDA #$00
STA L01E6
STA L01E8
RTS
; See "Principles of Interactive Computer Graphics", second edition
; Newman & Sproull, pages 65-68
L0C21 LDY #$0F
JSR L0D00 ;check bounds
STA ZPF4
LDY #$14
JSR L0D00 ;check bounds
STA ZPF9
@1 LDA ZPF9
ORA ZPF4
AND #$0F
BNE @2
CLC ;both endpoints are within the viewport
RTS
@2 LDA ZPF4
AND ZPF9
AND #$0F
BEQ @4
SEC ;both endpoints are outside viewport and the
@3 RTS ; line does not enter viewport
@4 LDA ZPF4 ;both endpoints outside, but check if the
AND #$0F ; line crosses into the viewport
BEQ @5
LDX #$00
LDY #$0F
JSR L0D59 ;copy
LDX #$05
LDY #$14
JSR L0D59 ;copy
JSR @6 ;midpoint subdivision
BCS @3
LDX #$0F
LDY #$0A
JSR L0D59 ;copy
BEQ @1
@5 LDA ZPF9
AND #$0F
BEQ @1
LDX #$00
LDY #$14
JSR L0D59 ;copy
LDX #$05
LDY #$0F
JSR L0D59
JSR @6
BCS @3
LDX #$14
LDY #$0A
JMP L0D59
; ---- Mid-Point Subdivision ----
@6 LDA ZPE5 ;border bits (from)
EOR ZPEA ; (to)
AND ZPE5
ASL A
ASL A
ASL A
ASL A ;mul 16 (move lo nybble to hi)
STA ZPDF
AND ZPEA
BEQ @8 ;br to try it out
LDA ZPEA
AND #$0F
BNE @7 ;br if it's completely outside
LDX #$0A
LDY #$05
CLC
JMP L0D59
@7 SEC ;completely outside viewport
RTS
@8 STA ZPDB
STA ZPDD
@9 ROL ZPDB
LDA ZPE1 ;XPOS (from)
ADC ZPE6 ;XPOS (to)
STA ZPEB
LDA ZPE2 ;XPOS+1 (from)
ADC ZPE7 ;XPOS+1 (to)
BVS @10
CMP #$80
@10 ROR A ;div 2
STA ZPEC
ROR ZPEB ;div 2
ROR ZPDB
ROL ZPDD
LDA ZPE3 ;YPOS (from)
ADC ZPE8 ;YPOS (to)
STA ZPED
LDA ZPE4 ;YPOS+1 (from)
ADC ZPE9 ;YPOS+1 (to)
BVS @11
CMP #$80
@11 ROR A ;div 2
STA ZPEE
ROR ZPED ;div 2
ROR ZPDD
LDY #$0A
JSR L0D00 ;check if the midpoint is inside vport
STA ZPEF
AND ZPE5
AND #$0F
BEQ @13 ;br if inside viewport
LDX #$00
JSR L0D59
LDA ZPE5
AND ZPEA
AND #$0F
BEQ @9
@12 CLC ;completely inside viewport
RTS
@13 LDA ZPEF
AND ZPDF
BNE @12 ;all done
LDX #$05
JSR L0D59
BEQ @9 ;go around for another try
; CHECK VIEWPORT BOUNDS inside outside
; bit # 7 6 5 4 3 2 1 0
; leaves flag in acc -> T B R L T B R L
L0D00 LDA #$00 ;check viewport bounds
LDX ZPE2,Y ;XPOS+1
BMI @6 ; br if neg -- outside viewport
CPX VPORT_L+1
BCC @6 ; br if VPORT_L+1>XPOS+1
BNE @2 ; br if not equal
LDX ZPE1,Y ;XPOS
CPX VPORT_L
BCC @6 ; br if VPORT_L>XPOS
BEQ @5 ; br if equal
@1 LDX ZPE2,Y ;XPOS+1
@2 CPX VPORT_R+1
BCC @7 ; br if VPORT_R+1>XPOS+1
BNE @3 ; br if not equal
LDX ZPE1,Y ;XPOS
CPX VPORT_R
BCC @7 ; br if VPORT_R>XPOS
BEQ @4 ; br if equal
@3 ORA #BITON1 ;outside of the right edge
BNE @7 ; always
@4 ORA #BITON5 ;inside of the right edge
BNE @7 ; always
@5 ORA #BITON4 ;inside of the left edge
BNE @1 ; always -- go check right edge
@6 ORA #BITON0 ;outside of the left edge
@7 LDX ZPE4,Y ;YPOS+1
BMI @12 ; br if neg -- outside
BNE @9 ; br if hi-byte is not zero -- outside
LDX ZPE3,Y ;YPOS
CPX VPORT_B
BCC @12
BEQ @11
@8 CPX VPORT_T
BEQ @10 ; br if equal
BCC @13 ; br if VPORT_T>YPOS
@9 ORA #BITON3 ;above top edge (outside)
RTS
@10 ORA #BITON7 ;at top edge (inside)
RTS
@11 ORA #BITON6 ;at bottom edge (inside)
BNE @8 ; br always -- go check top edge
@12 ORA #BITON2 ;below bottom edge (outside)
@13 RTS
L0D59 LDA #$05
STA ZPE0
@1 LDA ZPE1,Y
STA ZPE1,X
INX
INY
DEC ZPE0
BNE @1
RTS
CALCBASE ;Calculate base address -- ACC:=YPOS
STA ZPD9
SEC
LDA #$BF
SBC ZPD9
TAY
LSR A
LSR A
LSR A ;div 8
TAX
TYA
ASL A
ASL A ;mul 4
AND #$1C
ORA L01F3,X
TAY
ORA L01B2
STA ZPCB
TYA
ORA L01B3
STA ZPCD
LDA L020B,X
STA ZPCA
STA ZPCC
STX ZPE7
RTS
CALCBYTE ;Calculate byte offset -- ACC:=XPOS, Y_REG:=XPOS+1
SEC
BEQ @3 ; br if XPOS+1=00
DEY
BEQ @1
LDY #$48 ;gets here when X_HI=2
ADC #$01
BCC @2 ; br if XPOS<=255
@1 LDY #$23 ;gets here when X_HI=1
ADC #$04
BCC @2
INY
SBC #$07
@2 INY
@3 SBC #$07 ; DIV 7 -- the old-fashioned way
BCS @2
TAX ; remainder into X
TYA
LDY COL_TAB+$35,X
STY ZPCF
LDY ZPD5
CPY #$02
STY ZPD2
BCC @4
BEQ @5
ASL A
LDY COL_TAB+$20,X
STY ZPD0
LDY COL_TAB+$27,X
STY ZPCF
STX ZPD1 ;remainder (in 2's complement form)
CPX #$FC
ADC #$00
@4 STA ZPCE ;byte offset
RTS ; something get left in ACC
@5 LSR A
STA ZPCE ;byte offset
ROR ZPD2
RTS
L0DD8 BPL L0E16
CLC
LDA ZPCB
BIT L025A
BNE L0E08
ASL ZPCA
BCS L0E00
BIT L0258
BEQ L0DF0
ADC #$1F
SEC
BCS L0E02
L0DF0 ADC #$23
PHA
LDA ZPCA
ADC #$B0
BCS L0DFB
ADC #$F0
L0DFB STA ZPCA
PLA
BCS L0E02
L0E00 ADC #$1F
L0E02 ROR ZPCA
LDX ZPCA
STX ZPCC
L0E08 ADC #$FC
L0E0A STA ZPCB
AND #$1F
STA ZPE7
ORA L01B3
STA ZPCD
RTS
L0E16 CLC
LDA ZPCB
ADC #$04
BIT L025A
BNE L0E0A
ASL ZPCA
BCC L0E3E
ADC #$E0
CLC
BIT L0259
BEQ L0E40
LDA ZPCA
ADC #$50
EOR #$F0
BEQ L0E36
EOR #$F0
L0E36 STA ZPCA
LDA ZPCB
AND #$E0
BCC L0E40
L0E3E ADC #$E0
L0E40 ROR ZPCA
LDX ZPCA
STX ZPCC
BCC L0E0A
L0E48 BVS L0E4D
JMP L0EA7
L0E4D LDX ZPD5
CPX #$02
BEQ L0E6B
BCS L0E84
LSR ZPCF
BCC L0E6A
DEY
BPL L0E64
L0E5C ROL ZPCF
INY
STY ZPCE
RTS
L0E62 LDY #$27
L0E64 LDA #$40
STA ZPCF
STY ZPCE
L0E6A RTS
L0E6B LSR ZPCF
BCC L0E6A
LDA #$40
STA ZPCF
ASL A
EOR ZPD2
STA ZPD2
BPL L0E6A
DEY
STY ZPCE
BPL L0E6A
LSR ZPD2
SEC
BCS L0E5C
L0E84 LDX ZPD1
CPX #$FC
BNE L0E8B
DEY
L0E8B DEX
CPX #$F9
BCS L0E98
LDX #$FF
DEY
BPL L0E98
INY
LDX #$F9
L0E98 STY ZPCE
STX ZPD1
LDA COL_TAB+$27,X
STA ZPCF
LDA COL_TAB+$20,X
STA ZPD0
RTS
L0EA7 LDX ZPD5
CPX #$02
BEQ @3
BCS @4
ASL ZPCF
BPL @2
INY
CPY #$28
BCC @1
JMP L0E62
@1 LDA #$01
STA ZPCF
STY ZPCE
@2 RTS
@3 ASL ZPCF
BPL @2
LDA #$01
STA ZPCF
LDA #$FF
EOR ZPD2
STA ZPD2
BMI @2
INY
STY ZPCE
CPY #$28
BCC @2
ROR ZPD2
JMP L0E62
@4 LDX ZPD1
CPX #$FB
BNE @5
INY
@5 INX
BNE @6
LDX #$F9
INY
CPY #$28
BCC @6
LDX #$FF
LDY #$27
@6 STY ZPCE
STX ZPD1
LDA COL_TAB+$20,X
STA ZPD0
LDA COL_TAB+$27,X
STA ZPCF
RTS
L0F02 SEC
LDA ZPF5
SBC ZPF0
PHA
LDA ZPF6
SBC ZPF1
STA ZPD9
BCS @1
PLA
EOR #$FF
ADC #$01
PHA
LDA #$00
SBC ZPD9
@1 STA ZPDE
PLA
STA ZPDD
SEC
LDA ZPF7
SBC ZPF2
BCS @2
EOR #$FF
ADC #$01
@2 STA ZPDB
ROR ZPD9
LDY ZPCE
LDX ZPDE
BNE @3
CMP ZPDD
BCS @7
@3 STX ZPE2
TXA
LSR A
STA ZPE4
LDA ZPDD
BNE @4
DEC ZPE2
@4 STA ZPE1
ROR A
STA ZPE3
@5 LDA ZPE3
SEC
SBC ZPDB
STA ZPE3
BCS @6
DEC ZPE4
BPL @6
ADC ZPDD
STA ZPE3
LDA ZPE4
ADC ZPDE
STA ZPE4
LDA ZPD9
JSR L0DD8
@6 BIT ZPD9
JSR L0E48
JSR L0FAA
DEC ZPE1
BNE @5
DEC ZPE2
BPL @5
RTS
@7 STA ZPE1
TAX
BEQ @10
LSR A
STA ZPE4
@8 LDA ZPE4
SEC
SBC ZPDD
STA ZPE4
BCS @9
ADC ZPDB
STA ZPE4
BIT ZPD9
JSR L0E48
@9 LDA ZPD9
JSR L0DD8
JSR L0FAA
DEC ZPE1
BNE @8
@10 RTS
L0F9D LDA ZPF2 ;JSR, JMP from LINETO
JSR CALCBASE ;calc base addr
LDA ZPF0
LDY ZPF1
JSR CALCBYTE ;calc byte offset
TAY
L0FAA BIT ZPD7
LDX ZPD5
DEX
BEQ @5
LDA L01E6
ASL A
LDA PN_COL
BCC @1
LDA F_COL
@1 CPX #$02
BNE @2
JMP L1054
@2 BVC @3
JSR L1199
@3 CMP #$00
BEQ @4
LDA ZPCF
@4 JMP L1081
@5 BIT ZPE7
BPL @6
CPY ZPE5
BEQ @8
@6 LDA F_COL
STA ZPDF
LDA PN_COL
STA ZPE0
BIT ZPD7
BVC @7
LDA L01E6
PHA
LDA #$F0
STA L01E6
SEC
JSR L11AB
STA ZPDF
LDA #$00
STA L01E6
CLC
JSR L11AB
STA ZPE0
PLA
STA L01E6
@7 LDA ZPE0
ASL A
ASL A
ASL A
ASL A
ORA ZPDF
STA L01E6+1
@8 LDX ZPCF
LDA L01E6
ASL A
LDA #$F0
BCC @9
LDA #$0F
@9 STA ZPCF
AND L01E6+1
JSR L10A8
BIT L01E8
BPL @11
LDA L01E6
ASL A
LDA #$0F
BCC @10
LDA #$F0
@10 STA ZPCF
LDA ZPCF
AND L01E6+1
JSR L10A8
@11 STX ZPCF
LDA (ZPCA),Y
ORA ZPCF
LDX L01E6
BEQ @12
EOR ZPCF
@12 STA (ZPCA),Y
LDA #$F0
STA ZPE7
STY ZPE5
RTS
L1054 BVC @1
JSR L11B7
@1 JSR L1148
TAX
LDA ZPCF
BEQ @2
LDA ZPDF
JSR L1085
@2 LDA ZPCF
PHA
LDA ZPD0
BEQ @4
STA ZPCF
CMP #$60
PHP
BNE @3
DEY
@3 TXA
JSR L10A8
PLP
BNE @4
INY
@4 PLA
STA ZPCF
RTS
L1081 BIT ZPD2
BMI L10A8
L1085 BIT ZPD7
BPL @1
EOR ZPCF
@1 BIT ZPD6
BMI @5
BVS @4
EOR (ZPCA),Y
AND ZPCF
@2 EOR (ZPCA),Y
@3 STA (ZPCA),Y
RTS
@4 ORA (ZPCA),Y
BVS @3
@5 BVC @2
EOR #$FF
EOR ZPCF
AND (ZPCA),Y
BVS @3
L10A8 BIT ZPD7
BPL @1
EOR ZPCF
@1 BIT ZPD6
BMI @5
BVS @4
EOR (ZPCC),Y
AND ZPCF
@2 EOR (ZPCC),Y
@3 STA (ZPCC),Y
RTS
@4 ORA (ZPCC),Y
BVS @3
@5 BVC @2
EOR #$FF
EOR ZPCF
AND (ZPCC),Y
BVS @3
L10CB LDY ZPCE ;read color at pen position
LDX ZPD5
CPX #$03
BEQ L10F6
LDA ZPCF
BIT ZPD2
BMI @1
AND (ZPCA),Y
BCC @2
@1 AND (ZPCC),Y
@2 BEQ @3
LDA #$0F
@3 CPX #$01
BEQ @4
RTS
@4 TAX
LDA (ZPCC),Y
CPX #$00
BEQ @5
LSR A
LSR A
LSR A
LSR A
@5 AND #$0F
RTS
L10F6 LDA (ZPCA),Y
AND ZPCF
STA ZPDF
LDA ZPD0
CMP #$60
PHP
BNE @1
DEY
@1 AND (ZPCC),Y
PLP
BNE @2
INY
@2 LDX ZPD1
INX
BNE @3
LSR A
LSR A
LSR A
RTS
@3 INX
BNE @4
ROL ZPDF
ROL ZPDF
ROL A
RTS
@4 INX
BNE @5
LDA ZPDF
LSR A
LSR A
RTS
@5 INX
BNE @6
ROL A
ROL A
ROL ZPDF
ROL A
ROL ZPDF
LDA ZPDF
RTS
@6 INX
BNE @7
LSR A
RTS
@7 INX
BNE @8
ASL ZPDF
ASL ZPDF
ROL A
ASL ZPDF
ROL A
ASL ZPDF
ROL A
RTS
@8 LDA ZPDF
RTS
L1148 LDX ZPD1
INX
BNE @1
STX ZPDF
ASL A
ASL A
ASL A
RTS
@1 INX
BNE @2
LSR A
TAX
LDA #$00
ROR A
ROR A
STA ZPDF
TXA
RTS
@2 INX
BNE @3
ASL A
ASL A
STA ZPDF
TXA
RTS
@3 INX
BNE @4
STX ZPDF
LSR A
ROR ZPDF
LSR A
ROR ZPDF
LSR ZPDF
TAX
LDA ZPDF
STX ZPDF
RTS
@4 INX
BNE @5
ASL A
STX ZPDF
RTS
@5 INX
BNE @6
STX ZPDF
LSR A
ROR ZPDF
LSR A
ROR ZPDF
LSR A
ROR ZPDF
LSR ZPDF
RTS
@6 STA ZPDF
LDA #$00
RTS
L1199 LDA ZPCF
BIT ZPD2
BMI @1
AND (ZPCA),Y
BPL @2
@1 AND (ZPCC),Y
@2 BEQ L11BA
LDA #$0F
BNE L11BA
L11AB LDA (ZPCC),Y
BCS @1
LSR A
LSR A
LSR A
LSR A
@1 AND #$0F
BPL L11BA
L11B7 JSR L10F6
L11BA STA ZPDC
LDA L01E6
BPL @1
LDA F_COL
JMP @2
@1 LDA PN_COL
@2 ASL A
ASL A
ASL A
LSR ZPDC
ORA ZPDC
TAX
LDA COL_TAB,X
BCS @3
LSR A
LSR A
LSR A
LSR A
@3 AND #$0F
RTS
.endproc