237 lines
4.7 KiB
ArmAsm
Raw Normal View History

2021-03-01 11:47:52 -05:00
; A 123-byte Apple II Lo-res Fake Palette Rotation Demo
; The Apple II has no Palette rotation hardware, so we fake it
; For Lovebyte 2021
; by Vince `deater` Weaver (vince@deater.net) / dSr
; with some help from qkumba
2021-01-09 01:41:44 -05:00
2021-01-09 11:58:12 -05:00
; 151 -- original
; 137 -- optimize generation
2021-01-09 12:26:57 -05:00
; 136 -- align lookup table so we can index it easier
; 130 -- optimize indexing of lookup
; 126 -- run loops backaward
; 124 -- notice X already 0 before plot
; 131 -- use GBASCALC. much faster, but 7 bytes larger
2021-01-09 13:19:52 -05:00
; 129 -- run loop backwards
; 128 -- set color ourselves
; 127 -- overlap color lookup with sine table
2021-01-09 15:00:32 -05:00
; 119 -- forgot to comment out unused
2021-01-09 23:16:54 -05:00
; 121 -- make it use full screen (40x48)
2021-01-09 15:00:32 -05:00
; 149 -- add page flipping
; 144 -- optimize a bit
2021-01-09 15:48:29 -05:00
; 141 -- smc DRAW_PAGE
2021-01-10 15:11:32 -05:00
; 139 -- from qkumba, remove php/plp
; 138 -- from qkumba, remove SAVEX
2021-02-28 22:22:14 -05:00
; 133 -- run from zero page
; 132 -- make lookup 8*sin+7
; 131 -- re-arrange sine table
; 128 -- call into PLOT for MASK seting
2021-03-01 11:47:52 -05:00
; urgh lovebyte wants 124 byte (counts header)
2021-02-28 22:22:14 -05:00
; 127 -- base YY<<16 by adding smc, not by shifting
; 125 -- realize that the top byte wraps so no need to and
; 124 -- re-arrange code to make an CLC unnecessary
2021-03-01 11:47:52 -05:00
; 123 -- qkumba noticed we can use the $FF offset directly in page flip
2021-01-09 15:48:29 -05:00
2021-01-09 01:41:44 -05:00
2021-02-28 22:22:14 -05:00
; zero page
GBASL = $26
GBASH = $27
MASK = $2E
COLOR = $30
;CTEMP = $68
YY = $69
; soft-switches
FULLGR = $C052
PAGE1 = $C054
; ROM routines
PLOT1 = $F80E ;; PLOT at (GBASL),Y (need MASK to be $0f or $f0)
GBASCALC= $F847 ;; take Y-coord/2 in A, put address in GBASL/H ( a trashed, C clear)
SETCOL = $F864 ;; COLOR=A*17
SETGR = $FB40
.zeropage
.globalzp colorlookup,plot_lookup_smc,draw_page_smc,frame_smc,sinetable
2021-01-09 01:41:44 -05:00
;================================
; Clear screen and setup graphics
;================================
plasma:
2021-01-09 01:41:44 -05:00
2021-01-09 23:25:43 -05:00
jsr SETGR ; set lo-res 40x40 mode
bit FULLGR ; make it 40x48
2021-01-09 01:41:44 -05:00
2021-01-09 23:25:43 -05:00
; color = ( 8.0 + 8*sin(x) + 8.0 + 8*sin(y) )/2
; becomes
; color = ( 16 + (sintable[xx&0xf]) + (sintable[yy&0xf])) / 2;
; we only create a 16x16 texture, which we pattern across 40x48 screen
2021-01-09 11:58:12 -05:00
2021-02-28 22:22:14 -05:00
; I've tried re-optimizing this about 10 different ways
; and it never ends up shorter
2021-01-09 12:26:57 -05:00
create_lookup:
ldx #15
2021-02-28 22:22:14 -05:00
create_yloop:
ldy #15
2021-01-09 01:41:44 -05:00
create_xloop:
2021-02-28 22:22:14 -05:00
sec
lda sinetable,X
adc sinetable,Y ; 15+sin(x)+sin(y)
2021-01-09 01:41:44 -05:00
lsr
lookup_smc:
2021-01-09 12:26:57 -05:00
sta lookup ; always starts at $d00
inc lookup_smc+1
2021-01-09 01:41:44 -05:00
2021-02-28 22:22:14 -05:00
dey
2021-01-09 12:26:57 -05:00
bpl create_xloop
2021-02-28 22:22:14 -05:00
dex
2021-01-09 12:26:57 -05:00
bpl create_yloop
2021-01-09 15:00:32 -05:00
; X and Y both $FF
2021-01-09 12:26:57 -05:00
create_lookup_done:
2021-01-09 01:41:44 -05:00
forever_loop:
2021-01-09 12:26:57 -05:00
cycle_colors:
2021-01-09 01:41:44 -05:00
2021-02-28 22:22:14 -05:00
; cycle colors
; instead of advancing entire frame, do slightly slower route
; instead now and just incrememnting the frame and doing the
; adjustment at plot time.
2021-01-09 01:41:44 -05:00
2021-02-28 22:22:14 -05:00
; increment frame
2021-01-09 12:26:57 -05:00
2021-02-28 22:22:14 -05:00
inc frame_smc+1
2021-01-09 23:25:43 -05:00
; set/flip pages
; we want to flip pages and then draw to the offscreen one
flip_pages:
2021-01-09 15:00:32 -05:00
2021-02-28 22:22:14 -05:00
; ldy #0
2021-03-01 11:47:52 -05:00
; iny ; y is $FF, make it 0
2021-01-09 15:48:29 -05:00
lda draw_page_smc+1 ; DRAW_PAGE
2021-03-01 11:47:52 -05:00
bne done_page
dey
2021-01-09 15:00:32 -05:00
done_page:
2021-03-01 11:47:52 -05:00
; ldx PAGE1,Y ; set display page to PAGE1 or PAGE2
ldx $BF56,Y ; PAGE1 - $FF
2021-01-09 15:00:32 -05:00
2021-01-09 23:16:54 -05:00
eor #$4 ; flip draw page between $400/$800
2021-01-09 15:48:29 -05:00
sta draw_page_smc+1 ; DRAW_PAGE
2021-01-09 15:00:32 -05:00
2021-01-09 23:25:43 -05:00
; plot current frame
; scan whole 40x48 screen and plot each point based on
; lookup table colors
plot_frame:
2021-01-09 01:41:44 -05:00
2021-01-09 23:16:54 -05:00
ldx #47 ; YY=47 (count backwards)
2021-01-09 01:41:44 -05:00
plot_yloop:
2021-01-09 15:00:32 -05:00
2021-02-28 22:22:14 -05:00
txa ; get YY into A
pha ; save X for later
2021-01-09 23:25:43 -05:00
lsr ; call actually wants Ycoord/2
2021-02-28 22:22:14 -05:00
php ; save C flag for mask handling
; ugh can't use PLOT trick as it always will draw something
; to PAGE1 even if we don't want to
2021-01-09 23:25:43 -05:00
jsr GBASCALC ; point GBASL/H to address in (A is ycoord/2)
2021-01-09 15:00:32 -05:00
; after, A is GBASL, C is clear
2021-01-09 23:25:43 -05:00
lda GBASH ; adjust to be PAGE1/PAGE2 ($400 or $800)
2021-01-09 15:48:29 -05:00
draw_page_smc:
adc #0
2021-01-09 15:00:32 -05:00
sta GBASH
2021-02-28 22:22:14 -05:00
; increment YY in top nibble of lookup for (yy<<16)+xx
; clc from above, C always 0
lda plot_lookup_smc+1
adc #$10 ; no need to mask as it will oflo and be ignored
sta plot_lookup_smc+1
2021-01-09 15:00:32 -05:00
;==========
ldy #39 ; XX = 39 (countdown)
2021-02-28 22:22:14 -05:00
; sets MASK by calling into middle of PLOT routine
; by Y being 39 draw in a spot that gets over-written
plp
jsr $f806
2021-01-09 01:41:44 -05:00
plot_xloop:
2021-02-28 22:22:14 -05:00
tya ; get XX & 0x0f
2021-01-09 01:41:44 -05:00
and #$f
tax
plot_lookup_smc:
2021-02-28 22:22:14 -05:00
lda lookup,X ; load lookup, (YY*16)+XX
clc
frame_smc:
adc #$00 ; add in frame
2021-01-09 13:19:52 -05:00
2021-01-09 01:41:44 -05:00
and #$f
2021-01-09 23:27:28 -05:00
lsr ; we actually only have 8 colors
2021-01-09 15:48:29 -05:00
2021-01-09 01:41:44 -05:00
tax
2021-02-28 22:22:14 -05:00
2021-01-09 23:27:28 -05:00
lda colorlookup,X ; lookup color
2021-02-28 22:22:14 -05:00
2021-01-09 23:27:28 -05:00
sta COLOR ; each nibble should be same
2021-01-09 01:41:44 -05:00
2021-01-09 23:16:54 -05:00
jsr PLOT1 ; plot at GBASL,Y (x co-ord goes in Y)
2021-01-09 01:41:44 -05:00
2021-01-09 13:19:52 -05:00
dey
bpl plot_xloop
2021-01-09 01:41:44 -05:00
2021-01-10 15:11:32 -05:00
pla ; restore YY
tax
2021-01-09 13:19:52 -05:00
dex
bpl plot_yloop
bmi forever_loop
2021-01-09 01:41:44 -05:00
2021-01-09 13:19:52 -05:00
colorlookup:
2021-02-28 22:22:14 -05:00
2021-01-10 15:11:32 -05:00
; blue
2021-01-09 13:19:52 -05:00
.byte $55,$22,$66,$77,$ff,$77,$55 ; ,$00 shared w sin table
2021-01-09 01:41:44 -05:00
2021-02-28 22:22:14 -05:00
2021-01-09 01:41:44 -05:00
sinetable:
2021-02-28 22:22:14 -05:00
; this is actually (8*sin(x))+7
; re-arranged so starts with $00 for colorlookup overlap
.byte $00,$FF
HACK: ; use the $0200 here for (HACK),Y addressing?
; in the end no way to get Y set properly
.byte $00,$02,$04
.byte $07,$0A,$0C,$0E,$0F,$0E,$0C,$0A
.byte $07,$04,$02
2021-01-09 01:41:44 -05:00
2021-01-09 13:19:52 -05:00
2021-01-09 15:48:29 -05:00
; make lookup happen at page boundary
2021-01-09 01:41:44 -05:00
2021-02-28 22:22:14 -05:00
.org $200
2021-01-09 01:41:44 -05:00
lookup: