From bc978bfa0b6767f9f4544e5892c66b9b80a24477 Mon Sep 17 00:00:00 2001 From: Fatbag Date: Thu, 14 Jun 2012 09:19:13 -0500 Subject: [PATCH] * Rewrote all of the chunk parsers to use a bytestream reader. Most noticeably, all of the string-reading code is shared now, and all of the "Size -="s have been taken out. * Condensed STR# reading of formats 0, -1, -2, and -4 together. * The STR# parser now supports "formatless" format 0 STR# chunks. * Made all of the command-line tools cross-platform; replaced file IO with fopen()/etc, and replaced time measurement with clock(). There is no longer a dependency on Windows.h. * Added a "Server GUI" folder to tools. Niotso Server will basically be a background daemon., and communication would "normally" be through the command line until you run a GUI. --- Libraries/FileHandler/far/farextract.c | 122 ++++++------- Libraries/FileHandler/iff/bcon.c | 7 +- Libraries/FileHandler/iff/cats.c | 27 +-- Libraries/FileHandler/iff/fcns.c | 69 ++----- Libraries/FileHandler/iff/glob.c | 38 +--- Libraries/FileHandler/iff/iff.c | 16 +- Libraries/FileHandler/iff/iff.h | 9 +- Libraries/FileHandler/iff/iffexport.c | 72 +++++--- Libraries/FileHandler/iff/iffparser.h | 146 +++++++++++++++ Libraries/FileHandler/iff/palt.c | 7 +- Libraries/FileHandler/iff/rsmp.c | 78 +++----- Libraries/FileHandler/iff/spr.c | 76 ++------ Libraries/FileHandler/iff/str.c | 241 +++++++------------------ Libraries/FileHandler/iff/string.c | 18 +- Libraries/FileHandler/iff/tmpl.c | 28 ++- Libraries/FileHandler/iff/trcn.c | 79 +++----- Libraries/FileHandler/utk/utkdecode.c | 69 ++++--- Libraries/FileHandler/xa/xadecode.c | 69 ++++--- Tools/Server GUI/CMakeLists.txt | 0 Tools/iff2html/iff2html.c | 1 + 20 files changed, 515 insertions(+), 657 deletions(-) create mode 100644 Libraries/FileHandler/iff/iffparser.h create mode 100644 Tools/Server GUI/CMakeLists.txt diff --git a/Libraries/FileHandler/far/farextract.c b/Libraries/FileHandler/far/farextract.c index 9864f63..990c02d 100644 --- a/Libraries/FileHandler/far/farextract.c +++ b/Libraries/FileHandler/far/farextract.c @@ -16,25 +16,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "config.h" - -#define _CRT_SECURE_NO_WARNINGS -#include -#include +#include #include - -#ifdef HAVE_STDINT_H - #include -#else - typedef signed char int8_t; - typedef unsigned char uint8_t; - typedef signed short int16_t; - typedef unsigned short uint16_t; - typedef signed long int32_t; - typedef unsigned long uint32_t; - typedef unsigned int uintptr_t; -#endif - +#include +#include +#include +#include "config.h" #include "libfar.h" enum { @@ -49,15 +36,12 @@ enum { int main(int argc, char *argv[]){ int profile = 0, overwrite = 0; char infile[256] = "", outdirectory[256] = ""; - - HANDLE ProcessHeap = GetProcessHeap(); - HANDLE hFile; - DWORD ArchiveSize; - DWORD bytestransferred = 0; + FILE * hFile; + size_t ArchiveSize; uint8_t * ArchiveData; int ArchiveType; - - unsigned BeginningTime, EndingTime; + clock_t BeginningTime, EndingTime; + unsigned extracted = 0; int i; /**** @@ -121,33 +105,32 @@ int main(int argc, char *argv[]){ libfar_set_option(LIBFAR_CONFIG_REFPACK_HNSV, 0xFB); /**** - ** Attempt to open the file and read in the entire contents to memory + ** Open the file and read in the entire contents to memory */ - hFile = CreateFile(infile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - if(GetLastError() == ERROR_FILE_NOT_FOUND){ - printf("%sThe specified input file does not exist.", "farextract: error: "); - return -1; - } - printf("%sThe input file could not be opened for reading.", "farextract: error: "); + hFile = fopen(infile, "rb"); + if(hFile == NULL){ + printf("%sThe specified input file does not exist or could not be opened for reading.", "farextract: error: "); return -1; } - ArchiveSize = GetFileSize(hFile, NULL); - if(ArchiveSize < LIBFAR_ARCHIVE_MINIMUM_SIZE){ + fseek(hFile, 0, SEEK_END); + ArchiveSize = ftell(hFile); + if(ArchiveSize < 24){ printf("%sNot a valid archive.", "farextract: error: "); return -1; } - ArchiveData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, ArchiveSize); + fseek(hFile, 0, SEEK_SET); + + ArchiveData = malloc(ArchiveSize); if(ArchiveData == NULL){ printf("%sMemory for this archive could not be allocated.", "farextract: error: "); return -1; } - if(!ReadFile(hFile, ArchiveData, ArchiveSize, &bytestransferred, NULL) || bytestransferred != ArchiveSize){ + if(!fread(ArchiveData, ArchiveSize, 1, hFile)){ printf("%sThe input file could not be read.", "farextract: error: "); return -1; } - CloseHandle(hFile); + fclose(hFile); /**** ** Identify the type of archive @@ -179,7 +162,7 @@ int main(int argc, char *argv[]){ filescount = FARFileInfo->Files; printf("This archive contains %u files.\n\nExtracting\n", filescount); - BeginningTime = GetTickCount(); + BeginningTime = clock(); /**** ** Load entry information @@ -211,12 +194,20 @@ int main(int argc, char *argv[]){ } /* Decompression, if any, was successful */ - hFile = CreateFile(destination, GENERIC_WRITE, 0, NULL, CREATE_NEW+overwrite, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - printf(" (%u/%u) Skipped (%s): %s\n", file, filescount, - (!overwrite && GetLastError() == ERROR_FILE_EXISTS) ? "file exists" : "could not open", - EntryNode->Entry.Filename); + if(!overwrite){ + hFile = fopen(destination, "rb"); + if(hFile != NULL){ + /* File exists */ + fclose(hFile); + printf(" (%u/%u) Skipped (%s): %s\n", file, filescount, "could not open", EntryNode->Entry.Filename); + if(EntryNode->Entry.DecompressedData != EntryNode->Entry.CompressedData) + libfar_free(EntryNode->Entry.DecompressedData); + continue; + } + } + hFile = fopen(destination, "wb"); + if(hFile == NULL){ + printf(" (%u/%u) Skipped (%s): %s\n", file, filescount, "could not open", EntryNode->Entry.Filename); if(EntryNode->Entry.DecompressedData != EntryNode->Entry.CompressedData) libfar_free(EntryNode->Entry.DecompressedData); continue; @@ -230,15 +221,15 @@ int main(int argc, char *argv[]){ EntryNode->Entry.TypeID, EntryNode->Entry.GroupID, EntryNode->Entry.FileID, EntryNode->Entry.DecompressedSize); - WriteFile(hFile, EntryNode->Entry.DecompressedData, - EntryNode->Entry.DecompressedSize, &bytestransferred, NULL); - CloseHandle(hFile); + fwrite(EntryNode->Entry.DecompressedData, 1, EntryNode->Entry.DecompressedSize, hFile); + fclose(hFile); if(EntryNode->Entry.DecompressedData != EntryNode->Entry.CompressedData) libfar_free(EntryNode->Entry.DecompressedData); + extracted++; } - printf("\nFinished extracting %u of %u files in %.2f seconds.", file, filescount, - ((float) (GetTickCount() - BeginningTime))/1000); + printf("\nFinished extracting %u of %u files in %.2f seconds.", extracted, filescount, + ((float) (clock() - BeginningTime))/CLOCKS_PER_SEC); }else{ /* Persist file */ PersistFile * PersistInfo; @@ -263,25 +254,34 @@ int main(int argc, char *argv[]){ ** Extract the data */ printf("Extracting\n"); - BeginningTime = GetTickCount(); + BeginningTime = clock(); if(!far_read_persist_data(PersistInfo, ArchiveData+18)){ printf("%sNot a valid archive.", "farextract: error: "); return -1; } - EndingTime = GetTickCount(); + EndingTime = clock(); - hFile = CreateFile(destination, GENERIC_WRITE, 0, NULL, CREATE_NEW+overwrite, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - printf((!overwrite && GetLastError() == ERROR_FILE_EXISTS) ? - "%sFile exists." : "%sCould not open.", "farextract: error: "); + if(!overwrite){ + hFile = fopen(destination, "rb"); + if(hFile != NULL){ + /* File exists */ + fclose(hFile); + printf("%sFile exists.", "farextract: error: "); + libfar_free(PersistInfo->DecompressedData); + return -1; + } + } + hFile = fopen(destination, "wb"); + if(hFile == NULL){ + printf("%sCould not open.", "farextract: error: "); + libfar_free(PersistInfo->DecompressedData); return -1; } - WriteFile(hFile, PersistInfo->DecompressedData, - PersistInfo->DecompressedSize, &bytestransferred, NULL); - CloseHandle(hFile); + + fwrite(PersistInfo->DecompressedData, 1, PersistInfo->DecompressedSize, hFile); + fclose(hFile); printf("Extracted %u bytes in %.2f seconds.\n", PersistInfo->DecompressedSize, - ((float) (EndingTime - BeginningTime))/1000); + ((float) (EndingTime - BeginningTime))/CLOCKS_PER_SEC); } return 0; } \ No newline at end of file diff --git a/Libraries/FileHandler/iff/bcon.c b/Libraries/FileHandler/iff/bcon.c index 750888e..b5647aa 100644 --- a/Libraries/FileHandler/iff/bcon.c +++ b/Libraries/FileHandler/iff/bcon.c @@ -17,14 +17,13 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFF_BCON *BCONData; - unsigned Size = ChunkInfo->Size - 76; unsigned i; - if(Size < 2) + if(ChunkInfo->Size < 2) return 0; ChunkInfo->FormattedData = calloc(1, sizeof(IFF_BCON)); if(ChunkInfo->FormattedData == NULL) @@ -35,7 +34,7 @@ int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){ BCONData->Flags = read_uint8le(Buffer + 1); if(BCONData->ConstantCount == 0) return 1; - if(BCONData->ConstantCount * 2 /* bytes */ > Size - 2) + if(BCONData->ConstantCount * 2 /* bytes */ > ChunkInfo->Size - 2) return 0; BCONData->Constants = malloc(BCONData->ConstantCount * sizeof(uint16_t)); diff --git a/Libraries/FileHandler/iff/cats.c b/Libraries/FileHandler/iff/cats.c index af3c70b..66400f7 100644 --- a/Libraries/FileHandler/iff/cats.c +++ b/Libraries/FileHandler/iff/cats.c @@ -16,36 +16,19 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_cats(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFStringPair * StringData; - unsigned Size = ChunkInfo->Size - 76; - int s; + bytestream b; + set_bytestream(&b, Buffer, ChunkInfo->Size); ChunkInfo->FormattedData = calloc(1, sizeof(IFFStringPair)); if(ChunkInfo->FormattedData == NULL) return 0; + StringData = ChunkInfo->FormattedData; - - for(s=0; s<2; s++){ - unsigned length; - for(length=0; length != Size && Buffer[length]; length++); - if(length == Size) return 0; - - if(length != 0){ - char ** string = (s==0) ? &StringData->Key : &StringData->Value; - *string = malloc(length+1); - if(*string == NULL) return 0; - strcpy(*string, (char*) Buffer); - - Buffer += length; - Size -= length; - } - Buffer++; Size--; - } - - return 1; + return (read_c_string(&b, &StringData->Key) && read_c_string(&b, &StringData->Value)); } void iff_free_cats(void * FormattedData){ diff --git a/Libraries/FileHandler/iff/fcns.c b/Libraries/FileHandler/iff/fcns.c index 4ed1938..05f7b32 100644 --- a/Libraries/FileHandler/iff/fcns.c +++ b/Libraries/FileHandler/iff/fcns.c @@ -16,25 +16,26 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_fcns(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFConstantList *List; - unsigned Size = ChunkInfo->Size - 76; + bytestream b; unsigned i; - if(Size < 16) + if(ChunkInfo->Size < 16) return 0; + set_bytestream(&b, Buffer, ChunkInfo->Size); ChunkInfo->FormattedData = calloc(1, sizeof(IFFConstantList)); if(ChunkInfo->FormattedData == NULL) return 0; List = ChunkInfo->FormattedData; - List->Reserved = read_uint32le(Buffer); - List->Version = read_uint32le(Buffer+4); - memcpy(List->MagicNumber, Buffer+8, 4); - List->MagicNumber[4] = 0x00; - List->ConstantCount = read_uint32le(Buffer+12); + List->Reserved = read_uint32(&b); + List->Version = read_uint32(&b); + memcpy(List->MagicNumber, b.Buffer, 4); + skipbytes(&b, 4); + List->ConstantCount = read_uint32(&b); if(List->Reserved != 0 || List->Version == 0 || List->Version > 2) return 0; @@ -42,61 +43,29 @@ int iff_parse_fcns(IFFChunk * ChunkInfo, const uint8_t * Buffer){ if(List->Constants == NULL) return 0; - Buffer += 16; Size -= 16; for(i=0; iConstantCount; i++){ IFFConstant * Constant = &List->Constants[i]; unsigned s; for(s=0; s<2; s++){ char ** string = (s==0) ? &Constant->Name : &Constant->Description; - unsigned length; - if(Size == 0) return 0; - if(List->Version < 2){ - /* C string */ - for(length=0; length != Size && Buffer[length]; length++); - if(length == Size) return 0; - - if(length != 0){ - *string = malloc(length+1); - if(*string == NULL) return 0; - strcpy(*string, (char*) Buffer); - } - - Buffer += length+1; - Size -= length+1; + /* C string, possible padding */ + if(!read_c_string(&b, string)) + return 0; /* Skip past the 0xA3 character; ** see global.iff chunk 546 for why you can't do modulo-2 to detect this */ - if(Size && *Buffer == 0xA3){ - Buffer++; Size--; - } + if(b.Size && *b.Buffer == 0xA3) + skipbytes(&b, 1); }else{ - /* Pascal string */ - length = read_uint8le(Buffer); - Buffer++; Size--; - if(length > 127){ - if(Size == 0) return 0; - length = (length&127) | (read_uint8le(Buffer)<<7); - Buffer++; Size--; - } - - if(length != 0){ - *string = malloc(length+1); - if(*string == NULL) return 0; - memcpy(*string, Buffer, length); - (*string)[length] = 0x00; - } - - Buffer += length; - Size -= length; + /* Extended Pascal string, no padding */ + if(!read_pascal2_string(&b, string)) + return 0; } if(s == 0){ - union { float f; uint32_t v; } value; - if(Size < 4) return 0; - value.v = read_uint32le(Buffer); - Constant->Value = value.f; - Buffer+=4; Size-=4; + if(b.Size < 4) return 0; + Constant->Value = read_float(&b); } } } diff --git a/Libraries/FileHandler/iff/glob.c b/Libraries/FileHandler/iff/glob.c index 090ce23..5eecf52 100644 --- a/Libraries/FileHandler/iff/glob.c +++ b/Libraries/FileHandler/iff/glob.c @@ -16,39 +16,13 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_glob(IFFChunk * ChunkInfo, const uint8_t * Buffer){ - char ** string = (char**) &ChunkInfo->FormattedData; - unsigned Size = ChunkInfo->Size - 76; - unsigned length; + bytestream b; + set_bytestream(&b, Buffer, ChunkInfo->Size); - if(Size == 0){ - *string = NULL; - return 0; - } - - /* Try reading as a C string */ - for(length=0; length != Size && Buffer[length] && Buffer[length] != 0xA3; length++); - - if(length != Size && !Buffer[length] /* null character; in these strings, 0xA3 doesn't count */){ - if(length > 0){ - *string = malloc(length+1); - if(*string == NULL) return 0; - strcpy(*string, (char*) Buffer); - } - return 1; - } - - /* Try again as a Pascal string */ - length = Buffer[0]; - if(length >= Size) return 0; - - if(length > 0){ - *string = malloc(length+1); - if(*string == NULL) return 0; - memcpy(*string, Buffer+1, length); - (*string)[length] = 0x00; - } - return 1; + /* Try reading as a C string, and if that fails, again as a Pascal string */ + return (read_c_string(&b, (char**) &ChunkInfo->FormattedData) || + read_pascal_string(&b, (char**) &ChunkInfo->FormattedData)); } \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iff.c b/Libraries/FileHandler/iff/iff.c index 0f7ae79..4b311cd 100644 --- a/Libraries/FileHandler/iff/iff.c +++ b/Libraries/FileHandler/iff/iff.c @@ -17,7 +17,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" /**** ** Supported Chunks @@ -91,7 +91,7 @@ IFFFile * iff_create() IFFFile *ptr = calloc(1, sizeof(IFFFile)); if(ptr == NULL) return NULL; - ptr->Chunks = malloc(sizeof(IFFChunk)); + ptr->Chunks = calloc(1, sizeof(IFFChunk)); if(ptr->Chunks == NULL){ free(ptr); return NULL; @@ -151,11 +151,13 @@ int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChu if(ChunkInfo->Size < 76 || ChunkInfo->Size > MaxChunkSize) return 0; - if(ChunkInfo->Size > 76){ - ChunkInfo->Data = malloc(ChunkInfo->Size - 76); + ChunkInfo->Size -= 76; + + if(ChunkInfo->Size){ + ChunkInfo->Data = malloc(ChunkInfo->Size); if(ChunkInfo->Data == NULL) return 0; - memcpy(ChunkInfo->Data, Buffer+76, ChunkInfo->Size - 76); + memcpy(ChunkInfo->Data, Buffer+76, ChunkInfo->Size); } ChunkInfo->FormattedData = NULL; @@ -171,8 +173,8 @@ int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned if(!iff_read_chunk(chunk, Buffer, BufferSize)) return 0; - Buffer += chunk->Size; - BufferSize -= chunk->Size; + Buffer += chunk->Size + 76; + BufferSize -= chunk->Size + 76; } return 1; } diff --git a/Libraries/FileHandler/iff/iff.h b/Libraries/FileHandler/iff/iff.h index 90c1289..8a11ab2 100644 --- a/Libraries/FileHandler/iff/iff.h +++ b/Libraries/FileHandler/iff/iff.h @@ -17,6 +17,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef IFF_H +#define IFF_H + #include #include #include @@ -41,13 +44,13 @@ #endif /* -** IFF file headers +** IFF file structs */ typedef struct IFFChunk_s { char Type[5]; - uint32_t Size; + uint32_t Size; /* After subtracting the 76-byte header */ uint16_t ChunkID; uint16_t Flags; char Label[65]; @@ -263,4 +266,6 @@ void iff_delete(IFFFile * IFFFileInfo); #ifdef __cplusplus } +#endif + #endif \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iffexport.c b/Libraries/FileHandler/iff/iffexport.c index 78cdb3a..3e79066 100644 --- a/Libraries/FileHandler/iff/iffexport.c +++ b/Libraries/FileHandler/iff/iffexport.c @@ -16,9 +16,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #include #include -#include +#include #include "iff.h" int charmatches(char c, const char * filter){ @@ -30,14 +32,14 @@ int charmatches(char c, const char * filter){ } int main(int argc, char *argv[]){ - HANDLE hFile; + FILE * hFile; int overwrite = 0; char *InFile, *OutDirectory; - HANDLE ProcessHeap = GetProcessHeap(); - DWORD FileSize; - DWORD bytestransferred = 0; + size_t FileSize; uint8_t * IFFData; + clock_t BeginningTime; unsigned chunkcount, chunk; + unsigned exported = 0; IFFFile * IFFFileInfo; IFFChunk * ChunkData; @@ -65,30 +67,29 @@ int main(int argc, char *argv[]){ ** Open the file and read in entire contents to memory */ - hFile = CreateFile(InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - if(GetLastError() == ERROR_FILE_NOT_FOUND){ - printf("%sThe specified input file does not exist.", "iffexport: error: "); - return -1; - } - printf("%sThe input file could not be opened for reading.", "iffexport: error: "); + 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; } - FileSize = GetFileSize(hFile, NULL); - if(FileSize < 64){ + fseek(hFile, 0, SEEK_END); + FileSize = ftell(hFile); + if(FileSize < 24){ printf("%sNot a valid IFF file.", "iffexport: error: "); return -1; } - IFFData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, FileSize); + 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(!ReadFile(hFile, IFFData, FileSize, &bytestransferred, NULL) || bytestransferred != FileSize){ + if(!fread(IFFData, FileSize, 1, hFile)){ printf("%sThe input file could not be read.", "iffexport: error: "); return -1; } - CloseHandle(hFile); + fclose(hFile); /**** ** Load header information @@ -115,6 +116,7 @@ int main(int argc, char *argv[]){ chunkcount = IFFFileInfo->ChunkCount; printf("This IFF file contains %u chunks.\n\nExporting\n", chunkcount); + BeginningTime = clock(); /**** ** Extract each entry @@ -138,20 +140,34 @@ int main(int argc, char *argv[]){ sprintf(destination, "%s/%s.%s", OutDirectory, name, (!memcmp(ChunkData->Type, "BMP_", 4) || !memcmp(ChunkData->Type, "FBMP", 4)) ? "bmp" : "dat"); - hFile = CreateFile(destination, GENERIC_WRITE, 0, NULL, CREATE_NEW+overwrite, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - printf(" (%u/%u) Skipped (%s): %s\n", chunk, chunkcount, - (!overwrite && GetLastError() == ERROR_FILE_EXISTS) ? "file exists" : "could not open", - name); - continue; + if(!overwrite){ + hFile = fopen(destination, "rb"); + if(hFile != NULL){ + /* File exists */ + char c; + fclose(hFile); + printf("File \"%s\" exists.\nContinue anyway? (y/n) ", destination); + c = getchar(); + if(c != 'y' && c != 'Y'){ + printf("\nAborted."); + return -1; + } + } + overwrite++; } + hFile = fopen(destination, "wb"); + if(hFile == NULL){ + printf("%sThe output file could not be opened for writing.", "iffexport: error: "); + return -1; + } + fwrite(ChunkData->Data, 1, ChunkData->Size, hFile); + fclose(hFile); - printf(" (%u/%u) %s (%u bytes)\n", chunk, chunkcount, name, ChunkData->Size-76); - - WriteFile(hFile, ChunkData->Data, ChunkData->Size-76, &bytestransferred, NULL); - CloseHandle(hFile); + exported++; } + printf("\nExported %u of %u chunks in %.2f seconds.", exported, chunkcount, + ((float) (clock() - BeginningTime))/CLOCKS_PER_SEC); + return 0; } \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iffparser.h b/Libraries/FileHandler/iff/iffparser.h new file mode 100644 index 0000000..bdf68e5 --- /dev/null +++ b/Libraries/FileHandler/iff/iffparser.h @@ -0,0 +1,146 @@ +/* + FileHandler - General-purpose file handling library for Niotso + iffparser.h - 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. +*/ + +#include "iff.h" + +typedef struct { + const uint8_t * Buffer; + size_t Size; + const uint8_t * StartPos; + size_t TotalSize; + uint8_t Endian; /* 0 = little, 1 = big */ +} bytestream; + +static __inline void set_bytestream(bytestream * b, const uint8_t * Buffer, size_t Size){ + b->Buffer = Buffer; + b->Size = Size; + b->StartPos = Buffer; + b->TotalSize = Size; + b->Endian = 0; +} + +static __inline uint32_t read_uint32(bytestream * b){ + unsigned value = (b->Endian == 0) ? read_uint32le(b->Buffer) : read_uint32be(b->Buffer); + b->Buffer += 4; + b->Size -= 4; + return value; +} + +static __inline uint16_t read_uint16(bytestream * b){ + unsigned value = (b->Endian == 0) ? read_uint16le(b->Buffer) : read_uint16be(b->Buffer); + b->Buffer += 2; + b->Size -= 2; + return value; +} + +static __inline uint8_t read_uint8(bytestream * b){ + uint8_t value = b->Buffer[0]; + b->Buffer += 1; + b->Size -= 1; + return value; +} + +static __inline float read_float(bytestream *b){ + union { float f; uint32_t v; } value; + value.v = read_uint32(b); + return value.f; +} + +static __inline int skipbytes(bytestream * b, size_t bytes){ + if(b->Size < bytes) return 0; + b->Buffer += bytes; b->Size -= bytes; + return 1; +} + +static __inline int seekto(bytestream * b, size_t Position){ + if(Position > b->TotalSize) return 0; + b->Buffer = b->StartPos + Position; + b->Size = b->TotalSize - Position; + return 1; +} + +static __inline size_t read_c_string(bytestream * b, char ** dest){ + size_t length; + for(length=0; length != b->Size && b->Buffer[length]; length++); + if(length == b->Size) return 0; + + if(length != 0){ + *dest = malloc(length+1); + if(*dest == NULL) return 0; + strcpy(*dest, (char*) b->Buffer); + } + + b->Buffer += length + 1; + b->Size -= length + 1; + return length + 1; +} + +static __inline size_t read_pascal_string(bytestream * b, char ** dest){ + size_t length; + if(!b->Size) return 0; + length = b->Buffer[0]; + if(length >= b->Size) return 0; + + if(length > 0){ + *dest = malloc(length+1); + if(*dest == NULL) return 0; + memcpy(*dest, b->Buffer+1, length); + (*dest)[length] = 0x00; + } + + b->Buffer += 1 + length; + b->Size -= 1 + length; + return 1 + length; +} + +static __inline size_t read_pascal2_string(bytestream * b, char ** dest){ + size_t length; + int countbytes = 1; + if(!b->Size) return 0; + length = b->Buffer[0]; + + if(length > 127){ + /* 2-byte length */ + if(b->Size == 1) return 0; + length = (length&127) | (b->Buffer[1]<<7); + countbytes++; + } + + if(countbytes+length > b->Size) return 0; + + if(length != 0){ + *dest = malloc(length+1); + if(*dest == NULL) return 0; + memcpy(*dest, b->Buffer+countbytes, length); + (*dest)[length] = 0x00; + } + + b->Buffer += countbytes + length; + b->Size -= countbytes + length; + return countbytes + length; +} + +static __inline size_t skip_padding(bytestream * b){ + size_t padding = 0; + while(b->Size && b->Buffer[0] == 0xA3){ + padding++; + b->Buffer++; + b->Size--; + } + return padding; +} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/palt.c b/Libraries/FileHandler/iff/palt.c index a9fc487..7f60aa3 100644 --- a/Libraries/FileHandler/iff/palt.c +++ b/Libraries/FileHandler/iff/palt.c @@ -16,13 +16,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_palt(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFPalette *Palette; - unsigned Size = ChunkInfo->Size - 76; - if(Size < 16) + if(ChunkInfo->Size < 16) return 0; ChunkInfo->FormattedData = malloc(sizeof(IFFPalette)); if(ChunkInfo->FormattedData == NULL) @@ -34,7 +33,7 @@ int iff_parse_palt(IFFChunk * ChunkInfo, const uint8_t * Buffer){ Palette->Reserved1 = read_uint32le(Buffer+8); Palette->Reserved2 = read_uint32le(Buffer+12); if(Palette->Version != 1 || Palette->ColorCount == 0 || Palette->ColorCount > 256 || - Palette->Reserved1 != 0 || Palette->Reserved2 != 0 || Palette->ColorCount*3 > Size-16) + Palette->Reserved1 != 0 || Palette->Reserved2 != 0 || Palette->ColorCount*3 > ChunkInfo->Size-16) return 0; memcpy(Palette->Data, Buffer+16, Palette->ColorCount*3); diff --git a/Libraries/FileHandler/iff/rsmp.c b/Libraries/FileHandler/iff/rsmp.c index 16b6c82..714ea49 100644 --- a/Libraries/FileHandler/iff/rsmp.c +++ b/Libraries/FileHandler/iff/rsmp.c @@ -16,26 +16,27 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFResourceMap *Map; - unsigned Size = ChunkInfo->Size - 76; + bytestream b; unsigned i; - if(Size < 20) + if(ChunkInfo->Size < 20) return 0; + set_bytestream(&b, Buffer, ChunkInfo->Size); ChunkInfo->FormattedData = calloc(1, sizeof(IFFResourceMap)); if(ChunkInfo->FormattedData == NULL) return 0; Map = ChunkInfo->FormattedData; - Map->Reserved = read_uint32le(Buffer); - Map->Version = read_uint32le(Buffer+4); - memcpy(Map->MagicNumber, Buffer+8, 4); - Map->MagicNumber[4] = 0x00; - Map->IFFSize = read_uint32le(Buffer+12); - Map->TypeCount = read_uint32le(Buffer+16); + Map->Reserved = read_uint32(&b); + Map->Version = read_uint32(&b); + memcpy(Map->MagicNumber, b.Buffer, 4); + skipbytes(&b, 4); + Map->IFFSize = read_uint32(&b); + Map->TypeCount = read_uint32(&b); if(Map->Reserved != 0 || Map->Version > 1) return 0; @@ -43,64 +44,31 @@ int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer){ if(Map->ResourceTypes == NULL) return 0; - Buffer += 20; Size -= 20; for(i=0; iTypeCount; i++){ IFFResourceType * Type = &Map->ResourceTypes[i]; unsigned j; - if(Size < 8) return 0; - memcpy(Type->Type, Buffer, 4); - Type->Type[4] = 0x00; - Type->ResourceCount = read_uint32le(Buffer+4); + if(b.Size < 8) return 0; + + memcpy(Type->Type, b.Buffer, 4); + skipbytes(&b, 4); + Type->ResourceCount = read_uint32(&b); Type->Resources = calloc(Type->ResourceCount, sizeof(IFFResource)); if(Type->Resources == NULL) return 0; - Buffer += 8; Size -= 8; for(j=0; jResourceCount; j++){ IFFResource * Resource = &Type->Resources[j]; - unsigned length; - if(Size < ((Map->Version == 0) ? 9 : 11)) return 0; - Resource->Offset = read_uint32le(Buffer); - Buffer += 4; - if(Map->Version == 0){ - Resource->ChunkID = read_uint16le(Buffer); - Buffer += 2; Size -= 2; - }else{ - Resource->ChunkID = read_uint32le(Buffer); - Buffer += 4; Size -= 4; - } - Resource->Flags = read_uint16le(Buffer); - Buffer += 2; - Size -= 4+2; + if(b.Size < ((Map->Version == 0) ? 9 : 11)) return 0; + Resource->Offset = read_uint32(&b); + Resource->ChunkID = (Map->Version == 0) ? read_uint16(&b) : read_uint32(&b); + Resource->Flags = read_uint16(&b); if(Map->Version == 0){ - /* C string */ - for(length=0; length != Size && Buffer[length]; length++); - if(length == Size) return 0; - - if(length != 0){ - Resource->Label = malloc(length+1); - if(Resource->Label == NULL) return 0; - strcpy(Resource->Label, (char*) Buffer); - - Buffer += length; - Size -= length; - } - Buffer++; Size--; + if(!read_c_string(&b, &Resource->Label)) + return 0; }else{ - /* Pascal string */ - length = read_uint8le(Buffer); - Buffer++; Size--; - - if(length != 0){ - Resource->Label = malloc(length+1); - if(Resource->Label == NULL) return 0; - memcpy(Resource->Label, Buffer, length); - Resource->Label[length] = 0x00; - } - - Buffer += length; - Size -= length; + if(!read_pascal_string(&b, &Resource->Label)) + return 0; } } } diff --git a/Libraries/FileHandler/iff/spr.c b/Libraries/FileHandler/iff/spr.c index b39bf80..dbf898b 100644 --- a/Libraries/FileHandler/iff/spr.c +++ b/Libraries/FileHandler/iff/spr.c @@ -17,72 +17,27 @@ */ #include -#include "iff.h" - -typedef struct { - const uint8_t * StartPos; - const uint8_t * Buffer; - size_t TotalSize; - size_t Size; - uint8_t Endian; /* 0 = little, 1 = big */ -} bytestream; - -static unsigned read_uint32xe(bytestream * b){ - if(b->Size >= 4){ - unsigned value = (b->Endian == 0) ? read_uint32le(b->Buffer) : read_uint32be(b->Buffer); - b->Buffer += 4; - b->Size -= 4; - return value; - } - return 0; -} - -static unsigned read_uint16xe(bytestream * b){ - if(b->Size >= 2){ - unsigned value = (b->Endian == 0) ? read_uint16le(b->Buffer) : read_uint16be(b->Buffer); - b->Buffer += 2; - b->Size -= 2; - return value; - } - return 0; -} - -static int skipbytes(bytestream * b, uint32_t bytes){ - if(b->Size < bytes) return 0; - b->Buffer += bytes; b->Size -= bytes; - return 1; -} - -static int seekto(bytestream * b, uint32_t Position){ - if(Position > b->TotalSize) return 0; - b->Buffer = b->StartPos + Position; - b->Size = b->TotalSize - Position; - return 1; -} +#include "iffparser.h" int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFSpriteList *SpriteList; - unsigned ChunkSize = ChunkInfo->Size - 76; + unsigned ChunkSize = ChunkInfo->Size; bytestream b; unsigned i; - b.StartPos = Buffer; - b.Buffer = Buffer; - b.TotalSize = ChunkSize; - b.Size = ChunkSize; - b.Endian = 0; - if(ChunkSize < 12) return 0; + set_bytestream(&b, Buffer, ChunkSize); + ChunkInfo->FormattedData = calloc(1, sizeof(IFFSpriteList)); if(ChunkInfo->FormattedData == NULL) return 0; SpriteList = ChunkInfo->FormattedData; if((Buffer[0]|Buffer[1]) == 0) b.Endian++; /* Big endian */ - SpriteList->Version = read_uint32xe(&b); - SpriteList->SpriteCount = read_uint32xe(&b); - SpriteList->PaletteID = read_uint32xe(&b); + SpriteList->Version = read_uint32(&b); + SpriteList->SpriteCount = read_uint32(&b); + SpriteList->PaletteID = read_uint32(&b); if(SpriteList->Version < 502 || (SpriteList->Version > 505 && SpriteList->Version != 1001)) return 0; @@ -93,7 +48,7 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){ /* At this point, we are looking at the first field of the first sprite */ for(SpriteList->SpriteCount = 0; b.Size >= 18; SpriteList->SpriteCount++){ - if(read_uint32xe(&b) != 1001 || !skipbytes(&b, read_uint32xe(&b))) + if(read_uint32(&b) != 1001 || !skipbytes(&b, read_uint32(&b))) break; } seekto(&b, 12); @@ -113,20 +68,23 @@ int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){ if(SpriteList->Version != 1001){ /* Jump to the next sprite using the offset table; this is mandatory */ seekto(&b, 12 + 4*i); - if(!seekto(&b, read_uint32xe(&b))) + if(!seekto(&b, read_uint32(&b))) return 0; if((SpriteSize = b.Size) < 10) return 0; } if(SpriteList->Version == 1001){ - read_uint32xe(&b); /* Sprite version; already checked to be equal to 1001 */ - SpriteSize = read_uint32xe(&b); + seekto(&b, b.Buffer - b.StartPos); /* Resynchronize b.Size with b.Buffer */ + if(b.Size < 18) + return 0; + read_uint32(&b); /* Sprite version; already checked to be equal to 1001 */ + SpriteSize = read_uint32(&b); } - Sprite->Reserved = read_uint32xe(&b); - Sprite->Height = read_uint16xe(&b); - Sprite->Width = read_uint16xe(&b); + Sprite->Reserved = read_uint32(&b); + Sprite->Height = read_uint16(&b); + Sprite->Width = read_uint16(&b); if(Sprite->Reserved != 0 || Sprite->Height == 0 || Sprite->Width == 0 || Sprite->Height > UINT_MAX/Sprite->Width/2){ /* This happens in the third sprite of every SPR# chunk in sprites.iff */ Sprite->InvalidDimensions = 1; diff --git a/Libraries/FileHandler/iff/str.c b/Libraries/FileHandler/iff/str.c index 241ada5..d6f0232 100644 --- a/Libraries/FileHandler/iff/str.c +++ b/Libraries/FileHandler/iff/str.c @@ -17,156 +17,100 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFString * StringData; - unsigned Size = ChunkInfo->Size - 76; + bytestream b; - if(Size < 2) + if(ChunkInfo->Size < 2) return 0; + set_bytestream(&b, Buffer, ChunkInfo->Size); ChunkInfo->FormattedData = calloc(1, sizeof(IFFString)); if(ChunkInfo->FormattedData == NULL) return 0; StringData = ChunkInfo->FormattedData; - StringData->Format = read_int16le(Buffer); - if((Size-=2) < 2) /* TSO allows this; as seen in the animations chunk in personglobals.iff */ + StringData->Format = read_uint16(&b); + if(b.Size < 2) /* TSO allows this; as seen in the animations chunk in personglobals.iff */ return 1; - Buffer += 2; - switch(StringData->Format){ + if(StringData->Format < -4 || StringData->Format > 0){ + /* Seen often in The Sims 1's Behavior.iff */ + StringData->Format = 0; + seekto(&b, 0); + b.Endian++; + } - case 0: { /* 00 00 */ - unsigned i; - IFFLanguageSet * LanguageSet = &StringData->LanguageSets[0]; + if(StringData->Format != -3){ + unsigned LanguageSetCount = 1; + unsigned ls; - LanguageSet->PairCount = read_uint16le(Buffer); - Buffer += 2; Size -= 2; - if(LanguageSet->PairCount == 0) - return 1; - - LanguageSet->Pairs = calloc(LanguageSet->PairCount, sizeof(IFFStringPair)); - if(LanguageSet->Pairs == NULL) - return 0; - - for(i=0; iPairCount; i++){ - unsigned length; - - if(Size == 0) return 0; - length = read_uint8le(Buffer); - Buffer++; Size--; - if(length != 0){ - if(length > Size) return 0; - LanguageSet->Pairs[i].Key = malloc(length+1); - if(LanguageSet->Pairs[i].Key == NULL) return 0; - memcpy(LanguageSet->Pairs[i].Key, Buffer, length); - LanguageSet->Pairs[i].Key[length] = 0x00; - - Buffer += length; - Size -= length; - } + if(StringData->Format == -4){ + LanguageSetCount = read_uint8(&b); + if(LanguageSetCount > 20) return 0; } - } return 1; - case -1: { /* FF FF */ - unsigned i; - IFFLanguageSet * LanguageSet = &StringData->LanguageSets[0]; + for(ls=0; lsLanguageSets[ls]; + unsigned p; - LanguageSet->PairCount = read_uint16le(Buffer); - Buffer += 2; Size -= 2; - if(LanguageSet->PairCount == 0) - return 1; + if(b.Size < 2) return 0; + LanguageSet->PairCount = read_uint16(&b); + if(LanguageSet->PairCount == 0) + continue; - LanguageSet->Pairs = calloc(LanguageSet->PairCount, sizeof(IFFStringPair)); - if(LanguageSet->Pairs == NULL) - return 0; + LanguageSet->Pairs = calloc(LanguageSet->PairCount, sizeof(IFFStringPair)); + if(LanguageSet->Pairs == NULL) + return 0; - for(i=0; iPairCount; i++){ - unsigned length; - - for(length=0; length != Size && Buffer[length]; length++); - if(length == Size) return 0; - - if(length != 0){ - LanguageSet->Pairs[i].Key = malloc(length+1); - if(LanguageSet->Pairs[i].Key == NULL) return 0; - strcpy(LanguageSet->Pairs[i].Key, (char*) Buffer); - - Buffer += length; - Size -= length; - } - Buffer++; Size--; - } - } return 1; - - case -2: { /* FE FF */ - unsigned i; - IFFLanguageSet * LanguageSet = &StringData->LanguageSets[0]; - - LanguageSet->PairCount = read_uint16le(Buffer); - Buffer += 2; Size -= 2; - if(LanguageSet->PairCount == 0) - return 1; - - LanguageSet->Pairs = calloc(LanguageSet->PairCount, sizeof(IFFStringPair)); - if(LanguageSet->Pairs == NULL) - return 0; - - for(i=0; iPairCount; i++){ - int s; - - for(s=0; s<2; s++){ - unsigned length; - for(length=0; length != Size && Buffer[length]; length++); - if(length == Size) return 0; - - if(length != 0){ - char ** string = (s==0) ? &LanguageSet->Pairs[i].Key : &LanguageSet->Pairs[i].Value; - *string = malloc(length+1); - if(*string == NULL) return 0; - strcpy(*string, (char*) Buffer); - - Buffer += length; - Size -= length; + for(p=0; pPairCount; p++){ + IFFStringPair * Pair = &LanguageSet->Pairs[p]; + if(StringData->Format == 0){ + if(!read_pascal_string(&b, &Pair->Key)) + return 0; + }else if(StringData->Format >=-2){ + if(!read_c_string(&b, &Pair->Key)) + return 0; + if(StringData->Format == -2 && !read_c_string(&b, &Pair->Value)) + return 0; + }else{ + if(!b.Size || read_uint8(&b) != ls) + return 0; + if(!read_pascal2_string(&b, &Pair->Key) || !read_pascal2_string(&b, &Pair->Value)) + return 0; } - Buffer++; Size--; } } - } return 1; - - case -3: { /* FD FF */ + }else{ + /* FD FF requires a lot of extra work -- and isn't even found in TSO */ IFFLanguageSet * LanguageSet = StringData->LanguageSets; - unsigned i; - unsigned TotalPairCount = read_uint16le(Buffer); + unsigned TotalPairCount; unsigned Index[20] = {0}; - const uint8_t * Start = (Buffer += 2); - Size -= 2; + unsigned i; + TotalPairCount = read_uint16(&b); if(TotalPairCount == 0) return 1; /* - ** Scan through the chunk to count up the number of strings in each LanguageSet, + ** Scan through the chunk to count up the number of pairs in each LanguageSet, ** and then allocate exactly that much and fill in the data on the second pass */ /* 1st pass */ for(i=0; i= 20) return 0; LanguageSet[lang].PairCount++; - Buffer++; Size--; for(s=0; s<2; s++){ - /* Includes the string length check too */ unsigned length; - for(length=0; length != Size && Buffer[length]; length++); - if(length == Size) return 0; - Buffer += length+1; - Size -= length+1; + for(length=0; length != b.Size && b.Buffer[length]; length++); + if(length == b.Size) return 0; + skipbytes(&b, length+1); } } @@ -176,82 +120,19 @@ int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ } /* 2nd pass */ - Buffer = Start; + set_bytestream(&b, Buffer+4, ChunkInfo->Size-4); for(i=0; iKey : &Pair->Value; - *string = malloc(length+1); - if(*string == NULL) return 0; - strcpy(*string, (char*) Buffer); - - Buffer += length; - } - Buffer++; - } - } - } return 1; - - case -4: { /* FC FF */ - unsigned lang; - unsigned LanguageSetCount = read_uint8le(Buffer); - Buffer++; Size--; - if(LanguageSetCount > 20) return 0; - - for(lang=0; langLanguageSets[lang]; - - if(Size < 2) return 0; - LanguageSet->PairCount = read_uint16le(Buffer); - Buffer += 2; Size -= 2; - if(LanguageSet->PairCount == 0) - continue; - - LanguageSet->Pairs = calloc(LanguageSet->PairCount, sizeof(IFFStringPair)); - if(LanguageSet->Pairs == NULL) + if(!read_c_string(&b, &Pair->Key) || !read_c_string(&b, &Pair->Value)) return 0; - - for(i=0; iPairCount; i++){ - unsigned s; - if(Size == 0) return 0; - Buffer++; Size--; /* Skip over the "Language set index" */ - - for(s=0; s<2; s++){ - unsigned length; - if(Size == 0) return 0; - length = read_uint8le(Buffer); - Buffer++; Size--; - if(length > 127){ - if(Size == 0) return 0; - length = (length&127) | (read_uint8le(Buffer)<<7); - Buffer++; Size--; - } - if(length != 0){ - IFFStringPair * Pair = &LanguageSet->Pairs[i]; - char ** string = (s==0) ? &Pair->Key : &Pair->Value; - if(length > Size) return 0; - *string = malloc(length+1); - if(*string == NULL) return 0; - memcpy(*string, Buffer, length); - (*string)[length] = 0x00; - - Buffer += length; - Size -= length; - } - } - } } - } return 1; - } - return 0; + return 1; } void iff_free_str(void * FormattedData){ diff --git a/Libraries/FileHandler/iff/string.c b/Libraries/FileHandler/iff/string.c index 57abc82..ee1c57f 100644 --- a/Libraries/FileHandler/iff/string.c +++ b/Libraries/FileHandler/iff/string.c @@ -16,20 +16,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_c_string(IFFChunk * ChunkInfo, const uint8_t * Buffer){ - char ** string = (char**) &ChunkInfo->FormattedData; - unsigned Size = ChunkInfo->Size - 76; - unsigned length; - - for(length=0; length != Size && Buffer[length]; length++); - if(length == Size) return 0; - - if(length > 0){ - *string = malloc(length+1); - if(*string == NULL) return 0; - strcpy(*string, (char*) Buffer); - } - return 1; + bytestream b; + set_bytestream(&b, Buffer, ChunkInfo->Size); + return (read_c_string(&b, (char**) &ChunkInfo->FormattedData) != 0); } \ No newline at end of file diff --git a/Libraries/FileHandler/iff/tmpl.c b/Libraries/FileHandler/iff/tmpl.c index ca673af..23ccae8 100644 --- a/Libraries/FileHandler/iff/tmpl.c +++ b/Libraries/FileHandler/iff/tmpl.c @@ -16,26 +16,26 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_tmpl(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFTemplate *Template; - unsigned Size = ChunkInfo->Size - 76; + bytestream b; + const uint8_t * ptr = Buffer; + unsigned Size = ChunkInfo->Size; unsigned FieldCount; unsigned i; - const uint8_t * TempBuffer = Buffer; if(Size == 0) return 1; /* Walk through a first-pass to find the total field count */ for(FieldCount=0; Size; FieldCount++){ - unsigned length = *TempBuffer; - + unsigned length = *ptr; if(Size < 5 || length > Size-5) return 0; - TempBuffer += length+5; Size -= length+5; + ptr += length+5; Size -= length+5; } - ChunkInfo->FormattedData = malloc(sizeof(IFFTemplate)); + ChunkInfo->FormattedData = calloc(1, sizeof(IFFTemplate)); if(ChunkInfo->FormattedData == NULL) return 0; @@ -45,17 +45,15 @@ int iff_parse_tmpl(IFFChunk * ChunkInfo, const uint8_t * Buffer){ if(Template->Fields == NULL) return 0; + set_bytestream(&b, Buffer, ChunkInfo->Size); + for(i=0; iFields[i]; - unsigned length = *Buffer; - Field->Name = malloc(length+1); - if(Field->Name == NULL) return 0; - memcpy(Field->Name, Buffer+1, length); - Field->Name[length] = 0x00; - Buffer += length+1; + if(!read_pascal_string(&b, &Field->Name)) + return 0; - memcpy(Field->Type, Buffer, 4); - Buffer += 4; + memcpy(Field->Type, b.Buffer, 4); + skipbytes(&b, 4); } return 1; diff --git a/Libraries/FileHandler/iff/trcn.c b/Libraries/FileHandler/iff/trcn.c index 4dd8ccd..2454662 100644 --- a/Libraries/FileHandler/iff/trcn.c +++ b/Libraries/FileHandler/iff/trcn.c @@ -17,26 +17,26 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "iff.h" +#include "iffparser.h" int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer){ IFFRangeSet *RangeSet; - unsigned Size = ChunkInfo->Size - 76; + bytestream b; unsigned i; - if(Size < 16) + if(ChunkInfo->Size < 16) return 0; + set_bytestream(&b, Buffer, ChunkInfo->Size); ChunkInfo->FormattedData = calloc(1, sizeof(IFFRangeSet)); if(ChunkInfo->FormattedData == NULL) return 0; RangeSet = ChunkInfo->FormattedData; - RangeSet->Ranges = NULL; - RangeSet->Reserved = read_uint32le(Buffer); - RangeSet->Version = read_uint32le(Buffer+4); - memcpy(RangeSet->MagicNumber, Buffer+8, 4); - RangeSet->MagicNumber[4] = 0x00; - RangeSet->RangeCount = read_uint32le(Buffer+12); + RangeSet->Reserved = read_uint32(&b); + RangeSet->Version = read_uint32(&b); + memcpy(RangeSet->MagicNumber, b.Buffer, 4); + skipbytes(&b, 4); + RangeSet->RangeCount = read_uint32(&b); if(RangeSet->Reserved != 0 || RangeSet->Version > 2) return 0; if(RangeSet->RangeCount == 0) @@ -46,69 +46,40 @@ int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer){ if(RangeSet->Ranges == NULL) return 0; - Buffer += 16; Size -= 16; for(i=0; iRangeCount; i++){ unsigned s; IFFRangeEntry * Range = &RangeSet->Ranges[i]; - if(Size < 10) + if(b.Size < 10) return 0; - Range->IsUsed = read_uint32le(Buffer); - Range->DefaultValue = read_uint32le(Buffer+4); - Buffer += 8; Size -= 8; + Range->IsUsed = read_uint32(&b); + Range->DefaultValue = read_uint32(&b); for(s=0; s<2; s++){ char ** string = (s==0) ? &Range->Name : &Range->Comment; - unsigned length; - if(Size == 0) return 0; + if(b.Size == 0) return 0; if(RangeSet->Version < 2){ - /* C string */ - for(length=0; length != Size && Buffer[length]; length++); - if(length == Size) return 0; - - if(length != 0){ - *string = malloc(length+1); - if(*string == NULL) return 0; - strcpy(*string, (char*) Buffer); - } - - Buffer += length+1; - Size -= length+1; + /* C string, possible padding */ + if(!read_c_string(&b, string)) + return 0; /* Skip past the 0xA3 character; ** see global.iff chunk 546 for why you can't do modulo-2 to detect this */ - if(Size && *Buffer == 0xA3){ - Buffer++; Size--; - } + if(b.Size && *b.Buffer == 0xA3) + skipbytes(&b, 1); }else{ - /* Pascal string */ - length = read_uint8le(Buffer); - Buffer++; Size--; - if(length > 127){ - if(Size == 0) return 0; - length = (length&127) | (read_uint8le(Buffer)<<7); - Buffer++; Size--; - } - - if(length != 0){ - *string = malloc(length+1); - if(*string == NULL) return 0; - memcpy(*string, Buffer, length); - (*string)[length] = 0x00; - } - - Buffer += length; - Size -= length; + /* Extended Pascal string, no padding */ + if(!read_pascal2_string(&b, string)) + return 0; } } if(RangeSet->Version != 0){ - if(Size < 5) return 0; - Range->Enforced = read_uint8le(Buffer); - Range->RangeMin = read_uint16le(Buffer+1); - Range->RangeMax = read_uint16le(Buffer+3); - Buffer += 5; Size -= 5; + if(b.Size < 5) return 0; + Range->Enforced = read_uint8(&b); + Range->RangeMin = read_uint16(&b); + Range->RangeMax = read_uint16(&b); } } diff --git a/Libraries/FileHandler/utk/utkdecode.c b/Libraries/FileHandler/utk/utkdecode.c index 6df3657..302c31c 100644 --- a/Libraries/FileHandler/utk/utkdecode.c +++ b/Libraries/FileHandler/utk/utkdecode.c @@ -16,9 +16,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include +#include #include -#include +#include +#include #include "read_utk.h" #ifndef write_int32 @@ -35,13 +37,11 @@ int main(int argc, char *argv[]){ int overwrite = 0; char *InFile, *OutFile; - HANDLE hFile; - HANDLE ProcessHeap = GetProcessHeap(); - unsigned FileSize; - DWORD bytestransferred = 0; + FILE * hFile; + size_t FileSize; uint8_t * UTKData; utkheader_t UTKHeader; - unsigned BeginningTime, EndingTime; + clock_t BeginningTime, EndingTime; if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ printf("Usage: utkdecode [-f] infile outfile\n" @@ -68,30 +68,29 @@ int main(int argc, char *argv[]){ ** Open the file and read in entire contents to memory */ - hFile = CreateFile(InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - if(GetLastError() == ERROR_FILE_NOT_FOUND){ - printf("%sThe specified input file does not exist.", "utkdecode: error: "); - return -1; - } - printf("%sThe input file could not be opened for reading.", "utkdecode: error: "); + 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; } - FileSize = GetFileSize(hFile, NULL); + fseek(hFile, 0, SEEK_END); + FileSize = ftell(hFile); if(FileSize < 24){ printf("%sNot a valid UTK file.", "utkdecode: error: "); return -1; } - UTKData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, FileSize); + 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(!ReadFile(hFile, UTKData, FileSize, &bytestransferred, NULL) || bytestransferred != FileSize){ + if(!fread(UTKData, FileSize, 1, hFile)){ printf("%sThe input file could not be read.", "utkdecode: error: "); return -1; } - CloseHandle(hFile); + fclose(hFile); /**** ** Transcode the data from UTK to LPCM @@ -103,7 +102,7 @@ int main(int argc, char *argv[]){ } if(argc >= 3){ /* Transcode */ - uint8_t * WaveData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, 44+UTKHeader.dwOutSize); + uint8_t * WaveData = malloc(44+UTKHeader.dwOutSize); if(WaveData == NULL){ printf("%sMemory for this file could not be allocated.", "utkdecode: error: "); return -1; @@ -111,14 +110,14 @@ int main(int argc, char *argv[]){ UTKGenerateTables(); - BeginningTime = GetTickCount(); + BeginningTime = clock(); if(!utk_decode(UTKData+32, WaveData+44, UTKHeader.Frames)){ printf("%sMemory for this file could not be allocated.", "utkdecode: error: "); return -1; } - EndingTime = GetTickCount(); + EndingTime = clock(); - HeapFree(ProcessHeap, HEAP_NO_SERIALIZE, UTKData); + free(UTKData); /**** ** Write the Microsoft WAV header @@ -142,29 +141,29 @@ int main(int argc, char *argv[]){ ** Write the contents to the output file */ - hFile = CreateFile(OutFile, GENERIC_WRITE, 0, NULL, CREATE_NEW+overwrite, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - if(!overwrite && GetLastError() == ERROR_FILE_EXISTS){ + if(!overwrite){ + hFile = fopen(OutFile, "rb"); + if(hFile != NULL){ + /* File exists */ char c; + fclose(hFile); printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile); c = getchar(); if(c != 'y' && c != 'Y'){ printf("\nAborted."); return -1; } - hFile = CreateFile(OutFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - } - if(hFile == INVALID_HANDLE_VALUE){ - printf("%sThe output file could not be opened for writing.", "utkdecode: error: "); - return -1; } } + hFile = fopen(OutFile, "wb"); + if(hFile == NULL){ + printf("%sThe output file could not be opened for writing.", "utkdecode: error: "); + return -1; + } printf("Extracted %u bytes in %.2f seconds.\n", (unsigned) UTKHeader.dwOutSize, - ((float) (EndingTime - BeginningTime))/1000); - WriteFile(hFile, WaveData, 44+UTKHeader.dwOutSize, &bytestransferred, NULL); - CloseHandle(hFile); + ((float)(EndingTime - BeginningTime))/CLOCKS_PER_SEC); + fwrite(WaveData, 1, 44+UTKHeader.dwOutSize, hFile); + fclose(hFile); } return 0; diff --git a/Libraries/FileHandler/xa/xadecode.c b/Libraries/FileHandler/xa/xadecode.c index 418a104..55e5ebf 100644 --- a/Libraries/FileHandler/xa/xadecode.c +++ b/Libraries/FileHandler/xa/xadecode.c @@ -14,9 +14,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include +#include #include -#include +#include +#include #include "read_xa.h" #ifndef write_int32 @@ -33,13 +35,11 @@ int main(int argc, char *argv[]){ int overwrite = 0; char *InFile, *OutFile; - HANDLE hFile; - HANDLE ProcessHeap = GetProcessHeap(); - unsigned FileSize; - DWORD bytestransferred = 0; + FILE * hFile; + size_t FileSize; uint8_t * XAData; xaheader_t XAHeader; - unsigned BeginningTime, EndingTime; + clock_t BeginningTime, EndingTime; if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ printf("Usage: xadecode [-f] infile outfile\n" @@ -66,30 +66,29 @@ int main(int argc, char *argv[]){ ** Open the file and read in entire contents to memory */ - hFile = CreateFile(InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - if(GetLastError() == ERROR_FILE_NOT_FOUND){ - printf("%sThe specified input file does not exist.", "xadecode: error: "); - return -1; - } - printf("%sThe input file could not be opened for reading.", "xadecode: error: "); + 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; } - FileSize = GetFileSize(hFile, NULL); + fseek(hFile, 0, SEEK_END); + FileSize = ftell(hFile); if(FileSize < 24){ printf("%sNot a valid XA file.", "xadecode: error: "); return -1; } - XAData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, FileSize); + 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(!ReadFile(hFile, XAData, FileSize, &bytestransferred, NULL) || bytestransferred != FileSize){ + if(!fread(XAData, FileSize, 1, hFile)){ printf("%sThe input file could not be read.", "xadecode: error: "); return -1; } - CloseHandle(hFile); + fclose(hFile); /**** ** Transcode the data from XA to LPCM @@ -101,20 +100,20 @@ int main(int argc, char *argv[]){ } if(argc >= 3){ /* Transcode */ - uint8_t * WaveData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, 44+XAHeader.dwOutSize); + uint8_t * WaveData = malloc(44+XAHeader.dwOutSize); if(WaveData == NULL){ printf("%sMemory for this file could not be allocated.", "xadecode: error: "); return -1; } - BeginningTime = GetTickCount(); + 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; } - EndingTime = GetTickCount(); + EndingTime = clock(); - HeapFree(ProcessHeap, HEAP_NO_SERIALIZE, XAData); + free(XAData); /**** ** Write the Microsoft WAV header @@ -138,29 +137,29 @@ int main(int argc, char *argv[]){ ** Write the contents to the output file */ - hFile = CreateFile(OutFile, GENERIC_WRITE, 0, NULL, CREATE_NEW+overwrite, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if(hFile == INVALID_HANDLE_VALUE){ - if(!overwrite && GetLastError() == ERROR_FILE_EXISTS){ + if(!overwrite){ + hFile = fopen(OutFile, "rb"); + if(hFile != NULL){ + /* File exists */ char c; + fclose(hFile); printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile); c = getchar(); if(c != 'y' && c != 'Y'){ printf("\nAborted."); return -1; } - hFile = CreateFile(OutFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - } - if(hFile == INVALID_HANDLE_VALUE){ - printf("%sThe output file could not be opened for writing.", "xadecode: error: "); - return -1; } } + hFile = fopen(OutFile, "wb"); + if(hFile == NULL){ + printf("%sThe output file could not be opened for writing.", "xadecode: error: "); + return -1; + } printf("Extracted %u bytes in %.2f seconds.\n", (unsigned) XAHeader.dwOutSize, - ((float) (EndingTime - BeginningTime))/1000); - WriteFile(hFile, WaveData, 44+XAHeader.dwOutSize, &bytestransferred, NULL); - CloseHandle(hFile); + ((float)(EndingTime - BeginningTime))/CLOCKS_PER_SEC); + fwrite(WaveData, 1, 44+XAHeader.dwOutSize, hFile); + fclose(hFile); } return 0; diff --git a/Tools/Server GUI/CMakeLists.txt b/Tools/Server GUI/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/Tools/iff2html/iff2html.c b/Tools/iff2html/iff2html.c index a9f2eef..2af7a90 100644 --- a/Tools/iff2html/iff2html.c +++ b/Tools/iff2html/iff2html.c @@ -17,6 +17,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include