Skip to content

Commit

Permalink
Add support for loading embedded games into an archive.
Browse files Browse the repository at this point in the history
  • Loading branch information
Arignir committed Jan 2, 2024
1 parent 50e833b commit 334f676
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 8 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:
- name: Install Dependencies
uses: msys2/setup-msys2@v2
with:
install: make mingw-w64-x86_64-meson mingw-w64-x86_64-ninja mingw-w64-x86_64-pkg-config mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL2 mingw-w64-x86_64-glew
install: make mingw-w64-x86_64-meson mingw-w64-x86_64-ninja mingw-w64-x86_64-pkg-config mingw-w64-x86_64-gcc mingw-w64-x86_64-SDL2 mingw-w64-x86_64-glew mingw-w64-x86_64-cmake mingw-w64-x86_64-libarchive
- name: Build Hades
run: |
meson build -Dstatic_executable=true
meson --buildtype=release build -Dstatic_executable=true
cd build
ninja
- name: Test Hades
Expand All @@ -41,7 +41,7 @@ jobs:
submodules: recursive
- name: Install Dependencies
run: |
brew install meson ninja sdl2 glew create-dmg
brew install meson ninja sdl2 glew libarchive create-dmg
- name: Build Hades
run: |
rm -rf /tmp/build/
Expand Down Expand Up @@ -137,10 +137,10 @@ jobs:
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y meson ninja-build libsdl2-dev libglew-dev libgtk-3-dev
sudo apt-get install -y meson ninja-build libsdl2-dev libglew-dev libgtk-3-dev libarchive-dev
- name: Build Hades
run: |
meson build --werror
meson --buildtype=release build --werror
cd build
ninja
- name: Test Hades
Expand Down
4 changes: 3 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[submodule "external/cimgui"]
path = external/cimgui
url = https://github.com/cimgui/cimgui.git
branch = Lib_Only
[submodule "external/stb"]
path = external/stb
url = https://github.com/nothings/stb.git
Expand All @@ -11,3 +10,6 @@
[submodule "external/mjson"]
path = external/mjson
url = https://github.com/cesanta/mjson.git
[submodule "subprojects/libarchive"]
path = subprojects/libarchive
url = https://github.com/libarchive/libarchive.git
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ project(
default_options: ['c_std=gnu17', 'cpp_std=c++11', 'buildtype=release'],
)

cmake = import('cmake')

incdir = include_directories('include', 'source')
cflags = [
'-fms-extensions',
Expand Down
101 changes: 100 additions & 1 deletion source/app/emulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#define _GNU_SOURCE
#define STB_IMAGE_WRITE_IMPLEMENTATION

#include <archive.h>
#include <archive_entry.h>
#include <stb_image_write.h>
#include <errno.h>
#include "app/app.h"
Expand Down Expand Up @@ -262,6 +264,94 @@ app_emulator_configure_bios(
return (false);
}

static
bool
app_emulator_configure_rom_archive(
struct app *app,
char const *archive_path
) {
struct archive *archive;
struct archive_entry *entry;
int err;
bool game_found;

logln(HS_INFO, "Path given identified as an archived.");

game_found = false;
archive = archive_read_new();
hs_assert(archive);

archive_read_support_filter_all(archive);
archive_read_support_format_all(archive);

err = archive_read_open_filename(archive, archive_path, 4096);
if (err != ARCHIVE_OK) {
app_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to open the path as an archive: %s.",
archive_path,
archive_error_string(archive)
);
return (true);
}

while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
char const *entry_name;
char const *ext;

entry_name = archive_entry_pathname(entry);
ext = strrchr(entry_name, '.');
if (ext && !strcmp(ext, ".gba")) {
size_t file_len;
ssize_t read_len;
void *data;

file_len = 0;
data = NULL;
do {
data = realloc(data, file_len + 4096);
hs_assert(data);

read_len = archive_read_data(archive, data + file_len, 4096);
if (read_len < 0) {
app_new_notification(
app,
UI_NOTIFICATION_ERROR,
"Failed to archive's entry %s: %s.",
entry_name,
archive_error_string(archive)
);
free(data);
goto cleanup;
}
file_len += read_len;
} while (read_len > 0);

game_found = true;

app->emulation.launch_config->rom.data = data;
app->emulation.launch_config->rom.size = file_len;

goto cleanup;
}

archive_read_data_skip(archive);
}

app_new_notification(
app,
UI_NOTIFICATION_ERROR,
"No valid GBA game found in the archive.",
archive_path,
archive_error_string(archive)
);

cleanup:
archive_read_free(archive);
return (!game_found);
}

static
bool
app_emulator_configure_rom(
Expand Down Expand Up @@ -387,21 +477,28 @@ app_emulator_configure(
struct message_reset event;
char *backup_path;
char *extension;
bool is_archive;
size_t basename_len;
size_t i;
uint8_t *code;

app_emulator_unconfigure(app);

logln(HS_INFO, "Loading game at \"%s%s%s\".", g_light_green, rom_path, g_reset);

app->emulation.launch_config = calloc(1, sizeof(struct launch_config));
hs_assert(app->emulation.launch_config);

extension = strrchr(rom_path, '.');

// We consider anything that isn't ending with `.gba` or `.bin` as an archive.
// XXX: Should we build a hard-coded list instead?
if (extension) {
basename_len = extension - rom_path;
is_archive = (bool)(strcmp(extension, ".gba") && strcmp(extension, ".bin"));
} else {
basename_len = strlen(rom_path);
is_archive = false;
}

for (i = 0; i < MAX_QUICKSAVES; ++i) {
Expand All @@ -426,7 +523,7 @@ app_emulator_configure(
);

if (app_emulator_configure_bios(app)
|| app_emulator_configure_rom(app, rom_path)
|| (is_archive ? app_emulator_configure_rom_archive(app, rom_path) : app_emulator_configure_rom(app, rom_path))
|| app_emulator_configure_backup(app, backup_path)
) {
app_emulator_unconfigure(app);
Expand Down Expand Up @@ -502,6 +599,8 @@ app_emulator_configure(

app_config_push_recent_rom(app, rom_path);

logln(HS_INFO, "Game successfully loaded.");

return (false);
}

Expand Down
3 changes: 2 additions & 1 deletion source/app/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ libapp = static_library(
'emulator.c',
'bindings.c',
'main.c',
dependencies: [
dependencies: imgui_dep + [
dependency('threads', required: true, static: get_option('static_executable')),
dependency('libarchive', required: true, static: get_option('static_executable')),
],
link_with: [libgba, imgui, nfde, mjson] + libapp_extra_deps,
include_directories: [incdir, imgui_inc, nfde_inc, mjson_inc, stb_inc],
Expand Down
1 change: 1 addition & 0 deletions subprojects/libarchive
Submodule libarchive added at 6468cd

0 comments on commit 334f676

Please sign in to comment.