; lenser -- C64 cartridge viewer (runs from ROM at $8000), fully self-contained. ; ; Unlike the disk viewer (a PRG at $0801 with the picture appended), this runs ; from a 16K cartridge. It copies the image data block -- appended after this ; code in ROM -- down to $2000 (same layout the disk viewer wants, bitmap at ; $2000, screen $3F40, and for multicolor colram $4328 + bg $4710), programs the ; VIC, and holds the picture. It uses NO KERNAL/IRQ services (a 16K cart hides ; BASIC and the autostart entry runs before the KERNAL fully initialises), so it ; polls the hardware directly -- CIA1 for the keyboard, the raster for timing. ; ; #defines set by viewer/assemble.py -- ; MCMODE 0 = hires, 1 = multicolor ; NPAGES number of 256-byte pages of image data to copy ; WAITMODE 0 forever / 1 until a key / 2 about WAITSECS seconds ; WAITSECS, RATE (frames per second, 50 PAL / 60 NTSC) ; ; assembled by viewer/assemble.py via xa * = $8000 .word cold ; cold-start vector .word cold ; NMI / warm vector .byte $c3,$c2,$cd,$38,$30 ; CBM80 autostart signature SRC = $fb DST = $fd CNT = $02 ; 16-bit frame countdown (seconds mode) cold: sei ldx #$ff txs cld ; map the standard memory layout so BOTH halves of the 16K cart are ; visible -- ROML $8000-$9FFF and ROMH $A000-$BFFF (needs HIRAM=1) -- plus ; I/O at $D000. Set the data latch ($01) BEFORE the DDR ($00): on a cart ; cold-start the latch may be low while the DDR is all-inputs (so the port ; reads the correct map via pull-ups). Enabling the DDR first would drive ; that low latch onto the port, bank ROML out, and crash the next fetch ; (this is exactly what failed in VICE). lda #$37 sta $01 ; LORAM+HIRAM+CHAREN = ROML, ROMH, I/O, KERNAL lda #$2f sta $00 ; now enable the port outputs ; VIC bank 0 ($0000-$3FFF) so the VIC sees our bitmap at $2000 lda #$3f sta $dd02 ; CIA2 port A bits 0-5 = output lda #$c7 sta $dd00 ; bank 0 (bits 0-1 = 11) lda #$0b sta $d011 ; blank during setup ; ---- copy NPAGES of image data from ROM (datasrc) to $2000 ---- lda #datasrc sta SRC+1 lda #$00 sta DST lda #$20 sta DST+1 ldx #NPAGES ldy #$00 dcopy: lda (SRC),y sta (DST),y iny bne dcopy inc SRC+1 inc DST+1 dex bne dcopy ; ---- copy screen RAM $3F40 -> $0400 ---- lda #$40 sta SRC lda #$3f sta SRC+1 lda #$00 sta DST lda #$04 sta DST+1 jsr copy1024 #if MCMODE == 1 ; ---- copy colour RAM $4328 -> $D800 ---- lda #$28 sta SRC lda #$43 sta SRC+1 lda #$00 sta DST lda #$d8 sta DST+1 jsr copy1024 #endif ; ---- program the VIC-II ---- lda #$00 sta $d020 ; border black #if MCMODE == 1 lda $4710 sta $d021 ; background colour lda #$d8 sta $d016 ; multicolor on #endif #if MCMODE == 0 lda #$c8 sta $d016 ; hires #endif lda #$18 sta $d018 ; screen $0400, bitmap $2000 lda #$3b sta $d011 ; bitmap mode, display on ; ---- hold the picture ---- #if WAITMODE == 0 forever: jmp forever #endif #if WAITMODE == 1 lda #$ff sta $dc02 ; CIA1 port A = output (column select) lda #$00 sta $dc03 ; CIA1 port B = input (row read) sta $dc00 ; drive all keyboard columns low kwait: lda $dc01 ; rows; $FF = no key, any key pulls a row low cmp #$ff beq kwait jmp $fce2 ; reset (a 16K cart can't return to BASIC) #endif #if WAITMODE == 2 lda #<(WAITSECS*RATE) sta CNT lda #>(WAITSECS*RATE) sta CNT+1 sloop: sw1: lda $d012 cmp #$fa bne sw1 ; wait until raster reaches line 250 sw2: lda $d012 cmp #$fa beq sw2 ; wait until it leaves -> one frame elapsed lda CNT bne sdec dec CNT+1 sdec: dec CNT lda CNT ora CNT+1 bne sloop jmp $fce2 ; reset #endif copy1024: ldx #4 ldy #0 c1k: lda (SRC),y sta (DST),y iny bne c1k inc SRC+1 inc DST+1 dex bne c1k rts datasrc: ; image data block appended here by the packager