Compare commits

...

3 Commits

Author SHA1 Message Date
f987b02c65 [nostalgia/gfx] Move to TileSheetV5
All checks were successful
Build / build (push) Successful in 3m23s
2025-01-21 02:21:01 -06:00
3c056276c1 [turbine,nostalgia] Cleanup 2025-01-20 23:19:07 -06:00
87e2fdefcf [ox/std] Make UAnyPtr uncopyable 2025-01-20 20:42:00 -06:00
28 changed files with 304 additions and 204 deletions

View File

@ -64,7 +64,7 @@ class AnyPtrT {
} }
} }
constexpr AnyPtrT(AnyPtrT const&other) noexcept { constexpr AnyPtrT(AnyPtrT const&other) noexcept requires(!unique) {
if (other) { if (other) {
m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData); m_wrapPtr = other.m_wrapPtr->copyTo(m_wrapData);
} }
@ -104,11 +104,9 @@ class AnyPtrT {
return *this; return *this;
} }
constexpr AnyPtrT &operator=(AnyPtrT const&ptr) noexcept { constexpr AnyPtrT &operator=(AnyPtrT const&ptr) noexcept requires(!unique) {
if (this != &ptr) { if (this != &ptr) {
if constexpr(unique) { if (std::is_constant_evaluated()) {
free();
} else if (std::is_constant_evaluated()) {
ox::safeDelete(m_wrapPtr); ox::safeDelete(m_wrapPtr);
} }
if (ptr) { if (ptr) {

View File

@ -12,7 +12,7 @@ namespace nostalgia::gfx {
using Color16 = uint16_t; using Color16 = uint16_t;
/** /**
* Nostalgia Core logically uses 16 bit colors, but must translate that to 32 * Nostalgia logically uses 16 bit colors, but must translate that to 32
* bit colors in some implementations. * bit colors in some implementations.
*/ */
using Color32 = uint32_t; using Color32 = uint32_t;

View File

@ -4,10 +4,7 @@
#pragma once #pragma once
#include <ox/fs/fs.hpp> #include <ox/std/memory.hpp>
#include <ox/model/desctypes.hpp>
#include <ox/std/buffer.hpp>
#include <ox/std/size.hpp>
#include <turbine/context.hpp> #include <turbine/context.hpp>
@ -19,9 +16,7 @@ class Context;
void safeDelete(Context *ctx) noexcept; void safeDelete(Context *ctx) noexcept;
using ContextUPtr = ox::UPtr<Context>; ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params = {}) noexcept;
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const&params = {}) noexcept;
keel::Context &keelCtx(Context &ctx) noexcept; keel::Context &keelCtx(Context &ctx) noexcept;

View File

@ -16,7 +16,7 @@
namespace nostalgia::gfx { namespace nostalgia::gfx {
struct Sprite { struct Sprite {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Sprite"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.Sprite";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
bool enabled = false; bool enabled = false;
int x = 0; int x = 0;
@ -46,7 +46,7 @@ OX_MODEL_BEGIN(Sprite)
OX_MODEL_END() OX_MODEL_END()
struct BgTile { struct BgTile {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.BgTile"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.BgTile";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
unsigned tileIdx = 0; unsigned tileIdx = 0;
unsigned palBank = 0; unsigned palBank = 0;
@ -62,7 +62,7 @@ OX_MODEL_BEGIN(BgTile)
OX_MODEL_END() OX_MODEL_END()
struct TileSheetSetEntrySection { struct TileSheetSetEntrySection {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheetSetEntrySection"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.TileSheetSetEntrySection";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
int32_t begin = 0; int32_t begin = 0;
int32_t tiles = 0; int32_t tiles = 0;
@ -78,7 +78,7 @@ OX_MODEL_BEGIN(TileSheetSetEntrySection)
OX_MODEL_END() OX_MODEL_END()
struct TileSheetSetEntry { struct TileSheetSetEntry {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheetSetEntry"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.TileSheetSetEntry";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
ox::FileAddress tilesheet; ox::FileAddress tilesheet;
ox::Vector<TileSheetSetEntrySection> sections; ox::Vector<TileSheetSetEntrySection> sections;
@ -90,7 +90,7 @@ OX_MODEL_BEGIN(TileSheetSetEntry)
OX_MODEL_END() OX_MODEL_END()
struct TileSheetSet { struct TileSheetSet {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheetSet"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.TileSheetSet";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
static constexpr auto Preloadable = true; static constexpr auto Preloadable = true;
int32_t bpp = 0; int32_t bpp = 0;

View File

@ -5,10 +5,8 @@
#pragma once #pragma once
#include <ox/fs/fs.hpp> #include <ox/fs/fs.hpp>
#include <ox/std/array.hpp>
#include <ox/std/point.hpp> #include <ox/std/point.hpp>
#include <ox/std/size.hpp> #include <ox/std/size.hpp>
#include <ox/std/span.hpp>
#include <ox/std/types.hpp> #include <ox/std/types.hpp>
#include <ox/model/def.hpp> #include <ox/model/def.hpp>
@ -290,7 +288,105 @@ constexpr ox::Error repair(TileSheetV4 &ts) noexcept {
} }
using TileSheet = TileSheetV4; struct TileSheetV5 {
using SubSheetIdx = ox::Vector<std::size_t, 4>;
struct SubSheet {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.TileSheet.SubSheet";
static constexpr auto TypeVersion = 5;
SubSheetId id = 0;
ox::String name;
int columns = 0;
int rows = 0;
ox::Vector<SubSheet> subsheets;
ox::Vector<uint8_t> pixels;
constexpr SubSheet() noexcept = default;
SubSheet(
SubSheetId const pId,
ox::StringParam pName,
int const pColumns,
int const pRows) noexcept:
id(pId),
name(std::move(pName)),
columns(pColumns),
rows(pRows),
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile)) {
}
SubSheet(
SubSheetId const pId,
ox::StringParam pName,
int const pColumns,
int const pRows,
ox::Vector<uint8_t> pPixels) noexcept:
id(pId),
name(std::move(pName)),
columns(pColumns),
rows(pRows),
pixels(std::move(pPixels)) {
}
/**
*
* @return the dimensional size of the SubSheet (e.g. width * height)
*/
[[nodiscard]]
constexpr std::size_t size() const noexcept {
return static_cast<std::size_t>(columns) * static_cast<std::size_t>(rows);
}
};
static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.TileSheet";
static constexpr auto TypeVersion = 5;
int8_t bpp = 4;
SubSheetId idIt = 0;
ox::FileAddress defaultPalette;
SubSheet subsheet{0, "Root", 1, 1};
};
[[nodiscard]]
constexpr bool valid(TileSheetV5::SubSheet const&ss) noexcept {
if (ss.subsheets.empty()) {
return static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) == ss.pixels.size();
} else {
return ss.pixels.empty() && ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
[](TileSheetV5::SubSheet const&s) {
return valid(s);
});
}
}
[[nodiscard]]
constexpr bool valid(TileSheetV5 const&ts) noexcept {
return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet);
}
constexpr void repair(TileSheetV5::SubSheet &ss, int const bpp) noexcept {
if (ss.subsheets.empty()) {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile);
ss.pixels.resize(bytes);
} else {
ss.pixels.clear();
ss.columns = -1;
ss.rows = -1;
}
for (auto &s : ss.subsheets) {
repair(s, bpp);
}
}
constexpr ox::Error repair(TileSheetV5 &ts) noexcept {
if (ts.bpp != 4 && ts.bpp != 8) {
return ox::Error{1, "Unable to repair TileSheet"};
}
repair(ts.subsheet, ts.bpp);
return {};
}
using TileSheet = TileSheetV5;
[[nodiscard]] [[nodiscard]]
std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept; std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
@ -311,7 +407,7 @@ uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept;
uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept; uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept;
[[nodiscard]] [[nodiscard]]
uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, std::size_t idx) noexcept; uint8_t getPixel(TileSheet::SubSheet const&ss, std::size_t idx) noexcept;
[[nodiscard]] [[nodiscard]]
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept; uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
@ -320,44 +416,24 @@ uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept; uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
[[nodiscard]] [[nodiscard]]
uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, ox::Point const&pt) noexcept; uint8_t getPixel(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
constexpr void walkPixels(TileSheet::SubSheet const&ss, int8_t pBpp, auto callback) noexcept { constexpr void walkPixels(TileSheet::SubSheet const&ss, int8_t, auto callback) noexcept {
if (pBpp == 4) { for (std::size_t i = 0; i < ss.pixels.size(); ++i) {
const auto pixelCnt = ox::min<std::size_t>( callback(i, ss.pixels[i]);
static_cast<std::size_t>(ss.columns * ss.rows * PixelsPerTile) / 2,
ss.pixels.size());
//oxAssert(pixels.size() == pixelCnt, "Pixel count does not match rows and columns");
for (std::size_t i = 0; i < pixelCnt; ++i) {
const auto colorIdx1 = static_cast<uint8_t>(ss.pixels[i] & 0xF);
const auto colorIdx2 = static_cast<uint8_t>(ss.pixels[i] >> 4);
callback(i * 2 + 0, colorIdx1);
callback(i * 2 + 1, colorIdx2);
}
} else {
const auto pixelCnt = ox::min<std::size_t>(
static_cast<std::size_t>(ss.columns * ss.rows * PixelsPerTile),
ss.pixels.size());
for (std::size_t i = 0; i < pixelCnt; ++i) {
const auto p = ss.pixels[i];
callback(i, p);
}
} }
} }
void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept; void setPixel(TileSheet::SubSheet &ss, ox::Point const&pt, uint8_t palIdx) noexcept;
void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept; ox::Error setPixelCount(TileSheet::SubSheet &ss, std::size_t cnt) noexcept;
ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) noexcept;
/** /**
* Gets a count of the pixels in this sheet, and not that of its children. * Gets a count of the pixels in this sheet, and not that of its children.
* @param pBpp bits per pixel, need for knowing how to count the pixels
* @return a count of the pixels in this sheet * @return a count of the pixels in this sheet
*/ */
[[nodiscard]] [[nodiscard]]
unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept; unsigned pixelCnt(TileSheet::SubSheet const&ss) noexcept;
/** /**
* *
@ -365,7 +441,7 @@ unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept;
* @param pBpp * @param pBpp
* @param sz size of Subsheet in tiles (not pixels) * @param sz size of Subsheet in tiles (not pixels)
*/ */
ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const&sz) noexcept; ox::Error resizeSubsheet(TileSheet::SubSheet &ss, ox::Size const&sz) noexcept;
/** /**
* validateSubSheetIdx takes a SubSheetIdx and moves the index to the * validateSubSheetIdx takes a SubSheetIdx and moves the index to the
@ -522,6 +598,22 @@ OX_MODEL_BEGIN(TileSheetV4)
OX_MODEL_FIELD(subsheet) OX_MODEL_FIELD(subsheet)
OX_MODEL_END() OX_MODEL_END()
OX_MODEL_BEGIN(TileSheetV5::SubSheet)
OX_MODEL_FIELD(id)
OX_MODEL_FIELD(name)
OX_MODEL_FIELD(rows)
OX_MODEL_FIELD(columns)
OX_MODEL_FIELD(subsheets)
OX_MODEL_FIELD(pixels)
OX_MODEL_END()
OX_MODEL_BEGIN(TileSheetV5)
OX_MODEL_FIELD(bpp)
OX_MODEL_FIELD(idIt)
OX_MODEL_FIELD(defaultPalette)
OX_MODEL_FIELD(subsheet)
OX_MODEL_END()
OX_MODEL_BEGIN(CompactTileSheetV1) OX_MODEL_BEGIN(CompactTileSheetV1)
OX_MODEL_FIELD(bpp) OX_MODEL_FIELD(bpp)
OX_MODEL_FIELD(defaultPalette) OX_MODEL_FIELD(defaultPalette)

View File

@ -19,10 +19,10 @@ Context::Context(turbine::Context &tctx) noexcept: turbineCtx(tctx) {
ox::Error initGfx(Context &ctx, InitParams const&) noexcept; ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const&params) noexcept { ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params) noexcept {
auto ctx = ox::make_unique<Context>(tctx); auto ctx = ox::make_unique<Context>(tctx);
OX_RETURN_ERROR(initGfx(*ctx, params)); OX_RETURN_ERROR(initGfx(*ctx, params));
return ContextUPtr(std::move(ctx)); return ox::UPtr<Context>(std::move(ctx));
} }
keel::Context &keelCtx(Context &ctx) noexcept { keel::Context &keelCtx(Context &ctx) noexcept {

View File

@ -4,7 +4,6 @@
#include <ox/model/model.hpp> #include <ox/model/model.hpp>
#include <keel/asset.hpp>
#include <keel/module.hpp> #include <keel/module.hpp>
#include <nostalgia/gfx/palette.hpp> #include <nostalgia/gfx/palette.hpp>
@ -24,12 +23,13 @@ static class: public keel::Module {
TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter; TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter; TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter;
TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter; TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter;
TileSheetV4ToTileSheetV5Converter m_tileSheetV4ToTileSheetV5Converter;
TileSheetToCompactTileSheetConverter m_tileSheetToCompactTileSheetConverter; TileSheetToCompactTileSheetConverter m_tileSheetToCompactTileSheetConverter;
public: public:
[[nodiscard]] [[nodiscard]]
ox::String id() const noexcept override { ox::String id() const noexcept override {
return ox::String("net.drinkingtea.nostalgia.core"); return ox::String{"net.drinkingtea.nostalgia.gfx"};
} }
[[nodiscard]] [[nodiscard]]
@ -39,6 +39,7 @@ static class: public keel::Module {
keel::generateTypeDesc<TileSheetV2>, keel::generateTypeDesc<TileSheetV2>,
keel::generateTypeDesc<TileSheetV3>, keel::generateTypeDesc<TileSheetV3>,
keel::generateTypeDesc<TileSheetV4>, keel::generateTypeDesc<TileSheetV4>,
keel::generateTypeDesc<TileSheetV5>,
keel::generateTypeDesc<CompactTileSheetV1>, keel::generateTypeDesc<CompactTileSheetV1>,
keel::generateTypeDesc<PaletteV1>, keel::generateTypeDesc<PaletteV1>,
keel::generateTypeDesc<PaletteV2>, keel::generateTypeDesc<PaletteV2>,
@ -59,6 +60,7 @@ static class: public keel::Module {
&m_tileSheetV1ToTileSheetV2Converter, &m_tileSheetV1ToTileSheetV2Converter,
&m_tileSheetV2ToTileSheetV3Converter, &m_tileSheetV2ToTileSheetV3Converter,
&m_tileSheetV3ToTileSheetV4Converter, &m_tileSheetV3ToTileSheetV4Converter,
&m_tileSheetV4ToTileSheetV5Converter,
&m_tileSheetToCompactTileSheetConverter, &m_tileSheetToCompactTileSheetConverter,
}; };
} }
@ -92,6 +94,7 @@ static class: public keel::Module {
}, },
}; };
} }
} const mod; } const mod;
keel::Module const*keelModule() noexcept { keel::Module const*keelModule() noexcept {

View File

@ -133,6 +133,46 @@ ox::Error TileSheetV3ToTileSheetV4Converter::convert(
return {}; return {};
} }
void TileSheetV4ToTileSheetV5Converter::convertSubsheet(
int const bpp,
TileSheetV4::SubSheet &src,
TileSheetV5::SubSheet &dst,
SubSheetId &idIt) noexcept {
dst.id = idIt;
dst.name = std::move(src.name);
dst.columns = src.columns;
dst.rows = src.rows;
if (bpp == 4) {
dst.pixels.reserve(2 * src.pixels.size());
dst.pixels.resize(0);
for (auto const p : src.pixels) {
dst.pixels.emplace_back(static_cast<uint8_t>(p & 0xf));
dst.pixels.emplace_back(static_cast<uint8_t>(p >> 4));
}
oxAssert(dst.pixels.size() == src.pixels.size() *2, "mismatch");
} else {
dst.pixels = std::move(src.pixels);
}
++idIt;
dst.subsheets.resize(src.subsheets.size());
for (auto i = 0u; i < src.subsheets.size(); ++i) {
convertSubsheet(bpp, src.subsheets[i], dst.subsheets[i], idIt);
}
}
ox::Error TileSheetV4ToTileSheetV5Converter::convert(
keel::Context&,
TileSheetV4 &src,
TileSheetV5 &dst) const noexcept {
dst.bpp = src.bpp;
dst.idIt = src.idIt;
dst.defaultPalette = std::move(src.defaultPalette);
convertSubsheet(dst.bpp, src.subsheet, dst.subsheet, dst.idIt);
return {};
}
ox::Error TileSheetToCompactTileSheetConverter::convert( ox::Error TileSheetToCompactTileSheetConverter::convert(
keel::Context&, keel::Context&,
TileSheet &src, TileSheet &src,

View File

@ -56,6 +56,15 @@ class TileSheetV3ToTileSheetV4Converter: public keel::Converter<TileSheetV3, Til
ox::Error convert(keel::Context&, TileSheetV3 &src, TileSheetV4 &dst) const noexcept final; ox::Error convert(keel::Context&, TileSheetV3 &src, TileSheetV4 &dst) const noexcept final;
}; };
class TileSheetV4ToTileSheetV5Converter final: public keel::Converter<TileSheetV4, TileSheetV5> {
static void convertSubsheet(
int bpp,
TileSheetV4::SubSheet &src,
TileSheetV5::SubSheet &dst,
SubSheetId &idIt) noexcept;
ox::Error convert(keel::Context&, TileSheetV4 &src, TileSheetV5 &dst) const noexcept override;
};
class TileSheetToCompactTileSheetConverter: public keel::Converter<TileSheet, CompactTileSheet> { class TileSheetToCompactTileSheetConverter: public keel::Converter<TileSheet, CompactTileSheet> {
ox::Error convert(keel::Context&, TileSheet &src, CompactTileSheet &dst) const noexcept final; ox::Error convert(keel::Context&, TileSheet &src, CompactTileSheet &dst) const noexcept final;
}; };

View File

@ -23,10 +23,10 @@ Context::~Context() noexcept {
shutdownGfx(*this); shutdownGfx(*this);
} }
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const&params) noexcept { ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params) noexcept {
auto ctx = ox::make_unique<Context>(tctx, params); auto ctx = ox::make_unique<Context>(tctx, params);
OX_RETURN_ERROR(initGfx(*ctx, params)); OX_RETURN_ERROR(initGfx(*ctx, params));
return ContextUPtr(ctx.release()); return ox::UPtr<Context>(ctx.release());
} }
keel::Context &keelCtx(Context &ctx) noexcept { keel::Context &keelCtx(Context &ctx) noexcept {

View File

@ -650,7 +650,7 @@ ox::Error loadSpriteTileSheet(
CompactTileSheet const&ts, CompactTileSheet const&ts,
bool loadDefaultPalette) noexcept { bool loadDefaultPalette) noexcept {
OX_REQUIRE(tsd, normalizeTileSheet(ts)); OX_REQUIRE(tsd, normalizeTileSheet(ts));
oxTracef("nostalgia.core.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height); oxTracef("nostalgia.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height);
ctx.spriteBlocks.tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data()); ctx.spriteBlocks.tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
if (loadDefaultPalette) { if (loadDefaultPalette) {
OX_RETURN_ERROR(loadSpritePalette(ctx, ts.defaultPalette)); OX_RETURN_ERROR(loadSpritePalette(ctx, ts.defaultPalette));
@ -673,7 +673,7 @@ void setBgTile(
int row, int row,
BgTile const&tile) noexcept { BgTile const&tile) noexcept {
oxTracef( oxTracef(
"nostalgia.core.gfx.setBgTile", "nostalgia.gfx.setBgTile",
"bgIdx: {}, column: {}, row: {}, tile: {}, palBank: {}", "bgIdx: {}, column: {}, row: {}, tile: {}, palBank: {}",
bgIdx, column, row, tile.tileIdx, tile.palBank); bgIdx, column, row, tile.tileIdx, tile.palBank);
const auto z = static_cast<uint_t>(bgIdx); const auto z = static_cast<uint_t>(bgIdx);

View File

@ -28,12 +28,12 @@ ox::Error AddSubSheetCommand::redo() noexcept {
auto &parent = getSubSheet(m_img, m_parentIdx); auto &parent = getSubSheet(m_img, m_parentIdx);
if (m_addedSheets.size() < 2) { if (m_addedSheets.size() < 2) {
auto i = parent.subsheets.size(); auto i = parent.subsheets.size();
parent.subsheets.emplace_back(m_img.idIt++, ox::sfmt("Subsheet {}", i), 1, 1, m_img.bpp); parent.subsheets.emplace_back(m_img.idIt++, ox::sfmt("Subsheet {}", i), 1, 1);
} else { } else {
parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 0", parent.columns, parent.rows, std::move(parent.pixels)); parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 0", parent.columns, parent.rows, std::move(parent.pixels));
parent.rows = 0; parent.rows = 0;
parent.columns = 0; parent.columns = 0;
parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 1", 1, 1, m_img.bpp); parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 1", 1, 1);
} }
return {}; return {};
} }

View File

@ -38,7 +38,7 @@ CutPasteCommand::CutPasteCommand(
auto const dstPt = p.pt + dstStart; auto const dstPt = p.pt + dstStart;
if (dstPt.x <= dstEnd.x && dstPt.y <= dstEnd.y) { if (dstPt.x <= dstEnd.x && dstPt.y <= dstEnd.y) {
auto const idx = gfx::idx(ss, dstPt); auto const idx = gfx::idx(ss, dstPt);
m_changes.emplace_back(static_cast<uint32_t>(idx), p.colorIdx, getPixel(ss, m_img.bpp, idx)); m_changes.emplace_back(static_cast<uint32_t>(idx), p.colorIdx, getPixel(ss, idx));
} }
} }
} }
@ -46,7 +46,7 @@ CutPasteCommand::CutPasteCommand(
ox::Error CutPasteCommand::redo() noexcept { ox::Error CutPasteCommand::redo() noexcept {
auto &subsheet = getSubSheet(m_img, m_subSheetIdx); auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
for (const auto &c : m_changes) { for (const auto &c : m_changes) {
setPixel(subsheet, m_img.bpp, c.idx, static_cast<uint8_t>(c.newPalIdx)); subsheet.pixels[c.idx] = static_cast<uint8_t>(c.newPalIdx);
} }
return {}; return {};
} }
@ -54,7 +54,7 @@ ox::Error CutPasteCommand::redo() noexcept {
ox::Error CutPasteCommand::undo() noexcept { ox::Error CutPasteCommand::undo() noexcept {
auto &subsheet = getSubSheet(m_img, m_subSheetIdx); auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
for (const auto &c : m_changes) { for (const auto &c : m_changes) {
setPixel(subsheet, m_img.bpp, c.idx, static_cast<uint8_t>(c.oldPalIdx)); subsheet.pixels[c.idx] = static_cast<uint8_t>(c.oldPalIdx);
} }
return {}; return {};
} }

View File

@ -14,13 +14,13 @@ OX_MODEL_FWD_DECL(class TileSheetClipboard);
class TileSheetClipboard: public turbine::ClipboardObject<TileSheetClipboard> { class TileSheetClipboard: public turbine::ClipboardObject<TileSheetClipboard> {
public: public:
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.studio.TileSheetClipboard";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
OX_MODEL_FRIEND(TileSheetClipboard); OX_MODEL_FRIEND(TileSheetClipboard);
struct Pixel { struct Pixel {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard.Pixel"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.studio.TileSheetClipboard.Pixel";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
uint16_t colorIdx = 0; uint16_t colorIdx = 0;
ox::Point pt; ox::Point pt;

View File

@ -15,7 +15,7 @@ DrawCommand::DrawCommand(
m_subSheetIdx(std::move(subSheetIdx)), m_subSheetIdx(std::move(subSheetIdx)),
m_palIdx(palIdx) { m_palIdx(palIdx) {
auto &subsheet = getSubSheet(m_img, m_subSheetIdx); auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, m_img.bpp, idx)); m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, idx));
} }
DrawCommand::DrawCommand( DrawCommand::DrawCommand(
@ -28,20 +28,20 @@ DrawCommand::DrawCommand(
m_palIdx(palIdx) { m_palIdx(palIdx) {
auto &subsheet = getSubSheet(m_img, m_subSheetIdx); auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
for (auto const idx : idxList) { for (auto const idx : idxList) {
m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, m_img.bpp, idx)); m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, idx));
} }
} }
bool DrawCommand::append(std::size_t idx) noexcept { bool DrawCommand::append(std::size_t idx) noexcept {
auto &subsheet = getSubSheet(m_img, m_subSheetIdx); auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
if (m_changes.back().value->idx != idx && getPixel(subsheet, m_img.bpp, idx) != m_palIdx) { if (m_changes.back().value->idx != idx && getPixel(subsheet, idx) != m_palIdx) {
// duplicate entries are bad // duplicate entries are bad
auto existing = ox::find_if(m_changes.cbegin(), m_changes.cend(), [idx](auto const&c) { auto existing = ox::find_if(m_changes.cbegin(), m_changes.cend(), [idx](auto const&c) {
return c.idx == idx; return c.idx == idx;
}); });
if (existing == m_changes.cend()) { if (existing == m_changes.cend()) {
m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, m_img.bpp, idx)); m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, idx));
setPixel(subsheet, m_img.bpp, idx, static_cast<uint8_t>(m_palIdx)); subsheet.pixels[idx] = static_cast<uint8_t>(m_palIdx);
return true; return true;
} }
} }
@ -59,7 +59,7 @@ bool DrawCommand::append(ox::Vector<std::size_t> const&idxList) noexcept {
ox::Error DrawCommand::redo() noexcept { ox::Error DrawCommand::redo() noexcept {
auto &subsheet = getSubSheet(m_img, m_subSheetIdx); auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
for (auto const&c : m_changes) { for (auto const&c : m_changes) {
setPixel(subsheet, m_img.bpp, c.idx, static_cast<uint8_t>(m_palIdx)); subsheet.pixels[c.idx] = static_cast<uint8_t>(m_palIdx);
} }
return {}; return {};
} }
@ -67,7 +67,7 @@ ox::Error DrawCommand::redo() noexcept {
ox::Error DrawCommand::undo() noexcept { ox::Error DrawCommand::undo() noexcept {
auto &subsheet = getSubSheet(m_img, m_subSheetIdx); auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
for (auto const&c : m_changes) { for (auto const&c : m_changes) {
setPixel(subsheet, m_img.bpp, c.idx, static_cast<uint8_t>(c.oldPalIdx)); subsheet.pixels[c.idx] = static_cast<uint8_t>(c.oldPalIdx);
} }
return {}; return {};
} }

View File

@ -17,7 +17,7 @@ gfx::UpdateSubSheetCommand::UpdateSubSheetCommand(
m_sheet{getSubSheet(m_img, m_idx)} { m_sheet{getSubSheet(m_img, m_idx)} {
m_sheet = getSubSheet(m_img, m_idx); m_sheet = getSubSheet(m_img, m_idx);
m_sheet.name = std::move(name); m_sheet.name = std::move(name);
OX_THROW_ERROR(resizeSubsheet(m_sheet, m_img.bpp, {cols, rows})); OX_THROW_ERROR(resizeSubsheet(m_sheet, {cols, rows}));
} }
ox::Error UpdateSubSheetCommand::redo() noexcept { ox::Error UpdateSubSheetCommand::redo() noexcept {

View File

@ -16,7 +16,7 @@ namespace nostalgia::gfx {
namespace ig = studio::ig; namespace ig = studio::ig;
struct TileSheetEditorConfig { struct TileSheetEditorConfig {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetEditorConfig"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.studio.TileSheetEditorConfig";
static constexpr auto TypeVersion = 1; static constexpr auto TypeVersion = 1;
TileSheet::SubSheetIdx activeSubsheet{}; TileSheet::SubSheetIdx activeSubsheet{};
}; };
@ -47,8 +47,8 @@ static ox::Vector<uint32_t> normalizePixelSizes(
static ox::Vector<uint32_t> normalizePixelArrangement( static ox::Vector<uint32_t> normalizePixelArrangement(
ox::Vector<uint32_t> const&inPixels, ox::Vector<uint32_t> const&inPixels,
int cols, int const cols,
int scale) { int const scale) {
auto const scalePt = ox::Point{scale, scale}; auto const scalePt = ox::Point{scale, scale};
auto const width = cols * TileWidth; auto const width = cols * TileWidth;
auto const height = static_cast<int>(inPixels.size()) / width; auto const height = static_cast<int>(inPixels.size()) / width;

View File

@ -67,7 +67,7 @@ void TileSheetEditorModel::cut() {
iterateSelectionRows(*m_selection, [&](int const x, int const y) { iterateSelectionRows(*m_selection, [&](int const x, int const y) {
auto pt = ox::Point{x, y}; auto pt = ox::Point{x, y};
auto const idx = gfx::idx(s, pt); auto const idx = gfx::idx(s, pt);
auto const c = getPixel(s, m_img.bpp, idx); auto const c = getPixel(s, idx);
pt -= m_selection->a; pt -= m_selection->a;
cb->addPixel(pt, c); cb->addPixel(pt, c);
blankCb.addPixel(pt, 0); blankCb.addPixel(pt, 0);
@ -88,7 +88,7 @@ void TileSheetEditorModel::copy() {
auto pt = ox::Point{x, y}; auto pt = ox::Point{x, y};
const auto&s = activeSubSheet(); const auto&s = activeSubSheet();
const auto idx = gfx::idx(s, pt); const auto idx = gfx::idx(s, pt);
const auto c = getPixel(s, m_img.bpp, idx); const auto c = getPixel(s, idx);
pt -= m_selection->a; pt -= m_selection->a;
cb->addPixel(pt, c); cb->addPixel(pt, c);
}); });
@ -159,7 +159,7 @@ void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t const pal
const auto idx = gfx::idx(activeSubSheet, pt); const auto idx = gfx::idx(activeSubSheet, pt);
if (m_ongoingDrawCommand) { if (m_ongoingDrawCommand) {
m_updated = m_updated || m_ongoingDrawCommand->append(idx); m_updated = m_updated || m_ongoingDrawCommand->append(idx);
} else if (getPixel(activeSubSheet, m_img.bpp, idx) != palIdx) { } else if (getPixel(activeSubSheet, idx) != palIdx) {
pushCommand(ox::make<DrawCommand>( pushCommand(ox::make<DrawCommand>(
m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx))); m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx)));
} }
@ -206,7 +206,7 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept {
return; return;
} }
ox::Array<bool, PixelsPerTile> updateMap = {}; ox::Array<bool, PixelsPerTile> updateMap = {};
auto const oldColor = getPixel(activeSubSheet, m_img.bpp, pt); auto const oldColor = getPixel(activeSubSheet, pt);
getFillPixels(activeSubSheet, updateMap, pt, oldColor); getFillPixels(activeSubSheet, updateMap, pt, oldColor);
ox::Vector<std::size_t> idxList; ox::Vector<std::size_t> idxList;
auto i = gfx::idx(activeSubSheet, pt) / PixelsPerTile * PixelsPerTile; auto i = gfx::idx(activeSubSheet, pt) / PixelsPerTile * PixelsPerTile;
@ -219,7 +219,7 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept {
// do updates to sheet // do updates to sheet
if (m_ongoingDrawCommand) { if (m_ongoingDrawCommand) {
m_updated = m_updated || m_ongoingDrawCommand->append(idxList); m_updated = m_updated || m_ongoingDrawCommand->append(idxList);
} else if (getPixel(activeSubSheet, m_img.bpp, pt) != palIdx) { } else if (getPixel(activeSubSheet, pt) != palIdx) {
pushCommand(ox::make<DrawCommand>(m_img, m_activeSubsSheetIdx, idxList, palIdx)); pushCommand(ox::make<DrawCommand>(m_img, m_activeSubsSheetIdx, idxList, palIdx));
} }
} }
@ -298,7 +298,7 @@ void TileSheetEditorModel::getFillPixels(
int const oldColor) const noexcept { int const oldColor) const noexcept {
auto const idx = ptToIdx(pt, activeSubSheet.columns); auto const idx = ptToIdx(pt, activeSubSheet.columns);
auto const relIdx = idx % PixelsPerTile; auto const relIdx = idx % PixelsPerTile;
if (pixels[relIdx] || getPixel(activeSubSheet, m_img.bpp, idx) != oldColor) { if (pixels[relIdx] || getPixel(activeSubSheet, idx) != oldColor) {
return; return;
} }
// mark pixels to update // mark pixels to update

View File

@ -127,6 +127,7 @@ void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept {
auto const height = subSheet.rows * TileHeight; auto const height = subSheet.rows * TileHeight;
auto const pixels = static_cast<size_t>(width) * static_cast<size_t>(height); auto const pixels = static_cast<size_t>(width) * static_cast<size_t>(height);
auto const vboLen = static_cast<size_t>(s_programSrc.vboLen); auto const vboLen = static_cast<size_t>(s_programSrc.vboLen);
oxAssert(subSheet.pixels.size() == pixels, "incorrect pixels");
m_bufferSet.vertices.resize(pixels * vboLen); m_bufferSet.vertices.resize(pixels * vboLen);
m_bufferSet.elements.resize(pixels * VertexEboLength); m_bufferSet.elements.resize(pixels * VertexEboLength);
// set pixels // set pixels

View File

@ -28,21 +28,20 @@ static TileSheet::SubSheet const *getSubsheet(TileSheet::SubSheet const&ss, SubS
} }
[[nodiscard]] [[nodiscard]]
static size_t getTileCnt(TileSheet::SubSheet const&ss, int const bpp) noexcept { static size_t getTileCnt(TileSheet::SubSheet const&ss) noexcept {
if (ss.subsheets.empty()) { if (ss.subsheets.empty()) {
auto const bytesPerTile = bpp == 4 ? 32u : 64u; return ss.pixels.size() / PixelsPerTile;
return ss.pixels.size() / bytesPerTile;
} else { } else {
size_t out{}; size_t out{};
for (auto const&child: ss.subsheets) { for (auto const&child: ss.subsheets) {
out += getTileCnt(child, bpp); out += getTileCnt(child);
} }
return out; return out;
} }
} }
size_t getTileCnt(TileSheet const&ts) noexcept { size_t getTileCnt(TileSheet const&ts) noexcept {
return getTileCnt(ts.subsheet, ts.bpp); return getTileCnt(ts.subsheet);
} }
TileSheet::SubSheet const *getSubsheet(TileSheet const&ts, SubSheetId const id) noexcept { TileSheet::SubSheet const *getSubsheet(TileSheet const&ts, SubSheetId const id) noexcept {
@ -52,44 +51,35 @@ TileSheet::SubSheet const *getSubsheet(TileSheet const&ts, SubSheetId const id)
static ox::Optional<size_t> getPixelIdx( static ox::Optional<size_t> getPixelIdx(
TileSheet::SubSheet const&ss, TileSheet::SubSheet const&ss,
SubSheetId const id, SubSheetId const id,
size_t &idx, size_t &idx) noexcept {
int8_t const bpp) noexcept {
for (auto const&child: ss.subsheets) { for (auto const&child: ss.subsheets) {
if (child.id == id) { if (child.id == id) {
return ox::Optional<size_t>(ox::in_place, idx); return ox::Optional<size_t>(ox::in_place, idx);
} }
if (auto out = getPixelIdx(child, id, idx, bpp)) { if (auto out = getPixelIdx(child, id, idx)) {
return out; return out;
} }
idx += pixelCnt(child, bpp); idx += pixelCnt(child);
} }
return ox::Optional<size_t>{}; return ox::Optional<size_t>{};
} }
ox::Optional<size_t> getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept { ox::Optional<size_t> getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept {
size_t idx{}; size_t idx{};
auto const out = getPixelIdx(ts.subsheet, id, idx, ts.bpp); auto const out = getPixelIdx(ts.subsheet, id, idx);
return out ? ox::Optional<size_t>{ox::in_place, *out / PixelsPerTile} : out; return out ? ox::Optional<size_t>{ox::in_place, *out / PixelsPerTile} : out;
} }
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept { uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t const idx) noexcept {
if (idx & 1) {
return ss.pixels[idx / 2] >> 4;
} else {
return ss.pixels[idx / 2] & 0b0000'1111;
}
}
uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept {
return ss.pixels[idx]; return ss.pixels[idx];
} }
uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, std::size_t idx) noexcept { uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t const idx) noexcept {
if (pBpp == 4) { return ss.pixels[idx];
return getPixel4Bpp(ss, idx); }
} else {
return getPixel8Bpp(ss, idx); uint8_t getPixel(TileSheet::SubSheet const&ss, std::size_t const idx) noexcept {
} return ss.pixels[idx];
} }
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept { uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept {
@ -102,73 +92,48 @@ uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept
return getPixel8Bpp(ss, idx); return getPixel8Bpp(ss, idx);
} }
uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, ox::Point const&pt) noexcept { uint8_t getPixel(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept {
const auto idx = ptToIdx(pt, ss.columns); const auto idx = ptToIdx(pt, ss.columns);
return getPixel(ss, pBpp, idx); return getPixel(ss, idx);
} }
static void setPixel(ox::Vector<uint8_t> &pixels, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept { static void setPixel(
auto &pixel = pixels[static_cast<std::size_t>(idx / 2)]; ox::Vector<uint8_t> &pixels,
if (pBpp == 4) { int const columns,
if (idx & 1) { ox::Point const&pt,
pixel = static_cast<uint8_t>((pixel & 0b0000'1111) | (palIdx << 4)); uint8_t const palIdx) noexcept {
} else {
pixel = (pixel & 0b1111'0000) | (palIdx);
}
} else {
pixel = palIdx;
}
}
void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept {
setPixel(ss.pixels, pBpp, idx, palIdx);
}
static void setPixel(ox::Vector<uint8_t> &pixels, int columns, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept {
const auto idx = ptToIdx(pt, columns); const auto idx = ptToIdx(pt, columns);
setPixel(pixels, pBpp, idx, palIdx); pixels[idx] = palIdx;
} }
void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept { void setPixel(TileSheet::SubSheet &ss, ox::Point const&pt, uint8_t const palIdx) noexcept {
const auto idx = ptToIdx(pt, ss.columns); const auto idx = ptToIdx(pt, ss.columns);
setPixel(ss, pBpp, idx, palIdx); ss.pixels[idx] = palIdx;
} }
static ox::Error setPixelCount(ox::Vector<uint8_t> &pixels, int8_t pBpp, std::size_t cnt) noexcept { static ox::Error setPixelCount(ox::Vector<uint8_t> &pixels, std::size_t const cnt) noexcept {
size_t sz{}; pixels.reserve(cnt);
switch (pBpp) { pixels.resize(cnt);
case 4:
sz = cnt / 2;
break;
case 8:
sz = cnt;
break;
default:
return ox::Error(1, "Invalid pBpp used for TileSheet::SubSheet::setPixelCount");
}
pixels.reserve(sz);
pixels.resize(sz);
return {}; return {};
} }
ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) noexcept { ox::Error setPixelCount(TileSheet::SubSheet &ss, std::size_t const cnt) noexcept {
return setPixelCount(ss.pixels, pBpp, cnt); return setPixelCount(ss.pixels, cnt);
} }
unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept { unsigned pixelCnt(TileSheet::SubSheet const&ss) noexcept {
const auto pixelsSize = static_cast<unsigned>(ss.pixels.size()); return static_cast<unsigned>(ss.pixels.size());
return pBpp == 4 ? pixelsSize * 2 : pixelsSize;
} }
ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const&sz) noexcept { ox::Error resizeSubsheet(TileSheet::SubSheet &ss, ox::Size const&sz) noexcept {
ox::Vector<uint8_t> out; ox::Vector<uint8_t> out;
OX_RETURN_ERROR(setPixelCount(out, pBpp, static_cast<size_t>(sz.width * sz.height) * PixelsPerTile)); OX_RETURN_ERROR(setPixelCount(out, static_cast<size_t>(sz.width * sz.height) * PixelsPerTile));
auto const w = ox::min<int32_t>(ss.columns, sz.width) * TileWidth; auto const w = ox::min<int32_t>(ss.columns, sz.width) * TileWidth;
auto const h = ox::min<int32_t>(ss.rows, sz.height) * TileHeight; auto const h = ox::min<int32_t>(ss.rows, sz.height) * TileHeight;
for (auto x = 0; x < w; ++x) { for (auto x = 0; x < w; ++x) {
for (auto y = 0; y < h; ++y) { for (auto y = 0; y < h; ++y) {
auto const palIdx = getPixel(ss, pBpp, {x, y}); auto const palIdx = getPixel(ss, {x, y});
setPixel(out, sz.width, pBpp, {x, y}, palIdx); setPixel(out, sz.width, {x, y}, palIdx);
} }
} }
ss.columns = sz.width; ss.columns = sz.width;
@ -177,7 +142,7 @@ ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const&sz
return {}; return {};
} }
ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept { ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId const pId) noexcept {
if (ss.id == pId) { if (ss.id == pId) {
return ox::StringView(ss.name); return ox::StringView(ss.name);
} }
@ -193,7 +158,7 @@ ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId p
TileSheet::SubSheetIdx validateSubSheetIdx( TileSheet::SubSheetIdx validateSubSheetIdx(
TileSheet::SubSheetIdx &&pIdx, TileSheet::SubSheetIdx &&pIdx,
std::size_t pIdxIt, std::size_t const pIdxIt,
TileSheet::SubSheet const&pSubsheet) noexcept { TileSheet::SubSheet const&pSubsheet) noexcept {
if (pIdxIt >= pIdx.size()) { if (pIdxIt >= pIdx.size()) {
return std::move(pIdx); return std::move(pIdx);
@ -216,9 +181,9 @@ TileSheet::SubSheetIdx validateSubSheetIdx(TileSheet const&ts, TileSheet::SubShe
return validateSubSheetIdx(std::move(idx), 0, ts.subsheet); return validateSubSheetIdx(std::move(idx), 0, ts.subsheet);
} }
const TileSheet::SubSheet &getSubSheet( TileSheet::SubSheet const&getSubSheet(
TileSheet::SubSheetIdx const&idx, TileSheet::SubSheetIdx const&idx,
std::size_t idxIt, std::size_t const idxIt,
TileSheet::SubSheet const&pSubsheet) noexcept { TileSheet::SubSheet const&pSubsheet) noexcept {
if (idxIt == idx.size()) { if (idxIt == idx.size()) {
return pSubsheet; return pSubsheet;
@ -232,7 +197,7 @@ const TileSheet::SubSheet &getSubSheet(
TileSheet::SubSheet &getSubSheet( TileSheet::SubSheet &getSubSheet(
TileSheet::SubSheetIdx const&idx, TileSheet::SubSheetIdx const&idx,
std::size_t idxIt, std::size_t const idxIt,
TileSheet::SubSheet &pSubsheet) noexcept { TileSheet::SubSheet &pSubsheet) noexcept {
if (idxIt == idx.size()) { if (idxIt == idx.size()) {
return pSubsheet; return pSubsheet;
@ -251,10 +216,10 @@ TileSheet::SubSheet &getSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx
ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept { ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept {
auto &parent = getSubSheet(ts, idx); auto &parent = getSubSheet(ts, idx);
if (parent.subsheets.size() < 2) { if (parent.subsheets.size() < 2) {
parent.subsheets.emplace_back(++ts.idIt, ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1, ts.bpp); parent.subsheets.emplace_back(++ts.idIt, ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1);
} else { } else {
parent.subsheets.emplace_back(++ts.idIt, "Subsheet 0", parent.columns, parent.rows, ts.bpp); parent.subsheets.emplace_back(++ts.idIt, "Subsheet 0", parent.columns, parent.rows);
parent.subsheets.emplace_back(++ts.idIt, "Subsheet 1", 1, 1, ts.bpp); parent.subsheets.emplace_back(++ts.idIt, "Subsheet 1", 1, 1);
} }
return ox::Error(0); return ox::Error(0);
} }
@ -262,7 +227,7 @@ ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept
ox::Error rmSubSheet( ox::Error rmSubSheet(
TileSheet &ts, TileSheet &ts,
TileSheet::SubSheetIdx const&idx, TileSheet::SubSheetIdx const&idx,
std::size_t idxIt, std::size_t const idxIt,
TileSheet::SubSheet &pSubsheet) noexcept { TileSheet::SubSheet &pSubsheet) noexcept {
if (idxIt == idx.size() - 1) { if (idxIt == idx.size() - 1) {
return pSubsheet.subsheets.erase(idx[idxIt]).error; return pSubsheet.subsheets.erase(idx[idxIt]).error;
@ -315,18 +280,12 @@ uint8_t getPixel8Bpp(
ox::Pair<uint8_t> get2Pixels4Bpp( ox::Pair<uint8_t> get2Pixels4Bpp(
CompactTileSheet const&ts, CompactTileSheet const&ts,
size_t const idx) noexcept { size_t const idx) noexcept {
oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp"); return get2Pixels8Bpp(ts, idx);
auto const out = ts.pixels[idx / 2];
return {
static_cast<uint8_t>(out & 0x0f),
static_cast<uint8_t>(out >> 4),
};
} }
ox::Pair<uint8_t> get2Pixels8Bpp( ox::Pair<uint8_t> get2Pixels8Bpp(
CompactTileSheet const&ts, CompactTileSheet const&ts,
size_t const idx) noexcept { size_t const idx) noexcept {
oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
return { return {
static_cast<uint8_t>(ts.pixels[idx]), static_cast<uint8_t>(ts.pixels[idx]),
static_cast<uint8_t>(ts.pixels[idx + 1]), static_cast<uint8_t>(ts.pixels[idx + 1]),
@ -336,7 +295,7 @@ ox::Pair<uint8_t> get2Pixels8Bpp(
static ox::Result<SubSheetId> getIdFor( static ox::Result<SubSheetId> getIdFor(
TileSheet::SubSheet const&ss, TileSheet::SubSheet const&ss,
ox::SpanView<ox::StringView> const&pNamePath, ox::SpanView<ox::StringView> const&pNamePath,
std::size_t pIt = 0) noexcept { std::size_t const pIt = 0) noexcept {
for (auto &sub : ss.subsheets) { for (auto &sub : ss.subsheets) {
if (sub.name == pNamePath[pIt]) { if (sub.name == pNamePath[pIt]) {
if (pIt == pNamePath.size()) { if (pIt == pNamePath.size()) {
@ -358,8 +317,7 @@ ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::StringViewCR path) noexc
static ox::Result<uint32_t> getTileOffset( static ox::Result<uint32_t> getTileOffset(
TileSheet::SubSheet const&ss, TileSheet::SubSheet const&ss,
ox::SpanView<ox::StringView> const&pNamePath, ox::SpanView<ox::StringView> const&pNamePath,
int8_t pBpp, std::size_t const pIt = 0,
std::size_t pIt = 0,
uint32_t pCurrentTotal = 0) noexcept { uint32_t pCurrentTotal = 0) noexcept {
// pIt == pNamePath.size() - 1 && // pIt == pNamePath.size() - 1 &&
if (ss.name != pNamePath[pIt]) { if (ss.name != pNamePath[pIt]) {
@ -370,44 +328,52 @@ static ox::Result<uint32_t> getTileOffset(
} }
for (auto &sub : ss.subsheets) { for (auto &sub : ss.subsheets) {
auto [offset, err] = getTileOffset( auto [offset, err] = getTileOffset(
sub, pNamePath, pBpp, pIt + 1, pCurrentTotal); sub, pNamePath, pIt + 1, pCurrentTotal);
if (!err) { if (!err) {
return offset; return offset;
} }
// Possible bug? Shoud this be usinga a recursive version of // Possible bug? Should this be using a recursive version of
// pixelCnt will count pixels in subsheets of sub as well. // pixelCnt will count pixels in subsheets of sub as well.
pCurrentTotal += pixelCnt(sub, pBpp) / PixelsPerTile; pCurrentTotal += pixelCnt(sub) / PixelsPerTile;
} }
return ox::Error(1, "SubSheet not found"); return ox::Error(1, "SubSheet not found");
} }
ox::Result<uint32_t> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept { ox::Result<uint32_t> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept {
return gfx::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.'), ts.bpp); return gfx::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.'));
} }
ox::Result<ox::StringView> getNameFor(TileSheet &ts, SubSheetId pId) noexcept { ox::Result<ox::StringView> getNameFor(TileSheet &ts, SubSheetId const pId) noexcept {
return gfx::getNameFor(ts.subsheet, pId); return gfx::getNameFor(ts.subsheet, pId);
} }
ox::Result<ox::StringView> getNameFor(TileSheet const&ts, SubSheetId pId) noexcept { ox::Result<ox::StringView> getNameFor(TileSheet const&ts, SubSheetId const pId) noexcept {
return gfx::getNameFor(ts.subsheet, pId); return gfx::getNameFor(ts.subsheet, pId);
} }
static void readPixelsTo(TileSheet::SubSheet &ss, ox::Vector<uint8_t> &pPixels) noexcept { static void readPixelsTo(TileSheet::SubSheet &ss, int const pBpp, ox::Vector<uint8_t> &pPixels) noexcept {
if (!ss.subsheets.empty()) { if (!ss.subsheets.empty()) {
for (auto &s: ss.subsheets) { for (auto &s: ss.subsheets) {
readPixelsTo(s, pPixels); readPixelsTo(s, pBpp, pPixels);
} }
} else { } else {
for (auto p : ss.pixels) { if (pBpp == 4) {
for (size_t i{}; i < ss.pixels.size() - 1; i += 2) {
auto const p1 = ss.pixels[i];
auto const p2 = ss.pixels[i + 1];
pPixels.emplace_back(static_cast<uint8_t>(p1 | (p2 << 4)));
}
} else {
for (auto const p : ss.pixels) {
pPixels.emplace_back(p); pPixels.emplace_back(p);
} }
} }
}
} }
ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept { ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept {
ox::Vector<uint8_t> out; ox::Vector<uint8_t> out;
readPixelsTo(ts.subsheet, out); readPixelsTo(ts.subsheet, ts.bpp, out);
return out; return out;
} }
@ -415,7 +381,7 @@ ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept {
ox::Vector<uint32_t> resizeTileSheetData( ox::Vector<uint32_t> resizeTileSheetData(
ox::Vector<uint32_t> const&srcPixels, ox::Vector<uint32_t> const&srcPixels,
ox::Size const&srcSize, ox::Size const&srcSize,
int scale) noexcept { int const scale) noexcept {
ox::Vector<uint32_t> dst; ox::Vector<uint32_t> dst;
auto dstWidth = srcSize.width * scale; auto dstWidth = srcSize.width * scale;
auto dstHeight = srcSize.height * scale; auto dstHeight = srcSize.height * scale;

View File

@ -15,7 +15,7 @@ namespace nostalgia::scene {
class SceneEditorView { class SceneEditorView {
private: private:
gfx::ContextUPtr m_cctx; ox::UPtr<gfx::Context> m_cctx;
SceneStatic const&m_sceneStatic; SceneStatic const&m_sceneStatic;
Scene m_scene; Scene m_scene;
glutils::FrameBuffer m_frameBuffer; glutils::FrameBuffer m_frameBuffer;

View File

@ -17,11 +17,7 @@ namespace turbine {
class Context; class Context;
struct ContextDeleter { void safeDelete(Context *p);
void operator()(Context *p) noexcept;
};
using ContextUPtr = ox::UPtr<Context, ContextDeleter>;
void shutdown(Context &ctx) noexcept; void shutdown(Context &ctx) noexcept;

View File

@ -16,9 +16,9 @@ namespace turbine {
using TimeMs = uint64_t; using TimeMs = uint64_t;
ox::Result<ContextUPtr> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept; ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept;
ox::Result<ContextUPtr> init(ox::StringViewCR fsPath, ox::StringViewCR appName) noexcept; ox::Result<ox::UPtr<Context>> init(ox::StringViewCR fsPath, ox::StringViewCR appName) noexcept;
ox::Error run(Context &ctx) noexcept; ox::Error run(Context &ctx) noexcept;

View File

@ -6,8 +6,8 @@
namespace turbine { namespace turbine {
void ContextDeleter::operator()(Context *p) noexcept { void safeDelete(Context *p) {
ox::safeDelete(p); delete p;
} }
keel::Context const&keelCtx(Context const&ctx) noexcept { keel::Context const&keelCtx(Context const&ctx) noexcept {

View File

@ -58,7 +58,7 @@ OX_ALLOW_UNSAFE_BUFFERS_END
return ox::Error(1); return ox::Error(1);
} }
ox::Result<ContextUPtr> init( ox::Result<ox::UPtr<Context>> init(
ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept { ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept {
auto ctx = ox::make_unique<Context>(); auto ctx = ox::make_unique<Context>();
OX_RETURN_ERROR(keel::init(ctx->keelCtx, std::move(fs), appName)); OX_RETURN_ERROR(keel::init(ctx->keelCtx, std::move(fs), appName));
@ -68,7 +68,7 @@ ox::Result<ContextUPtr> init(
OX_RETURN_ERROR(initGfx(*ctx)); OX_RETURN_ERROR(initGfx(*ctx));
initTimer(); initTimer();
initIrq(); initIrq();
return ox::UPtr<turbine::Context, ContextDeleter>(std::move(ctx)); return ox::UPtr<Context>(std::move(ctx));
} }
void shutdown(Context&) noexcept { void shutdown(Context&) noexcept {

View File

@ -8,8 +8,8 @@
namespace turbine { namespace turbine {
void ContextDeleter::operator()(Context *p) noexcept { void safeDelete(Context *p) {
ox::safeDelete(p); delete p;
} }
keel::Context const&keelCtx(Context const&ctx) noexcept { keel::Context const&keelCtx(Context const&ctx) noexcept {

View File

@ -40,7 +40,7 @@ static void draw(GLFWwindow *window, int, int) noexcept {
draw(ctx); draw(ctx);
} }
ox::Result<ContextUPtr> init( ox::Result<ox::UPtr<Context>> init(
ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept { ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept {
auto ctx = ox::make_unique<Context>(); auto ctx = ox::make_unique<Context>();
OX_RETURN_ERROR(keel::init(ctx->keelCtx, std::move(fs), appName)); OX_RETURN_ERROR(keel::init(ctx->keelCtx, std::move(fs), appName));
@ -51,10 +51,10 @@ ox::Result<ContextUPtr> init(
OX_RETURN_ERROR(initGfx(*ctx)); OX_RETURN_ERROR(initGfx(*ctx));
glfwSetWindowSizeCallback(ctx->window, draw); glfwSetWindowSizeCallback(ctx->window, draw);
ctx->mandatoryRefreshPeriodEnd = ticksMs(*ctx) + config::MandatoryRefreshPeriod; ctx->mandatoryRefreshPeriodEnd = ticksMs(*ctx) + config::MandatoryRefreshPeriod;
return ox::UPtr<Context, ContextDeleter>(ctx.release()); return ox::UPtr<Context>(ctx.release());
} }
static void tickFps(Context &ctx, uint64_t nowMs) noexcept { static void tickFps(Context &ctx, uint64_t const nowMs) noexcept {
++ctx.draws; ++ctx.draws;
if (ctx.draws >= 500) { if (ctx.draws >= 500) {
auto const duration = static_cast<double>(nowMs - ctx.prevFpsCheckTime) / 1000.0; auto const duration = static_cast<double>(nowMs - ctx.prevFpsCheckTime) / 1000.0;
@ -114,7 +114,7 @@ TimeMs ticksMs(Context const&ctx) noexcept {
return static_cast<TimeMs>(now) - ctx.startTime; return static_cast<TimeMs>(now) - ctx.startTime;
} }
bool buttonDown(Context const&ctx, Key key) noexcept { bool buttonDown(Context const&ctx, Key const key) noexcept {
return (ctx.keysDown >> static_cast<int>(key)) & 1; return (ctx.keysDown >> static_cast<int>(key)) & 1;
} }

View File

@ -8,7 +8,7 @@
namespace turbine { namespace turbine {
ox::Result<ContextUPtr> init(ox::StringViewCR fsPath, ox::StringViewCR appName) noexcept { ox::Result<ox::UPtr<Context>> init(ox::StringViewCR fsPath, ox::StringViewCR appName) noexcept {
OX_REQUIRE_M(fs, keel::loadRomFs(fsPath)); OX_REQUIRE_M(fs, keel::loadRomFs(fsPath));
return init(std::move(fs), appName); return init(std::move(fs), appName);
} }