;FM-DRIVER NEW VERSION ;BY GORRY! 87/10/7-88/01/24 ORG $F200 PROGRAM.START ;{{{{{{{{{{{{{{{{{{{{ INITIALIZE ;IN DE=MML START ADDRESS. JP DIM.TONESET JP FM.M.TRK JP FM.TEMPO JR FM.DRIVER FM.ERRORPRINT LD HL,(ERRADRW):LD A,H:OR L:RET Z LD DE,FM.MSG1:CALL $1202 ;PRINT HL CALL $0483:PUSH HL:LD A,H:SUB $40:LD H,0:LD L,A ;PRINT (DE) LD C,$18:CALL FM.DIV:ADD A,$31:CALL $04C8 ;PRINT CHR$(A) POP HL:CALL $04BA:LD DE,20:OR A:SBC HL,DE LD BC,HL:INC E FM.ERRORPRINT1 IN A,(C):CALL $04C8 ;PRINT CHR$(A); INC BC:DEC E:JR NZ,FM.ERRORPRINT1 LD A,13:JP $04BC ;PRINT CHR$(13); FM.MSG1 DM "HÃÞ ERR. Äׯ¸" DB 0 FM.DRIVER CP 3:RET NZ LD A,(DE):INC DE:AND $5F CP "F" JP Z,FM.FADEOUT. CP "S" JP Z,FM.OFF CP "P" RET NZ DJNZ FM.P.OPTION LD A,$18 ;JR n LD (FM.CLEAR1),A JR FM.START FM.P.OPTION LD A,$3E ;LD A,n (JR KILL PATCH) LD (FM.CLEAR1),A LD A,B:CP 8:RET NZ FM.START DI:LD (FM.STACKW),SP:LD SP,FM.STACK+40 PUSH AF EX AF,AF':EXX PUSH AF:PUSH BC EX AF,AF':EXX PUSH BC PUSH DE PUSH HL PUSH IX PUSH IY EX DE,HL LD IX,FM.WORKSTART LD DE,FM.WORKSTEP XOR A:LD C,A LD B,8 FM.CLEAR DEC B:XOR A:LD (IX+FM@KEYFLAG),A PUSH DE:LD A,7:SUB B:LD (FM.CHANNEL),A CALL FM.KEYOFF POP DE INC B:LD A,1 LD (IX+FM@OFFWAIT),A LD (IX+FM@OFFWAIT+1),A:DEC A LD (IX+FM@ONWAIT),A LD (IX+FM@ONWAIT+1),A FM.CLEAR1 JR FM.CLEAR2 LD A,(HL):INC HL CP "1":LD A,0:RLA:PUSH AF:ADD A,C:LD C,A:POP AF FM.CLEAR2 LD (IX+FM@ENDFLAG),A ADD IX,DE DJNZ FM.CLEAR XOR A LD (FM.CHANNEL),A:LD (ERRADRW),A:LD (ERRADRW+1),A LD (FM.FADEPATCH),A:LD (FM.FADEWORK),A LD A,8:SUB C LD (FM.ENDCOUNT),A CALL FM.MMLADRSET CALL FM.CTCSET2:LD IX,FM.WORKSTART:JP FM.MLOOP4 ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ MML ANALYZE ;IN IX=WORK AREA START ADDRESS. FM.KAISEKI LD C,(IX+FM@MMLADR) LD B,(IX+FM@MMLADR+1) PUSH BC:POP IY FM.K.LOOP PUSH IY:POP BC:IN A,(C) INC IY ;-------------------- MML COMMAND CHECK OR A JP Z,FM.MMLEND CP " " JR Z,FM.K.LOOP CP "@" JP Z,FM.TONESET OPATCH1 CP ">" ;ºÉ ÌÀ ¦ JP Z,FM.OCTUP OPATCH2 CP "<" ;²Ú¶´Ù Ä X-68000 Æ ÅØϽ¡ JP Z,FM.OCTDOWN CP "^" JP Z,FM.DETUNE CP "|" JP Z,FM.REPEATSET CP ":" JP Z,FM.REPEATJUMP CP "[" JP Z,FM.RETURNSET CP "]" JP Z,FM.RETURNJUMP CP $9F ;ÊÞ¯¸½×¯¼­ JP Z,FM.FADEOUT CP "/" JP Z,FM.KEYOFF... CP "(" JP Z,FM.PORTAMENTO AND $5F CP "P" JP Z,FM.PAN CP "X" JP Z,FM.EXCHG CP "Y" JP Z,FM.WRTREG CP "V" JP Z,FM.VOLUME CP "R" JP Z,FM.KYUFU CP "L" JP Z,FM.LENGTH CP "O" JP Z,FM.OCTSET CP "Q" JP Z,FM.GATESET CP "T" JP Z,FM.TEMPO. CP "S" JP Z,FM.SOFT.ENVELOP.SET CP "W" JP Z,FM.DELAYSET CALL FM.ONPUANALYZE JP C,FM.ERROR:JR FM.ONPU ;-------------------- FM.ONPUANALYZE SUB "A" RET C CP 7 CCF:RET C LD D,A PUSH IY:POP BC:IN A,(C) CP "#" JR Z,FM.SHARP CP "+" JR Z,FM.SHARP CP "-" SCF:CCF:RET NZ FM.FLAT LD A,14 JR FM.ONPUPLUS FM.SHARP LD A,7 FM.ONPUPLUS ADD A,D LD D,A INC IY RET ;-------------------- FM.ONPU LD A,D:LD (FM.ONPUCODE),A LD HL,FM.FREQTABLE ADD A,L LD L,A LD A,0 ADC A,H LD H,A LD A,(IX+FM@OCTERV) ADD A,(HL) LD (IX+FM@FREQ),A LD D,A LD A,(FM.CHANNEL) ADD A,$28 ;OPM REGISTER OF [KEY CODE] CALL FM.WRITE LD D,(IX+FM@DETUNE) LD (IX+FM@FREQ+1),D ADD A,8 CALL FM.WRITE CALL FM.KEYON XOR A LD (IX+FM@PORTAW),A LD (IX+FM@PORTAW+1),A LD A,(IX+FM@S.DELAY) LD (IX+FM@S.DELAYW),A XOR A:EX AF,AF' LD DE,0 FM.TIE CALL FM.ONCHOU LD L,A:LD H,0 CALL FM.FUTEN ADD HL,DE:EX DE,HL PUSH IY:POP BC:IN A,(C) CP "&":SCF:CCF JR NZ,FM.NOTTIE2 INC IY:EX AF,AF':INC A:EX AF,AF' PUSH IY:POP BC:PUSH BC:IN A,(C):INC IY AND $5F:PUSH DE:CALL FM.ONPUANALYZE:LD A,D:POP DE POP BC:JR C,FM.NOTTIE. DB $FE ;CP n FM.ONPUCODE DB 0 JR Z,FM.TIE FM.NOTTIE. PUSH BC:POP IY FM.NOTTIE EX AF,AF':ADD A,255 FM.NOTTIE2 LD A,0:RLA:LD (IX+FM@KEYFLAG),A FM.NOTTIE1 EX DE,HL PUSH HL LD C,(IX+FM@GATE):CALL FM.MULHL LD C,8 CALL FM.DIV LD (IX+FM@ONWAIT),L LD (IX+FM@ONWAIT+1),H POP DE EX DE,HL OR A:SBC HL,DE INC HL:INC H LD (IX+FM@OFFWAIT),L LD (IX+FM@OFFWAIT+1),H:JR FM.ONPUEND1 FM.TIE. PUSH IY:POP BC:IN A,(C) CP "&" LD A,0 JR NZ,FM.ONPUEND INC A INC IY FM.ONPUEND LD (IX+FM@KEYFLAG),A FM.ONPUEND1 PUSH IY:POP BC LD (IX+FM@MMLADR),C LD (IX+FM@MMLADR+1),B JP FM.MLOOP5 ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ ONCHOU ANALYZE ;IN IY=MML ADDRESS ;OUT Areg=ONCHOU (ERROR...Areg=DEFAULT) FM.ONCHOU DB $FD LD B,H:DB $FD LD C,L:IN A,(C) CP "%" JR Z,FM.ONCHOU% CALL FM.GET10 JR NC,FM.ONCHOU1 LD A,(IX+FM@LNGDEF):JR FM.ONCHOUDEF FM.ONCHOU1 FM.ONCHOU. FM.NOT64 LD HL,192 ;»²ÀÝ µÝÌß LD C,A CALL FM.DIV JR C,FM.ONCHOUERR FM.ONCHOUDEF LD C,A LD B,1 FM.ONCHOU.. EXX:PUSH IY:POP BC:IN A,(C):EXX CP "." LD A,C RET NZ INC B INC IY JR FM.ONCHOU.. FM.ONCHOU% INC IY CALL FM.GET10 JR C,FM.ONCHOUERR LD B,1:RET FM.ONCHOUERR POP AF ;CALL-STACK KILL JP FM.ERROR ;-------------------- FUTEN SHORI FM.FUTEN PUSH DE:PUSH BC LD DE,HL FM.FUTEN1 DEC B JR Z,FM.FUTENEND SRL D RR E ADD HL,DE JR FM.FUTEN1 FM.FUTENEND POP BC:POP DE RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ GET 10¼Ý DATA ;IN IY=MML ADDRESS ;OUT Areg=DATA (ERROR...Cy=1) FM.GET10 EXX:PUSH IY:POP BC:IN A,(C):EXX CP "$" JP Z,FM.GET16 SUB "0" RET C CP 10 CCF RET C PUSH BC FM.GET10A LD C,A INC IY EXX:PUSH IY:POP BC:IN A,(C):EXX SUB "0" JR C,FM.GET10E CP 10 JR NC,FM.GET10E LD B,A LD A,C ADD A,A ADD A,A ADD A,A ADD A,C ADD A,C ADD A,B JR FM.GET10A FM.GET10E LD A,C POP BC OR A ;Cy=0 RET ;-------------------- FM.GET10F PUSH IY:POP BC:IN A,(C) CP "-" JR Z,FM.GET10F. CALL FM.GET10 JP C,FM.ONCHOUERR RET FM.GET10F. INC IY CALL FM.GET10 JP C,FM.ONCHOUERR OR $80 RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ GET HEX DATA ;IN IY=MML ADDRESS-1 ;OUT Areg=DATA (ERROR...Cy=1) FM.GET16 INC IY CALL FM.A2HEX RET ;-------------------- 2HEX (MZ-700 1Z-009A ÖØ) FM.A2HEX PUSH BC EXX:PUSH IY:POP BC:IN A,(C):EXX INC IY CALL FM.HEX JR C,FM.A2HEX1 RRCA RRCA RRCA RRCA LD C,A EXX:PUSH IY:POP BC:IN A,(C):EXX INC IY CALL FM.HEX JR C,FM.A2HEX1 OR C FM.A2HEX1 POP BC RET ;-------------------- HEX (MZ-700 1Z-009A ÖØ) FM.HEX CP $30 RET C CP $3A JR C,FM.HEX1 SUB 7 CP $40 CCF RET C FM.HEX1 AND $0F RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ WRITE TO OPM FM.WRITE PUSH BC LD BC,$0701 EX AF,AF' FM.WRITE1 IN A,(C) BIT 7,A JP NZ,FM.WRITE1 DEC C EX AF,AF' OUT (C),A INC C OUT (C),D POP BC RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ OPM REGISTER [OUTPUT LEVEL] STORE FM.OPMWORKSET SUB $60 RET C CP $20 RET NC PUSH DE LD DE,FM.OP1WORK ADD A,E LD E,A LD A,0 ADC A,D LD D,A POP AF LD (DE),A RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ Y COMMAND FM.WRTREG CALL FM.GET10 JP C,FM.ERROR INC IY LD C,A PUSH BC CALL FM.GET10 POP BC JP C,FM.ERROR LD D,A LD A,C FM.WRTREG1 CALL FM.WRITE PUSH AF:PUSH DE CALL FM.OPMWORKSET POP DE:POP AF SUB $30:JP C,FM.K.LOOP CP 8:JP NC,FM.K.LOOP LD C,FM.WORKSTEP CALL FM.MUL LD BC,FM.WORKSTART+FM@DETUNE ADD HL,BC LD (HL),D JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ KEY ON (LFO OFF) FM.KEYON LD A,(IX+FM@KEYFLAG) DEC A RET Z LD A,(FM.CHANNEL) ADD A,(IX+FM@OPMASK) LD D,A LD A,$08 ;OPM REGISTER [KEY ON&OFF] CALL FM.WRITE FM.LFOOFF FM.LFOOUT FM.LFOON LD A,(IX+FM@LFOSYNC) DEC A:RET NZ LD A,$01 ;OPM REGISTER[LFO RESET] LD D,2 CALL FM.WRITE LD D,0 JP FM.WRITE ;D1 ÀÁ»¹Þ ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ KEY OFF FM.KEYOFF... LD HL,FM.K.LOOP PUSH HL JP FM.KEYOFF. FM.KEYOFF LD A,(IX+FM@KEYFLAG) DEC A RET Z FM.KEYOFF. LD A,(FM.CHANNEL) LD D,A LD A,8 JP FM.WRITE ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ KAKEZAN FM.MUL ;HL=A*C LD L,A LD H,0 FM.MULHL ;HL=HL*C PUSH DE:EX DE,HL:PUSH AF LD HL,0 LD A,C FM.MULHL1 SRL A JR NC,FM.MULHL2 ADD HL,DE FM.MULHL2 SLA E RL D OR A JR NZ,FM.MULHL1 POP AF:POP DE RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ WARIZAN FM.DIV ;A=HL/C (HL=HL/C) PUSH DE:EX DE,HL LD HL,0:LD B,H LD A,16 FM.DIV1 EX DE,HL:ADD HL,HL:EX DE,HL ADC HL,HL OR A SBC HL,BC JR C,FM.NOTDIV INC DE FM.DIV1. DEC A JR NZ,FM.DIV1 LD A,E:OR A:EX DE,HL:POP DE RET FM.NOTDIV ADD HL,BC JR FM.DIV1. ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ KYUFU(R COMMAND) FM.KYUFU CALL FM.ONCHOU FM.KYUFU1 LD L,A:LD H,0 CALL FM.FUTEN INC HL:INC H LD (IX+FM@OFFWAIT),L LD (IX+FM@OFFWAIT+1),H XOR A LD (IX+FM@ONWAIT),A LD (IX+FM@ONWAIT+1),A LD (IX+FM@PORTAW),A LD (IX+FM@PORTAW+1),A JP FM.TIE. ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ OCTERVE SET(O COMMAND) FM.OCTSET CALL FM.GET10 JP C,FM.ERROR CP 9 JP NC,FM.ERROR JP Z,FM.ERROR DEC A ADD A,A ADD A,A ADD A,A ADD A,A LD (IX+FM@OCTERV),A JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ OCTERVE UP & DOWN (>,< COMMAND) FM.OCTUP LD A,$10 JR FM.OCTCALC FM.OCTDOWN LD A,$F0 FM.OCTCALC ADD A,(IX+FM@OCTERV) CP $80 JP NC,FM.ERROR LD (IX+FM@OCTERV),A JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ ONCHOU DEFAULT SET(L COMMAND) FM.LENGTH CALL FM.ONCHOU LD (IX+FM@LNGDEF),A JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ GATE SET(Q COMMAND) FM.GATESET CALL FM.GET10 JP C,FM.ERROR CP 9 JP NC,FM.ERROR LD (IX+FM@GATE),A JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ STEREO SET(P COMMAND) FM.STEREO LD A,(IX+FM@RL.FB.AL) AND $3F OR B LD D,A LD A,(FM.CHANNEL) ADD A,$20 ;OPM REGISTER [RL.FB.AL] CALL FM.WRITE JP FM.K.LOOP FM.PAN CALL FM.GET10 JP C,FM.ERROR RRCA:RRCA LD B,A JR FM.STEREO ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ DETUNE SET(^ COMMAND) FM.DETUNE PUSH IY:POP BC:IN A,(C) CP "+" JR Z,FM.DETUNEPLUS CP "-" JR Z,FM.DETUNEMINUS CALL FM.GET10 JP C,FM.ERROR LD (IX+FM@DETUNE),A LD D,A:LD A,(FM.CHANNEL):ADD A,$30:CALL FM.WRITE JP FM.K.LOOP ;-------------------- FM.DETUNEPLUS INC IY CALL FM.GET10 JP C,FM.ERROR DB $DD LD D,H:DB $DD LD E,L LD HL,FM@FREQ+1 ADD HL,DE ADD A,(HL) PUSH AF:LD D,A LD A,$30 ;OPM REGISTER[KEY FRACTION] LD C,A CALL FM.WRITE:LD (HL),D DEC HL POP AF:LD A,(HL) ADC A,0 LD B,A AND 3 CP 3:CCF LD A,B ADC A,0 LD D,A LD A,$F8:ADD A,C CALL FM.WRITE:LD (HL),D JP FM.K.LOOP FM.DETUNEMINUS INC IY CALL FM.GET10 JP C,FM.ERROR DB $DD LD D,H:DB $DD LD E,L LD HL,FM@FREQ+1 ADD HL,DE LD B,A:LD A,(HL):SUB B PUSH AF:LD D,A LD A,$30 ;OPM REGISTER[KEY FRACTION] LD C,A CALL FM.WRITE:LD (HL),D DEC HL POP AF:LD A,(HL) SBC A,0 LD B,A AND 3 CP 3:CCF LD A,B SBC A,0 LD D,A LD A,$F8:ADD A,C CALL FM.WRITE:LD (HL),D JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ VOLUME SET(V COMMAND) FM.VOLUME CALL FM.VOLUME... JP FM.K.LOOP FM.VOLUME... CALL FM.GET10 JP C,FM.ONCHOUERR LD C,3 CALL FM.MUL LD A,80 ADD A,L JR FM.VOLUME1. FM.VOLUME1 INC IY PUSH IY:POP BC:IN A,(C) CP "+" JR Z,FM.VOLPLUS CP "-" JR NZ,FM.VOLUME@ FM.VOLMINUS INC IY:CALL FM.GET10 JP C,FM.ONCHOUERR NEG:ADD A,(IX+FM@VOLUME) JR C,FM.VOLUME1. XOR A JR FM.VOLUME1. FM.VOLPLUS INC IY:CALL FM.GET10 JP C,FM.ONCHOUERR ADD A,(IX+FM@VOLUME) CP 128:JR C,FM.VOLUME1. LD A,127 JR FM.VOLUME1. FM.VOLUME@ CALL FM.GET10 JP C,FM.ONCHOUERR FM.VOLUME1. LD (IX+FM@VOLUME),A FM.VOLUME. LD C,A LD A,(FM.CHANNEL) LD HL,FM.OP4WORK ADD A,L LD L,A LD A,0 ADC A,H LD H,A LD A,(HL) CALL FM.VOLCALC LD D,A LD A,(FM.CHANNEL) ADD A,$78 ;OPM REGISTER [OP4 OUTPUT LEVEL] CALL FM.WRITE LD A,(IX+FM@RL.FB.AL) AND 7 CP 4 RET C LD DE,8 SBC HL,DE PUSH AF LD A,(HL) CALL FM.VOLCALC LD D,A LD A,(FM.CHANNEL) ADD A,$70 CALL FM.WRITE POP AF CP 5 RET C LD DE,8 SBC HL,DE PUSH AF LD A,(HL) CALL FM.VOLCALC LD D,A LD A,(FM.CHANNEL) ADD A,$68 CALL FM.WRITE POP AF CP 7 RET NZ LD DE,8 SBC HL,DE LD A,(HL) CALL FM.VOLCALC LD D,A LD A,(FM.CHANNEL) ADD A,$60 CALL FM.WRITE RET ;-------------------- ;-------------------- VOLUME CALC FM.VOLCALC PUSH BC LD B,A:LD A,127:SUB C:ADD A,B:LD B,A:LD A,(FM.FADEWORK):ADD A,B CP $80 JR C,FM.VOLCALC1 LD A,127 FM.VOLCALC1 POP BC:RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ TONE SET FM.TONESET DB $FD LD B,H:DB $FD LD C,L:IN A,(C):LD HL,FM.K.LOOP ;CALL STACK PUSH HL:CP "V":JP Z,FM.VOLUME1:CP "v":JP Z,FM.VOLUME1 POP HL:CALL FM.GET10 JP C,FM.ERROR CP 33 JP NC,FM.ERROR LD H,0 LD L,A ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL EX DE,HL LD HL,(FM.TONEADR) ADD HL,DE LD D,(HL) INC HL LD A,(FM.CHANNEL) LD B,D CP 7 ;LAST CHANNEL JR NZ,FM.NOTNOISE LD A,$0F ;OPM REGISTER [NOISE FREQ] CALL FM.WRITE JR FM.NOTLFO FM.NOTNOISE OR A ;FIRST CHANNEL JR NZ,FM.NOTLFO XOR A BIT 6,B JR Z,FM.NOTSYNC INC A FM.NOTSYNC LD (IX+FM@LFOSYNC),A LD A,1 LD D,2 CALL FM.WRITE LD D,0 CALL FM.WRITE ;LFO RESET LD D,(HL) INC HL LD A,$18 ;OPM REGISTER [LFRQ] CALL FM.WRITE LD D,(HL) INC HL INC A ;OPM REGISTER [P.AMD] CALL FM.WRITE LD D,(HL) LD A,$1B ;OPM REGISTER [WAVE FORM] CALL FM.WRITE JR FM.TONESET1 FM.NOTLFO INC HL INC HL FM.TONESET1 LD A,(HL) AND $78 LD (IX+FM@OPMASK),A INC HL LD D,(HL) LD A,(FM.CHANNEL) ADD A,$20 ;OPM REGISTER [RL.FB.AL] CALL FM.WRITE LD (IX+FM@RL.FB.AL),D ADD A,$18 ;OPM REGISTER [P.AMS] INC HL LD D,(HL) CALL FM.WRITE LD (IX+FM@P.AMSWORK),D ADD A,8 FM.TONESET2 INC HL LD D,(HL) CALL FM.WRITE PUSH AF CALL FM.OPMWORKSET POP AF ADD A,8 JR NC,FM.TONESET2 FM.TONESET3 INC HL LD D,(HL) SET 7,D LD A,$19 ;OPM REGISTER [P.AMD] CALL FM.WRITE LD A,(IX+FM@VOLUME) CALL FM.VOLUME1.:JP FM.K.LOOP ; ; REPEAT SET FM.REPEATSET INC IY:CALL FM.GET10 JR NC,FM.REPEATSET1 LD A,2 FM.REPEATSET1 LD (IX+FM@REPCOUNT),A PUSH IY:POP BC LD (IX+FM@REPEAT),C LD (IX+FM@REPEAT+1),B JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ REPEAT JUMP (:| COMMAND) FM.REPEATJUMP PUSH IY:POP BC:IN A,(C) CP "|":JR NZ,FM.REPEATJUMP2 INC IY:DEC (IX+FM@REPCOUNT) JP Z,FM.K.LOOP FM.REPEATJUMP1 INC BC LD (IX+FM@REPEATENDADR+1),B LD (IX+FM@REPEATENDADR),C LD C,(IX+FM@REPEAT) LD B,(IX+FM@REPEAT+1) PUSH BC:POP IY JP FM.K.LOOP FM.REPEATJUMP2 LD A,(IX+FM@REPCOUNT) DEC A:JP NZ,FM.K.LOOP LD C,(IX+FM@REPEATENDADR) DB $FD LD L,C LD B,(IX+FM@REPEATENDADR+1) DB $FD LD H,B JP FM.K.LOOP ; ;{{{{{{{{{{{{{{{{{{{{ MUGEN LOOP SET ([ COMMAND) ¼ÞÂÊ ³´Ä µÅ¼Þ¥¥ FM.RETURNSET CALL FM.GET10 JR NC,FM.RETURNSET1 LD A,2 FM.RETURNSET1 LD (IX+FM@REPCOUNT2),A PUSH IY:POP BC LD (IX+FM@RETURN),C LD (IX+FM@RETURN+1),B JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ MUGEN LOOP JUMP (] COMMAND) ÓÄÊ Ñ¹ÞÝÙ°Ìß FM.RETURNJUMP ;¾ÝÖ³ ÀÞ¯ÀÝÀÞÖ¡ LD A,(IX+FM@REPCOUNT2) OR A:JR Z,FM.RETURNJUMP1 DEC (IX+FM@REPCOUNT2) JP Z,FM.K.LOOP FM.RETURNJUMP1 LD C,(IX+FM@RETURN) LD B,(IX+FM@RETURN+1) PUSH BC:POP IY JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ TEMPO SET FM.TEMPO. CALL FM.GET10 JP C,FM.ERROR LD C,A CALL FM.TEMPO1 JP FM.K.LOOP ;-------------------- FM.TEMPO CP 2:RET NZ:LD C,(HL) FM.TEMPO1 LD HL,9766:CALL FM.DIV ;1000/192(ms)/(250*16*8)*60 LD (FM.TEMPOW),A:JP FM.CTCSET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ EXCHANGE <,> (X6,X1 COMMAND) ºÚÃÞ X68 ¶×Ó FM.EXCHG ;PC88 ¶×Ó CALL FM.GET10 ; ׸ÃÞ¼®! JP C,FM.ERROR CP 6 JR NZ,FM.EXCHG1 LD HL,OPATCH1+1 LD (HL),"<" LD HL,OPATCH2+1 LD (HL),">" JP FM.K.LOOP FM.EXCHG1 DEC A JP NZ,FM.ERROR LD HL,OPATCH1+1 LD (HL),">" LD HL,OPATCH2+1 LD (HL),"<" JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ FADE OUT FM.FADEOUT. DEC B:JR Z,FM.FADEOUT.. LD A,(DE) JR FM.FADEOUT... FM.FADEOUT CALL FM.GET10 LD HL,FM.K.LOOP:PUSH HL ;CALL STACK JR NC,FM.FADEOUT... FM.FADEOUT.. LD A,8 FM.FADEOUT... LD (FM.FADETIMING),A LD (FM.FADETIME),A LD A,$34 ;INC (HL) LD (FM.FADEPATCH),A XOR A LD (FM.FADEWORK),A RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ SOFT ENVELOP SET FM.SOFT.ENVELOP.SET CALL FM.GET10 JP C,FM.ERROR LD (IX+FM@S.SPEED),A INC IY:CALL FM.GET10F JP C,FM.ERROR LD (IX+FM@S.PMD),A INC IY:CALL FM.GET10 JP C,FM.ERROR LD (IX+FM@S.PMS),A ; INC IY:CALL FM.GET10F ; JP C,FM.ERROR ; LD (IX+FM@S.AMD),A ; INC IY:CALL FM.GET10 ; JP C,FM.ERROR ; LD (IX+FM@S.AMS),A INC IY:CALL FM.GET10 JP C,FM.ERROR INC A:LD (IX+FM@S.DELAY),A ; INC IY:CALL FM.GET10 ; JP C,FM.ERROR ; LD (IX+FM@S.WAVEFORM),A JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ SOFT ENVELOP DELAY SET FM.DELAYSET CALL FM.GET10 JP C,FM.ERROR INC A:LD (IX+FM@S.DELAY),A JP FM.K.LOOP ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ PORTAMENTO SET FM.PORTAMENTOONKAI CALL FM.GET10 JR NC,FM.PORTAMENTO1 LD A,(IX+FM@OCTERV) OR A:RRCA:RRCA:RRCA:RRCA:INC A FM.PORTAMENTO1 LD C,12:CALL FM.MUL:PUSH HL PUSH IY:POP BC:IN A,(C):INC IY CALL FM.ONPUANALYZE:LD A,D JP C,FM.ONCHOUERR LD HL,FM.FREQTABLE1 ADD A,L LD L,A LD A,0 ADC A,H LD H,A LD A,(HL) POP BC ADD A,C RET FM.PORTAMENTO CALL FM.PORTAMENTOONKAI LD (FM.PORTAPATCH),HL:PUSH AF INC IY CALL FM.PORTAMENTOONKAI:INC IY POP BC:SUB B JR C,FM.PORTAMENTOMINUS FM.PORTAMENTOPLUS PUSH AF ; INC IY CALL FM.ONCHOU:LD H,0:LD L,A:CALL FM.FUTEN:LD A,L POP HL:PUSH AF:LD L,0 LD C,A CALL FM.DIV JR FM.PORTAMENTO. FM.PORTAMENTOMINUS NEG PUSH AF ; INC IY CALL FM.ONCHOU:LD H,0:LD L,A:CALL FM.FUTEN:LD A,L POP HL:PUSH AF:LD L,0 LD C,A CALL FM.DIV:EX DE,HL:LD HL,0:OR A:SBC HL,DE FM.PORTAMENTO. LD (IX+FM@PORTAW),L LD (IX+FM@PORTAW+1),H POP AF LD (IX+FM@ONWAIT),A XOR A LD (IX+FM@ONWAIT+1),A INC A LD (IX+FM@OFFWAIT),A LD (IX+FM@OFFWAIT+1),A DB $21 ;LD HL,nn FM.PORTAPATCH DW 0 LD DE,21:SBC HL,DE LD A,(IX+FM@OCTERV):ADD A,(HL) LD D,A:LD A,(FM.CHANNEL) ADD A,$28 ;OPM REGISTER[KEY CODE] CALL FM.WRITE LD (IX+FM@FREQ),D LD D,(IX+FM@DETUNE) ADD A,8 ;OPM REGISTER[KEY FRACTION] CALL FM.WRITE LD (IX+FM@FREQ+1),D CALL FM.KEYON LD A,(IX+FM@S.DELAY) LD (IX+FM@S.DELAYW),A JP FM.TIE. ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ MML END FM.MMLEND DB $FD LD A,L LD (IX+FM@MMLADR),A DB $FD LD A,H LD (IX+FM@MMLADR+1),A LD A,1 LD (IX+FM@ENDFLAG),A LD HL,FM.ENDCOUNT DEC (HL) JP NZ,FM.M.LOOP FM.MMLEND1 CALL FM.OFF LD IY,1 ;NO ERROR DAYO-N! JR FM.POPREG ;FM DRIVER END... ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ ERROR SHORI FM.OFF CALL FM.CTCOFF LD HL,FM.KEYFLAG LD BC,FM.WORKSTEP LD D,7 LD A,8 ;OPM REGISTER[KEY ON&OFF] FM.OPMOFF CALL FM.WRITE DEC D JR NZ,FM.OPMOFF JP FM.WRITE ;-------------------- FM.ERROR CALL FM.OFF FM.POPREG DEC IY:LD (ERRADRW),IY POP IY POP IX POP HL POP DE POP BC EX AF,AF':EXX POP BC:POP AF EX AF,AF':EXX POP AF LD SP,(FM.STACKW) EI RETI ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ TIMING LOOP FM.M.LOOP LD DE,FM.WORKSTEP ADD IX,DE LD A,(FM.CHANNEL) INC A AND 7 LD (FM.CHANNEL),A JP NZ,FM.MLOOP4 LD HL,FM.FADETIME DEC (HL) ; LD (FM.FADETIME),A JP NZ,FM.NOTFADE DB $36 ;LD (HL),n FM.FADETIMING DB 0 INC HL LD A,(HL) ;FM.FADEWORK FM.FADEPATCH DB 0 ;INC (HL) ; LD (FM.FADEWORK),A CP $7F:JP NC,FM.MMLEND1 FM.NOTFADE POP IY POP IX POP HL POP DE POP BC EX AF,AF':EXX POP BC:POP AF EX AF,AF':EXX POP AF LD SP,(FM.STACKW) EI RETI ; {{{{{{{{{{{{{{{{{{{{ INTERRUPT ROUTINE ÜØºÐ¶Þ ¶¶ÙÄ ººÍ ¸ÙÝÀÞÖ! FM.INT LD (FM.STACKW),SP:LD SP,FM.STACK+40 PUSH AF EX AF,AF':EXX PUSH AF:PUSH BC EX AF,AF':EXX PUSH BC PUSH DE PUSH HL PUSH IX PUSH IY LD BC,$1A01 ;8255 ADDRESS FM.INT... IN A,(C) AND $40 ;ºÚ ¼Å²Ä ·°ÜØºÐ¶Þ ·¶Å¸ ůÁ¬³ÝÀÞÖ¯!(Ö°½ÙÆ ÎÞ³¿³) JP NZ,FM.INT... ;Oh! MZ 1985/10 P107 Æ ¶²Ã±¯Àؽ١ ºÚɾ²ÃÞ ÅÝÄÞ DI ;¶Î߯ÀºÄ¶¥¥¥ SHARP É ÊÞ¶ÔÛ°°°!! LD IX,FM.WORKSTART FM.MLOOP4 LD A,(IX+FM@ENDFLAG) DEC A JP Z,FM.M.LOOP LD A,(IX+FM@VOLUME):CALL FM.VOLUME. FM.SOFT.ENVELOP LD HL,FM@S.DELAYW DB $DD LD D,H:DB $DD LD E,L ADD HL,DE LD A,(HL) OR A JP Z,FM.SOFT.PM DEC (HL) JP NZ,FM.MLOOP5 DEC HL LD (HL),A DEC HL LD A,(IX+FM@S.PMD):SRA A:RES 6,A:LD (HL),A DEC HL XOR A:LD (HL),A JP FM.SOFT.PM. FM.SOFT.PM DEC HL DEC HL DEC HL FM.SOFT.PM. LD A,(HL) ;SPEEDW ADD A,(IX+FM@S.SPEED) LD (HL),A JP NC,FM.MLOOP5 INC HL LD B,(HL) ;PMFLAG LD C,(IX+FM@FREQ) LD A,(IX+FM@FREQ+1) BIT 7,B JP Z,FM.PMPLUS FM.PMMINUS SUB (IX+FM@S.PMS) LD (IX+FM@FREQ+1),A ; PUSH AF ; LD D,A ; LD A,(FM.CHANNEL) ; ADD A,$30 ;OPM REGISTER[KEY FRACTION] ; CALL FM.WRITE ; POP AF LD A,C SBC A,0 LD D,A AND 3 SUB 3:CCF LD A,D:SBC A,0 LD (IX+FM@FREQ),A ; LD D,A ; LD A,(FM.CHANNEL) ; ADD A,$28 ;OPM REGISTER[KEY CODE] ; CALL FM.WRITE JP FM.PMCOUNT FM.PMPLUS ADD A,(IX+FM@S.PMS) LD (IX+FM@FREQ+1),A ; PUSH AF ; LD D,A ; LD A,(FM.CHANNEL) ; ADD A,$30 ;OPM REGISTER[KEY FRACTION] ; CALL FM.WRITE ; POP AF LD A,C ADC A,0 LD D,A AND 3 SUB 3:CCF LD A,D:ADC A,0 LD (IX+FM@FREQ),A ; LD D,A ; LD A,(FM.CHANNEL) ; ADD A,$28 ;OPM REGISTER[KEY CODE] ; CALL FM.WRITE FM.PMCOUNT DEC B LD A,B AND $7F JP NZ,FM.PMEND LD A,(IX+FM@S.PMD):AND $7F ADD A,B XOR $80 LD B,A FM.PMEND LD (HL),B FM.MLOOP5 LD H,(IX+FM@FREQ) LD L,(IX+FM@FREQ+1) LD E,(IX+FM@PORTAW) LD D,(IX+FM@PORTAW+1) ADD HL,DE LD A,H:AND 3:CP 3:JP NZ,FM.MLOOP5. LD A,D:RLA:LD A,0:RLA:RLA:SUB H:NEG:INC A:LD H,A FM.MLOOP5. LD A,(FM.CHANNEL):ADD A,$28 ;OPM REGISTER[KEY CODE] LD D,H:CALL FM.WRITE:LD (IX+FM@FREQ),H ADD A,8 ;OPM REGISTER[KEY FRACTION] LD D,L:CALL FM.WRITE:LD (IX+FM@FREQ+1),L FM.MLOOP5.. LD L,(IX+FM@ONWAIT) LD H,(IX+FM@ONWAIT+1) LD A,H OR L JP Z,FM.MLOOP6 DEC HL LD (IX+FM@ONWAIT),L LD (IX+FM@ONWAIT+1),H LD A,H OR L CALL Z,FM.KEYOFF JP FM.M.LOOP FM.MLOOP6 DEC (IX+FM@OFFWAIT) JP NZ,FM.M.LOOP DEC (IX+FM@OFFWAIT+1) JP NZ,FM.M.LOOP JP FM.KAISEKI ;{{{{{{{{{{{{{{{{{{{{ CTC SET FM.CTCSET ;{{{{{{{{{{{{{{{{{{{{ FM.CTCSET1 FM.CTCSET2 LD BC,$0704 ;turbo - $1FA0 LD A,7 OUT (C),A LD A,32 OUT (C),A LD A,$58 OUT (C),A LD C,7 ;turbo - 3 LD A,$C7 OUT (C),A DB $3E ;LD A,n FM.TEMPOW DB 0 OUT (C),A LD HL,FM.INT LD ($005E),HL ;INTERRUPT VECTOR SET ºÚ»´ ¶´Ø¬ TurboBASIC ÃÞÓ ;OK É Ê½ÞÃÞ½¶Þ¥¥¥ ËÏÅ ËÄÊ Ô¯ÃÐà Á®ÝϹÞ! RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ CTC OFF FM.CTCOFF LD BC,$0704 ;Turbo - $1FA0 LD A,3 OUT (C),A RET ;{{{{{{{{{{{{{{{{{{{{ ;{{{{{{{{{{{{{{{{{{{{ MML ADDRESS SET FM.MMLADRSET LD DE,FM.WORKSTEP-1 LD HL,FM.MMLADR LD A,$40:LD C,0 FM.MMLADRSET1 LD (HL),C INC HL LD (HL),A ADD HL,DE ADD A,$18 JR NZ,FM.MMLADRSET1 RET FM.MMLSTARTSET LD A,$40:LD C,0 LD HL,FM.MMLSTART FM.MMLSTARTSET1 LD (HL),C:INC HL LD (HL),A:INC HL:LD B,A:OUT (C),C ADD A,$18 JR NZ,FM.MMLSTARTSET1 JR FM.MMLADRSET FM.M.TRK CP 3 RET NZ LD A,B OR A RET Z LD A,(DE):SUB "0" RET C JR Z,FM.MMLSTARTSET DEC A:CP 8 RET NC PUSH BC:POP IX LD HL,FM.MMLSTART ADD A,A ADD A,L LD L,A LD A,0 ADC A,H LD H,A:PUSH HL LD C,(HL) INC HL LD B,(HL) INC DE PUSH IX:POP HL DEC H:JR Z,FM.M.TRK2 FM.M.TRK1 LD A,(DE) OUT (C),A INC DE INC BC DEC H JR NZ,FM.M.TRK1 FM.M.TRK2 OUT (C),H POP HL LD (HL),C INC HL LD (HL),B RET ;{{{{{{{{{{{{{{{{{{{{ ;DIM n(4,10)=>FM DRIVER DIM.TONESET LD A,(DE) CP 32 RET NC LD C,32:PUSH DE CALL FM.MUL EX DE,HL:LD HL,(FM.TONEADR) ADD HL,DE ; ADD A,A ; ADD A,A ; ADD A,L ; LD L,A ; LD A,0 ; ADC A,H POP DE INC DE LD A,(DE) DB $FD LD L,A INC DE LD A,(DE) DB $FD LD H,A LD B,(IY+100) ;NOISE(X68000-FREE) LD A,(IY+30) ;SYNC RRCA RRCA OR B LD (HL),A INC HL LD A,(IY+40) ;SPEED LD (HL),A INC HL LD A,(IY+80) ;AMD LD (HL),A INC HL LD B,(IY+20) ;WAVE FORM LD A,(IY+10) ;OPERATOR MASK ADD A,A ADD A,A ADD A,A ADD A,B LD (HL),A INC HL LD B,(IY) ;FEED BACK/ALGORITHM LD A,(IY+90) ;PAN(STEREO) RRCA RRCA OR B LD (HL),A INC HL LD B,(IY+60) ;AMS LD A,(IY+50) ;PMS ADD A,A ADD A,A ADD A,A ADD A,A OR B LD (HL),A INC HL LD DE,4 CALL DATAMAKE ADD IY,DE CALL DATAMAKE DEC IY:DEC IY CALL DATAMAKE ADD IY,DE CALL DATAMAKE LD DE,20:ADD HL,DE LD A,(IY+70-6) ;PMD OR $80 LD (HL),A RET DATAMAKE PUSH HL LD B,(IY+72) ;MULTIPLE LD A,(IY+82) ;DETUNE 1 CP 8 JP C,DATAMAKE.1 NEG ADD A,4 DATAMAKE.1 ADD A,A ADD A,A ADD A,A ADD A,A OR B LD (HL),A ADD HL,DE LD A,(IY+52) ;OUTPUT(TOTAL) LEVEL LD (HL),A ADD HL,DE LD B,(IY+2) ;ATTACK RATE LD A,(IY+62) ;KEY SCALING RRCA RRCA OR B LD (HL),A ADD HL,DE LD B,(IY+12) ;DECAY RATE LD A,(IY+102) ;AMS-EN RRCA OR B LD (HL),A ADD HL,DE LD B,(IY+22) ;SUSTAIN RATE LD A,(IY+92) ;DETUNE 2 RRCA RRCA OR B LD (HL),A ADD HL,DE LD B,(IY+32) ;RELEASE RATE LD A,(IY+42) ;SUSTAIN(DECAY) LEVEL ADD A,A ADD A,A ADD A,A ADD A,A OR B LD (HL),A POP HL INC HL RET ;{{{{{{{{{{{{{{{{{{{{ FM.FREQTABLE DB $18,$1A,$0C,$0E,$11,$12,$15 ; A B C D E F G DB $19,$1C,$0D,$10,$12,$14,$16 ; A+ B+ C+ D+ E+ F+ G+ DB $16,$19,$0B,$0D,$10,$11,$14 FM.FREQTABLE1 DB 09,11,00,02,04,05,07 ; A B C D E F G DB 10,12,01,03,05,06,08 ; A+ B+ C+ D+ E+ F+ G+ DB 08,10,-1,01,03,04,06 FM.TONEADR DW PROGRAM.START-$400 ;{{{{{{{{{{{{{{{{{{{{ WORK AREAS.... FM.WORKSTART FM.MMLADR DS 2*8 FM.ONWAIT DS 2*8 FM.OFFWAIT DS 2*8 FM.VOLUMEW DS 1*8 FM.OPMASK DS 1*8 FM.FREQ DS 2*8 FM.REPEAT DS 2*8 FM.RETURN DS 2*8 FM.OCTERV DS 1*8 FM.GATE DS 1*8 FM.LNGDEF DS 1*8 FM.RL.FB.AL DS 1*8 FM.P.AMSWORK DS 1*8 FM.DETUNEW DS 1*8 FM.KEYFLAG DS 1*8 FM.ENDFLAG DS 1*8 FM.REPCOUNT DS 1*8 FM.LFOSYNC DS 1*8 FM.REPCOUNT2 DS 1*8 FM.S.SPEED DS 1*8 FM.S.PMD DS 1*8 FM.S.AMD DS 1*8 FM.S.AMS DS 1*8 FM.S.PMS DS 1*8 FM.S.WAVEFORM DS 1*8 FM.S.DELAY DS 1*8 FM.S.SPEEDW DS 1*8 FM.S.PMDW DS 1*8 FM.S.AMDW DS 1*8 FM.S.DELAYW DS 1*8 FM.PORTAW DS 2*8 FM.REPEATENDADR DS 2*8 FM.WORK1END FM.ENDCOUNT DS 1 FM.CHANNEL DS 1 FM.OP1WORK DS 8 FM.OP2WORK DS 8 FM.OP3WORK DS 8 FM.OP4WORK DS 8 FM.MMLSTART DS 2*8 FM.WORKSTEP EQU FM.WORK1END-FM.WORKSTART/8 FM.FADETIME DS 1 FM.FADEWORK DS 1 FM@MMLADR EQU 0 FM@ONWAIT EQU 2 FM@OFFWAIT EQU 4 FM@VOLUME EQU 6 FM@OPMASK EQU 7 FM@FREQ EQU 8 FM@REPEAT EQU 10 FM@RETURN EQU 12 FM@OCTERV EQU 14 FM@GATE EQU 15 FM@LNGDEF EQU 16 FM@RL.FB.AL EQU 17 FM@P.AMSWORK EQU 18 FM@DETUNE EQU 19 FM@KEYFLAG EQU 20 FM@ENDFLAG EQU 21 FM@REPCOUNT EQU 22 FM@LFOSYNC EQU 23 FM@REPCOUNT2 EQU 24 FM@S.SPEED EQU 25 FM@S.PMD EQU 26 FM@S.AMD EQU 27 FM@S.AMS EQU 28 FM@S.PMS EQU 29 FM@S.WAVEFORM EQU 30 FM@S.DELAY EQU 31 FM@S.SPEEDW EQU 32 FM@S.PMDW EQU 33 FM@S.AMDW EQU 34 FM@S.DELAYW EQU 35 FM@PORTAW EQU 36 FM@REPEATENDADR EQU 38 FM.STACKW DS 2 FM.STACK DS 20*2 ERRADRW DS 2