mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-25 05:55:01 +00:00
Merge pull request #46 from Wunkolo/io-file-cpp
Migrate `IOFile` implementation to `io_file.cpp`
This commit is contained in:
commit
fc7e0b2b03
6 changed files with 176 additions and 166 deletions
|
@ -69,7 +69,7 @@ else()
|
||||||
message(FATAL_ERROR "Currently unsupported CPU architecture")
|
message(FATAL_ERROR "Currently unsupported CPU architecture")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SOURCE_FILES src/main.cpp src/emulator.cpp src/core/CPU/cpu_dynarmic.cpp src/core/CPU/dynarmic_cycles.cpp
|
set(SOURCE_FILES src/main.cpp src/emulator.cpp src/io_file.cpp src/core/CPU/cpu_dynarmic.cpp src/core/CPU/dynarmic_cycles.cpp
|
||||||
src/core/memory.cpp
|
src/core/memory.cpp
|
||||||
)
|
)
|
||||||
set(CRYPTO_SOURCE_FILES src/core/crypto/aes_engine.cpp)
|
set(CRYPTO_SOURCE_FILES src/core/crypto/aes_engine.cpp)
|
||||||
|
|
|
@ -44,48 +44,7 @@ class Emulator {
|
||||||
NCSD loadedNCSD;
|
NCSD loadedNCSD;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Emulator() : kernel(cpu, memory, gpu), cpu(memory, kernel), gpu(memory), memory(cpu.getTicksRef()) {
|
Emulator();
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
|
|
||||||
Helpers::panic("Failed to initialize SDL2");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make SDL use consistent positional button mapping
|
|
||||||
SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0");
|
|
||||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) {
|
|
||||||
Helpers::warn("Failed to initialize SDL2 GameController: %s", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request OpenGL 4.1 Core (Max available on MacOS)
|
|
||||||
// MacOS gets mad if we don't explicitly demand a core profile
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
|
||||||
window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
|
|
||||||
|
|
||||||
if (window == nullptr) {
|
|
||||||
Helpers::panic("Window creation failed: %s", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
glContext = SDL_GL_CreateContext(window);
|
|
||||||
if (glContext == nullptr) {
|
|
||||||
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gladLoadGL(reinterpret_cast<GLADloadfunc>(SDL_GL_GetProcAddress))) {
|
|
||||||
Helpers::panic("OpenGL init failed: %s", SDL_GetError());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER)) {
|
|
||||||
gameController = SDL_GameControllerOpen(0);
|
|
||||||
|
|
||||||
if (gameController != nullptr) {
|
|
||||||
SDL_Joystick* stick = SDL_GameControllerGetJoystick(gameController);
|
|
||||||
gameControllerID = SDL_JoystickInstanceID(stick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void step();
|
void step();
|
||||||
void render();
|
void render();
|
||||||
|
|
|
@ -1,136 +1,36 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
// 64 bit offsets for MSVC
|
|
||||||
#define fseeko _fseeki64
|
|
||||||
#define ftello _ftelli64
|
|
||||||
#define fileno _fileno
|
|
||||||
|
|
||||||
#pragma warning(disable : 4996)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <io.h> // For _chsize_s
|
|
||||||
#else
|
|
||||||
#include <unistd.h> // For ftruncate
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class IOFile {
|
class IOFile {
|
||||||
FILE* handle = nullptr;
|
FILE* handle = nullptr;
|
||||||
static inline std::filesystem::path appData = ""; // Directory for holding app data. AppData on Windows
|
static inline std::filesystem::path appData = ""; // Directory for holding app data. AppData on Windows
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IOFile() {}
|
IOFile() {}
|
||||||
IOFile(FILE* handle) : handle(handle) {}
|
IOFile(FILE* handle) : handle(handle) {}
|
||||||
IOFile(const std::filesystem::path& path, const char* permissions = "rb") {
|
IOFile(const std::filesystem::path& path, const char* permissions = "rb");
|
||||||
open(path, permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isOpen() {
|
bool isOpen() { return handle != nullptr; }
|
||||||
return handle != nullptr;
|
bool open(const std::filesystem::path& path, const char* permissions = "rb");
|
||||||
}
|
bool open(const char* filename, const char* permissions = "rb");
|
||||||
|
void close();
|
||||||
|
|
||||||
bool open(const std::filesystem::path& path, const char* permissions = "rb") {
|
std::pair<bool, std::size_t> read(void* data, std::size_t length, std::size_t dataSize);
|
||||||
const auto str = path.string(); // For some reason converting paths directly with c_str() doesn't work
|
std::pair<bool, std::size_t> readBytes(void* data, std::size_t count);
|
||||||
return open(str.c_str(), permissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool open(const char* filename, const char* permissions = "rb") {
|
std::pair<bool, std::size_t> write(const void* data, std::size_t length, std::size_t dataSize);
|
||||||
handle = std::fopen(filename, permissions);
|
std::pair<bool, std::size_t> writeBytes(const void* data, std::size_t count);
|
||||||
return isOpen();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close() {
|
std::optional<std::uint64_t> size();
|
||||||
if (isOpen()) {
|
|
||||||
fclose(handle);
|
|
||||||
handle = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<bool, std::size_t> read(void* data, std::size_t length, std::size_t dataSize) {
|
bool seek(std::int64_t offset, int origin = SEEK_SET);
|
||||||
if (!isOpen()) {
|
bool rewind();
|
||||||
return { false, std::numeric_limits<std::size_t>::max() };
|
FILE* getHandle();
|
||||||
}
|
static void setAppDataDir(const std::filesystem::path& dir);
|
||||||
|
static std::filesystem::path getAppData() { return appData; }
|
||||||
if (length == 0) return { true, 0 };
|
|
||||||
return { true, std::fread(data, dataSize, length, handle) };
|
|
||||||
}
|
|
||||||
|
|
||||||
auto readBytes(void* data, std::size_t count) {
|
|
||||||
return read(data, count, sizeof(std::uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<bool, std::size_t> write(const void* data, std::size_t length, std::size_t dataSize) {
|
|
||||||
if (!isOpen()) {
|
|
||||||
return { false, std::numeric_limits<std::size_t>::max() };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length == 0) return { true, 0 };
|
|
||||||
return { true, std::fwrite(data, dataSize, length, handle) };
|
|
||||||
}
|
|
||||||
|
|
||||||
auto writeBytes(const void* data, std::size_t count) {
|
|
||||||
return write(data, count, sizeof(std::uint8_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::uint64_t> size() {
|
|
||||||
if (!isOpen()) return {};
|
|
||||||
|
|
||||||
std::uint64_t pos = ftello(handle);
|
|
||||||
if (fseeko(handle, 0, SEEK_END) != 0) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint64_t size = ftello(handle);
|
|
||||||
if ((size != pos) && (fseeko(handle, pos, SEEK_SET) != 0)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool seek(std::int64_t offset, int origin = SEEK_SET) {
|
|
||||||
if (!isOpen() || fseeko(handle, offset, origin) != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool rewind() {
|
|
||||||
return seek(0, SEEK_SET);
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* getHandle() {
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setAppDataDir(const std::filesystem::path& dir) {
|
|
||||||
if (dir == "") Helpers::panic("Failed to set app data directory");
|
|
||||||
appData = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the size of the file to "size" and returns whether it succeeded or not
|
// Sets the size of the file to "size" and returns whether it succeeded or not
|
||||||
bool setSize(std::uint64_t size) {
|
bool setSize(std::uint64_t size);
|
||||||
if (!isOpen()) return false;
|
|
||||||
bool success;
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
success = _chsize_s(_fileno(handle), size) == 0;
|
|
||||||
#else
|
|
||||||
success = ftruncate(fileno(handle), size) == 0;
|
|
||||||
#endif
|
|
||||||
fflush(handle);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::filesystem::path getAppData() { return IOFile::appData; }
|
|
||||||
};
|
};
|
|
@ -1,5 +1,48 @@
|
||||||
#include "emulator.hpp"
|
#include "emulator.hpp"
|
||||||
|
|
||||||
|
Emulator::Emulator() : kernel(cpu, memory, gpu), cpu(memory, kernel), gpu(memory), memory(cpu.getTicksRef()) {
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
|
||||||
|
Helpers::panic("Failed to initialize SDL2");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make SDL use consistent positional button mapping
|
||||||
|
SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0");
|
||||||
|
if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) {
|
||||||
|
Helpers::warn("Failed to initialize SDL2 GameController: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request OpenGL 4.1 Core (Max available on MacOS)
|
||||||
|
// MacOS gets mad if we don't explicitly demand a core profile
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||||
|
window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_OPENGL);
|
||||||
|
|
||||||
|
if (window == nullptr) {
|
||||||
|
Helpers::panic("Window creation failed: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
glContext = SDL_GL_CreateContext(window);
|
||||||
|
if (glContext == nullptr) {
|
||||||
|
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gladLoadGL(reinterpret_cast<GLADloadfunc>(SDL_GL_GetProcAddress))) {
|
||||||
|
Helpers::panic("OpenGL init failed: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER)) {
|
||||||
|
gameController = SDL_GameControllerOpen(0);
|
||||||
|
|
||||||
|
if (gameController != nullptr) {
|
||||||
|
SDL_Joystick* stick = SDL_GameControllerGetJoystick(gameController);
|
||||||
|
gameControllerID = SDL_JoystickInstanceID(stick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
void Emulator::reset() {
|
void Emulator::reset() {
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
gpu.reset();
|
gpu.reset();
|
||||||
|
|
108
src/io_file.cpp
Normal file
108
src/io_file.cpp
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
#include "io_file.hpp"
|
||||||
|
|
||||||
|
#include "helpers.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// 64 bit offsets for MSVC
|
||||||
|
#define fseeko _fseeki64
|
||||||
|
#define ftello _ftelli64
|
||||||
|
#define fileno _fileno
|
||||||
|
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <io.h> // For _chsize_s
|
||||||
|
#else
|
||||||
|
#include <unistd.h> // For ftruncate
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IOFile::IOFile(const std::filesystem::path& path, const char* permissions) { open(path, permissions); }
|
||||||
|
|
||||||
|
bool IOFile::open(const std::filesystem::path& path, const char* permissions) {
|
||||||
|
const auto str = path.string(); // For some reason converting paths directly with c_str() doesn't work
|
||||||
|
return open(str.c_str(), permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOFile::open(const char* filename, const char* permissions) {
|
||||||
|
handle = std::fopen(filename, permissions);
|
||||||
|
return isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOFile::close() {
|
||||||
|
if (isOpen()) {
|
||||||
|
fclose(handle);
|
||||||
|
handle = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, std::size_t> IOFile::read(void* data, std::size_t length, std::size_t dataSize) {
|
||||||
|
if (!isOpen()) {
|
||||||
|
return {false, std::numeric_limits<std::size_t>::max()};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length == 0) return {true, 0};
|
||||||
|
return {true, std::fread(data, dataSize, length, handle)};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, std::size_t> IOFile::write(const void* data, std::size_t length, std::size_t dataSize) {
|
||||||
|
if (!isOpen()) {
|
||||||
|
return {false, std::numeric_limits<std::size_t>::max()};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length == 0) {
|
||||||
|
return {true, 0};
|
||||||
|
} else {
|
||||||
|
return {true, std::fwrite(data, dataSize, length, handle)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, std::size_t> IOFile::readBytes(void* data, std::size_t count) { return read(data, count, sizeof(std::uint8_t)); }
|
||||||
|
std::pair<bool, std::size_t> IOFile::writeBytes(const void* data, std::size_t count) { return write(data, count, sizeof(std::uint8_t)); }
|
||||||
|
|
||||||
|
std::optional<std::uint64_t> IOFile::size() {
|
||||||
|
if (!isOpen()) return {};
|
||||||
|
|
||||||
|
std::uint64_t pos = ftello(handle);
|
||||||
|
if (fseeko(handle, 0, SEEK_END) != 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint64_t size = ftello(handle);
|
||||||
|
if ((size != pos) && (fseeko(handle, pos, SEEK_SET) != 0)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOFile::seek(std::int64_t offset, int origin) {
|
||||||
|
if (!isOpen() || fseeko(handle, offset, origin) != 0) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOFile::rewind() { return seek(0, SEEK_SET); }
|
||||||
|
FILE* IOFile::getHandle() { return handle; }
|
||||||
|
|
||||||
|
void IOFile::setAppDataDir(const std::filesystem::path& dir) {
|
||||||
|
if (dir == "") Helpers::panic("Failed to set app data directory");
|
||||||
|
appData = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOFile::setSize(std::uint64_t size) {
|
||||||
|
if (!isOpen()) return false;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
success = _chsize_s(_fileno(handle), size) == 0;
|
||||||
|
#else
|
||||||
|
success = ftruncate(fileno(handle), size) == 0;
|
||||||
|
#endif
|
||||||
|
fflush(handle);
|
||||||
|
return success;
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ int main (int argc, char *argv[]) {
|
||||||
|
|
||||||
emu.initGraphicsContext();
|
emu.initGraphicsContext();
|
||||||
|
|
||||||
auto romPath = std::filesystem::current_path() / (argc > 1 ? argv[1] : "OoT Demo Encrypted.3ds");
|
auto romPath = std::filesystem::current_path() / (argc > 1 ? argv[1] : "teapot.elf");
|
||||||
if (!emu.loadROM(romPath)) {
|
if (!emu.loadROM(romPath)) {
|
||||||
// For some reason just .c_str() doesn't show the proper path
|
// For some reason just .c_str() doesn't show the proper path
|
||||||
Helpers::panic("Failed to load ROM file: %s", romPath.string().c_str());
|
Helpers::panic("Failed to load ROM file: %s", romPath.string().c_str());
|
||||||
|
|
Loading…
Add table
Reference in a new issue