mirror of
https://github.com/pret/pokefirered.git
synced 2026-05-11 06:25:23 -05:00
208 lines
5.7 KiB
C
208 lines
5.7 KiB
C
#include "global.h"
|
|
#include "gflib.h"
|
|
#include "decompress.h"
|
|
#include "pokemon.h"
|
|
|
|
EWRAM_DATA ALIGNED(4) u8 gDecompressionBuffer[0x4000] = {0};
|
|
|
|
void LZDecompressWram(const void *src, void *dest)
|
|
{
|
|
LZ77UnCompWram(src, dest);
|
|
}
|
|
|
|
void LZDecompressVram(const void *src, void *dest)
|
|
{
|
|
LZ77UnCompVram(src, dest);
|
|
}
|
|
|
|
// Checks if `ptr` is likely LZ77 data
|
|
// Checks word-alignment, min/max size, and header byte
|
|
// Returns uncompressed size if true, 0 otherwise
|
|
u32 IsLZ77Data(const void *ptr, u32 minSize, u32 maxSize)
|
|
{
|
|
const u8 *data = ptr;
|
|
u32 size;
|
|
// Compressed data must be word aligned
|
|
if (((u32)ptr) & 3)
|
|
return 0;
|
|
// Check LZ77 header byte
|
|
// See https://problemkaputt.de/gbatek.htm#biosdecompressionfunctions
|
|
if (data[0] != 0x10)
|
|
return 0;
|
|
|
|
// Read 24-bit uncompressed size
|
|
size = data[1] | (data[2] << 8) | (data[3] << 16);
|
|
if (size >= minSize && size <= maxSize)
|
|
return size;
|
|
return 0;
|
|
}
|
|
|
|
u16 LoadCompressedSpriteSheet(const struct CompressedSpriteSheet *src)
|
|
{
|
|
struct SpriteSheet dest;
|
|
|
|
LZ77UnCompWram(src->data, gDecompressionBuffer);
|
|
dest.data = gDecompressionBuffer;
|
|
dest.size = src->size;
|
|
dest.tag = src->tag;
|
|
return LoadSpriteSheet(&dest);
|
|
}
|
|
|
|
// This can be used for either compressed or uncompressed sprite sheets
|
|
u16 LoadCompressedSpriteSheetByTemplate(const struct SpriteTemplate *template, s32 offset)
|
|
{
|
|
struct SpriteTemplate myTemplate;
|
|
struct SpriteFrameImage myImage;
|
|
u32 size;
|
|
|
|
// Check for LZ77 header and read uncompressed size, or fallback if not compressed (zero size)
|
|
if ((size = IsLZ77Data(template->images->data, TILE_SIZE_4BPP, sizeof(gDecompressionBuffer))) == 0)
|
|
return LoadSpriteSheetByTemplate(template, 0, offset);
|
|
|
|
LZ77UnCompWram(template->images->data, gDecompressionBuffer);
|
|
myImage.data = gDecompressionBuffer;
|
|
myImage.size = size + offset;
|
|
myTemplate.images = &myImage;
|
|
myTemplate.tileTag = template->tileTag;
|
|
|
|
return LoadSpriteSheetByTemplate(&myTemplate, 0, offset);
|
|
}
|
|
|
|
void LoadCompressedSpriteSheetOverrideBuffer(const struct CompressedSpriteSheet *src, void *buffer)
|
|
{
|
|
struct SpriteSheet dest;
|
|
|
|
LZ77UnCompWram(src->data, buffer);
|
|
dest.data = buffer;
|
|
dest.size = src->size;
|
|
dest.tag = src->tag;
|
|
LoadSpriteSheet(&dest);
|
|
}
|
|
|
|
void LoadCompressedSpritePalette(const struct CompressedSpritePalette *src)
|
|
{
|
|
struct SpritePalette dest;
|
|
|
|
LZ77UnCompWram(src->data, gDecompressionBuffer);
|
|
dest.data = (void *) gDecompressionBuffer;
|
|
dest.tag = src->tag;
|
|
LoadSpritePalette(&dest);
|
|
}
|
|
|
|
void LoadCompressedSpritePaletteWithTag(const u32 *pal, u16 tag)
|
|
{
|
|
struct SpritePalette dest;
|
|
|
|
LZ77UnCompWram(pal, gDecompressionBuffer);
|
|
dest.data = (void *) gDecompressionBuffer;
|
|
dest.tag = tag;
|
|
LoadSpritePalette(&dest);
|
|
}
|
|
|
|
void LoadCompressedSpritePaletteOverrideBuffer(const struct CompressedSpritePalette *src, void *buffer)
|
|
{
|
|
struct SpritePalette dest;
|
|
|
|
LZ77UnCompWram(src->data, buffer);
|
|
dest.data = buffer;
|
|
dest.tag = src->tag;
|
|
LoadSpritePalette(&dest);
|
|
}
|
|
|
|
void DecompressPicFromTable(const struct CompressedSpriteSheet *src, void *buffer)
|
|
{
|
|
LZ77UnCompWram(src->data, buffer);
|
|
}
|
|
|
|
void HandleLoadSpecialPokePic(bool32 isFrontPic, void *dest, s32 species, u32 personality)
|
|
{
|
|
LoadSpecialPokePic(dest, species, personality, isFrontPic);
|
|
}
|
|
|
|
void LoadSpecialPokePic(void *dest, s32 species, u32 personality, bool8 isFrontPic)
|
|
{
|
|
species = SanitizeSpeciesId(species);
|
|
if (species == SPECIES_UNOWN)
|
|
species = GetUnownSpeciesId(personality);
|
|
|
|
if (isFrontPic)
|
|
{
|
|
#if P_GENDER_DIFFERENCES
|
|
if (gSpeciesInfo[species].frontPicFemale != NULL && IsPersonalityFemale(species, personality))
|
|
LZ77UnCompWram(gSpeciesInfo[species].frontPicFemale, dest);
|
|
else
|
|
#endif
|
|
if (gSpeciesInfo[species].frontPic != NULL)
|
|
LZ77UnCompWram(gSpeciesInfo[species].frontPic, dest);
|
|
else
|
|
LZ77UnCompWram(gSpeciesInfo[SPECIES_NONE].frontPic, dest);
|
|
}
|
|
else
|
|
{
|
|
#if P_GENDER_DIFFERENCES
|
|
if (gSpeciesInfo[species].backPicFemale != NULL && IsPersonalityFemale(species, personality))
|
|
LZ77UnCompWram(gSpeciesInfo[species].backPicFemale, dest);
|
|
else
|
|
#endif
|
|
if (gSpeciesInfo[species].backPic != NULL)
|
|
LZ77UnCompWram(gSpeciesInfo[species].backPic, dest);
|
|
else
|
|
LZ77UnCompWram(gSpeciesInfo[SPECIES_NONE].backPic, dest);
|
|
}
|
|
DrawSpindaSpots(species, personality, dest, isFrontPic);
|
|
}
|
|
|
|
bool8 LoadCompressedSpriteSheetUsingHeap(const struct CompressedSpriteSheet *src)
|
|
{
|
|
struct SpriteSheet dest;
|
|
void *buffer;
|
|
|
|
buffer = AllocZeroed(src->data[0] >> 8);
|
|
LZ77UnCompWram(src->data, buffer);
|
|
|
|
dest.data = buffer;
|
|
dest.size = src->size;
|
|
dest.tag = src->tag;
|
|
|
|
LoadSpriteSheet(&dest);
|
|
Free(buffer);
|
|
return FALSE;
|
|
}
|
|
|
|
bool8 LoadCompressedSpritePaletteUsingHeap(const struct CompressedSpritePalette *src)
|
|
{
|
|
struct SpritePalette dest;
|
|
void *buffer;
|
|
|
|
buffer = AllocZeroed(src->data[0] >> 8);
|
|
LZ77UnCompWram(src->data, buffer);
|
|
dest.data = buffer;
|
|
dest.tag = src->tag;
|
|
|
|
LoadSpritePalette(&dest);
|
|
Free(buffer);
|
|
return FALSE;
|
|
}
|
|
|
|
bool8 LoadCompressedSpritePaletteUsingHeapWithTag(const u32 *pal, u16 tag)
|
|
{
|
|
struct SpritePalette dest;
|
|
void *buffer;
|
|
|
|
buffer = AllocZeroed(*((u32 *)pal) >> 8);
|
|
if (!buffer)
|
|
return TRUE;
|
|
LZ77UnCompWram(pal, buffer);
|
|
dest.data = buffer;
|
|
dest.tag = tag;
|
|
LoadSpritePalette(&dest);
|
|
Free(buffer);
|
|
return FALSE;
|
|
}
|
|
|
|
u32 GetDecompressedDataSize(const u32 *ptr)
|
|
{
|
|
const u8 *ptr8 = (const u8 *)ptr;
|
|
return (ptr8[3] << 16) | (ptr8[2] << 8) | (ptr8[1]);
|
|
}
|