Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/inventory.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "ultra64.h"
#include "item.h"
#include "upgrade.h"

struct PlayState;

Expand Down
12 changes: 0 additions & 12 deletions include/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,6 @@ typedef enum EquipValueBoots {
/* 4 */ EQUIP_VALUE_BOOTS_MAX
} EquipValueBoots;

typedef enum UpgradeType {
/* 0x00 */ UPG_QUIVER,
/* 0x01 */ UPG_BOMB_BAG,
/* 0x02 */ UPG_STRENGTH,
/* 0x03 */ UPG_SCALE,
/* 0x04 */ UPG_WALLET,
/* 0x05 */ UPG_BULLET_BAG,
/* 0x06 */ UPG_DEKU_STICKS,
/* 0x07 */ UPG_DEKU_NUTS,
/* 0x08 */ UPG_MAX
} UpgradeType;

typedef enum QuestItem {
/* 0x00 */ QUEST_MEDALLION_FOREST,
/* 0x01 */ QUEST_MEDALLION_FIRE,
Expand Down
4 changes: 0 additions & 4 deletions include/save.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,6 @@ typedef enum LinkAge {
#define TUNIC_EQUIP_TO_PLAYER(tunicEquip) ((tunicEquip) - 1)
#define BOOTS_EQUIP_TO_PLAYER(bootsEquip) ((bootsEquip) - 1)

#define CUR_UPG_VALUE(upg) ((s32)(gSaveContext.save.info.inventory.upgrades & gUpgradeMasks[upg]) >> gUpgradeShifts[upg])
#define CAPACITY(upg, value) gUpgradeCapacities[upg][value]
#define CUR_CAPACITY(upg) CAPACITY(upg, CUR_UPG_VALUE(upg))

#define CHECK_QUEST_ITEM(item) (gSaveContext.save.info.inventory.questItems & gBitFlags[item])
#define CHECK_DUNGEON_ITEM(item, dungeonIndex) (gSaveContext.save.info.inventory.dungeonItems[dungeonIndex] & gBitFlags[item])

Expand Down
163 changes: 163 additions & 0 deletions include/upgrade.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#ifndef UPGRADE_H
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Organization wise, I don't particularly feel that item upgrades are a substantially complex system to where we need to split them from item.h

#define UPGRADE_H

#include "assert.h"
#include "ultra64/ultratypes.h"

typedef enum UpgradeType {
/* 0x00 */ UPG_QUIVER,
/* 0x01 */ UPG_BOMB_BAG,
/* 0x02 */ UPG_STRENGTH,
/* 0x03 */ UPG_SCALE,
/* 0x04 */ UPG_WALLET,
/* 0x05 */ UPG_BULLET_BAG,
/* 0x06 */ UPG_DEKU_STICKS,
/* 0x07 */ UPG_DEKU_NUTS,
/* 0x08 */ UPG_MAX
} UpgradeType;

#define BIT_WIDTH_UPG_QUIVER 3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think personally I'd prefer it that you have this section organized like...

  • enum UpgradeType
  • BIT_WIDTH_* all listed in sequence, assert "Upgrades must fit in a u32"
  • SHIFT_* all listed in sequence

Then finally enum QuiverUpgrades, assert, enum BombBagUpgrades, assert


typedef enum QuiverUpgrades {
/* 0 */ UPG_QUIVER_NONE,
/* 1 */ UPG_QUIVER_NORMAL,
/* 2 */ UPG_QUIVER_BIG,
/* 3 */ UPG_QUIVER_BIGGEST,
/* 4 */ UPG_QUIVER_MAX
} QuiverUpgrades;

static_assert(UPG_QUIVER_MAX <= 1 << BIT_WIDTH_UPG_QUIVER, "All quiver upgrade values should fit in its assigned bitwidth");

#define BIT_WIDTH_UPG_BOMB_BAG 3

typedef enum BombBagUpgrades {
/* 0 */ UPG_BOMB_BAG_NONE,
/* 1 */ UPG_BOMB_BAG_NORMAL,
/* 2 */ UPG_BOMB_BAG_BIG,
/* 3 */ UPG_BOMB_BAG_BIGGEST,
/* 4 */ UPG_BOMB_BAG_MAX
} BombBagUpgrades;

static_assert(UPG_BOMB_BAG_MAX <= 1 << BIT_WIDTH_UPG_BOMB_BAG, "All bomb bag upgrade values should fit in its assigned bitwidth");

#define BIT_WIDTH_UPG_STRENGTH 3

typedef enum StrengthUpgrades {
/* 0 */ UPG_STRENGTH_NONE,
/* 1 */ UPG_STRENGTH_GORON_BRACELET,
/* 2 */ UPG_STRENGTH_SILVER_GAUNTLETS,
/* 3 */ UPG_STRENGTH_GOLD_GAUNTLETS,
/* 4 */ UPG_STRENGTH_MAX
} StrengthUpgrades;

static_assert(UPG_STRENGTH_MAX <= 1 << BIT_WIDTH_UPG_STRENGTH, "All strength upgrade values should fit in its assigned bitwidth");

#define BIT_WIDTH_UPG_SCALE 3

typedef enum ScaleUpgrades {
/* 0 */ UPG_SCALE_NONE,
/* 1 */ UPG_SCALE_SILVER,
/* 2 */ UPG_SCALE_GOLD,
/* 3 */ UPG_SCALE_MAX
} ScaleUpgrades;

static_assert(UPG_SCALE_MAX <= 1 << BIT_WIDTH_UPG_SCALE, "All scale upgrade values should fit in its assigned bitwidth");

#define BIT_WIDTH_UPG_WALLET 2

typedef enum WalletUpgrades {
/* 0 */ UPG_WALLET_CHILD,
/* 1 */ UPG_WALLET_ADULT,
/* 2 */ UPG_WALLET_GIANT,
/* 3 */ UPG_WALLET_MAX
} WalletUpgrades;

static_assert(UPG_WALLET_MAX <= 1 << BIT_WIDTH_UPG_WALLET, "All wallet upgrade values should fit in its assigned bitwidth");

#define BIT_WIDTH_UPG_BULLET_BAG 3

typedef enum BulletBagUpgrades {
/* 0 */ UPG_BULLET_BAG_NONE,
/* 1 */ UPG_BULLET_BAG_NORMAL,
/* 2 */ UPG_BULLET_BAG_BIG,
/* 3 */ UPG_BULLET_BAG_BIGGEST,
/* 4 */ UPG_BULLET_BAG_MAX
} BulletBagUpgrades;

static_assert(UPG_BULLET_BAG_MAX <= 1 << BIT_WIDTH_UPG_BULLET_BAG, "All bullet bag upgrade values should fit in its assigned bitwidth");

#define BIT_WIDTH_UPG_DEKU_STICKS 3

typedef enum DekuStickUpgrades {
/* 0 */ UPG_DEKU_STICKS_NONE,
/* 1 */ UPG_DEKU_STICKS_10,
/* 2 */ UPG_DEKU_STICKS_20,
/* 3 */ UPG_DEKU_STICKS_30,
/* 4 */ UPG_DEKU_STICKS_MAX
} DekuStickUpgrades;

static_assert(UPG_DEKU_STICKS_MAX <= 1 << BIT_WIDTH_UPG_DEKU_STICKS, "All deku stick upgrade values should fit in its assigned bitwidth");

#define BIT_WIDTH_UPG_DEKU_NUTS 3

typedef enum DekuNutUpgrades {
/* 0 */ UPG_DEKU_NUTS_NONE,
/* 1 */ UPG_DEKU_NUTS_20,
/* 2 */ UPG_DEKU_NUTS_30,
/* 3 */ UPG_DEKU_NUTS_40,
/* 4 */ UPG_DEKU_NUTS_MAX
} DekuNutUpgrades;

static_assert(UPG_DEKU_NUTS_MAX <= 1 << BIT_WIDTH_UPG_DEKU_NUTS, "All deku nut upgrade values should fit in its assigned bitwidth");

#define BITS_PER_BYTE 8
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this has come up before (someone could correct me if I'm wrong or wishes to debate this), but the preference is to just inline the constant value of 8 instead of using CHAR_BIT from <climits> or a custom BITS_PER_BYTE define


static_assert(
BIT_WIDTH_UPG_QUIVER +
BIT_WIDTH_UPG_BOMB_BAG +
BIT_WIDTH_UPG_STRENGTH +
BIT_WIDTH_UPG_SCALE +
BIT_WIDTH_UPG_WALLET +
BIT_WIDTH_UPG_BULLET_BAG +
BIT_WIDTH_UPG_DEKU_STICKS +
BIT_WIDTH_UPG_DEKU_NUTS < sizeof(u32) * BITS_PER_BYTE,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
BIT_WIDTH_UPG_DEKU_NUTS < sizeof(u32) * BITS_PER_BYTE,
BIT_WIDTH_UPG_DEKU_NUTS <= sizeof(u32) * BITS_PER_BYTE,

"Upgrades must fit in a u32"
);

#define SHIFT_UPG_QUIVER 0
#define SHIFT_UPG_BOMB_BAG (SHIFT_UPG_QUIVER + BIT_WIDTH_UPG_QUIVER)
#define SHIFT_UPG_STRENGTH (SHIFT_UPG_BOMB_BAG + BIT_WIDTH_UPG_BOMB_BAG)
#define SHIFT_UPG_SCALE (SHIFT_UPG_STRENGTH + BIT_WIDTH_UPG_STRENGTH)
#define SHIFT_UPG_WALLET (SHIFT_UPG_SCALE + BIT_WIDTH_UPG_SCALE)
#define SHIFT_UPG_BULLET_BAG (SHIFT_UPG_WALLET + BIT_WIDTH_UPG_WALLET)
#define SHIFT_UPG_DEKU_STICKS (SHIFT_UPG_BULLET_BAG + BIT_WIDTH_UPG_BULLET_BAG)
#define SHIFT_UPG_DEKU_NUTS (SHIFT_UPG_DEKU_STICKS + BIT_WIDTH_UPG_DEKU_STICKS)

#ifndef GLUE
# define GLUE(a, b) a##b
#endif
#ifndef GLUE2
# define GLUE2(a, b) GLUE(a, b)
#endif

#define GET_UPGRADE_BITMASK(upg) (((1 << GLUE2(BIT_WIDTH_, upg)) - 1) << GLUE2(SHIFT_, upg))

#define GET_PACKED_UPGRADE_VALUE(upgValue, upg) ((upgValue & ((1 << GLUE2(BIT_WIDTH_, upg)) - 1)) << GLUE2(SHIFT_, upg))

#define GET_PACKED_UPGRADES_VALUE(quiver, bombBag, strength, scale, wallet, bulletBag, dekuSticks, dekuNuts) \
( \
GET_PACKED_UPGRADE_VALUE(quiver, UPG_QUIVER) | \
GET_PACKED_UPGRADE_VALUE(bombBag, UPG_BOMB_BAG) | \
GET_PACKED_UPGRADE_VALUE(strength, UPG_STRENGTH) | \
GET_PACKED_UPGRADE_VALUE(scale, UPG_SCALE) | \
GET_PACKED_UPGRADE_VALUE(wallet, UPG_WALLET) | \
GET_PACKED_UPGRADE_VALUE(bulletBag, UPG_BULLET_BAG) | \
GET_PACKED_UPGRADE_VALUE(dekuSticks, UPG_DEKU_STICKS) | \
GET_PACKED_UPGRADE_VALUE(dekuNuts, UPG_DEKU_NUTS) \
)

#define CUR_UPG_VALUE(upg) ((s32)(gSaveContext.save.info.inventory.upgrades & gUpgradeMasks[upg]) >> gUpgradeShifts[upg])
#define CAPACITY(upg, value) gUpgradeCapacities[upg][value]
#define CUR_CAPACITY(upg) CAPACITY(upg, CUR_UPG_VALUE(upg))

#endif
33 changes: 9 additions & 24 deletions src/code/z_inventory.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,15 @@ u16 gEquipNegMasks[EQUIP_TYPE_MAX] = {
};

u32 gUpgradeMasks[UPG_MAX] = {
0x00000007, // UPG_QUIVER
0x00000038, // UPG_BOMB_BAG
0x000001C0, // UPG_STRENGTH
0x00000E00, // UPG_SCALE
0x00003000, // UPG_WALLET
0x0001C000, // UPG_BULLET_BAG
0x000E0000, // UPG_DEKU_STICKS
0x00700000, // UPG_DEKU_NUTS
GET_UPGRADE_BITMASK(UPG_QUIVER), GET_UPGRADE_BITMASK(UPG_BOMB_BAG), GET_UPGRADE_BITMASK(UPG_STRENGTH),
GET_UPGRADE_BITMASK(UPG_SCALE), GET_UPGRADE_BITMASK(UPG_WALLET), GET_UPGRADE_BITMASK(UPG_BULLET_BAG),
GET_UPGRADE_BITMASK(UPG_DEKU_STICKS), GET_UPGRADE_BITMASK(UPG_DEKU_NUTS),
};

u32 gUpgradeNegMasks[UPG_MAX] = {
~0x00000007, // UPG_QUIVER
~0x00000038, // UPG_BOMB_BAG
~0x000001C0, // UPG_STRENGTH
~0x00000E00, // UPG_SCALE
~0x00003000, // UPG_WALLET
~0x0001C000, // UPG_BULLET_BAG
~0x000E0000, // UPG_DEKU_STICKS
~0x00700000, // UPG_DEKU_NUTS
~GET_UPGRADE_BITMASK(UPG_QUIVER), ~GET_UPGRADE_BITMASK(UPG_BOMB_BAG), ~GET_UPGRADE_BITMASK(UPG_STRENGTH),
~GET_UPGRADE_BITMASK(UPG_SCALE), ~GET_UPGRADE_BITMASK(UPG_WALLET), ~GET_UPGRADE_BITMASK(UPG_BULLET_BAG),
~GET_UPGRADE_BITMASK(UPG_DEKU_STICKS), ~GET_UPGRADE_BITMASK(UPG_DEKU_NUTS),
};

u8 gEquipShifts[EQUIP_TYPE_MAX] = {
Expand All @@ -59,14 +50,8 @@ u8 gEquipShifts[EQUIP_TYPE_MAX] = {
};

u8 gUpgradeShifts[UPG_MAX] = {
0, // UPG_QUIVER
3, // UPG_BOMB_BAG
6, // UPG_STRENGTH
9, // UPG_SCALE
12, // UPG_WALLET
14, // UPG_BULLET_BAG
17, // UPG_DEKU_STICKS
20, // UPG_DEKU_NUTS
SHIFT_UPG_QUIVER, SHIFT_UPG_BOMB_BAG, SHIFT_UPG_STRENGTH, SHIFT_UPG_SCALE,
SHIFT_UPG_WALLET, SHIFT_UPG_BULLET_BAG, SHIFT_UPG_DEKU_STICKS, SHIFT_UPG_DEKU_NUTS,
};

u16 gUpgradeCapacities[UPG_MAX][4] = {
Expand Down
Loading