; lenser -- Atari static-playfield slideshow viewer (GR.15 / GR.9 / GR.8). ; ; Self-booting (OS loads this to $2000, JSRs $2006). Steps through NIMAGES ; pictures stored as raw sectors -- image i at sectors BASESEC + i*SPI -- SIO- ; reading SPI sectors and showing each before advancing (key / seconds / both). ; ; DOUBLE BUFFERED so the previous slide stays on screen while the next loads (no ; blank between slides). Two RAM buffers alternate as front/back -- ; buffer 0 -- bitmap $4000/$5000, colour bytes $6000 ; buffer 1 -- bitmap $7000/$8000, colour bytes $9000 ; both kept below $A000 so they are RAM even when the BASIC ROM is enabled. The ; display list's two LMS addresses point at the front buffer; each slide is SIO- ; read into the *back* buffer while the front (the previous picture) keeps ; displaying, then -- during a vertical blank so the change isn't torn -- the LMS ; addresses and colour registers are switched to it. ss_hi = ssbuf*$30 is the ; high-byte offset ($00 buffer 0, $30 buffer 1) added to every buffer address. ; ; The mode is fixed for the whole slideshow, chosen by build-time #defines -- ; DLMODE ANTIC mode byte ($0e GR.15, $0f GR.9/GR.8) ; GPRIOR GTIA priority/mode ($00, or $40 for GR.9) ; COLORMODE colour-register layout (0 GR.15 / 1 GR.9 / 2 GR.8) ; plus WAITMODE/WAITSECS/RATE, NIMAGES, LOOPFLAG, BASESEC, SPI (see assemble.py). colptr = $cb ; zero-page pointer to the back buffer's colours * = $2000 boot: .byte 0 ; flags .byte 0 ; sector count (patched by the ATR writer) .word $2000 ; load address .word binit ; init address (DOSINI) cont: ; $2006 -- OS JSRs here after loading the stub lda #dlist sta $231 ; SDLSTH lda #GPRIOR sta $26f ; GPRIOR lda #$00 sta $22f ; SDMCTL = 0 (blank before the first image only) sta ssidx sta ssbuf ; first slide loads into buffer 0 ssmain: jsr sethi ; ss_hi = ssbuf * $30 jsr readimg ; SIO-load image ssidx into the back buffer ; ---- wait for a vertical blank, then flip to the back buffer ---- ; (the front buffer -- the previous slide -- has stayed on screen) lda $14 vbwait: cmp $14 beq vbwait ; RTCLOK ticked -> we are in the vertical blank ; display-list LMS -- region 1 = base, region 2 = base + $1000 lda #$00 sta lms1 sta lms2 lda #$40 clc adc ss_hi sta lms1+1 ; $40 / $70 lda #$50 clc adc ss_hi sta lms2+1 ; $50 / $80 ; colour bytes are at base + $2000 lda #$00 sta colptr lda #$60 clc adc ss_hi sta colptr+1 ; $60 / $90 #if COLORMODE == 0 ldy #$00 lda (colptr),y sta $2c8 ; COLBAK (value 0) ldy #$01 lda (colptr),y sta $2c4 ; COLPF0 (value 1) ldy #$02 lda (colptr),y sta $2c5 ; COLPF1 (value 2) ldy #$03 lda (colptr),y sta $2c6 ; COLPF2 (value 3) #endif #if COLORMODE == 1 ldy #$00 lda (colptr),y sta $2c8 ; COLBAK = hue (GR.9) #endif #if COLORMODE == 2 ldy #$00 lda (colptr),y sta $2c6 ; COLPF2 background sta $2c8 ; COLBAK border = background ldy #$01 lda (colptr),y sta $2c5 ; COLPF1 foreground #endif lda #$22 sta $22f ; SDMCTL on (a no-op after the first slide) jsr sswait lda ssbuf eor #$01 sta ssbuf ; next slide loads into the other buffer inc ssidx lda ssidx cmp #NIMAGES bcc ssmain #if LOOPFLAG == 1 lda #$00 sta ssidx jmp ssmain #else lda #$00 sta $09 ; clear BOOT? so warmstart enters BASIC jmp $e474 ; warm-start (exit) #endif binit: rts ; ss_hi = ssbuf * $30 (back-buffer high-byte offset -- $00 buffer 0, $30 buffer 1) sethi: ldx #$00 lda ssbuf beq sh0 ldx #$30 sh0: stx ss_hi rts ; ---- SIO read SPI sectors of image ssidx into the back buffer (base+$0000) ---- readimg: lda #BASESEC sta secn+1 ldx ssidx beq rsbuf radd: clc lda secn adc #SPI sta secn bcc ra1 inc secn+1 ra1: dex bne radd rsbuf: lda #$00 sta $0304 ; DBUFLO = $00 lda #$40 clc adc ss_hi sta $0305 ; DBUFHI = $40 / $70 (back buffer base) lda #SPI sta cnt rloop: lda #$31 sta $0300 ; DDEVIC = disk lda #$01 sta $0301 ; DUNIT 1 lda #$52 sta $0302 ; DCOMND R (read) lda #$40 sta $0303 ; DSTATS = read direction lda #$1f sta $0306 ; DTIMLO lda #$80 sta $0308 ; DBYTLO = 128 lda #$00 sta $0309 ; DBYTHI lda secn sta $030a ; DAUX1 sector low lda secn+1 sta $030b ; DAUX2 sector high jsr $e459 ; SIOV clc lda $0304 adc #$80 sta $0304 ; buffer += 128 bcc rb1 inc $0305 rb1: inc secn bne rb2 inc secn+1 rb2: dec cnt bne rloop rts ; ---- wait (returns; defeats attract mode via $4d) ---- sswait: #if WAITMODE == 1 lda #$ff sta $2fc ; clear CH sw1: lda #$00 sta $4d lda $2fc cmp #$ff beq sw1 rts #endif #if WAITMODE == 2 lda #$00 sta $12 sta $13 sta $14 ; reset RTCLOK sw2: lda #$00 sta $4d lda $13 cmp #>(WAITSECS*RATE) bcc sw2 bne sw2d lda $14 cmp #<(WAITSECS*RATE) bcc sw2 sw2d: rts #endif #if WAITMODE == 3 lda #$ff sta $2fc lda #$00 sta $12 sta $13 sta $14 sw3: lda #$00 sta $4d lda $2fc cmp #$ff bne sw3d ; any key ends the slide lda $13 cmp #>(WAITSECS*RATE) bcc sw3 bne sw3d lda $14 cmp #<(WAITSECS*RATE) bcc sw3 sw3d: rts #endif ssidx: .byte 0 ssbuf: .byte 0 ; 0 or 1 -- which buffer the next slide loads into ss_hi: .byte 0 ; ssbuf * $30 (back-buffer high-byte offset) secn: .word 0 cnt: .byte 0 dlist: .byte $70,$70,$70 ; 24 blank scan lines .byte DLMODE+$40 ; LMS + mode lms1: .word $4000 ; region 1 base (patched to the front buffer) .dsb 101,DLMODE .byte DLMODE+$40 ; LMS + mode lms2: .word $5000 ; region 2 base (patched to the front buffer) .dsb 89,DLMODE .byte $41 ; JVB .word dlist