From e09226657b9ea7fa01f9299a8d438be6bcf1cc70 Mon Sep 17 00:00:00 2001 From: Dagen Brock Date: Tue, 11 Dec 2012 13:49:34 -0600 Subject: [PATCH] start of sound code --- applerom.s | 15 ++ festro.s | 395 ++++++++++++++++++++++++++++++++++---------------- sndplay.s | 109 ++++++++++++++ soundengine.s | 127 ++++++++++++++++ 4 files changed, 518 insertions(+), 128 deletions(-) create mode 100644 applerom.s create mode 100644 sndplay.s create mode 100644 soundengine.s diff --git a/applerom.s b/applerom.s new file mode 100644 index 0000000..5ead1a9 --- /dev/null +++ b/applerom.s @@ -0,0 +1,15 @@ + +************************************************** +* Apple Standard Memory Locations +* @todo: finalize as include? +************************************************** +CLRLORES equ $F832 +LORES equ $C050 +TXTSET equ $C051 +MIXCLR equ $C052 +MIXSET equ $C053 +KEY equ $C000 +STROBE equ $C010 +SPEAKER equ $C030 +VBL equ $C02E +RDVBLBAR equ $C019 ;not VBL (VBL signal low) diff --git a/festro.s b/festro.s index e2bc147..aa6a283 100644 --- a/festro.s +++ b/festro.s @@ -26,6 +26,14 @@ srcPtrL equz $02 srcPtrR equz $04 srcPtrD equz $06 + +************************************************** +* Demo Machine initialization +************************************************** + jsr DetectIIgs + jsr InitState + + ************************************************** * Main Demo Controller @@ -40,6 +48,7 @@ DemoMain bra :mainLoop DemoSubroutineTable +* dw HandleKfestLogo dw HandleProdrop dw HandleScan01 @@ -52,9 +61,9 @@ DemoSubroutineTable dw HandleScan03 dw HandleLoResInit - dw HandleFireRatio20 + dw SetFireRatio20 dw HandleFireState1 - dw HandleFireRatio90 + dw SetFireRatio90 dw HandleFireState1 dw HandleFireStateK dw HandleFireState1 @@ -69,10 +78,10 @@ DemoSubroutineTable dw HandleFireState1 dw HandleFireStateYear dw HandleFireState1 - dw HandleFireRatio20 + dw SetFireRatio20 dw HandleFireState1 dw HandleFireState1 - dw HandleFireRatio01 + dw SetFireRatio01 dw HandleFireState1 dw HandleKfestLogo dw HandleMedWait @@ -95,97 +104,6 @@ DemoSubroutineTable dw HandleFinalScreen dw P8Quit -HandleAppleDraw -:mainLoop - lda #1 - sta _appleDone - - lda #AppleLogo - sta srcPtr - lda #>AppleLogo - sta srcPtr+1 - - - lda #_appleOffsetY - sta _currentY - -:lineStart asl - tax - lda LoLineTable,x - sta dstPtr - lda LoLineTable+1,x - sta dstPtr+1 - - lda dstPtr ; add offset - clc - adc #_appleOffsetX - sta dstPtr - bcc :noCarry2 - inc dstPtr+1 -:noCarry2 - ; src = buffer - ; dst = screen - - - ldy #$00 -:drawLoop lda (srcPtr),y -* bra :noMagic - cmp (dstPtr),y - beq :nextChar - stz _appleDone - jsr GetRand - cmp #$00 ; occasional black pixel @todo - beq :noMagic - cmp #$F8 ; had to add in a way to keep it from - blt :noMagic ; getting stuck so now it occasionally puts - lda (srcPtr),y ; the right pixel even when it wasn't -:noMagic sta (dstPtr),y ; found by getrand. (because it's only pseudorandom) - -:nextChar iny - cpy #AppleLogoWidth - bne :drawLoop -:nextLine lda srcPtr - clc - adc #AppleLogoWidth - sta srcPtr - bcc :noCarry1 - inc srcPtr+1 -:noCarry1 - inc _currentY ; handle screen offset - lda _currentY - cmp #AppleLogoHeight+_appleOffsetY - bne :lineStart - -:donePass lda #$5 - jsr SimplerWait - lda _appleDone - beq :mainLoop - lda #$33 - jsr SimplerWait - inc GDemoState - jmp DemoMain - -_currentY db #$00 -_appleDone db #$00 -_appleOffsetX equ 10 -_appleOffsetY equ 8 - - - - - -* done = true -* while !done -* for x = 0 to width -* for y = 0 to height -* load buffer x,y -* cmp screen x,y (plus offsets) -* if (screen = buffer) continue -* done = false -* get rand -* store at screen x,y -* waitvbl - HandleFinalScreen @@ -570,8 +488,11 @@ _defaultStarSpeed equ #$10 inc cmp #8*4+#_defaultStarSpeed bne :slowDown - lda #$40 - jsr SimplerWait + jsr SErandStatic + jsr SErandStatic + jsr SErandStatic + jsr SErandStatic + * speed up again @@ -766,35 +687,34 @@ ScrollLeft HandleLoResInit sta LORES jsr ClearLoRes - inc GDemoState - jmp DemoMain + jmp DemoNext + HandleTextClear sta TXTSET jsr ClearText - inc GDemoState - jmp DemoMain + jmp DemoNext -HandleFireRatio01 +SetFireRatio01 lda #$01 sta GFireRatio - inc GDemoState - jmp DemoMain -HandleFireRatio20 + jmp DemoNext + +SetFireRatio20 lda #$20 sta GFireRatio - inc GDemoState - jmp DemoMain + jmp DemoNext -HandleFireRatio90 +SetFireRatio90 lda #$90 sta GFireRatio - inc GDemoState - jmp DemoMain + jmp DemoNext -HandleFireRatioC0 +SetFireRatioC0 lda #$C0 sta GFireRatio - inc GDemoState + jmp DemoNext + +DemoNext inc GDemoState jmp DemoMain HandleFireState1 @@ -861,7 +781,9 @@ FirePass pha jsr MakeHeat jsr Scroll8 jsr Average8 + jsr VBlank jsr DrawBufFullScreen + jsr RandPop plx pla rts @@ -873,8 +795,15 @@ HandleFireStateYear jsr FirePass3 ; preserves A,X,Y dec bne :loop - inc GDemoState - jmp DemoMain + jmp DemoNext + + + +RandPop jsr GetRandHot + bne :noPop + sta SPEAKER +:noPop rts + * A = count X=lowbyte Y=hibyte FirePass2 @@ -883,6 +812,7 @@ FirePass2 phy jsr MakeHeat jsr Scroll8 + jsr RandPop ply plx jsr DrawSpriteMask @@ -898,6 +828,7 @@ FirePass3 phy jsr MakeHeat jsr Scroll8 + jsr RandPop ply plx jsr DrawSpriteMaskBig @@ -1146,6 +1077,17 @@ DrawStringXYWait beq :done sta (dstPtr),y iny + pha + phx + phy + lda #6 + ldx #1 + ldy #24 + jsr tone + ply + plx + pla + lda _drawWait jsr SimplerWait bra :loop @@ -1444,6 +1386,7 @@ HandleProdrop jmp :prodropUpdate :prodropScan + jsr soundDownReset lda #0 ; start scan at line 0 every time sta _prodropScanLine @@ -1517,18 +1460,25 @@ HandleProdrop jmp DemoMain rts ;; @todo: add rts support to jmp table stuff? -]prodropAnimDone +]prodropAnimDone ;; might rework this.. is there any point in returning to + ;; the main demo loop between scans and such? lda #0 sta _prodropState ; uhg..reset state before exit so can be called again inc GDemoState ; ugh again... not great.. using globals jmp DemoMain + +* This is the animation loop :prodropUpdate lda #0 ; finished = false - sta _prodropAnimDone - + stz _prodropAnimDone :prodropUpdateLoop + lda _prodropSound + bne :noSound + lda #4 + jsr soundDown ;SErandBlip +:noSound stz _prodropSound ; if this flag gets set we call our sound routine lda #16 tax tay @@ -1580,6 +1530,7 @@ HandleProdrop ]dropCharWrite equ *-1 ; we set this differently for GRaphics mode sta (dstPtr),y * breath... holy crap all that just to draw a space at X,Y +* now we draw the character one line down ldy #2 lda (srcPtr),y ; get Y value inc ; move it down @@ -1600,6 +1551,8 @@ HandleProdrop bra ]nextAnimChar ]charFinished + lda #1 ; SET SOUND ANY TIME NEW CHAR DROPS + sta _prodropSound lda #0 sta (srcPtr) bra ]nextAnimChar @@ -1611,6 +1564,7 @@ HandleProdrop sta (srcPtr),y + ]nextAnimChar lda srcPtr clc @@ -1643,6 +1597,30 @@ HandleProdrop _prodropAnimDone db 1 ; any time we find a character it flips this false _prodropScanLine db 0 ; starts scanning at line 0 _prodropState db 0 ; starts with 0, which is scan mode +_prodropSound db 0 ; determine if we should call sound engine + +soundDownReset stz _sndFreq + stz _sndFreq+1 + rts + +_sndFreq dw 0 +_sndInt db 0 +soundDown pha ;interval + ldy _sndFreq + ldx _sndFreq+1 + lda #$8 + jsr tone + pla + cmp _sndInt + beq :intMatch + inc _sndInt + rts +:intMatch stz _sndInt + inc _sndFreq + bcs :inc + rts +:inc inc _sndFreq+1 + rts @@ -1751,6 +1729,117 @@ _swipeMaxWidth db #0 ; set # characters per line in the source buffer _swipeXOffset db #$0 ; screen offset for placement _swipeYOffset db #$0 ; screen offset for placement + + +HandleAppleDraw +:mainLoop + lda #1 + sta _appleDone + + lda #AppleLogo + sta srcPtr + lda #>AppleLogo + sta srcPtr+1 + + + lda #_appleOffsetY + sta _currentY + +:lineStart asl + tax + lda LoLineTable,x + sta dstPtr + lda LoLineTable+1,x + sta dstPtr+1 + + lda dstPtr ; add offset + clc + adc #_appleOffsetX + sta dstPtr + bcc :noCarry2 + inc dstPtr+1 +:noCarry2 + ; src = buffer + ; dst = screen + + + ldy #$00 +:drawLoop lda (srcPtr),y +* bra :noMagic + cmp (dstPtr),y + beq :nextChar + stz _appleDone + jsr GetRand + cmp #$10 ; occasional black pixel @todo + bge :noBlack + lda #0 + bra :noMagic +:noBlack cmp #$FA ; had to add in a way to keep it from + blt :noMagic ; getting stuck so now it occasionally puts + lda (srcPtr),y ; the right pixel even when it wasn't +:noMagic sta (dstPtr),y ; found by getrand. (because it's only pseudorandom) + +:nextChar iny + cpy #AppleLogoWidth + bne :drawLoop +:nextLine lda srcPtr + clc + adc #AppleLogoWidth + sta srcPtr + bcc :noCarry1 + inc srcPtr+1 +:noCarry1 + inc _currentY ; handle screen offset + lda _currentY + cmp #AppleLogoHeight+_appleOffsetY + bne :lineStart + +:donePass lda #$5 + jsr SimplerWait + lda _appleDone + beq :mainLoop + lda #$33 + jsr SimplerWait + inc GDemoState + jmp DemoMain + +_currentY db #$00 +_appleDone db #$00 +_appleOffsetX equ 10 +_appleOffsetY equ 8 + + + + + +* done = true +* while !done +* for x = 0 to width +* for y = 0 to height +* load buffer x,y +* cmp screen x,y (plus offsets) +* if (screen = buffer) continue +* done = false +* get rand +* store at screen x,y +* waitvbl + + + + + + + + + + + + + + + + + ********************* * DEMO ONLY! * x=10,y=10 @@ -1857,6 +1946,10 @@ KeyHandler sta GKeyEvent cmp #"q" beq P8Quit + cmp #"Q" + beq P8Quit + cmp #K_ESC + beq P8Quit ]noKey rts @@ -2392,18 +2485,61 @@ _multiplyResult dw 0000 ************************************************** -* Apple Standard Memory Locations -* @todo: finalize as include? +* See if we're running on a IIgs +* From Apple II Technote: +* Miscellaneous #7 +* Apple II Family Identification ************************************************** -CLRLORES EQU $F832 -LORES EQU $C050 -TXTSET EQU $C051 -MIXCLR EQU $C052 -MIXSET EQU $C053 -KEY EQU $C000 -STROBE EQU $C010 -SPEAKER EQU $C030 -VBL EQU $C02E +DetectIIgs + sec ;Set carry bit (flag) + jsr $FE1F ;Call to the monitor + bcs :oldmachine ;If carry is still set, then old machine +* bcc :newmachine ;If carry is clear, then new machine +:newmachine lda #1 + sta GMachineIIgs + rts +:oldmachine stz GMachineIIgs + rts + +InitState + lda GMachineIIgs + beq :IIe + rts +:IIe rts + +VBlank lda _vblType + bne :IIc + jsr VBlankNormal + rts +:IIc rts + +_vblType db 0 ; 0 - normal, 1 - IIc + +************************************************** +* Wait for vertical blanking interval - IIe/IIgs +************************************************** +VBlankNormal +:loop1 lda RDVBLBAR + bpl :loop1 ; not VBL +:loop lda $c019 + bmi :loop ;wait for beginning of VBL interval + rts + + + + +************************************************** +* Keyboard equates +************************************************** +K_CTRL equ $60 +K_ESC equ $9b +K_DELETE equ $7f +K_SHIFT equ $20 + +K_CTRL_S equ "s"-K_CTRL +K_CTRL_P equ "n"-K_CTRL + + ************************************************** * Lores/Text lines @@ -2455,6 +2591,7 @@ DSEG2 ds 4096 ; Secondary (overflow region?) GKeyEvent db 0 ; keypress - allow subroutines to access GDemoState db 0 ; current demo state +GMachineIIgs db 0 ; machine identification flag ************************************************** @@ -2465,5 +2602,7 @@ ProdropStateUpdate equ #1 ; Does one round of character updates, buffer&screen ProdropStateDone equ #2 ; Really just to let the callee(s) know it's all done use festrodata ; all the sprites and such + use soundengine ; bleep, boops and clicks + use applerom ; softswitch locations, etc lst on sav /code/festro.sys diff --git a/sndplay.s b/sndplay.s new file mode 100644 index 0000000..5a33330 --- /dev/null +++ b/sndplay.s @@ -0,0 +1,109 @@ +************************************************** +* SNDPLAY +* @author Dagen Brock +* @date 2012-12-10 +************************************************** + + org $2000 + typ #$ff + xc off ; 65c02 + xc + lst off + +:noKey lda KEY + cmp #$80 + blt :noKey + bit STROBE + cmp #K_ESC + beq P8Quit + cmp #"+" + beq :slideUp + cmp #"-" + beq :slideDown + cmp #"_" + beq :slideDown + cmp #"]" + beq :play + cmp #"/" + bne :noChangeDur + lda _noteDur + clc + adc #$20 + sta _noteDur + jsr HexPrint + bra :noKey +:slideUp inc _slideNote + lda _slideNote + bra :printBeep +:slideDown dec _slideNote + lda _slideNote + bra :printBeep +:play ldx _noteDur + lda _slideNote + bra :printBeep +:noChangeDur + + + + sec + sbc #"a" + tax + lda _SE_tones,x +:printBeep jsr HexPrint + ldx _noteDur + jsr SENoteAX + bra :noKey +_noteDur db #$20 +_slideNote db 0 + +P8Quit jsr $bf00 + dfb $65 + da qparms + rts +qparms dfb 4 + dfb 0 + da $0000 + dfb 0 + da $0000 + +* print accumulator +HexPrint pha + pha + lsr + lsr + lsr + lsr + tax + lda _chars,x + sta $400 + pla + and #%00001111 + tax + lda _chars,x + sta $401 + pla + rts + +_chars asc "0123456789ABCDEF" + + +************************************************** +* Awesome PRNG thx to White Flame (aka David Holz) +************************************************** +GetRand + lda _randomByte + beq :doEor + asl + bcc :noEor +:doEor eor #$1d +:noEor sta _randomByte + rts + +_randomByte db 0 + +K_ESC equ $9b + + use soundengine ; bleep, boops and clicks + use applerom + lst on + sav /code/sndplay.sys diff --git a/soundengine.s b/soundengine.s new file mode 100644 index 0000000..87b9b01 --- /dev/null +++ b/soundengine.s @@ -0,0 +1,127 @@ +* COSMOS THEME + +Song01 + +_SE_tonesBAD db 255,241,227,214,202,191,180,170,161,152,143,135 + db 128,121,114,108,102,096,091,085,081,076,072,068 + db 064,060,057,054,051,048,045,043,040,038,036,034 + +_SE_tones db NoteG0,NoteGsharp0,NoteA0,NoteBflat0,NoteB0 + db NoteC1,NoteCsharp1,NoteD1,NoteDsharp1,NoteE1 + db NoteF1,NoteFsharp1,NoteG1,NoteGsharp1,NoteA1 + db NoteBflat1,NoteB1,NoteC2,NoteCsharp2,NoteD2 + db NoteDsharp2,NoteE2,NoteF2 + +NoteG0 equ $00 ; because it loops +NoteGsharp0 equ $f0 +NoteA0 equ $e6 +NoteBflat0 equ $d5 +NoteB0 equ $cb ; speculating here on up +NoteC1 equ $c0 +NoteCsharp1 equ $b5 +NoteD1 equ $ac +NoteDsharp1 equ $a3 +NoteE1 equ $99 +NoteF1 equ $90 +NoteFsharp1 equ $89 +NoteG1 equ $80 +NoteGsharp1 equ $79 +NoteA1 equ $72 +NoteBflat1 equ $6c +NoteB1 equ $66 +NoteC2 equ $60 +NoteCsharp2 equ $5b +NoteD2 equ $56 +NoteDsharp2 equ $51 +NoteE2 equ $4c +NoteF2 equ $48 + ; starts to suck here anyway + + +SErandStatic + ldy #$ff +:loop lda SPEAKER + jsr GetRand +* lsr + beq :next +:wait dec + bne :wait +:next dey + bne :loop + rts + + + + +SErandBlip + jsr GetRand + sta _SECURRNOTE + lda #5 + sta _SECURRNOTE+1 + jsr SEplayNote + rts + +* a = freq ... x = dur +SENoteAX + sta _SECURRNOTE + stx _SECURRNOTE+1 + jsr SEplayNote + ;lda _SECURRNOTE+1 + ;ldy _SECURRNOTE + ;ldx #$0 + ;jsr tone + rts + +SEplayNote +:loop lda SPEAKER +:whyWut dey + bne :thar + dec _SECURRNOTE+1 + beq :doneThat +:thar dex + bne :whyWut + ldx _SECURRNOTE + jmp :loop +:doneThat rts + + +_SECURRNOTE db 0,0 ; current note being played (frequency/duration) + + +*------------------------------- +* +* T O N E +* +* In: y-x = pitch lo-hi +* a = duration +* +*------------------------------- +tone + sty :pitch + stx :pitch+1 + +:outloop bit SPEAKER + + ldx #0 +:midloop ldy #0 + +:inloop iny + cpy :pitch + bcc :inloop + + inx + cpx :pitch+1 + bcc :midloop + + sec + sbc #1 + bne :outloop + + rts + +:pitch ds 2 + + + + +