void ExportModelFormat() { unsigned char *archive_ark; unsigned char *model_chunk; FILE *file = NULL; // File pointer long chunkUnpackedLength = 0; long chunkType = 0;//compression type long chunkPackedLength = 0; if ((file = fopen(SHOCK_MODEL_FILE, "rb")) == NULL) { printf("\nArchive not found!\n"); return; } long fileSize = getFileSize(file); int filepos = ftell(file); archive_ark = new unsigned char[fileSize]; fread(archive_ark, fileSize, 1, file); fclose(file); for (int k = 2300; k <= 2379; k++) { long blockAddress = getShockBlockAddress(k, archive_ark, &chunkPackedLength, &chunkUnpackedLength, &chunkType); if (blockAddress == -1) { return; } model_chunk = new unsigned char[chunkUnpackedLength]; LoadShockChunk(blockAddress, chunkType, archive_ark, model_chunk, chunkPackedLength, chunkUnpackedLength); printf("Header 0 : %d\n", getValAtAddress(model_chunk, 0, 8)); printf("Header 1 : %d\n", getValAtAddress(model_chunk, 1, 8)); printf("Header 2 : %d\n", getValAtAddress(model_chunk, 2, 8)); printf("Header 3 : %d\n", getValAtAddress(model_chunk, 3, 8)); printf("Header 4 : %d\n", getValAtAddress(model_chunk, 4, 8)); printf("Header 5 : %d\n", getValAtAddress(model_chunk, 5, 8)); printf("Header 6 : %d\n", getValAtAddress(model_chunk, 6, 16)); int noFaces = getValAtAddress(model_chunk, 6, 16); long add_ptr = 8; while (add_ptr < chunkUnpackedLength) { switch (getValAtAddress(model_chunk, add_ptr, 16)) { case 0: //End of sub-hull whatever that means default: printf("\n\t%d", getValAtAddress(model_chunk, add_ptr, 16)); add_ptr = add_ptr + 2; } } } }
void unpackStrings(int game) { char filePath[255]; switch (game) { case UWDEMO: case UW1: strcpy_s(filePath, UW1_STRINGS_FILE);break; case UW2: strcpy_s(filePath, UW2_STRINGS_FILE);break; case SHOCK: strcpy_s(filePath, SHOCK_STRINGS_FILE);break; } huffman_node *hman; block_dir *blocks; unsigned char *Buffer; long NoOfNodes; long NoOfStringBlocks; long address_pointer=0; //char *str; FILE *file = NULL; // File pointer //fopen_s(file,filePath, "rb"); if (fopen_s(&file,filePath, "rb") != 0) { printf("Could not open specified file\n"); } else { // Get the size of the file in bytes long fileSize = getFileSize(file); // Allocate space in the buffer for the whole file Buffer = new unsigned char[fileSize]; fread(Buffer, fileSize, 1,file); fclose(file); NoOfNodes=getValAtAddress(Buffer,address_pointer,16); int i=0; hman = new huffman_node [NoOfNodes]; address_pointer=address_pointer+2; while (i<NoOfNodes) { hman[i].symbol= Buffer[address_pointer+0]; hman[i].parent= Buffer[address_pointer+1]; hman[i].left= Buffer[address_pointer+2]; hman[i].right= Buffer[address_pointer+3]; printf("Node:%d parent=%d, left=%d, right=%d, symbol=%c\n",i,hman[i].parent, hman[i].left, hman[i].right, hman[i].symbol); i++; address_pointer=address_pointer+4; } //next is the number of string blocks NoOfStringBlocks=getValAtAddress(Buffer,address_pointer,16); blocks=new block_dir[NoOfStringBlocks]; address_pointer=address_pointer+2; i=0; while (i<NoOfStringBlocks) { blocks[i].block_no = getValAtAddress(Buffer,address_pointer,16); address_pointer=address_pointer+2; blocks[i].address = getValAtAddress(Buffer,address_pointer,32); address_pointer=address_pointer+4; blocks[i].NoOfEntries = getValAtAddress(Buffer,blocks[i].address,16); //look ahead and get no of entries. i++; } i=0; while (i<NoOfStringBlocks) { //printf("Block %d is at address %d. It has %d entries\n",blocks[i].block_no,blocks[i].address, blocks[i].NoOfEntries ); address_pointer=2 + blocks[i].address + blocks[i].NoOfEntries *2; //printf("It's strings begin at %d\n", address_pointer); //printf("It should end at %d\n",blocks[i+1].address ); printf("\n+=====================================+\n"); printf("Block Name: %d\n", blocks[i].block_no); long strAdd; int blnFnd; strAdd= address_pointer; for (int j=0;j< blocks[i].NoOfEntries;j++) { //Based on abysmal /uwadv implementations. blnFnd=0; char c; int bit = 0; int raw = 0; int node=0; do { node = NoOfNodes - 1; // starting node // huffman tree decode loop while (char(hman[node].left) != -1 && char(hman[node].right) != -1) { if (bit == 0) { bit = 8; raw = Buffer[address_pointer++]; //stream.get<uint8_t>(); } // decide which node is next node = raw & 0x80 ? short (hman[node].right) : short (hman[node].left); raw <<= 1; bit--; } // have a new symbol if ((hman[node].symbol !='|') && (hman[node].symbol !=10)){ if (blnFnd==0) //{printf("\nBlock %d String %d at %d:",blocks[i].block_no, j, strAdd); } {printf("\n%03d=",j); } printf("%c",hman[node].symbol); blnFnd = 1; } } while (hman[node].symbol != '|'); } i++; } } }
void unpackStringsShock(char filePath[255]) {//this looks familiar. //long BlockNo; unsigned char *tmp_ark ; long chunkPackedLength; long chunkUnpackedLength; //char *filePath = SHOCK_STRINGS_FILE; FILE *file = NULL; // File pointer if (fopen_s(&file,filePath, "rb") != 0) { printf("Could not open specified file\n"); } else { // Get the size of the file in bytes long fileSize = getFileSize(file); // Allocate space in the tmp_ark for the whole file tmp_ark = new unsigned char[fileSize]; fread(tmp_ark, fileSize, 1,file); fclose(file); int blnLevelFound =0; long DirectoryAddress=getValAtAddress(tmp_ark,124,32); //printf("\nThe directory is at %d\n", DirectoryAddress); long NoOfChunks = getValAtAddress(tmp_ark,DirectoryAddress,16); //printf("there are %d chunks\n",NoOfChunks); long firstChunkAddress = getValAtAddress(tmp_ark,DirectoryAddress+2,32); //printf("The first chunk is at %d\n", firstChunkAddress); long address_pointer=DirectoryAddress+6; long AddressOfBlockStart= firstChunkAddress; for (int k=0; k< NoOfChunks; k++) { long chunkId = getValAtAddress(tmp_ark,address_pointer,16); chunkUnpackedLength =getValAtAddress(tmp_ark,address_pointer+2,24); long chunkType = getValAtAddress(tmp_ark,address_pointer+5,8); chunkPackedLength = getValAtAddress(tmp_ark,address_pointer+6,24); long chunkContentType = getValAtAddress(tmp_ark,address_pointer+9,8); //printf("Index: %d, Chunk %d, Unpack size %d, compression %d, packed size %d, content type %d\t",k,chunkId, chunkUnpackedLength, chunkType,chunkPackedLength,chunkContentType); //printf("Absolute address is %d\n",AddressOfBlockStart); long NoSubChunks = getValAtAddress(tmp_ark,AddressOfBlockStart,16); printf("\nChunk %d has %d sub chunks",k, NoSubChunks); printf("\n+=====================================+\n"); long strPtr=2; for (int i = 0; i<NoSubChunks;i++) { long subChunkStart =AddressOfBlockStart+ getValAtAddress(tmp_ark,AddressOfBlockStart+strPtr,32); long subChunkEnd = AddressOfBlockStart+getValAtAddress(tmp_ark,AddressOfBlockStart+strPtr+4,32); if (subChunkEnd > subChunkStart) { printf("%d = %.*s\n",i, subChunkEnd- subChunkStart, tmp_ark + subChunkStart); } strPtr+=4; } AddressOfBlockStart=AddressOfBlockStart+ chunkPackedLength; if ((AddressOfBlockStart % 4) != 0) AddressOfBlockStart = AddressOfBlockStart + 4 - (AddressOfBlockStart % 4); // chunk offsets always fall on 4-byte boundaries address_pointer=address_pointer+10; } } }
void BuildXDataFile(int game) { int right; int left; //portraits. //this looks familiar. //long BlockNo; unsigned char *tmp_ark; long chunkPackedLength; long chunkUnpackedLength; char *filePath = SHOCK_STRINGS_FILE; FILE *file = NULL; // File pointer if (fopen_s(&file, filePath, "rb") != 0) { printf("Could not open specified file\n"); } else { // Get the size of the file in bytes long fileSize = getFileSize(file); // Allocate space in the tmp_ark for the whole file tmp_ark = new unsigned char[fileSize]; fread(tmp_ark, fileSize, 1, file); fclose(file); int blnLevelFound = 0; long DirectoryAddress = getValAtAddress(tmp_ark, 124, 32); //printf("\nThe directory is at %d\n", DirectoryAddress); long NoOfChunks = getValAtAddress(tmp_ark, DirectoryAddress, 16); //printf("there are %d chunks\n", NoOfChunks); long firstChunkAddress = getValAtAddress(tmp_ark, DirectoryAddress + 2, 32); //printf("The first chunk is at %d\n", firstChunkAddress); long address_pointer = DirectoryAddress + 6; long AddressOfBlockStart = firstChunkAddress; for (int k = 0; k< NoOfChunks; k++) { long chunkId = getValAtAddress(tmp_ark, address_pointer, 16); chunkUnpackedLength = getValAtAddress(tmp_ark, address_pointer + 2, 24); long chunkType = getValAtAddress(tmp_ark, address_pointer + 5, 8); chunkPackedLength = getValAtAddress(tmp_ark, address_pointer + 6, 24); long chunkContentType = getValAtAddress(tmp_ark, address_pointer + 9, 8); long NoSubChunks = getValAtAddress(tmp_ark, AddressOfBlockStart, 16); //printf("\n@Chunk:%d\n{", chunkId); if ((chunkId >= 2441) && (chunkId <= 2621)) {//we have a log. int step = 0; long strPtr = 2; for (int i = 0; i<NoSubChunks; i++) { long subChunkStart = AddressOfBlockStart + getValAtAddress(tmp_ark, AddressOfBlockStart + strPtr, 32); long subChunkEnd = AddressOfBlockStart + getValAtAddress(tmp_ark, AddressOfBlockStart + strPtr + 4, 32); if (subChunkEnd > subChunkStart) { switch (step) { case 0: {//Build the xdata header printf("readables/shock/log_%04d\n\t{\n\tprecache\n",chunkId); printf("\t\"num_pages\" : \"1\"\n"); //Info Line : has the following format : //[event][colour]LeftId[, []RightId] // event : 'iEE' or 't' // EE = Hex Number of Log / eMail to follow immediately // 't' is set for Texts following a 'iEE' Text //colour : 'cCC' // CC = Hex Number of Colour Index in Palette; //only Sender and Subject are drawn in this colour // LeftId, RightId: //decimal subchunk number of left(and right) bitmaps to show; //char *str; char *str; str=new char[subChunkEnd - subChunkStart]; for (int x = 0; x < subChunkEnd - subChunkStart; x++) { str[x] = tmp_ark[subChunkStart + x]; } //sprintf_s(str, "%.*s", subChunkEnd - subChunkStart, tmp_ark + subChunkStart); //The first line defines who appears in the gui //printf(" %.*s\n", subChunkEnd - subChunkStart, tmp_ark + subChunkStart); right=-1; left=-1; parseInfoLine(str, subChunkEnd - subChunkStart, &left, &right); strPtr += 4; step++; break; } case 1: { //Then the title of the document printf("\t\"page1_title\" :\n\t\t{\n"); printf("\t\t\"%.*s\\n\"\n\t\t}", subChunkEnd - subChunkStart, tmp_ark + subChunkStart); strPtr += 4; step++; break; } case 2: { //And then the body printf("\n\t\"page1_body\" :\n\t\t{\n\t\t\""); }//and falls thru default: {//And the body printf("%.*s\\n", subChunkEnd - subChunkStart, tmp_ark + subChunkStart); step++; strPtr += 4; break; } } } } if (step >= 1) { //Finish out the xdata definition printf("\"\n\t\t}\n\t\t\n\t\"gui_page1\" : \"guis/readables/log.gui\"\n"); if (left != -1) { printf("\t\"page1_PortraitLeft\" : \"guis/assets/shock/logs/0040_%04d.tga\"\n", left); } else { printf("\t\"page1_PortraitLeft\" : \"guis/assets/shock/logs/0040_0030.tga\"\n"); } if (right != -1) { printf("\t\"page1_PortraitRight\" : \"guis/assets/shock/logs/0040_%04d.tga\"", right); } else { printf("\t\"page1_PortraitRight\" : \"guis/assets/shock/logs/0040_0030.tga\""); } printf("\n}\n\n"); } } AddressOfBlockStart = AddressOfBlockStart + chunkPackedLength; if ((AddressOfBlockStart % 4) != 0) AddressOfBlockStart = AddressOfBlockStart + 4 - (AddressOfBlockStart % 4); // chunk offsets always fall on 4-byte boundaries address_pointer = address_pointer + 10; } } }
void ExtractConversations(int game) { //UW1&2 //Pulls info outo cnv.ark //At the moment just trying to understand the problems of implementing conversations. FILE *file = NULL; unsigned char *cnv_ark; unsigned char *bab; long fileSize; int add_ptr; int cnv_ptr; if (game != UW1) { return; } if ((file = fopen("c:\\games\\uw1\\save2\\bglobals.dat", "rb")) == NULL) fprintf(LOGFILE, "Could not open specified file\n"); else {//Read in the game globals in the specified save file. fileSize = getFileSize(file); bab = new unsigned char[fileSize]; fread(bab,fileSize,1,file); fclose(file); add_ptr = 0; while (add_ptr < fileSize) { int convSlot = getValAtAddress(bab,add_ptr,16); add_ptr = add_ptr + 2; int convSlotSize = getValAtAddress(bab, add_ptr, 16); //fprintf(LOGFILE,"Slot %d - Size %d\n", convSlot,convSlotSize); for (int k = 0; k < convSlotSize; k++) { add_ptr = add_ptr + 2; //fprintf(LOGFILE, "\tGlobal (%d) %d\n",k, getValAtAddress(bab,add_ptr,16)); } add_ptr = add_ptr + 2; } } if ((file = fopen(UW1_CONVERSATION, "rb")) == NULL) fprintf(LOGFILE,"Could not open specified file\n"); else fprintf(LOGFILE,""); fileSize = getFileSize(file); cnv_ark = new unsigned char[fileSize]; fread(cnv_ark, fileSize, 1, file); fclose(file); fprintf(LOGFILE,"Conversation Header\nNo of Conversations %d", getValAtAddress(cnv_ark, 0, 16)); int noOfConversations = getValAtAddress(cnv_ark, 0, 16); add_ptr = 2; for (int i = 0; i < noOfConversations; i++) { cnv_ptr = getValAtAddress(cnv_ark, add_ptr, 32); if (cnv_ptr != 0) { fprintf(LOGFILE,"\n\t Offset to conversation %d: %d", i, getValAtAddress(cnv_ark, add_ptr, 32)); fprintf(LOGFILE,"\n\t\tConversation Header:"); fprintf(LOGFILE,"\n\t\tUnknown: %d", getValAtAddress(cnv_ark, cnv_ptr + 0, 16)); fprintf(LOGFILE,"\n\t\tUnknown: %d", getValAtAddress(cnv_ark, cnv_ptr + 2, 16)); fprintf(LOGFILE,"\n\t\tCode Size: %d", getValAtAddress(cnv_ark, cnv_ptr + 4, 16)); int codeSize = getValAtAddress(cnv_ark, cnv_ptr + 4, 16); fprintf(LOGFILE,"\n\t\tUnknown: %d", getValAtAddress(cnv_ark, cnv_ptr + 6, 16)); fprintf(LOGFILE,"\n\t\tUnknown: %d", getValAtAddress(cnv_ark, cnv_ptr + 8, 16)); fprintf(LOGFILE,"\n\t\tStrings Block: %d", getValAtAddress(cnv_ark, cnv_ptr + 0xA, 16)); fprintf(LOGFILE,"\n\t\tTalking to: %d", getValAtAddress(cnv_ark, cnv_ptr + 0xA, 16) - 0x0e00 + 16); fprintf(LOGFILE,"\n\t\tNo of Memory slots: %d", getValAtAddress(cnv_ark, cnv_ptr + 0xC, 16)); int NoOfImports = getValAtAddress(cnv_ark, cnv_ptr + 0xE, 16); fprintf(LOGFILE,"\n\t\tNo of imported globals: %d", getValAtAddress(cnv_ark, cnv_ptr + 0xE, 16)); fprintf(LOGFILE,"\n\t\t\tImported Functions List"); int func_ptr = cnv_ptr + 0x10; for (int k = 0; k < NoOfImports; k++) { fprintf(LOGFILE,"\n\n\t\t\tLength of Function Name: %d", getValAtAddress(cnv_ark, func_ptr, 16)); int functionLength = getValAtAddress(cnv_ark, func_ptr, 16); fprintf(LOGFILE,"\n\t\t\tFunction Name:"); for (int j = 0; j < functionLength; j++) { fprintf(LOGFILE,"%c", cnv_ark[func_ptr + 2 + j]); } fprintf(LOGFILE,"\n\t\t\t\tID (imported func) or Memory address (variable): %d", getValAtAddress(cnv_ark, func_ptr + functionLength + 2, 16)); fprintf(LOGFILE,"\n\t\t\t\tUnknown: %d", getValAtAddress(cnv_ark, func_ptr + functionLength + 4, 16)); switch (getValAtAddress(cnv_ark, func_ptr + functionLength + 6, 16))//Import Type { case 0x010F: fprintf(LOGFILE,"\n\t\t\t\tImport Type: Variable"); break; case 0x0111: fprintf(LOGFILE,"\n\t\t\t\tImport Type: Imported Func"); break; default: fprintf(LOGFILE,"\n\t\t\t\tImport Type: Unknown %d", getValAtAddress(cnv_ark, func_ptr + functionLength + 6, 16)); break; } switch (getValAtAddress(cnv_ark, func_ptr + functionLength + 8, 16)) { case 0x000: fprintf(LOGFILE,"\n\t\t\t\tReturn Type: void", getValAtAddress(cnv_ark, func_ptr + functionLength + 8, 16)); break; case 0x129: fprintf(LOGFILE,"\n\t\t\t\tReturn Type: Int", getValAtAddress(cnv_ark, func_ptr + functionLength + 8, 16)); break; case 0x12B: fprintf(LOGFILE,"\n\t\t\t\tReturn Type: String"); break; default: fprintf(LOGFILE,"\n\t\t\t\tReturn Type: Unknown %d", getValAtAddress(cnv_ark, func_ptr + functionLength + 8, 16)); break; } func_ptr = func_ptr + functionLength + 10; } fprintf(LOGFILE,"\n\t\t\t\t\tCode:\n"); for (int z = 0; z<codeSize * 2; z = z + 2) { fprintf(LOGFILE,"\t\t\t\t\t"); int OPCode = getValAtAddress(cnv_ark, func_ptr + z, 16); //fprintf(LOGFILE,"%d,", getValAtAddress(cnv_ark, func_ptr + z, 16)); fprintf(LOGFILE,"%d:",z); switch (OPCode) { case cnv_NOP: fprintf(LOGFILE,"NOP\n"); break; case cnv_OPADD: fprintf(LOGFILE,"OPADD\n"); break; case cnv_OPMUL: fprintf(LOGFILE,"OPMUL\n"); break; case cnv_OPSUB: fprintf(LOGFILE,"OPSUB\n"); break; case cnv_OPDIV: fprintf(LOGFILE,"OPDIV\n"); break; case cnv_OPMOD: fprintf(LOGFILE,"OPMOD\n"); break; case cnv_OPOR: fprintf(LOGFILE,"OPOR\n"); break; case cnv_OPAND: fprintf(LOGFILE,"OPAND\n"); break; case cnv_OPNOT: fprintf(LOGFILE,"OPNOT\n"); break; case cnv_TSTGT: fprintf(LOGFILE,"TSTGT\n"); break; case cnv_TSTGE: fprintf(LOGFILE,"TSTGE\n"); break; case cnv_TSTLT: fprintf(LOGFILE,"TSTLT\n"); break; case cnv_TSTLE: fprintf(LOGFILE,"TSTLE\n"); break; case cnv_TSTEQ: fprintf(LOGFILE,"TSTEQ\n"); break; case cnv_TSTNE: fprintf(LOGFILE,"TSTNE\n"); break; case cnv_JMP: fprintf(LOGFILE,"JMP "); z = z + 2; fprintf(LOGFILE," %d\n", getValAtAddress(cnv_ark, func_ptr + z, 16)); break; case cnv_BEQ: fprintf(LOGFILE,"BEQ "); z = z + 2; fprintf(LOGFILE," %d\n,", getValAtAddress(cnv_ark, func_ptr + z, 16)); break; case cnv_BNE: fprintf(LOGFILE,"BNE "); z = z + 2; fprintf(LOGFILE," %d\n", getValAtAddress(cnv_ark, func_ptr + z, 16)); break; case cnv_BRA: fprintf(LOGFILE,"BRA "); z = z + 2; fprintf(LOGFILE," %d\n", getValAtAddress(cnv_ark, func_ptr + z, 16)); break; case cnv_CALL: fprintf(LOGFILE,"CALL "); z = z + 2; fprintf(LOGFILE," %d\n", getValAtAddress(cnv_ark, func_ptr + z, 16)); break; case cnv_CALLI: fprintf(LOGFILE,"CALLI "); z = z + 2; fprintf(LOGFILE," %d\n", getValAtAddress(cnv_ark, func_ptr + z, 16)); break; case cnv_RET: fprintf(LOGFILE,"RET\n"); break; case cnv_PUSHI: fprintf(LOGFILE,"PUSHI "); z = z + 2; fprintf(LOGFILE," %d\n", getValAtAddress(cnv_ark, func_ptr + z, 16)); break; case cnv_PUSHI_EFF: fprintf(LOGFILE,"PUSHI_EFF "); z = z + 2; fprintf(LOGFILE," %d\n", getValAtAddress(cnv_ark, func_ptr + z, 16)); break; case cnv_POP: fprintf(LOGFILE,"POP\n"); break; case cnv_SWAP: fprintf(LOGFILE,"SWAP\n"); break; case cnv_PUSHBP: fprintf(LOGFILE,"PUSHBP\n"); break; case cnv_POPBP: fprintf(LOGFILE,"POPBP\n"); break; case cnv_SPTOBP: fprintf(LOGFILE,"SPTOBP\n"); break; case cnv_BPTOSP: fprintf(LOGFILE,"BPTOSP\n"); break; case cnv_ADDSP: fprintf(LOGFILE,"ADDSP\n"); break; case cnv_FETCHM: fprintf(LOGFILE,"FETCHM\n"); break; case cnv_STO: fprintf(LOGFILE,"STO\n"); break; case cnv_OFFSET: fprintf(LOGFILE,"OFFSET\n"); break; case cnv_START: fprintf(LOGFILE,"START\n"); break; case cnv_SAVE_REG: fprintf(LOGFILE,"SAVE_REG\n"); break; case cnv_PUSH_REG: fprintf(LOGFILE,"PUSH_REG\n"); break; case cnv_STRCMP: fprintf(LOGFILE,"STRCMP\n"); break; case cnv_EXIT_OP: fprintf(LOGFILE,"EXIT_OP\n"); break; case cnv_SAY_OP: fprintf(LOGFILE,"SAY_OP\n"); break; case cnv_RESPOND_OP: fprintf(LOGFILE,"RESPOND_OP\n"); break; case cnv_OPNEG: fprintf(LOGFILE,"OPNEG\n"); break; } } } else { //fprintf(LOGFILE,"\t (Empty Slot)"); } add_ptr = add_ptr + 4; } }