Restructure

This commit is contained in:
CocoSimone
2022-12-22 22:33:43 +01:00
parent ba62db8f12
commit 4adb7a46f8
70 changed files with 554 additions and 582 deletions

View File

@@ -60,11 +60,12 @@ target_include_directories(parallel-rdp PUBLIC
parallel-rdp-standalone/vulkan parallel-rdp-standalone/vulkan
parallel-rdp-standalone/vulkan-headers/include parallel-rdp-standalone/vulkan-headers/include
parallel-rdp-standalone/util parallel-rdp-standalone/util
../../src/n64 ../../src/backend
../../src/n64/core/ ../../src/utils
../../src/n64/core/mmio ../../src/backend/core/
../../src/n64/core/interpreter/ ../../src/backend/core/mmio
../../src/n64/core/registers ../../src/backend/core/interpreter/
../../src/backend/core/registers
parallel-rdp-standalone parallel-rdp-standalone
.. ..
../capstone/include ../capstone/include

View File

@@ -2,7 +2,8 @@
#include <core/RDP.hpp> #include <core/RDP.hpp>
#include <memory> #include <memory>
#include <rdp_device.hpp> #include <rdp_device.hpp>
#include <util.hpp> #include <log.hpp>
#include <File.hpp>
#include <SDL2/SDL_vulkan.h> #include <SDL2/SDL_vulkan.h>
#include <imgui/backends/imgui_impl_vulkan.h> #include <imgui/backends/imgui_impl_vulkan.h>
#include <imgui/Window.hpp> #include <imgui/Window.hpp>

View File

@@ -4,8 +4,8 @@ project(gadolinium)
set(BUILD_SHARED_LIBS OFF) set(BUILD_SHARED_LIBS OFF)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
file(GLOB_RECURSE CORE_SOURCES n64/*.cpp) file(GLOB_RECURSE CORE_SOURCES backend/*.cpp)
file(GLOB_RECURSE CORE_HEADERS n64/*.hpp) file(GLOB_RECURSE CORE_HEADERS backend/*.hpp)
file(GLOB_RECURSE FRONTEND_SOURCES frontend/*.cpp) file(GLOB_RECURSE FRONTEND_SOURCES frontend/*.cpp)
file(GLOB_RECURSE FRONTEND_HEADERS frontend/*.hpp) file(GLOB_RECURSE FRONTEND_HEADERS frontend/*.hpp)
@@ -30,20 +30,20 @@ add_executable(gadolinium
${FRONTEND_HEADERS} ${FRONTEND_HEADERS}
main.cpp main.cpp
common.hpp common.hpp
util.hpp backend/Scheduler.cpp
n64/Scheduler.cpp backend/Scheduler.hpp)
n64/Scheduler.hpp)
target_include_directories(gadolinium PRIVATE target_include_directories(gadolinium PRIVATE
. .
n64 backend
n64/core backend/core
n64/core/interpreter/ backend/core/interpreter/
n64/core/registers backend/core/registers
n64/core/mmio backend/core/mmio
n64/core/rsp backend/core/rsp
frontend frontend
frontend/imgui frontend/imgui
utils
../external ../external
../external/xbyak ../external/xbyak
../external/imgui/imgui ../external/imgui/imgui

42
src/Discord.hpp Normal file
View File

@@ -0,0 +1,42 @@
#pragma once
#include <discord_rpc.h>
#include <string>
#include <ctime>
namespace util {
enum State {
Idling,
Playing,
Paused
};
inline void UpdateRPC(State state, const std::string& game = "") {
DiscordRichPresence presence{};
std::string textState, textDetails;
switch(state) {
case Idling:
textDetails = "Idling";
break;
case Playing:
textDetails = "In-game";
textState = "Playing \"" + game + "\"";
break;
case Paused:
textDetails = "In-game";
textState = "Playing \"" + game + "\" (Paused)";
break;
}
presence.details = textDetails.c_str();
presence.state = textState.c_str();
presence.startTimestamp = time(nullptr);
presence.largeImageText = "Gadolinium";
presence.largeImageKey = "logo";
Discord_UpdatePresence(&presence);
}
inline void ClearRPC() {
Discord_ClearPresence();
}
}

View File

@@ -2,7 +2,7 @@
#include <ParallelRDPWrapper.hpp> #include <ParallelRDPWrapper.hpp>
#include <Window.hpp> #include <Window.hpp>
#include <algorithm> #include <algorithm>
#include "m64.hpp" #include <MupenMovie.hpp>
#include <Scheduler.hpp> #include <Scheduler.hpp>
namespace n64 { namespace n64 {

View File

@@ -1,5 +1,5 @@
#include <m64.hpp> #include <MupenMovie.hpp>
#include <util.hpp> #include <log.hpp>
struct TASMovieHeader { struct TASMovieHeader {
u8 signature[4]; u8 signature[4];

View File

@@ -1,6 +1,6 @@
#include <Audio.hpp> #include <Audio.hpp>
#include <SDL_audio.h> #include <SDL_audio.h>
#include <util.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
#define AUDIO_SAMPLE_RATE 44100 #define AUDIO_SAMPLE_RATE 44100

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "common.hpp" #include <common.hpp>
namespace n64 { namespace n64 {
void PushSample(float, float, float, float); void PushSample(float, float, float, float);

View File

@@ -1,5 +1,5 @@
#include <n64/core/Interpreter.hpp> #include <core/Interpreter.hpp>
#include <util.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
void Interpreter::Reset() { void Interpreter::Reset() {

View File

@@ -1,6 +1,6 @@
#include <n64/core/MMIO.hpp> #include <core/MMIO.hpp>
#include <util.hpp> #include <log.hpp>
#include <n64/core/Mem.hpp> #include <core/Mem.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
namespace n64 { namespace n64 {

30
src/backend/core/MMIO.hpp Normal file
View File

@@ -0,0 +1,30 @@
#pragma once
#include <core/mmio/VI.hpp>
#include <core/mmio/MI.hpp>
#include <core/mmio/AI.hpp>
#include <core/mmio/PI.hpp>
#include <core/mmio/RI.hpp>
#include <core/mmio/SI.hpp>
#include <core/RSP.hpp>
#include <core/RDP.hpp>
namespace n64 {
struct Mem;
struct Registers;
struct MMIO {
MMIO();
void Reset();
VI vi;
MI mi;
AI ai;
PI pi;
RI ri;
SI si;
RSP rsp;
RDP rdp;
u32 Read(u32);
void Write(Mem&, Registers&, u32, u32);
};
}

View File

@@ -2,7 +2,8 @@
#include <fstream> #include <fstream>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <core/registers/Cop0.hpp> #include <core/registers/Cop0.hpp>
#include <n64/core/Interpreter.hpp> #include <core/Interpreter.hpp>
#include <File.hpp>
namespace n64 { namespace n64 {
Mem::Mem() { Mem::Mem() {

View File

@@ -1,9 +1,10 @@
#pragma once #pragma once
#include <common.hpp> #include <common.hpp>
#include <n64/memory_regions.hpp> #include <MemoryRegions.hpp>
#include <n64/core/MMIO.hpp> #include <core/MMIO.hpp>
#include <vector> #include <vector>
#include <util.hpp> #include <MemoryHelpers.hpp>
#include <log.hpp>
namespace n64 { namespace n64 {
struct Registers; struct Registers;

37
src/backend/core/RCP.hpp Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include <common.hpp>
static constexpr u16 rcpRom[] = {
0xffff, 0xff00, 0xfe01, 0xfd04, 0xfc07, 0xfb0c, 0xfa11, 0xf918, 0xf81f, 0xf727, 0xf631, 0xf53b, 0xf446, 0xf352, 0xf25f, 0xf16d,
0xf07c, 0xef8b, 0xee9c, 0xedae, 0xecc0, 0xebd3, 0xeae8, 0xe9fd, 0xe913, 0xe829, 0xe741, 0xe65a, 0xe573, 0xe48d, 0xe3a9, 0xe2c5,
0xe1e1, 0xe0ff, 0xe01e, 0xdf3d, 0xde5d, 0xdd7e, 0xdca0, 0xdbc2, 0xdae6, 0xda0a, 0xd92f, 0xd854, 0xd77b, 0xd6a2, 0xd5ca, 0xd4f3,
0xd41d, 0xd347, 0xd272, 0xd19e, 0xd0cb, 0xcff8, 0xcf26, 0xce55, 0xcd85, 0xccb5, 0xcbe6, 0xcb18, 0xca4b, 0xc97e, 0xc8b2, 0xc7e7,
0xc71c, 0xc652, 0xc589, 0xc4c0, 0xc3f8, 0xc331, 0xc26b, 0xc1a5, 0xc0e0, 0xc01c, 0xbf58, 0xbe95, 0xbdd2, 0xbd10, 0xbc4f, 0xbb8f,
0xbacf, 0xba10, 0xb951, 0xb894, 0xb7d6, 0xb71a, 0xb65e, 0xb5a2, 0xb4e8, 0xb42e, 0xb374, 0xb2bb, 0xb203, 0xb14b, 0xb094, 0xafde,
0xaf28, 0xae73, 0xadbe, 0xad0a, 0xac57, 0xaba4, 0xaaf1, 0xaa40, 0xa98e, 0xa8de, 0xa82e, 0xa77e, 0xa6d0, 0xa621, 0xa574, 0xa4c6,
0xa41a, 0xa36e, 0xa2c2, 0xa217, 0xa16d, 0xa0c3, 0xa01a, 0x9f71, 0x9ec8, 0x9e21, 0x9d79, 0x9cd3, 0x9c2d, 0x9b87, 0x9ae2, 0x9a3d,
0x9999, 0x98f6, 0x9852, 0x97b0, 0x970e, 0x966c, 0x95cb, 0x952b, 0x948b, 0x93eb, 0x934c, 0x92ad, 0x920f, 0x9172, 0x90d4, 0x9038,
0x8f9c, 0x8f00, 0x8e65, 0x8dca, 0x8d30, 0x8c96, 0x8bfc, 0x8b64, 0x8acb, 0x8a33, 0x899c, 0x8904, 0x886e, 0x87d8, 0x8742, 0x86ad,
0x8618, 0x8583, 0x84f0, 0x845c, 0x83c9, 0x8336, 0x82a4, 0x8212, 0x8181, 0x80f0, 0x8060, 0x7fd0, 0x7f40, 0x7eb1, 0x7e22, 0x7d93,
0x7d05, 0x7c78, 0x7beb, 0x7b5e, 0x7ad2, 0x7a46, 0x79ba, 0x792f, 0x78a4, 0x781a, 0x7790, 0x7706, 0x767d, 0x75f5, 0x756c, 0x74e4,
0x745d, 0x73d5, 0x734f, 0x72c8, 0x7242, 0x71bc, 0x7137, 0x70b2, 0x702e, 0x6fa9, 0x6f26, 0x6ea2, 0x6e1f, 0x6d9c, 0x6d1a, 0x6c98,
0x6c16, 0x6b95, 0x6b14, 0x6a94, 0x6a13, 0x6993, 0x6914, 0x6895, 0x6816, 0x6798, 0x6719, 0x669c, 0x661e, 0x65a1, 0x6524, 0x64a8,
0x642c, 0x63b0, 0x6335, 0x62ba, 0x623f, 0x61c5, 0x614b, 0x60d1, 0x6058, 0x5fdf, 0x5f66, 0x5eed, 0x5e75, 0x5dfd, 0x5d86, 0x5d0f,
0x5c98, 0x5c22, 0x5bab, 0x5b35, 0x5ac0, 0x5a4b, 0x59d6, 0x5961, 0x58ed, 0x5879, 0x5805, 0x5791, 0x571e, 0x56ac, 0x5639, 0x55c7,
0x5555, 0x54e3, 0x5472, 0x5401, 0x5390, 0x5320, 0x52af, 0x5240, 0x51d0, 0x5161, 0x50f2, 0x5083, 0x5015, 0x4fa6, 0x4f38, 0x4ecb,
0x4e5e, 0x4df1, 0x4d84, 0x4d17, 0x4cab, 0x4c3f, 0x4bd3, 0x4b68, 0x4afd, 0x4a92, 0x4a27, 0x49bd, 0x4953, 0x48e9, 0x4880, 0x4817,
0x47ae, 0x4745, 0x46dc, 0x4674, 0x460c, 0x45a5, 0x453d, 0x44d6, 0x446f, 0x4408, 0x43a2, 0x433c, 0x42d6, 0x4270, 0x420b, 0x41a6,
0x4141, 0x40dc, 0x4078, 0x4014, 0x3fb0, 0x3f4c, 0x3ee8, 0x3e85, 0x3e22, 0x3dc0, 0x3d5d, 0x3cfb, 0x3c99, 0x3c37, 0x3bd6, 0x3b74,
0x3b13, 0x3ab2, 0x3a52, 0x39f1, 0x3991, 0x3931, 0x38d2, 0x3872, 0x3813, 0x37b4, 0x3755, 0x36f7, 0x3698, 0x363a, 0x35dc, 0x357f,
0x3521, 0x34c4, 0x3467, 0x340a, 0x33ae, 0x3351, 0x32f5, 0x3299, 0x323e, 0x31e2, 0x3187, 0x312c, 0x30d1, 0x3076, 0x301c, 0x2fc2,
0x2f68, 0x2f0e, 0x2eb4, 0x2e5b, 0x2e02, 0x2da9, 0x2d50, 0x2cf8, 0x2c9f, 0x2c47, 0x2bef, 0x2b97, 0x2b40, 0x2ae8, 0x2a91, 0x2a3a,
0x29e4, 0x298d, 0x2937, 0x28e0, 0x288b, 0x2835, 0x27df, 0x278a, 0x2735, 0x26e0, 0x268b, 0x2636, 0x25e2, 0x258d, 0x2539, 0x24e5,
0x2492, 0x243e, 0x23eb, 0x2398, 0x2345, 0x22f2, 0x22a0, 0x224d, 0x21fb, 0x21a9, 0x2157, 0x2105, 0x20b4, 0x2063, 0x2012, 0x1fc1,
0x1f70, 0x1f1f, 0x1ecf, 0x1e7f, 0x1e2e, 0x1ddf, 0x1d8f, 0x1d3f, 0x1cf0, 0x1ca1, 0x1c52, 0x1c03, 0x1bb4, 0x1b66, 0x1b17, 0x1ac9,
0x1a7b, 0x1a2d, 0x19e0, 0x1992, 0x1945, 0x18f8, 0x18ab, 0x185e, 0x1811, 0x17c4, 0x1778, 0x172c, 0x16e0, 0x1694, 0x1648, 0x15fd,
0x15b1, 0x1566, 0x151b, 0x14d0, 0x1485, 0x143b, 0x13f0, 0x13a6, 0x135c, 0x1312, 0x12c8, 0x127f, 0x1235, 0x11ec, 0x11a3, 0x1159,
0x1111, 0x10c8, 0x107f, 0x1037, 0x0fef, 0x0fa6, 0x0f5e, 0x0f17, 0x0ecf, 0x0e87, 0x0e40, 0x0df9, 0x0db2, 0x0d6b, 0x0d24, 0x0cdd,
0x0c97, 0x0c50, 0x0c0a, 0x0bc4, 0x0b7e, 0x0b38, 0x0af2, 0x0aad, 0x0a68, 0x0a22, 0x09dd, 0x0998, 0x0953, 0x090f, 0x08ca, 0x0886,
0x0842, 0x07fd, 0x07b9, 0x0776, 0x0732, 0x06ee, 0x06ab, 0x0668, 0x0624, 0x05e1, 0x059e, 0x055c, 0x0519, 0x04d6, 0x0494, 0x0452,
0x0410, 0x03ce, 0x038c, 0x034a, 0x0309, 0x02c7, 0x0286, 0x0245, 0x0204, 0x01c3, 0x0182, 0x0141, 0x0101, 0x00c0, 0x0080, 0x0040
};

View File

@@ -1,8 +1,8 @@
#include <n64/core/RDP.hpp> #include <core/RDP.hpp>
#include <util.hpp> #include <log.hpp>
#include <n64/core/RSP.hpp> #include <core/RSP.hpp>
#include <parallel-rdp/ParallelRDPWrapper.hpp> #include <parallel-rdp/ParallelRDPWrapper.hpp>
#include <n64/core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
namespace n64 { namespace n64 {
RDP::RDP() { RDP::RDP() {

View File

@@ -80,4 +80,4 @@ struct RDP {
RunCommand(mi, regs, rsp); RunCommand(mi, regs, rsp);
} }
}; };
} // n64 } // backend

View File

@@ -1,7 +1,7 @@
#include <n64/core/RSP.hpp> #include <core/RSP.hpp>
#include <util.hpp> #include <log.hpp>
#include <n64/core/Mem.hpp> #include <core/Mem.hpp>
#include <n64/core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
namespace n64 { namespace n64 {
RSP::RSP() { RSP::RSP() {

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <n64/core/mmio/MI.hpp> #include <core/mmio/MI.hpp>
#include <n64/core/RDP.hpp> #include <core/RDP.hpp>
#include <n64/memory_regions.hpp> #include <MemoryRegions.hpp>
#include <Interrupt.hpp> #include <Interrupt.hpp>
#define RSP_BYTE(addr) (dmem[BYTE_ADDRESS(addr) & 0xFFF]) #define RSP_BYTE(addr) (dmem[BYTE_ADDRESS(addr) & 0xFFF])

37
src/backend/core/RSQ.hpp Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include <common.hpp>
static constexpr u16 rsqRom[] = {
0xffff, 0xff00, 0xfe02, 0xfd06, 0xfc0b, 0xfb12, 0xfa1a, 0xf923, 0xf82e, 0xf73b, 0xf648, 0xf557, 0xf467, 0xf379, 0xf28c, 0xf1a0,
0xf0b6, 0xefcd, 0xeee5, 0xedff, 0xed19, 0xec35, 0xeb52, 0xea71, 0xe990, 0xe8b1, 0xe7d3, 0xe6f6, 0xe61b, 0xe540, 0xe467, 0xe38e,
0xe2b7, 0xe1e1, 0xe10d, 0xe039, 0xdf66, 0xde94, 0xddc4, 0xdcf4, 0xdc26, 0xdb59, 0xda8c, 0xd9c1, 0xd8f7, 0xd82d, 0xd765, 0xd69e,
0xd5d7, 0xd512, 0xd44e, 0xd38a, 0xd2c8, 0xd206, 0xd146, 0xd086, 0xcfc7, 0xcf0a, 0xce4d, 0xcd91, 0xccd6, 0xcc1b, 0xcb62, 0xcaa9,
0xc9f2, 0xc93b, 0xc885, 0xc7d0, 0xc71c, 0xc669, 0xc5b6, 0xc504, 0xc453, 0xc3a3, 0xc2f4, 0xc245, 0xc198, 0xc0eb, 0xc03f, 0xbf93,
0xbee9, 0xbe3f, 0xbd96, 0xbced, 0xbc46, 0xbb9f, 0xbaf8, 0xba53, 0xb9ae, 0xb90a, 0xb867, 0xb7c5, 0xb723, 0xb681, 0xb5e1, 0xb541,
0xb4a2, 0xb404, 0xb366, 0xb2c9, 0xb22c, 0xb191, 0xb0f5, 0xb05b, 0xafc1, 0xaf28, 0xae8f, 0xadf7, 0xad60, 0xacc9, 0xac33, 0xab9e,
0xab09, 0xaa75, 0xa9e1, 0xa94e, 0xa8bc, 0xa82a, 0xa799, 0xa708, 0xa678, 0xa5e8, 0xa559, 0xa4cb, 0xa43d, 0xa3b0, 0xa323, 0xa297,
0xa20b, 0xa180, 0xa0f6, 0xa06c, 0x9fe2, 0x9f59, 0x9ed1, 0x9e49, 0x9dc2, 0x9d3b, 0x9cb4, 0x9c2f, 0x9ba9, 0x9b25, 0x9aa0, 0x9a1c,
0x9999, 0x9916, 0x9894, 0x9812, 0x9791, 0x9710, 0x968f, 0x960f, 0x9590, 0x9511, 0x9492, 0x9414, 0x9397, 0x931a, 0x929d, 0x9221,
0x91a5, 0x9129, 0x90af, 0x9034, 0x8fba, 0x8f40, 0x8ec7, 0x8e4f, 0x8dd6, 0x8d5e, 0x8ce7, 0x8c70, 0x8bf9, 0x8b83, 0x8b0d, 0x8a98,
0x8a23, 0x89ae, 0x893a, 0x88c6, 0x8853, 0x87e0, 0x876d, 0x86fb, 0x8689, 0x8618, 0x85a7, 0x8536, 0x84c6, 0x8456, 0x83e7, 0x8377,
0x8309, 0x829a, 0x822c, 0x81bf, 0x8151, 0x80e4, 0x8078, 0x800c, 0x7fa0, 0x7f34, 0x7ec9, 0x7e5e, 0x7df4, 0x7d8a, 0x7d20, 0x7cb6,
0x7c4d, 0x7be5, 0x7b7c, 0x7b14, 0x7aac, 0x7a45, 0x79de, 0x7977, 0x7911, 0x78ab, 0x7845, 0x77df, 0x777a, 0x7715, 0x76b1, 0x764d,
0x75e9, 0x7585, 0x7522, 0x74bf, 0x745d, 0x73fa, 0x7398, 0x7337, 0x72d5, 0x7274, 0x7213, 0x71b3, 0x7152, 0x70f2, 0x7093, 0x7033,
0x6fd4, 0x6f76, 0x6f17, 0x6eb9, 0x6e5b, 0x6dfd, 0x6da0, 0x6d43, 0x6ce6, 0x6c8a, 0x6c2d, 0x6bd1, 0x6b76, 0x6b1a, 0x6abf, 0x6a64,
0x6a09, 0x6955, 0x68a1, 0x67ef, 0x673e, 0x668d, 0x65de, 0x6530, 0x6482, 0x63d6, 0x632b, 0x6280, 0x61d7, 0x612e, 0x6087, 0x5fe0,
0x5f3a, 0x5e95, 0x5df1, 0x5d4e, 0x5cac, 0x5c0b, 0x5b6b, 0x5acb, 0x5a2c, 0x598f, 0x58f2, 0x5855, 0x57ba, 0x5720, 0x5686, 0x55ed,
0x5555, 0x54be, 0x5427, 0x5391, 0x52fc, 0x5268, 0x51d5, 0x5142, 0x50b0, 0x501f, 0x4f8e, 0x4efe, 0x4e6f, 0x4de1, 0x4d53, 0x4cc6,
0x4c3a, 0x4baf, 0x4b24, 0x4a9a, 0x4a10, 0x4987, 0x48ff, 0x4878, 0x47f1, 0x476b, 0x46e5, 0x4660, 0x45dc, 0x4558, 0x44d5, 0x4453,
0x43d1, 0x434f, 0x42cf, 0x424f, 0x41cf, 0x4151, 0x40d2, 0x4055, 0x3fd8, 0x3f5b, 0x3edf, 0x3e64, 0x3de9, 0x3d6e, 0x3cf5, 0x3c7c,
0x3c03, 0x3b8b, 0x3b13, 0x3a9c, 0x3a26, 0x39b0, 0x393a, 0x38c5, 0x3851, 0x37dd, 0x3769, 0x36f6, 0x3684, 0x3612, 0x35a0, 0x352f,
0x34bf, 0x344f, 0x33df, 0x3370, 0x3302, 0x3293, 0x3226, 0x31b9, 0x314c, 0x30df, 0x3074, 0x3008, 0x2f9d, 0x2f33, 0x2ec8, 0x2e5f,
0x2df6, 0x2d8d, 0x2d24, 0x2cbc, 0x2c55, 0x2bee, 0x2b87, 0x2b21, 0x2abb, 0x2a55, 0x29f0, 0x298b, 0x2927, 0x28c3, 0x2860, 0x27fd,
0x279a, 0x2738, 0x26d6, 0x2674, 0x2613, 0x25b2, 0x2552, 0x24f2, 0x2492, 0x2432, 0x23d3, 0x2375, 0x2317, 0x22b9, 0x225b, 0x21fe,
0x21a1, 0x2145, 0x20e8, 0x208d, 0x2031, 0x1fd6, 0x1f7b, 0x1f21, 0x1ec7, 0x1e6d, 0x1e13, 0x1dba, 0x1d61, 0x1d09, 0x1cb1, 0x1c59,
0x1c01, 0x1baa, 0x1b53, 0x1afc, 0x1aa6, 0x1a50, 0x19fa, 0x19a5, 0x1950, 0x18fb, 0x18a7, 0x1853, 0x17ff, 0x17ab, 0x1758, 0x1705,
0x16b2, 0x1660, 0x160d, 0x15bc, 0x156a, 0x1519, 0x14c8, 0x1477, 0x1426, 0x13d6, 0x1386, 0x1337, 0x12e7, 0x1298, 0x1249, 0x11fb,
0x11ac, 0x115e, 0x1111, 0x10c3, 0x1076, 0x1029, 0x0fdc, 0x0f8f, 0x0f43, 0x0ef7, 0x0eab, 0x0e60, 0x0e15, 0x0dca, 0x0d7f, 0x0d34,
0x0cea, 0x0ca0, 0x0c56, 0x0c0c, 0x0bc3, 0x0b7a, 0x0b31, 0x0ae8, 0x0aa0, 0x0a58, 0x0a10, 0x09c8, 0x0981, 0x0939, 0x08f2, 0x08ab,
0x0865, 0x081e, 0x07d8, 0x0792, 0x074d, 0x0707, 0x06c2, 0x067d, 0x0638, 0x05f3, 0x05af, 0x056a, 0x0526, 0x04e2, 0x049f, 0x045b,
0x0418, 0x03d5, 0x0392, 0x0350, 0x030d, 0x02cb, 0x0289, 0x0247, 0x0206, 0x01c4, 0x0183, 0x0142, 0x0101, 0x00c0, 0x0080, 0x0040
};

View File

@@ -1,6 +1,6 @@
#include <core/registers/Cop0.hpp> #include <core/registers/Cop0.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <util.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
void Cop0::mtc0(Registers& regs, u32 instr) { void Cop0::mtc0(Registers& regs, u32 instr) {

View File

@@ -1,6 +1,6 @@
#include <core/registers/Cop1.hpp> #include <core/registers/Cop1.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <n64/core/Mem.hpp> #include <core/Mem.hpp>
#include <cmath> #include <cmath>
#include <cfenv> #include <cfenv>

View File

@@ -1,5 +1,5 @@
#include <n64/core/Interpreter.hpp> #include <core/Interpreter.hpp>
#include <util.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
void Interpreter::special(Mem& mem, u32 instr) { void Interpreter::special(Mem& mem, u32 instr) {

View File

@@ -1,5 +1,4 @@
#include <n64/core/Interpreter.hpp> #include <core/Interpreter.hpp>
#include <util.hpp>
#define se_imm(x) ((s16)((x) & 0xFFFF)) #define se_imm(x) ((s16)((x) & 0xFFFF))
#define check_address_error(mask, addr) (((!regs.cop0.is_64bit_addressing) && (s32)(addr) != (addr)) || (((addr) & (mask)) != 0)) #define check_address_error(mask, addr) (((!regs.cop0.is_64bit_addressing) && (s32)(addr) != (addr)) || (((addr) & (mask)) != 0))

View File

@@ -1,8 +1,8 @@
#include <n64/core/mmio/AI.hpp> #include <core/mmio/AI.hpp>
#include <util.hpp> #include <log.hpp>
#include <n64/core/Mem.hpp> #include <core/Mem.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <n64/core/Audio.hpp> #include <core/Audio.hpp>
namespace n64 { namespace n64 {
void AI::Reset() { void AI::Reset() {

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <common.hpp> #include <common.hpp>
#include <n64/core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
namespace n64 { namespace n64 {
struct Mem; struct Mem;

View File

@@ -1,5 +1,5 @@
#include <n64/core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
#include <n64/core/mmio/MI.hpp> #include <core/mmio/MI.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
namespace n64 { namespace n64 {

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <common.hpp> #include <common.hpp>
#include <n64/core/mmio/MI.hpp> #include <core/mmio/MI.hpp>
namespace n64 { namespace n64 {

View File

@@ -1,7 +1,7 @@
#include <n64/core/mmio/MI.hpp> #include <core/mmio/MI.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <util.hpp> #include <log.hpp>
#include <n64/core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
#define MI_VERSION_REG 0x02020102 #define MI_VERSION_REG 0x02020102

View File

@@ -1,6 +1,6 @@
#include <n64/core/mmio/PI.hpp> #include <core/mmio/PI.hpp>
#include <util.hpp> #include <log.hpp>
#include <n64/core/Mem.hpp> #include <core/Mem.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
namespace n64 { namespace n64 {

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <common.hpp> #include <common.hpp>
#include <n64/core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
namespace n64 { namespace n64 {

View File

@@ -1,8 +1,8 @@
#include <n64/core/mmio/PIF.hpp> #include <core/mmio/PIF.hpp>
#include <n64/core/Mem.hpp> #include <core/Mem.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <util.hpp> #include <log.hpp>
#include "m64.hpp" #include <MupenMovie.hpp>
namespace n64 { namespace n64 {
static int channel = 0; static int channel = 0;

View File

@@ -1,5 +1,5 @@
#include <n64/core/mmio/RI.hpp> #include <core/mmio/RI.hpp>
#include <util.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
RI::RI() { RI::RI() {

View File

@@ -1,6 +1,6 @@
#include <n64/core/mmio/SI.hpp> #include <core/mmio/SI.hpp>
#include <n64/core/Mem.hpp> #include <core/Mem.hpp>
#include "Scheduler.hpp" #include <Scheduler.hpp>
namespace n64 { namespace n64 {
SI::SI() { SI::SI() {
@@ -45,7 +45,7 @@ void DMA(Mem& mem, Registers& regs) {
for(int i = 0; i < 64; i++) { for(int i = 0; i < 64; i++) {
mem.pifRam[i] = mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)]; mem.pifRam[i] = mem.mmio.rdp.rdram[BYTE_ADDRESS(si.dramAddr + i)];
} }
util::logdebug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})\n", si.pifAddr, si.dramAddr); util::debug("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})\n", si.pifAddr, si.dramAddr);
ProcessPIFCommands(mem.pifRam, si.controller, mem); ProcessPIFCommands(mem.pifRam, si.controller, mem);
} }
InterruptRaise(mem.mmio.mi, regs, Interrupt::SI); InterruptRaise(mem.mmio.mi, regs, Interrupt::SI);
@@ -67,7 +67,7 @@ void SI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
status.dmaBusy = true; status.dmaBusy = true;
toDram = false; toDram = false;
scheduler.enqueueRelative({SI_DMA_DELAY, DMA}); scheduler.enqueueRelative({SI_DMA_DELAY, DMA});
util::logdebug("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})\n", dramAddr, val & 0x1FFFFFFF); util::debug("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})\n", dramAddr, val & 0x1FFFFFFF);
} break; } break;
case 0x04800018: case 0x04800018:
InterruptLower(mem.mmio.mi, regs, Interrupt::SI); InterruptLower(mem.mmio.mi, regs, Interrupt::SI);

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include <common.hpp> #include <common.hpp>
#include <n64/core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
#include <n64/core/mmio/MI.hpp> #include <core/mmio/MI.hpp>
#include <n64/core/mmio/PIF.hpp> #include <core/mmio/PIF.hpp>
namespace n64 { namespace n64 {

View File

@@ -1,8 +1,8 @@
#include <n64/core/mmio/VI.hpp> #include <core/mmio/VI.hpp>
#include <util.hpp> #include <log.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <n64/core/mmio/MI.hpp> #include <core/mmio/MI.hpp>
#include <n64/core/mmio/Interrupt.hpp> #include <core/mmio/Interrupt.hpp>
namespace n64 { namespace n64 {
VI::VI () { VI::VI () {

View File

@@ -103,4 +103,4 @@ struct VI {
int numFields; int numFields;
int cyclesPerHalfline; int cyclesPerHalfline;
}; };
} // n64 } // backend

View File

@@ -1,7 +1,7 @@
#include <core/registers/Cop0.hpp> #include <core/registers/Cop0.hpp>
#include <util.hpp> #include <log.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <n64/core/Interpreter.hpp> #include <core/Interpreter.hpp>
namespace n64 { namespace n64 {
Cop0::Cop0() { Cop0::Cop0() {

View File

@@ -1,7 +1,7 @@
#include <core/registers/Cop1.hpp> #include <core/registers/Cop1.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <n64/core/Interpreter.hpp> #include <core/Interpreter.hpp>
#include <util.hpp> #include <log.hpp>
namespace n64 { namespace n64 {
Cop1::Cop1() { Cop1::Cop1() {

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <core/registers/Cop0.hpp> #include <core/registers/Cop0.hpp>
#include <cstring>
namespace n64 { namespace n64 {
union FCR31 { union FCR31 {

View File

@@ -1,5 +1,5 @@
#include <n64/core/RSP.hpp> #include <core/RSP.hpp>
#include <util.hpp> #include <log.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <Interrupt.hpp> #include <Interrupt.hpp>
#include <Mem.hpp> #include <Mem.hpp>

View File

@@ -1,8 +1,9 @@
#include <RSP.hpp> #include <RSP.hpp>
#include <util.hpp> #include <log.hpp>
#include <core/registers/Registers.hpp> #include <core/registers/Registers.hpp>
#include <Mem.hpp> #include <Mem.hpp>
#include <rcp_rsq.hpp> #include <RCP.hpp>
#include <RSQ.hpp>
namespace n64 { namespace n64 {
inline bool AcquireSemaphore(RSP& rsp) { inline bool AcquireSemaphore(RSP& rsp) {
@@ -1093,7 +1094,7 @@ inline u32 rcp(s32 sinput) {
u64 dinput = (u64)input; u64 dinput = (u64)input;
u32 index = ((dinput << shift) & 0x7FC00000) >> 22; u32 index = ((dinput << shift) & 0x7FC00000) >> 22;
s32 result = rcp_rom[index]; s32 result = rcpRom[index];
result = (0x10000 | result) << 14; result = (0x10000 | result) << 14;
result = (result >> (31 - shift)) ^ mask; result = (result >> (31 - shift)) ^ mask;
return result; return result;
@@ -1115,7 +1116,7 @@ inline u32 rsq(u32 input) {
int shift = __builtin_clz(input) + 1; int shift = __builtin_clz(input) + 1;
int index = (((input << shift) >> 24) | ((shift & 1) << 8)); int index = (((input << shift) >> 24) | ((shift & 1) << 8));
u32 rom = (((u32)rsq_rom[index]) << 14); u32 rom = (((u32)rsqRom[index]) << 14);
int r_shift = ((32 - shift) >> 1); int r_shift = ((32 - shift) >> 1);
u32 result = (0x40000000 | rom) >> r_shift; u32 result = (0x40000000 | rom) >> r_shift;

View File

@@ -1,8 +1,6 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <bitset> #include <bitset>
#include <fmt/format.h>
#include <fmt/color.h>
using u8 = uint8_t; using u8 = uint8_t;
using u16 = uint16_t; using u16 = uint16_t;
@@ -15,9 +13,6 @@ using s64 = int64_t;
using u128 = __uint128_t; using u128 = __uint128_t;
using s128 = __int128_t; using s128 = __int128_t;
#define KiB * 1024
#define MiB ((KiB) * 1024)
#define GiB ((MiB) * 1024)
#define N64_CPU_FREQ 93750000 #define N64_CPU_FREQ 93750000
#define N64_CYCLES_PER_FRAME ((N64_CPU_FREQ) / 60) #define N64_CYCLES_PER_FRAME ((N64_CPU_FREQ) / 60)
#define HALF_ADDRESS(addr) ((addr) ^ 2) #define HALF_ADDRESS(addr) ((addr) ^ 2)

View File

@@ -38,7 +38,7 @@ void App::Run() {
switch(event.key.keysym.sym) { switch(event.key.keysym.sym) {
case SDLK_o: { case SDLK_o: {
nfdchar_t* outpath; nfdchar_t* outpath;
const nfdu8filteritem_t filter {"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; const nfdu8filteritem_t filter {"Nintendo 64 roms", "backend,z64,v64,N64,Z64,V64"};
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr); nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
if(result == NFD_OKAY) { if(result == NFD_OKAY) {
LoadROM(outpath); LoadROM(outpath);

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <imgui/Window.hpp> #include <imgui/Window.hpp>
#include <util.hpp> #include <Discord.hpp>
struct App { struct App {
App(); App();

View File

@@ -4,8 +4,8 @@
#include <fstream> #include <fstream>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <fmt/format.h> #include <fmt/format.h>
#include <Mem.hpp> #include <MemoryHelpers.hpp>
#include <execution> #include <File.hpp>
using namespace nlohmann; using namespace nlohmann;
namespace fs = std::filesystem; namespace fs = std::filesystem;
@@ -18,7 +18,7 @@ GameList::GameList(const std::string& path) {
for(const auto& p : fs::directory_iterator{path}) { for(const auto& p : fs::directory_iterator{path}) {
const auto filename = p.path().string(); const auto filename = p.path().string();
if(p.path().extension() == ".n64" || p.path().extension() == ".z64" || p.path().extension() == ".v64" || if(p.path().extension() == ".backend" || p.path().extension() == ".z64" || p.path().extension() == ".v64" ||
p.path().extension() == ".N64" || p.path().extension() == ".Z64" || p.path().extension() == ".V64") { p.path().extension() == ".N64" || p.path().extension() == ".Z64" || p.path().extension() == ".V64") {
std::ifstream file(filename, std::ios::binary); std::ifstream file(filename, std::ios::binary);
file.unsetf(std::ios::skipws); file.unsetf(std::ios::skipws);

View File

@@ -1,19 +1,31 @@
#include <Settings.hpp> #include <Settings.hpp>
#include <fstream> #include <fstream>
#include <filesystem> #include <filesystem>
#include <utilities.hpp>
#include <nfd.h> #include <nfd.h>
#include <Widgets.hpp>
namespace fs = std::filesystem; namespace fs = std::filesystem;
#define checkjsonentry(name, type, param1, param2, defaultVal) \
do { \
auto name##Entry = settings[param1][param2]; \
if(!name##Entry.empty()) { \
auto value = name##Entry.get<type>(); \
name = value; \
} else { \
settingsFile.clear(); \
settings[param1][param2] = defaultVal; \
settingsFile << settings; \
name = defaultVal; \
} \
} while(0)
Settings::Settings(n64::Core& core) { Settings::Settings(n64::Core& core) {
auto modes = std::fstream::in | std::fstream::out;
auto fileExists = fs::exists("resources/settings.json"); auto fileExists = fs::exists("resources/settings.json");
if(!fileExists) { std::fstream settingsFile;
modes |= std::fstream::trunc;
}
std::fstream settingsFile{"resources/settings.json", modes};
if(fileExists) { if(fileExists) {
settingsFile = std::fstream("resources/settings.json", std::fstream::in | std::fstream::out);
settings = json::parse(settingsFile); settings = json::parse(settingsFile);
auto entryCpuType = settings["cpu"]["type"]; auto entryCpuType = settings["cpu"]["type"];
if(!entryCpuType.empty()) { if(!entryCpuType.empty()) {
@@ -37,6 +49,7 @@ Settings::Settings(n64::Core& core) {
checkjsonentry(lockChannels, bool, "audio", "lockChannels", true); checkjsonentry(lockChannels, bool, "audio", "lockChannels", true);
checkjsonentry(gamesDir, std::string, "general", "gamesDir", ""); checkjsonentry(gamesDir, std::string, "general", "gamesDir", "");
} else { } else {
settingsFile = std::fstream("resources/settings.json", std::fstream::trunc | std::fstream::in | std::fstream::out);
settings["general"]["gamesDir"] = ""; settings["general"]["gamesDir"] = "";
settings["cpu"]["type"] = "interpreter"; settings["cpu"]["type"] = "interpreter";
settings["audio"]["volumeR"] = 0.5; settings["audio"]["volumeR"] = 0.5;
@@ -51,17 +64,23 @@ Settings::Settings(n64::Core& core) {
settingsFile << settings; settingsFile << settings;
} }
settingsFile.close(); settingsFile.close();
} }
Settings::~Settings() { Settings::~Settings() {
auto modes = std::fstream::out;
auto fileExists = fs::exists("resources/settings.json"); auto fileExists = fs::exists("resources/settings.json");
std::fstream settingsFile;
if(fileExists) { if(fileExists) {
modes = modes | std::fstream::trunc; settingsFile = std::fstream("resources/settings.json", std::fstream::trunc | std::fstream::out);
std::fstream settingsFile{"resources/settings.json", modes}; settings["general"]["gamesDir"] = gamesDir;
settings["cpu"]["type"] = cpuType;
settings["audio"]["volumeR"] = volumeR;
settings["audio"]["volumeL"] = volumeL;
settings["audio"]["lockChannels"] = lockChannels;
settingsFile << settings;
} else {
settingsFile = std::fstream("resources/settings.json", std::fstream::out);
settings["general"]["gamesDir"] = gamesDir; settings["general"]["gamesDir"] = gamesDir;
settings["cpu"]["type"] = cpuType; settings["cpu"]["type"] = cpuType;
@@ -69,8 +88,9 @@ Settings::~Settings() {
settings["audio"]["volumeL"] = volumeL; settings["audio"]["volumeL"] = volumeL;
settings["audio"]["lockChannels"] = lockChannels; settings["audio"]["lockChannels"] = lockChannels;
settingsFile << settings; settingsFile << settings;
settingsFile.close();
} }
settingsFile.close();
} }
void Settings::RenderWidget(bool& show) { void Settings::RenderWidget(bool& show) {

View File

@@ -0,0 +1,21 @@
#pragma once
#include <imgui.h>
inline bool CreateComboList(const char* label, int* index, const char** items, int items_count) {
if (ImGui::BeginCombo(label, items[*index])) {
for (int n = 0; n < items_count; n++) {
const bool is_selected = (*index == n);
if (ImGui::Selectable(items[n], is_selected)) {
*index = n;
}
if (is_selected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
return true;
}
return false;
}

View File

@@ -5,9 +5,11 @@
#include <Audio.hpp> #include <Audio.hpp>
#include <SDL.h> #include <SDL.h>
#include <iostream> #include <iostream>
#include <fstream>
#include <Discord.hpp>
VkInstance instance{}; VkInstance instance{};
using fs = std::filesystem; namespace fs = std::filesystem;
Window::Window(n64::Core& core) : settings(core), gameList(settings.GetGamesDir()) { Window::Window(n64::Core& core) : settings(core), gameList(settings.GetGamesDir()) {
InitSDL(); InitSDL();
@@ -209,7 +211,7 @@ float Window::Render(n64::Core& core) {
if (ImGui::BeginMenu("File")) { if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Open", "O")) { if (ImGui::MenuItem("Open", "O")) {
nfdchar_t *outpath; nfdchar_t *outpath;
const nfdu8filteritem_t filter{"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"}; const nfdu8filteritem_t filter{"Nintendo 64 roms", "backend,z64,v64,N64,Z64,V64"};
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr); nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
if (result == NFD_OKAY) { if (result == NFD_OKAY) {
LoadROM(core, outpath); LoadROM(core, outpath);

View File

@@ -1,36 +0,0 @@
#pragma once
#include <imgui.h>
inline bool CreateComboList(const char* label, int* index, const char** items, int items_count) {
if (ImGui::BeginCombo(label, items[*index])) {
for (int n = 0; n < items_count; n++) {
const bool is_selected = (*index == n);
if (ImGui::Selectable(items[n], is_selected)) {
*index = n;
}
if (is_selected) {
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
return true;
}
return false;
}
#define checkjsonentry(name, type, param1, param2, defaultVal) \
do { \
auto name##Entry = settings[param1][param2]; \
if(!name##Entry.empty()) { \
auto value = name##Entry.get<type>(); \
name = value; \
} else { \
settingsFile.clear(); \
settings[param1][param2] = defaultVal; \
settingsFile << settings; \
name = defaultVal; \
} \
} while(0)
}

View File

@@ -1,5 +1,5 @@
#include <frontend/App.hpp> #include <frontend/App.hpp>
#include "m64.hpp" #include <MupenMovie.hpp>
#ifdef _WIN32 #ifdef _WIN32
#define main SDL_main #define main SDL_main

View File

@@ -1,30 +0,0 @@
#pragma once
#include <n64/core/mmio/VI.hpp>
#include <n64/core/mmio/MI.hpp>
#include <n64/core/mmio/AI.hpp>
#include <n64/core/mmio/PI.hpp>
#include <n64/core/mmio/RI.hpp>
#include <n64/core/mmio/SI.hpp>
#include <n64/core/RSP.hpp>
#include <n64/core/RDP.hpp>
namespace n64 {
struct Mem;
struct Registers;
struct MMIO {
MMIO();
void Reset();
VI vi;
MI mi;
AI ai;
PI pi;
RI ri;
SI si;
RSP rsp;
RDP rdp;
u32 Read(u32);
void Write(Mem&, Registers&, u32, u32);
};
}

View File

@@ -1,72 +0,0 @@
#pragma once
#include <common.hpp>
static constexpr u16 rcp_rom[] = {
0xffff, 0xff00, 0xfe01, 0xfd04, 0xfc07, 0xfb0c, 0xfa11, 0xf918, 0xf81f, 0xf727, 0xf631, 0xf53b, 0xf446, 0xf352, 0xf25f, 0xf16d,
0xf07c, 0xef8b, 0xee9c, 0xedae, 0xecc0, 0xebd3, 0xeae8, 0xe9fd, 0xe913, 0xe829, 0xe741, 0xe65a, 0xe573, 0xe48d, 0xe3a9, 0xe2c5,
0xe1e1, 0xe0ff, 0xe01e, 0xdf3d, 0xde5d, 0xdd7e, 0xdca0, 0xdbc2, 0xdae6, 0xda0a, 0xd92f, 0xd854, 0xd77b, 0xd6a2, 0xd5ca, 0xd4f3,
0xd41d, 0xd347, 0xd272, 0xd19e, 0xd0cb, 0xcff8, 0xcf26, 0xce55, 0xcd85, 0xccb5, 0xcbe6, 0xcb18, 0xca4b, 0xc97e, 0xc8b2, 0xc7e7,
0xc71c, 0xc652, 0xc589, 0xc4c0, 0xc3f8, 0xc331, 0xc26b, 0xc1a5, 0xc0e0, 0xc01c, 0xbf58, 0xbe95, 0xbdd2, 0xbd10, 0xbc4f, 0xbb8f,
0xbacf, 0xba10, 0xb951, 0xb894, 0xb7d6, 0xb71a, 0xb65e, 0xb5a2, 0xb4e8, 0xb42e, 0xb374, 0xb2bb, 0xb203, 0xb14b, 0xb094, 0xafde,
0xaf28, 0xae73, 0xadbe, 0xad0a, 0xac57, 0xaba4, 0xaaf1, 0xaa40, 0xa98e, 0xa8de, 0xa82e, 0xa77e, 0xa6d0, 0xa621, 0xa574, 0xa4c6,
0xa41a, 0xa36e, 0xa2c2, 0xa217, 0xa16d, 0xa0c3, 0xa01a, 0x9f71, 0x9ec8, 0x9e21, 0x9d79, 0x9cd3, 0x9c2d, 0x9b87, 0x9ae2, 0x9a3d,
0x9999, 0x98f6, 0x9852, 0x97b0, 0x970e, 0x966c, 0x95cb, 0x952b, 0x948b, 0x93eb, 0x934c, 0x92ad, 0x920f, 0x9172, 0x90d4, 0x9038,
0x8f9c, 0x8f00, 0x8e65, 0x8dca, 0x8d30, 0x8c96, 0x8bfc, 0x8b64, 0x8acb, 0x8a33, 0x899c, 0x8904, 0x886e, 0x87d8, 0x8742, 0x86ad,
0x8618, 0x8583, 0x84f0, 0x845c, 0x83c9, 0x8336, 0x82a4, 0x8212, 0x8181, 0x80f0, 0x8060, 0x7fd0, 0x7f40, 0x7eb1, 0x7e22, 0x7d93,
0x7d05, 0x7c78, 0x7beb, 0x7b5e, 0x7ad2, 0x7a46, 0x79ba, 0x792f, 0x78a4, 0x781a, 0x7790, 0x7706, 0x767d, 0x75f5, 0x756c, 0x74e4,
0x745d, 0x73d5, 0x734f, 0x72c8, 0x7242, 0x71bc, 0x7137, 0x70b2, 0x702e, 0x6fa9, 0x6f26, 0x6ea2, 0x6e1f, 0x6d9c, 0x6d1a, 0x6c98,
0x6c16, 0x6b95, 0x6b14, 0x6a94, 0x6a13, 0x6993, 0x6914, 0x6895, 0x6816, 0x6798, 0x6719, 0x669c, 0x661e, 0x65a1, 0x6524, 0x64a8,
0x642c, 0x63b0, 0x6335, 0x62ba, 0x623f, 0x61c5, 0x614b, 0x60d1, 0x6058, 0x5fdf, 0x5f66, 0x5eed, 0x5e75, 0x5dfd, 0x5d86, 0x5d0f,
0x5c98, 0x5c22, 0x5bab, 0x5b35, 0x5ac0, 0x5a4b, 0x59d6, 0x5961, 0x58ed, 0x5879, 0x5805, 0x5791, 0x571e, 0x56ac, 0x5639, 0x55c7,
0x5555, 0x54e3, 0x5472, 0x5401, 0x5390, 0x5320, 0x52af, 0x5240, 0x51d0, 0x5161, 0x50f2, 0x5083, 0x5015, 0x4fa6, 0x4f38, 0x4ecb,
0x4e5e, 0x4df1, 0x4d84, 0x4d17, 0x4cab, 0x4c3f, 0x4bd3, 0x4b68, 0x4afd, 0x4a92, 0x4a27, 0x49bd, 0x4953, 0x48e9, 0x4880, 0x4817,
0x47ae, 0x4745, 0x46dc, 0x4674, 0x460c, 0x45a5, 0x453d, 0x44d6, 0x446f, 0x4408, 0x43a2, 0x433c, 0x42d6, 0x4270, 0x420b, 0x41a6,
0x4141, 0x40dc, 0x4078, 0x4014, 0x3fb0, 0x3f4c, 0x3ee8, 0x3e85, 0x3e22, 0x3dc0, 0x3d5d, 0x3cfb, 0x3c99, 0x3c37, 0x3bd6, 0x3b74,
0x3b13, 0x3ab2, 0x3a52, 0x39f1, 0x3991, 0x3931, 0x38d2, 0x3872, 0x3813, 0x37b4, 0x3755, 0x36f7, 0x3698, 0x363a, 0x35dc, 0x357f,
0x3521, 0x34c4, 0x3467, 0x340a, 0x33ae, 0x3351, 0x32f5, 0x3299, 0x323e, 0x31e2, 0x3187, 0x312c, 0x30d1, 0x3076, 0x301c, 0x2fc2,
0x2f68, 0x2f0e, 0x2eb4, 0x2e5b, 0x2e02, 0x2da9, 0x2d50, 0x2cf8, 0x2c9f, 0x2c47, 0x2bef, 0x2b97, 0x2b40, 0x2ae8, 0x2a91, 0x2a3a,
0x29e4, 0x298d, 0x2937, 0x28e0, 0x288b, 0x2835, 0x27df, 0x278a, 0x2735, 0x26e0, 0x268b, 0x2636, 0x25e2, 0x258d, 0x2539, 0x24e5,
0x2492, 0x243e, 0x23eb, 0x2398, 0x2345, 0x22f2, 0x22a0, 0x224d, 0x21fb, 0x21a9, 0x2157, 0x2105, 0x20b4, 0x2063, 0x2012, 0x1fc1,
0x1f70, 0x1f1f, 0x1ecf, 0x1e7f, 0x1e2e, 0x1ddf, 0x1d8f, 0x1d3f, 0x1cf0, 0x1ca1, 0x1c52, 0x1c03, 0x1bb4, 0x1b66, 0x1b17, 0x1ac9,
0x1a7b, 0x1a2d, 0x19e0, 0x1992, 0x1945, 0x18f8, 0x18ab, 0x185e, 0x1811, 0x17c4, 0x1778, 0x172c, 0x16e0, 0x1694, 0x1648, 0x15fd,
0x15b1, 0x1566, 0x151b, 0x14d0, 0x1485, 0x143b, 0x13f0, 0x13a6, 0x135c, 0x1312, 0x12c8, 0x127f, 0x1235, 0x11ec, 0x11a3, 0x1159,
0x1111, 0x10c8, 0x107f, 0x1037, 0x0fef, 0x0fa6, 0x0f5e, 0x0f17, 0x0ecf, 0x0e87, 0x0e40, 0x0df9, 0x0db2, 0x0d6b, 0x0d24, 0x0cdd,
0x0c97, 0x0c50, 0x0c0a, 0x0bc4, 0x0b7e, 0x0b38, 0x0af2, 0x0aad, 0x0a68, 0x0a22, 0x09dd, 0x0998, 0x0953, 0x090f, 0x08ca, 0x0886,
0x0842, 0x07fd, 0x07b9, 0x0776, 0x0732, 0x06ee, 0x06ab, 0x0668, 0x0624, 0x05e1, 0x059e, 0x055c, 0x0519, 0x04d6, 0x0494, 0x0452,
0x0410, 0x03ce, 0x038c, 0x034a, 0x0309, 0x02c7, 0x0286, 0x0245, 0x0204, 0x01c3, 0x0182, 0x0141, 0x0101, 0x00c0, 0x0080, 0x0040
};
static constexpr u16 rsq_rom[] = {
0xffff, 0xff00, 0xfe02, 0xfd06, 0xfc0b, 0xfb12, 0xfa1a, 0xf923, 0xf82e, 0xf73b, 0xf648, 0xf557, 0xf467, 0xf379, 0xf28c, 0xf1a0,
0xf0b6, 0xefcd, 0xeee5, 0xedff, 0xed19, 0xec35, 0xeb52, 0xea71, 0xe990, 0xe8b1, 0xe7d3, 0xe6f6, 0xe61b, 0xe540, 0xe467, 0xe38e,
0xe2b7, 0xe1e1, 0xe10d, 0xe039, 0xdf66, 0xde94, 0xddc4, 0xdcf4, 0xdc26, 0xdb59, 0xda8c, 0xd9c1, 0xd8f7, 0xd82d, 0xd765, 0xd69e,
0xd5d7, 0xd512, 0xd44e, 0xd38a, 0xd2c8, 0xd206, 0xd146, 0xd086, 0xcfc7, 0xcf0a, 0xce4d, 0xcd91, 0xccd6, 0xcc1b, 0xcb62, 0xcaa9,
0xc9f2, 0xc93b, 0xc885, 0xc7d0, 0xc71c, 0xc669, 0xc5b6, 0xc504, 0xc453, 0xc3a3, 0xc2f4, 0xc245, 0xc198, 0xc0eb, 0xc03f, 0xbf93,
0xbee9, 0xbe3f, 0xbd96, 0xbced, 0xbc46, 0xbb9f, 0xbaf8, 0xba53, 0xb9ae, 0xb90a, 0xb867, 0xb7c5, 0xb723, 0xb681, 0xb5e1, 0xb541,
0xb4a2, 0xb404, 0xb366, 0xb2c9, 0xb22c, 0xb191, 0xb0f5, 0xb05b, 0xafc1, 0xaf28, 0xae8f, 0xadf7, 0xad60, 0xacc9, 0xac33, 0xab9e,
0xab09, 0xaa75, 0xa9e1, 0xa94e, 0xa8bc, 0xa82a, 0xa799, 0xa708, 0xa678, 0xa5e8, 0xa559, 0xa4cb, 0xa43d, 0xa3b0, 0xa323, 0xa297,
0xa20b, 0xa180, 0xa0f6, 0xa06c, 0x9fe2, 0x9f59, 0x9ed1, 0x9e49, 0x9dc2, 0x9d3b, 0x9cb4, 0x9c2f, 0x9ba9, 0x9b25, 0x9aa0, 0x9a1c,
0x9999, 0x9916, 0x9894, 0x9812, 0x9791, 0x9710, 0x968f, 0x960f, 0x9590, 0x9511, 0x9492, 0x9414, 0x9397, 0x931a, 0x929d, 0x9221,
0x91a5, 0x9129, 0x90af, 0x9034, 0x8fba, 0x8f40, 0x8ec7, 0x8e4f, 0x8dd6, 0x8d5e, 0x8ce7, 0x8c70, 0x8bf9, 0x8b83, 0x8b0d, 0x8a98,
0x8a23, 0x89ae, 0x893a, 0x88c6, 0x8853, 0x87e0, 0x876d, 0x86fb, 0x8689, 0x8618, 0x85a7, 0x8536, 0x84c6, 0x8456, 0x83e7, 0x8377,
0x8309, 0x829a, 0x822c, 0x81bf, 0x8151, 0x80e4, 0x8078, 0x800c, 0x7fa0, 0x7f34, 0x7ec9, 0x7e5e, 0x7df4, 0x7d8a, 0x7d20, 0x7cb6,
0x7c4d, 0x7be5, 0x7b7c, 0x7b14, 0x7aac, 0x7a45, 0x79de, 0x7977, 0x7911, 0x78ab, 0x7845, 0x77df, 0x777a, 0x7715, 0x76b1, 0x764d,
0x75e9, 0x7585, 0x7522, 0x74bf, 0x745d, 0x73fa, 0x7398, 0x7337, 0x72d5, 0x7274, 0x7213, 0x71b3, 0x7152, 0x70f2, 0x7093, 0x7033,
0x6fd4, 0x6f76, 0x6f17, 0x6eb9, 0x6e5b, 0x6dfd, 0x6da0, 0x6d43, 0x6ce6, 0x6c8a, 0x6c2d, 0x6bd1, 0x6b76, 0x6b1a, 0x6abf, 0x6a64,
0x6a09, 0x6955, 0x68a1, 0x67ef, 0x673e, 0x668d, 0x65de, 0x6530, 0x6482, 0x63d6, 0x632b, 0x6280, 0x61d7, 0x612e, 0x6087, 0x5fe0,
0x5f3a, 0x5e95, 0x5df1, 0x5d4e, 0x5cac, 0x5c0b, 0x5b6b, 0x5acb, 0x5a2c, 0x598f, 0x58f2, 0x5855, 0x57ba, 0x5720, 0x5686, 0x55ed,
0x5555, 0x54be, 0x5427, 0x5391, 0x52fc, 0x5268, 0x51d5, 0x5142, 0x50b0, 0x501f, 0x4f8e, 0x4efe, 0x4e6f, 0x4de1, 0x4d53, 0x4cc6,
0x4c3a, 0x4baf, 0x4b24, 0x4a9a, 0x4a10, 0x4987, 0x48ff, 0x4878, 0x47f1, 0x476b, 0x46e5, 0x4660, 0x45dc, 0x4558, 0x44d5, 0x4453,
0x43d1, 0x434f, 0x42cf, 0x424f, 0x41cf, 0x4151, 0x40d2, 0x4055, 0x3fd8, 0x3f5b, 0x3edf, 0x3e64, 0x3de9, 0x3d6e, 0x3cf5, 0x3c7c,
0x3c03, 0x3b8b, 0x3b13, 0x3a9c, 0x3a26, 0x39b0, 0x393a, 0x38c5, 0x3851, 0x37dd, 0x3769, 0x36f6, 0x3684, 0x3612, 0x35a0, 0x352f,
0x34bf, 0x344f, 0x33df, 0x3370, 0x3302, 0x3293, 0x3226, 0x31b9, 0x314c, 0x30df, 0x3074, 0x3008, 0x2f9d, 0x2f33, 0x2ec8, 0x2e5f,
0x2df6, 0x2d8d, 0x2d24, 0x2cbc, 0x2c55, 0x2bee, 0x2b87, 0x2b21, 0x2abb, 0x2a55, 0x29f0, 0x298b, 0x2927, 0x28c3, 0x2860, 0x27fd,
0x279a, 0x2738, 0x26d6, 0x2674, 0x2613, 0x25b2, 0x2552, 0x24f2, 0x2492, 0x2432, 0x23d3, 0x2375, 0x2317, 0x22b9, 0x225b, 0x21fe,
0x21a1, 0x2145, 0x20e8, 0x208d, 0x2031, 0x1fd6, 0x1f7b, 0x1f21, 0x1ec7, 0x1e6d, 0x1e13, 0x1dba, 0x1d61, 0x1d09, 0x1cb1, 0x1c59,
0x1c01, 0x1baa, 0x1b53, 0x1afc, 0x1aa6, 0x1a50, 0x19fa, 0x19a5, 0x1950, 0x18fb, 0x18a7, 0x1853, 0x17ff, 0x17ab, 0x1758, 0x1705,
0x16b2, 0x1660, 0x160d, 0x15bc, 0x156a, 0x1519, 0x14c8, 0x1477, 0x1426, 0x13d6, 0x1386, 0x1337, 0x12e7, 0x1298, 0x1249, 0x11fb,
0x11ac, 0x115e, 0x1111, 0x10c3, 0x1076, 0x1029, 0x0fdc, 0x0f8f, 0x0f43, 0x0ef7, 0x0eab, 0x0e60, 0x0e15, 0x0dca, 0x0d7f, 0x0d34,
0x0cea, 0x0ca0, 0x0c56, 0x0c0c, 0x0bc3, 0x0b7a, 0x0b31, 0x0ae8, 0x0aa0, 0x0a58, 0x0a10, 0x09c8, 0x0981, 0x0939, 0x08f2, 0x08ab,
0x0865, 0x081e, 0x07d8, 0x0792, 0x074d, 0x0707, 0x06c2, 0x067d, 0x0638, 0x05f3, 0x05af, 0x056a, 0x0526, 0x04e2, 0x049f, 0x045b,
0x0418, 0x03d5, 0x0392, 0x0350, 0x030d, 0x02cb, 0x0289, 0x0247, 0x0206, 0x01c4, 0x0183, 0x0142, 0x0101, 0x00c0, 0x0080, 0x0040
};

View File

@@ -1,326 +0,0 @@
#pragma once
#include <common.hpp>
#include <type_traits>
#include <cassert>
#include <portable_endian_bswap.h>
#include <fstream>
#include <vector>
#include <array>
#include <chrono>
#include <functional>
#include <discord_rpc.h>
namespace util {
using SteadyClock = std::chrono::steady_clock;
using DurationMillis = std::chrono::duration<double, std::milli>;
using TimePoint = std::chrono::time_point<SteadyClock, DurationMillis>;
enum MessageType : u8 {
Info, Warn, Error
};
template <MessageType messageType = Info, typename ...Args>
constexpr void print(const std::string& fmt, Args... args) {
#ifndef _WIN32
if constexpr(messageType == Error) {
fmt::print(fmt::emphasis::bold | fg(fmt::color::red), fmt, args...);
exit(-1);
} else if constexpr(messageType == Warn) {
fmt::print(fg(fmt::color::yellow), fmt, args...);
} else if constexpr(messageType == Info) {
fmt::print(fmt, args...);
}
#else
if constexpr(messageType == Error) {
fmt::print(fmt, args...);
exit(-1);
} else {
fmt::print(fmt, args...);
}
#endif
}
template <typename ...Args>
constexpr void panic(const std::string& fmt, Args... args) {
print<Error>(fmt, args...);
}
template <typename ...Args>
constexpr void warn(const std::string& fmt, Args... args) {
print<Warn>(fmt, args...);
}
template <typename ...Args>
constexpr void info(const std::string& fmt, Args... args) {
print(fmt, args...);
}
template <typename ...Args>
constexpr void logdebug(const std::string& fmt, Args... args) {
#ifndef NDEBUG
print(fmt, args...);
#endif
}
template <typename T, bool HToBE = false>
[[maybe_unused]] 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);
}
return be16toh(num);
} else if constexpr(sizeof(T) == 4) {
if constexpr(HToBE) {
return htobe32(num);
}
return be32toh(num);
} else if constexpr(sizeof(T) == 8) {
if constexpr(HToBE) {
return htobe64(num);
}
return be64toh(num);
}
}
template <typename T>
inline T ReadAccess(u8* data, u32 index) {
if constexpr(sizeof(T) == 1) {
return data[index];
} else if constexpr (sizeof(T) == 2 || sizeof(T) == 4) {
T result = 0;
memcpy(&result, &data[index], sizeof(T));
return result;
} else {
static_assert(sizeof(T) == 8);
u32 hi = 0;
u32 lo = 0;
memcpy(&hi, &data[index + 0], sizeof(u32));
memcpy(&lo, &data[index + 4], sizeof(u32));
T result = ((T)hi << 32) | (T)lo;
return result;
}
}
template <typename T>
inline void WriteAccess(u8* data, u32 index, T val) {
if constexpr(sizeof(T) == 1) {
data[index] = val;
return;
} else if constexpr (sizeof(T) == 2 || sizeof(T) == 4){
memcpy(&data[index], &val, sizeof(T));
} else {
static_assert(sizeof(T) == 8);
u32 hi = val >> 32;
u32 lo = val;
memcpy(&data[index + 0], &hi, sizeof(u32));
memcpy(&data[index + 4], &lo, sizeof(u32));
}
}
inline void SwapBuffer32(size_t size, u8* data) {
for(int i = 0; i < size; i += 4) {
u32 original = *(u32*)&data[i];
*(u32*)&data[i] = bswap_32(original);
}
}
inline void SwapBuffer16(size_t size, u8* data) {
for(int i = 0; i < size; i += 2) {
u16 original = *(u16*)&data[i];
*(u16*)&data[i] = bswap_16(original);
}
}
inline u32 crc32(u32 crc, const u8 *buf, size_t len) {
static u32 table[256];
static int have_table = 0;
u32 rem;
u8 octet;
int i, j;
const u8 *p, *q;
if (have_table == 0) {
for (i = 0; i < 256; i++) {
rem = i;
for (j = 0; j < 8; j++) {
if (rem & 1) {
rem >>= 1;
rem ^= 0xedb88320;
} else
rem >>= 1;
}
table[i] = rem;
}
have_table = 1;
}
crc = ~crc;
q = buf + len;
for (p = buf; p < q; p++) {
octet = *p; /* Cast to unsigned octet. */
crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet];
}
return ~crc;
}
enum RomTypes {
Z64 = 0x80371240,
N64 = 0x40123780,
V64 = 0x37804012
};
inline void SwapN64RomJustCRC(size_t size, u8* rom, u32& crc) {
RomTypes endianness;
memcpy(&endianness, rom, 4);
endianness = static_cast<RomTypes>(be32toh(endianness));
switch(endianness) {
case RomTypes::V64: {
SwapBuffer16(size, rom);
crc = crc32(0, rom, size);
} break;
case RomTypes::N64: {
SwapBuffer32(size, rom);
crc = crc32(0, rom, size);
} break;
case RomTypes::Z64:
crc = crc32(0, rom, size);
break;
default:
panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!\n");
}
}
inline void SwapN64Rom(size_t size, u8* rom, u32& crc, u32& cicChecksum) {
RomTypes endianness;
memcpy(&endianness, rom, 4);
endianness = static_cast<RomTypes>(be32toh(endianness));
switch(endianness) {
case RomTypes::V64: {
u8* temp = (u8*)calloc(size, 1);
memcpy(temp, rom, size);
SwapBuffer16(size, temp);
crc = crc32(0, temp, size);
cicChecksum = crc32(0, &temp[0x40], 0x9c0);
free(temp);
SwapBuffer32(size, rom);
SwapBuffer16(size, rom);
} break;
case RomTypes::N64: {
u8* temp = (u8*)calloc(size, 1);
memcpy(temp, rom, size);
SwapBuffer32(size, temp);
crc = crc32(0, temp, size);
cicChecksum = crc32(0, &temp[0x40], 0x9c0);
free(temp);
} break;
case RomTypes::Z64:
crc = crc32(0, rom, size);
cicChecksum = crc32(0, &rom[0x40], 0x9c0);
SwapBuffer32(size, rom);
break;
default:
panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!\n");
}
}
template <size_t size, typename T = u8>
struct CircularBuffer {
CircularBuffer() : head(0) {
raw.fill(T());
}
// make it scroll
void PushValue(T val) {
raw[head] = val;
head++;
if(head == size) {
head = 0;
}
}
T PopValue() {
head--;
if(head == 0) {
head = size - 1;
}
return raw[head];
}
T& operator[](const int index) {
return raw[index];
}
auto begin() { return raw.begin(); }
auto end() { return raw.end(); }
auto fill(const T& u) { raw.fill(u); }
size_t GetHead() { return head; }
private:
std::array<T, size> raw;
size_t head;
};
inline size_t NextPow2(size_t num) {
// Taken from "Bit Twiddling Hacks" by Sean Anderson:
// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--num;
num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
return num + 1;
}
inline auto ReadFileBinary(const std::string& path, u32** buf) {
std::ifstream file(path, std::ios::binary);
file.unsetf(std::ios::skipws);
if(!file.is_open()) {
panic("Could not load file '{}'!\n", path);
}
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0, std::ios::beg);
*buf = (u32*)calloc(size, 1);
file.read(reinterpret_cast<char*>(*buf), size);
file.close();
return size;
}
enum State {
Idling,
Playing,
Paused
};
inline void UpdateRPC(State state, const std::string& game = "") {
DiscordRichPresence presence{};
std::string textState, textDetails;
switch(state) {
case Idling:
textDetails = "Idling";
break;
case Playing:
textDetails = "In-game";
textState = "Playing \"" + game + "\"";
break;
case Paused:
textDetails = "In-game";
textState = "Playing \"" + game + "\" (Paused)";
break;
}
presence.details = textDetails.c_str();
presence.state = textState.c_str();
presence.startTimestamp = time(nullptr);
presence.largeImageText = "Gadolinium";
presence.largeImageKey = "logo";
Discord_UpdatePresence(&presence);
}
inline void ClearRPC() {
Discord_ClearPresence();
}

34
src/utils/File.hpp Normal file
View File

@@ -0,0 +1,34 @@
#pragma once
#include <fstream>
#include <log.hpp>
namespace util {
inline auto ReadFileBinary(const std::string& path, u32** buf) {
std::ifstream file(path, std::ios::binary);
file.unsetf(std::ios::skipws);
if(!file.is_open()) {
panic("Could not load file '{}'!\n", path);
}
file.seekg(0, std::ios::end);
size_t size = file.tellg();
file.seekg(0, std::ios::beg);
*buf = (u32*)calloc(size, 1);
file.read(reinterpret_cast<char*>(*buf), size);
file.close();
return size;
}
inline size_t NextPow2(size_t num) {
// Taken from "Bit Twiddling Hacks" by Sean Anderson:
// https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--num;
num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
return num + 1;
}
}

154
src/utils/MemoryHelpers.hpp Normal file
View File

@@ -0,0 +1,154 @@
#pragma once
#include <common.hpp>
#include <cstring>
#include <portable_endian_bswap.h>
#include <log.hpp>
namespace util {
template<typename T>
inline T ReadAccess(u8 *data, u32 index) {
if constexpr (sizeof(T) == 1) {
return data[index];
} else if constexpr (sizeof(T) == 2 || sizeof(T) == 4) {
T result = 0;
memcpy(&result, &data[index], sizeof(T));
return result;
} else {
static_assert(sizeof(T) == 8);
u32 hi = 0;
u32 lo = 0;
memcpy(&hi, &data[index + 0], sizeof(u32));
memcpy(&lo, &data[index + 4], sizeof(u32));
T result = ((T) hi << 32) | (T) lo;
return result;
}
}
template<typename T>
inline void WriteAccess(u8 *data, u32 index, T val) {
if constexpr (sizeof(T) == 1) {
data[index] = val;
return;
} else if constexpr (sizeof(T) == 2 || sizeof(T) == 4) {
memcpy(&data[index], &val, sizeof(T));
} else {
static_assert(sizeof(T) == 8);
u32 hi = val >> 32;
u32 lo = val;
memcpy(&data[index + 0], &hi, sizeof(u32));
memcpy(&data[index + 4], &lo, sizeof(u32));
}
}
inline void SwapBuffer32(size_t size, u8 *data) {
for (int i = 0; i < size; i += 4) {
u32 original = *(u32 *) &data[i];
*(u32 *) &data[i] = bswap_32(original);
}
}
inline void SwapBuffer16(size_t size, u8 *data) {
for (int i = 0; i < size; i += 2) {
u16 original = *(u16 *) &data[i];
*(u16 *) &data[i] = bswap_16(original);
}
}
inline u32 crc32(u32 crc, const u8 *buf, size_t len) {
static u32 table[256];
static int have_table = 0;
u32 rem;
u8 octet;
int i, j;
const u8 *p, *q;
if (have_table == 0) {
for (i = 0; i < 256; i++) {
rem = i;
for (j = 0; j < 8; j++) {
if (rem & 1) {
rem >>= 1;
rem ^= 0xedb88320;
} else
rem >>= 1;
}
table[i] = rem;
}
have_table = 1;
}
crc = ~crc;
q = buf + len;
for (p = buf; p < q; p++) {
octet = *p; /* Cast to unsigned octet. */
crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet];
}
return ~crc;
}
enum RomTypes {
Z64 = 0x80371240,
N64 = 0x40123780,
V64 = 0x37804012
};
inline void SwapN64RomJustCRC(size_t size, u8 *rom, u32 &crc) {
RomTypes endianness;
memcpy(&endianness, rom, 4);
endianness = static_cast<RomTypes>(be32toh(endianness));
switch (endianness) {
case RomTypes::V64: {
SwapBuffer16(size, rom);
crc = crc32(0, rom, size);
}
break;
case RomTypes::N64: {
SwapBuffer32(size, rom);
crc = crc32(0, rom, size);
}
break;
case RomTypes::Z64:
crc = crc32(0, rom, size);
break;
default:
panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!\n");
}
}
inline void SwapN64Rom(size_t size, u8 *rom, u32 &crc, u32 &cicChecksum) {
RomTypes endianness;
memcpy(&endianness, rom, 4);
endianness = static_cast<RomTypes>(be32toh(endianness));
switch (endianness) {
case RomTypes::V64: {
u8 *temp = (u8 *) calloc(size, 1);
memcpy(temp, rom, size);
SwapBuffer16(size, temp);
crc = crc32(0, temp, size);
cicChecksum = crc32(0, &temp[0x40], 0x9c0);
free(temp);
SwapBuffer32(size, rom);
SwapBuffer16(size, rom);
}
break;
case RomTypes::N64: {
u8 *temp = (u8 *) calloc(size, 1);
memcpy(temp, rom, size);
SwapBuffer32(size, temp);
crc = crc32(0, temp, size);
cicChecksum = crc32(0, &temp[0x40], 0x9c0);
free(temp);
}
break;
case RomTypes::Z64:
crc = crc32(0, rom, size);
cicChecksum = crc32(0, &rom[0x40], 0x9c0);
SwapBuffer32(size, rom);
break;
default:
panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!\n");
}
}
}

59
src/utils/log.hpp Normal file
View File

@@ -0,0 +1,59 @@
#pragma once
#include <common.hpp>
#include <fmt/format.h>
#include <fmt/color.h>
namespace util {
enum MessageType : u8 {
Info, Debug, Warn, Error
};
template <MessageType messageType = Info, typename ...Args>
constexpr void print(const std::string& fmt, Args... args) {
#ifndef _WIN32
if constexpr(messageType == Error) {
fmt::print(fmt::emphasis::bold | fg(fmt::color::red), fmt, args...);
exit(-1);
} else if constexpr(messageType == Warn) {
fmt::print(fg(fmt::color::yellow), fmt, args...);
} else if constexpr(messageType == Info) {
fmt::print(fmt, args...);
} else if constexpr(messageType == Debug) {
#ifndef NDEBUG
fmt::print(fmt, args...);
#endif
}
#else
if constexpr(messageType == Error) {
fmt::print(fmt, args...);
exit(-1);
} else if constexpr(messageType == Debug) {
#ifndef NDEBUG
fmt::print(fmt, args...);
#endif
} else {
fmt::print(fmt, args...);
}
#endif
}
template <typename ...Args>
constexpr void panic(const std::string& fmt, Args... args) {
print<Error>(fmt, args...);
}
template <typename ...Args>
constexpr void warn(const std::string& fmt, Args... args) {
print<Warn>(fmt, args...);
}
template <typename ...Args>
constexpr void info(const std::string& fmt, Args... args) {
print(fmt, args...);
}
template <typename ...Args>
constexpr void debug(const std::string& fmt, Args... args) {
print<Debug>(fmt, args...);
}
}