system: added MemoryControl and RamControl registers

Reset most of devices on softReset
This commit is contained in:
Jakub Czekański 2021-04-07 19:10:14 +02:00
parent 51f855ea0a
commit 3dede45f93
16 changed files with 154 additions and 26 deletions

View file

@ -227,6 +227,7 @@ add_library(core STATIC
src/device/mdec/algorithm.cpp
src/device/mdec/mdec.cpp
src/device/memory_control.cpp
src/device/ram_control.cpp
src/device/serial.cpp
src/device/spu/adsr.cpp
src/device/spu/interpolation.cpp

View file

@ -29,7 +29,7 @@ KeyBindings controller(int n);
namespace DefaultHotkeys {
KeyBindings keyboard();
} // namespace DefaultKeyBindings
} // namespace DefaultHotkeys
struct avocado_config_t {
std::string bios = "";
@ -89,6 +89,7 @@ struct avocado_config_t {
int memoryCard = 0;
int spu = 0;
int system = 1;
int memoryControl = 0;
} log;
} debug;

View file

@ -10,7 +10,9 @@
#include "system.h"
namespace device::dma {
DMA::DMA(System* sys) : sys(sys) {
DMA::DMA(System* sys) : sys(sys) { reset(); }
void DMA::reset() {
dma[0] = std::make_unique<DMA0Channel>(Channel::MDECin, sys, sys->mdec.get());
dma[1] = std::make_unique<DMA1Channel>(Channel::MDECout, sys, sys->mdec.get());
dma[2] = std::make_unique<DMA2Channel>(Channel::GPU, sys, sys->gpu.get());
@ -18,6 +20,11 @@ DMA::DMA(System* sys) : sys(sys) {
dma[4] = std::make_unique<DMA4Channel>(Channel::SPU, sys, sys->spu.get());
dma[5] = std::make_unique<DMA5Channel>(Channel::PIO, sys);
dma[6] = std::make_unique<DMA6Channel>(Channel::OTC, sys);
// TODO: Verify with real HW
control._reg = 0;
status._reg = 0;
pendingInterrupt = false;
}
void DMA::step() {

View file

@ -104,6 +104,7 @@ class DMA {
public:
DMA(System* sys);
void reset();
void step();
uint8_t read(uint32_t address);
void write(uint32_t address, uint8_t data);

View file

@ -5,10 +5,9 @@ class Expansion2 {
static const uint32_t BASE_ADDRESS = 0x1F802000;
uint8_t post;
void reset();
public:
Expansion2();
void reset();
uint8_t read(uint32_t address);
void write(uint32_t address, uint8_t data);
};

View file

@ -3,7 +3,14 @@
using namespace interrupt;
Interrupt::Interrupt(System* sys) : sys(sys) {}
Interrupt::Interrupt(System* sys) : sys(sys) { reset(); }
void Interrupt::reset() {
// TODO: Verify with real HW
status._reg = 0;
mask._reg = 0;
}
void Interrupt::trigger(IrqNumber irq) {
if (irq > 10) return;
status._reg |= (1 << irq);

View file

@ -49,6 +49,7 @@ class Interrupt {
public:
Interrupt(System* sys);
void reset();
void step();
uint8_t read(uint32_t address);
void write(uint32_t address, uint8_t data);

3
src/device/mdec/mdec.h Executable file → Normal file
View file

@ -61,8 +61,6 @@ class MDEC {
std::vector<uint32_t> output;
size_t outputPtr;
void reset();
// Algorithm
void decodeMacroblocks();
void yuvToRgb(decodedBlock& output, int blockX, int blockY);
@ -72,6 +70,7 @@ class MDEC {
public:
MDEC();
void reset();
void step();
uint32_t read(uint32_t address);
void handleCommand(uint8_t cmd, uint32_t data);

View file

@ -1,15 +1,56 @@
#include "memory_control.h"
#include <fmt/core.h>
#include <config.h>
MemoryControl::MemoryControl() { reset(); }
MemoryControl::MemoryControl() {
verbose = config.debug.log.memoryControl > 0;
reset();
}
void MemoryControl::reset() {}
void MemoryControl::reset() {
// TODO: Check reset values
exp1Base._reg = 0;
exp2Base._reg = 0;
exp1Config._reg = 0;
exp3Config._reg = 0;
biosConfig._reg = 0;
spuConfig._reg = 0;
cdromConfig._reg = 0;
exp2Config._reg = 0;
}
uint32_t MemoryControl::read(uint32_t address) {
(void)address;
#define ADDR (address + 0x1f801000)
#define READ(a, reg) \
if (ADDR >= (a) && ADDR < (a) + 4) { \
if (verbose && (ADDR & 3) == 3) fmt::print("[MEMCTRL] R @ " #reg ": 0x{:08x}\n", (reg)._reg); \
return (reg).read(ADDR - (a)); \
}
#define WRITE(a, reg) \
if (ADDR >= (a) && ADDR < (a) + 4) { \
(reg).write(ADDR - (a), data); \
if (verbose && (ADDR & 3) == 3) fmt::print("[MEMCTRL] W @ " #reg ": 0x{:08x}\n", (reg)._reg); \
return; \
}
uint8_t MemoryControl::read(uint32_t address) {
READ(0x1F801000, exp1Base);
READ(0x1F801004, exp2Base);
READ(0x1F801008, exp1Config);
READ(0x1F80100C, exp3Config);
READ(0x1F801010, biosConfig);
READ(0x1F801014, spuConfig);
READ(0x1F801018, cdromConfig);
READ(0x1F80101C, exp2Config);
return 0;
}
void MemoryControl::write(uint32_t address, uint32_t data) {
(void)address;
(void)data;
void MemoryControl::write(uint32_t address, uint8_t data) {
WRITE(0x1F801000, exp1Base);
WRITE(0x1F801004, exp2Base);
WRITE(0x1F801008, exp1Config);
WRITE(0x1F80100C, exp3Config);
WRITE(0x1F801010, biosConfig);
WRITE(0x1F801014, spuConfig);
WRITE(0x1F801018, cdromConfig);
WRITE(0x1F80101C, exp2Config);
}

View file

@ -2,17 +2,31 @@
#include "device.h"
class MemoryControl {
Reg32 status;
void reset();
bool verbose = false;
Reg32 exp1Base;
Reg32 exp2Base;
Reg32 exp1Config;
Reg32 exp2Config;
Reg32 exp3Config;
Reg32 biosConfig;
Reg32 spuConfig;
Reg32 cdromConfig;
public:
MemoryControl();
uint32_t read(uint32_t address);
void write(uint32_t address, uint32_t data);
void reset();
uint8_t read(uint32_t address);
void write(uint32_t address, uint8_t data);
template <class Archive>
void serialize(Archive& ar) {
ar(status);
ar(exp1Base);
ar(exp2Base);
ar(exp1Config);
ar(exp2Config);
ar(exp3Config);
ar(biosConfig);
ar(spuConfig);
ar(cdromConfig);
}
};

View file

@ -0,0 +1,21 @@
#include "ram_control.h"
#include <fmt/core.h>
#include <config.h>
RamControl::RamControl() {
verbose = config.debug.log.memoryControl > 0;
reset();
}
void RamControl::reset() {
ramSize._reg = 0x00000b88; // TODO: Check reset value
}
uint8_t RamControl::read(uint32_t address) { return ramSize.read(address); }
void RamControl::write(uint32_t address, uint8_t data) {
ramSize.write(address, data);
if (verbose && address == 0x3) {
fmt::print("[RAMCTRL] RAM_SIZE: 0x{:08x}\n", ramSize._reg);
}
}

18
src/device/ram_control.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include "device.h"
class RamControl {
bool verbose = false;
Reg32 ramSize;
public:
RamControl();
void reset();
uint8_t read(uint32_t address);
void write(uint32_t address, uint8_t data);
template <class Archive>
void serialize(Archive& ar) {
ar(ramSize);
}
};

View file

@ -6,10 +6,9 @@ class Serial {
Reg32 status;
Reg16 baud;
void reset();
public:
Serial();
void reset();
void step();
uint8_t read(uint32_t address);
void write(uint32_t address, uint8_t data);

View file

@ -20,7 +20,7 @@ namespace state {
const char* lastSaveName = "last.state";
struct StateMetadata {
inline static const uint32_t SAVESTATE_VERSION = 5;
inline static const uint32_t SAVESTATE_VERSION = 6;
uint32_t version = SAVESTATE_VERSION;
std::string biosPath;

View file

@ -27,6 +27,7 @@ System::System() {
expansion2 = std::make_unique<Expansion2>();
interrupt = std::make_unique<Interrupt>(this);
memoryControl = std::make_unique<MemoryControl>();
ramControl = std::make_unique<RamControl>();
cacheControl = std::make_unique<CacheControl>(this);
serial = std::make_unique<Serial>();
for (int t : {0, 1, 2}) {
@ -162,7 +163,7 @@ INLINE T System::readMemory(uint32_t address) {
READ_IO(0x1f801000, 0x1f801024, memoryControl);
READ_IO(0x1f801040, 0x1f801050, controller);
READ_IO(0x1f801050, 0x1f801060, serial);
READ_IO(0x1f801060, 0x1f801064, memoryControl);
READ_IO(0x1f801060, 0x1f801064, ramControl);
READ_IO(0x1f801070, 0x1f801078, interrupt);
READ_IO(0x1f801080, 0x1f801100, dma);
READ_IO(0x1f801100, 0x1f801110, timer[0]);
@ -211,7 +212,7 @@ INLINE void System::writeMemory(uint32_t address, T data) {
WRITE_IO(0x1f801000, 0x1f801024, memoryControl);
WRITE_IO(0x1f801040, 0x1f801050, controller);
WRITE_IO(0x1f801050, 0x1f801060, serial);
WRITE_IO(0x1f801060, 0x1f801064, memoryControl);
WRITE_IO(0x1f801060, 0x1f801064, ramControl);
WRITE_IO(0x1f801070, 0x1f801078, interrupt);
WRITE_IO(0x1f801080, 0x1f801100, dma);
WRITE_IO(0x1f801100, 0x1f801110, timer[0]);
@ -426,7 +427,23 @@ void System::emulateFrame() {
}
void System::softReset() {
fmt::print("Soft reset\n");
// cdrom->reset();
// controller->reset();
dma->reset();
expansion2->reset();
gpu->reset();
interrupt->reset();
mdec->reset();
memoryControl->reset();
ramControl->reset();
cacheControl->reset();
// spu->reset();
serial->reset();
for (int t : {0, 1, 2}) {
// timer[t]->reset();
}
// cpu->reset();
cpu->setPC(0xBFC00000);
cpu->inBranchDelay = false;
state = State::run;

View file

@ -10,6 +10,7 @@
#include "device/interrupt.h"
#include "device/mdec/mdec.h"
#include "device/memory_control.h"
#include "device/ram_control.h"
#include "device/serial.h"
#include "device/spu/spu.h"
#include "device/timer.h"
@ -77,6 +78,7 @@ struct System {
std::unique_ptr<Interrupt> interrupt;
std::unique_ptr<mdec::MDEC> mdec;
std::unique_ptr<MemoryControl> memoryControl;
std::unique_ptr<RamControl> ramControl;
std::unique_ptr<CacheControl> cacheControl;
std::unique_ptr<spu::SPU> spu;
std::unique_ptr<Serial> serial;