diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2021-07-03 00:49:03 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2022-03-30 08:20:20 +0200 |
| commit | 6b9f686913efc3725b2690033cd4f398e07076ba (patch) | |
| tree | e9aa91a6b9f617d78123ebe7ad272fc42a60d306 /src/container | |
| parent | c9e6ae44a9aeb89b3f48f3443d6baa80103f7445 (diff) | |
| download | jancity-6b9f686913efc3725b2690033cd4f398e07076ba.tar.gz | |
Add project source code
Diffstat (limited to 'src/container')
| -rw-r--r-- | src/container/CMakeLists.txt | 11 | ||||
| -rw-r--r-- | src/container/inc/container.h | 43 | ||||
| -rw-r--r-- | src/container/ps1/inc/container/port.h | 6 | ||||
| -rw-r--r-- | src/container/sdl-1.2/inc/container/port.h | 6 | ||||
| -rw-r--r-- | src/container/src/container.c | 225 |
5 files changed, 291 insertions, 0 deletions
diff --git a/src/container/CMakeLists.txt b/src/container/CMakeLists.txt new file mode 100644 index 0000000..740fe37 --- /dev/null +++ b/src/container/CMakeLists.txt @@ -0,0 +1,11 @@ +set(inc "inc") + +if(PS1_BUILD) + set(inc ${inc} "ps1/inc") +elseif(SDL1_2_BUILD) + set(inc ${inc} "sdl-1.2/inc") +endif() + +add_library(container "src/container.c") +target_include_directories(container PUBLIC ${inc}) +target_link_libraries(container PUBLIC gfx sfx) diff --git a/src/container/inc/container.h b/src/container/inc/container.h new file mode 100644 index 0000000..59ab5fd --- /dev/null +++ b/src/container/inc/container.h @@ -0,0 +1,43 @@ +#ifndef CONTAINER_H +#define CONTAINER_H + +#include <container/port.h> +#include <gfx.h> +#include <sfx.h> +#include <stddef.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct container +{ + const char *path; + + enum + { + CONTAINER_TYPE_SPRITE, + CONTAINER_TYPE_SOUND + } type; + + union + { + struct sprite *sprite; + struct sound *sound; + } data; + + struct container_rt + { + struct container *c; + } *rt; +}; + +int container_load_ex(const char *path, const struct container *list, size_t n); +void container_free(const struct container *list, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* CONTAINER_H */ diff --git a/src/container/ps1/inc/container/port.h b/src/container/ps1/inc/container/port.h new file mode 100644 index 0000000..aaf2f96 --- /dev/null +++ b/src/container/ps1/inc/container/port.h @@ -0,0 +1,6 @@ +#ifndef CONTAINER_PS1_H +#define CONTAINER_PS1_H + +#define container_load(path, list, n) container_load_ex("cdrom:\\"path";1", list, n) + +#endif /* CONTAINER_PS1_H */ diff --git a/src/container/sdl-1.2/inc/container/port.h b/src/container/sdl-1.2/inc/container/port.h new file mode 100644 index 0000000..b58697d --- /dev/null +++ b/src/container/sdl-1.2/inc/container/port.h @@ -0,0 +1,6 @@ +#ifndef CONTAINER_SDL_12_H +#define CONTAINER_SDL_12_H + +#define container_load(path, list, n) container_load_ex(path, list, n) + +#endif /* CONTAINER_SDL_12_H */ diff --git a/src/container/src/container.c b/src/container/src/container.c new file mode 100644 index 0000000..008ca58 --- /dev/null +++ b/src/container/src/container.c @@ -0,0 +1,225 @@ +#include <container.h> +#include <gfx.h> +#include <sfx.h> +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static int readstr(char *const str, const size_t n, FILE *const f) +{ + int ret = -1; + size_t i = 0; + + do + { + if (i >= n) + { + fprintf(stderr, "%s: string too long (> %zu bytes): %*.s\n", + __func__, n, (int)n, str); + goto end; + } + else if (!fread(&str[i], sizeof *str, 1, f)) + { + fprintf(stderr, "%s: expected null-terminated string\n", __func__); + goto end; + } + } while (str[i++]); + + ret = 0; + +end: + return ret; +} + +static int get_file_size(size_t *const sz, FILE *const f) +{ + char szstr[sizeof "2147483647"]; + + if (readstr(szstr, sizeof szstr, f)) + return -1; + + errno = 0; + const unsigned long val = strtoul(szstr, NULL, 10); + + if (errno) + { + fprintf(stderr, "%s: strtoul(3): %s\n", __func__, strerror(errno)); + return -1; + } + + *sz = val; + return 0; +} + +static int read_file_contents(const struct container *const el, FILE *const f, + const long init_off, const size_t sz) +{ + int ret = -1; + + switch (el->type) + { + case CONTAINER_TYPE_SPRITE: + if (sprite_from_fp(el->data.sprite, f)) + goto end; + + break; + + case CONTAINER_TYPE_SOUND: + if (sfx_sound_from_fp(el->data.sound, f)) + goto end; + + break; + } + + const long off = ftell(f); + + if (off < 0) + { + fprintf(stderr, "%s:%d: fseek failed: %s\n", + __func__, __LINE__, strerror(errno)); + goto end; + } + else if (off > init_off + sz) + { + fprintf(stderr, "%s: %s: detected read past file contents\n", + __func__, el->path); + goto end; + } + else if (off != init_off + sz) + { + fprintf(stderr, "only %ld bytes read, %ld expected\n", + off, init_off + sz); + goto end; + } + + ret = 0; + +end: + return ret; +} + +static const struct container *find_element(const struct container *const list, + const size_t n, FILE *const f) +{ + char name[128]; + + if (readstr(name, sizeof name, f)) + return NULL; + + for (size_t i = 0; i < n; i++) + { + const struct container *const el = &list[i]; + + if (!strcmp(el->path, name)) + return el; + } + + fprintf(stderr, "file %s not found on the list\n", name); + return NULL; +} + +static int read_element(const struct container *const list, const size_t n, + FILE *const f, bool *const done) +{ + int ret = -1; + long init_off; + const struct container *el = NULL; + size_t sz; + + if (!(el = find_element(list, n, f))) + goto end; + else if (get_file_size(&sz, f)) + goto end; + else if ((init_off = ftell(f)) < 0) + { + fprintf(stderr, "%s:%d: fseek failed: %s\n", + __func__, __LINE__, strerror(errno)); + goto end; + } + else if (read_file_contents(el, f, init_off, sz)) + goto end; + + done[el - list] = true; + ret = 0; + +end: + return ret; +} + +static int read_all_elements(const struct container *const list, const size_t n, + FILE *const f) +{ + int ret = -1; + /* VLAs are generally frowned upon, but we can safely assume + * 'n' is reasonably low. */ + bool done[n]; + + memset(&done, 0, sizeof done); + + for (size_t i = 0; i < sizeof done / sizeof *done; i++) + if (feof(f) || ferror(f) + || read_element(list, n, f, done)) + goto end; + + for (size_t i = 0; i < sizeof done / sizeof *done; i++) + { + if (!done[i]) + { + fprintf(stderr, "%s: %s not found inside container file\n", + __func__, list[i].path); + goto end; + } + } + + ret = 0; + +end: + return ret; +} + +void container_free(const struct container *const list, const size_t n) +{ + if (!list) + return; + + for (size_t i = 0; i < n; i++) + { + const struct container *const el = &list[i]; + + switch (el->type) + { + case CONTAINER_TYPE_SPRITE: + sprite_free(el->data.sprite); + break; + + case CONTAINER_TYPE_SOUND: + sfx_free(el->data.sound); + break; + } + } +} + +int container_load_ex(const char *const path, const struct container *const list, + const size_t n) +{ + int ret = -1; + FILE *f = NULL; + + if (!(f = fopen(path, "rb"))) + { + fprintf(stderr, "could not open %s: %s\n", path, strerror(errno)); + goto end; + } + else if (read_all_elements(list, n, f)) + goto end; + + ret = 0; + +end: + if (f) + fclose(f); + + return ret; +} |
