Merge branch 'master' of github.com:fleroviux/Panda3DS into pica-tev-emulation

This commit is contained in:
fleroviux 2023-06-20 22:47:47 +02:00
commit 4cb7e3625b
13 changed files with 427 additions and 412 deletions

View file

@ -88,44 +88,45 @@ template <bool indexed>
void GPU::drawArrays() {
// Base address for vertex attributes
// The vertex base is always on a quadword boundary because the PICA does weird alignment shit any time possible
const u32 vertexBase = ((regs[PICAInternalRegs::VertexAttribLoc] >> 1) & 0xfffffff) * 16;
const u32 vertexCount = regs[PICAInternalRegs::VertexCountReg]; // Total # of vertices to transfer
const u32 vertexBase = ((regs[PICA::InternalRegs::VertexAttribLoc] >> 1) & 0xfffffff) * 16;
const u32 vertexCount = regs[PICA::InternalRegs::VertexCountReg]; // Total # of vertices to transfer
// Configures the type of primitive and the number of vertex shader outputs
const u32 primConfig = regs[PICAInternalRegs::PrimitiveConfig];
const u32 primType = Helpers::getBits<8, 2>(primConfig);
if (primType != 0 && primType != 1 && primType != 3) Helpers::panic("[PICA] Tried to draw unimplemented shape %d\n", primType);
const u32 primConfig = regs[PICA::InternalRegs::PrimitiveConfig];
const PICA::PrimType primType = static_cast<PICA::PrimType>(Helpers::getBits<8, 2>(primConfig));
if (primType == PICA::PrimType::TriangleFan) Helpers::panic("[PICA] Tried to draw unimplemented shape %d\n", primType);
if (vertexCount > Renderer::vertexBufferSize) Helpers::panic("[PICA] vertexCount > vertexBufferSize");
if ((primType == 0 && vertexCount % 3) || (primType == 1 && vertexCount < 3)) {
if ((primType == PICA::PrimType::TriangleList && vertexCount % 3) ||
(primType == PICA::PrimType::TriangleStrip && vertexCount < 3)) {
Helpers::panic("Invalid vertex count for primitive. Type: %d, vert count: %d\n", primType, vertexCount);
}
// Get the configuration for the index buffer, used only for indexed drawing
u32 indexBufferConfig = regs[PICAInternalRegs::IndexBufferConfig];
u32 indexBufferConfig = regs[PICA::InternalRegs::IndexBufferConfig];
u32 indexBufferPointer = vertexBase + (indexBufferConfig & 0xfffffff);
bool shortIndex = Helpers::getBit<31>(indexBufferConfig); // Indicates whether vert indices are 16-bit or 8-bit
// Stuff the global attribute config registers in one u64 to make attr parsing easier
// TODO: Cache this when the vertex attribute format registers are written to
u64 vertexCfg = u64(regs[PICAInternalRegs::AttribFormatLow]) | (u64(regs[PICAInternalRegs::AttribFormatHigh]) << 32);
u64 vertexCfg = u64(regs[PICA::InternalRegs::AttribFormatLow]) | (u64(regs[PICA::InternalRegs::AttribFormatHigh]) << 32);
if constexpr (!indexed) {
u32 offset = regs[PICAInternalRegs::VertexOffsetReg];
u32 offset = regs[PICA::InternalRegs::VertexOffsetReg];
log("PICA::DrawArrays(vertex count = %d, vertexOffset = %d)\n", vertexCount, offset);
} else {
log("PICA::DrawElements(vertex count = %d, index buffer config = %08X)\n", vertexCount, indexBufferConfig);
}
// Total number of input attributes to shader. Differs between GS and VS. Currently stubbed to the VS one, as we don't have geometry shaders.
const u32 inputAttrCount = (regs[PICAInternalRegs::VertexShaderInputBufferCfg] & 0xf) + 1;
const u32 inputAttrCount = (regs[PICA::InternalRegs::VertexShaderInputBufferCfg] & 0xf) + 1;
const u64 inputAttrCfg = getVertexShaderInputConfig();
for (u32 i = 0; i < vertexCount; i++) {
u32 vertexIndex; // Index of the vertex in the VBO
if constexpr (!indexed) {
vertexIndex = i + regs[PICAInternalRegs::VertexOffsetReg];
vertexIndex = i + regs[PICA::InternalRegs::VertexOffsetReg];
} else {
if (shortIndex) {
auto ptr = getPointerPhys<u16>(indexBufferPointer);
@ -235,9 +236,9 @@ void GPU::drawArrays() {
OutputVertex out;
// Map shader outputs to fixed function properties
const u32 totalShaderOutputs = regs[PICAInternalRegs::ShaderOutputCount] & 7;
const u32 totalShaderOutputs = regs[PICA::InternalRegs::ShaderOutputCount] & 7;
for (int i = 0; i < totalShaderOutputs; i++) {
const u32 config = regs[PICAInternalRegs::ShaderOutmap0 + i];
const u32 config = regs[PICA::InternalRegs::ShaderOutmap0 + i];
for (int j = 0; j < 4; j++) { // pls unroll
const u32 mapping = (config >> (j * 8)) & 0x1F;
@ -257,17 +258,12 @@ void GPU::drawArrays() {
//printf("(u, v ) = (%f, %f)\n", vertices[i].UVs.u(), vertices[i].UVs.v());
}
// The fourth type is meant to be "Geometry primitive". TODO: Find out what that is
static constexpr std::array<OpenGL::Primitives, 4> primTypes = {
OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle
};
const auto shape = primTypes[primType];
renderer.drawVertices(shape, std::span(vertices).first(vertexCount));
renderer.drawVertices(primType, std::span(vertices).first(vertexCount));
}
Vertex GPU::getImmediateModeVertex() {
Vertex v;
const int totalAttrCount = (regs[PICAInternalRegs::VertexShaderAttrNum] & 0xf) + 1;
const int totalAttrCount = (regs[PICA::InternalRegs::VertexShaderAttrNum] & 0xf) + 1;
// Copy immediate mode attributes to vertex shader unit
for (int i = 0; i < totalAttrCount; i++) {

View file

@ -33,7 +33,7 @@ u32 GPU::readInternalReg(u32 index) {
}
void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
using namespace PICAInternalRegs;
using namespace PICA::InternalRegs;
if (index > regNum) {
Helpers::panic("Tried to write to invalid GPU register. Index: %X, value: %08X\n", index, value);
@ -68,7 +68,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
case ColourBufferFormat: {
u32 format = getBits<16, 3>(value);
renderer.setColourFormat(format);
renderer.setColourFormat(static_cast<PICA::ColorFmt>(format));
break;
}
@ -79,8 +79,8 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
}
case DepthBufferFormat: {
u32 fmt = value & 0x3;
renderer.setDepthFormat(fmt);
u32 format = value & 0x3;
renderer.setDepthFormat(static_cast<PICA::DepthFmt>(format));
break;
}
@ -137,7 +137,7 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
if (fixedAttribIndex < 12) [[likely]] {
shaderUnit.vs.fixedAttributes[fixedAttribIndex++] = attr;
} else if (fixedAttribIndex == 15) { // Otherwise if it's 15, we're submitting an immediate mode vertex
const uint totalAttrCount = (regs[PICAInternalRegs::VertexShaderAttrNum] & 0xf) + 1;
const uint totalAttrCount = (regs[PICA::InternalRegs::VertexShaderAttrNum] & 0xf) + 1;
if (totalAttrCount <= immediateModeAttrIndex) {
printf("Broken state in the immediate mode vertex submission pipeline. Failing silently\n");
immediateModeAttrIndex = 0;
@ -151,13 +151,13 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) {
immediateModeVertices[immediateModeVertIndex++] = v;
// Get primitive type
const u32 primConfig = regs[PICAInternalRegs::PrimitiveConfig];
const u32 primConfig = regs[PICA::InternalRegs::PrimitiveConfig];
const u32 primType = getBits<8, 2>(primConfig);
// If we've reached 3 verts, issue a draw call
// Handle rendering depending on the primitive type
if (immediateModeVertIndex == 3) {
renderer.drawVertices(OpenGL::Triangle, immediateModeVertices);
renderer.drawVertices(PICA::PrimType::TriangleList, immediateModeVertices);
switch (primType) {
// Triangle or geometry primitive. Draw a triangle and discard all vertices

View file

@ -1,3 +1,4 @@
#include <bit>
#include <cassert>
#include <cstring>

View file

@ -320,10 +320,10 @@ void Renderer::reset() {
// Init the colour/depth buffer settings to some random defaults on reset
colourBufferLoc = 0;
colourBufferFormat = ColourBuffer::Formats::RGBA8;
colourBufferFormat = PICA::ColorFmt::RGBA8;
depthBufferLoc = 0;
depthBufferFormat = DepthBuffer::Formats::Depth16;
depthBufferFormat = PICA::DepthFmt::Depth16;
if (triangleProgram.exists()) {
const auto oldProgram = OpenGL::getProgram();
@ -436,7 +436,7 @@ void Renderer::initGraphicsContext() {
// Set up the OpenGL blending context to match the emulated PICA
void Renderer::setupBlending() {
const bool blendingEnabled = (regs[PICAInternalRegs::ColourOperation] & (1 << 8)) != 0;
const bool blendingEnabled = (regs[PICA::InternalRegs::ColourOperation] & (1 << 8)) != 0;
// Map of PICA blending equations to OpenGL blending equations. The unused blending equations are equivalent to equation 0 (add)
static constexpr std::array<GLenum, 8> blendingEquations = {
@ -456,7 +456,7 @@ void Renderer::setupBlending() {
OpenGL::enableBlend();
// Get blending equations
const u32 blendControl = regs[PICAInternalRegs::BlendFunc];
const u32 blendControl = regs[PICA::InternalRegs::BlendFunc];
const u32 rgbEquation = blendControl & 0x7;
const u32 alphaEquation = getBits<8, 3>(blendControl);
@ -466,7 +466,7 @@ void Renderer::setupBlending() {
const u32 alphaSourceFunc = getBits<24, 4>(blendControl);
const u32 alphaDestFunc = getBits<28, 4>(blendControl);
const u32 constantColor = regs[PICAInternalRegs::BlendColour];
const u32 constantColor = regs[PICA::InternalRegs::BlendColour];
const u32 r = constantColor & 0xff;
const u32 g = getBits<8, 8>(constantColor);
const u32 b = getBits<16, 8>(constantColor);
@ -511,7 +511,13 @@ void Renderer::setupTextureEnvState() {
glUniform1ui(textureEnvBufferColorLoc, regs[0xfd]);
}
void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex> vertices) {
void Renderer::drawVertices(PICA::PrimType primType, std::span<const Vertex> vertices) {
// The fourth type is meant to be "Geometry primitive". TODO: Find out what that is
static constexpr std::array<OpenGL::Primitives, 4> primTypes = {
OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle
};
const auto primitiveTopology = primTypes[static_cast<usize>(primType)];
// TODO: We should implement a GL state tracker that tracks settings like scissor, blending, bound program, etc
// This way if we attempt to eg do multiple glEnable(GL_BLEND) calls in a row, it will say "Oh blending is already enabled"
// And not actually perform the very expensive driver call for it
@ -522,7 +528,7 @@ void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex>
triangleProgram.use();
// Adjust alpha test if necessary
const u32 alphaControl = regs[PICAInternalRegs::AlphaTestConfig];
const u32 alphaControl = regs[PICA::InternalRegs::AlphaTestConfig];
if (alphaControl != oldAlphaControl) {
oldAlphaControl = alphaControl;
glUniform1ui(alphaControlLoc, alphaControl);
@ -532,7 +538,7 @@ void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex>
OpenGL::Framebuffer poop = getColourFBO();
poop.bind(OpenGL::DrawAndReadFramebuffer);
const u32 depthControl = regs[PICAInternalRegs::DepthAndColorMask];
const u32 depthControl = regs[PICA::InternalRegs::DepthAndColorMask];
const bool depthEnable = depthControl & 1;
const bool depthWriteEnable = getBit<12>(depthControl);
const int depthFunc = getBits<4, 3>(depthControl);
@ -543,9 +549,9 @@ void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex>
GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL
};
const float depthScale = f24::fromRaw(regs[PICAInternalRegs::DepthScale] & 0xffffff).toFloat32();
const float depthOffset = f24::fromRaw(regs[PICAInternalRegs::DepthOffset] & 0xffffff).toFloat32();
const bool depthMapEnable = regs[PICAInternalRegs::DepthmapEnable] & 1;
const float depthScale = f24::fromRaw(regs[PICA::InternalRegs::DepthScale] & 0xffffff).toFloat32();
const float depthOffset = f24::fromRaw(regs[PICA::InternalRegs::DepthOffset] & 0xffffff).toFloat32();
const bool depthMapEnable = regs[PICA::InternalRegs::DepthmapEnable] & 1;
// Update depth uniforms
if (oldDepthScale != depthScale) {
@ -585,7 +591,7 @@ void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex>
u32 format = regs[ioBase + (i == 0 ? 14 : 6)] & 0xF;
glActiveTexture(GL_TEXTURE0 + i);
Texture targetTex(addr, static_cast<Texture::Formats>(format), width, height, config);
Texture targetTex(addr, static_cast<PICA::TextureFmt>(format), width, height, config);
OpenGL::Texture tex = getTexture(targetTex);
tex.bind();
}
@ -593,15 +599,15 @@ void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex>
glActiveTexture(GL_TEXTURE0);
// Update the texture unit configuration uniform if it changed
const u32 texUnitConfig = regs[PICAInternalRegs::TexUnitCfg];
const u32 texUnitConfig = regs[PICA::InternalRegs::TexUnitCfg];
if (oldTexUnitConfig != texUnitConfig) {
oldTexUnitConfig = texUnitConfig;
glUniform1ui(texUnitConfigLoc, texUnitConfig);
}
// TODO: Actually use this
float viewportWidth = f24::fromRaw(regs[PICAInternalRegs::ViewportWidth] & 0xffffff).toFloat32() * 2.0;
float viewportHeight = f24::fromRaw(regs[PICAInternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0;
float viewportWidth = f24::fromRaw(regs[PICA::InternalRegs::ViewportWidth] & 0xffffff).toFloat32() * 2.0;
float viewportHeight = f24::fromRaw(regs[PICA::InternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0;
OpenGL::setViewport(viewportWidth, viewportHeight);
// Note: The code below must execute after we've bound the colour buffer & its framebuffer
@ -623,7 +629,7 @@ void Renderer::drawVertices(OpenGL::Primitives primType, std::span<const Vertex>
}
vbo.bufferVertsSub(vertices);
OpenGL::draw(primType, vertices.size());
OpenGL::draw(primitiveTopology, vertices.size());
}
constexpr u32 topScreenBuffer = 0x1f000000;
@ -685,8 +691,8 @@ void Renderer::bindDepthBuffer() {
tex = depthBufferCache.add(sampleBuffer).texture.m_handle;
}
if (DepthBuffer::Formats::Depth24Stencil8 != depthBufferFormat) Helpers::panic("TODO: Should we remove stencil attachment?");
auto attachment = depthBufferFormat == DepthBuffer::Formats::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
if (PICA::DepthFmt::Depth24Stencil8 != depthBufferFormat) Helpers::panic("TODO: Should we remove stencil attachment?");
auto attachment = depthBufferFormat == PICA::DepthFmt::Depth24Stencil8 ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex, 0);
}

View file

@ -43,34 +43,34 @@ u64 Texture::sizeInBytes() {
u64 pixelCount = u64(size.x()) * u64(size.y());
switch (format) {
case Formats::RGBA8: // 4 bytes per pixel
case PICA::TextureFmt::RGBA8: // 4 bytes per pixel
return pixelCount * 4;
case Formats::RGB8: // 3 bytes per pixel
case PICA::TextureFmt::RGB8: // 3 bytes per pixel
return pixelCount * 3;
case Formats::RGBA5551: // 2 bytes per pixel
case Formats::RGB565:
case Formats::RGBA4:
case Formats::RG8:
case Formats::IA8:
case PICA::TextureFmt::RGBA5551: // 2 bytes per pixel
case PICA::TextureFmt::RGB565:
case PICA::TextureFmt::RGBA4:
case PICA::TextureFmt::RG8:
case PICA::TextureFmt::IA8:
return pixelCount * 2;
case Formats::A8: // 1 byte per pixel
case Formats::I8:
case Formats::IA4:
case PICA::TextureFmt::A8: // 1 byte per pixel
case PICA::TextureFmt::I8:
case PICA::TextureFmt::IA4:
return pixelCount;
case Formats::I4: // 4 bits per pixel
case Formats::A4:
case PICA::TextureFmt::I4: // 4 bits per pixel
case PICA::TextureFmt::A4:
return pixelCount / 2;
case Formats::ETC1: // Compressed formats
case Formats::ETC1A4: {
case PICA::TextureFmt::ETC1: // Compressed formats
case PICA::TextureFmt::ETC1A4: {
// Number of 4x4 tiles
const u64 tileCount = pixelCount / 16;
// Tiles are 8 bytes each on ETC1 and 16 bytes each on ETC1A4
const u64 tileSize = format == Formats::ETC1 ? 8 : 16;
const u64 tileSize = format == PICA::TextureFmt::ETC1 ? 8 : 16;
return tileCount * tileSize;
}
@ -111,9 +111,9 @@ u32 Texture::getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) {
// Get the texel at position (u, v)
// fmt: format of the texture
// data: texture data of the texture
u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
switch (fmt) {
case Formats::RGBA4: {
case PICA::TextureFmt::RGBA4: {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
auto ptr = static_cast<const u8*>(data);
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
@ -126,7 +126,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (alpha << 24) | (b << 16) | (g << 8) | r;
}
case Formats::RGBA5551: {
case PICA::TextureFmt::RGBA5551: {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
auto ptr = static_cast<const u8*>(data);
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
@ -139,7 +139,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (alpha << 24) | (b << 16) | (g << 8) | r;
}
case Formats::RGB565: {
case PICA::TextureFmt::RGB565: {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
auto ptr = static_cast<const u8*>(data);
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
@ -151,7 +151,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (0xff << 24) | (b << 16) | (g << 8) | r;
}
case Formats::RG8: {
case PICA::TextureFmt::RG8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
auto ptr = static_cast<const u8*>(data);
@ -162,7 +162,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (0xff << 24) | (b << 16) | (g << 8) | r;
}
case Formats::RGB8: {
case PICA::TextureFmt::RGB8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 3);
auto ptr = static_cast<const u8*>(data);
@ -173,7 +173,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (0xff << 24) | (b << 16) | (g << 8) | r;
}
case Formats::RGBA8: {
case PICA::TextureFmt::RGBA8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 4);
auto ptr = static_cast<const u8*>(data);
@ -185,7 +185,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (alpha << 24) | (b << 16) | (g << 8) | r;
}
case Formats::IA4: {
case PICA::TextureFmt::IA4: {
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
auto ptr = static_cast<const u8*>(data);
@ -197,7 +197,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity;
}
case Formats::A4: {
case PICA::TextureFmt::A4: {
u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
auto ptr = static_cast<const u8*>(data);
@ -209,7 +209,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (alpha << 24) | (0 << 16) | (0 << 8) | 0;
}
case Formats::A8: {
case PICA::TextureFmt::A8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
auto ptr = static_cast<const u8*>(data);
const u8 alpha = ptr[offset];
@ -218,7 +218,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (alpha << 24) | (0 << 16) | (0 << 8) | 0;
}
case Formats::I4: {
case PICA::TextureFmt::I4: {
u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
auto ptr = static_cast<const u8*>(data);
@ -230,7 +230,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity;
}
case Formats::I8: {
case PICA::TextureFmt::I8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
auto ptr = static_cast<const u8*>(data);
const u8 intensity = ptr[offset];
@ -239,7 +239,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity;
}
case Formats::IA8: {
case PICA::TextureFmt::IA8: {
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
auto ptr = static_cast<const u8*>(data);
@ -249,8 +249,8 @@ u32 Texture::decodeTexel(u32 u, u32 v, Texture::Formats fmt, const void* data) {
return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity;
}
case Formats::ETC1: return getTexelETC(false, u, v, size.u(), data);
case Formats::ETC1A4: return getTexelETC(true, u, v, size.u(), data);
case PICA::TextureFmt::ETC1: return getTexelETC(false, u, v, size.u(), data);
case PICA::TextureFmt::ETC1A4: return getTexelETC(true, u, v, size.u(), data);
default:
Helpers::panic("[Texture::DecodeTexel] Unimplemented format = %d", static_cast<int>(fmt));
@ -271,24 +271,4 @@ void Texture::decodeTexture(const void* data) {
texture.bind();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.u(), size.v(), GL_RGBA, GL_UNSIGNED_BYTE, decoded.data());
}
std::string Texture::textureFormatToString(Texture::Formats fmt) {
switch (fmt) {
case Formats::A4: return "A4";
case Formats::A8: return "A8";
case Formats::ETC1: return "ETC1";
case Formats::ETC1A4: return "ETC1A4";
case Formats::I4: return "I4";
case Formats::I8: return "I8";
case Formats::IA4: return "IA4";
case Formats::IA8: return "IA8";
case Formats::RG8: return "RG8";
case Formats::RGB565: return "RGB565";
case Formats::RGB8: return "RGB8";
case Formats::RGBA4: return "RGBA4";
case Formats::RGBA5551: return "RGBA5551";
case Formats::RGBA8: return "RGBA8";
default: return "Unknown";
}
}

View file

@ -73,7 +73,7 @@ void CFGService::getConfigInfoBlk2(u32 messagePointer) {
};
for (int i = 0; i < 8; i++) {
mem.write32(output + i * 4, std::bit_cast<u32, float>(STEREO_CAMERA_SETTINGS[i]));
mem.write32(output + i * 4, Helpers::bit_cast<u32, float>(STEREO_CAMERA_SETTINGS[i]));
}
} else if (size == 0x1C && blockID == 0xA0000) { // Username
writeStringU16(output, u"Pander");

View file

@ -83,7 +83,7 @@ void HIDService::getGyroscopeCoefficient(u32 messagePointer) {
constexpr float gyroscopeCoeff = 14.375f; // Same as retail 3DS
mem.write32(messagePointer, IPC::responseHeader(0x15, 2, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, std::bit_cast<u32, float>(gyroscopeCoeff));
mem.write32(messagePointer + 8, Helpers::bit_cast<u32, float>(gyroscopeCoeff));
}
void HIDService::getIPCHandles(u32 messagePointer) {