SAVMSC = $58 VDSLST = $200 VDSLSTL = $200 VDSLSTH = $201 COLPF0 = $D016 COLPF1 = $D017 COLPF2 = $D018 COLPF3 = $D019 COLBK = $D01A AUDC1 = $D201 DMACTL = $D400 DLISTL = $D402 DLISTH = $D403 WSYNC = $D40A VCOUNT = $D40B NMIEN = $D40E temp1l = $80 temp1h = $81 temp1 = temp1l temp2l = $82 temp2h = $83 temp2 = temp2l sample_ptrl = $84 sample_ptrh = $85 sample_ptr = sample_ptrl scanline = $86 frame_counter = $89 ;height = 160 height = 192 bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 ;scanline_offset = 31 + (40 - 24) / 2 scanline_offset = 30 scanline_max = (lines_per_frame - scanline_offset) / 2 .data .import frame1_top .import frame1_bottom .import frame1_palette1_even .import frame1_palette1_odd .import frame1_palette2_even .import frame1_palette2_odd .import frame1_palette3_even .import frame1_palette3_odd .import displaylist .code .export start .proc start ; Disable display DMA lda #$00 sta DMACTL ; Disable VBI and DLI but allow Reset lda #$20 sta NMIEN ; Set up the display list lda #.lobyte(displaylist) sta DLISTL lda #.hibyte(displaylist) sta DLISTH ; Set up the DLI handler lda #.lobyte(dli_handler) sta VDSLSTL lda #.hibyte(dli_handler) sta VDSLSTH ; Disable VBI but allow Reset and DLI lda #$a0 sta NMIEN ; Manually wait for first scan line wait_vblank: sta WSYNC lda VCOUNT bne wait_vblank ; Re-enable display DMA lda #$22 sta DMACTL wait_start: ; Wait for the vblank ; Resynchronize the scanline counter wait_loop: ldy VCOUNT ; 4 cycles bne wait_loop ; 2 cycles .macro inner_scanline frame_offset, line_offset ; Y should be VCOUNT at entry ; it'll fire on unused lines, but harmlessly ;ldy scanline ; 3 cyc ;inc scanline ; 5 cyc ; 23-26 cycles before break ; Leisurely memory fetches lda frame1_palette1_even + frame_offset + line_offset - scanline_offset / 2,y ; 4/5 @FIXME alternate pha ; 3 ldx frame1_palette2_even + frame_offset + line_offset - scanline_offset / 2,y ; 4/5 lda frame1_palette3_even + frame_offset + line_offset - scanline_offset / 2,y ; 4/5 tay ; 2 pla ; 3 ; Wait for horizontal blank sta WSYNC ; 4 ; 12 cycles after break ; Update color registers as fast as possible sta COLPF0 ; 4 stx COLPF1 ; 4 sty COLPF2 ; 4 .endmacro .macro run_frame frame_offset .scope ; each scanline is 228 color clocks ; that's 114 CPU cycles ; minus 41-43 for DMA leaves 71-73 clock cycles per line each_scanline_pair: sty scanline ; 3 cycles inner_scanline frame_offset, 0 ; 23-26 cycles before break, 12 cycles after ldy scanline ; 3 cycles inner_scanline frame_offset, 128 ; 23-26 cycles before break, 12 cycles after ; pair cleanup: 6 cycles ldy VCOUNT ; 4 cycles bne each_scanline_pair ; 2 cycles ; frame cleanup: 11 cycles lda frame_counter ; 3 cycles eor #1 ; 2 cycles sta frame_counter ; 3 cycles ;jmp wait_start ; 3 cycles jmp each_frame ; 3 cycles .endscope .endmacro each_frame: run_frame1: run_frame 0 .endproc .proc dli_handler lda #0 sta frame_counter rti .endproc