overhaul directory structure

This commit is contained in:
Justin Scofield
2022-06-15 20:56:15 -04:00
parent 70c59d0e96
commit efcaad0f53
62 changed files with 6948 additions and 85 deletions

View File

@@ -16,4 +16,4 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Project Files
add_subdirectory(src)
add_subdirectory(tests)
add_subdirectory(test)

View File

@@ -1,5 +1,5 @@
#ifndef YAZE_APPLICATION_CORE_CONSTANTS_H
#define YAZE_APPLICATION_CORE_CONSTANTS_H
#ifndef YAZE_application_CORE_CONSTANTS_H
#define YAZE_application_CORE_CONSTANTS_H
#include <array>
#include <string>
@@ -21,7 +21,7 @@ using uint = unsigned int;
using uchar = unsigned char;
namespace yaze {
namespace Application {
namespace application {
namespace Core {
namespace Constants {
@@ -1226,7 +1226,7 @@ static const std::string TileTypeNames[] = {
} // namespace Constants
} // namespace Core
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -11,7 +11,7 @@
#include "Editor/editor.h"
namespace yaze {
namespace Application {
namespace application {
namespace Core {
bool Controller::isActive() const { return active_; }
@@ -181,5 +181,5 @@ void Controller::CreateGuiContext() {
}
} // namespace Core
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -15,7 +15,7 @@
int main(int argc, char **argv);
namespace yaze {
namespace Application {
namespace application {
namespace Core {
class Controller {
@@ -49,7 +49,7 @@ class Controller {
};
} // namespace Core
} // namespace Application
} // namespace application
} // namespace yaze
#endif // YAZE_APPLICATION_CORE_CONTROLLER_H

View File

@@ -4,7 +4,7 @@
#include "controller.h"
int main(int argc, char** argv) {
yaze::Application::Core::Controller controller;
yaze::application::Core::Controller controller;
controller.onEntry();
while (controller.isActive()) {
controller.onInput();

View File

@@ -3,7 +3,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Data {
using namespace Core;
@@ -345,5 +345,5 @@ void Overworld::LoadOverworldMap() {
}
} // namespace Data
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -13,7 +13,7 @@
#include "overworld_map.h"
namespace yaze {
namespace Application {
namespace application {
namespace Data {
class Overworld {
@@ -68,7 +68,7 @@ class Overworld {
};
} // namespace Data
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -4,7 +4,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Data {
using namespace Core;
@@ -355,5 +355,5 @@ void OverworldMap::BuildTileset(int gameState) {
}
} // namespace Data
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -8,7 +8,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Data {
using ushort = unsigned short;
@@ -73,5 +73,5 @@ class OverworldMap {
};
} // namespace Data
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -5,7 +5,7 @@
#include "Core/constants.h"
namespace yaze {
namespace Application {
namespace application {
namespace Data {
ROM::~ROM() {
@@ -116,10 +116,127 @@ uint32_t ROM::GetRomPosition(const Graphics::TilePreset &preset, int directAddr,
return filePos;
}
unsigned char *sheetBuffer = (unsigned char *)malloc(0x1000);
unsigned char bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
void SNES3bppTo8bppSheet() // 128x32
{
int xx = 0; // positions where we are at on the sheet
int yy = 0;
int pos = 0;
int ypos = 0;
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[(y * 2) + (24 * pos)] & (bitmask[x])));
unsigned char b2 =
(unsigned char)(buffer[((y * 2) + (24 * pos)) + 1] & (bitmask[x]));
unsigned char b3 =
(unsigned char)(buffer[(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;
};
sheetBuffer[x + (xx) + (y * 128) + (yy * 1024)] = b;
}
}
pos++;
ypos++;
xx += 8;
if (ypos >= 16) {
yy++;
xx = 0;
ypos = 0;
}
}
}
char *Decompress(int pos, bool reversed = false) {
// char* buffer = new char[0x800];
for (int i = 0; i < 0x800; i++) {
buffer[i] = 0;
}
unsigned int bufferPos = 0;
unsigned char cmd = 0;
unsigned int length = 0;
unsigned char databyte = (unsigned char)romData[pos];
while (true) {
databyte = (unsigned char)romData[pos];
if (databyte == 0xFF) // End of decompression
{
break;
}
if ((databyte & 0xE0) == 0xE0) // Expanded Command
{
cmd = (unsigned char)((databyte >> 2) & 0x07);
length =
(unsigned short)(((romData[pos] << 8) | romData[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)romData[pos++];
}
// Do not advance in the ROM
break;
case 01: // Byte Fill
for (int i = 0; i < length; i++) {
buffer[bufferPos++] = (unsigned char)romData[pos];
}
pos += 1; // Advance 1 byte in the ROM
break;
case 02: // Word Fill
for (int i = 0; i < length; i += 2) {
buffer[bufferPos++] = (unsigned char)romData[pos];
buffer[bufferPos++] = (unsigned char)romData[pos + 1];
}
pos += 2; // Advance 2 byte in the ROM
break;
case 03: // Increasing Fill
{
unsigned char incByte = (unsigned char)romData[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 = ((romData[pos + 1] & 0xFF) << 8);
unsigned short s2 = ((romData[pos] & 0xFF));
unsigned short Addr = (unsigned short)(s1 | s2);
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;
}
int AddressFromBytes(uchar addr1, uchar addr2, uchar addr3) {
return (addr1 << 16) | (addr2 << 8) | addr3;
}
} // namespace Data
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -1,5 +1,5 @@
#ifndef YAZE_APPLICATION_UTILS_ROM_H
#define YAZE_APPLICATION_UTILS_ROM_H
#ifndef YAZE_application_UTILS_ROM_H
#define YAZE_application_UTILS_ROM_H
#include <compressions/alttpcompression.h>
#include <rommapping.h>
@@ -17,7 +17,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Data {
int AddressFromBytes(uchar addr1, uchar addr2, uchar addr3);
@@ -53,7 +53,7 @@ class ROM {
};
} // namespace Data
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -4,7 +4,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Editor {
using namespace Core;
@@ -266,14 +266,14 @@ void Editor::DrawSurface() {
tile8 tile = arranged_tiles_[j][i];
// SDL_PIXELFORMAT_RGB888 ?
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(
0, 8, 8, SDL_BITSPERPIXEL(3), SDL_PIXELFORMAT_RGB444);
0, 8, 8, SDL_BITSPERPIXEL(4), SDL_PIXELFORMAT_RGB444);
if (surface == nullptr) {
SDL_Log("SDL_CreateRGBSurfaceWithFormat() failed: %s", SDL_GetError());
exit(1);
}
SDL_PixelFormat *format = surface->format;
format->palette = current_palette_.GetSDL_Palette();
char *ptr = (char *)surface->pixels;
uchar *ptr = (uchar *)surface->pixels;
for (int k = 0; k < 8; k++) {
for (int l = 0; l < 8; l++) {
@@ -341,7 +341,7 @@ void Editor::DrawProjectEditor() {
ImGui::Image((void *)(SDL_Texture *)texture, ImVec2(32, 32));
if (i != 16) {
ImGui::SameLine();
} else if ( i == 16 ) {
} else if (i == 16) {
i = 0;
}
i++;
@@ -506,5 +506,5 @@ void Editor::DrawScreenEditor() {
}
} // namespace Editor
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -15,7 +15,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Editor {
class Editor {
@@ -65,7 +65,7 @@ class Editor {
};
} // namespace Editor
} // namespace Application
} // namespace application
} // namespace yaze
#endif // YAZE_APPLICATION_VIEW_EDITOR_H

View File

@@ -27,7 +27,7 @@
// have an overworld map viewer, in less than few hours if are able to
// understand the data quickly
namespace yaze {
namespace Application {
namespace application {
namespace Editor {
void OverworldEditor::Update() {
if (rom_.isLoaded()) {
@@ -286,5 +286,5 @@ void OverworldEditor::DrawChangelist() {
}
} // namespace Editor
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -10,7 +10,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Editor {
static constexpr unsigned int k4BPP = 4;
@@ -70,7 +70,7 @@ class OverworldEditor {
bool opt_enable_grid = true;
};
} // namespace Editor
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -1,10 +1,10 @@
#include "tile_editor.h"
namespace yaze {
namespace Application {
namespace application {
namespace Editor {
void TileEditor::UpdateScreen() {}
} // namespace Editor
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -2,14 +2,14 @@
#define YAZE_APPLICATION_EDITOR_TILEEDITOR_H
namespace yaze {
namespace Application {
namespace application {
namespace Editor {
class TileEditor {
public:
void UpdateScreen();
};
} // namespace Editor
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -5,7 +5,7 @@
#include "Data/rom.h"
namespace yaze {
namespace Application {
namespace application {
namespace Graphics {
int GetPCGfxAddress(char *romData, char id) {
@@ -174,5 +174,5 @@ void CreateAllGfxData(char *romData, char *allgfx16Ptr) {
}
} // namespace Graphics
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -6,7 +6,7 @@
#include "Core/constants.h"
namespace yaze {
namespace Application {
namespace application {
namespace Graphics {
class Bitmap {
@@ -31,7 +31,7 @@ char *CreateAllGfxDataRaw(char *romData);
void CreateAllGfxData(char *romData, char *allgfx16Ptr);
} // namespace Graphics
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -1696,7 +1696,7 @@
#define ICON_MD_SET_MEAL "\xef\x87\xaa" // U+f1ea
#define ICON_MD_SETTINGS "\xee\xa2\xb8" // U+e8b8
#define ICON_MD_SETTINGS_ACCESSIBILITY "\xef\x81\x9d" // U+f05d
#define ICON_MD_SETTINGS_APPLICATIONS "\xee\xa2\xb9" // U+e8b9
#define ICON_MD_SETTINGS_applicationS "\xee\xa2\xb9" // U+e8b9
#define ICON_MD_SETTINGS_BACKUP_RESTORE "\xee\xa2\xba" // U+e8ba
#define ICON_MD_SETTINGS_BLUETOOTH "\xee\xa2\xbb" // U+e8bb
#define ICON_MD_SETTINGS_BRIGHTNESS "\xee\xa2\xbd" // U+e8bd

View File

@@ -4,7 +4,7 @@
#include <cstring>
namespace yaze {
namespace Application {
namespace application {
namespace Graphics {
SNESColor::SNESColor() : rgb(ImVec4(0.f, 0.f, 0.f, 0.f)) {}
@@ -109,5 +109,5 @@ SDL_Palette* SNESPalette::GetSDL_Palette() {
}
} // namespace Graphics
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -12,7 +12,7 @@
#include <vector>
namespace yaze {
namespace Application {
namespace application {
namespace Graphics {
struct SNESColor {
@@ -44,7 +44,7 @@ class SNESPalette {
};
} // namespace Graphics
} // namespace Application
} // namespace application
} // namespace yaze
#endif // YAZE_APPLICATION_GRAPHICS_PALETTE_H

View File

@@ -9,7 +9,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Graphics {
void Scene::buildSurface(const std::vector<tile8>& tiles, SNESPalette& mPalette,
@@ -74,5 +74,5 @@ void Scene::setTilesZoom(unsigned int tileZoom) {
void Scene::setTilesPattern(TilesPattern tp) { tilesPattern = tp; }
} // namespace Graphics
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -10,7 +10,7 @@
#include "Graphics/tile.h"
namespace yaze {
namespace Application {
namespace application {
namespace Graphics {
class Scene {
@@ -33,7 +33,7 @@ class Scene {
};
} // namespace Graphics
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -4,7 +4,7 @@
#include "imgui/imgui_internal.h"
namespace yaze {
namespace Application {
namespace application {
namespace Core {
namespace Style {
@@ -109,5 +109,5 @@ void ColorsYaze() {
}
} // namespace Style
} // namespace Core
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -5,7 +5,7 @@
#include <imgui/imgui_internal.h>
namespace yaze {
namespace Application {
namespace application {
namespace Core {
namespace Style {
@@ -13,7 +13,7 @@ void ColorsYaze();
} // namespace Style
} // namespace Core
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -9,7 +9,7 @@
#include <regex>
namespace yaze {
namespace Application {
namespace application {
namespace Graphics {
TilesPattern::TilesPattern() {
@@ -22,6 +22,8 @@ TilesPattern::TilesPattern() {
transform_vector_.push_back(std::vector<int>{4, 5, 6, 7});
transform_vector_.push_back(std::vector<int>{8, 9, 11, 12});
transform_vector_.push_back(std::vector<int>{13, 14, 15, 16});
// "[0, 1, 4, 5], [2, 3, 6, 7], [8, 9, C, D], [A, B, E, F]"
}
// [pattern]
@@ -146,5 +148,5 @@ std::vector<std::vector<tile8> > TilesPattern::transform(
}
} // namespace Graphics
} // namespace Application
} // namespace application
} // namespace yaze

View File

@@ -12,7 +12,7 @@
#include "Graphics/palette.h"
namespace yaze {
namespace Application {
namespace application {
namespace Graphics {
// vhopppcc cccccccc
@@ -100,7 +100,7 @@ class TilePreset {
};
} // namespace Graphics
} // namespace Application
} // namespace application
} // namespace yaze
#endif

View File

@@ -32,19 +32,18 @@ add_library("NintendoCompression" STATIC ${SNESHACKING_SOURCES})
add_executable(
yaze
yaze.cc
Application/Core/controller.cc
Application/Core/renderer.cc
Application/Core/window.cc
Application/Data/rom.cc
Application/Data/OW/overworld.cc
Application/Data/OW/overworld_map.cc
Application/Graphics/bitmap.cc
Application/Graphics/tile.cc
Application/Graphics/palette.cc
Application/Graphics/style.cc
Application/Graphics/scene.cc
Application/Editor/editor.cc
Application/Editor/overworld_editor.cc
application/Core/controller.cc
application/Core/input.cc
application/Data/rom.cc
application/Data/OW/overworld.cc
application/Data/OW/overworld_map.cc
application/Graphics/bitmap.cc
application/Graphics/tile.cc
application/Graphics/palette.cc
application/Graphics/style.cc
application/Graphics/scene.cc
application/Editor/editor.cc
application/Editor/overworld_editor.cc
# GUI libraries
${IMGUI_PATH}/imgui.cpp
${IMGUI_PATH}/imgui_demo.cpp
@@ -67,7 +66,7 @@ add_executable(
target_include_directories(
yaze PUBLIC
Library/
Application/
application/
"C:/msys64/mingw64/include/libpng16"
"C:/msys64/mingw64/include/SDL2"
"C:/msys64/mingw64/include"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,185 @@
#include "controller.h"
#include <SDL2/SDL.h>
#include <imgui/backends/imgui_impl_sdl.h>
#include <imgui/backends/imgui_impl_sdlrenderer.h>
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
#include <memory>
#include "Editor/editor.h"
namespace yaze {
namespace application {
namespace Core {
bool Controller::isActive() const { return active_; }
void Controller::onEntry() {
CreateWindow();
CreateRenderer();
CreateGuiContext();
editor_.SetupScreen(sdl_renderer_);
ImGuiIO &io = ImGui::GetIO();
io.KeyMap[ImGuiKey_Backspace] = SDL_GetScancodeFromKey(SDLK_BACKSPACE);
io.KeyMap[ImGuiKey_Enter] = SDL_GetScancodeFromKey(SDLK_RETURN);
io.KeyMap[ImGuiKey_UpArrow] = SDL_GetScancodeFromKey(SDLK_UP);
io.KeyMap[ImGuiKey_DownArrow] = SDL_GetScancodeFromKey(SDLK_DOWN);
io.KeyMap[ImGuiKey_Tab] = SDL_GetScancodeFromKey(SDLK_TAB);
io.KeyMap[ImGuiKey_LeftCtrl] = SDL_GetScancodeFromKey(SDLK_LCTRL);
active_ = true;
}
void Controller::onInput() {
int wheel = 0;
int mouseX;
int mouseY;
SDL_Event event;
ImGuiIO &io = ImGui::GetIO();
const int buttons = SDL_GetMouseState(&mouseX, &mouseY);
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_UP:
case SDLK_DOWN:
case SDLK_RETURN:
case SDLK_BACKSPACE:
case SDLK_TAB:
io.KeysDown[event.key.keysym.scancode] =
(event.type == SDL_KEYDOWN);
break;
default:
break;
}
break;
case SDL_KEYUP: {
int key = event.key.keysym.scancode;
IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
io.KeysDown[key] = (event.type == SDL_KEYDOWN);
io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
break;
}
case SDL_WINDOWEVENT:
switch (event.window.event) {
case SDL_WINDOWEVENT_CLOSE:
quit();
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
io.DisplaySize.x = static_cast<float>(event.window.data1);
io.DisplaySize.y = static_cast<float>(event.window.data2);
break;
default:
break;
}
break;
case SDL_TEXTINPUT:
io.AddInputCharactersUTF8(event.text.text);
break;
case SDL_MOUSEWHEEL:
wheel = event.wheel.y;
break;
default:
break;
}
}
io.DeltaTime = 1.0f / 60.0f;
io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY));
io.MouseDown[0] = buttons & SDL_BUTTON(SDL_BUTTON_LEFT);
io.MouseDown[1] = buttons & SDL_BUTTON(SDL_BUTTON_RIGHT);
io.MouseWheel = static_cast<float>(wheel);
}
void Controller::onLoad() { editor_.UpdateScreen(); }
void Controller::doRender() {
SDL_RenderClear(sdl_renderer_.get());
ImGui::Render();
ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
SDL_RenderPresent(sdl_renderer_.get());
}
void Controller::onExit() {
ImGui_ImplSDLRenderer_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
SDL_Quit();
}
void Controller::CreateWindow() {
if (SDL_Init(SDL_INIT_EVERYTHING)) {
SDL_Log("SDL_Init: %s\n", SDL_GetError());
} else {
sdl_window_ = std::unique_ptr<SDL_Window, sdl_deleter>(
SDL_CreateWindow("Yet Another Zelda3 Editor", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
1200, // width, in pixels
800, // height, in pixels
SDL_WINDOW_RESIZABLE),
sdl_deleter());
}
}
void Controller::CreateRenderer() {
if (sdl_window_ == nullptr) {
SDL_Log("SDL_CreateWindow: %s\n", SDL_GetError());
SDL_Quit();
} else {
sdl_renderer_ = std::unique_ptr<SDL_Renderer, sdl_deleter>(
SDL_CreateRenderer(
sdl_window_.get(), -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
sdl_deleter());
if (sdl_renderer_ == nullptr) {
SDL_Log("SDL_CreateRenderer: %s\n", SDL_GetError());
SDL_Quit();
} else {
SDL_SetRenderDrawBlendMode(sdl_renderer_.get(), SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(sdl_renderer_.get(), 0x00, 0x00, 0x00, 0x00);
}
}
}
void Controller::CreateGuiContext() {
// Create the ImGui and ImPlot contexts
ImGui::CreateContext();
// Initialize ImGui for SDL
ImGui_ImplSDL2_InitForSDLRenderer(sdl_window_.get(), sdl_renderer_.get());
ImGui_ImplSDLRenderer_Init(sdl_renderer_.get());
// Load available fonts
const ImGuiIO &io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("assets/Fonts/Karla-Regular.ttf", 14.0f);
// merge in icons from Google Material Design
static const ImWchar icons_ranges[] = {ICON_MIN_MD, 0xf900, 0};
ImFontConfig icons_config;
icons_config.MergeMode = true;
icons_config.GlyphOffset.y = 5.0f;
icons_config.GlyphMinAdvanceX = 13.0f;
icons_config.PixelSnapH = true;
io.Fonts->AddFontFromFileTTF(FONT_ICON_FILE_NAME_MD, 18.0f, &icons_config,
icons_ranges);
io.Fonts->AddFontFromFileTTF("assets/Fonts/Roboto-Medium.ttf", 14.0f);
io.Fonts->AddFontFromFileTTF("assets/Fonts/Cousine-Regular.ttf", 14.0f);
io.Fonts->AddFontFromFileTTF("assets/Fonts/DroidSans.ttf", 16.0f);
// Set the default style
Style::ColorsYaze();
// Build a new ImGui frame
ImGui_ImplSDLRenderer_NewFrame();
ImGui_ImplSDL2_NewFrame(sdl_window_.get());
}
} // namespace Core
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,55 @@
#ifndef YAZE_APPLICATION_CORE_CONTROLLER_H
#define YAZE_APPLICATION_CORE_CONTROLLER_H
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <imgui/backends/imgui_impl_sdl.h>
#include <imgui/backends/imgui_impl_sdlrenderer.h>
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
#include "Editor/editor.h"
#include "Graphics/icons.h"
#include "Graphics/style.h"
int main(int argc, char **argv);
namespace yaze {
namespace application {
namespace Core {
class Controller {
public:
Controller() = default;
bool isActive() const;
void onEntry();
void onInput();
void onLoad();
void doRender();
void onExit();
private:
void CreateWindow();
void CreateRenderer();
void CreateGuiContext();
inline void quit() { active_ = false; }
friend int ::main(int argc, char **argv);
struct sdl_deleter {
void operator()(SDL_Window *p) const { SDL_DestroyWindow(p); }
void operator()(SDL_Renderer *p) const { SDL_DestroyRenderer(p); }
void operator()(SDL_Texture *p) const { SDL_DestroyTexture(p); }
};
bool active_;
Editor::Editor editor_;
std::shared_ptr<SDL_Window> sdl_window_;
std::shared_ptr<SDL_Renderer> sdl_renderer_;
};
} // namespace Core
} // namespace application
} // namespace yaze
#endif // YAZE_APPLICATION_CORE_CONTROLLER_H

View File

@@ -0,0 +1,18 @@
#ifndef YAZE_APPLICATION_CONTROLLER_ENTRYPOINT_H
#define YAZE_APPLICATION_CONTROLLER_ENTRYPOINT_H
#include "controller.h"
int main(int argc, char** argv) {
yaze::application::Core::Controller controller;
controller.onEntry();
while (controller.isActive()) {
controller.onInput();
controller.onLoad();
controller.doRender();
}
controller.onExit();
return EXIT_SUCCESS;
}
#endif // YAZE_APPLICATION_CONTROLLER_ENTRYPOINT_H

View File

@@ -0,0 +1,25 @@
#include "input.h"
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
namespace yaze {
namespace Gui {
const int kStepOneHex = 0x01;
const int kStepFastHex = 0x0F;
bool InputHex(const char* label, int* data) {
return ImGui::InputScalar(label, ImGuiDataType_U64, data, &kStepOneHex,
&kStepFastHex, "%06X",
ImGuiInputTextFlags_CharsHexadecimal);
}
bool InputHexShort(const char* label, int* data) {
return ImGui::InputScalar(label, ImGuiDataType_U32, data, &kStepOneHex,
&kStepFastHex, "%06X",
ImGuiInputTextFlags_CharsHexadecimal);
}
} // namespace Gui
} // namespace yaze

View File

@@ -0,0 +1,19 @@
#ifndef YAZE_APPLICATION_CORE_INPUT_H
#define YAZE_APPLICATION_CORE_INPUT_H
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
#include <cstddef>
#include <cstdint>
namespace yaze {
namespace Gui {
IMGUI_API bool InputHex(const char* label, int* data);
IMGUI_API bool InputHexShort(const char* label, int* data);
} // namespace Gui
} // namespace yaze
#endif

View File

@@ -0,0 +1,349 @@
#include "overworld.h"
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Data {
using namespace Core;
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);
delete[] overworldMapPointer;
delete[] owactualMapPointer;
}
}
static TileInfo GetTilesInfo(ushort tile) {
// vhopppcc cccccccc
ushort o = 0;
ushort v = 0;
ushort h = 0;
ushort tid = (ushort)(tile & 0x3FF);
uchar p = (uchar)((tile >> 10) & 0x07);
o = (ushort)((tile & 0x2000) >> 13);
h = (ushort)((tile & 0x4000) >> 14);
v = (ushort)((tile & 0x8000) >> 15);
return TileInfo(tid, p, v, h, o);
}
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)));
}
AssembleMap32Tiles();
AssembleMap16Tiles();
DecompressAllMapTiles();
// Map Initialization :
for (int i = 0; i < 160; i++) {
allmaps.push_back(OverworldMap(rom_, tiles16, (uchar)i));
}
FetchLargeMaps();
LoadOverworldMap();
auto size = tiles16.size();
for (int i = 0; i < 160; i++) {
allmaps[i].BuildMap(mapParent, size, gameState, allmapsTilesLW,
allmapsTilesDW, allmapsTilesSP);
}
isLoaded = true;
}
ushort Overworld::GenerateTile32(int i, int k, int dimension) {
return (ushort)(rom_.GetRawData()[map32address[dimension] + k + (i)] +
(((rom_.GetRawData()[map32address[dimension] + (i) +
(k <= 1 ? 4 : 5)] >>
(k % 2 == 0 ? 4 : 0)) &
0x0F) *
256));
}
void Overworld::AssembleMap32Tiles() {
for (int i = 0; i < 0x33F0; i += 6) {
ushort tl, tr, bl, br;
for (int k = 0; k < 4; k++) {
tl = GenerateTile32(i, k, (int)Dimension::map32TilesTL);
tr = GenerateTile32(i, k, (int)Dimension::map32TilesTR);
bl = GenerateTile32(i, k, (int)Dimension::map32TilesBL);
br = GenerateTile32(i, k, (int)Dimension::map32TilesBR);
tiles32.push_back(Tile32(tl, tr, bl, br));
}
}
allmapsTilesLW = (ushort**)malloc(tiles32.size() * sizeof(ushort*));
for (int i = 0; i < tiles32.size(); i++)
allmapsTilesLW[i] = (ushort*)malloc(tiles32.size() * sizeof(ushort));
allmapsTilesDW = (ushort**)malloc(tiles32.size() * sizeof(ushort*));
for (int i = 0; i < tiles32.size(); i++)
allmapsTilesDW[i] = (ushort*)malloc(tiles32.size() * sizeof(ushort));
allmapsTilesSP = (ushort**)malloc(tiles32.size() * sizeof(ushort*));
for (int i = 0; i < tiles32.size(); i++)
allmapsTilesSP[i] = (ushort*)malloc(tiles32.size() * sizeof(ushort));
}
void Overworld::AssembleMap16Tiles() {
int tpos = Core::Constants::map16Tiles;
for (int i = 0; i < 4096; i += 1) // 3760
{
TileInfo t0 = GetTilesInfo((uintptr_t)rom_.GetRawData() + tpos);
tpos += 2;
TileInfo t1 = GetTilesInfo((uintptr_t)rom_.GetRawData() + tpos);
tpos += 2;
TileInfo t2 = GetTilesInfo((uintptr_t)rom_.GetRawData() + tpos);
tpos += 2;
TileInfo t3 = GetTilesInfo((uintptr_t)rom_.GetRawData() + tpos);
tpos += 2;
tiles16.push_back(Tile16(t0, t1, t2, t3));
}
}
void Overworld::DecompressAllMapTiles() {
int lowest = 0x0FFFFF;
int highest = 0x0F8000;
int sx = 0;
int sy = 0;
int c = 0;
for (int i = 0; i < 160; i++) {
int p1 = (rom_.GetRawData()[(Constants::compressedAllMap32PointersHigh) +
2 + (int)(3 * i)]
<< 16) +
(rom_.GetRawData()[(Constants::compressedAllMap32PointersHigh) +
1 + (int)(3 * i)]
<< 8) +
(rom_.GetRawData()[(Constants::compressedAllMap32PointersHigh +
(int)(3 * i))]);
char* tmp = new char[256];
p1 = lorom_snes_to_pc(p1, &tmp);
std::cout << tmp << std::endl;
int p2 = (rom_.GetRawData()[(Constants::compressedAllMap32PointersLow) + 2 +
(int)(3 * i)]
<< 16) +
(rom_.GetRawData()[(Constants::compressedAllMap32PointersLow) + 1 +
(int)(3 * i)]
<< 8) +
(rom_.GetRawData()[(Constants::compressedAllMap32PointersLow +
(int)(3 * i))]);
p2 = lorom_snes_to_pc(p2, &tmp);
std::cout << tmp << std::endl;
delete[] tmp;
int ttpos = 0;
unsigned int compressedSize1 = 0;
unsigned int compressedSize2 = 0;
unsigned int compressedLength1 = 0;
unsigned int compressedLength2 = 0;
if (p1 >= highest) {
highest = p1;
}
if (p2 >= highest) {
highest = p2;
}
if (p1 <= lowest) {
if (p1 > 0x0F8000) {
lowest = p1;
}
}
if (p2 <= lowest) {
if (p2 > 0x0F8000) {
lowest = p2;
}
}
auto bytes =
alttp_decompress_overworld((char*)rom_.GetRawData(), p2, 1000,
&compressedSize1, &compressedLength1);
auto bytes2 =
alttp_decompress_overworld((char*)rom_.GetRawData(), p1, 1000,
&compressedSize2, &compressedLength2);
for (int y = 0; y < 16; y++) {
for (int x = 0; x < 16; x++) {
ushort tidD = (ushort)((bytes2[ttpos] << 8) + bytes[ttpos]);
int tpos = tidD;
if (tpos < tiles32.size()) {
if (i < 64) {
allmapsTilesLW[(x * 2) + (sx * 32)][(y * 2) + (sy * 32)] =
tiles32[tpos].tile0_;
allmapsTilesLW[(x * 2) + 1 + (sx * 32)][(y * 2) + (sy * 32)] =
tiles32[tpos].tile1_;
allmapsTilesLW[(x * 2) + (sx * 32)][(y * 2) + 1 + (sy * 32)] =
tiles32[tpos].tile2_;
allmapsTilesLW[(x * 2) + 1 + (sx * 32)][(y * 2) + 1 + (sy * 32)] =
tiles32[tpos].tile3_;
} else if (i < 128 && i >= 64) {
allmapsTilesDW[(x * 2) + (sx * 32)][(y * 2) + (sy * 32)] =
tiles32[tpos].tile0_;
allmapsTilesDW[(x * 2) + 1 + (sx * 32)][(y * 2) + (sy * 32)] =
tiles32[tpos].tile1_;
allmapsTilesDW[(x * 2) + (sx * 32)][(y * 2) + 1 + (sy * 32)] =
tiles32[tpos].tile2_;
allmapsTilesDW[(x * 2) + 1 + (sx * 32)][(y * 2) + 1 + (sy * 32)] =
tiles32[tpos].tile3_;
} else {
allmapsTilesSP[(x * 2) + (sx * 32)][(y * 2) + (sy * 32)] =
tiles32[tpos].tile0_;
allmapsTilesSP[(x * 2) + 1 + (sx * 32)][(y * 2) + (sy * 32)] =
tiles32[tpos].tile1_;
allmapsTilesSP[(x * 2) + (sx * 32)][(y * 2) + 1 + (sy * 32)] =
tiles32[tpos].tile2_;
allmapsTilesSP[(x * 2) + 1 + (sx * 32)][(y * 2) + 1 + (sy * 32)] =
tiles32[tpos].tile3_;
}
}
ttpos += 1;
}
}
sx++;
if (sx >= 8) {
sy++;
sx = 0;
}
c++;
if (c >= 64) {
sx = 0;
sy = 0;
c = 0;
}
}
std::cout << "MapPointers(lowest) : " << lowest << std::endl;
std::cout << "MapPointers(highest) : " << highest << std::endl;
}
void Overworld::FetchLargeMaps() {
for (int i = 128; i < 145; i++) {
mapParent[i] = 0;
}
mapParent[128] = 128;
mapParent[129] = 129;
mapParent[130] = 129;
mapParent[137] = 129;
mapParent[138] = 129;
mapParent[136] = 136;
allmaps[136].largeMap = false;
bool mapChecked[64];
for (int i = 0; i < 64; i++) {
mapChecked[i] = false;
}
int xx = 0;
int yy = 0;
while (true) {
int i = xx + (yy * 8);
if (mapChecked[i] == false) {
if (allmaps[i].largeMap == true) {
mapChecked[i] = true;
mapParent[i] = (uchar)i;
mapParent[i + 64] = (uchar)(i + 64);
mapChecked[i + 1] = true;
mapParent[i + 1] = (uchar)i;
mapParent[i + 65] = (uchar)(i + 64);
mapChecked[i + 8] = true;
mapParent[i + 8] = (uchar)i;
mapParent[i + 72] = (uchar)(i + 64);
mapChecked[i + 9] = true;
mapParent[i + 9] = (uchar)i;
mapParent[i + 73] = (uchar)(i + 64);
xx++;
} else {
mapParent[i] = (uchar)i;
mapParent[i + 64] = (uchar)(i + 64);
mapChecked[i] = true;
}
}
xx++;
if (xx >= 8) {
xx = 0;
yy += 1;
if (yy >= 8) {
break;
}
}
}
}
void Overworld::LoadOverworldMap() {
overworldMapBitmap = new Bitmap(128, 128, overworldMapPointer);
owactualMapBitmap = new Bitmap(512, 512, owactualMapPointer);
// Mode 7
char* ptr = overworldMapPointer;
int pos = 0;
for (int sy = 0; sy < 16; sy++) {
for (int sx = 0; sx < 16; sx++) {
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
ptr[x + (sx * 8) + (y * 128) + (sy * 1024)] =
rom_.GetRawData()[0x0C4000 + pos];
pos++;
}
}
}
}
// ColorPalette cp = overworldMapBitmap.Palette;
// for (int i = 0; i < 256; i += 2)
// {
// //55B27 = US LW
// //55C27 = US DW
// cp.Entries[i / 2] = getColor((short)((ROM.DATA[0x55B27 + i + 1] << 8) +
// ROM.DATA[0x55B27 + i]));
// int k = 0;
// int j = 0;
// for (int y = 10; y < 14; y++)
// {
// for (int x = 0; x < 15; x++)
// {
// cp.Entries[145 + k] = Palettes.globalSprite_Palettes[0][j];
// k++;
// j++;
// }
// k++;
// }
// }
// overworldMapBitmap.Palette = cp;
// owactualMapBitmap.Palette = cp;
}
} // namespace Data
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,74 @@
#ifndef YAZE_APPLICATION_DATA_OVERWORLD_H
#define YAZE_APPLICATION_DATA_OVERWORLD_H
#include <rommapping.h>
#include <memory>
#include <vector>
#include "Core/constants.h"
#include "Data/rom.h"
#include "Graphics/bitmap.h"
#include "Graphics/tile.h"
#include "overworld_map.h"
namespace yaze {
namespace application {
namespace Data {
class Overworld {
public:
Overworld() = default;
~Overworld();
void Load(Data::ROM rom);
char* overworldMapPointer = new char[0x40000];
Graphics::Bitmap* overworldMapBitmap;
char* owactualMapPointer = new char[0x40000];
Graphics::Bitmap* owactualMapBitmap;
private:
Data::ROM rom_;
int gameState = 1;
bool isLoaded = false;
uchar mapParent[160];
ushort** allmapsTilesLW; // 64 maps * (32*32 tiles)
ushort** allmapsTilesDW; // 64 maps * (32*32 tiles)
ushort** allmapsTilesSP; // 32 maps * (32*32 tiles)
std::vector<Graphics::Tile16> tiles16;
std::vector<Graphics::Tile32> tiles32;
std::vector<Graphics::Tile32> map16tiles;
std::vector<OverworldMap> allmaps;
std::vector<ushort> tileLeftEntrance;
std::vector<ushort> tileRightEntrance;
int map32address[4] = {
Core::Constants::map32TilesTL, Core::Constants::map32TilesTR,
Core::Constants::map32TilesBL, Core::Constants::map32TilesBR};
enum Dimension {
map32TilesTL = 0,
map32TilesTR = 1,
map32TilesBL = 2,
map32TilesBR = 3
};
ushort GenerateTile32(int i, int k, int dimension);
void AssembleMap32Tiles();
void AssembleMap16Tiles();
void DecompressAllMapTiles();
void FetchLargeMaps();
void LoadOverworldMap();
};
} // namespace Data
} // namespace application
} // namespace yaze
#endif

View File

@@ -0,0 +1,359 @@
#include "overworld_map.h"
#include "Data/rom.h"
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Data {
using namespace Core;
using namespace Graphics;
OverworldMap::OverworldMap(Data::ROM rom,
const std::vector<Graphics::Tile16> tiles16,
uchar index)
: rom_(rom), index(index), tiles16_(tiles16), parent(index) {
if (index != 0x80) {
if (index <= 150) {
if (rom_.GetRawData()[Constants::overworldMapSize + (index & 0x3F)] !=
0) {
largeMap = true;
}
}
}
if (index < 64) {
sprgfx[0] = rom_.GetRawData()[Constants::overworldSpriteset + parent];
sprgfx[1] = rom_.GetRawData()[Constants::overworldSpriteset + parent + 64];
sprgfx[2] = rom_.GetRawData()[Constants::overworldSpriteset + parent + 128];
gfx = rom_.GetRawData()[Constants::mapGfx + parent];
palette = rom_.GetRawData()[Constants::overworldMapPalette + parent];
sprpalette[0] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent];
sprpalette[1] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent + 64];
sprpalette[2] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent + 128];
musics[0] = rom_.GetRawData()[Constants::overworldMusicBegining + parent];
musics[1] = rom_.GetRawData()[Constants::overworldMusicZelda + parent];
musics[2] =
rom_.GetRawData()[Constants::overworldMusicMasterSword + parent];
musics[3] = rom_.GetRawData()[Constants::overworldMusicAgahim + parent];
} else if (index < 128) {
sprgfx[0] = rom_.GetRawData()[Constants::overworldSpriteset + parent + 128];
sprgfx[1] = rom_.GetRawData()[Constants::overworldSpriteset + parent + 128];
sprgfx[2] = rom_.GetRawData()[Constants::overworldSpriteset + parent + 128];
gfx = rom_.GetRawData()[Constants::mapGfx + parent];
palette = rom_.GetRawData()[Constants::overworldMapPalette + parent];
sprpalette[0] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent + 128];
sprpalette[1] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent + 128];
sprpalette[2] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent + 128];
musics[0] = rom_.GetRawData()[Constants::overworldMusicDW + (parent - 64)];
} else {
if (index == 0x94) {
parent = 128;
} else if (index == 0x95) {
parent = 03;
} else if (index == 0x96) // pyramid bg use 0x5B map
{
parent = 0x5B;
} else if (index == 0x97) // pyramid bg use 0x5B map
{
parent = 0x00;
} else if (index == 156) {
parent = 67;
} else if (index == 157) {
parent = 0;
} else if (index == 158) {
parent = 0;
} else if (index == 159) {
parent = 44;
} else if (index == 136) {
parent = 136;
}
messageID = rom_.GetRawData()[Constants::overworldMessages + parent];
sprgfx[0] = rom_.GetRawData()[Constants::overworldSpriteset + parent + 128];
sprgfx[1] = rom_.GetRawData()[Constants::overworldSpriteset + parent + 128];
sprgfx[2] = rom_.GetRawData()[Constants::overworldSpriteset + parent + 128];
sprpalette[0] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent + 128];
sprpalette[1] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent + 128];
sprpalette[2] =
rom_.GetRawData()[Constants::overworldSpritePalette + parent + 128];
palette =
rom_.GetRawData()[Constants::overworldSpecialPALGroup + parent - 128];
if (index >= 0x80 && index <= 0x8A && index != 0x88) {
gfx = rom_.GetRawData()[Constants::overworldSpecialGFXGroup +
(parent - 128)];
palette = rom_.GetRawData()[Constants::overworldSpecialPALGroup + 1];
} else if (index == 0x88) {
gfx = 81;
palette = 0;
} else // pyramid bg use 0x5B map
{
gfx = rom_.GetRawData()[Constants::mapGfx + parent];
palette = rom_.GetRawData()[Constants::overworldMapPalette + parent];
}
}
}
void OverworldMap::BuildMap(uchar* mapParent, int count, int gameState,
ushort** allmapsTilesLW, ushort** allmapsTilesDW,
ushort** allmapsTilesSP) {
tilesUsed = new ushort*[32];
for (int i = 0; i < 32; i++) tilesUsed[i] = new ushort;
if (largeMap) {
this->parent = mapParent[index];
if (parent != index) {
if (!firstLoad) {
gfx = rom_.GetRawData()[Constants::mapGfx + parent];
palette = rom_.GetRawData()[Constants::overworldMapPalette + parent];
firstLoad = true;
}
}
}
BuildTileset(gameState);
BuildTiles16Gfx(count); // build on GFX.mapgfx16Ptr
int world = 0;
if (index < 64) {
tilesUsed = allmapsTilesLW;
} else if (index < 128 && index >= 64) {
tilesUsed = allmapsTilesDW;
world = 1;
} else {
tilesUsed = allmapsTilesSP;
world = 2;
}
int superY = ((index - (world * 64)) / 8);
int superX = index - (world * 64) - (superY * 8);
for (int y = 0; y < 32; y++) {
for (int x = 0; x < 32; x++) {
CopyTile8bpp16((x * 16), (y * 16),
tilesUsed[x + (superX * 32)][y + (superY * 32)], gfxPtr,
mapblockset16);
}
}
}
void OverworldMap::CopyTile8bpp16(int x, int y, int tile, int* destbmpPtr,
int* sourcebmpPtr) {
int sourceY = (tile / 8);
int sourceX = (tile) - ((sourceY)*8);
int sourcePtrPos = ((tile - ((tile / 8) * 8)) * 16) +
((tile / 8) * 2048); //(sourceX * 16) + (sourceY * 128);
uchar* sourcePtr = (uchar*)sourcebmpPtr;
int destPtrPos = (x + (y * 512));
uchar* destPtr = (uchar*)destbmpPtr;
for (int ystrip = 0; ystrip < 16; ystrip++) {
for (int xstrip = 0; xstrip < 16; xstrip++) {
destPtr[destPtrPos + xstrip + (ystrip * 512)] =
sourcePtr[sourcePtrPos + xstrip + (ystrip * 128)];
}
}
}
void OverworldMap::CopyTile8bpp16From8(int xP, int yP, int tileID,
int* destbmpPtr, int* sourcebmpPtr) {
auto gfx16Data = (uchar*)destbmpPtr;
auto gfx8Data = currentOWgfx16Ptr;
int offsets[] = {0, 8, 4096, 4104};
auto tiles = tiles16_[tileID];
for (auto tile = 0; tile < 4; tile++) {
TileInfo info = tiles.tiles_info[tile];
int offset = offsets[tile];
for (auto y = 0; y < 8; y++) {
for (auto x = 0; x < 4; x++) {
CopyTileToMap(x, y, xP, yP, offset, info, gfx16Data, gfx8Data);
}
}
}
}
void OverworldMap::BuildTiles16Gfx(int count) {
uchar* gfx16Data = (uchar*)mapblockset16;
uchar* gfx8Data = currentOWgfx16Ptr;
int offsets[] = {0, 8, 1024, 1032};
auto yy = 0;
auto xx = 0;
for (auto i = 0; i < count; i++) // number of tiles16 3748?
{
// 8x8 tile draw
// gfx8 = 4bpp so everyting is /2F
auto tiles = tiles16_[i];
for (auto tile = 0; tile < 4; tile++) {
TileInfo info = tiles16_[i].tiles_info[tile];
int offset = offsets[tile];
for (auto y = 0; y < 8; y++) {
for (auto x = 0; x < 4; x++) {
CopyTile(x, y, xx, yy, offset, info, gfx16Data, gfx8Data);
}
}
}
xx += 16;
if (xx >= 128) {
yy += 2048;
xx = 0;
}
}
}
void OverworldMap::CopyTile(int x, int y, int xx, int yy, int offset,
TileInfo tile, uchar* gfx16Pointer,
uchar* gfx8Pointer) // map,current
{
int mx = x;
int my = y;
uchar r = 0;
if (tile.horizontal_mirror_ != 0) {
mx = 3 - x;
r = 1;
}
if (tile.vertical_mirror_ != 0) {
my = 7 - y;
}
int tx = ((tile.id_ / 16) * 512) + ((tile.id_ - ((tile.id_ / 16) * 16)) * 4);
auto index = xx + yy + offset + (mx * 2) + (my * 128);
auto pixel = gfx8Pointer[tx + (y * 64) + x];
gfx16Pointer[index + r ^ 1] = (uchar)((pixel & 0x0F) + tile.palette_ * 16);
gfx16Pointer[index + r] = (uchar)(((pixel >> 4) & 0x0F) + tile.palette_ * 16);
}
void OverworldMap::CopyTileToMap(int x, int y, int xx, int yy, int offset,
TileInfo tile, uchar* gfx16Pointer,
uchar* gfx8Pointer) // map,current
{
int mx = x;
int my = y;
uchar r = 0;
if (tile.horizontal_mirror_ != 0) {
mx = 3 - x;
r = 1;
}
if (tile.vertical_mirror_ != 0) {
my = 7 - y;
}
int tx = ((tile.id_ / 16) * 512) + ((tile.id_ - ((tile.id_ / 16) * 16)) * 4);
auto index = xx + (yy * 512) + offset + (mx * 2) + (my * 512);
auto pixel = gfx8Pointer[tx + (y * 64) + x];
gfx16Pointer[index + r ^ 1] = (uchar)((pixel & 0x0F) + tile.palette_ * 16);
gfx16Pointer[index + r] = (uchar)(((pixel >> 4) & 0x0F) + tile.palette_ * 16);
}
void OverworldMap::BuildTileset(int gameState) {
int indexWorld = 0x20;
if (parent < 0x40) {
indexWorld = 0x20;
} else if (parent >= 0x40 && parent < 0x80) {
indexWorld = 0x21;
} else if (parent == 0x88) {
indexWorld = 36;
}
// Sprites Blocksets
staticgfx[8] = 115 + 0;
staticgfx[9] = 115 + 1;
staticgfx[10] = 115 + 6;
staticgfx[11] = 115 + 7;
for (int i = 0; i < 4; i++) {
staticgfx[12 + i] =
(uchar)(rom_.GetRawData()[Constants::sprite_blockset_pointer +
(sprgfx[gameState] * 4) + i] +
115);
}
// Main Blocksets
for (int i = 0; i < 8; i++) {
staticgfx[i] = rom_.GetRawData()[Constants::overworldgfxGroups2 +
(indexWorld * 8) + i];
}
if (rom_.GetRawData()[Constants::overworldgfxGroups + (gfx * 4)] != 0) {
staticgfx[3] = rom_.GetRawData()[Constants::overworldgfxGroups + (gfx * 4)];
}
if (rom_.GetRawData()[Constants::overworldgfxGroups + (gfx * 4) + 1] != 0) {
staticgfx[4] =
rom_.GetRawData()[Constants::overworldgfxGroups + (gfx * 4) + 1];
}
if (rom_.GetRawData()[Constants::overworldgfxGroups + (gfx * 4) + 2] != 0) {
staticgfx[5] =
rom_.GetRawData()[Constants::overworldgfxGroups + (gfx * 4) + 2];
}
if (rom_.GetRawData()[Constants::overworldgfxGroups + (gfx * 4) + 3] != 0) {
staticgfx[6] =
rom_.GetRawData()[Constants::overworldgfxGroups + (gfx * 4) + 3];
}
// Hardcoded overworld GFX Values, for death mountain
if ((parent >= 0x03 && parent <= 0x07) ||
(parent >= 0x0B && parent <= 0x0E)) {
staticgfx[7] = 89;
} else if ((parent >= 0x43 && parent <= 0x47) ||
(parent >= 0x4B && parent <= 0x4E)) {
staticgfx[7] = 89;
} else {
staticgfx[7] = 91;
}
uchar* currentmapgfx8Data = new uchar[(128 * 512) / 2];
// (uchar*)GFX.currentOWgfx16Ptr.ToPointer(); // loaded gfx for the current
// // map (empty at this point)
uchar* allgfxData = new uchar[(128 * 7136) / 2];
// (uchar*)GFX.allgfx16Ptr
// .ToPointer(); // all gfx of the game pack of 2048 uchars (4bpp)
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 2048; j++) {
uchar mapByte = allgfxData[j + (staticgfx[i] * 2048)];
switch (i) {
case 0:
case 3:
case 4:
case 5:
mapByte += 0x88;
break;
}
currentmapgfx8Data[(i * 2048) + j] = mapByte; // Upload used gfx data
}
}
}
} // namespace Data
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,77 @@
#include <imgui/imgui.h>
#include <cstddef>
#include <memory>
#include "Data/rom.h"
#include "Graphics/bitmap.h"
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Data {
using ushort = unsigned short;
class OverworldMap {
public:
uchar parent = 0;
uchar index = 0;
uchar gfx = 0;
uchar palette = 0;
bool firstLoad = false;
short messageID = 0;
bool largeMap = false;
uchar sprgfx[3];
uchar sprpalette[3];
uchar musics[4];
int* gfxPtr = new int[512 * 512];
int* mapblockset16 = new int[1048576];
Graphics::Bitmap mapblockset16Bitmap;
Graphics::Bitmap gfxBitmap;
uchar* staticgfx =
new uchar[16]; // Need to be used to display map and not pre render it!
ushort** tilesUsed;
bool needRefresh = false;
Data::ROM rom_;
uchar* currentOWgfx16Ptr = new uchar[(128 * 512) / 2];
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,
ushort** allmapsTilesSP);
void CopyTile8bpp16(int x, int y, int tile, int* destbmpPtr,
int* sourcebmpPtr);
void CopyTile8bpp16From8(int xP, int yP, int tileID, int* destbmpPtr,
int* sourcebmpPtr);
private:
void BuildTiles16Gfx(int count);
// void ReloadPalettes() { LoadPalette(); }
void CopyTile(int x, int y, int xx, int yy, int offset,
Graphics::TileInfo tile, uchar* gfx16Pointer,
uchar* gfx8Pointer);
void CopyTileToMap(int x, int y, int xx, int yy, int offset,
Graphics::TileInfo tile, uchar* gfx16Pointer,
uchar* gfx8Pointer);
void LoadPalette();
void SetColorsPalette(int index, ImVec4 main, ImVec4 animated, ImVec4 aux1,
ImVec4 aux2, ImVec4 hud, ImVec4 bgrcolor, ImVec4 spr,
ImVec4 spr2);
void BuildTileset(int gameState);
};
} // namespace Data
} // namespace application
} // namespace yaze

244
src/application/Data/rom.cc Normal file
View File

@@ -0,0 +1,244 @@
#include "rom.h"
#include <filesystem>
#include "Core/constants.h"
namespace yaze {
namespace application {
namespace Data {
ROM::~ROM() {
if (loaded) {
delete[] current_rom_;
}
}
// 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());
std::ifstream file(path.c_str(), std::ios::binary);
if (!file.is_open()) {
std::cout << "Error: Could not open ROM file " << path << std::endl;
return;
}
current_rom_ = new unsigned char[size_];
for (unsigned int i = 0; i < size_; i++) {
char byte_read_ = ' ';
file.read(&byte_read_, sizeof(char));
current_rom_[i] = byte_read_;
}
file.close();
memcpy(title, current_rom_ + 32704, 21);
version_ = current_rom_[27];
loaded = true;
}
std::vector<tile8> ROM::ExtractTiles(Graphics::TilePreset &preset) {
std::cout << "Extracting tiles..." << std::endl;
uint filePos = 0;
uint size_out = 0;
uint size = preset.length_;
int tilePos = preset.pc_tiles_location_;
std::vector<tile8> rawTiles;
filePos = GetRomPosition(preset, tilePos, preset.SNESTilesLocation);
std::cout << "ROM Position: " << filePos << " from "
<< preset.SNESTilesLocation << std::endl;
// decompress the graphics
auto data = (char *)malloc(sizeof(char) * size);
memcpy(data, (current_rom_ + 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;
if (data == nullptr) {
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;
for (unsigned int tilePos = 0; tilePos < size;
tilePos += preset.bits_per_pixel_ * 8) {
tile8 newTile = unpack_bpp_tile(data, tilePos, preset.bits_per_pixel_);
newTile.id = tileCpt;
rawTiles.push_back(newTile);
tileCpt++;
}
std::cout << "Done unpacking tiles" << std::endl;
free(data);
std::cout << "Done extracting tiles." << std::endl;
return rawTiles;
}
Graphics::SNESPalette ROM::ExtractPalette(Graphics::TilePreset &preset) {
unsigned int filePos = GetRomPosition(preset, preset.pc_palette_location_,
preset.SNESPaletteLocation);
std::cout << "Palette pos : " << filePos << std::endl; // TODO: make this hex
unsigned int palette_size = pow(2, preset.bits_per_pixel_); // - 1;
auto palette_data = std::make_unique<unsigned char[]>(palette_size * 2);
memcpy(palette_data.get(), current_rom_ + filePos, palette_size * 2);
// char *ab = (char *)malloc(sizeof(char) * (palette_size * 2));
// memcpy(ab, current_rom_ + filePos, palette_size * 2);
for (int i = 0; i < palette_size; i++) {
std::cout << palette_data[i];
}
std::cout << std::endl;
const unsigned char *data = palette_data.get();
Graphics::SNESPalette pal(data);
if (preset.no_zero_color_) {
Graphics::SNESColor col;
col.setRgb(ImVec4(153, 153, 153, 255));
pal.colors.push_back(col);
pal.colors.erase(pal.colors.begin(),
pal.colors.begin() + pal.colors.size() - 1);
}
return pal;
}
uint32_t ROM::GetRomPosition(const Graphics::TilePreset &preset, int directAddr,
unsigned int snesAddr) const {
unsigned int filePos = -1;
std::cout << "directAddr:" << directAddr << std::endl;
if (directAddr == -1) {
filePos = rommapping_snes_to_pc(snesAddr, type_, has_header_);
} else {
filePos = directAddr;
if (has_header_) filePos += 0x200;
}
std::cout << "filePos:" << filePos << std::endl;
return filePos;
}
unsigned char *sheetBuffer = (unsigned char *)malloc(0x1000);
unsigned char bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
void SNES3bppTo8bppSheet() // 128x32
{
char *buffer = new char[0x800];
int xx = 0; // positions where we are at on the sheet
int yy = 0;
int pos = 0;
int ypos = 0;
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[(y * 2) + (24 * pos)] & (bitmask[x])));
unsigned char b2 =
(unsigned char)(buffer[((y * 2) + (24 * pos)) + 1] & (bitmask[x]));
unsigned char b3 =
(unsigned char)(buffer[(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;
};
sheetBuffer[x + (xx) + (y * 128) + (yy * 1024)] = b;
}
}
pos++;
ypos++;
xx += 8;
if (ypos >= 16) {
yy++;
xx = 0;
ypos = 0;
}
}
}
char *Decompress(int pos, bool reversed = false) {
char *buffer = new char[0x800];
for (int i = 0; i < 0x800; i++) {
buffer[i] = 0;
}
unsigned int bufferPos = 0;
unsigned char cmd = 0;
unsigned int length = 0;
char romData[256];
unsigned char databyte = (unsigned char)romData[pos];
while (true) {
databyte = (unsigned char)romData[pos];
if (databyte == 0xFF) // End of decompression
{
break;
}
if ((databyte & 0xE0) == 0xE0) // Expanded Command
{
cmd = (unsigned char)((databyte >> 2) & 0x07);
length =
(unsigned short)(((romData[pos] << 8) | romData[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)romData[pos++];
}
// Do not advance in the ROM
break;
case 01: // Byte Fill
for (int i = 0; i < length; i++) {
buffer[bufferPos++] = (unsigned char)romData[pos];
}
pos += 1; // Advance 1 byte in the ROM
break;
case 02: // Word Fill
for (int i = 0; i < length; i += 2) {
buffer[bufferPos++] = (unsigned char)romData[pos];
buffer[bufferPos++] = (unsigned char)romData[pos + 1];
}
pos += 2; // Advance 2 byte in the ROM
break;
case 03: // Increasing Fill
{
unsigned char incByte = (unsigned char)romData[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 = ((romData[pos + 1] & 0xFF) << 8);
unsigned short s2 = ((romData[pos] & 0xFF));
unsigned short Addr = (unsigned short)(s1 | s2);
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;
}
int AddressFromBytes(uchar addr1, uchar addr2, uchar addr3) {
return (addr1 << 16) | (addr2 << 8) | addr3;
}
} // namespace Data
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,59 @@
#ifndef YAZE_APPLICATION_UTILS_ROM_H
#define YAZE_APPLICATION_UTILS_ROM_H
#include <compressions/alttpcompression.h>
#include <rommapping.h>
#include <tile.h>
#include <cstddef>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "Core/constants.h"
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Data {
int AddressFromBytes(uchar addr1, uchar addr2, uchar addr3);
class ROM {
public:
~ROM();
void LoadFromFile(const std::string& path);
std::vector<tile8> ExtractTiles(Graphics::TilePreset& preset);
Graphics::SNESPalette ExtractPalette(Graphics::TilePreset& preset);
uint32_t GetRomPosition(const Graphics::TilePreset& preset, int directAddr,
unsigned int snesAddr) const;
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; }
private:
bool loaded = false;
bool has_header_ = false;
uchar* current_rom_;
uchar version_;
uchar title[21] = "ROM Not Loaded";
uint uncompressed_size_;
uint compressed_size_;
uint compress_size_;
long int size_;
enum rom_type type_ = LoROM;
std::shared_ptr<uchar> rom_ptr_;
};
} // namespace Data
} // namespace application
} // namespace yaze
#endif

View File

@@ -0,0 +1,510 @@
#include "editor.h"
#include "Graphics/palette.h"
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Editor {
using namespace Core;
Editor::Editor() {
for (auto &k : Core::Constants::kKeywords)
language_65816_.mKeywords.emplace(k);
for (auto &k : Core::Constants::kIdentifiers) {
TextEditor::Identifier id;
id.mDeclaration = "Built-in function";
language_65816_.mIdentifiers.insert(std::make_pair(std::string(k), id));
}
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[ \\t]*#[ \\t]*[a-zA-Z_]+", TextEditor::PaletteIndex::Preprocessor));
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"L?\\\"(\\\\.|[^\\\"])*\\\"", TextEditor::PaletteIndex::String));
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"\\'\\\\?[^\\']\\'", TextEditor::PaletteIndex::CharLiteral));
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?",
TextEditor::PaletteIndex::Number));
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[+-]?[0-9]+[Uu]?[lL]?[lL]?", TextEditor::PaletteIndex::Number));
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"0[0-7]+[Uu]?[lL]?[lL]?", TextEditor::PaletteIndex::Number));
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?",
TextEditor::PaletteIndex::Number));
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[a-zA-Z_][a-zA-Z0-9_]*", TextEditor::PaletteIndex::Identifier));
language_65816_.mTokenRegexStrings.push_back(
std::make_pair<std::string, TextEditor::PaletteIndex>(
"[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/"
"\\;\\,\\.]",
TextEditor::PaletteIndex::Punctuation));
language_65816_.mCommentStart = "/*";
language_65816_.mCommentEnd = "*/";
language_65816_.mSingleLineComment = ";";
language_65816_.mCaseSensitive = false;
language_65816_.mAutoIndentation = true;
language_65816_.mName = "65816";
asm_editor_.SetLanguageDefinition(language_65816_);
asm_editor_.SetPalette(TextEditor::GetDarkPalette());
current_set_.bits_per_pixel_ = 4;
current_set_.pc_tiles_location_ = 0x80000;
current_set_.SNESTilesLocation = 0x0000;
current_set_.length_ = 28672;
current_set_.pc_palette_location_ = 906022;
current_set_.SNESPaletteLocation = 0;
}
void Editor::SetupScreen(std::shared_ptr<SDL_Renderer> renderer) {
sdl_renderer_ = renderer;
}
void Editor::UpdateScreen() {
const ImGuiIO &io = ImGui::GetIO();
ImGui::NewFrame();
ImGui::SetNextWindowPos(ImVec2(0, 0));
ImVec2 dimensions(io.DisplaySize.x, io.DisplaySize.y);
ImGui::SetNextWindowSize(dimensions, ImGuiCond_Always);
if (!ImGui::Begin("##YazeMain", nullptr, main_editor_flags_)) {
ImGui::End();
return;
}
DrawYazeMenu();
TAB_BAR("##TabBar")
DrawProjectEditor();
DrawOverworldEditor();
DrawDungeonEditor();
DrawGraphicsEditor();
DrawSpriteEditor();
DrawScreenEditor();
END_TAB_BAR()
ImGui::End();
}
void Editor::DrawYazeMenu() {
MENU_BAR()
DrawFileMenu();
DrawEditMenu();
DrawViewMenu();
DrawHelpMenu();
END_MENU_BAR()
if (ImGuiFileDialog::Instance()->Display("ChooseFileDlgKey")) {
if (ImGuiFileDialog::Instance()->IsOk()) {
std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName();
std::string filePath = ImGuiFileDialog::Instance()->GetCurrentPath();
rom_.LoadFromFile(filePathName);
overworld_editor_.SetRom(rom_);
rom_data_ = (void *)rom_.GetRawData();
}
ImGuiFileDialog::Instance()->Close();
}
}
void Editor::DrawFileMenu() const {
if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Open", "Ctrl+O")) {
ImGuiFileDialog::Instance()->OpenDialog("ChooseFileDlgKey", "Open ROM",
".sfc,.smc", ".");
}
if (ImGui::BeginMenu("Open Recent")) {
ImGui::MenuItem("alttp.sfc");
ImGui::EndMenu();
}
if (ImGui::MenuItem("Save", "Ctrl+S")) {
// TODO: Implement this
}
if (ImGui::MenuItem("Save As..")) {
// TODO: Implement this
}
ImGui::Separator();
// TODO: Make these options matter
if (ImGui::BeginMenu("Options")) {
static bool enabled = true;
ImGui::MenuItem("Enabled", "", &enabled);
ImGui::BeginChild("child", ImVec2(0, 60), true);
for (int i = 0; i < 10; i++) ImGui::Text("Scrolling Text %d", i);
ImGui::EndChild();
static float f = 0.5f;
static int n = 0;
ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
ImGui::InputFloat("Input", &f, 0.1f);
ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
ImGui::EndMenu();
}
ImGui::EndMenu();
}
}
void Editor::DrawEditMenu() const {
if (ImGui::BeginMenu("Edit")) {
if (ImGui::MenuItem("Undo", "Ctrl+Z")) {
// TODO: Implement this
}
if (ImGui::MenuItem("Undo", "Ctrl+Y")) {
// TODO: Implement this
}
ImGui::Separator();
if (ImGui::MenuItem("Cut", "Ctrl+X")) {
// TODO: Implement this
}
if (ImGui::MenuItem("Copy", "Ctrl+C")) {
// TODO: Implement this
}
if (ImGui::MenuItem("Paste", "Ctrl+V")) {
// TODO: Implement this
}
ImGui::Separator();
if (ImGui::MenuItem("Find", "Ctrl+F")) {
// TODO: Implement this
}
ImGui::EndMenu();
}
}
void Editor::DrawViewMenu() {
static bool show_imgui_metrics = false;
static bool show_imgui_style_editor = false;
static bool show_memory_editor = false;
static bool show_asm_editor = false;
static bool show_imgui_demo = false;
if (show_imgui_metrics) {
ImGui::ShowMetricsWindow(&show_imgui_metrics);
}
if (show_memory_editor) {
static MemoryEditor mem_edit;
mem_edit.DrawWindow("Memory Editor", rom_data_, rom_.getSize());
}
if (show_imgui_demo) {
ImGui::ShowDemoWindow();
}
if (show_asm_editor) {
static bool asm_is_loaded = false;
auto cpos = asm_editor_.GetCursorPosition();
static const char *fileToEdit = "assets/bunnyhood.asm";
if (!asm_is_loaded) {
std::ifstream t(fileToEdit);
if (t.good()) {
std::string str((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
asm_editor_.SetText(str);
}
asm_is_loaded = true;
}
ImGui::Begin("ASM Editor", &show_asm_editor);
ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
cpos.mColumn + 1, asm_editor_.GetTotalLines(),
asm_editor_.IsOverwrite() ? "Ovr" : "Ins",
asm_editor_.CanUndo() ? "*" : " ",
asm_editor_.GetLanguageDefinition().mName.c_str(), fileToEdit);
asm_editor_.Render(fileToEdit);
ImGui::End();
}
if (show_imgui_style_editor) {
ImGui::Begin("Style Editor (ImGui)", &show_imgui_style_editor);
ImGui::ShowStyleEditor();
ImGui::End();
}
if (ImGui::BeginMenu("View")) {
ImGui::MenuItem("HEX Editor", nullptr, &show_memory_editor);
ImGui::MenuItem("ASM Editor", nullptr, &show_asm_editor);
ImGui::MenuItem("ImGui Demo", nullptr, &show_imgui_demo);
ImGui::Separator();
if (ImGui::BeginMenu("GUI Tools")) {
ImGui::MenuItem("Metrics (ImGui)", nullptr, &show_imgui_metrics);
ImGui::MenuItem("Style Editor (ImGui)", nullptr,
&show_imgui_style_editor);
ImGui::EndMenu();
}
ImGui::EndMenu();
}
}
void Editor::DrawHelpMenu() const {
if (ImGui::BeginMenu("Help")) {
if (ImGui::MenuItem("About")) {
}
ImGui::EndMenu();
}
}
void Editor::DrawSurface() {
arranged_tiles_ =
Graphics::TilesPattern::transform(current_set_.tilesPattern, tiles_);
for (unsigned int j = 0; j < arranged_tiles_.size(); j++) {
for (unsigned int i = 0; i < arranged_tiles_[0].size(); i++) {
tile8 tile = arranged_tiles_[j][i];
// SDL_PIXELFORMAT_RGB888 ?
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(
0, 8, 8, SDL_BITSPERPIXEL(4), SDL_PIXELFORMAT_RGB444);
if (surface == nullptr) {
SDL_Log("SDL_CreateRGBSurfaceWithFormat() failed: %s", SDL_GetError());
exit(1);
}
SDL_PixelFormat *format = surface->format;
format->palette = current_palette_.GetSDL_Palette();
uchar *ptr = (uchar *)surface->pixels;
for (int k = 0; k < 8; k++) {
for (int l = 0; l < 8; l++) {
ptr[k * 8 + l] = tile.data[k * 8 + l];
}
}
SDL_Texture *texture =
SDL_CreateTextureFromSurface(sdl_renderer_.get(), surface);
if (texture == nullptr) {
std::cout << "Error: " << SDL_GetError() << std::endl;
}
imagesCache[tile.id] = texture;
}
}
}
void Editor::DrawProjectEditor() {
if (ImGui::BeginTabItem("Project")) {
if (ImGui::BeginTable("##projectTable", 2,
ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableSetupColumn("##inputs");
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::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);
BASIC_BUTTON("ExtractTiles") {
if (rom_.isLoaded()) {
tiles_ = rom_.ExtractTiles(current_set_);
}
}
BASIC_BUTTON("ExtractPalette") {
if (rom_.isLoaded()) {
current_palette_ = rom_.ExtractPalette(current_set_);
}
}
BASIC_BUTTON("BuildSurface") {
if (rom_.isLoaded()) {
DrawSurface();
}
}
static int i = 0;
for (auto &[key, texture] : imagesCache) {
ImGui::Image((void *)(SDL_Texture *)texture, ImVec2(32, 32));
if (i != 16) {
ImGui::SameLine();
} else if (i == 16) {
i = 0;
}
i++;
}
ImGui::TableNextColumn();
static ImVector<ImVec2> points;
static ImVec2 scrolling(0.0f, 0.0f);
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_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(
"canvas", 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);
// Pan (we use a zero mouse threshold when there's no context menu)
const float mouse_threshold_for_pan =
opt_enable_context_menu ? -1.0f : 0.0f;
if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right,
mouse_threshold_for_pan)) {
scrolling.x += io.MouseDelta.x;
scrolling.y += io.MouseDelta.y;
}
// Context menu (under default mouse threshold)
ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
if (opt_enable_context_menu && drag_delta.x == 0.0f &&
drag_delta.y == 0.0f)
ImGui::OpenPopupOnItemClick("context",
ImGuiPopupFlags_MouseButtonRight);
if (ImGui::BeginPopup("context")) {
ImGui::MenuItem("Placeholder");
ImGui::EndPopup();
}
// 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;
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));
}
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;
}
}
}
draw_list->PopClipRect();
ImGui::EndTable();
}
ImGui::EndTabItem();
}
}
void Editor::DrawOverworldEditor() {
if (ImGui::BeginTabItem("Overworld")) {
overworld_editor_.Update();
ImGui::EndTabItem();
}
}
void Editor::DrawDungeonEditor() {
if (ImGui::BeginTabItem("Dungeon")) {
if (ImGui::BeginTable("DWToolset", 9, toolset_table_flags_, ImVec2(0, 0))) {
ImGui::TableSetupColumn("#undoTool");
ImGui::TableSetupColumn("#redoTool");
ImGui::TableSetupColumn("#history");
ImGui::TableSetupColumn("#separator");
ImGui::TableSetupColumn("#bg1Tool");
ImGui::TableSetupColumn("#bg2Tool");
ImGui::TableSetupColumn("#bg3Tool");
ImGui::TableSetupColumn("#itemTool");
ImGui::TableSetupColumn("#spriteTool");
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_UNDO);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_REDO);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_MANAGE_HISTORY);
ImGui::TableNextColumn();
ImGui::Text(ICON_MD_MORE_VERT);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_FILTER_1);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_FILTER_2);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_FILTER_3);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_GRASS);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_PEST_CONTROL_RODENT);
ImGui::EndTable();
}
ImGui::EndTabItem();
}
}
void Editor::DrawGraphicsEditor() {
if (ImGui::BeginTabItem("Graphics")) {
ImGui::EndTabItem();
}
}
void Editor::DrawSpriteEditor() {
if (ImGui::BeginTabItem("Sprites")) {
ImGui::EndTabItem();
}
}
void Editor::DrawScreenEditor() {
if (ImGui::BeginTabItem("Screens")) {
ImGui::EndTabItem();
}
}
} // namespace Editor
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,71 @@
#ifndef YAZE_APPLICATION_VIEW_EDITOR_H
#define YAZE_APPLICATION_VIEW_EDITOR_H
#include <ImGuiColorTextEdit/TextEditor.h>
#include <ImGuiFileDialog/ImGuiFileDialog.h>
#include <imgui/imgui.h>
#include <imgui/imgui_memory_editor.h>
#include <imgui/misc/cpp/imgui_stdlib.h>
#include "Core/constants.h"
#include "Core/input.h"
#include "Data/rom.h"
#include "Editor/overworld_editor.h"
#include "Graphics/icons.h"
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Editor {
class Editor {
public:
Editor();
void SetupScreen(std::shared_ptr<SDL_Renderer> renderer);
void UpdateScreen();
private:
void DrawYazeMenu();
void DrawFileMenu() const;
void DrawEditMenu() const;
void DrawViewMenu();
void DrawHelpMenu() const;
void DrawSurface();
void DrawProjectEditor();
void DrawOverworldEditor();
void DrawDungeonEditor();
void DrawGraphicsEditor();
void DrawSpriteEditor();
void DrawScreenEditor();
void *rom_data_;
bool is_loaded_ = true;
std::vector<tile8> tiles_;
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;
std::shared_ptr<SDL_Renderer> sdl_renderer_;
Data::ROM rom_;
TextEditor asm_editor_;
TextEditor::LanguageDefinition language_65816_;
OverworldEditor overworld_editor_;
Graphics::Scene current_scene_;
Graphics::SNESPalette current_palette_;
Graphics::TilePreset current_set_;
ImGuiWindowFlags main_editor_flags_ =
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoTitleBar;
ImGuiTableFlags toolset_table_flags_ = ImGuiTableFlags_SizingFixedFit;
};
} // namespace Editor
} // namespace application
} // namespace yaze
#endif // YAZE_APPLICATION_VIEW_EDITOR_H

View File

@@ -0,0 +1,290 @@
#include "overworld_editor.h"
#include <imgui.h>
#include <cmath>
#include "Graphics/bitmap.h"
#include "Graphics/icons.h"
#include "Graphics/tile.h"
// first step would be to decompress all graphics data from the game
// (in alttp that's easy they're all located in the same location all the
// same sheet size 128x32) have a code that convert PC address to SNES and
// vice-versa
// 1) find the gfx pointers (you could use ZS constant file)
// 2) decompress all the gfx with your lz2 decompressor
// 3) convert the 3bpp snes data into PC 4bpp (probably the hardest part)
// 4) get the tiles32 data
// 5) get the tiles16 data
// 6) get the map32 data (they must be decompressed as well with a lz2
// variant not the same as gfx compression but pretty similar) 7) get the
// gfx data of the map yeah i forgot that one and load 4bpp in a pseudo vram
// and use that to render tiles on screen 8) try to render the tiles on the
// bitmap in black & white to start 9) get the palettes data and try to find
// how they're loaded in the game that's a big puzzle to solve then 9 you'll
// have an overworld map viewer, in less than few hours if are able to
// understand the data quickly
namespace yaze {
namespace application {
namespace Editor {
void OverworldEditor::Update() {
if (rom_.isLoaded()) {
if (!doneLoaded) {
// overworld.Load(rom_);
doneLoaded = true;
}
}
if (show_changelist_) {
DrawChangelist();
}
DrawToolset();
ImGui::Separator();
if (ImGui::BeginTable("#owEditTable", 2, ow_edit_flags, ImVec2(0, 0))) {
ImGui::TableSetupColumn("#overworldCanvas");
ImGui::TableSetupColumn("#tileSelector");
ImGui::TableNextColumn();
DrawOverworldCanvas();
ImGui::TableNextColumn();
DrawTileSelector();
ImGui::EndTable();
}
}
void OverworldEditor::DrawToolset() {
if (ImGui::BeginTable("Toolset", 14, toolset_table_flags, ImVec2(0, 0))) {
ImGui::TableSetupColumn("#undoTool");
ImGui::TableSetupColumn("#redoTool");
ImGui::TableSetupColumn("#drawTool");
ImGui::TableSetupColumn("#separator2");
ImGui::TableSetupColumn("#zoomOutTool");
ImGui::TableSetupColumn("#zoomInTool");
ImGui::TableSetupColumn("#separator");
ImGui::TableSetupColumn("#history");
ImGui::TableSetupColumn("#entranceTool");
ImGui::TableSetupColumn("#exitTool");
ImGui::TableSetupColumn("#itemTool");
ImGui::TableSetupColumn("#spriteTool");
ImGui::TableSetupColumn("#transportTool");
ImGui::TableSetupColumn("#musicTool");
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_UNDO);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_REDO);
ImGui::TableNextColumn();
if (ImGui::Button(ICON_MD_MANAGE_HISTORY)) {
if (!show_changelist_)
show_changelist_ = true;
else
show_changelist_ = false;
}
ImGui::TableNextColumn();
ImGui::Text(ICON_MD_MORE_VERT);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_ZOOM_OUT);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_ZOOM_IN);
ImGui::TableNextColumn();
ImGui::Text(ICON_MD_MORE_VERT);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_DRAW);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_DOOR_FRONT);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_DOOR_BACK);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_GRASS);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_PEST_CONTROL_RODENT);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_ADD_LOCATION);
ImGui::TableNextColumn();
ImGui::Button(ICON_MD_MUSIC_NOTE);
ImGui::EndTable();
}
}
void OverworldEditor::DrawOverworldMapSettings() {
if (ImGui::BeginTable("#mapSettings", 7, ow_map_settings_flags, ImVec2(0, 0),
-1)) {
ImGui::TableSetupColumn("##1stCol");
ImGui::TableSetupColumn("##gfxCol");
ImGui::TableSetupColumn("##palCol");
ImGui::TableSetupColumn("##sprgfxCol");
ImGui::TableSetupColumn("##sprpalCol");
ImGui::TableSetupColumn("##msgidCol");
ImGui::TableSetupColumn("##2ndCol");
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(100.f);
ImGui::Combo("##world", &current_world_,
"Light World\0Dark World\0Extra World\0");
ImGui::TableNextColumn();
ImGui::Text("GFX");
ImGui::SameLine();
ImGui::SetNextItemWidth(kInputFieldSize);
ImGui::InputText("##mapGFX", map_gfx_, kByteSize);
ImGui::TableNextColumn();
ImGui::Text("Palette");
ImGui::SameLine();
ImGui::SetNextItemWidth(kInputFieldSize);
ImGui::InputText("##mapPal", map_palette_, kByteSize);
ImGui::TableNextColumn();
ImGui::Text("Spr GFX");
ImGui::SameLine();
ImGui::SetNextItemWidth(kInputFieldSize);
ImGui::InputText("##sprGFX", spr_gfx_, kByteSize);
ImGui::TableNextColumn();
ImGui::Text("Spr Palette");
ImGui::SameLine();
ImGui::SetNextItemWidth(kInputFieldSize);
ImGui::InputText("##sprPal", spr_palette_, kByteSize);
ImGui::TableNextColumn();
ImGui::Text("Msg ID");
ImGui::SameLine();
ImGui::SetNextItemWidth(50.f);
ImGui::InputText("##msgid", spr_palette_, kMessageIdSize);
ImGui::TableNextColumn();
ImGui::Checkbox("Show grid", &opt_enable_grid);
ImGui::EndTable();
}
}
void OverworldEditor::DrawOverworldCanvas() {
DrawOverworldMapSettings();
ImGui::Separator();
static ImVector<ImVec2> points;
static ImVec2 scrolling(0.0f, 0.0f);
static bool opt_enable_context_menu = true;
static bool adding_line = false;
ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
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(
"canvas", 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);
// Add first and second point
if (is_hovered && !adding_line &&
ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
points.push_back(mouse_pos_in_canvas);
points.push_back(mouse_pos_in_canvas);
adding_line = true;
}
if (adding_line) {
points.back() = mouse_pos_in_canvas;
if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) adding_line = false;
}
// Pan (we use a zero mouse threshold when there's no context menu)
const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f;
if (is_active &&
ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
scrolling.x += io.MouseDelta.x;
scrolling.y += io.MouseDelta.y;
}
// Context menu (under default mouse threshold)
ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
if (opt_enable_context_menu && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
if (ImGui::BeginPopup("context")) {
if (adding_line) points.resize(points.size() - 2);
adding_line = false;
if (ImGui::MenuItem("Remove one", NULL, false, points.Size > 0)) {
points.resize(points.size() - 2);
}
if (ImGui::MenuItem("Remove all", NULL, false, points.Size > 0)) {
points.clear();
}
ImGui::EndPopup();
}
// 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;
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));
}
for (int n = 0; n < points.Size; n += 2)
draw_list->AddLine(
ImVec2(origin.x + points[n].x, origin.y + points[n].y),
ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y),
IM_COL32(255, 255, 0, 255), 2.0f);
draw_list->PopClipRect();
}
void OverworldEditor::DrawTileSelector() {
if (ImGui::BeginTabBar("##TabBar", ImGuiTabBarFlags_FittingPolicyScroll)) {
if (ImGui::BeginTabItem("Tile8")) {
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Tile16")) {
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}
void OverworldEditor::DrawChangelist() {
if (!ImGui::Begin("Changelist")) {
ImGui::End();
}
ImGui::Text("Test");
ImGui::End();
}
} // namespace Editor
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,76 @@
#ifndef YAZE_APPLICATION_EDITOR_OVERWORLDEDITOR_H
#define YAZE_APPLICATION_EDITOR_OVERWORLDEDITOR_H
#include <imgui/imgui.h>
#include "Data/OW/overworld.h"
#include "Graphics/icons.h"
#include "Graphics/palette.h"
#include "Graphics/scene.h"
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Editor {
static constexpr unsigned int k4BPP = 4;
class OverworldEditor {
public:
void Update();
void SetRom(Data::ROM &rom) { rom_ = rom; }
private:
void DrawToolset();
void DrawOverworldMapSettings();
void DrawOverworldCanvas();
void DrawTileSelector();
void DrawChangelist();
bool show_changelist_ = false;
Data::ROM rom_;
Data::Overworld overworld;
Graphics::Scene current_scene_;
Graphics::Bitmap allgfxBitmap;
Graphics::SNESPalette palette_;
Graphics::TilePreset current_set_;
SDL_Texture *gfx_texture = nullptr;
int allgfx_width = 0;
int allgfx_height = 0;
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] = "";
char map_palette_[3] = "";
char spr_gfx_[3] = "";
char spr_palette_[3] = "";
char message_id_[5] = "";
int current_world_ = 0;
bool isLoaded = false;
bool doneLoaded = false;
constexpr static int kByteSize = 3;
constexpr static int kMessageIdSize = 5;
constexpr static float kInputFieldSize = 30.f;
bool opt_enable_grid = true;
};
} // namespace Editor
} // namespace application
} // namespace yaze
#endif

View File

@@ -0,0 +1,10 @@
#include "tile_editor.h"
namespace yaze {
namespace application {
namespace Editor {
void TileEditor::UpdateScreen() {}
} // namespace Editor
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,15 @@
#ifndef YAZE_APPLICATION_EDITOR_TILEEDITOR_H
#define YAZE_APPLICATION_EDITOR_TILEEDITOR_H
namespace yaze {
namespace application {
namespace Editor {
class TileEditor {
public:
void UpdateScreen();
};
} // namespace Editor
} // namespace application
} // namespace yaze
#endif

View File

@@ -0,0 +1,178 @@
#include "bitmap.h"
#include <rommapping.h>
#include "Data/rom.h"
namespace yaze {
namespace application {
namespace Graphics {
int GetPCGfxAddress(char *romData, char id) {
char **info1 = new char *[255];
int gfxPointer1 =
lorom_snes_to_pc((romData[Core::Constants::gfx_1_pointer + 1] << 8) +
(romData[Core::Constants::gfx_1_pointer]),
info1);
int gfxPointer2 =
lorom_snes_to_pc((romData[Core::Constants::gfx_2_pointer + 1] << 8) +
(romData[Core::Constants::gfx_2_pointer]),
info1);
int gfxPointer3 =
lorom_snes_to_pc((romData[Core::Constants::gfx_3_pointer + 1] << 8) +
(romData[Core::Constants::gfx_3_pointer]),
info1);
char gfxGamePointer1 = romData[gfxPointer1 + id];
char gfxGamePointer2 = romData[gfxPointer2 + id];
char gfxGamePointer3 = romData[gfxPointer3 + id];
return lorom_snes_to_pc(
Data::AddressFromBytes(gfxGamePointer1, gfxGamePointer2, gfxGamePointer3),
info1);
}
char *CreateAllGfxDataRaw(char *romData) {
// 0-112 -> compressed 3bpp bgr -> (decompressed each) 0x600 chars
// 113-114 -> compressed 2bpp -> (decompressed each) 0x800 chars
// 115-126 -> uncompressed 3bpp sprites -> (each) 0x600 chars
// 127-217 -> compressed 3bpp sprites -> (decompressed each) 0x600 chars
// 218-222 -> compressed 2bpp -> (decompressed each) 0x800 chars
char *buffer = new char[346624];
int bufferPos = 0;
char *data = new char[2048];
unsigned int uncompressedSize = 0;
unsigned int compressedSize = 0;
for (int i = 0; i < Core::Constants::NumberOfSheets; i++) {
isbpp3[i] = ((i >= 0 && i <= 112) || // Compressed 3bpp bg
(i >= 115 && i <= 126) || // Uncompressed 3bpp sprites
(i >= 127 && i <= 217) // Compressed 3bpp sprites
);
// uncompressed sheets
if (i >= 115 && i <= 126) {
data = new char[Core::Constants::Uncompressed3BPPSize];
int startAddress = GetPCGfxAddress(romData, (char)i);
for (int j = 0; j < Core::Constants::Uncompressed3BPPSize; j++) {
data[j] = romData[j + startAddress];
}
} else {
data = alttp_decompress_gfx((char *)romData,
GetPCGfxAddress(romData, (char)i),
Core::Constants::UncompressedSheetSize,
&uncompressedSize, &compressedSize);
}
for (int j = 0; j < sizeof(data); j++) {
buffer[j + bufferPos] = data[j];
}
bufferPos += sizeof(data);
}
return buffer;
}
void CreateAllGfxData(char *romData, char *allgfx16Ptr) {
char *data = CreateAllGfxDataRaw(romData);
char *newData = new char[0x6F800];
uchar *mask = new uchar[]{0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
int sheetPosition = 0;
// 8x8 tile
for (int s = 0; s < Core::Constants::NumberOfSheets; s++) // Per Sheet
{
for (int j = 0; j < 4; j++) // Per Tile Line Y
{
for (int i = 0; i < 16; i++) // Per Tile Line X
{
for (int y = 0; y < 8; y++) // Per Pixel Line
{
if (isbpp3[s]) {
char lineBits0 =
data[(y * 2) + (i * 24) + (j * 384) + sheetPosition];
char lineBits1 =
data[(y * 2) + (i * 24) + (j * 384) + 1 + sheetPosition];
char lineBits2 =
data[(y) + (i * 24) + (j * 384) + 16 + sheetPosition];
for (int x = 0; x < 4; x++) // Per Pixel X
{
char pixdata = 0;
char pixdata2 = 0;
if ((lineBits0 & mask[(x * 2)]) == mask[(x * 2)]) {
pixdata += 1;
}
if ((lineBits1 & mask[(x * 2)]) == mask[(x * 2)]) {
pixdata += 2;
}
if ((lineBits2 & mask[(x * 2)]) == mask[(x * 2)]) {
pixdata += 4;
}
if ((lineBits0 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) {
pixdata2 += 1;
}
if ((lineBits1 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) {
pixdata2 += 2;
}
if ((lineBits2 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) {
pixdata2 += 4;
}
newData[(y * 64) + (x) + (i * 4) + (j * 512) + (s * 2048)] =
(char)((pixdata << 4) | pixdata2);
}
} else {
char lineBits0 =
data[(y * 2) + (i * 16) + (j * 256) + sheetPosition];
char lineBits1 =
data[(y * 2) + (i * 16) + (j * 256) + 1 + sheetPosition];
for (int x = 0; x < 4; x++) // Per Pixel X
{
char pixdata = 0;
char pixdata2 = 0;
if ((lineBits0 & mask[(x * 2)]) == mask[(x * 2)]) {
pixdata += 1;
}
if ((lineBits1 & mask[(x * 2)]) == mask[(x * 2)]) {
pixdata += 2;
}
if ((lineBits0 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) {
pixdata2 += 1;
}
if ((lineBits1 & mask[(x * 2) + 1]) == mask[(x * 2) + 1]) {
pixdata2 += 2;
}
newData[(y * 64) + (x) + (i * 4) + (j * 512) + (s * 2048)] =
(char)((pixdata << 4) | pixdata2);
}
}
}
}
}
if (isbpp3[s]) {
sheetPosition += Core::Constants::Uncompressed3BPPSize;
} else {
sheetPosition += Core::Constants::UncompressedSheetSize;
}
}
char *allgfx16Data = (char *)allgfx16Ptr;
for (int i = 0; i < 0x6F800; i++) {
allgfx16Data[i] = newData[i];
}
}
} // namespace Graphics
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,37 @@
#ifndef YAZE_APPLICATION_UTILS_BITMAP_H
#define YAZE_APPLICATION_UTILS_BITMAP_H
#include <SDL2/SDL.h>
#include "Core/constants.h"
namespace yaze {
namespace application {
namespace Graphics {
class Bitmap {
public:
Bitmap() = default;
Bitmap(int width, int height, char *data)
: width_(width), height_(height), pixel_data_(data) {}
int GetWidth() const { return width_; }
int GetHeight() const { return height_; }
private:
int width_;
int height_;
char *pixel_data_;
};
static bool isbpp3[Core::Constants::NumberOfSheets];
int GetPCGfxAddress(char *romData, char id);
char *CreateAllGfxDataRaw(char *romData);
void CreateAllGfxData(char *romData, char *allgfx16Ptr);
} // namespace Graphics
} // namespace application
} // namespace yaze
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
#include "palette.h"
#include <cstdlib>
#include <cstring>
namespace yaze {
namespace application {
namespace Graphics {
SNESColor::SNESColor() : rgb(ImVec4(0.f, 0.f, 0.f, 0.f)) {}
SNESColor::SNESColor(ImVec4 val) : rgb(val) {
m_color col;
col.red = (uchar)val.x;
col.blue = (uchar)val.y;
col.green = (uchar)val.z;
snes = convertcolor_rgb_to_snes(col);
}
void SNESColor::setRgb(ImVec4 val) {
rgb = val;
m_color col;
col.red = val.x;
col.blue = val.y;
col.green = val.z;
snes = convertcolor_rgb_to_snes(col);
}
void SNESColor::setSNES(uint16_t val) {
snes = val;
m_color col = convertcolor_snes_to_rgb(val);
rgb = ImVec4(col.red, col.green, col.blue, 1.f);
}
SNESPalette::SNESPalette(uint8_t mSize) : size_(mSize) {
for (unsigned int i = 0; i < mSize; i++) {
SNESColor col;
colors.push_back(col);
}
}
SNESPalette::SNESPalette(char* data) {
assert((sizeof(data) % 4 == 0) && (sizeof(data) <= 32));
size_ = sizeof(data) / 2;
for (unsigned i = 0; i < sizeof(data); i += 2) {
SNESColor col;
col.snes = static_cast<uchar>(data[i + 1]) << 8;
col.snes = col.snes | static_cast<uchar>(data[i]);
m_color mColor = convertcolor_snes_to_rgb(col.snes);
col.rgb = ImVec4(mColor.red, mColor.green, mColor.blue, 1.f);
colors.push_back(col);
}
}
SNESPalette::SNESPalette(const unsigned char* snes_pal) {
assert((sizeof(snes_pal) % 4 == 0) && (sizeof(snes_pal) <= 32));
size_ = sizeof(snes_pal) / 2;
for (unsigned i = 0; i < sizeof(snes_pal); i += 2) {
SNESColor col;
col.snes = snes_pal[i + 1] << (uint16_t) 8;
col.snes = col.snes | snes_pal[i];
m_color mColor = convertcolor_snes_to_rgb(col.snes);
col.rgb = ImVec4(mColor.red, mColor.green, mColor.blue, 1.f);
colors.push_back(col);
}
}
SNESPalette::SNESPalette(std::vector<ImVec4> cols) {
for (const auto& each : cols) {
SNESColor scol;
scol.setRgb(each);
colors.push_back(scol);
}
size_ = cols.size();
}
char* SNESPalette::encode() {
// char* data(size * 2, 0);
char* data = new char[size_ * 2];
for (unsigned int i = 0; i < size_; i++) {
// std::cout << QString::number(colors[i].snes, 16);
data[i * 2] = (char)(colors[i].snes & 0xFF);
data[i * 2 + 1] = (char)(colors[i].snes >> 8);
}
return data;
}
SDL_Palette* SNESPalette::GetSDL_Palette() {
std::cout << "Converting SNESPalette to SDL_Palette" << std::endl;
auto sdl_palette = std::make_shared<SDL_Palette>();
sdl_palette->ncolors = size_;
auto* sdl_colors = new SDL_Color[size_];
for (int i = 0; i < size_; i++) {
sdl_colors[i].r = (uint8_t)colors[i].rgb.x * 100;
sdl_colors[i].g = (uint8_t)colors[i].rgb.y * 100;
sdl_colors[i].b = (uint8_t)colors[i].rgb.z * 100;
std::cout << "Color " << i << " added (R:" << sdl_colors[i].r
<< " G:" << sdl_colors[i].g << " B:" << sdl_colors[i].b << ")"
<< std::endl;
}
sdl_palette->colors = sdl_colors;
// store the pointers to free them later
sdl_palettes_.push_back(sdl_palette);
colors_arrays_.push_back(sdl_colors);
return sdl_palette.get();
}
} // namespace Graphics
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,50 @@
#ifndef YAZE_APPLICATION_GRAPHICS_PALETTE_H
#define YAZE_APPLICATION_GRAPHICS_PALETTE_H
#include <SDL2/SDL.h>
#include <imgui/imgui.h>
#include <palette.h>
#include <tile.h>
#include <cstdint>
#include <iostream>
#include <memory>
#include <vector>
namespace yaze {
namespace application {
namespace Graphics {
struct SNESColor {
SNESColor();
explicit SNESColor(ImVec4);
uint16_t snes = 0;
ImVec4 rgb;
void setRgb(ImVec4);
void setSNES(uint16_t);
uint8_t approxSNES();
ImVec4 approxRGB();
};
class SNESPalette {
public:
SNESPalette() = default;
explicit SNESPalette(uint8_t mSize);
explicit SNESPalette(char* snesPal);
explicit SNESPalette(const unsigned char* snes_pal);
explicit SNESPalette(std::vector<ImVec4>);
char* encode();
SDL_Palette* GetSDL_Palette();
int size_ = 0;
std::vector<SNESColor> colors;
std::vector<std::shared_ptr<SDL_Palette>> sdl_palettes_;
std::vector<SDL_Color*> colors_arrays_;
};
} // namespace Graphics
} // namespace application
} // namespace yaze
#endif // YAZE_APPLICATION_GRAPHICS_PALETTE_H

View File

@@ -0,0 +1,78 @@
#include "scene.h"
#include <SDL2/SDL.h>
#include <tile.h>
#include <iostream>
#include <vector>
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Graphics {
void Scene::buildSurface(const std::vector<tile8>& tiles, SNESPalette& mPalette,
const TilesPattern& tp) {
arrangedTiles = TilesPattern::transform(tp, tiles);
tilesPattern = tp;
allTiles = tiles;
for (unsigned int j = 0; j < arrangedTiles.size(); j++) {
for (unsigned int i = 0; i < arrangedTiles[0].size(); i++) {
tile8 tile = arrangedTiles[j][i];
// SDL_PIXELFORMAT_RGB888 ?
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(
0, 8, 8, SDL_BITSPERPIXEL(3), SDL_PIXELFORMAT_RGB444);
if (surface == nullptr) {
SDL_Log("SDL_CreateRGBSurfaceWithFormat() failed: %s", SDL_GetError());
exit(1);
}
SDL_PixelFormat* format = surface->format;
format->palette = mPalette.GetSDL_Palette();
char* ptr = (char*)surface->pixels;
for (int k = 0; k < 8; k++) {
for (int l = 0; l < 8; l++) {
ptr[k * 8 + l] = tile.data[k * 8 + l];
}
}
// SDL_Texture* texture =
// SDL_CreateTextureFromSurface(Core::renderer, surface);
// if (texture == nullptr) {
// std::cout << "Error: " << SDL_GetError() << std::endl;
// }
// imagesCache[tile.id] = texture;
}
}
}
void Scene::updateScene() {
std::cout << "Update scene";
unsigned int itemCpt = 0;
for (unsigned int j = 0; j < arrangedTiles.size(); j++) {
for (unsigned int i = 0; i < arrangedTiles[0].size(); i++) {
tile8 tile = arrangedTiles[j][i];
// QPixmap m = imagesCache[tile.id];
// GraphicsTileItem *tileItem = (GraphicsTileItem *)items()[itemCpt];
// tileItem->image = m;
// tileItem->rawTile = tile;
// tileItem->setTileZoom(tilesZoom);
// tileItem->setPos(i * tileItem->boundingRect().width() + i,
// j * tileItem->boundingRect().width() + j);
itemCpt++;
}
}
}
void Scene::setTilesZoom(unsigned int tileZoom) {
tilesZoom = tileZoom;
// if (!items().isEmpty()) updateScene();
}
void Scene::setTilesPattern(TilesPattern tp) { tilesPattern = tp; }
} // namespace Graphics
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,39 @@
#ifndef YAZE_APPLICATION_GRAPHICS_SCENE_H
#define YAZE_APPLICATION_GRAPHICS_SCENE_H
#include <SDL2/SDL.h>
#include <tile.h>
#include <iostream>
#include <vector>
#include "Graphics/tile.h"
namespace yaze {
namespace application {
namespace Graphics {
class Scene {
public:
Scene() = default;
void buildSurface(const std::vector<tile8>& tiles, SNESPalette& mPalette,
const TilesPattern& tp);
void updateScene();
void setTilesZoom(unsigned int tileZoom);
void setTilesPattern(TilesPattern tp);
std::unordered_map<unsigned int, SDL_Texture*> imagesCache;
private:
unsigned int tilesZoom;
TilesPattern tilesPattern;
std::vector<tile8> allTiles;
std::vector<std::vector<tile8>> arrangedTiles;
};
} // namespace Graphics
} // namespace application
} // namespace yaze
#endif

View File

@@ -0,0 +1,113 @@
#include "style.h"
#include "imgui/imgui.h"
#include "imgui/imgui_internal.h"
namespace yaze {
namespace application {
namespace Core {
namespace Style {
void ColorsYaze() {
ImGuiStyle *style = &ImGui::GetStyle();
ImVec4 *colors = style->Colors;
style->WindowPadding = ImVec2(10.f, 10.f);
style->FramePadding = ImVec2(10.f, 3.f);
style->CellPadding = ImVec2(4.f, 5.f);
style->ItemSpacing = ImVec2(10.f, 5.f);
style->ItemInnerSpacing = ImVec2(5.f, 5.f);
style->TouchExtraPadding = ImVec2(0.f, 0.f);
style->IndentSpacing = 20.f;
style->ScrollbarSize = 14.f;
style->GrabMinSize = 15.f;
style->WindowBorderSize = 0.f;
style->ChildBorderSize = 1.f;
style->PopupBorderSize = 1.f;
style->FrameBorderSize = 0.f;
style->TabBorderSize = 0.f;
style->WindowRounding = 0.f;
style->ChildRounding = 0.f;
style->FrameRounding = 5.f;
style->PopupRounding = 0.f;
style->ScrollbarRounding = 5.f;
auto alttpDarkGreen = ImVec4(0.18f, 0.26f, 0.18f, 1.0f);
auto alttpMidGreen = ImVec4(0.28f, 0.36f, 0.28f, 1.0f);
auto allttpLightGreen = ImVec4(0.36f, 0.45f, 0.36f, 1.0f);
auto allttpLightestGreen = ImVec4(0.49f, 0.57f, 0.49f, 1.0f);
colors[ImGuiCol_MenuBarBg] = alttpDarkGreen;
colors[ImGuiCol_TitleBg] = alttpMidGreen;
colors[ImGuiCol_Header] = alttpDarkGreen;
colors[ImGuiCol_HeaderHovered] = allttpLightGreen;
colors[ImGuiCol_HeaderActive] = alttpMidGreen;
colors[ImGuiCol_TitleBgActive] = alttpDarkGreen;
colors[ImGuiCol_TitleBgCollapsed] = alttpMidGreen;
colors[ImGuiCol_Tab] = alttpDarkGreen;
colors[ImGuiCol_TabHovered] = alttpMidGreen;
colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive],
colors[ImGuiCol_TitleBgActive], 0.60f);
colors[ImGuiCol_Button] = alttpMidGreen;
colors[ImGuiCol_ButtonHovered] = allttpLightestGreen;
colors[ImGuiCol_ButtonActive] = allttpLightGreen;
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.36f, 0.45f, 0.36f, 0.30f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.36f, 0.45f, 0.36f, 0.40f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.85f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
colors[ImGuiCol_Border] = allttpLightGreen;
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.28f, 0.36f, 0.28f, 0.40f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.28f, 0.36f, 0.28f, 0.69f);
colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
colors[ImGuiCol_TabUnfocused] =
ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
colors[ImGuiCol_TabUnfocusedActive] =
ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = alttpDarkGreen;
colors[ImGuiCol_TableBorderStrong] = alttpMidGreen;
colors[ImGuiCol_TableBorderLight] =
ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
}
} // namespace Style
} // namespace Core
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,19 @@
#ifndef YAZE_APPLICATION_CORE_STYLE_H
#define YAZE_APPLICATION_CORE_STYLE_H
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
namespace yaze {
namespace application {
namespace Core {
namespace Style {
void ColorsYaze();
} // namespace Style
} // namespace Core
} // namespace application
} // namespace yaze
#endif

View File

@@ -0,0 +1,152 @@
#include "tile.h"
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <regex>
namespace yaze {
namespace application {
namespace Graphics {
TilesPattern::TilesPattern() {
tiles_per_row_ = 16;
number_of_tiles_ = 16;
// std::vector<int>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 11, 12, 13, 14, 15,
// 16});
transform_vector_.push_back(std::vector<int>{0, 1, 2, 3});
transform_vector_.push_back(std::vector<int>{4, 5, 6, 7});
transform_vector_.push_back(std::vector<int>{8, 9, 11, 12});
transform_vector_.push_back(std::vector<int>{13, 14, 15, 16});
// "[0, 1, 4, 5], [2, 3, 6, 7], [8, 9, C, D], [A, B, E, F]"
}
// [pattern]
// name = "32x32 B (4x4)"
// number_of_tile = 16
// pattern =
void TilesPattern::default_settings() {
number_of_tiles_ = 16;
std::string patternString =
"[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, A, B], [C, D, E, F]";
transform_vector_.clear();
std::smatch cm;
std::regex arrayRegExp("(\\[[\\s|0-F|a-f|,]+\\])");
int pos = 0;
while (std::regex_search(patternString, cm, arrayRegExp)) {
std::string arrayString = cm[1];
std::vector<int> tmpVect;
uint stringPos = 1;
while (arrayString[stringPos] != ']') {
while (arrayString[stringPos] == ' ') stringPos++;
std::smatch cm_;
std::regex hex("([0-F|a-f]+)");
bool ok;
std::regex_search(arrayString, cm, hex);
if (cm[1] == stringPos) {
std::cout << "here" << std::endl;
// tmpVect.push_back(stoi(cm[1]));
}
while (arrayString[stringPos] == ' ') stringPos++;
stringPos++; // should be the comma
}
pos += cm.size();
transform_vector_.push_back(tmpVect);
}
std::cout << transform_vector_.size() << std::endl;
}
std::vector<std::vector<tile8> > TilesPattern::transform(
const std::vector<tile8> &tiles) const {
uint repeatOffsetY = 0;
uint repeatOffsetX = 0;
uint tVectHeight = transform_vector_.size();
uint tVectWidth = transform_vector_[0].size();
uint repeat = 0;
std::vector<std::vector<tile8> > toret;
uint transPerRow = tiles_per_row_ / tVectWidth;
uint nbTransform = tiles.size() / number_of_tiles_;
printf("Tiles size : %d\nnbtransform : %d\npattern number of tiles : %d\n",
tiles.size(), nbTransform, number_of_tiles_);
if (transPerRow > nbTransform)
toret.resize(tVectHeight);
else
toret.resize(((uint)(((double)nbTransform / (double)transPerRow) + 0.5)) *
tVectHeight);
for (auto &each : toret) {
each.resize(tiles_per_row_);
}
std::cout << toret[0].size() << " x " << toret.size();
while (repeat != nbTransform) {
std::cout << "repeat" << repeat;
for (uint j = 0; j < tVectHeight; j++) {
for (uint i = 0; i < tVectWidth; i++) {
uint posTile = transform_vector_[j][i] + number_of_tiles_ * repeat;
uint posX = i + repeatOffsetX;
uint posY = j + repeatOffsetY;
printf("X: %d - Y: %d - posTile : %d \n", posX, posY, posTile);
toret.at(posY).at(posX) = tiles[posTile];
}
}
if (repeatOffsetX + tVectWidth == tiles_per_row_) {
repeatOffsetX = 0;
repeatOffsetY += tVectHeight;
} else
repeatOffsetX += tVectWidth;
repeat++;
}
std::cout << "End of transform" << std::endl;
return toret;
}
std::vector<tile8> TilesPattern::reverse(
const std::vector<tile8> &tiles) const {
uint repeatOffsetY = 0;
uint repeatOffsetX = 0;
uint tVectHeight = transform_vector_.size();
uint tVectWidth = transform_vector_[0].size();
uint repeat = 0;
uint nbTransPerRow = tiles_per_row_ / tVectWidth;
uint nbTiles = tiles.size();
std::vector<tile8> toretVec(tiles.size());
for (uint i = 0; i < nbTiles; i++) {
uint lineNb = i / tiles_per_row_;
uint lineInTab = lineNb % tVectHeight;
uint colInTab = i % tVectWidth;
uint tileNb = transform_vector_[lineInTab][colInTab];
uint lineBlock = i / (nbTransPerRow * number_of_tiles_);
uint blockNB =
(i % (nbTransPerRow * number_of_tiles_) % tiles_per_row_) / tVectWidth;
std::cout << colInTab << lineInTab << " = " << tileNb;
uint pos = tileNb + (lineBlock + blockNB) * number_of_tiles_;
std::cout << i << "Goes to : " << pos;
toretVec[pos] = tiles[i];
}
return toretVec;
}
std::vector<std::vector<tile8> > TilesPattern::transform(
const TilesPattern &pattern, const std::vector<tile8> &tiles) {
return pattern.transform(tiles);
}
} // namespace Graphics
} // namespace application
} // namespace yaze

View File

@@ -0,0 +1,106 @@
#ifndef YAZE_APPLICATION_DATA_TILE_H
#define YAZE_APPLICATION_DATA_TILE_H
#include <tile.h>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <vector>
#include "Core/constants.h"
#include "Graphics/palette.h"
namespace yaze {
namespace application {
namespace Graphics {
// vhopppcc cccccccc
// [0, 1]
// [2, 3]
class TileInfo {
public:
ushort id_;
ushort over_;
ushort vertical_mirror_;
ushort horizontal_mirror_;
uchar palette_;
TileInfo() = default;
TileInfo(ushort id, uchar palette, ushort v, ushort h, ushort o)
: id_(id),
over_(o),
vertical_mirror_(v),
horizontal_mirror_(h),
palette_(palette) {}
};
class Tile32 {
public:
ushort tile0_;
ushort tile1_;
ushort tile2_;
ushort tile3_;
Tile32(ushort t0, ushort t1, ushort t2, ushort t3)
: tile0_(t0), tile1_(t1), tile2_(t2), tile3_(t3) {}
};
class Tile16 {
public:
TileInfo tile0_;
TileInfo tile1_;
TileInfo tile2_;
TileInfo tile3_;
std::vector<TileInfo> tiles_info;
Tile16(TileInfo t0, TileInfo t1, TileInfo t2, TileInfo t3)
: tile0_(t0), tile1_(t1), tile2_(t2), tile3_(t3) {
tiles_info.push_back(tile0_);
tiles_info.push_back(tile1_);
tiles_info.push_back(tile2_);
tiles_info.push_back(tile3_);
}
};
class TilesPattern {
public:
TilesPattern();
std::string name;
std::string description;
bool custom;
unsigned int tiles_per_row_;
unsigned int number_of_tiles_;
void default_settings();
static TilesPattern pattern(std::string name);
static std::vector<std::vector<tile8>> transform(
const TilesPattern& pattern, const std::vector<tile8>& tiles);
protected:
std::vector<std::vector<tile8>> transform(
const std::vector<tile8>& tiles) const;
std::vector<tile8> reverse(const std::vector<tile8>& tiles) const;
private:
std::vector<std::vector<int>> transform_vector_;
};
class TilePreset {
public:
TilePreset() = default;
TilesPattern tilesPattern;
bool no_zero_color_ = false;
int pc_tiles_location_ = 0;
int pc_palette_location_ = 0;
int bits_per_pixel_ = 0;
int length_ = 0;
int SNESTilesLocation = 0;
int SNESPaletteLocation = 0;
};
} // namespace Graphics
} // namespace application
} // namespace yaze
#endif

View File

@@ -1,7 +1,7 @@
#ifndef YAZE_YAZE_H
#define YAZE_YAZE_H
#include "Application/Core/controller.h"
#include "Application/Core/entry_point.h"
#include "application/Core/controller.h"
#include "application/Core/entry_point.h"
#endif // YAZE_YAZE_H

View File

@@ -17,10 +17,10 @@ add_executable(
yaze_test
yaze_test.cc
rom_test.cc
../src/Application/Data/rom.cc
../src/Application/Graphics/tile.cc
../src/Application/Graphics/tile.cc
../src/Application/Graphics/palette.cc
../src/application/Data/rom.cc
../src/application/Graphics/tile.cc
../src/application/Graphics/tile.cc
../src/application/Graphics/palette.cc
${SNESHACKING_PATH}/compressions/alttpcompression.c
${SNESHACKING_PATH}/compressions/stdnintendo.c
${SNESHACKING_PATH}/tile.c
@@ -33,7 +33,7 @@ add_executable(
target_include_directories(
yaze_test PUBLIC
../src/Library/
../src/Application/
../src/application/
${SNESHACKING_PATH}
)

View File

@@ -35,8 +35,8 @@ class DecompressionTest : public ::testing::Test {
void TearDown() override {}
unsigned int c_size_;
yaze::Application::Data::ROM rom_;
yaze::Application::Graphics::TilePreset tile_preset_;
yaze::application::Data::ROM rom_;
yaze::application::Graphics::TilePreset tile_preset_;
};
TEST_F(DecompressionTest, test_valid_command_decompress) {
@@ -93,7 +93,7 @@ TEST_F(DecompressionTest, test_compress_decompress) {
TEST_F(DecompressionTest, basic_test) {
rom_.LoadFromFile("assets/alttp.sfc");
tile_preset_.bpp_ = 4;
tile_preset_.bits_per_pixel_ = 4;
tile_preset_.length_ = 28672;
tile_preset_.pc_tiles_location_ = 0x80000;
tile_preset_.SNESTilesLocation = 0x0000;

View File

@@ -3,7 +3,7 @@
namespace YazeTests {
TEST(YazeApplicationTests, TemplateTest) {
TEST(YazeapplicationTests, TemplateTest) {
int i = 0;
ASSERT_EQ(i, 0);
}