; GMC-X1 VER.4.13 PSG OFF VERSION. ; 89/06/11 09:44PM ORG $E000 JP PROGRAM.START ; ; ; DATA.AREA EQU $9000 DATA.START.ADR DW 0 MML.START DW $8000 DATA.ADR DW DATA.AREA MML.ADR DW $8000 FM.FLAG DB 1 GOSUB.WORK DS 2*26 MML.NO.WORK DS 1*26 TONE.NO.WORK DS 2*128 CHANNEL DB 0 ERROR.CODE DB 0 WORK.START LINE.NUMBER DW 0 NOTE.DATA DB 0 L1COUNT DB 192 LENGTH.DEFAULT DW 48 OCTERVE DB 4 GATE.DATA DB 7 FUTEN DB 0 KEY.WORK DB 0 OCTERVE.WORK DB 0 GATE DB 0 VOLUME DB 0 DETUNE DW 0 TRANSPOSE DW 0 LOOP.STACK.NO DB 0 LOOP.START.STACK DS 8*2 LOOP.BREAK.STACK DS 8*2 TEMPO DB 120 NOISEFREQ DB 0 PAN DB 0 PAN.SWITCH DB 0 OCTERVE.WORK.1 DB 0 GATE.FLAG DB 0 NOTE.FLAG DB 0 WORK.END @LINE.NUMBER EQU 0 @NOTE.DATA EQU 2 @L1COUNT EQU 3 @LENGTH.DEFAULT EQU 4 @OCTERVE EQU 6 @GATE.DATA EQU 7 @FUTEN EQU 8 @KEY.WORK EQU 9 @OCTERVE.WORK EQU 10 @GATE EQU 11 @VOLUME EQU 12 @DETUNE EQU 13 @TRANSPOSE EQU 15 @LOOP.STACK.NO EQU 17 @LOOP.START.STACK EQU 18 @LOOP.BREAK.STACK EQU 34 @TEMPO EQU 50 @NOISEFREQ EQU 51 @PAN EQU 52 @PAN.SWITCH EQU 53 @OCTERVE.WORK.1 EQU 54 @GATE.FLAG EQU 55 @NOTE.FLAG EQU 56 CHANNEL.MAX EQU 8 PRINT.CHR EQU $1FF4 PRINT.SP EQU $1FF1 PRINT.MES EQU $1FE5 PRINT.MES. EQU $1FE2 PRINT.HL EQU $1FBE INKEY EQU $2021 ; ; ; SOFT.ENV.DATA ; DS 8*16 NOTE.TABLE DB 9*2,11*2,0*2,2*2,4*2,5*2,7*2 NOTE.TABLE.SHARP DB 10*2,12*2,1*2,3*2,5*2,6*2,8*2 NOTE.TABLE.FLAT DB 8*2,10*2,-1*2,1*2,3*2,4*2,6*2 ; ; ; PROGRAM.START ;IN DE=MML START ADDRESS ; HL=COMPILE ADDRESS LD (DATA.ADR),HL ;OUT HL=COMPILE END ADDRESS LD (DATA.START.ADR),HL CALL MASTER.INIT ;CALL SOFT.ENV.SET ;JP C,ERROR CALL TONE.SET JP C,ERROR CALL SUB.MML.SET JP C,ERROR LD A,8 LD (CHANNEL),A MAIN.LOOP LD HL,(DATA.START.ADR) LD A,(CHANNEL) DEC A ADD A,A LD D,0 LD E,A ADD HL,DE PUSH HL LD HL,(DATA.ADR) LD DE,(DATA.START.ADR) OR A:SBC HL,DE EX DE,HL POP HL LD (HL),E INC HL LD (HL),D CALL MML.ANALYZE.INIT CALL MML.SET JP C,ERROR LD A,15*2+193 CALL PUT.DATA.A LD A,(CHANNEL) DEC A LD (CHANNEL),A JP NZ,MAIN.LOOP ; :JP $DE00 CALL PRINT.MES. DM "DATA END $" DB 0 LD HL,(DATA.ADR) DEC HL CALL PRINT.HL LD A,13 CALL PRINT.CHR RET ; PRINT.LINENO LD HL,(LINE.NUMBER) LD DE,10000 CALL PRINT.DEC.1 LD DE,1000 CALL PRINT.DEC.1 LD DE,100 CALL PRINT.DEC.1 LD DE,10 CALL PRINT.DEC.1 LD DE,1 CALL PRINT.DEC.1 JP PRINT.SP PRINT.DEC.1 XOR A PRINT.DEC.1.1 INC A SBC HL,DE JR NC,PRINT.DEC.1.1 ADD A,$2F ADD HL,DE JP PRINT.CHR ERROR CALL PRINT.LINENO LD HL,(MML.ADR) PUSH HL LD B,1 ERROR.0 LD A,(HL) CP $0D JP Z,ERROR.0.1 INC B DEC HL JP ERROR.0 ERROR.0.1 INC HL LD (MML.ADR),HL ERROR.1 CALL GET.DATA CALL MML.ADR.INC CALL PRINT.CHR DJNZ ERROR.1 POP HL CALL PRINT.SP LD A,"$" CALL PRINT.CHR CALL PRINT.HL CALL PRINT.SP LD HL,MESSAGE.ADR.TABLE LD D,0 LD A,(ERROR.CODE) ADD A,A LD E,A ADD HL,DE LD E,(HL) INC HL LD D,(HL) CALL PRINT.MES RET MESSAGE.ADR.TABLE DW M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16,M17,M18 M1 DM "SYNTAX ERR" DB 0 M2 DM "OCTAVE OVER" DB 0 M3 DM "LOOPNEST OVER" DB 0 M4 DM "NO LOOPSTART MARK" DB 0 M5 DM "?" DB 0 M6 DM "ILLEGAL LENGTH" DB 0 M7 DM "MISSING OPERAND" DB 0 M8 DM "ILLEGAL MML" DB 0 M9 DM "VOLUME OVER" DB 0 M10 DM "ILLEGAL GATE" DB 0 M11 DM "NO LOOPEND MARK" DB 0 M12 DM "REG DATA ERR" DB 0 M13 DM "TEMPO ERR" DB 0 M14 DM "DETUNE ERR" DB 0 M15 DM "NOISE ERR" DB 0 M16 DM "FADE ERR" DB 0 M17 DM "LFO ERR" DB 0 M18 DM "@ No. ERR" DB 0 ; ; ; MASTER.INIT ;IN DE=MML START ADDRESS LD (MML.START),DE LD DE,(DATA.START.ADR) LD HL,CHANNEL.MAX*2 ADD HL,DE LD (DATA.ADR),HL LD HL,GOSUB.WORK LD DE,GOSUB.WORK+1 LD BC,26*2-1 LD (HL),0 LDIR RET ; ; ; SOFT.ENV.SET ;CALL MML.ANALYZE.INIT SOFT.ENV.SET.1 ;CALL LINE.SEARCH ;RET Z ;CP "#" ;JP NZ,SOFT.ENV.SET.1 ;CALL MML.ADR.INC ;CALL GET.8.DATA ;JP C,SOFT.ENV.ERROR ;CP 16 ;CCF ;JP C,SOFT.ENV.ERROR ;ADD A,A ;ADD A,A ;ADD A,A ;LD HL,SOFT.ENV.DATA ;LD D,0 ;LD E,A ;ADD HL,DE ;LD B,8 SOFT.ENV.SET.2 ;CALL GET.8.DATA ;JP C,SOFT.ENV.ERROR ;LD (HL),A ;INC HL ;DJNZ SOFT.ENV.SET.2 ;JP SOFT.ENV.SET.1 SOFT.ENV.ERROR ;LD A,5 ;LD (ERROR.CODE),A ;RET ; ; ; MML.ANALYZE.INIT LD HL,(MML.START) LD (MML.ADR),HL LD HL,WORK.START LD DE,WORK.START+1 LD BC,WORK.END-WORK.START-1 LD (HL),0 LDIR LD IX,WORK.START LD (IX+@OCTERVE),4 LD (IX+@LENGTH.DEFAULT),48 LD (IX+@VOLUME),5 LD (IX+@TEMPO),120 LD (IX+@GATE),7 LD (IX+@L1COUNT),192 RET ; ; ; SUB.MML.SET CALL MML.NO.SEARCH LD A,"A" LD (CHANNEL),A SUB.MML.SET.1 LD HL,GOSUB.WORK LD DE,MML.NO.WORK SUB.MML.SET.2 LD A,(DE) INC DE OR A JP Z,SUB.MML.SET.4 PUSH DE PUSH HL CALL MML.ANALYZE.INIT POP HL LD DE,(DATA.ADR) LD (HL),E INC HL LD (HL),D INC HL PUSH HL CALL MML.SET POP HL POP DE RET C SUB.MML.SET.3 LD A,(CHANNEL) INC A LD (CHANNEL),A CP "Z"+1 JP NZ,SUB.MML.SET.2 RET SUB.MML.SET.4 INC HL:INC HL JP SUB.MML.SET.3 ; ; ; LINE.SEARCH PUSH HL LINE.SEARCH. LD HL,(LINE.NUMBER) INC HL LD (LINE.NUMBER),HL DEC HL LD A,H OR L JP Z,LINE.SEARCH.2 LINE.SEARCH.1 LD HL,(MML.ADR) PUSH BC LD BC,0 LD A,$0D CPIR POP BC LD (MML.ADR),HL LINE.SEARCH.2 CALL GET.DATA CP $0D JP Z,LINE.SEARCH. OR A POP HL RET ; MML.NO.SEARCH LD HL,MML.NO.WORK LD DE,MML.NO.WORK+1 LD BC,1*26-1 LD (HL),0 LDIR LD HL,(MML.START) LD (MML.ADR),HL MML.NO.SEARCH.1 CALL LINE.SEARCH RET Z SUB "A" JP C,MML.NO.SEARCH.1 CP "Z"-"A"+1 JP NC,MML.NO.SEARCH.1 LD HL,MML.NO.WORK ADD A,L LD L,A LD A,0 ADC A,H LD H,A LD (HL),1 JP MML.NO.SEARCH.1 ; ; ; GET.DATA PUSH HL LD HL,(MML.ADR) LD A,(HL) CP "a" JP C,GET.DATA.1 CP "z"+1 JP NC,GET.DATA.1 SUB $20 GET.DATA.1 POP HL RET ; SKIP.GET.DATA CALL GET.DATA CP " " JP Z,SKIP.GET.DATA.1 CP "," JP Z,SKIP.GET.DATA.1 RET SKIP.GET.DATA.1 CALL MML.ADR.INC JP SKIP.GET.DATA ; MML.ADR.INC PUSH HL LD HL,(MML.ADR) INC HL LD (MML.ADR),HL POP HL RET ; MML.ADR.DEC PUSH HL LD HL,(MML.ADR) DEC HL LD (MML.ADR),HL POP HL RET ; ; ; GET.8.DATA CALL SKIP.GET.DATA CP "$" JP Z,GET.HEX2 SUB "0" RET C CP 10 CCF RET C PUSH BC LD C,A GET.8.DATA.1 CALL MML.ADR.INC CALL GET.DATA SUB "0" JP C,GET.8.DATA.2 CP 10 JP NC,GET.8.DATA.2 SLA C:LD B,C:SLA C:SLA C:ADD A,B:ADD A,C ;C=C*10+A LD C,A JP GET.8.DATA.1 GET.8.DATA.2 LD A,C POP BC OR A RET ; GET.8A.DATA CALL SKIP.GET.DATA CP "-" JP Z,GET.8A.DATA.1 CP "+" JP Z,GET.8A.DATA.2 JP GET.8.DATA GET.8A.DATA.1 CALL MML.ADR.INC CALL GET.8.DATA RET C XOR $FF:INC A OR A RET GET.8A.DATA.2 CALL MML.ADR.INC JP GET.8.DATA ; ; ; GET.HEX2 CALL MML.ADR.INC CALL GET.HEX RET C CALL MML.ADR.INC ADD A,A:ADD A,A:ADD A,A:ADD A,A PUSH BC LD C,A CALL GET.HEX JP Z,GET.HEX2.1 ADD A,C CALL MML.ADR.INC GET.HEX2.1 POP BC RET GET.HEX CALL GET.DATA SUB "0" RET C CP 10 CCF RET NC SUB "A"-"0"+10 CP 16 CCF RET C CP 10 RET ; GET.HEX4 CALL GET.HEX2 RET C LD H,A CALL GET.HEX2 LD L,A RET ; ; ; MML.SET MML.SET.A CALL LINE.SEARCH JP Z,MML.SET.C CP " " JP Z,MML.SET.A LD B,A LD A,(CHANNEL) CP "A" JP NC,MML.SET.B LD B,A CALL GET.8.DATA JP C,MML.SET.A JP MML.SET.B. MML.SET.B CALL MML.ADR.INC MML.SET.B. CP B JP Z,MML.SET. JP MML.SET.A MML.SET.C LD A,(LOOP.STACK.NO) OR A JP NZ,COM.ERROR.11 RET ; MML.SET. CALL SKIP.GET.DATA CP $0D JP Z,MML.SET.A CP "'" JP Z,MML.SET.A CP "A" JP C,MML.SET.1 CP "G"+1 JP C,NOTE.COM MML.SET.1 CALL MML.ADR.INC CP "R" JP Z,REST.COM CP "(" JP Z,PORTAMENTO.COM CP "O" JP Z,OCTERVE.COM CP "L" JP Z,DEF.LENGTH.COM CP "V" JP Z,VOLUME.COM CP "Q" JP Z,GATE.COM CP "<" PATCH1 JP Z,OCTUP.COM CP ">" PATCH2 JP Z,OCTDOWN.COM CP "]" JP Z,VOLUP.COM CP "[" JP Z,VOLDOWN.COM CP "|" JP Z,LOOP.START.COM CP ":" JP Z,LOOP.BREAK.COM CP "Y" JP Z,WRITE.REG.COM CP "T" JP Z,TEMPO.COM CP "^" JP Z,DETUNE.COM CP "I" JP Z,TRANSPOSE.COM CP "N" JP Z,NOISEFREQ.COM CP "/" JP Z,KEYOFF.COM CP $9F ;تق¯¸½×¯¼­ JP Z,FADE.COM CP "*" JP Z,NOISESWITCH.COM CP "@" JP Z,EXTEND.COMMAND CP "&" JP Z,MML.SET. CP "S" JP Z,SOFT.LFO.COM CP "W" JP Z,LFO.DELAY.COM CP "H" JP Z,LFO.SPEED.COM CP "P" JP Z,PAN.COM CP "X" JP Z,OCTSWITCH.COM CP ";" JP Z,MML.SET.C JP COM.ERROR.1 ; ; ; NOTE.COM ;IN A="C"-"B" CALL NOTE.ANALYZE JP C,COM.ERROR.8 LD (NOTE.DATA),A CALL LENGTH.ANALYZE JP C,COM.ERROR.6 LD E,A LD D,0 CALL LENGTH.FUTEN EX DE,HL LD A,(GATE) LD (GATE.DATA),A NOTE.COM.1 CALL GET.DATA LD DE,(MML.ADR) CP "&" JP NZ,NOTE.COM.2 LD (IX+@GATE.DATA),0 CALL MML.ADR.INC LD DE,(MML.ADR) CALL SKIP.GET.DATA CALL NOTE.ANALYZE JP C,NOTE.COM.2 CP (IX+@NOTE.DATA) JP NZ,NOTE.COM.2 LD A,(GATE) LD (GATE.DATA),A CALL LENGTH.ANALYZE JP C,COM.ERROR.6 LD E,A LD D,0 CALL LENGTH.FUTEN ADD HL,DE JP NOTE.COM.1 NOTE.COM.2 LD (MML.ADR),DE LD A,(GATE.DATA) OR A LD A,(NOTE.DATA) JP Z,NOTE.COM.3 PUSH HL LD DE,(LENGTH.DEFAULT) OR A SBC HL,DE POP HL JP Z,NOTE.COM.4 INC A CALL PUT.DATA.A NOTE.COM.2. LD A,(GATE.FLAG) DEC A JP Z,NOTE.COM.2.A LD A,(GATE.DATA) LD DE,HL CALL HL.MULTIPLE.A NOTE.COM.2.. SRL H:RR L:SRL H:RR L:SRL H:RR L LD A,H OR L JP NZ,NOTE.COM.2.1 LD HL,1 NOTE.COM.2.1 DEC HL CALL PUT.DATA.HL.. INC HL EX DE,HL OR A SBC HL,DE CALL PUT.DATA.HL.. JP MML.SET. NOTE.COM.2.A PUSH HL LD A,(GATE.DATA) LD E,A LD D,0 OR A:SBC HL,DE JP C,NOTE.COM.2.B LD A,H OR L JP Z,NOTE.COM.2.B JP NOTE.COM.2.C NOTE.COM.2.B LD HL,1 NOTE.COM.2.C DEC HL CALL PUT.DATA.HL.. INC HL EX DE,HL POP HL OR A:SBC HL,DE CALL PUT.DATA.HL.. JP MML.SET. NOTE.COM.3 INC A CALL PUT.DATA.A DEC HL CALL PUT.DATA.HL.. LD HL,$FFFF CALL PUT.DATA.HL JP MML.SET. NOTE.COM.4 CALL PUT.DATA.A JP MML.SET. ; ; ; NOTE.ANALYZE PUSH DE PUSH HL CALL MML.ADR.INC LD C,A CALL GET.DATA CP "+" JP Z,NOTE.ANALYZE.1 CP "#" JP Z,NOTE.ANALYZE.1 CP "-" JP Z,NOTE.ANALYZE.2 LD HL,NOTE.TABLE JP NOTE.ANALYZE.3 NOTE.ANALYZE.1 LD HL,NOTE.TABLE.SHARP CALL MML.ADR.INC JP NOTE.ANALYZE.3 NOTE.ANALYZE.2 LD HL,NOTE.TABLE.FLAT CALL MML.ADR.INC NOTE.ANALYZE.3 LD A,C SUB "A" JP C,NOTE.ANALYZE.RET CP 8 CCF:JP C,NOTE.ANALYZE.RET LD E,A LD D,0 ADD HL,DE XOR A LD C,(IX+@OCTERVE) NOTE.ANALYZE.4 DEC C JP Z,NOTE.ANALYZE.5 ADD A,12*2 JP NOTE.ANALYZE.4 NOTE.ANALYZE.5 ADD A,(HL) CP $60*2 CCF NOTE.ANALYZE.RET POP HL POP DE RET ; ; ; LENGTH.ANALYZE CALL GET.DATA CP "%" JP Z,LENGTH.ANALYZE.% CALL GET.8.DATA JP C,LENGTH.ANALYZE.1 CP (IX+@L1COUNT) JP Z,LENGTH.ANALYZE. CCF RET C LENGTH.ANALYZE. LD C,A LD A,(L1COUNT) CALL A.DIV.C JP LENGTH.ANALYZE.2 LENGTH.ANALYZE.1 LD A,(LENGTH.DEFAULT) LENGTH.ANALYZE.2 PUSH AF PUSH BC LD C,0 LENGTH.ANALYZE.3 CALL GET.DATA CP "." JP NZ,LENGTH.ANALYZE.4 INC C CALL MML.ADR.INC JP LENGTH.ANALYZE.3 LENGTH.ANALYZE.4 LD (IX+@FUTEN),C POP BC POP AF OR A RET LENGTH.ANALYZE.% CALL MML.ADR.INC CALL GET.8.DATA RET C JP LENGTH.ANALYZE.2 ; ; ; LENGTH.FUTEN ;IN DE=LENGTH PUSH HL LD HL,DE LD A,(FUTEN) LENGTH.FUTEN.1 OR A JP Z,LENGTH.FUTEN.2 SRL D RR E ADD HL,DE DEC A JP LENGTH.FUTEN.1 LENGTH.FUTEN.2 EX DE,HL POP HL RET ; ; ; HL.MULTIPLE.A PUSH DE EX DE,HL LD HL,0 HL.MULTIPLE.A.1 OR A JP Z,HL.MULTIPLE.A.3 SRL A JP NC,HL.MULTIPLE.A.2 ADD HL,DE HL.MULTIPLE.A.2 SLA E:RL D JP HL.MULTIPLE.A.1 HL.MULTIPLE.A.3 POP DE RET ; ; ; A.DIV.C PUSH BC PUSH DE LD D,A XOR A LD B,8 A.DIV.C.1 SLA D RLA CP C JP C,A.DIV.C.2 SUB C INC D A.DIV.C.2 DJNZ A.DIV.C.1 LD A,D POP DE POP BC RET ; ; ; REST.COM CALL LENGTH.ANALYZE JP C,COM.ERROR.6 LD E,A LD D,0 CALL LENGTH.FUTEN EX DE,HL REST.COM.1 CALL GET.DATA LD (IX+@KEY.WORK),0 CP "R" JP Z,REST.COM.1. CP "&" JP NZ,REST.COM.2 LD (IX+@KEY.WORK),1 CALL MML.ADR.INC CALL GET.DATA CP "R" JP NZ,REST.COM.2 REST.COM.1. CALL MML.ADR.INC CALL LENGTH.ANALYZE JP C,COM.ERROR.6 LD E,A LD D,0 CALL LENGTH.FUTEN ADD HL,DE JP REST.COM.1 REST.COM.2 PUSH HL LD DE,(LENGTH.DEFAULT) OR A SBC HL,DE POP HL JP Z,REST.COM.3 LD A,127*2+1 CALL PUT.DATA.A DEC HL CALL PUT.DATA.HL.. JP REST.COM.4 REST.COM.3 LD A,127*2 CALL PUT.DATA.A REST.COM.4 LD A,(KEY.WORK) OR A JP NZ,MML.SET. LD A,16*2+193 CALL PUT.DATA.A JP MML.SET. ; ; ; PORTAMENTO.COM LD A,9*2+193 CALL PUT.DATA.A CALL GET.DATA CALL NOTE.ANALYZE LD (NOTE.DATA),A CALL PUT.DATA.A CALL GET.8A.DATA JP C,PORTAMENTO.COM. LD C,(IX+@OCTERVE) ADD A,C OR A JP Z,COM.ERROR.2 CP 9 JP NC,COM.ERROR.2 LD (OCTERVE),A ;LD (IX+@OCTERVE.WORK),C PORTAMENTO.COM. CALL GET.DATA JP PORTAMENTO.COM.2 PORTAMENTO.COM.1 ;LD C,(IX+@OCTERVE) ;LD (IX+@OCTERVE.WORK),C PORTAMENTO.COM.2 CALL NOTE.ANALYZE SUB (IX+@NOTE.DATA) JP Z,COM.ERROR.8 LD (IX+@NOTE.FLAG),0 JP NC,PORTAMENTO.COM.2. NEG LD (IX+@NOTE.FLAG),1 PORTAMENTO.COM.2. SRL A LD (NOTE.DATA),A CALL MML.ADR.INC CALL LENGTH.ANALYZE JP C,COM.ERROR.6 LD E,A LD D,0 CALL LENGTH.FUTEN LD H,(IX+@NOTE.DATA) LD L,0 CALL HL.DIV.DE LD A,(NOTE.FLAG) OR A JP Z,PORTAMENTO.COM.2.. PUSH DE EX DE,HL LD HL,0 SBC HL,DE POP DE PORTAMENTO.COM.2.. CALL PUT.DATA.HL EX DE,HL DEC HL CALL PUT.DATA.HL.. ;LD A,(OCTERVE.WORK) ;LD (OCTERVE),A CALL GET.DATA CP "&" JP Z,MML.SET. JP KEYOFF.COM ; ; ; OCTERVE.COM CALL GET.8.DATA OCTERVE.COM.1 CP 9 JP NC,COM.ERROR.2 OR A JP Z,COM.ERROR.2 LD (OCTERVE),A JP MML.SET. OCTUP.COM LD A,(OCTERVE) INC A JP OCTERVE.COM.1 OCTDOWN.COM LD A,(OCTERVE) DEC A JP OCTERVE.COM.1 ; ; ; DEF.LENGTH.COM CALL LENGTH.ANALYZE JP C,COM.ERROR.6 LD E,A LD D,0 CALL LENGTH.FUTEN DEF.LENGTH.COM.1 LD (LENGTH.DEFAULT),DE DEF.LENGTH.COM.2 LD A,2*2+193 CALL PUT.DATA.A LD A,(GATE) LD (GATE.DATA),A EX DE,HL JP NOTE.COM.2. ; ; ; VOLUME.COM LD A,(FM.FLAG) OR A JP NZ,VOLUME.COM.FM CALL GET.8.DATA JP C,COM.ERROR.9 XOR $0F LD C,A LD A,1*2+193 CALL PUT.DATA.A LD A,C CALL PUT.DATA.A LD (VOLUME),A JP MML.SET. VOLUME.COM.FM CALL GET.8.DATA JP C,COM.ERROR.9 LD C,A ADD A,A ADD A,C ADD A,80 XOR $7F LD C,A LD A,1*2+193 CALL PUT.DATA.A LD A,C CALL PUT.DATA.A LD (VOLUME),A JP MML.SET. ; ; ; GATE.COM CALL GET.8.DATA JP C,COM.ERROR.10 CP 9 JP NC,COM.ERROR.10 LD (IX+@GATE.FLAG),0 LD (GATE),A LD DE,(LENGTH.DEFAULT) JP DEF.LENGTH.COM.2 ; ; ; RELATIVE.VOL LD A,(FM.FLAG) OR A JP NZ,RELATIVE.VOL.FM RELATIVE.VOL.1 LD A,(VOLUME) SUB C CP 16 ;JP NC,COM.ERROR.9 LD (VOLUME),A LD A,23*2+193 CALL PUT.DATA.A LD A,C CALL PUT.DATA.A JP MML.SET. RELATIVE.VOL.FM LD A,(VOLUME) ADD A,C ;JP M,COM.ERROR.9 LD (VOLUME),A LD A,23*2+193 CALL PUT.DATA.A LD A,C CALL PUT.DATA.A JP MML.SET. ; ; ; VOLUP.COM LD A,(FM.FLAG) LD C,0 OR A JP NZ,VOLUP.COM.FM LD B,1 VOLUP.COM.1 LD A,C SUB B LD C,A CALL GET.DATA CP "]" JP NZ,RELATIVE.VOL CALL MML.ADR.INC JP VOLUP.COM.1 VOLUP.COM.FM LD B,3 JP VOLUP.COM.1 ; ; ; VOLDOWN.COM LD A,(FM.FLAG) LD C,0 OR A JP NZ,VOLDOWN.COM.FM LD B,1 VOLDOWN.COM.1 LD A,C ADD A,B LD C,A CALL GET.DATA CP "[" JP NZ,RELATIVE.VOL CALL MML.ADR.INC JP VOLDOWN.COM.1 VOLDOWN.COM.FM LD B,3 JP VOLDOWN.COM.1 ; ; ; LOOP.START.COM CALL MML.ADR.INC LD A,18*2+193 CALL PUT.DATA.A CALL GET.8.DATA JP NC,LOOP.START.COM.1 LD A,2 LOOP.START.COM.1 CALL PUT.DATA.A LD D,0 LD E,(IX+@LOOP.STACK.NO) LD A,E CP 4*2+1 JP NC,COM.ERROR.3 LD HL,LOOP.START.STACK ADD HL,DE LD A,E ADD A,2 LD (LOOP.STACK.NO),A LD DE,(DATA.ADR) LD (HL),E INC HL LD (HL),D LD DE,15 ADD HL,DE LD (HL),$FF INC HL LD (HL),$FF JP MML.SET. ; ; ; LOOP.BREAK.COM CALL GET.DATA CP "|" JP Z,LOOP.END.COM LD A,5*2+193 CALL PUT.DATA.A LD D,0 LD E,(IX+@LOOP.STACK.NO) DEC E:DEC E LD HL,LOOP.BREAK.STACK ADD HL,DE LD DE,(DATA.ADR) LD (HL),E INC HL LD (HL),D LD A,(OCTERVE) LD (OCTERVE.WORK.1),A LD HL,$FFFF CALL PUT.DATA.HL JP MML.SET. LOOP.END.COM CALL MML.ADR.INC LD A,4*2+193 CALL PUT.DATA.A LD D,0 LD E,(IX+@LOOP.STACK.NO) DEC E:DEC E JP M,COM.ERROR.4 LD (IX+@LOOP.STACK.NO),E LD HL,LOOP.START.STACK ADD HL,DE LD E,(HL) INC HL LD D,(HL) EX DE,HL CALL PUT.DATA.HL.1 LD HL,15 ADD HL,DE LD E,(HL) INC HL LD D,(HL) LD A,E:AND D:INC A JP Z,MML.SET. LD HL,(DATA.ADR) LD (DATA.ADR),DE CALL PUT.DATA.HL.1 LD A,(OCTERVE.WORK.1) LD (OCTERVE),A LD (DATA.ADR),HL JP MML.SET. ; ; ; WRITE.REG.COM LD A,3*2+193 CALL PUT.DATA.A CALL GET.8.DATA JP C,COM.ERROR.12 CALL PUT.DATA.A CALL GET.8.DATA JP C,COM.ERROR.12 CALL PUT.DATA.A JP MML.SET. ; ; ; TEMPO.COM LD A,10*2+193 CALL PUT.DATA.A CALL GET.8.DATA JP C,COM.ERROR.12 LD (TEMPO),A TEMPO.COM.1 LD E,A LD D,0 LD HL,9766 CALL HL.DIV.DE LD A,L CALL PUT.DATA.A JP MML.SET. ; ; ; DETUNE.COM LD A,11*2+193 CALL PUT.DATA.A CALL GET.16A.DATA JP C,COM.ERROR.14 LD DE,(TRANSPOSE) LD (DETUNE),HL ADD HL,DE CALL PUT.DATA.HL JP MML.SET. ; ; ; GET.16.DATA CALL SKIP.GET.DATA CP "$" JP Z,GET.HEX4 SUB "0" RET C CP 10 CCF RET C LD L,A LD H,0 PUSH DE GET.16.DATA.1 CALL MML.ADR.INC CALL GET.DATA SUB "0" JP C,GET.16.DATA.2 CP 10 JP NC,GET.16.DATA.2 ADD HL,HL LD DE,HL ADD HL,HL ADD HL,HL ADD HL,DE LD E,A LD D,0 ADD HL,DE JP GET.16.DATA.1 GET.16.DATA.2 POP DE OR A RET GET.16A.DATA CALL SKIP.GET.DATA CP "-" JP Z,GET.16A.DATA.2 CP "+" JP NZ,GET.16A.DATA.1 CALL MML.ADR.INC GET.16A.DATA.1 JP GET.16.DATA GET.16A.DATA.2 CALL MML.ADR.INC CALL GET.16.DATA RET C PUSH DE LD DE,0 EX DE,HL SBC HL,DE POP DE OR A RET ; ; ; TRANSPOSE.COM LD A,11*2+193 CALL PUT.DATA.A CALL GET.8A.DATA JP C,COM.ERROR.14 LD H,A LD L,0 LD (TRANSPOSE+1),A LD DE,(DETUNE) ADD HL,DE CALL PUT.DATA.HL JP MML.SET. ; ; ; NOISEFREQ.COM LD A,12*2+193 CALL PUT.DATA.A CALL GET.8.DATA JP C,COM.ERROR.15 LD (NOISEFREQ),A CALL PUT.DATA.A JP MML.SET. ; ; ; KEYOFF.COM LD A,16*2+193 CALL PUT.DATA.A JP MML.SET. ; ; ; FADE.COM LD A,14*2+193 CALL PUT.DATA.A CALL GET.8.DATA JP C,COM.ERROR.15 CALL PUT.DATA.A CALL GET.8.DATA JP NC,FADE.COM.1 XOR A JP FADE.COM.3 FADE.COM.1 LD C,A LD A,(FM.FLAG) OR A LD A,127 JP NZ,FADE.COM.2 LD A,15 FADE.COM.2 SUB C FADE.COM.3 CALL PUT.DATA.A CALL GET.8.DATA JP NC,FADE.COM.4 XOR A FADE.COM.4 LD C,A LD A,(FM.FLAG) OR A LD A,127 JP NZ,FADE.COM.5 LD A,15 FADE.COM.5 SUB C FADE.COM.6 CALL PUT.DATA.A JP MML.SET. ; ; ; SOFT.LFO.COM LD A,6*2+193 CALL PUT.DATA.A CALL GET.8.DATA JP C,COM.ERROR.17 CALL PUT.DATA.A CALL GET.8A.DATA JP C,COM.ERROR.17 LD C,0 OR A JP P,SOFT.LFO.COM.1 INC C XOR $FF INC A SOFT.LFO.COM.1 CALL PUT.DATA.A CALL GET.16.DATA JP C,COM.ERROR.17 DEC C JP NZ,SOFT.LFO.COM.2 EX DE,HL LD HL,0 OR A SBC HL,DE SOFT.LFO.COM.2 CALL PUT.DATA.HL CALL GET.8.DATA JP C,COM.ERROR.17 CALL PUT.DATA.A JP MML.SET. ; ; ; LFO.DELAY.COM LD A,7*2+193 CALL PUT.DATA.A LFO.DELAY.COM.1 CALL GET.8.DATA JP C,COM.ERROR.17 CALL PUT.DATA.A JP MML.SET. LFO.SPEED.COM LD A,8*2+193 CALL PUT.DATA.A JP LFO.DELAY.COM.1 ; ; ; PUT.DATA.A PUSH HL LD HL,(DATA.ADR) LD (HL),A INC HL LD (DATA.ADR),HL POP HL RET PUT.DATA.HL.. PUSH AF LD A,L:INC A CALL PUT.DATA.A LD A,H:INC A CALL PUT.DATA.A POP AF RET PUT.DATA.HL PUSH AF LD A,L CALL PUT.DATA.A LD A,H CALL PUT.DATA.A POP AF RET PUT.DATA.HL.1 PUSH HL PUSH DE LD DE,(DATA.START.ADR) OR A:SBC HL,DE CALL PUT.DATA.HL POP DE POP HL RET ; ; ; NOISESWITCH.COM LD A,(FM.FLAG) OR A JP NZ,NOISESWITCH.COM.FM LD A,13*2+193 CALL PUT.DATA.A CALL GET.8.DATA LD E,A LD D,0 LD HL,NOISESWITCH.DATA ADD HL,DE LD A,(HL) CALL PUT.DATA.A JP MML.SET. NOISESWITCH.COM.FM LD A,13*2+193 CALL PUT.DATA.A CALL GET.8.DATA CALL PUT.DATA.A JP MML.SET. NOISESWITCH.DATA DB 9,8,1,0 ; ; ; COM.ERROR.1 XOR A JP COM.ERROR.RET COM.ERROR.2 LD A,1 JP COM.ERROR.RET COM.ERROR.3 LD A,2 JP COM.ERROR.RET COM.ERROR.4 LD A,3 JP COM.ERROR.RET COM.ERROR.5 LD A,4 JP COM.ERROR.RET COM.ERROR.6 LD A,5 JP COM.ERROR.RET COM.ERROR.7 LD A,6 JP COM.ERROR.RET COM.ERROR.8 LD A,7 JP COM.ERROR.RET COM.ERROR.9 LD A,8 JP COM.ERROR.RET COM.ERROR.10 LD A,9 JP COM.ERROR.RET COM.ERROR.11 LD A,10 JP COM.ERROR.RET COM.ERROR.12 LD A,11 JP COM.ERROR.RET COM.ERROR.13 LD A,12 JP COM.ERROR.RET COM.ERROR.14 LD A,13 JP COM.ERROR.RET COM.ERROR.15 LD A,14 JP COM.ERROR.RET COM.ERROR.16 LD A,15 JP COM.ERROR.RET COM.ERROR.17 LD A,16 JP COM.ERROR.RET COM.ERROR.18 LD A,17 JP COM.ERROR.RET COM.ERROR.RET LD (ERROR.CODE),A SCF RET ; ; ; EXTEND.COMMAND CALL GET.DATA CALL MML.ADR.INC CP "V" JP Z,VOLUME@.COM CP "L" JP Z,LENGTH@.COM CP "C" JP Z,L1COUNT@.COM CP "S" JP Z,GOSUB@.COM CP "R" JP Z,RETURN@.COM CP "^" JP Z,DETUNE@.COM CP "T" JP Z,TEMPO@.COM CP "I" JP Z,TRANSPOSE@.COM CP "N" JP Z,NOISEFREQ@.COM CP "P" JP Z,PAN@.COM CP "A" JP Z,ATTACK.MODE.COM CP "Q" JP Z,GATE@.COM TONE.SET.COM CALL MML.ADR.DEC LD A,(FM.FLAG) DEC A JP Z,TONE.SET.COM.FM CALL GET.8.DATA JP C,COM.ERROR.18 CP 16 CCF JP C,COM.ERROR.18 ADD A,A:ADD A,A:ADD A,A LD E,A LD D,0 LD A,17*2+193 CALL PUT.DATA.A LD B,8 LD HL,SOFT.ENV.DATA ADD HL,DE TONE.SET.COM.1 LD A,(HL) CALL PUT.DATA.A INC HL DJNZ TONE.SET.COM.1 JP MML.SET. TONE.SET.COM.FM CALL GET.8.DATA JP C,COM.ERROR.18 CP 128 JP NC,COM.ERROR.18 PUSH AF LD A,0*2+193 CALL PUT.DATA.A POP AF LD HL,TONE.NO.WORK ADD A,A ADD A,L:LD L,A:LD A,0:ADC A,H:LD H,A LD E,(HL) INC HL LD D,(HL) EX DE,HL CALL PUT.DATA.HL.1 LD A,(PAN.SWITCH) DEC A JP NZ,MML.SET. LD A,(PAN) JP PAN.COM.1 ; ; ; VOLUME@.COM CALL GET.8.DATA JP C,VOLUME@.COM.3 VOLUME@.COM.0 LD C,A LD A,(FM.FLAG) DEC A LD A,C JP Z,VOLUME@.COM.1 CP 16 JP NC,COM.ERROR.9 JP VOLUME@.COM.2 VOLUME@.COM.1 XOR $7F JP M,COM.ERROR.9 VOLUME@.COM.2 LD (VOLUME),A LD H,A LD L,1*2+193 CALL PUT.DATA.HL JP MML.SET. VOLUME@.COM.3 CALL GET.8A.DATA JP C,COM.ERROR.9 NEG LD C,A JP RELATIVE.VOL ; ; ; LENGTH@.COM CALL GET.16.DATA JP C,COM.ERROR.6 EX DE,HL JP DEF.LENGTH.COM.1 ; ; ; L1COUNT@.COM CALL GET.8.DATA JP C,COM.ERROR.6 LD (L1COUNT),A JP MML.SET. ; ; ; GOSUB@.COM LD A,20*2+193 CALL PUT.DATA.A CALL GET.DATA SUB "A" JP C,COM.ERROR.1 CP 26 JP NC,COM.ERROR.1 CALL MML.ADR.INC ADD A,A LD E,A LD D,0 LD HL,GOSUB.WORK ADD HL,DE LD E,(HL) INC HL LD D,(HL) EX DE,HL CALL PUT.DATA.HL.1 JP MML.SET. ; RETURN@.COM LD A,21*2+193 CALL PUT.DATA.A JP MML.SET. ; ; ; DETUNE@.COM CALL GET.16A.DATA JP C,COM.ERROR.14 LD DE,(DETUNE) ADD HL,DE LD (DETUNE),HL OR A SBC HL,DE LD A,22*2+193 CALL PUT.DATA.A CALL PUT.DATA.HL JP MML.SET. ; ; ; TEMPO@.COM LD A,10*2+193 CALL PUT.DATA.A CALL GET.8A.DATA JP C,COM.ERROR.13 ADD A,(IX+@TEMPO) LD (TEMPO),A JP TEMPO.COM.1 ; ; ; TRANSPOSE@.COM CALL GET.8A.DATA JP C,COM.ERROR.14 LD H,A ADD A,(IX+@TRANSPOSE+1) LD (IX+@TRANSPOSE+1),A LD L,0 LD A,22*2+193 CALL PUT.DATA.A CALL PUT.DATA.HL JP MML.SET. ; ; ; NOISEFREQ@.COM CALL GET.8A.DATA JP C,COM.ERROR.15 LD H,A ADD A,(IX+@NOISEFREQ) LD (IX+@NOISEFREQ),A LD L,24*2+193 CALL PUT.DATA.HL JP MML.SET. ; ; ; PAN@.COM CALL GET.8.DATA LD (PAN.SWITCH),A JP MML.SET. ; PAN.COM CALL GET.8.DATA LD (PAN),A PAN.COM.1 LD H,A LD L,19*2+193 CALL PUT.DATA.HL JP MML.SET. ; ; ; OCTSWITCH.COM CALL GET.8.DATA DEC A JP Z,OCTSWITCH.COM.1 CP 5 JP NZ,COM.ERROR.8 LD HL,OCTUP.COM LD (PATCH1+1),HL LD HL,OCTDOWN.COM LD (PATCH2+1),HL JP MML.SET. OCTSWITCH.COM.1 LD HL,OCTDOWN.COM LD (PATCH1+1),HL LD HL,OCTUP.COM LD (PATCH2+1),HL JP MML.SET. ; ATTACK.MODE.COM CALL GET.8.DATA JP C,COM.ERROR.1 OR A LD A,25*2+193 JP NZ,ATTACK.MODE.COM.1 LD A,26*2+193 ATTACK.MODE.COM.1 CALL PUT.DATA.A JP MML.SET. ; GATE@.COM CALL LENGTH.ANALYZE JP C,COM.ERROR.11 LD E,A LD D,0 CALL LENGTH.FUTEN LD A,E LD (IX+@GATE.FLAG),1 LD (GATE),A LD DE,(LENGTH.DEFAULT) JP DEF.LENGTH.COM.2 ; ; ; HL.DIV.DE PUSH AF PUSH BC PUSH DE LD BC,HL LD HL,0 LD A,16 HL.DIV.DE.1 OR A JP Z,HL.DIV.DE.3 DEC A SLA C:RL B:RL L:RL H OR A SBC HL,DE JP C,HL.DIV.DE.2 INC BC JP HL.DIV.DE.1 HL.DIV.DE.2 ADD HL,DE JP HL.DIV.DE.1 HL.DIV.DE.3 LD HL,BC POP DE POP BC POP AF RET ; ; ; TONE.SET CALL MML.ANALYZE.INIT TONE.SET.1 CALL LINE.SEARCH RET Z CP "@" JP NZ,TONE.SET.1 CALL MML.ADR.INC CALL GET.8.DATA JP C,TONE.SET.ERROR CP 128 CCF JP C,TONE.SET.ERROR LD DE,(DATA.ADR) LD HL,32 ADD HL,DE LD (DATA.ADR),HL LD HL,TONE.NO.WORK ADD A,A ADD A,L LD L,A LD A,0 ADC A,H LD H,A LD (HL),E INC HL LD (HL),D LD IY,DE CALL GET.8.DATA JP C,TONE.SET.ERROR LD C,A CALL GET.8.DATA JP C,TONE.SET.ERROR RLA:RLA:RLA LD (IY+26),A CALL GET.8.DATA JP C,TONE.SET.ERROR LD (IY+30),A CALL GET.8.DATA JP C,TONE.SET.ERROR RRA:RRCA LD D,A CALL GET.8.DATA JP C,TONE.SET.ERROR LD (IY+27),A CALL GET.8.DATA JP C,TONE.SET.ERROR OR $80 LD (IY+29),A CALL GET.8.DATA JP C,TONE.SET.ERROR LD (IY+28),A CALL GET.8.DATA JP C,TONE.SET.ERROR RLCA:RLCA:RLCA:RLCA LD B,A CALL GET.8.DATA JP C,TONE.SET.ERROR OR B LD (IY+1),A CALL GET.8.DATA JP C,TONE.SET.ERROR RRCA:RRCA OR C LD (IY),A CALL GET.8.DATA JP C,TONE.SET.ERROR OR D LD (IY+31),A INC IY:INC IY CALL TONE.SET.2 INC IY:INC IY CALL TONE.SET.2 DEC IY CALL TONE.SET.2 INC IY:INC IY CALL TONE.SET.2 JP TONE.SET.1 TONE.SET.ERROR LD A,18 RET TONE.SET.2 CALL SKIP.GET.DATA CP "0" JP C,TONE.SET.2. CP "9"+1 JP NC,TONE.SET.2. JP TONE.SET.2.. TONE.SET.2. CALL LINE.SEARCH JP Z,TONE.SET.ERROR.1 CP " " JP NZ,TONE.SET.2 TONE.SET.2.. CALL GET.8.DATA JP C,TONE.SET.2 LD B,A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 LD C,A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 LD D,A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 LD E,A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 RLCA:RLCA:RLCA:RLCA OR E LD (IY+20),A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 LD (IY+4),A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 RRCA:RRCA OR B LD (IY+8),A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 LD B,A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 RLCA:RLCA:RLCA:RLCA OR B LD (IY+0),A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 RRCA:RRCA OR D LD (IY+16),A CALL GET.8.DATA JP C,TONE.SET.ERROR.1 RRCA OR C LD (IY+12),A RET TONE.SET.ERROR.1 POP AF LD A,15 RET