diff --git a/Source/Apps/VGM/VGMPLAY.ASM b/Source/Apps/VGM/VGMPLAY.ASM index 9c7b747d..e7ed560a 100644 --- a/Source/Apps/VGM/VGMPLAY.ASM +++ b/Source/Apps/VGM/VGMPLAY.ASM @@ -1,4 +1,6 @@ +;------------------------------------------------------------------------------ ; SN76489 + AY-3-8910 + YM2162 VGM player for CP/M +;------------------------------------------------------------------------------ ; ; Based on VGM player by J.B. Langston ; https://github.com/jblang/SN76489 @@ -8,10 +10,16 @@ ; YM2162/YM3484, GD3 support, VGM Chip identification, ; default file type, basic file size checking added by Phil Summers ; -; Compile with: +; Bugs: YM2612 Mute not working. +; +; Assemble with: ; ; TASM -80 -b VGMPLAY.ASM VGMPLAY.COM - +; +;------------------------------------------------------------------------------ +; Device and system specific definitions +;------------------------------------------------------------------------------ +; P8X180 .EQU 0 ; System configuration RC2014 .EQU 0 SBCECB .EQU 1 @@ -63,10 +71,26 @@ RTCIO .EQU 070H #DEFCONT \ nop #DEFCONT \ ld a,val #DEFCONT \ out (YMDAT),a +#DEFCONT \ nop +#DEFCONT \ nop + +#DEFINE setreg2(reg,val) \ +#DEFCONT \ ld a,reg +#DEFCONT \ out (YM2SEL),a +#DEFCONT \ nop +#DEFCONT \ nop +#DEFCONT \ ld a,val +#DEFCONT \ out (YM2DAT),a +#DEFCONT \ nop +#DEFCONT \ nop D50 .EQU 500 ; 900 ;735 D60 .EQU 600 ; 1000 ;882 +;------------------------------------------------------------------------------ +; VGM Codes +;------------------------------------------------------------------------------ + VGM_GG_W .EQU 04FH ; GAME GEAR PSG STEREO. WRITE DD TO PORT 0X06 VGM_PSG_W .EQU 050H ; PSG (SN76489/SN76496) WRITE VALUE DD VGM_YM2612_W .EQU 052H ; YM2612 WRITE VALUE DD @@ -75,6 +99,10 @@ VGM_W735 .EQU 062H ; WAIT 735 SAMPLES (1/60TH SECOND) VGM_W882 .EQU 063H ; WAIT 882 SAMPLES (1/50TH SECOND) VGM_ESD .EQU 066H ; END OF SOUND DATA +;------------------------------------------------------------------------------ +; Generic CP/M definitions +;------------------------------------------------------------------------------ + BOOT .EQU 0000H ; boot location BDOS .EQU 0005H ; bdos entry point FCB .EQU 005CH ; file control block @@ -89,7 +117,10 @@ READF .EQU 20 ; BDOS sequential read function CR .EQU 0DH ; carriage return LF .EQU 0AH ; line feed -EOS .EQU '$' ; end of string marker + +;------------------------------------------------------------------------------ +; Program Start +;------------------------------------------------------------------------------ .ORG 100H @@ -99,9 +130,64 @@ EOS .EQU '$' ; end of string marker LD DE,MSG_WELC ; Welcome Message CALL PRTSTR - LD A,(FCB+1) ; Get first char of filename + CALL READVGM ; Read in the VGM file + + CALL VGMINFO ; Check and display VGM Information + + LD HL, (VGMDATA + 34H) ; Determine start of VGM + LD A, H ; data. + OR L + JR NZ, _S1 + LD HL, 000CH ; Default location (40H - 34H) +_S1 LD DE, VGMDATA + 34H + ADD HL, DE + LD (VGMPOS), HL + + LD HL,D60 ; VGM delay (60hz) + LD (VGMDLY), HL + +MAINLOOP CALL PLAY ; Play one frame + + LD C,6 ; Check for keypress + LD E,0FFH + CALL BDOS + OR A + JR NZ,EXIT + + LD HL,(VGMDLY) ; Frame delay +L1 LD B,FRAME_DLY + DJNZ $ + DEC HL + LD A,H + OR L + JR NZ,L1 + + JR MAINLOOP +; +;------------------------------------------------------------------------------ +; Program Exit +;------------------------------------------------------------------------------ +; +EXIT +#IFDEF SBCV2004 + CALL FASTIO +#ENDIF + CALL VGMDEVICES ; Display devices used + CALL VGMMUTE ; Mute Devices + + LD DE,MSG_EXIT +EXIT_ERR: CALL PRTSTR ; Generic message or error + LD SP, (OLDSTACK) ; Exit to CP/M + RST 00H +; +;------------------------------------------------------------------------------ +; Read VGM file into memory +;------------------------------------------------------------------------------ +; +READVGM: LD A,(FCB+1) ; Get first char of filename CP ' ' ; Compare to blank - JP Z,ERR ; If so, missing filename + LD DE,MSG_NOFILE ; If blank, missing filename + JP Z,EXIT_ERR ; so exit LD A,(FCB+9) ; If the filetype CP ' ' ; is blanks JR NZ,HASEXT ; then assume @@ -116,7 +202,8 @@ HASEXT: LD C,OPENF ; Open File LD DE,FCB CALL BDOS INC A - JP Z,ERR + LD DE,MSG_NOFILE + JP Z,EXIT_ERR XOR A ; Read VGM file into memory LD (FCBCR), A @@ -144,8 +231,13 @@ RLOOP RDONE LD C, CLOSEF ; Close the file LD DE, FCB CALL BDOS - - LD DE,MSG_BADF ; Check valid file + RET +; +;------------------------------------------------------------------------------ +; Display VGM information. +;------------------------------------------------------------------------------ +; +VGMINFO: LD DE,MSG_BADF ; Check valid file LD HL,VGMDATA LD A,(HL) CP 'V' @@ -229,144 +321,8 @@ GD3_NXT2: LD A,(HL) ; Print English Title JR GD3_NXT2 GD3_NXT3: CALL CRLF - -SKIP_GD3: LD HL, (VGMDATA + 34H) ; Determine start of VGM - LD A, H ; data. - OR L - JR NZ, _S1 - LD HL, 000CH ; Default location (40H - 34H) -_S1 LD DE, VGMDATA + 34H - ADD HL, DE - LD (VGMPOS), HL - - LD HL,D60 ; VGM delay (60hz) - LD (VGMDLY), HL - -MAINLOOP CALL PLAY ; Play one frame - - LD C,6 ; Check for keypress - LD E,0FFH - CALL BDOS - OR A - JR NZ,EXIT - - LD HL,(VGMDLY) ; Frame delay -L1 LD B,FRAME_DLY - DJNZ $ - DEC HL - LD A,H - OR L - JR NZ,L1 - - JR MAINLOOP - -EXIT -#IFDEF SBCV2004 - CALL FASTIO -#ENDIF - - LD DE,MSG_PO - CALL PRTSTR - - LD A,(IX+0) - PUSH AF - AND %00000011 - srl a - ADC A,'0' - CP '0' - JR Z,NOSN - CALL PRTCHR - LD DE,MSG_SN - CALL PRTSTR - -NOSN: POP AF - srl a - srl a - PUSH AF - - AND %00000011 - srl a - ADC A,'0' - CP '0' - JR Z,NOAY - CALL PRTCHR - LD DE,MSG_AY - CALL PRTSTR - -NOAY: POP AF - srl a - srl a - PUSH AF - - AND %00000011 - srl a - ADC A,'0' - CP '0' - JR Z,NOYM - CALL PRTCHR - LD DE,MSG_YM - CALL PRTSTR - -NOYM: LD A, 9FH ; Mute all channels on psg - OUT (PSGREG), A - OUT (PSG2REG), A - LD A, 0BFH - OUT (PSGREG), A - OUT (PSG2REG), A - LD A, 0DFH - OUT (PSGREG), A - OUT (PSG2REG), A - LD A, 0FFH - OUT (PSGREG), A - OUT (PSG2REG), A - - LD A, 8 ; Mute all channels on ay - OUT (RSEL), A - OUT (RSEL2), A - XOR A - OUT (RDAT), A - OUT (RDAT2), A - LD A, 9 - OUT (RSEL), A - OUT (RSEL2), A - XOR A - OUT (RDAT), A - OUT (RDAT2), A - LD A, 10 - OUT (RSEL), A - OUT (RSEL2), A - XOR A - OUT (RDAT), A - OUT (RDAT2), A - CALL FASTIO - - setreg($22,$00) ; lfo off - setreg($27,$00) ; note off ch 0 - setreg($28,$01) ; note off ch 1 - setreg($28,$02) ; note off ch 2 - setreg($28,$03) ; note off ch 3 - setreg($28,$04) ; note off ch 4 - setreg($28,$05) ; note off ch 5 - setreg($28,$06) ; note off ch 6 - setreg($28,$01) ; note off ch 1 - setreg($2b,$00) ; dac off - setreg($28,$00) ; key off - - LD DE,MSG_EXIT -EXIT_ERR: CALL PRTSTR - - LD SP, (OLDSTACK) - RST 00H - -ERR LD C, PRINTF - LD DE, NOFILE - CALL BDOS - RST 00H - -NOFILE .DB "File not found", CR, LF, EOS -MSG_MEM .DB "File to big", CR, LF, EOS -MSG_EXIT .DB "FINISHED.",CR,LF,0 - +SKIP_GD3: RET +; ;------------------------------------------------------------------------------ ; VGM Player. ;------------------------------------------------------------------------------ @@ -374,7 +330,7 @@ PLAY #IFDEF SBCV2004 CALL SLOWIO #ENDIF - LD IX,DEV_FLAG + LD IX,VGM_DEV LD HL, (VGMPOS) ; Start processing VGM commands NEXT LD A, (HL) INC HL @@ -392,6 +348,8 @@ NEXT LD A, (HL) NEXT1 CP VGM_GG_W ; Game Gear SN76489 stereo. Ignored JR NZ, PSG + LD IX,VGM_DEV + SET 6,(IX+0) INC HL JR NEXT @@ -400,7 +358,7 @@ PSG CP VGM_PSG_W ; Write byte to SN76489. LD A, (HL) INC HL OUT (PSGREG), A - LD IX,DEV_FLAG + LD IX,VGM_DEV SET 0,(IX+0) JR NEXT @@ -409,7 +367,7 @@ PSG2 CP 30H ; Write byte to second SN76489. LD A, (HL) INC HL OUT (PSG2REG), A - LD IX,DEV_FLAG + LD IX,VGM_DEV SET 1,(IX+0) JR NEXT @@ -426,14 +384,14 @@ AY CP 0A0H LD A, (HL) INC HL OUT (RDAT2), A - LD IX,DEV_FLAG + LD IX,VGM_DEV SET 2,(IX+0) JR NEXT AY1 OUT (RSEL), A LD A, (HL) INC HL OUT (RDAT), A - LD IX,DEV_FLAG + LD IX,VGM_DEV SET 3,(IX+0) JR NEXT @@ -441,19 +399,18 @@ AY1 OUT (RSEL), A YM: CP 052H JR NZ, YM2 - LD A,(HL) OUT (YMSEL),A INC HL LD A,(HL) OUT (YMDAT),A INC HL - LD IX,DEV_FLAG + LD IX,VGM_DEV SET 4,(IX+0) JP NEXT - +; YM2: CP 053H - JR NZ, PCM + JR NZ,WAITNN LD A,(HL) OUT (YM2SEL),A @@ -461,12 +418,11 @@ YM2: CP 053H LD A,(HL) OUT (YM2DAT),A INC HL - LD IX,DEV_FLAG + LD IX,VGM_DEV SET 4,(IX+0) JP NEXT - -PCM: -WAITNN CP 61H ; Wait nn samples +; +WAITNN: CP 61H ; Wait nn samples JR NZ, WAIT60 LD A, (HL) INC HL @@ -477,21 +433,21 @@ WAITNN CP 61H ; Wait nn samples LD H, D LD (VGMDLY), HL RET - +; WAIT60 CP VGM_W735 ; Wait 735 samples (60Hz) JR NZ, WAIT50 LD (VGMPOS), HL LD HL, D50 LD (VGMDLY), HL RET - +; WAIT50 CP VGM_W882 ; Wait 882 samples (50Hz) JR NZ, WAIT1 LD (VGMPOS), HL LD HL, D60 LD (VGMDLY), HL RET - +; WAIT1 CP 70H ; WAIT 0-15 SAMPLES JR C, UNK ; CODES 70-7FH CP 80H @@ -501,11 +457,130 @@ WAIT1 CP 70H ; WAIT 0-15 SAMPLES LD H, 0 LD (VGMDLY), HL RET - -UNK: CALL PRTDOT - CALL PRTHEX +; +UNK: LD IX,VGM_DEV ; Set flag for + SET 6,(IX+0) ; unknown device + INC HL ; Try and skip JP NEXT +; +;------------------------------------------------------------------------------ +; Display VGM Devices detected during playback. +;------------------------------------------------------------------------------ +; +VGMDEVICES: LD DE,MSG_PO ; Played on ... + CALL PRTSTR +; + LD A,(IX+0) + PUSH AF +; + LD DE,MSG_SN ; SN76489 Devices + CALL CHKDEV +; + POP AF + SRL A + SRL A + PUSH AF +; + LD DE,MSG_AY ; AY-3-8910 Devices + CALL CHKDEV +; + POP AF + SRL A + SRL A + PUSH AF +; + LD DE,MSG_YM ; YM-2612 Devices + CALL CHKDEV +; + POP AF + SRL A + SRL A +; PUSH AF +; + LD DE,MSG_UNK ; Unknown Device Code detected +; CALL CHKDEV +; +CHKDEV: AND %00000011 ; Display + SRL A ; number of + ADC A,'0' ; devices + CP '0' + RET Z ; Skip if not + CALL PRTCHR ; used. + CALL PRTSTR + RET +; +;------------------------------------------------------------------------------ +; Mute Devices. +;------------------------------------------------------------------------------ +; +VGMMUTE: LD A,(IX+0) ; Only mute devices used. + AND %00000011 + JR Z,SKIP1 + LD A, 9FH ; Mute all channels on psg + OUT (PSGREG), A + OUT (PSG2REG), A + LD A, 0BFH + OUT (PSGREG), A + OUT (PSG2REG), A + LD A, 0DFH + OUT (PSGREG), A + OUT (PSG2REG), A + LD A, 0FFH + OUT (PSGREG), A + OUT (PSG2REG), A + +SKIP1: LD A,(IX+0) + AND %00001100 + JR Z,SKIP2 + + LD A, 8 ; Mute all channels on ay + OUT (RSEL), A + OUT (RSEL2), A + XOR A + OUT (RDAT), A + OUT (RDAT2), A + LD A, 9 + OUT (RSEL), A + OUT (RSEL2), A + XOR A + OUT (RDAT), A + OUT (RDAT2), A + LD A, 10 + OUT (RSEL), A + OUT (RSEL2), A + XOR A + OUT (RDAT), A + OUT (RDAT2), A + CALL FASTIO + +SKIP2: LD A,(IX+0) + AND %00110000 + JP Z,SKIP3 + + setreg($22,$00) ; lfo off + setreg($27,$00) ; Disable independant Channel 3 + setreg($28,$00) ; note off ch 1 + setreg($28,$01) ; note off ch 2 + setreg($28,$02) ; note off ch 3 + setreg($28,$04) ; note off ch 4 + setreg($28,$05) ; note off ch 5 + setreg($28,$06) ; note off ch 6 + setreg($2b,$00) ; dac off + + setreg($b4,$00) ; sound off ch 1-3 + setreg($b5,$00) + setreg($b6,$00) + setreg2($b4,$00) ; sound off ch 4-6 + setreg2($b5,$00) + setreg2($b6,$00) + +SKIP3: RET +; +;------------------------------------------------------------------------------ +; Hardware specific routines. +;------------------------------------------------------------------------------ +; SLOWIO: #IFDEF SBCV2004 PUSH AF @@ -515,7 +590,7 @@ SLOWIO: POP AF #ENDIF RET - +; FASTIO: #IFDEF SBCV2004 LD A,(HB_RTCVAL) @@ -523,9 +598,17 @@ FASTIO: OUT (RTCIO),A ; NORMAL CLOCK SPEED #ENDIF RET - +; +;------------------------------------------------------------------------------ +; External routines. +;------------------------------------------------------------------------------ +; #INCLUDE "printing.inc" - +; +;------------------------------------------------------------------------------ +; Strings and constants. +;------------------------------------------------------------------------------ +; MSG_WELC: .DB "VGM Player for RomWBW v0.2, 27-Nov-2021",CR,LF ; .DB "J.B. Langston/Marco Maccaferri/Phil Summers",CR,LF .DB 0 @@ -534,15 +617,20 @@ MSG_PO .DB "Played on : ",0 MSG_YM: .DB "xYM-2612 ",0 MSG_SN: .DB "xSN76489 ",0 MSG_AY: .DB "xAY-3-8910 ",0 - +MSG_UNK .DB "xUnsupported device encountered", CR, LF, 0 +MSG_EXIT: .DB "FINISHED.",CR,LF,0 +MSG_NOFILE: .DB "File not found", CR, LF, 0 +MSG_MEM: .DB "File to big", CR, LF, 0 +; ;------------------------------------------------------------------------------ ; Variables ;------------------------------------------------------------------------------ - +; VGMPOS .DW 0 VGMDLY .DW 0 +VGMUNK_F .DB 0 ; Flag for unknown device +VGM_DEV .DB %00000000 ; UUYYAASS -DEV_FLAG .DB %00000000 ; 000YAASS OLDSTACK .DW 0 ; original stack pointer .DS 40H ; space for stack STACK ; top of stack @@ -552,5 +640,4 @@ STACK ; top of stack ;------------------------------------------------------------------------------ VGMDATA - .END