Save and load some basic IPU state.

This commit is contained in:
Jean-Philip Desjardins 2023-12-08 13:10:20 -05:00
parent 85ff0350da
commit f65f6f240b
5 changed files with 138 additions and 0 deletions

View file

@ -501,6 +501,7 @@ set(COMMON_SRC_FILES
states/MemoryStateFile.h
states/RegisterState.cpp
states/RegisterState.h
states/RegisterStateUtils.h
states/RegisterStateCollectionFile.cpp
states/RegisterStateCollectionFile.h
states/RegisterStateFile.cpp

View file

@ -379,6 +379,7 @@ void CSubSystem::SaveState(Framework::CZipArchiveWriter& archive)
m_vpu1->SaveState(archive);
m_timer.SaveState(archive);
m_gif.SaveState(archive);
m_ipu.SaveState(archive);
m_os->GetLibMc2().SaveState(archive);
}
@ -405,6 +406,7 @@ void CSubSystem::LoadState(Framework::CZipArchiveReader& archive)
m_vpu1->LoadState(archive);
m_timer.LoadState(archive);
m_gif.LoadState(archive);
m_ipu.LoadState(archive);
m_os->GetLibMc2().LoadState(archive);
}

View file

@ -24,12 +24,38 @@
#include "DMAC.h"
#include "INTC.h"
#include "Ps2Const.h"
#include "../states/RegisterStateFile.h"
#include "../states/RegisterStateUtils.h"
#include "../states/MemoryStateFile.h"
#define LOG_NAME ("ee_ipu")
//#define _DECODE_LOGGING
#define DECODE_LOG_NAME ("ipu_decode")
#define STATE_REGS_XML ("ipu/regs.xml")
#define STATE_INFIFO_REGS_XML ("ipu/infifo.xml")
#define STATE_OUTFIFO ("ipu/outfifo")
#define STATE_INTRAIQ ("ipu/intraiq")
#define STATE_NONINTRAIQ ("ipu/nonintraiq")
#define STATE_VQCLUT ("ipu/vqclut")
#define STATE_REGS_CTRL ("CTRL")
#define STATE_REGS_CMD0 ("CMD0")
#define STATE_REGS_CMD1 ("CMD1")
#define STATE_REGS_TH0 ("TH0")
#define STATE_REGS_TH1 ("TH1")
#define STATE_REGS_CURRENTCMDID ("currentCmdId")
#define STATE_REGS_LASTCMDID ("lastCmdId")
#define STATE_REGS_ISBUSY ("isBusy")
#define STATE_REGS_DCPRED0 ("dcPredictor0")
#define STATE_REGS_DCPRED1 ("dcPredictor1")
#define STATE_REGS_DCPRED2 ("dcPredictor2")
#define STATE_INFIFO_REGS_SIZE ("size")
#define STATE_INFIFO_REGS_BITPOSITION ("bitPosition")
#define STATE_INFIFO_REGS_BUFFER_FORMAT ("Buffer%d")
using namespace IPU;
using namespace MPEG2;
@ -268,6 +294,59 @@ void CIPU::SetRegister(uint32 nAddress, uint32 nValue)
}
}
void CIPU::SaveState(Framework::CZipArchiveWriter& archive)
{
{
auto registerFile = std::make_unique<CRegisterStateFile>(STATE_REGS_XML);
registerFile->SetRegister32(STATE_REGS_CTRL, m_IPU_CTRL);
registerFile->SetRegister32(STATE_REGS_CMD0, m_IPU_CMD[0]);
registerFile->SetRegister32(STATE_REGS_CMD1, m_IPU_CMD[1]);
registerFile->SetRegister32(STATE_REGS_TH0, m_nTH0);
registerFile->SetRegister32(STATE_REGS_TH1, m_nTH1);
registerFile->SetRegister32(STATE_REGS_CURRENTCMDID, m_currentCmdId);
registerFile->SetRegister32(STATE_REGS_LASTCMDID, m_lastCmdId);
registerFile->SetRegister32(STATE_REGS_ISBUSY, m_isBusy ? 1 : 0);
registerFile->SetRegister32(STATE_REGS_DCPRED0, m_nDcPredictor[0]);
registerFile->SetRegister32(STATE_REGS_DCPRED1, m_nDcPredictor[1]);
registerFile->SetRegister32(STATE_REGS_DCPRED2, m_nDcPredictor[2]);
archive.InsertFile(std::move(registerFile));
}
m_IN_FIFO.SaveState(STATE_INFIFO_REGS_XML, archive);
archive.InsertFile(std::make_unique<CMemoryStateFile>(STATE_INTRAIQ, m_nIntraIQ, sizeof(m_nIntraIQ)));
archive.InsertFile(std::make_unique<CMemoryStateFile>(STATE_NONINTRAIQ, m_nNonIntraIQ, sizeof(m_nNonIntraIQ)));
archive.InsertFile(std::make_unique<CMemoryStateFile>(STATE_VQCLUT, m_nVQCLUT, sizeof(m_nVQCLUT)));
assert(m_currentCmdId == IPU_INVALID_CMDID);
}
void CIPU::LoadState(Framework::CZipArchiveReader& archive)
{
{
auto registerFile = CRegisterStateFile(*archive.BeginReadFile(STATE_REGS_XML));
m_IPU_CTRL = registerFile.GetRegister32(STATE_REGS_CTRL);
m_IPU_CMD[0] = registerFile.GetRegister32(STATE_REGS_CMD0);
m_IPU_CMD[1] = registerFile.GetRegister32(STATE_REGS_CMD1);
m_nTH0 = registerFile.GetRegister32(STATE_REGS_TH0);
m_nTH1 = registerFile.GetRegister32(STATE_REGS_TH1);
m_currentCmdId = registerFile.GetRegister32(STATE_REGS_CURRENTCMDID);
m_lastCmdId = registerFile.GetRegister32(STATE_REGS_LASTCMDID);
m_isBusy = registerFile.GetRegister32(STATE_REGS_ISBUSY) != 0;
m_nDcPredictor[0] = registerFile.GetRegister32(STATE_REGS_DCPRED0);
m_nDcPredictor[1] = registerFile.GetRegister32(STATE_REGS_DCPRED1);
m_nDcPredictor[2] = registerFile.GetRegister32(STATE_REGS_DCPRED2);
}
m_IN_FIFO.LoadState(STATE_INFIFO_REGS_XML, archive);
archive.BeginReadFile(STATE_INTRAIQ)->Read(m_nIntraIQ, sizeof(m_nIntraIQ));
archive.BeginReadFile(STATE_NONINTRAIQ)->Read(m_nNonIntraIQ, sizeof(m_nNonIntraIQ));
archive.BeginReadFile(STATE_VQCLUT)->Read(m_nVQCLUT, sizeof(m_nVQCLUT));
assert(m_currentCmdId == IPU_INVALID_CMDID);
}
void CIPU::CountTicks(uint32 ticks)
{
if(m_currentCmdId != IPU_INVALID_CMDID)
@ -897,6 +976,23 @@ void CIPU::CINFIFO::Reset()
m_lookupBitsDirty = false;
}
void CIPU::CINFIFO::SaveState(const char* regsFileName, Framework::CZipArchiveWriter& archive)
{
auto registerFile = std::make_unique<CRegisterStateFile>(regsFileName);
registerFile->SetRegister32(STATE_INFIFO_REGS_SIZE, m_size);
registerFile->SetRegister32(STATE_INFIFO_REGS_BITPOSITION, m_bitPosition);
RegisterStateUtils::WriteArray(*registerFile.get(), m_buffer, STATE_INFIFO_REGS_BUFFER_FORMAT);
archive.InsertFile(std::move(registerFile));
}
void CIPU::CINFIFO::LoadState(const char* regsFileName, Framework::CZipArchiveReader& archive)
{
auto registerFile = CRegisterStateFile(*archive.BeginReadFile(regsFileName));
m_size = registerFile.GetRegister32(STATE_INFIFO_REGS_SIZE);
m_bitPosition = registerFile.GetRegister32(STATE_INFIFO_REGS_BITPOSITION);
RegisterStateUtils::ReadArray(registerFile, m_buffer, STATE_INFIFO_REGS_BUFFER_FORMAT);
}
void CIPU::CINFIFO::SyncLookupBits()
{
unsigned int lookupPosition = (m_bitPosition & ~0x1F) / 8;

View file

@ -9,6 +9,8 @@
#include "mpeg2/DctCoefficientTable.h"
#include "../MailBox.h"
#include "Convertible.h"
#include "zip/ZipArchiveWriter.h"
#include "zip/ZipArchiveReader.h"
class CINTC;
@ -33,6 +35,10 @@ public:
void Reset();
uint32 GetRegister(uint32);
void SetRegister(uint32, uint32);
void SaveState(Framework::CZipArchiveWriter&);
void LoadState(Framework::CZipArchiveReader&);
void SetDMA3ReceiveHandler(const Dma3ReceiveHandler&);
uint32 ReceiveDMA4(uint32, uint32, bool, uint8*, uint8*);
@ -166,7 +172,10 @@ private:
void SetBitPosition(unsigned int);
unsigned int GetSize() const;
unsigned int GetAvailableBits() const;
void Reset();
void SaveState(const char*, Framework::CZipArchiveWriter&);
void LoadState(const char*, Framework::CZipArchiveReader&);
enum BUFFERSIZE
{

View file

@ -0,0 +1,30 @@
#pragma once
#include "string_format.h"
namespace RegisterStateUtils
{
template <typename RegisterStateType, typename ArrayType, std::size_t ArraySize>
void ReadArray(const RegisterStateType& registerState, ArrayType (&array)[ArraySize], const char* format)
{
static_assert((sizeof(array) & 0x0F) == 0);
static const size_t regCount = sizeof(array) / (sizeof(uint128));
for(size_t i = 0; i < regCount; i++)
{
auto registerName = string_format(format, i);
reinterpret_cast<uint128*>(array)[i] = registerState.GetRegister128(registerName.c_str());
}
}
template <typename RegisterStateType, typename ArrayType, std::size_t ArraySize>
void WriteArray(RegisterStateType& registerState, const ArrayType (&array)[ArraySize], const char* format)
{
static_assert((sizeof(array) & 0x0F) == 0);
static const size_t regCount = sizeof(array) / (sizeof(uint128));
for(size_t i = 0; i < regCount; i++)
{
auto registerName = string_format(format, i);
registerState.SetRegister128(registerName.c_str(), reinterpret_cast<const uint128*>(array)[i]);
}
}
}