From ce9ac5383ee6596eb109f91e2e3f276c502d5d8c Mon Sep 17 00:00:00 2001 From: Justin Scofield Date: Sat, 11 Jun 2022 10:06:54 -0400 Subject: [PATCH] Importing a bunch of code from Skarsnik sneshacking repo --- src/Application/Editor/Editor.cc | 33 +++- src/Application/Editor/Editor.h | 2 + src/Application/Graphics/Palette.cc | 83 +++++++++ src/Application/Graphics/Palette.h | 42 +++++ src/Application/Graphics/Tile.cc | 194 ++++++++++++++++++++- src/Application/Graphics/Tile.h | 38 +++- src/Application/Utils/ROM.cc | 257 ++++++++++++++++++++++++++-- src/Application/Utils/ROM.h | 46 ++++- 8 files changed, 671 insertions(+), 24 deletions(-) create mode 100644 src/Application/Graphics/Palette.cc create mode 100644 src/Application/Graphics/Palette.h diff --git a/src/Application/Editor/Editor.cc b/src/Application/Editor/Editor.cc index e0222787..12b3dae2 100644 --- a/src/Application/Editor/Editor.cc +++ b/src/Application/Editor/Editor.cc @@ -27,11 +27,15 @@ void Editor::UpdateScreen() { overworld_texture = &overworld.owactualMapTexture; doneLoaded = true; } - ImGui::Image((void*)(intptr_t)overworld_texture, ImVec2(overworld.overworldMapBitmap->GetWidth(), overworld.overworldMapBitmap->GetHeight())); + // ImGui::Image((void*)(intptr_t)overworld_texture, + // ImVec2(overworld.overworldMapBitmap->GetWidth(), + // overworld.overworldMapBitmap->GetHeight())); } if (ImGui::BeginTabBar("##TabBar")) { DrawOverworldEditor(); + DrawDungeonEditor(); + DrawROMInfo(); ImGui::EndTabBar(); } // ImGui::ShowDemoWindow(); @@ -155,12 +159,8 @@ void Editor::DrawOverworldEditor() { ImGui::Checkbox("Enable grid", &opt_enable_grid); - ImVec2 canvas_p0 = - ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! - ImVec2 canvas_sz = - ImGui::GetContentRegionAvail(); // Resize canvas to what's available - if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f; - if (canvas_sz.y < 50.0f) canvas_sz.y = 50.0f; + ImVec2 canvas_p0 = ImGui::GetCursorScreenPos(); + ImVec2 canvas_sz = ImGui::GetContentRegionAvail(); ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y); @@ -194,8 +194,6 @@ void Editor::DrawOverworldEditor() { } // Pan (we use a zero mouse threshold when there's no context menu) - // You may decide to make that threshold dynamic based on whether the mouse - // is hovering something etc. const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f; if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, @@ -247,6 +245,23 @@ void Editor::DrawOverworldEditor() { ImGui::EndTabItem(); } } +void DrawDungeonEditor() { + if (ImGui::BeginTabItem("Dungeon")) { + ImGui::EndTabItem(); + } +} + +void Editor::DrawROMInfo() { + if (ImGui::BeginTabItem("ROM Info")) { + if (isLoaded) { + ImGui::Text("Title: %s", rom.getTitle()); + ImGui::Text("Version: %d", rom.getVersion()); + ImGui::Text("ROM Size: %ld", rom.getSize()); + } + + ImGui::EndTabItem(); + } +} } // namespace View } // namespace Application diff --git a/src/Application/Editor/Editor.h b/src/Application/Editor/Editor.h index 280b9791..0c6c1d44 100644 --- a/src/Application/Editor/Editor.h +++ b/src/Application/Editor/Editor.h @@ -26,6 +26,8 @@ class Editor { void DrawEditMenu() const; void DrawOverworldEditor(); + void DrawDungeonEditor(); + void DrawROMInfo(); bool isLoaded = false; bool doneLoaded = false; diff --git a/src/Application/Graphics/Palette.cc b/src/Application/Graphics/Palette.cc new file mode 100644 index 00000000..e718230e --- /dev/null +++ b/src/Application/Graphics/Palette.cc @@ -0,0 +1,83 @@ +#include "Palette.h" + +#include +#include + +namespace yaze { +namespace Application { +namespace Graphics { + +r_palette* palette_create(const unsigned int size, const unsigned int id) +{ + r_palette *new_pal = (r_palette*) malloc(sizeof(r_palette)); + new_pal->colors = (m_color*) malloc(sizeof(m_color) * size); + new_pal->id = id; + new_pal->size = size; + return new_pal; +} + +void palette_free(r_palette* tofree) +{ + free(tofree->colors); + free(tofree); +} + + +r_palette *palette_extract(const char* data, const unsigned int offset, const unsigned int palette_size) +{ + r_palette* toret = palette_create(palette_size, 0); + unsigned colnum = 0; + for (int i = 0; i < palette_size * 2; i += 2) + { + unsigned short snes_color; + snes_color = ((uchar) data[offset + i + 1]) << 8; + snes_color = snes_color | ((uchar) data[offset + i]); + toret->colors[colnum] = convertcolor_snes_to_rgb(snes_color); + colnum++; + } + return toret; +} + +char* palette_convert(const r_palette pal) +{ + char* toret = (char*) malloc(pal.size * 2); + for (unsigned int i = 0; i < pal.size; i++) + { + unsigned short snes_data = convertcolor_rgb_to_snes(pal.colors[i]); + toret[i * 2] = snes_data & 0xFF; + toret[i * 2 + 1] = snes_data >> 8; + } + return toret; +} + +m_color convertcolor_snes_to_rgb(const unsigned short snes_color) +{ + m_color toret; + + toret.red = ((snes_color ) % 32) * 8; + toret.green = ((snes_color / 32) % 32) * 8; + toret.blue = ((snes_color / 1024) % 32) * 8; + + toret.red = toret.red + toret.red / 32; + toret.green = toret.green + toret.green / 32; + toret.blue = toret.blue + toret.blue / 32; + return toret; +} + +unsigned short convertcolor_rgb_to_snes(const m_color color) +{ + return convertcolor_rgb_to_snes2(color.red, color.green, color.blue); +} + +unsigned short convertcolor_rgb_to_snes2(const uchar red, const uchar green, const uchar blue) +{ + uchar R = red / 8; + uchar G = green / 8; + uchar B = blue / 8; + + return B * 1024 + G * 32 + R; +} + +} +} +} \ No newline at end of file diff --git a/src/Application/Graphics/Palette.h b/src/Application/Graphics/Palette.h new file mode 100644 index 00000000..01163187 --- /dev/null +++ b/src/Application/Graphics/Palette.h @@ -0,0 +1,42 @@ +#ifndef YAZE_APPLICATION_GRAPHICS_PALETTE_H +#define YAZE_APPLICATION_GRAPHICS_PALETTE_H + +namespace yaze { +namespace Application { +namespace Graphics { + +extern "C" { + +typedef unsigned char uchar; + +typedef struct { + unsigned char red; + unsigned char green; + unsigned char blue; +} m_color; + +typedef struct { + unsigned int id; + unsigned int size; + m_color* colors; +} r_palette; + +r_palette* palette_create(const unsigned int size, const unsigned int id); +void palette_free(r_palette* tofree); + +r_palette* palette_extract(const char* data, const unsigned int offset, + const unsigned int palette_size); + +char* palette_convert(const r_palette pal); + +m_color convertcolor_snes_to_rgb(const unsigned short snes_color); +unsigned short convertcolor_rgb_to_snes(const m_color color); +unsigned short convertcolor_rgb_to_snes2(const uchar red, const uchar green, + const uchar blue); +} + +} // namespace Graphics +} // namespace Application +} // namespace yaze + +#endif // YAZE_APPLICATION_GRAPHICS_PALETTE_H \ No newline at end of file diff --git a/src/Application/Graphics/Tile.cc b/src/Application/Graphics/Tile.cc index 496819bb..129dd01a 100644 --- a/src/Application/Graphics/Tile.cc +++ b/src/Application/Graphics/Tile.cc @@ -1,5 +1,12 @@ #include "Tile.h" +#include + +#include +#include +#include +#include + namespace yaze { namespace Application { namespace Graphics { @@ -21,6 +28,191 @@ ushort TileInfo::toShort() { return value; } -} // namespace Data +char* hexString(const char* str, const unsigned int size) { + char* toret = (char*)malloc(size * 3 + 1); + + unsigned int i; + for (i = 0; i < size; i++) { + sprintf(toret + i * 3, "%02X ", (unsigned char)str[i]); + } + toret[size * 3] = 0; + return toret; +} + +void export_tile_to_png(tile8 rawtile, const r_palette pal, + const char* filename) { + FILE* fp = fopen(filename, "wb"); + png_structp png_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_infop info_ptr = png_create_info_struct(png_ptr); + png_init_io(png_ptr, fp); + png_set_strip_alpha(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + png_color* png_palette = + (png_color*)png_malloc(png_ptr, pal.size * sizeof(png_color)); + + for (unsigned int i = 0; i < pal.size; i++) { + png_palette[i].blue = pal.colors[i].blue; + png_palette[i].green = pal.colors[i].green; + png_palette[i].red = pal.colors[i].red; + } + png_set_IHDR(png_ptr, info_ptr, 8, 8, 8, PNG_COLOR_TYPE_PALETTE, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + png_set_PLTE(png_ptr, info_ptr, png_palette, pal.size); + + png_write_info(png_ptr, info_ptr); + png_set_packing(png_ptr); + + png_byte* row_pointers[8]; + for (unsigned int i = 0; i < 8; i++) { + row_pointers[i] = (png_byte*)png_malloc(png_ptr, sizeof(png_byte)); + memcpy(row_pointers[i], rawtile.data + i * 8, 8); + } + + png_write_image(png_ptr, row_pointers); + + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + png_free(png_ptr, png_palette); + png_free(png_ptr, row_pointers); +} + +tile8 unpack_bpp1_tile(const char* data, const unsigned int offset) { + return (unpack_bpp_tile(data, offset, 1)); +} + +tile8 unpack_bpp2_tile(const char* data, const unsigned int offset) { + return (unpack_bpp_tile(data, offset, 2)); +} + +tile8 unpack_bpp3_tile(const char* data, const unsigned int offset) { + return (unpack_bpp_tile(data, offset, 3)); +} + +tile8 unpack_bpp4_tile(const char* data, const unsigned int offset) { + return (unpack_bpp_tile(data, offset, 4)); +} + +tile8 unpack_bpp8_tile(const char* data, const unsigned int offset) { + return (unpack_bpp_tile(data, offset, 8)); +} + +tile8 unpack_mode7_tile(const char* data, const unsigned int offset) { + tile8 tile; + memcpy(tile.data, data + offset, 64); + return tile; +} + +tile8 unpack_bpp_tile(const char* data, const unsigned int offset, + const unsigned bpp) { + tile8 tile; + assert(bpp >= 1 && bpp <= 8); + unsigned int bpp_pos[8]; // More for conveniance and readibility + for (int col = 0; col < 8; col++) { + for (int row = 0; row < 8; row++) { + if (bpp == 1) { + tile.data[col * 8 + row] = (data[offset + col] >> (7 - row)) & 0x01; + continue; + } + /* SNES bpp format interlace each byte of the first 2 bitplanes. + * | byte 1 of first bitplane | byte 1 of the second bitplane | byte 2 of + * first bitplane | byte 2 of second bitplane | .. + */ + bpp_pos[0] = offset + col * 2; + bpp_pos[1] = offset + col * 2 + 1; + char mask = 1 << (7 - row); + tile.data[col * 8 + row] = (data[bpp_pos[0]] & mask) == mask; + tile.data[col * 8 + row] |= ((data[bpp_pos[1]] & mask) == mask) << 1; + if (bpp == 3) { + // When we have 3 bitplanes, the bytes for the third bitplane are after + // the 16 bytes of the 2 bitplanes. + bpp_pos[2] = offset + 16 + col; + tile.data[col * 8 + row] |= ((data[bpp_pos[2]] & mask) == mask) << 2; + } + if (bpp >= 4) { + // For 4 bitplanes, the 2 added bitplanes are interlaced like the first + // two. + bpp_pos[2] = offset + 16 + col * 2; + bpp_pos[3] = offset + 16 + col * 2 + 1; + tile.data[col * 8 + row] |= ((data[bpp_pos[2]] & mask) == mask) << 2; + tile.data[col * 8 + row] |= ((data[bpp_pos[3]] & mask) == mask) << 3; + } + if (bpp == 8) { + bpp_pos[4] = offset + 32 + col * 2; + bpp_pos[5] = offset + 32 + col * 2 + 1; + bpp_pos[6] = offset + 48 + col * 2; + bpp_pos[7] = offset + 48 + col * 2 + 1; + tile.data[col * 8 + row] |= ((data[bpp_pos[4]] & mask) == mask) << 4; + tile.data[col * 8 + row] |= ((data[bpp_pos[5]] & mask) == mask) << 5; + tile.data[col * 8 + row] |= ((data[bpp_pos[6]] & mask) == mask) << 6; + tile.data[col * 8 + row] |= ((data[bpp_pos[7]] & mask) == mask) << 7; + } + } + } + return tile; +} + +byte* pack_bpp1_tile(const tile8 tile) { + unsigned int p = 1; + return pack_bpp_tile(tile, 1, &p); +} + +byte* pack_bpp2_tile(const tile8 tile) { + unsigned int p = 1; + return pack_bpp_tile(tile, 2, &p); +} + +byte* pack_bpp3_tile(const tile8 tile) { + unsigned int p = 1; + return pack_bpp_tile(tile, 3, &p); +} + +byte* pack_bpp4_tile(const tile8 tile) { + unsigned int p = 1; + return pack_bpp_tile(tile, 4, &p); +} + +byte* pack_bpp8_tile(const tile8 tile) { + unsigned int p = 1; + return pack_bpp_tile(tile, 8, &p); +} + +byte* pack_bpp_tile(tile8 tile, const unsigned int bpp, unsigned int* size) { + byte* output = (byte*)malloc(bpp * 8); + memset(output, 0, bpp * 8); + unsigned maxcolor = 2 << bpp; + *size = 0; + + for (unsigned int col = 0; col < 8; col++) { + for (unsigned int row = 0; row < 8; row++) { + byte color = tile.data[col * 8 + row]; + if (color > maxcolor) return NULL; + + if (bpp == 1) output[col] += (byte)((color & 1) << (7 - row)); + if (bpp >= 2) { + output[col * 2] += (byte)((color & 1) << (7 - row)); + output[col * 2 + 1] += (byte)(((color & 2) == 2) << (7 - row)); + } + if (bpp == 3) output[16 + col] += (byte)(((color & 4) == 4) << (7 - row)); + if (bpp >= 4) { + output[16 + col * 2] += (byte)(((color & 4) == 4) << (7 - row)); + output[16 + col * 2 + 1] += (byte)(((color & 8) == 8) << (7 - row)); + } + if (bpp == 8) { + output[32 + col * 2] += (byte)(((color & 16) == 16) << (7 - row)); + output[32 + col * 2 + 1] += (byte)(((color & 32) == 32) << (7 - row)); + output[48 + col * 2] += (byte)(((color & 64) == 64) << (7 - row)); + output[48 + col * 2 + 1] += (byte)(((color & 128) == 128) << (7 - row)); + } + } + } + *size = bpp * 8; + return output; +} + +} // namespace Graphics } // namespace Application } // namespace yaze diff --git a/src/Application/Graphics/Tile.h b/src/Application/Graphics/Tile.h index bdc77b74..2234fd4f 100644 --- a/src/Application/Graphics/Tile.h +++ b/src/Application/Graphics/Tile.h @@ -3,13 +3,48 @@ #include +#include "Palette.h" + namespace yaze { namespace Application { namespace Graphics { using byte = unsigned char; using ushort = unsigned short; +using uint = unsigned int; +// SkarAlttp project code +extern "C" { + +typedef struct { + unsigned int id; + char data[64]; + unsigned int palette_id; +} tile8; + +tile8 unpack_bpp8_tile(const char* data, const unsigned int offset); +tile8 unpack_bpp4_tile(const char* data, const unsigned int offset); +tile8 unpack_bpp3_tile(const char* data, const unsigned int offset); +tile8 unpack_bpp2_tile(const char* data, const unsigned int offset); +tile8 unpack_bpp1_tile(const char* data, const unsigned int offset); + +tile8 unpack_bpp_tile(const char* data, const unsigned int offset, + const unsigned int bpp); + +byte* pack_bpp1_tile(const tile8 tile); +byte* pack_bpp2_tile(const tile8 tile); +byte* pack_bpp3_tile(const tile8 tile); +byte* pack_bpp4_tile(const tile8 tile); +byte* pack_bpp8_tile(const tile8 tile); + +byte* pack_bpp_tile(const tile8 tile, const unsigned int bpp, + unsigned int* size); + +void export_tile_to_png(tile8 rawtile, const r_palette pal, + const char* filename); +} + +// End SkarAlttp project code class TileInfo { public: ushort id_; @@ -84,7 +119,8 @@ class Tile16 { ; } }; -} // namespace Data + +} // namespace Graphics } // namespace Application } // namespace yaze diff --git a/src/Application/Utils/ROM.cc b/src/Application/Utils/ROM.cc index 00589c42..78247f33 100644 --- a/src/Application/Utils/ROM.cc +++ b/src/Application/Utils/ROM.cc @@ -1,27 +1,270 @@ #include "ROM.h" +#define ROMMAPPING_LOCATION_SNES_RESERVED -1 +#define ROMMAPPING_LOCATION_SRAM -2 +#define ROMMAPPING_LOCATION_WRAM -3 + namespace yaze { namespace Application { namespace Utils { using namespace Graphics; +char *rommapping_error_text; +/* + * LoRoM is quite easy + */ +int lorom_snes_to_pc(const unsigned int snes_addr, char** info) +{ + unsigned char bank = snes_addr >> 16; + unsigned int offset = snes_addr & 0x00FFFF; + //printf("snes_addr: %X - Bank: %X - Offset: %X\n", snes_addr, bank, offset); + + // 80-FD is a mirror to the start + if (bank >= 0x80 && bank <= 0xFD) + bank -= 0x80; + if (bank >= 0x00 && bank <= 0x3F && offset < 0x8000 && offset >= 0x2000) + { + *info = "SNES Reserved"; + return ROMMAPPING_LOCATION_SNES_RESERVED; + } + if ((((bank >= 0x70 && bank <= 0x7D) || bank == 0xFE || bank == 0xFF) && offset < 0x8000)) + { + *info = "SRAM"; + return ROMMAPPING_LOCATION_SRAM; + } + if (bank == 0x7E || bank == 0x7F || + (bank >= 0x00 && bank <= 0x3F && offset < 0x2000) + ) + { + *info = "WRAM section"; + return ROMMAPPING_LOCATION_WRAM; + } + + if (bank >= 0x40 && bank <= 0x6F && offset < 0x8000) + return bank * 0x8000 + offset; + if (bank == 0xFE || bank == 0xFF) // this work as if 7E was regular bank + bank -= 0xFE - 0x7E; + return bank * 0x8000 + (offset - 0x8000); +} + +int hirom_snes_to_pc(const unsigned int snes_addr, char **info) +{ + unsigned char bank = snes_addr >> 16; + unsigned int offset = snes_addr & 0x00FFFF; + + // 80-FD is a mirror to the start + if (bank >= 0x80 && bank <= 0xFD) + bank -= 0x80; + + if ((bank >= 0x00 && bank <= 0x1F && offset < 0x8000 && offset >= 0x2000) || + (bank >= 0x20 && bank <= 0x3F && offset < 0x6000 && offset >= 0x2000) + ) + { + *info = "SNES Reserved"; + return ROMMAPPING_LOCATION_SNES_RESERVED; + } + if (bank >= 0x20 && bank <= 0x3F && offset >= 0x6000 && offset < 0x8000) + { + *info = "SRAM"; + return ROMMAPPING_LOCATION_SRAM; + } + if ((bank == 0x7E || bank == 0x7F) || + (bank >= 0x00 && bank <= 0x3F && offset < 0x2000)) + { + *info = "WRAM Section"; + return ROMMAPPING_LOCATION_WRAM; + } +/*#include + printf("%02X:%04X\n", bank, offset);*/ + if (bank >= 0xFE) + bank -= 0xFE - 0x3E; + if (bank >= 0x40 && bank <= 0x7D) + bank -= 0x40; + return (bank << 16) + offset; +} + +int hirom_pc_to_snes(const unsigned int pc_addr) +{ + unsigned int bank = pc_addr >> 16; + unsigned int offset = pc_addr & 0x00FFFF; + + //printf("%02X:%04X\n", bank, offset); + if (bank <= 0x3F && offset >= 0x8000) + return pc_addr; + if (bank <= 0x3D) + return pc_addr + 0x400000; + return pc_addr + 0xFE0000; +} + +int hirom_sram_snes_to_pc(const unsigned int snes_addr) +{ + unsigned int bank = snes_addr >> 16; + unsigned int offset = snes_addr & 0x00FFFF; + + if (bank >= 0x20 && bank <= 0x3F && offset >= 0x6000 && offset < 0x8000) + return (bank - 0x20) * 0x2000 + (offset - 0x6000); + return -1; +} + +int hirom_sram_pc_to_snes(const unsigned int pc_addr) +{ + unsigned int chuck_nb = pc_addr / 0x2000; + unsigned int rest = pc_addr % 0x2000; + + return ((0x20 + chuck_nb) << 16) + 0x6000 + rest; +} + +int lorom_pc_to_snes(const unsigned int pc_addr) +{ + + unsigned int bank = pc_addr / 0x8000; + unsigned int offset = pc_addr % 0x8000 + 0x8000; + + //printf("pc_addr: %X - Bank: %X - Offset: %X\n", pc_addr, bank, offset); + + return (bank << 16) + offset; +} + +int lorom_sram_pc_to_snes(const unsigned int pc_addr) +{ + int chuck_nb = pc_addr / 0x8000; + int rest = pc_addr % 0x8000; + + if (chuck_nb <= 0xD) + return ((0x70 + chuck_nb) << 16) + rest; + if (chuck_nb == 0xE || chuck_nb == 0xF) + return ((0xF0 + chuck_nb) << 16) + rest; + return -1; +} + +int lorom_sram_snes_to_pc(const unsigned int snes_addr) +{ + unsigned char bank = snes_addr >> 16; + unsigned int offset = snes_addr & 0x00FFFF; + + // F0-FD are mirror of 70-7D + if (bank >= 0xF0 && bank <= 0xFD) + bank -= 0x80; + if (bank >= 0x70 && bank <= 0x7D && offset < 0x8000) + return (bank - 0x70) * 0x8000 + offset; + if ((bank == 0xFE || bank == 0xFF) && offset < 0x8000) + return ((bank - 0xFE) + 0xE) * 0x8000 + offset; + return -1; +} + +int rommapping_snes_to_pc(const unsigned int snes_addr, enum rom_type rom_type, bool header) +{ + int pc_addr; + char *info; + switch (rom_type) + { + case LoROM: + pc_addr = lorom_snes_to_pc(snes_addr, &info); + break; + case HiROM: + pc_addr = hirom_snes_to_pc(snes_addr, &info); + break; + default: + return -1; + } + + if (pc_addr < 0) { + rommapping_error_text = (char *) malloc(strlen(info) + 1); + strcpy(rommapping_error_text, info); + return pc_addr; + } + if (header) + pc_addr += 0x200; + return pc_addr; +} + +int rommapping_pc_to_snes(const unsigned int pc_addr, enum rom_type rom_type, bool header) +{ + int snes_addr; + + switch (rom_type) + { + case LoROM: + snes_addr = lorom_pc_to_snes(header ? pc_addr - 0x200 : pc_addr); + break; + case HiROM: + snes_addr = hirom_pc_to_snes(header ? pc_addr - 0x200 : pc_addr); + break; + default: + return -1; + } + return snes_addr; +} + + +int rommapping_sram_snes_to_pc(const unsigned int snes_addr, enum rom_type rom_type, bool header) +{ + int pc_addr; + switch (rom_type) + { + case LoROM: + pc_addr = lorom_sram_snes_to_pc(snes_addr); + break; + case HiROM: + pc_addr = hirom_sram_snes_to_pc(snes_addr); + break; + default: + return -1; + } + if (header) + pc_addr += 0x200; + return pc_addr; +} + +int rommapping_sram_pc_to_snes(const unsigned int pc_addr, enum rom_type rom_type, bool header) +{ + int snes_addr; + + switch (rom_type) + { + case LoROM: + snes_addr = lorom_sram_pc_to_snes(header ? pc_addr - 0x200 : pc_addr); + break; + case HiROM: + snes_addr = hirom_sram_pc_to_snes(header ? pc_addr - 0x200 : pc_addr); + break; + default: + return -1; + } + return snes_addr; +} + void ROM::LoadFromFile(const std::string& path) { FILE * file = fopen(path.c_str(), "r+"); if (file == NULL) return; fseek(file, 0, SEEK_END); - long int size = ftell(file); + size = ftell(file); fclose(file); - std::cout << "size: " << size << std::endl; - // Reading data to array of unsigned chars file = fopen(path.c_str(), "r+"); current_rom_ = (unsigned char *) malloc(size); int bytes_read = fread(current_rom_, sizeof(unsigned char), size, file); fclose(file); + memcpy(title, current_rom_, 21); + type = LoROM; + fastrom = (current_rom_[21] & 0b00110000) == 0b00110000; + if (current_rom_[21] & 1) + type = HiROM; + if ((current_rom_[21] & 0b00000111) == 0b00000111) + type = ExHiROM; + + sram_size = 0x400 << current_rom_[24]; + creator_id = (current_rom_[26] << 8) | current_rom_[25]; + version = current_rom_[27]; + checksum_comp = (current_rom_[29] << 8) | current_rom_[28]; + checksum = (current_rom_[31] << 8) | current_rom_[30]; + make_sense = false; + if ((checksum ^ checksum_comp) == 0xFFFF) + make_sense = true; } int ROM::SnesToPc(int addr) { @@ -76,14 +319,6 @@ int ROM::ReadLong(int addr) { current_rom_[addr]); } -Tile16 ROM::ReadTile16(int addr) { - ushort t1 = (ushort)((current_rom_[addr + 1] << 8) + current_rom_[addr]); - ushort t2 = (ushort)((current_rom_[addr + 3] << 8) + current_rom_[addr + 2]); - ushort t3 = (ushort)((current_rom_[addr + 5] << 8) + current_rom_[addr + 4]); - ushort t4 = (ushort)((current_rom_[addr + 7] << 8) + current_rom_[addr + 6]); - return Tile16((unsigned long)((t1 << 48) + (t2 << 32) + (t3 << 16) + t4)); -} - ushort ROM::ReadShort(int addr) { return (ushort)((current_rom_[addr + 1] << 8) + current_rom_[addr]); } diff --git a/src/Application/Utils/ROM.h b/src/Application/Utils/ROM.h index 42809eff..d568f47d 100644 --- a/src/Application/Utils/ROM.h +++ b/src/Application/Utils/ROM.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,33 @@ namespace Utils { using byte = unsigned char; using ushort = unsigned short; +extern "C" { + +enum rom_type { LoROM, HiROM, ExLoROM, ExHiROM }; + +extern char* rommapping_error_text; + +int rommapping_snes_to_pc(const unsigned int snes_addr, enum rom_type rom_type, + bool header); +int rommapping_pc_to_snes(const unsigned int pc_addr, enum rom_type rom_type, + bool header); + +int rommapping_sram_snes_to_pc(const unsigned int snes_addr, + enum rom_type rom_type, bool header); +int rommapping_sram_pc_to_snes(const unsigned int pc_addr, + enum rom_type rom_type, bool header); + +int lorom_snes_to_pc(const unsigned int snes_addr, char** info); +int lorom_sram_snes_to_pc(const unsigned int snes_addr); +int lorom_pc_to_snes(const unsigned int pc_addr); +int lorom_sram_pc_to_snes(const unsigned int pc_addr); + +int hirom_snes_to_pc(const unsigned int snes_addr, char** info); +int hirom_sram_snes_to_pc(const unsigned int snes_addr); +int hirom_pc_to_snes(const unsigned int pc_addr); +int hirom_sram_pc_to_snes(const unsigned int pc_addr); +} + class ROM { public: int SnesToPc(int addr); @@ -31,18 +59,32 @@ class ROM { short ReadReverseShort(int addr); ushort ReadByte(int addr); short ReadRealShort(int addr); - Graphics::Tile16 ReadTile16(int addr); void WriteShort(int addr, int value); int ReadLong(int addr); void WriteLong(int addr, int value); void LoadFromFile(const std::string& path); - inline byte * GetRawData() { return current_rom_; } + inline byte* GetRawData() { return current_rom_; } + + const unsigned char* getTitle() const { return title; } + unsigned int getSize() const { return size; } + char getVersion() const { return version; } private: std::vector original_rom_; std::vector working_rom_; byte* current_rom_; + + enum rom_type type; + bool fastrom; + bool make_sense; + unsigned char title[21]; + long int size; + unsigned int sram_size; + uint16_t creator_id; + unsigned char version; + unsigned char checksum_comp; + unsigned char checksum; }; } // namespace Utils