#include #include #include typedef unsigned int uint32; typedef unsigned short uint16; typedef unsigned char uint8 ; typedef uint8* buffer; char PADDING[] = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA}; #define MD34_TAG 0x4d443334 #define MODL_TAG 0x4d4f444c #define VEC2_TAG 0x56454332 #define VEC3_TAG 0x56454333 #define VEC4_TAG 0x56454334 #define QUAT_TAG 0x51554154 #define COL__TAG 0x434f4c5f #define FLAG_TAG 0x464c4147 #define BNDS_TAG 0x424e4453 #define SVC3_TAG 0x53564333 #define REAL_TAG 0x5245414c #define CHAR_TAG 0x43484152 #define U8___TAG 0x55385f5f #define I16__TAG 0x4931365f #define U16__TAG 0x5531365f #define I32__TAG 0x4933325f #define U32__TAG 0x5533325f #define IREF_TAG 0x49524546 #define EVNT_TAG 0x45564e54 #define SDEV_TAG 0x53444556 #define SD2V_TAG 0x53443256 #define SD3V_TAG 0x53443356 #define SDR3_TAG 0x53445233 #define SDCC_TAG 0x53444343 #define SDS6_TAG 0x53445336 #define SDU6_TAG 0x53445536 #define SD4Q_TAG 0x53443451 #define SDFG_TAG 0x53444647 #define SDMB_TAG 0x53444d42 #define BONE_TAG 0x424f4e45 #define STC__TAG 0x5354435f #define STS__TAG 0x5354535f #define REGN_TAG 0x5245474e #define BAT__TAG 0x4241545f #define MSEC_TAG 0x4d534543 #define DIV__TAG 0x4449565f #define ATT__TAG 0x4154545f #define LITE_TAG 0x4c495445 #define MATM_TAG 0x4d41544d #define PATU_TAG 0x50415455 #define TRGD_TAG 0x54524744 #define LAYR_TAG 0x4c415952 #define MAT__TAG 0x4d41545f #define DIS__TAG 0x4449535f #define CMS__TAG 0x434d535f #define CMP__TAG 0x434d505f #define TER__TAG 0x5445525f #define VOL__TAG 0x564f4c5f #define VON__TAG 0x564f4e5f #define CREP_TAG 0x43524550 #define SCHR_TAG 0x53434852 #define STBM_TAG 0x5354424d #define PAR__TAG 0x5041525f #define PARC_TAG 0x50415243 #define PROJ_TAG 0x50524f4a #define PHYJ_TAG 0x5048594a #define FOR__TAG 0x464f525f #define DMSE_TAG 0x444d5345 #define PHSH_TAG 0x50485348 #define PHRB_TAG 0x50485242 #define SSGS_TAG 0x53534753 #define ATVL_TAG 0x4154564c #define BBSC_TAG 0x42425343 #define SRIB_TAG 0x53524942 #define RIB__TAG 0x5249425f #define IKJT_TAG 0x494b4a54 #define SHBX_TAG 0x53484258 #define CAM__TAG 0x43414d5f #define WRP__TAG 0x5752505f buffer readBuffer(FILE* fp, size_t size, int pos) { fseek (fp , pos , SEEK_SET); buffer buf = malloc(size); fread(buf, size, 1, fp); return buf; } struct Reference { uint32 nEntries; uint32 ref; uint32 flags; }; typedef struct MD34 { uint32 magic; uint32 indexOffset; uint32 entries; struct Reference modelHeader; } MD34; // Size = 16 byte / 0x10 byte typedef struct ChunkEntry { uint32 tag; uint32 offset; uint32 nEntries; uint32 version; //Specific } ChunkEntry; int main ( int argc, char *argv[] ) { int pauseAtTheEnd = 1; if (argc != 2 && argc != 3) { printf("Drag an m3 file to this tool.\n"); printf("or do HotSm3ToSc2m3 -c.\n"); system( "PAUSE" ); return 0; } if (argc == 3) pauseAtTheEnd = (strcmp (argv[2],"-c") != 0); int isM3A = 0; char* extention; { int len = strlen(argv[1]); int i = 0; for (; i != len; i++) if (argv[1][i] == '.') extention = &argv[1][i]; } char outFile[256]; outFile[0] = 0; strcat(outFile,argv[1]); outFile[strlen(outFile)-strlen(extention)] = 0; strcat(outFile,"_Sc2"); strcat(outFile,extention); ChunkEntry* entries; FILE *file; file = fopen(argv[1], "rb"); uint32 lastOffset; MD34* header = malloc(sizeof(MD34)); fread(header, sizeof(MD34),1, file); lastOffset = header->indexOffset; if (MD34_TAG != header->magic) { printf("This is not a valid M3 file.\n"); return -1; } fseek (file , lastOffset , SEEK_SET); entries = malloc(sizeof(ChunkEntry)*header->entries); fread(entries, sizeof(ChunkEntry), header->entries, file); buffer* entryBuffers = malloc(sizeof(buffer*)*header->entries); uint32* bufferSizes = malloc(sizeof(uint32*)*header->entries); int i = 0; int n = header->entries; /* printf("HotS M3\n"); for (i = 0;i != n; i++) { char* tag = (char*)&entries[i].tag; printf("\tEntry\n"); printf("\t\tTag: %c%c%c%c\n",tag[3],tag[2],tag[1],tag[0]); printf("\t\tnumEntries: %d\n",entries[i].nEntries); printf("\t\tversion: %d\n",entries[i].version); } */ for (i = 0;i != n; i++) { int next = i + 1; int bufferSize; if (next == n) bufferSize = lastOffset - entries[i].offset; else bufferSize = entries[next].offset - entries[i].offset; entryBuffers[i] = readBuffer(file,bufferSize, entries[i].offset); bufferSizes[i] = bufferSize; } fclose(file); //Write file = fopen(outFile, "wb"); int offsetFix = 0; FILE* logFile = fopen("Logfile.txt", "w"); for (i = 0;i != n; i++) { int size = ftell(file); int j, s; entries[i].offset += offsetFix; switch (entries[i].tag) { case MODL_TAG: if (entries[i].version == 26) { s = entries[i].nEntries; void* buff = entryBuffers[i]; for(j = 0; j != s; j++) { fwrite (buff , 96, 1, file); uint32* vertexFlags = (uint32*)&buff[96]; *vertexFlags = ((*vertexFlags) & 0xFFFFFF00) | 0x7D; fwrite (vertexFlags , 4, 1, file); buff += 100; fwrite (buff , 720, 1, file); buff += 720; } break; } case RIB__TAG: if (entries[i].version == 9) { s = entries[i].nEntries; void* buff = entryBuffers[i]; for(j = 0; j != s; j++) { fwrite (buff , 396, 1, file); buff += 400; fwrite (buff , 360, 1, file); buff += 360; } entries[i].version = 8; break; } case LAYR_TAG: if (entries[i].version == 26) { uint32 fill = 0x00000000; s = entries[i].nEntries; void* buff = entryBuffers[i]; for(j = 0; j != s; j++) { fwrite (buff , 464, 1, file); fwrite (&fill , 4, 1, file); buff += 465; } entries[i].version = 25; break; } case PAR__TAG: if (entries[i].version == 24) { s = entries[i].nEntries; void* buff = entryBuffers[i]; for(j = 0; j != s; j++) { fwrite (buff , 400, 1, file); buff += 404; fwrite (buff , 1092, 1, file); buff += 1092; } entries[i].version = 23; break; } case FOR__TAG: if (entries[i].version == 2) entries[i].version = 1; default: fwrite (entryBuffers[i] , bufferSizes[i], 1, file); break; } size = ftell(file) - size; int padding = (((size >> 4) + ((size & 0x0F) != 0)) << 4) - size; fwrite(PADDING,padding, 1,file); offsetFix = offsetFix + (size + padding) - bufferSizes[i]; char* tag = (char*)&entries[i].tag; fprintf(logFile,"Tag: %c%c%c%c\n",tag[3],tag[2],tag[1],tag[0]); fprintf(logFile,"\tsize:%d\n", size/entries[i].nEntries); } uint32 pos = ftell(file); fseek (file , 0x04 , SEEK_SET); fwrite (&pos , sizeof(uint32), 1, file); fseek (file , pos , SEEK_SET); fwrite (entries , sizeof(ChunkEntry), n, file); fclose(file); fclose(logFile); printf("Strings Found: \n"); for (i = 0;i != n; i++) { if (entries[i].tag == CHAR_TAG) if (strlen(entryBuffers[i]) > 0) printf("\t%s\n", entryBuffers[i]); } if (pauseAtTheEnd) system( "PAUSE" ); return 0; }