mirror of
https://github.com/JaCzekanski/Avocado.git
synced 2024-06-02 19:27:41 -04:00
system: added MemoryControl and RamControl registers
Reset most of devices on softReset
This commit is contained in:
parent
51f855ea0a
commit
3dede45f93
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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
3
src/device/mdec/mdec.h
Executable file → Normal 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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
};
|
21
src/device/ram_control.cpp
Normal file
21
src/device/ram_control.cpp
Normal 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
18
src/device/ram_control.h
Normal 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);
|
||||
}
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue