Add scad_format for CGX, COL, OBJ files
This commit is contained in:
@@ -23,6 +23,7 @@ set(
|
||||
YAZE_APP_GFX_SRC
|
||||
app/gfx/bitmap.cc
|
||||
app/gfx/compression.cc
|
||||
app/gfx/scad_format.cc
|
||||
app/gfx/snes_palette.cc
|
||||
app/gfx/snes_tile.cc
|
||||
)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "app/editor/palette_editor.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/compression.h"
|
||||
#include "app/gfx/scad_format.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/input.h"
|
||||
@@ -114,7 +116,10 @@ absl::Status GraphicsEditor::DrawCgxImport() {
|
||||
strncpy(cgx_file_name_,
|
||||
ImGuiFileDialog::Instance()->GetCurrentFileName().c_str(),
|
||||
sizeof(cgx_file_name_));
|
||||
status_ = temp_rom_.LoadFromFile(cgx_file_path_, /*z3_load=*/false);
|
||||
// status_ = temp_rom_.LoadFromFile(cgx_file_path_, /*z3_load=*/false);
|
||||
status_ = gfx::DecodeCgxFile(cgx_file_path_, cgx_data_, extra_cgx_data_,
|
||||
decoded_cgx_);
|
||||
auto cgx_header = gfx::ExtractCgxHeader(extra_cgx_data_);
|
||||
is_open_ = true;
|
||||
cgx_loaded_ = true;
|
||||
});
|
||||
@@ -122,17 +127,69 @@ absl::Status GraphicsEditor::DrawCgxImport() {
|
||||
[this]() { ImGui::SetClipboardText(cgx_file_path_); });
|
||||
|
||||
core::ButtonPipe("Decompress CGX Data", [this]() {
|
||||
/*
|
||||
cgx_viewer_.LoadCgx(temp_rom_);
|
||||
auto all_tiles_data = cgx_viewer_.GetCgxData();
|
||||
cgx_bitmap_.Create(core::kTilesheetWidth, 8192, core::kTilesheetDepth,
|
||||
all_tiles_data.data(), all_tiles_data.size());
|
||||
*/
|
||||
// cgx_surface_ = gfx::CreateCgxPreviewImage(current_palette_index_,
|
||||
// cgx_data_,
|
||||
// extra_cgx_data_, decoded_col_);
|
||||
// cgx_bitmap_.CreateFromSurface(cgx_surface_);
|
||||
|
||||
cgx_bitmap_.Create(0x80, 0x200, 8, decoded_cgx_);
|
||||
if (col_file_) {
|
||||
cgx_bitmap_.ApplyPalette(col_file_palette_);
|
||||
// cgx_bitmap_.ApplyPalette(col_file_palette_);
|
||||
cgx_bitmap_.ApplyPalette(decoded_col_);
|
||||
rom_.RenderBitmap(&cgx_bitmap_);
|
||||
}
|
||||
});
|
||||
|
||||
CLEAR_AND_RETURN_STATUS(status_)
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status GraphicsEditor::DrawPaletteControls() {
|
||||
gui::TextWithSeparators("COL Import");
|
||||
ImGui::InputText("##ColFile", col_file_name_, sizeof(col_file_name_));
|
||||
ImGui::SameLine();
|
||||
|
||||
core::FileDialogPipeline(
|
||||
"ImportColKey", ".COL,.col,.BAK,.bak\0", "Open COL", [this]() {
|
||||
strncpy(col_file_path_,
|
||||
ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
|
||||
sizeof(col_file_path_));
|
||||
strncpy(col_file_name_,
|
||||
ImGuiFileDialog::Instance()->GetCurrentFileName().c_str(),
|
||||
sizeof(col_file_name_));
|
||||
status_ = temp_rom_.LoadFromFile(col_file_path_,
|
||||
/*z3_load=*/false);
|
||||
auto col_data_ = gfx::GetColFileData(temp_rom_.data());
|
||||
if (col_file_palette_group_.size() != 0) {
|
||||
col_file_palette_group_.Clear();
|
||||
}
|
||||
col_file_palette_group_ = gfx::CreatePaletteGroupFromColFile(col_data_);
|
||||
col_file_palette_ = gfx::SNESPalette(col_data_);
|
||||
|
||||
// gigaleak dev format based code
|
||||
decoded_col_ = gfx::DecodeColFile(col_file_path_);
|
||||
col_file_ = true;
|
||||
is_open_ = true;
|
||||
});
|
||||
|
||||
core::ButtonPipe("Copy COL Path",
|
||||
[this]() { ImGui::SetClipboardText(col_file_path_); });
|
||||
|
||||
if (rom_.isLoaded()) {
|
||||
gui::TextWithSeparators("ROM Palette");
|
||||
gui::InputHex("Palette Index", ¤t_palette_index_);
|
||||
ImGui::Combo("Palette", ¤t_palette_, kPaletteGroupAddressesKeys,
|
||||
IM_ARRAYSIZE(kPaletteGroupAddressesKeys));
|
||||
}
|
||||
|
||||
if (col_file_palette_.size() != 0) {
|
||||
core::SelectablePalettePipeline(current_palette_index_, refresh_graphics_,
|
||||
col_file_palette_);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -167,49 +224,6 @@ absl::Status GraphicsEditor::DrawFileImport() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status GraphicsEditor::DrawPaletteControls() {
|
||||
gui::TextWithSeparators("COL Import");
|
||||
ImGui::InputText("##ColFile", col_file_name_, sizeof(col_file_name_));
|
||||
ImGui::SameLine();
|
||||
|
||||
core::FileDialogPipeline(
|
||||
"ImportColKey", ".COL,.col,.BAK,.bak\0", "Open COL", [this]() {
|
||||
strncpy(col_file_path_,
|
||||
ImGuiFileDialog::Instance()->GetFilePathName().c_str(),
|
||||
sizeof(col_file_path_));
|
||||
strncpy(col_file_name_,
|
||||
ImGuiFileDialog::Instance()->GetCurrentFileName().c_str(),
|
||||
sizeof(col_file_name_));
|
||||
status_ = temp_rom_.LoadFromFile(col_file_path_,
|
||||
/*z3_load=*/false);
|
||||
auto col_data_ = gfx::GetColFileData(temp_rom_.data());
|
||||
if (col_file_palette_group_.size() != 0) {
|
||||
col_file_palette_group_.Clear();
|
||||
}
|
||||
col_file_palette_group_ = gfx::CreatePaletteGroupFromColFile(col_data_);
|
||||
col_file_palette_ = gfx::SNESPalette(col_data_);
|
||||
col_file_ = true;
|
||||
is_open_ = true;
|
||||
});
|
||||
|
||||
core::ButtonPipe("Copy COL Path",
|
||||
[this]() { ImGui::SetClipboardText(col_file_path_); });
|
||||
|
||||
if (rom_.isLoaded()) {
|
||||
gui::TextWithSeparators("ROM Palette");
|
||||
gui::InputHex("Palette Index", ¤t_palette_index_);
|
||||
ImGui::Combo("Palette", ¤t_palette_, kPaletteGroupAddressesKeys,
|
||||
IM_ARRAYSIZE(kPaletteGroupAddressesKeys));
|
||||
}
|
||||
|
||||
if (col_file_palette_.size() != 0) {
|
||||
core::SelectablePalettePipeline(current_palette_index_, refresh_graphics_,
|
||||
col_file_palette_);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status GraphicsEditor::DrawClipboardImport() {
|
||||
gui::TextWithSeparators("Clipboard Import");
|
||||
core::ButtonPipe("Paste from Clipboard", [this]() {
|
||||
|
||||
@@ -111,6 +111,13 @@ class GraphicsEditor {
|
||||
Bytes import_data_;
|
||||
Bytes graphics_buffer_;
|
||||
|
||||
std::vector<uint8_t> decoded_cgx_;
|
||||
std::vector<uint8_t> cgx_data_;
|
||||
std::vector<uint8_t> extra_cgx_data_;
|
||||
std::vector<SDL_Color> decoded_col_;
|
||||
|
||||
SDL_Surface* cgx_surface_;
|
||||
|
||||
MemoryEditor cgx_memory_editor_;
|
||||
MemoryEditor col_memory_editor_;
|
||||
|
||||
|
||||
@@ -36,14 +36,14 @@ namespace editor {
|
||||
absl::Status PaletteEditor::Update() {
|
||||
for (int i = 0; i < kNumPalettes; ++i) {
|
||||
if (ImGui::TreeNode(kPaletteCategoryNames[i].data())) {
|
||||
DrawPaletteGroup(i);
|
||||
RETURN_IF_ERROR(DrawPaletteGroup(i))
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void PaletteEditor::DrawPaletteGroup(int i) {
|
||||
absl::Status PaletteEditor::DrawPaletteGroup(int i) {
|
||||
auto size = rom_.GetPaletteGroup(kPaletteGroupNames[i].data()).size();
|
||||
auto palettes = rom_.GetPaletteGroup(kPaletteGroupNames[i].data());
|
||||
for (int j = 0; j < size; j++) {
|
||||
@@ -73,8 +73,8 @@ void PaletteEditor::DrawPaletteGroup(int i) {
|
||||
if (ImGui::ColorEdit4(
|
||||
"Edit Color", col.data(),
|
||||
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha)) {
|
||||
rom_.UpdatePaletteColor(kPaletteGroupNames[i].data(), j, n,
|
||||
palette[n]);
|
||||
RETURN_IF_ERROR(rom_.UpdatePaletteColor(kPaletteGroupNames[i].data(),
|
||||
j, n, palette[n]))
|
||||
}
|
||||
if (ImGui::Button("Copy as..", ImVec2(-1, 0))) ImGui::OpenPopup("Copy");
|
||||
if (ImGui::BeginPopup("Copy")) {
|
||||
@@ -99,6 +99,7 @@ void PaletteEditor::DrawPaletteGroup(int i) {
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
|
||||
|
||||
@@ -36,7 +36,7 @@ class PaletteEditor {
|
||||
auto SetupROM(ROM& rom) { rom_ = rom; }
|
||||
|
||||
private:
|
||||
void DrawPaletteGroup(int i);
|
||||
absl::Status DrawPaletteGroup(int i);
|
||||
|
||||
ImVec4 saved_palette_[256] = {};
|
||||
ImVec4 current_color_;
|
||||
|
||||
@@ -104,6 +104,19 @@ void Bitmap::Create(int width, int height, int depth, Bytes data) {
|
||||
GrayscalePalette(surface_->format->palette);
|
||||
}
|
||||
|
||||
void Bitmap::CreateFromSurface(SDL_Surface *surface) {
|
||||
active_ = true;
|
||||
width_ = surface->w;
|
||||
height_ = surface->h;
|
||||
depth_ = 8;
|
||||
pixel_data_ = static_cast<uchar *>(surface->pixels);
|
||||
surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
|
||||
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
|
||||
SDL_PIXELFORMAT_INDEX8),
|
||||
SDL_Surface_Deleter());
|
||||
surface_->pixels = pixel_data_;
|
||||
}
|
||||
|
||||
void Bitmap::Apply(Bytes data) {
|
||||
pixel_data_ = data.data();
|
||||
data_ = data;
|
||||
@@ -124,6 +137,11 @@ void Bitmap::UpdateTexture(std::shared_ptr<SDL_Renderer> renderer) {
|
||||
SDL_Texture_Deleter{}};
|
||||
}
|
||||
|
||||
void Bitmap::SetSurface(SDL_Surface *surface) {
|
||||
surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
|
||||
surface, SDL_Surface_Deleter());
|
||||
}
|
||||
|
||||
// Convert SNESPalette to SDL_Palette for surface.
|
||||
void Bitmap::ApplyPalette(const SNESPalette &palette) {
|
||||
palette_ = palette;
|
||||
@@ -144,6 +162,17 @@ void Bitmap::ApplyPalette(const SNESPalette &palette) {
|
||||
SDL_LockSurface(surface_.get());
|
||||
}
|
||||
|
||||
void Bitmap::ApplyPalette(const std::vector<SDL_Color> &palette) {
|
||||
SDL_UnlockSurface(surface_.get());
|
||||
for (int i = 0; i < palette.size(); ++i) {
|
||||
surface_->format->palette->colors[i].r = palette[i].r;
|
||||
surface_->format->palette->colors[i].g = palette[i].g;
|
||||
surface_->format->palette->colors[i].b = palette[i].b;
|
||||
surface_->format->palette->colors[i].a = palette[i].a;
|
||||
}
|
||||
SDL_LockSurface(surface_.get());
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
@@ -28,13 +28,18 @@ class Bitmap {
|
||||
void Create(int width, int height, int depth, int data_size);
|
||||
void Create(int width, int height, int depth, uchar *data, int data_size);
|
||||
void Create(int width, int height, int depth, Bytes data);
|
||||
|
||||
void CreateFromSurface(SDL_Surface *surface);
|
||||
|
||||
void Apply(Bytes data);
|
||||
|
||||
void CreateTexture(std::shared_ptr<SDL_Renderer> renderer);
|
||||
void UpdateTexture(std::shared_ptr<SDL_Renderer> renderer);
|
||||
|
||||
void SetSurface(SDL_Surface *surface);
|
||||
|
||||
void ApplyPalette(const SNESPalette &palette);
|
||||
void ApplyPalette(const std::vector<SDL_Color> &palette);
|
||||
|
||||
void WriteToPixel(int position, uchar value) {
|
||||
this->pixel_data_[position] = value;
|
||||
|
||||
262
src/app/gfx/scad_format.cc
Normal file
262
src/app/gfx/scad_format.cc
Normal file
@@ -0,0 +1,262 @@
|
||||
#include "scad_format.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/core/constants.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace gfx {
|
||||
|
||||
CgxHeader ExtractCgxHeader(std::vector<uint8_t>& cgx_header) {
|
||||
CgxHeader header;
|
||||
memcpy(&header, cgx_header.data(), sizeof(CgxHeader));
|
||||
return header;
|
||||
}
|
||||
|
||||
absl::Status DecodeCgxFile(std::string_view filename,
|
||||
std::vector<uint8_t>& cgx_data,
|
||||
std::vector<uint8_t>& extra_cgx_data,
|
||||
std::vector<uint8_t>& decoded_cgx) {
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
return absl::NotFoundError("CGX file not found.");
|
||||
}
|
||||
|
||||
std::vector<uint8_t> file_content((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
cgx_data =
|
||||
std::vector<uint8_t>(file_content.begin(), file_content.end() - 0x500);
|
||||
file.seekg(cgx_data.size() + 0x100);
|
||||
extra_cgx_data = std::vector<uint8_t>((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
file.close();
|
||||
|
||||
decoded_cgx.clear();
|
||||
const uint16_t num_tiles = cgx_data.size() >> 5;
|
||||
for (size_t i = 0; i < num_tiles; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
for (int h = 0; h < 8; h++) {
|
||||
uint8_t pixel = 0;
|
||||
for (int l = 0; l < 2; l++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
if (cgx_data[(i * 0x20) + (l * 0x10) + (j * 2) + k] &
|
||||
(1 << (7 - h))) {
|
||||
pixel = pixel | (1 << (l * 2 + k));
|
||||
}
|
||||
}
|
||||
}
|
||||
decoded_cgx.push_back(pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (decoded_cgx.size() < 0x10000) {
|
||||
std::cout << "Resetting VRAM Offset to not be out of bounds." << std::endl;
|
||||
//// default_offset "0"
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status DecodeObjFile(
|
||||
std::string_view filename, std::vector<uint8_t>& obj_data,
|
||||
std::vector<uint8_t> actual_obj_data,
|
||||
std::unordered_map<std::string, std::vector<uint8_t>> decoded_obj,
|
||||
std::vector<uint8_t>& decoded_extra_obj, int& obj_loaded) {
|
||||
std::vector<uint8_t> header_obj;
|
||||
int obj_range;
|
||||
int expected_cut;
|
||||
if (obj_loaded == 0) {
|
||||
obj_range = 0x180;
|
||||
expected_cut = 0x500;
|
||||
} else {
|
||||
obj_range = 0x300;
|
||||
expected_cut = 0x900;
|
||||
}
|
||||
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
return absl::NotFoundError("OBJ file not found.");
|
||||
}
|
||||
|
||||
std::vector<uint8_t> file_content((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
obj_data = file_content;
|
||||
file.close();
|
||||
|
||||
int cut = obj_data.size() & 0x0FFF;
|
||||
actual_obj_data =
|
||||
std::vector<uint8_t>(obj_data.begin(), obj_data.end() - cut);
|
||||
decoded_extra_obj =
|
||||
std::vector<uint8_t>(obj_data.begin() + actual_obj_data.size(),
|
||||
obj_data.begin() + actual_obj_data.size() + 0x100);
|
||||
header_obj = std::vector<uint8_t>(
|
||||
actual_obj_data.begin() + actual_obj_data.size(), actual_obj_data.end());
|
||||
|
||||
if (cut > expected_cut) {
|
||||
std::vector<uint8_t> scad_data;
|
||||
int j = 0;
|
||||
int k = (obj_loaded == 0) ? 63 : 127;
|
||||
|
||||
for (size_t i = 0; i < (actual_obj_data.size() / 6); i++) {
|
||||
std::vector<uint8_t> data = {
|
||||
actual_obj_data[k * 6 + 0 + j], // display
|
||||
actual_obj_data[k * 6 + 1 + j], // unknown
|
||||
actual_obj_data[k * 6 + 2 + j], // y-disp
|
||||
actual_obj_data[k * 6 + 3 + j], // x-disp
|
||||
actual_obj_data[k * 6 + 5 + j], // props
|
||||
actual_obj_data[k * 6 + 4 + j] // tile
|
||||
};
|
||||
scad_data.insert(scad_data.end(), data.begin(), data.end());
|
||||
|
||||
k = k - 1;
|
||||
if (k == -1) {
|
||||
k = (obj_loaded == 0) ? 63 : 127;
|
||||
j = j + ((k + 1) * 6);
|
||||
}
|
||||
}
|
||||
|
||||
int extra_data_range = 0x400 * (obj_loaded + 1) + 0x100;
|
||||
for (int i = 0; i < extra_data_range; i++) {
|
||||
scad_data.push_back(header_obj[i]);
|
||||
}
|
||||
|
||||
obj_data = scad_data;
|
||||
actual_obj_data =
|
||||
std::vector<uint8_t>(obj_data.begin(), obj_data.end() - cut);
|
||||
}
|
||||
|
||||
decoded_obj.clear();
|
||||
for (int k = 0; k < 128; k++) {
|
||||
decoded_obj["frame " + std::to_string(k)] = std::vector<uint8_t>(obj_range);
|
||||
for (int i = 0; i < obj_range; i++) {
|
||||
try {
|
||||
decoded_obj["frame " + std::to_string(k)][i] =
|
||||
obj_data[i + (obj_range * k)];
|
||||
} catch (...) {
|
||||
decoded_obj["frame " + std::to_string(k)][i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
std::vector<SDL_Color> DecodeColFile(const std::string& filename) {
|
||||
std::vector<SDL_Color> decoded_col;
|
||||
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
||||
|
||||
if (!file.is_open()) {
|
||||
return decoded_col; // Return an empty vector if the file couldn't be
|
||||
// opened.
|
||||
}
|
||||
|
||||
std::streamsize size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> buffer(size);
|
||||
if (file.read(buffer.data(), size)) {
|
||||
buffer.resize(size - 0x200);
|
||||
|
||||
int k = 0;
|
||||
for (size_t i = 0; i < buffer.size() / 2; i++) {
|
||||
uint16_t current_color = static_cast<unsigned char>(buffer[k]) |
|
||||
(static_cast<unsigned char>(buffer[k + 1]) << 8);
|
||||
|
||||
SDL_Color color;
|
||||
color.r = (current_color & 31) << 3;
|
||||
color.g = ((current_color >> 5) & 31) << 3;
|
||||
color.b = ((current_color >> 10) & 31) << 3;
|
||||
color.a = (i & 0xF) == 0 ? 0 : 255;
|
||||
|
||||
decoded_col.push_back(color);
|
||||
k += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return decoded_col;
|
||||
}
|
||||
|
||||
SDL_Surface* CreateCgxPreviewImage(int default_cgram,
|
||||
const std::vector<uint8_t>& cgx_data,
|
||||
const std::vector<uint8_t>& extra_cgx_data,
|
||||
std::vector<SDL_Color> decoded_col) {
|
||||
std::vector<std::vector<std::vector<int>>> tiles;
|
||||
|
||||
const int target_width = 16;
|
||||
const int target_height = 64;
|
||||
int num_tiles = cgx_data.size() >> 5;
|
||||
|
||||
int set_height = std::floor(num_tiles / target_width);
|
||||
|
||||
for (int tile = 0; tile < num_tiles; tile++) {
|
||||
std::vector<std::vector<int>> single_tile;
|
||||
for (int row = 0; row < 8; row++) {
|
||||
std::vector<int> single_row;
|
||||
for (int col = 0; col < 8; col++) {
|
||||
int palette_num = 0;
|
||||
for (int pair = 0; pair < 2; pair++) {
|
||||
for (int bitplane = 0; bitplane < 2; bitplane++) {
|
||||
if (cgx_data[(tile * 0x20) + (pair * 0x10) + (row * 2) + bitplane] &
|
||||
(1 << (7 - col))) {
|
||||
palette_num |= (1 << (pair * 2 + bitplane));
|
||||
}
|
||||
}
|
||||
}
|
||||
single_row.push_back(palette_num);
|
||||
}
|
||||
single_tile.push_back(single_row);
|
||||
}
|
||||
tiles.push_back(single_tile);
|
||||
}
|
||||
|
||||
std::vector<int> pixmap;
|
||||
int row_i = 0;
|
||||
for (int line = 0; line < set_height; line++) {
|
||||
for (int row = 0; row < 8; row++) {
|
||||
for (int i = 0; i < target_width; i++) {
|
||||
for (int color : tiles[row_i + i][row]) {
|
||||
pixmap.push_back(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
row_i += target_width;
|
||||
}
|
||||
|
||||
int cols = target_width * 8;
|
||||
int rows = target_height * 8;
|
||||
|
||||
SDL_Surface* cgx_image = SDL_CreateRGBSurface(0, cols, rows, 32, 0, 0, 0, 0);
|
||||
|
||||
int use_palette = default_cgram;
|
||||
|
||||
for (int row = 0; row < rows; row++) {
|
||||
for (int col = 0; col < cols; col++) {
|
||||
int extra_data_index = (col >> 3) | (row & 0xFF8) << 1;
|
||||
int palette_row = extra_cgx_data[extra_data_index];
|
||||
int index = (row * cols) + col;
|
||||
|
||||
if (index >= 0 && index < pixmap.size() &&
|
||||
(pixmap[index] + use_palette + palette_row * 16) <
|
||||
decoded_col.size()) {
|
||||
SDL_Color color =
|
||||
decoded_col[pixmap[index] + use_palette + palette_row * 16];
|
||||
uint32_t pixel =
|
||||
SDL_MapRGBA(cgx_image->format, color.r, color.g, color.b, color.a);
|
||||
((uint32_t*)cgx_image->pixels)[(row * cols) + col] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cgx_image;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
71
src/app/gfx/scad_format.h
Normal file
71
src/app/gfx/scad_format.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef YAZE_APP_GFX_scad_format_H
|
||||
#define YAZE_APP_GFX_scad_format_H
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "app/core/constants.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace gfx {
|
||||
|
||||
// Address Description
|
||||
// 00000 - 00003 File type "SCH"
|
||||
// 00004 - 00008 Bit mode "?BIT"
|
||||
// 00009 - 00013 Version number "Ver-????\n"
|
||||
// 00014 - 00017 Header size
|
||||
// 00018 - 0001B Hardware name "SFC" or "CGB" or "GB"
|
||||
// 0001C - 0001C BG/OBJ flag (for AGB)
|
||||
// 0001D - 0001D Color Pallette Number
|
||||
// 0001D - 000FF Reserved
|
||||
// 00100 - 001FF Color Path
|
||||
struct CgxHeader {
|
||||
char file_type[4];
|
||||
char bit_mode[5];
|
||||
char version_number[9];
|
||||
uint32_t header_size;
|
||||
char hardware_name[4];
|
||||
uint8_t bg_obj_flag;
|
||||
uint8_t color_palette_number;
|
||||
uint8_t reserved[0xE3];
|
||||
uint8_t color_path[0x100];
|
||||
};
|
||||
|
||||
CgxHeader ExtractCgxHeader(std::vector<uint8_t>& cgx_header);
|
||||
|
||||
absl::Status DecodeCgxFile(std::string_view filename,
|
||||
std::vector<uint8_t>& cgx_data,
|
||||
std::vector<uint8_t>& extra_cgx_data,
|
||||
std::vector<uint8_t>& decoded_cgx);
|
||||
|
||||
std::vector<SDL_Color> DecodeColFile(const std::string& filename);
|
||||
|
||||
absl::Status DecodeObjFile(
|
||||
std::string_view filename, std::vector<uint8_t>& obj_data,
|
||||
std::vector<uint8_t> actual_obj_data,
|
||||
std::unordered_map<std::string, std::vector<uint8_t>> decoded_obj,
|
||||
std::vector<uint8_t>& decoded_extra_obj, int& obj_loaded);
|
||||
|
||||
SDL_Surface* CreateCgxPreviewImage(int default_cgram,
|
||||
const std::vector<uint8_t>& cgx_data,
|
||||
const std::vector<uint8_t>& extra_cgx_data,
|
||||
std::vector<SDL_Color> decoded_col);
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_GFX_scad_format_H
|
||||
@@ -71,7 +71,7 @@ Bytes BPP8SNESToIndexed(Bytes data, uint64_t bpp) {
|
||||
|
||||
// 16 tiles = 1024 bytes
|
||||
auto buffer = Bytes(data.size());
|
||||
auto bitmap_data = Bytes(128 * 128 + 2048);
|
||||
auto bitmap_data = Bytes(0x80 * 0x800);
|
||||
int yy = 0;
|
||||
int xx = 0;
|
||||
int pos = 0;
|
||||
@@ -101,31 +101,31 @@ Bytes BPP8SNESToIndexed(Bytes data, uint64_t bpp) {
|
||||
auto b = 0;
|
||||
if (b1 != 0) {
|
||||
b |= 1;
|
||||
};
|
||||
}
|
||||
if (b2 != 0) {
|
||||
b |= 2;
|
||||
};
|
||||
}
|
||||
if (bpp >= 4) {
|
||||
if (b3 != 0) {
|
||||
b |= 4;
|
||||
};
|
||||
}
|
||||
if (b4 != 0) {
|
||||
b |= 8;
|
||||
};
|
||||
}
|
||||
}
|
||||
if (bpp >= 8) {
|
||||
if (b5 != 0) {
|
||||
b |= 0x10;
|
||||
};
|
||||
}
|
||||
if (b6 != 0) {
|
||||
b |= 0x20;
|
||||
};
|
||||
}
|
||||
if (b7 != 0) {
|
||||
b |= 0x40;
|
||||
};
|
||||
}
|
||||
if (b8 != 0) {
|
||||
b |= 0x80;
|
||||
};
|
||||
}
|
||||
}
|
||||
bitmap_data[((x + xx) * sheet_width) + y + (yy * 8)] = b;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "cgx_viewer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
@@ -13,12 +14,13 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace viewer {
|
||||
|
||||
constexpr int kMatchedBytes[] = {0x4E, 0x41, 0x4B, 0x31, 0x39, 0x38, 0x39};
|
||||
constexpr int kOffsetFromMatchedBytesEnd = 0x1D;
|
||||
constexpr uint16_t kMatchedBytes[] = {0x4E, 0x41, 0x4B, 0x31, 0x39, 0x38, 0x39};
|
||||
constexpr uint16_t kOffsetFromMatchedBytesEnd = 0x1D;
|
||||
|
||||
void CgxViewer::LoadCgx(ROM &cgx_rom) {
|
||||
void CgxViewer::LoadCgx(ROM& cgx_rom) {
|
||||
int matching_position = -1;
|
||||
bool matched = false;
|
||||
|
||||
for (int i = 0;
|
||||
i < cgx_rom.size() - sizeof(kMatchedBytes) - kOffsetFromMatchedBytesEnd;
|
||||
i++) {
|
||||
@@ -48,8 +50,33 @@ void CgxViewer::LoadCgx(ROM &cgx_rom) {
|
||||
LoadGfx(current_selection_);
|
||||
}
|
||||
|
||||
void CgxViewer::LoadGfx(int combo_bpp) {
|
||||
if (combo_bpp == 0) {
|
||||
bpp_ = 4;
|
||||
} else if (combo_bpp == 1) {
|
||||
bpp_ = 2;
|
||||
} else if (combo_bpp == 2) {
|
||||
bpp_ = 8;
|
||||
} else if (combo_bpp == 3) {
|
||||
bpp_ = 40;
|
||||
for (int i = 0; i < raw_data_.size(); i++) {
|
||||
all_tiles_data_[i] = raw_data_[i];
|
||||
}
|
||||
// Refresh palettes and "picture box" aka canvas
|
||||
RefreshPalettes();
|
||||
return;
|
||||
}
|
||||
|
||||
Bytes decomp_sheet = gfx::BPP8SNESToIndexed(raw_data_.vector(), bpp_);
|
||||
for (int i = 0; i < decomp_sheet.size(); i++) {
|
||||
all_tiles_data_.push_back(decomp_sheet[i]);
|
||||
}
|
||||
|
||||
RefreshPalettes();
|
||||
}
|
||||
|
||||
void CgxViewer::DrawBG1(int p, int bpp) {
|
||||
auto *ptr = (uchar *)screen_bitmap_.data();
|
||||
auto* ptr = (uchar*)screen_bitmap_.data();
|
||||
// for each tile on the tile buffer
|
||||
for (int i = 0; i < 0x400; i++) {
|
||||
if (room_bg1_bitmap_.data()[i + p] != 0xFFFF) {
|
||||
@@ -85,31 +112,6 @@ void CgxViewer::DrawBG2() {}
|
||||
|
||||
void CgxViewer::DrawOAM(int bpp, int drawmode, gfx::OAMTile data, int frame) {}
|
||||
|
||||
void CgxViewer::LoadGfx(int combo_bpp) {
|
||||
if (combo_bpp == 0) {
|
||||
bpp_ = 4;
|
||||
} else if (combo_bpp == 1) {
|
||||
bpp_ = 2;
|
||||
} else if (combo_bpp == 2) {
|
||||
bpp_ = 8;
|
||||
} else if (combo_bpp == 3) {
|
||||
bpp_ = 40;
|
||||
for (int i = 0; i < raw_data_.size(); i++) {
|
||||
all_tiles_data_[i] = raw_data_[i];
|
||||
}
|
||||
// Refresh palettes and "picture box" aka canvas
|
||||
RefreshPalettes();
|
||||
return;
|
||||
}
|
||||
|
||||
Bytes decomp_sheet = gfx::BPP8SNESToIndexed(raw_data_.vector(), bpp_);
|
||||
for (int i = 0; i < decomp_sheet.size(); i++) {
|
||||
all_tiles_data_.push_back(decomp_sheet[i]);
|
||||
}
|
||||
|
||||
RefreshPalettes();
|
||||
}
|
||||
|
||||
void CgxViewer::LoadScr() {}
|
||||
|
||||
void CgxViewer::RefreshPalettes() {}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define YAZE_APP_VIEWER_CGX_VIEWER_H
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "app/core/pipeline.h"
|
||||
@@ -14,6 +15,7 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace viewer {
|
||||
|
||||
|
||||
class CgxViewer {
|
||||
public:
|
||||
void LoadCgx(ROM&);
|
||||
|
||||
Reference in New Issue
Block a user