P * * Transfer POINT1 to current field pointer * ZPTOF1P LDA CURFLD ASL TAX LDA POINT1 STA F1P,X LDA POINT1+1 STA F1P+1,X RTS * * Transfer current field pointer to POINT1 * F1PTOZP LDA CURFLD ASL TAX LDA F1P,X STA POINT1 LDA F1P+1,X STA POINT1+1 RTS * * OTHER * Handle other special commands, like start music, * go to instrument editor, edit frequencies, etc. * ISOTHER LDX ISFLAG BNE :RTS LDX $028D ;Check for CTRL key CPX #4 BCC :FUNC LDX #9 :LOOP DEX BMI :RTS CMP :CTAB,X BNE :LOOP :RTS RTS :FUNC LDX #9 CMP #134 BEQ :RTS INX CMP #135 BEQ :RTS INX CMP #136 BEQ :RTS INX CMP #140 ;f8 RTS :CTAB DFB 9 ;CTRL-i DFB 4 ;CTRL-d DFB 14 ; -n DFB 16 ; -p DFB 1 ; -a DFB 19 ; -s DFB 20 ; -t DFB 26 ; -z DFB 5 ; -e OTHER TXA ASL TAX LDA :OTAB,X STA :JMP+1 LDA :OTAB+1,X STA :JMP+2 JSR ZPTOF1P ;Save whatever's been done JSR SAVEPP LDA #00 STA BLFLAG ;Stop any block operation LDA #155 JSR CHROUT LDA #6 STA $D021 STA $D020 LDA #15 STA COLOR :JMP JMP $A000 :OTAB DA INTDELAY DA EDDUR DA EDNOTE DA PLAYSONG DA AUDIBLE DA SINGLE DA TRANSP DA PRINST DA EXIT DA INSTED DA MACMAN DA DISK DA OLDDISK * * Exit to BASIC * EXIT JSR STROUT DFB 147,13 TXT 'Press RS/RESTORE to restart',0d,00 PLA PLA JMP GOBASIC * * Set interrupt delay * INTDELAY JSR STROUT DFB 147,13 TXT 'Current interrupt count=$',00 LDX TIMERUPT+1 LDA TIMERUPT LDY #16 JSR PRINTNUM LDA #13 JSR CHROUT JSR CHROUT LDA #'$' JSR CHROUT LDX #4 JSR INPUT BEQ :DONE ;Skip if empty LDA #STRING LDY #16 ;Base 16 JSR ASCTONUM LDA ACC STA TIMERUPT LDA ACC+1 STA TIMERUPT+1 :DONE INC $CC ;Fix cursor hack * * ODONE -- Fix up pointers and restore screen. * ODONE PLA PLA JMP EDMAIN * * AUDIBLE -- Hear notes as they are played * PLFLAG DFB 0 AUDIBLE LDA PLFLAG EOR #$FF STA PLFLAG BNE :DONE JSR CLRGATE :DONE JMP ODONE * * SINGLE -- Single step * STEPSIZE DFB 1 TEMPSTEP DFB 1 NOSTEPS DFB 00 SINGLE JSR SETMSG LDX #23 LDY #7 JSR PLOPXY JSR PLOPSTR TXT 'Single step, skip=',00 LDX STEPSIZE JSR PRINTX LDA #00 STA NOSTEPS ;flag LDA $028D ;If SHIFT is down AND #1 ;play from current pos BEQ :INIT JSR CURPOS JMP :LOOP :INIT JSR PLAYINIT :LOOP JSR GETIN LDY #1 CMP #32 ;Step by one BEQ :PLAY CMP #'s' ;Step by large amount BEQ :SPLAY CMP #'c' BEQ :GETARG CMP #13 BNE :LOOP LDA #00 STA ISFLAG ;Restore check LDA NOSTEPS ;Don't reset pointers if no BEQ :EXIT ;steps were taken. JSR V1GETP CPX BFIELD1+1 ;Don't decrement if at beginning BNE :DEC1 CMP BFIELD1 BEQ :C1 :DEC1 SEC ;Back up pointers! SBC #2 BCS :C1 DEX :C1 STX F1P+1 STA F1P ;Set pointers from player JSR V2GETP CPX BFIELD2+1 BNE :DEC2 CMP BFIELD2 BEQ :C2 :DEC2 SEC SBC #2 BCS :C2 DEX :C2 STX F2P+1 STA F2P JSR V3GETP CPX BFIELD3+1 BNE :DEC3 CMP BFIELD3 BEQ :C3 :DEC3 SEC SBC #2 BCS :C3 DEX :C3 STX F3P+1 STA F3P JSR CLRGATE :EXIT JMP ODONE :SPLAY LDY STEPSIZE :PLAY STY TEMPSTEP LDA NOSTEPS ;We've taken a step ORA #$FF STA NOSTEPS :LOOP2 JSR MAINPLAY DEC TEMPSTEP BNE :LOOP2 JMP :LOOP :GETARG JSR READARG STA STEPSIZE JMP SINGLE * * Transpose commands -- allow addition/subtraction * to notes using '.' key. * TRANSP LDA $028D AND #1 BNE :EDIT LDA TRNSFLAG EOR #$01 STA TRNSFLAG JMP ODONE :EDIT LDA #147 JSR CHROUT LDX #04 LDY #00 JSR PLOPXY JSR PLOPSTR TXT '(D)ur transpose=',00 LDA TRANSDUR JSR PHBYTE LDX #05 LDY #00 JSR PLOPXY CLC INX JSR PLOT JSR PLOPSTR TXT '(N)ote transpose=',00 LDA TRANSNOT JSR PHBYTE :WAIT JSR GETIN BEQ :WAIT CMP #'e' BEQ :EXIT CMP #'d' BEQ :DUR CMP #'n' BEQ :NOTE JSR STOP BNE :WAIT :EXIT JMP ODONE :NOTE JSR GETNUM BEQ :EDIT STA TRANSNOT BNE :EDIT :DUR JSR GETNUM BEQ :EDIT STA TRANSDUR BNE :EDIT TRNSFLAG DFB 00 TRANSDUR DFB 00 TRANSNOT DFB 00 TRNSPOSE LDA TRNSFLAG BEQ :RTS LDY #01 LDA (POINT1),Y BMI :RTS CLC ADC TRANSDUR CMP #24 BCS :C1 STA (POINT1),Y :C1 DEY LDA (POINT1),Y CLC ADC TRANSNOT CMP #192 BCS :RTS STA (POINT1),Y :RTS RTS * * Set player pointers to the current positions * CURPOS LDA F1P LDX F1P+1 JSR V1SETP LDA F2P LDX F2P+1 JSR V2SETP LDA F3P LDX F3P+1 JSR V3SETP LDA #1 STA DURATION STA DURATION+1 STA DURATION+2 LDA #00 ;Enable all voices STA STOPME STA STOPME+1 STA STOPME+2 RTS CLRGATE ENT LDA SHADOW+4 ;Clear gate bits AND #$FE STA SHADOW+4 STA $D404 LDA SHADOW+$B AND #$FE STA SHADOW+$B STA $D40B LDA SHADOW+$12 AND #$FE STA SHADOW+$12 STA $D412 RTS * * PRINST -- Print instrument table * PRINST LDA #147 JSR CHROUT LDX #00 STX EROW :LOOP LDY #00 JSR PLOPXY TXA JSR PHBYTE LDA #32 JSR CHAROUT JSR CHAROUT TXA STA TEMP ASL ADC TEMP ASL TAX LDY #6 :L1 LDA INAMES,X JSR CHAROUT INX DEY BNE :L1 LDA TEMP ;Instrument # ASL ASL ASL ADC TEMP TAX LDY #9 :L2 LDA #32 JSR CHAROUT LDA INSTAB,X JSR PHBYTE INX DEY BNE :L2 INC EROW LDX EROW CPX #14 BNE :LOOP LDY #0 CLC JSR PLOT JSR WAITKEY JMP ODONE * * Edit duration table * EDDUR LDA #3 STA ECOL LDA #00 STA EROW LDA #147 JSR CHROUT :PRINT LDX #23 STX TEMP :LOOP LDY #00 JSR PLOPXY TXA ;0..9, A-N CLC ADC #48 CMP #58 BCC :CONT ADC #6 :CONT JSR CHAROUT LDA #32 JSR CHAROUT JSR CHAROUT LDA DURTAB,X JSR PHBYTE LDA #32 JSR CHAROUT LDA #'(' JSR CHAROUT LDA DURTAB,X LDX #00 LDY #10 JSR PLOPNUM LDA #')' JSR CHAROUT LDA #32 JSR CHAROUT JSR CHAROUT DEC TEMP LDX TEMP BPL :LOOP :EDIT LDX EROW LDY #03 JSR PLOPXY JSR TOG :WAIT JSR GETIN BEQ :WAIT CMP #17 BEQ :DOWN CMP #145 BEQ :UP CMP #13 BEQ :INPUT CMP #'e' BEQ :EXIT JSR STOP BNE :WAIT :EXIT JMP ODONE ;Exit :DOWN LDA EROW CMP #23 BCS :WAIT JSR TOG INC EROW BNE :EDIT :UP LDA EROW BEQ :WAIT JSR TOG DEC EROW BPL :EDIT :INPUT LDX #24 LDY #00 CLC JSR PLOT JSR GETNUM BEQ :DONE LDX EROW STA DURTAB,X :DONE JSR CLRBOT JMP :PRINT * * Edit note text/frequency table * EROW DFB 00 ECOL DFB 00 EDNOTE LDA #00 STA EROW LDA #5 STA ECOL :PRINT LDA #147 JSR CHROUT LDX #00 STX TEMP :LOOP LDY #00 JSR PLOPXY TXA CMP #23 ADC #65 JSR CHAROUT LDA #32 JSR CHAROUT LDA NOTEPOS,X JSR PHBYTE LDA #32 JSR CHAROUT LDA NOTETEXT,X JSR CHAROUT LDA NOTETEXT+24,X JSR CHAROUT LDA #32 JSR CHAROUT LDA NOTEFREQ,X JSR PHBYTE LDA #32 JSR CHAROUT LDA NOTEFREQ+24,X JSR PHBYTE LDA #32 JSR CHAROUT JSR CHAROUT LDA #'(' JSR CHAROUT LDY TEMP LDA NOTEFREQ,Y LDX NOTEFREQ+24,Y LDY #10 JSR PLOPNUM LDA #')' JSR CHAROUT INC TEMP LDX TEMP CPX #24 BNE :LOOP :EDIT LDX EROW LDY ECOL JSR PLOPXY JSR TOG :WAIT JSR GETIN BEQ :WAIT CMP #17 BEQ :DOWN CMP #29 BEQ :RIGHT CMP #157 BEQ :LEFT CMP #145 BEQ :UP CMP #13 BEQ :INPUT CMP #'e' BEQ :EXIT JSR STOP BNE :WAIT :EXIT JSR COMPFREQ JMP ODONE ;Exit :DOWN LDX EROW CPX #23 BEQ :WAIT JSR TOG INC EROW BNE :EDIT :UP LDX EROW BEQ :WAIT JSR TOG DEC EROW BPL :EDIT :LEFT JSR TOG LDA ECOL CMP #2 BEQ :EDIT SBC #3 STA ECOL BPL :EDIT :RIGHT JSR TOG LDA ECOL CMP #11 BEQ :EDIT ADC #3 STA ECOL BPL :EDIT :INPUT JSR CLRBOT LDX #24 LDY #00 CLC JSR PLOT LDA ECOL CMP #11 BEQ :HI CMP #8 BEQ :LO CMP #2 BEQ :POS JSR STROUT TXT 'Note text:',00 LDX #2 JSR INPUT LDA STRBUF BNE :C1 LDA #32 STA STRBUF+1 :C1 LDX EROW STA NOTETEXT,X LDA STRBUF+1 BNE :C2 LDA #32 :C2 STA NOTETEXT+24,X JSR CLRBOT JMP :PRINT :HI JSR STROUT TXT 'Freq hi:',00 JSR GETNUM BEQ :DONE LDX EROW STA NOTEFREQ+24,X :DONE JSR CLRBOT JMP :PRINT :LO JSR STROUT TXT 'Freq lo:',00 JSR GETNUM BEQ :DONE LDX EROW STA NOTEFREQ,X BPL :DONE :POS JSR STROUT TXT 'Position (0-23):',00 JSR GETNUM BEQ :DONE CMP #24 BCS :DONE LDX EROW STA NOTEPOS,X BPL :DONE CLRBOT LDX #24 LDY #00 CLC JSR PLOT JSR STROUT TXT ' ',00 RTS GETNUM LDX #4 ;Read in hex or dec number JSR INPUT BEQ :RTS LDA STRBUF CMP #'$' BEQ :HEX CMP #'-' BEQ :NEG LDA #STRBUF LDY #10 JSR ASCTONUM LDA ACC LDX #$FF :RTS RTS :HEX LDA #STRBUF+1 LDY #16 JSR ASCTONUM LDA ACC LDX #$FF RTS :NEG LDA #STRBUF+1 LDY #10 JSR ASCTONUM LDA ACC EOR #$FF CLC ADC #01 LDX #$FF RTS TOG LDY ECOL JSR :BLAH INY :BLAH LDA (SCREENP),Y EOR #$80 STA (SCREENP),Y RTS * * COMPFREQ -- Compute frequency table * COMPFREQ LDX #23 :LOOP1 LDA NOTEFREQ,X ;Low byte STA TEMP LDA NOTEFREQ+24,X ;High LDY #8 :LOOP2 ASL TEMP ROL BCS :DONE DEY BNE :LOOP2 :DONE ROR ROR TEMP LDY NOTEPOS,X CPY #24 BCC :CONT LDY #23 :CONT STA FREQHI+192-24,Y ;Highest octave LDA TEMP STA FREQLO+192-24,Y TXA STA KEYPOS,Y DEX BPL :LOOP1 LDX #192-25 :LOOP3 LDA FREQHI+24,X ;Lower octaves LSR STA FREQHI,X LDA FREQLO+24,X ROR STA FREQLO,X DEX CPX #$FF BNE :LOOP3 RTS * * DISK -- i/o routines * DISK LDA #PLAYSTRT-2 STA LOADADDR+1 STA SAVESTRT+1 LDA FREBOT STA SAVEEND LDA FREBOT+1 STA SAVEEND+1 LDA #VERSION STA LOADID+1 STA PLAYSTRT-1 LDA #>:TEXT LDX #<:TEXT JSR DISKIO LDA NEWDATA BEQ :EXIT JSR MUSINIT :EXIT JMP ODONE :TEXT DFB 147 TXT ' Load/save music' DFB 13,13,00 * * OLDDISK -- Load old versions of music data * OLDBEGIN DA 00 OLDDISK LDA FREBOT STA LOADADDR LDA FREBOT+1 STA LOADADDR+1 LDA #$FF STA LOADID STA LOADID+1 STA SAVEFLAG ;Disable save LDA #>:TEXT LDX #<:TEXT JSR DISKIO LDA NEWDATA BNE :MOVE :EXIT LDA #00 STA SAVEFLAG JMP ODONE :TEXT DFB 147 TXT ' Load old version music' DFB 13,13,00 :ERR JSR STROUT DFB 13 TXT 'Unknown data format' DFB 13,0 JSR WAITKEY JMP :EXIT :MOVE LDA FREBOT STA AUX LDA FREBOT+1 STA AUX+1 LDY #01 LDA (AUX),Y CMP #$C0 BNE :ERR DEY LDA (AUX),Y BEQ :OLD0 CMP #2 BEQ :OLD2 CMP #3 BEQ :OLD3 CMP #4 ;Current version! This way, BNE :ERR ;data may be extracted if ;something becomes corrupted, etc. ;Version $C004 begins at INAMES * Version $C003 began at INAMES :OLD3 LDA #INAMES BNE :OLDADD * Version $C002 began at KEYPOS :OLD2 LDA #KEYPOS BNE :OLDADD * Version $C000 began at NOTETEXT :OLD0 LDA #NOTETEXT :OLDADD STA OLDBEGIN STX OLDBEGIN+1 EXTRACT LDA LOADADDR CLC ADC #2 STA BLSTART LDA LOADADDR+1 ADC #00 STA BLSTART+1 ;First NOTETEXT, pointers, etc. LDA #00 ;offset back from $1000 SEC SBC OLDBEGIN STA ACC LDA #$10 SBC OLDBEGIN+1 STA ACC+1 LDA BLSTART CLC ADC ACC STA BLEND LDA BLSTART+1 ADC ACC+1 STA BLEND+1 LDA OLDBEGIN STA BLDEST LDA OLDBEGIN+1 STA BLDEST+1 JSR BLMOVE ;The variables ;Next, freq tables and such LDA BLEND ;BLEND is at "$1000" CLC ADC #64 STA BLSTART LDA BLEND+1 ADC #00 STA BLSTART+1 LDA BLSTART ADC #<$1330-$1040 STA BLEND LDA BLSTART+1 ADC #>$1330-$1040 STA BLEND+1 LDA #FREQLO STA BLDEST+1 JSR BLMOVE LDA MACBEGIN ;Compute how far forwards SEC ;(or backwards) the field data SBC FIELDP ;has moved STA AUX LDA MACBEGIN+1 SBC FIELDP+1 STA AUX+1 ;AUX=offset from old location ;Now copy the field data. LDA FIELDP ;End of old player SEC SBC OLDBEGIN ;Offset STA FIELDP LDA FIELDP+1 SBC OLDBEGIN+1 STA FIELDP+1 LDA FIELDP CLC ADC #2 ;Skip ID bytes STA FIELDP LDA FIELDP+1 ADC #00 STA FIELDP+1 LDA FIELDP ;Now add offset to load address CLC ADC LOADADDR STA BLSTART LDA FIELDP+1 ADC LOADADDR+1 STA BLSTART+1 LDA $AE ;End of load STA BLEND LDA $AF STA BLEND+1 LDA MACBEGIN STA BLDEST LDA MACBEGIN+1 STA BLDEST+1 JSR BLMOVE LDA BLEND ;Compute new end of data SEC SBC BLSTART STA BLEND LDA BLEND+1 SBC BLSTART+1 STA BLEND+1 LDA BLEND CLC ADC BLDEST STA FREBOT LDA BLEND+1 ADC BLDEST+1 STA FREBOT+1 LDX #4 :LOOP LDA FIELDS,X ;Fix up pointers CLC ADC AUX STA BFIELD1,X ;SAVEPP will store in FIELDS LDA FIELDS+1,X ADC AUX+1 STA BFIELD1+1,X DEX DEX BPL :LOOP LDX #62 ;Fix up markers :LOOP2 LDA MARKERS,X CLC ADC AUX STA MARKERS,X LDA MARKERS+1,X ADC AUX+1 STA MARKERS+1,X DEX DEX BPL :LOOP2 LDA FIELDP+2 CLC ADC AUX STA FIELDEND STA ACC LDA FIELDP+3 ADC AUX+1 STA FIELDEND+1 STA ACC+1 :LOOP3 LDA ACC ;Finally, fix up the fold CMP FREBOT ;(if any) pointers LDA ACC+1 SBC FREBOT+1 BCS :ALLDONE LDY #00 :L3 LDA (ACC),Y CLC ADC AUX STA (ACC),Y INY LDA (ACC),Y ADC AUX+1 STA (ACC),Y INY CPY #4 BCC :L3 LDA ACC CLC ADC #12 STA ACC BCC :LOOP3 INC ACC+1 BNE :LOOP3 :ALLDONE JSR SAVEPP ;Copy pointers into player ;Wheeewwww!!! JSR MUSINIT LDA #00 STA SAVEFLAG JMP ODONE * * Toggle play signal to interrupt routine. * PLAYFLAG ENT DFB 00 PLAYTIME DA 00 ;Timer value while playing PLAYSONG LDA PLAYFLAG EOR #$FF STA PLAYFLAG BEQ :NORUPT LDA $028D ;If SHIFT is down AND #1 ;play from current pos BEQ :INIT JSR CURPOS JMP :CONT :INIT JSR PLAYINIT :CONT LDA #00 STA $DC0E ;Stop countdown LDA TIMERUPT STA PLAYTIME STA $DC04 ;Timer A low LDA TIMERUPT+1 STA PLAYTIME+1 STA $DC05 ;Timer A hi LDA #01 ;Continuous mode STA $DC0E JMP ODONE :NORUPT LDA #00 ;Restore normal CIA value STA $DC0E LDA #$C6 STA $DC04 LDA #$42 STA $DC05 LDA #01 STA $DC0E JSR CLRGATE JMP ODONE * * SAVEPP -- ZP -> player * SAVEPP LDA MACBEGIN STA FIELDP ;playvars LDA MACBEGIN+1 STA FIELDP+1 LDA FIELDEND STA FIELDP+2 LDA FIELDEND+1 STA FIELDP+3 LDA FREBOT STA FIELDP+4 LDA FREBOT+1 STA FIELDP+5 LDX #5 :LOOP LDA BFIELD1,X STA FIELDS,X DEX BPL :LOOP RTS * Player -> ZP LOADPP LDA FIELDP STA MACBEGIN LDA FIELDP+1 STA MACBEGIN+1 LDA FIELDP+2 STA FIELDEND LDA FIELDP+3 STA FIELDEND+1 LDA FIELDP+4 STA FREBOT LDA FIELDP+5 STA FREBOT+1 LDX #5 :LOOP LDA FIELDS,X STA BFIELD1,X DEX BPL :LOOP RTS * * STAFIELD * Store the data in (.X,.A) into (point1) * STAFIELD PHA LDY #01 STA (POINT1),Y DEY TXA STA (POINT1),Y PLA RTS * * PLNOTE -- Play an individual note if flag is set * PLNOTE LDA PLFLAG ;See if play note is enabled BEQ :DONE LDA #01 STA STOPME ;Disable voices STA STOPME+1 STA STOPME+2 LDY CURFLD STA DURATION,Y ;Force execution LDA #00 STA STOPME,Y ;Enable current voice INY STY CURVOICE ;Curvoice = 1,2,3 DO 0 ;DON'T clear any gate bits CPY #01 ;Clear correct gate bits BEQ :C2 LDA SHADOW+4 AND #$FE STA SHADOW+4 STA $D404 :C2 CPY #02 BEQ :C3 LDA SHADOW+$B AND #$FE STA SHADOW+$B STA $D40B :C3 CPY #3 BEQ :CONT LDA SHADOW+$12 AND #$FE STA SHADOW+$12 STA $D412 FIN :CONT LDA POINT1 LDX POINT1+1 JSR SETP ;Set voice pointer JSR MAINPLAY ;Play note :DONE RTS * * Center the current field, at row 11 if possible * FCENTER LDA CURFLD ASL TAY LDA POINT1 SEC SBC BFIELD1,Y PHA LDA POINT1+1 SBC BFIELD1+1,Y TAX PLA JMP GOROW