Subject: Re: [stella] Scan lines, FotR.... From: Paul Slocum <paul-stella@xxxxxxxxxxxxxx> Date: Wed, 24 Apr 2002 00:46:16 -0500 |
Turns out Dark Mage *also* has 271 scan lines. So it's not anything my code, in particular, is doing, but rather something in Greg's engine.
Where would I look to figure out whether that's something I can reduce to a more NTSC-friendly value (I assume 262 or 263 would be ideal...) ?
;--------------------------------------------------------------------------- ; ; Synthcart by Paul Slocum ; ; Text macros from Dark Mage (Greg Troutman) ; Text code from Stellar Track (Atari) ; ;--------------------------------------------------------------------------- processor 6502 include vcs.h ;--------------------------------------------------------------------------- ; Constants ;--------------------------------------------------------------------------- SETUPDELAY equ #255 ; Amount of balance attenuation BALATT equ 5 ;--------------------------------------------------------------------------- ; RAM Variables ;--------------------------------------------------------------------------- frame equ $80 temp equ frame + 1 ; 16 bit temp temp16L equ temp + 1 temp16H equ temp16L + 1 ; Initialize Flag init equ temp16H + 1 visualBuffer equ init + 1; 46 bytes (overlaps with gfxBuffer and textPointer) ; Text engine variables grfxBuffer equ init + 1 ; 24 bytes ; Array of text pointers to be displayed textPointer equ grfxBuffer + 24 ; 22 bytes visualPointer equ textPointer + 22 ; (overlap) scanSec equ textPointer + 22 EOTflag equ scanSec + 1 backColor equ EOTflag + 1 ; Variable for reading Keyboards keyRead equ backColor + 1 note1 equ keyRead + 1 note2 equ note1 + 1 vol1 equ note2 + 1 vol2 equ vol1 + 1 soundTypeL equ vol2 + 1 soundTypeR equ soundTypeL + 1 sound1 equ soundTypeR + 1 sound2 equ sound1 + 1 soundEffect equ sound2 + 1 arpOn equ soundEffect + 1 arpPattern equ arpOn + 1 scale equ arpPattern + 1 beatBox1 equ scale + 1 beatBox2 equ beatBox1 + 1 beatLock equ beatBox2 + 1 beatBank equ beatLock + 1 beatResetCount equ beatBank + 1 adsrcount equ beatResetCount + 1 adsrSetting equ adsrcount + 1 ; Attack/Decay/Sustain/Release variables adsrLevel1 equ adsrSetting + 1 adsrLevel2 equ adsrLevel1 + 1 adsrEnable1 equ adsrLevel2 + 1 adsrEnable2 equ adsrEnable1 + 1 lastNote1 equ adsrEnable2 + 1 lastNote2 equ lastNote1 + 1 lastSound1 equ lastNote2 + 1 lastSound2 equ lastSound1 + 1 ; Attenuation atten1 equ lastSound2 + 1 atten2 equ atten1 + 1 balAttLeft equ atten2 + 1 balAttRight equ balAttLeft + 1 ; Metrenome stuff beat equ balAttRight + 1 tempoCount equ beat + 1 ; Color cycle counter colorCycle equ tempoCount + 1 arpShort equ colorCycle + 1 ;*** visualMode equ arpShort + 1 easterPointer equ visualMode + 1 visualModeCount equ easterPointer + 1 setupMode equ visualModeCount + 1 setupCount equ setupMode + 1 lastSetupKey equ setupCount + 1 tempo equ lastSetupKey + 1 ; Keyboard key buffers keys1 equ tempo + 1 keypad1 equ keys1 + 1 ; 4 bytes keys2 equ keypad1 + 4 keypad2 equ keys2 + 1 ; 4 bytes tempKeys1 equ keypad2 + 4 tempKeypad1 equ tempKeys1 + 1 ; 4 bytes tempKeys2 equ tempKeypad1 + 4 tempKeypad2 equ tempKeys2 + 1 ; 4 bytes ; 111 bytes 1-25-02 ;--------------------------------------------------------------------------- ; Text Macros ;--------------------------------------------------------------------------- ; a few macros for storing text in a reasonably easy to read format ;--------------------------------------------------------------------------- mac off dc.b <#{0} endm mac wordOff dc.b #<{1} dc.b #>{1} endm mac mapRow wordOff {1} wordOff {2} wordOff {3} wordOff {4} wordOff {5} endm mac EOL dc.b #$FF endm mac EOT dc.b #$FE endm mac line ;must supply 12 characters, though 0's will not be assembled ;------------------------------------------------------------ if {1} != 0 off {1} endif if {2} != 0 off {2} endif if {3} != 0 off {3} endif if {4} != 0 off {4} endif if {5} != 0 off {5} endif if {6} != 0 off {6} endif if {7} != 0 off {7} endif if {8} != 0 off {8} endif if {9} != 0 off {9} endif if {10} != 0 off {10} endif if {11} != 0 off {11} endif if {12} != 0 off {12} endif EOL endm mac blank line #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0 endm ;--------------------------------------------------------------------------- ;--------------------------------------------------------------------------- org $1000 ;--------------------------------------------------------------------------- ;--------------------------------------------------------------------------- ;--------------------------------------------------------------------------- ; Font Data ;--------------------------------------------------------------------------- ; Include the font data here so it is aligned on a page ; boundary without wasting any space ;--------------------------------------------------------------------------- include snthfont.h ;just change the filename to use a different font... ;-------------------------------------------------------------------------- ; Println ;-------------------------------------------------------------------------- ; Most of this subroutine is ripped from Stellar Trak. Feel free to add ; your own comments--it's pretty straightforward ;) and very touchy. Won't ; work if a page boundary appears at certain places, due to excruciating ; cycle dependency, so if modifying the source, you might need an ALIGN ; pseudo-op to correct flubbery text displays. ALIGN 256 will always work, ; but maybe ALIGN 128, ALIGN 64, etc. will also work, and not waste as many ; bytes. ;-------------------------------------------------------------------------- align 256 println ldx #4 sta WSYNC pause nop dex bne pause lda temp lda temp sta HMCLR ldx #$90 ldy #6 ;FONTHEIGHT lda frame and #$01 beq oddFrame jmp evenFrame print1 sta GRP1 lda (grfxBuffer + $8),y sta GRP0 lda (grfxBuffer + $C),y stx HMP0 stx HMP1 sta GRP1 lda (grfxBuffer + $10),y sta GRP0 lda (grfxBuffer + $14),y sta GRP1 sta GRP0 evenFrame dey bmi wrapEven lda (grfxBuffer + $2),y lsr sta GRP0 lda (grfxBuffer +6),y lsr sta.w $001C sta HMOVE lda (grfxBuffer + $A),y lsr sta GRP0 lda (grfxBuffer + $12),y lsr sta temp lda (grfxBuffer + $E),y lsr sta GRP1 lda temp sta GRP0 lda (grfxBuffer + $16),y lsr sta GRP1 oddFrame sta GRP0 lda #$70 sta HMP0 sta HMP1 dey bmi wrapOdd lda (grfxBuffer),y sta GRP0 lda (grfxBuffer + $4),y sta HMOVE jmp print1 wrapEven stx HMP0 stx HMP1 sta WSYNC sta HMOVE jmp print2 wrapOdd sta WSYNC sta temp sta temp print2 lda #$00 sta GRP0 sta GRP1 sta GRP0 rts ; println ;--------------------------------------------------------------------------- ; Start of Program ;--------------------------------------------------------------------------- ; Clear memory, locate character graphics positions and such, ; initialize key memory values, start GameLoop. ;------------------------------------------------------------- Start sei cld ldx #$FF txs lda #0 clear sta 0,x dex bne clear ;--------------------------------------------------------------------------- ; Initialize variables ;--------------------------------------------------------------------------- jsr fontSetup ; debug - start in setup mode ;lda #2 ;sta setupMode ;lda #255 ;sta setupCount ;lda #255 ;sta visualMode lda #11 sta beatBox1 sta beatBox2 lda #2 sta tempo sta soundTypeL sta soundTypeR ; clear keypad buffers jsr clearKeys ; Set initialization flag. ; This stays set until the first frame is drawn. lda #255 sta init sta lastSetupKey lda #startupSoundEffect sta soundEffect ; Set up the text pointers for the status screen jsr printStatus sta lastNote1 sta lastNote2 lda #$0f ;set text color to white sta COLUP0 sta COLUP1 jsr graphicsSetup ;-------------------------------------------------------------------------- ; GameLoop ;-------------------------------------------------------------------------- GameLoop jsr VSync ;start vertical retrace inc frame ;we count frames for alternating graphics displays jsr VBlank ; spare time during screen blank jsr Picture ; draw one screen jsr overscan ; do overscan ; Clear init flag lda #0 sta init jmp GameLoop ;back to top ;--------------------------------------------------------------------------- ; Font Setup ;--------------------------------------------------------------------------- ;the entire font is limited to one page, so we can hard code that page ;value into the MSB position of our graphics buffer ;----------------------------------------------------- fontSetup ldx #23 ;graphics buffer is 24 bytes lda #>_space ;load up the page value for the font grOff sta grfxBuffer,x ;stuff it, won't ever change dex ;back up two bytes dex bpl grOff ;and loop rts ;--------------------------------------------------------------------------- ; Text Engine Graphics Setup ;--------------------------------------------------------------------------- ; use cycle counting to get the GRP registers configured and located ; in exactly the right spot ;--------------------------------------------------------------------------- graphicsSetup sta WSYNC ;newline lda #54 ;triple copy sprites, spaced wide sta NUSIZ0 ;for both player graphic registers sta NUSIZ1 lda #$31 ;draw leftmost and rightmost 2 playfield bits: reflect sta PF0 ;this turns left/right edges black sta CTRLPF ;this makes playfield reflective nop ;wait 2 cycles, we need them get our RESP0/1 right sta VDELP0 ;turn on vertical delay for both players sta VDELP1 sta RESP0 ;mark our left margin here in P0 lda #$D0 ;setup to shift over 3 pixels to the right sta RESP1 ;set P1 sta HMP0 ;prep P0 for his HMOVE lda #$C0 ;setup to shift P1 4 pixels to the right sta HMP1 ;prep P1 for his HMOVE sta WSYNC ;newline sta HMOVE ;anchor them down rts ;-------------------------------------------------------------------------- ; VSync ;-------------------------------------------------------------------------- VSync lda #2 ;bit 1 needs to be 1 to start retrace sta VSYNC ;start retrace sta WSYNC ;wait a few lines sta WSYNC lda #44 ;prepare timer to exit blank period (44) sta TIM64T ;turn it on sta WSYNC ;wait one more sta VSYNC ;done with retrace, write 0 to bit 1 rts ; VSync ;-------------------------------------------------------------------------- ; Easter Check ;-------------------------------------------------------------------------- ; Checks to see if the user has activated ; an easter egg (by playing a special melody) ;-------------------------------------------------------------------------- easterCheck lda note1 cmp #255 beq stay lda sound1 cmp #7 beq contEaster cmp #1 beq contEaster jmp resetPointer contEaster ldx easterPointer lda note1 cmp easterArray,x beq stay inx cmp easterArray,x bne resetPointer cpx #6 beq activateEaster stx easterPointer rts activateEaster lda visualMode beq setupVisualMode lda #0 sta visualMode sta easterPointer ; Disable missles sta ENAM0 sta ENAM1 ; Have to re-setup text graphics since everything's ; messed up in visual mode. jsr fontSetup jsr graphicsSetup ; Set up the text pointers for the status screen jsr printStatus ;set text color to white lda #$0f sta COLUP0 sta COLUP1 rts setupVisualMode lda #100 sta visualModeCount resetPointer lda #0 sta easterPointer rts stay rts ; easterCheck ;-------------------------------------------------------------------------- ; Clear temp Keypad Buffers ;-------------------------------------------------------------------------- ; This function is copied in the upper 4k as clearKeys8k ;-------------------------------------------------------------------------- clearKeys lda #255 sta tempKeypad1; sta tempKeypad1+1; sta tempKeypad1+2; sta tempKeypad1+3; sta tempKeypad2; sta tempKeypad2+1; sta tempKeypad2+2; sta tempKeypad2+3; lda #0 sta tempKeys1 sta tempKeys2 rts ; clearKeys ;-------------------------------------------------------------------------- ; Background Color Cycling ;-------------------------------------------------------------------------- colorCycling ; Decrement the beat reset counter here. ; This makes it so the measure/beat will ; reset when a beat and arp are off for a while. lda beatResetCount beq noDecResetCount dec beatResetCount noDecResetCount lda visualMode bne colorModeA ; Use special bkgd colors for setup mode lda setupCount beq goAhead lda setupMode cmp #1 beq colorModeA lda #62 sta colorCycle rts colorModeA lda #51 sta colorCycle rts goAhead ; Every other frame lda frame and #%00000001 beq skipCycle lda colorCycle cmp #39 bmi skipColorReset lda #0 skipColorReset tax inx stx colorCycle skipCycle rts ; colorCycling ;-------------------------------------------------------------------------- ; Set Sound Text ;-------------------------------------------------------------------------- ; Stores a pointer to sound type text ; in the text pointer array using a lookup ; table. ; - ACC must contain the sound type (255 = beat) ; - X must contain the offset in the text pointer array ; where the text is to be stored. ;-------------------------------------------------------------------------- setSoundText cmp #255 bne notBeat lda #2 notBeat asl ; x2 tay dey ; back off one word. The array's just dey ; set up like this. ; ERRCHECK ; (the Atari will crash if an odd value ; occurs here) ; cpy #22 ; bpl err ; jmp noErr ;err ; ldy #22 ;noErr ; Set sound text lda soundTextArray,y sta textPointer,x inx iny lda soundTextArray,y sta textPointer,x rts ; setSoundText ;-------------------------------------------------------------------------- ; Set Arp Text ;-------------------------------------------------------------------------- ; Stores a pointer to arpeggiator text ; in the text pointer array based on arp settings. ; ; - X must contain the offset in the text pointer array ; where the text is to be stored. ;-------------------------------------------------------------------------- setArpText ; set up arp text from arp settings lda arpShort and #8 sta temp lda arpOn asl adc temp tay lda arpTextArray,y sta textPointer,x iny inx lda arpTextArray,y sta textPointer,x rts ; setArpText ;-------------------------------------------------------------------------- ; Set Tempo Text ;-------------------------------------------------------------------------- ; Stores a pointer to tempo text ; in the text pointer array based on tempo settings. ; ; - X must contain the offset in the text pointer array ; where the text is to be stored. ;-------------------------------------------------------------------------- setTempoText ; set up tempo text from tempo delay lda tempo asl tay lda tempoTextArray,y sta textPointer,x inx iny lda tempoTextArray,y sta textPointer,x rts ; setTempoText ;-------------------------------------------------------------------------- ; Set ADSR Text ;-------------------------------------------------------------------------- ; Stores a pointer to ADSR text ; in the text pointer array based on tempo settings. ; ; - X must contain the offset in the text pointer array ; where the text is to be stored. ;-------------------------------------------------------------------------- setADSRText lda adsrSetting cmp #8 ; tremelo bne notTremText lda #5 notTremText asl tay ;DEBUG ;ldy #2 lda adsrTextArray,y sta textPointer,x inx iny lda adsrTextArray,y sta textPointer,x rts ; setADSRText ;-------------------------------------------------------------------------- ; Set Title Text ;-------------------------------------------------------------------------- ; Stores a pointer to title text. ; Fuji logo flashes with tempo. ; ; - X must contain the offset in the text pointer array ; where the text is to be stored. ;-------------------------------------------------------------------------- setTitleText ; If the beatResetCount is zero, then ; the beat will reset next time it's started, ; so don't flash the tempo ldy #0 lda beatResetCount beq alwaysOn lda beat and #%00001100 lsr tay alwaysOn lda titleTextArray,y sta textPointer,x inx iny lda titleTextArray,y sta textPointer,x rts ; setTitleText ;-------------------------------------------------------------------------- ; Set Arp Pattren ;-------------------------------------------------------------------------- ; Stores a pointer to arp pattern text. ; ; - X must contain the offset in the text pointer array ; where the text is to be stored. ;-------------------------------------------------------------------------- setArpPatternText lda arpPattern asl tay lda arpPatternTextArray,y sta textPointer,x inx iny lda arpPatternTextArray,y sta textPointer,x rts ; setArpPatternText ;-------------------------------------------------------------------------- ; Set Balance and Bank Text ;-------------------------------------------------------------------------- ; Stores a pointer to balance and bank text. ; (Balance and Beat Bank are on the same line) ; ; - X must contain the offset in the text pointer array ; where the text is to be stored. ;-------------------------------------------------------------------------- setBalBankText lda beatBank asl ldy balAttLeft beq checkRightBal ora #8 checkRightBal ldy balAttRight beq copyBalPointer ora #16 copyBalPointer tay lda balBeatTextArray,y sta textPointer,x inx iny lda balBeatTextArray,y sta textPointer,x rts ; setBalText ;-------------------------------------------------------------------------- ; Set Scale Text ;-------------------------------------------------------------------------- ; Stores a pointer to scale text. ; ; - X must contain the offset in the text pointer array ; where the text is to be stored. ;-------------------------------------------------------------------------- setScaleText lda scale asl tay lda scaleTextArray,y sta textPointer,x inx iny lda scaleTextArray,y sta textPointer,x rts ; setScaleText ;-------------------------------------------------------------------------- ; Set Text ;-------------------------------------------------------------------------- ; Stores text pointer in text pointer array. ; ; - ACC must be low byte ; - X must be high byte ; - Y must by text pointer array offset ;-------------------------------------------------------------------------- setText sta textPointer,y txa iny sta textPointer,y rts ; setText ;-------------------------------------------------------------------------- ; Print Status Screen ;-------------------------------------------------------------------------- ; This sets the text pointers to display the ; status screen (the information shown while ; playing the synthcart ;-------------------------------------------------------------------------- printStatus ldx #0 jsr setTitleText ldx #2 jsr setADSRText ldx #4 jsr setTempoText ldx #6 jsr setArpText ldx #8 jsr setArpPatternText ldx #10 jsr setScaleText ldx #12 jsr setBalBankText lda #<tx_leftsound ldx #>tx_leftsound ldy #14 jsr setText ldx #16 lda soundTypeL jsr setSoundText lda #<tx_rightsound ldx #>tx_rightsound ldy #18 jsr setText ldx #20 lda soundTypeR jsr setSoundText rts ; setupStatus ;-------------------------------------------------------------------------- ; Print Setup Screen B ;-------------------------------------------------------------------------- ; This sets the text pointers to display the ; setup screen B, where the user changes ; synthesizer settings ;-------------------------------------------------------------------------- printSetupB lda #<tx_setupB1 sta textPointer + 0 lda #>tx_setupB1 sta textPointer + 1 lda #<tx_setupB2 sta textPointer + 2 lda #>tx_setupB2 sta textPointer + 3 lda #<tx_setupB3 sta textPointer + 4 lda #>tx_setupB3 sta textPointer + 5 lda #<tx_setupB4 sta textPointer + 6 lda #>tx_setupB4 sta textPointer + 7 lda #<tx_setupB5 sta textPointer + 8 lda #>tx_setupB5 sta textPointer + 9 lda #<tx_setupB6 sta textPointer + 10 lda #>tx_setupB6 sta textPointer + 11 lda #<tx_setupB7 sta textPointer + 12 lda #>tx_setupB7 sta textPointer + 13 lda #<tx_setupB8 sta textPointer + 14 lda #>tx_setupB8 sta textPointer + 15 ldx #16 jsr setADSRText ldx #18 jsr setTempoText ldx #20 jsr setArpText rts ; printSetupB ;-------------------------------------------------------------------------- ; Print Setup Screen A ;-------------------------------------------------------------------------- ; This sets the text pointers to display the ; setup screen A, where the user changes ; synthesizer settings ;-------------------------------------------------------------------------- printSetupA lda #<tx_setupA1 sta textPointer + 0 lda #>tx_setupA1 sta textPointer + 1 lda #<tx_setupA2 sta textPointer + 2 lda #>tx_setupA2 sta textPointer + 3 lda #<tx_setupA3 sta textPointer + 4 lda #>tx_setupA3 sta textPointer + 5 lda #<tx_setupA4 sta textPointer + 6 lda #>tx_setupA4 sta textPointer + 7 lda #<tx_setupA5 sta textPointer + 8 lda #>tx_setupA5 sta textPointer + 9 lda #<tx_setupA6 sta textPointer + 10 lda #>tx_setupA6 sta textPointer + 11 lda #<tx_setupA7 sta textPointer + 12 lda #>tx_setupA7 sta textPointer + 13 lda #<tx_setupA8 sta textPointer + 14 lda #>tx_setupA8 sta textPointer + 15 ldx #16 jsr setArpPatternText ldx #18 jsr setScaleText ldx #20 jsr setBalBankText rts ; printSetupA ;-------------------------------------------------------------------------- ; Print Visual Mode ;-------------------------------------------------------------------------- ; Displays a message that visual mode is being activated ;-------------------------------------------------------------------------- printVisualMode lda #<tx_blank sta textPointer + 0 sta textPointer + 2 sta textPointer + 4 sta textPointer + 6 sta textPointer + 8 sta textPointer + 10 sta textPointer + 12 sta textPointer + 14 sta textPointer + 16 lda #>tx_blank sta textPointer + 1 sta textPointer + 3 sta textPointer + 5 sta textPointer + 7 sta textPointer + 9 sta textPointer + 11 sta textPointer + 13 sta textPointer + 15 sta textPointer + 17 lda #<tx_visual1 ldx #>tx_visual1 ldy #18 jsr setText lda #<tx_visual2 ldx #>tx_visual2 ldy #20 jsr setText rts ; printVisualMode ;-------------------------------------------------------------------------- ; Handle Setup Mode Keys ;-------------------------------------------------------------------------- ; If in setup mode, deal with setup keys ; pressed. Must be called after readKeyboards. ;-------------------------------------------------------------------------- handleSetupKeys lda setupCount beq noSetup ldx setupMode dex beq setup1 dex bne noSetup jsr handleSetup2 rts setup1 jsr handleSetup1 rts noSetup rts ; handleSetupKeys ;-------------------------------------------------------------------------- ; Handle Switches ;-------------------------------------------------------------------------- ; Read and respond to console switches. ; Set up sound types. ; Display sound information on screen. ;-------------------------------------------------------------------------- handleSwitches ; *** Choose Sound from B&W, DF1, and DF2 switches *** lda SWCHB and #%00001000 lsr sta temp lda SWCHB and #%11000000 clc rol rol rol ora temp ; Now ACC = ; ; BRL ; W ; 00000111 ; Get the two sounds from the sound pair arrays tax lda soundPairArrayL,x sta soundTypeL lda soundPairArrayR,x sta soundTypeR ; Clear the selected beats if ; beatbox is de-selected cmp #255 beq noBeatReset lda #11 sta beatBox1 sta beatBox2 noBeatReset ; Game Select Switch (activates Advanced Setup Mode for a few seconds) ;-------------------------------------------------------------------------- lda SWCHB and #%000000010 bne noSel lda setupCount bne noSoundB lda #setupActEffect sta soundEffect noSoundB lda #255 sta setupCount lda #2 sta setupMode noSel ; Game Reset Switch (activates Setup Mode for a few seconds) ;-------------------------------------------------------------------------- lda SWCHB and #%000000001 bne noRes lda setupCount bne noSoundA lda #setupActEffect sta soundEffect noSoundA lda #255 sta setupCount lda #1 sta setupMode noRes ; Update display ;-------------------------------------------------------------------------- updateDisplay ; check setup mode timer to see if setup mode is active lda setupCount beq statusScreen ; Count down dec setupCount bne noSetupDeactivateSound lda #setupDeaEffect sta soundEffect noSetupDeactivateSound ; Figure out which setup mode is enabled lda setupMode cmp #1 beq goPrintSetupB ; Don't print test if visual mode is active lda visualMode bne handleVisualMode jsr printSetupA jmp handleVisualMode goPrintSetupB ; Don't print test if visual mode is active lda visualMode bne handleVisualMode jsr printSetupB jmp handleVisualMode ; Setup mode is not active, so print the status screen statusScreen ; Don't print test if visual mode is active lda visualMode bne handleVisualMode jsr printStatus ; Handle Visual Mode ;-------------------------------------------------------------------------- handleVisualMode ; If visualModeCount is >0 then ; display "light show mode" message. ldx visualModeCount bne goVisualMode jmp endHandleSwitches goVisualMode dex stx visualModeCount beq activateVisualMode jsr printVisualMode jmp endHandleSwitches ; Time has expired so switch to visual mode activateVisualMode lda #255 sta visualMode ; The visual color buffer shares space with the ; text buffers, so clear them out before ; visual mode starts. lda #0 ldx #45 clearVisual sta visualBuffer,x dex bne clearVisual sta visualBuffer,x endHandleSwitches rts ; handleSwitches ;-------------------------------------------------------------------------- ; Handle Setup 1 ;-------------------------------------------------------------------------- ; Deal with keys pressed in setup mode. ; Changes synth settings. ; Don't call this unless the synth is in setup mode ; since it will clear the keyboard buffers. ;-------------------------------------------------------------------------- handleSetup1 lda keypad1 cmp #255 bne handleKeys lda keypad2 cmp #255 bne handleKeys ; Only unmark on odd frames (long story...) lda keyRead and #%00000001 beq noLastKeyReset ; Unmark the "last key" indicating that the key was released lda lastSetupKey and #%01111111 sta lastSetupKey noLastKeyReset ; No keys pressed -- quit jmp quitHandleSetup endSetup ; If a key is pressed twice in a row, quit setup mode lda #0 sta setupCount lda #255 sta lastSetupKey ; Setup mode de-activate sound effect lda #setupDeaEffect sta soundEffect jmp quitHandleSetup handleKeys ; reset setup mode delay ldx #255 stx setupCount ; Handle the tempo keys first since they're the ; only ones that won't close setup if pressed twice cmp #0 bne notTempUp ora #%10000000 cmp lastSetupKey beq noDecTempo sta lastSetupKey lda tempo beq noDecTempo ; Key press sound effect ldx #setupSelectEffect stx soundEffect dec tempo lda #0 sta tempoCount noDecTempo jmp quitHandleSetup notTempUp cmp #3 bne notTempDown ora #%10000000 cmp lastSetupKey beq noIncTempo sta lastSetupKey lda tempo cmp #9 beq noIncTempo ; Key press sound effect ldx #setupSelectEffect stx soundEffect inc tempo noIncTempo jmp quitHandleSetup notTempDown bit lastSetupKey bmi noKeyHitSound ; Key press sound effect ldx #setupSelectEffect stx soundEffect noKeyHitSound ; Check to see if the same key was pressed twice in a row cmp lastSetupKey beq endSetup ; Mark the new "last key" ora #%10000000 sta lastSetupKey and #%01111111 cmp #4 bne notArp32 lda #3 sta arpOn jmp quitHandleSetup notArp32 cmp #1 bne notArp16 lda #2 sta arpOn jmp quitHandleSetup notArp16 cmp #2 bne notArp8 lda #1 sta arpOn jmp quitHandleSetup notArp8 cmp #5 bne notArpOff lda #0 sta arpOn jmp quitHandleSetup notArpOff cmp #9 bne notTremA lda #4 sta adsrSetting jmp quitHandleSetup notTremA cmp #7 bne notLongRelease lda #2 sta adsrSetting lda #0 sta adsrLevel1 sta adsrLevel2 jmp quitHandleSetup notLongRelease cmp #6 bne notTremS lda #8 sta adsrSetting jmp quitHandleSetup notTremS cmp #8 bne notSlowAtk lda #1 sta adsrSetting jmp quitHandleSetup notSlowAtk cmp #10 bne notSlowAtkRel lda #3 sta adsrSetting lda #0 sta adsrLevel1 sta adsrLevel2 jmp quitHandleSetup notSlowAtkRel cmp #11 bne notNormAtk lda #0 sta adsrSetting jmp quitHandleSetup notNormAtk quitHandleSetup ; Clear keypad buffers ldx #255 stx keypad1 stx keypad1+1 stx keypad1+2 stx keypad1+3 stx keypad2 stx keypad2+1 stx keypad2+2 stx keypad2+3 rts ; handleSetup ;-------------------------------------------------------------------------- ; Handle Setup 2 ;-------------------------------------------------------------------------- ; Deal with keys pressed in setup mode. ; Changes synth settings. ; Don't call this unless the synth is in setup mode ; since it will clear the keyboard buffers. ;-------------------------------------------------------------------------- handleSetup2 lda keypad1 cmp #255 bne handleKeys2 lda keypad2 cmp #255 bne handleKeys2 ; Only unmark on odd frames (long story...) lda keyRead and #%00000001 beq noLastKeyReset2 ; Unmark the "last key" indicating that the key was released lda lastSetupKey and #%01111111 sta lastSetupKey noLastKeyReset2 ; No keys pressed -- quit jmp quitHandleSetup2 endSetup2 ; If a key is pressed twice in a row, quit setup mode lda #0 sta setupCount lda #255 sta lastSetupKey ; Setup mode de-activate sound effect lda #setupDeaEffect sta soundEffect jmp quitHandleSetup2 handleKeys2 ; reset setup mode delay ldx #255 stx setupCount bit lastSetupKey bmi noKeyHitSound2 ; Key press sound effect ldx #setupSelectEffect stx soundEffect noKeyHitSound2 ; Check to see if the same key was pressed twice in a row cmp lastSetupKey beq endSetup2 ; Mark the new "last key" ora #%10000000 sta lastSetupKey and #%01111111 ; Check keys/set settings... cmp #0 bne notArpUp lda #0 sta arpPattern jmp quitHandleSetup2 notArpUp cmp #1 bne notArpDown lda #1 sta arpPattern jmp quitHandleSetup2 notArpDown cmp #2 bne notArpMix lda #2 sta arpPattern jmp quitHandleSetup2 notArpMix cmp #6 bne notBeatBank1 lda #0 sta beatBank jmp quitHandleSetup2 notBeatBank1 cmp #7 bne notBeatBank2 lda #1 sta beatBank jmp quitHandleSetup2 notBeatBank2 cmp #8 bne notBeatBank3 lda #2 sta beatBank jmp quitHandleSetup2 notBeatBank3 cmp #3 bne notMajorScale lda #0 sta scale jmp quitHandleSetup2 notMajorScale cmp #4 bne notMinorScale lda #1 sta scale jmp quitHandleSetup2 notMinorScale cmp #5 bne notAtonalScale lda #2 sta scale jmp quitHandleSetup2 notAtonalScale cmp #9 bne notLeftBal lda #0 sta balAttLeft lda #BALATT sta balAttRight jmp quitHandleSetup2 notLeftBal cmp #10 bne notCentBal lda #0 sta balAttLeft sta balAttRight jmp quitHandleSetup2 notCentBal cmp #11 bne notRightBal lda #BALATT sta balAttLeft lda #0 sta balAttRight jmp quitHandleSetup2 notRightBal quitHandleSetup2 ; Clear keypad buffers ldx #255 stx keypad1 stx keypad1+1 stx keypad1+2 stx keypad1+3 stx keypad2 stx keypad2+1 stx keypad2+2 stx keypad2+3 rts ; handleSetup2 ;-------------------------------------------------------------------------- ; Sound Effect Player ;-------------------------------------------------------------------------- ; This function plays sound effects to indicate the status ; of the machine. Sound effects are selected by setting ; soundEffect to the start of a sound in the ; sound effect array. ;-------------------------------------------------------------------------- soundEffectPlayer ldx soundEffect lda soundEffectArray,x cmp #255 beq noSoundEffects sta note1 inx stx soundEffect lda #5 sta sound1 lda #7 sta vol1 noSoundEffects rts ; soundEffectPlayer ;-------------------------------------------------------------------------- ; Voice Manager ;-------------------------------------------------------------------------- ; This funtion calls the standard player, argpeggiator, and beat box ; based on which setup is selected. It also designates voices ; to the players based on some rules: ; ; 1) If keys are pressed on both keyboards, then each sound ; generator gets one voice. ; 2) If multiple keys are pressed on a keyboard and none on the other, ; the sound generator can have both voices. ; 3) The arpeggiator gets at most one voice. ; ; Note that the BeatBox is only allowed on soundR ;-------------------------------------------------------------------------- voiceManager lda soundTypeR cmp #255 beq beatBoxPlay lda arpOn bne arpPlay ; Standard Play on both keypads ;-------------------------------------------------------------------------- standard lda keypad1 cmp #255 beq twoOnTwo lda keypad2 cmp #255 beq twoOnOne oneOnEach lda #<keypad1 ; Use keypad 1 sta temp16L lda #0 sta temp16H ldy #1 ; One voice available ldx #0 ; Osc 1 jsr standardPlayer lda #<keypad2 ; Use keypad 2 sta temp16L lda #0 sta temp16H ldy #1 ; One voice available ldx #1 ; Osc 2 jsr standardPlayer rts twoOnOne lda #<keypad1 ; Use keypad 1 sta temp16L lda #0 sta temp16H ldy #2 ; Two voices available ldx #0 ; Osc1 primary jsr standardPlayer rts twoOnTwo lda #<keypad2 ; Use keypad 2 sta temp16L lda #0 sta temp16H ldy #2 ; Two voices available ldx #1 ; Osc2 primary jsr standardPlayer rts ; Arp on both keypads ;-------------------------------------------------------------------------- arpPlay lda #<keypad2 ; Use keypad 1 sta temp16L lda #0 sta temp16H lda #1 ; Osc1 jsr arp lda #<keypad1 ; Use keypad 2 sta temp16L lda #0 sta temp16H lda #0 ; Osc2 jsr arp rts ; Standard play on left, Beatbox on right ;-------------------------------------------------------------------------- beatBoxPlay lda arpOn bne beatAndArpPlay lda keypad1 cmp #255 beq checkRelease lda beatBox1 cmp #11 beq twoOnPlayer jmp beatAndPlayer ; Before going to twoOnBeat, need to make ; sure that long release isn't on and fading ; out a release. checkRelease ; Check to see if a long ; release is being held lda adsrSetting and #2 beq twoOnBeat ldx adsrLevel1 beq twoOnBeat beatAndPlayer lda #<keypad1 ; Use keypad 1 sta temp16L lda #0 sta temp16H ldy #1 ; One voice available ldx #0 ; Osc 1 jsr standardPlayer lda #1 ; One voice jsr callBeatBox rts twoOnPlayer lda #<keypad1 ; Use keypad 1 sta temp16L lda #0 sta temp16H ldy #2 ; Two voices available ldx #0 ; Osc 1 jsr standardPlayer rts twoOnBeat lda #2 ; Two voices available jsr callBeatBox rts ; Arp on left, Beatbox on right ;-------------------------------------------------------------------------- beatAndArpPlay lda keypad1 cmp #255 bne beatOneArpOne ; Check to see if a long ; release is being held lda adsrSetting and #2 beq twoOnBeat ldx adsrLevel1 beq twoOnBeat beatOneArpOne lda #<keypad1 ; Use keypad 1 sta temp16L lda #0 ; page 1/osc1 sta temp16H jsr arp lda #1 ; One voice jsr callBeatBox rts ; voiceManager ;-------------------------------------------------------------------------- ; Tempo ;-------------------------------------------------------------------------- ; Generates tempo based on set tempo ;-------------------------------------------------------------------------- handleTempo ; Now deal with the tempo ; increment the tempo counter inc tempoCount ; Check to see if the tempo counter ; has reached the point where the beat counter ; will be incremented lda tempo clc adc #4 cmp tempoCount bne quitTempo ; reset the tempo counter lda #0 sta tempoCount ; increment the beat ldx beat inx stx beat cpx #128 bne quitTempo lda #0 sta beat quitTempo rts ; tempo ;-------------------------------------------------------------------------- ; Arpeggiator ;-------------------------------------------------------------------------- ; Effectively two arpeggiators -- can arpeggiate both keypads ; simultaneously. Each supports up to 4 points. ; - temp16 should contain the address of the keypad array ; - ACC should contain the primary oscillator number (0 or 1) ;-------------------------------------------------------------------------- arp tax lda soundTypeL,x sta sound1,x ldy #0 lda (temp16L),y cmp #255 bne keyCount sta note1,x ; enable adsr control for arp lda #255 sta adsrEnable1,x rts ; Get number of keys pressed keyCount lda #255 sta beatResetCount txa pha ; Get the location of the number of keys ; variable (right before key array) ldx temp16L dex ; Get number of keys pressed ldy 0,x playArp ; # of keys pressed dey tya asl asl asl sta temp clc lda beat and #%00011111 ; Check arp rate (8/16/32) and shift accordingly ldx arpOn cpx #3 beq doneShifting lsr cpx #2 beq doneShifting lsr doneShifting and #%00000111 clc ; keyspressed*8 + beat = arpArray index adc temp asl asl adc arpPattern tax lda arpUpArray,x tay lda (temp16L),y asl asl clc adc scale tax pla tay lda soundData1,x sta note1,y ; Handle balance setting lda balAttLeft,y adc atten1,y sta atten1,y ; enable adsr control for arp lda #255 sta adsrEnable1,y endArp rts ; arp ;-------------------------------------------------------------------------- ; Standard Player ;-------------------------------------------------------------------------- ; For normal playing of notes from keyboard ; data (no arpeggiator or beat box) ; - temp16 should contain the address of the keypad array ; - Y should contain the number of voices available (1 or 2) ; - x should contain the primary oscillator number (0 or 1) ; - ACC should contain the attenuation setting ; If two oscillators are available, the other oscillator ; will be used if a second key is pressed on the keypad. ;-------------------------------------------------------------------------- standardPlayer lda balAttLeft,x sta temp cpy #2 bne primaryOsc secondOsc lda soundTypeL,x pha txa eor #%00000001 tax pla sta sound1,x ldy #1 lda (temp16L),y cmp #255 beq noSound2 asl asl clc adc scale tay lda soundData1,y noSound2 sta note1,x ; Handle balance setting lda temp adc atten1,x sta atten1,x ; enable adsr control for standard play lda #255 sta adsrEnable1,x txa eor #%00000001 tax primaryOsc ldy #0 lda (temp16L),y cmp #255 beq noSound1 asl asl clc adc scale tay lda soundData1,y noSound1 sta note1,x ; Handle balance setting lda temp adc atten1,x sta atten1,x ; enable adsr control for standard play lda #255 sta adsrEnable1,x lda soundTypeL,x sta sound1,x rts ; standardPlayer ;-------------------------------------------------------------------------- ; VBlank ;-------------------------------------------------------------------------- ; Handle user input and display setup during the VBLANK period ;-------------------------------------------------------------------------- VBlank ; Read keyboards here. jsr readKeyboards jsr handleSetupKeys ; If the tempo is calculated once per frame, the tempo change ; increments are too large. So I chose to count the tempo ; twice per frame. The tempo is checked and the voices setup here, ; but the notePlayer is called about halfway through the screen draw ; to keep the tempo steady. jsr handleTempo jsr calcVolume jsr easterCheck jsr soundEffectPlayer jsr colorCycling rts ; VBlank ;-------------------------------------------------------------------------- ; Overscan ;-------------------------------------------------------------------------- ; I ran out of time in VBlank, so I'm doing some things during overscan ;-------------------------------------------------------------------------- overscan sta WSYNC lda #33 ; Use the timer to make sure overscan takes (34) sta TIM64T ; 30 scan lines. 29 scan lines * 76 = 2204 / 64 = 34.4 jsr handleSwitches ldx #255 stx adsrEnable1 stx adsrEnable2 jsr voiceManager jsr calcVolume jsr soundEffectPlayer jsr notePlayer jsr handleTempo ldx #255 stx adsrEnable1 stx adsrEnable2 jsr voiceManager endOS lda INTIM ; We finished, but wait for timer bne endOS ; by looping till zero sta WSYNC ; End last scanline lda #$82 sta VBLANK lda #$02 sta VBLANK rts ; overscan ;-------------------------------------------------------------------------- ; Note Player ;-------------------------------------------------------------------------- ; Actually plays assigned notes using assigned voices ;-------------------------------------------------------------------------- notePlayer ; Sound type ldx sound1 ldy sound2 stx AUDC0 sty AUDC1 ; Frequency ldx note1 ldy note2 stx AUDF0 sty AUDF1 ; Volume ldx vol1 ldy vol2 stx AUDV0 sty AUDV1 rts ; notePlayer ;-------------------------------------------------------------------------- ; Show Visuals ;-------------------------------------------------------------------------- ; Alternative draw screen function for visual mode ;-------------------------------------------------------------------------- showVisuals pictureLoop2 lda INTIM ;check timer for end of VBLANK period bne pictureLoop2 ;loop until it reaches 0 lda #0 sta COLUBK lda #$80 sta VBLANK ;end screen blank ; Setup Color buffer pointer ;-------------------------------------------------------------------------- ldx visualPointer inx cpx #46 bmi notResetVis ldx #0 notResetVis stx visualPointer sta WSYNC ; Put current note color into buffer ;-------------------------------------------------------------------------- ; Put the next color in the scrolling buffer ; based on the current note1. lda note1 cmp #255 bne calcColor lda #0 jmp setColor calcColor asl asl asl asl asl ora #%00000100 setColor sta visualBuffer,x sta WSYNC ; Set the missile colors based on the current note2. lda note2 cmp #255 bne getColor2 lda #0 jmp setColor2 getColor2 asl asl asl asl asl ora #%00001000 setColor2 sta WSYNC sta COLUP0 sta COLUP1 ; Enable missiles lda #255 sta ENAM0 sta ENAM1 sta WSYNC ; Draw screen loop ;-------------------------------------------------------------------------- ldy #46 visualLoop sta WSYNC ; Move the missles around every few scanlines ; based on notes pressed. This creates some ; neat patterns. lda note1 asl asl sta HMM0 lda note2 asl asl sta HMM1 sta WSYNC sta HMOVE ; Have to play last calculated note around middle of screen ; for steadiest beat. cpy #22 bne noNotePlay ; Have to save X and Y on stack tya pha txa pha jsr notePlayer pla tax pla tay noNotePlay sta WSYNC ; Display the scrolling note-color buffer inx cpx #46 bmi notResetVis2 ldx #0 notResetVis2 sta WSYNC lda visualBuffer,x sta COLUBK dey bne visualLoop ; Done drawing screen. Finish up. ;-------------------------------------------------------------------------- sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC sta WSYNC lda #$82 sta VBLANK ; Finished a screen, blank the beam. rts ; showVisuals ;-------------------------------------------------------------------------- ; Draw TV Pictures ;-------------------------------------------------------------------------- ; Here is where we step down the screen drawing everything. ; ; Note that temp16 is used in here as a text pointer, so don't use ; it for anything else during the loop. ;-------------------------------------------------------------------------- Picture ldx visualMode beq regularPicture jmp showVisuals regularPicture lda #0 sta COLUBK lda #11 ;setup counter for rows of text sta scanSec ;store in zero page memory variable ldy #0 ;Y is used to track progress through this screen's text sty EOTflag pictureLoop lda INTIM ;check timer for end of VBLANK period bne pictureLoop ;loop until it reaches 0 ;sta WSYNC ;newline (1) lda #$80 sta VBLANK ;end screen blank ScanLoop ;--------------------------------------------------------------------------- ; This allows a different pointer to each line of text lda #12 clc sbc scanSec ; Get the current row of chars pha asl ; multiply x2 tax ; Get the pointer to the next text. lda textPointer,x sta temp16L inx lda textPointer,x sta temp16H ; *** Set the BG Colors *** pla tay adc colorCycle tax lda bgColorCycles,x sta backColor lda setupCount beq loadSetupArray lda dividerArray1,y jmp drawDividers loadSetupArray lda dividerArray2,y drawDividers beq skipWhiteLine sta WSYNC ; Draw a white line lda #$0D sta COLUBK lda setupCount beq skipWhiteLine cpy #8 beq skipWhiteLine ; This makes some of the divider lines ; in setup mode shorter to make the keyboard ; grid look better ; Waste some cycles: lda (temp16L,y) lda (temp16L,y) lda (temp16L,y) lda (temp16L,y) lda (temp16L,y) lda (temp16L,y) lda (temp16L,y) lda (temp16L,y) nop nop lda temp16L lda backColor sta COLUBK skipWhiteLine ; Around the middle of the screen, the notePlayer is called. ; This must occur on a line where the white divider line ; is not drawn (on the Status or Setup screen) cpy #5 bne skipNotePlayer jsr notePlayer skipNotePlayer lda #64 ; A variable amount of text will be processed, so stay.... ldx backColor sta WSYNC jmp timer ; Timer ;-------------------------------------------------------------------------- ; align 256 timer sta TIM8T ;....in sync by timing out after finished (7 scanlines) stx COLUBK ldx #22 ;write 12 spaces to text buffer to wipe out what's there lda #<_space ; from previous row/frame/etc. blankLine sta grfxBuffer,x ;grfxBuffer is our 24 byte, 16 bit list of chars dex dex bpl blankLine ;fill it lda EOTflag bne eol ldx #0 ; Will load from left to right. ldy #0 ; Each line is referenced individually. nextCol lda (temp16L),y ; Indirect/indexed - pointer to a section of text iny ; next char cmp #$FF ; FF is EOL beq eol ; done with a line? cmp #$FE bne noEOT lda #1 sta EOTflag jmp eol noEOT sta grfxBuffer,x ; No, stuff this char into the buffer inx inx jmp nextCol ; Just keep going--a screen w/o 10 $FF's will screw this up eol lda INTIM ; We finished, but wait for timer bne eol ; by looping till zero sta WSYNC ; end current line tya ; Need to save Y by putting into accumulator pha ; then onto stack. jsr println ; Print this row via subroutine. (6 scanlines) pla ; Pull Y off stack tay ; and put back. dec scanSec ; next row to print beq quitScanLoop; loop until all 11 rows of text have been displayed jmp ScanLoop quitScanLoop sta WSYNC ; Skip one line if in setup mode to make it exactly 262 lines lda setupCount bne skipLastLine sta WSYNC skipLastLine ; Draw the white line at the bottom. lda #$0D sta COLUBK sta WSYNC lda #$82 sta VBLANK ; Finished a screen, blank the beam. endScreen rts ; Picture ;--------------------------------------------------------------------------- ; Text and Note Data ;--------------------------------------------------------------------------- include snthdata.h ;-------------------------------------------------------------------------- ; Call Keyboard Reader ;-------------------------------------------------------------------------- ; Bankswitching code to call keyboard reader subroutine ; and then switch back to bank 1. ;-------------------------------------------------------------------------- org $1FC0 readKeyboards ldx $1FF9 ; (switch to bank 2) nop ; 1FE3 jsr readKeyboards8k nop ; . nop ; . nop ; 1FE6 lda $1FF8 (Switch back to bank 1) nop ; . nop ; . rts ;-------------------------------------------------------------------------- ; Call Calculate Volume ;-------------------------------------------------------------------------- ; Bankswitching code to call beat player subroutine ; and then switch back to bank 1. ;-------------------------------------------------------------------------- org $1FD0 calcVolume ldx $1FF9 ; (switch to bank 2) nop ; 1FE3 jsr calcVolume8k nop ; . nop ; . nop ; 1FE6 lda $1FF8 (Switch back to bank 1) nop ; . nop ; . rts ;-------------------------------------------------------------------------- ; Call Beat Box ;-------------------------------------------------------------------------- ; Bankswitching code to call beat player subroutine ; and then switch back to bank 1. ; ; Can't use ACC here since it is set to the number ; of oscillators for the beat box player. ;-------------------------------------------------------------------------- org $1FE0 callBeatBox ldx $1FF9 ; (switch to bank 2) nop ; 1FE3 jsr beat box nop ; . nop ; . nop ; 1FE6 lda $1FF8 (Switch back to bank 1) nop ; . nop ; . rts ;--------------------------------------------------------------------------- ; Program Startup Vector ;--------------------------------------------------------------------------- org $1FF3 ; The cart will start in bank 2, then a bankswitch ; will occur and land here... jmp Start ; Start program org $1FFC ; Program startup vector (not used) .word Start .word Start include snthup4k.h ; Upper 4k
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[stella] Scan lines, FotR...., Adam Thornton | Thread | Re: [stella] Scan lines, FotR...., Glenn Saunders |
Re: [stella] Cosmic Ark disassemble, Glenn Saunders | Date | Re: [stella] Cosmic Ark disassemble, Thomas Jentzsch |
Month |