; Digital Mary Had a Little Lamb ; Jeff Haber ; 29 April 2017 ; Mary Had A Little Lamb ; EDCDEEE ; DDDEGG ; EDCDEEE ; EDDEDC ; dasm MHALL.asm -f3 -v0 -sMHALL.sym -lMHALL.lst -oMHALL.bin ; Attempt to produce a simple in-tune song PROCESSOR 6502 include vcs.h ;============================================================================== ; Define Notes ;============================================================================== C_FIVE = 141 ; C5 is 523.25 Hz. 6507 runs at 1,193,333 Hz. ; 1,193,333/523.25= 2280.6 machine cycles ; Divide by 2 for each half of the square wave ; equals 1140.3 machine cycles ; the wait loops are 8 cycles which means I need to loop ; through approximately 142 times for each half wave ; Subtract 1 for the 5 cycle delay in initial AUDV0 loadings D_FIVE = 125 ; E_FIVE = 112 ; F_FIVE = 105 ; G_FIVE = 94 ; A_FIVE = 83 ; B_FIVE = 74 ; END_SONG = 0 ; WHOLE_NOTE = 255 HALF_NOTE = 128 QUARTER_NOTE = 64 SEG.U VARS ORG $80 ; Start of Cartridge ; Tell DASM to start here. RAM begins at $80 Hold5: ds 1 ; Used to hold wave high or low CurrentNoteDuration: ds 1 ; Quarter note, half note, etc CurrentNote: ds 1 ; Which note the song is on ; define the segment for code SEG CODE ; 2K ROM starts at $F800, 4K ROM starts at $F000 ORG $F800 InitSystem: sei ; Set Interrupt cld ; Clear the decimal bit. ldx #$FF ; Start at the top of the stack txs ; Transfer to the stack lda #0 ClearMem: sta 0,X ; Store zero at (0+X) dex ; Do all of RAM bne ClearMem ; Repeat if we are not down to zero ;============================================================================== ; Load Tune ;============================================================================== LoadTune: lda Song,y ; Load the current note of the song (half wave value) sta Hold5 ; Store it in RAM lda Song,y+1 ; Load the duration of the note sta CurrentNoteDuration ; Store it in RAM Tone: lda #$0F ; 2 set volume high for high part of square wave sta AUDV0 ; 3 ;============================================================================== ; Wave High ;============================================================================== WaitHigh: ; Loop to hold high part of wave dec Hold5 ; 5 bne WaitHigh ; 3 8 8 machine cycles per loop through WaitHighFine: ; Future use for fine tuning notes with a 5 cycle loop ;dex ; Future use for fine tuning notes with a 5 cycle loop ;bne WaitHighFine ; lda Song,y ; 4 Re-load the current note of the song sta Hold5 ; 3 Store it in RAM for low half of the wave ;============================================================================== ; Wave Low ;============================================================================== Interval: lda #$00 ; 2 Turn off volume for bottom of square wave sta AUDV0 ; 3 WaitLow: ; dec Hold5 ; 5 bne WaitLow ; 3 8 Holds 8 with the branch taken WaitLowFine: ;dex ; Future use ;bne WaitLowFine ; ;============================================================================== ; Next CurrentNote? ;============================================================================== dec CurrentNoteDuration ; 5 bne Tone ; 3 ;============================================================================== ; Get Next CurrentNote ;============================================================================== inc CurrentNote ; Increment to next note inc CurrentNote ; Again to skip over duration lda CurrentNote tay ; Put it in index lda Song,y ; Load the note beq StartOver ; if END_SONG then go to reset sta Hold5 ; otherwise, store in RAM lda Song,y+1 ; load the note duration sta CurrentNoteDuration ; Store it in RAM jmp LoadTune ; Back to the top StartOver: ldy #0 sty CurrentNote sty Hold5 sty CurrentNoteDuration jmp LoadTune Song: byte E_FIVE,HALF_NOTE,D_FIVE,HALF_NOTE,C_FIVE,HALF_NOTE byte D_FIVE,HALF_NOTE,E_FIVE,HALF_NOTE,E_FIVE,HALF_NOTE,E_FIVE,WHOLE_NOTE byte D_FIVE,HALF_NOTE,D_FIVE,HALF_NOTE,D_FIVE,WHOLE_NOTE byte E_FIVE,HALF_NOTE,G_FIVE,HALF_NOTE,G_FIVE,WHOLE_NOTE byte E_FIVE,HALF_NOTE,D_FIVE,HALF_NOTE,C_FIVE,HALF_NOTE byte D_FIVE,HALF_NOTE,E_FIVE,HALF_NOTE,E_FIVE,HALF_NOTE,E_FIVE,HALF_NOTE byte E_FIVE,HALF_NOTE,D_FIVE,HALF_NOTE,D_FIVE,HALF_NOTE byte E_FIVE,HALF_NOTE,D_FIVE,HALF_NOTE,C_FIVE,WHOLE_NOTE byte END_SONG ; End of Cartridge ORG $FFFA ; set address to 6507 Interrupt Vectors .WORD InitSystem ; NMI .WORD InitSystem ; RESET .WORD InitSystem ; IRQ