mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-04 21:50:35 -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
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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue