Compare commits

..
3 Commits
Author SHA1 Message Date
iris cf0378719c Roms list properly handle sorting + use ircolib's log so i can stop worrying about re-definition of macros and shit 2026-06-15 17:06:15 +02:00
iris 642fc17391 Merge commit '00cc9309cb3a9e41afe5def8dcb9bf5b089b9a21' into dev 2026-06-15 11:56:38 +02:00
iris 00cc9309cb Squashed 'external/ircolib/' changes from ce3cd726c..de6e324bd
de6e324bd separate emu thread
10d3daf86 Roms List improvements
95d202f37 Let's make the rom list process on a separate thread so the emulator doesnt take ages to load.
fc306967f Wow the ROM Header was just completely busted. Game list view works now
bad1691ee fuck this shit
2b59e5f46 game list in progress
d26417b83 remappable inputs in progress
ac4af8106 input
e72abc240 update readme
430139dc9 Qt6 frontend
3080d4d45 Fix this small bug too
08cd13b85 Cop0 unused functions do not actually pose a threat (as per manual). They don't do anything, so shall we.
61bb4fb44 make idle loop detection a little more specific with where the load goes
b037de4c3 SAZDFsdff
12e81e73e need to figure out why n64-systemtest loops indefinitely at some address that appears to be valid (i think it's me not invalidating the cache properly)
204f0e13b idle skipping seems to work!
cb8bb634a sdkfjlasdf
58e5c89c1 Fix compilation issue on my machine (no idea)
24fb2898e attempting more serious idle skipping
214719577 Place rsp.Step inside cached interpreter. Gains about 3 more fps
bb97dcc23 mmmmm
920b77d38 wjkhasdfjhkasdf
430ccdab4 it's a start...
4f42a673a Cached interpreter plays Mario 64. Start looking into RSP as well
c9a030787 idle skipping works!
5fbda03ce new idea
366637aba Idle skipping... maybe?
609fa2fb0 Cache instructions implemented but broken lmao. Commented out for now
e140a6d12 - Stop using inheritance for CPU, instead use composition. - Introduce KAIZEN_JIT_ENABLED optional define instead of relying on __aarch64__ and the like. - More cache work
68e613057 prep cache impl
811b4d809 fix clang format
fda755f7d idk
d5024ebbf small MI refactor in preparation of (eventually) implementing the RDRAM interface properly
694b45341 Merge commit '206dcdedf195fb320913584180edb12c7731e396' as 'external/SDL'
206dcdedf Squashed 'external/SDL/' content from commit 4d17b99d0a
4d16e1cb4 need to update sdl
848b19920 Fix compilation error
db61b5299 Merge commit 'e94a94559f28e49678fbcf72199a5258137b0fe9' as 'external/imgui'
e94a94559 Squashed 'external/imgui/' content from commit 02e9b8cac
52edb3757 need to update imgui
c1a705e86 Emulate weird JALR behaviour
4b4c32f4b Fix exception for "unusable COP1" in 4 instructions i missed accidentally (again)
df5828142 Bug putting 0s in the log everywhere
f8b580048 Make isviewer a sink to file
8241e9735 Fix exception for "unusable COP1" in 4 instructions i missed accidentally
b29715f20 small changes
d9a620bc1 make use of my new small utility library
0d1aa938e Add 'external/ircolib/' from commit 'ce3cd726c8df8388d554abf8bb55d55020eb4450'
e64eb40b3 Fuck git

git-subtree-dir: external/ircolib
git-subtree-split: de6e324bde
2026-06-15 11:56:38 +02:00
53 changed files with 3131 additions and 3079 deletions
+26 -26
View File
@@ -1,43 +1,43 @@
#pragma once
#include <types.hpp>
#include <ircolib/types.hpp>
#include <fstream>
#include <vector>
#include <filesystem>
namespace ircolib {
namespace fs = std::filesystem;
namespace ircolib {
static inline std::vector<u8> ReadFileBinary(const std::string &path) {
std::ifstream file(path, std::ios::binary);
return {std::istreambuf_iterator{file}, {}};
static inline std::vector<u8> read_file_binary(const std::string &path) {
std::ifstream file(path, std::ios::binary);
return {std::istreambuf_iterator{file}, {}};
}
static inline void WriteFileBinary(const std::vector<u8> &data, const std::string &path) {
std::ofstream file(path, std::ios::binary);
std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file});
static inline void write_file_binary(const std::vector<u8> &data, const std::string &path) {
std::ofstream file(path, std::ios::binary);
std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file});
}
static inline void WriteFileBinary(const u8 *data, const size_t size, const std::string &path) {
FILE *out = fopen(path.c_str(), "wb");
fwrite(data, size, 1, out);
fclose(out);
static inline void write_file_binary(const u8 *data, const u32 size, const std::string &path) {
FILE *out = fopen(path.c_str(), "wb");
fwrite(data, size, 1, out);
fclose(out);
}
template <size_t Size>
static inline void WriteFileBinary(const std::array<u8, Size> &data, const std::string &path) {
std::ofstream file(path, std::ios::binary);
std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file});
static inline void write_file_binary(const std::array<u8, Size> &data, const std::string &path) {
std::ofstream file(path, std::ios::binary);
std::copy(data.begin(), data.end(), std::ostreambuf_iterator{file});
}
static 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;
static inline u32 next_pow2(u32 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;
}
} // namespace Util
} // namespace ircolib
+42 -43
View File
@@ -1,106 +1,105 @@
#pragma once
#include <cmath>
#include <types.hpp>
#include <ircolib/types.hpp>
namespace ircolib {
static inline auto roundCeil(float f) {
#ifdef SIMD_SUPPORT
__m128 t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_TO_POS_INF);
return _mm_cvtss_f32(t);
__m128 t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_TO_POS_INF);
return _mm_cvtss_f32(t);
#else
return ceilf(f);
return ceilf(f);
#endif
}
static inline auto roundCeil(double f) {
#ifdef SIMD_SUPPORT
__m128d t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_TO_POS_INF);
return _mm_cvtsd_f64(t);
__m128d t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_TO_POS_INF);
return _mm_cvtsd_f64(t);
#else
return ceil(f);
return ceil(f);
#endif
}
static inline auto roundNearest(float f) {
#ifdef SIMD_SUPPORT
__m128 t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_TO_NEAREST_INT);
return _mm_cvtss_f32(t);
__m128 t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_TO_NEAREST_INT);
return _mm_cvtss_f32(t);
#else
return roundf(f);
return roundf(f);
#endif
}
static inline auto roundNearest(double f) {
#ifdef SIMD_SUPPORT
__m128d t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_TO_NEAREST_INT);
return _mm_cvtsd_f64(t);
__m128d t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_TO_NEAREST_INT);
return _mm_cvtsd_f64(t);
#else
return round(f);
return round(f);
#endif
}
static inline auto roundCurrent(float f) {
#ifdef SIMD_SUPPORT
auto t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_CUR_DIRECTION);
return _mm_cvtss_f32(t);
auto t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_CUR_DIRECTION);
return _mm_cvtss_f32(t);
#else
return rint(f);
return rint(f);
#endif
}
static inline auto roundCurrent(double f) {
#ifdef SIMD_SUPPORT
auto t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_CUR_DIRECTION);
return _mm_cvtsd_f64(t);
auto t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_CUR_DIRECTION);
return _mm_cvtsd_f64(t);
#else
return rint(f);
return rint(f);
#endif
}
static inline auto roundFloor(float f) {
#ifdef SIMD_SUPPORT
__m128 t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_TO_NEG_INF);
return _mm_cvtss_f32(t);
__m128 t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_TO_NEG_INF);
return _mm_cvtss_f32(t);
#else
return floor(f);
return floor(f);
#endif
}
static inline auto roundFloor(double f) {
#ifdef SIMD_SUPPORT
__m128d t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_TO_NEG_INF);
return _mm_cvtsd_f64(t);
__m128d t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_TO_NEG_INF);
return _mm_cvtsd_f64(t);
#else
return floor(f);
return floor(f);
#endif
}
static inline auto roundTrunc(float f) {
#ifdef SIMD_SUPPORT
__m128 t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_TO_ZERO);
return _mm_cvtss_f32(t);
__m128 t = _mm_set_ss(f);
t = _mm_round_ss(t, t, _MM_FROUND_TO_ZERO);
return _mm_cvtss_f32(t);
#else
return trunc(f);
return trunc(f);
#endif
}
static inline auto roundTrunc(double f) {
#ifdef SIMD_SUPPORT
__m128d t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_TO_ZERO);
return _mm_cvtsd_f64(t);
__m128d t = _mm_set_sd(f);
t = _mm_round_sd(t, t, _MM_FROUND_TO_ZERO);
return _mm_cvtsd_f64(t);
#else
return trunc(f);
return trunc(f);
#endif
}
} // namespace Util
} // namespace ircolib
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include <print>
#include <ircolib/types.hpp>
namespace ircolib {
enum LogLevel : u8 { Trace, Debug, Info, Warn, Error, Always };
constexpr LogLevel globalLogLevel = Warn;
template <typename... Args>
void panic(std::format_string<Args...> fmt, Args &&...args) {
std::print("[FATAL] ");
std::println(fmt, std::forward<Args>(args)...);
exit(1);
}
template <typename... Args>
void error(std::format_string<Args...> fmt, Args &&...args) {
if (LogLevel::Error >= globalLogLevel) {
std::print("[ERROR] ");
std::println(fmt, std::forward<Args>(args)...);
}
}
template <typename... Args>
void warn(std::format_string<Args...> fmt, Args &&...args) {
if (LogLevel::Warn >= globalLogLevel) {
std::print("[WARN] ");
std::println(fmt, std::forward<Args>(args)...);
}
}
template <typename... Args>
void info(std::format_string<Args...> fmt, Args &&...args) {
if (LogLevel::Info >= globalLogLevel) {
std::print("[INFO] ");
std::println(fmt, std::forward<Args>(args)...);
}
}
template <typename... Args>
void debug(std::format_string<Args...> fmt, Args &&...args) {
if (LogLevel::Debug >= globalLogLevel) {
std::print("[DEBUG] ");
std::println(fmt, std::forward<Args>(args)...);
}
}
template <typename... Args>
void trace(std::format_string<Args...> fmt, Args &&...args) {
if (LogLevel::Trace >= globalLogLevel) {
std::print("[TRACE] ");
std::println(fmt, std::forward<Args>(args)...);
}
}
template <typename... Args>
void always(std::format_string<Args...> fmt, Args &&...args) {
std::println(fmt, std::forward<Args>(args)...);
}
} // namespace ircolib
+85 -71
View File
@@ -1,5 +1,6 @@
#pragma once
#include <types.hpp>
#include "types.hpp"
#include <cstddef>
#include <cstring>
#include <functional>
#include <bit>
@@ -8,139 +9,152 @@
#include <concepts>
namespace ircolib {
static inline std::vector<u8> IntegralToBuffer(const std::integral auto &val) {
std::vector<u8> ret{};
ret.resize(sizeof(val));
static inline std::vector<u8> integral_to_buffer(const std::integral auto &val) {
std::vector<u8> ret{};
ret.resize(sizeof(val));
memcpy(ret.data(), &val, sizeof(val));
memcpy(ret.data(), &val, sizeof(val));
return ret;
return ret;
}
static inline constexpr bool IsInsideRange(const std::integral auto& addr,
const std::integral auto& start,
const std::integral auto& end) {
return addr >= start && addr <= end;
static inline auto integral_to_slice(const std::integral auto &val) -> std::array<u8, sizeof(val)> {
std::array<u8, sizeof(val)> ret{};
memcpy(ret.data(), &val, sizeof(val));
return ret;
}
static inline constexpr bool is_inside_range(const std::integral auto &addr, const std::integral auto &start,
const std::integral auto &end) {
return addr >= start && addr <= end;
}
template <typename T>
static constexpr inline T ReadAccess(const u8 *data, const u32 index);
static constexpr inline T read_access(const u8 *data, const u32 index);
template <typename T>
static constexpr inline T ReadAccess(const std::vector<u8> &data, const u32 index);
static constexpr inline T read_access(const std::vector<u8> &data, const u32 index);
template <typename T, size_t Size>
static constexpr inline T ReadAccess(const std::array<u8, Size> &data, const u32 index);
static constexpr inline T read_access(const std::array<u8, Size> &data, const u32 index);
template <typename T>
static constexpr inline void WriteAccess(u8 *data, const u32 index, const T val);
static constexpr inline void write_access(u8 *data, const u32 index, const T val);
template <typename T>
static constexpr inline void WriteAccess(std::vector<u8> &data, const u32 index, const T val);
static constexpr inline void write_access(std::vector<u8> &data, const u32 index, const T val);
template <typename T, size_t Size>
static constexpr inline void WriteAccess(std::array<u8, Size> &data, const u32 index, const T val);
static constexpr inline void write_access(std::array<u8, Size> &data, const u32 index, const T val);
template <>
constexpr inline u64 ReadAccess(const u8 *data, const u32 index) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
const auto& result = static_cast<u64>(hi) << 32 | static_cast<u64>(lo);
return result;
constexpr inline u64 read_access(const u8 *data, const u32 index) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
const auto &result = static_cast<u64>(hi) << 32 | static_cast<u64>(lo);
return result;
}
template <typename T>
static constexpr inline T ReadAccess(const u8 *data, const u32 index) {
return *reinterpret_cast<const T *>(&data[index]);
static constexpr inline T read_access(const u8 *data, const u32 index) {
return *reinterpret_cast<const T *>(&data[index]);
}
template <>
constexpr inline u64 ReadAccess(const std::vector<u8> &data, const u32 index) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
return (static_cast<u64>(hi) << 32) | static_cast<u64>(lo);
constexpr inline u64 read_access(const std::vector<u8> &data, const u32 index) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
return (static_cast<u64>(hi) << 32) | static_cast<u64>(lo);
}
template <typename T>
static constexpr inline T ReadAccess(const std::vector<u8> &data, const u32 index) {
return *reinterpret_cast<const T *>(&data[index]);
static constexpr inline T read_access(const std::vector<u8> &data, const u32 index) {
return *reinterpret_cast<const T *>(&data[index]);
}
template <size_t Size>
constexpr inline u64 ReadAccess(const std::array<u8, Size> &data, const u32 index) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
return static_cast<u64>(hi) << 32 | static_cast<u64>(lo);
static constexpr inline u64 read_access(const std::array<u8, Size> &data, const u32 index) {
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
return static_cast<u64>(hi) << 32 | static_cast<u64>(lo);
}
template <typename T, size_t Size>
static constexpr inline T ReadAccess(const std::array<u8, Size> &data, const u32 index) {
return *reinterpret_cast<const T *>(&data[index]);
static constexpr inline T read_access(const std::array<u8, Size> &data, const u32 index) {
return *reinterpret_cast<const T *>(&data[index]);
}
template <size_t Size>
constexpr inline void WriteAccess(std::array<u8, Size> &data, const u32 index, const u64 val) {
const u32 hi = val >> 32;
const u32 lo = val;
static constexpr inline void write_access(std::array<u8, Size> &data, const u32 index, const u64 val) {
const u32 hi = val >> 32;
const u32 lo = val;
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
}
template <typename T, size_t Size>
static constexpr inline void WriteAccess(std::array<u8, Size> &data, const u32 index, const T val) {
*reinterpret_cast<T *>(&data[index]) = val;
static constexpr inline void write_access(std::array<u8, Size> &data, const u32 index, const T val) {
*reinterpret_cast<T *>(&data[index]) = val;
}
template <>
constexpr inline void WriteAccess(std::vector<u8> &data, const u32 index, const u64 val) {
const u32 hi = val >> 32;
const u32 lo = val;
constexpr inline void write_access(std::vector<u8> &data, const u32 index, const u64 val) {
const u32 hi = val >> 32;
const u32 lo = val;
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
}
template <typename T>
static constexpr inline void WriteAccess(std::vector<u8> &data, const u32 index, const T val) {
*reinterpret_cast<T *>(&data[index]) = val;
static constexpr inline void write_access(std::vector<u8> &data, const u32 index, const T val) {
*reinterpret_cast<T *>(&data[index]) = val;
}
template <>
constexpr inline void WriteAccess(u8 *data, const u32 index, const u64 val) {
const u32 hi = val >> 32;
const u32 lo = val;
constexpr inline void write_access(u8 *data, const u32 index, const u64 val) {
const u32 hi = val >> 32;
const u32 lo = val;
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
}
template <typename T>
static constexpr inline void WriteAccess(u8 *data, const u32 index, const T val) {
*reinterpret_cast<T *>(&data[index]) = val;
static constexpr inline void write_access(u8 *data, const u32 index, const T val) {
*reinterpret_cast<T *>(&data[index]) = val;
}
template <typename T>
static constexpr inline void SwapBuffer(std::vector<u8> &data) {
for (size_t i = 0; i < data.size(); i += sizeof(T)) {
const T original = *reinterpret_cast<T *>(&data[i]);
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
}
static constexpr inline void swap_buffer(std::vector<u8> &data) {
for (u32 i = 0; i < data.size(); i += sizeof(T)) {
const T original = *reinterpret_cast<T *>(&data[i]);
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
}
}
template <typename T, size_t Size>
static constexpr inline void SwapBuffer(std::array<u8, Size> &data) {
for (size_t i = 0; i < data.size(); i += sizeof(T)) {
const T original = *reinterpret_cast<T *>(&data[i]);
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
}
static constexpr inline void swap_buffer(std::array<u8, Size> &data) {
for (u32 i = 0; i < data.size(); i += sizeof(T)) {
const T original = *reinterpret_cast<T *>(&data[i]);
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
}
}
template <typename T>
static constexpr inline void swap_buffer(u8 *data, u32 size) {
for (u32 i = 0; i < size; i += sizeof(T)) {
const T original = *reinterpret_cast<T *>(&data[i]);
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
}
}
#ifdef _WIN32
inline void *aligned_alloc(const size_t alignment, const size_t size) { return _aligned_malloc(size, alignment); }
inline void *aligned_alloc(const u32 alignment, const u32 size) { return _aligned_malloc(size, alignment); }
inline void aligned_free(void *ptr) { _aligned_free(ptr); }
#else
inline void *aligned_alloc(const size_t alignment, const size_t size) {
return std::aligned_alloc(alignment, size);
}
inline void *aligned_alloc(const u32 alignment, const u32 size) { return std::aligned_alloc(alignment, size); }
inline void aligned_free(void *ptr) { std::free(ptr); }
#endif
} // namespace Util
} // namespace ircolib
+35
View File
@@ -1,5 +1,11 @@
#pragma once
#include <cstdint>
#ifdef USE_NEON
#include <sse2neon.h>
#else
#include <emmintrin.h>
#include <smmintrin.h>
#endif
namespace ircolib {
using u8 = uint8_t;
@@ -10,4 +16,33 @@ using s8 = int8_t;
using s16 = int16_t;
using s32 = int32_t;
using s64 = int64_t;
template <typename T, u32 bit>
static constexpr bool is_bit_set(const T &val) {
return val & (1 << bit);
}
template <typename T, u32 bit>
static constexpr void set_bit(T &val) {
val |= 1 << bit;
}
template <typename T>
inline bool is_bit_set(const T &val, const u32 &bit) {
return val & (1 << bit);
}
template <typename T>
inline void set_bit(T &val, const u32 &bit) {
val |= 1 << bit;
}
template <typename T>
inline void clear_bit(T &val, const u32 &bit) {
val &= ~(1 << bit);
}
} // namespace ircolib
constexpr ircolib::u32 operator""_kib(const unsigned long long v) { return v * 1024; }
constexpr ircolib::u32 operator""_mib(const unsigned long long v) { return v * 1024 * 1024; }
constexpr ircolib::u32 operator""_gib(const unsigned long long v) { return v * 1024 * 1024 * 1024; }
+7 -6
View File
@@ -38,7 +38,7 @@ Util::IntrusivePtr<Context> InitVulkanContext(WSIPlatform *platform, const unsig
if (!new_context->init_instance(instance_ext.data(), instance_ext.size(),
CONTEXT_CREATION_ENABLE_ADVANCED_WSI_BIT)) {
panic("Failed to create Vulkan instance.\n");
ircolib::panic("Failed to create Vulkan instance.\n");
}
const auto tmp_surface = platform->create_surface(new_context->get_instance(), VK_NULL_HANDLE);
@@ -51,7 +51,7 @@ Util::IntrusivePtr<Context> InitVulkanContext(WSIPlatform *platform, const unsig
}
if (!ret) {
panic("Failed to create Vulkan device.\n");
ircolib::panic("Failed to create Vulkan device.\n");
}
return new_context;
@@ -67,15 +67,15 @@ void ParallelRDP::LoadWSIPlatform(const std::shared_ptr<WSIPlatform> &wsi_platfo
if (constexpr Context::SystemHandles handles;
!wsi->init_from_existing_context(InitVulkanContext(wsi_platform.get(), 1, handles, instanceFactory))) {
panic("Failed to initialize WSI: init_from_existing_context() failed");
ircolib::panic("Failed to initialize WSI: init_from_existing_context() failed");
}
if (!wsi->init_device()) {
panic("Failed to initialize WSI: init_device() failed");
ircolib::panic("Failed to initialize WSI: init_device() failed");
}
if (!wsi->init_surface_swapchain()) {
panic("Failed to initialize WSI: init_surface_swapchain() failed");
ircolib::panic("Failed to initialize WSI: init_surface_swapchain() failed");
}
windowInfo = newWindowInfo;
@@ -124,7 +124,8 @@ void ParallelRDP::Init(const std::shared_ptr<WSIPlatform> &wsiPlatform,
offset, 8 * 1024 * 1024, 4 * 1024 * 1024, flags);
if (!command_processor->device_is_supported()) {
panic("This device probably does not support 8/16-bit storage. Make sure you're using up-to-date drivers!");
ircolib::panic(
"This device probably does not support 8/16-bit storage. Make sure you're using up-to-date drivers!");
}
}
+1 -1
View File
@@ -56,7 +56,7 @@ u32 Core::StepCPU() {
if (cpuType == CachedInterpreter)
return interpreter.ExecuteCached() + regs.PopStalledCycles();
panic("Invalid CPU type?");
ircolib::panic("Invalid CPU type?");
}
void Core::StepRSP(const u32 cpuCycles) {
+4 -4
View File
@@ -73,15 +73,15 @@ std::string GameDB::match(ROM &rom) {
return result;
}
info("Matched code for {}, but not region! Game supposedly exists in regions [{}] but this image has "
"region {}",
name, regions, rom.header.countryCode);
ircolib::info("Matched code for {}, but not region! Game supposedly exists in regions [{}] but this image has "
"region {}",
name, regions, rom.header.countryCode);
rom.saveType = saveType;
rom.gameNameDB = name;
return result;
}
info("Did not match any Game DB entries. Code: {} Region: {}", rom.code, rom.header.countryCode);
ircolib::info("Did not match any Game DB entries. Code: {} Region: {}", rom.code, rom.header.countryCode);
rom.gameNameDB = "";
rom.saveType = SAVE_NONE;
+1 -1
View File
@@ -1,6 +1,6 @@
#include <Netplay.hpp>
#include <PIF.hpp>
#include <array>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace Netplay {}
+7 -7
View File
@@ -1,6 +1,6 @@
#pragma once
#include <ircolib/mem_access.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace Util {
#define Z64 0x80371200
@@ -13,7 +13,7 @@ FORCE_INLINE void SwapN64Rom(std::vector<u8> &rom, u32 endianness) {
if (endianness >> 24 != 0x80) {
if ((endianness & 0xFF) != 0x80) {
if ((endianness >> 16 & 0xff) != 0x80) {
panic("Unrecognized rom endianness");
ircolib::panic("Unrecognized rom endianness");
return;
} else {
altByteShift = 12;
@@ -29,20 +29,20 @@ FORCE_INLINE void SwapN64Rom(std::vector<u8> &rom, u32 endianness) {
switch (endianness) {
case V64:
ircolib::SwapBuffer<u16>(rom);
ircolib::swap_buffer<u16>(rom);
if constexpr (!toBE)
ircolib::SwapBuffer<u32>(rom);
ircolib::swap_buffer<u32>(rom);
break;
case N64:
if constexpr (toBE)
ircolib::SwapBuffer<u32>(rom);
ircolib::swap_buffer<u32>(rom);
break;
case Z64:
if constexpr (!toBE)
ircolib::SwapBuffer<u32>(rom);
ircolib::swap_buffer<u32>(rom);
break;
default:
panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!");
ircolib::panic("Unrecognized rom format! Make sure this is a valid Nintendo 64 ROM dump!");
}
}
} // namespace Util
+2 -2
View File
@@ -63,10 +63,10 @@ void Scheduler::HandleEvents() {
case NONE:
break;
case IMPOSSIBLE:
panic("Impossible scheduler event happened");
ircolib::panic("Impossible scheduler event happened");
return;
default:
panic("Unknown scheduler event type {}", static_cast<int>(type));
ircolib::panic("Unknown scheduler event type {}", static_cast<int>(type));
return;
}
events.pop();
+2 -1
View File
@@ -1,7 +1,8 @@
#pragma once
#include <functional>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <queue>
#include <types.hpp>
enum EventType { NONE, PAUSE, STOP, RESET, PI_BUS_WRITE_COMPLETE, PI_DMA_COMPLETE, SI_DMA, IMPOSSIBLE };
+46 -52
View File
@@ -3,75 +3,69 @@
#include <optional>
Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 address, const u32 instruction) const {
cs_insn *insn;
const auto bytes = ircolib::IntegralToBuffer(std::byteswap(instruction));
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
cs_insn *insn;
const auto bytes = ircolib::integral_to_buffer(std::byteswap(instruction));
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
if (count <= 0)
return {};
if (count <= 0)
return {};
DisassemblyResult result{true, std::format("0x{:016X}:\t{}\t{}", insn[0].address, insn[0].mnemonic, insn[0].op_str)};
DisassemblyResult result{true,
std::format("0x{:016X}:\t{}\t{}", insn[0].address, insn[0].mnemonic, insn[0].op_str)};
cs_free(insn, count);
cs_free(insn, count);
return result;
return result;
}
[[nodiscard]] Disassembler::DisassemblyResult Disassembler::Disassemble(const u32 address) const {
u32 paddr;
if(!n64::Core::GetRegs().cop0.MapVAddr(n64::Cop0::TLBAccessType::LOAD, address, paddr))
return DisassemblyResult{false, ""};
u32 paddr;
if (!n64::Core::GetRegs().cop0.MapVAddr(n64::Cop0::TLBAccessType::LOAD, address, paddr))
return DisassemblyResult{false, ""};
u32 instruction = n64::Core::GetMem().Read<u32>(paddr);
u32 instruction = n64::Core::GetMem().Read<u32>(paddr);
return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction);
return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction);
}
Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 address, const u32 instruction) const {
n64::Core& core = n64::Core::GetInstance();
cs_insn *insn;
const auto bytes = ircolib::IntegralToBuffer(std::byteswap(instruction));
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
n64::Core &core = n64::Core::GetInstance();
cs_insn *insn;
const auto bytes = ircolib::integral_to_buffer(std::byteswap(instruction));
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
if (count <= 0)
return {};
if (count <= 0)
return {};
DisassemblyResult result{true};
result.address = insn[0].address;
result.mnemonic = insn[0].mnemonic;
DisassemblyResult result{true};
result.address = insn[0].address;
result.mnemonic = insn[0].mnemonic;
result.full += std::format("0x{:016X}", result.address) + ":\t";
result.full += result.mnemonic + "\t";
result.full += std::format("0x{:016X}", result.address) + ":\t";
result.full += result.mnemonic + "\t";
const cs_detail *details = insn[0].detail;
auto formatOperand = [&](const cs_mips_op &operand) {
switch (operand.type) {
case MIPS_OP_IMM:
return DisassemblyResult::Operand{
0xffcbf1ae,
std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm)
};
case MIPS_OP_MEM:
return DisassemblyResult::Operand{
0xffaef1c3,
std::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp)
};
case MIPS_OP_REG:
return DisassemblyResult::Operand{
0xffaef1eb,
std::format("{}", cs_reg_name(handle, operand.reg))
};
default:
return DisassemblyResult::Operand { 0xff808080, "" };
const cs_detail *details = insn[0].detail;
auto formatOperand = [&](const cs_mips_op &operand) {
switch (operand.type) {
case MIPS_OP_IMM:
return DisassemblyResult::Operand{0xffcbf1ae,
std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm)};
case MIPS_OP_MEM:
return DisassemblyResult::Operand{
0xffaef1c3, std::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp)};
case MIPS_OP_REG:
return DisassemblyResult::Operand{0xffaef1eb, std::format("{}", cs_reg_name(handle, operand.reg))};
default:
return DisassemblyResult::Operand{0xff808080, ""};
}
};
for (u8 i = 0; i < details->mips.op_count && i < 3; i++) {
result.ops[i] = formatOperand(details->mips.operands[i]);
result.full += result.ops[i].str + "\t";
}
};
for (u8 i = 0; i < details->mips.op_count && i < 3; i++) {
result.ops[i] = formatOperand(details->mips.operands[i]);
result.full += result.ops[i].str + "\t";
}
cs_free(insn, count);
cs_free(insn, count);
return result;
return result;
}
+4 -3
View File
@@ -1,8 +1,9 @@
#pragma once
#include <capstone/capstone.h>
#include <utils/log.hpp>
#include <ircolib/log.hpp>
#include <ircolib/mem_access.hpp>
#include <array>
#include <types.hpp>
struct Disassembler {
struct DisassemblyResult {
@@ -32,11 +33,11 @@ struct Disassembler {
explicit Disassembler(const bool rsp) : rsp(rsp) {
if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>((rsp ? CS_MODE_32 : CS_MODE_64) | CS_MODE_BIG_ENDIAN),
&handle) != CS_ERR_OK) {
panic("Could not initialize {} disassembler!", rsp ? "RSP" : "CPU");
ircolib::panic("Could not initialize {} disassembler!", rsp ? "RSP" : "CPU");
}
if (cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON) != CS_ERR_OK) {
warn("Could not enable disassembler's details!");
ircolib::warn("Could not enable disassembler's details!");
details = false;
}
}
+3 -3
View File
@@ -126,7 +126,7 @@ bool Interpreter::DetectIdleLoop(const std::array<Instruction, MAX_INSTR_PER_BLO
const u64 address = regs.Read<s64>(load.rs()) + offset;
u32 paddr;
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr))
panic("Failed to translate load address in DetectIdleLoop");
ircolib::panic("Failed to translate load address in DetectIdleLoop");
return isLoad && delay.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -8 &&
load.rt() == delay.rs() && delay.rt() == branch.rs() && IsAddressMMIOorRDRAM(paddr);
@@ -148,7 +148,7 @@ bool Interpreter::DetectIdleLoop(const std::array<Instruction, MAX_INSTR_PER_BLO
if (isLoad) {
u32 paddr;
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr))
panic("Failed to translate load address in DetectIdleLoop");
ircolib::panic("Failed to translate load address in DetectIdleLoop");
return isLoad && andi.opcode() == Instruction::ANDI && branch.IsBranch() && branch.offset() == -12 &&
load.rt() == andi.rs() && andi.rt() == branch.rs() && IsAddressMMIOorRDRAM(paddr);
@@ -234,7 +234,7 @@ u32 Interpreter::ExecuteCached() {
}
if (blockCycles == 0)
panic("Cycles are 0");
ircolib::panic("Cycles are 0");
return blockCycles;
}
+56 -56
View File
@@ -3,67 +3,67 @@
namespace n64 {
void MMIO::Reset() {
rsp.Reset();
rdp.Reset();
mi.Reset();
vi.Reset();
ai.Reset();
pi.Reset();
ri.Reset();
si.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 RSP_REGION:
return rsp.Read(addr);
case RDP_REGION:
return rdp.Read(addr);
case MI_REGION:
return mi.Read(addr);
case VI_REGION:
return vi.Read(addr);
case AI_REGION:
return ai.Read(addr);
case PI_REGION:
return pi.Read(addr);
case RI_REGION:
return ri.Read(addr);
case SI_REGION:
return si.Read(addr);
default:
panic("Unhandled mmio read at addr {:08X}", addr);
}
switch (addr) {
case RSP_REGION:
return rsp.Read(addr);
case RDP_REGION:
return rdp.Read(addr);
case MI_REGION:
return mi.Read(addr);
case VI_REGION:
return vi.Read(addr);
case AI_REGION:
return ai.Read(addr);
case PI_REGION:
return pi.Read(addr);
case RI_REGION:
return ri.Read(addr);
case SI_REGION:
return si.Read(addr);
default:
ircolib::panic("Unhandled mmio read at addr {:08X}", addr);
}
}
void MMIO::Write(const u32 addr, const u32 val) {
switch (addr) {
case RSP_REGION:
rsp.Write(addr, val);
break;
case RDP_REGION:
rdp.Write(addr, val);
break;
case MI_REGION:
mi.Write(addr, val);
break;
case VI_REGION:
vi.Write(addr, val);
break;
case AI_REGION:
ai.Write(addr, val);
break;
case PI_REGION:
pi.Write(addr, val);
break;
case RI_REGION:
ri.Write(addr, val);
break;
case SI_REGION:
si.Write(addr, val);
break;
default:
panic("Unhandled mmio write at addr {:08X} with val {:08X}", addr, val);
}
switch (addr) {
case RSP_REGION:
rsp.Write(addr, val);
break;
case RDP_REGION:
rdp.Write(addr, val);
break;
case MI_REGION:
mi.Write(addr, val);
break;
case VI_REGION:
vi.Write(addr, val);
break;
case AI_REGION:
ai.Write(addr, val);
break;
case PI_REGION:
pi.Write(addr, val);
break;
case RI_REGION:
ri.Write(addr, val);
break;
case SI_REGION:
si.Write(addr, val);
break;
default:
ircolib::panic("Unhandled mmio write at addr {:08X} with val {:08X}", addr, val);
}
}
} // namespace n64
+148 -144
View File
@@ -20,7 +20,7 @@ void Mem::Reset() {
std::error_code err;
saveData.sync(err);
if (err) {
error("[Mem]: Could not sync save data!");
ircolib::error("[Mem]: Could not sync save data!");
return;
}
saveData.unmap();
@@ -39,26 +39,26 @@ void Mem::LoadSRAM(SaveType save_type, fs::path path) {
if (saveData.is_mapped()) {
saveData.sync(err);
if (err) {
error(R"([Mem]: Could not sync save data stored @ "{}")", sramPath);
ircolib::error(R"([Mem]: Could not sync save data stored @ "{}")", sramPath);
return;
}
saveData.unmap();
}
auto sramVec = ircolib::ReadFileBinary(sramPath);
auto sramVec = ircolib::read_file_binary(sramPath);
if (sramVec.empty()) {
ircolib::WriteFileBinary(std::array<u8, SRAM_SIZE>{}, sramPath);
sramVec = ircolib::ReadFileBinary(sramPath);
ircolib::write_file_binary(std::array<u8, SRAM_SIZE>{}, sramPath);
sramVec = ircolib::read_file_binary(sramPath);
}
if (sramVec.size() != SRAM_SIZE) {
error("[Mem]: Save data is corrupt or has unexpected size! (it's {} KiB)", sramVec.size() / 1024);
ircolib::error("[Mem]: Save data is corrupt or has unexpected size! (it's {} KiB)", sramVec.size() / 1024);
return;
}
saveData = mio::make_mmap_sink(sramPath, err);
if (err) {
error(R"([Mem]: Could not create file sink for save data @ "{}")", sramPath);
ircolib::error(R"([Mem]: Could not create file sink for save data @ "{}")", sramPath);
}
}
}
@@ -84,7 +84,7 @@ FORCE_INLINE void SetROMCIC(u32 checksum, ROM &rom) {
rom.cicType = CIC_NUS_6106_7106;
break;
default:
warn("Could not determine CIC TYPE! Checksum: 0x{:08X} is unknown!", checksum);
ircolib::warn("Could not determine CIC TYPE! Checksum: 0x{:08X} is unknown!", checksum);
rom.cicType = UNKNOWN_CIC_TYPE;
break;
}
@@ -104,7 +104,7 @@ ROM Mem::LoadROM(const bool isArchive, const std::string &filename) {
buf = Util::OpenROM(filename, sizeAdjusted);
}
endianness = std::byteswap(ircolib::ReadAccess<u32>(buf, 0));
endianness = std::byteswap(ircolib::read_access<u32>(buf, 0));
Util::SwapN64Rom<true>(buf, endianness);
std::ranges::copy(buf, res.cart.begin());
@@ -130,7 +130,7 @@ ROM Mem::LoadROM(const bool isArchive, const std::string &filename) {
const u32 checksum = SDL_crc32(0, &res.cart[0x40], 0x9C0);
SetROMCIC(checksum, res);
endianness = std::byteswap(ircolib::ReadAccess<u32>(res.cart, 0));
endianness = std::byteswap(ircolib::read_access<u32>(res.cart, 0));
Util::SwapN64Rom(res.cart, endianness);
res.pal = IsROMPAL(res);
return res;
@@ -141,38 +141,38 @@ u8 Mem::Read(const u32 paddr) {
n64::Registers &regs = n64::Core::GetRegs();
const SI &si = mmio.si;
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END))
if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END))
return mmio.rdp.ReadRDRAM<u8>(paddr);
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return src[BYTE_ADDRESS(paddr & 0xfff)];
}
if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2))
if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2))
return mmio.pi.BusRead<u8, false>(paddr);
if (ircolib::IsInsideRange(paddr, AI_REGION_START, AI_REGION_END)) {
if (ircolib::is_inside_range(paddr, AI_REGION_START, AI_REGION_END)) {
const u32 w = mmio.ai.Read(paddr & ~3);
const int offs = 3 - (paddr & 3);
return w >> offs * 8 & 0xff;
}
if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) {
panic("8-bit read access from MMIO addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) {
ircolib::panic("8-bit read access from MMIO addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
return 0;
}
if (ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END))
if (ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END))
return si.pif.bootrom[BYTE_ADDRESS(paddr) - PIF_ROM_REGION_START];
if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END))
if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END))
return si.pif.ram[paddr - PIF_RAM_REGION_START];
if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4))
if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4))
return 0;
panic("8-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
ircolib::panic("8-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
return 0;
}
@@ -181,29 +181,29 @@ u16 Mem::Read(const u32 paddr) {
n64::Registers &regs = n64::Core::GetRegs();
const SI &si = mmio.si;
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END))
if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END))
return mmio.rdp.ReadRDRAM<u16>(paddr);
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return ircolib::ReadAccess<u16>(src, HALF_ADDRESS(paddr & 0xfff));
return ircolib::read_access<u16>(src, HALF_ADDRESS(paddr & 0xfff));
}
if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2))
if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2))
return mmio.pi.BusRead<u16, false>(paddr);
if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
return mmio.Read(paddr);
if (ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END))
return ircolib::ReadAccess<u16>(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START);
if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END))
return std::byteswap(ircolib::ReadAccess<u16>(si.pif.ram, paddr - PIF_RAM_REGION_START));
if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4))
if (ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END))
return ircolib::read_access<u16>(si.pif.bootrom, HALF_ADDRESS(paddr) - PIF_ROM_REGION_START);
if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END))
return std::byteswap(ircolib::read_access<u16>(si.pif.ram, paddr - PIF_RAM_REGION_START));
if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4))
return 0;
panic("16-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
ircolib::panic("16-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
return 0;
}
@@ -212,30 +212,30 @@ u32 Mem::Read(const u32 paddr) {
n64::Registers &regs = n64::Core::GetRegs();
const SI &si = mmio.si;
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END))
if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END))
return mmio.rdp.ReadRDRAM<u32>(paddr);
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return ircolib::ReadAccess<u32>(src, paddr & 0xfff);
return ircolib::read_access<u32>(src, paddr & 0xfff);
}
if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2))
if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2))
return mmio.pi.BusRead<u32, false>(paddr);
if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
return mmio.Read(paddr);
if (ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END))
return ircolib::ReadAccess<u32>(si.pif.bootrom, paddr - PIF_ROM_REGION_START);
if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END))
return std::byteswap(ircolib::ReadAccess<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START));
if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4))
if (ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END))
return ircolib::read_access<u32>(si.pif.bootrom, paddr - PIF_ROM_REGION_START);
if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END))
return std::byteswap(ircolib::read_access<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START));
if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4))
return 0;
panic("32-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
ircolib::panic("32-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
return 0;
}
@@ -244,30 +244,30 @@ u64 Mem::Read(const u32 paddr) {
n64::Registers &regs = n64::Core::GetRegs();
const SI &si = mmio.si;
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END))
if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END))
return mmio.rdp.ReadRDRAM<u64>(paddr);
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
const auto &src = paddr & 0x1000 ? mmio.rsp.imem : mmio.rsp.dmem;
return ircolib::ReadAccess<u64>(src, paddr & 0xfff);
return ircolib::read_access<u64>(src, paddr & 0xfff);
}
if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2))
if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2))
return mmio.pi.BusRead<u64, false>(paddr);
if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
return mmio.Read(paddr);
if (ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END))
return ircolib::ReadAccess<u64>(si.pif.bootrom, paddr - PIF_ROM_REGION_START);
if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END))
return std::byteswap(ircolib::ReadAccess<u64>(si.pif.ram, paddr - PIF_RAM_REGION_START));
if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4))
if (ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END))
return ircolib::read_access<u64>(si.pif.bootrom, paddr - PIF_ROM_REGION_START);
if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END))
return std::byteswap(ircolib::read_access<u64>(si.pif.ram, paddr - PIF_RAM_REGION_START));
if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4))
return 0;
panic("64-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
ircolib::panic("64-bit read access in unhandled addr 0x{:08X} @ pc 0x{:016X}", paddr, (u64)regs.pc);
return 0;
}
@@ -276,45 +276,46 @@ void Mem::Write<u8>(u32 paddr, u32 val) {
n64::Registers &regs = n64::Core::GetRegs();
SI &si = mmio.si;
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
mmio.rdp.WriteRDRAM<u8>(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
val = val << (8 * (3 - (paddr & 3)));
bool is_imem = paddr & 0x1000;
auto &dest = is_imem ? mmio.rsp.imem : mmio.rsp.dmem;
paddr = (paddr & 0xFFF) & ~3;
ircolib::WriteAccess<u32>(dest, paddr, val);
ircolib::write_access<u32>(dest, paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) {
trace("BusWrite<u8> @ {:08X} = {:02X}", paddr, val);
if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) {
ircolib::trace("BusWrite<u8> @ {:08X} = {:02X}", paddr, val);
mmio.pi.BusWrite<u8, false>(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
panic("MMIO Write<u8>!");
if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
ircolib::panic("MMIO Write<u8>!");
if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) {
if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) {
val = val << (8 * (3 - (paddr & 3)));
paddr = (paddr - PIF_RAM_REGION_START) & ~3;
ircolib::WriteAccess<u32>(si.pif.ram, paddr, std::byteswap(val));
ircolib::write_access<u32>(si.pif.ram, paddr, std::byteswap(val));
si.pif.ProcessCommands();
return;
}
if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) ||
ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4))
if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) ||
ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4))
return;
panic("Unimplemented 8-bit write at address {:08X} with value {:02X} (PC = {:016X})", paddr, val, (u64)regs.pc);
ircolib::panic("Unimplemented 8-bit write at address {:08X} with value {:02X} (PC = {:016X})", paddr, val,
(u64)regs.pc);
}
template <>
@@ -322,45 +323,46 @@ void Mem::Write<u16>(u32 paddr, u32 val) {
n64::Registers &regs = n64::Core::GetRegs();
SI &si = mmio.si;
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
mmio.rdp.WriteRDRAM<u16>(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
val = val << (16 * !(paddr & 2));
bool is_imem = paddr & 0x1000;
auto &dest = is_imem ? mmio.rsp.imem : mmio.rsp.dmem;
paddr = (paddr & 0xFFF) & ~3;
ircolib::WriteAccess<u32>(dest, paddr, val);
ircolib::write_access<u32>(dest, paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) {
trace("BusWrite<u8> @ {:08X} = {:04X}", paddr, val);
if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) {
ircolib::trace("BusWrite<u8> @ {:08X} = {:04X}", paddr, val);
mmio.pi.BusWrite<u16, false>(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
panic("MMIO Write<u16>!");
if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
ircolib::panic("MMIO Write<u16>!");
if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) {
if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) {
val = val << (16 * !(paddr & 2));
paddr &= ~3;
ircolib::WriteAccess<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val));
ircolib::write_access<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val));
si.pif.ProcessCommands();
return;
}
if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) ||
ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4))
if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) ||
ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4))
return;
panic("Unimplemented 16-bit write at address {:08X} with value {:04X} (PC = {:016X})", paddr, val, (u64)regs.pc);
ircolib::panic("Unimplemented 16-bit write at address {:08X} with value {:04X} (PC = {:016X})", paddr, val,
(u64)regs.pc);
}
template <>
@@ -368,85 +370,87 @@ void Mem::Write<u32>(const u32 paddr, const u32 val) {
n64::Registers &regs = n64::Core::GetRegs();
SI &si = mmio.si;
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
mmio.rdp.WriteRDRAM<u32>(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
bool is_imem = paddr & 0x1000;
auto &dest = is_imem ? mmio.rsp.imem : mmio.rsp.dmem;
ircolib::WriteAccess<u32>(dest, paddr & 0xfff, val);
ircolib::write_access<u32>(dest, paddr & 0xfff, val);
return;
}
if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) {
trace("BusWrite<u8> @ {:08X} = {:08X}", paddr, val);
if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) {
ircolib::trace("BusWrite<u8> @ {:08X} = {:08X}", paddr, val);
mmio.pi.BusWrite<u32, false>(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) {
if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2)) {
mmio.Write(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) {
ircolib::WriteAccess<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val));
if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) {
ircolib::write_access<u32>(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val));
si.pif.ProcessCommands();
return;
}
if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) ||
ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4))
if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) ||
ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4))
return;
panic("Unimplemented 32-bit write at address {:08X} with value {:08X} (PC = {:016X})", paddr, val, (u64)regs.pc);
ircolib::panic("Unimplemented 32-bit write at address {:08X} with value {:08X} (PC = {:016X})", paddr, val,
(u64)regs.pc);
}
void Mem::Write(const u32 paddr, u64 val) {
n64::Registers &regs = n64::Core::GetRegs();
SI &si = mmio.si;
if (ircolib::IsInsideRange(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
if (ircolib::is_inside_range(paddr, RDRAM_REGION_START, RDRAM_REGION_END)) {
mmio.rdp.WriteRDRAM<u64>(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
if (ircolib::is_inside_range(paddr, DMEM_REGION_START, RSP_MEM_REGION_END)) {
bool is_imem = paddr & 0x1000;
auto &dest = is_imem ? mmio.rsp.imem : mmio.rsp.dmem;
val >>= 32;
ircolib::WriteAccess<u32>(dest, paddr & 0xfff, val);
ircolib::write_access<u32>(dest, paddr & 0xfff, val);
return;
}
if (ircolib::IsInsideRange(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) {
trace("BusWrite<u64> @ {:08X} = {:016X}", paddr, val);
if (ircolib::is_inside_range(paddr, CART_REGION_START_2_1, CART_REGION_END_1_2)) {
ircolib::trace("BusWrite<u64> @ {:08X} = {:016X}", paddr, val);
mmio.pi.BusWrite<false>(paddr, val);
return;
}
if (ircolib::IsInsideRange(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
panic("MMIO Write<u64>!");
if (ircolib::is_inside_range(paddr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(paddr, MMIO_REGION_START_2, MMIO_REGION_END_2))
ircolib::panic("MMIO Write<u64>!");
if (ircolib::IsInsideRange(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) {
ircolib::WriteAccess<u64>(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val));
if (ircolib::is_inside_range(paddr, PIF_RAM_REGION_START, PIF_RAM_REGION_END)) {
ircolib::write_access<u64>(si.pif.ram, paddr - PIF_RAM_REGION_START, std::byteswap(val));
si.pif.ProcessCommands();
return;
}
if (ircolib::IsInsideRange(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::IsInsideRange(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::IsInsideRange(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::IsInsideRange(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) ||
ircolib::IsInsideRange(paddr, UNUSED_START_4, UNUSED_END_4))
if (ircolib::is_inside_range(paddr, UNUSED_START_1, UNUSED_END_1) || // unused
ircolib::is_inside_range(paddr, UNUSED_START_2, UNUSED_END_2) ||
ircolib::is_inside_range(paddr, UNUSED_START_3, UNUSED_END_3) ||
ircolib::is_inside_range(paddr, PIF_ROM_REGION_START, PIF_ROM_REGION_END) ||
ircolib::is_inside_range(paddr, UNUSED_START_4, UNUSED_END_4))
return;
panic("Unimplemented 64-bit write at address {:08X} with value {:016X} (PC = {:016X})", paddr, val, (u64)regs.pc);
ircolib::panic("Unimplemented 64-bit write at address {:08X} with value {:016X} (PC = {:016X})", paddr, val,
(u64)regs.pc);
}
template <>
@@ -456,14 +460,14 @@ u32 Mem::BackupRead<u32>(const u32 addr) {
return 0;
case SAVE_EEPROM_4k:
case SAVE_EEPROM_16k:
warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read");
ircolib::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read");
return 0;
case SAVE_FLASH_1m:
return flash.Read<u32>(addr);
case SAVE_SRAM_256k:
return 0xFFFFFFFF;
default:
panic("Backup read word with unknown save type");
ircolib::panic("Backup read word with unknown save type");
}
}
@@ -474,7 +478,7 @@ u8 Mem::BackupRead<u8>(const u32 addr) {
return 0;
case SAVE_EEPROM_4k:
case SAVE_EEPROM_16k:
warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read");
ircolib::warn("Accessing cartridge backup type SAVE_EEPROM, returning 0 for word read");
return 0;
case SAVE_FLASH_1m:
return flash.Read<u8>(addr);
@@ -483,10 +487,10 @@ u8 Mem::BackupRead<u8>(const u32 addr) {
assert(addr < saveData.size());
return saveData[addr];
} else {
panic("Invalid backup Read<u8> if save data is not initialized");
ircolib::panic("Invalid backup Read<u8> if save data is not initialized");
}
default:
panic("Backup read word with unknown save type");
ircolib::panic("Backup read word with unknown save type");
}
}
@@ -494,18 +498,18 @@ template <>
void Mem::BackupWrite<u32>(const u32 addr, const u32 val) {
switch (rom.saveType) {
case SAVE_NONE:
warn("Accessing cartridge with save type SAVE_NONE in write word");
ircolib::warn("Accessing cartridge with save type SAVE_NONE in write word");
break;
case SAVE_EEPROM_4k:
case SAVE_EEPROM_16k:
panic("Accessing cartridge with save type SAVE_EEPROM in write word");
ircolib::panic("Accessing cartridge with save type SAVE_EEPROM in write word");
case SAVE_FLASH_1m:
flash.Write<u32>(addr, val);
break;
case SAVE_SRAM_256k:
break;
default:
panic("Backup read word with unknown save type");
ircolib::panic("Backup read word with unknown save type");
}
}
@@ -513,11 +517,11 @@ template <>
void Mem::BackupWrite<u8>(const u32 addr, const u8 val) {
switch (rom.saveType) {
case SAVE_NONE:
warn("Accessing cartridge with save type SAVE_NONE in write word");
ircolib::warn("Accessing cartridge with save type SAVE_NONE in write word");
break;
case SAVE_EEPROM_4k:
case SAVE_EEPROM_16k:
panic("Accessing cartridge with save type SAVE_EEPROM in write word");
ircolib::panic("Accessing cartridge with save type SAVE_EEPROM in write word");
case SAVE_FLASH_1m:
flash.Write<u8>(addr, val);
break;
@@ -526,11 +530,11 @@ void Mem::BackupWrite<u8>(const u32 addr, const u8 val) {
assert(addr < saveData.size());
saveData[addr] = val;
} else {
panic("Invalid backup Write<u8> if save data is not initialized");
ircolib::panic("Invalid backup Write<u8> if save data is not initialized");
}
break;
default:
panic("Backup read word with unknown save type");
ircolib::panic("Backup read word with unknown save type");
}
}
} // namespace n64
+7 -7
View File
@@ -4,7 +4,7 @@
#include <backend/MemoryRegions.hpp>
#include <backend/core/MMIO.hpp>
#include <common.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <vector>
#include <algorithm>
@@ -100,22 +100,22 @@ struct Mem {
std::vector<u8> temp{};
temp.resize(size);
std::copy(mmio.rdp.rdram.begin() + start, mmio.rdp.rdram.begin() + size - 1, temp.begin());
ircolib::SwapBuffer<u32>(temp);
ircolib::WriteFileBinary(temp, "rdram.bin");
ircolib::swap_buffer<u32>(temp);
ircolib::write_file_binary(temp, "rdram.bin");
}
FORCE_INLINE void DumpIMEM() const {
std::array<u8, IMEM_SIZE> temp{};
std::ranges::copy(mmio.rsp.imem, temp.begin());
ircolib::SwapBuffer<u32>(temp);
ircolib::WriteFileBinary(temp, "imem.bin");
ircolib::swap_buffer<u32>(temp);
ircolib::write_file_binary(temp, "imem.bin");
}
FORCE_INLINE void DumpDMEM() const {
std::array<u8, DMEM_SIZE> temp{};
std::ranges::copy(mmio.rsp.dmem, temp.begin());
ircolib::SwapBuffer<u32>(temp);
ircolib::WriteFileBinary(temp, "dmem.bin");
ircolib::swap_buffer<u32>(temp);
ircolib::write_file_binary(temp, "dmem.bin");
}
MMIO mmio;
+12 -12
View File
@@ -1,4 +1,4 @@
#include <log.hpp>
#include <ircolib/log.hpp>
#include <parallel-rdp/ParallelRDPWrapper.hpp>
#include <Core.hpp>
@@ -25,21 +25,21 @@ void RDP::WriteRDRAM<u8>(const size_t idx, const u8 v) {
template <>
void RDP::WriteRDRAM<u16>(const size_t idx, const u16 v) {
if (const size_t real = HALF_ADDRESS(idx); real < RDRAM_SIZE) [[likely]] {
ircolib::WriteAccess<u16>(rdram, real, v);
ircolib::write_access<u16>(rdram, real, v);
}
}
template <>
void RDP::WriteRDRAM<u32>(const size_t idx, const u32 v) {
if (idx < RDRAM_SIZE) [[likely]] {
ircolib::WriteAccess<u32>(rdram, idx, v);
ircolib::write_access<u32>(rdram, idx, v);
}
}
template <>
void RDP::WriteRDRAM<u64>(const size_t idx, const u64 v) {
if (idx < RDRAM_SIZE) [[likely]] {
ircolib::WriteAccess<u64>(rdram, idx, v);
ircolib::write_access<u64>(rdram, idx, v);
}
}
@@ -54,7 +54,7 @@ u8 RDP::ReadRDRAM<u8>(const size_t idx) {
template <>
u16 RDP::ReadRDRAM<u16>(const size_t idx) {
if (const size_t real = HALF_ADDRESS(idx); real < RDRAM_SIZE) [[likely]]
return ircolib::ReadAccess<u16>(rdram, real);
return ircolib::read_access<u16>(rdram, real);
return 0;
}
@@ -62,7 +62,7 @@ u16 RDP::ReadRDRAM<u16>(const size_t idx) {
template <>
u32 RDP::ReadRDRAM<u32>(const size_t idx) {
if (idx < RDRAM_SIZE) [[likely]]
return ircolib::ReadAccess<u32>(rdram, idx);
return ircolib::read_access<u32>(rdram, idx);
return 0;
}
@@ -70,7 +70,7 @@ u32 RDP::ReadRDRAM<u32>(const size_t idx) {
template <>
u64 RDP::ReadRDRAM<u64>(const size_t idx) {
if (idx < RDRAM_SIZE) [[likely]]
return ircolib::ReadAccess<u64>(rdram, idx);
return ircolib::read_access<u64>(rdram, idx);
return 0;
}
@@ -98,7 +98,7 @@ auto RDP::Read(const u32 addr) const -> u32 {
case 0x0410001C:
return dpc.tmem;
default:
panic("Unhandled DP Command Registers read (addr: {:08X})", addr);
ircolib::panic("Unhandled DP Command Registers read (addr: {:08X})", addr);
}
return 0;
@@ -116,7 +116,7 @@ void RDP::Write(const u32 addr, const u32 val) {
WriteStatus(val);
break;
default:
panic("Unhandled DP Command Registers write (addr: {:08X}, val: {:08X})", addr, val);
ircolib::panic("Unhandled DP Command Registers write (addr: {:08X}, val: {:08X})", addr, val);
}
}
@@ -216,13 +216,13 @@ void RDP::RunCommand() {
return;
if (len + remaining_cmds * 4 > COMMAND_BUFFER_SIZE) {
panic("Too many RDP commands");
ircolib::panic("Too many RDP commands");
return;
}
if (dpc.status.xbusDmemDma) {
for (int i = 0; i < len; i += 4) {
const u32 cmd = ircolib::ReadAccess<u32>(mem.mmio.rsp.dmem, current + i & 0xFFF);
const u32 cmd = ircolib::read_access<u32>(mem.mmio.rsp.dmem, current + i & 0xFFF);
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
}
} else {
@@ -231,7 +231,7 @@ void RDP::RunCommand() {
}
for (int i = 0; i < len; i += 4) {
const u32 cmd = ircolib::ReadAccess<u32>(rdram, current + i);
const u32 cmd = ircolib::read_access<u32>(rdram, current + i);
cmd_buf[remaining_cmds + (i >> 2)] = cmd;
}
}
+8 -8
View File
@@ -1,5 +1,5 @@
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace n64 {
RSP::RSP() { Reset(); }
@@ -53,8 +53,8 @@ auto RSP::Read(const u32 addr) -> u32 {
{
auto &regs = Core::GetRegs();
panic("Unimplemented SP register read {:08X} (cpu pc: 0x{:016X}, rsp pc: 0x{:04X}, ra: 0x{:016X})", addr,
(u64)regs.oldPC, pc & 0xffc, (u64)regs.gpr[31]);
ircolib::panic("Unimplemented SP register read {:08X} (cpu pc: 0x{:016X}, rsp pc: 0x{:04X}, ra: 0x{:016X})",
addr, (u64)regs.oldPC, pc & 0xffc, (u64)regs.gpr[31]);
}
}
}
@@ -111,7 +111,7 @@ void RSP::DMA<true>() {
u32 mem_address = spDMASPAddr.address & 0xFF8;
u32 dram_address = spDMADRAMAddr.address & 0xFFFFF8;
trace("SP DMA from RSP to RDRAM (size: {} B, {:08X} to {:08X})", length, mem_address, dram_address);
ircolib::trace("SP DMA from RSP to RDRAM (size: {} B, {:08X} to {:08X})", length, mem_address, dram_address);
for (u32 i = 0; i < spDMALen.count + 1; i++) {
for (u32 j = 0; j < length; j++) {
@@ -125,7 +125,7 @@ void RSP::DMA<true>() {
mem_address += length;
mem_address &= 0xFF8;
}
trace("Addresses after: RSP: 0x{:08X}, Dram: 0x{:08X}", mem_address, dram_address);
ircolib::trace("Addresses after: RSP: 0x{:08X}, Dram: 0x{:08X}", mem_address, dram_address);
lastSuccessfulSPAddr.address = mem_address;
lastSuccessfulSPAddr.bank = spDMASPAddr.bank;
@@ -145,7 +145,7 @@ void RSP::DMA<false>() {
u32 mem_address = spDMASPAddr.address & 0xFF8;
u32 dram_address = spDMADRAMAddr.address & 0xFFFFF8;
trace("SP DMA from RDRAM to RSP (size: {} B, {:08X} to {:08X})", length, dram_address, mem_address);
ircolib::trace("SP DMA from RDRAM to RSP (size: {} B, {:08X} to {:08X})", length, dram_address, mem_address);
for (u32 i = 0; i < spDMALen.count + 1; i++) {
for (u32 j = 0; j < length; j++) {
@@ -159,7 +159,7 @@ void RSP::DMA<false>() {
mem_address += length;
mem_address &= 0xFF8;
}
trace("Addresses after: RSP: 0x{:08X}, Dram: 0x{:08X}", mem_address, dram_address);
ircolib::trace("Addresses after: RSP: 0x{:08X}, Dram: 0x{:08X}", mem_address, dram_address);
lastSuccessfulSPAddr.address = mem_address;
lastSuccessfulSPAddr.bank = spDMASPAddr.bank;
@@ -195,7 +195,7 @@ void RSP::Write(const u32 addr, const u32 val) {
}
break;
default:
panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, val);
ircolib::panic("Unimplemented SP register write {:08X}, val: {:08X}", addr, val);
}
}
} // namespace n64
+1 -1
View File
@@ -150,7 +150,7 @@ struct RSP {
FORCE_INLINE void Step() {
gpr[0] = 0;
const u32 instr = ircolib::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
const u32 instr = ircolib::read_access<u32>(imem, pc & IMEM_DSIZE);
oldPC = pc & 0xFFC;
pc = nextPC & 0xFFC;
nextPC += 4;
@@ -1,5 +1,5 @@
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <ranges>
namespace n64 {
@@ -42,11 +42,12 @@ void Cop0::eret() {
void Cop0::tlbr() {
if (index.i >= 32) {
panic("TLBR with TLB index {}", index.i);
auto i = index.i;
if (i >= 32) {
ircolib::panic("TLBR with TLB index {}", i);
}
const TLBEntry entry = tlb[index.i];
const TLBEntry entry = tlb[i];
entryHi.raw = entry.entryHi.raw;
entryLo0.raw = entry.entryLo0.raw & 0x3FFFFFFF;
@@ -64,7 +65,7 @@ void Cop0::tlbw(const int index_) {
page_mask.mask = top | (top >> 1);
if (index_ >= 32) {
panic("TLBWI with TLB index {}", index_);
ircolib::panic("TLBWI with TLB index {}", index_);
}
tlb[index_].entryHi.raw = entryHi.raw;
@@ -555,7 +555,7 @@ void Cop1::cfc1(const Instruction instr) {
val = fcr31.read();
break;
default:
panic("Undefined CFC1 with rd != 0 or 31");
ircolib::panic("Undefined CFC1 with rd != 0 or 31");
}
regs.Write(instr.rt(), val);
}
@@ -604,7 +604,7 @@ void Cop1::ctc1(const Instruction instr) {
}
break;
default:
panic("Undefined CTC1 with rd != 0 or 31");
ircolib::panic("Undefined CTC1 with rd != 0 or 31");
}
}
+8 -8
View File
@@ -1,5 +1,5 @@
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <Instruction.hpp>
namespace n64 {
@@ -164,8 +164,8 @@ void Interpreter::special(const Instruction instr) {
dsra32(instr);
break;
default:
panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.special_hi,
instr.instr.opcode.special_lo, instr.instr.raw, static_cast<u64>(regs.oldPC));
ircolib::panic("Unimplemented special {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.special_hi,
instr.instr.opcode.special_lo, instr.instr.raw, static_cast<u64>(regs.oldPC));
}
}
@@ -215,8 +215,8 @@ void Interpreter::regimm(const Instruction instr) {
bllink(instr, regs.Read<s64>(instr.rs()) >= 0);
break;
default:
panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.regimm_hi,
instr.instr.opcode.regimm_lo, u32(instr), static_cast<u64>(regs.oldPC));
ircolib::panic("Unimplemented regimm {} {} ({:08X}) (pc: {:016X})", instr.instr.opcode.regimm_hi,
instr.instr.opcode.regimm_lo, u32(instr), static_cast<u64>(regs.oldPC));
}
}
@@ -327,7 +327,7 @@ void Interpreter::DecodeExecute(const Instruction instr) {
bl(instr, regs.cop1.fcr31.compare);
break;
default:
panic("Undefined BC COP1 {:02X}", instr.cop_rt());
ircolib::panic("Undefined BC COP1 {:02X}", instr.cop_rt());
}
return;
}
@@ -450,8 +450,8 @@ void Interpreter::DecodeExecute(const Instruction instr) {
sd(instr);
break;
default:
panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.instr.opcode.op, u32(instr),
static_cast<u64>(regs.oldPC));
ircolib::panic("Unimplemented instruction {:02X} ({:08X}) (pc: {:016X})", instr.instr.opcode.op, u32(instr),
static_cast<u64>(regs.oldPC));
}
}
} // namespace n64
@@ -876,7 +876,7 @@ void Interpreter::cache(const Instruction instr) {
u32 ptag = GetPhysicalAddressPTag(paddr);
if (type > 1)
panic("Unknown cache type {}", type);
ircolib::panic("Unknown cache type {}", type);
if (type == 0)
return CacheTypeInstruction(op, vaddr, paddr, ptag);
@@ -905,7 +905,7 @@ void Interpreter::CacheTypeInstruction(const u8 op, const u64 vaddr, const u32 p
icache.WriteBack(vaddr, paddr, ptag);
break;
default:
panic("Unimplemented icache op 0b{:03b}", op);
ircolib::panic("Unimplemented icache op 0b{:03b}", op);
}
}
@@ -941,7 +941,7 @@ void Interpreter::CacheTypeData(const u8 op, const u64 vaddr, const u32 paddr, c
dcache.WriteBack(vaddr, paddr, ptag);
break;
default:
panic("Unimplemented dcache op 0b{:03b}", op);
ircolib::panic("Unimplemented dcache op 0b{:03b}", op);
}
}*/
} // namespace n64
+23 -23
View File
@@ -28,32 +28,32 @@ void Flash::Load(SaveType saveType, const std::string &path) {
if (saveData.is_mapped()) {
saveData.sync(error);
if (error) {
panic("Could not sync {}", flashPath);
ircolib::panic("Could not sync {}", flashPath);
}
saveData.unmap();
}
auto flashVec = ircolib::ReadFileBinary(flashPath);
auto flashVec = ircolib::read_file_binary(flashPath);
if (flashVec.empty()) {
std::vector<u8> dummy{};
dummy.resize(FLASH_SIZE);
ircolib::WriteFileBinary(dummy, flashPath);
flashVec = ircolib::ReadFileBinary(flashPath);
ircolib::write_file_binary(dummy, flashPath);
flashVec = ircolib::read_file_binary(flashPath);
}
if (flashVec.size() != FLASH_SIZE) {
panic("Corrupt SRAM!");
ircolib::panic("Corrupt SRAM!");
}
saveData = mio::make_mmap_sink(flashPath, error);
if (error) {
panic("Could not make mmap {}", flashPath);
ircolib::panic("Could not make mmap {}", flashPath);
}
}
}
void Flash::CommandExecute() const {
trace("Flash::CommandExecute");
ircolib::trace("Flash::CommandExecute");
switch (state) {
case FlashState::Idle:
break;
@@ -63,7 +63,7 @@ void Flash::CommandExecute() const {
saveData[eraseOffs + i] = 0xFF;
}
} else {
panic("Accessing flash when not mapped!");
ircolib::panic("Accessing flash when not mapped!");
}
break;
case FlashState::Write:
@@ -72,11 +72,11 @@ void Flash::CommandExecute() const {
saveData[writeOffs + i] = writeBuf[i];
}
} else {
panic("Accessing flash when not mapped!");
ircolib::panic("Accessing flash when not mapped!");
}
break;
case FlashState::Read:
panic("Execute command when flash in read state");
ircolib::panic("Execute command when flash in read state");
break;
case FlashState::Status:
break;
@@ -134,10 +134,10 @@ void Flash::Write<u32>(u32 index, u32 val) {
CommandRead();
break;
default:
warn("Invalid flash command: {:02X}", cmd);
ircolib::warn("Invalid flash command: {:02X}", cmd);
}
} else {
warn("Flash Write of {:08X} @ {:08X}", val, index);
ircolib::warn("Flash Write of {:08X} @ {:08X}", val, index);
}
}
@@ -145,19 +145,19 @@ template <>
void Flash::Write<u8>(u32 index, u8 val) {
switch (state) {
case FlashState::Idle:
panic("Invalid FlashState::Idle with Write<u8>");
ircolib::panic("Invalid FlashState::Idle with Write<u8>");
case FlashState::Status:
panic("Invalid FlashState::Status with Write<u8>");
ircolib::panic("Invalid FlashState::Status with Write<u8>");
case FlashState::Erase:
panic("Invalid FlashState::Erase with Write<u8>");
ircolib::panic("Invalid FlashState::Erase with Write<u8>");
case FlashState::Read:
panic("Invalid FlashState::Read with Write<u8>");
ircolib::panic("Invalid FlashState::Read with Write<u8>");
case FlashState::Write:
assert(index <= 0x7F && "Out of range flash Write8");
writeBuf[index] = val;
break;
default:
warn("Invalid flash state on Write<u8>: {:02X}", static_cast<u8>(state));
ircolib::warn("Invalid flash state on Write<u8>: {:02X}", static_cast<u8>(state));
}
}
@@ -165,27 +165,27 @@ template <>
u8 Flash::Read<u8>(const u32 index) const {
switch (state) {
case FlashState::Idle:
panic("Flash read byte while in state FLASH_STATE_IDLE");
ircolib::panic("Flash read byte while in state FLASH_STATE_IDLE");
case FlashState::Write:
panic("Flash read byte while in state FLASH_STATE_WRITE");
ircolib::panic("Flash read byte while in state FLASH_STATE_WRITE");
case FlashState::Read:
if (saveData.is_mapped()) {
const u8 value = saveData[index];
trace("Flash read byte in state read: index {:08X} = {:02X}", index, value);
ircolib::trace("Flash read byte in state read: index {:08X} = {:02X}", index, value);
return value;
}
panic("Accessing flash when not mapped!");
ircolib::panic("Accessing flash when not mapped!");
case FlashState::Status:
{
const u32 offset = (7 - (index % 8)) * 8;
const u8 value = (status >> offset) & 0xFF;
trace("Flash read byte in state status: index {:08X} = {:02X}", index, value);
ircolib::trace("Flash read byte in state status: index {:08X} = {:02X}", index, value);
return value;
}
default:
panic("Flash read byte while in unknown state");
ircolib::panic("Flash read byte while in unknown state");
return 0;
}
}
+3 -3
View File
@@ -5,11 +5,11 @@
namespace n64 {
static bool IsAddressMMIOorRDRAM(u32 addr) {
if (ircolib::IsInsideRange(addr, RDRAM_REGION_START, RDRAM_REGION_END))
if (ircolib::is_inside_range(addr, RDRAM_REGION_START, RDRAM_REGION_END))
return true;
if (ircolib::IsInsideRange(addr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::IsInsideRange(addr, MMIO_REGION_START_2, MMIO_REGION_END_2))
if (ircolib::is_inside_range(addr, MMIO_REGION_START_1, MMIO_REGION_END_1) ||
ircolib::is_inside_range(addr, MMIO_REGION_START_2, MMIO_REGION_END_2))
return true;
return false;
+2 -2
View File
@@ -1,5 +1,5 @@
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <Options.hpp>
namespace n64 {
@@ -76,7 +76,7 @@ void AI::Write(const u32 addr, const u32 val) {
dac.precision = bitrate + 1;
break;
default:
panic("Unhandled AI write at addr {:08X} with val {:08X}", addr, val);
ircolib::panic("Unhandled AI write at addr {:08X} with val {:08X}", addr, val);
}
}
+33 -33
View File
@@ -1,5 +1,5 @@
#include <Audio.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <SDL3/SDL.h>
namespace n64 {
@@ -9,49 +9,49 @@ namespace n64 {
#define BYTES_PER_HALF_SECOND (((float)AUDIO_SAMPLE_RATE / 2) * SYSTEM_SAMPLE_SIZE)
AudioDevice::AudioDevice() {
audioStreamMutex = SDL_CreateMutex();
if (!audioStreamMutex) {
panic("Unable to initialize audio mutex: {}", SDL_GetError());
}
audioStreamMutex = SDL_CreateMutex();
if (!audioStreamMutex) {
ircolib::panic("Unable to initialize audio mutex: {}", SDL_GetError());
}
SDL_InitSubSystem(SDL_INIT_AUDIO);
request = {SYSTEM_SAMPLE_FORMAT, 2, AUDIO_SAMPLE_RATE};
SDL_InitSubSystem(SDL_INIT_AUDIO);
request = {SYSTEM_SAMPLE_FORMAT, 2, AUDIO_SAMPLE_RATE};
audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &request, nullptr, nullptr);
if (!audioStream) {
panic("Unable to create audio stream: {}", SDL_GetError());
}
audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &request, nullptr, nullptr);
if (!audioStream) {
ircolib::panic("Unable to create audio stream: {}", SDL_GetError());
}
}
void AudioDevice::PushSample(const float left, const float volumeL, const float right, const float volumeR) {
const float adjustedL = left * volumeL;
const float adjustedR = right * volumeR;
const float samples[]{adjustedL, adjustedR};
const float adjustedL = left * volumeL;
const float adjustedR = right * volumeR;
const float samples[]{adjustedL, adjustedR};
if (const auto availableBytes = static_cast<float>(SDL_GetAudioStreamAvailable(audioStream));
availableBytes <= BYTES_PER_HALF_SECOND) {
SDL_PutAudioStreamData(audioStream, samples, 2 * SYSTEM_SAMPLE_SIZE);
}
if (const auto availableBytes = static_cast<float>(SDL_GetAudioStreamAvailable(audioStream));
availableBytes <= BYTES_PER_HALF_SECOND) {
SDL_PutAudioStreamData(audioStream, samples, 2 * SYSTEM_SAMPLE_SIZE);
}
if (!running) {
SDL_ResumeAudioStreamDevice(audioStream);
running = true;
}
if (!running) {
SDL_ResumeAudioStreamDevice(audioStream);
running = true;
}
}
void AudioDevice::AdjustSampleRate(int sampleRate) {
LockMutex();
SDL_DestroyAudioStream(audioStream);
LockMutex();
SDL_DestroyAudioStream(audioStream);
if (sampleRate < 4000) { // hack for Animal Forest. It requests a frequency of 3000-something. Weird asf
sampleRate *= 4000.f / static_cast<float>(sampleRate);
}
request = {SYSTEM_SAMPLE_FORMAT, 2, sampleRate};
if (sampleRate < 4000) { // hack for Animal Forest. It requests a frequency of 3000-something. Weird asf
sampleRate *= 4000.f / static_cast<float>(sampleRate);
}
request = {SYSTEM_SAMPLE_FORMAT, 2, sampleRate};
audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &request, nullptr, nullptr);
if (!audioStream) {
panic("Unable to create audio stream: {}", SDL_GetError());
}
UnlockMutex();
audioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &request, nullptr, nullptr);
if (!audioStream) {
ircolib::panic("Unable to create audio stream: {}", SDL_GetError());
}
UnlockMutex();
}
} // namespace n64
+47 -47
View File
@@ -1,6 +1,6 @@
#include <core/mmio/MI.hpp>
#include <core/registers/Registers.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
#define MI_VERSION_REG 0x02020102
@@ -8,58 +8,58 @@ namespace n64 {
MI::MI() { Reset(); }
void MI::Reset() {
intrMask.raw = 0;
intr.raw = 0;
mode.raw = 0;
intrMask.raw = 0;
intr.raw = 0;
mode.raw = 0;
}
auto MI::Read(u32 paddr) const -> u32 {
switch (paddr & 0xF) {
case 0x0:
return mode.raw & 0x3FF;
case 0x4:
return MI_VERSION_REG;
case 0x8:
return intr.raw & 0x3F;
case 0xC:
return intrMask.raw & 0x3F;
default:
panic("Unhandled MI[{:08X}] read", paddr);
}
switch (paddr & 0xF) {
case 0x0:
return mode.raw & 0x3FF;
case 0x4:
return MI_VERSION_REG;
case 0x8:
return intr.raw & 0x3F;
case 0xC:
return intrMask.raw & 0x3F;
default:
ircolib::panic("Unhandled MI[{:08X}] read", paddr);
}
}
void MI::Write(u32 paddr, u32 val) {
switch (paddr & 0xF) { //-----------sc-cscs-cvvv-vvvv
case 0x0: // ----|----|----|----|--uu|deer|rccc|cccc
mode.repeatCount = val & 0x7F;
mode.repeat = val & 0x100 ? 1 : val & 0x80 ? 0 : mode.repeat;
mode.ebus = val & 0x400 ? 1 : val & 0x200 ? 0 : mode.ebus;
mode.upper = val & 0x2000 ? 1 : val & 0x1000 ? 0 : mode.upper;
if(val & 0x800) {
InterruptLower(Interrupt::DP);
switch (paddr & 0xF) { //-----------sc-cscs-cvvv-vvvv
case 0x0: // ----|----|----|----|--uu|deer|rccc|cccc
mode.repeatCount = val & 0x7F;
mode.repeat = val & 0x100 ? 1 : val & 0x80 ? 0 : mode.repeat;
mode.ebus = val & 0x400 ? 1 : val & 0x200 ? 0 : mode.ebus;
mode.upper = val & 0x2000 ? 1 : val & 0x1000 ? 0 : mode.upper;
if (val & 0x800) {
InterruptLower(Interrupt::DP);
}
break;
case 0x4:
case 0x8:
break;
case 0xC:
for (int bit = 0; bit < 6; bit++) {
const int clearbit = bit << 1;
const int setbit = (bit << 1) + 1;
if (val & (1 << clearbit)) {
intrMask.raw &= ~(1 << bit);
}
if (val & (1 << setbit)) {
intrMask.raw |= 1 << bit;
}
}
UpdateInterrupt();
break;
default:
ircolib::panic("Unhandled MI write @ 0x{:08X} with value 0x{:08X}", paddr, val);
}
break;
case 0x4:
case 0x8:
break;
case 0xC:
for (int bit = 0; bit < 6; bit++) {
const int clearbit = bit << 1;
const int setbit = (bit << 1) + 1;
if (val & (1 << clearbit)) {
intrMask.raw &= ~(1 << bit);
}
if (val & (1 << setbit)) {
intrMask.raw |= 1 << bit;
}
}
UpdateInterrupt();
break;
default:
panic("Unhandled MI write @ 0x{:08X} with value 0x{:08X}", paddr, val);
}
}
} // namespace n64
+131 -98
View File
@@ -2,7 +2,7 @@
#include <Scheduler.hpp>
#include <cmath>
#include <core/mmio/PI.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace n64 {
PI::PI() { Reset(); }
@@ -52,17 +52,20 @@ auto PI::BusRead<u8, true>(u32 addr) -> u8 {
switch (addr) {
case REGION_PI_UNKNOWN:
mem.DumpRDRAM();
panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
"returning FF because it is not emulated (pc: 0x{:016X})",
addr, (u64)Core::GetRegs().oldPC);
ircolib::panic(
"Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
"returning FF because it is not emulated (pc: 0x{:016X})",
addr, (u64)Core::GetRegs().oldPC);
case REGION_PI_64DD_REG:
panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::panic(
"Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, "
"returning FF because it is not emulated",
addr);
case REGION_PI_64DD_ROM:
warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::warn(
"Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, "
"returning FF because it is not emulated",
addr);
return 0xFF;
case REGION_PI_SRAM:
return mem.BackupRead<u8>(addr - SREGION_PI_SRAM);
@@ -71,14 +74,16 @@ auto PI::BusRead<u8, true>(u32 addr) -> u8 {
// round to nearest 4 byte boundary, keeping old LSB
const u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
if (index >= mem.rom.cart.size()) {
warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr,
index, index, mem.rom.cart.size(), mem.rom.cart.size());
ircolib::warn(
"Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr,
index, index, mem.rom.cart.size(), mem.rom.cart.size());
return 0xFF;
}
return mem.rom.cart[index];
}
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -91,17 +96,20 @@ auto PI::BusRead<u8, false>(u32 addr) -> u8 {
switch (addr) {
case REGION_PI_UNKNOWN:
panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::panic(
"Reading byte from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
"returning FF because it is not emulated",
addr);
case REGION_PI_64DD_REG:
panic("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::panic(
"Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, "
"returning FF because it is not emulated",
addr);
case REGION_PI_64DD_ROM:
warn("Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::warn(
"Reading byte from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, "
"returning FF because it is not emulated",
addr);
return 0xFF;
case REGION_PI_SRAM:
return mem.BackupRead<u8>(addr - SREGION_PI_SRAM);
@@ -111,14 +119,16 @@ auto PI::BusRead<u8, false>(u32 addr) -> u8 {
// round to nearest 4 byte boundary, keeping old LSB
const u32 index = BYTE_ADDRESS(addr) - SREGION_PI_ROM;
if (index >= mem.rom.cart.size()) {
warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr,
index, index, mem.rom.cart.size(), mem.rom.cart.size());
ircolib::warn(
"Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM! ({}/0x{:016X})", addr,
index, index, mem.rom.cart.size(), mem.rom.cart.size());
return 0xFF;
}
return mem.rom.cart[index];
}
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -127,25 +137,28 @@ void PI::BusWrite<u8, true>(u32 addr, u32 val) {
n64::Mem &mem = n64::Core::GetMem();
switch (addr) {
case REGION_PI_UNKNOWN:
panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
ircolib::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
case REGION_PI_64DD_REG:
if (addr == 0x05000020) {
fprintf(stderr, "%c", val);
} else {
warn("Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!",
val, addr);
ircolib::warn(
"Writing byte 0x{:02X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!",
val, addr);
}
break;
case REGION_PI_64DD_ROM:
panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
ircolib::panic("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val,
addr);
case REGION_PI_SRAM:
mem.BackupWrite<u8>(addr - SREGION_PI_SRAM, val);
break;
case REGION_PI_ROM:
warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
ircolib::warn("Writing byte 0x{:02X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
break;
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -169,31 +182,35 @@ auto PI::BusRead<u16, false>(u32 addr) -> u16 {
switch (addr) {
case REGION_PI_UNKNOWN:
panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::panic(
"Reading half from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
"returning FF because it is not emulated",
addr);
case REGION_PI_64DD_REG:
panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::panic(
"Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, "
"returning FF because it is not emulated",
addr);
case REGION_PI_64DD_ROM:
panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::panic(
"Reading half from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, "
"returning FF because it is not emulated",
addr);
case REGION_PI_SRAM:
panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
ircolib::panic("Reading half from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
case REGION_PI_ROM:
{
addr = (addr + 2) & ~3;
const u32 index = HALF_ADDRESS(addr) - SREGION_PI_ROM;
if (index > mem.rom.cart.size() - 1) {
panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index,
index);
ircolib::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr,
index, index);
}
return ircolib::ReadAccess<u16>(mem.rom.cart, index);
return ircolib::read_access<u16>(mem.rom.cart, index);
}
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -210,19 +227,22 @@ void PI::BusWrite<u16, false>(u32 addr, u32 val) {
switch (addr) {
case REGION_PI_UNKNOWN:
panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
ircolib::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
case REGION_PI_64DD_REG:
panic("Writing half 0x{:04X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!",
val, addr);
ircolib::panic(
"Writing half 0x{:04X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val,
addr);
case REGION_PI_64DD_ROM:
panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
ircolib::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val,
addr);
case REGION_PI_SRAM:
panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr);
ircolib::panic("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr);
case REGION_PI_ROM:
warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
ircolib::warn("Writing half 0x{:04X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
break;
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -240,19 +260,22 @@ auto PI::BusRead<u32, false>(u32 addr) -> u32 {
switch (addr) {
case REGION_PI_UNKNOWN:
warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::warn(
"Reading word from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN - This is the N64DD, "
"returning FF because it is not emulated",
addr);
return 0xFF;
case REGION_PI_64DD_REG:
warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::warn(
"Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG - This is the N64DD, "
"returning FF because it is not emulated",
addr);
return 0xFF;
case REGION_PI_64DD_ROM:
warn("Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, "
"returning FF because it is not emulated",
addr);
ircolib::warn(
"Reading word from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM - This is the N64DD, "
"returning FF because it is not emulated",
addr);
return 0xFF;
case REGION_PI_SRAM:
return mem.BackupRead<u32>(addr);
@@ -263,20 +286,22 @@ auto PI::BusRead<u32, false>(u32 addr) -> u32 {
switch (addr) {
case REGION_CART_ISVIEWER_BUFFER:
return std::byteswap<u32>(
ircolib::ReadAccess<u32>(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER));
ircolib::read_access<u32>(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER));
case CART_ISVIEWER_FLUSH:
panic("Read from ISViewer flush!");
ircolib::panic("Read from ISViewer flush!");
default:
break;
}
warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index, index);
ircolib::warn("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr,
index, index);
return 0;
}
return ircolib::ReadAccess<u32>(mem.rom.cart, index);
return ircolib::read_access<u32>(mem.rom.cart, index);
}
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -293,20 +318,21 @@ void PI::BusWrite<u32, false>(u32 addr, u32 val) {
if (!WriteLatch(val)) [[unlikely]] {
return;
}
warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
ircolib::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
return;
case REGION_PI_64DD_REG:
if (!WriteLatch(val)) [[unlikely]] {
return;
}
warn("Writing word 0x{:08X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!",
val, addr);
ircolib::warn(
"Writing word 0x{:08X} to address 0x{:08X} in region: REGION_PI_64DD_ROM, this is the 64DD, ignoring!", val,
addr);
return;
case REGION_PI_64DD_ROM:
if (!WriteLatch(val)) [[unlikely]] {
return;
}
warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
ircolib::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
return;
case REGION_PI_SRAM:
if (!WriteLatch(val)) [[unlikely]] {
@@ -317,7 +343,7 @@ void PI::BusWrite<u32, false>(u32 addr, u32 val) {
case REGION_PI_ROM:
switch (addr) {
case REGION_CART_ISVIEWER_BUFFER:
ircolib::WriteAccess<u32>(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER, std::byteswap(val));
ircolib::write_access<u32>(mem.isviewer, addr - SREGION_CART_ISVIEWER_BUFFER, std::byteswap(val));
break;
case CART_ISVIEWER_FLUSH:
{
@@ -327,21 +353,23 @@ void PI::BusWrite<u32, false>(u32 addr, u32 val) {
mem.isviewer_sink << message;
mem.isviewer_sink.flush();
} else {
panic("ISViewer buffer size is emulated at {} bytes, but received a flush command for {} bytes!",
CART_ISVIEWER_SIZE, val);
ircolib::panic(
"ISViewer buffer size is emulated at {} bytes, but received a flush command for {} bytes!",
CART_ISVIEWER_SIZE, val);
}
break;
}
default:
if (!WriteLatch(val)) [[unlikely]] {
warn("Couldn't latch PI bus, ignoring write to REGION_PI_ROM");
ircolib::warn("Couldn't latch PI bus, ignoring write to REGION_PI_ROM");
return;
}
warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
ircolib::warn("Writing word 0x{:08X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
}
return;
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -359,24 +387,25 @@ auto PI::BusRead<u64, false>(u32 addr) -> u64 {
switch (addr) {
case REGION_PI_UNKNOWN:
panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", addr);
ircolib::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", addr);
case REGION_PI_64DD_REG:
panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", addr);
ircolib::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", addr);
case REGION_PI_64DD_ROM:
panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", addr);
ircolib::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", addr);
case REGION_PI_SRAM:
panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
ircolib::panic("Reading dword from address 0x{:08X} in unsupported region: REGION_PI_SRAM", addr);
case REGION_PI_ROM:
{
const u32 index = addr - SREGION_PI_ROM;
if (index > mem.rom.cart.size() - 7) { // -7 because we're reading an entire dword
panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr, index,
index);
ircolib::panic("Address 0x{:08X} accessed an index {}/0x{:X} outside the bounds of the ROM!", addr,
index, index);
}
return ircolib::ReadAccess<u64>(mem.rom.cart, index);
return ircolib::read_access<u64>(mem.rom.cart, index);
}
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -393,18 +422,22 @@ void PI::BusWrite<false>(u32 addr, u64 val) {
switch (addr) {
case REGION_PI_UNKNOWN:
panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val, addr);
ircolib::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_UNKNOWN", val,
addr);
case REGION_PI_64DD_REG:
panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", val, addr);
ircolib::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_REG", val,
addr);
case REGION_PI_64DD_ROM:
panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val, addr);
ircolib::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_64DD_ROM", val,
addr);
case REGION_PI_SRAM:
panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr);
ircolib::panic("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_SRAM", val, addr);
case REGION_PI_ROM:
warn("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
ircolib::warn("Writing dword 0x{:016X} to address 0x{:08X} in unsupported region: REGION_PI_ROM", val, addr);
break;
default:
panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!", addr);
ircolib::panic("Should never end up here! Access to address {:08X} which did not match any PI bus regions!",
addr);
}
}
@@ -451,7 +484,7 @@ auto PI::Read(u32 addr) const -> u32 {
case 0x04600030:
return piBsdDom2Rls;
default:
panic("Unhandled PI[{:08X}] read", addr);
ircolib::panic("Unhandled PI[{:08X}] read", addr);
}
}
@@ -465,7 +498,7 @@ u8 PI::GetDomain(const u32 address) {
case REGION_PI_SRAM:
return 2;
default:
panic("Unknown PI domain for address {:08X}!", address);
ircolib::panic("Unknown PI domain for address {:08X}!", address);
}
}
@@ -490,7 +523,7 @@ u32 PI::AccessTiming(const u8 domain, const u32 length) const {
page_size = 1 << (piBsdDom2Pgs + 2);
break;
default:
panic("Unknown PI domain: {}\n", domain);
ircolib::panic("Unknown PI domain: {}\n", domain);
}
const uint32_t pages = static_cast<uint32_t>(ceil(static_cast<double>(length) / static_cast<double>(page_size)));
@@ -506,7 +539,7 @@ template <>
void PI::DMA<false>() {
n64::Mem &mem = n64::Core::GetMem();
const s32 len = rdLen + 1;
trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
ircolib::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
if (mem.rom.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1);
}
@@ -524,7 +557,7 @@ void PI::DMA<false>() {
dmaBusy = true;
u64 completo = AccessTiming(GetDomain(cartAddr), len);
trace("Will complete in {} cycles", completo);
ircolib::trace("Will complete in {} cycles", completo);
Scheduler::GetInstance().EnqueueRelative(completo, PI_DMA_COMPLETE);
}
@@ -533,7 +566,7 @@ template <>
void PI::DMA<true>() {
n64::Mem &mem = n64::Core::GetMem();
const s32 len = wrLen + 1;
trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
ircolib::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
if (mem.rom.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < (CART_REGION_START_2_2 + 1_mb)) {
cartAddr = SREGION_PI_SRAM | ((cartAddr & (1_mb - 1)) << 1);
@@ -551,7 +584,7 @@ void PI::DMA<true>() {
dmaBusy = true;
u64 completo = AccessTiming(GetDomain(cartAddr), len);
trace("Will complete in {} cycles", completo);
ircolib::trace("Will complete in {} cycles", completo);
Scheduler::GetInstance().EnqueueRelative(completo, PI_DMA_COMPLETE);
}
@@ -603,7 +636,7 @@ void PI::Write(u32 addr, u32 val) {
piBsdDom2Rls = val & 0xff;
break;
default:
panic("Unhandled PI[{:08X}] write ({:08X})", val, addr);
ircolib::panic("Unhandled PI[{:08X}] write ({:08X})", val, addr);
}
}
} // namespace n64
+24 -24
View File
@@ -2,7 +2,7 @@
#include <cassert>
#include <cic_nus_6105/n64_cic_nus_6105.hpp>
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <Options.hpp>
#define MEMPAK_SIZE 32768
@@ -17,14 +17,14 @@ void PIF::Reset() {
if (mempak.is_mapped()) {
mempak.sync(error);
if (error) {
panic("Could not sync {}", mempakPath);
ircolib::panic("Could not sync {}", mempakPath);
}
mempak.unmap();
}
if (eeprom.is_mapped()) {
eeprom.sync(error);
if (error) {
panic("Could not sync {}", eepromPath);
ircolib::panic("Could not sync {}", eepromPath);
}
eeprom.unmap();
}
@@ -48,25 +48,25 @@ void PIF::MaybeLoadMempak() {
if (mempak.is_mapped()) {
mempak.sync(error);
if (error) {
panic("Could not sync {}", mempakPath);
ircolib::panic("Could not sync {}", mempakPath);
}
mempak.unmap();
}
auto mempakVec = ircolib::ReadFileBinary(mempakPath);
auto mempakVec = ircolib::read_file_binary(mempakPath);
if (mempak.empty()) {
info(R"(Empty mempak, making one @ "{}" ...)", mempakPath);
ircolib::WriteFileBinary(std::array<u8, MEMPAK_SIZE>{}, mempakPath);
mempakVec = ircolib::ReadFileBinary(mempakPath);
ircolib::info(R"(Empty mempak, making one @ "{}" ...)", mempakPath);
ircolib::write_file_binary(std::array<u8, MEMPAK_SIZE>{}, mempakPath);
mempakVec = ircolib::read_file_binary(mempakPath);
}
if (mempakVec.size() != MEMPAK_SIZE) {
panic("Corrupt mempak!");
ircolib::panic("Corrupt mempak!");
}
mempak = mio::make_mmap_sink(mempakPath, error);
if (error) {
panic("Could not open {}", mempakPath);
ircolib::panic("Could not open {}", mempakPath);
}
mempakOpen = true;
}
@@ -85,7 +85,7 @@ FORCE_INLINE size_t GetSaveSize(SaveType saveType) {
case SAVE_FLASH_1m:
return 131072;
default:
panic("Unknown save type!");
ircolib::panic("Unknown save type!");
}
}
@@ -101,28 +101,28 @@ void PIF::LoadEeprom(const SaveType saveType, const std::string &path) {
if (eeprom.is_mapped()) {
eeprom.sync(error);
if (error) {
panic("Could not sync {}", eepromPath);
ircolib::panic("Could not sync {}", eepromPath);
}
eeprom.unmap();
}
eepromSize = GetSaveSize(saveType);
auto eepromVec = ircolib::ReadFileBinary(eepromPath);
auto eepromVec = ircolib::read_file_binary(eepromPath);
if (eepromVec.empty()) {
std::vector<u8> dummy{};
dummy.resize(GetSaveSize(saveType));
ircolib::WriteFileBinary(dummy, eepromPath);
ircolib::write_file_binary(dummy, eepromPath);
eepromVec = dummy;
}
if (eepromVec.size() != eepromSize) {
panic("Corrupt eeprom!");
ircolib::panic("Corrupt eeprom!");
}
eeprom = mio::make_mmap_sink(eepromPath, error);
if (error) {
panic("Could not open {}. Reason {}", eepromPath, error.message());
ircolib::panic("Could not open {}. Reason {}", eepromPath, error.message());
}
}
}
@@ -254,7 +254,7 @@ void PIF::ConfigureJoyBusFrame() {
}
break;
default:
panic("Invalid read RTC block {}", commandStart);
ircolib::panic("Invalid read RTC block {}", commandStart);
}
}
break;
@@ -262,7 +262,7 @@ void PIF::ConfigureJoyBusFrame() {
memset(res, 0, 8);
break;
default:
panic("Invalid PIF command: {:X}", commandIndex);
ircolib::panic("Invalid PIF command: {:X}", commandIndex);
}
i += commandLength + reslen;
@@ -351,12 +351,12 @@ void PIF::EepromRead(const u8 *cmd, u8 *res) const {
if (channel == 4) {
const u8 offset = cmd[3];
if ((offset * 8) >= GetSaveSize(mem.rom.saveType)) {
panic("Out of range EEPROM read! offset: {:02X}", offset);
ircolib::panic("Out of range EEPROM read! offset: {:02X}", offset);
}
std::copy_n(eeprom.begin() + offset * 8, 8, res);
} else {
panic("EEPROM read on bad channel {}", channel);
ircolib::panic("EEPROM read on bad channel {}", channel);
}
}
@@ -366,14 +366,14 @@ void PIF::EepromWrite(const u8 *cmd, u8 *res) {
if (channel == 4) {
const u8 offset = cmd[3];
if ((offset * 8) >= GetSaveSize(mem.rom.saveType)) {
panic("Out of range EEPROM write! offset: {:02X}", offset);
ircolib::panic("Out of range EEPROM write! offset: {:02X}", offset);
}
std::copy_n(cmd + 4, 8, eeprom.begin() + offset * 8);
res[0] = 0; // Error byte, I guess it always succeeds?
} else {
panic("EEPROM write on bad channel {}", channel);
ircolib::panic("EEPROM write on bad channel {}", channel);
}
}
@@ -384,7 +384,7 @@ void PIF::HLE(const bool pal, const CICType cicType) const {
switch (cicType) {
case UNKNOWN_CIC_TYPE:
warn("Unknown CIC type!");
ircolib::warn("Unknown CIC type!");
break;
case CIC_NUS_6101:
regs.Write<u64>(0, 0x0000000000000000);
@@ -651,7 +651,7 @@ void PIF::Execute() const {
mem.Write<u32>(PIF_RAM_REGION_START + 0x24, cicSeeds[cicType]);
switch (cicType) {
case UNKNOWN_CIC_TYPE:
warn("Unknown CIC type!");
ircolib::warn("Unknown CIC type!");
break;
case CIC_NUS_6101 ... CIC_NUS_6103_7103:
mem.Write<u32>(0x318, RDRAM_SIZE);
+103 -103
View File
@@ -1,121 +1,121 @@
#include <Netplay.hpp>
#include <PIF.hpp>
#include <PIF/MupenMovie.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace n64 {
void PIF::InitDevices(SaveType saveType) {
joybusDevices[0].type = JOYBUS_CONTROLLER;
joybusDevices[0].accessoryType = ACCESSORY_MEMPACK;
for (int i = 1; i < 4; i++) { // TODO: make this configurable
joybusDevices[i].type = JOYBUS_NONE;
joybusDevices[i].accessoryType = ACCESSORY_NONE;
}
joybusDevices[0].type = JOYBUS_CONTROLLER;
joybusDevices[0].accessoryType = ACCESSORY_MEMPACK;
for (int i = 1; i < 4; i++) { // TODO: make this configurable
joybusDevices[i].type = JOYBUS_NONE;
joybusDevices[i].accessoryType = ACCESSORY_NONE;
}
if (saveType == SAVE_EEPROM_4k) {
joybusDevices[4].type = JOYBUS_4KB_EEPROM;
} else if (saveType == SAVE_EEPROM_16k) {
joybusDevices[4].type = JOYBUS_16KB_EEPROM;
} else {
joybusDevices[4].type = JOYBUS_NONE;
}
joybusDevices[5].type = JOYBUS_NONE;
if (saveType == SAVE_EEPROM_4k) {
joybusDevices[4].type = JOYBUS_4KB_EEPROM;
} else if (saveType == SAVE_EEPROM_16k) {
joybusDevices[4].type = JOYBUS_16KB_EEPROM;
} else {
joybusDevices[4].type = JOYBUS_NONE;
}
joybusDevices[5].type = JOYBUS_NONE;
}
void PIF::ControllerID(u8 *res) const {
if (channel < 6) {
switch (joybusDevices[channel].type) {
case JOYBUS_NONE:
res[0] = 0x00;
res[1] = 0x00;
res[2] = 0x00;
break;
case JOYBUS_CONTROLLER:
res[0] = 0x05;
res[1] = 0x00;
res[2] = joybusDevices[channel].accessoryType != ACCESSORY_NONE ? 0x01 : 0x02;
break;
case JOYBUS_DANCEPAD:
res[0] = 0x05;
res[1] = 0x00;
res[2] = 0x00;
break;
case JOYBUS_VRU:
res[0] = 0x00;
res[1] = 0x01;
res[2] = 0x00;
break;
case JOYBUS_MOUSE:
res[0] = 0x02;
res[1] = 0x00;
res[2] = 0x00;
break;
case JOYBUS_RANDNET_KEYBOARD:
res[0] = 0x00;
res[1] = 0x02;
res[2] = 0x00;
break;
case JOYBUS_DENSHA_DE_GO:
res[0] = 0x20;
res[1] = 0x04;
res[2] = 0x00;
break;
case JOYBUS_4KB_EEPROM:
res[0] = 0x00;
res[1] = 0x80;
res[2] = 0x00;
break;
case JOYBUS_16KB_EEPROM:
res[0] = 0x00;
res[1] = 0xC0;
res[2] = 0x00;
break;
if (channel < 6) {
switch (joybusDevices[channel].type) {
case JOYBUS_NONE:
res[0] = 0x00;
res[1] = 0x00;
res[2] = 0x00;
break;
case JOYBUS_CONTROLLER:
res[0] = 0x05;
res[1] = 0x00;
res[2] = joybusDevices[channel].accessoryType != ACCESSORY_NONE ? 0x01 : 0x02;
break;
case JOYBUS_DANCEPAD:
res[0] = 0x05;
res[1] = 0x00;
res[2] = 0x00;
break;
case JOYBUS_VRU:
res[0] = 0x00;
res[1] = 0x01;
res[2] = 0x00;
break;
case JOYBUS_MOUSE:
res[0] = 0x02;
res[1] = 0x00;
res[2] = 0x00;
break;
case JOYBUS_RANDNET_KEYBOARD:
res[0] = 0x00;
res[1] = 0x02;
res[2] = 0x00;
break;
case JOYBUS_DENSHA_DE_GO:
res[0] = 0x20;
res[1] = 0x04;
res[2] = 0x00;
break;
case JOYBUS_4KB_EEPROM:
res[0] = 0x00;
res[1] = 0x80;
res[2] = 0x00;
break;
case JOYBUS_16KB_EEPROM:
res[0] = 0x00;
res[1] = 0xC0;
res[2] = 0x00;
break;
}
} else {
ircolib::panic("Device ID on unknown channel {}", channel);
}
} else {
panic("Device ID on unknown channel {}", channel);
}
}
bool PIF::ReadButtons(u8 *res) {
if (channel >= 6) {
res[0] = 0;
res[1] = 0;
res[2] = 0;
res[3] = 0;
return false;
}
switch (joybusDevices[channel].type) {
case JOYBUS_NONE:
res[0] = 0x00;
res[1] = 0x00;
res[2] = 0x00;
res[3] = 0x00;
return false; // Device not present
case JOYBUS_4KB_EEPROM:
case JOYBUS_16KB_EEPROM:
case JOYBUS_CONTROLLER:
if (movie.IsLoaded()) {
const Controller controller = movie.NextInputs();
res[0] = controller.byte1;
res[1] = controller.byte2;
res[2] = controller.joyX;
res[3] = controller.joyY;
} else {
res[0] = joybusDevices[channel].controller.byte1;
res[1] = joybusDevices[channel].controller.byte2;
res[2] = joybusDevices[channel].controller.joyX;
res[3] = joybusDevices[channel].controller.joyY;
if (channel >= 6) {
res[0] = 0;
res[1] = 0;
res[2] = 0;
res[3] = 0;
return false;
}
return true;
case JOYBUS_DANCEPAD:
case JOYBUS_VRU:
case JOYBUS_MOUSE:
case JOYBUS_RANDNET_KEYBOARD:
case JOYBUS_DENSHA_DE_GO:
return false;
}
return true;
switch (joybusDevices[channel].type) {
case JOYBUS_NONE:
res[0] = 0x00;
res[1] = 0x00;
res[2] = 0x00;
res[3] = 0x00;
return false; // Device not present
case JOYBUS_4KB_EEPROM:
case JOYBUS_16KB_EEPROM:
case JOYBUS_CONTROLLER:
if (movie.IsLoaded()) {
const Controller controller = movie.NextInputs();
res[0] = controller.byte1;
res[1] = controller.byte2;
res[2] = controller.joyX;
res[3] = controller.joyY;
} else {
res[0] = joybusDevices[channel].controller.byte1;
res[1] = joybusDevices[channel].controller.byte2;
res[2] = joybusDevices[channel].controller.joyX;
res[3] = joybusDevices[channel].controller.joyY;
}
return true;
case JOYBUS_DANCEPAD:
case JOYBUS_VRU:
case JOYBUS_MOUSE:
case JOYBUS_RANDNET_KEYBOARD:
case JOYBUS_DENSHA_DE_GO:
return false;
}
return true;
}
} // namespace n64
+96 -99
View File
@@ -3,136 +3,133 @@
#include <File.hpp>
#include <PIF.hpp>
union TASMovieControllerData {
struct {
unsigned dpadRight : 1;
unsigned dpadLeft : 1;
unsigned dpadDown : 1;
unsigned dpadUp : 1;
unsigned start : 1;
unsigned z : 1;
unsigned b : 1;
unsigned a : 1;
unsigned cRight : 1;
unsigned cLeft : 1;
unsigned cDown : 1;
unsigned cUp : 1;
unsigned r : 1;
unsigned l : 1;
unsigned : 2;
signed analogX : 8;
signed analogY : 8;
};
u32 raw;
struct {
unsigned dpadRight : 1;
unsigned dpadLeft : 1;
unsigned dpadDown : 1;
unsigned dpadUp : 1;
unsigned start : 1;
unsigned z : 1;
unsigned b : 1;
unsigned a : 1;
unsigned cRight : 1;
unsigned cLeft : 1;
unsigned cDown : 1;
unsigned cUp : 1;
unsigned r : 1;
unsigned l : 1;
unsigned : 2;
signed analogX : 8;
signed analogY : 8;
};
u32 raw;
} __attribute__((packed));
static_assert(sizeof(TASMovieControllerData) == 4);
void MupenMovie::Load(const fs::path &path) {
filename = path.stem().string();
loadedTasMovie = ircolib::ReadFileBinary(path.string());
if (!IsLoaded()) {
error("Error loading movie!");
return;
}
filename = path.stem().string();
loadedTasMovie = ircolib::read_file_binary(path.string());
if (!IsLoaded()) {
ircolib::error("Error loading movie!");
return;
}
std::memcpy(&loadedTasMovieHeader, loadedTasMovie.data(), sizeof(TASMovieHeader));
std::memcpy(&loadedTasMovieHeader, loadedTasMovie.data(), sizeof(TASMovieHeader));
if (loadedTasMovieHeader.signature[0] != 0x4D || loadedTasMovieHeader.signature[1] != 0x36 ||
loadedTasMovieHeader.signature[2] != 0x34 || loadedTasMovieHeader.signature[3] != 0x1A) {
error("Failed to load movie: incorrect signature. Are you sure this is a valid movie?");
return;
}
if (loadedTasMovieHeader.signature[0] != 0x4D || loadedTasMovieHeader.signature[1] != 0x36 ||
loadedTasMovieHeader.signature[2] != 0x34 || loadedTasMovieHeader.signature[3] != 0x1A) {
ircolib::error("Failed to load movie: incorrect signature. Are you sure this is a valid movie?");
return;
}
if (loadedTasMovieHeader.version != 3) {
error("This movie is version {}: only version 3 is supported.", loadedTasMovieHeader.version);
return;
}
if (loadedTasMovieHeader.version != 3) {
ircolib::error("This movie is version {}: only version 3 is supported.", loadedTasMovieHeader.version);
return;
}
if (loadedTasMovieHeader.startType != 2) {
error("Movie start type is {} - only movies with a start type of 2 are supported (start at power on)",
loadedTasMovieHeader.startType);
return;
}
if (loadedTasMovieHeader.startType != 2) {
ircolib::error("Movie start type is {} - only movies with a start type of 2 are supported (start at power on)",
loadedTasMovieHeader.startType);
return;
}
info("Loaded movie '{}' ", loadedTasMovieHeader.movie_description);
info("by {}", loadedTasMovieHeader.author_name);
info("{} controller(s) connected", loadedTasMovieHeader.numControllers);
ircolib::info("Loaded movie '{}' ", loadedTasMovieHeader.movie_description);
ircolib::info("by {}", loadedTasMovieHeader.author_name);
ircolib::info("{} controller(s) connected", loadedTasMovieHeader.numControllers);
if (loadedTasMovieHeader.numControllers != 1) {
error("Currently, only movies with 1 controller connected are supported.");
return;
}
if (loadedTasMovieHeader.numControllers != 1) {
ircolib::error("Currently, only movies with 1 controller connected are supported.");
return;
}
loadedTasMovieIndex = sizeof(TASMovieHeader) - 4; // skip header
loadedTasMovieIndex = sizeof(TASMovieHeader) - 4; // skip header
}
MupenMovie::MupenMovie(const fs::path &path) {
Load(path);
}
MupenMovie::MupenMovie(const fs::path &path) { Load(path); }
void MupenMovie::Reset() {
if (!IsLoaded())
return;
if (!IsLoaded())
return;
loadedTasMovieIndex = sizeof(TASMovieHeader) - 4; // skip header
loadedTasMovieIndex = sizeof(TASMovieHeader) - 4; // skip header
}
FORCE_INLINE void LogController(const n64::Controller &controller) {
debug("c_right: {}", controller.cRight);
debug("c_left: {}", controller.cLeft);
debug("c_down: {}", controller.cDown);
debug("c_up: {}", controller.cUp);
debug("r: {}", controller.r);
debug("l: {}", controller.l);
debug("dp_right: {}", controller.dpRight);
debug("dp_left: {}", controller.dpLeft);
debug("dp_down: {}", controller.dpDown);
debug("dp_up: {}", controller.dpUp);
debug("z: {}", controller.z);
debug("b: {}", controller.b);
debug("a: {}", controller.a);
debug("start: {}", controller.start);
debug("joy_x: {}", controller.joyX);
debug("joy_y: {}", controller.joyY);
ircolib::debug("c_right: {}", controller.cRight);
ircolib::debug("c_left: {}", controller.cLeft);
ircolib::debug("c_down: {}", controller.cDown);
ircolib::debug("c_up: {}", controller.cUp);
ircolib::debug("r: {}", controller.r);
ircolib::debug("l: {}", controller.l);
ircolib::debug("dp_right: {}", controller.dpRight);
ircolib::debug("dp_left: {}", controller.dpLeft);
ircolib::debug("dp_down: {}", controller.dpDown);
ircolib::debug("dp_up: {}", controller.dpUp);
ircolib::debug("z: {}", controller.z);
ircolib::debug("b: {}", controller.b);
ircolib::debug("a: {}", controller.a);
ircolib::debug("start: {}", controller.start);
ircolib::debug("joy_x: {}", controller.joyX);
ircolib::debug("joy_y: {}", controller.joyY);
}
n64::Controller MupenMovie::NextInputs() {
if (loadedTasMovieIndex + sizeof(TASMovieControllerData) > loadedTasMovie.size()) {
loadedTasMovie.clear();
n64::Controller emptyController{};
return emptyController;
}
if (loadedTasMovieIndex + sizeof(TASMovieControllerData) > loadedTasMovie.size()) {
loadedTasMovie.clear();
n64::Controller emptyController{};
return emptyController;
}
TASMovieControllerData movieCData{};
memcpy(&movieCData, &loadedTasMovie[loadedTasMovieIndex], sizeof(TASMovieControllerData));
TASMovieControllerData movieCData{};
memcpy(&movieCData, &loadedTasMovie[loadedTasMovieIndex], sizeof(TASMovieControllerData));
loadedTasMovieIndex += sizeof(TASMovieControllerData);
loadedTasMovieIndex += sizeof(TASMovieControllerData);
n64::Controller controller{};
n64::Controller controller{};
controller.cRight = movieCData.cRight;
controller.cLeft = movieCData.cLeft;
controller.cDown = movieCData.cDown;
controller.cUp = movieCData.cUp;
controller.r = movieCData.r;
controller.l = movieCData.l;
controller.cRight = movieCData.cRight;
controller.cLeft = movieCData.cLeft;
controller.cDown = movieCData.cDown;
controller.cUp = movieCData.cUp;
controller.r = movieCData.r;
controller.l = movieCData.l;
controller.dpRight = movieCData.dpadRight;
controller.dpLeft = movieCData.dpadLeft;
controller.dpDown = movieCData.dpadDown;
controller.dpUp = movieCData.dpadUp;
controller.dpRight = movieCData.dpadRight;
controller.dpLeft = movieCData.dpadLeft;
controller.dpDown = movieCData.dpadDown;
controller.dpUp = movieCData.dpadUp;
controller.z = movieCData.z;
controller.b = movieCData.b;
controller.a = movieCData.a;
controller.start = movieCData.start;
controller.z = movieCData.z;
controller.b = movieCData.b;
controller.a = movieCData.a;
controller.start = movieCData.start;
controller.joyX = movieCData.analogX;
controller.joyY = movieCData.analogY;
controller.joyX = movieCData.analogX;
controller.joyY = movieCData.analogY;
LogController(controller);
LogController(controller);
return controller;
return controller;
}
+33 -33
View File
@@ -1,47 +1,47 @@
#include <core/mmio/RI.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace n64 {
RI::RI() { Reset(); }
void RI::Reset() {
mode = 0xE;
config = 0x40;
select = 0x14;
refresh = 0x63634;
mode = 0xE;
config = 0x40;
select = 0x14;
refresh = 0x63634;
}
auto RI::Read(u32 addr) const -> u32 {
switch (addr) {
case 0x04700000:
return mode;
case 0x04700004:
return config;
case 0x0470000C:
return select;
case 0x04700010:
return refresh;
default:
panic("Unhandled RI[{:08X}] read", addr);
}
switch (addr) {
case 0x04700000:
return mode;
case 0x04700004:
return config;
case 0x0470000C:
return select;
case 0x04700010:
return refresh;
default:
ircolib::panic("Unhandled RI[{:08X}] read", addr);
}
}
void RI::Write(u32 addr, u32 val) {
switch (addr) {
case 0x04700000:
mode = val;
break;
case 0x04700004:
config = val;
break;
case 0x0470000C:
select = val;
break;
case 0x04700010:
refresh = val;
break;
default:
panic("Unhandled RI[{:08X}] write with val {:08X}", addr, val);
}
switch (addr) {
case 0x04700000:
mode = val;
break;
case 0x04700004:
config = val;
break;
case 0x0470000C:
select = val;
break;
case 0x04700010:
refresh = val;
break;
default:
ircolib::panic("Unhandled RI[{:08X}] write with val {:08X}", addr, val);
}
}
} // namespace n64
+4 -4
View File
@@ -32,7 +32,7 @@ auto SI::Read(u32 addr) const -> u32 {
return val;
}
default:
panic("Unhandled SI[{:08X}] read", addr);
ircolib::panic("Unhandled SI[{:08X}] read", addr);
}
}
@@ -44,7 +44,7 @@ void SI::DMA<true>() {
for (int i = 0; i < 64; i++) {
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
}
trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr);
ircolib::trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr);
}
// rdram -> pif
@@ -54,7 +54,7 @@ void SI::DMA<false>() {
for (int i = 0; i < 64; i++) {
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
}
trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr);
ircolib::trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr);
}
void SI::DMA() {
@@ -89,7 +89,7 @@ void SI::Write(u32 addr, u32 val) {
mem.mmio.mi.InterruptLower(MI::Interrupt::SI);
break;
default:
panic("Unhandled SI[{:08X}] write ({:08X})", addr, val);
ircolib::panic("Unhandled SI[{:08X}] write ({:08X})", addr, val);
}
}
} // namespace n64
+3 -3
View File
@@ -1,5 +1,5 @@
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace n64 {
VI::VI() { Reset(); }
@@ -55,7 +55,7 @@ u32 VI::Read(const u32 paddr) const {
default:
{
n64::Registers &regs = n64::Core::GetRegs();
panic("32-bit read access on unhandled VI register @ pc 0x{:016X}", u64(regs.oldPC));
ircolib::panic("32-bit read access on unhandled VI register @ pc 0x{:016X}", u64(regs.oldPC));
return 0;
}
}
@@ -120,7 +120,7 @@ void VI::Write(const u32 paddr, const u32 val) {
case 0x0440003C:
break;
default:
panic("Unimplemented VI[{:08X}] write ({:08X})", paddr, val);
ircolib::panic("Unimplemented VI[{:08X}] write ({:08X})", paddr, val);
}
}
} // namespace n64
+32 -32
View File
@@ -1,5 +1,5 @@
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace n64 {
Cop0::Cop0() { Reset(); }
@@ -103,7 +103,7 @@ u32 Cop0::GetReg32(const u8 addr) {
case 31:
return openbus;
default:
panic("Unsupported word read from COP0 register {}", addr);
ircolib::panic("Unsupported word read from COP0 register {}", addr);
}
}
@@ -140,7 +140,7 @@ u64 Cop0::GetReg64(const u8 addr) const {
case 31:
return openbus;
default:
panic("Unsupported dword read from COP0 register {}", addr);
ircolib::panic("Unsupported dword read from COP0 register {}", addr);
}
}
@@ -236,7 +236,7 @@ void Cop0::SetReg32(const u8 addr, const u32 value) {
case 31:
break;
default:
panic("Unsupported word write from COP0 register {}", addr);
ircolib::panic("Unsupported word write from COP0 register {}", addr);
}
}
@@ -281,7 +281,7 @@ void Cop0::SetReg64(const u8 addr, const u64 value) {
ErrorEPC = (s64)value;
break;
default:
panic("Unsupported dword write to COP0 register {}", addr);
ircolib::panic("Unsupported dword write to COP0 register {}", addr);
}
}
@@ -387,7 +387,7 @@ void Cop0::FireException(const ExceptionCode code, const int cop, s64 pc) {
}
if (status.bev) {
panic("BEV bit set!");
ircolib::panic("BEV bit set!");
}
regs.SetPC32(s32(0x80000000 + vectorOffset));
@@ -408,7 +408,7 @@ void Cop0::HandleTLBException(const u64 vaddr) {
Cop0::ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAccessType accessType) {
switch (error) {
case NONE:
panic("Getting TLB exception with error NONE");
ircolib::panic("Getting TLB exception with error NONE");
case INVALID:
case MISS:
return accessType == LOAD ? ExceptionCode::TLBLoad : ExceptionCode::TLBStore;
@@ -417,7 +417,7 @@ Cop0::ExceptionCode Cop0::GetTLBExceptionCode(const TLBError error, const TLBAcc
case DISALLOWED_ADDRESS:
return accessType == LOAD ? ExceptionCode::AddressErrorLoad : ExceptionCode::AddressErrorStore;
default:
panic("Getting TLB exception for unknown error code! ({})", static_cast<u8>(error));
ircolib::panic("Getting TLB exception for unknown error code! ({})", static_cast<u8>(error));
return {};
}
}
@@ -459,14 +459,14 @@ void Cop0::decode(const Instruction instr) {
}
break;
default:
panic("Unimplemented COP0 instruction {}", instr.cop_rs());
ircolib::panic("Unimplemented COP0 instruction {}", instr.cop_rs());
}
}
template <>
bool Cop0::MapVirtualAddress<u32, true>(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) {
if (ircolib::IsInsideRange(vaddr, START_VREGION_KUSEG, END_VREGION_KUSEG))
if (ircolib::is_inside_range(vaddr, START_VREGION_KUSEG, END_VREGION_KUSEG))
return ProbeTLB(accessType, s64(s32(vaddr)), paddr);
tlbError = DISALLOWED_ADDRESS;
@@ -476,25 +476,25 @@ bool Cop0::MapVirtualAddress<u32, true>(const TLBAccessType accessType, const u6
template <>
bool Cop0::MapVirtualAddress<u32, false>(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) {
u8 segment = static_cast<u32>(vaddr) >> 29 & 7;
if (ircolib::IsInsideRange(segment, 0, 3) || segment == 7)
if (ircolib::is_inside_range(segment, 0, 3) || segment == 7)
return ProbeTLB(accessType, static_cast<s32>(vaddr), paddr);
if (ircolib::IsInsideRange(segment, 4, 5)) {
if (ircolib::is_inside_range(segment, 4, 5)) {
paddr = vaddr & 0x1FFFFFFF;
return true;
}
if (segment == 6)
panic("Unimplemented virtual mapping in KSSEG! ({:08X})", vaddr);
ircolib::panic("Unimplemented virtual mapping in KSSEG! ({:08X})", vaddr);
panic("Should never end up in base case in MapVirtualAddress! ({:08X})", vaddr);
ircolib::panic("Should never end up in base case in MapVirtualAddress! ({:08X})", vaddr);
return false;
}
template <>
bool Cop0::MapVirtualAddress<u64, true>(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) {
if (ircolib::IsInsideRange(vaddr, 0x0000000000000000, 0x000000FFFFFFFFFF))
if (ircolib::is_inside_range(vaddr, 0x0000000000000000, 0x000000FFFFFFFFFF))
return ProbeTLB(accessType, vaddr, paddr);
tlbError = DISALLOWED_ADDRESS;
@@ -503,19 +503,19 @@ bool Cop0::MapVirtualAddress<u64, true>(const TLBAccessType accessType, const u6
template <>
bool Cop0::MapVirtualAddress<u64, false>(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) {
if (ircolib::IsInsideRange(vaddr, 0x0000000000000000, 0x000000FFFFFFFFFF) || // VREGION_XKUSEG
ircolib::IsInsideRange(vaddr, 0x4000000000000000, 0x400000FFFFFFFFFF) || // VREGION_XKSSEG
ircolib::IsInsideRange(vaddr, 0xC000000000000000, 0xC00000FF7FFFFFFF) || // VREGION_XKSEG
ircolib::IsInsideRange(vaddr, 0xFFFFFFFFE0000000, 0xFFFFFFFFFFFFFFFF)) // VREGION_CKSEG3
if (ircolib::is_inside_range(vaddr, 0x0000000000000000, 0x000000FFFFFFFFFF) || // VREGION_XKUSEG
ircolib::is_inside_range(vaddr, 0x4000000000000000, 0x400000FFFFFFFFFF) || // VREGION_XKSSEG
ircolib::is_inside_range(vaddr, 0xC000000000000000, 0xC00000FF7FFFFFFF) || // VREGION_XKSEG
ircolib::is_inside_range(vaddr, 0xFFFFFFFFE0000000, 0xFFFFFFFFFFFFFFFF)) // VREGION_CKSEG3
return ProbeTLB(accessType, vaddr, paddr);
if (ircolib::IsInsideRange(vaddr, 0x8000000000000000, 0xBFFFFFFFFFFFFFFF)) { // VREGION_XKPHYS
if (ircolib::is_inside_range(vaddr, 0x8000000000000000, 0xBFFFFFFFFFFFFFFF)) { // VREGION_XKPHYS
if (!kernelMode)
panic("Access to XKPHYS address 0x{:016X} when outside kernel mode!", vaddr);
ircolib::panic("Access to XKPHYS address 0x{:016X} when outside kernel mode!", vaddr);
const u8 high_two_bits = (vaddr >> 62) & 0b11;
if (high_two_bits != 0b10)
panic("Access to XKPHYS address 0x{:016X} with high two bits != 0b10!", vaddr);
ircolib::panic("Access to XKPHYS address 0x{:016X} with high two bits != 0b10!", vaddr);
const u8 subsegment = (vaddr >> 59) & 0b11;
bool cached = subsegment != 2; // do something with this eventually
@@ -530,31 +530,31 @@ bool Cop0::MapVirtualAddress<u64, false>(const TLBAccessType accessType, const u
return true;
}
if (ircolib::IsInsideRange(vaddr, 0xFFFFFFFF80000000, 0xFFFFFFFF9FFFFFFF) || // VREGION_CKSEG0
ircolib::IsInsideRange(vaddr, 0xFFFFFFFFA0000000, 0xFFFFFFFFBFFFFFFF)) { // VREGION_CKSEG1
if (ircolib::is_inside_range(vaddr, 0xFFFFFFFF80000000, 0xFFFFFFFF9FFFFFFF) || // VREGION_CKSEG0
ircolib::is_inside_range(vaddr, 0xFFFFFFFFA0000000, 0xFFFFFFFFBFFFFFFF)) { // VREGION_CKSEG1
u32 cut = u32(vaddr) >> 28;
u32 num = cut == 0xA;
// Identical to ksegX in 32 bit mode.
// Unmapped translation. Subtract the base address of the space to get the physical address.
paddr = vaddr - (cut << 28); // Implies cutting off the high 32 bits
trace("CKSEG{}: Translated 0x{:016X} to 0x{:08X}", num, vaddr, paddr);
ircolib::trace("CKSEG{}: Translated 0x{:016X} to 0x{:08X}", num, vaddr, paddr);
return true;
}
if (ircolib::IsInsideRange(vaddr, 0x0000010000000000, 0x3FFFFFFFFFFFFFFF) || // VREGION_XBAD1
ircolib::IsInsideRange(vaddr, 0x4000010000000000, 0x7FFFFFFFFFFFFFFF) || // VREGION_XBAD2
ircolib::IsInsideRange(vaddr, 0xC00000FF80000000, 0xFFFFFFFF7FFFFFFF)) { // VREGION_XBAD3
if (ircolib::is_inside_range(vaddr, 0x0000010000000000, 0x3FFFFFFFFFFFFFFF) || // VREGION_XBAD1
ircolib::is_inside_range(vaddr, 0x4000010000000000, 0x7FFFFFFFFFFFFFFF) || // VREGION_XBAD2
ircolib::is_inside_range(vaddr, 0xC00000FF80000000, 0xFFFFFFFF7FFFFFFF)) { // VREGION_XBAD3
tlbError = DISALLOWED_ADDRESS;
return false;
}
panic("Resolving virtual address 0x{:016X} in 64 bit mode", vaddr);
ircolib::panic("Resolving virtual address 0x{:016X} in 64 bit mode", vaddr);
return false; // just to silence warning
}
bool Cop0::MapVAddr(const TLBAccessType accessType, const u64 vaddr, u32 &paddr) {
if (supervisorMode)
panic("Supervisor mode memory access");
ircolib::panic("Supervisor mode memory access");
if (is64BitAddressing) [[unlikely]] {
if (kernelMode) [[likely]]
@@ -562,7 +562,7 @@ bool Cop0::MapVAddr(const TLBAccessType accessType, const u64 vaddr, u32 &paddr)
if (userMode)
return MapVirtualAddress<u64, true>(accessType, vaddr, paddr);
panic("Unknown mode! This should never happen!");
ircolib::panic("Unknown mode! This should never happen!");
}
if (kernelMode) [[likely]]
@@ -570,6 +570,6 @@ bool Cop0::MapVAddr(const TLBAccessType accessType, const u64 vaddr, u32 &paddr)
if (userMode)
return MapVirtualAddress<u32, true>(accessType, vaddr, paddr);
panic("Unknown mode! This should never happen!");
ircolib::panic("Unknown mode! This should never happen!");
}
} // namespace n64
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once
#include <common.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <unordered_map>
#include <Instruction.hpp>
+269 -269
View File
@@ -1,290 +1,290 @@
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace n64 {
Cop1::Cop1() { Reset(); }
void Cop1::Reset() {
fcr0 = 0xa00;
fcr31.write(0x01000800);
memset(fgr, 0, 32 * sizeof(FloatingPointReg));
fcr0 = 0xa00;
fcr31.write(0x01000800);
memset(fgr, 0, 32 * sizeof(FloatingPointReg));
}
void Cop1::decode(const Instruction instr) {
switch (instr.cop_rs()) {
// 000r_rccc
case 0x00:
mfc1(instr);
break;
case 0x01:
dmfc1(instr);
break;
case 0x02:
cfc1(instr);
break;
case 0x03:
unimplemented();
break;
case 0x04:
mtc1(instr);
break;
case 0x05:
dmtc1(instr);
break;
case 0x06:
ctc1(instr);
break;
case 0x07:
unimplemented();
break;
case 0x10: // s
switch (instr.cop_funct()) {
switch (instr.cop_rs()) {
// 000r_rccc
case 0x00:
adds(instr);
break;
mfc1(instr);
break;
case 0x01:
subs(instr);
break;
dmfc1(instr);
break;
case 0x02:
muls(instr);
break;
cfc1(instr);
break;
case 0x03:
divs(instr);
break;
unimplemented();
break;
case 0x04:
sqrts(instr);
break;
mtc1(instr);
break;
case 0x05:
abss(instr);
break;
dmtc1(instr);
break;
case 0x06:
movs(instr);
break;
ctc1(instr);
break;
case 0x07:
negs(instr);
break;
case 0x08:
roundls(instr);
break;
case 0x09:
truncls(instr);
break;
case 0x0A:
ceills(instr);
break;
case 0x0B:
floorls(instr);
break;
case 0x0C:
roundws(instr);
break;
case 0x0D:
truncws(instr);
break;
case 0x0E:
ceilws(instr);
break;
case 0x0F:
floorws(instr);
break;
case 0x21:
cvtds(instr);
break;
case 0x24:
cvtws(instr);
break;
case 0x25:
cvtls(instr);
break;
case 0x30:
cf<float>(instr);
break;
case 0x31:
cun<float>(instr);
break;
case 0x32:
ceq<float>(instr);
break;
case 0x33:
cueq<float>(instr);
break;
case 0x34:
colt<float>(instr);
break;
case 0x35:
cult<float>(instr);
break;
case 0x36:
cole<float>(instr);
break;
case 0x37:
cule<float>(instr);
break;
case 0x38:
csf<float>(instr);
break;
case 0x39:
cngle<float>(instr);
break;
case 0x3A:
cseq<float>(instr);
break;
case 0x3B:
cngl<float>(instr);
break;
case 0x3C:
clt<float>(instr);
break;
case 0x3D:
cnge<float>(instr);
break;
case 0x3E:
cle<float>(instr);
break;
case 0x3F:
cngt<float>(instr);
break;
unimplemented();
break;
case 0x10: // s
switch (instr.cop_funct()) {
case 0x00:
adds(instr);
break;
case 0x01:
subs(instr);
break;
case 0x02:
muls(instr);
break;
case 0x03:
divs(instr);
break;
case 0x04:
sqrts(instr);
break;
case 0x05:
abss(instr);
break;
case 0x06:
movs(instr);
break;
case 0x07:
negs(instr);
break;
case 0x08:
roundls(instr);
break;
case 0x09:
truncls(instr);
break;
case 0x0A:
ceills(instr);
break;
case 0x0B:
floorls(instr);
break;
case 0x0C:
roundws(instr);
break;
case 0x0D:
truncws(instr);
break;
case 0x0E:
ceilws(instr);
break;
case 0x0F:
floorws(instr);
break;
case 0x21:
cvtds(instr);
break;
case 0x24:
cvtws(instr);
break;
case 0x25:
cvtls(instr);
break;
case 0x30:
cf<float>(instr);
break;
case 0x31:
cun<float>(instr);
break;
case 0x32:
ceq<float>(instr);
break;
case 0x33:
cueq<float>(instr);
break;
case 0x34:
colt<float>(instr);
break;
case 0x35:
cult<float>(instr);
break;
case 0x36:
cole<float>(instr);
break;
case 0x37:
cule<float>(instr);
break;
case 0x38:
csf<float>(instr);
break;
case 0x39:
cngle<float>(instr);
break;
case 0x3A:
cseq<float>(instr);
break;
case 0x3B:
cngl<float>(instr);
break;
case 0x3C:
clt<float>(instr);
break;
case 0x3D:
cnge<float>(instr);
break;
case 0x3E:
cle<float>(instr);
break;
case 0x3F:
cngt<float>(instr);
break;
default:
unimplemented();
}
break;
case 0x11: // d
switch (instr.cop_funct()) {
case 0x00:
addd(instr);
break;
case 0x01:
subd(instr);
break;
case 0x02:
muld(instr);
break;
case 0x03:
divd(instr);
break;
case 0x04:
sqrtd(instr);
break;
case 0x05:
absd(instr);
break;
case 0x06:
movd(instr);
break;
case 0x07:
negd(instr);
break;
case 0x08:
roundld(instr);
break;
case 0x09:
truncld(instr);
break;
case 0x0A:
ceilld(instr);
break;
case 0x0B:
floorld(instr);
break;
case 0x0C:
roundwd(instr);
break;
case 0x0D:
truncwd(instr);
break;
case 0x0E:
ceilwd(instr);
break;
case 0x0F:
floorwd(instr);
break;
case 0x20:
cvtsd(instr);
break;
case 0x24:
cvtwd(instr);
break;
case 0x25:
cvtld(instr);
break;
case 0x30:
cf<double>(instr);
break;
case 0x31:
cun<double>(instr);
break;
case 0x32:
ceq<double>(instr);
break;
case 0x33:
cueq<double>(instr);
break;
case 0x34:
colt<double>(instr);
break;
case 0x35:
cult<double>(instr);
break;
case 0x36:
cole<double>(instr);
break;
case 0x37:
cule<double>(instr);
break;
case 0x38:
csf<double>(instr);
break;
case 0x39:
cngle<double>(instr);
break;
case 0x3A:
cseq<double>(instr);
break;
case 0x3B:
cngl<double>(instr);
break;
case 0x3C:
clt<double>(instr);
break;
case 0x3D:
cnge<double>(instr);
break;
case 0x3E:
cle<double>(instr);
break;
case 0x3F:
cngt<double>(instr);
break;
default:
unimplemented();
}
break;
case 0x14: // w
switch (instr.cop_funct()) {
case 0x20:
cvtsw(instr);
break;
case 0x21:
cvtdw(instr);
break;
default:
unimplemented();
}
break;
case 0x15: // l
switch (instr.cop_funct()) {
case 0x20:
cvtsl(instr);
break;
case 0x21:
cvtdl(instr);
break;
default:
unimplemented();
}
break;
default:
unimplemented();
ircolib::panic("Unimplemented COP1 instruction {}", instr.cop_rs());
}
break;
case 0x11: // d
switch (instr.cop_funct()) {
case 0x00:
addd(instr);
break;
case 0x01:
subd(instr);
break;
case 0x02:
muld(instr);
break;
case 0x03:
divd(instr);
break;
case 0x04:
sqrtd(instr);
break;
case 0x05:
absd(instr);
break;
case 0x06:
movd(instr);
break;
case 0x07:
negd(instr);
break;
case 0x08:
roundld(instr);
break;
case 0x09:
truncld(instr);
break;
case 0x0A:
ceilld(instr);
break;
case 0x0B:
floorld(instr);
break;
case 0x0C:
roundwd(instr);
break;
case 0x0D:
truncwd(instr);
break;
case 0x0E:
ceilwd(instr);
break;
case 0x0F:
floorwd(instr);
break;
case 0x20:
cvtsd(instr);
break;
case 0x24:
cvtwd(instr);
break;
case 0x25:
cvtld(instr);
break;
case 0x30:
cf<double>(instr);
break;
case 0x31:
cun<double>(instr);
break;
case 0x32:
ceq<double>(instr);
break;
case 0x33:
cueq<double>(instr);
break;
case 0x34:
colt<double>(instr);
break;
case 0x35:
cult<double>(instr);
break;
case 0x36:
cole<double>(instr);
break;
case 0x37:
cule<double>(instr);
break;
case 0x38:
csf<double>(instr);
break;
case 0x39:
cngle<double>(instr);
break;
case 0x3A:
cseq<double>(instr);
break;
case 0x3B:
cngl<double>(instr);
break;
case 0x3C:
clt<double>(instr);
break;
case 0x3D:
cnge<double>(instr);
break;
case 0x3E:
cle<double>(instr);
break;
case 0x3F:
cngt<double>(instr);
break;
default:
unimplemented();
}
break;
case 0x14: // w
switch (instr.cop_funct()) {
case 0x20:
cvtsw(instr);
break;
case 0x21:
cvtdw(instr);
break;
default:
unimplemented();
}
break;
case 0x15: // l
switch (instr.cop_funct()) {
case 0x20:
cvtsl(instr);
break;
case 0x21:
cvtdl(instr);
break;
default:
unimplemented();
}
break;
default:
panic("Unimplemented COP1 instruction {}", instr.cop_rs());
}
}
} // namespace n64
+425 -425
View File
@@ -1,456 +1,456 @@
#include <Core.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
namespace n64 {
void RSP::special(const Instruction instr) {
MI& mi = Core::GetMem().mmio.mi;
switch (instr.cop_funct()) {
case 0x00:
if (instr != 0) {
sll(instr);
MI &mi = Core::GetMem().mmio.mi;
switch (instr.cop_funct()) {
case 0x00:
if (instr != 0) {
sll(instr);
}
break;
case 0x02:
srl(instr);
break;
case 0x03:
sra(instr);
break;
case 0x04:
sllv(instr);
break;
case 0x06:
srlv(instr);
break;
case 0x07:
srav(instr);
break;
case 0x08:
jr(instr);
break;
case 0x09:
jalr(instr);
break;
case 0x0D:
spStatus.halt = true;
steps = 0;
spStatus.broke = true;
if (spStatus.interruptOnBreak) {
mi.InterruptRaise(MI::Interrupt::SP);
}
break;
case 0x20:
case 0x21:
add(instr);
break;
case 0x22:
case 0x23:
sub(instr);
break;
case 0x24:
and_(instr);
break;
case 0x25:
or_(instr);
break;
case 0x26:
xor_(instr);
break;
case 0x27:
nor(instr);
break;
case 0x2A:
slt(instr);
break;
case 0x2B:
sltu(instr);
break;
default:
ircolib::panic("Unhandled RSP special instruction ({:06b})", instr.cop_funct());
}
break;
case 0x02:
srl(instr);
break;
case 0x03:
sra(instr);
break;
case 0x04:
sllv(instr);
break;
case 0x06:
srlv(instr);
break;
case 0x07:
srav(instr);
break;
case 0x08:
jr(instr);
break;
case 0x09:
jalr(instr);
break;
case 0x0D:
spStatus.halt = true;
steps = 0;
spStatus.broke = true;
if (spStatus.interruptOnBreak) {
mi.InterruptRaise(MI::Interrupt::SP);
}
break;
case 0x20:
case 0x21:
add(instr);
break;
case 0x22:
case 0x23:
sub(instr);
break;
case 0x24:
and_(instr);
break;
case 0x25:
or_(instr);
break;
case 0x26:
xor_(instr);
break;
case 0x27:
nor(instr);
break;
case 0x2A:
slt(instr);
break;
case 0x2B:
sltu(instr);
break;
default:
panic("Unhandled RSP special instruction ({:06b})", instr.cop_funct());
}
}
void RSP::regimm(const Instruction instr) {
switch (instr.cop_rt()) {
case 0x00:
b(instr, gpr[instr.rs()] < 0);
break;
case 0x01:
b(instr, gpr[instr.rs()] >= 0);
break;
case 0x10:
blink(instr, gpr[instr.rs()] < 0);
break;
case 0x11:
blink(instr, gpr[instr.rs()] >= 0);
break;
default:
panic("Unhandled RSP regimm instruction ({:05b})", instr.cop_rt());
}
switch (instr.cop_rt()) {
case 0x00:
b(instr, gpr[instr.rs()] < 0);
break;
case 0x01:
b(instr, gpr[instr.rs()] >= 0);
break;
case 0x10:
blink(instr, gpr[instr.rs()] < 0);
break;
case 0x11:
blink(instr, gpr[instr.rs()] >= 0);
break;
default:
ircolib::panic("Unhandled RSP regimm instruction ({:05b})", instr.cop_rt());
}
}
void RSP::lwc2(const Instruction instr) {
switch (instr.rd()) {
case 0x00:
lbv(instr);
break;
case 0x01:
lsv(instr);
break;
case 0x02:
llv(instr);
break;
case 0x03:
ldv(instr);
break;
case 0x04:
lqv(instr);
break;
case 0x05:
lrv(instr);
break;
case 0x06:
lpv(instr);
break;
case 0x07:
luv(instr);
break;
case 0x08:
lhv(instr);
break;
case 0x09:
lfv(instr);
break;
case 0x0A:
break;
case 0x0B:
ltv(instr);
break;
default:
panic("Unhandled RSP LWC2 {:05b}", instr.rd());
}
switch (instr.rd()) {
case 0x00:
lbv(instr);
break;
case 0x01:
lsv(instr);
break;
case 0x02:
llv(instr);
break;
case 0x03:
ldv(instr);
break;
case 0x04:
lqv(instr);
break;
case 0x05:
lrv(instr);
break;
case 0x06:
lpv(instr);
break;
case 0x07:
luv(instr);
break;
case 0x08:
lhv(instr);
break;
case 0x09:
lfv(instr);
break;
case 0x0A:
break;
case 0x0B:
ltv(instr);
break;
default:
ircolib::panic("Unhandled RSP LWC2 {:05b}", instr.rd());
}
}
void RSP::swc2(const Instruction instr) {
switch (instr.rd()) {
case 0x00:
sbv(instr);
break;
case 0x01:
ssv(instr);
break;
case 0x02:
slv(instr);
break;
case 0x03:
sdv(instr);
break;
case 0x04:
sqv(instr);
break;
case 0x05:
srv(instr);
break;
case 0x06:
spv(instr);
break;
case 0x07:
suv(instr);
break;
case 0x08:
shv(instr);
break;
case 0x09:
sfv(instr);
break;
case 0x0A:
swv(instr);
break;
case 0x0B:
stv(instr);
break;
default:
panic("Unhandled RSP SWC2 {:05b}", instr.rd());
}
switch (instr.rd()) {
case 0x00:
sbv(instr);
break;
case 0x01:
ssv(instr);
break;
case 0x02:
slv(instr);
break;
case 0x03:
sdv(instr);
break;
case 0x04:
sqv(instr);
break;
case 0x05:
srv(instr);
break;
case 0x06:
spv(instr);
break;
case 0x07:
suv(instr);
break;
case 0x08:
shv(instr);
break;
case 0x09:
sfv(instr);
break;
case 0x0A:
swv(instr);
break;
case 0x0B:
stv(instr);
break;
default:
ircolib::panic("Unhandled RSP SWC2 {:05b}", instr.rd());
}
}
void RSP::cop2(const Instruction instr) {
switch (instr.cop_funct()) {
case 0x00:
if (instr >> 25 & 1) {
vmulf(instr);
} else {
switch (instr.cop_rs()) {
case 0x00:
mfc2(instr);
switch (instr.cop_funct()) {
case 0x00:
if (instr >> 25 & 1) {
vmulf(instr);
} else {
switch (instr.cop_rs()) {
case 0x00:
mfc2(instr);
break;
case 0x02:
cfc2(instr);
break;
case 0x04:
mtc2(instr);
break;
case 0x06:
ctc2(instr);
break;
default:
ircolib::panic("Unhandled RSP COP2 sub ({:05b})", instr.cop_rs());
}
}
break;
case 0x02:
cfc2(instr);
case 0x01:
vmulu(instr);
break;
case 0x04:
mtc2(instr);
case 0x02:
vrndp(instr);
break;
case 0x06:
ctc2(instr);
case 0x03:
vmulq(instr);
break;
default:
panic("Unhandled RSP COP2 sub ({:05b})", instr.cop_rs());
}
case 0x04:
vmudl(instr);
break;
case 0x05:
vmudm(instr);
break;
case 0x06:
vmudn(instr);
break;
case 0x07:
vmudh(instr);
break;
case 0x08:
vmacf(instr);
break;
case 0x09:
vmacu(instr);
break;
case 0x0A:
vrndn(instr);
break;
case 0x0B:
vmacq(instr);
break;
case 0x0C:
vmadl(instr);
break;
case 0x0D:
vmadm(instr);
break;
case 0x0E:
vmadn(instr);
break;
case 0x0F:
vmadh(instr);
break;
case 0x10:
vadd(instr);
break;
case 0x11:
vsub(instr);
break;
case 0x12:
vzero(instr);
break;
case 0x13:
vabs(instr);
break;
case 0x14:
vaddc(instr);
break;
case 0x15:
vsubc(instr);
break;
case 0x16 ... 0x1C:
case 0x1E:
case 0x1F:
case 0x2E:
case 0x2F:
vzero(instr);
break;
case 0x1D:
vsar(instr);
break;
case 0x20:
vlt(instr);
break;
case 0x21:
veq(instr);
break;
case 0x22:
vne(instr);
break;
case 0x23:
vge(instr);
break;
case 0x24:
vcl(instr);
break;
case 0x25:
vch(instr);
break;
case 0x26:
vcr(instr);
break;
case 0x27:
vmrg(instr);
break;
case 0x28:
vand(instr);
break;
case 0x29:
vnand(instr);
break;
case 0x2A:
vor(instr);
break;
case 0x2B:
vnor(instr);
break;
case 0x2C:
vxor(instr);
break;
case 0x2D:
vnxor(instr);
break;
case 0x31:
vrcpl(instr);
break;
case 0x35:
vrsql(instr);
break;
case 0x32:
case 0x36:
vrcph(instr);
break;
case 0x30:
vrcp(instr);
break;
case 0x33:
vmov(instr);
break;
case 0x34:
vrsq(instr);
break;
case 0x38 ... 0x3E:
vzero(instr);
break;
case 0x37:
case 0x3F:
break;
default:
ircolib::panic("Unhandled RSP COP2 ({:06b})", instr.cop_funct());
}
break;
case 0x01:
vmulu(instr);
break;
case 0x02:
vrndp(instr);
break;
case 0x03:
vmulq(instr);
break;
case 0x04:
vmudl(instr);
break;
case 0x05:
vmudm(instr);
break;
case 0x06:
vmudn(instr);
break;
case 0x07:
vmudh(instr);
break;
case 0x08:
vmacf(instr);
break;
case 0x09:
vmacu(instr);
break;
case 0x0A:
vrndn(instr);
break;
case 0x0B:
vmacq(instr);
break;
case 0x0C:
vmadl(instr);
break;
case 0x0D:
vmadm(instr);
break;
case 0x0E:
vmadn(instr);
break;
case 0x0F:
vmadh(instr);
break;
case 0x10:
vadd(instr);
break;
case 0x11:
vsub(instr);
break;
case 0x12:
vzero(instr);
break;
case 0x13:
vabs(instr);
break;
case 0x14:
vaddc(instr);
break;
case 0x15:
vsubc(instr);
break;
case 0x16 ... 0x1C:
case 0x1E:
case 0x1F:
case 0x2E:
case 0x2F:
vzero(instr);
break;
case 0x1D:
vsar(instr);
break;
case 0x20:
vlt(instr);
break;
case 0x21:
veq(instr);
break;
case 0x22:
vne(instr);
break;
case 0x23:
vge(instr);
break;
case 0x24:
vcl(instr);
break;
case 0x25:
vch(instr);
break;
case 0x26:
vcr(instr);
break;
case 0x27:
vmrg(instr);
break;
case 0x28:
vand(instr);
break;
case 0x29:
vnand(instr);
break;
case 0x2A:
vor(instr);
break;
case 0x2B:
vnor(instr);
break;
case 0x2C:
vxor(instr);
break;
case 0x2D:
vnxor(instr);
break;
case 0x31:
vrcpl(instr);
break;
case 0x35:
vrsql(instr);
break;
case 0x32:
case 0x36:
vrcph(instr);
break;
case 0x30:
vrcp(instr);
break;
case 0x33:
vmov(instr);
break;
case 0x34:
vrsq(instr);
break;
case 0x38 ... 0x3E:
vzero(instr);
break;
case 0x37:
case 0x3F:
break;
default:
panic("Unhandled RSP COP2 ({:06b})", instr.cop_funct());
}
}
void RSP::cop0(const Instruction instr) {
if ((instr & 0x7FF) == 0) {
switch (instr.cop_rs()) {
case 0x00:
mfc0(Core::GetMem().mmio.rdp, instr);
break;
case 0x04:
mtc0(instr);
break;
default:
panic("Unhandled RSP COP0 ({:05b})", instr.cop_rs());
if ((instr & 0x7FF) == 0) {
switch (instr.cop_rs()) {
case 0x00:
mfc0(Core::GetMem().mmio.rdp, instr);
break;
case 0x04:
mtc0(instr);
break;
default:
ircolib::panic("Unhandled RSP COP0 ({:05b})", instr.cop_rs());
}
} else {
ircolib::panic("RSP COP0 unknown {:08X}", u32(instr));
}
} else {
panic("RSP COP0 unknown {:08X}", u32(instr));
}
}
void RSP::Exec(const Instruction instr) {
Mem& mem = Core::GetMem();
MMIO &mmio = mem.mmio;
MI &mi = mmio.mi;
switch (instr.opcode()) {
case 0x00:
special(instr);
break;
case 0x01:
regimm(instr);
break;
case 0x02:
j(instr);
break;
case 0x03:
jal(instr);
break;
case 0x04:
b(instr, gpr[instr.rt()] == gpr[instr.rs()]);
break;
case 0x05:
b(instr, gpr[instr.rt()] != gpr[instr.rs()]);
break;
case 0x06:
b(instr, gpr[instr.rs()] <= 0);
break;
case 0x07:
b(instr, gpr[instr.rs()] > 0);
break;
case 0x08:
case 0x09:
addi(instr);
break;
case 0x0A:
slti(instr);
break;
case 0x0B:
sltiu(instr);
break;
case 0x0C:
andi(instr);
break;
case 0x0D:
ori(instr);
break;
case 0x0E:
xori(instr);
break;
case 0x0F:
lui(instr);
break;
case 0x10:
cop0(instr);
break;
case 0x12:
cop2(instr);
break;
case 0x20:
lb(instr);
break;
case 0x21:
lh(instr);
break;
case 0x23:
case 0x27:
lw(instr);
break;
case 0x24:
lbu(instr);
break;
case 0x25:
lhu(instr);
break;
case 0x28:
sb(instr);
break;
case 0x29:
sh(instr);
break;
case 0x2B:
sw(instr);
break;
case 0x32:
lwc2(instr);
break;
case 0x3A:
swc2(instr);
break;
default:
mem.DumpIMEM();
panic("Unhandled RSP instruction ({:06b}, {:04X})", instr.opcode(), oldPC);
}
Mem &mem = Core::GetMem();
MMIO &mmio = mem.mmio;
MI &mi = mmio.mi;
switch (instr.opcode()) {
case 0x00:
special(instr);
break;
case 0x01:
regimm(instr);
break;
case 0x02:
j(instr);
break;
case 0x03:
jal(instr);
break;
case 0x04:
b(instr, gpr[instr.rt()] == gpr[instr.rs()]);
break;
case 0x05:
b(instr, gpr[instr.rt()] != gpr[instr.rs()]);
break;
case 0x06:
b(instr, gpr[instr.rs()] <= 0);
break;
case 0x07:
b(instr, gpr[instr.rs()] > 0);
break;
case 0x08:
case 0x09:
addi(instr);
break;
case 0x0A:
slti(instr);
break;
case 0x0B:
sltiu(instr);
break;
case 0x0C:
andi(instr);
break;
case 0x0D:
ori(instr);
break;
case 0x0E:
xori(instr);
break;
case 0x0F:
lui(instr);
break;
case 0x10:
cop0(instr);
break;
case 0x12:
cop2(instr);
break;
case 0x20:
lb(instr);
break;
case 0x21:
lh(instr);
break;
case 0x23:
case 0x27:
lw(instr);
break;
case 0x24:
lbu(instr);
break;
case 0x25:
lhu(instr);
break;
case 0x28:
sb(instr);
break;
case 0x29:
sh(instr);
break;
case 0x2B:
sw(instr);
break;
case 0x32:
lwc2(instr);
break;
case 0x3A:
swc2(instr);
break;
default:
mem.DumpIMEM();
ircolib::panic("Unhandled RSP instruction ({:06b}, {:04X})", instr.opcode(), oldPC);
}
}
} // namespace n64
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -14,9 +14,9 @@ void EmuThread::run() {
const auto index = e.gdevice.which;
gamepad = SDL_OpenGamepad(index);
warn("Found controller!");
warn("Name: {}", SDL_GetGamepadName(gamepad));
warn("Vendor: {}", SDL_GetGamepadVendor(gamepad));
ircolib::warn("Found controller!");
ircolib::warn("Name: {}", SDL_GetGamepadName(gamepad));
ircolib::warn("Vendor: {}", SDL_GetGamepadVendor(gamepad));
}
}
+1 -19
View File
@@ -36,26 +36,8 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
connect(romsListTable, &RomsListTable::cleared, this, [&] { centralWidget->setCurrentWidget(romPathNotSet); });
connect(romsListTable, &RomsListTable::populateFinished, this, [&] {
for (int i = 0; i < romsListTable->size(); i++) {
const auto &[countryCode, version, _, name, regions, lastPlayed, timePlayed] = (*romsListTable)[i];
romsListTable->insertRow(i);
romsListTable->setItem(
i, 0,
new QTableWidgetItem(
std::format("{} ({}) (Rev {})", name, n64::GameDB::regionCodeToReadable(countryCode), version)
.c_str()));
romsListTable->setItem(i, 1, new QTableWidgetItem(regions.c_str()));
romsListTable->setItem(i, 2, new QTableWidgetItem(lastPlayed.c_str()));
romsListTable->setItem(i, 3, new QTableWidgetItem(timePlayed.c_str()));
}
romsListTable->resizeRowsToContents();
centralWidget->setCurrentWidget(romsListTable);
});
connect(romsListTable, &QTableWidget::cellDoubleClicked, this,
[&](int row, int) { LoadROM((*romsListTable)[row].path); });
[&](int row, int) { LoadROM(romsListTable->GetPathForClickedCell(row)); });
installEventFilter(this);
+2 -2
View File
@@ -16,7 +16,7 @@ static CompositorCategory GetOSCompositorCategory() {
if (platform_name == QStringLiteral("cocoa") || platform_name == QStringLiteral("ios"))
return CompositorCategory::MacOS;
warn("Unknown Qt platform!");
ircolib::warn("Unknown Qt platform!");
return CompositorCategory::Windows;
}
@@ -34,7 +34,7 @@ RenderWidget::RenderWidget() {
}
if (!Vulkan::Context::init_loader(nullptr)) {
panic("Could not initialize Vulkan ICD");
ircolib::panic("Could not initialize Vulkan ICD");
}
qtVkInstanceFactory = std::make_unique<QtInstanceFactory>();
+18 -16
View File
@@ -13,38 +13,31 @@ RomsListTable::RomsListTable(GeneralSettings *general) {
setSelectionBehavior(QAbstractItemView::SelectRows);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSortingEnabled(true);
setColumnCount(4);
setColumnCount(5);
setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
setHorizontalHeaderItem(1, new QTableWidgetItem("Regions"));
setHorizontalHeaderItem(2, new QTableWidgetItem("Last played"));
setHorizontalHeaderItem(3, new QTableWidgetItem("Time played"));
setHorizontalHeaderItem(4, new QTableWidgetItem("__path__"));
hideColumn(4);
connect(general, &GeneralSettings::romFolderSelected, this, [&] {
std::thread popThread([&] {
populate(Options::GetRomsPath());
emit populateFinished();
});
std::thread popThread([&] { populate(Options::GetRomsPath()); });
popThread.detach();
});
connect(general, &GeneralSettings::romFolderCleared, this, [&] {
for (int i = 0; i < rowCount(); i++)
removeRow(i);
romsList = {};
clearContents();
emit cleared();
});
std::thread popThread([&] {
populate(Options::GetRomsPath());
emit populateFinished();
});
std::thread popThread([&] { populate(Options::GetRomsPath()); });
popThread.detach();
}
void RomsListTable::populate(const std::string &romsPath) {
if (!romsPath.empty()) {
int i = 0;
for (const auto &file : fs::recursive_directory_iterator{romsPath}) {
if (!file.is_regular_file())
continue;
@@ -67,8 +60,17 @@ void RomsListTable::populate(const std::string &romsPath) {
if (rom.gameNameDB.empty())
rom.gameNameDB = fs::path(filename).stem().string();
romsList.push_back(
{rom.header.countryCode, rom.header.version, filename, rom.gameNameDB, regions, "Never", "0h 00m 00s"});
insertRow(i);
setItem(i, 0,
new QTableWidgetItem(std::format("{} ({}) (Rev {})", rom.gameNameDB,
n64::GameDB::regionCodeToReadable(rom.header.countryCode),
rom.header.version)
.c_str()));
setItem(i, 1, new QTableWidgetItem(regions.c_str()));
setItem(i, 2, new QTableWidgetItem("Never"));
setItem(i, 3, new QTableWidgetItem("0h 0m 0s"));
setItem(i, 4, new QTableWidgetItem(filename.c_str()));
i++;
}
}
}
+2 -4
View File
@@ -19,14 +19,12 @@ class RomsListTable : public QTableWidget {
void populate(const std::string &);
public:
std::vector<RomsListEntry> romsList;
RomsListTable(GeneralSettings *);
size_t size() { return romsList.size(); }
size_t size() { return rowCount(); }
RomsListEntry &operator[](const size_t i) { return romsList[i]; }
std::string GetPathForClickedCell(int i) const { return item(i, 4)->text().toStdString(); }
signals:
void populateFinished();
void cleared();
};
+1 -1
View File
@@ -1,6 +1,6 @@
#include <CPUSettings.hpp>
#include <Options.hpp>
#include <log.hpp>
#include <ircolib/log.hpp>
CPUSettings::CPUSettings() : settings(QSettings::UserScope) {
types = new QComboBox();
+1 -1
View File
@@ -2,7 +2,7 @@
#include <Options.hpp>
#include <QFileDialog>
#include <QCoreApplication>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <QPushButton>
GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) {
-6
View File
@@ -1,11 +1,5 @@
#pragma once
#include <ircolib/types.hpp>
#ifdef USE_NEON
#include <sse2neon.h>
#else
#include <emmintrin.h>
#include <smmintrin.h>
#endif
using u8 = ircolib::u8;
using u16 = ircolib::u16;
+37 -36
View File
@@ -4,55 +4,56 @@
namespace Util {
std::vector<u8> OpenROM(const std::string &filename, size_t &sizeAdjusted) {
auto buf = ircolib::ReadFileBinary(filename);
sizeAdjusted = ircolib::NextPow2(buf.size());
return buf;
auto buf = ircolib::read_file_binary(filename);
sizeAdjusted = ircolib::next_pow2(buf.size());
return buf;
}
std::vector<u8> OpenArchive(const std::string &path, size_t &sizeAdjusted) {
const auto stream = ar_open_file(fs::path(path).string().c_str());
const auto stream = ar_open_file(fs::path(path).string().c_str());
if (!stream) {
panic("Could not open archive! Are you sure it's an archive?");
}
if (!stream) {
ircolib::panic("Could not open archive! Are you sure it's an archive?");
}
ar_archive *archive = ar_open_zip_archive(stream, false);
ar_archive *archive = ar_open_zip_archive(stream, false);
if (!archive)
archive = ar_open_rar_archive(stream);
if (!archive)
archive = ar_open_7z_archive(stream);
if (!archive)
archive = ar_open_tar_archive(stream);
if (!archive)
archive = ar_open_rar_archive(stream);
if (!archive)
archive = ar_open_7z_archive(stream);
if (!archive)
archive = ar_open_tar_archive(stream);
if (!archive) {
ar_close(stream);
panic("Could not open archive! Are you sure it's a supported archive? (7z, zip, rar and tar are supported)");
}
if (!archive) {
ar_close(stream);
ircolib::panic(
"Could not open archive! Are you sure it's a supported archive? (7z, zip, rar and tar are supported)");
}
std::vector<u8> buf{};
std::vector<u8> buf{};
std::vector<std::string> rom_exts{".n64", ".z64", ".v64", ".N64", ".Z64", ".V64"};
std::vector<std::string> rom_exts{".n64", ".z64", ".v64", ".N64", ".Z64", ".V64"};
while (ar_parse_entry(archive)) {
auto filename = ar_entry_get_name(archive);
auto extension = fs::path(filename).extension();
while (ar_parse_entry(archive)) {
auto filename = ar_entry_get_name(archive);
auto extension = fs::path(filename).extension();
if (std::ranges::any_of(rom_exts, [&](const auto &x) { return extension == x; })) {
const auto size = ar_entry_get_size(archive);
sizeAdjusted = ircolib::NextPow2(size);
buf.resize(sizeAdjusted);
ar_entry_uncompress(archive, buf.data(), size);
break;
if (std::ranges::any_of(rom_exts, [&](const auto &x) { return extension == x; })) {
const auto size = ar_entry_get_size(archive);
sizeAdjusted = ircolib::next_pow2(size);
buf.resize(sizeAdjusted);
ar_entry_uncompress(archive, buf.data(), size);
break;
}
ar_close_archive(archive);
ar_close(stream);
ircolib::panic("Could not find any rom image in the archive!");
}
ar_close_archive(archive);
ar_close(stream);
panic("Could not find any rom image in the archive!");
}
ar_close_archive(archive);
ar_close(stream);
return buf;
}
return buf;
}
} // namespace Util
+2 -1
View File
@@ -1,9 +1,10 @@
#pragma once
#include <fstream>
#include <log.hpp>
#include <ircolib/log.hpp>
#include <vector>
#include <filesystem>
#include <ircolib/file.hpp>
#include <types.hpp>
namespace fs = std::filesystem;
-67
View File
@@ -1,67 +0,0 @@
#pragma once
#include <common.hpp>
#include <print>
#include <string>
#if !defined(NDEBUG) && !defined(_WIN32)
#include <dlfcn.h>
#endif
namespace Util {
enum LogLevel : u8 { Trace, Debug, Info, Warn, Error, Always };
#ifndef NDEBUG
static constexpr auto globalLogLevel = Debug;
#else
static constexpr auto globalLogLevel = Warn;
#endif
template <LogLevel messageType = Info, class... Args>
void print(const std::format_string<Args...> fmt, Args... args) {
if (messageType >= globalLogLevel) {
if (messageType <= Debug) {
#ifndef NDEBUG
std::println(fmt, std::forward<Args>(args)...);
#endif
} else {
std::println(fmt, std::forward<Args>(args)...);
}
}
}
#define panic(fmt, ...) \
do { \
Util::print<Util::Error>("[FATAL] " fmt __VA_OPT__(, ) __VA_ARGS__); \
exit(-1); \
} \
while (0)
#define error(fmt, ...) \
do { \
Util::print<Util::Error>("[ERROR] " fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
while (0)
#define warn(fmt, ...) \
do { \
Util::print<Util::Warn>("[WARN] " fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
while (0)
#define info(fmt, ...) \
do { \
Util::print<Util::Info>("[INFO] " fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
while (0)
#define debug(fmt, ...) \
do { \
Util::print<Util::Debug>("[DEBUG] " fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
while (0)
#define trace(fmt, ...) \
do { \
Util::print<Util::Trace>("[TRACE] " fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
while (0)
#define always(fmt, ...) \
do { \
Util::print<Util::Always>(fmt __VA_OPT__(, ) __VA_ARGS__); \
} \
while (0)
} // namespace Util