Fix parallel-rdp integration and reset whole state upon loading rom
This commit is contained in:
13
external/parallel-rdp/ParallelRDPWrapper.cpp
vendored
13
external/parallel-rdp/ParallelRDPWrapper.cpp
vendored
@@ -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;
|
||||||
|
|||||||
2
external/parallel-rdp/ParallelRDPWrapper.hpp
vendored
2
external/parallel-rdp/ParallelRDPWrapper.hpp
vendored
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Core.hpp>
|
|
||||||
#include <imgui/Window.hpp>
|
#include <imgui/Window.hpp>
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
|
|||||||
@@ -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")) {
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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++) {
|
||||||
|
|||||||
@@ -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(); }
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -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...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user