diff --git a/include/PICA/gpu.hpp b/include/PICA/gpu.hpp index 4b60b3ef..2512e698 100644 --- a/include/PICA/gpu.hpp +++ b/include/PICA/gpu.hpp @@ -47,7 +47,7 @@ class GPU { }; u64 getVertexShaderInputConfig() { - return u64(regs[PICAInternalRegs::VertexShaderInputCfgLow]) | (u64(regs[PICAInternalRegs::VertexShaderInputCfgHigh]) << 32); + return u64(regs[PICA::InternalRegs::VertexShaderInputCfgLow]) | (u64(regs[PICA::InternalRegs::VertexShaderInputCfgHigh]) << 32); } std::array attributeInfo; // Info for each of the 12 attributes diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 89f13913..bcc658e9 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -1,131 +1,224 @@ #pragma once #include "helpers.hpp" -namespace PICAInternalRegs { - enum : u32 { - // Rasterizer registers - ViewportWidth = 0x41, - ViewportInvw = 0x42, - ViewportHeight = 0x43, - ViewportInvh = 0x44, +namespace PICA { + namespace InternalRegs { + enum : u32 { + // Rasterizer registers + ViewportWidth = 0x41, + ViewportInvw = 0x42, + ViewportHeight = 0x43, + ViewportInvh = 0x44, - DepthScale = 0x4D, - DepthOffset = 0x4E, - ShaderOutputCount = 0x4F, - ShaderOutmap0 = 0x50, + DepthScale = 0x4D, + DepthOffset = 0x4E, + ShaderOutputCount = 0x4F, + ShaderOutmap0 = 0x50, - DepthmapEnable = 0x6D, - TexUnitCfg = 0x80, + DepthmapEnable = 0x6D, + TexUnitCfg = 0x80, - // Framebuffer registers - ColourOperation = 0x100, - BlendFunc = 0x101, - BlendColour = 0x103, - AlphaTestConfig = 0x104, - DepthAndColorMask = 0x107, - DepthBufferFormat = 0x116, - ColourBufferFormat = 0x117, - DepthBufferLoc = 0x11C, - ColourBufferLoc = 0x11D, - FramebufferSize = 0x11E, + // Framebuffer registers + ColourOperation = 0x100, + BlendFunc = 0x101, + BlendColour = 0x103, + AlphaTestConfig = 0x104, + DepthAndColorMask = 0x107, + DepthBufferFormat = 0x116, + ColourBufferFormat = 0x117, + DepthBufferLoc = 0x11C, + ColourBufferLoc = 0x11D, + FramebufferSize = 0x11E, - // Geometry pipeline registers - VertexAttribLoc = 0x200, - AttribFormatLow = 0x201, - AttribFormatHigh = 0x202, - IndexBufferConfig = 0x227, - VertexCountReg = 0x228, - VertexOffsetReg = 0x22A, - SignalDrawArrays = 0x22E, - SignalDrawElements = 0x22F, + // Geometry pipeline registers + VertexAttribLoc = 0x200, + AttribFormatLow = 0x201, + AttribFormatHigh = 0x202, + IndexBufferConfig = 0x227, + VertexCountReg = 0x228, + VertexOffsetReg = 0x22A, + SignalDrawArrays = 0x22E, + SignalDrawElements = 0x22F, - Attrib0Offset = 0x203, - Attrib1Offset = 0x206, - Attrib2Offset = 0x209, - Attrib3Offset = 0x20C, - Attrib4Offset = 0x20F, - Attrib5Offset = 0x212, - Attrib6Offset = 0x215, - Attrib7Offset = 0x218, - Attrib8Offset = 0x21B, - Attrib9Offset = 0x21E, - Attrib10Offset = 0x221, - Attrib11Offset = 0x224, + Attrib0Offset = 0x203, + Attrib1Offset = 0x206, + Attrib2Offset = 0x209, + Attrib3Offset = 0x20C, + Attrib4Offset = 0x20F, + Attrib5Offset = 0x212, + Attrib6Offset = 0x215, + Attrib7Offset = 0x218, + Attrib8Offset = 0x21B, + Attrib9Offset = 0x21E, + Attrib10Offset = 0x221, + Attrib11Offset = 0x224, - Attrib0Config2 = 0x205, - Attrib1Config2 = 0x208, - Attrib2Config2 = 0x20B, - Attrib3Config2 = 0x20E, - Attrib4Config2 = 0x211, - Attrib5Config2 = 0x214, - Attrib6Config2 = 0x217, - Attrib7Config2 = 0x21A, - Attrib8Config2 = 0x21D, - Attrib9Config2 = 0x220, - Attrib10Config2 = 0x223, - Attrib11Config2 = 0x226, + Attrib0Config2 = 0x205, + Attrib1Config2 = 0x208, + Attrib2Config2 = 0x20B, + Attrib3Config2 = 0x20E, + Attrib4Config2 = 0x211, + Attrib5Config2 = 0x214, + Attrib6Config2 = 0x217, + Attrib7Config2 = 0x21A, + Attrib8Config2 = 0x21D, + Attrib9Config2 = 0x220, + Attrib10Config2 = 0x223, + Attrib11Config2 = 0x226, - AttribInfoStart = Attrib0Offset, - AttribInfoEnd = Attrib11Config2, + AttribInfoStart = Attrib0Offset, + AttribInfoEnd = Attrib11Config2, - // Fixed attribute registers - FixedAttribIndex = 0x232, - FixedAttribData0 = 0x233, - FixedAttribData1 = 0x234, - FixedAttribData2 = 0x235, + // Fixed attribute registers + FixedAttribIndex = 0x232, + FixedAttribData0 = 0x233, + FixedAttribData1 = 0x234, + FixedAttribData2 = 0x235, - // Command processor registers - CmdBufSize0 = 0x238, - CmdBufSize1 = 0x239, - CmdBufAddr0 = 0x23A, - CmdBufAddr1 = 0x23B, - CmdBufTrigger0 = 0x23C, - CmdBufTrigger1 = 0x23D, + // Command processor registers + CmdBufSize0 = 0x238, + CmdBufSize1 = 0x239, + CmdBufAddr0 = 0x23A, + CmdBufAddr1 = 0x23B, + CmdBufTrigger0 = 0x23C, + CmdBufTrigger1 = 0x23D, - PrimitiveConfig = 0x25E, - PrimitiveRestart = 0x25F, + PrimitiveConfig = 0x25E, + PrimitiveRestart = 0x25F, - // Vertex shader registers - VertexShaderAttrNum = 0x242, - VertexBoolUniform = 0x2B0, - VertexIntUniform0 = 0x2B1, - VertexIntUniform1 = 0x2B2, - VertexIntUniform2 = 0x2B3, - VertexIntUniform3 = 0x2B4, + // Vertex shader registers + VertexShaderAttrNum = 0x242, + VertexBoolUniform = 0x2B0, + VertexIntUniform0 = 0x2B1, + VertexIntUniform1 = 0x2B2, + VertexIntUniform2 = 0x2B3, + VertexIntUniform3 = 0x2B4, - VertexShaderEntrypoint = 0x2BA, - VertexShaderTransferEnd = 0x2BF, - VertexFloatUniformIndex = 0x2C0, - VertexFloatUniformData0 = 0x2C1, - VertexFloatUniformData1 = 0x2C2, - VertexFloatUniformData2 = 0x2C3, - VertexFloatUniformData3 = 0x2C4, - VertexFloatUniformData4 = 0x2C5, - VertexFloatUniformData5 = 0x2C6, - VertexFloatUniformData6 = 0x2C7, - VertexFloatUniformData7 = 0x2C8, + VertexShaderEntrypoint = 0x2BA, + VertexShaderTransferEnd = 0x2BF, + VertexFloatUniformIndex = 0x2C0, + VertexFloatUniformData0 = 0x2C1, + VertexFloatUniformData1 = 0x2C2, + VertexFloatUniformData2 = 0x2C3, + VertexFloatUniformData3 = 0x2C4, + VertexFloatUniformData4 = 0x2C5, + VertexFloatUniformData5 = 0x2C6, + VertexFloatUniformData6 = 0x2C7, + VertexFloatUniformData7 = 0x2C8, - VertexShaderInputBufferCfg = 0x2B9, - VertexShaderInputCfgLow = 0x2BB, - VertexShaderInputCfgHigh = 0x2BC, + VertexShaderInputBufferCfg = 0x2B9, + VertexShaderInputCfgLow = 0x2BB, + VertexShaderInputCfgHigh = 0x2BC, - VertexShaderTransferIndex = 0x2CB, - VertexShaderData0 = 0x2CC, - VertexShaderData1 = 0x2CD, - VertexShaderData2 = 0x2CE, - VertexShaderData3 = 0x2CF, - VertexShaderData4 = 0x2D0, - VertexShaderData5 = 0x2D1, - VertexShaderData6 = 0x2D2, - VertexShaderData7 = 0x2D3, - VertexShaderOpDescriptorIndex = 0x2D5, - VertexShaderOpDescriptorData0 = 0x2D6, - VertexShaderOpDescriptorData1 = 0x2D7, - VertexShaderOpDescriptorData2 = 0x2D8, - VertexShaderOpDescriptorData3 = 0x2D9, - VertexShaderOpDescriptorData4 = 0x2DA, - VertexShaderOpDescriptorData5 = 0x2DB, - VertexShaderOpDescriptorData6 = 0x2DC, - VertexShaderOpDescriptorData7 = 0x2DD, + VertexShaderTransferIndex = 0x2CB, + VertexShaderData0 = 0x2CC, + VertexShaderData1 = 0x2CD, + VertexShaderData2 = 0x2CE, + VertexShaderData3 = 0x2CF, + VertexShaderData4 = 0x2D0, + VertexShaderData5 = 0x2D1, + VertexShaderData6 = 0x2D2, + VertexShaderData7 = 0x2D3, + VertexShaderOpDescriptorIndex = 0x2D5, + VertexShaderOpDescriptorData0 = 0x2D6, + VertexShaderOpDescriptorData1 = 0x2D7, + VertexShaderOpDescriptorData2 = 0x2D8, + VertexShaderOpDescriptorData3 = 0x2D9, + VertexShaderOpDescriptorData4 = 0x2DA, + VertexShaderOpDescriptorData5 = 0x2DB, + VertexShaderOpDescriptorData6 = 0x2DC, + VertexShaderOpDescriptorData7 = 0x2DD, + }; + } + + enum class TextureFmt : u32 { + RGBA8 = 0x0, + RGB8 = 0x1, + RGBA5551 = 0x2, + RGB565 = 0x3, + RGBA4 = 0x4, + IA8 = 0x5, + RG8 = 0x6, + I8 = 0x7, + A8 = 0x8, + IA4 = 0x9, + I4 = 0xA, + A4 = 0xB, + ETC1 = 0xC, + ETC1A4 = 0xD, }; -} \ No newline at end of file + + enum class ColorFmt : u32 { + RGBA8 = 0x0, + RGB8 = 0x1, + RGBA5551 = 0x2, + RGB565 = 0x3, + RGBA4 = 0x4, + }; + + enum class DepthFmt : u32 { + Depth16 = 0, + Unknown1 = 1, // Technically selectable, but function is unknown + Depth24 = 2, + Depth24Stencil8 = 3, + }; + + // Returns the string representation of a texture format + inline constexpr const char* textureFormatToString(TextureFmt fmt) { + switch (fmt) { + case TextureFmt::RGBA8: return "RGBA8"; + case TextureFmt::RGB8: return "RGB8"; + case TextureFmt::RGBA5551: return "RGBA5551"; + case TextureFmt::RGB565: return "RGB565"; + case TextureFmt::RGBA4: return "RGBA4"; + case TextureFmt::IA8: return "IA8"; + case TextureFmt::RG8: return "RG8"; + case TextureFmt::I8: return "I8"; + case TextureFmt::A8: return "A8"; + case TextureFmt::IA4: return "IA4"; + case TextureFmt::I4: return "I4"; + case TextureFmt::A4: return "A4"; + case TextureFmt::ETC1: return "ETC1"; + case TextureFmt::ETC1A4: return "ETC1A4"; + default: return "Unknown"; + } + } + + inline constexpr const char* textureFormatToString(ColorFmt fmt) { + return textureFormatToString(static_cast(fmt)); + } + + inline constexpr bool hasStencil(DepthFmt format) { return format == PICA::DepthFmt::Depth24Stencil8; } + + // Size occupied by each pixel in bytes + + // All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) + inline constexpr usize sizePerPixel(TextureFmt format) { + switch (format) { + case TextureFmt::RGB8: return 3; + case TextureFmt::RGBA8: return 4; + default: return 2; + } + } + + inline constexpr usize sizePerPixel(ColorFmt format) { + return sizePerPixel(static_cast(format)); + } + + inline constexpr usize sizePerPixel(DepthFmt format) { + switch (format) { + case DepthFmt::Depth16: return 2; + case DepthFmt::Depth24: return 3; + case DepthFmt::Depth24Stencil8: return 4; + default: return 1; // Invalid format + } + } + + enum class PrimType : u32 { + TriangleList = 0, + TriangleStrip = 1, + TriangleFan = 2, + GeometryPrimitive = 3, + }; + +} // namespace PICA \ No newline at end of file diff --git a/include/helpers.hpp b/include/helpers.hpp index 237a333b..853e487b 100644 --- a/include/helpers.hpp +++ b/include/helpers.hpp @@ -1,6 +1,6 @@ #pragma once -#include #include +#include #include #include #include @@ -8,8 +8,16 @@ #include #include #include + #include "termcolor.hpp" +// We have to detect and special-case AppleClang at the moment since its C++20 support is finicky and doesn't quite support std::bit_cast +#if defined(__clang__) && defined(__apple_build_version__) +#define HELPERS_APPLE_CLANG +#else +#include +#endif + using u8 = std::uint8_t; using u16 = std::uint16_t; using u32 = std::uint32_t; @@ -23,78 +31,74 @@ using s32 = std::int32_t; using s64 = std::int64_t; namespace Helpers { - [[noreturn]] static void panic(const char* fmt, ...) { - std::va_list args; - va_start(args, fmt); - std::cout << termcolor::on_red << "[FATAL] "; - std::vprintf (fmt, args); - std::cout << termcolor::reset << "\n"; - va_end(args); + [[noreturn]] static void panic(const char* fmt, ...) { + std::va_list args; + va_start(args, fmt); + std::cout << termcolor::on_red << "[FATAL] "; + std::vprintf(fmt, args); + std::cout << termcolor::reset << "\n"; + va_end(args); - exit(1); - } + exit(1); + } - static void warn(const char* fmt, ...) { - std::va_list args; - va_start(args, fmt); - std::cout << termcolor::on_red << "[Warning] "; - std::vprintf (fmt, args); - std::cout << termcolor::reset << "\n"; - va_end(args); - } + static void warn(const char* fmt, ...) { + std::va_list args; + va_start(args, fmt); + std::cout << termcolor::on_red << "[Warning] "; + std::vprintf(fmt, args); + std::cout << termcolor::reset << "\n"; + va_end(args); + } - static std::vector loadROM(std::string directory) { - std::ifstream file (directory, std::ios::binary); - if (file.fail()) - panic("Couldn't read %s", directory.c_str()); + static std::vector loadROM(std::string directory) { + std::ifstream file(directory, std::ios::binary); + if (file.fail()) panic("Couldn't read %s", directory.c_str()); - std::vector ROM; + std::vector ROM; - file.unsetf(std::ios::skipws); - ROM.insert(ROM.begin(), - std::istream_iterator(file), - std::istream_iterator()); + file.unsetf(std::ios::skipws); + ROM.insert(ROM.begin(), std::istream_iterator(file), std::istream_iterator()); - file.close(); + file.close(); - printf ("%s loaded successfully\n", directory.c_str()); - return ROM; - } + printf("%s loaded successfully\n", directory.c_str()); + return ROM; + } - static constexpr bool buildingInDebugMode() { - #ifdef NDEBUG - return false; - #endif + static constexpr bool buildingInDebugMode() { +#ifdef NDEBUG + return false; +#endif + return true; + } - return true; - } - - static void debug_printf (const char* fmt, ...) { - if constexpr (buildingInDebugMode()) { - std::va_list args; - va_start(args, fmt); - std::vprintf (fmt, args); - va_end(args); - } - } + static void debug_printf(const char* fmt, ...) { + if constexpr (buildingInDebugMode()) { + std::va_list args; + va_start(args, fmt); + std::vprintf(fmt, args); + va_end(args); + } + } - /// Sign extend an arbitrary-size value to 32 bits - static constexpr u32 inline signExtend32 (u32 value, u32 startingSize) { - auto temp = (s32) value; - auto bitsToShift = 32 - startingSize; - return (u32) (temp << bitsToShift >> bitsToShift); - } + /// Sign extend an arbitrary-size value to 32 bits + static constexpr u32 inline signExtend32(u32 value, u32 startingSize) { + auto temp = (s32)value; + auto bitsToShift = 32 - startingSize; + return (u32)(temp << bitsToShift >> bitsToShift); + } - /// Sign extend an arbitrary-size value to 16 bits - static constexpr u16 signExtend16 (u16 value, u32 startingSize) { - auto temp = (s16) value; - auto bitsToShift = 16 - startingSize; - return (u16) (temp << bitsToShift >> bitsToShift); - } + /// Sign extend an arbitrary-size value to 16 bits + static constexpr u16 signExtend16(u16 value, u32 startingSize) { + auto temp = (s16)value; + auto bitsToShift = 16 - startingSize; + return (u16)(temp << bitsToShift >> bitsToShift); + } /// Create a mask with `count` number of one bits. - template - static constexpr T ones () { + template + static constexpr T ones() { constexpr usize bitsize = CHAR_BIT * sizeof(T); static_assert(count <= bitsize, "count larger than bitsize of T"); @@ -105,74 +109,74 @@ namespace Helpers { } /// Extract bits from an integer-type - template - static constexpr T getBit (T value) { - return (value >> offset) & T(1); + template + static constexpr T getBit(T value) { + return (value >> offset) & T(1); } /// Extract bits from an integer-type - template - static constexpr T getBits (T value) { - return (value >> offset) & ones(); + template + static constexpr T getBits(T value) { + return (value >> offset) & ones(); } - /// Check if a bit "bit" of value is set - static constexpr bool isBitSet (u32 value, int bit) { - return (value >> bit) & 1; - } + /// Check if a bit "bit" of value is set + static constexpr bool isBitSet(u32 value, int bit) { return (value >> bit) & 1; } - /// rotate number right - template - static constexpr T rotr (T value, int bits) { - constexpr auto bitWidth = sizeof(T) * 8; - bits &= bitWidth - 1; - return (value >> bits) | (value << (bitWidth - bits)); - } + /// rotate number right + template + static constexpr T rotr(T value, int bits) { + constexpr auto bitWidth = sizeof(T) * 8; + bits &= bitWidth - 1; + return (value >> bits) | (value << (bitWidth - bits)); + } - // rotate number left - template - static constexpr T rotl (T value, int bits) { - constexpr auto bitWidth = sizeof(T) * 8; - bits &= bitWidth - 1; - return (value << bits) | (value >> (bitWidth - bits)); - } + // rotate number left + template + static constexpr T rotl(T value, int bits) { + constexpr auto bitWidth = sizeof(T) * 8; + bits &= bitWidth - 1; + return (value << bits) | (value >> (bitWidth - bits)); + } - /// Used to make the compiler evaluate beeg loops at compile time for the tablegen - template - static constexpr void static_for_impl( Func&& f, std::integer_sequence ) { - ( f( std::integral_constant{ } ),... ); - } + /// Used to make the compiler evaluate beeg loops at compile time for the tablegen + template + static constexpr void static_for_impl(Func&& f, std::integer_sequence) { + (f(std::integral_constant{}), ...); + } - template - static constexpr void static_for(Func&& f) { - static_for_impl( std::forward(f), std::make_integer_sequence{ } ); - } + template + static constexpr void static_for(Func&& f) { + static_for_impl(std::forward(f), std::make_integer_sequence{}); + } - // For values < 0x99 - static constexpr inline u8 incBCDByte(u8 value) { - return ((value & 0xf) == 0x9) ? value + 7 : value + 1; - } -}; + // For values < 0x99 + static constexpr inline u8 incBCDByte(u8 value) { return ((value & 0xf) == 0x9) ? value + 7 : value + 1; } + +#ifdef HELPERS_APPLE_CLANG + template + constexpr To bit_cast(const From& from) noexcept { + return *reinterpret_cast(&from); + } +#else + template + constexpr To bit_cast(const From& from) noexcept { + return std::bit_cast(from); + } +#endif +}; // namespace Helpers // UDLs for memory size values -constexpr size_t operator""_KB(unsigned long long int x) { - return 1024ULL * x; -} - -constexpr size_t operator""_MB(unsigned long long int x) { - return 1024_KB * x; -} - -constexpr size_t operator""_GB(unsigned long long int x) { - return 1024_MB * x; -} +constexpr size_t operator""_KB(unsigned long long int x) { return 1024ULL * x; } +constexpr size_t operator""_MB(unsigned long long int x) { return 1024_KB * x; } +constexpr size_t operator""_GB(unsigned long long int x) { return 1024_MB * x; } // useful macros // likely/unlikely #ifdef __GNUC__ - #define likely(x) __builtin_expect((x),1) - #define unlikely(x) __builtin_expect((x),0) -#else - #define likely(x) (x) - #define unlikely(x) (x) -#endif \ No newline at end of file +#define likely(x) __builtin_expect((x), 1) +#define unlikely(x) __builtin_expect((x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 7ed9c1b2..9b592a12 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -8,6 +8,7 @@ #include "opengl.hpp" #include "surface_cache.hpp" #include "textures.hpp" +#include "PICA/regs.hpp" // More circular dependencies! class GPU; @@ -59,12 +60,12 @@ class Renderer { OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)' - u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer - ColourBuffer::Formats colourBufferFormat; // Format of the colours stored in the colour buffer + u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer + PICA::ColorFmt colourBufferFormat; // Format of the colours stored in the colour buffer // Same for the depth/stencil buffer u32 depthBufferLoc; - DepthBuffer::Formats depthBufferFormat; + PICA::DepthFmt depthBufferFormat; // Dummy VAO/VBO for blitting the final output OpenGL::VertexArray dummyVAO; @@ -93,23 +94,19 @@ class Renderer { void getGraphicsContext(); // Set up graphics context for rendering void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control); // Clear a GPU buffer in VRAM void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags); // Perform display transfer - void drawVertices(OpenGL::Primitives primType, std::span vertices); // Draw the given vertices + void drawVertices(PICA::PrimType primType, std::span vertices); // Draw the given vertices void setFBSize(u32 width, u32 height) { fbSize.x() = width; fbSize.y() = height; } - void setColourFormat(ColourBuffer::Formats format) { colourBufferFormat = format; } - void setColourFormat(u32 format) { colourBufferFormat = static_cast(format); } - - void setDepthFormat(DepthBuffer::Formats format) { depthBufferFormat = format; } - void setDepthFormat(u32 format) { - if (format == 1) { + void setColourFormat(PICA::ColorFmt format) { colourBufferFormat = format; } + void setDepthFormat(PICA::DepthFmt format) { + if (format == PICA::DepthFmt::Unknown1) { Helpers::panic("[PICA] Undocumented depth-stencil mode!"); } - - depthBufferFormat = static_cast(format); + depthBufferFormat = format; } void setColourBufferLoc(u32 loc) { colourBufferLoc = loc; } diff --git a/include/renderer_gl/surfaces.hpp b/include/renderer_gl/surfaces.hpp index 680a1454..7ff36c6d 100644 --- a/include/renderer_gl/surfaces.hpp +++ b/include/renderer_gl/surfaces.hpp @@ -1,4 +1,5 @@ #pragma once +#include "PICA/regs.hpp" #include "boost/icl/interval.hpp" #include "helpers.hpp" #include "opengl.hpp" @@ -7,18 +8,8 @@ template using Interval = boost::icl::right_open_interval; struct ColourBuffer { - enum class Formats : u32 { - RGBA8 = 0, - BGR8 = 1, - RGB5A1 = 2, - RGB565 = 3, - RGBA4 = 4, - - Trash1 = 5, Trash2 = 6, Trash3 = 7 // Technically selectable, but their function is unknown - }; - u32 location; - Formats format; + PICA::ColorFmt format; OpenGL::uvec2 size; bool valid; @@ -30,7 +21,7 @@ struct ColourBuffer { ColourBuffer() : valid(false) {} - ColourBuffer(u32 loc, Formats format, u32 x, u32 y, bool valid = true) + ColourBuffer(u32 loc, PICA::ColorFmt format, u32 x, u32 y, bool valid = true) : location(loc), format(format), size({x, y}), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -78,31 +69,14 @@ struct ColourBuffer { size.x() == other.size.x() && size.y() == other.size.y(); } - // Size occupied by each pixel in bytes - // All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) - size_t sizePerPixel() { - switch (format) { - case Formats::BGR8: return 3; - case Formats::RGBA8: return 4; - default: return 2; - } - } - size_t sizeInBytes() { - return (size_t)size.x() * (size_t)size.y() * sizePerPixel(); + return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format); } }; struct DepthBuffer { - enum class Formats : u32 { - Depth16 = 0, - Garbage = 1, - Depth24 = 2, - Depth24Stencil8 = 3 - }; - u32 location; - Formats format; + PICA::DepthFmt format; OpenGL::uvec2 size; // Implicitly set to the size of the framebuffer bool valid; @@ -113,7 +87,7 @@ struct DepthBuffer { DepthBuffer() : valid(false) {} - DepthBuffer(u32 loc, Formats format, u32 x, u32 y, bool valid = true) : + DepthBuffer(u32 loc, PICA::DepthFmt format, u32 x, u32 y, bool valid = true) : location(loc), format(format), size({x, y}), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -121,10 +95,6 @@ struct DepthBuffer { range = Interval(loc, (u32)endLoc); } - bool hasStencil() { - return format == Formats::Depth24Stencil8; - } - void allocate() { // Create texture for the FBO, setting up filters and the like // Reading back the current texture is slow, but allocate calls should be few and far between. @@ -167,18 +137,7 @@ struct DepthBuffer { size.x() == other.size.x() && size.y() == other.size.y(); } - // Size occupied by each pixel in bytes - size_t sizePerPixel() { - switch (format) { - case Formats::Depth16: return 2; - case Formats::Depth24: return 3; - case Formats::Depth24Stencil8: return 4; - - default: return 1; // Invalid format - } - } - size_t sizeInBytes() { - return (size_t)size.x() * (size_t)size.y() * sizePerPixel(); + return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format); } }; \ No newline at end of file diff --git a/include/renderer_gl/textures.hpp b/include/renderer_gl/textures.hpp index 3cf7871c..5469a59f 100644 --- a/include/renderer_gl/textures.hpp +++ b/include/renderer_gl/textures.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include "PICA/regs.hpp" #include "boost/icl/interval.hpp" #include "helpers.hpp" #include "opengl.hpp" @@ -9,28 +10,9 @@ template using Interval = boost::icl::right_open_interval; struct Texture { - enum class Formats : u32 { - RGBA8 = 0, - RGB8 = 1, - RGBA5551 = 2, - RGB565 = 3, - RGBA4 = 4, - IA8 = 5, - RG8 = 6, - I8 = 7, - A8 = 8, - IA4 = 9, - I4 = 10, - A4 = 11, - ETC1 = 12, - ETC1A4 = 13, - - Trash1 = 14, Trash2 = 15 // TODO: What are these? - }; - u32 location; u32 config; // Magnification/minification filter, wrapping configs, etc - Formats format; + PICA::TextureFmt format; OpenGL::uvec2 size; bool valid; @@ -41,7 +23,7 @@ struct Texture { Texture() : valid(false) {} - Texture(u32 loc, Formats format, u32 x, u32 y, u32 config, bool valid = true) + Texture(u32 loc, PICA::TextureFmt format, u32 x, u32 y, u32 config, bool valid = true) : location(loc), format(format), size({x, y}), config(config), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -62,7 +44,7 @@ struct Texture { void free(); u64 sizeInBytes(); - u32 decodeTexel(u32 u, u32 v, Formats fmt, const void* data); + u32 decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data); // Get the morton interleave offset of a texel based on its U and V values static u32 mortonInterleave(u32 u, u32 v); @@ -70,12 +52,9 @@ struct Texture { static u32 getSwizzledOffset(u32 u, u32 v, u32 width, u32 bytesPerPixel); static u32 getSwizzledOffset_4bpp(u32 u, u32 v, u32 width); - // Returns the string representation of a texture format - static std::string textureFormatToString(Formats fmt); - // Returns the format of this texture as a string std::string formatToString() { - return textureFormatToString(format); + return PICA::textureFormatToString(format); } // Returns the texel at coordinates (u, v) of an ETC1(A4) texture diff --git a/src/core/PICA/gpu.cpp b/src/core/PICA/gpu.cpp index e771fd86..4b896807 100644 --- a/src/core/PICA/gpu.cpp +++ b/src/core/PICA/gpu.cpp @@ -88,44 +88,45 @@ template 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(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(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 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++) { diff --git a/src/core/PICA/regs.cpp b/src/core/PICA/regs.cpp index 26feaf9d..14f61ef7 100644 --- a/src/core/PICA/regs.cpp +++ b/src/core/PICA/regs.cpp @@ -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(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(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 diff --git a/src/core/kernel/threads.cpp b/src/core/kernel/threads.cpp index cf6b2cac..c8325031 100644 --- a/src/core/kernel/threads.cpp +++ b/src/core/kernel/threads.cpp @@ -1,3 +1,4 @@ +#include #include #include diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 4c47eade..ff18d5cb 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -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 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 vertices) { +void Renderer::drawVertices(PICA::PrimType primType, std::span vertices) { + // The fourth type is meant to be "Geometry primitive". TODO: Find out what that is + static constexpr std::array primTypes = { + OpenGL::Triangle, OpenGL::TriangleStrip, OpenGL::TriangleFan, OpenGL::Triangle + }; + const auto primitiveTopology = primTypes[static_cast(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 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 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 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 u32 format = regs[ioBase + (i == 0 ? 14 : 6)] & 0xF; glActiveTexture(GL_TEXTURE0 + i); - Texture targetTex(addr, static_cast(format), width, height, config); + Texture targetTex(addr, static_cast(format), width, height, config); OpenGL::Texture tex = getTexture(targetTex); tex.bind(); } @@ -593,15 +599,15 @@ void Renderer::drawVertices(OpenGL::Primitives primType, std::span 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 } 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); } diff --git a/src/core/renderer_gl/textures.cpp b/src/core/renderer_gl/textures.cpp index f59d0779..a806e1eb 100644 --- a/src/core/renderer_gl/textures.cpp +++ b/src/core/renderer_gl/textures.cpp @@ -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(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(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(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(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(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(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(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(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(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(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(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(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(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"; - } } \ No newline at end of file diff --git a/src/core/services/cfg.cpp b/src/core/services/cfg.cpp index ab969183..6925e3d8 100644 --- a/src/core/services/cfg.cpp +++ b/src/core/services/cfg.cpp @@ -73,7 +73,7 @@ void CFGService::getConfigInfoBlk2(u32 messagePointer) { }; for (int i = 0; i < 8; i++) { - mem.write32(output + i * 4, std::bit_cast(STEREO_CAMERA_SETTINGS[i])); + mem.write32(output + i * 4, Helpers::bit_cast(STEREO_CAMERA_SETTINGS[i])); } } else if (size == 0x1C && blockID == 0xA0000) { // Username writeStringU16(output, u"Pander"); diff --git a/src/core/services/hid.cpp b/src/core/services/hid.cpp index ed7f2afd..7993dc7a 100644 --- a/src/core/services/hid.cpp +++ b/src/core/services/hid.cpp @@ -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(gyroscopeCoeff)); + mem.write32(messagePointer + 8, Helpers::bit_cast(gyroscopeCoeff)); } void HIDService::getIPCHandles(u32 messagePointer) {