mirror of
https://github.com/deater/dos33fsprogs.git
synced 2025-01-03 18:29:53 +00:00
880 lines
24 KiB
ArmAsm
880 lines
24 KiB
ArmAsm
;*******************************************************************************
|
|
;* Micro-Painter, by Bob Bishop *
|
|
;* Copyright 1980 Datasoft, Inc. All Rights Reserved. *
|
|
;* *
|
|
;* Disassembly of "PAINT" routines. *
|
|
;*******************************************************************************
|
|
;* Disassembly by Andy McFadden, using 6502bench SourceGen v1.4. *
|
|
;* Last updated 2019/10/25. *
|
|
;*******************************************************************************
|
|
|
|
color_black = 0
|
|
color_purple = 1
|
|
color_green = 2
|
|
color_blue = 3
|
|
color_orange = 4
|
|
color_white = 5
|
|
|
|
work_buffer = $7000 ; work data area,$ from $7000-7fff
|
|
|
|
TXTCLR = $c050
|
|
MIXCLR = $c052
|
|
TXTPAGE1 = $c054
|
|
LORES = $c056
|
|
|
|
pageflg = $00
|
|
xc = $01
|
|
yc = $02
|
|
back = $03
|
|
evenc = $04
|
|
oddc = $05
|
|
screen_bit = $06
|
|
hptr = $07
|
|
cflag = $09
|
|
ptr = $0e
|
|
match_color = $10
|
|
add_coord_lo = $12
|
|
plot_coord_lo = $13
|
|
add_coord_ptr = $14 ; new coords are added at this point
|
|
plot_coord_ptr = $16 ; coords are read from this pointer and plotted
|
|
tmp = $18
|
|
|
|
|
|
;*******************************************************************************
|
|
;* FILL - flood fill with dither pattern. *
|
|
;* *
|
|
;* Uses a circular buffer at $7000-7fff to hold X/Y coordinates. The color of *
|
|
;* the pixel at the initial X/Y is used as the to-fill color. *
|
|
;* *
|
|
;* Start by adding the initial X/Y to the work buffer. We then loop, removing *
|
|
;* the first coordinate from the buffer and testing the color at that location.*
|
|
;* If it matches, we draw the pixel, and then add the four adjacent pixels to *
|
|
;* the list. Repeat until the list is empty. *
|
|
;* *
|
|
;* Warning: filling with the same color, e.g. filling a white area with white,*
|
|
;* will likely hang. *
|
|
;* *
|
|
;* On entry: *
|
|
;* $01 - X-coord *
|
|
;* $02 - Y-coord *
|
|
;* $04 - even color (0-5) *
|
|
;* $05 - odd color (0-5) *
|
|
;* *
|
|
;* Preserves X/Y registers. *
|
|
;*******************************************************************************
|
|
|
|
|
|
FILL:
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
lda #$80
|
|
sta back
|
|
jsr PLT ; get current color at X,Y
|
|
lda back
|
|
sta match_color ; this is the color we're replacing
|
|
lda #<work_buffer
|
|
sta add_coord_ptr
|
|
sta plot_coord_ptr
|
|
lda #>work_buffer
|
|
sta add_coord_ptr+1
|
|
sta plot_coord_ptr+1
|
|
lda xc ; put first point into work buffer
|
|
sta work_buffer
|
|
lda yc
|
|
sta work_buffer+1
|
|
ldy #$02 ; point next output past the X,Y we just added
|
|
sty add_coord_lo
|
|
ldy #$00
|
|
sty plot_coord_lo
|
|
|
|
; Get the next candidate coordinate.
|
|
|
|
FillLoop:
|
|
lda (plot_coord_ptr),Y
|
|
sta xc
|
|
iny
|
|
lda (plot_coord_ptr),Y
|
|
sta yc
|
|
iny
|
|
bne L6845 ; still on same page, branch
|
|
inc plot_coord_ptr+1 ; move to next page
|
|
lda plot_coord_ptr+1
|
|
cmp #$80 ;did we reach the end of the buffer?
|
|
bne L6845 ; no, keep going
|
|
lda #>work_buffer ; yes, reset it
|
|
sta plot_coord_ptr+1
|
|
L6845:
|
|
sty plot_coord_lo
|
|
lda #$80
|
|
sta back
|
|
jsr PLT ; get screen pixel color
|
|
lda back
|
|
cmp match_color ; matching color?
|
|
bne L6873 ; no, don't plot
|
|
|
|
; The current pixel matches the color we want to replace. Plot a pixel and add
|
|
; the four adjacent pixels to the work list.
|
|
|
|
jsr DITHER ; plot pixel with dither colors
|
|
inc xc
|
|
jsr AddCoord ; X+1,Y
|
|
dec xc
|
|
inc yc
|
|
jsr AddCoord ; X,Y+1
|
|
dec xc
|
|
dec yc
|
|
jsr AddCoord ; X-1,Y
|
|
inc xc
|
|
dec yc
|
|
jsr AddCoord ; X-1,Y-1
|
|
inc yc
|
|
L6873:
|
|
ldy plot_coord_lo ; have we reached the end?
|
|
cpy add_coord_lo
|
|
bne FillLoop ; low part differs, continue
|
|
lda plot_coord_ptr+1
|
|
cmp add_coord_ptr+1
|
|
bne FillLoop ; high part differs, continue
|
|
pla ; done!
|
|
tay
|
|
pla
|
|
tax
|
|
rts
|
|
|
|
AddCoord:
|
|
lda yc ; check Y-coord
|
|
cmp #255 ; off top of screen?
|
|
beq L68CA ; yes, ignore
|
|
cmp #192 ; off bottom of screen?
|
|
beq L68CA ; yes, ignore
|
|
lda xc ; check X-coord
|
|
cmp #$ff ; off left of screen?
|
|
beq L68CA ; yes, ignore
|
|
cmp #140 ; off right of screen?
|
|
beq L68CA ; yes, ignore
|
|
|
|
; Looks good, add X,Y to list.
|
|
; Note add_coord_ptr is always $xx00; the low byte is in add_coord_lo.
|
|
|
|
ldy add_coord_lo
|
|
sta (add_coord_ptr),Y
|
|
iny
|
|
lda yc
|
|
sta (add_coord_ptr),Y
|
|
iny
|
|
sty add_coord_lo
|
|
lda add_coord_ptr+1
|
|
sta tmp
|
|
cpy #$00 ; did we advance to next page?
|
|
bne L68B8 ; no, continue
|
|
inc add_coord_ptr+1 ; yes, advance
|
|
lda add_coord_ptr+1
|
|
cmp #(>work_buffer)+16 ; did we reach end of work area?
|
|
bne L68B8 ; no, still good
|
|
lda #>work_buffer ; yes, wrap around
|
|
sta add_coord_ptr+1
|
|
L68B8:
|
|
cpy plot_coord_lo ; did we run into the "write" ptr?
|
|
bne L68CA ; no
|
|
lda plot_coord_ptr+1 ; check the high byte
|
|
cmp add_coord_ptr+1
|
|
bne L68CA ;still no
|
|
dec add_coord_lo ; whoops; back up, discarding what we just added
|
|
dec add_coord_lo
|
|
lda tmp ; restore previous high byte
|
|
sta add_coord_ptr+1
|
|
L68CA:
|
|
rts
|
|
|
|
.align $100
|
|
|
|
DITHER:
|
|
jmp DITHER1
|
|
|
|
PLT:
|
|
jmp PLT1 ; external entry point
|
|
|
|
;*******************************************************************************
|
|
;* DITHER - plot a point with dithered colors. *
|
|
;* *
|
|
;* On entry: *
|
|
;* *
|
|
;* $00 - hi-res page (zero for page 1, nonzero for page 2) *
|
|
;* $01 - X coordinate [0,139] *
|
|
;* $02 - Y coordinate [0,191] *
|
|
;* $04 - even color value *
|
|
;* $05 - odd color value *
|
|
;* *
|
|
;* Preserves X/Y registers. *
|
|
;*******************************************************************************
|
|
;Clear variables
|
|
|
|
|
|
|
|
DITHER1:
|
|
txa
|
|
pha
|
|
lda yc ; start with the Y-coord
|
|
ldx evenc ; check the even color
|
|
beq L691A ; black, use checkerboard
|
|
cpx #color_white ; white
|
|
beq L691A ; yes, use checkerboard pattern
|
|
ldx oddc ; check the odd color
|
|
beq L691A ; black, use checkerboard
|
|
cpx #color_white ; white?
|
|
bne L691C ; yes, use checkerboard
|
|
L691A:
|
|
eor xc ; factor in the X coord to get checkerboard
|
|
L691C:
|
|
and #$01 ; only low bit matters
|
|
tax ; X=0 or 1
|
|
lda evenc,X ; load evenc or oddc
|
|
sta back ; set as color to draw
|
|
jmp Plt2
|
|
|
|
;*******************************************************************************
|
|
;* PLT - plot a point and return the current color. *
|
|
;* *
|
|
;* On entry: *
|
|
;* *
|
|
;* $00 = hi-res page (zero for page 1, nonzero for page 2) *
|
|
;* $01 = X-coord [0,139] *
|
|
;* $02 = Y-coord [0,191] *
|
|
;* $03 = $80=no plot, 0-5=color to draw *
|
|
;* *
|
|
;* On exit: *
|
|
;* $03 = screen color (0-5) (will be the new color if we're in draw mode) *
|
|
;* *
|
|
;* Preserves X/Y registers. *
|
|
;*******************************************************************************
|
|
|
|
PLT1:
|
|
txa
|
|
pha
|
|
Plt2:
|
|
tya
|
|
pha
|
|
jsr SetRowBase ; set $07-08 as hi-res pointer
|
|
ldx back ; get color
|
|
bmi L693B ; not drawing, branch
|
|
lda color_flag_0,X ; get color flags for the two bits
|
|
sta cflag
|
|
lda color_flag_1,X
|
|
sta cflag+1
|
|
L693B:
|
|
ldx xc
|
|
ldy div7_tab,X ; get byte offset
|
|
lda bit_tab,X ; get bit offset (low bit of pair)
|
|
sta screen_bit
|
|
|
|
; We want to read/write two hi-res bits, so we loop through here twice.
|
|
|
|
ldx #$00 ; first bit
|
|
BitLoop:
|
|
lda screen_bit
|
|
bit back ; are we writing?
|
|
bpl PlotWrite ; yes, branch
|
|
|
|
; Just reading the screen.
|
|
|
|
and (hptr),Y ; test screen bit
|
|
beq BitLoopBottom ; not set
|
|
txa ; 0 or 1
|
|
sec ; will add +1 or +2
|
|
adc back ; so this sets bit 0 or bit 1
|
|
sta back
|
|
lda (hptr),Y ; check hi bit
|
|
bpl BitLoopBottom ; not set, branch
|
|
lda back ; set bit 2 if the hi-res pixel's high bit was set
|
|
ora #$04
|
|
sta back
|
|
bne BitLoopBottom
|
|
|
|
|
|
; Draw the pixel.
|
|
|
|
PlotWrite:
|
|
eor #$ff ; reverse screen bit to form mask
|
|
and (hptr),Y ; AND with screen data
|
|
sta (hptr),Y ; store, clearing previous value at that bit
|
|
lda cflag,X ; get color flag 0 or 1
|
|
beq BitLoopBottom ; zero, don't need to set pixel or high bit
|
|
lda screen_bit ; nonzero, set the appropriate bit in the pixel
|
|
ora (hptr),Y
|
|
sta (hptr),Y
|
|
lda cflag ; is it black or white?
|
|
cmp cflag+1 ; (want black/white to match hi bit of adjacent color)
|
|
beq BitLoopBottom ; yes, leave high bit alone
|
|
lda (hptr),Y ; not black or white, so we need to set high bit
|
|
and #$7f ; clear whatever's there now
|
|
sta (hptr),Y
|
|
lda cflag,X ; get high bit from color flag
|
|
and #$80
|
|
ora (hptr),Y
|
|
sta (hptr),Y ; set that on the screen
|
|
BitLoopBottom:
|
|
inx
|
|
cpx #$02 ; have we done it twice?
|
|
beq BitLoopDone ; yes, bail
|
|
asl screen_bit ; no, shift screen bit to next position
|
|
bpl BitLoop ; didn't shift into high bit, loop
|
|
iny ; shifted into high bit, move on to next byte
|
|
lda #$01 ; and reset bit to low bit
|
|
sta screen_bit
|
|
bne BitLoop ; (always)
|
|
|
|
BitLoopDone:
|
|
lda back ; were we writing?
|
|
bpl L69A3 ; yes, bail
|
|
and #$07 ; no, do a color lookup
|
|
tax
|
|
lda bits_to_color,X ; convert 00000HBA to 0-5
|
|
sta back
|
|
L69A3:
|
|
pla
|
|
tay
|
|
pla
|
|
tax
|
|
rts
|
|
|
|
;.junk 29
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
|
|
;
|
|
; Sets $07-08 as the hi-res base pointer for the row in "yc".
|
|
;
|
|
|
|
SetRowBase:
|
|
ldy yc
|
|
lda ytable_lo,Y
|
|
sta hptr
|
|
lda pageflg ; 0 for page 1, nonzero for page 2
|
|
beq L69D2
|
|
lda #$60 ; configure for page 2
|
|
L69D2:
|
|
eor ytable_hi,Y
|
|
sta hptr+1
|
|
rts
|
|
|
|
; These bytes have three possible values. They're used by PLT to figure out
|
|
; which bits to set on the hi-res screen for a given color (0-5).
|
|
;
|
|
; $00 = don't set this bit
|
|
; $7f = set this bit, clear high bit of byte
|
|
; $ff = set this bit, set high bit of byte
|
|
;
|
|
; Each hi-res color (in our 140x192 screen) requires two bits per pixel. One
|
|
; bit comes from each table.
|
|
|
|
color_flag_0:
|
|
.byte $00,$7f,$00,$ff,$00,$ff
|
|
|
|
color_flag_1:
|
|
.byte $00,$00,$7f,$00,$ff,$ff
|
|
;
|
|
; Converts a bit pattern to a color, 0-5.
|
|
;
|
|
; Index is a 3-bit value 00000HBA, where A is set if the first bit of the hi-res
|
|
; pixel was set, B is set if the second bit of the hi-res pixel was set, and H
|
|
; is set if the high bit of at least one of the bytes with a pixel was set.
|
|
; (Remember that we're treating the screen as being 140 pixels across, so it's
|
|
; two bits per pixel.)
|
|
|
|
bits_to_color:
|
|
.byte color_black
|
|
.byte color_purple
|
|
.byte color_green
|
|
.byte color_white
|
|
.byte color_black
|
|
.byte color_blue
|
|
.byte color_orange
|
|
.byte color_white
|
|
|
|
.align $100
|
|
|
|
SCOPE:
|
|
jmp SCOPE1 ; entry point from Applesoft
|
|
|
|
;*******************************************************************************
|
|
;* INIT - initialize "micro" / "scope" mode *
|
|
;* *
|
|
;* Clears the lo-res screen and enables lo-res graphics mode. *
|
|
;* *
|
|
;* Preserves X/Y registers. *
|
|
;*******************************************************************************
|
|
; Clear variables
|
|
|
|
|
|
INIT:
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
|
|
; Clear lo-res screen to black.
|
|
|
|
ldx #23 ; X = row
|
|
ClearLoLoop:
|
|
lda lr_ytable_lo,X
|
|
sta ptr
|
|
lda lr_ytable_hi,X
|
|
sta ptr+1
|
|
lda #$00
|
|
ldy #39 ; Y = column
|
|
L6A17:
|
|
sta (ptr),Y
|
|
dey
|
|
bpl L6A17
|
|
dex
|
|
bpl ClearLoLoop
|
|
|
|
; Configure soft-switches for lo-res.
|
|
sta TXTCLR
|
|
sta MIXCLR
|
|
sta TXTPAGE1
|
|
sta LORES
|
|
pla
|
|
tay
|
|
pla
|
|
tax
|
|
rts
|
|
|
|
;*******************************************************************************
|
|
;* SCOPE - display part of the hi-res screen magnified on the lo-res screen. *
|
|
;* *
|
|
;* On entry: *
|
|
;* $00 = X position [0,139] *
|
|
;* $01 = Y position [0,191] *
|
|
;* *
|
|
;* Preserves X/Y registers. *
|
|
;*******************************************************************************
|
|
;Clear variables
|
|
xc_scope = $00
|
|
yc_scope = $01
|
|
col_ctr = $02
|
|
row_ctr = $03
|
|
saved_byte_off = $04
|
|
work_ptr_lo = $05
|
|
first_bit = $06
|
|
hr_byte = $07
|
|
hi_in_lo = $08
|
|
start_x = $09
|
|
;hptr = $0c
|
|
work_ptr = $0e
|
|
|
|
|
|
|
|
|
|
SCOPE1:
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
sec ; left edge is XC - 9
|
|
lda xc_scope
|
|
sbc #9
|
|
sta xc_scope
|
|
sta start_x
|
|
sec
|
|
lda yc_scope ; top edge is YC - 11
|
|
sbc #11
|
|
sta yc_scope
|
|
lda #$00
|
|
sta work_ptr_lo
|
|
sta work_ptr
|
|
lda #>work_buffer
|
|
sta work_ptr+1 ; out_ptr = work buffer
|
|
|
|
;
|
|
; Phase 1: convert hi-res pixels to values in the work buffer.
|
|
;
|
|
; Each hi-res pixel in our window gets two adjacent values in the work buffer,
|
|
; one per bit. The value is from 0-3, and reflects the state of one bit on the
|
|
; pixel plus the high bit of the byte.
|
|
;
|
|
; Note: there's a 1-pixel black border on the left and right of the lo-res
|
|
; display, presumably to allow the central 2x2 block to be centered on the
|
|
; screen. There's also a 2-pixel black border on the bottom of the screen.
|
|
;
|
|
|
|
lda #23
|
|
sta row_ctr
|
|
RowLoop:
|
|
lda #38
|
|
sta col_ctr
|
|
ldx yc_scope ; get the Y-coord
|
|
cpx #192 ; did we wrap off the top?
|
|
bcs OffEdge ; yes, bail
|
|
lda ytable_lo,X ; get the hi-res row base
|
|
sta hptr
|
|
lda ytable_hi,X
|
|
sta hptr+1
|
|
ldx xc_scope ; get the X-coord
|
|
cpx #140 ; did we wrap around to the left when subtracting?
|
|
bcc ScanPixel ; no, scan it
|
|
|
|
; We're off the left edge, so just fill in black until we get on the screen.
|
|
|
|
ldy work_ptr_lo
|
|
lda #$00
|
|
OffLeftLoop:
|
|
sta (work_ptr),Y
|
|
iny
|
|
sta (work_ptr),Y
|
|
iny
|
|
bne L6A7A
|
|
inc work_ptr+1
|
|
L6A7A:
|
|
dec col_ctr
|
|
dec col_ctr
|
|
inx
|
|
bne OffLeftLoop
|
|
sty work_ptr_lo
|
|
clc
|
|
|
|
; Get the color of a pixel. X coordinate in X-reg, carry flag is clear.
|
|
|
|
ScanPixel:
|
|
lda bit_tab,X ; get first hi-res pixel bit
|
|
sta first_bit
|
|
ldy div7_tab,X ; get byte offset
|
|
ldx col_ctr ; lo-res column counter
|
|
L6A8E:
|
|
lda (hptr),Y ; get hi-res byte
|
|
sta hr_byte
|
|
and #$80 ; clear everything but the hi bit
|
|
rol ; roll it into the low bit
|
|
rol ; (note carry was clear)
|
|
sta hi_in_lo
|
|
iny
|
|
sty saved_byte_off
|
|
ldy work_ptr_lo
|
|
L6A9D:
|
|
lda hr_byte ; get pixel byte
|
|
and first_bit ; mask off everything but interesting bit
|
|
beq L6AA5 ; bit not set, branch
|
|
lda #$02 ; bit set, use $02 regardless of bit position
|
|
L6AA5:
|
|
ora hi_in_lo ; add high bit (so now value is 0-3)
|
|
sta (work_ptr),Y ; save that off
|
|
iny ; advance work ptr
|
|
bne L6AAE
|
|
inc work_ptr+1
|
|
L6AAE:
|
|
dex ; decrement column counter
|
|
beq L6AD2 ; bail when we reach column 0
|
|
asl first_bit ; shift to the next bit in the pixel
|
|
bpl L6A9D ; still in same byte, repeat
|
|
sty work_ptr_lo
|
|
lda #$01 ; move to next byte, reset mask to bit 0
|
|
sta first_bit
|
|
ldy saved_byte_off
|
|
cpy #40 ; off right edge of hi-res screen?
|
|
bcc L6A8E ; nope, keep going
|
|
stx col_ctr ; yes, go into "off edge" code
|
|
|
|
; We're off the edge, to the right or the bottom. Fill out the row with black
|
|
; pixels.
|
|
|
|
OffEdge:
|
|
ldy work_ptr_lo
|
|
lda #$00
|
|
L6AC7:
|
|
sta (work_ptr),Y
|
|
iny
|
|
bne L6ACE
|
|
inc work_ptr+1
|
|
L6ACE:
|
|
dec col_ctr ; decrement the column counter
|
|
bne L6AC7 ; not end of row yet, branch
|
|
L6AD2:
|
|
sty work_ptr_lo
|
|
lda start_x ; reset X-coord
|
|
sta xc_scope
|
|
inc yc_scope ; advance to next row
|
|
dec row_ctr ; are we done?
|
|
beq Scope2 ; yes, move to rendering
|
|
jmp RowLoop ; no, loop
|
|
|
|
.align $100
|
|
|
|
; Phase 2: render the contents of the work buffer on the lo-res screen.
|
|
;
|
|
; The values in the work buffer are from 0-3. 0/2 indicates that the
|
|
; corresponding hi-res bit was set, +1 if the high bit in the byte was set.
|
|
|
|
;work_ptr = $0c
|
|
lr_ptr = $0e
|
|
|
|
Scope2:
|
|
lda #$01 ; left edge; 1-pixel boundary at sides
|
|
sta xc_scope
|
|
lda #$00 ; no border at top
|
|
sta yc_scope
|
|
sta saved_byte_off
|
|
sta work_ptr
|
|
lda #>work_buffer
|
|
sta work_ptr+1
|
|
ldx yc_scope ; get lo-res screen row base
|
|
L6B12:
|
|
lda lr_ytable_lo,X
|
|
sta lr_ptr
|
|
lda lr_ytable_hi,X
|
|
sta lr_ptr+1
|
|
DrawLoLoop:
|
|
ldy saved_byte_off
|
|
lda (work_ptr),Y ; get the first value
|
|
iny
|
|
asl ; shift it over
|
|
asl
|
|
ora (work_ptr),Y ; add in the second value
|
|
iny ; advance work ptr
|
|
bne L6B2A
|
|
inc work_ptr+1
|
|
L6B2A:
|
|
sty saved_byte_off
|
|
tax ; put color value (0-15) in X
|
|
lda lr_color_map,X ; convert it to a lo-res color
|
|
ldy xc_scope
|
|
sta (lr_ptr),Y ; plot 2x2 pixel (two bytes wide)
|
|
iny
|
|
sta (lr_ptr),Y
|
|
iny
|
|
sty xc_scope
|
|
cpy #39 ; end of row?
|
|
bne DrawLoLoop ; not yet, loop
|
|
lda #$01 ; reset X-coord
|
|
sta xc_scope
|
|
inc yc_scope ; advance to next row
|
|
ldx yc_scope
|
|
cpx #23 ; done? (leaves 1-pixel boundary at bottom)
|
|
bne L6B12 ; no, loop
|
|
|
|
; Draw crosshairs. It flickers a little because, on each loop, we draw the hi-
|
|
; res colors and then slam the crosshairs down.
|
|
|
|
lda #$dd ; two pixels, color=13 (yellow)
|
|
ldx #$04
|
|
L6B4E:
|
|
sta $05b5,X ; hard-wired screen positions
|
|
sta $05be,X
|
|
dex
|
|
bpl L6B4E
|
|
ldx #$01
|
|
L6B59:
|
|
sta $043b,X
|
|
sta $04bb,X
|
|
sta $06bb,X
|
|
sta $073b,X
|
|
dex
|
|
bpl L6B59
|
|
|
|
; Add "half-pixel" crosshair gap. The hi-res pixel at the center is a 2x2 lo-
|
|
; res block. We create a gap of 1 lo-res block between it and the crosshair.
|
|
; For the vertical line, that means we're not writing a full byte, because each
|
|
; text byte holds two lo-res blocks.
|
|
|
|
ldx #$01
|
|
L6B6A:
|
|
lda $053b,X ; draw one pixel with color=13
|
|
and #$f0 ; leave other pixel alone
|
|
ora #$0d
|
|
sta $053b,X
|
|
lda $063b,X
|
|
and #$0f
|
|
ora #$d0
|
|
sta $063b,X
|
|
dex
|
|
bpl L6B6A
|
|
pla
|
|
tay
|
|
pla
|
|
tax
|
|
rts
|
|
|
|
; Low-res row address, low byte.
|
|
|
|
lr_ytable_lo:
|
|
.byte $00,$80,$00,$80,$00,$80,$00,$80
|
|
.byte $28,$a8,$28,$a8,$28,$a8,$28,$a8
|
|
.byte $50,$d0,$50,$d0,$50,$d0,$50,$d0
|
|
|
|
; Low-res row address,$ high byte.
|
|
|
|
lr_ytable_hi:
|
|
.byte $04,$04,$05,$05,$06,$06,$07,$07
|
|
.byte $04,$04,$05,$05,$06,$06,$07,$07
|
|
.byte $04,$04,$05,$05,$06,$06,$07,$07
|
|
|
|
;
|
|
; Map hi-res pixel values to lo-res colors.
|
|
;
|
|
; Index is AHBH, where A and B are the hi-res pixel values, and H is the high
|
|
; bit of the hi-res byte. For example, green is 0010, purple is 1010, orange is
|
|
; 0111, blue is 1101.
|
|
;
|
|
; Some pixels straddle two bytes and potentially have different values for the
|
|
; high bit in each. Each color thus has two entries.
|
|
;
|
|
lr_color_map:
|
|
.byte $00 ; 0000 lo-res color 0 = black
|
|
.byte $00 ; 0001
|
|
.byte $cc ; 0010 12 = light green
|
|
.byte $99 ; 0011 9 = orange
|
|
.byte $00 ; 0100
|
|
.byte $00 ; 0101
|
|
.byte $cc ; 0110
|
|
.byte $99 ; 0111
|
|
.byte $33 ; 1000 3 = purple
|
|
.byte $33 ; 1001
|
|
.byte $ff ; 1010 15 = white
|
|
.byte $ff ; 1011
|
|
.byte $66 ; 1100 6 = medium blue
|
|
.byte $66 ; 1101
|
|
.byte $ff ; 1110
|
|
.byte $ff ; 1111
|
|
|
|
.align $100
|
|
|
|
; Hi-res row base address, low byte.
|
|
ytable_lo:
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00,$80,$80,$80,$80,$80,$80,$80,$80
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00,$80,$80,$80,$80,$80,$80,$80,$80
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00,$80,$80,$80,$80,$80,$80,$80,$80
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00,$80,$80,$80,$80,$80,$80,$80,$80
|
|
.byte $28,$28,$28,$28,$28,$28,$28,$28,$a8,$a8,$a8,$a8,$a8,$a8,$a8,$a8
|
|
.byte $28,$28,$28,$28,$28,$28,$28,$28,$a8,$a8,$a8,$a8,$a8,$a8,$a8,$a8
|
|
.byte $28,$28,$28,$28,$28,$28,$28,$28,$a8,$a8,$a8,$a8,$a8,$a8,$a8,$a8
|
|
.byte $28,$28,$28,$28,$28,$28,$28,$28,$a8,$a8,$a8,$a8,$a8,$a8,$a8,$a8
|
|
.byte $50,$50,$50,$50,$50,$50,$50,$50,$d0,$d0,$d0,$d0,$d0,$d0,$d0,$d0
|
|
.byte $50,$50,$50,$50,$50,$50,$50,$50,$d0,$d0,$d0,$d0,$d0,$d0,$d0,$d0
|
|
.byte $50,$50,$50,$50,$50,$50,$50,$50,$d0,$d0,$d0,$d0,$d0,$d0,$d0,$d0
|
|
.byte $50,$50,$50,$50,$50,$50,$50,$50,$d0,$d0,$d0,$d0,$d0,$d0,$d0,$d0
|
|
|
|
;*******************************************************************************
|
|
;* CLEAN -- set all non-white pixels to black. *
|
|
;* *
|
|
;* Preserves X/Y registers. *
|
|
;*******************************************************************************
|
|
|
|
; Clear variables
|
|
|
|
CLEAN:
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
ldy #$00
|
|
L6CC6:
|
|
ldx #$00
|
|
L6CC8:
|
|
stx xc
|
|
sty yc
|
|
lda #$80 ; read only
|
|
sta back
|
|
jsr PLT ; get current pixel color
|
|
lda back
|
|
cmp #color_white ; is it a white pixel?
|
|
beq L6CE0 ; yes, leave it alone
|
|
lda #color_black ; no, clear it
|
|
sta back
|
|
jsr PLT ; draw black pixel
|
|
L6CE0:
|
|
inx
|
|
cpx #140 ; end of line?
|
|
bne L6CC8 ; no, continue
|
|
iny
|
|
cpy #192 ; end of screen?
|
|
bne L6CC6 ; no, continue
|
|
pla
|
|
tay
|
|
pla
|
|
tax
|
|
rts
|
|
|
|
.align $100
|
|
|
|
; Hi-res row base address, high byte.
|
|
|
|
ytable_hi:
|
|
.byte $20,$24,$28,$2c,$30,$34,$38,$3c,$20,$24,$28,$2c,$30,$34,$38,$3c
|
|
.byte $21,$25,$29,$2d,$31,$35,$39,$3d,$21,$25,$29,$2d,$31,$35,$39,$3d
|
|
.byte $22,$26,$2a,$2e,$32,$36,$3a,$3e,$22,$26,$2a,$2e,$32,$36,$3a,$3e
|
|
.byte $23,$27,$2b,$2f,$33,$37,$3b,$3f,$23,$27,$2b,$2f,$33,$37,$3b,$3f
|
|
.byte $20,$24,$28,$2c,$30,$34,$38,$3c,$20,$24,$28,$2c,$30,$34,$38,$3c
|
|
.byte $21,$25,$29,$2d,$31,$35,$39,$3d,$21,$25,$29,$2d,$31,$35,$39,$3d
|
|
.byte $22,$26,$2a,$2e,$32,$36,$3a,$3e,$22,$26,$2a,$2e,$32,$36,$3a,$3e
|
|
.byte $23,$27,$2b,$2f,$33,$37,$3b,$3f,$23,$27,$2b,$2f,$33,$37,$3b,$3f
|
|
.byte $20,$24,$28,$2c,$30,$34,$38,$3c,$20,$24,$28,$2c,$30,$34,$38,$3c
|
|
.byte $21,$25,$29,$2d,$31,$35,$39,$3d,$21,$25,$29,$2d,$31,$35,$39,$3d
|
|
.byte $22,$26,$2a,$2e,$32,$36,$3a,$3e,$22,$26,$2a,$2e,$32,$36,$3a,$3e
|
|
.byte $23,$27,$2b,$2f,$33,$37,$3b,$3f,$23,$27,$2b,$2f,$33,$37,$3b,$3f
|
|
|
|
;*******************************************************************************
|
|
;* NEG -- reverse colors on entire hi-res screen *
|
|
;* *
|
|
;* Does a top-to-bottom operation to avoid the Venetian-blind look. *
|
|
;*******************************************************************************
|
|
|
|
; Clear variables
|
|
|
|
NEG:
|
|
txa
|
|
pha
|
|
tya
|
|
pha
|
|
ldx #$00 ; start at the top
|
|
L6DC6:
|
|
stx yc
|
|
jsr SetRowBase ; get address in hptr
|
|
ldy #39 ; for each byte in the row
|
|
L6DCD:
|
|
lda (hptr),Y
|
|
eor #$ff ; reverse colors
|
|
sta (hptr),Y
|
|
dey
|
|
bpl L6DCD
|
|
inx ; next row
|
|
cpx #192 ; done?
|
|
bne L6DC6
|
|
pla
|
|
tay
|
|
pla
|
|
tax
|
|
rts
|
|
|
|
|
|
|
|
.align $100
|
|
|
|
; Maps X coordinate [0,139] to bit.
|
|
|
|
bit_tab:
|
|
.byte $01,$04,$10,$40,$02,$08,$20,$01,$04,$10,$40,$02,$08,$20,$01,$04
|
|
.byte $10,$40,$02,$08,$20,$01,$04,$10,$40,$02,$08,$20,$01,$04,$10,$40
|
|
.byte $02,$08,$20,$01,$04,$10,$40,$02,$08,$20,$01,$04,$10,$40,$02,$08
|
|
.byte $20,$01,$04,$10,$40,$02,$08,$20,$01,$04,$10,$40,$02,$08,$20,$01
|
|
.byte $04,$10,$40,$02,$08,$20,$01,$04,$10,$40,$02,$08,$20,$01,$04,$10
|
|
.byte $40,$02,$08,$20,$01,$04,$10,$40,$02,$08,$20,$01,$04,$10,$40,$02
|
|
.byte $08,$20,$01,$04,$10,$40,$02,$08,$20,$01,$04,$10,$40,$02,$08,$20
|
|
.byte $01,$04,$10,$40,$02,$08,$20,$01,$04,$10,$40,$02,$08,$20,$01,$04
|
|
.byte $10,$40,$02,$08,$20,$01,$04,$10,$40,$02,$08,$20
|
|
|
|
.align $100
|
|
|
|
; Maps X coordinate [0,$139] to byte [0,$39].
|
|
|
|
div7_tab:
|
|
.byte $00,$00,$00,$00,$01,$01,$01,$02,$02,$02,$02,$03,$03,$03,$04,$04
|
|
.byte $04,$04,$05,$05,$05,$06,$06,$06,$06,$07,$07,$07,$08,$08,$08,$08
|
|
.byte $09,$09,$09,$0a,$0a,$0a,$0a,$0b,$0b,$0b,$0c,$0c,$0c,$0c,$0d,$0d
|
|
.byte $0d,$0e,$0e,$0e,$0e,$0f,$0f,$0f,$10,$10,$10,$10,$11,$11,$11,$12
|
|
.byte $12,$12,$12,$13,$13,$13,$14,$14,$14,$14,$15,$15,$15,$16,$16,$16
|
|
.byte $16,$17,$17,$17,$18,$18,$18,$18,$19,$19,$19,$1a,$1a,$1a,$1a,$1b
|
|
.byte $1b,$1b,$1c,$1c,$1c,$1c,$1d,$1d,$1d,$1e,$1e,$1e,$1e,$1f,$1f,$1f
|
|
.byte $20,$20,$20,$20,$21,$21,$21,$22,$22,$22,$22,$23,$23,$23,$24,$24
|
|
.byte $24,$24,$25,$25,$25,$26,$26,$26,$26,$27,$27,$27
|