diff --git a/CMakeLists.txt b/CMakeLists.txt index a78cb54..3c8e35c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,8 +18,8 @@ endif() if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) # Base options - set(CFLAGS "-Wall -Wextra -Wabi -pedantic -m32 -mmmx -msse -msse2 -msse3 -mfpmath=both -msahf") - set(LDFLAGS "-m32") + set(CFLAGS "-Wall -Wextra -Wabi -pedantic -m32 -mmmx -msse -msse2 -msse3 -mfpmath=both -msahf -fvisibility=internal") + set(LDFLAGS "-m32 -fvisibility=hidden -fvisibility-inlines-hidden") set(RCFLAGS "-F pe-i386") set(ASMFLAGS "-O3 -F win32") @@ -64,7 +64,7 @@ endif() enable_language(ASM) set(CMAKE_ASM_COMPILER "gcc") -set(CMAKE_ASM_FLAGS "-fno-strict-aliasing ${CFLAGS}") +set(CMAKE_ASM_FLAGS "${CFLAGS}") if(WIN32) set(DIST_NAME "windows" CACHE STRING "Output folder name for the _dist folder (no start or end slash)") diff --git a/Client/Audio/Startup.cpp b/Client/Audio/Startup.cpp index 97cd323..161f2c6 100644 --- a/Client/Audio/Startup.cpp +++ b/Client/Audio/Startup.cpp @@ -56,7 +56,7 @@ PlayableSound_t * LoadSound(const Sound_t * Sound){ Sound->SamplingRate, //nSamplesPerSec ((Sound->Channels * Sound->BitDepth) >> 3) * Sound->SamplingRate, //nAvgBytesPerSec ((Sound->Channels * Sound->BitDepth) >> 3), //nBlockAlign - Sound->BitDepth, //wBitsPerSample; + Sound->BitDepth, //wBitsPerSample 0 //cbSize }; diff --git a/Client/System/System.cpp b/Client/System/System.cpp index 22e0ba0..a19515f 100644 --- a/Client/System/System.cpp +++ b/Client/System/System.cpp @@ -24,13 +24,11 @@ HANDLE Process; HANDLE ProcessHeap; LARGE_INTEGER ClockFreq; volatile float FramePeriod; -UserInput_t UserInput; +UserInput_t UserInput = {0}; volatile UserInput_t UserInput_v; bool SceneFailed = false; int Initialize(){ - memset(&UserInput, 0, sizeof(UserInput)); - QueryPerformanceFrequency(&ClockFreq); DEVMODE dm; diff --git a/Client/Window/SetCursor.cpp b/Client/Window/SetCursor.cpp new file mode 100644 index 0000000..e69de29 diff --git a/Client/Window/Window.cpp b/Client/Window/Window.cpp index 6aff40a..8758d65 100644 --- a/Client/Window/Window.cpp +++ b/Client/Window/Window.cpp @@ -179,7 +179,7 @@ static int CreateWindowInvisible(HINSTANCE hInst, unsigned Width, unsigned Heigh //Use a style of WS_OVERLAPPEDWINDOW to allow resizing AdjustWindowRectEx(&WindowRect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE, - WS_EX_APPWINDOW); //This finds the dimensions of a window with a client area of our specified dimensions + WS_EX_APPWINDOW); //This finds the dimensions of a window with a client area of our specified dimensions //Note: Windows can be positioned anywhere, even outside the visible workspace, //but their sizes are limited to the size of the workspace on the primary display. diff --git a/Libraries/FileHandler/Audio.cpp b/Libraries/FileHandler/Audio.cpp index b036e54..9f8fb00 100644 --- a/Libraries/FileHandler/Audio.cpp +++ b/Libraries/FileHandler/Audio.cpp @@ -14,14 +14,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include +#include "FileHandler.hpp" #include "libmpg123/mpg123.h" #include "utk/read_utk.h" #include "wav/read_wav.h" #include "xa/read_xa.h" -#include "FileHandler.hpp" namespace File { diff --git a/Libraries/FileHandler/CMakeLists.txt b/Libraries/FileHandler/CMakeLists.txt index bf0bf2f..39a0c4b 100644 --- a/Libraries/FileHandler/CMakeLists.txt +++ b/Libraries/FileHandler/CMakeLists.txt @@ -21,8 +21,6 @@ set(FILEHANDLER_SOURCES Image.cpp bmp/read_bmp.c cst/cst.c - iff/chunks.c - iff/iff.c utk/read_utk.c wav/read_wav.c xa/read_xa.c @@ -30,11 +28,12 @@ set(FILEHANDLER_SOURCES include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler) -add_library(FileHandler_static STATIC ${FILEHANDLER_SOURCES}) -set_target_properties(FileHandler_static PROPERTIES - OUTPUT_NAME "FileHandler${FILEHANDLER_SERIES}" - PREFIX "" - CLEAN_DIRECT_OUTPUT 1) +#### Static library (uncomment to build) +#add_library(FileHandler_static STATIC ${FILEHANDLER_SOURCES}) +#set_target_properties(FileHandler_static PROPERTIES +# OUTPUT_NAME "FileHandler${FILEHANDLER_SERIES}" +# PREFIX "" +# CLEAN_DIRECT_OUTPUT 1) add_library(FileHandler_shared SHARED ${FILEHANDLER_SOURCES}) set_target_properties(FileHandler_shared PROPERTIES @@ -44,4 +43,4 @@ set_target_properties(FileHandler_shared PROPERTIES PREFIX "" IMPORT_PREFIX "" CLEAN_DIRECT_OUTPUT 1) -target_link_libraries(FileHandler_shared kernel32 jpegturbo_static libmpg123_static libpng_static zlib_static) \ No newline at end of file +target_link_libraries(FileHandler_shared kernel32 iff_static jpegturbo_static libmpg123_static libpng_static zlib_static) \ No newline at end of file diff --git a/Libraries/FileHandler/FileHandler.hpp b/Libraries/FileHandler/FileHandler.hpp index c8dc118..eca79e9 100644 --- a/Libraries/FileHandler/FileHandler.hpp +++ b/Libraries/FileHandler/FileHandler.hpp @@ -21,10 +21,14 @@ #include #include #include +#include +#include #ifndef NOWINDOWS #include #endif +#define fhexport __declspec(dllexport) + struct Asset_t { uint32_t Group; uint32_t File; @@ -62,12 +66,12 @@ struct Sound_t { namespace File { -extern int Error; -extern size_t FileSize; +fhexport extern int Error; +fhexport extern size_t FileSize; -uint8_t * ReadFile(const char * Filename); -Image_t * ReadImageFile(const char * Filename); -Sound_t * ReadSoundFile(const char * Filename); +fhexport uint8_t * ReadFile(const char * Filename); +fhexport Image_t * ReadImageFile(const char * Filename); +fhexport Sound_t * ReadSoundFile(const char * Filename); } diff --git a/Libraries/FileHandler/Image.cpp b/Libraries/FileHandler/Image.cpp index 92b55db..89429a2 100644 --- a/Libraries/FileHandler/Image.cpp +++ b/Libraries/FileHandler/Image.cpp @@ -14,15 +14,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include +#define NOWINDOWS +#include "FileHandler.hpp" #include //Used by libpng #include "bmp/read_bmp.h" #include "libjpeg-turbo/jpeglib.h" #include "libpng/png.h" -#define NOWINDOWS -#include "FileHandler.hpp" namespace File { @@ -38,18 +35,29 @@ static uint8_t * ReadJPG(Image_t * Image, const uint8_t * InData, size_t FileSiz static uint8_t * ReadBMP(Image_t * Image, const uint8_t * InData, size_t FileSize); static uint8_t * ReadPNG(Image_t * Image, const uint8_t * InData, size_t FileSize); static uint8_t * ReadTGA(Image_t * Image, const uint8_t * InData, size_t FileSize); +static uint8_t * ReadCUR(Image_t * Image, const uint8_t * InData, size_t FileSize); + +static uint8_t * ReadTGACUR(Image_t * Image, const uint8_t * InData, size_t FileSize){ + //Microsoft and Truevision, y u no more creative with your file signatures? + //In many cases we're going to see these bytes, exactly, at the beginning in both formats: + //00 00 02 00 01 00 + //So screw it. Try parsing the file first as a TGA, then as a CUR. + + uint8_t * Result = ReadTGA(Image, InData, FileSize); + return Result ? Result : ReadCUR(Image, InData, FileSize); +} static const uint8_t Signature[] = { 'B', //BMP 0xFF, //JPEG 0x89, //PNG - 0x00 //TGA + 0x00 //TGA or CUR }; static uint8_t* (* const ImageFunction[])(Image_t*, const uint8_t*, size_t) = { ReadBMP, ReadJPG, ReadPNG, - ReadTGA + ReadTGACUR }; Image_t * ReadImageFile(const char * Filename){ @@ -217,4 +225,8 @@ static uint8_t * ReadTGA(Image_t * Image, const uint8_t * InData, size_t FileSiz return NULL; } +static uint8_t * ReadCUR(Image_t * Image, const uint8_t * InData, size_t FileSize){ + return NULL; +} + } \ No newline at end of file diff --git a/Libraries/FileHandler/cur/read_cur.c b/Libraries/FileHandler/cur/read_cur.c new file mode 100644 index 0000000..2f759d9 --- /dev/null +++ b/Libraries/FileHandler/cur/read_cur.c @@ -0,0 +1,16 @@ +/* + Niotso - Copyright (C) 2012 Fatbag + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ \ No newline at end of file diff --git a/Libraries/FileHandler/cur/read_cur.h b/Libraries/FileHandler/cur/read_cur.h new file mode 100644 index 0000000..2f759d9 --- /dev/null +++ b/Libraries/FileHandler/cur/read_cur.h @@ -0,0 +1,16 @@ +/* + Niotso - Copyright (C) 2012 Fatbag + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ \ No newline at end of file diff --git a/Libraries/FileHandler/iff/CMakeLists.txt b/Libraries/FileHandler/iff/CMakeLists.txt index 47c4fca..515dbee 100644 --- a/Libraries/FileHandler/iff/CMakeLists.txt +++ b/Libraries/FileHandler/iff/CMakeLists.txt @@ -2,8 +2,25 @@ cmake_minimum_required(VERSION 2.6) project(iff) set(IFF_SOURCES - chunks.c iff.c + bcon.c + rsmp.c + str.c + trcn.c ) -add_executable(iffexport iffexport.c ${IFF_SOURCES}) \ No newline at end of file +add_library(iff_static STATIC ${IFF_SOURCES}) +set_target_properties(iff_static PROPERTIES + OUTPUT_NAME "iff" + PREFIX "" + CLEAN_DIRECT_OUTPUT 1) + +#### Shared library (uncomment to build) +#add_library(iff_shared SHARED ${IFF_SOURCES}) +#set_target_properties(libiff_shared PROPERTIES +# OUTPUT_NAME "iff" +# PREFIX "" +# CLEAN_DIRECT_OUTPUT 1) + +add_executable(iffexport iffexport.c) +target_link_libraries(iffexport iff_static) \ No newline at end of file diff --git a/Libraries/FileHandler/iff/bcon.c b/Libraries/FileHandler/iff/bcon.c new file mode 100644 index 0000000..fce2bdc --- /dev/null +++ b/Libraries/FileHandler/iff/bcon.c @@ -0,0 +1,54 @@ +/* + bcon.c - Copyright (c) 2012 Fatbag + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + 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" + +int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){ + IFF_BCON *BCONData; + unsigned Size = ChunkInfo->Size - 76; + unsigned i; + + if(Size < 2) + return 0; + ChunkInfo->FormattedData = malloc(sizeof(IFF_BCON)); + if(ChunkInfo->FormattedData == NULL) + return 0; + + BCONData = (IFF_BCON*) ChunkInfo->FormattedData; + BCONData->Constants = NULL; + BCONData->ConstantCount = read_uint8le(Buffer); + BCONData->Flags = read_uint8le(Buffer + 1); + if(BCONData->ConstantCount == 0) + return 1; + if(BCONData->ConstantCount * 2 /* bytes */ > Size - 2){ + return 0; + } + + BCONData->Constants = malloc(BCONData->ConstantCount * sizeof(uint16_t)); + if(BCONData->Constants == NULL){ + return 0; + } + + Buffer += 2; + for(i=0; iConstantCount; i++, Buffer += 2) + BCONData->Constants[i] = read_uint16le(Buffer); + return 1; +} + +void iff_free_bcon(void * FormattedData){ + IFF_BCON *BCONData = (IFF_BCON*) FormattedData; + free(BCONData->Constants); +} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/chunks.c b/Libraries/FileHandler/iff/chunks.c deleted file mode 100644 index 0d2f6e8..0000000 --- a/Libraries/FileHandler/iff/chunks.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - chunks.c - Copyright (c) 2012 Fatbag - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - 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 -#include -#include -#include "iff.h" - -/* All chunk-parsing functions */ -static int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize); -static int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer); -static int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer); -static int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer); - -int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){ - unsigned i; - const char chunktypes[] = - "STR#" "CTSS" "FAMs" "TTAs" - "BCON" - "TRCN" - ; - int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = { - iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str, - iff_parse_bcon, - iff_parse_trcn - }; - - for(i=0; chunktypes[i*4] != '\0'; i++){ - if(!memcmp(ChunkInfo->Type, chunktypes+i*4, 4)) - return iff_parse_function[i](ChunkInfo, Buffer); - } - return 0; -} - -static int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize){ - return 1; -} - -static int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){ - IFF_BCON *BCONData; - unsigned Size = ChunkInfo->Size - 76; - unsigned i; - - if(Size < 2) - return 0; - ChunkInfo->FormattedData = malloc(sizeof(IFF_BCON)); - if(ChunkInfo->FormattedData == NULL) - return 0; - - BCONData = (IFF_BCON*) ChunkInfo->FormattedData; - BCONData->ConstantCount = read_uint8le(Buffer); - BCONData->Flags = read_uint8le(Buffer + 1); - if(BCONData->ConstantCount == 0) - return 1; - if(BCONData->ConstantCount * 2 > Size - 2){ - free(BCONData); - return 0; - } - - BCONData->Constants = malloc(BCONData->ConstantCount * sizeof(uint16_t)); - if(BCONData->Constants == NULL){ - free(BCONData); - return 0; - } - - Buffer += 2; - for(i=0; iConstantCount; i++, Buffer += 2) - BCONData->Constants[i] = read_uint16le(Buffer); - return 1; -} - -static int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ - /* No bounds checking yet */ - IFF_STR * StringData; - unsigned Size = ChunkInfo->Size - 76; - - if(Size < 2) - return 0; - ChunkInfo->FormattedData = malloc(sizeof(IFF_STR)); - if(ChunkInfo->FormattedData == NULL) - return 0; - - StringData = (IFF_STR*) ChunkInfo->FormattedData; - memset(StringData, 0, sizeof(IFF_STR)); - StringData->Format = read_int16le(Buffer); - Buffer += 2; - if(Size-2 < 2) /* TSO allows this; as seen in the animations chunk in personglobals.iff */ - return 1; - - switch(StringData->Format){ - - case 0: { - unsigned i; - IFFStringPairNode * PrevPair = NULL; - - StringData->LanguageSets[0].PairCount = read_uint16le(Buffer); - Buffer += 2; - if(StringData->LanguageSets[0].PairCount == 0) - return 1; - - for(i=0; iLanguageSets[0].PairCount; i++){ - IFFStringPairNode * CurrentPair; - unsigned length; - CurrentPair = malloc(sizeof(IFFStringPairNode)); - memset(CurrentPair, 0, sizeof(IFFStringPairNode)); - - if(i == 0) StringData->LanguageSets[0].FirstPair = CurrentPair; - else PrevPair->NextPair = CurrentPair; - CurrentPair->PrevPair = PrevPair; - - /* Key */ - length = read_uint8le(Buffer); - if(length != 0){ - CurrentPair->Pair.Key = malloc(length+1); - memcpy(CurrentPair->Pair.Key, Buffer+1, length); - CurrentPair->Pair.Key[length] = 0x00; - } - Buffer += length+1; - - PrevPair = CurrentPair; - } - StringData->LanguageSets[0].LastPair = PrevPair; - } return 1; - - case -1: { - unsigned i; - IFFStringPairNode * PrevPair = NULL; - - StringData->LanguageSets[0].PairCount = read_uint16le(Buffer); - Buffer += 2; - if(StringData->LanguageSets[0].PairCount == 0) - return 1; - - for(i=0; iLanguageSets[0].PairCount; i++){ - IFFStringPairNode * CurrentPair; - unsigned length; - CurrentPair = malloc(sizeof(IFFStringPairNode)); - memset(CurrentPair, 0, sizeof(IFFStringPairNode)); - - if(i == 0) StringData->LanguageSets[0].FirstPair = CurrentPair; - else PrevPair->NextPair = CurrentPair; - CurrentPair->PrevPair = PrevPair; - - /* Key */ - length = strlen((char*)Buffer); - if(length != 0){ - CurrentPair->Pair.Key = malloc(length+1); - strcpy(CurrentPair->Pair.Key, (char*)Buffer); - } - Buffer += length+1; - - PrevPair = CurrentPair; - } - StringData->LanguageSets[0].LastPair = PrevPair; - } return 1; - - case -2: { - unsigned i; - IFFStringPairNode * PrevPair = NULL; - - StringData->LanguageSets[0].PairCount = read_uint16le(Buffer); - Buffer += 2; - if(StringData->LanguageSets[0].PairCount == 0) - return 1; - - for(i=0; iLanguageSets[0].PairCount; i++){ - IFFStringPairNode * CurrentPair; - unsigned length; - CurrentPair = malloc(sizeof(IFFStringPairNode)); - memset(CurrentPair, 0, sizeof(IFFStringPairNode)); - - if(i == 0) StringData->LanguageSets[0].FirstPair = CurrentPair; - else PrevPair->NextPair = CurrentPair; - CurrentPair->PrevPair = PrevPair; - - /* Key */ - length = strlen((char*)Buffer); - if(length != 0){ - CurrentPair->Pair.Key = malloc(length+1); - strcpy(CurrentPair->Pair.Key, (char*)Buffer); - } - Buffer += length+1; - - /* Value */ - length = strlen((char*)Buffer); - if(length != 0){ - CurrentPair->Pair.Value = malloc(length+1); - strcpy(CurrentPair->Pair.Value, (char*)Buffer); - } - Buffer += length+1; - - PrevPair = CurrentPair; - } - StringData->LanguageSets[0].LastPair = PrevPair; - } return 1; - - case -3: { - unsigned i, TotalPairCount; - - TotalPairCount = read_uint16le(Buffer); - Buffer += 2; - if(TotalPairCount == 0) - return 1; - - for(i=0; iPair.LanguageSet = read_uint8le(Buffer) - 1; - Buffer++; - - /* Key */ - length = strlen((char*)Buffer); - if(length != 0){ - Pair->Pair.Key = malloc(length+1); - strcpy(Pair->Pair.Key, (char*)Buffer); - } - Buffer += length+1; - - /* Value */ - length = strlen((char*)Buffer); - if(length != 0){ - Pair->Pair.Value = malloc(length+1); - strcpy(Pair->Pair.Value, (char*)Buffer); - } - Buffer += length+1; - - /* Add the pair to the end of the associated language set */ - Pair->PrevPair = StringData->LanguageSets[0].LastPair; - if(StringData->LanguageSets[0].PairCount == 0) - StringData->LanguageSets[0].FirstPair = Pair; - else - StringData->LanguageSets[0].LastPair->NextPair = Pair; - StringData->LanguageSets[0].PairCount++; - StringData->LanguageSets[0].LastPair = Pair; - } - } return 1; - - case -4: { - unsigned LanguageSet; - unsigned LanguageSetCount = read_uint8le(Buffer); - Buffer++; - if(LanguageSetCount > 20) LanguageSetCount = 20; - - for(LanguageSet=0; LanguageSetLanguageSets[LanguageSet].PairCount = read_uint16le(Buffer); - Buffer += 2; - if(StringData->LanguageSets[LanguageSet].PairCount == 0) - continue; - - for(i=0; iLanguageSets[LanguageSet].PairCount; i++){ - IFFStringPairNode * CurrentPair; - unsigned length; - CurrentPair = malloc(sizeof(IFFStringPairNode)); - memset(CurrentPair, 0, sizeof(IFFStringPairNode)); - - if(i == 0) StringData->LanguageSets[LanguageSet].FirstPair = CurrentPair; - else PrevPair->NextPair = CurrentPair; - CurrentPair->PrevPair = PrevPair; - - Buffer++; /* Skip over LanguageSet */ - - /* Key */ - length = read_uint8le(Buffer); - if(length > 127){ - length = (length & 127) | (read_uint8le(Buffer+1) << 7); - Buffer++; - } - if(length != 0){ - CurrentPair->Pair.Key = malloc(length+1); - memcpy(CurrentPair->Pair.Key, Buffer+1, length); - CurrentPair->Pair.Key[length] = 0x00; - } - Buffer += length + 1; - - /* Value */ - length = read_uint8le(Buffer); - if(length > 127){ - length = (length & 127) | (read_uint8le(Buffer+1) << 7); - Buffer++; - } - if(length != 0){ - CurrentPair->Pair.Value = malloc(length+1); - memcpy(CurrentPair->Pair.Value, Buffer+1, length); - CurrentPair->Pair.Value[length] = 0x00; - } - Buffer += length + 1; - - PrevPair = CurrentPair; - } - StringData->LanguageSets[LanguageSet].LastPair = PrevPair; - } - } return 1; - - } - - free(ChunkInfo->FormattedData); - return 0; -} - -static int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer){ - IFF_TRCN * TRCNData; - unsigned Size = ChunkInfo->Size - 76; - unsigned i; - - if(Size < 16) - return 0; - ChunkInfo->FormattedData = malloc(sizeof(IFF_TRCN)); - if(ChunkInfo->FormattedData == NULL) - return 0; - - TRCNData = (IFF_TRCN*) ChunkInfo->FormattedData; - TRCNData->Reserved = read_uint32le(Buffer+0); - TRCNData->Version = read_uint32le(Buffer+4); - memcpy(TRCNData->MagicNumber, Buffer+8, 4); - TRCNData->MagicNumber[4] = 0x00; - TRCNData->EntryCount = read_uint32le(Buffer+12); - - if(TRCNData->Reserved != 0 || TRCNData->Version > 2 || strcmp(TRCNData->MagicNumber, "NCRT")){ - free(TRCNData); - return 0; - } - ChunkInfo->FormattedData = malloc(TRCNData->EntryCount * sizeof(IFFRangePair)); - if(ChunkInfo->FormattedData == NULL){ - free(TRCNData); - return 0; - } - - Buffer += 16; - for(i=0; iEntryCount; i++){/* - IsUnused = read_uint32le(Buffer+0); - Unknown = read_uint32le(Buffer+4);*/ - } -} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iff.c b/Libraries/FileHandler/iff/iff.c index 9b4d38c..07d9afb 100644 --- a/Libraries/FileHandler/iff/iff.c +++ b/Libraries/FileHandler/iff/iff.c @@ -14,25 +14,57 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include -#include #include "iff.h" -#ifndef __inline -#define __inline -#endif -#ifndef __restrict -#define __restrict -#endif +/**** +** Supported Chunks +*/ + +#define iff_register(x) \ + int iff_parse_##x(IFFChunk *, const uint8_t *); \ + void iff_free_##x(void *) + +int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize); +int iff_free_rsmp(void * FormattedData); + +/* The order of these chunks must remain the same throughout this block: */ +iff_register(bcon); +iff_register(str); +iff_register(trcn); + +const char chunktypes[] = + "STR#" "CTSS" "FAMs" "TTAs" + "BCON" + "TRCN" +; +int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = { + iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str, + iff_parse_bcon, + iff_parse_trcn +}; +void (* const iff_free_function[])(void*) = { + iff_free_str, iff_free_str, iff_free_str, iff_free_str, + iff_free_bcon, + iff_free_trcn +}; +/* End */ + + +/**** +** API public functions +*/ IFFFile * iff_create() { - IFFFile *ptr = malloc(sizeof(IFFFile)); + IFFFile *ptr = calloc(1, sizeof(IFFFile)); if(ptr == NULL) return NULL; - - memset(ptr, 0, sizeof(IFFFile)); - + + ptr->Chunks = malloc(sizeof(IFFChunk)); + if(ptr->Chunks == NULL){ + free(ptr); + return NULL; + } + ptr->SizeAllocated = sizeof(IFFChunk); return ptr; } @@ -55,55 +87,20 @@ int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned File return 1; } -IFFChunkNode * iff_add_chunk(IFFFile * IFFFileInfo, int Position) +IFFChunk * iff_add_chunk(IFFFile * IFFFileInfo) { - IFFChunkNode *ptr = malloc(sizeof(IFFChunkNode)), *node; - if(ptr == NULL) return NULL; - memset(ptr, 0, sizeof(IFFChunkNode)); - if(IFFFileInfo == NULL) return ptr; - - if(Position >= 0){ - node = IFFFileInfo->FirstChunk; - - if(node == NULL){ - IFFFileInfo->FirstChunk = ptr; - IFFFileInfo->LastChunk = ptr; - }else{ - /* Find the node we will take the place of */ - while(Position-- && node->NextChunk != NULL) - node = node->NextChunk; - - if(node->PrevChunk == NULL) - IFFFileInfo->FirstChunk = ptr; - - /* Shift this node and all nodes after it above us */ - ptr->PrevChunk = node->PrevChunk; - ptr->NextChunk = node; - node->PrevChunk = ptr; - } - }else{ - node = IFFFileInfo->LastChunk; - - if(node == NULL){ - IFFFileInfo->FirstChunk = ptr; - IFFFileInfo->LastChunk = ptr; - }else{ - /* Find the node we will take the place of */ - while(++Position && node->PrevChunk != NULL) - node = node->PrevChunk; - - if(node->NextChunk == NULL) - IFFFileInfo->LastChunk = ptr; - - /* Shift this node and all nodes before it below us */ - ptr->PrevChunk = node; - ptr->NextChunk = node->NextChunk; - node->NextChunk = ptr; - } + if((IFFFileInfo->ChunkCount+1)*sizeof(IFFChunk) > IFFFileInfo->SizeAllocated){ + IFFChunk * ptr; + if(IFFFileInfo->SizeAllocated > SIZE_MAX/2) return NULL; + ptr = realloc(IFFFileInfo->Chunks, IFFFileInfo->SizeAllocated<<1); + if(ptr == NULL) return NULL; + + IFFFileInfo->Chunks = ptr; + IFFFileInfo->SizeAllocated<<=1; } IFFFileInfo->ChunkCount++; - return ptr; + return IFFFileInfo->Chunks + IFFFileInfo->ChunkCount-1; } int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize) @@ -114,6 +111,7 @@ int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChu return 0; memcpy(ChunkInfo->Type, Buffer+0, 4); + ChunkInfo->Type[4] = 0x00; ChunkInfo->Size = read_uint32be(Buffer+4); ChunkInfo->ChunkID = read_uint16be(Buffer+8); ChunkInfo->Flags = read_uint16be(Buffer+10); @@ -135,16 +133,62 @@ int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChu int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned BufferSize) { while(BufferSize){ - IFFChunkNode * chunk = iff_add_chunk(IFFFileInfo, -1); + IFFChunk * chunk = iff_add_chunk(IFFFileInfo); if(chunk == NULL) return 0; - if(!iff_read_chunk(&chunk->Chunk, Buffer, BufferSize)){ - free(chunk); + if(!iff_read_chunk(chunk, Buffer, BufferSize)) return 0; - } - Buffer += chunk->Chunk.Size; - BufferSize -= chunk->Chunk.Size; + Buffer += chunk->Size; + BufferSize -= chunk->Size; } return 1; +} + +int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer){ + unsigned i; + for(i=0; chunktypes[i*4] != '\0'; i++){ + if(!memcmp(ChunkInfo->Type, chunktypes+i*4, 4)){ + if(iff_parse_function[i](ChunkInfo, Buffer)) return 1; + iff_free_chunk(ChunkInfo->FormattedData); + return 0; + } + } + return 0; +} + +void iff_free_chunk(IFFChunk * ChunkInfo){ + unsigned i; + if(ChunkInfo == NULL || ChunkInfo->FormattedData) return; + + for(i=0; chunktypes[i*4] != '\0'; i++){ + if(!memcmp(ChunkInfo->Type, chunktypes+i*4, 4)){ + if(iff_free_function[i]) + iff_free_function[i](ChunkInfo->FormattedData); + free(ChunkInfo->FormattedData); + return; + } + } +} + +void iff_delete(IFFFile * IFFFileInfo){ + unsigned i; + if(IFFFileInfo == NULL) return; + + if(IFFFileInfo->Chunks != NULL){ + for(i=0; iChunkCount; i++){ + iff_free_chunk(IFFFileInfo->Chunks+i); + free(IFFFileInfo->Chunks[i].Data); + } + free(IFFFileInfo->Chunks); + } + + if(IFFFileInfo->ResourceMap != NULL){ + free(IFFFileInfo->ResourceMap->Data); + free(IFFFileInfo->ResourceMap->FormattedData); + free(IFFFileInfo->ResourceMap); + } + + free(IFFFileInfo); + IFFFileInfo = NULL; } \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iff.h b/Libraries/FileHandler/iff/iff.h index 4b99294..7ed7bb5 100644 --- a/Libraries/FileHandler/iff/iff.h +++ b/Libraries/FileHandler/iff/iff.h @@ -14,6 +14,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include +#include + #ifndef read_uint32be #define read_int32be(x) (signed)(((x)[0]<<(8*3)) | ((x)[1]<<(8*2)) | ((x)[2]<<(8*1)) | ((x)[3]<<(8*0))) #define read_int24be(x) (signed)(((x)[0]<<(8*2)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*0))) @@ -37,7 +41,7 @@ ** IFF file headers */ -typedef struct IFFChunk_struct +typedef struct IFFChunk_s { char Type[5]; uint32_t Size; @@ -48,21 +52,14 @@ typedef struct IFFChunk_struct void * FormattedData; } IFFChunk; -typedef struct IFFChunkNode_struct -{ - IFFChunk Chunk; - struct IFFChunkNode_struct * PrevChunk; - struct IFFChunkNode_struct * NextChunk; -} IFFChunkNode; - -typedef struct IFFFile_struct +typedef struct IFFFile_s { uint8_t Header[64]; uint32_t ChunkCount; - IFFChunkNode * FirstChunk; - IFFChunkNode * LastChunk; - IFFChunkNode * ResourceMap; + size_t SizeAllocated; + IFFChunk * Chunks; + IFFChunk * ResourceMap; } IFFFile; static const uint8_t Header_IFF[] = "IFF FILE 2.5:TYPE FOLLOWED BY SIZE\0 JAMIE DOORNBOS & MAXIS 1"; @@ -73,7 +70,7 @@ static const uint8_t Header_IFF[] = "IFF FILE 2.5:TYPE FOLLOWED BY SIZE\0 JAMIE /* BCON chunk */ -typedef struct IFF_BCON_struct +typedef struct IFF_BCON_s { uint8_t ConstantCount; uint8_t Flags; @@ -106,28 +103,20 @@ enum IFFLanguage { IFFLANG_KOREAN = 20 }; -typedef struct IFFStringPair_struct +typedef struct IFFStringPair_s { uint8_t LanguageSet; char * Key; char * Value; } IFFStringPair; -typedef struct IFFStringPairNode_struct -{ - IFFStringPair Pair; - struct IFFStringPairNode_struct * PrevPair; - struct IFFStringPairNode_struct * NextPair; -} IFFStringPairNode; - -typedef struct IFFLanguageSet_struct +typedef struct IFFLanguageSet_s { uint16_t PairCount; - IFFStringPairNode * FirstPair; - IFFStringPairNode * LastPair; + IFFStringPair * Pairs; } IFFLanguageSet; -typedef struct IFF_STR_struct +typedef struct IFF_STR_s { int16_t Format; IFFLanguageSet LanguageSets[20]; @@ -135,7 +124,7 @@ typedef struct IFF_STR_struct /* TRCN chunk */ -typedef struct IFFRangePair_struct +typedef struct IFFRangePair_s { uint32_t IsUnused; uint32_t Unknown; @@ -146,7 +135,7 @@ typedef struct IFFRangePair_struct uint16_t RangeMax; } IFFRangePair; -typedef struct IFF_TRCN_struct +typedef struct IFF_TRCN_s { uint32_t Reserved; uint32_t Version; @@ -166,20 +155,15 @@ extern "C" { IFFFile * iff_create(); int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize); -IFFChunkNode * iff_add_chunk(IFFFile * IFFFileInfo, int Position); +IFFChunk * iff_add_chunk(IFFFile * IFFFileInfo); int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize); +int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer); int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned BufferSize); +void iff_free_chunk(IFFChunk * ChunkInfo); void iff_delete_chunk(IFFFile * IFFFileInfo, int Position); void iff_delete(IFFFile * IFFFileInfo); - -/* -** IFF chunk functions -*/ - -int iff_parse_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer); - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/Libraries/FileHandler/iff/iffexport.c b/Libraries/FileHandler/iff/iffexport.c index 96a4a8f..0ba77d4 100644 --- a/Libraries/FileHandler/iff/iffexport.c +++ b/Libraries/FileHandler/iff/iffexport.c @@ -19,6 +19,14 @@ #include #include "iff.h" +int charmatches(char c, const char * filter){ + while(*filter){ + if(c == *filter) return 1; + filter++; + } + return 0; +} + int main(int argc, char *argv[]){ HANDLE hFile; int overwrite = 0; @@ -27,9 +35,9 @@ int main(int argc, char *argv[]){ DWORD FileSize; DWORD bytestransferred = 0; uint8_t * IFFData; - unsigned chunkcount, chunk = 0; + unsigned chunkcount, chunk; IFFFile * IFFFileInfo; - IFFChunkNode * ChunkNode; + IFFChunk * ChunkData; if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ printf("Usage: iffexport [-f] infile outdirectory\n" @@ -109,19 +117,23 @@ int main(int argc, char *argv[]){ /**** ** Extract each entry */ - for(ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk){ + for(chunk = 1, ChunkData = IFFFileInfo->Chunks; chunk <= chunkcount; chunk++, ChunkData++){ char name[256], destination[256]; char filter[] = "\\/:*?\"<>|"; int i; - chunk++; - sprintf(name, "%03u-%s-%04X-%s", chunk, ChunkNode->Chunk.Type, ChunkNode->Chunk.ChunkID, ChunkNode->Chunk.Label); + sprintf(name, "%03u-%s-%04X-%s", chunk, ChunkData->Type, ChunkData->ChunkID, ChunkData->Label); + for(i=0; name[i] != 0x00; i++){ + if(name[i] == '\t') name[i] = ' '; + else if(name[i] < ' ' || name[i] > '~') name[i] = '.'; + else if(charmatches(name[i], "\\/:*?\"<>|")) name[i] = '.'; + } for(i=0; i<9; i++){ char * c = name; while((c = strchr(c, filter[i])) != NULL) *c = '.'; } - sprintf(destination, "%s/%s.%s", OutDirectory, name, (!memcmp(ChunkNode->Chunk.Type, "BMP_", 4)) ? "bmp" : "dat"); + sprintf(destination, "%s/%s.%s", OutDirectory, name, (!memcmp(ChunkData->Type, "BMP_", 4)) ? "bmp" : "dat"); hFile = CreateFile(destination, GENERIC_WRITE, 0, NULL, CREATE_NEW+overwrite, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); @@ -132,9 +144,9 @@ int main(int argc, char *argv[]){ continue; } - printf(" (%u/%u) %s (%u bytes)\n", chunk, chunkcount, name, ChunkNode->Chunk.Size-76); + printf(" (%u/%u) %s (%u bytes)\n", chunk, chunkcount, name, ChunkData->Size-76); - WriteFile(hFile, ChunkNode->Chunk.Data, ChunkNode->Chunk.Size-76, &bytestransferred, NULL); + WriteFile(hFile, ChunkData->Data, ChunkData->Size-76, &bytestransferred, NULL); CloseHandle(hFile); } diff --git a/Libraries/FileHandler/iff/rsmp.c b/Libraries/FileHandler/iff/rsmp.c new file mode 100644 index 0000000..23fd8f0 --- /dev/null +++ b/Libraries/FileHandler/iff/rsmp.c @@ -0,0 +1,24 @@ +/* + rsmp.c - Copyright (c) 2012 Fatbag + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + 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" + +int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned IFFSize){ + return 0; +} + +void iff_free_rsmp(void * FormattedData){ +} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/str.c b/Libraries/FileHandler/iff/str.c new file mode 100644 index 0000000..94740ff --- /dev/null +++ b/Libraries/FileHandler/iff/str.c @@ -0,0 +1,278 @@ +/* + str.c - Copyright (c) 2012 Fatbag + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + 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" + +int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){ + IFF_STR * StringData; + unsigned Size = ChunkInfo->Size - 76; + + if(Size < 2) + return 0; + ChunkInfo->FormattedData = calloc(1, sizeof(IFF_STR)); + if(ChunkInfo->FormattedData == NULL) + return 0; + + StringData = (IFF_STR*) ChunkInfo->FormattedData; + StringData->Format = read_int16le(Buffer); + if((Size-=2) < 2) /* TSO allows this; as seen in the animations chunk in personglobals.iff */ + return 1; + Buffer += 2; + + switch(StringData->Format){ + + case 0: { /* 00 00 */ + 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++){ + 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; + } + } + } return 1; + + case -1: { /* FF 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++){ + unsigned length; + + if(Size == 0) return 0; + for(length=0; Size-length && Buffer[length]; length++); + if(Buffer[length] != 0x00) 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; + if(Size == 0) return 0; + for(length=0; Size-length && Buffer[length]; length++); + if(Buffer[length] != 0x00) 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; + } + Buffer++; Size--; + } + } + } return 1; + + case -3: { /* FD FF */ + IFFLanguageSet * LanguageSet = StringData->LanguageSets; + unsigned i; + unsigned TotalPairCount = read_uint16le(Buffer); + unsigned Index[20] = {0}; + const uint8_t * Start = (Buffer += 2); + Size -= 2; + + if(TotalPairCount == 0) + return 1; + + /* + ** Scan through the chunk to count up the number of strings 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; + if(Size == 0) return 0; + for(length=0; Size-length && Buffer[length]; length++); + if(Buffer[length] != 0x00) return 0; + Buffer += length+1; + Size -= length+1; + } + } + + for(i=0; i<20; i++){ + LanguageSet[i].Pairs = calloc(LanguageSet[i].PairCount, sizeof(IFFStringPair)); + if(LanguageSet[i].Pairs == NULL) return 0; + } + + /* 2nd pass */ + Buffer = Start; + 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) + 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; +} + +void iff_free_str(void * FormattedData){ + /* + ** Requirements: + ** - PairCount and Pairs must be initialized for all 20 LanguageSets + ** - If the Pairs pointer is nonzero, there must be PairCount initialized pairs in Pairs + */ + + IFF_STR * StringData = (IFF_STR*) FormattedData; + unsigned ls; + + for(ls=0; ls<20; ls++){ + IFFLanguageSet * LanguageSet = &StringData->LanguageSets[ls]; + unsigned p; + if(LanguageSet->Pairs){ + for(p=0; pPairCount; p++){ + free(LanguageSet->Pairs[p].Key); + free(LanguageSet->Pairs[p].Value); + } + free(LanguageSet->Pairs); + } + } +} \ No newline at end of file diff --git a/Libraries/FileHandler/iff/trcn.c b/Libraries/FileHandler/iff/trcn.c new file mode 100644 index 0000000..16f545a --- /dev/null +++ b/Libraries/FileHandler/iff/trcn.c @@ -0,0 +1,55 @@ +/* + trcn.c - Copyright (c) 2012 Fatbag + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + 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" + +int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer){ + return 0; /* + IFF_TRCN * TRCNData; + unsigned Size = ChunkInfo->Size - 76; + unsigned i; + + if(Size < 16) + return 0; + ChunkInfo->FormattedData = malloc(sizeof(IFF_TRCN)); + if(ChunkInfo->FormattedData == NULL) + return 0; + + TRCNData = (IFF_TRCN*) ChunkInfo->FormattedData; + TRCNData->Reserved = read_uint32le(Buffer+0); + TRCNData->Version = read_uint32le(Buffer+4); + memcpy(TRCNData->MagicNumber, Buffer+8, 4); + TRCNData->MagicNumber[4] = 0x00; + TRCNData->EntryCount = read_uint32le(Buffer+12); + + if(TRCNData->Reserved != 0 || TRCNData->Version > 2 || strcmp(TRCNData->MagicNumber, "NCRT")){ + free(TRCNData); + return 0; + } + ChunkInfo->FormattedData = malloc(TRCNData->EntryCount * sizeof(IFFRangePair)); + if(ChunkInfo->FormattedData == NULL){ + free(TRCNData); + return 0; + } + + Buffer += 16; + for(i=0; iEntryCount; i++){ + } */ +} + +void iff_free_trcn(void * FormattedData){ + /*IFF_TRCN *TRCNData = (IFF_TRCN*) FormattedData;*/ +} \ No newline at end of file diff --git a/Libraries/FileHandler/tga/read_tga.h b/Libraries/FileHandler/tga/read_tga.h new file mode 100644 index 0000000..e79bb09 Binary files /dev/null and b/Libraries/FileHandler/tga/read_tga.h differ diff --git a/Libraries/libvitaboy/CMakeLists.txt b/Libraries/libvitaboy/CMakeLists.txt index 5b8c209..c6c69d4 100644 --- a/Libraries/libvitaboy/CMakeLists.txt +++ b/Libraries/libvitaboy/CMakeLists.txt @@ -23,10 +23,11 @@ endif() include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler) -add_library(libvitaboy_static STATIC ${LIBVITABOY_SOURCES}) -set_target_properties(libvitaboy_static PROPERTIES - OUTPUT_NAME "vitaboy" - CLEAN_DIRECT_OUTPUT 1) +#### Static library (uncomment to build) +#add_library(libvitaboy_static STATIC ${LIBVITABOY_SOURCES}) +#set_target_properties(libvitaboy_static PROPERTIES +# OUTPUT_NAME "vitaboy" +# CLEAN_DIRECT_OUTPUT 1) add_library(libvitaboy_shared SHARED ${LIBVITABOY_SOURCES}) set_target_properties(libvitaboy_shared PROPERTIES @@ -39,7 +40,7 @@ set_target_properties(libvitaboy_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1) add_executable(vbparse vbparse.cpp) -target_link_libraries(vbparse libvitaboy_static FileHandler_shared) +target_link_libraries(vbparse libvitaboy_shared FileHandler_shared) add_executable(Renderer Renderer.cpp) target_link_libraries(Renderer libvitaboy_shared FileHandler_shared opengl32 glu32 winmm) \ No newline at end of file diff --git a/Tools/FARDive/CMakeLists.txt b/Tools/FARDive/CMakeLists.txt index 394948b..f263321 100644 --- a/Tools/FARDive/CMakeLists.txt +++ b/Tools/FARDive/CMakeLists.txt @@ -17,4 +17,4 @@ if(WIN32) endif() include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler/libpng) -target_link_libraries(FARDive ${FARDIVE_LINK} libpng_shared) \ No newline at end of file +target_link_libraries(FARDive ${FARDIVE_LINK} FileHandler_shared) \ No newline at end of file diff --git a/Tools/iff2html/CMakeLists.txt b/Tools/iff2html/CMakeLists.txt index e0cfc4b..b912b59 100644 --- a/Tools/iff2html/CMakeLists.txt +++ b/Tools/iff2html/CMakeLists.txt @@ -9,4 +9,4 @@ set(IFF2HTML_SOURCES include_directories(${CMAKE_SOURCE_DIR}/Libraries/FileHandler) add_executable(iff2html ${IFF2HTML_SOURCES}) -target_link_libraries(iff2html FileHandler_shared) \ No newline at end of file +target_link_libraries(iff2html iff_static) \ No newline at end of file diff --git a/Tools/iff2html/iff2html.c b/Tools/iff2html/iff2html.c index 84f01c3..d625f3d 100644 --- a/Tools/iff2html/iff2html.c +++ b/Tools/iff2html/iff2html.c @@ -16,7 +16,6 @@ #include #include -#include #include #include "md5.h" @@ -57,7 +56,7 @@ int main(int argc, char *argv[]){ uint8_t * IFFData; unsigned chunk = 0; IFFFile * IFFFileInfo; - IFFChunkNode * ChunkNode; + IFFChunk * ChunkData; if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ printf("Usage: iff2html [-f] infile (outfile)\n" @@ -95,7 +94,6 @@ 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); hFile = fopen(InFile, "rb"); if(hFile == NULL){ printf("%sThe specified input file does not exist or could not be opened for reading.", "iff2html: error: "); @@ -149,9 +147,8 @@ int main(int argc, char *argv[]){ MD5Final(digest, &md5c); free(IFFData); - for(chunk = 1, ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk, chunk++) - iff_parse_chunk(&ChunkNode->Chunk, ChunkNode->Chunk.Data); - + for(chunk = 0, ChunkData = IFFFileInfo->Chunks; chunk < IFFFileInfo->ChunkCount; chunk++, ChunkData++) + iff_parse_chunk(ChunkData, ChunkData->Data); /**** ** Open the output file and write the header @@ -263,28 +260,28 @@ int main(int argc, char *argv[]){ fprintf(hFile, "\n"); fprintf(hFile, "
Contents – %u chunks
\n", IFFFileInfo->ChunkCount); fprintf(hFile, "
    \n"); - for(i=1, ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk, i++) + for(i=1, ChunkData = IFFFileInfo->Chunks; i <= IFFFileInfo->ChunkCount; i++, ChunkData++) fprintf(hFile, "
  • %u [%s] (%.4X)%s%s
  • \n", - i, ChunkNode->Chunk.ChunkID, i, ChunkNode->Chunk.Type, ChunkNode->Chunk.ChunkID, - (ChunkNode->Chunk.Label[0] != 0x00) ? " – " : "", ChunkNode->Chunk.Label); + i, ChunkData->ChunkID, i, ChunkData->Type, ChunkData->ChunkID, + (ChunkData->Label[0] != 0x00) ? " – " : "", ChunkData->Label); fprintf(hFile, "
\n"); fprintf(hFile, "
\n"); fprintf(hFile, "\n"); - for(i=1, ChunkNode = IFFFileInfo->FirstChunk; ChunkNode; ChunkNode = ChunkNode->NextChunk, i++){ - IFF_STR * StringData = (IFF_STR*) ChunkNode->Chunk.FormattedData; + for(i=1, ChunkData = IFFFileInfo->Chunks; i <= IFFFileInfo->ChunkCount; i++, ChunkData++){ + IFF_STR * StringData = (IFF_STR*) ChunkData->FormattedData; fprintf(hFile, "

%u [%s] (%.4X)%s%s (Jump)

\n", - i, ChunkNode->Chunk.ChunkID, i, ChunkNode->Chunk.Type, ChunkNode->Chunk.ChunkID, - (ChunkNode->Chunk.Label[0] != 0x00) ? " – " : "", ChunkNode->Chunk.Label, - i, ChunkNode->Chunk.ChunkID); + i, ChunkData->ChunkID, i, ChunkData->Type, ChunkData->ChunkID, + (ChunkData->Label[0] != 0x00) ? " – " : "", ChunkData->Label, + i, ChunkData->ChunkID); fprintf(hFile, "
\n"); - if(ChunkNode->Chunk.FormattedData == NULL){ + if(ChunkData->FormattedData == NULL){ fprintf(hFile, "The contents of this chunk could not be parsed.\n"); - }else if(!strcmp(ChunkNode->Chunk.Type, "STR#") || - !strcmp(ChunkNode->Chunk.Type, "CTSS") || - !strcmp(ChunkNode->Chunk.Type, "FAMs") || - !strcmp(ChunkNode->Chunk.Type, "TTAs") ){ + }else if(!strcmp(ChunkData->Type, "STR#") || + !strcmp(ChunkData->Type, "CTSS") || + !strcmp(ChunkData->Type, "FAMs") || + !strcmp(ChunkData->Type, "TTAs") ){ /**** ** STR# parsing */ @@ -330,31 +327,31 @@ int main(int argc, char *argv[]){ fprintf(hFile, "LanguageString pairs\n"); for(LanguageSet=0; LanguageSet<20; LanguageSet++){ - IFFStringPairNode * PairNode; + IFFStringPair * Pair; unsigned PairIndex; if(StringData->LanguageSets[LanguageSet].PairCount == 0) continue; fprintf(hFile, "%s\n", StringData->LanguageSets[LanguageSet].PairCount, LanguageStrings[LanguageSet]); - for(PairIndex=1, PairNode = StringData->LanguageSets[LanguageSet].FirstPair; PairNode; - PairNode = PairNode->NextPair, PairIndex++){ + for(PairIndex=1, Pair = StringData->LanguageSets[LanguageSet].Pairs; + PairIndex <= StringData->LanguageSets[LanguageSet].PairCount; PairIndex++, Pair++){ if(PairIndex != 1) fprintf(hFile, ""); fprintf(hFile, "%u%s%s\n", PairIndex, - (PairNode->Pair.Key) != NULL ? PairNode->Pair.Key : "", - (PairNode->Pair.Value) != NULL ? PairNode->Pair.Value : ""); + (Pair->Key) != NULL ? Pair->Key : "", + (Pair->Value) != NULL ? Pair->Value : ""); } } fprintf(hFile, "\n"); } - }else if(!strcmp(ChunkNode->Chunk.Type, "BCON")){ + }else if(!strcmp(ChunkData->Type, "BCON")){ /**** ** BCON parsing */ - IFF_BCON * BCONData = (IFF_BCON*) ChunkNode->Chunk.FormattedData; + IFF_BCON * BCONData = (IFF_BCON*) ChunkData->FormattedData; fprintf(hFile, "\n"); fprintf(hFile, "\n", BCONData->Flags, BCONData->Flags); fprintf(hFile, "
Flags:%02X (%d)
\n"); @@ -372,6 +369,7 @@ int main(int argc, char *argv[]){ fprintf(hFile, "
\n\n"); } + iff_delete(IFFFileInfo); fprintf(hFile, "
This page was generated by the use of iff2html.\n"); @@ -379,5 +377,7 @@ int main(int argc, char *argv[]){ fprintf(hFile, "\n"); fprintf(hFile, ""); fclose(hFile); + + printf("Wrote contents to '%s'.\n", OutFile); return 0; } \ No newline at end of file