From bbef72a9b03215f863b0d3cd998b1641967b13a9 Mon Sep 17 00:00:00 2001 From: Justin Scofield Date: Sun, 24 Jul 2022 00:01:05 -0400 Subject: [PATCH] Reoragnize V2 functions in ROM --- src/app/rom.cc | 311 ++++++++++++++++++++++++------------------------- src/app/rom.h | 9 +- 2 files changed, 157 insertions(+), 163 deletions(-) diff --git a/src/app/rom.cc b/src/app/rom.cc index 035a26ef..b87dd178 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -40,6 +40,159 @@ absl::Status ROM::OpenFromFile(const absl::string_view &filename) { return absl::OkStatus(); } +absl::Status ROM::LoadAllGraphicsDataV2() { + Bytes sheet; + int buffer_pos = 0; + + for (int i = 0; i < core::NumberOfSheets; i++) { + if (i >= 115 && i <= 126) { // uncompressed sheets + sheet.resize(core::Uncompressed3BPPSize); + auto offset = GetGraphicsAddress(i); + for (int j = 0; j < core::Uncompressed3BPPSize; j++) { + sheet[j] = rom_data_[j + offset]; + } + } else { + auto offset = GetGraphicsAddress(i); + absl::StatusOr new_sheet = + DecompressV2(offset, core::UncompressedSheetSize); + if (!new_sheet.ok()) { + return new_sheet.status(); + } else { + sheet = std::move(*new_sheet); + } + } + + absl::StatusOr converted_sheet = Convert3bppTo8bppSheet(sheet); + if (!converted_sheet.ok()) { + return converted_sheet.status(); + } else { + Bytes result = std::move(*converted_sheet); + gfx::Bitmap tilesheet_bmp(core::kTilesheetWidth, core::kTilesheetHeight, + core::kTilesheetDepth, result.data()); + tilesheet_bmp.CreateTexture(renderer_); + graphics_bin_v2_[i] = tilesheet_bmp; + } + } + return absl::OkStatus(); +} + +absl::StatusOr ROM::DecompressV2(int offset, int size, bool reversed) { + Bytes buffer(size); + uint length = 0; + uint buffer_pos = 0; + uchar cmd = 0; + uchar databyte = rom_data_[offset]; + while (databyte != 0xFF) { // End of decompression + databyte = rom_data_[offset]; + + if ((databyte & 0xE0) == 0xE0) { // Expanded Command + cmd = ((databyte >> 2) & 0x07); + length = (((rom_data_[offset] << 8) | rom_data_[offset + 1]) & 0x3FF); + offset += 2; // Advance 2 bytes in ROM + } else { // Normal Command + cmd = ((databyte >> 5) & 0x07); + length = (databyte & 0x1F); + offset += 1; // Advance 1 byte in ROM + } + length += 1; // each commands is at least of size 1 even if index 00 + + switch (cmd) { + case kCommandDirectCopy: // Does not advance in the ROM + for (int i = 0; i < length; i++) + buffer[buffer_pos++] = rom_data_[offset++]; + break; + case kCommandByteFill: // Advances 1 byte in the ROM + for (int i = 0; i < length; i++) + buffer[buffer_pos++] = rom_data_[offset]; + offset += 1; + break; + case kCommandWordFill: // Advance 2 byte in the ROM + for (int i = 0; i < length; i += 2) { + buffer[buffer_pos++] = rom_data_[offset]; + buffer[buffer_pos++] = rom_data_[offset + 1]; + } + offset += 2; + break; + case kCommandIncreasingFill: { + uchar inc_byte = rom_data_[offset]; + for (int i = 0; i < length; i++) buffer[buffer_pos++] = inc_byte++; + offset += 1; // Advance 1 byte in the ROM + } break; + case kCommandRepeatingBytes: { + ushort s1 = ((rom_data_[offset + 1] & 0xFF) << 8); + ushort s2 = ((rom_data_[offset] & 0xFF)); + if (reversed) { // Reversed byte order for overworld maps + auto addr = (rom_data_[offset + 2]) | ((rom_data_[offset + 1]) << 8); + if (addr > buffer_pos) { + return absl::InternalError(absl::StrFormat( + "DecompressOverworldV2: Offset for command copy exceeds " + "current position (Offset : %#04x | Pos : %#06x)\n", + addr, buffer_pos)); + } + if (buffer_pos + length >= size) { + size *= 2; + buffer.resize(size); + } + memcpy(buffer.data() + buffer_pos, rom_data_.data() + offset, length); + offset += 2; + } else { + auto addr = (ushort)(s1 | s2); + for (int i = 0; i < length; i++) { + buffer[buffer_pos] = buffer[addr + i]; + buffer_pos++; + } + offset += 2; // Advance 2 bytes in the ROM + } + } break; + } + } + + return buffer; +} + +absl::StatusOr ROM::Convert3bppTo8bppSheet(Bytes sheet, int size) { + Bytes sheet_buffer_out(size); + int xx = 0; // positions where we are at on the sheet + int yy = 0; + int pos = 0; + int ypos = 0; + + // for each tiles, 16 per line + for (int i = 0; i < 64; i++) { + // for each line + for (int y = 0; y < 8; y++) { + //[0] + [1] + [16] + for (int x = 0; x < 8; x++) { + auto b1 = ((sheet[(y * 2) + (24 * pos)] & (kGraphicsBitmap[x]))); + auto b2 = (sheet[((y * 2) + (24 * pos)) + 1] & (kGraphicsBitmap[x])); + auto b3 = (sheet[(16 + y) + (24 * pos)] & (kGraphicsBitmap[x])); + unsigned char b = 0; + if (b1 != 0) { + b |= 1; + } + if (b2 != 0) { + b |= 2; + } + if (b3 != 0) { + b |= 4; + } + sheet_buffer_out[x + (xx) + (y * 128) + (yy * 1024)] = b; + } + } + pos++; + ypos++; + xx += 8; + if (ypos >= 16) { + yy++; + xx = 0; + ypos = 0; + } + } + return sheet_buffer_out; +} + +// ---------------------------------------------------------------------------- + void ROM::Close() { if (is_loaded_) { delete[] current_rom_; @@ -113,42 +266,6 @@ void ROM::LoadAllGraphicsData() { master_gfx_bin_ = buffer; } -absl::Status ROM::LoadAllGraphicsDataV2() { - Bytes sheet; - int buffer_pos = 0; - - for (int i = 0; i < core::NumberOfSheets; i++) { - if (i >= 115 && i <= 126) { // uncompressed sheets - sheet.resize(core::Uncompressed3BPPSize); - auto offset = GetGraphicsAddress(i); - for (int j = 0; j < core::Uncompressed3BPPSize; j++) { - sheet[j] = rom_data_[j + offset]; - } - } else { - auto offset = GetGraphicsAddress(i); - absl::StatusOr new_sheet = - DecompressV2(offset, core::UncompressedSheetSize); - if (!new_sheet.ok()) { - return new_sheet.status(); - } else { - sheet = std::move(*new_sheet); - } - } - - absl::StatusOr converted_sheet = Convert3bppTo8bppSheet(sheet); - if (!converted_sheet.ok()) { - return converted_sheet.status(); - } else { - Bytes result = std::move(*converted_sheet); - gfx::Bitmap tilesheet_bmp(core::kTilesheetWidth, core::kTilesheetHeight, - core::kTilesheetDepth, result.data()); - tilesheet_bmp.CreateTexture(renderer_); - graphics_bin_v2_[i] = tilesheet_bmp; - } - } - return absl::OkStatus(); -} - uint ROM::GetGraphicsAddress(uint8_t offset) const { uint snes_address = 0; uint pc_address = 0; @@ -246,128 +363,6 @@ uchar *ROM::Decompress(int pos, int size, bool reversed) { return buffer; } -absl::StatusOr ROM::DecompressV2(int offset, int size, bool reversed) { - Bytes buffer(size); - uint length = 0; - uint buffer_pos = 0; - uchar cmd = 0; - - uchar databyte = rom_data_[offset]; - while (databyte != 0xFF) { // End of decompression - databyte = rom_data_[offset]; - - // Expanded Command - if ((databyte & 0xE0) == 0xE0) { - cmd = ((databyte >> 2) & 0x07); - length = (((rom_data_[offset] << 8) | rom_data_[offset + 1]) & 0x3FF); - offset += 2; // Advance 2 bytes in ROM - } else { // Normal Command - cmd = ((databyte >> 5) & 0x07); - length = (databyte & 0x1F); - offset += 1; // Advance 1 byte in ROM - } - length += 1; // each commands is at least of size 1 even if index 00 - - switch (cmd) { - case kCommandDirectCopy: - for (int i = 0; i < length; i++) - buffer[buffer_pos++] = rom_data_[offset++]; - // Do not advance in the ROM - break; - case kCommandByteFill: - for (int i = 0; i < length; i++) - buffer[buffer_pos++] = rom_data_[offset]; - offset += 1; // Advance 1 byte in the ROM - break; - case kCommandWordFill: - for (int i = 0; i < length; i += 2) { - buffer[buffer_pos++] = rom_data_[offset]; - buffer[buffer_pos++] = rom_data_[offset + 1]; - } - offset += 2; // Advance 2 byte in the ROM - break; - case kCommandIncreasingFill: { - uchar inc_byte = rom_data_[offset]; - for (int i = 0; i < length; i++) buffer[buffer_pos++] = inc_byte++; - offset += 1; // Advance 1 byte in the ROM - } break; - case kCommandRepeatingBytes: { - ushort s1 = ((rom_data_[offset + 1] & 0xFF) << 8); - ushort s2 = ((rom_data_[offset] & 0xFF)); - // Reversed byte order for overworld maps - if (reversed) { - auto addr = (rom_data_[offset + 2]) | ((rom_data_[offset + 1]) << 8); - if (addr > buffer_pos) { - return absl::InternalError( - absl::StrFormat("DecompressOverworldV2: Offset for command " - "copy existing is larger than the current " - "position (Offset : %#04x | Pos %#06x\n", - addr, buffer_pos)); - } - - if (buffer_pos + length >= size) { - size *= 2; - buffer.resize(size); - std::cout << "DecompressOverworldV2: Reallocating buffer"; - } - memcpy(buffer.data() + buffer_pos, rom_data_.data() + offset, length); - offset += 2; - } else { - auto addr = (ushort)(s1 | s2); - for (int i = 0; i < length; i++) { - buffer[buffer_pos] = buffer[addr + i]; - buffer_pos++; - } - offset += 2; // Advance 2 bytes in the ROM - } - } break; - } - } - - return buffer; -} - -absl::StatusOr ROM::Convert3bppTo8bppSheet(Bytes sheet, int size) { - Bytes sheet_buffer_out(size); - int xx = 0; // positions where we are at on the sheet - int yy = 0; - int pos = 0; - int ypos = 0; - - // for each tiles, 16 per line - for (int i = 0; i < 64; i++) { - // for each line - for (int y = 0; y < 8; y++) { - //[0] + [1] + [16] - for (int x = 0; x < 8; x++) { - auto b1 = ((sheet[(y * 2) + (24 * pos)] & (kGraphicsBitmap[x]))); - auto b2 = (sheet[((y * 2) + (24 * pos)) + 1] & (kGraphicsBitmap[x])); - auto b3 = (sheet[(16 + y) + (24 * pos)] & (kGraphicsBitmap[x])); - unsigned char b = 0; - if (b1 != 0) { - b |= 1; - } - if (b2 != 0) { - b |= 2; - } - if (b3 != 0) { - b |= 4; - } - sheet_buffer_out[x + (xx) + (y * 128) + (yy * 1024)] = b; - } - } - pos++; - ypos++; - xx += 8; - if (ypos >= 16) { - yy++; - xx = 0; - ypos = 0; - } - } - return sheet_buffer_out; -} - // 128x32 uchar *ROM::SNES3bppTo8bppSheet(uchar *buffer_in, int sheet_id, int size) { // 8bpp sheet out diff --git a/src/app/rom.h b/src/app/rom.h index 3df7a519..124adb12 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -41,6 +41,10 @@ struct OWMapTiles { class ROM { public: absl::Status OpenFromFile(const absl::string_view& filename); + absl::StatusOr DecompressV2(int offset, int size = 0x800, + bool reversed = false); + absl::StatusOr Convert3bppTo8bppSheet(Bytes sheet, int size = 0x1000); + absl::Status LoadAllGraphicsDataV2(); // absl::Status SaveOverworld(); // absl::Status SaveDungeons(); @@ -57,11 +61,6 @@ class ROM { uchar* DecompressOverworld(int pos, int size); uchar* Decompress(int pos, int size = 0x800, bool reversed = false); - absl::StatusOr DecompressV2(int offset, int size = 0x800, - bool reversed = false); - absl::StatusOr Convert3bppTo8bppSheet(Bytes sheet, int size = 0x1000); - absl::Status LoadAllGraphicsDataV2(); - uchar* SNES3bppTo8bppSheet(uchar* buffer_in, int sheet_id = 0, int size = 0x1000);