mirror of
https://github.com/simtactics/niotso.git
synced 2025-03-15 08:11:22 +00:00
* 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.
This commit is contained in:
parent
cb40cbd867
commit
bc978bfa0b
20 changed files with 515 additions and 657 deletions
|
@ -16,25 +16,12 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#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;
|
||||
}
|
|
@ -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));
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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; i<List->ConstantCount; 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef IFF_H
|
||||
#define IFF_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
@ -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
|
|
@ -16,9 +16,11 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
#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;
|
||||
}
|
146
Libraries/FileHandler/iff/iffparser.h
Normal file
146
Libraries/FileHandler/iff/iffparser.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
iffparser.h - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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; i<Map->TypeCount; 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; j<Type->ResourceCount; 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,72 +17,27 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
|
|
|
@ -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; i<LanguageSet->PairCount; 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; ls<LanguageSetCount; ls++){
|
||||
IFFLanguageSet * LanguageSet = &StringData->LanguageSets[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; i<LanguageSet->PairCount; 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; i<LanguageSet->PairCount; 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; p<LanguageSet->PairCount; 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<TotalPairCount; i++){
|
||||
unsigned lang, s;
|
||||
if(Size == 0) return 0;
|
||||
lang = read_uint8le(Buffer) - 1;
|
||||
if(b.Size == 0) return 0;
|
||||
lang = read_uint8(&b) - 1;
|
||||
if(lang >= 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; i<TotalPairCount; i++){
|
||||
unsigned lang = read_uint8le(Buffer) - 1, s;
|
||||
IFFStringPair * Pair = &LanguageSet[lang].Pairs[Index[lang]++];
|
||||
Buffer++;
|
||||
IFFStringPair * Pair;
|
||||
unsigned lang;
|
||||
lang = read_uint8(&b) - 1;
|
||||
Pair = &LanguageSet[lang].Pairs[Index[lang]++];
|
||||
|
||||
for(s=0; s<2; s++){
|
||||
unsigned length = strlen((char*) Buffer);
|
||||
if(length != 0){
|
||||
char ** string = (s==0) ? &Pair->Key : &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; lang<LanguageSetCount; lang++){
|
||||
unsigned i;
|
||||
IFFLanguageSet * LanguageSet = &StringData->LanguageSets[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; i<LanguageSet->PairCount; 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){
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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; i<FieldCount; i++){
|
||||
IFFTemplateField * Field = &Template->Fields[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;
|
||||
|
|
|
@ -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; i<RangeSet->RangeCount; 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#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;
|
||||
|
|
|
@ -14,9 +14,11 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#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;
|
||||
|
|
0
Tools/Server GUI/CMakeLists.txt
Normal file
0
Tools/Server GUI/CMakeLists.txt
Normal file
|
@ -17,6 +17,7 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <iff/iff.h>
|
||||
|
|
Loading…
Add table
Reference in a new issue