implemented zarbys decompression and conversion code to get a graphics sheet on the screen finally

This commit is contained in:
Justin Scofield
2022-06-19 11:57:42 -04:00
parent 4734062067
commit 39f451b3fc
4 changed files with 119 additions and 58 deletions

View File

@@ -115,15 +115,7 @@ uint32_t ROM::GetRomPosition(int direct_addr, uint snes_addr) const {
return filePos;
}
uchar* ROM::LoadGraphicsSheet(int offset) {
auto tilesheet_position = Core::Constants::gfx_1_pointer +
(offset * Core::Constants::UncompressedSheetSize);
auto data = Decompress(tilesheet_position);
return SNES3bppTo8bppSheet((uchar*)data);
}
// char *buffer = new char[0x800] AKA sheet_buffer_in 3bpp
uchar *ROM::SNES3bppTo8bppSheet(uchar *sheet_buffer_in) // 128x32
uchar *ROM::SNES3bppTo8bppSheet(uchar *buffer_in, int sheet_id) // 128x32
{
// 8bpp sheet out
const uchar bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
@@ -132,6 +124,11 @@ uchar *ROM::SNES3bppTo8bppSheet(uchar *sheet_buffer_in) // 128x32
int yy = 0;
int pos = 0;
int ypos = 0;
if (sheet_id != 0) {
yy = sheet_id;
}
for (int i = 0; i < 64; i++) // for each tiles //16 per lines
{
for (int y = 0; y < 8; y++) // for each lines
@@ -139,12 +136,12 @@ uchar *ROM::SNES3bppTo8bppSheet(uchar *sheet_buffer_in) // 128x32
//[0] + [1] + [16]
for (int x = 0; x < 8; x++) {
unsigned char b1 = (unsigned char)((
sheet_buffer_in[(y * 2) + (24 * pos)] & (bitmask[x])));
buffer_in[(y * 2) + (24 * pos)] & (bitmask[x])));
unsigned char b2 =
(unsigned char)(sheet_buffer_in[((y * 2) + (24 * pos)) + 1] &
(unsigned char)(buffer_in[((y * 2) + (24 * pos)) + 1] &
(bitmask[x]));
unsigned char b3 =
(unsigned char)(sheet_buffer_in[(16 + y) + (24 * pos)] &
(unsigned char)(buffer_in[(16 + y) + (24 * pos)] &
(bitmask[x]));
unsigned char b = 0;
if (b1 != 0) {
@@ -180,7 +177,7 @@ char *ROM::Decompress(int pos, bool reversed) {
unsigned char cmd = 0;
unsigned int length = 0;
unsigned char databyte = (unsigned char)current_rom_[pos];
uchar databyte = current_rom_[pos];
while (true) {
databyte = (unsigned char)current_rom_[pos];
if (databyte == 0xFF) // End of decompression
@@ -246,6 +243,40 @@ char *ROM::Decompress(int pos, bool reversed) {
return buffer;
}
SDL_Surface* ROM::GetGraphicsSheet(int num_sheets) {
int height = 32 * num_sheets;
SDL_Surface *surface =
SDL_CreateRGBSurfaceWithFormat(0, 128, height, 8, SDL_PIXELFORMAT_INDEX8);
std::cout << "Drawing surface" << std::endl;
uchar *sheet_buffer = nullptr;
// int sheet_buffer_pos = 0;
for (int i = 0; i < 8; i++) {
surface->format->palette->colors[i].r = (unsigned char)(i * 31);
surface->format->palette->colors[i].g = (unsigned char)(i * 31);
surface->format->palette->colors[i].b = (unsigned char)(i * 31);
}
unsigned int snesAddr = 0;
unsigned int pcAddr = 0;
for (int i = 0; i < num_sheets; i++) {
snesAddr =
(unsigned int)((((unsigned char)(current_rom_[0x4F80 + i]) <<
16) |
((unsigned char)(current_rom_[0x505F + i]) << 8)
|
((unsigned char)(current_rom_[0x513E]))));
pcAddr = SnesToPc(snesAddr);
std::cout << "Decompressing..." << std::endl;
char *decomp = Decompress(pcAddr);
std::cout << "Converting to 8bpp sheet..." << std::endl;
sheet_buffer = SNES3bppTo8bppSheet((uchar *)decomp, i);
std::cout << "Assigning pixel data..." << std::endl;
}
surface->pixels = sheet_buffer;
return surface;
}
int AddressFromBytes(uchar addr1, uchar addr2, uchar addr3) {
return (addr1 << 16) | (addr2 << 8) | addr3;
}

View File

@@ -35,11 +35,20 @@ class ROM {
const uchar* getTitle() const { return title; }
long int getSize() const { return size_; }
char getVersion() const { return version_; }
bool isLoaded() const { return loaded; }
uchar* LoadGraphicsSheet(int offset);
uchar* SNES3bppTo8bppSheet(uchar *sheet_buffer_in);
bool isLoaded() const { return loaded; }
uchar* SNES3bppTo8bppSheet(uchar* buffer_in, int sheet_id = 0);
char* Decompress(int pos, bool reversed = false);
SDL_Surface* GetGraphicsSheet(int num_sheets);
unsigned int SnesToPc(unsigned int addr) {
if (addr >= 0x808000) {
addr -= 0x808000;
}
unsigned int temp = (addr & 0x7FFF) + ((addr / 2) & 0xFF8000);
return (temp + 0x0);
}
private:
bool loaded = false;
@@ -54,8 +63,7 @@ class ROM {
enum rom_type type_ = LoROM;
std::shared_ptr<uchar> rom_ptr_;
std::unordered_map<unsigned int, std::shared_ptr<uchar[2048]>>
decompressed_sheets;
std::vector<SDL_Surface> surfaces_;
};
} // namespace Data

View File

@@ -290,49 +290,77 @@ void Editor::DrawSurface() {
}
}
void Editor::DrawGraphicsSheet(int offset) {
SDL_Surface *surface =
SDL_CreateRGBSurfaceWithFormat(0, 128, 32, 8, SDL_PIXELFORMAT_INDEX8);
std::cout << "Drawing surface" << std::endl;
uchar *sheet_buffer = nullptr;
for (int i = 0; i < 8; i++) {
surface->format->palette->colors[i].r = (unsigned char)(i * 31);
surface->format->palette->colors[i].g = (unsigned char)(i * 31);
surface->format->palette->colors[i].b = (unsigned char)(i * 31);
}
unsigned int snesAddr = 0;
unsigned int pcAddr = 0;
snesAddr = (unsigned int)((
((unsigned char)(rom_.GetRawData()[0x4F80 + offset]) << 16) |
((unsigned char)(rom_.GetRawData()[0x505F + offset]) << 8) |
((unsigned char)(rom_.GetRawData()[0x513E]))));
pcAddr = rom_.SnesToPc(snesAddr);
std::cout << "Decompressing..." << std::endl;
char *decomp = rom_.Decompress(pcAddr);
std::cout << "Converting to 8bpp sheet..." << std::endl;
sheet_buffer = rom_.SNES3bppTo8bppSheet((uchar *)decomp);
std::cout << "Assigning pixel data..." << std::endl;
surface->pixels = sheet_buffer;
std::cout << "Creating texture from surface..." << std::endl;
sheet_texture = SDL_CreateTextureFromSurface(sdl_renderer_.get(), surface);
if (sheet_texture == nullptr) {
std::cout << "Error: " << SDL_GetError() << std::endl;
}
}
void Editor::DrawProjectEditor() {
if (ImGui::BeginTabItem("Project")) {
if (ImGui::BeginTable("##projectTable", 2,
ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableSetupColumn("##inputs");
ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable)) {
ImGui::TableSetupColumn("##inputs", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##outputs");
ImGui::TableNextColumn();
ImGui::Text("Title: %s", rom_.getTitle());
ImGui::Text("Version: %d", rom_.getVersion());
ImGui::Text("ROM Size: %ld", rom_.getSize());
ImGui::Separator();
// ----------------------------------------------------------------------
static bool loaded_image = false;
static int tilesheet_offset = 0;
ImGui::InputInt("Tilesheet Offset", &tilesheet_offset);
ImGui::Text("Zarby Retrieval Code");
BASIC_BUTTON("Retrieve Graphics") {
if (rom_.isLoaded()) {
DrawGraphicsSheet(tilesheet_offset);
loaded_image = true;
}
}
ImGui::Separator();
// ----------------------------------------------------------------------
ImGui::InputInt("Bits per Pixel", &current_set_.bits_per_pixel_);
yaze::Gui::InputHex("PC Tile Location", &current_set_.pc_tiles_location_);
yaze::Gui::InputHex("SNES Tile Location",
&current_set_.SNESTilesLocation);
ImGui::InputInt("Tile Preset Length", &current_set_.length_);
ImGui::InputInt("PC Palette Location",
&current_set_.pc_palette_location_);
yaze::Gui::InputHex("SNES Palette Location",
&current_set_.SNESPaletteLocation);
static bool loaded_image = false;
static uchar* image_data = nullptr;
ImGui::Text("Zarby Retrieval Code");
BASIC_BUTTON("Retrieve Graphics") {
if (rom_.isLoaded()) {
if (!loaded_image) {
image_data = rom_.LoadGraphicsSheet(current_set_.pc_tiles_location_);
loaded_image = true;
} else {
// TODO: build the sdl surface from the tilesheet data
}
}
}
ImGui::Separator();
ImGui::Text("Skarsnik Retrieval Code");
BASIC_BUTTON("ExtractTiles") {
if (rom_.isLoaded()) {
@@ -370,7 +398,8 @@ void Editor::DrawProjectEditor() {
static bool opt_enable_context_menu = true;
static bool opt_enable_grid = true;
ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
// ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
ImVec2 canvas_sz = ImVec2(512 + 1, ImGui::GetContentRegionAvail().y);
ImVec2 canvas_p1 =
ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
@@ -414,7 +443,7 @@ void Editor::DrawProjectEditor() {
// Draw grid + all lines in the canvas
draw_list->PushClipRect(canvas_p0, canvas_p1, true);
if (opt_enable_grid) {
const float GRID_STEP = 64.0f;
const float GRID_STEP = 32.0f;
for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x;
x += GRID_STEP)
draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y),
@@ -427,20 +456,10 @@ void Editor::DrawProjectEditor() {
IM_COL32(200, 200, 200, 40));
}
if (current_scene_.imagesCache.size() != 0) {
for (const auto &[key, value] : current_scene_.imagesCache) {
const float GRID_STEP = 8.0f;
float x = fmodf(scrolling.x, GRID_STEP);
float y = fmodf(scrolling.y, GRID_STEP);
draw_list->AddImage((void *)(SDL_Surface *)value,
ImVec2(canvas_p0.x + x, canvas_p0.y),
ImVec2(canvas_p0.x + x, canvas_p1.y));
x += GRID_STEP;
if (x == 128) {
x = 0;
y += GRID_STEP;
}
}
if (loaded_image) {
draw_list->AddImage((void *)(SDL_Texture *)sheet_texture,
ImVec2(canvas_p0.x + 2, canvas_p0.y + 2),
ImVec2(canvas_p0.x + 512, canvas_p0.y + 128));
}
draw_list->PopClipRect();

View File

@@ -32,6 +32,9 @@ class Editor {
void DrawHelpMenu() const;
void DrawSurface();
void DrawGraphicsSheet(int offset = 0);
void DrawProjectEditor();
void DrawOverworldEditor();
void DrawDungeonEditor();
@@ -46,6 +49,7 @@ class Editor {
std::vector<std::vector<tile8>> arranged_tiles_;
std::unordered_map<unsigned int, std::shared_ptr<SDL_Texture>> texture_cache_;
std::unordered_map<unsigned int, SDL_Texture *> imagesCache;
SDL_Texture *sheet_texture = nullptr;
std::shared_ptr<SDL_Renderer> sdl_renderer_;
Data::ROM rom_;
@@ -53,7 +57,6 @@ class Editor {
TextEditor::LanguageDefinition language_65816_;
OverworldEditor overworld_editor_;
Graphics::Scene current_scene_;
Graphics::SNESPalette current_palette_;
Graphics::TilePreset current_set_;