Skip to content

Commit

Permalink
Handle metadata for 0SC images
Browse files Browse the repository at this point in the history
Fix 13
  • Loading branch information
carstene1ns committed Sep 23, 2024
1 parent 2812de5 commit 8afdf5a
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 18 deletions.
28 changes: 11 additions & 17 deletions src/io/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,29 +328,23 @@ unsigned char* File::loadRLE (int length, bool checkSize) {

int pos = 0;
while (pos < length) {
unsigned char code = loadChar();
unsigned char amount = code & 127;

int rle = loadChar();

if (rle & 128) {

int byte = loadChar();
int amount = rle & 127;
if (code & 128) {
unsigned char value = loadChar();

if (pos + amount >= length) break;

memset(buffer + pos, byte, amount);
memset(buffer + pos, value, amount);
pos += amount;
} else if (amount) {
if (pos + amount >= length) break;

} else if (rle) {

if (pos + rle >= length) break;

fread(buffer + pos, 1, rle, file);

pos += rle;

} else buffer[pos++] = loadChar();

fread(buffer + pos, 1, amount, file);
pos += amount;
} else
buffer[pos++] = loadChar();
}

if (checkSize) {
Expand Down
10 changes: 9 additions & 1 deletion src/jj1/scene/jj1sceneload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,15 @@ void JJ1Scene::loadData (File *f) {
else height = f->loadShort(SH);

images = new JJ1SceneImage(images);
images->image = f->loadSurface(width, height, false);
if (type == 5 || type == 6) {
f->seek(-5, false); // account for metadata 2 + 2
unsigned char* pixels = unpackRLE(f->loadBlock(dataLen), dataLen, width * height + 4);
images->image = createSurface(pixels + 4, width, height);
delete[] pixels;
} else {
images->image = f->loadSurface(width, height, false);
}

images->id = loop;

}
Expand Down
59 changes: 59 additions & 0 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "util.h"
#include "io/file.h"
#include "io/log.h"

#include <string.h>

Expand Down Expand Up @@ -298,3 +299,61 @@ fixed fCos (fixed angle) {
return sinLut[(angle + 256) & 1023];

}


/**
* Unpack a block of RLE compressed data.
*
* @param data Buffer containing compressed data
* @param size The length of the compressed block
* @param outSize The length of the uncompressed block
*
* @return Buffer containing the uncompressed data
*/
unsigned char* unpackRLE (unsigned char* data, unsigned int size, unsigned int outSize) {
unsigned char* buffer = new unsigned char[outSize];

unsigned int posIn = 0, posOut = 0;
while (posIn < size) {
unsigned char code = data[posIn];
unsigned char amount = code & 127;

if (code & 128) { // repeat
unsigned char value = data[posIn+1];

if (posOut + amount >= outSize) {
LOG_WARN("Exceeding write buffer while RLE unpacking.");
break;
}

memset(buffer + posOut, value, amount);

posIn += 2;
posOut += amount;
} else if (amount) { // copy

if (posOut + amount >= outSize) {
LOG_WARN("Exceeding write buffer while RLE unpacking.");
break;
}

memcpy(buffer + posOut, data + posIn + 1, amount);

posIn += amount + 1;
posOut += amount;
} else { // end marker
buffer[posOut++] = data[posIn+1];
posIn += 2;

//LOG_MAX("End marker found while RLE unpacking.");
break;
}
}

if(size != posIn || outSize != posOut) {
LOG_DEBUG("RLE block has incorrect size: in %d/%d out %d/%d", size, posIn, outSize, posOut);
}

delete[] data;
return buffer;
}
1 change: 1 addition & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,6 @@ void uppercaseString (char *string);
void camelcaseString (char *string);
fixed fSin (fixed angle);
fixed fCos (fixed angle);
unsigned char* unpackRLE (unsigned char* data, unsigned int size, unsigned int outSize);

#endif

0 comments on commit 8afdf5a

Please sign in to comment.