Added rtti-reader and made various cleanups, switching to Shutdown_M for error handling

This commit is contained in:
Fatbag 2012-12-03 12:31:24 -06:00
parent 5444c9aea6
commit 6dddbd2efa
25 changed files with 771 additions and 194 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -23,7 +23,21 @@
#include <time.h>
#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;
}

View file

@ -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

View file

@ -1,7 +1,5 @@
/*
FileHandler - General-purpose file handling library for Niotso
utkdecode.c - Copyright (c) 2011-2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
utkdecode.c - Copyright (c) 2011-2012 Fatbag <X-Fi6@phppoll.org>
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);
}

View file

@ -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);
}

1
Server/AUTHORS Normal file
View file

@ -0,0 +1 @@
Fatbag <X-Fi6@phppoll.org>

2
Server/CHANGES Normal file
View file

@ -0,0 +1,2 @@
Technical Preview 1
* Initial release

View file

@ -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
<http://wiki.niotso.org/Niotso/Legal_Summary>
---
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

0
Server/README Normal file
View file

View file

@ -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);

21
Server/TODO Normal file
View file

@ -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:
<http://wiki.niotso.org/Niotso_Release_Schedule>
//----------//
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

View file

@ -1,4 +1,5 @@
add_subdirectory(FARDive)
add_subdirectory(hitutils)
add_subdirectory(iff2html)
add_subdirectory(rtti-reader)
add_subdirectory(tsoscan)

View file

@ -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");

View file

@ -41,7 +41,7 @@ DECLARE_INTERFACE(cUnknownObject1)
DWORD Unknown12;
};
DECLARE_INTERFACE(cEdithEditorCOMDirector)
DECLARE_INTERFACE(cTSOEdithEditorDCOMDirector)
{
void * vtable2;
void * vtable1;

View file

@ -1 +1 @@
gcc -Wall -Wextra -Wabi -pedantic -m32 -o TSOEdithEditor.exe TSOEdithEditor.cpp -mconsole
gcc -Wall -Wextra -Wabi -pedantic -fno-exceptions -m32 -o TSOEdithEditor.exe TSOEdithEditor.cpp -mconsole

View file

@ -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);

View file

@ -19,8 +19,9 @@
#include <basetyps.h>
#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;

View file

@ -1 +1 @@
gcc -Wall -Wextra -Wabi -pedantic -m32 -o TSOSimulatorClient.exe TSOSimulatorClient.cpp -mconsole
gcc -Wall -Wextra -Wabi -pedantic -fno-exceptions -m32 -o TSOSimulatorClient.exe TSOSimulatorClient.cpp -mconsole

View file

@ -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;
}

View file

@ -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})

View file

@ -0,0 +1,524 @@
/*
rtti-reader - The Sims Online MSVC RTTI Class Hierarchy Extractor
rtti-reader.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
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:
//<http://www.openrce.org/articles/full_view/23>
//<https://www.blackhat.com/presentations/bh-dc-07/Sabanal_Yason/Paper/bh-dc-07-Sabanal_Yason-WP.pdf>
//For information about the Windows PE header, read:
//<https://en.wikibooks.org/wiki/X86_Disassembly/Windows_Executable_Files#File_Format>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#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 <class T>
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<RTTIBaseClassDescriptor> 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<RTTICompleteObjectLocator> COLL;
RTTITypeDescriptor TD;
RTTIClassHierarchyDescriptor CHD;
void init(){
COLL.init();
CHD.BCDL.init();
}
bool DependsOn(const RTTIClass& X) const {
for(uint32_t i=1; i<CHD.BCDL.Count; i++)
if(CHD.BCDL.Buffer[i].TD.Fields.Address == X.TD.Fields.Address)
return true;
return false;
}
static int Compare(const void * Aptr, const void * Bptr){
const RTTIClass& A = *reinterpret_cast<const RTTIClass*>(Aptr);
const RTTIClass& B = *reinterpret_cast<const RTTIClass*>(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<size);
skip(-(int)i); //Seek back
return true;
}
bool find32(uint32_t address){
char buffer[4];
write_uint32(buffer, address);
return memfind(buffer, 4);
}
bool GenericFill(uint8_t *ptr, size_t count){
const size_t padding = offsetof(PaddingTest,B)-offsetof(PaddingTest,A);
count -= padding;
if(count > brc.end - brc.position)
return false;
uint32_t *field = reinterpret_cast<uint32_t*>(ptr);
*field = brc.position; //The Address field always comes first
do {
ptr += padding; count -= padding;
field = reinterpret_cast<uint32_t*>(ptr);
*field = read32();
} while(count);
return true;
}
template <class T>
inline bool Fill(T& context) {
return GenericFill(reinterpret_cast<uint8_t*>(&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 <X-Fi6@phppoll.org>.\n"
"rtti-reader is maintained by the Niotso project.\n"
"Home page: <http://www.niotso.org/>\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<SegmentCount; i++){
if(!DLL.strcmp(".rdata")){
DLL.skip(8); DLL.rdata.size = DLL.read32();
DLL.rdata.offset = DLL.read32();
DLL.skip(24);
} else if(!DLL.strcmp(".data")){
DLL.skip(8); DLL.data.size = DLL.read32();
DLL.data.offset = DLL.read32();
DLL.skip(24);
} else DLL.skip(40);
}
if(DLL.rdata.size == 0)
Shutdown_M("Missing .rdata segment");
else if(DLL.data.size == 0)
Shutdown_M("Missing .data segment");
else if(DLL.rdata.size > 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<RTTIClass> 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<CHD.Fields.BaseClassCount; i++, bcdlpos+=4){
DLL.lookat(DLL.rdata);
if(!DLL.seek(bcdlpos))
Shutdown_M("Unexpectedly reached end of binary");
uint32_t BCDAddress = DLL.read32();
if(!DLL.seek(BCDAddress - ImageBase))
Shutdown_M("Unexpectedly reached end of binary");
RTTIBaseClassDescriptor& BCD = CHD.BCDL.add();
if(!DLL.Fill(BCD))
Shutdown_M("Unexpectedly reached end of binary");
DLL.lookat(DLL.data);
if(!DLL.seek(BCD.Fields.TypeDescriptorAddress - ImageBase))
Shutdown_M("Unexpectedly reached end of binary");
if(!DLL.Fill(BCD.TD))
Shutdown_M("Unexpectedly reached end of binary");
length = DLL.strlen();
if(length == (unsigned)-1)
Shutdown_M("Unexpectedly reached end of binary");
BCD.TD.Name = (char*) malloc(length+1);
BCD.TD.UnmangledName = (char*) malloc(length+1-6);
if(!BCD.TD.Name || !BCD.TD.UnmangledName)
Shutdown_M("Failed to allocate memory");
DLL.strcpy(BCD.TD.Name);
for(size_t j=0; j<length-6; j++){
char c = BCD.TD.Name[j+4];
BCD.TD.UnmangledName[j] = (
(c >= '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<RCL.Count; i++){
RTTIClass& RC = RCL.Buffer[i];
RTTIClassHierarchyDescriptor& CHD = RC.CHD;
printf("\nClass %s (mangled: %s)\n", RC.TD.UnmangledName, RC.TD.Name);
printf(" * Class Hierarchy Descriptor: (Address %08X)\n", CHD.Fields.Address + ImageBase);
printf(" * Reserved: %u\n", CHD.Fields.Reserved);
printf(" * Attributes: %u\n", CHD.Fields.Attributes);
printf(" * Base class count: %u\n", CHD.Fields.BaseClassCount);
printf(" * Base class list address: %08X\n", CHD.Fields.BaseClassListAddress);
for(uint32_t j=0; j<CHD.Fields.BaseClassCount; j++){
RTTIBaseClassDescriptor& BCD = CHD.BCDL.Buffer[j];
printf(" * Base class descriptor #%u: (Address %08X)\n", j, BCD.Fields.Address + ImageBase);
printf(" * Base class count: %u\n", BCD.Fields.BaseClassCount);
printf(" * Member offset: %d\n", BCD.Fields.MemberOffset);
printf(" * COL address offset: %d\n", BCD.Fields.COLAddressOffset);
printf(" * v-table offset: %d\n", BCD.Fields.VTableOffset);
printf(" * Attributes: %u\n", BCD.Fields.Attributes);
printf(" * Type descriptor: (Address %08X)\n", BCD.Fields.TypeDescriptorAddress);
printf(" * v-table address: %08X\n", BCD.TD.Fields.VTableAddress);
printf(" * Reserved: %u\n", BCD.TD.Fields.Reserved);
printf(" * Name: %s (mangled: %s)\n", BCD.TD.UnmangledName, BCD.TD.Name);
}
for(uint32_t j=0; j<RC.COLL.Count; j++){
RTTICompleteObjectLocator& COL = RC.COLL.Buffer[j];
printf(" * Complete object locator #%u: (Address %08X)\n", j, COL.Fields.Address + ImageBase);
printf(" * Reserved: %u\n", COL.Fields.Reserved);
printf(" * Offset: %d\n", COL.Fields.Offset);
printf(" * CD Offset: %d\n", COL.Fields.CDOffset);
printf(" * Type descriptor address: %08X\n", COL.Fields.TypeDescriptorAddress);
printf(" * Class descriptor address: %08X\n", COL.Fields.ClassDescriptorAddress);
printf(" * v-table address: %08X\n", COL.VTableAddress);
}
}
printf("\n****\n** [ 2 of 2 ] Class Hierarchy for %s\n****\n", BaseName);
qsort(RCL.Buffer, RCL.Count, sizeof(RTTIClass), RTTIClass::Compare);
for(i=0; i<RCL.Count; i++){
RTTIClass& RC = RCL.Buffer[i];
printf("\nclass %s", RC.TD.UnmangledName);
if(RC.CHD.BCDL.Count > 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<RC.CHD.BCDL.Count; j++)
printf(", %s", RC.CHD.BCDL.Buffer[j].TD.UnmangledName);
}
printf(";");
}
printf("\n\nCompleted RTTI report.\nDependencies provided for %u of %u classes.\n", RCL.Count, TotalClassCount);
return 0;
}

View file

@ -24,7 +24,7 @@
#include <iff/iff.h>
#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;
}