From 12bfe77ed32b827ef2bf46260144e896f77bb841 Mon Sep 17 00:00:00 2001 From: Randy Thiemann Date: Mon, 30 Oct 2023 23:30:12 +0100 Subject: [PATCH] Add in-game song... That's going to be fun to cram in! --- src/res/sources/game.fur | Bin 0 -> 1836 bytes src/res/sources/game.vgm | Bin 0 -> 90988 bytes src/res/sources/gameparse.py | 241 +++++++++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 src/res/sources/game.fur create mode 100644 src/res/sources/game.vgm create mode 100644 src/res/sources/gameparse.py diff --git a/src/res/sources/game.fur b/src/res/sources/game.fur new file mode 100644 index 0000000000000000000000000000000000000000..0f18e0bc3ccfb2948c80d144f8dd50868a6e4f5f GIT binary patch literal 1836 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

6aDwfC9gy!21R0{xLn_ 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 literal 0 HcmV?d00001 diff --git a/src/res/sources/gameparse.py b/src/res/sources/gameparse.py new file mode 100644 index 0000000..a43f203 --- /dev/null +++ b/src/res/sources/gameparse.py @@ -0,0 +1,241 @@ +# DMGTRIS +# Copyright (C) 2023 - Randy Thiemann + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from construct import Struct, Const, Int32ul, Int16ul, Int8ul, Bytes + +vgm_header = Struct( + "magic" / Const(b"Vgm "), + "eof_offset" / Int32ul, + "version" / Int32ul, + "sn76489_clock" / Int32ul, + "ym2413_clock" / Int32ul, + "gd3_offset" / Int32ul, + "total_samples" / Int32ul, + "loop_offset" / Int32ul, + "loop_samples" / Int32ul, + "rate" / Int32ul, + "sn_fb" / Int16ul, + "sn_w" / Int8ul, + "sn_c" / Int8ul, + "ym2612_clock" / Int32ul, + "ym2151_clock" / Int32ul, + "vgm_data_offset" / Int32ul, + "seg_pcm_clock" / Int32ul, + "seg_pcm_intf_reg" / Int32ul, + "rf5c68_clock" / Int32ul, + "ym2203_clock" / Int32ul, + "ym2608_clock" / Int32ul, + "ym2610_clock" / Int32ul, + "ym3812_clock" / Int32ul, + "ym3526_clock" / Int32ul, + "y8950_clock" / Int32ul, + "ymf262_clock" / Int32ul, + "ymf278b_clock" / Int32ul, + "ymf271_clock" / Int32ul, + "ymz280b_clock" / Int32ul, + "rf5c164_clock" / Int32ul, + "pwm_clock" / Int32ul, + "ay8910_clock" / Int32ul, + "ay8910_type" / Int8ul, + "ay8910_flags" / Int8ul, + "ym2203_ay8910_flags" / Int8ul, + "ym2608_ay8910_flags" / Int8ul, + "volume_mod" / Int8ul, + "reserved_0" / Bytes(1), + "loop_base" / Int8ul, + "loop_modifier" / Int8ul, + "dmg_clock" / Int32ul, + "nes_apu_clock" / Int32ul, + "multi_pcm_clock" / Int32ul, + "upd7759_clock" / Int32ul, + "okim6258_clock" / Int32ul, + "okim6258_flags" / Int8ul, + "k054539_flags" / Int8ul, + "c140_chip_type" / Int8ul, + "reserved_1" / Bytes(1), + "okim6295_clock" / Int32ul, + "k051649_k052539_clock" / Int32ul, + "k054539_clock" / Int32ul, + "huc6280_clock" / Int32ul, + "c140_clock" / Int32ul, + "k053260_clock" / Int32ul, + "pokey_clock" / Int32ul, + "qsound_clock" / Int32ul, + "scsp_clock" / Int32ul, + "extra_hdr_offset" / Int32ul, + "wonder_swan_clock" / Int32ul, + "vsu_clock" / Int32ul, + "saa1099_clock" / Int32ul, + "es5503_clock" / Int32ul, + "es5505_es5506_clock" / Int32ul, + "es5503_num_channels" / Int8ul, + "es5505_es5506_num_channels" / Int8ul, + "c352_clock_div" / Int8ul, + "reserved_2" / Bytes(1), + "x1_010_clock" / Int32ul, + "c352_clock" / Int32ul, + "ga20_clock" / Int32ul, + "reserved_3" / Bytes(28) +) + +b3_command = Struct( + "command" / Const(b'\xB3'), + "reg" / Int8ul, + "data" / Int8ul +) + +register_names = [ + "REG_UNK", # 0x00 + "REG_UNK", # 0x01 + "REG_UNK", # 0x02 + "REG_UNK", # 0x03 + "REG_UNK", # 0x04 + "REG_UNK", # 0x05 + "REG_UNK", # 0x06 + "REG_UNK", # 0x07 + "REG_UNK", # 0x08 + "REG_UNK", # 0x09 + "REG_UNK", # 0x0A + "REG_UNK", # 0x0B + "REG_UNK", # 0x0C + "REG_UNK", # 0x0D + "REG_UNK", # 0x0E + "REG_UNK", # 0x0F + "REG_NR10_CH1_SWEEP", # 0x10 + "REG_NR11_CH1_LENDT", # 0x11 + "REG_NR12_CH1_VOLEV", # 0x12 + "REG_NR13_CH1_FRQLO", # 0x13 + "REG_NR14_CH1_FRQHI", # 0x14 + "REG_UNK", # 0x15 + "REG_NR21_CH2_LENDT", # 0x16 + "REG_NR22_CH2_VOLEV", # 0x17 + "REG_NR23_CH2_FRQLO", # 0x18 + "REG_NR24_CH2_FRQHI", # 0x19 + "REG_NR30_CH3_DACEN", # 0x1A + "REG_NR31_CH3_LENGT", # 0x1B + "REG_NR32_CH3_VOLUM", # 0x1C + "REG_NR33_CH3_FRQLO", # 0x1D + "REG_NR34_CH3_FRQHI", # 0x1E + "REG_UNK", # 0x1F + "REG_NR41_CH4_LENGT", # 0x20 + "REG_NR42_CH4_VOLEV", # 0x21 + "REG_NR43_CH4_FQRND", # 0x22 + "REG_NR44_CH4_CNTRL", # 0x23 + "REG_NR50_MVOLVINPN", # 0x24 + "REG_NR51_MASTERPAN", # 0x25 + "REG_NR52_MASTERCTL", # 0x26 + "REG_UNK", # 0x27 + "REG_UNK", # 0x28 + "REG_UNK", # 0x29 + "REG_UNK", # 0x2A + "REG_UNK", # 0x2B + "REG_UNK", # 0x2C + "REG_UNK", # 0x2D + "REG_UNK", # 0x2E + "REG_UNK", # 0x2F + "REG_WAVE_PATTERN_0", # 0x30 + "REG_WAVE_PATTERN_1", # 0x31 + "REG_WAVE_PATTERN_2", # 0x32 + "REG_WAVE_PATTERN_3", # 0x33 + "REG_WAVE_PATTERN_4", # 0x34 + "REG_WAVE_PATTERN_5", # 0x35 + "REG_WAVE_PATTERN_6", # 0x36 + "REG_WAVE_PATTERN_7", # 0x37 + "REG_WAVE_PATTERN_8", # 0x38 + "REG_WAVE_PATTERN_9", # 0x39 + "REG_WAVE_PATTERN_A", # 0x3A + "REG_WAVE_PATTERN_B", # 0x3B + "REG_WAVE_PATTERN_C", # 0x3C + "REG_WAVE_PATTERN_D", # 0x3D + "REG_WAVE_PATTERN_E", # 0x3E + "REG_WAVE_PATTERN_F", # 0x3F +] + +def chunks(lst, n): + for i in range(0, len(lst), n): + yield lst[i:i + n] + +class DB: + l = [] + + def __init__(self): + self.l = [] + + def __str__(self): + out = [] + for chunk in chunks(self.l, 8): + out.append(f" db {', '.join(chunk)}") + return "\n".join(out) + "\n" + + def __repr__(self): + return str(self) + + def __len__(self): + return len(self.l) + + def add(self, *args): + if len(args) == 1: + self.l.append(f"${args[0]:02X}") + else: + self.l.append(register_names[args[0]]) + self.l.append(f"${args[1]:02X}") + + def trim(self): + while self.l[-1] == "$FF": + self.l.pop() + +for c, v in enumerate(register_names): + if v != "REG_UNK": + print(f"DEF {v} EQU ${c:02X}") + +print() +print("sMusicGame::") + +with open("game.vgm", "rb") as f: + data = f.read() + header = vgm_header.parse(data) + data_offset = 0x34 + header.vgm_data_offset + data = data[data_offset:] + db = DB() + ctr = 0 + last = None + while len(data) > 0: + if data.startswith(b'\x67\x66'): + data = data[3:] + data = data[Int32ul.parse(data) + 4:] + elif data.startswith(b'\xB3'): + b3 = b3_command.parse(data) + if last == 0x62: + print(db) + db = DB() + db.add(b3.reg + 0x10, b3.data) + last = 0xB3 + data = data[3:] + elif data.startswith(b'\x62'): + db.add(0xFF) + last = 0x62 + data = data[1:] + elif data.startswith(b'\x66'): + if len(db) > 0: + db.trim() + db.add(0xFE) + print(db, end="") + break + else: + print(f"Unknown command: ${data[0]:02X}") + data = data[1:] + +print("sMusicGameEnd::")