Update to ares v114r08 release.
- PlayStation: fixed a bug in the SLLV instruction - PlayStation: implemented interrupts
このコミットが含まれているのは:
コミット
0ed46cc2b1
@ -2,7 +2,7 @@
|
||||
|
||||
namespace ares {
|
||||
static const string Name = "ares";
|
||||
static const string Version = "114.7";
|
||||
static const string Version = "114.8";
|
||||
static const string Copyright = "ares team";
|
||||
static const string License = "BY-NC-ND 4.0";
|
||||
static const string LicenseURI = "https://creativecommons.org/licenses/by-nc-nd/4.0/";
|
||||
|
@ -26,13 +26,21 @@ auto CPU::raiseException(uint code, uint coprocessor) -> void {
|
||||
auto CPU::instruction() -> void {
|
||||
auto address = PC;
|
||||
|
||||
if(auto interrupts = scc.cause.interruptPending & scc.status.interruptMask) {
|
||||
if(interrupt.line & scc.status.frame[0].interruptEnable) {
|
||||
scc.cause.interruptPending = interrupts;
|
||||
step(1);
|
||||
return raiseException(0);
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr(1) {
|
||||
pipeline.address = address;
|
||||
pipeline.instruction = bus.readWord(address);
|
||||
//instructionDebug();
|
||||
decoderEXECUTE();
|
||||
instructionEpilogue();
|
||||
step(1);
|
||||
step(2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,8 +73,8 @@ auto CPU::instructionEpilogue() -> bool {
|
||||
}
|
||||
|
||||
auto CPU::instructionDebug() -> void {
|
||||
pipeline.address = PC;
|
||||
pipeline.instruction = bus.readWord(pipeline.address);
|
||||
//pipeline.address = PC;
|
||||
//pipeline.instruction = bus.readWord(pipeline.address);
|
||||
|
||||
static vector<bool> mask;
|
||||
if(!mask) mask.resize(0x0800'0000);
|
||||
|
@ -87,7 +87,7 @@
|
||||
op(0x01, INVALID);
|
||||
op(0x02, SRL, RD, RT, SA);
|
||||
op(0x03, SRA, RD, RT, SA);
|
||||
op(0x04, SLLV, RD, RT, SA);
|
||||
op(0x04, SLLV, RD, RT, RS);
|
||||
op(0x05, INVALID);
|
||||
op(0x06, SRLV, RD, RT, RS);
|
||||
op(0x07, SRAV, RD, RT, RS);
|
||||
|
@ -7,7 +7,7 @@
|
||||
auto disassemble(u32 address, u32 instruction) -> string;
|
||||
template<typename... P> auto hint(P&&... p) const -> string;
|
||||
|
||||
bool showColors = true;
|
||||
bool showColors = false;
|
||||
bool showValues = true;
|
||||
|
||||
//private:
|
||||
|
@ -4,6 +4,7 @@ namespace ares::PlayStation {
|
||||
|
||||
CPU cpu;
|
||||
#include "core/core.cpp"
|
||||
#include "interrupt.cpp"
|
||||
#include "dma.cpp"
|
||||
#include "serialization.cpp"
|
||||
|
||||
|
@ -19,14 +19,57 @@ struct CPU : Thread {
|
||||
|
||||
#include "core/core.hpp"
|
||||
|
||||
struct DMA : Memory::IO<DMA> {
|
||||
struct Interrupt {
|
||||
enum : uint { Vblank, GPU, CDROM, DMA, Timer0, Timer1, Timer2, Peripheral, SIO, SPU, PIO };
|
||||
|
||||
CPU& self;
|
||||
Interrupt(CPU& self) : self(self) {}
|
||||
|
||||
//interrupt.cpp
|
||||
auto poll() -> void;
|
||||
auto pulse(uint source) -> void;
|
||||
auto raise(uint source) -> void;
|
||||
auto lower(uint source) -> void;
|
||||
|
||||
auto readByte(u32 address) -> u8;
|
||||
auto readHalf(u32 address) -> u16;
|
||||
auto readWord(u32 address) -> u32;
|
||||
auto writeByte(u32 address, u8 data) -> void;
|
||||
auto writeHalf(u32 address, u16 data) -> void;
|
||||
auto writeWord(u32 address, u32 data) -> void;
|
||||
|
||||
struct Source {
|
||||
uint1 line = 0;
|
||||
uint1 stat = 0;
|
||||
uint1 mask = 0;
|
||||
};
|
||||
|
||||
uint1 line = 0;
|
||||
Source vblank;
|
||||
Source gpu;
|
||||
Source cdrom;
|
||||
Source dma;
|
||||
Source timer0;
|
||||
Source timer1;
|
||||
Source timer2;
|
||||
Source peripheral;
|
||||
Source sio;
|
||||
Source spu;
|
||||
Source pio;
|
||||
} interrupt{*this};
|
||||
|
||||
struct DMA {
|
||||
enum : uint { MDECIN, MDECOUT, GPU, CDROM, SPU, PIO, OTC }; //channels
|
||||
|
||||
CPU& self;
|
||||
DMA(CPU& self) : self(self) {}
|
||||
|
||||
//dma.cpp
|
||||
auto readByte(u32 address) -> u8;
|
||||
auto readHalf(u32 address) -> u16;
|
||||
auto readWord(u32 address) -> u32;
|
||||
auto writeByte(u32 address, u8 data) -> void;
|
||||
auto writeHalf(u32 address, u16 data) -> void;
|
||||
auto writeWord(u32 address, u32 data) -> void;
|
||||
auto transferLinear(uint c) -> void;
|
||||
auto transferLinked(uint c) -> void;
|
||||
|
@ -1,20 +1,28 @@
|
||||
auto CPU::DMA::readByte(u32 address) -> u8 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto CPU::DMA::readHalf(u32 address) -> u16 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto CPU::DMA::readWord(u32 address) -> u32 {
|
||||
uint32 data = 0;
|
||||
uint32 c = address >> 4 & 7;
|
||||
|
||||
//DnMADR: DMA Base Address
|
||||
if((address & 0xffff'ff0f) == 0x1f80'1080 && c < 7) {
|
||||
if((address & 0xffff'ff8f) == 0x1f80'1080 && c < 7) {
|
||||
data.bit(0,23) = channel[c].address;
|
||||
}
|
||||
|
||||
//DnBCR: DMA Block Control
|
||||
if((address & 0xffff'ff0f) == 0x1f80'1084 && c < 7) {
|
||||
if((address & 0xffff'ff8f) == 0x1f80'1084 && c < 7) {
|
||||
data.bit( 0,15) = channel[c].length;
|
||||
data.bit(16,31) = channel[c].blocks;
|
||||
}
|
||||
|
||||
//DnCHCR: DMA Channel Control
|
||||
if((address & 0xffff'ff0f) == 0x1f80'1088 && c < 7) {
|
||||
if((address & 0xffff'ff8f) == 0x1f80'1088 && c < 7) {
|
||||
data.bit( 0) = channel[c].direction;
|
||||
data.bit( 1) = channel[c].step;
|
||||
data.bit( 2) = channel[c].chopping.enable;
|
||||
@ -68,6 +76,12 @@ auto CPU::DMA::readWord(u32 address) -> u32 {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto CPU::DMA::writeByte(u32 address, u8 value) -> void {
|
||||
}
|
||||
|
||||
auto CPU::DMA::writeHalf(u32 address, u16 value) -> void {
|
||||
}
|
||||
|
||||
auto CPU::DMA::writeWord(u32 address, u32 value) -> void {
|
||||
uint32 data = value;
|
||||
uint32 c = address >> 4 & 7;
|
||||
@ -95,12 +109,14 @@ auto CPU::DMA::writeWord(u32 address, u32 value) -> void {
|
||||
channel[c].trigger = data.bit(28);
|
||||
channel[c].unknown = data.bit(29,30);
|
||||
|
||||
//print(c, " ", channel[c].direction, " ", channel[c].synchronization, " ", hex(channel[c].address, 8L), "\n");
|
||||
|
||||
if(channel[c].active()) {
|
||||
//u32 base = address & 0xffff'fff0;
|
||||
//print("DMA", c, " ", hex(readWord(base + 8), 8L), " ", hex(readWord(base + 0), 8L), " ", hex(readWord(base + 4), 8L), "\n");
|
||||
|
||||
if(channel[c].synchronization == 0) transferLinear(c);
|
||||
if(channel[c].synchronization == 1) transferLinear(c);
|
||||
if(channel[c].synchronization == 2) transferLinked(c);
|
||||
self.interrupt.pulse(CPU::Interrupt::DMA);
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,6 +210,8 @@ auto CPU::DMA::transferLinked(uint c) -> void {
|
||||
address = header & 0xffffff;
|
||||
if(address & 0x800000) break;
|
||||
} while(--timeout);
|
||||
channel[c].enable = 0;
|
||||
channel[c].trigger = 0;
|
||||
}
|
||||
|
||||
auto CPU::DMA::pollIRQ() -> void {
|
||||
|
146
ares/ps1/cpu/interrupt.cpp
ノーマルファイル
146
ares/ps1/cpu/interrupt.cpp
ノーマルファイル
@ -0,0 +1,146 @@
|
||||
auto CPU::Interrupt::poll() -> void {
|
||||
line = 0;
|
||||
line |= vblank.stat & vblank.mask;
|
||||
line |= gpu.stat & gpu.mask;
|
||||
line |= cdrom.stat & cdrom.mask;
|
||||
line |= dma.stat & dma.mask;
|
||||
line |= timer0.stat & timer0.mask;
|
||||
line |= timer1.stat & timer1.mask;
|
||||
line |= timer2.stat & timer2.mask;
|
||||
line |= peripheral.stat & peripheral.mask;
|
||||
line |= sio.stat & sio.mask;
|
||||
line |= spu.stat & spu.mask;
|
||||
line |= pio.stat & pio.mask;
|
||||
self.scc.cause.interruptPending.bit(2) = line;
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::pulse(uint source) -> void {
|
||||
raise(source);
|
||||
lower(source);
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::raise(uint source) -> void {
|
||||
if(source == 0 && !vblank.line) vblank.line = vblank.stat = 1;
|
||||
if(source == 1 && !gpu.line) gpu.line = gpu.stat = 1;
|
||||
if(source == 2 && !cdrom.line) cdrom.line = cdrom.stat = 1;
|
||||
if(source == 3 && !dma.line) dma.line = dma.stat = 1;
|
||||
if(source == 4 && !timer0.line) timer0.line = timer0.stat = 1;
|
||||
if(source == 5 && !timer1.line) timer1.line = timer1.stat = 1;
|
||||
if(source == 6 && !timer2.line) timer2.line = timer2.stat = 1;
|
||||
if(source == 7 && !peripheral.line) peripheral.line = peripheral.stat = 1;
|
||||
if(source == 8 && !sio.line) sio.line = sio.stat = 1;
|
||||
if(source == 9 && !spu.line) spu.line = spu.stat = 1;
|
||||
if(source == 10 && !pio.line) pio.line = pio.stat = 1;
|
||||
poll();
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::lower(uint source) -> void {
|
||||
if(source == 0) vblank.line = 0;
|
||||
if(source == 1) gpu.line = 0;
|
||||
if(source == 2) cdrom.line = 0;
|
||||
if(source == 3) dma.line = 0;
|
||||
if(source == 4) timer0.line = 0;
|
||||
if(source == 5) timer1.line = 0;
|
||||
if(source == 6) timer2.line = 0;
|
||||
if(source == 7) peripheral.line = 0;
|
||||
if(source == 8) sio.line = 0;
|
||||
if(source == 9) spu.line = 0;
|
||||
if(source == 10) pio.line = 0;
|
||||
poll();
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::readByte(u32 address) -> u8 {
|
||||
uint8 data = 0;
|
||||
print("* read byte ", hex(address, 8L), "\n");
|
||||
return data;
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::readHalf(u32 address) -> u16 {
|
||||
uint16 data = 0;
|
||||
|
||||
//I_STAT
|
||||
if(address == 0x1f80'1070) {
|
||||
data.bit( 0) = vblank.stat;
|
||||
data.bit( 1) = gpu.stat;
|
||||
data.bit( 2) = cdrom.stat;
|
||||
data.bit( 3) = dma.stat;
|
||||
data.bit( 4) = timer0.stat;
|
||||
data.bit( 5) = timer1.stat;
|
||||
data.bit( 6) = timer2.stat;
|
||||
data.bit( 7) = peripheral.stat;
|
||||
data.bit( 8) = sio.stat;
|
||||
data.bit( 9) = spu.stat;
|
||||
data.bit(10) = pio.stat;
|
||||
}
|
||||
|
||||
//I_MASK
|
||||
if(address == 0x1f80'1074) {
|
||||
data.bit( 0) = vblank.mask;
|
||||
data.bit( 1) = gpu.mask;
|
||||
data.bit( 2) = cdrom.mask;
|
||||
data.bit( 3) = dma.mask;
|
||||
data.bit( 4) = timer0.mask;
|
||||
data.bit( 5) = timer1.mask;
|
||||
data.bit( 6) = timer2.mask;
|
||||
data.bit( 7) = peripheral.mask;
|
||||
data.bit( 8) = sio.mask;
|
||||
data.bit( 9) = spu.mask;
|
||||
data.bit(10) = pio.mask;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::readWord(u32 address) -> u32 {
|
||||
uint32 data = 0;
|
||||
data |= readHalf(address & ~3 | 0) << 0;
|
||||
data |= readHalf(address & ~3 | 2) << 16;
|
||||
return data;
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::writeByte(u32 address, u8 value) -> void {
|
||||
uint8 data = value;
|
||||
print("* write byte ", hex(address, 8L), "\n");
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::writeHalf(u32 address, u16 value) -> void {
|
||||
uint16 data = value;
|
||||
|
||||
//I_STAT
|
||||
if(address == 0x1f80'1070) {
|
||||
if(!data.bit( 0)) vblank.stat = 0;
|
||||
if(!data.bit( 1)) gpu.stat = 0;
|
||||
if(!data.bit( 2)) cdrom.stat = 0;
|
||||
if(!data.bit( 3)) dma.stat = 0;
|
||||
if(!data.bit( 4)) timer0.stat = 0;
|
||||
if(!data.bit( 5)) timer1.stat = 0;
|
||||
if(!data.bit( 6)) timer2.stat = 0;
|
||||
if(!data.bit( 7)) peripheral.stat = 0;
|
||||
if(!data.bit( 8)) sio.stat = 0;
|
||||
if(!data.bit( 9)) spu.stat = 0;
|
||||
if(!data.bit(10)) pio.stat = 0;
|
||||
poll();
|
||||
}
|
||||
|
||||
//I_MASK
|
||||
if(address == 0x1f80'1074) {
|
||||
vblank.mask = data.bit( 0);
|
||||
gpu.mask = data.bit( 1);
|
||||
cdrom.mask = data.bit( 2);
|
||||
dma.mask = data.bit( 3);
|
||||
timer0.mask = data.bit( 4);
|
||||
timer1.mask = data.bit( 5);
|
||||
timer2.mask = data.bit( 6);
|
||||
peripheral.mask = data.bit( 7);
|
||||
sio.mask = data.bit( 8);
|
||||
spu.mask = data.bit( 9);
|
||||
pio.mask = data.bit(10);
|
||||
poll();
|
||||
}
|
||||
}
|
||||
|
||||
auto CPU::Interrupt::writeWord(u32 address, u32 value) -> void {
|
||||
uint32 data = value;
|
||||
writeHalf(address & ~3 | 0, value >> 0);
|
||||
writeHalf(address & ~3 | 2, value >> 16);
|
||||
}
|
@ -22,8 +22,13 @@ auto GPU::unload() -> void {
|
||||
}
|
||||
|
||||
auto GPU::main() -> void {
|
||||
if(io.vcounter == 240) {
|
||||
cpu.interrupt.raise(CPU::Interrupt::Vblank);
|
||||
}
|
||||
|
||||
if(++io.vcounter == 262) {
|
||||
io.vcounter = 0;
|
||||
cpu.interrupt.lower(CPU::Interrupt::Vblank);
|
||||
refreshed = true;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//Graphics Processing Unit
|
||||
|
||||
struct GPU : Thread, Memory::IO<GPU> {
|
||||
struct GPU : Thread {
|
||||
Node::Component node;
|
||||
Node::Screen screen;
|
||||
|
||||
@ -14,14 +14,19 @@ struct GPU : Thread, Memory::IO<GPU> {
|
||||
auto power(bool reset) -> void;
|
||||
|
||||
//io.cpp
|
||||
auto readByte(u32 address) -> u8;
|
||||
auto readHalf(u32 address) -> u16;
|
||||
auto readWord(u32 address) -> u32;
|
||||
auto writeByte(u32 address, u8 data) -> void;
|
||||
auto writeHalf(u32 address, u16 data) -> void;
|
||||
auto writeWord(u32 address, u32 data) -> void;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
struct IO {
|
||||
u16 vcounter = 0;
|
||||
uint16 vcounter = 0;
|
||||
uint2 dmaDirection = 0;
|
||||
} io;
|
||||
|
||||
//unserialized:
|
||||
|
@ -1,3 +1,11 @@
|
||||
auto GPU::readByte(u32 address) -> u8 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto GPU::readHalf(u32 address) -> u16 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto GPU::readWord(u32 address) -> u32 {
|
||||
uint32 data = 0;
|
||||
|
||||
@ -7,14 +15,27 @@ auto GPU::readWord(u32 address) -> u32 {
|
||||
|
||||
//GPUSTAT
|
||||
if(address == 0x1f80'1814) {
|
||||
data.bit(26) = 1; //ready to receive command
|
||||
data.bit(27) = 1; //ready to send VRAM to CPU
|
||||
data.bit(28) = 1; //ready to receive DMA block
|
||||
switch(io.dmaDirection) {
|
||||
case 0: data.bit(25) = 0; break;
|
||||
case 1: data.bit(25) = 1; break;
|
||||
case 2: data.bit(25) = 1; break;
|
||||
case 3: data.bit(25) = 1; break;
|
||||
}
|
||||
data.bit(26) = 1; //ready to receive command
|
||||
data.bit(27) = 1; //ready to send VRAM to CPU
|
||||
data.bit(28) = 1; //ready to receive DMA block
|
||||
data.bit(29,30) = io.dmaDirection;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
auto GPU::writeByte(u32 address, u8 value) -> void {
|
||||
}
|
||||
|
||||
auto GPU::writeHalf(u32 address, u16 value) -> void {
|
||||
}
|
||||
|
||||
auto GPU::writeWord(u32 address, u32 value) -> void {
|
||||
uint32 data = value;
|
||||
|
||||
@ -24,5 +45,9 @@ auto GPU::writeWord(u32 address, u32 value) -> void {
|
||||
|
||||
//GP1
|
||||
if(address == 0x1f80'1814) {
|
||||
u8 command = data >> 24;
|
||||
if(command == 0x04) {
|
||||
io.dmaDirection = data.bit(0,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,14 @@
|
||||
if(address <= 0x1eff'ffff) return unmapped; \
|
||||
if(address <= 0x1f7f'ffff) return unmapped; \
|
||||
if(address <= 0x1f80'03ff) return cpu.cache.access(__VA_ARGS__); \
|
||||
if(address <= 0x1f80'107f) return unmapped; \
|
||||
if(address <= 0x1f80'106f) return unmapped; \
|
||||
if(address <= 0x1f80'107f) return cpu.interrupt.access(__VA_ARGS__); \
|
||||
if(address <= 0x1f80'10ff) return cpu.dma.access(__VA_ARGS__); \
|
||||
if(address <= 0x1f80'17ff) return unmapped; \
|
||||
if(address <= 0x1f80'180f) return unmapped; \
|
||||
if(address <= 0x1f80'181f) return gpu.access(__VA_ARGS__); \
|
||||
if(address <= 0x1f80'1bff) return unmapped; \
|
||||
if(address <= 0x1f80'1fff) return spu.access(__VA_ARGS__); \
|
||||
if(address <= 0x1fbf'ffff) return unmapped; \
|
||||
if(address <= 0x1fff'ffff) return bios.access(__VA_ARGS__); \
|
||||
return unmapped; \
|
||||
|
@ -94,43 +94,6 @@ struct Writable {
|
||||
u32 maskWord = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IO {
|
||||
auto readByte(u32 address) -> u8 {
|
||||
auto data = ((T*)this)->readWord(address);
|
||||
switch(address & 3) {
|
||||
case 0: return data >> 0;
|
||||
case 1: return data >> 8;
|
||||
case 2: return data >> 16;
|
||||
case 3: return data >> 24;
|
||||
} unreachable;
|
||||
}
|
||||
|
||||
auto readHalf(u32 address) -> u16 {
|
||||
auto data = ((T*)this)->readWord(address);
|
||||
switch(address & 2) {
|
||||
case 0: return data >> 0;
|
||||
case 2: return data >> 16;
|
||||
} unreachable;
|
||||
}
|
||||
|
||||
auto writeByte(u32 address, u8 data) -> void {
|
||||
switch(address & 3) {
|
||||
case 0: return ((T*)this)->writeWord(address, data << 0);
|
||||
case 1: return ((T*)this)->writeWord(address, data << 8);
|
||||
case 2: return ((T*)this)->writeWord(address, data << 16);
|
||||
case 3: return ((T*)this)->writeWord(address, data << 24);
|
||||
}
|
||||
}
|
||||
|
||||
auto writeHalf(u32 address, u16 data) -> void {
|
||||
switch(address & 2) {
|
||||
case 0: return ((T*)this)->writeWord(address, data << 0);
|
||||
case 2: return ((T*)this)->writeWord(address, data << 16);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct Bus {
|
||||
|
52
ares/ps1/spu/io.cpp
ノーマルファイル
52
ares/ps1/spu/io.cpp
ノーマルファイル
@ -0,0 +1,52 @@
|
||||
auto SPU::readByte(u32 address) -> u8 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto SPU::readHalf(u32 address) -> u16 {
|
||||
uint16 data = 0;
|
||||
|
||||
//SPURAMCNT
|
||||
if(address == 0x1f80'1dac) {
|
||||
data.bit(1,3) = io.ramTransferType;
|
||||
}
|
||||
|
||||
//SPUSTAT
|
||||
if(address == 0x1f80'1dae) {
|
||||
data.bit(0) = io.cdAudioEnable;
|
||||
data.bit(1) = io.externalAudioEnable;
|
||||
data.bit(2) = io.cdAudioReverb;
|
||||
data.bit(3) = io.externalAudioReverb;
|
||||
data.bit(4,5) = io.ramTransferMode;
|
||||
data.bit(7) = io.ramTransferMode.bit(1); //unverified
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
auto SPU::readWord(u32 address) -> u32 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto SPU::writeByte(u32 address, u8 value) -> void {
|
||||
}
|
||||
|
||||
auto SPU::writeHalf(u32 address, u16 value) -> void {
|
||||
uint16 data = value;
|
||||
|
||||
//SPUCNT
|
||||
if(address == 0x1f80'1daa) {
|
||||
io.cdAudioEnable = data.bit(0);
|
||||
io.externalAudioEnable = data.bit(1);
|
||||
io.cdAudioReverb = data.bit(2);
|
||||
io.externalAudioReverb = data.bit(3);
|
||||
io.ramTransferMode = data.bit(4,5);
|
||||
}
|
||||
|
||||
//SPURAMCHT
|
||||
if(address == 0x1f80'1dac) {
|
||||
io.ramTransferType = data.bit(1,3);
|
||||
}
|
||||
}
|
||||
|
||||
auto SPU::writeWord(u32 address, u32 value) -> void {
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
namespace ares::PlayStation {
|
||||
|
||||
SPU spu;
|
||||
#include "io.cpp"
|
||||
#include "serialization.cpp"
|
||||
|
||||
auto SPU::load(Node::Object parent) -> void {
|
||||
@ -33,6 +34,7 @@ auto SPU::step(uint clocks) -> void {
|
||||
|
||||
auto SPU::power(bool reset) -> void {
|
||||
Thread::reset();
|
||||
io = {};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,8 +14,28 @@ struct SPU : Thread {
|
||||
|
||||
auto power(bool reset) -> void;
|
||||
|
||||
//io.cpp
|
||||
auto readByte(u32 address) -> u8;
|
||||
auto readHalf(u32 address) -> u16;
|
||||
auto readWord(u32 address) -> u32;
|
||||
auto writeByte(u32 address, u8 data) -> void;
|
||||
auto writeHalf(u32 address, u16 data) -> void;
|
||||
auto writeWord(u32 address, u32 data) -> void;
|
||||
|
||||
//serialization.cpp
|
||||
auto serialize(serializer&) -> void;
|
||||
|
||||
struct IO {
|
||||
//SPUCNT
|
||||
uint1 cdAudioEnable = 0;
|
||||
uint1 externalAudioEnable = 0;
|
||||
uint1 cdAudioReverb = 0;
|
||||
uint1 externalAudioReverb = 0;
|
||||
uint2 ramTransferMode = 0;
|
||||
|
||||
//SPURAMCNT
|
||||
uint3 ramTransferType = 0;
|
||||
} io;
|
||||
};
|
||||
|
||||
extern SPU spu;
|
||||
|
読み込み中…
新しいイシューから参照
ユーザーをブロックする