init
This commit is contained in:
commit
3557439489
|
@ -0,0 +1,6 @@
|
||||||
|
cmake*
|
||||||
|
.cache
|
||||||
|
build
|
||||||
|
compile_commands.json
|
||||||
|
test
|
||||||
|
.idea
|
|
@ -0,0 +1,8 @@
|
||||||
|
test:
|
||||||
|
image: danger89/cmake:latest
|
||||||
|
script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake ..
|
||||||
|
- make
|
||||||
|
- ./test
|
|
@ -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
|
|
@ -0,0 +1,115 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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) {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef SPITWAD_SPITWAD_H
|
||||||
|
#define SPITWAD_SPITWAD_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
Loading…
Reference in New Issue