Files
Pokemon-Firered/src/item_menu_icons.c
T
2023-05-12 10:52:07 -04:00

440 lines
11 KiB
C

#include "global.h"
#include "gflib.h"
#include "decompress.h"
#include "graphics.h"
#include "item_menu_icons.h"
#include "constants/items.h"
enum {
TAG_BAG = 100,
TAG_SWAP_LINE,
TAG_ITEM_ICON,
TAG_ITEM_ICON_ALT,
};
#define NUM_SWAP_LINE_SPRITES 9
// Indexes for sItemMenuIconSpriteIds
enum {
SPR_BAG,
SPR_SWAP_LINE_START,
SPR_ITEM_ICON = SPR_SWAP_LINE_START + NUM_SWAP_LINE_SPRITES,
SPR_ITEM_ICON_ALT,
SPR_COUNT
};
enum {
ANIM_SWAP_LINE_START,
ANIM_SWAP_LINE_MID,
ANIM_SWAP_LINE_END,
};
enum {
AFFINEANIM_BAG_IDLE,
AFFINEANIM_BAG_SHAKE,
};
static EWRAM_DATA u8 sItemMenuIconSpriteIds[SPR_COUNT] = {0};
static EWRAM_DATA void *sItemIconTilesBuffer = NULL;
static EWRAM_DATA void *sItemIconTilesBufferPadded = NULL;
static void SpriteCB_BagVisualSwitchingPockets(struct Sprite *sprite);
static void SpriteCB_ShakeBagSprite(struct Sprite *sprite);
static const struct OamData sOamData_Bag = {
.affineMode = ST_OAM_AFFINE_NORMAL,
.shape = SPRITE_SHAPE(64x64),
.size = SPRITE_SIZE(64x64),
.priority = 1,
.paletteNum = 0
};
static const union AnimCmd sAnim_Bag_OpenPokeBallsPocket[] = {
ANIMCMD_FRAME( 0, 5),
ANIMCMD_FRAME(0x40, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_Bag_OpenItemsPocket[] = {
ANIMCMD_FRAME( 0, 5),
ANIMCMD_FRAME(0x80, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_Bag_OpenKeyItemsPocket[] = {
ANIMCMD_FRAME( 0, 5),
ANIMCMD_FRAME(0xc0, 0),
ANIMCMD_END
};
static const union AnimCmd *const sAnims_Bag[] = {
[POCKET_ITEMS - 1] = sAnim_Bag_OpenItemsPocket,
[POCKET_KEY_ITEMS - 1] = sAnim_Bag_OpenKeyItemsPocket,
[POCKET_POKE_BALLS - 1] = sAnim_Bag_OpenPokeBallsPocket,
};
static const union AffineAnimCmd sAffineAnim_BagIdle[] = {
AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),
AFFINEANIMCMD_END
};
static const union AffineAnimCmd sAffineAnim_BagShake[] = {
AFFINEANIMCMD_FRAME(0, 0, -2, 2),
AFFINEANIMCMD_FRAME(0, 0, 2, 4),
AFFINEANIMCMD_FRAME(0, 0, -2, 4),
AFFINEANIMCMD_FRAME(0, 0, 2, 2),
AFFINEANIMCMD_END
};
static const union AffineAnimCmd *const sAffineAnimTable_Bag[] = {
[AFFINEANIM_BAG_IDLE] = sAffineAnim_BagIdle,
[AFFINEANIM_BAG_SHAKE] = sAffineAnim_BagShake
};
const struct CompressedSpriteSheet gSpriteSheet_BagMale = {
.data = gBagMale_Gfx,
.size = 0x2000,
.tag = TAG_BAG
};
const struct CompressedSpriteSheet gSpriteSheet_BagFemale = {
.data = gBagFemale_Gfx,
.size = 0x2000,
.tag = TAG_BAG
};
const struct CompressedSpritePalette gSpritePalette_Bag = {
.data = gBag_Pal,
.tag = TAG_BAG
};
static const struct SpriteTemplate sSpriteTemplate_Bag = {
.tileTag = TAG_BAG,
.paletteTag = TAG_BAG,
.oam = &sOamData_Bag,
.anims = sAnims_Bag,
.images = NULL,
.affineAnims = sAffineAnimTable_Bag,
.callback = SpriteCallbackDummy
};
static const struct OamData sOamData_SwapLine = {
.affineMode = ST_OAM_AFFINE_OFF,
.shape = SPRITE_SHAPE(16x16),
.size = SPRITE_SIZE(16x16),
.priority = 1,
.paletteNum = 1
};
static const union AnimCmd sAnim_SwapLine_Start[] = {
ANIMCMD_FRAME(0, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_SwapLine_Mid[] = {
ANIMCMD_FRAME(4, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_SwapLine_End[] = {
ANIMCMD_FRAME(0, 0, .hFlip = TRUE),
ANIMCMD_END
};
static const union AnimCmd *const sAnims_SwapLine[] = {
[ANIM_SWAP_LINE_START] = sAnim_SwapLine_Start,
[ANIM_SWAP_LINE_MID] = sAnim_SwapLine_Mid,
[ANIM_SWAP_LINE_END] = sAnim_SwapLine_End
};
const struct CompressedSpriteSheet gBagSwapSpriteSheet = {
.data = gSwapLine_Gfx,
.size = 0x100,
.tag = TAG_SWAP_LINE
};
const struct CompressedSpritePalette gBagSwapSpritePalette = {
.data = gSwapLine_Pal,
.tag = TAG_SWAP_LINE
};
static const struct SpriteTemplate sSpriteTemplate_SwapLine = {
.tileTag = TAG_SWAP_LINE,
.paletteTag = TAG_SWAP_LINE,
.oam = &sOamData_SwapLine,
.anims = sAnims_SwapLine,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
};
static const struct OamData sOamData_ItemIcon = {
.affineMode = ST_OAM_AFFINE_OFF,
.shape = SPRITE_SHAPE(32x32),
.size = SPRITE_SIZE(32x32),
.priority = 1,
.paletteNum = 2
};
static const union AnimCmd sAnim_ItemIcon[] = {
ANIMCMD_FRAME(0, 0),
ANIMCMD_END
};
static const union AnimCmd *const sAnims_ItemIcon[] = {
sAnim_ItemIcon
};
static const struct SpriteTemplate sSpriteTemplate_ItemIcon = {
.tileTag = TAG_ITEM_ICON,
.paletteTag = TAG_ITEM_ICON,
.oam = &sOamData_ItemIcon,
.anims = sAnims_ItemIcon,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy
};
#include "data/item_icon_table.h"
void ResetItemMenuIconState(void)
{
u16 i;
for (i = 0; i < SPR_COUNT; i++)
sItemMenuIconSpriteIds[i] = SPRITE_NONE;
}
void CreateBagSprite(u8 animNum)
{
sItemMenuIconSpriteIds[SPR_BAG] = CreateSprite(&sSpriteTemplate_Bag, 40, 68, 0);
SetBagVisualPocketId(animNum);
}
void SetBagVisualPocketId(u8 animNum)
{
struct Sprite *sprite = &gSprites[sItemMenuIconSpriteIds[SPR_BAG]];
sprite->y2 = -5;
sprite->callback = SpriteCB_BagVisualSwitchingPockets;
StartSpriteAnim(sprite, animNum);
}
static void SpriteCB_BagVisualSwitchingPockets(struct Sprite *sprite)
{
if (sprite->y2 != 0)
sprite->y2++;
else
sprite->callback = SpriteCallbackDummy;
}
void ShakeBagSprite(void)
{
struct Sprite *sprite = &gSprites[sItemMenuIconSpriteIds[SPR_BAG]];
if (sprite->affineAnimEnded)
{
StartSpriteAffineAnim(sprite, AFFINEANIM_BAG_SHAKE);
sprite->callback = SpriteCB_ShakeBagSprite;
}
}
static void SpriteCB_ShakeBagSprite(struct Sprite *sprite)
{
if (sprite->affineAnimEnded)
{
StartSpriteAffineAnim(sprite, AFFINEANIM_BAG_IDLE);
sprite->callback = SpriteCallbackDummy;
}
}
void CreateSwapLine(void)
{
u8 i;
u8 * spriteIds = &sItemMenuIconSpriteIds[SPR_SWAP_LINE_START];
for (i = 0; i < NUM_SWAP_LINE_SPRITES; i++)
{
spriteIds[i] = CreateSprite(&sSpriteTemplate_SwapLine, i * 16 + 96, 7, 0);
switch (i)
{
case 0:
// ANIM_SWAP_LINE_START, by default
break;
case NUM_SWAP_LINE_SPRITES - 1:
StartSpriteAnim(&gSprites[spriteIds[i]], ANIM_SWAP_LINE_END);
break;
default:
StartSpriteAnim(&gSprites[spriteIds[i]], ANIM_SWAP_LINE_MID);
break;
}
gSprites[spriteIds[i]].invisible = TRUE;
}
}
void SetSwapLineInvisibility(bool8 invisible)
{
u8 i;
u8 * spriteIds = &sItemMenuIconSpriteIds[SPR_SWAP_LINE_START];
for (i = 0; i < NUM_SWAP_LINE_SPRITES; i++)
gSprites[spriteIds[i]].invisible = invisible;
}
void UpdateSwapLinePos(s16 x, u16 y)
{
u8 i;
u8 * spriteIds = &sItemMenuIconSpriteIds[SPR_SWAP_LINE_START];
for (i = 0; i < NUM_SWAP_LINE_SPRITES; i++)
{
gSprites[spriteIds[i]].x2 = x;
gSprites[spriteIds[i]].y = y + 7;
}
}
static bool8 TryAllocItemIconTilesBuffers(void)
{
void ** ptr1, ** ptr2;
ptr1 = &sItemIconTilesBuffer;
*ptr1 = Alloc(0x120);
if (*ptr1 == NULL)
return FALSE;
ptr2 = &sItemIconTilesBufferPadded;
*ptr2 = AllocZeroed(0x200);
if (*ptr2 == NULL)
{
Free(*ptr1);
return FALSE;
}
return TRUE;
}
void CopyItemIconPicTo4x4Buffer(const void *src, void *dest)
{
u8 i;
for (i = 0; i < 3; i++)
CpuCopy16(src + 0x60 * i, dest + 0x80 * i, 0x60);
}
u8 AddItemIconObject(u16 tilesTag, u16 paletteTag, u16 itemId)
{
struct SpriteTemplate template;
struct SpriteSheet spriteSheet;
struct CompressedSpritePalette spritePalette;
u8 spriteId;
if (!TryAllocItemIconTilesBuffers())
return MAX_SPRITES;
LZDecompressWram(GetItemIconGfxPtr(itemId, ITEMICON_TILES), sItemIconTilesBuffer);
CopyItemIconPicTo4x4Buffer(sItemIconTilesBuffer, sItemIconTilesBufferPadded);
spriteSheet.data = sItemIconTilesBufferPadded;
spriteSheet.size = 0x200;
spriteSheet.tag = tilesTag;
LoadSpriteSheet(&spriteSheet);
spritePalette.data = GetItemIconGfxPtr(itemId, ITEMICON_PAL);
spritePalette.tag = paletteTag;
LoadCompressedSpritePalette(&spritePalette);
CpuCopy16(&sSpriteTemplate_ItemIcon, &template, sizeof(struct SpriteTemplate));
template.tileTag = tilesTag;
template.paletteTag = paletteTag;
spriteId = CreateSprite(&template, 0, 0, 0);
Free(sItemIconTilesBuffer);
Free(sItemIconTilesBufferPadded);
return spriteId;
}
u8 AddItemIconObjectWithCustomObjectTemplate(const struct SpriteTemplate * origTemplate, u16 tilesTag, u16 paletteTag, u16 itemId)
{
struct SpriteTemplate template;
struct SpriteSheet spriteSheet;
struct CompressedSpritePalette spritePalette;
u8 spriteId;
if (!TryAllocItemIconTilesBuffers())
return MAX_SPRITES;
LZDecompressWram(GetItemIconGfxPtr(itemId, ITEMICON_TILES), sItemIconTilesBuffer);
CopyItemIconPicTo4x4Buffer(sItemIconTilesBuffer, sItemIconTilesBufferPadded);
spriteSheet.data = sItemIconTilesBufferPadded;
spriteSheet.size = 0x200;
spriteSheet.tag = tilesTag;
LoadSpriteSheet(&spriteSheet);
spritePalette.data = GetItemIconGfxPtr(itemId, ITEMICON_PAL);
spritePalette.tag = paletteTag;
LoadCompressedSpritePalette(&spritePalette);
CpuCopy16(origTemplate, &template, sizeof(struct SpriteTemplate));
template.tileTag = tilesTag;
template.paletteTag = paletteTag;
spriteId = CreateSprite(&template, 0, 0, 0);
Free(sItemIconTilesBuffer);
Free(sItemIconTilesBufferPadded);
return spriteId;
}
void CreateItemMenuIcon(u16 itemId, u8 idx)
{
u8 * spriteIds = &sItemMenuIconSpriteIds[SPR_ITEM_ICON];
u8 spriteId;
if (spriteIds[idx] == SPRITE_NONE)
{
// Either TAG_ITEM_ICON or TAG_ITEM_ICON_ALT
FreeSpriteTilesByTag(TAG_ITEM_ICON + idx);
FreeSpritePaletteByTag(TAG_ITEM_ICON + idx);
spriteId = AddItemIconObject(TAG_ITEM_ICON + idx, TAG_ITEM_ICON + idx, itemId);
if (spriteId != MAX_SPRITES)
{
spriteIds[idx] = spriteId;
gSprites[spriteId].x2 = 24;
gSprites[spriteId].y2 = 140;
}
}
}
void DestroyItemMenuIcon(u8 idx)
{
u8 * spriteIds = &sItemMenuIconSpriteIds[SPR_ITEM_ICON];
if (spriteIds[idx] != SPRITE_NONE)
{
DestroySpriteAndFreeResources(&gSprites[spriteIds[idx]]);
spriteIds[idx] = SPRITE_NONE;
}
}
// attrId is either ITEMICON_TILES or ITEMICON_PAL
const u32 *GetItemIconGfxPtr(u16 itemId, u8 attrId)
{
if (itemId > ITEMS_COUNT)
itemId = ITEM_NONE;
return sItemIconTable[itemId][attrId];
}
void CreateBerryPouchItemIcon(u16 itemId, u8 idx)
{
u8 * spriteIds = &sItemMenuIconSpriteIds[SPR_ITEM_ICON];
u8 spriteId;
if (spriteIds[idx] == SPRITE_NONE)
{
// Either TAG_ITEM_ICON or TAG_ITEM_ICON_ALT
FreeSpriteTilesByTag(TAG_ITEM_ICON + idx);
FreeSpritePaletteByTag(TAG_ITEM_ICON + idx);
spriteId = AddItemIconObject(TAG_ITEM_ICON + idx, TAG_ITEM_ICON + idx, itemId);
if (spriteId != MAX_SPRITES)
{
spriteIds[idx] = spriteId;
gSprites[spriteId].x2 = 24;
gSprites[spriteId].y2 = 147; // This value is the only difference from CreateItemMenuIcon
}
}
}