[nostalgia/core] Start port of PC gfx to OpenGL
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
#include <nostalgia/core/input.hpp>
|
||||
#include <nostalgia/core/core.hpp>
|
||||
|
||||
#include "core.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
static event_handler g_eventHandler = nullptr;
|
||||
@@ -24,6 +26,7 @@ ox::Error init(Context *ctx) {
|
||||
}
|
||||
|
||||
ox::Error run(Context *ctx) {
|
||||
auto id = ctx->windowerData<SdlImplData>();
|
||||
for (auto running = true; running;) {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
@@ -40,6 +43,7 @@ ox::Error run(Context *ctx) {
|
||||
}
|
||||
}
|
||||
draw(ctx);
|
||||
SDL_GL_SwapWindow(id->window);
|
||||
SDL_Delay(1);
|
||||
}
|
||||
return OxError(0);
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2016 - 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
struct SdlImplData {
|
||||
SDL_Window *window = nullptr;
|
||||
SDL_GLContext renderer = nullptr;
|
||||
std::array<SDL_Texture*, 4> bgTextures{};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -10,26 +10,21 @@
|
||||
#ifdef NOST_FPS_PRINT
|
||||
#include <iostream>
|
||||
#endif
|
||||
#include <iostream>
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <ox/claw/read.hpp>
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/core/userland/gfx.hpp>
|
||||
|
||||
#include "core.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
using TileMap = std::array<std::array<int, 128>, 128>;
|
||||
|
||||
struct SdlImplData {
|
||||
SDL_Window *window = nullptr;
|
||||
SDL_Renderer *renderer = nullptr;
|
||||
std::array<SDL_Texture*, 4> bgTextures{};
|
||||
std::array<TileMap, 4> bgTileMaps{};
|
||||
int64_t prevFpsCheckTime = 0;
|
||||
uint64_t draws = 0;
|
||||
};
|
||||
|
||||
constexpr auto Scale = 5;
|
||||
|
||||
static ox::Result<ox::Vector<char>> readFile(Context *ctx, const ox::FileAddress &file) {
|
||||
@@ -51,22 +46,32 @@ ox::Result<T> readObj(Context *ctx, const ox::FileAddress &file) {
|
||||
|
||||
ox::Error initGfx(Context *ctx) {
|
||||
auto id = new SdlImplData;
|
||||
ctx->setImplData(id);
|
||||
id->window = SDL_CreateWindow("nostalgia", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 240 * Scale, 160 * Scale,
|
||||
SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
id->renderer = SDL_CreateRenderer(id->window, -1, SDL_RENDERER_ACCELERATED);
|
||||
return OxError(id->window == nullptr);
|
||||
ctx->setWindowerData(id);
|
||||
id->window = SDL_CreateWindow("nostalgia", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
240 * Scale, 160 * Scale,
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
if (id->window == nullptr) {
|
||||
return OxError(1, SDL_GetError());
|
||||
}
|
||||
id->renderer = SDL_GL_CreateContext(id->window);
|
||||
if (id->renderer == nullptr) {
|
||||
return OxError(1, SDL_GetError());
|
||||
}
|
||||
oxReturnError(renderer::init(ctx));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error shutdownGfx(Context *ctx) {
|
||||
auto id = ctx->implData<SdlImplData>();
|
||||
oxReturnError(renderer::shutdown(ctx));
|
||||
auto id = ctx->windowerData<SdlImplData>();
|
||||
for (auto tex : id->bgTextures) {
|
||||
if (tex) {
|
||||
SDL_DestroyTexture(tex);
|
||||
}
|
||||
}
|
||||
SDL_DestroyRenderer(id->renderer);
|
||||
SDL_GL_DeleteContext(id->renderer);
|
||||
SDL_DestroyWindow(id->window);
|
||||
ctx->setWindowerData(nullptr);
|
||||
delete id;
|
||||
return OxError(0);
|
||||
}
|
||||
@@ -98,8 +103,8 @@ ox::Error loadBgTileSheet(Context *ctx,
|
||||
int section,
|
||||
ox::FileAddress tilesheetPath,
|
||||
ox::FileAddress palettePath) {
|
||||
auto id = ctx->implData<SdlImplData>();
|
||||
auto [tilesheet, tserr] = readObj<NostalgiaGraphic>(ctx, tilesheetPath);
|
||||
//auto id = ctx->windowerData<SdlImplData>();
|
||||
const auto [tilesheet, tserr] = readObj<NostalgiaGraphic>(ctx, tilesheetPath);
|
||||
oxReturnError(tserr);
|
||||
NostalgiaPalette palette;
|
||||
if (!palettePath) {
|
||||
@@ -108,31 +113,36 @@ ox::Error loadBgTileSheet(Context *ctx,
|
||||
oxReturnError(readObj<NostalgiaPalette>(ctx, palettePath).get(&palette));
|
||||
|
||||
const unsigned bytesPerTile = tilesheet.bpp == 8 ? 64 : 32;
|
||||
const auto tiles = tilesheet.tiles.size() / bytesPerTile;
|
||||
const auto tiles = tilesheet.pixels.size() / bytesPerTile;
|
||||
const int width = 8;
|
||||
const int height = 8 * tiles;
|
||||
const auto format = SDL_PIXELFORMAT_INDEX8;
|
||||
auto surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 16, format);
|
||||
auto sdlPalette = createSDL_Palette(palette);
|
||||
SDL_SetSurfacePalette(surface, sdlPalette);
|
||||
if (bytesPerTile == 64) {
|
||||
SDL_memcpy(surface->pixels, tilesheet.tiles.data(), bytesPerTile * tiles);
|
||||
} else {
|
||||
for (std::size_t i = 0; i < tilesheet.tiles.size(); ++i) {
|
||||
static_cast<uint8_t*>(surface->pixels)[i * 2 + 0] = tilesheet.tiles[i] & 0xF;
|
||||
static_cast<uint8_t*>(surface->pixels)[i * 2 + 1] = tilesheet.tiles[i] >> 4;
|
||||
//const auto format = SDL_PIXELFORMAT_INDEX8;
|
||||
//const auto sdlPalette = createSDL_Palette(palette);
|
||||
std::vector<uint32_t> pixels;
|
||||
if (bytesPerTile == 64) { // 8 BPP
|
||||
pixels.resize(tilesheet.pixels.size());
|
||||
for (std::size_t i = 0; i < tilesheet.pixels.size(); ++i) {
|
||||
pixels[i] = toColor32(palette.colors[tilesheet.pixels[i]]);
|
||||
}
|
||||
} else { // 4 BPP
|
||||
pixels.resize(tilesheet.pixels.size() * 2);
|
||||
for (std::size_t i = 0; i < tilesheet.pixels.size(); ++i) {
|
||||
pixels[i * 2 + 0] = toColor32(palette.colors[tilesheet.pixels[i] & 0xF]);
|
||||
pixels[i * 2 + 1] = toColor32(palette.colors[tilesheet.pixels[i] >> 4]);
|
||||
}
|
||||
}
|
||||
|
||||
auto texture = SDL_CreateTextureFromSurface(id->renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_FreePalette(sdlPalette);
|
||||
oxReturnError(renderer::loadTexture(ctx, section, pixels.data(), width, height));
|
||||
|
||||
auto sectionIdx = static_cast<unsigned>(section);
|
||||
if (id->bgTextures[sectionIdx]) {
|
||||
SDL_DestroyTexture(id->bgTextures[sectionIdx]);
|
||||
}
|
||||
id->bgTextures[sectionIdx] = texture;
|
||||
//auto texture = SDL_CreateTextureFromSurface(nullptr, surface);
|
||||
//SDL_FreeSurface(surface);
|
||||
//SDL_FreePalette(sdlPalette);
|
||||
|
||||
//auto sectionIdx = static_cast<unsigned>(section);
|
||||
//if (id->bgTextures[sectionIdx]) {
|
||||
// SDL_DestroyTexture(id->bgTextures[sectionIdx]);
|
||||
//}
|
||||
//id->bgTextures[sectionIdx] = texture;
|
||||
|
||||
return OxError(0);
|
||||
}
|
||||
@@ -144,11 +154,10 @@ ox::Error loadSpriteTileSheet(Context*,
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
void drawBackground(Context *ctx, const TileMap &tm, SDL_Texture *tex) {
|
||||
void drawBackground(Context*, const TileMap &tm, SDL_Texture *tex) {
|
||||
if (tex) {
|
||||
constexpr auto DstSize = 8 * Scale;
|
||||
auto id = ctx->implData<SdlImplData>();
|
||||
//oxTrace("nostalgia::core::drawBackground") << "Drawing background";
|
||||
oxTracef("nostalgia::core::sdl::drawBackground", "Drawing background");
|
||||
SDL_Rect src = {}, dst = {};
|
||||
src.x = 0;
|
||||
src.w = 8;
|
||||
@@ -160,7 +169,7 @@ void drawBackground(Context *ctx, const TileMap &tm, SDL_Texture *tex) {
|
||||
for (auto &m : tm) {
|
||||
for (auto t : m) {
|
||||
src.y = t * 8;
|
||||
SDL_RenderCopy(id->renderer, tex, &src, &dst);
|
||||
SDL_RenderCopy(nullptr, tex, &src, &dst);
|
||||
dst.x += DstSize;
|
||||
}
|
||||
dst.x = 0;
|
||||
@@ -169,49 +178,4 @@ void drawBackground(Context *ctx, const TileMap &tm, SDL_Texture *tex) {
|
||||
}
|
||||
}
|
||||
|
||||
void draw(Context *ctx) {
|
||||
auto id = ctx->implData<SdlImplData>();
|
||||
++id->draws;
|
||||
if (id->draws >= 5000) {
|
||||
using namespace std::chrono;
|
||||
const auto now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||
const auto duration = static_cast<double>(now - id->prevFpsCheckTime) / 1000.0;
|
||||
const auto fps = static_cast<int>(static_cast<double>(id->draws) / duration);
|
||||
#ifdef NOST_FPS_PRINT
|
||||
std::cout << "FPS: " << fps << '\n';
|
||||
#endif
|
||||
oxTrace("nostalgia::core::gfx::fps") << "FPS:" << fps;
|
||||
id->prevFpsCheckTime = now;
|
||||
id->draws = 0;
|
||||
}
|
||||
SDL_RenderClear(id->renderer);
|
||||
for (std::size_t i = 0; i < id->bgTileMaps.size(); i++) {
|
||||
auto tex = id->bgTextures[i];
|
||||
auto &tm = id->bgTileMaps[i];
|
||||
drawBackground(ctx, tm, tex);
|
||||
}
|
||||
SDL_RenderPresent(id->renderer);
|
||||
}
|
||||
|
||||
void puts(Context *ctx, int column, int row, const char *str) {
|
||||
for (int i = 0; str[i]; i++) {
|
||||
setTile(ctx, 0, column + i, row, static_cast<uint8_t>(charMap[static_cast<uint8_t>(str[i])]));
|
||||
}
|
||||
}
|
||||
|
||||
void setTile(Context *ctx, int layer, int column, int row, uint8_t tile) {
|
||||
auto id = ctx->implData<SdlImplData>();
|
||||
auto z = static_cast<unsigned>(layer);
|
||||
auto y = static_cast<unsigned>(row);
|
||||
auto x = static_cast<unsigned>(column);
|
||||
id->bgTileMaps[z][y][x] = tile;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
void hideSprite(Context*, unsigned) {
|
||||
}
|
||||
|
||||
void setSprite(Context*, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned, unsigned) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user