summaryrefslogtreecommitdiff
path: root/jni/physfs-serve-sdl-wrap.c
diff options
context:
space:
mode:
authorJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-16 18:49:26 +0900
committerJari Vetoniemi <jari.vetoniemi@indooratlas.com>2020-03-30 00:39:06 +0900
commitfcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch)
tree64cb17de3f41a2b6fef2368028fbd00349946994 /jni/physfs-serve-sdl-wrap.c
Fresh start
Diffstat (limited to 'jni/physfs-serve-sdl-wrap.c')
-rw-r--r--jni/physfs-serve-sdl-wrap.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/jni/physfs-serve-sdl-wrap.c b/jni/physfs-serve-sdl-wrap.c
new file mode 100644
index 0000000..ccdbce4
--- /dev/null
+++ b/jni/physfs-serve-sdl-wrap.c
@@ -0,0 +1,162 @@
+#include "libphysfs-serve.h"
+#include <physfs.h>
+#include <SDL_rwops.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+static void ignore_ret(bool b, ...) {};
+#define ignore_ret(x) ignore_ret(true, x);
+
+struct io_wrapper {
+ SDL_RWops *ops;
+ const char *path;
+};
+
+static SDL_RWops*
+get_ops(struct io_wrapper *w) { return w->ops; }
+
+static const char*
+get_path(struct io_wrapper *w) { return w->path; }
+
+static PHYSFS_sint64
+SDLRWIoRead(struct PHYSFS_Io *io, void *buf, PHYSFS_uint64 len) {
+ return SDL_RWread(get_ops(io->opaque), buf, 1, len);
+}
+
+static int
+SDLRWIoSeek(struct PHYSFS_Io *io, PHYSFS_uint64 offset) {
+ return (SDL_RWseek(get_ops(io->opaque), offset, RW_SEEK_SET) != -1);
+}
+
+static PHYSFS_sint64
+SDLRWIoTell(struct PHYSFS_Io *io) {
+ return SDL_RWseek(get_ops(io->opaque), 0, RW_SEEK_CUR);
+}
+
+static PHYSFS_sint64
+SDLRWIoLength(struct PHYSFS_Io *io) {
+ return SDL_RWsize(get_ops(io->opaque));
+}
+
+static PHYSFS_Io* SDLRWIo_new(const char *path);
+
+static struct PHYSFS_Io*
+SDLRWIoDuplicate(struct PHYSFS_Io *io) {
+ PHYSFS_Io *dup = SDLRWIo_new(get_path(io->opaque));
+ if (dup) SDLRWIoSeek(dup, io->tell(io));
+ return dup;
+}
+
+static void
+SDLRWIoDestroy(struct PHYSFS_Io *io) {
+ SDL_RWclose(get_ops(io->opaque));
+ free(io->opaque);
+ free(io);
+}
+
+static void*
+copy_dynamic(const void *ptr, const size_t size) {
+ void *cpy = malloc(size);
+ memcpy(cpy, ptr, size);
+ return cpy;
+}
+#define copy_static(x) copy_dynamic(&x, sizeof(x))
+
+static PHYSFS_Io*
+SDLRWIo_new(const char *path) {
+ struct io_wrapper wrapper = {
+ .ops = SDL_RWFromFile(path, "r"),
+ .path = path,
+ };
+
+ if (!wrapper.ops)
+ return NULL;
+
+ struct PHYSFS_Io io = {
+ .version = 0,
+ .opaque = copy_static(wrapper),
+ .read = SDLRWIoRead,
+ .write = NULL,
+ .seek = SDLRWIoSeek,
+ .tell = SDLRWIoTell,
+ .length = SDLRWIoLength,
+ .duplicate = SDLRWIoDuplicate,
+ .flush = NULL,
+ .destroy = SDLRWIoDestroy
+ };
+
+ if (!io.opaque) {
+ SDL_RWclose(wrapper.ops);
+ return NULL;
+ }
+
+ return copy_static(io);
+}
+
+static bool
+mount(const char *path, const char *root, bool append) {
+ if (PHYSFS_mount(path, root, append))
+ return true;
+
+ PHYSFS_Io *io = SDLRWIo_new(path);
+ if (!PHYSFS_mountIo(io, path, root, append)) {
+ io->destroy(io);
+ return false;
+ }
+
+ return true;
+}
+
+static const char*
+content_type(struct physfs_serve *serve, const char *path) {
+ if (physfs_ends_with(path, ".rpgmvp")) return "image/png";
+ else if (physfs_ends_with(path, ".rpgmvo")) return "audio/ogg";
+ else if (physfs_ends_with(path, ".rpgmvm")) return "audio/mp4";
+ return physfs_default_content_type(serve, path);
+}
+
+static bool
+path_rewrite(struct physfs_serve *serve, char buf[], const size_t bufsz, struct PHYSFS_Stat *st) {
+ if (physfs_default_path_rewrite(serve, buf, bufsz, st)) return true;
+ if (physfs_ends_with(buf, ".rpgmvm")) {
+ buf[strlen(buf) - 1] = 'o';
+ if (st->filetype == -1 && PHYSFS_stat(buf, st)) return false;
+ } else if (physfs_ends_with(buf, ".rpgmvo")) {
+ buf[strlen(buf) - 1] = 'm';
+ if (st->filetype == -1 && PHYSFS_stat(buf, st)) return false;
+ } else if (physfs_ends_with(buf, ".webm")) {
+ buf[strlen(buf) - 1] = '0';
+ buf[strlen(buf) - 2] = '4';
+ buf[strlen(buf) - 3] = 'p';
+ buf[strlen(buf) - 4] = 'm';
+ if (st->filetype == -1 && PHYSFS_stat(buf, st)) return false;
+ } else if (physfs_ends_with(buf, ".mp4")) {
+ buf[strlen(buf) + 2] = 0;
+ buf[strlen(buf) + 1] = 'm';
+ buf[strlen(buf)] = 'b';
+ buf[strlen(buf) - 1] = 'e';
+ buf[strlen(buf) - 2] = 'w';
+ if (st->filetype == -1 && PHYSFS_stat(buf, st)) return false;
+ }
+ return false;
+}
+
+#define SERVE_INIT .content_type = content_type, .path_rewrite = path_rewrite
+#define PHYSFS_mount mount
+#define main physfs_serve_main
+#include "physfs-serve.c"
+#undef main
+#undef PHYSFS_mount
+#undef SERVE_INIT
+
+#include <SDL.h>
+#include <unistd.h>
+
+int
+main(int argc, char *argv[]) {
+ SDL_Init(0);
+ int ret = physfs_serve_main(argc, argv);
+ SDL_Quit();
+ return ret;
+}