mirror of
https://github.com/libretro/Play-.git
synced 2025-02-26 06:25:30 +00:00
978 lines
21 KiB
C++
978 lines
21 KiB
C++
#pragma once
|
|
|
|
#include <thread>
|
|
#include <vector>
|
|
#include <functional>
|
|
#include <atomic>
|
|
#include <array>
|
|
#include <boost/signals2.hpp>
|
|
|
|
#include "bitmap/Bitmap.h"
|
|
#include "Types.h"
|
|
#include "Convertible.h"
|
|
#include "../MailBox.h"
|
|
#include "../Integer64.h"
|
|
#include "zip/ZipArchiveWriter.h"
|
|
#include "zip/ZipArchiveReader.h"
|
|
|
|
class CFrameDump;
|
|
class CGsPacketMetadata;
|
|
struct MASSIVEWRITE_INFO;
|
|
|
|
#define PREF_CGSHANDLER_PRESENTATION_MODE "renderer.presentationmode"
|
|
|
|
enum GS_REGS
|
|
{
|
|
GS_REG_PRIM = 0x00,
|
|
GS_REG_RGBAQ = 0x01,
|
|
GS_REG_ST = 0x02,
|
|
GS_REG_UV = 0x03,
|
|
GS_REG_XYZF2 = 0x04,
|
|
GS_REG_XYZ2 = 0x05,
|
|
GS_REG_TEX0_1 = 0x06,
|
|
GS_REG_TEX0_2 = 0x07,
|
|
GS_REG_CLAMP_1 = 0x08,
|
|
GS_REG_CLAMP_2 = 0x09,
|
|
GS_REG_FOG = 0x0A,
|
|
GS_REG_XYZF3 = 0x0C,
|
|
GS_REG_XYZ3 = 0x0D,
|
|
GS_REG_TEX1_1 = 0x14,
|
|
GS_REG_TEX1_2 = 0x15,
|
|
GS_REG_TEX2_1 = 0x16,
|
|
GS_REG_TEX2_2 = 0x17,
|
|
GS_REG_XYOFFSET_1 = 0x18,
|
|
GS_REG_XYOFFSET_2 = 0x19,
|
|
GS_REG_PRMODECONT = 0x1A,
|
|
GS_REG_PRMODE = 0x1B,
|
|
GS_REG_TEXCLUT = 0x1C,
|
|
GS_REG_MIPTBP1_1 = 0x34,
|
|
GS_REG_MIPTBP1_2 = 0x35,
|
|
GS_REG_MIPTBP2_1 = 0x36,
|
|
GS_REG_MIPTBP2_2 = 0x37,
|
|
GS_REG_TEXA = 0x3B,
|
|
GS_REG_FOGCOL = 0x3D,
|
|
GS_REG_TEXFLUSH = 0x3F,
|
|
GS_REG_SCISSOR_1 = 0x40,
|
|
GS_REG_SCISSOR_2 = 0x41,
|
|
GS_REG_ALPHA_1 = 0x42,
|
|
GS_REG_ALPHA_2 = 0x43,
|
|
GS_REG_COLCLAMP = 0x46,
|
|
GS_REG_TEST_1 = 0x47,
|
|
GS_REG_TEST_2 = 0x48,
|
|
GS_REG_PABE = 0x49,
|
|
GS_REG_FBA_1 = 0x4A,
|
|
GS_REG_FBA_2 = 0x4B,
|
|
GS_REG_FRAME_1 = 0x4C,
|
|
GS_REG_FRAME_2 = 0x4D,
|
|
GS_REG_ZBUF_1 = 0x4E,
|
|
GS_REG_ZBUF_2 = 0x4F,
|
|
GS_REG_BITBLTBUF = 0x50,
|
|
GS_REG_TRXPOS = 0x51,
|
|
GS_REG_TRXREG = 0x52,
|
|
GS_REG_TRXDIR = 0x53,
|
|
GS_REG_HWREG = 0x54,
|
|
GS_REG_SIGNAL = 0x60,
|
|
GS_REG_FINISH = 0x61,
|
|
GS_REG_LABEL = 0x62,
|
|
};
|
|
|
|
class CGSHandler
|
|
{
|
|
public:
|
|
enum RAMSIZE
|
|
{
|
|
RAMSIZE = 0x00400000,
|
|
};
|
|
|
|
enum PRESENTATION_MODE
|
|
{
|
|
PRESENTATION_MODE_FILL,
|
|
PRESENTATION_MODE_FIT,
|
|
PRESENTATION_MODE_ORIGINAL
|
|
};
|
|
|
|
enum PRIVATE_REGISTER
|
|
{
|
|
GS_PMODE = 0x12000000,
|
|
GS_SMODE2 = 0x12000020,
|
|
GS_DISPFB1 = 0x12000070,
|
|
GS_DISPLAY1 = 0x12000080,
|
|
GS_DISPFB2 = 0x12000090,
|
|
GS_DISPLAY2 = 0x120000A0,
|
|
GS_CSR = 0x12001000,
|
|
GS_IMR = 0x12001010,
|
|
GS_SIGLBLID = 0x12001080,
|
|
};
|
|
|
|
enum
|
|
{
|
|
CSR_SIGNAL_EVENT = 0x0001,
|
|
CSR_FINISH_EVENT = 0x0002,
|
|
CSR_HSYNC_INT = 0x0004,
|
|
CSR_VSYNC_INT = 0x0008,
|
|
CSR_RESET = 0x0200,
|
|
CSR_FIELD = 0x2000,
|
|
CSR_FIFO_STATUS = 0xC000,
|
|
CSR_FIFO_NEITHER = 0x0000,
|
|
CSR_FIFO_EMPTY = 0x4000,
|
|
CSR_FIFO_FULL = 0x8000
|
|
};
|
|
|
|
struct PRESENTATION_PARAMS
|
|
{
|
|
uint32 windowWidth;
|
|
uint32 windowHeight;
|
|
PRESENTATION_MODE mode;
|
|
};
|
|
|
|
enum PSM
|
|
{
|
|
PSMCT32 = 0x00,
|
|
PSMCT24 = 0x01,
|
|
PSMCT16 = 0x02,
|
|
PSMCT24_UNK = 0x09,
|
|
PSMCT16S = 0x0A,
|
|
PSMT8 = 0x13,
|
|
PSMT4 = 0x14,
|
|
PSMT8H = 0x1B,
|
|
PSMT4HL = 0x24,
|
|
PSMT4HH = 0x2C,
|
|
PSMZ32 = 0x30,
|
|
PSMZ24 = 0x31,
|
|
PSMZ16 = 0x32,
|
|
PSMZ16S = 0x3A,
|
|
PSM_MAX = 0x40,
|
|
};
|
|
|
|
enum PRIM_TYPE
|
|
{
|
|
PRIM_POINT,
|
|
PRIM_LINE,
|
|
PRIM_LINESTRIP,
|
|
PRIM_TRIANGLE,
|
|
PRIM_TRIANGLESTRIP,
|
|
PRIM_TRIANGLEFAN,
|
|
PRIM_SPRITE,
|
|
PRIM_INVALID,
|
|
};
|
|
|
|
enum ALPHABLEND_ABD
|
|
{
|
|
ALPHABLEND_ABD_CS,
|
|
ALPHABLEND_ABD_CD,
|
|
ALPHABLEND_ABD_ZERO,
|
|
ALPHABLEND_ABD_INVALID
|
|
};
|
|
|
|
enum ALPHABLEND_C
|
|
{
|
|
ALPHABLEND_C_AS,
|
|
ALPHABLEND_C_AD,
|
|
ALPHABLEND_C_FIX,
|
|
ALPHABLEND_C_INVALID
|
|
};
|
|
|
|
enum REGISTER_MAX
|
|
{
|
|
REGISTER_MAX = 0x80
|
|
};
|
|
|
|
//Reg 0x00
|
|
struct PRIM : public convertible<uint64>
|
|
{
|
|
unsigned int nType : 3;
|
|
unsigned int nShading : 1;
|
|
unsigned int nTexture : 1;
|
|
unsigned int nFog : 1;
|
|
unsigned int nAlpha : 1;
|
|
unsigned int nAntiAliasing : 1;
|
|
unsigned int nUseUV : 1;
|
|
unsigned int nContext : 1;
|
|
unsigned int nUseFloat : 1;
|
|
unsigned int nReserved0 : 21;
|
|
uint32 nReserved1;
|
|
};
|
|
static_assert(sizeof(PRIM) == sizeof(uint64), "Size of PRIM struct must be 8 bytes.");
|
|
|
|
//Reg 0x01
|
|
struct RGBAQ : public convertible<uint64>
|
|
{
|
|
uint8 nR;
|
|
uint8 nG;
|
|
uint8 nB;
|
|
uint8 nA;
|
|
float nQ;
|
|
};
|
|
static_assert(sizeof(RGBAQ) == sizeof(uint64), "Size of RGBAQ struct must be 8 bytes.");
|
|
|
|
//Reg 0x02
|
|
struct ST : public convertible<uint64>
|
|
{
|
|
float nS;
|
|
float nT;
|
|
};
|
|
static_assert(sizeof(ST) == sizeof(uint64), "Size of ST struct must be 8 bytes.");
|
|
|
|
//Reg 0x03
|
|
struct UV : public convertible<uint64>
|
|
{
|
|
uint16 nU;
|
|
uint16 nV;
|
|
uint32 nReserved;
|
|
|
|
float GetU() const
|
|
{
|
|
return static_cast<float>(nU & 0x3FFF) / 16.0f;
|
|
}
|
|
float GetV() const
|
|
{
|
|
return static_cast<float>(nV & 0x3FFF) / 16.0f;
|
|
}
|
|
};
|
|
static_assert(sizeof(UV) == sizeof(uint64), "Size of UV struct must be 8 bytes.");
|
|
|
|
//Reg 0x04/0x0C
|
|
struct XYZF : public convertible<uint64>
|
|
{
|
|
unsigned int nX : 16;
|
|
unsigned int nY : 16;
|
|
unsigned int nZ : 24;
|
|
unsigned int nF : 8;
|
|
|
|
float GetX()
|
|
{
|
|
return static_cast<float>(nX) / 16.0f;
|
|
}
|
|
float GetY()
|
|
{
|
|
return static_cast<float>(nY) / 16.0f;
|
|
}
|
|
};
|
|
static_assert(sizeof(XYZF) == sizeof(uint64), "Size of XYZF struct must be 8 bytes.");
|
|
|
|
//Reg 0x05/0x0D
|
|
struct XYZ : public convertible<uint64>
|
|
{
|
|
unsigned int nX : 16;
|
|
unsigned int nY : 16;
|
|
uint32 nZ;
|
|
|
|
float GetX()
|
|
{
|
|
return static_cast<float>(nX) / 16.0f;
|
|
}
|
|
float GetY()
|
|
{
|
|
return static_cast<float>(nY) / 16.0f;
|
|
}
|
|
float GetZ()
|
|
{
|
|
return static_cast<float>(nZ);
|
|
}
|
|
};
|
|
static_assert(sizeof(XYZ) == sizeof(uint64), "Size of XYZ struct must be 8 bytes.");
|
|
|
|
//Reg 0x06/0x07
|
|
struct TEX0 : public convertible<uint64>
|
|
{
|
|
unsigned int nBufPtr : 14;
|
|
unsigned int nBufWidth : 6;
|
|
unsigned int nPsm : 6;
|
|
unsigned int nWidth : 4;
|
|
unsigned int nPad0 : 2;
|
|
unsigned int nPad1 : 2;
|
|
unsigned int nColorComp : 1;
|
|
unsigned int nFunction : 2;
|
|
unsigned int nCBP : 14;
|
|
unsigned int nCPSM : 4;
|
|
unsigned int nCSM : 1;
|
|
unsigned int nCSA : 5;
|
|
unsigned int nCLD : 3;
|
|
uint32 GetBufPtr() const
|
|
{
|
|
return nBufPtr * 256;
|
|
}
|
|
uint32 GetBufWidth() const
|
|
{
|
|
return nBufWidth * 64;
|
|
}
|
|
uint32 GetWidth() const
|
|
{
|
|
return (1 << nWidth);
|
|
}
|
|
uint32 GetHeight() const
|
|
{
|
|
return (1 << (nPad0 | (nPad1 << 2)));
|
|
}
|
|
uint32 GetCLUTPtr() const
|
|
{
|
|
return nCBP * 256;
|
|
}
|
|
};
|
|
static_assert(sizeof(TEX0) == sizeof(uint64), "Size of TEX0 struct must be 8 bytes.");
|
|
|
|
//Reg 0x08/0x09
|
|
struct CLAMP : public convertible<uint64>
|
|
{
|
|
unsigned int nWMS : 2;
|
|
unsigned int nWMT : 2;
|
|
unsigned int nMINU : 10;
|
|
unsigned int nMAXU : 10;
|
|
unsigned int nReserved0 : 8;
|
|
unsigned int nReserved1 : 2;
|
|
unsigned int nMAXV : 10;
|
|
unsigned int nReserved2 : 20;
|
|
unsigned int GetMinU()
|
|
{
|
|
return nMINU;
|
|
}
|
|
unsigned int GetMaxU()
|
|
{
|
|
return nMAXU;
|
|
}
|
|
unsigned int GetMinV()
|
|
{
|
|
return (nReserved0) | (nReserved1 << 8);
|
|
}
|
|
unsigned int GetMaxV()
|
|
{
|
|
return nMAXV;
|
|
}
|
|
};
|
|
static_assert(sizeof(CLAMP) == sizeof(uint64), "Size of CLAMP struct must be 8 bytes.");
|
|
|
|
//Reg 0x14/0x15
|
|
struct TEX1 : public convertible<uint64>
|
|
{
|
|
unsigned int nLODMethod : 1;
|
|
unsigned int nReserved0 : 1;
|
|
unsigned int nMaxMip : 3;
|
|
unsigned int nMagFilter : 1;
|
|
unsigned int nMinFilter : 3;
|
|
unsigned int nMipBaseAddr : 1;
|
|
unsigned int nReserved1 : 9;
|
|
unsigned int nLODL : 2;
|
|
unsigned int nReserved2 : 11;
|
|
unsigned int nLODK : 12;
|
|
unsigned int nReserved3 : 20;
|
|
|
|
float GetK() const
|
|
{
|
|
int16 temp = nLODK | ((nLODK & 0x800) ? 0xF000 : 0x0000);
|
|
return static_cast<float>(temp) / 16.0f;
|
|
}
|
|
};
|
|
static_assert(sizeof(TEX1) == sizeof(uint64), "Size of TEX1 struct must be 8 bytes.");
|
|
|
|
//Reg 0x16/0x17
|
|
struct TEX2 : public convertible<uint64>
|
|
{
|
|
unsigned int nReserved0 : 20;
|
|
unsigned int nPsm : 6;
|
|
unsigned int nReserved1 : 6;
|
|
unsigned int nReserved2 : 5;
|
|
unsigned int nCBP : 14;
|
|
unsigned int nCPSM : 4;
|
|
unsigned int nCSM : 1;
|
|
unsigned int nCSA : 5;
|
|
unsigned int nCLD : 3;
|
|
uint32 GetCLUTPtr()
|
|
{
|
|
return nCBP * 256;
|
|
}
|
|
};
|
|
static_assert(sizeof(TEX2) == sizeof(uint64), "Size of TEX2 struct must be 8 bytes.");
|
|
|
|
//Reg 0x18/0x19
|
|
struct XYOFFSET : public convertible<uint64>
|
|
{
|
|
uint16 nOffsetX;
|
|
uint16 nReserved0;
|
|
uint16 nOffsetY;
|
|
uint16 nReserved1;
|
|
float GetX()
|
|
{
|
|
return static_cast<float>(nOffsetX) / 16.0f;
|
|
}
|
|
float GetY()
|
|
{
|
|
return static_cast<float>(nOffsetY) / 16.0f;
|
|
}
|
|
};
|
|
static_assert(sizeof(XYOFFSET) == sizeof(uint64), "Size of XYOFFSET struct must be 8 bytes.");
|
|
|
|
//Reg 0x1B
|
|
struct PRMODE : public convertible<uint64>
|
|
{
|
|
unsigned int nReserved0 : 3;
|
|
unsigned int nShading : 1;
|
|
unsigned int nTexture : 1;
|
|
unsigned int nFog : 1;
|
|
unsigned int nAlpha : 1;
|
|
unsigned int nAntiAliasing : 1;
|
|
unsigned int nUseUV : 1;
|
|
unsigned int nContext : 1;
|
|
unsigned int nUseFloat : 1;
|
|
unsigned int nReserved1 : 21;
|
|
uint32 nReserved2;
|
|
};
|
|
static_assert(sizeof(PRMODE) == sizeof(uint64), "Size of PRMODE struct must be 8 bytes.");
|
|
|
|
//Reg 0x34/0x35
|
|
struct MIPTBP1 : public convertible<uint64>
|
|
{
|
|
unsigned int tbp1 : 14;
|
|
unsigned int tbw1 : 6;
|
|
unsigned int pad0 : 12;
|
|
unsigned int pad1 : 2;
|
|
unsigned int tbw2 : 6;
|
|
unsigned int tbp3 : 14;
|
|
unsigned int tbw3 : 6;
|
|
unsigned int reserved : 4;
|
|
uint32 GetTbp1() const
|
|
{
|
|
return tbp1 * 256;
|
|
}
|
|
uint32 GetTbp2() const
|
|
{
|
|
return (pad0 | (pad1 << 12)) * 256;
|
|
}
|
|
uint32 GetTbp3() const
|
|
{
|
|
return tbp3 * 256;
|
|
}
|
|
uint32 GetTbw1() const
|
|
{
|
|
return tbw1 * 64;
|
|
}
|
|
uint32 GetTbw2() const
|
|
{
|
|
return tbw2 * 64;
|
|
}
|
|
uint32 GetTbw3() const
|
|
{
|
|
return tbw3 * 64;
|
|
}
|
|
};
|
|
static_assert(sizeof(MIPTBP1) == sizeof(uint64), "Size of MIPTBP1 struct must be 8 bytes.");
|
|
|
|
//Reg 0x36/0x37
|
|
struct MIPTBP2 : public convertible<uint64>
|
|
{
|
|
unsigned int tbp4 : 14;
|
|
unsigned int tbw4 : 6;
|
|
unsigned int pad0 : 12;
|
|
unsigned int pad1 : 2;
|
|
unsigned int tbw5 : 6;
|
|
unsigned int tbp6 : 14;
|
|
unsigned int tbw6 : 6;
|
|
unsigned int reserved : 4;
|
|
uint32 GetTbp4() const
|
|
{
|
|
return tbp4 * 256;
|
|
}
|
|
uint32 GetTbp5() const
|
|
{
|
|
return (pad0 | (pad1 << 12)) * 256;
|
|
}
|
|
uint32 GetTbp6() const
|
|
{
|
|
return tbp6 * 256;
|
|
}
|
|
uint32 GetTbw4() const
|
|
{
|
|
return tbw4 * 64;
|
|
}
|
|
uint32 GetTbw5() const
|
|
{
|
|
return tbw5 * 64;
|
|
}
|
|
uint32 GetTbw6() const
|
|
{
|
|
return tbw6 * 64;
|
|
}
|
|
};
|
|
static_assert(sizeof(MIPTBP2) == sizeof(uint64), "Size of MIPTBP2 struct must be 8 bytes.");
|
|
|
|
//Reg 0x3B
|
|
struct TEXA : public convertible<uint64>
|
|
{
|
|
unsigned int nTA0 : 8;
|
|
unsigned int nReserved0 : 7;
|
|
unsigned int nAEM : 1;
|
|
unsigned int nReserved1 : 16;
|
|
unsigned int nTA1 : 8;
|
|
unsigned int nReserved2 : 24;
|
|
};
|
|
static_assert(sizeof(TEXA) == sizeof(uint64), "Size of TEXA struct must be 8 bytes.");
|
|
|
|
//Reg 0x3D
|
|
struct FOGCOL : public convertible<uint64>
|
|
{
|
|
unsigned int nFCR : 8;
|
|
unsigned int nFCG : 8;
|
|
unsigned int nFCB : 8;
|
|
unsigned int nReserved0 : 8;
|
|
unsigned int nReserved1 : 32;
|
|
};
|
|
static_assert(sizeof(FOGCOL) == sizeof(uint64), "Size of FOGCOL struct must be 8 bytes.");
|
|
|
|
//Reg 0x3F
|
|
struct TEXCLUT : public convertible<uint64>
|
|
{
|
|
unsigned int nCBW : 6;
|
|
unsigned int nCOU : 6;
|
|
unsigned int nCOV : 10;
|
|
unsigned int nReserved1 : 10;
|
|
unsigned int nReserved2 : 32;
|
|
uint32 GetBufWidth()
|
|
{
|
|
return nCBW * 64;
|
|
}
|
|
uint32 GetOffsetU()
|
|
{
|
|
return nCOU * 16;
|
|
}
|
|
uint32 GetOffsetV()
|
|
{
|
|
return nCOV;
|
|
}
|
|
};
|
|
static_assert(sizeof(TEXCLUT) == sizeof(uint64), "Size of TEXCLUT struct must be 8 bytes.");
|
|
|
|
//Reg 0x40/0x41
|
|
struct SCISSOR : public convertible<uint64>
|
|
{
|
|
unsigned int scax0 : 11;
|
|
unsigned int reserved0 : 5;
|
|
unsigned int scax1 : 11;
|
|
unsigned int reserved1 : 5;
|
|
unsigned int scay0 : 11;
|
|
unsigned int reserved2 : 5;
|
|
unsigned int scay1 : 11;
|
|
unsigned int reserved3 : 5;
|
|
};
|
|
static_assert(sizeof(SCISSOR) == sizeof(uint64), "Size of SCISSOR struct must be 8 bytes.");
|
|
|
|
//Reg 0x42/0x43
|
|
struct ALPHA : public convertible<uint64>
|
|
{
|
|
unsigned int nA : 2;
|
|
unsigned int nB : 2;
|
|
unsigned int nC : 2;
|
|
unsigned int nD : 2;
|
|
unsigned int nReserved0 : 24;
|
|
unsigned int nFix : 8;
|
|
unsigned int nReserved1 : 24;
|
|
};
|
|
static_assert(sizeof(ALPHA) == sizeof(uint64), "Size of ALPHA struct must be 8 bytes.");
|
|
|
|
//Reg 0x47/0x48
|
|
struct TEST : public convertible<uint64>
|
|
{
|
|
unsigned int nAlphaEnabled : 1;
|
|
unsigned int nAlphaMethod : 3;
|
|
unsigned int nAlphaRef : 8;
|
|
unsigned int nAlphaFail : 2;
|
|
unsigned int nDestAlphaEnabled : 1;
|
|
unsigned int nDestAlphaMode : 1;
|
|
unsigned int nDepthEnabled : 1;
|
|
unsigned int nDepthMethod : 2;
|
|
unsigned int nReserved0 : 13;
|
|
uint32 nReserved1;
|
|
};
|
|
static_assert(sizeof(TEST) == sizeof(uint64), "Size of TEST struct must be 8 bytes.");
|
|
|
|
//Reg 0x4C/0x4D
|
|
struct FRAME : public convertible<uint64>
|
|
{
|
|
unsigned int nPtr : 9;
|
|
unsigned int nReserved0 : 7;
|
|
unsigned int nWidth : 6;
|
|
unsigned int nReserved1 : 2;
|
|
unsigned int nPsm : 6;
|
|
unsigned int nReserved2 : 2;
|
|
unsigned int nMask : 32;
|
|
uint32 GetBasePtr() const
|
|
{
|
|
return nPtr * 8192;
|
|
}
|
|
uint32 GetWidth() const
|
|
{
|
|
return nWidth * 64;
|
|
}
|
|
};
|
|
static_assert(sizeof(FRAME) == sizeof(uint64), "Size of FRAME struct must be 8 bytes.");
|
|
|
|
//Reg 0x4E/0x4F
|
|
struct ZBUF : public convertible<uint64>
|
|
{
|
|
unsigned int nPtr : 9;
|
|
unsigned int nReserved0 : 15;
|
|
unsigned int nPsm : 4;
|
|
unsigned int nReserved1 : 4;
|
|
unsigned int nMask : 1;
|
|
unsigned int nReserved2 : 31;
|
|
uint32 GetBasePtr() const
|
|
{
|
|
return nPtr * 8192;
|
|
}
|
|
};
|
|
static_assert(sizeof(ZBUF) == sizeof(uint64), "Size of ZBUF struct must be 8 bytes.");
|
|
|
|
//Reg 0x50
|
|
struct BITBLTBUF : public convertible<uint64>
|
|
{
|
|
unsigned int nSrcPtr : 14;
|
|
unsigned int nReserved0 : 2;
|
|
unsigned int nSrcWidth : 6;
|
|
unsigned int nReserved1 : 2;
|
|
unsigned int nSrcPsm : 6;
|
|
unsigned int nReserved2 : 2;
|
|
unsigned int nDstPtr : 14;
|
|
unsigned int nReserved3 : 2;
|
|
unsigned int nDstWidth : 6;
|
|
unsigned int nReserved4 : 2;
|
|
unsigned int nDstPsm : 6;
|
|
unsigned int nReserved5 : 2;
|
|
uint32 GetSrcPtr()
|
|
{
|
|
return nSrcPtr * 256;
|
|
}
|
|
uint32 GetSrcWidth()
|
|
{
|
|
return nSrcWidth * 64;
|
|
}
|
|
uint32 GetDstPtr()
|
|
{
|
|
return nDstPtr * 256;
|
|
}
|
|
uint32 GetDstWidth()
|
|
{
|
|
return nDstWidth * 64;
|
|
}
|
|
};
|
|
static_assert(sizeof(BITBLTBUF) == sizeof(uint64), "Size of BITBLTBUF struct must be 8 bytes.");
|
|
|
|
//Reg 0x51
|
|
struct TRXPOS : public convertible<uint64>
|
|
{
|
|
unsigned int nSSAX : 11;
|
|
unsigned int nReserved0 : 5;
|
|
unsigned int nSSAY : 11;
|
|
unsigned int nReserved1 : 5;
|
|
unsigned int nDSAX : 11;
|
|
unsigned int nReserved2 : 5;
|
|
unsigned int nDSAY : 11;
|
|
unsigned int nDIR : 2;
|
|
unsigned int nReserved3 : 3;
|
|
};
|
|
static_assert(sizeof(TRXPOS) == sizeof(uint64), "Size of TRXPOS struct must be 8 bytes.");
|
|
|
|
//Reg 0x52
|
|
struct TRXREG : public convertible<uint64>
|
|
{
|
|
unsigned int nRRW : 12;
|
|
unsigned int nReserved0 : 20;
|
|
unsigned int nRRH : 12;
|
|
unsigned int nReserved1 : 20;
|
|
};
|
|
static_assert(sizeof(TRXREG) == sizeof(uint64), "Size of TRXREG struct must be 8 bytes.");
|
|
|
|
//Reg 0x60
|
|
struct SIGNAL : public convertible<uint64>
|
|
{
|
|
unsigned int id : 32;
|
|
unsigned int idmsk : 32;
|
|
};
|
|
static_assert(sizeof(SIGNAL) == sizeof(uint64), "Size of SIGNAL struct must be 8 bytes.");
|
|
|
|
//Reg 0x62
|
|
struct LABEL : public convertible<uint64>
|
|
{
|
|
unsigned int id : 32;
|
|
unsigned int idmsk : 32;
|
|
};
|
|
static_assert(sizeof(LABEL) == sizeof(uint64), "Size of LABEL struct must be 8 bytes.");
|
|
|
|
typedef std::pair<uint8, uint64> RegisterWrite;
|
|
typedef std::vector<RegisterWrite> RegisterWriteList;
|
|
typedef std::function<CGSHandler*(void)> FactoryFunction;
|
|
|
|
CGSHandler();
|
|
virtual ~CGSHandler();
|
|
|
|
static void RegisterPreferences();
|
|
void NotifyPreferencesChanged();
|
|
|
|
void Reset();
|
|
void SetPresentationParams(const PRESENTATION_PARAMS&);
|
|
|
|
virtual void SaveState(Framework::CZipArchiveWriter&);
|
|
virtual void LoadState(Framework::CZipArchiveReader&);
|
|
|
|
void SetFrameDump(CFrameDump*);
|
|
|
|
bool GetDrawEnabled() const;
|
|
void SetDrawEnabled(bool);
|
|
|
|
void WritePrivRegister(uint32, uint32);
|
|
uint32 ReadPrivRegister(uint32);
|
|
|
|
void SetLoggingEnabled(bool);
|
|
static std::string DisassembleWrite(uint8, uint64);
|
|
|
|
void SetVBlank();
|
|
void ResetVBlank();
|
|
|
|
void WriteRegister(uint8, uint64);
|
|
void FeedImageData(const void*, uint32);
|
|
void ReadImageData(void*, uint32);
|
|
void WriteRegisterMassively(RegisterWriteList, const CGsPacketMetadata*);
|
|
|
|
virtual void SetCrt(bool, unsigned int, bool);
|
|
void Initialize();
|
|
void Release();
|
|
virtual void ProcessHostToLocalTransfer() = 0;
|
|
virtual void ProcessLocalToHostTransfer() = 0;
|
|
virtual void ProcessLocalToLocalTransfer() = 0;
|
|
virtual void ProcessClutTransfer(uint32, uint32) = 0;
|
|
void Flip(bool showOnly = false);
|
|
virtual void ReadFramebuffer(uint32, uint32, void*) = 0;
|
|
|
|
void MakeLinearCLUT(const TEX0&, std::array<uint32, 256>&) const;
|
|
|
|
uint8* GetRam();
|
|
uint64* GetRegisters();
|
|
|
|
uint64 GetSMODE2() const;
|
|
void SetSMODE2(uint64);
|
|
|
|
int GetPendingTransferCount() const;
|
|
bool IsInterruptPending();
|
|
|
|
unsigned int GetCrtWidth() const;
|
|
unsigned int GetCrtHeight() const;
|
|
bool GetCrtIsInterlaced() const;
|
|
bool GetCrtIsFrameMode() const;
|
|
|
|
virtual Framework::CBitmap GetScreenshot();
|
|
|
|
boost::signals2::signal<void()> OnFlipComplete;
|
|
|
|
boost::signals2::signal<void(uint32)> OnNewFrame;
|
|
|
|
protected:
|
|
struct DELAYED_REGISTER
|
|
{
|
|
uint32 heldValue;
|
|
INTEGER64 value;
|
|
};
|
|
|
|
enum CLUTSIZE
|
|
{
|
|
CLUTSIZE = 0x400,
|
|
CLUTENTRYCOUNT = (CLUTSIZE / 2)
|
|
};
|
|
|
|
enum CLAMP_MODE
|
|
{
|
|
CLAMP_MODE_REPEAT,
|
|
CLAMP_MODE_CLAMP,
|
|
CLAMP_MODE_REGION_CLAMP,
|
|
CLAMP_MODE_REGION_REPEAT,
|
|
CLAMP_MODE_MAX
|
|
};
|
|
|
|
enum TEX0_FUNCTION
|
|
{
|
|
TEX0_FUNCTION_MODULATE,
|
|
TEX0_FUNCTION_DECAL,
|
|
TEX0_FUNCTION_HIGHLIGHT,
|
|
TEX0_FUNCTION_HIGHLIGHT2,
|
|
TEX0_FUNCTION_MAX
|
|
};
|
|
|
|
enum MAG_FILTER
|
|
{
|
|
MAG_FILTER_NEAREST = 0,
|
|
MAG_FILTER_LINEAR = 1
|
|
};
|
|
|
|
enum MIN_FILTER
|
|
{
|
|
MIN_FILTER_NEAREST = 0,
|
|
MIN_FILTER_LINEAR = 1,
|
|
MIN_FILTER_NEAREST_MIP_NEAREST = 2,
|
|
MIN_FILTER_NEAREST_MIP_LINEAR = 3,
|
|
MIN_FILTER_LINEAR_MIP_NEAREST = 4,
|
|
MIN_FILTER_LINEAR_MIP_LINEAR = 5
|
|
};
|
|
|
|
enum ALPHA_TEST_METHOD
|
|
{
|
|
ALPHA_TEST_NEVER,
|
|
ALPHA_TEST_ALWAYS,
|
|
ALPHA_TEST_LESS,
|
|
ALPHA_TEST_LEQUAL,
|
|
ALPHA_TEST_EQUAL,
|
|
ALPHA_TEST_GEQUAL,
|
|
ALPHA_TEST_GREATER,
|
|
ALPHA_TEST_NOTEQUAL,
|
|
ALPHA_TEST_MAX
|
|
};
|
|
|
|
enum ALPHA_TEST_FAIL_METHOD
|
|
{
|
|
ALPHA_TEST_FAIL_KEEP,
|
|
ALPHA_TEST_FAIL_FBONLY,
|
|
ALPHA_TEST_FAIL_ZBONLY,
|
|
ALPHA_TEST_FAIL_RGBONLY
|
|
};
|
|
|
|
//-----------------------------------
|
|
//Private Registers
|
|
|
|
struct SMODE2 : public convertible<uint64>
|
|
{
|
|
unsigned int interlaced : 1;
|
|
unsigned int ffmd : 1;
|
|
unsigned int dpms : 2;
|
|
unsigned int reserved0 : 28;
|
|
unsigned int reserved1;
|
|
};
|
|
static_assert(sizeof(SMODE2) == sizeof(uint64), "Size of SMODE2 struct must be 8 bytes.");
|
|
|
|
struct DISPFB : public convertible<uint64>
|
|
{
|
|
unsigned int nBufPtr : 9;
|
|
unsigned int nBufWidth : 6;
|
|
unsigned int nPSM : 5;
|
|
unsigned int nReserved0 : 12;
|
|
unsigned int nX : 11;
|
|
unsigned int nY : 11;
|
|
unsigned int nReserved1 : 10;
|
|
uint32 GetBufPtr()
|
|
{
|
|
return nBufPtr * 8192;
|
|
};
|
|
uint32 GetBufWidth()
|
|
{
|
|
return nBufWidth * 64;
|
|
};
|
|
};
|
|
static_assert(sizeof(DISPFB) == sizeof(uint64), "Size of DISPFB struct must be 8 bytes.");
|
|
|
|
struct DISPLAY : public convertible<uint64>
|
|
{
|
|
unsigned int nX : 12;
|
|
unsigned int nY : 11;
|
|
unsigned int nMagX : 4;
|
|
unsigned int nMagY : 5;
|
|
unsigned int nW : 12;
|
|
unsigned int nH : 12;
|
|
unsigned int reserved : 8;
|
|
};
|
|
static_assert(sizeof(DISPLAY) == sizeof(uint64), "Size of DISPLAY struct must be 8 bytes.");
|
|
|
|
struct SIGLBLID : public convertible<uint64>
|
|
{
|
|
unsigned int sigid : 32;
|
|
unsigned int lblid : 32;
|
|
};
|
|
static_assert(sizeof(SIGLBLID) == sizeof(uint64), "Size of SIGLBLID struct must be 8 bytes.");
|
|
|
|
struct TRXCONTEXT
|
|
{
|
|
uint32 nSize;
|
|
uint32 nRealSize;
|
|
uint32 nRRX;
|
|
uint32 nRRY;
|
|
bool nDirty;
|
|
};
|
|
|
|
typedef bool (CGSHandler::*TRANSFERWRITEHANDLER)(const void*, uint32);
|
|
typedef void (CGSHandler::*TRANSFERREADHANDLER)(void*, uint32);
|
|
|
|
void LogWrite(uint8, uint64);
|
|
void LogPrivateWrite(uint32);
|
|
|
|
void WriteToDelayedRegister(uint32, uint32, DELAYED_REGISTER&);
|
|
|
|
void ThreadProc();
|
|
virtual void InitializeImpl() = 0;
|
|
virtual void ReleaseImpl() = 0;
|
|
void ResetBase();
|
|
virtual void ResetImpl();
|
|
virtual void NotifyPreferencesChangedImpl();
|
|
virtual void FlipImpl();
|
|
void MarkNewFrame();
|
|
virtual void WriteRegisterImpl(uint8, uint64);
|
|
void FeedImageDataImpl(const void*, uint32);
|
|
void ReadImageDataImpl(void*, uint32);
|
|
void WriteRegisterMassivelyImpl(const MASSIVEWRITE_INFO&);
|
|
|
|
void BeginTransfer();
|
|
|
|
TRANSFERWRITEHANDLER m_transferWriteHandlers[PSM_MAX];
|
|
TRANSFERREADHANDLER m_transferReadHandlers[PSM_MAX];
|
|
|
|
bool TransferWriteHandlerInvalid(const void*, uint32);
|
|
template <typename Storage>
|
|
bool TransferWriteHandlerGeneric(const void*, uint32);
|
|
bool TransferWriteHandlerPSMT4(const void*, uint32);
|
|
bool TransferWriteHandlerPSMCT24(const void*, uint32);
|
|
bool TransferWriteHandlerPSMT8H(const void*, uint32);
|
|
template <uint32, uint32>
|
|
bool TransferWriteHandlerPSMT4H(const void*, uint32);
|
|
|
|
void TransferReadHandlerInvalid(void*, uint32);
|
|
template <typename Storage>
|
|
void TransferReadHandlerGeneric(void*, uint32);
|
|
|
|
void SyncCLUT(const TEX0&);
|
|
template <typename Indexor>
|
|
bool ReadCLUT4_16(const TEX0&);
|
|
template <typename Indexor>
|
|
bool ReadCLUT8_16(const TEX0&);
|
|
void ReadCLUT4(const TEX0&);
|
|
void ReadCLUT8(const TEX0&);
|
|
|
|
static bool IsCompatibleFramebufferPSM(unsigned int, unsigned int);
|
|
|
|
bool m_loggingEnabled;
|
|
|
|
uint64 m_nPMODE; //0x12000000
|
|
uint64 m_nSMODE2; //0x12000020
|
|
DELAYED_REGISTER m_nDISPFB1; //0x12000070
|
|
DELAYED_REGISTER m_nDISPLAY1; //0x12000080
|
|
DELAYED_REGISTER m_nDISPFB2; //0x12000090
|
|
DELAYED_REGISTER m_nDISPLAY2; //0x120000A0
|
|
uint64 m_nCSR; //0x12001000
|
|
uint64 m_nIMR; //0x12001010
|
|
uint64 m_nSIGLBLID; //0x12001080
|
|
|
|
PRESENTATION_PARAMS m_presentationParams;
|
|
|
|
TRXCONTEXT m_trxCtx;
|
|
|
|
uint64 m_nReg[REGISTER_MAX];
|
|
|
|
uint8* m_pRAM;
|
|
|
|
uint16* m_pCLUT;
|
|
uint32 m_nCBP0;
|
|
uint32 m_nCBP1;
|
|
|
|
uint32 m_drawCallCount;
|
|
|
|
unsigned int m_nCrtMode;
|
|
std::thread m_thread;
|
|
std::recursive_mutex m_registerMutex;
|
|
std::atomic<int> m_transferCount;
|
|
CMailBox m_mailBox;
|
|
bool m_threadDone;
|
|
CFrameDump* m_frameDump;
|
|
bool m_drawEnabled = true;
|
|
};
|