Squashed 'deps/nostalgia/' changes from 3c7652ef..161640fa

161640fa [nostalgia] Cleanup
e42126c9 [nostalgia/core] Improve TileSheet validation, add repair
36942cca [nostalgia,olympic] Replace SpanView with Span<const T>
b14f1d50 [ox] Replace SpanView with Span<const T>
1bf4f246 [applib] Make run take args as a SpanView
edda8e01 [ox/clargs] Add constructor that takes a SpanView
3308b4dd [ox/std] Add missing + and += operators to Span
27f4703a [teagba] Suppress warnings for unsafe buffers
6af00d9a [nostalgia] Enable warnings for unsafe buffers
86b9f931 [olympic] Enable warnings for unsafe buffers
a0ed1b3f [ox/std] Fix Span raw array constructor
8dad624b [studio/applib] Cleanup
dc6605fd [keel] Add missing error checking to pack
c78d3cf6 [ox] Add more unsafe buffer exceptions
cee4f65d [ox/std] Replace an unsafe buffer
cd3eeeef [ox/fs] Suppress unsafe buffer warnings
287d42f2 [ox/clargs] Cleanup
dbbaaa46 [ox/clargs] Enable unsafe buffer warnings
9b8a8c4e [ox/std] Enable unsafe buffer warnings
e44fa288 [cityhash] Add pragmas to ignore unsafe buffer warnings
e13c6e81 [ox/std] Remove raw char* CharBufferWriter constructor
cb55b31a [ox/std] Cleanup
ab3f9e16 [ox/std] Make Span access check message consistent with other messages
8f25ef96 [ox/std] Make CharBufferWriter constructor take a Span
e13eebaf [ox/std] Cleanup an unsafe buffer
114f5c66 [ox/std] Add overflow checking to SpanIterator
df44fe23 [keel] Cleanup
72f4db3d [nostalgia/core/studio] Fix paste command to never paste beyond target dimensions
8a9ff971 [nostalgia/core] Fix resizeSubsheet to work for both growing and shrinking
5a8da59d [keel] Fix readAsset to actually return asset
afa3a13d [keel] Cleanup
6522cf8a [keel] Add ensureValid call to readAsset
f772e48b [ox] Add Vector/Array/Span overflow checking
13bfe881 [nostalgia/core] Fix resizeSubsheet array overflow
50254754 Merge commit '9e11019b87ba27d1dac9e097dc212a126e404218'
bfe890ae [ox] Fix typo in docs
ab5bc1ad [ox/std] Remove oxRequireT and oxRequireMT
abf7548a [nostalgia/core] Add missing include
e2682b5e [studio/modlib] Add missing include
792ad414 [nostalgia] Remove .vs dir

git-subtree-dir: deps/nostalgia
git-subtree-split: 161640fa11986677dc2e1da6ffd4575e38ab31ad
This commit is contained in:
2024-12-04 19:55:17 -06:00
parent 9e11019b87
commit 4ccdfc3a6e
101 changed files with 842 additions and 731 deletions

View File

@@ -121,11 +121,20 @@ ox::Error loadSpritePalette(
CompactPalette const&palette,
size_t page = 0) noexcept;
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
ox::StringViewCR palettePath) noexcept;
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
ox::FileAddress const&paletteAddr) noexcept;
ox::Error loadSpritePalette(
Context &ctx,
ox::StringViewCR palettePath) noexcept;
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept;
@@ -143,6 +152,14 @@ ox::Error loadBgTileSheet(
size_t srcTileIdx,
size_t tileCnt) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::StringViewCR tsPath,
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
@@ -157,6 +174,12 @@ ox::Error loadBgTileSheet(
CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank = {}) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::StringViewCR tilesheetPath,
ox::Optional<unsigned> const&paletteBank) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
@@ -168,6 +191,11 @@ ox::Error loadSpriteTileSheet(
CompactTileSheet const&ts,
bool loadDefaultPalette) noexcept;
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::StringViewCR tilesheetPath,
bool loadDefaultPalette = false) noexcept;
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,

View File

@@ -4,6 +4,8 @@
#pragma once
#include <ox/std/types.hpp>
namespace nostalgia::core {
struct InitParams {
@@ -12,4 +14,4 @@ struct InitParams {
uint_t glBlocksPerSprite = 64;
};
}
}

View File

@@ -33,7 +33,14 @@ struct TileSheetV1 {
[[nodiscard]]
constexpr bool valid(TileSheetV1 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
auto const bytes = static_cast<size_t>(ts.columns * ts.rows * PixelsPerTile) / (ts.bpp == 4 ? 2 : 1);
return (ts.bpp == 4 || ts.bpp == 8) && ts.pixels.size() == bytes;
}
constexpr ox::Error repair(TileSheetV1 &ts, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ts.columns * ts.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
ts.pixels.resize(bytes);
return {};
}
@@ -65,9 +72,34 @@ struct TileSheetV2 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV2::SubSheet const&ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
[bpp, bytes](TileSheetV2::SubSheet const&s) {
return bytes == s.pixels.size() && valid(s, bpp);
});
}
[[nodiscard]]
constexpr bool valid(TileSheetV2 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp);
}
constexpr void repair(TileSheetV2::SubSheet &ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
ss.pixels.resize(bytes);
for (auto &s : ss.subsheets) {
repair(s, bpp);
}
}
constexpr ox::Error repair(TileSheetV2 &ts) noexcept {
if (ts.bpp != 4 && ts.bpp != 8) {
return OxError(1, "Unable to repair TileSheet");
}
repair(ts.subsheet, ts.bpp);
return {};
}
@@ -110,9 +142,34 @@ struct TileSheetV3 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV3::SubSheet const&ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
[bpp, bytes](TileSheetV3::SubSheet const&s) {
return bytes == s.pixels.size() && valid(s, bpp);
});
}
[[nodiscard]]
constexpr bool valid(TileSheetV3 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp);
}
constexpr void repair(TileSheetV3::SubSheet &ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
ss.pixels.resize(bytes);
for (auto &s : ss.subsheets) {
repair(s, bpp);
}
}
constexpr ox::Error repair(TileSheetV3 &ts) noexcept {
if (ts.bpp != 4 && ts.bpp != 8) {
return OxError(1, "Unable to repair TileSheet");
}
repair(ts.subsheet, ts.bpp);
return {};
}
@@ -173,9 +230,34 @@ struct TileSheetV4 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV4::SubSheet const&ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
[bpp, bytes](TileSheetV4::SubSheet const&s) {
return bytes == s.pixels.size() && valid(s, bpp);
});
}
[[nodiscard]]
constexpr bool valid(TileSheetV4 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
return (ts.bpp == 4 || ts.bpp == 8) && valid(ts.subsheet, ts.bpp);
}
constexpr void repair(TileSheetV4::SubSheet &ss, int bpp) noexcept {
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
ss.pixels.resize(bytes);
for (auto &s : ss.subsheets) {
repair(s, bpp);
}
}
constexpr ox::Error repair(TileSheetV4 &ts) noexcept {
if (ts.bpp != 4 && ts.bpp != 8) {
return OxError(1, "Unable to repair TileSheet");
}
repair(ts.subsheet, ts.bpp);
return {};
}

View File

@@ -17,6 +17,8 @@
#include "context.hpp"
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
namespace nostalgia::core {
static constexpr auto SpriteCount = 128;
@@ -283,3 +285,5 @@ uint_t spriteCount(Context&) noexcept {
}
}
OX_ALLOW_UNSAFE_BUFFERS_END

View File

@@ -25,7 +25,9 @@ using namespace nostalgia::core;
void panic(const char *file, int line, const char *panicMsg, ox::Error const&err) noexcept {
// reset heap to make sure we have enough memory to allocate context data
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END);
OX_ALLOW_UNSAFE_BUFFERS_END
auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap();
auto ctx = init(*tctx).unwrap();
std::ignore = initGfx(*ctx, {});

View File

@@ -18,6 +18,14 @@ int tileRows(Context&) noexcept {
return GbaTileRows;
}
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
ox::StringViewCR palettePath) noexcept {
oxRequire(pal, keel::readObj<CompactPalette>(keelCtx(ctx), palettePath));
return loadBgPalette(ctx, palBank, *pal, 0);
}
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,
@@ -26,6 +34,13 @@ ox::Error loadBgPalette(
return loadBgPalette(ctx, palBank, *pal, 0);
}
ox::Error loadSpritePalette(
Context &ctx,
ox::StringViewCR palettePath) noexcept {
oxRequire(pal, keel::readObj<CompactPalette>(keelCtx(ctx), palettePath));
return loadSpritePalette(ctx, *pal, 0);
}
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
@@ -44,6 +59,26 @@ ox::Error loadBgTileSheet(
return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::StringViewCR tsPath,
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept {
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tsPath));
return loadBgTileSheet(ctx, cbb, *ts, dstTileIdx, srcTileIdx, tileCnt);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::StringViewCR tilesheetPath,
ox::Optional<unsigned> const&paletteBank) noexcept {
oxRequire(ts, keel::readObj<CompactTileSheet>(keelCtx(ctx), tilesheetPath));
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
@@ -53,6 +88,14 @@ ox::Error loadBgTileSheet(
return loadBgTileSheet(ctx, cbb, *ts, paletteBank);
}
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::StringViewCR tilesheetPath,
bool loadDefaultPalette) noexcept {
oxRequire(ts, readObj<CompactTileSheet>(keelCtx(ctx), tilesheetPath));
return loadSpriteTileSheet(ctx, *ts, loadDefaultPalette);
}
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
@@ -213,12 +256,11 @@ void puts(
int const column,
int const row,
ox::StringViewCR str) noexcept {
auto const col = static_cast<uint_t>(column);
for (auto i = 0u; i < str.bytes(); ++i) {
setBgTile(
ctx,
0,
static_cast<int>(col + i),
column + static_cast<int>(i),
row,
static_cast<uint8_t>(charMap[static_cast<uint8_t>(str[i])]));
}

View File

@@ -554,20 +554,21 @@ static ox::Result<TileSheetData> buildSetTsd(
static void copyPixels(
CompactTileSheet const&ts,
uint32_t *dst,
ox::Span<uint32_t> dst,
size_t const srcPxIdx,
size_t pxlCnt) noexcept {
size_t idx{};
if (ts.bpp == 4) {
for (size_t i = 0; i < pxlCnt; i += 2) {
auto const [a, b] = get2Pixels4Bpp(ts, i + srcPxIdx);
*(dst++) = a;
*(dst++) = b;
dst[idx++] = a;
dst[idx++] = b;
}
} else if (ts.bpp == 8) {
for (size_t i = 0; i < pxlCnt; i += 2) {
auto const [a, b] = get2Pixels8Bpp(ts, i + srcPxIdx);
*(dst++) = a;
*(dst++) = b;
dst[idx++] = a;
dst[idx++] = b;
}
}
}
@@ -587,7 +588,7 @@ ox::Error loadBgTileSheet(
if (dstPxIdx + pxlCnt >= cbbPxls.size()) {
return OxError(1, "video mem dst overflow");
}
auto const dst = &cbbPxls[dstPxIdx];
auto const dst = ox::Span{cbbPxls} + dstPxIdx;
copyPixels(ts, dst, srcPxIdx, pxlCnt);
auto const cbbTiles = cbbPxls.size() / bytesPerTile;
int constexpr cbbWidth = 8;

View File

@@ -12,7 +12,7 @@ TileSheetClipboard::Pixel::Pixel(uint16_t pColorIdx, ox::Point pPt) noexcept {
}
void TileSheetClipboard::addPixel(const ox::Point &pt, uint16_t colorIdx) noexcept {
void TileSheetClipboard::addPixel(ox::Point const&pt, uint16_t colorIdx) noexcept {
m_pixels.emplace_back(colorIdx, pt);
}
@@ -25,18 +25,20 @@ CutPasteCommand::CutPasteCommand(
CommandId commandId,
TileSheet &img,
TileSheet::SubSheetIdx subSheetIdx,
const ox::Point &dstStart,
const ox::Point &dstEnd,
const TileSheetClipboard &cb) noexcept:
ox::Point const&dstStart,
ox::Point dstEnd,
TileSheetClipboard const&cb) noexcept:
m_commandId(commandId),
m_img(img),
m_subSheetIdx(std::move(subSheetIdx)) {
const auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
for (const auto &p : cb.pixels()) {
const auto dstPt = p.pt + dstStart;
auto const&ss = getSubSheet(m_img, m_subSheetIdx);
dstEnd.x = std::min(ss.columns * TileWidth - 1, dstEnd.x);
dstEnd.y = std::min(ss.rows * TileHeight - 1, dstEnd.y);
for (auto const&p : cb.pixels()) {
auto const dstPt = p.pt + dstStart;
if (dstPt.x <= dstEnd.x && dstPt.y <= dstEnd.y) {
const auto idx = core::idx(subsheet, dstPt);
m_changes.emplace_back(static_cast<uint32_t>(idx), p.colorIdx, getPixel(subsheet, m_img.bpp, idx));
auto const idx = core::idx(ss, dstPt);
m_changes.emplace_back(static_cast<uint32_t>(idx), p.colorIdx, getPixel(ss, m_img.bpp, idx));
}
}
}

View File

@@ -68,7 +68,7 @@ class CutPasteCommand: public TileSheetCommand {
TileSheet &img,
TileSheet::SubSheetIdx subSheetIdx,
ox::Point const&dstStart,
ox::Point const&dstEnd,
ox::Point dstEnd,
TileSheetClipboard const&cb) noexcept;
ox::Error redo() noexcept final;
@@ -83,4 +83,4 @@ class CutPasteCommand: public TileSheetCommand {
};
}
}

View File

@@ -2,6 +2,8 @@
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <ox/std/algorithm.hpp>
#include "deletetilescommand.hpp"
namespace nostalgia::core {
@@ -20,11 +22,9 @@ core::DeleteTilesCommand::DeleteTilesCommand(
// copy pixels to be erased
{
auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels;
auto dst = m_deletedPixels.data();
auto src = p.data() + m_deletePos;
const auto sz = m_deleteSz * sizeof(decltype(p[0]));
ox::memcpy(dst, src, sz);
auto dst = m_deletedPixels.begin();
auto src = s.pixels.begin() + m_deletePos;
ox::copy_n(src, m_deleteSz, dst);
}
}
@@ -32,9 +32,9 @@ ox::Error core::DeleteTilesCommand::redo() noexcept {
auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels;
auto srcPos = m_deletePos + m_deleteSz;
const auto src = p.data() + srcPos;
const auto dst1 = p.data() + m_deletePos;
const auto dst2 = p.data() + (p.size() - m_deleteSz);
auto const src = &p[srcPos];
auto const dst1 = &p[m_deletePos];
auto const dst2 = &p[(p.size() - m_deleteSz)];
ox::memmove(dst1, src, p.size() - srcPos);
ox::memset(dst2, 0, m_deleteSz * sizeof(decltype(p[0])));
return {};
@@ -43,10 +43,10 @@ ox::Error core::DeleteTilesCommand::redo() noexcept {
ox::Error DeleteTilesCommand::undo() noexcept {
auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels;
const auto src = p.data() + m_deletePos;
const auto dst1 = p.data() + m_deletePos + m_deleteSz;
const auto dst2 = src;
const auto sz = p.size() - m_deletePos - m_deleteSz;
auto const src = &p[m_deletePos];
auto const dst1 = &p[m_deletePos + m_deleteSz];
auto const dst2 = src;
auto const sz = p.size() - m_deletePos - m_deleteSz;
ox::memmove(dst1, src, sz);
ox::memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size());
return {};

View File

@@ -21,10 +21,9 @@ core::InsertTilesCommand::InsertTilesCommand(
{
auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels;
auto dst = m_deletedPixels.data();
auto src = p.data() + p.size() - m_insertCnt;
const auto sz = m_insertCnt * sizeof(decltype(p[0]));
ox::memcpy(dst, src, sz);
auto dst = m_deletedPixels.begin();
auto src = p.begin() + p.size() - m_insertCnt;
ox::copy_n(src, m_insertCnt, dst);
}
}
@@ -32,8 +31,8 @@ ox::Error InsertTilesCommand::redo() noexcept {
auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels;
auto dstPos = m_insertPos + m_insertCnt;
const auto dst = p.data() + dstPos;
const auto src = p.data() + m_insertPos;
auto const dst = &p[dstPos];
auto const src = &p[m_insertPos];
ox::memmove(dst, src, p.size() - dstPos);
ox::memset(src, 0, m_insertCnt * sizeof(decltype(p[0])));
return {};
@@ -42,11 +41,11 @@ ox::Error InsertTilesCommand::redo() noexcept {
ox::Error InsertTilesCommand::undo() noexcept {
auto &s = getSubSheet(m_img, m_idx);
auto &p = s.pixels;
const auto srcIdx = m_insertPos + m_insertCnt;
const auto src = p.data() + srcIdx;
const auto dst1 = p.data() + m_insertPos;
const auto dst2 = p.data() + p.size() - m_insertCnt;
const auto sz = p.size() - srcIdx;
auto const srcIdx = m_insertPos + m_insertCnt;
auto const src = &p[srcIdx];
auto const dst1 = &p[m_insertPos];
auto const dst2 = &p[p.size() - m_insertCnt];
auto const sz = p.size() - srcIdx;
ox::memmove(dst1, src, sz);
ox::memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size());
return {};

View File

@@ -120,7 +120,7 @@ ox::StringView TileSheetEditorModel::palPath() const noexcept {
}
constexpr ox::StringView uuidPrefix = "uuid://";
if (ox::beginsWith(path, uuidPrefix)) {
auto uuid = ox::StringView(path.data() + uuidPrefix.bytes(), path.bytes() - uuidPrefix.bytes());
auto uuid = ox::StringView(&path[uuidPrefix.bytes()], path.bytes() - uuidPrefix.bytes());
auto out = keelCtx(m_tctx).uuidToPath.at(uuid);
if (out.error) {
return {};
@@ -197,7 +197,7 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int palIdx) noexcept {
if (pt.x >= s.columns * TileWidth || pt.y >= s.rows * TileHeight) {
return;
}
getFillPixels(updateMap.data(), pt, oldColor);
getFillPixels(updateMap, pt, oldColor);
ox::Vector<std::size_t> idxList;
auto i = core::idx(s, pt) / PixelsPerTile * PixelsPerTile;
for (auto u : updateMap) {
@@ -281,7 +281,7 @@ bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept {
return m_selection && m_selection->contains(pt);
}
void TileSheetEditorModel::getFillPixels(bool *pixels, ox::Point const&pt, int oldColor) const noexcept {
void TileSheetEditorModel::getFillPixels(ox::Span<bool> pixels, ox::Point const&pt, int oldColor) const noexcept {
const auto &activeSubSheet = this->activeSubSheet();
const auto tileIdx = [activeSubSheet](const ox::Point &pt) noexcept {
return ptToIdx(pt, activeSubSheet.columns) / PixelsPerTile;

View File

@@ -128,7 +128,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
bool pixelSelected(std::size_t idx) const noexcept;
private:
void getFillPixels(bool *pixels, ox::Point const&pt, int oldColor) const noexcept;
void getFillPixels(ox::Span<bool> pixels, ox::Point const&pt, int oldColor) const noexcept;
void pushCommand(studio::UndoCommand *cmd) noexcept;

View File

@@ -163,8 +163,8 @@ unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept {
ox::Error resizeSubsheet(TileSheet::SubSheet &ss, int8_t pBpp, ox::Size const&sz) noexcept {
ox::Vector<uint8_t> out;
oxReturnError(setPixelCount(out, pBpp, static_cast<size_t>(sz.width * sz.height) * PixelsPerTile));
auto const w = ss.columns * TileWidth;
auto const h = ss.rows * TileHeight;
auto const w = ox::min<int32_t>(ss.columns, sz.width) * TileWidth;
auto const h = ox::min<int32_t>(ss.rows, sz.height) * TileHeight;
for (auto x = 0; x < w; ++x) {
for (auto y = 0; y < h; ++y) {
auto const palIdx = getPixel(ss, pBpp, {x, y});

View File

@@ -24,9 +24,10 @@ static std::map<ox::StringView, ox::Error(*)()> tests = {
},
};
int main(int argc, const char **args) {
int main(int argc, const char **argv) {
int retval = -1;
if (argc > 0) {
auto const args = ox::Span{argv, static_cast<size_t>(argc)};
auto const testName = ox::StringView(args[1]);
if (tests.find(testName) != tests.end()) {
retval = static_cast<int>(tests[testName]());