aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Marshall <SquidMan72@gmail.com>2009-01-27 15:26:45 -0800
committerAlex Marshall <SquidMan72@gmail.com>2009-01-27 15:26:45 -0800
commit93a6d0d65a83fb2aa56696534b66f46c4e214940 (patch)
treea26bfcf341f213c1c20bb58d5c67ad71480d6141
Initial commit
-rwxr-xr-xbrlan.h104
-rwxr-xr-xendian.h38
-rw-r--r--main.c317
-rwxr-xr-xtypes.h16
4 files changed, 475 insertions, 0 deletions
diff --git a/brlan.h b/brlan.h
new file mode 100755
index 0000000..d3fe66e
--- /dev/null
+++ b/brlan.h
@@ -0,0 +1,104 @@
+#ifndef BRLAN_H_
+#define BRLAN_H_
+
+#include "types.h"
+
+typedef char fourcc[4];
+
+typedef enum
+{
+ RLPA_ENTRY = 0
+} entry_type;
+
+typedef struct
+{
+ char magic[4]; // "pai1" in ASCII.
+ u32 size; // Size of section, which is rest of the file. (header.file_size - header.offset_pai1)
+ u32 unk1; // Unknown?
+ u16 flags; // Flags?
+ u16 num_entries; // Number of tags in the brlan.
+ u32 unk2; // Only if bit 25 of flags is set.
+ u32 entry_offset; // Offset to entries. (Relative to start of pai1 header.)
+} pai1_header_type2;
+
+typedef struct
+{
+ char magic[4]; // "RLAN" in ASCII.
+ u32 unk1; // Always 0xFEFF 0x0008. Possibly a versioning string.
+ u32 file_size; // Size of whole file, including the header.
+ u16 pai1_offset; // The offset to the pai1 header from the start of file.
+ u16 pai1_count; // How many pai1 sections there are (duh, only 1... wtf?)
+} brlan_header;
+
+typedef struct
+{
+ char magic[4]; // "pai1" in ASCII.
+ u32 size; // Size of section, which is rest of the file. (header.file_size - header.offset_pai1)
+ u32 unk1; // Unknown
+ u16 flags; // Flags
+ u16 num_entries; // Number of tags in the brlan.
+} pai1_universal;
+
+typedef struct
+{
+ char magic[4]; // "pai1" in ASCII.
+ u32 size; // Size of section, which is rest of the file. (header.file_size - header.offset_pai1)
+ u32 unk1; // Unknown?
+ u16 flags; // Flags?
+ u16 num_entries; // Number of tags in the brlan.
+ u32 entry_offset; // Offset to entries. (Relative to start of pai1 header.)
+} pai1_header_type1;
+
+typedef struct
+{
+ char name[20]; // Name of the BRLAN entry. (Must be defined in the BRLYT)
+ u32 flags; // Flags? (If bit 25 is set, we have another u32 after the entry. It's use is unknown.)
+ u32 anim_header_len; // Length of the animation header which is directly after this entry.
+} brlan_entry;
+
+typedef struct
+{
+ char magic[4]; // "RLPA" in ASCII
+ u8 entry_count; // How many entries in this chunk.
+ u8 pad1; // All cases I've seen is zero.
+ u8 pad2; // All cases I've seen is zero.
+ u8 pad3; // All cases I've seen is zero.
+} RLPA_header;
+
+typedef struct
+{
+ u32 offset; // Offset to the data pointed to by this entry.
+ // Relative to the start of the RLPA header.
+} RLPA_entry;
+
+typedef struct
+{
+ u32 flags; // Flags?
+ u16 coord_count; // How many coordinates.
+ u16 pad1; // All cases I've seen is zero.
+ u32 unk1; // ??? In every case I've seen, it is \x00\x00\x00\x0C.
+} RLPA_entryinfo;
+
+typedef struct
+{ // Bits not listed here are currently unknown.
+ u32 part1; // If Bit 9 is set in flags, this is an f32, with a coordinate. (Bit 17 seems to act the same)
+ u32 part2; // If Bit 16 is set in flags, this is an f32, with another coordinate. (Bit 17 seems to act the same)
+ u32 part3; // With Bit 16 set in flags, this seems to be yet another coordinate. (Bit 17 seems to act the same)
+} RLPA_data;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif //BRLAN_H_
+
diff --git a/endian.h b/endian.h
new file mode 100755
index 0000000..4c12e6b
--- /dev/null
+++ b/endian.h
@@ -0,0 +1,38 @@
+#ifndef _ENDIAN_H_
+#define _ENDIAN_H_
+
+#include "types.h"
+
+//#define be16(x) ((x>>8)|(x<<8))
+//#define be32(x) ((x>>24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x<<24))
+//#define be64(x) ((x>>56)|((x<<40)&(u64)0x00FF000000000000)|((x<<24)&(u64)0x0000FF0000000000)|((x<<8)&(u64)0x000000FF00000000)|((x>>8)&(u64)0x00000000FF000000)|((x>>24)&(u64)0x0000000000FF0000)|((x<<40)&(u64)0x000000000000FF00)|(x<<56))
+
+u16 be16(u16 x)
+{
+ return (x>>8) |
+ (x<<8);
+}
+
+u32 be32(u32 x)
+{
+ return (x>>24) |
+ ((x<<8) & 0x00FF0000) |
+ ((x>>8) & 0x0000FF00) |
+ (x<<24);
+}
+
+// __int64 for MSVC, "long long" for gcc
+u64 be64(u64 x)
+{
+ return (x>>56) |
+ ((x<<40) & (u64)0x00FF000000000000) |
+ ((x<<24) & (u64)0x0000FF0000000000) |
+ ((x<<8) & (u64)0x000000FF00000000) |
+ ((x>>8) & (u64)0x00000000FF000000) |
+ ((x>>24) & (u64)0x0000000000FF0000) |
+ ((x>>40) & (u64)0x000000000000FF00) |
+ (x<<56);
+}
+
+#endif //_ENDIAN_H_
+
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..3501fa8
--- /dev/null
+++ b/main.c
@@ -0,0 +1,317 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "brlan.h"
+#include "endian.h"
+
+//#define DEBUGBRLAN
+
+#ifdef DEBUGBRLAN
+#define dbgprintf printf
+#else
+#define dbgprintf //
+#endif //DEBUGBRLAN
+
+char RLPA_FourCC[] = "RLPA";
+
+size_t fileoffset = 0;
+
+void ReadDataFromMemoryX(void* destination, void* input, size_t size)
+{
+ u8* out = (u8*)destination;
+ u8* in = ((u8*)input) + fileoffset;
+ memcpy(out, in, size);
+}
+
+void ReadDataFromMemory(void* destination, void* input, size_t size)
+{
+ ReadDataFromMemoryX(destination, input, size);
+ fileoffset += size;
+}
+
+void CreateGlobal_pai1(pai1_header_type2 *pai1_header, pai1_header_type1 pai1_header1, pai1_header_type2 pai1_header2, int pai1_header_type)
+{
+ if(pai1_header_type == 1) {
+ pai1_header->magic[0] = pai1_header1.magic[0];
+ pai1_header->magic[1] = pai1_header1.magic[1];
+ pai1_header->magic[2] = pai1_header1.magic[2];
+ pai1_header->magic[3] = pai1_header1.magic[3];
+ pai1_header->size = pai1_header1.size;
+ pai1_header->unk1 = pai1_header1.unk1;
+ pai1_header->flags = pai1_header1.flags;
+ pai1_header->num_entries = pai1_header1.num_entries;
+ pai1_header->unk2 = 0;
+ pai1_header->entry_offset = pai1_header1.entry_offset;
+ }else
+ memcpy(pai1_header, &pai1_header2, sizeof(pai1_header_type2));
+}
+
+void DisplayRLPAData(u32 flags, RLPA_data data)
+{
+ u32 p1 = be32(data.part1);
+ u32 p2 = be32(data.part2);
+ u32 p3 = be32(data.part3);
+ if((flags & (1 << 9)) >= 1)
+ printf(" Coordinate 1: %f\n", *(f32*)(&p1));
+ else if((flags & (1 << 17)) >= 1)
+ printf(" Coordinate 1: %f\n", *(f32*)(&p1));
+ else
+ printf(" Part 1: %08x\n", p1);
+ if((flags & (1 << 16)) >= 1)
+ printf(" Coordinate 2: %f\n", *(f32*)(&p2));
+ else if((flags & (1 << 17)) >= 1)
+ printf(" Coordinate 2: %f\n", *(f32*)(&p2));
+ else
+ printf(" Part 2: %08x\n", p2);
+ if((flags & (1 << 16)) >= 1)
+ printf(" Coordinate 3: %f\n", *(f32*)(&p3));
+ else if((flags & (1 << 17)) >= 1)
+ printf(" Coordinate 3: %f\n", *(f32*)(&p3));
+ else
+ printf(" Part 3: %08x\n", p3);
+}
+
+int FourCCsMatch(fourcc cc1, fourcc cc2)
+{
+ if((cc1[0] == cc2[0]) && (cc1[1] == cc2[1]) && (cc1[2] == cc2[2]) && (cc1[3] == cc2[3]))
+ return 1;
+ else
+ return 0;
+}
+
+void DisplayRLPAInformation(int idx, RLPA_header* heads, RLPA_entry** entriesx,
+ RLPA_entryinfo** entryinfosx, RLPA_data*** datasxx)
+{
+ RLPA_header head = heads[idx];
+ RLPA_entry* entries = entriesx[idx];
+ RLPA_entryinfo* entryinfos = entryinfosx[idx];
+ RLPA_data** datas = datasxx[idx];
+
+ printf(" Magic: %c%c%c%c\n", head.magic[0], head.magic[1], head.magic[2], head.magic[3]);
+ printf(" Number of entries: %u\n", head.entry_count);
+ printf(" Unk1: %02x\n", head.pad1);
+ printf(" Unk2: %02x\n", head.pad2);
+ printf(" Unk3: %02x\n", head.pad3);
+ int i, z;
+ printf(" Entries:\n");
+ for(i = 0; i < head.entry_count; i++) {
+ printf(" Index: %u\n", i);
+ printf(" Offset: %lu\n", be32(entries[i].offset));
+ printf(" Flags: %08x\n", be32(entryinfos[i].flags));
+ printf(" Unk1: %04x\n", be16(entryinfos[i].pad1));
+ printf(" Unk2: %08x\n", be32(entryinfos[i].unk1));
+ printf(" Data Count: %u\n", be16(entryinfos[i].coord_count));
+ for(z = 0; z < be16(entryinfos[i].coord_count); z++)
+ DisplayRLPAData(be32(entryinfos[i].flags), datas[i][z]);
+ }
+}
+
+void ReadRLPAFromBRLAN(int idx, u8* brlan_file, RLPA_header *head, RLPA_entry** entries,
+ RLPA_entryinfo** entryinfo, RLPA_data*** data)
+{
+ int rlpahead_location = fileoffset;
+ ReadDataFromMemory(&head[idx], brlan_file, sizeof(RLPA_header));
+ dbgprintf("read header. entry count %d\n", head[idx].entry_count);
+ int i, z;
+ entries[idx] = realloc(entries[idx], sizeof(RLPA_entry) * head[idx].entry_count);
+ dbgprintf("reallocated entries[idx]\n");
+ entryinfo[idx] = realloc(entryinfo[idx], sizeof(RLPA_entryinfo) * head[idx].entry_count);
+ dbgprintf("reallocated entryinfo[idx]\n");
+ if(data[idx] == NULL) {
+ dbgprintf("callocating data[idx]\n");
+ data[idx] = (RLPA_data**)malloc(sizeof(RLPA_data*) * head[idx].entry_count);
+ dbgprintf("callocated data[idx]\n");
+ }else{
+ dbgprintf("reallocating data[idx] %08x\n", data[idx]);
+ data[idx] = (RLPA_data**)realloc(data[idx], sizeof(RLPA_data*) * head[idx].entry_count);
+ dbgprintf("reallocated data[idx]\n");
+ }
+ for(i = 0; i < head[idx].entry_count; i++) {
+ dbgprintf("reading entry %d 0x%08x\n", i, &entries[idx][i]);
+ ReadDataFromMemory(&entries[idx][i], brlan_file, sizeof(RLPA_entry));
+ dbgprintf("read entry.\n");
+ }
+ for(i = 0; i < head[idx].entry_count; i++) {
+ dbgprintf("i %d cnt %d\n", i, head[idx].entry_count);
+ fileoffset = be32(entries[idx][i].offset) + rlpahead_location;
+ dbgprintf("read entry infos. 0x%08x\n", &entryinfo[idx][i]);
+ ReadDataFromMemory(&entryinfo[idx][i], brlan_file, sizeof(RLPA_entryinfo));
+ dbgprintf("read entry info 0x%08x. %u\n", &data[idx][i][0], be16(entryinfo[idx][i].coord_count));
+ data[idx][i] = realloc(NULL, sizeof(RLPA_data) * be16(entryinfo[idx][i].coord_count));
+ dbgprintf("reallocated data[i].\n");
+ for(z = 0; z < be16(entryinfo[idx][i].coord_count); z++) {
+ dbgprintf("reading data 0x%08x\n", &data[idx][i][z]);
+ ReadDataFromMemory(&data[idx][i][z], brlan_file, sizeof(RLPA_data));
+ dbgprintf("read data.\n");
+ }
+ }
+}
+
+void parse_brlan(char* filename)
+{
+ FILE* fp = fopen(filename, "rb");
+ if(fp == NULL) {
+ printf("Error! Couldn't open %s!\n", filename);
+ exit(1);
+ }
+ fseek(fp, 0, SEEK_END);
+ int file_size = ftell(fp);
+ dbgprintf("Filesize is %d\n", file_size);
+ u8* brlan_file = (u8*)malloc(file_size);
+ dbgprintf("brlan_file allocated\n");
+ fseek(fp, 0, SEEK_SET);
+ fread(brlan_file, file_size, 1, fp);
+ dbgprintf("brlan_file read to.\n");
+
+ brlan_header header;
+ ReadDataFromMemoryX(&header, brlan_file, sizeof(brlan_header));
+ dbgprintf("brlan_header read to.\n");
+ fileoffset = be16(header.pai1_offset);
+ pai1_universal universal;
+ ReadDataFromMemoryX(&universal, brlan_file, sizeof(pai1_universal));
+ dbgprintf("pa1_universal read to.\n");
+
+ int pai1_header_type;
+ pai1_header_type1 pai1_header1;
+ pai1_header_type2 pai1_header2;
+ pai1_header_type2 pai1_header;
+
+ if((be32(universal.flags) & (1 << 25)) >= 1) {
+ pai1_header_type = 2;
+ ReadDataFromMemory(&pai1_header2, brlan_file, sizeof(pai1_header_type2));
+ } else {
+ pai1_header_type = 1;
+ ReadDataFromMemory(&pai1_header1, brlan_file, sizeof(pai1_header_type1));
+ }
+ dbgprintf("pai1 headers gotten.\n");
+
+ CreateGlobal_pai1(&pai1_header, pai1_header1, pai1_header2, pai1_header_type);
+ dbgprintf("pai1 global created.\n");
+
+ int tagcount = be16(pai1_header.num_entries);
+ dbgprintf("tagcount done.\n");
+ u32 *taglocations = (u32*)calloc(tagcount, sizeof(u32));
+ dbgprintf("allocated tag locations.\n");
+ fourcc CCs[256];
+ memset(CCs, 0, 256*4);
+ dbgprintf("allocated fourccs.\n");
+ ReadDataFromMemory(taglocations, brlan_file, tagcount * sizeof(u32));
+ dbgprintf("read tag locations.\n");
+ brlan_entry *tag_entries = (brlan_entry*)calloc(tagcount, sizeof(brlan_entry));
+ dbgprintf("tag entries allocated.\n");
+ RLPA_header *RLPA_heads = NULL;
+ dbgprintf("rlpa heads created.\n");
+ RLPA_entry **RLPA_entries = NULL;
+ dbgprintf("rlpa entries created.\n");
+ RLPA_entryinfo **RLPA_entryinfos = NULL;
+ dbgprintf("rlpa entry infos created.\n");
+ RLPA_data ***RLPA_datas = NULL;
+ dbgprintf("rlpa datas created.\n");
+ int RLPA_cnt = 1;
+ int i;
+ for(i = 0; i < tagcount; i++) {
+ fileoffset = be32(taglocations[i]) + be16(header.pai1_offset);
+ dbgprintf("fileoffset set.\n");
+ ReadDataFromMemory(&(tag_entries[i]), brlan_file, sizeof(brlan_entry));
+ dbgprintf("got tag entry.\n");
+ if((be32(tag_entries[i].flags) & (1 << 25)) >= 1) {
+ fileoffset += sizeof(u32);
+ dbgprintf("skipped extra.\n");
+ }
+ u8 magick[4];
+ ReadDataFromMemoryX(magick, brlan_file, 4);
+ memcpy(CCs[i], magick, 4);
+ dbgprintf("read fourcc from %04x %02x%02x%02x%02x.\n", fileoffset, magick[0], magick[1], magick[2], magick[3]);
+ if(FourCCsMatch(RLPA_FourCC, CCs[i]) == 1) {
+ dbgprintf("we found a rlpa.\n");
+ RLPA_heads = realloc(RLPA_heads, sizeof(RLPA_header) * RLPA_cnt);
+ dbgprintf("reallocated rlpa heads.\n");
+ RLPA_entries = realloc(RLPA_entries, sizeof(RLPA_entry) * RLPA_cnt * 20);
+ dbgprintf("reallocated rlpa entries.\n");
+ RLPA_entryinfos = realloc(RLPA_entryinfos, sizeof(RLPA_entryinfo) * RLPA_cnt * 20);
+ dbgprintf("reallocated rlpa entryinfos.\n");
+ RLPA_datas = realloc(RLPA_datas, sizeof(RLPA_data) * RLPA_cnt * 20 * 6);
+ dbgprintf("reallocated rlpa datas.\n");
+ if(RLPA_heads == NULL) {
+ printf("Error allocating heads.\n");
+ exit(2);
+ }
+ if(RLPA_entries == NULL) {
+ printf("Error allocating entries.\n");
+ exit(2);
+ }
+ if(RLPA_entryinfos == NULL) {
+ printf("Error allocating entryinfos.\n");
+ exit(2);
+ }
+ if(RLPA_datas == NULL) {
+ printf("Error allocating datas.\n");
+ exit(2);
+ }
+ ReadRLPAFromBRLAN(RLPA_cnt - 1, brlan_file, RLPA_heads, RLPA_entries,
+ RLPA_entryinfos, RLPA_datas);
+ RLPA_cnt++;
+ }
+ dbgprintf("looping.\n");
+ }
+
+ printf("Parsed BRLAN! Information:\n");
+ printf("Main header:\n");
+ printf(" Magic: %c%c%c%c\n", header.magic[0], header.magic[1], header.magic[2], header.magic[3]);
+ printf(" Filesize: %lu\n", be32(header.file_size));
+ printf(" %s real file size!\n", be32(header.file_size) == file_size ? "Matches" : "Does not match");
+ printf(" pai1 Offset: %04x\n", be16(header.pai1_offset));
+ printf(" pai1 Count: %04x\n", be16(header.pai1_count));
+ printf("\npai1 header:\n");
+ printf(" Type: %d\n", pai1_header_type);
+ printf(" Magic: %c%c%c%c\n", pai1_header.magic[0], pai1_header.magic[1], pai1_header.magic[2], pai1_header.magic[3]);
+ printf(" Size: %lu\n", be32(pai1_header.size));
+ printf(" unk1: %08lx\n", be32(pai1_header.unk1));
+ printf(" Flags: %04x\n", be16(pai1_header.flags));
+ printf(" Number of Entries: %u\n", be16(pai1_header.num_entries));
+ printf(" unk2: %08lx\n", be32(pai1_header.unk2));
+ printf(" Offset to Entries: 0x%08lx\n", be32(pai1_header.entry_offset));
+ printf("\nBRLAN entries:");
+ RLPA_cnt = 0;
+ for(i = 0; i < tagcount; i++) {
+ printf("\n Index: %u\n", i);
+ printf(" Name: %s\n", tag_entries[i].name);
+ printf(" Flags: %08x\n", be32(tag_entries[i].flags));
+ printf(" Animation Header Length: %lu\n", be32(tag_entries[i].anim_header_len));
+ printf(" FourCC: %c%c%c%c\n", CCs[i][0], CCs[i][1], CCs[i][2], CCs[i][3]);
+ if(FourCCsMatch(RLPA_FourCC, CCs[i]) == 1) {
+ dbgprintf("found rlpa. cnt %d.\n", RLPA_cnt);
+ DisplayRLPAInformation(RLPA_cnt, RLPA_heads, RLPA_entries, RLPA_entryinfos, RLPA_datas);
+ RLPA_cnt++;
+ }else{
+ printf(" Sorry, this type is currently unsupported.\n");
+ }
+ }
+ free(brlan_file);
+ fclose(fp);
+}
+
+int main(int argc, char* argv[])
+{
+ parse_brlan(argv[1]);
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/types.h b/types.h
new file mode 100755
index 0000000..4fbc764
--- /dev/null
+++ b/types.h
@@ -0,0 +1,16 @@
+#ifndef __TYPEDEFS_H_
+#define __TYPEDEFS_H_
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+typedef unsigned long long u64;
+typedef signed char s8;
+typedef signed short s16;
+typedef signed long s32;
+typedef signed long long s64;
+
+typedef float f32;
+typedef double f64;
+
+#endif //__TYPEDEFS_H_