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
|
submodules: recursive
|
||||||
- name: Setup dependencies
|
- name: Setup dependencies
|
||||||
run: |
|
run: |
|
||||||
vcpkg install sdl2[vulkan]:x64-windows
|
vcpkg install sdl2[vulkan]:x64-windows fmt:x64-windows nlohmann-json:x64-windows mio:x64-windows
|
||||||
vcpkg install fmt:x64-windows
|
|
||||||
vcpkg install nlohmann-json:x64-windows
|
|
||||||
vcpkg install mio:x64-windows
|
|
||||||
- name: Build Kaizen
|
- name: Build Kaizen
|
||||||
run: |
|
run: |
|
||||||
cmake -B build -T clangcl -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -S src
|
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"]
|
[submodule "external/fmt"]
|
||||||
path = external/fmt
|
path = external/fmt
|
||||||
url = https://github.com/fmtlib/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].fp_mask = 1;
|
||||||
fragLayout.sets[0].array_size[0] = 1;
|
fragLayout.sets[0].array_size[0] = 1;
|
||||||
|
|
||||||
u32* fullscreenQuadVert, *fullscreenQuadFrag;
|
auto fullscreenQuadVert = Util::ReadFileBinary("resources/vert.spv");
|
||||||
auto sizeVert = Util::ReadFileBinary("resources/vert.spv", &fullscreenQuadVert);
|
auto fullscreenQuadFrag = Util::ReadFileBinary("resources/frag.spv");
|
||||||
auto sizeFrag = Util::ReadFileBinary("resources/frag.spv", &fullscreenQuadFrag);
|
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);
|
auto aligned_rdram = reinterpret_cast<uintptr_t>(rdram);
|
||||||
uintptr_t offset = 0;
|
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
|
||||||
../external/imgui/imgui/backends
|
../external/imgui/imgui/backends
|
||||||
../external/discord-rpc/include
|
../external/discord-rpc/include
|
||||||
|
../external/unarr
|
||||||
${SDL2_INCLUDE_DIRS}
|
${SDL2_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ add_subdirectory(../external/discord-rpc discord-rpc)
|
|||||||
add_subdirectory(../external/imgui imgui)
|
add_subdirectory(../external/imgui imgui)
|
||||||
add_subdirectory(../external/nativefiledialog-extended nfd)
|
add_subdirectory(../external/nativefiledialog-extended nfd)
|
||||||
add_subdirectory(../external/parallel-rdp parallel-rdp)
|
add_subdirectory(../external/parallel-rdp parallel-rdp)
|
||||||
|
add_subdirectory(../external/unarr unarr)
|
||||||
|
|
||||||
add_executable(kaizen main.cpp)
|
add_executable(kaizen main.cpp)
|
||||||
|
|
||||||
@@ -77,4 +79,4 @@ file(REMOVE
|
|||||||
${PROJECT_BINARY_DIR}/resources/shader.vert)
|
${PROJECT_BINARY_DIR}/resources/shader.vert)
|
||||||
|
|
||||||
target_link_libraries(kaizen PUBLIC frontend frontend-imgui
|
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)
|
||||||
|
|||||||
@@ -20,15 +20,21 @@ void Core::LoadROM(const std::string& rom_) {
|
|||||||
cpu.Reset();
|
cpu.Reset();
|
||||||
pause = false;
|
pause = false;
|
||||||
romLoaded = true;
|
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);
|
GameDB::match(cpu.mem);
|
||||||
cpu.mem.mmio.vi.isPal = cpu.mem.IsROMPAL();
|
cpu.mem.mmio.vi.isPal = cpu.mem.IsROMPAL();
|
||||||
cpu.mem.mmio.si.pif.InitDevices(cpu.mem.saveType);
|
cpu.mem.mmio.si.pif.InitDevices(cpu.mem.saveType);
|
||||||
cpu.mem.mmio.si.pif.LoadMempak(rom_);
|
cpu.mem.mmio.si.pif.LoadMempak(rom);
|
||||||
cpu.mem.mmio.si.pif.LoadEeprom(cpu.mem.saveType, rom_);
|
cpu.mem.mmio.si.pif.LoadEeprom(cpu.mem.saveType, rom);
|
||||||
cpu.mem.flash.Load(cpu.mem.saveType, rom_);
|
cpu.mem.flash.Load(cpu.mem.saveType, rom);
|
||||||
cpu.mem.LoadSRAM(cpu.mem.saveType, rom_);
|
cpu.mem.LoadSRAM(cpu.mem.saveType, rom);
|
||||||
cpu.mem.mmio.si.pif.ExecutePIF(cpu.mem, cpu.regs);
|
cpu.mem.mmio.si.pif.ExecutePIF(cpu.mem, cpu.regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <core/registers/Cop0.hpp>
|
#include <core/registers/Cop0.hpp>
|
||||||
#include <core/Interpreter.hpp>
|
#include <core/Interpreter.hpp>
|
||||||
#include <File.hpp>
|
#include <File.hpp>
|
||||||
|
#include <unarr.h>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
Mem::Mem() {
|
Mem::Mem() {
|
||||||
@@ -76,29 +77,75 @@ FORCE_INLINE void SetROMCIC(u32 checksum, ROM& rom) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mem::LoadROM(const std::string& filename) {
|
std::vector<u8> Mem::OpenArchive(const std::string &path, size_t& sizeAdjusted) {
|
||||||
std::ifstream file(filename, std::ios::binary);
|
auto stream = ar_open_file(fs::path(path).u8string().c_str());
|
||||||
file.unsetf(std::ios::skipws);
|
|
||||||
|
|
||||||
if(!file.is_open()) {
|
if(!stream) {
|
||||||
Util::panic("Unable to open {}!", filename);
|
Util::panic("Could not open archive! Are you sure it's an archive?");
|
||||||
}
|
}
|
||||||
|
|
||||||
file.seekg(0, std::ios::end);
|
ar_archive* archive = ar_open_zip_archive(stream, false);
|
||||||
size_t size = file.tellg();
|
|
||||||
file.seekg(0, std::ios::beg);
|
|
||||||
|
|
||||||
size_t sizeAdjusted = Util::NextPow2(size);
|
if(!archive) archive = ar_open_rar_archive(stream);
|
||||||
rom.mask = sizeAdjusted - 1;
|
if(!archive) archive = ar_open_7z_archive(stream);
|
||||||
u8* buf = (u8*)malloc(sizeAdjusted);
|
if(!archive) archive = ar_open_tar_archive(stream);
|
||||||
file.read(reinterpret_cast<char*>(buf), size);
|
|
||||||
file.close();
|
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));
|
u32 endianness = be32toh(*reinterpret_cast<u32*>(buf));
|
||||||
Util::SwapN64Rom<true>(sizeAdjusted, buf, endianness);
|
Util::SwapN64Rom<true>(sizeAdjusted, buf, endianness);
|
||||||
|
|
||||||
memcpy(rom.cart, buf, sizeAdjusted);
|
memcpy(rom.cart, buf, sizeAdjusted);
|
||||||
rom.size = sizeAdjusted;
|
rom.size = sizeAdjusted;
|
||||||
|
rom.mask = sizeAdjusted - 1;
|
||||||
memcpy(&rom.header, buf, sizeof(ROMHeader));
|
memcpy(&rom.header, buf, sizeof(ROMHeader));
|
||||||
memcpy(rom.gameNameCart, rom.header.imageName, sizeof(rom.header.imageName));
|
memcpy(rom.gameNameCart, rom.header.imageName, sizeof(rom.header.imageName));
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,9 @@ struct Mem {
|
|||||||
Mem();
|
Mem();
|
||||||
void Reset();
|
void Reset();
|
||||||
void LoadSRAM(SaveType, fs::path);
|
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* {
|
[[nodiscard]] auto GetRDRAM() const -> u8* {
|
||||||
return mmio.rdp.rdram;
|
return mmio.rdp.rdram;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ using m128i = __m128i;
|
|||||||
#define HALF_ADDRESS(addr) ((addr) ^ 2)
|
#define HALF_ADDRESS(addr) ((addr) ^ 2)
|
||||||
#define BYTE_ADDRESS(addr) ((addr) ^ 3)
|
#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 RD(x) (((x) >> 11) & 0x1F)
|
||||||
#define RT(x) (((x) >> 16) & 0x1F)
|
#define RT(x) (((x) >> 16) & 0x1F)
|
||||||
#define RS(x) (((x) >> 21) & 0x1F)
|
#define RS(x) (((x) >> 21) & 0x1F)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ void App::Run() {
|
|||||||
switch(event.key.keysym.sym) {
|
switch(event.key.keysym.sym) {
|
||||||
case SDLK_o: {
|
case SDLK_o: {
|
||||||
nfdchar_t* outpath;
|
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);
|
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
||||||
if(result == NFD_OKAY) {
|
if(result == NFD_OKAY) {
|
||||||
LoadROM(outpath);
|
LoadROM(outpath);
|
||||||
|
|||||||
@@ -3,21 +3,9 @@
|
|||||||
#include <log.hpp>
|
#include <log.hpp>
|
||||||
|
|
||||||
namespace Util {
|
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);
|
std::ifstream file(path, std::ios::binary);
|
||||||
file.unsetf(std::ios::skipws);
|
return {std::istreambuf_iterator{file}, {}};
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE size_t NextPow2(size_t num) {
|
FORCE_INLINE size_t NextPow2(size_t num) {
|
||||||
|
|||||||
Reference in New Issue
Block a user