Merge pull request #521 from red031000/master

sync bag.c with heartgold
This commit is contained in:
Akira Akashi 2023-07-03 19:21:08 +01:00 committed by GitHub
commit 2f964cb953
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1633 additions and 809 deletions

View File

@ -168,7 +168,7 @@ clean: mostlyclean clean-fs clean-tools
clean-fs:
$(RM) $(filter %.narc %.arc,$(HOSTFS_FILES))
$(RM) $(patsubst %.narc,%.naix,$(patsubst %.arc,%.naix,$(filter %.narc %.arc,$(HOSTFS_FILES))))
$(RM) $(NCGR_CLEAN_LIST) $(NCLR_CLEAN_LIST) $(NCER_CLEAN_LIST) $(FS_CLEAN_LIST)
$(RM) $(NCGR_CLEAN_LIST) $(NCLR_CLEAN_LIST) $(NCER_CLEAN_LIST) $(NANR_CLEAN_LIST) $(FS_CLEAN_LIST)
find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' \) -exec $(RM) {} +
$(RM) files/msgdata/msg/narc_*.bin
@ -283,6 +283,9 @@ $(NCPR_NCLR_FILES): GFX_FLAGS = -ncpr
%.NCER: %.json
$(GFX) $< $@
%.NANR: %.json
$(GFX) $< $@
%.NSCR: %_map.json
$(GFX) $< $@ $(GFX_FLAGS)

View File

@ -2096,7 +2096,7 @@ _020360EA:
ldr r1, _0203627C ; =UNK_020F2A90
add r0, r7, #0x0
mov r2, #0xb
bl CreateBagView
bl Bag_CreateView
mov r1, #0x7e
lsl r1, r1, #0x2
add r3, r5, #0x0
@ -3141,7 +3141,7 @@ _020369C6:
mov r1, #0x4
add r2, sp, #0x8
add r3, #0x1
bl sub_0206F17C
bl BagCursor_Field_PocketGetPosition
mov r0, #0x7e
add r2, sp, #0x8
lsl r0, r0, #0x2
@ -3188,7 +3188,7 @@ sub_02036A14: ; 0x02036A14
ldrb r3, [r3, #0x1]
ldr r0, [r0, #0x0]
mov r1, #0x4
bl sub_0206F190
bl BagCursor_Field_PocketSetPosition
mov r1, #0x7e
lsl r1, r1, #0x2
ldr r1, [r4, r1]

View File

@ -233,7 +233,7 @@ sub_02037400: ; 0x02037400
mov r1, #0xb
bl sub_02034A28
mov r0, #0xb
bl sub_0206F164
bl BagCursor_New
add r1, r4, #0x0
add r1, #0x94
str r0, [r1, #0x0]

View File

@ -267,7 +267,7 @@ sub_02037844: ; 0x02037844
bl Save_Bag_Get
ldr r1, _02037898 ; =UNK_020F2BDC
mov r2, #0xb
bl CreateBagView
bl Bag_CreateView
add r3, r5, #0x0
add r3, #0x94
ldr r1, [r5, #0xc]
@ -328,7 +328,7 @@ _020378C8:
add r0, r6, #0x0
ldr r1, [r1, #0x0]
mov r2, #0x20
bl CreateBagView
bl Bag_CreateView
add r3, r5, #0x0
add r3, #0x94
ldr r1, [r5, #0xc]

View File

@ -46,7 +46,7 @@ sub_020889B0: ; 0x020889B0
str r0, [r4, #0x0]
str r5, [r4, #0x10]
ldr r0, [r4, #0x0]
bl sub_0206F164
bl BagCursor_New
str r0, [r4, #0xc]
ldr r0, [r5, #0x4]
cmp r0, #0x1

View File

@ -5024,22 +5024,22 @@
.extern Bag_PocketNotEmpty
.extern Bag_GetQuantity
.extern Pocket_GetQuantity
.extern CreateBagView
.extern Bag_CreateView
.extern Bag_GetPocketSlotN
.extern Save_Bag_Get
.extern sub_0206F164
.extern sub_0206F17C
.extern sub_0206F18C
.extern sub_0206F190
.extern sub_0206F19C
.extern sub_0206F1A0
.extern sub_0206F1AC
.extern sub_0206F1B0
.extern sub_0206F1B4
.extern sub_0206F1B8
.extern sub_0206F1C0
.extern sub_0206F1E4
.extern sub_0206F1EC
.extern BagCursor_New
.extern BagCursor_Field_PocketGetPosition
.extern BagCursor_Field_GetPocket
.extern BagCursor_Field_PocketSetPosition
.extern BagCursor_Field_SetPocket
.extern BagCursor_Battle_PocketGetPosition
.extern BagCursor_Battle_GetLastUsedItem
.extern BagCursor_Battle_GetLastUsedPocket
.extern BagCursor_Battle_GetPocket
.extern BagCursor_Battle_PocketSetPosition
.extern BagCursor_Battle_Init
.extern BagCursor_Battle_SetLastUsedItem
.extern BagCursor_Battle_SetPocket
.extern sub_0206F3B8
.extern sub_0206F3D8
.extern sub_0207008C

View File

@ -11163,7 +11163,7 @@ ov06_0223ECF0: ; 0x0223ECF0
bl Save_Bag_Get
ldr r1, _0223ED48 ; =0x0224F47C
mov r2, #0xb
bl CreateBagView
bl Bag_CreateView
add r3, r5, #0
str r0, [r4, #4]
add r3, #0x94

View File

@ -3808,7 +3808,7 @@ _02213CA8:
bl ov11_02230218
add r1, r4, #0
add r2, r6, #0
bl sub_0206F1E4
bl BagCursor_Battle_SetLastUsedItem
pop {r3, r4, r5, r6, r7, pc}
thumb_func_start ov09_02213CB8
@ -12685,18 +12685,18 @@ _02218730:
add r1, r5, #0
add r2, r2, r5
add r3, r3, r5
bl sub_0206F1A0
bl BagCursor_Battle_PocketGetPosition
add r0, r5, #1
lsl r0, r0, #0x18
lsr r5, r0, #0x18
cmp r5, #5
blo _02218730
add r0, r6, #0
bl sub_0206F1AC
bl BagCursor_Battle_GetLastUsedItem
ldr r1, [r4]
strh r0, [r1, #0x20]
add r0, r6, #0
bl sub_0206F1B0
bl BagCursor_Battle_GetLastUsedPocket
ldr r1, [r4]
strb r0, [r1, #0x1f]
add r0, r4, #0
@ -12873,7 +12873,7 @@ ov09_02218888: ; 0x02218888
ldr r0, [r4]
ldr r0, [r0]
bl ov11_02230218
bl sub_0206F1B4
bl BagCursor_Battle_GetPocket
ldr r1, _02218950 ; =0x0000114D
strb r0, [r4, r1]
add r0, r4, #0
@ -13687,7 +13687,7 @@ _02218F4E:
ldrb r2, [r2]
ldrb r3, [r3]
add r1, r4, #0
bl sub_0206F1B8
bl BagCursor_Battle_PocketSetPosition
add r0, r4, #1
lsl r0, r0, #0x18
lsr r4, r0, #0x18
@ -13696,7 +13696,7 @@ _02218F4E:
ldr r1, _02218F8C ; =0x0000114D
add r0, r6, #0
ldrb r1, [r5, r1]
bl sub_0206F1EC
bl BagCursor_Battle_SetPocket
_02218F78:
ldr r0, [r5]
mov r1, #1
@ -14300,7 +14300,7 @@ ov09_0221944C: ; 0x0221944C
bl ov11_02230218
add r1, r4, #0
add r2, r6, #0
bl sub_0206F1E4
bl BagCursor_Battle_SetLastUsedItem
pop {r3, r4, r5, r6, r7, pc}
thumb_func_start ov09_02219474

View File

@ -1039,7 +1039,7 @@ _0222DC42:
bl ov11_0222FE94
add r0, r4, #0
bl ov11_02230218
bl sub_0206F1C0
bl BagCursor_Battle_Init
mov r0, #5
mov r1, #4
mov r2, #0

View File

@ -4708,7 +4708,7 @@ _0223F598:
bl ov11_02230218
ldrh r1, [r6]
ldrb r2, [r6, #2]
bl sub_0206F1E4
bl BagCursor_Battle_SetLastUsedItem
_0223F5D2:
ldrh r1, [r6]
mov r0, #0x4a

View File

@ -5810,7 +5810,7 @@ _021DA41E:
bl Save_Bag_Get
ldr r1, _021DA5D8 ; =ov14_021E6264
mov r2, #9
bl CreateBagView
bl Bag_CreateView
mov r1, #0x85
lsl r1, r1, #2
str r0, [r4, r1]

View File

@ -1114,7 +1114,7 @@ _021E74AE:
ldr r0, [r0, #0x6c]
add r2, #1
add r3, sp, #0
bl sub_0206F17C
bl BagCursor_Field_PocketGetPosition
add r0, sp, #0
ldrb r0, [r0, #1]
cmp r0, #0
@ -1139,7 +1139,7 @@ _021E74F2:
add r0, #0xc4
ldr r0, [r0]
ldr r0, [r0, #0x6c]
bl sub_0206F18C
bl BagCursor_Field_GetPocket
mov r1, #0
mov r3, #0xc
_021E7502:
@ -1195,7 +1195,7 @@ _021E7540:
ldr r0, [r0, #0x6c]
lsr r2, r2, #0x18
lsr r3, r3, #0x18
bl sub_0206F190
bl BagCursor_Field_PocketSetPosition
add r4, r4, #1
add r5, #0xc
cmp r4, #8
@ -1210,7 +1210,7 @@ _021E7568:
mul r1, r2
add r1, r7, r1
ldrb r1, [r1, #8]
bl sub_0206F19C
bl BagCursor_Field_SetPocket
_021E757E:
pop {r3, r4, r5, r6, r7, pc}
thumb_func_end ov75_021E752C

View File

@ -1,458 +1,420 @@
#include "global.h"
#include "constants/items.h"
#include "MI_memory.h"
#include "bag.h"
#include "itemtool.h"
#include "heap.h"
u32 Save_Bag_sizeof(void)
{
return sizeof(struct Bag);
static u32 Bag_GetItemPocket(Bag *bag, u16 itemId, ItemSlot **itemSlots, u32 *countPtr, HeapID heapId);
static ItemSlot *Pocket_GetItemSlotForAdd(ItemSlot *slots, u32 count, u16 itemId, u16 quantity, u16 maxQuantity);
static ItemSlot *Bag_GetItemSlotForAdd(Bag *bag, u16 itemId, u16 quantity, HeapID heapId);
static ItemSlot *Pocket_GetItemSlotForRemove(ItemSlot *slots, u32 count, u16 itemId, u16 quantity);
static ItemSlot *Bag_GetItemSlotForRemove(Bag *bag, u16 itemId, u16 quantity, HeapID heapId);
static void SwapItemSlots(ItemSlot *a, ItemSlot *b);
static void PocketCompaction(ItemSlot *slots, u32 count);
static void SortPocket(ItemSlot *slots, u32 count);
u32 Save_Bag_sizeof(void) {
return sizeof(Bag);
}
struct Bag * Save_Bag_New(HeapID heapId)
{
struct Bag * ret = (struct Bag *)AllocFromHeap(heapId, sizeof(struct Bag));
Save_Bag_Init(ret);
return ret;
Bag *Save_Bag_New(HeapID heapId) {
Bag *bag = (Bag *) AllocFromHeap(heapId, sizeof(Bag));
Save_Bag_Init(bag);
return bag;
}
void Save_Bag_Init(struct Bag * bag)
{
MI_CpuClear16(bag, sizeof(struct Bag));
void Save_Bag_Init(Bag *bag) {
MI_CpuClear16(bag, sizeof(Bag));
}
void Save_Bag_Copy(const struct Bag * src, struct Bag * dest)
{
MI_CpuCopy8(src, dest, sizeof(struct Bag));
void Save_Bag_Copy(const Bag *src, Bag *dest) {
MI_CpuCopy8(src, dest, sizeof(Bag));
}
u32 Bag_GetRegisteredItem(struct Bag * bag)
{
u32 Bag_GetRegisteredItem(Bag *bag) {
return bag->registeredItem;
}
void Bag_SetRegisteredItem(struct Bag * bag, u32 item)
{
void Bag_SetRegisteredItem(Bag *bag, u32 item) {
bag->registeredItem = item;
}
u32 Bag_GetItemPocket(struct Bag * bag, u16 item_id, struct ItemSlot ** slot_p, u32 * count_p, HeapID heapId)
{
u32 pocket = GetItemAttr(item_id, 5, heapId);
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;
static u32 Bag_GetItemPocket(Bag *bag, u16 itemId, ItemSlot **itemSlots, u32 *countPtr, HeapID heapId) {
u32 pocket = GetItemAttr(itemId, ITEMATTR_POCKET, heapId);
switch (pocket) {
case POCKET_KEY_ITEMS:
*itemSlots = bag->keyItems;
*countPtr = NUM_BAG_KEY_ITEMS;
break;
case POCKET_ITEMS:
*itemSlots = bag->items;
*countPtr = NUM_BAG_ITEMS;
break;
case POCKET_BERRIES:
*itemSlots = bag->berries;
*countPtr = NUM_BAG_BERRIES;
break;
case POCKET_MEDICINE:
*itemSlots = bag->medicine;
*countPtr = NUM_BAG_MEDICINE;
break;
case POCKET_BALLS:
*itemSlots = bag->balls;
*countPtr = NUM_BAG_BALLS;
break;
case POCKET_BATTLE_ITEMS:
*itemSlots = bag->battleItems;
*countPtr = NUM_BAG_BATTLE_ITEMS;
break;
case POCKET_MAIL:
*itemSlots = bag->mail;
*countPtr = NUM_BAG_MAIL;
break;
case POCKET_TMHMS:
*itemSlots = bag->TMsHMs;
*countPtr = NUM_BAG_TMS_HMS;
break;
}
return pocket;
}
struct ItemSlot * Pocket_GetItemSlotForAdd(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)
static ItemSlot *Pocket_GetItemSlotForAdd(ItemSlot *slots, u32 count, u16 itemId, u16 quantity, u16 maxQuantity) {
s32 i;
s32 found = -1;
for (i = 0; i < count; i++) {
if (slots[i].id == itemId) {
// Only one stack allowed per item.
// If the resulting stack would be too large,
// pretend there's no room for it.
if (quantity + slots[i].quantity > maxQuantity) {
return NULL;
}
return &slots[i];
}
if (found == -1 && slots[i].id == ITEM_NONE && slots[i].quantity == 0)
{
if (found == -1 && slots[i].id == ITEM_NONE && slots[i].quantity == 0) {
found = i;
}
}
if (found == -1)
if (found == -1) {
return NULL;
}
return &slots[found];
}
struct ItemSlot * Bag_GetItemSlotForAdd(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId)
{
struct ItemSlot * slots;
static ItemSlot *Bag_GetItemSlotForAdd(Bag *bag, u16 itemId, u16 quantity, HeapID heapId) {
ItemSlot *slots;
u32 count;
u32 pocket = Bag_GetItemPocket(bag, item_id, &slots, &count, heapId);
if (pocket == POCKET_TMHMS)
{
return Pocket_GetItemSlotForAdd(slots, count, item_id, quantity, 99);
}
else
{
return Pocket_GetItemSlotForAdd(slots, count, item_id, quantity, 999);
u32 pocket = Bag_GetItemPocket(bag, itemId, &slots, &count, heapId);
if (pocket == POCKET_TMHMS) {
return Pocket_GetItemSlotForAdd(slots, count, itemId, quantity, BAG_TMHM_QUANTITY_MAX);
} else {
return Pocket_GetItemSlotForAdd(slots, count, itemId, quantity, BAG_SLOT_QUANTITY_MAX);
}
}
BOOL Bag_HasSpaceForItem(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId)
{
return Bag_GetItemSlotForAdd(bag, item_id, quantity, heapId) != NULL;
BOOL Bag_HasSpaceForItem(Bag *bag, u16 itemId, u16 quantity, HeapID heapId) {
return Bag_GetItemSlotForAdd(bag, itemId, quantity, heapId) != NULL;
}
BOOL Bag_AddItem(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId)
{
struct ItemSlot * slots = Bag_GetItemSlotForAdd(bag, item_id, quantity, heapId);
if (slots == NULL)
BOOL Bag_AddItem(Bag *bag, u16 itemId, u16 quantity, HeapID heapId) {
ItemSlot *slot = Bag_GetItemSlotForAdd(bag, itemId, quantity, heapId);
if (slot == NULL) {
return FALSE;
slots->id = item_id;
slots->quantity += quantity;
}
slot->id = itemId;
slot->quantity += quantity;
u32 count;
u32 pocket = Bag_GetItemPocket(bag, item_id, &slots, &count, heapId);
if (pocket == POCKET_TMHMS || pocket == POCKET_BERRIES)
{
SortPocket(slots, count);
u32 pocket = Bag_GetItemPocket(bag, itemId, &slot, &count, heapId);
if (pocket == POCKET_TMHMS || pocket == POCKET_BERRIES) {
SortPocket(slot, count);
}
return TRUE;
}
struct ItemSlot * Pocket_GetItemSlotForRemove(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;
static ItemSlot *Pocket_GetItemSlotForRemove(ItemSlot *slots, u32 count, u16 itemId, u16 quantity) {
for (s32 i = 0; i < count; i++) {
if (slots[i].id == itemId) {
if (slots[i].quantity < quantity) {
return NULL;
}
return &slots[i];
}
}
return NULL;
}
struct ItemSlot * Bag_GetItemSlotForRemove(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId)
{
struct ItemSlot * slots;
static ItemSlot *Bag_GetItemSlotForRemove(Bag *bag, u16 itemId, u16 quantity, HeapID heapId) {
ItemSlot *slots;
u32 count;
(void)Bag_GetItemPocket(bag, item_id, &slots, &count, heapId);
return Pocket_GetItemSlotForRemove(slots, count, item_id, quantity);
Bag_GetItemPocket(bag, itemId, &slots, &count, heapId);
return Pocket_GetItemSlotForRemove(slots, count, itemId, quantity);
}
BOOL Bag_TakeItem(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId)
{
struct ItemSlot * slots = Bag_GetItemSlotForRemove(bag, item_id, quantity, heapId);
if (slots == NULL)
return FALSE;
slots->quantity -= quantity;
if (slots->quantity == 0)
slots->id = ITEM_NONE;
u32 count;
(void)Bag_GetItemPocket(bag, item_id, &slots, &count, heapId);
PocketCompaction(slots, count);
return TRUE;
}
BOOL Pocket_TakeItem(struct ItemSlot * slots, u32 count, u16 item_id, u16 quantity)
{
struct ItemSlot * slot = Pocket_GetItemSlotForRemove(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 Bag_HasItem(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId)
{
return Bag_GetItemSlotForRemove(bag, item_id, quantity, heapId) != NULL;
}
BOOL Bag_PocketNotEmpty(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:
BOOL Bag_TakeItem(Bag *bag, u16 itemId, u16 quantity, HeapID heapId) {
ItemSlot *slot = Bag_GetItemSlotForRemove(bag, itemId, quantity, heapId);
if (slot == NULL) {
return FALSE;
}
int i;
for (i = 0; i < count; i++)
{
if (slots[i].id != ITEM_NONE)
slot->quantity -= quantity;
if (slot->quantity == 0) {
slot->id = ITEM_NONE;
}
u32 count;
Bag_GetItemPocket(bag, itemId, &slot, &count, heapId);
PocketCompaction(slot, count);
return TRUE;
}
BOOL Pocket_TakeItem(ItemSlot *slots, u32 count, u16 itemId, u16 quantity) {
ItemSlot *slot = Pocket_GetItemSlotForRemove(slots, count, itemId, quantity);
if (slot == NULL) {
return FALSE;
}
slot->quantity -= quantity;
if (slot->quantity == 0) {
slot->id = ITEM_NONE;
}
PocketCompaction(slots, count);
return TRUE;
}
BOOL Bag_HasItem(Bag *bag, u16 itemId, u16 quantity, HeapID heapId) {
return Bag_GetItemSlotForRemove(bag, itemId, quantity, heapId) != NULL;
}
BOOL Bag_PocketNotEmpty(Bag *bag, u32 pocket) {
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;
}
for (s32 i = 0; i < count; i++) {
if (slots[i].id != ITEM_NONE) {
return TRUE;
}
}
return FALSE;
}
u16 Bag_GetQuantity(struct Bag * bag, u16 item_id, HeapID heapId)
{
struct ItemSlot * slot = Bag_GetItemSlotForRemove(bag, item_id, 1, heapId);
if (slot == NULL)
u16 Bag_GetQuantity(Bag *bag, u16 itemId, HeapID heapId) {
ItemSlot *slot = Bag_GetItemSlotForRemove(bag, itemId, 1, heapId);
if (slot == NULL) {
return 0;
}
return slot->quantity;
}
u16 Pocket_GetQuantity(struct ItemSlot * slots, u32 count, u16 item_id)
{
struct ItemSlot * slot = Pocket_GetItemSlotForRemove(slots, count, item_id, 1);
if (slot == NULL)
u16 Pocket_GetQuantity(ItemSlot *slots, u32 count, u16 itemId) {
ItemSlot *slot = Pocket_GetItemSlotForRemove(slots, count, itemId, 1);
if (slot == NULL) {
return 0;
}
return slot->quantity;
}
void SwapItemSlots(struct ItemSlot * a, struct ItemSlot * b)
{
struct ItemSlot tmp;
tmp = *a;
static void SwapItemSlots(ItemSlot *a, ItemSlot *b) {
ItemSlot c = *a;
*a = *b;
*b = tmp;
*b = c;
}
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)
{
static void PocketCompaction(ItemSlot *slots, u32 count) {
for (s32 i = 0; i < count - 1; i++) {
for (s32 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))
{
static void SortPocket(ItemSlot *slots, u32 count) {
for (s32 i = 0; i < count - 1; i++) {
for (s32 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]);
}
}
}
}
struct BagView * CreateBagView(struct Bag * bag, const u8 * pockets, HeapID heapId)
BagView *Bag_CreateView(Bag *bag, const u8 *pockets, HeapID heapId)
{
struct BagView * view = BagView_New((u8)heapId);
BagView *ret = BagView_New(heapId);
for (u32 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;
for (u32 i = 0; pockets[i] != POCKET_BAG_VIEW_END; i++) {
switch (pockets[i]) {
case POCKET_KEY_ITEMS:
BagView_SetItem(ret, bag->keyItems, POCKET_KEY_ITEMS, i);
break;
case POCKET_ITEMS:
BagView_SetItem(ret, bag->items, POCKET_ITEMS, i);
break;
case POCKET_BERRIES:
BagView_SetItem(ret, bag->berries, POCKET_BERRIES, i);
break;
case POCKET_MEDICINE:
BagView_SetItem(ret, bag->medicine, POCKET_MEDICINE, i);
break;
case POCKET_BALLS:
BagView_SetItem(ret, bag->balls, POCKET_BALLS, i);
break;
case POCKET_BATTLE_ITEMS:
BagView_SetItem(ret, bag->battleItems, POCKET_BATTLE_ITEMS, i);
break;
case POCKET_MAIL:
BagView_SetItem(ret, bag->mail, POCKET_MAIL, i);
break;
case POCKET_TMHMS:
BagView_SetItem(ret, bag->TMsHMs, POCKET_TMHMS, i);
break;
}
}
return view;
}
struct ItemSlot * Bag_GetPocketSlotN(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 * Save_Bag_Get(struct SaveData * save)
{
return (struct Bag *)SaveArray_Get(save, 3);
}
struct BagCursor * sub_0206F164(HeapID heapId)
{
struct BagCursor * ret = (struct BagCursor *)AllocFromHeap(heapId, sizeof(struct BagCursor));
MI_CpuClear16(ret, sizeof(struct BagCursor));
return ret;
}
void sub_0206F17C(struct BagCursor * a0, u32 a1, u8 * a2, u8 * a3)
{
*a2 = a0->field.position[a1];
*a3 = a0->field.scroll[a1];
}
ItemSlot *Bag_GetPocketSlotN(Bag *bag, u8 pocket, u32 slot) {
ItemSlot *slots;
u32 count;
u16 sub_0206F18C(struct BagCursor * a0)
{
return a0->field.pocket;
}
void sub_0206F190(struct BagCursor * a0, u32 a1, u8 a2, u8 a3)
{
a0->field.position[a1] = a2;
a0->field.scroll[a1] = a3;
}
void sub_0206F19C(struct BagCursor * a0, u16 a1)
{
a0->field.pocket = a1;
}
void sub_0206F1A0(struct BagCursor * a0, u32 a1, u8 * a2, u8 * a3)
{
*a2 = a0->battle.position[a1];
*a3 = a0->battle.scroll[a1];
}
u16 sub_0206F1AC(struct BagCursor * a0)
{
return a0->battle.lastUsedItem;
}
u16 sub_0206F1B0(struct BagCursor * a0)
{
return a0->battle.lastUsedPocket;
}
u16 sub_0206F1B4(struct BagCursor * a0)
{
return a0->battle.pocket;
}
void sub_0206F1B8(struct BagCursor * a0, u32 a1, u8 a2, u8 a3)
{
a0->battle.position[a1] = a2;
a0->battle.scroll[a1] = a3;
}
void sub_0206F1C0(struct BagCursor * a0)
{
u32 i;
for (i = 0; i < 5; i++)
{
sub_0206F1B8(a0, i, 0, 0);
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;
}
sub_0206F1EC(a0, 0);
// UB: If pocket invalid, count and slot are uninitialized
if (slot >= count) {
return NULL;
}
return &slots[slot];
}
void sub_0206F1E4(struct BagCursor * a0, u16 a1, u16 a2)
{
a0->battle.lastUsedItem = a1;
a0->battle.lastUsedPocket = a2;
Bag *Save_Bag_Get(SaveData *saveData) {
return SaveArray_Get(saveData, SAVE_BAG);
}
void sub_0206F1EC(struct BagCursor * a0, u16 a1)
{
a0->battle.pocket = a1;
BagCursor *BagCursor_New(HeapID heapId) {
BagCursor *ret = AllocFromHeap(heapId, sizeof(BagCursor));
MI_CpuClear16(ret, sizeof(BagCursor));
return ret;
}
void BagCursor_Field_PocketGetPosition(BagCursor *cursor, u32 pocket, u8 *position, u8 *scroll) {
*position = cursor->field.position[pocket];
*scroll = cursor->field.scroll[pocket];
}
u16 BagCursor_Field_GetPocket(BagCursor *cursor) {
return cursor->field.pocket;
}
void BagCursor_Field_PocketSetPosition(BagCursor *cursor, u32 pocket, u8 position, u8 scroll) {
cursor->field.position[pocket] = position;
cursor->field.scroll[pocket] = scroll;
}
void BagCursor_Field_SetPocket(BagCursor *cursor, u16 pocket) {
cursor->field.pocket = pocket;
}
void BagCursor_Battle_PocketGetPosition(BagCursor *cursor, u32 pocket, u8 *position, u8 *scroll) {
*position = cursor->battle.position[pocket];
*scroll = cursor->battle.scroll[pocket];
}
u16 BagCursor_Battle_GetLastUsedItem(BagCursor *cursor) {
return cursor->battle.lastUsedItem;
}
u16 BagCursor_Battle_GetLastUsedPocket(BagCursor *cursor) {
return cursor->battle.lastUsedPocket;
}
u16 BagCursor_Battle_GetPocket(BagCursor *cursor) {
return cursor->battle.pocket;
}
void BagCursor_Battle_PocketSetPosition(BagCursor *cursor, u32 pocket, u8 position, u8 scroll) {
cursor->battle.position[pocket] = position;
cursor->battle.scroll[pocket] = scroll;
}
void BagCursor_Battle_Init(BagCursor *cursor) {
for (u32 i = 0; i < 5; i++) {
BagCursor_Battle_PocketSetPosition(cursor, i, 0, 0);
}
BagCursor_Battle_SetPocket(cursor, 0);
}
void BagCursor_Battle_SetLastUsedItem(BagCursor *cursor, u16 itemId, u16 pocket) {
cursor->battle.lastUsedItem = itemId;
cursor->battle.lastUsedPocket = pocket;
}
void BagCursor_Battle_SetPocket(BagCursor *cursor, u16 pocket) {
cursor->battle.pocket = pocket;
}

View File

@ -5,7 +5,7 @@
#include "gx.h"
#include "heap.h"
const u8 sTilemapWidthByBufferSize[] = {
static const u8 sTilemapWidthByBufferSize[] = {
[GF_BG_SCR_SIZE_128x128] = 0x10,
[GF_BG_SCR_SIZE_256x256] = 0x20,
[GF_BG_SCR_SIZE_256x512] = 0x20,

View File

@ -89,7 +89,7 @@ u32 sub_02088B4C(struct UnkStruct_02088AAC *r0)
.exitFunc = ov75_021E6F00,
.ovly = FS_OVERLAY_ID(OVERLAY_75)
};
struct BagView *bag_view = CreateBagView(r0->poffinCaseAppData->bag, UNK_020FD6F4, r0->heapId);
struct BagView *bag_view = Bag_CreateView(r0->poffinCaseAppData->bag, UNK_020FD6F4, r0->heapId);
sub_0206E314(bag_view, r0->poffinCaseAppData->save, (u8)((u8)r0->unk06 == 1 ? 5 : 4), r0->unk0C);
@ -166,7 +166,7 @@ u32 sub_02088C3C(struct UnkStruct_02088AAC *r0)
u8 sp5;
u8 sp6;
sub_0206F17C(r0->unk0C, 4, &sp6, &sp5);
BagCursor_Field_PocketGetPosition(r0->unk0C, 4, &sp6, &sp5);
sub_020851F8(r0->ovly_param, sp5, sp6, (u8)(berry_count + 2));
r0->ovly_data = OverlayManager_New(&OVERLAY_68_MANAGER, (s32 *)r0->ovly_param, r0->heapId);
@ -185,7 +185,7 @@ u32 sub_02088CDC(struct UnkStruct_02088AAC *r0)
u8 sp1;
sub_0208524C(r0->ovly_param, &sp0, &sp1);
sub_0206F190(r0->unk0C, 4, sp1, sp0);
BagCursor_Field_PocketSetPosition(r0->unk0C, 4, sp1, sp0);
FreeToHeap(r0->ovly_param);
r0->ovly_param = NULL;

View File

@ -1,4 +1,6 @@
narc_0000.NCLR
narc_0001.NANR
narc_0003.NANR
*.NCER
narc_0007.NCGR
narc_0008.NCGR

View File

@ -0,0 +1,46 @@
{
"labelEnabled": true,
"sequenceCount": 2,
"frameCount": 2,
"sequences": [
{
"frameCount": 1,
"loopStartFrame": 0,
"animationElement": 0,
"animationType": 1,
"playbackMode": 1,
"frameData": [
{
"frameDelay": 1,
"resultId": 0
}
]
},
{
"frameCount": 1,
"loopStartFrame": 0,
"animationElement": 0,
"animationType": 1,
"playbackMode": 1,
"frameData": [
{
"frameDelay": 1,
"resultId": 1
}
]
}
],
"animationResults": [
{
"resultType": 0,
"index": 0
},
{
"resultType": 0,
"index": 1
}
],
"resultCount": 2,
"labels": ["CellAnime0", "CellAnime1"],
"labelCount": 2
}

View File

@ -0,0 +1,140 @@
{
"labelEnabled": true,
"sequenceCount": 6,
"frameCount": 12,
"sequences": [
{
"frameCount": 1,
"loopStartFrame": 0,
"animationElement": 0,
"animationType": 1,
"playbackMode": 1,
"frameData": [
{
"frameDelay": 1,
"resultId": 0
}
]
},
{
"frameCount": 2,
"loopStartFrame": 0,
"animationElement": 0,
"animationType": 1,
"playbackMode": 2,
"frameData": [
{
"frameDelay": 4,
"resultId": 0
},
{
"frameDelay": 4,
"resultId": 1
}
]
},
{
"frameCount": 2,
"loopStartFrame": 0,
"animationElement": 0,
"animationType": 1,
"playbackMode": 2,
"frameData": [
{
"frameDelay": 6,
"resultId": 0
},
{
"frameDelay": 6,
"resultId": 1
}
]
},
{
"frameCount": 2,
"loopStartFrame": 0,
"animationElement": 0,
"animationType": 1,
"playbackMode": 2,
"frameData": [
{
"frameDelay": 12,
"resultId": 0
},
{
"frameDelay": 12,
"resultId": 1
}
]
},
{
"frameCount": 2,
"loopStartFrame": 0,
"animationElement": 0,
"animationType": 1,
"playbackMode": 2,
"frameData": [
{
"frameDelay": 20,
"resultId": 0
},
{
"frameDelay": 20,
"resultId": 1
}
]
},
{
"frameCount": 3,
"loopStartFrame": 0,
"animationElement": 2,
"animationType": 1,
"playbackMode": 2,
"frameData": [
{
"frameDelay": 32,
"resultId": 2
},
{
"frameDelay": 2,
"resultId": 3
},
{
"frameDelay": 2,
"resultId": 4
}
]
}
],
"animationResults": [
{
"resultType": 0,
"index": 0
},
{
"resultType": 0,
"index": 1
},
{
"resultType": 2,
"index": 0,
"positionX": 0,
"positionY": 0
},
{
"resultType": 2,
"index": 0,
"positionX": 1,
"positionY": 0
},
{
"resultType": 2,
"index": 0,
"positionX": -1,
"positionY": 0
}
],
"resultCount": 5,
"labels": ["CellAnime0", "CellAnime1", "CellAnime2", "CellAnime3", "CellAnime4", "CellAnime5"],
"labelCount": 6
}

View File

@ -2671,7 +2671,9 @@ files/poketool/pokegra/pokegra.narc: \
files/poketool/icongra/poke_icon.narc: \
files/poketool/icongra/poke_icon/narc_0000.NCLR \
files/poketool/icongra/poke_icon/narc_0001.NANR \
files/poketool/icongra/poke_icon/narc_0002.NCER \
files/poketool/icongra/poke_icon/narc_0003.NANR \
files/poketool/icongra/poke_icon/narc_0004.NCER \
files/poketool/icongra/poke_icon/narc_0006.NCER \
files/poketool/icongra/poke_icon/narc_0007.NCGR \

View File

@ -1211,3 +1211,6 @@ NCLR_CLEAN_LIST := files/application/wifi_earth/wifi_earth/narc_0006.NCLR \
NCER_CLEAN_LIST := files/poketool/icongra/poke_icon/narc_0002.NCER \
files/poketool/icongra/poke_icon/narc_0004.NCER \
files/poketool/icongra/poke_icon/narc_0006.NCER
NANR_CLEAN_LIST := files/poketool/icongra/poke_icon/narc_0001.NANR \
files/poketool/icongra/poke_icon/narc_0003.NANR

View File

@ -7,54 +7,34 @@
#include "save.h"
typedef struct Bag {
struct ItemSlot items[NUM_BAG_ITEMS];
struct ItemSlot keyItems[NUM_BAG_KEY_ITEMS];
struct ItemSlot TMsHMs[NUM_BAG_TMS_HMS];
struct ItemSlot mail[NUM_BAG_MAIL];
struct ItemSlot medicine[NUM_BAG_MEDICINE];
struct ItemSlot berries[NUM_BAG_BERRIES];
struct ItemSlot balls[NUM_BAG_BALLS];
struct ItemSlot battleItems[NUM_BAG_BATTLE_ITEMS];
ItemSlot items[NUM_BAG_ITEMS];
ItemSlot keyItems[NUM_BAG_KEY_ITEMS];
ItemSlot TMsHMs[NUM_BAG_TMS_HMS];
ItemSlot mail[NUM_BAG_MAIL];
ItemSlot medicine[NUM_BAG_MEDICINE];
ItemSlot berries[NUM_BAG_BERRIES];
ItemSlot balls[NUM_BAG_BALLS];
ItemSlot battleItems[NUM_BAG_BATTLE_ITEMS];
u32 registeredItem;
} Bag;
u32 Save_Bag_sizeof(void);
struct Bag * Save_Bag_New(HeapID heapId);
void Save_Bag_Init(struct Bag * bag);
void Save_Bag_Copy(const struct Bag * src, struct Bag * dest);
u32 Bag_GetRegisteredItem(struct Bag * bag);
void Bag_SetRegisteredItem(struct Bag * bag, u32 item);
u32 Bag_GetItemPocket(struct Bag * bag, u16 item_id, struct ItemSlot ** slot_p, u32 * count_p, HeapID heapId);
struct ItemSlot * Pocket_GetItemSlotForAdd(struct ItemSlot * slots, u32 count, u16 item_id, u16 quantity, u16 maxquantity);
struct ItemSlot * Bag_GetItemSlotForAdd(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId);
BOOL Bag_HasSpaceForItem(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId);
BOOL Bag_AddItem(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId);
struct ItemSlot * Pocket_GetItemSlotForRemove(struct ItemSlot * slots, u32 count, u16 item_id, u16 quantity);
struct ItemSlot * Bag_GetItemSlotForRemove(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId);
BOOL Bag_TakeItem(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId);
BOOL Pocket_TakeItem(struct ItemSlot * slots, u32 count, u16 item_id, u16 quantity);
BOOL Bag_HasItem(struct Bag * bag, u16 item_id, u16 quantity, HeapID heapId);
BOOL Bag_PocketNotEmpty(struct Bag * bag, u32 pocket);
u16 Bag_GetQuantity(struct Bag * bag, u16 item_id, HeapID heapId);
u16 Pocket_GetQuantity(struct ItemSlot * slots, u32 count, u16 item_id);
void SwapItemSlots(struct ItemSlot * a, struct ItemSlot * b);
void PocketCompaction(struct ItemSlot * slots, u32 count);
void SortPocket(struct ItemSlot * slots, u32 count);
struct BagView * CreateBagView(struct Bag * bag, const u8 * pockets, HeapID heapId);
struct ItemSlot * Bag_GetPocketSlotN(struct Bag * bag, u32 pocket, u32 slot);
struct Bag * Save_Bag_Get(struct SaveData * save);
struct BagCursor * sub_0206F164(HeapID heapId);
void sub_0206F17C(struct BagCursor * a0, u32 a1, u8 * a2, u8 * a3);
u16 sub_0206F18C(struct BagCursor * a0);
void sub_0206F190(struct BagCursor * a0, u32 a1, u8 a2, u8 a3);
void sub_0206F19C(struct BagCursor * a0, u16 a1);
void sub_0206F1A0(struct BagCursor * a0, u32 a1, u8 * a2, u8 * a3);
u16 sub_0206F1AC(struct BagCursor * a0);
u16 sub_0206F1B0(struct BagCursor * a0);
u16 sub_0206F1B4(struct BagCursor * a0);
void sub_0206F1B8(struct BagCursor * a0, u32 a1, u8 a2, u8 a3);
void sub_0206F1C0(struct BagCursor * a0);
void sub_0206F1E4(struct BagCursor * a0, u16 a1, u16 a2);
void sub_0206F1EC(struct BagCursor * a0, u16 a1);
Bag *Save_Bag_New(HeapID heapId);
void Save_Bag_Init(Bag *bag);
void Save_Bag_Copy(const Bag *src, Bag *dest);
u32 Bag_GetRegisteredItem(Bag *bag);
void Bag_SetRegisteredItem(Bag *bag, u32 item);
BOOL Bag_HasSpaceForItem(Bag *bag, u16 itemId, u16 quantity, HeapID heapId);
BOOL Bag_AddItem(Bag *bag, u16 itemId, u16 quantity, HeapID heapId);
BOOL Bag_TakeItem(Bag *bag, u16 itemId, u16 quantity, HeapID heapId);
BOOL Pocket_TakeItem(ItemSlot *slots, u32 count, u16 itemId, u16 quantity);
BOOL Bag_HasItem(Bag *bag, u16 itemId, u16 quantity, HeapID heapId);
BOOL Bag_PocketNotEmpty(Bag *bag, u32 pocket);
u16 Bag_GetQuantity(Bag *bag, u16 itemId, HeapID heapId);
u16 Pocket_GetQuantity(ItemSlot *slots, u32 count, u16 itemId);
void SortPocket(ItemSlot *slots, u32 count);
BagView * Bag_CreateView(Bag *bag, const u8 *pockets, HeapID heapId);
ItemSlot *Bag_GetPocketSlotN(Bag *bag, u8 pocket, u32 slot);
Bag *Save_Bag_Get(SaveData *saveData);
#endif //POKEDIAMOND_BAG_H

View File

@ -2,6 +2,7 @@
#define POKEDIAMOND_BAG_CURSOR_H
#include "global.h"
#include "heap.h"
typedef struct BagCursorField {
u8 scroll[8];
@ -23,4 +24,18 @@ typedef struct BagCursor {
BagCursorBattle battle;
} BagCursor;
BagCursor *BagCursor_New(HeapID heapId);
void BagCursor_Field_PocketGetPosition(BagCursor *cursor, u32 pocket, u8 *position, u8 *scroll);
u16 BagCursor_Field_GetPocket(BagCursor *cursor);
void BagCursor_Field_PocketSetPosition(BagCursor *cursor, u32 pocket, u8 position, u8 scroll);
void BagCursor_Field_SetPocket(BagCursor *cursor, u16 pocket);
void BagCursor_Battle_PocketGetPosition(BagCursor *cursor, u32 pocket, u8 *position, u8 *scroll);
u16 BagCursor_Battle_GetLastUsedItem(BagCursor *cursor);
u16 BagCursor_Battle_GetLastUsedPocket(BagCursor *cursor);
u16 BagCursor_Battle_GetPocket(BagCursor *cursor);
void BagCursor_Battle_PocketSetPosition(BagCursor *cursor, u32 pocket, u8 position, u8 scroll);
void BagCursor_Battle_Init(BagCursor *cursor);
void BagCursor_Battle_SetLastUsedItem(BagCursor *cursor, u16 itemId, u16 pocket);
void BagCursor_Battle_SetPocket(BagCursor *cursor, u16 pocket);
#endif // POKEDIAMOND_BAG_CURSOR_H

View File

@ -10,6 +10,8 @@
#define POCKET_BATTLE_ITEMS 6
#define POCKET_KEY_ITEMS 7
#define POCKET_BAG_VIEW_END 0xFF
#define NUM_BAG_ITEMS 165
#define NUM_BAG_KEY_ITEMS 50
#define NUM_BAG_TMS_HMS 100
@ -19,6 +21,9 @@
#define NUM_BAG_BALLS 15
#define NUM_BAG_BATTLE_ITEMS 30
#define BAG_SLOT_QUANTITY_MAX 999
#define BAG_TMHM_QUANTITY_MAX 99
#define ITEMATTR_PRICE 0
#define ITEMATTR_HOLD_EFFECT 1
#define ITEMATTR_HOLD_EFFECT_PARAM 2

View File

@ -1,6 +1,7 @@
#ifndef POKEDIAMOND_CONSTANTS_SAVE_ARRAYS_H
#define POKEDIAMOND_CONSTANTS_SAVE_ARRAYS_H
#define SAVE_BAG 3
#define SAVE_SAFARI_ZONE 27
#define SAVE_BLOCK_NUM 36

View File

@ -1,4 +1,4 @@
Copyright (c) 2015 YamaArashi
Copyright (c) 2015 YamaArashi, 2021-2023 red031000
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -19,7 +19,7 @@ all: nitrogfx
@:
nitrogfx-debug: $(SRCS) convert_png.h gfx.h global.h jasc_pal.h lz.h rl.h util.h font.h json.h cJSON.h
$(CC) $(CFLAGS) -DDEBUG $(SRCS) -o $@ $(LDFLAGS) $(LIBS)
$(CC) $(CFLAGS) -g -DDEBUG $(SRCS) -o $@ $(LDFLAGS) $(LIBS)
nitrogfx: $(SRCS) convert_png.h gfx.h global.h jasc_pal.h lz.h rl.h util.h font.h json.h cJSON.h
$(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS)

View File

@ -96,9 +96,9 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
return (const char*) (global_error.json + global_error.position);
}
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
{
if (!cJSON_IsString(item))
if (!cJSON_IsString(item))
{
return NULL;
}
@ -106,9 +106,9 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
return item->valuestring;
}
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
{
if (!cJSON_IsNumber(item))
if (!cJSON_IsNumber(item))
{
return (double) NAN;
}
@ -117,8 +117,8 @@ CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
}
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 14)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
CJSON_PUBLIC(const char*) cJSON_Version(void)
@ -347,7 +347,7 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu
goto loop_end;
}
}
loop_end:
loop_end:
number_c_string[i] = '\0';
number = strtod((const char*)number_c_string, (char**)&after_end);
@ -511,7 +511,7 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
return NULL;
}
memcpy(newbuffer, p->buffer, p->offset + 1);
p->hooks.deallocate(p->buffer);
}
@ -761,7 +761,7 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi
return sequence_length;
fail:
fail:
return 0;
}
@ -820,7 +820,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
{
*output_pointer++ = *input_pointer++;
}
/* escape sequence */
/* escape sequence */
else
{
unsigned char sequence_length = 2;
@ -852,7 +852,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
*output_pointer++ = input_pointer[1];
break;
/* UTF-16 literal */
/* UTF-16 literal */
case 'u':
sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
if (sequence_length == 0)
@ -880,7 +880,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu
return true;
fail:
fail:
if (output != NULL)
{
input_buffer->hooks.deallocate(output);
@ -1045,7 +1045,7 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
{
buffer->offset++;
buffer->offset++;
}
if (buffer->offset == buffer->length)
@ -1103,7 +1103,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer
}
buffer.content = (const unsigned char*)value;
buffer.length = buffer_length;
buffer.length = buffer_length;
buffer.offset = 0;
buffer.hooks = global_hooks;
@ -1135,7 +1135,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer
return item;
fail:
fail:
if (item != NULL)
{
cJSON_Delete(item);
@ -1230,7 +1230,7 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i
return printed;
fail:
fail:
if (buffer->buffer != NULL)
{
hooks->deallocate(buffer->buffer);
@ -1508,7 +1508,7 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
goto fail; /* expected end of array */
}
success:
success:
input_buffer->depth--;
if (head != NULL) {
@ -1522,7 +1522,7 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf
return true;
fail:
fail:
if (head != NULL)
{
cJSON_Delete(head);
@ -1684,7 +1684,7 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
goto fail; /* expected end of object */
}
success:
success:
input_buffer->depth--;
if (head != NULL) {
@ -1697,7 +1697,7 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu
input_buffer->offset++;
return true;
fail:
fail:
if (head != NULL)
{
cJSON_Delete(head);
@ -1989,7 +1989,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
}
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic push
#pragma GCC diagnostic push
#endif
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wcast-qual"
@ -2000,7 +2000,7 @@ static void* cast_away_const(const void* string)
return (void*)string;
}
#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#endif
@ -2689,7 +2689,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co
if (a && a->child) {
a->child->prev = n;
}
return a;
}
@ -2768,7 +2768,7 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
return newitem;
fail:
fail:
if (newitem != NULL)
{
cJSON_Delete(newitem);
@ -2976,7 +2976,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
{
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
{
return false;
}

View File

@ -81,7 +81,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 14
#define CJSON_VERSION_PATCH 15
#include <stddef.h>
@ -124,9 +124,9 @@ typedef struct cJSON
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
@ -255,8 +255,8 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable adress area. */
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Copyright (c) 2015 YamaArashi
// Copyright (c) 2015 YamaArashi, 2021-2023 red031000
#ifndef GFX_H
#define GFX_H
@ -30,10 +30,10 @@ struct Image {
};
void ReadImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors);
uint32_t ReadNtrImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors);
uint32_t ReadNtrImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors, bool scanFrontToBack);
void WriteImage(char *path, int numTiles, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors);
void WriteNtrImage(char *path, int numTiles, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image,
bool invertColors, bool clobberSize, bool byteOrder, bool version101, bool sopc, bool scanned,
bool invertColors, bool clobberSize, bool byteOrder, bool version101, bool sopc, uint32_t scanMode,
uint32_t key, bool wrongSize);
void FreeImage(struct Image *image);
void ReadGbaPalette(char *path, struct Palette *palette);
@ -41,6 +41,7 @@ void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIn
void WriteGbaPalette(char *path, struct Palette *palette);
void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum);
void WriteNtrCell(char *path, struct JsonToCellOptions *options);
void WriteNtrScreen(char *outputPath, struct JsonToScreenOptions *options);
void WriteNtrScreen(char *path, struct JsonToScreenOptions *options);
void WriteNtrAnimation(char *path, struct JsonToAnimationOptions *options);
#endif // GFX_H

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 red031000
// Copyright (c) 2021-2023 red031000
#include "global.h"
#include "cJSON.h"
@ -230,6 +230,176 @@ struct JsonToScreenOptions *ParseNSCRJson(char *path)
return options;
}
struct JsonToAnimationOptions *ParseNANRJson(char *path)
{
int filelength;
unsigned char *jsonString = ReadWholeFile(path, &filelength);
cJSON *json = cJSON_Parse((const char *)jsonString);
struct JsonToAnimationOptions *options = malloc(sizeof(struct JsonToAnimationOptions));
if (json == NULL)
{
const char *errorPtr = cJSON_GetErrorPtr();
FATAL_ERROR("Error in line \"%s\"\n", errorPtr);
}
cJSON *sequenceCount = cJSON_GetObjectItemCaseSensitive(json, "sequenceCount");
cJSON *frameCount = cJSON_GetObjectItemCaseSensitive(json, "frameCount");
options->sequenceCount = GetInt(sequenceCount);
options->frameCount = GetInt(frameCount);
options->sequenceData = malloc(sizeof(struct SequenceData *) * options->sequenceCount);
int i;
for (i = 0; i < options->sequenceCount; i++)
{
options->sequenceData[i] = malloc(sizeof(struct SequenceData));
}
cJSON *sequence = NULL;
cJSON *sequences = cJSON_GetObjectItemCaseSensitive(json, "sequences");
i = 0;
cJSON_ArrayForEach(sequence, sequences)
{
if (i > options->sequenceCount - 1)
FATAL_ERROR("Sequence count is incorrect.\n");
cJSON *frameCount = cJSON_GetObjectItemCaseSensitive(sequence, "frameCount");
cJSON *loopStartFrame = cJSON_GetObjectItemCaseSensitive(sequence, "loopStartFrame");
cJSON *animationElement = cJSON_GetObjectItemCaseSensitive(sequence, "animationElement");
cJSON *animationType = cJSON_GetObjectItemCaseSensitive(sequence, "animationType");
cJSON *playbackMode = cJSON_GetObjectItemCaseSensitive(sequence, "playbackMode");
options->sequenceData[i]->frameCount = GetInt(frameCount);
options->sequenceData[i]->loopStartFrame = GetInt(loopStartFrame);
options->sequenceData[i]->animationElement = GetInt(animationElement);
options->sequenceData[i]->animationType = GetInt(animationType);
options->sequenceData[i]->playbackMode = GetInt(playbackMode);
options->sequenceData[i]->frameData = malloc(sizeof(struct FrameData *) * options->sequenceData[i]->frameCount);
int j;
for (j = 0; j < options->sequenceData[i]->frameCount; j++)
{
options->sequenceData[i]->frameData[j] = malloc(sizeof(struct FrameData));
}
j = 0;
cJSON *frame = NULL;
cJSON *frameData = cJSON_GetObjectItemCaseSensitive(sequence, "frameData");
cJSON_ArrayForEach(frame, frameData)
{
if (j > options->sequenceData[i]->frameCount - 1)
FATAL_ERROR("Sequence frame count is incorrect.\n");
cJSON *frameDelay = cJSON_GetObjectItemCaseSensitive(frame, "frameDelay");
cJSON *resultId = cJSON_GetObjectItemCaseSensitive(frame, "resultId");
options->sequenceData[i]->frameData[j]->frameDelay = GetInt(frameDelay);
options->sequenceData[i]->frameData[j]->resultId = GetInt(resultId);
j++;
}
i++;
}
//todo implement extended attributes
cJSON *resultCount = cJSON_GetObjectItemCaseSensitive(json, "resultCount");
options->resultCount = GetInt(resultCount);
options->animationResults = malloc(sizeof(struct AnimationResults *) * options->resultCount);
for (i = 0; i < options->resultCount; i++)
{
options->animationResults[i] = malloc(sizeof(struct AnimationResults));
}
i = 0;
cJSON *animationResult = NULL;
cJSON *animationResults = cJSON_GetObjectItemCaseSensitive(json, "animationResults");
cJSON_ArrayForEach(animationResult, animationResults)
{
if (i > options->resultCount - 1)
FATAL_ERROR("Frame count is incorrect.\n");
cJSON *resultType = cJSON_GetObjectItemCaseSensitive(animationResult, "resultType");
options->animationResults[i]->resultType = GetInt(resultType);
switch (options->animationResults[i]->resultType) {
case 0: { //index
cJSON *index = cJSON_GetObjectItemCaseSensitive(animationResult, "index");
options->animationResults[i]->index = GetInt(index);
break;
}
case 1: { //SRT
cJSON *index = cJSON_GetObjectItemCaseSensitive(animationResult, "index");
cJSON *rotation = cJSON_GetObjectItemCaseSensitive(animationResult, "rotation");
cJSON *scaleX = cJSON_GetObjectItemCaseSensitive(animationResult, "scaleX");
cJSON *scaleY = cJSON_GetObjectItemCaseSensitive(animationResult, "scaleY");
cJSON *positionX = cJSON_GetObjectItemCaseSensitive(animationResult, "positionX");
cJSON *positionY = cJSON_GetObjectItemCaseSensitive(animationResult, "positionY");
options->animationResults[i]->dataSrt.index = GetInt(index);
options->animationResults[i]->dataSrt.rotation = GetInt(rotation);
options->animationResults[i]->dataSrt.scaleX = GetInt(scaleX);
options->animationResults[i]->dataSrt.scaleY = GetInt(scaleY);
options->animationResults[i]->dataSrt.positionX = GetInt(positionX);
options->animationResults[i]->dataSrt.positionY = GetInt(positionY);
break;
}
case 2: { //T
cJSON *index = cJSON_GetObjectItemCaseSensitive(animationResult, "index");
//cJSON *rotation = cJSON_GetObjectItemCaseSensitive(animationResult, "rotation");
cJSON *positionX = cJSON_GetObjectItemCaseSensitive(animationResult, "positionX");
cJSON *positionY = cJSON_GetObjectItemCaseSensitive(animationResult, "positionY");
options->animationResults[i]->dataT.index = GetInt(index);
//options->animationResults[i]->dataSrt.rotation = GetInt(rotation);
options->animationResults[i]->dataT.positionX = GetInt(positionX);
options->animationResults[i]->dataT.positionY = GetInt(positionY);
break;
}
}
i++;
}
cJSON *labelBool = cJSON_GetObjectItemCaseSensitive(json, "labelEnabled");
options->labelEnabled = GetBool(labelBool);
if (options->labelEnabled)
{
cJSON *labelCount = cJSON_GetObjectItemCaseSensitive(json, "labelCount");
options->labelCount = GetInt(labelCount);
options->labels = malloc(sizeof(char *) * options->labelCount);
cJSON *labels = cJSON_GetObjectItemCaseSensitive(json, "labels");
cJSON *label = NULL;
int j = 0;
cJSON_ArrayForEach(label, labels)
{
char *labelString = GetString(label);
options->labels[j] = malloc(strlen(labelString) + 1);
strcpy(options->labels[j], labelString);
j++;
}
}
cJSON_Delete(json);
free(jsonString);
return options;
}
void FreeNCERCell(struct JsonToCellOptions *options)
{
for (int i = 0; i < options->cellCount; i++)
@ -244,6 +414,7 @@ void FreeNCERCell(struct JsonToCellOptions *options)
}
free(options->labels);
}
free(options->cells);
free(options);
}
@ -253,3 +424,31 @@ void FreeNSCRScreen(struct JsonToScreenOptions *options)
free(options);
}
void FreeNANRAnimation(struct JsonToAnimationOptions *options)
{
for (int i = 0; i < options->sequenceCount; i++)
{
for (int j = 0; j < options->sequenceData[i]->frameCount; j++)
{
free(options->sequenceData[i]->frameData[j]);
}
free(options->sequenceData[i]->frameData);
free(options->sequenceData[i]);
}
for (int i = 0; i < options->resultCount; i++)
{
free(options->animationResults[i]);
}
if (options->labelEnabled)
{
for (int j = 0; j < options->labelCount; j++)
{
free(options->labels[j]);
}
free(options->labels);
}
free(options->sequenceData);
free(options->animationResults);
free(options);
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2021 red031000
// Copyright (c) 2021-2023 red031000
#ifndef JSON_H
#define JSON_H
@ -7,7 +7,9 @@
struct JsonToCellOptions *ParseNCERJson(char *path);
struct JsonToScreenOptions *ParseNSCRJson(char *path);
struct JsonToAnimationOptions *ParseNANRJson(char *path);
void FreeNCERCell(struct JsonToCellOptions *options);
void FreeNSCRScreen(struct JsonToScreenOptions *options);
void FreeNANRAnimation(struct JsonToAnimationOptions *options);
#endif //JSON_H

View File

@ -1,5 +1,6 @@
// Copyright (c) 2015 YamaArashi
// Copyright (c) 2015 YamaArashi, 2021-2023 red031000
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
@ -45,8 +46,30 @@ void ConvertGbaToPng(char *inputPath, char *outputPath, struct GbaToPngOptions *
FreeImage(&image);
}
void ConvertNtrToPng(char *inputPath, char *outputPath, struct GbaToPngOptions *options)
void ConvertNtrToPng(char *inputPath, char *outputPath, struct NtrToPngOptions *options)
{
// handle empty files if possible
FILE *fp = fopen(inputPath, "rb");
if (options->handleEmpty)
{
if (fp != NULL)
{
fseek(fp, 0, SEEK_END);
uint32_t size = ftell(fp);
rewind(fp);
if (size == 0)
{
FILE *out = fopen(outputPath, "wb+");
fclose(out);
fclose(fp);
return;
}
}
}
fclose(fp);
struct Image image;
if (options->paletteFilePath != NULL)
@ -58,8 +81,8 @@ void ConvertNtrToPng(char *inputPath, char *outputPath, struct GbaToPngOptions *
{
image.hasPalette = false;
}
uint32_t key = ReadNtrImage(inputPath, options->width, 0, options->metatileWidth, options->metatileHeight, &image, !image.hasPalette);
uint32_t key = ReadNtrImage(inputPath, options->width, 0, options->metatileWidth, options->metatileHeight, &image, !image.hasPalette, options->scanFrontToBack);
if (key)
{
@ -95,6 +118,27 @@ void ConvertPngToGba(char *inputPath, char *outputPath, struct PngToGbaOptions *
void ConvertPngToNtr(char *inputPath, char *outputPath, struct PngToNtrOptions *options)
{
// handle empty files if possible
FILE *fp = fopen(inputPath, "rb");
if (options->handleEmpty)
{
if (fp != NULL)
{
fseek(fp, 0, SEEK_END);
uint32_t size = ftell(fp);
rewind(fp);
if (size == 0)
{
FILE *out = fopen(outputPath, "wb+");
fclose(out);
fclose(fp);
return;
}
}
}
fclose(fp);
struct Image image;
image.bitDepth = options->bitDepth;
@ -102,7 +146,7 @@ void ConvertPngToNtr(char *inputPath, char *outputPath, struct PngToNtrOptions *
ReadPng(inputPath, &image);
uint32_t key = 0;
if (options->scanned)
if (options->scanMode)
{
char* string = malloc(strlen(inputPath) + 5);
sprintf(string, "%s.key", inputPath);
@ -118,7 +162,7 @@ void ConvertPngToNtr(char *inputPath, char *outputPath, struct PngToNtrOptions *
WriteNtrImage(outputPath, options->numTiles, image.bitDepth, options->metatileWidth, options->metatileHeight,
&image, !image.hasPalette, options->clobberSize, options->byteOrder, options->version101,
options->sopc, options->scanned, key, options->wrongSize);
options->sopc, options->scanMode, key, options->wrongSize);
FreeImage(&image);
}
@ -128,7 +172,10 @@ void HandleGbaToPngCommand(char *inputPath, char *outputPath, int argc, char **a
char *inputFileExtension = GetFileExtension(inputPath);
struct GbaToPngOptions options;
options.paletteFilePath = NULL;
options.bitDepth = inputFileExtension[0] - '0';
if (isdigit(inputFileExtension[0]))
options.bitDepth = inputFileExtension[0] - '0';
else
options.bitDepth = 4;
options.hasTransparency = false;
options.width = 1;
options.metatileWidth = 1;
@ -204,13 +251,15 @@ void HandleGbaToPngCommand(char *inputPath, char *outputPath, int argc, char **a
void HandleNtrToPngCommand(char *inputPath, char *outputPath, int argc, char **argv)
{
struct GbaToPngOptions options;
struct NtrToPngOptions options;
options.paletteFilePath = NULL;
options.hasTransparency = false;
options.width = 1;
options.width = 0;
options.metatileWidth = 1;
options.metatileHeight = 1;
options.palIndex = 1;
options.scanFrontToBack = false;
options.handleEmpty = false;
for (int i = 3; i < argc; i++)
{
@ -281,13 +330,21 @@ void HandleNtrToPngCommand(char *inputPath, char *outputPath, int argc, char **a
if (options.metatileHeight < 1)
FATAL_ERROR("metatile height must be positive.\n");
}
else if (strcmp(option, "-scanfronttoback") == 0)
{
options.scanFrontToBack = true;
}
else if (strcmp(option, "-handleempty") == 0)
{
options.handleEmpty = true;
}
else
{
FATAL_ERROR("Unrecognized option \"%s\".\n", option);
}
}
if (options.metatileWidth > options.width)
if (options.width != 0 && options.metatileWidth > options.width)
options.width = options.metatileWidth;
ConvertNtrToPng(inputPath, outputPath, &options);
@ -296,7 +353,11 @@ void HandleNtrToPngCommand(char *inputPath, char *outputPath, int argc, char **a
void HandlePngToGbaCommand(char *inputPath, char *outputPath, int argc, char **argv)
{
char *outputFileExtension = GetFileExtension(outputPath);
int bitDepth = outputFileExtension[0] - '0';
int bitDepth;
if (strcmp(outputFileExtension, "nbfc") == 0)
bitDepth = 4;
else
bitDepth = outputFileExtension[0] - '0';
struct PngToGbaOptions options;
options.numTiles = 0;
options.bitDepth = bitDepth;
@ -367,7 +428,8 @@ void HandlePngToNtrCommand(char *inputPath, char *outputPath, int argc, char **a
options.byteOrder = true;
options.version101 = false;
options.sopc = false;
options.scanned = false;
options.scanMode = 0;
options.handleEmpty = false;
for (int i = 3; i < argc; i++)
{
@ -443,11 +505,23 @@ void HandlePngToNtrCommand(char *inputPath, char *outputPath, int argc, char **a
}
else if (strcmp(option, "-scanned") == 0)
{
options.scanned = true;
if (options.scanMode != 0)
FATAL_ERROR("Scan mode specified more than once.\n-scanned goes back to front as in DP, -scanfronttoback goes front to back as in PtHGSS\n");
options.scanMode = 1;
}
else if (strcmp(option, "-scanfronttoback") == 0)
{
if (options.scanMode != 0)
FATAL_ERROR("Scan mode specified more than once.\n-scanned goes back to front as in DP, -scanfronttoback goes front to back as in PtHGSS\n");
options.scanMode = 2;
}
else if (strcmp(option, "-wrongsize") == 0) {
options.wrongSize = true;
}
else if (strcmp(option, "-handleempty") == 0)
{
options.handleEmpty = true;
}
else
{
FATAL_ERROR("Unrecognized option \"%s\".\n", option);
@ -732,6 +806,32 @@ void HandleJsonToNtrScreenCommand(char *inputPath, char *outputPath, int argc UN
FreeNSCRScreen(options);
}
void HandleJsonToNtrAnimationCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
{
struct JsonToAnimationOptions *options;
options = ParseNANRJson(inputPath);
options->multiCell = false;
WriteNtrAnimation(outputPath, options);
FreeNANRAnimation(options);
}
void HandleJsonToNtrMulticellAnimationCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
{
struct JsonToAnimationOptions *options;
options = ParseNANRJson(inputPath);
options->multiCell = true;
WriteNtrAnimation(outputPath, options);
FreeNANRAnimation(options);
}
void HandleLatinFontToPngCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
{
struct Image image;
@ -992,6 +1092,8 @@ int main(int argc, char **argv)
{ "png", "fwjpnfont", HandlePngToFullwidthJapaneseFontCommand },
{ "json", "NCER", HandleJsonToNtrCellCommand },
{ "json", "NSCR", HandleJsonToNtrScreenCommand },
{ "json", "NANR", HandleJsonToNtrAnimationCommand },
{ "json", "NMAR", HandleJsonToNtrMulticellAnimationCommand },
{ NULL, "huff", HandleHuffCompressCommand },
{ NULL, "lz", HandleLZCompressCommand },
{ "huff", NULL, HandleHuffDecompressCommand },

View File

@ -1,8 +1,9 @@
// Copyright (c) 2018 huderlem
// Copyright (c) 2018 huderlem, 2021-2023 red031000
#ifndef OPTIONS_H
#define OPTIONS_H
#include <stdint.h>
#include <stdbool.h>
struct GbaToPngOptions {
@ -31,8 +32,21 @@ struct PngToNtrOptions {
bool byteOrder;
bool version101;
bool sopc;
bool scanned;
uint32_t scanMode;
bool wrongSize;
bool handleEmpty;
};
struct NtrToPngOptions {
char *paletteFilePath;
int bitDepth;
bool hasTransparency;
int width;
int metatileWidth;
int metatileHeight;
int palIndex;
bool scanFrontToBack;
bool handleEmpty;
};
struct Attr0 {
@ -91,4 +105,55 @@ struct JsonToScreenOptions {
int bitdepth;
};
struct FrameData {
int resultId;
short frameDelay;
};
struct SequenceData {
short frameCount;
short loopStartFrame;
short animationElement;
short animationType;
int playbackMode;
struct FrameData **frameData;
};
struct AnimationDataSRT {
short index;
unsigned short rotation;
int scaleX;
int scaleY;
short positionX;
short positionY;
};
struct AnimationDataT {
short index;
//unsigned short rotation;
short positionX;
short positionY;
};
struct AnimationResults {
short resultType;
union {
short index;
struct AnimationDataSRT dataSrt;
struct AnimationDataT dataT;
};
};
struct JsonToAnimationOptions {
bool multiCell;
short sequenceCount;
short frameCount;
struct SequenceData **sequenceData;
struct AnimationResults **animationResults;
bool labelEnabled;
char **labels;
int labelCount;
short resultCount;
};
#endif // OPTIONS_H

View File

@ -101,7 +101,7 @@ unsigned char *RLCompress(unsigned char *src, int srcSize, int *compressedSize)
srcPos++;
uncompressedLength++;
}
if (uncompressedLength > 0)
{
dest[destPos++] = uncompressedLength - 1;

View File

@ -13,4 +13,45 @@ unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount);
void WriteWholeFile(char *path, void *buffer, int bufferSize);
void WriteGenericNtrHeader(FILE* fp, const char* magicNumber, uint32_t size, bool byteorder, bool version101, uint16_t sectionCount);
// Unaligned IO
static inline uint8_t ReadU8(const unsigned char *ptr, const size_t offset) {
return ptr[offset];
}
static inline uint16_t ReadU16(const unsigned char *ptr, const size_t offset) {
return ptr[offset] | (ptr[offset + 1] << 8);
}
static inline uint32_t ReadU32(const unsigned char *ptr, const size_t offset) {
return ptr[offset] | (ptr[offset + 1] << 8) | (ptr[offset + 2] << 16) | (ptr[offset + 3] << 24);
}
static inline int8_t ReadS8(const unsigned char *ptr, const size_t offset) {
return ptr[offset];
}
static inline int16_t ReadS16(const unsigned char *ptr, const size_t offset) {
return ptr[offset] | (ptr[offset + 1] << 8);
}
static inline int32_t ReadS32(const unsigned char *ptr, const size_t offset) {
return ptr[offset] | (ptr[offset + 1] << 8) | (ptr[offset + 2] << 16) | (ptr[offset + 3] << 24);
}
static inline void WriteU8(unsigned char *ptr, const size_t offset, uint8_t value) {
ptr[offset] = value;
}
static inline void WriteU16(unsigned char *ptr, const size_t offset, uint16_t value) {
ptr[offset] = value;
ptr[offset + 1] = value >> 8;
}
static inline void WriteU32(unsigned char *ptr, const size_t offset, uint32_t value) {
ptr[offset] = value;
ptr[offset + 1] = value >> 8;
ptr[offset + 2] = value >> 16;
ptr[offset + 3] = value >> 24;
}
#endif // UTIL_H