mirror of https://github.com/wwarthen/RomWBW.git
Browse Source
This utility scans .VGM files in the current directory and displays which sound chips they use. Useful for determining VGM compatibility with RomWBW's VGM player. Features: - Scans all .VGM files in current directory - Detects SN76489, YM2612, YM2151, and AY-3-8910 chips - Displays results in a formatted table - Supports dual-chip configurations Could you please integrate this into the RomWBW build process alongside the existing VGM player utilities?pull/635/head
1 changed files with 539 additions and 0 deletions
@ -0,0 +1,539 @@ |
|||||
|
;------------------------------------------------------------------------------ |
||||
|
; VGM File Info Display for CP/M |
||||
|
;------------------------------------------------------------------------------ |
||||
|
; |
||||
|
; Scans all .VGM files in current directory and displays chip information |
||||
|
; in a formatted table |
||||
|
; |
||||
|
; (c) 2025 Joao Miguel Duraes |
||||
|
; Licensed under the MIT License |
||||
|
; |
||||
|
; Version: 1.0 - 06-Dec-2025 |
||||
|
; |
||||
|
; Assemble with: |
||||
|
; TASM -80 -b vgminfo.asm vgminfo.com |
||||
|
; |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; CP/M definitions |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
BOOT .equ 0000H ; boot location |
||||
|
BDOS .equ 0005H ; bdos entry point |
||||
|
FCB .equ 005CH ; file control block |
||||
|
FCBCR .equ FCB + 20H ; fcb current record |
||||
|
BUFF .equ 0080H ; DMA buffer |
||||
|
|
||||
|
PRINTF .equ 9 ; BDOS print string function |
||||
|
OPENF .equ 15 ; BDOS open file function |
||||
|
CLOSEF .equ 16 ; BDOS close file function |
||||
|
READF .equ 20 ; BDOS sequential read function |
||||
|
SETDMA .equ 26 ; BDOS set DMA address |
||||
|
SFIRST .equ 17 ; BDOS search first |
||||
|
SNEXT .equ 18 ; BDOS search next |
||||
|
|
||||
|
CR .equ 0DH ; carriage return |
||||
|
LF .equ 0AH ; line feed |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; VGM Header offsets |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
VGM_IDENT .equ 00H ; "Vgm " identifier |
||||
|
VGM_VERSION .equ 08H ; Version |
||||
|
VGM_DATAOFF .equ 34H ; VGM data offset (relative to 0x34) |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; VGM Command codes (subset) |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
VGM_PSG1_W .equ 050H ; PSG (SN76489) write |
||||
|
VGM_PSG2_W .equ 030H ; PSG #2 write |
||||
|
VGM_YM26121_W .equ 052H ; YM2612 port 0 write |
||||
|
VGM_YM26122_W .equ 053H ; YM2612 port 1 write |
||||
|
VGM_YM26123_W .equ 0A2H ; YM2612 #2 port 0 write |
||||
|
VGM_YM26124_W .equ 0A3H ; YM2612 #2 port 1 write |
||||
|
VGM_YM21511_W .equ 054H ; YM2151 write |
||||
|
VGM_YM21512_W .equ 0A4H ; YM2151 #2 write |
||||
|
VGM_AY_W .equ 0A0H ; AY-3-8910 write |
||||
|
VGM_ESD .equ 066H ; End of sound data |
||||
|
VGM_WNS .equ 061H ; Wait n samples |
||||
|
VGM_W735 .equ 062H ; Wait 735 samples |
||||
|
VGM_W882 .equ 063H ; Wait 882 samples |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; Program Start |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
.ORG 100H |
||||
|
|
||||
|
START: LD SP, STACK ; Setup stack |
||||
|
|
||||
|
; Display header |
||||
|
LD DE, MSG_HEADER |
||||
|
CALL PRTSTR |
||||
|
LD DE, MSG_DIVIDER |
||||
|
CALL PRTSTR |
||||
|
|
||||
|
; Setup search for *.VGM files |
||||
|
LD DE, SEARCH_FCB |
||||
|
LD C, SFIRST |
||||
|
CALL BDOS |
||||
|
CP 0FFH ; No files found? |
||||
|
JP Z, NO_FILES |
||||
|
|
||||
|
FILE_LOOP: |
||||
|
; A contains directory entry index (0-3) |
||||
|
; Each entry is 32 bytes, so multiply by 32 |
||||
|
AND 03H ; Mask to 0-3 |
||||
|
RLCA |
||||
|
RLCA |
||||
|
RLCA |
||||
|
RLCA |
||||
|
RLCA ; Multiply by 32 |
||||
|
LD L, A |
||||
|
LD H, 0 |
||||
|
LD DE, BUFF |
||||
|
ADD HL, DE ; HL now points to directory entry |
||||
|
|
||||
|
; Copy filename from directory entry to our FCB |
||||
|
INC HL ; Skip user number |
||||
|
LD DE, FILE_FCB+1 ; Destination |
||||
|
LD BC, 11 ; 8+3 filename |
||||
|
LDIR |
||||
|
|
||||
|
; Open and process this file |
||||
|
CALL PROCESS_FILE |
||||
|
|
||||
|
; Search for next file |
||||
|
LD DE, SEARCH_FCB |
||||
|
LD C, SNEXT |
||||
|
CALL BDOS |
||||
|
CP 0FFH |
||||
|
JP NZ, FILE_LOOP |
||||
|
|
||||
|
; Done |
||||
|
LD DE, MSG_DIVIDER |
||||
|
CALL PRTSTR |
||||
|
JP BOOT ; Exit to CP/M |
||||
|
|
||||
|
NO_FILES: LD DE, MSG_NOFILES |
||||
|
CALL PRTSTR |
||||
|
JP BOOT |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; Process a VGM file - read header and display info |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
PROCESS_FILE: |
||||
|
; Reset FCB |
||||
|
XOR A |
||||
|
LD (FILE_FCB), A ; Default drive |
||||
|
LD (FILE_FCB+12), A ; Clear extent |
||||
|
LD (FILE_FCB+32), A ; Clear current record |
||||
|
|
||||
|
; Open file |
||||
|
LD DE, FILE_FCB |
||||
|
LD C, OPENF |
||||
|
CALL BDOS |
||||
|
CP 0FFH |
||||
|
RET Z ; Can't open, skip |
||||
|
|
||||
|
; Set DMA to our buffer for first block |
||||
|
LD DE, VGMBUF |
||||
|
LD C, SETDMA |
||||
|
CALL BDOS |
||||
|
|
||||
|
; Read first 128 bytes (header) |
||||
|
LD DE, FILE_FCB |
||||
|
LD C, READF |
||||
|
CALL BDOS |
||||
|
OR A |
||||
|
JR NZ, READ_DONE ; EOF or error |
||||
|
|
||||
|
; Read second 128 bytes (to allow scanning right after header) |
||||
|
LD DE, VGMBUF+128 |
||||
|
LD C, SETDMA |
||||
|
CALL BDOS |
||||
|
LD DE, FILE_FCB |
||||
|
LD C, READF |
||||
|
CALL BDOS |
||||
|
|
||||
|
; Read third 128 bytes |
||||
|
LD DE, VGMBUF+256 |
||||
|
LD C, SETDMA |
||||
|
CALL BDOS |
||||
|
LD DE, FILE_FCB |
||||
|
LD C, READF |
||||
|
CALL BDOS |
||||
|
|
||||
|
; Read fourth 128 bytes |
||||
|
LD DE, VGMBUF+384 |
||||
|
LD C, SETDMA |
||||
|
CALL BDOS |
||||
|
LD DE, FILE_FCB |
||||
|
LD C, READF |
||||
|
CALL BDOS |
||||
|
|
||||
|
READ_DONE: |
||||
|
|
||||
|
; Restore DMA |
||||
|
LD DE, BUFF |
||||
|
LD C, SETDMA |
||||
|
CALL BDOS |
||||
|
|
||||
|
; Close file |
||||
|
LD DE, FILE_FCB |
||||
|
LD C, CLOSEF |
||||
|
CALL BDOS |
||||
|
|
||||
|
; Check if valid VGM |
||||
|
LD HL, VGMBUF |
||||
|
LD A, (HL) |
||||
|
CP 'V' |
||||
|
RET NZ |
||||
|
INC HL |
||||
|
LD A, (HL) |
||||
|
CP 'g' |
||||
|
RET NZ |
||||
|
INC HL |
||||
|
LD A, (HL) |
||||
|
CP 'm' |
||||
|
RET NZ |
||||
|
INC HL |
||||
|
LD A, (HL) |
||||
|
CP ' ' |
||||
|
RET NZ |
||||
|
|
||||
|
; Display filename (exactly 8 chars from FCB) |
||||
|
LD HL, FILE_FCB+1 |
||||
|
LD B, 8 |
||||
|
PRINT_NAME: LD A, (HL) |
||||
|
CALL PRTCHR |
||||
|
INC HL |
||||
|
DJNZ PRINT_NAME |
||||
|
|
||||
|
; Add 2-space gap |
||||
|
LD A, ' ' |
||||
|
CALL PRTCHR |
||||
|
LD A, ' ' |
||||
|
CALL PRTCHR |
||||
|
|
||||
|
|
||||
|
PAD_DONE: |
||||
|
|
||||
|
; Check and display chip info |
||||
|
CALL CHECK_CHIPS |
||||
|
|
||||
|
; New line |
||||
|
CALL CRLF |
||||
|
|
||||
|
RET |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; Check which chips are used by scanning VGM command stream (first ~100 cmds) |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
CHECK_CHIPS: |
||||
|
; Initialize chip flags |
||||
|
XOR A |
||||
|
LD (CHIP_FLAGS), A |
||||
|
|
||||
|
; Compute absolute data start within VGMBUF window |
||||
|
LD HL, (VGMBUF+VGM_DATAOFF) |
||||
|
LD A, H |
||||
|
OR L |
||||
|
JR NZ, GOT_OFFSET |
||||
|
LD HL, 000CH ; Default for VGM < 1.50 (0x40-0x34) |
||||
|
GOT_OFFSET: LD DE, VGMBUF+VGM_DATAOFF |
||||
|
ADD HL, DE ; HL = VGMBUF + 0x34 + offset |
||||
|
|
||||
|
; Constrain to our 256-byte buffer |
||||
|
LD DE, VGMBUF |
||||
|
SBC HL, DE ; HL = offset from VGMBUF base |
||||
|
ADD HL, DE ; restore HL absolute inside VGMBUF |
||||
|
|
||||
|
; Scan up to 100 commands or until EOD |
||||
|
LD C, 100 |
||||
|
SCAN_LOOP: LD A, (HL) |
||||
|
INC HL |
||||
|
|
||||
|
CP VGM_ESD |
||||
|
JP Z, SCAN_DONE |
||||
|
|
||||
|
CP VGM_PSG1_W |
||||
|
JP NZ, CHK_PSG2 |
||||
|
LD A, (CHIP_FLAGS) |
||||
|
OR 01H ; bit 0 = SN #1 |
||||
|
LD (CHIP_FLAGS), A |
||||
|
INC HL ; Skip data byte |
||||
|
JP SCAN_NEXT |
||||
|
|
||||
|
CHK_PSG2: CP VGM_PSG2_W |
||||
|
JP NZ, CHK_YM2612 |
||||
|
LD A, (CHIP_FLAGS) |
||||
|
OR 02H ; bit 1 = SN #2 |
||||
|
LD (CHIP_FLAGS), A |
||||
|
INC HL |
||||
|
JP SCAN_NEXT |
||||
|
|
||||
|
CHK_YM2612: CP VGM_YM26121_W |
||||
|
JR Z, GOT_YM2612_1 |
||||
|
CP VGM_YM26122_W |
||||
|
JR Z, GOT_YM2612_1 |
||||
|
CP VGM_YM26123_W |
||||
|
JR Z, GOT_YM2612_2 |
||||
|
CP VGM_YM26124_W |
||||
|
JP NZ, CHK_YM2151 |
||||
|
GOT_YM2612_2: LD A, (CHIP_FLAGS) |
||||
|
OR 08H ; bit 3 = YM2612 #2 |
||||
|
LD (CHIP_FLAGS), A |
||||
|
INC HL |
||||
|
INC HL ; Skip 2 data bytes |
||||
|
JP SCAN_NEXT |
||||
|
GOT_YM2612_1: LD A, (CHIP_FLAGS) |
||||
|
OR 04H ; bit 2 = YM2612 #1 |
||||
|
LD (CHIP_FLAGS), A |
||||
|
INC HL |
||||
|
INC HL |
||||
|
JP SCAN_NEXT |
||||
|
|
||||
|
CHK_YM2151: CP VGM_YM21511_W |
||||
|
JR Z, GOT_YM2151_1 |
||||
|
CP VGM_YM21512_W |
||||
|
JP NZ, CHK_AY |
||||
|
LD A, (CHIP_FLAGS) |
||||
|
OR 20H ; bit 5 = YM2151 #2 |
||||
|
LD (CHIP_FLAGS), A |
||||
|
INC HL |
||||
|
INC HL |
||||
|
JP SCAN_NEXT |
||||
|
GOT_YM2151_1: LD A, (CHIP_FLAGS) |
||||
|
OR 10H ; bit 4 = YM2151 #1 |
||||
|
LD (CHIP_FLAGS), A |
||||
|
INC HL |
||||
|
INC HL |
||||
|
JP SCAN_NEXT |
||||
|
|
||||
|
CHK_AY: CP VGM_AY_W |
||||
|
JP NZ, CHK_WAIT |
||||
|
LD A, (HL) ; Get register/chip byte |
||||
|
BIT 7, A ; Bit 7 = chip 2? |
||||
|
JR Z, GOT_AY1 |
||||
|
LD A, (CHIP_FLAGS) |
||||
|
OR 80H ; bit 7 = AY #2 |
||||
|
LD (CHIP_FLAGS), A |
||||
|
INC HL |
||||
|
INC HL |
||||
|
JP SCAN_NEXT |
||||
|
GOT_AY1: LD A, (CHIP_FLAGS) |
||||
|
OR 40H ; bit 6 = AY #1 |
||||
|
LD (CHIP_FLAGS), A |
||||
|
INC HL |
||||
|
INC HL ; Skip 2 data bytes |
||||
|
JP SCAN_NEXT |
||||
|
|
||||
|
CHK_WAIT: CP VGM_WNS |
||||
|
JR NZ, CHK_W735 |
||||
|
INC HL |
||||
|
INC HL ; Skip 2-byte wait value |
||||
|
JP SCAN_NEXT |
||||
|
|
||||
|
CHK_W735: CP VGM_W735 |
||||
|
JR Z, SCAN_NEXT |
||||
|
CP VGM_W882 |
||||
|
JR Z, SCAN_NEXT |
||||
|
|
||||
|
; Unknown command or short wait 0x70-0x7F -> just continue |
||||
|
CP 70H |
||||
|
JR C, SCAN_NEXT |
||||
|
CP 80H |
||||
|
JR NC, SCAN_NEXT |
||||
|
|
||||
|
SCAN_NEXT: DEC C |
||||
|
JP NZ, SCAN_LOOP |
||||
|
|
||||
|
SCAN_DONE: ; Display chips found |
||||
|
LD B, 0 ; Chip counter |
||||
|
LD A, (CHIP_FLAGS) |
||||
|
LD C, A ; Save flags |
||||
|
|
||||
|
; SN76489 |
||||
|
AND 03H ; bits 0-1 |
||||
|
JP Z, NO_SN |
||||
|
LD A, B |
||||
|
OR A |
||||
|
CALL NZ, PRINT_COMMA |
||||
|
LD A, C |
||||
|
AND 03H |
||||
|
CP 03H ; Both chips? |
||||
|
JR Z, SN_DUAL |
||||
|
LD DE, MSG_SN76489 |
||||
|
CALL PRTSTR |
||||
|
JR SN_DONE |
||||
|
SN_DUAL: LD DE, MSG_SN76489X2 |
||||
|
CALL PRTSTR |
||||
|
SN_DONE: INC B |
||||
|
NO_SN: |
||||
|
; YM2612 |
||||
|
LD A, C |
||||
|
AND 0CH ; bits 2-3 |
||||
|
JR Z, NO_YM2612 |
||||
|
LD A, B |
||||
|
OR A |
||||
|
CALL NZ, PRINT_COMMA |
||||
|
LD A, C |
||||
|
AND 0CH |
||||
|
CP 0CH ; Both chips? |
||||
|
JR Z, YM2612_DUAL |
||||
|
LD DE, MSG_YM2612 |
||||
|
CALL PRTSTR |
||||
|
JR YM2612_DONE |
||||
|
YM2612_DUAL: LD DE, MSG_YM2612X2 |
||||
|
CALL PRTSTR |
||||
|
YM2612_DONE: INC B |
||||
|
NO_YM2612: |
||||
|
; YM2151 |
||||
|
LD A, C |
||||
|
AND 30H ; bits 4-5 |
||||
|
JR Z, NO_YM2151 |
||||
|
LD A, B |
||||
|
OR A |
||||
|
CALL NZ, PRINT_COMMA |
||||
|
LD A, C |
||||
|
AND 30H |
||||
|
CP 30H ; Both chips? |
||||
|
JR Z, YM2151_DUAL |
||||
|
LD DE, MSG_YM2151 |
||||
|
CALL PRTSTR |
||||
|
JR YM2151_DONE |
||||
|
YM2151_DUAL: LD DE, MSG_YM2151X2 |
||||
|
CALL PRTSTR |
||||
|
YM2151_DONE: INC B |
||||
|
NO_YM2151: |
||||
|
; AY-3-8910 |
||||
|
LD A, C |
||||
|
AND 0C0H ; bits 6-7 |
||||
|
JR Z, NO_AY |
||||
|
LD A, B |
||||
|
OR A |
||||
|
CALL NZ, PRINT_COMMA |
||||
|
LD A, C |
||||
|
AND 0C0H |
||||
|
CP 0C0H ; Both chips? |
||||
|
JR Z, AY_DUAL |
||||
|
LD DE, MSG_AY8910 |
||||
|
CALL PRTSTR |
||||
|
JR AY_DONE |
||||
|
AY_DUAL: LD DE, MSG_AY8910X2 |
||||
|
CALL PRTSTR |
||||
|
AY_DONE: INC B |
||||
|
NO_AY: |
||||
|
; None |
||||
|
LD A, B |
||||
|
OR A |
||||
|
RET NZ |
||||
|
LD DE, MSG_UNKNOWN |
||||
|
CALL PRTSTR |
||||
|
RET |
||||
|
|
||||
|
PRINT_COMMA: LD A, ',' |
||||
|
CALL PRTCHR |
||||
|
LD A, ' ' |
||||
|
CALL PRTCHR |
||||
|
RET |
||||
|
|
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; Print string pointed to by DE (terminated by 0) |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
PRTSTR: LD A, (DE) |
||||
|
OR A |
||||
|
RET Z |
||||
|
CALL PRTCHR |
||||
|
INC DE |
||||
|
JR PRTSTR |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; Print character in A |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
PRTCHR: PUSH BC |
||||
|
PUSH DE |
||||
|
PUSH HL |
||||
|
LD E, A |
||||
|
LD C, 2 |
||||
|
CALL BDOS |
||||
|
POP HL |
||||
|
POP DE |
||||
|
POP BC |
||||
|
RET |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; Print CR/LF |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
CRLF: LD A, CR |
||||
|
CALL PRTCHR |
||||
|
LD A, LF |
||||
|
CALL PRTCHR |
||||
|
RET |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; Messages |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
MSG_HEADER: .DB CR, LF |
||||
|
.DB "VGM Music Chip Scanner v1.0 - 06-Dec-2025", CR, LF |
||||
|
.DB "(c)2025 Joao Miguel Duraes - MIT License", CR, LF |
||||
|
.DB CR, LF |
||||
|
.DB "Filename Chips Used", CR, LF |
||||
|
.DB 0 |
||||
|
|
||||
|
MSG_DIVIDER: .DB "======== =====================", CR, LF |
||||
|
.DB 0 |
||||
|
|
||||
|
MSG_NOFILES: .DB "No .VGM files found in current directory", CR, LF |
||||
|
.DB 0 |
||||
|
|
||||
|
MSG_SN76489: .DB "SN76489", 0 |
||||
|
MSG_SN76489X2: .DB "2xSN76489", 0 |
||||
|
MSG_YM2612: .DB "YM2612", 0 |
||||
|
MSG_YM2612X2: .DB "2xYM2612", 0 |
||||
|
MSG_YM2151: .DB "YM2151", 0 |
||||
|
MSG_YM2151X2: .DB "2xYM2151", 0 |
||||
|
MSG_AY8910: .DB "AY-3-8910", 0 |
||||
|
MSG_AY8910X2: .DB "2xAY-3-8910", 0 |
||||
|
MSG_UNKNOWN: .DB "Unknown/None", 0 |
||||
|
|
||||
|
;------------------------------------------------------------------------------ |
||||
|
; Data area |
||||
|
;------------------------------------------------------------------------------ |
||||
|
|
||||
|
; Search FCB for *.VGM |
||||
|
SEARCH_FCB: .DB 0 ; Default drive |
||||
|
.DB '?','?','?','?','?','?','?','?' ; Filename (wildcard) |
||||
|
.DB 'V','G','M' ; Extension |
||||
|
.FILL 24, 0 ; Rest of FCB |
||||
|
|
||||
|
; FCB for opening files |
||||
|
FILE_FCB: .DB 0 ; Default drive |
||||
|
.FILL 35, 0 ; Rest of FCB |
||||
|
|
||||
|
DIR_CODE: .DB 0 ; Directory code from search |
||||
|
CHIP_FLAGS: .DB 0 ; Detected chip flags |
||||
|
; bit0 SN76489 #1, bit1 SN76489 #2 |
||||
|
; bit2 YM2612 #1, bit3 YM2612 #2 |
||||
|
; bit4 YM2151 #1, bit5 YM2151 #2 |
||||
|
; bit6 AY #1, bit7 AY #2 |
||||
|
|
||||
|
; Buffer for VGM header + first data sector (256 bytes) |
||||
|
VGMBUF: .FILL 512, 0 |
||||
|
|
||||
|
; Stack space |
||||
|
.FILL 64, 0 |
||||
|
STACK: .DW 0 |
||||
|
|
||||
|
.END |
||||
Loading…
Reference in new issue