diff options
Diffstat (limited to 'src/video_core/pica.h')
| -rw-r--r-- | src/video_core/pica.h | 651 |
1 files changed, 326 insertions, 325 deletions
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 7099c31a0..1d1a686e0 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -16,15 +16,16 @@ | |||
| 16 | #include "common/bit_field.h" | 16 | #include "common/bit_field.h" |
| 17 | #include "common/common_funcs.h" | 17 | #include "common/common_funcs.h" |
| 18 | #include "common/common_types.h" | 18 | #include "common/common_types.h" |
| 19 | #include "common/vector_math.h" | ||
| 20 | #include "common/logging/log.h" | 19 | #include "common/logging/log.h" |
| 20 | #include "common/vector_math.h" | ||
| 21 | 21 | ||
| 22 | namespace Pica { | 22 | namespace Pica { |
| 23 | 23 | ||
| 24 | // Returns index corresponding to the Regs member labeled by field_name | 24 | // Returns index corresponding to the Regs member labeled by field_name |
| 25 | // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions | 25 | // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions |
| 26 | // when used with array elements (e.g. PICA_REG_INDEX(vs_uniform_setup.set_value[1])). | 26 | // when used with array elements (e.g. PICA_REG_INDEX(vs_uniform_setup.set_value[1])). |
| 27 | // For details cf. https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members | 27 | // For details cf. |
| 28 | // https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members | ||
| 28 | // Hopefully, this will be fixed sometime in the future. | 29 | // Hopefully, this will be fixed sometime in the future. |
| 29 | // For lack of better alternatives, we currently hardcode the offsets when constant | 30 | // For lack of better alternatives, we currently hardcode the offsets when constant |
| 30 | // expressions are needed via PICA_REG_INDEX_WORKAROUND (on sane compilers, static_asserts | 31 | // expressions are needed via PICA_REG_INDEX_WORKAROUND (on sane compilers, static_asserts |
| @@ -37,8 +38,9 @@ namespace Pica { | |||
| 37 | // really is this annoying. This macro just forwards its first argument to PICA_REG_INDEX | 38 | // really is this annoying. This macro just forwards its first argument to PICA_REG_INDEX |
| 38 | // and then performs a (no-op) cast to size_t iff the second argument matches the expected | 39 | // and then performs a (no-op) cast to size_t iff the second argument matches the expected |
| 39 | // field offset. Otherwise, the compiler will fail to compile this code. | 40 | // field offset. Otherwise, the compiler will fail to compile this code. |
| 40 | #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ | 41 | #define PICA_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ |
| 41 | ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), size_t>::type)PICA_REG_INDEX(field_name)) | 42 | ((typename std::enable_if<backup_workaround_index == PICA_REG_INDEX(field_name), \ |
| 43 | size_t>::type)PICA_REG_INDEX(field_name)) | ||
| 42 | #endif // _MSC_VER | 44 | #endif // _MSC_VER |
| 43 | 45 | ||
| 44 | struct Regs { | 46 | struct Regs { |
| @@ -51,8 +53,8 @@ struct Regs { | |||
| 51 | 53 | ||
| 52 | enum class CullMode : u32 { | 54 | enum class CullMode : u32 { |
| 53 | // Select which polygons are considered to be "frontfacing". | 55 | // Select which polygons are considered to be "frontfacing". |
| 54 | KeepAll = 0, | 56 | KeepAll = 0, |
| 55 | KeepClockWise = 1, | 57 | KeepClockWise = 1, |
| 56 | KeepCounterClockWise = 2, | 58 | KeepCounterClockWise = 2, |
| 57 | // TODO: What does the third value imply? | 59 | // TODO: What does the third value imply? |
| 58 | }; | 60 | }; |
| @@ -69,48 +71,47 @@ struct Regs { | |||
| 69 | 71 | ||
| 70 | INSERT_PADDING_WORDS(0x9); | 72 | INSERT_PADDING_WORDS(0x9); |
| 71 | 73 | ||
| 72 | BitField<0, 24, u32> viewport_depth_range; // float24 | 74 | BitField<0, 24, u32> viewport_depth_range; // float24 |
| 73 | BitField<0, 24, u32> viewport_depth_near_plane; // float24 | 75 | BitField<0, 24, u32> viewport_depth_near_plane; // float24 |
| 74 | 76 | ||
| 75 | BitField<0, 3, u32> vs_output_total; | 77 | BitField<0, 3, u32> vs_output_total; |
| 76 | 78 | ||
| 77 | union VSOutputAttributes { | 79 | union VSOutputAttributes { |
| 78 | // Maps components of output vertex attributes to semantics | 80 | // Maps components of output vertex attributes to semantics |
| 79 | enum Semantic : u32 | 81 | enum Semantic : u32 { |
| 80 | { | 82 | POSITION_X = 0, |
| 81 | POSITION_X = 0, | 83 | POSITION_Y = 1, |
| 82 | POSITION_Y = 1, | 84 | POSITION_Z = 2, |
| 83 | POSITION_Z = 2, | 85 | POSITION_W = 3, |
| 84 | POSITION_W = 3, | 86 | |
| 85 | 87 | QUATERNION_X = 4, | |
| 86 | QUATERNION_X = 4, | 88 | QUATERNION_Y = 5, |
| 87 | QUATERNION_Y = 5, | 89 | QUATERNION_Z = 6, |
| 88 | QUATERNION_Z = 6, | 90 | QUATERNION_W = 7, |
| 89 | QUATERNION_W = 7, | 91 | |
| 90 | 92 | COLOR_R = 8, | |
| 91 | COLOR_R = 8, | 93 | COLOR_G = 9, |
| 92 | COLOR_G = 9, | 94 | COLOR_B = 10, |
| 93 | COLOR_B = 10, | 95 | COLOR_A = 11, |
| 94 | COLOR_A = 11, | 96 | |
| 95 | 97 | TEXCOORD0_U = 12, | |
| 96 | TEXCOORD0_U = 12, | 98 | TEXCOORD0_V = 13, |
| 97 | TEXCOORD0_V = 13, | 99 | TEXCOORD1_U = 14, |
| 98 | TEXCOORD1_U = 14, | 100 | TEXCOORD1_V = 15, |
| 99 | TEXCOORD1_V = 15, | ||
| 100 | 101 | ||
| 101 | // TODO: Not verified | 102 | // TODO: Not verified |
| 102 | VIEW_X = 18, | 103 | VIEW_X = 18, |
| 103 | VIEW_Y = 19, | 104 | VIEW_Y = 19, |
| 104 | VIEW_Z = 20, | 105 | VIEW_Z = 20, |
| 105 | 106 | ||
| 106 | TEXCOORD2_U = 22, | 107 | TEXCOORD2_U = 22, |
| 107 | TEXCOORD2_V = 23, | 108 | TEXCOORD2_V = 23, |
| 108 | 109 | ||
| 109 | INVALID = 31, | 110 | INVALID = 31, |
| 110 | }; | 111 | }; |
| 111 | 112 | ||
| 112 | BitField< 0, 5, Semantic> map_x; | 113 | BitField<0, 5, Semantic> map_x; |
| 113 | BitField< 8, 5, Semantic> map_y; | 114 | BitField<8, 5, Semantic> map_y; |
| 114 | BitField<16, 5, Semantic> map_z; | 115 | BitField<16, 5, Semantic> map_z; |
| 115 | BitField<24, 5, Semantic> map_w; | 116 | BitField<24, 5, Semantic> map_w; |
| 116 | } vs_output_attributes[7]; | 117 | } vs_output_attributes[7]; |
| @@ -128,77 +129,75 @@ struct Regs { | |||
| 128 | BitField<0, 2, ScissorMode> mode; | 129 | BitField<0, 2, ScissorMode> mode; |
| 129 | 130 | ||
| 130 | union { | 131 | union { |
| 131 | BitField< 0, 16, u32> x1; | 132 | BitField<0, 16, u32> x1; |
| 132 | BitField<16, 16, u32> y1; | 133 | BitField<16, 16, u32> y1; |
| 133 | }; | 134 | }; |
| 134 | 135 | ||
| 135 | union { | 136 | union { |
| 136 | BitField< 0, 16, u32> x2; | 137 | BitField<0, 16, u32> x2; |
| 137 | BitField<16, 16, u32> y2; | 138 | BitField<16, 16, u32> y2; |
| 138 | }; | 139 | }; |
| 139 | } scissor_test; | 140 | } scissor_test; |
| 140 | 141 | ||
| 141 | union { | 142 | union { |
| 142 | BitField< 0, 10, s32> x; | 143 | BitField<0, 10, s32> x; |
| 143 | BitField<16, 10, s32> y; | 144 | BitField<16, 10, s32> y; |
| 144 | } viewport_corner; | 145 | } viewport_corner; |
| 145 | 146 | ||
| 146 | INSERT_PADDING_WORDS(0x1); | 147 | INSERT_PADDING_WORDS(0x1); |
| 147 | 148 | ||
| 148 | //TODO: early depth | 149 | // TODO: early depth |
| 149 | INSERT_PADDING_WORDS(0x1); | 150 | INSERT_PADDING_WORDS(0x1); |
| 150 | 151 | ||
| 151 | INSERT_PADDING_WORDS(0x2); | 152 | INSERT_PADDING_WORDS(0x2); |
| 152 | 153 | ||
| 153 | enum DepthBuffering : u32 { | 154 | enum DepthBuffering : u32 { |
| 154 | WBuffering = 0, | 155 | WBuffering = 0, |
| 155 | ZBuffering = 1, | 156 | ZBuffering = 1, |
| 156 | }; | 157 | }; |
| 157 | BitField< 0, 1, DepthBuffering> depthmap_enable; | 158 | BitField<0, 1, DepthBuffering> depthmap_enable; |
| 158 | 159 | ||
| 159 | INSERT_PADDING_WORDS(0x12); | 160 | INSERT_PADDING_WORDS(0x12); |
| 160 | 161 | ||
| 161 | struct TextureConfig { | 162 | struct TextureConfig { |
| 162 | enum TextureType : u32 { | 163 | enum TextureType : u32 { |
| 163 | Texture2D = 0, | 164 | Texture2D = 0, |
| 164 | TextureCube = 1, | 165 | TextureCube = 1, |
| 165 | Shadow2D = 2, | 166 | Shadow2D = 2, |
| 166 | Projection2D = 3, | 167 | Projection2D = 3, |
| 167 | ShadowCube = 4, | 168 | ShadowCube = 4, |
| 168 | Disabled = 5, | 169 | Disabled = 5, |
| 169 | }; | 170 | }; |
| 170 | 171 | ||
| 171 | enum WrapMode : u32 { | 172 | enum WrapMode : u32 { |
| 172 | ClampToEdge = 0, | 173 | ClampToEdge = 0, |
| 173 | ClampToBorder = 1, | 174 | ClampToBorder = 1, |
| 174 | Repeat = 2, | 175 | Repeat = 2, |
| 175 | MirroredRepeat = 3, | 176 | MirroredRepeat = 3, |
| 176 | }; | 177 | }; |
| 177 | 178 | ||
| 178 | enum TextureFilter : u32 { | 179 | enum TextureFilter : u32 { Nearest = 0, Linear = 1 }; |
| 179 | Nearest = 0, | ||
| 180 | Linear = 1 | ||
| 181 | }; | ||
| 182 | 180 | ||
| 183 | union { | 181 | union { |
| 184 | u32 raw; | 182 | u32 raw; |
| 185 | BitField< 0, 8, u32> r; | 183 | BitField<0, 8, u32> r; |
| 186 | BitField< 8, 8, u32> g; | 184 | BitField<8, 8, u32> g; |
| 187 | BitField<16, 8, u32> b; | 185 | BitField<16, 8, u32> b; |
| 188 | BitField<24, 8, u32> a; | 186 | BitField<24, 8, u32> a; |
| 189 | } border_color; | 187 | } border_color; |
| 190 | 188 | ||
| 191 | union { | 189 | union { |
| 192 | BitField< 0, 16, u32> height; | 190 | BitField<0, 16, u32> height; |
| 193 | BitField<16, 16, u32> width; | 191 | BitField<16, 16, u32> width; |
| 194 | }; | 192 | }; |
| 195 | 193 | ||
| 196 | union { | 194 | union { |
| 197 | BitField< 1, 1, TextureFilter> mag_filter; | 195 | BitField<1, 1, TextureFilter> mag_filter; |
| 198 | BitField< 2, 1, TextureFilter> min_filter; | 196 | BitField<2, 1, TextureFilter> min_filter; |
| 199 | BitField< 8, 2, WrapMode> wrap_t; | 197 | BitField<8, 2, WrapMode> wrap_t; |
| 200 | BitField<12, 2, WrapMode> wrap_s; | 198 | BitField<12, 2, WrapMode> wrap_s; |
| 201 | BitField<28, 2, TextureType> type; ///< @note Only valid for texture 0 according to 3DBrew. | 199 | BitField<28, 2, TextureType> |
| 200 | type; ///< @note Only valid for texture 0 according to 3DBrew. | ||
| 202 | }; | 201 | }; |
| 203 | 202 | ||
| 204 | INSERT_PADDING_WORDS(0x1); | 203 | INSERT_PADDING_WORDS(0x1); |
| @@ -216,39 +215,39 @@ struct Regs { | |||
| 216 | }; | 215 | }; |
| 217 | 216 | ||
| 218 | enum class TextureFormat : u32 { | 217 | enum class TextureFormat : u32 { |
| 219 | RGBA8 = 0, | 218 | RGBA8 = 0, |
| 220 | RGB8 = 1, | 219 | RGB8 = 1, |
| 221 | RGB5A1 = 2, | 220 | RGB5A1 = 2, |
| 222 | RGB565 = 3, | 221 | RGB565 = 3, |
| 223 | RGBA4 = 4, | 222 | RGBA4 = 4, |
| 224 | IA8 = 5, | 223 | IA8 = 5, |
| 225 | RG8 = 6, ///< @note Also called HILO8 in 3DBrew. | 224 | RG8 = 6, ///< @note Also called HILO8 in 3DBrew. |
| 226 | I8 = 7, | 225 | I8 = 7, |
| 227 | A8 = 8, | 226 | A8 = 8, |
| 228 | IA4 = 9, | 227 | IA4 = 9, |
| 229 | I4 = 10, | 228 | I4 = 10, |
| 230 | A4 = 11, | 229 | A4 = 11, |
| 231 | ETC1 = 12, // compressed | 230 | ETC1 = 12, // compressed |
| 232 | ETC1A4 = 13, // compressed | 231 | ETC1A4 = 13, // compressed |
| 233 | }; | 232 | }; |
| 234 | 233 | ||
| 235 | enum class LogicOp : u32 { | 234 | enum class LogicOp : u32 { |
| 236 | Clear = 0, | 235 | Clear = 0, |
| 237 | And = 1, | 236 | And = 1, |
| 238 | AndReverse = 2, | 237 | AndReverse = 2, |
| 239 | Copy = 3, | 238 | Copy = 3, |
| 240 | Set = 4, | 239 | Set = 4, |
| 241 | CopyInverted = 5, | 240 | CopyInverted = 5, |
| 242 | NoOp = 6, | 241 | NoOp = 6, |
| 243 | Invert = 7, | 242 | Invert = 7, |
| 244 | Nand = 8, | 243 | Nand = 8, |
| 245 | Or = 9, | 244 | Or = 9, |
| 246 | Nor = 10, | 245 | Nor = 10, |
| 247 | Xor = 11, | 246 | Xor = 11, |
| 248 | Equiv = 12, | 247 | Equiv = 12, |
| 249 | AndInverted = 13, | 248 | AndInverted = 13, |
| 250 | OrReverse = 14, | 249 | OrReverse = 14, |
| 251 | OrInverted = 15, | 250 | OrInverted = 15, |
| 252 | }; | 251 | }; |
| 253 | 252 | ||
| 254 | static unsigned NibblesPerPixel(TextureFormat format) { | 253 | static unsigned NibblesPerPixel(TextureFormat format) { |
| @@ -273,15 +272,15 @@ struct Regs { | |||
| 273 | case TextureFormat::I8: | 272 | case TextureFormat::I8: |
| 274 | case TextureFormat::A8: | 273 | case TextureFormat::A8: |
| 275 | case TextureFormat::IA4: | 274 | case TextureFormat::IA4: |
| 276 | default: // placeholder for yet unknown formats | 275 | default: // placeholder for yet unknown formats |
| 277 | return 2; | 276 | return 2; |
| 278 | } | 277 | } |
| 279 | } | 278 | } |
| 280 | 279 | ||
| 281 | union { | 280 | union { |
| 282 | BitField< 0, 1, u32> texture0_enable; | 281 | BitField<0, 1, u32> texture0_enable; |
| 283 | BitField< 1, 1, u32> texture1_enable; | 282 | BitField<1, 1, u32> texture1_enable; |
| 284 | BitField< 2, 1, u32> texture2_enable; | 283 | BitField<2, 1, u32> texture2_enable; |
| 285 | }; | 284 | }; |
| 286 | TextureConfig texture0; | 285 | TextureConfig texture0; |
| 287 | INSERT_PADDING_WORDS(0x8); | 286 | INSERT_PADDING_WORDS(0x8); |
| @@ -301,64 +300,62 @@ struct Regs { | |||
| 301 | const TextureFormat format; | 300 | const TextureFormat format; |
| 302 | }; | 301 | }; |
| 303 | const std::array<FullTextureConfig, 3> GetTextures() const { | 302 | const std::array<FullTextureConfig, 3> GetTextures() const { |
| 304 | return {{ | 303 | return {{{texture0_enable.ToBool(), texture0, texture0_format}, |
| 305 | { texture0_enable.ToBool(), texture0, texture0_format }, | 304 | {texture1_enable.ToBool(), texture1, texture1_format}, |
| 306 | { texture1_enable.ToBool(), texture1, texture1_format }, | 305 | {texture2_enable.ToBool(), texture2, texture2_format}}}; |
| 307 | { texture2_enable.ToBool(), texture2, texture2_format } | ||
| 308 | }}; | ||
| 309 | } | 306 | } |
| 310 | 307 | ||
| 311 | // 0xc0-0xff: Texture Combiner (akin to glTexEnv) | 308 | // 0xc0-0xff: Texture Combiner (akin to glTexEnv) |
| 312 | struct TevStageConfig { | 309 | struct TevStageConfig { |
| 313 | enum class Source : u32 { | 310 | enum class Source : u32 { |
| 314 | PrimaryColor = 0x0, | 311 | PrimaryColor = 0x0, |
| 315 | PrimaryFragmentColor = 0x1, | 312 | PrimaryFragmentColor = 0x1, |
| 316 | SecondaryFragmentColor = 0x2, | 313 | SecondaryFragmentColor = 0x2, |
| 317 | 314 | ||
| 318 | Texture0 = 0x3, | 315 | Texture0 = 0x3, |
| 319 | Texture1 = 0x4, | 316 | Texture1 = 0x4, |
| 320 | Texture2 = 0x5, | 317 | Texture2 = 0x5, |
| 321 | Texture3 = 0x6, | 318 | Texture3 = 0x6, |
| 322 | 319 | ||
| 323 | PreviousBuffer = 0xd, | 320 | PreviousBuffer = 0xd, |
| 324 | Constant = 0xe, | 321 | Constant = 0xe, |
| 325 | Previous = 0xf, | 322 | Previous = 0xf, |
| 326 | }; | 323 | }; |
| 327 | 324 | ||
| 328 | enum class ColorModifier : u32 { | 325 | enum class ColorModifier : u32 { |
| 329 | SourceColor = 0x0, | 326 | SourceColor = 0x0, |
| 330 | OneMinusSourceColor = 0x1, | 327 | OneMinusSourceColor = 0x1, |
| 331 | SourceAlpha = 0x2, | 328 | SourceAlpha = 0x2, |
| 332 | OneMinusSourceAlpha = 0x3, | 329 | OneMinusSourceAlpha = 0x3, |
| 333 | SourceRed = 0x4, | 330 | SourceRed = 0x4, |
| 334 | OneMinusSourceRed = 0x5, | 331 | OneMinusSourceRed = 0x5, |
| 335 | 332 | ||
| 336 | SourceGreen = 0x8, | 333 | SourceGreen = 0x8, |
| 337 | OneMinusSourceGreen = 0x9, | 334 | OneMinusSourceGreen = 0x9, |
| 338 | 335 | ||
| 339 | SourceBlue = 0xc, | 336 | SourceBlue = 0xc, |
| 340 | OneMinusSourceBlue = 0xd, | 337 | OneMinusSourceBlue = 0xd, |
| 341 | }; | 338 | }; |
| 342 | 339 | ||
| 343 | enum class AlphaModifier : u32 { | 340 | enum class AlphaModifier : u32 { |
| 344 | SourceAlpha = 0x0, | 341 | SourceAlpha = 0x0, |
| 345 | OneMinusSourceAlpha = 0x1, | 342 | OneMinusSourceAlpha = 0x1, |
| 346 | SourceRed = 0x2, | 343 | SourceRed = 0x2, |
| 347 | OneMinusSourceRed = 0x3, | 344 | OneMinusSourceRed = 0x3, |
| 348 | SourceGreen = 0x4, | 345 | SourceGreen = 0x4, |
| 349 | OneMinusSourceGreen = 0x5, | 346 | OneMinusSourceGreen = 0x5, |
| 350 | SourceBlue = 0x6, | 347 | SourceBlue = 0x6, |
| 351 | OneMinusSourceBlue = 0x7, | 348 | OneMinusSourceBlue = 0x7, |
| 352 | }; | 349 | }; |
| 353 | 350 | ||
| 354 | enum class Operation : u32 { | 351 | enum class Operation : u32 { |
| 355 | Replace = 0, | 352 | Replace = 0, |
| 356 | Modulate = 1, | 353 | Modulate = 1, |
| 357 | Add = 2, | 354 | Add = 2, |
| 358 | AddSigned = 3, | 355 | AddSigned = 3, |
| 359 | Lerp = 4, | 356 | Lerp = 4, |
| 360 | Subtract = 5, | 357 | Subtract = 5, |
| 361 | Dot3_RGB = 6, | 358 | Dot3_RGB = 6, |
| 362 | 359 | ||
| 363 | MultiplyThenAdd = 8, | 360 | MultiplyThenAdd = 8, |
| 364 | AddThenMultiply = 9, | 361 | AddThenMultiply = 9, |
| @@ -366,9 +363,9 @@ struct Regs { | |||
| 366 | 363 | ||
| 367 | union { | 364 | union { |
| 368 | u32 sources_raw; | 365 | u32 sources_raw; |
| 369 | BitField< 0, 4, Source> color_source1; | 366 | BitField<0, 4, Source> color_source1; |
| 370 | BitField< 4, 4, Source> color_source2; | 367 | BitField<4, 4, Source> color_source2; |
| 371 | BitField< 8, 4, Source> color_source3; | 368 | BitField<8, 4, Source> color_source3; |
| 372 | BitField<16, 4, Source> alpha_source1; | 369 | BitField<16, 4, Source> alpha_source1; |
| 373 | BitField<20, 4, Source> alpha_source2; | 370 | BitField<20, 4, Source> alpha_source2; |
| 374 | BitField<24, 4, Source> alpha_source3; | 371 | BitField<24, 4, Source> alpha_source3; |
| @@ -376,9 +373,9 @@ struct Regs { | |||
| 376 | 373 | ||
| 377 | union { | 374 | union { |
| 378 | u32 modifiers_raw; | 375 | u32 modifiers_raw; |
| 379 | BitField< 0, 4, ColorModifier> color_modifier1; | 376 | BitField<0, 4, ColorModifier> color_modifier1; |
| 380 | BitField< 4, 4, ColorModifier> color_modifier2; | 377 | BitField<4, 4, ColorModifier> color_modifier2; |
| 381 | BitField< 8, 4, ColorModifier> color_modifier3; | 378 | BitField<8, 4, ColorModifier> color_modifier3; |
| 382 | BitField<12, 3, AlphaModifier> alpha_modifier1; | 379 | BitField<12, 3, AlphaModifier> alpha_modifier1; |
| 383 | BitField<16, 3, AlphaModifier> alpha_modifier2; | 380 | BitField<16, 3, AlphaModifier> alpha_modifier2; |
| 384 | BitField<20, 3, AlphaModifier> alpha_modifier3; | 381 | BitField<20, 3, AlphaModifier> alpha_modifier3; |
| @@ -386,21 +383,21 @@ struct Regs { | |||
| 386 | 383 | ||
| 387 | union { | 384 | union { |
| 388 | u32 ops_raw; | 385 | u32 ops_raw; |
| 389 | BitField< 0, 4, Operation> color_op; | 386 | BitField<0, 4, Operation> color_op; |
| 390 | BitField<16, 4, Operation> alpha_op; | 387 | BitField<16, 4, Operation> alpha_op; |
| 391 | }; | 388 | }; |
| 392 | 389 | ||
| 393 | union { | 390 | union { |
| 394 | u32 const_color; | 391 | u32 const_color; |
| 395 | BitField< 0, 8, u32> const_r; | 392 | BitField<0, 8, u32> const_r; |
| 396 | BitField< 8, 8, u32> const_g; | 393 | BitField<8, 8, u32> const_g; |
| 397 | BitField<16, 8, u32> const_b; | 394 | BitField<16, 8, u32> const_b; |
| 398 | BitField<24, 8, u32> const_a; | 395 | BitField<24, 8, u32> const_a; |
| 399 | }; | 396 | }; |
| 400 | 397 | ||
| 401 | union { | 398 | union { |
| 402 | u32 scales_raw; | 399 | u32 scales_raw; |
| 403 | BitField< 0, 2, u32> color_scale; | 400 | BitField<0, 2, u32> color_scale; |
| 404 | BitField<16, 2, u32> alpha_scale; | 401 | BitField<16, 2, u32> alpha_scale; |
| 405 | }; | 402 | }; |
| 406 | 403 | ||
| @@ -424,8 +421,8 @@ struct Regs { | |||
| 424 | 421 | ||
| 425 | enum class FogMode : u32 { | 422 | enum class FogMode : u32 { |
| 426 | None = 0, | 423 | None = 0, |
| 427 | Fog = 5, | 424 | Fog = 5, |
| 428 | Gas = 7, | 425 | Gas = 7, |
| 429 | }; | 426 | }; |
| 430 | 427 | ||
| 431 | union { | 428 | union { |
| @@ -435,7 +432,7 @@ struct Regs { | |||
| 435 | union { | 432 | union { |
| 436 | // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in | 433 | // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in |
| 437 | // these masks are set | 434 | // these masks are set |
| 438 | BitField< 8, 4, u32> update_mask_rgb; | 435 | BitField<8, 4, u32> update_mask_rgb; |
| 439 | BitField<12, 4, u32> update_mask_a; | 436 | BitField<12, 4, u32> update_mask_a; |
| 440 | 437 | ||
| 441 | bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const { | 438 | bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const { |
| @@ -450,8 +447,8 @@ struct Regs { | |||
| 450 | 447 | ||
| 451 | union { | 448 | union { |
| 452 | u32 raw; | 449 | u32 raw; |
| 453 | BitField< 0, 8, u32> r; | 450 | BitField<0, 8, u32> r; |
| 454 | BitField< 8, 8, u32> g; | 451 | BitField<8, 8, u32> g; |
| 455 | BitField<16, 8, u32> b; | 452 | BitField<16, 8, u32> b; |
| 456 | } fog_color; | 453 | } fog_color; |
| 457 | 454 | ||
| @@ -469,66 +466,64 @@ struct Regs { | |||
| 469 | 466 | ||
| 470 | union { | 467 | union { |
| 471 | u32 raw; | 468 | u32 raw; |
| 472 | BitField< 0, 8, u32> r; | 469 | BitField<0, 8, u32> r; |
| 473 | BitField< 8, 8, u32> g; | 470 | BitField<8, 8, u32> g; |
| 474 | BitField<16, 8, u32> b; | 471 | BitField<16, 8, u32> b; |
| 475 | BitField<24, 8, u32> a; | 472 | BitField<24, 8, u32> a; |
| 476 | } tev_combiner_buffer_color; | 473 | } tev_combiner_buffer_color; |
| 477 | 474 | ||
| 478 | INSERT_PADDING_WORDS(0x2); | 475 | INSERT_PADDING_WORDS(0x2); |
| 479 | 476 | ||
| 480 | const std::array<Regs::TevStageConfig,6> GetTevStages() const { | 477 | const std::array<Regs::TevStageConfig, 6> GetTevStages() const { |
| 481 | return {{ tev_stage0, tev_stage1, | 478 | return {{tev_stage0, tev_stage1, tev_stage2, tev_stage3, tev_stage4, tev_stage5}}; |
| 482 | tev_stage2, tev_stage3, | ||
| 483 | tev_stage4, tev_stage5 }}; | ||
| 484 | }; | 479 | }; |
| 485 | 480 | ||
| 486 | enum class BlendEquation : u32 { | 481 | enum class BlendEquation : u32 { |
| 487 | Add = 0, | 482 | Add = 0, |
| 488 | Subtract = 1, | 483 | Subtract = 1, |
| 489 | ReverseSubtract = 2, | 484 | ReverseSubtract = 2, |
| 490 | Min = 3, | 485 | Min = 3, |
| 491 | Max = 4, | 486 | Max = 4, |
| 492 | }; | 487 | }; |
| 493 | 488 | ||
| 494 | enum class BlendFactor : u32 { | 489 | enum class BlendFactor : u32 { |
| 495 | Zero = 0, | 490 | Zero = 0, |
| 496 | One = 1, | 491 | One = 1, |
| 497 | SourceColor = 2, | 492 | SourceColor = 2, |
| 498 | OneMinusSourceColor = 3, | 493 | OneMinusSourceColor = 3, |
| 499 | DestColor = 4, | 494 | DestColor = 4, |
| 500 | OneMinusDestColor = 5, | 495 | OneMinusDestColor = 5, |
| 501 | SourceAlpha = 6, | 496 | SourceAlpha = 6, |
| 502 | OneMinusSourceAlpha = 7, | 497 | OneMinusSourceAlpha = 7, |
| 503 | DestAlpha = 8, | 498 | DestAlpha = 8, |
| 504 | OneMinusDestAlpha = 9, | 499 | OneMinusDestAlpha = 9, |
| 505 | ConstantColor = 10, | 500 | ConstantColor = 10, |
| 506 | OneMinusConstantColor = 11, | 501 | OneMinusConstantColor = 11, |
| 507 | ConstantAlpha = 12, | 502 | ConstantAlpha = 12, |
| 508 | OneMinusConstantAlpha = 13, | 503 | OneMinusConstantAlpha = 13, |
| 509 | SourceAlphaSaturate = 14, | 504 | SourceAlphaSaturate = 14, |
| 510 | }; | 505 | }; |
| 511 | 506 | ||
| 512 | enum class CompareFunc : u32 { | 507 | enum class CompareFunc : u32 { |
| 513 | Never = 0, | 508 | Never = 0, |
| 514 | Always = 1, | 509 | Always = 1, |
| 515 | Equal = 2, | 510 | Equal = 2, |
| 516 | NotEqual = 3, | 511 | NotEqual = 3, |
| 517 | LessThan = 4, | 512 | LessThan = 4, |
| 518 | LessThanOrEqual = 5, | 513 | LessThanOrEqual = 5, |
| 519 | GreaterThan = 6, | 514 | GreaterThan = 6, |
| 520 | GreaterThanOrEqual = 7, | 515 | GreaterThanOrEqual = 7, |
| 521 | }; | 516 | }; |
| 522 | 517 | ||
| 523 | enum class StencilAction : u32 { | 518 | enum class StencilAction : u32 { |
| 524 | Keep = 0, | 519 | Keep = 0, |
| 525 | Zero = 1, | 520 | Zero = 1, |
| 526 | Replace = 2, | 521 | Replace = 2, |
| 527 | Increment = 3, | 522 | Increment = 3, |
| 528 | Decrement = 4, | 523 | Decrement = 4, |
| 529 | Invert = 5, | 524 | Invert = 5, |
| 530 | IncrementWrap = 6, | 525 | IncrementWrap = 6, |
| 531 | DecrementWrap = 7 | 526 | DecrementWrap = 7 |
| 532 | }; | 527 | }; |
| 533 | 528 | ||
| 534 | struct { | 529 | struct { |
| @@ -538,8 +533,8 @@ struct Regs { | |||
| 538 | }; | 533 | }; |
| 539 | 534 | ||
| 540 | union { | 535 | union { |
| 541 | BitField< 0, 8, BlendEquation> blend_equation_rgb; | 536 | BitField<0, 8, BlendEquation> blend_equation_rgb; |
| 542 | BitField< 8, 8, BlendEquation> blend_equation_a; | 537 | BitField<8, 8, BlendEquation> blend_equation_a; |
| 543 | 538 | ||
| 544 | BitField<16, 4, BlendFactor> factor_source_rgb; | 539 | BitField<16, 4, BlendFactor> factor_source_rgb; |
| 545 | BitField<20, 4, BlendFactor> factor_dest_rgb; | 540 | BitField<20, 4, BlendFactor> factor_dest_rgb; |
| @@ -554,16 +549,16 @@ struct Regs { | |||
| 554 | 549 | ||
| 555 | union { | 550 | union { |
| 556 | u32 raw; | 551 | u32 raw; |
| 557 | BitField< 0, 8, u32> r; | 552 | BitField<0, 8, u32> r; |
| 558 | BitField< 8, 8, u32> g; | 553 | BitField<8, 8, u32> g; |
| 559 | BitField<16, 8, u32> b; | 554 | BitField<16, 8, u32> b; |
| 560 | BitField<24, 8, u32> a; | 555 | BitField<24, 8, u32> a; |
| 561 | } blend_const; | 556 | } blend_const; |
| 562 | 557 | ||
| 563 | union { | 558 | union { |
| 564 | BitField< 0, 1, u32> enable; | 559 | BitField<0, 1, u32> enable; |
| 565 | BitField< 4, 3, CompareFunc> func; | 560 | BitField<4, 3, CompareFunc> func; |
| 566 | BitField< 8, 8, u32> ref; | 561 | BitField<8, 8, u32> ref; |
| 567 | } alpha_test; | 562 | } alpha_test; |
| 568 | 563 | ||
| 569 | struct { | 564 | struct { |
| @@ -572,13 +567,13 @@ struct Regs { | |||
| 572 | u32 raw_func; | 567 | u32 raw_func; |
| 573 | 568 | ||
| 574 | // If true, enable stencil testing | 569 | // If true, enable stencil testing |
| 575 | BitField< 0, 1, u32> enable; | 570 | BitField<0, 1, u32> enable; |
| 576 | 571 | ||
| 577 | // Comparison operation for stencil testing | 572 | // Comparison operation for stencil testing |
| 578 | BitField< 4, 3, CompareFunc> func; | 573 | BitField<4, 3, CompareFunc> func; |
| 579 | 574 | ||
| 580 | // Mask used to control writing to the stencil buffer | 575 | // Mask used to control writing to the stencil buffer |
| 581 | BitField< 8, 8, u32> write_mask; | 576 | BitField<8, 8, u32> write_mask; |
| 582 | 577 | ||
| 583 | // Value to compare against for stencil testing | 578 | // Value to compare against for stencil testing |
| 584 | BitField<16, 8, u32> reference_value; | 579 | BitField<16, 8, u32> reference_value; |
| @@ -592,21 +587,21 @@ struct Regs { | |||
| 592 | u32 raw_op; | 587 | u32 raw_op; |
| 593 | 588 | ||
| 594 | // Action to perform when the stencil test fails | 589 | // Action to perform when the stencil test fails |
| 595 | BitField< 0, 3, StencilAction> action_stencil_fail; | 590 | BitField<0, 3, StencilAction> action_stencil_fail; |
| 596 | 591 | ||
| 597 | // Action to perform when stencil testing passed but depth testing fails | 592 | // Action to perform when stencil testing passed but depth testing fails |
| 598 | BitField< 4, 3, StencilAction> action_depth_fail; | 593 | BitField<4, 3, StencilAction> action_depth_fail; |
| 599 | 594 | ||
| 600 | // Action to perform when both stencil and depth testing pass | 595 | // Action to perform when both stencil and depth testing pass |
| 601 | BitField< 8, 3, StencilAction> action_depth_pass; | 596 | BitField<8, 3, StencilAction> action_depth_pass; |
| 602 | }; | 597 | }; |
| 603 | } stencil_test; | 598 | } stencil_test; |
| 604 | 599 | ||
| 605 | union { | 600 | union { |
| 606 | BitField< 0, 1, u32> depth_test_enable; | 601 | BitField<0, 1, u32> depth_test_enable; |
| 607 | BitField< 4, 3, CompareFunc> depth_test_func; | 602 | BitField<4, 3, CompareFunc> depth_test_func; |
| 608 | BitField< 8, 1, u32> red_enable; | 603 | BitField<8, 1, u32> red_enable; |
| 609 | BitField< 9, 1, u32> green_enable; | 604 | BitField<9, 1, u32> green_enable; |
| 610 | BitField<10, 1, u32> blue_enable; | 605 | BitField<10, 1, u32> blue_enable; |
| 611 | BitField<11, 1, u32> alpha_enable; | 606 | BitField<11, 1, u32> alpha_enable; |
| 612 | BitField<12, 1, u32> depth_write_enable; | 607 | BitField<12, 1, u32> depth_write_enable; |
| @@ -617,16 +612,16 @@ struct Regs { | |||
| 617 | 612 | ||
| 618 | // Components are laid out in reverse byte order, most significant bits first. | 613 | // Components are laid out in reverse byte order, most significant bits first. |
| 619 | enum class ColorFormat : u32 { | 614 | enum class ColorFormat : u32 { |
| 620 | RGBA8 = 0, | 615 | RGBA8 = 0, |
| 621 | RGB8 = 1, | 616 | RGB8 = 1, |
| 622 | RGB5A1 = 2, | 617 | RGB5A1 = 2, |
| 623 | RGB565 = 3, | 618 | RGB565 = 3, |
| 624 | RGBA4 = 4, | 619 | RGBA4 = 4, |
| 625 | }; | 620 | }; |
| 626 | 621 | ||
| 627 | enum class DepthFormat : u32 { | 622 | enum class DepthFormat : u32 { |
| 628 | D16 = 0, | 623 | D16 = 0, |
| 629 | D24 = 2, | 624 | D24 = 2, |
| 630 | D24S8 = 3, | 625 | D24S8 = 3, |
| 631 | }; | 626 | }; |
| 632 | 627 | ||
| @@ -673,7 +668,7 @@ struct Regs { | |||
| 673 | // while the height is stored as the actual height minus one. | 668 | // while the height is stored as the actual height minus one. |
| 674 | // Hence, don't access these fields directly but use the accessors | 669 | // Hence, don't access these fields directly but use the accessors |
| 675 | // GetWidth() and GetHeight() instead. | 670 | // GetWidth() and GetHeight() instead. |
| 676 | BitField< 0, 11, u32> width; | 671 | BitField<0, 11, u32> width; |
| 677 | BitField<12, 10, u32> height; | 672 | BitField<12, 10, u32> height; |
| 678 | }; | 673 | }; |
| 679 | 674 | ||
| @@ -759,10 +754,12 @@ struct Regs { | |||
| 759 | 754 | ||
| 760 | /// Selects which lighting components are affected by fresnel | 755 | /// Selects which lighting components are affected by fresnel |
| 761 | enum class LightingFresnelSelector { | 756 | enum class LightingFresnelSelector { |
| 762 | None = 0, ///< Fresnel is disabled | 757 | None = 0, ///< Fresnel is disabled |
| 763 | PrimaryAlpha = 1, ///< Primary (diffuse) lighting alpha is affected by fresnel | 758 | PrimaryAlpha = 1, ///< Primary (diffuse) lighting alpha is affected by fresnel |
| 764 | SecondaryAlpha = 2, ///< Secondary (specular) lighting alpha is affected by fresnel | 759 | SecondaryAlpha = 2, ///< Secondary (specular) lighting alpha is affected by fresnel |
| 765 | Both = PrimaryAlpha | SecondaryAlpha, ///< Both primary and secondary lighting alphas are affected by fresnel | 760 | Both = |
| 761 | PrimaryAlpha | | ||
| 762 | SecondaryAlpha, ///< Both primary and secondary lighting alphas are affected by fresnel | ||
| 766 | }; | 763 | }; |
| 767 | 764 | ||
| 768 | /// Factor used to scale the output of a lighting LUT | 765 | /// Factor used to scale the output of a lighting LUT |
| @@ -789,57 +786,63 @@ struct Regs { | |||
| 789 | }; | 786 | }; |
| 790 | 787 | ||
| 791 | union LightColor { | 788 | union LightColor { |
| 792 | BitField< 0, 10, u32> b; | 789 | BitField<0, 10, u32> b; |
| 793 | BitField<10, 10, u32> g; | 790 | BitField<10, 10, u32> g; |
| 794 | BitField<20, 10, u32> r; | 791 | BitField<20, 10, u32> r; |
| 795 | 792 | ||
| 796 | Math::Vec3f ToVec3f() const { | 793 | Math::Vec3f ToVec3f() const { |
| 797 | // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color component | 794 | // These fields are 10 bits wide, however 255 corresponds to 1.0f for each color |
| 795 | // component | ||
| 798 | return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); | 796 | return Math::MakeVec((f32)r / 255.f, (f32)g / 255.f, (f32)b / 255.f); |
| 799 | } | 797 | } |
| 800 | }; | 798 | }; |
| 801 | 799 | ||
| 802 | /// Returns true if the specified lighting sampler is supported by the current Pica lighting configuration | 800 | /// Returns true if the specified lighting sampler is supported by the current Pica lighting |
| 801 | /// configuration | ||
| 803 | static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) { | 802 | static bool IsLightingSamplerSupported(LightingConfig config, LightingSampler sampler) { |
| 804 | switch (sampler) { | 803 | switch (sampler) { |
| 805 | case LightingSampler::Distribution0: | 804 | case LightingSampler::Distribution0: |
| 806 | return (config != LightingConfig::Config1); | 805 | return (config != LightingConfig::Config1); |
| 807 | 806 | ||
| 808 | case LightingSampler::Distribution1: | 807 | case LightingSampler::Distribution1: |
| 809 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && (config != LightingConfig::Config5); | 808 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config1) && |
| 809 | (config != LightingConfig::Config5); | ||
| 810 | 810 | ||
| 811 | case LightingSampler::Fresnel: | 811 | case LightingSampler::Fresnel: |
| 812 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config2) && (config != LightingConfig::Config4); | 812 | return (config != LightingConfig::Config0) && (config != LightingConfig::Config2) && |
| 813 | (config != LightingConfig::Config4); | ||
| 813 | 814 | ||
| 814 | case LightingSampler::ReflectRed: | 815 | case LightingSampler::ReflectRed: |
| 815 | return (config != LightingConfig::Config3); | 816 | return (config != LightingConfig::Config3); |
| 816 | 817 | ||
| 817 | case LightingSampler::ReflectGreen: | 818 | case LightingSampler::ReflectGreen: |
| 818 | case LightingSampler::ReflectBlue: | 819 | case LightingSampler::ReflectBlue: |
| 819 | return (config == LightingConfig::Config4) || (config == LightingConfig::Config5) || (config == LightingConfig::Config7); | 820 | return (config == LightingConfig::Config4) || (config == LightingConfig::Config5) || |
| 821 | (config == LightingConfig::Config7); | ||
| 820 | default: | 822 | default: |
| 821 | UNREACHABLE_MSG("Regs::IsLightingSamplerSupported: Reached " | 823 | UNREACHABLE_MSG("Regs::IsLightingSamplerSupported: Reached " |
| 822 | "unreachable section, sampler should be one " | 824 | "unreachable section, sampler should be one " |
| 823 | "of Distribution0, Distribution1, Fresnel, " | 825 | "of Distribution0, Distribution1, Fresnel, " |
| 824 | "ReflectRed, ReflectGreen or ReflectBlue, instead " | 826 | "ReflectRed, ReflectGreen or ReflectBlue, instead " |
| 825 | "got %i", static_cast<int>(config)); | 827 | "got %i", |
| 828 | static_cast<int>(config)); | ||
| 826 | } | 829 | } |
| 827 | } | 830 | } |
| 828 | 831 | ||
| 829 | struct { | 832 | struct { |
| 830 | struct LightSrc { | 833 | struct LightSrc { |
| 831 | LightColor specular_0; // material.specular_0 * light.specular_0 | 834 | LightColor specular_0; // material.specular_0 * light.specular_0 |
| 832 | LightColor specular_1; // material.specular_1 * light.specular_1 | 835 | LightColor specular_1; // material.specular_1 * light.specular_1 |
| 833 | LightColor diffuse; // material.diffuse * light.diffuse | 836 | LightColor diffuse; // material.diffuse * light.diffuse |
| 834 | LightColor ambient; // material.ambient * light.ambient | 837 | LightColor ambient; // material.ambient * light.ambient |
| 835 | 838 | ||
| 836 | // Encoded as 16-bit floating point | 839 | // Encoded as 16-bit floating point |
| 837 | union { | 840 | union { |
| 838 | BitField< 0, 16, u32> x; | 841 | BitField<0, 16, u32> x; |
| 839 | BitField<16, 16, u32> y; | 842 | BitField<16, 16, u32> y; |
| 840 | }; | 843 | }; |
| 841 | union { | 844 | union { |
| 842 | BitField< 0, 16, u32> z; | 845 | BitField<0, 16, u32> z; |
| 843 | }; | 846 | }; |
| 844 | 847 | ||
| 845 | INSERT_PADDING_WORDS(0x3); | 848 | INSERT_PADDING_WORDS(0x3); |
| @@ -854,7 +857,8 @@ struct Regs { | |||
| 854 | 857 | ||
| 855 | INSERT_PADDING_WORDS(0x4); | 858 | INSERT_PADDING_WORDS(0x4); |
| 856 | }; | 859 | }; |
| 857 | static_assert(sizeof(LightSrc) == 0x10 * sizeof(u32), "LightSrc structure must be 0x10 words"); | 860 | static_assert(sizeof(LightSrc) == 0x10 * sizeof(u32), |
| 861 | "LightSrc structure must be 0x10 words"); | ||
| 858 | 862 | ||
| 859 | LightSrc light[8]; | 863 | LightSrc light[8]; |
| 860 | LightColor global_ambient; // Emission + (material.ambient * lighting.ambient) | 864 | LightColor global_ambient; // Emission + (material.ambient * lighting.ambient) |
| @@ -862,8 +866,8 @@ struct Regs { | |||
| 862 | BitField<0, 3, u32> num_lights; // Number of enabled lights - 1 | 866 | BitField<0, 3, u32> num_lights; // Number of enabled lights - 1 |
| 863 | 867 | ||
| 864 | union { | 868 | union { |
| 865 | BitField< 2, 2, LightingFresnelSelector> fresnel_selector; | 869 | BitField<2, 2, LightingFresnelSelector> fresnel_selector; |
| 866 | BitField< 4, 4, LightingConfig> config; | 870 | BitField<4, 4, LightingConfig> config; |
| 867 | BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2 | 871 | BitField<22, 2, u32> bump_selector; // 0: Texture 0, 1: Texture 1, 2: Texture 2 |
| 868 | BitField<27, 1, u32> clamp_highlights; | 872 | BitField<27, 1, u32> clamp_highlights; |
| 869 | BitField<28, 2, LightingBumpMode> bump_mode; | 873 | BitField<28, 2, LightingBumpMode> bump_mode; |
| @@ -892,16 +896,17 @@ struct Regs { | |||
| 892 | } config1; | 896 | } config1; |
| 893 | 897 | ||
| 894 | bool IsDistAttenDisabled(unsigned index) const { | 898 | bool IsDistAttenDisabled(unsigned index) const { |
| 895 | const unsigned disable[] = { config1.disable_dist_atten_light_0, config1.disable_dist_atten_light_1, | 899 | const unsigned disable[] = { |
| 896 | config1.disable_dist_atten_light_2, config1.disable_dist_atten_light_3, | 900 | config1.disable_dist_atten_light_0, config1.disable_dist_atten_light_1, |
| 897 | config1.disable_dist_atten_light_4, config1.disable_dist_atten_light_5, | 901 | config1.disable_dist_atten_light_2, config1.disable_dist_atten_light_3, |
| 898 | config1.disable_dist_atten_light_6, config1.disable_dist_atten_light_7 }; | 902 | config1.disable_dist_atten_light_4, config1.disable_dist_atten_light_5, |
| 903 | config1.disable_dist_atten_light_6, config1.disable_dist_atten_light_7}; | ||
| 899 | return disable[index] != 0; | 904 | return disable[index] != 0; |
| 900 | } | 905 | } |
| 901 | 906 | ||
| 902 | union { | 907 | union { |
| 903 | BitField<0, 8, u32> index; ///< Index at which to set data in the LUT | 908 | BitField<0, 8, u32> index; ///< Index at which to set data in the LUT |
| 904 | BitField<8, 5, u32> type; ///< Type of LUT for which to set data | 909 | BitField<8, 5, u32> type; ///< Type of LUT for which to set data |
| 905 | } lut_config; | 910 | } lut_config; |
| 906 | 911 | ||
| 907 | BitField<0, 1, u32> disable; | 912 | BitField<0, 1, u32> disable; |
| @@ -917,9 +922,9 @@ struct Regs { | |||
| 917 | // abs mode is disabled, LUT indexes are in the range of (-1.0, 1.0). Otherwise, they are in | 922 | // abs mode is disabled, LUT indexes are in the range of (-1.0, 1.0). Otherwise, they are in |
| 918 | // the range of (0.0, 1.0). | 923 | // the range of (0.0, 1.0). |
| 919 | union { | 924 | union { |
| 920 | BitField< 1, 1, u32> disable_d0; | 925 | BitField<1, 1, u32> disable_d0; |
| 921 | BitField< 5, 1, u32> disable_d1; | 926 | BitField<5, 1, u32> disable_d1; |
| 922 | BitField< 9, 1, u32> disable_sp; | 927 | BitField<9, 1, u32> disable_sp; |
| 923 | BitField<13, 1, u32> disable_fr; | 928 | BitField<13, 1, u32> disable_fr; |
| 924 | BitField<17, 1, u32> disable_rb; | 929 | BitField<17, 1, u32> disable_rb; |
| 925 | BitField<21, 1, u32> disable_rg; | 930 | BitField<21, 1, u32> disable_rg; |
| @@ -927,9 +932,9 @@ struct Regs { | |||
| 927 | } abs_lut_input; | 932 | } abs_lut_input; |
| 928 | 933 | ||
| 929 | union { | 934 | union { |
| 930 | BitField< 0, 3, LightingLutInput> d0; | 935 | BitField<0, 3, LightingLutInput> d0; |
| 931 | BitField< 4, 3, LightingLutInput> d1; | 936 | BitField<4, 3, LightingLutInput> d1; |
| 932 | BitField< 8, 3, LightingLutInput> sp; | 937 | BitField<8, 3, LightingLutInput> sp; |
| 933 | BitField<12, 3, LightingLutInput> fr; | 938 | BitField<12, 3, LightingLutInput> fr; |
| 934 | BitField<16, 3, LightingLutInput> rb; | 939 | BitField<16, 3, LightingLutInput> rb; |
| 935 | BitField<20, 3, LightingLutInput> rg; | 940 | BitField<20, 3, LightingLutInput> rg; |
| @@ -937,9 +942,9 @@ struct Regs { | |||
| 937 | } lut_input; | 942 | } lut_input; |
| 938 | 943 | ||
| 939 | union { | 944 | union { |
| 940 | BitField< 0, 3, LightingScale> d0; | 945 | BitField<0, 3, LightingScale> d0; |
| 941 | BitField< 4, 3, LightingScale> d1; | 946 | BitField<4, 3, LightingScale> d1; |
| 942 | BitField< 8, 3, LightingScale> sp; | 947 | BitField<8, 3, LightingScale> sp; |
| 943 | BitField<12, 3, LightingScale> fr; | 948 | BitField<12, 3, LightingScale> fr; |
| 944 | BitField<16, 3, LightingScale> rb; | 949 | BitField<16, 3, LightingScale> rb; |
| 945 | BitField<20, 3, LightingScale> rg; | 950 | BitField<20, 3, LightingScale> rg; |
| @@ -972,9 +977,9 @@ struct Regs { | |||
| 972 | // above), the first N slots below will be set to integers within the range of 0-7, | 977 | // above), the first N slots below will be set to integers within the range of 0-7, |
| 973 | // corresponding to the actual light that is enabled for each slot. | 978 | // corresponding to the actual light that is enabled for each slot. |
| 974 | 979 | ||
| 975 | BitField< 0, 3, u32> slot_0; | 980 | BitField<0, 3, u32> slot_0; |
| 976 | BitField< 4, 3, u32> slot_1; | 981 | BitField<4, 3, u32> slot_1; |
| 977 | BitField< 8, 3, u32> slot_2; | 982 | BitField<8, 3, u32> slot_2; |
| 978 | BitField<12, 3, u32> slot_3; | 983 | BitField<12, 3, u32> slot_3; |
| 979 | BitField<16, 3, u32> slot_4; | 984 | BitField<16, 3, u32> slot_4; |
| 980 | BitField<20, 3, u32> slot_5; | 985 | BitField<20, 3, u32> slot_5; |
| @@ -982,7 +987,8 @@ struct Regs { | |||
| 982 | BitField<28, 3, u32> slot_7; | 987 | BitField<28, 3, u32> slot_7; |
| 983 | 988 | ||
| 984 | unsigned GetNum(unsigned index) const { | 989 | unsigned GetNum(unsigned index) const { |
| 985 | const unsigned enable_slots[] = { slot_0, slot_1, slot_2, slot_3, slot_4, slot_5, slot_6, slot_7 }; | 990 | const unsigned enable_slots[] = {slot_0, slot_1, slot_2, slot_3, |
| 991 | slot_4, slot_5, slot_6, slot_7}; | ||
| 986 | return enable_slots[index]; | 992 | return enable_slots[index]; |
| 987 | } | 993 | } |
| 988 | } light_enable; | 994 | } light_enable; |
| @@ -1006,58 +1012,54 @@ struct Regs { | |||
| 1006 | 1012 | ||
| 1007 | // Descriptor for internal vertex attributes | 1013 | // Descriptor for internal vertex attributes |
| 1008 | union { | 1014 | union { |
| 1009 | BitField< 0, 2, VertexAttributeFormat> format0; // size of one element | 1015 | BitField<0, 2, VertexAttributeFormat> format0; // size of one element |
| 1010 | BitField< 2, 2, u64> size0; // number of elements minus 1 | 1016 | BitField<2, 2, u64> size0; // number of elements minus 1 |
| 1011 | BitField< 4, 2, VertexAttributeFormat> format1; | 1017 | BitField<4, 2, VertexAttributeFormat> format1; |
| 1012 | BitField< 6, 2, u64> size1; | 1018 | BitField<6, 2, u64> size1; |
| 1013 | BitField< 8, 2, VertexAttributeFormat> format2; | 1019 | BitField<8, 2, VertexAttributeFormat> format2; |
| 1014 | BitField<10, 2, u64> size2; | 1020 | BitField<10, 2, u64> size2; |
| 1015 | BitField<12, 2, VertexAttributeFormat> format3; | 1021 | BitField<12, 2, VertexAttributeFormat> format3; |
| 1016 | BitField<14, 2, u64> size3; | 1022 | BitField<14, 2, u64> size3; |
| 1017 | BitField<16, 2, VertexAttributeFormat> format4; | 1023 | BitField<16, 2, VertexAttributeFormat> format4; |
| 1018 | BitField<18, 2, u64> size4; | 1024 | BitField<18, 2, u64> size4; |
| 1019 | BitField<20, 2, VertexAttributeFormat> format5; | 1025 | BitField<20, 2, VertexAttributeFormat> format5; |
| 1020 | BitField<22, 2, u64> size5; | 1026 | BitField<22, 2, u64> size5; |
| 1021 | BitField<24, 2, VertexAttributeFormat> format6; | 1027 | BitField<24, 2, VertexAttributeFormat> format6; |
| 1022 | BitField<26, 2, u64> size6; | 1028 | BitField<26, 2, u64> size6; |
| 1023 | BitField<28, 2, VertexAttributeFormat> format7; | 1029 | BitField<28, 2, VertexAttributeFormat> format7; |
| 1024 | BitField<30, 2, u64> size7; | 1030 | BitField<30, 2, u64> size7; |
| 1025 | BitField<32, 2, VertexAttributeFormat> format8; | 1031 | BitField<32, 2, VertexAttributeFormat> format8; |
| 1026 | BitField<34, 2, u64> size8; | 1032 | BitField<34, 2, u64> size8; |
| 1027 | BitField<36, 2, VertexAttributeFormat> format9; | 1033 | BitField<36, 2, VertexAttributeFormat> format9; |
| 1028 | BitField<38, 2, u64> size9; | 1034 | BitField<38, 2, u64> size9; |
| 1029 | BitField<40, 2, VertexAttributeFormat> format10; | 1035 | BitField<40, 2, VertexAttributeFormat> format10; |
| 1030 | BitField<42, 2, u64> size10; | 1036 | BitField<42, 2, u64> size10; |
| 1031 | BitField<44, 2, VertexAttributeFormat> format11; | 1037 | BitField<44, 2, VertexAttributeFormat> format11; |
| 1032 | BitField<46, 2, u64> size11; | 1038 | BitField<46, 2, u64> size11; |
| 1033 | 1039 | ||
| 1034 | BitField<48, 12, u64> attribute_mask; | 1040 | BitField<48, 12, u64> attribute_mask; |
| 1035 | 1041 | ||
| 1036 | // number of total attributes minus 1 | 1042 | // number of total attributes minus 1 |
| 1037 | BitField<60, 4, u64> num_extra_attributes; | 1043 | BitField<60, 4, u64> num_extra_attributes; |
| 1038 | }; | 1044 | }; |
| 1039 | 1045 | ||
| 1040 | inline VertexAttributeFormat GetFormat(int n) const { | 1046 | inline VertexAttributeFormat GetFormat(int n) const { |
| 1041 | VertexAttributeFormat formats[] = { | 1047 | VertexAttributeFormat formats[] = {format0, format1, format2, format3, |
| 1042 | format0, format1, format2, format3, | 1048 | format4, format5, format6, format7, |
| 1043 | format4, format5, format6, format7, | 1049 | format8, format9, format10, format11}; |
| 1044 | format8, format9, format10, format11 | ||
| 1045 | }; | ||
| 1046 | return formats[n]; | 1050 | return formats[n]; |
| 1047 | } | 1051 | } |
| 1048 | 1052 | ||
| 1049 | inline int GetNumElements(int n) const { | 1053 | inline int GetNumElements(int n) const { |
| 1050 | u64 sizes[] = { | 1054 | u64 sizes[] = {size0, size1, size2, size3, size4, size5, |
| 1051 | size0, size1, size2, size3, | 1055 | size6, size7, size8, size9, size10, size11}; |
| 1052 | size4, size5, size6, size7, | 1056 | return (int)sizes[n] + 1; |
| 1053 | size8, size9, size10, size11 | ||
| 1054 | }; | ||
| 1055 | return (int)sizes[n]+1; | ||
| 1056 | } | 1057 | } |
| 1057 | 1058 | ||
| 1058 | inline int GetElementSizeInBytes(int n) const { | 1059 | inline int GetElementSizeInBytes(int n) const { |
| 1059 | return (GetFormat(n) == VertexAttributeFormat::FLOAT) ? 4 : | 1060 | return (GetFormat(n) == VertexAttributeFormat::FLOAT) |
| 1060 | (GetFormat(n) == VertexAttributeFormat::SHORT) ? 2 : 1; | 1061 | ? 4 |
| 1062 | : (GetFormat(n) == VertexAttributeFormat::SHORT) ? 2 : 1; | ||
| 1061 | } | 1063 | } |
| 1062 | 1064 | ||
| 1063 | inline int GetStride(int n) const { | 1065 | inline int GetStride(int n) const { |
| @@ -1069,7 +1071,7 @@ struct Regs { | |||
| 1069 | } | 1071 | } |
| 1070 | 1072 | ||
| 1071 | inline int GetNumTotalAttributes() const { | 1073 | inline int GetNumTotalAttributes() const { |
| 1072 | return (int)num_extra_attributes+1; | 1074 | return (int)num_extra_attributes + 1; |
| 1073 | } | 1075 | } |
| 1074 | 1076 | ||
| 1075 | // Attribute loaders map the source vertex data to input attributes | 1077 | // Attribute loaders map the source vertex data to input attributes |
| @@ -1079,9 +1081,9 @@ struct Regs { | |||
| 1079 | u32 data_offset; | 1081 | u32 data_offset; |
| 1080 | 1082 | ||
| 1081 | union { | 1083 | union { |
| 1082 | BitField< 0, 4, u64> comp0; | 1084 | BitField<0, 4, u64> comp0; |
| 1083 | BitField< 4, 4, u64> comp1; | 1085 | BitField<4, 4, u64> comp1; |
| 1084 | BitField< 8, 4, u64> comp2; | 1086 | BitField<8, 4, u64> comp2; |
| 1085 | BitField<12, 4, u64> comp3; | 1087 | BitField<12, 4, u64> comp3; |
| 1086 | BitField<16, 4, u64> comp4; | 1088 | BitField<16, 4, u64> comp4; |
| 1087 | BitField<20, 4, u64> comp5; | 1089 | BitField<20, 4, u64> comp5; |
| @@ -1099,11 +1101,8 @@ struct Regs { | |||
| 1099 | }; | 1101 | }; |
| 1100 | 1102 | ||
| 1101 | inline int GetComponent(int n) const { | 1103 | inline int GetComponent(int n) const { |
| 1102 | u64 components[] = { | 1104 | u64 components[] = {comp0, comp1, comp2, comp3, comp4, comp5, |
| 1103 | comp0, comp1, comp2, comp3, | 1105 | comp6, comp7, comp8, comp9, comp10, comp11}; |
| 1104 | comp4, comp5, comp6, comp7, | ||
| 1105 | comp8, comp9, comp10, comp11 | ||
| 1106 | }; | ||
| 1107 | return (int)components[n]; | 1106 | return (int)components[n]; |
| 1108 | } | 1107 | } |
| 1109 | } attribute_loaders[12]; | 1108 | } attribute_loaders[12]; |
| @@ -1157,8 +1156,8 @@ struct Regs { | |||
| 1157 | // kicked off. | 1156 | // kicked off. |
| 1158 | // 2) Games can configure these registers to provide a command list subroutine mechanism. | 1157 | // 2) Games can configure these registers to provide a command list subroutine mechanism. |
| 1159 | 1158 | ||
| 1160 | BitField< 0, 20, u32> size[2]; ///< Size (in bytes / 8) of each channel's command buffer | 1159 | BitField<0, 20, u32> size[2]; ///< Size (in bytes / 8) of each channel's command buffer |
| 1161 | BitField< 0, 28, u32> addr[2]; ///< Physical address / 8 of each channel's command buffer | 1160 | BitField<0, 28, u32> addr[2]; ///< Physical address / 8 of each channel's command buffer |
| 1162 | u32 trigger[2]; ///< Triggers execution of the channel's command buffer when written to | 1161 | u32 trigger[2]; ///< Triggers execution of the channel's command buffer when written to |
| 1163 | 1162 | ||
| 1164 | unsigned GetSize(unsigned index) const { | 1163 | unsigned GetSize(unsigned index) const { |
| @@ -1174,19 +1173,16 @@ struct Regs { | |||
| 1174 | 1173 | ||
| 1175 | INSERT_PADDING_WORDS(0x07); | 1174 | INSERT_PADDING_WORDS(0x07); |
| 1176 | 1175 | ||
| 1177 | enum class GPUMode : u32 { | 1176 | enum class GPUMode : u32 { Drawing = 0, Configuring = 1 }; |
| 1178 | Drawing = 0, | ||
| 1179 | Configuring = 1 | ||
| 1180 | }; | ||
| 1181 | 1177 | ||
| 1182 | GPUMode gpu_mode; | 1178 | GPUMode gpu_mode; |
| 1183 | 1179 | ||
| 1184 | INSERT_PADDING_WORDS(0x18); | 1180 | INSERT_PADDING_WORDS(0x18); |
| 1185 | 1181 | ||
| 1186 | enum class TriangleTopology : u32 { | 1182 | enum class TriangleTopology : u32 { |
| 1187 | List = 0, | 1183 | List = 0, |
| 1188 | Strip = 1, | 1184 | Strip = 1, |
| 1189 | Fan = 2, | 1185 | Fan = 2, |
| 1190 | Shader = 3, // Programmable setup unit implemented in a geometry shader | 1186 | Shader = 3, // Programmable setup unit implemented in a geometry shader |
| 1191 | }; | 1187 | }; |
| 1192 | 1188 | ||
| @@ -1200,8 +1196,8 @@ struct Regs { | |||
| 1200 | BitField<0, 16, u32> bool_uniforms; | 1196 | BitField<0, 16, u32> bool_uniforms; |
| 1201 | 1197 | ||
| 1202 | union { | 1198 | union { |
| 1203 | BitField< 0, 8, u32> x; | 1199 | BitField<0, 8, u32> x; |
| 1204 | BitField< 8, 8, u32> y; | 1200 | BitField<8, 8, u32> y; |
| 1205 | BitField<16, 8, u32> z; | 1201 | BitField<16, 8, u32> z; |
| 1206 | BitField<24, 8, u32> w; | 1202 | BitField<24, 8, u32> w; |
| 1207 | } int_uniforms[4]; | 1203 | } int_uniforms[4]; |
| @@ -1217,9 +1213,9 @@ struct Regs { | |||
| 1217 | BitField<0, 16, u32> main_offset; | 1213 | BitField<0, 16, u32> main_offset; |
| 1218 | 1214 | ||
| 1219 | union { | 1215 | union { |
| 1220 | BitField< 0, 4, u64> attribute0_register; | 1216 | BitField<0, 4, u64> attribute0_register; |
| 1221 | BitField< 4, 4, u64> attribute1_register; | 1217 | BitField<4, 4, u64> attribute1_register; |
| 1222 | BitField< 8, 4, u64> attribute2_register; | 1218 | BitField<8, 4, u64> attribute2_register; |
| 1223 | BitField<12, 4, u64> attribute3_register; | 1219 | BitField<12, 4, u64> attribute3_register; |
| 1224 | BitField<16, 4, u64> attribute4_register; | 1220 | BitField<16, 4, u64> attribute4_register; |
| 1225 | BitField<20, 4, u64> attribute5_register; | 1221 | BitField<20, 4, u64> attribute5_register; |
| @@ -1236,10 +1232,12 @@ struct Regs { | |||
| 1236 | 1232 | ||
| 1237 | int GetRegisterForAttribute(int attribute_index) const { | 1233 | int GetRegisterForAttribute(int attribute_index) const { |
| 1238 | u64 fields[] = { | 1234 | u64 fields[] = { |
| 1239 | attribute0_register, attribute1_register, attribute2_register, attribute3_register, | 1235 | attribute0_register, attribute1_register, attribute2_register, |
| 1240 | attribute4_register, attribute5_register, attribute6_register, attribute7_register, | 1236 | attribute3_register, attribute4_register, attribute5_register, |
| 1241 | attribute8_register, attribute9_register, attribute10_register, attribute11_register, | 1237 | attribute6_register, attribute7_register, attribute8_register, |
| 1242 | attribute12_register, attribute13_register, attribute14_register, attribute15_register, | 1238 | attribute9_register, attribute10_register, attribute11_register, |
| 1239 | attribute12_register, attribute13_register, attribute14_register, | ||
| 1240 | attribute15_register, | ||
| 1243 | }; | 1241 | }; |
| 1244 | return (int)fields[attribute_index]; | 1242 | return (int)fields[attribute_index]; |
| 1245 | } | 1243 | } |
| @@ -1251,11 +1249,7 @@ struct Regs { | |||
| 1251 | INSERT_PADDING_WORDS(0x2); | 1249 | INSERT_PADDING_WORDS(0x2); |
| 1252 | 1250 | ||
| 1253 | struct { | 1251 | struct { |
| 1254 | enum Format : u32 | 1252 | enum Format : u32 { FLOAT24 = 0, FLOAT32 = 1 }; |
| 1255 | { | ||
| 1256 | FLOAT24 = 0, | ||
| 1257 | FLOAT32 = 1 | ||
| 1258 | }; | ||
| 1259 | 1253 | ||
| 1260 | bool IsFloat32() const { | 1254 | bool IsFloat32() const { |
| 1261 | return format == FLOAT32; | 1255 | return format == FLOAT32; |
| @@ -1263,7 +1257,8 @@ struct Regs { | |||
| 1263 | 1257 | ||
| 1264 | union { | 1258 | union { |
| 1265 | // Index of the next uniform to write to | 1259 | // Index of the next uniform to write to |
| 1266 | // TODO: ctrulib uses 8 bits for this, however that seems to yield lots of invalid indices | 1260 | // TODO: ctrulib uses 8 bits for this, however that seems to yield lots of invalid |
| 1261 | // indices | ||
| 1267 | // TODO: Maybe the uppermost index is for the geometry shader? Investigate! | 1262 | // TODO: Maybe the uppermost index is for the geometry shader? Investigate! |
| 1268 | BitField<0, 7, u32> index; | 1263 | BitField<0, 7, u32> index; |
| 1269 | 1264 | ||
| @@ -1315,12 +1310,12 @@ struct Regs { | |||
| 1315 | return sizeof(Regs) / sizeof(u32); | 1310 | return sizeof(Regs) / sizeof(u32); |
| 1316 | } | 1311 | } |
| 1317 | 1312 | ||
| 1318 | const u32& operator [] (int index) const { | 1313 | const u32& operator[](int index) const { |
| 1319 | const u32* content = reinterpret_cast<const u32*>(this); | 1314 | const u32* content = reinterpret_cast<const u32*>(this); |
| 1320 | return content[index]; | 1315 | return content[index]; |
| 1321 | } | 1316 | } |
| 1322 | 1317 | ||
| 1323 | u32& operator [] (int index) { | 1318 | u32& operator[](int index) { |
| 1324 | u32* content = reinterpret_cast<u32*>(this); | 1319 | u32* content = reinterpret_cast<u32*>(this); |
| 1325 | return content[index]; | 1320 | return content[index]; |
| 1326 | } | 1321 | } |
| @@ -1339,7 +1334,9 @@ private: | |||
| 1339 | // is technically allowed since C++11. This macro should be enabled once MSVC adds | 1334 | // is technically allowed since C++11. This macro should be enabled once MSVC adds |
| 1340 | // support for that. | 1335 | // support for that. |
| 1341 | #ifndef _MSC_VER | 1336 | #ifndef _MSC_VER |
| 1342 | #define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(Regs, field_name) == position * 4, "Field "#field_name" has invalid position") | 1337 | #define ASSERT_REG_POSITION(field_name, position) \ |
| 1338 | static_assert(offsetof(Regs, field_name) == position * 4, \ | ||
| 1339 | "Field " #field_name " has invalid position") | ||
| 1343 | 1340 | ||
| 1344 | ASSERT_REG_POSITION(trigger_irq, 0x10); | 1341 | ASSERT_REG_POSITION(trigger_irq, 0x10); |
| 1345 | ASSERT_REG_POSITION(cull_mode, 0x40); | 1342 | ASSERT_REG_POSITION(cull_mode, 0x40); |
| @@ -1392,11 +1389,15 @@ ASSERT_REG_POSITION(vs, 0x2b0); | |||
| 1392 | #undef ASSERT_REG_POSITION | 1389 | #undef ASSERT_REG_POSITION |
| 1393 | #endif // !defined(_MSC_VER) | 1390 | #endif // !defined(_MSC_VER) |
| 1394 | 1391 | ||
| 1395 | static_assert(sizeof(Regs::ShaderConfig) == 0x30 * sizeof(u32), "ShaderConfig structure has incorrect size"); | 1392 | static_assert(sizeof(Regs::ShaderConfig) == 0x30 * sizeof(u32), |
| 1393 | "ShaderConfig structure has incorrect size"); | ||
| 1396 | 1394 | ||
| 1397 | // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway. | 1395 | // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value |
| 1398 | static_assert(sizeof(Regs) <= 0x300 * sizeof(u32), "Register set structure larger than it should be"); | 1396 | // anyway. |
| 1399 | static_assert(sizeof(Regs) >= 0x300 * sizeof(u32), "Register set structure smaller than it should be"); | 1397 | static_assert(sizeof(Regs) <= 0x300 * sizeof(u32), |
| 1398 | "Register set structure larger than it should be"); | ||
| 1399 | static_assert(sizeof(Regs) >= 0x300 * sizeof(u32), | ||
| 1400 | "Register set structure smaller than it should be"); | ||
| 1400 | 1401 | ||
| 1401 | /// Initialize Pica state | 1402 | /// Initialize Pica state |
| 1402 | void Init(); | 1403 | void Init(); |