Fix parallel-rdp integration and reset whole state upon loading rom

This commit is contained in:
CocoSimone
2022-08-13 11:44:35 +02:00
parent ed34d9c9ba
commit e2313c212c
41 changed files with 250 additions and 92 deletions

View File

@@ -92,11 +92,11 @@ public:
} }
uint32_t get_surface_width() override { uint32_t get_surface_width() override {
return 800; return 640;
} }
uint32_t get_surface_height() override { uint32_t get_surface_height() override {
return 600; return 480;
} }
bool alive(Vulkan::WSI &wsi_) override { bool alive(Vulkan::WSI &wsi_) override {
@@ -106,6 +106,15 @@ public:
void poll_input() override { } void poll_input() override { }
void event_frame_tick(double frame, double elapsed) override { } void event_frame_tick(double frame, double elapsed) override { }
const VkApplicationInfo *get_application_info() override {
return &appInfo;
}
VkApplicationInfo appInfo {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.apiVersion = VK_API_VERSION_1_1
};
}; };
Program* fullscreen_quad_program; Program* fullscreen_quad_program;

View File

@@ -1,5 +1,4 @@
#pragma once #pragma once
#define VULKAN_DEBUG
#include <Core.hpp> #include <Core.hpp>
#include <wsi.hpp> #include <wsi.hpp>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
@@ -26,7 +25,6 @@ class SDLParallelRdpWindowInfo : public ParallelRdpWindowInfo {
} }
}; };
static u32 windowID;
VkQueue GetGraphicsQueue(); VkQueue GetGraphicsQueue();
VkInstance GetVkInstance(); VkInstance GetVkInstance();
VkPhysicalDevice GetVkPhysicalDevice(); VkPhysicalDevice GetVkPhysicalDevice();

View File

@@ -3,6 +3,8 @@ project(natsukashii)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED true) set(CMAKE_CXX_STANDARD_REQUIRED true)
add_compile_definitions(VULKAN_DEBUG)
add_subdirectory(n64) add_subdirectory(n64)
add_subdirectory(frontend) add_subdirectory(frontend)
@@ -12,3 +14,4 @@ add_executable(natsukashii main.cpp)
target_link_libraries(natsukashii PUBLIC frontend n64 fmt) target_link_libraries(natsukashii PUBLIC frontend n64 fmt)
target_include_directories(natsukashii PUBLIC . ../external) target_include_directories(natsukashii PUBLIC . ../external)
target_compile_options(natsukashii PUBLIC -Wpedantic -Wimplicit-fallthrough -Wextra -Wall)

View File

@@ -9,11 +9,12 @@ void App::Run() {
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
//ImGui_ImplSDL2_ProcessEvent(&event); //ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT) switch(event.type) {
done = true; case SDL_QUIT: done = true; break;
if (window.gotClosed(event)) case SDL_WINDOWEVENT:
done = true; done = window.gotClosed(event);
if(event.type == SDL_KEYDOWN) { break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) { switch(event.key.keysym.sym) {
case SDLK_o: { case SDLK_o: {
nfdchar_t* outpath; nfdchar_t* outpath;
@@ -24,20 +25,19 @@ void App::Run() {
NFD_FreePath(outpath); NFD_FreePath(outpath);
} }
} break; } break;
} } break;
} }
core.PollInputs(event); core.PollInputs(event);
} }
if(core.romLoaded) if(core.romLoaded) {
core.Run(); core.Run(window);
if(core.romLoaded)
UpdateScreenParallelRdp(window, core.GetVI()); UpdateScreenParallelRdp(window, core.GetVI());
else } else {
UpdateScreenParallelRdpNoGame(window); UpdateScreenParallelRdpNoGame(window);
}
SDL_Delay(16); SDL_Delay(1);
} }
} }

View File

@@ -1,5 +1,4 @@
#pragma once #pragma once
#include <Core.hpp>
#include <imgui/Window.hpp> #include <imgui/Window.hpp>
struct App { struct App {

View File

@@ -12,8 +12,7 @@ Window::Window(n64::Core& core) {
} }
[[nodiscard]] bool Window::gotClosed(SDL_Event event) { [[nodiscard]] bool Window::gotClosed(SDL_Event event) {
return event.type == SDL_WINDOWEVENT return event.window.event == SDL_WINDOWEVENT_CLOSE
&& event.window.event == SDL_WINDOWEVENT_CLOSE
&& event.window.windowID == SDL_GetWindowID(window); && event.window.windowID == SDL_GetWindowID(window);
} }
@@ -177,18 +176,18 @@ Window::~Window() {
vkDestroyInstance(instance, nullptr); vkDestroyInstance(instance, nullptr);
} }
ImDrawData* Window::Present() { ImDrawData* Window::Present(n64::Core& core) {
//ImGui_ImplVulkan_NewFrame(); //ImGui_ImplVulkan_NewFrame();
//ImGui_ImplSDL2_NewFrame(window); //ImGui_ImplSDL2_NewFrame(window);
//ImGui::NewFrame(); //ImGui::NewFrame();
// //
Render(); Render(core);
//ImGui::Render(); //ImGui::Render();
return ImGui::GetDrawData(); return ImGui::GetDrawData();
} }
void Window::Render() { void Window::Render(n64::Core& core) {
ImGui::BeginMainMenuBar(); ImGui::BeginMainMenuBar();
if(ImGui::BeginMenu("File")) { if(ImGui::BeginMenu("File")) {
if(ImGui::BeginMenu("Open")) { if(ImGui::BeginMenu("Open")) {

View File

@@ -10,15 +10,14 @@
struct Window { struct Window {
explicit Window(n64::Core& core); explicit Window(n64::Core& core);
~Window(); ~Window();
ImDrawData* Present(); ImDrawData* Present(n64::Core& core);
[[nodiscard]] bool gotClosed(SDL_Event event); [[nodiscard]] bool gotClosed(SDL_Event event);
private: private:
SDL_Window* window; SDL_Window* window;
n64::Core core;
void InitSDL(); void InitSDL();
void InitImgui(); void InitImgui();
void Render(); void Render(n64::Core& core);
VkInstance instance{}; VkInstance instance{};
VkPhysicalDevice physicalDevice{}; VkPhysicalDevice physicalDevice{};

View File

@@ -1,8 +1,8 @@
#define SDL_MAIN_HANDLED #define SDL_MAIN_HANDLED
#include <frontend/App.hpp> #include <frontend/App.hpp>
int main() { int main(int argc, char* argv[]) {
App* app = new App; App app;
app->Run(); app.Run();
return 0; return 0;
} }

View File

@@ -12,6 +12,7 @@ target_link_libraries(n64 PUBLIC core)
target_include_directories(n64 PUBLIC target_include_directories(n64 PUBLIC
. .
.. ..
../frontend/imgui
../../external ../../external
../../external/imgui/imgui ../../external/imgui/imgui
../../external/imgui/imgui/backends ../../external/imgui/imgui/backends

View File

@@ -1,12 +1,25 @@
#include <Core.hpp> #include <Core.hpp>
#include <ParallelRDPWrapper.hpp>
#include <Window.hpp>
namespace n64 { namespace n64 {
Core::Core() {
Reset();
}
void Core::Reset() {
cpu.Reset();
mem.Reset();
romLoaded = false;
}
void Core::LoadROM(const std::string& rom) { void Core::LoadROM(const std::string& rom) {
Reset();
mem.LoadROM(rom); mem.LoadROM(rom);
romLoaded = true; romLoaded = true;
} }
void Core::Run() { void Core::Run(Window& window) {
MMIO& mmio = mem.mmio; MMIO& mmio = mem.mmio;
for(mmio.vi.current = 0; mmio.vi.current < 262; mmio.vi.current++) { for(mmio.vi.current = 0; mmio.vi.current < 262; mmio.vi.current++) {
for (int i = 0; i < 6000; i++) { for (int i = 0; i < 6000; i++) {

View File

@@ -4,12 +4,14 @@
#include <Mem.hpp> #include <Mem.hpp>
#include <string> #include <string>
struct Window;
namespace n64 { namespace n64 {
struct Core { struct Core {
~Core() = default; ~Core() = default;
Core() = default; Core();
void Reset();
void LoadROM(const std::string&); void LoadROM(const std::string&);
void Run(); void Run(Window&);
void PollInputs(SDL_Event); void PollInputs(SDL_Event);
VI& GetVI() { return mem.mmio.vi; } VI& GetVI() { return mem.mmio.vi; }
u8* GetRDRAM() { return mem.rdram.data(); } u8* GetRDRAM() { return mem.rdram.data(); }

View File

@@ -4,18 +4,18 @@
#include <util.hpp> #include <util.hpp>
namespace n64 { namespace n64 {
void Cpu::Reset() {
regs.Reset();
}
Cpu::Cpu() { Cpu::Cpu() {
#ifndef NDEBUG
if (cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle)) { if (cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle)) {
util::panic("Could not initialize capstone!\n"); util::panic("Could not initialize capstone!\n");
} }
#endif
} }
Cpu::~Cpu() { Cpu::~Cpu() {
#ifndef NDEBUG
cs_close(&handle); cs_close(&handle);
#endif
} }
inline bool ShouldServiceInterrupt(Registers& regs) { inline bool ShouldServiceInterrupt(Registers& regs) {
@@ -99,21 +99,16 @@ inline void HandleInterrupt(Registers& regs) {
} }
void Cpu::LogInstruction(u32 instruction) { void Cpu::LogInstruction(u32 instruction) {
#ifndef NDEBUG count = cs_disasm(handle, reinterpret_cast<u8*>(&instruction), 4, regs.pc, 0, &insn);
/*u8 code[4]{};
u32 bswapped = be32toh(instruction);
memcpy(code, &instruction, 4);
count = cs_disasm(handle, code, 4, regs.pc, 0, &insn);
if (count > 0) { if (count > 0) {
for(auto j = 0; j < count; j++) { for(auto j = 0; j < count; j++) {
printf("%016lX:\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); util::logdebug("0x{:016X}:\t{}\t\t{}\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
} }
cs_free(insn, count); cs_free(insn, count);
} else { } else {
util::panic("Failed to disassemble {:08X}!", instruction); util::logdebug("Failed to disassemble 0x{:08X}!", instruction);
}*/ }
#endif
} }
void Cpu::Step(Mem& mem) { void Cpu::Step(Mem& mem) {
@@ -123,8 +118,14 @@ void Cpu::Step(Mem& mem) {
CheckCompareInterrupt(mem.mmio.mi, regs); CheckCompareInterrupt(mem.mmio.mi, regs);
static int count = 0;
if(regs.gpr[30] == -1 && count < 1) {
util::logdebug("Test passed!\n");
count++;
}
u32 instruction = mem.Read<u32>(regs, regs.pc, regs.pc); u32 instruction = mem.Read<u32>(regs, regs.pc, regs.pc);
LogInstruction(instruction); //LogInstruction(instruction);
HandleInterrupt(regs); HandleInterrupt(regs);

View File

@@ -1,22 +1,19 @@
#pragma once #pragma once
#include <Registers.hpp> #include <Registers.hpp>
#include <Mem.hpp> #include <Mem.hpp>
#ifndef NDEBUG
#include <capstone/capstone.h> #include <capstone/capstone.h>
#endif
namespace n64 { namespace n64 {
struct Cpu { struct Cpu {
Cpu(); Cpu();
~Cpu(); ~Cpu();
void Reset();
void Step(Mem&); void Step(Mem&);
Registers regs; Registers regs;
private: private:
#ifndef NDEBUG
csh handle{}; csh handle{};
cs_insn *insn = nullptr; cs_insn *insn = nullptr;
size_t count{}; size_t count{};
#endif
friend struct Cop1; friend struct Cop1;
void LogInstruction(u32); void LogInstruction(u32);

View File

@@ -4,6 +4,21 @@
#include <n64/core/cpu/Registers.hpp> #include <n64/core/cpu/Registers.hpp>
namespace n64 { namespace n64 {
MMIO::MMIO () {
Reset();
}
void MMIO::Reset() {
rsp.Reset();
rdp.Reset();
mi.Reset();
vi.Reset();
ai.Reset();
pi.Reset();
ri.Reset();
si.Reset();
}
u32 MMIO::Read(u32 addr) { u32 MMIO::Read(u32 addr) {
switch (addr) { switch (addr) {
case 0x04040000 ... 0x040FFFFF: return rsp.Read(addr); case 0x04040000 ... 0x040FFFFF: return rsp.Read(addr);

View File

@@ -13,7 +13,8 @@ struct Mem;
struct Registers; struct Registers;
struct MMIO { struct MMIO {
MMIO() = default; MMIO();
void Reset();
VI vi; VI vi;
MI mi; MI mi;
AI ai; AI ai;

View File

@@ -7,8 +7,16 @@
namespace n64 { namespace n64 {
Mem::Mem() { Mem::Mem() {
Reset();
}
void Mem::Reset() {
rdram.resize(RDRAM_SIZE); rdram.resize(RDRAM_SIZE);
sram.resize(SRAM_SIZE); sram.resize(SRAM_SIZE);
std::fill(rdram.begin(), rdram.end(), 0);
std::fill(sram.begin(), sram.end(), 0);
romMask = 0;
mmio.Reset();
} }
void Mem::LoadROM(const std::string& filename) { void Mem::LoadROM(const std::string& filename) {
@@ -21,12 +29,13 @@ void Mem::LoadROM(const std::string& filename) {
file.seekg(0, std::ios::end); file.seekg(0, std::ios::end);
auto size = file.tellg(); auto size = file.tellg();
auto size_adjusted = util::NextPow2(size); auto sizeAdjusted = util::NextPow2(size);
romMask = size_adjusted - 1; romMask = sizeAdjusted - 1;
file.seekg(0, std::ios::beg); file.seekg(0, std::ios::beg);
cart.resize(size_adjusted); std::fill(cart.begin(), cart.end(), 0);
file.read(reinterpret_cast<char*>(cart.data()), size); cart.resize(sizeAdjusted);
cart.insert(cart.begin(), std::istream_iterator<u8>(file), std::istream_iterator<u8>());
file.close(); file.close();
util::SwapN64Rom(size, cart.data()); util::SwapN64Rom(size, cart.data());
@@ -107,8 +116,6 @@ void Mem::Write(Registers& regs, u32 vaddr, T val, s64 pc) {
case 0x04001000 ... 0x04001FFF: util::WriteAccess<T>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); break; case 0x04001000 ... 0x04001FFF: util::WriteAccess<T>(mmio.rsp.imem, paddr & IMEM_DSIZE, val); break;
case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF: case 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break; case 0x04300000 ... 0x044FFFFF: case 0x04500000 ... 0x048FFFFF: mmio.Write(*this, regs, paddr, val); break;
case 0x10000000 ... 0x1FBFFFFF: util::WriteAccess<T>(cart.data(), paddr & romMask, val); break;
case 0x1FC00000 ... 0x1FC007BF: util::WriteAccess<T>(pifBootrom, paddr & PIF_BOOTROM_DSIZE, val); break;
case 0x1FC007C0 ... 0x1FC007FF: util::WriteAccess<T>(pifRam, paddr & PIF_RAM_DSIZE, val); break; case 0x1FC007C0 ... 0x1FC007FF: util::WriteAccess<T>(pifRam, paddr & PIF_RAM_DSIZE, val); break;
case 0x00800000 ... 0x03FFFFFF: case 0x04002000 ... 0x0403FFFF: case 0x00800000 ... 0x03FFFFFF: case 0x04002000 ... 0x0403FFFF:
case 0x04200000 ... 0x042FFFFF: case 0x04200000 ... 0x042FFFFF:

View File

@@ -9,6 +9,7 @@ struct Registers;
struct Mem { struct Mem {
~Mem() = default; ~Mem() = default;
Mem(); Mem();
void Reset();
void LoadROM(const std::string&); void LoadROM(const std::string&);
[[nodiscard]] auto GetRDRAM() -> u8* { [[nodiscard]] auto GetRDRAM() -> u8* {
return rdram.data(); return rdram.data();

View File

@@ -5,6 +5,15 @@
#include <n64/core/mmio/Interrupt.hpp> #include <n64/core/mmio/Interrupt.hpp>
namespace n64 { namespace n64 {
RDP::RDP() {
Reset();
}
void RDP::Reset() {
dpc.status.raw = 0x80;
memset(cmd_buf, 0, 0x100000);
}
static const int cmd_lens[64] = { static const int cmd_lens[64] = {
2, 2, 2, 2, 2, 2, 2, 2, 8, 12, 24, 28, 24, 28, 40, 44, 2, 2, 2, 2, 2, 2, 2, 2, 8, 12, 24, 28, 24, 28, 40, 44,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,

View File

@@ -48,10 +48,11 @@ struct DPC {
}; };
struct RDP { struct RDP {
DPC dpc{.status{.raw = 0x80}}; DPC dpc;
u32 cmd_buf[0xFFFFF]{}; u32 cmd_buf[0xFFFFF]{};
RDP() = default; RDP();
void Reset();
auto Read(u32 addr) const -> u32; auto Read(u32 addr) const -> u32;
void Write(u32 addr, u32 val); void Write(u32 addr, u32 val);

View File

@@ -4,6 +4,31 @@
#include <n64/core/mmio/Interrupt.hpp> #include <n64/core/mmio/Interrupt.hpp>
namespace n64 { namespace n64 {
RSP::RSP() {
Reset();
}
void RSP::Reset() {
spStatus.raw = 0;
spStatus.halt = true;
oldPC = 0;
pc = 0;
nextPC = 0;
spDMASPAddr.raw = 0;
spDMADRAMAddr.raw = 0;
spDMARDLen.raw = 0;
spDMAWRLen.raw = 0;
memset(dmem, 0, DMEM_SIZE);
memset(imem, 0, IMEM_SIZE);
memset(vpr, 0, 32 * sizeof(VPR));
memset(gpr, 0, 32);
vce = 0;
acc = {.h={}, .m={}, .l={}};
vcc = {.l = {}, .h = {}};
vco = {.l = {}, .h = {}};
semaphore = false;
}
void RSP::Step(MI& mi, Registers& regs, RDP& rdp) { void RSP::Step(MI& mi, Registers& regs, RDP& rdp) {
if(!spStatus.halt) { if(!spStatus.halt) {
gpr[0] = 0; gpr[0] = 0;

View File

@@ -105,12 +105,13 @@ struct Registers;
} while(0) } while(0)
struct RSP { struct RSP {
RSP() = default; RSP();
void Reset();
void Step(MI& mi, Registers& regs, RDP& rdp); void Step(MI& mi, Registers& regs, RDP& rdp);
auto Read(u32 addr) const -> u32; auto Read(u32 addr) const -> u32;
void Write(Mem& mem, Registers& regs, u32 addr, u32 value); void Write(Mem& mem, Registers& regs, u32 addr, u32 value);
void Exec(MI& mi, Registers& regs, RDP& rdp, u32 instr); void Exec(MI& mi, Registers& regs, RDP& rdp, u32 instr);
SPStatus spStatus{.raw = 1}; SPStatus spStatus;
u16 oldPC{}, pc{}, nextPC = 4; u16 oldPC{}, pc{}, nextPC = 4;
SPDMASPAddr spDMASPAddr{}; SPDMASPAddr spDMASPAddr{};
SPDMADRAMAddr spDMADRAMAddr{}; SPDMADRAMAddr spDMADRAMAddr{};

View File

@@ -2,6 +2,10 @@
namespace n64 { namespace n64 {
Registers::Registers() { Registers::Registers() {
Reset();
}
void Registers::Reset() {
delaySlot = false; delaySlot = false;
prevDelaySlot = false; prevDelaySlot = false;
memset(gpr, 0, 32*sizeof(s64)); memset(gpr, 0, 32*sizeof(s64));
@@ -14,6 +18,8 @@ Registers::Registers() {
gpr[20] = 0x0000000000000001; gpr[20] = 0x0000000000000001;
gpr[22] = 0x000000000000003F; gpr[22] = 0x000000000000003F;
gpr[29] = (s64)0xFFFFFFFFA4001FF0; gpr[29] = (s64)0xFFFFFFFFA4001FF0;
cop0.Reset();
cop1.Reset();
} }
void Registers::SetPC(s64 val) { void Registers::SetPC(s64 val) {

View File

@@ -5,6 +5,7 @@
namespace n64 { namespace n64 {
struct Registers { struct Registers {
Registers(); Registers();
void Reset();
void SetPC(s64); void SetPC(s64);
s64 gpr[32]; s64 gpr[32];
Cop0 cop0; Cop0 cop0;

View File

@@ -169,7 +169,7 @@ void Cpu::bllink(u32 instr, bool cond) {
void Cpu::lui(u32 instr) { void Cpu::lui(u32 instr) {
s64 val = (s16)instr; s64 val = (s16)instr;
val *= 65536; val <<= 16;
regs.gpr[RT(instr)] = val; regs.gpr[RT(instr)] = val;
} }

View File

@@ -5,12 +5,16 @@
namespace n64 { namespace n64 {
Cop0::Cop0() { Cop0::Cop0() {
Reset();
}
void Cop0::Reset() {
cause.raw = 0xB000007C; cause.raw = 0xB000007C;
random = 0x0000001F; random = 0x0000001F;
status.raw = 0x241000E0; status.raw = 0x241000E0;
wired = 64; wired = 64;
index = 64; index = 64;
PRId = 0x00000B00; PRId = 0x00000B22;
Config = 0x7006E463; Config = 0x7006E463;
EPC = 0xFFFFFFFFFFFFFFFF; EPC = 0xFFFFFFFFFFFFFFFF;
ErrorEPC = 0xFFFFFFFFFFFFFFFF; ErrorEPC = 0xFFFFFFFFFFFFFFFF;

View File

@@ -159,6 +159,8 @@ struct Cop0 {
template<class T> template<class T>
void SetReg(u8, T); void SetReg(u8, T);
void Reset();
PageMask pageMask{}; PageMask pageMask{};
EntryHi entryHi{}; EntryHi entryHi{};
EntryLo entryLo0{}, entryLo1{}; EntryLo entryLo0{}, entryLo1{};

View File

@@ -4,6 +4,16 @@
#include <util.hpp> #include <util.hpp>
namespace n64 { namespace n64 {
Cop1::Cop1() {
Reset();
}
void Cop1::Reset() {
fcr0 = 0xa00;
fcr31.raw = 0;
memset(fgr, 0, 32 * sizeof(FGR));
}
void Cop1::decode(Cpu& cpu, u32 instr) { void Cop1::decode(Cpu& cpu, u32 instr) {
Registers& regs = cpu.regs; Registers& regs = cpu.regs;
if(!regs.cop0.status.cu1) { if(!regs.cop0.status.cu1) {

View File

@@ -50,9 +50,11 @@ struct Cpu;
struct Registers; struct Registers;
struct Cop1 { struct Cop1 {
u32 fcr0; Cop1();
FCR31 fcr31; u32 fcr0{};
FGR fgr[32]; FCR31 fcr31{};
FGR fgr[32]{};
void Reset();
void decode(Cpu&, u32); void decode(Cpu&, u32);
friend struct Cpu; friend struct Cpu;
private: private:

View File

@@ -5,6 +5,18 @@
#include <n64/core/Audio.hpp> #include <n64/core/Audio.hpp>
namespace n64 { namespace n64 {
void AI::Reset() {
dmaEnable = 0;
dacRate = 0;
bitrate = 0;
dmaCount = 0;
memset(dmaLen, 0, 2);
memset(dmaAddr, 0, 2);
dmaAddrCarry = false;
cycles = 0;
dac = {44100, N64_CPU_FREQ / dac.freq, 16};
}
auto AI::Read(u32 addr) const -> u32 { auto AI::Read(u32 addr) const -> u32 {
switch(addr) { switch(addr) {
case 0x04500004: return dmaLen[0]; case 0x04500004: return dmaLen[0];

View File

@@ -8,6 +8,7 @@ struct Registers;
struct AI { struct AI {
AI() = default; AI() = default;
void Reset();
auto Read(u32) const -> u32; auto Read(u32) const -> u32;
void Write(Mem&, Registers&, u32, u32); void Write(Mem&, Registers&, u32, u32);
void Step(Mem&, Registers&, int); void Step(Mem&, Registers&, int);

View File

@@ -7,6 +7,10 @@
namespace n64 { namespace n64 {
MI::MI() { MI::MI() {
Reset();
}
void MI::Reset() {
miIntrMask.raw = 0; miIntrMask.raw = 0;
miIntr.raw = 0; miIntr.raw = 0;
miMode = 0; miMode = 0;

View File

@@ -20,6 +20,7 @@ struct Registers;
struct MI { struct MI {
MI(); MI();
void Reset();
[[nodiscard]] auto Read(u32) const -> u32; [[nodiscard]] auto Read(u32) const -> u32;
void Write(Registers& regs, u32, u32); void Write(Registers& regs, u32, u32);

View File

@@ -4,6 +4,19 @@
#include <n64/core/cpu/Registers.hpp> #include <n64/core/cpu/Registers.hpp>
namespace n64 { namespace n64 {
PI::PI() {
Reset();
}
void PI::Reset() {
dramAddr = 0;
cartAddr = 0;
rdLen = 0;
wrLen = 0;
status = 0;
memset(stub, 0, 8);
}
auto PI::Read(MI& mi, u32 addr) const -> u32 { auto PI::Read(MI& mi, u32 addr) const -> u32 {
switch(addr) { switch(addr) {
case 0x04600000: return dramAddr; case 0x04600000: return dramAddr;

View File

@@ -8,7 +8,8 @@ struct Mem;
struct Registers; struct Registers;
struct PI { struct PI {
PI() = default; PI();
void Reset();
auto Read(MI&, u32) const -> u32; auto Read(MI&, u32) const -> u32;
void Write(Mem&, Registers&, u32, u32); void Write(Mem&, Registers&, u32, u32);
u32 dramAddr{}, cartAddr{}; u32 dramAddr{}, cartAddr{};

View File

@@ -2,6 +2,17 @@
#include <util.hpp> #include <util.hpp>
namespace n64 { namespace n64 {
RI::RI() {
Reset();
}
void RI::Reset() {
mode = 0xE;
config = 0x40;
select = 0x14;
refresh = 0x63634;
}
auto RI::Read(u32 addr) const -> u32 { auto RI::Read(u32 addr) const -> u32 {
switch(addr) { switch(addr) {
case 0x04700000: return mode; case 0x04700000: return mode;

View File

@@ -4,7 +4,8 @@
namespace n64 { namespace n64 {
struct RI { struct RI {
RI() = default; RI();
void Reset();
u32 mode{0xE}, config{0x40}, select{0x14}, refresh{0x63634}; u32 mode{0xE}, config{0x40}, select{0x14}, refresh{0x63634};
auto Read(u32) const -> u32; auto Read(u32) const -> u32;
void Write(u32, u32); void Write(u32, u32);

View File

@@ -3,6 +3,15 @@
#include <util.hpp> #include <util.hpp>
namespace n64 { namespace n64 {
SI::SI() {
Reset();
}
void SI::Reset() {
status.raw = 0;
dramAddr = 0;
controller.raw = 0;
}
auto SI::Read(MI& mi, u32 addr) const -> u32 { auto SI::Read(MI& mi, u32 addr) const -> u32 {
switch(addr) { switch(addr) {

View File

@@ -21,7 +21,8 @@ union SIStatus {
struct Mem; struct Mem;
struct SI { struct SI {
SI() = default; SI();
void Reset();
SIStatus status{}; SIStatus status{};
u32 dramAddr{}; u32 dramAddr{};
Controller controller{}; Controller controller{};

View File

@@ -6,13 +6,11 @@
namespace n64 { namespace n64 {
VI::VI () { VI::VI () {
status.raw = 0xF; Reset();
}
void VI::Reset() {
intr = 256; intr = 256;
origin = 0;
width = 320;
current = 0;
vsync = 0;
hsync = 0;
numHalflines = 262; numHalflines = 262;
numFields = 1; numFields = 1;
cyclesPerHalfline = 1000; cyclesPerHalfline = 1000;
@@ -29,8 +27,8 @@ u32 VI::Read(u32 paddr) const {
case 0x04400018: return vsync; case 0x04400018: return vsync;
case 0x0440001C: return hsync; case 0x0440001C: return hsync;
case 0x04400020: return hsyncLeap.raw; case 0x04400020: return hsyncLeap.raw;
case 0x04400024: return hvideo.raw; case 0x04400024: return hstart.raw;
case 0x04400028: return vvideo.raw; case 0x04400028: return vstart.raw;
case 0x0440002C: return vburst; case 0x0440002C: return vburst;
case 0x04400030: return xscale.raw; case 0x04400030: return xscale.raw;
case 0x04400034: return yscale.raw; case 0x04400034: return yscale.raw;
@@ -72,8 +70,8 @@ void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) {
hsync = val & 0x3FF; hsync = val & 0x3FF;
} break; } break;
case 0x04400020: hsyncLeap.raw = val; break; case 0x04400020: hsyncLeap.raw = val; break;
case 0x04400024: hvideo.raw = val; break; case 0x04400024: hstart.raw = val; break;
case 0x04400028: vvideo.raw = val; break; case 0x04400028: vstart.raw = val; break;
case 0x0440002C: vburst = val; break; case 0x0440002C: vburst = val; break;
case 0x04400030: xscale.raw = val; break; case 0x04400030: xscale.raw = val; break;
case 0x04400034: yscale.raw = val; break; case 0x04400034: yscale.raw = val; break;

View File

@@ -87,10 +87,10 @@ struct Registers;
struct VI { struct VI {
VI(); VI();
void Reset();
[[nodiscard]] u32 Read(u32) const; [[nodiscard]] u32 Read(u32) const;
void Write(MI&, Registers&, u32, u32); void Write(MI&, Registers&, u32, u32);
AxisScale xscale{}, yscale{}; AxisScale xscale{}, yscale{};
VIVideo hvideo{}, vvideo{};
VIHsyncLeap hsyncLeap{}; VIHsyncLeap hsyncLeap{};
VIStatus status{}; VIStatus status{};
VIBurst burst{}; VIBurst burst{};

View File

@@ -8,7 +8,7 @@
namespace util { namespace util {
enum MessageType : u8 { enum MessageType : u8 {
Info, Warn, Error, Debug Info, Warn, Error
}; };
template <MessageType messageType = Info, typename ...Args> template <MessageType messageType = Info, typename ...Args>
@@ -18,7 +18,7 @@ constexpr void print(const std::string& fmt, Args... args) {
exit(-1); exit(-1);
} else if constexpr(messageType == Warn) { } else if constexpr(messageType == Warn) {
fmt::print(fg(fmt::color::yellow), fmt, args...); fmt::print(fg(fmt::color::yellow), fmt, args...);
} else if constexpr(messageType == Info || messageType == Debug) { } else if constexpr(messageType == Info) {
fmt::print(fmt, args...); fmt::print(fmt, args...);
} }
} }