ref: 6297be577d985375af5c416da898a78ba6ddf6b5
parent: 5ae8a5cc7145fdfec335d20ee22029059f7ce94c
author: Snesrev <snesrev@protonmail.com>
date: Mon Oct 10 22:22:20 EDT 2022
Asset compiler now uses PNG-images as input Also renamed variables Fix so it won't decompress sheets < 12
--- a/ancilla.c
+++ b/ancilla.c
@@ -3742,7 +3742,7 @@
}
if (!ancilla_arr3[k] && ancilla_item_to_link[k] == 0x20) {
ancilla_arr3[k] = 1;
- palette_sp6 = 4;
+ palette_sp6r_indoors = 4;
overworld_palette_aux_or_main = 0x200;
Palette_Load_SpriteEnvironment_Dungeon();
flag_update_cgram_in_nmi++;
@@ -3902,7 +3902,7 @@
ancilla_x_lo[k] = bak0;
ancilla_x_hi[k] = bak1;
if (breaktowerseal_var4 >= 240) {
- palette_sp6 = 0;
+ palette_sp6r_indoors = 0;
overworld_palette_aux_or_main = 0x200;
Palette_Load_SpriteEnvironment_Dungeon();
flag_update_cgram_in_nmi++;
@@ -6716,7 +6716,7 @@
for (int i = 0x17; i >= 0; i--)
breaktowerseal_sparkle_var1[i] = 0xff;
DecodeAnimatedSpriteTile_variable(0x28);
- palette_sp6 = 4;
+ palette_sp6r_indoors = 4;
overworld_palette_aux_or_main = 0x200;
Palette_Load_SpriteEnvironment_Dungeon();
flag_update_cgram_in_nmi++;
--- a/attract.c
+++ b/attract.c
@@ -360,10 +360,10 @@
overworld_palette_aux_or_main = 0x200;
flag_update_cgram_in_nmi++;
Palette_BgAndFixedColor_Black();
- Palette_Load_SpritePal0Left();
+ Palette_Load_Sp0L();
Palette_Load_SpriteMain();
- Palette_Load_SpriteAux1();
- Palette_Load_SpriteAux2();
+ Palette_Load_Sp5L();
+ Palette_Load_Sp6L();
Palette_Load_SpriteEnvironment_Dungeon();
Palette_Load_HUD();
Palette_Load_DungeonSet();
@@ -524,10 +524,10 @@
Dungeon_LoadAndDrawEntranceRoom(0x74);
WORD(attract_state) = bak1;
attract_var12 = bak0;
- dung_hdr_palette_1 = 0;
- overworld_palette_sp0 = 0;
- sprite_aux1_palette = 14;
- sprite_aux2_palette = 3;
+ palette_main_indoors = 0;
+ palette_sp0l = 0;
+ palette_sp5l = 14;
+ palette_sp6l = 3;
Dungeon_SaveAndLoadLoadAllPalettes(0, 0x7e);
main_palette_buffer[0x1d] = 0x3800;
@@ -560,10 +560,10 @@
WORD(attract_state) = bak1;
attract_var12 = bak0;
- dung_hdr_palette_1 = 2;
- overworld_palette_sp0 = 0;
- sprite_aux1_palette = 14;
- sprite_aux2_palette = 3;
+ palette_main_indoors = 2;
+ palette_sp0l = 0;
+ palette_sp5l = 14;
+ palette_sp6l = 3;
Dungeon_SaveAndLoadLoadAllPalettes(1, 0x7f);
main_palette_buffer[0x1d] = 0x3800;
@@ -589,16 +589,16 @@
WORD(attract_state) = bak1;
attract_var12 = bak0;
- dung_hdr_palette_1 = 0;
- overworld_palette_sp0 = 0;
- sprite_aux1_palette = 14;
- sprite_aux2_palette = 3;
+ palette_main_indoors = 0;
+ palette_sp0l = 0;
+ palette_sp5l = 14;
+ palette_sp6l = 3;
overworld_palette_aux_or_main = 0;
- Palette_Load_SpritePal0Left();
+ Palette_Load_Sp0L();
Palette_Load_SpriteMain();
- Palette_Load_SpriteAux1();
- Palette_Load_SpriteAux2();
+ Palette_Load_Sp5L();
+ Palette_Load_Sp6L();
Palette_Load_SpriteEnvironment_Dungeon();
Palette_Load_HUD();
Palette_Load_DungeonSet();
--- a/dungeon.c
+++ b/dungeon.c
@@ -3702,10 +3702,10 @@
dung_want_lights_out_copy = dung_want_lights_out;
dung_want_lights_out = hdr_ptr[0] & 1;
const DungPalInfo *dpi = &kDungPalinfos[hdr_ptr[1]];
- dung_hdr_palette_1 = dpi->pal0;
- overworld_palette_sp0 = dpi->pal1;
- sprite_aux1_palette = dpi->pal2;
- sprite_aux2_palette = dpi->pal3;
+ palette_main_indoors = dpi->pal0;
+ palette_sp0l = dpi->pal1;
+ palette_sp5l = dpi->pal2;
+ palette_sp6l = dpi->pal3;
aux_tile_theme_index = hdr_ptr[2];
sprite_graphics_index = hdr_ptr[3] + 0x40;
dung_hdr_collision_2 = hdr_ptr[4];
@@ -6432,7 +6432,7 @@
Dungeon_LoadAttributeTable();
misc_sprites_graphics_index = 10;
InitializeTilesets();
- palette_sp6 = 10;
+ palette_sp6r_indoors = 10;
Dungeon_LoadPalettes();
if (link_is_bunny_mirror | link_is_bunny)
LoadGearPalettes_bunny();
@@ -7743,7 +7743,7 @@
submodule_index = 0;
nmi_load_bg_from_vram = 0;
last_music_control = music_unk1;
- if (overworld_palette_swap_flag)
+ if (palette_swap_flag)
Palette_RevertTranslucencySwap();
}
}
@@ -7861,7 +7861,7 @@
subsubmodule_index = bak + 1;
misc_sprites_graphics_index = 10;
InitializeTilesets();
- palette_sp6 = 10;
+ palette_sp6r_indoors = 10;
Dungeon_LoadPalettes();
Hud_RestoreTorchBackground();
button_mask_b_y = 0;
--- a/ending.c
+++ b/ending.c
@@ -246,11 +246,11 @@
int i = submodule_index >> 1;
sprite_graphics_index = kEnding_SpritePack[i];
const DungPalInfo *dpi = GetDungPalInfo(kEnding_SpritePal[i] & 0x3f);
- sprite_aux1_palette = dpi->pal2;
- sprite_aux2_palette = dpi->pal3;
+ palette_sp5l = dpi->pal2;
+ palette_sp6l = dpi->pal3;
misc_sprites_graphics_index = 10;
InitializeTilesets();
- palette_sp6 = 10;
+ palette_sp6r_indoors = 10;
Dungeon_LoadPalettes();
BGMODE_copy = 9;
R16 = 0;
@@ -578,7 +578,7 @@
DecompressAnimatedDungeonTiles(0x5d);
bg_tile_animation_countdown = 2;
BYTE(overworld_screen_index) = 0;
- dung_hdr_palette_1 = 0;
+ palette_main_indoors = 0;
overworld_palette_aux3_bp7_lo = 0;
R16 = 0;
R18 = 0;
--- a/load_gfx.c
+++ b/load_gfx.c
@@ -877,9 +877,9 @@
int8 sp6 = kGraphicsLoadSp6[k - 1];
if (sp6 >= 0) {
- palette_sp6 = sp6;
+ palette_sp6r_indoors = sp6;
if (k == 1) {
- palette_sp6 = 10;
+ palette_sp6r_indoors = 10;
overworld_palette_aux_or_main = 0x200;
Palette_Load_SpriteEnvironment();
flag_update_cgram_in_nmi++;
@@ -989,7 +989,14 @@
}
int Decomp_spr(uint8 *dst, int gfx) { // 80e772
- return Decompress(dst, GetCompSpritePtr(gfx));
+ if (gfx < 12)
+ gfx = 12; // ensure it wont decode bad sheets.
+ const uint8 *sprite_data = GetCompSpritePtr(gfx);
+ // If the size is not 0x600 then it's compressed
+ if (gfx >= 103 || (((uint32 *)kSprGfx)[gfx + 1] - ((uint32 *)kSprGfx)[gfx]) != 0x600)
+ return Decompress(dst, sprite_data);
+ memcpy(dst, sprite_data, 0x600);
+ return 0x600;
}
int Decomp_bg(uint8 *dst, int gfx) { // 80e78f
@@ -1649,7 +1656,7 @@
}
void Dungeon_HandleTranslucencyAndPalette() { // 82a1e9
- if (overworld_palette_swap_flag)
+ if (palette_swap_flag)
Palette_RevertTranslucencySwap();
CGWSEL_copy = 2;
@@ -1683,9 +1690,9 @@
darkening_or_lightening_screen = 2;
overworld_palette_aux_or_main = 0;
Palette_Load_DungeonSet();
- Palette_Load_SpritePal0Left();
- Palette_Load_SpriteAux1();
- Palette_Load_SpriteAux2();
+ Palette_Load_Sp0L();
+ Palette_Load_Sp5L();
+ Palette_Load_Sp6L();
subsubmodule_index += 1;
}
@@ -1697,12 +1704,12 @@
overworld_palette_aux1_bp2to4_hi = 3;
overworld_palette_aux2_bp5to7_hi = 3;
overworld_palette_aux3_bp7_lo = 0;
- palette_sp6 = 5;
- overworld_palette_sp0 = 11;
- overworld_palette_swap_flag = 0;
+ palette_sp6r_indoors = 5;
+ palette_sp0l = 11;
+ palette_swap_flag = 0;
overworld_palette_aux_or_main = 0;
Palette_BgAndFixedColor_Black();
- Palette_Load_SpritePal0Left();
+ Palette_Load_Sp0L();
Palette_Load_SpriteMain();
Palette_Load_OWBGMain();
Palette_Load_OWBG1();
@@ -1718,10 +1725,10 @@
void Dungeon_LoadPalettes() { // 82c630
overworld_palette_aux_or_main = 0;
Palette_BgAndFixedColor_Black();
- Palette_Load_SpritePal0Left();
+ Palette_Load_Sp0L();
Palette_Load_SpriteMain();
- Palette_Load_SpriteAux1();
- Palette_Load_SpriteAux2();
+ Palette_Load_Sp5L();
+ Palette_Load_Sp6L();
Palette_Load_Sword();
Palette_Load_Shield();
Palette_Load_SpriteEnvironment();
@@ -1732,7 +1739,7 @@
}
void Overworld_LoadPalettesInner() { // 82c65f
- overworld_pal_unk1 = dung_hdr_palette_1;
+ overworld_pal_unk1 = palette_main_indoors;
overworld_pal_unk2 = overworld_palette_aux3_bp7_lo;
overworld_pal_unk3 = byte_7E0AB7;
darkening_or_lightening_screen = 2;
@@ -1753,13 +1760,13 @@
overworld_palette_aux_or_main &= 0xff;
Palette_Load_SpriteMain();
Palette_Load_SpriteEnvironment();
- Palette_Load_SpriteAux1();
- Palette_Load_SpriteAux2();
+ Palette_Load_Sp5L();
+ Palette_Load_Sp6L();
Palette_Load_Sword();
Palette_Load_Shield();
Palette_Load_LinkArmorAndGloves();
- overworld_palette_sp0 = (savegame_is_darkworld & 0x40) ? 3 : 1;
- Palette_Load_SpritePal0Left();
+ palette_sp0l = (savegame_is_darkworld & 0x40) ? 3 : 1;
+ Palette_Load_Sp0L();
Palette_Load_HUD();
Palette_Load_OWBGMain();
}
@@ -1800,14 +1807,14 @@
d = kOwSprPalInfo + spr * 2;
if (d[0] >= 0)
- sprite_aux1_palette = d[0];
+ palette_sp5l = d[0];
if (d[1] >= 0)
- sprite_aux2_palette = d[1];
+ palette_sp6l = d[1];
Palette_Load_OWBG1();
Palette_Load_OWBG2();
Palette_Load_OWBG3();
- Palette_Load_SpriteAux1();
- Palette_Load_SpriteAux2();
+ Palette_Load_Sp5L();
+ Palette_Load_Sp6L();
}
void Palette_BgAndFixedColor_Black() { // 8ed5f4
@@ -1852,7 +1859,7 @@
}
void Palette_SetTranslucencySwap(bool v) { // 8ed65c
- overworld_palette_swap_flag = v;
+ palette_swap_flag = v;
uint16 a, b;
for (int i = 0; i < 8; i++) {
a = aux_palette_buffer[i + 0x80];
@@ -1959,35 +1966,64 @@
Palette_Restore_Coldata();
}
-void Palette_Load_SpritePal0Left() { // 9bec77
- const uint16 *src = kPalette_SpriteAux3 + overworld_palette_sp0 * 7;
- Palette_LoadSingle(src, overworld_palette_swap_flag ? 0x1e2 : 0x102, 6);
+/* Summary of sprite palette usage
+0l: kPalette_SpriteAux3[palette_sp0l]
+0r: kPalette_MiscSprite[7 / 9] or kPalette_DungBgMain[(palette_main_indoors >> 1) * 90]
+1 : common sprites
+2 : -"-
+3 : -"-
+4 : -"-
+5l: palette_sp5l
+5r: link sword/shield
+6l: palette_sp6l
+6r: kPalette_MiscSprite[6 / 8] or kPalette_MiscSprite[palette_sp6r_indoors]
+7 : link armor and gloves
+*/
+
+enum {
+ kPal_sp0l = 0x102,
+ kPal_sp0r = 0x112,
+ kPal_sp1to4 = 0x122, // This is used for 64 colors, colors switched if in darkworld mode
+ kPal_sp5l = 0x1a2,
+ kPal_Sword = 0x1b2,
+ kPal_Shield = 0x1b8,
+ kPal_sp6l = 0x1c2,
+ kPal_sp6r = 0x1d2,
+ kPal_sp7l = 0x1e2,
+ kPal_sp7r = 0x1f2,
+ kPal_ArmorGloves = 0x1e2,
+ kPal_PalaceMap = 0x182,
+};
+
+void Palette_Load_Sp0L() { // 9bec77
+ const uint16 *src = kPalette_SpriteAux3 + palette_sp0l * 7;
+ Palette_LoadSingle(src, palette_swap_flag ? kPal_sp7l : kPal_sp0l, 6);
}
void Palette_Load_SpriteMain() { // 9bec9e
const uint16 *src = kPalette_MainSpr + (overworld_screen_index & 0x40 ? 60 : 0);
- Palette_LoadMultiple(src, 0x122, 14, 3);
+ Palette_LoadMultiple(src, kPal_sp1to4, 14, 3);
}
-void Palette_Load_SpriteAux1() { // 9becc5
- const uint16 *src = kPalette_SpriteAux1 + (sprite_aux1_palette) * 7;
- Palette_LoadSingle(src, 0x1A2, 6);
+void Palette_Load_Sp5L() { // 9becc5
+ const uint16 *src = kPalette_SpriteAux1 + (palette_sp5l) * 7;
+ Palette_LoadSingle(src, kPal_sp5l, 6);
}
-void Palette_Load_SpriteAux2() { // 9bece4
- const uint16 *src = kPalette_SpriteAux1 + (sprite_aux2_palette) * 7;
- Palette_LoadSingle(src, 0x1C2, 6);
+void Palette_Load_Sp6L() { // 9bece4
+ const uint16 *src = kPalette_SpriteAux1 + (palette_sp6l) * 7;
+ Palette_LoadSingle(src, kPal_sp6l, 6);
}
void Palette_Load_Sword() { // 9bed03
const uint16 *src = kPalette_Sword + ((int8)link_sword_type > 0 ? link_sword_type - 1 : 0) * 3; // wtf: zelda reads offset 0xff
- Palette_LoadMultiple_Arbitrary(src, 0x1b2, 2);
+ Palette_LoadMultiple_Arbitrary(src, kPal_Sword, 2);
flag_update_cgram_in_nmi += 1;
}
void Palette_Load_Shield() { // 9bed29
const uint16 *src = kPalette_Shield + (link_shield_type ? link_shield_type - 1 : 0) * 4;
- Palette_LoadMultiple_Arbitrary(src, 0x1b8, 3);
+ Palette_LoadMultiple_Arbitrary(src, kPal_Shield, 3);
flag_update_cgram_in_nmi += 1;
}
@@ -1998,26 +2034,28 @@
Palette_MiscSprite_Outdoors();
}
+// avoid renaming in assets.dat
+#define kPalette_MiscSprite kPalette_MiscSprite_Indoors
+
void Palette_Load_SpriteEnvironment_Dungeon() { // 9bed72
- const uint16 *src = kPalette_MiscSprite_Indoors + palette_sp6 * 7;
- Palette_LoadSingle(src, 0x1d2, 6);
+ const uint16 *src = kPalette_MiscSprite + palette_sp6r_indoors * 7;
+ Palette_LoadSingle(src, kPal_sp6r, 6);
}
void Palette_MiscSprite_Outdoors() { // 9bed91
int t = (overworld_screen_index & 0x40) ? 9 : 7;
- const uint16 *src = kPalette_MiscSprite_Indoors + t * 7;
- Palette_LoadSingle(src, overworld_palette_swap_flag ? 0x1f2 : 0x112, 6);
- src = kPalette_MiscSprite_Indoors + (t - 1) * 7;
- Palette_LoadSingle(src, 0x1d2, 6);
+ const uint16 *src = kPalette_MiscSprite + t * 7;
+ Palette_LoadSingle(src, palette_swap_flag ? kPal_sp7r : kPal_sp0r, 6);
+ Palette_LoadSingle(src - 7, kPal_sp6r, 6);
}
void Palette_Load_DungeonMapSprite() { // 9beddd
- Palette_LoadMultiple(kPalette_PalaceMapSpr, 0x182, 6, 2);
+ Palette_LoadMultiple(kPalette_PalaceMapSpr, kPal_PalaceMap, 6, 2);
}
void Palette_Load_LinkArmorAndGloves() { // 9bedf9
const uint16 *src = kPalette_ArmorAndGloves + link_armor * 15;
- Palette_LoadMultiple_Arbitrary(src, 0x1e2, 14);
+ Palette_LoadMultiple_Arbitrary(src, kPal_ArmorGloves, 14);
Palette_UpdateGlovesColor();
}
@@ -2037,9 +2075,9 @@
}
void Palette_Load_DungeonSet() { // 9bee74
- const uint16 *src = kPalette_DungBgMain + (dung_hdr_palette_1 >> 1) * 90;
+ const uint16 *src = kPalette_DungBgMain + (palette_main_indoors >> 1) * 90;
Palette_LoadMultiple(src, 0x42, 14, 5);
- Palette_LoadSingle(src, overworld_palette_swap_flag ? 0x1f2 : 0x112, 6);
+ Palette_LoadSingle(src, palette_swap_flag ? kPal_sp7r : kPal_sp0r, 6);
}
void Palette_Load_OWBG3() { // 9beea8
--- a/load_gfx.h
+++ b/load_gfx.h
@@ -132,10 +132,10 @@
void Palette_Restore_BG_From_Flash();
void Palette_Restore_Coldata();
void Palette_Restore_BG_And_HUD();
-void Palette_Load_SpritePal0Left();
+void Palette_Load_Sp0L();
void Palette_Load_SpriteMain();
-void Palette_Load_SpriteAux1();
-void Palette_Load_SpriteAux2();
+void Palette_Load_Sp5L();
+void Palette_Load_Sp6L();
void Palette_Load_Sword();
void Palette_Load_Shield();
void Palette_Load_SpriteEnvironment();
--- a/main.c
+++ b/main.c
@@ -25,7 +25,10 @@
#include "assets.h"
#include "load_gfx.h"
+static bool g_run_without_emu = 0;
+
+
// Forwards
static bool LoadRom(const char *filename);
static void LoadLinkGraphics();
@@ -60,7 +63,6 @@
static bool g_display_perf;
static int g_curr_fps;
static int g_ppu_render_flags = 0;
-static bool g_run_without_emu = false;
static int g_snes_width, g_snes_height;
static int g_sdl_audio_mixer_volume = SDL_MIX_MAXVOLUME;
--- a/messaging.c
+++ b/messaging.c
@@ -829,7 +829,7 @@
load_chr_halfslot_even_odd = 15;
Graphics_LoadChrHalfSlot();
load_chr_halfslot_even_odd = 0;
- palette_sp6 = 5;
+ palette_sp6r_indoors = 5;
overworld_palette_aux_or_main = 0x200;
Palette_Load_SpriteEnvironment_Dungeon();
Palette_Load_SpriteMain();
@@ -2036,7 +2036,7 @@
if (a >= 0)
r3 -= a;
}
- SetOamPlain(&oam_buf[spr_pos], 0x19, kDungMap_Tab33[r3] - 4, 0, overworld_palette_swap_flag ? 0x30 : 0x3e, 2);
+ SetOamPlain(&oam_buf[spr_pos], 0x19, kDungMap_Tab33[r3] - 4, 0, palette_swap_flag ? 0x30 : 0x3e, 2);
}
int DungeonMap_DrawBlinkingIndicator(int spr_pos) { // 8aeb50
binary files /dev/null b/other/3x5_font.png differ
--- a/overworld.c
+++ b/overworld.c
@@ -1449,7 +1449,7 @@
overworld_palette_aux_or_main = 0;
Palette_Load_SpriteMain();
Palette_Load_SpriteEnvironment();
- Palette_Load_SpritePal0Left();
+ Palette_Load_Sp0L();
Palette_Load_HUD();
Palette_Load_OWBGMain();
uint8 sc = overworld_screen_index;
--- a/player.c
+++ b/player.c
@@ -177,7 +177,6 @@
}
if (link_player_handler_state)
Player_CheckHandleCapeStuff();
-
kPlayerHandlers[link_player_handler_state]();
}
@@ -6518,7 +6517,7 @@
byte_7E03F3 = 0;
byte_7E0322 = 0;
flag_is_link_immobilized = 0;
- overworld_palette_swap_flag = 0;
+ palette_swap_flag = 0;
player_unk1 = 0;
link_give_damage = 0;
link_actual_vel_y = 0;
--- a/player_oam.c
+++ b/player_oam.c
@@ -927,7 +927,7 @@
int r2 = kPlayerOamOtherOffs[dir * 40 + yt] + rt;
int r4loc = kPlayerOamSpriteLocs[r2];
- link_palette_bits_of_oam = overworld_palette_swap_flag ? 0 : 0xe00;
+ link_palette_bits_of_oam = palette_swap_flag ? 0 : 0xe00;
link_dma_var1 = link_dma_var2 = 0;
int xt = FindInByteArray(kPlayerOam_Tab5, yt, 7);
--- a/select_file.c
+++ b/select_file.c
@@ -211,7 +211,7 @@
music_control = 11;
submodule_index++;
overworld_palette_aux_or_main = 0x200;
- dung_hdr_palette_1 = 6;
+ palette_main_indoors = 6;
nmi_disable_core_updates = 6;
Palette_Load_DungeonSet();
Palette_Load_OWBG3();
--- a/sprite_main.c
+++ b/sprite_main.c
@@ -73,58 +73,6 @@
0x09, 0x13, 0x14, 0x4a, 0x21, 0x1d, 0x15, 0x18, 0x19, 0x31, 0x1a, 0x1a, 0x1b, 0x1c, 0x4b, 0x1e,
0x1f, 0x49, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x22, 0x23, 0x29, 0x16, 0x2b, 0x2c, 0x2d, 0x3d, 0x3c, 0x48
};
-static const DrawMultipleData kUncleDraw_Table[48] = {
- { 0, -10, 0x0e00, 2},
- { 0, 0, 0x0c06, 2},
- { 0, -10, 0x0e00, 2},
- { 0, 0, 0x0c06, 2},
- { 0, -10, 0x0e00, 2},
- { 0, 0, 0x0c06, 2},
- { 0, -10, 0x0e02, 2},
- { 0, 0, 0x0c06, 2},
- { 0, -10, 0x0e02, 2},
- { 0, 0, 0x0c06, 2},
- { 0, -10, 0x0e02, 2},
- { 0, 0, 0x0c06, 2},
- { -7, 2, 0x0d07, 2},
- { -7, 2, 0x0d07, 2},
- { 10, 12, 0x8d05, 0},
- { 10, 4, 0x8d15, 0},
- { 0, -10, 0x0e00, 2},
- { 0, 0, 0x0c04, 2},
- { -7, 1, 0x0d07, 2},
- { -7, 1, 0x0d07, 2},
- { 10, 13, 0x8d05, 0},
- { 10, 5, 0x8d15, 0},
- { 0, -9, 0x0e00, 2},
- { 0, 1, 0x4c04, 2},
- { -7, 8, 0x8d05, 0},
- { 1, 8, 0x8d06, 0},
- { 0, -10, 0x0e02, 2},
- { -6, -1, 0x4d07, 2},
- { 0, 0, 0x0c23, 2},
- { 0, 0, 0x0c23, 2},
- { -9, 7, 0x8d05, 0},
- { -1, 7, 0x8d06, 0},
- { 0, -9, 0x0e02, 2},
- { -6, 0, 0x4d07, 2},
- { 0, 1, 0x0c25, 2},
- { 0, 1, 0x0c25, 2},
- {-10, -17, 0x0d07, 2},
- { 15, -12, 0x8d15, 0},
- { 15, -4, 0x8d05, 0},
- { 0, -28, 0x0e08, 2},
- { -8, -19, 0x0c20, 2},
- { 8, -19, 0x4c20, 2},
- { 0, -28, 0x0e08, 2},
- { 0, -28, 0x0e08, 2},
- { -8, -19, 0x0c20, 2},
- { 8, -19, 0x4c20, 2},
- { -8, -19, 0x0c20, 2},
- { 8, -19, 0x4c20, 2},
-};
-static const uint8 kUncleDraw_Dma3[8] = {8, 8, 0, 0, 6, 6, 0, 0};
-static const uint8 kUncleDraw_Dma4[8] = {0, 0, 0, 0, 4, 4, 0, 0x8b}; // wtf
static const uint8 kUncle_LeaveHouse_Delay[2] = {64, 224};
static const uint8 kUncle_LeaveHouse_Dir[2] = {2, 1};
static const int8 kUncle_LeaveHouse_Xvel[4] = {0, 0, -12, 12};
@@ -535,7 +483,7 @@
&Sprite_11_Hinox,
&Sprite_12_Moblin,
&Sprite_13_MiniHelmasaur,
- &Sprite_14_ThievesTownGrate_bounce,
+ &Sprite_14_ThievesTownGrate,
&Sprite_15_Antifairy,
&Sprite_16_Elder_bounce,
&Sprite_17_Hoarder,
@@ -552,7 +500,7 @@
&Sprite_22_Ropa,
&Sprite_23_RedBari,
&Sprite_23_RedBari,
- &Sprite_25_TalkingTree_bounce,
+ &Sprite_25_TalkingTree,
&Sprite_26_HardhatBeetle,
&Sprite_27_Deadrock,
&Sprite_28_DarkWorldHintNPC,
@@ -560,32 +508,32 @@
&Sprite_SweepingLady,
&Sprite_2B_Hobo,
&Sprite_Lumberjacks,
- &Sprite_2D_TelepathicTile_bounce,
+ &Sprite_2D_TelepathicTile,
&Sprite_2E_FluteKid,
&Sprite_MazeGameLady,
&Sprite_MazeGameGuy,
&Sprite_FortuneTeller,
&Sprite_QuarrelBros,
- &Sprite_33_RupeePull_bounce,
+ &Sprite_33_RupeePull,
&Sprite_YoungSnitchLady,
&Sprite_InnKeeper,
&Sprite_Witch,
- &Sprite_37_Waterfall_bounce,
- &Sprite_38_EyeStatue_bounce,
+ &Sprite_37_Waterfall,
+ &Sprite_38_EyeStatue,
&Sprite_39_Locksmith,
- &Sprite_3A_MagicBat_bounce,
+ &Sprite_3A_MagicBat,
&Sprite_DashItem,
&Sprite_TroughBoy,
&Sprite_OldSnitchLady,
&Sprite_17_Hoarder,
- &Sprite_TutorialGuardOrBarrier_bounce,
- &Sprite_TutorialGuardOrBarrier_bounce,
+ &Sprite_TutorialGuardOrBarrier,
+ &Sprite_TutorialGuardOrBarrier,
// Trampoline 48 entries
&Sprite_41_BlueGuard,
&Sprite_41_BlueGuard,
&Sprite_41_BlueGuard,
&Sprite_44_BluesainBolt,
- &Sprite_45_UsainBolt,
+ &Sprite_45_HogSpearMan,
&Sprite_46_BlueArcher,
&Sprite_47_GreenBushGuard,
&Sprite_48_RedJavelinGuard,
@@ -623,20 +571,20 @@
&Sprite_66_WallCannonVerticalLeft,
&Sprite_66_WallCannonVerticalLeft,
&Sprite_6A_BallNChain,
- &Sprite_CannonTrooper,
+ &Sprite_6B_CannonTrooper,
&Sprite_6C_MirrorPortal,
&Sprite_6D_Rat,
&Sprite_6E_Rope,
&Sprite_6F_Keese,
- &Sprite_70_KingHelmasaurFireball_bounce,
+ &Sprite_70_KingHelmasaurFireball,
&Sprite_71_Leever,
&Sprite_72_FairyPond,
- &Sprite_73_UncleAndPriest_bounce,
+ &Sprite_73_UncleAndPriest,
&Sprite_RunningMan,
&Sprite_BottleVendor,
&Sprite_76_Zelda,
&Sprite_15_Antifairy,
- &Sprite_78_MrsSahasrahla_bounce,
+ &Sprite_78_MrsSahasrahla,
// Trampoline 68 entries
&Sprite_79_Bee,
&Sprite_7A_Agahnim,
@@ -749,18 +697,18 @@
&Sprite_E4_SmallKey,
&Sprite_E4_SmallKey,
&Sprite_D9_GreenRupee,
- &Sprite_Mushroom,
- &Sprite_FakeSword,
- &Sprite_PotionShop,
+ &Sprite_E7_Mushroom,
+ &Sprite_E8_FakeSword,
+ &Sprite_E9_PotionShop,
&Sprite_HeartContainer,
&Sprite_HeartPiece,
&Sprite_EC_ThrownItem,
- &Sprite_SomariaPlatform,
- &Sprite_MovableMantleTrampoline,
- &Sprite_SomariaPlatform,
- &Sprite_SomariaPlatform,
- &Sprite_SomariaPlatform,
- &Sprite_F2_MedallionTablet_bounce,
+ &Sprite_ED_SomariaPlatform,
+ &Sprite_EE_MovableMantle,
+ &Sprite_ED_SomariaPlatform,
+ &Sprite_ED_SomariaPlatform,
+ &Sprite_ED_SomariaPlatform,
+ &Sprite_F2_MedallionTablet,
};
static HandlerFuncK *const kSpritePrep_Main[243] = {
&SpritePrep_Raven,
@@ -772,7 +720,7 @@
&SpritePrep_Switch,
&SpritePrep_SwitchFacingUp,
&SpritePrep_Octorok,
- &SpritePrep_Moldorm_bounce,
+ &SpritePrep_Moldorm,
&SpritePrep_Octorok,
&SpritePrep_DoNothingA,
&SpritePrep_DoNothingA,
@@ -847,7 +795,7 @@
&SpritePrep_DoNothingD,
&SpritePrep_KingZora,
&SpritePrep_ArmosKnight,
- &SpritePrep_Lanmolas_bounce,
+ &SpritePrep_Lanmolas,
&SpritePrep_SwimmingZora,
&SpritePrep_WalkingZora,
&SpritePrep_DesertStatue,
@@ -1371,7 +1319,7 @@
}
}
-void Sprite_MovableMantleTrampoline(int k) {
+void Sprite_EE_MovableMantle(int k) {
MovableMantle_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
@@ -1467,7 +1415,7 @@
SpriteDraw_Shadow_custom(k, &info, kSoldier_DrawShadow[sprite_D[k]]);
}
-void Sprite_CannonTrooper(int k) {
+void Sprite_6B_CannonTrooper(int k) {
if (sprite_C[k] != 0) {
Sprite_Cannonball(k);
return;
@@ -1716,7 +1664,7 @@
garnish_countdown[j] = 15;
}
-void Sprite_70_KingHelmasaurFireball_bounce(int k) { // 85807f
+void Sprite_70_KingHelmasaurFireball(int k) { // 85807f
static const uint8 kHelmasaurFireball_Char[3] = {0xcc, 0xcc, 0xca};
static const uint8 kHelmasaurFireball_Flags[2] = {0x33, 0x73};
static const uint8 kHelmasaurFireball_Gfx[4] = {2, 2, 1, 0};
@@ -2590,8 +2538,6 @@
}
void Sprite_Beamos_Laser(int k) { // 8591b5
-
-
if (sprite_delay_aux1[k])
return;
BeamosLaser_Draw(k);
@@ -4918,7 +4864,7 @@
}
}
-void Sprite_45_UsainBolt(int k) { // 85cbe0
+void Sprite_45_HogSpearMan(int k) { // 85cbe0
Guard_HandleAllAnimation(k);
if (Sprite_ReturnIfInactive(k))
return;
@@ -6427,7 +6373,7 @@
}
}
-void Sprite_Mushroom(int k) { // 85ee78
+void Sprite_E7_Mushroom(int k) { // 85ee78
SpriteDraw_SingleLarge(k);
if (Sprite_CheckIfLinkIsBusy())
return;
@@ -6445,7 +6391,7 @@
}
}
-void Sprite_FakeSword(int k) { // 85eeaf
+void Sprite_E8_FakeSword(int k) { // 85eeaf
FakeSword_Draw(k);
if (Sprite_ReturnIfPaused(k))
return;
@@ -6826,7 +6772,7 @@
sprite_defl_bits[j] |= 0x20;
}
-void Sprite_PotionShop(int k) { // 85f633
+void Sprite_E9_PotionShop(int k) { // 85f633
switch(sprite_subtype2[k]) {
case 0: Sprite_MagicShopAssistant_Main(k); return;
case 1: Sprite_BagOfPowder(k); return;
@@ -7996,7 +7942,7 @@
sprite_delay_main[k] = GetRandomNumber() & 127;
}
-void SpritePrep_Moldorm_bounce(int k) { // 868f8a
+void SpritePrep_Moldorm(int k) { // 868f8a
if (Sprite_ReturnIfBossFinished(k))
return;
sprite_ignore_projectile[k]++;
@@ -8003,7 +7949,7 @@
Sprite_InitializedSegmented(k);
}
-void SpritePrep_Lanmolas_bounce(int k) { // 868f95
+void SpritePrep_Lanmolas(int k) { // 868f95
static const uint8 kLanmola_InitDelay[3] = {128, 192, 255};
if (Sprite_ReturnIfBossFinished(k))
@@ -10586,7 +10532,7 @@
if (Sprite_PrepOamCoordOrDoubleRet(k, &info))
return;
uint8 flags;
- sprite_oam_flags[k] = flags = overworld_palette_swap_flag ? sprite_oam_flags[k] | 0xe : sprite_oam_flags[k] & ~0xe;
+ sprite_oam_flags[k] = flags = palette_swap_flag ? sprite_oam_flags[k] | 0xe : sprite_oam_flags[k] & ~0xe;
uint8 r1 = sprite_B[k] >> 2 & 3;
oam_cur_ptr += 4, oam_ext_cur_ptr += 1;
@@ -10899,7 +10845,7 @@
}
}
-void Sprite_73_UncleAndPriest_bounce(int k) { // 86bfe0
+void Sprite_73_UncleAndPriest(int k) { // 86bfe0
switch (sprite_E[k]) {
case 0:
Sprite_Uncle(k);
@@ -10980,7 +10926,7 @@
}
}
-void Sprite_TutorialGuardOrBarrier_bounce(int k) { // 86bffe
+void Sprite_TutorialGuardOrBarrier(int k) { // 86bffe
if (sprite_type[k] == 0x40) {
Sprite_EvilBarrier(k);
return;
@@ -11013,7 +10959,7 @@
}
}
-void Sprite_F2_MedallionTablet_bounce(int k) { // 86c00d
+void Sprite_F2_MedallionTablet(int k) { // 86c00d
switch (sprite_subtype2[k]) {
case 0:
MedallionTablet_Main(k);
@@ -11024,7 +10970,7 @@
}
}
-void Sprite_33_RupeePull_bounce(int k) { // 86c017
+void Sprite_33_RupeePull(int k) { // 86c017
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
@@ -11046,7 +10992,7 @@
}
}
-void Sprite_14_ThievesTownGrate_bounce(int k) { // 86c01c
+void Sprite_14_ThievesTownGrate(int k) { // 86c01c
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
if (Sprite_ReturnIfInactive(k))
@@ -11079,7 +11025,7 @@
SpritePrep_Snitches(k);
}
-void Sprite_37_Waterfall_bounce(int k) { // 86c03a
+void Sprite_37_Waterfall(int k) { // 86c03a
switch (sprite_subtype2[k]) {
case 0: Waterfall(k); break;
case 1: Sprite_BatCrash(k); break;
@@ -11086,7 +11032,7 @@
}
}
-void Sprite_38_EyeStatue_bounce(int k) { // 86c03f
+void Sprite_38_EyeStatue(int k) { // 86c03f
if (!sprite_B[k]) {
PrepOamCoordsRet info;
Sprite_PrepOamCoord(k, &info);
@@ -11099,7 +11045,7 @@
}
}
-void Sprite_3A_MagicBat_bounce(int k) { // 86c044
+void Sprite_3A_MagicBat(int k) { // 86c044
if (sprite_head_dir[k]) {
Sprite_MadBatterBolt(k);
return;
@@ -11206,7 +11152,7 @@
}
}
-void Sprite_78_MrsSahasrahla_bounce(int k) { // 86c071
+void Sprite_78_MrsSahasrahla(int k) { // 86c071
ElderWife_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
@@ -11259,11 +11205,11 @@
HeartUpgrade_CheckIfAlreadyObtained(k);
}
-void Sprite_2D_TelepathicTile_bounce(int k) { // 86c0b2
+void Sprite_2D_TelepathicTile(int k) { // 86c0b2
assert(0);
}
-void Sprite_25_TalkingTree_bounce(int k) { // 86c0d5
+void Sprite_25_TalkingTree(int k) { // 86c0d5
switch (sprite_subtype2[k]) {
case 0: TalkingTree_Mouth(k); break;
case 1: TalkingTree_Eye(k); break;
@@ -13176,6 +13122,59 @@
}
void Uncle_Draw(int k) { // 8dd391
+ static const DrawMultipleData kUncleDraw_Table[48] = {
+ { 0, -10, 0x0e00, 2},
+ { 0, 0, 0x0c06, 2},
+ { 0, -10, 0x0e00, 2},
+ { 0, 0, 0x0c06, 2},
+ { 0, -10, 0x0e00, 2},
+ { 0, 0, 0x0c06, 2},
+ { 0, -10, 0x0e02, 2},
+ { 0, 0, 0x0c06, 2},
+ { 0, -10, 0x0e02, 2},
+ { 0, 0, 0x0c06, 2},
+ { 0, -10, 0x0e02, 2},
+ { 0, 0, 0x0c06, 2},
+ { -7, 2, 0x0d07, 2},
+ { -7, 2, 0x0d07, 2},
+ { 10, 12, 0x8d05, 0},
+ { 10, 4, 0x8d15, 0},
+ { 0, -10, 0x0e00, 2},
+ { 0, 0, 0x0c04, 2},
+ { -7, 1, 0x0d07, 2},
+ { -7, 1, 0x0d07, 2},
+ { 10, 13, 0x8d05, 0},
+ { 10, 5, 0x8d15, 0},
+ { 0, -9, 0x0e00, 2},
+ { 0, 1, 0x4c04, 2},
+ { -7, 8, 0x8d05, 0},
+ { 1, 8, 0x8d06, 0},
+ { 0, -10, 0x0e02, 2},
+ { -6, -1, 0x4d07, 2},
+ { 0, 0, 0x0c23, 2},
+ { 0, 0, 0x0c23, 2},
+ { -9, 7, 0x8d05, 0},
+ { -1, 7, 0x8d06, 0},
+ { 0, -9, 0x0e02, 2},
+ { -6, 0, 0x4d07, 2},
+ { 0, 1, 0x0c25, 2},
+ { 0, 1, 0x0c25, 2},
+ {-10, -17, 0x0d07, 2},
+ { 15, -12, 0x8d15, 0},
+ { 15, -4, 0x8d05, 0},
+ { 0, -28, 0x0e08, 2},
+ { -8, -19, 0x0c20, 2},
+ { 8, -19, 0x4c20, 2},
+ { 0, -28, 0x0e08, 2},
+ { 0, -28, 0x0e08, 2},
+ { -8, -19, 0x0c20, 2},
+ { 8, -19, 0x4c20, 2},
+ { -8, -19, 0x0c20, 2},
+ { 8, -19, 0x4c20, 2},
+ };
+ static const uint8 kUncleDraw_Dma3[8] = { 8, 8, 0, 0, 6, 6, 0, 0 };
+ static const uint8 kUncleDraw_Dma4[8] = { 0, 0, 0, 0, 4, 4, 0, 0x8b }; // wtf
+
Oam_AllocateFromRegionB(0x18);
const DrawMultipleData *src = &kUncleDraw_Table[sprite_D[k] * 12 + sprite_graphics[k] * 6];
@@ -13210,6 +13209,7 @@
{-8, 14, 0x840a, 2},
{ 8, 14, 0xc40a, 2},
};
+ sprite_graphics[k] = 0;
Sprite_DrawMultiplePlayerDeferred(k, &kBugNetKid_Dmd[sprite_graphics[k] * 6], 6, NULL);
}
@@ -22816,7 +22816,7 @@
}
sprite_obj_prio[k] |= kYellowStalfos_ObjPrio[sprite_ai_state[k]];
- YellowStalfos_Draw(k);
+ YellowStalfos_Draw(k);
if (Sprite_ReturnIfInactive(k))
return;
if (link_sword_type >= 3) {
@@ -25466,7 +25466,7 @@
sprite_graphics[k]++;
}
-void Sprite_SomariaPlatform(int k) { // 9ef6d4
+void Sprite_ED_SomariaPlatform(int k) { // 9ef6d4
switch(sprite_graphics[k]) {
case 0: {
SomariaPlatform_LocatePath(k);
--- a/sprite_main.h
+++ b/sprite_main.h
@@ -20,10 +20,10 @@
void Sprite_WishPond3(int k);
int Sprite_SpawnSmallSplash(int k);
void HeartUpgrade_CheckIfAlreadyObtained(int k);
-void Sprite_MovableMantleTrampoline(int k);
+void Sprite_EE_MovableMantle(int k);
void Sprite_GoodOrBadArcheryTarget(int k);
void ChainBallTrooper_Draw(int k);
-void Sprite_CannonTrooper(int k);
+void Sprite_6B_CannonTrooper(int k);
void Bee_PutInBottle(int k);
void Sprite_Wizzbeam(int k);
void Kiki_LyingInwait(int k);
@@ -37,7 +37,7 @@
bool Landmine_CheckDetonationFromHammer(int k);
void Sprite_DrawLargeWaterTurbulence(int k);
void Sprite_SpawnSparkleGarnish(int k);
-void Sprite_70_KingHelmasaurFireball_bounce(int k);
+void Sprite_70_KingHelmasaurFireball(int k);
void Sprite_66_WallCannonVerticalLeft(int k);
void Sprite_65_ArcheryGame(int k);
void ArcheryGame_Host(int k);
@@ -142,7 +142,7 @@
void Guard_AnimateHead(int k, int oam_offs, const PrepOamCoordsRet *poc);
void Guard_AnimateBody(int k, int oam_idx, const PrepOamCoordsRet *poc);
void Guard_AnimateWeapon(int k, const PrepOamCoordsRet *poc);
-void Sprite_45_UsainBolt(int k);
+void Sprite_45_HogSpearMan(int k);
void BoltGuard_TriggerChaseTheme(int k);
void Sprite_44_BluesainBolt(int k);
void PsychoTrooper_Draw(int k);
@@ -200,8 +200,8 @@
void Zelda_EnteringSanctuary(int k);
void Zelda_AtSanctuary(int k);
void SpritePrep_Mushroom(int k);
-void Sprite_Mushroom(int k);
-void Sprite_FakeSword(int k);
+void Sprite_E7_Mushroom(int k);
+void Sprite_E8_FakeSword(int k);
void FakeSword_Draw(int k);
void SpritePrep_HeartContainer(int k);
void Sprite_HeartContainer(int k);
@@ -222,7 +222,7 @@
void MagicShopAssistant_SpawnGreenCauldron(int k);
void MagicShopAssistant_SpawnBlueCauldron(int k);
void MagicShopAssistant_SpawnRedCauldron(int k);
-void Sprite_PotionShop(int k);
+void Sprite_E9_PotionShop(int k);
void Sprite_BagOfPowder(int k);
void MagicPowderItem_Draw(int k);
void Sprite_GreenCauldron(int k);
@@ -331,8 +331,8 @@
void SpritePrep_DesertStatue(int k);
void SpritePrep_DoNothingD(int k);
void SpritePrep_Octorok(int k);
-void SpritePrep_Moldorm_bounce(int k);
-void SpritePrep_Lanmolas_bounce(int k);
+void SpritePrep_Moldorm(int k);
+void SpritePrep_Lanmolas(int k);
void SpritePrep_BigSpike(int k);
void SpritePrep_SwimmingZora(int k);
void SpritePrep_Geldman(int k);
@@ -459,24 +459,24 @@
void SpritePrep_Hobo_SpawnFire(int k);
void Sprite_Hobo_Smoke(int k);
void Hobo_SpawnSmoke(int k);
-void Sprite_73_UncleAndPriest_bounce(int k);
+void Sprite_73_UncleAndPriest(int k);
void SpritePrep_UncleAndPriest_bounce(int k);
void SpritePrep_OldMan_bounce(int k);
-void Sprite_TutorialGuardOrBarrier_bounce(int k);
-void Sprite_F2_MedallionTablet_bounce(int k);
-void Sprite_33_RupeePull_bounce(int k);
-void Sprite_14_ThievesTownGrate_bounce(int k);
+void Sprite_TutorialGuardOrBarrier(int k);
+void Sprite_F2_MedallionTablet(int k);
+void Sprite_33_RupeePull(int k);
+void Sprite_14_ThievesTownGrate(int k);
void SpritePrep_Snitch_bounce_2(int k);
void SpritePrep_Snitch_bounce_3(int k);
-void Sprite_37_Waterfall_bounce(int k);
-void Sprite_38_EyeStatue_bounce(int k);
-void Sprite_3A_MagicBat_bounce(int k);
+void Sprite_37_Waterfall(int k);
+void Sprite_38_EyeStatue(int k);
+void Sprite_3A_MagicBat(int k);
void SpritePrep_Zelda_bounce(int k);
-void Sprite_78_MrsSahasrahla_bounce(int k);
+void Sprite_78_MrsSahasrahla(int k);
void Sprite_16_Elder_bounce(int k);
void SpritePrep_HeartPiece(int k);
-void Sprite_2D_TelepathicTile_bounce(int k);
-void Sprite_25_TalkingTree_bounce(int k);
+void Sprite_2D_TelepathicTile(int k);
+void Sprite_25_TalkingTree(int k);
void Sprite_1C_Statue(int k);
bool Statue_CheckForSwitch(int k);
void MovableStatue_Draw(int k);
@@ -939,7 +939,7 @@
void Sprite_Apple(int k);
void Sprite_BC_Drunkard(int k);
void SomariaPlatform_LocatePath(int k);
-void Sprite_SomariaPlatform(int k);
+void Sprite_ED_SomariaPlatform(int k);
void SomariaPlatformAndPipe_HandleMovement(int k);
uint8 SomariaPlatformAndPipe_CheckTile(int k);
void SomariaPlatform_Draw(int k);
--- a/tables/compile_resources.py
+++ b/tables/compile_resources.py
@@ -6,11 +6,9 @@
import tables
import compile_music
import array, hashlib, struct
+from functools import cache
+import sprite_sheets
-print_int_array = util.print_int_array
-
-PATH = ''
-
def flatten(xss):
return [x for xs in xss for x in xs]
@@ -19,7 +17,6 @@
assets = {}
-
def add_asset_uint8(name, data):
assert name not in assets
assets[name] = ('uint8', bytes(array.array('B', data)))
@@ -38,7 +35,7 @@
def print_map32_to_map16():
tab = {}
- for line in open(PATH + 'map32_to_map16.txt'):
+ for line in open('map32_to_map16.txt'):
line = line.strip()
x, xs = line.split(':', 1)
tab[int(x)] = [int(t) for t in xs.split(',')]
@@ -67,7 +64,7 @@
def print_dialogue():
new_r = []
offs = []
- for line in open(PATH + 'dialogue.txt'):
+ for line in open('dialogue.txt'):
line = line.strip('\n')
a, b = line.split(': ', 1)
index = int(a)
@@ -80,41 +77,6 @@
ROM = util.LoadedRom(sys.argv[1] if len(sys.argv) >= 2 else None)
-kCompSpritePtrs = [
- 0x10f000,0x10f600,0x10fc00,0x118200,0x118800,0x118e00,0x119400,0x119a00,
- 0x11a000,0x11a600,0x11ac00,0x11b200,0x14fffc,0x1585d4,0x158ab6,0x158fbe,
- 0x1593f8,0x1599a6,0x159f32,0x15a3d7,0x15a8f1,0x15aec6,0x15b418,0x15b947,
- 0x15bed0,0x15c449,0x15c975,0x15ce7c,0x15d394,0x15d8ac,0x15ddc0,0x15e34c,
- 0x15e8e8,0x15ee31,0x15f3a6,0x15f92d,0x15feba,0x1682ff,0x1688e0,0x168e41,
- 0x1692df,0x169883,0x169cd0,0x16a26e,0x16a275,0x16a787,0x16aa06,0x16ae9d,
- 0x16b3ff,0x16b87e,0x16be6b,0x16c13d,0x16c619,0x16cbbb,0x16d0f1,0x16d641,
- 0x16d95a,0x16dd99,0x16e278,0x16e760,0x16ed25,0x16f20f,0x16f6b7,0x16fa5f,
- 0x16fd29,0x1781cd,0x17868d,0x178b62,0x178fd5,0x179527,0x17994b,0x179ea7,
- 0x17a30e,0x17a805,0x17acf8,0x17b2a2,0x17b7f9,0x17bc93,0x17c237,0x17c78e,
- 0x17cd55,0x17d2bc,0x17d82f,0x17dcec,0x17e1cc,0x17e36b,0x17e842,0x17eb38,
- 0x17ed58,0x17f06c,0x17f4fd,0x17fa39,0x17ff86,0x18845c,0x1889a1,0x188d64,
- 0x18919d,0x189610,0x189857,0x189b24,0x189dd2,0x18a03f,0x18a4ed,0x18a7ba,
- 0x18aedf,0x18af0d,0x18b520,0x18b953,
-]
-
-kCompBgPtrs = [
- 0x11b800,0x11bce2,0x11c15f,0x11c675,0x11cb84,0x11cf4c,0x11d2ce,0x11d726,
- 0x11d9cf,0x11dec4,0x11e393,0x11e893,0x11ed7d,0x11f283,0x11f746,0x11fc21,
- 0x11fff2,0x128498,0x128a0e,0x128f30,0x129326,0x129804,0x129d5b,0x12a272,
- 0x12a6fe,0x12aa77,0x12ad83,0x12b167,0x12b51d,0x12b840,0x12bd54,0x12c1c9,
- 0x12c73d,0x12cc86,0x12d198,0x12d6b1,0x12db6a,0x12e0ea,0x12e6bd,0x12eb51,
- 0x12f135,0x12f6c5,0x12fc71,0x138129,0x138693,0x138bad,0x139117,0x139609,
- 0x139b21,0x13a074,0x13a619,0x13ab2b,0x13b00c,0x13b4f5,0x13b9eb,0x13bebf,
- 0x13c3ce,0x13c817,0x13cb68,0x13cfb5,0x13d460,0x13d8c2,0x13dd7a,0x13e266,
- 0x13e7af,0x13ece5,0x13f245,0x13f6f0,0x13fc30,0x1480e9,0x14863b,0x148a7c,
- 0x148f2a,0x149346,0x1497ed,0x149cc2,0x14a173,0x14a61d,0x14ab5d,0x14b083,
- 0x14b4bd,0x14b94e,0x14be0e,0x14c291,0x14c7ba,0x14cce4,0x14d1db,0x14d6bd,
- 0x14db77,0x14ded1,0x14e2ac,0x14e754,0x14ebae,0x14ef4e,0x14f309,0x14f6f4,
- 0x14fa55,0x14ff8c,0x14ff93,0x14ff9a,0x14ffa1,0x14ffa8,0x14ffaf,0x14ffb6,
- 0x14ffbd,0x14ffc4,0x14ffcb,0x14ffd2,0x14ffd9,0x14ffe0,0x14ffe7,0x14ffee,
- 0x14fff5,0x18b520,0x18b953,
-]
-
def compress_store(r):
rr = []
j, jend = 0, len(r)
@@ -135,19 +97,23 @@
return b''.join([struct.pack('I', i) for i in all_offs] + arr)
def print_images():
- lengths = b''
+ sprsheet = sprite_sheets.load_sprite_sheets()
+
all = []
- for i in range(12):
- all.append(bytes(ROM.get_bytes(kCompSpritePtrs[i], 0x600)))
- for i in range(12, 108):
- decomp, comp_len = util.decomp(kCompSpritePtrs[i], ROM.get_byte, False, True)
- all.append(bytes(ROM.get_bytes(kCompSpritePtrs[i], comp_len)))
+ for i in range(108):
+ if sprsheet != None and i < 103:
+ all.append(sprsheet.encode_sheet_in_snes_format(i))
+ elif i < 12:
+ all.append(bytes(ROM.get_bytes(tables.kCompSpritePtrs[i], 0x600)))
+ else:
+ decomp, comp_len = util.decomp(tables.kCompSpritePtrs[i], ROM.get_byte, False, True)
+ all.append(bytes(ROM.get_bytes(tables.kCompSpritePtrs[i], comp_len)))
add_asset_uint8('kSprGfx', pack_u32_arrays(all))
all = []
- for i in range(len(kCompBgPtrs)):
- decomp, comp_len = util.decomp(kCompBgPtrs[i], ROM.get_byte, False, True)
- all.append(bytes(ROM.get_bytes(kCompBgPtrs[i], comp_len)))
+ for i in range(len(tables.kCompBgPtrs)):
+ decomp, comp_len = util.decomp(tables.kCompBgPtrs[i], ROM.get_byte, False, True)
+ all.append(bytes(ROM.get_bytes(tables.kCompBgPtrs[i], comp_len)))
add_asset_uint8('kBgGfx', pack_u32_arrays(all))
@@ -193,13 +159,10 @@
add_asset_uint16('kOverworldMapPaletteData', ROM.get_words(0x8ADB27, 256))
-g_overworld_yaml_cache = {}
+@cache
def load_overworld_yaml(room):
- if room not in g_overworld_yaml_cache:
- g_overworld_yaml_cache[room] = yaml.safe_load(open(PATH+'overworld/overworld-%d.yaml' % room, 'r'))
- return g_overworld_yaml_cache[room]
+ return yaml.safe_load(open('overworld/overworld-%d.yaml' % room, 'r'))
-
def print_overworld():
r = []
for i in range(160):
@@ -465,11 +428,9 @@
add_asset_uint8('kDungMap_Tiles', pack_u32_arrays(r2))
-g_dungeon_yaml_cache = {}
+@cache
def load_dungeon_yaml(room):
- if room not in g_dungeon_yaml_cache:
- g_dungeon_yaml_cache[room] = yaml.safe_load(open(PATH+'dungeon/dungeon-%d.yaml' % room, 'r'))
- return g_dungeon_yaml_cache[room]
+ return yaml.safe_load(open('dungeon/dungeon-%d.yaml' % room, 'r'))
def print_dungeon_sprites():
offsets=[0 for i in range(320)]
@@ -700,7 +661,7 @@
data = []
offsets = [0] * 8
- default_yaml = yaml.safe_load(open(PATH+'dungeon/default_rooms.yaml', 'r'))
+ default_yaml = yaml.safe_load(open('dungeon/default_rooms.yaml', 'r'))
for i in range(len(offsets)):
offsets[i] = len(data)
print_layer(default_yaml['Default%d' % i], None)
@@ -709,7 +670,7 @@
data = []
offsets = [0] * 19
- overlay_yaml = yaml.safe_load(open(PATH+'dungeon/overlay_rooms.yaml', 'r'))
+ overlay_yaml = yaml.safe_load(open('dungeon/overlay_rooms.yaml', 'r'))
for i in range(len(offsets)):
offsets[i] = len(data)
print_layer(overlay_yaml['Overlay%d' % i], None)
@@ -746,7 +707,7 @@
add_asset_uint8('kBgTilemap_%d' % i, ROM.get_bytes(s, l))
def print_link_graphics():
- image = Image.open(PATH+'linksprite.png')
+ image = Image.open('linksprite.png')
data = image.tobytes()
def encode_4bit_sprite(data, offset, pitch):
b = [0] * 32
@@ -768,7 +729,6 @@
for song in ['intro', 'indoor', 'ending']:
name, data = compile_music.print_song(song)
add_asset_uint8(name, data)
-
def print_all():
print_sound_banks()
--- a/tables/extract_resources.py
+++ b/tables/extract_resources.py
@@ -2,31 +2,14 @@
import sys
import text_compression
import util
-from PIL import Image
+from util import get_bytes, get_words, get_byte, get_word, get_int8, get_int16
import tables
import yaml
import extract_music
import os
+import sprite_sheets
+from functools import cache
-PATH=''
-
-ROM = util.LoadedRom(sys.argv[1] if len(sys.argv) >= 2 else None)
-
-get_byte = ROM.get_byte
-get_word = ROM.get_word
-get_bytes = ROM.get_bytes
-
-def get_int8(ea):
- b = get_byte(ea)
- if b & 0x80: b -= 256
- return b
-
-def get_int16(ea):
- b = get_word(ea)
- if b & 0x8000: b -= 65536
- return b
-
-
def print_map32_to_map16(f):
for i in range(2218):
def getit(ea):
@@ -44,6 +27,7 @@
for j in range(4):
print('%5d: %4d, %4d, %4d, %4d' % (i * 4 + j, t0[j], t1[j], t2[j], t3[j]), file = f)
+@cache
def get_exit_datas():
r = {}
for i in range(79):
@@ -99,7 +83,6 @@
y['door'] = ['palace' if fdoor & 0x8000 else 'sanctuary', (fdoor & 0x7e) >> 1, (fdoor & 0x3f80) >> 7]
r.setdefault(screen_index, []).append(y)
return r
-EXIT_DATAS = get_exit_datas()
def get_loadoffs(c, d):
x, y = c[0] >> 4, c[1] >> 4
@@ -107,6 +90,7 @@
y += d[1]
return (y&0x3f) << 7 | (x&0x3f) << 1
+@cache
def get_ow_travel_infos():
r = {}
for i in range(17):
@@ -138,8 +122,8 @@
y['unk'] = [unk1, unk3]
r.setdefault(screen_index, []).append(y)
return r
-OW_TRAVEL_INFOS = get_ow_travel_infos()
+@cache
def get_ow_entrance_info():
r = {}
for i in range(129):
@@ -148,8 +132,8 @@
entrance_id = get_byte(0x9BBB73 + i)
r.setdefault(area, []).append({'index' : i, 'x' : (pos >> 1) & 0x3f, 'y' : (pos >> 7) & 0x3f, 'entrance_id' : entrance_id})
return r
-OW_ENTRANCE_INFO = get_ow_entrance_info()
+@cache
def get_hole_infos():
r = {}
for i in range(19):
@@ -158,7 +142,6 @@
entrance_id = get_byte(0x9BB84C + i)
r.setdefault(area, []).append({'x' : (pos >> 1) & 0x3f, 'y' : (pos >> 7) & 0x3f, 'entrance_id' : entrance_id})
return r
-HOLE_INFO = get_hole_infos()
def print_overworld_area(overworld_area):
is_small = get_bytes(0x82F88D, 192)
@@ -204,11 +187,12 @@
}
y['Header'] = header
- y['Travel'] = OW_TRAVEL_INFOS.get(overworld_area, [])
- y['Entrances'] = OW_ENTRANCE_INFO.get(overworld_area, [])
- if overworld_area in HOLE_INFO:
- y['Holes'] = HOLE_INFO[overworld_area]
- y['Exits'] = EXIT_DATAS.get(overworld_area, [])
+ y['Travel'] = get_ow_travel_infos().get(overworld_area, [])
+ y['Entrances'] = get_ow_entrance_info().get(overworld_area, [])
+ hole_infos = get_hole_infos()
+ if overworld_area in hole_infos:
+ y['Holes'] = hole_infos[overworld_area]
+ y['Exits'] = get_exit_datas().get(overworld_area, [])
y['Items'] = get_items()
def decode_sprites(base_addr):
@@ -247,10 +231,10 @@
}
s = yaml.dump(y, default_flow_style=None, sort_keys=False)
- open(PATH+'overworld/overworld-%d.yaml' % overworld_area, 'w').write(s)
+ open('overworld/overworld-%d.yaml' % overworld_area, 'w').write(s)
def print_all_overworld_areas():
- area_heads = ROM.get_bytes(0x82A5EC, 64)
+ area_heads = get_bytes(0x82A5EC, 64)
for i in range(160):
if i >= 128 or area_heads[i&63] == (i&63):
@@ -259,124 +243,6 @@
def print_dialogue():
text_compression.print_strings(open('dialogue.txt', 'w'), get_byte)
-def decomp_one_spr_2bit(data, offs, target, toffs, pitch):
- for y in range(8):
- d0, d1 = data[offs + y * 2], data[offs + y * 2 + 1]
- for x in range(8):
- t = ((d0 >> x) & 1) * 1 + ((d1 >> x) & 1) * 2
- target[toffs + y * pitch + (7 - x)] = t * 255 // 3
-
-def decomp_one_spr_3bit(data, offs, target, toffs, pitch):
- for y in range(8):
- d0, d1, d2 = data[offs + y * 2], data[offs + y * 2 + 1], data[offs + y + 16]
- for x in range(8):
- t = ((d0 >> x) & 1) * 1 + ((d1 >> x) & 1) * 2 + ((d2 >> x) & 1) * 4
- target[toffs + y * pitch + (7 - x)] = t * 255 // 7
-
-def decomp_one_spr_4bit(data, offs, target, toffs, pitch):
- for y in range(8):
- d0, d1, d2, d3 = data[offs + y * 2 + 0], data[offs + y * 2 + 1], data[offs + y * 2 + 16], data[offs + y * 2 + 17]
- for x in range(8):
- t = ((d0 >> x) & 1) * 1 + ((d1 >> x) & 1) * 2 + ((d2 >> x) & 1) * 4 + ((d3 >> x) & 1) * 8
- target[toffs + y * pitch + (7 - x)] = t
-
-def save_array_as_image(dimensions, data, fname, palette = None):
- img = Image.new('L' if palette == None else 'P', dimensions)
- img.putdata(data)
- if palette != None:
- img.putpalette(palette)
- img.save(fname)
-
-
-def decomp_save(data, fname, func, step, height=32, palette=None):
- dst=[0]*128*height
- for i in range(16*height//8):
- x = i % 16
- y = i // 16
- func(data, i * step, dst, x * 8 + y * 8 * 128, 128)
- save_array_as_image((128, height), dst, fname, palette)
-
-def convert_snes_palette(v):
- r=[]
- for x in v:
- r.extend(((x & 0x1f) << 3, (x >> 5 & 0x1f) << 3, (x >> 10 & 0x1f) << 3))
- return r
-
-
-def decode_link_sprites():
- kLinkPalette = [0, 0x7fff, 0x237e, 0x11b7, 0x369e, 0x14a5, 0x1ff, 0x1078, 0x599d, 0x3647, 0x3b68, 0xa4a, 0x12ef, 0x2a5c, 0x1571, 0x7a18]
- decomp_save(get_bytes(0x108000, 32768), PATH+'linksprite.png',
- decomp_one_spr_4bit, 32, 448, convert_snes_palette(kLinkPalette))
-
-def decomp_save_2bit(data, fname):
- dst=[0]*128*64
- for i in range(128):
- x = i % 16
- y = i // 16
- decomp_one_spr_2bit(data, i * 16, dst, x * 8 + y * 8 * 128, 128)
- img = Image.new("L", (128, 64))
- img.putdata(dst)
- img.save(fname)
-
-
-gfx_desc = {
- 0x00 : ('3bpp_np', 'Half slot images'),
-
- 0x01 : ('3bpp_np', 'Half slot images'),
- 0x02 : ('3bpp_np', 'Half slot images'),
- 0x03 : ('3bpp_np', 'Half slot images'),
- 0x04 : ('3bpp_np', 'Half slot images'),
- 0x05 : ('3bpp_np', 'Half slot images'),
-
- 0x06 : ('3bpp_np', 'common spr gfx'),
- 0x07 : ('3bpp_np', 'common spr gfx'),
-
- 0x08 : ('3bpp_np', 'Half slot images'),
- 0x09 : ('3bpp_np', 'Half slot images'),
- 0x0a : ('3bpp_np', 'Half slot images'),
- 0x0b : ('3bpp_np', 'Half slot images'),
-
- 88 : ('3bpp', 'Tagalong gfx'),
- 89 : ('3bpp', 'Tagalong gfx'),
-
- 90 : ('3bpp', 'animated sprites'),
- 91 : ('3bpp', 'animated sprites'),
- 92 : ('3bpp', 'animated sprites'),
- 93 : ('3bpp', 'animated sprites'),
- 94 : ('3bpp', 'sword/shield gfx'),
- 95 : ('3bpp', 'sword/shield gfx'),
-
-
- 100 : ('3bpp', 'Tagalong gfx'),
- 101 : ('3bpp', 'Tagalong gfx'),
- 102 : ('3bpp', 'Tagalong gfx'),
-
- 103 : ('2bpp', 'Attract images loaded to 7800'),
- 104 : ('2bpp', 'empty'),
- 105 : ('2bpp', 'hud icons loaded to 7xxx'),
- 106 : ('2bpp', 'hud icons loaded to 7xxx'),
- 107 : ('2bpp', 'hud icons loaded to 7xxx'),
-}
-
-def decomp_generic(k, mode, fname_add = "misc"):
- fname = 'img/%.3d - %s.png' % (k, fname_add)
- if mode == '2bpp':
- r = util.decomp(kCompSpritePtrs[k], get_byte, False)
- decomp_save_2bit(r, fname)
- elif mode == '3bpp_np':
- print(k)
- r = get_bytes(kCompSpritePtrs[k], 0x600)
- decomp_save(r, fname, decomp_one_spr_3bit, 24)
- elif mode== '3bpp':
- r = util.decomp(kCompSpritePtrs[k], get_byte, False)
- decomp_save(r, fname, decomp_one_spr_3bit, 24)
- else:
- assert 0
-
-if 0:
- for k, v in gfx_desc.items():
- decomp_generic(k, v[0])
-
def decode_room_objects(p):
objs = []
j = 0
@@ -418,6 +284,7 @@
doors.append({'type':get_byte(p + 1), 'pos' : get_byte(p) >> 4, 'dir' : A & 3})
p += 2
+@cache
def get_chest_info():
ea = 0x81e96e
all = {}
@@ -427,8 +294,6 @@
all.setdefault(room & 0x7fff, []).append((data, (room & 0x8000) != 0))
return all
-CHEST_INFO = get_chest_info()
-
def _get_entrance_info_one(i, set):
def get_exit_door(i):
x = get_word((0x82D724, 0x82DC32)[set] + i * 2)
@@ -498,7 +363,7 @@
y['associated_entrance_index'] = get_word(0x82DC40 + i * 2)
return room, y
-
+@cache
def get_entrance_info(set):
r = {}
for i in range(133 if set == 0 else 7):
@@ -506,9 +371,9 @@
r.setdefault(room, []).append(y)
return r
-ENTRANCE_INFO = get_entrance_info(0)
-STARTING_POINT_INFO = get_entrance_info(1)
-PITS_HURT_PLAYER = set(get_word(0x80990C + i * 2) for i in range(57))
+@cache
+def pits_hurt_player():
+ return set(get_word(0x80990C + i * 2) for i in range(57))
def print_room(room_index):
p = 0x1f8000 + room_index * 3
@@ -545,7 +410,7 @@
'stair3_dest' : [get_byte(p+13),p8 & 3],
'tele_msg' : get_word(0x87F61D+room_index*2),
'sort_sprites' : sort_sprites_setting,
- 'pits_hurt_player' : room_index in PITS_HURT_PLAYER
+ 'pits_hurt_player' : room_index in pits_hurt_player()
}
def get_sprites():
@@ -587,7 +452,7 @@
def get_chests():
r = []
- for data, big in CHEST_INFO.get(room_index, []):
+ for data, big in get_chest_info().get(room_index, []):
if big:
r.append('%d!' % data)
else:
@@ -598,9 +463,9 @@
secrets = get_secrets()
data = {'Header' : header, 'Sprites' : sprites, 'Secrets' : secrets, 'Chests' : get_chests()}
- data['Entrances'] = ENTRANCE_INFO.get(room_index, [])
- if room_index in STARTING_POINT_INFO:
- data['StartingPoints'] = STARTING_POINT_INFO[room_index]
+ data['Entrances'] = get_entrance_info(0).get(room_index, [])
+ if room_index in get_entrance_info(1):
+ data['StartingPoints'] = get_entrance_info(1)[room_index]
p = room_addr + 2
p, objs, doors = decode_room_objects(p)
@@ -615,13 +480,12 @@
data['Layer3'] = objs
if doors: data['Layer3.doors'] = doors
-
return yaml.dump(data, default_flow_style=None, sort_keys=False)
def print_all_dungeon_rooms():
for i in range(320):
s = print_room(i)
- open(PATH + 'dungeon/dungeon-%d.yaml' % i, 'w').write(s)
+ open( 'dungeon/dungeon-%d.yaml' % i, 'w').write(s)
def print_default_rooms():
def print_default_room(idx):
@@ -634,7 +498,7 @@
for i in range(8):
default_rooms['Default%d' % i] = print_default_room(i)
s = yaml.dump(default_rooms, default_flow_style=None, sort_keys=False)
- open(PATH + 'dungeon/default_rooms.yaml', 'w').write(s)
+ open('dungeon/default_rooms.yaml', 'w').write(s)
def print_overlay_rooms():
def print_overlay_room(idx):
@@ -647,21 +511,26 @@
for i in range(19):
default_rooms['Overlay%d' % i] = print_overlay_room(i)
s = yaml.dump(default_rooms, default_flow_style=None, sort_keys=False)
- open(PATH + 'dungeon/overlay_rooms.yaml', 'w').write(s)
+ open('dungeon/overlay_rooms.yaml', 'w').write(s)
-def print_all():
+def make_directories():
os.makedirs('img', exist_ok=True)
os.makedirs('overworld', exist_ok=True)
os.makedirs('dungeon', exist_ok=True)
os.makedirs('sound', exist_ok=True)
+
+def print_all_text_stuff():
print_all_overworld_areas()
- decode_link_sprites()
print_all_dungeon_rooms()
print_overlay_rooms()
print_default_rooms()
print_dialogue()
- print_map32_to_map16(open(PATH+'map32_to_map16.txt', 'w'))
- extract_music.extract_sound_data(ROM)
+ print_map32_to_map16(open('map32_to_map16.txt', 'w'))
+
+ROM = util.load_rom(sys.argv[1] if len(sys.argv) >= 2 else None)
-
-print_all()
+make_directories()
+print_all_text_stuff()
+extract_music.extract_sound_data(ROM)
+sprite_sheets.decode_link_sprites()
+sprite_sheets.decode_sprite_sheets()
--- /dev/null
+++ b/tables/sprite_sheet_info.py
@@ -1,0 +1,1547 @@
+class Entry:
+ def __init__(self, name, dungeon_or_ow, tileset_and_pal, ss_idx, matrix, pal_base):
+ self.name = name
+ self.dungeon_or_ow = dungeon_or_ow
+ self.tileset, self.palset_idx = tileset_and_pal
+ self.ss_idx = ss_idx
+ self.matrix = matrix
+ self.pal_base = pal_base
+
+entries = []
+def add(name, lw = None, dw = None, sheet = None, ow = None, dung = None, ss_1 = None, ss_2 = None, ss_3 = None, ss_4 = None, palette = None):
+ def doit(tileset_and_pal, dungeon_or_ow, suffix = ''):
+ all_chars = sorted(set("".join([ss.lower() for ss in (ss_1, ss_2, ss_3, ss_4) if ss != None])))
+ for ch in all_chars:
+ if ch == '\n' or ch == '.' or ch == 'o': continue
+ for ss_idx, ss in enumerate((ss_1, ss_2, ss_3, ss_4)):
+ if ss == None: continue
+ ss = ss.lower().replace('o', 'x')
+ matrix = ss.splitlines()[1:]
+ assert len(matrix) == 4 and all(len(m) == 16 for m in matrix), name
+ matrix2 = [[('x' if x == ch else '.') for x in m] for m in matrix]
+ if any('x' in m for m in matrix2):
+ entries.append(Entry(name + suffix, dungeon_or_ow, tileset_and_pal, ss_idx, matrix2, palette if ch == 'x' else int(ch)))
+
+ if lw and dw:
+ doit(lw, 0, ' - LW')
+ doit(dw, 1, ' - DW')
+ elif lw:
+ doit(lw, 0)
+ elif dw:
+ doit(dw, 1)
+ elif ow:
+ doit(ow, 0)
+ elif dung:
+ doit(dung, 2)
+ elif sheet:
+ doit(sheet, 3)
+
+
+add("00 - Raven", lw=(4, 3), dw=(23, 13), ss_4 = """
+....XXXXXX......
+....XXXXXX......
+................
+................""")
+
+add("01 - Vulture", ow=(8, 4), ss_3 = """
+XXXXXXXX........
+XXXXXXXX........
+................
+................""")
+
+add("04 - PullSwitch", dung=(6, 29), ss_4 = """
+..............XX
+..............XX
+..............XX
+..............XX""")
+
+add("07 - PullSwitch2", dung=(4, 0), ss_3 = """
+................
+................
+..XXXX..........
+..XXXX..........""")
+
+add("08 - Octorok", lw=(11, 3), dw=(22, 10), ss_3 = """
+XXXXXX..........
+XXXXXX..........
+XXXX.....XXX....
+XXXX....XXXXX...""")
+
+add("09 - Moldorm", dung=(12, 6), ss_3 = """
+5555555555666666
+5555555555666666
+5555555566666666
+5555555566666666""")
+
+add("0b - Chicken", lw=(6, 1), dw=(21, 16), ss_4 = """
+................
+................
+..........XXXX..
+..........XXXX..""")
+
+add("0d - Buzzblob", ow=(7, 6), ss_4 = """
+..........XXXXXX
+..........XXXXXX
+XXXXXX..........
+XXXX............""")
+
+add("0e - SnapDragon", ow=(19, 14), ss_1 = """
+................
+................
+........XXXX....
+........XXXXXXXX""", ss_3 = """
+............XXXX
+............XXXX
+..........XXXXXX
+..........XXXXXX""")
+
+add("0f - Octoballon", ow=(4, 3), ss_3 = """
+......XX....XX..
+......XX....XX..
+............XX..
+.............X..""")
+
+add("11 - Hinox", dw=(19, 14), ss_1 = """
+33333333....3333
+33333333....3333
+333333......3333
+333333..........""")
+
+add("12 - Moblin", ow=(19, 14), ss_3 = """
+XXXXXXXXXXXX....
+XXXXXXXXXXXX....
+XXXXXXXXXX......
+XXXXXXXXXX......""")
+
+add("13 - MiniHelmasaur", dung=(12, 26), ss_2 = """
+..............XX
+............X.XX
+....XXXXXXXXXXXX
+....XXXXXXXXXXXX""")
+
+add("15 - Antifairy", dung=(8, 10), ss_4 = """
+................
+................
+.1.1............
+................""")
+
+# Aginah is (16, 7)
+add("16 - Elder", dung=(16, 28), ss_3 = """
+................
+................
+XXXXXX..........
+XXXXXX..........""")
+
+add("17 - Hoarder", ow=(4, 3), ss_4 = """
+................
+................
+......XXXX......
+......XXXX......""")
+
+
+add("18 - MiniMoldorm", dung=(19, 13), ss_2 = """
+.............X..
+.............X..
+XXXX............
+XXXX............""")
+
+add("19 - Poe", lw=(3, 2), dw=(21, 16), ss_4 = """
+................
+................
+......XX........
+......XX........""")
+
+add("1a - Smithy", dung=(5, 30), ss_2 = """
+XXXXXX..........
+XXXXXX..........
+XXXXXX..........
+XXXXXX..........""")
+
+add("1a - Smithy", ow=(29, 0), ss_4 = """
+........XX......
+........XX......
+................
+................""")
+
+add("1c - Statue", dung=(17, 10), ss_4 = """
+XXX.............
+XX..............
+................
+................""")
+
+add("1e - CrystalSwitch", dung=(8, 15), ss_4 = """
+................
+................
+....11..........
+....11..........""")
+
+add("1f - SickKid", dung=(13, 21), ss_1 = """
+..........6666XX
+..........6666XX
+.......X......XX
+.......X......XX""")
+
+
+add("20 - Sluggula", dung=(29, 17), ss_3 = """
+XXXXXX..........
+XXXXXX..........
+xx........xxxxxx
+xx........xxxxxx""")
+
+
+add("21 - PushSwitch", dung=(17, 10), ss_4 = """
+..........xxxx..
+..........xxxx..
+..........xx....
+..........xx....""")
+
+add("22 - Ropa", ow=(19, 14), ss_1 = """
+........xxxx....
+........xxxx....
+......xx........
+......xx........""")
+
+# also used for blue bari
+add("23 - RedBari", dung=(8, 15), ss_1 = """
+................
+................
+xxxx..xx........
+xxxx..xx........""")
+
+add("25 - TalkingTree (S27)", dw=(19, 16), ss_4 = """
+................
+................
+........xx......
+........xx......""")
+
+add("25 - TalkingTree (S21)", dw=(21, 16), ss_1 = """
+................
+................
+........xx......
+........xx......""")
+
+add("26 - HardhatBeetle", dung=(19, 13), ss_2 = """
+xxxxxxxxxxxxx...
+xxxxxxxxxxxx....
+................
+................""")
+add("27 - Deadrock", ow=(16, 9), ss_4 = """
+..xxxxxx........
+..xxxxxx........
+..xxxx..........
+..xxxx..........""")
+add("28 - DarkWorldHintNpc", dung=(5, 7), ss_2 = """
+..........55....
+..........55....
+..............55
+..............55""")
+add("28 - DarkWorldHintNpc", dung=(5, 7), ss_1 = """
+................
+................
+....55..........
+....55..........""")
+add("28 - DarkWorldHintNpc", dung=(5, 7), ss_1 = """
+....44..........
+....44..........
+................
+................""")
+add("28 - DarkWorldHintNpc", dung=(7, 7), ss_1 = """
+..............55
+..............55
+..............55
+..............55""")
+add("28 - DarkWorldHintNpc", dung=(5, 28), ss_2 = """
+................
+................
+..........5555..
+..........5555..""")
+
+
+add("29 - Human/Woman", dung=(15, 35), ss_1 = """
+............xxxx
+............xxxx
+................
+................""", ss_4 = """
+..........xxxxxx
+..........xxxxxx
+................
+................""")
+
+add("29 - Human/Thief", dung=(40, 7), ss_1 = """
+xxxxxxxx..xx..xx
+xxxxxxxx..xx..xx
+xxxxxx......xx..
+xxxxxx......xx..""", palette = 7)
+
+
+add("29 - Human/Elder", dung=(15, 35), ss_3 = """
+....xxxxxx......
+....xxxxxx......
+..xx............
+..xx............""")
+
+add("2a - SweepingLady", ow=(6, 1), ss_3 = """
+..........xxxxxx
+..........xxxxxx
+................
+................""")
+
+add("2b - Hobo", ow=(12, 8), ss_3 = """
+........xxxx....
+........xxxx....
+......xxxxxxx...
+......xxxxxxx...""")
+
+add("2c - LumberJacks", ow=(26, 6), ss_1 = """
+..............xx
+..............xx
+................
+................""", ss_3 = """
+................
+................
+....xxxxxx......
+....xxxxxx....44""")
+
+add("2e - FluteKid - LW", lw=(15, 1), ss_3= """
+................
+................
+........xxxx...x
+........xxxx..xx""")
+
+
+add("2e - FluteKid - DW", dw=(17,11), ss_4 = """
+........xxxx00..
+........xxxx00..
+......xxxx..00..
+......xxxx..00..""", palette = 3)
+
+
+add("2f - MazeGameLady", ow=(6, 1), ss_4 = """
+xxxx............
+xxxx............
+xxxxxxxxxx......
+xxxxxxxxxx......""")
+
+add("30 - MazeGameGuy", ow=(6, 1), ss_1="""
+xxxx............
+xxxx............
+xx..............
+xx..............""")
+
+add("31 - FortuneTeller", dung=(5, 30), ss_1 = """
+..........xxxx..
+..........xxxx..
+..........x.x...
+................""", ss_2 = """
+................
+................
+......xxxx......
+......xxxx......""")
+
+add("32 - QuarrelBros", dung=(15,2), ss_1 = """
+....XX..XXXX....
+....XX..XXXX....
+................
+................""")
+
+add("34 - YoungSnitchLady", ow=(6,1), ss_1 = """
+................
+................
+....xxxxxx......
+....xxxxxx......""", ss_4 = """
+..xx............
+..xx............
+....xxxxxx......
+....xxxxxx......""")
+
+add("35 - InnKeeper", dung=(15,5), ss_4 = """
+....xxxxxxxxxxxx
+....xxxxxxxxxxxx
+..............xx
+..............xx""")
+
+add("36 - Witch", ow=(13, 6), ss_3 = """
+xxxxxx11........
+xxxxxx11........
+..............xx
+..............xx""")
+
+add("39 - Locksmith", ow=(10, 0), ss_4 = """
+................
+................
+..........xxxx..
+..........xxxx..""")
+
+add("3a - MagicBat", dung=(9, 32), ss_4 = """
+................
+................
+..........xxxx..
+..........xxxx.x""")
+
+add("3b - TreeTop", ow=(26, 6), ss_1 = """
+xxxxxxxxxx......
+xxxxxxxxxx......
+xxxxxxxxxxxx....
+xxxxxxxxxxxx....""", palette = 0)
+
+add("3c - TroughBoy", ow=(6, 1), ss_3 = """
+4444............
+4444............
+55........55....
+55........55....""")
+
+add("3d - OldSnitchLady", ow=(6, 1), ss_4 = """
+xxxx............
+xxxx............
+xxxxxxxxxx......
+xxxxxxxxxx......""")
+
+# rock crab is included in two sheets
+add("3e - RockCrab", ow=(10, 0), ss_4 = """
+................
+................
+......xxxx......
+......xxxx......""", palette = 0)
+
+add("3e - RockCrab (S16)", ow=(33, 0), ss_4 = """
+................
+................
+......xxxx......
+......xxxx......""", palette = 0)
+
+
+add("3f - PalaceGuard", ow=(2, 1), ss_1 = """
+xx..............
+xx..............
+......xxxxx.....
+......xxxxx.....""", palette = 4)
+
+add("3f - PalaceGuard", ow=(2, 1), ss_2 = """
+xxxxxxxx......xx
+xxxxxxxx......xx
+....xx..........
+....xx..........""")
+
+
+add("40 - ElectricBarrier", ow=(2, 1), ss_4 = """
+..........xxxx..
+..........xxxx..
+......xxxx......
+......xxxx......""")
+
+
+add("41 - Soldier", dung=(3, 0), ss_2 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""")
+
+add("41 - Soldier (DW)", dung=(36, 37), ss_2 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", ss_3 = """
+................
+................
+......xxxxxxxxx.
+......xxxxxxxxx.
+""")
+
+add("44 - Warrior", dung=(33, 38), ss_1 = """
+xxxxxx..........
+xxxxxx..........
+................
+................""")
+
+add("47 - GrassArcher", ow=(4, 3), ss_1 = """
+..xxxxxxxxxxxxxx
+..xxxxxxxxxxxxxx
+11xxxx..........
+11xxxx..........""")
+
+add("4a - RedBombKnight", ow=(1, 3), ss_1 = """
+xxxxxxxxxxxxxxx.
+xxxxxxxxxxxxxxx.
+..xx........xxxx
+..xx........xxx.""")
+
+add("4b - GreenKnifeGuard", ow=(2, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xx....xxxxxxxxxx
+xx....xxxxxxxxxx""")
+
+add("4c - Geldman", ow=(8, 4), ss_3 = """
+................
+................
+xxxxxxxx........
+xxxxxxxxx.......""")
+
+add("4d - Toppo", ow=(4, 3), ss_4 = """
+xxxx............
+xxxx............
+................
+................""")
+
+add("4e - Popo", dung=(8, 11), ss_2 = """
+xxxx............
+xxxx............
+................
+................""")
+
+add("51 - ArmosStatue", ow=(5, 7), ss_4 = """
+xx..............
+xx..............
+xx..............
+xx..............""", palette = 5)
+
+add("52 - ZoraKing", ow=(14, 8), ss_3 = """
+........2222....
+........2222....
+........2.......
+................""", ss_4 = """
+xxxx2222........
+xxxx2222........
+xxxx2222..xx....
+xxxx2222..xx....""")
+
+add("53 - ArmosKnight", dung=(9, 11), ss_4 = """
+xxxxxxxxxx......
+xxxxxxxxxx......
+xxxxxx..........
+xxxxxx..........""")
+
+add("54 - Lanmolas", dung=(11, 4), ss_4 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""")
+
+add("55 - FireBallZora", lw=(4, 3), dw=(22, 10), ss_3 = """
+........2222....
+........2222....
+....xxxx2.......
+....xxxx........""")
+
+add("56 - WalkingZora", ow=(14, 8), ss_4 = """
+........xxxxxxxx
+........xxxxxxxx
+........xx..xxxx
+........xx..xxxx""")
+
+add("57 - HyliaObstacle", ow=(8, 4), ss_3 = """
+..............xx
+..............xx
+..............xx
+..............xx""")
+
+add("58 - Crab", ow=(4, 3), ss_3 = """
+..............xx
+..............xx
+..............xx
+..............xx""")
+
+add("59 - LostWoodsBird", ow=(12, 1), ss_4 = """
+................
+................
+...xxxx.........
+...xxxx.........""")
+
+add("5a - LostWoodsSquirrel", ow=(12, 1), ss_4 = """
+.....xx.........
+.....xx.........
+.xx.............
+.xx.............""")
+
+add("5b - Spark", dung=(17, 10), ss_1 = """
+................
+................
+........xx......
+........xx......""", palette = 2)
+
+add("5d - Roller", dung=(30, 24), ss_3 = """
+........xxx.....
+........xxx.....
+................
+................""")
+
+add("5f - Roller", dung=(30, 24), ss_3 = """
+..............xx
+..............xx
+..............xx
+................""")
+
+add("61 - Beamos", dung=(10, 9), ss_2 = """
+........xx555...
+........xx551...
+........xx......
+........xx......""")
+
+add("62 - MasterSword", ow=(12, 1), ss_3 = """
+xxxxxxxx........
+xxxxxxxx........
+xxxxxx..........
+xxxxxx..........""", ss_4 = """
+...xx...........
+...xx...........
+x......xx.......
+x......xx.......""")
+
+add("63 - DebirandoPit", dung=(10, 9), ss_1 = """
+..xxxx..........
+..xxxx..........
+..xx....xxxx....
+..xx....xxxx....""")
+
+add("64 - Debirando", dung=(10, 9), ss_1 = """
+xx..............
+xx..............
+xx..............
+xx..............""", palette = 3)
+
+add("65 - ArcherGame", dung=(5, 30), ss_1 = """
+..xxxxxxxx......
+..xxxxxxxx......
+..xxxxxxxx.x....
+xxxxxxxxxxxx....""", palette = 4)
+
+add("66 - Cannon", dung=(10, 9), ss_1 = """
+..........xxxxxx
+..........xxxxxx
+....44........xx
+....44........xx""")
+
+add("6a - MorningStar", dung=(4, 1), ss_1 = """
+xxxxxxxxxxxxxxx.
+xxxxxxxxxxxxxxx.
+..xx......xxxxxx
+..xx......xxxxxx""", ss_2 = """
+......xxxxxxx.xO
+......xxxxxxx.xO
+xxxxxxxxxxx.....
+xxxxxxxxxxx.....""")
+
+add("6b - CannonTrooper", dung=(4, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxx.""")
+
+add("6d - Rat", dung=(1, 1), ss_3 = """
+......xxxxxxxxxx
+......xxxxxxxxxx
+..xx............
+..xx............""")
+
+add("6d - Rat (DW)", dung=(33, 35), ss_3 = """
+......xxxxxxxxxx
+......xxxxxxxxxx
+xxxx............
+xxxx............""")
+
+
+
+add("6e - Rope", dung=(1, 1), ss_3 = """
+................
+................
+....xxxxxxxx....
+....xxxxxxxx....""")
+
+add("6e - Rope (DW)", dung=(33, 35), ss_3 = """
+................
+................
+....xxxxxxxx....
+....xxxxxxxx....""")
+
+add("6f - Keese", dung=(1, 1), ss_3 = """
+xxxxxx..........
+xxxxxx..........
+................
+................""")
+
+add("6f - Keese (DW)", dung=(33, 35), ss_3 = """
+xxxxxx..........
+xxxxxx..........
+................
+................""")
+
+add("70 - KingHelmasaurFireball", dung=(21, 16), ss_3 = """
+................
+................
+............xx..
+............xx..""", ss_4 = """
+..........xxxx..
+..........xxxx.x
+................
+................""")
+
+add("71 - Leever", dung=(10, 9), ss_1 = """
+......xxxx......
+......xxxx......
+......xxx.......
+......xxx.......""")
+
+add("72 - FairyPond", dung=(7, 7), ss_4 = """
+........xxxxxxxx
+........xxxxxxxx
+................
+................""")
+
+add("72 - FairyPond", dung=(7, 34), ss_4 = """
+................
+................
+.........xxxxxxx
+.........xxxxxxx""")
+
+add("73 - UncleAndPriest", dung=(6, 29), ss_1 = """
+OOOOOOxxxxxxxxxx
+OOOOOOxxxxxxxxxx
+xxxxxxxxxxxx0000
+xxxxxxxxxxxx0000""", palette = 4)
+
+add("73 - UncleAndPriest", dung=(13, 21), ss_1 = """
+xxxxxxxxxx......
+xxxxxxxxxx......
+xxxxxxx.xxxxxx..
+xxxxxxx.xxxxxx..""", palette = 4)
+
+
+
+add("74 - RunningMan", ow=(6, 1), ss_1 = """
+................
+................
+..........xxxxxx
+..........xxxxxx""", ss_4 = """
+..........xxxxxx
+..........xxxxxx
+..............xx
+..............xx""")
+
+add("75 - BottleVendor", ow=(6, 1), ss_3 = """
+........xx......
+........xx......
+..xx........xx..
+..xx........xx..""")
+
+add("78 - MrsSahasrahla", dung=(5, 2), ss_1 = """
+................
+................
+........xx......
+........xx......""", ss_3 = """
+..............xx
+..............xx
+................
+................""")
+
+add("7a - Agahnim", dung=(24, 27), ss_1 = """
+............xxxx
+............xxxx
+............xxxx
+............xxxx""", ss_2 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", ss_4 = """
+xxxxxx..xxxx...x
+xxxxxx..xxxx..xx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 6)
+
+add("7b - AgahnimBalls", dung=(24, 27), ss_4 = """
+......xx....xxx.
+......xx....xx..
+................
+................""", palette = 2)
+
+add("7c - StalfosHead", dung=(8, 11), ss_1 = """
+xxxxxx..........
+xxxxxx..........
+................
+................""")
+
+add("7d - BigSpikeBlock", dung=(12, 16), ss_4 = """
+....xx..........
+....xx..........
+................
+................""")
+
+add("7e - FireBlade", dung=(17, 10), ss_1 = """
+................
+................
+........xx......
+........xx......""")
+
+add("81 - WaterBug", dung=(17, 10), ss_3 = """
+xxxxxx..........
+xxxxxx..........
+................
+................""")
+
+add("83 - GreenEyegore", dung=(10, 9), ss_3 = """
+..........xxxxxx
+..........xxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx..""")
+
+add("83 - GreenEyegore", dung=(8, 39), ss_2 = """
+....xxxx......xx
+....xxxx......xx
+..xxxxxx..xxxxxx
+..xxxxxx..xxxxxx""")
+
+add("85 - YellowStalfos", dung=(25, 15), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+....xx....xxxxxx
+....xx....xxxxxx""")
+
+add("86 - Kodongo", dung=(25, 6), ss_3 = """
+............xx..
+............xx..
+xxxxxxxxxxxxxx..
+xxxxxxxxxxxxxx..""")
+
+add("88 - Mothula", dung=(26, 14), ss_3 = """
+xxxxxxxxxx.xxxxx
+xxxxxxxxxx.xxxxx
+xxxxxxxxxx..xxxx
+xxxxxxxxxx..xxxx""")
+
+add("89 - MothulaRing", dung=(26, 14), ss_3 = """
+..........x.....
+..........x.....
+..........xx....
+..........xx....""")
+
+add("8a - SpikeBlock", dung=(8, 15), ss_4 = """
+................
+................
+......xx........
+......xx........""")
+
+add("8b - Gibdo", dung=(19, 13), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxx..........
+xxxxxx..........""")
+
+add("8c - Arrghus", dung=(20, 8), ss_3 = """
+xxxxxxxxxx......
+xxxxxxxxxx......
+xxxxxxxxxx......
+xxxxxxxxxx......""")
+
+add("8e - TerrorPin", dung=(25, 15), ss_3 = """
+..........xx..xx
+..........xx..xx
+..............xx
+..............xx""")
+
+add("8f - Blob", dung=(17, 8), ss_2 = """
+xxxxxx..........
+xxxxxx..........
+x...............
+x...............""")
+
+add("90 - WallMaster", dung=(19, 13), ss_3 = """
+................
+................
+......xxxxxxxxxx
+......xxxxxxxxxx""")
+
+add("91 - StalfosKnight", dung=(28, 19), ss_2 = """
+......xxxxxxxx..
+......xxxxxxxx..
+.xxxxxxxxxx.....
+.xxxxxxxxxx.....""")
+
+add("92 - HelmasaurKing", dung=(21, 16), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxx66
+xxxxxxxxxxxxxx66""", ss_4 = """
+6666666666xxxxxx
+6666666666xxxxxx
+6666xxOOOOOOOOOO
+6666xxOOOOOOOOOO""", palette = 5)
+
+add("93 - Bumper", dung=(12, 26), ss_4 = """
+................
+................
+............xx..
+............xx..""")
+
+add("94 - Pirogusu", dung=(17, 10), ss_3 = """
+.......x....xxxx
+.......x....xxxx
+..........xxxxxx
+..........xxxxxx""")
+
+add("95 - LaserEye", dung=(29, 17), ss_4 = """
+......xxxx......
+..2...xxxx......
+................
+...2............""")
+
+add("99 - Pengator", dung=(28, 19), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxx..........
+xxxxxx..........""")
+
+add("9a - Kyameron", dung=(17, 10), ss_3 = """
+......x.xxxx....
+......x.xxxx....
+xxxxxxxxxx......
+xxxxxxxxxx......""")
+
+add("9b - Wizzrobe", dung=(29, 17), ss_3 = """
+......xxxxxxxxxx
+......xxxxxxxxxx
+....xx..........
+..xxxx..........""")
+
+add("9b - Wizzrobe (DW)", dung=(36, 37), ss_3 = """
+......xxxxxxxxxx
+......xxxxxxxxxx
+....xx..........
+..xxxx..........""")
+
+
+
+add("9c - Babasu", dung=(17, 10), ss_2 = """
+..............xx
+..............xx
+...........xxxxx
+...........xxxxx""", palette=1)
+
+add("9e - HauntedGroveOstrich", ow=(15, 1), ss_3 = """
+xxxxxx..........
+xxxxxx..........
+xxxxxx..........
+xxxxxx..........""")
+
+add("9f - HauntedGroveRabbit", ow=(15, 1), ss_3 = """
+........xxxxxx..
+........xxxxxx..
+......xx........
+......xx........""")
+
+add("A0 - HauntedGroveBird", ow=(15, 1), ss_3 = """
+......xx......xx
+......xx......xx
+............xxx.
+............xx..""")
+
+add("A1 - Freezor", dung=(28, 19), ss_3 = """
+................
+................
+......xxxxxxxxxx
+......xxxxxxxxxx""")
+
+add("A2 - Kholdstare", dung=(22, 20), ss_3 = """
+xxxxxxxx....xx..
+xxxxxxxx....xx..
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""")
+
+add("A4 - FallingIce", dung=(22, 20), ss_3 = """
+........xxxx..xx
+........xxxx..xx
+................
+................""")
+
+add("A5 - Zazak", dung=(27, 23), ss_3 = """
+xxxxxxxxxx......
+xxxxxxxxxx......
+xxxxxxxxxx......
+xxxxxxxxxx......""")
+
+add("A8 - GreenZirro", ow=(19, 14), ss_4 = """
+xxxxxxxx........
+xxxxxxxx........
+xxxxxxxx........
+xxxxxxxx.......7""")
+
+add("AA - Pikit", ow=(19, 14), ss_4 = """
+........xxxxxxxx
+........xxxxxxxx
+..........xxxxx.
+..........xxxxx.""")
+
+add("AD - OldMan", dung=(1, 7), ss_3 = """
+................
+................
+............xxxx
+............xxxx""")
+
+
+add("B4 - PurpleChest", ow=(21, 16), ss_1 = """
+................
+................
+..............xx
+..............xx""", ss_4 = """
+................
+................
+..............xx
+..............xx""")
+
+add("B5 - BombShop", dung=(5, 31), ss_2 = """
+........xx..xxxx
+........xx..xx44
+................
+................""", palette = 1)
+
+add("B6 - Kiki", ow=(23, 13), ss_4 = """
+..........xxx.xx
+..........xxxxxx
+............xxxx
+............xxxx""")
+
+add("B9 - BullyAndPinkBall", dw=(20, 12), ss_4 = """
+....xx..........
+....xx..........
+xxxx............
+xxxx............""", palette = 6)
+
+add("B9 - BullyAndPinkBall", dw=(20, 12), ss_4 = """
+xxxx............
+xxxx............
+................
+................""")
+
+add("BB - Shopkeeper", dung=(5, 7), ss_1 = """
+xxxx............
+xxxx............
+xxxx............
+xxxx............""", palette = 5)
+
+add("BB - Shopkeeper", dung=(5, 7), ss_4 = """
+11..22......4422
+11..22......4422
+........22......
+........22......""")
+
+add("BB - Shopkeeper", dung=(15, 31), ss_2 = """
+......xx........
+......xx........
+................
+................""", palette = 6)
+
+add("BB - Shopkeeper", dung=(40, 5), ss_1 = """
+xxxxxxxx..xx..xx
+xxxxxxxx..xx..xx
+xxxxxx......xx..
+xxxxxx......xx..""", palette = 6)
+
+add("BB - Shopkeeper", dung=(15, 5), ss_1 = """
+xxxx............
+xxxx............
+xx..............
+xx..............""", palette = 6)
+
+add("BB - Shopkeeper", dung=(42, 32), ss_1 = """
+xxxxxxxx..xx..xx
+xxxxxxxx..xx..xx
+xxxxxx..........
+xxxxxx..........""", palette = 6)
+
+add("BC - Drunkard", dung=(15, 5), ss_1 = """
+......xx........
+......xx........
+..xx............
+..xx............""", ss_3 = """
+................
+................
+..............xx
+................""", palette = 4)
+
+add("BD - Viterous", dung=(22, 18), ss_4 = """
+xxxxxxxxxxxx....
+xxxxxxxxxxxx....
+xxxxxxxxxxxx....
+xxxxxxxxxxxx....""")
+
+add("BF - ViterousLightning", dung=(22, 18), ss_4 = """
+............xxxx
+............xxxx
+............xxxx
+............xxxx""")
+
+add("C0 - Catfish", ow=(22, 10), ss_3 = """
+......xxxxxxxxx.
+......xxxxxxxxx.
+........x...xxx.
+.............xx.""")
+
+add("C1 - CutsceneAgahnim", dung=(18, 12), ss_1 = """
+xxxxxx..........
+xxxxxx..........
+xxxxxxxx........
+xxxxxxx.........""", ss_3 = """
+xxxx............
+xxxx............
+xxxx............
+xxxx............""", ss_4 = """
+..............2.
+...............x
+............xxxx
+............xxxx""", palette = 5)
+
+add("C3 - Gibo", dung=(27, 23), ss_3 = """
+..........xxxxxx
+..........xxxxxx
+..........xxxxxx
+..........xxxxxx""")
+
+add("C7 - Pokey", dung=(30, 24), ss_3 = """
+xxxx............
+xxxx............
+xxxx............
+xxxx............""")
+
+add("C8 - BigFairy", dung=(7, 7), ss_3 = """
+..........xxxxxx
+..........xxxxxx
+..........xxxxxx
+..........xxxxxx""")
+
+add("C9 - Tektite", dw=(5, 7), ss_4 = """
+........xxxx....
+........xxxx....
+..........xx....
+..........xx....""", palette = 4)
+
+add("CA - ChainChomp", dung=(30, 24), ss_3 = """
+......xx...xxx..
+......xx....xx..
+......xxxxxx....
+......xxxxxx....""")
+
+add("CB - Trinexx", dung=(23, 25), ss_1 = """
+xxxx55xx55xxxxXX
+xxxx55xx55xxxxXX
+xxxx55xxxxxxxxXX
+xxxx55xxxxxxxxXX""", ss_4 = """
+xxxxxxXXXXXXXXXX
+xxxxxxXXXXXXXXXX
+xxxxxxxxxxXXXXxx
+xxxxxxxxxxXXXXxx""")
+
+add("CE - Blind", dung=(32, 23), ss_3 = """
+xxxxxxxxxxxxxx66
+xxxxxxxxxxxxxx66
+666666xxxxxx6666
+666666xxxxxx6666""", palette = 5)
+
+add("CF - Swamola", ow=(22, 15), ss_4 = """
+xxxx............
+xxxx............
+xxxxxxxxxxxx....
+xxxxxxxxxxxx....""")
+
+add("D0 - Lynel", ow=(20, 12), ss_4 = """
+......xxxxxxxxxx
+......xxxxxxxxxx
+....xxxxxxxxxxxx
+....xxxxxxxxxxxx""")
+
+add("D5 - DigGameGuy", ow=(27, 18), ss_2 = """
+xxxxxxx.........
+xxxxxxx.........
+................
+................""", palette = 5)
+
+add("D6 - Ganon", dung=(34, 33), ss_2 = """
+....xx..........
+....xx..........
+xxxxxx..........
+xxxxxx..........""", palette = 4)
+
+add("D6 - Ganon", dung=(34, 33), ss_1 = """
+xx5555xxxxxxxx55
+xx5555xxxxxxxx55
+xx5555xxxxxxxxxx
+xx5555xxxxxxxxxx""", ss_2 = """
+xxxx..xxxxxxxx55
+xxxx..xxxxxxxx55
+......xxxxxxxx55
+......xxxxxxxx55""", ss_3 = """
+xxxx55xxxxxxxxxx
+xxxx55xxxxxxxxxx
+xxxx55xxxxxxxxxx
+xxxx55xxxxxxxxxx""", ss_4 = """
+xxxxxx5555xxxx55
+xxxxxx5555xxxx55
+xxxxxx5555xxxx55
+xxxxxx5555xxxx55""", palette = 6)
+
+add("E7 - Mushroom", ow=(7, 5), ss_4 = """
+................
+................
+..............xx
+..............xx""", palette = 3)
+
+add("E8 - FakeSword", ow=(7, 5), ss_4 = """
+................
+................
+................
+....xx..........""")
+
+add("E9 - PotionShop", dung=(5, 5), ss_4 = """
+................
+................
+......xx........
+......xx........""", palette = 2)
+
+add("ED - SomariaPlatform", dung=(30, 24), ss_3 = """
+................
+................
+............XX..
+............XX..""")
+
+add("EE - MovableMantle", dung=(3, 0), ss_1 = """
+............xxxx
+............xxxx
+............xxxx
+............xxxx""")
+
+add("F2 - MedallionTablet", ow=(8, 4), ss_3 = """
+..........xxxx..
+..........xxxx..
+..........xxxx..
+..........xxxx..""")
+
+add("F4 - FallingRocks", ow=(5, 7), ss_4 = """
+............xxxx
+............xxxx
+............xxxx
+............xxxx""")
+
+add("XX - Unknown Sheet 00", sheet=(0, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 01", sheet=(1, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 02", sheet=(2, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 03", sheet=(3, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 04", sheet=(4, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 05", sheet=(5, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 06", sheet=(6, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 07", sheet=(7, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 08", sheet=(8, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 09", sheet=(9, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 10", sheet=(10, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 11", sheet=(11, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 14", ow=(37, 1), ss_1 = """
+........xx..xx..
+........xx..xx..
+........xxxx..xx
+........xxxx..xx""", palette = 4)
+
+
+add("XX - Unknown Sheet 15", ow=(26, 1), ss_1 = """
+..........xxxx..
+..........xxxx..
+............xxxx
+............xxxx""", palette = 4)
+
+
+add("XX - Unknown Sheet 21", ow=(21, 1), ss_1 = """
+............xx..
+............xx..
+................
+................""", palette = 4)
+
+add("XX - Unknown Sheet 27", ow=(25, 1), ss_4 = """
+................
+................
+...............x
+................""", palette = 4)
+
+add("XX - Unknown Sheet 37", ow=(93, 1), ss_3 = """
+................
+................
+..xx..xxxx......
+......xxxx......""", palette = 4)
+
+
+add("XX - Unknown Sheet 39", ow=(94, 1), ss_3 = """
+....xx..........
+....xx.....x....
+....xx..........
+....xx........xx""", palette = 4)
+
+add("XX - Unknown Sheet 41", dung=(36, 1), ss_3 = """
+xxxxxx..........
+xxxxxx..........
+xxxx...........x
+xx.............x""", palette = 4)
+
+
+add("XX - Unknown Sheet 42", ow=(107, 1), ss_3 = """
+.......xxx......
+.......xxx......
+................
+................""", palette = 4)
+
+add("XX - Unknown Sheet 43", dung=(16, 1), ss_4 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 44", ow=(72, 1), ss_2 = """
+.............x..
+.............x..
+xx..............
+xx..............""", palette = 4)
+
+add("XX - Unknown Sheet 45", ow=(45, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 46", ow=(73, 1), ss_3 = """
+xxxxxxxxxx......
+xxxxxxxxxx......
+................
+..............xx""", palette = 4)
+
+add("XX - Intro Sheet 50", sheet=(50, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Ending Sheet 52", sheet=(52, 1), ss_2 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Ending Sheet 53", sheet=(53, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 54", ow=(40, 1), ss_4 = """
+xxx....x........
+xxx....x........
+................
+................""", palette = 4)
+
+add("XX - Unknown Sheet 55", ow=(12, 1), ss_3 = """
+............xxxx
+............xxxx
+.............xxx
+.............xxx""", palette = 4)
+
+add("XX - Unknown Sheet 72", ow=(2, 1), ss_1 = """
+................
+................
+...........xxxxx
+...........xxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 75", ow=(27, 1), ss_1 = """
+................
+................
+.............x..
+............xx..""", palette = 4)
+
+
+add("XX - Unknown Sheet 76", ow=(13, 1), ss_3 = """
+..............xx
+..............xx
+..........xx....
+..........xx....""", palette = 4)
+
+add("XX - Unknown Sheet 82", dung=(19, 1), ss_4 = """
+xxxx......xxxx..
+xx.x......xxxx..
+x.x.....xxxx....
+xxx.....xxxx....""", palette = 4)
+
+add("XX - Unknown Sheet 83", dung=(38, 1), ss_4 = """
+...xxxxxxx....xx
+..xxxxxxxx....xx
+xxxxxxxxxx..xxxx
+xxxxxxxxxx..xxxx""", palette = 4)
+
+add("XX - Unknown Sheet 84", sheet=(84, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 85", dung=(63, 1), ss_1 = """
+......xxxxxx....
+......xxxxxx....
+........xxxx....
+.......xxxxx....""", palette = 4)
+
+add("XX - Map Sheet 86", sheet=(86, 1), ss_2 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Map Sheet 87", sheet=(87, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 88", sheet=(88, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Tagalong S89", sheet=(89, 1), ss_4 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 90", dung=(5, 1), ss_4 = """
+..xx..xxxxxx....
+..xx..xxxxxx....
+xxxxxx....xxxxxx
+xxxxxx....xxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 91", sheet=(91, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 92", sheet=(92, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 93", ow=(43, 1), ss_3 = """
+xxxxxxxxxxxx....
+xxxxxxxxxxxx....
+xxxxxxxxxxxx....
+xxxxxxxxxxxx....""", palette = 4)
+
+add("XX - Unknown Sheet 94", sheet=(94, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 95", sheet=(95, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Unknown Sheet 96", sheet=(96, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Map Sheet 97", sheet=(97, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Map Sheet 98", sheet=(98, 1), ss_2 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Map Sheet 99", sheet=(99, 1), ss_3 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Tagalong S100", sheet=(100, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+add("XX - Tagalong S101", sheet=(101, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
+
+
+add("XX - Tagalong S102", sheet=(102, 1), ss_1 = """
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxx""", palette = 4)
--- /dev/null
+++ b/tables/sprite_sheets.py
@@ -1,0 +1,503 @@
+from PIL import Image
+import sprite_sheet_info
+import util
+from util import get_bytes, get_words, get_byte
+import array
+import tables
+from functools import cache
+
+def save_as_png(dimensions, data, fname, palette = None):
+ img = Image.new('L' if palette == None else 'P', dimensions)
+ img.putdata(data)
+ if palette != None:
+ img.putpalette(palette)
+ img.save(fname)
+
+def save_as_24bpp_png(dimensions, data, fname):
+ img = Image.new("RGB", dimensions)
+ img.putdata(data)
+ img.save(fname)
+
+@cache
+def decode_2bit_tileset(tileset):
+ data = util.decomp(tables.kCompSpritePtrs[tileset], get_byte, False)
+ assert len(data) == 0x400
+ height = 32
+ dst = bytearray(128*height)
+ def decode_2bit(offs, toffs):
+ for y in range(8):
+ d0, d1 = data[offs + y * 2], data[offs + y * 2 + 1]
+ for x in range(8):
+ t = ((d0 >> x) & 1) * 1 + ((d1 >> x) & 1) * 2
+ dst[toffs + y * 128 + (7 - x)] = t * 255 // 3
+ for i in range(16*height//8):
+ x = i % 16
+ y = i // 16
+ decode_2bit(i * 16, x * 8 + y * 8 * 128)
+ return dst
+
+def is_high_3bit_tileset(tileset):
+ # is 0x5c, 0x5e, 0x5f included or not?
+ return tileset in (0x52, 0x53, 0x5a, 0x5b, 0x5c, 0x5e, 0x5f)
+
+def get_unpacked_snes_tileset(tileset):
+ if tileset < 12:
+ return get_bytes(tables.kCompSpritePtrs[tileset], 0x600)
+ else:
+ return util.decomp(tables.kCompSpritePtrs[tileset], get_byte, False)
+
+@cache
+def decode_3bit_tileset(tileset):
+ data = get_unpacked_snes_tileset(tileset)
+ assert len(data) == 0x600
+ base = 8 if is_high_3bit_tileset(tileset) else 0
+ height = 32
+ dst = bytearray(128*height)
+ def decode_3bit(offs, toffs):
+ for y in range(8):
+ d0, d1, d2 = data[offs + y * 2], data[offs + y * 2 + 1], data[offs + y + 16]
+ for x in range(8):
+ t = ((d0 >> x) & 1) * 1 + ((d1 >> x) & 1) * 2 + ((d2 >> x) & 1) * 4
+ dst[toffs + y * 128 + (7 - x)] = base + t
+ for i in range(16*height//8):
+ x, y = i % 16, i // 16
+ decode_3bit(i * 24, x * 8 + y * 8 * 128)
+ return dst
+
+def decode_4bit_tileset_link():
+ height = 448
+ data = get_bytes(0x108000, 0x800 * height // 32) # only link sprites for now
+ dst = bytearray(128*height)
+ def decode_4bit(offs, toffs):
+ for y in range(8):
+ d0, d1, d2, d3 = data[offs + y * 2 + 0], data[offs + y * 2 + 1], data[offs + y * 2 + 16], data[offs + y * 2 + 17]
+ for x in range(8):
+ t = ((d0 >> x) & 1) * 1 + ((d1 >> x) & 1) * 2 + ((d2 >> x) & 1) * 4 + ((d3 >> x) & 1) * 8
+ dst[toffs + y * 128 + (7 - x)] = t
+ for i in range(16*height//8):
+ x, y = i % 16, i // 16
+ decode_4bit(i * 32, x * 8 + y * 8 * 128)
+ return dst
+
+def convert_snes_palette(v):
+ rr=bytearray()
+ for x in v:
+ r, g, b = x & 0x1f, x >> 5 & 0x1f, x >> 10 & 0x1f
+ rr.extend((r << 3 | r >> 2, g << 3 | g >> 2, b << 3 | b >> 2))
+ return rr
+
+def convert_int24_palette_to_bytes(v):
+ rr=bytearray()
+ for x in v:
+ rr.extend((x & 0xff, x >> 8 & 0xff, x >> 16 & 0xff))
+ return rr
+
+def convert_snes_palette_to_int(v):
+ rr=[]
+ for x in v:
+ r, g, b = x & 0x1f, x >> 5 & 0x1f, x >> 10 & 0x1f
+ rr.append((r << 3 | r >> 2) | (g << 3 | g >> 2) << 8 | (b << 3 | b >> 2) << 16)
+ return rr
+
+def decode_link_sprites():
+ kLinkPalette = [0, 0x7fff, 0x237e, 0x11b7, 0x369e, 0x14a5, 0x1ff, 0x1078, 0x599d, 0x3647, 0x3b68, 0xa4a, 0x12ef, 0x2a5c, 0x1571, 0x7a18]
+ save_as_png((128, 448), decode_4bit_tileset_link(), 'linksprite.png', convert_snes_palette(kLinkPalette))
+
+# Returns the dungeon palette for the specified palette index
+# 0 = lightworld, 1 = darkworld, 2 = dungeon
+@cache
+def get_palette_subidx(palset_idx, dungeon_or_ow, which_palette):
+ spmain = 1 if (dungeon_or_ow == 1) else 0
+ if dungeon_or_ow == 2:
+ main, sp0l, sp5l, sp6l = tables.kDungPalinfos[palset_idx]
+ sp0r = (main // 2) + 11
+ sp6r = 10
+ else:
+ sp5l, sp6l = tables.kOwSprPalInfo[palset_idx * 2 : palset_idx * 2 + 2]
+ sp0l = 3 if dungeon_or_ow == 1 else 1
+ sp0r = 9 if dungeon_or_ow == 1 else 7
+ sp6r = 8 if dungeon_or_ow == 1 else 6
+ pal_defs = (sp0l, sp0r,
+ spmain, None, spmain, None, spmain, None, None, None,
+ sp5l, None,
+ sp6l, sp6r,
+ None, None)
+ return pal_defs[which_palette]
+
+@cache
+def get_palette_subset(pal_idx, j):
+ if j == None: j = 0
+ pal = [0] * 7
+ if pal_idx == 0: # 0
+ kPalette_SpriteAux3 = get_words(0x9BD39E, 84)
+ return kPalette_SpriteAux3[j * 7 : j * 7 + 7]
+ if pal_idx == 1: # 0R
+ if j < 11:
+ kPalette_MiscSprite = get_words(0x9BD446, 77)
+ return kPalette_MiscSprite[j * 7 : j * 7 + 7]
+ else:
+ kPalette_DungBgMain = get_words(0x9BD734, 1800)
+ return kPalette_DungBgMain[(j - 11) * 90 : (j - 11) * 90 + 7]
+ if pal_idx in (2, 3, 4, 5, 6, 7, 8, 9):
+ o = j * 60 + ((pal_idx - 2) >> 1) * 15 + (pal_idx & 1) * 8
+ kPalette_MainSpr = get_words(0x9BD218, 120)
+ return kPalette_MainSpr[o : o + 7]
+ if pal_idx in (10, 12):
+ kPalette_SpriteAux1 = get_words(0x9BD4E0, 168)
+ return kPalette_SpriteAux1[j * 7 : j * 7 + 7]
+ assert pal_idx != 11
+ if pal_idx == 13:
+ kPalette_MiscSprite = get_words(0x9BD446, 77)
+ return kPalette_MiscSprite[j * 7 : j * 7 + 7]
+ elif pal_idx == 14:
+ kPalette_ArmorAndGloves = get_words(0x9BD308, 75)
+ return kPalette_ArmorAndGloves[1:8]
+ elif pal_idx == 15:
+ kPalette_ArmorAndGloves = get_words(0x9BD308, 75)
+ return kPalette_ArmorAndGloves[9:16]
+
+@cache
+def get_full_palette(pal_idx, pal_subidx):
+ rv = []
+ if pal_idx & 1:
+ rv.extend([0x00fe00] * 9)
+ else:
+ rv.extend([0x00fe00] * 1)
+ rv.extend(convert_snes_palette_to_int(get_palette_subset(pal_idx, pal_subidx)))
+ rv += [0xe000e0] * (256 - len(rv))
+ # change the transparent to teal #008080
+ for i in range(0, 128, 8):
+ rv[i] = 0x808000
+ rv[252] = 0xc0c0c0 # palette text
+ rv[253] = 0xf0f0f0 # unallocated
+ rv[254] = 0x404040 # lines
+ rv[255] = 0xe0e0e0 # bg
+ return rv
+
+@cache
+def get_font_3x5():
+ return Image.open('../other/3x5_font.png').tobytes()
+
+def draw_letter3x5(dst, dst_pitch, dx, dy, ch, color):
+ font = get_font_3x5()
+ dst_offs = dy * dst_pitch + dx
+ src_offs = (ord(ch) & 31) * 4 + (ord(ch) // 32) * 6 * 128
+ for y in range(6):
+ for x in range(3):
+ if font[src_offs + y * 128 + x] == 0:
+ dst[dst_offs + y * dst_pitch + x] = color
+
+def draw_string3x5(dst, dst_pitch, dx, dy, s, color):
+ for ch in s:
+ draw_letter3x5(dst, dst_pitch, dx, dy, ch, color)
+ dx += 4
+
+def convert_to_24bpp(data, palette):
+ out = [0] * len(data)
+ for i in range(len(data)):
+ out[i] = palette[data[i]]
+ return out
+
+def concat_byte_arrays(ar):
+ r = bytearray()
+ for a in ar:
+ r += a
+ return r
+
+def fixup_sprite_set_entry(e, e_prev):
+ sprite_index = int(e.name[:2], 16) if e.name[0] != 'X' else 10000
+
+ if e.dungeon_or_ow != 3:
+ e.tileset = tables.kSpriteTilesets[e.tileset + (64 if e.dungeon_or_ow == 2 else 0)][e.ss_idx]
+ e.high_palette = is_high_3bit_tileset(e.tileset)
+ e.skip_header = False
+ if e.pal_base == None:
+ if sprite_index < len(tables.kSpriteInit_Flags3):
+ e.pal_base = (tables.kSpriteInit_Flags3[sprite_index] >> 1) & 7
+ else:
+ e.pal_base = 4 # just default to some palette
+
+ e.pal_idx = e.pal_base * 2 + e.high_palette
+ e.pal_subidx = get_palette_subidx(e.palset_idx, e.dungeon_or_ow, e.pal_idx)
+
+ if e_prev != None and e_prev.name == e.name and e_prev.pal_idx == e.pal_idx and e_prev.pal_subidx == e.pal_subidx:
+ e.skip_header = True
+
+ # the (pal_idx, pal_subidx) tuple identifies the palette
+ e.encoded_id = e.pal_base | e.tileset << 3 | e.skip_header << 10 | (e.pal_subidx or 0) << 11
+ e.encoded_id = e.encoded_id << 8 | ((e.encoded_id + 41) % 255)
+
+
+BIGW = 148
+def save_sprite_set_entry(finaldst, e, master_tilesheets = None):
+ empty_253 = [253] * 8
+ def fill_with_empty(dst, dst_offs):
+ for y in range(8):
+ o = dst_offs + y * BIGW
+ dst[o : o + 8] = empty_253
+
+ def copy_8x8(dst, dst_offs, src, src_offs, base):
+ for y in range(8):
+ for x in range(8):
+ dst[dst_offs + y * BIGW + x] = src[src_offs + y * 128 + x] + base
+
+ def hline(dst, x1, x2, y, color):
+ for x in range(x1, x2 + 1):
+ dst[y * BIGW + x] = color
+
+ def vline(dst, x, y1, y2, color):
+ for y in range(y1, y2 + 1):
+ dst[y * BIGW + x] = color
+
+ def fillrect(dst, x1, x2, y1, y2, color):
+ for y in range(y1, y2 + 1):
+ hline(dst, x1, x2, y, color)
+
+ def encode_id(dst, x, y, v):
+ while v:
+ if v & 1:
+ dst[y * BIGW + x] = 253
+ x -= 1
+ v >>= 1
+
+ palette = get_full_palette(e.pal_idx, e.pal_subidx)
+
+ if not e.skip_header:
+ pal_subidx = e.pal_subidx
+ if e.high_palette:
+ pal_name = '%sR' % e.pal_base
+ else:
+ pal_name = ' %s' % e.pal_base
+ if e.pal_base in (1, 2, 3):
+ assert e.pal_subidx in (0, 1)
+ pal_subidx = 'LW' if pal_subidx == 0 else 'DW'
+
+ header = bytearray([255] * BIGW * 9)
+ draw_string3x5(header, BIGW, 1, 3, e.name[:22], 254)
+
+ for i in range(7):
+ xx = BIGW - 37 + i * 5 - 9
+ fillrect(header, xx, xx + 4, 3, 7, i + (9 if e.high_palette else 1))
+
+ if pal_subidx != None:
+ draw_string3x5(header, BIGW, BIGW - 9, 3, '%2s' % pal_subidx, 252)
+
+ draw_string3x5(header, BIGW, BIGW - 45 - 9, 3, pal_name, 252)
+ finaldst.extend(convert_to_24bpp(header, palette))
+
+ bigdst = bytearray([255] * BIGW * 36)
+ hline(bigdst, 1, 137, 0, 254)
+ hline(bigdst, 1, 137, 34, 254)
+ vline(bigdst, 1, 0, 34, 254)
+ vline(bigdst, 137, 0, 34, 254)
+
+ encode_id(bigdst, 137, 35, e.encoded_id << 9 | 0x55)
+
+ src = decode_3bit_tileset(e.tileset) # returns 128x64
+
+ for i in range(16*4):
+ x, y = i % 16, i // 16
+ dst_offs = (y * 8 + 1 + (y >> 1)) * BIGW + x * 8 + 2 + (x >> 1)
+ if x & 8: dst_offs
+ m = e.matrix[y][x]
+ if m == '.':
+ fill_with_empty(bigdst, dst_offs)
+ else:
+ copy_8x8(bigdst, dst_offs, src, x * 8 + y * 8 * 128, 0)
+ if master_tilesheets:
+ master_tilesheets.insert(e.tileset, src, x, y, palette, 0)
+
+ # collapse unused matrix sections
+ if all(m=='.' for m in e.matrix[0]) and all(m=='.' for m in e.matrix[1]):
+ del bigdst[1*BIGW:17*BIGW]
+ elif all(m=='.' for m in e.matrix[2]) and all(m=='.' for m in e.matrix[3]):
+ del bigdst[18*BIGW:34*BIGW]
+
+ draw_string3x5(bigdst, BIGW, BIGW - 9, 2, ' %d' % e.ss_idx, 252)
+ draw_string3x5(bigdst, BIGW, BIGW - 9, 2 + 9, '%.2d' % e.tileset, 252)
+
+ finaldst.extend(convert_to_24bpp(bigdst, palette))
+
+def fixup_entries():
+ e_prev = None
+ for e in sprite_sheet_info.entries:
+ fixup_sprite_set_entry(e, e_prev)
+ e_prev = e
+
+class MasterTilesheets:
+ def __init__(self):
+ self.sheets = {}
+
+ def insert(self, tileset, src, xp, yp, palette, pal_base):
+ sheet = self.sheets.get(tileset)
+ if sheet == None:
+ sheet = (array.array('I', [0x00f000] * 128 * 32), None)
+ self.sheets[tileset] = sheet
+ sheet24 = sheet[0]
+ for y in range(yp * 8, yp * 8 + 8):
+ for x in range(xp * 8, xp * 8 + 8):
+ o = y * 128 + x
+ sheet24[o] = palette[pal_base + src[o]]
+
+ def add_verify_8x8(self, tileset, pal_lut, img_data, pitch, dst_pos, src_pos):
+ # add to the master sheet
+ sheet = self.sheets.get(tileset)
+ if sheet == None:
+ sheet = (array.array('I', [0x00f000] * 128 * 32), bytearray([248] * 128 * 32))
+ self.sheets[tileset] = sheet
+ sheet24, sheet8 = sheet[0], sheet[1]
+ for y in range(8):
+ for x in range(8):
+ pixel = img_data[src_pos + y * pitch + x]
+ o = dst_pos + y * 128 + x
+ sheet24[o] = pixel
+ pixel8 = pal_lut.get(pixel)
+ if pixel8 == None:
+ raise Exception('Pixel #%.6x not found' % pixel)
+ if sheet8[o] != 248 and pixel8 != sheet8[o]:
+ raise Exception('Pixel has more than one value')
+ sheet8[o] = pixel8
+
+ def save_to_all_sheets(self):
+ rv = array.array('I')
+ rv8 = bytearray()
+
+ def extend_with_string_line(text):
+ header = array.array('I', [0xf0f0f0] * 128 * 8)
+ draw_string3x5(header, 128, 1, 2, text, 0x404040)
+ rv.extend(header)
+ header8 = bytearray([255] * 128 * 8)
+ draw_string3x5(header8, 128, 1, 2, text, 254)
+ rv8.extend(header8)
+ extend_with_string_line('AUTO GENERATED DO NOT EDIT')
+ kk = 0
+ for k in sorted(self.sheets.keys()):
+ extend_with_string_line('Sheet %d' % k)
+ rv.extend(self.sheets[k][0])
+ rv8.extend(self.sheets[k][1])
+ if k != kk:
+ print('Missing %d' % kk)
+ kk = k + 1
+ palette8 = get_full_palette(4, 0)
+ for i, v in enumerate(convert_snes_palette_to_int(get_palette_subset(5, 0))):
+ palette8[i + 9] = v
+ palette8[248] = 0x00f000
+ save_as_png((128, len(rv)//128), rv8, 'sprites/all_sheets_8bit.png', palette = convert_int24_palette_to_bytes(palette8))
+ save_as_24bpp_png((128, len(rv)//128), rv, 'sprites/all_sheets.png')
+ self.verify_identical_to_snes()
+
+ def verify_identical_to_snes(self):
+ for tileset in range(103):
+ a = self.encode_sheet_in_snes_format(tileset)
+ b = get_unpacked_snes_tileset(tileset)
+ if a != b:
+ print('Sheet %d mismatch' % tileset)
+ break
+
+ # convert a tileset to the 8bit snes format, 24 bytes per tile
+ def encode_sheet_in_snes_format(self, tileset):
+ sheet8 = self.sheets[tileset][1]
+ result = bytearray(24 * 16 * 4)
+ def encode_into(dst_pos, src_pos):
+ for y in range(8):
+ for x in range(8):
+ b = sheet8[src_pos + 128 * y + 7 - x]
+ result[dst_pos+2*y] |= (b & 1) << x
+ result[dst_pos+2*y+1] |= ((b & 2) >> 1) << x
+ result[dst_pos+y+16] |= ((b & 4) >> 2) << x
+ for y in range(4):
+ for x in range(16):
+ encode_into((y * 16 + x) * 24, y * 8 * 128 + x * 8)
+ return result
+
+
+def decode_sprite_sheets():
+ master_tilesheets = MasterTilesheets()
+
+ fixup_entries()
+ for char in "0123456789ABCDEFX":
+ dst = []
+ for e in sprite_sheet_info.entries:
+ if e.name[0].upper() == char:
+ save_sprite_set_entry(dst, e, master_tilesheets)
+ if len(dst):
+ save_as_24bpp_png((BIGW, len(dst) // BIGW), dst, 'sprites/sprites_%s.png' % char)
+ master_tilesheets.save_to_all_sheets()
+
+def load_sprite_sheets():
+ master_tilesheets = MasterTilesheets()
+ for char in "0123456789ABCDEFX":
+ img = Image.open('sprites/sprites_%s.png' % char)
+ img_size = img.size
+ img_data = array.array('I', (a[0] | a[1] << 8 | a[2] << 16 for a in img.getdata()))
+ pitch = img.size[0]
+
+ def find_next_tag(start_pos):
+ for i in range(start_pos, len(img_data) - pitch * 2, pitch if start_pos != 0 else 1):
+ if img_data[i+0] == 0x404040 and img_data[i+pitch] == 0x404040 and \
+ img_data[i+pitch * 2 + 0] == 0xf0f0f0 and img_data[i+pitch * 2 - 1] == 0xe0e0e0 and \
+ img_data[i+pitch * 2 - 2] == 0xf0f0f0 and img_data[i+pitch * 2 - 3] == 0xe0e0e0 and \
+ img_data[i+pitch * 2 - 4] == 0xf0f0f0 and img_data[i+pitch * 2 - 5] == 0xe0e0e0 and \
+ img_data[i+pitch * 2 - 6] == 0xf0f0f0 and img_data[i+pitch * 2 - 7] == 0xe0e0e0:
+ return i + pitch * 2
+ else:
+ return None
+
+ def decode_tag(pos):
+ r = 0
+ for i in range(64):
+ v = img_data[pos - 63 + i]
+ assert v in (0xe0e0e0, 0xf0f0f0)
+ r = r * 2 + (v == 0xf0f0f0)
+ if (r & 0x1ff) != 0x55:
+ raise Exception('Invalid tag')
+ r >>= 9
+ if (((r >> 8) + 41) % 255) != (r & 0xff):
+ raise Exception('Invalid checksum')
+ r >>= 8
+ return r & 7, (r >> 3) & 127, (r >> 10) & 1, (r >> 11) & 31
+
+ def determine_image_rects(tag_pos):
+ h = 1
+ while (img_data[tag_pos - pitch * (h + 1)] == 0x404040):
+ h += 1
+ if h == 19:
+ if img_data[tag_pos - pitch * 2 - 1] == 0xe0e0e0:
+ image_rects = ((0, tag_pos - 135 - pitch * 18), )
+ elif img_data[tag_pos - pitch * 18 - 1] == 0xe0e0e0:
+ image_rects = ((1, tag_pos - 135 - pitch * 17), )
+ else:
+ raise Exception('cant uncompact')
+ elif h == 35:
+ image_rects = ((0, tag_pos - 135 - pitch * 34), (1, tag_pos - 135 - pitch * 17))
+ else:
+ raise Exception('height not found')
+ return image_rects, h
+
+ def get_pal_lut(tag_pos, is_high):
+ # read palette colors from the image pixels
+ pal_lut = {img_data[tag_pos + 5 * i] : i + (9 if is_high else 1) for i in range(7)}
+ pal_lut[0x808000] = 0 # transparent color
+ return pal_lut
+
+ def is_empty(pos):
+ return all(img_data[pos+y*pitch+x] == 0xf0f0f0 for x in range(8) for y in range(8))
+
+ pal_lut = None
+ tag_pos = 0
+ while True:
+ tag_pos = find_next_tag(tag_pos)
+ if tag_pos == None:
+ break
+ pal_base, tileset, headerless, pal_subidx = decode_tag(tag_pos)
+ image_rects, box_height = determine_image_rects(tag_pos)
+ if not headerless:
+ pal_lut = get_pal_lut(tag_pos - pitch * (box_height + 3) - 34, is_high_3bit_tileset(tileset))
+ for idx, sheet_pos in image_rects:
+ for y in range(2):
+ for x in range(16):
+ src_pos = sheet_pos + (y * 8 + (y >> 1)) * pitch + (x * 8 + (x >> 1))
+ dst_pos = (y + idx * 2) * 8 * 128 + x * 8
+ if not is_empty(src_pos):
+ master_tilesheets.add_verify_8x8(tileset, pal_lut, img_data, pitch, dst_pos, src_pos)
+ return master_tilesheets
--- /dev/null
+++ b/tables/sprites/.gitignore
@@ -1,0 +1,1 @@
+/*.png
--- a/tables/tables.py
+++ b/tables/tables.py
@@ -880,3 +880,253 @@
82 : "Warp", 0x84 : "Staircase", 0x86 : 'Bombable', 0x88 : 'Switch' }
for k,v in kSpecialSecret.items():
r[k] = '%.2X-%s' % (k, v)
+n kSpecialSecret.items():
+ r[k] = '%.2X-%s' % (k, v)
+ return r
+
+kSecretNames = get_secret_names()
+kSecretNamesRev = invert_dict(kSecretNames)
+
+kCompSpritePtrs = [
+ 0x10f000,0x10f600,0x10fc00,0x118200,0x118800,0x118e00,0x119400,0x119a00,
+ 0x11a000,0x11a600,0x11ac00,0x11b200,0x14fffc,0x1585d4,0x158ab6,0x158fbe,
+ 0x1593f8,0x1599a6,0x159f32,0x15a3d7,0x15a8f1,0x15aec6,0x15b418,0x15b947,
+ 0x15bed0,0x15c449,0x15c975,0x15ce7c,0x15d394,0x15d8ac,0x15ddc0,0x15e34c,
+ 0x15e8e8,0x15ee31,0x15f3a6,0x15f92d,0x15feba,0x1682ff,0x1688e0,0x168e41,
+ 0x1692df,0x169883,0x169cd0,0x16a26e,0x16a275,0x16a787,0x16aa06,0x16ae9d,
+ 0x16b3ff,0x16b87e,0x16be6b,0x16c13d,0x16c619,0x16cbbb,0x16d0f1,0x16d641,
+ 0x16d95a,0x16dd99,0x16e278,0x16e760,0x16ed25,0x16f20f,0x16f6b7,0x16fa5f,
+ 0x16fd29,0x1781cd,0x17868d,0x178b62,0x178fd5,0x179527,0x17994b,0x179ea7,
+ 0x17a30e,0x17a805,0x17acf8,0x17b2a2,0x17b7f9,0x17bc93,0x17c237,0x17c78e,
+ 0x17cd55,0x17d2bc,0x17d82f,0x17dcec,0x17e1cc,0x17e36b,0x17e842,0x17eb38,
+ 0x17ed58,0x17f06c,0x17f4fd,0x17fa39,0x17ff86,0x18845c,0x1889a1,0x188d64,
+ 0x18919d,0x189610,0x189857,0x189b24,0x189dd2,0x18a03f,0x18a4ed,0x18a7ba,
+ 0x18aedf,0x18af0d,0x18b520,0x18b953,
+]
+
+kCompBgPtrs = [
+ 0x11b800,0x11bce2,0x11c15f,0x11c675,0x11cb84,0x11cf4c,0x11d2ce,0x11d726,
+ 0x11d9cf,0x11dec4,0x11e393,0x11e893,0x11ed7d,0x11f283,0x11f746,0x11fc21,
+ 0x11fff2,0x128498,0x128a0e,0x128f30,0x129326,0x129804,0x129d5b,0x12a272,
+ 0x12a6fe,0x12aa77,0x12ad83,0x12b167,0x12b51d,0x12b840,0x12bd54,0x12c1c9,
+ 0x12c73d,0x12cc86,0x12d198,0x12d6b1,0x12db6a,0x12e0ea,0x12e6bd,0x12eb51,
+ 0x12f135,0x12f6c5,0x12fc71,0x138129,0x138693,0x138bad,0x139117,0x139609,
+ 0x139b21,0x13a074,0x13a619,0x13ab2b,0x13b00c,0x13b4f5,0x13b9eb,0x13bebf,
+ 0x13c3ce,0x13c817,0x13cb68,0x13cfb5,0x13d460,0x13d8c2,0x13dd7a,0x13e266,
+ 0x13e7af,0x13ece5,0x13f245,0x13f6f0,0x13fc30,0x1480e9,0x14863b,0x148a7c,
+ 0x148f2a,0x149346,0x1497ed,0x149cc2,0x14a173,0x14a61d,0x14ab5d,0x14b083,
+ 0x14b4bd,0x14b94e,0x14be0e,0x14c291,0x14c7ba,0x14cce4,0x14d1db,0x14d6bd,
+ 0x14db77,0x14ded1,0x14e2ac,0x14e754,0x14ebae,0x14ef4e,0x14f309,0x14f6f4,
+ 0x14fa55,0x14ff8c,0x14ff93,0x14ff9a,0x14ffa1,0x14ffa8,0x14ffaf,0x14ffb6,
+ 0x14ffbd,0x14ffc4,0x14ffcb,0x14ffd2,0x14ffd9,0x14ffe0,0x14ffe7,0x14ffee,
+ 0x14fff5,0x18b520,0x18b953,
+]
+
+kSpriteTilesets = [
+ ( 0, 73, 0, 0),
+ (70, 73, 12, 29),
+ (72, 73, 19, 29),
+ (70, 73, 19, 14),
+ (72, 73, 12, 17),
+ (72, 73, 12, 16),
+ (79, 73, 74, 80),
+ (14, 73, 74, 17),
+ (70, 73, 18, 0),
+ ( 0, 73, 0, 80),
+ ( 0, 73, 0, 17),
+ (72, 73, 12, 0),
+ ( 0, 0, 55, 54),
+ (72, 73, 76, 17),
+ (93, 44, 12, 68),
+ ( 0, 0, 78, 0),
+ (15, 0, 18, 16),
+ ( 0, 0, 0, 76),
+ ( 0, 13, 23, 0),
+ (22, 13, 23, 27),
+ (22, 13, 23, 20),
+ (21, 13, 23, 21),
+ (22, 13, 24, 25),
+ (22, 13, 23, 25),
+ (22, 13, 0, 0),
+ (22, 13, 24, 27),
+ (15, 73, 74, 17),
+ (75, 42, 92, 21),
+ (22, 73, 23, 29),
+ ( 0, 0, 0, 21),
+ (22, 13, 23, 16),
+ (22, 73, 18, 0),
+ (22, 73, 12, 17),
+ ( 0, 0, 18, 16),
+ (22, 13, 0, 17),
+ (22, 73, 12, 0),
+ (22, 13, 76, 17),
+ (14, 13, 74, 17),
+ (22, 26, 23, 27),
+ (79, 52, 74, 80),
+ (53, 77, 101, 54),
+ (74, 52, 78, 0),
+ (14, 52, 74, 17),
+ (81, 52, 93, 89),
+ (75, 73, 76, 17),
+ (45, 0, 0, 0),
+ (93, 0, 18, 89),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ (71, 73, 43, 45),
+ (70, 73, 28, 82),
+ ( 0, 73, 28, 82),
+ (93, 73, 0, 82),
+ (70, 73, 19, 82),
+ (75, 77, 74, 90),
+ (71, 73, 28, 82),
+ (75, 77, 57, 54),
+ (31, 44, 46, 82),
+ (31, 44, 46, 29),
+ (47, 44, 46, 82),
+ (47, 44, 46, 49),
+ (31, 30, 48, 82),
+ (81, 73, 19, 0),
+ (79, 73, 19, 80),
+ (79, 77, 74, 80),
+ (75, 73, 76, 43),
+ (31, 32, 34, 83),
+ (85, 61, 66, 67),
+ (31, 30, 35, 82),
+ (31, 30, 57, 58),
+ (31, 30, 58, 62),
+ (31, 30, 60, 61),
+ (64, 30, 39, 63),
+ (85, 26, 66, 67),
+ (31, 30, 42, 82),
+ (31, 30, 56, 82),
+ (31, 32, 40, 82),
+ (31, 32, 38, 82),
+ (31, 44, 37, 82),
+ (31, 32, 39, 82),
+ (31, 30, 41, 82),
+ (31, 44, 59, 82),
+ (70, 73, 36, 82),
+ (33, 65, 69, 51),
+ (31, 44, 40, 49),
+ (31, 13, 41, 82),
+ (31, 30, 39, 82),
+ (31, 32, 39, 83),
+ (72, 73, 19, 82),
+ (14, 30, 74, 80),
+ (31, 32, 38, 83),
+ (21, 0, 0, 0),
+ (31, 0, 42, 82),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ ( 0, 0, 0, 0),
+ (50, 0, 0, 8),
+ (93, 73, 0, 82),
+ (85, 73, 66, 67),
+ (97, 98, 99, 80),
+ (97, 98, 99, 80),
+ (97, 98, 99, 80),
+ (97, 98, 99, 80),
+ (97, 98, 99, 80),
+ (97, 98, 99, 80),
+ (97, 86, 87, 80),
+ (97, 98, 99, 80),
+ (97, 98, 99, 80),
+ (97, 86, 87, 80),
+ (97, 86, 99, 80),
+ (97, 86, 87, 80),
+ (97, 86, 51, 80),
+ (97, 86, 87, 80),
+ (97, 98, 99, 80),
+ (97, 98, 99, 80),
+]
+
+kDungPalinfos = [
+ ( 0, 0, 3, 1),
+ ( 2, 0, 3, 1),
+ ( 4, 0, 10, 1),
+ ( 6, 0, 1, 7),
+ (10, 2, 2, 7),
+ ( 4, 4, 3, 10),
+ (12, 5, 8, 20),
+ (14, 0, 3, 10),
+ ( 2, 0, 15, 20),
+ (10, 2, 0, 7),
+ ( 2, 0, 15, 12),
+ ( 6, 0, 6, 7),
+ ( 0, 0, 14, 18),
+ (18, 5, 5, 11),
+ (18, 0, 2, 12),
+ (16, 5, 10, 7),
+ (16, 0, 16, 12),
+ (22, 7, 2, 7),
+ (22, 0, 7, 15),
+ ( 8, 0, 4, 12),
+ ( 8, 0, 4, 9),
+ ( 4, 0, 3, 1),
+ (20, 0, 4, 4),
+ (20, 0, 20, 12),
+ (24, 5, 7, 11),
+ (24, 6, 16, 12),
+ (26, 5, 8, 20),
+ (26, 2, 0, 7),
+ ( 6, 0, 3, 10),
+ (28, 0, 3, 1),
+ (30, 0, 11, 17),
+ ( 4, 0, 11, 17),
+ (14, 0, 0, 2),
+ (32, 8, 19, 13),
+ (10, 0, 3, 10),
+ (20, 0, 4, 4),
+ (26, 2, 2, 7),
+ (26, 10, 0, 0),
+ ( 0, 0, 3, 2),
+ (14, 0, 3, 7),
+ (26, 5, 5, 11),
+]
+
+kOwSprPalInfo = [
+ -1, -1, 3, 10, 3, 6, 3, 1, 0, 2, 3, 14, 3, 2, 19, 1, 11, 12, 17, 1, 7, 5, 17, 0,
+ 9, 11, 15, 5, 3, 5, 3, 7, 15, 2, 10, 2, 5, 1, 12, 14,
+]
+
+kSpriteInit_Flags3 = [
+ 0x19, 0xb, 0x1b, 0x4b, 0x41, 0x41, 0x41, 0x4d, 0x1d, 1, 0x1d, 0x19, 0x8d, 0x1b, 9, 0x9d,
+ 0x3d, 1, 9, 0x11, 0x40, 1, 0x4d, 0x19, 7, 0x1d, 0x59, 0x80, 0x4d, 0x40, 1, 0x49,
+ 0x1b, 0x41, 3, 0x13, 0x15, 0x41, 0x18, 0x1b, 0x41, 0x47, 0xf, 0x49, 0x4b, 0x4d, 0x41, 0x47,
+ 0x49, 0x4d, 0x49, 0x40, 0x4d, 0x47, 0x49, 0x41, 0x74, 0x47, 0x5b, 0x58, 0x51, 0x49, 0x1d, 0x5d,
+ 3, 0x19, 0x1b, 0x17, 0x19, 0x17, 0x19, 0x1b, 0x17, 0x17, 0x17, 0x1b, 0xd, 9, 0x19, 0x19,
+ 0x49, 0x5d, 0x5b, 0x49, 0xd, 3, 0x13, 0x41, 0x1b, 0x5b, 0x5d, 0x43, 0x43, 0x4d, 0x4d, 0x4d,
+ 0x4d, 0x4d, 0x49, 1, 0, 0x41, 0x4d, 0x4d, 0x4d, 0x4d, 0x1d, 9, 0xc4, 0xd, 0xd, 9,
+ 3, 3, 0x4b, 0x47, 0x47, 0x49, 0x49, 0x41, 0x47, 0x36, 0x8b, 0x49, 0x1d, 0x49, 0x43, 0x43,
+ 0x43, 0xb, 0x41, 0xd, 7, 0xb, 0x1d, 0x43, 0xd, 0x43, 0xd, 0x1d, 0x4d, 0x4d, 0x1b, 0x1b,
+ 0xa, 0xb, 0, 5, 0xd, 1, 1, 1, 1, 0xb, 5, 1, 1, 1, 7, 0x17,
+ 0x19, 0xd, 0xd, 0x80, 0x4d, 0x19, 0x17, 0x19, 0xb, 9, 0xd, 0x4a, 0x12, 0x49, 0xc3, 0xc3,
--- a/tables/util.py
+++ b/tables/util.py
@@ -2,6 +2,7 @@
import sys
import hashlib
import os
+from functools import cache
# Both are common SNES rom extensions. For Zelda3 (NA), they are equivalent files.
COMMON_ROM_NAMES = ['zelda3.sfc', 'zelda3.smc']
@@ -8,6 +9,36 @@
DEFAULT_ROM_DIRECTORY = os.path.dirname(__file__)
ZELDA3_SHA256 = '66871d66be19ad2c34c927d6b14cd8eb6fc3181965b6e517cb361f7316009cfb'
+def load_rom(filename):
+ global ROM
+ ROM = LoadedRom(filename)
+ return ROM
+
+def get_byte(addr):
+ return ROM.get_byte(addr)
+
+@cache
+def get_bytes(addr, n):
+ return ROM.get_bytes(addr, n)
+
+@cache
+def get_words(addr, n):
+ return ROM.get_words(addr, n)
+
+def get_int8(ea):
+ b = get_byte(ea)
+ if b & 0x80: b -= 256
+ return b
+
+def get_int16(ea):
+ b = get_word(ea)
+ if b & 0x8000: b -= 65536
+ return b
+
+def get_word(addr):
+ return ROM.get_word(addr)
+
+
class LoadedRom:
def __init__(self, path = None):
rom_path = self.__get_rom_path(path)
@@ -28,7 +59,7 @@
return self.get_byte(ea) + self.get_byte(ea + 1) * 256 + self.get_byte(ea + 2) * 65536
def get_bytes(self, addr, n):
- r = []
+ r = bytearray()
for i in range(n):
r.append(self.get_byte(addr))
addr += 1
--- a/tagalong.c
+++ b/tagalong.c
@@ -662,7 +662,7 @@
uint8 pal;
skip_first_sprites:
pal = kTagalongDraw_Pals[follower_indicator];
- if (pal == 7 && overworld_palette_swap_flag)
+ if (pal == 7 && palette_swap_flag)
pal = 0;
if (follower_indicator == 13) {
--- a/variables.h
+++ b/variables.h
@@ -603,19 +603,19 @@
#define unused_config_gfx (*(uint16*)(g_ram+0xAA6))
#define overworld_palette_aux_or_main (*(uint16*)(g_ram+0xAA8))
#define load_chr_halfslot_even_odd (*(uint8*)(g_ram+0xAAA))
-#define overworld_palette_sp0 (*(uint8*)(g_ram+0xAAC))
-#define sprite_aux1_palette (*(uint8*)(g_ram+0xAAD))
-#define sprite_aux2_palette (*(uint8*)(g_ram+0xAAE))
+#define palette_sp0l (*(uint8*)(g_ram+0xAAC))
+#define palette_sp5l (*(uint8*)(g_ram+0xAAD))
+#define palette_sp6l (*(uint8*)(g_ram+0xAAE))
#define byte_7E0AB0 (*(uint8*)(g_ram+0xAB0))
-#define palette_sp6 (*(uint8*)(g_ram+0xAB1))
+#define palette_sp6r_indoors (*(uint8*)(g_ram+0xAB1))
#define hud_palette (*(uint8*)(g_ram+0xAB2))
#define overworld_palette_mode (*(uint8*)(g_ram+0xAB3))
#define overworld_palette_aux1_bp2to4_hi (*(uint8*)(g_ram+0xAB4))
#define overworld_palette_aux2_bp5to7_hi (*(uint8*)(g_ram+0xAB5))
-#define dung_hdr_palette_1 (*(uint8*)(g_ram+0xAB6))
+#define palette_main_indoors (*(uint8*)(g_ram+0xAB6))
#define byte_7E0AB7 (*(uint8*)(g_ram+0xAB7))
#define overworld_palette_aux3_bp7_lo (*(uint8*)(g_ram+0xAB8))
-#define overworld_palette_swap_flag (*(uint8*)(g_ram+0xABD))
+#define palette_swap_flag (*(uint8*)(g_ram+0xABD))
#define flag_overworld_area_did_change (*(uint8*)(g_ram+0xABF))
#define dma_source_addr_6 (*(uint16*)(g_ram+0xAC0))
#define dma_source_addr_11 (*(uint16*)(g_ram+0xAC2))
--- a/zelda_cpu_infra.c
+++ b/zelda_cpu_infra.c
@@ -382,7 +382,15 @@
WORD(rom[(addr >> 16) << 15 | (addr & 0x7fff)]) = value;
}
+static void PatchRomArray(uint8_t *rom, uint32_t addr, const uint8 *values, int n) {
+ for (int i = 0; i < n; i++) {
+ rom[(addr >> 16) << 15 | (addr & 0x7fff)] = values[i];
+ addr += 1;
+ }
+}
+
+
static void PatchRom(uint8_t *rom) {
// fix a bug with unitialized memory
{
@@ -552,6 +560,10 @@
PatchRomWord(rom, 0xddfac + 1, 0xfa85, 0xfa70); // call Hud_Rebuild instead of Hud_UpdateOnly
+ // Make sure it's not calling Decomp_spr on tilesheets less than 12
+ PatchRomWord(rom, 0xe589, 0xe772, 0xe852); // call New addr
+ static const uint8 kFixSoItWontDecodeSheetLessThan12[] = { 0xc0, 0x0c, 0xb0, 0x02, 0xa0, 0x0c, 0x4c, 0x72, 0xe7 };
+ PatchRomArray(rom, 0xe852, kFixSoItWontDecodeSheetLessThan12, sizeof(kFixSoItWontDecodeSheetLessThan12));
}