440 lines
11 KiB
C
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
|
|
}
|
|
}
|
|
}
|