Support for loading archives

This commit is contained in:
SimoneN64
2023-06-11 17:54:53 +02:00
parent cfc080fe2d
commit 3bb4f5e31e
11 changed files with 96 additions and 44 deletions

View File

@@ -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
View File

@@ -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

View File

@@ -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

Submodule external/unarr added at 569ffdb063

View File

@@ -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)

View File

@@ -20,15 +20,21 @@ void Core::LoadROM(const std::string& rom_) {
cpu.Reset();
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);
}

View File

@@ -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));

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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) {