commit 3557439489e45dc65b16d38d7824899f996087da Author: Evan Burkey Date: Wed Feb 28 08:10:56 2024 -0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d6b993 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +cmake* +.cache +build +compile_commands.json +test +.idea \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..9572630 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,8 @@ +test: + image: danger89/cmake:latest + script: + - mkdir build + - cd build + - cmake .. + - make + - ./test diff --git a/DOOM1.WAD b/DOOM1.WAD new file mode 100644 index 0000000..1a58f66 Binary files /dev/null and b/DOOM1.WAD differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ab0ced --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# spitWAD + +`spitWAD` is a simple DOOM WAD management library + +`DOOM1.WAD` contained in this repo is the shareware version of DOOM and is used for tests diff --git a/spitwad.c b/spitwad.c new file mode 100644 index 0000000..0193223 --- /dev/null +++ b/spitwad.c @@ -0,0 +1,115 @@ +#include +#include + +#include "spitwad.h" + +static int fail(const char* msg) { + fprintf(stderr, "%s\n", msg); + return 1; +} + +static uint32_t getlong(const unsigned char* data, size_t offset) { + return data[offset] | data[offset + 1] << 8 | data[offset + 2] << 16 | data[offset + 3] << 24; +} + +static uint16_t getshort(const unsigned char* data, size_t offset) { + return data[offset] | data[offset + 1] << 8; +} + +static char* getstring(const unsigned char* data, size_t offset) { + char* s = malloc(sizeof(char) * 9); + strncpy(s, data + offset, 8); + s[8] = '\0'; + return s; +} + +int new_WAD(struct WAD* wad, const unsigned char* data, size_t data_sz) { + if (wad == NULL) { + return fail("Supplied wad to new_WAD was NULL"); + } + + wad->data = malloc(sizeof(unsigned char) * data_sz); + if (wad->data == NULL) { + destroy_WAD(wad); + return fail("Allocation failure for wad->data"); + } + memcpy(wad->data, data, data_sz); + wad->data_sz = data_sz; + + char name[5]; + memcpy(name, data, 4); + name[4] = '\0'; + if (strcmp(name, "IWAD") == 0) { + wad->type = IWAD; + } else if (strcmp(name, "PWAD") == 0) { + wad->type = PWAD; + } else { + destroy_WAD(wad); + return fail("WAD Type was not IWAD or PWAD"); + } + + wad->dir_sz = getlong(data, 4); + wad->dir_offset = getlong(data, 8); + + wad->directory = malloc(sizeof(struct DirEntry) * wad->dir_sz); + if (wad->directory == NULL) { + destroy_WAD(wad); + return fail("Allocation failure for wad->directory"); + } + + for (size_t i = wad->dir_offset, j = 0; i < data_sz; i += 16, ++j) { + wad->directory[j].offset = getlong(data, i); + wad->directory[j].length = getlong(data, i + 4); + + char *s = getstring(data, i + 8); + strcpy(wad->directory[j].name, s); + free(s); + } + + return 0; +} + +int new_WAD_from_file(struct WAD* wad, const char* path) { + if (wad == NULL) { + fprintf(stderr, "Supplied wad to new_WAD_from_file was NULL\n"); + return 0; + } + + FILE *fp = NULL; + fp = fopen(path, "r"); + if (fp == NULL) { + destroy_WAD(wad); + fprintf(stderr, "Failed to open %s. Returning NULL\n", path); + return 1; + } + + fseek(fp, 0, SEEK_END); + size_t fsz = ftell(fp); + rewind(fp); + + unsigned char *buf = NULL; + buf = (unsigned char*)malloc(sizeof(unsigned char) * fsz); + if (buf == NULL) { + destroy_WAD(wad); + fclose(fp); + return fail("Failed to allocate buf in new_WAD_from_file"); + } + + fread(buf, 1, fsz, fp); + fclose(fp); + + new_WAD(wad, buf, fsz); + free(buf); + return 0; +} + +void destroy_WAD(struct WAD* wad) { + free(wad->data); + free(wad->directory); + free(wad); + wad = NULL; +} + +int write_to_file(struct WAD* wad, const char* path) { + +} diff --git a/spitwad.h b/spitwad.h new file mode 100644 index 0000000..f8c126d --- /dev/null +++ b/spitwad.h @@ -0,0 +1,32 @@ +#ifndef SPITWAD_SPITWAD_H +#define SPITWAD_SPITWAD_H + +#include +#include + +enum WAD_Type { + IWAD, + PWAD +}; + +struct DirEntry { + uint32_t offset; + uint32_t length; + char name[9]; +}; + +struct WAD { + enum WAD_Type type; + uint32_t dir_sz; + uint32_t dir_offset; + unsigned char *data; + size_t data_sz; + struct DirEntry *directory; +}; + +int new_WAD(struct WAD* wad, const unsigned char* data, size_t data_sz); +int new_WAD_from_file(struct WAD* wad, const char* path); +void destroy_WAD(struct WAD* wad); +int write_to_file(struct WAD* wad, const char* path); + +#endif //SPITWAD_SPITWAD_H diff --git a/test.c b/test.c new file mode 100644 index 0000000..53accdc --- /dev/null +++ b/test.c @@ -0,0 +1,18 @@ +#include +#include +#include + +#include "spitwad.h" + +int main() { + struct WAD *wad = malloc(sizeof(struct WAD)); + assert(new_WAD_from_file(wad, "DOOM1.WAD") == 0); + + // Values from manually inspecting DOOM1.WAD with a third-party tool + assert(wad->type == IWAD); + assert(wad->dir_sz == 1264); + assert(wad->dir_offset == 4175796); + assert(wad->directory[0].offset == 12); + assert(wad->directory[0].length == 10752); + assert(strcmp(wad->directory[0].name, "PLAYPAL") == 0); +} \ No newline at end of file