Last active
October 4, 2024 22:45
-
-
Save applecuckoo/b6472465a8fb84b3e7488448a4a217e3 to your computer and use it in GitHub Desktop.
A draft ImHex pattern for the VGM chiptune file format
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma author applecuckoo | |
#pragma description VGM chiptune files (WIP) | |
#pragma endian little | |
#pragma MIME audio/x-vgm | |
import type.magic; | |
import type.byte; | |
import std.core; | |
import std.string; | |
import std.ptr; | |
import std.fxpt; | |
import std.io; | |
import std.math; | |
struct PackedBCD<auto Digits> { | |
type::Nibbles bytes[Digits]; | |
} [[/*sealed,*/ format("format_packed_bcd")]]; | |
fn format_packed_bcd(auto bcd) { | |
str result; | |
for (u32 i = 3, i < sizeof(bcd.bytes), i -= 1) { | |
u8 highbyte = bcd.bytes[i].high; | |
if (highbyte >= 10) | |
return "Invalid"; | |
result += std::format("{}", highbyte); | |
u8 lowbyte = bcd.bytes[i].low; | |
if (lowbyte >= 10) | |
return "Invalid"; | |
result += std::format("{}", lowbyte); | |
} | |
std::fxpt::fixed result_fmt; | |
result_fmt = std::string::parse_int(result, 10); | |
return result_fmt; | |
}; | |
bitfield SN76489Flags { | |
frequency : 1; | |
negateOutput : 1; | |
GameGearStereo : 1; | |
clockDiv : 1; | |
XNORNoiseMode : 1; | |
padding : 3; | |
}; | |
bitfield AY8910Flags { | |
legacyOutput : 1; | |
singleOutput : 1; | |
discreteOutput : 1; | |
RAWOutput : 1; | |
YMclockDivLow : 1; | |
padding : 3; | |
}; | |
bitfield OKIM6258Flags { | |
clockDiv : 2; | |
ADPCMsel : 1; | |
outputBitDepth : 1; | |
padding : 4; | |
}; | |
bitfield K054539Flags { | |
reverseStereo : 1; | |
disableReverb : 1; | |
KeyOnUpdate : 1; | |
padding : 5; | |
}; | |
enum AY8190Type : u8 { | |
AY8910, | |
AY8912, | |
AY8913, | |
AY8914, | |
YM2149 = 0x10, | |
YM3439, | |
YMZ284, | |
YMZ294, | |
}; | |
enum C140Type : u8 { | |
C140_NamcoSystem2, | |
C140_NamcoSystem21, | |
ASIC219_NamcoNA, | |
}; | |
struct Gd3 { | |
type::Magic<"Gd3 "> ident; | |
u8 version[4]; | |
u32 Gd3Length; | |
std::string::NullString16 trackNameEng; | |
std::string::NullString16 trackNameOriginal; | |
std::string::NullString16 gameNameEng; | |
std::string::NullString16 gameNameOriginal; | |
std::string::NullString16 sysNameEng; | |
std::string::NullString16 sysNameOriginal; | |
std::string::NullString16 trackAuthorEnglish; | |
std::string::NullString16 trackAuthorOriginal; | |
std::string::NullString16 gameReleaseDate; | |
std::string::NullString16 VGMConverter; | |
std::string::NullString16 Notes; | |
}; | |
struct Header { | |
type::Magic<"Vgm "> ident; | |
u32 eofOffset; | |
PackedBCD<4> version; // TODO: decode this 'properly'? this is 4-bit BCD | |
u32 SN76489_clk; // TODO: bit 31 and the dual chip bit indicates if a T6W28 is in play | |
u32 YM2413_clk; | |
Gd3 *Gd3Offset : u32 [[pointer_base("std::ptr::relative_to_parent")]]; | |
u32 sampleCount; | |
u32 loopOffset; | |
u32 loopSamples; | |
// VGM 1.01 onwards | |
u32 rate; | |
// VGM 1.10 onwards | |
u16 SN76489_feedback; | |
u8 SN76489_shift_width; | |
// VGM 1.51 onwards | |
SN76489Flags snflags; | |
// VGM 1.10 onwards | |
u32 YM2612_clk; | |
u32 YM2151_clk; | |
// VGM 1.50 onwards | |
u32 VGMOffset; | |
// VGM 1.51 onwards | |
u32 SegaPCM_clk; | |
u32 SegaPCM_reg; | |
u32 RF5C68_clk; | |
u32 YM2203_clk; | |
u32 YM2608_clk; | |
u32 YM2610_clk; // TODO: bit 31 indicates if this is a YM2610B or not | |
u32 YM3812_clk; | |
u32 YM3526_clk; | |
u32 Y8950_clk; | |
u32 YMF262_clk; | |
u32 YMF278B_clk; | |
u32 YMF271_clk; | |
u32 YMZ280B_clk; | |
u32 RF5C164_clk; | |
u32 PWM_clk; | |
u32 AY8910_clk; | |
AY8190Type AY8910_type; | |
AY8910Flags AY8910_flags; | |
u8 YM2203_flags; | |
u8 YM2608_flags; | |
// VGM 1.60 onwards | |
u8 volumeMod; | |
padding[1]; | |
u8 loopBase; | |
// VGM 1.51 onwards | |
u8 loopMod; | |
// VGM 1.61 onwards | |
u32 DMG_clk; | |
u32 APU_clk; // TODO: bit 31 enables the FDS sound addon | |
u32 MultiPCM_clk; | |
u32 uPD7759_clk; | |
u32 OKIM6258_clk; | |
OKIM6258Flags OKIM6258_flags; | |
K054539Flags K054539_flags; | |
C140Type C140_type; | |
padding[1]; | |
u32 OKIM6295_clk; | |
u32 K051649_clk; | |
u32 K054539_clk; | |
u32 HuC6280_clk; | |
u32 C140_clk; | |
u32 K053260_clk; | |
u32 Pokey_clk; | |
u32 QSound_clk; | |
// VGM 1.71 onwards | |
u32 SCSP_clk; | |
// VGM 1.70 onwards | |
u32 extraHeaderOffset; | |
// VGM 1.71 onwards | |
u32 WonderSwan_clk; | |
u32 VSU_clk; | |
u32 SAA1099_clk; | |
u32 ES5503_clk; | |
u32 ES5005_clk; | |
u8 ES5503_ch; | |
u8 ES5505_ch; // TODO: bit 31 indicates if this chip is an ES5505 or a ES5506 | |
u8 C352_clockDiv; | |
u32 X1_010_clk; | |
u32 C352_clk; | |
u32 GA20_clk; | |
// VGM 1.72 onwards | |
u32 Mikey_clk; | |
}; | |
struct VGM { | |
Header header; | |
}; | |
VGM vgm @ 0x00; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment