diff --git a/src/Application/Data/rom.cc b/src/Application/Data/rom.cc index ab9e1236..674d1c48 100644 --- a/src/Application/Data/rom.cc +++ b/src/Application/Data/rom.cc @@ -1,27 +1,30 @@ #include "ROM.h" +#include + namespace yaze { namespace Application { namespace Data { void ROM::LoadFromFile(const std::string &path) { - FILE *file = fopen(path.c_str(), "r+"); - if (file == NULL) return; - fseek(file, 0, SEEK_END); - size = ftell(file); - fclose(file); + type_ = LoROM; + size_ = std::filesystem::file_size(path.c_str()); + std::ifstream file(path.c_str(), std::ios::binary); + if (!file.is_open()) { + std::cout << "Error: Could not open ROM file " << path << std::endl; + } + current_rom_ = new unsigned char[size_]; + data_ = new char[size_]; - // Reading data to array of unsigned chars - file = fopen(path.c_str(), "r+"); - current_rom_ = (unsigned char *)malloc(size); - rom_data_ = (char *)malloc(size); - fread(rom_data_, sizeof(char), size, file); - int bytes_read = fread(current_rom_, sizeof(unsigned char), size, file); - fclose(file); + for (unsigned int i = 0; i < size_; i++) { + char byte_read_ = ' '; + file.read(&byte_read_, sizeof(char)); + current_rom_[i] = byte_read_; + data_[i] = byte_read_; + } - memcpy(title, rom_data_ + 32704, 21); - type = LoROM; - version = current_rom_[27]; + memcpy(title, data_ + 32704, 21); + version_ = current_rom_[27]; loaded = true; } @@ -35,17 +38,19 @@ std::vector ROM::ExtractTiles(TilePreset &preset) { filePos = getRomPosition(preset, tilePos, preset.SNESTilesLocation); std::cout << "ROM Position: " << filePos << " from " << preset.SNESTilesLocation << std::endl; - + // decompress the graphics char *data = (char *)malloc(sizeof(char) * size); - memcpy(data, (rom_data_ + filePos), size); - data = alttp_decompress_gfx(data, 0, size, &size_out, &lastCompressedSize); - std::cout << "size: " << size << std::endl; - std::cout << "lastCompressedSize: " << lastCompressedSize << std::endl; + memcpy(data, (data_ + filePos), size); + //data = alttp_decompress_gfx(data, 0, size, &size_out, &compressed_size_); + // std::cout << "size: " << size << std::endl; + // std::cout << "lastCompressedSize: " << compressed_size_ << std::endl; + data = Decompress(filePos); if (data == NULL) { std::cout << alttp_decompression_error << std::endl; return rawTiles; } + // unpack the tiles based on their depth unsigned tileCpt = 0; std::cout << "Unpacking tiles..." << std::endl; @@ -67,7 +72,7 @@ SNESPalette ROM::ExtractPalette(TilePreset &preset) { std::cout << "Palette pos : " << filePos << std::endl; // TODO: make this hex unsigned int palette_size = pow(2, preset.bpp); // - 1; char *ab = (char *)malloc(sizeof(char) * (palette_size * 2)); - memcpy(ab, rom_data_ + filePos, palette_size * 2); + memcpy(ab, data_ + filePos, palette_size * 2); for (int i = 0; i < palette_size; i++) { std::cout << ab[i]; @@ -90,7 +95,6 @@ SNESPalette ROM::ExtractPalette(TilePreset &preset) { unsigned int ROM::getRomPosition(const TilePreset &preset, int directAddr, unsigned int snesAddr) { bool romHasHeader = false; // romInfo.hasHeader - if (overrideHeaderInfo) romHasHeader = overridenHeaderInfo; unsigned int filePos = -1; enum rom_type rType = LoROM; std::cout << "ROM::getRomPosition: directAddr:" << directAddr << std::endl; @@ -112,6 +116,79 @@ short ROM::AddressFromBytes(byte addr1, byte addr2) { return (short)((addr1 << 8) | (addr2)); } +char *ROM::Decompress(int pos, bool reversed) { + char *buffer = new char[0x600]; + for (int i = 0; i < 0x600; i++) { + buffer[i] = 0; + } + unsigned int bufferPos = 0; + unsigned char cmd = 0; + unsigned int length = 0; + unsigned char databyte = (unsigned char)data_[pos]; + while (true) { + databyte = (unsigned char)data_[pos]; + if (databyte == 0xFF) // End of decompression + { + break; + } + + if ((databyte & 0xE0) == 0xE0) // Expanded Command + { + cmd = (unsigned char)((databyte >> 2) & 0x07); + length = (unsigned short)(((data_[pos] << 8) | data_[pos + 1]) & 0x3FF); + pos += 2; // Advance 2 bytes in ROM + } else // Normal Command + { + cmd = (unsigned char)((databyte >> 5) & 0x07); + length = (unsigned char)(databyte & 0x1F); + pos += 1; // Advance 1 byte in ROM + } + length += 1; // Every commands are at least 1 size even if 00 + switch (cmd) { + case 00: // Direct Copy (Could be replaced with a MEMCPY) + for (int i = 0; i < length; i++) { + buffer[bufferPos++] = (unsigned char)data_[pos++]; + } + // Do not advance in the ROM + break; + case 01: // Byte Fill + for (int i = 0; i < length; i++) { + buffer[bufferPos++] = (unsigned char)data_[pos]; + } + pos += 1; // Advance 1 byte in the ROM + break; + case 02: // Word Fill + for (int i = 0; i < length; i++) { + buffer[bufferPos++] = (unsigned char)data_[pos]; + buffer[bufferPos++] = (unsigned char)data_[pos + 1]; + } + pos += 2; // Advance 2 byte in the ROM + break; + case 03: // Increasing Fill + { + unsigned char incByte = (unsigned char)data_[pos]; + for (int i = 0; i < (unsigned int)length; i++) { + buffer[bufferPos++] = (unsigned char)incByte++; + } + pos += 1; // Advance 1 byte in the ROM + } break; + case 04: // Repeat (Reversed byte order for maps) + { + unsigned short s1 = ((data_[pos + 1] & 0xFF) << 8); + unsigned short s2 = ((data_[pos] & 0xFF)); + unsigned short Addr = (unsigned short)(s1 | s2); + printf("Repeat Address : %4X", Addr); + for (int i = 0; i < length; i++) { + buffer[bufferPos] = (unsigned char)buffer[Addr + i]; + bufferPos++; + } + pos += 2; // Advance 2 bytes in the ROM + } break; + } + } + return buffer; +} + } // namespace Data } // namespace Application } // namespace yaze \ No newline at end of file diff --git a/src/Application/Data/rom.h b/src/Application/Data/rom.h index d8070e67..be7e221d 100644 --- a/src/Application/Data/rom.h +++ b/src/Application/Data/rom.h @@ -35,28 +35,27 @@ class ROM { unsigned int getRomPosition(const TilePreset& preset, int directAddr, unsigned int snesAddr); short AddressFromBytes(byte addr1, byte addr2); + char* Decompress(int pos, bool reversed = false); + inline byte* GetRawData() { return current_rom_; } const unsigned char* getTitle() const { return title; } - unsigned int getSize() const { return size; } - char getVersion() const { return version; } + unsigned int getSize() const { return size_; } + char getVersion() const { return version_; } bool isLoaded() const { return loaded; } private: bool loaded = false; byte* current_rom_; - char* rom_data_; + char* data_; - bool fastrom; - long int size; - enum rom_type type; + long int size_; + enum rom_type type_; - bool overrideHeaderInfo; - bool overridenHeaderInfo; - unsigned int lastUnCompressSize; - unsigned int lastCompressedSize; - unsigned int lastCompressSize; - unsigned char version; + unsigned int uncompressed_size_; + unsigned int compressed_size_; + unsigned int compress_size_; + unsigned char version_; unsigned char title[21] = "ROM Not Loaded"; };