Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/Dev' into upgradeful_item_2
Browse files Browse the repository at this point in the history
  • Loading branch information
AngheloAlf committed Sep 1, 2024
2 parents c4dc491 + 6d5ee07 commit 2c4a263
Show file tree
Hide file tree
Showing 173 changed files with 44,454 additions and 37,764 deletions.
3 changes: 1 addition & 2 deletions ASM/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@ $(OBJDIR)/%_bin.o: $(RESOURCEDIR)/%.bin
$(OBJCOPY) --redefine-sym _binary_resources_$*_bin_end=$(call UC,$*)_RESOURCE_END $@
$(OBJCOPY) --redefine-sym _binary_resources_$*_bin_size=$(call UC,$*)_RESOURCE_SIZE $@


$(RESOURCEDIR):
mkdir -p $@

$(OBJECTS): | $(OBJDIR)

$(RESOURCES): | $(RESOURCEDIR)
$(RESOURCES): | $(OBJDIR) $(RESOURCEDIR)

bundle: $(RESOURCES) $(OBJECTS)
$(LD) -T linker_script.ld -T ootSymbols.ld -o $(OUTDIR)/bundle.o -i -L. $(patsubst %.o,-l:%.o,$(OBJECTS) $(RESOURCES))
Expand Down
20 changes: 19 additions & 1 deletion ASM/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,21 @@
'address': address,
}

# Loop through a second time, add lengths to each data symbol
# This could probably be optimized to run in a single pass :)
with open('build/asm_symbols.txt', 'r') as f:
for line in f:
parts = line.strip().split(' ')
if len(parts) < 2:
continue
address, sym_name = parts
if sym_name.startswith('.'):
# split on the ':' to get the length, in hex
type, hex_length = sym_name.split(':')
for symbol, sym_data in symbols.items():
if sym_data['address'] == address and sym_data['type'] == 'data':
sym_data['length'] = int(hex_length, 16)

# Output symbols

os.chdir(run_dir)
Expand All @@ -116,7 +131,10 @@
addr = addr - 0x80400000 + 0x03480000
else:
continue
data_symbols[name] = '{0:08X}'.format(addr)
data_symbols[name] = {
'address': f'{addr:08X}',
'length': sym.get('length', 0),
}
with open('../data/generated/symbols.json', 'w') as f:
json.dump(data_symbols, f, indent=4, sort_keys=True)

Expand Down
170 changes: 119 additions & 51 deletions ASM/c/actor.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
#include "textures.h"
#include "actor.h"
#include "en_wonderitem.h"
#include "scene.h"
#include "en_item00.h"

extern uint8_t POTCRATE_TEXTURES_MATCH_CONTENTS;
extern uint16_t CURR_ACTOR_SPAWN_INDEX;
extern uint8_t SHUFFLE_SILVER_RUPEES;
extern int8_t curr_scene_setup;
extern xflag_t* spawn_actor_with_flag;

#define BG_HAKA_TUBO 0x00BB // Shadow temple spinning pot
#define BG_SPOT18_BASKET 0x015C // Goron city spinning pot
Expand All @@ -26,35 +29,33 @@ extern int8_t curr_scene_setup;
#define EN_G_SWITCH 0x0117 //Silver Rupee
#define EN_WONDER_ITEM 0x0112 // Wonder Item

// Called at the end of Actor_SetWorldToHome
// Reset the rotations for any actors that we may have passed data in through Actor_Spawn
void Actor_SetWorldToHome_End(z64_actor_t* actor) {
switch (actor->actor_id) {
case BG_HAKA_TUBO:
case BG_SPOT18_BASKET:
case OBJ_MURE3:
case OBJ_COMB: {
actor->rot_world.z = 0;
break;
}
case EN_ITEM00:
case EN_WONDER_ITEM: {
actor->rot_world.y = 0;
}
default: {
break;
}
// Get a pointer to the additional data that is stored at the beginning of every actor
// This is calculated as the actor's address + the actor instance size from the overlay table.
ActorAdditionalData* Actor_GetAdditionalData(z64_actor_t* actor) {
return (ActorAdditionalData*)(((uint8_t*)actor) - 0x10);
}

// Build an xflag from actor ID and subflag
// Store the flag using the pointer
void Actor_BuildFlag(z64_actor_t* actor, xflag_t* flag, uint16_t actor_index, uint8_t subflag) {
flag->scene = z64_game.scene_index;
if (z64_game.scene_index == 0x3E) {
flag->grotto.room = actor->room_index;
flag->grotto.grotto_id = z64_file.grotto_id & 0x1F;
flag->grotto.flag = actor_index;
flag->grotto.subflag = subflag;
} else {
flag->room = actor->room_index;
flag->setup = curr_scene_setup;
flag->flag = actor_index;
flag->subflag = subflag;
}
}

// Called from Actor_UpdateAll when spawning the actors in the scene's/room's actor list.
// For Pots/Crates/Beehives, sets the actors spawn index into unused y/z rotation fields
// This works because this hack occurs after the actor has been spawned and Actor_SetWorldToHome has been called
// Otherwise the actor would be rotated :)
// Now that we resized pots/crates/beehives we could probably just store this info in new space in the actor. But this works for now.
// Called from Actor_UpdateAll when spawning the actors in the scene's/room's actor list to store flags in the new space that we added to the actors.
// Prior to being called, CURR_ACTOR_SPAWN_INDEX is set to the current position in the actor spawn list.
void Actor_After_UpdateAll_Hack(z64_actor_t* actor, z64_game_t* game) {
Actor_StoreFlagInRotation(actor, game, CURR_ACTOR_SPAWN_INDEX);
Actor_StoreFlagByIndex(actor, game, CURR_ACTOR_SPAWN_INDEX);
Actor_StoreChestType(actor, game);

// Add additional actor hacks here. These get called shortly after the call to actor_init
Expand All @@ -63,51 +64,86 @@ void Actor_After_UpdateAll_Hack(z64_actor_t* actor, z64_game_t* game) {
CURR_ACTOR_SPAWN_INDEX = 0; // reset CURR_ACTOR_SPAWN_INDEX
}

// For pots/crates/beehives, store the flag in the actor's unused initial rotation fields
// Flag consists of the room # and the actor index
void Actor_StoreFlagInRotation(z64_actor_t* actor, z64_game_t* game, uint16_t actor_index) {
uint16_t flag = actor_index | (actor->room_index << 8); // Calculate the flag
// For pots/crates/beehives, store the flag in the new space in the actor instance.
// Flag consists of the room #, scene setup, and the actor index
void Actor_StoreFlag(z64_actor_t* actor, z64_game_t* game, xflag_t flag) {
ActorAdditionalData* extra = Actor_GetAdditionalData(actor);
flag = resolve_alternative_flag(&flag);
if (CURR_ACTOR_SPAWN_INDEX) {
extra->actor_id = CURR_ACTOR_SPAWN_INDEX;
}
override_t override = lookup_override_by_newflag(&flag);
switch (actor->actor_id) {
// For the following actors we store the flag in the z rotation
// For the following actors we store the flag in the new space added to the actor.
case OBJ_TSUBO:
case EN_TUBO_TRAP:
case OBJ_KIBAKO:
case OBJ_COMB: {
actor->rot_init.z = flag;
break;
}
// For the following actors we store the flag in the y rotation
case OBJ_COMB:
case OBJ_KIBAKO2:
case EN_WONDER_ITEM: {
actor->rot_init.y = flag;
case EN_ITEM00:
case EN_WONDER_ITEM:
{
// For these actors, only store the flag if there is a valid override
if (override.key.all) {
extra->flag = flag;
}
break;
}
case BG_SPOT18_BASKET:
case OBJ_MURE3:
case BG_HAKA_TUBO:
{
// For these actors which use subflags, always store the flag which serves as the base when calculating the subflag.
// Don't really need to do this since we will recalculate the flag and check the override when spawning the subflags.
extra->flag = flag;
}
default: {
break;
}
}
}

// For pots/crates/beehives, determine the override and store the chest type in new space in the actor instance
// For pots/crates/beehives, store the flag in the new space in the actor instance.
// Flag consists of the room #, scene setup, and the actor index
void Actor_StoreFlagByIndex(z64_actor_t* actor, z64_game_t* game, uint16_t actor_index) {
// Zeroize extra data;

xflag_t flag = (xflag_t) { 0 };
Actor_BuildFlag(actor, &flag, actor_index, 0);
Actor_StoreFlag(actor, game, flag);
}

// Get an override for new flag. If the override doesn't exist, or flag has already been set, return 0.
override_t get_newflag_override(xflag_t* flag) {
override_t override = lookup_override_by_newflag(flag);
if (override.key.all != 0) {
if (!Get_NewFlag(flag)) {
return override;
}
}
return (override_t) { 0 };
}

// For pots/crates/beehives match contents, determine the override and store the chest type in new space in the actor instance
// So we don't have to hit the override table every frame.
void Actor_StoreChestType(z64_actor_t* actor, z64_game_t* game) {
uint8_t* pChestType = NULL;
override_t override = { 0 };

xflag_t* flag = &(Actor_GetAdditionalData(actor)->flag);
if (actor->actor_id == OBJ_TSUBO) { // Pots
override = get_pot_override(actor, game);
override = get_newflag_override(flag);
pChestType = &(((ObjTsubo*)actor)->chest_type);
} else if (actor->actor_id == EN_TUBO_TRAP) { // Flying Pots
override = get_flying_pot_override(actor, game);
override = get_newflag_override(flag);
pChestType = &(((EnTuboTrap*)actor)->chest_type);
} else if (actor->actor_id == OBJ_KIBAKO2) { // Large Crates
override = get_crate_override(actor, game);
override = get_newflag_override(flag);
pChestType = &(((ObjKibako2*)actor)->chest_type);
} else if (actor->actor_id == OBJ_KIBAKO) { // Small wooden crates
override = get_smallcrate_override(actor, game);
override = get_newflag_override(flag);
pChestType = &(((ObjKibako*)actor)->chest_type);
} else if (actor->actor_id == OBJ_COMB) {
override = get_beehive_override(actor, game);
override = get_newflag_override(flag);
pChestType = &(((ObjComb*)actor)->chest_type);
}
if (override.key.all != 0 && pChestType != NULL) { // If we don't have an override key, then either this item doesn't have an override entry, or it has already been collected.
Expand Down Expand Up @@ -158,19 +194,22 @@ z64_actor_t* Actor_SpawnEntry_Hack(void* actorCtx, ActorEntry* actorEntry, z64_g
bool spawn_override_silver_rupee(ActorEntry* actorEntry, z64_game_t* globalCtx, bool* overridden) {
*overridden = false;
if (SHUFFLE_SILVER_RUPEES) { // Check if silver rupee shuffle is enabled.
// Build a dummy enitem00 actor
EnItem00 dummy;
dummy.actor.actor_id = 0x15;
dummy.actor.rot_init.y = (globalCtx->room_index << 8) + CURR_ACTOR_SPAWN_INDEX;
dummy.actor.variable = 0;
xflag_t flag = {
.scene = globalCtx->scene_index,
.setup = curr_scene_setup,
.room = globalCtx->room_index,
.flag = CURR_ACTOR_SPAWN_INDEX,
.subflag = 0,
};

flag = resolve_alternative_flag(&flag);
uint8_t type = (actorEntry->params >> 0x0C) & 0xF;
if (type != 1) { // only override actual silver rupees, not the switches or pots.
return true;
}
override_t override = lookup_override(&(dummy.actor), globalCtx->scene_index, 0);
override_t override = lookup_override_by_newflag(&flag);
if (override.key.all != 0) {
dummy.override = override;
if (type == 1 && !Get_CollectibleOverrideFlag(&dummy)) {
if (type == 1 && !Get_NewFlag(&flag)) {
// Spawn a green rupee which will be overridden using the collectible hacks.
actorEntry->params = 0;
actorEntry->id = EN_ITEM00;
Expand Down Expand Up @@ -201,3 +240,32 @@ z64_actor_t* Player_SpawnEntry_Hack(void* actorCtx, ActorEntry* playerEntry, z64
return z64_SpawnActor(actorCtx, globalCtx, playerEntry->id, playerEntry->pos.x, playerEntry->pos.y, playerEntry->pos.z,
playerEntry->rot.x, playerEntry->rot.y, playerEntry->rot.z, playerEntry->params);
}

// This is our entrypoint back into Actor_Spawn. Call/return this to spawn the actor
extern z64_actor_t* Actor_Spawn_Continue(void* actorCtx, z64_game_t* globalCtx, int16_t actorId, float posX, float posY, float posZ, int16_t rotX, int16_t rotY, int16_t rotZ, int16_t params);

z64_actor_t* Actor_Spawn_Hook(void* actorCtx, z64_game_t* globalCtx, int16_t actorId, float posX, float posY, float posZ, int16_t rotX, int16_t rotY, int16_t rotZ, int16_t params) {
bool continue_spawn = true;

ActorEntry entry;
entry.id = actorId;
entry.params = params;
entry.pos.x = (int16_t)posX;
entry.pos.y = (int16_t)posY;
entry.pos.z = (int16_t)posZ;
entry.rot.x = rotX;
entry.rot.y = rotY;
entry.rot.z = rotZ;

if (continue_spawn) {
z64_actor_t* spawned = Actor_Spawn_Continue(actorCtx, globalCtx, actorId, posX, posY, posZ, rotX, rotY, rotZ, params);
if (spawned) {
if (spawn_actor_with_flag) {
Actor_StoreFlag(spawned, globalCtx, *spawn_actor_with_flag);
Actor_StoreChestType(spawned, globalCtx);
}
}
return spawned;
}
return NULL;
}
20 changes: 16 additions & 4 deletions ASM/c/actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@
#define ACTOR_H

#include "z64.h"
#include "get_items.h"
#include <stdbool.h>

void Actor_SetWorldToHome_End(z64_actor_t* actor);
// New data added to the end of every actor.
// Make sure the size of this struct is equal to the amount of space added added in Actor_Spawn_Malloc_Hack from actor.asm
typedef struct {
/* 0x00 */ uint16_t actor_id;
/* 0x02 */ xflag_t flag;
} ActorAdditionalData;

void Actor_After_UpdateAll_Hack(z64_actor_t* actor, z64_game_t* game);
void Actor_StoreFlagInRotation(z64_actor_t* actor, z64_game_t* game, uint16_t actor_index);
void Actor_StoreChestType(z64_actor_t* actor, z64_game_t* game);
z64_actor_t* Actor_SpawnEntry_Hack(void* actorCtx, ActorEntry* actorEntry, z64_game_t* globalCtx);
void Actor_StoreFlagByIndex(z64_actor_t* actor, z64_game_t* game, uint16_t actor_index);
void Actor_StoreFlag(z64_actor_t* actor, z64_game_t* game, xflag_t flag);
void Actor_StoreChestType(z64_actor_t* actor, z64_game_t *game);
z64_actor_t *Actor_SpawnEntry_Hack(void* actorCtx, ActorEntry* actorEntry, z64_game_t* globalCtx);
bool spawn_override_silver_rupee(ActorEntry* actorEntry, z64_game_t* globalCtx, bool* overridden);
void after_spawn_override_silver_rupee(z64_actor_t* actor, bool overridden);
void Actor_BuildFlag(z64_actor_t* actor, xflag_t* flag, uint16_t actor_index, uint8_t subflag);
ActorAdditionalData* Actor_GetAdditionalData(z64_actor_t* actor);
override_t get_newflag_override(xflag_t* flag);
extern ActorOverlay gActorOverlayTable[];
#endif
9 changes: 9 additions & 0 deletions ASM/c/bg_gate_shutter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "z64.h"

typedef struct BgGateShutter {
/* 0x0000 */ DynaPolyActor dyna;
/* 0x0154 */ void* actionFunc;
/* 0x0158 */ int16_t openingState; // 1 if gate is opening
/* 0x015C */ z64_xyzf_t somePos;
/* 0x0168 */ int16_t unk_168;
} BgGateShutter; // size = 0x016C
Loading

0 comments on commit 2c4a263

Please sign in to comment.