stuff/iwad64ex.c

128 lines
2.7 KiB
C

/*
iwad64ex.c : Extracts the embedded IWAD in Hexen 64.
Currently does not decompress the data (or fix the endianness in data).
(C)2019 Marisa the Magician, UnSX Team.
Released under the MIT license.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
typedef struct
{
char sig[4];
uint32_t nlumps;
uint32_t dirpos;
} wad_t;
typedef struct
{
uint32_t filepos, size;
char name[8];
} lump_t;
char *data;
wad_t *wad;
lump_t *lumps;
uint32_t btl( uint32_t b )
{
return ((b>>24)&0xff)|((b<<8)&0xff0000)
|((b>>8)&0xff00)|((b<<24)&0xff000000);
}
int main( int argc, char **argv )
{
if ( argc < 3 )
{
fprintf(stderr,"usage: iwad64ex <romfile> <wadfile>\n");
return 1;
}
FILE *romfile = fopen(argv[1],"rb");
if ( !romfile )
{
fprintf(stderr,"failed to open %s for reading: %s\n",
argv[1],strerror(errno));
return 2;
}
ssize_t fpos = 0;
char buf[4096];
ssize_t found = 0;
while ( !feof(romfile) )
{
memset(buf,0,4096);
int bsiz = fread(buf,1,4096,romfile);
// to avoid GNU-exclusive memmem function I'll just roll out
// my own thing here (fuckin' GNU and their exclusives...)
for ( int i=0; i<bsiz-5; i++ )
{
if ( !memcmp(buf+i,"IWAD",4)
|| !memcmp(buf+i,"PWAD",4) )
{
fpos += i;
found = 1;
break;
}
}
if ( found ) break;
fpos += bsiz;
}
if ( !found )
{
fclose(romfile);
fprintf(stderr,"WAD signature not found in ROM\n");
return 8;
}
printf("Embedded wad found at %#zx\n",fpos);
data = malloc(12);
if ( !data )
{
fclose(romfile);
fprintf(stderr,"cannot allocate 12 bytes for wad header: %s",
strerror(errno));
return 16;
}
fseek(romfile,fpos,SEEK_SET);
fread(data,1,12,romfile);
wad = (wad_t*)data;
// fix endianness
wad->nlumps = btl(wad->nlumps);
wad->dirpos = btl(wad->dirpos);
// reallocate to fit
size_t fullsiz = wad->dirpos+wad->nlumps*16;
data = realloc(data,fullsiz);
wad = (wad_t*)data;
if ( errno )
{
fclose(romfile);
free(data);
fprintf(stderr,"cannot allocate %zd bytes for full wad: %s",
fullsiz,strerror(errno));
return 32;
}
fread(data+12,1,fullsiz-12,romfile);
lumps = (lump_t*)(data+wad->dirpos);
// loop and fix endianness
for ( int i=0; i<wad->nlumps; i++ )
{
lumps[i].filepos = btl(lumps[i].filepos);
lumps[i].size = btl(lumps[i].size);
printf("%.8s %d %d\n",lumps[i].name,lumps[i].size,
lumps[i].filepos);
}
fclose(romfile);
FILE *wadfile = fopen(argv[2],"wb");
if ( !wadfile )
{
fprintf(stderr,"failed to open %s for writing: %s\n",
argv[2],strerror(errno));
return 4;
}
fwrite(data,1,fullsiz,wadfile);
fclose(wadfile);
free(data);
printf("wrote %s, %d bytes\n",argv[2],fullsiz);
return 0;
}