Skip to content

Commit

Permalink
Finished implementing compression algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
aglab2 committed Aug 29, 2024
1 parent e704071 commit 1391f68
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 19 deletions.
28 changes: 17 additions & 11 deletions src/compress.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "compress.h"

#include "savestate.h"
#include "bool.h"
#include "libc/string.h"

Expand Down Expand Up @@ -62,7 +63,7 @@ typedef struct

static MinMatcHash hashMinMatch(MinMatch match)
{
return (MinMatcHash){((match.match3 * 506832829U) << 8) >> (32 - HASH_CHAINS_BITS), (match.match4 * 2654435761U) >> (32 - HASH_CHAINS_BITS)};
return (MinMatcHash){((match.match3 * 506832829U)) >> (32 - HASH_CHAINS_BITS), (match.match4 * 2654435761U) >> (32 - HASH_CHAINS_BITS)};
}

static void wildCopy4(uint8_t *dst, const uint8_t *src, const uint8_t *dstEnd)
Expand Down Expand Up @@ -132,7 +133,7 @@ static MinMatchPtr tryMinMatch(uint32_t potentialMinMatchOffset, MinMatch minMat
}
}

void mlz4_compress(const uint8_t *in, const uint32_t inSize, uint8_t *out, uint32_t *outSize)
uint32_t mlz4_compress(const uint8_t *in, const uint32_t inSize, uint8_t *out)
{
uint8_t *compressedData = out;

Expand All @@ -142,23 +143,25 @@ void mlz4_compress(const uint8_t *in, const uint32_t inSize, uint8_t *out, uint3
uint8_t hashChains4[HASH_CHAINS_SIZE] = {};
#else
// placed in gDecompressionHeap
uint8_t *hashChains3 = (uint8_t *)0x801c1000;
uint8_t *hashChains4 = (uint8_t *)0x801c1000 + HASH_CHAINS_SIZE;
uint8_t *hashChains3 = Hacktice_gState->memory + MaxStateSize - HASH_CHAINS_SIZE * 2 - 0xf00;
uint8_t *hashChains4 = hashChains3 + HASH_CHAINS_SIZE;
bzero(hashChains3, 2 * HASH_CHAINS_SIZE);
#endif

// should be safe to do
*(uint32_t *)outCursor = inSize;
PUT_UNALIGNED4(inSize, outCursor);
outCursor += 4;

#if 0
// uncompressible data, just write it out as literals
if (inSize <= 8)
{
outCursor[0] = ((uint8_t)inSize) << 4;
outCursor++;
WILD_COPY_MOVE(outCursor, in, inSize);
*outSize = (size_t)(outCursor - compressedData);
return;
return (uint32_t) (outCursor - compressedData);
}
#endif

const uint8_t *inEnd = in + inSize;
const uint8_t *inCursor = in + 4;
Expand Down Expand Up @@ -192,8 +195,7 @@ void mlz4_compress(const uint8_t *in, const uint32_t inSize, uint8_t *out, uint3
}

WILD_COPY_MOVE(outCursor, inLiteralStart, literalsCount);
*outSize = (uint32_t)(outCursor - compressedData);
return;
return (uint32_t)(outCursor - compressedData);
}

MinMatch minMatch = readMinMatch(inCursor);
Expand Down Expand Up @@ -247,10 +249,10 @@ void mlz4_compress(const uint8_t *in, const uint32_t inSize, uint8_t *out, uint3
}
}

void mlz4_decompress(const uint8_t *in, uint8_t *out)
uint32_t mlz4_decompress(const uint8_t *in, uint8_t *out)
{
const uint8_t *inCursor = in;
uint32_t originalSize = *(uint32_t *)inCursor;
uint32_t originalSize = GET_UNALIGNED4(inCursor);
inCursor += 4;

uint8_t *outCursor = out;
Expand Down Expand Up @@ -279,6 +281,7 @@ void mlz4_decompress(const uint8_t *in, uint8_t *out)
// last 4 literals must be in safety margin
memcpy(outCursor, inCursor, literalsCount);
outCursor += literalsCount;
inCursor += literalsCount;
break;
}
else
Expand Down Expand Up @@ -306,4 +309,7 @@ void mlz4_decompress(const uint8_t *in, uint8_t *out)
const uint8_t *matchStart = outCursor - offset;
WILD_COPY_MOVE(outCursor, matchStart, matchesCount);
}

// TODO: this is incredibly ugly, rework this mess
return inCursor - in;
}
4 changes: 2 additions & 2 deletions src/compress.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
#define uint8_t u8
#define uint32_t u32

void mlz4_compress(const uint8_t* in, const uint32_t inSize, uint8_t* out, uint32_t* outSize);
void mlz4_decompress(const uint8_t* in, uint8_t* out);
uint32_t mlz4_compress(const uint8_t* in, const uint32_t inSize, uint8_t* out);
uint32_t mlz4_decompress(const uint8_t* in, uint8_t* out);
22 changes: 19 additions & 3 deletions src/savestate.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

#include "game/area.h"
#include "game/camera.h"
#include "game/display.h"
#include "game/print.h"
#include "game/level_update.h"
#include "libc/string.h"
#include "libc/stdio.h"

void set_play_mode(s16 playMode);

Expand All @@ -22,6 +24,9 @@ extern u8 _hackticeStateDataStart[];
extern u8 _hackticeStateDataEnd[];
#endif

#define IS_DECADES_LATER (0x8C63E074U == (*(uint32_t*) 0x802C99C4))
extern struct GfxPool gGfxPools[2];

static bool sMustSaveState = 0;

static void resetCamera()
Expand All @@ -48,16 +53,27 @@ void SaveState_onNormal()
Hacktice_gState->area = gCurrAreaIndex;
Hacktice_gState->level = gCurrLevelNum;
Hacktice_gState->size = sizeof(State);
uint32_t stateSize = 0;
mlz4_compress(_hackticeStateDataStart, _hackticeStateDataEnd - _hackticeStateDataStart, Hacktice_gState->memory, &stateSize);
uint32_t stateSize = mlz4_compress(_hackticeStateDataStart, _hackticeStateDataEnd - _hackticeStateDataStart, Hacktice_gState->memory);
// Decades Later extra logic
if (IS_DECADES_LATER)
{
uint32_t exStateSize = mlz4_compress((uint8_t*) gGfxPools, sizeof(gGfxPools), Hacktice_gState->memory + stateSize);
static char buf[16];
sprintf(buf, "%d %d", stateSize, exStateSize);
TextManager_addLine(buf, 30);
}
}
else
{
if (Config_action() == Config_ButtonAction_LOAD_STATE)
{
if (Hacktice_gState->area == gCurrAreaIndex && Hacktice_gState->level == gCurrLevelNum)
{
mlz4_decompress(Hacktice_gState->memory, _hackticeStateDataStart);
uint32_t compressedSize = mlz4_decompress(Hacktice_gState->memory, _hackticeStateDataStart);
if (IS_DECADES_LATER)
{
mlz4_decompress(Hacktice_gState->memory + compressedSize, (uint8_t*) gGfxPools);
}
resetCamera();
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/savestate.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ void SaveState_onPause();
void SaveState_onNormal();

// TODO: This is very much a culprit, useless one too
#define MaxStateSize 0x30000
#define MaxStateSize 0x28000

typedef struct
{
s32 size;
s16 level;
s16 area;
char memory[MaxStateSize];
u8 memory[MaxStateSize];
} State;

#ifdef BINARY
Expand Down
2 changes: 1 addition & 1 deletion src/xversion.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
HACKTICE_VERSION(1, 6, 0)
HACKTICE_VERSION(1, 6, 1)

0 comments on commit 1391f68

Please sign in to comment.