mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-04 13:47:04 -04:00
zTSO
- Added libraries from formats and libvitaboy
This commit is contained in:
parent
66ce473514
commit
5efdb29315
101 changed files with 11711 additions and 10889 deletions
2
library/formats/AUTHORS
Normal file
2
library/formats/AUTHORS
Normal 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
202
library/formats/Audio.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
52
library/formats/CMakeLists.txt
Normal file
52
library/formats/CMakeLists.txt
Normal 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
15
library/formats/COPYING
Normal 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
58
library/formats/File.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
87
library/formats/FileHandler.hpp
Normal file
87
library/formats/FileHandler.hpp
Normal 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
265
library/formats/Image.cpp
Normal 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
32
library/formats/README
Normal 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
0
library/formats/TODO
Normal file
17
library/formats/Text.cpp
Normal file
17
library/formats/Text.cpp
Normal 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.
|
||||
*/
|
160
library/formats/bmp/read_bmp.c
Normal file
160
library/formats/bmp/read_bmp.c
Normal 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;
|
||||
}
|
53
library/formats/bmp/read_bmp.h
Normal file
53
library/formats/bmp/read_bmp.h
Normal 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
49
library/formats/cst/cst.c
Normal 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
23
library/formats/cst/cst.h
Normal 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;
|
17
library/formats/cur/read_cur.c
Normal file
17
library/formats/cur/read_cur.c
Normal 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.
|
||||
*/
|
17
library/formats/cur/read_cur.h
Normal file
17
library/formats/cur/read_cur.h
Normal 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.
|
||||
*/
|
22
library/formats/far/CMakeLists.txt
Normal file
22
library/formats/far/CMakeLists.txt
Normal 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)
|
24
library/formats/far/config.h
Normal file
24
library/formats/far/config.h
Normal 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
446
library/formats/far/far.c
Normal 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
176
library/formats/far/far.h
Normal 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
|
430
library/formats/far/farextract.c
Normal file
430
library/formats/far/farextract.c
Normal 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;
|
||||
}
|
200
library/formats/far/libfar.svg
Normal file
200
library/formats/far/libfar.svg
Normal 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 |
163
library/formats/far/refpack_dec.c
Normal file
163
library/formats/far/refpack_dec.c
Normal 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
17
library/formats/hit/evt.c
Normal 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
17
library/formats/hit/hit.c
Normal 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
17
library/formats/hit/hot.c
Normal 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
17
library/formats/hit/hsm.c
Normal 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.
|
||||
*/
|
37
library/formats/iff/CMakeLists.txt
Normal file
37
library/formats/iff/CMakeLists.txt
Normal 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)
|
53
library/formats/iff/bcon.c
Normal file
53
library/formats/iff/bcon.c
Normal 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);
|
||||
}
|
91
library/formats/iff/bhav.c
Normal file
91
library/formats/iff/bhav.c
Normal 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);
|
||||
}
|
38
library/formats/iff/cats.c
Normal file
38
library/formats/iff/cats.c
Normal 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
108
library/formats/iff/dgrp.c
Normal 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);
|
||||
}
|
||||
}
|
86
library/formats/iff/fcns.c
Normal file
86
library/formats/iff/fcns.c
Normal 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);
|
||||
}
|
||||
}
|
28
library/formats/iff/glob.c
Normal file
28
library/formats/iff/glob.c
Normal 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
251
library/formats/iff/iff.c
Normal 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
365
library/formats/iff/iff.h
Normal 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
|
173
library/formats/iff/iffexport.c
Normal file
173
library/formats/iff/iffexport.c
Normal 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;
|
||||
}
|
146
library/formats/iff/iffparser.h
Normal file
146
library/formats/iff/iffparser.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
FileHandler - General-purpose file handling library for Niotso
|
||||
iffparser.h - Copyright (c) 2012 Niotso Project <http://niotso.org/>
|
||||
Author(s): Fatbag <X-Fi6@phppoll.org>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "iff.h"
|
||||
|
||||
typedef struct {
|
||||
const uint8_t * Buffer;
|
||||
size_t Size;
|
||||
const uint8_t * StartPos;
|
||||
size_t TotalSize;
|
||||
uint8_t Endian; /* 0 = little, 1 = big */
|
||||
} bytestream;
|
||||
|
||||
static __inline void set_bytestream(bytestream * b, const uint8_t * Buffer, size_t Size){
|
||||
b->Buffer = Buffer;
|
||||
b->Size = Size;
|
||||
b->StartPos = Buffer;
|
||||
b->TotalSize = Size;
|
||||
b->Endian = 0;
|
||||
}
|
||||
|
||||
static __inline uint32_t read_uint32(bytestream * b){
|
||||
unsigned value = (b->Endian == 0) ? read_uint32le(b->Buffer) : read_uint32be(b->Buffer);
|
||||
b->Buffer += 4;
|
||||
b->Size -= 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
static __inline uint16_t read_uint16(bytestream * b){
|
||||
unsigned value = (b->Endian == 0) ? read_uint16le(b->Buffer) : read_uint16be(b->Buffer);
|
||||
b->Buffer += 2;
|
||||
b->Size -= 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
static __inline uint8_t read_uint8(bytestream * b){
|
||||
uint8_t value = b->Buffer[0];
|
||||
b->Buffer += 1;
|
||||
b->Size -= 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
static __inline float read_float(bytestream *b){
|
||||
union { float f; uint32_t v; } value;
|
||||
value.v = read_uint32(b);
|
||||
return value.f;
|
||||
}
|
||||
|
||||
static __inline int skipbytes(bytestream * b, size_t bytes){
|
||||
if(b->Size < bytes) return 0;
|
||||
b->Buffer += bytes; b->Size -= bytes;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __inline int seekto(bytestream * b, size_t Position){
|
||||
if(Position > b->TotalSize) return 0;
|
||||
b->Buffer = b->StartPos + Position;
|
||||
b->Size = b->TotalSize - Position;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static __inline size_t read_c_string(bytestream * b, char ** dest){
|
||||
size_t length;
|
||||
for(length=0; length != b->Size && b->Buffer[length]; length++);
|
||||
if(length == b->Size) return 0;
|
||||
|
||||
if(length != 0){
|
||||
*dest = malloc(length+1);
|
||||
if(*dest == NULL) return 0;
|
||||
strcpy(*dest, (char*) b->Buffer);
|
||||
}
|
||||
|
||||
b->Buffer += length + 1;
|
||||
b->Size -= length + 1;
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
static __inline size_t read_pascal_string(bytestream * b, char ** dest){
|
||||
size_t length;
|
||||
if(!b->Size) return 0;
|
||||
length = b->Buffer[0];
|
||||
if(length >= b->Size) return 0;
|
||||
|
||||
if(length > 0){
|
||||
*dest = malloc(length+1);
|
||||
if(*dest == NULL) return 0;
|
||||
memcpy(*dest, b->Buffer+1, length);
|
||||
(*dest)[length] = 0x00;
|
||||
}
|
||||
|
||||
b->Buffer += 1 + length;
|
||||
b->Size -= 1 + length;
|
||||
return 1 + length;
|
||||
}
|
||||
|
||||
static __inline size_t read_pascal2_string(bytestream * b, char ** dest){
|
||||
size_t length;
|
||||
int countbytes = 1;
|
||||
if(!b->Size) return 0;
|
||||
length = b->Buffer[0];
|
||||
|
||||
if(length > 127){
|
||||
/* 2-byte length */
|
||||
if(b->Size == 1) return 0;
|
||||
length = (length&127) | (b->Buffer[1]<<7);
|
||||
countbytes++;
|
||||
}
|
||||
|
||||
if(countbytes+length > b->Size) return 0;
|
||||
|
||||
if(length != 0){
|
||||
*dest = malloc(length+1);
|
||||
if(*dest == NULL) return 0;
|
||||
memcpy(*dest, b->Buffer+countbytes, length);
|
||||
(*dest)[length] = 0x00;
|
||||
}
|
||||
|
||||
b->Buffer += countbytes + length;
|
||||
b->Size -= countbytes + length;
|
||||
return countbytes + length;
|
||||
}
|
||||
|
||||
static __inline size_t skip_padding(bytestream * b){
|
||||
size_t padding = 0;
|
||||
while(b->Size && b->Buffer[0] == 0xA3){
|
||||
padding++;
|
||||
b->Buffer++;
|
||||
b->Size--;
|
||||
}
|
||||
return padding;
|
||||
}
|
60
library/formats/iff/objf.c
Normal file
60
library/formats/iff/objf.c
Normal 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);
|
||||
}
|
41
library/formats/iff/palt.c
Normal file
41
library/formats/iff/palt.c
Normal 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;
|
||||
}
|
93
library/formats/iff/rsmp.c
Normal file
93
library/formats/iff/rsmp.c
Normal 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
221
library/formats/iff/spr.c
Normal 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
227
library/formats/iff/spr2.c
Normal 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
159
library/formats/iff/str.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
25
library/formats/iff/string.c
Normal file
25
library/formats/iff/string.c
Normal 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);
|
||||
}
|
70
library/formats/iff/tmpl.c
Normal file
70
library/formats/iff/tmpl.c
Normal 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);
|
||||
}
|
||||
}
|
0
library/formats/iff/tprp.c
Normal file
0
library/formats/iff/tprp.c
Normal file
100
library/formats/iff/trcn.c
Normal file
100
library/formats/iff/trcn.c
Normal 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);
|
||||
}
|
0
library/formats/iff/ttab.c
Normal file
0
library/formats/iff/ttab.c
Normal file
17
library/formats/ini/read_ini.c
Normal file
17
library/formats/ini/read_ini.c
Normal 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.
|
||||
*/
|
35
library/formats/resource.rc
Normal file
35
library/formats/resource.rc
Normal 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
BIN
library/formats/tga/elf.dat
Normal file
Binary file not shown.
93
library/formats/tga/elf.txt
Normal file
93
library/formats/tga/elf.txt
Normal 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
|
461
library/formats/tga/hitutils.h
Normal file
461
library/formats/tga/hitutils.h
Normal 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
|
||||
};
|
50
library/formats/tga/read_tga.c
Normal file
50
library/formats/tga/read_tga.c
Normal 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;
|
||||
}
|
17
library/formats/tga/read_tga.h
Normal file
17
library/formats/tga/read_tga.h
Normal 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
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
17
library/formats/uis/uis.c
Normal 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
34
library/formats/uis/uis.h
Normal 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;
|
9
library/formats/utk/CMakeLists.txt
Normal file
9
library/formats/utk/CMakeLists.txt
Normal 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})
|
335
library/formats/utk/read_utk.c
Normal file
335
library/formats/utk/read_utk.c
Normal 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];
|
||||
}
|
||||
}
|
59
library/formats/utk/read_utk.h
Normal file
59
library/formats/utk/read_utk.h
Normal 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
|
164
library/formats/utk/utkdecode.c
Normal file
164
library/formats/utk/utkdecode.c
Normal 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;
|
||||
}
|
57
library/formats/wav/read_wav.c
Normal file
57
library/formats/wav/read_wav.c
Normal 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;
|
||||
}
|
44
library/formats/wav/read_wav.h
Normal file
44
library/formats/wav/read_wav.h
Normal 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
|
9
library/formats/xa/CMakeLists.txt
Normal file
9
library/formats/xa/CMakeLists.txt
Normal 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})
|
147
library/formats/xa/read_xa.c
Normal file
147
library/formats/xa/read_xa.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
45
library/formats/xa/read_xa.h
Normal file
45
library/formats/xa/read_xa.h
Normal 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
|
164
library/formats/xa/xadecode.c
Normal file
164
library/formats/xa/xadecode.c
Normal 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;
|
||||
}
|
14
library/libgldemo/CMakeLists.txt
Normal file
14
library/libgldemo/CMakeLists.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
project(libgldemo)
|
||||
|
||||
if(WIN32)
|
||||
set(LIBGLDEMO_SOURCES wgl.c)
|
||||
else()
|
||||
set(LIBGLDEMO_SOURCES glx.c)
|
||||
add_definitions(-D_POSIX_C_SOURCE=200112)
|
||||
endif()
|
||||
|
||||
add_library(libgldemo_static STATIC ${LIBGLDEMO_SOURCES})
|
||||
set_target_properties(libgldemo_static PROPERTIES
|
||||
OUTPUT_NAME "gldemo"
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
234
library/libgldemo/glx.c
Normal file
234
library/libgldemo/glx.c
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
libgldemo - General-purpose OpenGL demo backend
|
||||
glx.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 "libgldemo.h"
|
||||
|
||||
static Display *display = NULL;
|
||||
static int screen = 0;
|
||||
static Window window = 0;
|
||||
static GLXContext hrc = 0;
|
||||
|
||||
static uint8_t keys[256] = {0};
|
||||
static uint8_t f11_pressed = 0;
|
||||
static uint16_t WndWidth, WndHeight;
|
||||
static uint16_t ResWidth, ResHeight;
|
||||
static int fullscreen = 0;
|
||||
|
||||
void KillGLWindow()
|
||||
{
|
||||
if(hrc){
|
||||
glXMakeCurrent(display, None, NULL);
|
||||
glXDestroyContext(display, hrc);
|
||||
hrc = 0;
|
||||
}
|
||||
|
||||
if(window){
|
||||
XDestroyWindow(display, window);
|
||||
window = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int CreateGLWindow(const char *__restrict title, uint16_t width, uint16_t height)
|
||||
{
|
||||
int attlist[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 4,
|
||||
GLX_GREEN_SIZE, 4,
|
||||
GLX_BLUE_SIZE, 4,
|
||||
GLX_DEPTH_SIZE, 16,
|
||||
GLX_DOUBLEBUFFER,
|
||||
None
|
||||
};
|
||||
XVisualInfo *visualinfo;
|
||||
Colormap cmap;
|
||||
Atom wmDelete;
|
||||
XSetWindowAttributes attr;
|
||||
int (APIENTRY *glXSwapIntervalSGIptr)(int);
|
||||
|
||||
visualinfo = glXChooseVisual(display, screen, attlist);
|
||||
if(visualinfo == NULL){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Can't find a suitable pixel format.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create a color map */
|
||||
cmap = XCreateColormap(display, RootWindow(display, visualinfo->screen), visualinfo->visual, AllocNone);
|
||||
attr.colormap = cmap;
|
||||
attr.border_pixel = 0;
|
||||
|
||||
hrc = glXCreateContext(display, visualinfo, NULL, GL_TRUE);
|
||||
if(hrc == NULL){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Failed to create an OpenGL rendering context.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
attr.event_mask = KeyPressMask | KeyReleaseMask | StructureNotifyMask;
|
||||
if(fullscreen){
|
||||
attr.override_redirect = True;
|
||||
width = ResWidth;
|
||||
height = ResHeight;
|
||||
XWarpPointer(display, None, window, 0, 0, 0, 0, 0, 0);
|
||||
}else{
|
||||
attr.override_redirect = False;
|
||||
}
|
||||
|
||||
if(!(window = XCreateWindow(display, XRootWindow(display, visualinfo->screen),
|
||||
(ResWidth - width)>>1,
|
||||
(ResHeight - height)>>1,
|
||||
width,
|
||||
height,
|
||||
0, visualinfo->depth, InputOutput, visualinfo->visual,
|
||||
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &attr)
|
||||
)){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Window creation error.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WndWidth = width;
|
||||
WndHeight = height;
|
||||
|
||||
XSetStandardProperties(display, window, title, title, None, NULL, 0, NULL);
|
||||
XMapRaised(display, window);
|
||||
XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", True);
|
||||
XSetWMProtocols(display, window, &wmDelete, 1);
|
||||
|
||||
/* connect the glx-context to the window */
|
||||
glXMakeCurrent(display, window, hrc);
|
||||
XFlush(display);
|
||||
|
||||
if(!Demo.InitGL()){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Initialization failed.");
|
||||
return 0;
|
||||
}
|
||||
if(!Demo.ResizeScene(width&&height ? width : 1, width&&height ? height : 1)){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Scene resize failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
glXSwapIntervalSGIptr = (int (APIENTRY *)(int)) glXGetProcAddressARB((const GLubyte *) "glXSwapIntervalSGI");
|
||||
if(glXSwapIntervalSGIptr) glXSwapIntervalSGIptr(1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int dotclock;
|
||||
XF86VidModeModeLine modeline;
|
||||
struct timespec time1;
|
||||
display = XOpenDisplay(0);
|
||||
if(display == NULL){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Failed to obtain the X11 display context.");
|
||||
return 0;
|
||||
}
|
||||
XkbSetDetectableAutoRepeat(display, True, 0);
|
||||
screen = XDefaultScreen(display);
|
||||
XF86VidModeGetModeLine(display, screen, &dotclock, &modeline);
|
||||
ResWidth = modeline.hdisplay;
|
||||
ResHeight = modeline.vdisplay;
|
||||
|
||||
if(Demo.Startup && !Demo.Startup())
|
||||
return -1;
|
||||
|
||||
if(!CreateGLWindow(Demo.Title, Demo.Width, Demo.Height))
|
||||
return -1;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &time1);
|
||||
|
||||
while(1){
|
||||
struct timespec time2;
|
||||
float TimeDelta;
|
||||
|
||||
while(XPending(display)){
|
||||
XEvent event;
|
||||
XNextEvent(display, &event);
|
||||
|
||||
switch(event.type){
|
||||
|
||||
case ConfigureNotify:
|
||||
if(((unsigned)event.xconfigure.width != WndWidth) ||
|
||||
((unsigned)event.xconfigure.height != WndHeight)){
|
||||
WndWidth = event.xconfigure.width;
|
||||
WndHeight = event.xconfigure.height;
|
||||
Demo.ResizeScene(event.xconfigure.width, event.xconfigure.height);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyPress: {
|
||||
KeySym key = XLookupKeysym(&event.xkey, 0);
|
||||
if(key <= 255)
|
||||
keys[(key + 'A' - 'a') & 255] = 1;
|
||||
else if(key == XK_Left) keys[KEY_LEFT] = 1;
|
||||
else if(key == XK_Up) keys[KEY_UP] = 1;
|
||||
else if(key == XK_Right) keys[KEY_RIGHT] = 1;
|
||||
else if(key == XK_Down) keys[KEY_DOWN] = 1;
|
||||
else{
|
||||
if(key == XK_Escape){
|
||||
KillGLWindow();
|
||||
XCloseDisplay(display);
|
||||
return (!Demo.Shutdown || Demo.Shutdown()) ? 0 : -1;
|
||||
}
|
||||
if(key == XK_F11 && !f11_pressed){
|
||||
KillGLWindow();
|
||||
fullscreen = !fullscreen;
|
||||
CreateGLWindow(Demo.Title, Demo.Width, Demo.Height);
|
||||
f11_pressed = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case KeyRelease: {
|
||||
KeySym key = XLookupKeysym(&event.xkey, 0);
|
||||
if(key <= 255)
|
||||
keys[(key + 'A' - 'a') & 255] = 0;
|
||||
else if(key == XK_Left) keys[KEY_LEFT] = 0;
|
||||
else if(key == XK_Up) keys[KEY_UP] = 0;
|
||||
else if(key == XK_Right) keys[KEY_RIGHT] = 0;
|
||||
else if(key == XK_Down) keys[KEY_DOWN] = 0;
|
||||
else if(key == XK_F11) f11_pressed = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case ClientMessage:
|
||||
if (XGetAtomName(display, event.xclient.message_type)[0] == 'W'){
|
||||
KillGLWindow();
|
||||
XCloseDisplay(display);
|
||||
return (!Demo.Shutdown || Demo.Shutdown()) ? 0 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the timedelta */
|
||||
clock_gettime(CLOCK_REALTIME, &time2);
|
||||
TimeDelta = (float)(time2.tv_sec - time1.tv_sec) + ((float)(time2.tv_nsec - time1.tv_nsec)) * 1e-9;
|
||||
if(TimeDelta < 0) TimeDelta = 0; /* Safe-guard in case of system delay */
|
||||
time1 = time2;
|
||||
|
||||
/* Draw */
|
||||
Demo.DrawScene(TimeDelta, keys);
|
||||
glXSwapBuffers(display, window);
|
||||
}
|
||||
}
|
68
library/libgldemo/libgldemo.h
Normal file
68
library/libgldemo/libgldemo.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
libgldemo - General-purpose OpenGL demo backend
|
||||
libgldemo.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 <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
typedef struct {
|
||||
const char *__restrict Title;
|
||||
uint16_t Width, Height;
|
||||
|
||||
int (* Startup)(void);
|
||||
int (* Shutdown)(void);
|
||||
int (* InitGL)(void);
|
||||
int (* ResizeScene)(uint16_t width, uint16_t height);
|
||||
int (* DrawScene)(float TimeDelta, uint8_t keys[256]);
|
||||
} DemoConfig;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern const DemoConfig Demo;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
||||
#define DemoMessageBox(x) MessageBox(NULL, x, NULL, MB_OK)
|
||||
#define DemoErrorBox(x) MessageBox(NULL, x, NULL, MB_OK | MB_ICONERROR)
|
||||
|
||||
#define KEY_LEFT VK_LEFT
|
||||
#define KEY_UP VK_UP
|
||||
#define KEY_RIGHT VK_RIGHT
|
||||
#define KEY_DOWN VK_DOWN
|
||||
#else
|
||||
#define POSIX_C_SOURCE 199309L
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <GL/glx.h>
|
||||
#include <X11/extensions/xf86vmode.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#define DemoMessageBox(x) fprintf(stdout, "%s\n", x)
|
||||
#define DemoErrorBox(x) fprintf(stderr, "%s\n", x)
|
||||
|
||||
#define KEY_LEFT 0x25
|
||||
#define KEY_UP 0x26
|
||||
#define KEY_RIGHT 0x27
|
||||
#define KEY_DOWN 0x28
|
||||
#endif
|
281
library/libgldemo/wgl.c
Normal file
281
library/libgldemo/wgl.c
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
libgldemo - General-purpose OpenGL demo backend
|
||||
wgl.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 "libgldemo.h"
|
||||
|
||||
static HWND hWnd = NULL;
|
||||
static HDC hDC = NULL;
|
||||
static HGLRC hRC = NULL;
|
||||
static HINSTANCE hInst;
|
||||
|
||||
static uint8_t keys[256] = {0};
|
||||
static uint16_t ResWidth, ResHeight, ResDepth;
|
||||
static int fullscreen = 0;
|
||||
static float FramePeriod;
|
||||
|
||||
static void KillGLWindow()
|
||||
{
|
||||
if(fullscreen){
|
||||
ShowCursor(1);
|
||||
}
|
||||
|
||||
if(hRC){
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(hRC);
|
||||
hRC = NULL;
|
||||
}
|
||||
|
||||
if(hDC){
|
||||
ReleaseDC(hWnd, hDC);
|
||||
hDC = NULL;
|
||||
}
|
||||
|
||||
if(hWnd){
|
||||
DestroyWindow(hWnd);
|
||||
hWnd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int CreateGLWindow(const char *__restrict title, uint16_t width, uint16_t height)
|
||||
{
|
||||
const PIXELFORMATDESCRIPTOR pfd = {
|
||||
sizeof(PIXELFORMATDESCRIPTOR), 1, /* Size and version */
|
||||
PFD_DRAW_TO_WINDOW | /* dwFlags */
|
||||
PFD_SUPPORT_OPENGL |
|
||||
PFD_DOUBLEBUFFER,
|
||||
PFD_TYPE_RGBA, /* iPixelType */
|
||||
0, /* cColorBits */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* R,G,B,A bits */
|
||||
0, 0, 0, 0, 0, /* Accumulation buffer bits */
|
||||
16, /* cDepthBits */
|
||||
0, /* cStencilBits */
|
||||
0, /* cAuxBuffers */
|
||||
PFD_MAIN_PLANE, /* iLayerType */
|
||||
0, /* Reserved */
|
||||
0, 0, 0 /* Masks */
|
||||
};
|
||||
DWORD dwStyle, dwExStyle;
|
||||
RECT WindowRect;
|
||||
int PixelFormat;
|
||||
BOOL (WINAPI *wglSwapIntervalEXT)(int);
|
||||
int (WINAPI *wglGetSwapIntervalEXT)(void);
|
||||
|
||||
if(fullscreen){
|
||||
dwExStyle = WS_EX_APPWINDOW | WS_EX_TOPMOST;
|
||||
dwStyle = WS_POPUP;
|
||||
|
||||
width = ResWidth;
|
||||
height = ResHeight;
|
||||
ShowCursor(0);
|
||||
}else{
|
||||
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
dwStyle = WS_OVERLAPPEDWINDOW;
|
||||
|
||||
WindowRect.left = 0;
|
||||
WindowRect.right = width;
|
||||
WindowRect.top = 0;
|
||||
WindowRect.bottom = height;
|
||||
AdjustWindowRectEx(&WindowRect, dwStyle, 0, dwExStyle);
|
||||
width = WindowRect.right - WindowRect.left;
|
||||
height = WindowRect.bottom - WindowRect.top;
|
||||
}
|
||||
|
||||
if(!(hWnd = CreateWindowEx(dwExStyle, "OpenGL",
|
||||
title,
|
||||
dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||
(ResWidth - width)>>1,
|
||||
(ResHeight - height)>>1,
|
||||
width,
|
||||
height,
|
||||
NULL, NULL, hInst, NULL))
|
||||
){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Window creation error.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hDC = GetDC(hWnd);
|
||||
if(!hDC){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Failed to create an OpenGL device context.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PixelFormat = ChoosePixelFormat(hDC, &pfd);
|
||||
if(!PixelFormat){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Can't find a suitable PixelFormat.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!SetPixelFormat(hDC, PixelFormat, &pfd)){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Can't set the PixelFormat.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hRC = wglCreateContext(hDC);
|
||||
if(!hRC){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Failed to create an OpenGL rendering context.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!wglMakeCurrent(hDC, hRC)){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Failed to activate the OpenGL device context.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ShowWindow(hWnd, SW_SHOW);
|
||||
SetForegroundWindow(hWnd);
|
||||
SetFocus(hWnd);
|
||||
|
||||
if(!Demo.InitGL()){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Initialization failed.");
|
||||
return 0;
|
||||
}
|
||||
if(!Demo.ResizeScene(width&&height ? width : 1, width&&height ? height : 1)){
|
||||
KillGLWindow();
|
||||
DemoErrorBox("Scene resize failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wglSwapIntervalEXT = (BOOL (WINAPI *)(int)) wglGetProcAddress("wglSwapIntervalEXT");
|
||||
if(wglSwapIntervalEXT) wglSwapIntervalEXT(1);
|
||||
wglGetSwapIntervalEXT = (int (WINAPI *)(void)) wglGetProcAddress("wglGetSwapIntervalEXT");
|
||||
if(wglGetSwapIntervalEXT) wglGetSwapIntervalEXT(); /* Seems necessary on some cards */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg) {
|
||||
case WM_KEYDOWN:
|
||||
if(wParam == VK_ESCAPE){
|
||||
PostQuitMessage(0);
|
||||
}else if(wParam == VK_F11 && !keys[VK_F11]){
|
||||
KillGLWindow();
|
||||
fullscreen = !fullscreen;
|
||||
if(!CreateGLWindow(Demo.Title, Demo.Width, Demo.Height))
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
case WM_KEYUP:
|
||||
keys[wParam] = (uMsg == WM_KEYDOWN);
|
||||
return 0;
|
||||
|
||||
case WM_DEVMODECHANGE: {
|
||||
DEVMODE dm;
|
||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
|
||||
ResWidth = dm.dmPelsWidth;
|
||||
ResHeight = dm.dmPelsHeight;
|
||||
ResDepth = dm.dmBitsPerPel;
|
||||
FramePeriod = 1.0f/dm.dmDisplayFrequency;
|
||||
}
|
||||
case WM_SIZE:
|
||||
Demo.ResizeScene(LOWORD(lParam), HIWORD(lParam));
|
||||
return 0;
|
||||
|
||||
case WM_CLOSE:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||
{
|
||||
WNDCLASS wc = {
|
||||
CS_HREDRAW | CS_VREDRAW | CS_OWNDC, /* style */
|
||||
(WNDPROC) WndProc, /* lpfnWndProc */
|
||||
0, /* cbClsExtra */
|
||||
0, /* cbWndExtra */
|
||||
NULL, /* hInstance */
|
||||
NULL, /* hIcon */
|
||||
NULL, /* hCursor */
|
||||
NULL, /* hbrBackground */
|
||||
NULL, /* lpszMenuName */
|
||||
"OpenGL" /* lpszClassName */
|
||||
};
|
||||
DEVMODE dm;
|
||||
LARGE_INTEGER ClockFreq, PreviousTime;
|
||||
|
||||
UNREFERENCED_PARAMETER(hPrevInstance);
|
||||
UNREFERENCED_PARAMETER(lpCmdLine);
|
||||
UNREFERENCED_PARAMETER(nCmdShow);
|
||||
|
||||
wc.hInstance = hInst = hInstance;
|
||||
wc.hIcon = (HICON) LoadImage(NULL, IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_SHARED);
|
||||
wc.hCursor = (HCURSOR) LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
|
||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
|
||||
ResWidth = dm.dmPelsWidth;
|
||||
ResHeight = dm.dmPelsHeight;
|
||||
ResDepth = dm.dmBitsPerPel;
|
||||
FramePeriod = 1.0f/dm.dmDisplayFrequency;
|
||||
QueryPerformanceFrequency(&ClockFreq);
|
||||
|
||||
if(!RegisterClass(&wc)){
|
||||
MessageBox(NULL, "Failed to register the window class.", NULL, MB_OK | MB_ICONERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(Demo.Startup && !Demo.Startup())
|
||||
return -1;
|
||||
|
||||
if(!CreateGLWindow(Demo.Title, Demo.Width, Demo.Height))
|
||||
return -1;
|
||||
|
||||
QueryPerformanceCounter(&PreviousTime);
|
||||
|
||||
while(1){
|
||||
MSG msg;
|
||||
LARGE_INTEGER CurrentTime;
|
||||
float TimeDelta;
|
||||
|
||||
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
if(msg.message == WM_QUIT){
|
||||
KillGLWindow();
|
||||
UnregisterClass("OpenGL", hInstance);
|
||||
return (!Demo.Shutdown || Demo.Shutdown()) ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the timedelta */
|
||||
QueryPerformanceCounter(&CurrentTime);
|
||||
TimeDelta = (float)(CurrentTime.QuadPart-PreviousTime.QuadPart)/ClockFreq.QuadPart;
|
||||
PreviousTime = CurrentTime;
|
||||
if(TimeDelta < 0 || TimeDelta > 5) /* Safe-guard in case of system delay */
|
||||
continue;
|
||||
|
||||
/* Draw */
|
||||
Demo.DrawScene(TimeDelta, keys);
|
||||
SwapBuffers(hDC);
|
||||
|
||||
/* Sleep for the remainder of the frame */
|
||||
QueryPerformanceCounter(&CurrentTime);
|
||||
TimeDelta = (float)(CurrentTime.QuadPart-PreviousTime.QuadPart)/ClockFreq.QuadPart;
|
||||
TimeDelta = (FramePeriod - TimeDelta) * 1000;
|
||||
if(TimeDelta > 1 && TimeDelta < 100) Sleep((unsigned) TimeDelta);
|
||||
}
|
||||
}
|
1
library/libvitaboy/AUTHORS
Normal file
1
library/libvitaboy/AUTHORS
Normal file
|
@ -0,0 +1 @@
|
|||
Fatbag <X-Fi6@phppoll.org>
|
15
library/libvitaboy/CHANGES
Normal file
15
library/libvitaboy/CHANGES
Normal file
|
@ -0,0 +1,15 @@
|
|||
libvitaboy 1.0.1 (2012-03-10) Fatbag
|
||||
|
||||
* Corrected the BlendVertices function; blend vertices tug real vertices, not the other way around
|
||||
* Interleaved all vertex data (coords, texcoords, normals, blend weights) into the VertexData array
|
||||
* Made reading floats cross-platform (on modern architectures that use IEEE floats) by using unions
|
||||
|
||||
|
||||
libvitaboy 1.0.0 (2012-03-04) Fatbag
|
||||
|
||||
* First stable release
|
||||
* Read support for ANIM, APR, BND, COL, HAG, MESH, OFT, PO, SKEL
|
||||
* Working rendering and animation of characters in OpenGL
|
||||
* Basic keyboard controls
|
||||
* Support for environments: MinGW
|
||||
* Support for platforms: i686, x86-64
|
51
library/libvitaboy/CMakeLists.txt
Normal file
51
library/libvitaboy/CMakeLists.txt
Normal file
|
@ -0,0 +1,51 @@
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
project(libvitaboy)
|
||||
|
||||
set(LIBVITABOY_SERIES 0)
|
||||
set(LIBVITABOY_MAJOR 0)
|
||||
set(LIBVITABOY_MINOR 1)
|
||||
|
||||
set(LIBVITABOY_SOURCES
|
||||
anim.cpp
|
||||
apr.cpp
|
||||
bnd.cpp
|
||||
col.cpp
|
||||
hag.cpp
|
||||
libvitaboy.cpp
|
||||
mesh.cpp
|
||||
oft.cpp
|
||||
po.cpp
|
||||
skel.cpp
|
||||
)
|
||||
if(WIN32)
|
||||
set(LIBVITABOY_SOURCES ${LIBVITABOY_SOURCES} resource.rc)
|
||||
else()
|
||||
add_definitions(-Dstricmp=strcasecmp)
|
||||
endif()
|
||||
|
||||
include_directories(${LIBGLDEMO_INCLUDE} ${FILEHANDLER_INCLUDE})
|
||||
|
||||
#### Static library (uncomment to build)
|
||||
#add_library(libvitaboy_static STATIC ${LIBVITABOY_SOURCES})
|
||||
#set_target_properties(libvitaboy_static PROPERTIES
|
||||
# OUTPUT_NAME "vitaboy"
|
||||
# CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
add_library(libvitaboy_shared SHARED ${LIBVITABOY_SOURCES})
|
||||
if(WIN32)
|
||||
set_target_properties(libvitaboy_shared PROPERTIES OUTPUT_NAME "vitaboy${LIBVITABOY_SERIES}")
|
||||
else()
|
||||
set_target_properties(libvitaboy_shared PROPERTIES OUTPUT_NAME "vitaboy")
|
||||
endif()
|
||||
set_target_properties(libvitaboy_shared PROPERTIES
|
||||
COMPILE_FLAGS "-fvisibility=default"
|
||||
VERSION ${LIBVITABOY_SERIES}.${LIBVITABOY_MAJOR}.${LIBVITABOY_MINOR}
|
||||
PREFIX "lib"
|
||||
IMPORT_PREFIX "lib"
|
||||
CLEAN_DIRECT_OUTPUT 1)
|
||||
|
||||
add_executable(vbparse vbparse.cpp)
|
||||
target_link_libraries(vbparse libvitaboy_shared FileHandler_shared)
|
||||
|
||||
add_executable(Renderer ${GLDEMO_EXE} Renderer.cpp)
|
||||
target_link_libraries(Renderer libvitaboy_shared ${GLDEMO_LINK} FileHandler_shared m)
|
15
library/libvitaboy/COPYING
Normal file
15
library/libvitaboy/COPYING
Normal file
|
@ -0,0 +1,15 @@
|
|||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
Version 1.0.1
|
||||
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.
|
67
library/libvitaboy/README
Normal file
67
library/libvitaboy/README
Normal file
|
@ -0,0 +1,67 @@
|
|||
***************************************************************************
|
||||
* ** libvitaboy - Open source OpenGL TSO character animation library ** *
|
||||
* ** Copyright (c) 2012 Drew D'Addesio ("Fatbag", <X-Fi6@phppoll.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. *
|
||||
***************************************************************************
|
||||
|
||||
|
||||
libvitaboy is a cross-platform C++ library for parsing the various character rendering formats used in The Sims Online and using
|
||||
that information to render and animate the 3D characters of the game using OpenGL.
|
||||
|
||||
Formats include:
|
||||
(*) ANIM (Animation)
|
||||
(*) APR (Appearance)
|
||||
(*) BND (Binding)
|
||||
(*) COL (Collection)
|
||||
(*) HAG (Hand Group)
|
||||
(*) MESH (Mesh)
|
||||
(*) OFT (Outfit)
|
||||
(*) PO (Purchasable Outfit)
|
||||
(*) SKEL (Skeleton)
|
||||
|
||||
|
||||
1. What this library will do for you
|
||||
|
||||
You can use this library to render a character in a predetermined location.
|
||||
|
||||
|
||||
2. Compiling
|
||||
|
||||
Compiling is straightforward. The Makefiles and project files should already be set up for you, and are easy to tweak.
|
||||
Before compiling the library, make your changes to config.h to specify what's compiled in.
|
||||
|
||||
a. Compiling from a Makefile
|
||||
|
||||
Makefiles are listed in the top directory in the format Makefile.$(PLATFORM). Just copy the one applicable to your platform
|
||||
to the destination file "Makefile" and run GNU make.
|
||||
|
||||
b. Compiling from a project file
|
||||
|
||||
Project files are held within their own directories. They can be opened up with the target IDE and be compiled by
|
||||
invoking the compile action of that IDE.
|
||||
|
||||
c. Compiling using your own Makefile or project file
|
||||
|
||||
It's possible no such file exists for your platform. In this case, look at whichever Makefile is most relevant to your
|
||||
platform, copy all source files down (.cpp, .hpp, ...), and add it your own Makefile or project. In theory,
|
||||
it should work. :)
|
||||
|
||||
libvitaboy is intended to work with any C++ compiler. If not, and the compiler is not only modern and popular but also free
|
||||
software (gratis, libre, open source software), please report it as a bug.
|
||||
|
||||
|
||||
3. Useful links
|
||||
|
||||
libvitaboy is hosted by and maintained by the Niotso project.
|
||||
Home page: <http://www.niotso.org/>
|
||||
Don Hopkins documentation:
|
||||
(*) http://www.donhopkins.com/drupal/node/20 [Sims Character Animation File Format]
|
||||
(*) http://www.donhopkins.com/drupal/node/21 [Details on The Sims Character Animation File Format and Rendering]
|
||||
(*) http://www.donhopkins.com/drupal/node/19 [Sims VitaBoy Character Animation Library Documentation]
|
||||
(*) http://www.donhopkins.com/home/movies/ [Index of Archived Streaming QuickTime Movies]
|
441
library/libvitaboy/Renderer.cpp
Normal file
441
library/libvitaboy/Renderer.cpp
Normal file
|
@ -0,0 +1,441 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
Renderer.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Instructions:
|
||||
You must have the following files in the same directory as the Renderer binary:
|
||||
|
||||
Skeleton:
|
||||
* skeleton.skel ("adult.skel" in ./avatardata/skeletons/)
|
||||
|
||||
Meshes:
|
||||
* body.mesh (pick one from ./avatardata/bodies/meshes/)
|
||||
* head.mesh (pick one from ./avatardata/heads/meshes/)
|
||||
* lhand.mesh (pick one from ./avatardata/hands/meshes/)
|
||||
* rhand.mesh (pick one from ./avatardata/hands/meshes/)
|
||||
|
||||
Textures:
|
||||
* body.jpg (pick one from ./avatardata/bodies/textures/)
|
||||
* head.jpg (pick one from ./avatardata/heads/textures/)
|
||||
* hand.jpg (pick one from ./avatardata/hands/textures/)
|
||||
|
||||
Animation:
|
||||
* animation.anim (pick one from ./avatardata/animations/)
|
||||
|
||||
==== Controls ====
|
||||
Arrow keys: Rotate the sim
|
||||
i,j,k,l: Translate the sim around the screen
|
||||
z,x: Rotate the sim like a clock
|
||||
a,s: Zoom in, out
|
||||
q: Toggle skeleton
|
||||
n: Animate the character
|
||||
F11: Enter/leave fullscreen
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <FileHandler.hpp>
|
||||
#include <libgldemo.h>
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
static float zoom = -10;
|
||||
struct BasicVertex_t {
|
||||
float x, y, z;
|
||||
};
|
||||
struct CharacterPlacement_t {
|
||||
BasicVertex_t Translation;
|
||||
BasicVertex_t Rotation;
|
||||
};
|
||||
static CharacterPlacement_t Character = {{0,-3,0}, {0,0,0}};
|
||||
|
||||
static Skeleton_t Skeleton;
|
||||
|
||||
static const unsigned TextureCount = 3;
|
||||
static unsigned texture[3];
|
||||
enum { Texture_Body, Texture_Head, Texture_Hand };
|
||||
static const char* const TexturePaths[] = {"body.jpg", "head.jpg", "hand.jpg"};
|
||||
|
||||
static const unsigned MeshCount = 4;
|
||||
static Mesh_t Meshes[4];
|
||||
enum { Mesh_Body, Mesh_Head, Mesh_LHand, Mesh_RHand };
|
||||
static const char* const MeshPaths[] = {"body.mesh", "head.mesh", "lhand.mesh", "rhand.mesh" };
|
||||
static const unsigned Mesh_UseTexture[] = { Texture_Body, Texture_Head, Texture_Hand, Texture_Hand };
|
||||
static const char* const MeshActivate[] = {NULL, "HEAD", "L_HAND", "R_HAND"};
|
||||
|
||||
static Animation_t Animation;
|
||||
static float AnimationTime = 0;
|
||||
|
||||
static bool ShowMesh = true;
|
||||
static bool ShowSkeleton = true;
|
||||
|
||||
static bool PressedQ = false;
|
||||
|
||||
static void DisplayFileError(const char * Filename){
|
||||
const char * Message;
|
||||
switch(File::Error){
|
||||
case FERR_NOT_FOUND:
|
||||
Message = "%s does not exist.";
|
||||
break;
|
||||
case FERR_OPEN:
|
||||
Message = "%s could not be opened for reading.";
|
||||
break;
|
||||
case FERR_BLANK:
|
||||
case FERR_UNRECOGNIZED:
|
||||
case FERR_INVALIDDATA:
|
||||
Message = "%s is corrupt or invalid.";
|
||||
break;
|
||||
case FERR_MEMORY:
|
||||
Message = "Memory for %s could not be allocated.";
|
||||
break;
|
||||
default:
|
||||
Message = "%s could not be read.";
|
||||
break;
|
||||
}
|
||||
|
||||
char Buffer[1024];
|
||||
sprintf(Buffer, Message, Filename);
|
||||
DemoErrorBox(Buffer);
|
||||
}
|
||||
|
||||
static int LoadTextures()
|
||||
{
|
||||
glGenTextures(3, texture);
|
||||
for(int i=0; i<3; i++){
|
||||
Image_t * Image = File::ReadImageFile(TexturePaths[i]);
|
||||
if(!Image){
|
||||
DisplayFileError(TexturePaths[i]);
|
||||
return false;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture[i]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->Width, Image->Height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->Data);
|
||||
free(Image->Data);
|
||||
free(Image);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int InitGL()
|
||||
{
|
||||
if(!LoadTextures())
|
||||
return false;
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClearDepth(1.0f);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_RESCALE_NORMAL);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||
glFrontFace(GL_CW);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ResizeScene(uint16_t width, uint16_t height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
// Calculate The Aspect Ratio Of The Window
|
||||
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
|
||||
// glScalef(-1.0f, 1.0f, 1.0f);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void TransformVertices(Bone_t& Bone)
|
||||
{
|
||||
glTranslatef(Bone.Translation.x, Bone.Translation.y, Bone.Translation.z);
|
||||
float Matrix[16];
|
||||
FindQuaternionMatrix(Matrix, &Bone.Rotation);
|
||||
glMultMatrixf(Matrix);
|
||||
|
||||
unsigned MeshIndex = 0;
|
||||
unsigned BoneIndex;
|
||||
|
||||
for(unsigned i=1; i<MeshCount; i++){
|
||||
if(!strcmp(Bone.Name, MeshActivate[i])){
|
||||
MeshIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Mesh_t& Mesh = Meshes[MeshIndex];
|
||||
for(BoneIndex=0; BoneIndex<Mesh.BindingCount; BoneIndex++){
|
||||
if(!strcmp(Bone.Name, Mesh.BoneNames[Mesh.BoneBindings[BoneIndex].BoneIndex]))
|
||||
break;
|
||||
}
|
||||
|
||||
if(BoneIndex < Mesh.BindingCount){
|
||||
for(unsigned i=0; i<Mesh.BoneBindings[BoneIndex].RealVertexCount; i++){
|
||||
unsigned VertexIndex = Mesh.BoneBindings[BoneIndex].FirstRealVertex + i;
|
||||
Vertex_t& RelativeVertex = Mesh.VertexData[VertexIndex];
|
||||
Vertex_t& AbsoluteVertex = Mesh.TransformedVertexData[VertexIndex];
|
||||
|
||||
glTranslatef(RelativeVertex.Coord.x, RelativeVertex.Coord.y, RelativeVertex.Coord.z);
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, Matrix);
|
||||
AbsoluteVertex.Coord.x = Matrix[12];
|
||||
AbsoluteVertex.Coord.y = Matrix[13];
|
||||
AbsoluteVertex.Coord.z = Matrix[14];
|
||||
glTranslatef(-RelativeVertex.Coord.x, -RelativeVertex.Coord.y, -RelativeVertex.Coord.z);
|
||||
}
|
||||
for(unsigned i=0; i<Mesh.BoneBindings[BoneIndex].BlendVertexCount; i++){
|
||||
unsigned VertexIndex = Mesh.RealVertexCount + Mesh.BoneBindings[BoneIndex].FirstBlendVertex + i;
|
||||
Vertex_t& RelativeVertex = Mesh.VertexData[VertexIndex];
|
||||
Vertex_t& AbsoluteVertex = Mesh.TransformedVertexData[VertexIndex];
|
||||
|
||||
glTranslatef(RelativeVertex.Coord.x, RelativeVertex.Coord.y, RelativeVertex.Coord.z);
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, Matrix);
|
||||
AbsoluteVertex.Coord.x = Matrix[12];
|
||||
AbsoluteVertex.Coord.y = Matrix[13];
|
||||
AbsoluteVertex.Coord.z = Matrix[14];
|
||||
glTranslatef(-RelativeVertex.Coord.x, -RelativeVertex.Coord.y, -RelativeVertex.Coord.z);
|
||||
}
|
||||
}
|
||||
|
||||
if(Bone.ChildrenCount == 1){
|
||||
TransformVertices(*Bone.Children[0]);
|
||||
}else if(Bone.ChildrenCount > 1){
|
||||
for(unsigned i=0; i<Bone.ChildrenCount; i++){
|
||||
glPushMatrix();
|
||||
TransformVertices(*Bone.Children[i]);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BlendVertices()
|
||||
{
|
||||
for(unsigned i=0; i<MeshCount; i++){
|
||||
Mesh_t& Mesh = Meshes[i];
|
||||
for(unsigned i=0; i<Mesh.BlendVertexCount; i++){
|
||||
Vertex_t& BlendVertex = Mesh.TransformedVertexData[Mesh.RealVertexCount + i];
|
||||
float Weight = BlendVertex.BlendData.Weight;
|
||||
Vertex_t& RealVertex = Mesh.TransformedVertexData[BlendVertex.BlendData.OtherVertex];
|
||||
RealVertex.Coord.x =
|
||||
Weight * BlendVertex.Coord.x +
|
||||
(1-Weight) * RealVertex.Coord.x;
|
||||
RealVertex.Coord.y =
|
||||
Weight * BlendVertex.Coord.y +
|
||||
(1-Weight) * RealVertex.Coord.y;
|
||||
RealVertex.Coord.z =
|
||||
Weight * BlendVertex.Coord.z +
|
||||
(1-Weight) * RealVertex.Coord.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawMeshes()
|
||||
{
|
||||
glPointSize(2.0);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
TransformVertices(Skeleton.Bones[0]);
|
||||
glPopMatrix();
|
||||
BlendVertices();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
for(unsigned i=0; i<MeshCount; i++){
|
||||
glBindTexture(GL_TEXTURE_2D, texture[Mesh_UseTexture[i]]);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vertex_t), &Meshes[i].TransformedVertexData[0].Coord);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex_t), &Meshes[i].TransformedVertexData[0].TextureCoord);
|
||||
glDrawElements(GL_TRIANGLES, Meshes[i].FaceCount*3, GL_UNSIGNED_INT, Meshes[i].FaceData);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
static void AdvanceFrame(Skeleton_t& Skeleton, Animation_t& Animation, float TimeDelta)
|
||||
{
|
||||
float Duration = (float)Animation.Motions[0].FrameCount/30;
|
||||
AnimationTime += TimeDelta;
|
||||
AnimationTime = fmodf(AnimationTime, Duration); //Loop the animation
|
||||
|
||||
for(unsigned i=0; i<Animation.MotionsCount; i++){
|
||||
unsigned BoneIndex = FindBone(Skeleton, Animation.Motions[i].BoneName, Skeleton.BoneCount);
|
||||
if(BoneIndex == (unsigned)-1) continue;
|
||||
|
||||
Bone_t& Bone = Skeleton.Bones[BoneIndex];
|
||||
|
||||
unsigned Frame = AnimationTime*30;
|
||||
float FractionShown = AnimationTime*30 - Frame;
|
||||
unsigned NextFrame = (Frame+1 != Animation.Motions[0].FrameCount) ? Frame+1 : 0;
|
||||
|
||||
if(Animation.Motions[i].HasTranslation){
|
||||
Translation_t& Translation = Animation.Motions[i].Translations[Frame];
|
||||
Translation_t& NextTranslation = Animation.Motions[i].Translations[NextFrame];
|
||||
Bone.Translation.x = (1-FractionShown)*Translation.x + FractionShown*NextTranslation.x;
|
||||
Bone.Translation.y = (1-FractionShown)*Translation.y + FractionShown*NextTranslation.y;
|
||||
Bone.Translation.z = (1-FractionShown)*Translation.z + FractionShown*NextTranslation.z;
|
||||
}
|
||||
if(Animation.Motions[i].HasRotation){
|
||||
Rotation_t& Rotation = Animation.Motions[i].Rotations[Frame];
|
||||
Rotation_t& NextRotation = Animation.Motions[i].Rotations[NextFrame];
|
||||
|
||||
//Use nlerp to interpolate
|
||||
float w1 = 1.0f - FractionShown, w2 = FractionShown;
|
||||
if(DotProduct(&Rotation, &NextRotation) < 0)
|
||||
w1 *= -1;
|
||||
|
||||
Bone.Rotation.x = w1*Rotation.x + w2*NextRotation.x;
|
||||
Bone.Rotation.y = w1*Rotation.y + w2*NextRotation.y;
|
||||
Bone.Rotation.z = w1*Rotation.z + w2*NextRotation.z;
|
||||
Bone.Rotation.w = w1*Rotation.w + w2*NextRotation.w;
|
||||
|
||||
Normalize(&Bone.Rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawBonesSkeleton(Bone_t& Bone)
|
||||
{
|
||||
glPointSize(5.0);
|
||||
glTranslatef(Bone.Translation.x, Bone.Translation.y, Bone.Translation.z);
|
||||
float RotationMatrix[16];
|
||||
FindQuaternionMatrix(RotationMatrix, &Bone.Rotation);
|
||||
glMultMatrixf(RotationMatrix);
|
||||
|
||||
if(!strcmp(Bone.Name, "ROOT"))
|
||||
glColor3f(1.0, 0.0, 0.0);
|
||||
else if(!strcmp(Bone.Name, "HEAD"))
|
||||
glColor3f(1.0, 1.0, 0.0);
|
||||
else
|
||||
glColor3f(0.0, 1.0, 0.0);
|
||||
glBegin(GL_POINTS); glVertex3f(0, 0, 0); glEnd();
|
||||
|
||||
if(Bone.ChildrenCount == 1){
|
||||
DrawBonesSkeleton(*Bone.Children[0]);
|
||||
}else if(Bone.ChildrenCount > 1){
|
||||
for(unsigned i=0; i<Bone.ChildrenCount; i++){
|
||||
glPushMatrix();
|
||||
DrawBonesSkeleton(*Bone.Children[i]);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawSkeleton()
|
||||
{
|
||||
glPushMatrix();
|
||||
DrawBonesSkeleton(Skeleton.Bones[0]);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
static int DrawScene(float TimeDelta, uint8_t keys[256])
|
||||
{
|
||||
//Handle user interaction
|
||||
if(keys['A']) /*{if(zoom <=-1.0f) zoom+=0.05f; }*/ zoom+=3*TimeDelta;
|
||||
if(keys['S']) /*{if(zoom >=-10.0f) zoom-=0.05f; }*/ zoom-=3*TimeDelta;
|
||||
if(keys[KEY_UP]){ if((Character.Rotation.x-=60*TimeDelta) <=-360) Character.Rotation.x+=360; }
|
||||
if(keys[KEY_DOWN]){ if((Character.Rotation.x+=60*TimeDelta) >=360) Character.Rotation.x-=360; }
|
||||
if(keys[KEY_LEFT]){ if((Character.Rotation.y-=60*TimeDelta) <=-360) Character.Rotation.y+=360; }
|
||||
if(keys[KEY_RIGHT]){ if((Character.Rotation.y+=60*TimeDelta) >=360) Character.Rotation.y-=360; }
|
||||
if(keys['X']){ if((Character.Rotation.z-=60*TimeDelta) <=-360) Character.Rotation.z+=360; }
|
||||
if(keys['Z']){ if((Character.Rotation.z+=60*TimeDelta) >=360) Character.Rotation.z-=360; }
|
||||
if(keys['K']){ Character.Translation.y-=3*TimeDelta; }
|
||||
if(keys['I']){ Character.Translation.y+=3*TimeDelta; }
|
||||
if(keys['J']){ Character.Translation.x-=3*TimeDelta; }
|
||||
if(keys['L']){ Character.Translation.x+=3*TimeDelta; }
|
||||
if(keys['Q']){ if(!PressedQ){ PressedQ = 1; ShowSkeleton = !ShowSkeleton; }} else PressedQ = 0;
|
||||
if(keys['N']){ AdvanceFrame(Skeleton, Animation, TimeDelta); }
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the screen and the depth buffer
|
||||
|
||||
glLoadIdentity();
|
||||
glTranslatef(Character.Translation.x, Character.Translation.y, zoom + Character.Translation.z);
|
||||
glRotatef(Character.Rotation.x,1.0f,0.0f,0.0f);
|
||||
glRotatef(Character.Rotation.y,0.0f,1.0f,0.0f);
|
||||
glRotatef(Character.Rotation.z,0.0f,0.0f,1.0f);
|
||||
|
||||
if(ShowMesh){
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glColor3f(1.0, 1.0, 1.0);
|
||||
|
||||
DrawMeshes();
|
||||
}
|
||||
|
||||
if(ShowSkeleton){
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
DrawSkeleton();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Read(const char * Filename, uint8_t ** InData){
|
||||
*InData = File::ReadFile(Filename);
|
||||
if(*InData != NULL){
|
||||
VBFile.set(*InData, File::FileSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
DisplayFileError(Filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
static int Startup()
|
||||
{
|
||||
uint8_t * InData;
|
||||
|
||||
if(!Read("skeleton.skel", &InData))
|
||||
return 0;
|
||||
ReadSkeleton(Skeleton);
|
||||
free(InData);
|
||||
|
||||
for(unsigned i=0; i<MeshCount; i++){
|
||||
if(!Read(MeshPaths[i], &InData))
|
||||
return 0;
|
||||
ReadMesh(Meshes[i]);
|
||||
free(InData);
|
||||
}
|
||||
|
||||
if(!Read("animation.anim", &InData))
|
||||
return 0;
|
||||
ReadAnimation(Animation);
|
||||
free(InData);
|
||||
|
||||
AdvanceFrame(Skeleton, Animation, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
const DemoConfig Demo = {
|
||||
"libvitaboy - Renderer", //Title
|
||||
640,480, //Width, Height
|
||||
Startup, //Startup
|
||||
NULL, //Shutdown
|
||||
InitGL, //InitGL
|
||||
ResizeScene, //ResizeScene
|
||||
DrawScene //DrawScene
|
||||
};
|
||||
}
|
10
library/libvitaboy/THANKS
Normal file
10
library/libvitaboy/THANKS
Normal file
|
@ -0,0 +1,10 @@
|
|||
--------------------------------|----------------------------------------------------------------
|
||||
| Thanks to | for |
|
||||
|--------------------------------|----------------------------------------------------------------|
|
||||
| Don Hopkins | Kickstarting The Sims 1 customization, encouraging fine |
|
||||
| | individuals to document the game, and most importantly, |
|
||||
| | sharing with us his documentation of his VitaBoy skeletal |
|
||||
| | character animation library used in The Sims 1, in the form |
|
||||
| | of articles and videos. Dozens of thanks from each one of us. |
|
||||
| (*) <http://www.donhopkins.com/> |
|
||||
-------------------------------------------------------------------------------------------------
|
159
library/libvitaboy/anim.cpp
Normal file
159
library/libvitaboy/anim.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
anim.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.
|
||||
*/
|
||||
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
static unsigned motionnumber = 0;
|
||||
|
||||
void ReadAnimation(Animation_t& Animation){
|
||||
printf("===== Animation =====\n");
|
||||
Animation.Version = VBFile.readint32();
|
||||
printf("Version: %u\n", Animation.Version);
|
||||
Animation.Name = VBFile.readstring2();
|
||||
printf("Name: %s\n", Animation.Name);
|
||||
Animation.Duration = VBFile.readfloat();
|
||||
printf("Duration: %g\n", Animation.Duration/1000);
|
||||
Animation.Distance = VBFile.readfloat();
|
||||
printf("Distance: %g\n", Animation.Distance);
|
||||
Animation.IsMoving = VBFile.readint8();
|
||||
printf("IsMoving: %u\n", Animation.IsMoving);
|
||||
|
||||
Animation.TranslationsCount = VBFile.readint32();
|
||||
printf("TranslationsCount: %u\n", Animation.TranslationsCount);
|
||||
Animation.TranslationsOffset = VBFile.getpos();
|
||||
VBFile.seekto(Animation.TranslationsOffset + 12*Animation.TranslationsCount);
|
||||
|
||||
Animation.RotationsCount = VBFile.readint32();
|
||||
printf("RotationsCount: %u\n", Animation.RotationsCount);
|
||||
Animation.RotationsOffset = VBFile.getpos();
|
||||
VBFile.seekto(Animation.RotationsOffset + 16*Animation.RotationsCount);
|
||||
|
||||
Animation.MotionsCount = VBFile.readint32();
|
||||
printf("MotionsCount: %u\n", Animation.MotionsCount);
|
||||
Animation.Motions = (Motion_t*) malloc(Animation.MotionsCount * sizeof(Motion_t));
|
||||
for(unsigned i=0; i<Animation.MotionsCount; i++){
|
||||
ReadMotion(Animation, Animation.Motions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadMotion(Animation_t& Animation, Motion_t& Motion){
|
||||
motionnumber++;
|
||||
printf("\n\n [Motion %u]\n", motionnumber);
|
||||
Motion.Unknown = VBFile.readint32();
|
||||
printf(" | Unknown: %u\n", Motion.Unknown);
|
||||
Motion.BoneName = VBFile.readstring();
|
||||
printf(" | BoneName: %s\n", Motion.BoneName);
|
||||
Motion.FrameCount = VBFile.readint32();
|
||||
printf(" | FrameCount: %u\n", Motion.FrameCount);
|
||||
Motion.Duration = VBFile.readfloat();
|
||||
printf(" | Duration: %g\n", Motion.Duration/1000);
|
||||
|
||||
Motion.HasTranslation = VBFile.readint8();
|
||||
printf(" | HasTranslation: %u\n", Motion.HasTranslation);
|
||||
Motion.HasRotation = VBFile.readint8();
|
||||
printf(" | HasRotation: %u\n", Motion.HasRotation);
|
||||
Motion.FirstTranslation = VBFile.readint32();
|
||||
if(Motion.HasTranslation)
|
||||
printf(" | FirstTranslation: %u\n", Motion.FirstTranslation);
|
||||
Motion.FirstRotation = VBFile.readint32();
|
||||
if(Motion.HasRotation)
|
||||
printf(" | FirstRotation: %u\n", Motion.FirstRotation);
|
||||
|
||||
if(Motion.HasTranslation){
|
||||
Motion.Translations = (Translation_t*) malloc(Motion.FrameCount * sizeof(Translation_t));
|
||||
|
||||
unsigned pos = VBFile.getpos();
|
||||
VBFile.seekto(Animation.TranslationsOffset + 12*Motion.FirstTranslation);
|
||||
for(unsigned i=0; i<Motion.FrameCount; i++){
|
||||
Motion.Translations[i].x = -VBFile.readfloat();
|
||||
Motion.Translations[i].y = VBFile.readfloat();
|
||||
Motion.Translations[i].z = VBFile.readfloat();
|
||||
}
|
||||
VBFile.seekto(pos);
|
||||
}
|
||||
|
||||
if(Motion.HasRotation){
|
||||
Motion.Rotations = (Rotation_t*) malloc(Motion.FrameCount * sizeof(Rotation_t));
|
||||
|
||||
unsigned pos = VBFile.getpos();
|
||||
VBFile.seekto(Animation.RotationsOffset + 16*Motion.FirstRotation);
|
||||
for(unsigned i=0; i<Motion.FrameCount; i++){
|
||||
Motion.Rotations[i].x = VBFile.readfloat();
|
||||
Motion.Rotations[i].y = -VBFile.readfloat();
|
||||
Motion.Rotations[i].z = -VBFile.readfloat();
|
||||
Motion.Rotations[i].w = VBFile.readfloat();
|
||||
}
|
||||
VBFile.seekto(pos);
|
||||
}
|
||||
|
||||
Motion.HasPropsLists = VBFile.readint8();
|
||||
printf(" | HasPropsLists: %u\n", Motion.HasPropsLists);
|
||||
if(Motion.HasPropsLists){
|
||||
ReadPropsLists(Motion);
|
||||
}
|
||||
|
||||
Motion.HasTimePropsLists = VBFile.readint8();
|
||||
printf(" | HasTimePropsLists: %u\n", Motion.HasTimePropsLists);
|
||||
if(Motion.HasTimePropsLists){
|
||||
ReadTimePropsLists(Motion);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadPropsList(PropsList_t& PropsList){
|
||||
unsigned count = PropsList.PropsCount = VBFile.readint32();
|
||||
printf(" | | | PropsCount: %u\n", count);
|
||||
PropsList.Props = (Prop_t*) malloc(count * sizeof(Prop_t));
|
||||
|
||||
for(unsigned i=0; i<count; i++){
|
||||
printf(" | | | [Prop %u]\n", i+1);
|
||||
ReadPropEntries(PropsList.Props[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadPropsLists(Motion_t& Motion){
|
||||
unsigned count = Motion.PropsListsCount = VBFile.readint32();
|
||||
Motion.PropsLists = (PropsList_t*) malloc(count * sizeof(PropsList_t));
|
||||
|
||||
for(unsigned i=0; i<count; i++){
|
||||
ReadPropsList(Motion.PropsLists[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadTimePropsList(TimePropsList_t& TimePropsList){
|
||||
unsigned count = TimePropsList.TimePropsCount = VBFile.readint32();
|
||||
printf(" | | TimePropsCount: %u\n", count);
|
||||
TimePropsList.TimeProps = (TimeProp_t*) malloc(count * sizeof(TimeProp_t));
|
||||
|
||||
for(unsigned i=0; i<count; i++){
|
||||
printf(" | | [TimeProp %u]\n", i+1);
|
||||
TimePropsList.TimeProps[i].ID = VBFile.readint32();
|
||||
printf(" | | | ID: %u\n", TimePropsList.TimeProps[i].ID);
|
||||
ReadPropsList(TimePropsList.TimeProps[i].PropsList);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadTimePropsLists(Motion_t& Motion){
|
||||
unsigned count = Motion.TimePropsListsCount = VBFile.readint32();
|
||||
printf(" | TimePropsListsCount: %u\n", count);
|
||||
Motion.TimePropsLists = (TimePropsList_t*) malloc(count * sizeof(TimePropsList_t));
|
||||
|
||||
for(unsigned i=0; i<count; i++){
|
||||
printf(" | [TimePropsList %u]\n", i+1);
|
||||
ReadTimePropsList(Motion.TimePropsLists[i]);
|
||||
}
|
||||
}
|
35
library/libvitaboy/apr.cpp
Normal file
35
library/libvitaboy/apr.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
apr.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.
|
||||
*/
|
||||
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
void ReadAppearance(Appearance_t& Appearance){
|
||||
printf("\n========== Appearance ==========\n");
|
||||
Appearance.Version = VBFile.readint32();
|
||||
printf("Version: %u\n", Appearance.Version);
|
||||
|
||||
ReadAsset(Appearance.Thumbnail, NOGROUP);
|
||||
|
||||
Appearance.BindingCount = VBFile.readint32();
|
||||
printf("Binding count: %u\n", Appearance.BindingCount);
|
||||
Appearance.Bindings = (Asset_t*) malloc(Appearance.BindingCount * sizeof(Asset_t));
|
||||
for(unsigned i=0; i<Appearance.BindingCount; i++){
|
||||
printf("\n [Binding %u]\n", i);
|
||||
ReadAsset(Appearance.Bindings[i], NOGROUP);
|
||||
}
|
||||
}
|
40
library/libvitaboy/bnd.cpp
Normal file
40
library/libvitaboy/bnd.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
bnd.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.
|
||||
*/
|
||||
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
void ReadBinding(Binding_t& Binding){
|
||||
printf("\n========== Binding ==========\n");
|
||||
Binding.Version = VBFile.readint32();
|
||||
printf("Version: %u\n", Binding.Version);
|
||||
|
||||
Binding.BoneName = VBFile.readstring();
|
||||
printf("Bone name: %s\n", Binding.BoneName);
|
||||
|
||||
Binding.MeshDef = VBFile.readint32();
|
||||
if(Binding.MeshDef){
|
||||
printf("\n Mesh:\n");
|
||||
ReadAsset(Binding.Mesh, READGROUP);
|
||||
}
|
||||
|
||||
Binding.AppearanceDef = VBFile.readint32();
|
||||
if(Binding.AppearanceDef){
|
||||
printf("\n Appearance:\n");
|
||||
ReadAsset(Binding.Appearance, READGROUP);
|
||||
}
|
||||
}
|
33
library/libvitaboy/col.cpp
Normal file
33
library/libvitaboy/col.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
col.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.
|
||||
*/
|
||||
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
void ReadCollection(Collection_t& Collection){
|
||||
printf("\n========== Collection ==========\n");
|
||||
Collection.POCount = VBFile.readint32();
|
||||
printf("Purchasable Outfit count: %u\n", Collection.POCount);
|
||||
Collection.PurchasableOutfits = (PODef_t*) malloc(Collection.POCount * sizeof(PODef_t));
|
||||
for(unsigned i=0; i<Collection.POCount; i++){
|
||||
printf("\n [Purchasable Outfit %u]\n", i);
|
||||
|
||||
Collection.PurchasableOutfits[i].Index = VBFile.readint32();
|
||||
printf(" | Index: %u\n", Collection.PurchasableOutfits[i].Index);
|
||||
ReadAsset(Collection.PurchasableOutfits[i].PO, NOGROUP);
|
||||
}
|
||||
}
|
11
library/libvitaboy/config.h
Normal file
11
library/libvitaboy/config.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* config.h - libvitaboy build configuration */
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libvitaboy"
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION_A 1
|
||||
#define VERSION_B 0
|
||||
#define VERSION_C 1
|
||||
#define VERSION_STR "1.0.1"
|
||||
#define REVISION 0
|
28
library/libvitaboy/hag.cpp
Normal file
28
library/libvitaboy/hag.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
libvitaboy - Copyright (c) 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 "libvitaboy.hpp"
|
||||
|
||||
void ReadHandGroup(HandGroup_t& HandGroup){
|
||||
printf("\n========== Hand Group ==========\n");
|
||||
HandGroup.Version = VBFile.readint32();
|
||||
printf("Version: %u\n", HandGroup.Version);
|
||||
|
||||
for(unsigned i=0; i<18; i++){
|
||||
printf("\n [Purchasable Outfit %u]\n", i);
|
||||
ReadAsset(HandGroup.HandAppearances[i], NOGROUP);
|
||||
}
|
||||
}
|
93
library/libvitaboy/libvitaboy.cpp
Normal file
93
library/libvitaboy/libvitaboy.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
libvitaboy.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.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
VBFile_t VBFile;
|
||||
|
||||
void ReadAsset(Asset_t& Asset, bool ReadGroup){
|
||||
Asset.Group = (ReadGroup) ? VBFile.readint32() : 0xA96F6D42;
|
||||
printf(" | Group: %u\n", Asset.Group);
|
||||
Asset.File = VBFile.readint32();
|
||||
printf(" | File: %u\n", Asset.File);
|
||||
Asset.Type = VBFile.readint32();
|
||||
printf(" | Type: %u\n", Asset.Type);
|
||||
}
|
||||
|
||||
void ReadPropEntry(KeyValuePair_t& Entry){
|
||||
Entry.Key = VBFile.readstring();
|
||||
printf(" | | | | | Key: %s\n", Entry.Key);
|
||||
Entry.Value = VBFile.readstring();
|
||||
printf(" | | | | | Value: %s\n", Entry.Value);
|
||||
}
|
||||
|
||||
void ReadPropEntries(Prop_t& Prop){
|
||||
unsigned count = Prop.EntriesCount = VBFile.readint32();
|
||||
printf(" | | | | EntriesCount: %u\n", Prop.EntriesCount);
|
||||
Prop.Entries = (KeyValuePair_t*) malloc(count * sizeof(KeyValuePair_t));
|
||||
|
||||
for(unsigned i=0; i<count; i++){
|
||||
printf(" | | | | [Entry %u]\n", i+1);
|
||||
ReadPropEntry(Prop.Entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
float DotProduct(Rotation_t * q1, Rotation_t * q2){
|
||||
return q1->x*q2->x + q1->y*q2->y + q1->z*q2->z + q1->w*q2->w;
|
||||
}
|
||||
|
||||
void Normalize(Rotation_t * q){
|
||||
float magnitude = q->x*q->x + q->y*q->y + q->z*q->z + q->w*q->w;
|
||||
if(magnitude != 0){
|
||||
magnitude = 1.0f/sqrt(magnitude);
|
||||
q->x *= magnitude;
|
||||
q->y *= magnitude;
|
||||
q->z *= magnitude;
|
||||
q->w *= magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
void FindQuaternionMatrix(float * Matrix, Rotation_t * Quaternion){
|
||||
float x2 = Quaternion->x * Quaternion->x;
|
||||
float y2 = Quaternion->y * Quaternion->y;
|
||||
float z2 = Quaternion->z * Quaternion->z;
|
||||
float xy = Quaternion->x * Quaternion->y;
|
||||
float xz = Quaternion->x * Quaternion->z;
|
||||
float yz = Quaternion->y * Quaternion->z;
|
||||
float wx = Quaternion->w * Quaternion->x;
|
||||
float wy = Quaternion->w * Quaternion->y;
|
||||
float wz = Quaternion->w * Quaternion->z;
|
||||
|
||||
Matrix[0] = 1.0f - 2.0f * (y2 + z2);
|
||||
Matrix[1] = 2.0f * (xy - wz);
|
||||
Matrix[2] = 2.0f * (xz + wy);
|
||||
Matrix[3] = 0.0f;
|
||||
Matrix[4] = 2.0f * (xy + wz);
|
||||
Matrix[5] = 1.0f - 2.0f * (x2 + z2);
|
||||
Matrix[6] = 2.0f * (yz - wx);
|
||||
Matrix[7] = 0.0f;
|
||||
Matrix[8] = 2.0f * (xz - wy);
|
||||
Matrix[9] = 2.0f * (yz + wx);
|
||||
Matrix[10] = 1.0f - 2.0f * (x2 + y2);
|
||||
Matrix[11] = 0.0f;
|
||||
Matrix[12] = 0.0f;
|
||||
Matrix[13] = 0.0f;
|
||||
Matrix[14] = 0.0f;
|
||||
Matrix[15] = 1.0f;
|
||||
}
|
407
library/libvitaboy/libvitaboy.hpp
Normal file
407
library/libvitaboy/libvitaboy.hpp
Normal file
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
libvitaboy.hpp - 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 LIBVITABOY_HPP
|
||||
#define LIBVITABOY_HPP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <FileHandler.hpp>
|
||||
|
||||
/****
|
||||
** Bytestream
|
||||
*/
|
||||
|
||||
class VBFile_t {
|
||||
private:
|
||||
const uint8_t *Buffer, *Position;
|
||||
unsigned Size;
|
||||
|
||||
public:
|
||||
inline void set(const void *_Buffer, unsigned _Size){
|
||||
Buffer = (const uint8_t*) _Buffer;
|
||||
Position = (const uint8_t*) _Buffer;
|
||||
Size = _Size;
|
||||
}
|
||||
|
||||
inline unsigned getpos(){
|
||||
return Position-Buffer;
|
||||
}
|
||||
|
||||
inline void seekto(unsigned offset){
|
||||
Position = Buffer+offset;
|
||||
}
|
||||
inline void seekahead(unsigned count){
|
||||
Position += count;
|
||||
}
|
||||
inline void seekback(unsigned count){
|
||||
Position -= count;
|
||||
}
|
||||
|
||||
inline uint32_t readint32(){
|
||||
uint32_t value = (uint32_t)((Position[0]<<(8*3)) | (Position[1]<<(8*2)) | (Position[2]<<(8*1)) | (Position[3]<<(8*0)));
|
||||
Position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint32_t readint16(){
|
||||
uint16_t value = (uint16_t)((Position[0]<<(8*1)) | (Position[1]<<(8*0)));
|
||||
Position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline uint32_t readint8(){
|
||||
uint8_t value = (uint8_t)((Position[0]<<(8*0)));
|
||||
Position += 1;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline float readfloat(){
|
||||
union { uint32_t i; float f; } value;
|
||||
value.i = (uint32_t)((Position[0]<<(8*0)) | (Position[1]<<(8*1)) | (Position[2]<<(8*2)) | (Position[3]<<(8*3)));
|
||||
Position += 4;
|
||||
return value.f;
|
||||
}
|
||||
|
||||
inline void readbytes(void* Destination, unsigned length){
|
||||
memcpy(Destination, Position, length);
|
||||
Position += length;
|
||||
}
|
||||
|
||||
inline char* readstring(){
|
||||
//Read a Pascal string with 1 length byte
|
||||
unsigned length = readint8();
|
||||
char *string = (char*) malloc(length+1);
|
||||
readbytes(string, length);
|
||||
string[length] = '\0';
|
||||
return string;
|
||||
}
|
||||
|
||||
inline char* readstring2(){
|
||||
//Read a Pascal string with 2 length bytes
|
||||
unsigned length = readint16();
|
||||
char *string = (char*) malloc(length+1);
|
||||
readbytes(string, length);
|
||||
string[length] = '\0';
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
extern VBFile_t VBFile;
|
||||
|
||||
/****
|
||||
** Common
|
||||
*/
|
||||
|
||||
enum ReadGroup {
|
||||
NOGROUP,
|
||||
READGROUP
|
||||
};
|
||||
|
||||
struct Translation_t {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
struct Rotation_t {
|
||||
float x, y, z, w;
|
||||
};
|
||||
|
||||
struct KeyValuePair_t {
|
||||
char * Key;
|
||||
char * Value;
|
||||
};
|
||||
|
||||
struct Prop_t {
|
||||
uint32_t EntriesCount;
|
||||
KeyValuePair_t * Entries;
|
||||
};
|
||||
|
||||
struct PropsList_t {
|
||||
uint32_t PropsCount;
|
||||
Prop_t * Props;
|
||||
};
|
||||
|
||||
void ReadAsset(Asset_t& Asset, bool ReadGroup);
|
||||
void ReadPropEntry(KeyValuePair_t& Entry);
|
||||
void ReadPropEntries(Prop_t& Prop);
|
||||
void ReadPropsList(PropsList_t& PropsList);
|
||||
float DotProduct(Rotation_t * q1, Rotation_t * q2);
|
||||
void Normalize(Rotation_t * q);
|
||||
void CombineQuaternions(Rotation_t * Destination, Rotation_t * Source);
|
||||
void FindQuaternionMatrix(float * Matrix, Rotation_t * Quaternion);
|
||||
|
||||
|
||||
/****
|
||||
** Animation (*.anim)
|
||||
*/
|
||||
|
||||
struct TimeProp_t {
|
||||
uint32_t ID;
|
||||
PropsList_t PropsList;
|
||||
};
|
||||
|
||||
struct TimePropsList_t {
|
||||
uint32_t TimePropsCount;
|
||||
TimeProp_t * TimeProps;
|
||||
};
|
||||
|
||||
struct Motion_t {
|
||||
uint32_t Unknown;
|
||||
char * BoneName;
|
||||
uint32_t FrameCount;
|
||||
float Duration; //Converted to seconds
|
||||
uint8_t HasTranslation;
|
||||
uint8_t HasRotation;
|
||||
uint32_t FirstTranslation;
|
||||
uint32_t FirstRotation;
|
||||
Translation_t * Translations;
|
||||
Rotation_t * Rotations;
|
||||
|
||||
uint8_t HasPropsLists;
|
||||
uint32_t PropsListsCount;
|
||||
PropsList_t * PropsLists;
|
||||
|
||||
uint8_t HasTimePropsLists;
|
||||
uint32_t TimePropsListsCount;
|
||||
TimePropsList_t * TimePropsLists;
|
||||
};
|
||||
|
||||
struct Animation_t {
|
||||
uint32_t Version;
|
||||
char * Name;
|
||||
float Duration; //Converted to seconds
|
||||
float Distance;
|
||||
uint8_t IsMoving;
|
||||
uint32_t TranslationsCount;
|
||||
uint32_t RotationsCount;
|
||||
uint32_t MotionsCount;
|
||||
|
||||
unsigned TranslationsOffset;
|
||||
unsigned RotationsOffset;
|
||||
|
||||
Motion_t * Motions;
|
||||
};
|
||||
|
||||
void ReadAnimation(Animation_t& Animation);
|
||||
void ReadMotion(Animation_t& Animation, Motion_t& Motion);
|
||||
void ReadPropsLists(Motion_t& Motion);
|
||||
void ReadTimePropsList(TimePropsList_t& TimePropsList);
|
||||
void ReadTimePropsLists(Motion_t& Motion);
|
||||
|
||||
|
||||
/****
|
||||
** Appearance (*.apr)
|
||||
*/
|
||||
|
||||
struct Appearance_t {
|
||||
uint32_t Version;
|
||||
Asset_t Thumbnail;
|
||||
uint32_t BindingCount;
|
||||
Asset_t * Bindings;
|
||||
};
|
||||
|
||||
void ReadAppearance(Appearance_t& Appearance);
|
||||
|
||||
|
||||
/****
|
||||
** Binding (*.bnd)
|
||||
*/
|
||||
|
||||
struct Binding_t {
|
||||
uint32_t Version;
|
||||
char * BoneName;
|
||||
uint32_t MeshDef;
|
||||
Asset_t Mesh;
|
||||
uint32_t AppearanceDef;
|
||||
Asset_t Appearance;
|
||||
};
|
||||
|
||||
void ReadBinding(Binding_t& Binding);
|
||||
|
||||
|
||||
/****
|
||||
** Collection (*.col)
|
||||
*/
|
||||
|
||||
struct PODef_t {
|
||||
uint32_t Index;
|
||||
Asset_t PO;
|
||||
};
|
||||
|
||||
struct Collection_t {
|
||||
uint32_t POCount;
|
||||
PODef_t * PurchasableOutfits;
|
||||
};
|
||||
|
||||
void ReadCollection(Collection_t& Collection);
|
||||
|
||||
|
||||
/****
|
||||
** Hand Group (*.hag)
|
||||
*/
|
||||
|
||||
struct HandGroup_t {
|
||||
uint32_t Version;
|
||||
Asset_t HandAppearances[18];
|
||||
};
|
||||
|
||||
void ReadHandGroup(HandGroup_t& HandGroup);
|
||||
|
||||
|
||||
/****
|
||||
** Mesh (*.mesh)
|
||||
*/
|
||||
|
||||
struct TextureVertex_t {
|
||||
float u, v;
|
||||
};
|
||||
|
||||
struct Coord_t {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
struct TextureCoord_t {
|
||||
float u, v;
|
||||
};
|
||||
|
||||
struct NormalCoord_t {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
struct BlendData_t {
|
||||
float Weight;
|
||||
unsigned OtherVertex;
|
||||
};
|
||||
|
||||
struct Vertex_t {
|
||||
Coord_t Coord;
|
||||
TextureCoord_t TextureCoord;
|
||||
NormalCoord_t NormalCoord;
|
||||
|
||||
unsigned BoneIndex;
|
||||
BlendData_t BlendData;
|
||||
};
|
||||
|
||||
struct Face_t {
|
||||
unsigned VertexA, VertexB, VertexC;
|
||||
};
|
||||
|
||||
struct BoneBinding_t {
|
||||
unsigned BoneIndex;
|
||||
unsigned FirstRealVertex;
|
||||
unsigned RealVertexCount;
|
||||
unsigned FirstBlendVertex;
|
||||
unsigned BlendVertexCount;
|
||||
};
|
||||
|
||||
struct Mesh_t {
|
||||
uint32_t Version;
|
||||
uint32_t BoneCount;
|
||||
char ** BoneNames;
|
||||
uint32_t FaceCount;
|
||||
Face_t * FaceData;
|
||||
uint32_t BindingCount;
|
||||
BoneBinding_t * BoneBindings;
|
||||
uint32_t RealVertexCount;
|
||||
uint32_t BlendVertexCount;
|
||||
uint32_t TotalVertexCount;
|
||||
Vertex_t * VertexData;
|
||||
Vertex_t * TransformedVertexData;
|
||||
};
|
||||
|
||||
void ReadMesh(Mesh_t& Mesh);
|
||||
|
||||
|
||||
/****
|
||||
** Outfit (*.oft)
|
||||
*/
|
||||
|
||||
enum OutfitColor {
|
||||
OutfitColor_Light,
|
||||
OutfitColor_Medium,
|
||||
OutfitColor_Dark
|
||||
};
|
||||
|
||||
enum OutfitRegion {
|
||||
OutfitRegion_Head = 0,
|
||||
OutfitRegion_Body = 18
|
||||
};
|
||||
|
||||
struct Outfit_t {
|
||||
uint32_t Version;
|
||||
uint32_t Unknown;
|
||||
Asset_t Appearance[3];
|
||||
uint32_t Group;
|
||||
uint32_t Region;
|
||||
};
|
||||
|
||||
void ReadOutfit(Outfit_t& Outfit);
|
||||
|
||||
|
||||
/****
|
||||
** Purchasable Outfit (*.po)
|
||||
*/
|
||||
|
||||
struct PurchasableOutfit_t {
|
||||
uint32_t Version;
|
||||
uint32_t Unknown;
|
||||
uint32_t OutfitDef;
|
||||
Asset_t Outfit;
|
||||
uint32_t CollectionDef;
|
||||
Asset_t Collection;
|
||||
};
|
||||
|
||||
void ReadPurchasableOutfit(PurchasableOutfit_t& PurchasableOutfit);
|
||||
|
||||
|
||||
/****
|
||||
** Skeleton (*.skel)
|
||||
*/
|
||||
|
||||
struct Bone_t {
|
||||
uint32_t Unknown;
|
||||
char * Name;
|
||||
char * ParentsName;
|
||||
uint8_t HasProps;
|
||||
PropsList_t PropsList;
|
||||
Translation_t Translation;
|
||||
Rotation_t Rotation;
|
||||
uint32_t CanTranslate;
|
||||
uint32_t CanRotate;
|
||||
uint32_t CanBlend;
|
||||
float WiggleValue;
|
||||
float WigglePower;
|
||||
|
||||
unsigned ChildrenCount;
|
||||
Bone_t ** Children;
|
||||
};
|
||||
|
||||
struct Skeleton_t {
|
||||
uint32_t Version;
|
||||
char * Name;
|
||||
uint16_t BoneCount;
|
||||
Bone_t * Bones;
|
||||
};
|
||||
|
||||
void ReadSkeleton(Skeleton_t& Bone);
|
||||
void ReadBone(Skeleton_t& Skeleton, Bone_t& Bone, unsigned Index);
|
||||
unsigned FindBone(Skeleton_t& Skeleton, const char * BoneName, unsigned Count);
|
||||
|
||||
#endif
|
95
library/libvitaboy/mesh.cpp
Normal file
95
library/libvitaboy/mesh.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
mesh.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.
|
||||
*/
|
||||
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
void ReadMesh(Mesh_t& Mesh){
|
||||
printf("\n========== Mesh ==========\n");
|
||||
Mesh.Version = VBFile.readint32();
|
||||
printf("Version: %u\n", Mesh.Version);
|
||||
|
||||
Mesh.BoneCount = VBFile.readint32();
|
||||
printf("BoneCount: %u\n", Mesh.BoneCount);
|
||||
Mesh.BoneNames = (char**) malloc(Mesh.BoneCount * sizeof(char*));
|
||||
for(unsigned i=0; i<Mesh.BoneCount; i++){
|
||||
Mesh.BoneNames[i] = VBFile.readstring();
|
||||
printf("| Bone %u: %s\n", i+1, Mesh.BoneNames[i]);
|
||||
}
|
||||
|
||||
Mesh.FaceCount = VBFile.readint32();
|
||||
printf("FaceCount: %u\n", Mesh.FaceCount);
|
||||
Mesh.FaceData = (Face_t*) malloc(Mesh.FaceCount * sizeof(Face_t));
|
||||
for(unsigned i=0; i<Mesh.FaceCount; i++){
|
||||
Mesh.FaceData[i].VertexA = VBFile.readint32();
|
||||
Mesh.FaceData[i].VertexB = VBFile.readint32();
|
||||
Mesh.FaceData[i].VertexC = VBFile.readint32();
|
||||
}
|
||||
|
||||
Mesh.BindingCount = VBFile.readint32();
|
||||
Mesh.BoneBindings = (BoneBinding_t*) malloc(Mesh.BindingCount * sizeof(BoneBinding_t));
|
||||
printf("BindingCount: %u\n", Mesh.BindingCount);
|
||||
for(unsigned i=0; i<Mesh.BindingCount; i++){
|
||||
Mesh.BoneBindings[i].BoneIndex = VBFile.readint32();
|
||||
Mesh.BoneBindings[i].FirstRealVertex = VBFile.readint32();
|
||||
Mesh.BoneBindings[i].RealVertexCount = VBFile.readint32();
|
||||
Mesh.BoneBindings[i].FirstBlendVertex = VBFile.readint32();
|
||||
Mesh.BoneBindings[i].BlendVertexCount = VBFile.readint32();
|
||||
}
|
||||
|
||||
Mesh.RealVertexCount = VBFile.readint32();
|
||||
printf("RealVertexCount: %u\n", Mesh.RealVertexCount);
|
||||
TextureVertex_t * TextureVertexData = (TextureVertex_t*) malloc(Mesh.RealVertexCount * sizeof(TextureVertex_t));
|
||||
for(unsigned i=0; i<Mesh.RealVertexCount; i++){
|
||||
TextureVertexData[i].u = VBFile.readfloat();
|
||||
TextureVertexData[i].v = -VBFile.readfloat();
|
||||
}
|
||||
|
||||
Mesh.BlendVertexCount = VBFile.readint32();
|
||||
printf("BlendVertexCount: %u\n", Mesh.BlendVertexCount);
|
||||
BlendData_t * BlendData = (BlendData_t*) malloc(Mesh.BlendVertexCount * sizeof(BlendData_t));
|
||||
for(unsigned i=0; i<Mesh.BlendVertexCount; i++){
|
||||
BlendData[i].Weight = (float)VBFile.readint32()/0x8000;
|
||||
BlendData[i].OtherVertex = VBFile.readint32();
|
||||
}
|
||||
|
||||
Mesh.TotalVertexCount = VBFile.readint32();
|
||||
printf("TotalVertexCount: %u\n", Mesh.TotalVertexCount);
|
||||
Mesh.VertexData = (Vertex_t*) malloc(Mesh.TotalVertexCount * sizeof(Vertex_t));
|
||||
Mesh.TransformedVertexData = (Vertex_t*) malloc(Mesh.TotalVertexCount * sizeof(Vertex_t));
|
||||
for(unsigned i=0; i<Mesh.TotalVertexCount; i++){
|
||||
Mesh.VertexData[i].Coord.x = -VBFile.readfloat();
|
||||
Mesh.VertexData[i].Coord.y = VBFile.readfloat();
|
||||
Mesh.VertexData[i].Coord.z = VBFile.readfloat();
|
||||
Mesh.TransformedVertexData[i].NormalCoord.x = -VBFile.readfloat();
|
||||
Mesh.TransformedVertexData[i].NormalCoord.y = VBFile.readfloat();
|
||||
Mesh.TransformedVertexData[i].NormalCoord.z = VBFile.readfloat();
|
||||
|
||||
if(i<Mesh.RealVertexCount){
|
||||
//Fixed vertex
|
||||
Mesh.TransformedVertexData[i].TextureCoord.u = TextureVertexData[i].u;
|
||||
Mesh.TransformedVertexData[i].TextureCoord.v = TextureVertexData[i].v;
|
||||
}else{
|
||||
//Blended vertex
|
||||
Mesh.TransformedVertexData[i].BlendData.Weight = BlendData[i-Mesh.RealVertexCount].Weight;
|
||||
Mesh.TransformedVertexData[i].BlendData.OtherVertex = BlendData[i-Mesh.RealVertexCount].OtherVertex;
|
||||
}
|
||||
}
|
||||
|
||||
free(TextureVertexData);
|
||||
free(BlendData);
|
||||
}
|
39
library/libvitaboy/oft.cpp
Normal file
39
library/libvitaboy/oft.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
oft.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.
|
||||
*/
|
||||
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
void ReadOutfit(Outfit_t& Outfit){
|
||||
printf("\n========== Outfit ==========\n");
|
||||
Outfit.Version = VBFile.readint32();
|
||||
printf("Version: %u\n", Outfit.Version);
|
||||
|
||||
Outfit.Unknown = VBFile.readint32();
|
||||
printf("Unknown: %u\n", Outfit.Unknown);
|
||||
|
||||
const char* Colors[] = {"Light", "Medium", "Dark"};
|
||||
for(unsigned i=0; i<3; i++){
|
||||
printf("\n [%s Appearance]\n", Colors[i]);
|
||||
ReadAsset(Outfit.Appearance[i], NOGROUP);
|
||||
}
|
||||
|
||||
Outfit.Group = VBFile.readint32();
|
||||
printf("Group: %u\n", Outfit.Group);
|
||||
Outfit.Region = VBFile.readint32();
|
||||
printf("Region: %u\n", Outfit.Region);
|
||||
}
|
40
library/libvitaboy/po.cpp
Normal file
40
library/libvitaboy/po.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
po.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.
|
||||
*/
|
||||
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
void ReadPurchasableOutfit(PurchasableOutfit_t& PurchasableOutfit){
|
||||
printf("\n========== Purchasable Outfit ==========\n");
|
||||
PurchasableOutfit.Version = VBFile.readint32();
|
||||
printf("Version: %u\n", PurchasableOutfit.Version);
|
||||
|
||||
PurchasableOutfit.Unknown = VBFile.readint32();
|
||||
printf("Unknown: %u\n", PurchasableOutfit.Unknown);
|
||||
|
||||
PurchasableOutfit.OutfitDef = VBFile.readint32();
|
||||
if(PurchasableOutfit.OutfitDef){
|
||||
printf("\n Outfit:\n");
|
||||
ReadAsset(PurchasableOutfit.Outfit, READGROUP);
|
||||
}
|
||||
|
||||
PurchasableOutfit.CollectionDef = VBFile.readint32();
|
||||
if(PurchasableOutfit.CollectionDef){
|
||||
printf("\n Collection:\n");
|
||||
ReadAsset(PurchasableOutfit.Collection, READGROUP);
|
||||
}
|
||||
}
|
35
library/libvitaboy/resource.rc
Normal file
35
library/libvitaboy/resource.rc
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Name of package */
|
||||
#define PACKAGE "libvitaboy"
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION_A 1
|
||||
#define VERSION_B 0
|
||||
#define VERSION_C 1
|
||||
#define VERSION_STR "1.0.1"
|
||||
#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", "Free, open source C++ OpenGL TSO character rendering and animation library"
|
||||
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
|
97
library/libvitaboy/skel.cpp
Normal file
97
library/libvitaboy/skel.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
skel.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.
|
||||
*/
|
||||
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
void ReadSkeleton(Skeleton_t& Skeleton){
|
||||
printf("\n========== Skeleton ==========\n");
|
||||
Skeleton.Version = VBFile.readint32();
|
||||
printf("Version: %u\n", Skeleton.Version);
|
||||
Skeleton.Name = VBFile.readstring();
|
||||
printf("Name: %s\n", Skeleton.Name);
|
||||
|
||||
Skeleton.BoneCount = VBFile.readint16();
|
||||
printf("BoneCount: %u\n", Skeleton.BoneCount);
|
||||
Skeleton.Bones = (Bone_t*) malloc(Skeleton.BoneCount * sizeof(Bone_t));
|
||||
for(unsigned i=0; i<Skeleton.BoneCount; i++){
|
||||
printf("\n [Bone %u]\n", i);
|
||||
ReadBone(Skeleton, Skeleton.Bones[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadBone(Skeleton_t& Skeleton, Bone_t& Bone, unsigned Index){
|
||||
Bone.Unknown = VBFile.readint32();
|
||||
printf(" | Unknown: %u\n", Bone.Unknown);
|
||||
Bone.Name = VBFile.readstring();
|
||||
printf(" | Name: %s\n", Bone.Name);
|
||||
Bone.ParentsName = VBFile.readstring();
|
||||
printf(" | Parent's name: %s\n", Bone.ParentsName);
|
||||
|
||||
Bone.HasProps = VBFile.readint8();
|
||||
printf(" | HasProps: %u\n", Bone.HasProps);
|
||||
if(Bone.HasProps){
|
||||
ReadPropsList(Bone.PropsList);
|
||||
}
|
||||
|
||||
printf(" | Translation:\n");
|
||||
Bone.Translation.x = -VBFile.readfloat();
|
||||
printf(" | | x: %g\n", Bone.Translation.x);
|
||||
Bone.Translation.y = VBFile.readfloat();
|
||||
printf(" | | y: %g\n", Bone.Translation.y);
|
||||
Bone.Translation.z = VBFile.readfloat();
|
||||
printf(" | | z: %g\n", Bone.Translation.z);
|
||||
printf(" | Rotation:\n");
|
||||
Bone.Rotation.x = VBFile.readfloat();
|
||||
printf(" | | x: %g\n", Bone.Rotation.x);
|
||||
Bone.Rotation.y = -VBFile.readfloat();
|
||||
printf(" | | y: %g\n", Bone.Rotation.y);
|
||||
Bone.Rotation.z = -VBFile.readfloat();
|
||||
printf(" | | z: %g\n", Bone.Rotation.z);
|
||||
Bone.Rotation.w = VBFile.readfloat();
|
||||
printf(" | | w: %g\n", Bone.Rotation.w);
|
||||
|
||||
Bone.CanTranslate = VBFile.readint32();
|
||||
printf(" | CanTranslate: %u\n", Bone.CanTranslate);
|
||||
Bone.CanRotate = VBFile.readint32();
|
||||
printf(" | CanRotate: %u\n", Bone.CanRotate);
|
||||
Bone.CanBlend = VBFile.readint32();
|
||||
printf(" | CanBlend: %u\n", Bone.CanBlend);
|
||||
|
||||
Bone.WiggleValue = VBFile.readfloat();
|
||||
printf(" | WiggleValue: %g\n", Bone.WiggleValue);
|
||||
Bone.WigglePower = VBFile.readfloat();
|
||||
printf(" | WigglePower: %g\n", Bone.WigglePower);
|
||||
|
||||
Bone.ChildrenCount = 0;
|
||||
Bone.Children = (Bone_t**) malloc((Skeleton.BoneCount-Index-1) * sizeof(Bone_t*));
|
||||
|
||||
unsigned Parent = FindBone(Skeleton, Bone.ParentsName, Index);
|
||||
if(Parent != (unsigned)-1){
|
||||
Bone_t& ParentBone = Skeleton.Bones[Parent];
|
||||
ParentBone.Children[ParentBone.ChildrenCount] = &Bone;
|
||||
ParentBone.ChildrenCount++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned FindBone(Skeleton_t& Skeleton, const char * BoneName, unsigned Count){
|
||||
for(unsigned i=0; i<Count; i++){
|
||||
if(!strcmp(Skeleton.Bones[i].Name, BoneName)) return i;
|
||||
}
|
||||
|
||||
return (unsigned)-1;
|
||||
}
|
159
library/libvitaboy/vbparse.cpp
Normal file
159
library/libvitaboy/vbparse.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
libvitaboy - Open source OpenGL TSO character animation library
|
||||
vbparse.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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <FileHandler.hpp>
|
||||
#include "libvitaboy.hpp"
|
||||
|
||||
enum VBFileType {
|
||||
VBFILE_ANIM,
|
||||
VBFILE_APR,
|
||||
VBFILE_BND,
|
||||
VBFILE_COL,
|
||||
VBFILE_HAG,
|
||||
VBFILE_MESH,
|
||||
VBFILE_OFT,
|
||||
VBFILE_PO,
|
||||
VBFILE_SKEL
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
int type;
|
||||
char * InFile;
|
||||
|
||||
if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
|
||||
printf("Usage: vbparse [-t type] infile\n"
|
||||
"Parse a TSO VitaBoy file.\n"
|
||||
"\n"
|
||||
"Supported types:\n"
|
||||
" (*) ANIM - Animation\n"
|
||||
" (*) APR - Appearance\n"
|
||||
" (*) BND - Binding\n"
|
||||
" (*) COL - Collection\n"
|
||||
" (*) HAG - Hand group\n"
|
||||
" (*) MESH - Mesh\n"
|
||||
" (*) OFT - Outfit\n"
|
||||
" (*) PO - Purchasable object\n"
|
||||
" (*) SKEL - Skeleton\n"
|
||||
"\n"
|
||||
"Report bugs to <X-Fi6@phppoll.org>.\n"
|
||||
"vbparse is maintained by the Niotso project.\n"
|
||||
"Home page: <http://www.niotso.org/>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc >= 4 && !strcmp(argv[1], "-t")){
|
||||
if(!stricmp(argv[2], "anim")) type = 0;
|
||||
else if(!stricmp(argv[2], "apr")) type = 1;
|
||||
else if(!stricmp(argv[2], "bnd")) type = 2;
|
||||
else if(!stricmp(argv[2], "col")) type = 3;
|
||||
else if(!stricmp(argv[2], "hag")) type = 4;
|
||||
else if(!stricmp(argv[2], "mesh")) type = 5;
|
||||
else if(!stricmp(argv[2], "oft")) type = 6;
|
||||
else if(!stricmp(argv[2], "po")) type = 7;
|
||||
else if(!stricmp(argv[2], "skel")) type = 8;
|
||||
else{
|
||||
printf("%sUnrecognized type '%s'", "vbparse: Error: ", argv[2]);
|
||||
return -1;
|
||||
}
|
||||
InFile = argv[3];
|
||||
}else{
|
||||
char * pos = strrchr(argv[1], '.') + 1;
|
||||
if(!stricmp(pos, "anim")) type = 0;
|
||||
else if(!stricmp(pos, "apr")) type = 1;
|
||||
else if(!stricmp(pos, "bnd")) type = 2;
|
||||
else if(!stricmp(pos, "col")) type = 3;
|
||||
else if(!stricmp(pos, "hag")) type = 4;
|
||||
else if(!stricmp(pos, "mesh")) type = 5;
|
||||
else if(!stricmp(pos, "oft")) type = 6;
|
||||
else if(!stricmp(pos, "po")) type = 7;
|
||||
else if(!stricmp(pos, "skel")) type = 8;
|
||||
else{
|
||||
printf("%sUnrecognized type", "vbparse: Error: ");
|
||||
return -1;
|
||||
}
|
||||
InFile = argv[1];
|
||||
}
|
||||
|
||||
uint8_t *InData = File::ReadFile(InFile);
|
||||
if(InData == NULL){
|
||||
const char * Message;
|
||||
switch(File::Error){
|
||||
case FERR_NOT_FOUND:
|
||||
Message = "%s does not exist.";
|
||||
break;
|
||||
case FERR_OPEN:
|
||||
Message = "%s could not be opened for reading.";
|
||||
break;
|
||||
case FERR_BLANK:
|
||||
Message = "%s is corrupt or invalid.";
|
||||
break;
|
||||
case FERR_MEMORY:
|
||||
Message = "Memory for %s could not be allocated.";
|
||||
break;
|
||||
default:
|
||||
Message = "%s could not be read.";
|
||||
break;
|
||||
}
|
||||
printf(Message, InFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
VBFile.set(InData, File::FileSize);
|
||||
|
||||
switch(type){
|
||||
case VBFILE_ANIM:
|
||||
Animation_t Animation;
|
||||
ReadAnimation(Animation);
|
||||
break;
|
||||
case VBFILE_APR:
|
||||
Appearance_t Appearance;
|
||||
ReadAppearance(Appearance);
|
||||
break;
|
||||
case VBFILE_BND:
|
||||
Binding_t Binding;
|
||||
ReadBinding(Binding);
|
||||
break;
|
||||
case VBFILE_COL:
|
||||
Collection_t Collection;
|
||||
ReadCollection(Collection);
|
||||
break;
|
||||
case VBFILE_HAG:
|
||||
HandGroup_t HandGroup;
|
||||
ReadHandGroup(HandGroup);
|
||||
break;
|
||||
case VBFILE_MESH:
|
||||
Mesh_t Mesh;
|
||||
ReadMesh(Mesh);
|
||||
break;
|
||||
case VBFILE_OFT:
|
||||
Outfit_t Outfit;
|
||||
ReadOutfit(Outfit);
|
||||
break;
|
||||
case VBFILE_PO:
|
||||
PurchasableOutfit_t PurchasableOutfit;
|
||||
ReadPurchasableOutfit(PurchasableOutfit);
|
||||
break;
|
||||
case VBFILE_SKEL:
|
||||
Skeleton_t Skeleton;
|
||||
ReadSkeleton(Skeleton);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue