From 6dddbd2efa50a83dffb5730a4ae68472e90d154a Mon Sep 17 00:00:00 2001 From: Fatbag Date: Mon, 3 Dec 2012 12:31:24 -0600 Subject: [PATCH] Added rtti-reader and made various cleanups, switching to Shutdown_M for error handling --- Libraries/FileHandler/File.cpp | 2 +- Libraries/FileHandler/FileHandler.hpp | 4 +- Libraries/FileHandler/Image.cpp | 2 +- Libraries/FileHandler/far/farextract.c | 50 +- Libraries/FileHandler/iff/iffexport.c | 84 +-- Libraries/FileHandler/utk/read_utk.c | 5 +- Libraries/FileHandler/utk/utkdecode.c | 91 ++- Libraries/FileHandler/xa/xadecode.c | 87 ++- Server/AUTHORS | 1 + Server/CHANGES | 2 + Server/COPYING | 21 + Server/README | 0 Server/Server.cpp | 3 +- Server/TODO | 21 + Tools/CMakeLists.txt | 1 + .../TSOEdithEditor/TSOEdithEditor.cpp | 12 +- .../TSOEdithEditor/TSOEdithEditor.hpp | 2 +- .../TSOEdithEditor/compile.bat | 2 +- .../TSOSimulatorClient/TSOSimulatorClient.cpp | 2 +- .../TSOSimulatorClient/TSOSimulatorClient.hpp | 10 +- Tools/TSOSimulatorClient/compile.bat | 2 +- Tools/iff2html/iff2html.c | 5 +- Tools/rtti-reader/CMakeLists.txt | 8 + Tools/rtti-reader/rtti-reader.cpp | 524 ++++++++++++++++++ Tools/tsoscan/tsoscan.c | 24 +- 25 files changed, 771 insertions(+), 194 deletions(-) create mode 100644 Server/AUTHORS create mode 100644 Server/CHANGES create mode 100644 Server/README create mode 100644 Server/TODO create mode 100644 Tools/rtti-reader/CMakeLists.txt create mode 100644 Tools/rtti-reader/rtti-reader.cpp diff --git a/Libraries/FileHandler/File.cpp b/Libraries/FileHandler/File.cpp index 80f0981..f2107d7 100644 --- a/Libraries/FileHandler/File.cpp +++ b/Libraries/FileHandler/File.cpp @@ -45,9 +45,9 @@ uint8_t * ReadFile(const char * Filename){ } size_t bytestransferred = fread(InData, 1, FileSize, hFile); + fclose(hFile); if(bytestransferred != FileSize){ free(InData); - fclose(hFile); File::Error = FERR_READ; return NULL; } diff --git a/Libraries/FileHandler/FileHandler.hpp b/Libraries/FileHandler/FileHandler.hpp index 3c8ac41..ca268a1 100644 --- a/Libraries/FileHandler/FileHandler.hpp +++ b/Libraries/FileHandler/FileHandler.hpp @@ -68,9 +68,9 @@ struct Sound_t { namespace File { -inline unsigned GetFileSize(FILE * hFile){ +inline size_t GetFileSize(FILE * hFile){ fseek(hFile, 0, SEEK_END); - unsigned FileSize = ftell(hFile); + size_t FileSize = ftell(hFile); fseek(hFile, 0, SEEK_SET); return FileSize; } diff --git a/Libraries/FileHandler/Image.cpp b/Libraries/FileHandler/Image.cpp index c06feae..7c04adf 100644 --- a/Libraries/FileHandler/Image.cpp +++ b/Libraries/FileHandler/Image.cpp @@ -127,7 +127,7 @@ static int fill_mem_input_buffer(j_decompress_ptr cinfo){ } static void skip_input_data(j_decompress_ptr cinfo, long bytes) { - struct jpeg_source_mgr * src = cinfo->src; + jpeg_source_mgr * src = cinfo->src; if(bytes > (long) src->bytes_in_buffer){ ERREXIT(cinfo, JERR_FILE_READ); diff --git a/Libraries/FileHandler/far/farextract.c b/Libraries/FileHandler/far/farextract.c index 237b76e..64bcd0c 100644 --- a/Libraries/FileHandler/far/farextract.c +++ b/Libraries/FileHandler/far/farextract.c @@ -34,7 +34,7 @@ enum { int main(int argc, char *argv[]){ int profile = 0, overwrite = 0; - char infile[256] = "", outdirectory[256] = ""; + const char * InFile = "", * OutDirectory; FILE * hFile; size_t ArchiveSize; uint8_t * ArchiveData; @@ -66,7 +66,7 @@ int main(int argc, char *argv[]){ return 0; } - for(i=1; !infile[0] && i != argc-1; i++){ + for(i=1; !InFile[0] && i != argc-1; i++){ /* Match for options */ if(!profile){ if(!strcmp(argv[i], "-ts1")){ profile = profile_ts1; continue; } @@ -82,18 +82,18 @@ int main(int argc, char *argv[]){ } /* Not an option */ if(!strcmp(argv[i], "-")){ - printf("%sReading from standard input is not yet implemented.", "farextract: error: "); + fprintf(stderr, "%sReading from standard input is not yet implemented.", "farextract: error: "); return -1; } - strcpy(infile, argv[i]); + InFile = argv[i]; continue; } /* We're left with the out directory */ - if(!infile[0]){ - printf("%sReading from standard input is not yet implemented.", "farextract: error: "); + if(!InFile[0]){ + fprintf(stderr, "%sReading from standard input is not yet implemented.", "farextract: error: "); return -1; } - strcpy(outdirectory, argv[i]); + OutDirectory = argv[i]; /**** ** Handle profile settings @@ -107,26 +107,26 @@ int main(int argc, char *argv[]){ ** Open the file and read in the entire contents to memory */ - hFile = fopen(infile, "rb"); + hFile = fopen(InFile, "rb"); if(hFile == NULL){ - printf("%sThe specified input file does not exist or could not be opened for reading.", "farextract: error: "); + fprintf(stderr, "%sThe specified input file does not exist or could not be opened for reading.", "farextract: error: "); return -1; } fseek(hFile, 0, SEEK_END); ArchiveSize = ftell(hFile); if(ArchiveSize < 24){ - printf("%sNot a valid archive.", "farextract: error: "); + fprintf(stderr, "%sNot a valid archive.", "farextract: error: "); return -1; } fseek(hFile, 0, SEEK_SET); ArchiveData = malloc(ArchiveSize); if(ArchiveData == NULL){ - printf("%sMemory for this archive could not be allocated.", "farextract: error: "); + fprintf(stderr, "%sMemory for this archive could not be allocated.", "farextract: error: "); return -1; } - if(!fread(ArchiveData, ArchiveSize, 1, hFile)){ - printf("%sThe input file could not be read.", "farextract: error: "); + if(fread(ArchiveData, 1, ArchiveSize, hFile) != ArchiveSize){ + fprintf(stderr, "%sThe input file could not be read.", "farextract: error: "); return -1; } fclose(hFile); @@ -137,7 +137,7 @@ int main(int argc, char *argv[]){ ArchiveType = far_identify(ArchiveData, ArchiveSize); if(ArchiveType == FAR_TYPE_INVALID){ - printf("%sNot a valid archive.", "farextract: error: "); + fprintf(stderr, "%sNot a valid archive.", "farextract: error: "); return -1; } @@ -151,11 +151,11 @@ int main(int argc, char *argv[]){ FARFile * FARFileInfo = far_create_archive(ArchiveType); if(FARFileInfo == NULL){ - printf("%sMemory for this archive could not be allocated.", "farextract: error: "); + fprintf(stderr, "%sMemory for this archive could not be allocated.", "farextract: error: "); return -1; } if(!far_read_header(FARFileInfo, ArchiveData, ArchiveSize)){ - printf("%sNot a valid archive.", "farextract: error: "); + fprintf(stderr, "%sNot a valid archive.", "farextract: error: "); return -1; } @@ -169,7 +169,7 @@ int main(int argc, char *argv[]){ if(!far_enumerate_entries(FARFileInfo, ArchiveData+FARFileInfo->IndexOffset, ArchiveSize-FARFileInfo->IndexOffset, ArchiveSize)){ - printf("%sEntry data is corrupt.", "farextract: error: "); + fprintf(stderr, "%sEntry data is corrupt.", "farextract: error: "); return -1; } @@ -181,9 +181,9 @@ int main(int argc, char *argv[]){ file++; if(EntryNode->Entry.Filename) - sprintf(destination, "%s/%s", outdirectory, EntryNode->Entry.Filename); + sprintf(destination, "%s/%s", OutDirectory, EntryNode->Entry.Filename); else - sprintf(destination, "%s/%08x-%08x-%08x.dat", outdirectory, + sprintf(destination, "%s/%08x-%08x-%08x.dat", OutDirectory, EntryNode->Entry.TypeID, EntryNode->Entry.GroupID, EntryNode->Entry.FileID); if(!far_read_entry_data(FARFileInfo, &(EntryNode->Entry), ArchiveData)){ @@ -233,7 +233,7 @@ int main(int argc, char *argv[]){ /* Persist file */ PersistFile * PersistInfo; char destination[256]; - sprintf(destination, "%s/%s.out", outdirectory, infile); + sprintf(destination, "%s/%s.out", OutDirectory, InFile); /**** ** Load header information @@ -241,11 +241,11 @@ int main(int argc, char *argv[]){ PersistInfo = far_create_persist(); if(PersistInfo == NULL){ - printf("%sMemory for this archive could not be allocated.", "farextract: error: "); + fprintf(stderr, "%sMemory for this archive could not be allocated.", "farextract: error: "); return -1; } if(!far_read_persist_header(PersistInfo, ArchiveData, ArchiveSize)){ - printf("%sNot a valid archive.", "farextract: error: "); + fprintf(stderr, "%sNot a valid archive.", "farextract: error: "); return -1; } @@ -255,7 +255,7 @@ int main(int argc, char *argv[]){ printf("Extracting\n"); BeginningTime = clock(); if(!far_read_persist_data(PersistInfo, ArchiveData+18)){ - printf("%sNot a valid archive.", "farextract: error: "); + fprintf(stderr, "%sNot a valid archive.", "farextract: error: "); return -1; } EndingTime = clock(); @@ -265,14 +265,14 @@ int main(int argc, char *argv[]){ if(hFile != NULL){ /* File exists */ fclose(hFile); - printf("%sFile exists.", "farextract: error: "); + fprintf(stderr, "%sFile exists.", "farextract: error: "); libfar_free(PersistInfo->DecompressedData); return -1; } } hFile = fopen(destination, "wb"); if(hFile == NULL){ - printf("%sCould not open.", "farextract: error: "); + fprintf(stderr, "%sCould not open.", "farextract: error: "); libfar_free(PersistInfo->DecompressedData); return -1; } diff --git a/Libraries/FileHandler/iff/iffexport.c b/Libraries/FileHandler/iff/iffexport.c index 98e6d6c..0272d03 100644 --- a/Libraries/FileHandler/iff/iffexport.c +++ b/Libraries/FileHandler/iff/iffexport.c @@ -23,7 +23,21 @@ #include #include "iff.h" -int charmatches(char c, const char * filter){ +static FILE * hFile = NULL; +static uint8_t * IFFData = NULL; +static IFFFile IFFFileInfo; +static int iffcreated = 0; + +static void Shutdown_M(const char * Message){ + fprintf(stderr, "iffexport: error: %s.", Message); + if(iffcreated) + iff_delete(&IFFFileInfo); + free(IFFData); + fclose(hFile); + exit(EXIT_FAILURE); +} + +static int charmatches(char c, const char * filter){ while(*filter){ if(c == *filter) return 1; filter++; @@ -32,18 +46,15 @@ int charmatches(char c, const char * filter){ } int main(int argc, char *argv[]){ - FILE * hFile; int overwrite = 0; - char *InFile, *OutDirectory; + const char *InFile, *OutDirectory; size_t FileSize; - uint8_t * IFFData; clock_t BeginningTime; unsigned chunkcount, chunk; unsigned exported = 0; - IFFFile IFFFileInfo; IFFChunk * ChunkData; - if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ + if(argc < 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ printf("Usage: iffexport [-f] infile outdirectory\n" "Export the resources of an EA IFF file.\n" "Use -f to force overwriting without confirmation.\n" @@ -68,50 +79,39 @@ int main(int argc, char *argv[]){ */ hFile = fopen(InFile, "rb"); - if(hFile == NULL){ - printf("%sThe specified input file does not exist or could not be opened for reading.", "iffexport: error: "); - return -1; - } + if(hFile == NULL) + Shutdown_M("The specified input file does not exist or could not be opened for reading"); fseek(hFile, 0, SEEK_END); FileSize = ftell(hFile); - if(FileSize < 24){ - printf("%sNot a valid IFF file.", "iffexport: error: "); - return -1; - } + if(FileSize < 24) + Shutdown_M("Not a valid IFF file"); fseek(hFile, 0, SEEK_SET); IFFData = malloc(FileSize); - if(IFFData == NULL){ - printf("%sMemory for this file could not be allocated.", "iffexport: error: "); - return -1; - } - if(!fread(IFFData, FileSize, 1, hFile)){ - printf("%sThe input file could not be read.", "iffexport: error: "); - return -1; - } - fclose(hFile); + if(IFFData == NULL) + Shutdown_M("Memory for this file could not be allocated"); + if(fread(IFFData, 1, FileSize, hFile) != FileSize) + Shutdown_M("The input file could not be read"); + fclose(hFile); hFile = NULL; /**** ** Load header information */ - if(!iff_create(&IFFFileInfo)){ - printf("%sMemory for this file could not be allocated.", "iffexport: error: "); - return -1; - } - if(!iff_read_header(&IFFFileInfo, IFFData, FileSize)){ - printf("%sNot a valid IFF file.", "iffexport: error: "); - return -1; - } + if(!iff_create(&IFFFileInfo)) + Shutdown_M("Memory for this file could not be allocated"); + iffcreated++; + if(!iff_read_header(&IFFFileInfo, IFFData, FileSize)) + Shutdown_M("Not a valid IFF file"); /**** ** Load entry information */ - if(!iff_enumerate_chunks(&IFFFileInfo, IFFData+64, FileSize-64)){ - printf("%sChunk data is corrupt.", "iffexport: error: "); - return -1; - } + if(!iff_enumerate_chunks(&IFFFileInfo, IFFData+64, FileSize-64)) + Shutdown_M("Chunk data is corrupt"); + + free(IFFData); IFFData = NULL; chunkcount = IFFFileInfo.ChunkCount; printf("This IFF file contains %u chunks.\n\nExporting\n", chunkcount); @@ -144,21 +144,19 @@ int main(int argc, char *argv[]){ if(hFile != NULL){ /* File exists */ char c; - fclose(hFile); + fclose(hFile); hFile = NULL; printf("File \"%s\" exists.\nContinue anyway? (y/n) ", destination); c = getchar(); if(c != 'y' && c != 'Y'){ - printf("\nAborted."); - return -1; + printf("\n"); + Shutdown_M("Aborted"); } } overwrite++; } hFile = fopen(destination, "wb"); - if(hFile == NULL){ - printf("%sThe output file could not be opened for writing.", "iffexport: error: "); - return -1; - } + if(hFile == NULL) + Shutdown_M("The output file could not be opened for writing"); fwrite(ChunkData->Data, 1, ChunkData->Size, hFile); fclose(hFile); @@ -168,5 +166,7 @@ int main(int argc, char *argv[]){ printf("\nExported %u of %u chunks in %.2f seconds.", exported, chunkcount, ((float) (clock() - BeginningTime))/CLOCKS_PER_SEC); + iff_delete(&IFFFileInfo); + return 0; } \ No newline at end of file diff --git a/Libraries/FileHandler/utk/read_utk.c b/Libraries/FileHandler/utk/read_utk.c index 9d74f03..cd0dba9 100644 --- a/Libraries/FileHandler/utk/read_utk.c +++ b/Libraries/FileHandler/utk/read_utk.c @@ -26,9 +26,10 @@ #define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1))) #endif #ifndef write_int32 - #define write_uint16(dest, src) \ + #define write_uint16(dest, src) do {\ (dest)[0] = ((src)&0x00FF)>>(8*0); \ - (dest)[1] = ((src)&0xFF00)>>(8*1) + (dest)[1] = ((src)&0xFF00)>>(8*1); \ + } while(0) #endif #ifndef round diff --git a/Libraries/FileHandler/utk/utkdecode.c b/Libraries/FileHandler/utk/utkdecode.c index 0dd7e9e..655e5ae 100644 --- a/Libraries/FileHandler/utk/utkdecode.c +++ b/Libraries/FileHandler/utk/utkdecode.c @@ -1,7 +1,5 @@ /* - FileHandler - General-purpose file handling library for Niotso - utkdecode.c - Copyright (c) 2011-2012 Niotso Project - Author(s): Fatbag + utkdecode.c - Copyright (c) 2011-2012 Fatbag Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -24,22 +22,34 @@ #include "read_utk.h" #ifndef write_int32 - #define write_uint32(dest, src) \ + #define write_uint32(dest, src) do {\ (dest)[0] = ((src)&0x000000FF)>>(8*0); \ (dest)[1] = ((src)&0x0000FF00)>>(8*1); \ (dest)[2] = ((src)&0x00FF0000)>>(8*2); \ - (dest)[3] = ((src)&0xFF000000)>>(8*3) - #define write_uint16(dest, src) \ + (dest)[3] = ((src)&0xFF000000)>>(8*3); \ + } while(0) + #define write_uint16(dest, src) do {\ (dest)[0] = ((src)&0x00FF)>>(8*0); \ - (dest)[1] = ((src)&0xFF00)>>(8*1) + (dest)[1] = ((src)&0xFF00)>>(8*1); \ + } while(0) #endif +static FILE * hFile = NULL; +static uint8_t * UTKData = NULL; +static uint8_t * WaveData = NULL; + +static void Shutdown_M(const char * Message){ + fprintf(stderr, "utkdecode: error: %s.", Message); + free(WaveData); + free(UTKData); + fclose(hFile); + exit(EXIT_FAILURE); +} + int main(int argc, char *argv[]){ int overwrite = 0; - char *InFile, *OutFile; - FILE * hFile; + const char *InFile, *OutFile; size_t FileSize; - uint8_t * UTKData; utkheader_t UTKHeader; clock_t BeginningTime, EndingTime; @@ -69,55 +79,41 @@ int main(int argc, char *argv[]){ */ hFile = fopen(InFile, "rb"); - if(hFile == NULL){ - printf("%sThe specified input file does not exist or could not be opened for reading.", "utkdecode: error: "); - return -1; - } + if(hFile == NULL) + Shutdown_M("The specified input file does not exist or could not be opened for reading"); fseek(hFile, 0, SEEK_END); FileSize = ftell(hFile); - if(FileSize < 24){ - printf("%sNot a valid UTK file.", "utkdecode: error: "); - return -1; - } + if(FileSize < 32) + Shutdown_M("Not a valid UTK file"); fseek(hFile, 0, SEEK_SET); UTKData = malloc(FileSize); - if(UTKData == NULL){ - printf("%sMemory for this file could not be allocated.", "utkdecode: error: "); - return -1; - } - if(!fread(UTKData, FileSize, 1, hFile)){ - printf("%sThe input file could not be read.", "utkdecode: error: "); - return -1; - } - fclose(hFile); + if(UTKData == NULL) + Shutdown_M("Memory for this file could not be allocated"); + if(fread(UTKData, 1, FileSize, hFile) != FileSize) + Shutdown_M("The input file could not be read"); + fclose(hFile); hFile = NULL; /**** ** Transcode the data from UTK to LPCM */ - if(!utk_read_header(&UTKHeader, UTKData, FileSize)){ - printf("%sNot a valid UTK file.", "utkdecode: error: "); - return -1; - } + if(!utk_read_header(&UTKHeader, UTKData, FileSize)) + Shutdown_M("Not a valid UTK file"); if(argc >= 3){ /* Transcode */ - uint8_t * WaveData = malloc(44+UTKHeader.dwOutSize); - if(WaveData == NULL){ - printf("%sMemory for this file could not be allocated.", "utkdecode: error: "); - return -1; - } + WaveData = malloc(44+UTKHeader.dwOutSize); + if(WaveData == NULL) + Shutdown_M("Memory for this file could not be allocated"); UTKGenerateTables(); BeginningTime = clock(); - if(!utk_decode(UTKData+32, WaveData+44, UTKHeader.Frames)){ - printf("%sMemory for this file could not be allocated.", "utkdecode: error: "); - return -1; - } + if(!utk_decode(UTKData+32, WaveData+44, UTKHeader.Frames)) + Shutdown_M("Memory for this file could not be allocated"); EndingTime = clock(); - free(UTKData); + free(UTKData); UTKData = NULL; /**** ** Write the Microsoft WAV header @@ -146,23 +142,22 @@ int main(int argc, char *argv[]){ if(hFile != NULL){ /* File exists */ char c; - fclose(hFile); + fclose(hFile); hFile = NULL; printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile); c = getchar(); if(c != 'y' && c != 'Y'){ - printf("\nAborted.\n"); - return -1; + printf("\n"); + Shutdown_M("Aborted"); } } } hFile = fopen(OutFile, "wb"); - if(hFile == NULL){ - printf("%sThe output file could not be opened for writing.", "utkdecode: error: "); - return -1; - } + if(hFile == NULL) + Shutdown_M("The output file could not be opened for writing"); printf("Extracted %u bytes in %.2f seconds.\n", (unsigned) UTKHeader.dwOutSize, ((float)(EndingTime - BeginningTime))/CLOCKS_PER_SEC); fwrite(WaveData, 1, 44+UTKHeader.dwOutSize, hFile); + free(WaveData); fclose(hFile); } diff --git a/Libraries/FileHandler/xa/xadecode.c b/Libraries/FileHandler/xa/xadecode.c index 5c57885..6b8901f 100644 --- a/Libraries/FileHandler/xa/xadecode.c +++ b/Libraries/FileHandler/xa/xadecode.c @@ -22,22 +22,34 @@ #include "read_xa.h" #ifndef write_int32 - #define write_uint32(dest, src) \ + #define write_uint32(dest, src) do {\ (dest)[0] = ((src)&0x000000FF)>>(8*0); \ (dest)[1] = ((src)&0x0000FF00)>>(8*1); \ (dest)[2] = ((src)&0x00FF0000)>>(8*2); \ - (dest)[3] = ((src)&0xFF000000)>>(8*3) - #define write_uint16(dest, src) \ + (dest)[3] = ((src)&0xFF000000)>>(8*3); \ + } while(0) + #define write_uint16(dest, src) do {\ (dest)[0] = ((src)&0x00FF)>>(8*0); \ - (dest)[1] = ((src)&0xFF00)>>(8*1) + (dest)[1] = ((src)&0xFF00)>>(8*1); \ + } while(0) #endif +static FILE * hFile = NULL; +static uint8_t * XAData = NULL; +static uint8_t * WaveData = NULL; + +static void Shutdown_M(const char * Message){ + fprintf(stderr, "xadecode: error: %s.", Message); + free(WaveData); + free(XAData); + fclose(hFile); + exit(EXIT_FAILURE); +} + int main(int argc, char *argv[]){ int overwrite = 0; - char *InFile, *OutFile; - FILE * hFile; + const char *InFile, *OutFile; size_t FileSize; - uint8_t * XAData; xaheader_t XAHeader; clock_t BeginningTime, EndingTime; @@ -67,53 +79,39 @@ int main(int argc, char *argv[]){ */ hFile = fopen(InFile, "rb"); - if(hFile == NULL){ - printf("%sThe specified input file does not exist or could not be opened for reading.", "xadecode: error: "); - return -1; - } + if(hFile == NULL) + Shutdown_M("The specified input file does not exist or could not be opened for reading"); fseek(hFile, 0, SEEK_END); FileSize = ftell(hFile); - if(FileSize < 24){ - printf("%sNot a valid XA file.", "xadecode: error: "); - return -1; - } + if(FileSize < 24) + Shutdown_M("Not a valid XA file"); fseek(hFile, 0, SEEK_SET); XAData = malloc(FileSize); - if(XAData == NULL){ - printf("%sMemory for this file could not be allocated.", "xadecode: error: "); - return -1; - } - if(!fread(XAData, FileSize, 1, hFile)){ - printf("%sThe input file could not be read.", "xadecode: error: "); - return -1; - } - fclose(hFile); + if(XAData == NULL) + Shutdown_M("Memory for this file could not be allocated"); + if(fread(XAData, 1, FileSize, hFile) != FileSize) + Shutdown_M("The input file could not be read"); + fclose(hFile); hFile = NULL; /**** ** Transcode the data from XA to LPCM */ - if(!xa_read_header(&XAHeader, XAData, FileSize)){ - printf("%sNot a valid XA file.", "xadecode: error: "); - return -1; - } + if(!xa_read_header(&XAHeader, XAData, FileSize)) + Shutdown_M("Not a valid XA file"); if(argc >= 3){ /* Transcode */ - uint8_t * WaveData = malloc(44+XAHeader.dwOutSize); - if(WaveData == NULL){ - printf("%sMemory for this file could not be allocated.", "xadecode: error: "); - return -1; - } + WaveData = malloc(44+XAHeader.dwOutSize); + if(WaveData == NULL) + Shutdown_M("Memory for this file could not be allocated"); BeginningTime = clock(); - if(!xa_decode(XAData+24, WaveData+44, XAHeader.Frames, XAHeader.nChannels)){ - printf("%sMemory for this file could not be allocated.", "xadecode: error: "); - return -1; - } + if(!xa_decode(XAData+24, WaveData+44, XAHeader.Frames, XAHeader.nChannels)) + Shutdown_M("Memory for this file could not be allocated"); EndingTime = clock(); - free(XAData); + free(XAData); XAData = NULL; /**** ** Write the Microsoft WAV header @@ -142,23 +140,22 @@ int main(int argc, char *argv[]){ if(hFile != NULL){ /* File exists */ char c; - fclose(hFile); + fclose(hFile); hFile = NULL; printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile); c = getchar(); if(c != 'y' && c != 'Y'){ - printf("\nAborted.\n"); - return -1; + printf("\n"); + Shutdown_M("Aborted"); } } } hFile = fopen(OutFile, "wb"); - if(hFile == NULL){ - printf("%sThe output file could not be opened for writing.", "xadecode: error: "); - return -1; - } + if(hFile == NULL) + Shutdown_M("The output file could not be opened for writing"); printf("Extracted %u bytes in %.2f seconds.\n", (unsigned) XAHeader.dwOutSize, ((float)(EndingTime - BeginningTime))/CLOCKS_PER_SEC); fwrite(WaveData, 1, 44+XAHeader.dwOutSize, hFile); + free(WaveData); fclose(hFile); } diff --git a/Server/AUTHORS b/Server/AUTHORS new file mode 100644 index 0000000..256626b --- /dev/null +++ b/Server/AUTHORS @@ -0,0 +1 @@ +Fatbag \ No newline at end of file diff --git a/Server/CHANGES b/Server/CHANGES new file mode 100644 index 0000000..aacc0cb --- /dev/null +++ b/Server/CHANGES @@ -0,0 +1,2 @@ +Technical Preview 1 + * Initial release \ No newline at end of file diff --git a/Server/COPYING b/Server/COPYING index e587591..acdc1dc 100644 --- a/Server/COPYING +++ b/Server/COPYING @@ -1,3 +1,24 @@ +IMPORTANT: +Niotso is distributed under the terms of the GNU GPLv3. + +While this license does permit others to compile, distribute, change, +and distribute changes to Niotso, in reality, many of these freedoms +cannot legally be enacted by anybody. + +Specifically, if you make changes to Niotso such that it significantly +changes the "game experience as presented to the player", it cannot +be distributed to others. You also may not distribute a version of +Niotso that has stripped the EA or Maxis trademarked names or logos +anywhere from the game. Personal use of these modifications is okay. + +These restrictions are not enforced by us, but may potentially be used +by EA in attempt to take down your game. + +If you have any questions, you may visit + + +--- + GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 diff --git a/Server/README b/Server/README new file mode 100644 index 0000000..e69de29 diff --git a/Server/Server.cpp b/Server/Server.cpp index 7542b0c..82b38be 100644 --- a/Server/Server.cpp +++ b/Server/Server.cpp @@ -152,7 +152,8 @@ int main(int, char **) socklen_t addrlen = sizeof(sockaddr_in6); ssize_t packetsize = recvfrom(epev[0].data.fd, packetdata, 1500, 0, (sockaddr*) &client_addr, &addrlen); if(packetsize < 0){ - if(errno == EINTR || errno == ECONNRESET || errno == ENOTCONN || errno == ETIMEDOUT) + if(errno == EINTR || errno == ECONNRESET || errno == ENOTCONN || errno == ETIMEDOUT || + errno == EAGAIN || errno == EWOULDBLOCK) continue; SHUTDOWN_M("Socket closed unexpectedly on call to recvfrom", close_epoll); diff --git a/Server/TODO b/Server/TODO new file mode 100644 index 0000000..8f37171 --- /dev/null +++ b/Server/TODO @@ -0,0 +1,21 @@ +Because there are too many long-term things to list that we still have "to do" to reach the next development phase (e.g. +alpha to beta), this file contains only the things that are worked on currently or that will be in the very near future. + +While anybody is free to work on _anything_ at any point during Niotso's time, this list shall ONLY contain those relevant +to complete the criteria for the next development phase, which can be found here: + + +//----------// + +Development Phase: Planning + +Technical Preview 1 +Schedule: (Not very subject to change) + 1. Implement cst, uis, ini, and xml parsers with support for UTF-8 [20%] + 2. Replicate functionality up until the login dialog [90%] + 3. Implement the audio engine + 4. Implement the OpenGL-based windowing system + 5. Replicate character selection and creation features and the city selection dialog + 6. Implement debug logging and support for configuration files + 7. Implement the code needed to allow the game to read all necessary files from the TSOClient folder + 8. Port the client to Linux \ No newline at end of file diff --git a/Tools/CMakeLists.txt b/Tools/CMakeLists.txt index 54f7fde..5709862 100644 --- a/Tools/CMakeLists.txt +++ b/Tools/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(FARDive) add_subdirectory(hitutils) add_subdirectory(iff2html) +add_subdirectory(rtti-reader) add_subdirectory(tsoscan) \ No newline at end of file diff --git a/Tools/TSOSimulatorClient/TSOEdithEditor/TSOEdithEditor.cpp b/Tools/TSOSimulatorClient/TSOEdithEditor/TSOEdithEditor.cpp index 0b3d132..7f5a28e 100644 --- a/Tools/TSOSimulatorClient/TSOEdithEditor/TSOEdithEditor.cpp +++ b/Tools/TSOSimulatorClient/TSOEdithEditor/TSOEdithEditor.cpp @@ -27,23 +27,23 @@ int main(){ return -1; } - cEdithEditorCOMDirector * (__stdcall *GZDllGetGZCOMDirector)(void) = - (cEdithEditorCOMDirector * (__stdcall *)(void)) GetProcAddress(dllmodule, "GZDllGetGZCOMDirector"); + cTSOEdithEditorDCOMDirector * (__stdcall *GZDllGetGZCOMDirector)(void) = + (cTSOEdithEditorDCOMDirector * (__stdcall *)(void)) GetProcAddress(dllmodule, "GZDllGetGZCOMDirector"); if(GZDllGetGZCOMDirector == NULL){ printf("TSOEdithEditor: Error: Failed to find GZDllGetGZCOMDirector() in TSOEdithEditorD.dll."); return -1; } printf("TSOEdithEditor: Calling GZDllGetGZCOMDirector() ...\n"); - cEdithEditorCOMDirector * Edith = GZDllGetGZCOMDirector(); + cTSOEdithEditorDCOMDirector * Edith = GZDllGetGZCOMDirector(); printf("TSOEdithEditor: Finished calling GZDllGetGZCOMDirector().\nThe value returned was: %p.\n", (void *) Edith); while(true){ char buffer[8]; printf("\nCall a function (0, 1, 2, ...) or q to exit. "); - fgets(buffer, 8, stdin); - if(buffer[0] == 'q') break; - Edith->Object1.vtable5[atoi(buffer)](); + //fgets(buffer, 8, stdin); + //if(buffer[0] == 'q') break; + //Edith->Object1.vtable5[atoi(buffer)](); } printf("TSOEdithEditor: Exiting.\n"); diff --git a/Tools/TSOSimulatorClient/TSOEdithEditor/TSOEdithEditor.hpp b/Tools/TSOSimulatorClient/TSOEdithEditor/TSOEdithEditor.hpp index 791588f..2214dae 100644 --- a/Tools/TSOSimulatorClient/TSOEdithEditor/TSOEdithEditor.hpp +++ b/Tools/TSOSimulatorClient/TSOEdithEditor/TSOEdithEditor.hpp @@ -41,7 +41,7 @@ DECLARE_INTERFACE(cUnknownObject1) DWORD Unknown12; }; -DECLARE_INTERFACE(cEdithEditorCOMDirector) +DECLARE_INTERFACE(cTSOEdithEditorDCOMDirector) { void * vtable2; void * vtable1; diff --git a/Tools/TSOSimulatorClient/TSOEdithEditor/compile.bat b/Tools/TSOSimulatorClient/TSOEdithEditor/compile.bat index 4893a1f..4d8af3e 100644 --- a/Tools/TSOSimulatorClient/TSOEdithEditor/compile.bat +++ b/Tools/TSOSimulatorClient/TSOEdithEditor/compile.bat @@ -1 +1 @@ -gcc -Wall -Wextra -Wabi -pedantic -m32 -o TSOEdithEditor.exe TSOEdithEditor.cpp -mconsole \ No newline at end of file +gcc -Wall -Wextra -Wabi -pedantic -fno-exceptions -m32 -o TSOEdithEditor.exe TSOEdithEditor.cpp -mconsole \ No newline at end of file diff --git a/Tools/TSOSimulatorClient/TSOSimulatorClient.cpp b/Tools/TSOSimulatorClient/TSOSimulatorClient.cpp index a2aeacf..75e7818 100644 --- a/Tools/TSOSimulatorClient/TSOSimulatorClient.cpp +++ b/Tools/TSOSimulatorClient/TSOSimulatorClient.cpp @@ -38,7 +38,7 @@ int main(){ cTSOSimulatorClientDCOMDirector * Simulator = GZDllGetGZCOMDirector(); printf("TSOSimulatorClient: Finished calling GZDllGetGZCOMDirector().\nThe value returned was: %p.\n", (void *) Simulator); - printf("%s\n%s\n%s\n", Simulator->Object1.Strings1[0], Simulator->Object1.Strings2[0], Simulator->Object1.Strings3[0]); + printf("%s\n%s\n%s\n", Simulator->String1.Strings1[0], Simulator->String1.Strings2[0], Simulator->String1.Strings3[0]); printf("TSOSimulatorClient: Exiting.\n"); FreeLibrary(dllmodule); diff --git a/Tools/TSOSimulatorClient/TSOSimulatorClient.hpp b/Tools/TSOSimulatorClient/TSOSimulatorClient.hpp index 076ff00..6621c92 100644 --- a/Tools/TSOSimulatorClient/TSOSimulatorClient.hpp +++ b/Tools/TSOSimulatorClient/TSOSimulatorClient.hpp @@ -19,8 +19,9 @@ #include #pragma pack(0) -DECLARE_INTERFACE(cUnknownObject1) +DECLARE_INTERFACE(cRZString) { + //Base classes: cRZString, std::char_traits, ?$_String_base@DV?$__default_alloc_template@$00$0A@@std@@@std, cIGZString, cIGZUnknown DWORD Zero1; DWORD Zero2; void * vtable5; @@ -43,13 +44,14 @@ DECLARE_INTERFACE(cUnknownObject1) DECLARE_INTERFACE(cTSOSimulatorClientDCOMDirector) { + //Base classes: cTSOSimulatorClientDCOMDirector, cRZCOMDllDirector, cIGZCOMDirector, cIGZUnknown, cIGZFrameWorkHooks, cIGZUnknown void * vtable2; void * vtable1; - cUnknownObject1 Object1; + cRZString String1; void * vtable4; void * vtable3; - cUnknownObject1 Object2; - cUnknownObject1 Object3; + cRZString String2; + cRZString String3; DWORD Zero1; DWORD Zero2; diff --git a/Tools/TSOSimulatorClient/compile.bat b/Tools/TSOSimulatorClient/compile.bat index 0561632..4355932 100644 --- a/Tools/TSOSimulatorClient/compile.bat +++ b/Tools/TSOSimulatorClient/compile.bat @@ -1 +1 @@ -gcc -Wall -Wextra -Wabi -pedantic -m32 -o TSOSimulatorClient.exe TSOSimulatorClient.cpp -mconsole \ No newline at end of file +gcc -Wall -Wextra -Wabi -pedantic -fno-exceptions -m32 -o TSOSimulatorClient.exe TSOSimulatorClient.cpp -mconsole \ No newline at end of file diff --git a/Tools/iff2html/iff2html.c b/Tools/iff2html/iff2html.c index 2080866..768b7e1 100644 --- a/Tools/iff2html/iff2html.c +++ b/Tools/iff2html/iff2html.c @@ -119,6 +119,7 @@ int main(int argc, char *argv[]){ fseek(hFile, 0, SEEK_END); FileSize = ftell(hFile); if(FileSize < 64){ + fclose(hFile); printf("%sNot a valid IFF file.", "iff2html: error: "); return -1; } @@ -126,10 +127,12 @@ int main(int argc, char *argv[]){ IFFData = malloc(FileSize); if(IFFData == NULL){ + fclose(hFile); printf("%sMemory for this file could not be allocated.", "iff2html: error: "); return -1; } - if(!fread(IFFData, FileSize, 1, hFile)){ + if(fread(IFFData, 1, FileSize, hFile) != FileSize){ + fclose(hFile); printf("%sThe input file could not be read.", "iff2html: error: "); return -1; } diff --git a/Tools/rtti-reader/CMakeLists.txt b/Tools/rtti-reader/CMakeLists.txt new file mode 100644 index 0000000..251b0eb --- /dev/null +++ b/Tools/rtti-reader/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 2.6) +project(rtti-reader) + +set(RTTIREADER_SOURCES + rtti-reader.cpp +) + +add_executable(rtti-reader ${RTTIREADER_SOURCES}) \ No newline at end of file diff --git a/Tools/rtti-reader/rtti-reader.cpp b/Tools/rtti-reader/rtti-reader.cpp new file mode 100644 index 0000000..86b1e7b --- /dev/null +++ b/Tools/rtti-reader/rtti-reader.cpp @@ -0,0 +1,524 @@ +/* + rtti-reader - The Sims Online MSVC RTTI Class Hierarchy Extractor + rtti-reader.cpp - Copyright (c) 2012 Niotso Project + Author(s): Fatbag + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +//For information about MSVC RTTI, read: +// +// + +//For information about the Windows PE header, read: +// + +#include +#include +#include +#include +#include + +#ifndef read_int32 + #define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3))) + #define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1))) +#endif +#ifndef write_int32 + #define write_uint32(dest, src) do { \ + (dest)[0] = ((src)&0x000000FF)>>(8*0); \ + (dest)[1] = ((src)&0x0000FF00)>>(8*1); \ + (dest)[2] = ((src)&0x00FF0000)>>(8*2); \ + (dest)[3] = ((src)&0xFF000000)>>(8*3); \ + } while(0) +#endif + +static void Shutdown_M(const char * Message); + +struct Segment { + size_t size, offset; + Segment() : size(0) {} +}; + +struct ByteReaderContext { + size_t start, position, end; + bool seek(size_t pos){ + if(pos > end) + return false; + position = pos; + return true; + } + bool skip(int pos = 1){ + if(position + pos > end) + return false; + position += pos; + return true; + } +}; + +struct PaddingTest { + uint32_t A; + uint32_t B; +}; + +template +struct RTTIVector { + size_t Count, SizeAllocated; + T * Buffer; + + void init(){ + Count = 0, SizeAllocated = sizeof(T); + if(!(Buffer = (T*) malloc(sizeof(T)))) + Shutdown_M("Failed to allocate memory"); + } + T& add(){ + if((Count+1)*sizeof(T) > SizeAllocated) + if(SizeAllocated > SIZE_MAX/2 || !(Buffer = (T*) realloc(Buffer, SizeAllocated<<=1))) + Shutdown_M("Failed to allocate memory"); + + return Buffer[Count++]; + } +}; + +struct RTTITypeDescriptor { + struct { + uint32_t Address; + uint32_t VTableAddress; + uint32_t Reserved; + } Fields; + char * Name; + char * UnmangledName; +}; + +struct RTTIBaseClassDescriptor { + struct { + uint32_t Address; + uint32_t TypeDescriptorAddress; + uint32_t BaseClassCount; + uint32_t MemberOffset; + uint32_t COLAddressOffset; + uint32_t VTableOffset; + uint32_t Attributes; + } Fields; + RTTITypeDescriptor TD; +}; + +struct RTTIClassHierarchyDescriptor { + struct { + uint32_t Address; + uint32_t Reserved; + uint32_t Attributes; + uint32_t BaseClassCount; + uint32_t BaseClassListAddress; + } Fields; + RTTIVector BCDL; +}; + +struct RTTICompleteObjectLocator { + struct { + uint32_t Address; + uint32_t Reserved; + uint32_t Offset; + uint32_t CDOffset; + uint32_t TypeDescriptorAddress; + uint32_t ClassDescriptorAddress; + } Fields; + uint32_t VTableAddress; +}; + +struct RTTIClass { + RTTIVector COLL; + RTTITypeDescriptor TD; + RTTIClassHierarchyDescriptor CHD; + void init(){ + COLL.init(); + CHD.BCDL.init(); + } + bool DependsOn(const RTTIClass& X) const { + for(uint32_t i=1; i(Aptr); + const RTTIClass& B = *reinterpret_cast(Bptr); + + if(A.DependsOn(B)) return 1; //If A depends on B, A > B + if(B.DependsOn(A)) return -1; //If B depends on A, B > A + return strcmp(A.TD.UnmangledName, B.TD.UnmangledName); + } +}; + +struct PEFile { + static PEFile * ptr; + FILE * hFile; + uint8_t * Data; + Segment rdata, data; + ByteReaderContext brc; + + PEFile(const char * filename) : Data(NULL) { + PEFile::ptr = this; + + hFile = fopen(filename, "rb"); + if(!hFile) + Shutdown_M("The specified input file does not exist or could not be opened for reading"); + + fseek(hFile, 0, SEEK_END); + size_t FileSize = ftell(hFile); + if(FileSize < 64) + Shutdown_M("Not a valid Windows PE file"); + fseek(hFile, 0, SEEK_SET); + + Data = (uint8_t*) malloc(FileSize); + if(!Data) + Shutdown_M("Failed to allocate memory"); + if(fread(Data, 1, FileSize, hFile) != FileSize) + Shutdown_M("Failed to read input file"); + + fclose(hFile); + + brc.start = brc.position = 0; + brc.end = FileSize; + } + ~PEFile(){ + if(hFile) + fclose(hFile); + if(Data) + free(Data); + } + + inline bool seek(size_t pos, int offset = 0){ + return brc.seek(pos + offset); + } + + inline bool skip(size_t pos = 1, int offset = 0){ + return brc.skip(pos + offset); + } + int nextchar(){ + if(!brc.skip()) + return EOF; + return Data[brc.position-1]; + } + void lookat(Segment& segment){ + brc.start = brc.position = segment.offset; + brc.end = segment.offset + segment.size; + } + + uint32_t read32(){ + return brc.skip(4) ? read_uint32(Data+brc.position-4) : -1; + } + uint16_t read16(){ + return brc.skip(2) ? read_uint16(Data+brc.position-2) : -1; + } + size_t strlen(){ + size_t i = (size_t)-1; + int byte; + do { + byte = nextchar(); + if(byte == EOF) + return -1; + i++; + } while(byte); + skip(-(int)i-1); //Seek back + return i; + } + bool strcpy(char * dest){ + int i = 0; + do { + int byte = nextchar(); + if(byte == EOF) + return false; + *dest = (char) byte; + i--; + } while(*dest++); + skip(i); //Seek back + return true; + } + int strcmp(const char * data){ + int i = 0; + int byte; + do { + byte = nextchar(); + if(byte == EOF) + return -1; + i--; + } while(*data++ && (char)byte == *(data-1)); + skip(i); //Seek back + return byte - *(data-1); + } + enum { Parse_QuestionMark = 1}; + bool memfind(const char * data, size_t size, int MemParse = 0){ + size_t i = 0; + do { + int byte = nextchar(); + if(byte == EOF) + return false; + else if((char)byte != data[i] && (!MemParse || data[i] != '?')){ + skip(-(int)i); + i = 0; + } else i++; + } while(i brc.end - brc.position) + return false; + + uint32_t *field = reinterpret_cast(ptr); + *field = brc.position; //The Address field always comes first + + do { + ptr += padding; count -= padding; + field = reinterpret_cast(ptr); + *field = read32(); + } while(count); + + return true; + } + + template + inline bool Fill(T& context) { + return GenericFill(reinterpret_cast(&context.Fields), sizeof(context.Fields)); + } +}; + +PEFile * PEFile::ptr; + +static void Shutdown_M(const char * Message){ + fprintf(stderr, "rtti-reader: error: %s.", Message); + if(PEFile::ptr) + PEFile::ptr->~PEFile(); + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]){ + unsigned i; + const char * InFile, * BaseName; + + if(argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ + printf("Usage: rtti-reader infile\n" + "Extract class information from an EXE or DLL using MSVC RTTI.\n" + "\n" + "Report bugs to .\n" + "rtti-reader is maintained by the Niotso project.\n" + "Home page: \n"); + return 0; + } + + InFile = argv[1]; + + int slash; + for(i=0, slash=-1; InFile[i]; i++) + if(InFile[i] == '/' || InFile[i] == '\\') slash = i; + BaseName = InFile + slash + 1; + + PEFile DLL(InFile); + if(DLL.read16() != 0x5A4D) //"MZ" + Shutdown_M("Not a valid Windows PE file"); + + DLL.seek(60); + DLL.seek(DLL.read32(), 6); unsigned SegmentCount = DLL.read16(); + DLL.skip(12); unsigned OptionalHeaderSize = DLL.read16(); + DLL.skip(30); unsigned ImageBase = DLL.read32(); + DLL.skip(OptionalHeaderSize, -32); + + for(i=0; i UINT_MAX-DLL.rdata.offset || DLL.rdata.size+DLL.rdata.offset > DLL.brc.end) + Shutdown_M(".rdata segment is invalid"); + else if(DLL.data.size > UINT_MAX-DLL.data.offset || DLL.data.size+DLL.data.offset > DLL.brc.end) + Shutdown_M(".data segment is invalid"); + + printf("\n****\n** [ 1 of 2] RTTI Report for %s\n****\n", BaseName); + + RTTIVector RCL; + RCL.init(); + + DLL.lookat(DLL.data); + unsigned TotalClassCount = 0; + while(DLL.skip(8) && DLL.memfind(".?AV", 4, PEFile::Parse_QuestionMark)){ + TotalClassCount++; + size_t length = DLL.strlen(); + if(length == (unsigned)-1) + Shutdown_M("Unexpectedly reached end of binary"); + + size_t TDAddress = DLL.brc.position + ImageBase - 8, datapos = DLL.brc.position + length + 1; + DLL.lookat(DLL.rdata); + + RTTIClass * RCPointer = NULL; + + for(size_t rdatapos = DLL.brc.position + 12; + DLL.seek(rdatapos) && DLL.find32(TDAddress); rdatapos += 4, DLL.lookat(DLL.rdata)){ + //Find all complete object locators that belong to this class + rdatapos = DLL.brc.position; + if(!DLL.skip(4)) + continue; + size_t CDAddress = DLL.read32() - ImageBase; + if(CDAddress < DLL.brc.start || CDAddress > DLL.brc.end-4) + continue; //This was a base class descriptor + + //Add this COL to our respective RTTIClass + bool newclass = false; + if(RCPointer == NULL){ + //This is a new class; add it to the RCL + newclass = true; + RTTIClass& RC = RCL.add(); + RCPointer = &RC; + RC.init(); + } + RTTIClass& RC = *RCPointer; + + RTTICompleteObjectLocator& COL = RC.COLL.add(); + + DLL.seek(rdatapos,-12); + size_t COLAddress = DLL.brc.position + ImageBase; + if(!DLL.Fill(COL)) + Shutdown_M("Unexpectedly reached end of binary"); + + DLL.lookat(DLL.rdata); + COL.VTableAddress = (DLL.find32(COLAddress)) ? DLL.brc.position + ImageBase : (uint32_t)-1; + + if(newclass){ + if(!DLL.seek(COL.Fields.ClassDescriptorAddress - ImageBase)) + Shutdown_M("Unexpectedly reached end of binary"); + RTTIClassHierarchyDescriptor& CHD = RC.CHD; + if(!DLL.Fill(CHD)) + Shutdown_M("Unexpectedly reached end of binary"); + + if(!DLL.seek(CHD.Fields.BaseClassListAddress - ImageBase)) + Shutdown_M("Unexpectedly reached end of binary"); + size_t bcdlpos; + for(i=0, bcdlpos = DLL.brc.position; i= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || c == '_') + ? c : ' '; + } + BCD.TD.UnmangledName[length-6] = '\0'; + + if(newclass){ + newclass = false; + memcpy(&RC.TD, &BCD.TD, sizeof(RTTITypeDescriptor)); + } + } + } + } + + DLL.lookat(DLL.data); + DLL.seek(datapos); + } + + for (i=0; i 1){ + //The first BCD always refers to the class itself, e.g. class A "depends on class A". + printf(" : %s", RC.CHD.BCDL.Buffer[1].TD.UnmangledName); + for(uint32_t j=2; j #include "tsoscan.h" -void print_usage(){ +static void print_usage(){ printf("Usage: tsoscan [-f] [-o outfile] indir1 [indir2 [...]]\n" "Generate a statistical HTML page based on a number of IFF files.\n" "Use -f to force overwriting without confirmation.\n" @@ -43,7 +43,7 @@ int main(int argc, char *argv[]){ FILE *OutFile; if(!stats_create(&Stats)){ - printf("%sUnable to allocate enough memory.\n", TSOSCAN_ERROR); + fprintf(stderr, "%sUnable to allocate enough memory.\n", TSOSCAN_ERROR); return -1; } @@ -71,7 +71,7 @@ int main(int argc, char *argv[]){ unsigned DirStartIndex; if(dir == NULL){ - printf("%sUnable to open the specified directory '%s'. Skipping.\n", TSOSCAN_WARNING, CmdArgs->InDirs[i]); + fprintf(stderr, "%sUnable to open the specified directory '%s'. Skipping.\n", TSOSCAN_WARNING, CmdArgs->InDirs[i]); continue; } @@ -83,7 +83,7 @@ int main(int argc, char *argv[]){ rewinddir(dir); Files = realloc(Files, FileCount*sizeof(char**)); if(Files == NULL){ - printf("%sUnable to allocate enough memory.\n", TSOSCAN_ERROR); + fprintf(stderr, "%sUnable to allocate enough memory.\n", TSOSCAN_ERROR); return -1; } @@ -94,7 +94,7 @@ int main(int argc, char *argv[]){ int pathlen = strlen(entry->d_name); Files[DirStartIndex] = malloc(dirlen+pathlen+2); if(Files[DirStartIndex] == NULL){ - printf("%sUnable to allocate enough memory.\n", TSOSCAN_ERROR); + fprintf(stderr, "%sUnable to allocate enough memory.\n", TSOSCAN_ERROR); return -1; } @@ -126,7 +126,7 @@ int main(int argc, char *argv[]){ file = fopen(Files[i], "rb"); if(file == NULL){ - printf("%sUnable to open the specified file '%s'. Skipping.\n", TSOSCAN_WARNING, Files[i]); + fprintf(stderr, "%sUnable to open the specified file '%s'. Skipping.\n", TSOSCAN_WARNING, Files[i]); continue; } fseek(file, 0, SEEK_END); @@ -135,11 +135,11 @@ int main(int argc, char *argv[]){ data = malloc(FileSize); if(data == NULL){ - printf("%sUnable to allocate memory for the specified files.\n", TSOSCAN_ERROR); + fprintf(stderr, "%sUnable to allocate memory for the specified files.\n", TSOSCAN_ERROR); return -1; } - if(!fread(data, FileSize, 1, file)){ - printf("%sUnable to read the specified file '%s'. Skipping.\n", TSOSCAN_WARNING, Files[i]); + if(fread(data, 1, FileSize, file) != FileSize){ + fprintf(stderr, "%sUnable to read the specified file '%s'. Skipping.\n", TSOSCAN_WARNING, Files[i]); free(data); fclose(file); continue; @@ -147,7 +147,7 @@ int main(int argc, char *argv[]){ fclose(file); if(!iff_create(&iff)){ - printf("%sUnable to allocate memory for the specified files.\n", TSOSCAN_ERROR); + fprintf(stderr, "%sUnable to allocate memory for the specified files.\n", TSOSCAN_ERROR); return -1; } if(!iff_read_header(&iff, data, FileSize) || !iff_enumerate_chunks(&iff, data+64, FileSize-64)){ @@ -168,7 +168,7 @@ int main(int argc, char *argv[]){ for(ChunkIndex = 0, ChunkData = iff.Chunks; ChunkIndex < iff.ChunkCount; ChunkIndex++, ChunkData++){ unsigned version = stats_get_version(ChunkData->Type, ChunkData->Data); if(!stats_version_increment(&Stats, ChunkData->Type, version)){ - printf("%sUnable to allocate enough memory.\n", TSOSCAN_ERROR); + fprintf(stderr, "%sUnable to allocate enough memory.\n", TSOSCAN_ERROR); return -1; } } @@ -192,7 +192,7 @@ int main(int argc, char *argv[]){ } OutFile = fopen(CmdArgs->OutFile, "wb"); if(OutFile == NULL){ - printf("%sThe output file '%s' could not be opened for writing.", TSOSCAN_ERROR, CmdArgs->OutFile); + fprintf(stderr, "%sThe output file '%s' could not be opened for writing.", TSOSCAN_ERROR, CmdArgs->OutFile); return -1; }