1 #pragma once 2 3 #include <thread> 4 #include <vector> 5 #include <functional> 6 #include <atomic> 7 #include <array> 8 #include "signal/Signal.h" 9 10 #include "bitmap/Bitmap.h" 11 #include "Types.h" 12 #include "Convertible.h" 13 #include "../MailBox.h" 14 #include "../Integer64.h" 15 #include "zip/ZipArchiveWriter.h" 16 #include "zip/ZipArchiveReader.h" 17 18 class CFrameDump; 19 class CGsPacketMetadata; 20 class CINTC; 21 22 #define PREF_CGSHANDLER_PRESENTATION_MODE "renderer.presentationmode" 23 #define PREF_CGSHANDLER_WIDESCREEN "renderer.widescreen" 24 25 enum GS_REGS 26 { 27 GS_REG_PRIM = 0x00, 28 GS_REG_RGBAQ = 0x01, 29 GS_REG_ST = 0x02, 30 GS_REG_UV = 0x03, 31 GS_REG_XYZF2 = 0x04, 32 GS_REG_XYZ2 = 0x05, 33 GS_REG_TEX0_1 = 0x06, 34 GS_REG_TEX0_2 = 0x07, 35 GS_REG_CLAMP_1 = 0x08, 36 GS_REG_CLAMP_2 = 0x09, 37 GS_REG_FOG = 0x0A, 38 GS_REG_XYZF3 = 0x0C, 39 GS_REG_XYZ3 = 0x0D, 40 GS_REG_TEX1_1 = 0x14, 41 GS_REG_TEX1_2 = 0x15, 42 GS_REG_TEX2_1 = 0x16, 43 GS_REG_TEX2_2 = 0x17, 44 GS_REG_XYOFFSET_1 = 0x18, 45 GS_REG_XYOFFSET_2 = 0x19, 46 GS_REG_PRMODECONT = 0x1A, 47 GS_REG_PRMODE = 0x1B, 48 GS_REG_TEXCLUT = 0x1C, 49 GS_REG_MIPTBP1_1 = 0x34, 50 GS_REG_MIPTBP1_2 = 0x35, 51 GS_REG_MIPTBP2_1 = 0x36, 52 GS_REG_MIPTBP2_2 = 0x37, 53 GS_REG_TEXA = 0x3B, 54 GS_REG_FOGCOL = 0x3D, 55 GS_REG_TEXFLUSH = 0x3F, 56 GS_REG_SCISSOR_1 = 0x40, 57 GS_REG_SCISSOR_2 = 0x41, 58 GS_REG_ALPHA_1 = 0x42, 59 GS_REG_ALPHA_2 = 0x43, 60 GS_REG_COLCLAMP = 0x46, 61 GS_REG_TEST_1 = 0x47, 62 GS_REG_TEST_2 = 0x48, 63 GS_REG_PABE = 0x49, 64 GS_REG_FBA_1 = 0x4A, 65 GS_REG_FBA_2 = 0x4B, 66 GS_REG_FRAME_1 = 0x4C, 67 GS_REG_FRAME_2 = 0x4D, 68 GS_REG_ZBUF_1 = 0x4E, 69 GS_REG_ZBUF_2 = 0x4F, 70 GS_REG_BITBLTBUF = 0x50, 71 GS_REG_TRXPOS = 0x51, 72 GS_REG_TRXREG = 0x52, 73 GS_REG_TRXDIR = 0x53, 74 GS_REG_HWREG = 0x54, 75 GS_REG_SIGNAL = 0x60, 76 GS_REG_FINISH = 0x61, 77 GS_REG_LABEL = 0x62, 78 }; 79 80 class CGSHandler 81 { 82 public: 83 enum RAMSIZE 84 { 85 RAMSIZE = 0x00400000, 86 }; 87 88 enum PRESENTATION_MODE 89 { 90 PRESENTATION_MODE_FILL, 91 PRESENTATION_MODE_FIT, 92 PRESENTATION_MODE_ORIGINAL 93 }; 94 95 enum PRIVATE_REGISTER 96 { 97 GS_PMODE = 0x12000000, 98 GS_SMODE2 = 0x12000020, 99 GS_DISPFB1 = 0x12000070, 100 GS_DISPLAY1 = 0x12000080, 101 GS_DISPFB2 = 0x12000090, 102 GS_DISPLAY2 = 0x120000A0, 103 GS_CSR_ALT = 0x12000400, // Used by funslower demo 104 GS_CSR = 0x12001000, 105 GS_IMR = 0x12001010, 106 GS_BUSDIR = 0x12001040, 107 GS_SIGLBLID = 0x12001080, 108 }; 109 110 enum 111 { 112 CSR_SIGNAL_EVENT = 0x0001, 113 CSR_FINISH_EVENT = 0x0002, 114 CSR_HSYNC_INT = 0x0004, 115 CSR_VSYNC_INT = 0x0008, 116 CSR_RESET = 0x0200, 117 CSR_FIELD = 0x2000, 118 CSR_FIFO_STATUS = 0xC000, 119 CSR_FIFO_NEITHER = 0x0000, 120 CSR_FIFO_EMPTY = 0x4000, 121 CSR_FIFO_FULL = 0x8000 122 }; 123 124 struct PRESENTATION_PARAMS 125 { 126 uint32 windowWidth; 127 uint32 windowHeight; 128 PRESENTATION_MODE mode; 129 }; 130 131 struct PRESENTATION_VIEWPORT 132 { 133 int32 offsetX = 0; 134 int32 offsetY = 0; 135 int32 width = 0; 136 int32 height = 0; 137 }; 138 139 enum PSM 140 { 141 PSMCT32 = 0x00, 142 PSMCT24 = 0x01, 143 PSMCT16 = 0x02, 144 PSMCT24_UNK = 0x09, //Used by FFX (in menus) 145 PSMCT16S = 0x0A, 146 PSMT8 = 0x13, 147 PSMT4 = 0x14, 148 PSMT8H = 0x1B, 149 PSMCT32_UNK = 0x20, //Used by movies in LotR: RotK 150 PSMT4HL = 0x24, 151 PSMT4HH = 0x2C, 152 PSMZ32 = 0x30, 153 PSMZ24 = 0x31, 154 PSMZ16 = 0x32, 155 PSMZ16S = 0x3A, 156 PSM_MAX = 0x40, 157 }; 158 159 enum PRIM_TYPE 160 { 161 PRIM_POINT, 162 PRIM_LINE, 163 PRIM_LINESTRIP, 164 PRIM_TRIANGLE, 165 PRIM_TRIANGLESTRIP, 166 PRIM_TRIANGLEFAN, 167 PRIM_SPRITE, 168 PRIM_INVALID, 169 }; 170 171 enum ALPHABLEND_ABD 172 { 173 ALPHABLEND_ABD_CS, 174 ALPHABLEND_ABD_CD, 175 ALPHABLEND_ABD_ZERO, 176 ALPHABLEND_ABD_INVALID 177 }; 178 179 enum ALPHABLEND_C 180 { 181 ALPHABLEND_C_AS, 182 ALPHABLEND_C_AD, 183 ALPHABLEND_C_FIX, 184 ALPHABLEND_C_INVALID 185 }; 186 187 enum DEPTH_TEST_METHOD 188 { 189 DEPTH_TEST_NEVER, 190 DEPTH_TEST_ALWAYS, 191 DEPTH_TEST_GEQUAL, 192 DEPTH_TEST_GREATER 193 }; 194 195 enum ALPHA_TEST_METHOD 196 { 197 ALPHA_TEST_NEVER, 198 ALPHA_TEST_ALWAYS, 199 ALPHA_TEST_LESS, 200 ALPHA_TEST_LEQUAL, 201 ALPHA_TEST_EQUAL, 202 ALPHA_TEST_GEQUAL, 203 ALPHA_TEST_GREATER, 204 ALPHA_TEST_NOTEQUAL, 205 ALPHA_TEST_MAX 206 }; 207 208 enum ALPHA_TEST_FAIL_METHOD 209 { 210 ALPHA_TEST_FAIL_KEEP, 211 ALPHA_TEST_FAIL_FBONLY, 212 ALPHA_TEST_FAIL_ZBONLY, 213 ALPHA_TEST_FAIL_RGBONLY 214 }; 215 216 enum TEX0_FUNCTION 217 { 218 TEX0_FUNCTION_MODULATE, 219 TEX0_FUNCTION_DECAL, 220 TEX0_FUNCTION_HIGHLIGHT, 221 TEX0_FUNCTION_HIGHLIGHT2, 222 TEX0_FUNCTION_MAX 223 }; 224 225 enum CLAMP_MODE 226 { 227 CLAMP_MODE_REPEAT, 228 CLAMP_MODE_CLAMP, 229 CLAMP_MODE_REGION_CLAMP, 230 CLAMP_MODE_REGION_REPEAT, 231 CLAMP_MODE_MAX 232 }; 233 234 enum REGISTER_MAX 235 { 236 REGISTER_MAX = 0x80 237 }; 238 239 //Reg 0x00 240 struct PRIM : public convertible<uint64> 241 { 242 unsigned int nType : 3; 243 unsigned int nShading : 1; 244 unsigned int nTexture : 1; 245 unsigned int nFog : 1; 246 unsigned int nAlpha : 1; 247 unsigned int nAntiAliasing : 1; 248 unsigned int nUseUV : 1; 249 unsigned int nContext : 1; 250 unsigned int nUseFloat : 1; 251 unsigned int nReserved0 : 21; 252 uint32 nReserved1; 253 }; 254 static_assert(sizeof(PRIM) == sizeof(uint64), "Size of PRIM struct must be 8 bytes."); 255 256 //Reg 0x01 257 struct RGBAQ : public convertible<uint64> 258 { 259 uint8 nR; 260 uint8 nG; 261 uint8 nB; 262 uint8 nA; 263 float nQ; 264 }; 265 static_assert(sizeof(RGBAQ) == sizeof(uint64), "Size of RGBAQ struct must be 8 bytes."); 266 267 //Reg 0x02 268 struct ST : public convertible<uint64> 269 { 270 float nS; 271 float nT; 272 }; 273 static_assert(sizeof(ST) == sizeof(uint64), "Size of ST struct must be 8 bytes."); 274 275 //Reg 0x03 276 struct UV : public convertible<uint64> 277 { 278 uint16 nU; 279 uint16 nV; 280 uint32 nReserved; 281 GetUUV282 float GetU() const 283 { 284 return static_cast<float>(nU & 0x3FFF) / 16.0f; 285 } GetVUV286 float GetV() const 287 { 288 return static_cast<float>(nV & 0x3FFF) / 16.0f; 289 } 290 }; 291 static_assert(sizeof(UV) == sizeof(uint64), "Size of UV struct must be 8 bytes."); 292 293 //Reg 0x04/0x0C 294 struct XYZF : public convertible<uint64> 295 { 296 unsigned int nX : 16; 297 unsigned int nY : 16; 298 unsigned int nZ : 24; 299 unsigned int nF : 8; 300 GetXXYZF301 float GetX() 302 { 303 return static_cast<float>(nX) / 16.0f; 304 } GetYXYZF305 float GetY() 306 { 307 return static_cast<float>(nY) / 16.0f; 308 } 309 }; 310 static_assert(sizeof(XYZF) == sizeof(uint64), "Size of XYZF struct must be 8 bytes."); 311 312 //Reg 0x05/0x0D 313 struct XYZ : public convertible<uint64> 314 { 315 unsigned int nX : 16; 316 unsigned int nY : 16; 317 uint32 nZ; 318 GetXXYZ319 float GetX() 320 { 321 return static_cast<float>(nX) / 16.0f; 322 } GetYXYZ323 float GetY() 324 { 325 return static_cast<float>(nY) / 16.0f; 326 } GetZXYZ327 float GetZ() 328 { 329 return static_cast<float>(nZ); 330 } 331 }; 332 static_assert(sizeof(XYZ) == sizeof(uint64), "Size of XYZ struct must be 8 bytes."); 333 334 //Reg 0x06/0x07 335 struct TEX0 : public convertible<uint64> 336 { 337 unsigned int nBufPtr : 14; 338 unsigned int nBufWidth : 6; 339 unsigned int nPsm : 6; 340 unsigned int nWidth : 4; 341 unsigned int nPad0 : 2; 342 unsigned int nPad1 : 2; 343 unsigned int nColorComp : 1; 344 unsigned int nFunction : 2; 345 unsigned int nCBP : 14; 346 unsigned int nCPSM : 4; 347 unsigned int nCSM : 1; 348 unsigned int nCSA : 5; 349 unsigned int nCLD : 3; GetBufPtrTEX0350 uint32 GetBufPtr() const 351 { 352 return nBufPtr * 256; 353 } GetBufWidthTEX0354 uint32 GetBufWidth() const 355 { 356 return nBufWidth * 64; 357 } GetWidthTEX0358 uint32 GetWidth() const 359 { 360 return (1 << nWidth); 361 } GetHeightTEX0362 uint32 GetHeight() const 363 { 364 return (1 << (nPad0 | (nPad1 << 2))); 365 } GetCLUTPtrTEX0366 uint32 GetCLUTPtr() const 367 { 368 return nCBP * 256; 369 } 370 }; 371 static_assert(sizeof(TEX0) == sizeof(uint64), "Size of TEX0 struct must be 8 bytes."); 372 373 //Reg 0x08/0x09 374 struct CLAMP : public convertible<uint64> 375 { 376 unsigned int nWMS : 2; 377 unsigned int nWMT : 2; 378 unsigned int nMINU : 10; 379 unsigned int nMAXU : 10; 380 unsigned int nReserved0 : 8; 381 unsigned int nReserved1 : 2; 382 unsigned int nMAXV : 10; 383 unsigned int nReserved2 : 20; GetMinUCLAMP384 unsigned int GetMinU() 385 { 386 return nMINU; 387 } GetMaxUCLAMP388 unsigned int GetMaxU() 389 { 390 return nMAXU; 391 } GetMinVCLAMP392 unsigned int GetMinV() 393 { 394 return (nReserved0) | (nReserved1 << 8); 395 } GetMaxVCLAMP396 unsigned int GetMaxV() 397 { 398 return nMAXV; 399 } 400 }; 401 static_assert(sizeof(CLAMP) == sizeof(uint64), "Size of CLAMP struct must be 8 bytes."); 402 403 //Reg 0x14/0x15 404 struct TEX1 : public convertible<uint64> 405 { 406 unsigned int nLODMethod : 1; 407 unsigned int nReserved0 : 1; 408 unsigned int nMaxMip : 3; 409 unsigned int nMagFilter : 1; 410 unsigned int nMinFilter : 3; 411 unsigned int nMipBaseAddr : 1; 412 unsigned int nReserved1 : 9; 413 unsigned int nLODL : 2; 414 unsigned int nReserved2 : 11; 415 unsigned int nLODK : 12; 416 unsigned int nReserved3 : 20; 417 GetKTEX1418 float GetK() const 419 { 420 int16 temp = nLODK | ((nLODK & 0x800) ? 0xF000 : 0x0000); 421 return static_cast<float>(temp) / 16.0f; 422 } 423 }; 424 static_assert(sizeof(TEX1) == sizeof(uint64), "Size of TEX1 struct must be 8 bytes."); 425 426 //Reg 0x16/0x17 427 struct TEX2 : public convertible<uint64> 428 { 429 unsigned int nReserved0 : 20; 430 unsigned int nPsm : 6; 431 unsigned int nReserved1 : 6; 432 unsigned int nReserved2 : 5; 433 unsigned int nCBP : 14; 434 unsigned int nCPSM : 4; 435 unsigned int nCSM : 1; 436 unsigned int nCSA : 5; 437 unsigned int nCLD : 3; GetCLUTPtrTEX2438 uint32 GetCLUTPtr() 439 { 440 return nCBP * 256; 441 } 442 }; 443 static_assert(sizeof(TEX2) == sizeof(uint64), "Size of TEX2 struct must be 8 bytes."); 444 445 //Reg 0x18/0x19 446 struct XYOFFSET : public convertible<uint64> 447 { 448 uint16 nOffsetX; 449 uint16 nReserved0; 450 uint16 nOffsetY; 451 uint16 nReserved1; GetXXYOFFSET452 float GetX() 453 { 454 return static_cast<float>(nOffsetX) / 16.0f; 455 } GetYXYOFFSET456 float GetY() 457 { 458 return static_cast<float>(nOffsetY) / 16.0f; 459 } 460 }; 461 static_assert(sizeof(XYOFFSET) == sizeof(uint64), "Size of XYOFFSET struct must be 8 bytes."); 462 463 //Reg 0x1B 464 struct PRMODE : public convertible<uint64> 465 { 466 unsigned int nReserved0 : 3; 467 unsigned int nShading : 1; 468 unsigned int nTexture : 1; 469 unsigned int nFog : 1; 470 unsigned int nAlpha : 1; 471 unsigned int nAntiAliasing : 1; 472 unsigned int nUseUV : 1; 473 unsigned int nContext : 1; 474 unsigned int nUseFloat : 1; 475 unsigned int nReserved1 : 21; 476 uint32 nReserved2; 477 }; 478 static_assert(sizeof(PRMODE) == sizeof(uint64), "Size of PRMODE struct must be 8 bytes."); 479 480 //Reg 0x34/0x35 481 struct MIPTBP1 : public convertible<uint64> 482 { 483 unsigned int tbp1 : 14; 484 unsigned int tbw1 : 6; 485 unsigned int pad0 : 12; 486 unsigned int pad1 : 2; 487 unsigned int tbw2 : 6; 488 unsigned int tbp3 : 14; 489 unsigned int tbw3 : 6; 490 unsigned int reserved : 4; GetTbp1MIPTBP1491 uint32 GetTbp1() const 492 { 493 return tbp1 * 256; 494 } GetTbp2MIPTBP1495 uint32 GetTbp2() const 496 { 497 return (pad0 | (pad1 << 12)) * 256; 498 } GetTbp3MIPTBP1499 uint32 GetTbp3() const 500 { 501 return tbp3 * 256; 502 } GetTbw1MIPTBP1503 uint32 GetTbw1() const 504 { 505 return tbw1 * 64; 506 } GetTbw2MIPTBP1507 uint32 GetTbw2() const 508 { 509 return tbw2 * 64; 510 } GetTbw3MIPTBP1511 uint32 GetTbw3() const 512 { 513 return tbw3 * 64; 514 } 515 }; 516 static_assert(sizeof(MIPTBP1) == sizeof(uint64), "Size of MIPTBP1 struct must be 8 bytes."); 517 518 //Reg 0x36/0x37 519 struct MIPTBP2 : public convertible<uint64> 520 { 521 unsigned int tbp4 : 14; 522 unsigned int tbw4 : 6; 523 unsigned int pad0 : 12; 524 unsigned int pad1 : 2; 525 unsigned int tbw5 : 6; 526 unsigned int tbp6 : 14; 527 unsigned int tbw6 : 6; 528 unsigned int reserved : 4; GetTbp4MIPTBP2529 uint32 GetTbp4() const 530 { 531 return tbp4 * 256; 532 } GetTbp5MIPTBP2533 uint32 GetTbp5() const 534 { 535 return (pad0 | (pad1 << 12)) * 256; 536 } GetTbp6MIPTBP2537 uint32 GetTbp6() const 538 { 539 return tbp6 * 256; 540 } GetTbw4MIPTBP2541 uint32 GetTbw4() const 542 { 543 return tbw4 * 64; 544 } GetTbw5MIPTBP2545 uint32 GetTbw5() const 546 { 547 return tbw5 * 64; 548 } GetTbw6MIPTBP2549 uint32 GetTbw6() const 550 { 551 return tbw6 * 64; 552 } 553 }; 554 static_assert(sizeof(MIPTBP2) == sizeof(uint64), "Size of MIPTBP2 struct must be 8 bytes."); 555 556 //Reg 0x3B 557 struct TEXA : public convertible<uint64> 558 { 559 unsigned int nTA0 : 8; 560 unsigned int nReserved0 : 7; 561 unsigned int nAEM : 1; 562 unsigned int nReserved1 : 16; 563 unsigned int nTA1 : 8; 564 unsigned int nReserved2 : 24; 565 }; 566 static_assert(sizeof(TEXA) == sizeof(uint64), "Size of TEXA struct must be 8 bytes."); 567 568 //Reg 0x3D 569 struct FOGCOL : public convertible<uint64> 570 { 571 unsigned int nFCR : 8; 572 unsigned int nFCG : 8; 573 unsigned int nFCB : 8; 574 unsigned int nReserved0 : 8; 575 unsigned int nReserved1 : 32; 576 }; 577 static_assert(sizeof(FOGCOL) == sizeof(uint64), "Size of FOGCOL struct must be 8 bytes."); 578 579 //Reg 0x3F 580 struct TEXCLUT : public convertible<uint64> 581 { 582 unsigned int nCBW : 6; 583 unsigned int nCOU : 6; 584 unsigned int nCOV : 10; 585 unsigned int nReserved1 : 10; 586 unsigned int nReserved2 : 32; GetBufWidthTEXCLUT587 uint32 GetBufWidth() const 588 { 589 return nCBW * 64; 590 } GetOffsetUTEXCLUT591 uint32 GetOffsetU() const 592 { 593 return nCOU * 16; 594 } GetOffsetVTEXCLUT595 uint32 GetOffsetV() const 596 { 597 return nCOV; 598 } 599 }; 600 static_assert(sizeof(TEXCLUT) == sizeof(uint64), "Size of TEXCLUT struct must be 8 bytes."); 601 602 //Reg 0x40/0x41 603 struct SCISSOR : public convertible<uint64> 604 { 605 unsigned int scax0 : 11; 606 unsigned int reserved0 : 5; 607 unsigned int scax1 : 11; 608 unsigned int reserved1 : 5; 609 unsigned int scay0 : 11; 610 unsigned int reserved2 : 5; 611 unsigned int scay1 : 11; 612 unsigned int reserved3 : 5; 613 }; 614 static_assert(sizeof(SCISSOR) == sizeof(uint64), "Size of SCISSOR struct must be 8 bytes."); 615 616 //Reg 0x42/0x43 617 struct ALPHA : public convertible<uint64> 618 { 619 unsigned int nA : 2; 620 unsigned int nB : 2; 621 unsigned int nC : 2; 622 unsigned int nD : 2; 623 unsigned int nReserved0 : 24; 624 unsigned int nFix : 8; 625 unsigned int nReserved1 : 24; 626 }; 627 static_assert(sizeof(ALPHA) == sizeof(uint64), "Size of ALPHA struct must be 8 bytes."); 628 629 //Reg 0x47/0x48 630 struct TEST : public convertible<uint64> 631 { 632 unsigned int nAlphaEnabled : 1; 633 unsigned int nAlphaMethod : 3; 634 unsigned int nAlphaRef : 8; 635 unsigned int nAlphaFail : 2; 636 unsigned int nDestAlphaEnabled : 1; 637 unsigned int nDestAlphaMode : 1; 638 unsigned int nDepthEnabled : 1; 639 unsigned int nDepthMethod : 2; 640 unsigned int nReserved0 : 13; 641 uint32 nReserved1; 642 }; 643 static_assert(sizeof(TEST) == sizeof(uint64), "Size of TEST struct must be 8 bytes."); 644 645 //Reg 0x4C/0x4D 646 struct FRAME : public convertible<uint64> 647 { 648 unsigned int nPtr : 9; 649 unsigned int nReserved0 : 7; 650 unsigned int nWidth : 6; 651 unsigned int nReserved1 : 2; 652 unsigned int nPsm : 6; 653 unsigned int nReserved2 : 2; 654 unsigned int nMask : 32; GetBasePtrFRAME655 uint32 GetBasePtr() const 656 { 657 return nPtr * 8192; 658 } GetWidthFRAME659 uint32 GetWidth() const 660 { 661 return nWidth * 64; 662 } 663 }; 664 static_assert(sizeof(FRAME) == sizeof(uint64), "Size of FRAME struct must be 8 bytes."); 665 666 //Reg 0x4E/0x4F 667 struct ZBUF : public convertible<uint64> 668 { 669 unsigned int nPtr : 9; 670 unsigned int nReserved0 : 15; 671 unsigned int nPsm : 4; 672 unsigned int nReserved1 : 4; 673 unsigned int nMask : 1; 674 unsigned int nReserved2 : 31; GetBasePtrZBUF675 uint32 GetBasePtr() const 676 { 677 return nPtr * 8192; 678 } 679 }; 680 static_assert(sizeof(ZBUF) == sizeof(uint64), "Size of ZBUF struct must be 8 bytes."); 681 682 //Reg 0x50 683 struct BITBLTBUF : public convertible<uint64> 684 { 685 unsigned int nSrcPtr : 14; 686 unsigned int nReserved0 : 2; 687 unsigned int nSrcWidth : 6; 688 unsigned int nReserved1 : 2; 689 unsigned int nSrcPsm : 6; 690 unsigned int nReserved2 : 2; 691 unsigned int nDstPtr : 14; 692 unsigned int nReserved3 : 2; 693 unsigned int nDstWidth : 6; 694 unsigned int nReserved4 : 2; 695 unsigned int nDstPsm : 6; 696 unsigned int nReserved5 : 2; GetSrcPtrBITBLTBUF697 uint32 GetSrcPtr() const 698 { 699 return nSrcPtr * 256; 700 } GetSrcWidthBITBLTBUF701 uint32 GetSrcWidth() const 702 { 703 return nSrcWidth * 64; 704 } GetDstPtrBITBLTBUF705 uint32 GetDstPtr() const 706 { 707 return nDstPtr * 256; 708 } GetDstWidthBITBLTBUF709 uint32 GetDstWidth() const 710 { 711 return nDstWidth * 64; 712 } 713 }; 714 static_assert(sizeof(BITBLTBUF) == sizeof(uint64), "Size of BITBLTBUF struct must be 8 bytes."); 715 716 //Reg 0x51 717 struct TRXPOS : public convertible<uint64> 718 { 719 unsigned int nSSAX : 11; 720 unsigned int nReserved0 : 5; 721 unsigned int nSSAY : 11; 722 unsigned int nReserved1 : 5; 723 unsigned int nDSAX : 11; 724 unsigned int nReserved2 : 5; 725 unsigned int nDSAY : 11; 726 unsigned int nDIR : 2; 727 unsigned int nReserved3 : 3; 728 }; 729 static_assert(sizeof(TRXPOS) == sizeof(uint64), "Size of TRXPOS struct must be 8 bytes."); 730 731 //Reg 0x52 732 struct TRXREG : public convertible<uint64> 733 { 734 unsigned int nRRW : 12; 735 unsigned int nReserved0 : 20; 736 unsigned int nRRH : 12; 737 unsigned int nReserved1 : 20; 738 }; 739 static_assert(sizeof(TRXREG) == sizeof(uint64), "Size of TRXREG struct must be 8 bytes."); 740 741 //Reg 0x60 742 struct SIGNAL : public convertible<uint64> 743 { 744 unsigned int id : 32; 745 unsigned int idmsk : 32; 746 }; 747 static_assert(sizeof(SIGNAL) == sizeof(uint64), "Size of SIGNAL struct must be 8 bytes."); 748 749 //Reg 0x62 750 struct LABEL : public convertible<uint64> 751 { 752 unsigned int id : 32; 753 unsigned int idmsk : 32; 754 }; 755 static_assert(sizeof(LABEL) == sizeof(uint64), "Size of LABEL struct must be 8 bytes."); 756 757 typedef std::pair<uint8, uint64> RegisterWrite; 758 typedef std::vector<RegisterWrite> RegisterWriteList; 759 typedef std::function<CGSHandler*(void)> FactoryFunction; 760 761 typedef Framework::CSignal<void()> FlipCompleteEvent; 762 typedef Framework::CSignal<void(uint32)> NewFrameEvent; 763 764 CGSHandler(bool = true); 765 virtual ~CGSHandler(); 766 767 static void RegisterPreferences(); 768 void NotifyPreferencesChanged(); 769 770 void SetIntc(CINTC*); 771 void Reset(); 772 virtual void SetPresentationParams(const PRESENTATION_PARAMS&); 773 774 virtual void SaveState(Framework::CZipArchiveWriter&); 775 virtual void LoadState(Framework::CZipArchiveReader&); 776 void Copy(const CGSHandler*); 777 778 void SetFrameDump(CFrameDump*); 779 780 bool GetDrawEnabled() const; 781 void SetDrawEnabled(bool); 782 783 void WritePrivRegister(uint32, uint32); 784 uint32 ReadPrivRegister(uint32); 785 786 void SetLoggingEnabled(bool); 787 static std::string DisassembleWrite(uint8, uint64); 788 789 void SetVBlank(); 790 void ResetVBlank(); 791 792 void FeedImageData(const void*, uint32); 793 void ReadImageData(void*, uint32); 794 WriteRegister(const RegisterWrite & write)795 inline void WriteRegister(const RegisterWrite& write) 796 { 797 assert(m_writeBufferSize < REGISTERWRITEBUFFER_SIZE); 798 if(m_writeBufferSize == REGISTERWRITEBUFFER_SIZE) return; 799 m_writeBuffer[m_writeBufferSize++] = write; 800 } 801 802 void ProcessWriteBuffer(const CGsPacketMetadata*); 803 void SubmitWriteBuffer(); 804 void FlushWriteBuffer(); 805 806 virtual void SetCrt(bool, unsigned int, bool); 807 void Initialize(); 808 void Release(); 809 virtual void ProcessHostToLocalTransfer() = 0; 810 virtual void ProcessLocalToHostTransfer() = 0; 811 virtual void ProcessLocalToLocalTransfer() = 0; 812 virtual void ProcessClutTransfer(uint32, uint32) = 0; 813 void Flip(bool = false); 814 void Finish(); 815 virtual void ReadFramebuffer(uint32, uint32, void*) = 0; 816 817 void MakeLinearCLUT(const TEX0&, std::array<uint32, 256>&) const; 818 819 virtual uint8* GetRam() const; 820 uint64* GetRegisters(); 821 822 uint64 GetSMODE2() const; 823 void SetSMODE2(uint64); 824 825 uint64 GetBUSDIR() const; 826 827 int GetPendingTransferCount() const; 828 void NotifyEvent(uint32); 829 830 unsigned int GetCrtWidth() const; 831 unsigned int GetCrtHeight() const; 832 uint32 GetCrtFrameRate() const; 833 uint32 GetCrtHSyncFrequency() const; 834 bool GetCrtIsInterlaced() const; 835 bool GetCrtIsFrameMode() const; 836 std::pair<uint64, uint64> GetCurrentDisplayInfo(); 837 unsigned int GetCurrentReadCircuit(); 838 839 static std::pair<uint32, uint32> GetTransferInvalidationRange(const BITBLTBUF&, const TRXREG&, const TRXPOS&); 840 841 virtual Framework::CBitmap GetScreenshot(); 842 843 void SendGSCall(CMailBox::FunctionType&&); 844 void SendGSCall(const CMailBox::FunctionType&, bool = false, bool = false); 845 846 void ProcessSingleFrame(); 847 848 FlipCompleteEvent OnFlipComplete; 849 NewFrameEvent OnNewFrame; 850 851 protected: 852 struct DELAYED_REGISTER 853 { 854 uint32 heldValue; 855 INTEGER64 value; 856 }; 857 858 enum CLUTSIZE 859 { 860 CLUTSIZE = 0x400, 861 CLUTENTRYCOUNT = (CLUTSIZE / 2) 862 }; 863 864 enum 865 { 866 REGISTERWRITEBUFFER_SIZE = 0x100000, 867 REGISTERWRITEBUFFER_SUBMIT_THRESHOLD = 0x100 868 }; 869 870 enum MAG_FILTER 871 { 872 MAG_FILTER_NEAREST = 0, 873 MAG_FILTER_LINEAR = 1 874 }; 875 876 enum MIN_FILTER 877 { 878 MIN_FILTER_NEAREST = 0, 879 MIN_FILTER_LINEAR = 1, 880 MIN_FILTER_NEAREST_MIP_NEAREST = 2, 881 MIN_FILTER_NEAREST_MIP_LINEAR = 3, 882 MIN_FILTER_LINEAR_MIP_NEAREST = 4, 883 MIN_FILTER_LINEAR_MIP_LINEAR = 5 884 }; 885 886 //----------------------------------- 887 //Private Registers 888 enum CRT_MODE : uint32 889 { 890 CRT_MODE_NTSC = 0x02, 891 CRT_MODE_PAL = 0x03, 892 CRT_MODE_VGA_640_75 = 0x1C, 893 }; 894 895 struct SMODE2 : public convertible<uint64> 896 { 897 unsigned int interlaced : 1; 898 unsigned int ffmd : 1; 899 unsigned int dpms : 2; 900 unsigned int reserved0 : 28; 901 unsigned int reserved1; 902 }; 903 static_assert(sizeof(SMODE2) == sizeof(uint64), "Size of SMODE2 struct must be 8 bytes."); 904 905 struct DISPFB : public convertible<uint64> 906 { 907 unsigned int nBufPtr : 9; 908 unsigned int nBufWidth : 6; 909 unsigned int nPSM : 5; 910 unsigned int nReserved0 : 12; 911 unsigned int nX : 11; 912 unsigned int nY : 11; 913 unsigned int nReserved1 : 10; GetBufPtrDISPFB914 uint32 GetBufPtr() const 915 { 916 return nBufPtr * 8192; 917 }; GetBufWidthDISPFB918 uint32 GetBufWidth() const 919 { 920 return nBufWidth * 64; 921 }; 922 }; 923 static_assert(sizeof(DISPFB) == sizeof(uint64), "Size of DISPFB struct must be 8 bytes."); 924 925 struct DISPLAY : public convertible<uint64> 926 { 927 unsigned int nX : 12; 928 unsigned int nY : 11; 929 unsigned int nMagX : 4; 930 unsigned int nMagY : 5; 931 unsigned int nW : 12; 932 unsigned int nH : 12; 933 unsigned int reserved : 8; 934 }; 935 static_assert(sizeof(DISPLAY) == sizeof(uint64), "Size of DISPLAY struct must be 8 bytes."); 936 937 struct SIGLBLID : public convertible<uint64> 938 { 939 unsigned int sigid : 32; 940 unsigned int lblid : 32; 941 }; 942 static_assert(sizeof(SIGLBLID) == sizeof(uint64), "Size of SIGLBLID struct must be 8 bytes."); 943 944 struct TRXCONTEXT 945 { 946 uint32 nSize; 947 uint32 nRealSize; 948 uint32 nRRX; 949 uint32 nRRY; 950 bool nDirty; 951 }; 952 953 typedef bool (CGSHandler::*TRANSFERWRITEHANDLER)(const void*, uint32); 954 typedef void (CGSHandler::*TRANSFERREADHANDLER)(void*, uint32); 955 956 void LogWrite(uint8, uint64); 957 void LogPrivateWrite(uint32); 958 959 void WriteToDelayedRegister(uint32, uint32, DELAYED_REGISTER&); 960 961 void ThreadProc(); 962 virtual void InitializeImpl() = 0; 963 virtual void ReleaseImpl() = 0; 964 void ResetBase(); 965 virtual void ResetImpl(); 966 virtual void NotifyPreferencesChangedImpl(); 967 virtual void FlipImpl(); 968 virtual void MarkNewFrame(); 969 virtual void WriteRegisterImpl(uint8, uint64); 970 void FeedImageDataImpl(const uint8*, uint32); 971 void ReadImageDataImpl(void*, uint32); 972 void SubmitWriteBufferImpl(uint32, uint32); 973 974 void BeginTransfer(); 975 976 virtual void BeginTransferWrite(); 977 virtual void TransferWrite(const uint8*, uint32); 978 979 TRANSFERWRITEHANDLER m_transferWriteHandlers[PSM_MAX]; 980 TRANSFERREADHANDLER m_transferReadHandlers[PSM_MAX]; 981 982 bool TransferWriteHandlerInvalid(const void*, uint32); 983 template <typename Storage> 984 bool TransferWriteHandlerGeneric(const void*, uint32); 985 bool TransferWriteHandlerPSMT4(const void*, uint32); 986 bool TransferWriteHandlerPSMCT24(const void*, uint32); 987 bool TransferWriteHandlerPSMT8H(const void*, uint32); 988 template <uint32, uint32> 989 bool TransferWriteHandlerPSMT4H(const void*, uint32); 990 991 void TransferReadHandlerInvalid(void*, uint32); 992 template <typename Storage> 993 void TransferReadHandlerGeneric(void*, uint32); 994 void TransferReadHandlerPSMCT24(void*, uint32); 995 996 virtual void SyncCLUT(const TEX0&); 997 bool ProcessCLD(const TEX0&); 998 template <typename Indexor> 999 bool ReadCLUT4_16(const TEX0&); 1000 template <typename Indexor> 1001 bool ReadCLUT8_16(const TEX0&); 1002 void ReadCLUT4(const TEX0&); 1003 void ReadCLUT8(const TEX0&); 1004 1005 static bool IsCompatibleFramebufferPSM(unsigned int, unsigned int); 1006 1007 PRESENTATION_VIEWPORT GetPresentationViewport() const; 1008 1009 bool m_loggingEnabled; 1010 1011 uint64 m_nPMODE; //0x12000000 1012 uint64 m_nSMODE2; //0x12000020 1013 DELAYED_REGISTER m_nDISPFB1; //0x12000070 1014 DELAYED_REGISTER m_nDISPLAY1; //0x12000080 1015 DELAYED_REGISTER m_nDISPFB2; //0x12000090 1016 DELAYED_REGISTER m_nDISPLAY2; //0x120000A0 1017 uint64 m_nCSR; //0x12001000 1018 uint64 m_nIMR; //0x12001010 1019 uint64 m_nBUSDIR; //0x12001040 1020 uint64 m_nSIGLBLID; //0x12001080 1021 1022 PRESENTATION_PARAMS m_presentationParams; 1023 1024 TRXCONTEXT m_trxCtx; 1025 1026 uint64 m_nReg[REGISTER_MAX]; 1027 1028 uint8* m_pRAM; 1029 1030 uint16* m_pCLUT; 1031 uint32 m_nCBP0; 1032 uint32 m_nCBP1; 1033 1034 uint32 m_drawCallCount; 1035 1036 //Rename to register write buffer? 1037 RegisterWrite* m_writeBuffer; 1038 uint32 m_writeBufferSize = 0; 1039 uint32 m_writeBufferProcessIndex = 0; 1040 uint32 m_writeBufferSubmitIndex = 0; 1041 1042 CRT_MODE m_crtMode; 1043 std::thread m_thread; 1044 std::recursive_mutex m_registerMutex; 1045 std::atomic<int> m_transferCount; 1046 bool m_threadDone; 1047 CFrameDump* m_frameDump; 1048 bool m_drawEnabled = true; 1049 CINTC* m_intc = nullptr; 1050 bool m_gsThreaded = true; 1051 bool m_flipped = false; 1052 1053 private: 1054 CMailBox m_mailBox; 1055 }; 1056