Initial commit
This commit is contained in:
19
channel/banner/tools/Makefile
Normal file
19
channel/banner/tools/Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
CFLAGS = -O3 -Wall -I/usr/local/include -L/usr/local/lib
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
STRIP = $(PREFIX)strip
|
||||
|
||||
all: mkbns$(EXE) png2tpl$(EXE) lz77$(EXE)
|
||||
|
||||
mkbns$(EXE): mkbns.c
|
||||
$(CC) $(CFLAGS) -o mkbns mkbns.c -lm
|
||||
|
||||
png2tpl$(EXE): png2tpl.c
|
||||
$(CC) $(CFLAGS) -o png2tpl png2tpl.c -lpng
|
||||
|
||||
lz77$(EXE): lz77.c
|
||||
$(CC) $(CFLAGS) -o lz77 lz77.c
|
||||
|
||||
clean:
|
||||
rm -f mkbns$(EXE) png2tpl$(EXE) lz77$(EXE)
|
||||
13
channel/banner/tools/addimd5.py
Normal file
13
channel/banner/tools/addimd5.py
Normal file
@@ -0,0 +1,13 @@
|
||||
import md5, sys, struct
|
||||
|
||||
data= open(sys.argv[1]).read()
|
||||
|
||||
digest = md5.new(data).digest()
|
||||
|
||||
hdr = struct.pack(">4sI8x","IMD5",len(data))
|
||||
|
||||
f2 = open(sys.argv[2],"w")
|
||||
f2.write(hdr)
|
||||
f2.write(digest)
|
||||
f2.write(data)
|
||||
f2.close()
|
||||
48
channel/banner/tools/join-imet.py
Normal file
48
channel/banner/tools/join-imet.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import os, sys, struct, md5
|
||||
|
||||
output, datafile, iconarc, bannerarc, soundbns, namesfile = sys.argv[1:]
|
||||
|
||||
data = open(datafile,"r").read()
|
||||
|
||||
names={}
|
||||
|
||||
for i in open(namesfile,"r"):
|
||||
a,b = i.split("=")
|
||||
while b[-1] == "\n":
|
||||
b = b[:-1]
|
||||
b = b.replace("\\n","\n")
|
||||
names[a] = b.decode("utf-8")
|
||||
|
||||
def getsize(x):
|
||||
return os.stat(x).st_size
|
||||
|
||||
def pad(x,l):
|
||||
if len(x) > l:
|
||||
raise ValueError("%d > %d",len(x),l)
|
||||
n = l-len(x)
|
||||
return x + "\x00"*n
|
||||
|
||||
imet = "\x00"*0x40
|
||||
imet += struct.pack(">4sIIIIII","IMET",0x600,3,getsize(iconarc),getsize(bannerarc),getsize(soundbns),1)
|
||||
|
||||
for i in ["jp", "en", "de", "fr", "sp", "it", "nl", "cn", None, "ko"]:
|
||||
try:
|
||||
imet += pad(names[i].encode("UTF-16BE"),0x54)
|
||||
except KeyError:
|
||||
imet += "\x00"*0x54
|
||||
imet += "\x00"*(0x600 - len(imet))
|
||||
|
||||
imet = imet[:-16] + md5.new(imet).digest()
|
||||
|
||||
open(output,"w").write(imet)
|
||||
|
||||
f = open(sys.argv[1],"w")
|
||||
f.write(imet)
|
||||
f.write(data)
|
||||
|
||||
fsize = f.tell()
|
||||
|
||||
if (fsize % 20) != 0:
|
||||
f.write("\x00"*(20-(fsize%20)))
|
||||
|
||||
f.close()
|
||||
273
channel/banner/tools/lz77.c
Normal file
273
channel/banner/tools/lz77.c
Normal file
@@ -0,0 +1,273 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*Altered by Kuwanger*/
|
||||
/*************************************************************************
|
||||
* Name: lz.c
|
||||
* Author: Marcus Geelnard
|
||||
* Description: LZ77 coder/decoder implementation.
|
||||
* Reentrant: Yes
|
||||
* $Id: lz.c,v 1.4 2004/10/08 19:28:04 marcus256 Exp $
|
||||
*
|
||||
* The LZ77 compression scheme is a substitutional compression scheme
|
||||
* proposed by Abraham Lempel and Jakob Ziv in 1977. It is very simple in
|
||||
* its design, and uses no fancy bit level compression.
|
||||
*
|
||||
* This is my first attempt at an implementation of a LZ77 code/decoder.
|
||||
*
|
||||
* The principle of the LZ77 compression algorithm is to store repeated
|
||||
* occurrences of strings as references to previous occurrences of the same
|
||||
* string. The point is that the reference consumes less space than the
|
||||
* string itself, provided that the string is long enough (in this
|
||||
* implementation, the string has to be at least 4 bytes long, since the
|
||||
* minimum coded reference is 3 bytes long). Also note that the term
|
||||
* "string" refers to any kind of byte sequence (it does not have to be
|
||||
* an ASCII string, for instance).
|
||||
*
|
||||
* The coder uses a brute force approach to finding string matches in the
|
||||
* history buffer (or "sliding window", if you wish), which is very, very
|
||||
* slow. I recon the complexity is somewhere between O(n^2) and O(n^3),
|
||||
* depending on the input data.
|
||||
*
|
||||
* There is also a faster implementation that uses a large working buffer
|
||||
* in which a "jump table" is stored, which is used to quickly find
|
||||
* possible string matches (see the source code for LZ_CompressFast() for
|
||||
* more information). The faster method is an order of magnitude faster,
|
||||
* and also does a full string search in the entire input buffer (it does
|
||||
* not use a sliding window).
|
||||
*
|
||||
* The upside is that decompression is very fast, and the compression ratio
|
||||
* is often very good.
|
||||
*
|
||||
* The reference to a string is coded as a (length,offset) pair, where the
|
||||
* length indicates the length of the string, and the offset gives the
|
||||
* offset from the current data position. To distinguish between string
|
||||
* references and literal strings (uncompressed bytes), a string reference
|
||||
* is preceded by a marker byte, which is chosen as the least common byte
|
||||
* symbol in the input data stream (this marker byte is stored in the
|
||||
* output stream as the first byte).
|
||||
*
|
||||
* Occurrences of the marker byte in the stream are encoded as the marker
|
||||
* byte followed by a zero byte, which means that occurrences of the marker
|
||||
* byte have to be coded with two bytes.
|
||||
*
|
||||
* The lengths and offsets are coded in a variable length fashion, allowing
|
||||
* values of any magnitude (up to 4294967295 in this implementation).
|
||||
*
|
||||
* With this compression scheme, the worst case compression result is
|
||||
* (257/256)*insize + 1.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
* Copyright (c) 2003-2004 Marcus Geelnard
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would
|
||||
* be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
* Marcus Geelnard
|
||||
* marcus.geelnard at home.se
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Constants used for LZ77 coding
|
||||
*************************************************************************/
|
||||
|
||||
/* Maximum offset (can be any size < 2^32). Lower values gives faster
|
||||
compression, while higher values gives better compression.
|
||||
NOTE: LZ_CompressFast does not use this constant. */
|
||||
#define LZ_MAX_OFFSET 4096
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* INTERNAL FUNCTIONS *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* _LZ_StringCompare() - Return maximum length string match.
|
||||
*************************************************************************/
|
||||
|
||||
static unsigned int _LZ_StringCompare( unsigned char * str1,
|
||||
unsigned char * str2, unsigned int minlen, unsigned int maxlen )
|
||||
{
|
||||
unsigned int len;
|
||||
|
||||
for( len = minlen; (len < maxlen) && (str1[len] == str2[len]); ++ len );
|
||||
// for( len = minlen; (len < maxlen) && (str2+len+1 < str1-1) && (str1[len] == str2[len]); ++ len );
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* PUBLIC FUNCTIONS *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* LZ_Compress() - Compress a block of data using an LZ77 coder.
|
||||
* in - Input (uncompressed) buffer.
|
||||
* out - Output (compressed) buffer. This buffer must be 0.4% larger
|
||||
* than the input buffer, plus one byte.
|
||||
* insize - Number of input bytes.
|
||||
* The function returns the size of the compressed data.
|
||||
*************************************************************************/
|
||||
|
||||
int LZ_Compress( unsigned char *in, unsigned char *out,
|
||||
unsigned int insize )
|
||||
{
|
||||
unsigned char mask, bundle1, bundle2;
|
||||
int inpos, outpos, bytesleft;
|
||||
int maxoffset, offset, bestoffset;
|
||||
int maxlength, length, bestlength;
|
||||
unsigned char *ptr1, *ptr2, *flags;
|
||||
|
||||
/* Do we have anything to compress? */
|
||||
if( insize < 1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remember the repetition marker for the decoder */
|
||||
|
||||
out[0] = 0x10;
|
||||
out[1] = insize&0xFF;
|
||||
out[2] = (insize>>8)&0xFF;
|
||||
out[3] = (insize>>16)&0xFF;
|
||||
flags = &out[4];
|
||||
*flags = 0;
|
||||
mask = 128;
|
||||
|
||||
/* Start of compression */
|
||||
inpos = 0;
|
||||
outpos = 5;
|
||||
|
||||
/* Main compression loop */
|
||||
bytesleft = insize;
|
||||
do
|
||||
{
|
||||
/* Determine most distant position */
|
||||
if( inpos > LZ_MAX_OFFSET ) maxoffset = LZ_MAX_OFFSET;
|
||||
else maxoffset = inpos;
|
||||
|
||||
/* Get pointer to current position */
|
||||
ptr1 = &in[ inpos ];
|
||||
|
||||
/* Search history window for maximum length string match */
|
||||
bestlength = 2;
|
||||
bestoffset = 0;
|
||||
for( offset = 3; offset <= maxoffset; ++ offset )
|
||||
{
|
||||
/* Get pointer to candidate string */
|
||||
ptr2 = &ptr1[ -offset ];
|
||||
|
||||
/* Quickly determine if this is a candidate (for speed) */
|
||||
if( (ptr1[ 0 ] == ptr2[ 0 ]) &&
|
||||
(ptr1[ bestlength ] == ptr2[ bestlength ]) )
|
||||
{
|
||||
/* Determine maximum length for this offset */
|
||||
maxlength = ((inpos+1) > 18 ? 18 : inpos + 1);
|
||||
|
||||
/* Count maximum length match at this offset */
|
||||
length = _LZ_StringCompare( ptr1, ptr2, 0, maxlength );
|
||||
|
||||
/* Better match than any previous match? */
|
||||
if( length > bestlength )
|
||||
{
|
||||
bestlength = length;
|
||||
bestoffset = offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Was there a good enough match? */
|
||||
if( bestlength > 2)
|
||||
{
|
||||
*flags |= mask;
|
||||
mask >>= 1;
|
||||
bundle2 = ((bestlength-3)<<4) | (((bestoffset-1)&0xF00)>>8);
|
||||
bundle1 = (bestoffset-1)&0xFF;
|
||||
out [ outpos++ ] = bundle2;
|
||||
out [ outpos++ ] = bundle1;
|
||||
|
||||
inpos += bestlength;
|
||||
bytesleft -= bestlength;
|
||||
if (!mask) {
|
||||
mask = 128;
|
||||
flags = &out [ outpos++ ];
|
||||
*flags = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mask >>= 1;
|
||||
out[ outpos ++ ] = in[ inpos++ ];
|
||||
-- bytesleft;
|
||||
if (!mask) {
|
||||
mask = 128;
|
||||
flags = &out [ outpos++ ];
|
||||
*flags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while( bytesleft > 3 );
|
||||
|
||||
/* Dump remaining bytes, if any */
|
||||
while( inpos < insize )
|
||||
{
|
||||
out[ outpos ++ ] = in[ inpos++ ];
|
||||
}
|
||||
|
||||
while(outpos&3)
|
||||
out [ outpos ++] = 0;
|
||||
|
||||
return outpos;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int in, out, size;
|
||||
struct stat buf;
|
||||
unsigned char *uncompressed, *compressed;
|
||||
|
||||
if (argc == 3) {
|
||||
in = open(argv[1], O_RDONLY);
|
||||
out = creat(argv[2], 0600);
|
||||
fstat(in, &buf);
|
||||
uncompressed = malloc(buf.st_size);
|
||||
read(in, uncompressed, buf.st_size);
|
||||
close(in);
|
||||
compressed = malloc(buf.st_size*2);
|
||||
size = LZ_Compress(uncompressed, compressed, buf.st_size);
|
||||
write(out, "LZ77", 4);
|
||||
write(out, compressed, size);
|
||||
close(out);
|
||||
free(compressed);
|
||||
free(uncompressed);
|
||||
return 0;
|
||||
}
|
||||
printf("Usage: %s file.bin file.lz77\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
353
channel/banner/tools/mkbns.c
Normal file
353
channel/banner/tools/mkbns.c
Normal file
@@ -0,0 +1,353 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#if 0
|
||||
uint16_t deftbl[16] = {
|
||||
2048, 0,
|
||||
4096, -2048,
|
||||
0, 0,
|
||||
1536, 512,
|
||||
1920, 0,
|
||||
2176, 0,
|
||||
3680, -1664,
|
||||
3136, -1856
|
||||
};
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
int16_t deftbl[16] = {
|
||||
2048, 0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,0,
|
||||
0,0,
|
||||
};
|
||||
#endif
|
||||
|
||||
int16_t deftbl[16] = {
|
||||
674,1040,
|
||||
3598,-1738,
|
||||
2270,-583,
|
||||
3967,-1969,
|
||||
1516,381,
|
||||
3453, -1468,
|
||||
2606, -617,
|
||||
3795, -1759,
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
uint32_t fourcc;
|
||||
uint32_t unk;
|
||||
uint32_t filesize;
|
||||
uint16_t unk1,unk2;
|
||||
uint32_t infooff;
|
||||
uint32_t infosize;
|
||||
uint32_t dataoff;
|
||||
uint32_t datasize;
|
||||
} bnshdr;
|
||||
|
||||
typedef struct {
|
||||
uint32_t fourcc;
|
||||
uint32_t size;
|
||||
uint16_t looped;
|
||||
uint16_t unk2;
|
||||
uint16_t srate;
|
||||
uint16_t unk3;
|
||||
uint32_t looppoint;
|
||||
uint32_t samples;
|
||||
uint32_t unknown1[6];
|
||||
uint32_t start1;
|
||||
uint32_t start2;
|
||||
uint32_t unknown2[2];
|
||||
int16_t tbl1[16];
|
||||
uint16_t unka1[8];
|
||||
int16_t tbl2[16];
|
||||
uint16_t unka2[8];
|
||||
} bnsinfo;
|
||||
|
||||
float tables[2][16];
|
||||
|
||||
typedef struct {
|
||||
uint32_t fourcc;
|
||||
uint32_t size;
|
||||
} bnsdatahdr;
|
||||
|
||||
#define SWAB16(x) ((((x)>>8)&0xFF) | (((x)&0xFF)<<8))
|
||||
#define SWAB32(x) ((SWAB16((x)&0xFFFF)<<16)|(SWAB16(((x)>>16)&0xFFFF)))
|
||||
|
||||
#define ISWAB16(x) x=SWAB16(x)
|
||||
#define ISWAB32(x) x=SWAB32(x)
|
||||
|
||||
typedef struct {
|
||||
int16_t l;
|
||||
int16_t r;
|
||||
} sample;
|
||||
|
||||
int16_t lsamps[2][2] = {{0,0},{0,0}};
|
||||
int16_t rlsamps[2][2] = {{0,0},{0,0}};
|
||||
|
||||
#define CLAMP(a,min,max) (((a)>(max))?(max):(((a)<(min))?(min):(a)))
|
||||
|
||||
void unpack_adpcm(int idx, int16_t *table, uint8_t *data, int16_t *outbuf)
|
||||
{
|
||||
|
||||
int32_t index = (data[0] >> 4) & 0x7; //highest bit of byte is ignored
|
||||
uint32_t exponent = 28 - (data[0] & 0xf);
|
||||
int32_t factor1 = table[2*index];
|
||||
int32_t factor2 = table[2*index + 1];
|
||||
int i;
|
||||
int32_t sample;
|
||||
for(i=0;i<14;i++) {
|
||||
sample = data[1+(i/2)];
|
||||
if(!(i&1)) {
|
||||
sample = (sample&0xf0)<<24;
|
||||
} else {
|
||||
sample = (sample)<<28;
|
||||
}
|
||||
sample = ((lsamps[idx][1]*factor1 + lsamps[idx][0]*factor2)>>11) + (sample>>exponent);
|
||||
if(sample>32767) sample=32767;
|
||||
if(sample<-32768) sample=-32768;
|
||||
if(abs(sample)>20000) printf("dammit %d\n",sample);
|
||||
outbuf[i] = sample;
|
||||
lsamps[idx][0] = lsamps[idx][1];
|
||||
lsamps[idx][1] = outbuf[i];
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t findexp(float residual, uint8_t *nybble)
|
||||
{
|
||||
uint8_t exp = 0;
|
||||
|
||||
while((residual > 7.5f) || (residual < -8.5f)) {
|
||||
exp++;
|
||||
residual /= 2;
|
||||
}
|
||||
if(nybble)
|
||||
*nybble = CLAMP((int16_t)floor(residual),-8,7);
|
||||
return exp;
|
||||
}
|
||||
|
||||
uint8_t determine_std_exponent(int idx, int16_t *table, int index, int16_t *inbuf)
|
||||
{
|
||||
int32_t maxres = 0;
|
||||
int32_t factor1 = table[2*index];
|
||||
int32_t factor2 = table[2*index + 1];
|
||||
int32_t predictor;
|
||||
int32_t residual;
|
||||
int i;
|
||||
int16_t elsamps[2];
|
||||
memcpy(elsamps,rlsamps[idx],sizeof(int16_t)*2);
|
||||
for(i=0;i<14;i++) {
|
||||
predictor = (elsamps[1]*factor1 + elsamps[0]*factor2)/2048;
|
||||
residual = inbuf[i] - predictor;
|
||||
if(residual > maxres) maxres = residual;
|
||||
elsamps[0] = elsamps[1];
|
||||
elsamps[1] = inbuf[i];
|
||||
}
|
||||
return findexp(maxres,NULL);
|
||||
}
|
||||
|
||||
float compress_adpcm(int idx, int16_t *table, uint8_t tblidx, uint8_t *data, int16_t *inbuf, int16_t *lsamps) {
|
||||
|
||||
int32_t factor1 = table[2*tblidx];
|
||||
int32_t factor2 = table[2*tblidx + 1];
|
||||
int32_t predictor;
|
||||
int32_t residual;
|
||||
uint8_t exp;
|
||||
int8_t nybble;
|
||||
int i;
|
||||
float error = 0;
|
||||
|
||||
exp = determine_std_exponent(idx, table, tblidx, inbuf);
|
||||
|
||||
while(exp<=15) {
|
||||
memcpy(lsamps,rlsamps[idx],sizeof(int16_t)*2);
|
||||
data[0] = exp | tblidx<<4;
|
||||
error = 0;
|
||||
for(i=0;i<14;i++) {
|
||||
predictor = (lsamps[1]*factor1 + lsamps[0]*factor2)>>11;
|
||||
residual = inbuf[i] - predictor;
|
||||
residual = residual>>exp;
|
||||
if((residual > 7) || (residual < -8)) {
|
||||
exp++;
|
||||
break;
|
||||
}
|
||||
nybble = CLAMP(residual,-8,7);
|
||||
if(i&1) {
|
||||
data[i/2+1] |= nybble&0xf;
|
||||
} else {
|
||||
data[i/2+1] = nybble<<4;
|
||||
}
|
||||
predictor += nybble<<exp;
|
||||
lsamps[0] = lsamps[1];
|
||||
lsamps[1] = CLAMP(predictor,-32768,32767);
|
||||
error += powf(lsamps[1] - inbuf[i],2.0f);
|
||||
}
|
||||
if(i == 14) break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void repack_adpcm(int idx, int16_t *table, uint8_t *data, int16_t *inbuf)
|
||||
{
|
||||
uint8_t tblidx;
|
||||
uint8_t testdata[8];
|
||||
int16_t tlsamps[2];
|
||||
int16_t blsamps[2];
|
||||
float error;
|
||||
float besterror = 99999999.0f;
|
||||
for(tblidx = 0; tblidx < 8; tblidx++) {
|
||||
error = compress_adpcm(idx, table, tblidx, testdata, inbuf, tlsamps);
|
||||
if(error < besterror) {
|
||||
besterror = error;
|
||||
memcpy(data, testdata, 8);
|
||||
memcpy(blsamps, tlsamps, sizeof(int16_t)*2);
|
||||
}
|
||||
}
|
||||
memcpy(rlsamps[idx], blsamps, sizeof(int16_t)*2);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
FILE *f;
|
||||
FILE *f2 = NULL;
|
||||
FILE *fo;
|
||||
int i,j;
|
||||
int16_t sampbuf[14];
|
||||
|
||||
bnshdr hdr;
|
||||
bnsinfo info;
|
||||
bnsdatahdr datahdr;
|
||||
uint8_t *databuf;
|
||||
uint8_t *data1;
|
||||
uint8_t *data2;
|
||||
sample *datain;
|
||||
|
||||
int samples;
|
||||
int loop_pt = 0;
|
||||
int blocks;
|
||||
int separated_loop = 0;
|
||||
|
||||
if(argc > 4 && (atoi(argv[3]) == 1))
|
||||
separated_loop = 1;
|
||||
|
||||
f = fopen(argv[1],"r");
|
||||
fo = fopen(argv[2],"w");
|
||||
|
||||
fseek(f,0,SEEK_END);
|
||||
|
||||
samples = ftell(f)/(sizeof(uint16_t)*2);
|
||||
|
||||
if(separated_loop) {
|
||||
f2 = fopen(argv[4],"r");
|
||||
fseek(f2,0,SEEK_END);
|
||||
loop_pt = samples;
|
||||
samples += ftell(f2)/(sizeof(uint16_t)*2);
|
||||
}
|
||||
|
||||
blocks = (samples+13)/14;
|
||||
|
||||
memset(&hdr,0,sizeof(hdr));
|
||||
memset(&info,0,sizeof(info));
|
||||
memset(&datahdr,0,sizeof(datahdr));
|
||||
|
||||
hdr.fourcc = 0x20534e42;
|
||||
hdr.unk = SWAB32(0xfeff0100);
|
||||
hdr.filesize = SWAB32(blocks * 16 + sizeof(hdr) + sizeof(info) + sizeof(datahdr));
|
||||
hdr.unk1 = SWAB16(32);
|
||||
hdr.unk2 = SWAB16(2);
|
||||
hdr.infooff = SWAB32(sizeof(hdr));
|
||||
hdr.infosize = SWAB32(sizeof(info));
|
||||
hdr.dataoff = SWAB32(sizeof(hdr) + sizeof(info));
|
||||
hdr.datasize = SWAB32(sizeof(datahdr) + blocks * 16);
|
||||
|
||||
info.fourcc = 0x4f464e49;
|
||||
info.size = SWAB32(sizeof(info));
|
||||
info.srate = SWAB16(32000);
|
||||
if(argc > 3 && (atoi(argv[3]) == 1))
|
||||
info.looped = SWAB16(1);
|
||||
info.unk2 = SWAB16(0x200);
|
||||
info.looppoint = SWAB32(loop_pt);
|
||||
info.samples = SWAB32(samples);
|
||||
info.unknown1[0] = SWAB32(0x18);
|
||||
info.unknown1[1] = SWAB32(0x00);
|
||||
info.unknown1[2] = SWAB32(0x20);
|
||||
info.unknown1[3] = SWAB32(0x2c);
|
||||
info.unknown1[4] = SWAB32(0x00);
|
||||
info.unknown1[5] = SWAB32(0x38);
|
||||
info.unknown2[0] = SWAB32(0x68);
|
||||
info.unknown2[1] = SWAB32(0x00);
|
||||
info.start1 = SWAB32(0);
|
||||
info.start2 = SWAB32(blocks * 8);
|
||||
for(i=0;i<16;i++) {
|
||||
info.tbl1[i] = SWAB16((int16_t)(deftbl[i]));
|
||||
info.tbl2[i] = SWAB16((int16_t)(deftbl[i]));
|
||||
}
|
||||
|
||||
datahdr.fourcc = 0x41544144;
|
||||
datahdr.size = SWAB32(blocks * 16);
|
||||
|
||||
fwrite(&hdr,sizeof(hdr),1,fo);
|
||||
fwrite(&info,sizeof(info),1,fo);
|
||||
fwrite(&datahdr,sizeof(datahdr),1,fo);
|
||||
|
||||
|
||||
datain = malloc(sizeof(uint16_t)*2*blocks*14);
|
||||
memset(datain,0,sizeof(uint16_t)*2*blocks*14);
|
||||
|
||||
databuf = malloc(blocks * 16);
|
||||
data1 = databuf;
|
||||
data2 = databuf + blocks * 8;
|
||||
|
||||
if(separated_loop) {
|
||||
fseek(f,0,SEEK_SET);
|
||||
fread(datain,sizeof(uint16_t)*2,loop_pt,f);
|
||||
fseek(f2,0,SEEK_SET);
|
||||
fread(&datain[loop_pt],sizeof(uint16_t)*2,samples-loop_pt,f2);
|
||||
fclose(f);
|
||||
fclose(f2);
|
||||
} else {
|
||||
fseek(f,0,SEEK_SET);
|
||||
fread(datain,sizeof(uint16_t)*2,samples,f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
printf("Samples: 0x%x\n",samples);
|
||||
printf("Blocks: 0x%x Size ADPCM: 0x%x Size PCM: 0x%x\n",blocks,blocks*8,blocks*14);
|
||||
if(separated_loop)
|
||||
printf("Loop point: 0x%x samples\n",loop_pt);
|
||||
|
||||
for(i=0;i<blocks;i++) {
|
||||
//printf("Block %d\n",i);
|
||||
for(j=0;j<14;j++) {
|
||||
sampbuf[j] = datain[i*14+j].l;
|
||||
}
|
||||
repack_adpcm(0,deftbl,data1,sampbuf);
|
||||
//unpack_adpcm(0,deftbl,data1,sampbuf);
|
||||
for(j=0;j<14;j++) {
|
||||
sampbuf[j] = datain[i*14+j].r;
|
||||
}
|
||||
repack_adpcm(1,deftbl,data2,sampbuf);
|
||||
//unpack_adpcm(1,deftbl,data2,sampbuf);
|
||||
data1 += 8;
|
||||
data2 += 8;
|
||||
}
|
||||
|
||||
fwrite(databuf, blocks*16, 1, fo);
|
||||
|
||||
fclose(fo);
|
||||
|
||||
free(datain); free(databuf);
|
||||
return 0;
|
||||
}
|
||||
221
channel/banner/tools/png2tpl.c
Normal file
221
channel/banner/tools/png2tpl.c
Normal file
@@ -0,0 +1,221 @@
|
||||
#include <stdio.h>
|
||||
#include <png.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct tpl_hdr {
|
||||
uint32_t magic;
|
||||
uint32_t ntextures;
|
||||
uint32_t hdrsize;
|
||||
};
|
||||
|
||||
struct tpl_tex {
|
||||
uint32_t hdroff;
|
||||
uint32_t pltoff;
|
||||
};
|
||||
|
||||
struct tpl_texhdr {
|
||||
uint16_t height;
|
||||
uint16_t width;
|
||||
uint32_t format;
|
||||
uint32_t offset;
|
||||
uint32_t wraps;
|
||||
uint32_t wrapt;
|
||||
uint32_t minfilter;
|
||||
uint32_t maxfilter;
|
||||
float lodbias;
|
||||
uint8_t edgelod;
|
||||
uint8_t minlod;
|
||||
uint8_t maxlod;
|
||||
uint8_t unpacked;
|
||||
};
|
||||
|
||||
#define SWAB16(x) ((((x)>>8)&0xFF) | (((x)&0xFF)<<8))
|
||||
#define SWAB32(x) ((SWAB16(((uint32_t)(x))&0xFFFF)<<16)|(SWAB16((((uint32_t)(x))>>16)&0xFFFF)))
|
||||
|
||||
#define ISWAB16(x) x=SWAB16(x)
|
||||
#define ISWAB32(x) x=SWAB32(x)
|
||||
|
||||
#define ALIGN(x) (((x)+31)&(~31))
|
||||
|
||||
void do_ia8(int width, int height, FILE *fp, uint8_t **row_pointers) {
|
||||
|
||||
uint16_t **in = (uint16_t **)row_pointers;
|
||||
int wo, ho, wt, i, j;
|
||||
uint16_t *out;
|
||||
wo = (width + 3) & ~3;
|
||||
ho = (height + 3) & ~3;
|
||||
wt = wo/4;
|
||||
out = malloc(wo*ho*2);
|
||||
memset(out,0,wo*ho*2);
|
||||
for(i=0; i<height; i++) {
|
||||
for(j=0; j<width; j++) {
|
||||
int tx,ty,opos;
|
||||
tx = j / 4;
|
||||
ty = i / 4;
|
||||
opos = (tx*16) + (ty*16*wt) + j%4 + (i%4)*4;
|
||||
out[opos] = in[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
fwrite(out,2,wo*ho,fp);
|
||||
}
|
||||
|
||||
void do_rgb565(int width, int height, FILE *fp, uint8_t **row_pointers) {
|
||||
|
||||
uint8_t **in = (uint8_t **)row_pointers;
|
||||
int wo, ho, wt, i, j;
|
||||
uint16_t *out;
|
||||
wo = (width + 3) & ~3;
|
||||
ho = (height + 3) & ~3;
|
||||
wt = wo/4;
|
||||
out = malloc(wo*ho*2);
|
||||
memset(out,0,wo*ho*2);
|
||||
for(i=0; i<height; i++) {
|
||||
for(j=0; j<width; j++) {
|
||||
int tx,ty,opos;
|
||||
tx = j / 4;
|
||||
ty = i / 4;
|
||||
opos = (tx*16) + (ty*16*wt) + j%4 + (i%4)*4;
|
||||
out[opos] = SWAB16((in[i][j*3]<<8) & 0xF800);
|
||||
out[opos] |= SWAB16((in[i][j*3+1]<<3) & 0x07E0);
|
||||
out[opos] |= SWAB16((in[i][j*3+2]>>3) & 0x001F);
|
||||
}
|
||||
}
|
||||
|
||||
fwrite(out,2,wo*ho,fp);
|
||||
}
|
||||
|
||||
void do_i8(int width, int height, FILE *fp, uint8_t **in) {
|
||||
|
||||
int wo, ho, wt, i, j;
|
||||
uint8_t *out;
|
||||
wo = (width + 7) & ~7;
|
||||
ho = (height + 3) & ~3;
|
||||
wt = wo/8;
|
||||
out = malloc(wo*ho);
|
||||
memset(out,0,wo*ho);
|
||||
for(i=0; i<height; i++) {
|
||||
for(j=0; j<width; j++) {
|
||||
int tx,ty,opos;
|
||||
tx = j / 8;
|
||||
ty = i / 4;
|
||||
opos = (tx*32) + (ty*32*wt) + j%8 + (i%4)*8;
|
||||
out[opos] = in[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
fwrite(out,1,wo*ho,fp);
|
||||
}
|
||||
|
||||
|
||||
void do_rgba8(int width, int height, FILE *fp, uint8_t **row_pointers) {
|
||||
|
||||
uint32_t **in = (uint32_t **)row_pointers;
|
||||
int wo, ho, wt, i, j;
|
||||
uint16_t *out;
|
||||
wo = (width + 3) & ~3;
|
||||
ho = (height + 3) & ~3;
|
||||
wt = wo/4;
|
||||
out = malloc(wo*ho*4);
|
||||
memset(out,0,wo*ho*4);
|
||||
for(i=0; i<height; i++) {
|
||||
for(j=0; j<width; j++) {
|
||||
int tx,ty,opos;
|
||||
tx = j / 4;
|
||||
ty = i / 4;
|
||||
opos = (tx*32) + (ty*32*wt) + j%4 + (i%4)*4;
|
||||
out[opos] = (in[i][j]&0xFFFF);
|
||||
out[opos+16] = (in[i][j]>>16);
|
||||
}
|
||||
}
|
||||
|
||||
fwrite(out,2,wo*ho*2,fp);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
png_structp png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
{
|
||||
printf("PNG error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(argv[1],"rb");
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING|PNG_TRANSFORM_EXPAND|PNG_TRANSFORM_STRIP_16|PNG_TRANSFORM_SWAP_ALPHA, NULL);
|
||||
|
||||
uint8_t **row_pointers = png_get_rows(png_ptr, info_ptr);
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, filter_method, compression_type, interlace_type;
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_method);
|
||||
|
||||
printf("Texture: %d x %d\n",(int)width,(int)height);
|
||||
|
||||
FILE *fo = fopen(argv[2],"wb");
|
||||
|
||||
struct tpl_hdr tplhdr;
|
||||
tplhdr.magic = SWAB32(0x0020af30);
|
||||
tplhdr.ntextures = SWAB32(1);
|
||||
tplhdr.hdrsize = SWAB32(sizeof(struct tpl_hdr));
|
||||
|
||||
fwrite(&tplhdr,sizeof(struct tpl_hdr),1,fo);
|
||||
|
||||
struct tpl_tex tpltex;
|
||||
tpltex.hdroff = SWAB32(ftell(fo) + sizeof(struct tpl_tex));
|
||||
tpltex.pltoff = SWAB32(0);
|
||||
|
||||
fwrite(&tpltex,sizeof(struct tpl_tex),1,fo);
|
||||
|
||||
struct tpl_texhdr texhdr;
|
||||
memset(&texhdr,0,sizeof(struct tpl_texhdr));
|
||||
|
||||
|
||||
|
||||
texhdr.width = SWAB16(width);
|
||||
texhdr.height = SWAB16(height);
|
||||
texhdr.offset = SWAB32(ALIGN(ftell(fo) + sizeof(struct tpl_texhdr)));
|
||||
texhdr.minfilter = SWAB32(1);
|
||||
texhdr.maxfilter = SWAB32(1);
|
||||
texhdr.wraps = SWAB32(atoi(argv[3]));
|
||||
texhdr.wrapt = SWAB32(atoi(argv[4]));
|
||||
|
||||
switch(color_type) {
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
texhdr.format = SWAB32(3); //IA8
|
||||
fwrite(&texhdr,sizeof(struct tpl_texhdr),1,fo);
|
||||
fseek(fo,SWAB32(texhdr.offset),SEEK_SET);
|
||||
do_ia8(width, height, fo,row_pointers);
|
||||
break;
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
texhdr.format = SWAB32(1); //I8
|
||||
fwrite(&texhdr,sizeof(struct tpl_texhdr),1,fo);
|
||||
fseek(fo,SWAB32(texhdr.offset),SEEK_SET);
|
||||
do_i8(width, height, fo,row_pointers);
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
texhdr.format = SWAB32(6); //ARGB
|
||||
fwrite(&texhdr,sizeof(struct tpl_texhdr),1,fo);
|
||||
fseek(fo,SWAB32(texhdr.offset),SEEK_SET);
|
||||
do_rgba8(width, height, fo,row_pointers);
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
texhdr.format = SWAB32(4); //RGB565
|
||||
fwrite(&texhdr,sizeof(struct tpl_texhdr),1,fo);
|
||||
fseek(fo,SWAB32(texhdr.offset),SEEK_SET);
|
||||
do_rgb565(width, height, fo,row_pointers);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user