Support for loading archives
This commit is contained in:
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@@ -48,10 +48,7 @@ jobs:
|
||||
submodules: recursive
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
vcpkg install sdl2[vulkan]:x64-windows
|
||||
vcpkg install fmt:x64-windows
|
||||
vcpkg install nlohmann-json:x64-windows
|
||||
vcpkg install mio:x64-windows
|
||||
vcpkg install sdl2[vulkan]:x64-windows fmt:x64-windows nlohmann-json:x64-windows mio:x64-windows
|
||||
- name: Build Kaizen
|
||||
run: |
|
||||
cmake -B build -T clangcl -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -S src
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -7,3 +7,6 @@
|
||||
[submodule "external/fmt"]
|
||||
path = external/fmt
|
||||
url = https://github.com/fmtlib/fmt
|
||||
[submodule "external/unarr"]
|
||||
path = external/unarr
|
||||
url = https://github.com/selmf/unarr
|
||||
|
||||
11
external/parallel-rdp/ParallelRDPWrapper.cpp
vendored
11
external/parallel-rdp/ParallelRDPWrapper.cpp
vendored
@@ -154,11 +154,14 @@ void LoadParallelRDP(const u8* rdram) {
|
||||
fragLayout.sets[0].fp_mask = 1;
|
||||
fragLayout.sets[0].array_size[0] = 1;
|
||||
|
||||
u32* fullscreenQuadVert, *fullscreenQuadFrag;
|
||||
auto sizeVert = Util::ReadFileBinary("resources/vert.spv", &fullscreenQuadVert);
|
||||
auto sizeFrag = Util::ReadFileBinary("resources/frag.spv", &fullscreenQuadFrag);
|
||||
auto fullscreenQuadVert = Util::ReadFileBinary("resources/vert.spv");
|
||||
auto fullscreenQuadFrag = Util::ReadFileBinary("resources/frag.spv");
|
||||
auto sizeVert = fullscreenQuadVert.size();
|
||||
auto sizeFrag = fullscreenQuadFrag.size();
|
||||
|
||||
fullscreen_quad_program = wsi->get_device().request_program(fullscreenQuadVert, sizeVert, fullscreenQuadFrag, sizeFrag, &vertLayout, &fragLayout);
|
||||
fullscreen_quad_program = wsi->get_device().request_program(reinterpret_cast<u32*>(fullscreenQuadVert.data()), sizeVert,
|
||||
reinterpret_cast<u32*>(fullscreenQuadFrag.data()), sizeFrag,
|
||||
&vertLayout, &fragLayout);
|
||||
|
||||
auto aligned_rdram = reinterpret_cast<uintptr_t>(rdram);
|
||||
uintptr_t offset = 0;
|
||||
|
||||
1
external/unarr
vendored
Submodule
1
external/unarr
vendored
Submodule
Submodule external/unarr added at 569ffdb063
@@ -36,6 +36,7 @@ include_directories(
|
||||
../external/imgui/imgui
|
||||
../external/imgui/imgui/backends
|
||||
../external/discord-rpc/include
|
||||
../external/unarr
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
@@ -63,6 +64,7 @@ add_subdirectory(../external/discord-rpc discord-rpc)
|
||||
add_subdirectory(../external/imgui imgui)
|
||||
add_subdirectory(../external/nativefiledialog-extended nfd)
|
||||
add_subdirectory(../external/parallel-rdp parallel-rdp)
|
||||
add_subdirectory(../external/unarr unarr)
|
||||
|
||||
add_executable(kaizen main.cpp)
|
||||
|
||||
@@ -77,4 +79,4 @@ file(REMOVE
|
||||
${PROJECT_BINARY_DIR}/resources/shader.vert)
|
||||
|
||||
target_link_libraries(kaizen PUBLIC frontend frontend-imgui
|
||||
discord-rpc imgui nfd parallel-rdp backend fmt::fmt mio::mio nlohmann_json::nlohmann_json core registers interpreter mem mmio rsp SDL2::SDL2main SDL2::SDL2)
|
||||
discord-rpc imgui nfd parallel-rdp backend fmt::fmt unarr mio::mio nlohmann_json::nlohmann_json core registers interpreter mem mmio rsp SDL2::SDL2main SDL2::SDL2)
|
||||
|
||||
@@ -21,14 +21,20 @@ void Core::LoadROM(const std::string& rom_) {
|
||||
pause = false;
|
||||
romLoaded = true;
|
||||
|
||||
cpu.mem.LoadROM(rom);
|
||||
auto extension = fs::path(rom).extension().string();
|
||||
|
||||
bool isArchive = std::any_of(std::begin(ARCHIVE_TYPES), std::end(ARCHIVE_TYPES), [&](auto i) {
|
||||
return extension == i;
|
||||
});
|
||||
|
||||
cpu.mem.LoadROM(isArchive, rom);
|
||||
GameDB::match(cpu.mem);
|
||||
cpu.mem.mmio.vi.isPal = cpu.mem.IsROMPAL();
|
||||
cpu.mem.mmio.si.pif.InitDevices(cpu.mem.saveType);
|
||||
cpu.mem.mmio.si.pif.LoadMempak(rom_);
|
||||
cpu.mem.mmio.si.pif.LoadEeprom(cpu.mem.saveType, rom_);
|
||||
cpu.mem.flash.Load(cpu.mem.saveType, rom_);
|
||||
cpu.mem.LoadSRAM(cpu.mem.saveType, rom_);
|
||||
cpu.mem.mmio.si.pif.LoadMempak(rom);
|
||||
cpu.mem.mmio.si.pif.LoadEeprom(cpu.mem.saveType, rom);
|
||||
cpu.mem.flash.Load(cpu.mem.saveType, rom);
|
||||
cpu.mem.LoadSRAM(cpu.mem.saveType, rom);
|
||||
cpu.mem.mmio.si.pif.ExecutePIF(cpu.mem, cpu.regs);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <core/registers/Cop0.hpp>
|
||||
#include <core/Interpreter.hpp>
|
||||
#include <File.hpp>
|
||||
#include <unarr.h>
|
||||
|
||||
namespace n64 {
|
||||
Mem::Mem() {
|
||||
@@ -76,29 +77,75 @@ FORCE_INLINE void SetROMCIC(u32 checksum, ROM& rom) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mem::LoadROM(const std::string& filename) {
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
file.unsetf(std::ios::skipws);
|
||||
std::vector<u8> Mem::OpenArchive(const std::string &path, size_t& sizeAdjusted) {
|
||||
auto stream = ar_open_file(fs::path(path).u8string().c_str());
|
||||
|
||||
if(!file.is_open()) {
|
||||
Util::panic("Unable to open {}!", filename);
|
||||
if(!stream) {
|
||||
Util::panic("Could not open archive! Are you sure it's an archive?");
|
||||
}
|
||||
|
||||
file.seekg(0, std::ios::end);
|
||||
size_t size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
ar_archive* archive = ar_open_zip_archive(stream, false);
|
||||
|
||||
size_t sizeAdjusted = Util::NextPow2(size);
|
||||
rom.mask = sizeAdjusted - 1;
|
||||
u8* buf = (u8*)malloc(sizeAdjusted);
|
||||
file.read(reinterpret_cast<char*>(buf), size);
|
||||
file.close();
|
||||
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);
|
||||
Util::panic("Could not open archive! Are you sure it's a supported archive? (7z, zip, rar and tar are supported)");
|
||||
}
|
||||
|
||||
std::vector<u8> buf{};
|
||||
|
||||
while(ar_parse_entry(archive)) {
|
||||
auto filename = ar_entry_get_name(archive);
|
||||
auto extension = fs::path(filename).extension();
|
||||
|
||||
if(std::any_of(std::begin(ROM_EXTENSIONS), std::end(ROM_EXTENSIONS), [&](auto x) {
|
||||
return extension == x;
|
||||
})) {
|
||||
auto size = ar_entry_get_size(archive);
|
||||
sizeAdjusted = Util::NextPow2(size);
|
||||
buf.resize(sizeAdjusted);
|
||||
ar_entry_uncompress(archive, buf.data(), size);
|
||||
break;
|
||||
} else {
|
||||
ar_close_archive(archive);
|
||||
ar_close(stream);
|
||||
Util::panic("Could not find any rom image in the archive!");
|
||||
}
|
||||
}
|
||||
|
||||
ar_close_archive(archive);
|
||||
ar_close(stream);
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::vector<u8> Mem::OpenROM(const std::string& filename, size_t& sizeAdjusted) {
|
||||
auto buf = Util::ReadFileBinary(filename);
|
||||
sizeAdjusted = Util::NextPow2(buf.size());
|
||||
return buf;
|
||||
}
|
||||
|
||||
void Mem::LoadROM(bool isArchive, const std::string& filename) {
|
||||
size_t sizeAdjusted;
|
||||
u8* buf;
|
||||
std::vector<u8> temp{};
|
||||
if(isArchive) {
|
||||
temp = OpenArchive(filename, sizeAdjusted);
|
||||
} else {
|
||||
temp = OpenROM(filename, sizeAdjusted);
|
||||
}
|
||||
|
||||
buf = (u8*)calloc(sizeAdjusted, 1);
|
||||
std::copy(temp.begin(), temp.end(), buf);
|
||||
|
||||
u32 endianness = be32toh(*reinterpret_cast<u32*>(buf));
|
||||
Util::SwapN64Rom<true>(sizeAdjusted, buf, endianness);
|
||||
|
||||
memcpy(rom.cart, buf, sizeAdjusted);
|
||||
rom.size = sizeAdjusted;
|
||||
rom.mask = sizeAdjusted - 1;
|
||||
memcpy(&rom.header, buf, sizeof(ROMHeader));
|
||||
memcpy(rom.gameNameCart, rom.header.imageName, sizeof(rom.header.imageName));
|
||||
|
||||
|
||||
@@ -134,7 +134,9 @@ struct Mem {
|
||||
Mem();
|
||||
void Reset();
|
||||
void LoadSRAM(SaveType, fs::path);
|
||||
void LoadROM(const std::string&);
|
||||
static std::vector<u8> OpenROM(const std::string&, size_t&);
|
||||
static std::vector<u8> OpenArchive(const std::string&, size_t&);
|
||||
void LoadROM(bool, const std::string&);
|
||||
[[nodiscard]] auto GetRDRAM() const -> u8* {
|
||||
return mmio.rdp.rdram;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ using m128i = __m128i;
|
||||
#define HALF_ADDRESS(addr) ((addr) ^ 2)
|
||||
#define BYTE_ADDRESS(addr) ((addr) ^ 3)
|
||||
|
||||
#define ARCHIVE_TYPES {".zip",".7z",".rar",".tar"}
|
||||
#define ROM_EXTENSIONS {".n64",".z64",".v64",".N64",".Z64",".V64"}
|
||||
|
||||
#define RD(x) (((x) >> 11) & 0x1F)
|
||||
#define RT(x) (((x) >> 16) & 0x1F)
|
||||
#define RS(x) (((x) >> 21) & 0x1F)
|
||||
|
||||
@@ -49,7 +49,7 @@ void App::Run() {
|
||||
switch(event.key.keysym.sym) {
|
||||
case SDLK_o: {
|
||||
nfdchar_t* outpath;
|
||||
const nfdu8filteritem_t filter {"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"};
|
||||
const nfdu8filteritem_t filter {"Nintendo 64 roms/archives", "n64,z64,v64,N64,Z64,V64,zip,tar,rar,7z"};
|
||||
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
||||
if(result == NFD_OKAY) {
|
||||
LoadROM(outpath);
|
||||
|
||||
@@ -3,21 +3,9 @@
|
||||
#include <log.hpp>
|
||||
|
||||
namespace Util {
|
||||
FORCE_INLINE auto ReadFileBinary(const std::string& path, u32** buf) {
|
||||
FORCE_INLINE std::vector<u8> ReadFileBinary(const std::string& path) {
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
file.unsetf(std::ios::skipws);
|
||||
if(!file.is_open()) {
|
||||
panic("Could not load file '{}'!", path);
|
||||
}
|
||||
|
||||
file.seekg(0, std::ios::end);
|
||||
size_t size = file.tellg();
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
*buf = (u32*)calloc(size, 1);
|
||||
file.read(reinterpret_cast<char*>(*buf), size);
|
||||
file.close();
|
||||
return size;
|
||||
return {std::istreambuf_iterator{file}, {}};
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t NextPow2(size_t num) {
|
||||
|
||||
Reference in New Issue
Block a user