Getting very close to loading graphics on the screen... no time to explain
This commit is contained in:
@@ -15,14 +15,13 @@ namespace yaze {
|
||||
namespace Application {
|
||||
namespace Core {
|
||||
|
||||
static SDL_Renderer* renderer = nullptr;
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
void Create(SDL_Window* window);
|
||||
void Render();
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
SDL_Renderer* renderer = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -1,19 +1,31 @@
|
||||
#include "OverworldEditor.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "Core/Icons.h"
|
||||
#include "Graphics/Bitmap.h"
|
||||
#include "Graphics/Tile.h"
|
||||
#include "imgui.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
namespace Editor {
|
||||
void OverworldEditor::Update() {
|
||||
|
||||
if (rom_.isLoaded()) {
|
||||
if (!doneLoaded) {
|
||||
overworld.Load(rom_);
|
||||
Graphics::CreateAllGfxData(rom_.GetRawData(), allGfx16Ptr);
|
||||
SDL_Surface *surface =
|
||||
SDL_CreateRGBSurfaceFrom(allGfx16Ptr, 128, 7104, 4, 64,
|
||||
0x0000FF, // red mask
|
||||
0x00FF00, // green mask
|
||||
0xFF0000, // blue mask
|
||||
1);
|
||||
|
||||
surface = current_scene_.buildSurface(
|
||||
rom_.ExtractTiles(4, 2048), palette_, current_set_.tilesPattern);
|
||||
gfx_texture = SDL_CreateTextureFromSurface(Core::renderer, surface);
|
||||
doneLoaded = true;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +49,6 @@ void OverworldEditor::Update() {
|
||||
|
||||
void OverworldEditor::DrawToolset() {
|
||||
if (ImGui::BeginTable("Toolset", 14, toolset_table_flags, ImVec2(0, 0))) {
|
||||
|
||||
ImGui::TableSetupColumn("#undoTool");
|
||||
ImGui::TableSetupColumn("#redoTool");
|
||||
ImGui::TableSetupColumn("#drawTool");
|
||||
@@ -107,7 +118,6 @@ void OverworldEditor::DrawToolset() {
|
||||
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");
|
||||
@@ -176,13 +186,13 @@ void OverworldEditor::DrawOverworldCanvas() {
|
||||
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
|
||||
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
|
||||
canvas_p0.y + scrolling.y); // Lock scrolled origin
|
||||
const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x,
|
||||
io.MousePos.y - origin.y);
|
||||
|
||||
@@ -195,8 +205,7 @@ void OverworldEditor::DrawOverworldCanvas() {
|
||||
}
|
||||
if (adding_line) {
|
||||
points.back() = mouse_pos_in_canvas;
|
||||
if (!ImGui::IsMouseDown(ImGuiMouseButton_Left))
|
||||
adding_line = false;
|
||||
if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) adding_line = false;
|
||||
}
|
||||
|
||||
// Pan (we use a zero mouse threshold when there's no context menu)
|
||||
@@ -212,8 +221,7 @@ void OverworldEditor::DrawOverworldCanvas() {
|
||||
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);
|
||||
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);
|
||||
@@ -252,15 +260,12 @@ void OverworldEditor::DrawTileSelector() {
|
||||
if (ImGui::BeginTabBar("##TabBar")) {
|
||||
if (ImGui::BeginTabItem("Tile8")) {
|
||||
if (rom_.isLoaded()) {
|
||||
ImGui::Image((void *)(intptr_t)overworld_texture,
|
||||
ImVec2(overworld.overworldMapBitmap->GetWidth(),
|
||||
overworld.overworldMapBitmap->GetHeight()));
|
||||
ImGui::Image((void *)(intptr_t)gfx_texture, ImVec2(128, 7104));
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Tile16")) {
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
@@ -270,7 +275,6 @@ void OverworldEditor::DrawTileSelector() {
|
||||
|
||||
void OverworldEditor::DrawChangelist() {
|
||||
if (!ImGui::Begin("Changelist")) {
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -278,6 +282,6 @@ void OverworldEditor::DrawChangelist() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace Editor
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
} // namespace Editor
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
@@ -1,11 +1,14 @@
|
||||
#ifndef YAZE_APPLICATION_EDITOR_OVERWORLDEDITOR_H
|
||||
#define YAZE_APPLICATION_EDITOR_OVERWORLDEDITOR_H
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
#include "Core/Icons.h"
|
||||
#include "Data/Overworld.h"
|
||||
#include "Graphics/Palette.h"
|
||||
#include "Graphics/Scene.h"
|
||||
#include "Graphics/Tile.h"
|
||||
#include "Utils/Compression.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui/misc/cpp/imgui_stdlib.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
@@ -14,12 +17,12 @@ namespace Editor {
|
||||
using byte = unsigned char;
|
||||
|
||||
class OverworldEditor {
|
||||
public:
|
||||
public:
|
||||
void Update();
|
||||
|
||||
void SetRom(Utils::ROM & rom) { rom_ = rom; }
|
||||
void SetRom(Utils::ROM &rom) { rom_ = rom; }
|
||||
|
||||
private:
|
||||
private:
|
||||
void DrawToolset();
|
||||
void DrawOverworldMapSettings();
|
||||
void DrawOverworldCanvas();
|
||||
@@ -31,13 +34,19 @@ private:
|
||||
|
||||
Utils::ROM rom_;
|
||||
Data::Overworld overworld;
|
||||
Graphics::Scene current_scene_;
|
||||
Utils::ALTTPCompression alttp_compressor_;
|
||||
Graphics::Bitmap allgfxBitmap;
|
||||
Graphics::SNESPalette palette_;
|
||||
Graphics::TilePreset current_set_;
|
||||
|
||||
SDL_Texture *gfx_texture = nullptr;
|
||||
|
||||
int allgfx_width = 0;
|
||||
int allgfx_height = 0;
|
||||
GLuint *allgfx_texture = nullptr;
|
||||
|
||||
byte* allGfx16Ptr = new byte[(128 * 7136) / 2];
|
||||
byte *allGfx16Ptr = new byte[(128 * 7136) / 2];
|
||||
|
||||
GLuint *overworld_texture;
|
||||
|
||||
@@ -65,8 +74,8 @@ private:
|
||||
constexpr static float kInputFieldSize = 30.f;
|
||||
bool opt_enable_grid = true;
|
||||
};
|
||||
} // namespace Editor
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
} // namespace Editor
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Bitmap.h"
|
||||
#include "Utils/ROM.h"
|
||||
#include "Utils/Compression.h"
|
||||
#include "rommapping.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
@@ -9,20 +10,20 @@ namespace Graphics {
|
||||
int GetPCGfxAddress(byte *romData, byte id) {
|
||||
char** info1, **info2,** info3, **info4;
|
||||
int gfxPointer1 =
|
||||
Utils::lorom_snes_to_pc((romData[Constants::gfx_1_pointer + 1] << 8) +
|
||||
lorom_snes_to_pc((romData[Constants::gfx_1_pointer + 1] << 8) +
|
||||
(romData[Constants::gfx_1_pointer]), info1);
|
||||
int gfxPointer2 =
|
||||
Utils::lorom_snes_to_pc((romData[Constants::gfx_2_pointer + 1] << 8) +
|
||||
lorom_snes_to_pc((romData[Constants::gfx_2_pointer + 1] << 8) +
|
||||
(romData[Constants::gfx_2_pointer]), info2);
|
||||
int gfxPointer3 =
|
||||
Utils::lorom_snes_to_pc((romData[Constants::gfx_3_pointer + 1] << 8) +
|
||||
lorom_snes_to_pc((romData[Constants::gfx_3_pointer + 1] << 8) +
|
||||
(romData[Constants::gfx_3_pointer]), info3);
|
||||
|
||||
byte gfxGamePointer1 = romData[gfxPointer1 + id];
|
||||
byte gfxGamePointer2 = romData[gfxPointer2 + id];
|
||||
byte gfxGamePointer3 = romData[gfxPointer3 + id];
|
||||
|
||||
return Utils::lorom_snes_to_pc(Utils::AddressFromBytes(gfxGamePointer1, gfxGamePointer2,
|
||||
return lorom_snes_to_pc(Utils::AddressFromBytes(gfxGamePointer1, gfxGamePointer2,
|
||||
gfxGamePointer3), info4);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,67 +7,68 @@ namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
|
||||
r_palette* palette_create(const unsigned int size, const unsigned int id) {
|
||||
r_palette* new_pal = (r_palette*)malloc(sizeof(r_palette));
|
||||
new_pal->colors = (m_color*)malloc(sizeof(m_color) * size);
|
||||
new_pal->id = id;
|
||||
new_pal->size = size;
|
||||
return new_pal;
|
||||
SNESColor::SNESColor() {
|
||||
rgb = ImVec4(0.f, 0.f, 0.f, 0.f);
|
||||
snes = 0;
|
||||
}
|
||||
|
||||
void palette_free(r_palette* tofree) {
|
||||
free(tofree->colors);
|
||||
free(tofree);
|
||||
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);
|
||||
}
|
||||
|
||||
r_palette* palette_extract(const char* data, const unsigned int offset,
|
||||
const unsigned int palette_size) {
|
||||
r_palette* toret = palette_create(palette_size, 0);
|
||||
unsigned colnum = 0;
|
||||
for (int i = 0; i < palette_size * 2; i += 2) {
|
||||
unsigned short snes_color;
|
||||
snes_color = ((uchar)data[offset + i + 1]) << 8;
|
||||
snes_color = snes_color | ((uchar)data[offset + i]);
|
||||
toret->colors[colnum] = convertcolor_snes_to_rgb(snes_color);
|
||||
colnum++;
|
||||
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() { size = 0; }
|
||||
|
||||
SNESPalette::SNESPalette(uint8_t mSize) {
|
||||
size = mSize;
|
||||
for (unsigned int i = 0; i < mSize; i++) {
|
||||
SNESColor col;
|
||||
colors.push_back(col);
|
||||
}
|
||||
return toret;
|
||||
}
|
||||
|
||||
char* palette_convert(const r_palette pal) {
|
||||
char* toret = (char*)malloc(pal.size * 2);
|
||||
for (unsigned int i = 0; i < pal.size; i++) {
|
||||
unsigned short snes_data = convertcolor_rgb_to_snes(pal.colors[i]);
|
||||
toret[i * 2] = snes_data & 0xFF;
|
||||
toret[i * 2 + 1] = snes_data >> 8;
|
||||
SNESPalette::SNESPalette(char* data) {
|
||||
//assert((data.size() % 4 == 0) && data.size() <= 32);
|
||||
//size = data.size() / 2;
|
||||
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);
|
||||
}
|
||||
return toret;
|
||||
}
|
||||
|
||||
m_color convertcolor_snes_to_rgb(const unsigned short snes_color) {
|
||||
m_color toret;
|
||||
|
||||
toret.red = ((snes_color) % 32) * 8;
|
||||
toret.green = ((snes_color / 32) % 32) * 8;
|
||||
toret.blue = ((snes_color / 1024) % 32) * 8;
|
||||
|
||||
toret.red = toret.red + toret.red / 32;
|
||||
toret.green = toret.green + toret.green / 32;
|
||||
toret.blue = toret.blue + toret.blue / 32;
|
||||
return toret;
|
||||
SNESPalette::SNESPalette(std::vector<ImVec4> cols) {
|
||||
// foreach (ImVec4 col, cols) {
|
||||
// SNESColor scol;
|
||||
// scol.setRgb(col);
|
||||
// colors.push_back(scol);
|
||||
// }
|
||||
// size = cols.size();
|
||||
}
|
||||
|
||||
unsigned short convertcolor_rgb_to_snes(const m_color color) {
|
||||
return convertcolor_rgb_to_snes2(color.red, color.green, color.blue);
|
||||
}
|
||||
|
||||
unsigned short convertcolor_rgb_to_snes2(const uchar red, const uchar green,
|
||||
const uchar blue) {
|
||||
uchar R = red / 8;
|
||||
uchar G = green / 8;
|
||||
uchar B = blue / 8;
|
||||
|
||||
return B * 1024 + G * 32 + R;
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace Graphics
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
#ifndef YAZE_APPLICATION_GRAPHICS_PALETTE_H
|
||||
#define YAZE_APPLICATION_GRAPHICS_PALETTE_H
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <palette.h>
|
||||
#include <tile.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
|
||||
extern "C" {
|
||||
struct SNESColor {
|
||||
SNESColor();
|
||||
uint16_t snes;
|
||||
ImVec4 rgb;
|
||||
void setRgb(ImVec4);
|
||||
void setSNES(uint16_t);
|
||||
uint8_t approxSNES();
|
||||
ImVec4 approxRGB();
|
||||
};
|
||||
|
||||
typedef unsigned char uchar;
|
||||
class SNESPalette {
|
||||
public:
|
||||
SNESPalette();
|
||||
SNESPalette(uint8_t mSize);
|
||||
SNESPalette(char* snesPal);
|
||||
SNESPalette(std::vector<ImVec4>);
|
||||
|
||||
typedef struct {
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
} m_color;
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
unsigned int size;
|
||||
m_color* colors;
|
||||
} r_palette;
|
||||
|
||||
r_palette* palette_create(const unsigned int size, const unsigned int id);
|
||||
void palette_free(r_palette* tofree);
|
||||
|
||||
r_palette* palette_extract(const char* data, const unsigned int offset,
|
||||
const unsigned int palette_size);
|
||||
|
||||
char* palette_convert(const r_palette pal);
|
||||
|
||||
m_color convertcolor_snes_to_rgb(const unsigned short snes_color);
|
||||
unsigned short convertcolor_rgb_to_snes(const m_color color);
|
||||
unsigned short convertcolor_rgb_to_snes2(const uchar red, const uchar green,
|
||||
const uchar blue);
|
||||
}
|
||||
char* encode();
|
||||
uint8_t size;
|
||||
std::vector<SNESColor> colors;
|
||||
};
|
||||
|
||||
} // namespace Graphics
|
||||
} // namespace Application
|
||||
|
||||
94
src/Application/Graphics/Scene.cc
Normal file
94
src/Application/Graphics/Scene.cc
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "Scene.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
|
||||
void Scene::buildScene(const std::vector<tile8>& tiles,
|
||||
const 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];
|
||||
// QImage newImage(8, 8, QImage::Format_Indexed8);
|
||||
// newImage.setColorCount(mPalette.size);
|
||||
// for (int i = 0; i < mPalette.size; i++) {
|
||||
// newImage.setColor(i, mPalette.colors.at(i).rgb);
|
||||
// }
|
||||
// for (int i = 0; i < 8; i++) {
|
||||
// for (int j = 0; j < 8; j++)
|
||||
// newImage.setPixel(i, j, tile.data[i + j * 8]);
|
||||
// }
|
||||
// QPixmap m;
|
||||
// m.convertFromImage(newImage);
|
||||
// imagesCache[tile.id] = m;
|
||||
// GraphicsTileItem *newTileItem = new GraphicsTileItem(m, tile);
|
||||
// addItem(newTileItem);
|
||||
// newTileItem->setTileZoom(tilesZoom);
|
||||
// newTileItem->setPos(i * newTileItem->boundingRect().width() + i,
|
||||
// j * newTileItem->boundingRect().width() + j);
|
||||
}
|
||||
}
|
||||
// unsigned max_w =
|
||||
// items()[0]->boundingRect().width() * arrangedTiles[0].size() +
|
||||
// arrangedTiles[0].size();
|
||||
// unsigned max_h = items()[0]->boundingRect().width() * arrangedTiles.size()
|
||||
// +
|
||||
// arrangedTiles.size();
|
||||
// setSceneRect(QRect(0, 0, max_w, max_h));
|
||||
}
|
||||
|
||||
SDL_Surface* Scene::buildSurface(const std::vector<tile8>& tiles,
|
||||
const SNESPalette mPalette,
|
||||
const TilesPattern& tp) {
|
||||
|
||||
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, 128, 7104, SDL_BITSPERPIXEL(4), SDL_PIXELFORMAT_RGB444);
|
||||
|
||||
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];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
// unsigned max_w =
|
||||
// items()[0]->boundingRect().width() * arrangedTiles[0].size() +
|
||||
// arrangedTiles[0].size();
|
||||
// unsigned max_h = items()[0]->boundingRect().width() * arrangedTiles.size()
|
||||
// +
|
||||
// arrangedTiles.size();
|
||||
// setSceneRect(QRect(0, 0, max_w, max_h));
|
||||
}
|
||||
|
||||
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
|
||||
43
src/Application/Graphics/Scene.h
Normal file
43
src/Application/Graphics/Scene.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef YAZE_APPLICATION_GRAPHICS_SCENE_H
|
||||
#define YAZE_APPLICATION_GRAPHICS_SCENE_H
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <tile.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "Core/Renderer.h"
|
||||
#include "Graphics/Tile.h"
|
||||
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
Scene() = default;
|
||||
void buildScene(const std::vector<tile8>& tiles, const SNESPalette mPalette,
|
||||
const TilesPattern& tp);
|
||||
|
||||
SDL_Surface* buildSurface(const std::vector<tile8>& tiles,
|
||||
const SNESPalette mPalette, const TilesPattern& tp);
|
||||
|
||||
void updateScene();
|
||||
void setTilesZoom(unsigned int tileZoom);
|
||||
void setTilesPattern(TilesPattern tp);
|
||||
|
||||
private:
|
||||
std::vector<tile8> allTiles;
|
||||
std::vector<std::vector<tile8> > arrangedTiles;
|
||||
unsigned int tilesZoom;
|
||||
TilesPattern tilesPattern;
|
||||
// QMap<unsigned int, QPixmap> imagesCache;
|
||||
};
|
||||
|
||||
} // namespace Graphics
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "png.h"
|
||||
|
||||
@@ -11,6 +12,8 @@ namespace yaze {
|
||||
namespace Application {
|
||||
namespace Graphics {
|
||||
|
||||
std::unordered_map<std::string, TilesPattern> TilesPattern::m_Patterns;
|
||||
|
||||
ushort TileInfo::toShort() {
|
||||
ushort value = 0;
|
||||
// vhopppcc cccccccc
|
||||
@@ -39,228 +42,293 @@ char *hexString(const char *str, const unsigned int size) {
|
||||
return toret;
|
||||
}
|
||||
|
||||
void export_all_gfx_to_png(byte *tiledata) {
|
||||
|
||||
auto tile = unpack_bpp3_tile(tiledata, 0);
|
||||
Graphics::r_palette *pal = palette_create(8, 0);
|
||||
|
||||
for (unsigned int i = 0; i < 8; i++) {
|
||||
pal->colors[i].red = i * 30;
|
||||
pal->colors[i].blue = i * 30;
|
||||
pal->colors[i].green = i * 30;
|
||||
}
|
||||
|
||||
FILE *fp = fopen("test.png", "wb");
|
||||
png_structp png_ptr =
|
||||
png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
png_init_io(png_ptr, fp);
|
||||
png_set_strip_alpha(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
png_color *png_palette =
|
||||
(png_color *)png_malloc(png_ptr, pal->size * sizeof(png_color));
|
||||
|
||||
for (unsigned int i = 0; i < pal->size; i++) {
|
||||
png_palette[i].blue = pal->colors[i].blue;
|
||||
png_palette[i].green = pal->colors[i].green;
|
||||
png_palette[i].red = pal->colors[i].red;
|
||||
}
|
||||
png_set_IHDR(png_ptr, info_ptr, 8, 8, 8, PNG_COLOR_TYPE_PALETTE,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
|
||||
PNG_FILTER_TYPE_BASE);
|
||||
png_set_PLTE(png_ptr, info_ptr, png_palette, pal->size);
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
png_byte *row_pointers[8];
|
||||
for (unsigned int i = 0; i < 8; i++) {
|
||||
row_pointers[i] = (png_byte *)png_malloc(png_ptr, sizeof(png_byte));
|
||||
memcpy(row_pointers[i], tile.data + i * 8, 8);
|
||||
}
|
||||
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
png_free(png_ptr, png_palette);
|
||||
png_free(png_ptr, row_pointers);
|
||||
TilesPattern::TilesPattern() {
|
||||
tilesPerRow = 16;
|
||||
numberOfTiles = 16;
|
||||
}
|
||||
// [pattern]
|
||||
// name = "32x32 B (4x4)"
|
||||
// number_of_tile = 16
|
||||
// pattern =
|
||||
void TilesPattern::default_settings() {
|
||||
numberOfTiles = 16;
|
||||
std::string patternString = "[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, A, B], [C, D, E, F]";
|
||||
|
||||
void export_tile_to_png(tile8 rawtile, const r_palette pal,
|
||||
const char *filename) {
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
png_structp png_ptr =
|
||||
png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
png_init_io(png_ptr, fp);
|
||||
png_set_strip_alpha(png_ptr);
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
transformVector.clear();
|
||||
|
||||
png_color *png_palette =
|
||||
(png_color *)png_malloc(png_ptr, pal.size * sizeof(png_color));
|
||||
// if (regex_match ("softwareTesting", regex("(soft)(.*)") ))
|
||||
// cout << "string:literal => matched\n";
|
||||
|
||||
// const char mystr[] = "SoftwareTestingHelp";
|
||||
// string str ("software");
|
||||
// regex str_expr ("(soft)(.*)");
|
||||
|
||||
// if (regex_match (str,str_expr))
|
||||
// cout << "string:object => matched\n";
|
||||
|
||||
// if ( regex_match ( str.begin(), str.end(), str_expr ) )
|
||||
// cout << "string:range(begin-end)=> matched\n";
|
||||
|
||||
// cmatch cm;
|
||||
// regex_match (mystr,cm,str_expr);
|
||||
|
||||
// smatch sm;
|
||||
// regex_match (str,sm,str_expr);
|
||||
// regex_match ( str.cbegin(), str.cend(), sm, str_expr);
|
||||
// cout << "String:range, size:" << sm.size() << " matches\n";
|
||||
|
||||
// regex_match ( mystr, cm, str_expr, regex_constants::match_default );
|
||||
std::cmatch cm;
|
||||
std::regex arrayRegExp("(\\[[\\s|0-F|a-f|,]+\\])");
|
||||
|
||||
for (unsigned int i = 0; i < pal.size; i++) {
|
||||
png_palette[i].blue = pal.colors[i].blue;
|
||||
png_palette[i].green = pal.colors[i].green;
|
||||
png_palette[i].red = pal.colors[i].red;
|
||||
}
|
||||
png_set_IHDR(png_ptr, info_ptr, 8, 8, 8, PNG_COLOR_TYPE_PALETTE,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
|
||||
PNG_FILTER_TYPE_BASE);
|
||||
png_set_PLTE(png_ptr, info_ptr, png_palette, pal.size);
|
||||
int pos = 0;
|
||||
while (arrayRegExp.indexIn(patternString, pos) != -1) {
|
||||
std::string arrayString = arrayRegExp.cap(1);
|
||||
std::vector<int> tmpVect;
|
||||
// std::cout << arrayString;
|
||||
unsigned int stringPos = 1;
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
png_set_packing(png_ptr);
|
||||
while (arrayString[stringPos] != ']') {
|
||||
while (arrayString[stringPos] == ' ') stringPos++;
|
||||
std::regex hex("([0-F|a-f]+)");
|
||||
bool ok;
|
||||
|
||||
png_byte *row_pointers[8];
|
||||
for (unsigned int i = 0; i < 8; i++) {
|
||||
row_pointers[i] = (png_byte *)png_malloc(png_ptr, sizeof(png_byte));
|
||||
memcpy(row_pointers[i], rawtile.data + i * 8, 8);
|
||||
}
|
||||
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
png_free(png_ptr, png_palette);
|
||||
png_free(png_ptr, row_pointers);
|
||||
}
|
||||
|
||||
tile8 unpack_bpp1_tile(const byte *data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 1));
|
||||
}
|
||||
|
||||
tile8 unpack_bpp2_tile(const byte *data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 2));
|
||||
}
|
||||
|
||||
tile8 unpack_bpp3_tile(const byte *data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 3));
|
||||
}
|
||||
|
||||
tile8 unpack_bpp4_tile(const byte *data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 4));
|
||||
}
|
||||
|
||||
tile8 unpack_bpp8_tile(const byte *data, const unsigned int offset) {
|
||||
return (unpack_bpp_tile(data, offset, 8));
|
||||
}
|
||||
|
||||
tile8 unpack_mode7_tile(const byte *data, const unsigned int offset) {
|
||||
tile8 tile;
|
||||
memcpy(tile.data, data + offset, 64);
|
||||
return tile;
|
||||
}
|
||||
|
||||
tile8 unpack_bpp_tile(const byte *data, const unsigned int offset,
|
||||
const unsigned bpp) {
|
||||
tile8 tile;
|
||||
assert(bpp >= 1 && bpp <= 8);
|
||||
unsigned int bpp_pos[8]; // More for conveniance and readibility
|
||||
for (int col = 0; col < 8; col++) {
|
||||
for (int row = 0; row < 8; row++) {
|
||||
if (bpp == 1) {
|
||||
tile.data[col * 8 + row] = (data[offset + col] >> (7 - row)) & 0x01;
|
||||
continue;
|
||||
if (hex.indexIn(arrayString, stringPos) == stringPos) {
|
||||
tmpVect.push_back(hex.cap(1).toInt(&ok, 16));
|
||||
}
|
||||
/* SNES bpp format interlace each byte of the first 2 bitplanes.
|
||||
* | byte 1 of first bitplane | byte 1 of the second bitplane | byte 2 of
|
||||
* first bitplane | byte 2 of second bitplane | ..
|
||||
*/
|
||||
bpp_pos[0] = offset + col * 2;
|
||||
bpp_pos[1] = offset + col * 2 + 1;
|
||||
char mask = 1 << (7 - row);
|
||||
tile.data[col * 8 + row] = (data[bpp_pos[0]] & mask) == mask;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[1]] & mask) == mask) << 1;
|
||||
if (bpp == 3) {
|
||||
// When we have 3 bitplanes, the bytes for the third bitplane are after
|
||||
// the 16 bytes of the 2 bitplanes.
|
||||
bpp_pos[2] = offset + 16 + col;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[2]] & mask) == mask) << 2;
|
||||
}
|
||||
if (bpp >= 4) {
|
||||
// For 4 bitplanes, the 2 added bitplanes are interlaced like the first
|
||||
// two.
|
||||
bpp_pos[2] = offset + 16 + col * 2;
|
||||
bpp_pos[3] = offset + 16 + col * 2 + 1;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[2]] & mask) == mask) << 2;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[3]] & mask) == mask) << 3;
|
||||
}
|
||||
if (bpp == 8) {
|
||||
bpp_pos[4] = offset + 32 + col * 2;
|
||||
bpp_pos[5] = offset + 32 + col * 2 + 1;
|
||||
bpp_pos[6] = offset + 48 + col * 2;
|
||||
bpp_pos[7] = offset + 48 + col * 2 + 1;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[4]] & mask) == mask) << 4;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[5]] & mask) == mask) << 5;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[6]] & mask) == mask) << 6;
|
||||
tile.data[col * 8 + row] |= ((data[bpp_pos[7]] & mask) == mask) << 7;
|
||||
while (arrayString[stringPos] == ' ') stringPos++;
|
||||
stringPos++; // should be the comma
|
||||
}
|
||||
|
||||
pos += arrayRegExp.matchedLength();
|
||||
transformVector.push_back(tmpVect);
|
||||
}
|
||||
std::cout << transformVector.size() << std::endl;
|
||||
for ( const auto & each : transformVector )
|
||||
std::cout << each << std::endl;
|
||||
}
|
||||
|
||||
bool TilesPattern::load(std::string patternFile) {
|
||||
// QSettings pFile(patternFile, QSettings::IniFormat);
|
||||
// name = pFile.value("pattern/name").toString();
|
||||
// description = pFile.value("pattern/description").toString();
|
||||
// numberOfTiles = pFile.value("pattern/number_of_tile").toInt();
|
||||
// std::cout << name;
|
||||
// // unsigned int nbOfTile = pFile.value("_/number_of_tile").toUInt();
|
||||
// std::string patternString = pFile.value("pattern/pattern").toString();
|
||||
// std::cout << patternString;
|
||||
|
||||
// // Pattern String is a array description
|
||||
|
||||
// transformVector.clear();
|
||||
// QRegExp arrayRegExp("(\\[[\\s|0-F|a-f|,]+\\])");
|
||||
// int pos = 0;
|
||||
// while (arrayRegExp.indexIn(patternString, pos) != -1) {
|
||||
// std::string arrayString = arrayRegExp.cap(1);
|
||||
// std::vector<int> tmpVect;
|
||||
// // std::cout << arrayString;
|
||||
// unsigned int stringPos = 1;
|
||||
|
||||
// while (arrayString[stringPos] != ']') {
|
||||
// while (arrayString[stringPos].isSpace()) stringPos++;
|
||||
// QRegExp hex("([0-F|a-f]+)");
|
||||
// bool ok;
|
||||
// if (hex.indexIn(arrayString, stringPos) == stringPos) {
|
||||
// tmpVect.append(hex.cap(1).toInt(&ok, 16));
|
||||
// }
|
||||
// while (arrayString[stringPos].isSpace()) stringPos++;
|
||||
// stringPos++; // should be the comma
|
||||
// }
|
||||
// pos += arrayRegExp.matchedLength();
|
||||
// transformVector.append(tmpVect);
|
||||
// }
|
||||
// std::cout << transformVector.size() << transformVector;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TilesPattern::loadPatterns() {
|
||||
// foreach (std::string fileName, patternDirectory.entryList(QDir::Files)) {
|
||||
// TilesPattern tp;
|
||||
// std::cout << "Loading " << fileName;
|
||||
// if (!tp.load(patternDirectory.absoluteFilePath(fileName))) return false;
|
||||
// m_Patterns[tp.name] = tp;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
TilesPattern TilesPattern::pattern(std::string name) {
|
||||
return m_Patterns[name];
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, TilesPattern> TilesPattern::Patterns() {
|
||||
return m_Patterns;
|
||||
}
|
||||
|
||||
std::vector<std::vector<tile8> > TilesPattern::transform(
|
||||
const std::vector<tile8> &tiles) const {
|
||||
unsigned int repeatOffsetY = 0;
|
||||
unsigned int repeatOffsetX = 0;
|
||||
unsigned int tVectHeight = transformVector.size();
|
||||
unsigned int tVectWidth = transformVector[0].size();
|
||||
unsigned int repeat = 0;
|
||||
std::vector<std::vector<tile8> > toret;
|
||||
unsigned int transPerRow = tilesPerRow / tVectWidth;
|
||||
unsigned int nbTransform = tiles.size() / numberOfTiles;
|
||||
printf("Tiles size : %d - nbtransform : %d - pattern number of tiles : %d",
|
||||
tiles.size(), nbTransform, numberOfTiles);
|
||||
if (transPerRow > nbTransform)
|
||||
toret.resize(tVectHeight);
|
||||
else
|
||||
toret.resize(
|
||||
((unsigned int)(((double)nbTransform / (double)transPerRow) + 0.5)) *
|
||||
tVectHeight);
|
||||
|
||||
std::vector<std::vector<tile8> > vec(toret);
|
||||
auto it = vec.begin();
|
||||
for (auto each : vec) {
|
||||
each.resize(tilesPerRow);
|
||||
}
|
||||
// while (it.hasNext()) {
|
||||
// it.next().resize(tilesPerRow);
|
||||
// }
|
||||
// std::cout << toret[0].size() << "x" << toret.size();
|
||||
while (repeat != nbTransform) {
|
||||
// std::cout << "repeat" << repeat;
|
||||
for (unsigned int j = 0; j < tVectHeight; j++) {
|
||||
for (unsigned int i = 0; i < tVectWidth; i++) {
|
||||
unsigned int posTile = transformVector[j][i] + numberOfTiles * repeat;
|
||||
unsigned int posX = i + repeatOffsetX;
|
||||
unsigned int posY = j + repeatOffsetY;
|
||||
// qDebug("X: %d - Y: %d - posTile : %d", posX, posY, posTile);
|
||||
toret[posY][posX] = tiles[posTile];
|
||||
}
|
||||
}
|
||||
if (repeatOffsetX + tVectWidth == tilesPerRow) {
|
||||
repeatOffsetX = 0;
|
||||
repeatOffsetY += tVectHeight;
|
||||
} else
|
||||
repeatOffsetX += tVectWidth;
|
||||
repeat++;
|
||||
}
|
||||
return tile;
|
||||
std::cout << "End of transform";
|
||||
return toret;
|
||||
}
|
||||
|
||||
byte *pack_bpp1_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 1, &p);
|
||||
}
|
||||
std::vector<tile8> TilesPattern::reverse(
|
||||
const std::vector<tile8> &tiles) const {
|
||||
unsigned int repeatOffsetY = 0;
|
||||
unsigned int repeatOffsetX = 0;
|
||||
unsigned int tVectHeight = transformVector.size();
|
||||
unsigned int tVectWidth = transformVector[0].size();
|
||||
unsigned int repeat = 0;
|
||||
unsigned int nbTransPerRow = tilesPerRow / tVectWidth;
|
||||
unsigned int nbTiles = tiles.size();
|
||||
std::vector<tile8> toretVec(tiles.size());
|
||||
|
||||
byte *pack_bpp2_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 2, &p);
|
||||
}
|
||||
for (unsigned int i = 0; i < nbTiles; i++) {
|
||||
unsigned int lineNb = i / tilesPerRow;
|
||||
unsigned int lineInTab = lineNb % tVectHeight;
|
||||
unsigned int colInTab = i % tVectWidth;
|
||||
unsigned int tileNb = transformVector[lineInTab][colInTab];
|
||||
|
||||
byte *pack_bpp3_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 3, &p);
|
||||
}
|
||||
unsigned int lineBlock = i / (nbTransPerRow * numberOfTiles);
|
||||
unsigned int blockNB =
|
||||
(i % (nbTransPerRow * numberOfTiles) % tilesPerRow) / tVectWidth;
|
||||
|
||||
byte *pack_bpp4_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 4, &p);
|
||||
}
|
||||
|
||||
byte *pack_bpp8_tile(const tile8 tile) {
|
||||
unsigned int p = 1;
|
||||
return pack_bpp_tile(tile, 8, &p);
|
||||
}
|
||||
|
||||
byte *pack_bpp_tile(tile8 tile, const unsigned int bpp, unsigned int *size) {
|
||||
byte *output = (byte *)malloc(bpp * 8);
|
||||
memset(output, 0, bpp * 8);
|
||||
unsigned maxcolor = 2 << bpp;
|
||||
*size = 0;
|
||||
|
||||
for (unsigned int col = 0; col < 8; col++) {
|
||||
for (unsigned int row = 0; row < 8; row++) {
|
||||
byte color = tile.data[col * 8 + row];
|
||||
if (color > maxcolor) return NULL;
|
||||
|
||||
if (bpp == 1) output[col] += (byte)((color & 1) << (7 - row));
|
||||
if (bpp >= 2) {
|
||||
output[col * 2] += (byte)((color & 1) << (7 - row));
|
||||
output[col * 2 + 1] += (byte)(((color & 2) == 2) << (7 - row));
|
||||
}
|
||||
if (bpp == 3) output[16 + col] += (byte)(((color & 4) == 4) << (7 - row));
|
||||
if (bpp >= 4) {
|
||||
output[16 + col * 2] += (byte)(((color & 4) == 4) << (7 - row));
|
||||
output[16 + col * 2 + 1] += (byte)(((color & 8) == 8) << (7 - row));
|
||||
}
|
||||
if (bpp == 8) {
|
||||
output[32 + col * 2] += (byte)(((color & 16) == 16) << (7 - row));
|
||||
output[32 + col * 2 + 1] += (byte)(((color & 32) == 32) << (7 - row));
|
||||
output[48 + col * 2] += (byte)(((color & 64) == 64) << (7 - row));
|
||||
output[48 + col * 2 + 1] += (byte)(((color & 128) == 128) << (7 - row));
|
||||
}
|
||||
}
|
||||
// std::cout << colInTab << lineInTab << " = " << tileNb;
|
||||
// unsigned int pos = tileNb + ((i % tilesPerRow) / nbTransPerRow) *
|
||||
// numberOfTiles;
|
||||
unsigned int pos = tileNb + (lineBlock + blockNB) * numberOfTiles;
|
||||
// std::cout << i << "Goes to : " << pos;
|
||||
toretVec[pos] = tiles[i];
|
||||
}
|
||||
*size = bpp * 8;
|
||||
return output;
|
||||
return toretVec;
|
||||
}
|
||||
|
||||
std::vector<std::vector<tile8> > TilesPattern::transform(
|
||||
const TilesPattern &pattern, const std::vector<tile8> &tiles) {
|
||||
return pattern.transform(tiles);
|
||||
}
|
||||
|
||||
std::vector<std::vector<tile8> > TilesPattern::transform(
|
||||
const std::string id, const std::vector<tile8> &tiles) {
|
||||
return m_Patterns[id].transform(tiles);
|
||||
}
|
||||
|
||||
std::vector<tile8> TilesPattern::reverse(const TilesPattern &pattern,
|
||||
const std::vector<tile8> &tiles) {
|
||||
return pattern.reverse(tiles);
|
||||
}
|
||||
|
||||
|
||||
TilePreset::TilePreset()
|
||||
{
|
||||
name = "";
|
||||
romName = "";
|
||||
romType = "";
|
||||
|
||||
pcTilesLocation = -1;
|
||||
SNESTilesLocation = 0;
|
||||
length = 0;
|
||||
bpp = 0;
|
||||
compression = "None";
|
||||
pcPaletteLocation = 0;
|
||||
SNESPaletteLocation = 0;
|
||||
paletteNoZeroColor = false;
|
||||
}
|
||||
|
||||
bool TilePreset::save(const std::string &file)
|
||||
{
|
||||
// QSettings pFile(file, QSettings::IniFormat);
|
||||
|
||||
// if (pFile.isWritable() == false)
|
||||
// return false;
|
||||
|
||||
// pFile.setValue("_/name", name);
|
||||
// pFile.setValue("rom/name", romName);
|
||||
// pFile.setValue("rom/type", romType);
|
||||
|
||||
// pFile.setValue("tiles/pc_location", QString::number(pcTilesLocation, 16));
|
||||
// pFile.setValue("tiles/snes_location", QString::number(SNESTilesLocation, 16));
|
||||
// pFile.setValue("tiles/length", length);
|
||||
// pFile.setValue("tiles/bpp", bpp);
|
||||
// pFile.setValue("tiles/compression", compression);
|
||||
// pFile.setValue("tiles/pattern", tilesPattern.name);
|
||||
|
||||
// pFile.setValue("palette/pc_location", QString::number(pcPaletteLocation, 16));
|
||||
// pFile.setValue("palette/snes_location", QString::number(SNESPaletteLocation, 16));
|
||||
// pFile.setValue("palette/nozerocolor", paletteNoZeroColor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TilePreset::load(const std::string& file)
|
||||
{
|
||||
// QSettings pFile(file, QSettings::IniFormat);
|
||||
|
||||
// /* Meh solution to know if the file is right*/
|
||||
// if (pFile.value("_/name").toString().isEmpty())
|
||||
// return false;
|
||||
// name = pFile.value("_/name").toString();
|
||||
// romName = pFile.value("rom/name").toString();
|
||||
// romType = pFile.value("rom/type").toString();
|
||||
|
||||
// /* Locations are stored in a hex string */
|
||||
// bool ok;
|
||||
// pcTilesLocation = pFile.value("tiles/pc_location").toString().toUInt(&ok, 16);
|
||||
// SNESTilesLocation = pFile.value("tiles/snes_location").toString().toUInt(&ok, 16);
|
||||
// length = pFile.value("tiles/length").toInt();
|
||||
// bpp = pFile.value("tiles/bpp").toInt();
|
||||
// compression = pFile.value("tiles/compression").toString();
|
||||
// QString patternName = pFile.value("tiles/pattern").toString();
|
||||
// if (patternName.isEmpty())
|
||||
// patternName = "normal";
|
||||
// tilesPattern = TilesPattern::pattern(patternName);
|
||||
|
||||
// pcPaletteLocation = pFile.value("palette/pc_location").toString().toUInt(&ok, 16);
|
||||
// SNESPaletteLocation = pFile.value("palette/snes_location").toString().toUInt(&ok, 16);
|
||||
// paletteNoZeroColor = pFile.value("palette/nozerocolor").toBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Graphics
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#ifndef YAZE_APPLICATION_DATA_TILE_H
|
||||
#define YAZE_APPLICATION_DATA_TILE_H
|
||||
|
||||
#include <tile.h>
|
||||
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "Palette.h"
|
||||
@@ -13,40 +18,6 @@ using byte = unsigned char;
|
||||
using ushort = unsigned short;
|
||||
using uint = unsigned int;
|
||||
|
||||
// SkarAlttp project code
|
||||
extern "C" {
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
byte data[64];
|
||||
unsigned int palette_id;
|
||||
} tile8;
|
||||
|
||||
tile8 unpack_bpp8_tile(const byte* data, const unsigned int offset);
|
||||
tile8 unpack_bpp4_tile(const byte* data, const unsigned int offset);
|
||||
tile8 unpack_bpp3_tile(const byte* data, const unsigned int offset);
|
||||
tile8 unpack_bpp2_tile(const byte* data, const unsigned int offset);
|
||||
tile8 unpack_bpp1_tile(const byte* data, const unsigned int offset);
|
||||
|
||||
tile8 unpack_bpp_tile(const byte* data, const unsigned int offset,
|
||||
const unsigned int bpp);
|
||||
|
||||
byte* pack_bpp1_tile(const tile8 tile);
|
||||
byte* pack_bpp2_tile(const tile8 tile);
|
||||
byte* pack_bpp3_tile(const tile8 tile);
|
||||
byte* pack_bpp4_tile(const tile8 tile);
|
||||
byte* pack_bpp8_tile(const tile8 tile);
|
||||
|
||||
byte* pack_bpp_tile(const tile8 tile, const unsigned int bpp,
|
||||
unsigned int* size);
|
||||
|
||||
void export_all_gfx_to_png(byte* tiledata);
|
||||
|
||||
void export_tile_to_png(tile8 rawtile, const r_palette pal,
|
||||
const char* filename);
|
||||
}
|
||||
|
||||
// End SkarAlttp project code
|
||||
class TileInfo {
|
||||
public:
|
||||
ushort id_;
|
||||
@@ -122,6 +93,62 @@ class Tile16 {
|
||||
}
|
||||
};
|
||||
|
||||
class TilesPattern {
|
||||
public:
|
||||
TilesPattern();
|
||||
std::string name;
|
||||
std::string description;
|
||||
bool custom;
|
||||
unsigned int tilesPerRow;
|
||||
unsigned int numberOfTiles;
|
||||
|
||||
void default_settings();
|
||||
|
||||
bool load(std::string patternFile);
|
||||
|
||||
static bool loadPatterns();
|
||||
static TilesPattern pattern(std::string name);
|
||||
static std::unordered_map<std::string, TilesPattern> Patterns();
|
||||
static std::vector<std::vector<tile8> > transform(
|
||||
const TilesPattern& pattern, const std::vector<tile8>& tiles);
|
||||
static std::vector<std::vector<tile8> > transform(
|
||||
const std::string id, const std::vector<tile8>& tiles);
|
||||
static std::vector<tile8> reverse(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;
|
||||
std::vector<std::vector<int> > transformVector;
|
||||
|
||||
private:
|
||||
static std::unordered_map<std::string, TilesPattern> m_Patterns;
|
||||
};
|
||||
|
||||
class TilePreset {
|
||||
public:
|
||||
TilePreset();
|
||||
|
||||
bool save(const std::string& file);
|
||||
bool load(const std::string& file);
|
||||
|
||||
std::string name;
|
||||
std::string romName;
|
||||
std::string romType;
|
||||
TilesPattern tilesPattern;
|
||||
|
||||
unsigned int SNESTilesLocation;
|
||||
int pcTilesLocation;
|
||||
unsigned int SNESPaletteLocation;
|
||||
unsigned int pcPaletteLocation;
|
||||
bool paletteNoZeroColor;
|
||||
unsigned int length;
|
||||
|
||||
unsigned int bpp;
|
||||
std::string compression;
|
||||
};
|
||||
|
||||
} // namespace Graphics
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
|
||||
@@ -10,216 +10,9 @@ namespace Utils {
|
||||
|
||||
using namespace Graphics;
|
||||
|
||||
char *rommapping_error_text;
|
||||
/*
|
||||
* LoRoM is quite easy
|
||||
*/
|
||||
int lorom_snes_to_pc(const unsigned int snes_addr, char **info) {
|
||||
unsigned char bank = snes_addr >> 16;
|
||||
unsigned int offset = snes_addr & 0x00FFFF;
|
||||
// printf("snes_addr: %X - Bank: %X - Offset: %X\n", snes_addr, bank, offset);
|
||||
|
||||
// 80-FD is a mirror to the start
|
||||
if (bank >= 0x80 && bank <= 0xFD)
|
||||
bank -= 0x80;
|
||||
if (bank >= 0x00 && bank <= 0x3F && offset < 0x8000 && offset >= 0x2000) {
|
||||
*info = "SNES Reserved";
|
||||
return ROMMAPPING_LOCATION_SNES_RESERVED;
|
||||
}
|
||||
if ((((bank >= 0x70 && bank <= 0x7D) || bank == 0xFE || bank == 0xFF) &&
|
||||
offset < 0x8000)) {
|
||||
*info = "SRAM";
|
||||
return ROMMAPPING_LOCATION_SRAM;
|
||||
}
|
||||
if (bank == 0x7E || bank == 0x7F ||
|
||||
(bank >= 0x00 && bank <= 0x3F && offset < 0x2000)) {
|
||||
*info = "WRAM section";
|
||||
return ROMMAPPING_LOCATION_WRAM;
|
||||
}
|
||||
|
||||
if (bank >= 0x40 && bank <= 0x6F && offset < 0x8000)
|
||||
return bank * 0x8000 + offset;
|
||||
if (bank == 0xFE || bank == 0xFF) // this work as if 7E was regular bank
|
||||
bank -= 0xFE - 0x7E;
|
||||
return bank * 0x8000 + (offset - 0x8000);
|
||||
}
|
||||
|
||||
int hirom_snes_to_pc(const unsigned int snes_addr, char **info) {
|
||||
unsigned char bank = snes_addr >> 16;
|
||||
unsigned int offset = snes_addr & 0x00FFFF;
|
||||
|
||||
// 80-FD is a mirror to the start
|
||||
if (bank >= 0x80 && bank <= 0xFD)
|
||||
bank -= 0x80;
|
||||
|
||||
if ((bank >= 0x00 && bank <= 0x1F && offset < 0x8000 && offset >= 0x2000) ||
|
||||
(bank >= 0x20 && bank <= 0x3F && offset < 0x6000 && offset >= 0x2000)) {
|
||||
*info = "SNES Reserved";
|
||||
return ROMMAPPING_LOCATION_SNES_RESERVED;
|
||||
}
|
||||
if (bank >= 0x20 && bank <= 0x3F && offset >= 0x6000 && offset < 0x8000) {
|
||||
*info = "SRAM";
|
||||
return ROMMAPPING_LOCATION_SRAM;
|
||||
}
|
||||
if ((bank == 0x7E || bank == 0x7F) ||
|
||||
(bank >= 0x00 && bank <= 0x3F && offset < 0x2000)) {
|
||||
*info = "WRAM Section";
|
||||
return ROMMAPPING_LOCATION_WRAM;
|
||||
}
|
||||
/*#include <stdio.h>
|
||||
printf("%02X:%04X\n", bank, offset);*/
|
||||
if (bank >= 0xFE)
|
||||
bank -= 0xFE - 0x3E;
|
||||
if (bank >= 0x40 && bank <= 0x7D)
|
||||
bank -= 0x40;
|
||||
return (bank << 16) + offset;
|
||||
}
|
||||
|
||||
int hirom_pc_to_snes(const unsigned int pc_addr) {
|
||||
unsigned int bank = pc_addr >> 16;
|
||||
unsigned int offset = pc_addr & 0x00FFFF;
|
||||
|
||||
// printf("%02X:%04X\n", bank, offset);
|
||||
if (bank <= 0x3F && offset >= 0x8000)
|
||||
return pc_addr;
|
||||
if (bank <= 0x3D)
|
||||
return pc_addr + 0x400000;
|
||||
return pc_addr + 0xFE0000;
|
||||
}
|
||||
|
||||
int hirom_sram_snes_to_pc(const unsigned int snes_addr) {
|
||||
unsigned int bank = snes_addr >> 16;
|
||||
unsigned int offset = snes_addr & 0x00FFFF;
|
||||
|
||||
if (bank >= 0x20 && bank <= 0x3F && offset >= 0x6000 && offset < 0x8000)
|
||||
return (bank - 0x20) * 0x2000 + (offset - 0x6000);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hirom_sram_pc_to_snes(const unsigned int pc_addr) {
|
||||
unsigned int chuck_nb = pc_addr / 0x2000;
|
||||
unsigned int rest = pc_addr % 0x2000;
|
||||
|
||||
return ((0x20 + chuck_nb) << 16) + 0x6000 + rest;
|
||||
}
|
||||
|
||||
int lorom_pc_to_snes(const unsigned int pc_addr) {
|
||||
|
||||
unsigned int bank = pc_addr / 0x8000;
|
||||
unsigned int offset = pc_addr % 0x8000 + 0x8000;
|
||||
|
||||
// printf("pc_addr: %X - Bank: %X - Offset: %X\n", pc_addr, bank, offset);
|
||||
|
||||
return (bank << 16) + offset;
|
||||
}
|
||||
|
||||
int lorom_sram_pc_to_snes(const unsigned int pc_addr) {
|
||||
int chuck_nb = pc_addr / 0x8000;
|
||||
int rest = pc_addr % 0x8000;
|
||||
|
||||
if (chuck_nb <= 0xD)
|
||||
return ((0x70 + chuck_nb) << 16) + rest;
|
||||
if (chuck_nb == 0xE || chuck_nb == 0xF)
|
||||
return ((0xF0 + chuck_nb) << 16) + rest;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lorom_sram_snes_to_pc(const unsigned int snes_addr) {
|
||||
unsigned char bank = snes_addr >> 16;
|
||||
unsigned int offset = snes_addr & 0x00FFFF;
|
||||
|
||||
// F0-FD are mirror of 70-7D
|
||||
if (bank >= 0xF0 && bank <= 0xFD)
|
||||
bank -= 0x80;
|
||||
if (bank >= 0x70 && bank <= 0x7D && offset < 0x8000)
|
||||
return (bank - 0x70) * 0x8000 + offset;
|
||||
if ((bank == 0xFE || bank == 0xFF) && offset < 0x8000)
|
||||
return ((bank - 0xFE) + 0xE) * 0x8000 + offset;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rommapping_snes_to_pc(const unsigned int snes_addr, enum rom_type rom_type,
|
||||
bool header) {
|
||||
int pc_addr;
|
||||
char *info;
|
||||
switch (rom_type) {
|
||||
case LoROM:
|
||||
pc_addr = lorom_snes_to_pc(snes_addr, &info);
|
||||
break;
|
||||
case HiROM:
|
||||
pc_addr = hirom_snes_to_pc(snes_addr, &info);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pc_addr < 0) {
|
||||
rommapping_error_text = (char *)malloc(strlen(info) + 1);
|
||||
strcpy(rommapping_error_text, info);
|
||||
return pc_addr;
|
||||
}
|
||||
if (header)
|
||||
pc_addr += 0x200;
|
||||
return pc_addr;
|
||||
}
|
||||
|
||||
int rommapping_pc_to_snes(const unsigned int pc_addr, enum rom_type rom_type,
|
||||
bool header) {
|
||||
int snes_addr;
|
||||
|
||||
switch (rom_type) {
|
||||
case LoROM:
|
||||
snes_addr = lorom_pc_to_snes(header ? pc_addr - 0x200 : pc_addr);
|
||||
break;
|
||||
case HiROM:
|
||||
snes_addr = hirom_pc_to_snes(header ? pc_addr - 0x200 : pc_addr);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return snes_addr;
|
||||
}
|
||||
|
||||
int rommapping_sram_snes_to_pc(const unsigned int snes_addr,
|
||||
enum rom_type rom_type, bool header) {
|
||||
int pc_addr;
|
||||
switch (rom_type) {
|
||||
case LoROM:
|
||||
pc_addr = lorom_sram_snes_to_pc(snes_addr);
|
||||
break;
|
||||
case HiROM:
|
||||
pc_addr = hirom_sram_snes_to_pc(snes_addr);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (header)
|
||||
pc_addr += 0x200;
|
||||
return pc_addr;
|
||||
}
|
||||
|
||||
int rommapping_sram_pc_to_snes(const unsigned int pc_addr,
|
||||
enum rom_type rom_type, bool header) {
|
||||
int snes_addr;
|
||||
|
||||
switch (rom_type) {
|
||||
case LoROM:
|
||||
snes_addr = lorom_sram_pc_to_snes(header ? pc_addr - 0x200 : pc_addr);
|
||||
break;
|
||||
case HiROM:
|
||||
snes_addr = hirom_sram_pc_to_snes(header ? pc_addr - 0x200 : pc_addr);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return snes_addr;
|
||||
}
|
||||
|
||||
void ROM::LoadFromFile(const std::string &path) {
|
||||
|
||||
FILE *file = fopen(path.c_str(), "r+");
|
||||
if (file == NULL)
|
||||
return;
|
||||
if (file == NULL) return;
|
||||
fseek(file, 0, SEEK_END);
|
||||
size = ftell(file);
|
||||
fclose(file);
|
||||
@@ -234,23 +27,40 @@ void ROM::LoadFromFile(const std::string &path) {
|
||||
|
||||
type = LoROM;
|
||||
fastrom = (current_rom_[21] & 0b00110000) == 0b00110000;
|
||||
if (current_rom_[21] & 1)
|
||||
type = HiROM;
|
||||
if ((current_rom_[21] & 0b00000111) == 0b00000111)
|
||||
type = ExHiROM;
|
||||
if (current_rom_[21] & 1) type = HiROM;
|
||||
if ((current_rom_[21] & 0b00000111) == 0b00000111) type = ExHiROM;
|
||||
|
||||
sram_size = 0x400 << current_rom_[24];
|
||||
creator_id = (current_rom_[26] << 8) | current_rom_[25];
|
||||
version = current_rom_[27];
|
||||
checksum_comp = (current_rom_[29] << 8) | current_rom_[28];
|
||||
checksum = (current_rom_[31] << 8) | current_rom_[30];
|
||||
make_sense = false;
|
||||
if ((checksum ^ checksum_comp) == 0xFFFF)
|
||||
make_sense = true;
|
||||
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
|
||||
std::vector<tile8> ROM::ExtractTiles(unsigned int bpp, unsigned int length) {
|
||||
std::vector<tile8> rawTiles;
|
||||
unsigned int lastCompressedSize;
|
||||
unsigned int size = length;
|
||||
char *data =
|
||||
alttp_decompress_gfx(data, 0, length, &size, &lastCompressedSize);
|
||||
|
||||
if (data == NULL) {
|
||||
return rawTiles;
|
||||
}
|
||||
|
||||
unsigned tileCpt = 0;
|
||||
for (unsigned int tilePos = 0; tilePos < size; tilePos += bpp * 8) {
|
||||
tile8 newTile = unpack_bpp_tile(data, tilePos, bpp);
|
||||
newTile.id = tileCpt;
|
||||
rawTiles.push_back(newTile);
|
||||
tileCpt++;
|
||||
}
|
||||
|
||||
free(data);
|
||||
return rawTiles;
|
||||
}
|
||||
|
||||
|
||||
int ROM::SnesToPc(int addr) {
|
||||
if (addr >= 0x808000) {
|
||||
addr -= 0x808000;
|
||||
@@ -259,24 +69,6 @@ int ROM::SnesToPc(int addr) {
|
||||
return (temp + 0x0);
|
||||
}
|
||||
|
||||
// TODO: FIXME
|
||||
int ROM::PcToSnes(int addr) {
|
||||
byte b[4];
|
||||
// = BitConverter.GetBytes(addr)
|
||||
b[2] = (byte)(b[2] * 2);
|
||||
|
||||
if (b[1] >= 0x80) {
|
||||
b[2] += 1;
|
||||
} else {
|
||||
b[1] += 0x80;
|
||||
}
|
||||
|
||||
// return BitConverter.ToInt32(b, 0);
|
||||
// snes always have + 0x8000 no matter what, the bank on pc is always / 2
|
||||
|
||||
return ((addr * 2) & 0xFF0000) + (addr & 0x7FFF) + 0x8000;
|
||||
}
|
||||
|
||||
int AddressFromBytes(byte addr1, byte addr2, byte addr3) {
|
||||
return (addr1 << 16) | (addr2 << 8) | addr3;
|
||||
}
|
||||
@@ -317,6 +109,6 @@ short ROM::ReadReverseShort(int addr) {
|
||||
return (short)((current_rom_[addr] << 8) + current_rom_[addr + 1]);
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
} // namespace Utils
|
||||
} // namespace Application
|
||||
} // namespace yaze
|
||||
@@ -9,8 +9,13 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Compression.h"
|
||||
#include "Core/Constants.h"
|
||||
#include "Graphics/Tile.h"
|
||||
#include "compressions/alttpcompression.h"
|
||||
#include "compressions/stdnintendo.h"
|
||||
#include "rommapping.h"
|
||||
#include "tile.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace Application {
|
||||
@@ -19,39 +24,16 @@ namespace Utils {
|
||||
using byte = unsigned char;
|
||||
using ushort = unsigned short;
|
||||
|
||||
extern "C" {
|
||||
|
||||
enum rom_type { LoROM, HiROM, ExLoROM, ExHiROM };
|
||||
|
||||
extern char* rommapping_error_text;
|
||||
|
||||
int rommapping_snes_to_pc(const unsigned int snes_addr, enum rom_type rom_type,
|
||||
bool header);
|
||||
int rommapping_pc_to_snes(const unsigned int pc_addr, enum rom_type rom_type,
|
||||
bool header);
|
||||
|
||||
int rommapping_sram_snes_to_pc(const unsigned int snes_addr,
|
||||
enum rom_type rom_type, bool header);
|
||||
int rommapping_sram_pc_to_snes(const unsigned int pc_addr,
|
||||
enum rom_type rom_type, bool header);
|
||||
|
||||
int lorom_snes_to_pc(const unsigned int snes_addr, char** info);
|
||||
int lorom_sram_snes_to_pc(const unsigned int snes_addr);
|
||||
int lorom_pc_to_snes(const unsigned int pc_addr);
|
||||
int lorom_sram_pc_to_snes(const unsigned int pc_addr);
|
||||
|
||||
int hirom_snes_to_pc(const unsigned int snes_addr, char** info);
|
||||
int hirom_sram_snes_to_pc(const unsigned int snes_addr);
|
||||
int hirom_pc_to_snes(const unsigned int pc_addr);
|
||||
int hirom_sram_pc_to_snes(const unsigned int pc_addr);
|
||||
}
|
||||
using namespace Graphics;
|
||||
|
||||
int AddressFromBytes(byte addr1, byte addr2, byte addr3);
|
||||
|
||||
class ROM {
|
||||
public:
|
||||
void LoadFromFile(const std::string& path);
|
||||
std::vector<tile8> ExtractTiles(unsigned int bpp, unsigned int length);
|
||||
|
||||
int SnesToPc(int addr);
|
||||
int PcToSnes(int addr);
|
||||
short AddressFromBytes(byte addr1, byte addr2);
|
||||
ushort ReadShort(int addr);
|
||||
void Write(int addr, byte value);
|
||||
@@ -61,7 +43,6 @@ class ROM {
|
||||
void WriteShort(int addr, int value);
|
||||
int ReadLong(int addr);
|
||||
void WriteLong(int addr, int value);
|
||||
void LoadFromFile(const std::string& path);
|
||||
inline byte* GetRawData() { return current_rom_; }
|
||||
|
||||
const unsigned char* getTitle() const { return title; }
|
||||
|
||||
Reference in New Issue
Block a user