spitwad/spitwad.c

131 lines
3.2 KiB
C

#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);
return s;
}
int new_WAD_from_data(struct WAD* wad, const unsigned char* data, size_t data_sz) {
if (wad == NULL) {
return fail("Supplied wad to new_WAD_from_data 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);
strncpy(wad->directory[j].name, s, 8);
wad->directory[j].name[8] = '\0';
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_from_data(wad, buf, fsz);
free(buf);
return 0;
}
int new_WAD(struct WAD* wad) {
wad->data = NULL;
wad->data_sz = 0;
wad->directory = NULL;
wad->dir_sz = 0;
wad->dir_offset = 0;
}
void destroy_WAD(struct WAD* wad) {
free(wad->data);
free(wad->directory);
free(wad);
}
int write_to_file(struct WAD* wad, const char* path) {
FILE *fp = NULL;
fp = fopen(path, "wb");
if (fp == NULL) {
fprintf(stderr, "Failed to open %s\n", path);
return 1;
}
fwrite(wad->data, sizeof(unsigned char), wad->data_sz, fp);
fclose(fp);
return 0;
}