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 height = 192 bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 .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 for the next even scanline (VCOUNT is scan line / 2, so look for a change) wait_start: lda VCOUNT sta temp1 wait_loop: lda VCOUNT cmp temp1 beq wait_loop each_scanline: lda VCOUNT ; Resynchronize the scanline counter ; it'll fire on unused lines, but harmlessly clc sbc #15 asl tay .macro audio_prep ; 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 pha .endmacro .macro audio_inc ; Increment sample ptr clc lda sample_ptrl adc #1 sta sample_ptrl lda sample_ptrh adc #0 sta 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 .macro inner_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 sta AUDC1 .endmacro audio_prep inner_scanline audio_inc iny inner_scanline ;jmp wait_start 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