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 {
|
||||
return 800;
|
||||
return 640;
|
||||
}
|
||||
|
||||
uint32_t get_surface_height() override {
|
||||
return 600;
|
||||
return 480;
|
||||
}
|
||||
|
||||
bool alive(Vulkan::WSI &wsi_) override {
|
||||
@@ -106,6 +106,15 @@ public:
|
||||
void poll_input() 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;
|
||||
|
||||
2
external/parallel-rdp/ParallelRDPWrapper.hpp
vendored
2
external/parallel-rdp/ParallelRDPWrapper.hpp
vendored
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#define VULKAN_DEBUG
|
||||
#include <Core.hpp>
|
||||
#include <wsi.hpp>
|
||||
#include <SDL2/SDL.h>
|
||||
@@ -26,7 +25,6 @@ class SDLParallelRdpWindowInfo : public ParallelRdpWindowInfo {
|
||||
}
|
||||
};
|
||||
|
||||
static u32 windowID;
|
||||
VkQueue GetGraphicsQueue();
|
||||
VkInstance GetVkInstance();
|
||||
VkPhysicalDevice GetVkPhysicalDevice();
|
||||
|
||||
@@ -3,6 +3,8 @@ project(natsukashii)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED true)
|
||||
|
||||
add_compile_definitions(VULKAN_DEBUG)
|
||||
|
||||
add_subdirectory(n64)
|
||||
add_subdirectory(frontend)
|
||||
|
||||
@@ -12,3 +14,4 @@ add_executable(natsukashii main.cpp)
|
||||
|
||||
target_link_libraries(natsukashii PUBLIC frontend n64 fmt)
|
||||
target_include_directories(natsukashii PUBLIC . ../external)
|
||||
target_compile_options(natsukashii PUBLIC -Wpedantic -Wimplicit-fallthrough -Wextra -Wall)
|
||||
|
||||
@@ -9,35 +9,35 @@ void App::Run() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
//ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
if (event.type == SDL_QUIT)
|
||||
done = true;
|
||||
if (window.gotClosed(event))
|
||||
done = true;
|
||||
if(event.type == SDL_KEYDOWN) {
|
||||
switch(event.key.keysym.sym) {
|
||||
case SDLK_o: {
|
||||
nfdchar_t* outpath;
|
||||
const nfdu8filteritem_t filter {"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"};
|
||||
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
||||
if(result == NFD_OKAY) {
|
||||
core.LoadROM(outpath);
|
||||
NFD_FreePath(outpath);
|
||||
}
|
||||
switch(event.type) {
|
||||
case SDL_QUIT: done = true; break;
|
||||
case SDL_WINDOWEVENT:
|
||||
done = window.gotClosed(event);
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
switch(event.key.keysym.sym) {
|
||||
case SDLK_o: {
|
||||
nfdchar_t* outpath;
|
||||
const nfdu8filteritem_t filter {"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"};
|
||||
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
||||
if(result == NFD_OKAY) {
|
||||
core.LoadROM(outpath);
|
||||
NFD_FreePath(outpath);
|
||||
}
|
||||
} break;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
core.PollInputs(event);
|
||||
}
|
||||
|
||||
if(core.romLoaded)
|
||||
core.Run();
|
||||
|
||||
if(core.romLoaded)
|
||||
if(core.romLoaded) {
|
||||
core.Run(window);
|
||||
UpdateScreenParallelRdp(window, core.GetVI());
|
||||
else
|
||||
} else {
|
||||
UpdateScreenParallelRdpNoGame(window);
|
||||
}
|
||||
|
||||
SDL_Delay(16);
|
||||
SDL_Delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include <Core.hpp>
|
||||
#include <imgui/Window.hpp>
|
||||
|
||||
struct App {
|
||||
|
||||
@@ -12,8 +12,7 @@ Window::Window(n64::Core& core) {
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Window::gotClosed(SDL_Event event) {
|
||||
return event.type == SDL_WINDOWEVENT
|
||||
&& event.window.event == SDL_WINDOWEVENT_CLOSE
|
||||
return event.window.event == SDL_WINDOWEVENT_CLOSE
|
||||
&& event.window.windowID == SDL_GetWindowID(window);
|
||||
}
|
||||
|
||||
@@ -177,18 +176,18 @@ Window::~Window() {
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
}
|
||||
|
||||
ImDrawData* Window::Present() {
|
||||
ImDrawData* Window::Present(n64::Core& core) {
|
||||
//ImGui_ImplVulkan_NewFrame();
|
||||
//ImGui_ImplSDL2_NewFrame(window);
|
||||
//ImGui::NewFrame();
|
||||
//
|
||||
Render();
|
||||
Render(core);
|
||||
|
||||
//ImGui::Render();
|
||||
return ImGui::GetDrawData();
|
||||
}
|
||||
|
||||
void Window::Render() {
|
||||
void Window::Render(n64::Core& core) {
|
||||
ImGui::BeginMainMenuBar();
|
||||
if(ImGui::BeginMenu("File")) {
|
||||
if(ImGui::BeginMenu("Open")) {
|
||||
|
||||
@@ -10,15 +10,14 @@
|
||||
struct Window {
|
||||
explicit Window(n64::Core& core);
|
||||
~Window();
|
||||
ImDrawData* Present();
|
||||
ImDrawData* Present(n64::Core& core);
|
||||
|
||||
[[nodiscard]] bool gotClosed(SDL_Event event);
|
||||
private:
|
||||
SDL_Window* window;
|
||||
n64::Core core;
|
||||
void InitSDL();
|
||||
void InitImgui();
|
||||
void Render();
|
||||
void Render(n64::Core& core);
|
||||
|
||||
VkInstance instance{};
|
||||
VkPhysicalDevice physicalDevice{};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include <frontend/App.hpp>
|
||||
|
||||
int main() {
|
||||
App* app = new App;
|
||||
app->Run();
|
||||
int main(int argc, char* argv[]) {
|
||||
App app;
|
||||
app.Run();
|
||||
return 0;
|
||||
}
|
||||
@@ -12,6 +12,7 @@ target_link_libraries(n64 PUBLIC core)
|
||||
target_include_directories(n64 PUBLIC
|
||||
.
|
||||
..
|
||||
../frontend/imgui
|
||||
../../external
|
||||
../../external/imgui/imgui
|
||||
../../external/imgui/imgui/backends
|
||||
|
||||
@@ -1,15 +1,28 @@
|
||||
#include <Core.hpp>
|
||||
#include <ParallelRDPWrapper.hpp>
|
||||
#include <Window.hpp>
|
||||
|
||||
namespace n64 {
|
||||
Core::Core() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Core::Reset() {
|
||||
cpu.Reset();
|
||||
mem.Reset();
|
||||
romLoaded = false;
|
||||
}
|
||||
|
||||
void Core::LoadROM(const std::string& rom) {
|
||||
Reset();
|
||||
mem.LoadROM(rom);
|
||||
romLoaded = true;
|
||||
}
|
||||
|
||||
void Core::Run() {
|
||||
void Core::Run(Window& window) {
|
||||
MMIO& mmio = mem.mmio;
|
||||
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++) {
|
||||
cpu.Step(mem);
|
||||
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
|
||||
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
|
||||
@@ -17,7 +30,7 @@ void Core::Run() {
|
||||
mmio.rsp.Step(mmio.mi, cpu.regs, mmio.rdp);
|
||||
}
|
||||
|
||||
if((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
|
||||
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
|
||||
InterruptRaise(mmio.mi, cpu.regs, Interrupt::VI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
#include <Mem.hpp>
|
||||
#include <string>
|
||||
|
||||
struct Window;
|
||||
namespace n64 {
|
||||
struct Core {
|
||||
~Core() = default;
|
||||
Core() = default;
|
||||
Core();
|
||||
void Reset();
|
||||
void LoadROM(const std::string&);
|
||||
void Run();
|
||||
void Run(Window&);
|
||||
void PollInputs(SDL_Event);
|
||||
VI& GetVI() { return mem.mmio.vi; }
|
||||
u8* GetRDRAM() { return mem.rdram.data(); }
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
#include <util.hpp>
|
||||
|
||||
namespace n64 {
|
||||
void Cpu::Reset() {
|
||||
regs.Reset();
|
||||
}
|
||||
|
||||
Cpu::Cpu() {
|
||||
#ifndef NDEBUG
|
||||
if (cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64, &handle)) {
|
||||
util::panic("Could not initialize capstone!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Cpu::~Cpu() {
|
||||
#ifndef NDEBUG
|
||||
cs_close(&handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool ShouldServiceInterrupt(Registers& regs) {
|
||||
@@ -99,21 +99,16 @@ inline void HandleInterrupt(Registers& regs) {
|
||||
}
|
||||
|
||||
void Cpu::LogInstruction(u32 instruction) {
|
||||
#ifndef NDEBUG
|
||||
/*u8 code[4]{};
|
||||
u32 bswapped = be32toh(instruction);
|
||||
memcpy(code, &instruction, 4);
|
||||
count = cs_disasm(handle, code, 4, regs.pc, 0, &insn);
|
||||
count = cs_disasm(handle, reinterpret_cast<u8*>(&instruction), 4, regs.pc, 0, &insn);
|
||||
|
||||
if (count > 0) {
|
||||
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);
|
||||
} else {
|
||||
util::panic("Failed to disassemble {:08X}!", instruction);
|
||||
}*/
|
||||
#endif
|
||||
util::logdebug("Failed to disassemble 0x{:08X}!", instruction);
|
||||
}
|
||||
}
|
||||
|
||||
void Cpu::Step(Mem& mem) {
|
||||
@@ -123,8 +118,14 @@ void Cpu::Step(Mem& mem) {
|
||||
|
||||
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);
|
||||
LogInstruction(instruction);
|
||||
//LogInstruction(instruction);
|
||||
|
||||
HandleInterrupt(regs);
|
||||
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
#pragma once
|
||||
#include <Registers.hpp>
|
||||
#include <Mem.hpp>
|
||||
#ifndef NDEBUG
|
||||
#include <capstone/capstone.h>
|
||||
#endif
|
||||
|
||||
namespace n64 {
|
||||
struct Cpu {
|
||||
Cpu();
|
||||
~Cpu();
|
||||
void Reset();
|
||||
void Step(Mem&);
|
||||
Registers regs;
|
||||
private:
|
||||
#ifndef NDEBUG
|
||||
csh handle{};
|
||||
cs_insn *insn = nullptr;
|
||||
size_t count{};
|
||||
#endif
|
||||
friend struct Cop1;
|
||||
|
||||
void LogInstruction(u32);
|
||||
|
||||
@@ -4,6 +4,21 @@
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
|
||||
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) {
|
||||
switch (addr) {
|
||||
case 0x04040000 ... 0x040FFFFF: return rsp.Read(addr);
|
||||
|
||||
@@ -13,7 +13,8 @@ struct Mem;
|
||||
struct Registers;
|
||||
|
||||
struct MMIO {
|
||||
MMIO() = default;
|
||||
MMIO();
|
||||
void Reset();
|
||||
VI vi;
|
||||
MI mi;
|
||||
AI ai;
|
||||
|
||||
@@ -7,8 +7,16 @@
|
||||
|
||||
namespace n64 {
|
||||
Mem::Mem() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Mem::Reset() {
|
||||
rdram.resize(RDRAM_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) {
|
||||
@@ -21,12 +29,13 @@ void Mem::LoadROM(const std::string& filename) {
|
||||
|
||||
file.seekg(0, std::ios::end);
|
||||
auto size = file.tellg();
|
||||
auto size_adjusted = util::NextPow2(size);
|
||||
romMask = size_adjusted - 1;
|
||||
auto sizeAdjusted = util::NextPow2(size);
|
||||
romMask = sizeAdjusted - 1;
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
cart.resize(size_adjusted);
|
||||
file.read(reinterpret_cast<char*>(cart.data()), size);
|
||||
std::fill(cart.begin(), cart.end(), 0);
|
||||
cart.resize(sizeAdjusted);
|
||||
cart.insert(cart.begin(), std::istream_iterator<u8>(file), std::istream_iterator<u8>());
|
||||
|
||||
file.close();
|
||||
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 0x04040000 ... 0x040FFFFF: case 0x04100000 ... 0x041FFFFF:
|
||||
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 0x00800000 ... 0x03FFFFFF: case 0x04002000 ... 0x0403FFFF:
|
||||
case 0x04200000 ... 0x042FFFFF:
|
||||
|
||||
@@ -9,6 +9,7 @@ struct Registers;
|
||||
struct Mem {
|
||||
~Mem() = default;
|
||||
Mem();
|
||||
void Reset();
|
||||
void LoadROM(const std::string&);
|
||||
[[nodiscard]] auto GetRDRAM() -> u8* {
|
||||
return rdram.data();
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
#include <n64/core/mmio/Interrupt.hpp>
|
||||
|
||||
namespace n64 {
|
||||
RDP::RDP() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void RDP::Reset() {
|
||||
dpc.status.raw = 0x80;
|
||||
memset(cmd_buf, 0, 0x100000);
|
||||
}
|
||||
|
||||
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, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
|
||||
@@ -48,10 +48,11 @@ struct DPC {
|
||||
};
|
||||
|
||||
struct RDP {
|
||||
DPC dpc{.status{.raw = 0x80}};
|
||||
DPC dpc;
|
||||
u32 cmd_buf[0xFFFFF]{};
|
||||
|
||||
RDP() = default;
|
||||
RDP();
|
||||
void Reset();
|
||||
|
||||
auto Read(u32 addr) const -> u32;
|
||||
void Write(u32 addr, u32 val);
|
||||
|
||||
@@ -4,6 +4,31 @@
|
||||
#include <n64/core/mmio/Interrupt.hpp>
|
||||
|
||||
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) {
|
||||
if(!spStatus.halt) {
|
||||
gpr[0] = 0;
|
||||
|
||||
@@ -105,12 +105,13 @@ struct Registers;
|
||||
} while(0)
|
||||
|
||||
struct RSP {
|
||||
RSP() = default;
|
||||
RSP();
|
||||
void Reset();
|
||||
void Step(MI& mi, Registers& regs, RDP& rdp);
|
||||
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};
|
||||
SPStatus spStatus;
|
||||
u16 oldPC{}, pc{}, nextPC = 4;
|
||||
SPDMASPAddr spDMASPAddr{};
|
||||
SPDMADRAMAddr spDMADRAMAddr{};
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
namespace n64 {
|
||||
Registers::Registers() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Registers::Reset() {
|
||||
delaySlot = false;
|
||||
prevDelaySlot = false;
|
||||
memset(gpr, 0, 32*sizeof(s64));
|
||||
@@ -14,6 +18,8 @@ Registers::Registers() {
|
||||
gpr[20] = 0x0000000000000001;
|
||||
gpr[22] = 0x000000000000003F;
|
||||
gpr[29] = (s64)0xFFFFFFFFA4001FF0;
|
||||
cop0.Reset();
|
||||
cop1.Reset();
|
||||
}
|
||||
|
||||
void Registers::SetPC(s64 val) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
namespace n64 {
|
||||
struct Registers {
|
||||
Registers();
|
||||
void Reset();
|
||||
void SetPC(s64);
|
||||
s64 gpr[32];
|
||||
Cop0 cop0;
|
||||
|
||||
@@ -169,7 +169,7 @@ void Cpu::bllink(u32 instr, bool cond) {
|
||||
|
||||
void Cpu::lui(u32 instr) {
|
||||
s64 val = (s16)instr;
|
||||
val *= 65536;
|
||||
val <<= 16;
|
||||
regs.gpr[RT(instr)] = val;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
|
||||
namespace n64 {
|
||||
Cop0::Cop0() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Cop0::Reset() {
|
||||
cause.raw = 0xB000007C;
|
||||
random = 0x0000001F;
|
||||
status.raw = 0x241000E0;
|
||||
wired = 64;
|
||||
index = 64;
|
||||
PRId = 0x00000B00;
|
||||
PRId = 0x00000B22;
|
||||
Config = 0x7006E463;
|
||||
EPC = 0xFFFFFFFFFFFFFFFF;
|
||||
ErrorEPC = 0xFFFFFFFFFFFFFFFF;
|
||||
|
||||
@@ -159,6 +159,8 @@ struct Cop0 {
|
||||
template<class T>
|
||||
void SetReg(u8, T);
|
||||
|
||||
void Reset();
|
||||
|
||||
PageMask pageMask{};
|
||||
EntryHi entryHi{};
|
||||
EntryLo entryLo0{}, entryLo1{};
|
||||
|
||||
@@ -4,6 +4,16 @@
|
||||
#include <util.hpp>
|
||||
|
||||
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) {
|
||||
Registers& regs = cpu.regs;
|
||||
if(!regs.cop0.status.cu1) {
|
||||
|
||||
@@ -50,9 +50,11 @@ struct Cpu;
|
||||
struct Registers;
|
||||
|
||||
struct Cop1 {
|
||||
u32 fcr0;
|
||||
FCR31 fcr31;
|
||||
FGR fgr[32];
|
||||
Cop1();
|
||||
u32 fcr0{};
|
||||
FCR31 fcr31{};
|
||||
FGR fgr[32]{};
|
||||
void Reset();
|
||||
void decode(Cpu&, u32);
|
||||
friend struct Cpu;
|
||||
private:
|
||||
|
||||
@@ -5,6 +5,18 @@
|
||||
#include <n64/core/Audio.hpp>
|
||||
|
||||
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 {
|
||||
switch(addr) {
|
||||
case 0x04500004: return dmaLen[0];
|
||||
|
||||
@@ -8,6 +8,7 @@ struct Registers;
|
||||
|
||||
struct AI {
|
||||
AI() = default;
|
||||
void Reset();
|
||||
auto Read(u32) const -> u32;
|
||||
void Write(Mem&, Registers&, u32, u32);
|
||||
void Step(Mem&, Registers&, int);
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
|
||||
namespace n64 {
|
||||
MI::MI() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void MI::Reset() {
|
||||
miIntrMask.raw = 0;
|
||||
miIntr.raw = 0;
|
||||
miMode = 0;
|
||||
|
||||
@@ -20,6 +20,7 @@ struct Registers;
|
||||
|
||||
struct MI {
|
||||
MI();
|
||||
void Reset();
|
||||
[[nodiscard]] auto Read(u32) const -> u32;
|
||||
void Write(Registers& regs, u32, u32);
|
||||
|
||||
|
||||
@@ -4,6 +4,19 @@
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
|
||||
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 {
|
||||
switch(addr) {
|
||||
case 0x04600000: return dramAddr;
|
||||
|
||||
@@ -8,7 +8,8 @@ struct Mem;
|
||||
struct Registers;
|
||||
|
||||
struct PI {
|
||||
PI() = default;
|
||||
PI();
|
||||
void Reset();
|
||||
auto Read(MI&, u32) const -> u32;
|
||||
void Write(Mem&, Registers&, u32, u32);
|
||||
u32 dramAddr{}, cartAddr{};
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
#include <util.hpp>
|
||||
|
||||
namespace n64 {
|
||||
RI::RI() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void RI::Reset() {
|
||||
mode = 0xE;
|
||||
config = 0x40;
|
||||
select = 0x14;
|
||||
refresh = 0x63634;
|
||||
}
|
||||
|
||||
auto RI::Read(u32 addr) const -> u32 {
|
||||
switch(addr) {
|
||||
case 0x04700000: return mode;
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
namespace n64 {
|
||||
|
||||
struct RI {
|
||||
RI() = default;
|
||||
RI();
|
||||
void Reset();
|
||||
u32 mode{0xE}, config{0x40}, select{0x14}, refresh{0x63634};
|
||||
auto Read(u32) const -> u32;
|
||||
void Write(u32, u32);
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
#include <util.hpp>
|
||||
|
||||
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 {
|
||||
switch(addr) {
|
||||
|
||||
@@ -21,7 +21,8 @@ union SIStatus {
|
||||
struct Mem;
|
||||
|
||||
struct SI {
|
||||
SI() = default;
|
||||
SI();
|
||||
void Reset();
|
||||
SIStatus status{};
|
||||
u32 dramAddr{};
|
||||
Controller controller{};
|
||||
|
||||
@@ -6,13 +6,11 @@
|
||||
|
||||
namespace n64 {
|
||||
VI::VI () {
|
||||
status.raw = 0xF;
|
||||
Reset();
|
||||
}
|
||||
|
||||
void VI::Reset() {
|
||||
intr = 256;
|
||||
origin = 0;
|
||||
width = 320;
|
||||
current = 0;
|
||||
vsync = 0;
|
||||
hsync = 0;
|
||||
numHalflines = 262;
|
||||
numFields = 1;
|
||||
cyclesPerHalfline = 1000;
|
||||
@@ -29,8 +27,8 @@ u32 VI::Read(u32 paddr) const {
|
||||
case 0x04400018: return vsync;
|
||||
case 0x0440001C: return hsync;
|
||||
case 0x04400020: return hsyncLeap.raw;
|
||||
case 0x04400024: return hvideo.raw;
|
||||
case 0x04400028: return vvideo.raw;
|
||||
case 0x04400024: return hstart.raw;
|
||||
case 0x04400028: return vstart.raw;
|
||||
case 0x0440002C: return vburst;
|
||||
case 0x04400030: return xscale.raw;
|
||||
case 0x04400034: return yscale.raw;
|
||||
@@ -72,8 +70,8 @@ void VI::Write(MI& mi, Registers& regs, u32 paddr, u32 val) {
|
||||
hsync = val & 0x3FF;
|
||||
} break;
|
||||
case 0x04400020: hsyncLeap.raw = val; break;
|
||||
case 0x04400024: hvideo.raw = val; break;
|
||||
case 0x04400028: vvideo.raw = val; break;
|
||||
case 0x04400024: hstart.raw = val; break;
|
||||
case 0x04400028: vstart.raw = val; break;
|
||||
case 0x0440002C: vburst = val; break;
|
||||
case 0x04400030: xscale.raw = val; break;
|
||||
case 0x04400034: yscale.raw = val; break;
|
||||
|
||||
@@ -87,10 +87,10 @@ struct Registers;
|
||||
|
||||
struct VI {
|
||||
VI();
|
||||
void Reset();
|
||||
[[nodiscard]] u32 Read(u32) const;
|
||||
void Write(MI&, Registers&, u32, u32);
|
||||
AxisScale xscale{}, yscale{};
|
||||
VIVideo hvideo{}, vvideo{};
|
||||
VIHsyncLeap hsyncLeap{};
|
||||
VIStatus status{};
|
||||
VIBurst burst{};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace util {
|
||||
enum MessageType : u8 {
|
||||
Info, Warn, Error, Debug
|
||||
Info, Warn, Error
|
||||
};
|
||||
|
||||
template <MessageType messageType = Info, typename ...Args>
|
||||
@@ -18,7 +18,7 @@ constexpr void print(const std::string& fmt, Args... args) {
|
||||
exit(-1);
|
||||
} else if constexpr(messageType == Warn) {
|
||||
fmt::print(fg(fmt::color::yellow), fmt, args...);
|
||||
} else if constexpr(messageType == Info || messageType == Debug) {
|
||||
} else if constexpr(messageType == Info) {
|
||||
fmt::print(fmt, args...);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user