import configuration
config = configuration.Config()
rom = bytearray(open(config.rom_path, "r").read())

sfx_names = [
	"Snare1_2",
	"Snare2_2",
	"Snare3_2",
	"Snare4_2",
	"Snare5_2",
	"Triangle1_2",
	"Triangle2_2",
	"Snare6_2",
	"Snare7_2",
	"Snare8_2",
	"Snare9_2",
	"Cymbal1_2",
	"Cymbal2_2",
	"Cymbal3_2",
	"Muted_Snare1_2",
	"Triangle3_2",
	"Muted_Snare2_2",
	"Muted_Snare3_2",
	"Muted_Snare4_2",
	"Cry00_2",
	"Cry01_2",
	"Cry02_2",
	"Cry03_2",
	"Cry04_2",
	"Cry05_2",
	"Cry06_2",
	"Cry07_2",
	"Cry08_2",
	"Cry09_2",
	"Cry0A_2",
	"Cry0B_2",
	"Cry0C_2",
	"Cry0D_2",
	"Cry0E_2",
	"Cry0F_2",
	"Cry10_2",
	"Cry11_2",
	"Cry12_2",
	"Cry13_2",
	"Cry14_2",
	"Cry15_2",
	"Cry16_2",
	"Cry17_2",
	"Cry18_2",
	"Cry19_2",
	"Cry1A_2",
	"Cry1B_2",
	"Cry1C_2",
	"Cry1D_2",
	"Cry1E_2",
	"Cry1F_2",
	"Cry20_2",
	"Cry21_2",
	"Cry22_2",
	"Cry23_2",
	"Cry24_2",
	"Cry25_2",
	"Level_Up",
	"Get_Item2_2",
	"Tink_2",
	"Heal_HP_2",
	"Heal_Ailment_2",
	"Start_Menu_2",
	"Press_AB_2",
	"Ball_Toss",
	"Ball_Poof",
	"Faint_Thud",
	"Run",
	"Dex_Page_Added",
	"Caught_Mon",
	"Peck",
	"Faint_Fall",
	"Battle_09",
	"Pound",
	"Battle_0B",
	"Battle_0C",
	"Battle_0D",
	"Battle_0E",
	"Battle_0F",
	"Damage",
	"Not_Very_Effective",
	"Battle_12",
	"Battle_13",
	"Battle_14",
	"Vine_Whip",
	"Battle_16",
	"Battle_17",
	"Battle_18",
	"Battle_19",
	"Super_Effective",
	"Battle_1B",
	"Battle_1C",
	"Doubleslap",
	"Battle_1E",
	"Horn_Drill",
	"Battle_20",
	"Battle_21",
	"Battle_22",
	"Battle_23",
	"Battle_24",
	"Battle_25",
	"Battle_26",
	"Battle_27",
	"Battle_28",
	"Battle_29",
	"Battle_2A",
	"Battle_2B",
	"Battle_2C",
	"Psybeam",
	"Battle_2E",
	"Battle_2F",
	"Psychic_M",
	"Battle_31",
	"Battle_32",
	"Battle_33",
	"Battle_34",
	"Battle_35",
	"Battle_36",
	"Silph_Scope",
	"Snare1_1",
	"Snare2_1",
	"Snare3_1",
	"Snare4_1",
	"Snare5_1",
	"Triangle1_1",
	"Triangle2_1",
	"Snare6_1",
	"Snare7_1",
	"Snare8_1",
	"Snare9_1",
	"Cymbal1_1",
	"Cymbal2_1",
	"Cymbal3_1",
	"Muted_Snare1_1",
	"Triangle3_1",
	"Muted_Snare2_1",
	"Muted_Snare3_1",
	"Muted_Snare4_1",
	"Cry00_1",
	"Cry01_1",
	"Cry02_1",
	"Cry03_1",
	"Cry04_1",
	"Cry05_1",
	"Cry06_1",
	"Cry07_1",
	"Cry08_1",
	"Cry09_1",
	"Cry0A_1",
	"Cry0B_1",
	"Cry0C_1",
	"Cry0D_1",
	"Cry0E_1",
	"Cry0F_1",
	"Cry10_1",
	"Cry11_1",
	"Cry12_1",
	"Cry13_1",
	"Cry14_1",
	"Cry15_1",
	"Cry16_1",
	"Cry17_1",
	"Cry18_1",
	"Cry19_1",
	"Cry1A_1",
	"Cry1B_1",
	"Cry1C_1",
	"Cry1D_1",
	"Cry1E_1",
	"Cry1F_1",
	"Cry20_1",
	"Cry21_1",
	"Cry22_1",
	"Cry23_1",
	"Cry24_1",
	"Cry25_1",
	"Get_Item1_1",
	"Get_Item2_1",
	"Tink_1",
	"Heal_HP_1",
	"Heal_Ailment_1",
	"Start_Menu_1",
	"Press_AB_1",
	"Pokedex_Rating_1",
	"Get_Key_Item_1",
	"Poisoned_1",
	"Trade_Machine_1",
	"Turn_On_PC_1",
	"Turn_Off_PC_1",
	"Enter_PC_1",
	"Shrink_1",
	"Switch_1",
	"Healing_Machine_1",
	"Teleport_Exit1_1",
	"Teleport_Enter1_1",
	"Teleport_Exit2_1",
	"Ledge_1",
	"Teleport_Enter2_1",
	"Fly_1",
	"Denied_1",
	"Arrow_Tiles_1",
	"Push_Boulder_1",
	"SS_Anne_Horn_1",
	"Withdraw_Deposit_1",
	"Cut_1",
	"Go_Inside_1",
	"Swap_1",
	"59_1",
	"Purchase_1",
	"Collision_1",
	"Go_Outside_1",
	"Save_1",
	"Pokeflute",
	"Safari_Zone_PA",
	"Snare1_3",
	"Snare2_3",
	"Snare3_3",
	"Snare4_3",
	"Snare5_3",
	"Triangle1_3",
	"Triangle2_3",
	"Snare6_3",
	"Snare7_3",
	"Snare8_3",
	"Snare9_3",
	"Cymbal1_3",
	"Cymbal2_3",
	"Cymbal3_3",
	"Muted_Snare1_3",
	"Triangle3_3",
	"Muted_Snare2_3",
	"Muted_Snare3_3",
	"Muted_Snare4_3",
	"Cry00_3",
	"Cry01_3",
	"Cry02_3",
	"Cry03_3",
	"Cry04_3",
	"Cry05_3",
	"Cry06_3",
	"Cry07_3",
	"Cry08_3",
	"Cry09_3",
	"Cry0A_3",
	"Cry0B_3",
	"Cry0C_3",
	"Cry0D_3",
	"Cry0E_3",
	"Cry0F_3",
	"Cry10_3",
	"Cry11_3",
	"Cry12_3",
	"Cry13_3",
	"Cry14_3",
	"Cry15_3",
	"Cry16_3",
	"Cry17_3",
	"Cry18_3",
	"Cry19_3",
	"Cry1A_3",
	"Cry1B_3",
	"Cry1C_3",
	"Cry1D_3",
	"Cry1E_3",
	"Cry1F_3",
	"Cry20_3",
	"Cry21_3",
	"Cry22_3",
	"Cry23_3",
	"Cry24_3",
	"Cry25_3",
	"Get_Item1_3",
	"Get_Item2_3",
	"Tink_3",
	"Heal_HP_3",
	"Heal_Ailment_3",
	"Start_Menu_3",
	"Press_AB_3",
	"Pokedex_Rating_3",
	"Get_Key_Item_3",
	"Poisoned_3",
	"Trade_Machine_3",
	"Turn_On_PC_3",
	"Turn_Off_PC_3",
	"Enter_PC_3",
	"Shrink_3",
	"Switch_3",
	"Healing_Machine_3",
	"Teleport_Exit1_3",
	"Teleport_Enter1_3",
	"Teleport_Exit2_3",
	"Ledge_3",
	"Teleport_Enter2_3",
	"Fly_3",
	"Denied_3",
	"Arrow_Tiles_3",
	"Push_Boulder_3",
	"SS_Anne_Horn_3",
	"Withdraw_Deposit_3",
	"Cut_3",
	"Go_Inside_3",
	"Swap_3",
	"59_3",
	"Purchase_3",
	"Collision_3",
	"Go_Outside_3",
	"Save_3",
	"Intro_Lunge",
	"Intro_Hip",
	"Intro_Hop",
	"Intro_Raise",
	"Intro_Crash",
	"Intro_Whoosh",
	"Slots_Stop_Wheel",
	"Slots_Reward",
	"Slots_New_Spin",
	"Shooting_Star",
	]

banks = {
	0x02: 0x60,
	0x08: 0x78,
	0x1f: 0x68,
	}

music_commands = {
	0xd0: ["notetype", {"type": "nibble"}, 2],
	0xe0: ["octave", 1],
	0xe8: ["toggleperfectpitch", 1],
	0xea: ["vibrato", {"type": "byte"}, {"type": "nibble"}, 3],
	0xec: ["duty", {"type": "byte"}, 2],
	0xed: ["tempo", {"type": "word"}, 3],
	0xf0: ["volume", {"type": "nibble"}, 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,
	"word": 2,
	"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_",
	}

sfxnum = 0

for bank in banks:
	print bank
	header = bank * 0x4000 + 3
	for sfx in range(1,banks[bank]):
		sfxname = sfx_names[sfxnum]
		sfxfile = open("music/sfx/" + sfx_names[sfxnum].lower() + ".asm", 'w')
		sfxname = "SFX_" + sfxname
		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 += "\t{} {}".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)
						elif param_type == "word":
							output += " {}".format(param * 0x100 + rom[address + 1])
						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
		sfxnum += 1