added graphics sheet to the overworld editor section

This commit is contained in:
Justin Scofield
2022-06-20 13:02:33 -04:00
parent 8368139d49
commit 2fbc58ad03
10 changed files with 235 additions and 125 deletions

View File

@@ -11,19 +11,18 @@ using namespace Graphics;
Overworld::~Overworld() {
if (isLoaded) {
for (int i = 0; i < (int) tiles32.size(); i++) {
free(allmapsTilesLW[i]);
free(allmapsTilesDW[i]);
free(allmapsTilesSP[i]);
}
free(allmapsTilesLW);
free(allmapsTilesDW);
free(allmapsTilesSP);
for (int i = 0; i < (int)tiles32.size(); i++) {
free(allmapsTilesLW[i]);
free(allmapsTilesDW[i]);
free(allmapsTilesSP[i]);
}
free(allmapsTilesLW);
free(allmapsTilesDW);
free(allmapsTilesSP);
delete[] overworldMapPointer;
delete[] owactualMapPointer;
delete[] overworldMapPointer;
delete[] owactualMapPointer;
}
}
static TileInfo GetTilesInfo(ushort tile) {
@@ -41,14 +40,13 @@ static TileInfo GetTilesInfo(ushort tile) {
return TileInfo(tid, p, v, h, o);
}
void Overworld::Load(Data::ROM rom) {
void Overworld::Load(Data::ROM & rom) {
rom_ = rom;
for (int i = 0; i < 0x2B; i++) {
// tileLeftEntrance.push_back(
// rom_.ReadShort(Constants::overworldEntranceAllowedTilesLeft + (i *
// 2)));
// tileRightEntrance.push_back(rom_.ReadShort(
// Constants::overworldEntranceAllowedTilesRight + (i * 2)));
tileLeftEntrance.push_back(Constants::overworldEntranceAllowedTilesLeft +
(i * 2));
tileRightEntrance.push_back(Constants::overworldEntranceAllowedTilesRight +
(i * 2));
}
AssembleMap32Tiles();

View File

@@ -21,7 +21,7 @@ class Overworld {
Overworld() = default;
~Overworld();
void Load(Data::ROM rom);
void Load(Data::ROM & rom);
char* overworldMapPointer = new char[0x40000];
Graphics::Bitmap* overworldMapBitmap;

View File

@@ -10,7 +10,7 @@ namespace Data {
using namespace Core;
using namespace Graphics;
OverworldMap::OverworldMap(Data::ROM rom,
OverworldMap::OverworldMap(Data::ROM & rom,
const std::vector<Graphics::Tile16> tiles16,
uchar index)
: rom_(rom), index(index), tiles16_(tiles16), parent(index) {

View File

@@ -42,7 +42,7 @@ class OverworldMap {
uchar* currentOWgfx16Ptr = new uchar[(128 * 512) / 2];
std::vector<Graphics::Tile16> tiles16_;
OverworldMap(Data::ROM rom, const std::vector<Graphics::Tile16> tiles16,
OverworldMap(Data::ROM & rom, const std::vector<Graphics::Tile16> tiles16,
uchar index);
void BuildMap(uchar* mapParent, int count, int gameState,
ushort** allmapsTilesLW, ushort** allmapsTilesDW,

View File

@@ -11,9 +11,19 @@ namespace Data {
ROM::~ROM() {
if (loaded) {
delete[] current_rom_;
for (auto &each : decompressed_graphic_sheets_) {
free(each);
}
for (auto &each : converted_graphic_sheets_) {
free(each);
}
}
}
void ROM::SetupRenderer(std::shared_ptr<SDL_Renderer> renderer) {
sdl_renderer_ = renderer;
}
// TODO: check if the rom has a header on load
void ROM::LoadFromFile(const std::string &path) {
size_ = std::filesystem::file_size(path.c_str());
@@ -115,62 +125,10 @@ uint32_t ROM::GetRomPosition(int direct_addr, uint snes_addr) const {
return filePos;
}
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};
uchar *sheet_buffer_out = (unsigned char *)malloc(0x1000);
int xx = 0; // positions where we are at on the sheet
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
{
//[0] + [1] + [16]
for (int x = 0; x < 8; x++) {
unsigned char b1 = (unsigned char)((
buffer_in[(y * 2) + (24 * pos)] & (bitmask[x])));
unsigned char b2 =
(unsigned char)(buffer_in[((y * 2) + (24 * pos)) + 1] &
(bitmask[x]));
unsigned char b3 =
(unsigned char)(buffer_in[(16 + y) + (24 * pos)] &
(bitmask[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;
}
char *ROM::Decompress(int pos, bool reversed) {
char *buffer = new char[0x800];
for (int i = 0; i < 0x800; i++) {
char *ROM::Decompress(int pos, int size, bool reversed) {
char *buffer = new char[size];
decompressed_graphic_sheets_.push_back(buffer);
for (int i = 0; i < size; i++) {
buffer[i] = 0;
}
unsigned int bufferPos = 0;
@@ -243,37 +201,90 @@ char *ROM::Decompress(int pos, bool reversed) {
return buffer;
}
SDL_Surface* ROM::GetGraphicsSheet(int num_sheets) {
int height = 32 * num_sheets;
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};
uchar *sheet_buffer_out = (uchar *)malloc(0x1000);
converted_graphic_sheets_.push_back(sheet_buffer_out);
int xx = 0; // positions where we are at on the sheet
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
{
//[0] + [1] + [16]
for (int x = 0; x < 8; x++) {
unsigned char b1 =
(unsigned char)((buffer_in[(y * 2) + (24 * pos)] & (bitmask[x])));
unsigned char b2 =
(unsigned char)(buffer_in[((y * 2) + (24 * pos)) + 1] &
(bitmask[x]));
unsigned char b3 =
(unsigned char)(buffer_in[(16 + y) + (24 * pos)] & (bitmask[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;
}
SDL_Texture *ROM::DrawGraphicsSheet(int offset) {
SDL_Surface *surface =
SDL_CreateRGBSurfaceWithFormat(0, 128, height, 8, SDL_PIXELFORMAT_INDEX8);
std::cout << "Drawing surface" << std::endl;
SDL_CreateRGBSurfaceWithFormat(0, 128, 32, 8, SDL_PIXELFORMAT_INDEX8);
std::cout << "Drawing surface #" << offset << 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);
surface->format->palette->colors[i].r = i * 31;
surface->format->palette->colors[i].g = i * 31;
surface->format->palette->colors[i].b = 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 + i]))));
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;
}
snesAddr = (unsigned int)((((uchar)(current_rom_[0x4F80 + offset]) << 16) |
((uchar)(current_rom_[0x505F + offset]) << 8) |
((uchar)(current_rom_[0x513E + offset]))));
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);
std::cout << "Assigning pixel data..." << std::endl;
surface->pixels = sheet_buffer;
return surface;
std::cout << "Creating texture from surface..." << std::endl;
SDL_Texture *sheet_texture = nullptr;
sheet_texture = SDL_CreateTextureFromSurface(sdl_renderer_.get(), surface);
if (sheet_texture == nullptr) {
std::cout << "Error: " << SDL_GetError() << std::endl;
}
return sheet_texture;
}
int AddressFromBytes(uchar addr1, uchar addr2, uchar addr3) {

View File

@@ -26,22 +26,21 @@ class ROM {
public:
~ROM();
void SetupRenderer(std::shared_ptr<SDL_Renderer> renderer);
void LoadFromFile(const std::string& path);
std::vector<tile8> ExtractTiles(Graphics::TilePreset& preset);
Graphics::SNESPalette ExtractPalette(Graphics::TilePreset& preset);
uint32_t GetRomPosition(int direct_addr, uint snes_addr) const;
char* Decompress(int pos, int size = 0x800, bool reversed = false);
uchar* SNES3bppTo8bppSheet(uchar* buffer_in, int sheet_id = 0);
SDL_Texture* DrawGraphicsSheet(int offset);
inline uchar* GetRawData() { return current_rom_; }
const uchar* getTitle() const { return title; }
long int getSize() const { return size_; }
char getVersion() const { return version_; }
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 = 1);
unsigned int SnesToPc(unsigned int addr) {
if (addr >= 0x808000) {
addr -= 0x808000;
@@ -63,7 +62,10 @@ class ROM {
enum rom_type type_ = LoROM;
std::shared_ptr<uchar> rom_ptr_;
std::vector<char*> decompressed_graphic_sheets_;
std::vector<uchar*> converted_graphic_sheets_;
std::vector<SDL_Surface> surfaces_;
std::shared_ptr<SDL_Renderer> sdl_renderer_;
};
} // namespace Data

View File

@@ -96,6 +96,7 @@ Editor::~Editor() {
void Editor::SetupScreen(std::shared_ptr<SDL_Renderer> renderer) {
sdl_renderer_ = renderer;
rom_.SetupRenderer(renderer);
}
void Editor::UpdateScreen() {
@@ -139,6 +140,7 @@ void Editor::DrawYazeMenu() {
std::string filePath = ImGuiFileDialog::Instance()->GetCurrentPath();
rom_.LoadFromFile(filePathName);
rom_data_ = (void *)rom_.GetRawData();
overworld_editor_.SetupROM(rom_);
}
ImGuiFileDialog::Instance()->Close();
}
@@ -295,9 +297,9 @@ void Editor::DrawGraphicsSheet(int offset) {
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 + offset]))));
((uchar)(rom_.GetRawData()[0x4F80 + offset]) << 16) |
((uchar)(rom_.GetRawData()[0x505F + offset]) << 8) |
((uchar)(rom_.GetRawData()[0x513E + offset]))));
pcAddr = rom_.SnesToPc(snesAddr);
std::cout << "Decompressing..." << std::endl;
char *decomp = rom_.Decompress(pcAddr);
@@ -306,6 +308,7 @@ void Editor::DrawGraphicsSheet(int offset) {
std::cout << "Assigning pixel data..." << std::endl;
surface->pixels = sheet_buffer;
std::cout << "Creating texture from surface..." << std::endl;
SDL_Texture *sheet_texture = nullptr;
sheet_texture = SDL_CreateTextureFromSurface(sdl_renderer_.get(), surface);
imagesCache[offset] = sheet_texture;
if (sheet_texture == nullptr) {

View File

@@ -49,7 +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_;
@@ -62,8 +62,8 @@ class Editor {
ImGuiWindowFlags main_editor_flags_ =
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoTitleBar;
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar |
ImGuiWindowFlags_NoTitleBar;
ImGuiTableFlags toolset_table_flags_ = ImGuiTableFlags_SizingFixedFit;
};

View File

@@ -29,11 +29,15 @@
namespace yaze {
namespace application {
namespace Editor {
void OverworldEditor::SetupROM(Data::ROM &rom) { rom_ = rom; }
void OverworldEditor::Update() {
if (rom_.isLoaded()) {
if (!doneLoaded) {
// overworld.Load(rom_);
doneLoaded = true;
if (!all_graphics_loaded_) {
LoadGraphics();
overworld_.Load(rom_);
all_graphics_loaded_ = true;
}
}
@@ -44,7 +48,9 @@ void OverworldEditor::Update() {
DrawToolset();
ImGui::Separator();
if (ImGui::BeginTable("#owEditTable", 2, ow_edit_flags, ImVec2(0, 0))) {
ImGui::TableSetupColumn("#overworldCanvas", ImGuiTableColumnFlags_WidthStretch, ImGui::GetContentRegionAvail().x);
ImGui::TableSetupColumn("#overworldCanvas",
ImGuiTableColumnFlags_WidthStretch,
ImGui::GetContentRegionAvail().x);
ImGui::TableSetupColumn("#tileSelector");
ImGui::TableNextColumn();
DrawOverworldCanvas();
@@ -263,9 +269,23 @@ void OverworldEditor::DrawOverworldCanvas() {
draw_list->PopClipRect();
}
void OverworldEditor::DrawTileSelector() {
if (ImGui::BeginTabBar("##TabBar", ImGuiTabBarFlags_FittingPolicyScroll)) {
if (ImGui::BeginTabItem("Tile8")) {
ImGuiStyle &style = ImGui::GetStyle();
ImGuiID child_id = ImGui::GetID((void *)(intptr_t)1);
bool child_is_visible = ImGui::BeginChild(
child_id, ImGui::GetContentRegionAvail(), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
if (child_is_visible) // Avoid calling SetScrollHereY when running with
// culled items
{
DrawTile8Selector();
}
float scroll_x = ImGui::GetScrollX();
float scroll_max_x = ImGui::GetScrollMaxX();
ImGui::EndChild();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Tile16")) {
@@ -276,6 +296,70 @@ void OverworldEditor::DrawTileSelector() {
}
}
void OverworldEditor::DrawTile8Selector() {
static ImVec2 scrolling(0.0f, 0.0f);
ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
ImVec2 canvas_sz = ImVec2(256 + 1, kNumSheetsToLoad * 64);
ImVec2 canvas_p1 =
ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
// Draw border and background color
const ImGuiIO &io = ImGui::GetIO();
ImDrawList *draw_list = ImGui::GetWindowDrawList();
draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(32, 32, 32, 255));
draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255));
// This will catch our interactions
ImGui::InvisibleButton(
"Tile8SelectorCanvas", canvas_sz,
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
const bool is_hovered = ImGui::IsItemHovered(); // Hovered
const bool is_active = ImGui::IsItemActive(); // Held
const ImVec2 origin(canvas_p0.x + scrolling.x,
canvas_p0.y + scrolling.y); // Lock scrolled origin
const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x,
io.MousePos.y - origin.y);
// Context menu (under default mouse threshold)
ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
if (drag_delta.x == 0.0f && drag_delta.y == 0.0f)
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
if (ImGui::BeginPopup("context")) {
ImGui::EndPopup();
}
if (all_graphics_loaded_) {
for (const auto &[key, value] : all_texture_sheet_) {
int offset = 64 * (key + 1);
int top_left_y = canvas_p0.y + 2;
if (key >= 1) {
top_left_y = canvas_p0.y + 64 * key;
}
draw_list->AddImage((void *)(SDL_Texture *)value,
ImVec2(canvas_p0.x + 2, top_left_y),
ImVec2(canvas_p0.x + 256, canvas_p0.y + offset));
}
}
// Draw grid + all lines in the canvas
draw_list->PushClipRect(canvas_p0, canvas_p1, true);
if (opt_enable_grid) {
const float GRID_STEP = 16.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),
ImVec2(canvas_p0.x + x, canvas_p1.y),
IM_COL32(200, 200, 200, 40));
for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y;
y += GRID_STEP)
draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y),
ImVec2(canvas_p1.x, canvas_p0.y + y),
IM_COL32(200, 200, 200, 40));
}
draw_list->PopClipRect();
}
void OverworldEditor::DrawChangelist() {
if (!ImGui::Begin("Changelist")) {
ImGui::End();
@@ -285,6 +369,12 @@ void OverworldEditor::DrawChangelist() {
ImGui::End();
}
void OverworldEditor::LoadGraphics() {
for (int i = 0; i < kNumSheetsToLoad; i++) {
all_texture_sheet_[i] = rom_.DrawGraphicsSheet(i);
}
}
} // namespace Editor
} // namespace application
} // namespace yaze

View File

@@ -16,6 +16,7 @@ static constexpr unsigned int k4BPP = 4;
class OverworldEditor {
public:
void SetupROM(Data::ROM & rom);
void Update();
private:
@@ -23,16 +24,17 @@ class OverworldEditor {
void DrawOverworldMapSettings();
void DrawOverworldCanvas();
void DrawTileSelector();
void DrawTile8Selector();
void DrawChangelist();
bool show_changelist_ = false;
void LoadGraphics();
Data::ROM rom_;
Data::Overworld overworld;
Data::Overworld overworld_;
Graphics::Bitmap allgfxBitmap;
Graphics::SNESPalette palette_;
Graphics::TilePreset current_set_;
std::unordered_map<unsigned int, SDL_Texture *> all_texture_sheet_;
SDL_Texture *gfx_texture = nullptr;
@@ -41,12 +43,6 @@ class OverworldEditor {
uchar *allGfx16Ptr = new uchar[(128 * 7136) / 2];
ImGuiTableFlags toolset_table_flags = ImGuiTableFlags_SizingFixedFit;
ImGuiTableFlags ow_map_settings_flags = ImGuiTableFlags_Borders;
ImGuiTableFlags ow_edit_flags = ImGuiTableFlags_Reorderable |
ImGuiTableFlags_Resizable |
ImGuiTableFlags_SizingStretchSame;
float canvas_table_ratio = 30.f;
char map_gfx_[3] = "";
@@ -59,11 +55,21 @@ class OverworldEditor {
bool isLoaded = false;
bool doneLoaded = false;
bool opt_enable_grid = true;
bool show_changelist_ = false;
bool all_graphics_loaded_ = false;
constexpr static int kByteSize = 3;
constexpr static int kMessageIdSize = 5;
constexpr static float kInputFieldSize = 30.f;
bool opt_enable_grid = true;
constexpr static int kNumSheetsToLoad = 50;
constexpr static int kTile8DisplayHeight = 64;
ImGuiTableFlags toolset_table_flags = ImGuiTableFlags_SizingFixedFit;
ImGuiTableFlags ow_map_settings_flags = ImGuiTableFlags_Borders;
ImGuiTableFlags ow_edit_flags = ImGuiTableFlags_Reorderable |
ImGuiTableFlags_Resizable |
ImGuiTableFlags_SizingStretchSame;
};
} // namespace Editor
} // namespace application