Prince-of-Persia-Apple-II/01 POP Source/Source/HIRES.S

2131 lines
26 KiB
ArmAsm
Executable File

* hires
org = $ee00
tr on
lst off
*-------------------------------
*
* PRINCE OF PERSIA
* Copyright 1989 Jordan Mechner
*
*-------------------------------
org org
jmp boot3
jmp cls
jmp lay
jmp fastlay
jmp layrsave
jmp lrcls
jmp fastmask
jmp fastblack
jmp peel
jmp getwidth
jmp copyscrnMM
jmp copyscrnAA
jmp SETFASTAUX
jmp SETFASTMAIN
jmp copyscrnMA
jmp copyscrnAM
jmp INVERTY
*-------------------------------
put hrparams
*-------------------------------
boot3 = $f880 ;stage 3 boot
peelbuf1 = $d000
peelbuf2 = $d600
* Local vars
locals = $f0
locals2 = $18
dum locals
BASE ds 2
IMSAVE ds 2
XSAVE ds 1
YSAVE ds 1
WIDTH ds 1
HEIGHT ds 1
TOPEDGE ds 1
OFFLEFT ds 1
OFFRIGHT ds 1
YREG ds 1
CARRY ds 1
dum locals2
index
ztemp
AMASK ds 1
BMASK ds 1
VISWIDTH ds 1
RMOST ds 1
carryim ds 1
imbyte ds 1
dend
* OPACITY codes
and = 0
ora = 1
sta = 2
eor = 3 ;OR/shift/XOR
mask = 4 ;mask/OR
*-------------------------------
*
* Assume hires routines are called from auxmem
* (Exit with RAMRD, RAMWRT, ALTZP on)
*
*-------------------------------
cls jsr mainmem
jsr CLS
jmp auxmem
lay jsr mainmem
jsr LAY
jmp auxmem
fastlay
jsr FASTLAY
jmp auxmem
layrsave jsr mainmem
jsr LAYRSAVE
jmp auxmem
lrcls jsr mainmem
jsr LRCLS
jmp auxmem
fastmask
jsr FASTMASK
jmp auxmem
fastblack jsr mainmem
jsr FASTBLACK
jmp auxmem
peel
jsr PEEL
jmp auxmem
getwidth jsr mainmem
jsr GETWIDTH
jmp auxmem
copyscrnMM
jsr mainmem ;r/w main
]copyscrn jsr COPYSCRN
jmp auxmem
copyscrnAA
jsr auxmem ;r/w aux
jmp ]copyscrn
copyscrnMA
sta $c002 ;read main
sta $c005 ;write aux
jmp ]copyscrn
copyscrnAM
sta $c003 ;read aux
sta $c004 ;write main
jmp ]copyscrn
*-------------------------------
mainmem sta $c004 ;RAMWRT off
sta $c002 ;RAMRD off
rts
auxmem sta $c005 ;RAMWRT on
sta $c003 ;RAMRD on
rts
*-------------------------------
*
* Parameters passed to hires routines:
*
* PAGE $00 = hires page 1, $20 = hires page 2
* XCO Screen X-coord (0=left, 39=right)
* YCO Screen Y-coord (0=top, 191=bottom)
* OFFSET # of bits to shift image right (0-6)
* IMAGE Image # in table (1-127)
* TABLE Starting address of image table (2 bytes)
* BANK Memory bank of table (2 = main, 3 = aux)
* OPACITY Bits 0-6:
* 0 AND
* 1 OR
* 2 STA
* 3 special XOR (OR/shift/XOR)
* 4 mask/OR
* Bit 7: 0 = normal, 1 = mirror
* LEFTCUT Left edge of usable screen area
* (0 for full screen)
* RIGHTCUT Right edge +1 of usable screen area
* (40 for full screen)
* TOPCUT Top edge of usable screen area
* (0 for full screen)
* BOTCUT Bottom edge +1 of usable screen area
* (192 for full screen)
*
*-------------------------------
*
* Image table format:
*
* Byte 0: width (# of bytes)
* Byte 1: height (# of lines)
* Byte 2-n: image bytes (read left-right, top-bottom)
*
*-------------------------------
*
* To preserve the background behind an animated character,
* call LAYERSAVE before LAYing down each character image.
* Afterwards, call PEEL to "peel off" the character &
* restore the original background.
*
* Peel buffer stores background images sequentially, in
* normal image table format, & is cleared after every frame.
*
*-------------------------------
*
* C L S
*
* Clear hi-res screen to black2
*
*-------------------------------
CLS lda PAGE ;00 = page 1; 20 = page 2
clc
adc #$20
sta :loop+2
adc #$10
sta :smod+2
lda #$80 ;black2
ldx #$10
ldy #0
:loop sta $2000,y
:smod sta $3000,y
iny
bne :loop
inc :loop+2
inc :smod+2
dex
bne :loop
rts
*-------------------------------
*
* L O - R E S C L S
*
* Clear lo-res/text screen (page 1)
*
* In: A = color
*
*-------------------------------
LRCLS LDY #$F7
:2 STA $400,Y
STA $500,Y
STA $600,Y
STA $700,Y
DEY
CPY #$7F
BNE :3
LDY #$77
:3 CPY #$FF
BNE :2
RTS
*-------------------------------
*
* S E T I M A G E
*
* In: TABLE (2 bytes), IMAGE (image #)
* Out: IMAGE = image start address (2 bytes)
*
*-------------------------------
setimage lda IMAGE
asl
sec
sbc #1
tay
lda (TABLE),y
sta IMAGE
iny
lda (TABLE),y
sta IMAGE+1
rts
*-------------------------------
*
* G E T W I D T H
*
* In: BANK, TABLE, IMAGE
* Out: A = width, X = height
*
*-------------------------------
GETWIDTH
lda BANK
sta :RAMRD+1
:RAMRD sta $c003
jsr setimage
ldy #1
lda (IMAGE),y ;height
tax
dey
lda (IMAGE),y ;width
rts
*-------------------------------
*
* P R E P R E P
*
* In: IMAGE, XCO, YCO
*
*-------------------------------
PREPREP
* Save IMAGE, XCO, YCO
LDA IMAGE
STA IMSAVE
LDA XCO
STA XSAVE
LDA YCO
STA YSAVE
* Get image data start address
lda BANK
sta :RAMRD+1
:RAMRD sta $c003
jsr setimage
* Read first two bytes (width, height) of image table
LDY #0
LDA (IMAGE),Y
STA WIDTH
INY
LDA (IMAGE),Y
STA HEIGHT
LDA IMAGE
CLC
ADC #2
STA IMAGE
BCC :3
INC IMAGE+1
:3 sta $c002 ;RAMRD off (read mainmem)
]rts rts
*-------------------------------
*
* C R O P
*
* In: Results of PREPREP (XCO, YCO, HEIGHT, WIDTH)
* Screen area cutoffs (LEFTCUT, RIGHTCUT, TOPCUT, BOTCUT)
*
* Out:
*
* TOPEDGE Top line -1
* VISWIDTH Width, in bytes, of visible (onscreen) portion
* of image
* XCO X-coord of leftmost visible byte of image
* (must be 0-39)
* YCO Y-coord of lowest visible line of image
* (must be 0-191)
* OFFLEFT # of bytes off left edge
* OFFRIGHT # of bytes off right edge (including carry byte)
* RMOST # of bytes off right edge (excluding carry byte)
*
* Return - if entire image is offscreen, else +
*
*-------------------------------
CROP
* (1) Crop top & bottom
lda YCO
cmp BOTCUT
bcs :botoff ;Bottom o.s.
* Bottom is onscreen--check top
sec
sbc HEIGHT ;top line -1
cmp #191
bcc :topok ;Top is onscreen
lda TOPCUT ;Top is offscreen
sec
sbc #1
sta TOPEDGE
jmp :done
:topok sta TOPEDGE ;Top line -1 (0-191)
lda TOPCUT ;top line of image area (forced mask)
beq :done ;no top cutoff
sec
sbc #1
cmp TOPEDGE
bcc :done
sta TOPEDGE
bcs :done
* Bottom is o.s.--advance IMAGE pointer past o.s. portion
:botoff ;A = YCO
sec
sbc HEIGHT
clc
adc #1 ;top line
cmp BOTCUT
bcs :cancel ;Entire shape is o.s.
sec
sbc #1
sta TOPEDGE ;top line -1
ldx YCO
:loop
lda IMAGE
clc
adc WIDTH
sta IMAGE
bcc :1
inc IMAGE+1
:1
dex
cpx BOTCUT
bcs :loop
stx YCO
* (2) Crop sides
:done
lda XCO
bmi :leftoff
cmp LEFTCUT
bcs :leftok ;XCO >= LEFTCUT
* XCO < LEFTCUT: left edge is offscreen
:leftoff
lda LEFTCUT
sec
sbc XCO
sta OFFLEFT ;Width of o.s. portion
lda WIDTH
sec
sbc OFFLEFT
bmi :cancel ;Entire image is o.s. -- skip it
sta VISWIDTH ;Width of onscreen portion (can be 0)
lda LEFTCUT
sta XCO
* Assume image is <=40 bytes wide --> right edge is onscreen
lda #0
sta OFFRIGHT
sta RMOST
rts
* Left edge is onscreen; what about right edge?
:leftok ;A = XCO
cmp RIGHTCUT ;normally 40
bcs :cancel ;Entire image is o.s. - skip it
clc
adc WIDTH ;rightmost byte +1
cmp RIGHTCUT
bcc :bothok ;Entire image is onscreen
sec
sbc RIGHTCUT
sta RMOST ;Width of o.s. portion
clc
adc #1
sta OFFRIGHT ;+1
lda RIGHTCUT
sec
sbc XCO
sta VISWIDTH ;Width of onscreen portion
lda #0
sta OFFLEFT
rts
:bothok lda WIDTH
sta VISWIDTH
lda #0
sta OFFLEFT
sta OFFRIGHT
sta RMOST
rts
:cancel lda #-1 ;Entire image is o.s. - skip it
]rts rts
*-------------------------------
*
* Shift offset 1 bit right or left
* (for special XOR)
*
* In/out: X = offset
*
*-------------------------------
shiftoffset
cpx #6
bcs :left
inx
rts
:left dex
]rts rts
*-------------------------------
*
* L A Y E R S A V E
*
* In: Same as for LAY, plus PEELBUF (2 bytes)
* Out: PEELBUF (updated), PEELIMG (2 bytes), PEELXCO, PEELYCO
*
* PEELIMG is 2-byte pointer to beginning of image table.
* (Hi byte = 0 means no image has been stored.)
*
* PEELBUF is 2-byte pointer to first available byte in
* peel buffer.
*
*-------------------------------
LAYRSAVE
jsr PREPREP
lda OPACITY
bpl :normal
LDA XCO
SEC
SBC WIDTH
STA XCO
:normal
inc WIDTH ;extra byte to cover shift right
jsr CROP
bmi SKIPIT
lda PEELBUF ;PEELBUF: 2-byte pointer to 1st
sta PEELIMG ;available byte in peel buffer
lda PEELBUF+1
sta PEELIMG+1
lda XCO
sta PEELXCO
sta :smXCO+1
lda YCO
sta PEELYCO
lda PAGE ;spend 7 cycles now --
sta :smPAGE+1 ;save 1 in loop
ldy #0
lda VISWIDTH
beq SKIPIT
sta (PEELBUF),y
sta :smWIDTH+1
sec
sbc #1
sta :smSTART+1
* Continue
:cont iny
LDA YCO
SEC
SBC TOPEDGE
STA (PEELBUF),y ;Height of onscreen portion ("VISHEIGHT")
LDA PEELBUF
CLC
ADC #2
STA PEELBUF
BCC :ok
INC PEELBUF+1
:ok
* Like FASTLAY in reverse
ldx YCO
:loop LDA YLO,X
CLC
:smXCO ADC #0 ;XCO
STA :smBASE+1
LDA YHI,X
:smPAGE ADC #0 ;PAGE
STA :smBASE+2
:smSTART ldy #0 ;VISWIDTH-1
:inloop
:smBASE lda $2000,y
STA (PEELBUF),Y
dey
bpl :inloop
:smWIDTH LDA #0 ;VISWIDTH
ADC PEELBUF ;assume cc
STA PEELBUF
BCC :2
INC PEELBUF+1
:2
DEX
CPX TOPEDGE
BNE :loop
JMP DONE
SKIPIT lda #0
sta PEELIMG+1 ;signal that peelbuf is empty
JMP DONE
*-------------------------------
*
* L A Y
*
* General routine to lay down an image on hi-res screen
* (Handles edge-clipping, bit-shifting, & mirroring)
*
* Calls one of the following routines:
*
* LayGen General (OR, AND, STA)
* LayMask Mask & OR
* LayXOR Special XOR
*
* Transfers control to MLAY if image is to be mirrored
*
*-------------------------------
LAY
lda OPACITY
bpl :notmirr
and #$7f
sta OPACITY
jmp MLAY
:notmirr cmp #eor
bne :1
jmp LayXOR
:1 cmp #mask
bcc :2
jmp LayMask
:2 jmp LayGen
*-------------------------------
*
* General (AND/OR/STORE)
*
*-------------------------------
LayGen
jsr PREPREP
jsr CROP
bpl :cont
jmp DONE
:cont
lda BANK
sta :RAMRD1+1
sta :RAMRD2+1
LDX OFFSET
LDA SHIFTL,X
STA :91+1
LDA SHIFTH,X
STA :91+2
LDA CARRYL,X
STA :90+1
STA :92+1
LDA CARRYH,X
STA :90+2
STA :92+2
LDA AMASKS,X
STA :AMASK+1
LDA BMASKS,X
STA :BMASK+1
LDX OPACITY
LDA OPCODE,X
STA :80
STA :81
* Preparation completed -- Lay down shape
LDY YCO
:nextline
LDA YLO,Y
CLC
ADC XCO
STA BASE
LDA YHI,Y
ADC PAGE
STA BASE+1
LDY OFFLEFT
BEQ :2
* (a) Left edge of image is offscreen
* Take initial carry byte from image table
DEY
:RAMRD1 sta $c003 ;aux/main
lda (IMAGE),y
sta $c002 ;main
TAX
:90 LDA $FFFF,X ;CARRYn
STA CARRY
LDA IMAGE
CLC
ADC OFFLEFT
STA IMAGE
BCC :1
INC IMAGE+1
:1
LDY #0
LDA VISWIDTH
STA WIDTH
BNE :3
BEQ :4 ;Zero width
* (b) Left edge of image is onscreen
* Take initial carry byte from screen
:2 LDA (BASE),Y
:AMASK AND #0
STA CARRY
* Lay line down left-to-right fast as you can
:3
:RAMRD2 sta $c003 ;aux/main
lda (IMAGE),y
sta $c002 ;main
TAX
:91 LDA $FFFF,X ;SHIFTn
ORA CARRY ;Combine with carryover from previous byte
:80 STA (BASE),Y ;STA/ORA/AND/EOR depending on OPACITY
STA (BASE),Y
:92 LDA $FFFF,X ;CARRYn
STA CARRY ;Carry over to next byte
INY
CPY VISWIDTH
BCC :3
* Extra byte on right (carryover)
LDA OFFRIGHT
BNE :5 ;Rightmost byte is offscreen
:4 LDA (BASE),Y
:BMASK AND #0
ORA CARRY
:81 STA (BASE),Y
STA (BASE),Y
* Next line up
:5 LDA WIDTH
CLC
ADC IMAGE
STA IMAGE
BCC :6
INC IMAGE+1
:6 DEC YCO
LDY YCO
CPY TOPEDGE
BNE :nextline
* Restore parameters
DONE LDA IMSAVE
STA IMAGE
LDA XSAVE
STA XCO
LDA YSAVE
STA YCO
RTS
*-------------------------------
*
* Mask, then OR
*
*-------------------------------
]done jmp DONE
LayMask
ldx OPACITY ;4 = mask, 5 = visible mask
lda OPCODE,x ;4 = and, 5 = sta
sta :masksm1
sta :masksm2
jsr PREPREP
jsr CROP
bmi ]done
lda BANK
sta :RAMRD1+1
sta :RAMRD2+1
LDX OFFSET
LDA SHIFTL,X
STA :91+1
sta :93+1
LDA SHIFTH,X
STA :91+2
sta :93+2
LDA CARRYL,X
STA :90+1
STA :92+1
sta :94+1
sta :96+1
LDA CARRYH,X
STA :90+2
STA :92+2
sta :94+2
sta :96+2
LDA AMASKS,X
STA :AMASK+1
LDA BMASKS,X
STA :BMASK+1
LDY YCO
:nextline
LDA YLO,Y
CLC
ADC XCO
STA BASE
LDA YHI,Y
ADC PAGE
STA BASE+1
LDY OFFLEFT
BEQ :2
* (a) Left edge of image is offscreen
* Take initial carry byte from image table
dey
:RAMRD1 sta $c003
lda (IMAGE),y
; eor #$ff ;TEMP
; ora #$80 ;TEMP
sta $c002
tax
:96 lda $FFFF,x ;CARRYn
sta carryim
lda MASKTAB-$80,x
tax
:90 lda $FFFF,x ;CARRYn
sta CARRY
LDA IMAGE
CLC
ADC OFFLEFT
STA IMAGE
BCC :1
INC IMAGE+1
:1
ldy #0
LDA VISWIDTH
STA WIDTH
BNE :inloop
BEQ :4 ;Zero width
* (b) Left edge of image is onscreen
* Take initial carry byte from screen
:2
:AMASK lda #0 ;AMASK
sta CARRY
and (BASE),y
sta carryim
* Lay line down left-to-right fast as you can
:inloop
:RAMRD2 sta $c003
lda (IMAGE),y
; eor #$ff ;TEMP
; ora #$80 ;TEMP
sta $c002
tax
:93 lda $FFFF,x ;SHIFTn
ora carryim
sta imbyte ;shifted image byte
:94 lda $FFFF,x ;CARRYn
sta carryim
lda MASKTAB-$80,x
tax
:91 lda $FFFF,x ;SHIFTn
ora CARRY
:masksm1 and (BASE),y ;AND with mask byte
ora imbyte ;OR with original image byte
sta (BASE),y
:92 lda $FFFF,x ;CARRYn
sta CARRY ;Carry over to next byte
iny
cpy VISWIDTH
bcc :inloop
* Extra byte on right (carryover)
lda OFFRIGHT
bne :5 ;Rightmost byte is offscreen
:4
:BMASK lda #0 ;BMASK
ora CARRY
:masksm2 and (BASE),y
ora carryim
sta (BASE),y
* Next line up
:5 LDA WIDTH
CLC
ADC IMAGE
STA IMAGE
BCC :6
INC IMAGE+1
:6 DEC YCO
LDY YCO
CPY TOPEDGE
beq :done
jmp :nextline
:done jmp DONE
*-------------------------------
*
* Special XOR
*
* (OR, then shift 1 bit and XOR)
*
*-------------------------------
LayXOR
JSR PREPREP
jsr CROP
bpl :cont
jmp DONE
:cont
lda BANK
sta :RAMRD1+1
sta :RAMRD2+1
LDX OFFSET
LDA SHIFTL,X
STA :91+1
LDA SHIFTH,X
STA :91+2
LDA CARRYL,X
STA :90+1
STA :92+1
LDA CARRYH,X
STA :90+2
STA :92+2
jsr shiftoffset ;shift 1 bit right
lda SHIFTL,x
sta :s1+1
lda SHIFTH,x
sta :s1+2
lda CARRYL,x
sta :c1+1
sta :c2+1
lda CARRYH,x
sta :c1+2
sta :c2+2
LDA AMASKS,X
STA :AMASK+1
* Omit opcode setting
LDY YCO
:0 LDA YLO,Y
CLC
ADC XCO
STA BASE
LDA YHI,Y
ADC PAGE
STA BASE+1
LDY OFFLEFT
BEQ :2
* (a) Left edge offscreen
* Take CARRY from off left edge
DEY
:RAMRD1 sta $c003
lda (IMAGE),y
sta $c002
TAX
:c2 lda $FFFF,x ;CARRYn+1
sta carryim
:90 LDA $FFFF,X ;CARRYn
STA CARRY
LDA IMAGE
CLC
ADC OFFLEFT
STA IMAGE
BCC :1
INC IMAGE+1
:1 LDY #0
LDA VISWIDTH
STA WIDTH
BNE :inloop
BEQ :4 ;Zero width
* (b) Left edge onscreen
* Start a new line at left edge
:2 lda (BASE),y
:AMASK and #0 ;AMASK
sta CARRY
lda #0 ;0 XOR X == X
sta carryim
* Lay line down left-to-right fast as you can
:inloop
:RAMRD2 sta $c003
lda (IMAGE),y
sta $c002
tax
:s1 lda $FFFF,x ;SHIFTn+1
ora carryim
sta imbyte
:c1 lda $FFFF,x ;CARRYn+1
sta carryim
:91 lda $FFFF,x ;SHIFTn
ora CARRY ;Combine with carryover from previous byte
ora (BASE),y
eor imbyte
ora #$80 ;set hibit
sta (BASE),y
:92 LDA $FFFF,X ;CARRYn
STA CARRY ;Carry over to next byte
INY
CPY VISWIDTH
BCC :inloop
* Extra byte on right (carryover)
LDA OFFRIGHT
BNE :5 ;Rightmost byte is offscreen
:4 lda CARRY ;0's in unused part of byte
ora (BASE),y
eor carryim
ora #$80
sta (BASE),y
* Next line up
:5 LDA WIDTH
CLC
ADC IMAGE
STA IMAGE
BCC :6
INC IMAGE+1
:6 DEC YCO
LDY YCO
CPY TOPEDGE
beq :done
jmp :0
* Restore parameters
:done jmp DONE
*-------------------------------
*
* M I R R O R L A Y
*
* Called by LAY
*
* Specified starting byte (XCO, YCO) is image's bottom
* right corner, not bottom left; bytes are read off image
* table R-L, T-B and mirrored before printing.
*
* In: A = OPACITY, sans bit 7
*
*-------------------------------
MLAY ;A = OPACITY
cmp #eor
bne :1
jmp MLayXOR
:1 cmp #mask
bcc :2
jmp MLayMask
:2 jmp MLayGen
*-------------------------------
*
* General (AND/OR/STORE)
*
*-------------------------------
MLayGen
JSR PREPREP
LDA XCO
SEC
SBC WIDTH
STA XCO
jsr CROP
bpl :cont
jmp DONE
:cont
lda BANK
sta :RAMRD1+1
sta :RAMRD2+1
LDX OFFSET
LDA SHIFTL,X
STA :91+1
LDA SHIFTH,X
STA :91+2
LDA CARRYL,X
STA :90+1
STA :92+1
LDA CARRYH,X
STA :90+2
STA :92+2
LDA AMASKS,X
STA AMASK
LDA BMASKS,X
STA BMASK
LDX OPACITY
LDA OPCODE,X
STA :80
STA :81
* Lay on
LDY YCO
:0 LDA YLO,Y
STA BASE
LDA YHI,Y
CLC
ADC PAGE
STA BASE+1
LDY OFFLEFT
BEQ :2
* Take CARRY from off left edge
LDY VISWIDTH
:RAMRD1 sta $c003
lda (IMAGE),y
sta $c002
TAX
LDA MIRROR-$80,X
TAX
:90 LDA $FFFF,X ;CARRYn
STA CARRY
:1 DEY
BPL :3
BMI :4
* Start a new line at left edge
:2 LDY XCO
LDA (BASE),Y
AND AMASK
STA CARRY
LDY WIDTH
DEY
* Lay line down left-to-right fast as you can
:3 STY YREG
:RAMRD2 sta $c003
lda (IMAGE),y
sta $c002
TAX
LDA MIRROR-$80,X
TAX
:91 LDA $FFFF,X ;SHIFTn
ORA CARRY ;Combine with carryover from previous byte
LDY XCO
:80 STA (BASE),Y ;STA/ORA/AND/EOR depending on OPACITY
STA (BASE),Y
:92 LDA $FFFF,X ;CARRYn
STA CARRY ;Carry over to next byte
INC BASE
LDY YREG
CPY RMOST
BEQ :7
DEY
BPL :3
* Extra byte on right (carryover)
:7 LDA OFFRIGHT
BNE :5 ;Rightmost byte is offscreen
:4 LDY XCO
LDA (BASE),Y
AND BMASK
ORA CARRY
:81 STA (BASE),Y
STA (BASE),Y
* Next line up
:5 LDA WIDTH
CLC
ADC IMAGE
STA IMAGE
BCC :6
INC IMAGE+1
:6 DEC YCO
LDY YCO
CPY TOPEDGE
beq :done
jmp :0
:done JMP DONE
*-------------------------------
*
* Mask, then OR
*
*-------------------------------
MLayMask
ldx OPACITY ;4 = mask, 5 = visible mask
lda OPCODE,x ;4 = and, 5 = sta
sta :masksm1
sta :masksm2
JSR PREPREP
LDA XCO
SEC
SBC WIDTH
STA XCO
jsr CROP
bpl :cont
jmp DONE
:cont
lda BANK
sta :RAMRD1+1
sta :RAMRD2+1
LDX OFFSET
LDA SHIFTL,X
STA :91+1
sta :93+1
LDA SHIFTH,X
STA :91+2
sta :93+2
LDA CARRYL,X
STA :90+1
STA :92+1
sta :94+1
sta :96+1
LDA CARRYH,X
STA :90+2
STA :92+2
sta :94+2
sta :96+2
LDA AMASKS,X
STA :AMASK+1
LDA BMASKS,X
STA :BMASK+1
* Lay on
LDY YCO
:0 LDA YLO,Y
STA BASE
LDA YHI,Y
CLC
ADC PAGE
STA BASE+1
LDY OFFLEFT
BEQ :2
* (a) Left edge offscreen
* Take CARRY from off left edge
LDY VISWIDTH
:RAMRD1 sta $c003
lda (IMAGE),y
; eor #$ff ;TEMP
; ora #$80 ;TEMP
sta $c002
TAX
LDA MIRROR-$80,X
TAX
:96 lda $FFFF,x ;CARRYn
sta carryim
lda MASKTAB-$80,x
tax
:90 LDA $FFFF,X ;CARRYn
STA CARRY
:1 DEY
BPL :3
BMI :4
* (b) Left edge onscreen
* Start a new line at left edge
:2 LDY XCO
:AMASK lda #0 ;AMASK
sta CARRY
and (BASE),y
sta carryim
LDY WIDTH
DEY
* Lay line down left-to-right fast as you can
:3 STY YREG
:RAMRD2 sta $c003
lda (IMAGE),y
; eor #$ff ;TEMP
; ora #$80 ;TEMP
sta $c002
TAX
LDA MIRROR-$80,X
TAX
:93 lda $FFFF,x ;SHIFTn
ora carryim
sta imbyte
:94 lda $FFFF,x ;CARRYn
sta carryim
lda MASKTAB-$80,x
tax
:91 LDA $FFFF,X ;SHIFTn
ORA CARRY ;Combine with carryover from previous byte
LDY XCO
:masksm1 and (BASE),y
ora imbyte
STA (BASE),Y
:92 LDA $FFFF,X ;CARRYn
STA CARRY ;Carry over to next byte
INC BASE
LDY YREG
CPY RMOST
BEQ :7
DEY
BPL :3
* Extra byte on right (carryover)
:7 LDA OFFRIGHT
BNE :5 ;Rightmost byte is offscreen
:4 LDY XCO
LDA (BASE),Y
:BMASK AND #0 ;BMASK
ORA CARRY
:masksm2 and (BASE),y
ora carryim
STA (BASE),Y
* Next line up
:5 LDA WIDTH
CLC
ADC IMAGE
STA IMAGE
BCC :6
INC IMAGE+1
:6 DEC YCO
LDY YCO
CPY TOPEDGE
beq :done
jmp :0
:done jmp DONE
*-------------------------------
*
* Special XOR
*
*-------------------------------
MLayXOR
JSR PREPREP
LDA XCO
SEC
SBC WIDTH
STA XCO
jsr CROP
bpl :cont
jmp DONE
:cont
lda BANK
sta :RAMRD1+1
sta :RAMRD2+1
LDX OFFSET
LDA SHIFTL,X
STA :91+1
LDA SHIFTH,X
STA :91+2
LDA CARRYL,X
STA :90+1
STA :92+1
LDA CARRYH,X
STA :90+2
STA :92+2
jsr shiftoffset
lda SHIFTL,x
sta :s1+1
lda SHIFTH,x
sta :s1+2
lda CARRYL,x
sta :c1+1
sta :c2+1
lda CARRYH,x
sta :c1+2
sta :c2+2
LDA AMASKS,X
STA :AMASK+1
* Lay on
LDY YCO
:0 LDA YLO,Y
STA BASE
LDA YHI,Y
CLC
ADC PAGE
STA BASE+1
LDY OFFLEFT
BEQ :2
* (a) Left edge offscreen
* Take CARRY from off left edge
LDY VISWIDTH
:RAMRD1 sta $c003
lda (IMAGE),y
sta $c002
TAX
LDA MIRROR-$80,X
TAX
:c2 lda $FFFF,x ;CARRYn+1
sta carryim
:90 LDA $FFFF,X ;CARRYn
STA CARRY
:1 DEY
BPL :3
BMI :4
* (b) Left edge onscreen
* Start a new line at left edge
:2 ldy XCO
:AMASK lda #0 ;AMASK
and (BASE),y
sta CARRY
lda #0
sta carryim
LDY WIDTH
DEY
* Lay line down left-to-right fast as you can
:3 STY YREG
:RAMRD2 sta $c003
lda (IMAGE),y
sta $c002
TAX
LDA MIRROR-$80,X
TAX
:s1 lda $FFFF,x ;SHIFTn
ora carryim
sta imbyte
:c1 lda $FFFF,x ;CARRYn
sta carryim
:91 LDA $FFFF,X ;SHIFTn
ORA CARRY ;Combine with carryover from previous byte
LDY XCO
ora (BASE),y
eor imbyte
ora #$80
sta (BASE),Y
:92 LDA $FFFF,X ;CARRYn
STA CARRY ;Carry over to next byte
INC BASE
LDY YREG
CPY RMOST
BEQ :7
DEY
BPL :3
* Extra byte on right (carryover)
:7 LDA OFFRIGHT
BNE :5 ;Rightmost byte is offscreen
:4 LDY XCO
lda CARRY
ora (BASE),Y
eor carryim
ora #$80
STA (BASE),Y
* Next line up
:5 LDA WIDTH
CLC
ADC IMAGE
STA IMAGE
BCC :6
INC IMAGE+1
:6 DEC YCO
LDY YCO
CPY TOPEDGE
beq :done
jmp :0
:done JMP DONE
*-------------------------------
*
* Peel
*
*-------------------------------
PEEL
sta $c004
]ramrd1 sta $c003
jmp fastlaySTA
*-------------------------------
*
* F A S T L A Y
*
* Streamlined LAY routine
*
* No offset - no clipping - no mirroring - no masking -
* no EOR - trashes IMAGE - may crash if overtaxed -
* but it's fast.
*
* 10/3/88: OK for images to protrude PARTLY off top
*
*-------------------------------
FASTLAY
sta $c004 ;RAMWRT main
]ramrd2 sta $c003 ;RAMRD aux
jsr setimage
ldx OPACITY ;hi bit off!
cpx #sta
beq fastlaySTA
lda OPCODE,x
sta :smod
lda PAGE
sta :smPAGE+1
lda XCO
sta :smXCO+1
ldy #0
lda (IMAGE),y
sta :smWIDTH+1
sec
sbc #1
sta :smSTART+1
lda YCO
tax
iny
sbc (IMAGE),y
bcs :ok
lda #-1 ;limited Y-clipping
:ok sta :smTOP+1
lda IMAGE
clc
adc #2
sta IMAGE
bcc :1
inc IMAGE+1
:1
:outloop
lda YLO,x
clc
:smXCO adc #0
sta BASE
lda YHI,x
:smPAGE adc #$20
sta BASE+1
:smSTART ldy #3
:inloop
]ramrd3 sta $c003 ;RAMRD aux
lda (IMAGE),y
sta $c002 ;RAMRD main
:smod ora (BASE),y
sta (BASE),y
dey
bpl :inloop
:smWIDTH lda #4
adc IMAGE ;assume cc
sta IMAGE
bcc :2
inc IMAGE+1
:2
dex
:smTOP cpx #$ff
bne :outloop
rts
*-------------------------------
*
* Still more streamlined version of FASTLAY (STA only)
*
*-------------------------------
fastlaySTA
lda PAGE
sta :smPAGE+1
lda XCO
sta :smXCO+1
ldy #0
lda (IMAGE),y
sta :smWIDTH+1
sec
sbc #1
sta :smSTART+1
lda YCO
tax
iny
sbc (IMAGE),y
bcs :ok
lda #-1 ;limited Y-clipping
:ok sta :smTOP+1
lda IMAGE
clc
adc #2
sta IMAGE
bcc :1
inc IMAGE+1
:1
:outloop
lda YLO,x
clc
:smXCO adc #0
sta :smod+1
lda YHI,x
:smPAGE adc #$20
sta :smod+2
:smSTART ldy #3
:inloop
lda (IMAGE),y
:smod sta $2000,y ;BASE
dey
bpl :inloop
:smWIDTH lda #4
adc IMAGE ;cc
sta IMAGE
bcc :2
inc IMAGE+1
:2
dex
:smTOP cpx #$ff
bne :outloop
rts
*-------------------------------
*
* F A S T M A S K
*
*-------------------------------
FASTMASK
sta $c004 ;RAMWRT main
]ramrd4 sta $c003 ;RAMRD aux
jsr setimage
lda PAGE
sta :smPAGE+1
lda XCO
sta :smXCO+1
ldy #0
lda (IMAGE),y
sta :smWIDTH+1
sec
sbc #1
sta :smSTART+1
lda YCO
tax
iny
sbc (IMAGE),y
bcs :ok
lda #-1 ;limited Y-clipping
:ok sta :smTOP+1
lda IMAGE
clc
adc #2
sta IMAGE
bcc :1
inc IMAGE+1
:1
:outloop
stx index
lda YLO,x
clc
:smXCO adc #0
sta BASE
lda YHI,x
:smPAGE adc #$20
sta BASE+1
:smSTART ldy #3
:inloop
]ramrd5 sta $c003 ;RAMRD aux
lda (IMAGE),y
sta $c002 ;RAMRD main
tax
lda MASKTAB-$80,X
and (BASE),Y
sta (BASE),y
dey
bpl :inloop
:smWIDTH lda #4
adc IMAGE ;cc
sta IMAGE
bcc :2
inc IMAGE+1
:2
ldx index
dex
:smTOP cpx #$ff
bne :outloop
rts
*-------------------------------
*
* S E T F A S T M A I N / A U X
*
* Modify FASTLAY routines to expect image tables to
* be in main/auxmem. SETFAST need be called only once
* (e.g., when switching between game & builder).
*
*-------------------------------
SETFASTMAIN
lda #$02 ;RAMRD main
]setfast
sta ]ramrd1+1
sta ]ramrd2+1
sta ]ramrd3+1
sta ]ramrd4+1
sta ]ramrd5+1
rts
SETFASTAUX
lda #$03 ;RAMRD aux
bne ]setfast
*-------------------------------
*
* F A S T B L A C K
*
* Wipe a rectangular area to black2
*
* Width/height passed in IMAGE/IMAGE+1
* (width in bytes, height in pixels)
*
*-------------------------------
FASTBLACK
lda color
sta :smCOLOR+1
lda PAGE
sta :smPAGE+1
lda XCO
sta :smXCO+1
lda width
sec
sbc #1
sta :smSTART+1
lda YCO
tax
sbc height ;cs
sta :smTOP+1
:outloop
lda YLO,x
clc
:smXCO adc #0
sta :smod+1
lda YHI,x
:smPAGE adc #$20
sta :smod+2
:smCOLOR lda #$80
:smSTART ldy #3
:inloop
:smod sta $2000,y ;BASE
dey
bpl :inloop
dex
:smTOP cpx #$ff
bne :outloop
rts
*-------------------------------
*
* C O P Y S C R E E N
*
* Copy $2000 bytes
*
* In: IMAGE+1 = dest scrn, IMAGE = org scrn
* (use hi byte of actual memory address)
*
*-------------------------------
COPYSCRN
lda IMAGE+1
sta :dst1+2
clc
adc #$10
sta :dst2+2
lda IMAGE
sta :org1+2
adc #$10
sta :org2+2
ldx #$10
ldy #0
:loop
:org1 lda $2000,y
:dst1 sta $4000,y
:org2 lda $3000,y
:dst2 sta $5000,y
iny
bne :loop
inc :org1+2
inc :org2+2
inc :dst1+2
inc :dst2+2
dex
bne :loop
rts
*-------------------------------
* Invert Y-tables
*-------------------------------
INVERTY
ldx #191 ;low line
ldy #0 ;high line
* Switch low & high lines
:loop lda YLO,x
pha
lda YLO,y
sta YLO,x
pla
sta YLO,y
lda YHI,x
pha
lda YHI,y
sta YHI,x
pla
sta YHI,y
* Move 1 line closer to ctr
dex
iny
cpy #96
bcc :loop
]rts rts
*-------------------------------
lst
ds 1
usr $a9,1,$0000,*-org
lst off