238 lines
7.4 KiB
ArmAsm
238 lines
7.4 KiB
ArmAsm
; lenser -- slideshow viewer (self-contained code; pictures are separate files)
|
|
;
|
|
; Boots first on the disk (LOAD"*",8,1 then RUN) and steps through NIMAGES
|
|
; picture files named "00".."NN", each a PRG that KERNAL-loads to $2000 --
|
|
; $2000 bitmap 8000 (always)
|
|
; $3F40 screen 1000 (always -> copied to the buffer's video matrix)
|
|
; $4328 colram 1000 (multicolor only -> $D800)
|
|
; $4710 background 1 (multicolor only -> $D021)
|
|
; The per-image byte in ss_modes selects hires(0) vs multicolor(1) setup. mono
|
|
; uses the hires path. WAITMODE (viewer/wait.i) selects key / seconds / both.
|
|
;
|
|
; DOUBLE BUFFERED so the previous slide stays on screen while the next loads
|
|
; (no blank between slides). Two VIC banks alternate as front/back buffer:
|
|
; buffer 0 -- VIC bank 0, bitmap $2000, video matrix $0400 ($DD00 bits %11)
|
|
; buffer 1 -- VIC bank 1, bitmap $6000, video matrix $4400 ($DD00 bits %10)
|
|
; Both use $D018=$18 (matrix at bank+$0400, bitmap at bank+$2000); only the
|
|
; $DD00 bank bits differ, so the swap is a single write. Each slide is KERNAL-
|
|
; loaded into the *back* buffer (secondary address 0, so the file's $2000 header
|
|
; is ignored and it lands at the buffer's base) while the front buffer -- the
|
|
; previous picture -- stays displayed; then a bank flip makes it the front.
|
|
; ss_hi = ss_buf*$40 is the high-byte offset ($00 buffer 0, $40 buffer 1) added
|
|
; to every buffer-relative address. Colour RAM ($D800) is shared, so for a
|
|
; multicolor slide it is copied at the swap (a hires slide needs none, and swaps
|
|
; perfectly cleanly).
|
|
;
|
|
; assembled by viewer/assemble.py via xa; the ss_modes table is appended after
|
|
; this file by the generated wrapper, and NIMAGES / LOOPFLAG / WAITMODE etc. are
|
|
; #defined there.
|
|
|
|
; BASIC autostart, SYS 2061
|
|
* = $0801
|
|
.word basicend
|
|
.word 10
|
|
.byte $9e
|
|
.byte "2061"
|
|
.byte 0
|
|
basicend:
|
|
.word 0 ; ML begins at $080D
|
|
|
|
SRC = $fb
|
|
DST = $fd
|
|
|
|
start:
|
|
lda #$00
|
|
sta $9d ; suppress KERNAL LOAD messages
|
|
sta ss_idx ; start at the first image
|
|
sta ss_buf ; first slide loads into buffer 0
|
|
sta $d020 ; border black (once)
|
|
lda #$0b
|
|
sta $d011 ; display off -- the only blank, before slide 0
|
|
|
|
mainloop:
|
|
jsr name_build ; ss_name = "NN" from ss_idx
|
|
jsr setup_hi ; ss_hi = ss_buf * $40
|
|
lda #$ff
|
|
sta $cc ; cursor off (blink can't corrupt $D800)
|
|
|
|
; ---- KERNAL LOAD "NN" into the BACK buffer ($2000 or $6000) ----
|
|
; secondary address 0 -> the file's $2000 header is ignored and the data
|
|
; is loaded to the address passed in .X/.Y, so one data file can serve
|
|
; either buffer. The front buffer stays displayed throughout.
|
|
lda #2
|
|
ldx #<ss_name
|
|
ldy #>ss_name
|
|
jsr $ffbd ; SETNAM
|
|
lda #1
|
|
ldx #8
|
|
ldy #0 ; SA 0 -> load to .X/.Y address
|
|
jsr $ffba ; SETLFS
|
|
ldx #$00 ; load address low = $00
|
|
lda #$20
|
|
clc
|
|
adc ss_hi
|
|
tay ; load address high = $20 + ss_hi
|
|
lda #0 ; 0 = load (not verify)
|
|
jsr $ffd5 ; LOAD
|
|
|
|
; ---- copy screen RAM (base+$1F40) -> this buffer's video matrix ----
|
|
; (into the still-hidden back buffer, so it is invisible)
|
|
lda #$40
|
|
sta SRC
|
|
lda #$3f
|
|
clc
|
|
adc ss_hi
|
|
sta SRC+1 ; SRC = $3F40 / $7F40
|
|
lda #$00
|
|
sta DST
|
|
lda #$04
|
|
clc
|
|
adc ss_hi
|
|
sta DST+1 ; DST = $0400 / $4400
|
|
jsr copy1024
|
|
|
|
; ---- per-image mode -- 0 = hires/mono, 1 = multicolor ----
|
|
ldx ss_idx
|
|
lda ss_modes,x
|
|
beq ss_hires
|
|
|
|
; multicolor -- colour RAM (base+$2328) -> $D800, background from base+$2710
|
|
lda #$28
|
|
sta SRC
|
|
lda #$43
|
|
clc
|
|
adc ss_hi
|
|
sta SRC+1 ; SRC = $4328 / $8328
|
|
lda #$00
|
|
sta DST
|
|
lda #$d8
|
|
sta DST+1
|
|
jsr copy1024
|
|
lda #$10
|
|
sta SRC
|
|
lda #$47
|
|
clc
|
|
adc ss_hi
|
|
sta SRC+1 ; SRC = $4710 / $8710
|
|
ldy #$00
|
|
lda (SRC),y
|
|
sta $d021 ; background colour
|
|
jsr flip_bank ; make the back buffer the front
|
|
lda #$d8
|
|
sta $d016 ; multicolor on
|
|
jmp ss_on
|
|
|
|
ss_hires:
|
|
jsr flip_bank ; make the back buffer the front
|
|
lda #$c8
|
|
sta $d016 ; hires (multicolor off)
|
|
|
|
ss_on:
|
|
lda #$18
|
|
sta $d018 ; matrix bank+$0400, bitmap bank+$2000
|
|
lda #$3b
|
|
sta $d011 ; bitmap mode, display on
|
|
|
|
lda ss_buf
|
|
eor #$01
|
|
sta ss_buf ; next slide loads into the other buffer
|
|
|
|
#include "wait.i"
|
|
|
|
; ---- advance to the next image ----
|
|
inc ss_idx
|
|
lda ss_idx
|
|
cmp #NIMAGES
|
|
bcc ss_go ; still more images
|
|
#if LOOPFLAG == 1
|
|
lda #$00
|
|
sta ss_idx ; wrap around forever
|
|
ss_go:
|
|
jmp mainloop
|
|
#else
|
|
jmp ss_end ; done -> restore and return to BASIC
|
|
ss_go:
|
|
jmp mainloop
|
|
ss_end:
|
|
#endif
|
|
|
|
; ---- restore text mode and return to BASIC ----
|
|
lda $dd00
|
|
ora #$03
|
|
sta $dd00 ; VIC bank 0
|
|
lda #$1b
|
|
sta $d011
|
|
lda #$c8
|
|
sta $d016
|
|
lda #$15
|
|
sta $d018
|
|
lda #$0e
|
|
sta $d020 ; default border (light blue)
|
|
lda #$06
|
|
sta $d021 ; default background (blue)
|
|
lda #$00
|
|
sta $cc
|
|
jsr $e544 ; clear screen
|
|
rts
|
|
|
|
; ss_hi = ss_buf * $40 (high-byte offset for the current back buffer)
|
|
setup_hi:
|
|
ldy #$00
|
|
lda ss_buf
|
|
beq sh_set
|
|
ldy #$40
|
|
sh_set:
|
|
sty ss_hi
|
|
rts
|
|
|
|
; point VIC at the current buffer's bank (buffer 0 -> bank 0, buffer 1 -> bank 1)
|
|
flip_bank:
|
|
lda ss_buf
|
|
bne fb_one
|
|
lda $dd00
|
|
ora #$03
|
|
sta $dd00 ; bank 0 ($0000-$3FFF)
|
|
rts
|
|
fb_one:
|
|
lda $dd00
|
|
and #$fc
|
|
ora #$02
|
|
sta $dd00 ; bank 1 ($4000-$7FFF)
|
|
rts
|
|
|
|
; build the 2-char filename "NN" from ss_idx (0..99)
|
|
name_build:
|
|
lda ss_idx
|
|
ldx #$2f
|
|
sec
|
|
ss_ten:
|
|
inx
|
|
sbc #10
|
|
bcs ss_ten
|
|
adc #10 ; remainder 0..9 (carry was clear on exit)
|
|
ora #$30
|
|
sta ss_name+1 ; ones digit (PETSCII)
|
|
txa
|
|
sta ss_name ; tens digit (PETSCII)
|
|
rts
|
|
|
|
; copy 1024 bytes from (SRC) to (DST)
|
|
copy1024:
|
|
ldx #4
|
|
ldy #0
|
|
cploop:
|
|
lda (SRC),y
|
|
sta (DST),y
|
|
iny
|
|
bne cploop
|
|
inc SRC+1
|
|
inc DST+1
|
|
dex
|
|
bne cploop
|
|
rts
|
|
|
|
ss_idx: .byte 0
|
|
ss_buf: .byte 0 ; 0 or 1 -- which buffer the next slide loads into
|
|
ss_hi: .byte 0 ; ss_buf * $40 (buffer high-byte offset)
|
|
ss_name: .byte $30,$30 ; "00", rebuilt each slide from ss_idx
|
|
; ss_modes table (.byte per image) appended by viewer/assemble.py's wrapper
|