Merge pull request #11407 from AdmiralCurtiss/globals-gpfifo
HW/GPFifo: Refactor to class, move to Core::System.
This commit is contained in:
commit
21c29bad6b
|
@ -511,7 +511,9 @@ void FifoPlayer::WriteFifo(const u8* data, u32 start, u32 end)
|
||||||
u32 written = start;
|
u32 written = start;
|
||||||
u32 lastBurstEnd = end - 1;
|
u32 lastBurstEnd = end - 1;
|
||||||
|
|
||||||
auto& core_timing = Core::System::GetInstance().GetCoreTiming();
|
auto& system = Core::System::GetInstance();
|
||||||
|
auto& core_timing = system.GetCoreTiming();
|
||||||
|
auto& gpfifo = system.GetGPFifo();
|
||||||
|
|
||||||
// Write up to 256 bytes at a time
|
// Write up to 256 bytes at a time
|
||||||
while (written < end)
|
while (written < end)
|
||||||
|
@ -530,7 +532,7 @@ void FifoPlayer::WriteFifo(const u8* data, u32 start, u32 end)
|
||||||
PowerPC::ppcState.gather_pipe_ptr += burstEnd - written;
|
PowerPC::ppcState.gather_pipe_ptr += burstEnd - written;
|
||||||
written = burstEnd;
|
written = burstEnd;
|
||||||
|
|
||||||
GPFifo::Write8(data[written++]);
|
gpfifo.Write8(data[written++]);
|
||||||
|
|
||||||
// Advance core timing
|
// Advance core timing
|
||||||
u32 elapsedCycles = u32(((u64)written * m_CyclesPerFrame) / m_FrameFifoSize);
|
u32 elapsedCycles = u32(((u64)written * m_CyclesPerFrame) / m_FrameFifoSize);
|
||||||
|
@ -706,13 +708,16 @@ void FifoPlayer::WritePI(u32 address, u32 value)
|
||||||
|
|
||||||
void FifoPlayer::FlushWGP()
|
void FifoPlayer::FlushWGP()
|
||||||
{
|
{
|
||||||
|
auto& system = Core::System::GetInstance();
|
||||||
|
auto& gpfifo = system.GetGPFifo();
|
||||||
|
|
||||||
// Send 31 0s through the WGP
|
// Send 31 0s through the WGP
|
||||||
for (int i = 0; i < 7; ++i)
|
for (int i = 0; i < 7; ++i)
|
||||||
GPFifo::Write32(0);
|
gpfifo.Write32(0);
|
||||||
GPFifo::Write16(0);
|
gpfifo.Write16(0);
|
||||||
GPFifo::Write8(0);
|
gpfifo.Write8(0);
|
||||||
|
|
||||||
GPFifo::ResetGatherPipe();
|
gpfifo.ResetGatherPipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FifoPlayer::WaitForGPUInactive()
|
void FifoPlayer::WaitForGPUInactive()
|
||||||
|
@ -729,34 +734,46 @@ void FifoPlayer::WaitForGPUInactive()
|
||||||
|
|
||||||
void FifoPlayer::LoadBPReg(u8 reg, u32 value)
|
void FifoPlayer::LoadBPReg(u8 reg, u32 value)
|
||||||
{
|
{
|
||||||
GPFifo::Write8(0x61); // load BP reg
|
auto& system = Core::System::GetInstance();
|
||||||
|
auto& gpfifo = system.GetGPFifo();
|
||||||
|
|
||||||
|
gpfifo.Write8(0x61); // load BP reg
|
||||||
|
|
||||||
u32 cmd = (reg << 24) & 0xff000000;
|
u32 cmd = (reg << 24) & 0xff000000;
|
||||||
cmd |= (value & 0x00ffffff);
|
cmd |= (value & 0x00ffffff);
|
||||||
GPFifo::Write32(cmd);
|
gpfifo.Write32(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FifoPlayer::LoadCPReg(u8 reg, u32 value)
|
void FifoPlayer::LoadCPReg(u8 reg, u32 value)
|
||||||
{
|
{
|
||||||
GPFifo::Write8(0x08); // load CP reg
|
auto& system = Core::System::GetInstance();
|
||||||
GPFifo::Write8(reg);
|
auto& gpfifo = system.GetGPFifo();
|
||||||
GPFifo::Write32(value);
|
|
||||||
|
gpfifo.Write8(0x08); // load CP reg
|
||||||
|
gpfifo.Write8(reg);
|
||||||
|
gpfifo.Write32(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FifoPlayer::LoadXFReg(u16 reg, u32 value)
|
void FifoPlayer::LoadXFReg(u16 reg, u32 value)
|
||||||
{
|
{
|
||||||
GPFifo::Write8(0x10); // load XF reg
|
auto& system = Core::System::GetInstance();
|
||||||
GPFifo::Write32((reg & 0x0fff) | 0x1000); // load 4 bytes into reg
|
auto& gpfifo = system.GetGPFifo();
|
||||||
GPFifo::Write32(value);
|
|
||||||
|
gpfifo.Write8(0x10); // load XF reg
|
||||||
|
gpfifo.Write32((reg & 0x0fff) | 0x1000); // load 4 bytes into reg
|
||||||
|
gpfifo.Write32(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FifoPlayer::LoadXFMem16(u16 address, const u32* data)
|
void FifoPlayer::LoadXFMem16(u16 address, const u32* data)
|
||||||
{
|
{
|
||||||
|
auto& system = Core::System::GetInstance();
|
||||||
|
auto& gpfifo = system.GetGPFifo();
|
||||||
|
|
||||||
// Loads 16 * 4 bytes in xf memory starting at address
|
// Loads 16 * 4 bytes in xf memory starting at address
|
||||||
GPFifo::Write8(0x10); // load XF reg
|
gpfifo.Write8(0x10); // load XF reg
|
||||||
GPFifo::Write32(0x000f0000 | (address & 0xffff)); // load 16 * 4 bytes into address
|
gpfifo.Write32(0x000f0000 | (address & 0xffff)); // load 16 * 4 bytes into address
|
||||||
for (int i = 0; i < 16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
GPFifo::Write32(data[i]);
|
gpfifo.Write32(data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FifoPlayer::ShouldLoadBP(u8 address)
|
bool FifoPlayer::ShouldLoadBP(u8 address)
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
|
|
||||||
namespace GPFifo
|
namespace GPFifo
|
||||||
{
|
{
|
||||||
|
GPFifoManager::GPFifoManager(Core::System& system) : m_system(system)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// 32 Byte gather pipe with extra space
|
// 32 Byte gather pipe with extra space
|
||||||
// Overfilling is no problem (up to the real limit), CheckGatherPipe will blast the
|
// Overfilling is no problem (up to the real limit), CheckGatherPipe will blast the
|
||||||
// contents in nicely sized chunks
|
// contents in nicely sized chunks
|
||||||
|
@ -29,35 +33,32 @@ namespace GPFifo
|
||||||
// Both of these should actually work! Only problem is that we have to decide at run time,
|
// Both of these should actually work! Only problem is that we have to decide at run time,
|
||||||
// the same function could use both methods. Compile 2 different versions of each such block?
|
// the same function could use both methods. Compile 2 different versions of each such block?
|
||||||
|
|
||||||
// More room for the fastmodes
|
size_t GPFifoManager::GetGatherPipeCount()
|
||||||
alignas(GATHER_PIPE_SIZE) static u8 s_gather_pipe[GATHER_PIPE_EXTRA_SIZE];
|
|
||||||
|
|
||||||
static size_t GetGatherPipeCount()
|
|
||||||
{
|
{
|
||||||
return PowerPC::ppcState.gather_pipe_ptr - s_gather_pipe;
|
return PowerPC::ppcState.gather_pipe_ptr - m_gather_pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetGatherPipeCount(size_t size)
|
void GPFifoManager::SetGatherPipeCount(size_t size)
|
||||||
{
|
{
|
||||||
PowerPC::ppcState.gather_pipe_ptr = s_gather_pipe + size;
|
PowerPC::ppcState.gather_pipe_ptr = m_gather_pipe + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoState(PointerWrap& p)
|
void GPFifoManager::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
p.Do(s_gather_pipe);
|
p.Do(m_gather_pipe);
|
||||||
u32 pipe_count = static_cast<u32>(GetGatherPipeCount());
|
u32 pipe_count = static_cast<u32>(GetGatherPipeCount());
|
||||||
p.Do(pipe_count);
|
p.Do(pipe_count);
|
||||||
SetGatherPipeCount(pipe_count);
|
SetGatherPipeCount(pipe_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void GPFifoManager::Init()
|
||||||
{
|
{
|
||||||
ResetGatherPipe();
|
ResetGatherPipe();
|
||||||
PowerPC::ppcState.gather_pipe_base_ptr = s_gather_pipe;
|
PowerPC::ppcState.gather_pipe_base_ptr = m_gather_pipe;
|
||||||
memset(s_gather_pipe, 0, sizeof(s_gather_pipe));
|
memset(m_gather_pipe, 0, sizeof(m_gather_pipe));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsBNE()
|
bool GPFifoManager::IsBNE() const
|
||||||
{
|
{
|
||||||
// TODO: It's not clear exactly when the BNE (buffer not empty) bit is set.
|
// TODO: It's not clear exactly when the BNE (buffer not empty) bit is set.
|
||||||
// The PPC 750cl manual says in section 2.1.2.12 "Write Pipe Address Register (WPAR)" (page 78):
|
// The PPC 750cl manual says in section 2.1.2.12 "Write Pipe Address Register (WPAR)" (page 78):
|
||||||
|
@ -76,14 +77,14 @@ bool IsBNE()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetGatherPipe()
|
void GPFifoManager::ResetGatherPipe()
|
||||||
{
|
{
|
||||||
SetGatherPipeCount(0);
|
SetGatherPipeCount(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateGatherPipe()
|
void GPFifoManager::UpdateGatherPipe()
|
||||||
{
|
{
|
||||||
auto& system = Core::System::GetInstance();
|
auto& system = m_system;
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
auto& processor_interface = system.GetProcessorInterface();
|
auto& processor_interface = system.GetProcessorInterface();
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ void UpdateGatherPipe()
|
||||||
for (processed = 0; pipe_count >= GATHER_PIPE_SIZE; processed += GATHER_PIPE_SIZE)
|
for (processed = 0; pipe_count >= GATHER_PIPE_SIZE; processed += GATHER_PIPE_SIZE)
|
||||||
{
|
{
|
||||||
// copy the GatherPipe
|
// copy the GatherPipe
|
||||||
memcpy(cur_mem, s_gather_pipe + processed, GATHER_PIPE_SIZE);
|
memcpy(cur_mem, m_gather_pipe + processed, GATHER_PIPE_SIZE);
|
||||||
pipe_count -= GATHER_PIPE_SIZE;
|
pipe_count -= GATHER_PIPE_SIZE;
|
||||||
|
|
||||||
// increase the CPUWritePointer
|
// increase the CPUWritePointer
|
||||||
|
@ -112,11 +113,11 @@ void UpdateGatherPipe()
|
||||||
}
|
}
|
||||||
|
|
||||||
// move back the spill bytes
|
// move back the spill bytes
|
||||||
memmove(s_gather_pipe, s_gather_pipe + processed, pipe_count);
|
memmove(m_gather_pipe, m_gather_pipe + processed, pipe_count);
|
||||||
SetGatherPipeCount(pipe_count);
|
SetGatherPipeCount(pipe_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FastCheckGatherPipe()
|
void GPFifoManager::FastCheckGatherPipe()
|
||||||
{
|
{
|
||||||
if (GetGatherPipeCount() >= GATHER_PIPE_SIZE)
|
if (GetGatherPipeCount() >= GATHER_PIPE_SIZE)
|
||||||
{
|
{
|
||||||
|
@ -124,7 +125,7 @@ void FastCheckGatherPipe()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckGatherPipe()
|
void GPFifoManager::CheckGatherPipe()
|
||||||
{
|
{
|
||||||
if (GetGatherPipeCount() >= GATHER_PIPE_SIZE)
|
if (GetGatherPipeCount() >= GATHER_PIPE_SIZE)
|
||||||
{
|
{
|
||||||
|
@ -135,55 +136,64 @@ void CheckGatherPipe()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write8(const u8 value)
|
void GPFifoManager::Write8(const u8 value)
|
||||||
{
|
{
|
||||||
FastWrite8(value);
|
FastWrite8(value);
|
||||||
CheckGatherPipe();
|
CheckGatherPipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write16(const u16 value)
|
void GPFifoManager::Write16(const u16 value)
|
||||||
{
|
{
|
||||||
FastWrite16(value);
|
FastWrite16(value);
|
||||||
CheckGatherPipe();
|
CheckGatherPipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write32(const u32 value)
|
void GPFifoManager::Write32(const u32 value)
|
||||||
{
|
{
|
||||||
FastWrite32(value);
|
FastWrite32(value);
|
||||||
CheckGatherPipe();
|
CheckGatherPipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write64(const u64 value)
|
void GPFifoManager::Write64(const u64 value)
|
||||||
{
|
{
|
||||||
FastWrite64(value);
|
FastWrite64(value);
|
||||||
CheckGatherPipe();
|
CheckGatherPipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FastWrite8(const u8 value)
|
void GPFifoManager::FastWrite8(const u8 value)
|
||||||
{
|
{
|
||||||
*PowerPC::ppcState.gather_pipe_ptr = value;
|
*PowerPC::ppcState.gather_pipe_ptr = value;
|
||||||
PowerPC::ppcState.gather_pipe_ptr += sizeof(u8);
|
PowerPC::ppcState.gather_pipe_ptr += sizeof(u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FastWrite16(u16 value)
|
void GPFifoManager::FastWrite16(u16 value)
|
||||||
{
|
{
|
||||||
value = Common::swap16(value);
|
value = Common::swap16(value);
|
||||||
std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u16));
|
std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u16));
|
||||||
PowerPC::ppcState.gather_pipe_ptr += sizeof(u16);
|
PowerPC::ppcState.gather_pipe_ptr += sizeof(u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FastWrite32(u32 value)
|
void GPFifoManager::FastWrite32(u32 value)
|
||||||
{
|
{
|
||||||
value = Common::swap32(value);
|
value = Common::swap32(value);
|
||||||
std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u32));
|
std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u32));
|
||||||
PowerPC::ppcState.gather_pipe_ptr += sizeof(u32);
|
PowerPC::ppcState.gather_pipe_ptr += sizeof(u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FastWrite64(u64 value)
|
void GPFifoManager::FastWrite64(u64 value)
|
||||||
{
|
{
|
||||||
value = Common::swap64(value);
|
value = Common::swap64(value);
|
||||||
std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u64));
|
std::memcpy(PowerPC::ppcState.gather_pipe_ptr, &value, sizeof(u64));
|
||||||
PowerPC::ppcState.gather_pipe_ptr += sizeof(u64);
|
PowerPC::ppcState.gather_pipe_ptr += sizeof(u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateGatherPipe(GPFifoManager& gpfifo)
|
||||||
|
{
|
||||||
|
gpfifo.UpdateGatherPipe();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FastCheckGatherPipe(GPFifoManager& gpfifo)
|
||||||
|
{
|
||||||
|
gpfifo.FastCheckGatherPipe();
|
||||||
|
}
|
||||||
} // namespace GPFifo
|
} // namespace GPFifo
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
|
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
|
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace GPFifo
|
namespace GPFifo
|
||||||
{
|
{
|
||||||
// This address is configurable in the WPAR SPR, but all games put it at this address
|
// This address is configurable in the WPAR SPR, but all games put it at this address
|
||||||
|
@ -16,29 +21,48 @@ constexpr u32 GATHER_PIPE_PHYSICAL_ADDRESS = 0x0C008000;
|
||||||
constexpr u32 GATHER_PIPE_SIZE = 32;
|
constexpr u32 GATHER_PIPE_SIZE = 32;
|
||||||
constexpr u32 GATHER_PIPE_EXTRA_SIZE = GATHER_PIPE_SIZE * 16;
|
constexpr u32 GATHER_PIPE_EXTRA_SIZE = GATHER_PIPE_SIZE * 16;
|
||||||
|
|
||||||
// Init
|
class GPFifoManager final
|
||||||
void Init();
|
{
|
||||||
void DoState(PointerWrap& p);
|
public:
|
||||||
|
explicit GPFifoManager(Core::System& system);
|
||||||
|
|
||||||
// ResetGatherPipe
|
// Init
|
||||||
void ResetGatherPipe();
|
void Init();
|
||||||
void UpdateGatherPipe();
|
void DoState(PointerWrap& p);
|
||||||
void CheckGatherPipe();
|
|
||||||
void FastCheckGatherPipe();
|
|
||||||
|
|
||||||
bool IsBNE();
|
// ResetGatherPipe
|
||||||
|
void ResetGatherPipe();
|
||||||
|
void UpdateGatherPipe();
|
||||||
|
void CheckGatherPipe();
|
||||||
|
void FastCheckGatherPipe();
|
||||||
|
|
||||||
// Write
|
bool IsBNE() const;
|
||||||
void Write8(u8 value);
|
|
||||||
void Write16(u16 value);
|
|
||||||
void Write32(u32 value);
|
|
||||||
void Write64(u64 value);
|
|
||||||
|
|
||||||
// These expect pre-byteswapped values
|
// Write
|
||||||
// Also there's an upper limit of about 512 per batch
|
void Write8(u8 value);
|
||||||
// Most likely these should be inlined into JIT instead
|
void Write16(u16 value);
|
||||||
void FastWrite8(u8 value);
|
void Write32(u32 value);
|
||||||
void FastWrite16(u16 value);
|
void Write64(u64 value);
|
||||||
void FastWrite32(u32 value);
|
|
||||||
void FastWrite64(u64 value);
|
// These expect pre-byteswapped values
|
||||||
|
// Also there's an upper limit of about 512 per batch
|
||||||
|
// Most likely these should be inlined into JIT instead
|
||||||
|
void FastWrite8(u8 value);
|
||||||
|
void FastWrite16(u16 value);
|
||||||
|
void FastWrite32(u32 value);
|
||||||
|
void FastWrite64(u64 value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t GetGatherPipeCount();
|
||||||
|
void SetGatherPipeCount(size_t size);
|
||||||
|
|
||||||
|
// More room for the fastmodes
|
||||||
|
alignas(GATHER_PIPE_SIZE) u8 m_gather_pipe[GATHER_PIPE_EXTRA_SIZE];
|
||||||
|
|
||||||
|
Core::System& m_system;
|
||||||
|
};
|
||||||
|
|
||||||
|
// For use from the JIT.
|
||||||
|
void UpdateGatherPipe(GPFifoManager& gpfifo);
|
||||||
|
void FastCheckGatherPipe(GPFifoManager& gpfifo);
|
||||||
} // namespace GPFifo
|
} // namespace GPFifo
|
||||||
|
|
|
@ -51,7 +51,7 @@ void Init(const Sram* override_sram)
|
||||||
MemoryInterface::Init();
|
MemoryInterface::Init();
|
||||||
DSP::Init(Config::Get(Config::MAIN_DSP_HLE));
|
DSP::Init(Config::Get(Config::MAIN_DSP_HLE));
|
||||||
DVDInterface::Init();
|
DVDInterface::Init();
|
||||||
GPFifo::Init();
|
system.GetGPFifo().Init();
|
||||||
CPU::Init(Config::Get(Config::MAIN_CPU_CORE));
|
CPU::Init(Config::Get(Config::MAIN_CPU_CORE));
|
||||||
SystemTimers::Init();
|
SystemTimers::Init();
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ void DoState(PointerWrap& p)
|
||||||
p.DoMarker("DSP");
|
p.DoMarker("DSP");
|
||||||
DVDInterface::DoState(p);
|
DVDInterface::DoState(p);
|
||||||
p.DoMarker("DVDInterface");
|
p.DoMarker("DVDInterface");
|
||||||
GPFifo::DoState(p);
|
system.GetGPFifo().DoState(p);
|
||||||
p.DoMarker("GPFifo");
|
p.DoMarker("GPFifo");
|
||||||
ExpansionInterface::DoState(p);
|
ExpansionInterface::DoState(p);
|
||||||
p.DoMarker("ExpansionInterface");
|
p.DoMarker("ExpansionInterface");
|
||||||
|
|
|
@ -155,28 +155,28 @@ private:
|
||||||
u8* m_logical_page_mappings_base = nullptr;
|
u8* m_logical_page_mappings_base = nullptr;
|
||||||
|
|
||||||
// The actual memory used for backing the memory map.
|
// The actual memory used for backing the memory map.
|
||||||
u8* m_ram;
|
u8* m_ram = nullptr;
|
||||||
u8* m_exram;
|
u8* m_exram = nullptr;
|
||||||
u8* m_l1_cache;
|
u8* m_l1_cache = nullptr;
|
||||||
u8* m_fake_vmem;
|
u8* m_fake_vmem = nullptr;
|
||||||
|
|
||||||
// m_ram_size is the amount allocated by the emulator, whereas m_ram_size_real
|
// m_ram_size is the amount allocated by the emulator, whereas m_ram_size_real
|
||||||
// is what will be reported in lowmem, and thus used by emulated software.
|
// is what will be reported in lowmem, and thus used by emulated software.
|
||||||
// Note: Writing to lowmem is done by IPL. If using retail IPL, it will
|
// Note: Writing to lowmem is done by IPL. If using retail IPL, it will
|
||||||
// always be set to 24MB.
|
// always be set to 24MB.
|
||||||
u32 m_ram_size_real;
|
u32 m_ram_size_real = 0;
|
||||||
u32 m_ram_size;
|
u32 m_ram_size = 0;
|
||||||
u32 m_ram_mask;
|
u32 m_ram_mask = 0;
|
||||||
u32 m_fakevmem_size;
|
u32 m_fakevmem_size = 0;
|
||||||
u32 m_fakevmem_mask;
|
u32 m_fakevmem_mask = 0;
|
||||||
u32 m_l1_cache_size;
|
u32 m_l1_cache_size = 0;
|
||||||
u32 m_l1_cache_mask;
|
u32 m_l1_cache_mask = 0;
|
||||||
// m_exram_size is the amount allocated by the emulator, whereas m_exram_size_real
|
// m_exram_size is the amount allocated by the emulator, whereas m_exram_size_real
|
||||||
// is what gets used by emulated software. If using retail IOS, it will
|
// is what gets used by emulated software. If using retail IOS, it will
|
||||||
// always be set to 64MB.
|
// always be set to 64MB.
|
||||||
u32 m_exram_size_real;
|
u32 m_exram_size_real = 0;
|
||||||
u32 m_exram_size;
|
u32 m_exram_size = 0;
|
||||||
u32 m_exram_mask;
|
u32 m_exram_mask = 0;
|
||||||
|
|
||||||
bool m_is_fastmem_arena_initialized = false;
|
bool m_is_fastmem_arena_initialized = false;
|
||||||
|
|
||||||
|
@ -231,12 +231,12 @@ private:
|
||||||
//
|
//
|
||||||
// TODO: The actual size of RAM is 24MB; the other 8MB shouldn't be backed by actual memory.
|
// TODO: The actual size of RAM is 24MB; the other 8MB shouldn't be backed by actual memory.
|
||||||
// TODO: Do we want to handle the mirrors of the GC RAM?
|
// TODO: Do we want to handle the mirrors of the GC RAM?
|
||||||
std::array<PhysicalMemoryRegion, 4> m_physical_regions;
|
std::array<PhysicalMemoryRegion, 4> m_physical_regions{};
|
||||||
|
|
||||||
std::vector<LogicalMemoryView> m_logical_mapped_entries;
|
std::vector<LogicalMemoryView> m_logical_mapped_entries;
|
||||||
|
|
||||||
std::array<void*, PowerPC::BAT_PAGE_COUNT> m_physical_page_mappings;
|
std::array<void*, PowerPC::BAT_PAGE_COUNT> m_physical_page_mappings{};
|
||||||
std::array<void*, PowerPC::BAT_PAGE_COUNT> m_logical_page_mappings;
|
std::array<void*, PowerPC::BAT_PAGE_COUNT> m_logical_page_mappings{};
|
||||||
|
|
||||||
void InitMMIO(bool is_wii);
|
void InitMMIO(bool is_wii);
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,12 +85,12 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
MMIO::DirectWrite<u32>(&m_fifo_cpu_write_pointer, 0xFFFFFFE0));
|
MMIO::DirectWrite<u32>(&m_fifo_cpu_write_pointer, 0xFFFFFFE0));
|
||||||
|
|
||||||
mmio->Register(base | PI_FIFO_RESET, MMIO::InvalidRead<u32>(),
|
mmio->Register(base | PI_FIFO_RESET, MMIO::InvalidRead<u32>(),
|
||||||
MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
|
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
|
||||||
// Used by GXAbortFrame
|
// Used by GXAbortFrame
|
||||||
INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_FIFO_RESET: {:08x}", val);
|
INFO_LOG_FMT(PROCESSORINTERFACE, "Wrote PI_FIFO_RESET: {:08x}", val);
|
||||||
if ((val & 1) != 0)
|
if ((val & 1) != 0)
|
||||||
{
|
{
|
||||||
GPFifo::ResetGatherPipe();
|
system.GetGPFifo().ResetGatherPipe();
|
||||||
|
|
||||||
// Call Fifo::ResetVideoBuffer() from the video thread. Since that function
|
// Call Fifo::ResetVideoBuffer() from the video thread. Since that function
|
||||||
// resets various pointers used by the video thread, we can't call it directly
|
// resets various pointers used by the video thread, we can't call it directly
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
|
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
|
||||||
#include "Core/PowerPC/MMU.h"
|
#include "Core/PowerPC/MMU.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
#include "Core/System.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
@ -244,7 +245,7 @@ void Interpreter::mfspr(UGeckoInstruction inst)
|
||||||
// GPFifo::GATHER_PIPE_PHYSICAL_ADDRESS)).
|
// GPFifo::GATHER_PIPE_PHYSICAL_ADDRESS)).
|
||||||
// Currently, we always treat the buffer as not empty, as the exact behavior is unclear
|
// Currently, we always treat the buffer as not empty, as the exact behavior is unclear
|
||||||
// (and games that use display lists will hang if the bit doesn't eventually become zero).
|
// (and games that use display lists will hang if the bit doesn't eventually become zero).
|
||||||
if (GPFifo::IsBNE())
|
if (Core::System::GetInstance().GetGPFifo().IsBNE())
|
||||||
rSPR(index) |= 1;
|
rSPR(index) |= 1;
|
||||||
else
|
else
|
||||||
rSPR(index) &= ~1;
|
rSPR(index) &= ~1;
|
||||||
|
@ -370,7 +371,7 @@ void Interpreter::mtspr(UGeckoInstruction inst)
|
||||||
case SPR_WPAR:
|
case SPR_WPAR:
|
||||||
ASSERT_MSG(POWERPC, rSPR(SPR_WPAR) == GPFifo::GATHER_PIPE_PHYSICAL_ADDRESS,
|
ASSERT_MSG(POWERPC, rSPR(SPR_WPAR) == GPFifo::GATHER_PIPE_PHYSICAL_ADDRESS,
|
||||||
"Gather pipe changed to unexpected address {:08x} @ PC {:08x}", rSPR(SPR_WPAR), PC);
|
"Gather pipe changed to unexpected address {:08x} @ PC {:08x}", rSPR(SPR_WPAR), PC);
|
||||||
GPFifo::ResetGatherPipe();
|
Core::System::GetInstance().GetGPFifo().ResetGatherPipe();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Graphics Quantization Registers
|
// Graphics Quantization Registers
|
||||||
|
|
|
@ -527,7 +527,7 @@ bool Jit64::Cleanup()
|
||||||
CMP(64, R(RSCRATCH), Imm32(GPFifo::GATHER_PIPE_SIZE));
|
CMP(64, R(RSCRATCH), Imm32(GPFifo::GATHER_PIPE_SIZE));
|
||||||
FixupBranch exit = J_CC(CC_L);
|
FixupBranch exit = J_CC(CC_L);
|
||||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||||
ABI_CallFunction(GPFifo::UpdateGatherPipe);
|
ABI_CallFunctionP(GPFifo::UpdateGatherPipe, &Core::System::GetInstance().GetGPFifo());
|
||||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||||
SetJumpTarget(exit);
|
SetJumpTarget(exit);
|
||||||
did_something = true;
|
did_something = true;
|
||||||
|
@ -1027,7 +1027,7 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||||
js.mustCheckFifo = false;
|
js.mustCheckFifo = false;
|
||||||
BitSet32 registersInUse = CallerSavedRegistersInUse();
|
BitSet32 registersInUse = CallerSavedRegistersInUse();
|
||||||
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
||||||
ABI_CallFunction(GPFifo::FastCheckGatherPipe);
|
ABI_CallFunctionP(GPFifo::FastCheckGatherPipe, &Core::System::GetInstance().GetGPFifo());
|
||||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||||
gatherPipeIntCheck = true;
|
gatherPipeIntCheck = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,8 +281,9 @@ void JitArm64::Cleanup()
|
||||||
SUB(ARM64Reg::X0, ARM64Reg::X0, ARM64Reg::X1);
|
SUB(ARM64Reg::X0, ARM64Reg::X0, ARM64Reg::X1);
|
||||||
CMP(ARM64Reg::X0, GPFifo::GATHER_PIPE_SIZE);
|
CMP(ARM64Reg::X0, GPFifo::GATHER_PIPE_SIZE);
|
||||||
FixupBranch exit = B(CC_LT);
|
FixupBranch exit = B(CC_LT);
|
||||||
MOVP2R(ARM64Reg::X0, &GPFifo::UpdateGatherPipe);
|
MOVP2R(ARM64Reg::X1, &GPFifo::UpdateGatherPipe);
|
||||||
BLR(ARM64Reg::X0);
|
MOVP2R(ARM64Reg::X0, &Core::System::GetInstance().GetGPFifo());
|
||||||
|
BLR(ARM64Reg::X1);
|
||||||
SetJumpTarget(exit);
|
SetJumpTarget(exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,6 +966,7 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
||||||
ABI_PushRegisters(regs_in_use);
|
ABI_PushRegisters(regs_in_use);
|
||||||
m_float_emit.ABI_PushRegisters(fprs_in_use, ARM64Reg::X30);
|
m_float_emit.ABI_PushRegisters(fprs_in_use, ARM64Reg::X30);
|
||||||
MOVP2R(ARM64Reg::X8, &GPFifo::FastCheckGatherPipe);
|
MOVP2R(ARM64Reg::X8, &GPFifo::FastCheckGatherPipe);
|
||||||
|
MOVP2R(ARM64Reg::X0, &Core::System::GetInstance().GetGPFifo());
|
||||||
BLR(ARM64Reg::X8);
|
BLR(ARM64Reg::X8);
|
||||||
m_float_emit.ABI_PopRegisters(fprs_in_use, ARM64Reg::X30);
|
m_float_emit.ABI_PopRegisters(fprs_in_use, ARM64Reg::X30);
|
||||||
ABI_PopRegisters(regs_in_use);
|
ABI_PopRegisters(regs_in_use);
|
||||||
|
|
|
@ -332,20 +332,21 @@ static void WriteToHardware(Core::System& system, Memory::MemoryManager& memory,
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
GPFifo::Write8(static_cast<u8>(data));
|
system.GetGPFifo().Write8(static_cast<u8>(data));
|
||||||
return;
|
return;
|
||||||
case 2:
|
case 2:
|
||||||
GPFifo::Write16(static_cast<u16>(data));
|
system.GetGPFifo().Write16(static_cast<u16>(data));
|
||||||
return;
|
return;
|
||||||
case 4:
|
case 4:
|
||||||
GPFifo::Write32(data);
|
system.GetGPFifo().Write32(data);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
// Some kind of misaligned write. TODO: Does this match how the actual hardware handles it?
|
// Some kind of misaligned write. TODO: Does this match how the actual hardware handles it?
|
||||||
|
auto& gpfifo = system.GetGPFifo();
|
||||||
for (size_t i = size * 8; i > 0;)
|
for (size_t i = size * 8; i > 0;)
|
||||||
{
|
{
|
||||||
i -= 8;
|
i -= 8;
|
||||||
GPFifo::Write8(static_cast<u8>(data >> i));
|
gpfifo.Write8(static_cast<u8>(data >> i));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "Core/HW/DVD/DVDInterface.h"
|
#include "Core/HW/DVD/DVDInterface.h"
|
||||||
#include "Core/HW/DVD/DVDThread.h"
|
#include "Core/HW/DVD/DVDThread.h"
|
||||||
#include "Core/HW/EXI/EXI.h"
|
#include "Core/HW/EXI/EXI.h"
|
||||||
|
#include "Core/HW/GPFifo.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
#include "Core/HW/MemoryInterface.h"
|
#include "Core/HW/MemoryInterface.h"
|
||||||
#include "Core/HW/ProcessorInterface.h"
|
#include "Core/HW/ProcessorInterface.h"
|
||||||
|
@ -30,6 +31,8 @@ namespace Core
|
||||||
{
|
{
|
||||||
struct System::Impl
|
struct System::Impl
|
||||||
{
|
{
|
||||||
|
explicit Impl(System& system) : m_gp_fifo(system) {}
|
||||||
|
|
||||||
std::unique_ptr<SoundStream> m_sound_stream;
|
std::unique_ptr<SoundStream> m_sound_stream;
|
||||||
bool m_sound_stream_running = false;
|
bool m_sound_stream_running = false;
|
||||||
bool m_audio_dump_started = false;
|
bool m_audio_dump_started = false;
|
||||||
|
@ -43,6 +46,7 @@ struct System::Impl
|
||||||
ExpansionInterface::ExpansionInterfaceState m_expansion_interface_state;
|
ExpansionInterface::ExpansionInterfaceState m_expansion_interface_state;
|
||||||
Fifo::FifoManager m_fifo;
|
Fifo::FifoManager m_fifo;
|
||||||
GeometryShaderManager m_geometry_shader_manager;
|
GeometryShaderManager m_geometry_shader_manager;
|
||||||
|
GPFifo::GPFifoManager m_gp_fifo;
|
||||||
Memory::MemoryManager m_memory;
|
Memory::MemoryManager m_memory;
|
||||||
MemoryInterface::MemoryInterfaceState m_memory_interface_state;
|
MemoryInterface::MemoryInterfaceState m_memory_interface_state;
|
||||||
PixelEngine::PixelEngineManager m_pixel_engine;
|
PixelEngine::PixelEngineManager m_pixel_engine;
|
||||||
|
@ -54,7 +58,7 @@ struct System::Impl
|
||||||
VideoInterface::VideoInterfaceState m_video_interface_state;
|
VideoInterface::VideoInterfaceState m_video_interface_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
System::System() : m_impl{std::make_unique<Impl>()}
|
System::System() : m_impl{std::make_unique<Impl>(*this)}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +146,11 @@ GeometryShaderManager& System::GetGeometryShaderManager() const
|
||||||
return m_impl->m_geometry_shader_manager;
|
return m_impl->m_geometry_shader_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GPFifo::GPFifoManager& System::GetGPFifo() const
|
||||||
|
{
|
||||||
|
return m_impl->m_gp_fifo;
|
||||||
|
}
|
||||||
|
|
||||||
Memory::MemoryManager& System::GetMemory() const
|
Memory::MemoryManager& System::GetMemory() const
|
||||||
{
|
{
|
||||||
return m_impl->m_memory;
|
return m_impl->m_memory;
|
||||||
|
|
|
@ -43,6 +43,10 @@ namespace Fifo
|
||||||
{
|
{
|
||||||
class FifoManager;
|
class FifoManager;
|
||||||
}
|
}
|
||||||
|
namespace GPFifo
|
||||||
|
{
|
||||||
|
class GPFifoManager;
|
||||||
|
}
|
||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
class MemoryManager;
|
class MemoryManager;
|
||||||
|
@ -111,6 +115,7 @@ public:
|
||||||
ExpansionInterface::ExpansionInterfaceState& GetExpansionInterfaceState() const;
|
ExpansionInterface::ExpansionInterfaceState& GetExpansionInterfaceState() const;
|
||||||
Fifo::FifoManager& GetFifo() const;
|
Fifo::FifoManager& GetFifo() const;
|
||||||
GeometryShaderManager& GetGeometryShaderManager() const;
|
GeometryShaderManager& GetGeometryShaderManager() const;
|
||||||
|
GPFifo::GPFifoManager& GetGPFifo() const;
|
||||||
Memory::MemoryManager& GetMemory() const;
|
Memory::MemoryManager& GetMemory() const;
|
||||||
MemoryInterface::MemoryInterfaceState& GetMemoryInterfaceState() const;
|
MemoryInterface::MemoryInterfaceState& GetMemoryInterfaceState() const;
|
||||||
PixelEngine::PixelEngineManager& GetPixelEngine() const;
|
PixelEngine::PixelEngineManager& GetPixelEngine() const;
|
||||||
|
|
Loading…
Reference in New Issue