mirror of
https://github.com/pret/pokemon-reverse-engineering-tools.git
synced 2026-10-01 22:33:55 -04:00
126 lines
4.0 KiB
Python
Executable File
126 lines
4.0 KiB
Python
Executable File
import configuration
|
|
config = configuration.Config()
|
|
rom = bytearray(open(config.rom_path, "r").read())
|
|
|
|
banks = {
|
|
0x02: 0x60,
|
|
0x08: 0x78,
|
|
0x1f: 0x68,
|
|
}
|
|
|
|
music_commands = {
|
|
0xd0: ["notetype", {"type": "nibble"}, 2],
|
|
0xe0: ["octave", 1],
|
|
0xe8: ["togglecall", 1],
|
|
0xea: ["vibrato", {"type": "byte"}, {"type": "nibble"}, 3],
|
|
0xec: ["duty", {"type": "byte"}, 2],
|
|
0xed: ["tempo", {"type": "byte"}, {"type": "byte"}, 3],
|
|
0xf0: ["stereopanning", {"type": "byte"}, 2],
|
|
0xf8: ["executemusic", 1],
|
|
0xfc: ["dutycycle", {"type": "byte"}, 2],
|
|
0xfe: ["loopchannel", {"type": "byte"}, {"type": "label"}, 4],
|
|
0xff: ["endchannel", 1],
|
|
}
|
|
|
|
param_lengths = {
|
|
"nibble": 1,
|
|
"byte": 1,
|
|
"label": 2,
|
|
}
|
|
|
|
music_notes = {
|
|
0x0: "C_",
|
|
0x1: "C#",
|
|
0x2: "D_",
|
|
0x3: "D#",
|
|
0x4: "E_",
|
|
0x5: "F_",
|
|
0x6: "F#",
|
|
0x7: "G_",
|
|
0x8: "G#",
|
|
0x9: "A_",
|
|
0xa: "A#",
|
|
0xb: "B_",
|
|
}
|
|
|
|
for bank in banks:
|
|
header = bank * 0x4000 + 3
|
|
for sfx in range(1,banks[bank]):
|
|
sfxname = "SFX_{:02x}_{:02x}".format(bank, sfx)
|
|
sfxfile = open("music/sfx/" + sfxname.lower() + ".asm", 'w')
|
|
startingaddress = rom[header + 2] * 0x100 + rom[header + 1] + (0x4000 * (bank - 1))
|
|
end = 0
|
|
curchannel = 1
|
|
lastchannel = (rom[header] >> 6) + 1
|
|
channelnumber = rom[header] % 0x10
|
|
output = ''
|
|
while 1:
|
|
address = startingaddress
|
|
if curchannel != lastchannel:
|
|
end = rom[header + 5] * 0x100 + rom[header + 4] + (0x4000 * (bank - 1))
|
|
byte = rom[address]
|
|
if byte == 0xf8 or (bank == 2 and sfx == 0x5e): executemusic = True
|
|
else: executemusic = False
|
|
output += "{}_Ch{}: ; {:02x} ({:0x}:{:02x})\n".format(sfxname, curchannel, address, bank, address % 0x4000 + 0x4000)
|
|
while 1:
|
|
if address == 0x2062a or address == 0x2063d or address == 0x20930:
|
|
output += "\n{}_branch_{:02x}:\n".format(sfxname, address)
|
|
if byte == 0x10 and not executemusic:
|
|
output += "\tunknownsfx0x{:02x} {}".format(byte, rom[address + 1])
|
|
command_length = 2
|
|
elif byte < 0x30 and not executemusic:
|
|
if channelnumber == 7:
|
|
output += "\tunknownnoise0x20 {}, {}, {}".format(byte % 0x10, rom[address + 1], rom[address + 2])
|
|
command_length = 3
|
|
else:
|
|
output += "\tunknownsfx0x20 {}, {}, {}, {}".format(byte % 0x10, rom[address + 1], rom[address + 2], rom[address + 3])
|
|
command_length = 4
|
|
elif byte < 0xc0:
|
|
output += "\tnote {}, {}".format(music_notes[byte >> 4], byte % 0x10 + 1)
|
|
command_length = 1
|
|
elif byte < 0xd0:
|
|
output += "\trest {}".format(byte % 0x10 + 1)
|
|
command_length = 1
|
|
else:
|
|
if byte < 0xe0:
|
|
command = music_commands[0xd0]
|
|
output += "\t{} {},".format(command[0], byte % 0x10)
|
|
byte = 0xd0
|
|
elif byte < 0xe8:
|
|
command = music_commands[0xe0]
|
|
output += "\t{} {}".format(command[0], 0xe8 - byte)
|
|
byte = 0xe0
|
|
else:
|
|
command = music_commands[byte]
|
|
output += "\t{}".format(command[0])
|
|
command_length = 1
|
|
params = 1
|
|
# print all params for current command
|
|
while params != len(music_commands[byte]) - 1:
|
|
param_type = music_commands[byte][params]["type"]
|
|
address += command_length
|
|
command_length = param_lengths[param_type]
|
|
param = rom[address]
|
|
if param_type == "nibble":
|
|
output += " {}, {}".format(param >> 4, param % 0x10)
|
|
elif param_type == "byte":
|
|
output += " {}".format(param)
|
|
else:
|
|
param += rom[address + 1] * 0x100 - 0x4000 + (bank * 0x4000)
|
|
if param == startingaddress: output += " {}_Ch{}".format(sfxname, curchannel)
|
|
else: output += " {}_branch_{:02x}".format(sfxname, param)
|
|
params += 1
|
|
if params != len(music_commands[byte]) - 1: output += ","
|
|
output += "\n"
|
|
address += command_length
|
|
if byte == 0xff or address == end: break
|
|
byte = rom[address]
|
|
header += 3
|
|
channelnumber = rom[header]
|
|
if curchannel == lastchannel:
|
|
output += "; {}".format(hex(address))
|
|
sfxfile.write(output)
|
|
break
|
|
output += "\n\n"
|
|
startingaddress = address
|
|
curchannel += 1 |