mirror of
https://github.com/simtactics/niotso.git
synced 2025-03-15 08:11:22 +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 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)
|
||||
{
|
||||
/* The required input size is:
|
||||
** Channels * (ceil(n/2) + ceil(n/28))
|
||||
** | a | | b |
|
||||
/* 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 2-sample bytes in the XA data for a single channel (Period: 2 frames)
|
||||
** b = The space required for all control bytes in the XA data for a single channel (Period: 28 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 (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.
|
||||
|
|
30
Makefile
30
Makefile
|
@ -7,6 +7,9 @@ buildenv = cmd
|
|||
# Installation directory (do not use backslashes)
|
||||
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)
|
||||
pgo = none
|
||||
|
||||
|
@ -21,6 +24,8 @@ LDFLAGS = -m32 -static -static-libgcc
|
|||
ARFLAGS = rcs
|
||||
RCFLAGS = -F pe-i386
|
||||
|
||||
CFLAGS_LANG_C =
|
||||
CFLAGS_LANG_CPP =
|
||||
|
||||
####
|
||||
## [Profiles]
|
||||
|
@ -46,13 +51,13 @@ WARNINGS = -Wall -Wextra -pedantic
|
|||
ifeq ($(buildenv),cmd)
|
||||
RM_R = -@del /s /q
|
||||
CP_F = copy /y
|
||||
EXE = .exe
|
||||
DLL = .dll
|
||||
EXE = .exe
|
||||
DLL = .dll
|
||||
else
|
||||
RM_R = -@rm -r
|
||||
CP_F = cp -f
|
||||
EXE =
|
||||
DLL = .so
|
||||
EXE =
|
||||
DLL = .so
|
||||
endif
|
||||
|
||||
ifeq ($(pgo),instrument)
|
||||
|
@ -68,11 +73,16 @@ endif
|
|||
|
||||
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:
|
||||
$(RM_R) *.o *.lo *.la *.Plo *.Pla *.gch *.pch *.obj *.res
|
||||
|
||||
$(RM_R) $(filter_obj)
|
||||
clean: objclean
|
||||
$(RM_R) *.exe *.dll *.so *.a *.lib
|
||||
|
||||
distclean: clean
|
||||
$(RM_R) *.gcda
|
||||
$(RM_R) $(filter_obj) $(filter_exe)
|
||||
profileclean:
|
||||
$(RM_R) $(filter_profile)
|
||||
distclean:
|
||||
$(RM_R) $(filter_obj) $(filter_exe) $(filter_profile) $(filter_dist)
|
Loading…
Add table
Reference in a new issue