From be8177b8a41cc76cc5d36fdbe582623b8d14831b Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 18 Dec 2022 20:41:29 +0800 Subject: [PATCH 01/10] ym26112 driver --- Source/Doc/Architecture.md | 15 +- Source/HBIOS/hbios.asm | 5 +- Source/HBIOS/hbios.inc | 1 + Source/HBIOS/ym2612.asm | 903 +++++++++++++++++++++++++------------ 4 files changed, 640 insertions(+), 284 deletions(-) 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..a8d8463e 100644 --- a/Source/HBIOS/ym2612.asm +++ b/Source/HBIOS/ym2612.asm @@ -1,319 +1,670 @@ -;====================================================================== -; 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) ; ;------------------------------------------------------------------------------ -; 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 - - ld b,+(s3-s2)/2 -pt2: call set2 ; [2] - djnz pt2 - - ld b,+(s4-s3)/2 -pt3: call set1 ; [1] - djnz pt3 - - ld b,+(s5-s4)/2 -pt4: call set2 ; [2] - djnz pt4 - +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 +; +YM_DURATION ret -set1: ld a,(hl) ; YM2162 Register write - inc hl ; Register bank [1] - out (YMSEL),a - ld a,(hl) +;------------------------------------------------------------------------------ +; 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 - 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) +t_loop: ld a,(hl) ; get register to write + out (c),a +; call PRTHEXBYTE 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 + inc c + ld a,(hl) ; get value to write + out (c),a +; call PRTHEXBYTE + 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 c + dec d + jr nz,t_loop +; + 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 -s1: .db $22,$00 ; [1] lfo off + 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 - .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 + ;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 - .db $b4,$00 ; [1] sound off ch 1-3 + ;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 (AY_PENDING_PERIOD), HL ; RETURN NZ IF NUMBER TOO LARGE + RET ; SAVE AND RETURN SUCCESSFUL +; +YM_PERIOD1: LD A, $FF ; REQUESTED PERIOD IS LARGER + LD (AY_PENDING_PERIOD), A ; THAN THE DEVICE CAN SUPPORT + LD (AY_PENDING_PERIOD+1), A; SO SET PERIOD TO FFFF + RET ; AND RETURN FAILURE +; +;------------------------------------------------------------------------------ +; Sound driver function - PLAY +; D = CHANNEL +;------------------------------------------------------------------------------ +; +YM_PLAY: LD A,(YM_RDY_RST) ; IF STILL IN RESET + OR A ; STATE GO SETUP FOR + CALL Z,YM_MAKE_RDY ; PLAYING +; + ld hl,(AY_PENDING_PERIOD) ; GET THE PREVIOUSLY SETUP + ld de,ym_playnote+5 ; TONE DATA AND + ld a,h + ld (de),a ; PATCH IT INTO THE + inc de ; YM2612 PLAY COMMAND + inc de + ld a,l + ld (de),a +; + 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, 8/2 + .db $28, $00 ; [0] KEY OFF + .db $A4, $3F ; [0] Frequency MSB + .db $A0, $FF ; [0] Frequency LSB + .db $28, $F0 ; [0] KEY ON + .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 reset state +;------------------------------------------------------------------------------ +; +part0: .equ YMSEL +part1: .equ YM2SEL +; +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 play +;------------------------------------------------------------------------------ +; +ym_cfg_ready: .db part0, 20/2 + .db $22, $00 ; [0] Global: LFO disable + .db $B0, $30 ; [0] Algorithm, Feedback <- pure sine wave + .db $3C, $01 ; [0] Operator 4.MUL = 1 + .db $B4, $C0 ; [0] Stereo output + .db $44, $7F ; [0] Mute operator 3 <- pure sine wave + .db $4C, $00 ; [0] Max volume for operator 4 + .db $5C, $1F ; [0] Operator 4.AR = shortest + .db $6C, $06 ; [0] Operator 4.D1R= 6 + .db $7C, $1F ; [0] Operator 4.D2R= 31 + .db $8C, $FF ; [0] Operator 4.SL = 15 / Operator4. RR=15 +; .db $A4, $3F ; [0] Frequency MSB +; .db $A0, 84;$FF ; [0] Frequency LSB +; .db $28, $00 ; [0] KEY OFF +; .db $28, $F0 ; [0] KEY ON +; + .db $00 ; End flag -s2: .db $b4,$00 ; [2] sound off ch 4-6 - .db $b5,$00 ; [2] - .db $b6,$00 ; [2] +;------------------------------------------------------------------------------ +; Register configuration data for hard reset +;------------------------------------------------------------------------------ +; +#IF (0) +ym_cfg_full: .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 ; [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] +s3: .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] 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] + .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] 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 $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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] 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] + .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] s19: - .db $b0,$00 ; [1] ch 1-3 algorith + feedback - .db $b1,$00 ; [1] - .db $b2,$00 ; [1] + .db $b0,$00 ; [0] ch 1-3 algorith + feedback + .db $b1,$00 ; [0] + .db $b2,$00 ; [0] s20: - .db $b0,$00 ; [2] ch 4-6 algorith + feedback - .db $b1,$00 ; [2] - .db $b2,$00 ; [2] + .db $b0,$00 ; [1] ch 4-6 algorith + feedback + .db $b1,$00 ; [1] + .db $b2,$00 ; [1] +; + .db $00 ; End flag s21: #ENDIF - From 285bc6611f9705b3c9207e9e7251e278eea56dc1 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 18 Dec 2022 20:44:55 +0800 Subject: [PATCH 02/10] Update Scales.asm --- Source/Apps/TEST/sound/Scales.asm | 284 +++++++++++++++++++++--------- 1 file changed, 202 insertions(+), 82 deletions(-) diff --git a/Source/Apps/TEST/sound/Scales.asm b/Source/Apps/TEST/sound/Scales.asm index bf91ea81..c63850b3 100644 --- a/Source/Apps/TEST/sound/Scales.asm +++ b/Source/Apps/TEST/sound/Scales.asm @@ -1,22 +1,173 @@ ; +;------------------------------------------------------------------------------ +; Play Scales using HBIOS +;------------------------------------------------------------------------------ +; +FCB .EQU $5C ; Location of default FCB +BDOS .EQU $0005 - .ORG $0100 +STEP .EQU 4 ; NOTE STEP I.E. 1 SEMITONE -; SCALES ON ALL THREE CHANNELS + .ORG $0100 +; + LD (OLDSTACK),SP ; save old stack pointer + LD SP,STACK ; set new stack pointer +; + LD A,(FCB+1) ; GET FIRST CHAR + CP '/' ; IS IT INDICATING AN ARGUMENT + LD A,0 ; ASSUME DEVICE 0 + JR NZ,NO_ARG ; + LD A,(FCB+2) ; GET NEXT CHARACTER + SUB '0' ; CALCULATE DEVICE # + LD (DEVICE),A ; -; JR SKIP +NO_ARG: LD C,A ; GET & DISPLAY # CHANNELS + LD B,$55 + LD E,1 + RST 08 + LD A,B + CALL PRTHEX + call CRLF - LD B,3 -NEXTCH0 LD A,B - DEC A - LD (CHANNEL),A - PUSH BC ; ACROSS - CALL SCALE ; ALL - POP BC ; CHANNELS - DJNZ NEXTCH0 + LD B,1 +; + CALL TST_TONE +; CALL TST_VOL +; +EXIT: LD SP, (OLDSTACK) ; Exit to CP/M + RST 00H + DI + HALT -; CONSTANT TONE ON ALL THREE CHANNELS, SCALE VOLUME -SKIP: +;------------------------------------------------------------------------------ +; FOR EACH CHANNEL PLAY SCALES FROM HIGHEST TO LOWEST. B = # CHANNELS +;------------------------------------------------------------------------------ + +TST_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 HALF + LD L,80H + RST 08 + POP BC +; + LD A,B +TST_TONE_LP: DEC A + LD (CHANNEL),A ; SAVE CURRENT CHANNEL + CALL SCALES ; PLAY SCALE + DJNZ TST_TONE_LP +; + PUSH BC + LD B,50H ; RESET DEVICE + RST 08 + POP BC +; + RET +; +;------------------------------------------------------------------------------ +; +SCALES: PUSH BC + PUSH AF + + LD HL,380 ; START NOTE + LD (NOTE),HL ; Top of Octave 7 is 343 +; +NEXT0: PUSH BC + LD BC,(NOTE) + CALL PRTHEXWORD + CALL PRTDOT + POP BC +; + LD B,53H ; NOTE + LD HL,(NOTE) + PUSH BC + RST 08 + POP BC + + OR A ; DID DRIVER FAIL + JR Z,NEXT4 ; THIS NOTE ? + + LD A,'n' + CALL FAILMSG + JR SKIP +; +NEXT4: LD B,57H ; DURATION + LD HL,1000 + PUSH BC + RST 08 + POP BC + + LD B,54H ; PLAY + LD A,(CHANNEL) + LD D,A + PUSH BC + RST 08 + POP BC +; + OR A ; DID DRIVER FAIL + JR Z,NEXT2 ; THIS NOTE ? + + LD A,'p' + 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 + 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 + + POP AF + POP BC +; + RET +; +FAILMSG: PUSH AF + PUSH BC ; YES SO DISPLAY + CALL PRTCHR + CALL CRLF + POP BC + POP AF + RET +; +;------------------------------------------------------------------------------ +; CONSTANT TONE ON ALL CHANNELS, SCALE VOLUME +;------------------------------------------------------------------------------ +TST_VOL: LD HL,332+48 ; TONE LD (NOTE),HL ; @@ -26,31 +177,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,75 +226,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 + PUSH BC LD A,(CHANNEL) LD D,A + POP BC 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 - LD A,(CHANNEL) - LD D,A - RST 08 -; - RET -; +;; +;------------------------------------------------------------------------------ +;------------------------------------------------------------------------------ + DELAY: LD HL,-1 DELAY1: DEC HL LD A,H @@ -136,10 +250,16 @@ DELAY1: DEC HL JR NZ,DELAY1 RET ; -BADFLAG .DB '*', $0D, $0A, '$' -NOTE .DW 128 -VOLUME .DB 0 -CHANNEL .DB 0 +#INCLUDE "printing.inc" +; +BADFLAG .DB '*','$' +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 From 2049b35ee21f2a946aeaa7612729c8d033cc756b Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 18 Dec 2022 20:56:12 +0800 Subject: [PATCH 03/10] Update ym2612.asm --- Source/HBIOS/ym2612.asm | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Source/HBIOS/ym2612.asm b/Source/HBIOS/ym2612.asm index a8d8463e..20d0ca80 100644 --- a/Source/HBIOS/ym2612.asm +++ b/Source/HBIOS/ym2612.asm @@ -51,9 +51,6 @@ YM_FNTBL: .DW YM_RESET ; YM_IDAT .EQU 0 ; NO INSTANCE DATA FOR THIS DEVICE ; -YM_DURATION - ret - ;------------------------------------------------------------------------------ ; YM2162 Initialization ; Announce device on console. @@ -252,6 +249,14 @@ YM_PERIOD1: LD A, $FF ; REQUESTED PERIOD IS LARGER 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 ;------------------------------------------------------------------------------ From d584d3d55349c98ae92ea2ec1defcc5de66b6037 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 18 Dec 2022 21:03:10 +0800 Subject: [PATCH 04/10] rename fm demo program --- Source/Apps/VGM/Build.cmd | 2 +- Source/Apps/VGM/Makefile | 4 ++-- Source/Apps/VGM/{YM2612.ASM => ymfmdemo.asm} | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) rename Source/Apps/VGM/{YM2612.ASM => ymfmdemo.asm} (98%) 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/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 From 030228e9b8bd1386b31378dcae78a2b41c90ca3c Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Sun, 18 Dec 2022 22:44:05 +0800 Subject: [PATCH 05/10] Update ym2612.asm --- Source/HBIOS/ym2612.asm | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/Source/HBIOS/ym2612.asm b/Source/HBIOS/ym2612.asm index 20d0ca80..fa568ac7 100644 --- a/Source/HBIOS/ym2612.asm +++ b/Source/HBIOS/ym2612.asm @@ -239,20 +239,20 @@ YM_PERIOD: LD A, H ; IF ZERO - ERROR ; 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 (AY_PENDING_PERIOD), HL ; RETURN NZ IF NUMBER TOO LARGE + 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 (AY_PENDING_PERIOD), A ; THAN THE DEVICE CAN SUPPORT - LD (AY_PENDING_PERIOD+1), A; SO SET PERIOD TO FFFF + 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 +; Sound driver function - DURATION ;------------------------------------------------------------------------------ ; -YM_DURATION: LD (YM_PENDING_DURATION),HL ; SET TONE DURATION +YM_DURATION: LD (YM_PENDING_DURATION),HL ; SET TONE DURATION XOR A RET ; @@ -265,7 +265,7 @@ YM_PLAY: LD A,(YM_RDY_RST) ; IF STILL IN RESET OR A ; STATE GO SETUP FOR CALL Z,YM_MAKE_RDY ; PLAYING ; - ld hl,(AY_PENDING_PERIOD) ; GET THE PREVIOUSLY SETUP + ld hl,(YM_PENDING_PERIOD) ; GET THE PREVIOUSLY SETUP ld de,ym_playnote+5 ; TONE DATA AND ld a,h ld (de),a ; PATCH IT INTO THE @@ -273,6 +273,13 @@ YM_PLAY: LD A,(YM_RDY_RST) ; IF STILL IN RESET inc de ld a,l ld (de),a + inc de + inc de + ld A,(YM_PENDING_VOLUME) ; GET VOLUME + srl a + cpl + and %01111111 ; PATCH IT INTO THE + ld (de),a ; YM2612 PLAY COMMAND ; ld hl,ym_playnote ; NOW PLAY IT jp ym_prog @@ -290,10 +297,11 @@ YM_MAKE_RDY: CPL ; Command sequence to play a note ;------------------------------------------------------------------------------ ; -ym_playnote: .db part0, 8/2 +ym_playnote: .db part0, 10/2 .db $28, $00 ; [0] KEY OFF - .db $A4, $3F ; [0] Frequency MSB - .db $A0, $FF ; [0] Frequency LSB + .db $A4, $3F ; [0] Frequency MSB ; patch +5 + .db $A0, $FF ; [0] Frequency LSB ; patch +7 + .db $4C, $00 ; [0] Volume ; patch +9 .db $28, $F0 ; [0] KEY ON .db $00 ; End flag ; From e409391f14f509495a7966d2ba66198ec7c3c8a3 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Mon, 19 Dec 2022 21:54:17 +0800 Subject: [PATCH 06/10] Update Scales.asm --- Source/Apps/TEST/sound/Scales.asm | 160 +++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 48 deletions(-) diff --git a/Source/Apps/TEST/sound/Scales.asm b/Source/Apps/TEST/sound/Scales.asm index c63850b3..46bbb19f 100644 --- a/Source/Apps/TEST/sound/Scales.asm +++ b/Source/Apps/TEST/sound/Scales.asm @@ -1,49 +1,60 @@ ; ;------------------------------------------------------------------------------ -; Play Scales using HBIOS +; PLAY SCALES USING HBIOS ;------------------------------------------------------------------------------ ; FCB .EQU $5C ; Location of default FCB BDOS .EQU $0005 - -STEP .EQU 4 ; NOTE STEP I.E. 1 SEMITONE - +; .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 - CP '/' ; IS IT INDICATING AN ARGUMENT - LD A,0 ; ASSUME DEVICE 0 - JR NZ,NO_ARG ; - LD A,(FCB+2) ; GET NEXT CHARACTER - SUB '0' ; CALCULATE DEVICE # - LD (DEVICE),A ; - -NO_ARG: LD C,A ; GET & DISPLAY # CHANNELS + 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 PRTHEX - call CRLF - - LD B,1 -; - CALL TST_TONE -; CALL TST_VOL + CALL PRTDECB + CALL CRLF ; NUMBER OF CHANNELS IS IN B ; -EXIT: LD SP, (OLDSTACK) ; Exit to CP/M - RST 00H - DI - HALT - ;------------------------------------------------------------------------------ -; FOR EACH CHANNEL PLAY SCALES FROM HIGHEST TO LOWEST. B = # CHANNELS +; LOOP THROUGH EACH CHANNEL ;------------------------------------------------------------------------------ -TST_TONE: LD A,(DEVICE) ; C CONTAINS DEVICE +CH__TONE: LD A,(DEVICE) ; C CONTAINS DEVICE LD C,A ; THROUGH THIS LOOP ; PUSH BC @@ -52,15 +63,17 @@ TST_TONE: LD A,(DEVICE) ; C CONTAINS DEVICE POP BC ; PUSH BC - LD B,51H ; VOLUME HALF - LD L,80H + 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 SCALES ; PLAY SCALE + CALL TST_SCALES ; SCALES TEST +; CALL TST_VOLUME ; VOLUME TEST + CALL CRLF DJNZ TST_TONE_LP ; PUSH BC @@ -68,23 +81,45 @@ TST_TONE_LP: DEC A RST 08 POP BC ; - RET +;------------------------------------------------------------------------------ +; RESTORE STACK & EXIT +;------------------------------------------------------------------------------ ; +EXIT: LD SP, (OLDSTACK) ; Exit to CP/M + RST 00H + DI + HALT +; +;------------------------------------------------------------------------------ +; PLAY SCALES FROM HIGHEST HBIOS NOTE TO LOWEST ;------------------------------------------------------------------------------ ; -SCALES: PUSH BC +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 BC,(NOTE) - CALL PRTHEXWORD - CALL PRTDOT +; + 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 ; NOTE + LD B,53H ; SET NOTE LD HL,(NOTE) PUSH BC RST 08 @@ -93,7 +128,7 @@ NEXT0: PUSH BC OR A ; DID DRIVER FAIL JR Z,NEXT4 ; THIS NOTE ? - LD A,'n' + LD DE,TXT_BAD_N CALL FAILMSG JR SKIP ; @@ -111,9 +146,9 @@ NEXT4: LD B,57H ; DURATION POP BC ; OR A ; DID DRIVER FAIL - JR Z,NEXT2 ; THIS NOTE ? + JR Z,NEXT2 ; TO PLAY ? - LD A,'p' + LD DE,TXT_BAD_N CALL FAILMSG JR SKIP ; @@ -131,7 +166,7 @@ SKIP: LD HL,(NOTE) JR NZ,NEXT0 ; LD B,51H ; VOLUME - LD L,00H + LD L,00H ; OFF PUSH BC RST 08 POP BC @@ -145,7 +180,7 @@ SKIP: LD HL,(NOTE) PUSH BC LD C, 6 ; check for keypress - LD E, 0FFH + LD E,0FFH CALL BDOS POP BC OR A @@ -157,17 +192,18 @@ SKIP: LD HL,(NOTE) RET ; FAILMSG: PUSH AF - PUSH BC ; YES SO DISPLAY - CALL PRTCHR + PUSH BC + CALL PRTSTR CALL CRLF POP BC POP AF RET ; ;------------------------------------------------------------------------------ -; CONSTANT TONE ON ALL CHANNELS, SCALE VOLUME +; CONSTANT TONE ON ALL CHANNELS, SCALE VOLUME ;------------------------------------------------------------------------------ -TST_VOL: +; +TST_VOLUME: LD HL,332+48 ; TONE LD (NOTE),HL ; @@ -241,8 +277,9 @@ NEXT1: LD B,51H ; VOLUME RET ;; ;------------------------------------------------------------------------------ +; LONG DELAY ;------------------------------------------------------------------------------ - +; DELAY: LD HL,-1 DELAY1: DEC HL LD A,H @@ -250,9 +287,37 @@ DELAY1: DEC HL JR NZ,DELAY1 RET ; +;------------------------------------------------------------------------------ +; 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" ; -BADFLAG .DB '*','$' +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 @@ -262,4 +327,3 @@ OLDSTACK .DW 0 ; original stack pointer STACK ; top of stack ; .END - From c072027b87af83ac135b42e240982ff7fc4b939e Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Tue, 20 Dec 2022 17:19:12 +0800 Subject: [PATCH 07/10] Preserve registers --- Source/Apps/Tune/printing.inc | 2 ++ Source/Apps/VGM/printing.inc | 2 ++ 2 files changed, 4 insertions(+) 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/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 From bd03277bfeeadfeee3056d7a4e6ad10bd70818e2 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Wed, 21 Dec 2022 05:31:38 +0800 Subject: [PATCH 08/10] Update ym2612.asm --- Source/HBIOS/ym2612.asm | 99 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/Source/HBIOS/ym2612.asm b/Source/HBIOS/ym2612.asm index fa568ac7..a63d085c 100644 --- a/Source/HBIOS/ym2612.asm +++ b/Source/HBIOS/ym2612.asm @@ -418,7 +418,7 @@ ym_cfg: .db part0, 24/2 ; Register configuration data for play ;------------------------------------------------------------------------------ ; -ym_cfg_ready: .db part0, 20/2 +;ym_cfg_ready: .db part0, 20/2 .db $22, $00 ; [0] Global: LFO disable .db $B0, $30 ; [0] Algorithm, Feedback <- pure sine wave .db $3C, $01 ; [0] Operator 4.MUL = 1 @@ -435,7 +435,102 @@ ym_cfg_ready: .db part0, 20/2 ; .db $28, $F0 ; [0] KEY ON ; .db $00 ; End flag - +; +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,%10000000 ; Channel 1-3 + .db $b5,%10000000 ; Left Channel + .db $b6,%10000000 +; + .db part1, 6/2 + .db $b4,%01000000 ; Channel 4-6 + .db $b5,%01000000 ; Right Channel + .db $b6,%01000000 +; + .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, $00 ; Channel 1-3 + .db $4d, $00 ; Max volume for operator 4 + .db $4e, $00 +; + .db part1, 6/2 + .db $4C, $00 ; Channel 4-6 + .db $4d, $00 ; Max volume for operator 4 + .db $4e, $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 hard reset ;------------------------------------------------------------------------------ From 96269a7f45e252697fea1352870fa40bd3f2f218 Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Wed, 21 Dec 2022 22:53:47 +0800 Subject: [PATCH 09/10] Update ym2612.asm --- Source/HBIOS/ym2612.asm | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/Source/HBIOS/ym2612.asm b/Source/HBIOS/ym2612.asm index a63d085c..bdd688fd 100644 --- a/Source/HBIOS/ym2612.asm +++ b/Source/HBIOS/ym2612.asm @@ -261,7 +261,34 @@ YM_DURATION: LD (YM_PENDING_DURATION),HL ; SET TONE DURATION ; D = CHANNEL ;------------------------------------------------------------------------------ ; -YM_PLAY: LD A,(YM_RDY_RST) ; IF STILL IN RESET +YM_PLAY: ld hl,ym_playnote+0 + ld a,d ; 000 > 000 011 > 100 + cp 3 ; 001 > 001 100 > 101 + ld e,part1 ; 010 > 010 101 > 110 + jr c,ch012 + sub 3 + ld d,a ; d = 0..2 + add a,4 + jr ch345 ; a = 4..6 +ch012: ld e,part0 +ch345: ld (hl),e + ld hl,ym_playnote+3 ; setup keyon channel + ld (hl),a + ld hl,ym_playnote+11 ; setup keyoff channel + or %11110000 + ld (hl),a + + ld a,$a4 ; setup frequency channel + add a,d ; msb + ld hl,ym_playnote+4 + ld (hl),a + + ld a,$a0 ; setup frequency channel + add a,d ; lsb + ld hl,ym_playnote+6 + ld (hl),a + + LD A,(YM_RDY_RST) ; IF STILL IN RESET OR A ; STATE GO SETUP FOR CALL Z,YM_MAKE_RDY ; PLAYING ; @@ -298,11 +325,11 @@ YM_MAKE_RDY: CPL ;------------------------------------------------------------------------------ ; ym_playnote: .db part0, 10/2 - .db $28, $00 ; [0] KEY OFF - .db $A4, $3F ; [0] Frequency MSB ; patch +5 - .db $A0, $FF ; [0] Frequency LSB ; patch +7 - .db $4C, $00 ; [0] Volume ; patch +9 - .db $28, $F0 ; [0] KEY ON + .db $28, $00 ; [0] KEY OFF ; 00000111 + .db $A4, $3F ; [0] Frequency MSB ; patch +5 ; A4+channel-1 + .db $A0, $FF ; [0] Frequency LSB ; patch +7 ; A4+channel-1 + .db $4C, $00 ; [0] Volume ; patch +9 ; 4C+channel-1 + .db $28, $F0 ; [0] KEY ON ; 00000111 .db $00 ; End flag ; ;------------------------------------------------------------------------------ From 5b1542e49bbafd68621c2c5594bbe3e60e03bc3f Mon Sep 17 00:00:00 2001 From: b1ackmai1er Date: Thu, 29 Dec 2022 18:57:50 +0800 Subject: [PATCH 10/10] Update ym2612.asm --- Source/HBIOS/ym2612.asm | 363 ++++++++++++++++++++++++---------------- 1 file changed, 215 insertions(+), 148 deletions(-) diff --git a/Source/HBIOS/ym2612.asm b/Source/HBIOS/ym2612.asm index bdd688fd..148e7329 100644 --- a/Source/HBIOS/ym2612.asm +++ b/Source/HBIOS/ym2612.asm @@ -30,13 +30,15 @@ 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 ; ;------------------------------------------------------------------------------ ; Driver function table and instance data ;------------------------------------------------------------------------------ ; YM_FNTBL: .DW YM_RESET - .DW YM_VOLUME + .DW ym_volume .DW YM_PERIOD .DW YM_NOTE .DW YM_PLAY @@ -84,14 +86,31 @@ ym_prog: ld c,(hl) ; get port address 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 -; call PRTHEXBYTE + out (c),a ; write reg to RSEL port +; +#IF (YM_DEBUG) + call PRTHEXBYTE ; register +#ENDIF +; inc hl - inc c + inc c ; point to RDAT port ld a,(hl) ; get value to write - out (c),a -; call PRTHEXBYTE + 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 ; @@ -100,10 +119,13 @@ nready1: in a,(c) ; ready with timeout ; ; timed out ; -ready1: inc hl - dec c - dec d +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 @@ -188,7 +210,7 @@ YM_RESET: ;CALL AY_CHKREDY ; RETURNS TO OUR CALLER IF NOT READY ; Sound driver function - VOLUME ;------------------------------------------------------------------------------ ; -YM_VOLUME: LD A,L ; SAVE VOLUME +ym_volume: LD A,L ; SAVE VOLUME LD (YM_PENDING_VOLUME),A XOR A ; SIGNAL SUCCESS RET @@ -261,31 +283,54 @@ YM_DURATION: LD (YM_PENDING_DURATION),HL ; SET TONE DURATION ; D = CHANNEL ;------------------------------------------------------------------------------ ; -YM_PLAY: ld hl,ym_playnote+0 - ld a,d ; 000 > 000 011 > 100 - cp 3 ; 001 > 001 100 > 101 - ld e,part1 ; 010 > 010 101 > 110 - jr c,ch012 +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 - jr ch345 ; a = 4..6 + add a,4 ; a = 4..6 + jr ch345 ch012: ld e,part0 -ch345: ld (hl),e - ld hl,ym_playnote+3 ; setup keyon channel +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 - ld hl,ym_playnote+11 ; setup keyoff channel - or %11110000 + + ld a,$a4 ; setup frequency register msb + add a,d ; $a4-$a6 + ld hl,ym_playcmd02 ld (hl),a - ld a,$a4 ; setup frequency channel - add a,d ; msb - ld hl,ym_playnote+4 + ld a,$a0 ; setup frequency register lsb + add a,d ; $a0-$a2 + ld hl,ym_playcmd04 ld (hl),a - ld a,$a0 ; setup frequency channel - add a,d ; lsb - ld hl,ym_playnote+6 + ld a,$4c ; setup volume register + add a,d ; $4c-$4e + ld hl,ym_playcmd06 ld (hl),a LD A,(YM_RDY_RST) ; IF STILL IN RESET @@ -293,21 +338,30 @@ ch345: ld (hl),e CALL Z,YM_MAKE_RDY ; PLAYING ; ld hl,(YM_PENDING_PERIOD) ; GET THE PREVIOUSLY SETUP - ld de,ym_playnote+5 ; TONE DATA AND + ld de,ym_playcmd03 ; TONE DATA AND ld a,h ld (de),a ; PATCH IT INTO THE - inc de ; YM2612 PLAY COMMAND - inc de + ld de,ym_playcmd05 ; YM2612 PLAY COMMAND ld a,l ld (de),a - inc de - inc de +; + 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 ; @@ -324,12 +378,22 @@ YM_MAKE_RDY: CPL ; Command sequence to play a note ;------------------------------------------------------------------------------ ; -ym_playnote: .db part0, 10/2 - .db $28, $00 ; [0] KEY OFF ; 00000111 - .db $A4, $3F ; [0] Frequency MSB ; patch +5 ; A4+channel-1 - .db $A0, $FF ; [0] Frequency LSB ; patch +7 ; A4+channel-1 - .db $4C, $00 ; [0] Volume ; patch +9 ; 4C+channel-1 - .db $28, $F0 ; [0] KEY ON ; 00000111 +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 $00 ; End flag ; ;------------------------------------------------------------------------------ @@ -386,83 +450,9 @@ ym_notetable: .dw 644 ; C ; 152 .dw 1268 ; approx ; ;------------------------------------------------------------------------------ -; Register configuration data for reset state -;------------------------------------------------------------------------------ -; -part0: .equ YMSEL -part1: .equ YM2SEL -; -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 play ;------------------------------------------------------------------------------ ; -;ym_cfg_ready: .db part0, 20/2 - .db $22, $00 ; [0] Global: LFO disable - .db $B0, $30 ; [0] Algorithm, Feedback <- pure sine wave - .db $3C, $01 ; [0] Operator 4.MUL = 1 - .db $B4, $C0 ; [0] Stereo output - .db $44, $7F ; [0] Mute operator 3 <- pure sine wave - .db $4C, $00 ; [0] Max volume for operator 4 - .db $5C, $1F ; [0] Operator 4.AR = shortest - .db $6C, $06 ; [0] Operator 4.D1R= 6 - .db $7C, $1F ; [0] Operator 4.D2R= 31 - .db $8C, $FF ; [0] Operator 4.SL = 15 / Operator4. RR=15 -; .db $A4, $3F ; [0] Frequency MSB -; .db $A0, 84;$FF ; [0] Frequency LSB -; .db $28, $00 ; [0] KEY OFF -; .db $28, $F0 ; [0] KEY ON -; - .db $00 ; End flag -; ym_cfg_ready: .db part0, 2/2 .db $22, $00 ; Global: LFO disable ; @@ -487,14 +477,14 @@ ym_cfg_ready: .db part0, 2/2 .db $3e, $01 ; .db part0, 6/2 - .db $b4,%10000000 ; Channel 1-3 - .db $b5,%10000000 ; Left Channel - .db $b6,%10000000 + .db $b4,%01000000 ; Channel 1-3 + .db $b5,%01000000 ; Left Channel + .db $b6,%01000000 ; .db part1, 6/2 - .db $b4,%01000000 ; Channel 4-6 - .db $b5,%01000000 ; Right Channel - .db $b6,%01000000 + .db $b4,%10000000 ; Channel 4-6 + .db $b5,%10000000 ; Right Channel + .db $b6,%10000000 ; .db part0, 6/2 .db $44, $7F ; Channel 1-3 @@ -507,14 +497,14 @@ ym_cfg_ready: .db part0, 2/2 .db $46, $7F ; .db part0, 6/2 - .db $4C, $00 ; Channel 1-3 - .db $4d, $00 ; Max volume for operator 4 - .db $4e, $00 + .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, $00 ; Channel 4-6 - .db $4d, $00 ; Max volume for operator 4 - .db $4e, $00 + .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 @@ -558,12 +548,71 @@ ym_cfg_ready: .db part0, 2/2 ; .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 +; Register configuration data for hard reset state ;------------------------------------------------------------------------------ ; -#IF (0) -ym_cfg_full: .db $22,$00 ; [0] lfo off +#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 @@ -576,11 +625,13 @@ ym_cfg_full: .db $22,$00 ; [0] lfo off .db $b5,$00 ; [0] .db $b6,$00 ; [0] -s2: .db $b4,$00 ; [1] sound off ch 4-6 + .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 ; [0] ch 1-3 total level minimum + .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] @@ -592,7 +643,8 @@ s3: .db $40,$7f ; [0] ch 1-3 total level minimum .db $4c,$7f ; [0] .db $4d,$7f ; [0] .db $4e,$7f ; [0] -s4: + + .db part1, 24/2 .db $40,$7f ; [1] ch 4-6 total level minimum .db $41,$7f ; [1] .db $42,$7f ; [1] @@ -605,7 +657,8 @@ s4: .db $4c,$7f ; [1] .db $4d,$7f ; [1] .db $4e,$7f ; [1] -s5: + + .db part0, 32/2 .db $2a,$00 ; [0] ; dac value .db $24,$00 ; [0] ; timer A frequency .db $25,$00 ; [0] ; timer A frequency @@ -622,7 +675,8 @@ s5: .db $3c,$00 ; [0] .db $3d,$00 ; [0] .db $3e,$00 ; [0] -s6: + + .db part1, 24/2 .db $30,$00 ; [1] ch 4-6 multiply & detune .db $31,$00 ; [1] .db $32,$00 ; [1] @@ -635,7 +689,8 @@ s6: .db $3c,$00 ; [1] .db $3d,$00 ; [1] .db $3e,$00 ; [1] -s7: + + .db part0, 24/2 .db $50,$00 ; [0] ch 1-3 attack rate and scaling .db $51,$00 ; [0] .db $52,$00 ; [0] @@ -648,7 +703,8 @@ s7: .db $5c,$00 ; [0] .db $5d,$00 ; [0] .db $5e,$00 ; [0] -s8: + + .db part1, 24/2 .db $50,$00 ; [1] ch 4-6 attack rate and scaling .db $51,$00 ; [1] .db $52,$00 ; [1] @@ -661,7 +717,8 @@ s8: .db $5c,$00 ; [1] .db $5d,$00 ; [1] .db $5e,$00 ; [1] -s9: + + .db part0, 24/2 .db $60,$00 ; [0] ch 1-3 decay rate and am enable .db $61,$00 ; [0] .db $62,$00 ; [0] @@ -674,7 +731,8 @@ s9: .db $6c,$00 ; [0] .db $6d,$00 ; [0] .db $6e,$00 ; [0] -s10: + + .db part1, 24/2 .db $60,$00 ; [1] ch 4-6 decay rate and am enable .db $61,$00 ; [1] .db $62,$00 ; [1] @@ -687,7 +745,8 @@ s10: .db $6c,$00 ; [1] .db $6d,$00 ; [1] .db $6e,$00 ; [1] -s11: + + .db part0, 24/2 .db $70,$00 ; [0] ch 1-3 sustain rate .db $71,$00 ; [0] .db $72,$00 ; [0] @@ -700,7 +759,8 @@ s11: .db $7c,$00 ; [0] .db $7d,$00 ; [0] .db $7e,$00 ; [0] -s12: + + .db part1, 24/2 .db $70,$00 ; [1] ch 4-6 sustain rate .db $71,$00 ; [1] .db $72,$00 ; [1] @@ -713,7 +773,8 @@ s12: .db $7c,$00 ; [1] .db $7d,$00 ; [1] .db $7e,$00 ; [1] -s13: + + .db part0, 24/2 .db $80,$00 ; [0] ch 1-3 release rate and sustain level .db $81,$00 ; [0] .db $82,$00 ; [0] @@ -726,7 +787,8 @@ s13: .db $8c,$00 ; [0] .db $8d,$00 ; [0] .db $8e,$00 ; [0] -s14: + + .db part1, 24/2 .db $80,$00 ; [1] ch 4-6 release rate and sustain level .db $81,$00 ; [1] .db $82,$00 ; [1] @@ -739,7 +801,8 @@ s14: .db $8c,$00 ; [1] .db $8d,$00 ; [1] .db $8e,$00 ; [1] -s15: + + .db part0, 24/2 .db $90,$00 ; [0] ch 1-3 ssg-eg .db $91,$00 ; [0] .db $92,$00 ; [0] @@ -752,7 +815,8 @@ s15: .db $9c,$00 ; [0] .db $9d,$00 ; [0] .db $9e,$00 ; [0] -s16: + + .db part1, 24/2 .db $90,$00 ; [1] ch 4-6 ssg-eg .db $91,$00 ; [1] .db $92,$00 ; [1] @@ -765,7 +829,8 @@ s16: .db $9c,$00 ; [1] .db $9d,$00 ; [1] .db $9e,$00 ; [1] -s17: + + .db part0, 12/2 .db $a0,$00 ; [0] ch 1-3 frequency .db $a1,$00 ; [0] .db $a2,$00 ; [0] @@ -778,7 +843,8 @@ s17: ; .db $ac,$00 ; [0] ; .db $ad,$00 ; [0] ; .db $ae,$00 ; [0] -s18: + + .db part1, 12/2 .db $a0,$00 ; [1] ch 4-6 frequency .db $a1,$00 ; [1] .db $a2,$00 ; [1] @@ -791,15 +857,16 @@ s18: ; .db $ac,$00 ; [1] ; .db $ad,$00 ; [1] ; .db $ae,$00 ; [1] -s19: + + .db part0, 6/2 .db $b0,$00 ; [0] ch 1-3 algorith + feedback .db $b1,$00 ; [0] .db $b2,$00 ; [0] -s20: + + .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 -s21: #ENDIF