diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 45d52eee..6ab671a2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -4,7 +4,6 @@ project(cores CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -add_subdirectory(gb) add_subdirectory(n64) add_library(cores diff --git a/src/core/gb/CMakeLists.txt b/src/core/gb/CMakeLists.txt deleted file mode 100644 index 269bf181..00000000 --- a/src/core/gb/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project(gb CXX) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -include(FetchContent) -FetchContent_Declare( - mio - GIT_REPOSITORY https://github.com/CocoSimone/mio - GIT_TAG master -) -FetchContent_Declare( - toml11 - GIT_REPOSITORY https://github.com/ToruNiina/toml11 - GIT_TAG dcfe39a783a94e8d52c885e5883a6fbb21529019 -) - -FetchContent_MakeAvailable(mio toml11) -find_package(fmt REQUIRED) - -add_library(gb - Core.hpp - Core.cpp - Cpu.hpp - Cpu.cpp - Ppu.hpp - Ppu.cpp - Mem.cpp - Mem.hpp - mbc.cpp - mbc.hpp - memory_regions.hpp - ../BaseCore.cpp - ../BaseCore.hpp) -target_include_directories(gb PRIVATE . .. ../../../external) -target_include_directories(gb PUBLIC ${mio_SOURCE_DIR}/include ${toml11_SOURCE_DIR}/include) -target_link_libraries(gb PRIVATE toml11::toml11 mio::mio fmt::fmt) diff --git a/src/core/gb/Core.cpp b/src/core/gb/Core.cpp deleted file mode 100644 index 5c994326..00000000 --- a/src/core/gb/Core.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -namespace natsukashii::gb::core { -Core::Core(const std::string& rom) { - mem.LoadROM(rom); -} - -void Core::Run() { - while(true) { - cpu.Step(mem); - } -} - -void Core::PollInputs(u32 windowID) { - SDL_Event event; - SDL_PollEvent(&event); - ShouldQuit() = event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == windowID; -} -} diff --git a/src/core/gb/Core.hpp b/src/core/gb/Core.hpp deleted file mode 100644 index 25d6e2d7..00000000 --- a/src/core/gb/Core.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace natsukashii::gb::core { -using namespace natsukashii::core; -struct Core : BaseCore { - ~Core() override = default; - explicit Core(const std::string&); - void Run() override; - void PollInputs(u32) override; -private: - Mem mem; - Cpu cpu; - // Ppu ppu; -}; -} diff --git a/src/core/gb/Cpu.cpp b/src/core/gb/Cpu.cpp deleted file mode 100644 index ac28c986..00000000 --- a/src/core/gb/Cpu.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -namespace natsukashii::gb::core { -Cpu::Cpu() {} - -void Cpu::Step(Mem& mem) { - FetchDecodeExecute(mem); -} - -void Cpu::FetchDecodeExecute(Mem& mem) { - u8 opcode = mem.Read8(regs.pc); - switch(opcode) { - case 0x01: case 0x11: case 0x21: case 0x31: // LD r16, u16 - SetR16<1>((opcode >> 4) & 3, mem.Consume16(regs.pc)); - break; - case 0xA8 ... 0xAF: // XOR A, r8 - regs.a() ^= GetR8(opcode & 7, mem); - regs.f().set(regs.a() == 0, false, false, false); - break; - case 0x02: case 0x12: case 0x22: case 0x32: { - u8 bits = (opcode >> 4) & 3; - mem.Write8(GetR16<2>(bits), regs.a()); - } break; - default: util::panic("Unimplemented opcode {:02X}, pc: {:04X}", opcode, regs.pc); - } - - regs.pc++; -} -} diff --git a/src/core/gb/Cpu.hpp b/src/core/gb/Cpu.hpp deleted file mode 100644 index 9947462e..00000000 --- a/src/core/gb/Cpu.hpp +++ /dev/null @@ -1,184 +0,0 @@ -#pragma once -#include -#include - -namespace natsukashii::gb::core { -template -struct Reg { - Reg() : raw(0) {}; - union { - T1 hi; - T2 lo; - }; - u16 raw = 0; -}; - -struct RegF { - RegF() : raw(0) {} - RegF(const u8& val) : raw(val) {} - - RegF& operator=(const u8& rhs) { - raw |= ((rhs >> 7) << 7); - raw |= ((rhs >> 6) << 6); - raw |= ((rhs >> 5) << 5); - raw |= ((rhs >> 4) << 4); - - return *this; - } - - bool zero() { return (raw >> 7) & 1; } - bool negative() { return (raw >> 6) & 1; } - bool halfcarry() { return (raw >> 5) & 1; } - bool carry() { return (raw >> 4) & 1; } - - void reset() { - zero(false); - negative(false); - halfcarry(false); - carry(false); - } - - void set(bool z, bool n, bool hc, bool ca) { - zero(z); - negative(n); - halfcarry(hc); - carry(ca); - } - - u8& get() { return raw; } -private: - u8 raw = 0; - - void zero(const bool& rhs) { - raw &= ~0xF; - raw |= (rhs << 7); - } - - void negative(const bool& rhs) { - raw &= ~0xF; - raw |= (rhs << 6); - } - - void halfcarry(const bool& rhs) { - raw &= ~0xF; - raw |= (rhs << 5); - } - - void carry(const bool& rhs) { - raw &= ~0xF; - raw |= (rhs << 4); - } -}; - -struct Registers { - Reg AF; - Reg BC; - Reg DE; - Reg HL; - u16 pc = 0, sp = 0; - - u8& a() { return AF.hi; } - RegF& f() { return AF.lo; } - u8& b() { return BC.hi; } - u8& c() { return BC.lo; } - u8& d() { return DE.hi; } - u8& e() { return DE.lo; } - u8& h() { return HL.hi; } - u8& l() { return HL.lo; } - - u16& af() { return AF.raw; } - u16& bc() { return BC.raw; } - u16& de() { return DE.raw; } - u16& hl() { return HL.raw; } -}; - -struct Cpu { - Cpu(); - void Step(Mem&); -private: - void FetchDecodeExecute(Mem& mem); - Registers regs; - - template - u16 GetR16(u8 bits) { - static_assert(group > 0 && group < 3, "Invalid GetR16 group"); - if constexpr (group == 1) { - switch(bits & 3) { - case 0: return regs.bc(); - case 1: return regs.de(); - case 2: return regs.hl(); - case 3: return regs.sp; - } - } else if constexpr (group == 2) { - switch(bits & 3) { - case 0: return regs.bc(); - case 1: return regs.de(); - case 2: return regs.hl()++; - case 3: return regs.hl()--; - } - } else if constexpr (group == 3) { - switch(bits & 3) { - case 0: return regs.bc(); - case 1: return regs.de(); - case 2: return regs.hl(); - case 3: return regs.af(); - } - } - return 0; - } - - template - void SetR16(u8 bits, u16 val) { - static_assert(group > 0 && group < 3, "Invalid SetR16 group"); - if constexpr (group == 1) { - switch(bits & 3) { - case 0: regs.bc() = val; break; - case 1: regs.de() = val; break; - case 2: regs.hl() = val; break; - case 3: regs.sp = val; break; - } - } else if constexpr (group == 2) { - switch(bits & 3) { - case 0: regs.bc() = val; break; - case 1: regs.de() = val; break; - case 2: regs.hl() = val; regs.hl()++; break; - case 3: regs.hl() = val; regs.hl()--; break; - } - } else if constexpr (group == 3) { - switch(bits & 3) { - case 0: regs.bc() = val; break; - case 1: regs.de() = val; break; - case 2: regs.hl() = val; break; - case 3: regs.af() = val; break; - } - } - } - - u8 GetR8(u8 bits, Mem& mem) { - switch(bits & 7) { - case 0: return regs.b(); - case 1: return regs.c(); - case 2: return regs.d(); - case 3: return regs.e(); - case 4: return regs.h(); - case 5: return regs.l(); - case 6: return mem.Read8(regs.hl()); - case 7: return regs.a(); - } - return 0; - } - - void SetR8(u8 bits, u8 val, Mem& mem) { - switch(bits & 7) { - case 0: regs.b() = val; break; - case 1: regs.c() = val; break; - case 2: regs.d() = val; break; - case 3: regs.e() = val; break; - case 4: regs.h() = val; break; - case 5: regs.l() = val; break; - case 6: return mem.Write8(regs.hl(), val); - case 7: regs.a() = val; break; - } - } -}; -} diff --git a/src/core/gb/Mem.cpp b/src/core/gb/Mem.cpp deleted file mode 100644 index 4b86f174..00000000 --- a/src/core/gb/Mem.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include -#include -#include -#include - -namespace natsukashii::gb::core { -Mem::Mem() { - auto data = toml::parse("config.toml"); - auto gb = toml::find(data, "gb"); - auto bootromPath = toml::find(gb, "bootrom"); - - LoadBootROM(bootromPath); -} - -void Mem::LoadBootROM(const std::string &filename) { - std::ifstream file(filename, std::ios::binary); - file.unsetf(std::ios::skipws); - - if(!file.is_open()) { - util::panic("Unable to open {}!", filename); - } - - file.read(reinterpret_cast(bootrom), 256); - file.close(); -} - -void Mem::LoadROM(const std::string& filename) { - std::ifstream file(filename, std::ios::binary); - file.unsetf(std::ios::skipws); - - if(!file.is_open()) { - util::panic("Unable to open {}!", filename); - } - - file.seekg(std::ios::end); - auto size = file.tellg(); - file.seekg(std::ios::beg); - - std::vector rom; - rom.reserve(size); - rom.insert(rom.begin(), - std::istream_iterator(file), - std::istream_iterator()); - - file.close(); - switch(rom[0x147]) { - case 0: - cart = std::make_unique(rom); - break; - default: - util::panic("Unimplemented cartridge type {:02X}!", rom[0x147]); - } -} - -u8 Mem::Read8(u16 addr) { - switch(addr) { - case ROM_RNG00: return io.BootROMMapped() ? bootrom[addr] : cart->Read(addr); - case ROM_RNGNN: return cart->Read(addr); - default: util::panic("[READ] Unimplemented addr: {:04X}", addr); - } - - return 0; -} - -void Mem::Write8(u16 addr, u8 val) { - switch(addr) { - case ROM_RNG00: case ROM_RNGNN: cart->Write(addr, val); - default: util::panic("[WRITE] Unimplemented addr: {:04X}", addr); - } -} - -u8 Mem::Consume8(u16& pc) { - u8 result = Read8(pc); - pc += 1; - return result; -} - -u16 Mem::Read16(u16 addr) { - return ((u16)Read8(addr) << 8) | Read8(addr + 1); -} - -void Mem::Write16(u16 addr, u16 val) { - Write8(addr, val >> 8); - Write8(addr + 1, val & 0xff); -} - -u16 Mem::Consume16(u16& pc) { - u8 hi = Consume8(pc); - return ((u16)hi << 8) | Consume8(pc); -} -} diff --git a/src/core/gb/Mem.hpp b/src/core/gb/Mem.hpp deleted file mode 100644 index d4b3309f..00000000 --- a/src/core/gb/Mem.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace natsukashii::gb::core { -struct IO { - [[nodiscard]] bool BootROMMapped() const { return ff50 != 1; } -private: - u8 ff50 = 0; -}; - -struct Mem { - Mem(); - void LoadROM(const std::string& filename); - u8 Read8(u16 addr); - void Write8(u16 addr, u8 val); - u8 Consume8(u16& pc); - u16 Read16(u16 addr); - void Write16(u16 addr, u16 val); - u16 Consume16(u16& pc); -private: - void LoadBootROM(const std::string& filename); - std::unique_ptr cart; - IO io{}; - u8 bootrom[BOOTROM_SIZE]{}; -}; -} diff --git a/src/core/gb/Ppu.cpp b/src/core/gb/Ppu.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/core/gb/Ppu.hpp b/src/core/gb/Ppu.hpp deleted file mode 100644 index e69de29b..00000000 diff --git a/src/core/gb/mbc.cpp b/src/core/gb/mbc.cpp deleted file mode 100644 index 1fd22424..00000000 --- a/src/core/gb/mbc.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -namespace natsukashii::gb::core { -NoMBC::NoMBC(std::vector rom) : data(std::move(rom)) {} - -u8 NoMBC::Read(u16 addr) { - return data[addr]; -} - -void NoMBC::Write(u16 addr, u8 val) { - util::panic("Writing to a NoMBC cartridge is not allowed! (Addr: {:04X})", addr); -} -} diff --git a/src/core/gb/mbc.hpp b/src/core/gb/mbc.hpp deleted file mode 100644 index 3ebf8e7c..00000000 --- a/src/core/gb/mbc.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include - -namespace natsukashii::gb::core { -struct Cartridge { - virtual u8 Read(u16 addr) { return 0; } - virtual void Write(u16 addr, u8 val) {} -}; - -struct NoMBC : public Cartridge { - explicit NoMBC(std::vector rom); - u8 Read(u16 addr) override; - void Write(u16 addr, u8 val) override; -private: - std::vector data{}; -}; -} diff --git a/src/core/gb/memory_regions.hpp b/src/core/gb/memory_regions.hpp deleted file mode 100644 index 3e06cc04..00000000 --- a/src/core/gb/memory_regions.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include - -#define BOOTROM_SIZE 512 -#define ROM_STR00 0x0000 -#define ROM_END00 ROM_STR00 + 0x3fff -#define ROM_STRNN ROM_END00 + 1 -#define ROM_ENDNN ROM_STRNN + 0x3fff -#define ROM_RNG00 ROM_STR00 ... ROM_END00 -#define ROM_RNGNN ROM_STRNN ... ROM_ENDNN -#define VRAM_START ROM_ENDNN + 1 -#define VRAM_END VRAM_START + 0x1fff -#define VRAM_RANGE VRAM_START ... VRAM_END -#define EXTRAM_START VRAM_END + 1 -#define EXTRAM_END EXTRAM_START + 0x1fff -#define EXTRAM_RANGE EXTRAM_START ... EXTRAM_END -#define WRAM_STR00 EXTRAM_END + 1 -#define WRAM_END00 WRAM_STR00 + 0xfff -#define WRAM_STRNN WRAM_END00 + 1 -#define WRAM_ENDNN WRAM_STRNN + 0xfff -#define WRAM_RNG00 WRAM_STR00 ... WRAM_END00 -#define WRAM_RNGNN WRAM_STRNN ... WRAM_ENDNN -#define OAM_START WRAM_ENDNN + 1 -#define OAM_END OAM_START + 0x9F -#define OAM_RANGE OAM_START ... OAM_END -#define UNUSABLE_START OAM_END + 1 -#define UNUSABLE_END UNUSABLE_START + 0x5F -#define UNUSABLE_RANGE UNUSABLE_START ... UNUSABLE_END -#define IO_START UNUSABLE_END + 1 -#define IO_END IO_START + 0x7F -#define IO_RANGE IO_START ... IO_END -#define HRAM_START IO_END + 1 -#define HRAM_END HRAM_START + 0x7E -#define HRAM_RANGE HRAM_START ... HRAM_END diff --git a/src/core/n64/core/CMakeLists.txt b/src/core/n64/core/CMakeLists.txt index a4d3f036..65d0f74b 100644 --- a/src/core/n64/core/CMakeLists.txt +++ b/src/core/n64/core/CMakeLists.txt @@ -3,6 +3,8 @@ project(n64-core) add_subdirectory(cpu) +add_subdirectory(../../../../external temp) + add_library(n64-core Cpu.hpp Cpu.cpp @@ -11,7 +13,17 @@ add_library(n64-core RDP.cpp RDP.hpp mmio/VI.cpp - mmio/VI.hpp mmio/Interrupt.hpp mmio/MI.cpp mmio/MI.hpp mmio/Interrupt.cpp MMIO.cpp MMIO.hpp RSP.cpp RSP.hpp rsp/decode.cpp rsp/instructions.cpp) + mmio/VI.hpp + mmio/Interrupt.hpp + mmio/MI.cpp + mmio/MI.hpp + mmio/Interrupt.cpp + MMIO.cpp + MMIO.hpp + RSP.cpp + RSP.hpp + rsp/decode.cpp + rsp/instructions.cpp) target_include_directories(n64-core PRIVATE . .. ../../ mmio) -target_link_libraries(n64-core PUBLIC n64-cpu) +target_link_libraries(n64-core PUBLIC n64-cpu parallel-rdp) diff --git a/src/core/n64/core/Cpu.cpp b/src/core/n64/core/Cpu.cpp index 8c45adc3..a0b74715 100644 --- a/src/core/n64/core/Cpu.cpp +++ b/src/core/n64/core/Cpu.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include +#include +#include #include namespace natsukashii::n64::core { @@ -49,22 +49,22 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) { regs.cop0.status.exl = true; regs.cop0.cause.copError = cop; - regs.cop0.cause.exceptionCode = code; + regs.cop0.cause.exceptionCode = static_cast(code); if(regs.cop0.status.bev) { util::panic("BEV bit set!\n"); } else { switch(code) { - case Interrupt: case TLBModification: - case AddressErrorLoad: case AddressErrorStore: - case InstructionBusError: case DataBusError: - case Syscall: case Breakpoint: - case ReservedInstruction: case CoprocessorUnusable: - case Overflow: case Trap: - case FloatingPointError: case Watch: + case ExceptionCode::Interrupt: case ExceptionCode::TLBModification: + case ExceptionCode::AddressErrorLoad: case ExceptionCode::AddressErrorStore: + case ExceptionCode::InstructionBusError: case ExceptionCode::DataBusError: + case ExceptionCode::Syscall: case ExceptionCode::Breakpoint: + case ExceptionCode::ReservedInstruction: case ExceptionCode::CoprocessorUnusable: + case ExceptionCode::Overflow: case ExceptionCode::Trap: + case ExceptionCode::FloatingPointError: case ExceptionCode::Watch: regs.SetPC((s64)((s32)0x80000180)); break; - case TLBLoad: case TLBStore: + case ExceptionCode::TLBLoad: case ExceptionCode::TLBStore: if(old_exl || regs.cop0.tlbError == INVALID) { regs.SetPC((s64)((s32)0x80000180)); } else if(Is64BitAddressing(regs.cop0, regs.cop0.badVaddr)) { @@ -73,14 +73,14 @@ void FireException(Registers& regs, ExceptionCode code, int cop, s64 pc) { regs.SetPC((s64)((s32)0x80000000)); } break; - default: util::panic("Unhandled exception! {}\n", code); + default: util::panic("Unhandled exception! {}\n", static_cast(code)); } } } inline void HandleInterrupt(Registers& regs) { if(ShouldServiceInterrupt(regs)) { - FireException(regs, Interrupt, 0, regs.pc); + FireException(regs, ExceptionCode::Interrupt, 0, regs.pc); } } @@ -89,9 +89,9 @@ void Cpu::Step(Mem& mem) { regs.prevDelaySlot = regs.delaySlot; regs.delaySlot = false; - CheckCompareInterrupt(mem.mmio.mi); + CheckCompareInterrupt(mem.mmio.mi, regs); - u32 instruction = mem.Read(regs, regs.pc, regs.pc); + u32 instruction = mem.Read(regs, regs.pc, regs.pc); HandleInterrupt(regs); diff --git a/src/core/n64/core/MMIO.hpp b/src/core/n64/core/MMIO.hpp index 2f8fdff3..fad4eec4 100644 --- a/src/core/n64/core/MMIO.hpp +++ b/src/core/n64/core/MMIO.hpp @@ -1,6 +1,8 @@ #pragma once -#include -#include +#include +#include +#include +#include namespace natsukashii::n64::core { struct Mem; @@ -10,6 +12,8 @@ struct MMIO { MMIO() = default; VI vi; MI mi; + RSP rsp; + RDP rdp; u32 Read(u32); void Write(Mem&, Registers& regs, u32, u32); diff --git a/src/core/n64/core/Mem.cpp b/src/core/n64/core/Mem.cpp index bb92f79a..4b79a55a 100644 --- a/src/core/n64/core/Mem.cpp +++ b/src/core/n64/core/Mem.cpp @@ -47,6 +47,8 @@ inline bool MapVAddr(Registers& regs, TLBAccessType accessType, u32 vaddr, u32& default: util::panic("Should never end up in default case in map_vaddr! ({:08X})\n", vaddr); } + + return false; } template @@ -72,16 +74,13 @@ T Mem::Read(Registers& regs, u32 vaddr, s64 pc) { case 0x80000000 ... 0xFFFFFFFF: case 0x1FC00800 ... 0x7FFFFFFF: return 0; default: util::panic("Unimplemented {}-bit read at address {:08X} (PC = {:016X})\n", sizeof(T) * 8, paddr, regs.pc); } + return 0; } -template u8 Mem::Read(Registers& regs, u32 vaddr, s64 pc); -template u16 Mem::Read(Registers& regs, u32 vaddr, s64 pc); -template u32 Mem::Read(Registers& regs, u32 vaddr, s64 pc); -template u64 Mem::Read(Registers& regs, u32 vaddr, s64 pc); -template u8 Mem::Read(Registers& regs, u32 vaddr, s64 pc); -template u16 Mem::Read(Registers& regs, u32 vaddr, s64 pc); -template u32 Mem::Read(Registers& regs, u32 vaddr, s64 pc); -template u64 Mem::Read(Registers& regs, u32 vaddr, s64 pc); +template u8 Mem::Read(Registers& regs, u32 vaddr, s64 pc); +template u16 Mem::Read(Registers& regs, u32 vaddr, s64 pc); +template u32 Mem::Read(Registers& regs, u32 vaddr, s64 pc); +template u64 Mem::Read(Registers& regs, u32 vaddr, s64 pc); template void Mem::Write(Registers& regs, u32 vaddr, T val, s64 pc) { @@ -108,12 +107,8 @@ void Mem::Write(Registers& regs, u32 vaddr, T val, s64 pc) { } } -template void Mem::Write(Registers& regs, u32 vaddr, u8 val, s64 pc); -template void Mem::Write(Registers& regs, u32 vaddr, u16 val, s64 pc); -template void Mem::Write(Registers& regs, u32 vaddr, u32 val, s64 pc); -template void Mem::Write(Registers& regs, u32 vaddr, u64 val, s64 pc); -template void Mem::Write(Registers& regs, u32 vaddr, u8 val, s64 pc); -template void Mem::Write(Registers& regs, u32 vaddr, u16 val, s64 pc); -template void Mem::Write(Registers& regs, u32 vaddr, u32 val, s64 pc); -template void Mem::Write(Registers& regs, u32 vaddr, u64 val, s64 pc); +template void Mem::Write(Registers& regs, u32 vaddr, u8 val, s64 pc); +template void Mem::Write(Registers& regs, u32 vaddr, u16 val, s64 pc); +template void Mem::Write(Registers& regs, u32 vaddr, u32 val, s64 pc); +template void Mem::Write(Registers& regs, u32 vaddr, u64 val, s64 pc); } \ No newline at end of file diff --git a/src/core/n64/core/Mem.hpp b/src/core/n64/core/Mem.hpp index f6e39ff2..7d928eaf 100644 --- a/src/core/n64/core/Mem.hpp +++ b/src/core/n64/core/Mem.hpp @@ -13,11 +13,12 @@ struct Mem { [[nodiscard]] auto GetRDRAM() -> u8* { return rdram.data(); } - template + template T Read(Registers&, u32, s64); - template + template void Write(Registers&, u32, T, s64); private: + friend struct Cpu; friend struct RSP; MMIO mmio; std::vector cart, rdram, sram; diff --git a/src/core/n64/core/RDP.cpp b/src/core/n64/core/RDP.cpp index a967366a..517c0b15 100644 --- a/src/core/n64/core/RDP.cpp +++ b/src/core/n64/core/RDP.cpp @@ -1,8 +1,8 @@ -#include +#include #include -#include +#include #include <../../../frontend/ParallelRDPWrapper.hpp> -#include +#include namespace natsukashii::n64::core { static const int cmd_lens[64] = { @@ -12,11 +12,12 @@ static const int cmd_lens[64] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; -u32 RDP::Read(u32 addr) { +auto RDP::Read(u32 addr) const -> u32{ switch(addr) { case 0x0410000C: return dpc.status.raw; default: util::panic("Unhandled DP Command Registers read (addr: {:08X})\n", addr); } + return 0; } void RDP::Write(u32 addr, u32 val) { diff --git a/src/core/n64/core/RDP.hpp b/src/core/n64/core/RDP.hpp index b86449bf..9926ca1f 100644 --- a/src/core/n64/core/RDP.hpp +++ b/src/core/n64/core/RDP.hpp @@ -53,7 +53,7 @@ struct RDP { RDP() = default; - u32 Read(u32 addr); + auto Read(u32 addr) const -> u32; void Write(u32 addr, u32 val); void StatusWrite(u32 val); void RunCommand(MI& mi, Registers& regs, RSP& rsp); diff --git a/src/core/n64/core/RSP.cpp b/src/core/n64/core/RSP.cpp index 70294de7..2888f85e 100644 --- a/src/core/n64/core/RSP.cpp +++ b/src/core/n64/core/RSP.cpp @@ -1,7 +1,7 @@ -#include +#include #include #include -#include "Interrupt.hpp" +#include namespace natsukashii::n64::core { void RSP::StepRSP(MI& mi, Registers& regs, RDP& rdp) { @@ -15,7 +15,7 @@ void RSP::StepRSP(MI& mi, Registers& regs, RDP& rdp) { } } -u32 RSP::Read(u32 addr) { +auto RSP::Read(u32 addr) const -> u32{ switch (addr) { case 0x04040000: return spDMASPAddr.raw & 0xFFFFF8; case 0x04040004: return spDMADRAMAddr.raw & 0x1FF8; @@ -26,6 +26,7 @@ u32 RSP::Read(u32 addr) { case 0x04080000: return pc & 0xFFF; default: util::panic("Unimplemented SP register read %08X\n", addr); } + return 0; } template diff --git a/src/core/n64/core/RSP.hpp b/src/core/n64/core/RSP.hpp index a83203f9..fe36162a 100644 --- a/src/core/n64/core/RSP.hpp +++ b/src/core/n64/core/RSP.hpp @@ -1,6 +1,6 @@ #pragma once -#include -#include +#include +#include #include namespace natsukashii::n64::core { @@ -107,7 +107,7 @@ struct Registers; struct RSP { RSP() = default; void StepRSP(MI& mi, Registers& regs, RDP& rdp); - u32 Read(u32 addr); + auto Read(u32 addr) const -> u32; void Write(Mem& mem, Registers& regs, u32 addr, u32 value); void Exec(MI& mi, Registers& regs, RDP& rdp, u32 instr); SPStatus spStatus{.raw = 1}; @@ -156,7 +156,7 @@ struct RSP { } return val; } -private: + void add(u32 instr); void addi(u32 instr); void and_(u32 instr); @@ -186,7 +186,7 @@ private: void vsar(u32 instr); void mfc0(RDP& rdp, u32 instr); void mtc0(MI& mi, Registers& regs, RDP& rdp, u32 instr); - +private: inline void branch(u16 address, bool cond) { if(cond) { nextPC = address & 0xFFF; diff --git a/src/core/n64/core/mmio/MI.cpp b/src/core/n64/core/mmio/MI.cpp index 8292636d..1b6af136 100644 --- a/src/core/n64/core/mmio/MI.cpp +++ b/src/core/n64/core/mmio/MI.cpp @@ -12,7 +12,7 @@ MI::MI() { miMode = 0; } -u32 MI::Read(u32 paddr) { +auto MI::Read(u32 paddr) const -> u32 { switch(paddr & 0xF) { case 0x0: return miMode & 0x3FF; case 0x4: return MI_VERSION_REG; @@ -20,6 +20,7 @@ u32 MI::Read(u32 paddr) { case 0xC: return miIntrMask.raw & 0x3F; default: util::panic("Unhandled MI[%08X] read\n", paddr); } + return 0; } void MI::Write(Registers& regs, u32 paddr, u32 val) { diff --git a/src/core/n64/core/mmio/MI.hpp b/src/core/n64/core/mmio/MI.hpp index 39bd332d..7948973f 100644 --- a/src/core/n64/core/mmio/MI.hpp +++ b/src/core/n64/core/mmio/MI.hpp @@ -20,7 +20,7 @@ struct Registers; struct MI { MI(); - u32 Read(u32); + [[nodiscard]] auto Read(u32) const -> u32; void Write(Registers& regs, u32, u32); u32 miMode; diff --git a/src/core/n64/core/mmio/VI.cpp b/src/core/n64/core/mmio/VI.cpp index 2f99a5ae..1e01da24 100644 --- a/src/core/n64/core/mmio/VI.cpp +++ b/src/core/n64/core/mmio/VI.cpp @@ -18,7 +18,7 @@ VI::VI () { cyclesPerHalfline = 1000; } -u32 VI::Read(u32 paddr) { +u32 VI::Read(u32 paddr) const { switch(paddr) { case 0x04400000: return status.raw; case 0x04400004: return origin; @@ -37,6 +37,7 @@ u32 VI::Read(u32 paddr) { default: util::panic("Unimplemented VI[%08X] read\n", paddr); } + return 0; } void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) { diff --git a/src/core/n64/core/mmio/VI.hpp b/src/core/n64/core/mmio/VI.hpp index fd544668..1f7da506 100644 --- a/src/core/n64/core/mmio/VI.hpp +++ b/src/core/n64/core/mmio/VI.hpp @@ -65,7 +65,7 @@ struct Registers; struct VI { VI(); - u32 Read(u32); + [[nodiscard]] u32 Read(u32) const; void Write(MI&, Registers&, u32, u32); VIScale xscale{}, yscale{}; VIVideo hvideo{}, vvideo{}; diff --git a/src/core/n64/core/rsp/decode.cpp b/src/core/n64/core/rsp/decode.cpp index 021aaaba..c3df6300 100644 --- a/src/core/n64/core/rsp/decode.cpp +++ b/src/core/n64/core/rsp/decode.cpp @@ -1,24 +1,25 @@ -#include +#include #include +#include namespace natsukashii::n64::core { inline void special(RSP& rsp, u32 instr) { u8 mask = instr & 0x3f; switch(mask) { - case 0x00: rsp_sll(rsp, instr); break; - case 0x04: rsp_sllv(rsp, instr); break; - case 0x08: rsp_jr(rsp, instr); break; + case 0x00: rsp.sll(instr); break; + case 0x04: rsp.sllv(instr); break; + case 0x08: rsp.jr(instr); break; case 0x0C: case 0x0D: rsp.spStatus.halt = true; rsp.spStatus.broke = true; break; case 0x20: case 0x21: - rsp_add(rsp, instr); + rsp.add(instr); break; - case 0x24: rsp_and_(rsp, instr); break; - case 0x25: rsp_or_(rsp, instr); break; - case 0x27: rsp_nor(rsp, instr); break; + case 0x24: rsp.and_(instr); break; + case 0x25: rsp.or_(instr); break; + case 0x27: rsp.nor(instr); break; default: util::panic("Unhandled RSP special instruction %d %d\n", (mask >> 3) & 7, mask & 7); } } @@ -26,8 +27,8 @@ inline void special(RSP& rsp, u32 instr) { inline void regimm(RSP& rsp, u32 instr) { u8 mask = ((instr >> 16) & 0x1F); switch(mask) { - case 0x00: rsp_b(rsp, instr, (s32)rsp.gpr[RS(instr)] < 0); break; - case 0x01: rsp_b(rsp, instr, (s32)rsp.gpr[RS(instr)] >= 0); break; + case 0x00: rsp.b(instr, (s32)rsp.gpr[RS(instr)] < 0); break; + case 0x01: rsp.b(instr, (s32)rsp.gpr[RS(instr)] >= 0); break; default: util::panic("Unhandled RSP regimm instruction %d %d\n", (mask >> 3) & 3, mask & 7); } } @@ -35,7 +36,7 @@ inline void regimm(RSP& rsp, u32 instr) { inline void lwc2(RSP& rsp, u32 instr) { u8 mask = (instr >> 11) & 0x1F; switch(mask) { - case 0x04: rsp_lqv(rsp, instr); break; + case 0x04: rsp.lqv(instr); break; default: util::panic("Unhandled RSP LWC2 %d %d\n", (mask >> 3) & 3, mask & 7); } } @@ -43,7 +44,7 @@ inline void lwc2(RSP& rsp, u32 instr) { inline void swc2(RSP& rsp, u32 instr) { u8 mask = (instr >> 11) & 0x1F; switch(mask) { - case 0x04: rsp_sqv(rsp, instr); break; + case 0x04: rsp.sqv(instr); break; default: util::panic("Unhandled RSP SWC2 %d %d\n", (mask >> 3) & 3, mask & 7); } } @@ -54,15 +55,15 @@ inline void cop2(RSP& rsp, u32 instr) { switch(mask) { case 0x00: switch(mask_sub) { - case 0x02: rsp_cfc2(rsp, instr); break; - default: logfatal("Unhandled RSP COP2 sub %d %d\n", (mask_sub >> 3) & 3, mask_sub & 3); + case 0x02: rsp.cfc2(instr); break; + default: util::panic("Unhandled RSP COP2 sub %d %d\n", (mask_sub >> 3) & 3, mask_sub & 3); } break; - case 0x13: rsp_vabs(rsp, instr); break; - case 0x1D: rsp_vsar(rsp, instr); break; - case 0x21: rsp_veq(rsp, instr); break; - case 0x22: rsp_vne(rsp, instr); break; - case 0x33: rsp_vmov(rsp, instr); break; + case 0x13: rsp.vabs(instr); break; + case 0x1D: rsp.vsar(instr); break; + case 0x21: rsp.veq(instr); break; + case 0x22: rsp.vne(instr); break; + case 0x33: rsp.vmov(instr); break; default: util::panic("Unhandled RSP COP2 %d %d\n", (mask >> 3) & 7, mask & 7); } } @@ -70,8 +71,8 @@ inline void cop2(RSP& rsp, u32 instr) { inline void cop0(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u32 instr) { u8 mask = (instr >> 21) & 0x1F; switch(mask) { - case 0x00: rsp_mfc0(rsp, rdp, instr); break; - case 0x04: rsp_mtc0(mi, regs, rsp, rdp, instr); break; + case 0x00: rsp.mfc0(rdp, instr); break; + case 0x04: rsp.mtc0(mi, regs, rdp, instr); break; default: util::panic("Unhandled RSP COP0 %d %d\n", (mask >> 3) & 3, mask & 7); } } @@ -81,22 +82,22 @@ void RSP::Exec(MI &mi, Registers ®s, RDP &rdp, u32 instr) { switch(mask) { case 0x00: special(*this, instr); break; case 0x01: regimm(*this, instr); break; - case 0x02: rsp_j(instr); break; - case 0x03: rsp_jal(instr); break; - case 0x04: rsp_b(instr, gpr[RT(instr)] == gpr[RS(instr)]); break; - case 0x05: rsp_b(instr, gpr[RT(instr)] != gpr[RS(instr)]); break; - case 0x07: rsp_b(instr, gpr[RS(instr)] > 0); break; - case 0x08: case 0x09: rsp_addi(instr); break; - case 0x0C: rsp_andi(instr); break; - case 0x0D: rsp_ori(instr); break; - case 0x0F: rsp_lui(instr); break; + case 0x02: j(instr); break; + case 0x03: jal(instr); break; + case 0x04: b(instr, gpr[RT(instr)] == gpr[RS(instr)]); break; + case 0x05: b(instr, gpr[RT(instr)] != gpr[RS(instr)]); break; + case 0x07: b(instr, gpr[RS(instr)] > 0); break; + case 0x08: case 0x09: addi(instr); break; + case 0x0C: andi(instr); break; + case 0x0D: ori(instr); break; + case 0x0F: lui(instr); break; case 0x10: cop0(mi, regs, *this, rdp, instr); break; case 0x12: cop2(*this, instr); break; - case 0x21: rsp_lh(instr); break; - case 0x23: rsp_lw(instr); break; - case 0x28: rsp_sb(instr); break; - case 0x29: rsp_sh(instr); break; - case 0x2B: rsp_sw(instr); break; + case 0x21: lh(instr); break; + case 0x23: lw(instr); break; + case 0x28: sb(instr); break; + case 0x29: sh(instr); break; + case 0x2B: sw(instr); break; case 0x32: lwc2(*this, instr); break; case 0x3A: swc2(*this, instr); break; default: util::panic("Unhandled RSP instruction %d %d\n", (mask >> 3) & 7, mask & 7); diff --git a/src/core/n64/core/rsp/instructions.cpp b/src/core/n64/core/rsp/instructions.cpp index cb3699d7..b6b623fd 100644 --- a/src/core/n64/core/rsp/instructions.cpp +++ b/src/core/n64/core/rsp/instructions.cpp @@ -20,7 +20,7 @@ inline void ReleaseSemaphore(RSP& rsp) { rsp.semaphore = false; } -inline u32 GetCop0Reg(RSP& rsp, RDP& rdp, u8 index) { +inline auto GetCop0Reg(RSP& rsp, RDP& rdp, u8 index) -> u32{ switch(index) { case 4: return rsp.spStatus.raw; case 5: return rsp.spStatus.dmaFull; @@ -29,6 +29,7 @@ inline u32 GetCop0Reg(RSP& rsp, RDP& rdp, u8 index) { case 11: return rdp.dpc.status.raw; default: util::panic("Unhandled RSP COP0 register read at index {}\n", index); } + return 0; } inline void SetCop0Reg(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u8 index, u32 val) { @@ -49,7 +50,7 @@ inline void SetCop0Reg(MI& mi, Registers& regs, RSP& rsp, RDP& rdp, u8 index, u3 break; case 9: rdp.dpc.end = val & 0xFFFFF8; - rdp.RunCommand(mi, regs, rdp, rsp); + rdp.RunCommand(mi, regs, rsp); break; case 11: rdp.StatusWrite(val); break; default: util::panic("Unhandled RSP COP0 register write at index {}\n", index); diff --git a/src/core/util.hpp b/src/core/util.hpp index f3301c29..c524c31b 100644 --- a/src/core/util.hpp +++ b/src/core/util.hpp @@ -39,6 +39,7 @@ constexpr void info(const std::string& fmt, Args... args) { template auto GetSwapFunc(T num) -> T { + static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "GetSwapFunc used with invalid size!"); if constexpr(sizeof(T) == 2) { if constexpr(HToBE) { return htobe16(num); @@ -59,17 +60,26 @@ auto GetSwapFunc(T num) -> T { template inline T ReadAccess(u8* data, u32 index) { - static_assert(sizeof(T) != 2 || sizeof(T) != 4 || sizeof(T) != 8); - T result = 0; - memcpy(&result, &data[index], sizeof(T)); - return GetSwapFunc(result); + if constexpr(sizeof(T) == 1) { + return data[index]; + } else { + static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8); + T result = 0; + memcpy(&result, &data[index], sizeof(T)); + return GetSwapFunc(result); + } } template inline void WriteAccess(u8* data, u32 index, T val) { - static_assert(sizeof(T) != 2 || sizeof(T) != 4 || sizeof(T) != 8); - T temp = GetSwapFunc(val); - memcpy(&data[index], &temp, sizeof(T)); + if constexpr(sizeof(T) == 1) { + data[index] = val; + return; + } else { + static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8); + T temp = GetSwapFunc(val); + memcpy(&data[index], &temp, sizeof(T)); + } } #define Z64 0x80371240 diff --git a/src/frontend/ParallelRDPWrapper.hpp b/src/frontend/ParallelRDPWrapper.hpp index 9574aed8..18c71ed3 100644 --- a/src/frontend/ParallelRDPWrapper.hpp +++ b/src/frontend/ParallelRDPWrapper.hpp @@ -1,9 +1,9 @@ #pragma once -#include "n64/Core.hpp" -#include "parallel-rdp-standalone/vulkan/wsi.hpp" +#include +#include #include -#include "n64/core/mmio/VI.hpp" -#include "BaseCore.hpp" +#include +#include enum class Platform : bool { SDL, Qt diff --git a/src/frontend/sdl/CMakeLists.txt b/src/frontend/sdl/CMakeLists.txt index 9c550106..91217e3f 100644 --- a/src/frontend/sdl/CMakeLists.txt +++ b/src/frontend/sdl/CMakeLists.txt @@ -15,7 +15,5 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(argparse) -add_subdirectory(../../../external temp) - -target_include_directories(natsukashii-sdl PRIVATE . ../../core ../../core/gb ../../core/n64 ../../core/n64/core ../../core/n64/core/cpu/registers) -target_link_libraries(natsukashii-sdl PRIVATE cores argparse::argparse SDL2 parallel-rdp) +target_include_directories(natsukashii-sdl PRIVATE . ../../core) +target_link_libraries(natsukashii-sdl PRIVATE cores argparse::argparse SDL2) diff --git a/src/frontend/sdl/Frontend.cpp b/src/frontend/sdl/Frontend.cpp index 35117a41..2fec5146 100644 --- a/src/frontend/sdl/Frontend.cpp +++ b/src/frontend/sdl/Frontend.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include "../ParallelRDPWrapper.hpp" @@ -15,13 +14,7 @@ App::~App() { App::App(const std::string& rom, const std::string& selectedCore) { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_VIDEO_VULKAN); - if(selectedCore == "gb") { - window = SDL_CreateWindow("natukashii", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_RESIZABLE); - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); - SDL_RenderSetLogicalSize(renderer, 160, 144); - windowID = SDL_GetWindowID(window); - g_Core = std::make_unique(rom); - } else if(selectedCore == "n64") { + if(selectedCore == "n64") { window = SDL_CreateWindow("natukashii", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_RESIZABLE | SDL_WINDOW_VULKAN); windowID = SDL_GetWindowID(window); if(volkInitialize() != VK_SUCCESS) { @@ -29,7 +22,7 @@ App::App(const std::string& rom, const std::string& selectedCore) { } g_Core = std::make_unique(Platform::SDL, rom); } else { - util::panic("Unimplemented core!"); + util::panic("Unimplemented core \"{}\"!", selectedCore); } } diff --git a/src/frontend/sdl/Frontend.hpp b/src/frontend/sdl/Frontend.hpp index e8442219..a32282c8 100644 --- a/src/frontend/sdl/Frontend.hpp +++ b/src/frontend/sdl/Frontend.hpp @@ -2,7 +2,6 @@ #define SDL_MAIN_HANDLED #include #include -#include #include #include #include