Compare commits
2 Commits
c3e0b2eab3
...
e102d7c198
Author | SHA1 | Date | |
---|---|---|---|
e102d7c198 | |||
eade12482c |
5
.gitignore
vendored
5
.gitignore
vendored
@ -7,9 +7,8 @@
|
|||||||
|
|
||||||
.cache
|
.cache
|
||||||
|
|
||||||
/nitrofs/image.bin
|
/nitrofs/*.bin
|
||||||
/nitrofs/music.raw
|
/nitrofs/*.raw
|
||||||
/nitrofs/palette.bin
|
|
||||||
|
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
*.nds
|
*.nds
|
4
Makefile
4
Makefile
@ -29,8 +29,8 @@ SDIMAGE := image.bin
|
|||||||
# Source code paths
|
# Source code paths
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|
||||||
SOURCEDIRS := src libs/FastLZ/fastlz.c libs/RaylibDS libs/lwrb/lwrb/src/lwrb
|
SOURCEDIRS := src libs/FastLZ/fastlz.c libs/RaylibDS
|
||||||
INCLUDEDIRS := src libs/FastLZ libs/RaylibDS libs/lwrb/lwrb/src/include
|
INCLUDEDIRS := src libs/FastLZ libs/RaylibDS
|
||||||
GFXDIRS :=
|
GFXDIRS :=
|
||||||
BINDIRS :=
|
BINDIRS :=
|
||||||
AUDIODIRS :=
|
AUDIODIRS :=
|
||||||
|
@ -1,15 +1,27 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
palette="palette.png"
|
video1="video.mp4"
|
||||||
video="kiss2x.mp4"
|
palette1="palette1.png"
|
||||||
# output="kiss2x_out.mp4"
|
# output1="out_badapple.mp4"
|
||||||
output="out/out_%d.bmp"
|
output1="out1/out_%d.bmp"
|
||||||
|
|
||||||
filters="scale=256x192:flags=lanczos:force_original_aspect_ratio=decrease,pad=256:192:-1:-1:color=black"
|
video2="2d.mp4"
|
||||||
|
palette2="palette2.png"
|
||||||
|
output2="out2/out_%d.bmp"
|
||||||
|
# output="output.mp4"
|
||||||
|
|
||||||
|
filters="scale=256x192:flags=lanczos:force_original_aspect_ratio=decrease,pad=256:192:-1:-1:color=black,fps=30"
|
||||||
|
|
||||||
# video
|
# video
|
||||||
ffmpeg -i $video -vf "$filters,palettegen=max_colors=256:reserve_transparent=0:stats_mode=diff" -y $palette
|
ffmpeg -i $video1 -vf "$filters,palettegen=max_colors=256:reserve_transparent=0:stats_mode=diff" -y $palette1
|
||||||
ffmpeg -i $video -i $palette -filter_complex "$filters[x];[x][1:v]paletteuse=dither=none" -y $output
|
ffmpeg -i $video1 -i $palette1 -filter_complex "$filters[x];[x][1:v]paletteuse=dither=none" -y $output1
|
||||||
|
|
||||||
# audio
|
# audio
|
||||||
ffmpeg -i $video -f s16le -vn -ac 1 -ar 22050 -y music.raw
|
ffmpeg -i $video1 -f s16le -vn -ac 2 -ar 22050 -y music1.raw
|
||||||
|
|
||||||
|
# video
|
||||||
|
# ffmpeg -i $video2 -vf "$filters,palettegen=max_colors=256:reserve_transparent=0:stats_mode=diff" -y $palette2
|
||||||
|
# ffmpeg -i $video2 -i $palette2 -filter_complex "$filters[x];[x][1:v]paletteuse=dither=none" -y $output2
|
||||||
|
|
||||||
|
# # audio
|
||||||
|
# ffmpeg -i $video2 -f s16le -vn -ac 2 -ar 22050 -y music2.raw
|
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;
|
||||||
|
}
|
130
encoder/main.cpp
130
encoder/main.cpp
@ -1,4 +1,6 @@
|
|||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
@ -9,37 +11,70 @@
|
|||||||
#include "fastlz.h"
|
#include "fastlz.h"
|
||||||
|
|
||||||
extern "C" char *RLE_Code(unsigned char *raw_buffer, int raw_len, int *new_len);
|
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 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 PALETTE_SIZE 256
|
||||||
#define FRAME_SIZE 256*192
|
#define FRAME_SIZE 256*192
|
||||||
#define CHUNK_SIZE 10
|
#define CHUNK_SIZE 8
|
||||||
|
|
||||||
uint16_t palette_buffer[PALETTE_SIZE];
|
void Frame_RAWtoRGB15(unsigned char *frame, unsigned char *dest, uint16_t *palette_buffer);
|
||||||
|
|
||||||
size_t chunk_counter = 0;
|
int Compress(uint8_t type, uint8_t *frame_buffer, uint32_t frame_buffer_len, uint8_t *compress_buffer)
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
|
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[162000];
|
||||||
|
|
||||||
|
std::ofstream file_out;
|
||||||
|
|
||||||
printf("Finding total frame...");
|
printf("Finding total frame...");
|
||||||
// Find 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()) {
|
if (entry.is_regular_file()) {
|
||||||
std::string filename = entry.path().filename().string();
|
std::string filename = entry.path().filename().string();
|
||||||
int extpos = filename.find(".bmp", 4);
|
int extpos = filename.find(".bmp", 4);
|
||||||
@ -54,8 +89,8 @@ int main()
|
|||||||
// Generate palette
|
// Generate palette
|
||||||
printf("Generating palette map...\n");
|
printf("Generating palette map...\n");
|
||||||
int pal_w, pal_h, pal_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++)
|
for (int i=0; i<PALETTE_SIZE; i++)
|
||||||
{
|
{
|
||||||
int index = i*3;
|
int index = i*3;
|
||||||
@ -67,14 +102,35 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("Writing palette map...\n");
|
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.write(reinterpret_cast<const char*>(palette_buffer), sizeof(palette_buffer));
|
||||||
file_out.close();
|
file_out.close();
|
||||||
|
|
||||||
|
|
||||||
printf("Generating image map...\n");
|
printf("Generating image map...\n");
|
||||||
std::stringstream ss;
|
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);
|
||||||
|
|
||||||
|
// ########## PER FRAME ENCODER ##########
|
||||||
|
// for (int i=0; i<frame_total; i++)
|
||||||
|
// {
|
||||||
|
// ss.str("");
|
||||||
|
// ss << frame_path << "out_" << i+1 << ".bmp";
|
||||||
|
|
||||||
|
// 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, palette_buffer);
|
||||||
|
|
||||||
|
// compress_size = Compress(type, frame_buffer, FRAME_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);
|
||||||
|
|
||||||
|
// printf("write %i bytes (%i/%i)\n", compress_size, i+1, frame_total);
|
||||||
|
// }
|
||||||
|
// ########################################
|
||||||
|
|
||||||
// Calculate the number of complete iterations needed
|
// Calculate the number of complete iterations needed
|
||||||
int numIterations = frame_total / CHUNK_SIZE;
|
int numIterations = frame_total / CHUNK_SIZE;
|
||||||
@ -90,22 +146,23 @@ int main()
|
|||||||
int itemIndex = i * CHUNK_SIZE + i_chunk;
|
int itemIndex = i * CHUNK_SIZE + i_chunk;
|
||||||
|
|
||||||
ss.str("");
|
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());
|
// printf("loading %s\n", ss.str().c_str());
|
||||||
|
|
||||||
int frame_w, frame_h, frame_n;
|
int frame_w, frame_h, frame_n;
|
||||||
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &frame_w, &frame_h, &frame_n, 3);
|
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;
|
if ((compress_size) > compress_size_biggest) compress_size_biggest = compress_size;
|
||||||
compress_size_total += 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_size), sizeof(uint32_t));
|
||||||
file_out.write(reinterpret_cast<const char*>(compress_buffer), compress_size);
|
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);
|
printf("write chunk %i bytes %i/%i\n", compress_size, i, numIterations-1);
|
||||||
}
|
}
|
||||||
@ -117,23 +174,24 @@ int main()
|
|||||||
int i_chunk = 0;
|
int i_chunk = 0;
|
||||||
for (int k = frame_total-remainingItems; k<frame_total; k++) {
|
for (int k = frame_total-remainingItems; k<frame_total; k++) {
|
||||||
ss.str("");
|
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());
|
// printf("loading %s\n", ss.str().c_str());
|
||||||
|
|
||||||
int frame_w, frame_h, frame_n;
|
int frame_w, frame_h, frame_n;
|
||||||
unsigned char *frame_raw = stbi_load(ss.str().c_str(), &frame_w, &frame_h, &frame_n, 3);
|
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++;
|
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;
|
if ((compress_size) > compress_size_biggest) compress_size_biggest = compress_size;
|
||||||
compress_size_total += 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_size), sizeof(uint32_t));
|
||||||
file_out.write(reinterpret_cast<const char*>(compress_buffer), compress_size);
|
file_out.write(reinterpret_cast<const char*>(compress_buffer), compress_size);
|
||||||
|
// file_out.put('\0');
|
||||||
|
|
||||||
printf("write remaining chunk %i bytes\n", compress_size);
|
printf("write remaining chunk %i bytes\n", compress_size);
|
||||||
}
|
}
|
||||||
@ -146,7 +204,15 @@ int main()
|
|||||||
printf("Total Size : %1.fmb\n", static_cast<double>(compress_size_total) / (1024*1024));
|
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/", "main", 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++)
|
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 --*/
|
||||||
|
/*----------------------------------------------------------------------------*/
|
501
src/main.cpp
501
src/main.cpp
@ -1,58 +1,187 @@
|
|||||||
#include "fastlz.h"
|
#include "fastlz.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
|
#include "mm_types.h"
|
||||||
#include "nds/arm9/background.h"
|
#include "nds/arm9/background.h"
|
||||||
|
#include "nds/arm9/cache.h"
|
||||||
#include "nds/arm9/console.h"
|
#include "nds/arm9/console.h"
|
||||||
|
#include "nds/arm9/input.h"
|
||||||
|
#include "nds/arm9/sassert.h"
|
||||||
#include "nds/cothread.h"
|
#include "nds/cothread.h"
|
||||||
|
#include "nds/decompress.h"
|
||||||
#include "nds/dma.h"
|
#include "nds/dma.h"
|
||||||
|
#include "nds/interrupts.h"
|
||||||
#include "nds/timers.h"
|
#include "nds/timers.h"
|
||||||
#include "raylibds.hpp"
|
#include "raylibds.hpp"
|
||||||
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <nds.h>
|
#include <nds.h>
|
||||||
#include <maxmod9.h>
|
#include <maxmod9.h>
|
||||||
|
#include <sys/_types.h>
|
||||||
|
|
||||||
#define PALETTE_SIZE 256
|
#define PALETTE_SIZE 256
|
||||||
#define FRAME_SIZE 256*192
|
#define FRAME_SIZE 256*192
|
||||||
|
|
||||||
// TODO: hardcode fix
|
// TODO: hardcode fix
|
||||||
#define CHUNK_SIZE 10
|
#define CHUNK_SIZE 8
|
||||||
#define QUEUE_SIZE 6
|
|
||||||
#define FRAMERATE 30
|
#define FRAMERATE 30
|
||||||
#define VIDEO_TOTALFRAME 827
|
#define VIDEO_TOTALFRAME 6584
|
||||||
|
|
||||||
#define MMSTREAM_BUF_SIZE 800
|
#define VIDEO_RBUF_LEN CHUNK_SIZE*6
|
||||||
#define MUSIC_BUFFER_SIZE 16000
|
#define VIDEO_RBUF_BUFFER FRAME_SIZE
|
||||||
|
#define VIDEO_TEMP_SIZE 96100
|
||||||
|
|
||||||
|
#define MMSTREAM_BUF_SIZE 16*200
|
||||||
|
#define MUSIC_RBUF_SIZE 96000*2
|
||||||
|
|
||||||
void wait_forever(const char* msg);
|
void wait_forever(const char* msg);
|
||||||
void LoadNextChunk();
|
bool LoadNextChunk(unsigned char *dest);
|
||||||
void TimerCallback();
|
void TimerCallback();
|
||||||
void VBLCallback();
|
void VBLCallback();
|
||||||
void FrameStep();
|
void FrameStep();
|
||||||
int ThreadEntrypoint(void *arg);
|
int ThreadMusic(void *arg);
|
||||||
int ThreadVideo(void *arg);
|
int ThreadVideo(void *arg);
|
||||||
mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format );
|
mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format );
|
||||||
|
|
||||||
|
volatile bool doDraw = true;
|
||||||
|
volatile bool isPause = false;
|
||||||
|
volatile int noframe = 0;
|
||||||
|
|
||||||
|
void *sassert_malloc(size_t size)
|
||||||
|
{
|
||||||
|
void *p = malloc(size);
|
||||||
|
sassert(p != nullptr, "Memory allocation failed %i", size);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
struct RingBuffer {
|
struct RingBuffer {
|
||||||
char *buffer = nullptr;
|
unsigned char *buffer = nullptr;
|
||||||
|
int head;
|
||||||
|
int tail;
|
||||||
|
size_t buffer_size;
|
||||||
|
size_t size;
|
||||||
|
size_t count;
|
||||||
|
|
||||||
|
RingBuffer(size_t rb_len, size_t buffer_len, unsigned char * buffer_ptr)
|
||||||
|
{
|
||||||
|
buffer = buffer_ptr;
|
||||||
|
buffer_size = buffer_len;
|
||||||
|
size = rb_len;
|
||||||
|
head = 0;
|
||||||
|
tail = 0;
|
||||||
|
count = 0;
|
||||||
|
Raylib::nocashMessageFormat("per block %i", buffer_size/size);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* Get()
|
||||||
|
{
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
count--;
|
||||||
|
unsigned char* ptr = &buffer[head*(buffer_size/size)];
|
||||||
|
head = (head+1) % size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* Write()
|
||||||
|
{
|
||||||
|
if (count < size)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
unsigned char* ptr = &buffer[tail*(buffer_size/size)];
|
||||||
|
tail = (tail+1) % size;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* Manual_Read()
|
||||||
|
{
|
||||||
|
unsigned char* ptr = &buffer[head*(buffer_size/size)];
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* Manual_Write()
|
||||||
|
{
|
||||||
|
unsigned char* ptr = &buffer[tail*(buffer_size/size)];
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manual_Skip(int total)
|
||||||
|
{
|
||||||
|
count += total;
|
||||||
|
tail = (tail+total) % size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manual_Advance(int total)
|
||||||
|
{
|
||||||
|
count -= total;
|
||||||
|
head = (head+total) % size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getFree()
|
||||||
|
{
|
||||||
|
return size-count;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Rbuf_Music {
|
||||||
|
unsigned char *buffer = nullptr;
|
||||||
int head;
|
int head;
|
||||||
int tail;
|
int tail;
|
||||||
int size;
|
int size;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
RingBuffer(size_t size_t)
|
Rbuf_Music(size_t buffer_size, unsigned char* buffer_ptr)
|
||||||
{
|
{
|
||||||
buffer = (char*)malloc(size_t);
|
buffer = buffer_ptr;
|
||||||
size = size_t;
|
size = buffer_size;
|
||||||
head = 0;
|
head = 0;
|
||||||
tail = 0;
|
tail = 0;
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~RingBuffer()
|
void Skip(int total)
|
||||||
{
|
{
|
||||||
free(buffer);
|
count -= total;
|
||||||
|
head = (head+total) % size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Advance(int total)
|
||||||
|
{
|
||||||
|
count += total;
|
||||||
|
tail = (tail+total) % size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinearReadSize()
|
||||||
|
{
|
||||||
|
return size - head;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinearWriteSize()
|
||||||
|
{
|
||||||
|
return size - tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetFree()
|
||||||
|
{
|
||||||
|
return size-count;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *GetHead()
|
||||||
|
{
|
||||||
|
return &buffer[head];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *GetTail()
|
||||||
|
{
|
||||||
|
return &buffer[tail];
|
||||||
}
|
}
|
||||||
|
|
||||||
int read(char *dest, size_t len)
|
int read(char *dest, size_t len)
|
||||||
@ -64,13 +193,10 @@ struct RingBuffer {
|
|||||||
|
|
||||||
if (len < linear_len)
|
if (len < linear_len)
|
||||||
memcpy(dest, &buffer[head], len);
|
memcpy(dest, &buffer[head], len);
|
||||||
// swiCopy(&buffer[head], dest, len);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(dest, &buffer[head], linear_len);
|
memcpy(dest, &buffer[head], linear_len);
|
||||||
memcpy(&dest[linear_len], buffer, len-linear_len);
|
memcpy(&dest[linear_len], buffer, len-linear_len);
|
||||||
// swiCopy(&buffer[head], dest, linear_len);
|
|
||||||
// swiCopy(buffer, &dest[linear_len], len-linear_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
head = (head+len) % size;
|
head = (head+len) % size;
|
||||||
@ -90,13 +216,10 @@ struct RingBuffer {
|
|||||||
|
|
||||||
if (len < linear_len)
|
if (len < linear_len)
|
||||||
memcpy(&buffer[tail], data, len);
|
memcpy(&buffer[tail], data, len);
|
||||||
// swiCopy(data, &buffer[tail], len);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(&buffer[tail], data, linear_len);
|
memcpy(&buffer[tail], data, linear_len);
|
||||||
memcpy(buffer, &data[linear_len], len-linear_len);
|
memcpy(buffer, &data[linear_len], len-linear_len);
|
||||||
// swiCopy(data, &buffer[tail], linear_len);
|
|
||||||
// swiCopy(&data[linear_len], buffer, len-linear_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tail = (tail+len) % size;
|
tail = (tail+len) % size;
|
||||||
@ -110,24 +233,25 @@ struct RingBuffer {
|
|||||||
|
|
||||||
int ptr_background;
|
int ptr_background;
|
||||||
int ptr_subbackground;
|
int ptr_subbackground;
|
||||||
FILE *file_video = nullptr;
|
|
||||||
FILE *file_music = nullptr;
|
FILE *file_music = nullptr;
|
||||||
int file_music_len;
|
int file_music_len;
|
||||||
int file_video_len;
|
|
||||||
|
|
||||||
int framecounter = 0;
|
FILE *file_videomain = nullptr;
|
||||||
|
int file_videomain_len;
|
||||||
|
|
||||||
RingBuffer music_rb(MUSIC_BUFFER_SIZE);
|
RingBuffer *videomain_rb;
|
||||||
void *music_btemp;
|
unsigned char *frame_preload_temp;
|
||||||
|
unsigned char *frame_read_temp;
|
||||||
|
|
||||||
RingBuffer video_rb(FRAME_SIZE*CHUNK_SIZE*QUEUE_SIZE);
|
Rbuf_Music *music_rb;
|
||||||
void *video_btemp;
|
unsigned char *music_buffer_temp;
|
||||||
void *video_decompress;
|
|
||||||
void *video_compress;
|
|
||||||
|
|
||||||
u32 timer_video_start = 0;
|
uint32_t preload_video_size = 0;
|
||||||
u32 timer_video_end = 0;
|
uint32_t next_video_size = 0;
|
||||||
u32 timer_video_avg = 0;
|
|
||||||
|
volatile int timer_start = 0;
|
||||||
|
volatile int timer_avg = 0;
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|
||||||
@ -141,49 +265,57 @@ int main(void) {
|
|||||||
consoleDemoInit();
|
consoleDemoInit();
|
||||||
consoleDebugInit(DebugDevice_NOCASH);
|
consoleDebugInit(DebugDevice_NOCASH);
|
||||||
|
|
||||||
video_decompress = malloc(FRAME_SIZE*CHUNK_SIZE);
|
|
||||||
video_compress = malloc(FRAME_SIZE*CHUNK_SIZE);
|
|
||||||
video_btemp = malloc(FRAME_SIZE);
|
|
||||||
music_btemp = malloc(MUSIC_BUFFER_SIZE);
|
|
||||||
|
|
||||||
bool nitrofs = nitroFSInit(NULL);
|
bool nitrofs = nitroFSInit(NULL);
|
||||||
sassert(nitrofs, "error nitrofs");
|
sassert(nitrofs, "nitrofs init failed");
|
||||||
|
|
||||||
file_video = fopen("nitro:/image.bin", "rb");
|
frame_preload_temp = (unsigned char*)sassert_malloc(VIDEO_TEMP_SIZE);
|
||||||
sassert(file_video != nullptr, "failed to load image.bin");
|
music_buffer_temp = (unsigned char*)sassert_malloc(MUSIC_RBUF_SIZE);
|
||||||
fseek(file_video, 0, SEEK_END);
|
|
||||||
file_video_len = ftell(file_video);
|
|
||||||
fseek(file_video, 0, SEEK_SET);
|
|
||||||
|
|
||||||
file_music = fopen("nitro:/music.raw", "rb");
|
videomain_rb = new RingBuffer(VIDEO_RBUF_LEN, VIDEO_RBUF_LEN*VIDEO_RBUF_BUFFER, (unsigned char*)sassert_malloc(VIDEO_RBUF_LEN*VIDEO_RBUF_BUFFER));
|
||||||
|
music_rb = new Rbuf_Music(MUSIC_RBUF_SIZE, (unsigned char*)sassert_malloc(MUSIC_RBUF_SIZE));
|
||||||
|
|
||||||
|
memset(music_rb->buffer, 0, MUSIC_RBUF_SIZE);
|
||||||
|
|
||||||
|
file_videomain = fopen("nitro:/main_img.bin", "rb");
|
||||||
|
sassert(file_videomain != nullptr, "failed to load image.bin");
|
||||||
|
fseek(file_videomain, 0, SEEK_END);
|
||||||
|
file_videomain_len = ftell(file_videomain);
|
||||||
|
fseek(file_videomain, 0, SEEK_SET);
|
||||||
|
|
||||||
|
file_music = fopen("nitro:/music1.raw", "rb");
|
||||||
sassert(file_music != nullptr, "failed to load music.raw");
|
sassert(file_music != nullptr, "failed to load music.raw");
|
||||||
fseek(file_music, 0, SEEK_END);
|
fseek(file_music, 0, SEEK_END);
|
||||||
file_music_len = ftell(file_music);
|
file_music_len = ftell(file_music);
|
||||||
fseek(file_music, 0, SEEK_SET);
|
fseek(file_music, 0, SEEK_SET);
|
||||||
|
|
||||||
int pal_len;
|
|
||||||
unsigned char* pal = Raylib::LoadFile("nitro:/palette.bin", pal_len);
|
|
||||||
|
|
||||||
ptr_background = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0);
|
ptr_background = bgInit(3, BgType_Bmp8, BgSize_B8_256x256, 0, 0);
|
||||||
ptr_subbackground = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, VRAM_C_SUB_BG, 0);
|
// ptr_subbackground = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, VRAM_C_SUB_BG, 0);
|
||||||
|
|
||||||
DC_FlushRange(pal, pal_len);
|
int palmain_len;
|
||||||
dmaCopy(pal, BG_PALETTE, pal_len);
|
unsigned char* palmain = Raylib::LoadFile("nitro:/main_pal.bin", palmain_len);
|
||||||
dmaCopy(pal, BG_PALETTE_SUB, pal_len);
|
|
||||||
|
|
||||||
free(pal);
|
DC_FlushRange(palmain, palmain_len);
|
||||||
|
dmaCopy(palmain, BG_PALETTE, palmain_len);
|
||||||
|
|
||||||
Raylib::nocashMessageFormat("preload video");
|
Raylib::UnloadFile(palmain);
|
||||||
while(video_rb.size-video_rb.count >= FRAME_SIZE*CHUNK_SIZE) {
|
|
||||||
LoadNextChunk();
|
{
|
||||||
video_rb.write((char*)video_decompress, FRAME_SIZE*CHUNK_SIZE);
|
Raylib::nocashMessageFormat("preload video main");
|
||||||
|
do {
|
||||||
|
unsigned char *ptr = videomain_rb->Manual_Write();
|
||||||
|
LoadNextChunk(ptr);
|
||||||
|
videomain_rb->Manual_Skip(CHUNK_SIZE);
|
||||||
|
} while(videomain_rb->count+CHUNK_SIZE < videomain_rb->size);
|
||||||
|
|
||||||
|
Raylib::nocashMessageFormat("preload done");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Raylib::nocashMessageFormat("preload music");
|
Raylib::nocashMessageFormat("preload audio");
|
||||||
int len = music_rb.size - music_rb.count;
|
int len = music_rb->GetFree();
|
||||||
fread(music_btemp, sizeof(char), len, file_music);
|
fread(music_rb->GetTail(), len, 1, file_music);
|
||||||
music_rb.write((char*)music_btemp, len);
|
music_rb->Advance(len);
|
||||||
|
Raylib::nocashMessageFormat("preload done");
|
||||||
}
|
}
|
||||||
|
|
||||||
mm_ds_system sys;
|
mm_ds_system sys;
|
||||||
@ -191,42 +323,73 @@ int main(void) {
|
|||||||
sys.samp_count = 0;
|
sys.samp_count = 0;
|
||||||
sys.mem_bank = 0;
|
sys.mem_bank = 0;
|
||||||
sys.fifo_channel = FIFO_MAXMOD;
|
sys.fifo_channel = FIFO_MAXMOD;
|
||||||
mmInit( &sys );
|
mmInit(&sys);
|
||||||
|
|
||||||
mm_stream mystream;
|
mm_stream mystream;
|
||||||
mystream.sampling_rate = 22050;
|
mystream.sampling_rate = 22050;
|
||||||
mystream.buffer_length = MMSTREAM_BUF_SIZE;
|
mystream.buffer_length = MMSTREAM_BUF_SIZE;
|
||||||
mystream.callback = on_stream_request;
|
mystream.callback = on_stream_request;
|
||||||
mystream.format = MM_STREAM_16BIT_MONO;
|
mystream.format = MM_STREAM_16BIT_STEREO;
|
||||||
mystream.timer = MM_TIMER2;
|
mystream.timer = MM_TIMER1;
|
||||||
mystream.manual = false;
|
mystream.manual = false;
|
||||||
|
|
||||||
timerStart(3, ClockDivider_1024, TIMER_FREQ_1024(FRAMERATE), TimerCallback);
|
timerStart(0, ClockDivider_1024, TIMER_FREQ_1024(FRAMERATE), TimerCallback);
|
||||||
cothread_create(ThreadEntrypoint, NULL, 0, COTHREAD_DETACHED);
|
irqSet(IRQ_VBLANK, []{
|
||||||
cothread_create(ThreadVideo, NULL, 0, COTHREAD_DETACHED);
|
printf("\033[3;2H\033[Kno frame: %i\n", noframe);
|
||||||
|
printf("\033[4;2H\033[Kvideo buffer: %i frames\n", videomain_rb->count);
|
||||||
|
printf("\033[5;2H\033[Kmusic buffer: %i bytes\n", music_rb->count);
|
||||||
|
|
||||||
|
|
||||||
|
// static int counter = 0;
|
||||||
|
// counter++;
|
||||||
|
|
||||||
|
// if (counter % 30 == 0)
|
||||||
|
// printf("\033[6;2H\033[Kavg decode time: %ims\n", timerTicks2msec(timer_avg/30));
|
||||||
|
|
||||||
|
scanKeys();
|
||||||
|
if (keysUp() & KEY_A) isPause = !isPause;
|
||||||
|
if (keysUp() & KEY_B) FrameStep();
|
||||||
|
if (keysHeld() & KEY_Y) FrameStep();
|
||||||
|
});
|
||||||
|
|
||||||
|
cothread_create(ThreadMusic, NULL, 0, COTHREAD_DETACHED);
|
||||||
|
// cothread_create(ThreadVideo, NULL, 0, COTHREAD_DETACHED);
|
||||||
|
|
||||||
|
// cpuStartTiming(1);
|
||||||
|
|
||||||
mmStreamOpen( &mystream );
|
mmStreamOpen( &mystream );
|
||||||
|
|
||||||
cpuStartTiming(0);
|
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
cothread_yield_irq(IRQ_VBLANK);
|
cothread_yield();
|
||||||
scanKeys();
|
// swiWaitForVBlank();
|
||||||
|
// cothread_yield_irq(IRQ_VBLANK);
|
||||||
|
// scanKeys();
|
||||||
|
|
||||||
if (keysUp() & KEY_A) break;
|
|
||||||
|
|
||||||
printf("\033[4;2H\033[Kvideo buffer: %i", video_rb.count);
|
// if (keysUp() & KEY_A) FrameStep();
|
||||||
printf("\033[5;2H\033[Kmusic buffer: %i", music_rb.count);
|
|
||||||
printf("\033[6;2H\033[Kprogress: %0.f%%", ((float)framecounter/VIDEO_TOTALFRAME)*100);
|
|
||||||
|
|
||||||
static int frame = 0;
|
if (!isPause)
|
||||||
frame++;
|
{
|
||||||
|
if (file_videomain)
|
||||||
|
{
|
||||||
|
unsigned char *ptr = videomain_rb->Manual_Write();
|
||||||
|
if (videomain_rb->count+CHUNK_SIZE < videomain_rb->size)
|
||||||
|
{
|
||||||
|
// timer_start = cpuGetTiming();
|
||||||
|
LoadNextChunk(ptr);
|
||||||
|
videomain_rb->Manual_Skip(CHUNK_SIZE);
|
||||||
|
// timer_avg = cpuGetTiming() - timer_start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftell(file_videomain) == file_videomain_len)
|
||||||
|
{
|
||||||
|
fclose(file_videomain);
|
||||||
|
file_videomain = nullptr;
|
||||||
|
// return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (frame % 30 == 0)
|
|
||||||
{
|
|
||||||
printf("\033[8;2H\033[Kavg decoding time: %" PRIu32 "ms", timerTicks2msec(timer_video_avg/30));
|
|
||||||
timer_video_avg = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -234,49 +397,79 @@ int main(void) {
|
|||||||
|
|
||||||
int ThreadVideo(void *arg)
|
int ThreadVideo(void *arg)
|
||||||
{
|
{
|
||||||
while(1) {
|
// while(1) {
|
||||||
cothread_yield();
|
// if (videomain_rb->getFree() > (sizeof(uint32_t)+preload_video_size) && videomain_rb->getFree() > videomain_rb->size/2)
|
||||||
|
// {
|
||||||
|
// // Raylib::nocashMessageFormat("video thread %i %i", videomain_rb->getFree(), preload_video_size+4);
|
||||||
|
|
||||||
if (file_video != nullptr && video_rb.size-video_rb.count >= FRAME_SIZE*CHUNK_SIZE)
|
// // if (comutex_try_acquire(&mutex))
|
||||||
{
|
// // {
|
||||||
timer_video_start = cpuGetTiming();
|
// bool preload;
|
||||||
|
// do {
|
||||||
LoadNextChunk();
|
// preload = LoadNextChunk(file_videomain);
|
||||||
video_rb.write((char*)video_decompress, FRAME_SIZE*CHUNK_SIZE);
|
// } while(preload);
|
||||||
|
// // comutex_release(&mutex);
|
||||||
timer_video_end = cpuGetTiming();
|
// // }
|
||||||
timer_video_avg += timer_video_end - timer_video_start;
|
// }
|
||||||
|
|
||||||
if (ftell(file_video) == file_video_len)
|
// if (ftell(file_videomain) == file_videomain_len)
|
||||||
{
|
// {
|
||||||
fclose(file_video);
|
// fclose(file_videomain);
|
||||||
file_video = nullptr;
|
// file_videomain = nullptr;
|
||||||
}
|
// return 0;
|
||||||
}
|
// }
|
||||||
}
|
// cothread_yield();
|
||||||
|
// }
|
||||||
|
|
||||||
return 0;
|
// // Raylib::nocashMessageFormat("video thread exit");
|
||||||
|
// return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ThreadEntrypoint(void *arg)
|
int ThreadMusic(void *arg)
|
||||||
{
|
{
|
||||||
while(1) {
|
while(1) {
|
||||||
cothread_yield();
|
cothread_yield();
|
||||||
|
|
||||||
if (file_music != nullptr && music_rb.count < MUSIC_BUFFER_SIZE/2)
|
if (file_music != nullptr && music_rb->count < music_rb->size*0.35)
|
||||||
{
|
{
|
||||||
int len = music_rb.size - music_rb.count;
|
int free = music_rb->GetFree();
|
||||||
|
int linear = music_rb->LinearWriteSize();
|
||||||
|
|
||||||
if ((file_music_len - ftell(file_music)) < len)
|
// memset(music_buffer_temp, 0, MUSIC_RBUF_SIZE);
|
||||||
|
// fread(music_buffer_temp, free, 1, file_music);
|
||||||
|
|
||||||
|
|
||||||
|
if (free < linear)
|
||||||
{
|
{
|
||||||
memset(music_btemp, 0, MUSIC_BUFFER_SIZE);
|
// memcpy(music_rb->GetTail(), music_buffer_temp, free);
|
||||||
fread(music_btemp, sizeof(char), (file_music_len - ftell(file_music)), file_music);
|
fread(music_rb->GetTail(), 1, free, file_music);
|
||||||
fclose(file_music);
|
}
|
||||||
file_music = nullptr;
|
else
|
||||||
} else
|
{
|
||||||
fread(music_btemp, sizeof(char), len, file_music);
|
// memcpy(music_rb->GetTail(), music_buffer_temp, linear);
|
||||||
|
// memcpy(music_rb->buffer, music_buffer_temp, free-linear);
|
||||||
music_rb.write((char*)music_btemp, len);
|
fread(music_rb->GetTail(), 1, linear, file_music);
|
||||||
|
fread(music_rb->buffer, 1, free-linear, file_music);
|
||||||
|
}
|
||||||
|
|
||||||
|
music_rb->Advance(free);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftell(file_music) >= file_music_len)
|
||||||
|
{
|
||||||
|
fclose(file_music);
|
||||||
|
file_music = nullptr;
|
||||||
|
Raylib::nocashMessageFormat("music close!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool closeOnce = false;
|
||||||
|
|
||||||
|
if (!closeOnce && file_music == nullptr && music_rb->count <= 0)
|
||||||
|
{
|
||||||
|
mmStreamClose();
|
||||||
|
Raylib::nocashMessageFormat("stream close!");
|
||||||
|
closeOnce = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,26 +478,55 @@ int ThreadEntrypoint(void *arg)
|
|||||||
|
|
||||||
void FrameStep()
|
void FrameStep()
|
||||||
{
|
{
|
||||||
if (video_rb.count)
|
if (videomain_rb->count == 0 && !file_videomain) return;
|
||||||
|
|
||||||
|
if (videomain_rb->count)
|
||||||
{
|
{
|
||||||
video_rb.read((char*)video_btemp, FRAME_SIZE);
|
// if (comutex_try_acquire(&mutex))
|
||||||
dmaCopyAsynch(video_btemp, bgGetGfxPtr(ptr_background), FRAME_SIZE);
|
// {
|
||||||
framecounter++;
|
// videomain_rb->Get();
|
||||||
}
|
// videomain_rb->read((unsigned char*)&next_video_size, sizeof(uint32_t));
|
||||||
|
unsigned char *dest = videomain_rb->Get();
|
||||||
|
// Raylib::nocashMessageFormat("frame step start %p %i", dest, videomain_rb->count);
|
||||||
|
|
||||||
|
// videomain_rb->read(frame_read_temp, next_video_size);
|
||||||
|
|
||||||
|
// DC_FlushRange(dest, VIDEO_RBUF_BUFFER);
|
||||||
|
// decompress(dest, bgGetGfxPtr(ptr_background), DecompressType::LZ77Vram);
|
||||||
|
dmaCopyAsynch(dest, bgGetGfxPtr(ptr_background), FRAME_SIZE);
|
||||||
|
// dmaCopyAsynch(frame_temp, bgGetGfxPtr(ptr_background), FRAME_SIZE);
|
||||||
|
|
||||||
|
// comutex_release(&mutex);
|
||||||
|
// Raylib::nocashMessageFormat("frame step end");
|
||||||
|
} else {
|
||||||
|
printf("no frame!!!!!\n");
|
||||||
|
noframe++;
|
||||||
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerCallback()
|
void TimerCallback()
|
||||||
{
|
{
|
||||||
FrameStep();
|
FrameStep();
|
||||||
|
doDraw = false;
|
||||||
|
|
||||||
|
// printf("\033[4;2H\033[Kvideo buffer: %i", videomain_rb->count/(FRAME_SIZE));
|
||||||
|
// printf("\033[5;2H\033[Kmusic buffer: %i", music_rb->count/(MMSTREAM_BUF_SIZE*4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadNextChunk()
|
bool LoadNextChunk(unsigned char *dest)
|
||||||
{
|
{
|
||||||
uint32_t compress_size;
|
if (!dest) return false;
|
||||||
fread(&compress_size, sizeof(uint32_t), 1, file_video);
|
// Raylib::nocashMessageFormat("load next start, %p", dest);
|
||||||
|
|
||||||
fread(video_compress, sizeof(uint8_t), compress_size, file_video);
|
// videomain_rb->write((unsigned char*)&preload_video_size, sizeof(uint32_t));
|
||||||
fastlz_decompress(video_compress, compress_size, video_decompress, FRAME_SIZE*CHUNK_SIZE);
|
|
||||||
|
fread(&preload_video_size, sizeof(uint32_t), 1, file_videomain);
|
||||||
|
fread(frame_preload_temp, sizeof(uint8_t), preload_video_size, file_videomain);
|
||||||
|
decompress(frame_preload_temp, dest, DecompressType::LZ77);
|
||||||
|
// fastlz_decompress(frame_preload_temp, preload_video_size, dest, FRAME_SIZE*CHUNK_SIZE);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format ) {
|
mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats format ) {
|
||||||
@ -316,13 +538,42 @@ mm_word on_stream_request( mm_word length, mm_addr dest, mm_stream_formats forma
|
|||||||
case MM_STREAM_16BIT_STEREO: samplesize = 4; break;
|
case MM_STREAM_16BIT_STEREO: samplesize = 4; break;
|
||||||
}
|
}
|
||||||
int len = length*samplesize;
|
int len = length*samplesize;
|
||||||
|
int linear = music_rb->LinearWriteSize();
|
||||||
|
|
||||||
if (music_rb.count >= len)
|
// Raylib::nocashMessageFormat("%i", len);
|
||||||
|
|
||||||
|
// if (ftell(file_music) >= file_music_len) mmStreamClose();
|
||||||
|
// fread(music_buffer_temp, 1, len, file_music);
|
||||||
|
// memcpy(dest, music_buffer_temp, len);
|
||||||
|
// return length;
|
||||||
|
|
||||||
|
if (len < linear)
|
||||||
{
|
{
|
||||||
music_rb.read((char*)dest, len);
|
memcpy(dest, music_rb->GetHead(), len);
|
||||||
|
music_rb->Skip(len);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Raylib::nocashMessageFormat("linear %i", linear);
|
||||||
|
memcpy(dest, music_rb->GetHead(), linear);
|
||||||
|
// memcpy((char*)dest+linear, music_rb->buffer, len-linear);
|
||||||
|
music_rb->Skip(linear);
|
||||||
|
return linear/samplesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (music_rb.count < len && file_music == nullptr) mmStreamClose();
|
|
||||||
|
|
||||||
return length;
|
// if (len < linear)
|
||||||
|
// {
|
||||||
|
// memcpy(dest, music_rb->GetHead(), len);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // Raylib::nocashMessageFormat("linear %i", linear);
|
||||||
|
// memcpy(dest, music_rb->GetHead(), linear);
|
||||||
|
// memcpy((char*)dest+linear, music_rb->buffer, len-linear);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// music_rb->Skip(len);
|
||||||
|
// return length;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user