- Added libraries from formats and libvitaboy
This commit is contained in:
Tony Bark 2024-04-28 05:33:13 -04:00
parent 66ce473514
commit 5efdb29315
101 changed files with 11711 additions and 10889 deletions

2
library/formats/AUTHORS Normal file
View file

@ -0,0 +1,2 @@
Fatbag <X-Fi6@phppoll.org>
Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>

202
library/formats/Audio.cpp Normal file
View file

@ -0,0 +1,202 @@
/*
FileHandler - General-purpose file handling library for Niotso
Audio.cpp - Copyright (c) 2011-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 "FileHandler.hpp"
#include <mpg123.h>
#include "wav/read_wav.h"
#include "xa/read_xa.h"
#include "utk/read_utk.h"
namespace File {
enum SoundType {
FSND_WAV,
FSND_XA,
FSND_UTK,
FSND_MP3,
FSND_COUNT
};
static uint8_t * ReadWAV(Sound_t * Sound, const uint8_t * InData, size_t FileSize);
static uint8_t * ReadXA(Sound_t * Sound, const uint8_t * InData, size_t FileSize);
static uint8_t * ReadUTK(Sound_t * Sound, const uint8_t * InData, size_t FileSize);
static uint8_t * ReadMP3(Sound_t * Sound, const uint8_t * InData, size_t FileSize);
static const uint8_t Signature[] = {
'R', //WAV
'X', //XA
'U', //UTK
0xFF //MP3
};
static uint8_t* (* const SoundFunction[])(Sound_t*, const uint8_t*, size_t) = {
ReadWAV,
ReadXA,
ReadUTK,
ReadMP3
};
Sound_t * ReadSoundFile(const char * Filename){
uint8_t * InData = File::ReadFile(Filename);
if(InData == NULL) return NULL;
if(File::FileSize < 4){
free(InData);
File::Error = FERR_INVALIDDATA;
return NULL;
}
Sound_t * Sound = (Sound_t*) malloc(sizeof(Sound_t));
if(Sound == NULL){
free(InData);
File::Error = FERR_MEMORY;
return NULL;
}
for(int i=0; i<FSND_COUNT; i++){
if(InData[0] == Signature[i]){
uint8_t * OutData = SoundFunction[i](Sound, InData, File::FileSize);
free(InData);
if(OutData == NULL){
File::Error = FERR_INVALIDDATA;
return NULL;
}
return Sound;
}
}
free(InData);
File::Error = FERR_UNRECOGNIZED;
return NULL;
}
static uint8_t * ReadWAV(Sound_t * Sound, const uint8_t * InData, size_t FileSize){
wavheader_t WAVHeader;
if(!wav_read_header(&WAVHeader, InData, FileSize)){
return NULL;
}
uint8_t * OutData = (uint8_t*) malloc(WAVHeader.DataSize);
if(OutData == NULL){
return NULL;
}
memcpy(OutData, InData+44, WAVHeader.DataSize);
Sound->Channels = WAVHeader.nChannels;
Sound->SamplingRate = WAVHeader.nSamplesPerSec;
Sound->BitDepth = WAVHeader.wBitsPerSample;
Sound->Duration = WAVHeader.DataSize / WAVHeader.nBlockAlign;
Sound->Data = OutData;
return OutData;
}
static uint8_t * ReadXA(Sound_t * Sound, const uint8_t * InData, size_t FileSize){
xaheader_t XAHeader;
if(!xa_read_header(&XAHeader, InData, FileSize)){
return NULL;
}
uint8_t * OutData = (uint8_t*) malloc(XAHeader.dwOutSize);
if(OutData == NULL){
return NULL;
}
if(!xa_decode(InData+24, OutData, XAHeader.Frames, XAHeader.nChannels)){
free(OutData);
return NULL;
}
Sound->Channels = XAHeader.nChannels;
Sound->SamplingRate = XAHeader.nSamplesPerSec;
Sound->BitDepth = XAHeader.wBitsPerSample;
Sound->Duration = XAHeader.dwOutSize / XAHeader.nBlockAlign;
Sound->Data = OutData;
return OutData;
}
static uint8_t * ReadUTK(Sound_t * Sound, const uint8_t * InData, size_t FileSize){
utkheader_t UTKHeader;
if(!utk_read_header(&UTKHeader, InData, FileSize)){
return NULL;
}
uint8_t * OutData = (uint8_t*) malloc(UTKHeader.dwOutSize);
if(OutData == NULL){
return NULL;
}
if(!utk_decode(InData+32, OutData, FileSize-32, UTKHeader.Frames)){
free(OutData);
return NULL;
}
Sound->Channels = 1;
Sound->SamplingRate = UTKHeader.nSamplesPerSec;
Sound->BitDepth = UTKHeader.wBitsPerSample;
Sound->Duration = UTKHeader.dwOutSize / UTKHeader.nBlockAlign;
Sound->Data = OutData;
return OutData;
}
static uint8_t * ReadMP3(Sound_t * Sound, const uint8_t * InData, size_t FileSize){
mpg123_handle *mh;
if(mpg123_init() != MPG123_OK || (mh = mpg123_new(NULL, NULL)) == NULL){
mpg123_exit();
return NULL;
}
long rate;
int channels, encoding;
unsigned samples;
size_t OutSize;
uint8_t * OutData;
if(mpg123_format_none(mh) != MPG123_OK ||
mpg123_format(mh, 44100, MPG123_MONO | MPG123_STEREO, MPG123_ENC_SIGNED_16) != MPG123_OK ||
mpg123_open_feed(mh) != MPG123_OK ||
mpg123_feed(mh, InData, FileSize) != MPG123_OK ||
mpg123_set_filesize(mh, FileSize) != MPG123_OK ||
mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ||
(samples = mpg123_length(mh)) == 0 ||
(OutData = (uint8_t*) malloc(OutSize = samples * channels * 2)) == NULL
){
mpg123_close(mh);
mpg123_delete(mh);
mpg123_exit();
return NULL;
}
size_t decoded;
mpg123_read(mh, OutData, OutSize, &decoded);
mpg123_close(mh);
mpg123_delete(mh);
mpg123_exit();
if(decoded != OutSize){
free(OutData);
return NULL;
}
Sound->Channels = channels;
Sound->SamplingRate = rate;
Sound->BitDepth = 16;
Sound->Duration = samples;
Sound->Data = OutData;
return OutData;
}
}

View file

@ -0,0 +1,52 @@
cmake_minimum_required(VERSION 2.6)
project(FileHandler)
set(FILEHANDLER_SERIES 0)
set(FILEHANDLER_MAJOR 0)
set(FILEHANDLER_MINOR 0)
if(64BIT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic")
endif()
add_subdirectory(far)
add_subdirectory(iff)
add_subdirectory(utk)
add_subdirectory(xa)
set(FILEHANDLER_SOURCES
Audio.cpp
File.cpp
Image.cpp
bmp/read_bmp.c
cst/cst.c
utk/read_utk.c
wav/read_wav.c
xa/read_xa.c
)
if(WIN32)
set(FILEHANDLER_SOURCES ${FILEHANDLER_SOURCES} resource.rc)
endif()
include_directories(${FILEHANDLER_INCLUDE} ${LIBMPG123_INCLUDE} ${LIBJPEGTURBO_INCLUDE} ${LIBPNG_INCLUDE})
#### 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})
if(WIN32)
set_target_properties(FileHandler_shared PROPERTIES OUTPUT_NAME "FileHandler${FILEHANDLER_SERIES}")
else()
set_target_properties(FileHandler_shared PROPERTIES OUTPUT_NAME "FileHandler")
endif()
set_target_properties(FileHandler_shared PROPERTIES
VERSION ${FILEHANDLER_SERIES}.${FILEHANDLER_MAJOR}.${FILEHANDLER_MINOR}
PREFIX ""
IMPORT_PREFIX ""
CLEAN_DIRECT_OUTPUT 1)
target_link_libraries(FileHandler_shared far_static iff_static ${LIBJPEG_LINK} ${LIBMPG123_LINK} ${LIBPNG_LINK} ${ZLIB_LINK} m)

15
library/formats/COPYING Normal file
View file

@ -0,0 +1,15 @@
FileHandler - General-purpose file handling library for Niotso
Version 0.0.0
Copyright (c) 2012 Niotso Project <http://niotso.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.

58
library/formats/File.cpp Normal file
View file

@ -0,0 +1,58 @@
/*
FileHandler - General-purpose file handling library for Niotso
File.cpp - Copyright (c) 2011-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 "FileHandler.hpp"
namespace File {
int Error = 0;
size_t FileSize = 0;
uint8_t * ReadFile(const char * Filename){
FILE * hFile = fopen(Filename, "rb");
if(hFile == NULL){
File::Error = FERR_OPEN;
return NULL;
}
FileSize = File::GetFileSize(hFile);
if(FileSize == 0){
fclose(hFile);
File::Error = FERR_BLANK;
return NULL;
}
uint8_t * InData = (uint8_t*) malloc(FileSize);
if(InData == NULL){
fclose(hFile);
File::Error = FERR_MEMORY;
return NULL;
}
size_t bytestransferred = fread(InData, 1, FileSize, hFile);
fclose(hFile);
if(bytestransferred != FileSize){
free(InData);
File::Error = FERR_READ;
return NULL;
}
return InData;
}
}

View file

@ -0,0 +1,87 @@
/*
FileHandler - General-purpose file handling library for Niotso
FileHandler.hpp - Copyright (c) 2011-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.
*/
#ifndef FILEHANDLER_HPP
#define FILEHANDLER_HPP
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#ifdef WIN32
#define fhexport __declspec(dllexport)
#else
#define fhexport __attribute__((visibility ("default")))
#endif
struct Asset_t {
uint32_t Group;
uint32_t File;
uint32_t Type;
};
enum FErr {
FERR_NOT_FOUND,
FERR_OPEN,
FERR_BLANK,
FERR_MEMORY,
FERR_READ,
FERR_UNRECOGNIZED,
FERR_INVALIDDATA
};
enum ImageFormat_t {
FIMG_BGR24,
FIMG_BGRA32
};
struct Image_t {
unsigned Width, Height;
ImageFormat_t Format;
uint8_t * Data;
};
struct Sound_t {
unsigned Channels;
unsigned SamplingRate;
unsigned BitDepth;
unsigned Duration;
uint8_t * Data;
};
namespace File {
inline size_t GetFileSize(FILE * hFile){
fseek(hFile, 0, SEEK_END);
size_t FileSize = ftell(hFile);
fseek(hFile, 0, SEEK_SET);
return FileSize;
}
fhexport extern int Error;
fhexport extern size_t FileSize;
fhexport uint8_t * ReadFile(const char * Filename);
fhexport Image_t * ReadImageFile(const char * Filename);
fhexport Sound_t * ReadSoundFile(const char * Filename);
}
#endif

265
library/formats/Image.cpp Normal file
View file

@ -0,0 +1,265 @@
/*
FileHandler - General-purpose file handling library for Niotso
Image.cpp - Copyright (c) 2011-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 "FileHandler.hpp"
#include <jpeglib.h>
#include <jerror.h>
#include <png.h>
#include <setjmp.h> //Used for libpng
#include "bmp/read_bmp.h"
namespace File {
enum ImageType {
FIMG_BMP,
FIMG_JPEG,
FIMG_PNG,
FIMG_TGACUR,
FIMG_COUNT
};
static uint8_t * ReadJPG(Image_t * Image, const uint8_t * InData, size_t FileSize);
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 or CUR
};
static uint8_t* (* const ImageFunction[])(Image_t*, const uint8_t*, size_t) = {
ReadBMP,
ReadJPG,
ReadPNG,
ReadTGACUR
};
Image_t * ReadImageFile(const char * Filename){
uint8_t * InData = File::ReadFile(Filename);
if(InData == NULL) return NULL;
if(File::FileSize < 4){
free(InData);
File::Error = FERR_INVALIDDATA;
return NULL;
}
Image_t * Image = (Image_t*) malloc(sizeof(Image_t));
if(Image == NULL){
free(InData);
File::Error = FERR_MEMORY;
return NULL;
}
for(int i=0; i<FIMG_COUNT; i++){
if(InData[0] == Signature[i]){
uint8_t * OutData = ImageFunction[i](Image, InData, File::FileSize);
free(InData);
if(OutData == NULL){
File::Error = FERR_INVALIDDATA;
return NULL;
}
return Image;
}
}
free(InData);
File::Error = FERR_UNRECOGNIZED;
return NULL;
}
static uint8_t * ReadBMP(Image_t * Image, const uint8_t * InData, size_t FileSize){
bmpheader_t BMPHeader;
if(!bmp_read_header(&BMPHeader, InData, FileSize)){
return NULL;
}
uint8_t * OutData = (uint8_t*) malloc(BMPHeader.DecompressedSize);
if(OutData == NULL){
return NULL;
}
if(!bmp_read_data(&BMPHeader, InData, OutData)){
free(OutData);
return NULL;
}
Image->Width = BMPHeader.biWidth;
Image->Height = BMPHeader.biHeight;
Image->Format = FIMG_BGR24;
Image->Data = OutData;
return OutData;
}
// libjpeg-turbo v6 doesn't support jpeg_mem_src, so we have to implement it here
static void term_source(j_decompress_ptr){}
static int fill_mem_input_buffer(j_decompress_ptr cinfo){
ERREXIT(cinfo, JERR_FILE_READ);
return FALSE;
}
static void skip_input_data(j_decompress_ptr cinfo, long bytes)
{
jpeg_source_mgr * src = cinfo->src;
if(bytes > (long) src->bytes_in_buffer){
ERREXIT(cinfo, JERR_FILE_READ);
return;
}
src->next_input_byte += bytes;
src->bytes_in_buffer -= bytes;
}
static uint8_t * ReadJPG(Image_t * Image, const uint8_t * InData, size_t FileSize){
//Initialize
jpeg_decompress_struct cinfo;
jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
if (cinfo.src == NULL)
cinfo.src = (jpeg_source_mgr *)
(*cinfo.mem->alloc_small)((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof(jpeg_source_mgr));
jpeg_source_mgr *src = cinfo.src;
src->init_source = term_source;
src->fill_input_buffer = fill_mem_input_buffer;
src->skip_input_data = skip_input_data;
src->resync_to_restart = jpeg_resync_to_restart;
src->term_source = term_source;
src->bytes_in_buffer = FileSize;
src->next_input_byte = InData;
if(jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK){
jpeg_destroy_decompress(&cinfo);
return NULL;
}
cinfo.out_color_space = JCS_EXT_BGR;
if(!jpeg_start_decompress(&cinfo)){
jpeg_destroy_decompress(&cinfo);
return NULL;
}
//Read
unsigned row_stride = cinfo.output_width * cinfo.output_components;
uint8_t * OutData = (uint8_t*) malloc(cinfo.output_width * cinfo.output_height * cinfo.output_components);
if(OutData == NULL){
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return NULL;
}
for(unsigned i=cinfo.output_height; i; i--){
//According to the libjpeg documentation,
//jpeg_read_scanlines can only really read 1 scanline at a time.
//We need to convert to bottom-up format anyway.
uint8_t * Location = OutData + (i-1)*row_stride;
if(!jpeg_read_scanlines(&cinfo, &Location, 1)){
free(OutData);
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return NULL;
}
}
//Close up
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
if(Image){
Image->Width = cinfo.output_width;
Image->Height = cinfo.output_height;
Image->Format = FIMG_BGR24;
Image->Data = OutData;
}
return OutData;
}
struct pngdata_t {
const uint8_t * buffer;
size_t size;
};
static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length){
pngdata_t *pngdata = (pngdata_t *) png_get_io_ptr(png_ptr);
if(length > pngdata->size) png_error(png_ptr, "");
memcpy(data, pngdata->buffer, length);
pngdata->buffer += length;
pngdata->size -= length;
}
static uint8_t * ReadPNG(Image_t * Image, const uint8_t * InData, size_t FileSize){
pngdata_t pngdata;
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(png_ptr == NULL) return 0;
png_infop info_ptr = png_create_info_struct(png_ptr);
if(info_ptr == NULL){
png_destroy_read_struct(&png_ptr, NULL, NULL);
return NULL;
}
if(setjmp(png_jmpbuf(png_ptr))){
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return NULL;
}
pngdata.buffer = InData;
pngdata.size = FileSize;
png_set_read_fn(png_ptr, &pngdata, user_read_data);
png_set_user_limits(png_ptr, 4096, 4096);
png_read_png(png_ptr, info_ptr,
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA |
PNG_TRANSFORM_PACKING | PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_BGR, NULL);
//png_get_IHDR does not work in high-level mode.
unsigned width = png_get_image_width(png_ptr, info_ptr);
unsigned height = png_get_image_height(png_ptr, info_ptr);
uint8_t * OutData = (uint8_t *) malloc(width*height*3);
if(OutData == NULL){
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return NULL;
}
uint8_t **Scanlines = png_get_rows(png_ptr, info_ptr);
for(unsigned i=0; i<height; i++)
memcpy(OutData + i*width*3, Scanlines[height-i-1], width*3);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
Image->Width = width;
Image->Height = height;
Image->Format = FIMG_BGR24;
Image->Data = OutData;
return OutData;
}
static uint8_t * ReadTGA(Image_t * Image, const uint8_t * InData, size_t FileSize){
return NULL;
}
static uint8_t * ReadCUR(Image_t * Image, const uint8_t * InData, size_t FileSize){
return NULL;
}
}

32
library/formats/README Normal file
View file

@ -0,0 +1,32 @@
***************************************************************************
* ** FileHandler - General-purpose file handling library for Niotso ** *
* ** Copyright (c) 2011-2012 Niotso Project <http://niotso.org/ ** *
* *
* Use and distribution of all files in the "include" and "lib" folders *
* are governed under the ISC License, included with this source code in *
* "COPYING". *
* *
* All other files included but not aforementioned are not copyrighted, *
* and are distributed into the public domain. *
***************************************************************************
FileHandler is a generic C++ library written specifically for Niotso and used to read, and sometimes modify and write,
the various types of files used in The Sims Online.
FileHandler outsources most of its work to de-facto third-party libraries written in C89 (zlib, libpng, libjpeg-turbo,
libmpg123, ...), while other libraries, also written in C89, are provided inside FileHandler, without a flashy name (bmp, cst,
iff, far, ...).
FileHandler wraps around these libraries and provides a convenient C++ API to interact with these files to just the degree
needed by Niotso. The function of FileHandler is analogous to the gimex library used in The Sims Online.
Supported formats:
Image:
(*) bmp, png, jpg, cur, tga
Audio:
(*) wav, mp3, xa, utk
Archive:
(*) far, iff
Plain-text:
(*) ini, xml, cst, uis

0
library/formats/TODO Normal file
View file

17
library/formats/Text.cpp Normal file
View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
Text.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

View file

@ -0,0 +1,160 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_bmp.c - Copyright (c) 2011-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 <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "read_bmp.h"
#define BI_RGB 0
#define BI_RLE8 1
#ifndef read_uint32
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#endif
int bmp_read_header(bmpheader_t * BMPHeader, const uint8_t * Buffer, size_t FileSize){
unsigned padding;
if(FileSize < 54) return 0;
BMPHeader->bfType = read_uint16(Buffer);
BMPHeader->bfSize = read_uint32(Buffer+2);
BMPHeader->bfReserved1 = read_uint16(Buffer+6);
BMPHeader->bfReserved2 = read_uint16(Buffer+8);
BMPHeader->bfOffBits = read_uint32(Buffer+10);
BMPHeader->biSize = read_uint32(Buffer+14);
BMPHeader->biWidth = read_uint32(Buffer+18);
BMPHeader->biHeight = read_uint32(Buffer+22);
BMPHeader->biPlanes = read_uint16(Buffer+26);
BMPHeader->biBitCount = read_uint16(Buffer+28);
BMPHeader->biCompression = read_uint32(Buffer+30);
BMPHeader->biSizeImage = read_uint32(Buffer+34);
BMPHeader->biXPelsPerMeter = read_uint32(Buffer+38);
BMPHeader->biYPelsPerMeter = read_uint32(Buffer+42);
BMPHeader->biClrUsed = read_uint32(Buffer+46);
BMPHeader->biClrImportant = read_uint32(Buffer+50);
if(BMPHeader->bfSize == 0) BMPHeader->bfSize = FileSize;
BMPHeader->CompressedSize = BMPHeader->bfSize - BMPHeader->bfOffBits;
BMPHeader->DecompressedSize = BMPHeader->biWidth * BMPHeader->biHeight * 3;
padding = BMPHeader->biWidth%4;
if(padding != 0) padding = (BMPHeader->biHeight-1)*(4-padding);
if(BMPHeader->bfType != 0x4D42 ||
BMPHeader->bfSize > FileSize ||
BMPHeader->bfReserved1 != 0 || BMPHeader->bfReserved2 != 0 ||
BMPHeader->biSize != 40 ||
BMPHeader->biWidth == 0 || BMPHeader->biWidth > 4096 || /*< Includes negative check */
BMPHeader->biHeight == 0 || BMPHeader->biHeight > 4096 || /*< by treating as unsigned */
BMPHeader->biPlanes != 1 ||
(BMPHeader->biBitCount != 24 &&
(BMPHeader->biBitCount != 8 || BMPHeader->bfSize < 1078 /* We need room for the color palette */)) ||
(BMPHeader->biCompression != BI_RGB &&
(BMPHeader->biCompression != BI_RLE8 || BMPHeader->biBitCount > 8)) ||
BMPHeader->bfOffBits >= BMPHeader->bfSize ||
(BMPHeader->biCompression == BI_RGB &&
((BMPHeader->biBitCount == 24 && BMPHeader->CompressedSize < BMPHeader->DecompressedSize + padding) ||
(BMPHeader->biBitCount == 8 && BMPHeader->CompressedSize < BMPHeader->DecompressedSize/3 + padding)))
) return 0;
return 1;
}
int bmp_read_data(bmpheader_t * BMPHeader, const uint8_t *__restrict InBuffer, uint8_t *__restrict OutBuffer){
if(BMPHeader->biBitCount == 24 && BMPHeader->biCompression == BI_RGB){
unsigned pitch = BMPHeader->biWidth*3;
unsigned i;
unsigned padding = pitch%4;
if(padding != 0) padding = 4-padding;
for(i=0; i<BMPHeader->biHeight; i++)
memcpy(OutBuffer + i*pitch, InBuffer+BMPHeader->bfOffBits + i*(pitch + padding), pitch);
return 1;
}
if(BMPHeader->biBitCount == 32 && BMPHeader->biCompression == BI_RGB){
unsigned i;
for(i=0; i<BMPHeader->biHeight*BMPHeader->biWidth; i++){
*(OutBuffer++) = *(InBuffer++);
*(OutBuffer++) = *(InBuffer++);
*(OutBuffer++) = *(InBuffer++);
InBuffer++;
}
return 1;
}
if(BMPHeader->biBitCount == 8){
const uint8_t *__restrict Palette = InBuffer + 54;
InBuffer += BMPHeader->bfOffBits;
if(BMPHeader->biCompression == BI_RGB){
unsigned y, x;
unsigned padding = BMPHeader->biWidth % 4;
if(padding != 0) padding = 4-padding;
for(y=0; y<BMPHeader->biHeight; y++){
for(x=0; x<BMPHeader->biWidth; x++){
unsigned index = 4*(*InBuffer++);
*OutBuffer++ = Palette[index];
*OutBuffer++ = Palette[index+1];
*OutBuffer++ = Palette[index+2];
}
InBuffer += padding;
}
return 1;
}
if(BMPHeader->biCompression == BI_RLE8){
const uint8_t *__restrict const srcend = InBuffer+BMPHeader->CompressedSize;
uint8_t *__restrict const destend = OutBuffer+BMPHeader->DecompressedSize;
while((unsigned)(srcend-InBuffer) >= 2){
unsigned i;
const unsigned command = *InBuffer++;
const unsigned value = *InBuffer++;
if(command == 0){
if(value == 0) continue; /* End of scanline reminder */
if(value == 1) return (InBuffer == srcend && OutBuffer == destend); /* End of bitmap reminder */
if(value == 2) return 0; /* Delta, used for ICO/CUR masks; wrong kind of bitmap */
/* Absolute copy */
if(value > (unsigned)(srcend-InBuffer) || value*3 > (unsigned)(destend-OutBuffer)) break;
for(i=0; i<value; i++){
unsigned index = 4*(*InBuffer++);
*OutBuffer++ = Palette[index];
*OutBuffer++ = Palette[index+1];
*OutBuffer++ = Palette[index+2];
}
if(value%2 && InBuffer != srcend) InBuffer++; /* Padding */
}else{
/* Run */
unsigned index = 4*value;
if(command > (unsigned)(destend-OutBuffer)) break;
for(i=0; i<command; i++){
*OutBuffer++ = Palette[index];
*OutBuffer++ = Palette[index+1];
*OutBuffer++ = Palette[index+2];
}
}
}
}
}
return 0;
}

View file

@ -0,0 +1,53 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_bmp.h - Copyright (c) 2011-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.
*/
typedef struct
{
/* BITMAPFILEHEADER */
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
/* BITMAPINFOHEADER */
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
size_t CompressedSize;
size_t DecompressedSize;
} bmpheader_t;
#ifdef __cplusplus
extern "C" {
#endif
int bmp_read_header(bmpheader_t * BMPHeader, const uint8_t * Buffer, size_t FileSize);
int bmp_read_data(bmpheader_t * BMPHeader, const uint8_t * InData, uint8_t * OutData);
#ifdef __cplusplus
}
#endif

49
library/formats/cst/cst.c Normal file
View file

@ -0,0 +1,49 @@
/*
FileHandler - General-purpose file handling library for Niotso
cst.c - 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 <stdlib.h>
#include <string.h>
#include "cst.h"
static unsigned cst_count_strings(const char * Buffer, size_t FileSize){
unsigned count = 0;
int instring = 0;
while(FileSize--){
if(*Buffer == '^' && (instring = !instring) == 0)
count++;
Buffer++;
}
return count;
}
int cst_read(CSTFile * CSTFileInfo, char * Buffer, size_t FileSize){
CSTFileInfo->CSTData = Buffer;
CSTFileInfo->StringCount = cst_count_strings(Buffer, FileSize);
if(CSTFileInfo->StringCount != 0){
unsigned i;
CSTFileInfo->Strings = malloc(CSTFileInfo->StringCount * sizeof(char *));
if(CSTFileInfo->Strings == NULL)
return 0;
for(i=0; i<CSTFileInfo->StringCount; i++){
CSTFileInfo->Strings[i] = Buffer = strchr(Buffer, '^') + 1;
*(Buffer = strchr(Buffer, '^')) = 0x00;
Buffer++;
}
}
return 1;
}

23
library/formats/cst/cst.h Normal file
View file

@ -0,0 +1,23 @@
/*
FileHandler - General-purpose file handling library for Niotso
cst.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.
*/
typedef struct {
char * CSTData;
unsigned StringCount;
char ** Strings;
} CSTFile;

View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_cur.c - 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.
*/

View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_cur.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.
*/

View file

@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 2.6)
project(far)
set(FAR_SOURCES
far.c
refpack_dec.c
)
add_library(far_static STATIC ${FAR_SOURCES})
set_target_properties(far_static PROPERTIES
OUTPUT_NAME "far"
CLEAN_DIRECT_OUTPUT 1)
#### Shared library (uncomment to build)
#add_library(far_shared SHARED ${FAR_SOURCES})
#set_target_properties(far_shared PROPERTIES
# OUTPUT_NAME "far"
# PREFIX ""
# CLEAN_DIRECT_OUTPUT 1)
add_executable(farextract farextract.c)
target_link_libraries(farextract far_static)

View file

@ -0,0 +1,24 @@
/* config.h - far build configuration */
/* Define if you have the <stdint.h> header file. */
#define HAVE_STDINT_H
/* compile-in support */
#define FAR_ARCHIVEREAD
#define FAR_ARCHIVEWRITE
#define FAR_REFPACK_DECOMPRESS
#define FAR_REFPACK_COMPRESS
#define FAR_SUPPORT_FAR
#define FAR_SUPPORT_DBPF
#define FAR_SUPPORT_PERSIST
#define FAR_DEBUGSUPPORT
#define FAR_FILEIO
#define FAR_EMBEDDEDFUNCTIONS
/* end of compile-in support */
/* preferences -- on non-numerical definitions, define to 1 for "yes", 0 for "no" */
#define FAR_DEFAULT_1A 0
#define FAR_DEFAULT_DBPF_COMPRESSED 0
#define FAR_DEFAULT_MAX_FILE_NAME_LENGTH 255
#define FAR_DEFAULT_REFPACK_HNSV 0xFB
/* end of default preferences */

446
library/formats/far/far.c Normal file
View file

@ -0,0 +1,446 @@
/*
FileHandler - General-purpose file handling library for Niotso
far.c - Copyright (c) 2011-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 "config.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "far.h"
#if defined(FAR_SUPPORT_PERSIST)
#define FAR_MINSIZE_ANY MINSIZE_PERSIST
#elif defined(FAR_SUPPORT_FAR)
#define FAR_MINSIZE_ANY MINSIZE_FAR
#else
#define FAR_MINSIZE_ANY MINSIZE_DBPF
#endif
#ifndef read_int32
#define read_int32(x) (int)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_int24(x) (int)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)))
#define read_int16(x) (int)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#define read_int8(x) (int)(((x)[0]<<(8*0)))
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint24(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)))
#define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#define read_uint8(x) (unsigned)(((x)[0]<<(8*0)))
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
/* These options can be changed during runtime */
static int libfarOptions[] = {
FAR_DEFAULT_1A,
FAR_DEFAULT_DBPF_COMPRESSED,
FAR_DEFAULT_MAX_FILE_NAME_LENGTH,
FAR_DEFAULT_REFPACK_HNSV
};
void libfar_set_option(int Option, int Value){
libfarOptions[Option] = Value;
}
int libfar_get_option(int Option){
return libfarOptions[Option];
}
int far_identify(const uint8_t * Buffer, unsigned FileSize)
{
if(!FileSize) FileSize = ~0;
else if(FileSize < FAR_MINSIZE_ANY)
return FAR_TYPE_INVALID;
#ifdef FAR_SUPPORT_FAR
if(FileSize >= MINSIZE_FAR && !memcmp(Buffer, Header_FAR, 8))
return FAR_TYPE_FAR;
#endif
#ifdef FAR_SUPPORT_DBPF
if(FileSize >= MINSIZE_DBPF && !memcmp(Buffer, Header_DBPF, 4))
return FAR_TYPE_DBPF;
#endif
#ifdef FAR_SUPPORT_PERSIST
if(FileSize >= MINSIZE_PERSIST && Buffer[0] == 0x01)
return FAR_TYPE_PERSIST;
#endif
return FAR_TYPE_INVALID;
}
FARFile * far_create_archive(int Type)
{
FARFile *ptr = calloc(1, sizeof(FARFile));
if(ptr == NULL) return NULL;
ptr->Type = Type;
return ptr;
}
PersistFile * far_create_persist()
{
return calloc(1, sizeof(PersistFile));
}
FAREntryNode * far_add_entry(FARFile * FARFileInfo, int Position)
{
FAREntryNode *ptr = calloc(1, sizeof(FAREntryNode)), *node;
if(ptr == NULL) return NULL;
if(FARFileInfo == NULL) return ptr;
if(Position >= 0){
node = FARFileInfo->FirstEntry;
if(node == NULL){
FARFileInfo->FirstEntry = ptr;
FARFileInfo->LastEntry = ptr;
}else{
/* Find the node we will take the place of */
while(Position-- && node->NextEntry != NULL)
node = node->NextEntry;
if(node->PrevEntry == NULL)
FARFileInfo->FirstEntry = ptr;
/* Shift this node and all nodes after it above us */
ptr->PrevEntry = node->PrevEntry;
ptr->NextEntry = node;
node->PrevEntry = ptr;
}
}else{
node = FARFileInfo->LastEntry;
if(node == NULL){
FARFileInfo->FirstEntry = ptr;
FARFileInfo->LastEntry = ptr;
}else{
/* Find the node we will take the place of */
while(++Position && node->PrevEntry != NULL)
node = node->PrevEntry;
if(node->NextEntry == NULL)
FARFileInfo->LastEntry = ptr;
/* Shift this node and all nodes before it below us */
ptr->PrevEntry = node;
ptr->NextEntry = node->NextEntry;
node->NextEntry = ptr;
}
}
FARFileInfo->Files++;
return ptr;
}
int far_read_header(FARFile * FARFileInfo, const uint8_t * Buffer, unsigned FileSize)
{
if(!FileSize) FileSize = ~0;
else if(FileSize < FAR_MINSIZE_ANY)
return 0;
#ifdef FAR_SUPPORT_FAR
if(FARFileInfo->Type == FAR_TYPE_FAR){
FARFileInfo->MajorVersion = read_uint32(Buffer+8);
FARFileInfo->IndexOffset = read_uint32(Buffer+12);
if(FARFileInfo->MajorVersion != 1 && FARFileInfo->MajorVersion != 3)
return 0;
if(FARFileInfo->MajorVersion == 1)
FARFileInfo->Revision = !libfarOptions[FAR_CONFIG_DEFAULT_TO_1A];
if(FARFileInfo->IndexOffset > FileSize-4)
return 0;
FARFileInfo->Files = read_uint32(Buffer + FARFileInfo->IndexOffset);
if(FARFileInfo->Files > (FileSize-FARFileInfo->IndexOffset) / (
(FARFileInfo->MajorVersion == 1) ? (
(FARFileInfo->Revision == 0) ? MINSIZE_ENTRY_FAR_1A : MINSIZE_ENTRY_FAR_1B
) : MINSIZE_ENTRY_FAR_3)
) return 0;
return 1;
}
#endif
#ifdef FAR_SUPPORT_DBPF
if(FARFileInfo->Type == FAR_TYPE_DBPF){
int i;
FARFileInfo->MajorVersion = read_uint32(Buffer+4);
FARFileInfo->MinorVersion = read_uint32(Buffer+8);
FARFileInfo->DateCreated = read_uint32(Buffer+24);
FARFileInfo->DateModified = read_uint32(Buffer+28);
FARFileInfo->IndexMajorVersion = read_uint32(Buffer+32);
FARFileInfo->Files = read_uint32(Buffer+36);
FARFileInfo->IndexOffset = read_uint32(Buffer+40);
FARFileInfo->IndexSize = read_uint32(Buffer+44);
FARFileInfo->TrashCount = read_uint32(Buffer+48);
FARFileInfo->TrashOffset = read_uint32(Buffer+52);
FARFileInfo->TrashSize = read_uint32(Buffer+56);
FARFileInfo->IndexMinorVersion = read_uint32(Buffer+60);
if(FARFileInfo->MajorVersion != 1) return 0;
if(FARFileInfo->MinorVersion != 0) return 0;
if(FARFileInfo->IndexMajorVersion != 7) return 0;
if(FARFileInfo->IndexMinorVersion != 0) return 0;
for(i=12; i<24; i++)
if(Buffer[i] != 0x00) return 0;
if(FARFileInfo->Files){
if(FARFileInfo->Files > MAX_ENTRIES_DBPF) return 0;
if(FARFileInfo->IndexSize != FARFileInfo->Files*SIZEOF_ENTRY_DBPF) return 0;
if(FARFileInfo->IndexOffset > FileSize) return 0;
if(FARFileInfo->IndexSize > FileSize - FARFileInfo->IndexOffset) return 0;
}
if(FARFileInfo->TrashCount){
if(FARFileInfo->TrashCount > MAX_ENTRIES_DBPF) return 0;
if(FARFileInfo->TrashSize != FARFileInfo->TrashCount*SIZEOF_ENTRY_DBPF) return 0;
if(FARFileInfo->TrashOffset > FileSize) return 0;
if(FARFileInfo->TrashSize > FileSize - FARFileInfo->TrashOffset) return 0;
}
return 1;
}
#endif
return 0;
}
int far_read_entry(const FARFile * FARFileInfo, FAREntry * FAREntryInfo,
const uint8_t * Buffer, unsigned MaxEntrySize, unsigned ArchiveSize)
{
int MajorVersion = FARFileInfo->MajorVersion, Revision = FARFileInfo->Revision;
if(MaxEntrySize == 0) MaxEntrySize = ~0;
if(ArchiveSize == 0) ArchiveSize = ~0;
#ifdef FAR_SUPPORT_FAR
if(FARFileInfo->Type == FAR_TYPE_FAR){
unsigned MinEntrySize =
(MajorVersion == 1) ? (
(Revision == 0) ? MINSIZE_ENTRY_FAR_1A : MINSIZE_ENTRY_FAR_1B
) : MINSIZE_ENTRY_FAR_3;
if(MaxEntrySize < MinEntrySize)
return 0;
if(MajorVersion == 1){
FAREntryInfo->DecompressedSize = read_uint32(Buffer+0);
FAREntryInfo->CompressedSize = read_uint32(Buffer+4);
FAREntryInfo->DataOffset = read_uint32(Buffer+8);
if(Revision == 0)
FAREntryInfo->FilenameLength = read_uint32(Buffer+12);
else
FAREntryInfo->FilenameLength = read_uint16(Buffer+12);
}else if(MajorVersion == 3){
FAREntryInfo->DecompressedSize = read_uint32(Buffer+0);
FAREntryInfo->CompressedSize = read_uint24(Buffer+4);
FAREntryInfo->DataType = read_uint8(Buffer+7);
FAREntryInfo->DataOffset = read_uint32(Buffer+8);
FAREntryInfo->HasFilename = read_uint16(Buffer+12);
FAREntryInfo->FilenameLength = read_uint16(Buffer+14);
FAREntryInfo->TypeID = read_uint32(Buffer+16);
FAREntryInfo->FileID = read_uint32(Buffer+20);
}
if(FAREntryInfo->FilenameLength > MaxEntrySize - MinEntrySize) return 0;
if(FAREntryInfo->FilenameLength > (unsigned)libfarOptions[FAR_CONFIG_MAX_FILE_NAME_LENGTH]) return 0;
if(FAREntryInfo->CompressedSize > FAREntryInfo->DecompressedSize) return 0;
if(FAREntryInfo->DecompressedSize != 0){
if(FAREntryInfo->DataOffset > ArchiveSize) return 0;
if(FAREntryInfo->CompressedSize > ArchiveSize - FAREntryInfo->DataOffset) return 0;
}else if(MajorVersion == 3 && FAREntryInfo->DataType != 0) return 0;
FAREntryInfo->Filename = malloc(FAREntryInfo->FilenameLength + 1);
if(FAREntryInfo->Filename == NULL) return 0;
if(FAREntryInfo->FilenameLength != 0)
memcpy(FAREntryInfo->Filename, Buffer+MinEntrySize, FAREntryInfo->FilenameLength);
FAREntryInfo->Filename[FAREntryInfo->FilenameLength] = '\0';
return 1;
}
#endif
#ifdef FAR_SUPPORT_DBPF
if(FARFileInfo->Type == FAR_TYPE_DBPF){
if(MaxEntrySize < SIZEOF_ENTRY_DBPF) return 0;
FAREntryInfo->TypeID = read_uint32(Buffer+0);
FAREntryInfo->GroupID = read_uint32(Buffer+4);
FAREntryInfo->FileID = read_uint32(Buffer+8);
FAREntryInfo->DataOffset = read_uint32(Buffer+12);
FAREntryInfo->CompressedSize = read_uint32(Buffer+16);
FAREntryInfo->DecompressedSize = FAREntryInfo->CompressedSize;
if(FAREntryInfo->CompressedSize != 0){
if(FAREntryInfo->CompressedSize > ArchiveSize - FAREntryInfo->DataOffset) return 0;
if(FAREntryInfo->DataOffset > ArchiveSize) return 0;
if(FAREntryInfo->CompressedSize > ArchiveSize - FAREntryInfo->DataOffset) return 0;
}
return 1;
}
#endif
return 0;
}
int far_read_persist_header(PersistFile * PersistData, const uint8_t * Buffer, unsigned FileSize)
{
RefPackParameters * Parameters;
PersistData->BodyType = read_uint8(Buffer);
PersistData->DecompressedSize = read_uint32(Buffer+1);
PersistData->CompressedSize = read_uint32(Buffer+5);
PersistData->StreamBodySize = read_uint32(Buffer+9);
PersistData->Compressor = read_uint8(Buffer+13);
if(PersistData->BodyType != 1)
return 0;
if(PersistData->CompressedSize < FileSize-9)
return 0;
if(PersistData->CompressedSize != PersistData->StreamBodySize)
return 0;
PersistData->Parameters = malloc(sizeof(RefPackParameters));
if(PersistData->Parameters == NULL)
return 0;
Parameters = (RefPackParameters *) PersistData->Parameters;
Parameters->hnsv = read_uint8(Buffer+14);
Parameters->DecompressedSize = (Buffer[15]<<16) | (Buffer[16]<<8) | Buffer[17]; /* Big endian */
if((PersistData->DecompressedSize&0x00FFFFFF) != Parameters->DecompressedSize){
free(PersistData->Parameters); return 0;
}
return 1;
}
int far_read_entry_data(const FARFile * FARFileInfo, FAREntry * FAREntryInfo, uint8_t * Buffer)
{
int Compressed = (FARFileInfo->Type == FAR_TYPE_FAR) ? (
(FARFileInfo->MajorVersion == 1) ? (
FAREntryInfo->DecompressedSize != FAREntryInfo->CompressedSize
) : FAREntryInfo->DataType == 0x80) : libfarOptions[FAR_CONFIG_DBPF_COMPRESSED];
FAREntryInfo->CompressedData = Buffer+FAREntryInfo->DataOffset;
if(!Compressed)
FAREntryInfo->DecompressedData = FAREntryInfo->CompressedData;
else{
PersistFile * PersistInfo = &(FAREntryInfo->PersistData);
if(far_identify(FAREntryInfo->CompressedData, FAREntryInfo->CompressedSize) != FAR_TYPE_PERSIST)
return 0;
if(!far_read_persist_header(PersistInfo, FAREntryInfo->CompressedData, FAREntryInfo->CompressedSize))
return 0;
/* Verify that the Persist data agrees with the entry data */
if(PersistInfo->DecompressedSize != FAREntryInfo->DecompressedSize){
free(PersistInfo->Parameters); return 0;
}if(PersistInfo->CompressedSize != FAREntryInfo->CompressedSize - 9){
free(PersistInfo->Parameters); return 0;
}if(PersistInfo->Compressor != 0x10){
free(PersistInfo->Parameters); return 0;
}
PersistInfo->DecompressedData = FAREntryInfo->DecompressedData;
if(!far_read_persist_data(PersistInfo, FAREntryInfo->CompressedData+18)){
free(PersistInfo->Parameters); return 0;
}
FAREntryInfo->DecompressedData = PersistInfo->DecompressedData;
}
return 1;
}
int far_read_persist_data(PersistFile * PersistData, uint8_t * CompressedData)
{
if(CompressedData != NULL) PersistData->CompressedData = CompressedData;
PersistData->DecompressedData = malloc(PersistData->DecompressedSize);
if(PersistData->DecompressedData == NULL)
return 0;
if(!RefPackDecompress(PersistData->CompressedData, PersistData->CompressedSize-9,
PersistData->DecompressedData, PersistData->DecompressedSize,
libfarOptions[FAR_CONFIG_REFPACK_HNSV])){
free(PersistData->DecompressedData);
return 0;
}
return 1;
}
int far_enumerate_entries(FARFile * FARFileInfo, const uint8_t * Index, unsigned IndexSize, unsigned ArchiveSize)
{
unsigned Files = FARFileInfo->Files;
int ArchiveType = FARFileInfo->Type;
unsigned MinEntrySize = (ArchiveType == FAR_TYPE_FAR) ? (
(FARFileInfo->MajorVersion == 1) ? (
(FARFileInfo->Revision == 0) ? MINSIZE_ENTRY_FAR_1A : MINSIZE_ENTRY_FAR_1B
) : MINSIZE_ENTRY_FAR_3) : SIZEOF_ENTRY_DBPF;
unsigned EntriesAdded = 0;
FARFileInfo->Files = 0;
if(FARFileInfo->Type == FAR_TYPE_FAR)
Index += 4;
while(EntriesAdded < Files){
FAREntryNode * node = far_add_entry(FARFileInfo, -1);
if(node == NULL)
return 0;
if(!far_read_entry(FARFileInfo, &(node->Entry), Index, IndexSize, ArchiveSize)){
free(node);
return 0;
}
EntriesAdded++;
Index += MinEntrySize;
IndexSize -= MinEntrySize;
if(ArchiveType != FAR_TYPE_DBPF){
Index += node->Entry.FilenameLength;
IndexSize -= node->Entry.FilenameLength;
}
}
return (EntriesAdded == FARFileInfo->Files);
}
int far_enumerate_entry_data(const FARFile * FARFileInfo, uint8_t * Buffer)
{
FAREntryNode * node = FARFileInfo->FirstEntry;
while(node){
if(!far_read_entry_data(FARFileInfo, &(node->Entry), Buffer))
return 0;
node = node->NextEntry;
}
return 1;
}
void libfar_free(void * ptr)
{
free(ptr);
}

176
library/formats/far/far.h Normal file
View file

@ -0,0 +1,176 @@
/*
FileHandler - General-purpose file handling library for Niotso
far.h - Copyright (c) 2011 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.
*/
/****
** Constants
*/
/* libfarOptions array members */
#define FAR_CONFIG_DEFAULT_TO_1A 0
#define FAR_CONFIG_DBPF_COMPRESSED 1
#define FAR_CONFIG_MAX_FILE_NAME_LENGTH 2
#define FAR_CONFIG_REFPACK_HNSV 3
/* Archive types */
#define FAR_TYPE_INVALID 0
#define FAR_TYPE_FAR 1
#define FAR_TYPE_DBPF 2
#define FAR_TYPE_PERSIST 3
/* Numerical constants */
#define FAR_ARCHIVE_MINIMUM_SIZE 14
#define MINSIZE_FAR 20
#define MINSIZE_DBPF 64
#define MINSIZE_ENTRY_FAR_1A 16
#define MINSIZE_ENTRY_FAR_1B 14
#define MINSIZE_ENTRY_FAR_3 24
#define SIZEOF_ENTRY_DBPF 20
#define MAX_ENTRIES_FAR_1A 268435455
#define MAX_ENTRIES_FAR_1B 306783377
#define MAX_ENTRIES_FAR_3 178956970
#define MAX_ENTRIES_DBPF 214748364
#define MINSIZE_PERSIST 18
#define MAXSIZE_REFPACK_UNCOMPRESSED 16777215
#define MAXSIZE_REFPACK_COMPRESSED 16777215
/* Header bytes */
static const uint8_t Header_FAR[] = {'F','A','R','!','b','y','A','Z'};
static const uint8_t Header_DBPF[] = {'D','B','P','F'};
/****
** Data structures
*/
typedef struct PersistFile_s
{
uint8_t BodyType;
uint32_t DecompressedSize;
uint32_t CompressedSize;
uint32_t StreamBodySize;
uint8_t Compressor;
uint8_t * Parameters;
uint8_t * CompressedData;
uint8_t * DecompressedData;
} PersistFile;
typedef struct RefPackParameters_s
{
uint8_t hnsv;
uint32_t DecompressedSize;
} RefPackParameters;
typedef struct FAREntry_s
{
uint32_t DecompressedSize;
uint32_t CompressedSize;
uint8_t DataType;
uint32_t DataOffset;
uint16_t HasFilename;
uint32_t FilenameLength;
uint32_t TypeID;
uint32_t GroupID;
uint32_t FileID;
char * Filename;
PersistFile PersistData;
uint8_t * CompressedData;
uint8_t * DecompressedData;
} FAREntry;
typedef struct FAREntryNode_s
{
FAREntry Entry;
struct FAREntryNode_s * PrevEntry;
struct FAREntryNode_s * NextEntry;
} FAREntryNode;
typedef struct FARFile_s
{
int32_t Type;
/* Header */
uint32_t MajorVersion;
uint32_t MinorVersion;
uint32_t Revision;
uint32_t IndexOffset;
/* DBPF */
uint32_t DateCreated;
uint32_t DateModified;
uint32_t IndexMajorVersion;
uint32_t IndexSize;
uint32_t TrashCount;
uint32_t TrashOffset;
uint32_t TrashSize;
uint32_t IndexMinorVersion;
/* Regular index */
uint32_t Files;
FAREntryNode * FirstEntry;
FAREntryNode * LastEntry;
struct { /* DIR index for DBPF */
FAREntryNode * FirstEntry;
FAREntryNode * LastEntry;
} Dir;
struct { /* Trash index for DBPF */
FAREntryNode * FirstEntry;
FAREntryNode * LastEntry;
} Trash;
} FARFile;
/****
** Exported functions
*/
#ifdef __cplusplus
extern "C" {
#endif
void libfar_set_option(int Option, int Value);
int libfar_get_option(int Option);
int far_identify(const uint8_t * Buffer, unsigned FileSize);
FARFile * far_create_archive(int Type);
PersistFile * far_create_persist();
FAREntryNode * far_add_entry(FARFile * FARFileInfo, int Position);
int far_read_header(FARFile * FARFileInfo, const uint8_t * Buffer, unsigned FileSize);
int far_read_entry(const FARFile * FARFileInfo, FAREntry * FAREntryInfo,
const uint8_t * Buffer, unsigned MaxEntrySize, unsigned ArchiveSize);
int far_read_persist_header(PersistFile * PersistData, const uint8_t * Buffer, unsigned FileSize);
int far_read_entry_data(const FARFile * FARFileInfo, FAREntry * FAREntryInfo, uint8_t * Buffer);
int far_read_persist_data(PersistFile * PersistData, uint8_t * CompressedData);
int far_enumerate_entries(FARFile * FARFileInfo, const uint8_t * Index, unsigned IndexSize, unsigned ArchiveSize);
int far_enumerate_entry_data(const FARFile * FARFileInfo, uint8_t * Buffer);
FAREntryNode * far_search_id();
FAREntryNode * far_search_name();
FAREntryNode * far_search_multi();
void far_delete_entry(FARFile * FARFileInfo, int Position);
void far_delete_archive(FARFile * FARFileInfo);
void far_delete_persist(FARFile * FARFileInfo);
void libfar_free(void * ptr);
int RefPackDecompress(const uint8_t * CompressedData, size_t CompressedSize,
uint8_t * DecompressedData, size_t DecompressedSize, unsigned HNSV);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,430 @@
/*
FileHandler - General-purpose file handling library for Niotso
farextract.c - Copyright (c) 2011 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <sys/stat.h>
#include <errno.h>
#include "far.h"
#ifndef read_uint32
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#endif
#ifdef _WIN32
#define mkdir(path, x) mkdir(path)
#endif
static int mkpath(char * path){
char * p;
for(p = strpbrk(path+1, "/\\"); p; p = strpbrk(p+1, "/\\")){
char c = *p;
int value;
*p = '\0'; value = mkdir(path, 0644); *p = c;
if(value != 0 && errno != EEXIST)
return -1;
}
return 0;
}
enum {
profile_ts1 = 1,
profile_tso,
profile_sc4,
profile_ts2,
profile_spore,
profile_ts3
};
typedef struct {
uint32_t GroupID;
const char * Directory;
} GroupMap_t;
typedef struct {
uint32_t TypeID;
const char * Extension;
} TypeMap_t;
typedef struct {
uint8_t Size;
const char * Header;
const char * Extension;
} HeaderMap_t;
static const GroupMap_t GroupMap[] = {
{0x0A3C55C7, "Music/Stations/Horror/"},
{0x0A3C55CE, "Music/Stations/OldWorld/"},
{0x0A3C55D3, "Music/Stations/SciFi/"},
{0x1D6962CF, "SoundData/HitLabUI/"},
{0x1D8A8B4F, "SoundData/HitLabTestSamples/"},
{0x29D9359D, "SoundData/CustomTrks/"},
{0x29DAA4A6, "SoundData/Custom/"},
{0x29DD0888, "SoundData/Multiplayer/"},
{0x69C6C943, "SoundData/tsov2/"},
{0x8A6FCC30, "SoundData/EP5Samps/"},
{0x9DBDBF74, "SoundData/HitLists/"},
{0x9DBDBF89, "SoundData/Samples/"},
{0x9DF26DAD, "Music/Stations/Country/"},
{0x9DF26DAE, "Music/Stations/CountryD/"},
{0x9DF26DB1, "Music/Stations/Latin/"},
{0x9DF26DB3, "Music/Stations/Rap/"},
{0x9DF26DB6, "Music/Stations/Rock/"},
{0xA9C6C89A, "SoundData/Tracks/"},
{0xBD6E5937, "SoundData/HitLabTest/"},
{0xBDF26DB0, "Music/Stations/Disco/"},
{0xC9C6C9B3, "SoundData/HitListsTemp/"},
{0xDDBDBF8C, "SoundData/Stings/"},
{0xDDE8F5C6, "SoundData/EP2/"},
{0xDDF26DA9, "Music/Stations/Beach/"},
{0xDDF26DB4, "Music/Stations/Rave/"},
{0xFDBDBF87, "SoundData/TrackDefs/"},
{0xFDF26DAB, "Music/Stations/Classica/"}
};
static const TypeMap_t TypeMap[] = {
{0, ".dat"},
{1, ".bmp"},
{2, ".tga"},
{5, ".skel"},
{7, ".anim"},
{9, ".mesh"},
{11, ".bnd"},
{12, ".apr"},
{13, ".oft"},
{14, ".png"},
{15, ".po"},
{16, ".col"},
{18, ".hag"},
{20, ".jpg"},
{24, ".png"},
{0x0A8B0E70, ".mad"},
{0x1B6B9806, ".utk"},
{0x1D07EB4B, ".xa"},
{0x1D968538, ".xa"},
{0x2026960B, ".dat"},
{0x3CEC2B47, ".mp3"},
{0x3D968536, ".mp3"},
{0x5D73A611, ".trk"},
{0x7B1ACFCD, ".hls"},
{0x856DDBAC, ".bmp"},
{0x9D796DB4, ".tlo"},
{0x9D96853A, ".wav"},
{0xA3CD96CF, ".tkd"},
{0xBB7051F5, ".wav"}
};
static const HeaderMap_t AudioHeaders[] = {
{2, "XA", ".xa"},
{4, "RIFF", ".wav"},
{4, "UTM0", ".utk"},
{4, "\xFF\xFB\x90\x40", ".mp3"},
{24, "# Generated by UI editor", ".scr"}
};
static const char * groupid_to_dir(uint32_t GroupID){
size_t i;
for(i=0; i<sizeof(GroupMap)/sizeof(GroupMap_t); i++){
if(GroupMap[i].GroupID == GroupID)
return GroupMap[i].Directory;
}
fprintf(stderr, "%sUnrecognized Group ID 0x%08X.\n", "farextract: warning: ", GroupID);
return "./";
}
static const char * typeid_to_ext(uint32_t TypeID){
size_t i;
for(i=0; i<sizeof(TypeMap)/sizeof(TypeMap_t); i++){
if(TypeMap[i].TypeID == TypeID)
return TypeMap[i].Extension;
}
fprintf(stderr, "%sUnrecognized Type ID 0x%08X.\n", "farextract: warning: ", TypeID);
return ".dat";
}
static const char * header_to_ext(const uint8_t * Buffer, size_t Size){
size_t i;
for(i=0; i<sizeof(AudioHeaders)/sizeof(HeaderMap_t); i++){
if(Size >= AudioHeaders[i].Size && !memcmp(Buffer, AudioHeaders[i].Header, AudioHeaders[i].Size))
return AudioHeaders[i].Extension;
}
return ".str";
}
int main(int argc, char *argv[]){
int profile = 0, overwrite = 0;
const char * InFile = "", * OutDirectory;
FILE * hFile;
size_t ArchiveSize;
uint8_t * ArchiveData;
int ArchiveType;
clock_t BeginningTime, EndingTime;
unsigned extracted = 0;
int i;
/****
** Check the arguments
*/
if(argc == 1 || (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))){
printf("Usage: farextract [OPTIONS] [FILE] [OUTDIRECTORY]\n"
"Extract the contents of a FAR, DBPF, or Persist file.\n"
"With no FILE, or when FILE is -, read from standard input.\n"
"\n"
"Profile options:\n"
" -ts1, -tso, -sc4, Select presets suitable for The Sims 1,\n"
" -ts2, -spore, -ts3 The Sims Online, SimCity 4, Spore, or The Sims 3\n"
"\n");
printf("Miscellaneous options:\n"
" -f, --force Force overwriting of files without confirmation\n"
" -h, --help Show this help and exit\n"
"\n"
"Report bugs to <X-Fi6@phppoll.org>.\n"
"farextract and libfar are maintained by the Niotso project.\n"
"Home page: <http://www.niotso.org/>\n");
return 0;
}
for(i=1; !InFile[0] && i != argc-1; i++){
/* Match for options */
if(!profile){
if(!strcmp(argv[i], "-ts1")){ profile = profile_ts1; continue; }
if(!strcmp(argv[i], "-tso")){ profile = profile_tso; continue; }
if(!strcmp(argv[i], "-sc4")){ profile = profile_sc4; continue; }
if(!strcmp(argv[i], "-ts2")){ profile = profile_ts2; continue; }
if(!strcmp(argv[i], "-spore")){ profile = profile_spore; continue; }
if(!strcmp(argv[i], "-ts3")){ profile = profile_ts3; continue; }
}
if(!overwrite && (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--force"))){
overwrite = 1;
continue;
}
/* Not an option */
if(!strcmp(argv[i], "-")){
fprintf(stderr, "%sReading from standard input is not yet implemented.", "farextract: error: ");
return -1;
}
InFile = argv[i];
continue;
}
/* We're left with the out directory */
if(!InFile[0]){
fprintf(stderr, "%sReading from standard input is not yet implemented.", "farextract: error: ");
return -1;
}
OutDirectory = argv[i];
/****
** Handle profile settings
*/
if(!profile) profile = profile_tso;
libfar_set_option(FAR_CONFIG_DEFAULT_TO_1A, (profile == profile_ts1));
libfar_set_option(FAR_CONFIG_DBPF_COMPRESSED, (profile >= profile_sc4));
libfar_set_option(FAR_CONFIG_REFPACK_HNSV, 0xFB);
/****
** Open the file and read in the entire contents to memory
*/
hFile = fopen(InFile, "rb");
if(hFile == NULL){
fprintf(stderr, "%sThe specified input file does not exist or could not be opened for reading.", "farextract: error: ");
return -1;
}
fseek(hFile, 0, SEEK_END);
ArchiveSize = ftell(hFile);
if(ArchiveSize < 24){
fprintf(stderr, "%sNot a valid archive.", "farextract: error: ");
return -1;
}
fseek(hFile, 0, SEEK_SET);
ArchiveData = malloc(ArchiveSize);
if(ArchiveData == NULL){
fprintf(stderr, "%sMemory for this archive could not be allocated.", "farextract: error: ");
return -1;
}
if(fread(ArchiveData, 1, ArchiveSize, hFile) != ArchiveSize){
fprintf(stderr, "%sThe input file could not be read.", "farextract: error: ");
return -1;
}
fclose(hFile);
/****
** Identify the type of archive
*/
ArchiveType = far_identify(ArchiveData, ArchiveSize);
if(ArchiveType == FAR_TYPE_INVALID){
fprintf(stderr, "%sNot a valid archive.", "farextract: error: ");
return -1;
}
if(chdir(OutDirectory) != 0){
fprintf(stderr, "%sOutput directory '%s' does not exist.", "farextract: error: ", OutDirectory);
return -1;
}
if(ArchiveType != FAR_TYPE_PERSIST){
FAREntryNode * EntryNode;
unsigned file = 0, filescount;
/****
** Load header information
*/
FARFile * FARFileInfo = far_create_archive(ArchiveType);
if(FARFileInfo == NULL){
fprintf(stderr, "%sMemory for this archive could not be allocated.", "farextract: error: ");
return -1;
}
if(!far_read_header(FARFileInfo, ArchiveData, ArchiveSize)){
fprintf(stderr, "%sNot a valid archive.", "farextract: error: ");
return -1;
}
filescount = FARFileInfo->Files;
printf("This archive contains %u files.\n\nExtracting\n", filescount);
BeginningTime = clock();
/****
** Load entry information
*/
if(!far_enumerate_entries(FARFileInfo, ArchiveData+FARFileInfo->IndexOffset,
ArchiveSize-FARFileInfo->IndexOffset, ArchiveSize)){
fprintf(stderr, "%sEntry data is corrupt.", "farextract: error: ");
return -1;
}
/****
** Extract each entry
*/
for(EntryNode = FARFileInfo->FirstEntry; EntryNode; EntryNode = EntryNode->NextEntry){
char destbuffer[256], * destination = destbuffer;
file++;
if(EntryNode->Entry.Filename)
destination = EntryNode->Entry.Filename;
else
sprintf(destbuffer, "%s%08x%s", groupid_to_dir(EntryNode->Entry.GroupID),
EntryNode->Entry.FileID, typeid_to_ext(EntryNode->Entry.TypeID));
if(far_read_entry_data(FARFileInfo, &(EntryNode->Entry), ArchiveData)){
/* Decompression, if any, was successful */
if(!EntryNode->Entry.Filename && EntryNode->Entry.TypeID == 0x2026960B)
sprintf(destbuffer, "%s%08x%s", groupid_to_dir(EntryNode->Entry.GroupID), EntryNode->Entry.FileID,
header_to_ext(EntryNode->Entry.DecompressedData, EntryNode->Entry.DecompressedSize));
}else{
printf(" (%u/%u) Skipped (%s): %s\n", file, filescount, "entry data is corrupt", destination);
continue;
}
if(mkpath(destination) != 0){
fprintf(stderr, "%sCould not create path '%s'.", "farextract: error: ", destination);
return -1;
}
if(!overwrite){
hFile = fopen(destination, "rb");
if(hFile != NULL){
/* File exists */
fclose(hFile);
printf(" (%u/%u) Skipped (%s): %s\n", file, filescount, "file exists", destination);
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", destination);
if(EntryNode->Entry.DecompressedData != EntryNode->Entry.CompressedData)
libfar_free(EntryNode->Entry.DecompressedData);
continue;
}
printf(" (%u/%u) %s (Group ID: 0x%08X, File ID: 0x%08X, Type ID: 0x%08X) (%u bytes)\n", file, filescount,
destination, EntryNode->Entry.GroupID, EntryNode->Entry.FileID, EntryNode->Entry.TypeID,
EntryNode->Entry.DecompressedSize);
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.", extracted, filescount,
((float) (clock() - BeginningTime))/CLOCKS_PER_SEC);
}else{
/* Persist file */
PersistFile * PersistInfo;
/****
** Load header information
*/
PersistInfo = far_create_persist();
if(PersistInfo == NULL){
fprintf(stderr, "%sMemory for this archive could not be allocated.", "farextract: error: ");
return -1;
}
if(!far_read_persist_header(PersistInfo, ArchiveData, ArchiveSize)){
fprintf(stderr, "%sNot a valid archive.", "farextract: error: ");
return -1;
}
/****
** Extract the data
*/
printf("Extracting\n");
BeginningTime = clock();
if(!far_read_persist_data(PersistInfo, ArchiveData+18)){
fprintf(stderr, "%sNot a valid archive.", "farextract: error: ");
return -1;
}
EndingTime = clock();
if(!overwrite){
hFile = fopen(InFile, "rb");
if(hFile != NULL){
/* File exists */
fclose(hFile);
fprintf(stderr, "%sFile exists.", "farextract: error: ");
libfar_free(PersistInfo->DecompressedData);
return -1;
}
}
hFile = fopen(InFile, "wb");
if(hFile == NULL){
fprintf(stderr, "%sCould not open.", "farextract: error: ");
libfar_free(PersistInfo->DecompressedData);
return -1;
}
fwrite(PersistInfo->DecompressedData, 1, PersistInfo->DecompressedSize, hFile);
fclose(hFile);
printf("Extracted %u bytes in %.2f seconds.\n", PersistInfo->DecompressedSize,
((float) (EndingTime - BeginningTime))/CLOCKS_PER_SEC);
}
return 0;
}

View file

@ -0,0 +1,200 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="191.67342"
height="69.682022"
id="svg2"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="libfar.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="209.27206"
inkscape:cy="113.29596"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1030"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
fit-margin-top="2"
fit-margin-left="2"
fit-margin-right="2"
fit-margin-bottom="2" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-98.729108,-354.59789)">
<g
style="font-size:80.0009613px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:ParkAvenue BT;-inkscape-font-specification:ParkAvenue BT"
id="text2989">
<path
d="m 100.72911,361.63701 6.56014,-4.1602 0,45.6817 -6.56014,0 z"
style="font-family:Blue Highway;-inkscape-font-specification:Blue Highway"
id="path3052" />
<path
d="m 115.10672,368.99794 6.56014,0 0,34.16057 -6.56014,0 z m 3.28129,-3.52055 c -1.12144,4e-5 -2.01541,-0.4264 -2.68192,-1.27931 -0.66651,-0.85284 -0.99977,-1.89289 -0.99976,-3.12016 -10e-6,-1.27926 0.32023,-2.34576 0.9607,-3.1995 0.64047,-0.85364 1.54746,-1.28048 2.72098,-1.28053 1.01238,5e-5 1.87868,0.42689 2.59891,1.28053 0.72021,0.85374 1.08032,1.92024 1.08034,3.1995 -2e-5,1.22727 -0.37355,2.26732 -1.12062,3.12016 -0.74709,0.85291 -1.59997,1.27935 -2.55863,1.27931 z"
style="font-family:Blue Highway;-inkscape-font-specification:Blue Highway"
id="path3054" />
<path
d="m 135.88578,391.31755 c 0.10741,0.53387 0.34749,1.13405 0.72022,1.80055 0.37272,0.66653 0.83903,1.27973 1.39895,1.83963 0.55989,0.55991 1.19995,1.04005 1.92019,1.44044 0.7202,0.4004 1.50757,0.6006 2.36208,0.6006 1.17188,0 2.22454,-0.27995 3.158,-0.83986 0.93342,-0.55989 1.72038,-1.30656 2.36087,-2.24001 0.64045,-0.93344 1.1206,-2.04022 1.44045,-3.32036 0.3198,-1.28011 0.47971,-2.64039 0.47974,-4.08086 -3e-5,-3.57261 -0.55993,-6.34567 -1.67971,-8.31919 -1.11983,-1.97347 -3.12017,-2.96021 -6.00105,-2.96024 -1.59997,3e-5 -2.91997,0.60021 -3.96001,1.80056 -1.04006,1.2004 -1.7733,2.68031 -2.19973,4.43975 z m -6.56014,-30.55945 6.56014,-2.8809 0,13.92107 c 0.69336,-0.90656 1.76026,-1.66666 3.20072,-2.2803 1.44043,-0.61358 2.96063,-0.92039 4.5606,-0.92042 3.89326,3e-5 6.91982,1.57353 9.0797,4.72051 2.15983,3.14704 3.23976,7.54691 3.23979,13.19962 -3e-5,2.40076 -0.29341,4.64118 -0.88014,6.72128 -0.58679,2.08011 -1.44007,3.89328 -2.55984,5.43951 -1.11984,1.54625 -2.46669,2.75964 -4.04058,3.64018 -1.57393,0.88055 -3.34723,1.32082 -5.31989,1.32082 -1.49417,0 -2.84103,-0.29338 -4.04057,-0.88014 -1.19958,-0.58675 -2.2795,-1.73382 -3.23979,-3.4412 l 0,3.84038 -6.56014,0 z"
style="font-family:Blue Highway;-inkscape-font-specification:Blue Highway"
id="path3056" />
<path
d="m 169.59468,403.15851 -6.00105,0 0,-27.60043 -3.59868,0 0,-6.56014 3.59868,0 c -1e-5,-3.83952 0.74667,-6.82621 2.24002,-8.96007 1.49333,-2.13377 3.78706,-3.20067 6.88118,-3.20072 1.01237,5e-5 2.07846,0.0806 3.19828,0.2417 l 0,5.99861 c -1.27933,-0.21318 -2.34583,-0.30636 -3.1995,-0.27954 -0.8537,0.0269 -1.53364,0.25354 -2.03982,0.67994 -0.5062,0.42647 -0.86591,1.07996 -1.07911,1.96047 -0.21323,0.88058 -0.31984,2.06712 -0.31983,3.55961 l 6.71883,0 0,6.56014 -6.399,0 z"
style="font-family:Blue Highway;-inkscape-font-specification:Blue Highway"
id="path3058" />
<path
d="m 199.10675,388.91761 c -2e-5,-0.42642 -0.17336,-0.83943 -0.52002,-1.23902 -0.34671,-0.39957 -0.78657,-0.74625 -1.3196,-1.04006 -0.53307,-0.29376 -1.09297,-0.52041 -1.67971,-0.67994 -0.58677,-0.15949 -1.14708,-0.23924 -1.68093,-0.23926 -4.53294,2e-5 -6.7994,1.89295 -6.79939,5.67878 -1e-5,1.59997 0.59977,2.89352 1.79933,3.88066 1.19955,0.98717 2.62616,1.48074 4.27984,1.48074 0.53385,0 1.13403,-0.0802 1.80056,-0.24049 0.66649,-0.16031 1.30656,-0.38696 1.92019,-0.67994 0.61359,-0.29296 1.13362,-0.65307 1.56008,-1.08033 0.42641,-0.42724 0.63963,-0.93384 0.63965,-1.51979 z m 0.0806,11.28188 c -0.53388,0.79916 -1.49418,1.54543 -2.8809,2.23879 -1.38675,0.69337 -3.06645,1.04006 -5.03912,1.04006 -1.49417,0 -2.89433,-0.26653 -4.20049,-0.79957 -1.30617,-0.53305 -2.45283,-1.3196 -3.43998,-2.35965 -0.98716,-1.04005 -1.76069,-2.29332 -2.32059,-3.75981 -0.5599,-1.46648 -0.83985,-3.13317 -0.83985,-5.00006 0,-3.84118 1.10678,-6.77497 3.32035,-8.80138 2.21356,-2.02637 5.10666,-3.03956 8.67931,-3.03958 1.28092,2e-5 2.48129,0.1465 3.60111,0.43945 1.11979,0.293 2.13298,0.94649 3.03959,1.96048 -2e-5,-1.44043 -0.14651,-2.60052 -0.43946,-3.48027 -0.29299,-0.87971 -0.70641,-1.55964 -1.24025,-2.03982 -0.53388,-0.48012 -1.21422,-0.81338 -2.04104,-0.99977 -0.82685,-0.18633 -1.74645,-0.27951 -2.75882,-0.27954 -1.22724,3e-5 -2.28072,0.19982 -3.16044,0.59937 -0.87974,0.39961 -1.66629,0.89319 -2.35964,1.48073 l -2.96147,-5.04156 c 1.06772,-1.17349 2.40155,-2.08007 4.00152,-2.71976 1.59994,-0.63962 3.38625,-0.95945 5.35895,-0.95949 3.68004,4e-5 6.64027,1.10682 8.88072,3.32036 2.2404,2.21359 3.36061,5.24016 3.36064,9.07969 l 0,22.08035 -6.56014,0 z"
style="font-family:Blue Highway;-inkscape-font-specification:Blue Highway"
id="path3060" />
<path
d="m 226.83658,376.19774 c -1.06611,-0.58592 -1.86609,-0.87889 -2.39994,-0.87892 -1.70576,3e-5 -2.93217,0.65311 -3.67924,1.95925 -0.74709,1.30619 -1.12063,2.91957 -1.12062,4.84015 l 0,21.04029 -6.56014,0 0,-34.16057 6.56014,0 0,4.07964 c 0.37272,-1.3867 1.13241,-2.4532 2.27908,-3.1995 1.14665,-0.74623 2.4402,-1.11936 3.88066,-1.1194 1.28093,4e-5 2.37469,0.29301 3.28129,0.87892 z"
style="font-family:Blue Highway;-inkscape-font-specification:Blue Highway"
id="path3062" />
</g>
<rect
style="fill:#105785;fill-opacity:1;stroke:none"
id="rect2995"
width="20.804075"
height="20.804075"
x="240.98857"
y="356.87091" />
<rect
y="356.87091"
x="267.59845"
height="20.804075"
width="20.804075"
id="rect2997"
style="fill:#105785;fill-opacity:1;stroke:none" />
<rect
style="fill:#105785;fill-opacity:1;stroke:none"
id="rect2999"
width="20.804075"
height="20.804075"
x="267.59845"
y="382.02936" />
<rect
y="382.02936"
x="240.98863"
height="20.804075"
width="20.804075"
id="rect3001"
style="fill:#105785;fill-opacity:1;stroke:none" />
<g
style="font-size:80.0009613px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:ParkAvenue BT;-inkscape-font-specification:ParkAvenue BT"
id="text3831">
<path
d="m 106.6453,409.23288 -4.37505,0 0,3.87505 4.04692,0 0,1.1797 -4.04692,0 0,4.961 -1.31251,0 0,-11.20326 5.68756,0 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3011" />
<path
d="m 117.44231,419.24863 -1.45315,0 -1.18751,-3.14067 -4.75006,0 -1.1172,3.14067 -1.46095,0 4.29692,-11.20326 1.3594,0 z m -3.07035,-4.32037 -1.75784,-4.77349 c -0.0573,-0.15624 -0.11459,-0.40625 -0.17187,-0.75001 l -0.0312,0 c -0.0521,0.31772 -0.11199,0.56772 -0.17969,0.75001 l -1.74221,4.77349 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3013" />
<path
d="m 127.1143,419.24863 -1.56252,0 -1.87502,-3.14067 c -0.17189,-0.29166 -0.33856,-0.54036 -0.50001,-0.7461 -0.16147,-0.20573 -0.32683,-0.3737 -0.4961,-0.50391 -0.16928,-0.13021 -0.35157,-0.22526 -0.54688,-0.28516 -0.19532,-0.0599 -0.41538,-0.0898 -0.66017,-0.0899 l -1.07813,0 0,4.76569 -1.31252,0 0,-11.20326 3.34379,0 c 0.48958,1e-5 0.94141,0.0612 1.35549,0.18359 0.41406,0.12241 0.77344,0.30861 1.07813,0.5586 0.30469,0.25002 0.54297,0.56122 0.71486,0.93361 0.17186,0.37241 0.2578,0.80861 0.25781,1.30861 -10e-6,0.39064 -0.0586,0.74871 -0.17578,1.07423 -0.1172,0.32553 -0.28387,0.6159 -0.50001,0.8711 -0.21615,0.25522 -0.47657,0.47267 -0.78126,0.65236 -0.30469,0.17969 -0.64715,0.31902 -1.02735,0.41797 l 0,0.0312 c 0.18749,0.0833 0.35026,0.17839 0.48828,0.28516 0.13802,0.10678 0.26953,0.23308 0.39454,0.37891 0.12499,0.14584 0.24869,0.31121 0.3711,0.4961 0.12239,0.1849 0.25911,0.39975 0.41016,0.64454 z m -6.71883,-10.01575 0,4.06255 1.78127,0 c 0.32812,10e-6 0.63151,-0.0495 0.91016,-0.14844 0.27865,-0.099 0.51954,-0.24088 0.72267,-0.42578 0.20312,-0.1849 0.36198,-0.41146 0.47657,-0.6797 0.11458,-0.26823 0.17187,-0.56901 0.17188,-0.90235 -1e-5,-0.59896 -0.19402,-1.06641 -0.58204,-1.40237 -0.38803,-0.33593 -0.94924,-0.5039 -1.68362,-0.50391 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3015" />
<path
d="m 135.31752,416.06109 c -0.54167,0 -1.00783,-0.1901 -1.39845,-0.57032 -0.39063,-0.38021 -0.58595,-0.84115 -0.58595,-1.38283 0,-0.53646 0.19532,-1.00131 0.58595,-1.39455 0.39062,-0.39322 0.85678,-0.58984 1.39845,-0.58985 0.54167,1e-5 1.00261,0.19532 1.38283,0.58595 0.38021,0.39063 0.57031,0.85678 0.57032,1.39845 -1e-5,0.54168 -0.19011,1.00262 -0.57032,1.38283 -0.38022,0.38022 -0.84116,0.57032 -1.38283,0.57032 z"
style="letter-spacing:0.50000596px"
id="path3017" />
<path
d="m 145.39577,419.24863 0,-11.20326 3.09378,0 c 3.94796,1e-5 5.92194,1.82034 5.92195,5.461 -1e-5,1.72919 -0.5482,3.11853 -1.64455,4.16802 -1.09638,1.04949 -2.56384,1.57424 -4.4024,1.57424 z m 1.31251,-10.01575 0,8.82823 1.6719,0 c 1.46876,0 2.612,-0.39323 3.42972,-1.1797 0.81771,-0.78646 1.22657,-1.90106 1.22658,-3.34379 -1e-5,-2.86982 -1.52607,-4.30473 -4.57818,-4.30474 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3019" />
<path
d="m 156.61465,419.24863 0,-11.20326 3.18754,0 c 0.96875,1e-5 1.73699,0.23699 2.30471,0.71094 0.56771,0.47398 0.85157,1.09117 0.85157,1.85159 0,0.63543 -0.17188,1.18752 -0.51563,1.65627 -0.34376,0.46876 -0.81772,0.8021 -1.42189,1.00001 l 0,0.0312 c 0.75521,0.0885 1.35939,0.37371 1.81252,0.85548 0.45313,0.48178 0.67969,1.10809 0.6797,1.87893 -1e-5,0.95835 -0.34376,1.7344 -1.03126,2.32815 -0.68752,0.59376 -1.55472,0.89064 -2.6016,0.89064 z m 1.31251,-10.01575 0,3.61723 1.34377,0 c 0.71875,1e-5 1.28386,-0.17317 1.69533,-0.51953 0.41146,-0.34636 0.61719,-0.83464 0.6172,-1.46487 -1e-5,-1.08854 -0.71616,-1.63282 -2.14846,-1.63283 z m 0,4.79693 0,4.0313 1.78128,0 c 0.77083,0 1.3685,-0.18229 1.79299,-0.54688 0.42447,-0.36458 0.63672,-0.86459 0.63672,-1.50002 0,-1.32292 -0.90106,-1.98439 -2.70315,-1.9844 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3021" />
<path
d="m 167.11477,415.0142 0,4.23443 -1.31251,0 0,-11.20326 3.07816,0 c 1.19792,1e-5 2.12632,0.29168 2.78519,0.87501 0.65885,0.58335 0.98828,1.40627 0.98829,2.46878 -1e-5,1.06252 -0.3659,1.93232 -1.09767,2.6094 -0.73179,0.6771 -1.72008,1.01565 -2.96488,1.01564 z m 0,-5.78132 0,4.59381 1.37502,0 c 0.90625,0 1.59767,-0.20703 2.07424,-0.6211 0.47656,-0.41407 0.71485,-0.99871 0.71485,-1.75393 0,-1.47918 -0.87501,-2.21877 -2.62503,-2.21878 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3023" />
<path
d="m 180.45868,409.23288 -4.37505,0 0,3.87505 4.04692,0 0,1.1797 -4.04692,0 0,4.961 -1.31252,0 0,-11.20326 5.68757,0 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3025" />
<path
d="m 189.25566,416.06109 c -0.54167,0 -1.00782,-0.1901 -1.39845,-0.57032 -0.39063,-0.38021 -0.58595,-0.84115 -0.58595,-1.38283 0,-0.53646 0.19532,-1.00131 0.58595,-1.39455 0.39063,-0.39322 0.85678,-0.58984 1.39845,-0.58985 0.54167,1e-5 1.00261,0.19532 1.38283,0.58595 0.38021,0.39063 0.57031,0.85678 0.57032,1.39845 -1e-5,0.54168 -0.19011,1.00262 -0.57032,1.38283 -0.38022,0.38022 -0.84116,0.57032 -1.38283,0.57032 z"
style="letter-spacing:0.50000596px"
id="path3027" />
<path
d="m 200.64643,415.0142 0,4.23443 -1.31252,0 0,-11.20326 3.07816,0 c 1.19793,1e-5 2.12632,0.29168 2.78519,0.87501 0.65886,0.58335 0.98829,1.40627 0.98829,2.46878 0,1.06252 -0.36589,1.93232 -1.09766,2.6094 -0.73179,0.6771 -1.72008,1.01565 -2.96488,1.01564 z m 0,-5.78132 0,4.59381 1.37501,0 c 0.90626,0 1.59767,-0.20703 2.07425,-0.6211 0.47656,-0.41407 0.71484,-0.99871 0.71485,-1.75393 -1e-5,-1.47918 -0.87502,-2.21877 -2.62503,-2.21878 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3029" />
<path
d="m 214.56065,415.5689 -5.6485,0 c 0.0208,0.89063 0.26042,1.57814 0.71876,2.06252 0.45833,0.48438 1.08855,0.72657 1.89065,0.72657 0.90104,0 1.72918,-0.29688 2.4844,-0.89063 l 0,1.20313 c -0.70314,0.51043 -1.63284,0.76564 -2.7891,0.76564 -1.13022,0 -2.01825,-0.36329 -2.66409,-1.08986 -0.64584,-0.72657 -0.96876,-1.74871 -0.96876,-3.06644 0,-1.2448 0.35287,-2.25914 1.0586,-3.04301 0.70574,-0.78385 1.58205,-1.17578 2.62894,-1.17579 1.04688,10e-6 1.85679,0.33855 2.42972,1.01564 0.57292,0.67709 0.85938,1.61721 0.85938,2.82034 z m -1.31251,-1.08596 c -0.005,-0.73958 -0.1836,-1.31511 -0.53516,-1.72658 -0.35158,-0.41145 -0.83986,-0.61719 -1.46487,-0.61719 -0.60417,0 -1.1172,0.21615 -1.53908,0.64844 -0.42188,0.43231 -0.6823,0.99742 -0.78126,1.69533 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3031" />
<path
d="m 220.67791,412.54542 c -0.22396,-0.17187 -0.54688,-0.25781 -0.96876,-0.25781 -0.54688,0 -1.00392,0.25782 -1.37111,0.77344 -0.36719,0.51564 -0.55079,1.21877 -0.55079,2.1094 l 0,4.07818 -1.28126,0 0,-8.0001 1.28126,0 0,1.64846 0.0312,0 c 0.1823,-0.5625 0.46094,-1.00131 0.83595,-1.31642 0.375,-0.3151 0.79428,-0.47266 1.25783,-0.47267 0.33333,1e-5 0.58854,0.0365 0.76563,0.10938 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3033" />
<path
d="m 221.58417,418.95956 0,-1.37502 c 0.69792,0.51564 1.46616,0.77345 2.30471,0.77345 1.12501,0 1.68752,-0.375 1.68752,-1.12501 0,-0.21354 -0.0482,-0.39454 -0.14453,-0.54298 -0.0964,-0.14843 -0.22657,-0.27995 -0.39063,-0.39453 -0.16407,-0.11459 -0.35678,-0.21745 -0.57813,-0.3086 -0.22136,-0.0911 -0.45964,-0.1862 -0.71485,-0.28516 -0.35418,-0.14062 -0.66538,-0.28255 -0.93361,-0.42579 -0.26823,-0.14322 -0.49219,-0.30468 -0.67188,-0.48438 -0.17969,-0.17968 -0.31511,-0.38411 -0.40625,-0.61329 -0.0911,-0.22916 -0.13673,-0.49739 -0.13673,-0.80469 0,-0.375 0.0859,-0.70704 0.25782,-0.99611 0.17188,-0.28906 0.40105,-0.53125 0.68751,-0.72657 0.28646,-0.19531 0.61328,-0.34244 0.98048,-0.44141 0.36719,-0.099 0.7461,-0.14843 1.13673,-0.14844 0.69271,10e-6 1.31251,0.1198 1.8594,0.35938 l 0,1.29689 c -0.58856,-0.38542 -1.26565,-0.57813 -2.03128,-0.57813 -0.23959,0 -0.45573,0.0274 -0.64844,0.082 -0.19271,0.0547 -0.35808,0.13152 -0.4961,0.23047 -0.13803,0.099 -0.2448,0.21746 -0.32032,0.35547 -0.0755,0.13803 -0.11328,0.29038 -0.11328,0.45704 0,0.20834 0.0378,0.38282 0.11328,0.52344 0.0755,0.14064 0.1862,0.26564 0.33204,0.37501 0.14583,0.10938 0.32292,0.20834 0.53125,0.29688 0.20834,0.0885 0.44532,0.1849 0.71095,0.28906 0.35417,0.13543 0.67188,0.27475 0.95314,0.41798 0.28125,0.14323 0.52083,0.30469 0.71876,0.48438 0.19791,0.17969 0.35025,0.38672 0.45703,0.6211 0.10677,0.23438 0.16015,0.51303 0.16016,0.83595 -1e-5,0.39584 -0.0873,0.73959 -0.26172,1.03126 -0.17449,0.29167 -0.40756,0.53386 -0.69923,0.72657 -0.29167,0.19271 -0.62761,0.33594 -1.00782,0.42969 -0.38022,0.0937 -0.77866,0.14063 -1.19533,0.14063 -0.82293,0 -1.53648,-0.15886 -2.14065,-0.47657 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3035" />
<path
d="m 229.4202,409.21726 c -0.22917,10e-6 -0.42448,-0.0781 -0.58594,-0.23438 -0.16146,-0.15624 -0.24219,-0.35416 -0.24219,-0.59376 0,-0.23957 0.0807,-0.43879 0.24219,-0.59766 0.16146,-0.15885 0.35677,-0.23827 0.58594,-0.23829 0.23438,2e-5 0.4336,0.0794 0.59767,0.23829 0.16406,0.15887 0.24609,0.35809 0.24609,0.59766 0,0.22918 -0.082,0.4245 -0.24609,0.58595 -0.16407,0.16147 -0.36329,0.2422 -0.59767,0.24219 z m 0.62501,7.79697 c 0,0.73438 0.28386,1.10157 0.85157,1.10157 0.22917,0 0.4349,-0.0286 0.6172,-0.0859 l 0,1.15627 c -0.099,0.026 -0.23048,0.0508 -0.39454,0.0742 -0.16407,0.0234 -0.33724,0.0351 -0.51953,0.0351 -0.25522,0 -0.49481,-0.0417 -0.71876,-0.125 -0.22397,-0.0833 -0.41798,-0.21094 -0.58204,-0.38282 -0.16407,-0.17187 -0.29428,-0.38672 -0.39063,-0.64454 -0.0964,-0.25781 -0.14454,-0.55859 -0.14453,-0.90235 l 0,-5.99226 1.28126,0 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3037" />
<path
d="m 232.42805,418.95956 0,-1.37502 c 0.69792,0.51564 1.46616,0.77345 2.30471,0.77345 1.12501,0 1.68752,-0.375 1.68752,-1.12501 0,-0.21354 -0.0482,-0.39454 -0.14453,-0.54298 -0.0964,-0.14843 -0.22657,-0.27995 -0.39063,-0.39453 -0.16407,-0.11459 -0.35678,-0.21745 -0.57813,-0.3086 -0.22136,-0.0911 -0.45964,-0.1862 -0.71485,-0.28516 -0.35418,-0.14062 -0.66538,-0.28255 -0.93361,-0.42579 -0.26823,-0.14322 -0.49219,-0.30468 -0.67188,-0.48438 -0.17969,-0.17968 -0.31511,-0.38411 -0.40626,-0.61329 -0.0911,-0.22916 -0.13672,-0.49739 -0.13672,-0.80469 0,-0.375 0.0859,-0.70704 0.25782,-0.99611 0.17188,-0.28906 0.40104,-0.53125 0.68751,-0.72657 0.28646,-0.19531 0.61328,-0.34244 0.98048,-0.44141 0.36719,-0.099 0.7461,-0.14843 1.13673,-0.14844 0.69271,10e-6 1.31251,0.1198 1.8594,0.35938 l 0,1.29689 c -0.58856,-0.38542 -1.26565,-0.57813 -2.03128,-0.57813 -0.23959,0 -0.45573,0.0274 -0.64844,0.082 -0.19271,0.0547 -0.35808,0.13152 -0.4961,0.23047 -0.13803,0.099 -0.2448,0.21746 -0.32032,0.35547 -0.0755,0.13803 -0.11328,0.29038 -0.11328,0.45704 0,0.20834 0.0378,0.38282 0.11328,0.52344 0.0755,0.14064 0.1862,0.26564 0.33204,0.37501 0.14583,0.10938 0.32292,0.20834 0.53125,0.29688 0.20834,0.0885 0.44532,0.1849 0.71095,0.28906 0.35417,0.13543 0.67188,0.27475 0.95314,0.41798 0.28124,0.14323 0.52083,0.30469 0.71876,0.48438 0.19791,0.17969 0.35025,0.38672 0.45703,0.6211 0.10677,0.23438 0.16015,0.51303 0.16016,0.83595 -1e-5,0.39584 -0.0873,0.73959 -0.26172,1.03126 -0.17449,0.29167 -0.40756,0.53386 -0.69923,0.72657 -0.29167,0.19271 -0.62762,0.33594 -1.00782,0.42969 -0.38022,0.0937 -0.77866,0.14063 -1.19533,0.14063 -0.82293,0 -1.53648,-0.15886 -2.14065,-0.47657 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3039" />
<path
d="m 243.40474,419.1705 c -0.30209,0.16667 -0.70054,0.25 -1.19533,0.25 -1.40106,0 -2.10159,-0.78125 -2.10159,-2.34377 l 0,-4.73444 -1.37501,0 0,-1.09376 1.37501,0 0,-1.95315 1.28127,-0.41406 0,2.36721 2.01565,0 0,1.09376 -2.01565,0 0,4.50787 c 0,0.53647 0.0911,0.91928 0.27344,1.14845 0.18229,0.22917 0.48438,0.34376 0.90626,0.34376 0.32292,0 0.60157,-0.0885 0.83595,-0.26563 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3041" />
<path
d="m 251.97517,416.06109 c -0.54168,0 -1.00783,-0.1901 -1.39846,-0.57032 -0.39063,-0.38021 -0.58594,-0.84115 -0.58594,-1.38283 0,-0.53646 0.19531,-1.00131 0.58594,-1.39455 0.39063,-0.39322 0.85678,-0.58984 1.39846,-0.58985 0.54167,1e-5 1.00261,0.19532 1.38283,0.58595 0.3802,0.39063 0.57031,0.85678 0.57032,1.39845 -1e-5,0.54168 -0.19012,1.00262 -0.57032,1.38283 -0.38022,0.38022 -0.84116,0.57032 -1.38283,0.57032 z"
style="letter-spacing:0.50000596px"
id="path3043" />
<path
d="m 266.49096,419.43613 c -0.33334,0 -0.67189,-0.0326 -1.01564,-0.0977 -0.34375,-0.0651 -0.67709,-0.16406 -1.00001,-0.29688 -0.32292,-0.13281 -0.63152,-0.29688 -0.92579,-0.49219 -0.29428,-0.19531 -0.56121,-0.42318 -0.80079,-0.6836 -0.95314,-1.04168 -1.42971,-2.40367 -1.42971,-4.08599 0,-1.8073 0.48438,-3.24482 1.45315,-4.31255 0.97917,-1.07292 2.31773,-1.60938 4.01567,-1.60939 1.52084,1e-5 2.75523,0.52085 3.70317,1.56251 0.94792,1.04169 1.42188,2.40369 1.42189,4.08599 -10e-6,0.70835 -0.0794,1.37632 -0.23828,2.00393 -0.15887,0.62762 -0.39976,1.19403 -0.72267,1.69924 -0.32293,0.50522 -0.72918,0.93361 -1.21876,1.28517 -0.4896,0.35157 -1.06773,0.60287 -1.7344,0.75392 0.27083,0.29167 0.52474,0.54948 0.76173,0.77344 0.23697,0.22396 0.47395,0.41277 0.71095,0.56642 0.23697,0.15364 0.48306,0.26953 0.73829,0.34766 0.2552,0.0781 0.53645,0.11718 0.84376,0.11719 0.0833,-10e-6 0.17447,-0.004 0.27344,-0.0117 0.0989,-0.008 0.19921,-0.0208 0.30078,-0.0391 0.10155,-0.0182 0.19921,-0.0391 0.29297,-0.0625 0.0937,-0.0234 0.17968,-0.0508 0.25782,-0.082 l 0,1.26564 c -0.0833,0.026 -0.1771,0.0482 -0.28125,0.0664 -0.10418,0.0182 -0.20965,0.0339 -0.31641,0.0469 -0.10679,0.013 -0.21226,0.0234 -0.31641,0.0312 -0.10418,0.008 -0.20054,0.0117 -0.28907,0.0117 -0.50002,0 -0.94924,-0.0742 -1.34767,-0.22266 -0.39845,-0.14844 -0.77085,-0.35157 -1.1172,-0.60938 -0.34637,-0.25782 -0.68101,-0.5586 -1.00392,-0.90235 -0.32293,-0.34376 -0.66147,-0.71355 -1.01564,-1.10939 z m 0.17188,-10.39075 c -1.1771,10e-6 -2.13284,0.42449 -2.86722,1.27345 -0.73439,0.84898 -1.10158,1.96357 -1.10158,3.34379 0,1.37502 0.35677,2.48701 1.07033,3.33598 0.71875,0.83855 1.65366,1.25783 2.80472,1.25783 1.22917,0 2.19793,-0.40105 2.90628,-1.20314 0.70833,-0.80209 1.0625,-1.9245 1.06251,-3.36723 -10e-6,-1.48439 -0.34376,-2.62763 -1.03126,-3.42973 -0.68751,-0.80729 -1.63544,-1.21094 -2.84378,-1.21095 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3045" />
<path
d="m 279.80361,409.23288 -4.37505,0 0,3.87505 4.04692,0 0,1.1797 -4.04692,0 0,4.961 -1.31251,0 0,-11.20326 5.68756,0 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3047" />
<path
d="m 281.40519,418.7955 0,-1.5469 c 0.17709,0.15626 0.38933,0.29688 0.63673,0.42188 0.2474,0.12501 0.50782,0.23048 0.78126,0.31641 0.27344,0.0859 0.54818,0.15235 0.82423,0.19922 0.27604,0.0469 0.53125,0.0703 0.76563,0.0703 0.8073,0 1.41017,-0.14974 1.80862,-0.44923 0.39843,-0.29948 0.59765,-0.73047 0.59766,-1.29298 -1e-5,-0.30208 -0.0664,-0.56511 -0.19922,-0.78907 -0.13282,-0.22396 -0.31642,-0.42839 -0.55079,-0.61329 -0.23438,-0.1849 -0.51173,-0.36198 -0.83204,-0.53126 -0.32032,-0.16927 -0.66538,-0.34765 -1.03517,-0.53516 -0.39063,-0.19791 -0.75522,-0.39844 -1.09376,-0.60157 -0.33855,-0.20312 -0.63282,-0.42708 -0.88282,-0.67188 -0.25001,-0.24479 -0.44663,-0.52214 -0.58986,-0.83204 -0.14323,-0.3099 -0.21484,-0.67318 -0.21484,-1.08986 0,-0.51041 0.11198,-0.95443 0.33594,-1.33205 0.22396,-0.3776 0.51823,-0.6888 0.88282,-0.9336 0.36459,-0.24479 0.77996,-0.42708 1.24611,-0.54688 0.46615,-0.11979 0.94141,-0.17968 1.4258,-0.17969 1.10417,1e-5 1.90887,0.13282 2.41409,0.39844 l 0,1.47658 c -0.66147,-0.45833 -1.51044,-0.6875 -2.5469,-0.68751 -0.28647,10e-6 -0.57293,0.03 -0.85939,0.0898 -0.28646,0.0599 -0.54168,0.15757 -0.76563,0.29298 -0.22397,0.13543 -0.40626,0.30991 -0.54689,0.52344 -0.14062,0.21355 -0.21094,0.47397 -0.21094,0.78126 0,0.28647 0.0534,0.53387 0.16016,0.7422 0.10677,0.20834 0.26433,0.39845 0.47266,0.57032 0.20834,0.17188 0.46225,0.33855 0.76173,0.5 0.29948,0.16147 0.64454,0.33855 1.03517,0.53126 0.40104,0.19792 0.78125,0.40626 1.14064,0.62501 0.35937,0.21875 0.67448,0.46094 0.94532,0.72657 0.27083,0.26563 0.48568,0.5599 0.64454,0.88282 0.15885,0.32292 0.23828,0.69272 0.23829,1.10939 -1e-5,0.55209 -0.10809,1.01954 -0.32423,1.40236 -0.21615,0.38282 -0.50782,0.69402 -0.87501,0.9336 -0.36719,0.23959 -0.79038,0.41277 -1.26954,0.51954 -0.47918,0.10677 -0.98439,0.16016 -1.51565,0.16016 -0.17708,0 -0.39584,-0.0143 -0.65625,-0.043 -0.26043,-0.0287 -0.52605,-0.0703 -0.79689,-0.125 -0.27084,-0.0547 -0.52735,-0.1224 -0.76954,-0.20313 -0.24219,-0.0807 -0.4362,-0.17057 -0.58204,-0.26953 z"
style="font-size:16.00019073px;font-family:Gisha;-inkscape-font-specification:Gisha"
id="path3049" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -0,0 +1,163 @@
/*
FileHandler - General-purpose file handling library for Niotso
refpack_dec.c - Copyright (c) 2011 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 <string.h>
#include <stdint.h>
int RefPackDecompress(const uint8_t *__restrict CompressedData, size_t CompressedSize,
uint8_t *__restrict DecompressedData, size_t DecompressedSize, unsigned HNSV){
unsigned datawritten = 0;
int stopflag = 0, StopFlagData;
if(HNSV == 0) HNSV = 0xFB; /* EA default */
if (HNSV >= 0xFF) StopFlagData = 0x1F;
else if(HNSV >= 0xFE) StopFlagData = 0x00;
else if(HNSV >= 0xFD) StopFlagData = 0x01;
else if(HNSV >= 0xFB) StopFlagData = 0x03;
else if(HNSV >= 0xF7) StopFlagData = 0x07;
else StopFlagData = 0x0F;
while(CompressedSize > 0 && !stopflag){
unsigned ProceedingDataLength, ReferencedDataLength, ReferencedDataOffset;
unsigned currentbyte = *(CompressedData++);
CompressedSize--;
/****
** Fetch the opcode
*/
/* The first byte determines the size of the entire opcode. */
if(currentbyte <= 0x7F){ /* 2 bytes */
if(CompressedSize < 1) return 0;
CompressedSize -= 1;
/* First byte */
ProceedingDataLength = currentbyte & 0x03;
ReferencedDataLength = ((currentbyte & 0x1C) >> 2) + 3;
ReferencedDataOffset = (currentbyte & 0x60) << 3;
/* Second byte */
currentbyte = *(CompressedData++);
ReferencedDataOffset += currentbyte;
}else if(currentbyte <= 0xBF){ /* 3 bytes */
if(CompressedSize < 2) return 0;
CompressedSize -= 2;
/* First byte */
ReferencedDataLength = (currentbyte & 0x3F) + 4;
/* Second byte */
currentbyte = *(CompressedData++);
ProceedingDataLength = (currentbyte & 0xC0) >> 6;
ReferencedDataOffset = (currentbyte & 0x3F) << 8;
/* Third byte */
currentbyte = *(CompressedData++);
ReferencedDataOffset += currentbyte;
}else if(currentbyte <= 0xDF){ /* 4 bytes */
if(CompressedSize < 3) return 0;
CompressedSize -= 3;
/* First byte */
ProceedingDataLength = currentbyte & 0x03;
ReferencedDataLength = ((currentbyte & 0x0C) << 6) + 5;
ReferencedDataOffset = (currentbyte & 0x10) << 12;
/* Second byte */
currentbyte = *(CompressedData++);
ReferencedDataOffset += currentbyte << 8;
/* Third byte */
currentbyte = *(CompressedData++);
ReferencedDataOffset += currentbyte;
/* Fourth byte */
currentbyte = *(CompressedData++);
ReferencedDataLength += currentbyte;
}else{ /* 1 byte: Two different opcode types fall into this category */
if(currentbyte <= HNSV){
ProceedingDataLength = ((currentbyte & 0x1F) + 1) << 2;
}else{
ProceedingDataLength = currentbyte & StopFlagData;
stopflag++;
}
ReferencedDataLength = 0;
}
/****
** Copy proceeding data
*/
if(ProceedingDataLength != 0){
if(ProceedingDataLength > CompressedSize || ProceedingDataLength > DecompressedSize)
return 0;
memcpy(DecompressedData, CompressedData, ProceedingDataLength);
DecompressedSize -= ProceedingDataLength;
CompressedSize -= ProceedingDataLength;
datawritten += ProceedingDataLength;
DecompressedData += ProceedingDataLength;
CompressedData += ProceedingDataLength;
}
/****
** Copy referenced data
*/
if(ReferencedDataLength != 0){
/* It is possible that the offset specified does not provide for a large enough buffer to copy all at once from.
This event would be caused when the referenced data offset is set smaller than the referenced data length.
When this occurs, the decoder is to repeatedly copy/paste the referenced data until the length is satisfied.
We will do this in a way so that we call memcpy ceil(log2(N)) times instead of N times. */
ReferencedDataOffset++;
if(ReferencedDataLength > DecompressedSize || ReferencedDataOffset > datawritten)
return 0;
DecompressedSize -= ReferencedDataLength;
datawritten += ReferencedDataLength;
if(ReferencedDataOffset == 1){
memset(DecompressedData, *(DecompressedData-1), ReferencedDataLength);
DecompressedData += ReferencedDataLength;
}else{
unsigned copylength =
(ReferencedDataOffset < ReferencedDataLength) ? ReferencedDataOffset : ReferencedDataLength;
uint8_t *__restrict copysource = DecompressedData;
memcpy(DecompressedData, DecompressedData-ReferencedDataOffset, copylength);
DecompressedData += copylength;
ReferencedDataLength -= copylength;
while(ReferencedDataLength){
if(copylength > ReferencedDataLength)
copylength = ReferencedDataLength;
memcpy(DecompressedData, copysource, copylength);
DecompressedData += copylength;
ReferencedDataLength -= copylength;
if(!(copylength&0x80000000)) copylength <<= 1;
}
}
}
}
return (stopflag && !CompressedSize && !DecompressedSize);
}

17
library/formats/hit/evt.c Normal file
View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
evt.c - 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.
*/

17
library/formats/hit/hit.c Normal file
View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
hit.c - 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.
*/

17
library/formats/hit/hot.c Normal file
View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
hot.c - 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.
*/

17
library/formats/hit/hsm.c Normal file
View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
hsm.c - 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.
*/

View file

@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 2.6)
project(iff)
set(IFF_SOURCES
bhav.c
cats.c
iff.c
bcon.c
dgrp.c
fcns.c
glob.c
objf.c
palt.c
rsmp.c
spr.c
spr2.c
str.c
string.c
tmpl.c
trcn.c
)
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(iff_shared PROPERTIES
# OUTPUT_NAME "iff"
# PREFIX ""
# CLEAN_DIRECT_OUTPUT 1)
add_executable(iffexport iffexport.c)
target_link_libraries(iffexport iff_static)

View file

@ -0,0 +1,53 @@
/*
FileHandler - General-purpose file handling library for Niotso
bcon.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
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 "iffparser.h"
int iff_parse_bcon(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFF_BCON *BCONData;
unsigned i;
if(ChunkInfo->Size < 2)
return 0;
ChunkInfo->FormattedData = calloc(1, sizeof(IFF_BCON));
if(ChunkInfo->FormattedData == NULL)
return 0;
BCONData = ChunkInfo->FormattedData;
BCONData->ConstantCount = read_uint8le(Buffer);
BCONData->Flags = read_uint8le(Buffer + 1);
if(BCONData->ConstantCount == 0)
return 1;
if(BCONData->ConstantCount * 2 /* bytes */ > ChunkInfo->Size - 2)
return 0;
BCONData->Constants = malloc(BCONData->ConstantCount * sizeof(uint16_t));
if(BCONData->Constants == NULL)
return 0;
Buffer += 2;
for(i=0; i<BCONData->ConstantCount; i++, Buffer += 2)
BCONData->Constants[i] = read_uint16le(Buffer);
return 1;
}
void iff_free_bcon(void * FormattedData){
IFF_BCON *BCONData = FormattedData;
free(BCONData->Constants);
}

View file

@ -0,0 +1,91 @@
/*
FileHandler - General-purpose file handling library for Niotso
bhav.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
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 "iffparser.h"
#define HEADER_SIZE (12 + (Behavior->Version == 0x8003))
int iff_parse_bhav(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFBehavior *Behavior;
unsigned i;
if(ChunkInfo->Size < 12)
return 0;
ChunkInfo->FormattedData = calloc(1, sizeof(IFFBehavior));
if(ChunkInfo->FormattedData == NULL)
return 0;
Behavior = ChunkInfo->FormattedData;
Behavior->Version = read_uint16le(Buffer);
if(Behavior->Version < 0x8000 || Behavior->Version > 0x8003 || (Behavior->Version == 0x8003 && ChunkInfo->Size < 13))
return 0;
switch(Behavior->Version){
case 0x8000: {
Behavior->InstructionCount = read_uint16le(Buffer+2);
} break;
case 0x8001: {
Behavior->InstructionCount = read_uint16le(Buffer+2);
} break;
case 0x8002: {
Behavior->InstructionCount = read_uint16le(Buffer+2);
Behavior->Type = read_uint8le(Buffer+4);
Behavior->ArgumentCount = read_uint8le(Buffer+5);
Behavior->LocalCount = read_uint16le(Buffer+6);
Behavior->Flags = read_uint16le(Buffer+8);
} break;
default: {
Behavior->Type = read_uint8le(Buffer+2);
Behavior->ArgumentCount = read_uint8le(Buffer+3);
Behavior->LocalCount = read_uint8le(Buffer+4);
Behavior->Flags = read_uint16le(Buffer+7);
Behavior->InstructionCount = read_uint32le(Buffer+9);
} break;
}
if(Behavior->InstructionCount == 0)
return 1;
if(Behavior->InstructionCount > 255 || Behavior->InstructionCount*12 > ChunkInfo->Size - HEADER_SIZE)
return 0;
Behavior->Instructions = calloc(Behavior->InstructionCount, sizeof(IFFInstruction));
if(Behavior->Instructions == NULL)
return 0;
Buffer += HEADER_SIZE;
for(i=0; i<Behavior->InstructionCount; i++){
Behavior->Instructions[i].Opcode = read_uint16le(Buffer);
Behavior->Instructions[i].TDest = read_uint8le(Buffer+2);
Behavior->Instructions[i].FDest = read_uint8le(Buffer+3);
memcpy(Behavior->Instructions[i].Operands, Buffer+4, 8);
Buffer += 12;
}
return 1;
}
void iff_free_bhav(void * FormattedData){
IFFBehavior *Behavior = FormattedData;
free(Behavior->Instructions);
}

View file

@ -0,0 +1,38 @@
/*
FileHandler - General-purpose file handling library for Niotso
cats.c - 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 "iffparser.h"
int iff_parse_cats(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFStringPair * StringData;
bytestream b;
set_bytestream(&b, Buffer, ChunkInfo->Size);
ChunkInfo->FormattedData = calloc(1, sizeof(IFFStringPair));
if(ChunkInfo->FormattedData == NULL)
return 0;
StringData = ChunkInfo->FormattedData;
return (read_c_string(&b, &StringData->Key) && read_c_string(&b, &StringData->Value));
}
void iff_free_cats(void * FormattedData){
IFFStringPair * StringData = FormattedData;
free(StringData->Key);
free(StringData->Value);
}

108
library/formats/iff/dgrp.c Normal file
View file

@ -0,0 +1,108 @@
/*
FileHandler - General-purpose file handling library for Niotso
dgrp.c - 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 "iffparser.h"
#define read_split(x, y, z) \
(largefields ? read_uint##z(x) : read_uint##y(x))
int iff_parse_dgrp(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFDrawGroup *Group;
bytestream b;
int largefields;
unsigned i;
if(ChunkInfo->Size < 52)
return 0;
set_bytestream(&b, Buffer, ChunkInfo->Size);
ChunkInfo->FormattedData = calloc(1, sizeof(IFFDrawGroup));
if(ChunkInfo->FormattedData == NULL)
return 0;
Group = ChunkInfo->FormattedData;
Group->Version = read_uint16(&b);
if(Group->Version < 20000 || Group->Version > 20004 || Group->Version == 20002)
return 0;
largefields = (Group->Version >= 20003);
Group->AngleCount = read_split(&b, 16, 32);
if(Group->AngleCount != 12)
return 0;
for(i=0; i<12; i++){
IFFDrawAngle * Angle = &Group->DrawAngles[i];
unsigned j;
if(b.Size < ((!largefields) ? 4 : 12))
return 0;
if(!largefields)
Angle->SpriteCount = read_uint16(&b);
Angle->Direction = read_split(&b, 8, 32);
Angle->Zoom = read_split(&b, 8, 32);
if(largefields)
Angle->SpriteCount = read_uint32(&b);
if((Angle->Direction != 1 && Angle->Direction != 4 && Angle->Direction != 16 && Angle->Direction != 64)
|| (!Angle->Zoom || Angle->Zoom > 3))
return 0;
if(Angle->SpriteCount == 0)
continue;
Angle->SpriteInfo = calloc(Angle->SpriteCount, sizeof(IFFSpriteInfo));
if(Angle->SpriteInfo == NULL)
return 0;
for(j=0; j<Angle->SpriteCount; j++){
IFFSpriteInfo * Sprite = &Angle->SpriteInfo[j];
const uint8_t size[5] = {12, 16, 0, 24, 32};
if(b.Size < size[Group->Version - 20000])
return 0;
if(!largefields)
Sprite->Type = read_uint16(&b);
Sprite->ChunkID = read_split(&b, 16, 32);
Sprite->SpriteIndex = read_split(&b, 16, 32);
if(!largefields)
Sprite->Flags = read_uint16(&b);
Sprite->SpriteX = read_split(&b, 16, 32);
Sprite->SpriteY = read_split(&b, 16, 32);
if(Group->Version >= 20001){
Sprite->ObjectZ = read_float(&b);
if(Group->Version >= 20003){
Sprite->Flags = read_uint32(&b);
if(Group->Version == 20004){
Sprite->ObjectX = read_float(&b);
Sprite->ObjectY = read_float(&b);
}
}
}
}
}
return 1;
}
void iff_free_dgrp(void * FormattedData){
IFFDrawGroup *Group = FormattedData;
int i;
for(i=0; i<12; i++){
IFFDrawAngle *Angle = &Group->DrawAngles[i];
free(Angle->SpriteInfo);
}
}

View file

@ -0,0 +1,86 @@
/*
FileHandler - General-purpose file handling library for Niotso
fcns.c - 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 "iffparser.h"
int iff_parse_fcns(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFConstantList *List;
bytestream b;
unsigned i;
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_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;
List->Constants = calloc(List->ConstantCount, sizeof(IFFConstant));
if(List->Constants == NULL)
return 0;
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;
if(List->Version < 2){
/* 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(b.Size && *b.Buffer == 0xA3)
skipbytes(&b, 1);
}else{
/* Extended Pascal string, no padding */
if(!read_pascal2_string(&b, string))
return 0;
}
if(s == 0){
if(b.Size < 4) return 0;
Constant->Value = read_float(&b);
}
}
}
return 1;
}
void iff_free_fcns(void * FormattedData){
IFFConstantList * List = FormattedData;
if(List->Constants){
unsigned c;
for(c=0; c<List->ConstantCount; c++){
free(List->Constants[c].Name);
free(List->Constants[c].Description);
}
free(List->Constants);
}
}

View file

@ -0,0 +1,28 @@
/*
FileHandler - General-purpose file handling library for Niotso
glob.c - 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 "iffparser.h"
int iff_parse_glob(IFFChunk * ChunkInfo, const uint8_t * Buffer){
bytestream b;
set_bytestream(&b, Buffer, ChunkInfo->Size);
/* 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));
}

251
library/formats/iff/iff.c Normal file
View file

@ -0,0 +1,251 @@
/*
FileHandler - General-purpose file handling library for Niotso
iff.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
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 "iffparser.h"
/****
** Supported Chunks
*/
#define iff_register(x) \
int iff_parse_##x(IFFChunk *, const uint8_t *); \
void iff_free_##x(void *)
iff_register(bcon);
iff_register(dgrp);
iff_register(str);
iff_register(cats);
iff_register(c_string);
iff_register(glob);
iff_register(fcns);
iff_register(palt);
iff_register(bhav);
iff_register(objf);
iff_register(spr);
iff_register(spr2);
iff_register(tmpl);
iff_register(trcn);
iff_register(rsmp);
/* The ordering of these chunk types must match throughout this block: */
const char chunktypes[] =
"STR#" "CTSS" "FAMs" "TTAs" "CST\0"
"CATS"
"FWAV"
"GLOB"
"BCON"
"FCNS"
"PALT"
"SPR#"
"SPR2"
"DGRP"
"TMPL"
"TRCN"
"BHAV"
"OBJf"
"rsmp"
;
int (* const iff_parse_function[])(IFFChunk*, const uint8_t*) = {
iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str, iff_parse_str,
iff_parse_cats,
iff_parse_c_string,
iff_parse_glob,
iff_parse_bcon,
iff_parse_fcns,
iff_parse_palt,
iff_parse_spr,
iff_parse_spr2,
iff_parse_dgrp,
iff_parse_tmpl,
iff_parse_trcn,
iff_parse_bhav,
iff_parse_objf,
iff_parse_rsmp
};
void (* const iff_free_function[])(void*) = {
iff_free_str, iff_free_str, iff_free_str, iff_free_str, iff_free_str,
iff_free_cats,
NULL,
NULL,
iff_free_bcon,
iff_free_fcns,
NULL,
iff_free_spr,
iff_free_spr,
iff_free_dgrp,
iff_free_tmpl,
iff_free_trcn,
iff_free_bhav,
iff_free_objf,
iff_free_rsmp
};
/* End */
/****
** API public functions
*/
int iff_create(IFFFile * IFFFileInfo)
{
memset(IFFFileInfo, 0, sizeof(IFFFile));
IFFFileInfo->Chunks = calloc(1, sizeof(IFFChunk));
if(IFFFileInfo->Chunks == NULL)
return 0;
IFFFileInfo->SizeAllocated = sizeof(IFFChunk);
return 1;
}
int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize)
{
unsigned offset;
if(!FileSize) FileSize = ~0;
else if(FileSize < 64)
return 0;
if(memcmp(Buffer, Header_IFF, 60))
return 0;
memcpy(IFFFileInfo->Header, Buffer, 60);
offset = read_uint32be(Buffer+60);
if(offset > FileSize - 28)
return 0;
return 1;
}
IFFChunk * iff_add_chunk(IFFFile * IFFFileInfo)
{
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;
}
return &IFFFileInfo->Chunks[IFFFileInfo->ChunkCount++];
}
int iff_read_chunk(IFFChunk * ChunkInfo, const uint8_t * Buffer, unsigned MaxChunkSize)
{
if(MaxChunkSize == 0) MaxChunkSize = ~0;
if(MaxChunkSize < 76)
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);
memcpy(ChunkInfo->Label, Buffer+12, 64);
if(ChunkInfo->Size < 76 || ChunkInfo->Size > MaxChunkSize)
return 0;
ChunkInfo->Size -= 76;
if(ChunkInfo->Size){
ChunkInfo->Data = malloc(ChunkInfo->Size);
if(ChunkInfo->Data == NULL)
return 0;
memcpy(ChunkInfo->Data, Buffer+76, ChunkInfo->Size);
}
ChunkInfo->FormattedData = NULL;
return 1;
}
int iff_enumerate_chunks(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned BufferSize)
{
while(BufferSize){
IFFChunk * chunk = iff_add_chunk(IFFFileInfo);
if(chunk == NULL)
return 0;
if(!iff_read_chunk(chunk, Buffer, BufferSize))
return 0;
Buffer += chunk->Size + 76;
BufferSize -= chunk->Size + 76;
}
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);
return 0;
}
}
return 0;
}
IFFChunk * iff_find_chunk(IFFFile * IFFFileInfo, const char * Type, int ChunkID){
unsigned i;
for(i=0; i<IFFFileInfo->ChunkCount; i++){
IFFChunk * Chunk = &IFFFileInfo->Chunks[i];
if((Type == NULL || !strcmp(Chunk->Type, Type)) &&
(ChunkID == -1 || Chunk->ChunkID == ChunkID))
return Chunk;
}
return NULL;
}
void iff_free_chunk(IFFChunk * ChunkInfo){
unsigned i;
if(ChunkInfo == NULL || ChunkInfo->FormattedData == NULL) 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);
ChunkInfo->FormattedData = NULL;
return;
}
}
}
void iff_delete(IFFFile * IFFFileInfo){
unsigned i;
if(IFFFileInfo == NULL) return;
if(IFFFileInfo->Chunks != NULL){
for(i=0; i<IFFFileInfo->ChunkCount; 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);
}
}

365
library/formats/iff/iff.h Normal file
View file

@ -0,0 +1,365 @@
/*
FileHandler - General-purpose file handling library for Niotso
iff.h - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
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.
*/
#ifndef IFF_H
#define IFF_H
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#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)))
#define read_int16be(x) (signed)(((x)[0]<<(8*1)) | ((x)[1]<<(8*0)))
#define read_int8be(x) (signed)(((x)[0]<<(8*0)))
#define read_int32le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_int24le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)))
#define read_int16le(x) (signed)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#define read_int8le(x) (signed)(((x)[0]<<(8*0)))
#define read_uint32be(x) (unsigned)(((x)[0]<<(8*3)) | ((x)[1]<<(8*2)) | ((x)[2]<<(8*1)) | ((x)[3]<<(8*0)))
#define read_uint24be(x) (unsigned)(((x)[0]<<(8*2)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*0)))
#define read_uint16be(x) (unsigned)(((x)[0]<<(8*1)) | ((x)[1]<<(8*0)))
#define read_uint8be(x) (unsigned)(((x)[0]<<(8*0)))
#define read_uint32le(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint24le(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)))
#define read_uint16le(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#define read_uint8le(x) (unsigned)(((x)[0]<<(8*0)))
#endif
/*
** IFF file structs
*/
typedef struct IFFChunk_s
{
char Type[5];
uint32_t Size; /* After subtracting the 76-byte header */
uint16_t ChunkID;
uint16_t Flags;
char Label[65];
uint8_t * Data;
void * FormattedData;
} IFFChunk;
typedef struct IFFFile_s
{
uint8_t Header[64];
uint32_t ChunkCount;
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";
/*
** IFF chunk structs
*/
/* BCON chunk */
typedef struct IFF_BCON_s
{
uint8_t ConstantCount;
uint8_t Flags;
uint16_t * Constants;
} IFF_BCON;
/* BHAV chunk */
typedef struct IFFInstruction_s
{
uint16_t Opcode;
uint8_t TDest;
uint8_t FDest;
uint8_t Operands[8];
} IFFInstruction;
typedef struct IFFBehavior_s
{
uint16_t Version;
uint32_t InstructionCount;
uint8_t Type;
uint8_t ArgumentCount;
uint16_t LocalCount;
uint16_t Flags;
IFFInstruction * Instructions;
} IFFBehavior;
/* DGRP chunk */
typedef struct IFFSpriteInfo_s
{
uint16_t Type;
uint32_t ChunkID;
uint32_t SpriteIndex;
uint16_t Flags;
int32_t SpriteX;
int32_t SpriteY;
float ObjectZ;
float ObjectX;
float ObjectY;
} IFFSpriteInfo;
typedef struct IFFDrawAngle_s
{
uint16_t SpriteCount;
uint32_t Direction;
uint32_t Zoom;
IFFSpriteInfo * SpriteInfo;
} IFFDrawAngle;
typedef struct IFFDrawGroup_s
{
uint16_t Version;
uint32_t AngleCount;
IFFDrawAngle DrawAngles[12];
} IFFDrawGroup;
enum IFFDrawDirection {
IFFDIRECTION_NORTHEAST = 1,
IFFDIRECTION_SOUTHEAST = 4,
IFFDIRECTION_NORTHWEST = 16,
IFFDIRECTION_SOUTHWEST = 64
};
enum IFFDrawZoom {
IFFZOOM_FAR = 1,
IFFZOOM_MIDDLE,
IFFZOOM_CLOSE
};
/* FCNS chunk */
typedef struct IFFConstant_s
{
char * Name;
float Value;
char * Description;
} IFFConstant;
typedef struct IFFConstantList_s
{
uint32_t Reserved;
uint32_t Version;
char MagicNumber[5];
uint32_t ConstantCount;
IFFConstant * Constants;
} IFFConstantList;
/* OBJf chunk */
typedef struct IFFFunction_s
{
uint16_t ConditionID;
uint16_t ActionID;
} IFFFunction;
typedef struct IFFFunctionTable_s
{
uint32_t Reserved;
uint32_t Version;
char MagicNumber[5];
uint32_t FunctionCount;
IFFFunction * Functions;
} IFFFunctionTable;
/* PALT chunk */
typedef struct IFFPalette_s
{
uint32_t Version;
uint32_t ColorCount;
uint32_t Reserved1;
uint32_t Reserved2;
uint8_t Data[256*3];
} IFFPalette;
/* SPR#/SPR2 chunk */
typedef struct IFFSprite_s
{
uint32_t Reserved;
uint16_t Height;
uint16_t Width;
uint32_t Flags;
uint16_t PaletteID;
uint16_t TransparentColor;
int16_t YLoc;
int16_t XLoc;
uint8_t * IndexData;
uint8_t * BGRA32Data;
uint8_t * ZBuffer;
uint8_t InvalidDimensions;
} IFFSprite;
typedef struct IFFSpriteList_s
{
uint32_t Version;
uint32_t SpriteCount;
uint32_t PaletteID;
IFFSprite * Sprites;
} IFFSpriteList;
enum IFFSpriteFlags {
IFFSPRITE_FLAG_COLOR = 1,
IFFSPRITE_FLAG_ZBUFFER = 2,
IFFSPRITE_FLAG_ALPHA = 4
};
int iff_depalette(IFFSprite * Sprite, const IFFPalette * Palette);
/* STR# chunk */
enum IFFLanguage {
IFFLANG_DEFAULT = 0,
IFFLANG_EN_US = 1,
IFFLANG_EN_INTERNATIONAL = 2,
IFFLANG_FRENCH = 3,
IFFLANG_GERMAN = 4,
IFFLANG_ITALIAN = 5,
IFFLANG_SPANISH = 6,
IFFLANG_DUTCH = 7,
IFFLANG_DANISH = 8,
IFFLANG_SWEDISH = 9,
IFFLANG_NORWEGIAN = 10,
IFFLANG_FINNISH = 11,
IFFLANG_HEBREW = 12,
IFFLANG_RUSSIAN = 13,
IFFLANG_PORTUGUESE = 14,
IFFLANG_JAPANESE = 15,
IFFLANG_POLISH = 16,
IFFLANG_CHINESE_SIMPLIFIED = 17,
IFFLANG_CHINESE_TRADITIONAL = 18,
IFFLANG_THAI = 19,
IFFLANG_KOREAN = 20
};
typedef struct IFFStringPair_s
{
uint8_t LanguageSet;
char * Key;
char * Value;
} IFFStringPair;
typedef struct IFFLanguageSet_s
{
uint16_t PairCount;
IFFStringPair * Pairs;
} IFFLanguageSet;
typedef struct IFF_STR_s
{
int16_t Format;
IFFLanguageSet LanguageSets[20];
} IFFString;
/* TMPL chunk */
typedef struct IFFTemplateField_s
{
char * Name;
char Type[5];
} IFFTemplateField;
typedef struct IFFTemplate_s
{
uint32_t FieldCount;
IFFTemplateField * Fields;
} IFFTemplate;
/* TRCN chunk */
typedef struct IFFRangeEntry_s
{
uint32_t IsUsed;
uint32_t DefaultValue;
char * Name;
char * Comment;
uint8_t Enforced;
uint16_t RangeMin;
uint16_t RangeMax;
} IFFRangeEntry;
typedef struct IFFRangeSet_s
{
uint32_t Reserved;
uint32_t Version;
char MagicNumber[5];
uint32_t RangeCount;
IFFRangeEntry * Ranges;
} IFFRangeSet;
/* rsmp chunk */
typedef struct IFFResource_s
{
uint32_t Offset;
uint32_t ChunkID;
uint16_t Flags;
char * Label;
} IFFResource;
typedef struct IFFResouceType_s
{
char Type[5];
uint32_t ResourceCount;
IFFResource * Resources;
} IFFResourceType;
typedef struct IFFResourceMap_s
{
uint32_t Reserved;
uint32_t Version;
char MagicNumber[5];
uint32_t IFFSize;
uint32_t TypeCount;
IFFResourceType * ResourceTypes;
} IFFResourceMap;
#ifdef __cplusplus
extern "C" {
#endif
/*
** IFF file functions
*/
int iff_create(IFFFile * IFFFileInfo);
int iff_read_header(IFFFile * IFFFileInfo, const uint8_t * Buffer, unsigned FileSize);
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);
IFFChunk * iff_find_chunk(IFFFile * IFFFileInfo, const char * Type, int ChunkID);
void iff_free_chunk(IFFChunk * ChunkInfo);
void iff_delete_chunk(IFFFile * IFFFileInfo, int Position);
void iff_delete(IFFFile * IFFFileInfo);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,173 @@
/*
FileHandler - General-purpose file handling library for Niotso
iffexport.c - 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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include "iff.h"
static FILE * hFile = NULL;
static uint8_t * IFFData = NULL;
static IFFFile IFFFileInfo;
static int iffcreated = 0;
static void Shutdown_M(const char * Message){
fprintf(stderr, "iffexport: error: %s.\n", Message);
if(iffcreated)
iff_delete(&IFFFileInfo);
free(IFFData);
if(hFile)
fclose(hFile);
exit(EXIT_FAILURE);
}
static int charmatches(char c, const char * filter){
while(*filter){
if(c == *filter) return 1;
filter++;
}
return 0;
}
int main(int argc, char *argv[]){
int overwrite = 0;
const char *InFile, *OutDirectory;
size_t FileSize;
clock_t BeginningTime;
unsigned chunkcount, chunk;
unsigned exported = 0;
IFFChunk * ChunkData;
if(argc < 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
printf("Usage: iffexport [-f] infile outdirectory\n"
"Export the resources of an EA IFF file.\n"
"Use -f to force overwriting without confirmation.\n"
"\n"
"Report bugs to <X-Fi6@phppoll.org>.\n"
"iffexport is maintained by the Niotso project.\n"
"Home page: <http://www.niotso.org/>\n");
return 0;
}
if(argc >= 4 && !strcmp(argv[1], "-f")){
overwrite++;
InFile = argv[2];
OutDirectory = argv[3];
}else{
InFile = argv[1];
OutDirectory = argv[2];
}
/****
** Open the file and read in entire contents to memory
*/
hFile = fopen(InFile, "rb");
if(hFile == NULL)
Shutdown_M("The specified input file does not exist or could not be opened for reading");
fseek(hFile, 0, SEEK_END);
FileSize = ftell(hFile);
if(FileSize < 24)
Shutdown_M("Not a valid IFF file");
fseek(hFile, 0, SEEK_SET);
IFFData = malloc(FileSize);
if(IFFData == NULL)
Shutdown_M("Memory for this file could not be allocated");
if(fread(IFFData, 1, FileSize, hFile) != FileSize)
Shutdown_M("The input file could not be read");
fclose(hFile); hFile = NULL;
/****
** Load header information
*/
if(!iff_create(&IFFFileInfo))
Shutdown_M("Memory for this file could not be allocated");
iffcreated++;
if(!iff_read_header(&IFFFileInfo, IFFData, FileSize))
Shutdown_M("Not a valid IFF file");
/****
** Load entry information
*/
if(!iff_enumerate_chunks(&IFFFileInfo, IFFData+64, FileSize-64))
Shutdown_M("Chunk data is corrupt");
free(IFFData); IFFData = NULL;
chunkcount = IFFFileInfo.ChunkCount;
printf("This IFF file contains %u chunks.\n\nExporting\n", chunkcount);
BeginningTime = clock();
/****
** Extract each entry
*/
for(chunk = 1, ChunkData = IFFFileInfo.Chunks; chunk <= chunkcount; chunk++, ChunkData++){
char name[256], destination[256];
char filter[] = "\\/:*?\"<>|";
int i;
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(ChunkData->Type, "BMP_", 4) || !memcmp(ChunkData->Type, "FBMP", 4)) ? "bmp" : "dat");
if(!overwrite){
hFile = fopen(destination, "rb");
if(hFile != NULL){
/* File exists */
char c;
fclose(hFile); hFile = NULL;
printf("File \"%s\" exists.\nContinue anyway? (y/n) ", destination);
c = getchar();
if(c != 'y' && c != 'Y'){
printf("\n");
Shutdown_M("Aborted");
}
}
overwrite++;
}
hFile = fopen(destination, "wb");
if(hFile == NULL)
Shutdown_M("The output file could not be opened for writing");
fwrite(ChunkData->Data, 1, ChunkData->Size, hFile);
fclose(hFile);
exported++;
}
printf("\nExported %u of %u chunks in %.2f seconds.", exported, chunkcount,
((float) (clock() - BeginningTime))/CLOCKS_PER_SEC);
iff_delete(&IFFFileInfo);
return 0;
}

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

View file

@ -0,0 +1,60 @@
/*
FileHandler - General-purpose file handling library for Niotso
objf.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
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 "iffparser.h"
int iff_parse_objf(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFFunctionTable *Table;
unsigned i;
if(ChunkInfo->Size < 16)
return 0;
ChunkInfo->FormattedData = calloc(1, sizeof(IFFFunctionTable));
if(ChunkInfo->FormattedData == NULL)
return 0;
Table = ChunkInfo->FormattedData;
Table->Reserved = read_uint32le(Buffer);
Table->Version = read_uint32le(Buffer+4);
memcpy(Table->MagicNumber, Buffer+8, 4);
Table->MagicNumber[4] = 0x00;
Table->FunctionCount = read_uint32le(Buffer+12);
if(Table->Reserved != 0 || Table->Version != 0)
return 0;
if(Table->FunctionCount == 0)
return 1;
if(Table->FunctionCount > (ChunkInfo->Size - 16)/4)
return 0;
Table->Functions = malloc(Table->FunctionCount * sizeof(IFFFunction));
if(Table->Functions == NULL)
return 0;
Buffer += 16;
for(i=0; i<Table->FunctionCount; i++, Buffer += 4){
Table->Functions[i].ConditionID = read_uint16le(Buffer);
Table->Functions[i].ActionID = read_uint16le(Buffer+2);
}
return 1;
}
void iff_free_objf(void * FormattedData){
IFFFunctionTable *Table = FormattedData;
free(Table->Functions);
}

View file

@ -0,0 +1,41 @@
/*
FileHandler - General-purpose file handling library for Niotso
palt.c - 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 "iffparser.h"
int iff_parse_palt(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFPalette *Palette;
if(ChunkInfo->Size < 16)
return 0;
ChunkInfo->FormattedData = malloc(sizeof(IFFPalette));
if(ChunkInfo->FormattedData == NULL)
return 0;
Palette = ChunkInfo->FormattedData;
Palette->Version = read_uint32le(Buffer);
Palette->ColorCount = read_uint32le(Buffer+4);
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 > ChunkInfo->Size-16)
return 0;
memcpy(Palette->Data, Buffer+16, Palette->ColorCount*3);
return 1;
}

View file

@ -0,0 +1,93 @@
/*
FileHandler - General-purpose file handling library for Niotso
rsmp.c - 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 "iffparser.h"
int iff_parse_rsmp(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFResourceMap *Map;
bytestream b;
unsigned i;
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_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;
Map->ResourceTypes = calloc(Map->TypeCount, sizeof(IFFResourceType));
if(Map->ResourceTypes == NULL)
return 0;
for(i=0; i<Map->TypeCount; i++){
IFFResourceType * Type = &Map->ResourceTypes[i];
unsigned j;
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;
for(j=0; j<Type->ResourceCount; j++){
IFFResource * Resource = &Type->Resources[j];
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){
if(!read_c_string(&b, &Resource->Label))
return 0;
}else{
if(!read_pascal_string(&b, &Resource->Label))
return 0;
}
}
}
return 1;
}
void iff_free_rsmp(void * FormattedData){
IFFResourceMap * Map = FormattedData;
if(Map->ResourceTypes){
unsigned t;
for(t=0; t<Map->TypeCount; t++){
IFFResourceType * Type = &Map->ResourceTypes[t];
if(Type->Resources){
unsigned r;
for(r=0; r<Type->ResourceCount; r++)
free(Type->Resources[r].Label);
free(Type->Resources);
}
}
free(Map->ResourceTypes);
}
}

221
library/formats/iff/spr.c Normal file
View file

@ -0,0 +1,221 @@
/*
FileHandler - General-purpose file handling library for Niotso
spr.c - 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 "iffparser.h"
int iff_parse_spr(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFSpriteList *SpriteList;
bytestream b;
unsigned NextSpriteOffset; /* Used for Version 1001 in place of the offset table */
unsigned i;
if(ChunkInfo->Size < 12)
return 0;
set_bytestream(&b, Buffer, ChunkInfo->Size);
if((Buffer[0]|Buffer[1]) == 0) b.Endian++; /* Big endian */
ChunkInfo->FormattedData = calloc(1, sizeof(IFFSpriteList));
if(ChunkInfo->FormattedData == NULL)
return 0;
SpriteList = ChunkInfo->FormattedData;
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;
if(SpriteList->Version != 1001){
if(SpriteList->SpriteCount > b.Size/4)
return 0;
}else{
/* Sprite count is blank in version 1001, so we must walk and count up the sprites ourselves;
** this is easy with the sprite size field */
for(SpriteList->SpriteCount = 0; b.Size >= 16; SpriteList->SpriteCount++){
if(read_uint32(&b) != 1001 || !skipbytes(&b, read_uint32(&b)))
return 0;
}
NextSpriteOffset = 16;
}
if(SpriteList->SpriteCount == 0)
return 1;
SpriteList->Sprites = calloc(SpriteList->SpriteCount, sizeof(IFFSprite));
if(SpriteList->Sprites == NULL)
return 0;
for(i=0; i<SpriteList->SpriteCount; i++){
IFFSprite * Sprite = &SpriteList->Sprites[i];
unsigned SpriteSize;
unsigned row = 0;
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_uint32(&b)) || b.Size < 8)
return 0;
SpriteSize = b.Size;
}else{
/* Jump to the next sprite using the sprite size field; this is mandatory */
seekto(&b, NextSpriteOffset);
SpriteSize = read_uint32(&b);
NextSpriteOffset += SpriteSize + 8;
}
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/2/Sprite->Width){
/* This happens in the third sprite of every SPR# chunk in sprites.iff */
Sprite->InvalidDimensions = 1;
continue;
}
SpriteSize -= 8;
Sprite->IndexData = calloc(Sprite->Width*Sprite->Height, 2);
if(Sprite->IndexData == NULL)
return 0;
while(1){
/****
** Row command: valid commands are 0, 4, 5, 9, and 16
*/
uint8_t RowCommand, RowCount;
if(SpriteSize < 2)
return 0;
RowCommand = *(b.Buffer++);
RowCount = *(b.Buffer++);
SpriteSize -= 2;
if(RowCommand == 0 || RowCommand == 16){
/* Start marker */
}else if(RowCommand == 4){
/****
** Pixel command: valid commands are 1, 2, and 3
*/
unsigned pixel = 0;
if(row == Sprite->Height || RowCount < 2 || (RowCount -= 2) > SpriteSize || RowCount%2 != 0)
return 0;
SpriteSize -= RowCount;
while(RowCount){
uint8_t PixelCommand, PixelCount;
uint8_t * IndexData;
if(RowCount < 2)
return 0;
PixelCommand = *(b.Buffer++);
PixelCount = *(b.Buffer++);
RowCount -= 2;
if(PixelCount > Sprite->Width - pixel)
return 0;
IndexData = Sprite->IndexData + (Sprite->Width*row + pixel)*2;
pixel += PixelCount;
if(PixelCommand == 1){
/* Leave next n pixels as transparent */
}else if(PixelCommand == 2){
/* Set next n pixels to shared palette index */
uint8_t PaletteIndex;
if(RowCount < 2)
return 0;
PaletteIndex = *(b.Buffer++);
b.Buffer++; /* Padding byte */
RowCount -= 2;
while(PixelCount--){
*IndexData++ = PaletteIndex;
*IndexData++ = 0xFF;
}
}else if(PixelCommand == 3){
/* Set next n pixels to n palette indices */
int padding = PixelCount%2;
if(PixelCount + padding > RowCount)
return 0;
RowCount -= PixelCount + padding;
while(PixelCount--){
*IndexData++ = *(b.Buffer++);
*IndexData++ = 0xFF;
}
if(padding) b.Buffer++; /* Padding byte */
}else return 0;
}
row++;
}else if(RowCommand == 5){
/* End marker */
break;
}else if(RowCommand == 9){
/* Leave rows as transparent */
if(RowCount > Sprite->Height - row)
return 0;
row += RowCount;
}else return 0;
}
}
return 1;
}
void iff_free_spr(void * FormattedData){
IFFSpriteList *SpriteList = FormattedData;
if(SpriteList->Sprites){
unsigned s;
for(s=0; s<SpriteList->SpriteCount; s++){
IFFSprite *Sprite = &SpriteList->Sprites[s];
free(Sprite->IndexData);
free(Sprite->BGRA32Data);
free(Sprite->ZBuffer);
}
free(SpriteList->Sprites);
}
}
int iff_depalette(IFFSprite * Sprite, const IFFPalette * Palette){
unsigned PixelCount = Sprite->Width*Sprite->Height;
unsigned i;
Sprite->BGRA32Data = malloc(PixelCount*4);
if(Sprite->BGRA32Data == NULL) return 0;
for(i=0; i<PixelCount; i++){
uint8_t Index = Sprite->IndexData[2*i + 0];
if(Index >= Palette->ColorCount){
free(Sprite->BGRA32Data);
Sprite->BGRA32Data = NULL;
return 0;
}
Sprite->BGRA32Data[4*i + 0] = Palette->Data[3*Index + 2];
Sprite->BGRA32Data[4*i + 1] = Palette->Data[3*Index + 1];
Sprite->BGRA32Data[4*i + 2] = Palette->Data[3*Index + 0];
Sprite->BGRA32Data[4*i + 3] = Sprite->IndexData[2*i + 1];
}
return 1;
}

227
library/formats/iff/spr2.c Normal file
View file

@ -0,0 +1,227 @@
/*
FileHandler - General-purpose file handling library for Niotso
spr2.c - 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 "iffparser.h"
int iff_parse_spr2(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFSpriteList *SpriteList;
bytestream b;
unsigned NextSpriteOffset; /* Used for Version 1001 in place of the offset table */
unsigned i;
if(ChunkInfo->Size < 12)
return 0;
set_bytestream(&b, Buffer, ChunkInfo->Size);
if((Buffer[0]|Buffer[1]) == 0) b.Endian++; /* Big endian */
ChunkInfo->FormattedData = calloc(1, sizeof(IFFSpriteList));
if(ChunkInfo->FormattedData == NULL)
return 0;
SpriteList = ChunkInfo->FormattedData;
SpriteList->Version = read_uint32(&b);
if(SpriteList->Version != 1000 && SpriteList->Version != 1001)
return 0;
if(SpriteList->Version == 1000){
SpriteList->SpriteCount = read_uint32(&b);
SpriteList->PaletteID = read_uint32(&b);
if(SpriteList->SpriteCount > b.Size/4)
return 0;
}else{
SpriteList->PaletteID = read_uint32(&b);
skipbytes(&b, 4);
/* Sprite count is blank in version 1001, so we must walk and count up the sprites ourselves;
** this is easy with the sprite size field */
for(SpriteList->SpriteCount = 0; b.Size >= 24; SpriteList->SpriteCount++){
if(read_uint32(&b) != 1001 || !skipbytes(&b, read_uint32(&b)))
return 0;
}
NextSpriteOffset = 16;
}
if(SpriteList->SpriteCount == 0)
return 1;
SpriteList->Sprites = calloc(SpriteList->SpriteCount, sizeof(IFFSprite));
if(SpriteList->Sprites == NULL)
return 0;
for(i=0; i<SpriteList->SpriteCount; i++){
IFFSprite * Sprite = &SpriteList->Sprites[i];
unsigned SpriteSize;
unsigned row = 0;
int j;
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_uint32(&b)) || b.Size < 16)
return 0;
SpriteSize = b.Size;
}else{
/* Jump to the next sprite using the sprite size field; this is mandatory */
seekto(&b, NextSpriteOffset);
SpriteSize = read_uint32(&b);
NextSpriteOffset += SpriteSize + 8;
}
Sprite->Width = read_uint16(&b);
Sprite->Height = read_uint16(&b);
Sprite->Flags = read_uint32(&b);
Sprite->PaletteID = read_uint16(&b);
Sprite->TransparentColor = read_uint16(&b);
Sprite->YLoc = read_uint16(&b);
Sprite->XLoc = read_uint16(&b);
if((Sprite->Flags != 1 && Sprite->Flags != 3 && Sprite->Flags != 7) || Sprite->TransparentColor >= 256)
return 0;
if(Sprite->Height == 0 || Sprite->Width == 0 || Sprite->Height > UINT_MAX/2/Sprite->Width){
/* This happens in the many chunks in 2personportal.spf */
Sprite->InvalidDimensions = 1;
continue;
}
SpriteSize -= 16;
Sprite->IndexData = malloc(Sprite->Width*Sprite->Height*2);
if(Sprite->IndexData == NULL)
return 0;
for(j=0; j<Sprite->Width*Sprite->Height; j++){
Sprite->IndexData[2*j + 0] = Sprite->TransparentColor;
Sprite->IndexData[2*j + 1] = 0x00;
}
if(Sprite->Flags >= 3){ /* Has the Z-Buffer flag */
Sprite->ZBuffer = malloc(Sprite->Width*Sprite->Height);
if(Sprite->ZBuffer == NULL)
return 0;
memset(Sprite->ZBuffer, 0xFF, Sprite->Width*Sprite->Height);
}
while(1){
/****
** Row command: valid commands are 0, 4, and 5
*/
uint8_t RowCommand; /* 3 bits */
uint16_t RowCount; /* 13 bits */
if(SpriteSize < 2)
return 0;
RowCount = read_uint16le(b.Buffer);
RowCommand = RowCount >> 13;
RowCount &= 0x1FFF;
b.Buffer += 2;
SpriteSize -= 2;
if(RowCommand == 0){
/****
** Pixel command: valid commands are 1, 2, 3, and 6
*/
unsigned pixel = 0;
if(row == Sprite->Height || RowCount < 2 || (RowCount -= 2) > SpriteSize || RowCount%2 != 0)
return 0;
SpriteSize -= RowCount;
while(RowCount){
uint8_t PixelCommand; /* 3 bits */
uint16_t PixelCount; /* 13 bits */
uint8_t * IndexData, * ZBuffer;
if(RowCount < 2)
return 0;
PixelCount = read_uint16le(b.Buffer);
PixelCommand = PixelCount >> 13;
PixelCount &= 0x1FFF;
b.Buffer += 2;
RowCount -= 2;
if(PixelCount > Sprite->Width - pixel)
return 0;
IndexData = Sprite->IndexData + (Sprite->Width*row + pixel)*2;
ZBuffer = Sprite->ZBuffer + (Sprite->Width*row + pixel)*1;
pixel += PixelCount;
if(PixelCommand == 1){
/* color+z-buffer: Set next n pixels to n palette indices */
if(Sprite->Flags < 3 || PixelCount*2 > RowCount)
return 0;
RowCount -= PixelCount*2;
while(PixelCount--){
*ZBuffer++ = *(b.Buffer++);
IndexData[0] = *(b.Buffer++);
IndexData[1] = (IndexData[0] != Sprite->TransparentColor) ? 0xFF : 0x00;
IndexData += 2;
}
}else if(PixelCommand == 2){
/* color+z-buffer+alpha: Set next n pixels to n palette indices */
int padding = PixelCount%2;
if(Sprite->Flags < 7 || PixelCount*3 + padding > RowCount)
return 0;
RowCount -= PixelCount*3 + padding;
while(PixelCount--){
*ZBuffer++ = *(b.Buffer++);
*IndexData++ = *(b.Buffer++);
*IndexData++ = *(b.Buffer++);
}
if(padding) b.Buffer++; /* Padding byte */
}else if(PixelCommand == 3){
/* Leave next n pixels as transparent */
}else if(PixelCommand == 6){
/* color: Set next n pixels to n palette indices */
int padding = PixelCount%2;
if(PixelCount + padding > RowCount)
return 0;
RowCount -= PixelCount + padding;
while(PixelCount--){
IndexData[0] = *(b.Buffer++);
IndexData[1] = (IndexData[0] != Sprite->TransparentColor) ? 0xFF : 0x00;
if(Sprite->Flags >= 3)
*ZBuffer++ = (IndexData[0] != Sprite->TransparentColor) ? 0x00 : 0xFF;
IndexData += 2;
}
if(padding) b.Buffer++; /* Padding byte */
} else return 0;
}
row++;
}else if(RowCommand == 4){
/* Leave rows as transparent */
if(RowCount > Sprite->Height - row)
return 0;
row += RowCount;
}else if(RowCommand == 5){
/* End marker */
break;
}else return 0;
}
}
return 1;
}

159
library/formats/iff/str.c Normal file
View file

@ -0,0 +1,159 @@
/*
FileHandler - General-purpose file handling library for Niotso
str.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
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 "iffparser.h"
int iff_parse_str(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFString * StringData;
bytestream b;
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_uint16(&b);
if(b.Size < 2) /* TSO allows this; as seen in the animations chunk in personglobals.iff */
return 1;
if(StringData->Format < -4 || StringData->Format > 0){
/* Seen often in The Sims 1's Behavior.iff */
StringData->Format = 0;
seekto(&b, 0);
b.Endian++;
}
if(StringData->Format != -3){
unsigned LanguageSetCount = 1;
unsigned ls;
if(StringData->Format == -4){
LanguageSetCount = read_uint8(&b);
if(LanguageSetCount > 20) return 0;
}
for(ls=0; ls<LanguageSetCount; ls++){
IFFLanguageSet * LanguageSet = &StringData->LanguageSets[ls];
unsigned p;
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;
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;
}
}
}
}else{
/* FD FF requires a lot of extra work -- and isn't even found in TSO */
IFFLanguageSet * LanguageSet = StringData->LanguageSets;
unsigned TotalPairCount;
unsigned Index[20] = {0};
unsigned i;
TotalPairCount = read_uint16(&b);
if(TotalPairCount == 0)
return 1;
/*
** 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(b.Size == 0) return 0;
lang = read_uint8(&b) - 1;
if(lang >= 20) return 0;
LanguageSet[lang].PairCount++;
for(s=0; s<2; s++){
unsigned length;
for(length=0; length != b.Size && b.Buffer[length]; length++);
if(length == b.Size) return 0;
skipbytes(&b, 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 */
set_bytestream(&b, Buffer+4, ChunkInfo->Size-4);
for(i=0; i<TotalPairCount; i++){
IFFStringPair * Pair;
unsigned lang;
lang = read_uint8(&b) - 1;
Pair = &LanguageSet[lang].Pairs[Index[lang]++];
if(!read_c_string(&b, &Pair->Key) || !read_c_string(&b, &Pair->Value))
return 0;
}
}
return 1;
}
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
*/
IFFString * StringData = FormattedData;
unsigned ls;
for(ls=0; ls<20; ls++){
IFFLanguageSet * LanguageSet = &StringData->LanguageSets[ls];
if(LanguageSet->Pairs){
unsigned p;
for(p=0; p<LanguageSet->PairCount; p++){
free(LanguageSet->Pairs[p].Key);
free(LanguageSet->Pairs[p].Value);
}
free(LanguageSet->Pairs);
}
}
}

View file

@ -0,0 +1,25 @@
/*
FileHandler - General-purpose file handling library for Niotso
string.c - 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 "iffparser.h"
int iff_parse_c_string(IFFChunk * ChunkInfo, const uint8_t * Buffer){
bytestream b;
set_bytestream(&b, Buffer, ChunkInfo->Size);
return (read_c_string(&b, (char**) &ChunkInfo->FormattedData) != 0);
}

View file

@ -0,0 +1,70 @@
/*
FileHandler - General-purpose file handling library for Niotso
tmpl.c - 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 "iffparser.h"
int iff_parse_tmpl(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFTemplate *Template;
bytestream b;
const uint8_t * ptr = Buffer;
unsigned Size = ChunkInfo->Size;
unsigned FieldCount;
unsigned i;
if(Size == 0) return 1;
/* Walk through a first-pass to find the total field count */
for(FieldCount=0; Size; FieldCount++){
unsigned length = *ptr;
if(Size < 5 || length > Size-5)
return 0;
ptr += length+5; Size -= length+5;
}
ChunkInfo->FormattedData = calloc(1, sizeof(IFFTemplate));
if(ChunkInfo->FormattedData == NULL)
return 0;
Template = ChunkInfo->FormattedData;
Template->FieldCount = FieldCount;
Template->Fields = calloc(FieldCount, sizeof(IFFTemplateField));
if(Template->Fields == NULL)
return 0;
set_bytestream(&b, Buffer, ChunkInfo->Size);
for(i=0; i<FieldCount; i++){
IFFTemplateField * Field = &Template->Fields[i];
if(!read_pascal_string(&b, &Field->Name))
return 0;
memcpy(Field->Type, b.Buffer, 4);
skipbytes(&b, 4);
}
return 1;
}
void iff_free_tmpl(void * FormattedData){
IFFTemplate * Template = FormattedData;
if(Template->Fields){
unsigned f;
for(f=0; f<Template->FieldCount; f++)
free(Template->Fields[f].Name);
free(Template->Fields);
}
}

View file

100
library/formats/iff/trcn.c Normal file
View file

@ -0,0 +1,100 @@
/*
FileHandler - General-purpose file handling library for Niotso
trcn.c - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Ahmed El-Mahdawy <aa.mahdawy.10@gmail.com>
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 "iffparser.h"
int iff_parse_trcn(IFFChunk * ChunkInfo, const uint8_t * Buffer){
IFFRangeSet *RangeSet;
bytestream b;
unsigned i;
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->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)
return 1;
RangeSet->Ranges = calloc(RangeSet->RangeCount, sizeof(IFFRangeEntry));
if(RangeSet->Ranges == NULL)
return 0;
for(i=0; i<RangeSet->RangeCount; i++){
unsigned s;
IFFRangeEntry * Range = &RangeSet->Ranges[i];
if(b.Size < 10)
return 0;
Range->IsUsed = read_uint32(&b);
Range->DefaultValue = read_uint32(&b);
for(s=0; s<2; s++){
char ** string = (s==0) ? &Range->Name : &Range->Comment;
if(b.Size == 0) return 0;
if(RangeSet->Version < 2){
/* 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(b.Size && *b.Buffer == 0xA3)
skipbytes(&b, 1);
}else{
/* Extended Pascal string, no padding */
if(!read_pascal2_string(&b, string))
return 0;
}
}
if(RangeSet->Version != 0){
if(b.Size < 5) return 0;
Range->Enforced = read_uint8(&b);
Range->RangeMin = read_uint16(&b);
Range->RangeMax = read_uint16(&b);
}
}
return 1;
}
void iff_free_trcn(void * FormattedData){
IFFRangeSet *RangeSet = FormattedData;
if(RangeSet->Ranges){
unsigned i;
for(i=0; i<RangeSet->RangeCount; i++){
IFFRangeEntry *Entry = &RangeSet->Ranges[i];
free(Entry->Name);
free(Entry->Comment);
}
}
free(RangeSet->Ranges);
}

View file

View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_ini.c - 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.
*/

View file

@ -0,0 +1,35 @@
/* Name of package */
#define PACKAGE "FileHandler"
/* Version number of package */
#define VERSION_A 0
#define VERSION_B 0
#define VERSION_C 0
#define VERSION_STR "0.0.0"
#define REVISION 0
1 VERSIONINFO
FILEVERSION VERSION_A,VERSION_B,VERSION_C,REVISION
PRODUCTVERSION VERSION_A,VERSION_B,VERSION_C,REVISION
FILEOS 0x00040000L /* VOS_NT - 32-bit Windows */
FILETYPE 2 /* DLL */
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "Niotso project"
VALUE "FileDescription", "General-purpose file handling library for Niotso"
VALUE "FileVersion", VERSION_STR
VALUE "InternalName", PACKAGE
VALUE "LegalCopyright", "Copyright © 2012"
VALUE "OriginalFilename", PACKAGE".dll"
VALUE "ProductName", PACKAGE
VALUE "ProductVersion", VERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 0x04B0
END
END

BIN
library/formats/tga/elf.dat Normal file

Binary file not shown.

View file

@ -0,0 +1,93 @@
* Elf32_Word sh_name:
* Elf32_Word sh_type:
* Elf32_Word sh_flags:
* Elf32_Addr sh_addr:
* Elf32_Off sh_offset: (?? ?? ?? ??)
* Elf32_Word sh_size: (?? ?? ?? ??)
* Elf32_Word sh_link:
* Elf32_Word sh_info:
* Elf32_Word sh_addralign: 1 (01 00 00 00)
* Elf32_Word sh_entsize:
ELF Header:
* e_ident:
* Elf32_Word EI_MAG0: (7F 45 4C 46)
* unsigned char EI_CLASS: ELFCLASS32 (01)
* unsigned char EI_DATA: ELFDATA2LSB (01)
* unsigned char EI_VERSION: EV_CURRENT (01)
* unsigned char EI_PAD[9]: (00 00 00 00 00 00 00 00 00)
* Elf32_Half e_type: ET_REL (01 00)
* Elf32_Half e_machine: EM_NONE (00 00)
* Elf32_Word e_version: EV_CURRENT (01 00 00 00)
* Elf32_Addr e_entry: 0 (00 00 00 00)
* Elf32_Off e_phoff: 0 (00 00 00 00)
* Elf32_Off e_shoff: 64 (40 00 00 00)
* Elf32_Word e_flags: 0x00000001 (01 00 00 00)
* Elf32_Half e_ehsize: 52 (34 00)
* Elf32_Half e_phentsize: 0 (00 00)
* Elf32_Half e_phnum: 0 (00 00)
* Elf32_Half e_shentsize: 40 (28 00)
* Elf32_Half e_shnum: 6 (06 00)
* Elf32_Half e_shstrndx: 2 (02 00)
* unsigned char padding[12] = (00 00 00 00 00 00 00 00 00 00 00 00)
Section headers
0 (""): All 0s
1 (".text"):
* Elf32_Word sh_name: 1 (01 00 00 00)
* Elf32_Word sh_type: SHT_PROGBITS (01 00 00 00)
* Elf32_Word sh_flags: SHF_ALLOC | SHF_EXECINSTR (06 00 00 00)
* Elf32_Addr sh_addr: 0x00000010 (10 00 00 00)
* Elf32_Off sh_offset: (?? ?? ?? ??)
* Elf32_Word sh_size: (?? ?? ?? ??)
* Elf32_Word sh_link: 0 (00 00 00 00)
* Elf32_Word sh_info: 0 (00 00 00 00)
* Elf32_Word sh_addralign: 1 (01 00 00 00)
* Elf32_Word sh_entsize: 0 (00 00 00 00)
2 (".shstrtab"):
* Elf32_Word sh_name: 7 (07 00 00 00)
* Elf32_Word sh_type: SHT_STRTAB (03 00 00 00)
* Elf32_Word sh_flags: 0 (00 00 00 00)
* Elf32_Addr sh_addr: 0 (00 00 00 00)
* Elf32_Off sh_offset: (?? ?? ?? ??)
* Elf32_Word sh_size: (?? ?? ?? ??)
* Elf32_Word sh_link: 0 (00 00 00 00)
* Elf32_Word sh_info: 0 (00 00 00 00)
* Elf32_Word sh_addralign: 1 (01 00 00 00)
* Elf32_Word sh_entsize: 0 (00 00 00 00)
3 (".symtab"):
* Elf32_Word sh_name: 17 (11 00 00 00)
* Elf32_Word sh_type: SHT_SYMTAB (02 00 00 00)
* Elf32_Word sh_flags: 0 (00 00 00 00)
* Elf32_Addr sh_addr: 0 (00 00 00 00)
* Elf32_Off sh_offset: (?? ?? ?? ??)
* Elf32_Word sh_size: (?? ?? ?? ??)
* Elf32_Word sh_link: 4 (04 00 00 00)
* Elf32_Word sh_info: 5 (05 00 00 00)
* Elf32_Word sh_addralign: 1 (01 00 00 00)
* Elf32_Word sh_entsize: 16 (10 00 00 00)
4 (".strtab"):
* Elf32_Word sh_name: 25 (19 00 00 00)
* Elf32_Word sh_type: SHT_STRTAB (03 00 00 00)
* Elf32_Word sh_flags: 0 (00 00 00 00)
* Elf32_Addr sh_addr: 0 (00 00 00 00)
* Elf32_Off sh_offset: (?? ?? ?? ??)
* Elf32_Word sh_size: (?? ?? ?? ??)
* Elf32_Word sh_link: 0 (00 00 00 00)
* Elf32_Word sh_info: 0 (00 00 00 00)
* Elf32_Word sh_addralign: 1 (01 00 00 00)
* Elf32_Word sh_entsize: 0 (00 00 00 00)
5 (".rel.text"):
* Elf32_Word sh_name: 33 (21 00 00 00)
* Elf32_Word sh_type: SHT_REL (09 00 00 00)
* Elf32_Word sh_flags: 0 (00 00 00 00)
* Elf32_Addr sh_addr: 0 (00 00 00 00)
* Elf32_Off sh_offset: (?? ?? ?? ??)
* Elf32_Word sh_size: (?? ?? ?? ??)
* Elf32_Word sh_link: 3 (03 00 00 00)
* Elf32_Word sh_info: 1 (01 00 00 00)
* Elf32_Word sh_addralign: 1 (01 00 00 00)
* Elf32_Word sh_entsize: 8 (08 00 00 00)
Symbols:
0: All 0s

View file

@ -0,0 +1,461 @@
/*
hitutils - The Sims HIT (dis)assembler and linker
hitutils.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.
*/
#ifndef min
#define min(x,y) ((x) < (y) ? (x) : (y))
#endif
#ifndef max
#define max(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef read_int32
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#endif
#ifndef write_int32
#define write_uint32(dest, src) do {\
(dest)[0] = ((src)&0x000000FF)>>(8*0); \
(dest)[1] = ((src)&0x0000FF00)>>(8*1); \
(dest)[2] = ((src)&0x00FF0000)>>(8*2); \
(dest)[3] = ((src)&0xFF000000)>>(8*3); \
} while(0)
#define write_uint16(dest, src) do {\
(dest)[0] = ((src)&0x00FF)>>(8*0); \
(dest)[1] = ((src)&0xFF00)>>(8*1); \
} while(0)
#endif
extern char *strdup (const char *__s)
__THROW __attribute_malloc__ __nonnull ((1));
static void Shutdown();
static void Shutdown_M(const char * Message, ...){
va_list args;
va_start(args, Message);
vfprintf(stderr, Message, args);
va_end(args);
Shutdown();
exit(EXIT_FAILURE);
}
enum {
VERSION_TS1 = 1, VERSION_TSO
};
#define OPERAND_BYTES(x) (x)
#define OPERAND(x, y) ((y)<<((x)*4+4))
#define UNIMPLEMENTED ((uint32_t)~0)
enum operand_t {
o_byte = 1,
o_dword,
o_address,
o_variable,
o_jump
};
typedef struct {
const char * Name;
uint32_t Operands;
} instruction_t;
typedef struct {
const char * Name;
uint32_t Value;
} variable_t;
typedef struct {
uint8_t * Data;
size_t Size;
} ByteReaderContext;
static const uint8_t HITHeader[] = {'H','I','T','!',0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,'T','R','A','X'};
#define InstructionCount 96
static const instruction_t Instructions[] = {
{"note", UNIMPLEMENTED},
{"note_on", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"note_off", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"loadb", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_byte)},
{"loadl", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"set", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"call", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"return", OPERAND_BYTES(0)},
{"wait", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"callentrypoint", UNIMPLEMENTED},
{"wait_samp", OPERAND_BYTES(0)},
{"end", OPERAND_BYTES(0)},
{"jump", OPERAND_BYTES(1) | OPERAND(0, o_jump)},
{"test", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"nop", OPERAND_BYTES(0)},
{"add", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"sub", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"div", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"mul", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"cmp", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"less", UNIMPLEMENTED},
{"greater", UNIMPLEMENTED},
{"not", UNIMPLEMENTED},
{"rand", OPERAND_BYTES(3) | OPERAND(0, o_variable) | OPERAND(1, o_variable) | OPERAND(2, o_variable)},
{"abs", UNIMPLEMENTED},
{"limit", UNIMPLEMENTED},
{"error", UNIMPLEMENTED},
{"assert", UNIMPLEMENTED},
{"add_to_group", UNIMPLEMENTED},
{"remove_from_group", UNIMPLEMENTED},
{"get_var", UNIMPLEMENTED},
{"loop", OPERAND_BYTES(0)},
{"set_loop", OPERAND_BYTES(0)},
{"callback", UNIMPLEMENTED},
{"smart_add", UNIMPLEMENTED},
{"smart_remove", UNIMPLEMENTED},
{"smart_removeall", UNIMPLEMENTED},
{"smart_setcrit", UNIMPLEMENTED},
{"smart_choose", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"and", UNIMPLEMENTED},
{"nand", UNIMPLEMENTED},
{"or", UNIMPLEMENTED},
{"nor", UNIMPLEMENTED},
{"xor", UNIMPLEMENTED},
{"max", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"min", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"inc", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"dec", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"printreg", UNIMPLEMENTED},
{"play_trk", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"kill_trk", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"push", UNIMPLEMENTED},
{"push_mask", UNIMPLEMENTED},
{"push_vars", UNIMPLEMENTED},
{"call_mask", UNIMPLEMENTED},
{"call_push", UNIMPLEMENTED},
{"pop", UNIMPLEMENTED},
{"test1", OPERAND_BYTES(0)},
{"test2", OPERAND_BYTES(0)},
{"test3", OPERAND_BYTES(0)},
{"test4", OPERAND_BYTES(0)},
{"ifeq", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"ifne", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"ifgt", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"iflt", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"ifge", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"ifle", OPERAND_BYTES(4) | OPERAND(0, o_address)},
{"smart_setlist", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"seqgroup_kill", OPERAND_BYTES(1) | OPERAND(0, o_byte)},
{"seqgroup_wait", UNIMPLEMENTED},
{"seqgroup_return", OPERAND_BYTES(1) | OPERAND(0, o_byte)},
{"getsrcdatafield", OPERAND_BYTES(3) | OPERAND(0, o_variable) | OPERAND(1, o_variable) | OPERAND(2, o_variable)},
{"seqgroup_trkid", OPERAND_BYTES(2) | OPERAND(0, o_byte) | OPERAND(1, o_byte)},
{"setll", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"setlt", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"settl", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waiteq", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitne", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitgt", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitlt", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitge", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"waitle", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"duck", OPERAND_BYTES(0)},
{"unduck", OPERAND_BYTES(0)},
{"testx", UNIMPLEMENTED},
{"setlg", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"setgl", OPERAND_BYTES(5) | OPERAND(0, o_variable) | OPERAND(1, o_dword)},
{"throw", UNIMPLEMENTED},
{"setsrcdatafield", OPERAND_BYTES(3) | OPERAND(0, o_variable) | OPERAND(1, o_variable) | OPERAND(2, o_variable)},
{"stop_trk", OPERAND_BYTES(1) | OPERAND(0, o_variable)},
{"setchanreg", UNIMPLEMENTED},
{"play_note", UNIMPLEMENTED},
{"stop_note", UNIMPLEMENTED},
{"kill_note", UNIMPLEMENTED},
{"smart_index", OPERAND_BYTES(2) | OPERAND(0, o_variable) | OPERAND(1, o_variable)},
{"note_on_loop", OPERAND_BYTES(1) | OPERAND(0, o_variable)}
};
#define TSOVariableCount 82
static const variable_t TSOVariables[] = {
{"arg0", 0x00},
{"arg1", 0x01},
{"arg2", 0x02},
{"arg3", 0x03},
{"arg4", 0x04},
{"v1", 0x05},
{"v2", 0x06},
{"v3", 0x07},
{"v4", 0x08},
{"v5", 0x09},
{"v6", 0x0A},
{"v7", 0x0B},
{"v8", 0x0C},
{"h1", 0x0D},
{"h2", 0x0E},
{"h3", 0x0F},
{"argstype", 0x10},
{"trackdatasource", 0x11},
{"patch", 0x12},
{"priority", 0x13},
{"vol", 0x14},
{"extvol", 0x15},
{"pan", 0x16},
{"pitch", 0x17},
{"paused", 0x18},
{"fxtype", 0x19},
{"fxlevel", 0x1a},
{"duckpri", 0x1b},
{"Is3d", 0x1c},
{"IsHeadRelative", 0x1d},
{"MinDistance", 0x1e},
{"MaxDistance", 0x1f},
{"X", 0x20},
{"Y", 0x21},
{"Z", 0x22},
{"attack", 0x23},
{"decay", 0x24},
{"IsStreamed", 0x25},
{"bufsizemult", 0x26},
{"fade_dest", 0x27},
{"fade_var", 0x28},
{"fade_speed", 0x29},
{"fade_on", 0x2a},
{"Preload", 0x2b},
{"isplaying", 0x2c},
{"whattodowithupdate", 0x2d},
{"tempo", 0x2e},
{"target", 0x2f},
{"ctrlgroup", 0x30},
{"interrupt", 0x31},
{"ispositioned", 0x32},
{"AppObjectId", 0x34},
{"callbackarg", 0x35},
{"pitchrandmin", 0x36},
{"pitchrandmax", 0x37},
{"spl", 0x38},
{"sem", 0x39},
{"starttrackid", 0x3a},
{"endtrackid", 0x3b},
{"startdelay", 0x3c},
{"fadeinspeed", 0x3d},
{"fadeoutspeed", 0x3e},
{"hitlist", 0x3f},
{"SimSpeed", 0x64},
{"test_g1", 0x65},
{"test_g2", 0x66},
{"test_g3", 0x67},
{"test_g4", 0x68},
{"test_g5", 0x69},
{"test_g6", 0x6a},
{"test_g7", 0x6b},
{"test_g8", 0x6c},
{"test_g9", 0x6d},
{"main_songnum", 0x6e},
{"main_musichitlistid", 0x6f},
{"campfire_nexttrack", 0x70},
{"campfire_busy", 0x71},
{"main_duckpri", 0x7b},
{"main_vol", 0x7c},
{"main_fxtype", 0x7d},
{"main_fxlevel", 0x7e},
{"main_pause", 0x7f},
};
#define TS1VariableCount 87
static const variable_t TS1Variables[] = {
{"arg0", 0x00},
{"arg1", 0x01},
{"arg2", 0x02},
{"arg3", 0x03},
{"arg4", 0x04},
{"v1", 0x05},
{"v2", 0x06},
{"v3", 0x07},
{"v4", 0x08},
{"v5", 0x09},
{"v6", 0x0a},
{"v7", 0x0b},
{"v8", 0x0c},
{"h1", 0x0d},
{"h2", 0x0e},
{"h3", 0x0f},
{"priority", 0x11},
{"vol", 0x12},
{"extvol", 0x13},
{"pan", 0x14},
{"pitch", 0x15},
{"paused", 0x16},
{"fxtype", 0x17},
{"fxlevel", 0x18},
{"duckpri", 0x19},
{"Is3d", 0x1a},
{"IsHeadRelative", 0x1b},
{"MinDistance", 0x1c},
{"MaxDistance", 0x1d},
{"X", 0x1e},
{"Y", 0x1f},
{"Z", 0x20},
{"filter_type", 0x21},
{"filter_cutoff", 0x22},
{"filter_level", 0x23},
{"attack", 0x24},
{"decay", 0x25},
{"IsStreamed", 0x26},
{"BufSizeMult", 0x27},
{"fade_dest", 0x28},
{"fade_var", 0x29},
{"fade_speed", 0x2a},
{"Preload", 0x2b},
{"IsLooped", 0x2c},
{"fade_on", 0x2d},
{"isplaying", 0x2e},
{"source", 0x2f},
{"patch", 0x32},
{"WhatToDoWithUpdate", 0x33},
{"tempo", 0x34},
{"target", 0x35},
{"mutegroup", 0x36},
{"interrupt", 0x37},
{"IsPositioned", 0x38},
{"Spl", 0x39},
{"MultipleInstances", 0x3a},
{"AssociatedTrack1", 0x3b},
{"AssociatedTrack2", 0x3c},
{"AssociatedTrack3", 0x3d},
{"AssociatedTrack4", 0x3e},
{"AssociatedTrack5", 0x3f},
{"AssociatedTrack6", 0x40},
{"AssociatedTrack7", 0x41},
{"AssociatedTrack8", 0x42},
{"SimSpeed", 0x64},
{"test_g1", 0x65},
{"test_g2", 0x66},
{"test_g3", 0x67},
{"test_g4", 0x68},
{"test_g5", 0x69},
{"test_g6", 0x6a},
{"test_g7", 0x6b},
{"test_g8", 0x6c},
{"test_g9", 0x6d},
{"main_songnum", 0x6e},
{"main_musichitlistid", 0x6f},
{"campfire_nexttrack", 0x70},
{"campfire_busy", 0x71},
{"main_duckpri", 0x7b},
{"main_vol", 0x7c},
{"main_fxtype", 0x7d},
{"main_fxlevel", 0x7e},
{"main_pause", 0x7f},
};
#define ConstantCount 72
static const variable_t Constants[] = {
{"duckpri_always", 0x0},
{"duckpri_low", 0xa},
{"duckpri_normal", 0x14},
{"duckpri_high", 0x1e},
{"duckpri_higher", 0x28},
{"duckpri_evenhigher", 0x32},
{"duckpri_never", 0x64},
{"spl_infinite", 0x0},
{"spl_loud", 0xa},
{"spl_normal", 0x14},
{"spl_quiet", 0x64},
{"Instance", 0x0},
{"Gender", 0x1},
{"GroupMusic", 0x1},
{"GroupDialogMain", 0x2},
{"GroupDialogOverlay", 0x3},
{"PchDishwasherClose", 0x32},
{"PchDishwasherLoad", 0x33},
{"PchDishwasherLoad2", 0x34},
{"PchDishwasherOpen", 0x35},
{"PchDishwasherTurnDial", 0x39},
{"PchDishwasherTurnDial2", 0x3a},
{"TrkRadioStationCountry", 0x104},
{"TrkRadioStationBossaNova", 0x10e},
{"TrkRadioStationClassical", 0x10d},
{"TrkRadioStationRock", 0x118},
{"kSndobPlay", 1},
{"kSndobStop", 2},
{"kSndobKill", 3},
{"kSndobUpdate", 4},
{"kSndobSetVolume", 5},
{"kSndobSetPitch", 6},
{"kSndobSetPan", 7},
{"kSndobSetPosition", 8},
{"kSndobSetFxType", 9},
{"kSndobSetFxLevel", 10},
{"kSndobPause", 11},
{"kSndobUnpause", 12},
{"kSndobLoad", 13},
{"kSndobUnload", 14},
{"kSndobCache", 15},
{"kSndobUncache", 16},
{"kSndobCancelNote", 19},
{"kPlayPiano", 43},
{"kSetMusicMode", 36},
{"kLive", 0},
{"kBuy", 1},
{"kBuild", 2},
{"kHood", 3},
{"kFrontEnd", 4},
{"kGroupSfx", 1},
{"kGroupMusic", 2},
{"kGroupVox", 3},
{"kAction", 1000},
{"kComedy", 1001},
{"kRomance", 1002},
{"kNews", 1003},
{"kCountry", 1004},
{"kRock", 1005},
{"kJazz", 1006},
{"kClassical", 1007},
{"kArgsNormal", 0},
{"kArgsVolPan", 1},
{"kArgsIdVolPan", 2},
{"kArgsXYZ", 3},
{"kKillAll", 20},
{"kPause", 21},
{"kUnpause", 22},
{"kKillInstance", 23},
{"kTurnOnTv", 30},
{"kTurnOffTv", 31},
{"kUpdateSourceVolPan", 32},
};
static const uint8_t ObjectHeader[] = {
0x7F, 0x45, 0x4C, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00,
0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
0x19, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00
};

View file

@ -0,0 +1,50 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_tga.c - 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 <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "read_tga.h"
#ifndef read_uint32
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#endif
int tga_read_header(tgaheader_t * TGAHeader, const uint8_t * Buffer, size_t FileSize){
unsigned padding;
if(FileSize < ?) return 0;
TGAHeader->IDLength = read_uint8(Buffer);
TGAHeader->ColorMapType = read_uint8(Buffer+1);
TGAHeader->ImageType = read_uint8(Buffer+2);
/* Color map */
TGAHeader->FirstEntry = read_uint16(Buffer+3);
TGAHeader->ColorMapLength = read_uint16(Buffer+5);
TGAHeader->EntrySize = read_uint8(Buffer+7);
/* Image */
TGAHeader->XOrigin = read_uint16(Buffer+8);
TGAHeader->YOrigin = read_uint16(Buffer+10);
TGAHeader->Width = read_uint16(Buffer+12);
TGAHeader->Height = read_uint16(Buffer+14);
TGAHeader->ImageDepth = read_uint8(Buffer+16);
TGAHeader->Descriptor = read_uint8(Buffer+17);
return 1;
}

View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_tga.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.
*/

10644
library/formats/tga/tsov2.txt Normal file

File diff suppressed because it is too large Load diff

17
library/formats/uis/uis.c Normal file
View file

@ -0,0 +1,17 @@
/*
FileHandler - General-purpose file handling library for Niotso
uis.c - 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.
*/

34
library/formats/uis/uis.h Normal file
View file

@ -0,0 +1,34 @@
/*
FileHandler - General-purpose file handling library for Niotso
uis.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.
*/
enum UISTagType {
UIS_Type_Button,
UIS_Type_FormattedText,
UIS_Type_ListBox,
UIS_Type_ProgressBar,
UIS_Type_Slider,
UIS_Type_Text,
UIS_Type_TextEdit,
UIS_Type_Image,
UIS_Type_String,
UIS_Type_Custom
};
typedef struct {
UISTagType TagType;
} UISTag;

View file

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 2.6)
project(utk)
set(UTK_SOURCES
read_utk.c
utkdecode.c
)
add_executable(utkdecode ${UTK_SOURCES})

View file

@ -0,0 +1,335 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_utk.c - Copyright (c) 2011-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 <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "read_utk.h"
#ifndef read_int32
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#endif
#ifndef write_int32
#define write_uint16(dest, src) do {\
(dest)[0] = ((src)&0x00FF)>>(8*0); \
(dest)[1] = ((src)&0xFF00)>>(8*1); \
} while(0)
#endif
#ifndef round
#define round(x) ((x) >= 0 ? (x)+0.5 : (x)-0.5)
#endif
#ifndef clamp
#define clamp(x, low, high) ((x) < low ? low : (x) > high ? high : (x))
#endif
#ifndef min
#define min(x, y) ((x) < (y) ? (x) : (y))
#endif
static uint8_t ReadBits(utkcontext_t *ctx, uint8_t bits);
static void InitUTKParameters(utkcontext_t *ctx);
static void DecodeFrame(utkcontext_t *ctx);
static void GenerateExcitation(utkcontext_t *ctx, int Voiced, float * Window, int Interval);
static void Synthesize(utkcontext_t *ctx, unsigned Sample, unsigned Blocks);
static void RCtoLPC(const float *__restrict RC, float *__restrict LPC);
static const float UTKCosine[64] = {
0,
-.99677598476409912109375, -.99032700061798095703125, -.983879029750823974609375, -.977430999279022216796875,
-.970982015132904052734375, -.964533984661102294921875, -.958085000514984130859375, -.9516370296478271484375,
-.930754005908966064453125, -.904959976673126220703125, -.879167020320892333984375, -.853372991085052490234375,
-.827579021453857421875, -.801786005496978759765625, -.775991976261138916015625, -.75019800662994384765625,
-.724404990673065185546875, -.6986110210418701171875, -.6706349849700927734375, -.61904799938201904296875,
-.567460000514984130859375, -.515873014926910400390625, -.4642859995365142822265625, -.4126980006694793701171875,
-.361110985279083251953125, -.309523999691009521484375, -.257937014102935791015625, -.20634900033473968505859375,
-.1547619998455047607421875, -.10317499935626983642578125, -.05158700048923492431640625,
0,
+.05158700048923492431640625, +.10317499935626983642578125, +.1547619998455047607421875, +.20634900033473968505859375,
+.257937014102935791015625, +.309523999691009521484375, +.361110985279083251953125, +.4126980006694793701171875,
+.4642859995365142822265625, +.515873014926910400390625, +.567460000514984130859375, +.61904799938201904296875,
+.6706349849700927734375, +.6986110210418701171875, +.724404990673065185546875, +.75019800662994384765625,
+.775991976261138916015625, +.801786005496978759765625, +.827579021453857421875, +.853372991085052490234375,
+.879167020320892333984375, +.904959976673126220703125, +.930754005908966064453125, +.9516370296478271484375,
+.958085000514984130859375, +.964533984661102294921875, +.970982015132904052734375, +.977430999279022216796875,
+.983879029750823974609375, +.99032700061798095703125, +.99677598476409912109375
};
static const uint8_t UTKCodebook[512] = {
4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 17,
4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 21,
4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 18,
4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 25,
4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 17,
4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 22,
4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 18,
4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 0,
4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 17,
4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 21,
4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 18,
4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 26,
4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 17,
4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 22,
4, 6, 5, 9, 4, 6, 5, 13, 4, 6, 5, 10, 4, 6, 5, 18,
4, 6, 5, 9, 4, 6, 5, 14, 4, 6, 5, 10, 4, 6, 5, 2,
4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 23,
4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 27,
4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 24,
4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 1,
4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 23,
4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 28,
4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 24,
4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 3,
4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 23,
4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 27,
4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 24,
4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 1,
4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 23,
4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 28,
4, 11, 7, 15, 4, 12, 8, 19, 4, 11, 7, 16, 4, 12, 8, 24,
4, 11, 7, 15, 4, 12, 8, 20, 4, 11, 7, 16, 4, 12, 8, 3
};
static const uint8_t UTKCodeSkips[29] = {8,7,8,7,2,2,2,3,3,4,4,3,3,5,5,4,4,6,6,5,5,7,7,6,6,8,8,7,7};
int utk_read_header(utkheader_t * UTKHeader, const uint8_t * Buffer, size_t FileSize)
{
if(FileSize < 32) return 0;
memcpy(&UTKHeader->sID, Buffer, 4);
UTKHeader->dwOutSize = read_uint32(Buffer+4);
UTKHeader->dwWfxSize = read_uint32(Buffer+8);
UTKHeader->wFormatTag = read_uint16(Buffer+12);
UTKHeader->nChannels = read_uint16(Buffer+14);
UTKHeader->nSamplesPerSec = read_uint32(Buffer+16);
UTKHeader->nAvgBytesPerSec = read_uint32(Buffer+20);
UTKHeader->nBlockAlign = read_uint16(Buffer+24);
UTKHeader->wBitsPerSample = read_uint16(Buffer+26);
UTKHeader->cbSize = read_uint32(Buffer+28);
if(memcmp(UTKHeader->sID, "UTM0", 4) ||
UTKHeader->wFormatTag != 1 ||
UTKHeader->nChannels != 1 ||
UTKHeader->nSamplesPerSec < 8000 || UTKHeader->nSamplesPerSec > 192000 ||
!(UTKHeader->nSamplesPerSec%8000==0 || UTKHeader->nSamplesPerSec%11025==0) ||
UTKHeader->wBitsPerSample != 16 ||
UTKHeader->nBlockAlign != UTKHeader->nChannels*(UTKHeader->wBitsPerSample>>3) ||
UTKHeader->nAvgBytesPerSec != UTKHeader->nSamplesPerSec*UTKHeader->nBlockAlign ||
UTKHeader->dwOutSize%UTKHeader->nBlockAlign != 0 ||
UTKHeader->cbSize != 0
) return 0;
UTKHeader->Frames = UTKHeader->dwOutSize/UTKHeader->nBlockAlign;
UTKHeader->UTKDataSize = FileSize - 32;
return 1;
}
int utk_decode(const uint8_t *__restrict InBuffer, uint8_t *__restrict OutBuffer, size_t InSize, size_t Samples){
utkcontext_t p;
p.InData = InBuffer;
p.InDataEnd = InBuffer + InSize;
InitUTKParameters(&p);
while(Samples){
int i, BlockSize = min(Samples, 432);
DecodeFrame(&p);
for(i=0; i<BlockSize; i++){
int value = round(p.DecompressedFrame[i]);
value = clamp(value, -32768, 32767);
write_uint16(OutBuffer, value);
OutBuffer += 2;
}
Samples -= BlockSize;
}
return 1;
}
static uint8_t ReadBits(utkcontext_t *ctx, uint8_t bits){
unsigned value = ctx->UnreadBitsValue & (255>>(8-bits));
ctx->UnreadBitsValue >>= bits;
ctx->UnreadBitsCount -= bits;
if(ctx->UnreadBitsCount < 8 && ctx->InData != ctx->InDataEnd){
ctx->UnreadBitsValue |= *(ctx->InData++) << ctx->UnreadBitsCount;
ctx->UnreadBitsCount += 8;
}
return value;
}
static void InitUTKParameters(utkcontext_t *ctx){
int i;
float base;
ctx->UnreadBitsValue = *(ctx->InData++);
ctx->UnreadBitsCount = 8;
ctx->HalvedExcitation = ReadBits(ctx, 1);
ctx->VoicedThreshold = 32 - ReadBits(ctx, 4);
ctx->InnovationPower[0] = (ReadBits(ctx, 4)+1) * 8; /* significand */
base = 1.04f + (float)ReadBits(ctx, 6)/1000;
for(i=1; i<64; i++)
ctx->InnovationPower[i] = ctx->InnovationPower[i-1]*base;
memset(ctx->RC, 0, 12*sizeof(float));
memset(ctx->History, 0, 12*sizeof(float));
memset(ctx->Delay, 0, 324*sizeof(float));
}
static void DecodeFrame(utkcontext_t *ctx){
int i,j;
float Excitation[118]; /* includes 5 0-valued samples to both the left and the right */
float RCDelta[12];
int Voiced = 0;
memset(&Excitation[0], 0, 5*sizeof(float));
memset(&Excitation[113], 0, 5*sizeof(float));
for(i=0; i<12; i++){
unsigned result = ReadBits(ctx, (i<4) ? 6 : 5);
if(i==0 && result < ctx->VoicedThreshold) Voiced++;
RCDelta[i] = (UTKCosine[result + ((i<4)?0:16)] - ctx->RC[i])/4;
}
for(i=0; i<4; i++){
float PitchGain, InnovationGain;
int Phase = ReadBits(ctx, 8);
PitchGain = (float)ReadBits(ctx, 4)/15;
InnovationGain = ctx->InnovationPower[ReadBits(ctx, 6)];
if(!ctx->HalvedExcitation){
GenerateExcitation(ctx, Voiced, &Excitation[5], 1);
}else{
/* Fill the excitation window with half as many samples and interpolate the rest */
int Alignment = ReadBits(ctx, 1); /* whether to fill the even or odd samples */
int FillWithZero = ReadBits(ctx, 1);
GenerateExcitation(ctx, Voiced, &Excitation[5+Alignment], 2);
if(FillWithZero){
for(j=0; j<108; j+=2)
Excitation[5 + (1-Alignment) + j] = 0.0;
}else{
/* Use sinc interpolation with 6 neighboring samples */
float *x = &Excitation[5 + (1-Alignment)];
for(j=0; j<54; j++, x+=2)
*x = (x[-1]+x[+1]) * .5973859429f
- (x[-3]+x[+3]) * .1145915613f
+ (x[-5]+x[+5]) * .0180326793f;
InnovationGain /= 2;
}
}
/* If 216-Phase is negative on the first subframe, it will read into RC and History
as the reference decoder does, which have been initialized to 0 in InitUTKParameters(). */
for(j=0; j<108; j++)
ctx->DecompressedFrame[108*i + j] = InnovationGain*Excitation[5+j] + PitchGain*ctx->Delay[108*i + j + (216-Phase)];
for(j=0; j<108; j++)
ctx->WhatIsThis[108*i + j] = PitchGain*ctx->Delay[108*i + j + (216-Phase)];
}
memcpy(ctx->Delay, &ctx->DecompressedFrame[108], 324*sizeof(float));
for(i=0; i<4; i++){
/* Linearly interpolate the reflection coefficients for the current subframe */
for(j=0; j<12; j++)
ctx->RC[j] += RCDelta[j];
Synthesize(ctx, i*12, (i!=3) ? 12 : 396);
}
}
static void GenerateExcitation(utkcontext_t *ctx, int Voiced, float * Window, int Interval){
if(Voiced){
int Table = 0;
int i = 0;
while(i<108){
unsigned code = UTKCodebook[(Table<<8) | (ctx->UnreadBitsValue&0xFF)];
Table = (code<2 || code>8);
ReadBits(ctx, UTKCodeSkips[code]);
if(code >= 4){
/* Fill a sample with a value specified by the code; magnitude is limited to 6.0 */
Window[i] = (code-1)/4;
if(code&1)
Window[i] *= -1.0;
i += Interval;
}else if(code >= 2){
/* Fill between 7 and 70 samples with 0s */
int x = ReadBits(ctx, 6) + 7;
x = min(x, (108 - i)/Interval);
while(x--){
Window[i] = 0.0;
i += Interval;
}
}else{
/* Fill a sample with a custom value with magnitude >= 7.0 */
Window[i] = 7.0;
while(ReadBits(ctx, 1))
Window[i]++;
if(!ReadBits(ctx, 1))
Window[i] *= -1;
i += Interval;
}
}
}else{
/* Unvoiced: restrict all samples to 0.0, -2.0, or +2.0 without using the codebook */
int i;
for(i=0; i<108; i+=Interval){
if(!ReadBits(ctx, 1)) Window[i] = 0.0;
else if(!ReadBits(ctx, 1)) Window[i] = -2.0;
else Window[i] = 2.0;
}
}
}
static void Synthesize(utkcontext_t *ctx, size_t Sample, size_t Samples){
float LPC[12];
int offset = -1;
RCtoLPC(ctx->RC, LPC);
while(Samples--){
int i;
for(i=0; i<12; i++){
if(++offset == 12) offset = 0;
ctx->DecompressedFrame[Sample] += LPC[i] * ctx->History[offset];
}
ctx->History[offset--] = ctx->DecompressedFrame[Sample++];
}
}
static void RCtoLPC(const float *__restrict RC, float *__restrict LPC){
int i,j;
float RCTemp[12], LPCTemp[12];
RCTemp[0] = 1.0;
memcpy(&RCTemp[1], RC, 11*sizeof(float));
for(i=0; i<12; i++){
LPC[i] = 0.0;
for(j=11; j>=0; j--){
LPC[i] -= RC[j] * RCTemp[j];
if(j != 11)
RCTemp[j+1] = RCTemp[j] + RC[j] * LPC[i];
}
RCTemp[0] = LPCTemp[i] = LPC[i];
for(j=0; j<i; j++)
LPC[i] -= LPCTemp[i-j-1] * LPC[j];
}
}

View file

@ -0,0 +1,59 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_utk.h - Copyright (c) 2011-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.
*/
typedef struct
{
char sID[4];
uint32_t dwOutSize;
uint32_t dwWfxSize;
/* WAVEFORMATEX */
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t wBitsPerSample;
uint32_t cbSize;
unsigned Frames;
unsigned UTKDataSize;
} utkheader_t;
typedef struct {
const uint8_t *InData, *InDataEnd;
unsigned UnreadBitsValue, UnreadBitsCount;
int HalvedExcitation;
unsigned VoicedThreshold;
float InnovationPower[64];
float RC[12];
float History[12];
float Delay[324];
float DecompressedFrame[432];
float WhatIsThis[432];
} utkcontext_t;
#ifdef __cplusplus
extern "C" {
#endif
int utk_read_header(utkheader_t * UTKHeader, const uint8_t * Buffer, size_t FileSize);
int utk_decode(const uint8_t *__restrict InBuffer, uint8_t *__restrict OutBuffer, size_t InSize, size_t Samples);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,164 @@
/*
utkdecode.c - Copyright (c) 2011-2012 Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include "read_utk.h"
#ifndef write_int32
#define write_uint32(dest, src) do {\
(dest)[0] = ((src)&0x000000FF)>>(8*0); \
(dest)[1] = ((src)&0x0000FF00)>>(8*1); \
(dest)[2] = ((src)&0x00FF0000)>>(8*2); \
(dest)[3] = ((src)&0xFF000000)>>(8*3); \
} while(0)
#define write_uint16(dest, src) do {\
(dest)[0] = ((src)&0x00FF)>>(8*0); \
(dest)[1] = ((src)&0xFF00)>>(8*1); \
} while(0)
#endif
static FILE * hFile = NULL;
static uint8_t * UTKData = NULL;
static uint8_t * WaveData = NULL;
static void Shutdown_M(const char * Message){
fprintf(stderr, "utkdecode: error: %s.\n", Message);
free(WaveData);
free(UTKData);
if(hFile)
fclose(hFile);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]){
int overwrite = 0;
const char *InFile, *OutFile;
size_t FileSize;
utkheader_t UTKHeader;
clock_t BeginningTime, EndingTime;
if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
printf("Usage: utkdecode [-f] infile outfile\n"
" -or- utkdecode infile\n"
"Transcode or play a Maxis UTalk sound.\n"
"Use -f to force overwriting without confirmation.\n"
"\n"
"Report bugs to <X-Fi6@phppoll.org>.\n"
"utkdecode is maintained by the Niotso project.\n"
"Home page: <http://www.niotso.org/>\n");
return 0;
}
if(argc >= 4 && !strcmp(argv[1], "-f")){
overwrite++;
InFile = argv[2];
OutFile = argv[3];
}else{
InFile = argv[1];
OutFile = argv[2];
}
/****
** Open the file and read in entire contents to memory
*/
hFile = fopen(InFile, "rb");
if(hFile == NULL)
Shutdown_M("The specified input file does not exist or could not be opened for reading");
fseek(hFile, 0, SEEK_END);
FileSize = ftell(hFile);
if(FileSize < 32)
Shutdown_M("Not a valid UTK file");
fseek(hFile, 0, SEEK_SET);
UTKData = malloc(FileSize);
if(UTKData == NULL)
Shutdown_M("Memory for this file could not be allocated");
if(fread(UTKData, 1, FileSize, hFile) != FileSize)
Shutdown_M("The input file could not be read");
fclose(hFile); hFile = NULL;
/****
** Transcode the data from UTK to LPCM
*/
if(!utk_read_header(&UTKHeader, UTKData, FileSize))
Shutdown_M("Not a valid UTK file");
if(argc >= 3){ /* Transcode */
WaveData = malloc(44+UTKHeader.dwOutSize);
if(WaveData == NULL)
Shutdown_M("Memory for this file could not be allocated");
BeginningTime = clock();
if(!utk_decode(UTKData+32, WaveData+44, FileSize-32, UTKHeader.Frames))
Shutdown_M("Memory for this file could not be allocated");
EndingTime = clock();
free(UTKData); UTKData = NULL;
/****
** Write the Microsoft WAV header
*/
write_uint32(WaveData, 0x46464952); /* "RIFF" */
write_uint32(WaveData+4, 36+UTKHeader.dwOutSize);
write_uint32(WaveData+8, 0x45564157); /* "WAVE" */
write_uint32(WaveData+12, 0x20746d66); /* "fmt " */
write_uint32(WaveData+16, 16);
write_uint16(WaveData+20, 1);
write_uint16(WaveData+22, UTKHeader.nChannels);
write_uint32(WaveData+24, UTKHeader.nSamplesPerSec);
write_uint32(WaveData+28, UTKHeader.nAvgBytesPerSec);
write_uint16(WaveData+32, UTKHeader.nBlockAlign);
write_uint16(WaveData+34, UTKHeader.wBitsPerSample);
write_uint32(WaveData+36, 0x61746164); /* "data" */
write_uint32(WaveData+40, UTKHeader.dwOutSize);
/****
** Write the contents to the output file
*/
if(!overwrite){
hFile = fopen(OutFile, "rb");
if(hFile != NULL){
/* File exists */
char c;
fclose(hFile); hFile = NULL;
printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile);
c = getchar();
if(c != 'y' && c != 'Y'){
printf("\n");
Shutdown_M("Aborted");
}
}
}
hFile = fopen(OutFile, "wb");
if(hFile == NULL)
Shutdown_M("The output file could not be opened for writing");
printf("Extracted %u bytes in %.2f seconds.\n", (unsigned) UTKHeader.dwOutSize,
((float)(EndingTime - BeginningTime))/CLOCKS_PER_SEC);
fwrite(WaveData, 1, 44+UTKHeader.dwOutSize, hFile);
free(WaveData);
fclose(hFile);
}
return 0;
}

View file

@ -0,0 +1,57 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_wav.c - 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 <stdint.h>
#include <string.h>
#include "read_wav.h"
#define WAVE_FORMAT_PCM 1
#ifndef read_uint32
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#endif
int wav_read_header(wavheader_t * WAVHeader, const uint8_t * Buffer, size_t FileSize){
if(FileSize < 45) return 0;
WAVHeader->sID = read_uint32(Buffer);
WAVHeader->Size = read_uint32(Buffer+4);
WAVHeader->DataType = read_uint32(Buffer+8);
WAVHeader->FmtID = read_uint32(Buffer+12);
WAVHeader->FmtSize = read_uint32(Buffer+16);
WAVHeader->wFormatTag = read_uint16(Buffer+20);
WAVHeader->nChannels = read_uint16(Buffer+22);
WAVHeader->nSamplesPerSec = read_uint32(Buffer+24);
WAVHeader->nAvgBytesPerSec = read_uint32(Buffer+28);
WAVHeader->nBlockAlign = read_uint16(Buffer+32);
WAVHeader->wBitsPerSample = read_uint16(Buffer+34);
WAVHeader->DataID = read_uint32(Buffer+36);
WAVHeader->DataSize = read_uint32(Buffer+40);
if(WAVHeader->sID != 0x46464952 || WAVHeader->Size != FileSize-8 || WAVHeader->DataType != 0x45564157 ||
WAVHeader->FmtID != 0x20746D66 || WAVHeader->FmtSize != 16 || WAVHeader->wFormatTag != WAVE_FORMAT_PCM ||
WAVHeader->nChannels < 1 || WAVHeader->nChannels > 2 || WAVHeader->nSamplesPerSec == 0 ||
(WAVHeader->nSamplesPerSec%8000 != 0 && WAVHeader->nSamplesPerSec%11025 != 0) || WAVHeader->nSamplesPerSec > 48000 ||
WAVHeader->nAvgBytesPerSec != WAVHeader->nSamplesPerSec * WAVHeader->nBlockAlign ||
WAVHeader->nBlockAlign != WAVHeader->nChannels * WAVHeader->wBitsPerSample >> 3 ||
(WAVHeader->wBitsPerSample != 8 && WAVHeader->wBitsPerSample != 16) || WAVHeader->DataID != 0x61746164 ||
WAVHeader->DataSize != FileSize - 44 || WAVHeader->DataSize % WAVHeader->nBlockAlign != 0
) return 0;
return 1;
}

View file

@ -0,0 +1,44 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_wav.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.
*/
typedef struct
{
uint32_t sID;
uint32_t Size;
uint32_t DataType;
uint32_t FmtID;
uint32_t FmtSize;
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t wBitsPerSample;
uint32_t DataID;
uint32_t DataSize;
} wavheader_t;
#ifdef __cplusplus
extern "C" {
#endif
int wav_read_header(wavheader_t * WAVHeader, const uint8_t * Buffer, size_t FileSize);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 2.6)
project(xa)
set(XA_SOURCES
read_xa.c
xadecode.c
)
add_executable(xadecode ${XA_SOURCES})

View file

@ -0,0 +1,147 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_xa.c - Copyright (c) 2011 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 <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#include "read_xa.h"
#define HINIBBLE(byte) ((byte) >> 4)
#define LONIBBLE(byte) ((byte) & 0x0F)
#ifndef read_int32
#define read_uint32(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)) | ((x)[2]<<(8*2)) | ((x)[3]<<(8*3)))
#define read_uint16(x) (unsigned)(((x)[0]<<(8*0)) | ((x)[1]<<(8*1)))
#endif
size_t xa_compressed_size(size_t Frames, size_t Channels)
{
/* This function calculates the size of compressed XA data with known frames and channels, as such:
** Channels * (ceil(Frames/2) + ceil(Frames/28))
** | a | | b |
**
** a = The space required for all sample bytes in the XA data for a single channel (1 byte every 2 frames)
** b = The space required for all control bytes in the XA data for a single channel (1 byte every 28 frames)
** (a+b) is multiplied by Channels to produce the final size
**
** This source package assumes a partial block at the end of the XA data is legal but a partial frame is not.
*/
unsigned SingleChannelData = (((Frames+1)>>1) + (Frames+27)/28);
if(Frames > UINT_MAX-27) return 0;
if(UINT_MAX/SingleChannelData < Channels) return 0;
return Channels*SingleChannelData;
}
int xa_read_header(xaheader_t * XAHeader, const uint8_t * Buffer, size_t FileSize)
{
if(FileSize < 24) return 0;
memcpy(&XAHeader->szID, Buffer, 4);
XAHeader->dwOutSize = read_uint32(Buffer+4);
XAHeader->wFormatTag = read_uint16(Buffer+8);
XAHeader->nChannels = read_uint16(Buffer+10);
XAHeader->nSamplesPerSec = read_uint32(Buffer+12);
XAHeader->nAvgBytesPerSec = read_uint32(Buffer+16);
XAHeader->nBlockAlign = read_uint16(Buffer+20);
XAHeader->wBitsPerSample = read_uint16(Buffer+22);
if(XAHeader->szID[0] != 'X' || XAHeader->szID[1] != 'A' || XAHeader->szID[3] != '\0' ||
XAHeader->wFormatTag != 1 ||
XAHeader->nChannels == 0 || XAHeader->nChannels > 8 ||
XAHeader->nSamplesPerSec < 8000 || XAHeader->nSamplesPerSec > 192000 ||
!(XAHeader->nSamplesPerSec%8000==0 || XAHeader->nSamplesPerSec%11025==0) ||
XAHeader->wBitsPerSample != 16 ||
XAHeader->nBlockAlign != XAHeader->nChannels*(XAHeader->wBitsPerSample>>3) ||
XAHeader->nAvgBytesPerSec != XAHeader->nSamplesPerSec*XAHeader->nBlockAlign ||
XAHeader->dwOutSize%XAHeader->nBlockAlign != 0
) return 0;
XAHeader->Frames = XAHeader->dwOutSize/XAHeader->nBlockAlign;
XAHeader->XADataSize = xa_compressed_size(XAHeader->Frames, XAHeader->nChannels);
if(FileSize-24 < XAHeader->XADataSize)
return 0;
return 1;
}
static __inline int16_t Clip16(int sample)
{
if(sample>=32767) return 32767;
else if(sample<=-32768) return -32768;
else return (int16_t) sample;
}
typedef struct {
int PrevSample, CurSample;
int divisor; /* residual right-shift value */
int c1, c2; /* predictor coefficients */
} channel_t;
static const int16_t XATable[] =
{
0, 240, 460, 392,
0, 0, -208, -220,
0, 1, 3, 4,
7, 8, 10, 11,
0, -1, -3, -4
};
int xa_decode(const uint8_t *__restrict InBuffer, uint8_t *__restrict OutBuffer, size_t Frames, size_t Channels)
{
channel_t Channel[8];
memset(Channel, 0, sizeof(Channel));
if(Frames == 0) return 1;
while(1){
unsigned i;
for(i=0; i<Channels; i++){
unsigned byte = *(InBuffer++);
Channel[i].divisor = LONIBBLE(byte)+8;
Channel[i].c1 = XATable[HINIBBLE(byte)];
Channel[i].c2 = XATable[HINIBBLE(byte)+4];
}
for(i=0; i<14; i++){
unsigned j;
for(j=0; j<Channels; j++){
unsigned byte = *(InBuffer++);
int n;
for(n=4; n>=0; n-=4){
int NewValue = byte >> n;
NewValue = (NewValue << 28) >> Channel[j].divisor;
NewValue = (NewValue + Channel[j].CurSample*Channel[j].c1 + Channel[j].PrevSample*Channel[j].c2 + 128) >> 8;
Channel[j].PrevSample = Channel[j].CurSample;
Channel[j].CurSample = Clip16(NewValue);
}
*(OutBuffer++) = Channel[j].PrevSample>>(8*0);
*(OutBuffer++) = Channel[j].PrevSample>>(8*1);
}
if(!--Frames) return 1;
for(j=0; j<Channels; j++){
*(OutBuffer++) = Channel[j].CurSample>>(8*0);
*(OutBuffer++) = Channel[j].CurSample>>(8*1);
}
if(!--Frames) return 1;
}
}
}

View file

@ -0,0 +1,45 @@
/*
FileHandler - General-purpose file handling library for Niotso
read_xa.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.
*/
typedef struct
{
char szID[4];
uint32_t dwOutSize;
/* WAVEFORMATEX */
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t wBitsPerSample;
size_t Frames;
size_t XADataSize;
} xaheader_t;
#ifdef __cplusplus
extern "C" {
#endif
size_t xa_compressed_size(size_t Frames, size_t Channels);
int xa_read_header(xaheader_t * XAHeader, const uint8_t * Buffer, size_t FileSize);
int xa_decode(const uint8_t *__restrict InBuffer, uint8_t *__restrict OutBuffer, size_t Frames, size_t Channels);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,164 @@
/*
xadecode.c - Copyright (c) 2011-2012 Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
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 <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include "read_xa.h"
#ifndef write_int32
#define write_uint32(dest, src) do {\
(dest)[0] = ((src)&0x000000FF)>>(8*0); \
(dest)[1] = ((src)&0x0000FF00)>>(8*1); \
(dest)[2] = ((src)&0x00FF0000)>>(8*2); \
(dest)[3] = ((src)&0xFF000000)>>(8*3); \
} while(0)
#define write_uint16(dest, src) do {\
(dest)[0] = ((src)&0x00FF)>>(8*0); \
(dest)[1] = ((src)&0xFF00)>>(8*1); \
} while(0)
#endif
static FILE * hFile = NULL;
static uint8_t * XAData = NULL;
static uint8_t * WaveData = NULL;
static void Shutdown_M(const char * Message){
fprintf(stderr, "xadecode: error: %s.\n", Message);
free(WaveData);
free(XAData);
if(hFile)
fclose(hFile);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]){
int overwrite = 0;
const char *InFile, *OutFile;
size_t FileSize;
xaheader_t XAHeader;
clock_t BeginningTime, EndingTime;
if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
printf("Usage: xadecode [-f] infile outfile\n"
" -or- xadecode infile\n"
"Transcode or play a Maxis XA sound.\n"
"Use -f to force overwriting without confirmation.\n"
"\n"
"Report bugs to <X-Fi6@phppoll.org>.\n"
"xadecode is maintained by the Niotso project.\n"
"Home page: <http://www.niotso.org/>\n");
return 0;
}
if(argc >= 4 && !strcmp(argv[1], "-f")){
overwrite++;
InFile = argv[2];
OutFile = argv[3];
}else{
InFile = argv[1];
OutFile = argv[2];
}
/****
** Open the file and read in entire contents to memory
*/
hFile = fopen(InFile, "rb");
if(hFile == NULL)
Shutdown_M("The specified input file does not exist or could not be opened for reading");
fseek(hFile, 0, SEEK_END);
FileSize = ftell(hFile);
if(FileSize < 24)
Shutdown_M("Not a valid XA file");
fseek(hFile, 0, SEEK_SET);
XAData = malloc(FileSize);
if(XAData == NULL)
Shutdown_M("Memory for this file could not be allocated");
if(fread(XAData, 1, FileSize, hFile) != FileSize)
Shutdown_M("The input file could not be read");
fclose(hFile); hFile = NULL;
/****
** Transcode the data from XA to LPCM
*/
if(!xa_read_header(&XAHeader, XAData, FileSize))
Shutdown_M("Not a valid XA file");
if(argc >= 3){ /* Transcode */
WaveData = malloc(44+XAHeader.dwOutSize);
if(WaveData == NULL)
Shutdown_M("Memory for this file could not be allocated");
BeginningTime = clock();
if(!xa_decode(XAData+24, WaveData+44, XAHeader.Frames, XAHeader.nChannels))
Shutdown_M("Memory for this file could not be allocated");
EndingTime = clock();
free(XAData); XAData = NULL;
/****
** Write the Microsoft WAV header
*/
write_uint32(WaveData, 0x46464952); /* "RIFF" */
write_uint32(WaveData+4, 36+XAHeader.dwOutSize);
write_uint32(WaveData+8, 0x45564157); /* "WAVE" */
write_uint32(WaveData+12, 0x20746d66); /* "fmt " */
write_uint32(WaveData+16, 16);
write_uint16(WaveData+20, 1);
write_uint16(WaveData+22, XAHeader.nChannels);
write_uint32(WaveData+24, XAHeader.nSamplesPerSec);
write_uint32(WaveData+28, XAHeader.nAvgBytesPerSec);
write_uint16(WaveData+32, XAHeader.nBlockAlign);
write_uint16(WaveData+34, XAHeader.wBitsPerSample);
write_uint32(WaveData+36, 0x61746164); /* "data" */
write_uint32(WaveData+40, XAHeader.dwOutSize);
/****
** Write the contents to the output file
*/
if(!overwrite){
hFile = fopen(OutFile, "rb");
if(hFile != NULL){
/* File exists */
char c;
fclose(hFile); hFile = NULL;
printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile);
c = getchar();
if(c != 'y' && c != 'Y'){
printf("\n");
Shutdown_M("Aborted");
}
}
}
hFile = fopen(OutFile, "wb");
if(hFile == NULL)
Shutdown_M("The output file could not be opened for writing");
printf("Extracted %u bytes in %.2f seconds.\n", (unsigned) XAHeader.dwOutSize,
((float)(EndingTime - BeginningTime))/CLOCKS_PER_SEC);
fwrite(WaveData, 1, 44+XAHeader.dwOutSize, hFile);
free(WaveData);
fclose(hFile);
}
return 0;
}