Everything builds in Merlin-16 again.
This commit is contained in:
parent
7c36bc0010
commit
c1553c5a37
BIN
applecorn.po
BIN
applecorn.po
Binary file not shown.
|
@ -209,3 +209,5 @@ MAINZP MAC
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -474,3 +474,5 @@ OSBM2 ASC ').'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -449,3 +449,5 @@ BYTE76 LDX #$00 ; Update LEDs and return X=SHIFT
|
||||||
RTS ; Not possible with Apple
|
RTS ; Not possible with Apple
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
94
auxmem.gfx.s
94
auxmem.gfx.s
|
@ -1,94 +0,0 @@
|
||||||
* AUXMEM.GFX.S
|
|
||||||
* (c) Bobbi 2021 GPLv3
|
|
||||||
*
|
|
||||||
* Graphics operations
|
|
||||||
|
|
||||||
* Convert high-resolution screen coordinates
|
|
||||||
* from 1280x1024 to 280x192
|
|
||||||
CVTCOORD
|
|
||||||
* X-coordinate in VDUQ+5,+6 1280*7/32=280
|
|
||||||
LDA VDUQ+6 ; MSB of X-coord
|
|
||||||
CMP #$05 ; $500 is 1280
|
|
||||||
BCS :BIGX ; Value >=1280
|
|
||||||
STA ZP1+1 ; X-coord -> ZP1 and ZP2
|
|
||||||
STA ZP2+1
|
|
||||||
LDA VDUQ+5
|
|
||||||
STA ZP1+0
|
|
||||||
ASL A ; ZP2 *= 8
|
|
||||||
ROL ZP2+1
|
|
||||||
ASL A
|
|
||||||
ROL ZP2+1
|
|
||||||
ASL A
|
|
||||||
ROL ZP2+1
|
|
||||||
SEC ; ZP2-ZP1->ZP2
|
|
||||||
SBC ZP1+0
|
|
||||||
STA ZP2+0
|
|
||||||
LDA ZP2+1
|
|
||||||
SBC ZP1+1
|
|
||||||
LSR A ; ZP2 /= 32
|
|
||||||
ROR ZP2+0
|
|
||||||
LSR A
|
|
||||||
ROR ZP2+0
|
|
||||||
LSR A
|
|
||||||
ROR ZP2+0
|
|
||||||
LSR A
|
|
||||||
ROR ZP2+0
|
|
||||||
LSR A
|
|
||||||
ROR ZP2+0
|
|
||||||
STA VDUQ+6 ; ZP2 -> X-coord
|
|
||||||
LDA ZP2+0
|
|
||||||
STA VDUQ+5
|
|
||||||
|
|
||||||
* Y-coordinate in VDUQ+7,+8 1024*3/16=192
|
|
||||||
:YCOORD LDA VDUQ+8 ; MSB of Y-coord
|
|
||||||
AND #$FC
|
|
||||||
BNE :BIGY ; Y>1023
|
|
||||||
LDA VDUQ+8 ; Y-coord -> ZP1
|
|
||||||
STA ZP1+1
|
|
||||||
STA ZP2+1
|
|
||||||
LDA VDUQ+7
|
|
||||||
STA ZP1+0
|
|
||||||
ASL A ; ZP2 *= 2
|
|
||||||
ROL ZP2+1
|
|
||||||
CLC ; ZP2+ZP1->ZP2
|
|
||||||
ADC ZP1+0
|
|
||||||
STA ZP2+0
|
|
||||||
LDA ZP2+1
|
|
||||||
ADC ZP1+1
|
|
||||||
LSR A ; ZP2 /= 16
|
|
||||||
ROR ZP2+0
|
|
||||||
LSR A
|
|
||||||
ROR ZP2+0
|
|
||||||
LSR A
|
|
||||||
ROR ZP2+0
|
|
||||||
LSR A
|
|
||||||
ROR ZP2+0
|
|
||||||
STZ VDUQ+8 ; MSB always zero
|
|
||||||
SEC
|
|
||||||
LDA #191 ; 191 - ZP2 -> Y-coord
|
|
||||||
SBC ZP2+0
|
|
||||||
STA VDUQ+7
|
|
||||||
RTS
|
|
||||||
:BIGY STZ VDUQ+7 ; Y too large, row zero
|
|
||||||
STZ VDUQ+8
|
|
||||||
RTS
|
|
||||||
:BIGX LDA #$17 ; X too large, use 279
|
|
||||||
STA VDUQ+5
|
|
||||||
LDA #$01
|
|
||||||
STA VDUQ+6
|
|
||||||
BRA :YCOORD
|
|
||||||
|
|
||||||
* Add coordinates to XPIXEL, YPIXEL
|
|
||||||
RELCOORD CLC
|
|
||||||
LDA XPIXEL+0
|
|
||||||
ADC VDUQ+5
|
|
||||||
STA VDUQ+5
|
|
||||||
LDA XPIXEL+1
|
|
||||||
ADC VDUQ+6
|
|
||||||
STA VDUQ+6
|
|
||||||
CLC
|
|
||||||
LDA YPIXEL
|
|
||||||
ADC VDUQ+7
|
|
||||||
STA VDUQ+7
|
|
||||||
RTS
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ FSAREG EQU $B2
|
||||||
FSCTRL EQU FSXREG
|
FSCTRL EQU FSXREG
|
||||||
FSPTR1 EQU $B4
|
FSPTR1 EQU $B4
|
||||||
FSPTR2 EQU $B6
|
FSPTR2 EQU $B6
|
||||||
FSNUM EQU $C8 ; *TEMP*
|
FSNUM EQU $C8 ; *TEMP*
|
||||||
FSCMDLINE EQU $CE
|
FSCMDLINE EQU $CE
|
||||||
|
|
||||||
|
|
||||||
|
@ -671,19 +671,19 @@ FREERET
|
||||||
LDA AUXBLK+3 ; MSB of total blks
|
LDA AUXBLK+3 ; MSB of total blks
|
||||||
SBC AUXBLK+1 ; MSB of blocks used
|
SBC AUXBLK+1 ; MSB of blocks used
|
||||||
TAY
|
TAY
|
||||||
LDA #$00 ; *TO DO* b16-b23 of free
|
LDA #$00 ; *TO DO* b16-b23 of free
|
||||||
* NEW
|
* NEW
|
||||||
JSR :FREEDEC ; Print 'AAYYXX blocks aaayyyxxx bytes '
|
JSR :FREEDEC ; Print 'AAYYXX blocks aaayyyxxx bytes '
|
||||||
LDX #<:FREE
|
LDX #<:FREE
|
||||||
LDY #>:FREE
|
LDY #>:FREE
|
||||||
JSR OUTSTR ; Print 'free'<nl>
|
JSR OUTSTR ; Print 'free'<nl>
|
||||||
LDX AUXBLK+0 ; Blocks used
|
LDX AUXBLK+0 ; Blocks used
|
||||||
LDY AUXBLK+1
|
LDY AUXBLK+1
|
||||||
LDA #$00 ; *TO DO* b16-b23 of used
|
LDA #$00 ; *TO DO* b16-b23 of used
|
||||||
JSR :FREEDEC ; Print 'AAYYXX blocks aaayyyxxx bytes '
|
JSR :FREEDEC ; Print 'AAYYXX blocks aaayyyxxx bytes '
|
||||||
LDX #<:USED
|
LDX #<:USED
|
||||||
LDY #>:USED
|
LDY #>:USED
|
||||||
JMP OUTSTR ; Print 'used'<nl>
|
JMP OUTSTR ; Print 'used'<nl>
|
||||||
|
|
||||||
* OLD
|
* OLD
|
||||||
* JSR PRDECXY ; Print in decimal
|
* JSR PRDECXY ; Print in decimal
|
||||||
|
@ -706,20 +706,20 @@ FREERET
|
||||||
STA FSNUM+3
|
STA FSNUM+3
|
||||||
* What's the maximum number of blocks?
|
* What's the maximum number of blocks?
|
||||||
* JSR PRHEX ; Blocks b16-b23 in hex
|
* JSR PRHEX ; Blocks b16-b23 in hex
|
||||||
JSR PR2HEX ; Blocks b0-b15 in hex
|
JSR PR2HEX ; Blocks b0-b15 in hex
|
||||||
LDX #<:BLOCKS
|
LDX #<:BLOCKS
|
||||||
LDY #>:BLOCKS
|
LDY #>:BLOCKS
|
||||||
JSR OUTSTR ; ' blocks '
|
JSR OUTSTR ; ' blocks '
|
||||||
STZ FSNUM+0 ; FSNUM=blocks*512
|
STZ FSNUM+0 ; FSNUM=blocks*512
|
||||||
ASL FSNUM+1
|
ASL FSNUM+1
|
||||||
ROL FSNUM+2
|
ROL FSNUM+2
|
||||||
ROL FSNUM+3
|
ROL FSNUM+3
|
||||||
LDX #FSNUM ; X=>number to print
|
LDX #FSNUM ; X=>number to print
|
||||||
LDY #8 ; Y=pad up to 8 digits
|
LDY #8 ; Y=pad up to 8 digits
|
||||||
JSR PRINTDEC ; Print it in decimal
|
JSR PRINTDEC ; Print it in decimal
|
||||||
LDX #<:BYTES
|
LDX #<:BYTES
|
||||||
LDY #>:BYTES
|
LDY #>:BYTES
|
||||||
JMP OUTSTR ; ' bytes '
|
JMP OUTSTR ; ' bytes '
|
||||||
:BLOCKS ASC ' blocks '
|
:BLOCKS ASC ' blocks '
|
||||||
DB 0
|
DB 0
|
||||||
:BYTES ASC ' bytes '
|
:BYTES ASC ' bytes '
|
||||||
|
@ -979,3 +979,5 @@ ERROR5E DW $C000
|
||||||
ERROR2E DW $C800
|
ERROR2E DW $C800
|
||||||
ASC 'Disk changed' ; $2E - Disk switched
|
ASC 'Disk changed' ; $2E - Disk switched
|
||||||
DB $00
|
DB $00
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -180,3 +180,5 @@ BYTE00A BRK
|
||||||
HELLO ASC 'Applecorn MOS 2021-09-21'
|
HELLO ASC 'Applecorn MOS 2021-09-21'
|
||||||
DB $00 ; Unify MOS messages
|
DB $00 ; Unify MOS messages
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -133,43 +133,43 @@ PRDECPAD STX OSNUM+0
|
||||||
STY OSNUM+1
|
STY OSNUM+1
|
||||||
STZ OSNUM+2
|
STZ OSNUM+2
|
||||||
STZ OSNUM+3
|
STZ OSNUM+3
|
||||||
:PRDEC16 LDY #$05 ; 5 digits
|
:PRDEC16 LDY #$05 ; 5 digits
|
||||||
LDX #OSNUM ; number stored in OSNUM
|
LDX #OSNUM ; number stored in OSNUM
|
||||||
|
|
||||||
* Print up to 32-bit decimal number
|
* Print up to 32-bit decimal number
|
||||||
* See forum.6502.org/viewtopic.php?f=2&t=4894
|
* See forum.6502.org/viewtopic.php?f=2&t=4894
|
||||||
* X=>four byte zero page locations
|
* X=>four byte zero page locations
|
||||||
* Y= number of digits, 0 for no padding
|
* Y= number of digits, 0 for no padding
|
||||||
*
|
*
|
||||||
PRINTDEC sty OSPAD ; Number of padding+digits
|
PRINTDEC sty OSPAD ; Number of padding+digits
|
||||||
ldy #0 ; Digit counter
|
ldy #0 ; Digit counter
|
||||||
PRDECDIGIT lda #32 ; 32-bit divide
|
PRDECDIGIT lda #32 ; 32-bit divide
|
||||||
sta OSTEMP
|
sta OSTEMP
|
||||||
lda #0 ; Remainder=0
|
lda #0 ; Remainder=0
|
||||||
clv ; V=0 means div result = 0
|
clv ; V=0 means div result = 0
|
||||||
PRDECDIV10 cmp #10/2 ; Calculate OSNUM/10
|
PRDECDIV10 cmp #10/2 ; Calculate OSNUM/10
|
||||||
bcc PRDEC10
|
bcc PRDEC10
|
||||||
sbc #10/2+$80 ; Remove digit & set V=1 to show div result > 0
|
sbc #10/2+$80 ; Remove digit & set V=1 to show div result > 0
|
||||||
sec ; Shift 1 into div result
|
sec ; Shift 1 into div result
|
||||||
PRDEC10 rol 0,x ; Shift /10 result into OSNUM
|
PRDEC10 rol 0,x ; Shift /10 result into OSNUM
|
||||||
rol 1,x
|
rol 1,x
|
||||||
rol 2,x
|
rol 2,x
|
||||||
rol 3,x
|
rol 3,x
|
||||||
rol a ; Shift bits of input into acc (input mod 10)
|
rol a ; Shift bits of input into acc (input mod 10)
|
||||||
dec OSTEMP
|
dec OSTEMP
|
||||||
bne PRDECDIV10 ; Continue 32-bit divide
|
bne PRDECDIV10 ; Continue 32-bit divide
|
||||||
ora #48
|
ora #48
|
||||||
pha ; Push low digit 0-9 to print
|
pha ; Push low digit 0-9 to print
|
||||||
iny
|
iny
|
||||||
bvs PRDECDIGIT ; If V=1, result of /10 was > 0 & do next digit
|
bvs PRDECDIGIT ; If V=1, result of /10 was > 0 & do next digit
|
||||||
lda #32
|
lda #32
|
||||||
PRDECLP1 cpy OSPAD
|
PRDECLP1 cpy OSPAD
|
||||||
bcs PRDECLP2 ; Enough padding pushed
|
bcs PRDECLP2 ; Enough padding pushed
|
||||||
pha ; Push leading space characters
|
pha ; Push leading space characters
|
||||||
iny
|
iny
|
||||||
bne PRDECLP1
|
bne PRDECLP1
|
||||||
PRDECLP2 pla ; Pop character left to right
|
PRDECLP2 pla ; Pop character left to right
|
||||||
jsr OSWRCH ; Print it
|
jsr OSWRCH ; Print it
|
||||||
dey
|
dey
|
||||||
bne PRDECLP2
|
bne PRDECLP2
|
||||||
rts
|
rts
|
||||||
|
@ -532,3 +532,5 @@ MOSVEND
|
||||||
AUXBLK ASC '**ENDOFCODE**'
|
AUXBLK ASC '**ENDOFCODE**'
|
||||||
DS $200-13
|
DS $200-13
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,3 +71,5 @@ OSFILECB EQU $2EE ; OSFILE control block
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -499,3 +499,5 @@ ECHOLP1 JSR GSREAD
|
||||||
JSR OSWRCH
|
JSR OSWRCH
|
||||||
JMP ECHOLP1
|
JMP ECHOLP1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
384
auxmem.vdu.s
384
auxmem.vdu.s
|
@ -21,7 +21,7 @@
|
||||||
* VDU DRIVER ZERO PAGE
|
* VDU DRIVER ZERO PAGE
|
||||||
**********************
|
**********************
|
||||||
* $00D0-$00DF VDU driver zero page workspace
|
* $00D0-$00DF VDU driver zero page workspace
|
||||||
VDUSTATUS EQU $D0 ; $D0 # VDU status
|
VDUSTATUS EQU $D0 ; $D0 # VDU status
|
||||||
* bit 7 = VDU 21 VDU disabled
|
* bit 7 = VDU 21 VDU disabled
|
||||||
* bit 6 = COPY cursor active
|
* bit 6 = COPY cursor active
|
||||||
* bit 5 = VDU 5 Text at graphics cursor
|
* bit 5 = VDU 5 Text at graphics cursor
|
||||||
|
@ -31,40 +31,40 @@ VDUSTATUS EQU $D0 ; $D0 # VDU status
|
||||||
* bit 1 = Don't scroll (COPY cursor or VDU 5 mode)
|
* bit 1 = Don't scroll (COPY cursor or VDU 5 mode)
|
||||||
* bit 0 = VDU 2 printer echo active
|
* bit 0 = VDU 2 printer echo active
|
||||||
*
|
*
|
||||||
VDUCHAR EQU VDUSTATUS+1 ; $D1
|
VDUCHAR EQU VDUSTATUS+1 ; $D1
|
||||||
VDUADDR EQU VDUSTATUS+4 ; $D4 address of current char cell
|
VDUADDR EQU VDUSTATUS+4 ; $D4 address of current char cell
|
||||||
|
|
||||||
* TO DO: move these to VDU
|
* TO DO: move these to VDU
|
||||||
OLDCHAR EQU OSKBD1 ; *TEMP* ; character under cursor
|
OLDCHAR EQU OSKBD1 ; *TEMP* ; character under cursor
|
||||||
COPYCHAR EQU OSKBD2 ; *TEMP* ; character under copy cursor
|
COPYCHAR EQU OSKBD2 ; *TEMP* ; character under copy cursor
|
||||||
|
|
||||||
|
|
||||||
* VDU DRIVER MAIN WORKSPACE
|
* VDU DRIVER MAIN WORKSPACE
|
||||||
***************************
|
***************************
|
||||||
FXLINES EQU BYTEVARBASE+217 ; Paged scrolling line counter
|
FXLINES EQU BYTEVARBASE+217 ; Paged scrolling line counter
|
||||||
FXVDUQLEN EQU BYTEVARBASE+218 ; Length of pending VDU queue
|
FXVDUQLEN EQU BYTEVARBASE+218 ; Length of pending VDU queue
|
||||||
VDUVARS EQU $290
|
VDUVARS EQU $290
|
||||||
|
|
||||||
VDUTWINL EQU VDUVARS+$08 ; # text window left
|
VDUTWINL EQU VDUVARS+$08 ; # text window left
|
||||||
VDUTWINB EQU VDUVARS+$09 ; # text window bottom \ window
|
VDUTWINB EQU VDUVARS+$09 ; # text window bottom \ window
|
||||||
VDUTWINR EQU VDUVARS+$0A ; # text window right / size
|
VDUTWINR EQU VDUVARS+$0A ; # text window right / size
|
||||||
VDUTWINT EQU VDUVARS+$0B ; # text window top
|
VDUTWINT EQU VDUVARS+$0B ; # text window top
|
||||||
*
|
*
|
||||||
VDUPIXELS EQU VDUVARS+$13 ; *TEMP*
|
VDUPIXELS EQU VDUVARS+$13 ; *TEMP*
|
||||||
VDUBYTES EQU VDUVARS+$14 ; *TEMP* ; bytes per char
|
VDUBYTES EQU VDUVARS+$14 ; *TEMP* ; bytes per char
|
||||||
VDUMODE EQU VDUVARS+$15 ; *TEMP* ; current MODE
|
VDUMODE EQU VDUVARS+$15 ; *TEMP* ; current MODE
|
||||||
VDUSCREEN EQU VDUVARS+$16 ; *TEMP* ; Screen type, MODE 7?
|
VDUSCREEN EQU VDUVARS+$16 ; *TEMP* ; Screen type, MODE 7?
|
||||||
*
|
*
|
||||||
VDUTEXTX EQU VDUVARS+$18 ; absolute POS
|
VDUTEXTX EQU VDUVARS+$18 ; absolute POS
|
||||||
VDUTEXTY EQU VDUVARS+$19 ; absolute VPOS
|
VDUTEXTY EQU VDUVARS+$19 ; absolute VPOS
|
||||||
VDUCOPYX EQU VDUVARS+$1A ; absolute COPY cursor X posn
|
VDUCOPYX EQU VDUVARS+$1A ; absolute COPY cursor X posn
|
||||||
VDUCOPYY EQU VDUVARS+$1B ; absolute COPY cursor Y posn
|
VDUCOPYY EQU VDUVARS+$1B ; absolute COPY cursor Y posn
|
||||||
*
|
*
|
||||||
CURSOR EQU VDUVARS+$20 ; *TEMP* character used for cursor
|
CURSOR EQU VDUVARS+$20 ; *TEMP* character used for cursor
|
||||||
CURSORED EQU VDUVARS+$21 ; *TEMP* character used for edit cursor
|
CURSORED EQU VDUVARS+$21 ; *TEMP* character used for edit cursor
|
||||||
CURSORCP EQU VDUVARS+$22 ; *TEMP* character used for copy cursor
|
CURSORCP EQU VDUVARS+$22 ; *TEMP* character used for copy cursor
|
||||||
*
|
*
|
||||||
VDUQ EQU VDUVARS+$27 ; *TEMP* $27..$2F
|
VDUQ EQU VDUVARS+$27 ; *TEMP* $27..$2F
|
||||||
|
|
||||||
|
|
||||||
* Output character to VDU driver
|
* Output character to VDU driver
|
||||||
|
@ -74,31 +74,31 @@ VDUQ EQU VDUVARS+$27 ; *TEMP* $27..$2F
|
||||||
* CS if printer echo enabled for this character
|
* CS if printer echo enabled for this character
|
||||||
*
|
*
|
||||||
OUTCHAR LDX FXVDUQLEN
|
OUTCHAR LDX FXVDUQLEN
|
||||||
BNE ADDTOQ ; Waiting for chars
|
BNE ADDTOQ ; Waiting for chars
|
||||||
CMP #$7F
|
CMP #$7F
|
||||||
BEQ CTRLDEL ; =$7F - control char
|
BEQ CTRLDEL ; =$7F - control char
|
||||||
CMP #$20
|
CMP #$20
|
||||||
BCC CTRLCHAR ; <$20 - control char
|
BCC CTRLCHAR ; <$20 - control char
|
||||||
BIT VDUSTATUS
|
BIT VDUSTATUS
|
||||||
BMI OUTCHEXIT ; VDU disabled
|
BMI OUTCHEXIT ; VDU disabled
|
||||||
OUTCHARCP JSR PRCHRC ; Store char, checking keypress
|
OUTCHARCP JSR PRCHRC ; Store char, checking keypress
|
||||||
JSR VDU09 ; Move cursor right
|
JSR VDU09 ; Move cursor right
|
||||||
OUTCHEXIT LDA VDUSTATUS
|
OUTCHEXIT LDA VDUSTATUS
|
||||||
LSR A ; Return Cy=Printer Echo Enabled
|
LSR A ; Return Cy=Printer Echo Enabled
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
CTRLDEL LDA #$20 ; $7F becomes $20
|
CTRLDEL LDA #$20 ; $7F becomes $20
|
||||||
CTRLCHAR CMP #$01
|
CTRLCHAR CMP #$01
|
||||||
BEQ ADDQ ; One param
|
BEQ ADDQ ; One param
|
||||||
CMP #$11
|
CMP #$11
|
||||||
BCC CTRLCHARGO ; Zero params
|
BCC CTRLCHARGO ; Zero params
|
||||||
ADDQ STA VDUCHAR ; Save initial character
|
ADDQ STA VDUCHAR ; Save initial character
|
||||||
AND #$0F
|
AND #$0F
|
||||||
TAX
|
TAX
|
||||||
LDA QLEN,X
|
LDA QLEN,X
|
||||||
STA FXVDUQLEN ; Number of params to queue
|
STA FXVDUQLEN ; Number of params to queue
|
||||||
BEQ CTRLCHARGO1 ; Zero, do it now
|
BEQ CTRLCHARGO1 ; Zero, do it now
|
||||||
QDONE CLC ; CLC=Don't echo VDU queue to printer
|
QDONE CLC ; CLC=Don't echo VDU queue to printer
|
||||||
RTS
|
RTS
|
||||||
ADDTOQ STA VDUQ-256+9,X
|
ADDTOQ STA VDUQ-256+9,X
|
||||||
INC FXVDUQLEN
|
INC FXVDUQLEN
|
||||||
|
@ -106,28 +106,28 @@ ADDTOQ STA VDUQ-256+9,X
|
||||||
CTRLCHARGO1 LDA VDUCHAR
|
CTRLCHARGO1 LDA VDUCHAR
|
||||||
CTRLCHARGO ASL A
|
CTRLCHARGO ASL A
|
||||||
TAY
|
TAY
|
||||||
CMP #$10 ; 8*2
|
CMP #$10 ; 8*2
|
||||||
BCC CTRLCHARGO2 ; ctrl<$08, don't echo to printer
|
BCC CTRLCHARGO2 ; ctrl<$08, don't echo to printer
|
||||||
EOR #$FF ; ctrl>$0D, don't echo to printer
|
EOR #$FF ; ctrl>$0D, don't echo to printer
|
||||||
CMP #$E5 ; (13*2) EOR 255
|
CMP #$E5 ; (13*2) EOR 255
|
||||||
CTRLCHARGO2 PHP
|
CTRLCHARGO2 PHP
|
||||||
JSR CTRLCHARJMP ; Call routine
|
JSR CTRLCHARJMP ; Call routine
|
||||||
PLP
|
PLP
|
||||||
BCS OUTCHEXIT ; If echoable, test if printer enabled
|
BCS OUTCHEXIT ; If echoable, test if printer enabled
|
||||||
RTS ; Return, CC=Don't echo to printer
|
RTS ; Return, CC=Don't echo to printer
|
||||||
|
|
||||||
OUTCHARGO ASL A ; Entry point to move COPY cursor
|
OUTCHARGO ASL A ; Entry point to move COPY cursor
|
||||||
TAY ; (TEMP and scroll screen)
|
TAY ; (TEMP and scroll screen)
|
||||||
CTRLCHARJMP CPY #6*2
|
CTRLCHARJMP CPY #6*2
|
||||||
BEQ CTRLCHAR6 ; Always allow VDU 6 through
|
BEQ CTRLCHAR6 ; Always allow VDU 6 through
|
||||||
BIT VDUSTATUS
|
BIT VDUSTATUS
|
||||||
BMI VDU00 ; VDU disabled
|
BMI VDU00 ; VDU disabled
|
||||||
CTRLCHAR6 LDA CTRLADDRS+1,Y
|
CTRLCHAR6 LDA CTRLADDRS+1,Y
|
||||||
PHA
|
PHA
|
||||||
LDA CTRLADDRS+0,Y
|
LDA CTRLADDRS+0,Y
|
||||||
PHA
|
PHA
|
||||||
VDU27
|
VDU27
|
||||||
VDU00 RTS ; Enters code with CS=(ctrl>=8 && ctrl<=13)
|
VDU00 RTS ; Enters code with CS=(ctrl>=8 && ctrl<=13)
|
||||||
|
|
||||||
QLEN DB -0,-1,-2,-5,-0,-0,-1,-9 ; 32,1 or 17,18,19,20,21,22,23
|
QLEN DB -0,-1,-2,-5,-0,-0,-1,-9 ; 32,1 or 17,18,19,20,21,22,23
|
||||||
DB -8,-5,-0,-0,-4,-4,-0,-2 ; 24,25,26,27,28,29,30,31
|
DB -8,-5,-0,-0,-4,-4,-0,-2 ; 24,25,26,27,28,29,30,31
|
||||||
|
@ -148,46 +148,46 @@ CTRLADDRS DW VDU00-1,VDU01-1,VDU02-1,VDU03-1
|
||||||
* VDU 2 - Start print job
|
* VDU 2 - Start print job
|
||||||
VDU02
|
VDU02
|
||||||
* JSR select printer
|
* JSR select printer
|
||||||
LDA #$01 ; Set Printer Echo On
|
LDA #$01 ; Set Printer Echo On
|
||||||
BNE SETSTATUS
|
BNE SETSTATUS
|
||||||
|
|
||||||
* VDU 5 - Text at graphics cursor
|
* VDU 5 - Text at graphics cursor
|
||||||
VDU05 LDX VDUPIXELS
|
VDU05 LDX VDUPIXELS
|
||||||
BEQ SETEXIT ; 0 pixels per char, text only
|
BEQ SETEXIT ; 0 pixels per char, text only
|
||||||
* Turn cursor off and other stuff
|
* Turn cursor off and other stuff
|
||||||
LDA #$20 ; Set VDU 5 mode
|
LDA #$20 ; Set VDU 5 mode
|
||||||
BNE SETSTATUS
|
BNE SETSTATUS
|
||||||
|
|
||||||
* VDU 14 - Select paged scrolling
|
* VDU 14 - Select paged scrolling
|
||||||
VDU14 STZ FXLINES ; Reset line counter
|
VDU14 STZ FXLINES ; Reset line counter
|
||||||
LDA #$04 ; Set Paged Mode
|
LDA #$04 ; Set Paged Mode
|
||||||
BNE SETSTATUS
|
BNE SETSTATUS
|
||||||
|
|
||||||
* VDU 21 - Disable VDU
|
* VDU 21 - Disable VDU
|
||||||
VDU21 LDA #$80 ; Set VDU disabled
|
VDU21 LDA #$80 ; Set VDU disabled
|
||||||
|
|
||||||
SETSTATUS ORA VDUSTATUS ; Set bits in VDU STATUS
|
SETSTATUS ORA VDUSTATUS ; Set bits in VDU STATUS
|
||||||
STA VDUSTATUS
|
STA VDUSTATUS
|
||||||
SETEXIT RTS
|
SETEXIT RTS
|
||||||
|
|
||||||
* VDU 3 - End print job
|
* VDU 3 - End print job
|
||||||
VDU03
|
VDU03
|
||||||
* JSR flush printer
|
* JSR flush printer
|
||||||
LDA #$FE ; Clear Printer Echo
|
LDA #$FE ; Clear Printer Echo
|
||||||
BNE CLRSTATUS
|
BNE CLRSTATUS
|
||||||
|
|
||||||
* VDU 4 - Text at text cursor
|
* VDU 4 - Text at text cursor
|
||||||
VDU04
|
VDU04
|
||||||
* Turn cursor on and other stuff
|
* Turn cursor on and other stuff
|
||||||
LDA #$DF ; Clear VDU 5 mode
|
LDA #$DF ; Clear VDU 5 mode
|
||||||
BNE CLRSTATUS
|
BNE CLRSTATUS
|
||||||
|
|
||||||
* VDU 15 - Disable paged scrolling
|
* VDU 15 - Disable paged scrolling
|
||||||
VDU15 LDA #$FB ; Clear paged scrolling
|
VDU15 LDA #$FB ; Clear paged scrolling
|
||||||
BRA CLRSTATUS
|
BRA CLRSTATUS
|
||||||
|
|
||||||
* VDU 6 - Enable VDU
|
* VDU 6 - Enable VDU
|
||||||
VDU06 LDA #$7F ; Clear VDU disabled
|
VDU06 LDA #$7F ; Clear VDU disabled
|
||||||
|
|
||||||
CLRSTATUS AND VDUSTATUS
|
CLRSTATUS AND VDUSTATUS
|
||||||
STA VDUSTATUS
|
STA VDUSTATUS
|
||||||
|
@ -199,22 +199,22 @@ CLRSTATUS AND VDUSTATUS
|
||||||
* A=cursor key, CS from caller
|
* A=cursor key, CS from caller
|
||||||
COPYMOVE PHA
|
COPYMOVE PHA
|
||||||
BIT VDUSTATUS
|
BIT VDUSTATUS
|
||||||
BVS COPYMOVE2 ; Edit cursor already on
|
BVS COPYMOVE2 ; Edit cursor already on
|
||||||
JSR GETCHRC
|
JSR GETCHRC
|
||||||
STA COPYCHAR
|
STA COPYCHAR
|
||||||
LDA CURSORED
|
LDA CURSORED
|
||||||
JSR PUTCHRC ; Edit cursor
|
JSR PUTCHRC ; Edit cursor
|
||||||
SEC
|
SEC
|
||||||
JSR COPYSWAP2 ; Initialise copy cursor
|
JSR COPYSWAP2 ; Initialise copy cursor
|
||||||
ROR FLASHER
|
ROR FLASHER
|
||||||
ASL FLASHER ; Ensure b0=0
|
ASL FLASHER ; Ensure b0=0
|
||||||
LDA #$42
|
LDA #$42
|
||||||
ORA VDUSTATUS
|
ORA VDUSTATUS
|
||||||
STA VDUSTATUS ; Turn cursor editing on
|
STA VDUSTATUS ; Turn cursor editing on
|
||||||
COPYMOVE2 PLA
|
COPYMOVE2 PLA
|
||||||
AND #3 ; Convert to 8/9/10/11
|
AND #3 ; Convert to 8/9/10/11
|
||||||
ORA #8
|
ORA #8
|
||||||
COPYMOVE3 JMP OUTCHARGO ; Move edit cursor
|
COPYMOVE3 JMP OUTCHARGO ; Move edit cursor
|
||||||
|
|
||||||
** Turn editing cursor on/off
|
** Turn editing cursor on/off
|
||||||
*COPYCURSOR BIT VDUSTATUS
|
*COPYCURSOR BIT VDUSTATUS
|
||||||
|
@ -233,12 +233,12 @@ COPYMOVE3 JMP OUTCHARGO ; Move edit cursor
|
||||||
* Swap between edit and copy cursors
|
* Swap between edit and copy cursors
|
||||||
*COPYSWAP BIT VDUSTATUS
|
*COPYSWAP BIT VDUSTATUS
|
||||||
* BVC COPYSWAP4 ; Edit cursor off
|
* BVC COPYSWAP4 ; Edit cursor off
|
||||||
COPYSWAP1 CLC ; CC=Swap TEXT and COPY
|
COPYSWAP1 CLC ; CC=Swap TEXT and COPY
|
||||||
COPYSWAP2 LDX #1
|
COPYSWAP2 LDX #1
|
||||||
COPYSWAPLP LDY VDUCOPYX,X
|
COPYSWAPLP LDY VDUCOPYX,X
|
||||||
LDA VDUTEXTX,X
|
LDA VDUTEXTX,X
|
||||||
STA VDUCOPYX,X
|
STA VDUCOPYX,X
|
||||||
BCS COPYSWAP3 ; CS=Copy TEXT to COPY
|
BCS COPYSWAP3 ; CS=Copy TEXT to COPY
|
||||||
TYA
|
TYA
|
||||||
STA VDUTEXTX,X
|
STA VDUTEXTX,X
|
||||||
COPYSWAP3 DEX
|
COPYSWAP3 DEX
|
||||||
|
@ -247,18 +247,18 @@ COPYSWAP4 RTS
|
||||||
|
|
||||||
|
|
||||||
* Clear to EOL
|
* Clear to EOL
|
||||||
CLREOL LDA VDUTEXTY ; ROW
|
CLREOL LDA VDUTEXTY ; ROW
|
||||||
ASL
|
ASL
|
||||||
TAX
|
TAX
|
||||||
LDA SCNTAB,X ; LSB of row
|
LDA SCNTAB,X ; LSB of row
|
||||||
STA ZP1
|
STA ZP1
|
||||||
LDA SCNTAB+1,X ; MSB of row
|
LDA SCNTAB+1,X ; MSB of row
|
||||||
STA ZP1+1
|
STA ZP1+1
|
||||||
LDA VDUTEXTX ; COL
|
LDA VDUTEXTX ; COL
|
||||||
PHA
|
PHA
|
||||||
STZ VDUTEXTX ; COL
|
STZ VDUTEXTX ; COL
|
||||||
:L1
|
:L1
|
||||||
LDA VDUTEXTX ; COL
|
LDA VDUTEXTX ; COL
|
||||||
LSR
|
LSR
|
||||||
TAY
|
TAY
|
||||||
BCC :S1
|
BCC :S1
|
||||||
|
@ -266,42 +266,42 @@ CLREOL LDA VDUTEXTY ; ROW
|
||||||
:S1 LDA #" "
|
:S1 LDA #" "
|
||||||
STA (ZP1),Y
|
STA (ZP1),Y
|
||||||
>>> WRTAUX
|
>>> WRTAUX
|
||||||
LDA VDUTEXTX ; COL
|
LDA VDUTEXTX ; COL
|
||||||
CMP #79
|
CMP #79
|
||||||
BEQ :S2
|
BEQ :S2
|
||||||
INC VDUTEXTX ; COL
|
INC VDUTEXTX ; COL
|
||||||
BRA :L1
|
BRA :L1
|
||||||
:S2 PLA
|
:S2 PLA
|
||||||
STA VDUTEXTX ; COL
|
STA VDUTEXTX ; COL
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
* Clear the screen
|
* Clear the screen
|
||||||
CLEAR STZ VDUTEXTY ; ROW
|
CLEAR STZ VDUTEXTY ; ROW
|
||||||
STZ VDUTEXTX ; COL
|
STZ VDUTEXTX ; COL
|
||||||
:L1 JSR CLREOL
|
:L1 JSR CLREOL
|
||||||
:S2 LDA VDUTEXTY ; ROW
|
:S2 LDA VDUTEXTY ; ROW
|
||||||
CMP #23
|
CMP #23
|
||||||
BEQ :S3
|
BEQ :S3
|
||||||
INC VDUTEXTY ; ROW
|
INC VDUTEXTY ; ROW
|
||||||
BRA :L1
|
BRA :L1
|
||||||
:S3 STZ VDUTEXTY ; ROW
|
:S3 STZ VDUTEXTY ; ROW
|
||||||
STZ VDUTEXTX ; COL
|
STZ VDUTEXTX ; COL
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
* Calculate character address
|
* Calculate character address
|
||||||
CHARADDR LDA VDUTEXTY
|
CHARADDR LDA VDUTEXTY
|
||||||
ASL
|
ASL
|
||||||
TAX
|
TAX
|
||||||
LDA SCNTAB+0,X ; LSB of row address
|
LDA SCNTAB+0,X ; LSB of row address
|
||||||
STA VDUADDR+0
|
STA VDUADDR+0
|
||||||
LDA SCNTAB+1,X ; MSB of row address
|
LDA SCNTAB+1,X ; MSB of row address
|
||||||
STA VDUADDR+1
|
STA VDUADDR+1
|
||||||
LDA VDUTEXTX
|
LDA VDUTEXTX
|
||||||
BIT $C01F
|
BIT $C01F
|
||||||
SEC
|
SEC
|
||||||
BPL CHARADDR40 ; 40-col
|
BPL CHARADDR40 ; 40-col
|
||||||
LSR A
|
LSR A
|
||||||
CHARADDR40 TAY ; Y=offset into this row
|
CHARADDR40 TAY ; Y=offset into this row
|
||||||
RTS
|
RTS
|
||||||
* (VDUADDR),Y=>character address
|
* (VDUADDR),Y=>character address
|
||||||
* CC=auxmem
|
* CC=auxmem
|
||||||
|
@ -309,29 +309,29 @@ CHARADDR40 TAY ; Y=offset into this row
|
||||||
|
|
||||||
|
|
||||||
* Print char in A at ROW,COL
|
* Print char in A at ROW,COL
|
||||||
PRCHRC PHA ; Save character
|
PRCHRC PHA ; Save character
|
||||||
LDA $C000
|
LDA $C000
|
||||||
BPL :RESUME ; No key pressed
|
BPL :RESUME ; No key pressed
|
||||||
EOR #$80
|
EOR #$80
|
||||||
:PAUSE1 JSR KBDCHKESC ; Ask KBD to test if Escape
|
:PAUSE1 JSR KBDCHKESC ; Ask KBD to test if Escape
|
||||||
BIT ESCFLAG
|
BIT ESCFLAG
|
||||||
BMI :RESUMEACK ; Escape, skip pausing
|
BMI :RESUMEACK ; Escape, skip pausing
|
||||||
CMP #$13
|
CMP #$13
|
||||||
BNE :RESUME ; Not Ctrl-S
|
BNE :RESUME ; Not Ctrl-S
|
||||||
STA $C010 ; Ack. keypress
|
STA $C010 ; Ack. keypress
|
||||||
:PAUSE2 LDA $C000
|
:PAUSE2 LDA $C000
|
||||||
BPL :PAUSE2 ; Loop until keypress
|
BPL :PAUSE2 ; Loop until keypress
|
||||||
EOR #$80
|
EOR #$80
|
||||||
CMP #$11 ; Ctrl-Q
|
CMP #$11 ; Ctrl-Q
|
||||||
BEQ :RESUMEACK ; Stop pausing
|
BEQ :RESUMEACK ; Stop pausing
|
||||||
JSR KBDCHKESC ; Ask KBD to test if Escape
|
JSR KBDCHKESC ; Ask KBD to test if Escape
|
||||||
BIT ESCFLAG
|
BIT ESCFLAG
|
||||||
BPL :PAUSE2 ; No Escape, keep pausing
|
BPL :PAUSE2 ; No Escape, keep pausing
|
||||||
:RESUMEACK STA $C010 ; Ack. keypress
|
:RESUMEACK STA $C010 ; Ack. keypress
|
||||||
:RESUME PLA
|
:RESUME PLA
|
||||||
|
|
||||||
* Put character to screen
|
* Put character to screen
|
||||||
PUTCHRC EOR #$80 ; Convert character
|
PUTCHRC EOR #$80 ; Convert character
|
||||||
TAY
|
TAY
|
||||||
AND #$A0
|
AND #$A0
|
||||||
BNE PRCHR4
|
BNE PRCHR4
|
||||||
|
@ -339,29 +339,29 @@ PUTCHRC EOR #$80 ; Convert character
|
||||||
EOR #$40
|
EOR #$40
|
||||||
TAY
|
TAY
|
||||||
PRCHR4 PHY
|
PRCHR4 PHY
|
||||||
JSR CHARADDR ; Find character address
|
JSR CHARADDR ; Find character address
|
||||||
PLA ; Get character back
|
PLA ; Get character back
|
||||||
PHP ; Disable IRQs while
|
PHP ; Disable IRQs while
|
||||||
SEI ; toggling memory
|
SEI ; toggling memory
|
||||||
BCC PRCHR6 ; Aux memory
|
BCC PRCHR6 ; Aux memory
|
||||||
STA $C004 ; Switch to main memory
|
STA $C004 ; Switch to main memory
|
||||||
PRCHR6 STA (VDUADDR),Y ; Store it
|
PRCHR6 STA (VDUADDR),Y ; Store it
|
||||||
STA $C005 ; Back to aux memory
|
STA $C005 ; Back to aux memory
|
||||||
PLP ; Restore IRQs
|
PLP ; Restore IRQs
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
|
|
||||||
* Return char at ROW,COL in A and X, MODE in Y
|
* Return char at ROW,COL in A and X, MODE in Y
|
||||||
BYTE87
|
BYTE87
|
||||||
GETCHRC JSR CHARADDR ; Find character address
|
GETCHRC JSR CHARADDR ; Find character address
|
||||||
PHP ; Disable IRQs while
|
PHP ; Disable IRQs while
|
||||||
SEI ; toggling memory
|
SEI ; toggling memory
|
||||||
BCC GETCHR6 ; Aux memory
|
BCC GETCHR6 ; Aux memory
|
||||||
STA $C002 ; Switch to main memory
|
STA $C002 ; Switch to main memory
|
||||||
GETCHR6 LDA (VDUADDR),Y ; Get character
|
GETCHR6 LDA (VDUADDR),Y ; Get character
|
||||||
STA $C003 ; Back to aux memory
|
STA $C003 ; Back to aux memory
|
||||||
PLP ; Restore IRQs
|
PLP ; Restore IRQs
|
||||||
TAY ; Convert character
|
TAY ; Convert character
|
||||||
AND #$A0
|
AND #$A0
|
||||||
BNE GETCHR7
|
BNE GETCHR7
|
||||||
TYA
|
TYA
|
||||||
|
@ -369,16 +369,16 @@ GETCHR6 LDA (VDUADDR),Y ; Get character
|
||||||
TAY
|
TAY
|
||||||
GETCHR7 TYA
|
GETCHR7 TYA
|
||||||
EOR #$80
|
EOR #$80
|
||||||
TAX ; X=char for OSBYTE
|
TAX ; X=char for OSBYTE
|
||||||
LDY #$00
|
LDY #$00
|
||||||
BIT $C01F
|
BIT $C01F
|
||||||
BMI GETCHROK
|
BMI GETCHROK
|
||||||
INY ; Y=MODE
|
INY ; Y=MODE
|
||||||
GETCHROK RTS
|
GETCHROK RTS
|
||||||
|
|
||||||
|
|
||||||
BYTE86 LDY VDUTEXTY ; ROW ; $86 = read cursor pos
|
BYTE86 LDY VDUTEXTY ; ROW ; $86 = read cursor pos
|
||||||
LDX VDUTEXTX ; COL
|
LDX VDUTEXTX ; COL
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
* Perform backspace & delete operation
|
* Perform backspace & delete operation
|
||||||
|
@ -391,40 +391,40 @@ DELETE JSR BACKSPC
|
||||||
* Perform backspace/cursor left operation
|
* Perform backspace/cursor left operation
|
||||||
VDU08
|
VDU08
|
||||||
BACKSPC
|
BACKSPC
|
||||||
LDA VDUTEXTX ; COL
|
LDA VDUTEXTX ; COL
|
||||||
BEQ :S1
|
BEQ :S1
|
||||||
DEC VDUTEXTX ; COL
|
DEC VDUTEXTX ; COL
|
||||||
BRA :S3
|
BRA :S3
|
||||||
:S1 LDA VDUTEXTY ; ROW
|
:S1 LDA VDUTEXTY ; ROW
|
||||||
BEQ :S3
|
BEQ :S3
|
||||||
DEC VDUTEXTY ; ROW
|
DEC VDUTEXTY ; ROW
|
||||||
LDA #39
|
LDA #39
|
||||||
BIT $C01F
|
BIT $C01F
|
||||||
BPL :S2
|
BPL :S2
|
||||||
LDA #79
|
LDA #79
|
||||||
:S2
|
:S2
|
||||||
STA VDUTEXTX ; COL
|
STA VDUTEXTX ; COL
|
||||||
:S3 RTS
|
:S3 RTS
|
||||||
|
|
||||||
|
|
||||||
VDU10
|
VDU10
|
||||||
LDA VDUTEXTY ; ROW
|
LDA VDUTEXTY ; ROW
|
||||||
CMP #23
|
CMP #23
|
||||||
BEQ :TOSCRL ; JGH
|
BEQ :TOSCRL ; JGH
|
||||||
INC VDUTEXTY ; ROW
|
INC VDUTEXTY ; ROW
|
||||||
RTS
|
RTS
|
||||||
:TOSCRL JMP SCROLL ; JGH
|
:TOSCRL JMP SCROLL ; JGH
|
||||||
|
|
||||||
VDU11
|
VDU11
|
||||||
LDA VDUTEXTY ; ROW
|
LDA VDUTEXTY ; ROW
|
||||||
BEQ :DONE
|
BEQ :DONE
|
||||||
DEC VDUTEXTY ; ROW
|
DEC VDUTEXTY ; ROW
|
||||||
:DONE RTS
|
:DONE RTS
|
||||||
|
|
||||||
VDU13
|
VDU13
|
||||||
LDA #$BF
|
LDA #$BF
|
||||||
JSR CLRSTATUS ; Turn copy cursor off
|
JSR CLRSTATUS ; Turn copy cursor off
|
||||||
STZ VDUTEXTX ; COL
|
STZ VDUTEXTX ; COL
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
* Initialise VDU driver
|
* Initialise VDU driver
|
||||||
|
@ -447,33 +447,33 @@ VDUINIT STA VDUQ+8
|
||||||
VDU22 LDA VDUQ+8
|
VDU22 LDA VDUQ+8
|
||||||
AND #$07
|
AND #$07
|
||||||
STA VDUMODE
|
STA VDUMODE
|
||||||
LDX #$01 ; 80-col
|
LDX #$01 ; 80-col
|
||||||
CMP #$00
|
CMP #$00
|
||||||
BEQ VDU22A ; MODE 0 -> MODE 3, 80x24, text
|
BEQ VDU22A ; MODE 0 -> MODE 3, 80x24, text
|
||||||
CMP #$03
|
CMP #$03
|
||||||
BEQ VDU22A ; MODE 3 -> MODE 3, 80x24 text
|
BEQ VDU22A ; MODE 3 -> MODE 3, 80x24 text
|
||||||
CMP #$02
|
CMP #$02
|
||||||
BEQ VDU22G ; MODE 2 -> 280x192 HGR
|
BEQ VDU22G ; MODE 2 -> 280x192 HGR
|
||||||
DEX ; All other MODEs default to 40-col
|
DEX ; All other MODEs default to 40-col
|
||||||
VDU22A STA $C051 ; Enable Text
|
VDU22A STA $C051 ; Enable Text
|
||||||
STA $C00C,X ; Select 40col/80col
|
STA $C00C,X ; Select 40col/80col
|
||||||
STA $C055 ; PAGE2
|
STA $C055 ; PAGE2
|
||||||
STA $C052 ; Clear MIXED
|
STA $C052 ; Clear MIXED
|
||||||
STA $C00F ; Enable alt charset
|
STA $C00F ; Enable alt charset
|
||||||
BRA VDU22C
|
BRA VDU22C
|
||||||
|
|
||||||
VDU22G STA $C050 ; Enable Graphics
|
VDU22G STA $C050 ; Enable Graphics
|
||||||
STA $C057 ; Hi-Res
|
STA $C057 ; Hi-Res
|
||||||
STA $C054 ; PAGE1
|
STA $C054 ; PAGE1
|
||||||
STA $C052 ; Clear MIXED
|
STA $C052 ; Clear MIXED
|
||||||
JSR VDU16 ; Clear HGR screen
|
JSR VDU16 ; Clear HGR screen
|
||||||
|
|
||||||
* Set up default cursors
|
* Set up default cursors
|
||||||
VDU22C LDA #'_'
|
VDU22C LDA #'_'
|
||||||
STA CURSOR ; Normal cursor
|
STA CURSOR ; Normal cursor
|
||||||
STA CURSORCP ; Copy cursor when editing
|
STA CURSORCP ; Copy cursor when editing
|
||||||
LDA #$A0
|
LDA #$A0
|
||||||
STA CURSORED ; Edit cursor when editing
|
STA CURSORED ; Edit cursor when editing
|
||||||
* JSR VDU15 ; Turn off paged scrolling
|
* JSR VDU15 ; Turn off paged scrolling
|
||||||
* JSR VDU20 ; Reset colours
|
* JSR VDU20 ; Reset colours
|
||||||
* JSR VDU26 ; Reset windows
|
* JSR VDU26 ; Reset windows
|
||||||
|
@ -484,8 +484,8 @@ VDU12
|
||||||
JMP CLEAR
|
JMP CLEAR
|
||||||
|
|
||||||
VDU30
|
VDU30
|
||||||
STZ VDUTEXTY ; ROW
|
STZ VDUTEXTY ; ROW
|
||||||
STZ VDUTEXTX ; COL
|
STZ VDUTEXTX ; COL
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
VDU31
|
VDU31
|
||||||
|
@ -500,13 +500,13 @@ VDU31
|
||||||
CPX #40
|
CPX #40
|
||||||
BCS :DONE
|
BCS :DONE
|
||||||
:T9A
|
:T9A
|
||||||
STX VDUTEXTX ; COL
|
STX VDUTEXTX ; COL
|
||||||
STY VDUTEXTY ; ROW
|
STY VDUTEXTY ; ROW
|
||||||
:DONE RTS
|
:DONE RTS
|
||||||
|
|
||||||
* Perform cursor right operation
|
* Perform cursor right operation
|
||||||
VDU09
|
VDU09
|
||||||
LDA VDUTEXTX ; COL
|
LDA VDUTEXTX ; COL
|
||||||
CMP #39
|
CMP #39
|
||||||
BCC :S2
|
BCC :S2
|
||||||
BIT $C01F
|
BIT $C01F
|
||||||
|
@ -514,13 +514,13 @@ VDU09
|
||||||
CMP #79
|
CMP #79
|
||||||
BCC :S2
|
BCC :S2
|
||||||
:T11
|
:T11
|
||||||
STZ VDUTEXTX ; COL
|
STZ VDUTEXTX ; COL
|
||||||
LDA VDUTEXTY ; ROW
|
LDA VDUTEXTY ; ROW
|
||||||
CMP #23
|
CMP #23
|
||||||
BEQ SCROLL
|
BEQ SCROLL
|
||||||
INC VDUTEXTY ; ROW
|
INC VDUTEXTY ; ROW
|
||||||
:DONE RTS
|
:DONE RTS
|
||||||
:S2 INC VDUTEXTX ; COL
|
:S2 INC VDUTEXTX ; COL
|
||||||
BRA :DONE
|
BRA :DONE
|
||||||
SCROLL JSR SCROLLER
|
SCROLL JSR SCROLLER
|
||||||
JSR CLREOL
|
JSR CLREOL
|
||||||
|
@ -535,7 +535,7 @@ SCROLLER LDA #$00
|
||||||
CMP #23
|
CMP #23
|
||||||
BNE :L1
|
BNE :L1
|
||||||
BIT VDUSTATUS
|
BIT VDUSTATUS
|
||||||
BVC :L2 ; Copy cursor not active
|
BVC :L2 ; Copy cursor not active
|
||||||
JSR COPYSWAP1
|
JSR COPYSWAP1
|
||||||
LDA #11
|
LDA #11
|
||||||
JSR OUTCHARGO
|
JSR OUTCHARGO
|
||||||
|
@ -543,13 +543,13 @@ SCROLLER LDA #$00
|
||||||
:L2 RTS
|
:L2 RTS
|
||||||
|
|
||||||
* Copy line A+1 to line A
|
* Copy line A+1 to line A
|
||||||
SCR1LINE ASL ; Dest addr->ZP1
|
SCR1LINE ASL ; Dest addr->ZP1
|
||||||
TAX
|
TAX
|
||||||
LDA SCNTAB,X
|
LDA SCNTAB,X
|
||||||
STA ZP1
|
STA ZP1
|
||||||
LDA SCNTAB+1,X
|
LDA SCNTAB+1,X
|
||||||
STA ZP1+1
|
STA ZP1+1
|
||||||
INX ; Source addr->ZP2
|
INX ; Source addr->ZP2
|
||||||
INX
|
INX
|
||||||
LDA SCNTAB,X
|
LDA SCNTAB,X
|
||||||
STA ZP2
|
STA ZP2
|
||||||
|
@ -558,11 +558,11 @@ SCR1LINE ASL ; Dest addr->ZP1
|
||||||
LDY #$00
|
LDY #$00
|
||||||
:L1 LDA (ZP2),Y
|
:L1 LDA (ZP2),Y
|
||||||
STA (ZP1),Y
|
STA (ZP1),Y
|
||||||
STA $C002 ; Read main mem
|
STA $C002 ; Read main mem
|
||||||
>>> WRTMAIN
|
>>> WRTMAIN
|
||||||
LDA (ZP2),Y
|
LDA (ZP2),Y
|
||||||
STA (ZP1),Y
|
STA (ZP1),Y
|
||||||
STA $C003 ; Read aux mem
|
STA $C003 ; Read aux mem
|
||||||
>>> WRTAUX
|
>>> WRTAUX
|
||||||
INY
|
INY
|
||||||
CPY #40
|
CPY #40
|
||||||
|
@ -593,25 +593,25 @@ VDU16RET >>> ENTAUX
|
||||||
VDU17 RTS
|
VDU17 RTS
|
||||||
|
|
||||||
* VDU 18 - GCOL k,a - select graphics colour and plot action
|
* VDU 18 - GCOL k,a - select graphics colour and plot action
|
||||||
VDU18 LDA VDUQ+7 ; Argument 'k'
|
VDU18 LDA VDUQ+7 ; Argument 'k'
|
||||||
CMP #$04 ; k=4 means XOR
|
CMP #$04 ; k=4 means XOR
|
||||||
LDA #$00 ; Normal drawing mode
|
LDA #$00 ; Normal drawing mode
|
||||||
BNE :NORM
|
BNE :NORM
|
||||||
LDA #$01 ; XOR mode
|
LDA #$01 ; XOR mode
|
||||||
:NORM >>> WRTMAIN
|
:NORM >>> WRTMAIN
|
||||||
STA LINETYPE
|
STA LINETYPE
|
||||||
STA FDRAWADDR+5
|
STA FDRAWADDR+5
|
||||||
>>> WRTAUX
|
>>> WRTAUX
|
||||||
>>> XF2MAIN,SETLINE
|
>>> XF2MAIN,SETLINE
|
||||||
VDU18RET1 >>> ENTAUX
|
VDU18RET1 >>> ENTAUX
|
||||||
:NORM LDA VDUQ+8 ; Argument 'a'
|
:NORM LDA VDUQ+8 ; Argument 'a'
|
||||||
BPL :FOREGND ; <128 is foreground
|
BPL :FOREGND ; <128 is foreground
|
||||||
>>> WRTMAIN
|
>>> WRTMAIN
|
||||||
STA BGCOLOR ; Stored in main memory
|
STA BGCOLOR ; Stored in main memory
|
||||||
>>> WRTAUX
|
>>> WRTAUX
|
||||||
RTS
|
RTS
|
||||||
:FOREGND >>> WRTMAIN
|
:FOREGND >>> WRTMAIN
|
||||||
STA FGCOLOR ; Stored in main memory
|
STA FGCOLOR ; Stored in main memory
|
||||||
>>> WRTAUX
|
>>> WRTAUX
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
|
@ -631,29 +631,29 @@ VDU24 RTS
|
||||||
* x is in VDUQ+7,VDUQ+8
|
* x is in VDUQ+7,VDUQ+8
|
||||||
* y is in VDUQ+5,VDUQ+6
|
* y is in VDUQ+5,VDUQ+6
|
||||||
* k is in VDUQ+4
|
* k is in VDUQ+4
|
||||||
VDU25 JSR CVTCOORD ; Convert coordinate system
|
VDU25 JSR CVTCOORD ; Convert coordinate system
|
||||||
LDA VDUQ+4
|
LDA VDUQ+4
|
||||||
AND #$04 ; Bit 2 set -> absolute
|
AND #$04 ; Bit 2 set -> absolute
|
||||||
BNE :ABS
|
BNE :ABS
|
||||||
JSR RELCOORD ; Add coords to XPIXEL/YPIXEL
|
JSR RELCOORD ; Add coords to XPIXEL/YPIXEL
|
||||||
:ABS LDA VDUQ+4
|
:ABS LDA VDUQ+4
|
||||||
AND #$03
|
AND #$03
|
||||||
CMP #$0 ; Bits 0,1 clear -> just move
|
CMP #$0 ; Bits 0,1 clear -> just move
|
||||||
BNE :NOTMOVE
|
BNE :NOTMOVE
|
||||||
JMP HGRPOS ; Just update pos
|
JMP HGRPOS ; Just update pos
|
||||||
:NOTMOVE LDA VDUQ+4
|
:NOTMOVE LDA VDUQ+4
|
||||||
AND #$C0
|
AND #$C0
|
||||||
CMP #$40 ; Bit 7 clr, bit 6 set -> point
|
CMP #$40 ; Bit 7 clr, bit 6 set -> point
|
||||||
BNE :LINE
|
BNE :LINE
|
||||||
>>> WRTMAIN
|
>>> WRTMAIN
|
||||||
LDA VDUQ+4
|
LDA VDUQ+4
|
||||||
STA PLOTMODE
|
STA PLOTMODE
|
||||||
LDA VDUQ+5
|
LDA VDUQ+5
|
||||||
STA FDRAWADDR+6 ; LSB of X1
|
STA FDRAWADDR+6 ; LSB of X1
|
||||||
LDA VDUQ+6
|
LDA VDUQ+6
|
||||||
STA FDRAWADDR+7 ; MSB of X1
|
STA FDRAWADDR+7 ; MSB of X1
|
||||||
LDA VDUQ+7
|
LDA VDUQ+7
|
||||||
STA FDRAWADDR+8 ; Y1
|
STA FDRAWADDR+8 ; Y1
|
||||||
>>> WRTAUX
|
>>> WRTAUX
|
||||||
>>> XF2MAIN,DRAWPNT
|
>>> XF2MAIN,DRAWPNT
|
||||||
:LINE >>> WRTMAIN
|
:LINE >>> WRTMAIN
|
||||||
|
@ -666,11 +666,11 @@ VDU25 JSR CVTCOORD ; Convert coordinate system
|
||||||
LDA YPIXEL
|
LDA YPIXEL
|
||||||
STA FDRAWADDR+8
|
STA FDRAWADDR+8
|
||||||
LDA VDUQ+5
|
LDA VDUQ+5
|
||||||
STA FDRAWADDR+9 ; LSB of X1
|
STA FDRAWADDR+9 ; LSB of X1
|
||||||
LDA VDUQ+6
|
LDA VDUQ+6
|
||||||
STA FDRAWADDR+10 ; MSB of X1
|
STA FDRAWADDR+10 ; MSB of X1
|
||||||
LDA VDUQ+7
|
LDA VDUQ+7
|
||||||
STA FDRAWADDR+11 ; Y1
|
STA FDRAWADDR+11 ; Y1
|
||||||
>>> WRTAUX
|
>>> WRTAUX
|
||||||
>>> XF2MAIN,DRAWLINE
|
>>> XF2MAIN,DRAWLINE
|
||||||
VDU25RET >>> ENTAUX
|
VDU25RET >>> ENTAUX
|
||||||
|
@ -683,8 +683,8 @@ HGRPOS LDA VDUQ+5
|
||||||
LDA VDUQ+7
|
LDA VDUQ+7
|
||||||
STA YPIXEL
|
STA YPIXEL
|
||||||
RTS
|
RTS
|
||||||
XPIXEL DW $0000 ; Previous plot x-coord
|
XPIXEL DW $0000 ; Previous plot x-coord
|
||||||
YPIXEL DB $00 ; Previous plot y-coord
|
YPIXEL DB $00 ; Previous plot y-coord
|
||||||
|
|
||||||
* VDU 26 - Reset to default windows
|
* VDU 26 - Reset to default windows
|
||||||
VDU26 RTS
|
VDU26 RTS
|
||||||
|
@ -706,7 +706,7 @@ BYTE75 LDX VDUSTATUS
|
||||||
* TEST code for VIEW
|
* TEST code for VIEW
|
||||||
* OSBYTE &A0 - Read VDU variable
|
* OSBYTE &A0 - Read VDU variable
|
||||||
********************************
|
********************************
|
||||||
BYTEA0 LDY #79 ; Read VDU variable $09,$0A
|
BYTEA0 LDY #79 ; Read VDU variable $09,$0A
|
||||||
LDX #23
|
LDX #23
|
||||||
RTS
|
RTS
|
||||||
* TEST
|
* TEST
|
||||||
|
@ -716,3 +716,5 @@ BYTEA0 LDY #79 ; Read VDU variable $09,$0A
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,752 +0,0 @@
|
||||||
********************************
|
|
||||||
* *
|
|
||||||
* Fast Apple II Graphics *
|
|
||||||
* By Andy McFadden *
|
|
||||||
* Version 0.3, Aug 2015 *
|
|
||||||
* *
|
|
||||||
* Circle rendering *
|
|
||||||
* (Included by FDRAW.S) *
|
|
||||||
* *
|
|
||||||
* Developed with Merlin-16 *
|
|
||||||
* *
|
|
||||||
********************************
|
|
||||||
|
|
||||||
* TODO: if USE_FAST is 0, replace the outline circle
|
|
||||||
* plot code with calls to DrawPoint (or maybe a
|
|
||||||
* common sub-function so we don't trash the input
|
|
||||||
* parameters). Saves a little space.
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Draw a circle. The radius is in in_rad, and
|
|
||||||
* the center is at in_x0l+in_x0h,in_y0.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
DrawCircle
|
|
||||||
lda #$20 ;JSR
|
|
||||||
cmp _cp08 ;configured for outline?
|
|
||||||
beq :okay
|
|
||||||
jsr fixcplot
|
|
||||||
:okay
|
|
||||||
jmp calc_circle
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Draw filled circle.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
FillCircle
|
|
||||||
lda #$2c ;BIT
|
|
||||||
cmp _cp08 ;configured for fill?
|
|
||||||
beq :okay
|
|
||||||
jsr fixcplot
|
|
||||||
:okay
|
|
||||||
jsr calc_circle
|
|
||||||
jmp FillRaster
|
|
||||||
|
|
||||||
|
|
||||||
* Calculate a circle, using Bresenham's algorithm. The
|
|
||||||
* results are placed into the rasterization buffers.
|
|
||||||
*
|
|
||||||
* in_rad must be from 0 to 255. The x/y center
|
|
||||||
* coordinates must be on the screen, but the circle
|
|
||||||
* can extend off the edge.
|
|
||||||
*
|
|
||||||
* The computed values are stored in the rasterization
|
|
||||||
* tables. For an outline circle, we also plot the
|
|
||||||
* points immediately.
|
|
||||||
|
|
||||||
do USE_FAST ;*****
|
|
||||||
* local storage -- not used often enough to merit DP
|
|
||||||
circ_8bit ds 1
|
|
||||||
circ_clip ds 1
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
calc_circle
|
|
||||||
max_fast_rad equ 41
|
|
||||||
]cxl equ zloc0
|
|
||||||
]cxh equ zloc1
|
|
||||||
]cy equ zloc2
|
|
||||||
]dlo equ zloc3
|
|
||||||
]dhi equ zloc4
|
|
||||||
]xsav equ zloc5
|
|
||||||
]ysav equ zloc6
|
|
||||||
]min_x equ zloc7 ;min/max offsets from center
|
|
||||||
]max_x equ zloc8 ;(min is above center, max
|
|
||||||
]min_y equ zloc9 ; is below)
|
|
||||||
]max_y equ zloc10
|
|
||||||
]hitmp equ zloc11
|
|
||||||
* only used by hplot for outline circles
|
|
||||||
]hbasl equ zptr0
|
|
||||||
]andmask equ zloc11 ;overlaps with ]hitmp
|
|
||||||
]savxreg equ zloc12
|
|
||||||
]savyreg equ zloc13
|
|
||||||
|
|
||||||
* Special-case radius=0. It removes an annoying
|
|
||||||
* edge case (first y-- becomes 0xff, but 6502 cmp
|
|
||||||
* is unsigned).
|
|
||||||
lda in_rad
|
|
||||||
bne :notzero
|
|
||||||
ldy in_y0
|
|
||||||
sty rast_top
|
|
||||||
sty rast_bottom
|
|
||||||
lda in_x0l
|
|
||||||
sta rastx0l,y
|
|
||||||
sta rastx1l,y
|
|
||||||
lda in_x0h
|
|
||||||
sta rastx0h,y
|
|
||||||
sta rastx1h,y
|
|
||||||
rts
|
|
||||||
|
|
||||||
* Use different version of function for small
|
|
||||||
* circles, because we can do it all in 8 bits.
|
|
||||||
:notzero
|
|
||||||
do USE_FAST ;*****
|
|
||||||
ldy #$01
|
|
||||||
cmp #max_fast_rad ;in_rad in Acc
|
|
||||||
blt :use_fast
|
|
||||||
dey
|
|
||||||
:use_fast sty circ_8bit
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
lda in_x0l ;copy center to DP for speed
|
|
||||||
sta ]cxl
|
|
||||||
lda in_x0h
|
|
||||||
sta ]cxh
|
|
||||||
lda in_y0
|
|
||||||
sta ]cy
|
|
||||||
|
|
||||||
* Compute min/max values, based on offset from center.
|
|
||||||
* These are compared against offset-from-center x/y.
|
|
||||||
* We need tight bounds on Y because we use it to
|
|
||||||
* compute the rast_render top/bottom. Getting tight
|
|
||||||
* bounds on X is not so important, but we still need
|
|
||||||
* it for the no-clip optimization.
|
|
||||||
ldx #$04 ;count edges needing clip
|
|
||||||
|
|
||||||
lda #NUM_ROWS-1 ;191
|
|
||||||
sec
|
|
||||||
sbc ]cy ;maxY = 191-cy
|
|
||||||
cmp in_rad
|
|
||||||
blt :ylimok
|
|
||||||
lda in_rad ;clamp to radius
|
|
||||||
dex
|
|
||||||
:ylimok sta ]max_y ;maxY = 191-cy
|
|
||||||
|
|
||||||
lda ]cy ;minY = cy
|
|
||||||
cmp in_rad
|
|
||||||
blt :ylimok2
|
|
||||||
lda in_rad ;clamp to radius
|
|
||||||
dex
|
|
||||||
:ylimok2 sta ]min_y
|
|
||||||
|
|
||||||
lda ]cxh
|
|
||||||
beq :xlimlo
|
|
||||||
* Examples (note #<NUM_COLS-1 is 279-256 = 23):
|
|
||||||
* cx=265 (cxh=1 cxl=11), 23-11=14, chk rad
|
|
||||||
lda #<NUM_COLS-1 ;maxX = 279-cx
|
|
||||||
sec
|
|
||||||
sbc ]cxl
|
|
||||||
cmp in_rad
|
|
||||||
blt :xlimhok
|
|
||||||
lda in_rad ;clamp to radius
|
|
||||||
dex
|
|
||||||
:xlimhok sta ]max_x
|
|
||||||
|
|
||||||
lda in_rad ;min X always out of range
|
|
||||||
dex ; so just clamp to radius
|
|
||||||
sta ]min_x
|
|
||||||
jmp :xlimdone
|
|
||||||
|
|
||||||
* Examples:
|
|
||||||
* For cx=0 to 24, we can never pass right edge (our
|
|
||||||
* maximum radius is 255).
|
|
||||||
* cx=3, 23-3=20 + carry set --> bad, must use rad
|
|
||||||
* cx=24, 23-24=255 + carry clear --> ok, chk rad
|
|
||||||
* cx=255, 23-255=24 + carry clear --> ok, chk rad
|
|
||||||
:xlimlo
|
|
||||||
lda #<NUM_COLS-1 ;maxX = 279-cx
|
|
||||||
sec
|
|
||||||
sbc ]cxl
|
|
||||||
bcs :xuserad
|
|
||||||
cmp in_rad
|
|
||||||
blt :xlimok
|
|
||||||
:xuserad lda in_rad ;clamp to radius
|
|
||||||
dex
|
|
||||||
:xlimok sta ]max_x
|
|
||||||
|
|
||||||
lda ]cxl ;minX = (cx > 255) ?
|
|
||||||
cmp in_rad
|
|
||||||
blt :xlimok2
|
|
||||||
lda in_rad ;clamp to radius
|
|
||||||
dex
|
|
||||||
:xlimok2 sta ]min_x
|
|
||||||
|
|
||||||
:xlimdone
|
|
||||||
|
|
||||||
do USE_FAST ;*****
|
|
||||||
stx circ_clip
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
* set top/bottom rows for rasterizer
|
|
||||||
lda ]cy
|
|
||||||
clc
|
|
||||||
adc ]max_y
|
|
||||||
sta rast_bottom
|
|
||||||
lda ]cy
|
|
||||||
sec
|
|
||||||
sbc ]min_y
|
|
||||||
sta rast_top
|
|
||||||
|
|
||||||
DO 0 ;debug debug debug
|
|
||||||
LDA ]min_x ;save a copy where the
|
|
||||||
STA $0380 ; monitor won't trash it
|
|
||||||
LDA ]max_x
|
|
||||||
STA $0381
|
|
||||||
LDA ]min_y
|
|
||||||
STA $0382
|
|
||||||
LDA ]max_y
|
|
||||||
STA $0383
|
|
||||||
FIN
|
|
||||||
|
|
||||||
* Set initial conditions for Bresenham.
|
|
||||||
ldx #0 ;:x = 0
|
|
||||||
stx ]xsav
|
|
||||||
ldy in_rad ;:y = rad
|
|
||||||
sty ]ysav
|
|
||||||
lda #1 ;:d = 1 - rad
|
|
||||||
sec
|
|
||||||
sbc ]ysav ;in_rad
|
|
||||||
sta ]dlo
|
|
||||||
bcs :hizero ;C==1 if in_rad<=1
|
|
||||||
ldx #$ff ;C was 0, make neg
|
|
||||||
:hizero stx ]dhi
|
|
||||||
|
|
||||||
*
|
|
||||||
* Outer loop -- plot 8 points, then update values.
|
|
||||||
*
|
|
||||||
circ_loop
|
|
||||||
|
|
||||||
do USE_FAST ;*****
|
|
||||||
lda circ_clip
|
|
||||||
beq ncypy
|
|
||||||
jmp with_clip
|
|
||||||
|
|
||||||
* Quick version, no clipping required
|
|
||||||
* row cy+y: cx-x and cx+x
|
|
||||||
ncypy
|
|
||||||
lda ]ysav
|
|
||||||
clc
|
|
||||||
adc ]cy
|
|
||||||
tay ;y-coord in Y-reg
|
|
||||||
|
|
||||||
lda ]cxl
|
|
||||||
sec
|
|
||||||
sbc ]xsav
|
|
||||||
sta rastx0l,y
|
|
||||||
lda ]cxh
|
|
||||||
sbc #$00
|
|
||||||
sta rastx0h,y
|
|
||||||
_cp00 jsr cplotl
|
|
||||||
|
|
||||||
lda ]cxl
|
|
||||||
clc
|
|
||||||
adc ]xsav
|
|
||||||
sta rastx1l,y
|
|
||||||
lda ]cxh
|
|
||||||
adc #$00
|
|
||||||
sta rastx1h,y
|
|
||||||
_cp01 jsr cplotrn
|
|
||||||
|
|
||||||
* row cy-y: cx-x and cx+x
|
|
||||||
ncymy
|
|
||||||
lda ]cy
|
|
||||||
sec
|
|
||||||
sbc ]ysav
|
|
||||||
tay ;y-coord in Y-reg
|
|
||||||
|
|
||||||
lda ]cxl
|
|
||||||
sec
|
|
||||||
sbc ]xsav
|
|
||||||
sta rastx0l,y
|
|
||||||
lda ]cxh
|
|
||||||
sbc #$00
|
|
||||||
sta rastx0h,y
|
|
||||||
_cp02 jsr cplotl
|
|
||||||
|
|
||||||
lda ]cxl
|
|
||||||
clc
|
|
||||||
adc ]xsav
|
|
||||||
sta rastx1l,y
|
|
||||||
lda ]cxh
|
|
||||||
adc #$00
|
|
||||||
sta rastx1h,y
|
|
||||||
_cp03 jsr cplotrn
|
|
||||||
|
|
||||||
* row cy+x: cx-y and cx+y
|
|
||||||
ncypx
|
|
||||||
lda ]xsav ;off bottom?
|
|
||||||
clc
|
|
||||||
adc ]cy
|
|
||||||
tay ;y-coord in Y-reg
|
|
||||||
|
|
||||||
lda ]cxl
|
|
||||||
sec
|
|
||||||
sbc ]ysav
|
|
||||||
sta rastx0l,y
|
|
||||||
lda ]cxh
|
|
||||||
sbc #$00
|
|
||||||
sta rastx0h,y
|
|
||||||
_cp04 jsr cplotl
|
|
||||||
|
|
||||||
lda ]cxl
|
|
||||||
clc
|
|
||||||
adc ]ysav
|
|
||||||
sta rastx1l,y
|
|
||||||
lda ]cxh
|
|
||||||
adc #$00
|
|
||||||
sta rastx1h,y
|
|
||||||
_cp05 jsr cplotrn
|
|
||||||
|
|
||||||
* row cy-x: cx-y and cx+y
|
|
||||||
ncymx
|
|
||||||
lda ]cy
|
|
||||||
sec
|
|
||||||
sbc ]xsav
|
|
||||||
tay ;y-coord in Y-reg
|
|
||||||
|
|
||||||
lda ]cxl
|
|
||||||
sec
|
|
||||||
sbc ]ysav
|
|
||||||
sta rastx0l,y
|
|
||||||
lda ]cxh
|
|
||||||
sbc #$00
|
|
||||||
sta rastx0h,y
|
|
||||||
_cp06 jsr cplotl
|
|
||||||
|
|
||||||
lda ]cxl
|
|
||||||
clc
|
|
||||||
adc ]ysav
|
|
||||||
sta rastx1l,y
|
|
||||||
lda ]cxh
|
|
||||||
adc #$00
|
|
||||||
sta rastx1h,y
|
|
||||||
_cp07 jsr cplotrn
|
|
||||||
|
|
||||||
* CLICK
|
|
||||||
jmp circ_plot_done
|
|
||||||
|
|
||||||
fin ;***** (USE_FAST)
|
|
||||||
|
|
||||||
*
|
|
||||||
* Same thing, but this time clipping edges.
|
|
||||||
*
|
|
||||||
with_clip
|
|
||||||
|
|
||||||
* row cy+y: cx-x and cx+x
|
|
||||||
ccypy
|
|
||||||
lda ]ysav ;off bottom?
|
|
||||||
cmp ]max_y
|
|
||||||
beq :cypy_ok
|
|
||||||
bge cypy_skip ;completely off screen
|
|
||||||
:cypy_ok clc
|
|
||||||
adc ]cy
|
|
||||||
tay ;y-coord in Y-reg
|
|
||||||
|
|
||||||
ldx ]xsav ;handle cx-x
|
|
||||||
cpx ]min_x
|
|
||||||
blt :cxmx_ok
|
|
||||||
beq :cxmx_ok
|
|
||||||
lda #0 ;clip at 0
|
|
||||||
sta rastx0l,y
|
|
||||||
sta rastx0h,y
|
|
||||||
beq cxmx_done0 ;always
|
|
||||||
BREAK
|
|
||||||
:cxmx_ok lda ]cxl
|
|
||||||
sec
|
|
||||||
sbc ]xsav
|
|
||||||
sta rastx0l,y
|
|
||||||
lda ]cxh
|
|
||||||
sbc #$00
|
|
||||||
sta rastx0h,y
|
|
||||||
_cp08 jsr cplotl
|
|
||||||
cxmx_done0
|
|
||||||
|
|
||||||
cpx ]max_x ;handle cx+x
|
|
||||||
blt :cxpx_ok
|
|
||||||
beq :cxpx_ok
|
|
||||||
lda #<NUM_COLS-1
|
|
||||||
sta rastx1l,y
|
|
||||||
lda #>NUM_COLS-1
|
|
||||||
sta rastx1h,y
|
|
||||||
bne cxpx_done0 ;always
|
|
||||||
BREAK
|
|
||||||
:cxpx_ok lda ]cxl
|
|
||||||
clc
|
|
||||||
adc ]xsav
|
|
||||||
sta rastx1l,y
|
|
||||||
lda ]cxh
|
|
||||||
adc #$00
|
|
||||||
sta rastx1h,y
|
|
||||||
_cp09 jsr cplotr
|
|
||||||
cxpx_done0
|
|
||||||
cypy_skip
|
|
||||||
|
|
||||||
* row cy-y: cx-x and cx+x
|
|
||||||
ccymy
|
|
||||||
lda ]ysav ;off top?
|
|
||||||
cmp ]min_y
|
|
||||||
beq :cymy_ok
|
|
||||||
bge cymy_skip
|
|
||||||
:cymy_ok lda ]cy
|
|
||||||
sec
|
|
||||||
sbc ]ysav
|
|
||||||
tay ;y-coord in Y-reg
|
|
||||||
|
|
||||||
ldx ]xsav ;handle cx-x
|
|
||||||
cpx ]min_x
|
|
||||||
blt :cxmx_ok
|
|
||||||
beq :cxmx_ok
|
|
||||||
lda #0 ;clip at 0
|
|
||||||
sta rastx0l,y
|
|
||||||
sta rastx0h,y
|
|
||||||
beq cxmx_done1 ;always
|
|
||||||
BREAK
|
|
||||||
:cxmx_ok lda ]cxl
|
|
||||||
sec
|
|
||||||
sbc ]xsav
|
|
||||||
sta rastx0l,y
|
|
||||||
lda ]cxh
|
|
||||||
sbc #$00
|
|
||||||
sta rastx0h,y
|
|
||||||
_cp10 jsr cplotl
|
|
||||||
cxmx_done1
|
|
||||||
|
|
||||||
cpx ]max_x ;handle cx+x
|
|
||||||
blt :cxpx_ok
|
|
||||||
beq :cxpx_ok
|
|
||||||
lda #<NUM_COLS-1
|
|
||||||
sta rastx1l,y
|
|
||||||
lda #>NUM_COLS-1
|
|
||||||
sta rastx1h,y
|
|
||||||
bne cxpx_done1 ;always
|
|
||||||
BREAK
|
|
||||||
:cxpx_ok lda ]cxl
|
|
||||||
clc
|
|
||||||
adc ]xsav
|
|
||||||
sta rastx1l,y
|
|
||||||
lda ]cxh
|
|
||||||
adc #$00
|
|
||||||
sta rastx1h,y
|
|
||||||
_cp11 jsr cplotr
|
|
||||||
cxpx_done1
|
|
||||||
cymy_skip
|
|
||||||
|
|
||||||
* row cy+x: cx-y and cx+y
|
|
||||||
ccypx
|
|
||||||
lda ]xsav ;off bottom?
|
|
||||||
cmp ]max_y
|
|
||||||
beq :cypx_ok
|
|
||||||
bge cypx_skip
|
|
||||||
:cypx_ok clc
|
|
||||||
adc ]cy
|
|
||||||
tay ;y-coord in Y-reg
|
|
||||||
|
|
||||||
ldx ]ysav ;handle cx-y
|
|
||||||
cpx ]min_x
|
|
||||||
blt :cxmy_ok
|
|
||||||
beq :cxmy_ok
|
|
||||||
lda #0 ;clip at 0
|
|
||||||
sta rastx0l,y
|
|
||||||
sta rastx0h,y
|
|
||||||
beq cxmy_done2 ;always
|
|
||||||
BREAK
|
|
||||||
:cxmy_ok lda ]cxl
|
|
||||||
sec
|
|
||||||
sbc ]ysav
|
|
||||||
sta rastx0l,y
|
|
||||||
lda ]cxh
|
|
||||||
sbc #$00
|
|
||||||
sta rastx0h,y
|
|
||||||
_cp12 jsr cplotl
|
|
||||||
cxmy_done2
|
|
||||||
|
|
||||||
cpx ]max_x ;handle cx+y
|
|
||||||
blt :cxpy_ok
|
|
||||||
beq :cxpy_ok
|
|
||||||
lda #<NUM_COLS-1
|
|
||||||
sta rastx1l,y
|
|
||||||
lda #>NUM_COLS-1
|
|
||||||
sta rastx1h,y
|
|
||||||
bne cxpy_done2 ;always
|
|
||||||
BREAK
|
|
||||||
:cxpy_ok lda ]cxl
|
|
||||||
clc
|
|
||||||
adc ]ysav
|
|
||||||
sta rastx1l,y
|
|
||||||
lda ]cxh
|
|
||||||
adc #$00
|
|
||||||
sta rastx1h,y
|
|
||||||
_cp13 jsr cplotr
|
|
||||||
cxpy_done2
|
|
||||||
cypx_skip
|
|
||||||
|
|
||||||
* row cy-x: cx-y and cx+y
|
|
||||||
ccymx
|
|
||||||
lda ]xsav ;off top?
|
|
||||||
cmp ]min_y
|
|
||||||
beq :cymx_ok
|
|
||||||
bge cymx_skip
|
|
||||||
:cymx_ok lda ]cy
|
|
||||||
sec
|
|
||||||
sbc ]xsav
|
|
||||||
tay ;y-coord in Y-reg
|
|
||||||
|
|
||||||
ldx ]ysav ;handle cx-y
|
|
||||||
cpx ]min_x
|
|
||||||
blt :cxmy_ok
|
|
||||||
beq :cxmy_ok
|
|
||||||
lda #0 ;clip at 0
|
|
||||||
sta rastx0l,y
|
|
||||||
sta rastx0h,y
|
|
||||||
beq cxmy_done3 ;always
|
|
||||||
BREAK
|
|
||||||
:cxmy_ok lda ]cxl
|
|
||||||
sec
|
|
||||||
sbc ]ysav
|
|
||||||
sta rastx0l,y
|
|
||||||
lda ]cxh
|
|
||||||
sbc #$00
|
|
||||||
sta rastx0h,y
|
|
||||||
_cp14 jsr cplotl
|
|
||||||
cxmy_done3
|
|
||||||
|
|
||||||
cpx ]max_x ;handle cx+y
|
|
||||||
blt :cxpy_ok
|
|
||||||
beq :cxpy_ok
|
|
||||||
lda #<NUM_COLS-1
|
|
||||||
sta rastx1l,y
|
|
||||||
lda #>NUM_COLS-1
|
|
||||||
sta rastx1h,y
|
|
||||||
bne cxpy_done3 ;always
|
|
||||||
BREAK
|
|
||||||
:cxpy_ok lda ]cxl
|
|
||||||
clc
|
|
||||||
adc ]ysav
|
|
||||||
sta rastx1l,y
|
|
||||||
lda ]cxh
|
|
||||||
adc #$00
|
|
||||||
sta rastx1h,y
|
|
||||||
_cp15 jsr cplotr
|
|
||||||
cxpy_done3
|
|
||||||
cymx_skip
|
|
||||||
|
|
||||||
circ_plot_done
|
|
||||||
* Update X/Y/D. Up to about radius=41 we can maintain
|
|
||||||
* 'd' in an 8-bit register.
|
|
||||||
do USE_FAST ;*****
|
|
||||||
lda circ_8bit
|
|
||||||
beq circ_slow
|
|
||||||
|
|
||||||
*
|
|
||||||
* Bresenham update, with 8-bit 'd'.
|
|
||||||
*
|
|
||||||
ldx ]xsav
|
|
||||||
lda ]dlo
|
|
||||||
bmi :dneg
|
|
||||||
txa ;:d = d + ((x-y)*4) +5
|
|
||||||
sec
|
|
||||||
sbc ]ysav ;x <= y, may be neg or 0
|
|
||||||
asl
|
|
||||||
asl
|
|
||||||
clc ;can't know carry
|
|
||||||
adc #5
|
|
||||||
clc ;still don't want carry
|
|
||||||
adc ]dlo
|
|
||||||
sta ]dlo
|
|
||||||
dec ]ysav ;:y--
|
|
||||||
jmp :loopbot
|
|
||||||
:dneg txa ;:d = d + (x*4) +3
|
|
||||||
asl
|
|
||||||
asl ;x always pos, C=0
|
|
||||||
DO 0
|
|
||||||
BCC :TEST ;debug
|
|
||||||
BREAK ;debug
|
|
||||||
:TEST ;debug
|
|
||||||
FIN
|
|
||||||
adc #3
|
|
||||||
adc ]dlo
|
|
||||||
sta ]dlo
|
|
||||||
:loopbot
|
|
||||||
inx ;:x++
|
|
||||||
stx ]xsav
|
|
||||||
cpx ]ysav
|
|
||||||
beq :again
|
|
||||||
bge circ_done
|
|
||||||
:again jmp circ_loop
|
|
||||||
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
*
|
|
||||||
* Bresenham update, with 16-bit 'd'
|
|
||||||
*
|
|
||||||
circ_slow
|
|
||||||
CLICK
|
|
||||||
ldx ]xsav
|
|
||||||
lda ]dhi
|
|
||||||
bmi :dneg
|
|
||||||
lda ]dlo
|
|
||||||
clc
|
|
||||||
adc #5
|
|
||||||
sta ]dlo
|
|
||||||
bcc :noinc
|
|
||||||
inc ]dhi
|
|
||||||
:noinc
|
|
||||||
txa ;:d = d + ((x-y)*4) +5
|
|
||||||
ldy #$00
|
|
||||||
sty ]hitmp
|
|
||||||
sec
|
|
||||||
sbc ]ysav ;x <= y, may be neg or 0
|
|
||||||
beq :xeqy ;if x==y, nothing to add
|
|
||||||
ldy #$ff
|
|
||||||
sty ]hitmp
|
|
||||||
asl
|
|
||||||
rol ]hitmp
|
|
||||||
asl
|
|
||||||
rol ]hitmp
|
|
||||||
clc
|
|
||||||
adc ]dlo
|
|
||||||
sta ]dlo
|
|
||||||
lda ]dhi
|
|
||||||
adc ]hitmp
|
|
||||||
sta ]dhi
|
|
||||||
:xeqy
|
|
||||||
dec ]ysav ;:y--
|
|
||||||
jmp :loopbot
|
|
||||||
|
|
||||||
:dneg lda ]dlo ;:d = d + (x*4) + 3
|
|
||||||
clc
|
|
||||||
adc #3
|
|
||||||
sta ]dlo
|
|
||||||
bcc :noinc2
|
|
||||||
inc ]dhi
|
|
||||||
:noinc2 txa
|
|
||||||
ldy #0 ;x always positive
|
|
||||||
sty ]hitmp
|
|
||||||
asl
|
|
||||||
rol ]hitmp
|
|
||||||
asl
|
|
||||||
rol ]hitmp
|
|
||||||
clc ;not needed?
|
|
||||||
adc ]dlo
|
|
||||||
sta ]dlo
|
|
||||||
lda ]dhi
|
|
||||||
adc ]hitmp
|
|
||||||
sta ]dhi
|
|
||||||
:loopbot
|
|
||||||
inx ;:x++
|
|
||||||
stx ]xsav
|
|
||||||
cpx ]ysav
|
|
||||||
beq :again
|
|
||||||
bge circ_done
|
|
||||||
:again jmp circ_loop
|
|
||||||
|
|
||||||
|
|
||||||
circ_done rts
|
|
||||||
|
|
||||||
|
|
||||||
* Plot a point for outline circle rendering.
|
|
||||||
*
|
|
||||||
* X and Y must be preserved. Y holds the current line
|
|
||||||
* number.
|
|
||||||
*
|
|
||||||
* Most DP locations are in use -- see the variable
|
|
||||||
* declarations at the start of the circle function.
|
|
||||||
|
|
||||||
* cplotl is the entry point for the leftmost point.
|
|
||||||
cplotl
|
|
||||||
stx ]savxreg
|
|
||||||
sty ]savyreg
|
|
||||||
|
|
||||||
lda ylooklo,y
|
|
||||||
sta ]hbasl
|
|
||||||
lda ylookhi,y
|
|
||||||
_pg_or2 ora #$20
|
|
||||||
sta ]hbasl+1
|
|
||||||
|
|
||||||
* Convert the X coordinate into byte/bit.
|
|
||||||
ldx rastx0l,y ;x coord, lo
|
|
||||||
lda rastx0h,y ;>= 256?
|
|
||||||
beq :lotabl ;no, use the low table
|
|
||||||
ldy div7hi,x
|
|
||||||
lda mod7hi,x
|
|
||||||
bpl cplotcom ;always
|
|
||||||
BREAK ;debug
|
|
||||||
:lotabl ldy div7lo,x
|
|
||||||
lda mod7lo,x
|
|
||||||
jmp cplotcom
|
|
||||||
|
|
||||||
* cplotr is the entry point for the rightmost point.
|
|
||||||
* We use rastx1 instead of rastx0.
|
|
||||||
cplotr
|
|
||||||
lda ylooklo,y
|
|
||||||
sta ]hbasl
|
|
||||||
lda ylookhi,y
|
|
||||||
_pg_or3 ora #$20
|
|
||||||
sta ]hbasl+1
|
|
||||||
|
|
||||||
* If we just plotted the left point on the same line,
|
|
||||||
* we can skip the Y-lookup by jumping here.
|
|
||||||
cplotrn
|
|
||||||
stx ]savxreg
|
|
||||||
sty ]savyreg
|
|
||||||
|
|
||||||
ldx rastx1l,y ;x coord, lo
|
|
||||||
lda rastx1h,y ;>= 256?
|
|
||||||
beq :lotabl ;no, use the low table
|
|
||||||
ldy div7hi,x
|
|
||||||
lda mod7hi,x
|
|
||||||
bpl cplotcom ;always
|
|
||||||
BREAK ;debug
|
|
||||||
:lotabl ldy div7lo,x
|
|
||||||
lda mod7lo,x
|
|
||||||
|
|
||||||
* Plot the point. The byte offset (0-39) is in Y,
|
|
||||||
* the bit offset (0-6) is in A.
|
|
||||||
cplotcom
|
|
||||||
tax
|
|
||||||
lda colorline,y ;start with color pattern
|
|
||||||
eor (]hbasl),y ;flip all bits
|
|
||||||
and andmask,x ;clear other bits
|
|
||||||
eor (]hbasl),y ;restore ours, set theirs
|
|
||||||
sta (]hbasl),y
|
|
||||||
|
|
||||||
ldx ]savxreg
|
|
||||||
ldy ]savyreg
|
|
||||||
rts
|
|
||||||
|
|
||||||
* Reconfigure calc_circle to either JSR to cplotl/r,
|
|
||||||
* or just BIT the address (a 4-cycle no-op). The
|
|
||||||
* desired instruction is in A.
|
|
||||||
fixcplot
|
|
||||||
do USE_FAST ;*****
|
|
||||||
sta _cp00
|
|
||||||
sta _cp01
|
|
||||||
sta _cp02
|
|
||||||
sta _cp03
|
|
||||||
sta _cp04
|
|
||||||
sta _cp05
|
|
||||||
sta _cp06
|
|
||||||
sta _cp07
|
|
||||||
fin ;*****
|
|
||||||
sta _cp08
|
|
||||||
sta _cp09
|
|
||||||
sta _cp10
|
|
||||||
sta _cp11
|
|
||||||
sta _cp12
|
|
||||||
sta _cp13
|
|
||||||
sta _cp14
|
|
||||||
sta _cp15
|
|
||||||
rts
|
|
|
@ -1,588 +0,0 @@
|
||||||
********************************
|
|
||||||
* *
|
|
||||||
* Fast Apple II Graphics *
|
|
||||||
* By Andy McFadden *
|
|
||||||
* Version 0.3, Aug 2015 *
|
|
||||||
* *
|
|
||||||
* Point and line functions *
|
|
||||||
* (Included by FDRAW.S) *
|
|
||||||
* *
|
|
||||||
* Developed with Merlin-16 *
|
|
||||||
* *
|
|
||||||
********************************
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Draw a single point in the current color.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
DrawPoint
|
|
||||||
]hbasl equ zptr0
|
|
||||||
|
|
||||||
ldy in_y0
|
|
||||||
lda ylooklo,y
|
|
||||||
sta ]hbasl
|
|
||||||
lda ylookhi,y
|
|
||||||
ora g_page
|
|
||||||
sta ]hbasl+1
|
|
||||||
|
|
||||||
ldx in_x0l ;x coord, lo
|
|
||||||
lda in_x0h ;>= 256?
|
|
||||||
beq :lotabl ;no, use the low table
|
|
||||||
ldy div7hi,x
|
|
||||||
lda mod7hi,x
|
|
||||||
bpl :plotit ;always
|
|
||||||
BREAK ;debug
|
|
||||||
:lotabl ldy div7lo,x
|
|
||||||
lda mod7lo,x
|
|
||||||
|
|
||||||
* Plot the point. The byte offset (0-39) is in Y,
|
|
||||||
* the bit offset (0-6) is in A.
|
|
||||||
:plotit
|
|
||||||
tax
|
|
||||||
lda colorline,y ;start with color pattern
|
|
||||||
eor (]hbasl),y ;flip all bits
|
|
||||||
and andmask,x ;clear other bits
|
|
||||||
eor (]hbasl),y ;restore ours, set theirs
|
|
||||||
sta (]hbasl),y
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Draw a line between two points.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
DrawLine
|
|
||||||
|
|
||||||
]hbasl equ zptr0
|
|
||||||
]xposl equ zloc0 ;always left edge
|
|
||||||
]xposh equ zloc1
|
|
||||||
]ypos equ zloc2 ;top or bottom
|
|
||||||
]deltaxl equ zloc3
|
|
||||||
]deltaxh equ zloc4
|
|
||||||
]deltay equ zloc5
|
|
||||||
]count equ zloc6
|
|
||||||
]counth equ zloc7
|
|
||||||
]diff equ zloc8
|
|
||||||
]diffh equ zloc9
|
|
||||||
]andmask equ zloc10
|
|
||||||
]wideflag equ zloc11 ;doesn't really need DP
|
|
||||||
|
|
||||||
* We use a traditional Bresenham run-length approach.
|
|
||||||
* Run-slicing is possible, but the code is larger
|
|
||||||
* and the increased cost means it's only valuable
|
|
||||||
* for longer lines. An optimal solution would switch
|
|
||||||
* approaches based on line length.
|
|
||||||
*
|
|
||||||
* Start by identifying where x0 or x1 is on the
|
|
||||||
* left. To make life simpler we always work from
|
|
||||||
* left to right, flipping the coordinates if
|
|
||||||
* needed.
|
|
||||||
*
|
|
||||||
* We also need to figure out if the line is more
|
|
||||||
* than 255 pixels long -- which, because of
|
|
||||||
* inclusive coordinates, means abs(x0-x1) > 254.
|
|
||||||
lda in_x1l ;assume x0 on left
|
|
||||||
sec
|
|
||||||
sbc in_x0l
|
|
||||||
tax
|
|
||||||
beq checkvert ;low bytes even, check hi
|
|
||||||
lda in_x1h
|
|
||||||
sbc in_x0h
|
|
||||||
bcs lx0left
|
|
||||||
|
|
||||||
* x1 is on the left, so the values are negative
|
|
||||||
* (hi byte in A, lo byte in X)
|
|
||||||
lx0right eor #$ff ;invert hi
|
|
||||||
sta ]deltaxh ;store
|
|
||||||
txa
|
|
||||||
eor #$ff ;invert lo
|
|
||||||
sta ]deltaxl
|
|
||||||
inc ]deltaxl ;add one for 2s complement
|
|
||||||
bne :noinchi ;rolled into high byte?
|
|
||||||
inc ]deltaxh ;yes
|
|
||||||
:noinchi lda in_x1l ;start with x1
|
|
||||||
sta ]xposl
|
|
||||||
lda in_x1h
|
|
||||||
sta ]xposh
|
|
||||||
lda in_y1
|
|
||||||
sta ]ypos
|
|
||||||
sec
|
|
||||||
sbc in_y0 ;compute deltay
|
|
||||||
jmp lncommon
|
|
||||||
|
|
||||||
checkvert
|
|
||||||
lda in_x1h ;diff high bytes
|
|
||||||
sbc in_x0h ;(carry still set)
|
|
||||||
blt lx0right ;width=256, x0 right
|
|
||||||
bne lx0left ;width=256, x0 left
|
|
||||||
jmp vertline ;all zero, go vert
|
|
||||||
|
|
||||||
* (branch back from below)
|
|
||||||
* This is a purely horizontal line. We farm the job
|
|
||||||
* out to the raster fill code for speed. (There's
|
|
||||||
* no problem with the line code handling it; its just
|
|
||||||
* more efficient to let the raster code do it.)
|
|
||||||
phorizontal
|
|
||||||
ldy ]ypos
|
|
||||||
sty rast_top
|
|
||||||
sty rast_bottom
|
|
||||||
lda ]xposl
|
|
||||||
sta rastx0l,y
|
|
||||||
clc
|
|
||||||
adc ]deltaxl ;easier to add delta back
|
|
||||||
sta rastx1l,y ; in than sort out which
|
|
||||||
lda ]xposh ; arg is left vs. right
|
|
||||||
sta rastx0h,y
|
|
||||||
adc ]deltaxh
|
|
||||||
sta rastx1h,y
|
|
||||||
jmp FillRaster
|
|
||||||
|
|
||||||
* x0 is on the left, so the values are positive
|
|
||||||
lx0left stx ]deltaxl
|
|
||||||
sta ]deltaxh
|
|
||||||
lda in_x0l ;start with x0
|
|
||||||
sta ]xposl
|
|
||||||
lda in_x0h
|
|
||||||
sta ]xposh
|
|
||||||
lda in_y0 ;and y0
|
|
||||||
sta ]ypos
|
|
||||||
sec
|
|
||||||
sbc in_y1 ;compute deltay
|
|
||||||
|
|
||||||
* Value of (starty - endy) is in A, flags still set.
|
|
||||||
lncommon
|
|
||||||
bcs :posy
|
|
||||||
eor #$ff ;negative, invert
|
|
||||||
adc #$01
|
|
||||||
sta ]deltay
|
|
||||||
lda #$e8 ;INX
|
|
||||||
bne gotdy
|
|
||||||
:posy
|
|
||||||
_lmb beq phorizontal
|
|
||||||
sta ]deltay
|
|
||||||
lda #$ca ;DEX
|
|
||||||
gotdy sta _hmody
|
|
||||||
sta _vmody
|
|
||||||
sta _wmody
|
|
||||||
|
|
||||||
do 0 ;***** for regression test
|
|
||||||
ldx #$01
|
|
||||||
lda ]deltaxh
|
|
||||||
bne :iswide
|
|
||||||
lda ]deltaxl
|
|
||||||
cmp #$ff ;== 255?
|
|
||||||
beq :iswide
|
|
||||||
ldx #$00 ;notwide
|
|
||||||
:iswide stx $300
|
|
||||||
lda ]xposl
|
|
||||||
sta $301
|
|
||||||
lda ]xposh
|
|
||||||
sta $302
|
|
||||||
lda ]ypos
|
|
||||||
sta $303
|
|
||||||
ldx ]deltaxl
|
|
||||||
stx $304
|
|
||||||
ldx ]deltaxh
|
|
||||||
stx $305
|
|
||||||
ldx ]deltay
|
|
||||||
stx $306
|
|
||||||
lda _hmody
|
|
||||||
and #$20 ;nonzero means inc,
|
|
||||||
sta $307 ; zero means dec
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
* At this point we have the initial X position in
|
|
||||||
* ]startxl/h, the initial Y position in ]starty,
|
|
||||||
* deltax in ]deltaxl, deltay in ]deltay, and we've
|
|
||||||
* tweaked the Y-update instructions to either INC or
|
|
||||||
* DEC depending on the direction of movement.
|
|
||||||
*
|
|
||||||
* The next step is to decide whether the line is
|
|
||||||
* horizontal-dominant or vertical-dominant, and
|
|
||||||
* branch to the appropriate handler.
|
|
||||||
*
|
|
||||||
* The core loops for horiz and vert take about
|
|
||||||
* 80 cycles when moving diagonally, and about
|
|
||||||
* 20 fewer when moving in the primary direction.
|
|
||||||
* The wide-horiz is a bit slower.
|
|
||||||
ldy #$01 ;set "wide" flag to 1
|
|
||||||
lda ]deltaxl
|
|
||||||
ldx ]deltaxh
|
|
||||||
bne horzdom ;width >= 256
|
|
||||||
cmp #$ff ;width == 255
|
|
||||||
beq horzdom
|
|
||||||
dey ;not wide
|
|
||||||
cmp ]deltay
|
|
||||||
bge horzdom ; for diagonal lines
|
|
||||||
jmp vertdom
|
|
||||||
|
|
||||||
* We could special-case pure-diagonal lines here
|
|
||||||
* (just BEQ a couple lines up). It does
|
|
||||||
* represent our worst case. I'm not convinced
|
|
||||||
* we'll see them often enough to make it worthwhile.
|
|
||||||
|
|
||||||
|
|
||||||
* horizontal-dominant
|
|
||||||
horzdom
|
|
||||||
sty ]wideflag
|
|
||||||
sta ]count ;:count = deltax + 1
|
|
||||||
inc ]count
|
|
||||||
lsr ;:diff = deltax / 2
|
|
||||||
sta ]diff
|
|
||||||
|
|
||||||
* set Y to the byte offset in the line
|
|
||||||
* load the AND mask into ]andmask
|
|
||||||
ldx ]xposl
|
|
||||||
lda ]xposh ;>= 256?
|
|
||||||
beq :lotabl ;no, use the low table
|
|
||||||
ldy div7hi,x
|
|
||||||
lda mod7hi,x
|
|
||||||
bpl :gottab ;always
|
|
||||||
* BREAK ;debug
|
|
||||||
:lotabl ldy div7lo,x
|
|
||||||
lda mod7lo,x
|
|
||||||
:gottab
|
|
||||||
tax
|
|
||||||
lda andmask,x
|
|
||||||
sta ]andmask
|
|
||||||
|
|
||||||
* Set initial value for line address.
|
|
||||||
ldx ]ypos
|
|
||||||
lda ylooklo,x
|
|
||||||
sta ]hbasl
|
|
||||||
lda ylookhi,x
|
|
||||||
ora g_page
|
|
||||||
sta ]hbasl+1
|
|
||||||
|
|
||||||
lda ]wideflag ;is this a "wide" line?
|
|
||||||
beq :notwide ;nope, stay local
|
|
||||||
jmp widedom
|
|
||||||
|
|
||||||
:notwide lda colorline,y ;set initial color mask
|
|
||||||
sta _hlcolor+1
|
|
||||||
jmp horzloop
|
|
||||||
|
|
||||||
hrts rts
|
|
||||||
|
|
||||||
* bottom of loop, essentially
|
|
||||||
hnoroll sta ]diff ;3
|
|
||||||
hdecc dec ]count ;5 :count--
|
|
||||||
beq hrts ;2 :while (count != 0)
|
|
||||||
;= 7 or 10
|
|
||||||
|
|
||||||
* We keep the byte offset in the line in Y, and the
|
|
||||||
* line index in X, for the entire loop.
|
|
||||||
horzloop
|
|
||||||
_hlcolor lda #$00 ;2 start with color pattern
|
|
||||||
_lmdh eor (]hbasl),y ;5 flip all bits
|
|
||||||
and ]andmask ;3 clear other bits
|
|
||||||
eor (]hbasl),y ;5 restore ours, set theirs
|
|
||||||
sta (]hbasl),y ;6 = 21
|
|
||||||
|
|
||||||
* Move right. We shift the bit mask that determines
|
|
||||||
* the pixel. When we shift into bit 7, we know it's
|
|
||||||
* time to advance another byte.
|
|
||||||
*
|
|
||||||
* If this is a shallow line we would benefit from
|
|
||||||
* keeping the index in X and just doing a 4-cycle
|
|
||||||
* indexed load to get the mask. Not having the
|
|
||||||
* line number in X makes the line calc more
|
|
||||||
* expensive for steeper lines though.
|
|
||||||
lda ]andmask ;3
|
|
||||||
asl ;2 shift, losing hi bit
|
|
||||||
eor #$80 ;2 set the hi bit
|
|
||||||
bne :noh8 ;3 cleared hi bit?
|
|
||||||
* We could BEQ away and branch back in, but this
|
|
||||||
* happens every 7 iterations, so on average it's
|
|
||||||
* a very small improvement. If we happen to branch
|
|
||||||
* across a page boundary the double-branch adds
|
|
||||||
* two more cycles and we lose.
|
|
||||||
iny ;2 advance to next byte
|
|
||||||
lda colorline,y ;4 update color mask
|
|
||||||
sta _hlcolor+1 ;4
|
|
||||||
lda #$81 ;2 reset
|
|
||||||
:noh8 sta ]andmask ;3 = 13 + ((12-1)/7) = 14
|
|
||||||
|
|
||||||
* Update error diff.
|
|
||||||
lda ]diff ;3
|
|
||||||
sec ;2
|
|
||||||
sbc ]deltay ;3 :diff -= deltay
|
|
||||||
bcs hnoroll ;2+ :if (diff < 0) ...
|
|
||||||
;= 11 level, 10 up/down
|
|
||||||
adc ]deltaxl ;3 : diff += deltax
|
|
||||||
sta ]diff ;3
|
|
||||||
_hmody inx ;2 : ypos++ (or --)
|
|
||||||
lda ylooklo,x ;4 update hbasl after line
|
|
||||||
sta ]hbasl ;3 change
|
|
||||||
lda ylookhi,x ;4
|
|
||||||
_pg_or4 ora #$20 ;2
|
|
||||||
sta ]hbasl+1 ;3
|
|
||||||
bne hdecc ;3 = +27 this path -> 37
|
|
||||||
BREAK
|
|
||||||
* horizontal: 10+21+14+11=56 cycles/pixel
|
|
||||||
* diagonal: 7+21+14+37=79 cycles/pixel
|
|
||||||
|
|
||||||
|
|
||||||
* Vertical-dominant line. Could go up or down.
|
|
||||||
vertdom
|
|
||||||
ldx in_y0
|
|
||||||
cpx ]ypos ;starting at y0?
|
|
||||||
bne :endy0 ;yup
|
|
||||||
ldx in_y1 ;nope
|
|
||||||
:endy0 stx _vchk+1 ;end condition
|
|
||||||
|
|
||||||
lda ]deltay
|
|
||||||
lsr
|
|
||||||
sta ]diff ;:diff = deltay / 2
|
|
||||||
|
|
||||||
* set Y to the byte offset in the line
|
|
||||||
* load the AND mask into ]andmask
|
|
||||||
ldx ]xposl
|
|
||||||
lda ]xposh ;>= 256?
|
|
||||||
beq :lotabl ;no, use the low table
|
|
||||||
ldy div7hi,x
|
|
||||||
lda mod7hi,x
|
|
||||||
bpl :gottab ;always
|
|
||||||
BREAK ;debug
|
|
||||||
:lotabl ldy div7lo,x
|
|
||||||
lda mod7lo,x
|
|
||||||
:gottab
|
|
||||||
tax
|
|
||||||
lda andmask,x ;initial pixel mask
|
|
||||||
sta ]andmask
|
|
||||||
|
|
||||||
lda colorline,y ;initial color mask
|
|
||||||
sta _vlcolor+1
|
|
||||||
|
|
||||||
ldx ]ypos
|
|
||||||
jmp vertloop
|
|
||||||
|
|
||||||
* We keep the byte offset in the line in Y, and the
|
|
||||||
* line index in X, for the entire loop.
|
|
||||||
|
|
||||||
* Bottom of loop, essentially.
|
|
||||||
vnoroll sta ]diff ;3
|
|
||||||
|
|
||||||
vertloop
|
|
||||||
lda ylooklo,x ;4
|
|
||||||
sta ]hbasl ;3
|
|
||||||
lda ylookhi,x ;4
|
|
||||||
_pg_or5 ora #$20 ;2
|
|
||||||
sta ]hbasl+1 ;3 = 16
|
|
||||||
|
|
||||||
_vlcolor lda #$00 ;2 start with color pattern
|
|
||||||
_lmdv eor (]hbasl),y ;5 flip all bits
|
|
||||||
and ]andmask ;3 clear other bits
|
|
||||||
eor (]hbasl),y ;5 restore ours, set theirs
|
|
||||||
sta (]hbasl),y ;6 = 21
|
|
||||||
|
|
||||||
_vchk cpx #$00 ;2 was this last line?
|
|
||||||
beq vrts ;2 yes, done
|
|
||||||
_vmody inx ;2 :ypos++ (or --)
|
|
||||||
|
|
||||||
* Update error diff.
|
|
||||||
lda ]diff ;3
|
|
||||||
sec ;2
|
|
||||||
sbc ]deltaxl ;3 :diff -= deltax
|
|
||||||
bcs vnoroll ;2 :if (diff < 0) ...
|
|
||||||
;= 10 vert, 9 move right
|
|
||||||
|
|
||||||
adc ]deltay ;3 : diff += deltay
|
|
||||||
sta ]diff ;3
|
|
||||||
* Move right. We shift the bit mask that determines
|
|
||||||
* the pixel. When we shift into bit 7, we know it's
|
|
||||||
* time to advance another byte.
|
|
||||||
lda ]andmask ;3
|
|
||||||
asl ;2 shift, losing hi bit
|
|
||||||
eor #$80 ;2 set the hi bit
|
|
||||||
beq :is8 ;2+ goes to zero on 8th bit
|
|
||||||
sta ]andmask ;3
|
|
||||||
bne vertloop ;3 = 21 + (18/7) = 24
|
|
||||||
BREAK
|
|
||||||
|
|
||||||
:is8 iny ;2 advance to next byte
|
|
||||||
lda colorline,y ;4 update color
|
|
||||||
sta _vlcolor+1 ;4
|
|
||||||
lda #$81 ;2 reset
|
|
||||||
sta ]andmask ;3
|
|
||||||
bne vertloop ;3 = 18
|
|
||||||
BREAK
|
|
||||||
vrts rts
|
|
||||||
* vertical: 3 + 16 + 21 + 6 + 10 = 56 cycles
|
|
||||||
* diagonal: 16 + 21 + 6 + 9 + 24 = 76 cycles
|
|
||||||
|
|
||||||
|
|
||||||
* "Wide" horizontally-dominant loop. We have to
|
|
||||||
* maintain error-diff and deltax as 16-bit values.
|
|
||||||
* Most of the setup from the "narrow" version carried
|
|
||||||
* over, but we have to re-do the count and diff.
|
|
||||||
*
|
|
||||||
* Normally we set count to (deltax + 1) and decrement
|
|
||||||
* to zero, but it's actually easier to set it equal
|
|
||||||
* to deltax and check for -1.
|
|
||||||
widedom
|
|
||||||
lda ]deltaxh ;:count = deltax
|
|
||||||
sta ]counth
|
|
||||||
ldx ]deltaxl
|
|
||||||
stx ]count
|
|
||||||
stx ]diff
|
|
||||||
lsr ;:diff = deltax / 2
|
|
||||||
ror ]diff
|
|
||||||
sta ]diffh
|
|
||||||
ldx ]ypos
|
|
||||||
|
|
||||||
lda colorline,y ;set initial color mask
|
|
||||||
sta _wlcolor+1
|
|
||||||
|
|
||||||
* We keep the byte offset in the line in Y, and the
|
|
||||||
* line index in X, for the entire loop.
|
|
||||||
wideloop
|
|
||||||
_wlcolor lda #$00 ;2 start with color pattern
|
|
||||||
_lmdw eor (]hbasl),y ;5 flip all bits
|
|
||||||
and ]andmask ;3 clear other bits
|
|
||||||
eor (]hbasl),y ;5 restore ours, set theirs
|
|
||||||
sta (]hbasl),y ;6 = 21
|
|
||||||
|
|
||||||
* Move right. We shift the bit mask that determines
|
|
||||||
* the pixel. When we shift into bit 7, we know it's
|
|
||||||
* time to advance another byte.
|
|
||||||
lda ]andmask ;3
|
|
||||||
asl ;2 shift, losing hi bit
|
|
||||||
eor #$80 ;2 set the hi bit
|
|
||||||
bne :not7 ;3 goes to zero on 8th bit
|
|
||||||
iny ; 2 advance to next byte
|
|
||||||
lda colorline,y ; 4 update color mask
|
|
||||||
sta _hlcolor+1 ; 4
|
|
||||||
lda #$81 ; 2 reset
|
|
||||||
:not7 sta ]andmask ;3 = 13 usually, 25 every 7
|
|
||||||
|
|
||||||
* Update error diff, which is a positive number. If
|
|
||||||
* it goes negative ("if (diff < 0)") we act.
|
|
||||||
lda ]diff
|
|
||||||
sec
|
|
||||||
sbc ]deltay ;:diff -= deltay
|
|
||||||
bcs wnoroll ;didn't even roll low byte
|
|
||||||
dec ]diffh ;check hi byte
|
|
||||||
bpl wnoroll ;went 1->0, keep going
|
|
||||||
|
|
||||||
adc ]deltaxl ;: diff += deltax
|
|
||||||
sta ]diff
|
|
||||||
lda ]diffh
|
|
||||||
adc ]deltaxh
|
|
||||||
sta ]diffh
|
|
||||||
_wmody inx ;: ypos++ (or --)
|
|
||||||
lda ylooklo,x ;update hbasl after line
|
|
||||||
sta ]hbasl ; change
|
|
||||||
lda ylookhi,x
|
|
||||||
_pg_or6 ora #$20
|
|
||||||
sta ]hbasl+1
|
|
||||||
bne wdecc
|
|
||||||
BREAK
|
|
||||||
|
|
||||||
wnoroll sta ]diff
|
|
||||||
|
|
||||||
wdecc dec ]count ;5 :count--
|
|
||||||
lda ]count ;3
|
|
||||||
cmp #$ff ;2
|
|
||||||
bne wideloop ;3 :while (count > -1)
|
|
||||||
dec ]counth ;low rolled, decr high
|
|
||||||
beq wideloop ;went 1->0, keep going
|
|
||||||
rts
|
|
||||||
|
|
||||||
|
|
||||||
* Pure-vertical line. These are common in certain
|
|
||||||
* applications, and checking for it only adds two
|
|
||||||
* cycles to the general case.
|
|
||||||
vertline
|
|
||||||
ldx in_y0
|
|
||||||
ldy in_y1
|
|
||||||
cpx in_y1 ;y0 < y1?
|
|
||||||
blt :usey0 ;yes, go from y0 to y1
|
|
||||||
txa ;swap X/A
|
|
||||||
tay
|
|
||||||
ldx in_y1
|
|
||||||
:usey0 stx ]ypos
|
|
||||||
iny
|
|
||||||
sty _pvytest+1
|
|
||||||
|
|
||||||
ldx in_x0l ;xc lo
|
|
||||||
lda in_x0h ;>= 256?
|
|
||||||
beq :lotabl
|
|
||||||
ldy div7hi,x
|
|
||||||
lda mod7hi,x
|
|
||||||
bpl :gotit ;always
|
|
||||||
:lotabl ldy div7lo,x
|
|
||||||
lda mod7lo,x
|
|
||||||
|
|
||||||
* Byte offset is in Y, mod-7 value is in A.
|
|
||||||
:gotit tax
|
|
||||||
lda andmask,x
|
|
||||||
sta _pvand+1 ;this doesn't change
|
|
||||||
|
|
||||||
lda colorline,y
|
|
||||||
sta _pvcolor+1 ;nor does this
|
|
||||||
|
|
||||||
ldx ]ypos ;top line
|
|
||||||
|
|
||||||
* There's a trick where, when (linenum & 0x07) is
|
|
||||||
* nonzero, you just add 4 to hbasl+1 instead of
|
|
||||||
* re-doing the lookup. However, TXA+AND+BEQ
|
|
||||||
* followed by LDA+CLC+ADC+STA is 16 cycles, the same
|
|
||||||
* as our self-modified lookup, so it's not a win.
|
|
||||||
* (And if we used a second ylookhi and self-modded
|
|
||||||
* the table address, we could shave off another 2.)
|
|
||||||
|
|
||||||
* Main pure-vertical loop
|
|
||||||
pverloop
|
|
||||||
lda ylooklo,x ;4
|
|
||||||
sta ]hbasl ;3
|
|
||||||
lda ylookhi,x ;4
|
|
||||||
_pg_or7 ora #$20 ;2
|
|
||||||
sta ]hbasl+1 ;3 (= 16)
|
|
||||||
|
|
||||||
_pvcolor lda #$00 ;2 start with color pattern
|
|
||||||
_lmdpv eor (]hbasl),y ;5 flip all bits
|
|
||||||
_pvand and #$00 ;2 clear other bits
|
|
||||||
eor (]hbasl),y ;5
|
|
||||||
sta (]hbasl),y ;6 (= 20)
|
|
||||||
|
|
||||||
inx ;2
|
|
||||||
_pvytest cpx #$00 ;2 done?
|
|
||||||
bne pverloop ;3 = 7
|
|
||||||
rts
|
|
||||||
* 43 cycles/pixel
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Set the line mode according to in_arg
|
|
||||||
*
|
|
||||||
* A slightly silly feature to get xdraw lines
|
|
||||||
* without really working for it.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
SetLineMode
|
|
||||||
lda in_arg
|
|
||||||
beq :standard
|
|
||||||
|
|
||||||
* configure for xdraw
|
|
||||||
lda #$24 ;BIT dp
|
|
||||||
sta _lmb
|
|
||||||
sta _lmdh
|
|
||||||
sta _lmdv
|
|
||||||
sta _lmdw
|
|
||||||
sta _lmdpv
|
|
||||||
rts
|
|
||||||
|
|
||||||
* configure for standard drawing
|
|
||||||
:standard lda #$f0 ;BEQ
|
|
||||||
sta _lmb
|
|
||||||
lda #$51 ;EOR (dp),y
|
|
||||||
sta _lmdh
|
|
||||||
sta _lmdv
|
|
||||||
sta _lmdw
|
|
||||||
sta _lmdpv
|
|
||||||
rts
|
|
805
fdraw/FDRAW.S
805
fdraw/FDRAW.S
|
@ -1,805 +0,0 @@
|
||||||
********************************
|
|
||||||
* *
|
|
||||||
* Fast Apple II Graphics *
|
|
||||||
* By Andy McFadden *
|
|
||||||
* Version 0.3, Aug 2015 *
|
|
||||||
* *
|
|
||||||
* Main source file *
|
|
||||||
* *
|
|
||||||
* Developed with Merlin-16 *
|
|
||||||
* *
|
|
||||||
********************************
|
|
||||||
|
|
||||||
* Set to 1 to build FDRAW.FAST, set to zero to
|
|
||||||
* build FDRAW.SMALL.
|
|
||||||
USE_FAST equ 1
|
|
||||||
|
|
||||||
* Set to 1 to turn on beeps/clicks for debugging.
|
|
||||||
NOISE_ON equ 0
|
|
||||||
|
|
||||||
|
|
||||||
lst off
|
|
||||||
org $9400 ;;; CUSTOMIZED FOR APPLECORN
|
|
||||||
|
|
||||||
*
|
|
||||||
* Macros.
|
|
||||||
*
|
|
||||||
spkr equ $c030
|
|
||||||
bell equ $ff3a
|
|
||||||
|
|
||||||
* If enabled, click the speaker (changes flags only).
|
|
||||||
CLICK mac
|
|
||||||
do NOISE_ON
|
|
||||||
bit spkr
|
|
||||||
fin
|
|
||||||
<<<
|
|
||||||
* If enabled, beep the speaker (scrambles regs).
|
|
||||||
BEEP mac
|
|
||||||
do NOISE_ON
|
|
||||||
jsr bell
|
|
||||||
fin
|
|
||||||
<<<
|
|
||||||
* If enabled, insert a BRK.
|
|
||||||
BREAK mac
|
|
||||||
do NOISE_ON
|
|
||||||
brk $99
|
|
||||||
fin
|
|
||||||
<<<
|
|
||||||
|
|
||||||
* In "fast" mode, we align tables on page boundaries so we
|
|
||||||
* don't take a 1-cycle hit when the indexing crosses a page.
|
|
||||||
* In "small" mode, we skip the alignment.
|
|
||||||
PG_ALIGN mac
|
|
||||||
do USE_FAST
|
|
||||||
ds \
|
|
||||||
fin
|
|
||||||
<<<
|
|
||||||
|
|
||||||
*
|
|
||||||
* Hi-res screen constants.
|
|
||||||
*
|
|
||||||
BYTES_PER_ROW = 40
|
|
||||||
NUM_ROWS = 192
|
|
||||||
NUM_COLS = 280
|
|
||||||
|
|
||||||
*
|
|
||||||
* Variable storage. We assign generic names to
|
|
||||||
* zero-page scratch locations, then assign variables
|
|
||||||
* with real names to these.
|
|
||||||
*
|
|
||||||
* 06-09 are unused (except by SWEET-16)
|
|
||||||
* 1a-1d are Applesoft hi-res scratch
|
|
||||||
* cc-cf are only used by INTBASIC
|
|
||||||
* eb-ef and ff appear totally unused by ROM routines
|
|
||||||
*
|
|
||||||
zptr0 equ $1a ;2b
|
|
||||||
zloc0 equ $06
|
|
||||||
zloc1 equ $07
|
|
||||||
zloc2 equ $08
|
|
||||||
zloc3 equ $09
|
|
||||||
zloc4 equ $1c
|
|
||||||
zloc5 equ $1d
|
|
||||||
zloc6 equ $cc
|
|
||||||
zloc7 equ $cd
|
|
||||||
zloc8 equ $ce
|
|
||||||
zloc9 equ $cf
|
|
||||||
zloc10 equ $eb
|
|
||||||
zloc11 equ $ec
|
|
||||||
zloc12 equ $ed
|
|
||||||
zloc13 equ $ee
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Entry points for external programs.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
Entry
|
|
||||||
jmp Init ;initialize data tables
|
|
||||||
dfb 0,3 ;version number
|
|
||||||
|
|
||||||
*
|
|
||||||
* Parameters passed from external programs.
|
|
||||||
*
|
|
||||||
in_arg ds 1 ;generic argument
|
|
||||||
in_x0l ds 1 ;X coordinate 0, low part
|
|
||||||
in_x0h ds 1 ;X coordinate 0, high part
|
|
||||||
in_y0 ds 1 ;Y coordinate 0
|
|
||||||
in_x1l ds 1
|
|
||||||
in_x1h ds 1
|
|
||||||
in_y1 ds 1
|
|
||||||
in_rad ds 1 ;radius for circles
|
|
||||||
|
|
||||||
ds 3 ;pad to 16 bytes
|
|
||||||
|
|
||||||
jmp SetColor
|
|
||||||
jmp SetPage
|
|
||||||
jmp Clear
|
|
||||||
jmp DrawPoint
|
|
||||||
jmp DrawLine
|
|
||||||
jmp DrawRect
|
|
||||||
jmp FillRect
|
|
||||||
jmp DrawCircle
|
|
||||||
jmp FillCircle
|
|
||||||
jmp SetLineMode
|
|
||||||
jmp noimpl ;reserved2
|
|
||||||
jmp FillRaster
|
|
||||||
|
|
||||||
* Raster fill values. Top, bottom, and pointers to tables
|
|
||||||
* for the benefit of external callers.
|
|
||||||
rast_top ds 1
|
|
||||||
rast_bottom ds 1
|
|
||||||
da rastx0l
|
|
||||||
da rastx0h
|
|
||||||
da rastx1l
|
|
||||||
da rastx1h
|
|
||||||
|
|
||||||
noimpl rts
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Global variables.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
|
|
||||||
g_inited dfb 0 ;initialized?
|
|
||||||
g_color dfb 0 ;hi-res color (0-7)
|
|
||||||
g_page dfb $20 ;hi-res page ($20 or $40)
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Initialize.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
Init
|
|
||||||
lda #$00
|
|
||||||
sta in_arg
|
|
||||||
jsr SetColor ;set color to zero
|
|
||||||
jsr SetLineMode ;set normal lines
|
|
||||||
lda #$20
|
|
||||||
sta in_arg
|
|
||||||
sta g_inited
|
|
||||||
jmp SetPage ;set hi-res page 1
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Set the color.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
SetColor
|
|
||||||
lda in_arg
|
|
||||||
cmp g_color ;same as the old color?
|
|
||||||
beq :done
|
|
||||||
|
|
||||||
and #$07 ;safety first
|
|
||||||
sta g_color
|
|
||||||
|
|
||||||
* Update the "colorline" table, which provides a quick color
|
|
||||||
* lookup for odd/even bytes. We could also have one table
|
|
||||||
* per color and self-mod the "LDA addr,y" instructions to
|
|
||||||
* point to the current one, but that uses a bunch of memory
|
|
||||||
* and is kind of ugly. Takes 16 + (12 * 40) = 496 cycles.
|
|
||||||
tax ;2
|
|
||||||
lda xormask,x ;4
|
|
||||||
sta :_xormsk+1 ;4
|
|
||||||
|
|
||||||
lda oddcolor,x ;4
|
|
||||||
ldy #BYTES_PER_ROW-1 ;2
|
|
||||||
]loop sta colorline,y ;5
|
|
||||||
:_xormsk eor #$00 ;2
|
|
||||||
dey ;2
|
|
||||||
bpl ]loop ;3
|
|
||||||
|
|
||||||
:done rts
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Set the page.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
SetPage
|
|
||||||
lda g_inited ;let's just check this
|
|
||||||
beq noinit ; (not called too often)
|
|
||||||
|
|
||||||
lda in_arg
|
|
||||||
cmp #$20
|
|
||||||
beq :good
|
|
||||||
cmp #$40
|
|
||||||
beq :good
|
|
||||||
jmp bell
|
|
||||||
:good
|
|
||||||
sta g_page
|
|
||||||
|
|
||||||
do 0 ;*****
|
|
||||||
cmp ylookhi
|
|
||||||
beq :tabok
|
|
||||||
* Check to see if the values currently in the Y-lookup table
|
|
||||||
* match our current page setting. If they don't, we need to
|
|
||||||
* adjust the code that does lookups.
|
|
||||||
|
|
||||||
* This approach modifies the table itself, paying a large
|
|
||||||
* cost now so we don't have to pay it on every lookup.
|
|
||||||
* However, this costs 2+(16*192)=3074 cycles, while an
|
|
||||||
* "ORA imm" only adds two to each lookup, so we'd have
|
|
||||||
* to do a lot of drawing to make this worthwhile.
|
|
||||||
* (Note: assumes ylookhi is based at $2000 not $0000)
|
|
||||||
ldy #NUM_ROWS ;2
|
|
||||||
]loop lda ylookhi-1,y ;4
|
|
||||||
eor #$60 ;2 $20 <--> $40
|
|
||||||
sta ylookhi-1,y ;5
|
|
||||||
dey ;2
|
|
||||||
bne ]loop ;3
|
|
||||||
|
|
||||||
else ;*****
|
|
||||||
|
|
||||||
* This approach uses self-modifying code to update the
|
|
||||||
* relevant instructions. It's a bit messy to have it
|
|
||||||
* here, but it saves us from having to do it on
|
|
||||||
* every call.
|
|
||||||
*
|
|
||||||
* We could also have a second y-lookup table and
|
|
||||||
* use this to update the pointers. That would let
|
|
||||||
* us drop the "ORA imm" entirely, without the cost
|
|
||||||
* of the rewrite above, but eating up another 192 bytes.
|
|
||||||
sta _pg_or1+1 ;rastfill
|
|
||||||
sta _pg_or2+1 ;circle hplot
|
|
||||||
sta _pg_or3+1 ;circle hplot
|
|
||||||
sta _pg_or4+1 ;drawline
|
|
||||||
sta _pg_or5+1 ;drawline
|
|
||||||
sta _pg_or6+1 ;drawline
|
|
||||||
sta _pg_or7+1 ;drawline
|
|
||||||
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
:tabok rts
|
|
||||||
|
|
||||||
noinit ldy #$00
|
|
||||||
]loop lda :initmsg,y
|
|
||||||
beq :done
|
|
||||||
jsr $fded ;cout
|
|
||||||
iny
|
|
||||||
bne ]loop
|
|
||||||
:done rts
|
|
||||||
|
|
||||||
:initmsg asc "FDRAW NOT INITIALIZED",87,87,00
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Clear the screen to the current color.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
Clear
|
|
||||||
|
|
||||||
do USE_FAST ;*****
|
|
||||||
* This performs a "visually linear" clear, erasing the screen
|
|
||||||
* from left to right and top to bottom. To reduce the amount
|
|
||||||
* of code required we erase in thirds (top/middle/bottom).
|
|
||||||
*
|
|
||||||
* Compare to a "venetian blind" clear, which is what you get
|
|
||||||
* if you erase memory linearly.
|
|
||||||
*
|
|
||||||
* The docs discuss different approaches. This version
|
|
||||||
* requires ((2 + 5*64 + 11) * 40 + 14) * 3 = 40002 cycles.
|
|
||||||
* If we didn't divide it into thirds to keep the top-down
|
|
||||||
* look, we'd need (5*64 + 9) * 120 = 39480 cycles, so
|
|
||||||
* we're spending 522 cycles to avoid the venetian look.
|
|
||||||
lda :clrloop+2
|
|
||||||
cmp g_page
|
|
||||||
beq :pageok
|
|
||||||
|
|
||||||
* We're on the wrong hi-res page. Flip to the other one.
|
|
||||||
* 4 + (20*64) = 1284 cycles to do the flip (+ a few more
|
|
||||||
* because we're probably crossing a page boundary).
|
|
||||||
BEEP
|
|
||||||
ldy #NUM_ROWS ;2
|
|
||||||
]loop lda :clrloop-3+2,y ;4
|
|
||||||
eor #$60 ;2
|
|
||||||
sta :clrloop-3+2,y ;5
|
|
||||||
dey ;2
|
|
||||||
dey ;2
|
|
||||||
dey ;2
|
|
||||||
bne ]loop ;3
|
|
||||||
|
|
||||||
:pageok ldx g_color ;grab the current color
|
|
||||||
lda xormask,x
|
|
||||||
sta :_xormsk+1
|
|
||||||
lda evencolor,x
|
|
||||||
|
|
||||||
ldy #0
|
|
||||||
jsr :clearthird
|
|
||||||
ldy #BYTES_PER_ROW
|
|
||||||
jsr :clearthird
|
|
||||||
ldy #BYTES_PER_ROW*2
|
|
||||||
* fall through into :clearthird for final pass
|
|
||||||
|
|
||||||
:clearthird
|
|
||||||
ldx #BYTES_PER_ROW-1 ;2
|
|
||||||
:clrloop sta $2000,y ;5 (* 64)
|
|
||||||
sta $2400,y ;this could probably be
|
|
||||||
sta $2800,y ; done with LUP math
|
|
||||||
sta $2c00,y
|
|
||||||
sta $3000,y
|
|
||||||
sta $3400,y
|
|
||||||
sta $3800,y
|
|
||||||
sta $3c00,y
|
|
||||||
sta $2080,y
|
|
||||||
sta $2480,y
|
|
||||||
sta $2880,y
|
|
||||||
sta $2c80,y
|
|
||||||
sta $3080,y
|
|
||||||
sta $3480,y
|
|
||||||
sta $3880,y
|
|
||||||
sta $3c80,y
|
|
||||||
sta $2100,y
|
|
||||||
sta $2500,y
|
|
||||||
sta $2900,y
|
|
||||||
sta $2d00,y
|
|
||||||
sta $3100,y
|
|
||||||
sta $3500,y
|
|
||||||
sta $3900,y
|
|
||||||
sta $3d00,y
|
|
||||||
sta $2180,y
|
|
||||||
sta $2580,y
|
|
||||||
sta $2980,y
|
|
||||||
sta $2d80,y
|
|
||||||
sta $3180,y
|
|
||||||
sta $3580,y
|
|
||||||
sta $3980,y
|
|
||||||
sta $3d80,y
|
|
||||||
sta $2200,y
|
|
||||||
sta $2600,y
|
|
||||||
sta $2a00,y
|
|
||||||
sta $2e00,y
|
|
||||||
sta $3200,y
|
|
||||||
sta $3600,y
|
|
||||||
sta $3a00,y
|
|
||||||
sta $3e00,y
|
|
||||||
sta $2280,y
|
|
||||||
sta $2680,y
|
|
||||||
sta $2a80,y
|
|
||||||
sta $2e80,y
|
|
||||||
sta $3280,y
|
|
||||||
sta $3680,y
|
|
||||||
sta $3a80,y
|
|
||||||
sta $3e80,y
|
|
||||||
sta $2300,y
|
|
||||||
sta $2700,y
|
|
||||||
sta $2b00,y
|
|
||||||
sta $2f00,y
|
|
||||||
sta $3300,y
|
|
||||||
sta $3700,y
|
|
||||||
sta $3b00,y
|
|
||||||
sta $3f00,y
|
|
||||||
sta $2380,y
|
|
||||||
sta $2780,y
|
|
||||||
sta $2b80,y
|
|
||||||
sta $2f80,y
|
|
||||||
sta $3380,y
|
|
||||||
sta $3780,y
|
|
||||||
sta $3b80,y
|
|
||||||
sta $3f80,y
|
|
||||||
:_xormsk eor #$00 ;2 flip odd/even bits
|
|
||||||
iny ;2
|
|
||||||
dex ;2
|
|
||||||
bmi :done ;2
|
|
||||||
jmp :clrloop ;3
|
|
||||||
:done rts
|
|
||||||
|
|
||||||
else ;***** not USE_FAST
|
|
||||||
|
|
||||||
* This version was suggested by Marcus Heuser on
|
|
||||||
* comp.sys.apple2.programmer. It does a "venetian blind"
|
|
||||||
* clear, and takes (5 * 32 + 7) * 248 = 41416 cycles.
|
|
||||||
* It overwrites half of the screen holes.
|
|
||||||
lda :clrloop+5
|
|
||||||
cmp g_page
|
|
||||||
beq :pageok
|
|
||||||
|
|
||||||
* We're on the wrong hi-res page. Flip to the other one.
|
|
||||||
* 12 + (20*31) = 632 cycles to do the flip. We have to
|
|
||||||
* single out the first entry because it's $1f not $20.
|
|
||||||
BEEP
|
|
||||||
lda :clrloop+2 ;4
|
|
||||||
eor #$20 ;2 $1f <-> $3f
|
|
||||||
sta :clrloop+2 ;4
|
|
||||||
ldy #31*3 ;2
|
|
||||||
]loop lda :clrloop+2,y ;4
|
|
||||||
eor #$60 ;2 $20 <-> $40
|
|
||||||
sta :clrloop+2,y ;5
|
|
||||||
dey ;2
|
|
||||||
dey ;2
|
|
||||||
dey ;2
|
|
||||||
bne ]loop ;3
|
|
||||||
|
|
||||||
:pageok ldx g_color
|
|
||||||
lda xormask,x
|
|
||||||
sta :_xormsk+1
|
|
||||||
lda oddcolor,x
|
|
||||||
ldy #248 ;120 + 8 + 120
|
|
||||||
:clrloop
|
|
||||||
]addr = $1fff
|
|
||||||
lup 32 ;begin a loop in assembler
|
|
||||||
sta ]addr,y ;5
|
|
||||||
]addr = ]addr+$100 ;sta 20ff,21ff,...
|
|
||||||
--^
|
|
||||||
:_xormsk eor #$00 ;2
|
|
||||||
dey ;2
|
|
||||||
bne :clrloop ;3
|
|
||||||
rts
|
|
||||||
|
|
||||||
fin ;***** not USE_FAST
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Draw rectangle outline.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
DrawRect
|
|
||||||
* We could just issue 4 line draw calls here, maybe
|
|
||||||
* adjusting the vertical lines by 1 pixel up/down to
|
|
||||||
* avoid overdraw. But if the user wanted 4 lines,
|
|
||||||
* they could just draw 4 lines. Instead, we're going
|
|
||||||
* to draw a double line on each edge to ensure that
|
|
||||||
* the outline rectangle always has the correct color.
|
|
||||||
*
|
|
||||||
* Rather than draw two vertical lines, we draw a
|
|
||||||
* two-pixel-wide filled rectangle on each side.
|
|
||||||
*
|
|
||||||
* We don't want to double-up if the rect is only one
|
|
||||||
* pixel wide, so we have to check for that.
|
|
||||||
*
|
|
||||||
* If the rect is one pixel high, it's just a line.
|
|
||||||
* If it's two pixels high, we don't need to draw
|
|
||||||
* the left/right edges, just the top/bottom lines.
|
|
||||||
* If it's more than two tall, we don't need to draw
|
|
||||||
* the left/right edges on the top and bottom lines,
|
|
||||||
* so we save a few cycles by skipping those.
|
|
||||||
|
|
||||||
lda in_y1 ;copy top/bottom to local
|
|
||||||
sta rast_bottom
|
|
||||||
dec rast_bottom ;move up one
|
|
||||||
sec
|
|
||||||
sbc in_y0
|
|
||||||
beq :isline ;1 pixel high, just draw line
|
|
||||||
cmp #1
|
|
||||||
beq :twolines ;2 pixels high, lines only
|
|
||||||
ldy in_y0
|
|
||||||
iny ;start down a line
|
|
||||||
sty rast_top
|
|
||||||
|
|
||||||
lda in_x0h ;check to see if left/right
|
|
||||||
cmp in_x1h ; coords are the same; if
|
|
||||||
bne :notline ; so, going +1/-1 at edge
|
|
||||||
lda in_x0l ; will overdraw.
|
|
||||||
cmp in_x1l
|
|
||||||
bne :notlin1
|
|
||||||
|
|
||||||
:isline jmp DrawLine ;just treat like line
|
|
||||||
|
|
||||||
* Set up left edge. Top line is in Y.
|
|
||||||
:notline lda in_x0l
|
|
||||||
:notlin1 sta rastx0l,y
|
|
||||||
clc
|
|
||||||
adc #1
|
|
||||||
sta rastx1l,y
|
|
||||||
lda in_x0h
|
|
||||||
ora #$80 ;"repeat" flag
|
|
||||||
sta rastx0h,y
|
|
||||||
and #$7f
|
|
||||||
adc #0
|
|
||||||
sta rastx1h,y
|
|
||||||
jsr FillRaster
|
|
||||||
|
|
||||||
ldy rast_top
|
|
||||||
lda in_x1l ;now set up right edge
|
|
||||||
sta rastx1l,y
|
|
||||||
sec
|
|
||||||
sbc #1
|
|
||||||
sta rastx0l,y
|
|
||||||
lda in_x1h
|
|
||||||
sta rastx1h,y
|
|
||||||
sbc #0
|
|
||||||
ora #$80 ;"repeat" flag
|
|
||||||
sta rastx0h,y
|
|
||||||
jsr FillRaster
|
|
||||||
|
|
||||||
* Now the top/bottom lines.
|
|
||||||
:twolines
|
|
||||||
ldy in_y0
|
|
||||||
jsr :drawline
|
|
||||||
ldy in_y1
|
|
||||||
|
|
||||||
:drawline
|
|
||||||
sty rast_top
|
|
||||||
sty rast_bottom
|
|
||||||
lda in_x0l ;copy left/right to the
|
|
||||||
sta rastx0l,y ; table entry for the
|
|
||||||
lda in_x0h ; appropriate line
|
|
||||||
sta rastx0h,y
|
|
||||||
lda in_x1l
|
|
||||||
sta rastx1l,y
|
|
||||||
lda in_x1h
|
|
||||||
sta rastx1h,y
|
|
||||||
jmp FillRaster
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Draw filled rectangle.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
FillRect
|
|
||||||
* Just fill out the raster table and call the fill routine.
|
|
||||||
* We require y0=top, y1=bottom, x0=left, x1=right.
|
|
||||||
ldy in_y0
|
|
||||||
sty rast_top
|
|
||||||
lda in_y1
|
|
||||||
sta rast_bottom
|
|
||||||
|
|
||||||
lda in_x0l
|
|
||||||
sta rastx0l,y
|
|
||||||
lda in_x0h
|
|
||||||
ora #$80 ;"repeat" flag
|
|
||||||
sta rastx0h,y
|
|
||||||
lda in_x1l
|
|
||||||
sta rastx1l,y
|
|
||||||
lda in_x1h
|
|
||||||
sta rastx1h,y
|
|
||||||
|
|
||||||
jmp FillRaster
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Fill an area defined by the raster tables.
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
FillRaster
|
|
||||||
|
|
||||||
* Render rasterized output. The left and right edges
|
|
||||||
* are stored in the rastx0/rastx1 tables, and the top
|
|
||||||
* and bottom-most pixels are in rast_top/rast_bottom.
|
|
||||||
*
|
|
||||||
* This can be used to render an arbitrary convex
|
|
||||||
* polygon after it has been rasterized.
|
|
||||||
*
|
|
||||||
* If the high bit of the high byte of X0 is set, we
|
|
||||||
* go into "repeat" mode, where we just repeat the
|
|
||||||
* previous line. This saves about 40 cycles of
|
|
||||||
* overhead per line when drawing rectangles, plus
|
|
||||||
* what we would have to spend to populate multiple
|
|
||||||
* lines of the raster table. It only increases the
|
|
||||||
* general per-line cost by 3 cycles.
|
|
||||||
*
|
|
||||||
* We could use the "repeat" flag to use this code to
|
|
||||||
* draw vertical lines, though that's mostly of value
|
|
||||||
* to an external caller who knows ahead of time that
|
|
||||||
* the line is vertical. The DrawLine code is pretty
|
|
||||||
* good with vertical lines, and adding additional
|
|
||||||
* setup time to every vertical-dominant line to
|
|
||||||
* decide if it should call here seems like a
|
|
||||||
* losing proposition.
|
|
||||||
|
|
||||||
]hbasl equ zptr0
|
|
||||||
]hbash equ zptr0+1
|
|
||||||
]lftbyte equ zloc0
|
|
||||||
]lftbit equ zloc1
|
|
||||||
]rgtbyte equ zloc2
|
|
||||||
]rgtbit equ zloc3
|
|
||||||
]line equ zloc4
|
|
||||||
]andmask equ zloc5
|
|
||||||
]cur_line equ zloc6
|
|
||||||
]repting equ zloc7
|
|
||||||
|
|
||||||
ldx g_color ;configure color XOR byte
|
|
||||||
lda xormask,x
|
|
||||||
do USE_FAST ;*****
|
|
||||||
cmp rast_unroll+3 ;already configured?
|
|
||||||
beq :goodmask
|
|
||||||
jsr fixrastxor
|
|
||||||
:goodmask
|
|
||||||
else
|
|
||||||
sta _xorcolor+1
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
lda #$00
|
|
||||||
sta ]repting
|
|
||||||
|
|
||||||
ldy rast_top
|
|
||||||
|
|
||||||
* Main rasterization loop. Y holds the line number.
|
|
||||||
rastloop
|
|
||||||
sty ]cur_line ;3
|
|
||||||
ldx ylooklo,y ;4
|
|
||||||
stx ]hbasl ;3
|
|
||||||
lda ylookhi,y ;4
|
|
||||||
_pg_or1 ora #$20 ;2 will be $20 or $40
|
|
||||||
sta ]hbash ;3 = 19 cycles
|
|
||||||
do USE_FAST-1 ;***** i.e. not USE_FAST
|
|
||||||
stx _wrhires+1
|
|
||||||
sta _wrhires+2
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
* divide left edge by 7
|
|
||||||
ldx rastx0l,y ;4 line num in Y
|
|
||||||
lda rastx0h,y ;4
|
|
||||||
bpl :noflag ;2
|
|
||||||
sta rastx0h+1,y ;4 propagate
|
|
||||||
lda ]repting ;3 first time through?
|
|
||||||
beq :firstre ;2 yup, finish calculations
|
|
||||||
lda ]rgtbyte ;3 need this in A
|
|
||||||
bpl :repeat ;3 always
|
|
||||||
:firstre lda rastx0h,y ;reload
|
|
||||||
sta ]repting ;any nonzero will do
|
|
||||||
and #$7f ;strip repeat flag
|
|
||||||
:noflag beq :lotabl
|
|
||||||
lda mod7hi,x
|
|
||||||
sta ]lftbit
|
|
||||||
lda div7hi,x
|
|
||||||
sta ]lftbyte
|
|
||||||
bpl :gotlft ;always
|
|
||||||
BREAK ;debug
|
|
||||||
:lotabl lda mod7lo,x
|
|
||||||
sta ]lftbit
|
|
||||||
lda div7lo,x
|
|
||||||
sta ]lftbyte
|
|
||||||
:gotlft
|
|
||||||
|
|
||||||
* divide right edge by 7
|
|
||||||
ldx rastx1l,y ;4 line num in Y
|
|
||||||
lda rastx1h,y ;4
|
|
||||||
beq :lotabr ;3
|
|
||||||
lda mod7hi,x
|
|
||||||
sta ]rgtbit
|
|
||||||
lda div7hi,x
|
|
||||||
sta ]rgtbyte
|
|
||||||
bpl :gotrgt ;always
|
|
||||||
BREAK ;debug
|
|
||||||
:lotabr lda mod7lo,x ;4
|
|
||||||
sta ]rgtbit ;3
|
|
||||||
lda div7lo,x ;4
|
|
||||||
sta ]rgtbyte ;3 = 25 for X1 < 256
|
|
||||||
:gotrgt
|
|
||||||
|
|
||||||
:repeat
|
|
||||||
cmp ]lftbyte ;3
|
|
||||||
bne :not1byte ;3
|
|
||||||
|
|
||||||
* The left and right edges are in the same byte. We
|
|
||||||
* need to set up the mask differently, so we deal with
|
|
||||||
* it as a special case.
|
|
||||||
ldy ]lftbit
|
|
||||||
lda leftmask,y ;create the AND mask
|
|
||||||
ldx ]rgtbit
|
|
||||||
and rightmask,x ;strip out bits on right
|
|
||||||
sta ]andmask
|
|
||||||
|
|
||||||
ldy ]lftbyte
|
|
||||||
lda colorline,y ;get color bits
|
|
||||||
eor (]hbasl),y ;combine w/screen
|
|
||||||
and ]andmask ;remove not-ours
|
|
||||||
eor (]hbasl),y ;combine again
|
|
||||||
sta (]hbasl),y
|
|
||||||
jmp rastlinedone
|
|
||||||
|
|
||||||
* This is the more general case. We special-case the
|
|
||||||
* left and right edges, then byte-stomp the middle.
|
|
||||||
* On entry, ]rgtbyte is in A
|
|
||||||
:not1byte
|
|
||||||
sec ;2 compute number of full
|
|
||||||
sbc ]lftbyte ;3 and partial bytes to
|
|
||||||
tax ;2 draw
|
|
||||||
inx ;2
|
|
||||||
|
|
||||||
ldy ]rgtbit ;3
|
|
||||||
cpy #6 ;2
|
|
||||||
beq :rgtnospcl ;3
|
|
||||||
lda rightmask,y ;handle partial-byte right
|
|
||||||
sta ]andmask
|
|
||||||
ldy ]rgtbyte
|
|
||||||
lda colorline,y
|
|
||||||
eor (]hbasl),y
|
|
||||||
and ]andmask
|
|
||||||
eor (]hbasl),y
|
|
||||||
sta (]hbasl),y
|
|
||||||
dex ;adjust count
|
|
||||||
:rgtnospcl
|
|
||||||
|
|
||||||
ldy ]lftbit ;3 check left for partial
|
|
||||||
beq :lftnospcl ;3
|
|
||||||
lda leftmask,y ;handle partial-byte left
|
|
||||||
sta ]andmask
|
|
||||||
ldy ]lftbyte
|
|
||||||
lda colorline,y
|
|
||||||
eor (]hbasl),y
|
|
||||||
and ]andmask
|
|
||||||
eor (]hbasl),y
|
|
||||||
sta (]hbasl),y
|
|
||||||
dex ;adjust count
|
|
||||||
beq rastlinedone ;bail if all done
|
|
||||||
iny ;advance start position
|
|
||||||
bne :liny ;always
|
|
||||||
BREAK
|
|
||||||
:lftnospcl
|
|
||||||
|
|
||||||
ldy ]lftbyte ;3
|
|
||||||
:liny
|
|
||||||
|
|
||||||
do USE_FAST ;***** "fast" loop
|
|
||||||
* Instead of looping, jump into an unrolled loop.
|
|
||||||
* Cost is 10 cycles per byte with an extra 14 cycles
|
|
||||||
* of overhead, so we start to win at 4 bytes.
|
|
||||||
lda rastunidx,x ;4
|
|
||||||
sta :_rastun+1 ;4
|
|
||||||
lda colorline,y ;4 get odd/even color val
|
|
||||||
:_rastun jmp rast_unroll ;3
|
|
||||||
|
|
||||||
else ;***** "slow" loop
|
|
||||||
* Inner loop of the renderer. This runs 0-40x.
|
|
||||||
* Cost is 14 cycles/byte.
|
|
||||||
lda colorline,y ;get appropriate odd/even val
|
|
||||||
_wrhires sta $2000,y ;5 replaced with line addr
|
|
||||||
_xorcolor eor #$00 ;2 replaced with $00/$7f
|
|
||||||
iny ;2
|
|
||||||
dex ;2
|
|
||||||
bne _wrhires ;3
|
|
||||||
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
rastlinedone
|
|
||||||
ldy ]cur_line ;3 more lines to go?
|
|
||||||
cpy rast_bottom ;4
|
|
||||||
bge :done ;2
|
|
||||||
iny ;2
|
|
||||||
jmp rastloop ;3 must have line in Y
|
|
||||||
|
|
||||||
:done rts
|
|
||||||
|
|
||||||
fixrastxor
|
|
||||||
do USE_FAST ;*****
|
|
||||||
* Update the EOR statements in the unrolled rastfill code.
|
|
||||||
* Doing this with a loop takes ~600 cycles, doing it with
|
|
||||||
* unrolled stores takes 160. We only do this when we
|
|
||||||
* need to, so changing the color from green to blue won't
|
|
||||||
* cause this to run.
|
|
||||||
*
|
|
||||||
* Call with the XOR value in A.
|
|
||||||
]offset = 0
|
|
||||||
lup BYTES_PER_ROW
|
|
||||||
sta rast_unroll+3+]offset
|
|
||||||
]offset = ]offset+5
|
|
||||||
--^
|
|
||||||
BEEP
|
|
||||||
rts
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
|
|
||||||
* include the line functions
|
|
||||||
put FDRAW.LINE
|
|
||||||
|
|
||||||
* include the circle functions
|
|
||||||
put FDRAW.CIRCLE
|
|
||||||
|
|
||||||
lst on
|
|
||||||
CODE_END equ * ;end of code section
|
|
||||||
lst off
|
|
||||||
|
|
||||||
* include the data tables
|
|
||||||
put FDRAW.TABLES
|
|
||||||
|
|
||||||
lst on
|
|
||||||
DAT_END equ * ;end of data / BSS
|
|
||||||
lst off
|
|
||||||
|
|
||||||
* Save the appropriate object file.
|
|
||||||
do USE_FAST
|
|
||||||
sav FDRAW.FAST
|
|
||||||
else
|
|
||||||
sav FDRAW.SMALL
|
|
||||||
fin
|
|
|
@ -1,339 +0,0 @@
|
||||||
********************************
|
|
||||||
* *
|
|
||||||
* Fast Apple II Graphics *
|
|
||||||
* By Andy McFadden *
|
|
||||||
* Version 0.3, Aug 2015 *
|
|
||||||
* *
|
|
||||||
* Pre-computed data and *
|
|
||||||
* large internal buffers. *
|
|
||||||
* (Included by FDRAW.S) *
|
|
||||||
* *
|
|
||||||
* Developed with Merlin-16 *
|
|
||||||
* *
|
|
||||||
********************************
|
|
||||||
|
|
||||||
* Expected layout with alignment:
|
|
||||||
*
|
|
||||||
* P1 ylooklo, misc tables
|
|
||||||
* P2 ylookhi, colorline
|
|
||||||
* P3 rastx0l
|
|
||||||
* P4 rastx0h
|
|
||||||
* P5 rastx1l
|
|
||||||
* P6 rastx1h, div7hi, mod7hi
|
|
||||||
* P7 div7lo
|
|
||||||
* P8 mod7lo
|
|
||||||
* P9 rast_unroll, rastunidx
|
|
||||||
*
|
|
||||||
* Tables should be just under $900 bytes.
|
|
||||||
|
|
||||||
PG_ALIGN
|
|
||||||
|
|
||||||
* Hi-res Y lookup, low part (192 bytes).
|
|
||||||
ylooklo HEX 0000000000000000
|
|
||||||
HEX 8080808080808080
|
|
||||||
HEX 0000000000000000
|
|
||||||
HEX 8080808080808080
|
|
||||||
HEX 0000000000000000
|
|
||||||
HEX 8080808080808080
|
|
||||||
HEX 0000000000000000
|
|
||||||
HEX 8080808080808080
|
|
||||||
HEX 2828282828282828
|
|
||||||
HEX a8a8a8a8a8a8a8a8
|
|
||||||
HEX 2828282828282828
|
|
||||||
HEX a8a8a8a8a8a8a8a8
|
|
||||||
HEX 2828282828282828
|
|
||||||
HEX a8a8a8a8a8a8a8a8
|
|
||||||
HEX 2828282828282828
|
|
||||||
HEX a8a8a8a8a8a8a8a8
|
|
||||||
HEX 5050505050505050
|
|
||||||
HEX d0d0d0d0d0d0d0d0
|
|
||||||
HEX 5050505050505050
|
|
||||||
HEX d0d0d0d0d0d0d0d0
|
|
||||||
HEX 5050505050505050
|
|
||||||
HEX d0d0d0d0d0d0d0d0
|
|
||||||
HEX 5050505050505050
|
|
||||||
HEX d0d0d0d0d0d0d0d0
|
|
||||||
|
|
||||||
* Color masks for odd/even bytes, colors 0-7.
|
|
||||||
evencolor dfb $00,$2a,$55,$7f,$80,$aa,$d5,$ff
|
|
||||||
oddcolor dfb $00,$55,$2a,$7f,$80,$d5,$aa,$ff
|
|
||||||
|
|
||||||
* XOR mask for colors 0-7 - non-BW flip on odd/even.
|
|
||||||
xormask dfb $00,$7f,$7f,$00,$00,$7f,$7f,$00
|
|
||||||
|
|
||||||
* AND mask for the 7 pixel positions, high bit set
|
|
||||||
* for the color shift.
|
|
||||||
andmask dfb $81,$82,$84,$88,$90,$a0,$c0
|
|
||||||
|
|
||||||
* These are pixel AND masks, used with the modulo 7
|
|
||||||
* result. Entry #2 in leftmask means we're touching
|
|
||||||
* the rightmost 5 pixels, and entry #2 in rightmask
|
|
||||||
* means we're touching the 3 leftmost pixels.
|
|
||||||
*
|
|
||||||
* The high bit is always set, because we want to
|
|
||||||
* keep the color's high bit.
|
|
||||||
leftmask dfb $ff,$fe,$fc,$f8,$f0,$e0,$c0
|
|
||||||
rightmask dfb $81,$83,$87,$8f,$9f,$bf,$ff
|
|
||||||
|
|
||||||
PG_ALIGN
|
|
||||||
|
|
||||||
* Hi-res Y lookup, high part (192 bytes).
|
|
||||||
* OR with $20 or $40.
|
|
||||||
ylookhi HEX 0004080c1014181c
|
|
||||||
HEX 0004080c1014181c
|
|
||||||
HEX 0105090d1115191d
|
|
||||||
HEX 0105090d1115191d
|
|
||||||
HEX 02060a0e12161a1e
|
|
||||||
HEX 02060a0e12161a1e
|
|
||||||
HEX 03070b0f13171b1f
|
|
||||||
HEX 03070b0f13171b1f
|
|
||||||
HEX 0004080c1014181c
|
|
||||||
HEX 0004080c1014181c
|
|
||||||
HEX 0105090d1115191d
|
|
||||||
HEX 0105090d1115191d
|
|
||||||
HEX 02060a0e12161a1e
|
|
||||||
HEX 02060a0e12161a1e
|
|
||||||
HEX 03070b0f13171b1f
|
|
||||||
HEX 03070b0f13171b1f
|
|
||||||
HEX 0004080c1014181c
|
|
||||||
HEX 0004080c1014181c
|
|
||||||
HEX 0105090d1115191d
|
|
||||||
HEX 0105090d1115191d
|
|
||||||
HEX 02060a0e12161a1e
|
|
||||||
HEX 02060a0e12161a1e
|
|
||||||
HEX 03070b0f13171b1f
|
|
||||||
HEX 03070b0f13171b1f
|
|
||||||
|
|
||||||
* Masks for current color (even/odd), e.g. 55 2a 55 2a ...
|
|
||||||
* Updated whenever the color changes.
|
|
||||||
colorline ds 40
|
|
||||||
|
|
||||||
PG_ALIGN
|
|
||||||
rastx0l ds NUM_ROWS
|
|
||||||
PG_ALIGN
|
|
||||||
rastx0h ds NUM_ROWS
|
|
||||||
ds 1 ;repeat mode can overstep
|
|
||||||
PG_ALIGN
|
|
||||||
rastx1l ds NUM_ROWS
|
|
||||||
PG_ALIGN
|
|
||||||
rastx1h ds NUM_ROWS
|
|
||||||
|
|
||||||
* Lookup tables for dividing 0-279 by 7. The "hi"
|
|
||||||
* parts are 24 bytes each, so they fit inside
|
|
||||||
* the previous 192-byte entry. The "lo" parts
|
|
||||||
* each fill a page.
|
|
||||||
div7hi HEX 2424242525252525
|
|
||||||
HEX 2525262626262626
|
|
||||||
HEX 2627272727272727
|
|
||||||
mod7hi HEX 0405060001020304
|
|
||||||
HEX 0506000102030405
|
|
||||||
HEX 0600010203040506
|
|
||||||
|
|
||||||
PG_ALIGN
|
|
||||||
|
|
||||||
div7lo HEX 0000000000000001
|
|
||||||
HEX 0101010101010202
|
|
||||||
HEX 0202020202030303
|
|
||||||
HEX 0303030304040404
|
|
||||||
HEX 0404040505050505
|
|
||||||
HEX 0505060606060606
|
|
||||||
HEX 0607070707070707
|
|
||||||
HEX 0808080808080809
|
|
||||||
HEX 0909090909090a0a
|
|
||||||
HEX 0a0a0a0a0a0b0b0b
|
|
||||||
HEX 0b0b0b0b0c0c0c0c
|
|
||||||
HEX 0c0c0c0d0d0d0d0d
|
|
||||||
HEX 0d0d0e0e0e0e0e0e
|
|
||||||
HEX 0e0f0f0f0f0f0f0f
|
|
||||||
HEX 1010101010101011
|
|
||||||
HEX 1111111111111212
|
|
||||||
HEX 1212121212131313
|
|
||||||
HEX 1313131314141414
|
|
||||||
HEX 1414141515151515
|
|
||||||
HEX 1515161616161616
|
|
||||||
HEX 1617171717171717
|
|
||||||
HEX 1818181818181819
|
|
||||||
HEX 1919191919191a1a
|
|
||||||
HEX 1a1a1a1a1a1b1b1b
|
|
||||||
HEX 1b1b1b1b1c1c1c1c
|
|
||||||
HEX 1c1c1c1d1d1d1d1d
|
|
||||||
HEX 1d1d1e1e1e1e1e1e
|
|
||||||
HEX 1e1f1f1f1f1f1f1f
|
|
||||||
HEX 2020202020202021
|
|
||||||
HEX 2121212121212222
|
|
||||||
HEX 2222222222232323
|
|
||||||
HEX 2323232324242424
|
|
||||||
mod7lo HEX 0001020304050600
|
|
||||||
HEX 0102030405060001
|
|
||||||
HEX 0203040506000102
|
|
||||||
HEX 0304050600010203
|
|
||||||
HEX 0405060001020304
|
|
||||||
HEX 0506000102030405
|
|
||||||
HEX 0600010203040506
|
|
||||||
HEX 0001020304050600
|
|
||||||
HEX 0102030405060001
|
|
||||||
HEX 0203040506000102
|
|
||||||
HEX 0304050600010203
|
|
||||||
HEX 0405060001020304
|
|
||||||
HEX 0506000102030405
|
|
||||||
HEX 0600010203040506
|
|
||||||
HEX 0001020304050600
|
|
||||||
HEX 0102030405060001
|
|
||||||
HEX 0203040506000102
|
|
||||||
HEX 0304050600010203
|
|
||||||
HEX 0405060001020304
|
|
||||||
HEX 0506000102030405
|
|
||||||
HEX 0600010203040506
|
|
||||||
HEX 0001020304050600
|
|
||||||
HEX 0102030405060001
|
|
||||||
HEX 0203040506000102
|
|
||||||
HEX 0304050600010203
|
|
||||||
HEX 0405060001020304
|
|
||||||
HEX 0506000102030405
|
|
||||||
HEX 0600010203040506
|
|
||||||
HEX 0001020304050600
|
|
||||||
HEX 0102030405060001
|
|
||||||
HEX 0203040506000102
|
|
||||||
HEX 0304050600010203
|
|
||||||
|
|
||||||
|
|
||||||
* RastFill unrolled loop. At each step we store the current
|
|
||||||
* color value, XOR it to flip the bits if needed, and advance.
|
|
||||||
* The caller needs to set the appropriate initial value based
|
|
||||||
* on whether the address is odd or even.
|
|
||||||
*
|
|
||||||
* We can use a 3-cycle "EOR dp" or a 2-cycle "EOR imm". The
|
|
||||||
* former is one cycle slower, the latter requires us to
|
|
||||||
* self-mod 40 instructions when the color changes.
|
|
||||||
*
|
|
||||||
* This must be page-aligned so that we can take the value
|
|
||||||
* from the rastunidx table and self-mod a JMP without having
|
|
||||||
* to do a 16-bit add. We have just enough room for the
|
|
||||||
* unrolled loop (40*5+3) and x5 table (41) = 244 bytes, fits
|
|
||||||
* on a single page.
|
|
||||||
|
|
||||||
do USE_FAST ;*****
|
|
||||||
ds \
|
|
||||||
]hbasl equ zptr0 ;must match FillRaster
|
|
||||||
rast_unroll equ *
|
|
||||||
lst off
|
|
||||||
lup BYTES_PER_ROW
|
|
||||||
sta (]hbasl),y ;6
|
|
||||||
eor #$00 ;2
|
|
||||||
iny ;2 10 cycles, 5 bytes
|
|
||||||
--^
|
|
||||||
jmp rastlinedone
|
|
||||||
|
|
||||||
* Index into rast_unroll. If we need to output N bytes,
|
|
||||||
* we want to jump to (rast_unroll + (40 - N) * 5) (where
|
|
||||||
* 5 is the number of bytes per iteration).
|
|
||||||
rastunidx
|
|
||||||
]offset = BYTES_PER_ROW*5
|
|
||||||
lup BYTES_PER_ROW+1 ;0-40
|
|
||||||
dfb ]offset
|
|
||||||
]offset = ]offset-5
|
|
||||||
--^
|
|
||||||
|
|
||||||
fin ;*****
|
|
||||||
|
|
||||||
|
|
||||||
********************************
|
|
||||||
*
|
|
||||||
* Code used to generate tables above. If you want to
|
|
||||||
* decrease load size, use these functions to generate
|
|
||||||
* the data into empty memory, then discard the code.
|
|
||||||
* (Maybe use a negative DS and overlap with rastx0l?)
|
|
||||||
*
|
|
||||||
********************************
|
|
||||||
DO 0 ;*****
|
|
||||||
|
|
||||||
init_ylook
|
|
||||||
]hbasl equ zptr1
|
|
||||||
]hbash equ zptr1+1
|
|
||||||
|
|
||||||
* Initialize Y-lookup table. We just call the bascalc
|
|
||||||
* function.
|
|
||||||
ldx #NUM_ROWS
|
|
||||||
ldy #NUM_ROWS-1
|
|
||||||
]loop tya
|
|
||||||
jsr bascalc
|
|
||||||
lda hbasl
|
|
||||||
sta ylooklo,y
|
|
||||||
lda hbash
|
|
||||||
ora #$20 ;remove for $0000 base
|
|
||||||
sta ylookhi,y
|
|
||||||
dey
|
|
||||||
dex
|
|
||||||
bne ]loop
|
|
||||||
rts
|
|
||||||
|
|
||||||
* Hi-res base address calculation. This is based on the
|
|
||||||
* HPOSN routine at $F411.
|
|
||||||
*
|
|
||||||
* Call with the line in A. The results are placed into
|
|
||||||
* zptr1. X and Y are not disturbed.
|
|
||||||
*
|
|
||||||
* The value is in the $0000-1fff range, so you must OR
|
|
||||||
* the desired hi-res page in.
|
|
||||||
*
|
|
||||||
bascalc
|
|
||||||
pha
|
|
||||||
and #$c0
|
|
||||||
sta ]hbasl
|
|
||||||
lsr
|
|
||||||
lsr
|
|
||||||
ora ]hbasl
|
|
||||||
sta ]hbasl
|
|
||||||
pla
|
|
||||||
sta ]hbash
|
|
||||||
asl
|
|
||||||
asl
|
|
||||||
asl
|
|
||||||
rol ]hbash
|
|
||||||
asl
|
|
||||||
rol ]hbash
|
|
||||||
asl
|
|
||||||
ror ]hbasl
|
|
||||||
lda ]hbash
|
|
||||||
and #$1f
|
|
||||||
sta ]hbash
|
|
||||||
rts
|
|
||||||
|
|
||||||
*
|
|
||||||
* Create divide-by-7 tables.
|
|
||||||
*
|
|
||||||
mkdivtab
|
|
||||||
]val equ zloc0
|
|
||||||
|
|
||||||
ldy #0
|
|
||||||
sty ]val
|
|
||||||
ldx #0
|
|
||||||
]loop lda ]val
|
|
||||||
sta div7lo,y
|
|
||||||
txa
|
|
||||||
sta mod7lo,y
|
|
||||||
inx
|
|
||||||
iny
|
|
||||||
beq :lodone
|
|
||||||
cpx #7
|
|
||||||
bne ]loop
|
|
||||||
inc ]val
|
|
||||||
ldx #0
|
|
||||||
beq ]loop ;always
|
|
||||||
:lodone ;safe to ignore ]va update
|
|
||||||
]loop lda ]val
|
|
||||||
sta div7hi,y
|
|
||||||
txa
|
|
||||||
sta mod7hi,y
|
|
||||||
iny
|
|
||||||
cpy #280-256
|
|
||||||
beq :hidone
|
|
||||||
inx
|
|
||||||
cpx #7
|
|
||||||
bne ]loop
|
|
||||||
inc ]val
|
|
||||||
ldx #0
|
|
||||||
beq ]loop ;always
|
|
||||||
:hidone rts
|
|
||||||
|
|
||||||
FIN ;*****
|
|
|
@ -0,0 +1,754 @@
|
||||||
|
********************************
|
||||||
|
* *
|
||||||
|
* Fast Apple II Graphics *
|
||||||
|
* By Andy McFadden *
|
||||||
|
* Version 0.3, Aug 2015 *
|
||||||
|
* *
|
||||||
|
* Circle rendering *
|
||||||
|
* (Included by FDRAW.S) *
|
||||||
|
* *
|
||||||
|
* Developed with Merlin-16 *
|
||||||
|
* *
|
||||||
|
********************************
|
||||||
|
|
||||||
|
* TODO: if USE_FAST is 0, replace the outline circle
|
||||||
|
* plot code with calls to DrawPoint (or maybe a
|
||||||
|
* common sub-function so we don't trash the input
|
||||||
|
* parameters). Saves a little space.
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Draw a circle. The radius is in in_rad, and
|
||||||
|
* the center is at in_x0l+in_x0h,in_y0.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
DrawCircle
|
||||||
|
lda #$20 ;JSR
|
||||||
|
cmp _cp08 ;configured for outline?
|
||||||
|
beq :okay
|
||||||
|
jsr fixcplot
|
||||||
|
:okay
|
||||||
|
jmp calc_circle
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Draw filled circle.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
FillCircle
|
||||||
|
lda #$2c ;BIT
|
||||||
|
cmp _cp08 ;configured for fill?
|
||||||
|
beq :okay
|
||||||
|
jsr fixcplot
|
||||||
|
:okay
|
||||||
|
jsr calc_circle
|
||||||
|
jmp FillRaster
|
||||||
|
|
||||||
|
|
||||||
|
* Calculate a circle, using Bresenham's algorithm. The
|
||||||
|
* results are placed into the rasterization buffers.
|
||||||
|
*
|
||||||
|
* in_rad must be from 0 to 255. The x/y center
|
||||||
|
* coordinates must be on the screen, but the circle
|
||||||
|
* can extend off the edge.
|
||||||
|
*
|
||||||
|
* The computed values are stored in the rasterization
|
||||||
|
* tables. For an outline circle, we also plot the
|
||||||
|
* points immediately.
|
||||||
|
|
||||||
|
do USE_FAST ;*****
|
||||||
|
* local storage -- not used often enough to merit DP
|
||||||
|
circ_8bit ds 1
|
||||||
|
circ_clip ds 1
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
calc_circle
|
||||||
|
max_fast_rad equ 41
|
||||||
|
]cxl equ zloc0
|
||||||
|
]cxh equ zloc1
|
||||||
|
]cy equ zloc2
|
||||||
|
]dlo equ zloc3
|
||||||
|
]dhi equ zloc4
|
||||||
|
]xsav equ zloc5
|
||||||
|
]ysav equ zloc6
|
||||||
|
]min_x equ zloc7 ;min/max offsets from center
|
||||||
|
]max_x equ zloc8 ;(min is above center, max
|
||||||
|
]min_y equ zloc9 ; is below)
|
||||||
|
]max_y equ zloc10
|
||||||
|
]hitmp equ zloc11
|
||||||
|
* only used by hplot for outline circles
|
||||||
|
]hbasl equ zptr0
|
||||||
|
]andmask equ zloc11 ;overlaps with ]hitmp
|
||||||
|
]savxreg equ zloc12
|
||||||
|
]savyreg equ zloc13
|
||||||
|
|
||||||
|
* Special-case radius=0. It removes an annoying
|
||||||
|
* edge case (first y-- becomes 0xff, but 6502 cmp
|
||||||
|
* is unsigned).
|
||||||
|
lda in_rad
|
||||||
|
bne :notzero
|
||||||
|
ldy in_y0
|
||||||
|
sty rast_top
|
||||||
|
sty rast_bottom
|
||||||
|
lda in_x0l
|
||||||
|
sta rastx0l,y
|
||||||
|
sta rastx1l,y
|
||||||
|
lda in_x0h
|
||||||
|
sta rastx0h,y
|
||||||
|
sta rastx1h,y
|
||||||
|
rts
|
||||||
|
|
||||||
|
* Use different version of function for small
|
||||||
|
* circles, because we can do it all in 8 bits.
|
||||||
|
:notzero
|
||||||
|
do USE_FAST ;*****
|
||||||
|
ldy #$01
|
||||||
|
cmp #max_fast_rad ;in_rad in Acc
|
||||||
|
blt :use_fast
|
||||||
|
dey
|
||||||
|
:use_fast sty circ_8bit
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
lda in_x0l ;copy center to DP for speed
|
||||||
|
sta ]cxl
|
||||||
|
lda in_x0h
|
||||||
|
sta ]cxh
|
||||||
|
lda in_y0
|
||||||
|
sta ]cy
|
||||||
|
|
||||||
|
* Compute min/max values, based on offset from center.
|
||||||
|
* These are compared against offset-from-center x/y.
|
||||||
|
* We need tight bounds on Y because we use it to
|
||||||
|
* compute the rast_render top/bottom. Getting tight
|
||||||
|
* bounds on X is not so important, but we still need
|
||||||
|
* it for the no-clip optimization.
|
||||||
|
ldx #$04 ;count edges needing clip
|
||||||
|
|
||||||
|
lda #NUM_ROWS-1 ;191
|
||||||
|
sec
|
||||||
|
sbc ]cy ;maxY = 191-cy
|
||||||
|
cmp in_rad
|
||||||
|
blt :ylimok
|
||||||
|
lda in_rad ;clamp to radius
|
||||||
|
dex
|
||||||
|
:ylimok sta ]max_y ;maxY = 191-cy
|
||||||
|
|
||||||
|
lda ]cy ;minY = cy
|
||||||
|
cmp in_rad
|
||||||
|
blt :ylimok2
|
||||||
|
lda in_rad ;clamp to radius
|
||||||
|
dex
|
||||||
|
:ylimok2 sta ]min_y
|
||||||
|
|
||||||
|
lda ]cxh
|
||||||
|
beq :xlimlo
|
||||||
|
* Examples (note #<NUM_COLS-1 is 279-256 = 23):
|
||||||
|
* cx=265 (cxh=1 cxl=11), 23-11=14, chk rad
|
||||||
|
lda #<NUM_COLS-1 ;maxX = 279-cx
|
||||||
|
sec
|
||||||
|
sbc ]cxl
|
||||||
|
cmp in_rad
|
||||||
|
blt :xlimhok
|
||||||
|
lda in_rad ;clamp to radius
|
||||||
|
dex
|
||||||
|
:xlimhok sta ]max_x
|
||||||
|
|
||||||
|
lda in_rad ;min X always out of range
|
||||||
|
dex ; so just clamp to radius
|
||||||
|
sta ]min_x
|
||||||
|
jmp :xlimdone
|
||||||
|
|
||||||
|
* Examples:
|
||||||
|
* For cx=0 to 24, we can never pass right edge (our
|
||||||
|
* maximum radius is 255).
|
||||||
|
* cx=3, 23-3=20 + carry set --> bad, must use rad
|
||||||
|
* cx=24, 23-24=255 + carry clear --> ok, chk rad
|
||||||
|
* cx=255, 23-255=24 + carry clear --> ok, chk rad
|
||||||
|
:xlimlo
|
||||||
|
lda #<NUM_COLS-1 ;maxX = 279-cx
|
||||||
|
sec
|
||||||
|
sbc ]cxl
|
||||||
|
bcs :xuserad
|
||||||
|
cmp in_rad
|
||||||
|
blt :xlimok
|
||||||
|
:xuserad lda in_rad ;clamp to radius
|
||||||
|
dex
|
||||||
|
:xlimok sta ]max_x
|
||||||
|
|
||||||
|
lda ]cxl ;minX = (cx > 255) ?
|
||||||
|
cmp in_rad
|
||||||
|
blt :xlimok2
|
||||||
|
lda in_rad ;clamp to radius
|
||||||
|
dex
|
||||||
|
:xlimok2 sta ]min_x
|
||||||
|
|
||||||
|
:xlimdone
|
||||||
|
|
||||||
|
do USE_FAST ;*****
|
||||||
|
stx circ_clip
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
* set top/bottom rows for rasterizer
|
||||||
|
lda ]cy
|
||||||
|
clc
|
||||||
|
adc ]max_y
|
||||||
|
sta rast_bottom
|
||||||
|
lda ]cy
|
||||||
|
sec
|
||||||
|
sbc ]min_y
|
||||||
|
sta rast_top
|
||||||
|
|
||||||
|
DO 0 ;debug debug debug
|
||||||
|
LDA ]min_x ;save a copy where the
|
||||||
|
STA $0380 ; monitor won't trash it
|
||||||
|
LDA ]max_x
|
||||||
|
STA $0381
|
||||||
|
LDA ]min_y
|
||||||
|
STA $0382
|
||||||
|
LDA ]max_y
|
||||||
|
STA $0383
|
||||||
|
FIN
|
||||||
|
|
||||||
|
* Set initial conditions for Bresenham.
|
||||||
|
ldx #0 ;:x = 0
|
||||||
|
stx ]xsav
|
||||||
|
ldy in_rad ;:y = rad
|
||||||
|
sty ]ysav
|
||||||
|
lda #1 ;:d = 1 - rad
|
||||||
|
sec
|
||||||
|
sbc ]ysav ;in_rad
|
||||||
|
sta ]dlo
|
||||||
|
bcs :hizero ;C==1 if in_rad<=1
|
||||||
|
ldx #$ff ;C was 0, make neg
|
||||||
|
:hizero stx ]dhi
|
||||||
|
|
||||||
|
*
|
||||||
|
* Outer loop -- plot 8 points, then update values.
|
||||||
|
*
|
||||||
|
circ_loop
|
||||||
|
|
||||||
|
do USE_FAST ;*****
|
||||||
|
lda circ_clip
|
||||||
|
beq ncypy
|
||||||
|
jmp with_clip
|
||||||
|
|
||||||
|
* Quick version, no clipping required
|
||||||
|
* row cy+y: cx-x and cx+x
|
||||||
|
ncypy
|
||||||
|
lda ]ysav
|
||||||
|
clc
|
||||||
|
adc ]cy
|
||||||
|
tay ;y-coord in Y-reg
|
||||||
|
|
||||||
|
lda ]cxl
|
||||||
|
sec
|
||||||
|
sbc ]xsav
|
||||||
|
sta rastx0l,y
|
||||||
|
lda ]cxh
|
||||||
|
sbc #$00
|
||||||
|
sta rastx0h,y
|
||||||
|
_cp00 jsr cplotl
|
||||||
|
|
||||||
|
lda ]cxl
|
||||||
|
clc
|
||||||
|
adc ]xsav
|
||||||
|
sta rastx1l,y
|
||||||
|
lda ]cxh
|
||||||
|
adc #$00
|
||||||
|
sta rastx1h,y
|
||||||
|
_cp01 jsr cplotrn
|
||||||
|
|
||||||
|
* row cy-y: cx-x and cx+x
|
||||||
|
ncymy
|
||||||
|
lda ]cy
|
||||||
|
sec
|
||||||
|
sbc ]ysav
|
||||||
|
tay ;y-coord in Y-reg
|
||||||
|
|
||||||
|
lda ]cxl
|
||||||
|
sec
|
||||||
|
sbc ]xsav
|
||||||
|
sta rastx0l,y
|
||||||
|
lda ]cxh
|
||||||
|
sbc #$00
|
||||||
|
sta rastx0h,y
|
||||||
|
_cp02 jsr cplotl
|
||||||
|
|
||||||
|
lda ]cxl
|
||||||
|
clc
|
||||||
|
adc ]xsav
|
||||||
|
sta rastx1l,y
|
||||||
|
lda ]cxh
|
||||||
|
adc #$00
|
||||||
|
sta rastx1h,y
|
||||||
|
_cp03 jsr cplotrn
|
||||||
|
|
||||||
|
* row cy+x: cx-y and cx+y
|
||||||
|
ncypx
|
||||||
|
lda ]xsav ;off bottom?
|
||||||
|
clc
|
||||||
|
adc ]cy
|
||||||
|
tay ;y-coord in Y-reg
|
||||||
|
|
||||||
|
lda ]cxl
|
||||||
|
sec
|
||||||
|
sbc ]ysav
|
||||||
|
sta rastx0l,y
|
||||||
|
lda ]cxh
|
||||||
|
sbc #$00
|
||||||
|
sta rastx0h,y
|
||||||
|
_cp04 jsr cplotl
|
||||||
|
|
||||||
|
lda ]cxl
|
||||||
|
clc
|
||||||
|
adc ]ysav
|
||||||
|
sta rastx1l,y
|
||||||
|
lda ]cxh
|
||||||
|
adc #$00
|
||||||
|
sta rastx1h,y
|
||||||
|
_cp05 jsr cplotrn
|
||||||
|
|
||||||
|
* row cy-x: cx-y and cx+y
|
||||||
|
ncymx
|
||||||
|
lda ]cy
|
||||||
|
sec
|
||||||
|
sbc ]xsav
|
||||||
|
tay ;y-coord in Y-reg
|
||||||
|
|
||||||
|
lda ]cxl
|
||||||
|
sec
|
||||||
|
sbc ]ysav
|
||||||
|
sta rastx0l,y
|
||||||
|
lda ]cxh
|
||||||
|
sbc #$00
|
||||||
|
sta rastx0h,y
|
||||||
|
_cp06 jsr cplotl
|
||||||
|
|
||||||
|
lda ]cxl
|
||||||
|
clc
|
||||||
|
adc ]ysav
|
||||||
|
sta rastx1l,y
|
||||||
|
lda ]cxh
|
||||||
|
adc #$00
|
||||||
|
sta rastx1h,y
|
||||||
|
_cp07 jsr cplotrn
|
||||||
|
|
||||||
|
* CLICK
|
||||||
|
jmp circ_plot_done
|
||||||
|
|
||||||
|
fin ;***** (USE_FAST)
|
||||||
|
|
||||||
|
*
|
||||||
|
* Same thing, but this time clipping edges.
|
||||||
|
*
|
||||||
|
with_clip
|
||||||
|
|
||||||
|
* row cy+y: cx-x and cx+x
|
||||||
|
ccypy
|
||||||
|
lda ]ysav ;off bottom?
|
||||||
|
cmp ]max_y
|
||||||
|
beq :cypy_ok
|
||||||
|
bge cypy_skip ;completely off screen
|
||||||
|
:cypy_ok clc
|
||||||
|
adc ]cy
|
||||||
|
tay ;y-coord in Y-reg
|
||||||
|
|
||||||
|
ldx ]xsav ;handle cx-x
|
||||||
|
cpx ]min_x
|
||||||
|
blt :cxmx_ok
|
||||||
|
beq :cxmx_ok
|
||||||
|
lda #0 ;clip at 0
|
||||||
|
sta rastx0l,y
|
||||||
|
sta rastx0h,y
|
||||||
|
beq cxmx_done0 ;always
|
||||||
|
BREAK
|
||||||
|
:cxmx_ok lda ]cxl
|
||||||
|
sec
|
||||||
|
sbc ]xsav
|
||||||
|
sta rastx0l,y
|
||||||
|
lda ]cxh
|
||||||
|
sbc #$00
|
||||||
|
sta rastx0h,y
|
||||||
|
_cp08 jsr cplotl
|
||||||
|
cxmx_done0
|
||||||
|
|
||||||
|
cpx ]max_x ;handle cx+x
|
||||||
|
blt :cxpx_ok
|
||||||
|
beq :cxpx_ok
|
||||||
|
lda #<NUM_COLS-1
|
||||||
|
sta rastx1l,y
|
||||||
|
lda #>NUM_COLS-1
|
||||||
|
sta rastx1h,y
|
||||||
|
bne cxpx_done0 ;always
|
||||||
|
BREAK
|
||||||
|
:cxpx_ok lda ]cxl
|
||||||
|
clc
|
||||||
|
adc ]xsav
|
||||||
|
sta rastx1l,y
|
||||||
|
lda ]cxh
|
||||||
|
adc #$00
|
||||||
|
sta rastx1h,y
|
||||||
|
_cp09 jsr cplotr
|
||||||
|
cxpx_done0
|
||||||
|
cypy_skip
|
||||||
|
|
||||||
|
* row cy-y: cx-x and cx+x
|
||||||
|
ccymy
|
||||||
|
lda ]ysav ;off top?
|
||||||
|
cmp ]min_y
|
||||||
|
beq :cymy_ok
|
||||||
|
bge cymy_skip
|
||||||
|
:cymy_ok lda ]cy
|
||||||
|
sec
|
||||||
|
sbc ]ysav
|
||||||
|
tay ;y-coord in Y-reg
|
||||||
|
|
||||||
|
ldx ]xsav ;handle cx-x
|
||||||
|
cpx ]min_x
|
||||||
|
blt :cxmx_ok
|
||||||
|
beq :cxmx_ok
|
||||||
|
lda #0 ;clip at 0
|
||||||
|
sta rastx0l,y
|
||||||
|
sta rastx0h,y
|
||||||
|
beq cxmx_done1 ;always
|
||||||
|
BREAK
|
||||||
|
:cxmx_ok lda ]cxl
|
||||||
|
sec
|
||||||
|
sbc ]xsav
|
||||||
|
sta rastx0l,y
|
||||||
|
lda ]cxh
|
||||||
|
sbc #$00
|
||||||
|
sta rastx0h,y
|
||||||
|
_cp10 jsr cplotl
|
||||||
|
cxmx_done1
|
||||||
|
|
||||||
|
cpx ]max_x ;handle cx+x
|
||||||
|
blt :cxpx_ok
|
||||||
|
beq :cxpx_ok
|
||||||
|
lda #<NUM_COLS-1
|
||||||
|
sta rastx1l,y
|
||||||
|
lda #>NUM_COLS-1
|
||||||
|
sta rastx1h,y
|
||||||
|
bne cxpx_done1 ;always
|
||||||
|
BREAK
|
||||||
|
:cxpx_ok lda ]cxl
|
||||||
|
clc
|
||||||
|
adc ]xsav
|
||||||
|
sta rastx1l,y
|
||||||
|
lda ]cxh
|
||||||
|
adc #$00
|
||||||
|
sta rastx1h,y
|
||||||
|
_cp11 jsr cplotr
|
||||||
|
cxpx_done1
|
||||||
|
cymy_skip
|
||||||
|
|
||||||
|
* row cy+x: cx-y and cx+y
|
||||||
|
ccypx
|
||||||
|
lda ]xsav ;off bottom?
|
||||||
|
cmp ]max_y
|
||||||
|
beq :cypx_ok
|
||||||
|
bge cypx_skip
|
||||||
|
:cypx_ok clc
|
||||||
|
adc ]cy
|
||||||
|
tay ;y-coord in Y-reg
|
||||||
|
|
||||||
|
ldx ]ysav ;handle cx-y
|
||||||
|
cpx ]min_x
|
||||||
|
blt :cxmy_ok
|
||||||
|
beq :cxmy_ok
|
||||||
|
lda #0 ;clip at 0
|
||||||
|
sta rastx0l,y
|
||||||
|
sta rastx0h,y
|
||||||
|
beq cxmy_done2 ;always
|
||||||
|
BREAK
|
||||||
|
:cxmy_ok lda ]cxl
|
||||||
|
sec
|
||||||
|
sbc ]ysav
|
||||||
|
sta rastx0l,y
|
||||||
|
lda ]cxh
|
||||||
|
sbc #$00
|
||||||
|
sta rastx0h,y
|
||||||
|
_cp12 jsr cplotl
|
||||||
|
cxmy_done2
|
||||||
|
|
||||||
|
cpx ]max_x ;handle cx+y
|
||||||
|
blt :cxpy_ok
|
||||||
|
beq :cxpy_ok
|
||||||
|
lda #<NUM_COLS-1
|
||||||
|
sta rastx1l,y
|
||||||
|
lda #>NUM_COLS-1
|
||||||
|
sta rastx1h,y
|
||||||
|
bne cxpy_done2 ;always
|
||||||
|
BREAK
|
||||||
|
:cxpy_ok lda ]cxl
|
||||||
|
clc
|
||||||
|
adc ]ysav
|
||||||
|
sta rastx1l,y
|
||||||
|
lda ]cxh
|
||||||
|
adc #$00
|
||||||
|
sta rastx1h,y
|
||||||
|
_cp13 jsr cplotr
|
||||||
|
cxpy_done2
|
||||||
|
cypx_skip
|
||||||
|
|
||||||
|
* row cy-x: cx-y and cx+y
|
||||||
|
ccymx
|
||||||
|
lda ]xsav ;off top?
|
||||||
|
cmp ]min_y
|
||||||
|
beq :cymx_ok
|
||||||
|
bge cymx_skip
|
||||||
|
:cymx_ok lda ]cy
|
||||||
|
sec
|
||||||
|
sbc ]xsav
|
||||||
|
tay ;y-coord in Y-reg
|
||||||
|
|
||||||
|
ldx ]ysav ;handle cx-y
|
||||||
|
cpx ]min_x
|
||||||
|
blt :cxmy_ok
|
||||||
|
beq :cxmy_ok
|
||||||
|
lda #0 ;clip at 0
|
||||||
|
sta rastx0l,y
|
||||||
|
sta rastx0h,y
|
||||||
|
beq cxmy_done3 ;always
|
||||||
|
BREAK
|
||||||
|
:cxmy_ok lda ]cxl
|
||||||
|
sec
|
||||||
|
sbc ]ysav
|
||||||
|
sta rastx0l,y
|
||||||
|
lda ]cxh
|
||||||
|
sbc #$00
|
||||||
|
sta rastx0h,y
|
||||||
|
_cp14 jsr cplotl
|
||||||
|
cxmy_done3
|
||||||
|
|
||||||
|
cpx ]max_x ;handle cx+y
|
||||||
|
blt :cxpy_ok
|
||||||
|
beq :cxpy_ok
|
||||||
|
lda #<NUM_COLS-1
|
||||||
|
sta rastx1l,y
|
||||||
|
lda #>NUM_COLS-1
|
||||||
|
sta rastx1h,y
|
||||||
|
bne cxpy_done3 ;always
|
||||||
|
BREAK
|
||||||
|
:cxpy_ok lda ]cxl
|
||||||
|
clc
|
||||||
|
adc ]ysav
|
||||||
|
sta rastx1l,y
|
||||||
|
lda ]cxh
|
||||||
|
adc #$00
|
||||||
|
sta rastx1h,y
|
||||||
|
_cp15 jsr cplotr
|
||||||
|
cxpy_done3
|
||||||
|
cymx_skip
|
||||||
|
|
||||||
|
circ_plot_done
|
||||||
|
* Update X/Y/D. Up to about radius=41 we can maintain
|
||||||
|
* 'd' in an 8-bit register.
|
||||||
|
do USE_FAST ;*****
|
||||||
|
lda circ_8bit
|
||||||
|
beq circ_slow
|
||||||
|
|
||||||
|
*
|
||||||
|
* Bresenham update, with 8-bit 'd'.
|
||||||
|
*
|
||||||
|
ldx ]xsav
|
||||||
|
lda ]dlo
|
||||||
|
bmi :dneg
|
||||||
|
txa ;:d = d + ((x-y)*4) +5
|
||||||
|
sec
|
||||||
|
sbc ]ysav ;x <= y, may be neg or 0
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
clc ;can't know carry
|
||||||
|
adc #5
|
||||||
|
clc ;still don't want carry
|
||||||
|
adc ]dlo
|
||||||
|
sta ]dlo
|
||||||
|
dec ]ysav ;:y--
|
||||||
|
jmp :loopbot
|
||||||
|
:dneg txa ;:d = d + (x*4) +3
|
||||||
|
asl
|
||||||
|
asl ;x always pos, C=0
|
||||||
|
DO 0
|
||||||
|
BCC :TEST ;debug
|
||||||
|
BREAK ;debug
|
||||||
|
:TEST ;debug
|
||||||
|
FIN
|
||||||
|
adc #3
|
||||||
|
adc ]dlo
|
||||||
|
sta ]dlo
|
||||||
|
:loopbot
|
||||||
|
inx ;:x++
|
||||||
|
stx ]xsav
|
||||||
|
cpx ]ysav
|
||||||
|
beq :again
|
||||||
|
bge circ_done
|
||||||
|
:again jmp circ_loop
|
||||||
|
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
*
|
||||||
|
* Bresenham update, with 16-bit 'd'
|
||||||
|
*
|
||||||
|
circ_slow
|
||||||
|
CLICK
|
||||||
|
ldx ]xsav
|
||||||
|
lda ]dhi
|
||||||
|
bmi :dneg
|
||||||
|
lda ]dlo
|
||||||
|
clc
|
||||||
|
adc #5
|
||||||
|
sta ]dlo
|
||||||
|
bcc :noinc
|
||||||
|
inc ]dhi
|
||||||
|
:noinc
|
||||||
|
txa ;:d = d + ((x-y)*4) +5
|
||||||
|
ldy #$00
|
||||||
|
sty ]hitmp
|
||||||
|
sec
|
||||||
|
sbc ]ysav ;x <= y, may be neg or 0
|
||||||
|
beq :xeqy ;if x==y, nothing to add
|
||||||
|
ldy #$ff
|
||||||
|
sty ]hitmp
|
||||||
|
asl
|
||||||
|
rol ]hitmp
|
||||||
|
asl
|
||||||
|
rol ]hitmp
|
||||||
|
clc
|
||||||
|
adc ]dlo
|
||||||
|
sta ]dlo
|
||||||
|
lda ]dhi
|
||||||
|
adc ]hitmp
|
||||||
|
sta ]dhi
|
||||||
|
:xeqy
|
||||||
|
dec ]ysav ;:y--
|
||||||
|
jmp :loopbot
|
||||||
|
|
||||||
|
:dneg lda ]dlo ;:d = d + (x*4) + 3
|
||||||
|
clc
|
||||||
|
adc #3
|
||||||
|
sta ]dlo
|
||||||
|
bcc :noinc2
|
||||||
|
inc ]dhi
|
||||||
|
:noinc2 txa
|
||||||
|
ldy #0 ;x always positive
|
||||||
|
sty ]hitmp
|
||||||
|
asl
|
||||||
|
rol ]hitmp
|
||||||
|
asl
|
||||||
|
rol ]hitmp
|
||||||
|
clc ;not needed?
|
||||||
|
adc ]dlo
|
||||||
|
sta ]dlo
|
||||||
|
lda ]dhi
|
||||||
|
adc ]hitmp
|
||||||
|
sta ]dhi
|
||||||
|
:loopbot
|
||||||
|
inx ;:x++
|
||||||
|
stx ]xsav
|
||||||
|
cpx ]ysav
|
||||||
|
beq :again
|
||||||
|
bge circ_done
|
||||||
|
:again jmp circ_loop
|
||||||
|
|
||||||
|
|
||||||
|
circ_done rts
|
||||||
|
|
||||||
|
|
||||||
|
* Plot a point for outline circle rendering.
|
||||||
|
*
|
||||||
|
* X and Y must be preserved. Y holds the current line
|
||||||
|
* number.
|
||||||
|
*
|
||||||
|
* Most DP locations are in use -- see the variable
|
||||||
|
* declarations at the start of the circle function.
|
||||||
|
|
||||||
|
* cplotl is the entry point for the leftmost point.
|
||||||
|
cplotl
|
||||||
|
stx ]savxreg
|
||||||
|
sty ]savyreg
|
||||||
|
|
||||||
|
lda ylooklo,y
|
||||||
|
sta ]hbasl
|
||||||
|
lda ylookhi,y
|
||||||
|
_pg_or2 ora #$20
|
||||||
|
sta ]hbasl+1
|
||||||
|
|
||||||
|
* Convert the X coordinate into byte/bit.
|
||||||
|
ldx rastx0l,y ;x coord, lo
|
||||||
|
lda rastx0h,y ;>= 256?
|
||||||
|
beq :lotabl ;no, use the low table
|
||||||
|
ldy div7hi,x
|
||||||
|
lda mod7hi,x
|
||||||
|
bpl cplotcom ;always
|
||||||
|
BREAK ;debug
|
||||||
|
:lotabl ldy div7lo,x
|
||||||
|
lda mod7lo,x
|
||||||
|
jmp cplotcom
|
||||||
|
|
||||||
|
* cplotr is the entry point for the rightmost point.
|
||||||
|
* We use rastx1 instead of rastx0.
|
||||||
|
cplotr
|
||||||
|
lda ylooklo,y
|
||||||
|
sta ]hbasl
|
||||||
|
lda ylookhi,y
|
||||||
|
_pg_or3 ora #$20
|
||||||
|
sta ]hbasl+1
|
||||||
|
|
||||||
|
* If we just plotted the left point on the same line,
|
||||||
|
* we can skip the Y-lookup by jumping here.
|
||||||
|
cplotrn
|
||||||
|
stx ]savxreg
|
||||||
|
sty ]savyreg
|
||||||
|
|
||||||
|
ldx rastx1l,y ;x coord, lo
|
||||||
|
lda rastx1h,y ;>= 256?
|
||||||
|
beq :lotabl ;no, use the low table
|
||||||
|
ldy div7hi,x
|
||||||
|
lda mod7hi,x
|
||||||
|
bpl cplotcom ;always
|
||||||
|
BREAK ;debug
|
||||||
|
:lotabl ldy div7lo,x
|
||||||
|
lda mod7lo,x
|
||||||
|
|
||||||
|
* Plot the point. The byte offset (0-39) is in Y,
|
||||||
|
* the bit offset (0-6) is in A.
|
||||||
|
cplotcom
|
||||||
|
tax
|
||||||
|
lda colorline,y ;start with color pattern
|
||||||
|
eor (]hbasl),y ;flip all bits
|
||||||
|
and andmask,x ;clear other bits
|
||||||
|
eor (]hbasl),y ;restore ours, set theirs
|
||||||
|
sta (]hbasl),y
|
||||||
|
|
||||||
|
ldx ]savxreg
|
||||||
|
ldy ]savyreg
|
||||||
|
rts
|
||||||
|
|
||||||
|
* Reconfigure calc_circle to either JSR to cplotl/r,
|
||||||
|
* or just BIT the address (a 4-cycle no-op). The
|
||||||
|
* desired instruction is in A.
|
||||||
|
fixcplot
|
||||||
|
do USE_FAST ;*****
|
||||||
|
sta _cp00
|
||||||
|
sta _cp01
|
||||||
|
sta _cp02
|
||||||
|
sta _cp03
|
||||||
|
sta _cp04
|
||||||
|
sta _cp05
|
||||||
|
sta _cp06
|
||||||
|
sta _cp07
|
||||||
|
fin ;*****
|
||||||
|
sta _cp08
|
||||||
|
sta _cp09
|
||||||
|
sta _cp10
|
||||||
|
sta _cp11
|
||||||
|
sta _cp12
|
||||||
|
sta _cp13
|
||||||
|
sta _cp14
|
||||||
|
sta _cp15
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,590 @@
|
||||||
|
********************************
|
||||||
|
* *
|
||||||
|
* Fast Apple II Graphics *
|
||||||
|
* By Andy McFadden *
|
||||||
|
* Version 0.3, Aug 2015 *
|
||||||
|
* *
|
||||||
|
* Point and line functions *
|
||||||
|
* (Included by FDRAW.S) *
|
||||||
|
* *
|
||||||
|
* Developed with Merlin-16 *
|
||||||
|
* *
|
||||||
|
********************************
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Draw a single point in the current color.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
DrawPoint
|
||||||
|
]hbasl equ zptr0
|
||||||
|
|
||||||
|
ldy in_y0
|
||||||
|
lda ylooklo,y
|
||||||
|
sta ]hbasl
|
||||||
|
lda ylookhi,y
|
||||||
|
ora g_page
|
||||||
|
sta ]hbasl+1
|
||||||
|
|
||||||
|
ldx in_x0l ;x coord, lo
|
||||||
|
lda in_x0h ;>= 256?
|
||||||
|
beq :lotabl ;no, use the low table
|
||||||
|
ldy div7hi,x
|
||||||
|
lda mod7hi,x
|
||||||
|
bpl :plotit ;always
|
||||||
|
BREAK ;debug
|
||||||
|
:lotabl ldy div7lo,x
|
||||||
|
lda mod7lo,x
|
||||||
|
|
||||||
|
* Plot the point. The byte offset (0-39) is in Y,
|
||||||
|
* the bit offset (0-6) is in A.
|
||||||
|
:plotit
|
||||||
|
tax
|
||||||
|
lda colorline,y ;start with color pattern
|
||||||
|
eor (]hbasl),y ;flip all bits
|
||||||
|
and andmask,x ;clear other bits
|
||||||
|
eor (]hbasl),y ;restore ours, set theirs
|
||||||
|
sta (]hbasl),y
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Draw a line between two points.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
DrawLine
|
||||||
|
|
||||||
|
]hbasl equ zptr0
|
||||||
|
]xposl equ zloc0 ;always left edge
|
||||||
|
]xposh equ zloc1
|
||||||
|
]ypos equ zloc2 ;top or bottom
|
||||||
|
]deltaxl equ zloc3
|
||||||
|
]deltaxh equ zloc4
|
||||||
|
]deltay equ zloc5
|
||||||
|
]count equ zloc6
|
||||||
|
]counth equ zloc7
|
||||||
|
]diff equ zloc8
|
||||||
|
]diffh equ zloc9
|
||||||
|
]andmask equ zloc10
|
||||||
|
]wideflag equ zloc11 ;doesn't really need DP
|
||||||
|
|
||||||
|
* We use a traditional Bresenham run-length approach.
|
||||||
|
* Run-slicing is possible, but the code is larger
|
||||||
|
* and the increased cost means it's only valuable
|
||||||
|
* for longer lines. An optimal solution would switch
|
||||||
|
* approaches based on line length.
|
||||||
|
*
|
||||||
|
* Start by identifying where x0 or x1 is on the
|
||||||
|
* left. To make life simpler we always work from
|
||||||
|
* left to right, flipping the coordinates if
|
||||||
|
* needed.
|
||||||
|
*
|
||||||
|
* We also need to figure out if the line is more
|
||||||
|
* than 255 pixels long -- which, because of
|
||||||
|
* inclusive coordinates, means abs(x0-x1) > 254.
|
||||||
|
lda in_x1l ;assume x0 on left
|
||||||
|
sec
|
||||||
|
sbc in_x0l
|
||||||
|
tax
|
||||||
|
beq checkvert ;low bytes even, check hi
|
||||||
|
lda in_x1h
|
||||||
|
sbc in_x0h
|
||||||
|
bcs lx0left
|
||||||
|
|
||||||
|
* x1 is on the left, so the values are negative
|
||||||
|
* (hi byte in A, lo byte in X)
|
||||||
|
lx0right eor #$ff ;invert hi
|
||||||
|
sta ]deltaxh ;store
|
||||||
|
txa
|
||||||
|
eor #$ff ;invert lo
|
||||||
|
sta ]deltaxl
|
||||||
|
inc ]deltaxl ;add one for 2s complement
|
||||||
|
bne :noinchi ;rolled into high byte?
|
||||||
|
inc ]deltaxh ;yes
|
||||||
|
:noinchi lda in_x1l ;start with x1
|
||||||
|
sta ]xposl
|
||||||
|
lda in_x1h
|
||||||
|
sta ]xposh
|
||||||
|
lda in_y1
|
||||||
|
sta ]ypos
|
||||||
|
sec
|
||||||
|
sbc in_y0 ;compute deltay
|
||||||
|
jmp lncommon
|
||||||
|
|
||||||
|
checkvert
|
||||||
|
lda in_x1h ;diff high bytes
|
||||||
|
sbc in_x0h ;(carry still set)
|
||||||
|
blt lx0right ;width=256, x0 right
|
||||||
|
bne lx0left ;width=256, x0 left
|
||||||
|
jmp vertline ;all zero, go vert
|
||||||
|
|
||||||
|
* (branch back from below)
|
||||||
|
* This is a purely horizontal line. We farm the job
|
||||||
|
* out to the raster fill code for speed. (There's
|
||||||
|
* no problem with the line code handling it; its just
|
||||||
|
* more efficient to let the raster code do it.)
|
||||||
|
phorizontal
|
||||||
|
ldy ]ypos
|
||||||
|
sty rast_top
|
||||||
|
sty rast_bottom
|
||||||
|
lda ]xposl
|
||||||
|
sta rastx0l,y
|
||||||
|
clc
|
||||||
|
adc ]deltaxl ;easier to add delta back
|
||||||
|
sta rastx1l,y ; in than sort out which
|
||||||
|
lda ]xposh ; arg is left vs. right
|
||||||
|
sta rastx0h,y
|
||||||
|
adc ]deltaxh
|
||||||
|
sta rastx1h,y
|
||||||
|
jmp FillRaster
|
||||||
|
|
||||||
|
* x0 is on the left, so the values are positive
|
||||||
|
lx0left stx ]deltaxl
|
||||||
|
sta ]deltaxh
|
||||||
|
lda in_x0l ;start with x0
|
||||||
|
sta ]xposl
|
||||||
|
lda in_x0h
|
||||||
|
sta ]xposh
|
||||||
|
lda in_y0 ;and y0
|
||||||
|
sta ]ypos
|
||||||
|
sec
|
||||||
|
sbc in_y1 ;compute deltay
|
||||||
|
|
||||||
|
* Value of (starty - endy) is in A, flags still set.
|
||||||
|
lncommon
|
||||||
|
bcs :posy
|
||||||
|
eor #$ff ;negative, invert
|
||||||
|
adc #$01
|
||||||
|
sta ]deltay
|
||||||
|
lda #$e8 ;INX
|
||||||
|
bne gotdy
|
||||||
|
:posy
|
||||||
|
_lmb beq phorizontal
|
||||||
|
sta ]deltay
|
||||||
|
lda #$ca ;DEX
|
||||||
|
gotdy sta _hmody
|
||||||
|
sta _vmody
|
||||||
|
sta _wmody
|
||||||
|
|
||||||
|
do 0 ;***** for regression test
|
||||||
|
ldx #$01
|
||||||
|
lda ]deltaxh
|
||||||
|
bne :iswide
|
||||||
|
lda ]deltaxl
|
||||||
|
cmp #$ff ;== 255?
|
||||||
|
beq :iswide
|
||||||
|
ldx #$00 ;notwide
|
||||||
|
:iswide stx $300
|
||||||
|
lda ]xposl
|
||||||
|
sta $301
|
||||||
|
lda ]xposh
|
||||||
|
sta $302
|
||||||
|
lda ]ypos
|
||||||
|
sta $303
|
||||||
|
ldx ]deltaxl
|
||||||
|
stx $304
|
||||||
|
ldx ]deltaxh
|
||||||
|
stx $305
|
||||||
|
ldx ]deltay
|
||||||
|
stx $306
|
||||||
|
lda _hmody
|
||||||
|
and #$20 ;nonzero means inc,
|
||||||
|
sta $307 ; zero means dec
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
* At this point we have the initial X position in
|
||||||
|
* ]startxl/h, the initial Y position in ]starty,
|
||||||
|
* deltax in ]deltaxl, deltay in ]deltay, and we've
|
||||||
|
* tweaked the Y-update instructions to either INC or
|
||||||
|
* DEC depending on the direction of movement.
|
||||||
|
*
|
||||||
|
* The next step is to decide whether the line is
|
||||||
|
* horizontal-dominant or vertical-dominant, and
|
||||||
|
* branch to the appropriate handler.
|
||||||
|
*
|
||||||
|
* The core loops for horiz and vert take about
|
||||||
|
* 80 cycles when moving diagonally, and about
|
||||||
|
* 20 fewer when moving in the primary direction.
|
||||||
|
* The wide-horiz is a bit slower.
|
||||||
|
ldy #$01 ;set "wide" flag to 1
|
||||||
|
lda ]deltaxl
|
||||||
|
ldx ]deltaxh
|
||||||
|
bne horzdom ;width >= 256
|
||||||
|
cmp #$ff ;width == 255
|
||||||
|
beq horzdom
|
||||||
|
dey ;not wide
|
||||||
|
cmp ]deltay
|
||||||
|
bge horzdom ; for diagonal lines
|
||||||
|
jmp vertdom
|
||||||
|
|
||||||
|
* We could special-case pure-diagonal lines here
|
||||||
|
* (just BEQ a couple lines up). It does
|
||||||
|
* represent our worst case. I'm not convinced
|
||||||
|
* we'll see them often enough to make it worthwhile.
|
||||||
|
|
||||||
|
|
||||||
|
* horizontal-dominant
|
||||||
|
horzdom
|
||||||
|
sty ]wideflag
|
||||||
|
sta ]count ;:count = deltax + 1
|
||||||
|
inc ]count
|
||||||
|
lsr ;:diff = deltax / 2
|
||||||
|
sta ]diff
|
||||||
|
|
||||||
|
* set Y to the byte offset in the line
|
||||||
|
* load the AND mask into ]andmask
|
||||||
|
ldx ]xposl
|
||||||
|
lda ]xposh ;>= 256?
|
||||||
|
beq :lotabl ;no, use the low table
|
||||||
|
ldy div7hi,x
|
||||||
|
lda mod7hi,x
|
||||||
|
bpl :gottab ;always
|
||||||
|
* BREAK ;debug
|
||||||
|
:lotabl ldy div7lo,x
|
||||||
|
lda mod7lo,x
|
||||||
|
:gottab
|
||||||
|
tax
|
||||||
|
lda andmask,x
|
||||||
|
sta ]andmask
|
||||||
|
|
||||||
|
* Set initial value for line address.
|
||||||
|
ldx ]ypos
|
||||||
|
lda ylooklo,x
|
||||||
|
sta ]hbasl
|
||||||
|
lda ylookhi,x
|
||||||
|
ora g_page
|
||||||
|
sta ]hbasl+1
|
||||||
|
|
||||||
|
lda ]wideflag ;is this a "wide" line?
|
||||||
|
beq :notwide ;nope, stay local
|
||||||
|
jmp widedom
|
||||||
|
|
||||||
|
:notwide lda colorline,y ;set initial color mask
|
||||||
|
sta _hlcolor+1
|
||||||
|
jmp horzloop
|
||||||
|
|
||||||
|
hrts rts
|
||||||
|
|
||||||
|
* bottom of loop, essentially
|
||||||
|
hnoroll sta ]diff ;3
|
||||||
|
hdecc dec ]count ;5 :count--
|
||||||
|
beq hrts ;2 :while (count != 0)
|
||||||
|
;= 7 or 10
|
||||||
|
|
||||||
|
* We keep the byte offset in the line in Y, and the
|
||||||
|
* line index in X, for the entire loop.
|
||||||
|
horzloop
|
||||||
|
_hlcolor lda #$00 ;2 start with color pattern
|
||||||
|
_lmdh eor (]hbasl),y ;5 flip all bits
|
||||||
|
and ]andmask ;3 clear other bits
|
||||||
|
eor (]hbasl),y ;5 restore ours, set theirs
|
||||||
|
sta (]hbasl),y ;6 = 21
|
||||||
|
|
||||||
|
* Move right. We shift the bit mask that determines
|
||||||
|
* the pixel. When we shift into bit 7, we know it's
|
||||||
|
* time to advance another byte.
|
||||||
|
*
|
||||||
|
* If this is a shallow line we would benefit from
|
||||||
|
* keeping the index in X and just doing a 4-cycle
|
||||||
|
* indexed load to get the mask. Not having the
|
||||||
|
* line number in X makes the line calc more
|
||||||
|
* expensive for steeper lines though.
|
||||||
|
lda ]andmask ;3
|
||||||
|
asl ;2 shift, losing hi bit
|
||||||
|
eor #$80 ;2 set the hi bit
|
||||||
|
bne :noh8 ;3 cleared hi bit?
|
||||||
|
* We could BEQ away and branch back in, but this
|
||||||
|
* happens every 7 iterations, so on average it's
|
||||||
|
* a very small improvement. If we happen to branch
|
||||||
|
* across a page boundary the double-branch adds
|
||||||
|
* two more cycles and we lose.
|
||||||
|
iny ;2 advance to next byte
|
||||||
|
lda colorline,y ;4 update color mask
|
||||||
|
sta _hlcolor+1 ;4
|
||||||
|
lda #$81 ;2 reset
|
||||||
|
:noh8 sta ]andmask ;3 = 13 + ((12-1)/7) = 14
|
||||||
|
|
||||||
|
* Update error diff.
|
||||||
|
lda ]diff ;3
|
||||||
|
sec ;2
|
||||||
|
sbc ]deltay ;3 :diff -= deltay
|
||||||
|
bcs hnoroll ;2+ :if (diff < 0) ...
|
||||||
|
;= 11 level, 10 up/down
|
||||||
|
adc ]deltaxl ;3 : diff += deltax
|
||||||
|
sta ]diff ;3
|
||||||
|
_hmody inx ;2 : ypos++ (or --)
|
||||||
|
lda ylooklo,x ;4 update hbasl after line
|
||||||
|
sta ]hbasl ;3 change
|
||||||
|
lda ylookhi,x ;4
|
||||||
|
_pg_or4 ora #$20 ;2
|
||||||
|
sta ]hbasl+1 ;3
|
||||||
|
bne hdecc ;3 = +27 this path -> 37
|
||||||
|
BREAK
|
||||||
|
* horizontal: 10+21+14+11=56 cycles/pixel
|
||||||
|
* diagonal: 7+21+14+37=79 cycles/pixel
|
||||||
|
|
||||||
|
|
||||||
|
* Vertical-dominant line. Could go up or down.
|
||||||
|
vertdom
|
||||||
|
ldx in_y0
|
||||||
|
cpx ]ypos ;starting at y0?
|
||||||
|
bne :endy0 ;yup
|
||||||
|
ldx in_y1 ;nope
|
||||||
|
:endy0 stx _vchk+1 ;end condition
|
||||||
|
|
||||||
|
lda ]deltay
|
||||||
|
lsr
|
||||||
|
sta ]diff ;:diff = deltay / 2
|
||||||
|
|
||||||
|
* set Y to the byte offset in the line
|
||||||
|
* load the AND mask into ]andmask
|
||||||
|
ldx ]xposl
|
||||||
|
lda ]xposh ;>= 256?
|
||||||
|
beq :lotabl ;no, use the low table
|
||||||
|
ldy div7hi,x
|
||||||
|
lda mod7hi,x
|
||||||
|
bpl :gottab ;always
|
||||||
|
BREAK ;debug
|
||||||
|
:lotabl ldy div7lo,x
|
||||||
|
lda mod7lo,x
|
||||||
|
:gottab
|
||||||
|
tax
|
||||||
|
lda andmask,x ;initial pixel mask
|
||||||
|
sta ]andmask
|
||||||
|
|
||||||
|
lda colorline,y ;initial color mask
|
||||||
|
sta _vlcolor+1
|
||||||
|
|
||||||
|
ldx ]ypos
|
||||||
|
jmp vertloop
|
||||||
|
|
||||||
|
* We keep the byte offset in the line in Y, and the
|
||||||
|
* line index in X, for the entire loop.
|
||||||
|
|
||||||
|
* Bottom of loop, essentially.
|
||||||
|
vnoroll sta ]diff ;3
|
||||||
|
|
||||||
|
vertloop
|
||||||
|
lda ylooklo,x ;4
|
||||||
|
sta ]hbasl ;3
|
||||||
|
lda ylookhi,x ;4
|
||||||
|
_pg_or5 ora #$20 ;2
|
||||||
|
sta ]hbasl+1 ;3 = 16
|
||||||
|
|
||||||
|
_vlcolor lda #$00 ;2 start with color pattern
|
||||||
|
_lmdv eor (]hbasl),y ;5 flip all bits
|
||||||
|
and ]andmask ;3 clear other bits
|
||||||
|
eor (]hbasl),y ;5 restore ours, set theirs
|
||||||
|
sta (]hbasl),y ;6 = 21
|
||||||
|
|
||||||
|
_vchk cpx #$00 ;2 was this last line?
|
||||||
|
beq vrts ;2 yes, done
|
||||||
|
_vmody inx ;2 :ypos++ (or --)
|
||||||
|
|
||||||
|
* Update error diff.
|
||||||
|
lda ]diff ;3
|
||||||
|
sec ;2
|
||||||
|
sbc ]deltaxl ;3 :diff -= deltax
|
||||||
|
bcs vnoroll ;2 :if (diff < 0) ...
|
||||||
|
;= 10 vert, 9 move right
|
||||||
|
|
||||||
|
adc ]deltay ;3 : diff += deltay
|
||||||
|
sta ]diff ;3
|
||||||
|
* Move right. We shift the bit mask that determines
|
||||||
|
* the pixel. When we shift into bit 7, we know it's
|
||||||
|
* time to advance another byte.
|
||||||
|
lda ]andmask ;3
|
||||||
|
asl ;2 shift, losing hi bit
|
||||||
|
eor #$80 ;2 set the hi bit
|
||||||
|
beq :is8 ;2+ goes to zero on 8th bit
|
||||||
|
sta ]andmask ;3
|
||||||
|
bne vertloop ;3 = 21 + (18/7) = 24
|
||||||
|
BREAK
|
||||||
|
|
||||||
|
:is8 iny ;2 advance to next byte
|
||||||
|
lda colorline,y ;4 update color
|
||||||
|
sta _vlcolor+1 ;4
|
||||||
|
lda #$81 ;2 reset
|
||||||
|
sta ]andmask ;3
|
||||||
|
bne vertloop ;3 = 18
|
||||||
|
BREAK
|
||||||
|
vrts rts
|
||||||
|
* vertical: 3 + 16 + 21 + 6 + 10 = 56 cycles
|
||||||
|
* diagonal: 16 + 21 + 6 + 9 + 24 = 76 cycles
|
||||||
|
|
||||||
|
|
||||||
|
* "Wide" horizontally-dominant loop. We have to
|
||||||
|
* maintain error-diff and deltax as 16-bit values.
|
||||||
|
* Most of the setup from the "narrow" version carried
|
||||||
|
* over, but we have to re-do the count and diff.
|
||||||
|
*
|
||||||
|
* Normally we set count to (deltax + 1) and decrement
|
||||||
|
* to zero, but it's actually easier to set it equal
|
||||||
|
* to deltax and check for -1.
|
||||||
|
widedom
|
||||||
|
lda ]deltaxh ;:count = deltax
|
||||||
|
sta ]counth
|
||||||
|
ldx ]deltaxl
|
||||||
|
stx ]count
|
||||||
|
stx ]diff
|
||||||
|
lsr ;:diff = deltax / 2
|
||||||
|
ror ]diff
|
||||||
|
sta ]diffh
|
||||||
|
ldx ]ypos
|
||||||
|
|
||||||
|
lda colorline,y ;set initial color mask
|
||||||
|
sta _wlcolor+1
|
||||||
|
|
||||||
|
* We keep the byte offset in the line in Y, and the
|
||||||
|
* line index in X, for the entire loop.
|
||||||
|
wideloop
|
||||||
|
_wlcolor lda #$00 ;2 start with color pattern
|
||||||
|
_lmdw eor (]hbasl),y ;5 flip all bits
|
||||||
|
and ]andmask ;3 clear other bits
|
||||||
|
eor (]hbasl),y ;5 restore ours, set theirs
|
||||||
|
sta (]hbasl),y ;6 = 21
|
||||||
|
|
||||||
|
* Move right. We shift the bit mask that determines
|
||||||
|
* the pixel. When we shift into bit 7, we know it's
|
||||||
|
* time to advance another byte.
|
||||||
|
lda ]andmask ;3
|
||||||
|
asl ;2 shift, losing hi bit
|
||||||
|
eor #$80 ;2 set the hi bit
|
||||||
|
bne :not7 ;3 goes to zero on 8th bit
|
||||||
|
iny ; 2 advance to next byte
|
||||||
|
lda colorline,y ; 4 update color mask
|
||||||
|
sta _hlcolor+1 ; 4
|
||||||
|
lda #$81 ; 2 reset
|
||||||
|
:not7 sta ]andmask ;3 = 13 usually, 25 every 7
|
||||||
|
|
||||||
|
* Update error diff, which is a positive number. If
|
||||||
|
* it goes negative ("if (diff < 0)") we act.
|
||||||
|
lda ]diff
|
||||||
|
sec
|
||||||
|
sbc ]deltay ;:diff -= deltay
|
||||||
|
bcs wnoroll ;didn't even roll low byte
|
||||||
|
dec ]diffh ;check hi byte
|
||||||
|
bpl wnoroll ;went 1->0, keep going
|
||||||
|
|
||||||
|
adc ]deltaxl ;: diff += deltax
|
||||||
|
sta ]diff
|
||||||
|
lda ]diffh
|
||||||
|
adc ]deltaxh
|
||||||
|
sta ]diffh
|
||||||
|
_wmody inx ;: ypos++ (or --)
|
||||||
|
lda ylooklo,x ;update hbasl after line
|
||||||
|
sta ]hbasl ; change
|
||||||
|
lda ylookhi,x
|
||||||
|
_pg_or6 ora #$20
|
||||||
|
sta ]hbasl+1
|
||||||
|
bne wdecc
|
||||||
|
BREAK
|
||||||
|
|
||||||
|
wnoroll sta ]diff
|
||||||
|
|
||||||
|
wdecc dec ]count ;5 :count--
|
||||||
|
lda ]count ;3
|
||||||
|
cmp #$ff ;2
|
||||||
|
bne wideloop ;3 :while (count > -1)
|
||||||
|
dec ]counth ;low rolled, decr high
|
||||||
|
beq wideloop ;went 1->0, keep going
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
||||||
|
* Pure-vertical line. These are common in certain
|
||||||
|
* applications, and checking for it only adds two
|
||||||
|
* cycles to the general case.
|
||||||
|
vertline
|
||||||
|
ldx in_y0
|
||||||
|
ldy in_y1
|
||||||
|
cpx in_y1 ;y0 < y1?
|
||||||
|
blt :usey0 ;yes, go from y0 to y1
|
||||||
|
txa ;swap X/A
|
||||||
|
tay
|
||||||
|
ldx in_y1
|
||||||
|
:usey0 stx ]ypos
|
||||||
|
iny
|
||||||
|
sty _pvytest+1
|
||||||
|
|
||||||
|
ldx in_x0l ;xc lo
|
||||||
|
lda in_x0h ;>= 256?
|
||||||
|
beq :lotabl
|
||||||
|
ldy div7hi,x
|
||||||
|
lda mod7hi,x
|
||||||
|
bpl :gotit ;always
|
||||||
|
:lotabl ldy div7lo,x
|
||||||
|
lda mod7lo,x
|
||||||
|
|
||||||
|
* Byte offset is in Y, mod-7 value is in A.
|
||||||
|
:gotit tax
|
||||||
|
lda andmask,x
|
||||||
|
sta _pvand+1 ;this doesn't change
|
||||||
|
|
||||||
|
lda colorline,y
|
||||||
|
sta _pvcolor+1 ;nor does this
|
||||||
|
|
||||||
|
ldx ]ypos ;top line
|
||||||
|
|
||||||
|
* There's a trick where, when (linenum & 0x07) is
|
||||||
|
* nonzero, you just add 4 to hbasl+1 instead of
|
||||||
|
* re-doing the lookup. However, TXA+AND+BEQ
|
||||||
|
* followed by LDA+CLC+ADC+STA is 16 cycles, the same
|
||||||
|
* as our self-modified lookup, so it's not a win.
|
||||||
|
* (And if we used a second ylookhi and self-modded
|
||||||
|
* the table address, we could shave off another 2.)
|
||||||
|
|
||||||
|
* Main pure-vertical loop
|
||||||
|
pverloop
|
||||||
|
lda ylooklo,x ;4
|
||||||
|
sta ]hbasl ;3
|
||||||
|
lda ylookhi,x ;4
|
||||||
|
_pg_or7 ora #$20 ;2
|
||||||
|
sta ]hbasl+1 ;3 (= 16)
|
||||||
|
|
||||||
|
_pvcolor lda #$00 ;2 start with color pattern
|
||||||
|
_lmdpv eor (]hbasl),y ;5 flip all bits
|
||||||
|
_pvand and #$00 ;2 clear other bits
|
||||||
|
eor (]hbasl),y ;5
|
||||||
|
sta (]hbasl),y ;6 (= 20)
|
||||||
|
|
||||||
|
inx ;2
|
||||||
|
_pvytest cpx #$00 ;2 done?
|
||||||
|
bne pverloop ;3 = 7
|
||||||
|
rts
|
||||||
|
* 43 cycles/pixel
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Set the line mode according to in_arg
|
||||||
|
*
|
||||||
|
* A slightly silly feature to get xdraw lines
|
||||||
|
* without really working for it.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
SetLineMode
|
||||||
|
lda in_arg
|
||||||
|
beq :standard
|
||||||
|
|
||||||
|
* configure for xdraw
|
||||||
|
lda #$24 ;BIT dp
|
||||||
|
sta _lmb
|
||||||
|
sta _lmdh
|
||||||
|
sta _lmdv
|
||||||
|
sta _lmdw
|
||||||
|
sta _lmdpv
|
||||||
|
rts
|
||||||
|
|
||||||
|
* configure for standard drawing
|
||||||
|
:standard lda #$f0 ;BEQ
|
||||||
|
sta _lmb
|
||||||
|
lda #$51 ;EOR (dp),y
|
||||||
|
sta _lmdh
|
||||||
|
sta _lmdv
|
||||||
|
sta _lmdw
|
||||||
|
sta _lmdpv
|
||||||
|
rts
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,807 @@
|
||||||
|
********************************
|
||||||
|
* *
|
||||||
|
* Fast Apple II Graphics *
|
||||||
|
* By Andy McFadden *
|
||||||
|
* Version 0.3, Aug 2015 *
|
||||||
|
* *
|
||||||
|
* Main source file *
|
||||||
|
* *
|
||||||
|
* Developed with Merlin-16 *
|
||||||
|
* *
|
||||||
|
********************************
|
||||||
|
|
||||||
|
* Set to 1 to build FDRAW.FAST, set to zero to
|
||||||
|
* build FDRAW.SMALL.
|
||||||
|
USE_FAST equ 1
|
||||||
|
|
||||||
|
* Set to 1 to turn on beeps/clicks for debugging.
|
||||||
|
NOISE_ON equ 0
|
||||||
|
|
||||||
|
|
||||||
|
lst off
|
||||||
|
org $9400 ;;; CUSTOMIZED FOR APPLECORN
|
||||||
|
|
||||||
|
*
|
||||||
|
* Macros.
|
||||||
|
*
|
||||||
|
spkr equ $c030
|
||||||
|
bell equ $ff3a
|
||||||
|
|
||||||
|
* If enabled, click the speaker (changes flags only).
|
||||||
|
CLICK mac
|
||||||
|
do NOISE_ON
|
||||||
|
bit spkr
|
||||||
|
fin
|
||||||
|
<<<
|
||||||
|
* If enabled, beep the speaker (scrambles regs).
|
||||||
|
BEEP mac
|
||||||
|
do NOISE_ON
|
||||||
|
jsr bell
|
||||||
|
fin
|
||||||
|
<<<
|
||||||
|
* If enabled, insert a BRK.
|
||||||
|
BREAK mac
|
||||||
|
do NOISE_ON
|
||||||
|
brk $99
|
||||||
|
fin
|
||||||
|
<<<
|
||||||
|
|
||||||
|
* In "fast" mode, we align tables on page boundaries so we
|
||||||
|
* don't take a 1-cycle hit when the indexing crosses a page.
|
||||||
|
* In "small" mode, we skip the alignment.
|
||||||
|
PG_ALIGN mac
|
||||||
|
do USE_FAST
|
||||||
|
ds \
|
||||||
|
fin
|
||||||
|
<<<
|
||||||
|
|
||||||
|
*
|
||||||
|
* Hi-res screen constants.
|
||||||
|
*
|
||||||
|
BYTES_PER_ROW = 40
|
||||||
|
NUM_ROWS = 192
|
||||||
|
NUM_COLS = 280
|
||||||
|
|
||||||
|
*
|
||||||
|
* Variable storage. We assign generic names to
|
||||||
|
* zero-page scratch locations, then assign variables
|
||||||
|
* with real names to these.
|
||||||
|
*
|
||||||
|
* 06-09 are unused (except by SWEET-16)
|
||||||
|
* 1a-1d are Applesoft hi-res scratch
|
||||||
|
* cc-cf are only used by INTBASIC
|
||||||
|
* eb-ef and ff appear totally unused by ROM routines
|
||||||
|
*
|
||||||
|
zptr0 equ $1a ;2b
|
||||||
|
zloc0 equ $06
|
||||||
|
zloc1 equ $07
|
||||||
|
zloc2 equ $08
|
||||||
|
zloc3 equ $09
|
||||||
|
zloc4 equ $1c
|
||||||
|
zloc5 equ $1d
|
||||||
|
zloc6 equ $cc
|
||||||
|
zloc7 equ $cd
|
||||||
|
zloc8 equ $ce
|
||||||
|
zloc9 equ $cf
|
||||||
|
zloc10 equ $eb
|
||||||
|
zloc11 equ $ec
|
||||||
|
zloc12 equ $ed
|
||||||
|
zloc13 equ $ee
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Entry points for external programs.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
Entry
|
||||||
|
jmp Init ;initialize data tables
|
||||||
|
dfb 0,3 ;version number
|
||||||
|
|
||||||
|
*
|
||||||
|
* Parameters passed from external programs.
|
||||||
|
*
|
||||||
|
in_arg ds 1 ;generic argument
|
||||||
|
in_x0l ds 1 ;X coordinate 0, low part
|
||||||
|
in_x0h ds 1 ;X coordinate 0, high part
|
||||||
|
in_y0 ds 1 ;Y coordinate 0
|
||||||
|
in_x1l ds 1
|
||||||
|
in_x1h ds 1
|
||||||
|
in_y1 ds 1
|
||||||
|
in_rad ds 1 ;radius for circles
|
||||||
|
|
||||||
|
ds 3 ;pad to 16 bytes
|
||||||
|
|
||||||
|
jmp SetColor
|
||||||
|
jmp SetPage
|
||||||
|
jmp Clear
|
||||||
|
jmp DrawPoint
|
||||||
|
jmp DrawLine
|
||||||
|
jmp DrawRect
|
||||||
|
jmp FillRect
|
||||||
|
jmp DrawCircle
|
||||||
|
jmp FillCircle
|
||||||
|
jmp SetLineMode
|
||||||
|
jmp noimpl ;reserved2
|
||||||
|
jmp FillRaster
|
||||||
|
|
||||||
|
* Raster fill values. Top, bottom, and pointers to tables
|
||||||
|
* for the benefit of external callers.
|
||||||
|
rast_top ds 1
|
||||||
|
rast_bottom ds 1
|
||||||
|
da rastx0l
|
||||||
|
da rastx0h
|
||||||
|
da rastx1l
|
||||||
|
da rastx1h
|
||||||
|
|
||||||
|
noimpl rts
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Global variables.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
|
||||||
|
g_inited dfb 0 ;initialized?
|
||||||
|
g_color dfb 0 ;hi-res color (0-7)
|
||||||
|
g_page dfb $20 ;hi-res page ($20 or $40)
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Initialize.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
Init
|
||||||
|
lda #$00
|
||||||
|
sta in_arg
|
||||||
|
jsr SetColor ;set color to zero
|
||||||
|
jsr SetLineMode ;set normal lines
|
||||||
|
lda #$20
|
||||||
|
sta in_arg
|
||||||
|
sta g_inited
|
||||||
|
jmp SetPage ;set hi-res page 1
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Set the color.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
SetColor
|
||||||
|
lda in_arg
|
||||||
|
cmp g_color ;same as the old color?
|
||||||
|
beq :done
|
||||||
|
|
||||||
|
and #$07 ;safety first
|
||||||
|
sta g_color
|
||||||
|
|
||||||
|
* Update the "colorline" table, which provides a quick color
|
||||||
|
* lookup for odd/even bytes. We could also have one table
|
||||||
|
* per color and self-mod the "LDA addr,y" instructions to
|
||||||
|
* point to the current one, but that uses a bunch of memory
|
||||||
|
* and is kind of ugly. Takes 16 + (12 * 40) = 496 cycles.
|
||||||
|
tax ;2
|
||||||
|
lda xormask,x ;4
|
||||||
|
sta :_xormsk+1 ;4
|
||||||
|
|
||||||
|
lda oddcolor,x ;4
|
||||||
|
ldy #BYTES_PER_ROW-1 ;2
|
||||||
|
]loop sta colorline,y ;5
|
||||||
|
:_xormsk eor #$00 ;2
|
||||||
|
dey ;2
|
||||||
|
bpl ]loop ;3
|
||||||
|
|
||||||
|
:done rts
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Set the page.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
SetPage
|
||||||
|
lda g_inited ;let's just check this
|
||||||
|
beq noinit ; (not called too often)
|
||||||
|
|
||||||
|
lda in_arg
|
||||||
|
cmp #$20
|
||||||
|
beq :good
|
||||||
|
cmp #$40
|
||||||
|
beq :good
|
||||||
|
jmp bell
|
||||||
|
:good
|
||||||
|
sta g_page
|
||||||
|
|
||||||
|
do 0 ;*****
|
||||||
|
cmp ylookhi
|
||||||
|
beq :tabok
|
||||||
|
* Check to see if the values currently in the Y-lookup table
|
||||||
|
* match our current page setting. If they don't, we need to
|
||||||
|
* adjust the code that does lookups.
|
||||||
|
|
||||||
|
* This approach modifies the table itself, paying a large
|
||||||
|
* cost now so we don't have to pay it on every lookup.
|
||||||
|
* However, this costs 2+(16*192)=3074 cycles, while an
|
||||||
|
* "ORA imm" only adds two to each lookup, so we'd have
|
||||||
|
* to do a lot of drawing to make this worthwhile.
|
||||||
|
* (Note: assumes ylookhi is based at $2000 not $0000)
|
||||||
|
ldy #NUM_ROWS ;2
|
||||||
|
]loop lda ylookhi-1,y ;4
|
||||||
|
eor #$60 ;2 $20 <--> $40
|
||||||
|
sta ylookhi-1,y ;5
|
||||||
|
dey ;2
|
||||||
|
bne ]loop ;3
|
||||||
|
|
||||||
|
else ;*****
|
||||||
|
|
||||||
|
* This approach uses self-modifying code to update the
|
||||||
|
* relevant instructions. It's a bit messy to have it
|
||||||
|
* here, but it saves us from having to do it on
|
||||||
|
* every call.
|
||||||
|
*
|
||||||
|
* We could also have a second y-lookup table and
|
||||||
|
* use this to update the pointers. That would let
|
||||||
|
* us drop the "ORA imm" entirely, without the cost
|
||||||
|
* of the rewrite above, but eating up another 192 bytes.
|
||||||
|
sta _pg_or1+1 ;rastfill
|
||||||
|
sta _pg_or2+1 ;circle hplot
|
||||||
|
sta _pg_or3+1 ;circle hplot
|
||||||
|
sta _pg_or4+1 ;drawline
|
||||||
|
sta _pg_or5+1 ;drawline
|
||||||
|
sta _pg_or6+1 ;drawline
|
||||||
|
sta _pg_or7+1 ;drawline
|
||||||
|
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
:tabok rts
|
||||||
|
|
||||||
|
noinit ldy #$00
|
||||||
|
]loop lda :initmsg,y
|
||||||
|
beq :done
|
||||||
|
jsr $fded ;cout
|
||||||
|
iny
|
||||||
|
bne ]loop
|
||||||
|
:done rts
|
||||||
|
|
||||||
|
:initmsg asc "FDRAW NOT INITIALIZED",87,87,00
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Clear the screen to the current color.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
Clear
|
||||||
|
|
||||||
|
do USE_FAST ;*****
|
||||||
|
* This performs a "visually linear" clear, erasing the screen
|
||||||
|
* from left to right and top to bottom. To reduce the amount
|
||||||
|
* of code required we erase in thirds (top/middle/bottom).
|
||||||
|
*
|
||||||
|
* Compare to a "venetian blind" clear, which is what you get
|
||||||
|
* if you erase memory linearly.
|
||||||
|
*
|
||||||
|
* The docs discuss different approaches. This version
|
||||||
|
* requires ((2 + 5*64 + 11) * 40 + 14) * 3 = 40002 cycles.
|
||||||
|
* If we didn't divide it into thirds to keep the top-down
|
||||||
|
* look, we'd need (5*64 + 9) * 120 = 39480 cycles, so
|
||||||
|
* we're spending 522 cycles to avoid the venetian look.
|
||||||
|
lda :clrloop+2
|
||||||
|
cmp g_page
|
||||||
|
beq :pageok
|
||||||
|
|
||||||
|
* We're on the wrong hi-res page. Flip to the other one.
|
||||||
|
* 4 + (20*64) = 1284 cycles to do the flip (+ a few more
|
||||||
|
* because we're probably crossing a page boundary).
|
||||||
|
BEEP
|
||||||
|
ldy #NUM_ROWS ;2
|
||||||
|
]loop lda :clrloop-3+2,y ;4
|
||||||
|
eor #$60 ;2
|
||||||
|
sta :clrloop-3+2,y ;5
|
||||||
|
dey ;2
|
||||||
|
dey ;2
|
||||||
|
dey ;2
|
||||||
|
bne ]loop ;3
|
||||||
|
|
||||||
|
:pageok ldx g_color ;grab the current color
|
||||||
|
lda xormask,x
|
||||||
|
sta :_xormsk+1
|
||||||
|
lda evencolor,x
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
jsr :clearthird
|
||||||
|
ldy #BYTES_PER_ROW
|
||||||
|
jsr :clearthird
|
||||||
|
ldy #BYTES_PER_ROW*2
|
||||||
|
* fall through into :clearthird for final pass
|
||||||
|
|
||||||
|
:clearthird
|
||||||
|
ldx #BYTES_PER_ROW-1 ;2
|
||||||
|
:clrloop sta $2000,y ;5 (* 64)
|
||||||
|
sta $2400,y ;this could probably be
|
||||||
|
sta $2800,y ; done with LUP math
|
||||||
|
sta $2c00,y
|
||||||
|
sta $3000,y
|
||||||
|
sta $3400,y
|
||||||
|
sta $3800,y
|
||||||
|
sta $3c00,y
|
||||||
|
sta $2080,y
|
||||||
|
sta $2480,y
|
||||||
|
sta $2880,y
|
||||||
|
sta $2c80,y
|
||||||
|
sta $3080,y
|
||||||
|
sta $3480,y
|
||||||
|
sta $3880,y
|
||||||
|
sta $3c80,y
|
||||||
|
sta $2100,y
|
||||||
|
sta $2500,y
|
||||||
|
sta $2900,y
|
||||||
|
sta $2d00,y
|
||||||
|
sta $3100,y
|
||||||
|
sta $3500,y
|
||||||
|
sta $3900,y
|
||||||
|
sta $3d00,y
|
||||||
|
sta $2180,y
|
||||||
|
sta $2580,y
|
||||||
|
sta $2980,y
|
||||||
|
sta $2d80,y
|
||||||
|
sta $3180,y
|
||||||
|
sta $3580,y
|
||||||
|
sta $3980,y
|
||||||
|
sta $3d80,y
|
||||||
|
sta $2200,y
|
||||||
|
sta $2600,y
|
||||||
|
sta $2a00,y
|
||||||
|
sta $2e00,y
|
||||||
|
sta $3200,y
|
||||||
|
sta $3600,y
|
||||||
|
sta $3a00,y
|
||||||
|
sta $3e00,y
|
||||||
|
sta $2280,y
|
||||||
|
sta $2680,y
|
||||||
|
sta $2a80,y
|
||||||
|
sta $2e80,y
|
||||||
|
sta $3280,y
|
||||||
|
sta $3680,y
|
||||||
|
sta $3a80,y
|
||||||
|
sta $3e80,y
|
||||||
|
sta $2300,y
|
||||||
|
sta $2700,y
|
||||||
|
sta $2b00,y
|
||||||
|
sta $2f00,y
|
||||||
|
sta $3300,y
|
||||||
|
sta $3700,y
|
||||||
|
sta $3b00,y
|
||||||
|
sta $3f00,y
|
||||||
|
sta $2380,y
|
||||||
|
sta $2780,y
|
||||||
|
sta $2b80,y
|
||||||
|
sta $2f80,y
|
||||||
|
sta $3380,y
|
||||||
|
sta $3780,y
|
||||||
|
sta $3b80,y
|
||||||
|
sta $3f80,y
|
||||||
|
:_xormsk eor #$00 ;2 flip odd/even bits
|
||||||
|
iny ;2
|
||||||
|
dex ;2
|
||||||
|
bmi :done ;2
|
||||||
|
jmp :clrloop ;3
|
||||||
|
:done rts
|
||||||
|
|
||||||
|
else ;***** not USE_FAST
|
||||||
|
|
||||||
|
* This version was suggested by Marcus Heuser on
|
||||||
|
* comp.sys.apple2.programmer. It does a "venetian blind"
|
||||||
|
* clear, and takes (5 * 32 + 7) * 248 = 41416 cycles.
|
||||||
|
* It overwrites half of the screen holes.
|
||||||
|
lda :clrloop+5
|
||||||
|
cmp g_page
|
||||||
|
beq :pageok
|
||||||
|
|
||||||
|
* We're on the wrong hi-res page. Flip to the other one.
|
||||||
|
* 12 + (20*31) = 632 cycles to do the flip. We have to
|
||||||
|
* single out the first entry because it's $1f not $20.
|
||||||
|
BEEP
|
||||||
|
lda :clrloop+2 ;4
|
||||||
|
eor #$20 ;2 $1f <-> $3f
|
||||||
|
sta :clrloop+2 ;4
|
||||||
|
ldy #31*3 ;2
|
||||||
|
]loop lda :clrloop+2,y ;4
|
||||||
|
eor #$60 ;2 $20 <-> $40
|
||||||
|
sta :clrloop+2,y ;5
|
||||||
|
dey ;2
|
||||||
|
dey ;2
|
||||||
|
dey ;2
|
||||||
|
bne ]loop ;3
|
||||||
|
|
||||||
|
:pageok ldx g_color
|
||||||
|
lda xormask,x
|
||||||
|
sta :_xormsk+1
|
||||||
|
lda oddcolor,x
|
||||||
|
ldy #248 ;120 + 8 + 120
|
||||||
|
:clrloop
|
||||||
|
]addr = $1fff
|
||||||
|
lup 32 ;begin a loop in assembler
|
||||||
|
sta ]addr,y ;5
|
||||||
|
]addr = ]addr+$100 ;sta 20ff,21ff,...
|
||||||
|
--^
|
||||||
|
:_xormsk eor #$00 ;2
|
||||||
|
dey ;2
|
||||||
|
bne :clrloop ;3
|
||||||
|
rts
|
||||||
|
|
||||||
|
fin ;***** not USE_FAST
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Draw rectangle outline.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
DrawRect
|
||||||
|
* We could just issue 4 line draw calls here, maybe
|
||||||
|
* adjusting the vertical lines by 1 pixel up/down to
|
||||||
|
* avoid overdraw. But if the user wanted 4 lines,
|
||||||
|
* they could just draw 4 lines. Instead, we're going
|
||||||
|
* to draw a double line on each edge to ensure that
|
||||||
|
* the outline rectangle always has the correct color.
|
||||||
|
*
|
||||||
|
* Rather than draw two vertical lines, we draw a
|
||||||
|
* two-pixel-wide filled rectangle on each side.
|
||||||
|
*
|
||||||
|
* We don't want to double-up if the rect is only one
|
||||||
|
* pixel wide, so we have to check for that.
|
||||||
|
*
|
||||||
|
* If the rect is one pixel high, it's just a line.
|
||||||
|
* If it's two pixels high, we don't need to draw
|
||||||
|
* the left/right edges, just the top/bottom lines.
|
||||||
|
* If it's more than two tall, we don't need to draw
|
||||||
|
* the left/right edges on the top and bottom lines,
|
||||||
|
* so we save a few cycles by skipping those.
|
||||||
|
|
||||||
|
lda in_y1 ;copy top/bottom to local
|
||||||
|
sta rast_bottom
|
||||||
|
dec rast_bottom ;move up one
|
||||||
|
sec
|
||||||
|
sbc in_y0
|
||||||
|
beq :isline ;1 pixel high, just draw line
|
||||||
|
cmp #1
|
||||||
|
beq :twolines ;2 pixels high, lines only
|
||||||
|
ldy in_y0
|
||||||
|
iny ;start down a line
|
||||||
|
sty rast_top
|
||||||
|
|
||||||
|
lda in_x0h ;check to see if left/right
|
||||||
|
cmp in_x1h ; coords are the same; if
|
||||||
|
bne :notline ; so, going +1/-1 at edge
|
||||||
|
lda in_x0l ; will overdraw.
|
||||||
|
cmp in_x1l
|
||||||
|
bne :notlin1
|
||||||
|
|
||||||
|
:isline jmp DrawLine ;just treat like line
|
||||||
|
|
||||||
|
* Set up left edge. Top line is in Y.
|
||||||
|
:notline lda in_x0l
|
||||||
|
:notlin1 sta rastx0l,y
|
||||||
|
clc
|
||||||
|
adc #1
|
||||||
|
sta rastx1l,y
|
||||||
|
lda in_x0h
|
||||||
|
ora #$80 ;"repeat" flag
|
||||||
|
sta rastx0h,y
|
||||||
|
and #$7f
|
||||||
|
adc #0
|
||||||
|
sta rastx1h,y
|
||||||
|
jsr FillRaster
|
||||||
|
|
||||||
|
ldy rast_top
|
||||||
|
lda in_x1l ;now set up right edge
|
||||||
|
sta rastx1l,y
|
||||||
|
sec
|
||||||
|
sbc #1
|
||||||
|
sta rastx0l,y
|
||||||
|
lda in_x1h
|
||||||
|
sta rastx1h,y
|
||||||
|
sbc #0
|
||||||
|
ora #$80 ;"repeat" flag
|
||||||
|
sta rastx0h,y
|
||||||
|
jsr FillRaster
|
||||||
|
|
||||||
|
* Now the top/bottom lines.
|
||||||
|
:twolines
|
||||||
|
ldy in_y0
|
||||||
|
jsr :drawline
|
||||||
|
ldy in_y1
|
||||||
|
|
||||||
|
:drawline
|
||||||
|
sty rast_top
|
||||||
|
sty rast_bottom
|
||||||
|
lda in_x0l ;copy left/right to the
|
||||||
|
sta rastx0l,y ; table entry for the
|
||||||
|
lda in_x0h ; appropriate line
|
||||||
|
sta rastx0h,y
|
||||||
|
lda in_x1l
|
||||||
|
sta rastx1l,y
|
||||||
|
lda in_x1h
|
||||||
|
sta rastx1h,y
|
||||||
|
jmp FillRaster
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Draw filled rectangle.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
FillRect
|
||||||
|
* Just fill out the raster table and call the fill routine.
|
||||||
|
* We require y0=top, y1=bottom, x0=left, x1=right.
|
||||||
|
ldy in_y0
|
||||||
|
sty rast_top
|
||||||
|
lda in_y1
|
||||||
|
sta rast_bottom
|
||||||
|
|
||||||
|
lda in_x0l
|
||||||
|
sta rastx0l,y
|
||||||
|
lda in_x0h
|
||||||
|
ora #$80 ;"repeat" flag
|
||||||
|
sta rastx0h,y
|
||||||
|
lda in_x1l
|
||||||
|
sta rastx1l,y
|
||||||
|
lda in_x1h
|
||||||
|
sta rastx1h,y
|
||||||
|
|
||||||
|
jmp FillRaster
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Fill an area defined by the raster tables.
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
FillRaster
|
||||||
|
|
||||||
|
* Render rasterized output. The left and right edges
|
||||||
|
* are stored in the rastx0/rastx1 tables, and the top
|
||||||
|
* and bottom-most pixels are in rast_top/rast_bottom.
|
||||||
|
*
|
||||||
|
* This can be used to render an arbitrary convex
|
||||||
|
* polygon after it has been rasterized.
|
||||||
|
*
|
||||||
|
* If the high bit of the high byte of X0 is set, we
|
||||||
|
* go into "repeat" mode, where we just repeat the
|
||||||
|
* previous line. This saves about 40 cycles of
|
||||||
|
* overhead per line when drawing rectangles, plus
|
||||||
|
* what we would have to spend to populate multiple
|
||||||
|
* lines of the raster table. It only increases the
|
||||||
|
* general per-line cost by 3 cycles.
|
||||||
|
*
|
||||||
|
* We could use the "repeat" flag to use this code to
|
||||||
|
* draw vertical lines, though that's mostly of value
|
||||||
|
* to an external caller who knows ahead of time that
|
||||||
|
* the line is vertical. The DrawLine code is pretty
|
||||||
|
* good with vertical lines, and adding additional
|
||||||
|
* setup time to every vertical-dominant line to
|
||||||
|
* decide if it should call here seems like a
|
||||||
|
* losing proposition.
|
||||||
|
|
||||||
|
]hbasl equ zptr0
|
||||||
|
]hbash equ zptr0+1
|
||||||
|
]lftbyte equ zloc0
|
||||||
|
]lftbit equ zloc1
|
||||||
|
]rgtbyte equ zloc2
|
||||||
|
]rgtbit equ zloc3
|
||||||
|
]line equ zloc4
|
||||||
|
]andmask equ zloc5
|
||||||
|
]cur_line equ zloc6
|
||||||
|
]repting equ zloc7
|
||||||
|
|
||||||
|
ldx g_color ;configure color XOR byte
|
||||||
|
lda xormask,x
|
||||||
|
do USE_FAST ;*****
|
||||||
|
cmp rast_unroll+3 ;already configured?
|
||||||
|
beq :goodmask
|
||||||
|
jsr fixrastxor
|
||||||
|
:goodmask
|
||||||
|
else
|
||||||
|
sta _xorcolor+1
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
lda #$00
|
||||||
|
sta ]repting
|
||||||
|
|
||||||
|
ldy rast_top
|
||||||
|
|
||||||
|
* Main rasterization loop. Y holds the line number.
|
||||||
|
rastloop
|
||||||
|
sty ]cur_line ;3
|
||||||
|
ldx ylooklo,y ;4
|
||||||
|
stx ]hbasl ;3
|
||||||
|
lda ylookhi,y ;4
|
||||||
|
_pg_or1 ora #$20 ;2 will be $20 or $40
|
||||||
|
sta ]hbash ;3 = 19 cycles
|
||||||
|
do USE_FAST-1 ;***** i.e. not USE_FAST
|
||||||
|
stx _wrhires+1
|
||||||
|
sta _wrhires+2
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
* divide left edge by 7
|
||||||
|
ldx rastx0l,y ;4 line num in Y
|
||||||
|
lda rastx0h,y ;4
|
||||||
|
bpl :noflag ;2
|
||||||
|
sta rastx0h+1,y ;4 propagate
|
||||||
|
lda ]repting ;3 first time through?
|
||||||
|
beq :firstre ;2 yup, finish calculations
|
||||||
|
lda ]rgtbyte ;3 need this in A
|
||||||
|
bpl :repeat ;3 always
|
||||||
|
:firstre lda rastx0h,y ;reload
|
||||||
|
sta ]repting ;any nonzero will do
|
||||||
|
and #$7f ;strip repeat flag
|
||||||
|
:noflag beq :lotabl
|
||||||
|
lda mod7hi,x
|
||||||
|
sta ]lftbit
|
||||||
|
lda div7hi,x
|
||||||
|
sta ]lftbyte
|
||||||
|
bpl :gotlft ;always
|
||||||
|
BREAK ;debug
|
||||||
|
:lotabl lda mod7lo,x
|
||||||
|
sta ]lftbit
|
||||||
|
lda div7lo,x
|
||||||
|
sta ]lftbyte
|
||||||
|
:gotlft
|
||||||
|
|
||||||
|
* divide right edge by 7
|
||||||
|
ldx rastx1l,y ;4 line num in Y
|
||||||
|
lda rastx1h,y ;4
|
||||||
|
beq :lotabr ;3
|
||||||
|
lda mod7hi,x
|
||||||
|
sta ]rgtbit
|
||||||
|
lda div7hi,x
|
||||||
|
sta ]rgtbyte
|
||||||
|
bpl :gotrgt ;always
|
||||||
|
BREAK ;debug
|
||||||
|
:lotabr lda mod7lo,x ;4
|
||||||
|
sta ]rgtbit ;3
|
||||||
|
lda div7lo,x ;4
|
||||||
|
sta ]rgtbyte ;3 = 25 for X1 < 256
|
||||||
|
:gotrgt
|
||||||
|
|
||||||
|
:repeat
|
||||||
|
cmp ]lftbyte ;3
|
||||||
|
bne :not1byte ;3
|
||||||
|
|
||||||
|
* The left and right edges are in the same byte. We
|
||||||
|
* need to set up the mask differently, so we deal with
|
||||||
|
* it as a special case.
|
||||||
|
ldy ]lftbit
|
||||||
|
lda leftmask,y ;create the AND mask
|
||||||
|
ldx ]rgtbit
|
||||||
|
and rightmask,x ;strip out bits on right
|
||||||
|
sta ]andmask
|
||||||
|
|
||||||
|
ldy ]lftbyte
|
||||||
|
lda colorline,y ;get color bits
|
||||||
|
eor (]hbasl),y ;combine w/screen
|
||||||
|
and ]andmask ;remove not-ours
|
||||||
|
eor (]hbasl),y ;combine again
|
||||||
|
sta (]hbasl),y
|
||||||
|
jmp rastlinedone
|
||||||
|
|
||||||
|
* This is the more general case. We special-case the
|
||||||
|
* left and right edges, then byte-stomp the middle.
|
||||||
|
* On entry, ]rgtbyte is in A
|
||||||
|
:not1byte
|
||||||
|
sec ;2 compute number of full
|
||||||
|
sbc ]lftbyte ;3 and partial bytes to
|
||||||
|
tax ;2 draw
|
||||||
|
inx ;2
|
||||||
|
|
||||||
|
ldy ]rgtbit ;3
|
||||||
|
cpy #6 ;2
|
||||||
|
beq :rgtnospcl ;3
|
||||||
|
lda rightmask,y ;handle partial-byte right
|
||||||
|
sta ]andmask
|
||||||
|
ldy ]rgtbyte
|
||||||
|
lda colorline,y
|
||||||
|
eor (]hbasl),y
|
||||||
|
and ]andmask
|
||||||
|
eor (]hbasl),y
|
||||||
|
sta (]hbasl),y
|
||||||
|
dex ;adjust count
|
||||||
|
:rgtnospcl
|
||||||
|
|
||||||
|
ldy ]lftbit ;3 check left for partial
|
||||||
|
beq :lftnospcl ;3
|
||||||
|
lda leftmask,y ;handle partial-byte left
|
||||||
|
sta ]andmask
|
||||||
|
ldy ]lftbyte
|
||||||
|
lda colorline,y
|
||||||
|
eor (]hbasl),y
|
||||||
|
and ]andmask
|
||||||
|
eor (]hbasl),y
|
||||||
|
sta (]hbasl),y
|
||||||
|
dex ;adjust count
|
||||||
|
beq rastlinedone ;bail if all done
|
||||||
|
iny ;advance start position
|
||||||
|
bne :liny ;always
|
||||||
|
BREAK
|
||||||
|
:lftnospcl
|
||||||
|
|
||||||
|
ldy ]lftbyte ;3
|
||||||
|
:liny
|
||||||
|
|
||||||
|
do USE_FAST ;***** "fast" loop
|
||||||
|
* Instead of looping, jump into an unrolled loop.
|
||||||
|
* Cost is 10 cycles per byte with an extra 14 cycles
|
||||||
|
* of overhead, so we start to win at 4 bytes.
|
||||||
|
lda rastunidx,x ;4
|
||||||
|
sta :_rastun+1 ;4
|
||||||
|
lda colorline,y ;4 get odd/even color val
|
||||||
|
:_rastun jmp rast_unroll ;3
|
||||||
|
|
||||||
|
else ;***** "slow" loop
|
||||||
|
* Inner loop of the renderer. This runs 0-40x.
|
||||||
|
* Cost is 14 cycles/byte.
|
||||||
|
lda colorline,y ;get appropriate odd/even val
|
||||||
|
_wrhires sta $2000,y ;5 replaced with line addr
|
||||||
|
_xorcolor eor #$00 ;2 replaced with $00/$7f
|
||||||
|
iny ;2
|
||||||
|
dex ;2
|
||||||
|
bne _wrhires ;3
|
||||||
|
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
rastlinedone
|
||||||
|
ldy ]cur_line ;3 more lines to go?
|
||||||
|
cpy rast_bottom ;4
|
||||||
|
bge :done ;2
|
||||||
|
iny ;2
|
||||||
|
jmp rastloop ;3 must have line in Y
|
||||||
|
|
||||||
|
:done rts
|
||||||
|
|
||||||
|
fixrastxor
|
||||||
|
do USE_FAST ;*****
|
||||||
|
* Update the EOR statements in the unrolled rastfill code.
|
||||||
|
* Doing this with a loop takes ~600 cycles, doing it with
|
||||||
|
* unrolled stores takes 160. We only do this when we
|
||||||
|
* need to, so changing the color from green to blue won't
|
||||||
|
* cause this to run.
|
||||||
|
*
|
||||||
|
* Call with the XOR value in A.
|
||||||
|
]offset = 0
|
||||||
|
lup BYTES_PER_ROW
|
||||||
|
sta rast_unroll+3+]offset
|
||||||
|
]offset = ]offset+5
|
||||||
|
--^
|
||||||
|
BEEP
|
||||||
|
rts
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
|
||||||
|
* include the line functions
|
||||||
|
put FDRAW.LINE
|
||||||
|
|
||||||
|
* include the circle functions
|
||||||
|
put FDRAW.CIRCLE
|
||||||
|
|
||||||
|
lst on
|
||||||
|
CODE_END equ * ;end of code section
|
||||||
|
lst off
|
||||||
|
|
||||||
|
* include the data tables
|
||||||
|
put FDRAW.TABLES
|
||||||
|
|
||||||
|
lst on
|
||||||
|
DAT_END equ * ;end of data / BSS
|
||||||
|
lst off
|
||||||
|
|
||||||
|
* Save the appropriate object file.
|
||||||
|
do USE_FAST
|
||||||
|
sav FDRAW.FAST
|
||||||
|
else
|
||||||
|
sav FDRAW.SMALL
|
||||||
|
fin
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,341 @@
|
||||||
|
********************************
|
||||||
|
* *
|
||||||
|
* Fast Apple II Graphics *
|
||||||
|
* By Andy McFadden *
|
||||||
|
* Version 0.3, Aug 2015 *
|
||||||
|
* *
|
||||||
|
* Pre-computed data and *
|
||||||
|
* large internal buffers. *
|
||||||
|
* (Included by FDRAW.S) *
|
||||||
|
* *
|
||||||
|
* Developed with Merlin-16 *
|
||||||
|
* *
|
||||||
|
********************************
|
||||||
|
|
||||||
|
* Expected layout with alignment:
|
||||||
|
*
|
||||||
|
* P1 ylooklo, misc tables
|
||||||
|
* P2 ylookhi, colorline
|
||||||
|
* P3 rastx0l
|
||||||
|
* P4 rastx0h
|
||||||
|
* P5 rastx1l
|
||||||
|
* P6 rastx1h, div7hi, mod7hi
|
||||||
|
* P7 div7lo
|
||||||
|
* P8 mod7lo
|
||||||
|
* P9 rast_unroll, rastunidx
|
||||||
|
*
|
||||||
|
* Tables should be just under $900 bytes.
|
||||||
|
|
||||||
|
PG_ALIGN
|
||||||
|
|
||||||
|
* Hi-res Y lookup, low part (192 bytes).
|
||||||
|
ylooklo HEX 0000000000000000
|
||||||
|
HEX 8080808080808080
|
||||||
|
HEX 0000000000000000
|
||||||
|
HEX 8080808080808080
|
||||||
|
HEX 0000000000000000
|
||||||
|
HEX 8080808080808080
|
||||||
|
HEX 0000000000000000
|
||||||
|
HEX 8080808080808080
|
||||||
|
HEX 2828282828282828
|
||||||
|
HEX a8a8a8a8a8a8a8a8
|
||||||
|
HEX 2828282828282828
|
||||||
|
HEX a8a8a8a8a8a8a8a8
|
||||||
|
HEX 2828282828282828
|
||||||
|
HEX a8a8a8a8a8a8a8a8
|
||||||
|
HEX 2828282828282828
|
||||||
|
HEX a8a8a8a8a8a8a8a8
|
||||||
|
HEX 5050505050505050
|
||||||
|
HEX d0d0d0d0d0d0d0d0
|
||||||
|
HEX 5050505050505050
|
||||||
|
HEX d0d0d0d0d0d0d0d0
|
||||||
|
HEX 5050505050505050
|
||||||
|
HEX d0d0d0d0d0d0d0d0
|
||||||
|
HEX 5050505050505050
|
||||||
|
HEX d0d0d0d0d0d0d0d0
|
||||||
|
|
||||||
|
* Color masks for odd/even bytes, colors 0-7.
|
||||||
|
evencolor dfb $00,$2a,$55,$7f,$80,$aa,$d5,$ff
|
||||||
|
oddcolor dfb $00,$55,$2a,$7f,$80,$d5,$aa,$ff
|
||||||
|
|
||||||
|
* XOR mask for colors 0-7 - non-BW flip on odd/even.
|
||||||
|
xormask dfb $00,$7f,$7f,$00,$00,$7f,$7f,$00
|
||||||
|
|
||||||
|
* AND mask for the 7 pixel positions, high bit set
|
||||||
|
* for the color shift.
|
||||||
|
andmask dfb $81,$82,$84,$88,$90,$a0,$c0
|
||||||
|
|
||||||
|
* These are pixel AND masks, used with the modulo 7
|
||||||
|
* result. Entry #2 in leftmask means we're touching
|
||||||
|
* the rightmost 5 pixels, and entry #2 in rightmask
|
||||||
|
* means we're touching the 3 leftmost pixels.
|
||||||
|
*
|
||||||
|
* The high bit is always set, because we want to
|
||||||
|
* keep the color's high bit.
|
||||||
|
leftmask dfb $ff,$fe,$fc,$f8,$f0,$e0,$c0
|
||||||
|
rightmask dfb $81,$83,$87,$8f,$9f,$bf,$ff
|
||||||
|
|
||||||
|
PG_ALIGN
|
||||||
|
|
||||||
|
* Hi-res Y lookup, high part (192 bytes).
|
||||||
|
* OR with $20 or $40.
|
||||||
|
ylookhi HEX 0004080c1014181c
|
||||||
|
HEX 0004080c1014181c
|
||||||
|
HEX 0105090d1115191d
|
||||||
|
HEX 0105090d1115191d
|
||||||
|
HEX 02060a0e12161a1e
|
||||||
|
HEX 02060a0e12161a1e
|
||||||
|
HEX 03070b0f13171b1f
|
||||||
|
HEX 03070b0f13171b1f
|
||||||
|
HEX 0004080c1014181c
|
||||||
|
HEX 0004080c1014181c
|
||||||
|
HEX 0105090d1115191d
|
||||||
|
HEX 0105090d1115191d
|
||||||
|
HEX 02060a0e12161a1e
|
||||||
|
HEX 02060a0e12161a1e
|
||||||
|
HEX 03070b0f13171b1f
|
||||||
|
HEX 03070b0f13171b1f
|
||||||
|
HEX 0004080c1014181c
|
||||||
|
HEX 0004080c1014181c
|
||||||
|
HEX 0105090d1115191d
|
||||||
|
HEX 0105090d1115191d
|
||||||
|
HEX 02060a0e12161a1e
|
||||||
|
HEX 02060a0e12161a1e
|
||||||
|
HEX 03070b0f13171b1f
|
||||||
|
HEX 03070b0f13171b1f
|
||||||
|
|
||||||
|
* Masks for current color (even/odd), e.g. 55 2a 55 2a ...
|
||||||
|
* Updated whenever the color changes.
|
||||||
|
colorline ds 40
|
||||||
|
|
||||||
|
PG_ALIGN
|
||||||
|
rastx0l ds NUM_ROWS
|
||||||
|
PG_ALIGN
|
||||||
|
rastx0h ds NUM_ROWS
|
||||||
|
ds 1 ;repeat mode can overstep
|
||||||
|
PG_ALIGN
|
||||||
|
rastx1l ds NUM_ROWS
|
||||||
|
PG_ALIGN
|
||||||
|
rastx1h ds NUM_ROWS
|
||||||
|
|
||||||
|
* Lookup tables for dividing 0-279 by 7. The "hi"
|
||||||
|
* parts are 24 bytes each, so they fit inside
|
||||||
|
* the previous 192-byte entry. The "lo" parts
|
||||||
|
* each fill a page.
|
||||||
|
div7hi HEX 2424242525252525
|
||||||
|
HEX 2525262626262626
|
||||||
|
HEX 2627272727272727
|
||||||
|
mod7hi HEX 0405060001020304
|
||||||
|
HEX 0506000102030405
|
||||||
|
HEX 0600010203040506
|
||||||
|
|
||||||
|
PG_ALIGN
|
||||||
|
|
||||||
|
div7lo HEX 0000000000000001
|
||||||
|
HEX 0101010101010202
|
||||||
|
HEX 0202020202030303
|
||||||
|
HEX 0303030304040404
|
||||||
|
HEX 0404040505050505
|
||||||
|
HEX 0505060606060606
|
||||||
|
HEX 0607070707070707
|
||||||
|
HEX 0808080808080809
|
||||||
|
HEX 0909090909090a0a
|
||||||
|
HEX 0a0a0a0a0a0b0b0b
|
||||||
|
HEX 0b0b0b0b0c0c0c0c
|
||||||
|
HEX 0c0c0c0d0d0d0d0d
|
||||||
|
HEX 0d0d0e0e0e0e0e0e
|
||||||
|
HEX 0e0f0f0f0f0f0f0f
|
||||||
|
HEX 1010101010101011
|
||||||
|
HEX 1111111111111212
|
||||||
|
HEX 1212121212131313
|
||||||
|
HEX 1313131314141414
|
||||||
|
HEX 1414141515151515
|
||||||
|
HEX 1515161616161616
|
||||||
|
HEX 1617171717171717
|
||||||
|
HEX 1818181818181819
|
||||||
|
HEX 1919191919191a1a
|
||||||
|
HEX 1a1a1a1a1a1b1b1b
|
||||||
|
HEX 1b1b1b1b1c1c1c1c
|
||||||
|
HEX 1c1c1c1d1d1d1d1d
|
||||||
|
HEX 1d1d1e1e1e1e1e1e
|
||||||
|
HEX 1e1f1f1f1f1f1f1f
|
||||||
|
HEX 2020202020202021
|
||||||
|
HEX 2121212121212222
|
||||||
|
HEX 2222222222232323
|
||||||
|
HEX 2323232324242424
|
||||||
|
mod7lo HEX 0001020304050600
|
||||||
|
HEX 0102030405060001
|
||||||
|
HEX 0203040506000102
|
||||||
|
HEX 0304050600010203
|
||||||
|
HEX 0405060001020304
|
||||||
|
HEX 0506000102030405
|
||||||
|
HEX 0600010203040506
|
||||||
|
HEX 0001020304050600
|
||||||
|
HEX 0102030405060001
|
||||||
|
HEX 0203040506000102
|
||||||
|
HEX 0304050600010203
|
||||||
|
HEX 0405060001020304
|
||||||
|
HEX 0506000102030405
|
||||||
|
HEX 0600010203040506
|
||||||
|
HEX 0001020304050600
|
||||||
|
HEX 0102030405060001
|
||||||
|
HEX 0203040506000102
|
||||||
|
HEX 0304050600010203
|
||||||
|
HEX 0405060001020304
|
||||||
|
HEX 0506000102030405
|
||||||
|
HEX 0600010203040506
|
||||||
|
HEX 0001020304050600
|
||||||
|
HEX 0102030405060001
|
||||||
|
HEX 0203040506000102
|
||||||
|
HEX 0304050600010203
|
||||||
|
HEX 0405060001020304
|
||||||
|
HEX 0506000102030405
|
||||||
|
HEX 0600010203040506
|
||||||
|
HEX 0001020304050600
|
||||||
|
HEX 0102030405060001
|
||||||
|
HEX 0203040506000102
|
||||||
|
HEX 0304050600010203
|
||||||
|
|
||||||
|
|
||||||
|
* RastFill unrolled loop. At each step we store the current
|
||||||
|
* color value, XOR it to flip the bits if needed, and advance.
|
||||||
|
* The caller needs to set the appropriate initial value based
|
||||||
|
* on whether the address is odd or even.
|
||||||
|
*
|
||||||
|
* We can use a 3-cycle "EOR dp" or a 2-cycle "EOR imm". The
|
||||||
|
* former is one cycle slower, the latter requires us to
|
||||||
|
* self-mod 40 instructions when the color changes.
|
||||||
|
*
|
||||||
|
* This must be page-aligned so that we can take the value
|
||||||
|
* from the rastunidx table and self-mod a JMP without having
|
||||||
|
* to do a 16-bit add. We have just enough room for the
|
||||||
|
* unrolled loop (40*5+3) and x5 table (41) = 244 bytes, fits
|
||||||
|
* on a single page.
|
||||||
|
|
||||||
|
do USE_FAST ;*****
|
||||||
|
ds \
|
||||||
|
]hbasl equ zptr0 ;must match FillRaster
|
||||||
|
rast_unroll equ *
|
||||||
|
lst off
|
||||||
|
lup BYTES_PER_ROW
|
||||||
|
sta (]hbasl),y ;6
|
||||||
|
eor #$00 ;2
|
||||||
|
iny ;2 10 cycles, 5 bytes
|
||||||
|
--^
|
||||||
|
jmp rastlinedone
|
||||||
|
|
||||||
|
* Index into rast_unroll. If we need to output N bytes,
|
||||||
|
* we want to jump to (rast_unroll + (40 - N) * 5) (where
|
||||||
|
* 5 is the number of bytes per iteration).
|
||||||
|
rastunidx
|
||||||
|
]offset = BYTES_PER_ROW*5
|
||||||
|
lup BYTES_PER_ROW+1 ;0-40
|
||||||
|
dfb ]offset
|
||||||
|
]offset = ]offset-5
|
||||||
|
--^
|
||||||
|
|
||||||
|
fin ;*****
|
||||||
|
|
||||||
|
|
||||||
|
********************************
|
||||||
|
*
|
||||||
|
* Code used to generate tables above. If you want to
|
||||||
|
* decrease load size, use these functions to generate
|
||||||
|
* the data into empty memory, then discard the code.
|
||||||
|
* (Maybe use a negative DS and overlap with rastx0l?)
|
||||||
|
*
|
||||||
|
********************************
|
||||||
|
DO 0 ;*****
|
||||||
|
|
||||||
|
init_ylook
|
||||||
|
]hbasl equ zptr1
|
||||||
|
]hbash equ zptr1+1
|
||||||
|
|
||||||
|
* Initialize Y-lookup table. We just call the bascalc
|
||||||
|
* function.
|
||||||
|
ldx #NUM_ROWS
|
||||||
|
ldy #NUM_ROWS-1
|
||||||
|
]loop tya
|
||||||
|
jsr bascalc
|
||||||
|
lda hbasl
|
||||||
|
sta ylooklo,y
|
||||||
|
lda hbash
|
||||||
|
ora #$20 ;remove for $0000 base
|
||||||
|
sta ylookhi,y
|
||||||
|
dey
|
||||||
|
dex
|
||||||
|
bne ]loop
|
||||||
|
rts
|
||||||
|
|
||||||
|
* Hi-res base address calculation. This is based on the
|
||||||
|
* HPOSN routine at $F411.
|
||||||
|
*
|
||||||
|
* Call with the line in A. The results are placed into
|
||||||
|
* zptr1. X and Y are not disturbed.
|
||||||
|
*
|
||||||
|
* The value is in the $0000-1fff range, so you must OR
|
||||||
|
* the desired hi-res page in.
|
||||||
|
*
|
||||||
|
bascalc
|
||||||
|
pha
|
||||||
|
and #$c0
|
||||||
|
sta ]hbasl
|
||||||
|
lsr
|
||||||
|
lsr
|
||||||
|
ora ]hbasl
|
||||||
|
sta ]hbasl
|
||||||
|
pla
|
||||||
|
sta ]hbash
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
asl
|
||||||
|
rol ]hbash
|
||||||
|
asl
|
||||||
|
rol ]hbash
|
||||||
|
asl
|
||||||
|
ror ]hbasl
|
||||||
|
lda ]hbash
|
||||||
|
and #$1f
|
||||||
|
sta ]hbash
|
||||||
|
rts
|
||||||
|
|
||||||
|
*
|
||||||
|
* Create divide-by-7 tables.
|
||||||
|
*
|
||||||
|
mkdivtab
|
||||||
|
]val equ zloc0
|
||||||
|
|
||||||
|
ldy #0
|
||||||
|
sty ]val
|
||||||
|
ldx #0
|
||||||
|
]loop lda ]val
|
||||||
|
sta div7lo,y
|
||||||
|
txa
|
||||||
|
sta mod7lo,y
|
||||||
|
inx
|
||||||
|
iny
|
||||||
|
beq :lodone
|
||||||
|
cpx #7
|
||||||
|
bne ]loop
|
||||||
|
inc ]val
|
||||||
|
ldx #0
|
||||||
|
beq ]loop ;always
|
||||||
|
:lodone ;safe to ignore ]va update
|
||||||
|
]loop lda ]val
|
||||||
|
sta div7hi,y
|
||||||
|
txa
|
||||||
|
sta mod7hi,y
|
||||||
|
iny
|
||||||
|
cpy #280-256
|
||||||
|
beq :hidone
|
||||||
|
inx
|
||||||
|
cpx #7
|
||||||
|
bne ]loop
|
||||||
|
inc ]val
|
||||||
|
ldx #0
|
||||||
|
beq ]loop ;always
|
||||||
|
:hidone rts
|
||||||
|
|
||||||
|
FIN ;*****
|
||||||
|
|
||||||
|
|
|
@ -63,4 +63,6 @@ GEOFCMD EQU $D1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,8 @@ RESET TSX
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -141,10 +141,12 @@ LOADCODE PHP ; Save carry flag
|
||||||
JSR CROUT
|
JSR CROUT
|
||||||
PLP
|
PLP
|
||||||
RTS
|
RTS
|
||||||
:ADDRL DB $00 ; Destination address (LSB)
|
:ADDRL DB $00 ; Destination address (LSB)
|
||||||
:ADDRH DB $00 ; Destination address (MSB)
|
:ADDRH DB $00 ; Destination address (MSB)
|
||||||
:BLOCKS DB $00 ; Counter for blocks read
|
:BLOCKS DB $00 ; Counter for blocks read
|
||||||
:LEN DB $00 ; Length of filename
|
:LEN DB $00 ; Length of filename
|
||||||
:CANTOPEN ASC "Unable to open "
|
:CANTOPEN ASC "Unable to open "
|
||||||
DB $00
|
DB $00
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -127,4 +127,6 @@ QUITPL HEX 04 ; Number of parameters
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -142,6 +142,8 @@ ROM8 STR "USERROM2.ROM"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -211,6 +211,8 @@ FILEREFS DB $00,$00,$00,$00
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -308,4 +308,6 @@ PREFIX DS 65 ; Buffer for ProDOS prefix
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1061,16 +1061,16 @@ MAINRDEXIT >>> XF2AUX,NULLRTS ; Back to an RTS
|
||||||
CLRHGR >>> ENTMAIN
|
CLRHGR >>> ENTMAIN
|
||||||
LDA BGCOLOR
|
LDA BGCOLOR
|
||||||
STA FDRAWADDR+5
|
STA FDRAWADDR+5
|
||||||
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
||||||
JSR FDRAWADDR+22 ; FDRAW: Clear
|
JSR FDRAWADDR+22 ; FDRAW: Clear
|
||||||
LDA FGCOLOR
|
LDA FGCOLOR
|
||||||
STA FDRAWADDR+5
|
STA FDRAWADDR+5
|
||||||
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
||||||
>>> XF2AUX,VDU16RET
|
>>> XF2AUX,VDU16RET
|
||||||
|
|
||||||
* Call FDraw SetLineMode routine
|
* Call FDraw SetLineMode routine
|
||||||
SETLINE >>> ENTMAIN
|
SETLINE >>> ENTMAIN
|
||||||
JSR FDRAWADDR+43 ; FDRAW: SetLineMode
|
JSR FDRAWADDR+43 ; FDRAW: SetLineMode
|
||||||
>>> XF2AUX,VDU18RET1
|
>>> XF2AUX,VDU18RET1
|
||||||
|
|
||||||
* Call FDraw DrawLine routine
|
* Call FDraw DrawLine routine
|
||||||
|
@ -1089,8 +1089,8 @@ DRAWLINE >>> ENTMAIN
|
||||||
BRA :SETCOLOR
|
BRA :SETCOLOR
|
||||||
:S2 LDA BGCOLOR ; Draw in background colour
|
:S2 LDA BGCOLOR ; Draw in background colour
|
||||||
:SETCOLOR STA FDRAWADDR+5
|
:SETCOLOR STA FDRAWADDR+5
|
||||||
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
||||||
JSR FDRAWADDR+28 ; FDRAW: DrawLine
|
JSR FDRAWADDR+28 ; FDRAW: DrawLine
|
||||||
>>> XF2AUX,VDU25RET
|
>>> XF2AUX,VDU25RET
|
||||||
|
|
||||||
* Call FDraw DrawPoint routine
|
* Call FDraw DrawPoint routine
|
||||||
|
@ -1109,24 +1109,24 @@ DRAWPNT >>> ENTMAIN
|
||||||
BRA :SETCOLOR
|
BRA :SETCOLOR
|
||||||
:S2 LDA BGCOLOR ; Draw in background colour
|
:S2 LDA BGCOLOR ; Draw in background colour
|
||||||
:SETCOLOR STA FDRAWADDR+5
|
:SETCOLOR STA FDRAWADDR+5
|
||||||
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
||||||
JSR FDRAWADDR+25 ; FDRAW: DrawPoint
|
JSR FDRAWADDR+25 ; FDRAW: DrawPoint
|
||||||
>>> XF2AUX,VDU25RET
|
>>> XF2AUX,VDU25RET
|
||||||
|
|
||||||
* Reset colours and linetype
|
* Reset colours and linetype
|
||||||
GFXINIT JSR FDRAWADDR+0 ; Initialize FDRAW library
|
GFXINIT JSR FDRAWADDR+0 ; Initialize FDRAW library
|
||||||
LDA #$20
|
LDA #$20
|
||||||
STA FDRAWADDR+5
|
STA FDRAWADDR+5
|
||||||
JSR FDRAWADDR+19 ; FDRAW: Set page $2000
|
JSR FDRAWADDR+19 ; FDRAW: Set page $2000
|
||||||
STZ LINETYPE
|
STZ LINETYPE
|
||||||
STZ FDRAWADDR+5
|
STZ FDRAWADDR+5
|
||||||
JSR FDRAWADDR+43 ; FDRAW: SetLineMode
|
JSR FDRAWADDR+43 ; FDRAW: SetLineMode
|
||||||
LDA #$07
|
LDA #$07
|
||||||
STA FGCOLOR
|
STA FGCOLOR
|
||||||
STA FDRAWADDR+5
|
STA FDRAWADDR+5
|
||||||
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
JSR FDRAWADDR+16 ; FDRAW: SetColor
|
||||||
STZ BGCOLOR
|
STZ BGCOLOR
|
||||||
JSR FDRAWADDR+22 ; FDRAW: clear HGR screen
|
JSR FDRAWADDR+22 ; FDRAW: clear HGR screen
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
FGCOLOR DB $00 ; Foreground colour
|
FGCOLOR DB $00 ; Foreground colour
|
||||||
|
@ -1136,3 +1136,5 @@ PLOTMODE DB $00 ; K value for PLOT K,X,Y
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -386,3 +386,5 @@ MATCHBUF DS 65 ; For storing match results (Pascal str)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
49
memmap.txt
49
memmap.txt
|
@ -1,4 +1,4 @@
|
||||||
* Memory layout in main memory
|
* Memory layout in main memory (Apple environment)
|
||||||
*
|
*
|
||||||
* ; $0000-$00FF Zero page
|
* ; $0000-$00FF Zero page
|
||||||
* ; $0100-$01FF Stack
|
* ; $0100-$01FF Stack
|
||||||
|
@ -40,27 +40,46 @@ MOSFILE2 EQU $0341 ; $0341 length
|
||||||
*
|
*
|
||||||
* EQU $0400 ; $0400- Can't use as ProDOS uses 'hidden' bytes
|
* EQU $0400 ; $0400- Can't use as ProDOS uses 'hidden' bytes
|
||||||
* ; -$07FF within screen for workspace
|
* ; -$07FF within screen for workspace
|
||||||
SCREEN EQU $0800 ; $0800-$0BFF half 80-col screen or 40-col screen
|
SCREEN EQU $0800 ; $0800-$0BFF Half 80-col screen or 40-col screen
|
||||||
IOBUF0 EQU $0C00 ; $0C00-$0FFF For loading ROM, OSFILE, *.
|
IOBUF0 EQU $0C00 ; $0C00-$0FFF For loading ROM, OSFILE, *.
|
||||||
IOBUF1 EQU $1000 ; $1000-$13FF Four open files for langs
|
IOBUF1 EQU $1000 ; $1000-$13FF Four open files for langs
|
||||||
IOBUF2 EQU $1400 ; $1400-$17FF
|
IOBUF2 EQU $1400 ; $1400-$17FF
|
||||||
IOBUF3 EQU $1800 ; $1800-$1BFF
|
IOBUF3 EQU $1800 ; $1800-$1BFF
|
||||||
IOBUF4 EQU $1C00 ; $1C00-$1FFF
|
IOBUF4 EQU $1C00 ; $1C00-$1FFF
|
||||||
* ; $2000- Code, to do: make code move itself
|
|
||||||
* -$4FFF
|
|
||||||
BLKBUF EQU $5000 ; $5000-$53FF 512-byte buffer plus channel data
|
|
||||||
BLKBUFEND EQU $5200
|
|
||||||
|
|
||||||
|
|
||||||
* To do later:
|
|
||||||
* ; $2000-$3FFF Hi-Res screen 1
|
* ; $2000-$3FFF Hi-Res screen 1
|
||||||
* ; $4000-$5FFF Hi-Res screen 2
|
* ; $4000- Code, to do: make code move itself
|
||||||
* ; $6000- available
|
* -$6FFF
|
||||||
* ; -$95FF available
|
BLKBUF EQU $7000 ; $7000-$73FF 512-byte buffer plus channel data
|
||||||
|
BLKBUFEND EQU $7200
|
||||||
|
*
|
||||||
* ; $9600-$BDFF ProDOS buffers
|
* ; $9600-$BDFF ProDOS buffers
|
||||||
* ; $BE00-$BEFF MLI Global workspace
|
* ; $BE00-$BEFF MLI Global workspace
|
||||||
* ; $BF00-$BFFF MLI API interface
|
* ; $BF00-$BFFF MLI API interface
|
||||||
|
|
||||||
I think $0300-$03DF can be usefully used as filing system workspace,
|
|
||||||
the mainmem copies of the filename and control block, MOSNAME and CBFILE,
|
Memory layout in aux memory (Acorn environment)
|
||||||
and later for OSGBPB.
|
* ; $0000-$00FF Zero page
|
||||||
|
* ; $00-$8F Language workspace
|
||||||
|
* ; $90-$9F Network workspace
|
||||||
|
* ; $A0-$A7 NMI workspace
|
||||||
|
* ; $A8-$AF Non-MOS *command workspace
|
||||||
|
* ; $B0-$BF Temporary filing system workspace
|
||||||
|
* ; $C0-$CF Persistant filing system workspace
|
||||||
|
* ; $D0-$DF VDU driver workspace
|
||||||
|
* ; $E0-$EE Internal MOS workspace
|
||||||
|
* ; $EF-$FF MOS API workspace
|
||||||
|
* ; $0100-$01FF Stack
|
||||||
|
* ; $0200-$02FF Kernel vectors and workspace
|
||||||
|
* ; $0200-$0235 Vectors
|
||||||
|
* ; $0236-$028F OSBYTE variables
|
||||||
|
* ; $0290-$02ED
|
||||||
|
* ; $02EE-$02FF MOS control block
|
||||||
|
* ; $0300-$03FF
|
||||||
|
* ; $0300-
|
||||||
|
* ; $03E0-$03EF XFER workspace
|
||||||
|
* ; $03F0-$03FF
|
||||||
|
* ; $0400-$07FF Language workspace
|
||||||
|
* ; $0800-$0BFF Screen memory
|
||||||
|
* ; $0C00-$0DFF --> use as transient command buffer
|
||||||
|
* ; $0E00 Default PAGE
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue