diff options
Diffstat (limited to 'arm9/src')
-rw-r--r-- | arm9/src/bag.c | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/arm9/src/bag.c b/arm9/src/bag.c new file mode 100644 index 00000000..819c7739 --- /dev/null +++ b/arm9/src/bag.c @@ -0,0 +1,463 @@ +#include "global.h" +#include "MI_memory.h" +#include "bag.h" +#include "itemtool.h" +#include "heap.h" + +#pragma thumb on + +u32 Sav2_Bag_sizeof(void) +{ + return sizeof(struct Bag); +} + +struct Bag * Sav2_Bag_new(u32 heap_id) +{ + struct Bag * ret = (struct Bag *)AllocFromHeap(heap_id, sizeof(struct Bag)); + Sav2_Bag_init(ret); + return ret; +} + +void Sav2_Bag_init(struct Bag * bag) +{ + MI_CpuClear16(bag, sizeof(struct Bag)); +} + +void Sav2_Bag_copy(const struct Bag * src, struct Bag * dest) +{ + MI_CpuCopy8(src, dest, sizeof(struct Bag)); +} + +u32 Bag_GetRegisteredItem(struct Bag * bag) +{ + return bag->registeredItem; +} + +void Bag_SetRegisteredItem(struct Bag * bag, u32 item) +{ + bag->registeredItem = item; +} + +u32 GetItemPocket(struct Bag * bag, u16 item_id, struct ItemSlot ** slot_p, u32 * count_p, u32 heap_id) +{ + u32 pocket = GetItemAttr(item_id, 5, heap_id); + switch (pocket) + { + case POCKET_KEY_ITEMS: + *slot_p = bag->keyItems; + *count_p = NUM_BAG_KEY_ITEMS; + break; + case POCKET_ITEMS: + *slot_p = bag->items; + *count_p = NUM_BAG_ITEMS; + break; + case POCKET_BERRIES: + *slot_p = bag->berries; + *count_p = NUM_BAG_BERRIES; + break; + case POCKET_MEDICINE: + *slot_p = bag->medicine; + *count_p = NUM_BAG_MEDICINE; + break; + case POCKET_BALLS: + *slot_p = bag->balls; + *count_p = NUM_BAG_BALLS; + break; + case POCKET_BATTLE_ITEMS: + *slot_p = bag->battleItems; + *count_p = NUM_BAG_BATTLE_ITEMS; + break; + case POCKET_MAIL: + *slot_p = bag->mail; + *count_p = NUM_BAG_MAIL; + break; + case POCKET_TMHMS: + *slot_p = bag->TMsHMs; + *count_p = NUM_BAG_TMS_HMS; + break; + } + return pocket; +} + +struct ItemSlot * BagGetItemSlotForAddInternal(struct ItemSlot * slots, u32 count, u16 item_id, u16 quantity, u16 maxquantity) +{ + int i; + int found = -1; + for (i = 0; i < count; i++) + { + if (slots[i].id == item_id) + { + if (quantity + slots[i].quantity > maxquantity) + return NULL; + return &slots[i]; + } + if (found == -1 && slots[i].id == ITEM_NONE && slots[i].quantity == 0) + { + found = i; + } + } + if (found == -1) + return NULL; + return &slots[found]; +} + +struct ItemSlot * PocketGetItemSlotForAdd(struct Bag * bag, u16 item_id, u16 quantity, u32 heap_id) +{ + struct ItemSlot * slots; + u32 count; + u32 pocket = GetItemPocket(bag, item_id, &slots, &count, heap_id); + if (pocket == POCKET_TMHMS) + { + return BagGetItemSlotForAddInternal(slots, count, item_id, quantity, 99); + } + else + { + return BagGetItemSlotForAddInternal(slots, count, item_id, quantity, 999); + } +} + +BOOL BagHasSpaceForItem(struct Bag * bag, u16 item_id, u16 quantity, u32 heap_id) +{ + return PocketGetItemSlotForAdd(bag, item_id, quantity, heap_id) != NULL; +} + +BOOL BagAddItem(struct Bag * bag, u16 item_id, u16 quantity, u32 heap_id) +{ + struct ItemSlot * slots = PocketGetItemSlotForAdd(bag, item_id, quantity, heap_id); + if (slots == NULL) + return FALSE; + slots->id = item_id; + slots->quantity += quantity; + u32 count; + u32 pocket = GetItemPocket(bag, item_id, &slots, &count, heap_id); + if (pocket == POCKET_TMHMS || pocket == POCKET_BERRIES) + { + SortPocket(slots, count); + } + return TRUE; +} + +struct ItemSlot * PocketGetItemSlotForRemove(struct ItemSlot * slots, u32 count, u16 item_id, u16 quantity) +{ + int i; + for (i = 0; i < count; i++) + { + if (slots[i].id == item_id) + { + if (slots[i].quantity >= quantity) + return &slots[i]; + return NULL; + } + } + return NULL; +} + +struct ItemSlot * BagGetItemSlotForRemove(struct Bag * bag, u16 item_id, u16 quantity, u32 heap_id) +{ + struct ItemSlot * slots; + u32 count; + (void)GetItemPocket(bag, item_id, &slots, &count, heap_id); + return PocketGetItemSlotForRemove(slots, count, item_id, quantity); +} + +BOOL BagTakeItem(struct Bag * bag, u16 item_id, u16 quantity, u32 heap_id) +{ + struct ItemSlot * slots = BagGetItemSlotForRemove(bag, item_id, quantity, heap_id); + if (slots == NULL) + return FALSE; + slots->quantity -= quantity; + if (slots->quantity == 0) + slots->id = ITEM_NONE; + u32 count; + (void)GetItemPocket(bag, item_id, &slots, &count, heap_id); + PocketCompaction(slots, count); + return TRUE; +} + +BOOL PocketTakeItem(struct ItemSlot * slots, u32 count, u16 item_id, u16 quantity) +{ + struct ItemSlot * slot = PocketGetItemSlotForRemove(slots, count, item_id, quantity); + if (slot == NULL) + return FALSE; + slot->quantity -= quantity; + if (slot->quantity == 0) + slot->id = ITEM_NONE; + PocketCompaction(slots, count); + return TRUE; +} + +BOOL BagHasItem(struct Bag * bag, u16 item_id, u16 quantity, u32 heap_id) +{ + return BagGetItemSlotForRemove(bag, item_id, quantity, heap_id) != NULL; +} + +BOOL BagPocketNotEmpty(struct Bag * bag, u32 pocket) +{ + struct ItemSlot * slots; + u32 count; + switch (pocket) + { + case POCKET_KEY_ITEMS: + slots = bag->keyItems; + count = NUM_BAG_KEY_ITEMS; + break; + case POCKET_ITEMS: + slots = bag->items; + count = NUM_BAG_ITEMS; + break; + case POCKET_BERRIES: + slots = bag->berries; + count = NUM_BAG_BERRIES; + break; + case POCKET_MEDICINE: + slots = bag->medicine; + count = NUM_BAG_MEDICINE; + break; + case POCKET_BALLS: + slots = bag->balls; + count = NUM_BAG_BALLS; + break; + case POCKET_BATTLE_ITEMS: + slots = bag->battleItems; + count = NUM_BAG_BATTLE_ITEMS; + break; + case POCKET_MAIL: + slots = bag->mail; + count = NUM_BAG_MAIL; + break; + case POCKET_TMHMS: + slots = bag->TMsHMs; + count = NUM_BAG_TMS_HMS; + break; + default: + return FALSE; + } + int i; + for (i = 0; i < count; i++) + { + if (slots[i].id != ITEM_NONE) + return TRUE; + } + return FALSE; +} + +u16 BagGetQuantity(struct Bag * bag, u16 item_id, u32 heap_id) +{ + struct ItemSlot * slot = BagGetItemSlotForRemove(bag, item_id, 1, heap_id); + if (slot == NULL) + return 0; + return slot->quantity; +} + +u16 PocketGetQuantity(struct ItemSlot * slots, u32 count, u16 item_id) +{ + struct ItemSlot * slot = PocketGetItemSlotForRemove(slots, count, item_id, 1); + if (slot == NULL) + return 0; + return slot->quantity; +} + +void SwapItemSlots(struct ItemSlot * a, struct ItemSlot * b) +{ + struct ItemSlot tmp; + + tmp = *a; + *a = *b; + *b = tmp; +} + +void PocketCompaction(struct ItemSlot * slots, u32 count) +{ + int i, j; + for (i = 0; i < count - 1; i++) + { + for (j = i + 1; j < count; j++) + { + if (slots[i].quantity == 0) + { + SwapItemSlots(&slots[i], &slots[j]); + } + } + } +} + +void SortPocket(struct ItemSlot * slots, u32 count) +{ + int i, j; + for (i = 0; i < count - 1; i++) + { + for (j = i + 1; j < count; j++) + { + if (slots[i].quantity == 0 || (slots[j].quantity != 0 && slots[i].id > slots[j].id)) + { + SwapItemSlots(&slots[i], &slots[j]); + } + } + } +} + +extern struct BagView * BagView_new(u8 heap_id); +extern void BagView_setitem(struct BagView * view, struct ItemSlot * slot, u8 pocket, u8 idx); + +struct BagView * CreateBagView(struct Bag * bag, const u8 * pockets, u32 heap_id) +{ + struct BagView * view = BagView_new((u8)heap_id); + int i; + for (i = 0; pockets[i] != 0xFF; i++) + { + switch (pockets[i]) + { + case POCKET_KEY_ITEMS: + BagView_setitem(view, bag->keyItems, POCKET_KEY_ITEMS, (u8)i); + break; + case POCKET_ITEMS: + BagView_setitem(view, bag->items, POCKET_ITEMS, (u8)i); + break; + case POCKET_BERRIES: + BagView_setitem(view, bag->berries, POCKET_BERRIES, (u8)i); + break; + case POCKET_MEDICINE: + BagView_setitem(view, bag->medicine, POCKET_MEDICINE, (u8)i); + break; + case POCKET_BALLS: + BagView_setitem(view, bag->balls, POCKET_BALLS, (u8)i); + break; + case POCKET_BATTLE_ITEMS: + BagView_setitem(view, bag->battleItems, POCKET_BATTLE_ITEMS, (u8)i); + break; + case POCKET_MAIL: + BagView_setitem(view, bag->mail, POCKET_MAIL, (u8)i); + break; + case POCKET_TMHMS: + BagView_setitem(view, bag->TMsHMs, POCKET_TMHMS, (u8)i); + break; + } + } + return view; +} + +struct ItemSlot * BagGetPocketSlotN(struct Bag * bag, u32 pocket, u32 slot) +{ + struct ItemSlot * slots; + u32 count; + switch (pocket) + { + case POCKET_KEY_ITEMS: + slots = bag->keyItems; + count = NUM_BAG_KEY_ITEMS; + break; + case POCKET_ITEMS: + slots = bag->items; + count = NUM_BAG_ITEMS; + break; + case POCKET_BERRIES: + slots = bag->berries; + count = NUM_BAG_BERRIES; + break; + case POCKET_MEDICINE: + slots = bag->medicine; + count = NUM_BAG_MEDICINE; + break; + case POCKET_BALLS: + slots = bag->balls; + count = NUM_BAG_BALLS; + break; + case POCKET_BATTLE_ITEMS: + slots = bag->battleItems; + count = NUM_BAG_BATTLE_ITEMS; + break; + case POCKET_MAIL: + slots = bag->mail; + count = NUM_BAG_MAIL; + break; + case POCKET_TMHMS: + slots = bag->TMsHMs; + count = NUM_BAG_TMS_HMS; + break; + } + if (slot >= count) + return NULL; + return &slots[slot]; +} + +struct Bag * Sav2_Bag_get(struct SaveBlock2 * sav2) +{ + return (struct Bag *)SavArray_get(sav2, 3); +} + +struct UnkStruct_0206F164 * FUN_0206F164(u32 heap_id) +{ + struct UnkStruct_0206F164 * ret = (struct UnkStruct_0206F164 *)AllocFromHeap(heap_id, sizeof(struct UnkStruct_0206F164)); + MI_CpuClear16(ret, sizeof(struct UnkStruct_0206F164)); + return ret; +} + +void FUN_0206F17C(struct UnkStruct_0206F164 * a0, u32 a1, u8 * a2, u8 * a3) +{ + *a2 = a0->unk_08[a1]; + *a3 = a0->unk_00[a1]; +} + +u16 FUN_0206F18C(struct UnkStruct_0206F164 * a0) +{ + return a0->unk_10; +} + +void FUN_0206F190(struct UnkStruct_0206F164 * a0, u32 a1, u8 a2, u8 a3) +{ + a0->unk_08[a1] = a2; + a0->unk_00[a1] = a3; +} + +void FUN_0206F19C(struct UnkStruct_0206F164 * a0, u16 a1) +{ + a0->unk_10 = a1; +} + +void FUN_0206F1A0(struct UnkStruct_0206F164 * a0, u32 a1, u8 * a2, u8 * a3) +{ + *a2 = a0->unk_19[a1]; + *a3 = a0->unk_14[a1]; +} + +u16 FUN_0206F1AC(struct UnkStruct_0206F164 * a0) +{ + return a0->unk_1e; +} + +u16 FUN_0206F1B0(struct UnkStruct_0206F164 * a0) +{ + return a0->unk_20; +} + +u16 FUN_0206F1B4(struct UnkStruct_0206F164 * a0) +{ + return a0->unk_22; +} + +void FUN_0206F1B8(struct UnkStruct_0206F164 * a0, u32 a1, u8 a2, u8 a3) +{ + a0->unk_19[a1] = a2; + a0->unk_14[a1] = a3; +} + +void FUN_0206F1C0(struct UnkStruct_0206F164 * a0) +{ + u32 i; + for (i = 0; i < 5; i++) + { + FUN_0206F1B8(a0, i, 0, 0); + } + FUN_0206F1EC(a0, 0); +} + +void FUN_0206F1E4(struct UnkStruct_0206F164 * a0, u16 a1, u16 a2) +{ + a0->unk_1e = a1; + a0->unk_20 = a2; +} + +void FUN_0206F1EC(struct UnkStruct_0206F164 * a0, u16 a1) +{ + a0->unk_22 = a1; +} |