mirror of https://github.com/stenzek/duckstation
GTE: Stub and register read/write function
parent
6df8d42480
commit
4025d6e4a6
@ -1,192 +0,0 @@
|
||||
#include "cpu_bus.h"
|
||||
#include "YBaseLib/ByteStream.h"
|
||||
#include "YBaseLib/Log.h"
|
||||
#include "YBaseLib/String.h"
|
||||
#include <cstdio>
|
||||
Log_SetChannel(Bus);
|
||||
|
||||
Bus::Bus() = default;
|
||||
|
||||
Bus::~Bus() = default;
|
||||
|
||||
bool Bus::Initialize(System* system)
|
||||
{
|
||||
if (!LoadBIOS())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Bus::Reset()
|
||||
{
|
||||
m_ram.fill(static_cast<u8>(0));
|
||||
}
|
||||
|
||||
bool Bus::DoState(StateWrapper& sw)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bus::ReadByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8* value)
|
||||
{
|
||||
u32 temp = 0;
|
||||
const bool result = DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Byte>(cpu_address, bus_address, temp);
|
||||
*value = Truncate8(temp);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Bus::ReadWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16* value)
|
||||
{
|
||||
u32 temp = 0;
|
||||
const bool result =
|
||||
DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord>(cpu_address, bus_address, temp);
|
||||
*value = Truncate16(temp);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Bus::ReadDWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32* value)
|
||||
{
|
||||
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Word>(cpu_address, bus_address, *value);
|
||||
}
|
||||
|
||||
bool Bus::WriteByte(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u8 value)
|
||||
{
|
||||
u32 temp = ZeroExtend32(value);
|
||||
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::Byte>(cpu_address, bus_address, temp);
|
||||
}
|
||||
|
||||
bool Bus::WriteWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u16 value)
|
||||
{
|
||||
u32 temp = ZeroExtend32(value);
|
||||
return DispatchAccess<MemoryAccessType::Read, MemoryAccessSize::HalfWord>(cpu_address, bus_address, temp);
|
||||
}
|
||||
|
||||
bool Bus::WriteDWord(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32 value)
|
||||
{
|
||||
return DispatchAccess<MemoryAccessType::Write, MemoryAccessSize::Word>(cpu_address, bus_address, value);
|
||||
}
|
||||
|
||||
bool Bus::LoadBIOS()
|
||||
{
|
||||
std::FILE* fp = std::fopen("SCPH1001.BIN", "rb");
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
std::fseek(fp, 0, SEEK_END);
|
||||
const u32 size = static_cast<u32>(std::ftell(fp));
|
||||
std::fseek(fp, 0, SEEK_SET);
|
||||
|
||||
if (size != m_bios.size())
|
||||
{
|
||||
Log_ErrorPrintf("BIOS image mismatch, expecting %u bytes, got %u bytes", static_cast<u32>(m_bios.size()), size);
|
||||
std::fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::fread(m_bios.data(), 1, m_bios.size(), fp) != m_bios.size())
|
||||
{
|
||||
Log_ErrorPrintf("Failed to read BIOS image");
|
||||
std::fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::fclose(fp);
|
||||
|
||||
#if 1
|
||||
auto Patch = [this](u32 address, u32 value) { std::memcpy(&m_bios[address], &value, sizeof(value)); };
|
||||
Patch(0x6F0C, 0x24010001); // addiu $at, $zero, 1
|
||||
Patch(0x6F14, 0xaf81a9c0); // sw at, -0x5640(gp)
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress cpu_address,
|
||||
PhysicalMemoryAddress bus_address, u32& value)
|
||||
{
|
||||
SmallString str;
|
||||
str.AppendString("Invalid bus ");
|
||||
if (size == MemoryAccessSize::Byte)
|
||||
str.AppendString("byte");
|
||||
if (size == MemoryAccessSize::HalfWord)
|
||||
str.AppendString("word");
|
||||
if (size == MemoryAccessSize::Word)
|
||||
str.AppendString("dword");
|
||||
str.AppendCharacter(' ');
|
||||
if (type == MemoryAccessType::Read)
|
||||
str.AppendString("read");
|
||||
else
|
||||
str.AppendString("write");
|
||||
|
||||
str.AppendFormattedString(" at address 0x%08X (virtual address 0x%08X)", bus_address, cpu_address);
|
||||
if (type == MemoryAccessType::Write)
|
||||
str.AppendFormattedString(" (value 0x%08X)", value);
|
||||
|
||||
Log_ErrorPrint(str);
|
||||
if (type == MemoryAccessType::Read)
|
||||
value = UINT32_C(0xFFFFFFFF);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bus::ReadExpansionRegion2(MemoryAccessSize size, u32 offset, u32& value)
|
||||
{
|
||||
offset &= EXP2_MASK;
|
||||
|
||||
// rx/tx buffer empty
|
||||
if (offset == 0x21)
|
||||
{
|
||||
value = 0x04 | 0x08;
|
||||
return true;
|
||||
}
|
||||
|
||||
return DoInvalidAccess(MemoryAccessType::Read, size, EXP2_BASE | offset, EXP2_BASE | offset, value);
|
||||
}
|
||||
|
||||
bool Bus::WriteExpansionRegion2(MemoryAccessSize size, u32 offset, u32 value)
|
||||
{
|
||||
offset &= EXP2_MASK;
|
||||
|
||||
if (offset == 0x23)
|
||||
{
|
||||
if (value == '\r')
|
||||
return true;
|
||||
|
||||
if (value == '\n')
|
||||
{
|
||||
if (!m_tty_line_buffer.IsEmpty())
|
||||
Log_InfoPrintf("TTY: %s", m_tty_line_buffer.GetCharArray());
|
||||
m_tty_line_buffer.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tty_line_buffer.AppendCharacter(Truncate8(value));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (offset == 0x41)
|
||||
{
|
||||
Log_WarningPrintf("BIOS POST status: %02X", value & UINT32_C(0x0F));
|
||||
return true;
|
||||
}
|
||||
|
||||
return DoInvalidAccess(MemoryAccessType::Write, size, EXP2_BASE | offset, EXP2_BASE | offset, value);
|
||||
}
|
||||
|
||||
bool Bus::ReadSPU(MemoryAccessSize size, u32 offset, u32& value)
|
||||
{
|
||||
if (offset == 0x1AE)
|
||||
{
|
||||
value = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return DoInvalidAccess(MemoryAccessType::Write, size, SPU_BASE | offset, SPU_BASE | offset, value);
|
||||
}
|
||||
|
||||
bool Bus::WriteSPU(MemoryAccessSize size, u32 offset, u32 value)
|
||||
{
|
||||
return DoInvalidAccess(MemoryAccessType::Write, size, SPU_BASE | offset, SPU_BASE | offset, value);
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
#include "gte.h"
|
||||
|
||||
namespace GTE {
|
||||
|
||||
Core::Core() = default;
|
||||
|
||||
Core::~Core() = default;
|
||||
|
||||
void Core::Initialize() {}
|
||||
|
||||
void Core::Reset()
|
||||
{
|
||||
m_regs = {};
|
||||
}
|
||||
|
||||
bool Core::DoState(StateWrapper& sw)
|
||||
{
|
||||
sw.DoPOD(&m_regs);
|
||||
return !sw.HasError();
|
||||
}
|
||||
|
||||
void Core::ExecuteInstruction(Instruction inst) {}
|
||||
|
||||
} // namespace GTE
|
||||
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "common/state_wrapper.h"
|
||||
#include "gte_types.h"
|
||||
|
||||
namespace GTE {
|
||||
|
||||
class Core
|
||||
{
|
||||
public:
|
||||
Core();
|
||||
~Core();
|
||||
|
||||
void Initialize();
|
||||
void Reset();
|
||||
bool DoState(StateWrapper& sw);
|
||||
|
||||
u32 ReadRegister(u32 index) const { return m_regs.r32[index]; }
|
||||
void WriteRegister(u32 index, u32 value) { m_regs.r32[index] = value; }
|
||||
|
||||
u32 ReadDataRegister(u32 index) const { return m_regs.r32[index]; }
|
||||
void WriteDataRegister(u32 index, u32 value) { m_regs.r32[index] = value; }
|
||||
|
||||
u32 ReadControlRegister(u32 index) const { return m_regs.r32[index + 32]; }
|
||||
void WriteControlRegister(u32 index, u32 value) { m_regs.r32[index + 32] = value; }
|
||||
|
||||
void ExecuteInstruction(Instruction inst);
|
||||
|
||||
private:
|
||||
Regs m_regs = {};
|
||||
};
|
||||
|
||||
} // namespace GTE
|
||||
@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
#include "common/bitfield.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace GTE {
|
||||
static constexpr u32 NUM_REGS = 64;
|
||||
|
||||
union Regs
|
||||
{
|
||||
u32 r32[NUM_REGS];
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct
|
||||
{
|
||||
s16 V0[3]; // 0-1
|
||||
u16 pad1; // 1
|
||||
s16 V1[3]; // 2-3
|
||||
u16 pad2; // 3
|
||||
s16 V2[3]; // 4-5
|
||||
u16 pad3; // 5
|
||||
u8 RGBC[4]; // 6
|
||||
u16 OTZ; // 7
|
||||
u16 pad4; // 7
|
||||
s16 IR0; // 8
|
||||
u16 pad5; // 8
|
||||
s16 IR1; // 9
|
||||
u16 pad6; // 9
|
||||
s16 IR2; // 10
|
||||
u16 pad7; // 10
|
||||
s16 IR3; // 11
|
||||
u16 pad8; // 11
|
||||
s16 SXY0; // 12
|
||||
u16 pad9; // 12
|
||||
s16 SXY1; // 13
|
||||
u16 pad10; // 13
|
||||
s16 SXY2; // 14
|
||||
u16 pad11; // 14
|
||||
s16 SXYP; // 15
|
||||
u16 pad12; // 15
|
||||
u16 SZ0; // 16
|
||||
u16 pad13; // 16
|
||||
u16 SZ1; // 17
|
||||
u16 pad14; // 17
|
||||
u16 SZ2; // 18
|
||||
u16 pad15; // 18
|
||||
u16 SZ3; // 19
|
||||
u16 pad16; // 19
|
||||
u32 RGB0; // 20
|
||||
u32 RGB1; // 21
|
||||
u32 RGB2; // 22
|
||||
u32 RES1; // 23
|
||||
s32 MAC0; // 24
|
||||
s32 MAC1; // 25
|
||||
s32 MAC2; // 26
|
||||
s32 MAC4; // 27
|
||||
u16 IRGB; // 28
|
||||
u16 ORGB; // 29
|
||||
s32 LZCS; // 30
|
||||
s32 LZCR; // 31
|
||||
u16 RT[3][3]; // 32-36
|
||||
u16 pad17; // 36
|
||||
s32 TR[3]; // 37-39
|
||||
u16 L[3][3]; // 40-44
|
||||
u16 pad18; // 44
|
||||
u32 RBK; // 45
|
||||
u32 GBK; // 46
|
||||
u32 BBK; // 47
|
||||
u16 LR[3][3]; // 48-52
|
||||
u16 pad19; // 52
|
||||
u32 RFC; // 53
|
||||
u32 GFC; // 54
|
||||
u32 BFC; // 55
|
||||
u32 OFX; // 56
|
||||
u32 OFY; // 57
|
||||
u16 H; // 58
|
||||
u16 pad20; // 58
|
||||
u16 DQA; // 59
|
||||
u16 pad21; // 59
|
||||
u32 DQB; // 60
|
||||
u16 ZSF3; // 61
|
||||
u16 pad22; // 61
|
||||
u16 ZSF4; // 62
|
||||
u16 pad23; // 62
|
||||
u32 FLAG; // 63
|
||||
};
|
||||
#pragma pack(pop)
|
||||
};
|
||||
static_assert(sizeof(Regs) == (sizeof(u32) * NUM_REGS));
|
||||
|
||||
union Instruction
|
||||
{
|
||||
u32 bits;
|
||||
|
||||
BitField<u32, u8, 20, 5> fake_command;
|
||||
BitField<u32, u8, 19, 1> sf; // shift fraction in IR registers, 0=no fraction, 1=12bit fraction
|
||||
BitField<u32, u8, 17, 2> mvmva_multiply_matrix;
|
||||
BitField<u32, u8, 15, 2> mvmva_multiply_vector;
|
||||
BitField<u32, u8, 13, 2> mvmva_translation_vector;
|
||||
BitField<u32, bool, 10, 1> lm; // saturate IR1, IR2, IR3 result
|
||||
BitField<u32, u8, 0, 6> command;
|
||||
};
|
||||
|
||||
} // namespace GTE
|
||||
Loading…
Reference in New Issue