Commit 4ae08092 authored by Jack's avatar Jack
Browse files

implemented decoder from of p8.png together with code decompression

parent 97f6b035
......@@ -6,28 +6,25 @@
using namespace retro8;
using namespace io;
constexpr size_t IMAGE_WIDTH = 160;
constexpr size_t IMAGE_HEIGHT = 205;
constexpr size_t RAW_DATA_LENGTH = 0x4300;
uint8_t Stegano::assembleByte(const uint32_t v)
{
constexpr uint32_t MASK_ALPHA = 0xff00000;
constexpr uint32_t MASK_RED = 0x000000ff;
constexpr uint32_t MASK_ALPHA = 0xff000000;
constexpr uint32_t MASK_RED = 0x00ff0000;
constexpr uint32_t MASK_GREEN = 0x0000ff00;
constexpr uint32_t MASK_BLUE = 0x00ff0000;
constexpr uint32_t MASK_BLUE = 0x000000ff;
constexpr uint32_t SHIFT_ALPHA = 24;
constexpr uint32_t SHIFT_RED = 0;
constexpr uint32_t SHIFT_RED = 16;
constexpr uint32_t SHIFT_GREEN = 8;
constexpr uint32_t SHIFT_BLUE = 16;
constexpr uint32_t SHIFT_BLUE = 0;
return
((((v & MASK_ALPHA) >> SHIFT_ALPHA) & 0b11) ) |
((((v & MASK_RED) >> SHIFT_RED) & 0b11) << 2) |
((((v & MASK_GREEN) >> SHIFT_GREEN) & 0b11) << 4) |
((((v & MASK_BLUE) >> SHIFT_BLUE) & 0b11) << 6);
((((v & MASK_ALPHA) >> SHIFT_ALPHA) & 0b11) << 6) |
((((v & MASK_RED) >> SHIFT_RED) & 0b11) << 0) |
((((v & MASK_GREEN) >> SHIFT_GREEN) & 0b11) << 2) |
((((v & MASK_BLUE) >> SHIFT_BLUE) & 0b11) << 4);
}
void Stegano::load(const PngData& data, Machine& m)
......@@ -44,16 +41,65 @@ void Stegano::load(const PngData& data, Machine& m)
static_assert(RAW_DATA_LENGTH == SPRITE_SHEET_SIZE + TILE_MAP_SIZE + SPRITE_FLAGS_SIZE + MUSIC_SIZE + SOUND_SIZE, "Must be equal");
assert(data.length == IMAGE_WIDTH * IMAGE_HEIGHT);
auto* d = data.data;
/* first 0x4300 are read directly into the cart */
for (size_t i = 0; i < RAW_DATA_LENGTH; ++i)
m.memory().base()[i] = assembleByte(data.data[i]);
m.memory().base()[i] = assembleByte(d[i]);
size_t o = RAW_DATA_LENGTH;
std::array<uint8_t, 4> magic;
std::array<uint8_t, 4> expected = { { ':', 'c', ':', '\0' } };
/* read magic code heaader */
for (size_t i = 0; i < magic.size(); ++i)
magic[i] = assembleByte(data.data[o++]);
magic[i] = assembleByte(d[o++]);
assert(magic == expected);
/* read uint6_t lsb compressed length*/
size_t compressedLength = assembleByte(d[o]) << 8 | assembleByte(d[o + 1]);
o += 2;
/* skip 2 null*/
o += 2;
const std::string lookup = "\n 0123456789abcdefghijklmnopqrstuvwxyz!#%(){}[]<>+=/*:;.,~_";
std::string code;
assert(0x3b == lookup.length());
//TODO: optimize concatenation on string by reserving space
for (size_t i = 0; i < compressedLength; ++i)
{
uint8_t v = assembleByte(d[o + i]);
/* copy next */
if (v == 0x00)
{
uint8_t vn = assembleByte(d[o + i + 1]);
code += vn;
++i;
}
/* lookup */
else if (v <= 0x3b)
{
code += lookup[v - 1];
}
else
{
uint8_t vn = assembleByte(d[o + i + 1]);
auto offset = ((v - 0x3c) << 4) + (vn & 0xf);
auto length = (vn >> 4) + 2;
const size_t start = code.length() - offset;
for (size_t j = 0; j < length; ++j)
code += code[start + j];
++i;
}
}
m.code().initFromSource(code);
}
......@@ -16,6 +16,10 @@ namespace retro8
class Stegano
{
public:
static constexpr size_t IMAGE_WIDTH = 160;
static constexpr size_t IMAGE_HEIGHT = 205;
private:
uint8_t assembleByte(const uint32_t v);
public:
......
......@@ -107,9 +107,17 @@ void GameView::render()
retro8::io::LoaderP8 loader;
if (_path.empty())
_path = "pico-man.p8";
_path = "test.p8";
loader.load(_path, machine);
//loader.load(_path, machine);
/*SDL_Surface* surface = IMG_Load("pico-man.p8.png");
r8::io::PngData pngData = { static_cast<const uint32_t*>(surface->pixels), surface->h * surface->w };
assert(surface->pitch == r8::io::Stegano::IMAGE_WIDTH * sizeof(uint32_t));
assert(surface->format->BytesPerPixel == 4);
r8::io::Stegano stegano;
stegano.load(pngData, machine);*/
manager->setFrameRate(machine.code().require60fps() ? 60 : 30);
......@@ -120,11 +128,6 @@ void GameView::render()
//machine.sound().init();
//machine.sound().resume();
/*SDL_Surface* surface = IMG_Load("pico-man.p8.png");
r8::io::PngData pngData = { static_cast<const uint32_t*>(surface->pixels), surface->h * surface->w };
assert(surface->format->BytesPerPixel == 4);
r8::io::Stegano stegano;
stegano.load(pngData, machine);*/
/*for (int i = 0; i < 32; ++i)
machine.circ(64, 64, i+1, (r8::color_t)(i % 15 + 1));*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment