diff --git a/.gitignore b/.gitignore index 5f9172181dc8..3cdf896972b0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ *.8bpp *.gbapal *.lz +*.smol +*.fastSmol *.rl *.latfont *.hwjpnfont @@ -41,3 +43,4 @@ prefabs.json /pokeemerald-*.png src/data/map_group_count.h tools/trainerproc/trainerproc +tools/compresSmol/compresSmol diff --git a/Makefile b/Makefile index 2631e22192fb..e8a0bce0069a 100644 --- a/Makefile +++ b/Makefile @@ -151,6 +151,7 @@ endif AUTO_GEN_TARGETS := include make_tools.mk # Tool executables +SMOL := $(TOOLS_DIR)/compresSmol/compresSmol$(EXE) GFX := $(TOOLS_DIR)/gbagfx/gbagfx$(EXE) AIF := $(TOOLS_DIR)/aif2pcm/aif2pcm$(EXE) MID := $(TOOLS_DIR)/mid2agb/mid2agb$(EXE) @@ -294,7 +295,7 @@ clean-assets: rm -f $(DATA_ASM_SUBDIR)/layouts/layouts.inc $(DATA_ASM_SUBDIR)/layouts/layouts_table.inc rm -f $(DATA_ASM_SUBDIR)/maps/connections.inc $(DATA_ASM_SUBDIR)/maps/events.inc $(DATA_ASM_SUBDIR)/maps/groups.inc $(DATA_ASM_SUBDIR)/maps/headers.inc $(DATA_SRC_SUBDIR)/map_group_count.h find sound -iname '*.bin' -exec rm {} + - find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.rl' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} + + find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.smol' -o -iname '*.fastSmol' -o -iname '*.rl' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} + find $(DATA_ASM_SUBDIR)/maps \( -iname 'connections.inc' -o -iname 'events.inc' -o -iname 'header.inc' \) -exec rm {} + tidy: tidymodern tidycheck tidydebug @@ -328,13 +329,15 @@ generated: $(AUTO_GEN_TARGETS) %.pal: ; %.aif: ; -%.1bpp: %.png ; $(GFX) $< $@ -%.4bpp: %.png ; $(GFX) $< $@ -%.8bpp: %.png ; $(GFX) $< $@ -%.gbapal: %.pal ; $(GFX) $< $@ -%.gbapal: %.png ; $(GFX) $< $@ -%.lz: % ; $(GFX) $< $@ -%.rl: % ; $(GFX) $< $@ +%.1bpp: %.png ; $(GFX) $< $@ +%.4bpp: %.png ; $(GFX) $< $@ +%.8bpp: %.png ; $(GFX) $< $@ +%.gbapal: %.pal ; $(GFX) $< $@ +%.gbapal: %.png ; $(GFX) $< $@ +%.lz: % ; $(GFX) $< $@ +%.fastSmol: % ; $(SMOL) -w $< $@ false false false +%.smol: % ; $(SMOL) -w $< $@ +%.rl: % ; $(GFX) $< $@ clean-generated: -rm -f $(AUTO_GEN_TARGETS) diff --git a/include/config/test.h b/include/config/test.h index 90cf5a4b8807..b4d4ad553737 100644 --- a/include/config/test.h +++ b/include/config/test.h @@ -1137,4 +1137,7 @@ #undef B_FLAG_SLEEP_CLAUSE #define B_FLAG_SLEEP_CLAUSE FLAG_SPECIAL_FLAG_UNUSED_0x4003 +// Compression DebugPrintf switch +#define T_COMPRESSION_SHOULD_PRINT FALSE + #endif // GUARD_CONFIG_TEST_H diff --git a/include/decompress.h b/include/decompress.h index 178ab9a6ebc3..d4e710f1e897 100644 --- a/include/decompress.h +++ b/include/decompress.h @@ -3,11 +3,69 @@ #include "sprite.h" +#define TANS_TABLE_SIZE 64 +#define PACKED_FREQ_MASK 0x3F +#define PARTIAL_FREQ_MASK 0xC0000000 + +#define FIRST_LO_MASK 0x7f +#define CONTINUE_BIT 0x80 + +#define SMOL_IMAGE_SIZE_MULTIPLIER 4 + + extern u8 ALIGNED(4) gDecompressionBuffer[0x4000]; -void LZDecompressWram(const u32 *src, void *dest); -void LZDecompressVram(const u32 *src, void *dest); +struct LZ77Header { + u32 lz77IdBits:5; + u32 padding:3; + u32 size:24; +}; + +struct SmolHeader { + u32 mode:4; + u32 imageSize:14; + u32 symSize:14; + u32 initialState:6; + u32 bitstreamSize:13; + u32 loSize:13; +}; + +union CompressionHeader { + struct LZ77Header lz77; + struct SmolHeader smol; +}; + +struct SpriteSheetHeader { + u32 mode:4; + u32 numComponents:12; + u32 framesPerComponent:16; +}; + +enum CompressionMode { + MODE_LZ77 = 0, + BASE_ONLY = 1, + ENCODE_SYMS = 2, + ENCODE_DELTA_SYMS = 3, + ENCODE_LO = 4, + ENCODE_BOTH = 5, + ENCODE_BOTH_DELTA_SYMS = 6, + IS_FRAME_CONTAINER = 7, +}; + + +void DecompressDataWithHeaderVram(const u32 *src, void *dest); +void DecompressDataWithHeaderWram(const u32 *src, void *dest); + +// For decompressing a single part of a multi-part spritesheet +//void DecompressSubFrame(const u32 *src, void *dest, u32 frameId); + +void SmolDecompressData(const struct SmolHeader *header, const u32 *data, void *dest); + +bool32 isModeLoEncoded(enum CompressionMode mode); +bool32 isModeSymEncoded(enum CompressionMode mode); +bool32 isModeSymDelta(enum CompressionMode mode); +// Default Decompression functions are below here u32 IsLZ77Data(const void *ptr, u32 minSize, u32 maxSize); u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src); diff --git a/include/global.h b/include/global.h index c033ab9b3552..2148501e28c3 100644 --- a/include/global.h +++ b/include/global.h @@ -7,6 +7,7 @@ #include "gba/gba.h" #include "fpmath.h" #include "metaprogram.h" +#include "decompress.h" #include "constants/global.h" #include "constants/flags.h" #include "constants/vars.h" diff --git a/include/sprite.h b/include/sprite.h index 6a7b585bf387..80c9573f6178 100644 --- a/include/sprite.h +++ b/include/sprite.h @@ -245,6 +245,8 @@ struct Sprite u8 subspriteMode:2; /*0x43*/ u8 subpriority; + //u16 prevFrame; + //const u32 *spriteArray; }; struct OamMatrix diff --git a/make_tools.mk b/make_tools.mk index 75ebc05c9625..6a7de5b24ece 100644 --- a/make_tools.mk +++ b/make_tools.mk @@ -5,7 +5,7 @@ MAKEFLAGS += --no-print-directory # Inclusive list. If you don't want a tool to be built, don't add it here. TOOLS_DIR := tools -TOOL_NAMES := aif2pcm bin2c gbafix gbagfx jsonproc mapjson mid2agb preproc ramscrgen rsfont scaninc trainerproc +TOOL_NAMES := aif2pcm bin2c gbafix gbagfx jsonproc mapjson mid2agb preproc ramscrgen rsfont scaninc trainerproc compresSmol CHECK_TOOL_NAMES = patchelf mgba-rom-test-hydra TOOLDIRS := $(TOOL_NAMES:%=$(TOOLS_DIR)/%) diff --git a/src/battle_anim.c b/src/battle_anim.c index 640e0044ea6c..be9b17e4aa74 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -1574,18 +1574,18 @@ void LoadMoveBg(u16 bgId) void *dmaSrc; void *dmaDest; - LZDecompressWram(tilemap, gDecompressionBuffer); + DecompressDataWithHeaderWram(tilemap, gDecompressionBuffer); RelocateBattleBgPal(GetBattleBgPaletteNum(), (void *)gDecompressionBuffer, 0x100, FALSE); dmaSrc = gDecompressionBuffer; dmaDest = (void *)BG_SCREEN_ADDR(26); DmaCopy32(3, dmaSrc, dmaDest, 0x800); - LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)BG_SCREEN_ADDR(4)); + DecompressDataWithHeaderVram(gBattleAnimBackgroundTable[bgId].image, (void *)BG_SCREEN_ADDR(4)); LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, BG_PLTT_ID(GetBattleBgPaletteNum()), PLTT_SIZE_4BPP); } else { - LZDecompressVram(gBattleAnimBackgroundTable[bgId].tilemap, (void *)BG_SCREEN_ADDR(26)); - LZDecompressVram(gBattleAnimBackgroundTable[bgId].image, (void *)BG_CHAR_ADDR(2)); + DecompressDataWithHeaderVram(gBattleAnimBackgroundTable[bgId].tilemap, (void *)BG_SCREEN_ADDR(26)); + DecompressDataWithHeaderVram(gBattleAnimBackgroundTable[bgId].image, (void *)BG_CHAR_ADDR(2)); LoadCompressedPalette(gBattleAnimBackgroundTable[bgId].palette, BG_PLTT_ID(2), PLTT_SIZE_4BPP); } } diff --git a/src/battle_anim_effects_2.c b/src/battle_anim_effects_2.c index e751a1ca5125..f90ec11b1597 100755 --- a/src/battle_anim_effects_2.c +++ b/src/battle_anim_effects_2.c @@ -3095,7 +3095,7 @@ void AnimTask_LoadMusicNotesPals(u8 taskId) paletteNums[i] = AllocSpritePalette(ANIM_SPRITES_START - i); gMonSpritesGfxPtr->buffer = AllocZeroed(MON_PIC_SIZE * MAX_MON_PIC_FRAMES); - LZDecompressWram(gBattleAnimSpritePal_MusicNotes2, gMonSpritesGfxPtr->buffer); + DecompressDataWithHeaderWram(gBattleAnimSpritePal_MusicNotes2, gMonSpritesGfxPtr->buffer); for (i = 0; i < NUM_MUSIC_NOTE_PAL_TAGS; i++) LoadPalette(&gMonSpritesGfxPtr->buffer[i * 32], (u16)(OBJ_PLTT_ID(paletteNums[i])), PLTT_SIZE_4BPP); diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index f00626efe818..6e968beb74fa 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -955,7 +955,7 @@ void ClearBattleAnimBg(u32 bgId) void AnimLoadCompressedBgGfx(u32 bgId, const u32 *src, u32 tilesOffset) { CpuFill32(0, gBattleAnimBgTileBuffer, 0x2000); - LZDecompressWram(src, gBattleAnimBgTileBuffer); + DecompressDataWithHeaderWram(src, gBattleAnimBgTileBuffer); LoadBgTiles(bgId, gBattleAnimBgTileBuffer, 0x2000, tilesOffset); } diff --git a/src/battle_bg.c b/src/battle_bg.c index 328f990653e0..cba464eeafde 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -772,8 +772,8 @@ void DrawMainBattleBackground(void) { if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_RECORDED_LINK)) { - LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Frontier, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); } else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) @@ -781,23 +781,23 @@ void DrawMainBattleBackground(void) switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL)) { case SPECIES_GROUDON: - LZDecompressVram(gBattleTerrainTiles_Cave, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Cave, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Groudon, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case SPECIES_KYOGRE: - LZDecompressVram(gBattleTerrainTiles_Water, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Water, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Water, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Water, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Kyogre, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case SPECIES_RAYQUAZA: - LZDecompressVram(gBattleTerrainTiles_Rayquaza, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Rayquaza, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Rayquaza, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; default: - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].tileset, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].tilemap, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].tileset, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].tilemap, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(sBattleTerrainTable[gBattleTerrain].palette, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; } @@ -809,15 +809,15 @@ void DrawMainBattleBackground(void) u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { - LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_BuildingLeader, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); return; } else if (trainerClass == TRAINER_CLASS_CHAMPION) { - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumWallace, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); return; } @@ -827,48 +827,48 @@ void DrawMainBattleBackground(void) { default: case MAP_BATTLE_SCENE_NORMAL: - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].tileset, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].tilemap, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].tileset, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].tilemap, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(sBattleTerrainTable[gBattleTerrain].palette, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case MAP_BATTLE_SCENE_GYM: - LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_BuildingGym, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case MAP_BATTLE_SCENE_MAGMA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumMagma, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case MAP_BATTLE_SCENE_AQUA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumAqua, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case MAP_BATTLE_SCENE_SIDNEY: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumSidney, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case MAP_BATTLE_SCENE_PHOEBE: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumPhoebe, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case MAP_BATTLE_SCENE_GLACIA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumGlacia, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case MAP_BATTLE_SCENE_DRAKE: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumDrake, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; case MAP_BATTLE_SCENE_FRONTIER: - LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Frontier, BG_PLTT_ID(2), 3 * PLTT_SIZE_4BPP); break; } @@ -877,7 +877,7 @@ void DrawMainBattleBackground(void) void LoadBattleTextboxAndBackground(void) { - LZDecompressVram(gBattleTextboxTiles, (void *)(BG_CHAR_ADDR(0))); + DecompressDataWithHeaderVram(gBattleTextboxTiles, (void *)(BG_CHAR_ADDR(0))); CopyToBgTilemapBuffer(0, gBattleTextboxTilemap, 0, 0); CopyBgTilemapBufferToVram(0); LoadCompressedPalette(gBattleTextboxPalette, BG_PLTT_ID(0), 2 * PLTT_SIZE_4BPP); @@ -1147,8 +1147,8 @@ void DrawBattleEntryBackground(void) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) { - LZDecompressVram(gBattleVSFrame_Gfx, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(gVsLettersGfx, (void *)OBJ_VRAM0); + DecompressDataWithHeaderVram(gBattleVSFrame_Gfx, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gVsLettersGfx, (void *)OBJ_VRAM0); LoadCompressedPalette(gBattleVSFrame_Pal, BG_PLTT_ID(6), PLTT_SIZE_4BPP); SetBgAttribute(1, BG_ATTR_SCREENSIZE, 1); SetGpuReg(REG_OFFSET_BG1CNT, 0x5C04); @@ -1166,8 +1166,8 @@ void DrawBattleEntryBackground(void) { if (!(gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) || gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) { - LZDecompressVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(gBattleTerrainAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); } else { @@ -1186,20 +1186,20 @@ void DrawBattleEntryBackground(void) switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL)) { case SPECIES_GROUDON: - LZDecompressVram(gBattleTerrainAnimTiles_Cave, (void*)(BG_CHAR_ADDR(1))); - LZDecompressVram(gBattleTerrainAnimTilemap_Cave, (void*)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTiles_Cave, (void*)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTilemap_Cave, (void*)(BG_SCREEN_ADDR(28))); break; case SPECIES_KYOGRE: - LZDecompressVram(gBattleTerrainAnimTiles_Underwater, (void*)(BG_CHAR_ADDR(1))); - LZDecompressVram(gBattleTerrainAnimTilemap_Underwater, (void*)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTiles_Underwater, (void*)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTilemap_Underwater, (void*)(BG_SCREEN_ADDR(28))); break; case SPECIES_RAYQUAZA: - LZDecompressVram(gBattleTerrainAnimTiles_Rayquaza, (void*)(BG_CHAR_ADDR(1))); - LZDecompressVram(gBattleTerrainAnimTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTiles_Rayquaza, (void*)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(28))); break; default: - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].entryTileset, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].entryTilemap, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].entryTileset, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].entryTilemap, (void *)(BG_SCREEN_ADDR(28))); break; } } @@ -1210,27 +1210,27 @@ void DrawBattleEntryBackground(void) u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { - LZDecompressVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(gBattleTerrainAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); return; } else if (trainerClass == TRAINER_CLASS_CHAMPION) { - LZDecompressVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(gBattleTerrainAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); return; } } if (GetCurrentMapBattleScene() == MAP_BATTLE_SCENE_NORMAL) { - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].entryTileset, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].entryTilemap, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].entryTileset, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].entryTilemap, (void *)(BG_SCREEN_ADDR(28))); } else { - LZDecompressVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(gBattleTerrainAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTiles_Building, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gBattleTerrainAnimTilemap_Building, (void *)(BG_SCREEN_ADDR(28))); } } } @@ -1242,7 +1242,7 @@ bool8 LoadChosenBattleElement(u8 caseId) switch (caseId) { case 0: - LZDecompressVram(gBattleTextboxTiles, (void *)(BG_CHAR_ADDR(0))); + DecompressDataWithHeaderVram(gBattleTextboxTiles, (void *)(BG_CHAR_ADDR(0))); break; case 1: CopyToBgTilemapBuffer(0, gBattleTextboxTilemap, 0, 0); @@ -1254,17 +1254,17 @@ bool8 LoadChosenBattleElement(u8 caseId) case 3: if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) { - LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); } else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) { switch (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL)) { case SPECIES_GROUDON: - LZDecompressVram(gBattleTerrainTiles_Cave, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Cave, (void*)(BG_CHAR_ADDR(2))); break; case SPECIES_KYOGRE: - LZDecompressVram(gBattleTerrainTilemap_Water, (void*)(BG_SCREEN_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Water, (void*)(BG_SCREEN_ADDR(2))); break; } } @@ -1275,12 +1275,12 @@ bool8 LoadChosenBattleElement(u8 caseId) u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { - LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); break; } else if (trainerClass == TRAINER_CLASS_CHAMPION) { - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); break; } } @@ -1289,31 +1289,31 @@ bool8 LoadChosenBattleElement(u8 caseId) { default: case MAP_BATTLE_SCENE_NORMAL: - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].tileset, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].tileset, (void *)(BG_CHAR_ADDR(2))); break; case MAP_BATTLE_SCENE_GYM: - LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); break; case MAP_BATTLE_SCENE_MAGMA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); break; case MAP_BATTLE_SCENE_AQUA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); break; case MAP_BATTLE_SCENE_SIDNEY: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); break; case MAP_BATTLE_SCENE_PHOEBE: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); break; case MAP_BATTLE_SCENE_GLACIA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); break; case MAP_BATTLE_SCENE_DRAKE: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void *)(BG_CHAR_ADDR(2))); break; case MAP_BATTLE_SCENE_FRONTIER: - LZDecompressVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void *)(BG_CHAR_ADDR(2))); break; } } @@ -1321,14 +1321,14 @@ bool8 LoadChosenBattleElement(u8 caseId) case 4: if (gBattleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_EREADER_TRAINER)) { - LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); } else if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) { if (GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL) == SPECIES_GROUDON) - LZDecompressVram(gBattleTerrainTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); else - LZDecompressVram(gBattleTerrainTilemap_Water, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Water, (void *)(BG_SCREEN_ADDR(26))); } else { @@ -1337,12 +1337,12 @@ bool8 LoadChosenBattleElement(u8 caseId) u32 trainerClass = GetTrainerClassFromId(gTrainerBattleOpponent_A); if (trainerClass == TRAINER_CLASS_LEADER) { - LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); break; } else if (trainerClass == TRAINER_CLASS_CHAMPION) { - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); break; } } @@ -1351,31 +1351,31 @@ bool8 LoadChosenBattleElement(u8 caseId) { default: case MAP_BATTLE_SCENE_NORMAL: - LZDecompressVram(sBattleTerrainTable[gBattleTerrain].tilemap, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(sBattleTerrainTable[gBattleTerrain].tilemap, (void *)(BG_SCREEN_ADDR(26))); break; case MAP_BATTLE_SCENE_GYM: - LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); break; case MAP_BATTLE_SCENE_MAGMA: - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); break; case MAP_BATTLE_SCENE_AQUA: - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); break; case MAP_BATTLE_SCENE_SIDNEY: - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); break; case MAP_BATTLE_SCENE_PHOEBE: - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); break; case MAP_BATTLE_SCENE_GLACIA: - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); break; case MAP_BATTLE_SCENE_DRAKE: - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void *)(BG_SCREEN_ADDR(26))); break; case MAP_BATTLE_SCENE_FRONTIER: - LZDecompressVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void *)(BG_SCREEN_ADDR(26))); break; } } diff --git a/src/battle_dome.c b/src/battle_dome.c index 19c508652342..233c25dc50e6 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -5245,7 +5245,7 @@ static void Task_ShowTourneyTree(u8 taskId) break; case 2: sTilemapBuffer = AllocZeroed(BG_SCREEN_SIZE); - LZDecompressWram(gDomeTourneyTree_Tilemap, sTilemapBuffer); + DecompressDataWithHeaderWram(gDomeTourneyTree_Tilemap, sTilemapBuffer); SetBgTilemapBuffer(1, sTilemapBuffer); CopyBgTilemapBufferToVram(1); DecompressAndLoadBgGfxUsingHeap(1, gDomeTourneyTree_Gfx, 0x2000, 0, 0); diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 7677c9f38c38..da15c88aeaa4 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -655,7 +655,7 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) else lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personalityValue); - LZDecompressWram(lzPaletteData, gDecompressionBuffer); + DecompressDataWithHeaderWram(lzPaletteData, gDecompressionBuffer); LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); LoadPalette(gDecompressionBuffer, BG_PLTT_ID(8) + BG_PLTT_ID(battler), PLTT_SIZE_4BPP); @@ -809,7 +809,7 @@ bool8 BattleLoadAllHealthBoxesGfx(u8 state) void LoadBattleBarGfx(u8 unused) { - LZDecompressWram(gBattleInterfaceGfx_BattleBar, gMonSpritesGfxPtr->barFontGfx); + DecompressDataWithHeaderWram(gBattleInterfaceGfx_BattleBar, gMonSpritesGfxPtr->barFontGfx); } bool8 BattleInitAllSprites(u8 *state1, u8 *battler) @@ -975,7 +975,7 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo DmaCopy32(3, src, dst, MON_PIC_SIZE); paletteOffset = OBJ_PLTT_ID(battlerAtk); lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(targetSpecies, isShiny, personalityValue); - LZDecompressWram(lzPaletteData, gDecompressionBuffer); + DecompressDataWithHeaderWram(lzPaletteData, gDecompressionBuffer); LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); if (!megaEvo) @@ -1022,11 +1022,11 @@ void BattleLoadSubstituteOrMonSpriteGfx(u8 battler, bool8 loadMonSprite) position = GetBattlerPosition(battler); if (IsContest()) - LZDecompressVram(gBattleAnimSpriteGfx_SubstituteBack, gMonSpritesGfxPtr->spritesGfx[position]); + DecompressDataWithHeaderVram(gBattleAnimSpriteGfx_SubstituteBack, gMonSpritesGfxPtr->spritesGfx[position]); else if (GetBattlerSide(battler) != B_SIDE_PLAYER) - LZDecompressVram(gBattleAnimSpriteGfx_Substitute, gMonSpritesGfxPtr->spritesGfx[position]); + DecompressDataWithHeaderVram(gBattleAnimSpriteGfx_Substitute, gMonSpritesGfxPtr->spritesGfx[position]); else - LZDecompressVram(gBattleAnimSpriteGfx_SubstituteBack, gMonSpritesGfxPtr->spritesGfx[position]); + DecompressDataWithHeaderVram(gBattleAnimSpriteGfx_SubstituteBack, gMonSpritesGfxPtr->spritesGfx[position]); for (i = 1; i < 4; i++) { diff --git a/src/battle_pyramid_bag.c b/src/battle_pyramid_bag.c index be6c5bf9915e..e7f33018e5db 100644 --- a/src/battle_pyramid_bag.c +++ b/src/battle_pyramid_bag.c @@ -573,7 +573,7 @@ static bool8 LoadPyramidBagGfx(void) case 1: if (FreeTempTileDataBuffersIfPossible() != TRUE) { - LZDecompressWram(gBattlePyramidBagTilemap, gPyramidBagMenu->tilemapBuffer); + DecompressDataWithHeaderWram(gBattlePyramidBagTilemap, gPyramidBagMenu->tilemapBuffer); gPyramidBagMenu->state++; } break; @@ -1561,7 +1561,7 @@ static void LoadPyramidBagPalette(void) struct SpritePalette spritePalette; u16 *palPtr = Alloc(2 * PLTT_SIZE_4BPP); - LZDecompressWram(gBattlePyramidBag_Pal, palPtr); + DecompressDataWithHeaderWram(gBattlePyramidBag_Pal, palPtr); spritePalette.data = palPtr + PLTT_ID(gSaveBlock2Ptr->frontier.lvlMode); spritePalette.tag = TAG_PYRAMID_BAG; LoadSpritePalette(&spritePalette); diff --git a/src/battle_transition.c b/src/battle_transition.c index fbaa5cc0de34..7b738a3371ca 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -1370,7 +1370,7 @@ static bool8 Aqua_Init(struct Task *task) InitPatternWeaveTransition(task); GetBg0TilesDst(&tilemap, &tileset); CpuFill16(0, tilemap, BG_SCREEN_SIZE); - LZ77UnCompVram(sTeamAqua_Tileset, tileset); + DecompressDataWithHeaderVram(sTeamAqua_Tileset, tileset); LoadPalette(sEvilTeam_Palette, BG_PLTT_ID(15), sizeof(sEvilTeam_Palette)); task->tState++; @@ -1385,7 +1385,7 @@ static bool8 Magma_Init(struct Task *task) InitPatternWeaveTransition(task); GetBg0TilesDst(&tilemap, &tileset); CpuFill16(0, tilemap, BG_SCREEN_SIZE); - LZ77UnCompVram(sTeamMagma_Tileset, tileset); + DecompressDataWithHeaderVram(sTeamMagma_Tileset, tileset); LoadPalette(sEvilTeam_Palette, BG_PLTT_ID(15), sizeof(sEvilTeam_Palette)); task->tState++; @@ -1445,7 +1445,7 @@ static bool8 Aqua_SetGfx(struct Task *task) u16 *tilemap, *tileset; GetBg0TilesDst(&tilemap, &tileset); - LZ77UnCompVram(sTeamAqua_Tilemap, tilemap); + DecompressDataWithHeaderVram(sTeamAqua_Tilemap, tilemap); SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; @@ -1457,7 +1457,7 @@ static bool8 Magma_SetGfx(struct Task *task) u16 *tilemap, *tileset; GetBg0TilesDst(&tilemap, &tileset); - LZ77UnCompVram(sTeamMagma_Tilemap, tilemap); + DecompressDataWithHeaderVram(sTeamMagma_Tilemap, tilemap); SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; @@ -1511,8 +1511,8 @@ static bool8 Kyogre_Init(struct Task *task) GetBg0TilesDst(&tilemap, &tileset); CpuFill16(0, tilemap, BG_SCREEN_SIZE); - LZ77UnCompVram(sKyogre_Tileset, tileset); - LZ77UnCompVram(sKyogre_Tilemap, tilemap); + DecompressDataWithHeaderVram(sKyogre_Tileset, tileset); + DecompressDataWithHeaderVram(sKyogre_Tilemap, tilemap); task->tState++; return FALSE; @@ -3300,8 +3300,8 @@ static bool8 Groudon_Init(struct Task *task) GetBg0TilesDst(&tilemap, &tileset); CpuFill16(0, tilemap, BG_SCREEN_SIZE); - LZ77UnCompVram(sGroudon_Tileset, tileset); - LZ77UnCompVram(sGroudon_Tilemap, tilemap); + DecompressDataWithHeaderVram(sGroudon_Tileset, tileset); + DecompressDataWithHeaderVram(sGroudon_Tilemap, tilemap); task->tState++; task->tTimer = 0; @@ -4165,7 +4165,7 @@ static bool8 FrontierLogoWiggle_Init(struct Task *task) InitPatternWeaveTransition(task); GetBg0TilesDst(&tilemap, &tileset); CpuFill16(0, tilemap, BG_SCREEN_SIZE); - LZ77UnCompVram(sFrontierLogo_Tileset, tileset); + DecompressDataWithHeaderVram(sFrontierLogo_Tileset, tileset); LoadPalette(sFrontierLogo_Palette, BG_PLTT_ID(15), sizeof(sFrontierLogo_Palette)); task->tState++; @@ -4177,7 +4177,7 @@ static bool8 FrontierLogoWiggle_SetGfx(struct Task *task) u16 *tilemap, *tileset; GetBg0TilesDst(&tilemap, &tileset); - LZ77UnCompVram(sFrontierLogo_Tilemap, tilemap); + DecompressDataWithHeaderVram(sFrontierLogo_Tilemap, tilemap); SetSinWave((s16*)gScanlineEffectRegBuffers[0], 0, task->tSinIndex, 132, task->tAmplitude, DISPLAY_HEIGHT); task->tState++; @@ -4227,7 +4227,7 @@ static bool8 FrontierLogoWave_Init(struct Task *task) REG_BLDALPHA = sTransitionData->BLDALPHA; GetBg0TilesDst(&tilemap, &tileset); CpuFill16(0, tilemap, BG_SCREEN_SIZE); - LZ77UnCompVram(sFrontierLogo_Tileset, tileset); + DecompressDataWithHeaderVram(sFrontierLogo_Tileset, tileset); LoadPalette(sFrontierLogo_Palette, BG_PLTT_ID(15), sizeof(sFrontierLogo_Palette)); sTransitionData->cameraY = 0; @@ -4240,7 +4240,7 @@ static bool8 FrontierLogoWave_SetGfx(struct Task *task) u16 *tilemap, *tileset; GetBg0TilesDst(&tilemap, &tileset); - LZ77UnCompVram(sFrontierLogo_Tilemap, tilemap); + DecompressDataWithHeaderVram(sFrontierLogo_Tilemap, tilemap); task->tState++; return TRUE; @@ -4372,7 +4372,7 @@ static bool8 FrontierSquares_Init(struct Task *task) u16 *tilemap, *tileset; GetBg0TilesDst(&tilemap, &tileset); - LZ77UnCompVram(sFrontierSquares_FilledBg_Tileset, tileset); + DecompressDataWithHeaderVram(sFrontierSquares_FilledBg_Tileset, tileset); FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32); FillBgTilemapBufferRect(0, 1, 0, 0, MARGIN_SIZE, 32, 15); @@ -4430,13 +4430,13 @@ static bool8 FrontierSquares_Shrink(struct Task *task) break; case 1: BlendPalettes(PALETTES_ALL & ~(1 << 15), 16, RGB_BLACK); - LZ77UnCompVram(sFrontierSquares_EmptyBg_Tileset, tileset); + DecompressDataWithHeaderVram(sFrontierSquares_EmptyBg_Tileset, tileset); break; case 2: - LZ77UnCompVram(sFrontierSquares_Shrink1_Tileset, tileset); + DecompressDataWithHeaderVram(sFrontierSquares_Shrink1_Tileset, tileset); break; case 3: - LZ77UnCompVram(sFrontierSquares_Shrink2_Tileset, tileset); + DecompressDataWithHeaderVram(sFrontierSquares_Shrink2_Tileset, tileset); break; default: FillBgTilemapBufferRect_Palette0(0, 1, 0, 0, 32, 32); @@ -4467,7 +4467,7 @@ static bool8 FrontierSquaresSpiral_Init(struct Task *task) u16 *tilemap, *tileset; GetBg0TilesDst(&tilemap, &tileset); - LZ77UnCompVram(sFrontierSquares_FilledBg_Tileset, tileset); + DecompressDataWithHeaderVram(sFrontierSquares_FilledBg_Tileset, tileset); FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32); FillBgTilemapBufferRect(0, 1, 0, 0, MARGIN_SIZE, 32, 15); @@ -4585,7 +4585,7 @@ static bool8 FrontierSquaresScroll_Init(struct Task *task) u16 *tilemap, *tileset; GetBg0TilesDst(&tilemap, &tileset); - LZ77UnCompVram(sFrontierSquares_FilledBg_Tileset, tileset); + DecompressDataWithHeaderVram(sFrontierSquares_FilledBg_Tileset, tileset); FillBgTilemapBufferRect_Palette0(0, 0, 0, 0, 32, 32); CopyBgTilemapBufferToVram(0); LoadPalette(sFrontierSquares_Palette, BG_PLTT_ID(15), sizeof(sFrontierSquares_Palette)); diff --git a/src/battle_transition_frontier.c b/src/battle_transition_frontier.c index 3e40129fa5ef..c426e6e60c3a 100644 --- a/src/battle_transition_frontier.c +++ b/src/battle_transition_frontier.c @@ -221,8 +221,8 @@ static void LoadLogoGfx(void) u16 *tilemap, *tileset; GetBg0TilesDst(&tilemap, &tileset); - LZ77UnCompVram(sLogoCenter_Gfx, tileset); - LZ77UnCompVram(sLogoCenter_Tilemap, tilemap); + DecompressDataWithHeaderVram(sLogoCenter_Gfx, tileset); + DecompressDataWithHeaderVram(sLogoCenter_Tilemap, tilemap); LoadPalette(sLogo_Pal, BG_PLTT_ID(15), sizeof(sLogo_Pal)); LoadCompressedSpriteSheet(&sSpriteSheet_LogoCircles); LoadSpritePalette(&sSpritePalette_LogoCircles); diff --git a/src/berry_blender.c b/src/berry_blender.c index bf094b6fb98a..1bc4165b209f 100644 --- a/src/berry_blender.c +++ b/src/berry_blender.c @@ -943,7 +943,7 @@ static bool8 LoadBerryBlenderGfx(void) { case 0: sBerryBlender->tilesBuffer = AllocZeroed(GetDecompressedDataSize(gBerryBlenderCenter_Gfx) + 100); - LZDecompressWram(gBerryBlenderCenter_Gfx, sBerryBlender->tilesBuffer); + DecompressDataWithHeaderWram(gBerryBlenderCenter_Gfx, sBerryBlender->tilesBuffer); sBerryBlender->loadGfxState++; break; case 1: @@ -957,7 +957,7 @@ static bool8 LoadBerryBlenderGfx(void) sBerryBlender->loadGfxState++; break; case 3: - LZDecompressWram(gBerryBlenderOuter_Gfx, sBerryBlender->tilesBuffer); + DecompressDataWithHeaderWram(gBerryBlenderOuter_Gfx, sBerryBlender->tilesBuffer); sBerryBlender->loadGfxState++; break; case 4: @@ -965,7 +965,7 @@ static bool8 LoadBerryBlenderGfx(void) sBerryBlender->loadGfxState++; break; case 5: - LZDecompressWram(gBerryBlenderOuter_Tilemap, sBerryBlender->tilesBuffer); + DecompressDataWithHeaderWram(gBerryBlenderOuter_Tilemap, sBerryBlender->tilesBuffer); sBerryBlender->loadGfxState++; break; case 6: diff --git a/src/berry_crush.c b/src/berry_crush.c index 1f997708a751..1e6782a1bd24 100755 --- a/src/berry_crush.c +++ b/src/berry_crush.c @@ -1944,7 +1944,7 @@ static void CopyPlayerNameWindowGfxToBg(struct BerryCrushGame *game) u8 i = 0; u8 *windowGfx; - LZ77UnCompWram(gBerryCrush_TextWindows_Tilemap, gDecompressionBuffer); + DecompressDataWithHeaderWram(gBerryCrush_TextWindows_Tilemap, gDecompressionBuffer); for (windowGfx = gDecompressionBuffer; i < game->playerCount; i++) { diff --git a/src/berry_fix_graphics.c b/src/berry_fix_graphics.c index 80510a4ce173..84a9e874633e 100644 --- a/src/berry_fix_graphics.c +++ b/src/berry_fix_graphics.c @@ -41,8 +41,8 @@ static void UNUSED LoadBerryFixGraphics(u32 idx) REG_BG0HOFS = 0; REG_BG0VOFS = 0; REG_BLDCNT = 0; - LZ77UnCompVram(sBerryFixGraphics[idx].gfx, (void *)BG_CHAR_ADDR(0)); - LZ77UnCompVram(sBerryFixGraphics[idx].tilemap, (void *)BG_SCREEN_ADDR(31)); + DecompressDataWithHeaderVram(sBerryFixGraphics[idx].gfx, (void *)BG_CHAR_ADDR(0)); + DecompressDataWithHeaderVram(sBerryFixGraphics[idx].tilemap, (void *)BG_SCREEN_ADDR(31)); CpuCopy16(sBerryFixGraphics[idx].pltt, (void *)BG_PLTT, BG_PLTT_SIZE); REG_BG0CNT = BGCNT_SCREENBASE(31); REG_DISPCNT = DISPCNT_BG0_ON; diff --git a/src/berry_fix_program.c b/src/berry_fix_program.c index 5900cb298abb..025e71cd0a87 100644 --- a/src/berry_fix_program.c +++ b/src/berry_fix_program.c @@ -366,8 +366,8 @@ static void BerryFix_SetScene(int scene) break; } CopyBgTilemapBufferToVram(0); - LZ77UnCompVram(sBerryFixGraphics[scene].gfx, (void *)BG_CHAR_ADDR(1)); - LZ77UnCompVram(sBerryFixGraphics[scene].tilemap, (void *)BG_SCREEN_ADDR(31)); + DecompressDataWithHeaderVram(sBerryFixGraphics[scene].gfx, (void *)BG_CHAR_ADDR(1)); + DecompressDataWithHeaderVram(sBerryFixGraphics[scene].tilemap, (void *)BG_SCREEN_ADDR(31)); // These palettes range in size from 32-48 colors, so the below is interpreting whatever // follows the palette (by default, the corresponding tiles) as the remaining 80-96. CpuCopy32(sBerryFixGraphics[scene].palette, (void *)BG_PLTT, PLTT_SIZEOF(128)); diff --git a/src/berry_tag_screen.c b/src/berry_tag_screen.c index fcd322ce3374..8f5247fd3275 100644 --- a/src/berry_tag_screen.c +++ b/src/berry_tag_screen.c @@ -334,12 +334,12 @@ static bool8 LoadBerryTagGfx(void) case 1: if (FreeTempTileDataBuffersIfPossible() != TRUE) { - LZDecompressWram(gBerryTag_Gfx, sBerryTag->tilemapBuffers[0]); + DecompressDataWithHeaderWram(gBerryTag_Gfx, sBerryTag->tilemapBuffers[0]); sBerryTag->gfxState++; } break; case 2: - LZDecompressWram(gBerryTag_Pal, sBerryTag->tilemapBuffers[2]); + DecompressDataWithHeaderWram(gBerryTag_Pal, sBerryTag->tilemapBuffers[2]); sBerryTag->gfxState++; break; case 3: diff --git a/src/bg.c b/src/bg.c index 27a5fb0501bd..c8a0580e8266 100644 --- a/src/bg.c +++ b/src/bg.c @@ -872,7 +872,7 @@ void CopyToBgTilemapBuffer(u32 bg, const void *src, u16 mode, u16 destOffset) if (mode != 0) CpuCopy16(src, (void *)(sGpuBgConfigs2[bg].tilemap + (destOffset * 2)), mode); else - LZ77UnCompWram(src, (void *)(sGpuBgConfigs2[bg].tilemap + (destOffset * 2))); + DecompressDataWithHeaderWram(src, (void *)(sGpuBgConfigs2[bg].tilemap + (destOffset * 2))); } } diff --git a/src/contest.c b/src/contest.c index 96bb4e925d49..5b5cfc44c888 100644 --- a/src/contest.c +++ b/src/contest.c @@ -1133,8 +1133,8 @@ void LoadContestBgAfterMoveAnim(void) { s32 i; - LZDecompressVram(gContestInterfaceGfx, (void *)VRAM); - LZDecompressVram(gContestAudienceGfx, (void *)(BG_SCREEN_ADDR(4))); + DecompressDataWithHeaderVram(gContestInterfaceGfx, (void *)VRAM); + DecompressDataWithHeaderVram(gContestAudienceGfx, (void *)(BG_SCREEN_ADDR(4))); CopyToBgTilemapBuffer(3, gContestAudienceTilemap, 0, 0); CopyBgTilemapBufferToVram(3); LoadCompressedPalette(gContestInterfaceAudiencePalette, BG_PLTT_OFFSET, BG_PLTT_SIZE); @@ -1414,10 +1414,10 @@ static bool8 SetupContestGraphics(u8 *stateVar) RequestDma3Fill(0, (void *)VRAM + 0x10000, 0x8000, 1); break; case 1: - LZDecompressVram(gContestInterfaceGfx, (void *)VRAM); + DecompressDataWithHeaderVram(gContestInterfaceGfx, (void *)VRAM); break; case 2: - LZDecompressVram(gContestAudienceGfx, (void *)(BG_SCREEN_ADDR(4))); + DecompressDataWithHeaderVram(gContestAudienceGfx, (void *)(BG_SCREEN_ADDR(4))); DmaCopyLarge32(3, (void *)(BG_SCREEN_ADDR(4)), eUnzippedContestAudience_Gfx, 0x2000, 0x1000); break; case 3: diff --git a/src/contest_painting.c b/src/contest_painting.c index 8b647be12f04..cbcade4a751d 100644 --- a/src/contest_painting.c +++ b/src/contest_painting.c @@ -364,7 +364,7 @@ static void VBlankCB_ContestPainting(void) static void InitContestMonPixels(u16 species, bool8 backPic) { const void *pal = GetMonSpritePalFromSpeciesAndPersonality(species, gContestPaintingWinner->isShiny, gContestPaintingWinner->personality); - LZDecompressVram(pal, gContestPaintingMonPalette); + DecompressDataWithHeaderVram(pal, gContestPaintingMonPalette); if (!backPic) { HandleLoadSpecialPokePic(TRUE, diff --git a/src/contest_util.c b/src/contest_util.c index 3938fcd382da..a2b4e02caa51 100644 --- a/src/contest_util.c +++ b/src/contest_util.c @@ -452,7 +452,7 @@ static void LoadContestResultsBgGfx(void) s8 numStars, round2Points; u16 tile1, tile2; - LZDecompressVram(gContestResults_Gfx, (void *)BG_CHAR_ADDR(0)); + DecompressDataWithHeaderVram(gContestResults_Gfx, (void *)BG_CHAR_ADDR(0)); CopyToBgTilemapBuffer(3, gContestResults_Bg_Tilemap, 0, 0); CopyToBgTilemapBuffer(2, gContestResults_Interface_Tilemap, 0, 0); CopyToBgTilemapBuffer(0, gContestResults_WinnerBanner_Tilemap, 0, 0); diff --git a/src/credits.c b/src/credits.c index 9269460e928c..02e3c25ff688 100644 --- a/src/credits.c +++ b/src/credits.c @@ -543,8 +543,8 @@ static void Task_LoadShowMons(u8 taskId) ResetAllPicSprites(); FreeAllSpritePalettes(); gReservedSpritePaletteCount = 8; - LZ77UnCompVram(gBirchBagGrass_Gfx, (void *)VRAM); - LZ77UnCompVram(gBirchGrassTilemap, (void *)(BG_SCREEN_ADDR(7))); + DecompressDataWithHeaderVram(gBirchBagGrass_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(gBirchGrassTilemap, (void *)(BG_SCREEN_ADDR(7))); LoadPalette(gBirchBagGrass_Pal + 1, BG_PLTT_ID(0) + 1, PLTT_SIZEOF(2 * 16 - 1)); for (i = 0; i < MON_PIC_SIZE; i++) @@ -1285,7 +1285,7 @@ static void LoadTheEndScreen(u16 tileOffsetLoad, u16 tileOffsetWrite, u16 palOff u16 baseTile; u16 i; - LZ77UnCompVram(sCreditsCopyrightEnd_Gfx, (void *)(VRAM + tileOffsetLoad)); + DecompressDataWithHeaderVram(sCreditsCopyrightEnd_Gfx, (void *)(VRAM + tileOffsetLoad)); LoadPalette(gIntroCopyright_Pal, palOffset, sizeof(gIntroCopyright_Pal)); baseTile = (palOffset / 16) << 12; diff --git a/src/decompress.c b/src/decompress.c index 284bce48d331..4eeccdf68e30 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -8,15 +8,161 @@ EWRAM_DATA ALIGNED(4) u8 gDecompressionBuffer[0x4000] = {0}; -void LZDecompressWram(const u32 *src, void *dest) -{ - LZ77UnCompWram(src, dest); -} +// === WARNING === WARNING === WARNING === +// === No user serviceable code before === +// === the SpecialPokePic function, do === +// === not modify code unless magician === +// === WARNING === WARNING === WARNING === -void LZDecompressVram(const u32 *src, void *dest) -{ - LZ77UnCompVram(src, dest); -} +#define TABLE_READ_K(tableVal)((tableVal & 7)) +#define TABLE_READ_SYMBOL(tableVal)((tableVal & 0xFF) >> 3) +#define TABLE_READ_Y(tableVal)((tableVal >> 8) & 0xFF) +#define TABLE_READ_MASK(tableVal)((tableVal >> 16)) + +/* +Layout is the following: +u32 kVal:3; +u32 symbol:5; // Set in BuildDecompressionTable +u32 yVal:8; +u32 mask:8; +*/ + +#define SET_TABLE_ENTRY(k, y, mask)(((k) & 7) | ((y) << 8) | ((mask) << 16)) + +static IWRAM_DATA u32 sWorkingYkTable[TANS_TABLE_SIZE] = {0}; + +// Helper struct to build the tANS decode tables without having to do calculations at run-time +// Mask Table is 0, 1, 3, 7, 15, 31, 63. +static const u32 sYkTemplate[2*TANS_TABLE_SIZE] = { + [0] = 0, + [1] = SET_TABLE_ENTRY(6, (1 << 6) - 64, 63), + [2] = SET_TABLE_ENTRY(5, (2 << 5) - 64, 31), + [3] = SET_TABLE_ENTRY(5, (3 << 5) - 64, 31), + [4] = SET_TABLE_ENTRY(4, (4 << 4) - 64, 15), + [5] = SET_TABLE_ENTRY(4, (5 << 4) - 64, 15), + [6] = SET_TABLE_ENTRY(4, (6 << 4) - 64, 15), + [7] = SET_TABLE_ENTRY(4, (7 << 4) - 64, 15), + [8] = SET_TABLE_ENTRY(3, (8 << 3) - 64, 7), + [9] = SET_TABLE_ENTRY(3, (9 << 3) - 64, 7), + [10] = SET_TABLE_ENTRY(3, (10 << 3) - 64, 7), + [11] = SET_TABLE_ENTRY(3, (11 << 3) - 64, 7), + [12] = SET_TABLE_ENTRY(3, (12 << 3) - 64, 7), + [13] = SET_TABLE_ENTRY(3, (13 << 3) - 64, 7), + [14] = SET_TABLE_ENTRY(3, (14 << 3) - 64, 7), + [15] = SET_TABLE_ENTRY(3, (15 << 3) - 64, 7), + [16] = SET_TABLE_ENTRY(2, (16 << 2) - 64, 3), + [17] = SET_TABLE_ENTRY(2, (17 << 2) - 64, 3), + [18] = SET_TABLE_ENTRY(2, (18 << 2) - 64, 3), + [19] = SET_TABLE_ENTRY(2, (19 << 2) - 64, 3), + [20] = SET_TABLE_ENTRY(2, (20 << 2) - 64, 3), + [21] = SET_TABLE_ENTRY(2, (21 << 2) - 64, 3), + [22] = SET_TABLE_ENTRY(2, (22 << 2) - 64, 3), + [23] = SET_TABLE_ENTRY(2, (23 << 2) - 64, 3), + [24] = SET_TABLE_ENTRY(2, (24 << 2) - 64, 3), + [25] = SET_TABLE_ENTRY(2, (25 << 2) - 64, 3), + [26] = SET_TABLE_ENTRY(2, (26 << 2) - 64, 3), + [27] = SET_TABLE_ENTRY(2, (27 << 2) - 64, 3), + [28] = SET_TABLE_ENTRY(2, (28 << 2) - 64, 3), + [29] = SET_TABLE_ENTRY(2, (29 << 2) - 64, 3), + [30] = SET_TABLE_ENTRY(2, (30 << 2) - 64, 3), + [31] = SET_TABLE_ENTRY(2, (31 << 2) - 64, 3), + [32] = SET_TABLE_ENTRY(1, (32 << 1) - 64, 1), + [33] = SET_TABLE_ENTRY(1, (33 << 1) - 64, 1), + [34] = SET_TABLE_ENTRY(1, (34 << 1) - 64, 1), + [35] = SET_TABLE_ENTRY(1, (35 << 1) - 64, 1), + [36] = SET_TABLE_ENTRY(1, (36 << 1) - 64, 1), + [37] = SET_TABLE_ENTRY(1, (37 << 1) - 64, 1), + [38] = SET_TABLE_ENTRY(1, (38 << 1) - 64, 1), + [39] = SET_TABLE_ENTRY(1, (39 << 1) - 64, 1), + [40] = SET_TABLE_ENTRY(1, (40 << 1) - 64, 1), + [41] = SET_TABLE_ENTRY(1, (41 << 1) - 64, 1), + [42] = SET_TABLE_ENTRY(1, (42 << 1) - 64, 1), + [43] = SET_TABLE_ENTRY(1, (43 << 1) - 64, 1), + [44] = SET_TABLE_ENTRY(1, (44 << 1) - 64, 1), + [45] = SET_TABLE_ENTRY(1, (45 << 1) - 64, 1), + [46] = SET_TABLE_ENTRY(1, (46 << 1) - 64, 1), + [47] = SET_TABLE_ENTRY(1, (47 << 1) - 64, 1), + [48] = SET_TABLE_ENTRY(1, (48 << 1) - 64, 1), + [49] = SET_TABLE_ENTRY(1, (49 << 1) - 64, 1), + [50] = SET_TABLE_ENTRY(1, (50 << 1) - 64, 1), + [51] = SET_TABLE_ENTRY(1, (51 << 1) - 64, 1), + [52] = SET_TABLE_ENTRY(1, (52 << 1) - 64, 1), + [53] = SET_TABLE_ENTRY(1, (53 << 1) - 64, 1), + [54] = SET_TABLE_ENTRY(1, (54 << 1) - 64, 1), + [55] = SET_TABLE_ENTRY(1, (55 << 1) - 64, 1), + [56] = SET_TABLE_ENTRY(1, (56 << 1) - 64, 1), + [57] = SET_TABLE_ENTRY(1, (57 << 1) - 64, 1), + [58] = SET_TABLE_ENTRY(1, (58 << 1) - 64, 1), + [59] = SET_TABLE_ENTRY(1, (59 << 1) - 64, 1), + [60] = SET_TABLE_ENTRY(1, (60 << 1) - 64, 1), + [61] = SET_TABLE_ENTRY(1, (61 << 1) - 64, 1), + [62] = SET_TABLE_ENTRY(1, (62 << 1) - 64, 1), + [63] = SET_TABLE_ENTRY(1, (63 << 1) - 64, 1), + [64] = SET_TABLE_ENTRY(0, 64 - 64, 0), + [65] = SET_TABLE_ENTRY(0, 65 - 64, 0), + [66] = SET_TABLE_ENTRY(0, 66 - 64, 0), + [67] = SET_TABLE_ENTRY(0, 67 - 64, 0), + [68] = SET_TABLE_ENTRY(0, 68 - 64, 0), + [69] = SET_TABLE_ENTRY(0, 69 - 64, 0), + [70] = SET_TABLE_ENTRY(0, 70 - 64, 0), + [71] = SET_TABLE_ENTRY(0, 71 - 64, 0), + [72] = SET_TABLE_ENTRY(0, 72 - 64, 0), + [73] = SET_TABLE_ENTRY(0, 73 - 64, 0), + [74] = SET_TABLE_ENTRY(0, 74 - 64, 0), + [75] = SET_TABLE_ENTRY(0, 75 - 64, 0), + [76] = SET_TABLE_ENTRY(0, 76 - 64, 0), + [77] = SET_TABLE_ENTRY(0, 77 - 64, 0), + [78] = SET_TABLE_ENTRY(0, 78 - 64, 0), + [79] = SET_TABLE_ENTRY(0, 79 - 64, 0), + [80] = SET_TABLE_ENTRY(0, 80 - 64, 0), + [81] = SET_TABLE_ENTRY(0, 81 - 64, 0), + [82] = SET_TABLE_ENTRY(0, 82 - 64, 0), + [83] = SET_TABLE_ENTRY(0, 83 - 64, 0), + [84] = SET_TABLE_ENTRY(0, 84 - 64, 0), + [85] = SET_TABLE_ENTRY(0, 85 - 64, 0), + [86] = SET_TABLE_ENTRY(0, 86 - 64, 0), + [87] = SET_TABLE_ENTRY(0, 87 - 64, 0), + [88] = SET_TABLE_ENTRY(0, 88 - 64, 0), + [89] = SET_TABLE_ENTRY(0, 89 - 64, 0), + [90] = SET_TABLE_ENTRY(0, 90 - 64, 0), + [91] = SET_TABLE_ENTRY(0, 91 - 64, 0), + [92] = SET_TABLE_ENTRY(0, 92 - 64, 0), + [93] = SET_TABLE_ENTRY(0, 93 - 64, 0), + [94] = SET_TABLE_ENTRY(0, 94 - 64, 0), + [95] = SET_TABLE_ENTRY(0, 95 - 64, 0), + [96] = SET_TABLE_ENTRY(0, 96 - 64, 0), + [97] = SET_TABLE_ENTRY(0, 97 - 64, 0), + [98] = SET_TABLE_ENTRY(0, 98 - 64, 0), + [99] = SET_TABLE_ENTRY(0, 99 - 64, 0), + [100] = SET_TABLE_ENTRY(0, 100 - 64, 0), + [101] = SET_TABLE_ENTRY(0, 101 - 64, 0), + [102] = SET_TABLE_ENTRY(0, 102 - 64, 0), + [103] = SET_TABLE_ENTRY(0, 103 - 64, 0), + [104] = SET_TABLE_ENTRY(0, 104 - 64, 0), + [105] = SET_TABLE_ENTRY(0, 105 - 64, 0), + [106] = SET_TABLE_ENTRY(0, 106 - 64, 0), + [107] = SET_TABLE_ENTRY(0, 107 - 64, 0), + [108] = SET_TABLE_ENTRY(0, 108 - 64, 0), + [109] = SET_TABLE_ENTRY(0, 109 - 64, 0), + [110] = SET_TABLE_ENTRY(0, 110 - 64, 0), + [111] = SET_TABLE_ENTRY(0, 111 - 64, 0), + [112] = SET_TABLE_ENTRY(0, 112 - 64, 0), + [113] = SET_TABLE_ENTRY(0, 113 - 64, 0), + [114] = SET_TABLE_ENTRY(0, 114 - 64, 0), + [115] = SET_TABLE_ENTRY(0, 115 - 64, 0), + [116] = SET_TABLE_ENTRY(0, 116 - 64, 0), + [117] = SET_TABLE_ENTRY(0, 117 - 64, 0), + [118] = SET_TABLE_ENTRY(0, 118 - 64, 0), + [119] = SET_TABLE_ENTRY(0, 119 - 64, 0), + [120] = SET_TABLE_ENTRY(0, 120 - 64, 0), + [121] = SET_TABLE_ENTRY(0, 121 - 64, 0), + [122] = SET_TABLE_ENTRY(0, 122 - 64, 0), + [123] = SET_TABLE_ENTRY(0, 123 - 64, 0), + [124] = SET_TABLE_ENTRY(0, 124 - 64, 0), + [125] = SET_TABLE_ENTRY(0, 125 - 64, 0), + [126] = SET_TABLE_ENTRY(0, 126 - 64, 0), + [127] = SET_TABLE_ENTRY(0, 127 - 64, 0), +}; // Checks if `ptr` is likely LZ77 data // Checks word-alignment, min/max size, and header byte @@ -44,7 +190,7 @@ u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src) { struct SpriteSheet dest; - LZ77UnCompWram(src->data, gDecompressionBuffer); + DecompressDataWithHeaderWram(src->data, gDecompressionBuffer); dest.data = gDecompressionBuffer; dest.size = src->size; dest.tag = src->tag; @@ -62,7 +208,7 @@ u16 LoadCompressedSpriteSheetByTemplate(const struct SpriteTemplate *template, s if ((size = IsLZ77Data(template->images->data, TILE_SIZE_4BPP, sizeof(gDecompressionBuffer))) == 0) return LoadSpriteSheetByTemplate(template, 0, offset); - LZ77UnCompWram(template->images->data, gDecompressionBuffer); + DecompressDataWithHeaderWram(template->images->data, gDecompressionBuffer); myImage.data = gDecompressionBuffer; myImage.size = size + offset; myTemplate.images = &myImage; @@ -75,7 +221,7 @@ void LoadCompressedSpriteSheetOverrideBuffer(const struct CompressedSpriteSheet { struct SpriteSheet dest; - LZ77UnCompWram(src->data, buffer); + DecompressDataWithHeaderWram(src->data, buffer); dest.data = buffer; dest.size = src->size; dest.tag = src->tag; @@ -86,7 +232,7 @@ void LoadCompressedSpritePalette(const struct CompressedSpritePalette *src) { struct SpritePalette dest; - LZ77UnCompWram(src->data, gDecompressionBuffer); + DecompressDataWithHeaderWram(src->data, gDecompressionBuffer); dest.data = (void *) gDecompressionBuffer; dest.tag = src->tag; LoadSpritePalette(&dest); @@ -96,7 +242,7 @@ void LoadCompressedSpritePaletteWithTag(const u32 *pal, u16 tag) { struct SpritePalette dest; - LZ77UnCompWram(pal, gDecompressionBuffer); + DecompressDataWithHeaderWram(pal, gDecompressionBuffer); dest.data = (void *) gDecompressionBuffer; dest.tag = tag; LoadSpritePalette(&dest); @@ -106,7 +252,7 @@ void LoadCompressedSpritePaletteOverrideBuffer(const struct CompressedSpritePale { struct SpritePalette dest; - LZ77UnCompWram(src->data, buffer); + DecompressDataWithHeaderWram(src->data, buffer); dest.data = buffer; dest.tag = src->tag; LoadSpritePalette(&dest); @@ -114,7 +260,7 @@ void LoadCompressedSpritePaletteOverrideBuffer(const struct CompressedSpritePale void DecompressPicFromTable(const struct CompressedSpriteSheet *src, void *buffer) { - LZ77UnCompWram(src->data, buffer); + DecompressDataWithHeaderWram(src->data, buffer); } void HandleLoadSpecialPokePic(bool32 isFrontPic, void *dest, s32 species, u32 personality) @@ -122,6 +268,781 @@ void HandleLoadSpecialPokePic(bool32 isFrontPic, void *dest, s32 species, u32 pe LoadSpecialPokePic(dest, species, personality, isFrontPic); } +// Wrapper function for all decompression calls using formats with headers +// calls the correct decompression function depending on the header +// VRAM version +void DecompressDataWithHeaderVram(const u32 *src, void *dest) +{ + struct SmolHeader header; + CpuCopy32(src, &header, 8); + switch (header.mode) + { + case MODE_LZ77: + LZ77UnCompVram(src, dest); + break; + default: + SmolDecompressData(&header, &src[2], dest); + } +} + +// Wrapper function for all decompression calls using formats with headers +// calls the correct decompression function depending on the header +// WRAM version +void DecompressDataWithHeaderWram(const u32 *src, void *dest) +{ + struct SmolHeader header; + CpuCopy32(src, &header, 8); + switch (header.mode) + { + case MODE_LZ77: + LZ77UnCompWram(src, dest); + break; + default: + SmolDecompressData(&header, &src[2], dest); + } +} + +#define REP0(X) +#define REP1(X) X +#define REP2(X) REP1(X) X +#define REP3(X) REP2(X) X +#define REP4(X) REP3(X) X +#define REP5(X) REP4(X) X +#define REP6(X) REP5(X) X +#define REP7(X) REP6(X) X +#define REP8(X) REP7(X) X +#define REP9(X) REP8(X) X +#define REP10(X) REP9(X) X + +#define REP(TENS,ONES,X) \ + REP##TENS(REP10(X)) \ + REP##ONES(X) + +// Unpack packed tANS encoded data symbol frequences into their individual parts +static inline void UnpackFrequenciesLoop(const u32 *packedFreqs, u16 *freqs, u32 i) +{ + // Loop unpack + freqs[i*5 + 0] = (packedFreqs[i] >> (6*0)) & PACKED_FREQ_MASK; + freqs[i*5 + 1] = (packedFreqs[i] >> (6*1)) & PACKED_FREQ_MASK; + freqs[i*5 + 2] = (packedFreqs[i] >> (6*2)) & PACKED_FREQ_MASK; + freqs[i*5 + 3] = (packedFreqs[i] >> (6*3)) & PACKED_FREQ_MASK; + freqs[i*5 + 4] = (packedFreqs[i] >> (6*4)) & PACKED_FREQ_MASK; + + freqs[15] += (packedFreqs[i] & PARTIAL_FREQ_MASK) >> (30 - 2*i); +} + +static inline void UnpackFrequencies(const u32 *packedFreqs, u16 *freqs) +{ + freqs[15] = 0; + + UnpackFrequenciesLoop(packedFreqs, freqs, 0); + UnpackFrequenciesLoop(packedFreqs, freqs, 1); + UnpackFrequenciesLoop(packedFreqs, freqs, 2); +} + +// This is a small function, so we can store it in IWRAM for improved performance and don't need to worry about it taking too much precious IWRAM space. +ARM_FUNC __attribute__((section(".iwram.code"))) __attribute__((noinline)) static void CopyTable(u32 *dst, const u32 *src, u32 size, u32 orrVal) +{ + for (u32 i = 0; i < size; i++) { + *dst++ = (*src++) | orrVal; + } +} + +// Build the tANS decompression table from the specified frequencies and the precomputed helper struct +__attribute__((optimize("-O3"))) static void BuildDecompressionTable(const u32 *packedFreqs, u32 *table) +{ + u16 freqs[16]; + + UnpackFrequencies(packedFreqs, freqs); + + for (u8 i = 0; i < 16; i++) + { + const u32 *srcTemplate; + + switch (freqs[i]) { + case 0: + break; + default: { + srcTemplate = &sYkTemplate[freqs[i]]; + CopyTable(table, srcTemplate, freqs[i], i << 3); + table += freqs[i]; + srcTemplate += freqs[i]; + break; + } + case 1: + srcTemplate = &sYkTemplate[1]; + REP(0, 1, *table++ = *srcTemplate++ | (i << 3);) + break; + case 2: + srcTemplate = &sYkTemplate[2]; + REP(0, 2, *table++ = (*srcTemplate++) | (i << 3);) + break; + case 3: + srcTemplate = &sYkTemplate[3]; + REP(0, 3, *table++ = (*srcTemplate++) | (i << 3);) + break; + } + } +} + +static IWRAM_DATA u8 sBitIndex = 0; +static IWRAM_DATA const u32 *sDataPtr = 0; +static IWRAM_DATA u32 sCurrState = 0; + +extern void FastUnsafeCopy32(void *, const void *, u32 size); + +// Dark Egg magic +static inline void CopyFuncToIwram(void *funcBuffer, void *funcStartAddress, void *funcEndAdress) +{ + FastUnsafeCopy32(funcBuffer, funcStartAddress, funcEndAdress - funcStartAddress); +} + +// The reason for macros and unrolling the loops stems from the following: +// currK can be max 6, meaning in the worst case scenario it takes minimum 4 loop iterations, where we don't need to check if bitIndex is >= 32, because it's mathematically impossible for it to be. +// This optimization matters for large images, because we don't waste a cycle on comparing operations. If the loops run over 5000 times in total, these can be costly. + +#define LOT_LOOP_MAIN(nibble) \ +{ \ + u32 ykVals = ykTable[sCurrState]; \ + symbol |= TABLE_READ_SYMBOL(ykVals) << (nibble*4); \ + currK = TABLE_READ_K(ykVals); \ + sCurrState = TABLE_READ_Y(ykVals); \ + sCurrState += (currBits >> bitIndex) & TABLE_READ_MASK(ykVals); \ + bitIndex += currK; \ +} + +// The same for all the loops +#define LOOP_BITADVANCE() \ +{ \ + currBits = *data++; \ + bitIndex -= 32; \ + if (bitIndex != 0) \ + { \ + sCurrState += (currBits & ((1u << bitIndex) - 1)) << (currK - bitIndex); \ + } \ +} +// Inner loop of tANS decoding for Lengths and Offset data for decompression instructions, uses u8 data sizes +// Basic process for decoding a tANS encoded value is to read the current symbol from the decoding table, then calculate the next state +// from the y and k values for the current state and add the value read from the next k bits in the bitstream +ARM_FUNC __attribute__((noinline, no_reorder)) __attribute__((optimize("-O3"))) static void DecodeLOtANSLoop(const u32 *data, u32 *ykTable, u8 *resultVec, u8 *resultVecEnd) +{ + u32 currBits = *data++; + u32 bitIndex = sBitIndex; + u16 *resultVec_u16 = (u16 *) resultVec; + + do + { + u32 currK; + u32 symbol = 0; + + { + LOT_LOOP_MAIN(0); + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + LOT_LOOP_MAIN(1); + LOT_LOOP_MAIN(2); + LOT_LOOP_MAIN(3); + + goto LOOP_STORE; + } + } + { + LOT_LOOP_MAIN(1); + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + LOT_LOOP_MAIN(2); + LOT_LOOP_MAIN(3); + + goto LOOP_STORE; + } + } + { + LOT_LOOP_MAIN(2); + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + LOT_LOOP_MAIN(3); + + goto LOOP_STORE; + } + } + { + LOT_LOOP_MAIN(3); + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + *resultVec_u16++ = symbol; + if (resultVec_u16 >= (u16 *) resultVecEnd) + break; + + symbol = 0; + + LOT_LOOP_MAIN(0); + LOT_LOOP_MAIN(1); + LOT_LOOP_MAIN(2); + LOT_LOOP_MAIN(3); + } + } + +LOOP_STORE: + *resultVec_u16++ = symbol; + } while (resultVec_u16 < (u16 *) resultVecEnd); + + sBitIndex = bitIndex; + sDataPtr = data - 1; +} + +// Dark Egg magic +ARM_FUNC __attribute__((no_reorder)) static void SwitchToArmCallLOtANS(const u32 *data, u32 *ykTable, void *resultVec, void *resultVecEnd, void (*decodeFunction)(const u32 *data, u32 *ykTable, void *resultVec, void *resultVecEnd)) +{ + decodeFunction(data, ykTable, resultVec, resultVecEnd); +} + +// Function that decodes tANS encoded LO data, resulting data is u8 values +static void DecodeLOtANS(const u32 *data, const u32 *pFreqs, u8 *resultVec, u32 count) +{ + BuildDecompressionTable(pFreqs, sWorkingYkTable); + + // We want to store in packs of 2, so count needs to be divisible by 2 + u32 remainingCount = count % 2; + + u32 funcBuffer[400]; + + CopyFuncToIwram(funcBuffer, DecodeLOtANSLoop, SwitchToArmCallLOtANS); + SwitchToArmCallLOtANS(data, sWorkingYkTable, resultVec, &resultVec[count - remainingCount], (void *) funcBuffer); + + if (remainingCount) + { + u32 currBits = *sDataPtr; + u32 symbol = 0; + for (u32 currNibble = 0; currNibble < 2; currNibble++) + { + u32 ykVals = sWorkingYkTable[sCurrState]; + symbol |= TABLE_READ_SYMBOL(ykVals) << (currNibble*4); + u32 currK = TABLE_READ_K(ykVals); + sCurrState = TABLE_READ_Y(ykVals); + sCurrState += (currBits >> sBitIndex) & TABLE_READ_MASK(ykVals); + sBitIndex += currK; + if (sBitIndex >= 32) + { + currBits = *(++sDataPtr); + sBitIndex -= 32; + if (sBitIndex != 0) + { + sCurrState += (currBits & ((1u << sBitIndex) - 1)) << (currK - sBitIndex); + } + } + } + resultVec[count - remainingCount] = symbol; + } +} + +ARM_FUNC __attribute__((noinline, no_reorder)) __attribute__((optimize("-O3"))) static void DecodeSymtANSLoop(const u32 *data, u32 *ykTable, u16 *resultVec, u16 *resultVecEnd) +{ + u32 currBits = *data++; + u32 bitIndex = sBitIndex; + + do + { + u32 symbol = 0; + for (u32 currNibble = 0; currNibble < 4; currNibble++) + { + u32 ykVals = ykTable[sCurrState]; + symbol |= TABLE_READ_SYMBOL(ykVals) << (currNibble*4); + u32 currK = TABLE_READ_K(ykVals); + sCurrState = TABLE_READ_Y(ykVals); + sCurrState += (currBits >> bitIndex) & TABLE_READ_MASK(ykVals); + bitIndex += currK; + if (bitIndex >= 32) + { + currBits = *data++; + bitIndex -= 32; + if (bitIndex != 0) + { + sCurrState += (currBits & ((1u << bitIndex) - 1)) << (currK - bitIndex); + } + } + } + *resultVec++ = symbol; + } while (resultVec < resultVecEnd); + + sBitIndex = bitIndex; + sDataPtr = data - 1; +} + +ARM_FUNC __attribute__((no_reorder)) static void SwitchToArmCallDecodeSymtANS(const u32 *data, u32 *ykTable, u16 *resultVec, u16 *resultVecEnd, void (*decodeFunction)(const u32 *data, u32 *ykTable, u16 *resultVec, u16 *resultVecEnd)) +{ + decodeFunction(data, ykTable, resultVec, resultVecEnd); +} + +static void DecodeSymtANS(const u32 *data, const u32 *pFreqs, u16 *resultVec, u32 count) +{ + BuildDecompressionTable(pFreqs, sWorkingYkTable); + + u32 funcBuffer[300]; + CopyFuncToIwram(funcBuffer, DecodeSymtANSLoop, SwitchToArmCallDecodeSymtANS); + SwitchToArmCallDecodeSymtANS(data, sWorkingYkTable, resultVec, &resultVec[count], (void *) funcBuffer); +} + +#define ANS_LOOP_MAIN(nibble) \ +{ \ + u32 ykVals = ykTable[sCurrState]; \ + currK = TABLE_READ_K(ykVals); \ + currSymbol = (currSymbol + TABLE_READ_SYMBOL(ykVals)) & 0xf; \ + symbol |= currSymbol << (nibble*4); \ + sCurrState = TABLE_READ_Y(ykVals); \ + sCurrState += ((currBits >> bitIndex) & TABLE_READ_MASK(ykVals)); \ + bitIndex += currK; \ +} + +// Inner loop of tANS decoding for delta encoded symbol data, uses u16 data size +// Basic process for decoding a tANS encoded value is to read the current symbol from the decoding table, then calculate the next state +// from the y and k values for the current state and add the value read from the next k bits in the bitstream +ARM_FUNC __attribute__((noinline, no_reorder)) __attribute__((optimize("-O3"))) u32 DecodeSymDeltatANSLoop(const u32 *data, u32 *ykTable, u16 *resultVec, u16 *resultVecEnd) +{ + u32 currBits = *data++; + u32 currSymbol = 0; + u32 bitIndex = sBitIndex; + u32 * resultVec_32 = (u32*)(resultVec); // Since we're doing 2 symbols at one time we store as word which is faster than storing two halfwords. + + do + { + u32 symbol = 0; + u32 currK; + + { + ANS_LOOP_MAIN(0); + + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(1); + ANS_LOOP_MAIN(2); + ANS_LOOP_MAIN(3); + ANS_LOOP_MAIN(4); + + goto NIBBLE_5; + } + } + { + ANS_LOOP_MAIN(1); + + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(2); + ANS_LOOP_MAIN(3); + ANS_LOOP_MAIN(4); + ANS_LOOP_MAIN(5); + + goto NIBBLE_6; + } + } + { + ANS_LOOP_MAIN(2); + + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(3); + ANS_LOOP_MAIN(4); + ANS_LOOP_MAIN(5); + ANS_LOOP_MAIN(6); + + goto NIBBLE_7; + } + } + { + ANS_LOOP_MAIN(3); + + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(4); + ANS_LOOP_MAIN(5); + ANS_LOOP_MAIN(6); + ANS_LOOP_MAIN(7); + + goto LOOP_STORE; + } + } + NIBBLE_4: + { + ANS_LOOP_MAIN(4); + + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(5); + ANS_LOOP_MAIN(6); + ANS_LOOP_MAIN(7); + + goto LOOP_STORE; + } + } + NIBBLE_5: + { + ANS_LOOP_MAIN(5); + + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(6); + ANS_LOOP_MAIN(7); + + goto LOOP_STORE; + } + } + NIBBLE_6: + { + ANS_LOOP_MAIN(6); + + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(7); + + goto LOOP_STORE; + } + } + NIBBLE_7: + { + ANS_LOOP_MAIN(7); + + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + *resultVec_32++ = (symbol); + if (resultVec_32 >= (u32 *) resultVecEnd) + break; + + symbol = 0; + + ANS_LOOP_MAIN(0); + ANS_LOOP_MAIN(1); + ANS_LOOP_MAIN(2); + ANS_LOOP_MAIN(3); + + goto NIBBLE_4; + } + } + + LOOP_STORE: + *resultVec_32++ = (symbol); + + } while (resultVec_32 < (u32 *) resultVecEnd); + sBitIndex = bitIndex; + sDataPtr = data - 1; + return currSymbol; +} + +// Dark Egg magic +ARM_FUNC __attribute__((no_reorder)) static u32 SwitchToArmCallSymDeltaANS(const u32 *data, u32 *ykTable, u16 *resultVec, u16 *resultVecEnd, u32 (*decodeFunction)(const u32 *data, u32 *ykTable, u16 *resultVec, u16 *resultVecEnd)) +{ + return decodeFunction(data, ykTable, resultVec, resultVecEnd); +} + +static void DecodeSymDeltatANS(const u32 *data, const u32 *pFreqs, u16 *resultVec, u32 count) +{ + BuildDecompressionTable(pFreqs, sWorkingYkTable); + + // We want to store in packs of 2, so count needs to be divisible by 2 + u32 remainingCount = count % 2; + + u32 funcBuffer[450]; + CopyFuncToIwram(funcBuffer, DecodeSymDeltatANSLoop, SwitchToArmCallSymDeltaANS); + u32 currSymbol = SwitchToArmCallSymDeltaANS(data, sWorkingYkTable, resultVec, &resultVec[count - remainingCount], (void *) funcBuffer); + + if (remainingCount) + { + u32 currK; + u32 *ykTable = sWorkingYkTable; + const u32 *data = sDataPtr; + u32 currBits = *sDataPtr; + u32 bitIndex = sBitIndex; + u32 symbol = 0; + + ANS_LOOP_MAIN(0); + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(1); + ANS_LOOP_MAIN(2); + ANS_LOOP_MAIN(3); + + goto LOOP_STORE; + } + + ANS_LOOP_MAIN(1); + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(2); + ANS_LOOP_MAIN(3); + + goto LOOP_STORE; + } + + ANS_LOOP_MAIN(2); + if (bitIndex >= 32) + { + LOOP_BITADVANCE(); + + ANS_LOOP_MAIN(3); + + goto LOOP_STORE; + } + + ANS_LOOP_MAIN(3); + + LOOP_STORE: + resultVec[count - remainingCount] = symbol; + sBitIndex = bitIndex; + } +} + +static inline void Fill16(u16 value, void *_dst, u32 size) +{ + u16 *dst = _dst; + for (u32 i = 0; i < size; i++) { + dst[i] = value; + } +} + +static inline void Copy16(const void *_src, void *_dst, u32 size) +{ + const u16 *src = _src; + u16 *dst = _dst; + for (u32 i = 0; i < size; i++) { + dst[i] = src[i]; + } +} + +// Function to decode the instructions into the actual decompressed data +// Basic process: +// Read length from the loVec, 1 or 2 bytes as indicated by the last bit in the first byte +// Read offset from the loVec, 1 or 2 bytes as indicated by the last bit in the first byte +// If length is not 0 and offset is not 1: +// Insert the current value from the Symbol vector into current result position and advance symbol vector by 1 +// Copy values from values back in the result vector +// If length is not 0 and offser is 1: +// Insert the current value from the Symbol vector into current result position times, then advance symbol vector by 1 +// If length is 0: +// Insert number of symbols from the symbol vector into the result vector and advance the symbol vector position by +ARM_FUNC __attribute__((noinline, no_reorder)) __attribute__((optimize("-O3"))) static void DecodeInstructions(u32 headerLoSize, u8 *loVec, u16 *symVec, u16 *dest) +{ + u8 *loVecEnd = loVec + headerLoSize; + do + { + u32 currOffset, currLength; + + if (loVec[0] & CONTINUE_BIT) + { + currLength = (loVec[0] & FIRST_LO_MASK) | (loVec[1] << 7); + currOffset = loVec[2] & FIRST_LO_MASK; + if (loVec[2] & CONTINUE_BIT) + { + currOffset |= loVec[3] << 7; + loVec += 4; + } + else + { + loVec += 3; + } + } + else + { + currLength = loVec[0] & FIRST_LO_MASK; + currOffset = loVec[1] & FIRST_LO_MASK; + + if (loVec[1] & CONTINUE_BIT) + { + currOffset |= (loVec[2] << 7); + loVec += 3; + } + else + { + loVec += 2; + } + } + + if (currLength != 0) + { + u16 symVecVal = *symVec; + *dest++ = *symVec++; + if (currOffset == 1) + { + Fill16(symVecVal, dest, currLength); + dest += currLength; + } + else + { + // Copy16 is slower in this case. + u16 *from = dest - currOffset; + u16 *to = dest + currLength; + do { + *dest++ = *from++; + } while (dest != to); + } + } + else + { + Copy16(symVec, dest, currOffset); + dest += currOffset; + symVec += currOffset; + } + } while (loVec < loVecEnd); +} + +// Dark Egg magic +ARM_FUNC __attribute__((no_reorder)) static void SwitchToArmCallDecodeInstructions(u32 headerLoSize, u8 *loVec, u16 *symVec, void *dest, void (*decodeFunction)(u32 headerLoSize, u8 *loVec, u16 *symVec, void *dest)) +{ + decodeFunction(headerLoSize, loVec, symVec, dest); +} + +// Dark Egg magic +static void DecodeInstructionsIwram(u32 headerLoSize, u8 *loVec, u16 *symVec, void *dest) +{ + u32 funcBuffer[350]; + + CopyFuncToIwram(funcBuffer, DecodeInstructions, SwitchToArmCallDecodeInstructions); + SwitchToArmCallDecodeInstructions(headerLoSize, loVec, symVec, dest, (void *) funcBuffer); +} + +// Entrance point for smol compressed data +void SmolDecompressData(const struct SmolHeader *header, const u32 *data, void *dest) +{ + // This is apparently needed due to Game Freak sending bullshit down the decompression pipeline + if (header->loSize == 0 || header->symSize == 0) + return; + const u8 *leftoverPos = (u8 *)data; + + sCurrState = header->initialState; + + u32 headerLoSize = header->loSize; + u32 headerSymSize = header->symSize; + u32 alignedLoSize = header->loSize % 2 == 1 ? headerLoSize + 1 : headerLoSize; + u32 alignedSymSize = header->symSize % 2 == 1 ? headerSymSize + 1 : headerSymSize; + // Everything needs to be aligned. + void *memoryAlloced = Alloc((alignedSymSize*2) + alignedLoSize); + u16 *symVec = memoryAlloced; + u8 *loVec = memoryAlloced + alignedSymSize*2; + bool32 loEncoded = isModeLoEncoded(header->mode); + bool32 symEncoded = isModeSymEncoded(header->mode); + bool32 symDelta = isModeSymDelta(header->mode); + + const u32 *pLoFreqs; + const u32 *pSymFreqs; + + // Use different decoding flows depending on which mode the data is compressed with + switch (header->mode) + { + case ENCODE_LO: + pLoFreqs = &data[0]; + sDataPtr = &data[3]; + break; + case ENCODE_DELTA_SYMS: + case ENCODE_SYMS: + pSymFreqs = &data[0]; + sDataPtr = &data[3]; + break; + case ENCODE_BOTH: + case ENCODE_BOTH_DELTA_SYMS: + pLoFreqs = &data[0]; + pSymFreqs = &data[3]; + sDataPtr = &data[6]; + break; + } + + sBitIndex = 0; + // Decode tANS encoded LO data, mode 3, 4 and 5 + if (loEncoded) + { + DecodeLOtANS(sDataPtr, pLoFreqs, loVec, headerLoSize); + leftoverPos += 12; + } + // Decode tANS encoded symbol data, mode 1, 2, 4 and 5 + if (symEncoded) + { + // Symbols are delta encoded, mode 2 and 5 + if (symDelta) + DecodeSymDeltatANS(sDataPtr, pSymFreqs, symVec, headerSymSize); + // Symbols are not delta encoded, mode 1 and 4 + else + DecodeSymtANS(sDataPtr, pSymFreqs, symVec, headerSymSize); + leftoverPos += 12; + } + + // If not both of lo and sym data are tANS encoded, data that isn't entropy encoded exists + // This is stored after the 32-bit aligned bitstream + if (loEncoded || symEncoded) + leftoverPos += 4*header->bitstreamSize; + + // Copy the not entropy encoded symbol data to the symbol buffer + // Symbol data is u16 aligned + if (symEncoded == FALSE) + { + DmaCopy16(3, leftoverPos, symVec, headerSymSize*2); + leftoverPos += headerSymSize*2; + } + + // Copy the not entropy encoded lo data to the lo buffer + // Despite the individual lo values being u8 aligned, the entire vector for the u8 values is u16 aligned + if (loEncoded == FALSE) + { + DmaCopy16(3, leftoverPos, loVec, alignedLoSize); + } + + // Actually decode the final data from loVec and symVec + DecodeInstructionsIwram(headerLoSize, loVec, symVec, dest); + + Free(memoryAlloced); +} + +// Helper functions for determining modes +bool32 isModeLoEncoded(enum CompressionMode mode) +{ + if (mode == ENCODE_LO + || mode == ENCODE_BOTH + || mode == ENCODE_BOTH_DELTA_SYMS) + return TRUE; + return FALSE; +} + +bool32 isModeSymEncoded(enum CompressionMode mode) +{ + if (mode == ENCODE_SYMS + || mode == ENCODE_DELTA_SYMS + || mode == ENCODE_BOTH + || mode == ENCODE_BOTH_DELTA_SYMS) + return TRUE; + return FALSE; +} + +bool32 isModeSymDelta(enum CompressionMode mode) +{ + if (mode == ENCODE_DELTA_SYMS + || mode == ENCODE_BOTH_DELTA_SYMS) + return TRUE; + return FALSE; +} + void LoadSpecialPokePic(void *dest, s32 species, u32 personality, bool8 isFrontPic) { species = SanitizeSpeciesId(species); @@ -132,25 +1053,25 @@ void LoadSpecialPokePic(void *dest, s32 species, u32 personality, bool8 isFrontP { #if P_GENDER_DIFFERENCES if (gSpeciesInfo[species].frontPicFemale != NULL && IsPersonalityFemale(species, personality)) - LZ77UnCompWram(gSpeciesInfo[species].frontPicFemale, dest); + DecompressDataWithHeaderWram(gSpeciesInfo[species].frontPicFemale, dest); else #endif if (gSpeciesInfo[species].frontPic != NULL) - LZ77UnCompWram(gSpeciesInfo[species].frontPic, dest); + DecompressDataWithHeaderWram(gSpeciesInfo[species].frontPic, dest); else - LZ77UnCompWram(gSpeciesInfo[SPECIES_NONE].frontPic, dest); + DecompressDataWithHeaderWram(gSpeciesInfo[SPECIES_NONE].frontPic, dest); } else { #if P_GENDER_DIFFERENCES if (gSpeciesInfo[species].backPicFemale != NULL && IsPersonalityFemale(species, personality)) - LZ77UnCompWram(gSpeciesInfo[species].backPicFemale, dest); + DecompressDataWithHeaderWram(gSpeciesInfo[species].backPicFemale, dest); else #endif if (gSpeciesInfo[species].backPic != NULL) - LZ77UnCompWram(gSpeciesInfo[species].backPic, dest); + DecompressDataWithHeaderWram(gSpeciesInfo[species].backPic, dest); else - LZ77UnCompWram(gSpeciesInfo[SPECIES_NONE].backPic, dest); + DecompressDataWithHeaderWram(gSpeciesInfo[SPECIES_NONE].backPic, dest); } if (species == SPECIES_SPINDA && isFrontPic) @@ -160,9 +1081,9 @@ void LoadSpecialPokePic(void *dest, s32 species, u32 personality, bool8 isFrontP } } -void Unused_LZDecompressWramIndirect(const void **src, void *dest) +void Unused_DecompressDataWithHeaderWramIndirect(const void **src, void *dest) { - LZ77UnCompWram(*src, dest); + DecompressDataWithHeaderWram(*src, dest); } static void UNUSED StitchObjectsOn8x8Canvas(s32 object_size, s32 object_count, u8 *src_tiles, u8 *dest_tiles) @@ -316,8 +1237,14 @@ static void UNUSED StitchObjectsOn8x8Canvas(s32 object_size, s32 object_count, u u32 GetDecompressedDataSize(const u32 *ptr) { - const u8 *ptr8 = (const u8 *)ptr; - return (ptr8[3] << 16) | (ptr8[2] << 8) | (ptr8[1]); + union CompressionHeader *header = (union CompressionHeader *)ptr; + switch (header->smol.mode) + { + case MODE_LZ77: + return header->lz77.size; + default: + return header->smol.imageSize*SMOL_IMAGE_SIZE_MULTIPLIER; + } } bool8 LoadCompressedSpriteSheetUsingHeap(const struct CompressedSpriteSheet *src) @@ -325,8 +1252,8 @@ bool8 LoadCompressedSpriteSheetUsingHeap(const struct CompressedSpriteSheet *src struct SpriteSheet dest; void *buffer; - buffer = AllocZeroed(src->data[0] >> 8); - LZ77UnCompWram(src->data, buffer); + buffer = AllocZeroed(GetDecompressedDataSize(&src->data[0])); + DecompressDataWithHeaderWram(src->data, buffer); dest.data = buffer; dest.size = src->size; @@ -342,8 +1269,8 @@ bool8 LoadCompressedSpritePaletteUsingHeap(const struct CompressedSpritePalette struct SpritePalette dest; void *buffer; - buffer = AllocZeroed(src->data[0] >> 8); - LZ77UnCompWram(src->data, buffer); + buffer = AllocZeroed(GetDecompressedDataSize(&src->data[0])); + DecompressDataWithHeaderWram(src->data, buffer); dest.data = buffer; dest.tag = src->tag; diff --git a/src/decompress_asm.s b/src/decompress_asm.s new file mode 100644 index 000000000000..eeb7563ecd48 --- /dev/null +++ b/src/decompress_asm.s @@ -0,0 +1,20 @@ + .syntax unified + + .arm + .section .iwram.code + .align 2 + +.global FastUnsafeCopy32 +.type FastUnsafeCopy32, %function + + @ Word aligned, 32-byte copy + @ This function WILL overwrite your buffer, so make sure it is at least 32 bytes larger than the desired size. +FastUnsafeCopy32: + push {r4-r10} +.Lloop_32: + ldmia r1!, {r3-r10} + stmia r0!, {r3-r10} + subs r2, r2, #32 + bgt .Lloop_32 + pop {r4-r10} + bx lr diff --git a/src/decoration.c b/src/decoration.c index 2b8973c8151c..30e0854e2f04 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -2073,7 +2073,7 @@ static u8 AddDecorationIconObjectFromIconTable(u16 tilesTag, u16 paletteTag, u8 if (!AllocItemIconTemporaryBuffers()) return MAX_SPRITES; - LZDecompressWram(GetDecorationIconPicOrPalette(decor, 0), gItemIconDecompressionBuffer); + DecompressDataWithHeaderWram(GetDecorationIconPicOrPalette(decor, 0), gItemIconDecompressionBuffer); CopyItemIconPicTo4x4Buffer(gItemIconDecompressionBuffer, gItemIcon4x4Buffer); sheet.data = gItemIcon4x4Buffer; sheet.size = 0x200; diff --git a/src/dexnav.c b/src/dexnav.c index 61b7b78ba0e4..3d31683c865c 100644 --- a/src/dexnav.c +++ b/src/dexnav.c @@ -1648,7 +1648,7 @@ static bool8 DexNav_LoadGraphics(void) case 1: if (FreeTempTileDataBuffersIfPossible() != TRUE) { - LZDecompressWram(sDexNavGuiTilemap, sBg1TilemapBuffer); + DecompressDataWithHeaderWram(sDexNavGuiTilemap, sBg1TilemapBuffer); sDexNavUiDataPtr->state++; } break; diff --git a/src/diploma.c b/src/diploma.c index 2a188674503c..50284f7cc606 100644 --- a/src/diploma.c +++ b/src/diploma.c @@ -80,7 +80,7 @@ void CB2_ShowDiploma(void) DecompressAndCopyTileDataToVram(1, &sDiplomaTiles, 0, 0, 0); while (FreeTempTileDataBuffersIfPossible()) ; - LZDecompressWram(sDiplomaTilemap, sDiplomaTilemapPtr); + DecompressDataWithHeaderWram(sDiplomaTilemap, sDiplomaTilemapPtr); CopyBgTilemapBufferToVram(1); DisplayDiplomaText(); BlendPalettes(PALETTES_ALL, 16, RGB_BLACK); diff --git a/src/dodrio_berry_picking.c b/src/dodrio_berry_picking.c index ce1877c6cd27..5183ee85722d 100644 --- a/src/dodrio_berry_picking.c +++ b/src/dodrio_berry_picking.c @@ -3830,7 +3830,7 @@ static void LoadDodrioGfx(void) struct SpritePalette normal = {sDodrioNormal_Pal, PALTAG_DODRIO_NORMAL}; struct SpritePalette shiny = {sDodrioShiny_Pal, PALTAG_DODRIO_SHINY}; - LZ77UnCompWram(sDodrio_Gfx, ptr); + DecompressDataWithHeaderWram(sDodrio_Gfx, ptr); if (ptr) { struct SpriteSheet sheet = {ptr, 0x3000, GFXTAG_DODRIO}; @@ -4013,7 +4013,7 @@ static void CreateStatusBarSprites(void) void *ptr = AllocZeroed(0x180); struct SpritePalette pal = {sStatus_Pal, PALTAG_STATUS}; - LZ77UnCompWram(sStatus_Gfx, ptr); + DecompressDataWithHeaderWram(sStatus_Gfx, ptr); // This check should be one line up. if (ptr) { @@ -4155,7 +4155,7 @@ static void LoadBerryGfx(void) void *ptr = AllocZeroed(0x480); struct SpritePalette pal = {sBerries_Pal, PALTAG_BERRIES}; - LZ77UnCompWram(sBerries_Gfx, ptr); + DecompressDataWithHeaderWram(sBerries_Gfx, ptr); if (ptr) { struct SpriteSheet sheet = {ptr, 0x480, GFXTAG_BERRIES}; @@ -4303,7 +4303,7 @@ static void CreateCloudSprites(void) void *ptr = AllocZeroed(0x400); struct SpritePalette pal = {sCloud_Pal, PALTAG_CLOUD}; - LZ77UnCompWram(sCloud_Gfx, ptr); + DecompressDataWithHeaderWram(sCloud_Gfx, ptr); if (ptr) { struct SpriteSheet sheet = {ptr, 0x400, GFXTAG_CLOUD}; diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 80423aa3169e..8a3645e75431 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2061,7 +2061,7 @@ static u8 LoadDynamicFollowerPalette(u16 species, u8 form, bool32 shiny) if (IsLZ77Data(spritePalette.data, PLTT_SIZE_4BPP, PLTT_SIZE_4BPP)) { // IsLZ77Data guarantees word-alignment, so casting this is safe - LZ77UnCompWram((u32*)spritePalette.data, gDecompressionBuffer); + DecompressDataWithHeaderWram((u32*)spritePalette.data, gDecompressionBuffer); spritePalette.data = (void*)gDecompressionBuffer; } paletteNum = LoadSpritePalette(&spritePalette); diff --git a/src/expansion_intro.c b/src/expansion_intro.c index e37ea4b2e679..0b9754ee5ecd 100644 --- a/src/expansion_intro.c +++ b/src/expansion_intro.c @@ -308,10 +308,10 @@ static void ExpansionIntro_InitBgs(void) static void ExpansionIntro_LoadGraphics(void) { - LZ77UnCompVram(sBgTiles_PoweredBy, (void*) BG_CHAR_ADDR(sBgTemplates_RhhCopyrightScreen[EXPANSION_INTRO_BG3].charBaseIndex)); - LZ77UnCompVram(sBgMap_PoweredBy, (u16*) BG_SCREEN_ADDR(sBgTemplates_RhhCopyrightScreen[EXPANSION_INTRO_BG3].mapBaseIndex)); - LZ77UnCompVram(sBgTiles_RhhCredits, (void*) BG_CHAR_ADDR(sBgTemplates_RhhCopyrightScreen[EXPANSION_INTRO_BG2].charBaseIndex)); - LZ77UnCompVram(sBgMap_RhhCredits, (u16*) BG_SCREEN_ADDR(sBgTemplates_RhhCopyrightScreen[EXPANSION_INTRO_BG2].mapBaseIndex)); + DecompressDataWithHeaderVram(sBgTiles_PoweredBy, (void*) BG_CHAR_ADDR(sBgTemplates_RhhCopyrightScreen[EXPANSION_INTRO_BG3].charBaseIndex)); + DecompressDataWithHeaderVram(sBgMap_PoweredBy, (u16*) BG_SCREEN_ADDR(sBgTemplates_RhhCopyrightScreen[EXPANSION_INTRO_BG3].mapBaseIndex)); + DecompressDataWithHeaderVram(sBgTiles_RhhCredits, (void*) BG_CHAR_ADDR(sBgTemplates_RhhCopyrightScreen[EXPANSION_INTRO_BG2].charBaseIndex)); + DecompressDataWithHeaderVram(sBgMap_RhhCredits, (u16*) BG_SCREEN_ADDR(sBgTemplates_RhhCopyrightScreen[EXPANSION_INTRO_BG2].mapBaseIndex)); LoadCompressedPalette(sBgPal_Credits, 0x00, 0x60); LoadCompressedSpriteSheet(&sSpriteSheet_DizzyEgg); diff --git a/src/field_effect.c b/src/field_effect.c index 45631be6a348..1c1fa03db51c 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -911,7 +911,7 @@ u8 CreateTrainerSprite(u8 trainerSpriteID, s16 x, s16 y, u8 subpriority, u8 *buf static void UNUSED LoadTrainerGfx_TrainerCard(u8 gender, u16 palOffset, u8 *dest) { - LZDecompressVram(gTrainerSprites[gender].frontPic.data, dest); + DecompressDataWithHeaderVram(gTrainerSprites[gender].frontPic.data, dest); LoadCompressedPalette(gTrainerSprites[gender].palette.data, palOffset, PLTT_SIZE_4BPP); } diff --git a/src/fldeff_flash.c b/src/fldeff_flash.c index 1e2b9a95fc72..199e907e8fd7 100644 --- a/src/fldeff_flash.c +++ b/src/fldeff_flash.c @@ -216,8 +216,8 @@ static void Task_ExitCaveTransition1(u8 taskId) static void Task_ExitCaveTransition2(u8 taskId) { SetGpuReg(REG_OFFSET_DISPCNT, 0); - LZ77UnCompVram(sCaveTransitionTiles, (void *)(VRAM + 0xC000)); - LZ77UnCompVram(sCaveTransitionTilemap, (void *)(VRAM + 0xF800)); + DecompressDataWithHeaderVram(sCaveTransitionTiles, (void *)(VRAM + 0xC000)); + DecompressDataWithHeaderVram(sCaveTransitionTilemap, (void *)(VRAM + 0xF800)); LoadPalette(sCaveTransitionPalette_White, BG_PLTT_ID(14), PLTT_SIZE_4BPP); LoadPalette(&sCaveTransitionPalette_Enter[8], BG_PLTT_ID(14), PLTT_SIZEOF(8)); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 @@ -301,8 +301,8 @@ static void Task_EnterCaveTransition1(u8 taskId) static void Task_EnterCaveTransition2(u8 taskId) { SetGpuReg(REG_OFFSET_DISPCNT, 0); - LZ77UnCompVram(sCaveTransitionTiles, (void *)(VRAM + 0xC000)); - LZ77UnCompVram(sCaveTransitionTilemap, (void *)(VRAM + 0xF800)); + DecompressDataWithHeaderVram(sCaveTransitionTiles, (void *)(VRAM + 0xC000)); + DecompressDataWithHeaderVram(sCaveTransitionTilemap, (void *)(VRAM + 0xF800)); SetGpuReg(REG_OFFSET_BLDCNT, 0); SetGpuReg(REG_OFFSET_BLDALPHA, 0); SetGpuReg(REG_OFFSET_BLDY, 0); diff --git a/src/intro.c b/src/intro.c index 88cb1f820e42..b04084456236 100644 --- a/src/intro.c +++ b/src/intro.c @@ -1059,8 +1059,8 @@ static void MainCB2_EndIntro(void) static void LoadCopyrightGraphics(u16 tilesetAddress, u16 tilemapAddress, u16 paletteOffset) { - LZ77UnCompVram(gIntroCopyright_Gfx, (void *)(VRAM + tilesetAddress)); - LZ77UnCompVram(gIntroCopyright_Tilemap, (void *)(VRAM + tilemapAddress)); + DecompressDataWithHeaderVram(gIntroCopyright_Gfx, (void *)(VRAM + tilesetAddress)); + DecompressDataWithHeaderVram(gIntroCopyright_Tilemap, (void *)(VRAM + tilemapAddress)); LoadPalette(gIntroCopyright_Pal, paletteOffset, PLTT_SIZE_4BPP); } @@ -1184,14 +1184,14 @@ void Task_Scene1_Load(u8 taskId) SetGpuReg(REG_OFFSET_BG2VOFS, 80); SetGpuReg(REG_OFFSET_BG1VOFS, 24); SetGpuReg(REG_OFFSET_BG0VOFS, 40); - LZ77UnCompVram(sIntro1Bg_Gfx, (void *)VRAM); - LZ77UnCompVram(sIntro1Bg0_Tilemap, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(sIntro1Bg_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(sIntro1Bg0_Tilemap, (void *)(BG_CHAR_ADDR(2))); DmaClear16(3, BG_SCREEN_ADDR(17), BG_SCREEN_SIZE); - LZ77UnCompVram(sIntro1Bg1_Tilemap, (void *)(BG_SCREEN_ADDR(18))); + DecompressDataWithHeaderVram(sIntro1Bg1_Tilemap, (void *)(BG_SCREEN_ADDR(18))); DmaClear16(3, BG_SCREEN_ADDR(19), BG_SCREEN_SIZE); - LZ77UnCompVram(sIntro1Bg2_Tilemap, (void *)(BG_SCREEN_ADDR(20))); + DecompressDataWithHeaderVram(sIntro1Bg2_Tilemap, (void *)(BG_SCREEN_ADDR(20))); DmaClear16(3, BG_SCREEN_ADDR(21), BG_SCREEN_SIZE); - LZ77UnCompVram(sIntro1Bg3_Tilemap, (void *)(BG_SCREEN_ADDR(22))); + DecompressDataWithHeaderVram(sIntro1Bg3_Tilemap, (void *)(BG_SCREEN_ADDR(22))); DmaClear16(3, BG_SCREEN_ADDR(23), BG_SCREEN_SIZE); LoadPalette(sIntro1Bg_Pal, BG_PLTT_ID(0), sizeof(sIntro1Bg_Pal)); SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(22) | BGCNT_16COLOR | BGCNT_TXT256x512); @@ -1730,8 +1730,8 @@ static void SpriteCB_Manectric(struct Sprite *sprite) static void Task_Scene3_Load(u8 taskId) { IntroResetGpuRegs(); - LZ77UnCompVram(sIntroPokeball_Gfx, (void *)VRAM); - LZ77UnCompVram(sIntroPokeball_Tilemap, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(sIntroPokeball_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(sIntroPokeball_Tilemap, (void *)(BG_CHAR_ADDR(1))); LoadPalette(sIntroPokeball_Pal, BG_PLTT_ID(0), sizeof(sIntroPokeball_Pal)); gTasks[taskId].tAlpha = 0; gTasks[taskId].tZoomDiv = 0; @@ -1785,10 +1785,10 @@ static void Task_Scene3_LoadGroudon(u8 taskId) ResetSpriteData(); FreeAllSpritePalettes(); gReservedSpritePaletteCount = 8; - LZDecompressVram(gIntroGroudon_Gfx, (void *)VRAM); - LZDecompressVram(gIntroGroudon_Tilemap, (void *)(BG_CHAR_ADDR(3))); - LZDecompressVram(gIntroLegendBg_Gfx, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(gIntroGroudonBg_Tilemap, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gIntroGroudon_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(gIntroGroudon_Tilemap, (void *)(BG_CHAR_ADDR(3))); + DecompressDataWithHeaderVram(gIntroLegendBg_Gfx, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gIntroGroudonBg_Tilemap, (void *)(BG_SCREEN_ADDR(28))); LoadCompressedSpriteSheetUsingHeap(&gBattleAnimPicTable[GET_TRUE_SPRITE_INDEX(ANIM_TAG_ROCKS)]); LoadCompressedSpritePaletteUsingHeap(&gBattleAnimPaletteTable[GET_TRUE_SPRITE_INDEX(ANIM_TAG_ROCKS)]); CpuCopy16(gIntro3Bg_Pal, gPlttBufferUnfaded, sizeof(gIntro3Bg_Pal)); @@ -2060,9 +2060,9 @@ static void SpriteCB_GroudonRocks(struct Sprite *sprite) static void Task_Scene3_LoadKyogre(u8 taskId) { ResetSpriteData(); - LZDecompressVram(gIntroKyogre_Gfx, (void *)VRAM); - LZDecompressVram(gIntroKyogre_Tilemap, (void *)(BG_CHAR_ADDR(3))); - LZDecompressVram(gIntroKyogreBg_Tilemap, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gIntroKyogre_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(gIntroKyogre_Tilemap, (void *)(BG_CHAR_ADDR(3))); + DecompressDataWithHeaderVram(gIntroKyogreBg_Tilemap, (void *)(BG_SCREEN_ADDR(28))); LoadCompressedSpriteSheet(sSpriteSheet_Bubbles); LoadSpritePalette(sSpritePalette_Bubbles); BeginNormalPaletteFade(PALETTES_ALL & ~1, 0, 16, 0, RGB_WHITEALPHA); @@ -2368,16 +2368,16 @@ static void Task_Scene3_LoadClouds1(u8 taskId) SetGpuReg(REG_OFFSET_BG1VOFS, 0); SetGpuReg(REG_OFFSET_BG2HOFS, 0); SetGpuReg(REG_OFFSET_BG2VOFS, 0); - LZDecompressVram(gIntroClouds_Gfx, (void *)VRAM); - LZDecompressVram(gIntroClouds_Gfx, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(gIntroCloudsSun_Tilemap, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gIntroClouds_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(gIntroClouds_Gfx, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gIntroCloudsSun_Tilemap, (void *)(BG_SCREEN_ADDR(28))); gTasks[taskId].func = Task_Scene3_LoadClouds2; } static void Task_Scene3_LoadClouds2(u8 taskId) { - LZDecompressVram(gIntroCloudsLeft_Tilemap, (void *)(BG_CHAR_ADDR(3))); - LZDecompressVram(gIntroCloudsRight_Tilemap, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gIntroCloudsLeft_Tilemap, (void *)(BG_CHAR_ADDR(3))); + DecompressDataWithHeaderVram(gIntroCloudsRight_Tilemap, (void *)(BG_SCREEN_ADDR(26))); gTasks[taskId].func = Task_Scene3_InitClouds; } @@ -2435,10 +2435,10 @@ static void Task_Scene3_Clouds(u8 taskId) static void Task_Scene3_LoadLightning(u8 taskId) { - LZDecompressVram(gIntroRayquaza_Tilemap, (void *)(BG_SCREEN_ADDR(28))); - LZDecompressVram(gIntroRayquazaClouds_Tilemap, (void *)(BG_CHAR_ADDR(3))); - LZDecompressVram(gIntroRayquaza_Gfx, (void *)(BG_CHAR_ADDR(1))); - LZDecompressVram(gIntroRayquazaClouds_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(gIntroRayquaza_Tilemap, (void *)(BG_SCREEN_ADDR(28))); + DecompressDataWithHeaderVram(gIntroRayquazaClouds_Tilemap, (void *)(BG_CHAR_ADDR(3))); + DecompressDataWithHeaderVram(gIntroRayquaza_Gfx, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(gIntroRayquazaClouds_Gfx, (void *)VRAM); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON diff --git a/src/intro_credits_graphics.c b/src/intro_credits_graphics.c index c4b059fdd78b..3df31193040c 100644 --- a/src/intro_credits_graphics.c +++ b/src/intro_credits_graphics.c @@ -728,8 +728,8 @@ static void Task_BicycleBgAnimation(u8); void LoadIntroPart2Graphics(u8 scenery) { - LZ77UnCompVram(sGrass_Gfx, (void *)(BG_CHAR_ADDR(1))); - LZ77UnCompVram(sGrass_Tilemap, (void *)(BG_SCREEN_ADDR(15))); + DecompressDataWithHeaderVram(sGrass_Gfx, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(sGrass_Tilemap, (void *)(BG_SCREEN_ADDR(15))); LoadPalette(&sGrass_Pal, BG_PLTT_ID(15), sizeof(sGrass_Pal)); switch (scenery) { @@ -737,16 +737,16 @@ void LoadIntroPart2Graphics(u8 scenery) default: // Never reached, only called with an argument of 1 // Clouds are never used in this part of the intro - LZ77UnCompVram(sCloudsBg_Gfx, (void *)(VRAM)); - LZ77UnCompVram(sCloudsBg_Tilemap, (void *)(BG_SCREEN_ADDR(6))); + DecompressDataWithHeaderVram(sCloudsBg_Gfx, (void *)(VRAM)); + DecompressDataWithHeaderVram(sCloudsBg_Tilemap, (void *)(BG_SCREEN_ADDR(6))); LoadPalette(&sCloudsBg_Pal, BG_PLTT_ID(0), sizeof(sCloudsBg_Pal)); LoadCompressedSpriteSheet(sSpriteSheet_Clouds); LoadPalette(&sClouds_Pal, OBJ_PLTT_ID(0), sizeof(sClouds_Pal)); CreateCloudSprites(); break; case 1: - LZ77UnCompVram(sTrees_Gfx, (void *)(VRAM)); - LZ77UnCompVram(sTrees_Tilemap, (void *)(BG_SCREEN_ADDR(6))); + DecompressDataWithHeaderVram(sTrees_Gfx, (void *)(VRAM)); + DecompressDataWithHeaderVram(sTrees_Tilemap, (void *)(BG_SCREEN_ADDR(6))); LoadPalette(&sTrees_Pal, BG_PLTT_ID(0), sizeof(sTrees_Pal)); LoadCompressedSpriteSheet(sSpriteSheet_TreesSmall); LoadPalette(&sTreesSmall_Pal, OBJ_PLTT_ID(0), sizeof(sTreesSmall_Pal)); @@ -837,36 +837,36 @@ void SetIntroPart2BgCnt(u8 scenery) void LoadCreditsSceneGraphics(u8 scene) { - LZ77UnCompVram(sGrass_Gfx, (void *)(BG_CHAR_ADDR(1))); - LZ77UnCompVram(sGrass_Tilemap, (void *)(BG_SCREEN_ADDR(15))); + DecompressDataWithHeaderVram(sGrass_Gfx, (void *)(BG_CHAR_ADDR(1))); + DecompressDataWithHeaderVram(sGrass_Tilemap, (void *)(BG_SCREEN_ADDR(15))); switch (scene) { case SCENE_OCEAN_MORNING: default: LoadPalette(&sGrass_Pal, BG_PLTT_ID(15), sizeof(sGrass_Pal)); - LZ77UnCompVram(sCloudsBg_Gfx, (void *)(VRAM)); - LZ77UnCompVram(sCloudsBg_Tilemap, (void *)(BG_SCREEN_ADDR(6))); + DecompressDataWithHeaderVram(sCloudsBg_Gfx, (void *)(VRAM)); + DecompressDataWithHeaderVram(sCloudsBg_Tilemap, (void *)(BG_SCREEN_ADDR(6))); LoadPalette(&sCloudsBg_Pal, BG_PLTT_ID(0), sizeof(sCloudsBg_Pal)); LoadCompressedSpriteSheet(sSpriteSheet_Clouds); - LZ77UnCompVram(sClouds_Gfx, (void *)(OBJ_VRAM0)); + DecompressDataWithHeaderVram(sClouds_Gfx, (void *)(OBJ_VRAM0)); LoadPalette(&sClouds_Pal, OBJ_PLTT_ID(0), sizeof(sClouds_Pal)); CreateCloudSprites(); break; case SCENE_OCEAN_SUNSET: LoadPalette(&sGrassSunset_Pal, BG_PLTT_ID(15), sizeof(sGrassSunset_Pal)); - LZ77UnCompVram(sCloudsBg_Gfx, (void *)(VRAM)); - LZ77UnCompVram(sCloudsBg_Tilemap, (void *)(BG_SCREEN_ADDR(6))); + DecompressDataWithHeaderVram(sCloudsBg_Gfx, (void *)(VRAM)); + DecompressDataWithHeaderVram(sCloudsBg_Tilemap, (void *)(BG_SCREEN_ADDR(6))); LoadPalette(&sCloudsBgSunset_Pal, BG_PLTT_ID(0), sizeof(sCloudsBgSunset_Pal)); LoadCompressedSpriteSheet(sSpriteSheet_Clouds); - LZ77UnCompVram(sClouds_Gfx, (void *)(OBJ_VRAM0)); + DecompressDataWithHeaderVram(sClouds_Gfx, (void *)(OBJ_VRAM0)); LoadPalette(&sCloudsSunset_Pal, OBJ_PLTT_ID(0), sizeof(sCloudsSunset_Pal)); CreateCloudSprites(); break; case SCENE_FOREST_RIVAL_ARRIVE: case SCENE_FOREST_CATCH_RIVAL: LoadPalette(&sGrassSunset_Pal, BG_PLTT_ID(15), sizeof(sGrassSunset_Pal)); - LZ77UnCompVram(sTrees_Gfx, (void *)(VRAM)); - LZ77UnCompVram(sTrees_Tilemap, (void *)(BG_SCREEN_ADDR(6))); + DecompressDataWithHeaderVram(sTrees_Gfx, (void *)(VRAM)); + DecompressDataWithHeaderVram(sTrees_Tilemap, (void *)(BG_SCREEN_ADDR(6))); LoadPalette(&sTreesSunset_Pal, BG_PLTT_ID(0), sizeof(sTreesSunset_Pal)); LoadCompressedSpriteSheet(sSpriteSheet_TreesSmall); LoadPalette(&sTreesSunset_Pal, OBJ_PLTT_ID(0), sizeof(sTreesSunset_Pal)); @@ -874,8 +874,8 @@ void LoadCreditsSceneGraphics(u8 scene) break; case SCENE_CITY_NIGHT: LoadPalette(&sGrassNight_Pal, BG_PLTT_ID(15), sizeof(sGrassNight_Pal)); - LZ77UnCompVram(sHouses_Gfx, (void *)(VRAM)); - LZ77UnCompVram(sHouses_Tilemap, (void *)(BG_SCREEN_ADDR(6))); + DecompressDataWithHeaderVram(sHouses_Gfx, (void *)(VRAM)); + DecompressDataWithHeaderVram(sHouses_Tilemap, (void *)(BG_SCREEN_ADDR(6))); LoadPalette(&sHouses_Pal, BG_PLTT_ID(0), sizeof(sHouses_Pal)); LoadCompressedSpriteSheet(sSpriteSheet_HouseSilhouette); LoadPalette(&sHouseSilhouette_Pal, OBJ_PLTT_ID(0), sizeof(sHouseSilhouette_Pal)); diff --git a/src/item_icon.c b/src/item_icon.c index 03b56918be2f..26ebf82ecfd2 100644 --- a/src/item_icon.c +++ b/src/item_icon.c @@ -99,7 +99,7 @@ u8 AddItemIconSprite(u16 tilesTag, u16 paletteTag, u16 itemId) struct CompressedSpritePalette spritePalette; struct SpriteTemplate *spriteTemplate; - LZDecompressWram(GetItemIconPic(itemId), gItemIconDecompressionBuffer); + DecompressDataWithHeaderWram(GetItemIconPic(itemId), gItemIconDecompressionBuffer); CopyItemIconPicTo4x4Buffer(gItemIconDecompressionBuffer, gItemIcon4x4Buffer); spriteSheet.data = gItemIcon4x4Buffer; spriteSheet.size = 0x200; @@ -136,7 +136,7 @@ u8 AddCustomItemIconSprite(const struct SpriteTemplate *customSpriteTemplate, u1 struct CompressedSpritePalette spritePalette; struct SpriteTemplate *spriteTemplate; - LZDecompressWram(GetItemIconPic(itemId), gItemIconDecompressionBuffer); + DecompressDataWithHeaderWram(GetItemIconPic(itemId), gItemIconDecompressionBuffer); CopyItemIconPicTo4x4Buffer(gItemIconDecompressionBuffer, gItemIcon4x4Buffer); spriteSheet.data = gItemIcon4x4Buffer; spriteSheet.size = 0x200; diff --git a/src/item_menu.c b/src/item_menu.c index ff5d569f966f..a236c5a64352 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -827,7 +827,7 @@ static bool8 LoadBagMenu_Graphics(void) case 1: if (FreeTempTileDataBuffersIfPossible() != TRUE) { - LZDecompressWram(gBagScreen_GfxTileMap, gBagMenu->tilemapBuffer); + DecompressDataWithHeaderWram(gBagScreen_GfxTileMap, gBagMenu->tilemapBuffer); gBagMenu->graphicsLoadState++; } break; diff --git a/src/item_menu_icons.c b/src/item_menu_icons.c index 4e6339ba3096..a8c3a456759e 100644 --- a/src/item_menu_icons.c +++ b/src/item_menu_icons.c @@ -652,7 +652,7 @@ static void LoadBerryGfx(u8 berryId) pal.data = sBerryPicTable[berryId].pal; pal.tag = TAG_BERRY_PIC_PAL; LoadCompressedSpritePalette(&pal); - LZDecompressWram(sBerryPicTable[berryId].tiles, &gDecompressionBuffer[0x1000]); + DecompressDataWithHeaderWram(sBerryPicTable[berryId].tiles, &gDecompressionBuffer[0x1000]); ArrangeBerryGfx(&gDecompressionBuffer[0x1000], &gDecompressionBuffer[0]); } diff --git a/src/main_menu.c b/src/main_menu.c index bae80e543a0a..58bc4ec8d45d 100644 --- a/src/main_menu.c +++ b/src/main_menu.c @@ -1294,8 +1294,8 @@ static void Task_NewGameBirchSpeech_Init(u8 taskId) SetGpuReg(REG_OFFSET_BLDALPHA, 0); SetGpuReg(REG_OFFSET_BLDY, 0); - LZ77UnCompVram(sBirchSpeechShadowGfx, (void *)VRAM); - LZ77UnCompVram(sBirchSpeechBgMap, (void *)(BG_SCREEN_ADDR(7))); + DecompressDataWithHeaderVram(sBirchSpeechShadowGfx, (void *)VRAM); + DecompressDataWithHeaderVram(sBirchSpeechBgMap, (void *)(BG_SCREEN_ADDR(7))); LoadPalette(sBirchSpeechBgPals, BG_PLTT_ID(0), 2 * PLTT_SIZE_4BPP); LoadPalette(&sBirchSpeechBgGradientPal[8], BG_PLTT_ID(0) + 1, PLTT_SIZEOF(8)); ScanlineEffect_Stop(); @@ -1829,8 +1829,8 @@ static void CB2_NewGameBirchSpeech_ReturnFromNamingScreen(void) DmaFill32(3, 0, OAM, OAM_SIZE); DmaFill16(3, 0, PLTT, PLTT_SIZE); ResetPaletteFade(); - LZ77UnCompVram(sBirchSpeechShadowGfx, (u8 *)VRAM); - LZ77UnCompVram(sBirchSpeechBgMap, (u8 *)(BG_SCREEN_ADDR(7))); + DecompressDataWithHeaderVram(sBirchSpeechShadowGfx, (u8 *)VRAM); + DecompressDataWithHeaderVram(sBirchSpeechBgMap, (u8 *)(BG_SCREEN_ADDR(7))); LoadPalette(sBirchSpeechBgPals, BG_PLTT_ID(0), 2 * PLTT_SIZE_4BPP); LoadPalette(&sBirchSpeechBgGradientPal[1], BG_PLTT_ID(0) + 1, PLTT_SIZEOF(8)); ResetTasks(); diff --git a/src/menu.c b/src/menu.c index d9b331a8b2fd..8a46fc1a2615 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1944,17 +1944,14 @@ void task_free_buf_after_copying_tile_data_to_vram(u8 taskId) void *malloc_and_decompress(const void *src, u32 *size) { void *ptr; - u8 *sizeAsBytes = (u8 *)size; - u8 *srcAsBytes = (u8 *)src; + union CompressionHeader header; + CpuCopy32(src, &header, 8); - sizeAsBytes[0] = srcAsBytes[1]; - sizeAsBytes[1] = srcAsBytes[2]; - sizeAsBytes[2] = srcAsBytes[3]; - sizeAsBytes[3] = 0; + *size = GetDecompressedDataSize(src); ptr = Alloc(*size); if (ptr) - LZ77UnCompWram(src, ptr); + DecompressDataWithHeaderWram(src, ptr); return ptr; } diff --git a/src/menu_specialized.c b/src/menu_specialized.c index 7b6d94b5f23a..7c0ef392a462 100644 --- a/src/menu_specialized.c +++ b/src/menu_specialized.c @@ -1074,7 +1074,7 @@ void GetConditionMenuMonGfx(void *tilesDst, void *palDst, u16 boxId, u16 monId, u32 personality = GetBoxOrPartyMonData(boxId, monId, MON_DATA_PERSONALITY, NULL); LoadSpecialPokePic(tilesDst, species, personality, TRUE); - LZ77UnCompWram(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), palDst); + DecompressDataWithHeaderWram(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), palDst); } } diff --git a/src/mystery_gift_view.c b/src/mystery_gift_view.c index bc1939adf19a..de2a12e0ec28 100644 --- a/src/mystery_gift_view.c +++ b/src/mystery_gift_view.c @@ -243,7 +243,7 @@ s32 WonderCard_Enter(void) LoadPalette(GetTextWindowPalette(1), BG_PLTT_ID(2), PLTT_SIZE_4BPP); gPaletteFade.bufferTransferDisabled = TRUE; LoadPalette(sWonderCardData->gfx->pal, BG_PLTT_ID(1), PLTT_SIZE_4BPP); - LZ77UnCompWram(sWonderCardData->gfx->map, sWonderCardData->bgTilemapBuffer); + DecompressDataWithHeaderWram(sWonderCardData->gfx->map, sWonderCardData->bgTilemapBuffer); CopyRectToBgTilemapBufferRect(2, sWonderCardData->bgTilemapBuffer, 0, 0, DISPLAY_TILE_WIDTH, DISPLAY_TILE_HEIGHT, 0, 0, DISPLAY_TILE_WIDTH, DISPLAY_TILE_HEIGHT, 1, 0x008, 0); CopyBgTilemapBufferToVram(2); break; @@ -706,7 +706,7 @@ s32 WonderNews_Enter(void) LoadPalette(GetTextWindowPalette(1), BG_PLTT_ID(2), PLTT_SIZE_4BPP); gPaletteFade.bufferTransferDisabled = TRUE; LoadPalette(sWonderNewsData->gfx->pal, BG_PLTT_ID(1), PLTT_SIZE_4BPP); - LZ77UnCompWram(sWonderNewsData->gfx->map, sWonderNewsData->bgTilemapBuffer); + DecompressDataWithHeaderWram(sWonderNewsData->gfx->map, sWonderNewsData->bgTilemapBuffer); CopyRectToBgTilemapBufferRect(1, sWonderNewsData->bgTilemapBuffer, 0, 0, DISPLAY_TILE_WIDTH, 3, 0, 0, DISPLAY_TILE_WIDTH, 3, 1, 8, 0); CopyRectToBgTilemapBufferRect(3, sWonderNewsData->bgTilemapBuffer, 0, 3, DISPLAY_TILE_WIDTH, 3 + DISPLAY_TILE_HEIGHT, 0, 3, DISPLAY_TILE_WIDTH, 3 + DISPLAY_TILE_HEIGHT, 1, 8, 0); CopyBgTilemapBufferToVram(1); diff --git a/src/naming_screen.c b/src/naming_screen.c index 118d91cfb416..b775ddb933cf 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -1882,7 +1882,7 @@ static void SaveInputText(void) static void LoadGfx(void) { - LZ77UnCompWram(gNamingScreenMenu_Gfx, sNamingScreen->tileBuffer); + DecompressDataWithHeaderWram(gNamingScreenMenu_Gfx, sNamingScreen->tileBuffer); LoadBgTiles(1, sNamingScreen->tileBuffer, sizeof(sNamingScreen->tileBuffer), 0); LoadBgTiles(2, sNamingScreen->tileBuffer, sizeof(sNamingScreen->tileBuffer), 0); LoadBgTiles(3, sNamingScreen->tileBuffer, sizeof(sNamingScreen->tileBuffer), 0); diff --git a/src/palette.c b/src/palette.c index 2526479ca8df..e44b78345486 100644 --- a/src/palette.c +++ b/src/palette.c @@ -40,7 +40,7 @@ static const u8 sRoundedDownGrayscaleMap[] = { void LoadCompressedPalette(const u32 *src, u32 offset, u32 size) { - LZDecompressWram(src, gDecompressionBuffer); + DecompressDataWithHeaderWram(src, gDecompressionBuffer); CpuCopy16(gDecompressionBuffer, &gPlttBufferUnfaded[offset], size); CpuCopy16(gDecompressionBuffer, &gPlttBufferFaded[offset], size); } diff --git a/src/party_menu.c b/src/party_menu.c index bda62ba3d1fb..06ca47386a2c 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -888,7 +888,7 @@ static bool8 AllocPartyMenuBgGfx(void) case 1: if (!IsDma3ManagerBusyWithBgCopy()) { - LZDecompressWram(gPartyMenuBg_Tilemap, sPartyBgTilemapBuffer); + DecompressDataWithHeaderWram(gPartyMenuBg_Tilemap, sPartyBgTilemapBuffer); sPartyMenuInternal->data[0]++; } break; diff --git a/src/pokeball.c b/src/pokeball.c index 2b168cd7e3a5..3f273eeaff7d 100644 --- a/src/pokeball.c +++ b/src/pokeball.c @@ -1572,7 +1572,7 @@ void LoadBallGfx(u8 ballId) case BALL_REPEAT: case BALL_SAFARI: var = GetSpriteTileStartByTag(gBallSpriteSheets[ballId].tag); - LZDecompressVram(gOpenPokeballGfx, (void *)(OBJ_VRAM0 + 0x100 + var * 32)); + DecompressDataWithHeaderVram(gOpenPokeballGfx, (void *)(OBJ_VRAM0 + 0x100 + var * 32)); break; } } diff --git a/src/pokeblock.c b/src/pokeblock.c index b68fe16ce36e..d98ea4db8e00 100644 --- a/src/pokeblock.c +++ b/src/pokeblock.c @@ -653,7 +653,7 @@ static bool8 LoadPokeblockMenuGfx(void) case 1: if (FreeTempTileDataBuffersIfPossible() != TRUE) { - LZDecompressWram(gMenuPokeblock_Tilemap, sPokeblockMenu->tilemap); + DecompressDataWithHeaderWram(gMenuPokeblock_Tilemap, sPokeblockMenu->tilemap); sPokeblockMenu->gfxState++; } break; diff --git a/src/pokeblock_feed.c b/src/pokeblock_feed.c index f79f35a781d6..990e9240b7fd 100644 --- a/src/pokeblock_feed.c +++ b/src/pokeblock_feed.c @@ -697,7 +697,7 @@ static bool8 LoadMonAndSceneGfx(struct Pokemon *mon) case 7: if (FreeTempTileDataBuffersIfPossible() != TRUE) { - LZDecompressWram(gPokeblockFeedBg_Tilemap, sPokeblockFeed->tilemapBuffer); + DecompressDataWithHeaderWram(gPokeblockFeedBg_Tilemap, sPokeblockFeed->tilemapBuffer); sPokeblockFeed->loadGfxState++; } break; diff --git a/src/pokedex_area_screen.c b/src/pokedex_area_screen.c index dd45335afb05..720fd29d6a96 100644 --- a/src/pokedex_area_screen.c +++ b/src/pokedex_area_screen.c @@ -772,7 +772,7 @@ static void LoadAreaUnknownGraphics(void) .size = sizeof(sPokedexAreaScreen->areaUnknownGraphicsBuffer), .tag = TAG_AREA_UNKNOWN, }; - LZ77UnCompWram(gPokedexAreaScreenAreaUnknown_Gfx, sPokedexAreaScreen->areaUnknownGraphicsBuffer); + DecompressDataWithHeaderWram(gPokedexAreaScreenAreaUnknown_Gfx, sPokedexAreaScreen->areaUnknownGraphicsBuffer); LoadSpriteSheet(&spriteSheet); LoadSpritePalette(&sAreaUnknownSpritePalette); } diff --git a/src/pokemon_sprite_visualizer.c b/src/pokemon_sprite_visualizer.c index c6bb39faaff8..196467c37e43 100644 --- a/src/pokemon_sprite_visualizer.c +++ b/src/pokemon_sprite_visualizer.c @@ -744,7 +744,7 @@ static void BattleLoadOpponentMonSpriteGfxCustom(u16 species, bool8 isFemale, bo const u32 *lzPaletteData = GetMonSpritePalFromSpecies(species, isShiny, isFemale); u16 paletteOffset = OBJ_PLTT_ID(battlerId); - LZDecompressWram(lzPaletteData, gDecompressionBuffer); + DecompressDataWithHeaderWram(lzPaletteData, gDecompressionBuffer); LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); LoadPalette(gDecompressionBuffer, BG_PLTT_ID(8) + BG_PLTT_ID(battlerId), PLTT_SIZE_4BPP); } @@ -928,73 +928,73 @@ static void LoadBattleBg(u8 battleBgType, u8 battleTerrain) { default: case MAP_BATTLE_SCENE_NORMAL: - LZDecompressVram(sBattleTerrainTable[battleTerrain].tileset, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(sBattleTerrainTable[battleTerrain].tilemap, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(sBattleTerrainTable[battleTerrain].tileset, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(sBattleTerrainTable[battleTerrain].tilemap, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(sBattleTerrainTable[battleTerrain].palette, 0x20, 0x60); break; case MAP_BATTLE_SCENE_GYM: - LZDecompressVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_BuildingGym, 0x20, 0x60); break; case MAP_BATTLE_SCENE_MAGMA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumMagma, 0x20, 0x60); break; case MAP_BATTLE_SCENE_AQUA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumAqua, 0x20, 0x60); break; case MAP_BATTLE_SCENE_SIDNEY: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumSidney, 0x20, 0x60); break; case MAP_BATTLE_SCENE_PHOEBE: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumPhoebe, 0x20, 0x60); break; case MAP_BATTLE_SCENE_GLACIA: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumGlacia, 0x20, 0x60); break; case MAP_BATTLE_SCENE_DRAKE: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumDrake, 0x20, 0x60); break; case MAP_BATTLE_SCENE_FRONTIER: - LZDecompressVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Frontier, 0x20, 0x60); break; case MAP_BATTLE_SCENE_LEADER: - LZDecompressVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Building, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Building, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_BuildingLeader, 0x20, 0x60); break; case MAP_BATTLE_SCENE_WALLACE: - LZDecompressVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Stadium, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Stadium, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_StadiumWallace, 0x20, 0x60); break; case MAP_BATTLE_SCENE_GROUDON: - LZDecompressVram(gBattleTerrainTiles_Cave, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Cave, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Cave, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Groudon, 0x20, 0x60); break; case MAP_BATTLE_SCENE_KYOGRE: - LZDecompressVram(gBattleTerrainTiles_Water, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Water, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Water, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Water, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Kyogre, 0x20, 0x60); break; case MAP_BATTLE_SCENE_RAYQUAZA: - LZDecompressVram(gBattleTerrainTiles_Rayquaza, (void*)(BG_CHAR_ADDR(2))); - LZDecompressVram(gBattleTerrainTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(gBattleTerrainTiles_Rayquaza, (void*)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(gBattleTerrainTilemap_Rayquaza, (void*)(BG_SCREEN_ADDR(26))); LoadCompressedPalette(gBattleTerrainPalette_Rayquaza, 0x20, 0x60); break; } diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index 97142939311a..5bd6055729bb 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -3810,7 +3810,7 @@ static void SetScrollingBackground(void) { SetGpuReg(REG_OFFSET_BG3CNT, BGCNT_PRIORITY(3) | BGCNT_CHARBASE(3) | BGCNT_16COLOR | BGCNT_SCREENBASE(31)); DecompressAndLoadBgGfxUsingHeap(3, sScrollingBg_Gfx, 0, 0, 0); - LZ77UnCompVram(sScrollingBg_Tilemap, (void *)BG_SCREEN_ADDR(31)); + DecompressDataWithHeaderVram(sScrollingBg_Tilemap, (void *)BG_SCREEN_ADDR(31)); } static void ScrollBackground(void) @@ -3823,7 +3823,7 @@ static void LoadPokeStorageMenuGfx(void) { InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); DecompressAndLoadBgGfxUsingHeap(1, gStorageSystemMenu_Gfx, 0, 0, 0); - LZ77UnCompWram(sDisplayMenu_Tilemap, sStorage->displayMenuTilemapBuffer); + DecompressDataWithHeaderWram(sDisplayMenu_Tilemap, sStorage->displayMenuTilemapBuffer); SetBgTilemapBuffer(1, sStorage->displayMenuTilemapBuffer); ShowBg(1); ScheduleBgCopyTilemapToVram(1); @@ -3977,7 +3977,7 @@ static void LoadDisplayMonGfx(u16 species, u32 pid) if (species != SPECIES_NONE) { LoadSpecialPokePic(sStorage->tileBuffer, species, pid, TRUE); - LZ77UnCompWram(sStorage->displayMonPalette, sStorage->displayMonPalBuffer); + DecompressDataWithHeaderWram(sStorage->displayMonPalette, sStorage->displayMonPalBuffer); CpuCopy32(sStorage->tileBuffer, sStorage->displayMonTilePtr, MON_PIC_SIZE); LoadPalette(sStorage->displayMonPalBuffer, sStorage->displayMonPalOffset, PLTT_SIZE_4BPP); sStorage->displayMonSprite->invisible = FALSE; @@ -4044,7 +4044,7 @@ static void UpdateWaveformAnimation(void) static void InitSupplementalTilemaps(void) { - LZ77UnCompWram(gStorageSystemPartyMenu_Tilemap, sStorage->partyMenuTilemapBuffer); + DecompressDataWithHeaderWram(gStorageSystemPartyMenu_Tilemap, sStorage->partyMenuTilemapBuffer); LoadPalette(gStorageSystemPartyMenu_Pal, BG_PLTT_ID(1), PLTT_SIZE_4BPP); TilemapUtil_SetMap(TILEMAPID_PARTY_MENU, 1, sStorage->partyMenuTilemapBuffer, 12, 22); TilemapUtil_SetMap(TILEMAPID_CLOSE_BUTTON, 1, sCloseBoxButton_Tilemap, 9, 4); @@ -5391,7 +5391,7 @@ static void LoadWallpaperGfx(u8 boxId, s8 direction) if (wallpaperId != WALLPAPER_FRIENDS) { wallpaper = &sWallpapers[wallpaperId]; - LZ77UnCompWram(wallpaper->tilemap, sStorage->wallpaperTilemap); + DecompressDataWithHeaderWram(wallpaper->tilemap, sStorage->wallpaperTilemap); DrawWallpaper(sStorage->wallpaperTilemap, sStorage->wallpaperLoadDir, sStorage->wallpaperOffset); if (sStorage->wallpaperLoadDir != 0) @@ -5405,7 +5405,7 @@ static void LoadWallpaperGfx(u8 boxId, s8 direction) else { wallpaper = &sWaldaWallpapers[GetWaldaWallpaperPatternId()]; - LZ77UnCompWram(wallpaper->tilemap, sStorage->wallpaperTilemap); + DecompressDataWithHeaderWram(wallpaper->tilemap, sStorage->wallpaperTilemap); DrawWallpaper(sStorage->wallpaperTilemap, sStorage->wallpaperLoadDir, sStorage->wallpaperOffset); CpuCopy16(wallpaper->palettes, sStorage->wallpaperTilemap, 0x40); @@ -9184,12 +9184,12 @@ static void LoadItemIconGfx(u8 id, const u32 *itemTiles, const u32 *itemPal) return; CpuFastFill(0, sStorage->itemIconBuffer, 0x200); - LZ77UnCompWram(itemTiles, sStorage->tileBuffer); + DecompressDataWithHeaderWram(itemTiles, sStorage->tileBuffer); for (i = 0; i < 3; i++) CpuFastCopy(&sStorage->tileBuffer[i * 0x60], &sStorage->itemIconBuffer[i * 0x80], 0x60); CpuFastCopy(sStorage->itemIconBuffer, sStorage->itemIcons[id].tiles, 0x200); - LZ77UnCompWram(itemPal, sStorage->itemIconBuffer); + DecompressDataWithHeaderWram(itemPal, sStorage->itemIconBuffer); LoadPalette(sStorage->itemIconBuffer, sStorage->itemIcons[id].palIndex, PLTT_SIZE_4BPP); } diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 3636d2f0aea9..7dd2a7ea18ec 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -1418,24 +1418,24 @@ static bool8 DecompressGraphics(void) case 1: if (FreeTempTileDataBuffersIfPossible() != 1) { - LZDecompressWram(gSummaryPage_Info_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_INFO][0]); + DecompressDataWithHeaderWram(gSummaryPage_Info_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_INFO][0]); sMonSummaryScreen->switchCounter++; } break; case 2: - LZDecompressWram(gSummaryPage_InfoEgg_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_INFO][1]); + DecompressDataWithHeaderWram(gSummaryPage_InfoEgg_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_INFO][1]); sMonSummaryScreen->switchCounter++; break; case 3: - LZDecompressWram(gSummaryPage_Skills_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_SKILLS][1]); + DecompressDataWithHeaderWram(gSummaryPage_Skills_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_SKILLS][1]); sMonSummaryScreen->switchCounter++; break; case 4: - LZDecompressWram(gSummaryPage_BattleMoves_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_BATTLE_MOVES][1]); + DecompressDataWithHeaderWram(gSummaryPage_BattleMoves_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_BATTLE_MOVES][1]); sMonSummaryScreen->switchCounter++; break; case 5: - LZDecompressWram(gSummaryPage_ContestMoves_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_CONTEST_MOVES][1]); + DecompressDataWithHeaderWram(gSummaryPage_ContestMoves_Tilemap, sMonSummaryScreen->bgTilemapBuffers[PSS_PAGE_CONTEST_MOVES][1]); sMonSummaryScreen->switchCounter++; break; case 6: diff --git a/src/pokenav_conditions.c b/src/pokenav_conditions.c index 382ddde41324..49171442fc8d 100644 --- a/src/pokenav_conditions.c +++ b/src/pokenav_conditions.c @@ -538,7 +538,7 @@ static void ConditionGraphDrawMonPic(s16 listId, u8 loadId) isShiny = GetBoxOrPartyMonData(boxId, monId, MON_DATA_IS_SHINY, NULL); personality = GetBoxOrPartyMonData(boxId, monId, MON_DATA_PERSONALITY, NULL); LoadSpecialPokePic(menu->monPicGfx[loadId], species, personality, TRUE); - LZ77UnCompWram(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), menu->monPal[loadId]); + DecompressDataWithHeaderWram(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), menu->monPal[loadId]); } u16 GetMonListCount(void) diff --git a/src/pokenav_conditions_gfx.c b/src/pokenav_conditions_gfx.c index 8845307c0e6b..35464dfea6e7 100644 --- a/src/pokenav_conditions_gfx.c +++ b/src/pokenav_conditions_gfx.c @@ -222,7 +222,7 @@ static u32 LoopedTask_OpenConditionGraphMenu(s32 state) if (FreeTempTileDataBuffersIfPossible()) return LT_PAUSE; - LZ77UnCompVram(gPokenavCondition_Tilemap, menu->tilemapBuffers[0]); + DecompressDataWithHeaderVram(gPokenavCondition_Tilemap, menu->tilemapBuffers[0]); SetBgTilemapBuffer(3, menu->tilemapBuffers[0]); if (IsConditionMenuSearchMode() == TRUE) CopyToBgTilemapBufferRect(3, gPokenavOptions_Tilemap, 0, 5, 9, 4); @@ -236,7 +236,7 @@ static u32 LoopedTask_OpenConditionGraphMenu(s32 state) if (FreeTempTileDataBuffersIfPossible()) return LT_PAUSE; - LZ77UnCompVram(sConditionGraphData_Tilemap, menu->tilemapBuffers[2]); + DecompressDataWithHeaderVram(sConditionGraphData_Tilemap, menu->tilemapBuffers[2]); SetBgTilemapBuffer(2, menu->tilemapBuffers[2]); CopyBgTilemapBufferToVram(2); CopyPaletteIntoBufferUnfaded(gConditionGraphData_Pal, BG_PLTT_ID(3), PLTT_SIZE_4BPP); diff --git a/src/pokenav_main_menu.c b/src/pokenav_main_menu.c index 4c4777e5d523..fd86579d9252 100644 --- a/src/pokenav_main_menu.c +++ b/src/pokenav_main_menu.c @@ -686,7 +686,7 @@ static void LoadLeftHeaderGfxForMenu(u32 menuGfxId) tag = sMenuLeftHeaderSpriteSheets[menuGfxId].tag; size = GetDecompressedDataSize(sMenuLeftHeaderSpriteSheets[menuGfxId].data); LoadPalette(&gPokenavLeftHeader_Pal[tag * 16], OBJ_PLTT_ID(IndexOfSpritePaletteTag(1)), PLTT_SIZE_4BPP); - LZ77UnCompWram(sMenuLeftHeaderSpriteSheets[menuGfxId].data, gDecompressionBuffer); + DecompressDataWithHeaderWram(sMenuLeftHeaderSpriteSheets[menuGfxId].data, gDecompressionBuffer); RequestDma3Copy(gDecompressionBuffer, (void *)OBJ_VRAM0 + (GetSpriteTileStartByTag(2) * 32), size, 1); menu->leftHeaderSprites[1]->oam.tileNum = GetSpriteTileStartByTag(2) + sMenuLeftHeaderSpriteSheets[menuGfxId].size; @@ -706,7 +706,7 @@ static void LoadLeftHeaderGfxForSubMenu(u32 menuGfxId) tag = sPokenavSubMenuLeftHeaderSpriteSheets[menuGfxId].tag; size = GetDecompressedDataSize(sPokenavSubMenuLeftHeaderSpriteSheets[menuGfxId].data); LoadPalette(&gPokenavLeftHeader_Pal[tag * 16], OBJ_PLTT_ID(IndexOfSpritePaletteTag(2)), PLTT_SIZE_4BPP); - LZ77UnCompWram(sPokenavSubMenuLeftHeaderSpriteSheets[menuGfxId].data, &gDecompressionBuffer[0x1000]); + DecompressDataWithHeaderWram(sPokenavSubMenuLeftHeaderSpriteSheets[menuGfxId].data, &gDecompressionBuffer[0x1000]); RequestDma3Copy(&gDecompressionBuffer[0x1000], (void *)OBJ_VRAM0 + 0x800 + (GetSpriteTileStartByTag(2) * 32), size, 1); } diff --git a/src/pokenav_match_call_gfx.c b/src/pokenav_match_call_gfx.c index 80e2709cf0da..28a4bf7f9a91 100755 --- a/src/pokenav_match_call_gfx.c +++ b/src/pokenav_match_call_gfx.c @@ -1253,7 +1253,7 @@ static void LoadCheckPageTrainerPic(struct Pokenav_MatchCallGfx *gfx) if (trainerPic >= 0) { DecompressPicFromTable(&gTrainerSprites[trainerPic].frontPic, gfx->trainerPicGfx); - LZ77UnCompWram(gTrainerSprites[trainerPic].palette.data, gfx->trainerPicPal); + DecompressDataWithHeaderWram(gTrainerSprites[trainerPic].palette.data, gfx->trainerPicPal); cursor = RequestDma3Copy(gfx->trainerPicGfx, gfx->trainerPicGfxPtr, sizeof(gfx->trainerPicGfx), 1); LoadPalette(gfx->trainerPicPal, gfx->trainerPicPalOffset, sizeof(gfx->trainerPicPal)); gfx->trainerPicSprite->data[0] = 0; diff --git a/src/pokenav_region_map.c b/src/pokenav_region_map.c index b17689aad8b6..5dbf73b118cd 100755 --- a/src/pokenav_region_map.c +++ b/src/pokenav_region_map.c @@ -657,7 +657,7 @@ static u32 LoopedTask_DecompressCityMaps(s32 taskState) struct Pokenav_RegionMapGfx *state = GetSubstructPtr(POKENAV_SUBSTRUCT_REGION_MAP_ZOOM); if (taskState < NUM_CITY_MAPS) { - LZ77UnCompWram(sPokenavCityMaps[taskState].tilemap, state->cityZoomPics[taskState]); + DecompressDataWithHeaderWram(sPokenavCityMaps[taskState].tilemap, state->cityZoomPics[taskState]); return LT_INC_AND_CONTINUE; } diff --git a/src/rayquaza_scene.c b/src/rayquaza_scene.c index b3e0276f1d4a..871a5fac5f53 100644 --- a/src/rayquaza_scene.c +++ b/src/rayquaza_scene.c @@ -1599,9 +1599,9 @@ static void LoadDuoFightSceneGfx(void) DecompressAndCopyTileDataToVram(0, gRaySceneDuoFight_Clouds_Gfx, 0, 0, 0); while (FreeTempTileDataBuffersIfPossible()) ; - LZDecompressWram(gRaySceneDuoFight_Clouds2_Tilemap, sRayScene->tilemapBuffers[0]); - LZDecompressWram(gRaySceneDuoFight_Clouds1_Tilemap, sRayScene->tilemapBuffers[1]); - LZDecompressWram(gRaySceneDuoFight_Clouds3_Tilemap, sRayScene->tilemapBuffers[2]); + DecompressDataWithHeaderWram(gRaySceneDuoFight_Clouds2_Tilemap, sRayScene->tilemapBuffers[0]); + DecompressDataWithHeaderWram(gRaySceneDuoFight_Clouds1_Tilemap, sRayScene->tilemapBuffers[1]); + DecompressDataWithHeaderWram(gRaySceneDuoFight_Clouds3_Tilemap, sRayScene->tilemapBuffers[2]); LoadCompressedPalette(gRaySceneDuoFight_Clouds_Pal, BG_PLTT_ID(0), 2 * PLTT_SIZE_4BPP); LoadCompressedSpriteSheet(&sSpriteSheet_DuoFight_Groudon); LoadCompressedSpriteSheet(&sSpriteSheet_DuoFight_GroudonShoulder); @@ -2039,9 +2039,9 @@ static void LoadTakesFlightSceneGfx(void) DecompressAndCopyTileDataToVram(2, gRaySceneTakesFlight_Rayquaza_Gfx, 0, 0, 0); while (FreeTempTileDataBuffersIfPossible()) ; - LZDecompressWram(gRaySceneDuoFight_Clouds2_Tilemap, sRayScene->tilemapBuffers[0]); - LZDecompressWram(gRaySceneTakesFlight_Bg_Tilemap, sRayScene->tilemapBuffers[1]); - LZDecompressWram(gRaySceneTakesFlight_Rayquaza_Tilemap, sRayScene->tilemapBuffers[2]); + DecompressDataWithHeaderWram(gRaySceneDuoFight_Clouds2_Tilemap, sRayScene->tilemapBuffers[0]); + DecompressDataWithHeaderWram(gRaySceneTakesFlight_Bg_Tilemap, sRayScene->tilemapBuffers[1]); + DecompressDataWithHeaderWram(gRaySceneTakesFlight_Rayquaza_Tilemap, sRayScene->tilemapBuffers[2]); LoadCompressedPalette(gRaySceneTakesFlight_Rayquaza_Pal, BG_PLTT_ID(0), 2 * PLTT_SIZE_4BPP); LoadCompressedSpriteSheet(&sSpriteSheet_TakesFlight_Smoke); LoadCompressedSpritePalette(&sSpritePal_TakesFlight_Smoke); @@ -2242,8 +2242,8 @@ static void LoadDescendsSceneGfx(void) DecompressAndCopyTileDataToVram(1, gRaySceneDescends_Bg_Gfx, 0, 0, 0); while (FreeTempTileDataBuffersIfPossible()) ; - LZDecompressWram(gRaySceneDescends_Light_Tilemap, sRayScene->tilemapBuffers[0]); - LZDecompressWram(gRaySceneDescends_Bg_Tilemap, sRayScene->tilemapBuffers[3]); + DecompressDataWithHeaderWram(gRaySceneDescends_Light_Tilemap, sRayScene->tilemapBuffers[0]); + DecompressDataWithHeaderWram(gRaySceneDescends_Bg_Tilemap, sRayScene->tilemapBuffers[3]); CpuFastFill16(0, sRayScene->tilemapBuffers[2], BG_SCREEN_SIZE); CpuFastCopy(sRayScene->tilemapBuffers[3], sRayScene->tilemapBuffers[1], BG_SCREEN_SIZE); CpuFastFill16(0, &sRayScene->tilemapBuffers[1][0x100], 0x340); @@ -2493,10 +2493,10 @@ static void LoadChargesSceneGfx(void) DecompressAndCopyTileDataToVram(3, gRaySceneCharges_Bg_Gfx, 0, 0, 0); while (FreeTempTileDataBuffersIfPossible()) ; - LZDecompressWram(gRaySceneCharges_Orbs_Tilemap, sRayScene->tilemapBuffers[0]); - LZDecompressWram(gRaySceneCharges_Rayquaza_Tilemap, sRayScene->tilemapBuffers[1]); - LZDecompressWram(gRaySceneCharges_Streaks_Tilemap, sRayScene->tilemapBuffers[2]); - LZDecompressWram(gRaySceneCharges_Bg_Tilemap, sRayScene->tilemapBuffers[3]); + DecompressDataWithHeaderWram(gRaySceneCharges_Orbs_Tilemap, sRayScene->tilemapBuffers[0]); + DecompressDataWithHeaderWram(gRaySceneCharges_Rayquaza_Tilemap, sRayScene->tilemapBuffers[1]); + DecompressDataWithHeaderWram(gRaySceneCharges_Streaks_Tilemap, sRayScene->tilemapBuffers[2]); + DecompressDataWithHeaderWram(gRaySceneCharges_Bg_Tilemap, sRayScene->tilemapBuffers[3]); LoadCompressedPalette(gRaySceneCharges_Bg_Pal, BG_PLTT_ID(0), 4 * PLTT_SIZE_4BPP); } @@ -2678,9 +2678,9 @@ static void LoadChasesAwaySceneGfx(void) DecompressAndCopyTileDataToVram(0, gRaySceneChasesAway_Light_Gfx, 0, 0, 0); while (FreeTempTileDataBuffersIfPossible()) ; - LZDecompressWram(gRaySceneChasesAway_Bg_Tilemap, sRayScene->tilemapBuffers[1]); - LZDecompressWram(gRaySceneChasesAway_Light_Tilemap, sRayScene->tilemapBuffers[0]); - LZDecompressWram(gRaySceneChasesAway_Ring_Tilemap, sRayScene->tilemapBuffers[2]); + DecompressDataWithHeaderWram(gRaySceneChasesAway_Bg_Tilemap, sRayScene->tilemapBuffers[1]); + DecompressDataWithHeaderWram(gRaySceneChasesAway_Light_Tilemap, sRayScene->tilemapBuffers[0]); + DecompressDataWithHeaderWram(gRaySceneChasesAway_Ring_Tilemap, sRayScene->tilemapBuffers[2]); LoadCompressedPalette(gRaySceneChasesAway_Bg_Pal, BG_PLTT_ID(0), 3 * PLTT_SIZE_4BPP); LoadCompressedSpriteSheet(&sSpriteSheet_ChasesAway_Groudon); LoadCompressedSpriteSheet(&sSpriteSheet_ChasesAway_GroudonTail); diff --git a/src/region_map.c b/src/region_map.c index aba1162f5b91..26765ec8c928 100644 --- a/src/region_map.c +++ b/src/region_map.c @@ -549,7 +549,7 @@ bool8 LoadRegionMapGfx(void) if (sRegionMap->bgManaged) DecompressAndCopyTileDataToVram(sRegionMap->bgNum, sRegionMapBg_GfxLZ, 0, 0, 0); else - LZ77UnCompVram(sRegionMapBg_GfxLZ, (u16 *)BG_CHAR_ADDR(2)); + DecompressDataWithHeaderVram(sRegionMapBg_GfxLZ, (u16 *)BG_CHAR_ADDR(2)); break; case 1: if (sRegionMap->bgManaged) @@ -559,7 +559,7 @@ bool8 LoadRegionMapGfx(void) } else { - LZ77UnCompVram(sRegionMapBg_TilemapLZ, (u16 *)BG_SCREEN_ADDR(28)); + DecompressDataWithHeaderVram(sRegionMapBg_TilemapLZ, (u16 *)BG_SCREEN_ADDR(28)); } break; case 2: @@ -567,10 +567,10 @@ bool8 LoadRegionMapGfx(void) LoadPalette(sRegionMapBg_Pal, BG_PLTT_ID(7), 3 * PLTT_SIZE_4BPP); break; case 3: - LZ77UnCompWram(sRegionMapCursorSmallGfxLZ, sRegionMap->cursorSmallImage); + DecompressDataWithHeaderWram(sRegionMapCursorSmallGfxLZ, sRegionMap->cursorSmallImage); break; case 4: - LZ77UnCompWram(sRegionMapCursorLargeGfxLZ, sRegionMap->cursorLargeImage); + DecompressDataWithHeaderWram(sRegionMapCursorLargeGfxLZ, sRegionMap->cursorLargeImage); break; case 5: InitMapBasedOnPlayerLocation(); @@ -1707,11 +1707,11 @@ void CB2_OpenFlyMap(void) gMain.state++; break; case 5: - LZ77UnCompVram(sRegionMapFrameGfxLZ, (u16 *)BG_CHAR_ADDR(3)); + DecompressDataWithHeaderVram(sRegionMapFrameGfxLZ, (u16 *)BG_CHAR_ADDR(3)); gMain.state++; break; case 6: - LZ77UnCompVram(sRegionMapFrameTilemapLZ, (u16 *)BG_SCREEN_ADDR(30)); + DecompressDataWithHeaderVram(sRegionMapFrameTilemapLZ, (u16 *)BG_SCREEN_ADDR(30)); gMain.state++; break; case 7: @@ -1830,7 +1830,7 @@ static void LoadFlyDestIcons(void) { struct SpriteSheet sheet; - LZ77UnCompWram(sFlyTargetIcons_Gfx, sFlyMap->tileBuffer); + DecompressDataWithHeaderWram(sFlyTargetIcons_Gfx, sFlyMap->tileBuffer); sheet.data = sFlyMap->tileBuffer; sheet.size = sizeof(sFlyMap->tileBuffer); sheet.tag = TAG_FLY_ICON; diff --git a/src/roulette.c b/src/roulette.c index f4e6012a8dcd..7e7078230822 100644 --- a/src/roulette.c +++ b/src/roulette.c @@ -3522,12 +3522,12 @@ static void CreateGridSprites(void) u8 i, j; u8 spriteId; struct SpriteSheet s; - LZ77UnCompWram(sSpriteSheet_Headers.data, gDecompressionBuffer); + DecompressDataWithHeaderWram(sSpriteSheet_Headers.data, gDecompressionBuffer); s.data = gDecompressionBuffer; s.size = sSpriteSheet_Headers.size; s.tag = sSpriteSheet_Headers.tag; LoadSpriteSheet(&s); - LZ77UnCompWram(sSpriteSheet_GridIcons.data, gDecompressionBuffer); + DecompressDataWithHeaderWram(sSpriteSheet_GridIcons.data, gDecompressionBuffer); s.data = gDecompressionBuffer; s.size = sSpriteSheet_GridIcons.size; s.tag = sSpriteSheet_GridIcons.tag; @@ -3658,7 +3658,7 @@ static void CreateWheelIconSprites(void) u16 angle; struct SpriteSheet s; - LZ77UnCompWram(sSpriteSheet_WheelIcons.data, gDecompressionBuffer); + DecompressDataWithHeaderWram(sSpriteSheet_WheelIcons.data, gDecompressionBuffer); s.data = gDecompressionBuffer; s.size = sSpriteSheet_WheelIcons.size; s.tag = sSpriteSheet_WheelIcons.tag; @@ -3703,7 +3703,7 @@ static void CreateInterfaceSprites(void) for (i = 0; i < ARRAY_COUNT(sSpriteSheets_Interface) - 1; i++) { struct SpriteSheet s; - LZ77UnCompWram(sSpriteSheets_Interface[i].data, gDecompressionBuffer); + DecompressDataWithHeaderWram(sSpriteSheets_Interface[i].data, gDecompressionBuffer); s.data = gDecompressionBuffer; s.size = sSpriteSheets_Interface[i].size; s.tag = sSpriteSheets_Interface[i].tag; @@ -3851,7 +3851,7 @@ static void CreateWheelCenterSprite(void) { u8 spriteId; struct SpriteSheet s; - LZ77UnCompWram(sSpriteSheet_WheelCenter.data, gDecompressionBuffer); + DecompressDataWithHeaderWram(sSpriteSheet_WheelCenter.data, gDecompressionBuffer); s.data = gDecompressionBuffer; s.size = sSpriteSheet_WheelCenter.size; s.tag = sSpriteSheet_WheelCenter.tag; diff --git a/src/save_failed_screen.c b/src/save_failed_screen.c index 9bd981facc35..62b7dfe49174 100644 --- a/src/save_failed_screen.c +++ b/src/save_failed_screen.c @@ -194,10 +194,10 @@ static void CB2_SaveFailedScreen(void) DmaFill16(3, 0, VRAM, VRAM_SIZE); DmaFill32(3, 0, OAM, OAM_SIZE); DmaFill16(3, 0, PLTT, PLTT_SIZE); - LZ77UnCompVram(gBirchBagGrass_Gfx, (void *)VRAM); - LZ77UnCompVram(gBirchBagTilemap, (void *)(BG_SCREEN_ADDR(14))); - LZ77UnCompVram(gBirchGrassTilemap, (void *)(BG_SCREEN_ADDR(15))); - LZ77UnCompVram(sSaveFailedClockGfx, (void *)(OBJ_VRAM0 + 0x20)); + DecompressDataWithHeaderVram(gBirchBagGrass_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(gBirchBagTilemap, (void *)(BG_SCREEN_ADDR(14))); + DecompressDataWithHeaderVram(gBirchGrassTilemap, (void *)(BG_SCREEN_ADDR(15))); + DecompressDataWithHeaderVram(sSaveFailedClockGfx, (void *)(OBJ_VRAM0 + 0x20)); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); SetBgTilemapBuffer(0, (void *)&gDecompressionBuffer[0x2000]); diff --git a/src/shop.c b/src/shop.c index dae2ea86ffb4..b3e05a210f89 100644 --- a/src/shop.c +++ b/src/shop.c @@ -745,7 +745,7 @@ static void BuyMenuInitBgs(void) static void BuyMenuDecompressBgGraphics(void) { DecompressAndCopyTileDataToVram(1, gShopMenu_Gfx, 0x3A0, 0x3E3, 0); - LZDecompressWram(gShopMenu_Tilemap, sShopData->tilemapBuffers[0]); + DecompressDataWithHeaderWram(gShopMenu_Tilemap, sShopData->tilemapBuffers[0]); LoadCompressedPalette(gShopMenu_Pal, BG_PLTT_ID(12), PLTT_SIZE_4BPP); } diff --git a/src/slot_machine.c b/src/slot_machine.c index 7f1139651474..0d1e7301eb05 100644 --- a/src/slot_machine.c +++ b/src/slot_machine.c @@ -5015,9 +5015,9 @@ static void LoadSlotMachineGfx(void) LoadReelBackground(); sDigitalDisplayGfxPtr = Alloc(0x3200); - LZDecompressWram(gSlotMachineDigitalDisplay_Gfx, sDigitalDisplayGfxPtr); + DecompressDataWithHeaderWram(gSlotMachineDigitalDisplay_Gfx, sDigitalDisplayGfxPtr); sReelTimeGfxPtr = Alloc(0x3600); - LZDecompressWram(sReelTimeGfx, sReelTimeGfxPtr); + DecompressDataWithHeaderWram(sReelTimeGfx, sReelTimeGfxPtr); sSlotMachineSpritesheetsPtr = AllocZeroed(sizeof(struct SpriteSheet) * ARRAY_COUNT(sSlotMachineSpriteSheets)); for (i = 0; i < ARRAY_COUNT(sSlotMachineSpriteSheets); i++) { @@ -5055,7 +5055,7 @@ static void LoadReelBackground(void) static void LoadMenuGfx(void) { sMenuGfx = Alloc(0x2200); - LZDecompressWram(gSlotMachineMenu_Gfx, sMenuGfx); + DecompressDataWithHeaderWram(gSlotMachineMenu_Gfx, sMenuGfx); LoadBgTiles(2, sMenuGfx, 0x2200, 0); LoadPalette(gSlotMachineMenu_Pal, BG_PLTT_ID(0), 5 * PLTT_SIZE_4BPP); LoadPalette(sUnkPalette, BG_PLTT_ID(13), PLTT_SIZE_4BPP); diff --git a/src/sprite.c b/src/sprite.c index 2e021f5cbff8..4845e44a4e9d 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -875,8 +875,11 @@ void BeginAnim(struct Sprite *sprite) if (sprite->usingSheet) { + // Inject OW decompression here if (OW_GFX_COMPRESS && sprite->sheetSpan) + { imageValue = (imageValue + 1) << sprite->sheetSpan; + } sprite->oam.tileNum = sprite->sheetTileStart + imageValue; } else @@ -934,7 +937,17 @@ void AnimCmd_frame(struct Sprite *sprite) if (sprite->usingSheet) { if (OW_GFX_COMPRESS && sprite->sheetSpan) + { + // Inject OW frame switcher here + /* + if (imageValue >> 1 != sprite->prevFrame >> 1) + { + MgbaPrintf(MGBA_LOG_WARN, "Address: %u", &sprite->images->data); + } + sprite->prevFrame = imageValue; + */ imageValue = (imageValue + 1) << sprite->sheetSpan; + } sprite->oam.tileNum = sprite->sheetTileStart + imageValue; } else diff --git a/src/starter_choose.c b/src/starter_choose.c index 01b6600053da..b38b7df7f528 100644 --- a/src/starter_choose.c +++ b/src/starter_choose.c @@ -397,9 +397,9 @@ void CB2_ChooseStarter(void) DmaFill32(3, 0, OAM, OAM_SIZE); DmaFill16(3, 0, PLTT, PLTT_SIZE); - LZ77UnCompVram(gBirchBagGrass_Gfx, (void *)VRAM); - LZ77UnCompVram(gBirchBagTilemap, (void *)(BG_SCREEN_ADDR(6))); - LZ77UnCompVram(gBirchGrassTilemap, (void *)(BG_SCREEN_ADDR(7))); + DecompressDataWithHeaderVram(gBirchBagGrass_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(gBirchBagTilemap, (void *)(BG_SCREEN_ADDR(6))); + DecompressDataWithHeaderVram(gBirchGrassTilemap, (void *)(BG_SCREEN_ADDR(7))); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); diff --git a/src/title_screen.c b/src/title_screen.c index 1d605d1fc056..215abea8131f 100644 --- a/src/title_screen.c +++ b/src/title_screen.c @@ -596,15 +596,15 @@ void CB2_InitTitleScreen(void) break; case 1: // bg2 - LZ77UnCompVram(gTitleScreenPokemonLogoGfx, (void *)(BG_CHAR_ADDR(0))); - LZ77UnCompVram(gTitleScreenPokemonLogoTilemap, (void *)(BG_SCREEN_ADDR(9))); + DecompressDataWithHeaderVram(gTitleScreenPokemonLogoGfx, (void *)(BG_CHAR_ADDR(0))); + DecompressDataWithHeaderVram(gTitleScreenPokemonLogoTilemap, (void *)(BG_SCREEN_ADDR(9))); LoadPalette(gTitleScreenBgPalettes, BG_PLTT_ID(0), 15 * PLTT_SIZE_4BPP); // bg3 - LZ77UnCompVram(sTitleScreenRayquazaGfx, (void *)(BG_CHAR_ADDR(2))); - LZ77UnCompVram(sTitleScreenRayquazaTilemap, (void *)(BG_SCREEN_ADDR(26))); + DecompressDataWithHeaderVram(sTitleScreenRayquazaGfx, (void *)(BG_CHAR_ADDR(2))); + DecompressDataWithHeaderVram(sTitleScreenRayquazaTilemap, (void *)(BG_SCREEN_ADDR(26))); // bg1 - LZ77UnCompVram(sTitleScreenCloudsGfx, (void *)(BG_CHAR_ADDR(3))); - LZ77UnCompVram(gTitleScreenCloudsTilemap, (void *)(BG_SCREEN_ADDR(27))); + DecompressDataWithHeaderVram(sTitleScreenCloudsGfx, (void *)(BG_CHAR_ADDR(3))); + DecompressDataWithHeaderVram(gTitleScreenCloudsTilemap, (void *)(BG_SCREEN_ADDR(27))); ScanlineEffect_Stop(); ResetTasks(); ResetSpriteData(); diff --git a/src/trade.c b/src/trade.c index 04b1977c17b0..848a968dace0 100644 --- a/src/trade.c +++ b/src/trade.c @@ -2961,13 +2961,13 @@ static void TradeAnimInit_LoadGfx(void) DeactivateAllTextPrinters(); // Doing the graphics load... DecompressAndLoadBgGfxUsingHeap(0, gBattleTextboxTiles, 0, 0, 0); - LZDecompressWram(gBattleTextboxTilemap, gDecompressionBuffer); + DecompressDataWithHeaderWram(gBattleTextboxTilemap, gDecompressionBuffer); CopyToBgTilemapBuffer(0, gDecompressionBuffer, BG_SCREEN_SIZE, 0); LoadCompressedPalette(gBattleTextboxPalette, BG_PLTT_ID(0), PLTT_SIZE_4BPP); InitWindows(sTradeSequenceWindowTemplates); // ... and doing the same load again DecompressAndLoadBgGfxUsingHeap(0, gBattleTextboxTiles, 0, 0, 0); - LZDecompressWram(gBattleTextboxTilemap, gDecompressionBuffer); + DecompressDataWithHeaderWram(gBattleTextboxTilemap, gDecompressionBuffer); CopyToBgTilemapBuffer(0, gDecompressionBuffer, BG_SCREEN_SIZE, 0); LoadCompressedPalette(gBattleTextboxPalette, BG_PLTT_ID(0), PLTT_SIZE_4BPP); } @@ -3195,7 +3195,7 @@ static void SetTradeSequenceBgGpuRegs(u8 state) DISPCNT_OBJ_1D_MAP | DISPCNT_BG1_ON | DISPCNT_OBJ_ON); - LZ77UnCompVram(sWirelessCloseup_Map, (void *) BG_SCREEN_ADDR(5)); + DecompressDataWithHeaderVram(sWirelessCloseup_Map, (void *) BG_SCREEN_ADDR(5)); BlendPalettes(0x8, 16, RGB_BLACK); } else @@ -3210,8 +3210,8 @@ static void SetTradeSequenceBgGpuRegs(u8 state) break; case 3: LoadPalette(sWirelessSignalNone_Pal, BG_PLTT_ID(3), PLTT_SIZE_4BPP); - LZ77UnCompVram(sWirelessSignal_Gfx, (void *) BG_CHAR_ADDR(1)); - LZ77UnCompVram(sWirelessSignal_Tilemap, (void *) BG_SCREEN_ADDR(18)); + DecompressDataWithHeaderVram(sWirelessSignal_Gfx, (void *) BG_CHAR_ADDR(1)); + DecompressDataWithHeaderVram(sWirelessSignal_Tilemap, (void *) BG_SCREEN_ADDR(18)); sTradeAnim->bg2vofs = 80; SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | diff --git a/src/trainer_card.c b/src/trainer_card.c index 29e94bfe9f19..13a0f036a3f7 100755 --- a/src/trainer_card.c +++ b/src/trainer_card.c @@ -535,47 +535,47 @@ static bool8 LoadCardGfx(void) { case 0: if (sData->cardType != CARD_TYPE_FRLG) - LZ77UnCompWram(gHoennTrainerCardBg_Tilemap, sData->bgTilemap); + DecompressDataWithHeaderWram(gHoennTrainerCardBg_Tilemap, sData->bgTilemap); else - LZ77UnCompWram(gKantoTrainerCardBg_Tilemap, sData->bgTilemap); + DecompressDataWithHeaderWram(gKantoTrainerCardBg_Tilemap, sData->bgTilemap); break; case 1: if (sData->cardType != CARD_TYPE_FRLG) - LZ77UnCompWram(gHoennTrainerCardBack_Tilemap, sData->backTilemap); + DecompressDataWithHeaderWram(gHoennTrainerCardBack_Tilemap, sData->backTilemap); else - LZ77UnCompWram(gKantoTrainerCardBack_Tilemap, sData->backTilemap); + DecompressDataWithHeaderWram(gKantoTrainerCardBack_Tilemap, sData->backTilemap); break; case 2: if (!sData->isLink) { if (sData->cardType != CARD_TYPE_FRLG) - LZ77UnCompWram(gHoennTrainerCardFront_Tilemap, sData->frontTilemap); + DecompressDataWithHeaderWram(gHoennTrainerCardFront_Tilemap, sData->frontTilemap); else - LZ77UnCompWram(gKantoTrainerCardFront_Tilemap, sData->frontTilemap); + DecompressDataWithHeaderWram(gKantoTrainerCardFront_Tilemap, sData->frontTilemap); } else { if (sData->cardType != CARD_TYPE_FRLG) - LZ77UnCompWram(gHoennTrainerCardFrontLink_Tilemap, sData->frontTilemap); + DecompressDataWithHeaderWram(gHoennTrainerCardFrontLink_Tilemap, sData->frontTilemap); else - LZ77UnCompWram(gKantoTrainerCardFrontLink_Tilemap, sData->frontTilemap); + DecompressDataWithHeaderWram(gKantoTrainerCardFrontLink_Tilemap, sData->frontTilemap); } break; case 3: if (sData->cardType != CARD_TYPE_FRLG) - LZ77UnCompWram(sHoennTrainerCardBadges_Gfx, sData->badgeTiles); + DecompressDataWithHeaderWram(sHoennTrainerCardBadges_Gfx, sData->badgeTiles); else - LZ77UnCompWram(sKantoTrainerCardBadges_Gfx, sData->badgeTiles); + DecompressDataWithHeaderWram(sKantoTrainerCardBadges_Gfx, sData->badgeTiles); break; case 4: if (sData->cardType != CARD_TYPE_FRLG) - LZ77UnCompWram(gHoennTrainerCard_Gfx, sData->cardTiles); + DecompressDataWithHeaderWram(gHoennTrainerCard_Gfx, sData->cardTiles); else - LZ77UnCompWram(gKantoTrainerCard_Gfx, sData->cardTiles); + DecompressDataWithHeaderWram(gKantoTrainerCard_Gfx, sData->cardTiles); break; case 5: if (sData->cardType == CARD_TYPE_FRLG) - LZ77UnCompWram(sTrainerCardStickers_Gfx, sData->stickerTiles); + DecompressDataWithHeaderWram(sTrainerCardStickers_Gfx, sData->stickerTiles); break; default: sData->gfxLoadState = 0; diff --git a/src/use_pokeblock.c b/src/use_pokeblock.c index 7d6af9bd794a..4a58a2ee833c 100644 --- a/src/use_pokeblock.c +++ b/src/use_pokeblock.c @@ -1334,7 +1334,7 @@ static bool8 LoadUsePokeblockMenuGfx(void) sMonFrame_TilemapPtr = Alloc(1280); break; case 2: - LZ77UnCompVram(sMonFrame_Tilemap, sMonFrame_TilemapPtr); + DecompressDataWithHeaderVram(sMonFrame_Tilemap, sMonFrame_TilemapPtr); break; case 3: LoadBgTiles(3, sMonFrame_Gfx, 224, 0); @@ -1347,10 +1347,10 @@ static bool8 LoadUsePokeblockMenuGfx(void) sMenu->curMonXOffset = -80; break; case 6: - LZ77UnCompVram(gUsePokeblockGraph_Gfx, sGraph_Gfx); + DecompressDataWithHeaderVram(gUsePokeblockGraph_Gfx, sGraph_Gfx); break; case 7: - LZ77UnCompVram(gUsePokeblockGraph_Tilemap, sGraph_Tilemap); + DecompressDataWithHeaderVram(gUsePokeblockGraph_Tilemap, sGraph_Tilemap); LoadPalette(gUsePokeblockGraph_Pal, BG_PLTT_ID(2), PLTT_SIZE_4BPP); break; case 8: @@ -1362,7 +1362,7 @@ static bool8 LoadUsePokeblockMenuGfx(void) CopyBgTilemapBufferToVram(1); break; case 10: - LZ77UnCompVram(sGraphData_Tilemap, sMenu->tilemapBuffer); + DecompressDataWithHeaderVram(sGraphData_Tilemap, sMenu->tilemapBuffer); break; case 11: LoadBgTilemap(2, sMenu->tilemapBuffer, 1280, 0); diff --git a/src/wallclock.c b/src/wallclock.c index ab1add25a0b5..ec5410f5200e 100644 --- a/src/wallclock.c +++ b/src/wallclock.c @@ -644,7 +644,7 @@ static void LoadWallClockGraphics(void) DmaFillLarge16(3, 0, (void *)VRAM, VRAM_SIZE, 0x1000); DmaClear32(3, (void *)OAM, OAM_SIZE); DmaClear16(3, (void *)PLTT, PLTT_SIZE); - LZ77UnCompVram(gWallClock_Gfx, (void *)VRAM); + DecompressDataWithHeaderVram(gWallClock_Gfx, (void *)VRAM); if (gSpecialVar_0x8004 == MALE) LoadPalette(gWallClockMale_Pal, BG_PLTT_ID(0), PLTT_SIZE_4BPP); @@ -689,7 +689,7 @@ void CB2_StartWallClock(void) u8 spriteId; LoadWallClockGraphics(); - LZ77UnCompVram(gWallClockStart_Tilemap, (u16 *)BG_SCREEN_ADDR(7)); + DecompressDataWithHeaderVram(gWallClockStart_Tilemap, (u16 *)BG_SCREEN_ADDR(7)); taskId = CreateTask(Task_SetClock_WaitFadeIn, 0); gTasks[taskId].tHours = 10; @@ -733,7 +733,7 @@ void CB2_ViewWallClock(void) u8 angle2; LoadWallClockGraphics(); - LZ77UnCompVram(gWallClockView_Tilemap, (u16 *)BG_SCREEN_ADDR(7)); + DecompressDataWithHeaderVram(gWallClockView_Tilemap, (u16 *)BG_SCREEN_ADDR(7)); taskId = CreateTask(Task_ViewClock_WaitFadeIn, 0); InitClockWithRtc(taskId); diff --git a/src/window.c b/src/window.c index ec998083a04c..927b91a1e3c8 100644 --- a/src/window.c +++ b/src/window.c @@ -443,7 +443,7 @@ void CopyToWindowPixelBuffer(u32 windowId, const void *src, u16 size, u16 tileOf if (size != 0) CpuCopy16(src, gWindows[windowId].tileData + (32 * tileOffset), size); else - LZ77UnCompWram(src, gWindows[windowId].tileData + (32 * tileOffset)); + DecompressDataWithHeaderWram(src, gWindows[windowId].tileData + (32 * tileOffset)); } // Sets all pixels within the window to the fillValue color. diff --git a/test/compression/complex_battle_sprite.png b/test/compression/complex_battle_sprite.png new file mode 100644 index 000000000000..e6cc875e50a6 Binary files /dev/null and b/test/compression/complex_battle_sprite.png differ diff --git a/test/compression/gossifleur.png b/test/compression/gossifleur.png new file mode 100644 index 000000000000..a9d84f1c9a17 Binary files /dev/null and b/test/compression/gossifleur.png differ diff --git a/test/compression/large_mode_0.png b/test/compression/large_mode_0.png new file mode 100644 index 000000000000..9d4c57fcde4f Binary files /dev/null and b/test/compression/large_mode_0.png differ diff --git a/test/compression/large_mode_1.png b/test/compression/large_mode_1.png new file mode 100644 index 000000000000..9d4c57fcde4f Binary files /dev/null and b/test/compression/large_mode_1.png differ diff --git a/test/compression/large_mode_2.png b/test/compression/large_mode_2.png new file mode 100644 index 000000000000..9d4c57fcde4f Binary files /dev/null and b/test/compression/large_mode_2.png differ diff --git a/test/compression/large_mode_3.png b/test/compression/large_mode_3.png new file mode 100644 index 000000000000..df9f920ba5e3 Binary files /dev/null and b/test/compression/large_mode_3.png differ diff --git a/test/compression/large_mode_4.png b/test/compression/large_mode_4.png new file mode 100644 index 000000000000..df9f920ba5e3 Binary files /dev/null and b/test/compression/large_mode_4.png differ diff --git a/test/compression/large_mode_5.png b/test/compression/large_mode_5.png new file mode 100644 index 000000000000..df9f920ba5e3 Binary files /dev/null and b/test/compression/large_mode_5.png differ diff --git a/test/compression/ledian.png b/test/compression/ledian.png new file mode 100644 index 000000000000..f5fa8dec90e3 Binary files /dev/null and b/test/compression/ledian.png differ diff --git a/test/compression/medium_mode_0.png b/test/compression/medium_mode_0.png new file mode 100644 index 000000000000..3a4ba289c9ff Binary files /dev/null and b/test/compression/medium_mode_0.png differ diff --git a/test/compression/medium_mode_1.png b/test/compression/medium_mode_1.png new file mode 100644 index 000000000000..87d5d41ea559 Binary files /dev/null and b/test/compression/medium_mode_1.png differ diff --git a/test/compression/medium_mode_2.png b/test/compression/medium_mode_2.png new file mode 100644 index 000000000000..893bcee52a5b Binary files /dev/null and b/test/compression/medium_mode_2.png differ diff --git a/test/compression/medium_mode_3.png b/test/compression/medium_mode_3.png new file mode 100644 index 000000000000..f3f5871b4d0c Binary files /dev/null and b/test/compression/medium_mode_3.png differ diff --git a/test/compression/medium_mode_4.png b/test/compression/medium_mode_4.png new file mode 100644 index 000000000000..f3f5871b4d0c Binary files /dev/null and b/test/compression/medium_mode_4.png differ diff --git a/test/compression/medium_mode_5.png b/test/compression/medium_mode_5.png new file mode 100644 index 000000000000..4b8cb700cca5 Binary files /dev/null and b/test/compression/medium_mode_5.png differ diff --git a/test/compression/mr_mime.png b/test/compression/mr_mime.png new file mode 100644 index 000000000000..c4db5e51ec73 Binary files /dev/null and b/test/compression/mr_mime.png differ diff --git a/test/compression/secondary_tileset.png b/test/compression/secondary_tileset.png new file mode 100644 index 000000000000..00d6d94a4ef2 Binary files /dev/null and b/test/compression/secondary_tileset.png differ diff --git a/test/compression/simple_battle_sprite.png b/test/compression/simple_battle_sprite.png new file mode 100644 index 000000000000..631ab8f09449 Binary files /dev/null and b/test/compression/simple_battle_sprite.png differ diff --git a/test/compression/small_bubbles.png b/test/compression/small_bubbles.png new file mode 100644 index 000000000000..9547b39faf1a Binary files /dev/null and b/test/compression/small_bubbles.png differ diff --git a/test/compression/small_mode_0.png b/test/compression/small_mode_0.png new file mode 100644 index 000000000000..15cffcc857e8 Binary files /dev/null and b/test/compression/small_mode_0.png differ diff --git a/test/compression/small_mode_1.png b/test/compression/small_mode_1.png new file mode 100644 index 000000000000..76eb7c9a8f23 Binary files /dev/null and b/test/compression/small_mode_1.png differ diff --git a/test/compression/small_mode_2.png b/test/compression/small_mode_2.png new file mode 100644 index 000000000000..fd24e0621924 Binary files /dev/null and b/test/compression/small_mode_2.png differ diff --git a/test/compression/small_mode_3.png b/test/compression/small_mode_3.png new file mode 100644 index 000000000000..d0d7c927549b Binary files /dev/null and b/test/compression/small_mode_3.png differ diff --git a/test/compression/small_mode_4.png b/test/compression/small_mode_4.png new file mode 100644 index 000000000000..d0d7c927549b Binary files /dev/null and b/test/compression/small_mode_4.png differ diff --git a/test/compression/small_mode_5.png b/test/compression/small_mode_5.png new file mode 100644 index 000000000000..1d79d0608c66 Binary files /dev/null and b/test/compression/small_mode_5.png differ diff --git a/test/compression/smol.c b/test/compression/smol.c new file mode 100644 index 000000000000..eadba138b60d --- /dev/null +++ b/test/compression/smol.c @@ -0,0 +1,2524 @@ +#include "global.h" +#include "main.h" +#include "malloc.h" +#include "random.h" +#include "sprite.h" +#include "test/test.h" +#include "config/test.h" +#include "config/general.h" + +#ifdef NDEBUG +void CycleCountStart(); +u32 CycleCountEnd(); +#endif + +TEST("Compression test: tileset smol") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/tilesetTest.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/tilesetTest.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Tileset Smol: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: tileset fastSmol") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/tilesetTest.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/tilesetTest.4bpp.fastSmol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Tileset fastSmol: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: tileset LZ") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/tilesetTest.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/tilesetTest.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Tileset LZ: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: secondary tileset smol") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/secondary_tileset.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/secondary_tileset.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Secondary Tileset Smol: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: secondary tileset fastSmol") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/secondary_tileset.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/secondary_tileset.4bpp.fastSmol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Secondary Tileset fastSmol: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: secondary tileset LZ") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/secondary_tileset.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/secondary_tileset.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Secondary Tileset LZ: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} +TEST("Compression test: simple battle sprite smol") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/simple_battle_sprite.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/simple_battle_sprite.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Simple Sprite smol: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: simple battle sprite LZ") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/simple_battle_sprite.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/simple_battle_sprite.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Simple Sprite LZ: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: complex battle sprite") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/complex_battle_sprite.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/complex_battle_sprite.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Complex Sprite smol: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: complex battle sprite") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/complex_battle_sprite.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/complex_battle_sprite.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Time Complex Sprite LZ: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: Gossifleur") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/gossifleur.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/gossifleur.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Gossifleur: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: Ledian") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/ledian.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/ledian.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Ledian: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: Mr. Mime") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/mr_mime.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/mr_mime.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Ledian: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: bubbles") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_bubbles.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_bubbles.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small Bubbles: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 0") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_0.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_0.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 0: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} +TEST("Compression test: medium mode 0") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_0.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_0.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 0: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 0") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_0.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_0.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 0: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 1") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_1.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_1.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 1: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 1") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_1.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_1.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 1: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 1") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_1.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_1.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 1: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 2") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_2.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_2.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 2: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 2") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_2.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_2.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 2: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 2") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_2.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_2.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 2: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 3") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_3.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_3.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 3: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 3") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_3.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_3.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 3: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 3") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_3.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_3.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 3: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 4") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_4.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_4.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 4: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 4") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_4.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_4.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 4: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 4") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_4.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_4.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 4: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 5") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_5.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_5.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 5: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 5") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_5.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_5.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 5: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 5") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_5.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_5.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 5: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 0 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_0.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_0.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 0 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} +TEST("Compression test: medium mode 0 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_0.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_0.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 0 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 0 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_0.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_0.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 0 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 1 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_1.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_1.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 1 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 1 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_1.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_1.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 1 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 1 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_1.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_1.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 1 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 2 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_2.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_2.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 2 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 2 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_2.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_2.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 2 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 2 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_2.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_2.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 2 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 3 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_3.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_3.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 3 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 3 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_3.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_3.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 3 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 3 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_3.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_3.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 3 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 4 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_4.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_4.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 4 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 4 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_4.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_4.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 4 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 4 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_4.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_4.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 4 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: small mode 5 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/small_mode_5.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/small_mode_5.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Small mode 5 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: medium mode 5 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/medium_mode_5.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/medium_mode_5.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Medium mode 5 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: large mode 5 lz") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/large_mode_5.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/large_mode_5.4bpp.lz"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + if (T_COMPRESSION_SHOULD_PRINT) + CycleCountStart(); + DecompressDataWithHeaderWram(compFile, compBuffer); + if (T_COMPRESSION_SHOULD_PRINT) + { + DebugPrintf("Large mode 5 lz: %u", CycleCountEnd()); + } + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 63 1") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_63_1.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_63_1.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 62 2") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_62_2.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_62_2.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 61 3") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_61_3.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_61_3.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 60 4") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_60_4.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_60_4.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 59 5") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_59_5.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_59_5.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 58 6") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_58_6.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_58_6.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 57 7") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_57_7.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_57_7.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 56 8") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_56_8.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_56_8.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 55 9") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_55_9.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_55_9.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 54 10") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_54_10.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_54_10.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 53 11") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_53_11.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_53_11.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 52 12") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_52_12.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_52_12.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 51 13") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_51_13.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_51_13.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 50 14") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_50_14.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_50_14.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 49 15") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_49_15.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_49_15.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 48 16") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_48_16.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_48_16.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 47 17") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_47_17.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_47_17.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 46 18") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_46_18.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_46_18.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 45 19") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_45_19.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_45_19.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 44 20") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_44_20.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_44_20.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 43 21") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_43_21.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_43_21.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 42 22") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_42_22.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_42_22.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 41 23") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_41_23.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_41_23.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 40 24") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_40_24.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_40_24.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 39 25") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_39_25.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_39_25.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 38 26") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_38_26.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_38_26.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 37 27") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_37_27.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_37_27.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 36 28") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_36_28.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_36_28.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 35 29") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_35_29.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_35_29.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 34 30") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_34_30.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_34_30.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 33 31") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_33_31.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_33_31.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} + +TEST("Compression test: table generation 32 32") +{ + static const u32 origFile[] = INCBIN_U32("test/compression/table_32_32.4bpp"); + static const u32 compFile[] = INCBIN_U32("test/compression/table_32_32.4bpp.smol"); + u32 imageSize = GetDecompressedDataSize(compFile); + u32 *compBuffer = Alloc(imageSize); + DecompressDataWithHeaderWram(compFile, compBuffer); + + u32 val1 = 0; + u32 val2 = 0; + bool32 areEqual = TRUE; + for (u32 i = 0; i < imageSize/4; i++) + { + val1 = origFile[i]; + val2 = compBuffer[i]; + if (val1 != val2) + { + areEqual = FALSE; + break; + } + } + + EXPECT_EQ(areEqual, TRUE); + + Free(compBuffer); +} diff --git a/test/compression/table_32_32.png b/test/compression/table_32_32.png new file mode 100644 index 000000000000..4b5722c91033 Binary files /dev/null and b/test/compression/table_32_32.png differ diff --git a/test/compression/table_33_31.png b/test/compression/table_33_31.png new file mode 100644 index 000000000000..f21075b1f0a8 Binary files /dev/null and b/test/compression/table_33_31.png differ diff --git a/test/compression/table_34_30.png b/test/compression/table_34_30.png new file mode 100644 index 000000000000..53f81842b2b8 Binary files /dev/null and b/test/compression/table_34_30.png differ diff --git a/test/compression/table_35_29.png b/test/compression/table_35_29.png new file mode 100644 index 000000000000..0a60fcc7c264 Binary files /dev/null and b/test/compression/table_35_29.png differ diff --git a/test/compression/table_36_28.png b/test/compression/table_36_28.png new file mode 100644 index 000000000000..3dd266ca96e0 Binary files /dev/null and b/test/compression/table_36_28.png differ diff --git a/test/compression/table_37_27.png b/test/compression/table_37_27.png new file mode 100644 index 000000000000..651d7c3899f6 Binary files /dev/null and b/test/compression/table_37_27.png differ diff --git a/test/compression/table_38_26.png b/test/compression/table_38_26.png new file mode 100644 index 000000000000..0cbf8e0a0ad4 Binary files /dev/null and b/test/compression/table_38_26.png differ diff --git a/test/compression/table_39_25.png b/test/compression/table_39_25.png new file mode 100644 index 000000000000..c91994abcd30 Binary files /dev/null and b/test/compression/table_39_25.png differ diff --git a/test/compression/table_40_24.png b/test/compression/table_40_24.png new file mode 100644 index 000000000000..0f2b192610e4 Binary files /dev/null and b/test/compression/table_40_24.png differ diff --git a/test/compression/table_41_23.png b/test/compression/table_41_23.png new file mode 100644 index 000000000000..15cc2eac49c8 Binary files /dev/null and b/test/compression/table_41_23.png differ diff --git a/test/compression/table_42_22.png b/test/compression/table_42_22.png new file mode 100644 index 000000000000..d59f48b7fb38 Binary files /dev/null and b/test/compression/table_42_22.png differ diff --git a/test/compression/table_43_21.png b/test/compression/table_43_21.png new file mode 100644 index 000000000000..df7aeea81530 Binary files /dev/null and b/test/compression/table_43_21.png differ diff --git a/test/compression/table_44_20.png b/test/compression/table_44_20.png new file mode 100644 index 000000000000..354132253626 Binary files /dev/null and b/test/compression/table_44_20.png differ diff --git a/test/compression/table_45_19.png b/test/compression/table_45_19.png new file mode 100644 index 000000000000..2f6eeff3cc95 Binary files /dev/null and b/test/compression/table_45_19.png differ diff --git a/test/compression/table_46_18.png b/test/compression/table_46_18.png new file mode 100644 index 000000000000..c39bdf757c64 Binary files /dev/null and b/test/compression/table_46_18.png differ diff --git a/test/compression/table_47_17.png b/test/compression/table_47_17.png new file mode 100644 index 000000000000..792f053dc8c0 Binary files /dev/null and b/test/compression/table_47_17.png differ diff --git a/test/compression/table_48_16.png b/test/compression/table_48_16.png new file mode 100644 index 000000000000..d88f3794cfa6 Binary files /dev/null and b/test/compression/table_48_16.png differ diff --git a/test/compression/table_49_15.png b/test/compression/table_49_15.png new file mode 100644 index 000000000000..59114553276e Binary files /dev/null and b/test/compression/table_49_15.png differ diff --git a/test/compression/table_50_14.png b/test/compression/table_50_14.png new file mode 100644 index 000000000000..a773629b05a5 Binary files /dev/null and b/test/compression/table_50_14.png differ diff --git a/test/compression/table_51_13.png b/test/compression/table_51_13.png new file mode 100644 index 000000000000..edece0a3e87d Binary files /dev/null and b/test/compression/table_51_13.png differ diff --git a/test/compression/table_52_12.png b/test/compression/table_52_12.png new file mode 100644 index 000000000000..686ffb10835c Binary files /dev/null and b/test/compression/table_52_12.png differ diff --git a/test/compression/table_53_11.png b/test/compression/table_53_11.png new file mode 100644 index 000000000000..9fce27e88fd4 Binary files /dev/null and b/test/compression/table_53_11.png differ diff --git a/test/compression/table_54_10.png b/test/compression/table_54_10.png new file mode 100644 index 000000000000..ce94bc41eabe Binary files /dev/null and b/test/compression/table_54_10.png differ diff --git a/test/compression/table_55_9.png b/test/compression/table_55_9.png new file mode 100644 index 000000000000..30665e3e1458 Binary files /dev/null and b/test/compression/table_55_9.png differ diff --git a/test/compression/table_56_8.png b/test/compression/table_56_8.png new file mode 100644 index 000000000000..1d9da97dde56 Binary files /dev/null and b/test/compression/table_56_8.png differ diff --git a/test/compression/table_57_7.png b/test/compression/table_57_7.png new file mode 100644 index 000000000000..9c58b336779a Binary files /dev/null and b/test/compression/table_57_7.png differ diff --git a/test/compression/table_58_6.png b/test/compression/table_58_6.png new file mode 100644 index 000000000000..c3d836142242 Binary files /dev/null and b/test/compression/table_58_6.png differ diff --git a/test/compression/table_59_5.png b/test/compression/table_59_5.png new file mode 100644 index 000000000000..d7a283ced33c Binary files /dev/null and b/test/compression/table_59_5.png differ diff --git a/test/compression/table_60_4.png b/test/compression/table_60_4.png new file mode 100644 index 000000000000..cdbbee03db80 Binary files /dev/null and b/test/compression/table_60_4.png differ diff --git a/test/compression/table_61_3.png b/test/compression/table_61_3.png new file mode 100644 index 000000000000..2e420c5f7f84 Binary files /dev/null and b/test/compression/table_61_3.png differ diff --git a/test/compression/table_62_2.png b/test/compression/table_62_2.png new file mode 100644 index 000000000000..9965e96be792 Binary files /dev/null and b/test/compression/table_62_2.png differ diff --git a/test/compression/table_63_1.png b/test/compression/table_63_1.png new file mode 100644 index 000000000000..6f4be88870cb Binary files /dev/null and b/test/compression/table_63_1.png differ diff --git a/test/compression/tilesetTest.png b/test/compression/tilesetTest.png new file mode 100644 index 000000000000..17426ab80e8f Binary files /dev/null and b/test/compression/tilesetTest.png differ diff --git a/tools/compresSmol/Makefile b/tools/compresSmol/Makefile new file mode 100644 index 000000000000..85f6d0f28333 --- /dev/null +++ b/tools/compresSmol/Makefile @@ -0,0 +1,26 @@ +CXX ?= g++ + +CXXFLAGS := -Werror -std=c++17 -pthread -O2 -Wunused + +INCLUDES := -I . + +SRCS := compresSmol.cpp compressAlgo.cpp tANS.cpp fileDispatcher.cpp + +HEADERS := compressAlgo.h tANS.h fileDispatcher.h + +ifeq ($(OS),Windows_NT) +EXE := .exe +else +EXE := +endif + +.PHONY: all clean + +all: compresSmol$(EXE) + @: + +compresSmol$(EXE): $(SRCS) $(HEADERS) + $(CXX) $(CXXFLAGS) $(INCLUDES) $(SRCS) -o $@ $(LDFLAGS) + +clean: + $(RM) compresSmol compresSmol.exe diff --git a/tools/compresSmol/compresSmol.cpp b/tools/compresSmol/compresSmol.cpp new file mode 100644 index 000000000000..80d7ae9f88a4 --- /dev/null +++ b/tools/compresSmol/compresSmol.cpp @@ -0,0 +1,262 @@ +#include +#include +#include +#include +#include +#include +#include "fileDispatcher.h" +#include "compressAlgo.h" + +struct ThingCount { + size_t number = 0; + size_t count = 1; +}; + +bool isNumber(std::string input) +{ + return input.find_first_not_of("0123456789") == std::string::npos; +} + +enum Option { + ANALYZE, + WRITE, + FRAME_WRITE, + DECODE, + USAGE, +}; + +int main(int argc, char *argv[]) +{ + Option option = USAGE; + bool printUsage = false; + std::string input; + std::string output; + int numThreads = 1; + InputSettings settings(true, true, true); + + if (argc > 1) + { + std::string argument = argv[1]; + if (argument.compare("-a") == 0) + option = ANALYZE; + else if (argument.compare("-w") == 0) + option = WRITE; + else if (argument.compare("-fw") == 0) + option = FRAME_WRITE; + else if (argument.compare("-d") == 0) + option = DECODE; + } + switch (option) + { + case ANALYZE: + if (argc > 2) + input = argv[2]; + else + printUsage = true; + if (argc > 4) + { + std::string arg2 = argv[3]; + std::string arg2arg = argv[4]; + if (arg2.compare("-t") == 0 && isNumber(arg2arg)) + numThreads = std::stoi(arg2arg.c_str()); + } + if (argc > 7) + { + std::string setting1 = argv[5]; + std::string setting2 = argv[6]; + std::string setting3 = argv[7]; + if (setting1.compare("true") == 0) + settings.canEncodeLO = true; + else if (setting1.compare("false") == 0) + settings.canEncodeLO = false; + else + fprintf(stderr, "Unrecognized setting1 \"%s\", defaulting to \"true\"\n", setting1.c_str()); + if (setting2.compare("true") == 0) + settings.canEncodeSyms = true; + else if (setting2.compare("false") == 0) + settings.canEncodeSyms = false; + else + fprintf(stderr, "Unrecognized setting2 \"%s\", defaulting to \"true\"\n", setting2.c_str()); + if (setting3.compare("true") == 0) + settings.canDeltaSyms = true; + else if (setting3.compare("false") == 0) + settings.canDeltaSyms = false; + else + fprintf(stderr, "Unrecognized setting3 \"%s\", defaulting to \"true\"\n", setting3.c_str()); + } + break; + case FRAME_WRITE: + settings.useFrames = true; + option = WRITE; + case WRITE: + if (argc > 3) + { + input = argv[2]; + output = argv[3]; + if (argc > 6) + { + std::string setting1 = argv[4]; + std::string setting2 = argv[5]; + std::string setting3 = argv[6]; + if (setting1.compare("true") == 0) + settings.canEncodeLO = true; + else if (setting1.compare("false") == 0) + settings.canEncodeLO = false; + else + fprintf(stderr, "Unrecognized setting1 \"%s\", defaulting to \"true\"\n", setting1.c_str()); + if (setting2.compare("true") == 0) + settings.canEncodeSyms = true; + else if (setting2.compare("false") == 0) + settings.canEncodeSyms = false; + else + fprintf(stderr, "Unrecognized setting2 \"%s\", defaulting to \"true\"\n", setting2.c_str()); + if (setting3.compare("true") == 0) + settings.canDeltaSyms = true; + else if (setting3.compare("false") == 0) + settings.canDeltaSyms = false; + else + fprintf(stderr, "Unrecognized setting3 \"%s\", defaulting to \"true\"\n", setting3.c_str()); + } + } + else + { + printUsage = true; + } + break; + case DECODE: + if (argc > 3) + { + input = argv[2]; + output = argv[3]; + } + else + { + printUsage = true; + } + break; + case USAGE: + printUsage = true; + break; + } + if (printUsage) + { + printf("Usage:\n\ + %s -a \"path/to/some/directory\"\n\ + Analyses all images currently in .4bpp.lz format and compares with this compression.\n\ + -t can be appended to this mode to specify how many threads to use.\n\ + \n\ + %s -w \"path/to/some/file.4bpp\" \"path/to/some/file.4bpp.smol\"\ + Compresses the first argument and writes the result to the second argument.\n\ + These modes can also be appended with 4 true/false statements that control the following settings of the compression:\n\ + - If the compression instructions can be tANS encoded.\n\ + - If the raw symbols in the compression can be tANS encoded.\n\ + - If the compression instructions can be delta encoded.\n\ + - If the raw symbols in the compression ca be delta encoded.\n\ + %s -d \"path/to/some/file.4bpp.smol\" \"path/to/some/file.4bpp\"\n\ + Decompresses the first argument and writes it to the second argument.", argv[0], argv[0], argv[0]); + + return 0; + } + + if (option == ANALYZE) + { + std::filesystem::path dirPath = input; + FileDispatcher dispatcher(dirPath); + if (!dispatcher.initFileList()) + { + fprintf(stderr, "Failed to init file list\n"); + return 1; + } + std::mutex dispatchMutex; + std::vector allImages; + std::mutex imageMutex; + + settings.shouldCompare = true; + + std::vector threads; + for (int i = 0; i < numThreads; i++) + { + threads.emplace_back(analyzeImages, &allImages, &imageMutex, + &dispatcher, &dispatchMutex, + settings); + } + + for (int i = 0; i < numThreads; i++) + threads[i].join(); + + size_t lzSizes = 0; + size_t newSizes = 0; + size_t rawSizes = 0; + size_t totalImages = 0; + size_t invalidImages = 0; + for (CompressedImage currImage : allImages) + { + totalImages++; + if (currImage.isValid) + { + lzSizes += currImage.lzSize; + newSizes += currImage.compressedSize; + rawSizes += currImage.rawNumBytes; + } + else + { + fprintf(stderr, "Failed to solve %s\n", currImage.fileName.c_str()); + invalidImages++; + } + } + + fprintf(stderr, "RawSize: %zu\n", rawSizes); + fprintf(stderr, "LZsize: %zu\n", lzSizes); + fprintf(stderr, "SmolSize: %zu\n", newSizes); + fprintf(stderr, "Total Images: %zu\n", totalImages); + fprintf(stderr, "Invalid Images: %zu\n", invalidImages); + } + if (option == WRITE) + { + if (std::filesystem::exists(input)) + { + CompressedImage image; + if (settings.useFrames) + image = processImageFrames(input, settings); + else + image = processImage(input, settings); + if (image.isValid) + { + std::ofstream fileOut(output.c_str(), std::ios::out | std::ios::binary); + fileOut.write(reinterpret_cast(image.writeVec.data()), image.writeVec.size()*4); + fileOut.close(); + } + else + { + fprintf(stderr, "Failed to compress image %s\n", image.fileName.c_str()); + } + } + else + { + fprintf(stderr, "Input file %s doesn't exist\n", input.c_str()); + } + } + if (option == DECODE) + { + if (std::filesystem::exists(input)) + { + std::vector inData = readFileAsUInt(input); + std::vector image4bpp = readRawDataVecs(&inData); + std::vector charVec(image4bpp.size()*2); + for (size_t i = 0; i < image4bpp.size(); i++) + { + charVec[2*i] = image4bpp[i] & 0xff; + charVec[2*i + 1] = (image4bpp[i] >> 8) & 0xff; + } + std::ofstream fileOut(output.c_str(), std::ios::out | std::ios::binary); + std::copy(charVec.begin(), charVec.end(), std::ostreambuf_iterator(fileOut)); + fileOut.close(); + } + else + { + fprintf(stderr, "Input file %s doesn't exist\n", input.c_str()); + } + } + + return 0; +} diff --git a/tools/compresSmol/compressAlgo.cpp b/tools/compresSmol/compressAlgo.cpp new file mode 100644 index 000000000000..8d0b55aebbdc --- /dev/null +++ b/tools/compresSmol/compressAlgo.cpp @@ -0,0 +1,1556 @@ +#include "compressAlgo.h" + +std::vector getShortCopies(std::vector input, size_t minLength) +{ + std::vector copies; + for (size_t startIndex = 1; startIndex < input.size(); startIndex++) + { + size_t longestLength = 0; + size_t longestOffset; + for (size_t searchOffset = 1; searchOffset <= startIndex && searchOffset < 32767; searchOffset++) + { + size_t currLength = 0; + while (input[startIndex + currLength] == input[startIndex + currLength - searchOffset] + && startIndex + currLength < input.size()) + currLength++; + if (currLength > longestLength) + { + longestLength = currLength; + longestOffset = searchOffset; + } + } + + if (longestLength > 32767) + longestLength = 32767; + if (longestLength >= minLength) + { + std::vector::const_iterator start = input.begin() + startIndex; + std::vector::const_iterator end = input.begin() + startIndex + longestLength; + copies.push_back(ShortCopy(startIndex, longestLength, longestOffset, std::vector(start, end))); + copies[copies.size() - 1].firstSymbol = input[startIndex - 1]; + startIndex += longestLength; + } + } + std::vector checkVec(input.size()); + for (ShortCopy copy : copies) + for (size_t i = 0; i <= copy.length; i++) + checkVec[copy.index + i - 1]++; + size_t currStart = 0; + size_t currLength = 1; + unsigned short prevSym = checkVec[0]; + for (size_t i = 1; i < checkVec.size(); i++) + { + unsigned short currSym = checkVec[i]; + if (currSym == 0 && prevSym == 0) + currLength++; + else if (currSym == 0 && prevSym == 1) + { + currStart = i; + currLength = 1; + } + else if (currSym == 1 && prevSym == 0) + { + std::vector::const_iterator start = input.begin() + currStart; + std::vector::const_iterator end = input.begin() + currStart + currLength; + copies.push_back(ShortCopy(currStart, currLength, 0, std::vector(start, end))); + } + prevSym = currSym; + } + if (prevSym == 0) + { + std::vector::const_iterator start = input.begin() + currStart; + std::vector::const_iterator end = input.begin() + currStart + currLength; + copies.push_back(ShortCopy(currStart, currLength, 0, std::vector(start, end))); + } + + return copies; +} + + +bool verifyShortCopies(std::vector *pCopies, std::vector *pImage) +{ + std::vector decodedImage(pImage->size()); + for (ShortCopy copy : (*pCopies)) + { + if (copy.offset == 0) + { + for (size_t i = 0; i < copy.length; i++) + decodedImage[copy.index + i] = copy.usSequence[i]; + } + else + { + decodedImage[copy.index - 1] = copy.firstSymbol; + for (size_t i = 0; i < copy.length; i++) + decodedImage[copy.index + i] = (*pImage)[copy.index + i - copy.offset]; + } + } + for (size_t i = 0; i < decodedImage.size(); i++) + if (decodedImage[i] != (*pImage)[i]) + return false; + return true; +} + +SortedShortElement::SortedShortElement() {} + +SortedShortElement::SortedShortElement(size_t index, ShortCopy copy) +{ + this->index = index; + this->copy = copy; + isCopy = true; +} + +std::vector getShortInstructions(std::vector copies, size_t lengthMod) +{ + std::vector instructions; + std::vector unsortedElements; + std::vector sortedElements; + + for (ShortCopy copy : copies) + unsortedElements.push_back(SortedShortElement(copy.index, copy)); + + while (unsortedElements.size() != 0) + { + size_t smallestIndex = 0; + for (size_t i = 0; i < unsortedElements.size(); i++) + { + if (unsortedElements[i].index < unsortedElements[smallestIndex].index) + { + smallestIndex = i; + } + } + sortedElements.push_back(unsortedElements[smallestIndex]); + unsortedElements.erase(unsortedElements.begin() + smallestIndex); + } + for (size_t i = 0; i < sortedElements.size(); i++) + { + ShortCompressionInstruction currInstruction; + currInstruction.index = sortedElements[i].index; + currInstruction.offset = sortedElements[i].copy.offset; + currInstruction.length = sortedElements[i].copy.length; + currInstruction.symbols = sortedElements[i].copy.usSequence; + currInstruction.firstSymbol = sortedElements[i].copy.firstSymbol; + currInstruction.buildBytes(); + instructions.push_back(currInstruction); + } + return instructions; +} + +void ShortCompressionInstruction::buildBytes() +{ + if (offset != 0) + { + // Current pattern either exists earlier in the image + // or it's a long run of the same value + size_t currLength = length; + loBytes.push_back(currLength & LO_LOW_BITS_MASK); + currLength = currLength >> LO_NUM_LOW_BITS; + if (currLength != 0) + { + loBytes[loBytes.size() - 1] += LO_CONTINUE_BIT; + loBytes.push_back(currLength & BYTE_MASK); + } + size_t currOffset = offset; + loBytes.push_back(currOffset & LO_LOW_BITS_MASK); + currOffset = currOffset >> LO_NUM_LOW_BITS; + if (currOffset != 0) + { + loBytes[loBytes.size() - 1] += LO_CONTINUE_BIT; + loBytes.push_back(currOffset & BYTE_MASK); + } + symShorts.push_back(firstSymbol); + } + else + { + // The current pattern doesn't exist earlier in the image + // it has to be written section by section + // Set LENGTH parameter to 0, and use OFFSET parameter as length + loBytes.push_back(0); + size_t currLength = length; + loBytes.push_back(currLength & LO_LOW_BITS_MASK); + currLength = currLength >> LO_NUM_LOW_BITS; + if (currLength != 0) + { + loBytes[loBytes.size() - 1] += LO_CONTINUE_BIT; + loBytes.push_back(currLength & BYTE_MASK); + } + for (unsigned short currSymbol : symbols) + symShorts.push_back(currSymbol); + } +} + +void CompressionInstruction::buildBytes() +{ + std::vector currBytes; + if (offset != 0) + { + size_t currLength = length; + currBytes.push_back(currLength & 0x7f); + currLength = currLength >> 7; + if (currLength != 0) + { + currBytes[currBytes.size() - 1] += 128; + currBytes.push_back(currLength & 0xff); + } + size_t currOffset = offset; + currBytes.push_back(currOffset & 0x7f); + currOffset = currOffset >> 7; + if (currOffset != 0) + { + currBytes[currBytes.size() - 1] += 128; + currBytes.push_back(currOffset & 0xff); + } + currBytes.push_back(firstSymbol); + } + else + { + currBytes.push_back(0); + size_t currLength = length; + currBytes.push_back(currLength & 0x7f); + currLength = currLength >> 7; + if (currLength != 0) + { + currBytes[currBytes.size() - 1] += 128; + currBytes.push_back(currLength & 0xff); + } + for (unsigned char currSymbol : symbols) + currBytes.push_back(currSymbol); + } + bytes = currBytes; +} + +bool CompressionInstruction::verifyInstruction() +{ + bool lengthDone = false; + bool offsetDone = false; + size_t currLength = 0; + size_t currOffset = 0; + size_t usedLengths = 0; + size_t usedOffsets = 0; + std::vector currSymbols; + for (size_t i = 0; i < bytes.size(); i++) + { + if (!lengthDone) + { + currLength += (bytes[i] & 0x7f) << (7*usedLengths); + usedLengths++; + if ((bytes[i] & 0x80) != 0x80) + lengthDone = true; + } + else if (!offsetDone) + { + currOffset += (bytes[i] & 0x7f) << (7*usedOffsets); + usedOffsets++; + if ((bytes[i] & 0x80) != 0x80) + offsetDone = true; + } + else + { + currSymbols.push_back(bytes[i]); + } + } + return true; +} + +std::vector getLosFromInstructions(std::vector instructions) +{ + std::vector loVec; + for (ShortCompressionInstruction instruction : instructions) + { + for (unsigned char uc : instruction.loBytes) + loVec.push_back(uc); + } + return loVec; +} + +std::vector getSymsFromInstructions(std::vector instructions) +{ + std::vector symvec; + for (ShortCompressionInstruction instruction : instructions) + { + for (unsigned short uc : instruction.symShorts) + symvec.push_back(uc); + } + return symvec; +} + +std::vector decodeBytesShort(std::vector *pLoVec, std::vector *pSymVec) +{ + std::vector decodedImage; + size_t loIndex = 0; + size_t symIndex = 0; + while (loIndex < pLoVec->size()) + { + size_t currLength = 0; + size_t currOffset = 0; + currLength += (*pLoVec)[loIndex] & LO_LOW_BITS_MASK; + loIndex++; + if (((*pLoVec)[loIndex-1] & LO_CONTINUE_BIT) == LO_CONTINUE_BIT) + { + currLength += (*pLoVec)[loIndex] << LO_NUM_LOW_BITS; + loIndex++; + } + currOffset += (*pLoVec)[loIndex] & LO_LOW_BITS_MASK; + loIndex++; + if (((*pLoVec)[loIndex-1] & LO_CONTINUE_BIT) == LO_CONTINUE_BIT) + { + currOffset += (*pLoVec)[loIndex] << LO_NUM_LOW_BITS; + loIndex++; + } + if (currLength != 0) + { + decodedImage.push_back((*pSymVec)[symIndex]); + symIndex++; + for (size_t i = 0; i < currLength; i++) + decodedImage.push_back(decodedImage[decodedImage.size() - currOffset]); + } + else + { + for (size_t i = 0; i < currOffset; i++) + { + decodedImage.push_back((*pSymVec)[symIndex]); + symIndex++; + } + } + } + return decodedImage; +} + +bool verifyBytesShort(std::vector *pLoVec, std::vector *pSymVec, std::vector *pImage) +{ + std::vector shorts = decodeBytesShort(pLoVec, pSymVec); + return compareVectorsShort(&shorts, pImage); +} + +bool compareVectorsShort(std::vector *pVec1, std::vector *pVec2) +{ + if (pVec1->size() != pVec2->size()) + return false; + for (size_t i = 0; i < pVec1->size(); i++) + if ((*pVec1)[i] != (*pVec2)[i]) + return false; + return true; +} + +std::vector readFileAsUC(std::string filePath) +{ + std::ifstream iStream; + iStream.open(filePath.c_str(), std::ios::binary); + if (!iStream.is_open()) + { + fprintf(stderr, "Error: Couldn't open %s for reading bytes\n", filePath.c_str()); + return std::vector(0); + } + iStream.ignore( std::numeric_limits::max() ); + std::streamsize size = iStream.gcount(); + iStream.clear(); + iStream.seekg( 0, std::ios_base::beg ); + std::vector ucVec(size); + iStream.read((char*)(&ucVec[0]), size); + iStream.close(); + return ucVec; +} + +CompressedImage processImage(std::string fileName, InputSettings settings) +{ + CompressedImage image; + std::vector input = readFileAsUC(fileName); + if (settings.useFrames) + { + /* + // Determine number of frames + size_t totalPixels = input.size()*2; + // Split input and append + size_t smallFrames = totalPixels/OVERWORLD_16X16; + size_t largeFrames = totalPixels/OVERWORLD_32X32; + */ + } + else + { + image = processImageData(input, settings, fileName); + } + return image; +} + +CompressedImage processImageFrames(std::string fileName, InputSettings settings) +{ + CompressedImage image; + std::vector input = readFileAsUC(fileName); + std::vector> allInputs(4); + size_t totalSize = input.size(); + size_t partialSize = totalSize/4; + size_t subIndex = 0; + size_t inputIndex = 0; + std::vector frameOffsets; + for (unsigned char currChar : input) + { + frameOffsets.push_back(image.otherBits.size()); + if (subIndex == partialSize) + { + subIndex = 0; + inputIndex++; + } + allInputs[inputIndex].push_back(currChar); + subIndex++; + } + for (size_t i = 0; i < 4; i++) + { + CompressedImage tempImage = processImageData(allInputs[i], settings, fileName); + for (unsigned int currVal : tempImage.writeVec) + image.otherBits.push_back(currVal); + } + unsigned int header = IS_FRAME_CONTAINER; + image.writeVec.push_back(header); + for (size_t i = 0; i < 4; i++) + image.writeVec.push_back((unsigned int)frameOffsets[i]); + for (unsigned int currVal : image.otherBits) + image.writeVec.push_back(currVal); + image.isValid = true; + + return image; +} + +CompressedImage processImageData(std::vector input, InputSettings settings, std::string fileName) +{ + CompressedImage bestImage; + CompressionMode someMode; + bool hasImage = false; + std::vector rawBase = input; + std::vector usBase(rawBase.size()/2); + memcpy(usBase.data(), rawBase.data(), rawBase.size()); + size_t baseLZsize = 0; + bool byteFail = false; + bool copyFail = false; + bool compressionFail = false; + bool uIntConversionFail = false; + if (settings.shouldCompare) + { + std::string lzName = fileName + ".lz"; + baseLZsize = getFileSize(lzName); + } + std::vector bestLO; + std::vector bestSym; + std::vector bestInstructions; + for (size_t minCodeLength = 2; minCodeLength <= 15; minCodeLength++) + { + std::vector shortCopies = getShortCopies(usBase, minCodeLength); + if (!verifyShortCopies(&shortCopies, &usBase)) + { + copyFail = true; + continue; + } + std::vector shortInstructions = getShortInstructions(shortCopies, minCodeLength-1); + std::vector loVec = getLosFromInstructions(shortInstructions); + std::vector symVec = getSymsFromInstructions(shortInstructions); + if (!verifyBytesShort(&loVec, &symVec, &usBase)) + { + byteFail = true; + continue; + } + CompressionMode mode = BASE_ONLY; + //std::vector modesToUse = {ENCODE_SYMS}; + std::vector modesToUse = {BASE_ONLY, ENCODE_SYMS, ENCODE_DELTA_SYMS, ENCODE_LO, ENCODE_BOTH, ENCODE_BOTH_DELTA_SYMS}; + if (fileName.find("test/compression/") != std::string::npos) + { + if (fileName.find("mode_0.4bpp") != std::string::npos) + modesToUse = {BASE_ONLY}; + else if (fileName.find("mode_1.4bpp") != std::string::npos) + modesToUse = {ENCODE_SYMS}; + else if (fileName.find("mode_2.4bpp") != std::string::npos) + modesToUse = {ENCODE_DELTA_SYMS}; + else if (fileName.find("mode_3.4bpp") != std::string::npos) + modesToUse = {ENCODE_LO}; + else if (fileName.find("mode_4.4bpp") != std::string::npos) + modesToUse = {ENCODE_BOTH}; + else if (fileName.find("mode_5.4bpp") != std::string::npos) + modesToUse = {ENCODE_BOTH_DELTA_SYMS}; + else if (fileName.find("test/compression/table_") != std::string::npos) + modesToUse = {ENCODE_SYMS}; + + if (modesToUse.size() == 1) + { + settings.canDeltaSyms = true; + settings.canEncodeLO = true; + settings.canEncodeSyms = true; + } + } + + for (CompressionMode currMode : modesToUse) + { + mode = currMode; + if (!settings.canDeltaSyms + && (mode == ENCODE_DELTA_SYMS + || mode == ENCODE_BOTH_DELTA_SYMS)) + continue; + if (!settings.canEncodeLO + && (mode == ENCODE_LO + || mode == ENCODE_BOTH + || mode == ENCODE_BOTH_DELTA_SYMS)) + continue; + if (!settings.canEncodeSyms + && (mode == ENCODE_SYMS + || mode == ENCODE_BOTH + || mode == ENCODE_DELTA_SYMS + || mode == ENCODE_BOTH_DELTA_SYMS)) + continue; + CompressedImage image = fillCompressVecNew(loVec, symVec, mode,rawBase.size(), fileName); + if (!verifyCompressionShort(&image, &usBase)) + { + compressionFail = true; + continue; + } + std::vector uiVec = getUIntVecFromData(&image); + std::vector decodedImage = readRawDataVecs(&uiVec); + if (!compareVectorsShort(&decodedImage, &usBase)) + { + uIntConversionFail = true; + continue; + } + image.compressedSize = uiVec.size() * 4; + if (!hasImage) + { + bestLO = loVec; + bestSym = symVec; + bestInstructions = shortInstructions; + bestImage = image; + hasImage = true; + bestImage.writeVec = uiVec; + someMode = mode; + } + else if (image.compressedSize < bestImage.compressedSize) + { + bestLO = loVec; + bestSym = symVec; + bestInstructions = shortInstructions; + bestImage = image; + hasImage = true; + bestImage.writeVec = uiVec; + someMode = mode; + } + } + } + bestImage.mode = someMode; + bestImage.fileName = fileName; + bestImage.lzSize = baseLZsize; + bestImage.rawNumBytes = rawBase.size(); + if (hasImage) + bestImage.isValid = true; + else + { + fprintf(stderr, "Failed to compress image %s\nErrors: ", fileName.c_str()); + if (copyFail) + fprintf(stderr, "CopyProcessing "); + if (byteFail) + fprintf(stderr, "ByteConversion "); + if (compressionFail) + fprintf(stderr, "Compression "); + if (uIntConversionFail) + fprintf(stderr, "uIntConversion "); + printf("\n"); + } + return bestImage; +} + +CompressedImage getDataFromUIntVec(std::vector *pInput) +{ + CompressedImage image = readNewHeader(pInput); + + size_t readIndex = 2; + + bool loEncoded = isModeLoEncoded(image.mode); + bool symEncoded = isModeSymEncoded(image.mode); + + if (loEncoded) + { + image.loFreqs[0] = (*pInput)[readIndex]; + image.loFreqs[1] = (*pInput)[readIndex + 1]; + image.loFreqs[2] = (*pInput)[readIndex + 2]; + readIndex += 3; + } + if (symEncoded) + { + image.symFreqs[0] = (*pInput)[readIndex]; + image.symFreqs[1] = (*pInput)[readIndex + 1]; + image.symFreqs[2] = (*pInput)[readIndex + 2]; + readIndex += 3; + } + if (loEncoded || symEncoded) + { + for (size_t i = 0; i < image.bitreamSize; i++) + { + image.tANSbits.push_back((*pInput)[readIndex]); + readIndex++; + } + } + std::vector remainders; + while (readIndex < pInput->size()) + { + unsigned int currInt = (*pInput)[readIndex]; + for (size_t i = 0; i < 4; i++) + remainders.push_back((currInt >> (8*i)) & 0xff); + readIndex++; + } + size_t remIndex = 0; + if (!symEncoded) + { + for (size_t i = 0; i < image.symSize; i++) + { + unsigned short currSym = remainders[remIndex]; + remIndex++; + currSym += remainders[remIndex] << 8; + remIndex++; + image.symVec.push_back(currSym); + } + } + if (!loEncoded) + { + for (size_t i = 0; i < image.loSize; i++) + { + unsigned char currChar = remainders[remIndex]; + remIndex++; + image.loVec.push_back(currChar); + } + } + + return image; +} + +bool verifyCompressionShort(CompressedImage *pInput, std::vector *pImage) +{ + std::vector decodedImage = decodeImageShort(pInput); + return compareVectorsShort(&decodedImage, pImage); +} + +std::vector decodeImageShort(CompressedImage *pInput) +{ + DataVecs dataVecs = decodeDataVectorsNew(pInput); + return decodeBytesShort(&dataVecs.loVec, &dataVecs.symVec); +} + +DataVecs decodeDataVectorsNew(CompressedImage *pInput) +{ + CompressedImage headerValues = readNewHeader(&pInput->headers); + size_t loSize = headerValues.loSize; + size_t symSize = headerValues.symSize; + CompressionMode mode = headerValues.mode; + bool loEncoded = isModeLoEncoded(mode); + bool symEncoded = isModeSymEncoded(mode); + bool symDelta = isModeSymDelta(mode); + std::vector loFreqs = unpackFrequencies(&pInput->loFreqs[0]); + std::vector symFreqs = unpackFrequencies(&pInput->symFreqs[0]); + std::vector symbols = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::vector loDecode(TANS_TABLE_SIZE); + std::vector symDecode(TANS_TABLE_SIZE); + + std::vector loVec(loSize); + std::vector symVec(symSize); + std::vector loNibbles(loSize*2); + std::vector symNibbles(symSize*4); + + if (loEncoded) + { + size_t currCol = 0; + for (size_t i = 0; i < 16; i++) + { + for (size_t j = 0; j < loFreqs[i]; j++) + { + loDecode[currCol].state = TANS_TABLE_SIZE + currCol; + loDecode[currCol].symbol = i; + loDecode[currCol].y = loFreqs[i] + j; + int currK = 0; + while ((loDecode[currCol].y << currK) < TANS_TABLE_SIZE) + currK++; + loDecode[currCol].k = currK; + currCol++; + } + } + } + if (symEncoded) + { + size_t currCol = 0; + for (size_t i = 0; i < 16; i++) + { + for (size_t j = 0; j < symFreqs[i]; j++) + { + symDecode[currCol].state = TANS_TABLE_SIZE + currCol; + symDecode[currCol].symbol = i; + symDecode[currCol].y = symFreqs[i] + j; + int currK = 0; + while ((symDecode[currCol].y << currK) < TANS_TABLE_SIZE) + currK++; + symDecode[currCol].k = currK; + currCol++; + } + } + } + + std::vector allBits(pInput->tANSbits.size()*32); + size_t currIndex = 0; + for (unsigned int ui : pInput->tANSbits) + for (size_t i = 0; i < 32; i++) + { + unsigned int currVal = (ui >> i) & 0x1; + allBits[currIndex] = currVal; + currIndex++; + } + + if (!symEncoded) + for (size_t i = 0; i < symSize; i++) + symVec[i] = pInput->symVec[i]; + if (!loEncoded) + for (size_t i = 0; i < loSize; i++) + loVec[i] = pInput->loVec[i]; + + size_t bitIndex = 0; + int currState = pInput->initialState; + if (loEncoded) + { + bitIndex = decodeNibbles(loDecode, &allBits, &currState, &loNibbles, bitIndex, loSize*2); + } + if (loEncoded) + for (size_t i = 0; i < loVec.size(); i++) + loVec[i] = loNibbles[2*i] + (loNibbles[2*i + 1] << 4); + + if (symEncoded) + { + bitIndex = decodeNibbles(symDecode, &allBits, &currState, &symNibbles, bitIndex, symSize*4); + if (symDelta) + deltaDecode(&symNibbles, symNibbles.size()); + } + if (symEncoded) + for (size_t i = 0; i < symVec.size(); i++) + for (size_t j = 0; j < 4; j++) + symVec[i] += (unsigned short)symNibbles[i*4 + j] << (j*4); + + DataVecs returnData; + returnData.loVec = loVec; + returnData.symVec = symVec; + return returnData; +} + +void analyzeImages(std::vector *allImages, std::mutex *imageMutex, FileDispatcher *dispatcher, std::mutex *dispatchMutex, InputSettings settings) +{ + std::string fileName = "Initial Value"; + while (fileName != "") + { + dispatchMutex->lock(); + fileName = dispatcher->requestFileName(); + dispatchMutex->unlock(); + if (fileName == "") + break; + std::string uncompressedFileName = fileName.substr(0, fileName.size()-3); + CompressedImage currImage = processImage(uncompressedFileName, settings); + + imageMutex->lock(); + allImages->push_back(currImage); + imageMutex->unlock(); + } +} + +ShortCopy::ShortCopy() {} +ShortCopy::ShortCopy(size_t index, size_t length, size_t offset, std::vector usSequence) +{ + this->index = index; + this->length = length; + this->offset = offset; + this->usSequence = usSequence; +} + +std::vector getNormalizedCounts(std::vector input) +{ + std::vector tempVec(16); + for (size_t i = 0; i < input.size(); i++) + tempVec[i] = input[i]; + tempVec = normalizeCounts(tempVec, TANS_TABLE_SIZE); + bool shouldAdjust = false; + for (int i = 0; i < 16; i++) + if (tempVec[i] == TANS_TABLE_SIZE) + { + shouldAdjust = true; + tempVec[i]--; + } + if (shouldAdjust) + for (size_t i = 0; i < 16; i++) + if (tempVec[i] == 0) + { + tempVec[i]++; + break; + } + std::vector returnVec(16); + for (size_t i = 0; i < 16; i++) + returnVec[i] = tempVec[i]; + return returnVec; +} + +std::vector getFreqWriteInts(std::vector input) +{ + std::vector returnVec(3); + for (size_t i = 0; i < 5; i++) + { + unsigned int val1 = input[i]; + unsigned int val2 = input[5 + i]; + unsigned int val3 = input[10 + i]; + val1 = val1 << (i*6); + val2 = val2 << (i*6); + val3 = val3 << (i*6); + returnVec[0] += val1; + returnVec[1] += val2; + returnVec[2] += val3; + } + unsigned int lastVal = input[15]; + returnVec[0] += (lastVal & 0x3) << 30; + returnVec[1] += (lastVal & 0xc) << 28; + returnVec[2] += (lastVal & 0x30) << 26; + return returnVec; +} + +std::vector unpackFrequencies(unsigned int pInts[3]) +{ + std::vector returnVec; + int freq15 = 0; + for (size_t i = 0; i < 3; i++) + { + for (size_t j = 0; j < 5; j++) + { + int currVal = (pInts[i] >> (6*j)) & 0x3f; + returnVec.push_back(currVal); + } + freq15 += ((pInts[i] >> 30) & 0x3) << (2*i); + } + returnVec.push_back(freq15); + return returnVec; +} + +int findInitialState(EncodeCol encodeCol, unsigned char firstSymbol) +{ + for (size_t i = 0; i < encodeCol.symbols.size(); i++) + { + if (encodeCol.symbols[i].symbol == firstSymbol) + return encodeCol.symbols[i].nextState; + } + return -1; +} +/* + mode 5 + + state 6 11 + bitstream 12 23 8628 max so far, divide by 4 + loLength 12 23 2922 max so far + symLength 14 37 14k max so far + imageSize 10 47 16384 max so far, divide by 16 + + u32:5 mode+lz + u32:10 image size, divided by 32 + u32:14 symlength, divided by 2 + + u32:6 state + u32:12 bitstream, in ints + u32:12 loLength, in bytes +*/ +std::vector getNewHeaders(CompressionMode mode, size_t imageSize, size_t symLength, int initialState, size_t bitstreamSize, size_t loLength) +{ + if (initialState == -1) + initialState = 0; + std::vector returnVec(2); + + returnVec[0] += (unsigned int)mode; // 4 bits + returnVec[0] += (imageSize/IMAGE_SIZE_MODIFIER) << IMAGE_SIZE_OFFSET; // 14 bits + returnVec[0] += (symLength) << SYM_SIZE_OFFSET; // 14 bits + // 32 total + + returnVec[1] += initialState; // 6 bits + returnVec[1] += bitstreamSize << BITSTREAM_SIZE_OFFSET; // 13 bits + returnVec[1] += loLength << LO_SIZE_OFFSET; // 13 bits + + return returnVec; +} + +CompressedImage readNewHeader(std::vector *pInput) +{ + CompressedImage image; + std::vector headers(2); + headers[0] = (*pInput)[0]; + headers[1] = (*pInput)[1]; + image.mode = (CompressionMode)(headers[0] & MODE_MASK); + image.rawNumBytes = ((headers[0] >> IMAGE_SIZE_OFFSET) & IMAGE_SIZE_MASK) * IMAGE_SIZE_MODIFIER; + image.symSize = ((headers[0] >> SYM_SIZE_OFFSET) & SYM_SIZE_MASK); + + image.initialState = headers[1] & INITIAL_STATE_MASK; + image.bitreamSize = (headers[1] >> BITSTREAM_SIZE_OFFSET) & BITSTREAM_SIZE_MASK; + image.loSize = (headers[1] >> LO_SIZE_OFFSET) & LO_SIZE_MASK; + image.headers = headers; + return image; +} + +InputSettings::InputSettings() {} + +InputSettings::InputSettings(bool canEncodeLO, bool canEncodeSyms, bool canDeltaSyms) +{ + this->canEncodeLO = canEncodeLO; + this->canEncodeSyms = canEncodeSyms; + this->canDeltaSyms = canDeltaSyms; +} + +std::vector getUIntVecFromData(CompressedImage *pImage) +{ + CompressedImage otherImage = readNewHeader(&pImage->headers); + std::vector returnVec; + returnVec.push_back(pImage->headers[0]); + returnVec.push_back(pImage->headers[1]); + if (isModeLoEncoded(otherImage.mode)) + for (size_t i = 0; i < 3; i++) + returnVec.push_back(pImage->loFreqs[i]); + if (isModeSymEncoded(otherImage.mode)) + for (size_t i = 0; i < 3; i++) + returnVec.push_back(pImage->symFreqs[i]); + if (isModeLoEncoded(otherImage.mode) || isModeSymEncoded(otherImage.mode)) + for (unsigned int ui : pImage->tANSbits) + returnVec.push_back(ui); + unsigned int currInt = 0; + unsigned int currOffset = 0; + if (!isModeSymEncoded(otherImage.mode)) + { + for (size_t i = 0; i < pImage->symVec.size(); i++) + { + currInt += pImage->symVec[i] << (8*(currOffset % 4)); + currOffset += 2; + if (currOffset % 4 == 0) + { + returnVec.push_back(currInt); + currInt = 0; + } + } + } + if (!isModeLoEncoded(otherImage.mode)) + { + for (size_t i = 0; i < pImage->loVec.size(); i++) + { + currInt += 0; + currInt += pImage->loVec[i] << (8*(currOffset % 4)); + currOffset++; + if (currOffset % 4 == 0) + { + returnVec.push_back(currInt); + currInt = 0; + } + } + } + if (currOffset != 0) + returnVec.push_back(currInt); + return returnVec; +} + +bool verifyUIntVecShort(std::vector *pInput, std::vector *pImage) +{ + CompressedImage image = getDataFromUIntVec(pInput); + return verifyCompressionShort(&image, pImage); +} + +std::vector readFileAsUInt(std::string filePath) +{ + std::vector returnVec; + std::vector ucVec; + std::ifstream iStream; + iStream.open(filePath.c_str(), std::ios::binary); + if (!iStream.is_open()) + { + fprintf(stderr, "Error: Couldn't open file %s for reading\n", filePath.c_str()); + return returnVec; + } + iStream.ignore( std::numeric_limits::max() ); + std::streamsize size = iStream.gcount(); + ucVec.resize(size); + iStream.clear(); + iStream.seekg( 0, std::ios_base::beg ); + iStream.read((char*)(&ucVec[0]), size); + iStream.close(); + unsigned int *pUInt = reinterpret_cast(ucVec.data()); + for (size_t i = 0; i < ucVec.size()/4; i++) + returnVec.push_back(pUInt[i]); + return returnVec; +} + +bool isModeLoEncoded(CompressionMode mode) +{ + if (mode == ENCODE_LO + || mode == ENCODE_BOTH + || mode == ENCODE_BOTH_DELTA_SYMS) + return true; + return false; +} + +bool isModeSymEncoded(CompressionMode mode) +{ + if (mode == ENCODE_SYMS + || mode == ENCODE_DELTA_SYMS + || mode == ENCODE_BOTH + || mode == ENCODE_BOTH_DELTA_SYMS) + return true; + return false; +} + +bool isModeSymDelta(CompressionMode mode) +{ + if (mode == ENCODE_DELTA_SYMS + || mode == ENCODE_BOTH_DELTA_SYMS) + return true; + return false; +} + +CompressedImage fillCompressVecNew(std::vector loVec, std::vector symVec, CompressionMode mode, size_t imageBytes, std::string name) +{ + CompressedImage image; + bool loEncoded = isModeLoEncoded(mode); + bool symEncoded = isModeSymEncoded(mode); + bool symDelta = isModeSymDelta(mode); + + std::vector loNibbles(2*loVec.size()); + std::vector symNibbles(4*symVec.size()); + std::vector loDecode(TANS_TABLE_SIZE); + std::vector symDecode(TANS_TABLE_SIZE); + std::vector symbols = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + if (loEncoded) + { + for (size_t i = 0; i < loVec.size(); i++) + { + loNibbles[2*i] = (loVec)[i] & 0xf; + loNibbles[2*i + 1] = ((loVec)[i] >> 4) & 0xf; + } + std::vector loCounts(16); + for (unsigned char uc : loNibbles) + loCounts[uc]++; + std::vector freqsToUse = getNormalizedCounts(loCounts); + std::vector freqs = getFreqWriteInts(freqsToUse); + image.loFreqs[0] = freqs[0]; + image.loFreqs[1] = freqs[1]; + image.loFreqs[2] = freqs[2]; + size_t currCol = 0; + for (size_t i = 0; i < 16; i++) + { + for (size_t j = 0; j < freqsToUse[i]; j++) + { + loDecode[currCol].state = TANS_TABLE_SIZE + currCol; + loDecode[currCol].symbol = i; + loDecode[currCol].y = freqsToUse[i] + j; + int currK = 0; + while ((loDecode[currCol].y << currK) < TANS_TABLE_SIZE) + currK++; + loDecode[currCol].k = currK; + currCol++; + } + } + } + if (symEncoded) + { + for (size_t i = 0; i < symVec.size(); i++) + { + for (size_t j = 0; j < 4; j++) + symNibbles[4*i + j] = (symVec[i] >> (4*j)) & 0xf; + } + std::vector symCounts(16); + if (symDelta) + deltaEncode(&symNibbles, symNibbles.size()); + for (unsigned char uc : symNibbles) + symCounts[uc]++; + std::vector freqsToUse = getNormalizedCounts(symCounts); + freqsToUse = getTestFreqs(freqsToUse, name); + std::vector freqs = getFreqWriteInts(freqsToUse); + image.symFreqs[0] = freqs[0]; + image.symFreqs[1] = freqs[1]; + image.symFreqs[2] = freqs[2]; + size_t currCol = 0; + for (size_t i = 0; i < 16; i++) + { + for (size_t j = 0; j < freqsToUse[i]; j++) + { + symDecode[currCol].state = TANS_TABLE_SIZE + currCol; + symDecode[currCol].symbol = i; + symDecode[currCol].y = freqsToUse[i] + j; + int currK = 0; + while ((symDecode[currCol].y << currK) < TANS_TABLE_SIZE) + currK++; + symDecode[currCol].k = currK; + currCol++; + } + } + } + int currState = -1; + std::vector bitstream; + if (symEncoded) + { + std::vector reversedVec; + for (size_t i = 0; i < symNibbles.size(); i++) + reversedVec.push_back(symNibbles[symNibbles.size() - i - 1]); + std::vector symEncode = createEncodingTable(symDecode, symbols); + size_t startIndex = 0; + if (currState == -1) + { + currState = findInitialState(symEncode[0], reversedVec[0]) - TANS_TABLE_SIZE; + startIndex = 1; + } + for (size_t i = startIndex; i < reversedVec.size(); i++) + currState = encodeSingleSymbol(symEncode[currState], reversedVec[i], &bitstream) - TANS_TABLE_SIZE; + } + if (loEncoded) + { + std::vector reversedVec; + for (size_t i = 0; i < loNibbles.size(); i++) + reversedVec.push_back(loNibbles[loNibbles.size() - i - 1]); + std::vector loEncode = createEncodingTable(loDecode, symbols); + size_t startIndex = 0; + if (currState == -1) + { + currState = findInitialState(loEncode[0], reversedVec[0]) - TANS_TABLE_SIZE; + startIndex = 1; + } + for (size_t i = startIndex; i < reversedVec.size(); i++) + currState = encodeSingleSymbol(loEncode[currState], reversedVec[i], &bitstream) - TANS_TABLE_SIZE; + } + std::vector reversedBitstream(bitstream.size()); + for (size_t i = 0; i < bitstream.size(); i++) + reversedBitstream[reversedBitstream.size() - 1 - i] = bitstream[i]; + bitstream = reversedBitstream; + std::vector checkBits = bitstream; + int checkState = currState; + + size_t currBitIndex = 0; + if (loEncoded) + { + std::vector checkLoNibbles(loNibbles.size()); + currBitIndex = decodeNibbles(loDecode, &checkBits, &checkState, &checkLoNibbles, currBitIndex, loNibbles.size()); + for (size_t i = 0; i < loNibbles.size(); i++) + if (loNibbles[i] != checkLoNibbles[i]) + { + fprintf(stderr, "LO Mismatch\n"); + break; + } + } + if (symEncoded) + { + std::vector checkSymNibbles(symNibbles.size()); + currBitIndex = decodeNibbles(symDecode, &checkBits, &checkState, &checkSymNibbles, currBitIndex, symNibbles.size()); + for (size_t i = 0; i < symNibbles.size(); i++) + if (symNibbles[i] != checkSymNibbles[i]) + { + fprintf(stderr, "Symbol Mismatch\n"); + break; + } + } + + std::vector tANSbits; + unsigned int currInt = 0; + for (size_t i = 0; i < bitstream.size(); i++) + { + currInt += bitstream[i] << (i%32); + if ((i+1) % 32 == 0) + { + tANSbits.push_back(currInt); + currInt = 0; + } + } + if (bitstream.size() % 32 != 0) + tANSbits.push_back(currInt); + image.headers = getNewHeaders(mode, imageBytes, symVec.size(), currState, tANSbits.size(), loVec.size()); + image.tANSbits = tANSbits; + image.symVec = symVec; + image.loVec = loVec; + image.initialState = currState; + return image; +} + +size_t decodeNibbles(std::vector decodeTable, std::vector *bits, int *currState, std::vector *nibbleVec, size_t currBitIndex, size_t numNibbles) +{ + for (size_t i = 0; i < numNibbles; i++) + { + (*nibbleVec)[i] = decodeTable[*currState].symbol; + int currK = decodeTable[*currState].k; + int nextState = decodeTable[*currState].y << currK; + for (size_t j = 0; j < currK; j++) + { + nextState += (*bits)[currBitIndex] << j; + currBitIndex++; + } + *currState = nextState - TANS_TABLE_SIZE; + } + return currBitIndex; +} + +std::vector readRawDataVecs(std::vector *pInput) +{ + std::vector imageVec; + CompressedImage readImage = readNewHeader(pInput); + bool loEncoded = isModeLoEncoded(readImage.mode); + bool symEncoded = isModeSymEncoded(readImage.mode); + bool symDelta = isModeSymDelta(readImage.mode); + size_t readIndex = 2; + std::vector tANSbits; + std::vector allBits; + std::vector symVec(readImage.symSize); + std::vector loVec(readImage.loSize); + std::vector symDecode(TANS_TABLE_SIZE); + std::vector loDecode(TANS_TABLE_SIZE); + int currState = readImage.initialState; + if (loEncoded) + { + for (size_t i = 0; i < 3; i++) + readImage.loFreqs[i] = (*pInput)[readIndex + i]; + readIndex += 3; + std::vector loFreqs = unpackFrequencies(&readImage.loFreqs[0]); + size_t currCol = 0; + for (size_t i = 0; i < 16; i++) + { + for (size_t j = 0; j < loFreqs[i]; j++) + { + loDecode[currCol].state = TANS_TABLE_SIZE + currCol; + loDecode[currCol].symbol = i; + loDecode[currCol].y = loFreqs[i] + j; + int currK = 0; + while ((loDecode[currCol].y << currK) < TANS_TABLE_SIZE) + currK++; + loDecode[currCol].k = currK; + currCol++; + } + } + } + if (symEncoded) + { + for (size_t i = 0; i < 3; i++) + readImage.symFreqs[i] = (*pInput)[readIndex + i]; + readIndex += 3; + std::vector symFreqs = unpackFrequencies(&readImage.symFreqs[0]); + size_t currCol = 0; + for (size_t i = 0; i < 16; i++) + { + for (size_t j = 0; j < symFreqs[i]; j++) + { + symDecode[currCol].state = TANS_TABLE_SIZE + currCol; + symDecode[currCol].symbol = i; + symDecode[currCol].y = symFreqs[i] + j; + int currK = 0; + while ((symDecode[currCol].y << currK) < TANS_TABLE_SIZE) + currK++; + symDecode[currCol].k = currK; + currCol++; + } + } + } + if (loEncoded || symEncoded) + { + tANSbits.resize(readImage.bitreamSize); + for (size_t i = 0; i < readImage.bitreamSize; i++) + tANSbits[i] = (*pInput)[readIndex + i]; + readIndex += readImage.bitreamSize; + allBits.resize(tANSbits.size()*32); + size_t currIndex = 0; + for (unsigned int ui : tANSbits) + { + for (size_t i = 0; i < 32; i++) + { + unsigned int currVal = (ui >> i) & 0x1; + allBits[currIndex] = currVal; + currIndex++; + } + } + } + bool leftOverValues = false; + if (!symEncoded) + { + for (size_t i = 0; i < readImage.symSize; i++) + { + symVec[i] = ((*pInput)[readIndex] >> (16*(i%2))) & 0xffff; + if ((i+1) % 2 == 0) + { + readIndex++; + leftOverValues = false; + } + else + { + leftOverValues = true; + } + } + } + if (!loEncoded) + { + size_t offsetMod = 0; + if (leftOverValues) + offsetMod = 2; + for (size_t i = 0; i < readImage.loSize; i++) + { + loVec[i] = ((*pInput)[readIndex] >> (8*((i%4) + offsetMod))) & 0xff; + if ((i+offsetMod+1) % 4 == 0) + readIndex++; + } + } + size_t bitIndex = 0; + if (loEncoded) + { + std::vector loNibbles(readImage.loSize*2); + bitIndex = decodeNibbles(loDecode, &allBits, &currState, &loNibbles, bitIndex, readImage.loSize*2); + for (size_t i = 0; i < readImage.loSize; i++) + loVec[i] = loNibbles[2*i] + (loNibbles[2*i + 1] << 4); + } + if (symEncoded) + { + std::vector symNibbles(readImage.symSize*4); + bitIndex = decodeNibbles(symDecode, &allBits, &currState, &symNibbles, bitIndex, readImage.symSize*4); + if (symDelta) + deltaDecode(&symNibbles, symNibbles.size()); + for (size_t i = 0; i < readImage.symSize; i++) + for (size_t j = 0; j < 4; j++) + symVec[i] += (unsigned short)symNibbles[i*4 + j] << (4*j); + } + imageVec = decodeBytesShort(&loVec, &symVec); + return imageVec; +} + +void deltaEncode(std::vector *buffer, int length) +{ + unsigned char last = 0; + for (int i = 0; i < length; i++) + { + unsigned char current =(*buffer)[i]; + (*buffer)[i] = (current-last) & 0xf; + last = current; + } +} + +void deltaDecode(std::vector *buffer, int length) +{ + unsigned char last = 0; + for (int i = 0; i < length; i++) + { + unsigned char delta =(*buffer)[i]; + (*buffer)[i] = (delta+last) & 0xf; + last = (*buffer)[i]; + } +} + +std::vector getTestFreqs(std::vector freqs, std::string name) +{ + if (name.find("test/compression/table_") == std::string::npos) + return freqs; + if (name.find("table_63_1") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 63; + freqs[1] = 1; + } + if (name.find("table_62_2") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 62; + freqs[1] = 2; + } + if (name.find("table_61_3") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 61; + freqs[1] = 3; + } + if (name.find("table_60_4") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 60; + freqs[1] = 4; + } + if (name.find("table_59_5") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 59; + freqs[1] = 5; + } + if (name.find("table_58_6") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 58; + freqs[1] = 6; + } + if (name.find("table_57_7") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 57; + freqs[1] = 7; + } + if (name.find("table_56_8") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 56; + freqs[1] = 8; + } + if (name.find("table_55_9") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 55; + freqs[1] = 9; + } + if (name.find("table_54_10") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 54; + freqs[1] = 10; + } + if (name.find("table_53_11") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 53; + freqs[1] = 11; + } + if (name.find("table_52_12") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 52; + freqs[1] = 12; + } + if (name.find("table_51_13") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 51; + freqs[1] = 13; + } + if (name.find("table_50_14") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 50; + freqs[1] = 14; + } + if (name.find("table_49_15") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 49; + freqs[1] = 15; + } + if (name.find("table_48_16") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 48; + freqs[1] = 16; + } + if (name.find("table_47_17") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 47; + freqs[1] = 17; + } + if (name.find("table_46_18") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 46; + freqs[1] = 18; + } + if (name.find("table_45_19") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 45; + freqs[1] = 19; + } + if (name.find("table_44_20") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 44; + freqs[1] = 20; + } + if (name.find("table_43_21") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 43; + freqs[1] = 21; + } + if (name.find("table_42_22") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 42; + freqs[1] = 22; + } + if (name.find("table_41_23") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 41; + freqs[1] = 23; + } + if (name.find("table_40_24") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 40; + freqs[1] = 24; + } + if (name.find("table_39_25") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 39; + freqs[1] = 25; + } + if (name.find("table_38_26") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 38; + freqs[1] = 26; + } + if (name.find("table_37_27") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 37; + freqs[1] = 27; + } + if (name.find("table_36_28") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 36; + freqs[1] = 28; + } + if (name.find("table_35_29") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 35; + freqs[1] = 29; + } + if (name.find("table_34_30") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 34; + freqs[1] = 30; + } + if (name.find("table_33_31") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 33; + freqs[1] = 31; + } + if (name.find("table_32_32") != std::string::npos) + { + freqs.clear(); + freqs.resize(16); + freqs[0] = 32; + freqs[1] = 32; + } + return freqs; +} diff --git a/tools/compresSmol/compressAlgo.h b/tools/compresSmol/compressAlgo.h new file mode 100644 index 000000000000..8141e83a7ccb --- /dev/null +++ b/tools/compresSmol/compressAlgo.h @@ -0,0 +1,177 @@ +#ifndef COMPRES_SMOL +#define COMPRES_SMOL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "fileDispatcher.h" +#include "tANS.h" + +#define OVERWORLD_16X16 256 +#define OVERWORLD_32X32 1024 + +#define TANS_TABLE_SIZE 64 +#define LO_CONTINUE_BIT 0x80 +#define LO_LOW_BITS_MASK 0x7f +#define LO_NUM_LOW_BITS 0x7 +#define BYTE_MASK 0xff +#define SHORT_MASK 0xffff +#define NIBBLE_MASK 0xf +#define NUM_SHORT_BITS 0xf +#define LENGTH_MOD_MASK 0xf +#define INITIAL_STATE_MASK 0x3f +#define MODE_MASK 0x1f +#define IMAGE_SIZE_MASK 0x3fff +#define IMAGE_SIZE_OFFSET 4 +#define SYM_SIZE_MASK 0x3fff +#define SYM_SIZE_OFFSET 18 +#define BITSTREAM_SIZE_MASK 0x1fff +#define BITSTREAM_SIZE_OFFSET 6 +#define LO_SIZE_MASK 0x1fff +#define LO_SIZE_OFFSET 19 + +#define IMAGE_SIZE_MODIFIER 4 + +enum CompressionMode { + LZ77 = 0, + BASE_ONLY = 1, + ENCODE_SYMS = 2, + ENCODE_DELTA_SYMS = 3, + ENCODE_LO = 4, + ENCODE_BOTH = 5, + ENCODE_BOTH_DELTA_SYMS = 6, + IS_FRAME_CONTAINER = 7, +}; + +struct ShortCopy { + size_t index; + size_t length; + size_t offset; + unsigned short firstSymbol; + std::vector usSequence; + ShortCopy(); + ShortCopy(size_t index, size_t length, size_t offset, std::vector usSequence); +}; + +struct CompressionInstruction { + size_t length; + size_t offset; + size_t index; + unsigned char firstSymbol; + std::vector symbols; + std::vector bytes; + void buildBytes(); + bool verifyInstruction(); +}; + +struct ShortCompressionInstruction { + size_t length; + size_t offset; + size_t index; + unsigned short firstSymbol; + std::vector symbols; + std::vector loBytes; + std::vector symShorts; + void buildBytes(); + bool verifyInstruction(); +}; + +struct SortedShortElement { + size_t index; + ShortCopy copy; + bool isRun = false; + bool isCopy = false; + SortedShortElement(); + SortedShortElement(size_t index, ShortCopy copy); +}; + +struct CompressedImage { + std::string fileName; + CompressionMode mode; + size_t lzSize; + size_t loSize; + size_t symSize; + size_t bitreamSize = 0; + size_t rawNumBytes; + int initialState; + std::vector headers; + unsigned int loFreqs[3]; + unsigned int symFreqs[3]; + size_t compressedSize; + bool isValid = false; + std::vector writeVec; + std::vector tANSbits; + std::vector otherBits; + std::vector symVec; + std::vector loVec; +}; + +struct InputSettings { + bool canEncodeLO = true; + bool canEncodeSyms = true; + bool canDeltaSyms = true; + bool shouldCompare = false; + bool useFrames = false; + InputSettings(); + InputSettings(bool canEncodeLO, bool canEncodeSyms, bool canDeltaSyms); +}; + +struct DataVecs { + std::vector loVec; + std::vector symVec; +}; + +void analyzeImages(std::vector *allImages, std::mutex *imageMutex, FileDispatcher *dispatcher, std::mutex *dispatchMutex, InputSettings settings); + +CompressedImage processImage(std::string fileName, InputSettings settings); +CompressedImage processImageFrames(std::string fileName, InputSettings settings); +CompressedImage processImageData(std::vector input, InputSettings settings, std::string fileName); + +std::vector readFileAsUInt(std::string filePath); + +size_t getCompressedSize(CompressedImage *pImage); + +std::vector getShortCopies(std::vector input, size_t minLength); +bool verifyShortCopies(std::vector *pCopies, std::vector *pImage); + +std::vector getNormalizedCounts(std::vector input); +std::vector getFreqWriteInts(std::vector input); +std::vector getNewHeaders(CompressionMode mode, size_t imageSize, size_t symLength, int initialState, size_t bitstreamSize, size_t loLength); +int findInitialState(EncodeCol encodeCol, unsigned char firstSymbol); +CompressedImage fillCompressVecNew(std::vector loVec, std::vector symVec, CompressionMode mode, size_t imageBytes, std::string name); +std::vector getShortInstructions(std::vector copies, size_t lengthMod); +std::vector getLosFromInstructions(std::vector instructions); +std::vector getSymsFromInstructions(std::vector instructions); +std::vector unpackFrequencies(unsigned int pInts[3]); +CompressedImage getDataFromUIntVec(std::vector *pInput); +CompressedImage readNewHeader(std::vector *pInput); +std::vector getUIntVecFromData(CompressedImage *pImage); + +std::vector decodeBytesShort(std::vector *pLoVec, std::vector *pSymVec); +std::vector decodeImageShort(CompressedImage *pInput); +DataVecs decodeDataVectorsNew(CompressedImage *pInput); + +size_t decodeNibbles(std::vector decodeTable, std::vector *bits, int *currState, std::vector *nibbleVec, size_t currBitIndex, size_t numNibbles); + +bool compareVectorsShort(std::vector *pVec1, std::vector *pVec2); + +bool verifyCompressionShort(CompressedImage *pInput, std::vector *pImage); +bool verifyBytesShort(std::vector *pLoVec, std::vector *pSymVec, std::vector *pImage); +bool verifyUIntVecShort(std::vector *pInput, std::vector *pImage); + +std::vector readRawDataVecs(std::vector *pInput); + +bool isModeLoEncoded(CompressionMode mode); +bool isModeSymEncoded(CompressionMode mode); +bool isModeSymDelta(CompressionMode mode); + +void deltaEncode(std::vector *buffer, int length); +void deltaDecode(std::vector *buffer, int length); + +std::vector getTestFreqs(std::vector freqs, std::string name); +#endif diff --git a/tools/compresSmol/compressionTestBuilderLZ.zsh b/tools/compresSmol/compressionTestBuilderLZ.zsh new file mode 100755 index 000000000000..c644e7e7e429 --- /dev/null +++ b/tools/compresSmol/compressionTestBuilderLZ.zsh @@ -0,0 +1,75 @@ +#! /bin/zsh + +echo '#include "global.h"' +echo '#include "main.h"' +echo '#include "malloc.h"' +echo '#include "random.h"' +echo '#include "sprite.h"' +echo '#include "test/test.h"' + +currIt=-1 + +for file in graphics/**/*/anim_front.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.lz");' +done + +for file in graphics/**/*/front.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.lz");' +done + +for file in graphics/**/*/back.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.lz");' +done + +for file in graphics/**/*/anim_frontf.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.lz");' +done + +for file in graphics/**/*/frontf.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.lz");' +done + +for file in graphics/**/*/backf.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.lz");' +done + +echo '' +((currIt+=1)) +echo 'static const u32 *allFiles['$currIt'] =' +((currIt-=1)) +echo '{' +for i in {0..$currIt} +do + echo ' ['$i'] = animFront'$i',' +done +echo '};' +echo '' + +echo 'TEST("Compression test: all sprites, lz")' +echo '{' +echo ' u32 totalTime = 0;' +echo ' for (u32 j = 0; j < '$currIt'; j++)' +echo ' {' +echo ' const u32 *file = allFiles[j];' +echo ' u32 imageSize = GetDecompressedDataSize(file);' +echo ' u32 *compBuffer = Alloc(imageSize);' +echo ' CycleCountStart();' +echo ' DecompressDataWithHeaderWram(file, compBuffer);' +echo ' u32 timeTaken = CycleCountEnd();' +echo ' totalTime += timeTaken;' +echo ' Free(compBuffer);' +echo ' }' +echo ' DebugPrintf("Total time: %u", totalTime);' +echo '}' diff --git a/tools/compresSmol/compressionTestBuilderSmol.zsh b/tools/compresSmol/compressionTestBuilderSmol.zsh new file mode 100755 index 000000000000..3d0d777b53b9 --- /dev/null +++ b/tools/compresSmol/compressionTestBuilderSmol.zsh @@ -0,0 +1,75 @@ +#! /bin/zsh + +echo '#include "global.h"' +echo '#include "main.h"' +echo '#include "malloc.h"' +echo '#include "random.h"' +echo '#include "sprite.h"' +echo '#include "test/test.h"' + +currIt=-1 + +for file in graphics/**/*/anim_front.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.smol");' +done + +for file in graphics/**/*/front.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.smol");' +done + +for file in graphics/**/*/back.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.smol");' +done + +for file in graphics/**/*/anim_frontf.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.smol");' +done + +for file in graphics/**/*/frontf.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.smol");' +done + +for file in graphics/**/*/backf.4bpp.lz; do + ((currIt+=1)) + fileUncomp=${file::-3} + echo 'static const u32 animFront'$currIt'[] = INCBIN_U32("'$fileUncomp'.smol");' +done + +echo '' +((currIt+=1)) +echo 'static const u32 *allFiles['$currIt'] =' +((currIt-=1)) +echo '{' +for i in {0..$currIt} +do + echo ' ['$i'] = animFront'$i',' +done +echo '};' +echo '' + +echo 'TEST("Compression test: all sprites, smol")' +echo '{' +echo ' u32 totalTime = 0;' +echo ' for (u32 j = 0; j < '$currIt'; j++)' +echo ' {' +echo ' const u32 *file = allFiles[j];' +echo ' u32 imageSize = GetDecompressedDataSize(file);' +echo ' u32 *compBuffer = Alloc(imageSize);' +echo ' CycleCountStart();' +echo ' DecompressDataWithHeaderWram(file, compBuffer);' +echo ' u32 timeTaken = CycleCountEnd();' +echo ' totalTime += timeTaken;' +echo ' Free(compBuffer);' +echo ' }' +echo ' DebugPrintf("Total time: %u", totalTime);' +echo '}' diff --git a/tools/compresSmol/fileDispatcher.cpp b/tools/compresSmol/fileDispatcher.cpp new file mode 100644 index 000000000000..099dbad9bbd7 --- /dev/null +++ b/tools/compresSmol/fileDispatcher.cpp @@ -0,0 +1,45 @@ +#include "fileDispatcher.h" + +FileDispatcher::FileDispatcher(std::filesystem::path inPath) +{ + setFilePath(inPath); +} + +void FileDispatcher::setFilePath(std::filesystem::path inPath) +{ + filePath = inPath; +} + +bool FileDispatcher::initFileList() +{ + std::string fileName; + for (const std::filesystem::directory_entry &dirEntry : std::filesystem::recursive_directory_iterator(filePath)) + { + if (dirEntry.is_regular_file()) + { + fileName = dirEntry.path().string(); + if (fileName.find(".4bpp.lz") == std::string::npos) + continue; + } + else + { + continue; + } + fileList.push_back(fileName); + } + + if (fileList.size() == 0) + return false; + else + return true; +} + +std::string FileDispatcher::requestFileName() +{ + if (currentIndex >= fileList.size()) + return ""; + std::string returnString = fileList[currentIndex]; + std::cout << "Dispatching index " << currentIndex << ": " << returnString << "\n"; + currentIndex++; + return returnString; +} diff --git a/tools/compresSmol/fileDispatcher.h b/tools/compresSmol/fileDispatcher.h new file mode 100644 index 000000000000..b9cc549203c2 --- /dev/null +++ b/tools/compresSmol/fileDispatcher.h @@ -0,0 +1,22 @@ +#ifndef FILE_DISPATCHER +#define FILE_DISPATCHER +#include +#include +#include +#include +#include +#include + +class FileDispatcher { + std::vector fileList; + int currentIndex = 0; + std::mutex requestMutex; + std::filesystem::path filePath; +public: + FileDispatcher(); + FileDispatcher(std::filesystem::path inPath); + void setFilePath(std::filesystem::path inPath); + bool initFileList(); + std::string requestFileName(); +}; +#endif diff --git a/tools/compresSmol/tANS.cpp b/tools/compresSmol/tANS.cpp new file mode 100644 index 000000000000..20417ea4f0a5 --- /dev/null +++ b/tools/compresSmol/tANS.cpp @@ -0,0 +1,554 @@ +#include "tANS.h" + +std::vector createDecodingTable(std::vector symbols, std::vector frequencies) +{ + std::vector decodeTable; + + int totalFreq = 0; + std::vector yValueCounting = frequencies; + + for (int freq : frequencies) + totalFreq += freq; + + int indexCounter = 0; + // Create a table with size equal to the total frequencies + for (int i = 0; i < totalFreq; i++) + { + DecodeCol currCol; + int currentSymbolIndex = indexCounter % symbols.size(); + + // Set the state to total frequencies + current index + currCol.state = totalFreq + i; + // Set the symbol to the next valid symbol + currCol.symbol = symbols[currentSymbolIndex]; + // Set the y-value to the frequency of the symbol + number of times used + currCol.y = yValueCounting[currentSymbolIndex]; + // Calculate the k-value, where k is how many times y needs to be doubled + // to be larger or equal to the total frequency count + int k = 0; + int yDoubledk = currCol.y; + while (yDoubledk < totalFreq) + { + k++; + yDoubledk = currCol.y << k; + } + currCol.k = k; + decodeTable.push_back(currCol); + + // Update the y-value counter + yValueCounting[currentSymbolIndex]++; + // Decrease the freq for the symbol of the current table entry + frequencies[currentSymbolIndex]--; + + // Find the next valid symbol to generate a table entry for + indexCounter++; + for (int j = 0; j < symbols.size(); j++) + { + if (frequencies[indexCounter % symbols.size()] != 0) + break; + else + indexCounter++; + } + } + return decodeTable; +} + +std::vector createEncodingTable(std::vector decodeTable, std::vector symbols) +{ + std::vector encodeTable(decodeTable.size()); + for (int i = 0; i < decodeTable.size(); i++) + { + encodeTable[i].state = decodeTable.size() + i; + } + std::vector encodeHelpers; + + // Build the encoding helper tables, one per symbol + for (unsigned char symbol : symbols) + { + EncodeHelper newHelper; + newHelper.symbol = symbol; + encodeHelpers.push_back(newHelper); + } + + for (DecodeCol dCol : decodeTable) + { + unsigned char currSymbol = dCol.symbol; + int symbolIndex = 0; + while (encodeHelpers[symbolIndex].symbol != currSymbol) + { + symbolIndex++; + } + encodeHelpers[symbolIndex].states.push_back(dCol.state); + encodeHelpers[symbolIndex].yVals.push_back(dCol.y); + encodeHelpers[symbolIndex].kVals.push_back(dCol.k); + encodeHelpers[symbolIndex].yPrimVals.push_back(dCol.y << dCol.k); + } + // Build the encoding table, one column per state in decoding table + for (int helperNum = 0; helperNum < encodeHelpers.size(); helperNum++) + { + for (int i = 0; i < encodeHelpers[helperNum].states.size(); i++) + { + EncodeSymbolData currSymbol; + currSymbol.symbol = encodeHelpers[helperNum].symbol; + currSymbol.streamValue = 0; + currSymbol.numBits = encodeHelpers[helperNum].kVals[i]; + currSymbol.nextState = encodeHelpers[helperNum].states[i]; + int currIndex = encodeHelpers[helperNum].yPrimVals[i]-encodeTable.size(); + encodeTable[currIndex].symbols.push_back(currSymbol); + int limit = std::pow(2, currSymbol.numBits); + for (int j = 1; j < limit; j++) + { + currSymbol.streamValue++; + encodeTable[currIndex + j].symbols.push_back(currSymbol); + } + } + } + + return encodeTable; +} + +EncodedData encodeData(std::vector input, std::vector encodingTable) +{ + EncodedData data; + int state; + // Reverse the input, since ANS operates in FILO mode + std::vector reverseInput(input.size()); + for (int i = 0; i < input.size(); i++) + { + reverseInput[input.size() - 1 - i] = input[i]; + } + // Encode the string + int currentOffsetState = 0; + for (int i = 0; i < reverseInput.size(); i++) + { + unsigned char currChar = reverseInput[i]; + // Find correct encoding instruction for the symbol + for (EncodeSymbolData eSymbols : encodingTable[currentOffsetState].symbols) + { + if (eSymbols.symbol == currChar) + { + // Encode the symbol + state = eSymbols.nextState; + if (i == 0) + break; + int streamValue = eSymbols.streamValue; + int compVal = 1; + for (int numBit = eSymbols.numBits-1; numBit >= 0; numBit--) + { + unsigned char currBit = (streamValue >> numBit) & compVal; + data.bitStream.push_back(currBit); + } + break; + } + } + currentOffsetState = state - encodingTable.size(); + } + data.initialState = state; + + return data; +} + +int encodeSingleSymbol(EncodeCol currEncodeCol, unsigned char symbol, std::vector *bitstream) +{ + int newState; + for (EncodeSymbolData eSymbols : currEncodeCol.symbols) + { + if (eSymbols.symbol == symbol) + { + newState = eSymbols.nextState; + int streamValue = eSymbols.streamValue; + int compVal = 1; + for (int numBit = eSymbols.numBits-1; numBit >= 0; numBit--) + { + unsigned char currBit = (streamValue >> numBit) & compVal; + bitstream->push_back(currBit); + } + break; + } + } + return newState; +} + +std::vector decodeData(EncodedData *data, std::vector decodeTable, int numChars) +{ + unsigned int tableSize = decodeTable.size(); + unsigned int state = data->initialState; + std::vector returnVec(numChars); + returnVec[0] = decodeTable[state-tableSize].symbol; + for (int i = 1; i < numChars; i++) + { + unsigned int currY = decodeTable[state-tableSize].y; + unsigned int currK = decodeTable[state-tableSize].k; + unsigned int streamValue = 0; + // Horrible way of reading a value from the bitstream + for (int j = 0; j < currK; j++) + { + unsigned int tempVal; + bool val = data->bitStream.back(); + data->bitStream.pop_back(); + if (val) + tempVal = 1; + else + tempVal = 0; + streamValue += (tempVal << j); + } + // Calculate the next state and retrieve the symbol for that state + state = (currY << currK) + streamValue; + returnVec[i] = decodeTable[state-tableSize].symbol; + } + data->initialState = state; + return returnVec; +} + +std::vector findSymbols(std::vector input) +{ + std::vector symbols = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 , 11, 12, 13, 14, 15}; + return symbols; +} + +std::vector countSymbols(std::vector input, std::vector symbols) +{ + std::vector symbolCounts(symbols.size()); + for (int i = 0; i < input.size(); i++) + { + unsigned char currChar = input[i]; + for (int j = 0; j < symbols.size(); j++) + { + if (currChar == symbols[j]) + { + symbolCounts[j]++; + break; + } + } + } + // Setting found counts to be a minimum of 1 + for (int i = 0; i < symbols.size(); i++) + { + if (symbolCounts[i] == 0) + symbolCounts[i] = 1; + } + return symbolCounts; +} + +std::vector normalizeCounts(std::vector counts, int tableSize) +{ + return normalizeCounts(counts, tableSize, false); +} +std::vector normalizeCounts(std::vector counts, int tableSize, bool fillZeros) +{ + int totalCount = 0; + for (int count : counts) + { + totalCount += count; + } + if (totalCount < tableSize) + { + for (int i = 0; i < counts.size(); i++) + { + counts[i] *= (int)ceil((float)tableSize/(float)totalCount); + } + } + if (fillZeros) + for (int i = 0; i < counts.size(); i++) + if (counts[i] == 0) + counts[i] = 1; + + totalCount = 0; + for (int count : counts) + { + totalCount += count; + } + + bool shouldContinue = true; + std::vector normCounts(counts.size()); + while (shouldContinue) + { + int smallestCount; + int smallestIndex; + int firstIndex; + int largestCount = 0; + for (int i = 0; i < counts.size(); i++) + { + if (counts[i] != 0) + { + firstIndex = i; + smallestIndex = i; + smallestCount = counts[i]; + break; + } + } + for (int i = firstIndex; i < counts.size(); i++) + { + if (counts[i] < smallestCount && counts[i] != 0) + { + smallestCount = counts[i]; + smallestIndex = i; + } + if (counts[i] > largestCount) + { + largestCount = counts[i]; + } + } + if (largestCount == 0) + { + shouldContinue = false; + } + else + { + float frac = float(smallestCount)/float(totalCount); + int newCount = std::round(frac*float(tableSize)); + if (newCount == 0 and counts[smallestIndex] != 0) + { + newCount = 1; + } + normCounts[smallestIndex] = newCount; + tableSize -= newCount; + totalCount -= smallestCount; + counts[smallestIndex] = 0; + } + } + return normCounts; +} + +void printEncodeTable(std::vector encodeTable, std::vector symbols) +{ + printf(" x: "); + for (int i = 0; i < encodeTable.size(); i++) + { + printf("%3zu ", i+encodeTable.size()); + } + printf("\n"); + for (int i = 0; i < symbols.size(); i++) + { + printf("%3hhu s: ", symbols[i]); + for (int k = 0; k < encodeTable.size(); k++) + { + printf("%3i ", encodeTable[k].symbols[i].nextState); + } + printf("\n"); + printf("%3hhu b: ", symbols[i]); + for (int k = 0; k < encodeTable.size(); k++) + { + printf("%3i ", encodeTable[k].symbols[i].streamValue); + } + printf("\n"); + printf("%3hhu k: ", symbols[i]); + for (int k = 0; k < encodeTable.size(); k++) + { + printf("%3i ", encodeTable[k].symbols[i].numBits); + } + printf("\n"); + } +} + +void printDecodeTable(std::vector decodeTable) +{ + printf("State: "); + for (DecodeCol currCol : decodeTable) + printf("%3i ", currCol.state); + printf("\n"); + printf(" Sym: "); + for (DecodeCol currCol : decodeTable) + printf("%3hhu ", currCol.symbol); + printf("\n"); + printf(" Y: "); + for (DecodeCol currCol : decodeTable) + printf("%3i ", currCol.y); + printf("\n"); + printf(" K: "); + for (DecodeCol currCol : decodeTable) + printf("%3i ", currCol.k); + printf("\n"); +} + +std::vector readFileAsNibbles(std::string filePath) +{ + std::vector returnVec; + std::ifstream iStream; + iStream.open(filePath.c_str(), std::ios::binary); + if (!iStream.is_open()) + { + fprintf(stderr, "Error: Couldn't open %s for reading as nibbles\n", filePath.c_str()); + return returnVec; + } + iStream.ignore( std::numeric_limits::max() ); + std::streamsize size = iStream.gcount(); + iStream.clear(); + iStream.seekg( 0, std::ios_base::beg ); + std::vector ucVec(size); + iStream.read((char*)(&ucVec[0]), size); + iStream.close(); + for (unsigned char byte : ucVec) + { + returnVec.push_back(byte >> 4); + returnVec.push_back(byte & 0b00001111); + } + return returnVec; +} + +int getFileSize(std::string filePath) +{ + std::ifstream iStream; + iStream.open(filePath.c_str(), std::ios::binary); + if (!iStream.is_open()) + { + fprintf(stderr, "Error: Couldn't open %s for reading file size\n", filePath.c_str()); + return 0; + } + iStream.ignore( std::numeric_limits::max() ); + std::streamsize size = iStream.gcount(); + int returnSize = size; + iStream.clear(); + iStream.seekg( 0, std::ios_base::beg ); + iStream.close(); + return returnSize; +} + +void printCounts(std::vector counts) +{ + int totalCount = 0; + for (int count : counts) + { + printf("%4i ", count); + totalCount += count; + } + printf("%4i\n", totalCount); +} + +void printSymbols(std::vector symbols) +{ + for (int symbol : symbols) + printf("%4hhu ", symbol); + printf("\n"); +} + +void sortCount(std::vector *counts, std::vector *symbols) +{ + for (int i = 0; i < counts->size(); i++) + { + int currCount = (*counts)[i]; + int currChar = (*symbols)[i]; + for (int j = i; j < counts->size(); j++) + { + if ((*counts)[j] > currCount) + { + (*counts)[i] = (*counts)[j]; + (*symbols)[i] = (*symbols)[j]; + (*counts)[j] = currCount; + (*symbols)[j] = currChar; + currCount = (*counts)[i]; + currChar = (*symbols)[i]; + } + } + } +} + +bool areVectorsEqual(std::vector input, std::vector output) +{ + if (input.size() != output.size()) + return false; + for (int i = 0; i < input.size(); i++) + { + if (input[i] != output[i]) + return false; + } + return true; +} + +std::string getStringFromUCvec(std::vector input) +{ + std::stringstream ss; + for (unsigned char uc : input) + ss << getCharFromUC(uc); + return ss.str(); +} +std::vector getUCvecFromString(std::string input) +{ + std::vector ucVec(input.size()); + for (int i = 0; i < input.size(); i++) + ucVec[i] = getUCfromChar(input[i]); + return ucVec; +} + +unsigned char getUCfromChar(char input) +{ + switch (input) + { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'a': + return 10; + case 'b': + return 11; + case 'c': + return 12; + case 'd': + return 13; + case 'e': + return 14; + case 'f': + return 15; + default: + return 255; + } +} + +char getCharFromUC(unsigned char input) +{ + switch (input) + { + case 0: + return '0'; + case 1: + return '1'; + case 2: + return '2'; + case 3: + return '3'; + case 4: + return '4'; + case 5: + return '5'; + case 6: + return '6'; + case 7: + return '7'; + case 8: + return '8'; + case 9: + return '9'; + case 10: + return 'a'; + case 11: + return 'b'; + case 12: + return 'c'; + case 13: + return 'd'; + case 14: + return 'e'; + case 15: + return 'f'; + default: + return 'X'; + } +} + diff --git a/tools/compresSmol/tANS.h b/tools/compresSmol/tANS.h new file mode 100644 index 000000000000..04fefee8ee86 --- /dev/null +++ b/tools/compresSmol/tANS.h @@ -0,0 +1,74 @@ +#ifndef TANS_H +#define TANS_H +#include +#include +#include +#include +#include +#include +#include +#include + +struct DecodeCol { + int state; + unsigned char symbol; + int y; + int k; +}; + +struct EncodeHelper { + unsigned char symbol; + std::vector states; + std::vector yVals; + std::vector kVals; + std::vector yPrimVals; + int currentRepeat = 0; + int currentIndex = 0; +}; + +struct EncodeSymbolData { + unsigned char symbol; + int nextState; + int streamValue; + int numBits; +}; +struct EncodeCol { + int state; + std::vector symbols; +}; + +struct EncodedData { + int initialState; + std::vector bitStream; +}; + +std::vector createDecodingTable(std::vector symbols, std::vector frequencies); + +std::vector createEncodingTable(std::vector decodeTable, std::vector symbols); + +EncodedData encodeData(std::vector input, std::vector encodingTable); +std::vector decodeData(EncodedData *data, std::vector decodeTable, int numChars); + +std::vector findSymbols(std::vector input); +std::vector countSymbols(std::vector input, std::vector symbols); +std::vector normalizeCounts(std::vector counts, int tableSize); +std::vector normalizeCounts(std::vector counts, int tableSize, bool fillZeros); +void sortCount(std::vector *counts, std::vector *symbols); + +void printEncodeTable(std::vector encodeTable, std::vector symbols); +void printDecodeTable(std::vector decodeTable); +void printCounts(std::vector count); +void printSymbols(std::vector symbols); + +std::vector readFileAsNibbles(std::string filePath); +int getFileSize(std::string filePath); +bool areVectorsEqual(std::vector input, std::vector output); +int encodeSingleSymbol(EncodeCol currEncodeCol, unsigned char symbol, std::vector *bitstream); + +std::string getStringFromUCvec(std::vector input); +std::vector getUCvecFromString(std::string input); +unsigned char getUCfromChar(char input); +char getCharFromUC(unsigned char input); + + +#endif