processor 6502 include macro.h include vcs.h BPM equ 260 LFREQ equ 15600 ;line frequency LFQDIVB equ 8 ;line frequency division base LFQDIV equ LFREQ*60/BPM/4/LFQDIVB ;MainLoop gets called on every 16th STACKH equ 4 ;height of pattern/frequency stack #if (LFQDIV & $10) == 0 echo "LFQDIV & $10 must be non-zero, got",(LFQDIV & $10) #endif SEG.U VARS ORG $80 ;RAM ptrs ds 1 ;This used to be a bunch of pointers to music data, hence the name stackend ds 1 ;End of pattern/frequency stack echo "RAM:", ($100 - *), "bytes left" SEG CODE org $FF80 ;Kernel continued sta HMOVE ldx #LFQDIVB+STELLA-2 ;NOTE: for LFQDIV < 4 it's cheaper to do repeated STA WSYNC KernelInner sta WSYNC ;make visuals more complex after a while lda stackend cmp #6 bcc Simple sax CTRLPF Simple sty COLUP0 sty COLUP1 dex bne KernelInner dey PatTab bne Kernel - $80 ;things start to calm down around here cmp #16 bne MainLoop - $80 sta AUDV1 ;quiet you fool .byte $02 ;JAM .byte %00110001 ;actual start clc bcc Start .byte 0 .byte 0 ;peace and quiet Start cld ldx #0 txa ClearStack FreqTab ;3 dex pha bne ClearStack ;tay ;candidate for removal ;txs ;we're not using the stack ;RAM and TIA clear ;X = A = 0 ;Y and SP unknown MainLoop inc ptrs inc ptrs ;smaller than LDA/CLC/ADC/STA bne StackEndOK inc stackend StackEndOK ;was lda #0 and sta, but sax saves two bytes (X is usually zero-ish here) sax AUDV1 sax HMP0 sax HMP1 lda stackend sec sbc #STACKH bcs StartStartOK lda #0 StartStartOK tax DoNextEntry lda ptrs lsr asr #$0F bcs Silence tay lda PatTab,X GetBit lsr dey bpl GetBit bcc NextEntry ;pattern bit clear? ;pattern bit set lda FreqTab,X sta PF2 sta PF1 sta COLUBK eor #%00110111 ;change color a bit for PF, but keep brightness (sort of) ;also, a lot of the "sound" comes from twiddling these bits sta COLUPF sta AUDC1 eor $7E,X ;makes for an interesting tune when stacken is around 3-5 sta AUDF1 lda #%11011011 sta AUDV1 sta HMP1 sta GRP0 sta GRP1 lda #$30 ;%1101xxxx above == -3 sta HMP0 NextEntry inx cpx stackend bcc DoNextEntry Silence ;check that there isn't any gap between here and the reset vector GAP equ $FFFC-* ldy #LFQDIV ;this also serves as the reset vector Kernel sta WSYNC ;here we wrap around to $FF80 ;the PC ends up being $7100 though #if GAP echo "Expected zero-byte gap, got",GAP #endif