Last active
August 29, 2015 14:13
-
-
Save idimiter/8e9c6c987b3862c920eb to your computer and use it in GitHub Desktop.
Reversing tools for Road To El Dorado & In Cold Blood game file formats
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#define MAX_FILENAME 256 | |
typedef struct { | |
char magic[4]; // CLU | |
int version; // 2 | |
int header_size; | |
int count; | |
int hash; | |
int sector_number; // -1 | |
char name[60]; | |
} CLUHeader; | |
typedef struct { | |
int name_offset; | |
int data_size; | |
int data_offset; | |
int hash; | |
} CLUFile; | |
int main(int ac, char** av) { | |
FILE *fp; | |
FILE *out; | |
CLUHeader header; | |
char** filenames; | |
CLUFile *files; | |
void *buf = NULL; | |
int bIsExtracted = 0; | |
if (ac < 2) { | |
printf("Usage: %s [clu filename]\n", av[0]); | |
return 0; | |
} | |
if ( !(fp = fopen(av[1], "rb")) ) { | |
printf("Cannot open file: %s", av[1]); | |
return -1; | |
} | |
fread(&header, sizeof(CLUHeader), 1, fp); | |
printf("%s\n\nMagic: %s\nName: %s\nVersion: %d\nFiles count: %d\n\n", av[1], header.magic, header.name, header.version, header.count); | |
// Allocate memory for filenames | |
filenames = (char **) malloc(header.count * sizeof(char *)); | |
for (int i = 0; i < header.count; i++) | |
filenames[i] = (char *) malloc(MAX_FILENAME); | |
files = (CLUFile *) malloc(header.count * sizeof(CLUFile)); | |
fread(files, sizeof(CLUFile), header.count, fp); | |
for (int i = 0; i < header.count; i++) { | |
fseek(fp, files[i].name_offset, SEEK_SET); | |
fgets(filenames[i], MAX_FILENAME, fp); | |
printf("[%d] %s\n\tSize: %d bytes\n\tHash: %04X\n\tOffset: 0x%08X\n", i, filenames[i], files[i].data_size, files[i].hash, files[i].data_offset); | |
// Extract file data | |
if (!bIsExtracted && ac > 2) { | |
if ( i == atoi(av[2]) ) { | |
// if ( (out = fopen(filenames[i], "wb")) ) { | |
if ( (out = fopen(av[2], "wb")) ) { | |
buf = malloc(files[i].data_size); | |
fseek(fp, files[i].data_offset, SEEK_SET); | |
fread(buf, files[i].data_size, 1, fp); | |
fwrite(buf, files[i].data_size, 1, out); | |
fclose(out); | |
free(buf); | |
bIsExtracted = 1; | |
} | |
} | |
} | |
} | |
fclose(fp); | |
if (ac > 2) { | |
if (bIsExtracted) | |
printf("\nFile %s extacted successfully!\n", filenames[atoi(av[2])]); | |
else | |
printf("\nCould not extact %s!\n", av[2]); | |
} | |
// Memory cleanup | |
for (int i = 0; i < header.count; i++) | |
free(filenames[i]); | |
free(filenames); | |
free(files); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdio.h" | |
#include "stdlib.h" | |
#include "string.h" | |
#define MAX_STRING 1024 | |
typedef struct { | |
int version; // 1 | |
char magic[16]; // LNKT | |
char description[32]; | |
int count; | |
int unknown; // 6 | |
} LNKTHeader; // 60 bytes | |
typedef struct { | |
int start_offset; | |
int offset; | |
int size; | |
int hash; | |
} LNKTEntry; // 16 bytes | |
int main(int ac, char **av) { | |
FILE* fp; | |
LNKTHeader header; | |
LNKTEntry* entries; | |
char buf[MAX_STRING]; | |
if (ac < 2) { | |
printf("Usage: %s <LNKT file>\n", av[0]); | |
return 0; | |
} | |
if (!(fp = fopen(av[1], "rb")) ) { | |
printf("Cannot open: %s!\n", av[1]); | |
return -1; | |
} | |
fread(&header, sizeof(LNKTHeader), 1, fp); | |
printf("%s\n\nVersion: %d\nMagic: %s\nDescription: %s\nCount: %d\n", av[1], header.version, header.magic, header.description, header.count); | |
entries = (LNKTEntry*) calloc(header.count, sizeof(LNKTEntry)); | |
fread(entries, sizeof(LNKTEntry), header.count, fp); | |
for (int i = 0; i < header.count; i++) { | |
fseek(fp, entries[i].offset, SEEK_SET); | |
bzero(buf, MAX_STRING); | |
fread(buf, entries[i].size, 1, fp); | |
printf("[%d]:\n\tUNKNOWN: %04X\n\tOffset: %04X\n\tSize: %d\n\tHash: %04X\n\n%s\n\n==================\n\n", i, entries[i].unknown1, entries[i].offset, entries[i].size, entries[i].hash, buf); | |
} | |
fclose(fp); | |
free(entries); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
int make_hash(const char* s) { | |
int hash = 0; | |
for (int i = 0; i < strlen(s); i++) { | |
hash = s[i] + 131 * hash; | |
} | |
return hash; | |
} | |
int main(int ac, char** av) { | |
if (ac < 2) { | |
printf("Usage: %s <string>\n", av[0]); | |
return 0; | |
} | |
printf("%s: %04X\n", av[1], make_hash(av[1])); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
typedef struct { | |
unsigned char R; | |
unsigned char G; | |
unsigned char B; | |
unsigned char A; | |
} ColMap; | |
typedef struct { | |
char magic[4]; | |
int version; // 1 | |
ColMap pallete[256]; | |
int frames_count; | |
} PCBHeader; | |
typedef struct { | |
int atlas_x; | |
int atlas_y; | |
int width; | |
int height; | |
} PCBFrame; | |
void dumpFile(int offset, FILE *fp, PCBHeader *hdr) { | |
FILE *out; | |
unsigned char *data; | |
PCBFrame frame; | |
char outfile[256]; | |
sprintf(outfile, "out_%08X.ppm", offset); | |
fseek(fp, offset, SEEK_SET); | |
fread(&frame, sizeof(frame), 1, fp); | |
printf(" size: %dx%d u1:%d u2:%d\n", frame.width, frame.height, frame.atlas_x, frame.atlas_y); | |
int dataSize = frame.width * frame.height; | |
data = (unsigned char*) malloc(dataSize); | |
fread(data, dataSize, 1, fp); | |
// Export data to PPM | |
out = fopen(outfile, "wb"); | |
fprintf(out, "P6\n# pcb2ppm\n%d %d\n255\n", frame.width, frame.height); | |
for (int i = 0; i < dataSize; i++) { | |
ColMap color = hdr->pallete[data[i]]; | |
fwrite(&color.B, 1, 1, out); | |
fwrite(&color.G, 1, 1, out); | |
fwrite(&color.R, 1, 1, out); | |
} | |
free(data); | |
fclose(out); | |
} | |
int main(int ac, char** av) { | |
FILE *fp; | |
PCBHeader hdr; | |
int* frame_offsets; | |
if ( ac < 2 ) { | |
printf("Usage: %s [PCB file]\n", av[0]); | |
return 0; | |
} | |
if ( !(fp = fopen(av[1], "rb")) ) { | |
printf("Cannot open [%s]\n", av[1]); | |
return -1; | |
} | |
fread(&hdr, sizeof(PCBHeader), 1, fp); | |
printf("%s\n\nMagic: %s\nVersion: %d\nFrames: %d\n", av[1], hdr.magic, hdr.version, hdr.frames_count); | |
// Read frames offsets | |
frame_offsets = (int *) malloc(hdr.frames_count * sizeof(int)); | |
fread(frame_offsets, sizeof(int), hdr.frames_count, fp); | |
for (int i = 0; i < hdr.frames_count; i++) { | |
printf("Frame [%d]: 0x%08X", i, frame_offsets[i]); | |
dumpFile(frame_offsets[i], fp, &hdr); | |
} | |
free(frame_offsets); | |
fclose(fp); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
typedef struct { | |
unsigned char R; | |
unsigned char G; | |
unsigned char B; | |
unsigned char A; | |
} ColMap; | |
typedef struct { | |
char magic[4]; // RTX | |
int version; // 2 | |
int unknown; // 1 | |
ColMap pallete[256]; | |
int width; | |
int height; | |
int data_offset; // most of the time 256x256 | |
// Those are smaller images of the above all power of two, for the mipmaps | |
int offset1; // 128x128 | |
int offset2; // 64x64 | |
int offset3; // 32x32 | |
int offset4; // 16x16 | |
int offset5; // 8x8 | |
int offset6; // 4x4 | |
int offset7; // 2x2 | |
int offset8; // EOF | |
} RTXHeader; | |
int main(int ac, char** av) { | |
FILE *fp; | |
FILE *out; | |
RTXHeader hdr; | |
int* frame_offsets; | |
unsigned char* data; | |
if ( ac < 2 ) { | |
printf("Usage: %s [RevTex file]\n", av[0]); | |
return 0; | |
} | |
if ( !(fp = fopen(av[1], "rb")) ) { | |
printf("Cannot open [%s]\n", av[1]); | |
return -1; | |
} | |
fread(&hdr, sizeof(RTXHeader), 1, fp); | |
printf("%s\n\nMagic: %s\nVersion: %d\nResolution: %dx%d\n", av[1], hdr.magic, hdr.version, hdr.width, hdr.height); | |
int data_size = hdr.width * hdr.height; | |
printf("First size: %d\n", data_size); | |
fseek(fp, hdr.data_offset, SEEK_SET); | |
data = (unsigned char *) malloc(data_size); | |
fread(data, data_size, 1, fp); | |
fclose(fp); | |
// Export data to PPM | |
out = fopen("RTX_export.ppm", "wb"); | |
fprintf(out, "P6\n# pcb2ppm\n%d %d\n255\n", hdr.width, hdr.height); | |
for (int i = 0; i < data_size; i++) { | |
ColMap color = hdr.pallete[data[i]]; | |
fwrite(&color.B, 1, 1, out); | |
fwrite(&color.G, 1, 1, out); | |
fwrite(&color.R, 1, 1, out); | |
} | |
fclose(out); | |
free(data); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment