mirror of https://github.com/PCSX2/pcsx2.git
IPU: Adjust DMA timings, improve internal calling
[SAVEVERSION+]
This commit is contained in:
parent
2947e11b9b
commit
ae5cd7b3c3
|
@ -27,6 +27,7 @@
|
|||
alignas(16) tIPU_cmd ipu_cmd;
|
||||
alignas(16) tIPU_BP g_BP;
|
||||
alignas(16) decoder_t decoder;
|
||||
IPUStatus IPUCoreStatus;
|
||||
|
||||
static void (*IPUWorker)();
|
||||
|
||||
|
@ -92,15 +93,8 @@ void tIPU_cmd::clear()
|
|||
|
||||
__fi void IPUProcessInterrupt()
|
||||
{
|
||||
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
|
||||
if (ipuRegs.ctrl.BUSY)
|
||||
IPUWorker();
|
||||
|
||||
if (ipuRegs.ctrl.BUSY && !IPU1Status.DataRequested && !(cpuRegs.interrupt & 1 << IPU_PROCESS))
|
||||
{
|
||||
CPU_INT(IPU_PROCESS, ProcessedData ? ProcessedData : 64);
|
||||
}
|
||||
else
|
||||
ProcessedData = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
@ -112,6 +106,9 @@ void ipuReset()
|
|||
std::memset(&ipuRegs, 0, sizeof(ipuRegs));
|
||||
std::memset(&g_BP, 0, sizeof(g_BP));
|
||||
std::memset(&decoder, 0, sizeof(decoder));
|
||||
IPUCoreStatus.DataRequested = false;
|
||||
IPUCoreStatus.WaitingOnIPUFrom= false;
|
||||
IPUCoreStatus.WaitingOnIPUTo = false;
|
||||
|
||||
decoder.picture_structure = FRAME_PICTURE; //default: progressive...my guess:P
|
||||
|
||||
|
@ -149,6 +146,7 @@ bool SaveStateBase::ipuFreeze()
|
|||
Freeze(coded_block_pattern);
|
||||
Freeze(decoder);
|
||||
Freeze(ipu_cmd);
|
||||
Freeze(IPUCoreStatus);
|
||||
|
||||
return IsOkay();
|
||||
}
|
||||
|
@ -471,7 +469,6 @@ __fi void IPUCMD_WRITE(u32 val)
|
|||
{
|
||||
// don't process anything if currently busy
|
||||
//if (ipuRegs.ctrl.BUSY) Console.WriteLn("IPU BUSY!"); // wait for thread
|
||||
ProcessedData = 0;
|
||||
ipuRegs.ctrl.ECD = 0;
|
||||
ipuRegs.ctrl.SCD = 0;
|
||||
ipu_cmd.clear();
|
||||
|
@ -538,9 +535,10 @@ __fi void IPUCMD_WRITE(u32 val)
|
|||
|
||||
// Have a short delay immitating the time it takes to run IDEC/BDEC, other commands are near instant.
|
||||
// Mana Khemia/Metal Saga start IDEC then change IPU0 expecting there to be a delay before IDEC sends data.
|
||||
if (!CommandExecuteQueued && (ipu_cmd.CMD == SCE_IPU_IDEC || ipu_cmd.CMD == SCE_IPU_BDEC))
|
||||
if (ipu_cmd.CMD == SCE_IPU_IDEC || ipu_cmd.CMD == SCE_IPU_BDEC)
|
||||
{
|
||||
CommandExecuteQueued = true;
|
||||
IPUCoreStatus.WaitingOnIPUFrom = false;
|
||||
IPUCoreStatus.WaitingOnIPUTo = false;
|
||||
CPU_INT(IPU_PROCESS, 64);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -132,7 +132,7 @@ struct alignas(16) tIPU_BP {
|
|||
// be possible -- so if the fill fails we'll only return 0 if we don't have enough
|
||||
// remaining bits in the FIFO to fill the request.
|
||||
// Used to do ((FP!=0) && (BP + bits) <= 128) if we get here there's defo not enough data now though
|
||||
|
||||
IPUCoreStatus.WaitingOnIPUTo = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -293,8 +293,6 @@ extern bool EnableFMV;
|
|||
|
||||
alignas(16) extern tIPU_cmd ipu_cmd;
|
||||
extern uint eecount_on_last_vdec;
|
||||
extern bool CommandExecuteQueued;
|
||||
extern u32 ProcessedData;
|
||||
|
||||
extern void ipuReset();
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ void IPU_Fifo_Input::clear()
|
|||
writepos = 0;
|
||||
|
||||
// Because the FIFO is drained it will request more data immediately
|
||||
IPU1Status.DataRequested = true;
|
||||
IPUCoreStatus.DataRequested = true;
|
||||
|
||||
if (ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999)
|
||||
{
|
||||
|
@ -91,9 +91,7 @@ int IPU_Fifo_Input::write(const u32* pMem, int size)
|
|||
g_BP.IFC += transfer_size;
|
||||
|
||||
if (g_BP.IFC == 8)
|
||||
IPU1Status.DataRequested = false;
|
||||
|
||||
CPU_INT(IPU_PROCESS, transfer_size * BIAS);
|
||||
IPUCoreStatus.DataRequested = false;
|
||||
|
||||
return transfer_size;
|
||||
}
|
||||
|
@ -104,7 +102,7 @@ int IPU_Fifo_Input::read(void *value)
|
|||
if (g_BP.IFC <= 1)
|
||||
{
|
||||
// IPU FIFO is empty and DMA is waiting so lets tell the DMA we are ready to put data in the FIFO
|
||||
IPU1Status.DataRequested = true;
|
||||
IPUCoreStatus.DataRequested = true;
|
||||
|
||||
if(ipu1ch.chcr.STR && cpuRegs.eCycle[4] == 0x9999)
|
||||
{
|
||||
|
@ -142,7 +140,7 @@ int IPU_Fifo_Output::write(const u32 *value, uint size)
|
|||
ipuRegs.ctrl.OFC += transfer_size;
|
||||
|
||||
if(ipu0ch.chcr.STR)
|
||||
IPU_INT_FROM(ipuRegs.ctrl.OFC * BIAS);
|
||||
IPU_INT_FROM(1);
|
||||
|
||||
return transfer_size;
|
||||
}
|
||||
|
@ -181,12 +179,13 @@ void WriteFIFO_IPUin(const mem128_t* value)
|
|||
IPU_LOG( "WriteFIFO/IPUin <- 0x%08X.%08X.%08X.%08X", value->_u32[0], value->_u32[1], value->_u32[2], value->_u32[3]);
|
||||
|
||||
//committing every 16 bytes
|
||||
if( ipu_fifo.in.write(value->_u32, 1) == 0 )
|
||||
if( ipu_fifo.in.write(value->_u32, 1) > 0 )
|
||||
{
|
||||
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
|
||||
if (ipuRegs.ctrl.BUSY && IPUCoreStatus.WaitingOnIPUTo)
|
||||
{
|
||||
CommandExecuteQueued = false;
|
||||
CPU_INT(IPU_PROCESS, 8);
|
||||
IPUCoreStatus.WaitingOnIPUFrom = false;
|
||||
IPUCoreStatus.WaitingOnIPUTo = false;
|
||||
CPU_INT(IPU_PROCESS, 2 * BIAS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1010,6 +1010,7 @@ __ri static bool mpeg2sliceIDEC()
|
|||
// IPU0 isn't ready for data, so let's wait for it to be
|
||||
if ((!ipu0ch.chcr.STR || ipuRegs.ctrl.OFC || ipu0ch.qwc == 0) && ipu_cmd.pos[1] <= 2)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
return false;
|
||||
}
|
||||
macroblock_8& mb8 = decoder.mb8;
|
||||
|
@ -1123,6 +1124,8 @@ __ri static bool mpeg2sliceIDEC()
|
|||
if (ready_to_decode == true)
|
||||
{
|
||||
ready_to_decode = false;
|
||||
IPUCoreStatus.WaitingOnIPUFrom = false;
|
||||
IPUCoreStatus.WaitingOnIPUTo = false;
|
||||
CPU_INT(IPU_PROCESS, 64); // Should probably be much higher, but myst 3 doesn't like it right now.
|
||||
ipu_cmd.pos[1] = 2;
|
||||
return false;
|
||||
|
@ -1134,6 +1137,7 @@ __ri static bool mpeg2sliceIDEC()
|
|||
if (decoder.ipu0_data != 0)
|
||||
{
|
||||
// IPU FIFO filled up -- Will have to finish transferring later.
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
ipu_cmd.pos[1] = 2;
|
||||
return false;
|
||||
}
|
||||
|
@ -1141,6 +1145,7 @@ __ri static bool mpeg2sliceIDEC()
|
|||
mbaCount = 0;
|
||||
if (read)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
ipu_cmd.pos[1] = 3;
|
||||
return false;
|
||||
}
|
||||
|
@ -1308,6 +1313,7 @@ __fi static bool mpeg2_slice()
|
|||
// IPU0 isn't ready for data, so let's wait for it to be
|
||||
if ((!ipu0ch.chcr.STR || ipuRegs.ctrl.OFC || ipu0ch.qwc == 0) && ipu_cmd.pos[0] <= 3)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1514,6 +1520,8 @@ __fi static bool mpeg2_slice()
|
|||
{
|
||||
ipu_cmd.pos[0] = 3;
|
||||
ready_to_decode = false;
|
||||
IPUCoreStatus.WaitingOnIPUFrom = false;
|
||||
IPUCoreStatus.WaitingOnIPUTo = false;
|
||||
CPU_INT(IPU_PROCESS, 64); // Should probably be much higher, but myst 3 doesn't like it right now.
|
||||
return false;
|
||||
}
|
||||
|
@ -1525,6 +1533,7 @@ __fi static bool mpeg2_slice()
|
|||
if (decoder.ipu0_data != 0)
|
||||
{
|
||||
// IPU FIFO filled up -- Will have to finish transferring later.
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
ipu_cmd.pos[0] = 3;
|
||||
return false;
|
||||
}
|
||||
|
@ -1532,6 +1541,7 @@ __fi static bool mpeg2_slice()
|
|||
mbaCount = 0;
|
||||
if (read)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
ipu_cmd.pos[0] = 4;
|
||||
return false;
|
||||
}
|
||||
|
@ -1801,12 +1811,20 @@ __ri static bool ipuCSC(tIPU_CMD_CSC csc)
|
|||
if (csc.OFM)
|
||||
{
|
||||
ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb16) + 4 * ipu_cmd.pos[1], 32 - ipu_cmd.pos[1]);
|
||||
if (ipu_cmd.pos[1] < 32) return false;
|
||||
if (ipu_cmd.pos[1] < 32)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb32) + 4 * ipu_cmd.pos[1], 64 - ipu_cmd.pos[1]);
|
||||
if (ipu_cmd.pos[1] < 64) return false;
|
||||
if (ipu_cmd.pos[1] < 64)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ipu_cmd.pos[0] = 0;
|
||||
|
@ -1834,12 +1852,20 @@ __ri static bool ipuPACK(tIPU_CMD_CSC csc)
|
|||
if (csc.OFM)
|
||||
{
|
||||
ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*) & decoder.rgb16) + 4 * ipu_cmd.pos[1], 32 - ipu_cmd.pos[1]);
|
||||
if (ipu_cmd.pos[1] < 32) return false;
|
||||
if (ipu_cmd.pos[1] < 32)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ipu_cmd.pos[1] += ipu_fifo.out.write(((u32*)g_ipu_indx4) + 4 * ipu_cmd.pos[1], 8 - ipu_cmd.pos[1]);
|
||||
if (ipu_cmd.pos[1] < 8) return false;
|
||||
if (ipu_cmd.pos[1] < 8)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ipu_cmd.pos[0] = 0;
|
||||
|
|
|
@ -19,16 +19,12 @@
|
|||
#include "IPU/IPUdma.h"
|
||||
#include "IPU/IPU_MultiISA.h"
|
||||
|
||||
IPUStatus IPU1Status;
|
||||
bool CommandExecuteQueued;
|
||||
u32 ProcessedData;
|
||||
IPUDMAStatus IPU1Status;
|
||||
|
||||
void ipuDmaReset()
|
||||
{
|
||||
IPU1Status.InProgress = false;
|
||||
IPU1Status.DMAFinished = true;
|
||||
CommandExecuteQueued = false;
|
||||
ProcessedData = 0;
|
||||
}
|
||||
|
||||
bool SaveStateBase::ipuDmaFreeze()
|
||||
|
@ -37,7 +33,6 @@ bool SaveStateBase::ipuDmaFreeze()
|
|||
return false;
|
||||
|
||||
Freeze(IPU1Status);
|
||||
Freeze(CommandExecuteQueued);
|
||||
return IsOkay();
|
||||
}
|
||||
|
||||
|
@ -83,11 +78,18 @@ void IPU1dma()
|
|||
return;
|
||||
}
|
||||
|
||||
if (IPU1Status.DataRequested == false)
|
||||
if (IPUCoreStatus.DataRequested == false)
|
||||
{
|
||||
// IPU isn't expecting any data, so put it in to wait mode.
|
||||
cpuRegs.eCycle[4] = 0x9999;
|
||||
CPU_SET_DMASTALL(DMAC_TO_IPU, true);
|
||||
|
||||
// Shouldn't Happen.
|
||||
if (IPUCoreStatus.WaitingOnIPUTo)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUTo = false;
|
||||
CPU_INT(IPU_PROCESS, 4 * BIAS);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -127,26 +129,22 @@ void IPU1dma()
|
|||
if (IPU1Status.InProgress)
|
||||
totalqwc += IPU1chain();
|
||||
|
||||
//Do this here to prevent double settings on Chain DMA's
|
||||
if((totalqwc == 0 && g_BP.IFC < 8) || (IPU1Status.DMAFinished && !IPU1Status.InProgress))
|
||||
// Nothing has been processed except maybe a tag, or the DMA is ending
|
||||
if(totalqwc == 0 || (IPU1Status.DMAFinished && !IPU1Status.InProgress) || IPUCoreStatus.DataRequested)
|
||||
{
|
||||
totalqwc = std::max(4, totalqwc) + tagcycles;
|
||||
IPU_INT_TO(totalqwc * BIAS);
|
||||
}
|
||||
else
|
||||
{
|
||||
IPU1Status.DataRequested = false;
|
||||
|
||||
if (!(IPU1Status.DMAFinished && !IPU1Status.InProgress))
|
||||
{
|
||||
cpuRegs.eCycle[4] = 0x9999;//IPU_INT_TO(2048);
|
||||
cpuRegs.eCycle[4] = 0x9999;
|
||||
CPU_SET_DMASTALL(DMAC_TO_IPU, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
totalqwc = std::max(4, totalqwc) + tagcycles;
|
||||
IPU_INT_TO(totalqwc * BIAS);
|
||||
}
|
||||
}
|
||||
|
||||
if (IPUCoreStatus.WaitingOnIPUTo && g_BP.IFC >= 1)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUTo = false;
|
||||
CPU_INT(IPU_PROCESS, totalqwc * BIAS);
|
||||
}
|
||||
|
||||
IPU_LOG("Completed Call IPU1 DMA QWC Remaining %x Finished %d In Progress %d tadr %x", ipu1ch.qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1ch.tadr);
|
||||
|
@ -156,8 +154,12 @@ void IPU0dma()
|
|||
{
|
||||
if(!ipuRegs.ctrl.OFC)
|
||||
{
|
||||
if(!CommandExecuteQueued)
|
||||
// This shouldn't happen.
|
||||
if (IPUCoreStatus.WaitingOnIPUFrom)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = false;
|
||||
IPUProcessInterrupt();
|
||||
}
|
||||
CPU_SET_DMASTALL(DMAC_FROM_IPU, true);
|
||||
return;
|
||||
}
|
||||
|
@ -168,6 +170,12 @@ void IPU0dma()
|
|||
if ((!(ipu0ch.chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0ch.qwc == 0))
|
||||
{
|
||||
DevCon.Warning("How??");
|
||||
// This shouldn't happen.
|
||||
if (IPUCoreStatus.WaitingOnIPUFrom)
|
||||
{
|
||||
IPUCoreStatus.WaitingOnIPUFrom = false;
|
||||
CPU_INT(IPU_PROCESS, ipuRegs.ctrl.OFC * BIAS);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -195,11 +203,12 @@ void IPU0dma()
|
|||
if (!ipu0ch.qwc)
|
||||
IPU_INT_FROM(readsize * BIAS);
|
||||
|
||||
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
|
||||
CPU_SET_DMASTALL(DMAC_FROM_IPU, true);
|
||||
|
||||
if (ipuRegs.ctrl.BUSY && IPUCoreStatus.WaitingOnIPUFrom)
|
||||
{
|
||||
CommandExecuteQueued = false;
|
||||
CPU_SET_DMASTALL(DMAC_FROM_IPU, true);
|
||||
IPUProcessInterrupt();
|
||||
IPUCoreStatus.WaitingOnIPUFrom = false;
|
||||
CPU_INT(IPU_PROCESS, readsize * BIAS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,29 +268,19 @@ __fi void dmaIPU1() // toIPU
|
|||
IPU1Status.DMAFinished = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(IPU1Status.DataRequested)
|
||||
IPU1dma();
|
||||
else
|
||||
cpuRegs.eCycle[4] = 0x9999;
|
||||
}
|
||||
else // Normal Mode
|
||||
{
|
||||
IPU_LOG("Setting up IPU1 Normal mode");
|
||||
IPU1Status.InProgress = true;
|
||||
IPU1Status.DMAFinished = true;
|
||||
|
||||
if (IPU1Status.DataRequested)
|
||||
IPU1dma();
|
||||
else
|
||||
cpuRegs.eCycle[4] = 0x9999;
|
||||
}
|
||||
|
||||
IPU1dma();
|
||||
}
|
||||
|
||||
void ipuCMDProcess()
|
||||
{
|
||||
CommandExecuteQueued = false;
|
||||
ProcessedData = 0;
|
||||
IPUProcessInterrupt();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,15 @@
|
|||
|
||||
#include "IPU.h"
|
||||
|
||||
struct IPUStatus {
|
||||
struct IPUDMAStatus {
|
||||
bool InProgress;
|
||||
bool DMAFinished;
|
||||
};
|
||||
|
||||
struct IPUStatus {
|
||||
bool DataRequested;
|
||||
bool WaitingOnIPUFrom;
|
||||
bool WaitingOnIPUTo;
|
||||
};
|
||||
|
||||
extern void ipuCMDProcess();
|
||||
|
@ -33,4 +38,5 @@ extern void IPU0dma();
|
|||
extern void IPU1dma();
|
||||
|
||||
extern void ipuDmaReset();
|
||||
extern IPUStatus IPU1Status;
|
||||
extern IPUDMAStatus IPU1Status;
|
||||
extern IPUStatus IPUCoreStatus;
|
||||
|
|
|
@ -37,7 +37,7 @@ enum class FreezeAction
|
|||
// [SAVEVERSION+]
|
||||
// This informs the auto updater that the users savestates will be invalidated.
|
||||
|
||||
static const u32 g_SaveVersion = (0x9A40 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A41 << 16) | 0x0000;
|
||||
|
||||
|
||||
// the freezing data between submodules and core
|
||||
|
|
Loading…
Reference in New Issue