Skip to content

Commit

Permalink
berry images decompression buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
DizzyEggg committed Jan 16, 2025
1 parent 8c79e97 commit 94ce8b8
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 86 deletions.
16 changes: 13 additions & 3 deletions include/item_menu_icons.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ void RemoveBagItemIconSprite(u8 id);
void CreateItemMenuSwapLine(void);
void SetItemMenuSwapLineInvisibility(bool8 invisible);
void UpdateItemMenuSwapLinePos(u8 y);
u8 CreateBerryTagSprite(u8 id, s16 x, s16 y);
void FreeBerryTagSpritePalette(void);
u8 CreateSpinningBerrySprite(u8 berryId, u8 x, u8 y, bool8 startAffine);

// Note: Because of removing gDecompressionBuffer and allowing to create more than berry sprite at a time, the memory for gfx is allocated dynamically.
// For CreateBerryTagSprite and CreateSpinningBerrySprite the allocated ptr is stored in two last data fields(data[6], data[7]), so make sure to NOT put anything in there!
// The corresponding code has already been edited in berry_tag_screen.c and berry_blender.c
#define BERRY_ICON_GFX_PTR_DATA_ID 6
u32 CreateBerryTagSprite(u32 id, s32 x, s32 y);
u32 CreateSpinningBerrySprite(u32 berryId, s32 x, s32 y, bool32 startAffine);
// Needs to call either of these always after creating a Berry Icon sprite, because it frees allocated memory!
void DestroyBerryIconSprite(u32 spriteId, u32 berryId, bool32 freePal);
void DestroyBerryIconSpritePtr(struct Sprite *sprite, u32 berryId, bool32 freePal);

void FreeBerryIconSpritePalette(u32 berryId); // Unused atm, because it's also handled by DestroyBerryIconSprite. Leaving it as it still may be useful in some custom cases.

u8 CreateBerryFlavorCircleSprite(s16 x);

#endif // GUARD_ITEM_MENU_ICONS_H
13 changes: 8 additions & 5 deletions src/battle_gfx_sfx_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "constants/battle_anim.h"
#include "battle_interface.h"
#include "main.h"
#include "menu.h"
#include "dma3.h"
#include "malloc.h"
#include "graphics.h"
Expand Down Expand Up @@ -655,9 +656,10 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler)
else
lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personalityValue);

LZDecompressWram(lzPaletteData, gDecompressionBuffer);
LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP);
LoadPalette(gDecompressionBuffer, BG_PLTT_ID(8) + BG_PLTT_ID(battler), PLTT_SIZE_4BPP);
void *buffer = malloc_and_decompress(lzPaletteData, NULL);
LoadPalette(buffer, paletteOffset, PLTT_SIZE_4BPP);
LoadPalette(buffer, BG_PLTT_ID(8) + BG_PLTT_ID(battler), PLTT_SIZE_4BPP);
Free(buffer);

// transform's pink color
if (gBattleSpritesDataPtr->battlerData[battler].transformSpecies != SPECIES_NONE)
Expand Down Expand Up @@ -975,8 +977,9 @@ 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);
LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP);
void *buffer = malloc_and_decompress(lzPaletteData, NULL);
LoadPalette(buffer, paletteOffset, PLTT_SIZE_4BPP);
Free(buffer);

if (!megaEvo)
{
Expand Down
106 changes: 63 additions & 43 deletions src/berry_blender.c
Original file line number Diff line number Diff line change
Expand Up @@ -1126,68 +1126,84 @@ static void CB2_LoadBerryBlender(void)
UpdatePaletteFade();
}

#define sTargetY data[0]
#define sX data[1]
#define sY data[2]
#define sBounceSpeed data[3]
#define sYUpSpeed data[4]
#define sBounces data[5]
#define sXSpeed data[6]
#define sYDownSpeed data[7]
// Because of changing how Berry sprites are generated, we have to leave data[6] and data[7] untouched as it has an allocated memory ptr for berry's gfx.
struct BerrySpriteData
{
s16 sTargetY; // data0
s16 sX; // data1
s16 sY; // data2

s8 sBounceSpeed; // data3
u8 berryId; // data3

s8 sYUpSpeed; // data4
s8 sBounces; // data4

s8 sXSpeed; // data5
s8 sYDownSpeed; // data5
};

static inline struct BerrySpriteData *GetBerrySpriteDataAsStructPtr(struct Sprite *sprite)
{
return (void *)(&sprite->data[0]);
}

// For throwing berries into the machine
static void SpriteCB_Berry(struct Sprite *sprite)
{
sprite->sX += sprite->sXSpeed;
sprite->sY -= sprite->sYUpSpeed;
sprite->sY += sprite->sYDownSpeed;
sprite->sTargetY += sprite->sYDownSpeed;
sprite->sYUpSpeed--;
struct BerrySpriteData *spriteData = GetBerrySpriteDataAsStructPtr(sprite);

spriteData->sX += spriteData->sXSpeed;
spriteData->sY -= spriteData->sYUpSpeed;
spriteData->sY += spriteData->sYDownSpeed;
spriteData->sTargetY += spriteData->sYDownSpeed;
spriteData->sYUpSpeed--;

if (sprite->sTargetY < sprite->sY)
if (spriteData->sTargetY < spriteData->sY)
{
sprite->sBounceSpeed = sprite->sYUpSpeed = sprite->sBounceSpeed - 1;
spriteData->sBounceSpeed = spriteData->sYUpSpeed = spriteData->sBounceSpeed - 1;

if (++sprite->sBounces > 3)
DestroySprite(sprite);
if (++spriteData->sBounces > 3)
{
DestroyBerryIconSpritePtr(sprite, spriteData->berryId, TRUE);
return;
}
else
{
PlaySE(SE_BALL_TRAY_EXIT);
}
}
sprite->x = sprite->sX;
sprite->y = sprite->sY;
sprite->x = spriteData->sX;
sprite->y = spriteData->sY;
}

static void SetBerrySpriteData(struct Sprite *sprite, s16 x, s16 y, s16 bounceSpeed, s16 xSpeed, s16 ySpeed)
static void SetBerrySpriteData(struct Sprite *sprite, s32 x, s32 y, s32 bounceSpeed, s32 xSpeed, s32 ySpeed, u32 berryId)
{
sprite->sTargetY = y;
sprite->sX = x;
sprite->sY = y;
sprite->sBounceSpeed = bounceSpeed;
sprite->sYUpSpeed = 10;
sprite->sBounces = 0;
sprite->sXSpeed = xSpeed;
sprite->sYDownSpeed = ySpeed;
struct BerrySpriteData *spriteData = GetBerrySpriteDataAsStructPtr(sprite);

spriteData->sTargetY = y;
spriteData->sX = x;
spriteData->sY = y;
spriteData->sBounceSpeed = bounceSpeed;
spriteData->sYUpSpeed = 10;
spriteData->sBounces = 0;
spriteData->sXSpeed = xSpeed;
spriteData->sYDownSpeed = ySpeed;
spriteData->berryId = berryId;
sprite->callback = SpriteCB_Berry;
}

#undef sTargetY
#undef sX
#undef sY
#undef sBounceSpeed
#undef sYUpSpeed
#undef sBounces
#undef sXSpeed
#undef sYDownSpeed

static void CreateBerrySprite(u16 itemId, u8 playerId)
static void CreateBerrySprite(u32 itemId, u32 playerId)
{
u8 spriteId = CreateSpinningBerrySprite(ITEM_TO_BERRY(itemId) - 1, 0, 80, playerId & 1);
u32 berryId = ITEM_TO_BERRY(itemId) - 1;
u32 spriteId = CreateSpinningBerrySprite(berryId, 0, 80, playerId & 1);
SetBerrySpriteData(&gSprites[spriteId],
sBerrySpriteData[playerId][0],
sBerrySpriteData[playerId][1],
sBerrySpriteData[playerId][2],
sBerrySpriteData[playerId][3],
sBerrySpriteData[playerId][4]);
sBerrySpriteData[playerId][4],
berryId);
}

static void ConvertItemToBlenderBerry(struct BlenderBerry* berry, u16 itemId)
Expand Down Expand Up @@ -1612,6 +1628,9 @@ static void PrintPlayerNames(void)
}
}

// This is a small little addition, that basically speeds up the animation where all players' berries are thrown into the blender. Self-explanatory I hope!
#define BERRY_BLENDER_THROW_ALL_BERRIES_AT_ONCE TRUE

static void CB2_StartBlenderLocal(void)
{
s32 i, j;
Expand Down Expand Up @@ -1676,13 +1695,14 @@ static void CB2_StartBlenderLocal(void)
u32 playerId = sPlayerIdMap[sBerryBlender->numPlayers - 2][i];
if (sBerryBlender->playerToThrowBerry == playerId)
{
CreateBerrySprite(sBerryBlender->chosenItemId[sBerryBlender->playerToThrowBerry], i);
break;
CreateBerrySprite(sBerryBlender->chosenItemId[sBerryBlender->playerToThrowBerry++], i);
// If we're throwing all at once, continue the loop. If not, break out of the loop(vanilla behavior).
if (!BERRY_BLENDER_THROW_ALL_BERRIES_AT_ONCE)
break;
}
}
sBerryBlender->framesToWait = 0;
sBerryBlender->mainState++;
sBerryBlender->playerToThrowBerry++;
break;
case 12:
if (++sBerryBlender->framesToWait > 60)
Expand Down
7 changes: 4 additions & 3 deletions src/berry_tag_screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct BerryTagScreenStruct
{
u16 tilemapBuffers[3][0x400];
u16 berryId;
u16 currentSpriteBerryId;
u8 berrySpriteId;
u8 flavorCircleIds[FLAVOR_COUNT];
u16 gfxState;
Expand Down Expand Up @@ -466,13 +467,13 @@ static void PrintBerryDescription2(void)

static void CreateBerrySprite(void)
{
sBerryTag->berrySpriteId = CreateBerryTagSprite(sBerryTag->berryId - 1, 56, 64);
sBerryTag->currentSpriteBerryId = sBerryTag->berryId - 1;
sBerryTag->berrySpriteId = CreateBerryTagSprite(sBerryTag->currentSpriteBerryId, 56, 64);
}

static void DestroyBerrySprite(void)
{
DestroySprite(&gSprites[sBerryTag->berrySpriteId]);
FreeBerryTagSpritePalette();
DestroyBerryIconSprite(sBerryTag->berrySpriteId, sBerryTag->currentSpriteBerryId, TRUE);
}

static void CreateFlavorCircleSprites(void)
Expand Down
1 change: 0 additions & 1 deletion src/contest_link.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ static void Task_LinkContest_InitFlags(u8);

bool32 LinkContest_SendBlock(void *src, u16 size)
{
memcpy(gDecompressionBuffer, src, size);
if (SendBlock(BitmaskAllOtherLinkPlayers(), gDecompressionBuffer, size))
return TRUE;
else
Expand Down
90 changes: 62 additions & 28 deletions src/item_menu_icons.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
#include "item_menu.h"
#include "item_icon.h"
#include "item_menu_icons.h"
#include "malloc.h"
#include "menu_helpers.h"
#include "menu.h"
#include "sprite.h"
#include "window.h"
#include "util.h"
#include "constants/items.h"

enum {
Expand Down Expand Up @@ -269,18 +272,13 @@ static const union AnimCmd *const sBerryPicSpriteAnimTable[] =
sAnim_BerryPic
};

static const struct SpriteFrameImage sBerryPicSpriteImageTable[] =
{
{&gDecompressionBuffer[0], 0x800},
};

static const struct SpriteTemplate sBerryPicSpriteTemplate =
{
.tileTag = TAG_NONE,
.paletteTag = TAG_BERRY_PIC_PAL,
.oam = &sBerryPicOamData,
.anims = sBerryPicSpriteAnimTable,
.images = sBerryPicSpriteImageTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
};
Expand Down Expand Up @@ -319,7 +317,7 @@ static const struct SpriteTemplate sBerryPicRotatingSpriteTemplate =
.paletteTag = TAG_BERRY_PIC_PAL,
.oam = &sBerryPicRotatingOamData,
.anims = sBerryPicSpriteAnimTable,
.images = sBerryPicSpriteImageTable,
.images = NULL,
.affineAnims = sBerryPicRotatingAnimCmds,
.callback = SpriteCallbackDummy,
};
Expand Down Expand Up @@ -640,47 +638,83 @@ static void ArrangeBerryGfx(void *src, void *dest)
}
}

static void LoadBerryGfx(u8 berryId)
#define BERRY_SPRITE_SIZE ((64*64)/2) // 0x800

struct BerryDynamicGfx
{
struct CompressedSpritePalette pal;
ALIGNED(4) u8 gfx[BERRY_SPRITE_SIZE];
struct SpriteFrameImage images[1];
};

if (berryId == ITEM_TO_BERRY(ITEM_ENIGMA_BERRY_E_READER) - 1 && IsEnigmaBerryValid())
{
// unknown empty if statement
}
static struct BerryDynamicGfx *LoadBerryGfx(u8 berryId)
{
struct CompressedSpritePalette pal;

pal.data = sBerryPicTable[berryId].pal;
pal.tag = TAG_BERRY_PIC_PAL;
pal.tag = TAG_BERRY_PIC_PAL + berryId;
LoadCompressedSpritePalette(&pal);
LZDecompressWram(sBerryPicTable[berryId].tiles, &gDecompressionBuffer[0x1000]);
ArrangeBerryGfx(&gDecompressionBuffer[0x1000], &gDecompressionBuffer[0]);
struct BerryDynamicGfx *gfxAlloced = Alloc(sizeof(struct BerryDynamicGfx));
void *buffer = malloc_and_decompress(sBerryPicTable[berryId].tiles, NULL);
ArrangeBerryGfx(buffer, gfxAlloced->gfx);
Free(buffer);

return gfxAlloced;
}

u8 CreateBerryTagSprite(u8 id, s16 x, s16 y)
static u32 CreateBerrySprite(const struct SpriteTemplate *sprTemplate, u32 berryId, s32 x, s32 y)
{
LoadBerryGfx(id);
return CreateSprite(&sBerryPicSpriteTemplate, x, y, 0);
u32 spriteId;
struct BerryDynamicGfx *dynamicGfx = LoadBerryGfx(berryId);
struct SpriteTemplate newSprTemplate = *sprTemplate;

newSprTemplate.paletteTag += berryId;
newSprTemplate.images = dynamicGfx->images;

dynamicGfx->images[0].data = dynamicGfx->gfx;
dynamicGfx->images[0].size = BERRY_SPRITE_SIZE;
dynamicGfx->images[0].relativeFrames = FALSE;

spriteId = CreateSprite(&newSprTemplate, x, y, 0);
StoreWordInTwoHalfwords((u16 *) &gSprites[spriteId].data[BERRY_ICON_GFX_PTR_DATA_ID], (u32) dynamicGfx);
return spriteId;
}

void FreeBerryTagSpritePalette(void)
u32 CreateBerryTagSprite(u32 id, s32 x, s32 y)
{
FreeSpritePaletteByTag(TAG_BERRY_PIC_PAL);
return CreateBerrySprite(&sBerryPicSpriteTemplate, id, x, y);
}

// For throwing berries into the Berry Blender
u8 CreateSpinningBerrySprite(u8 berryId, u8 x, u8 y, bool8 startAffine)
u32 CreateSpinningBerrySprite(u32 berryId, s32 x, s32 y, bool32 startAffine)
{
u8 spriteId;

FreeSpritePaletteByTag(TAG_BERRY_PIC_PAL);
LoadBerryGfx(berryId);
spriteId = CreateSprite(&sBerryPicRotatingSpriteTemplate, x, y, 0);
if (startAffine == TRUE)
u32 spriteId = CreateBerrySprite(&sBerryPicRotatingSpriteTemplate, berryId, x, y);
if (startAffine)
StartSpriteAffineAnim(&gSprites[spriteId], 1);

return spriteId;
}

void DestroyBerryIconSprite(u32 spriteId, u32 berryId, bool32 freePal)
{
DestroyBerryIconSpritePtr(&gSprites[spriteId], berryId, freePal);
}

void DestroyBerryIconSpritePtr(struct Sprite *sprite, u32 berryId, bool32 freePal)
{
u32 gfxBuffer;

LoadWordFromTwoHalfwords((u16 *) &sprite->data[BERRY_ICON_GFX_PTR_DATA_ID], &gfxBuffer);
Free((void *)gfxBuffer);
DestroySprite(sprite);
if (freePal)
FreeBerryIconSpritePalette(berryId);
}

void FreeBerryIconSpritePalette(u32 berryId)
{
FreeSpritePaletteByTag(TAG_BERRY_PIC_PAL + berryId);
}

u8 CreateBerryFlavorCircleSprite(s16 x)
{
return CreateSprite(&sBerryCheckCircleSpriteTemplate, x, 116, 0);
Expand Down
Loading

0 comments on commit 94ce8b8

Please sign in to comment.