mirror of
https://github.com/simtactics/niotso.git
synced 2025-03-22 10:52:20 +00:00
Working UTK decompression!
Additionally: * Moved opus into the Libraries folder * Moved freetype into the Libraries folder
This commit is contained in:
parent
8d06606f28
commit
e53580919a
7 changed files with 605 additions and 16 deletions
|
@ -1,4 +1,4 @@
|
||||||
All you need installed to compile Niotso for Windows, Linux, or Mac is GCC 4.6 or newer.
|
All you need installed to compile Niotso for Windows, Linux, or Mac is GCC 4.6 or newer, and NASM for libjpeg-turbo.
|
||||||
|
|
||||||
Run "make" in this directory to compile every package. -j # will greatly speed up the compile time for processors with # cores.
|
Run "make" in this directory to compile every package. -j # will greatly speed up the compile time for processors with # cores.
|
||||||
Run "make install" after compiling to install Niotso to your game directory; please specify it first in the Makefile.
|
Run "make install" after compiling to install Niotso to your game directory; please specify it first in the Makefile.
|
||||||
|
|
30
Libraries/FileHandler/utk/Makefile
Normal file
30
Libraries/FileHandler/utk/Makefile
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# macros --------------------------------------------------------------------
|
||||||
|
CC = gcc
|
||||||
|
LD = gcc
|
||||||
|
CFLAGS = -m32 -Wall -Wextra -Wabi -Os -march=i686 -fomit-frame-pointer -g0
|
||||||
|
LDFLAGS = -m32 -s -fwhole-program
|
||||||
|
|
||||||
|
AR = ar rcs
|
||||||
|
WINDRES = windres -F pe-i386
|
||||||
|
|
||||||
|
OBJECTS = obj/read_utk.o obj/utkdecode.o
|
||||||
|
|
||||||
|
# These will rebuild the entire library upon edit.
|
||||||
|
DEPS = Makefile \
|
||||||
|
read_utk.h
|
||||||
|
|
||||||
|
# dependencies --------------------------------------------------------------
|
||||||
|
all: utkdecode.exe
|
||||||
|
|
||||||
|
$(OBJECTS): $(DEPS)
|
||||||
|
|
||||||
|
utkdecode.exe: $(OBJECTS)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $(OBJECTS)
|
||||||
|
|
||||||
|
# make rules ----------------------------------------------------------------
|
||||||
|
obj/%.o: %.c
|
||||||
|
$(CC) -c -ansi -pedantic $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
# maintenance ---------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
del /Q /S obj utkdecode.exe
|
325
Libraries/FileHandler/utk/read_utk.c
Normal file
325
Libraries/FileHandler/utk/read_utk.c
Normal file
|
@ -0,0 +1,325 @@
|
||||||
|
/*
|
||||||
|
read_utk.c - Copyright (c) 2011 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 <windows.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 round
|
||||||
|
#define round(x) ((x) >= 0 ? (x)+0.5 : (x)-0.5)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __inline
|
||||||
|
#define __inline
|
||||||
|
#endif
|
||||||
|
#ifndef __restrict
|
||||||
|
#define __restrict
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float UTKTable1[64];
|
||||||
|
uint8_t UTKTable2[512];
|
||||||
|
const uint8_t UTKTable3[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};
|
||||||
|
float UTKTable4[29];
|
||||||
|
|
||||||
|
int utk_read_header(utkheader_t * UTKHeader, const uint8_t * Buffer, unsigned FileSize)
|
||||||
|
{
|
||||||
|
if(FileSize < 28) 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, unsigned Frames){
|
||||||
|
utkparams_t p;
|
||||||
|
p.InData = InBuffer;
|
||||||
|
SetUTKParameters(&p);
|
||||||
|
|
||||||
|
while(Frames){
|
||||||
|
int i, BlockSize = (Frames > 432) ? 432 : Frames;
|
||||||
|
DecompressBlock(&p);
|
||||||
|
|
||||||
|
for(i=0; i<BlockSize; i++){
|
||||||
|
int value = round(p.DecompressedBlock[i]);
|
||||||
|
|
||||||
|
if(value < -32767)
|
||||||
|
value = 32767;
|
||||||
|
else if(value > 32768)
|
||||||
|
value = 98304;
|
||||||
|
|
||||||
|
*(OutBuffer++) = (value&0x00FFu)>>(8*0);
|
||||||
|
*(OutBuffer++) = (value&0xFF00u)>>(8*1);
|
||||||
|
}
|
||||||
|
Frames -= BlockSize;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UTKGenerateTables(void){
|
||||||
|
/* Call once */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* UTKTable1 */
|
||||||
|
UTKTable1[0] = 0;
|
||||||
|
for(i=-31; i<32; i++){
|
||||||
|
int s = (i>=0) ? 1 : -1;
|
||||||
|
if (s*i<14) UTKTable1[i+32] = i*.051587f;
|
||||||
|
else if(s*i<25) UTKTable1[i+32] = i*.051587f/2 + s*.337503f;
|
||||||
|
else UTKTable1[i+32] = i*.051587f/8 + s*.796876f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UTKTable2 */
|
||||||
|
for(i=0; i<512; i++){
|
||||||
|
switch(i%4){
|
||||||
|
case 0: UTKTable2[i] = 4; break;
|
||||||
|
case 1: UTKTable2[i] = (i<256) ? 6 : (11 + (i%8 > 4)); break;
|
||||||
|
case 2: UTKTable2[i] = (i<256) ? 5 : (7 + (i%8 > 4)); break;
|
||||||
|
case 3: {
|
||||||
|
uint8_t l1[] = {9,15,13,19,10,16};
|
||||||
|
uint8_t l2[] = {17,21,18,25,17,22,18,00,17,21,18,26,17,22,18,02,
|
||||||
|
23,27,24,01,23,28,24,03,23,27,24,01,23,28,24,03};
|
||||||
|
if(i%16 < 4) UTKTable2[i] = l1[0 + (i>256)];
|
||||||
|
else if(i%16 < 8) UTKTable2[i] = l1[2 + (i>256)] + (i%32 > 16);
|
||||||
|
else if(i%16 < 12) UTKTable2[i] = l1[4 + (i>256)];
|
||||||
|
else UTKTable2[i] = l2[i/16];
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UTKTable4 */
|
||||||
|
UTKTable4[0] = 0;
|
||||||
|
for(i=0; i<7; i++){
|
||||||
|
UTKTable4[4*i+1] = -i;
|
||||||
|
UTKTable4[4*i+2] = +i;
|
||||||
|
UTKTable4[4*i+3] = -i;
|
||||||
|
UTKTable4[4*i+4] = +i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadBits(utkparams_t *p, uint8_t i){
|
||||||
|
unsigned returnvalue = (255>>(8-i)) & p->x;
|
||||||
|
p->x >>= i;
|
||||||
|
p->y -= i;
|
||||||
|
|
||||||
|
if(p->y < 8){
|
||||||
|
unsigned value = *(p->InData++);
|
||||||
|
p->x |= value << (p->y&0xFF);
|
||||||
|
p->y += 8;
|
||||||
|
}
|
||||||
|
return returnvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUTKParameters(utkparams_t *p){
|
||||||
|
int i;
|
||||||
|
float s;
|
||||||
|
p->x = *(p->InData++);
|
||||||
|
p->y = 8;
|
||||||
|
p->a = ReadBits(p, 1);
|
||||||
|
p->b = 32 - ReadBits(p, 4);
|
||||||
|
p->c[0] = (ReadBits(p, 4)+1)*8;
|
||||||
|
|
||||||
|
s = ((float)ReadBits(p, 6))/1000 + 1.04;
|
||||||
|
for(i=1; i<64; i++)
|
||||||
|
p->c[i] = p->c[i-1]*s;
|
||||||
|
|
||||||
|
memset(&p->c[64], 0, 24*sizeof(float));
|
||||||
|
memset(p->d, 0, 324*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecompressBlock(utkparams_t *p){
|
||||||
|
int i,j;
|
||||||
|
float Window[118];
|
||||||
|
float Matrix[12];
|
||||||
|
int Branch = 0;
|
||||||
|
|
||||||
|
memset(&Window[0], 0, 5*sizeof(float));
|
||||||
|
memset(&Window[113], 0, 5*sizeof(float));
|
||||||
|
|
||||||
|
for(i=0; i<12; i++){
|
||||||
|
unsigned result = ReadBits(p, (i<4) ? 6 : 5);
|
||||||
|
if(i==0 && p->b > result) Branch++;
|
||||||
|
Matrix[i] = (UTKTable1[result + ((i<4)?0:16)] - p->c[64+i])/4;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<4; i++){
|
||||||
|
float c1, c2;
|
||||||
|
int o = (int)ReadBits(p, 8);
|
||||||
|
c1 = ((float)ReadBits(p, 4))/15;
|
||||||
|
c2 = p->c[ReadBits(p, 6)];
|
||||||
|
|
||||||
|
if(!p->a){
|
||||||
|
Unknown1(p, Branch, &Window[5], 1);
|
||||||
|
}else{
|
||||||
|
unsigned x = ReadBits(p, 1);
|
||||||
|
unsigned y = ReadBits(p, 1);
|
||||||
|
Unknown1(p, Branch, &Window[5+x], 2);
|
||||||
|
|
||||||
|
if(y){
|
||||||
|
for(j=0; j<108; j+=2)
|
||||||
|
Window[6-x + j] = 0;
|
||||||
|
}else{
|
||||||
|
float *z = &Window[6-x];
|
||||||
|
for(j=0; j<54; j++, z+=2)
|
||||||
|
*z =
|
||||||
|
(z[-5]+z[+5]) * .0180326793f
|
||||||
|
- (z[-3]+z[+3]) * .1145915613f
|
||||||
|
+ (z[-1]+z[+1]) * .5973859429f;
|
||||||
|
|
||||||
|
c2 /= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(j=0; j<108; j++)
|
||||||
|
p->DecompressedBlock[108*i + j] = c2*Window[5+j] + c1*p->d[216 + 108*i + j - o];
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(p->d, &p->DecompressedBlock[108], 324*sizeof(DWORD));
|
||||||
|
|
||||||
|
for(i=0; i<4; i++){
|
||||||
|
for(j=0; j<12; j++)
|
||||||
|
p->c[64+j] += Matrix[j];
|
||||||
|
|
||||||
|
Unknown2(p, i*12, (i!=3) ? 1 : 33);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unknown1(utkparams_t *p, int Branch, float * Window, int Interval){
|
||||||
|
if(Branch != 0){
|
||||||
|
unsigned a = 0;
|
||||||
|
unsigned i = 0;
|
||||||
|
while(i<108){
|
||||||
|
unsigned value = UTKTable2[(a<<8) | (p->x&0xFF)];
|
||||||
|
a = (value<2 || value>8);
|
||||||
|
ReadBits(p, UTKTable3[value]);
|
||||||
|
|
||||||
|
if(value >= 4){
|
||||||
|
Window[i] = UTKTable4[value];
|
||||||
|
i += Interval;
|
||||||
|
}else{
|
||||||
|
if(value > 1){
|
||||||
|
unsigned x = ReadBits(p, 6)+7;
|
||||||
|
if(x > (108 - i)/Interval)
|
||||||
|
x = (108 - i)/Interval;
|
||||||
|
|
||||||
|
while(x--){
|
||||||
|
Window[i] = 0;
|
||||||
|
i += Interval;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Window[i] = 7;
|
||||||
|
while(ReadBits(p, 1))
|
||||||
|
Window[i]++;
|
||||||
|
|
||||||
|
if(!ReadBits(p, 1))
|
||||||
|
Window[i] *= -1;
|
||||||
|
|
||||||
|
i += Interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
int i;
|
||||||
|
for(i=0; i<108; i+=Interval){
|
||||||
|
uint8_t b;
|
||||||
|
switch(p->x & 3){
|
||||||
|
case 3:
|
||||||
|
Window[i] = 2.0;
|
||||||
|
b = 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Window[i] = -2.0;
|
||||||
|
b = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Window[i] = 0.0;
|
||||||
|
b = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadBits(p, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unknown2(utkparams_t *p, unsigned Sample, unsigned Blocks){
|
||||||
|
unsigned i,j;
|
||||||
|
float Matrix[12];
|
||||||
|
int offset = 75;
|
||||||
|
Unknown2_1(&p->c[64], Matrix);
|
||||||
|
|
||||||
|
for(i=0; i<Blocks*12; i++){
|
||||||
|
float x = p->DecompressedBlock[Sample];
|
||||||
|
for(j=0; j<12; j++){
|
||||||
|
if(++offset == 88) offset = 76;
|
||||||
|
x += p->c[offset] * Matrix[j];
|
||||||
|
}
|
||||||
|
p->c[offset--] = x;
|
||||||
|
p->DecompressedBlock[Sample++] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unknown2_1(float *__restrict c64, float *__restrict Matrix){
|
||||||
|
int i,j;
|
||||||
|
float LocalMatrix1[12];
|
||||||
|
float LocalMatrix2[12];
|
||||||
|
LocalMatrix2[0] = 1;
|
||||||
|
memcpy(&LocalMatrix2[1], c64, 11*sizeof(float));
|
||||||
|
|
||||||
|
for(i=0; i<12; i++){
|
||||||
|
float x = 0;
|
||||||
|
for(j=11; j>=0; j--){
|
||||||
|
x -= c64[j] * LocalMatrix2[j];
|
||||||
|
if(j != 11)
|
||||||
|
LocalMatrix2[j+1] = x*c64[j] + LocalMatrix2[j];
|
||||||
|
}
|
||||||
|
LocalMatrix2[0] = x;
|
||||||
|
LocalMatrix1[i] = x;
|
||||||
|
|
||||||
|
for(j=0; j<i; j++)
|
||||||
|
x -= LocalMatrix1[i-j-1] * Matrix[j];
|
||||||
|
|
||||||
|
Matrix[i] = x;
|
||||||
|
}
|
||||||
|
}
|
60
Libraries/FileHandler/utk/read_utk.h
Normal file
60
Libraries/FileHandler/utk/read_utk.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
read_utk.h - Copyright (c) 2011 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];
|
||||||
|
DWORD dwOutSize;
|
||||||
|
DWORD dwWfxSize;
|
||||||
|
/* WAVEFORMATEX */
|
||||||
|
WORD wFormatTag;
|
||||||
|
WORD nChannels;
|
||||||
|
DWORD nSamplesPerSec;
|
||||||
|
DWORD nAvgBytesPerSec;
|
||||||
|
WORD nBlockAlign;
|
||||||
|
WORD wBitsPerSample;
|
||||||
|
DWORD cbSize;
|
||||||
|
|
||||||
|
unsigned Frames;
|
||||||
|
unsigned UTKDataSize;
|
||||||
|
} utkheader_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const uint8_t *InData;
|
||||||
|
unsigned x, y;
|
||||||
|
unsigned a, b;
|
||||||
|
float c[88];
|
||||||
|
float d[324];
|
||||||
|
float DecompressedBlock[432];
|
||||||
|
} utkparams_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int utk_read_header(utkheader_t * UTKHeader, const uint8_t * Buffer, unsigned FileSize);
|
||||||
|
int utk_decode(const uint8_t *__restrict InBuffer, uint8_t *__restrict OutBuffer, unsigned Frames);
|
||||||
|
void UTKGenerateTables(void);
|
||||||
|
uint8_t ReadCC(utkparams_t *p, uint8_t i);
|
||||||
|
void SetUTKParameters(utkparams_t *p);
|
||||||
|
void DecompressBlock(utkparams_t *p);
|
||||||
|
void Unknown1(utkparams_t *p, int Branch, float * Window, int Interval);
|
||||||
|
void Unknown2(utkparams_t *p, unsigned Sample, unsigned Blocks);
|
||||||
|
void Unknown2_1(float *__restrict c64, float *__restrict Matrix);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
164
Libraries/FileHandler/utk/utkdecode.c
Normal file
164
Libraries/FileHandler/utk/utkdecode.c
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
utkdecode.c - Copyright (c) 2011 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 <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include "read_utk.h"
|
||||||
|
|
||||||
|
#ifndef write_int32
|
||||||
|
#define write_uint32(dest, src) \
|
||||||
|
(dest)[0] = ((src)&0x000000FF)>>(8*0); \
|
||||||
|
(dest)[1] = ((src)&0x0000FF00)>>(8*1); \
|
||||||
|
(dest)[2] = ((src)&0x00FF0000)>>(8*2); \
|
||||||
|
(dest)[3] = ((src)&0xFF000000)>>(8*3)
|
||||||
|
#define write_uint16(dest, src) \
|
||||||
|
(dest)[0] = ((src)&0x00FF)>>(8*0); \
|
||||||
|
(dest)[1] = ((src)&0xFF00)>>(8*1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
int overwrite = 0;
|
||||||
|
char *InFile, *OutFile;
|
||||||
|
HANDLE hFile;
|
||||||
|
HANDLE ProcessHeap = GetProcessHeap();
|
||||||
|
unsigned FileSize;
|
||||||
|
DWORD bytestransferred = 0;
|
||||||
|
uint8_t * UTKData;
|
||||||
|
utkheader_t UTKHeader;
|
||||||
|
|
||||||
|
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/>");
|
||||||
|
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 = CreateFile(InFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
if(hFile == INVALID_HANDLE_VALUE){
|
||||||
|
if(GetLastError() == ERROR_FILE_NOT_FOUND){
|
||||||
|
printf("%sThe specified input file does not exist.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
printf("%sThe input file could not be opened for reading.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
FileSize = GetFileSize(hFile, NULL);
|
||||||
|
if(FileSize < 24){
|
||||||
|
printf("%sNot a valid UTK file.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
UTKData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, FileSize);
|
||||||
|
if(UTKData == NULL){
|
||||||
|
printf("%sMemory for this file could not be allocated.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(!ReadFile(hFile, UTKData, FileSize, &bytestransferred, NULL) || bytestransferred != FileSize){
|
||||||
|
printf("%sThe input file could not be read.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
|
||||||
|
/****
|
||||||
|
** Transcode the data from UTK to LPCM
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(!utk_read_header(&UTKHeader, UTKData, FileSize)){
|
||||||
|
printf("%sNot a valid UTK file.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc >= 3){ /* Transcode */
|
||||||
|
uint8_t * WaveData = HeapAlloc(ProcessHeap, HEAP_NO_SERIALIZE, 44+UTKHeader.dwOutSize);
|
||||||
|
if(WaveData == NULL){
|
||||||
|
printf("%sMemory for this file could not be allocated.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
UTKGenerateTables();
|
||||||
|
|
||||||
|
if(!utk_decode(UTKData+32, WaveData+44, UTKHeader.Frames)){
|
||||||
|
printf("%sMemory for this file could not be allocated.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(ProcessHeap, HEAP_NO_SERIALIZE, UTKData);
|
||||||
|
|
||||||
|
/****
|
||||||
|
** 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
hFile = CreateFile(OutFile, GENERIC_WRITE, 0, NULL, CREATE_NEW+overwrite,
|
||||||
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
if(hFile == INVALID_HANDLE_VALUE){
|
||||||
|
if(!overwrite && GetLastError() == ERROR_FILE_EXISTS){
|
||||||
|
char c;
|
||||||
|
printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile);
|
||||||
|
c = getchar();
|
||||||
|
if(c != 'y' && c != 'Y'){
|
||||||
|
printf("\nAborted.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
hFile = CreateFile(OutFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||||
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
}
|
||||||
|
if(hFile == INVALID_HANDLE_VALUE){
|
||||||
|
printf("%sThe output file could not be opened for writing.", "utkdecode: error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WriteFile(hFile, WaveData, 44+UTKHeader.dwOutSize, &bytestransferred, NULL);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -37,12 +37,12 @@
|
||||||
|
|
||||||
unsigned xa_compressed_size(unsigned Frames, unsigned Channels)
|
unsigned xa_compressed_size(unsigned Frames, unsigned Channels)
|
||||||
{
|
{
|
||||||
/* The required input size is:
|
/* This function calculates the size of compressed XA data with known frames and channels, as such:
|
||||||
** Channels * (ceil(n/2) + ceil(n/28))
|
** Channels * (ceil(Frames/2) + ceil(Frames/28))
|
||||||
** | a | | b |
|
** | a | | b |
|
||||||
**
|
**
|
||||||
** a = The space required for all 2-sample bytes in the XA data for a single channel (Period: 2 frames)
|
** 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 (Period: 28 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
|
** (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.
|
** This source package assumes a partial block at the end of the XA data is legal but a partial frame is not.
|
||||||
|
|
30
Makefile
30
Makefile
|
@ -7,6 +7,9 @@ buildenv = cmd
|
||||||
# Installation directory (do not use backslashes)
|
# Installation directory (do not use backslashes)
|
||||||
installdir = c:/Program Files (x86)/Maxis/The Sims Online/Niotso
|
installdir = c:/Program Files (x86)/Maxis/The Sims Online/Niotso
|
||||||
|
|
||||||
|
# Debugging (valid options: yes no)
|
||||||
|
debug = no
|
||||||
|
|
||||||
# Profile-guided optimization (valid options: none instrument optimize)
|
# Profile-guided optimization (valid options: none instrument optimize)
|
||||||
pgo = none
|
pgo = none
|
||||||
|
|
||||||
|
@ -21,6 +24,8 @@ LDFLAGS = -m32 -static -static-libgcc
|
||||||
ARFLAGS = rcs
|
ARFLAGS = rcs
|
||||||
RCFLAGS = -F pe-i386
|
RCFLAGS = -F pe-i386
|
||||||
|
|
||||||
|
CFLAGS_LANG_C =
|
||||||
|
CFLAGS_LANG_CPP =
|
||||||
|
|
||||||
####
|
####
|
||||||
## [Profiles]
|
## [Profiles]
|
||||||
|
@ -46,13 +51,13 @@ WARNINGS = -Wall -Wextra -pedantic
|
||||||
ifeq ($(buildenv),cmd)
|
ifeq ($(buildenv),cmd)
|
||||||
RM_R = -@del /s /q
|
RM_R = -@del /s /q
|
||||||
CP_F = copy /y
|
CP_F = copy /y
|
||||||
EXE = .exe
|
EXE = .exe
|
||||||
DLL = .dll
|
DLL = .dll
|
||||||
else
|
else
|
||||||
RM_R = -@rm -r
|
RM_R = -@rm -r
|
||||||
CP_F = cp -f
|
CP_F = cp -f
|
||||||
EXE =
|
EXE =
|
||||||
DLL = .so
|
DLL = .so
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(pgo),instrument)
|
ifeq ($(pgo),instrument)
|
||||||
|
@ -68,11 +73,16 @@ endif
|
||||||
|
|
||||||
include packages.makefile
|
include packages.makefile
|
||||||
|
|
||||||
|
filter_obj = *.o *.lo *.la *.Plo *.Pla *.gch *.pch *.obj *.res *.exp *.dep *.aps *.intermediate.manifest
|
||||||
|
filter_exe = *.exe *.dll *.so *.a *.lib
|
||||||
|
filter_profile = *.gcda
|
||||||
|
filter_dist = *.dsp *.dsw *.user *.ncb *.pdb *.idb *.opt *.plg *.suo */BuildLog.htm
|
||||||
|
|
||||||
objclean:
|
objclean:
|
||||||
$(RM_R) *.o *.lo *.la *.Plo *.Pla *.gch *.pch *.obj *.res
|
$(RM_R) $(filter_obj)
|
||||||
|
|
||||||
clean: objclean
|
clean: objclean
|
||||||
$(RM_R) *.exe *.dll *.so *.a *.lib
|
$(RM_R) $(filter_obj) $(filter_exe)
|
||||||
|
profileclean:
|
||||||
distclean: clean
|
$(RM_R) $(filter_profile)
|
||||||
$(RM_R) *.gcda
|
distclean:
|
||||||
|
$(RM_R) $(filter_obj) $(filter_exe) $(filter_profile) $(filter_dist)
|
Loading…
Add table
Reference in a new issue