add alt compression method
This commit is contained in:
parent
c3e0b2eab3
commit
eade12482c
415
encoder/lzss.c
Normal file
415
encoder/lzss.c
Normal file
@ -0,0 +1,415 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*-- lzss.c - LZSS coding for Nintendo GBA/DS --*/
|
||||
/*-- Copyright (C) 2011 CUE --*/
|
||||
/*-- --*/
|
||||
/*-- This program is free software: you can redistribute it and/or modify --*/
|
||||
/*-- it under the terms of the GNU General Public License as published by --*/
|
||||
/*-- the Free Software Foundation, either version 3 of the License, or --*/
|
||||
/*-- (at your option) any later version. --*/
|
||||
/*-- --*/
|
||||
/*-- This program is distributed in the hope that it will be useful, --*/
|
||||
/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
|
||||
/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
|
||||
/*-- GNU General Public License for more details. --*/
|
||||
/*-- --*/
|
||||
/*-- You should have received a copy of the GNU General Public License --*/
|
||||
/*-- along with this program. If not, see <http://www.gnu.org/licenses/>. --*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strcasecmp _stricmp
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#define CMD_DECODE 0x00 // decode
|
||||
#define CMD_CODE_10 0x10 // LZSS magic number
|
||||
|
||||
#define LZS_NORMAL 0x00 // normal mode, (0)
|
||||
#define LZS_FAST 0x80 // fast mode, (1 << 7)
|
||||
#define LZS_BEST 0x40 // best mode, (1 << 6)
|
||||
|
||||
#define LZS_WRAM 0x00 // VRAM not compatible (LZS_WRAM | LZS_NORMAL)
|
||||
#define LZS_VRAM 0x01 // VRAM compatible (LZS_VRAM | LZS_NORMAL)
|
||||
#define LZS_WFAST 0x80 // LZS_WRAM fast (LZS_WRAM | LZS_FAST)
|
||||
#define LZS_VFAST 0x81 // LZS_VRAM fast (LZS_VRAM | LZS_FAST)
|
||||
#define LZS_WBEST 0x40 // LZS_WRAM best (LZS_WRAM | LZS_BEST)
|
||||
#define LZS_VBEST 0x41 // LZS_VRAM best (LZS_VRAM | LZS_BEST)
|
||||
|
||||
#define LZS_SHIFT 1 // bits to shift
|
||||
#define LZS_MASK \
|
||||
0x80 // bits to check:
|
||||
// ((((1 << LZS_SHIFT) - 1) << (8 - LZS_SHIFT)
|
||||
|
||||
#define LZS_THRESHOLD 2 // max number of bytes to not encode
|
||||
#define LZS_N 0x1000 // max offset (1 << 12)
|
||||
#define LZS_F 0x12 // max coded ((1 << 4) + LZS_THRESHOLD)
|
||||
#define LZS_NIL LZS_N // index for root of binary search trees
|
||||
|
||||
#define RAW_MINIM 0x00000000 // empty file, 0 bytes
|
||||
#define RAW_MAXIM 0x00FFFFFF // 3-bytes length, 16MB - 1
|
||||
|
||||
#define LZS_MINIM 0x00000004 // header only (empty RAW file)
|
||||
#define LZS_MAXIM \
|
||||
0x01400000 // 0x01200003, padded to 20MB:
|
||||
// * header, 4
|
||||
// * length, RAW_MAXIM
|
||||
// * flags, (RAW_MAXIM + 7) / 8
|
||||
// 4 + 0x00FFFFFF + 0x00200000 + padding
|
||||
|
||||
unsigned char ring[LZS_N + LZS_F - 1];
|
||||
int dad[LZS_N + 1], lson[LZS_N + 1], rson[LZS_N + 1 + 256];
|
||||
size_t pos_ring, len_ring, lzs_vram;
|
||||
|
||||
#define EXIT(text) \
|
||||
{ \
|
||||
printf(text); \
|
||||
exit(-1); \
|
||||
}
|
||||
|
||||
void Title(void)
|
||||
{
|
||||
printf("\n"
|
||||
"LZSS - (c) CUE 2011\n"
|
||||
"LZSS coding for Nintendo GBA/DS\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
void Usage(void)
|
||||
{
|
||||
EXIT("Usage: LZSS command file_1_in file_1_out [file_2_in file_2_out [...]]\n"
|
||||
"\n"
|
||||
"command:\n"
|
||||
" -d ..... decode files\n"
|
||||
" -evn ... encode files, VRAM compatible, normal mode (LZ10)\n"
|
||||
" -ewn ... encode files, WRAM compatible, normal mode\n"
|
||||
" -evf ... encode files, VRAM compatible, fast mode\n"
|
||||
" -ewf ... encode files, WRAM compatible, fast mode\n"
|
||||
" -evo ... encode files, VRAM compatible, optimal mode (LZ-CUE)\n"
|
||||
" -ewo ... encode files, WRAM compatible, optimal mode (LZ-CUE)\n"
|
||||
"\n"
|
||||
"* multiple filenames are permitted\n");
|
||||
}
|
||||
|
||||
void *Memory(size_t length, size_t size);
|
||||
|
||||
void LZS_InsertNode(int r)
|
||||
{
|
||||
unsigned char *key;
|
||||
size_t i;
|
||||
int p, cmp, prev;
|
||||
|
||||
prev = (r - 1) & (LZS_N - 1);
|
||||
|
||||
cmp = 1;
|
||||
len_ring = 0;
|
||||
|
||||
key = &ring[r];
|
||||
p = LZS_N + 1 + key[0];
|
||||
|
||||
rson[r] = lson[r] = LZS_NIL;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (cmp >= 0)
|
||||
{
|
||||
if (rson[p] != LZS_NIL)
|
||||
p = rson[p];
|
||||
else
|
||||
{
|
||||
rson[p] = r;
|
||||
dad[r] = p;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lson[p] != LZS_NIL)
|
||||
p = lson[p];
|
||||
else
|
||||
{
|
||||
lson[p] = r;
|
||||
dad[r] = p;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < LZS_F; i++)
|
||||
if ((cmp = key[i] - ring[p + i]))
|
||||
break;
|
||||
|
||||
if (i > len_ring)
|
||||
{
|
||||
if (!lzs_vram || (p != prev))
|
||||
{
|
||||
pos_ring = p;
|
||||
if ((len_ring = i) == LZS_F)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dad[r] = dad[p];
|
||||
lson[r] = lson[p];
|
||||
rson[r] = rson[p];
|
||||
|
||||
dad[lson[p]] = r;
|
||||
dad[rson[p]] = r;
|
||||
|
||||
if (rson[dad[p]] == p)
|
||||
rson[dad[p]] = r;
|
||||
else
|
||||
lson[dad[p]] = r;
|
||||
|
||||
dad[p] = LZS_NIL;
|
||||
}
|
||||
|
||||
void LZS_DeleteNode(int p)
|
||||
{
|
||||
int q;
|
||||
|
||||
if (dad[p] == LZS_NIL)
|
||||
return;
|
||||
|
||||
if (rson[p] == LZS_NIL)
|
||||
{
|
||||
q = lson[p];
|
||||
}
|
||||
else if (lson[p] == LZS_NIL)
|
||||
{
|
||||
q = rson[p];
|
||||
}
|
||||
else
|
||||
{
|
||||
q = lson[p];
|
||||
if (rson[q] != LZS_NIL)
|
||||
{
|
||||
do
|
||||
{
|
||||
q = rson[q];
|
||||
} while (rson[q] != LZS_NIL);
|
||||
|
||||
rson[dad[q]] = lson[q];
|
||||
dad[lson[q]] = dad[q];
|
||||
lson[q] = lson[p];
|
||||
dad[lson[p]] = q;
|
||||
}
|
||||
|
||||
rson[q] = rson[p];
|
||||
dad[rson[p]] = q;
|
||||
}
|
||||
|
||||
dad[q] = dad[p];
|
||||
|
||||
if (rson[dad[p]] == p)
|
||||
rson[dad[p]] = q;
|
||||
else
|
||||
lson[dad[p]] = q;
|
||||
|
||||
dad[p] = LZS_NIL;
|
||||
}
|
||||
|
||||
void LZS_InitTree(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = LZS_N + 1; i <= LZS_N + 256; i++)
|
||||
rson[i] = LZS_NIL;
|
||||
|
||||
for (i = 0; i < LZS_N; i++)
|
||||
dad[i] = LZS_NIL;
|
||||
}
|
||||
|
||||
unsigned char *LZS_Code(unsigned char *raw_buffer, size_t raw_len, size_t *new_len, size_t best)
|
||||
{
|
||||
unsigned char *pak_buffer, *pak, *raw, *raw_end, *flg;
|
||||
size_t pak_len, len, pos, len_best, pos_best;
|
||||
unsigned int len_next, pos_next, len_post, pos_post;
|
||||
unsigned char mask;
|
||||
|
||||
#define SEARCH(l, p) \
|
||||
{ \
|
||||
l = LZS_THRESHOLD; \
|
||||
\
|
||||
pos = raw - raw_buffer >= LZS_N ? LZS_N : raw - raw_buffer; \
|
||||
for (; pos > lzs_vram; pos--) \
|
||||
{ \
|
||||
for (len = 0; len < LZS_F; len++) \
|
||||
{ \
|
||||
if (raw + len == raw_end) \
|
||||
break; \
|
||||
if (*(raw + len) != *(raw + len - pos)) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
if (len > l) \
|
||||
{ \
|
||||
p = pos; \
|
||||
if ((l = len) == LZS_F) \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
pak_len = 4 + raw_len + ((raw_len + 7) / 8);
|
||||
pak_buffer = Memory(pak_len, sizeof(char));
|
||||
|
||||
*(unsigned int *)pak_buffer = CMD_CODE_10 | (raw_len << 8);
|
||||
|
||||
pak = pak_buffer + 4;
|
||||
raw = raw_buffer;
|
||||
raw_end = raw_buffer + raw_len;
|
||||
|
||||
mask = 0;
|
||||
flg = NULL;
|
||||
|
||||
while (raw < raw_end)
|
||||
{
|
||||
if (!(mask >>= LZS_SHIFT))
|
||||
{
|
||||
flg = pak++;
|
||||
*flg = 0;
|
||||
mask = LZS_MASK;
|
||||
}
|
||||
|
||||
SEARCH(len_best, pos_best);
|
||||
|
||||
// LZ-CUE optimization start
|
||||
if (best)
|
||||
{
|
||||
if (len_best > LZS_THRESHOLD)
|
||||
{
|
||||
if (raw + len_best < raw_end)
|
||||
{
|
||||
raw += len_best;
|
||||
SEARCH(len_next, pos_next);
|
||||
(void)pos_next; // Unused
|
||||
raw -= len_best - 1;
|
||||
SEARCH(len_post, pos_post);
|
||||
(void)pos_post; // Unused
|
||||
raw--;
|
||||
|
||||
if (len_next <= LZS_THRESHOLD)
|
||||
len_next = 1;
|
||||
if (len_post <= LZS_THRESHOLD)
|
||||
len_post = 1;
|
||||
|
||||
if (len_best + len_next <= 1 + len_post)
|
||||
len_best = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// LZ-CUE optimization end
|
||||
|
||||
if (len_best > LZS_THRESHOLD)
|
||||
{
|
||||
raw += len_best;
|
||||
if (flg == NULL)
|
||||
EXIT(", ERROR: flg is NULL!\n");
|
||||
*flg |= mask;
|
||||
*pak++ = ((len_best - (LZS_THRESHOLD + 1)) << 4) | ((pos_best - 1) >> 8);
|
||||
*pak++ = (pos_best - 1) & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pak++ = *raw++;
|
||||
}
|
||||
}
|
||||
|
||||
*new_len = pak - pak_buffer;
|
||||
|
||||
return pak_buffer;
|
||||
}
|
||||
|
||||
unsigned char *LZS_Fast(unsigned char *raw_buffer, size_t raw_len, size_t *new_len)
|
||||
{
|
||||
unsigned char *pak_buffer, *pak, *raw, *raw_end, *flg;
|
||||
size_t pak_len, len;
|
||||
unsigned int r, s, len_tmp, i;
|
||||
unsigned char mask;
|
||||
|
||||
lzs_vram = LZS_VFAST & 0xF;
|
||||
|
||||
pak_len = 4 + raw_len + ((raw_len + 7) / 8);
|
||||
pak_buffer = Memory(pak_len, sizeof(char));
|
||||
|
||||
*(unsigned int *)pak_buffer = CMD_CODE_10 | (raw_len << 8);
|
||||
|
||||
pak = pak_buffer + 4;
|
||||
raw = raw_buffer;
|
||||
raw_end = raw_buffer + raw_len;
|
||||
|
||||
LZS_InitTree();
|
||||
|
||||
r = s = 0;
|
||||
|
||||
len = raw_len < LZS_F ? raw_len : LZS_F;
|
||||
while (r < LZS_N - len)
|
||||
ring[r++] = 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
ring[r + i] = *raw++;
|
||||
|
||||
LZS_InsertNode(r);
|
||||
|
||||
mask = 0;
|
||||
flg = NULL;
|
||||
|
||||
while (len)
|
||||
{
|
||||
if (!(mask >>= LZS_SHIFT))
|
||||
{
|
||||
flg = pak++;
|
||||
*flg = 0;
|
||||
mask = LZS_MASK;
|
||||
}
|
||||
|
||||
if (len_ring > len)
|
||||
len_ring = len;
|
||||
|
||||
if (len_ring > LZS_THRESHOLD)
|
||||
{
|
||||
if (flg == NULL)
|
||||
EXIT(", ERROR: flg is NULL!\n");
|
||||
*flg |= mask;
|
||||
pos_ring = ((r - pos_ring) & (LZS_N - 1)) - 1;
|
||||
*pak++ = ((len_ring - LZS_THRESHOLD - 1) << 4) | (pos_ring >> 8);
|
||||
*pak++ = pos_ring & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
len_ring = 1;
|
||||
*pak++ = ring[r];
|
||||
}
|
||||
|
||||
len_tmp = len_ring;
|
||||
for (i = 0; i < len_tmp; i++)
|
||||
{
|
||||
if (raw == raw_end)
|
||||
break;
|
||||
LZS_DeleteNode(s);
|
||||
ring[s] = *raw++;
|
||||
if (s < LZS_F - 1)
|
||||
ring[s + LZS_N] = ring[s];
|
||||
s = (s + 1) & (LZS_N - 1);
|
||||
r = (r + 1) & (LZS_N - 1);
|
||||
LZS_InsertNode(r);
|
||||
}
|
||||
while (i++ < len_tmp)
|
||||
{
|
||||
LZS_DeleteNode(s);
|
||||
s = (s + 1) & (LZS_N - 1);
|
||||
r = (r + 1) & (LZS_N - 1);
|
||||
if (--len)
|
||||
LZS_InsertNode(r);
|
||||
}
|
||||
}
|
||||
|
||||
*new_len = pak - pak_buffer;
|
||||
|
||||
return pak_buffer;
|
||||
}
|
108
encoder/main.cpp
108
encoder/main.cpp
@ -1,4 +1,6 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
@ -9,37 +11,70 @@
|
||||
#include "fastlz.h"
|
||||
|
||||
extern "C" char *RLE_Code(unsigned char *raw_buffer, int raw_len, int *new_len);
|
||||
extern "C" unsigned char *LZS_Fast(unsigned char *raw_buffer, size_t raw_len, size_t *new_len);
|
||||
extern "C" unsigned char *LZS_Code(unsigned char *raw_buffer, size_t raw_len, size_t *new_len, size_t best);
|
||||
|
||||
#define LZS_WRAM 0x00 // VRAM not compatible (LZS_WRAM | LZS_NORMAL)
|
||||
#define LZS_VRAM 0x01 // VRAM compatible (LZS_VRAM | LZS_NORMAL)
|
||||
|
||||
#define RGBtoRGB15(r,g,b) (((r >> 3) & 0x1F) | (((g >> 3) & 0x1F) << 5) | (((b >> 3) & 0x1F) << 10))
|
||||
|
||||
#define ASSETS_PATH "../assets"
|
||||
#define ASSETS_PATH "../assets/"
|
||||
|
||||
#define PALETTE_SIZE 256
|
||||
#define FRAME_SIZE 256*192
|
||||
#define CHUNK_SIZE 10
|
||||
#define CHUNK_SIZE 1
|
||||
|
||||
uint16_t palette_buffer[PALETTE_SIZE];
|
||||
void Frame_RAWtoRGB15(unsigned char *frame, unsigned char *dest, uint16_t *palette_buffer);
|
||||
|
||||
size_t chunk_counter = 0;
|
||||
size_t chunk_current = 0;
|
||||
|
||||
size_t frame_total = 0;
|
||||
uint8_t frame_buffer[FRAME_SIZE*CHUNK_SIZE];
|
||||
|
||||
uint32_t compress_size;
|
||||
uint32_t compress_size_total;
|
||||
size_t compress_size_biggest;
|
||||
uint8_t compress_buffer[FRAME_SIZE*CHUNK_SIZE*2];
|
||||
|
||||
std::ofstream file_out;
|
||||
|
||||
void Frame_RAWtoRGB15(unsigned char *frame, unsigned char *dest);
|
||||
|
||||
int main()
|
||||
int Compress(uint8_t type, uint8_t *frame_buffer, uint32_t frame_buffer_len, uint8_t *compress_buffer)
|
||||
{
|
||||
switch (type) {
|
||||
case 1: // fastlz
|
||||
return fastlz_compress_level(1, frame_buffer, frame_buffer_len, compress_buffer);
|
||||
break;
|
||||
|
||||
case 2: // rle
|
||||
{
|
||||
int compress_len;
|
||||
char *compress = RLE_Code(frame_buffer, frame_buffer_len, &compress_len);
|
||||
memcpy(compress_buffer, compress, compress_len);
|
||||
return compress_len;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: // lzss
|
||||
{
|
||||
size_t compress_len;
|
||||
unsigned char *compress = LZS_Fast(frame_buffer, frame_buffer_len, &compress_len);
|
||||
// int mode = LZS_VRAM;
|
||||
// unsigned char *compress = LZS_Code(frame_buffer, frame_buffer_len, &compress_len, mode);
|
||||
memcpy(compress_buffer, compress, compress_len);
|
||||
return compress_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Convert(std::string frame_path, std::string palette_path, std::string output_path, std::string output_basename, uint8_t type)
|
||||
{
|
||||
uint16_t palette_buffer[PALETTE_SIZE];
|
||||
|
||||
size_t frame_total = 0;
|
||||
uint8_t frame_buffer[FRAME_SIZE*CHUNK_SIZE];
|
||||
|
||||
uint32_t compress_size = 0;
|
||||
uint32_t compress_size_total = 0;
|
||||
size_t compress_size_biggest = 0;
|
||||
uint8_t compress_buffer[FRAME_SIZE*CHUNK_SIZE*2];
|
||||
|
||||
std::ofstream file_out;
|
||||
|
||||
printf("Finding total frame...");
|
||||
// Find total frame
|
||||
for (const auto& entry : std::filesystem::directory_iterator(ASSETS_PATH "/out/")) {
|
||||
for (const auto& entry : std::filesystem::directory_iterator(frame_path)) {
|
||||
if (entry.is_regular_file()) {
|
||||
std::string filename = entry.path().filename().string();
|
||||
int extpos = filename.find(".bmp", 4);
|
||||
@ -54,8 +89,8 @@ int main()
|
||||
// Generate palette
|
||||
printf("Generating palette map...\n");
|
||||
int pal_w, pal_h, pal_n;
|
||||
unsigned char *palette_raw = stbi_load(ASSETS_PATH "/palette.png", &pal_w, &pal_h, &pal_n, 3);
|
||||
|
||||
unsigned char *palette_raw = stbi_load(palette_path.c_str(), &pal_w, &pal_h, &pal_n, 3);
|
||||
|
||||
for (int i=0; i<PALETTE_SIZE; i++)
|
||||
{
|
||||
int index = i*3;
|
||||
@ -67,14 +102,13 @@ int main()
|
||||
}
|
||||
|
||||
printf("Writing palette map...\n");
|
||||
file_out.open(ASSETS_PATH "/palette.bin", std::ios::binary);
|
||||
file_out.open(output_path + output_basename + "_pal.bin", std::ios::binary);
|
||||
file_out.write(reinterpret_cast<const char*>(palette_buffer), sizeof(palette_buffer));
|
||||
file_out.close();
|
||||
|
||||
|
||||
printf("Generating image map...\n");
|
||||
std::stringstream ss;
|
||||
file_out.open(ASSETS_PATH "/image.bin", std::ios::binary);
|
||||
file_out.open(output_path + output_basename + "_img.bin", std::ios::binary);
|
||||
|
||||
// Calculate the number of complete iterations needed
|
||||
int numIterations = frame_total / CHUNK_SIZE;
|
||||
@ -90,22 +124,23 @@ int main()
|
||||
int itemIndex = i * CHUNK_SIZE + i_chunk;
|
||||
|
||||
ss.str("");
|
||||
ss << ASSETS_PATH "/out/out_" << itemIndex+1 << ".bmp";
|
||||
ss << frame_path << "out_" << itemIndex+1 << ".bmp";
|
||||
|
||||
// printf("loading %s\n", ss.str().c_str());
|
||||
|
||||
int frame_w, frame_h, frame_n;
|
||||
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &frame_w, &frame_h, &frame_n, 3);
|
||||
|
||||
Frame_RAWtoRGB15(frame_raw, &frame_buffer[i_chunk*FRAME_SIZE]);
|
||||
Frame_RAWtoRGB15(frame_raw, &frame_buffer[i_chunk*FRAME_SIZE], palette_buffer);
|
||||
}
|
||||
|
||||
compress_size = fastlz_compress_level(1, frame_buffer, FRAME_SIZE*CHUNK_SIZE, compress_buffer);
|
||||
compress_size = Compress(type, frame_buffer, FRAME_SIZE*CHUNK_SIZE, compress_buffer);
|
||||
if ((compress_size) > compress_size_biggest) compress_size_biggest = compress_size;
|
||||
compress_size_total += compress_size;
|
||||
|
||||
file_out.write(reinterpret_cast<const char*>(&compress_size), sizeof(uint32_t));
|
||||
file_out.write(reinterpret_cast<const char*>(compress_buffer), compress_size);
|
||||
// file_out.put('\0');
|
||||
|
||||
printf("write chunk %i bytes %i/%i\n", compress_size, i, numIterations-1);
|
||||
}
|
||||
@ -117,23 +152,24 @@ int main()
|
||||
int i_chunk = 0;
|
||||
for (int k = frame_total-remainingItems; k<frame_total; k++) {
|
||||
ss.str("");
|
||||
ss << ASSETS_PATH "/out/out_" << k+1 << ".bmp";
|
||||
ss << frame_path << "out_" << k+1 << ".bmp";
|
||||
|
||||
// printf("loading %s\n", ss.str().c_str());
|
||||
|
||||
int frame_w, frame_h, frame_n;
|
||||
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &frame_w, &frame_h, &frame_n, 3);
|
||||
|
||||
Frame_RAWtoRGB15(frame_raw, &frame_buffer[i_chunk*FRAME_SIZE]);
|
||||
Frame_RAWtoRGB15(frame_raw, &frame_buffer[i_chunk*FRAME_SIZE], palette_buffer);
|
||||
i_chunk++;
|
||||
}
|
||||
|
||||
compress_size = fastlz_compress_level(1, frame_buffer, FRAME_SIZE*CHUNK_SIZE, compress_buffer);
|
||||
compress_size = Compress(type, frame_buffer, FRAME_SIZE*CHUNK_SIZE, compress_buffer);
|
||||
if ((compress_size) > compress_size_biggest) compress_size_biggest = compress_size;
|
||||
compress_size_total += compress_size;
|
||||
|
||||
file_out.write(reinterpret_cast<const char*>(&compress_size), sizeof(uint32_t));
|
||||
file_out.write(reinterpret_cast<const char*>(compress_buffer), compress_size);
|
||||
// file_out.put('\0');
|
||||
|
||||
printf("write remaining chunk %i bytes\n", compress_size);
|
||||
}
|
||||
@ -146,7 +182,15 @@ int main()
|
||||
printf("Total Size : %1.fmb\n", static_cast<double>(compress_size_total) / (1024*1024));
|
||||
}
|
||||
|
||||
void Frame_RAWtoRGB15(unsigned char *frame, unsigned char *dest)
|
||||
int main()
|
||||
{
|
||||
// Convert(ASSETS_PATH "out1/", ASSETS_PATH "palette1.png", "../nitrofs/", "data_fastlz", 1);
|
||||
// Convert(ASSETS_PATH "out1/", ASSETS_PATH "palette1.png", "../nitrofs/", "data_rle", 2);
|
||||
Convert(ASSETS_PATH "out1/", ASSETS_PATH "palette1.png", "../nitrofs/", "data_lzss", 3);
|
||||
// Convert(ASSETS_PATH "out2/", ASSETS_PATH "palette2.png", "../nitrofs/", "sub");
|
||||
}
|
||||
|
||||
void Frame_RAWtoRGB15(unsigned char *frame, unsigned char *dest, uint16_t *palette_buffer)
|
||||
{
|
||||
for (int rgb=0; rgb<FRAME_SIZE; rgb++)
|
||||
{
|
||||
|
121
encoder/rle.c
Normal file
121
encoder/rle.c
Normal file
@ -0,0 +1,121 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*-- rle.c - RLE coding for Nintendo GBA/DS --*/
|
||||
/*-- Copyright (C) 2011 CUE --*/
|
||||
/*-- --*/
|
||||
/*-- This program is free software: you can redistribute it and/or modify --*/
|
||||
/*-- it under the terms of the GNU General Public License as published by --*/
|
||||
/*-- the Free Software Foundation, either version 3 of the License, or --*/
|
||||
/*-- (at your option) any later version. --*/
|
||||
/*-- --*/
|
||||
/*-- This program is distributed in the hope that it will be useful, --*/
|
||||
/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/
|
||||
/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/
|
||||
/*-- GNU General Public License for more details. --*/
|
||||
/*-- --*/
|
||||
/*-- You should have received a copy of the GNU General Public License --*/
|
||||
/*-- along with this program. If not, see <http://www.gnu.org/licenses/>. --*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#define CMD_DECODE 0x00 // decode
|
||||
#define CMD_CODE_30 0x30 // RLE magic number
|
||||
|
||||
#define RLE_CHECK 1 // bits to check
|
||||
#define RLE_MASK 0x80 // bits position:
|
||||
// ((((1 << RLE_CHECK) - 1) << (8 - RLE_CHECK)
|
||||
#define RLE_LENGTH 0x7F // length, (0xFF & ~RLE_MASK)
|
||||
|
||||
#define RLE_THRESHOLD 2 // max number of bytes to not encode
|
||||
#define RLE_N 0x80 // max store, (RLE_LENGTH + 1)
|
||||
#define RLE_F 0x82 // max coded, (RLE_LENGTH + RLE_THRESHOLD + 1)
|
||||
|
||||
#define RAW_MINIM 0x00000000 // empty file, 0 bytes
|
||||
#define RAW_MAXIM 0x00FFFFFF // 3-bytes length, 16MB - 1
|
||||
|
||||
#define RLE_MINIM 0x00000004 // header only (empty RAW file)
|
||||
#define RLE_MAXIM 0x01400000 // 0x01020003, padded to 20MB:
|
||||
// * header, 4
|
||||
// * length, RAW_MAXIM
|
||||
// * flags, (RAW_MAXIM + RLE_N - 1) / RLE_N
|
||||
// 4 + 0x00FFFFFF + 0x00020000 + padding
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#define BREAK(text) { printf(text); return; }
|
||||
#define EXIT(text) { printf(text); exit(-1); }
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void Title(void);
|
||||
void Usage(void);
|
||||
|
||||
char *Load(char *filename, int *length, int min, int max);
|
||||
void Save(char *filename, char *buffer, int length);
|
||||
char *Memory(int length, int size);
|
||||
|
||||
void RLE_Decode(char *filename);
|
||||
void RLE_Encode(char *filename);
|
||||
char *RLE_Code(unsigned char *raw_buffer, int raw_len, int *new_len);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
char *Memory(int length, int size) {
|
||||
char *fb;
|
||||
|
||||
fb = (char *) calloc(length, size);
|
||||
if (fb == NULL) EXIT("\nMemory error\n");
|
||||
|
||||
return(fb);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
char *RLE_Code(unsigned char *raw_buffer, int raw_len, int *new_len) {
|
||||
unsigned char *pak_buffer, *pak, *raw, *raw_end, store[RLE_N];
|
||||
unsigned int pak_len, len, store_len, count;
|
||||
|
||||
pak_len = 4 + raw_len + ((raw_len + RLE_N - 1) / RLE_N);
|
||||
pak_buffer = (unsigned char *) Memory(pak_len, sizeof(char));
|
||||
|
||||
*(unsigned int *)pak_buffer = CMD_CODE_30 | (raw_len << 8);
|
||||
|
||||
pak = pak_buffer + 4;
|
||||
raw = raw_buffer;
|
||||
raw_end = raw_buffer + raw_len;
|
||||
|
||||
store_len = 0;
|
||||
while (raw < raw_end) {
|
||||
for (len = 1; len < RLE_F; len++) {
|
||||
if (raw + len == raw_end) break;
|
||||
if (*(raw + len) != *raw) break;
|
||||
}
|
||||
|
||||
if (len <= RLE_THRESHOLD) store[store_len++] = *raw++;
|
||||
|
||||
if ((store_len == RLE_N) || (store_len && (len > RLE_THRESHOLD))) {
|
||||
*pak++ = store_len - 1;
|
||||
for (count = 0; count < store_len; count++) *pak++ = store[count];
|
||||
store_len = 0;
|
||||
}
|
||||
|
||||
if (len > RLE_THRESHOLD) {
|
||||
*pak++ = RLE_MASK | (len - (RLE_THRESHOLD + 1));
|
||||
*pak++ = *raw;
|
||||
raw += len;
|
||||
}
|
||||
}
|
||||
if (store_len) {
|
||||
*pak++ = store_len - 1;
|
||||
for (count = 0; count < store_len; count++) *pak++ = store[count];
|
||||
}
|
||||
|
||||
*new_len = pak - pak_buffer;
|
||||
|
||||
return(pak_buffer);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*-- EOF Copyright (C) 2011 CUE --*/
|
||||
/*----------------------------------------------------------------------------*/
|
Loading…
x
Reference in New Issue
Block a user