diff --git a/Source/Apps/TEST/sound/Scales.asm b/Source/Apps/TEST/sound/Scales.asm index bf91ea81..46bbb19f 100644 --- a/Source/Apps/TEST/sound/Scales.asm +++ b/Source/Apps/TEST/sound/Scales.asm @@ -1,22 +1,209 @@ ; +;------------------------------------------------------------------------------ +; PLAY SCALES USING HBIOS +;------------------------------------------------------------------------------ +; +FCB .EQU $5C ; Location of default FCB +BDOS .EQU $0005 +; + .ORG $0100 +; + LD (OLDSTACK),SP ; save old stack pointer + LD SP,STACK ; set new stack pointer +; +;------------------------------------------------------------------------------ +; GET DEVICE # FROM COMMAND LINE +;------------------------------------------------------------------------------ +; + LD A,(FCB+1) ; GET FIRST CHAR + SUB ' ' + JR Z,NO_ARG + SUB '0'-' ' + JP C,EXIT +; +;------------------------------------------------------------------------------ +; DISPLAY DEVICE AND NUMBER OF CHANNELS +;------------------------------------------------------------------------------ +; +NO_ARG: LD (DEVICE),A ; + LD DE,TXT_DEV ; DEVICE: + CALL PRTSTR + CALL PRTDECB + LD C,A ; GET DEVICE ID + LD A,':' + CALL PRTCHR + LD B,$55 + PUSH BC + LD E,4 + RST 08 + LD DE,TXT_NAME + LD A,B + RRCA \ RRCA \ RRCA \ RRCA + CALL PRTIDXDEA ; SHOW NAME + LD DE,TXT_CH + CALL PRTSTR +; + POP BC ; GET & DISPLAY # CHANNELS + LD E,1 + RST 08 + LD A,B + CALL PRTDECB + CALL CRLF ; NUMBER OF CHANNELS IS IN B +; +;------------------------------------------------------------------------------ +; LOOP THROUGH EACH CHANNEL +;------------------------------------------------------------------------------ + +CH__TONE: LD A,(DEVICE) ; C CONTAINS DEVICE + LD C,A ; THROUGH THIS LOOP +; + PUSH BC + LD B,50H ; RESET DEVICE + RST 08 + POP BC +; + PUSH BC + LD B,51H ; VOLUME FULL + LD L,0FFH + RST 08 + POP BC +; + LD A,B +TST_TONE_LP: DEC A + LD (CHANNEL),A ; SAVE CURRENT CHANNEL + CALL TST_SCALES ; SCALES TEST +; CALL TST_VOLUME ; VOLUME TEST + CALL CRLF + DJNZ TST_TONE_LP +; + PUSH BC + LD B,50H ; RESET DEVICE + RST 08 + POP BC +; +;------------------------------------------------------------------------------ +; RESTORE STACK & EXIT +;------------------------------------------------------------------------------ +; +EXIT: LD SP, (OLDSTACK) ; Exit to CP/M + RST 00H + DI + HALT +; +;------------------------------------------------------------------------------ +; PLAY SCALES FROM HIGHEST HBIOS NOTE TO LOWEST +;------------------------------------------------------------------------------ +; +TST_SCALES: PUSH BC + PUSH AF +; + LD HL,380 ; START NOTE + LD (NOTE),HL ; Top of Octave 7 is 343 + + LD B,51H ; VOLUME HIGH + LD L,0FFH + PUSH BC + RST 08 + POP BC +; +NEXT0: PUSH BC +; + LD DE,TXT_TSTCH ; DISPLAY CHANNEL + CALL PRTSTR + LD A,(CHANNEL) + CALL PRTDECB +; + LD DE,TXT_NOTE ; DISPLAY NOTE + CALL PRTSTR + LD HL,(NOTE) + CALL PRTDECW + POP BC +; + LD B,53H ; SET NOTE + LD HL,(NOTE) + PUSH BC + RST 08 + POP BC - .ORG $0100 + OR A ; DID DRIVER FAIL + JR Z,NEXT4 ; THIS NOTE ? -; SCALES ON ALL THREE CHANNELS + LD DE,TXT_BAD_N + CALL FAILMSG + JR SKIP +; +NEXT4: LD B,57H ; DURATION + LD HL,1000 + PUSH BC + RST 08 + POP BC -; JR SKIP + LD B,54H ; PLAY + LD A,(CHANNEL) + LD D,A + PUSH BC + RST 08 + POP BC +; + OR A ; DID DRIVER FAIL + JR Z,NEXT2 ; TO PLAY ? - LD B,3 -NEXTCH0 LD A,B - DEC A - LD (CHANNEL),A - PUSH BC ; ACROSS - CALL SCALE ; ALL - POP BC ; CHANNELS - DJNZ NEXTCH0 + LD DE,TXT_BAD_N + CALL FAILMSG + JR SKIP +; +NEXT2: CALL DELAY + CALL CRLF +; +SKIP: LD HL,(NOTE) + DEC HL + LD (NOTE),HL + + INC HL + LD A,H + OR L + DEC HL + JR NZ,NEXT0 +; + LD B,51H ; VOLUME + LD L,00H ; OFF + PUSH BC + RST 08 + POP BC +; + LD B,54H ; PLAY + LD A,(CHANNEL) + LD D,A + PUSH BC + RST 08 + POP BC + + PUSH BC + LD C, 6 ; check for keypress + LD E,0FFH + CALL BDOS + POP BC + OR A + JP NZ,EXIT -; CONSTANT TONE ON ALL THREE CHANNELS, SCALE VOLUME -SKIP: + POP AF + POP BC +; + RET +; +FAILMSG: PUSH AF + PUSH BC + CALL PRTSTR + CALL CRLF + POP BC + POP AF + RET +; +;------------------------------------------------------------------------------ +; CONSTANT TONE ON ALL CHANNELS, SCALE VOLUME +;------------------------------------------------------------------------------ +; +TST_VOLUME: LD HL,332+48 ; TONE LD (NOTE),HL ; @@ -26,31 +213,46 @@ NEXTCH1 LD A,B LD (CHANNEL),A PUSH BC ; ACROSS CALL TONE ; ALL + + LD C, 6 ; KEYPRESS + LD E, 0FFH + CALL BDOS POP BC ; CHANNELS + + OR A + JP NZ,EXIT + DJNZ NEXTCH1 RET -TONE: LD B,50H ; RESET - LD C,0 +TONE: LD A,(DEVICE) + LD C,A + + LD B,50H ; RESET + PUSH BC RST 08 + POP BC ; NEXT1: LD B,51H ; VOLUME - LD C,0 LD A,(VOLUME) LD L,A + PUSH BC RST 08 + POP BC ; LD B,53H ; NOTE - LD C,0 LD HL,(NOTE) + PUSH BC RST 08 + POP BC ; LD B,54H ; PLAY - LD C,0 LD A,(CHANNEL) LD D,A + PUSH BC RST 08 + POP BC ; CALL DELAY ; @@ -60,74 +262,23 @@ NEXT1: LD B,51H ; VOLUME JR NZ,NEXT1 ; LD B,51H ; VOLUME - LD C,0 LD L,00H + PUSH BC RST 08 + POP BC ; LD B,54H ; PLAY - LD C,0 - LD A,(CHANNEL) - LD D,A - RST 08 -; - RET -; -; -; -SCALE: LD B,50H ; RESET - LD C,0 - RST 08 -; - LD B,51H ; VOLUME - LD C,0 - LD L,80H - RST 08 -; - LD HL,380 - LD (NOTE),HL -; -NEXT0: LD B,53H ; NOTE - LD C,0 - LD HL,(NOTE) - RST 08 -; - LD B,54H ; PLAY - LD C,0 - LD A,(CHANNEL) - LD D,A - RST 08 -; - OR A - JR Z,NEXT2 - LD C,9 - LD DE,BADFLAG - CALL 5 - JR NEXT3 -; -NEXT2: CALL DELAY -; -NEXT3: LD HL,(NOTE) - DEC HL - LD A,L - LD (NOTE),A - LD A,H - LD (NOTE+1),A - OR L -; - JR NZ,NEXT0 -; - LD B,51H ; VOLUME - LD C,0 - LD L,00H - RST 08 -; - LD B,54H ; PLAY - LD C,0 + PUSH BC LD A,(CHANNEL) LD D,A + POP BC RST 08 ; RET +;; +;------------------------------------------------------------------------------ +; LONG DELAY +;------------------------------------------------------------------------------ ; DELAY: LD HL,-1 DELAY1: DEC HL @@ -136,10 +287,43 @@ DELAY1: DEC HL JR NZ,DELAY1 RET ; -BADFLAG .DB '*', $0D, $0A, '$' -NOTE .DW 128 -VOLUME .DB 0 -CHANNEL .DB 0 +;------------------------------------------------------------------------------ +; PRINT THE nTH STRING IN A LIST OF STRINGS WHERE EACH IS TERMINATED BY 0 +; A REGISTER DEFINES THE nTH STRING IN THE LIST TO PRINT AND DE POINTS +; TO THE START OF THE STRING LIST. +;------------------------------------------------------------------------------ +; +PRTIDXDEA: LD C,A + OR A +PRTIDXDEA1: JR Z,PRTIDXDEA3 ; FOUND TARGET SO EXIT +PRTIDXDEA2: LD A,(DE) ; LOOP UNIT + INC DE ; WE REACH + OR A ; END OF STRING + JR NZ,PRTIDXDEA2 + DEC C ; AT STRING END. SO GO + JR PRTIDXDEA1 ; CHECK FOR INDEX MATCH +PRTIDXDEA3: CALL PRTSTR ; DISPLAY THE STRING + RET +; +#INCLUDE "printing.inc" +; +TXT_CH .DB "CHANNELS: ",0 +TXT_TSTCH .DB "CHANNEL: ",0 +TXT_BAD_N .DB " BAD NOTE",0 +TXT_BAD_P .DB " PLAY ERROR",0 +TXT_NOTE .DB " NOTE: ",0 +TXT_DEV .DB "DEVICE: ",0 +TXT_NAME .DB "SN76489 ",0 + .DB "AY-3-8910 ",0 + .DB "I/O PORT ",0 + .DB "YM2612 ",0 +MODE .DB 0 ; scales mode or volume mode +DEVICE .DB 0 +NOTE .DW 128 +VOLUME .DB 0 +CHANNEL .DB 0 +OLDSTACK .DW 0 ; original stack pointer + .DS 40H ; space for stack +STACK ; top of stack ; .END - diff --git a/Source/Apps/Tune/printing.inc b/Source/Apps/Tune/printing.inc index 6d118ea2..be1ade84 100644 --- a/Source/Apps/Tune/printing.inc +++ b/Source/Apps/Tune/printing.inc @@ -34,6 +34,7 @@ PRTCR: ; Print a zero terminated string at (DE) without destroying any registers ; PRTSTR: + PUSH AF PUSH DE ; PRTSTR1: @@ -46,6 +47,7 @@ PRTSTR1: ; PRTSTR2: POP DE ; restore registers + POP AF RET ; ; Print the value in A in hex without destroying any registers diff --git a/Source/Apps/VGM/Build.cmd b/Source/Apps/VGM/Build.cmd index 7e2fe40e..08e013f5 100644 --- a/Source/Apps/VGM/Build.cmd +++ b/Source/Apps/VGM/Build.cmd @@ -6,7 +6,7 @@ set PATH=%TOOLS%\tasm32;%PATH% set TASMTABS=%TOOLS%\tasm32 tasm -t180 -g3 -fFF -dWBW vgmplay.asm vgmplay.com vgmplay.lst || exit /b -tasm -t180 -g3 -fFF -dWBW ym2612.asm ym2612.com ym2612.lst || exit /b +tasm -t180 -g3 -fFF -dWBW ymfmdemo.asm ymfmdemo.com ymfmdemo.lst || exit /b copy /Y vgmplay.com ..\..\..\Binary\Apps\ || exit /b copy /Y Tunes\*.vgm ..\..\..\Binary\Apps\Tunes\ || exit /b diff --git a/Source/Apps/VGM/Makefile b/Source/Apps/VGM/Makefile index 58cc9428..fdb643d9 100644 --- a/Source/Apps/VGM/Makefile +++ b/Source/Apps/VGM/Makefile @@ -11,8 +11,8 @@ vgmplay.com: $(DEPS) $(TASM) -dWBW vgmplay.asm vgmplay.com vgmplay.lst ym2612.com: - $(TASM) -dWBW ym2612.asm ym2612.com ym2612.lst + $(TASM) -dWBW ymfmdemo.asm ymfmdemo.com ymfmdemo.lst all:: mkdir -p $(DEST)/Tunes - cp Tunes/* $(DEST)/Tunes + cp Tunes/*.vgm $(DEST)/Tunes diff --git a/Source/Apps/VGM/printing.inc b/Source/Apps/VGM/printing.inc index 6d118ea2..be1ade84 100644 --- a/Source/Apps/VGM/printing.inc +++ b/Source/Apps/VGM/printing.inc @@ -34,6 +34,7 @@ PRTCR: ; Print a zero terminated string at (DE) without destroying any registers ; PRTSTR: + PUSH AF PUSH DE ; PRTSTR1: @@ -46,6 +47,7 @@ PRTSTR1: ; PRTSTR2: POP DE ; restore registers + POP AF RET ; ; Print the value in A in hex without destroying any registers diff --git a/Source/Apps/VGM/YM2612.ASM b/Source/Apps/VGM/ymfmdemo.asm similarity index 98% rename from Source/Apps/VGM/YM2612.ASM rename to Source/Apps/VGM/ymfmdemo.asm index b2014b64..ba45f419 100644 --- a/Source/Apps/VGM/YM2612.ASM +++ b/Source/Apps/VGM/ymfmdemo.asm @@ -25,6 +25,7 @@ MBC .equ 2 ; plt_romwbw .equ 1 ; Build for ROMWBW? plt_type .equ sbcecb ; Select build configuration +plt_cpuspd .equ 6 ; Non ROMWBW cpu speed default debug .equ 0 ctc_delay .equ 0 diff --git a/Source/Doc/Architecture.md b/Source/Doc/Architecture.md index c4e0f5fd..a67ff35a 100644 --- a/Source/Doc/Architecture.md +++ b/Source/Doc/Architecture.md @@ -1398,7 +1398,7 @@ Increase by steps of 4 to select the next corresponding note. Increase by steps of 48 to select the same note in next octave. If the driver is able to generate the requested note, a success (0) is -returned, otherwise a non-zero error state will be returned. +returned, otherwise a non-zero error value will be returned. The sound chip resolution and its oscillator limit the range and accuracy of the notes played. The typical range of the AY-3-8910 @@ -1443,7 +1443,7 @@ the following HBIOS calls would need to be made: ``` HBIOS B=51 C=00 L=80 ; Set volume to half level -HBIOS B=53 C=00 L=69 ; Select Middle C (C4) assuming SN76489 +HBIOS B=53 C=00 HL=152 ; Select Middle C (C4) HBIOS B=54 C=00 D=01 ; Play note on Channel 1 ``` @@ -1518,6 +1518,8 @@ AUDIO ID | Value | Device | Returned registers SND_SN76489 | 0x01 | SN76489 | E: Left channel port, L: Right channel port SND_AY38910 | 0x02 | AY-3-8910 | D: Address port, E: Data port SND_BITMODE | 0x03 | I/O PORT | D: Address port, E: Bit mask +SND_YM2612 | 0x04 | YM2612 | D: Part 0 Address port, E: Part 0 Data port + | | | H: Part 1 Address port, L: Part 1 Data port ### Function 0x56 -- Sound Duration (SNDDUR) @@ -1547,10 +1549,10 @@ and then return. | _Exit Results_ | A: Status (0=OK, else error) -| D: Serial Device Type -| E: Serial Device Number -| H: Serial Device Unit Mode -| L: Serial Device Unit I/O Base Address +| D: Sound Device Type +| E: Sound Device Number +| H: Sound Device Unit Mode +| L: Sound Device Unit I/O Base Address Reports information about the sound device unit specified. Register D indicates the device type (driver) and register E indicates the physical @@ -1565,6 +1567,7 @@ _Id_ | _Device Type / Driver_ 0x00 | SN76489 0x10 | AY38910 0x20 | BITMODE +0x30 | YM2612 `\clearpage`{=latex} diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index e02c525a..68fd47a5 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -3725,7 +3725,7 @@ SND_ADDENT: ; WORD UNIT SPECIFIC DATA (TYPICALLY A DEVICE INSTANCE DATA ADDRESS) ; SND_FNCNT .EQU 8 ; NUMBER OF SND FUNCS (FOR RANGE CHECK) -SND_MAX .EQU 4 ; UP TO 4 UNITS +SND_MAX .EQU 5 ; UP TO 4 UNITS SND_SIZ .EQU SND_MAX * 4 ; EACH ENTRY IS 4 BYTES ; .DB SND_FNCNT ; SND FUNCTION COUNT (FOR RANGE CHECK) @@ -3737,7 +3737,7 @@ SND_TBL .FILL SND_SIZ,0 ; SPACE FOR ENTRIES ; SPEAKER BEEP ROUTINE ;================================================================================================== ; -; ROUTINE TO BEEP THE DEAULT SOUND UNIT +; ROUTINE TO BEEP THE DEFAULT SOUND UNIT ; NEED TO CHECK FOR EXISTENCE OF SOUND UNIT ; WHICH CHANNEL SHOULD BE USED? IS THERE A GOOD DEFAULT CHANNEL? ; @@ -7041,6 +7041,7 @@ PS_SDSND .TEXT "SND$" PS_SDSN76489 .TEXT "SN76489$" PS_SDAY38910 .TEXT "AY-3-8910$" PS_SDBITMODE .TEXT "I/O PORT$" +PS_SDYM2612 .TEXT "YM2612$" ; ; 0 1 2 3 4 5 6 7 ; 01234567890123456789012345678901234567890123456789012345678901234567890123456789 diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index d0d59a42..fca747bf 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -333,6 +333,7 @@ VDADEV_VGA .EQU $40 ; ECB VGA3 - HITACHI HD6445 SNDDEV_SN76489 .EQU $00 SNDDEV_AY38910 .EQU $10 SNDDEV_BITMODE .EQU $20 +SNDDEV_YM2612 .EQU $30 ; ; HBIOS CONTROL BLOCK OFFSETS ; WARNING: THESE OFFSETS WILL CHANGE SIGNIFICANTLY BETWEEN RELEASES diff --git a/Source/HBIOS/ym2612.asm b/Source/HBIOS/ym2612.asm index 9ceadf4d..148e7329 100644 --- a/Source/HBIOS/ym2612.asm +++ b/Source/HBIOS/ym2612.asm @@ -1,319 +1,872 @@ -;====================================================================== -; YM2612 sound driver -; -; WRITTEN BY: PHIL SUMMERS -;====================================================================== -; -; PRESENTLY THIS IS JUST A STUB TO MUTE OUTPUT +;------------------------------------------------------------------------------ +; YM2612 sound driver +; Written by: Phil Summers (b1ackmailer) difficultylevelhigh@gmail.com ; -;====================================================================== -; -;====================================================================== +;------------------------------------------------------------------------------ +; References: +; https://www.smspower.org/maxim/Documents/YM2612 +; https://plutiedev.com/blog/20200103 +; https://www.plutiedev.com/ym2612-registers +; https://en.wikipedia.org/wiki/Scientific_pitch_notation +;------------------------------------------------------------------------------ +; Octave range is A#0-B7+3/4 HBIOS note 0..343 +;------------------------------------------------------------------------------ ; YMSEL .EQU VGMBASE+00H ; Primary YM2162 11000000 a1=0 a0=0 YMDAT .EQU VGMBASE+01H ; Primary YM2162 11000001 a1=0 a0=1 YM2SEL .EQU VGMBASE+02H ; Secondary YM2162 11000010 a1=1 a0=0 YM2DAT .EQU VGMBASE+03H ; Secondary YM2162 11000011 a1=1 a0=1 + +;------------------------------------------------------------------------------ +; Device capabilities and configuration +;------------------------------------------------------------------------------ ; -YM_CLR .EQU FALSE ; Set to clear all registers +YM_TONECNT .EQU 6 ; Count number of tone channels +YM_NOISECNT .EQU 0 ; Count number of noise channels +; +YM_PENDING_PERIOD .DW 0 ; PENDING PERIOD (12 BITS) ; ORDER +YM_PENDING_VOLUME .DB 0 ; PENDING VOL (8 BITS) ; SIGNIFICANT +YM_PENDING_DURATION .DW 0 ; PENDING DURATION (16 BITS) +YM_READY .DB 0 ; BIT 0 -> NZ DRIVER IS READY TO RECEIVE PLAY COMMAND + ; BIT 1 -> NZ EXECUTING WITHIN TIMER HANDLER = DO NOT DIS/ENABLE INT +YM_RDY_RST .DB 0 ; FLAG INDICATES IF DEVICE IS IN READY (NZ) OR RESET STATE (Z) +YM_DEBUG .EQU 0 ; CHANGE TO 1 TO ENABLE DEBUGGING +YM_RSTCFG .EQU 0 ; SET TO 1 FOR FULL REGISTER CLEAR ; ;------------------------------------------------------------------------------ -; YM2162 Mute +; Driver function table and instance data ;------------------------------------------------------------------------------ ; -YM2612_INIT: ld hl,s1 ; Start of register list to write - - ld b,+(s2-s1)/2 -pt1: call set1 ; [1] - djnz pt1 +YM_FNTBL: .DW YM_RESET + .DW ym_volume + .DW YM_PERIOD + .DW YM_NOTE + .DW YM_PLAY + .DW YM_QUERY + .DW YM_DURATION + .DW YM_DEVICE +; +#IF (($ - YM_FNTBL) != (SND_FNCNT * 2)) + .ECHO "*** INVALID SND FUNCTION TABLE ***\n" + !!!!! +#ENDIF +; +YM_IDAT .EQU 0 ; NO INSTANCE DATA FOR THIS DEVICE +; +;------------------------------------------------------------------------------ +; YM2162 Initialization +; Announce device on console. +; Setup function tables. Setup the device. +; Set volume off. +; Return initialization status +;------------------------------------------------------------------------------ +; +YM2612_INIT: CALL NEWLINE ; ANNOUNCE + PRTS("YM:$") +; + PRTS(" IO=0x$") + LD A,YMSEL + CALL PRTHEXBYTE +; + LD IY, YM_IDAT ; SETUP FUNCTION TABLE + LD BC, YM_FNTBL ; POINTER TO INSTANCE DATA + LD DE, YM_IDAT ; BC := FUNCTION TABLE ADDRESS + CALL SND_ADDENT ; DE := INSTANCE DATA PTR +; +YM_INIT: ld hl,ym_cfg +; call ym_prog +; ret +; +;------------------------------------------------------------------------------ +; Program ym2612 with a list of register entries +;------------------------------------------------------------------------------ +; +ym_prog: ld c,(hl) ; get port address + inc hl + ld d,(hl) ; count of pairs + inc hl +; +#IF (YM_DEBUG) + push af + ld a,c ; port + call PRTHEXBYTE + pop af +#ENDIF +; +t_loop: ld a,(hl) ; get register to write + out (c),a ; write reg to RSEL port +; +#IF (YM_DEBUG) + call PRTHEXBYTE ; register +#ENDIF +; + inc hl + inc c ; point to RDAT port + ld a,(hl) ; get value to write + out (c),a ; write value to RDAT port +; +#IF (YM_DEBUG) + call PRTHEXBYTE + call PC_SPACE +#ENDIF +; + dec c ; point back to RSEL port + ld b,0 ; check device +nready1: in a,(c) ; ready with timeout + rlca ; + jr nc,ready1 ; bits 7 = busy + djnz nready1 +; +; timed out +; +ready1: inc hl ; + dec d ; decrease # left to do + jr nz,t_loop +; +#IF (YM_DEBUG) + call NEWLINE +#ENDIF +; + ld a,(hl) ; end flag? + or a + jr nz,ym_prog ; no? restart + ret +; +;------------------------------------------------------------------------------ +; Sound driver function - QUERY and subfunctions +;------------------------------------------------------------------------------ +; +YM_QUERY: LD A, E + CP BF_SNDQ_CHCNT ; SUB FUNCTION 01 + JR Z, YM_QUERY_CHCNT +; + CP BF_SNDQ_VOLUME ; SUB FUNCTION 02 + JR Z, YM_QUERY_VOLUME +; + CP BF_SNDQ_PERIOD ; SUB FUNCTION 03 + JR Z, YM_QUERY_PERIOD +; + CP BF_SNDQ_DEV ; SUB FUNCTION 04 + JR Z, YM_QUERY_DEV +; + OR $FF ; SIGNAL FAILURE + RET +; +YM_QUERY_CHCNT: LD BC,(YM_TONECNT*256)+YM_NOISECNT + XOR A ; RETURN NUMBER OF TONE AND NOISE + RET ; NOISE CHANNELS IN BC +; +YM_QUERY_PERIOD:LD HL, (YM_PENDING_PERIOD) ; RETURN 16-BIT PERIOD + XOR A ; IN HL REGISTER + RET +; +YM_QUERY_VOLUME:LD A, (YM_PENDING_VOLUME) ; RETURN 8-BIT VOLUME + LD L, A ; IN L REGISTER + XOR A +; LD H, A + RET +; +YM_QUERY_DEV: LD B, SNDDEV_YM2612 ; RETURN DEVICE IDENTIFIER + LD DE, +(YMSEL*256)+YMDAT ; AND ADDRESS AND DATA PORT + LD HL, +(YM2SEL*256)+YM2DAT + XOR A + RET +; +;------------------------------------------------------------------------------ +; Sound driver function - DEVICE +;------------------------------------------------------------------------------ +; +YM_DEVICE: LD D,SNDDEV_YM2612 ; D := DEVICE TYPE + LD E,0 ; E := PHYSICAL UNIT + LD C,$00 ; C := DEVICE TYPE + LD H,0 ; H := MODE + LD L,YMSEL ; L := BASE I/O ADDRESS + XOR A + RET +; +;------------------------------------------------------------------------------ +; Sound driver function - RESET +; Initialize device. Set volume off. Reset volume and tone variables. +;------------------------------------------------------------------------------ +; +YM_RESET: ;CALL AY_CHKREDY ; RETURNS TO OUR CALLER IF NOT READY +; + PUSH DE + PUSH HL + CALL YM_INIT ; SET DEFAULT CHIP CONFIGURATION +; + XOR A ; SIGNAL SUCCESS + LD (YM_RDY_RST),A ; IN RESET STATE + LD (YM_PENDING_VOLUME),A ; SET VOLUME TO ZERO + LD H,A + LD L,A + LD (YM_PENDING_PERIOD),HL ; SET TONE PERIOD TO ZERO +; + POP HL + POP DE + RET +; +;------------------------------------------------------------------------------ +; Sound driver function - VOLUME +;------------------------------------------------------------------------------ +; +ym_volume: LD A,L ; SAVE VOLUME + LD (YM_PENDING_VOLUME),A + XOR A ; SIGNAL SUCCESS + RET +; +;------------------------------------------------------------------------------ +; Sound driver function - NOTE +;------------------------------------------------------------------------------ +; +YM_NOTE: ;CALL PRTHEXWORDHL + ;CALL PC_COLON - ld b,+(s3-s2)/2 -pt2: call set2 ; [2] - djnz pt2 + LD DE,40 ; Calculate the ym2612 block (octave) + ADD HL,DE ; This will go into b13-b11 + LD DE,48 ; HL / DE + CALL DIV16 ; BC = block (octave) HL = quarter semitone note +; + ADD HL,HL + LD DE,ym_notetable ; point HL to frequency entry + ADD HL,DE ; for the quarter semitone note - ld b,+(s4-s3)/2 -pt3: call set1 ; [1] - djnz pt3 + ;CALL PRTHEXWORDHL + ;CALL PC_COLON + ;CALL PRTHEXWORD + ;CALL PC_COLON +; + LD A,C ; SHIFT OCTAVE INTO RIGHT POSITION + ADD A,A ; X2 + ADD A,A ; X4 + ADD A,A ; X8 -NEEDS TO BE OR'ED WITH HIGH BYTE +; + LD E,(HL) ; COMBINE FREQUENCY ENTRY + INC HL ; AND BLOCK (OCTAVE) IN HL + OR (HL) + LD H,A + LD L,E - ld b,+(s5-s4)/2 -pt4: call set2 ; [2] - djnz pt4 + ;CALL PRTHEXWORDHL +; +;------------------------------------------------------------------------------ +; Sound driver function - PERIOD +; The format for setting frequency on the ym2612 is 00xxxyyy-yyyyyyyy +; Where xxx us the octave and yyy-yyyyyyyy is the frequency +;------------------------------------------------------------------------------ +; +YM_PERIOD: LD A, H ; IF ZERO - ERROR + OR L + JR Z, YM_PERIOD1 +; + LD A, H ; MAXIMUM TONE PERIOD IS 11-BITS + AND 11000000B ; ALLOWED RANGE IS 0001-07FF (2047) + JR NZ,YM_PERIOD1 ; AND 3 BITS FOR OCTAVE (7) + LD (YM_PENDING_PERIOD),HL ; RETURN NZ IF NUMBER TOO LARGE + RET ; SAVE AND RETURN SUCCESSFUL +; +YM_PERIOD1: LD A, $FF ; REQUESTED PERIOD IS LARGER + LD (YM_PENDING_PERIOD),A ; THAN THE DEVICE CAN SUPPORT + LD (YM_PENDING_PERIOD+1),A ; SO SET PERIOD TO FFFF + RET ; AND RETURN FAILURE +; +;------------------------------------------------------------------------------ +; Sound driver function - DURATION +;------------------------------------------------------------------------------ +; +YM_DURATION: LD (YM_PENDING_DURATION),HL ; SET TONE DURATION + XOR A + RET +; +;------------------------------------------------------------------------------ +; Sound driver function - PLAY +; D = CHANNEL +;------------------------------------------------------------------------------ +; +YM_PLAY: ld a,d + cp YM_TONECNT ; error if bad channel + ret nc + + cp 3 ; 000 > 000, 011 > 100 + ld e,part1 ; 001 > 001, 100 > 101 + jr c,ch012 ; 010 > 010, 101 > 110 + sub 3 + ld d,a ; d = 0..2 + add a,4 ; a = 4..6 + jr ch345 +ch012: ld e,part0 +ch345: +; +#IF (YM_DEBUG) + call PC_COLON + call PRTHEXBYTE ; a = 0..2 4..6 + push af + ld a,d + call PRTHEXBYTE ; d = 00..05 + ld a,e + call PRTHEXBYTE ; e = part0/part1 (c0/c2) + pop af + call NEWLINE +#ENDIF +; + ld hl,ym_playcmd01 + ld (hl),e ; set the part +; + ld hl,ym_playcmd00 ; setup keyoff channel + ld (hl),a + ld hl,ym_playcmd09 ; setup keyon channel + or %10000000 ; operator 4 only + ld (hl),a - ret + ld a,$a4 ; setup frequency register msb + add a,d ; $a4-$a6 + ld hl,ym_playcmd02 + ld (hl),a -set1: ld a,(hl) ; YM2162 Register write - inc hl ; Register bank [1] - out (YMSEL),a - ld a,(hl) - inc hl - out (YMDAT),a - push bc - ld b,0 ; check -set1a: in a,(YMSEL) ; device - rlca ; ready - jp nc,set1b ; with - djnz set1a ; timeout - ; timed out -set1b: pop bc - ret -; -set2: ld a,(hl) ; YM2162 Register write - inc hl ; Register Bank [2] - out (YM2SEL),a - ld a,(hl) - inc hl - out (YM2DAT),a - push bc ; check - ld b,0 ; device -set2a: in a,(YM2SEL) ; ready - rlca ; with - jp nc,set2b ; timeout - djnz set2a - ; timed out -set2b: pop bc - ret + ld a,$a0 ; setup frequency register lsb + add a,d ; $a0-$a2 + ld hl,ym_playcmd04 + ld (hl),a -s1: .db $22,$00 ; [1] lfo off + ld a,$4c ; setup volume register + add a,d ; $4c-$4e + ld hl,ym_playcmd06 + ld (hl),a - .db $27,$00 ; [1] Disable independant Channel 3 - .db $28,$00 ; [1] note off ch 1 - .db $28,$01 ; [1] note off ch 2 - .db $28,$02 ; [1] note off ch 3 - .db $28,$04 ; [1] note off ch 4 - .db $28,$05 ; [1] note off ch 5 - .db $28,$06 ; [1] note off ch 6 - .db $2b,$00 ; [1] dac off + LD A,(YM_RDY_RST) ; IF STILL IN RESET + OR A ; STATE GO SETUP FOR + CALL Z,YM_MAKE_RDY ; PLAYING +; + ld hl,(YM_PENDING_PERIOD) ; GET THE PREVIOUSLY SETUP + ld de,ym_playcmd03 ; TONE DATA AND + ld a,h + ld (de),a ; PATCH IT INTO THE + ld de,ym_playcmd05 ; YM2612 PLAY COMMAND + ld a,l + ld (de),a +; + ld de,ym_playcmd07 + ld A,(YM_PENDING_VOLUME) ; GET VOLUME + srl a + cpl + and %01111111 ; PATCH IT INTO THE + ld (de),a ; YM2612 PLAY COMMAND +#IF (YM_DEBUG) + ld b,16 ; debug + call NEWLINE ; dump + ld de,ym_playnote ; the +ym_dbgcmd: ld a,(de) ; command + call PRTHEXBYTE ; stream + call PC_SPACE + inc de + djnz ym_dbgcmd + call NEWLINE +#ENDIF + ld hl,ym_playnote ; NOW PLAY IT + jp ym_prog +; +;------------------------------------------------------------------------------ +; Make ready for hbios play +;------------------------------------------------------------------------------ +; +YM_MAKE_RDY: CPL + LD (YM_RDY_RST),A ; Invert the ready flag + ld hl,ym_cfg_ready ; Program ym2612 for playing + jp ym_prog +; +;------------------------------------------------------------------------------ +; Command sequence to play a note +;------------------------------------------------------------------------------ +; +ym_playnote: .db part0, 2/2 + .db $28 +ym_playcmd00: .db $00 ; [0] KEY OFF +; +ym_playcmd01: .db part0,6/2 +ym_playcmd02: .db $A4 +ym_playcmd03: .db $3F ; [X] Frequency MSB +ym_playcmd04: .db $A0 +ym_playcmd05: .db $FF ; [X] Frequency LSB +ym_playcmd06: .db $4C +ym_playcmd07: .db $00 ; [X] Volume +; + .db part0, 2/2 +ym_playcmd08: .db $28 +ym_playcmd09: .db $F0 ; [0] KEY ON - .db $b4,$00 ; [1] sound off ch 1-3 + .db $00 ; End flag +; +;------------------------------------------------------------------------------ +; Quarter semitone values +;------------------------------------------------------------------------------ +; +ym_notetable: .dw 644 ; C ; 152 + .dw 653 ; approx + .dw 663 ; approx + .dw 672 ; approx + .dw 681 ; C# ; 156 + .dw 691 ; approx + .dw 702 ; approx + .dw 712 ; approx + .dw 722 ; D ; 160 + .dw 733 ; approx + .dw 744 ; approx + .dw 754 ; approx + .dw 765 ; D# ; 164 + .dw 776 ; approx + .dw 788 ; approx + .dw 799 ; approx + .dw 810 ; E ; 168 + .dw 822 ; approx + .dw 834 ; approx + .dw 846 ; approx + .dw 858 ; F ; 172 + .dw 871 ; approx + .dw 884 ; approx + .dw 897 ; approx + .dw 910 ; F# ; 176 + .dw 924 ; approx + .dw 937 ; approx + .dw 951 ; approx + .dw 964 ; G ; 180 + .dw 978 ; approx + .dw 993 ; approx + .dw 1007 ; approx + .dw 1021 ; G# ; 184 + .dw 1036 ; approx + .dw 1051 ; approx + .dw 1066 ; approx + .dw 1081 ; A ; 188 + .dw 1097 ; approx + .dw 1114 ; approx + .dw 1130 ; approx + .dw 1146 ; A# ; 192 + .dw 1163 ; approx + .dw 1180 ; approx + .dw 1197 ; approx + .dw 1214 ; B ; 196 + .dw 1232 ; approx + .dw 1250 ; approx + .dw 1268 ; approx +; +;------------------------------------------------------------------------------ +; Register configuration data for play +;------------------------------------------------------------------------------ +; +ym_cfg_ready: .db part0, 2/2 + .db $22, $00 ; Global: LFO disable +; + .db part0, 6/2 + .db $B0,$30 ; Channel 1-3 + .db $b1,$30 ; Algorithm 0 S1>S2>S3>S4 + .db $b2,$30 ; Feedback pure sine wave +; + .db part1, 6/2 + .db $B0,$30 ; Channel 4-6 + .db $b1,$30 ; Algorithm 0 S1>S2>S3>S4 + .db $b2,$30 ; Feedback pure sine wave +; + .db part0, 6/2 + .db $3c, $01 ; Channel 1-3 + .db $3d, $01 ; Operator 4.MUL = 1 + .db $3e, $01 +; + .db part1, 6/2 + .db $3c, $01 ; Channel 4-6 + .db $3d, $01 ; Operator 4.MUL = 1 + .db $3e, $01 +; + .db part0, 6/2 + .db $b4,%01000000 ; Channel 1-3 + .db $b5,%01000000 ; Left Channel + .db $b6,%01000000 +; + .db part1, 6/2 + .db $b4,%10000000 ; Channel 4-6 + .db $b5,%10000000 ; Right Channel + .db $b6,%10000000 +; + .db part0, 6/2 + .db $44, $7F ; Channel 1-3 + .db $45, $7F ; Mute operator 3 <- pure sine wave + .db $46, $7F +; + .db part1, 6/2 + .db $44, $7F ; Channel 4-6 + .db $45, $7F ; Mute operator 3 <- pure sine wave + .db $46, $7F +; + .db part0, 6/2 + .db $4C, $7f ;$00 ; Channel 1-3 + .db $4d, $7f ;$00 ; Max volume for operator 4 + .db $4e, $7f ;$00 +; + .db part1, 6/2 + .db $4C, $7f ;$00 ; Channel 4-6 + .db $4d, $7f ;$00 ; Max volume for operator 4 + .db $4e, $7f ;$00 +; + .db part0, 6/2 + .db $5C, $1F ; Channel 1-3 + .db $5d, $1F ; Operator 4.AR = shortest + .db $5e, $1F +; + .db part1, 6/2 + .db $5C, $1F ; Channel 4-6 + .db $5d, $1F ; Operator 4.AR = shortest + .db $5e, $1F +; + .db part0, 6/2 + .db $6C, $06 ; Channel 1-3 + .db $6d, $06 ; Operator 4.D1R= 6 + .db $6e, $06 +; + .db part1, 6/2 + .db $6C, $06 ; Channel 4-6 + .db $6d, $06 ; Operator 4.D1R= 6 + .db $6e, $06 +; + .db part0, 6/2 + .db $7C, $1F ; Channel 1-3 + .db $7d, $1F ; Operator 4.D2R= 31 + .db $7e, $1F +; + .db part1, 6/2 + .db $7C, $1F ; Channel 4-6 + .db $7d, $1F ; Operator 4.D2R= 31 + .db $7e, $1F +; + .db part0, 6/2 + .db $8C, $FF ; Channel 1-3 + .db $8d, $FF ; Operator 4.SL = 15 / Operator4. RR=15 + .db $8e, $FF +; + .db part1, 6/2 + .db $8C, $FF ; Channel 4-6 + .db $8d, $FF ; Operator 4.SL = 15 / Operator4. RR=15 + .db $8e, $FF +; + .db $00 ; End flag +; +; +;------------------------------------------------------------------------------ +; Register configuration data for soft reset state +;------------------------------------------------------------------------------ +; +part0: .equ YMSEL +part1: .equ YM2SEL +; +#IF (YM_RSTCFG==0) +ym_cfg: .db part0, 24/2 + .db $22,$00 ; [0] lfo off + .db $27,$00 ; [0] Disable independant Channel 3 + .db $28,$00 ; [0] note off ch 1 + .db $28,$01 ; [0] note off ch 2 + .db $28,$02 ; [0] note off ch 3 + .db $28,$04 ; [0] note off ch 4 + .db $28,$05 ; [0] note off ch 5 + .db $28,$06 ; [0] note off ch 6 + .db $2b,$00 ; [0] dac off + .db $b4,$00 ; [0] sound off ch 1-3 .db $b5,$00 .db $b6,$00 +; + .db part1, 6/2 + .db $b4,$00 ; [1] sound off ch 4-6 + .db $b5,$00 ; [1] + .db $b6,$00 ; [1] +; + .db part0, 24/2 + .db $40,$7f ; [0] ch 1-3 total level minimum + .db $41,$7f ; [0] + .db $42,$7f ; [0] + .db $44,$7f ; [0] + .db $45,$7f ; [0] + .db $46,$7f ; [0] + .db $48,$7f ; [0] + .db $49,$7f ; [0] + .db $4a,$7f ; [0] + .db $4c,$7f ; [0] + .db $4d,$7f ; [0] + .db $4e,$7f ; [0] +; + .db part1, 24/2 + .db $40,$7f ; [1] ch 4-6 total level minimum + .db $41,$7f ; [1] + .db $42,$7f ; [1] + .db $44,$7f ; [1] + .db $45,$7f ; [1] + .db $46,$7f ; [1] + .db $48,$7f ; [1] + .db $49,$7f ; [1] + .db $4a,$7f ; [1] + .db $4c,$7f ; [1] + .db $4d,$7f ; [1] + .db $4e,$7f ; [1] +; + .db $00 ; End flag +; +;------------------------------------------------------------------------------ +; Register configuration data for hard reset state +;------------------------------------------------------------------------------ +; +#ELSE +ym_cfg: .db part0, 24/2 + .db $22,$00 ; [0] lfo off + .db $27,$00 ; [0] Disable independant Channel 3 + .db $28,$00 ; [0] note off ch 1 + .db $28,$01 ; [0] note off ch 2 + .db $28,$02 ; [0] note off ch 3 + .db $28,$04 ; [0] note off ch 4 + .db $28,$05 ; [0] note off ch 5 + .db $28,$06 ; [0] note off ch 6 + .db $2b,$00 ; [0] dac off + .db $b4,$00 ; [0] sound off ch 1-3 + .db $b5,$00 ; [0] + .db $b6,$00 ; [0] -s2: .db $b4,$00 ; [2] sound off ch 4-6 - .db $b5,$00 ; [2] - .db $b6,$00 ; [2] + .db part1, 6/2 + .db $b4,$00 ; [1] sound off ch 4-6 + .db $b5,$00 ; [1] + .db $b6,$00 ; [1] -s3: .db $40,$7f ; [1] ch 1-3 total level minimum - .db $41,$7f ; [1] - .db $42,$7f ; [1] - .db $44,$7f ; [1] - .db $45,$7f ; [1] - .db $46,$7f ; [1] - .db $48,$7f ; [1] - .db $49,$7f ; [1] - .db $4a,$7f ; [1] - .db $4c,$7f ; [1] - .db $4d,$7f ; [1] - .db $4e,$7f ; [1] -s4: - .db $40,$7f ; [2] ch 4-6 total level minimum - .db $41,$7f ; [2] - .db $42,$7f ; [2] - .db $44,$7f ; [2] - .db $45,$7f ; [2] - .db $46,$7f ; [2] - .db $48,$7f ; [2] - .db $49,$7f ; [2] - .db $4a,$7f ; [2] - .db $4c,$7f ; [2] - .db $4d,$7f ; [2] - .db $4e,$7f ; [2] -s5: -#IF (YM_CLR) - .db $2a,$00 ; [1] ; dac value - - .db $24,$00 ; [1] ; timer A frequency - .db $25,$00 ; [1] ; timer A frequency - .db $26,$00 ; [1] ; time B frequency + .db part0, 24/2 + .db $40,$7f ; [0] ch 1-3 total level minimum + .db $41,$7f ; [0] + .db $42,$7f ; [0] + .db $44,$7f ; [0] + .db $45,$7f ; [0] + .db $46,$7f ; [0] + .db $48,$7f ; [0] + .db $49,$7f ; [0] + .db $4a,$7f ; [0] + .db $4c,$7f ; [0] + .db $4d,$7f ; [0] + .db $4e,$7f ; [0] - .db $30,$00 ; [1] ; ch 1-3 multiply & detune - .db $31,$00 ; [1] - .db $32,$00 ; [1] - .db $34,$00 ; [1] - .db $35,$00 ; [1] - .db $36,$00 ; [1] - .db $38,$00 ; [1] - .db $39,$00 ; [1] - .db $3a,$00 ; [1] - .db $3c,$00 ; [1] - .db $3d,$00 ; [1] - .db $3e,$00 ; [1] -s6: - .db $30,$00 ; [2] ch 4-6 multiply & detune - .db $31,$00 ; [2] - .db $32,$00 ; [2] - .db $34,$00 ; [2] - .db $35,$00 ; [2] - .db $36,$00 ; [2] - .db $38,$00 ; [2] - .db $39,$00 ; [2] - .db $3a,$00 ; [2] - .db $3c,$00 ; [2] - .db $3d,$00 ; [2] - .db $3e,$00 ; [2] -s7: - .db $50,$00 ; [1] ch 1-3 attack rate and scaling - .db $51,$00 ; [1] - .db $52,$00 ; [1] - .db $54,$00 ; [1] - .db $55,$00 ; [1] - .db $56,$00 ; [1] - .db $58,$00 ; [1] - .db $59,$00 ; [1] - .db $5a,$00 ; [1] - .db $5c,$00 ; [1] - .db $5d,$00 ; [1] - .db $5e,$00 ; [1] -s8: - .db $50,$00 ; [2] ch 4-6 attack rate and scaling - .db $51,$00 ; [2] - .db $52,$00 ; [2] - .db $54,$00 ; [2] - .db $55,$00 ; [2] - .db $56,$00 ; [2] - .db $58,$00 ; [2] - .db $59,$00 ; [2] - .db $5a,$00 ; [2] - .db $5c,$00 ; [2] - .db $5d,$00 ; [2] - .db $5e,$00 ; [2] -s9: - .db $60,$00 ; [1] ch 1-3 decay rate and am enable - .db $61,$00 ; [1] - .db $62,$00 ; [1] - .db $64,$00 ; [1] - .db $65,$00 ; [1] - .db $66,$00 ; [1] - .db $68,$00 ; [1] - .db $69,$00 ; [1] - .db $6a,$00 ; [1] - .db $6c,$00 ; [1] - .db $6d,$00 ; [1] - .db $6e,$00 ; [1] -s10: - .db $60,$00 ; [2] ch 4-6 decay rate and am enable - .db $61,$00 ; [2] - .db $62,$00 ; [2] - .db $64,$00 ; [2] - .db $65,$00 ; [2] - .db $66,$00 ; [2] - .db $68,$00 ; [2] - .db $69,$00 ; [2] - .db $6a,$00 ; [2] - .db $6c,$00 ; [2] - .db $6d,$00 ; [2] - .db $6e,$00 ; [2] -s11: - .db $70,$00 ; [1] ch 1-3 sustain rate - .db $71,$00 ; [1] - .db $72,$00 ; [1] - .db $74,$00 ; [1] - .db $75,$00 ; [1] - .db $76,$00 ; [1] - .db $78,$00 ; [1] - .db $79,$00 ; [1] - .db $7a,$00 ; [1] - .db $7c,$00 ; [1] - .db $7d,$00 ; [1] - .db $7e,$00 ; [1] -s12: - .db $70,$00 ; [2] ch 4-6 sustain rate - .db $71,$00 ; [2] - .db $72,$00 ; [2] - .db $74,$00 ; [2] - .db $75,$00 ; [2] - .db $76,$00 ; [2] - .db $78,$00 ; [2] - .db $79,$00 ; [2] - .db $7a,$00 ; [2] - .db $7c,$00 ; [2] - .db $7d,$00 ; [2] - .db $7e,$00 ; [2] -s13: - .db $80,$00 ; [1] ch 1-3 release rate and sustain level - .db $81,$00 ; [1] - .db $82,$00 ; [1] - .db $84,$00 ; [1] - .db $85,$00 ; [1] - .db $86,$00 ; [1] - .db $88,$00 ; [1] - .db $89,$00 ; [1] - .db $8a,$00 ; [1] - .db $8c,$00 ; [1] - .db $8d,$00 ; [1] - .db $8e,$00 ; [1] -s14: - .db $80,$00 ; [2] ch 4-6 release rate and sustain level - .db $81,$00 ; [2] - .db $82,$00 ; [2] - .db $84,$00 ; [2] - .db $85,$00 ; [2] - .db $86,$00 ; [2] - .db $88,$00 ; [2] - .db $89,$00 ; [2] - .db $8a,$00 ; [2] - .db $8c,$00 ; [2] - .db $8d,$00 ; [2] - .db $8e,$00 ; [2] -s15: - .db $90,$00 ; [1] ch 1-3 ssg-eg - .db $91,$00 ; [1] - .db $92,$00 ; [1] - .db $94,$00 ; [1] - .db $95,$00 ; [1] - .db $96,$00 ; [1] - .db $98,$00 ; [1] - .db $99,$00 ; [1] - .db $9a,$00 ; [1] - .db $9c,$00 ; [1] - .db $9d,$00 ; [1] - .db $9e,$00 ; [1] -s16: - .db $90,$00 ; [2] ch 4-6 ssg-eg - .db $91,$00 ; [2] - .db $92,$00 ; [2] - .db $94,$00 ; [2] - .db $95,$00 ; [2] - .db $96,$00 ; [2] - .db $98,$00 ; [2] - .db $99,$00 ; [2] - .db $9a,$00 ; [2] - .db $9c,$00 ; [2] - .db $9d,$00 ; [2] - .db $9e,$00 ; [2] -s17: - .db $a0,$00 ; [1] ch 1-3 frequency - .db $a1,$00 ; [1] - .db $a2,$00 ; [1] - .db $a4,$00 ; [1] - .db $a5,$00 ; [1] - .db $a6,$00 ; [1] -; .db $a8,$00 ; [1] ch 3 special mode -; .db $a9,$00 ; [1] -; .db $aa,$00 ; [1] -; .db $ac,$00 ; [1] -; .db $ad,$00 ; [1] -; .db $ae,$00 ; [1] -s18: - .db $a0,$00 ; [2] ch 4-6 frequency - .db $a1,$00 ; [2] - .db $a2,$00 ; [2] - .db $a4,$00 ; [2] - .db $a5,$00 ; [2] - .db $a6,$00 ; [2] -; .db $a8,$00 ; [2] ch 3 special mode -; .db $a9,$00 ; [2] -; .db $aa,$00 ; [2] -; .db $ac,$00 ; [2] -; .db $ad,$00 ; [2] -; .db $ae,$00 ; [2] -s19: - .db $b0,$00 ; [1] ch 1-3 algorith + feedback - .db $b1,$00 ; [1] - .db $b2,$00 ; [1] -s20: - .db $b0,$00 ; [2] ch 4-6 algorith + feedback - .db $b1,$00 ; [2] - .db $b2,$00 ; [2] -s21: -#ENDIF + .db part1, 24/2 + .db $40,$7f ; [1] ch 4-6 total level minimum + .db $41,$7f ; [1] + .db $42,$7f ; [1] + .db $44,$7f ; [1] + .db $45,$7f ; [1] + .db $46,$7f ; [1] + .db $48,$7f ; [1] + .db $49,$7f ; [1] + .db $4a,$7f ; [1] + .db $4c,$7f ; [1] + .db $4d,$7f ; [1] + .db $4e,$7f ; [1] + + .db part0, 32/2 + .db $2a,$00 ; [0] ; dac value + .db $24,$00 ; [0] ; timer A frequency + .db $25,$00 ; [0] ; timer A frequency + .db $26,$00 ; [0] ; time B frequency + .db $30,$00 ; [0] ; ch 1-3 multiply & detune + .db $31,$00 ; [0] + .db $32,$00 ; [0] + .db $34,$00 ; [0] + .db $35,$00 ; [0] + .db $36,$00 ; [0] + .db $38,$00 ; [0] + .db $39,$00 ; [0] + .db $3a,$00 ; [0] + .db $3c,$00 ; [0] + .db $3d,$00 ; [0] + .db $3e,$00 ; [0] + + .db part1, 24/2 + .db $30,$00 ; [1] ch 4-6 multiply & detune + .db $31,$00 ; [1] + .db $32,$00 ; [1] + .db $34,$00 ; [1] + .db $35,$00 ; [1] + .db $36,$00 ; [1] + .db $38,$00 ; [1] + .db $39,$00 ; [1] + .db $3a,$00 ; [1] + .db $3c,$00 ; [1] + .db $3d,$00 ; [1] + .db $3e,$00 ; [1] + + .db part0, 24/2 + .db $50,$00 ; [0] ch 1-3 attack rate and scaling + .db $51,$00 ; [0] + .db $52,$00 ; [0] + .db $54,$00 ; [0] + .db $55,$00 ; [0] + .db $56,$00 ; [0] + .db $58,$00 ; [0] + .db $59,$00 ; [0] + .db $5a,$00 ; [0] + .db $5c,$00 ; [0] + .db $5d,$00 ; [0] + .db $5e,$00 ; [0] + + .db part1, 24/2 + .db $50,$00 ; [1] ch 4-6 attack rate and scaling + .db $51,$00 ; [1] + .db $52,$00 ; [1] + .db $54,$00 ; [1] + .db $55,$00 ; [1] + .db $56,$00 ; [1] + .db $58,$00 ; [1] + .db $59,$00 ; [1] + .db $5a,$00 ; [1] + .db $5c,$00 ; [1] + .db $5d,$00 ; [1] + .db $5e,$00 ; [1] + + .db part0, 24/2 + .db $60,$00 ; [0] ch 1-3 decay rate and am enable + .db $61,$00 ; [0] + .db $62,$00 ; [0] + .db $64,$00 ; [0] + .db $65,$00 ; [0] + .db $66,$00 ; [0] + .db $68,$00 ; [0] + .db $69,$00 ; [0] + .db $6a,$00 ; [0] + .db $6c,$00 ; [0] + .db $6d,$00 ; [0] + .db $6e,$00 ; [0] + + .db part1, 24/2 + .db $60,$00 ; [1] ch 4-6 decay rate and am enable + .db $61,$00 ; [1] + .db $62,$00 ; [1] + .db $64,$00 ; [1] + .db $65,$00 ; [1] + .db $66,$00 ; [1] + .db $68,$00 ; [1] + .db $69,$00 ; [1] + .db $6a,$00 ; [1] + .db $6c,$00 ; [1] + .db $6d,$00 ; [1] + .db $6e,$00 ; [1] + + .db part0, 24/2 + .db $70,$00 ; [0] ch 1-3 sustain rate + .db $71,$00 ; [0] + .db $72,$00 ; [0] + .db $74,$00 ; [0] + .db $75,$00 ; [0] + .db $76,$00 ; [0] + .db $78,$00 ; [0] + .db $79,$00 ; [0] + .db $7a,$00 ; [0] + .db $7c,$00 ; [0] + .db $7d,$00 ; [0] + .db $7e,$00 ; [0] + .db part1, 24/2 + .db $70,$00 ; [1] ch 4-6 sustain rate + .db $71,$00 ; [1] + .db $72,$00 ; [1] + .db $74,$00 ; [1] + .db $75,$00 ; [1] + .db $76,$00 ; [1] + .db $78,$00 ; [1] + .db $79,$00 ; [1] + .db $7a,$00 ; [1] + .db $7c,$00 ; [1] + .db $7d,$00 ; [1] + .db $7e,$00 ; [1] + + .db part0, 24/2 + .db $80,$00 ; [0] ch 1-3 release rate and sustain level + .db $81,$00 ; [0] + .db $82,$00 ; [0] + .db $84,$00 ; [0] + .db $85,$00 ; [0] + .db $86,$00 ; [0] + .db $88,$00 ; [0] + .db $89,$00 ; [0] + .db $8a,$00 ; [0] + .db $8c,$00 ; [0] + .db $8d,$00 ; [0] + .db $8e,$00 ; [0] + + .db part1, 24/2 + .db $80,$00 ; [1] ch 4-6 release rate and sustain level + .db $81,$00 ; [1] + .db $82,$00 ; [1] + .db $84,$00 ; [1] + .db $85,$00 ; [1] + .db $86,$00 ; [1] + .db $88,$00 ; [1] + .db $89,$00 ; [1] + .db $8a,$00 ; [1] + .db $8c,$00 ; [1] + .db $8d,$00 ; [1] + .db $8e,$00 ; [1] + + .db part0, 24/2 + .db $90,$00 ; [0] ch 1-3 ssg-eg + .db $91,$00 ; [0] + .db $92,$00 ; [0] + .db $94,$00 ; [0] + .db $95,$00 ; [0] + .db $96,$00 ; [0] + .db $98,$00 ; [0] + .db $99,$00 ; [0] + .db $9a,$00 ; [0] + .db $9c,$00 ; [0] + .db $9d,$00 ; [0] + .db $9e,$00 ; [0] + + .db part1, 24/2 + .db $90,$00 ; [1] ch 4-6 ssg-eg + .db $91,$00 ; [1] + .db $92,$00 ; [1] + .db $94,$00 ; [1] + .db $95,$00 ; [1] + .db $96,$00 ; [1] + .db $98,$00 ; [1] + .db $99,$00 ; [1] + .db $9a,$00 ; [1] + .db $9c,$00 ; [1] + .db $9d,$00 ; [1] + .db $9e,$00 ; [1] + + .db part0, 12/2 + .db $a0,$00 ; [0] ch 1-3 frequency + .db $a1,$00 ; [0] + .db $a2,$00 ; [0] + .db $a4,$00 ; [0] + .db $a5,$00 ; [0] + .db $a6,$00 ; [0] +; .db $a8,$00 ; [0] ch 3 special mode +; .db $a9,$00 ; [0] +; .db $aa,$00 ; [0] +; .db $ac,$00 ; [0] +; .db $ad,$00 ; [0] +; .db $ae,$00 ; [0] + + .db part1, 12/2 + .db $a0,$00 ; [1] ch 4-6 frequency + .db $a1,$00 ; [1] + .db $a2,$00 ; [1] + .db $a4,$00 ; [1] + .db $a5,$00 ; [1] + .db $a6,$00 ; [1] +; .db $a8,$00 ; [1] ch 3 special mode +; .db $a9,$00 ; [1] +; .db $aa,$00 ; [1] +; .db $ac,$00 ; [1] +; .db $ad,$00 ; [1] +; .db $ae,$00 ; [1] + + .db part0, 6/2 + .db $b0,$00 ; [0] ch 1-3 algorith + feedback + .db $b1,$00 ; [0] + .db $b2,$00 ; [0] + + .db part1, 6/2 + .db $b0,$00 ; [1] ch 4-6 algorith + feedback + .db $b1,$00 ; [1] + .db $b2,$00 ; [1] +; + .db $00 ; End flag +#ENDIF