diff --git a/ares/n64/ai/ai.cpp b/ares/n64/ai/ai.cpp index 1b64e26993..89b5f61da3 100644 --- a/ares/n64/ai/ai.cpp +++ b/ares/n64/ai/ai.cpp @@ -38,7 +38,7 @@ auto AI::sample(f64& left, f64& right) -> void { if(io.dmaLength[0] && io.dmaEnable) { io.dmaAddress[0].bit(13,23) += io.dmaAddressCarry; - auto data = rdram.ram.read(io.dmaAddress[0]); + auto data = rdram.ram.read(io.dmaAddress[0], "AI"); auto l = s16(data >> 16); auto r = s16(data >> 0); left = l / 32768.0; @@ -50,8 +50,9 @@ auto AI::sample(f64& left, f64& right) -> void { } if(!io.dmaLength[0]) { if(--io.dmaCount) { - io.dmaAddress[0] = io.dmaAddress[1]; - io.dmaLength [0] = io.dmaLength [1]; + io.dmaAddress[0] = io.dmaAddress[1]; + io.dmaLength [0] = io.dmaLength [1]; + io.dmaOriginPc[0] = io.dmaOriginPc[1]; mi.raise(MI::IRQ::AI); } } diff --git a/ares/n64/ai/ai.hpp b/ares/n64/ai/ai.hpp index aee1602da8..e6ff587e52 100644 --- a/ares/n64/ai/ai.hpp +++ b/ares/n64/ai/ai.hpp @@ -38,6 +38,7 @@ struct AI : Thread, Memory::RCP { n1 dmaAddressCarry; n18 dmaLength[2]; n2 dmaCount; + u64 dmaOriginPc[2]; n14 dacRate; n4 bitRate; } io; diff --git a/ares/n64/ai/io.cpp b/ares/n64/ai/io.cpp index d72a3ef408..56b21853df 100644 --- a/ares/n64/ai/io.cpp +++ b/ares/n64/ai/io.cpp @@ -38,6 +38,7 @@ auto AI::writeWord(u32 address, u32 data_, Thread& thread) -> void { if(io.dmaCount < 2) { if(io.dmaCount == 0) mi.raise(MI::IRQ::AI); io.dmaLength[io.dmaCount] = length; + io.dmaOriginPc[io.dmaCount] = cpu.ipu.pc; io.dmaCount++; } } diff --git a/ares/n64/cartridge/flash.cpp b/ares/n64/cartridge/flash.cpp index cfcbe2bf72..32402929d3 100644 --- a/ares/n64/cartridge/flash.cpp +++ b/ares/n64/cartridge/flash.cpp @@ -85,7 +85,8 @@ auto Cartridge::Flash::writeWord(u32 address, u64 data) -> void { } if(mode == Mode::Write) { for(u32 index = 0; index < 128; index += 2) { - u16 half = rdram.ram.read(source + index); + // FIXME: this is obviously wrong, the flash can't access RDRAM + u16 half = rdram.ram.read(source + index, "Flash"); Memory::Writable::write(offset + index, half); } } diff --git a/ares/n64/cpu/cpu.hpp b/ares/n64/cpu/cpu.hpp index 2cc91e9830..1aea84fb11 100644 --- a/ares/n64/cpu/cpu.hpp +++ b/ares/n64/cpu/cpu.hpp @@ -184,9 +184,11 @@ struct CPU : Thread { template auto write(u32 address, u64 data) -> void; bool valid; - bool dirty; + u16 dirty; u32 tag; u16 index; + u64 fillpc; + u64 dirtypc; union { u8 bytes[16]; u16 halfs[8]; diff --git a/ares/n64/cpu/dcache.cpp b/ares/n64/cpu/dcache.cpp index dd81312f62..442abe633f 100644 --- a/ares/n64/cpu/dcache.cpp +++ b/ares/n64/cpu/dcache.cpp @@ -4,9 +4,10 @@ auto CPU::DataCache::Line::hit(u32 address) const -> bool { auto CPU::DataCache::Line::fill(u32 address) -> void { cpu.step(40 * 2); - valid = 1; - dirty = 0; - tag = address & ~0x0000'0fff; + valid = 1; + dirty = 0; + tag = address & ~0x0000'0fff; + fillpc = cpu.ipu.pc; cpu.busReadBurst(tag | index, words); } @@ -41,7 +42,8 @@ auto CPU::DataCache::Line::write(u32 address, u64 data) -> void { words[address >> 2 & 2 | 0] = data >> 32; words[address >> 2 & 2 | 1] = data >> 0; } - dirty = 1; + dirty |= ((1 << Size) - 1) << (address & 0xF); + dirtypc = cpu.ipu.pc; } template @@ -60,7 +62,7 @@ auto CPU::DataCache::readDebug(u32 vaddr, u32 address) -> u8 { auto& line = this->line(vaddr); if(!line.hit(address)) { Thread dummyThread{}; - return bus.read(address, dummyThread); + return bus.read(address, dummyThread, "Ares Debugger"); } return line.read(address); } diff --git a/ares/n64/cpu/memory.cpp b/ares/n64/cpu/memory.cpp index d548d2be78..e319d26360 100644 --- a/ares/n64/cpu/memory.cpp +++ b/ares/n64/cpu/memory.cpp @@ -146,7 +146,7 @@ auto CPU::devirtualizeDebug(u64 vaddr) -> u64 { template inline auto CPU::busWrite(u32 address, u64 data) -> void { - bus.write(address, data, *this); + bus.write(address, data, *this, "CPU"); } template @@ -156,7 +156,7 @@ inline auto CPU::busWriteBurst(u32 address, u32 *data) -> void { template inline auto CPU::busRead(u32 address) -> u64 { - return bus.read(address, *this); + return bus.read(address, *this, "CPU"); } template @@ -239,7 +239,7 @@ auto CPU::readDebug(u64 vaddr) -> u8 { case Context::Segment::Mapped: if(auto match = tlb.load(vaddr, true)) { if(match.cache) return dcache.readDebug(vaddr, match.address & context.physMask); - return bus.read(match.address & context.physMask, dummyThread); + return bus.read(match.address & context.physMask, dummyThread, "Ares Debugger"); } return 0; case Context::Segment::Cached: @@ -247,9 +247,9 @@ auto CPU::readDebug(u64 vaddr) -> u8 { case Context::Segment::Cached32: return dcache.readDebug(vaddr, vaddr & 0xffff'ffff); case Context::Segment::Direct: - return bus.read(vaddr & 0x1fff'ffff, dummyThread); + return bus.read(vaddr & 0x1fff'ffff, dummyThread, "Ares Debugger"); case Context::Segment::Direct32: - return bus.read(vaddr & 0xffff'ffff, dummyThread); + return bus.read(vaddr & 0xffff'ffff, dummyThread, "Ares Debugger"); } unreachable; diff --git a/ares/n64/cpu/recompiler.cpp b/ares/n64/cpu/recompiler.cpp index 98f39dbecf..7c870ae0bc 100644 --- a/ares/n64/cpu/recompiler.cpp +++ b/ares/n64/cpu/recompiler.cpp @@ -36,7 +36,7 @@ auto CPU::Recompiler::emit(u32 vaddr, u32 address, bool singleInstruction) -> Bl Thread thread; bool hasBranched = 0; while(true) { - u32 instruction = bus.read(address, thread); + u32 instruction = bus.read(address, thread, "Ares Recompiler"); if(callInstructionPrologue) { mov32(reg(1), imm(instruction)); call(&CPU::instructionPrologue); diff --git a/ares/n64/memory/bus.hpp b/ares/n64/memory/bus.hpp index b72ae9b016..ee4fb3a25d 100644 --- a/ares/n64/memory/bus.hpp +++ b/ares/n64/memory/bus.hpp @@ -1,10 +1,9 @@ template -inline auto Bus::read(u32 address, Thread& thread) -> u64 { +inline auto Bus::read(u32 address, Thread& thread, const char *peripheral) -> u64 { static constexpr u64 unmapped = 0; static_assert(Size == Byte || Size == Half || Size == Word || Size == Dual); - if(address <= 0x007f'ffff) return rdram.ram.read(address); - if(address <= 0x03ef'ffff) return unmapped; + if(address <= 0x03ef'ffff) return rdram.ram.read(address, peripheral); if(address <= 0x03ff'ffff) return rdram.read(address, thread); if(address <= 0x0407'ffff) return rsp.read(address, thread); if(address <= 0x040f'ffff) return rsp.status.read(address, thread); @@ -27,16 +26,18 @@ template inline auto Bus::readBurst(u32 address, u32 *data, Thread& thread) -> void { static_assert(Size == DCache || Size == ICache); + if(address <= 0x03ef'ffff) return rdram.ram.readBurst(address, data, "CPU"); if(address <= 0x03ff'ffff) { - data[0] = read(address | 0x0, thread); - data[1] = read(address | 0x4, thread); - data[2] = read(address | 0x8, thread); - data[3] = read(address | 0xc, thread); + // FIXME: not hardware validated, no idea of the behavior + data[0] = rdram.readWord(address | 0x0, thread); + data[1] = 0; + data[2] = 0; + data[3] = 0; if constexpr(Size == ICache) { - data[4] = read(address | 0x10, thread); - data[5] = read(address | 0x14, thread); - data[6] = read(address | 0x18, thread); - data[7] = read(address | 0x1c, thread); + data[4] = 0; + data[5] = 0; + data[6] = 0; + data[7] = 0; } return; } @@ -46,15 +47,14 @@ inline auto Bus::readBurst(u32 address, u32 *data, Thread& thread) -> void { } template -inline auto Bus::write(u32 address, u64 data, Thread& thread) -> void { +inline auto Bus::write(u32 address, u64 data, Thread& thread, const char *peripheral) -> void { static_assert(Size == Byte || Size == Half || Size == Word || Size == Dual); if constexpr(Accuracy::CPU::Recompiler) { cpu.recompiler.invalidate(address + 0); if constexpr(Size == Dual) cpu.recompiler.invalidate(address + 4); } - if(address <= 0x007f'ffff) return rdram.ram.write(address, data); - if(address <= 0x03ef'ffff) return; + if(address <= 0x03ef'ffff) return rdram.ram.write(address, data, peripheral); if(address <= 0x03ff'ffff) return rdram.write(address, data, thread); if(address <= 0x0407'ffff) return rsp.write(address, data, thread); if(address <= 0x040f'ffff) return rsp.status.write(address, data, thread); @@ -76,21 +76,17 @@ inline auto Bus::write(u32 address, u64 data, Thread& thread) -> void { template inline auto Bus::writeBurst(u32 address, u32 *data, Thread& thread) -> void { static_assert(Size == DCache || Size == ICache); + if constexpr(Accuracy::CPU::Recompiler) { + cpu.recompiler.invalidateRange(address, address + (Size == DCache ? 16 : 32)); + } + if(address <= 0x03ef'ffff) return rdram.ram.writeBurst(address, data, "CPU"); if(address <= 0x03ff'ffff) { - write(address | 0x0, data[0], thread); - write(address | 0x4, data[1], thread); - write(address | 0x8, data[2], thread); - write(address | 0xc, data[3], thread); - if constexpr(Size == ICache) { - write(address | 0x10, data[4], thread); - write(address | 0x14, data[5], thread); - write(address | 0x18, data[6], thread); - write(address | 0x1c, data[7], thread); - } + // FIXME: not hardware validated, but a good guess + rdram.writeWord(address | 0x0, data[0], thread); return; } - debug(unusual, "[Bus::readBurst] CPU frozen because of cached write to non-RDRAM area: 0x", hex(address, 8L)); + debug(unusual, "[Bus::writeBurst] CPU frozen because of cached write to non-RDRAM area: 0x", hex(address, 8L)); cpu.scc.sysadFrozen = true; } diff --git a/ares/n64/memory/memory.hpp b/ares/n64/memory/memory.hpp index 0e7478c513..206940e62a 100644 --- a/ares/n64/memory/memory.hpp +++ b/ares/n64/memory/memory.hpp @@ -31,8 +31,8 @@ namespace Memory { struct Bus { //bus.hpp - template auto read(u32 address, Thread& thread) -> u64; - template auto write(u32 address, u64 data, Thread& thread) -> void; + template auto read(u32 address, Thread& thread, const char *peripheral) -> u64; + template auto write(u32 address, u64 data, Thread& thread, const char *peripheral) -> void; template auto readBurst(u32 address, u32* data, Thread& thread) -> void; template auto writeBurst(u32 address, u32* data, Thread& thread) -> void; diff --git a/ares/n64/n64.hpp b/ares/n64/n64.hpp index d386deb96f..d7d151a697 100644 --- a/ares/n64/n64.hpp +++ b/ares/n64/n64.hpp @@ -96,8 +96,8 @@ namespace ares::Nintendo64 { #include #include #include - #include #include + #include #include #include #include diff --git a/ares/n64/pi/dma.cpp b/ares/n64/pi/dma.cpp index 8b0fa86ce3..47ac25775b 100644 --- a/ares/n64/pi/dma.cpp +++ b/ares/n64/pi/dma.cpp @@ -3,14 +3,7 @@ auto PI::dmaRead() -> void { u32 lastCacheline = 0xffff'ffff; for(u32 address = 0; address < io.readLength; address += 2) { - if (system.homebrewMode && ((io.dramAddress + address) & ~15) != lastCacheline) { - lastCacheline = address & ~15; - auto& line = cpu.dcache.line(io.dramAddress + address); - if (line.hit(io.dramAddress) && line.dirty) { - debug(unusual, "PI DMA reading from cached memory ", hex((io.dramAddress + address) | 0x80000000), " (missing cache writeback?)"); - } - } - u16 data = rdram.ram.read(io.dramAddress + address); + u16 data = rdram.ram.read(io.dramAddress + address, "PI DMA"); busWrite(io.pbusAddress + address, data); } } @@ -49,17 +42,8 @@ auto PI::dmaWrite() -> void { cpu.recompiler.invalidateRange(io.dramAddress, cur_len); } - u32 lastCacheline = 0xffff'ffff; - for (u32 i = 0; i < cur_len; i++) { - if (system.homebrewMode && (io.dramAddress & ~15) != lastCacheline) { - lastCacheline = io.dramAddress & ~15; - auto& line = cpu.dcache.line(io.dramAddress); - if (line.hit(io.dramAddress)) { - debug(unusual, "PI DMA writing to cached memory ", hex(io.dramAddress | 0x80000000), " (missing cache invalidation?)"); - } - } - rdram.ram.write(io.dramAddress++, mem[i]); - } + for (u32 i = 0; i < cur_len; i++) + rdram.ram.write(io.dramAddress++, mem[i], "PI DMA"); io.dramAddress = (io.dramAddress + 7) & ~7; first_block = false; diff --git a/ares/n64/pi/io.cpp b/ares/n64/pi/io.cpp index c131bf3a69..86e866036e 100644 --- a/ares/n64/pi/io.cpp +++ b/ares/n64/pi/io.cpp @@ -98,6 +98,7 @@ auto PI::ioWrite(u32 address, u32 data_) -> void { //PI_READ_LENGTH io.readLength = n24(data); io.dmaBusy = 1; + io.originPc = cpu.ipu.pc; queue.insert(Queue::PI_DMA_Read, dmaDuration(true)); dmaRead(); } @@ -106,6 +107,7 @@ auto PI::ioWrite(u32 address, u32 data_) -> void { //PI_WRITE_LENGTH io.writeLength = n24(data); io.dmaBusy = 1; + io.originPc = cpu.ipu.pc; queue.insert(Queue::PI_DMA_Write, dmaDuration(false)); dmaWrite(); } diff --git a/ares/n64/pi/pi.hpp b/ares/n64/pi/pi.hpp index 240f177dd6..e824d5d739 100644 --- a/ares/n64/pi/pi.hpp +++ b/ares/n64/pi/pi.hpp @@ -51,6 +51,7 @@ struct PI : Memory::RCP { n32 readLength; n32 writeLength; n32 busLatch; + u64 originPc; } io; struct BSD { diff --git a/ares/n64/pif/io.cpp b/ares/n64/pif/io.cpp index 4d1ac5478f..44eb1ff76d 100644 --- a/ares/n64/pif/io.cpp +++ b/ares/n64/pif/io.cpp @@ -30,13 +30,13 @@ auto PIF::dmaRead(u32 address, u32 ramAddress) -> void { intA(Read, Size64); for(u32 offset = 0; offset < 64; offset += 4) { u32 data = readInt(address + offset); - rdram.ram.write(ramAddress + offset, data); + rdram.ram.write(ramAddress + offset, data, "SI DMA"); } } auto PIF::dmaWrite(u32 address, u32 ramAddress) -> void { for(u32 offset = 0; offset < 64; offset += 4) { - u32 data = rdram.ram.read(ramAddress + offset); + u32 data = rdram.ram.read(ramAddress + offset, "SI DMA"); writeInt(address + offset, data); } intA(Write, Size64); diff --git a/ares/n64/rdram/debugger.cpp b/ares/n64/rdram/debugger.cpp index 2d10c85f7a..04ca928b53 100644 --- a/ares/n64/rdram/debugger.cpp +++ b/ares/n64/rdram/debugger.cpp @@ -7,10 +7,10 @@ auto RDRAM::Debugger::load(Node::Object parent) -> void { } memory.ram->setRead([&](u32 address) -> u8 { - return rdram.ram.read(address); + return rdram.ram.read(address, "Ares Debugger"); }); memory.ram->setWrite([&](u32 address, u8 data) -> void { - return rdram.ram.write(address, data); + return rdram.ram.write(address, data, "Ares Debugger"); }); memory.dcache = parent->append("DCache"); @@ -25,7 +25,7 @@ auto RDRAM::Debugger::load(Node::Object parent) -> void { if(line.hit(address)) { line.write(address, data); } else { - rdram.ram.write(address, data); + rdram.ram.write(address, data, "Ares Debugger"); } }); @@ -59,3 +59,51 @@ auto RDRAM::Debugger::io(bool mode, u32 chipID, u32 address, u32 data) -> void { tracer.io->notify(message); } } + +auto RDRAM::Debugger::cacheErrorContext(string peripheral) -> string { + if(peripheral == "CPU") { + return { "\tCurrent CPU PC: ", hex(cpu.ipu.pc, 16L), "\n" }; + } + if(peripheral == "RSP DMA") { + if(rsp.dma.current.originCpu) { + return { "\tRSP DMA started at CPU PC: ", hex(rsp.dma.current.originPc, 16L), "\n" }; + } else { + return { "\tRSP DMA started at RSP PC: ", hex(rsp.dma.current.originPc, 3L), "\n" }; + } + } + if(peripheral == "PI DMA") { + return { "\tPI DMA started at CPU PC: ", hex(pi.io.originPc, 16L), "\n" }; + } + if(peripheral == "AI DMA") { + return { "\tAI DMA started at CPU PC: ", hex(ai.io.dmaOriginPc[0], 16L), "\n" }; + } + return ""; +} + +auto RDRAM::Debugger::readWord(u32 address, int size, const char *peripheral) -> void { + if (system.homebrewMode && (address & ~15) != lastReadCacheline) { + lastReadCacheline = address & ~15; + auto& line = cpu.dcache.line(address); + u16 dirtyMask = ((1 << size) - 1) << (address & 0xF); + if (line.hit(address) && (line.dirty & dirtyMask)) { + string msg = { peripheral, " reading from RDRAM address ", hex(address), " which is modified in the cache (missing cache writeback?)\n"}; + msg.append(string{ "\tCacheline was loaded at CPU PC: ", hex(line.fillpc, 16L), "\n" }); + msg.append(string{ "\tCacheline was last written at CPU PC: ", hex(line.dirtypc, 16L), "\n" }); + msg.append(cacheErrorContext(peripheral)); + debug(unusual, msg); + } + } +} + +auto RDRAM::Debugger::writeWord(u32 address, int size, u64 value, const char *peripheral) -> void { + if (system.homebrewMode && (address & ~15) != lastWrittenCacheline) { + lastWrittenCacheline = address & ~15; + auto& line = cpu.dcache.line(address); + if (line.hit(address)) { + string msg = { peripheral, " writing to RDRAM address ", hex(address), " which is cached (missing cache invalidation?)\n"}; + msg.append(string{ "\tCacheline was loaded at CPU PC: ", hex(line.fillpc, 16L), "\n" }); + msg.append(cacheErrorContext(peripheral)); + debug(unusual, msg); + } + } +} diff --git a/ares/n64/rdram/rdram.hpp b/ares/n64/rdram/rdram.hpp index 7c4bfc3117..75bbf9267c 100644 --- a/ares/n64/rdram/rdram.hpp +++ b/ares/n64/rdram/rdram.hpp @@ -4,23 +4,71 @@ struct RDRAM : Memory::RCP { Node::Object node; struct Writable : public Memory::Writable { + RDRAM& self; + + Writable(RDRAM& self) : self(self) {} + template - auto read(u32 address) -> u64 { + auto read(u32 address, const char *peripheral) -> u64 { if (address >= size) return 0; + if (system.homebrewMode) self.debugger.readWord(address, Size, peripheral); return Memory::Writable::read(address); } template - auto write(u32 address, u64 value) -> void { + auto write(u32 address, u64 value, const char *peripheral) -> void { if (address >= size) return; + if (system.homebrewMode) self.debugger.writeWord(address, Size, value, peripheral); Memory::Writable::write(address, value); } - } ram; + + template + auto writeBurst(u32 address, u32 *value, const char *peripheral) -> void { + if (address >= size) return; + Memory::Writable::write(address | 0x00, value[0]); + Memory::Writable::write(address | 0x04, value[1]); + Memory::Writable::write(address | 0x08, value[2]); + Memory::Writable::write(address | 0x0c, value[3]); + if (Size == ICache) { + Memory::Writable::write(address | 0x10, value[4]); + Memory::Writable::write(address | 0x14, value[5]); + Memory::Writable::write(address | 0x18, value[6]); + Memory::Writable::write(address | 0x1c, value[7]); + } + } + + template + auto readBurst(u32 address, u32 *value, const char *peripheral) -> void { + if (address >= size) { + value[0] = value[1] = value[2] = value[3] = 0; + if (Size == ICache) + value[4] = value[5] = value[6] = value[7] = 0; + return; + } + value[0] = Memory::Writable::read(address | 0x00); + value[1] = Memory::Writable::read(address | 0x04); + value[2] = Memory::Writable::read(address | 0x08); + value[3] = Memory::Writable::read(address | 0x0c); + if (Size == ICache) { + value[4] = Memory::Writable::read(address | 0x10); + value[5] = Memory::Writable::read(address | 0x14); + value[6] = Memory::Writable::read(address | 0x18); + value[7] = Memory::Writable::read(address | 0x1c); + } + } + + } ram{*this}; struct Debugger { + u32 lastReadCacheline = 0xffff'ffff; + u32 lastWrittenCacheline = 0xffff'ffff; + //debugger.cpp auto load(Node::Object) -> void; auto io(bool mode, u32 chipID, u32 address, u32 data) -> void; + auto readWord(u32 address, int size, const char *peripheral) -> void; + auto writeWord(u32 address, int size, u64 value, const char *peripheral) -> void; + auto cacheErrorContext(string peripheral) -> string; struct Memory { Node::Debugger::Memory ram; diff --git a/ares/n64/ri/ri.cpp b/ares/n64/ri/ri.cpp index 1ebca7025c..5267965c4b 100644 --- a/ares/n64/ri/ri.cpp +++ b/ares/n64/ri/ri.cpp @@ -27,8 +27,8 @@ auto RI::power(bool reset) -> void { io.refresh = 0x0006'3634; //store RDRAM size result into memory - rdram.ram.write(0x318, rdram.ram.size); //CIC-NUS-6102 - rdram.ram.write(0x3f0, rdram.ram.size); //CIC-NUS-6105 + rdram.ram.write(0x318, rdram.ram.size, "IPL3"); //CIC-NUS-6102 + rdram.ram.write(0x3f0, rdram.ram.size, "IPL3"); //CIC-NUS-6105 } } diff --git a/ares/n64/rsp/dma.cpp b/ares/n64/rsp/dma.cpp index fbc00b7962..b4879ae8ec 100644 --- a/ares/n64/rsp/dma.cpp +++ b/ares/n64/rsp/dma.cpp @@ -18,16 +18,17 @@ auto RSP::dmaTransferStep() -> void { } } for(u32 i = 0; i <= dma.current.length; i += 8) { - u64 data = rdram.ram.read(dma.current.dramAddress); + u64 data = rdram.ram.read(dma.current.dramAddress, "RSP DMA"); region.write(dma.current.pbusAddress, data); dma.current.dramAddress += 8; dma.current.pbusAddress += 8; } } if(dma.busy.write) { + u32 lastCacheline = 0xffff'ffff; for(u32 i = 0; i <= dma.current.length; i += 8) { u64 data = region.read(dma.current.pbusAddress); - rdram.ram.write(dma.current.dramAddress, data); + rdram.ram.write(dma.current.dramAddress, data, "RSP DMA"); dma.current.dramAddress += 8; dma.current.pbusAddress += 8; } diff --git a/ares/n64/rsp/interpreter-scc.cpp b/ares/n64/rsp/interpreter-scc.cpp index 672716aec7..528f87231b 100644 --- a/ares/n64/rsp/interpreter-scc.cpp +++ b/ares/n64/rsp/interpreter-scc.cpp @@ -1,9 +1,9 @@ auto RSP::MFC0(r32& rt, u8 rd) -> void { - if((rd & 8) == 0) rt.u32 = Nintendo64::rsp.ioRead ((rd & 7) << 2); + if((rd & 8) == 0) rt.u32 = Nintendo64::rsp.ioRead ((rd & 7) << 2, *this); if((rd & 8) != 0) rt.u32 = Nintendo64::rdp.readWord((rd & 7) << 2, *this); } auto RSP::MTC0(cr32& rt, u8 rd) -> void { - if((rd & 8) == 0) Nintendo64::rsp.ioWrite ((rd & 7) << 2, rt.u32); + if((rd & 8) == 0) Nintendo64::rsp.ioWrite ((rd & 7) << 2, rt.u32, *this); if((rd & 8) != 0) Nintendo64::rdp.writeWord((rd & 7) << 2, rt.u32, *this); } diff --git a/ares/n64/rsp/io.cpp b/ares/n64/rsp/io.cpp index 1daa5fccc0..68eb99fdf4 100644 --- a/ares/n64/rsp/io.cpp +++ b/ares/n64/rsp/io.cpp @@ -3,10 +3,10 @@ auto RSP::readWord(u32 address, Thread& thread) -> u32 { if(address & 0x1000) return imem.read(address); else return dmem.read(address); } - return ioRead(address); + return ioRead(address, thread); } -auto RSP::ioRead(u32 address) -> u32 { +auto RSP::ioRead(u32 address, Thread &thread) -> u32 { address = (address & 0x3ffff) >> 2; n32 data; @@ -72,10 +72,10 @@ auto RSP::writeWord(u32 address, u32 data, Thread& thread) -> void { if(address & 0x1000) return recompiler.invalidate(address & 0xfff), imem.write(address, data); else return dmem.write(address, data); } - return ioWrite(address, data); + return ioWrite(address, data, thread); } -auto RSP::ioWrite(u32 address, u32 data_) -> void { +auto RSP::ioWrite(u32 address, u32 data_, Thread& thread) -> void { address = (address & 0x3ffff) >> 2; n32 data = data_; @@ -96,6 +96,8 @@ auto RSP::ioWrite(u32 address, u32 data_) -> void { dma.pending.length.bit(3,11) = data.bit( 3,11); dma.pending.count = data.bit(12,19); dma.pending.skip.bit(3,11) = data.bit(23,31); + dma.pending.originCpu = &thread != this; + dma.pending.originPc = dma.pending.originCpu ? cpu.ipu.pc : (u64)rsp.ipu.r[31].u32; dma.full.read = 1; dma.full.write = 0; dmaTransferStart(); @@ -106,6 +108,8 @@ auto RSP::ioWrite(u32 address, u32 data_) -> void { dma.pending.length.bit(3,11) = data.bit( 3,11); dma.pending.count = data.bit(12,19); dma.pending.skip.bit(3,11) = data.bit(23,31); + dma.pending.originCpu = &thread != this; + dma.pending.originPc = dma.pending.originCpu ? cpu.ipu.pc : (u64)rsp.ipu.r[31].u32; dma.full.write = 1; dma.full.read = 0; dmaTransferStart(); diff --git a/ares/n64/rsp/rsp.hpp b/ares/n64/rsp/rsp.hpp index 8ce2ce8478..bfd33d5db1 100644 --- a/ares/n64/rsp/rsp.hpp +++ b/ares/n64/rsp/rsp.hpp @@ -166,8 +166,8 @@ struct RSP : Thread, Memory::RCP { //io.cpp auto readWord(u32 address, Thread& thread) -> u32; auto writeWord(u32 address, u32 data, Thread& thread) -> void; - auto ioRead(u32 address) -> u32; - auto ioWrite(u32 address, u32 data) -> void; + auto ioRead(u32 address, Thread& thread) -> u32; + auto ioWrite(u32 address, u32 data, Thread& thread) -> void; //serialization.cpp auto serialize(serializer&) -> void; @@ -180,7 +180,9 @@ struct RSP : Thread, Memory::RCP { n12 length; n12 skip; n8 count; - + n64 originPc; + n1 originCpu; + auto serialize(serializer&) -> void; } pending, current; diff --git a/ares/n64/vi/vi.cpp b/ares/n64/vi/vi.cpp index cffd269552..0057c2372d 100644 --- a/ares/n64/vi/vi.cpp +++ b/ares/n64/vi/vi.cpp @@ -150,7 +150,7 @@ auto VI::refresh() -> void { auto line = screen->pixels(1).data() + (dy - vscan_start) * hscan_len; u32 x0 = vi.io.xsubpixel + vi.io.xscale * (dx0 - vi.io.hstart); for(i32 dx = dx0; dx < dx1; dx++) { - u16 data = rdram.ram.read(address + (x0 >> 10) * 2); + u16 data = rdram.ram.read(address + (x0 >> 10) * 2, "VI"); line[dx - hscan_start] = 1 << 24 | data >> 1; x0 += vi.io.xscale; } @@ -168,7 +168,7 @@ auto VI::refresh() -> void { auto line = screen->pixels(1).data() + (dy - vscan_start) * hscan_len; u32 x0 = vi.io.xsubpixel + vi.io.xscale * (dx0 - vi.io.hstart); for(i32 dx = dx0; dx < dx1; dx++) { - u32 data = rdram.ram.read(address + (x0 >> 10) * 4); + u32 data = rdram.ram.read(address + (x0 >> 10) * 4, "VI"); line[dx - hscan_start] = data >> 8; x0 += vi.io.xscale; }