8bitlenser/c64view/viewer/fli.s
2026-06-14 17:43:12 -07:00

151 lines
3.7 KiB
ArmAsm

; c64view -- FLI multicolor viewer (self-contained)
;
; Re-points the VIC video matrix ($D018) and forces a badline ($D011 yscroll)
; on every visible raster line via a cycle-timed loop, giving per-line colour.
;
; Memory layout of appended data (loads from $4000):
; $4000+L*$400 screen RAM for line L (L=0..7), 1000 bytes each
; $6000 bitmap 8000 (offset $2000 in VIC bank 1)
; $8000 colour RAM 1000 (copied to $D800)
; $83E8 background 1
;
; assembled by viewer/assemble.py via xa
; BASIC autostart, SYS 2061
* = $0801
.word basicend
.word 10
.byte $9e
.byte "2061"
.byte 0
basicend:
.word 0 ; ML begins at $080D
start:
sei
; copy colour RAM $8000 -> $D800 (1024 bytes)
ldx #0
ccopy:
lda $8000,x
sta $d800,x
lda $8100,x
sta $d900,x
lda $8200,x
sta $da00,x
lda $8300,x
sta $db00,x
inx
bne ccopy
; build per-line tables. d018tab = ((line AND 7) << 4) OR $08
; d011tab = $38 OR (line AND 7) = BMM+DEN+RSEL plus yscroll
ldx #0
btab:
txa
and #$07
asl
asl
asl
asl
ora #$08
sta d018tab,x
; yscroll must equal (raster AND 7) to force a badline; the first
; displayed raster is 51, so line x maps to raster 51+x.
txa
clc
adc #$03
and #$07
ora #$38
sta d011tab,x
inx
bne btab
; VIC bank 1 ($4000-$7FFF)
lda $dd00
and #$fc
ora #$02
sta $dd00
lda $83e8
sta $d021 ; background
lda #$00
sta $d020 ; border black
lda #$d8
sta $d016 ; multicolor on
; raster IRQ setup
lda #<irq1
sta $0314
lda #>irq1
sta $0315
lda #$7f
sta $dc0d ; disable CIA timer IRQs
sta $dd0d
lda $dc0d
lda $dd0d
lda #$01
sta $d01a ; enable raster IRQ
lda #$30
sta $d012 ; line 48
lda $d011
and #$7f
sta $d011
asl $d019 ; ack
cli
hang:
jmp hang
; first IRQ, arrives with jitter on line 48, sets up the stabilised one
irq1:
lda #<irq2
sta $0314
lda #>irq2
sta $0315
inc $d012 ; fire again next line (49)
asl $d019 ; ack
tsx
cli
; burn the rest of the line so irq2 fires inside this NOP slide
.dsb 40,$ea ; 40 NOPs
; stabilised IRQ on line 49, runs the FLI loop
irq2:
txs ; restore sp from irq1
; cancel the remaining 0/1-cycle jitter: read the raster twice; the
; branch is 2 or 3 cycles depending on alignment, normalising entry.
lda $d012
cmp $d012
beq jl
jl:
; fixed delay so the first store lands before the c-access window
ldx #$0d
d0: dex
bne d0
nop
nop
ldx #$00
fliloop:
lda d011tab,x ; force badline (yscroll = line&7)
sta $d011
lda d018tab,x ; point video matrix at screen[line]
sta $d018
inx
cpx #200
bne fliloop
; bottom border: leave bitmap on but stop forcing badlines
lda #<irq1
sta $0314
lda #>irq1
sta $0315
lda #$30
sta $d012
asl $d019
jmp $ea81 ; restore regs + RTI
d018tab:
.dsb 256,0
d011tab:
.dsb 256,0