Remove GB core for now
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -1,20 +0,0 @@
|
||||
#include <Core.hpp>
|
||||
#include <SDL2/SDL_events.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include <Cpu.hpp>
|
||||
#include <Ppu.hpp>
|
||||
#include <Mem.hpp>
|
||||
#include <BaseCore.hpp>
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#include <Cpu.hpp>
|
||||
#include <util.hpp>
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
#pragma once
|
||||
#include <Mem.hpp>
|
||||
#include <util.hpp>
|
||||
|
||||
namespace natsukashii::gb::core {
|
||||
template <class T1, class T2>
|
||||
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<u8, RegF> AF;
|
||||
Reg<u8, u8> BC;
|
||||
Reg<u8, u8> DE;
|
||||
Reg<u8, u8> 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 <int group>
|
||||
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 <int group>
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
#include <Mem.hpp>
|
||||
#include <util.hpp>
|
||||
#include <memory_regions.hpp>
|
||||
#include <fstream>
|
||||
#include <toml.hpp>
|
||||
|
||||
namespace natsukashii::gb::core {
|
||||
Mem::Mem() {
|
||||
auto data = toml::parse("config.toml");
|
||||
auto gb = toml::find(data, "gb");
|
||||
auto bootromPath = toml::find<std::string>(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<char*>(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<u8> rom;
|
||||
rom.reserve(size);
|
||||
rom.insert(rom.begin(),
|
||||
std::istream_iterator<u8>(file),
|
||||
std::istream_iterator<u8>());
|
||||
|
||||
file.close();
|
||||
switch(rom[0x147]) {
|
||||
case 0:
|
||||
cart = std::make_unique<NoMBC>(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);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
#include <common.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <mio/mmap.hpp>
|
||||
#include <memory_regions.hpp>
|
||||
#include <mbc.hpp>
|
||||
|
||||
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<Cartridge> cart;
|
||||
IO io{};
|
||||
u8 bootrom[BOOTROM_SIZE]{};
|
||||
};
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#include <mbc.hpp>
|
||||
#include <utility>
|
||||
#include <util.hpp>
|
||||
|
||||
namespace natsukashii::gb::core {
|
||||
NoMBC::NoMBC(std::vector<u8> 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);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
#include <common.hpp>
|
||||
#include <vector>
|
||||
|
||||
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<u8> rom);
|
||||
u8 Read(u16 addr) override;
|
||||
void Write(u16 addr, u8 val) override;
|
||||
private:
|
||||
std::vector<u8> data{};
|
||||
};
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
#include <common.hpp>
|
||||
|
||||
#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
|
||||
@@ -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)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <Cpu.hpp>
|
||||
#include <MI.hpp>
|
||||
#include <Interrupt.hpp>
|
||||
#include <n64/core/Cpu.hpp>
|
||||
#include <n64/core/mmio/MI.hpp>
|
||||
#include <n64/core/mmio/Interrupt.hpp>
|
||||
#include <util.hpp>
|
||||
|
||||
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<u8>(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<u8>(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<u32>(regs, regs.pc, regs.pc);
|
||||
|
||||
HandleInterrupt(regs);
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include <mmio/VI.hpp>
|
||||
#include <mmio/MI.hpp>
|
||||
#include <n64/core/mmio/VI.hpp>
|
||||
#include <n64/core/mmio/MI.hpp>
|
||||
#include <n64/core/RSP.hpp>
|
||||
#include <n64/core/RDP.hpp>
|
||||
|
||||
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);
|
||||
|
||||
@@ -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 <class T, bool tlb>
|
||||
@@ -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<u8, true>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u16 Mem::Read<u16, true>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u32 Mem::Read<u32, true>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u64 Mem::Read<u64, true>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u8 Mem::Read<u8, false>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u16 Mem::Read<u16, false>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u32 Mem::Read<u32, false>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u64 Mem::Read<u64, false>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u8 Mem::Read<u8>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u16 Mem::Read<u16>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u32 Mem::Read<u32>(Registers& regs, u32 vaddr, s64 pc);
|
||||
template u64 Mem::Read<u64>(Registers& regs, u32 vaddr, s64 pc);
|
||||
|
||||
template <class T, bool tlb>
|
||||
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<u8, true>(Registers& regs, u32 vaddr, u8 val, s64 pc);
|
||||
template void Mem::Write<u16, true>(Registers& regs, u32 vaddr, u16 val, s64 pc);
|
||||
template void Mem::Write<u32, true>(Registers& regs, u32 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write<u64, true>(Registers& regs, u32 vaddr, u64 val, s64 pc);
|
||||
template void Mem::Write<u8, false>(Registers& regs, u32 vaddr, u8 val, s64 pc);
|
||||
template void Mem::Write<u16, false>(Registers& regs, u32 vaddr, u16 val, s64 pc);
|
||||
template void Mem::Write<u32, false>(Registers& regs, u32 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write<u64, false>(Registers& regs, u32 vaddr, u64 val, s64 pc);
|
||||
template void Mem::Write<u8>(Registers& regs, u32 vaddr, u8 val, s64 pc);
|
||||
template void Mem::Write<u16>(Registers& regs, u32 vaddr, u16 val, s64 pc);
|
||||
template void Mem::Write<u32>(Registers& regs, u32 vaddr, u32 val, s64 pc);
|
||||
template void Mem::Write<u64>(Registers& regs, u32 vaddr, u64 val, s64 pc);
|
||||
}
|
||||
@@ -13,11 +13,12 @@ struct Mem {
|
||||
[[nodiscard]] auto GetRDRAM() -> u8* {
|
||||
return rdram.data();
|
||||
}
|
||||
template <class T, bool tlb>
|
||||
template <class T, bool tlb = true>
|
||||
T Read(Registers&, u32, s64);
|
||||
template <class T, bool tlb>
|
||||
template <class T, bool tlb = true>
|
||||
void Write(Registers&, u32, T, s64);
|
||||
private:
|
||||
friend struct Cpu;
|
||||
friend struct RSP;
|
||||
MMIO mmio;
|
||||
std::vector<u8> cart, rdram, sram;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include <RDP.hpp>
|
||||
#include <n64/core/RDP.hpp>
|
||||
#include <util.hpp>
|
||||
#include <RSP.hpp>
|
||||
#include <n64/core/RSP.hpp>
|
||||
#include <../../../frontend/ParallelRDPWrapper.hpp>
|
||||
#include <Interrupt.hpp>
|
||||
#include <n64/core/mmio/Interrupt.hpp>
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <RSP.hpp>
|
||||
#include <n64/core/RSP.hpp>
|
||||
#include <util.hpp>
|
||||
#include <n64/core/Mem.hpp>
|
||||
#include "Interrupt.hpp"
|
||||
#include <n64/core/mmio/Interrupt.hpp>
|
||||
|
||||
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 <bool isDRAMdest>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <mmio/MI.hpp>
|
||||
#include <RDP.hpp>
|
||||
#include <n64/core/mmio/MI.hpp>
|
||||
#include <n64/core/RDP.hpp>
|
||||
#include <n64/memory_regions.hpp>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
#include <RSP.hpp>
|
||||
#include <n64/core/RSP.hpp>
|
||||
#include <util.hpp>
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -39,6 +39,7 @@ constexpr void info(const std::string& fmt, Args... args) {
|
||||
|
||||
template <typename T, bool HToBE = false>
|
||||
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 <typename T>
|
||||
inline T ReadAccess(u8* data, u32 index) {
|
||||
static_assert(sizeof(T) != 2 || sizeof(T) != 4 || sizeof(T) != 8);
|
||||
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<T>(result);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void WriteAccess(u8* data, u32 index, T val) {
|
||||
static_assert(sizeof(T) != 2 || sizeof(T) != 4 || sizeof(T) != 8);
|
||||
if constexpr(sizeof(T) == 1) {
|
||||
data[index] = val;
|
||||
return;
|
||||
} else {
|
||||
static_assert(sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8);
|
||||
T temp = GetSwapFunc<T, true>(val);
|
||||
memcpy(&data[index], &temp, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
#define Z64 0x80371240
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
#include "n64/Core.hpp"
|
||||
#include "parallel-rdp-standalone/vulkan/wsi.hpp"
|
||||
#include <n64/Core.hpp>
|
||||
#include <parallel-rdp-standalone/vulkan/wsi.hpp>
|
||||
#include <SDL2/SDL.h>
|
||||
#include "n64/core/mmio/VI.hpp"
|
||||
#include "BaseCore.hpp"
|
||||
#include <n64/core/mmio/VI.hpp>
|
||||
#include <BaseCore.hpp>
|
||||
|
||||
enum class Platform : bool {
|
||||
SDL, Qt
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include <Frontend.hpp>
|
||||
#include <gb/Core.hpp>
|
||||
#include <n64/Core.hpp>
|
||||
#include <volk.h>
|
||||
#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<gb::core::Core>(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<n64::core::Core>(Platform::SDL, rom);
|
||||
} else {
|
||||
util::panic("Unimplemented core!");
|
||||
util::panic("Unimplemented core \"{}\"!", selectedCore);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_vulkan.h>
|
||||
#include <BaseCore.hpp>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <util.hpp>
|
||||
|
||||
Reference in New Issue
Block a user