Skip to content

Commit

Permalink
Merge pull request #307 from wheremyfoodat/rhappy
Browse files Browse the repository at this point in the history
Stuff
  • Loading branch information
wheremyfoodat authored Oct 15, 2023
2 parents 2ab37b3 + 0421eae commit 07afcfb
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 19 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@
[submodule "third_party/LuaJIT"]
path = third_party/LuaJIT
url = https://github.com/Panda3DS-emu/LuaJIT
[submodule "third_party/mio"]
path = third_party/mio
url = https://github.com/vimpunk/mio
13 changes: 10 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ include_directories(third_party/xxhash/include)
include_directories(third_party/httplib)
include_directories(third_party/stb)
include_directories(third_party/opengl)
include_directories(third_party/mio/single_include)

add_compile_definitions(NOMINMAX) # Make windows.h not define min/max macros because third-party deps don't like it
add_compile_definitions(WIN32_LEAN_AND_MEAN) # Make windows.h not include literally everything
Expand Down Expand Up @@ -141,7 +142,7 @@ set(SOURCE_FILES src/emulator.cpp src/io_file.cpp src/config.cpp
src/core/CPU/cpu_dynarmic.cpp src/core/CPU/dynarmic_cycles.cpp
src/core/memory.cpp src/renderer.cpp src/core/renderer_null/renderer_null.cpp
src/http_server.cpp src/stb_image_write.c src/core/cheats.cpp src/core/action_replay.cpp
src/discord_rpc.cpp src/lua.cpp
src/discord_rpc.cpp src/lua.cpp src/memory_mapped_file.cpp
)
set(CRYPTO_SOURCE_FILES src/core/crypto/aes_engine.cpp)
set(KERNEL_SOURCE_FILES src/core/kernel/kernel.cpp src/core/kernel/resource_limits.cpp
Expand Down Expand Up @@ -181,7 +182,7 @@ set(RENDERER_SW_SOURCE_FILES src/core/renderer_sw/renderer_sw.cpp)
if(ENABLE_QT_GUI)
set(FRONTEND_SOURCE_FILES src/panda_qt/main.cpp src/panda_qt/screen.cpp src/panda_qt/main_window.cpp)
set(FRONTEND_HEADER_FILES include/panda_qt/screen.hpp include/panda_qt/main_window.hpp)

source_group("Source Files\\Qt" FILES ${FRONTEND_SOURCE_FILES})
source_group("Header Files\\Qt" FILES ${FRONTEND_HEADER_FILES})
include_directories(${Qt6Gui_PRIVATE_INCLUDE_DIRS})
Expand Down Expand Up @@ -219,7 +220,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
include/applets/applet.hpp include/applets/mii_selector.hpp include/math_util.hpp include/services/soc.hpp
include/services/news_u.hpp include/applets/software_keyboard.hpp include/applets/applet_manager.hpp include/fs/archive_user_save_data.hpp
include/services/amiibo_device.hpp include/services/nfc_types.hpp include/swap.hpp include/services/csnd.hpp include/services/nwm_uds.hpp
include/fs/archive_system_save_data.hpp include/lua_manager.hpp
include/fs/archive_system_save_data.hpp include/lua_manager.hpp include/memory_mapped_file.hpp
)

cmrc_add_resource_library(
Expand Down Expand Up @@ -413,6 +414,12 @@ if(ENABLE_QT_GUI)
target_link_libraries(Alber PRIVATE OpenGL::OpenGL OpenGL::EGL OpenGL::GLX)
endif()
endif()

qt_add_resources(Alber "app_images"
PREFIX "/"
FILES
docs/img/rsob_icon.png
)
else()
target_compile_definitions(Alber PUBLIC "PANDA3DS_FRONTEND_SDL=1")
endif()
Expand Down
Binary file added docs/img/rsob_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions include/emulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "cpu.hpp"
#include "crypto/aes_engine.hpp"
#include "discord_rpc.hpp"
#include "fs/romfs.hpp"
#include "io_file.hpp"
#include "lua_manager.hpp"
#include "memory.hpp"
Expand Down Expand Up @@ -120,6 +121,7 @@ class Emulator {
void initGraphicsContext() { gpu.initGraphicsContext(window); }
#endif

RomFS::DumpingResult dumpRomFS(const std::filesystem::path& path);
void setOutputSize(u32 width, u32 height) { gpu.setOutputSize(width, height); }

EmulatorConfig& getConfig() { return config; }
Expand Down
7 changes: 7 additions & 0 deletions include/fs/romfs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,12 @@ namespace RomFS {
std::vector<std::unique_ptr<RomFSNode>> files;
};

// Result codes when dumping RomFS. These are used by the frontend to print appropriate error messages if RomFS dumping fails
enum class DumpingResult {
Success = 0,
InvalidFormat = 1, // ROM is a format that doesn't support RomFS, such as ELF
NoRomFS = 2
};

std::unique_ptr<RomFSNode> parseRomFSTree(uintptr_t romFS, u64 romFSSize);
} // namespace RomFS
1 change: 1 addition & 0 deletions include/loader/ncch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct NCCH {
FSInfo exeFS;
FSInfo romFS;
CodeSetInfo text, data, rodata;
FSInfo partitionInfo;

// Contents of the .code file in the ExeFS
std::vector<u8> codeFile;
Expand Down
42 changes: 42 additions & 0 deletions include/memory_mapped_file.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include <filesystem>
#include <system_error>

#include "helpers.hpp"
#include "mio/mio.hpp"

// Minimal RAII wrapper over memory mapped files

class MemoryMappedFile {
std::filesystem::path filePath = ""; // path of our file
mio::mmap_sink map; // mmap sink for our file

u8* pointer = nullptr; // Pointer to the contents of the memory mapped file
bool opened = false;

public:
bool exists() const { return opened; }
u8* data() const { return pointer; }

std::error_code flush();
MemoryMappedFile();
MemoryMappedFile(const std::filesystem::path& path);

~MemoryMappedFile();
// Returns true on success
bool open(const std::filesystem::path& path);
void close();

// TODO: For memory-mapped output files we'll need some more stuff such as a constructor that takes path/size/shouldCreate as parameters

u8& operator[](size_t index) { return pointer[index]; }
const u8& operator[](size_t index) const { return pointer[index]; }

auto begin() { return map.begin(); }
auto end() { return map.end(); }
auto cbegin() { return map.cbegin(); }
auto cend() { return map.cend(); }

mio::mmap_sink& getSink() { return map; }
};
8 changes: 6 additions & 2 deletions include/panda_qt/main_window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
#include <QPalette>
#include <QtWidgets>
#include <atomic>
#include <thread>
#include <filesystem>
#include <thread>
#include <mutex>

#include "emulator.hpp"
#include "panda_qt/screen.hpp"
Expand All @@ -27,9 +28,11 @@ class MainWindow : public QMainWindow {
std::thread emuThread;

std::atomic<bool> appRunning = true; // Is the application itself running?
std::atomic<bool> needToLoadROM = false;
std::mutex messageQueueMutex; // Used for synchronizing messages between the emulator and UI
std::filesystem::path romToLoad = "";

bool needToLoadROM = false;

ScreenWidget screen;
QComboBox* themeSelect = nullptr;
QMenuBar* menuBar = nullptr;
Expand All @@ -39,6 +42,7 @@ class MainWindow : public QMainWindow {
void swapEmuBuffer();
void emuThreadMainLoop();
void selectROM();
void dumpRomFS();

// Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer
bool usingGL = false;
Expand Down
1 change: 1 addition & 0 deletions src/core/loader/ncch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn

codeFile.clear();
saveData.clear();
partitionInfo = info;

size = u64(*(u32*)&header[0x104]) * mediaUnit; // TODO: Maybe don't type pun because big endian will break
exheaderSize = *(u32*)&header[0x180];
Expand Down
64 changes: 63 additions & 1 deletion src/emulator.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "emulator.hpp"

#include <glad/gl.h>
#include <fstream>

#ifdef _WIN32
#include <windows.h>
Expand Down Expand Up @@ -581,4 +583,64 @@ void Emulator::updateDiscord() {
}
#else
void Emulator::updateDiscord() {}
#endif
#endif

static void dumpRomFSNode(const RomFS::RomFSNode& node, const char* romFSBase, const std::filesystem::path& path) {
for (auto& file : node.files) {
const auto p = path / file->name;
std::ofstream outFile(p);

outFile.write(romFSBase + file->dataOffset, file->dataSize);
}

for (auto& directory : node.directories) {
const auto newPath = path / directory->name;

// Create the directory for the new folder
std::error_code ec;
std::filesystem::create_directories(newPath, ec);

if (!ec) {
dumpRomFSNode(*directory, romFSBase, newPath);
}
}
}

RomFS::DumpingResult Emulator::dumpRomFS(const std::filesystem::path& path) {
using namespace RomFS;

if (romType != ROMType::NCSD && romType != ROMType::CXI && romType != ROMType::HB_3DSX) {
return DumpingResult::InvalidFormat;
}

// Contents of RomFS as raw bytes
std::vector<u8> romFS;
u64 size;

if (romType == ROMType::HB_3DSX) {
auto hb3dsx = memory.get3DSX();
if (!hb3dsx->hasRomFs()) {
return DumpingResult::NoRomFS;
}
size = hb3dsx->romFSSize;

romFS.resize(size);
hb3dsx->readRomFSBytes(&romFS[0], 0, size);
} else {
auto cxi = memory.getCXI();
if (!cxi->hasRomFS()) {
return DumpingResult::NoRomFS;
}

const u64 offset = cxi->romFS.offset;
size = cxi->romFS.size;

romFS.resize(size);
cxi->readFromFile(memory.CXIFile, cxi->partitionInfo, &romFS[0], offset - cxi->fileOffset, size);
}

std::unique_ptr<RomFSNode> node = parseRomFSTree((uintptr_t)&romFS[0], size);
dumpRomFSNode(*node, (const char*)&romFS[0], path);

return DumpingResult::Success;
}
37 changes: 37 additions & 0 deletions src/memory_mapped_file.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "memory_mapped_file.hpp"

MemoryMappedFile::MemoryMappedFile() : opened(false), filePath(""), pointer(nullptr) {}
MemoryMappedFile::MemoryMappedFile(const std::filesystem::path& path) { open(path); }
MemoryMappedFile::~MemoryMappedFile() { close(); }

// TODO: This should probably also return the error one way or another eventually
bool MemoryMappedFile::open(const std::filesystem::path& path) {
std::error_code error;
map = mio::make_mmap_sink(path.string(), 0, mio::map_entire_file, error);

if (error) {
opened = false;
return false;
}

filePath = path;
pointer = (u8*)map.data();
opened = true;
return true;
}

void MemoryMappedFile::close() {
if (opened) {
opened = false;
pointer = nullptr; // Set the pointer to nullptr to avoid errors related to lingering pointers

map.unmap();
}
}

std::error_code MemoryMappedFile::flush() {
std::error_code ret;
map.sync(ret);

return ret;
}
Loading

0 comments on commit 07afcfb

Please sign in to comment.