Play-/Source/GSHandler.cpp

1207 lines
28 KiB
C++
Raw Normal View History

#include <stdio.h>
#include <string.h>
#include <functional>
#include "GSHandler.h"
#include "INTC.h"
#include "PtrMacro.h"
#include "Log.h"
#include "MemoryStateFile.h"
#include "RegisterStateFile.h"
#define R_REG(a, v, r) \
if((a) & 0x4) \
{ \
v = (uint32)(r >> 32); \
} \
else \
{ \
v = (uint32)(r & 0xFFFFFFFF); \
}
#define W_REG(a, v, r) \
if((a) & 0x4) \
{ \
(r) &= 0x00000000FFFFFFFFULL; \
(r) |= (uint64)(v) << 32; \
} \
else \
{ \
(r) &= 0xFFFFFFFF00000000ULL; \
(r) |= (v); \
}
#define STATE_RAM ("gs/ram")
#define STATE_REGS ("gs/regs")
#define STATE_TRXCTX ("gs/trxcontext")
#define STATE_PRIVREGS ("gs/privregs.xml")
#define STATE_PRIVREGS_PMODE ("PMODE")
#define STATE_PRIVREGS_DISPFB1 ("DISPFB1")
#define STATE_PRIVREGS_DISPLAY1 ("DISPLAY1")
#define STATE_PRIVREGS_DISPFB2 ("DISPFB2")
#define STATE_PRIVREGS_DISPLAY2 ("DISPLAY2")
#define STATE_PRIVREGS_CSR ("CSR")
#define STATE_PRIVREGS_IMR ("IMR")
#define STATE_PRIVREGS_CRTINTERLACED ("CrtInterlated")
#define STATE_PRIVREGS_CRTMODE ("CrtMode")
#define STATE_PRIVREGS_CRTFRAMEMODE ("CrtFrameMode")
#define LOG_NAME ("gs")
using namespace Framework;
using namespace std;
using namespace std::tr1;
using namespace boost;
int CGSHandler::STORAGEPSMCT32::m_nBlockSwizzleTable[4][8] =
{
{ 0, 1, 4, 5, 16, 17, 20, 21 },
{ 2, 3, 6, 7, 18, 19, 22, 23 },
{ 8, 9, 12, 13, 24, 25, 28, 29 },
{ 10, 11, 14, 15, 26, 27, 30, 31 },
};
int CGSHandler::STORAGEPSMCT32::m_nColumnSwizzleTable[2][8] =
{
{ 0, 1, 4, 5, 8, 9, 12, 13, },
{ 2, 3, 6, 7, 10, 11, 14, 15, },
};
int CGSHandler::STORAGEPSMCT16::m_nBlockSwizzleTable[8][4] =
{
{ 0, 2, 8, 10, },
{ 1, 3, 9, 11, },
{ 4, 6, 12, 14, },
{ 5, 7, 13, 15, },
{ 16, 18, 24, 26, },
{ 17, 19, 25, 27, },
{ 20, 22, 28, 30, },
{ 21, 23, 29, 31, },
};
int CGSHandler::STORAGEPSMCT16::m_nColumnSwizzleTable[2][16] =
{
{ 0, 2, 8, 10, 16, 18, 24, 26, 1, 3, 9, 11, 17, 19, 25, 27, },
{ 4, 6, 12, 14, 20, 22, 28, 30, 5, 7, 13, 15, 21, 23, 29, 31, },
};
int CGSHandler::STORAGEPSMCT16S::m_nBlockSwizzleTable[8][4] =
{
{ 0, 2, 16, 18, },
{ 1, 3, 17, 19, },
{ 8, 10, 24, 26, },
{ 9, 11, 25, 27, },
{ 4, 6, 20, 22, },
{ 5, 7, 21, 23, },
{ 12, 14, 28, 30, },
{ 13, 15, 29, 31, },
};
int CGSHandler::STORAGEPSMCT16S::m_nColumnSwizzleTable[2][16] =
{
{ 0, 2, 8, 10, 16, 18, 24, 26, 1, 3, 9, 11, 17, 19, 25, 27, },
{ 4, 6, 12, 14, 20, 22, 28, 30, 5, 7, 13, 15, 21, 23, 29, 31, },
};
int CGSHandler::STORAGEPSMT8::m_nBlockSwizzleTable[4][8] =
{
{ 0, 1, 4, 5, 16, 17, 20, 21 },
{ 2, 3, 6, 7, 18, 19, 22, 23 },
{ 8, 9, 12, 13, 24, 25, 28, 29 },
{ 10, 11, 14, 15, 26, 27, 30, 31 },
};
int CGSHandler::STORAGEPSMT8::m_nColumnWordTable[2][2][8] =
{
{
{ 0, 1, 4, 5, 8, 9, 12, 13, },
{ 2, 3, 6, 7, 10, 11, 14, 15, },
},
{
{ 8, 9, 12, 13, 0, 1, 4, 5, },
{ 10, 11, 14, 15, 2, 3, 6, 7, },
},
};
int CGSHandler::STORAGEPSMT4::m_nBlockSwizzleTable[8][4] =
{
{ 0, 2, 8, 10, },
{ 1, 3, 9, 11, },
{ 4, 6, 12, 14, },
{ 5, 7, 13, 15, },
{ 16, 18, 24, 26, },
{ 17, 19, 25, 27, },
{ 20, 22, 28, 30, },
{ 21, 23, 29, 31, }
};
int CGSHandler::STORAGEPSMT4::m_nColumnWordTable[2][2][8] =
{
{
{ 0, 1, 4, 5, 8, 9, 12, 13, },
{ 2, 3, 6, 7, 10, 11, 14, 15, },
},
{
{ 8, 9, 12, 13, 0, 1, 4, 5, },
{ 10, 11, 14, 15, 2, 3, 6, 7, },
},
};
CGSHandler::CGSHandler() :
m_thread(NULL),
m_enabled(true)
{
m_pRAM = (uint8*)malloc(RAMSIZE);
for(int i = 0; i < PSM_MAX; i++)
{
m_pTransferHandler[i] = &CGSHandler::TrxHandlerInvalid;
}
m_pTransferHandler[PSMCT32] = &CGSHandler::TrxHandlerCopy<STORAGEPSMCT32>;
m_pTransferHandler[PSMCT24] = &CGSHandler::TrxHandlerPSMCT24;
m_pTransferHandler[PSMCT16] = &CGSHandler::TrxHandlerCopy<STORAGEPSMCT16>;
m_pTransferHandler[PSMT8] = &CGSHandler::TrxHandlerCopy<STORAGEPSMT8>;
m_pTransferHandler[PSMT4] = &CGSHandler::TrxHandlerPSMT4;
m_pTransferHandler[PSMT8H] = &CGSHandler::TrxHandlerPSMT8H;
m_pTransferHandler[PSMT4HL] = &CGSHandler::TrxHandlerPSMT4H<24, 0x0F000000>;
m_pTransferHandler[PSMT4HH] = &CGSHandler::TrxHandlerPSMT4H<28, 0xF0000000>;
Reset();
m_thread = new thread(bind(&CGSHandler::ThreadProc, this));
}
CGSHandler::~CGSHandler()
{
FREEPTR(m_pRAM);
}
void CGSHandler::Reset()
{
memset(m_nReg, 0, sizeof(uint64) * 0x80);
m_nReg[GS_REG_PRMODECONT] = 1;
memset(m_pRAM, 0, RAMSIZE);
m_nPMODE = 0;
m_nDISPFB1 = 0;
m_nDISPLAY1 = 0;
m_nDISPFB2 = 0;
m_nDISPLAY2 = 0;
m_nCSR = 0;
m_nIMR = 0;
m_nCrtIsInterlaced = false;
m_nCrtMode = 0;
m_nCrtIsFrameMode = false;
m_enabled = true;
}
void CGSHandler::SetEnabled(bool enabled)
{
m_enabled = enabled;
}
void CGSHandler::SaveState(CZipArchiveWriter& archive)
{
archive.InsertFile(new CMemoryStateFile(STATE_RAM, m_pRAM, RAMSIZE));
archive.InsertFile(new CMemoryStateFile(STATE_REGS, m_nReg, sizeof(uint64) * 0x80));
archive.InsertFile(new CMemoryStateFile(STATE_TRXCTX, &m_TrxCtx, sizeof(TRXCONTEXT)));
{
CRegisterStateFile* registerFile = new CRegisterStateFile(STATE_PRIVREGS);
registerFile->SetRegister64(STATE_PRIVREGS_PMODE, m_nPMODE);
registerFile->SetRegister64(STATE_PRIVREGS_DISPFB1, m_nDISPFB1);
registerFile->SetRegister64(STATE_PRIVREGS_DISPLAY1, m_nDISPLAY1);
registerFile->SetRegister64(STATE_PRIVREGS_DISPFB2, m_nDISPFB2);
registerFile->SetRegister64(STATE_PRIVREGS_DISPLAY2, m_nDISPLAY2);
registerFile->SetRegister64(STATE_PRIVREGS_CSR, m_nCSR);
registerFile->SetRegister64(STATE_PRIVREGS_IMR, m_nIMR);
registerFile->SetRegister32(STATE_PRIVREGS_CRTINTERLACED, m_nCrtIsInterlaced);
registerFile->SetRegister32(STATE_PRIVREGS_CRTMODE, m_nCrtMode);
registerFile->SetRegister32(STATE_PRIVREGS_CRTFRAMEMODE, m_nCrtIsFrameMode);
archive.InsertFile(registerFile);
}
}
void CGSHandler::LoadState(CZipArchiveReader& archive)
{
archive.BeginReadFile(STATE_RAM )->Read(m_pRAM, RAMSIZE);
archive.BeginReadFile(STATE_REGS )->Read(m_nReg, sizeof(uint64) * 0x80);
archive.BeginReadFile(STATE_TRXCTX )->Read(&m_TrxCtx, sizeof(TRXCONTEXT));
{
CRegisterStateFile registerFile(*archive.BeginReadFile(STATE_PRIVREGS));
m_nPMODE = registerFile.GetRegister64(STATE_PRIVREGS_PMODE);
m_nDISPFB1 = registerFile.GetRegister64(STATE_PRIVREGS_DISPFB1);
m_nDISPLAY1 = registerFile.GetRegister64(STATE_PRIVREGS_DISPLAY1);
m_nDISPFB2 = registerFile.GetRegister64(STATE_PRIVREGS_DISPFB2);
m_nDISPLAY2 = registerFile.GetRegister64(STATE_PRIVREGS_DISPLAY2);
m_nCSR = registerFile.GetRegister64(STATE_PRIVREGS_CSR);
m_nIMR = registerFile.GetRegister64(STATE_PRIVREGS_IMR);
m_nCrtIsInterlaced = registerFile.GetRegister32(STATE_PRIVREGS_CRTINTERLACED) != 0;
m_nCrtMode = registerFile.GetRegister32(STATE_PRIVREGS_CRTMODE);
m_nCrtIsFrameMode = registerFile.GetRegister32(STATE_PRIVREGS_CRTFRAMEMODE) != 0;
}
UpdateViewport();
}
void CGSHandler::SetVBlank()
{
m_nCSR |= 0x08;
// CINTC::AssertLine(CINTC::INTC_LINE_VBLANK_START);
}
void CGSHandler::ResetVBlank()
{
m_nCSR &= ~0x08;
//Alternate current field
m_nCSR ^= 0x2000;
// CINTC::AssertLine(CINTC::INTC_LINE_VBLANK_END);
}
uint32 CGSHandler::ReadPrivRegister(uint32 nAddress)
{
uint32 nData;
switch(nAddress >> 4)
{
case 0x1200100:
//Force CSR to have the H-Blank bit set.
m_nCSR |= 0x04;
R_REG(nAddress, nData, m_nCSR);
break;
default:
CLog::GetInstance().Print(LOG_NAME, "Read an unhandled priviledged register (0x%0.8X).\r\n", nAddress);
nData = 0xCCCCCCCC;
break;
}
return nData;
}
void CGSHandler::WritePrivRegister(uint32 nAddress, uint32 nData)
{
switch(nAddress >> 4)
{
case 0x1200000:
W_REG(nAddress, nData, m_nPMODE);
if(!(nAddress & 0x4))
{
if((m_nPMODE & 0x01) && (m_nPMODE & 0x02))
{
CLog::GetInstance().Print(LOG_NAME, "Warning. Both read circuits were enabled. Using RC1 for display.\r\n");
m_nPMODE &= ~0x02;
}
}
break;
case 0x1200007:
W_REG(nAddress, nData, m_nDISPFB1);
if(nAddress & 0x04)
{
#ifdef _DEBUG
DISPFB* dispfb;
dispfb = GetDispFb(0);
CLog::GetInstance().Print(LOG_NAME, "DISPFB1(FBP: 0x%0.8X, FBW: %i, PSM: %i, DBX: %i, DBY: %i);\r\n", \
dispfb->GetBufPtr(), \
dispfb->GetBufWidth(), \
dispfb->nPSM, \
dispfb->nX, \
dispfb->nY);
#endif
}
break;
case 0x1200008:
W_REG(nAddress, nData, m_nDISPLAY1);
if(nAddress & 0x04)
{
UpdateViewport();
}
break;
case 0x1200009:
W_REG(nAddress, nData, m_nDISPFB2);
if(nAddress & 0x04)
{
#ifdef _DEBUG
DISPFB* dispfb;
dispfb = GetDispFb(1);
CLog::GetInstance().Print(LOG_NAME, "DISPFB2(FBP: 0x%0.8X, FBW: %i, PSM: %i, DBX: %i, DBY: %i);\r\n", \
dispfb->GetBufPtr(), \
dispfb->GetBufWidth(), \
dispfb->nPSM, \
dispfb->nX, \
dispfb->nY);
#endif
Flip();
OnNewFrame();
}
break;
case 0x120000A:
W_REG(nAddress, nData, m_nDISPLAY2);
if(nAddress & 0x04)
{
UpdateViewport();
}
break;
case 0x1200100:
W_REG(nAddress, nData, m_nCSR);
if(!(nAddress & 0x04))
{
SetVBlank();
Flip();
OnNewFrame();
if(nData & 0x08)
{
ResetVBlank();
}
}
break;
case 0x1200101:
W_REG(nAddress, nData, m_nIMR);
break;
default:
CLog::GetInstance().Print(LOG_NAME, "Wrote to an unhandled priviledged register (0x%0.8X, 0x%0.8X).\r\n", nAddress, nData);
break;
}
}
void CGSHandler::Initialize()
{
m_mailBox.SendCall(bind(&CGSHandler::InitializeImpl, this));
}
void CGSHandler::Flip()
{
if(!m_enabled) return;
m_mailBox.SendCall(bind(&CGSHandler::FlipImpl, this));
}
void CGSHandler::WriteRegister(uint8 registerId, uint64 value)
{
m_mailBox.SendCall(bind(&CGSHandler::WriteRegisterImpl, this, registerId, value));
}
void CGSHandler::FeedImageData(void* data, uint32 length)
{
uint8* buffer = new uint8[length];
memcpy(buffer, data, length);
m_mailBox.SendCall(bind(&CGSHandler::FeedImageDataImpl, this, buffer, length));
}
void CGSHandler::WriteRegisterMassively(const RegisterWrite* writeList, unsigned int count)
{
m_mailBox.SendCall(bind(&CGSHandler::WriteRegisterMassivelyImpl, this, writeList, count));
}
void CGSHandler::UpdateViewport()
{
m_mailBox.SendCall(bind(&CGSHandler::UpdateViewportImpl, this));
}
void CGSHandler::WriteRegisterImpl(uint8 nRegister, uint64 nData)
{
m_nReg[nRegister] = nData;
switch(nRegister)
{
case GS_REG_TRXDIR:
BITBLTBUF* pBuf;
TRXREG* pReg;
unsigned int nPixelSize;
pBuf = GetBitBltBuf();
pReg = GetTrxReg();
//We need to figure out the pixel size of the source stream
switch(pBuf->nDstPsm)
{
case PSMCT32:
nPixelSize = 32;
break;
case PSMCT24:
nPixelSize = 24;
break;
case PSMCT16:
nPixelSize = 16;
break;
case PSMT8:
case PSMT8H:
nPixelSize = 8;
break;
case PSMT4:
case PSMT4HH:
case PSMT4HL:
nPixelSize = 4;
break;
default:
assert(0);
break;
}
m_TrxCtx.nSize = (pReg->nRRW * pReg->nRRH * nPixelSize) / 8;
m_TrxCtx.nRRX = 0;
m_TrxCtx.nRRY = 0;
m_TrxCtx.nDirty = false;
break;
}
#ifdef _DEBUG
//DisassembleWrite(nRegister, nData);
#endif
}
void CGSHandler::FeedImageDataImpl(void* pData, uint32 nLength)
{
scoped_array<uint8> dataPtr(reinterpret_cast<uint8*>(pData));
if(m_TrxCtx.nSize == 0)
{
#ifdef _DEBUG
CLog::GetInstance().Print(LOG_NAME, "Warning. Received image data when no transfer was expected.\r\n");
#endif
return;
}
if(m_TrxCtx.nSize < nLength)
{
nLength = m_TrxCtx.nSize;
//assert(0);
//return;
}
BITBLTBUF* pBuf(GetBitBltBuf());
if(pBuf->nDstPsm == 1) return;
m_TrxCtx.nDirty |= ((this)->*(m_pTransferHandler[pBuf->nDstPsm]))(pData, nLength);
m_TrxCtx.nSize -= nLength;
if(m_TrxCtx.nSize == 0)
{
if(m_TrxCtx.nDirty)
{
BITBLTBUF* pBuf;
TRXREG* pReg;
uint32 nSize;
pBuf = GetBitBltBuf();
pReg = GetTrxReg();
nSize = (pBuf->GetDstWidth() * pReg->nRRH * GetPsmPixelSize(pBuf->nDstPsm)) / 8;
ProcessImageTransfer(pBuf->GetDstPtr(), nSize);
}
}
}
void CGSHandler::WriteRegisterMassivelyImpl(const RegisterWrite* writeList, unsigned int count)
{
const RegisterWrite* writeIterator = writeList;
for(unsigned int i = 0; i < count; i++)
{
WriteRegisterImpl(writeIterator->first, writeIterator->second);
writeIterator++;
}
delete [] writeList;
}
void CGSHandler::FetchImagePSMCT16(uint16* pDst, uint32 nBufPos, uint32 nBufWidth, uint32 nWidth, uint32 nHeight)
{
CPixelIndexorPSMCT16 Indexor(m_pRAM, nBufPos, nBufWidth);
for(unsigned int j = 0; j < nHeight; j++)
{
for(unsigned int i = 0; i < nWidth; i++)
{
pDst[i] = Indexor.GetPixel(i, j);
}
pDst += (nWidth);
}
}
void CGSHandler::FetchImagePSMCT16S(uint16* pDst, uint32 nBufPos, uint32 nBufWidth, uint32 nWidth, uint32 nHeight)
{
CPixelIndexorPSMCT16S Indexor(m_pRAM, nBufPos, nBufWidth);
for(unsigned int j = 0; j < nHeight; j++)
{
for(unsigned int i = 0; i < nWidth; i++)
{
pDst[i] = Indexor.GetPixel(i, j);
}
pDst += (nWidth);
}
}
void CGSHandler::FetchImagePSMCT32(uint32* pDst, uint32 nBufPos, uint32 nBufWidth, uint32 nWidth, uint32 nHeight)
{
CPixelIndexorPSMCT32 Indexor(m_pRAM, nBufPos, nBufWidth);
for(unsigned int j = 0; j < nHeight; j++)
{
for(unsigned int i = 0; i < nWidth; i++)
{
pDst[i] = Indexor.GetPixel(i, j);
}
pDst += (nWidth);
}
}
bool CGSHandler::TrxHandlerInvalid(void* pData, uint32 nLength)
{
assert(0);
return false;
}
template <typename Storage>
bool CGSHandler::TrxHandlerCopy(void* pData, uint32 nLength)
{
typename Storage::Unit* pSrc;
uint32 nX, nY;
TRXPOS* pTrxPos;
TRXREG* pTrxReg;
BITBLTBUF* pTrxBuf;
bool nDirty = false;
nLength /= sizeof(typename Storage::Unit);
pTrxPos = GetTrxPos();
pTrxReg = GetTrxReg();
pTrxBuf = GetBitBltBuf();
CPixelIndexor<Storage> Indexor(m_pRAM, pTrxBuf->GetDstPtr(), pTrxBuf->nDstWidth);
pSrc = (typename Storage::Unit*)pData;
for(unsigned int i = 0; i < nLength; i++)
{
typename Storage::Unit* pPixel;
nX = (m_TrxCtx.nRRX + pTrxPos->nDSAX) % 2048;
nY = (m_TrxCtx.nRRY + pTrxPos->nDSAY) % 2048;
pPixel = Indexor.GetPixelAddress(nX, nY);
if((*pPixel) != pSrc[i])
{
(*pPixel) = pSrc[i];
nDirty = true;
}
m_TrxCtx.nRRX++;
if(m_TrxCtx.nRRX == pTrxReg->nRRW)
{
m_TrxCtx.nRRX = 0;
m_TrxCtx.nRRY++;
}
}
return nDirty;
}
bool CGSHandler::TrxHandlerPSMCT24(void* pData, uint32 nLength)
{
uint8* pSrc;
uint32* pDstPixel;
uint32 nSrcPixel;
uint32 nX, nY;
TRXPOS* pTrxPos;
TRXREG* pTrxReg;
BITBLTBUF* pTrxBuf;
pTrxPos = GetTrxPos();
pTrxReg = GetTrxReg();
pTrxBuf = GetBitBltBuf();
CPixelIndexorPSMCT32 Indexor(m_pRAM, pTrxBuf->GetDstPtr(), pTrxBuf->nDstWidth);
pSrc = (uint8*)pData;
for(unsigned int i = 0; i < nLength; i += 3)
{
nX = (m_TrxCtx.nRRX + pTrxPos->nDSAX) % 2048;
nY = (m_TrxCtx.nRRY + pTrxPos->nDSAY) % 2048;
pDstPixel = Indexor.GetPixelAddress(nX, nY);
nSrcPixel = (*(uint32*)&pSrc[i]) & 0x00FFFFFF;
(*pDstPixel) &= 0xFF000000;
(*pDstPixel) |= nSrcPixel;
m_TrxCtx.nRRX++;
if(m_TrxCtx.nRRX == pTrxReg->nRRW)
{
m_TrxCtx.nRRX = 0;
m_TrxCtx.nRRY++;
}
}
return true;
}
bool CGSHandler::TrxHandlerPSMT4(void* pData, uint32 nLength)
{
//Gotta rewrite this
TRXPOS* pTrxPos = GetTrxPos();
TRXREG* pTrxReg = GetTrxReg();
BITBLTBUF* pTrxBuf = GetBitBltBuf();
CPixelIndexorPSMT4 Indexor(m_pRAM, pTrxBuf->GetDstPtr(), pTrxBuf->nDstWidth);
// assert(0);
uint8* pSrc = (uint8*)pData;
for(unsigned int i = 0; i < nLength; i++)
{
uint8 nPixel[2];
nPixel[0] = (pSrc[i] >> 0) & 0x0F;
nPixel[1] = (pSrc[i] >> 4) & 0x0F;
for(unsigned int j = 0; j < 2; j++)
{
uint32 nX = (m_TrxCtx.nRRX + pTrxPos->nDSAX) % 2048;
uint32 nY = (m_TrxCtx.nRRY + pTrxPos->nDSAY) % 2048;
Indexor.SetPixel(nX, nY, nPixel[j]);
m_TrxCtx.nRRX++;
if(m_TrxCtx.nRRX == pTrxReg->nRRW)
{
m_TrxCtx.nRRX = 0;
m_TrxCtx.nRRY++;
}
}
}
return true;
}
template <uint32 nShift, uint32 nMask>
bool CGSHandler::TrxHandlerPSMT4H(void* pData, uint32 nLength)
{
uint8* pSrc;
uint8 nSrcPixel;
uint32 nX, nY;
uint32* pDstPixel;
TRXPOS* pTrxPos;
TRXREG* pTrxReg;
BITBLTBUF* pTrxBuf;
pTrxPos = GetTrxPos();
pTrxReg = GetTrxReg();
pTrxBuf = GetBitBltBuf();
CPixelIndexorPSMCT32 Indexor(m_pRAM, pTrxBuf->GetDstPtr(), pTrxBuf->nDstWidth);
pSrc = (uint8*)pData;
for(unsigned int i = 0; i < nLength; i++)
{
//Pixel 1
nX = (m_TrxCtx.nRRX + pTrxPos->nDSAX) % 2048;
nY = (m_TrxCtx.nRRY + pTrxPos->nDSAY) % 2048;
nSrcPixel = pSrc[i] & 0x0F;
pDstPixel = Indexor.GetPixelAddress(nX, nY);
(*pDstPixel) &= ~nMask;
(*pDstPixel) |= (nSrcPixel << nShift);
m_TrxCtx.nRRX++;
if(m_TrxCtx.nRRX == pTrxReg->nRRW)
{
m_TrxCtx.nRRX = 0;
m_TrxCtx.nRRY++;
}
//Pixel 2
nX = (m_TrxCtx.nRRX + pTrxPos->nDSAX) % 2048;
nY = (m_TrxCtx.nRRY + pTrxPos->nDSAY) % 2048;
nSrcPixel = (pSrc[i] & 0xF0);
pDstPixel = Indexor.GetPixelAddress(nX, nY);
(*pDstPixel) &= ~nMask;
(*pDstPixel) |= (nSrcPixel << (nShift - 4));
m_TrxCtx.nRRX++;
if(m_TrxCtx.nRRX == pTrxReg->nRRW)
{
m_TrxCtx.nRRX = 0;
m_TrxCtx.nRRY++;
}
}
return true;
}
bool CGSHandler::TrxHandlerPSMT8H(void* pData, uint32 nLength)
{
uint8* pSrc;
uint8 nSrcPixel;
uint32 nX, nY;
uint32* pDstPixel;
TRXPOS* pTrxPos;
TRXREG* pTrxReg;
BITBLTBUF* pTrxBuf;
pTrxPos = GetTrxPos();
pTrxReg = GetTrxReg();
pTrxBuf = GetBitBltBuf();
CPixelIndexorPSMCT32 Indexor(m_pRAM, pTrxBuf->GetDstPtr(), pTrxBuf->nDstWidth);
pSrc = (uint8*)pData;
for(unsigned int i = 0; i < nLength; i++)
{
nX = (m_TrxCtx.nRRX + pTrxPos->nDSAX) % 2048;
nY = (m_TrxCtx.nRRY + pTrxPos->nDSAY) % 2048;
nSrcPixel = pSrc[i];
pDstPixel = Indexor.GetPixelAddress(nX, nY);
(*pDstPixel) &= ~0xFF000000;
(*pDstPixel) |= (nSrcPixel << 24);
m_TrxCtx.nRRX++;
if(m_TrxCtx.nRRX == pTrxReg->nRRW)
{
m_TrxCtx.nRRX = 0;
m_TrxCtx.nRRY++;
}
}
return true;
}
void CGSHandler::SetCrt(bool nIsInterlaced, unsigned int nMode, bool nIsFrameMode)
{
m_nCrtMode = nMode;
m_nCrtIsInterlaced = nIsInterlaced;
m_nCrtIsFrameMode = nIsFrameMode;
UpdateViewport();
}
CGSHandler::DISPFB* CGSHandler::GetDispFb(unsigned int nUnit)
{
switch(nUnit)
{
case 0:
return (DISPFB*)&m_nDISPFB1;
break;
case 1:
return (DISPFB*)&m_nDISPFB2;
break;
default:
assert(0);
return NULL;
break;
}
}
CGSHandler::TEXCLUT* CGSHandler::GetTexClut()
{
return (TEXCLUT*)&m_nReg[GS_REG_TEXCLUT];
}
CGSHandler::FOGCOL* CGSHandler::GetFogCol()
{
return (FOGCOL*)&m_nReg[GS_REG_FOGCOL];
}
CGSHandler::FRAME* CGSHandler::GetFrame(unsigned int nUnit)
{
assert(nUnit < 2);
return (FRAME*)&m_nReg[GS_REG_FRAME_1 + nUnit];
}
CGSHandler::TRXREG* CGSHandler::GetTrxReg()
{
return (TRXREG*)&m_nReg[GS_REG_TRXREG];
}
CGSHandler::TRXPOS* CGSHandler::GetTrxPos()
{
return (TRXPOS*)&m_nReg[GS_REG_TRXPOS];
}
CGSHandler::BITBLTBUF* CGSHandler::GetBitBltBuf()
{
return (BITBLTBUF*)&m_nReg[GS_REG_BITBLTBUF];
}
unsigned int CGSHandler::GetCrtWidth()
{
switch(m_nCrtMode)
{
case 0x02:
case 0x03:
case 0x1C:
return 640;
break;
default:
assert(0);
return 640;
break;
}
}
unsigned int CGSHandler::GetCrtHeight()
{
switch(m_nCrtMode)
{
case 0x02:
return 448;
break;
case 0x03:
return 512;
break;
case 0x1C:
return 480;
break;
default:
assert(0);
return 448;
break;
}
}
bool CGSHandler::GetCrtIsInterlaced()
{
return m_nCrtIsInterlaced;
}
bool CGSHandler::GetCrtIsFrameMode()
{
return m_nCrtIsFrameMode;
}
unsigned int CGSHandler::GetPsmPixelSize(unsigned int nPSM)
{
switch(nPSM)
{
case PSMCT32:
case PSMT4HH:
case PSMT4HL:
case PSMT8H:
return 32;
break;
case PSMCT24:
return 24;
break;
case PSMCT16:
case PSMCT16S:
return 16;
break;
case PSMT8:
return 8;
break;
case PSMT4:
return 4;
break;
default:
assert(0);
return 0;
break;
}
}
void CGSHandler::DisassembleWrite(uint8 nRegister, uint64 nData)
{
GSPRIM pr;
double nX, nY, nZ;
double nU, nV;
double nS, nT;
//Filtering
//if(!((nRegister == GS_REG_FRAME_1) || (nRegister == GS_REG_FRAME_2))) return;
//if(!((nRegister == GS_REG_TEST_1) || (nRegister == GS_REG_TEST_2))) return;
switch(nRegister)
{
case GS_REG_PRIM:
DECODE_PRIM(nData, pr);
CLog::GetInstance().Print(LOG_NAME, "PRIM(PRI: %i, IIP: %i, TME: %i, FGE: %i, ABE: %i, AA1: %i, FST: %i, CTXT: %i, FIX: %i);\r\n", \
pr.nType, \
pr.nShading, \
pr.nTexture, \
pr.nFog, \
pr.nAlpha, \
pr.nAntiAliasing, \
pr.nUseUV, \
pr.nContext, \
pr.nUseFloat);
break;
case GS_REG_RGBAQ:
GSRGBAQ rgbaq;
DECODE_RGBAQ(nData, rgbaq);
CLog::GetInstance().Print(LOG_NAME, "RGBAQ(R: 0x%0.2X, G: 0x%0.2X, B: 0x%0.2X, A: 0x%0.2X, Q: %f);\r\n", \
rgbaq.nR,
rgbaq.nG,
rgbaq.nB,
rgbaq.nA,
rgbaq.nQ);
break;
case GS_REG_ST:
DECODE_ST(nData, nS, nT);
CLog::GetInstance().Print(LOG_NAME, "ST(S: %f, T: %f);\r\n", \
nS, \
nT);
break;
case GS_REG_UV:
DECODE_UV(nData, nU, nV);
CLog::GetInstance().Print(LOG_NAME, "UV(U: %f, V: %f);\r\n", \
nU, \
nV);
break;
case GS_REG_XYZ2:
DECODE_XYZ2(nData, nX, nY, nZ);
CLog::GetInstance().Print(LOG_NAME, "XYZ2(%f, %f, %f);\r\n", \
nX, \
nY, \
nZ);
break;
case GS_REG_XYZF2:
case GS_REG_XYZF3:
{
XYZF xyzf;
xyzf = *reinterpret_cast<XYZF*>(&nData);
CLog::GetInstance().Print(LOG_NAME, "%s(%f, %f, %i, %i);\r\n", \
(nRegister == GS_REG_XYZF2) ? "XYZF2" : "XYZF3",
xyzf.GetX(),
xyzf.GetY(),
xyzf.nZ,
xyzf.nF);
}
break;
case GS_REG_XYZ3:
DECODE_XYZ2(nData, nX, nY, nZ);
CLog::GetInstance().Print(LOG_NAME, "XYZ3(%f, %f, %f);\r\n", \
nX, \
nY, \
nZ);
break;
case GS_REG_TEX0_1:
case GS_REG_TEX0_2:
{
GSTEX0 tex;
DECODE_TEX0(nData, tex);
CLog::GetInstance().Print(LOG_NAME, "TEX0_%i(TBP: 0x%0.8X, TBW: %i, PSM: %i, TW: %i, TH: %i, TCC: %i, TFX: %i, CBP: 0x%0.8X, CPSM: %i, CSM: %i, CSA: %i, CLD: %i);\r\n", \
nRegister == GS_REG_TEX0_1 ? 1 : 2, \
tex.GetBufPtr(), \
tex.GetBufWidth(), \
tex.nPsm, \
tex.GetWidth(), \
tex.GetHeight(), \
tex.nColorComp, \
tex.nFunction, \
tex.GetCLUTPtr(), \
tex.nCPSM, \
tex.nCSM, \
tex.nCSA, \
tex.nCLD);
}
break;
case GS_REG_CLAMP_1:
case GS_REG_CLAMP_2:
{
CLAMP clamp;
clamp = *(CLAMP*)&nData;
CLog::GetInstance().Print(LOG_NAME, "CLAMP_%i(WMS: %i, WMT: %i, MINU: %i, MAXU: %i, MINV: %i, MAXV: %i);\r\n", \
nRegister == GS_REG_CLAMP_1 ? 1 : 2, \
clamp.nWMS, \
clamp.nWMT, \
clamp.GetMinU(), \
clamp.GetMaxU(), \
clamp.GetMinV(), \
clamp.GetMaxV());
}
break;
case GS_REG_TEX1_1:
case GS_REG_TEX1_2:
{
GSTEX1 tex1;
DECODE_TEX1(nData, tex1);
CLog::GetInstance().Print(LOG_NAME, "TEX1_%i(LCM: %i, MXL: %i, MMAG: %i, MMIN: %i, MTBA: %i, L: %i, K: %i);\r\n", \
nRegister == GS_REG_TEX1_1 ? 1 : 2, \
tex1.nLODMethod, \
tex1.nMaxMip, \
tex1.nMagFilter, \
tex1.nMinFilter, \
tex1.nMipBaseAddr, \
tex1.nLODL, \
tex1.nLODK);
}
break;
case GS_REG_TEX2_1:
case GS_REG_TEX2_2:
TEX2 tex2;
tex2 = *(TEX2*)&nData;
CLog::GetInstance().Print(LOG_NAME, "TEX2_%i(PSM: %i, CBP: 0x%0.8X, CPSM: %i, CSM: %i, CSA: %i, CLD: %i);\r\n", \
nRegister == GS_REG_TEX2_1 ? 1 : 2, \
tex2.nPsm, \
tex2.GetCLUTPtr(), \
tex2.nCPSM, \
tex2.nCSM, \
tex2.nCSA, \
tex2.nCLD);
break;
case GS_REG_XYOFFSET_1:
case GS_REG_XYOFFSET_2:
CLog::GetInstance().Print(LOG_NAME, "XYOFFSET_%i(%i, %i);\r\n", \
nRegister == GS_REG_XYOFFSET_1 ? 1 : 2, \
(uint32)((nData >> 0) & 0xFFFFFFFF), \
(uint32)((nData >> 32) & 0xFFFFFFFF));
break;
case GS_REG_PRMODECONT:
CLog::GetInstance().Print(LOG_NAME, "PRMODECONT(AC = %i);\r\n", \
nData & 1);
break;
case GS_REG_PRMODE:
GSPRMODE prm;
DECODE_PRMODE(nData, prm);
CLog::GetInstance().Print(LOG_NAME, "PRMODE(IIP: %i, TME: %i, FGE: %i, ABE: %i, AA1: %i, FST: %i, CTXT: %i, FIX: %i);\r\n", \
prm.nShading, \
prm.nTexture, \
prm.nFog, \
prm.nAlpha, \
prm.nAntiAliasing, \
prm.nUseUV, \
prm.nContext, \
prm.nUseFloat);
break;
case GS_REG_TEXCLUT:
TEXCLUT clut;
clut = *(TEXCLUT*)&nData;
CLog::GetInstance().Print(LOG_NAME, "TEXCLUT(CBW: %i, COU: %i, COV: %i);\r\n", \
clut.nCBW,
clut.nCOU,
clut.nCOV);
break;
case GS_REG_FOGCOL:
FOGCOL fogcol;
fogcol = *(FOGCOL*)&nData;
CLog::GetInstance().Print(LOG_NAME, "FOGCOL(R: 0x%0.2X, G: 0x%0.2X, B: 0x%0.2X);\r\n", \
fogcol.nFCR,
fogcol.nFCG,
fogcol.nFCB);
break;
case GS_REG_TEXA:
GSTEXA TexA;
DECODE_TEXA(nData, TexA);
CLog::GetInstance().Print(LOG_NAME, "TEXA(TA0: 0x%0.2X, AEM: %i, TA1: 0x%0.2X);\r\n", \
TexA.nTA0,
TexA.nAEM,
TexA.nTA1);
break;
case GS_REG_TEXFLUSH:
CLog::GetInstance().Print(LOG_NAME, "TEXFLUSH();\r\n");
break;
case GS_REG_ALPHA_1:
case GS_REG_ALPHA_2:
GSALPHA alpha;
DECODE_ALPHA(nData, alpha);
CLog::GetInstance().Print(LOG_NAME, "ALPHA_%i(A: %i, B: %i, C: %i, D: %i, FIX: 0x%0.2X);\r\n", \
nRegister == GS_REG_ALPHA_1 ? 1 : 2, \
alpha.nA, \
alpha.nB, \
alpha.nC, \
alpha.nD, \
alpha.nFix);
break;
case GS_REG_SCISSOR_1:
CLog::GetInstance().Print(LOG_NAME, "SCISSOR_1(%i, %i, %i, %i);\r\n", \
(uint32)((nData >> 0) & 0xFFFF), \
(uint32)((nData >> 16) & 0xFFFF), \
(uint32)((nData >> 32) & 0xFFFF), \
(uint32)((nData >> 48) & 0xFFFF));
break;
case GS_REG_TEST_1:
case GS_REG_TEST_2:
TEST tst;
tst <<= nData;
CLog::GetInstance().Print(LOG_NAME, "TEST_%i(ATE: %i, ATST: %i, AREF: 0x%0.2X, AFAIL: %i, DATE: %i, DATM: %i, ZTE: %i, ZTST: %i);\r\n", \
nRegister == GS_REG_TEST_1 ? 1 : 2, \
tst.nAlphaEnabled, \
tst.nAlphaMethod, \
tst.nAlphaRef, \
tst.nAlphaFail, \
tst.nDestAlphaEnabled, \
tst.nDestAlphaMode, \
tst.nDepthEnabled, \
tst.nDepthMethod);
break;
case GS_REG_FRAME_1:
case GS_REG_FRAME_2:
FRAME fr;
fr = *(FRAME*)&nData;
CLog::GetInstance().Print(LOG_NAME, "FRAME_%i(FBP: 0x%0.8X, FBW: %i, PSM: %i, FBMSK: %i);\r\n", \
nRegister == GS_REG_FRAME_1 ? 1 : 2, \
fr.GetBasePtr(), \
fr.GetWidth(), \
fr.nPsm, \
fr.nMask);
break;
case GS_REG_ZBUF_1:
case GS_REG_ZBUF_2:
ZBUF zbuf;
zbuf = *(ZBUF*)&nData;
CLog::GetInstance().Print(LOG_NAME, "ZBUF_%i(ZBP: 0x%0.8X, PSM: %i, ZMSK: %i);\r\n", \
nRegister == GS_REG_ZBUF_1 ? 1 : 2, \
zbuf.GetBasePtr(), \
zbuf.nPsm, \
zbuf.nMask);
break;
case GS_REG_BITBLTBUF:
BITBLTBUF buf;
buf = *(BITBLTBUF*)&nData;
CLog::GetInstance().Print(LOG_NAME, "BITBLTBUF(0x%0.8X, %i, %i, 0x%0.8X, %i, %i);\r\n", \
buf.GetSrcPtr(), \
buf.GetSrcWidth(), \
buf.nSrcPsm, \
buf.GetDstPtr(), \
buf.GetDstWidth(), \
buf.nDstPsm);
break;
case GS_REG_TRXPOS:
CLog::GetInstance().Print(LOG_NAME, "TRXPOS(%i, %i, %i, %i, %i);\r\n", \
(uint32)((nData >> 0) & 0xFFFF), \
(uint32)((nData >> 16) & 0xFFFF), \
(uint32)((nData >> 32) & 0xFFFF), \
(uint32)((nData >> 48) & 0xFF), \
(uint32)((nData >> 59) & 0x1));
break;
case GS_REG_TRXREG:
CLog::GetInstance().Print(LOG_NAME, "TRXREG(%i, %i);\r\n", \
(uint32)((nData >> 0) & 0xFFFFFFFF),
(uint32)((nData >> 32) & 0xFFFFFFFF));
break;
case GS_REG_TRXDIR:
CLog::GetInstance().Print(LOG_NAME, "TRXDIR(%i);\r\n", \
(uint32)((nData >> 0) & 0xFFFFFFFF));
break;
default:
CLog::GetInstance().Print(LOG_NAME, "Unknown command (0x%X).\r\n", nRegister);
break;
}
}
void CGSHandler::ThreadProc()
{
while(1)
{
m_mailBox.WaitForCall();
while(m_mailBox.IsPending())
{
m_mailBox.ReceiveCall();
}
}
}