/* * brlan.c * * * Created by Alex Marshall on 09/01/27. * Copyright 2009 __MyCompanyName__. All rights reserved. * */ #include #include #include #include #include #include "general.h" #include "memfile.h" #include "types.h" #include "brlan.h" #include "xml.h" #if DEBUGBRLAN == 1 #define dbgprintf printf #else #define dbgprintf // #endif //DEBUGBRLAN #define MAXIMUM_TAGS_SIZE (0xf000) #define MAXIMUM_TIMGS_SIZE (0x1000) fourcc tag_FourCCs[] = { "RLPA", "RLTS", "RLVI", "RLVC", "RLMC", "RLTP" }; char tag_types_list[15][24]; static size_t BRLAN_fileoffset = 0; FILE* xmlanout; u8 somethingElseIsSet = 0; u8 somethingIsSet = 0; static void BRLAN_ReadDataFromMemoryX(void* destination, void* input, size_t size) { u8* out = (u8*)destination; u8* in = ((u8*)input) + BRLAN_fileoffset; memcpy(out, in, size); } static void BRLAN_ReadDataFromMemory(void* destination, void* input, size_t size) { BRLAN_ReadDataFromMemoryX(destination, input, size); BRLAN_fileoffset += size; } static void CreateGlobal_pai1(brlan_pai1_header_type2 *pai1_header, brlan_pai1_header_type1 pai1_header1, brlan_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->framesize = pai1_header1.framesize; pai1_header->flags = pai1_header1.flags; pai1_header->unk1 = pai1_header1.unk1; pai1_header->num_timgs = pai1_header1.num_timgs; 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(brlan_pai1_header_type2)); } static 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; } static int FourCCInList(fourcc cc) { int i; for(i = 0; i < 6; i++) if(FourCCsMatch(cc, tag_FourCCs[i])) return 1; return 0; } 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); u32 lengthOfFile = ftell(fp); fseek(fp, 0, SEEK_SET); u8 data[lengthOfFile]; fread(data, lengthOfFile, 1, fp); int i; for(i = 0; i < 16; i++) memset(tag_types_list[i], 0, 24); strcpy(tag_types_list[0], "X Translation"); strcpy(tag_types_list[1], "Y Translation"); strcpy(tag_types_list[2], "Z Translation"); strcpy(tag_types_list[3], "0x03"); strcpy(tag_types_list[4], "0x04"); strcpy(tag_types_list[5], "Angle"); strcpy(tag_types_list[6], "X Zoom"); strcpy(tag_types_list[7], "Y Zoom"); strcpy(tag_types_list[8], "Width"); strcpy(tag_types_list[9], "Height"); strcpy(tag_types_list[10], "0x0A"); strcpy(tag_types_list[11], "0x0B"); strcpy(tag_types_list[12], "0x0C"); strcpy(tag_types_list[13], "0x0D"); strcpy(tag_types_list[14], "0x0E"); strcpy(tag_types_list[15], "0x0F"); BRLAN_fileoffset = 0; brlan_header header; BRLAN_ReadDataFromMemoryX(&header, data, sizeof(brlan_header)); dbgprintf("brlan_header read to.\n"); BRLAN_fileoffset = short_swap_bytes(header.pai1_offset); brlan_pai1_universal universal; BRLAN_ReadDataFromMemoryX(&universal, data, sizeof(brlan_pai1_universal)); dbgprintf("pa1_universal read to.\n"); int pai1_header_type; brlan_pai1_header_type1 pai1_header1; brlan_pai1_header_type2 pai1_header2; brlan_pai1_header_type2 pai1_header; if((be32(universal.flags) & (1 << 25)) >= 1) { pai1_header_type = 2; BRLAN_ReadDataFromMemory(&pai1_header2, data, sizeof(brlan_pai1_header_type2)); } else { pai1_header_type = 1; BRLAN_ReadDataFromMemory(&pai1_header1, data, sizeof(brlan_pai1_header_type1)); } CreateGlobal_pai1(&pai1_header, pai1_header1, pai1_header2, pai1_header_type); printf("\n" \ "\n", short_swap_bytes(pai1_header.framesize), pai1_header.flags); int timgs = short_swap_bytes(pai1_header.num_timgs); printf("Number of TPL files: %d\n", timgs); BRLAN_fileoffset = short_swap_bytes(header.pai1_offset) + sizeof(brlan_pai1_header_type1); if ( pai1_header_type == 2 ) BRLAN_fileoffset += 4; int tableoff = BRLAN_fileoffset; int currtableoff = BRLAN_fileoffset; for(i = 0; i < timgs; i++) { u32 curr_timg_off = 0; BRLAN_ReadDataFromMemory(&curr_timg_off, data, 4); char timgname[256]; memset(timgname, 0, 256); int z = tableoff + be32(curr_timg_off); int o; for(o = 0; data[z] != 0; timgname[o++] = data[z], z++); printf("\t\n", timgname); currtableoff += 4; } int tagcount = short_swap_bytes(pai1_header.num_entries); u32 taglocations[tagcount]; BRLAN_fileoffset = be32(pai1_header.entry_offset) + short_swap_bytes(header.pai1_offset); BRLAN_ReadDataFromMemory(taglocations, data, tagcount * sizeof(u32)); for(i = 0; i < tagcount; i++) { u8 isTriplet = 0; brlan_entry brlanEntry; tag_header tagHeader; tag_entry tagEntry; tag_entryinfo tagEntryInfo; BRLAN_fileoffset = be32(taglocations[i]) + short_swap_bytes(header.pai1_offset); u32 brlanEntryOffset = BRLAN_fileoffset; BRLAN_ReadDataFromMemory(&brlanEntry, data, sizeof(brlan_entry)); u32 offsetToExtras; u32 setOfOffsetsToOthers[2]; if(((be32(brlanEntry.flags) & (1 << 24)) >= 1 ) && ((be32(brlanEntry.flags) & (1<<25)) >=1)) { somethingElseIsSet = 1; BRLAN_ReadDataFromMemory(&setOfOffsetsToOthers[0], data, 4); BRLAN_ReadDataFromMemory(&setOfOffsetsToOthers[1], data, 4); }else if((be32(brlanEntry.flags) & (1 << 25)) >= 1) { somethingIsSet = 1; BRLAN_ReadDataFromMemory(&offsetToExtras, data, 4); } // if (somethingElseIsSet == 1) // { // BRLAN_ReadDataFromMemory(&tagHeader, data, sizeof(tag_header)); // printf("\t\n", be32(brlanEntry.flags)); // } BRLAN_ReadDataFromMemory(&tagHeader, data, sizeof(tag_header)); printf("\t\n", "Normal"); else { printf("format=\"%08x\">\n", be32(brlanEntry.flags)); } u32 startOfEntries = BRLAN_fileoffset; u32 sOE = startOfEntries; u32 j; for (j=0;j\n", tag_types_list[short_swap_bytes(tagEntryInfo.type)]); else printf("\t\t\n", short_swap_bytes(tagEntryInfo.type)); if( tagEntryInfo.unk1 == 0x2) isTriplet = 1; int k; for(k=0;k\n"); printf("\t\t\t\t%.12f\n", *(f32*)(&p1)); printf("\t\t\t\t%.12f\n", *(f32*)(&p2)); printf("\t\t\t\t%.12f\n", *(f32*)(&p3)); printf("\t\t\t\n"); } else { tag_data2 tagData2; memcpy(&tagData2, &data[sOE -8+ be32(tagEntry.offset) + sizeof(tag_entryinfo)+ (k*sizeof(tag_data2))], sizeof(tag_data2)); u32 p1 = be32(tagData2.part1); u16 p2 = short_swap_bytes(tagData2.part2); u16 p3 = short_swap_bytes(tagData2.padding); printf("\t\t\t\n"); printf("\t\t\t\t%.12f\n", *(f32*)(&p1)); printf("\t\t\t\t%04x\n", p2); printf("\t\t\t\t%04x\n", p3); printf("\t\t\t\n"); } } printf("\t\t\n"); isTriplet = 0; } printf("\t\n"); if (somethingIsSet == 1) { tag_header tagHeader; tag_entry tagEntry; tag_entryinfo tagEntryInfo; memcpy(&tagHeader, &data[brlanEntryOffset + be32(offsetToExtras)], sizeof(tag_header)); printf("\t\n", tagHeader.magic[0], tagHeader.magic[1], tagHeader.magic[2], tagHeader.magic[3]); for(j=0;j\n", tag_types_list[short_swap_bytes(tagEntryInfo.type)]); else printf("\t\t\n", short_swap_bytes(tagEntryInfo.type)); if ( tagEntryInfo.unk1 == short_swap_bytes(0x0200) ) isTriplet = 1; int k; for(k=0;k\n"); printf("\t\t\t\t%.12f\n", *(f32*)(&p1)); printf("\t\t\t\t%.12f\n", *(f32*)(&p2)); printf("\t\t\t\t%.12f\n", *(f32*)(&p3)); printf("\t\t\t\n"); } else { tag_data2 tagData2; memcpy(&tagData2, &data[brlanEntryOffset + be32(offsetToExtras) + be32(tagEntry.offset) + sizeof(tag_entryinfo)+ (k*sizeof(tag_data2))], sizeof(tag_data2)); u32 p1 = be32(tagData2.part1); u16 p2 = short_swap_bytes(tagData2.part2); u16 p3 = short_swap_bytes(tagData2.padding); printf("\t\t\t\n"); printf("\t\t\t\t%.12f\n", *(f32*)(&p1)); printf("\t\t\t\t%04x\n", p2); printf("\t\t\t\t%04x\n", p3); printf("\t\t\t\n"); } } printf("\t\t\n"); isTriplet = 0; } printf("\t\n"); } somethingIsSet = 0; } printf("\n"); fclose(fp); } void WriteBRLANTagHeader(tag_header* head, FILE* fp) { fwrite(head, sizeof(tag_header), 1, fp); } void WriteBRLANTagEntries(tag_entry* entry, u8 count, FILE* fp) { tag_entry writeentry; int i; for(i = 0; i < count; i++) { writeentry.offset = be32(entry[i].offset); fwrite(&writeentry, sizeof(tag_entry), 1, fp); } } void WriteBRLANTagEntryinfos(tag_entryinfo entryinfo, FILE* fp) { tag_entryinfo writeentryinfo; writeentryinfo.type = short_swap_bytes(entryinfo.type); writeentryinfo.unk1 = short_swap_bytes(entryinfo.unk1); writeentryinfo.coord_count = short_swap_bytes(entryinfo.coord_count); writeentryinfo.pad1 = short_swap_bytes(entryinfo.pad1); writeentryinfo.unk2 = be32(entryinfo.unk2); fwrite(&writeentryinfo, sizeof(tag_entryinfo), 1, fp); } void WriteBRLANTagData(tag_data* data, u16 count, FILE* fp) { tag_data writedata; int i; for(i = 0; i < count; i++) { writedata.part1 = be32(data[i].part1); writedata.part2 = be32(data[i].part2); writedata.part3 = be32(data[i].part3); fwrite(&writedata, sizeof(tag_data), 1, fp); } } void WriteBRLANEntry(brlan_entry *entr, FILE* fp) { brlan_entry writeentr; memset(writeentr.name, 0, 20); strncpy(writeentr.name, entr->name, 20); writeentr.flags = be32(entr->flags); writeentr.anim_header_len = be32(entr->anim_header_len); fwrite(&writeentr, sizeof(brlan_entry), 1, fp); } u32 create_entries_from_xml(mxml_node_t *tree, mxml_node_t *node, brlan_entry *entr, tag_header* head, u8** tagblob, u32* blobsize) { tag_entry* entry = NULL; tag_entryinfo* entryinfo = NULL; tag_data** data = NULL; tag_data2** data2 = NULL; mxml_node_t *tempnode = NULL; mxml_node_t *subnode = NULL; mxml_node_t *subsubnode = NULL; char temp[256]; char temp2[256]; char temp3[16][24]; int i, x; for(i = 0; i < 16; i++) memset(temp3[i], 0, 24); for(x = 0; x < 16; x++) for(i = 0; i < strlen(tag_types_list[x]); i++) temp3[x][i] = toupper(tag_types_list[x][i]); head->entry_count = 0; subnode = node; for (x = 0, subnode = mxmlFindElement(subnode, node, "entry", NULL, NULL, MXML_DESCEND); subnode != NULL; subnode = mxmlFindElement(subnode, node, "entry", NULL, NULL, MXML_DESCEND), x++) { head->entry_count++; entry = realloc(entry, sizeof(tag_entry) * head->entry_count); entryinfo = realloc(entryinfo, sizeof(tag_entryinfo) * head->entry_count); if(data == NULL) { data = (tag_data**)malloc(sizeof(tag_data*) * head->entry_count); data2 = (tag_data2**)malloc(sizeof(tag_data2*) * head->entry_count); } else { data = (tag_data**)realloc(data, sizeof(tag_data*) * head->entry_count); data2 = (tag_data2**)realloc(data, sizeof(tag_data2*) * head->entry_count); } data[x] = NULL; data2[x] = NULL; memset(temp, 0, 256); memset(temp2, 0, 256); if(mxmlElementGetAttr(subnode, "type") != NULL) strcpy(temp, mxmlElementGetAttr(subnode, "type")); else{ printf("No type attribute found!\nSkipping this entry!\n"); head->entry_count--; continue; } for(i = 0; i < strlen(temp); i++) temp2[i] = toupper(temp[i]); for(i = 0; (i < 17) && (strcmp(temp3[i - 1], temp2) != 0); i++); if(i == 17) { i = atoi(temp2); } else { i--; } entry[x].offset = 0; entryinfo[x].type = i; entryinfo[x].unk1 = 0x0200; entryinfo[x].pad1 = 0x0000; entryinfo[x].unk2 = 0x0000000C; entryinfo[x].coord_count = 0; subsubnode = subnode; for (i = 0, subsubnode = mxmlFindElement(subsubnode, subnode, "triplet", NULL, NULL, MXML_DESCEND); subsubnode != NULL; subsubnode = mxmlFindElement(subsubnode, subnode, "triplet", NULL, NULL, MXML_DESCEND), i++) { entryinfo[x].coord_count++; data[x] = realloc(data[x], sizeof(tag_data) * entryinfo[x].coord_count); tempnode = mxmlFindElement(subsubnode, subsubnode, "frame", NULL, NULL, MXML_DESCEND); if(tempnode == NULL) { printf("Couldn't find attribute \"frame\"!\n"); exit(1); } get_value(tempnode, temp, 256); *(f32*)(&(data[x][i].part1)) = atof(temp); tempnode = mxmlFindElement(subsubnode, subsubnode, "value", NULL, NULL, MXML_DESCEND); if(tempnode == NULL) { printf("Couldn't find attribute \"value\"!\n"); exit(1); } get_value(tempnode, temp, 256); *(f32*)(&(data[x][i].part2)) = atof(temp); tempnode = mxmlFindElement(subsubnode, subsubnode, "blend", NULL, NULL, MXML_DESCEND); if(tempnode == NULL) { printf("Couldn't find attribute \"blend\"!\n"); exit(1); } get_value(tempnode, temp, 256); *(f32*)(&(data[x][i].part3)) = atof(temp); } for (i = 0, subsubnode = mxmlFindElement(subnode, subnode, "pair", NULL, NULL, MXML_DESCEND); subsubnode != NULL; subsubnode = mxmlFindElement(subsubnode, subnode, "pair", NULL, NULL, MXML_DESCEND), i++) { entryinfo[x].unk1 = 0x100; entryinfo[x].coord_count++; data2[x] = realloc(data2[x], sizeof(tag_data2) * entryinfo[x].coord_count); tempnode = mxmlFindElement(subsubnode, subsubnode, "data1", NULL, NULL, MXML_DESCEND); if(tempnode == NULL) { printf("Couldn't find attribute \"data1\"!\n"); exit(1); } get_value(tempnode, temp, 256); *(f32*)(&(data2[x][i].part1)) = atof(temp); tempnode = mxmlFindElement(subsubnode, subsubnode, "data2", NULL, NULL, MXML_DESCEND); if(tempnode == NULL) { printf("Couldn't find attribute \"data2\"!\n"); exit(1); } get_value(tempnode, temp, 256); data2[x][i].part2 = short_swap_bytes(strtoul(temp, NULL, 16)); tempnode = mxmlFindElement(subsubnode, subsubnode, "padding", NULL, NULL, MXML_DESCEND); if(tempnode == NULL) { printf("Couldn't find attribute \"padding\"!\n"); exit(1); } get_value(tempnode, temp, 256); data2[x][i].padding = short_swap_bytes(strtoul(temp, NULL, 16)); } } FILE* fp = fopen("temp.blan", "wb+"); if(fp == NULL) { printf("Couldn't open temporary temp.blan file\n"); exit(1); } fseek(fp, 0, SEEK_SET); entr->anim_header_len = 0; WriteBRLANEntry(entr, fp); u32 fillerIntOffset = ftell(fp); u32 fillerInt = be32(0x60); if (entr->flags & 0x02000000) { fillerInt = be32(0x60); fwrite(&fillerInt, sizeof(u32), 1, fp); BRLAN_fileoffset += 4; } WriteBRLANTagHeader(head, fp); u32 entryloc = ftell(fp); u32 animLen; WriteBRLANTagEntries(entry, head->entry_count, fp); u32* entryinfolocs = (u32*)calloc(head->entry_count, sizeof(u32)); for(x = 0; x < head->entry_count; x++) { entryinfolocs[x] = ftell(fp); if (x>0) { if ( entryinfo[x].unk1 == (0x200) ) { entry[x].offset = entry[x-1].offset + sizeof(tag_entryinfo) + (entryinfo[x-1].coord_count * sizeof(tag_data)); } if ( entryinfo[x].unk1 == (0x100) ) { entry[x].offset = entry[x-1].offset + sizeof(tag_entryinfo) + (entryinfo[x-1].coord_count * sizeof(tag_data2)); } } else { entry[x].offset = x * (sizeof(tag_entryinfo) + sizeof(tag_data)); } WriteBRLANTagEntryinfos(entryinfo[x], fp); if (x==0) animLen = ftell(fp); if ( entryinfo[x].unk1 == 0x200 ) WriteBRLANTagData(data[x], entryinfo[x].coord_count, fp); if ( entryinfo[x].unk1 == 0x100 ) { tag_data2 writedata; int i; for(i = 0; i < entryinfo[x].coord_count; i++) { writedata.part1 = be32(data2[x][i].part1); writedata.part2 = (data2[x][i].part2); writedata.padding = (data2[x][i].padding); fwrite(&writedata, sizeof(tag_data2), 1, fp); } } } if ( entryinfo[0].unk1 == 0x200 ) free(data); if ( entryinfo[0].unk1 == 0x100 ) free(data2); u32 oldpos = ftell(fp); fseek(fp, entryloc, SEEK_SET); for(x=0;xentry_count;x++) entry[x].offset += sizeof(u32) * (head->entry_count) + 8; WriteBRLANTagEntries(entry, head->entry_count, fp); fseek(fp, oldpos, SEEK_SET); u32 filesz = ftell(fp); fseek(fp, 0, SEEK_SET); entr->anim_header_len = sizeof(brlan_entry); if (entr->flags & 0x02000000) { entr->anim_header_len += 4; u32 tempOffset = ftell(fp); fillerInt = be32(filesz); fseek(fp, fillerIntOffset, SEEK_SET); fwrite(&fillerInt, sizeof(u32), 1, fp); fseek(fp, tempOffset, SEEK_SET); } WriteBRLANEntry(entr, fp); mxml_node_t *addonnode = NULL; mxml_node_t *addonsubnode = NULL; mxml_node_t *addonsubsubnode = NULL; tag_header addonTagHeader; tag_entry addonTagEntry[256]; tag_entryinfo addonTagEntryInfo[256]; tag_data *addonTagData[1024]; tag_data2 *addonTagData2[1024]; char tempChar[256]; if(entr->flags & 0x02000000) { addonnode = mxmlFindElement(node, tree, "extratag", NULL, NULL, MXML_DESCEND); if (addonnode != NULL) { if(mxmlElementGetAttr(addonnode, "type") != NULL) strcpy(temp, mxmlElementGetAttr(addonnode, "type")); else{ printf("No type attribute found!\nSkipping this entry!\n"); } memcpy(addonTagHeader.magic, temp, 4); addonTagHeader.entry_count = 0x00; addonTagHeader.pad1 = 0x0; addonTagHeader.pad2 = 0x0; addonTagHeader.pad3 = 0x0; fseek(fp, oldpos, SEEK_SET); fwrite(&addonTagHeader, sizeof(tag_header), 1, fp); mxml_node_t *entrynode; for(entrynode = mxmlFindElement(addonnode, addonnode, "entry", NULL, NULL, MXML_DESCEND); entrynode != NULL; entrynode = mxmlFindElement(entrynode, addonnode, "entry", NULL, NULL, MXML_DESCEND)) { memset(temp, 0, 256); memset(temp2, 0, 256); if(mxmlElementGetAttr(entrynode, "type") != NULL) strcpy(temp, mxmlElementGetAttr(entrynode, "type")); else{ printf("No type attribute found!\nSkipping this entry!\n"); head->entry_count--; } for(i = 0; i < strlen(temp); i++) temp2[i] = toupper(temp[i]); for(i = 0; (i < 17) && (strcmp(temp3[i - 1], temp2) != 0); i++); if(i == 17) i = atoi(temp2); else i--; addonTagEntryInfo[addonTagHeader.entry_count].type = short_swap_bytes(i); addonTagEntryInfo[addonTagHeader.entry_count].unk1 = short_swap_bytes(0x0200); addonTagEntryInfo[addonTagHeader.entry_count].pad1 = 0x0000; addonTagEntryInfo[addonTagHeader.entry_count].unk2 = be32(0x0000000C); addonTagEntryInfo[addonTagHeader.entry_count].coord_count = 0x0; for(addonsubnode = mxmlFindElement(entrynode, entrynode, "triplet", NULL, NULL, MXML_DESCEND); addonsubnode != NULL; addonsubnode = mxmlFindElement(addonsubnode, entrynode, "triplet", NULL, NULL, MXML_DESCEND)) { addonTagEntryInfo[addonTagHeader.entry_count].unk1 = short_swap_bytes(0x0200); addonTagEntryInfo[addonTagHeader.entry_count].coord_count += 1; u32 tC = addonTagEntryInfo[addonTagHeader.entry_count].coord_count; addonTagData[addonTagHeader.entry_count] = realloc(addonTagData[addonTagHeader.entry_count], sizeof(tag_data) * tC); // S E R I O U S H E L P N E E D E D // addonsubsubnode = mxmlFindElement(addonsubnode, addonsubnode, "frame", NULL, NULL, MXML_DESCEND); if (addonsubsubnode != NULL) { get_value(addonsubsubnode, tempChar, 256); f32 f1 = atof(tempChar); addonTagData[addonTagHeader.entry_count][tC-1].part1 = *(u32*)&f1; addonTagData[addonTagHeader.entry_count][tC-1].part1 = int_swap_bytes(addonTagData[addonTagHeader.entry_count][tC-1].part1); } addonsubsubnode = mxmlFindElement(addonsubnode, addonsubnode, "value", NULL, NULL, MXML_DESCEND); if (addonsubsubnode != NULL) { get_value(addonsubsubnode, tempChar, 256); f32 f2 = atof(tempChar); addonTagData[addonTagHeader.entry_count][tC-1].part2 = *(u32*)&f2; addonTagData[addonTagHeader.entry_count][tC-1].part2 = int_swap_bytes(addonTagData[addonTagHeader.entry_count][tC-1].part2); } addonsubsubnode = mxmlFindElement(addonsubnode, addonsubnode, "blend", NULL, NULL, MXML_DESCEND); if(addonsubsubnode != NULL) { get_value(addonsubsubnode, tempChar, 256); f32 f3 = atof(tempChar); addonTagData[addonTagHeader.entry_count][tC-1].part3 = *(u32*)&f3; addonTagData[addonTagHeader.entry_count][tC-1].part3 = int_swap_bytes(addonTagData[addonTagHeader.entry_count][tC-1].part3); } } for(addonsubnode = mxmlFindElement(entrynode, entrynode, "pair", NULL, NULL, MXML_DESCEND); addonsubnode != NULL; addonsubnode = mxmlFindElement(addonsubnode, entrynode, "pair", NULL, NULL, MXML_DESCEND)) { addonTagEntryInfo[addonTagHeader.entry_count].unk1 = short_swap_bytes(0x0100); addonTagEntryInfo[addonTagHeader.entry_count].coord_count +=1; u32 tC = addonTagEntryInfo[addonTagHeader.entry_count].coord_count; addonTagData2[addonTagHeader.entry_count] = realloc(addonTagData2[addonTagHeader.entry_count], sizeof(tag_data2) * tC); addonsubsubnode = mxmlFindElement(addonsubnode, addonsubnode, "data1", NULL, NULL, MXML_DESCEND); if (addonsubsubnode != NULL) { get_value(addonsubsubnode, tempChar, 256); f32 f1 = atof(tempChar); addonTagData2[addonTagHeader.entry_count][tC-1].part1 = *(u32*)&f1; addonTagData2[addonTagHeader.entry_count][tC-1].part1 = int_swap_bytes(addonTagData2[addonTagHeader.entry_count][tC-1].part1); } addonsubsubnode = mxmlFindElement(addonsubnode, addonsubnode, "data2", NULL, NULL, MXML_DESCEND); if (addonsubsubnode != NULL) { get_value(addonsubsubnode, tempChar, 256); addonTagData2[addonTagHeader.entry_count][tC-1].part2 = short_swap_bytes((short)strtoul(tempChar, NULL, 16)); } addonsubsubnode = mxmlFindElement(addonsubnode, addonsubnode, "padding", NULL, NULL, MXML_DESCEND); if(addonsubsubnode != NULL) { get_value(addonsubsubnode, tempChar, 256); addonTagData2[addonTagHeader.entry_count][tC-1].padding = short_swap_bytes((short)strtoul(tempChar, NULL, 16)); } } u32 eC = addonTagHeader.entry_count; u32 cC = addonTagEntryInfo[eC].coord_count; if (addonTagHeader.entry_count > 0) { cC = short_swap_bytes(addonTagEntryInfo[eC-1].coord_count); printf("cC: %08x\n", cC); } addonTagEntry[addonTagHeader.entry_count].offset = sizeof(tag_header); if (addonTagHeader.entry_count > 0) { if (addonTagEntryInfo[eC-1].unk1 == 0x2) { addonTagEntry[addonTagHeader.entry_count].offset = addonTagEntry[addonTagHeader.entry_count-1].offset + sizeof(tag_entryinfo) + (sizeof(tag_data) * cC); } if (addonTagEntryInfo[eC-1].unk1 == 0x1) { addonTagEntry[addonTagHeader.entry_count].offset = addonTagEntry[addonTagHeader.entry_count-1].offset + sizeof(tag_entryinfo) + (sizeof(tag_data2) * cC); } } addonTagEntryInfo[eC].coord_count = short_swap_bytes(addonTagEntryInfo[eC].coord_count); addonTagHeader.entry_count++; } fseek(fp, oldpos, SEEK_SET); fwrite(&addonTagHeader, sizeof(tag_header), 1, fp); int l; for (l=0;l