Files
aurora/lib/dolphin/gx/GXVert.cpp
T
2026-06-04 23:43:13 -06:00

230 lines
5.9 KiB
C++

#include "gx.hpp"
#include "__gx.h"
#include "../../gx/fifo.hpp"
// Track vertex count between GXBegin/GXEnd for mismatch detection
static u16 sBeginNVerts = 0;
static u32 sBeginFifoSize = 0;
static bool sInBegin = false;
extern "C" {
void GXBegin(GXPrimitive primitive, GXVtxFmt vtxFmt, u16 nVerts) {
CHECK(!sInBegin, "GXBegin: called without matching GXEnd");
// Flush dirty state before starting a draw
if (__gx->dirtyState != 0) {
__GXSetDirtyState();
}
// Flush pending primitives if needed
if (*reinterpret_cast<u32*>(&__gx->vNum) != 0) {
__GXSendFlushPrim();
}
GX_WRITE_U8(vtxFmt | primitive);
GX_WRITE_U16(nVerts);
// Record state for vertex count validation in GXEnd
sBeginNVerts = nVerts;
sBeginFifoSize = aurora::gx::fifo::get_buffer_size();
sInBegin = true;
}
void GXEnd() {
if (sInBegin) {
u32 bytesWritten = aurora::gx::fifo::get_buffer_size() - sBeginFifoSize;
if (sBeginNVerts > 0 && bytesWritten > 0) {
u32 vtxSize = bytesWritten / sBeginNVerts;
u32 remainder = bytesWritten % sBeginNVerts;
if (remainder != 0) {
Log.warn("GXEnd: vertex data not evenly divisible: {} bytes for {} vertices", bytesWritten, sBeginNVerts);
}
u32 actualVerts = (vtxSize > 0) ? bytesWritten / vtxSize : 0;
CHECK(actualVerts == sBeginNVerts,
"GXEnd: vertex count mismatch: GXBegin declared {} vertices ({}B each, {}B total) "
"but {} bytes were written ({} vertices)",
sBeginNVerts, vtxSize, sBeginNVerts * vtxSize, bytesWritten, actualVerts);
}
sInBegin = false;
}
// TEMP: debugging aid
// if (!aurora::gx::fifo::in_display_list()) {
// aurora::gx::fifo::drain();
// }
}
void GXPosition3f32(f32 x, f32 y, f32 z) {
GX_WRITE_F32(x);
GX_WRITE_F32(y);
GX_WRITE_F32(z);
}
void GXPosition3u16(u16 x, u16 y, u16 z) {
GX_WRITE_U16(x);
GX_WRITE_U16(y);
GX_WRITE_U16(z);
}
void GXPosition3s16(s16 x, s16 y, s16 z) {
GX_WRITE_U16(static_cast<u16>(x));
GX_WRITE_U16(static_cast<u16>(y));
GX_WRITE_U16(static_cast<u16>(z));
}
void GXPosition3u8(u8 x, u8 y, u8 z) {
GX_WRITE_U8(x);
GX_WRITE_U8(y);
GX_WRITE_U8(z);
}
void GXPosition3s8(s8 x, s8 y, s8 z) {
GX_WRITE_U8(static_cast<u8>(x));
GX_WRITE_U8(static_cast<u8>(y));
GX_WRITE_U8(static_cast<u8>(z));
}
void GXPosition2f32(f32 x, f32 y) {
GX_WRITE_F32(x);
GX_WRITE_F32(y);
}
void GXPosition2u16(u16 x, u16 y) {
GX_WRITE_U16(x);
GX_WRITE_U16(y);
}
void GXPosition2s16(s16 x, s16 y) {
GX_WRITE_U16(static_cast<u16>(x));
GX_WRITE_U16(static_cast<u16>(y));
}
void GXPosition2u8(u8 x, u8 y) {
GX_WRITE_U8(x);
GX_WRITE_U8(y);
}
void GXPosition2s8(s8 x, s8 y) {
GX_WRITE_U8(static_cast<u8>(x));
GX_WRITE_U8(static_cast<u8>(y));
}
void GXPosition1x16(u16 idx) { GX_WRITE_U16(idx); }
void GXPosition1x8(u8 idx) { GX_WRITE_U8(idx); }
void GXNormal3f32(f32 x, f32 y, f32 z) {
GX_WRITE_F32(x);
GX_WRITE_F32(y);
GX_WRITE_F32(z);
}
void GXNormal3s16(s16 x, s16 y, s16 z) {
GX_WRITE_U16(static_cast<u16>(x));
GX_WRITE_U16(static_cast<u16>(y));
GX_WRITE_U16(static_cast<u16>(z));
}
void GXNormal3s8(s8 x, s8 y, s8 z) {
GX_WRITE_U8(static_cast<u8>(x));
GX_WRITE_U8(static_cast<u8>(y));
GX_WRITE_U8(static_cast<u8>(z));
}
void GXNormal1x16(u16 index) { GX_WRITE_U16(index); }
void GXNormal1x8(u8 index) { GX_WRITE_U8(index); }
void GXColor4f32(f32 r, f32 g, f32 b, f32 a) {
GX_WRITE_U8(static_cast<u8>(r * 255.0));
GX_WRITE_U8(static_cast<u8>(g * 255.0));
GX_WRITE_U8(static_cast<u8>(b * 255.0));
GX_WRITE_U8(static_cast<u8>(a * 255.0));
}
void GXColor4u8(u8 r, u8 g, u8 b, u8 a) {
GX_WRITE_U8(r);
GX_WRITE_U8(g);
GX_WRITE_U8(b);
GX_WRITE_U8(a);
}
void GXColor3u8(u8 r, u8 g, u8 b) {
GX_WRITE_U8(r);
GX_WRITE_U8(g);
GX_WRITE_U8(b);
}
void GXColor1u32(u32 clr) { GX_WRITE_U32(clr); }
void GXColor1u16(u16 clr) { GX_WRITE_U16(clr); }
void GXColor1x16(u16 index) { GX_WRITE_U16(index); }
void GXColor1x8(u8 index) { GX_WRITE_U8(index); }
void GXTexCoord2f32(f32 s, f32 t) {
GX_WRITE_F32(s);
GX_WRITE_F32(t);
}
void GXTexCoord2u16(u16 s, u16 t) {
GX_WRITE_U16(s);
GX_WRITE_U16(t);
}
void GXTexCoord2s16(s16 s, s16 t) {
GX_WRITE_U16(static_cast<u16>(s));
GX_WRITE_U16(static_cast<u16>(t));
}
void GXTexCoord2u8(u8 s, u8 t) {
GX_WRITE_U8(s);
GX_WRITE_U8(t);
}
void GXTexCoord2s8(s8 s, s8 t) {
GX_WRITE_U8(static_cast<u8>(s));
GX_WRITE_U8(static_cast<u8>(t));
}
void GXTexCoord1f32(f32 s) { GX_WRITE_F32(s); }
void GXTexCoord1u16(u16 s) { GX_WRITE_U16(s); }
void GXTexCoord1s16(s16 s) { GX_WRITE_U16(static_cast<u16>(s)); }
void GXTexCoord1u8(u8 s) { GX_WRITE_U8(s); }
void GXTexCoord1s8(s8 s) { GX_WRITE_U8(static_cast<u8>(s)); }
void GXTexCoord1x16(u16 index) { GX_WRITE_U16(index); }
void GXTexCoord1x8(u8 index) { GX_WRITE_U8(index); }
void GXCmd1u8(const u8 x) { aurora::gx::fifo::write_u8(x); }
void GXCmd1u16(const u16 x) { aurora::gx::fifo::write_u16(x); }
void GXCmd1u32(const u32 x) { aurora::gx::fifo::write_u32(x); }
void GXCmd1u64(const u64 x) { aurora::gx::fifo::write_u64(x); }
void GXParam1u8(const u8 x) { aurora::gx::fifo::write_u8(x); }
void GXParam1u16(const u16 x) { aurora::gx::fifo::write_u16(x); }
void GXParam1u32(const u32 x) { aurora::gx::fifo::write_u32(x); }
void GXParam1s8(const s8 x) { aurora::gx::fifo::write_u8(static_cast<uint8_t>(x)); }
void GXParam1s16(const s16 x) { aurora::gx::fifo::write_u16(static_cast<uint16_t>(x)); }
void GXParam1s32(const s32 x) { aurora::gx::fifo::write_u32(static_cast<uint32_t>(x)); }
void GXParam1f32(const f32 x) { aurora::gx::fifo::write_f32(x); }
void GXParam3f32(const f32 x, const f32 y, const f32 z) {
aurora::gx::fifo::write_f32(x);
aurora::gx::fifo::write_f32(y);
aurora::gx::fifo::write_f32(z);
}
void GXParam4f32(const f32 x, const f32 y, const f32 z, const f32 w) {
aurora::gx::fifo::write_f32(x);
aurora::gx::fifo::write_f32(y);
aurora::gx::fifo::write_f32(z);
aurora::gx::fifo::write_f32(w);
}
} // extern "C"