Play-/Source/gs/GsTransferRange.h
Jean-Philip Desjardins 139d0d1ee7 Cleanup.
2024-02-27 15:46:05 -05:00

115 lines
3.4 KiB
C++

#pragma once
#include "maybe_unused.h"
#include "GSHandler.h"
namespace GsTransfer
{
struct TransferRangeSrc
{
static uint32 GetBufferAddress(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.GetSrcPtr();
}
static uint32 GetBufferWidth(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.GetSrcWidth();
}
static uint32 GetBufferPsm(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.nSrcPsm;
}
static uint32 GetSAX(const CGSHandler::TRXPOS& trxPos)
{
return trxPos.nSSAX;
}
static uint32 GetSAY(const CGSHandler::TRXPOS& trxPos)
{
return trxPos.nSSAY;
}
};
struct TransferRangeDst
{
static uint32 GetBufferAddress(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.GetDstPtr();
}
static uint32 GetBufferWidth(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.GetDstWidth();
}
static uint32 GetBufferPsm(const CGSHandler::BITBLTBUF& bltBuf)
{
return bltBuf.nDstPsm;
}
static uint32 GetSAX(const CGSHandler::TRXPOS& trxPos)
{
return trxPos.nDSAX;
}
static uint32 GetSAY(const CGSHandler::TRXPOS& trxPos)
{
return trxPos.nDSAY;
}
};
template <typename TransferRangeTraits>
static std::pair<uint32, uint32> GetRange(const CGSHandler::BITBLTBUF& bltBuf, const CGSHandler::TRXREG& trxReg, const CGSHandler::TRXPOS& trxPos)
{
uint32 transferAddress = TransferRangeTraits::GetBufferAddress(bltBuf);
uint32 psm = TransferRangeTraits::GetBufferPsm(bltBuf);
//Find the pages that are touched by this transfer
auto transferPageSize = CGsPixelFormats::GetPsmPageSize(psm);
// DBZ Budokai Tenkaichi 2 and 3 use invalid (empty) buffer sizes
// Account for that, by assuming trxReg.nRRW.
auto width = TransferRangeTraits::GetBufferWidth(bltBuf);
if(width == 0)
{
width = trxReg.nRRW;
}
assert(trxReg.nRRW != 0);
assert(trxReg.nRRH != 0);
//Since there's a possibility of using RRW for the buffer width, we need to round up
uint32 pagePitch = (width + transferPageSize.first - 1) / transferPageSize.first;
uint32 sax = TransferRangeTraits::GetSAX(trxPos);
uint32 say = TransferRangeTraits::GetSAY(trxPos);
uint32 pageStartX = sax / transferPageSize.first;
uint32 pageStartY = say / transferPageSize.second;
uint32 pageEndX = (sax + trxReg.nRRW - 1) / transferPageSize.first;
uint32 pageEndY = (say + trxReg.nRRH - 1) / transferPageSize.second;
//Single page transfer
if((pageStartX == pageEndX) && (pageStartY == pageEndY))
{
uint32 transferPage = (pageStartY * pagePitch) + pageStartX;
uint32 transferOffset = transferPage * CGsPixelFormats::PAGESIZE;
return std::make_pair(transferAddress + transferOffset, CGsPixelFormats::PAGESIZE);
}
uint32 pageCountY = pageEndY - pageStartY + 1;
uint32 pageCount = pagePitch * pageCountY;
uint32 transferSize = pageCount * CGsPixelFormats::PAGESIZE;
uint32 transferOffset = ((pageStartY * pagePitch) + pageStartX) * CGsPixelFormats::PAGESIZE;
return std::make_pair(transferAddress + transferOffset, transferSize);
}
FRAMEWORK_MAYBE_UNUSED
static auto GetSrcRange(const CGSHandler::BITBLTBUF& bltBuf, const CGSHandler::TRXREG& trxReg, const CGSHandler::TRXPOS& trxPos)
{
return GetRange<TransferRangeSrc>(bltBuf, trxReg, trxPos);
}
FRAMEWORK_MAYBE_UNUSED
static auto GetDstRange(const CGSHandler::BITBLTBUF& bltBuf, const CGSHandler::TRXREG& trxReg, const CGSHandler::TRXPOS& trxPos)
{
return GetRange<TransferRangeDst>(bltBuf, trxReg, trxPos);
}
}