Merge pull request #46 from Wunkolo/io-file-cpp

Migrate `IOFile` implementation to `io_file.cpp`
This commit is contained in:
wheremyfoodat 2023-06-28 04:00:39 +03:00 committed by GitHub
commit fc7e0b2b03
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 176 additions and 166 deletions

View file

@ -69,7 +69,7 @@ else()
message(FATAL_ERROR "Currently unsupported CPU architecture")
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
)
set(CRYPTO_SOURCE_FILES src/core/crypto/aes_engine.cpp)

View file

@ -44,48 +44,7 @@ class Emulator {
NCSD loadedNCSD;
public:
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();
}
Emulator();
void step();
void render();

View file

@ -1,136 +1,36 @@
#pragma once
#include <cstdint>
#include <cstdio>
#include <filesystem>
#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 {
FILE* handle = nullptr;
static inline std::filesystem::path appData = ""; // Directory for holding app data. AppData on Windows
FILE* handle = nullptr;
static inline std::filesystem::path appData = ""; // Directory for holding app data. AppData on Windows
public:
IOFile() {}
IOFile(FILE* handle) : handle(handle) {}
IOFile(const std::filesystem::path& path, const char* permissions = "rb") {
open(path, permissions);
}
public:
IOFile() {}
IOFile(FILE* handle) : handle(handle) {}
IOFile(const std::filesystem::path& path, const char* permissions = "rb");
bool isOpen() {
return handle != nullptr;
}
bool isOpen() { 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") {
const auto str = path.string(); // For some reason converting paths directly with c_str() doesn't work
return open(str.c_str(), permissions);
}
std::pair<bool, std::size_t> read(void* data, std::size_t length, std::size_t dataSize);
std::pair<bool, std::size_t> readBytes(void* data, std::size_t count);
bool open(const char* filename, const char* permissions = "rb") {
handle = std::fopen(filename, permissions);
return isOpen();
}
std::pair<bool, std::size_t> write(const void* data, std::size_t length, std::size_t dataSize);
std::pair<bool, std::size_t> writeBytes(const void* data, std::size_t count);
void close() {
if (isOpen()) {
fclose(handle);
handle = nullptr;
}
}
std::optional<std::uint64_t> size();
std::pair<bool, std::size_t> read(void* data, std::size_t length, std::size_t dataSize) {
if (!isOpen()) {
return { false, std::numeric_limits<std::size_t>::max() };
}
bool seek(std::int64_t offset, int origin = SEEK_SET);
bool rewind();
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
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; }
// Sets the size of the file to "size" and returns whether it succeeded or not
bool setSize(std::uint64_t size);
};

View file

@ -1,5 +1,48 @@
#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() {
cpu.reset();
gpu.reset();

108
src/io_file.cpp Normal file
View 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;
}

View file

@ -5,7 +5,7 @@ int main (int argc, char *argv[]) {
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)) {
// For some reason just .c_str() doesn't show the proper path
Helpers::panic("Failed to load ROM file: %s", romPath.string().c_str());