2019-09-09 07:01:26 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "YBaseLib/String.h"
|
2019-10-04 09:41:18 +00:00
|
|
|
#include "common/bitfield.h"
|
2019-09-09 07:01:26 +00:00
|
|
|
#include "types.h"
|
|
|
|
#include <array>
|
|
|
|
|
|
|
|
class StateWrapper;
|
2019-09-17 06:26:00 +00:00
|
|
|
|
2019-09-24 13:44:38 +00:00
|
|
|
namespace CPU {
|
2019-09-17 06:26:00 +00:00
|
|
|
class Core;
|
|
|
|
}
|
|
|
|
|
2019-09-09 07:01:26 +00:00
|
|
|
class DMA;
|
2019-09-17 06:26:00 +00:00
|
|
|
class InterruptController;
|
2019-09-17 09:22:39 +00:00
|
|
|
class GPU;
|
|
|
|
class CDROM;
|
2019-09-20 06:47:41 +00:00
|
|
|
class Pad;
|
2019-09-20 13:40:19 +00:00
|
|
|
class Timers;
|
2019-09-24 13:44:38 +00:00
|
|
|
class SPU;
|
2019-09-29 02:51:34 +00:00
|
|
|
class MDEC;
|
2019-09-09 07:01:26 +00:00
|
|
|
class System;
|
|
|
|
|
|
|
|
class Bus
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Bus();
|
|
|
|
~Bus();
|
|
|
|
|
2019-09-24 13:44:38 +00:00
|
|
|
bool Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, Pad* pad,
|
2019-09-29 02:51:34 +00:00
|
|
|
Timers* timers, SPU* spu, MDEC* mdec);
|
2019-09-09 07:01:26 +00:00
|
|
|
void Reset();
|
|
|
|
bool DoState(StateWrapper& sw);
|
|
|
|
|
2019-09-24 14:36:24 +00:00
|
|
|
bool ReadByte(PhysicalMemoryAddress address, u8* value);
|
|
|
|
bool ReadHalfWord(PhysicalMemoryAddress address, u16* value);
|
|
|
|
bool ReadWord(PhysicalMemoryAddress address, u32* value);
|
|
|
|
bool WriteByte(PhysicalMemoryAddress address, u8 value);
|
|
|
|
bool WriteHalfWord(PhysicalMemoryAddress address, u16 value);
|
|
|
|
bool WriteWord(PhysicalMemoryAddress address, u32 value);
|
2019-09-09 07:01:26 +00:00
|
|
|
|
|
|
|
template<MemoryAccessType type, MemoryAccessSize size>
|
2019-09-24 14:36:24 +00:00
|
|
|
bool DispatchAccess(PhysicalMemoryAddress address, u32& value);
|
2019-09-09 07:01:26 +00:00
|
|
|
|
2019-09-14 03:22:05 +00:00
|
|
|
void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF));
|
2019-09-22 15:28:00 +00:00
|
|
|
void SetExpansionROM(std::vector<u8> data);
|
2019-09-14 03:22:05 +00:00
|
|
|
|
2019-09-09 07:01:26 +00:00
|
|
|
private:
|
2019-09-24 14:36:24 +00:00
|
|
|
enum : u32
|
|
|
|
{
|
|
|
|
EXP1_BASE = 0x1F000000,
|
|
|
|
EXP1_SIZE = 0x800000,
|
|
|
|
EXP1_MASK = EXP1_SIZE - 1,
|
|
|
|
MEMCTRL_BASE = 0x1F801000,
|
|
|
|
MEMCTRL_SIZE = 0x40,
|
|
|
|
MEMCTRL_MASK = MEMCTRL_SIZE - 1,
|
|
|
|
PAD_BASE = 0x1F801040,
|
|
|
|
PAD_SIZE = 0x10,
|
|
|
|
PAD_MASK = PAD_SIZE - 1,
|
|
|
|
SIO_BASE = 0x1F801050,
|
|
|
|
SIO_SIZE = 0x10,
|
|
|
|
SIO_MASK = SIO_SIZE - 1,
|
|
|
|
MEMCTRL2_BASE = 0x1F801060,
|
|
|
|
MEMCTRL2_SIZE = 0x10,
|
|
|
|
MEMCTRL2_MASK = MEMCTRL_SIZE - 1,
|
|
|
|
INTERRUPT_CONTROLLER_BASE = 0x1F801070,
|
|
|
|
INTERRUPT_CONTROLLER_SIZE = 0x10,
|
|
|
|
INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1,
|
|
|
|
DMA_BASE = 0x1F801080,
|
|
|
|
DMA_SIZE = 0x80,
|
|
|
|
DMA_MASK = DMA_SIZE - 1,
|
|
|
|
TIMERS_BASE = 0x1F801100,
|
|
|
|
TIMERS_SIZE = 0x40,
|
|
|
|
TIMERS_MASK = TIMERS_SIZE - 1,
|
|
|
|
CDROM_BASE = 0x1F801800,
|
2019-09-29 02:51:34 +00:00
|
|
|
CDROM_SIZE = 0x10,
|
2019-09-24 14:36:24 +00:00
|
|
|
CDROM_MASK = CDROM_SIZE - 1,
|
|
|
|
GPU_BASE = 0x1F801810,
|
|
|
|
GPU_SIZE = 0x10,
|
|
|
|
GPU_MASK = GPU_SIZE - 1,
|
2019-09-29 02:51:34 +00:00
|
|
|
MDEC_BASE = 0x1F801820,
|
|
|
|
MDEC_SIZE = 0x10,
|
|
|
|
MDEC_MASK = MDEC_SIZE - 1,
|
2019-09-24 14:36:24 +00:00
|
|
|
SPU_BASE = 0x1F801C00,
|
|
|
|
SPU_SIZE = 0x300,
|
|
|
|
SPU_MASK = 0x3FF,
|
|
|
|
EXP2_BASE = 0x1F802000,
|
|
|
|
EXP2_SIZE = 0x2000,
|
|
|
|
EXP2_MASK = EXP2_SIZE - 1,
|
|
|
|
BIOS_BASE = 0x1FC00000,
|
|
|
|
BIOS_SIZE = 0x80000
|
|
|
|
};
|
|
|
|
|
|
|
|
enum : u32
|
|
|
|
{
|
|
|
|
MEMCTRL_REG_COUNT = 9
|
|
|
|
};
|
|
|
|
|
2019-10-04 09:41:18 +00:00
|
|
|
union MEMDELAY
|
|
|
|
{
|
|
|
|
u32 bits;
|
|
|
|
|
|
|
|
BitField<u32, u8, 4, 4> access_time; // cycles
|
|
|
|
BitField<u32, bool, 8, 1> use_com0_time;
|
|
|
|
BitField<u32, bool, 9, 1> use_com1_time;
|
|
|
|
BitField<u32, bool, 10, 1> use_com2_time;
|
|
|
|
BitField<u32, bool, 11, 1> use_com3_time;
|
|
|
|
BitField<u32, bool, 12, 1> data_bus_16bit;
|
|
|
|
BitField<u32, u8, 16, 5> memory_window_size;
|
|
|
|
|
|
|
|
static constexpr u32 WRITE_MASK = 0b10101111'00011111'11111111'11111111;
|
|
|
|
};
|
|
|
|
|
|
|
|
union COMDELAY
|
|
|
|
{
|
|
|
|
u32 bits;
|
|
|
|
|
|
|
|
BitField<u32, u8, 0, 4> com0;
|
|
|
|
BitField<u32, u8, 4, 4> com1;
|
|
|
|
BitField<u32, u8, 8, 4> com2;
|
|
|
|
BitField<u32, u8, 12, 4> com3;
|
|
|
|
BitField<u32, u8, 16, 2> comunk;
|
|
|
|
|
|
|
|
static constexpr u32 WRITE_MASK = 0b00000000'00000011'11111111'11111111;
|
|
|
|
};
|
|
|
|
|
2019-09-24 14:36:24 +00:00
|
|
|
union MEMCTRL
|
|
|
|
{
|
|
|
|
u32 regs[MEMCTRL_REG_COUNT];
|
|
|
|
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
u32 exp1_base;
|
|
|
|
u32 exp2_base;
|
2019-10-04 09:41:18 +00:00
|
|
|
MEMDELAY exp1_delay_size;
|
|
|
|
MEMDELAY exp3_delay_size;
|
|
|
|
MEMDELAY bios_delay_size;
|
|
|
|
MEMDELAY spu_delay_size;
|
|
|
|
MEMDELAY cdrom_delay_size;
|
|
|
|
MEMDELAY exp2_delay_size;
|
|
|
|
COMDELAY common_delay;
|
2019-09-24 14:36:24 +00:00
|
|
|
};
|
|
|
|
};
|
2019-09-09 07:01:26 +00:00
|
|
|
|
|
|
|
bool LoadBIOS();
|
|
|
|
|
2019-10-04 09:41:18 +00:00
|
|
|
static std::tuple<TickCount, TickCount, TickCount> CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay);
|
|
|
|
void RecalculateMemoryTimings();
|
|
|
|
|
2019-09-09 07:01:26 +00:00
|
|
|
template<MemoryAccessType type, MemoryAccessSize size>
|
|
|
|
bool DoRAMAccess(u32 offset, u32& value);
|
|
|
|
|
|
|
|
template<MemoryAccessType type, MemoryAccessSize size>
|
|
|
|
bool DoBIOSAccess(u32 offset, u32& value);
|
|
|
|
|
2019-09-24 14:36:24 +00:00
|
|
|
bool DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress address, u32& value);
|
2019-09-09 07:01:26 +00:00
|
|
|
|
2019-09-22 15:28:00 +00:00
|
|
|
bool DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteEXP1(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
|
|
|
bool DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value);
|
2019-09-09 07:01:26 +00:00
|
|
|
|
2019-09-24 14:36:24 +00:00
|
|
|
bool DoReadMemoryControl(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteMemoryControl(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
|
|
|
bool DoReadMemoryControl2(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteMemoryControl2(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
2019-09-20 06:47:41 +00:00
|
|
|
bool DoReadPad(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWritePad(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
2019-09-22 15:28:00 +00:00
|
|
|
bool DoReadSIO(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteSIO(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
2019-09-17 09:22:39 +00:00
|
|
|
bool DoReadCDROM(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteCDROM(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
2019-09-11 04:01:19 +00:00
|
|
|
bool DoReadGPU(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteGPU(MemoryAccessSize size, u32 offset, u32 value);
|
2019-09-09 07:01:26 +00:00
|
|
|
|
2019-09-29 02:51:34 +00:00
|
|
|
bool DoReadMDEC(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteMDEC(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
2019-09-17 06:26:00 +00:00
|
|
|
bool DoReadInterruptController(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteInterruptController(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
2019-09-09 07:01:26 +00:00
|
|
|
bool DoReadDMA(MemoryAccessSize size, u32 offset, u32& value);
|
2019-09-11 04:01:19 +00:00
|
|
|
bool DoWriteDMA(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
2019-09-20 13:40:19 +00:00
|
|
|
bool DoReadTimers(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteTimers(MemoryAccessSize size, u32 offset, u32 value);
|
|
|
|
|
2019-09-24 13:44:38 +00:00
|
|
|
bool DoReadSPU(MemoryAccessSize size, u32 offset, u32& value);
|
|
|
|
bool DoWriteSPU(MemoryAccessSize size, u32 offset, u32 value);
|
2019-09-09 07:01:26 +00:00
|
|
|
|
2019-09-17 06:26:00 +00:00
|
|
|
CPU::Core* m_cpu = nullptr;
|
2019-09-09 07:01:26 +00:00
|
|
|
DMA* m_dma = nullptr;
|
2019-09-17 06:26:00 +00:00
|
|
|
InterruptController* m_interrupt_controller = nullptr;
|
2019-09-09 07:01:26 +00:00
|
|
|
GPU* m_gpu = nullptr;
|
2019-09-17 09:22:39 +00:00
|
|
|
CDROM* m_cdrom = nullptr;
|
2019-09-20 06:47:41 +00:00
|
|
|
Pad* m_pad = nullptr;
|
2019-09-20 13:40:19 +00:00
|
|
|
Timers* m_timers = nullptr;
|
2019-09-24 13:44:38 +00:00
|
|
|
SPU* m_spu = nullptr;
|
2019-09-29 02:51:34 +00:00
|
|
|
MDEC* m_mdec = nullptr;
|
2019-09-09 07:01:26 +00:00
|
|
|
|
2019-10-04 09:41:18 +00:00
|
|
|
std::array<TickCount, 3> m_bios_access_time = {};
|
|
|
|
std::array<TickCount, 3> m_cdrom_access_time = {};
|
|
|
|
std::array<TickCount, 3> m_spu_access_time = {};
|
|
|
|
|
2019-09-09 07:01:26 +00:00
|
|
|
std::array<u8, 2097152> m_ram{}; // 2MB RAM
|
|
|
|
std::array<u8, 524288> m_bios{}; // 512K BIOS ROM
|
2019-09-22 15:28:00 +00:00
|
|
|
std::vector<u8> m_exp1_rom;
|
2019-09-09 07:01:26 +00:00
|
|
|
|
2019-09-24 14:36:24 +00:00
|
|
|
MEMCTRL m_MEMCTRL = {};
|
|
|
|
u32 m_ram_size_reg = 0;
|
|
|
|
|
2019-09-09 07:01:26 +00:00
|
|
|
String m_tty_line_buffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
#include "bus.inl"
|