Compare commits

..

3 Commits

Author SHA1 Message Date
8764444758 [nostalgia/core] Add clearCbb functions
All checks were successful
Build / build (push) Successful in 3m12s
2025-01-14 21:13:42 -06:00
ce9a0b1fdb [nostalgia/core/opengl] Cleanup memcpys 2025-01-14 21:13:10 -06:00
f7a468ea1e [ox/std] Add spancpy 2025-01-14 21:10:18 -06:00
7 changed files with 120 additions and 32 deletions

View File

@ -14,7 +14,7 @@
#include "iterator.hpp"
#include "vector.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
namespace ox {
@ -133,7 +133,7 @@ class Span {
return m_items[i];
}
constexpr const T &operator[](std::size_t i) const noexcept {
constexpr T const&operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return m_items[i];
}
@ -168,8 +168,20 @@ class Span {
};
template<typename T>
using SpanView = Span<const T>;
using SpanView = Span<T const>;
template<typename T>
constexpr void spancpy(ox::Span<T> const dst, ox::SpanView<T> const src) noexcept {
auto const sz = ox::min(dst.size(), src.size());
if (std::is_constant_evaluated() || std::is_trivially_copyable_v<T>) {
for (size_t i{}; i < sz; ++i) {
dst.data()[i] = src.data()[i];
}
} else {
memcpy(dst.data(), src.data(), sz * sizeof(T));
}
}
}
OX_CLANG_NOWARN_END
OX_ALLOW_UNSAFE_BUFFERS_END

View File

@ -19,12 +19,15 @@
namespace std {
template<typename T>
constexpr bool is_union_v = __is_union(T);
inline constexpr bool is_union_v = __is_union(T);
constexpr bool is_constant_evaluated() noexcept {
inline constexpr bool is_constant_evaluated() noexcept {
return __builtin_is_constant_evaluated();
}
template<typename T>
inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(T);
}
#endif
@ -156,6 +159,9 @@ static_assert(is_class<int>::value == false);
template<typename T>
constexpr bool is_class_v = is_class<T>();
template<typename T>
inline constexpr bool is_trivially_copyable_v = std::is_trivially_copyable_v<T>;
template<typename T>
constexpr bool is_signed_v = integral_constant<bool, T(-1) < T(0)>::value;

View File

@ -142,6 +142,10 @@ ox::Error loadBgTileSheet(
unsigned cbb,
TileSheetSet const&set) noexcept;
void clearCbb(Context &ctx, unsigned cbb) noexcept;
void clearCbbs(Context &ctx) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,

View File

@ -0,0 +1,11 @@
/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <studio/studio.hpp>
namespace nostalgia::core {
}

View File

@ -18,6 +18,23 @@
namespace nostalgia::core {
struct SubSheetTemplate {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.SubSheetTemplate";
static constexpr auto TypeVersion = 1;
ox::String name;
int32_t width{};
int32_t height{};
ox::Vector<SubSheetTemplate> subsheets;
};
OX_MODEL_BEGIN(SubSheetTemplate)
OX_MODEL_FIELD(name)
OX_MODEL_FIELD(width)
OX_MODEL_FIELD(height)
OX_MODEL_FIELD(subsheets)
OX_MODEL_END()
// Predecessor to TileSheet, kept for backward compatibility
struct TileSheetV1 {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic";

View File

@ -63,6 +63,19 @@ ox::Error loadSpritePalette(
return {};
}
void clearCbb(Context&, unsigned const cbb) noexcept {
for (auto &v : MEM_BG_TILES[cbb]) {
v = 0;
}
}
void clearCbbs(Context &ctx) noexcept {
clearCbb(ctx, 0);
clearCbb(ctx, 1);
clearCbb(ctx, 2);
clearCbb(ctx, 3);
}
static ox::Error loadTileSheetSet(
Context &ctx,
ox::Span<uint16_t> tileMapTargetMem,

View File

@ -118,8 +118,8 @@ static void setSpriteBufferObject(
uint_t textureRow,
uint_t flipX,
uint_t priority,
float *vbo,
GLuint *ebo) noexcept {
ox::Span<float> vbo,
ox::Span<GLuint> ebo) noexcept {
// don't worry, this memcpy gets optimized to something much more ideal
constexpr float xmod = 0.1f;
constexpr float ymod = 0.1f;
@ -138,12 +138,12 @@ static void setSpriteBufferObject(
enabled, x + xmod, y + ymod, prif, R, textureRowf + 0, // top right
enabled, x, y + ymod, prif, L, textureRowf + 0, // top left
};
memcpy(vbo, vertices.data(), sizeof(vertices));
ox::spancpy<float>(vbo, vertices);
ox::Array<GLuint, SpriteVertexEboLength> const elms {
vi + 0, vi + 1, vi + 2,
vi + 2, vi + 3, vi + 0,
vi + 0, vi + 1, vi + 2,
vi + 2, vi + 3, vi + 0,
};
memcpy(ebo, elms.data(), sizeof(elms));
ox::spancpy<GLuint>(ebo, elms);
}
static void setTileBufferObject(
@ -155,8 +155,8 @@ static void setTileBufferObject(
float palOffset,
bool flipX,
bool flipY,
float *vbo,
GLuint *ebo) noexcept {
ox::Span<float> vbo,
ox::Span<GLuint> ebo) noexcept {
// don't worry, this memcpy gets optimized to something much more ideal
constexpr float ymod = 0.1f;
constexpr float xmod = 0.1f;
@ -170,24 +170,35 @@ static void setTileBufferObject(
float const T = flipY ? 1 : 0;
float const B = flipY ? 0 : 1;
ox::Array<float, BgVertexVboLength> const vertices {
x, y, prif, L, B, textureTileIdx, palOffset, // bottom left
x + xmod, y, prif, R, B, textureTileIdx, palOffset, // bottom right
x + xmod, y + ymod, prif, R, T, textureTileIdx, palOffset, // top right
x, y + ymod, prif, L, T, textureTileIdx, palOffset, // top left
x, y, prif, L, B, textureTileIdx, palOffset, // bottom left
x + xmod, y, prif, R, B, textureTileIdx, palOffset, // bottom right
x + xmod, y + ymod, prif, R, T, textureTileIdx, palOffset, // top right
x, y + ymod, prif, L, T, textureTileIdx, palOffset, // top left
};
memcpy(vbo, vertices.data(), sizeof(vertices));
ox::spancpy<float>(vbo, vertices);
ox::Array<GLuint, BgVertexEboLength> const elms {
vi + 0, vi + 1, vi + 2,
vi + 2, vi + 3, vi + 0,
vi + 0, vi + 1, vi + 2,
vi + 2, vi + 3, vi + 0,
};
memcpy(ebo, elms.data(), sizeof(elms));
ox::spancpy<GLuint>(ebo, elms);
}
static void initSpriteBufferObjects(Context &ctx, glutils::BufferSet &bs) noexcept {
for (auto i = 0u; i < ctx.spriteCount; ++i) {
auto vbo = &bs.vertices[i * static_cast<std::size_t>(SpriteVertexVboLength)];
auto ebo = &bs.elements[i * static_cast<std::size_t>(SpriteVertexEboLength)];
setSpriteBufferObject(i * static_cast<uint_t>(SpriteVertexVboRows) * ctx.blocksPerSprite, 0, 0, 0, 0, false, 0, vbo, ebo);
auto const vbo = ox::Span{bs.vertices}
+ i * static_cast<std::size_t>(SpriteVertexVboLength);
auto const ebo = ox::Span{bs.elements}
+ i * static_cast<std::size_t>(SpriteVertexEboLength);
setSpriteBufferObject(
i * static_cast<uint_t>(SpriteVertexVboRows) * ctx.blocksPerSprite,
0,
0,
0,
0,
false,
0,
vbo,
ebo);
}
}
@ -195,8 +206,10 @@ static void initBackgroundBufferObjects(glutils::BufferSet &bs) noexcept {
for (auto x = 0u; x < TileColumns; ++x) {
for (auto y = 0u; y < TileRows; ++y) {
const auto i = bgVertexRow(x, y);
auto vbo = &bs.vertices[i * static_cast<std::size_t>(BgVertexVboLength)];
auto ebo = &bs.elements[i * static_cast<std::size_t>(BgVertexEboLength)];
auto const vbo = ox::Span{bs.vertices}
+ i * static_cast<std::size_t>(BgVertexVboLength);
auto const ebo = ox::Span{bs.elements}
+ i * static_cast<std::size_t>(BgVertexEboLength);
setTileBufferObject(
static_cast<uint_t>(i * BgVertexVboRows),
static_cast<float>(x),
@ -421,8 +434,8 @@ static void setSprite(
auto const eboIdx = eboBase + renderer::SpriteVertexEboLength * i;
oxAssert(vboIdx < ctx.spriteBlocks.vertices.size(), "vbo overflow");
oxAssert(eboIdx < ctx.spriteBlocks.elements.size(), "ebo overflow");
auto const vbo = &ctx.spriteBlocks.vertices[vboIdx];
auto const ebo = &ctx.spriteBlocks.elements[eboIdx];
auto const vbo = ox::Span{ctx.spriteBlocks.vertices} + vboIdx;
auto const ebo = ox::Span{ctx.spriteBlocks.elements} + eboIdx;
renderer::setSpriteBufferObject(
static_cast<uint_t>(vboIdx),
enabled,
@ -556,7 +569,7 @@ static void copyPixels(
CompactTileSheet const&ts,
ox::Span<uint32_t> dst,
size_t const srcPxIdx,
size_t pxlCnt) noexcept {
size_t const pxlCnt) noexcept {
size_t idx{};
if (ts.bpp == 4) {
for (size_t i = 0; i < pxlCnt; i += 2) {
@ -573,6 +586,18 @@ static void copyPixels(
}
}
void clearCbb(Context &ctx, unsigned const cbb) noexcept {
for (auto &v : ctx.cbbs[cbb].pixels) {
v = 0;
}
}
void clearCbbs(Context &ctx) noexcept {
for (unsigned i = 0 ; i < ctx.cbbs.size(); ++i) {
clearCbb(ctx, i);
}
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned const cbb,
@ -656,8 +681,8 @@ void setBgTile(
const auto x = static_cast<uint_t>(column);
const auto i = renderer::bgVertexRow(x, y);
auto &cbb = ctx.cbbs[z];
const auto vbo = &cbb.vertices[i * renderer::BgVertexVboLength];
const auto ebo = &cbb.elements[i * renderer::BgVertexEboLength];
const auto vbo = ox::Span{cbb.vertices} + i * renderer::BgVertexVboLength;
const auto ebo = ox::Span{cbb.elements} + i * renderer::BgVertexEboLength;
auto &bg = ctx.backgrounds[bgIdx];
renderer::setTileBufferObject(
static_cast<uint_t>(i * renderer::BgVertexVboRows),