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 audiotemp = $87 frame_counter = $89 height = 160 bytes_per_line = 40 pages_per_frame = 32 lines_per_frame = 262 ;scanline_offset = 31 + (40 - 24) / 2 scanline_offset = 47 scanline_max = (lines_per_frame - scanline_offset) / 2 .data .import audio_samples .import audio_samples_end .import frame1_top .import frame1_bottom .import frame1_palette1 .import frame1_palette2 .import frame1_palette3 .import frame2_top .import frame2_bottom .import frame2_palette1 .import frame2_palette2 .import frame2_palette3 .import displaylist audio_high_byte: .scope .macro byteseq val .repeat 16 .byte val | $10 .endrep .endmacro byteseq $0 byteseq $1 byteseq $2 byteseq $3 byteseq $4 byteseq $5 byteseq $7 byteseq $8 byteseq $9 byteseq $a byteseq $b byteseq $c byteseq $d byteseq $e byteseq $f .endscope .code .export start .proc start ; 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 #$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 bne wait_loop .macro audio_prep ; Y is VCOUNT at entry lda (sample_ptr),y ; 5/6 cyc sta audiotemp ; 3 cyc .endmacro .macro inner_scanline palette1, palette2, palette3 ; it'll fire on unused lines, but harmlessly ldy scanline ; 3 cyc inc scanline ; 5 cyc ; Leisurely memory fetches lda palette1,y ; 5 @FIXME alternate pha ; ...3? ldx palette2,y ; 5 lda palette3,y ; 5 tay pla ; Wait for horizontal blank sta WSYNC ; Update color registers as fast as possible sta COLPF0 stx COLPF1 sty COLPF2 .endmacro .macro audio_play_lo ; 11 cycles lda audiotemp ; 3 cyc and #$0f ; 2 cyc ora #$10 ; 2 cyc sta AUDC1 ; 4 cyc .endmacro .macro audio_play_hi ; 12 cycles ldy audiotemp ; 3 cyc lda audio_high_byte,y ; 5 cyc sta AUDC1 ; 4 cyc .endmacro .macro audio_inc ; Increment sample ptr clc lda sample_ptrl adc #130 sta sample_ptrl lda sample_ptrh adc #0 sta 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 run_frame palette1, palette2, palette3 .scope each_scanline: ;audio_prep inner_scanline palette1, palette2, palette3 ;audio_play_lo inner_scanline palette1, palette2, palette3 ;audio_play_hi ldy VCOUNT ; save for audio lookup cpy #130 bne each_scanline ;audio_inc lda frame_counter eor #1 sta frame_counter jmp wait_start .endscope .endmacro lda #(256 - scanline_offset) sta scanline lda frame_counter bne run_frame2 run_frame frame1_palette1, frame1_palette2, frame1_palette3 run_frame2: run_frame frame2_palette1, frame2_palette2, frame2_palette3 .endproc .proc dli_handler lda #0 sta frame_counter rti .endproc