SAVMSC = $58 COLPF0 = $D016 COLPF1 = $D017 COLPF2 = $D018 COLPF3 = $D019 COLBK = $D01A AUDC1 = $D201 DMACTL = $D400 DLISTL = $D402 DLISTH = $D403 WSYNC = $D40A VCOUNT = $D40B NMIEN = $D40E framebuffer = $a000 framebuffer2 = $b000 temp1l = $80 temp1h = $81 temp1 = temp1l temp2l = $82 temp2h = $83 temp2 = temp2l sample_ptrl = $84 sample_ptrh = $85 sample_ptr = sample_ptrl scanline = $86 height = 192 bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 scanline_offset = 31 scanline_max = (lines_per_frame - scanline_offset) / 2 .data .import palette1 .import palette2 .import palette3 .import bitmap .import audio_samples .import audio_samples_end displaylist: ; 24 lines overscan .repeat 3 .byte $70 ; 8 blank lines .endrep ; 192 lines graphics ; ANTIC mode e (160px 2bpp, 1 scan line per line) .byte $4e .addr framebuffer .repeat height / 2 - 1 .byte $0e .endrep .byte $4e .addr framebuffer2 .repeat height / 2 - 1 .byte $0e .endrep .byte $41 ; jump and blank .addr displaylist .code .export start .proc start ; Copy the bitmap into our framebuffer lda #.lobyte(bitmap) sta temp1l lda #.hibyte(bitmap) sta temp1h lda #.lobyte(framebuffer) sta temp2l lda #.hibyte(framebuffer) sta temp2h jsr copy_half_frame ; Second half of bitmap has to be separately aligned lda #.lobyte(framebuffer2) sta temp2l lda #.hibyte(framebuffer2) sta temp2h jsr copy_half_frame ; Set up the audio sample buffer lda #.lobyte(audio_samples) sta sample_ptrl lda #.hibyte(audio_samples) sta sample_ptrh ; Disable display DMA lda #$00 sta DMACTL ; Disable VBI and DLI but allow Reset lda #32 sta NMIEN ; Set up the display list lda #.lobyte(displaylist) sta DLISTL lda #.hibyte(displaylist) sta DLISTH ; 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: lda VCOUNT bne wait_loop lda #(256 - scanline_offset) sta scanline each_scanline: ; it'll fire on unused lines, but harmlessly .macro fake1 jmp fake ; audio sample; low nybble ldx #0 lda (sample_ptr,x) sta temp2 ; high nybble lsr a lsr a lsr a lsr a ; set the volume-only bit ora #$10 pha ; low nybble lda temp2 and #$0f ; set the volume-only bit ora #$10 lda #0 pha .endmacro .macro audio_play ldy #0 lda (sample_ptr),y sta AUDC1 .endmacro .macro inner_scanline ldy scanline inc scanline ; Leisurely memory fetches lda palette1,y pha ldx palette2,y lda palette3,y tay pla ; Wait for horizontal blank sta WSYNC ; Update color registers as fast as possible sta COLPF0 stx COLPF1 sty COLPF2 ; Audio sample ;pla ;lda temp1 ;sta AUDC1 .endmacro inner_scanline audio_play .macro audio_inc ;; toooo slllooowwww ; Increment sample ptr inc sample_ptrl bne audio_cont inc sample_ptrh lda sample_ptrh cmp #.hibyte(audio_samples_end) bne audio_cont lda sample_ptrl cmp #.lobyte(audio_samples_end) bne audio_cont lda #.lobyte(audio_samples) sta sample_ptrl lda #.hibyte(audio_samples) sta sample_ptrh audio_cont: .endmacro ;audio_inc inner_scanline lda VCOUNT cmp #130 ;#130 bne each_scanline ;bne foo jmp wait_start ;foo: ;jmp each_scanline .endproc ; temp1 contains source address ; temp2 contains dest address ; clobbers a/x/y ; incremepts temp1 and temp2 to the end of their regions .proc copy_half_frame ldx #0 copy_loop_lines: ldy #00 copy_loop_bytes: lda (temp1),y sta (temp2),y iny cpy #bytes_per_line bne copy_loop_bytes clc lda temp1l adc #bytes_per_line sta temp1l lda temp1h adc #00 sta temp1h clc lda temp2l adc #bytes_per_line sta temp2l lda temp2h adc #00 sta temp2h inx cpx #(height / 2) bne copy_loop_lines rts .endproc