Refresh 11

This commit is contained in:
n64 2020-07-04 11:18:55 -04:00
parent 05c7d7031c
commit 9214dddabc
47 changed files with 489 additions and 290 deletions

11
CHANGES
View File

@ -1,3 +1,14 @@
Refresh 11
1.) (HEAD -> master, origin/master, origin/HEAD) Make geo_process_level_of_detail endian-independent (#1049)
2.) Label oMoveFlags and slight cleanup. (#1046)
3.) Avoid UB in synthesis_resample_and_mix_reverb (#1048)
4.) Change some void * to correct type (#1047)
5.) Remove oPathedWaypointsS16 and convert all paths to Trajectory struct. (#1045)
6.) Mr Blizzard documentation, Tox Box Unks (#1042)
7.) Pipe input to textconv. (#1041)
8.) Remove erroneous long double casts from audiofile.cpp (#1039)
9.) Replace fixed dialogID in play_dialog_sound to DIALOG_COUNT (#1040)
Refresh #10.1 Refresh #10.1
1.) Diff update (#1033) 1.) Diff update (#1033)
2.) Fix texture dimensions for exclamation boxes (#1034) 2.) Fix texture dimensions for exclamation boxes (#1034)

View File

@ -395,12 +395,10 @@ endif
endif endif
$(BUILD_DIR)/text/%/define_courses.inc.c: text/define_courses.inc.c text/%/courses.h $(BUILD_DIR)/text/%/define_courses.inc.c: text/define_courses.inc.c text/%/courses.h
$(CPP) $(VERSION_CFLAGS) $< -o $@ -I text/$*/ $(CPP) $(VERSION_CFLAGS) $< -o - -I text/$*/ | $(TEXTCONV) charmap.txt - $@
$(TEXTCONV) charmap.txt $@ $@
$(BUILD_DIR)/text/%/define_text.inc.c: text/define_text.inc.c text/%/courses.h text/%/dialogs.h $(BUILD_DIR)/text/%/define_text.inc.c: text/define_text.inc.c text/%/courses.h text/%/dialogs.h
$(CPP) $(VERSION_CFLAGS) $< -o $@ -I text/$*/ $(CPP) $(VERSION_CFLAGS) $< -o - -I text/$*/ | $(TEXTCONV) charmap.txt - $@
$(TEXTCONV) charmap.txt $@ $@
RSP_DIRS := $(BUILD_DIR)/rsp RSP_DIRS := $(BUILD_DIR)/rsp
ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(ASM_DIRS) $(GODDARD_SRC_DIRS) $(ULTRA_SRC_DIRS) $(ULTRA_ASM_DIRS) $(ULTRA_BIN_DIRS) $(BIN_DIRS) $(TEXTURE_DIRS) $(TEXT_DIRS) $(SOUND_SAMPLE_DIRS) $(addprefix levels/,$(LEVEL_DIRS)) include) $(MIO0_DIR) $(addprefix $(MIO0_DIR)/,$(VERSION)) $(SOUND_BIN_DIR) $(SOUND_BIN_DIR)/sequences/$(VERSION) $(RSP_DIRS) ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(ASM_DIRS) $(GODDARD_SRC_DIRS) $(ULTRA_SRC_DIRS) $(ULTRA_ASM_DIRS) $(ULTRA_BIN_DIRS) $(BIN_DIRS) $(TEXTURE_DIRS) $(TEXT_DIRS) $(SOUND_SAMPLE_DIRS) $(addprefix levels/,$(LEVEL_DIRS)) include) $(MIO0_DIR) $(addprefix $(MIO0_DIR)/,$(VERSION)) $(SOUND_BIN_DIR) $(SOUND_BIN_DIR)/sequences/$(VERSION) $(RSP_DIRS)

View File

@ -80,30 +80,22 @@
#define OBJ_MOVE_UNDERWATER_OFF_GROUND (1 << 5) // 0x0020 #define OBJ_MOVE_UNDERWATER_OFF_GROUND (1 << 5) // 0x0020
#define OBJ_MOVE_UNDERWATER_ON_GROUND (1 << 6) // 0x0040 #define OBJ_MOVE_UNDERWATER_ON_GROUND (1 << 6) // 0x0040
#define OBJ_MOVE_IN_AIR (1 << 7) // 0x0080 #define OBJ_MOVE_IN_AIR (1 << 7) // 0x0080
#define OBJ_MOVE_8 (1 << 8) // 0x0100 #define OBJ_MOVE_OUT_SCOPE (1 << 8) // 0x0100
#define OBJ_MOVE_HIT_WALL (1 << 9) // 0x0200 #define OBJ_MOVE_HIT_WALL (1 << 9) // 0x0200
#define OBJ_MOVE_HIT_EDGE (1 << 10) // 0x0400 #define OBJ_MOVE_HIT_EDGE (1 << 10) // 0x0400
#define OBJ_MOVE_ABOVE_LAVA (1 << 11) // 0x0800 #define OBJ_MOVE_ABOVE_LAVA (1 << 11) // 0x0800
#define OBJ_MOVE_LEAVING_WATER (1 << 12) // 0x1000 #define OBJ_MOVE_LEAVING_WATER (1 << 12) // 0x1000
#define OBJ_MOVE_13 (1 << 13) // 0x2000 #define OBJ_MOVE_BOUNCE (1 << 13) // 0x2000
#ifndef VERSION_JP #ifndef VERSION_JP
#define OBJ_MOVE_ABOVE_DEATH_BARRIER (1 << 14) // 0x4000 #define OBJ_MOVE_ABOVE_DEATH_BARRIER (1 << 14) // 0x4000
#endif #endif
#define OBJ_MOVE_MASK_ON_GROUND (OBJ_MOVE_LANDED | OBJ_MOVE_ON_GROUND) #define OBJ_MOVE_MASK_ON_GROUND (OBJ_MOVE_LANDED | OBJ_MOVE_ON_GROUND)
#define OBJ_MOVE_MASK_33 0x33
#define OBJ_MOVE_MASK_IN_WATER (\ #define OBJ_MOVE_MASK_IN_WATER (\
OBJ_MOVE_ENTERED_WATER |\ OBJ_MOVE_ENTERED_WATER |\
OBJ_MOVE_AT_WATER_SURFACE |\ OBJ_MOVE_AT_WATER_SURFACE |\
OBJ_MOVE_UNDERWATER_OFF_GROUND |\ OBJ_MOVE_UNDERWATER_OFF_GROUND |\
OBJ_MOVE_UNDERWATER_ON_GROUND) OBJ_MOVE_UNDERWATER_ON_GROUND)
#define OBJ_MOVE_MASK_HIT_WALL_OR_IN_WATER \
(OBJ_MOVE_HIT_WALL | OBJ_MOVE_MASK_IN_WATER)
#define OBJ_MOVE_MASK_NOT_AIR (\
OBJ_MOVE_LANDED |\
OBJ_MOVE_ON_GROUND |\
OBJ_MOVE_AT_WATER_SURFACE |\
OBJ_MOVE_UNDERWATER_ON_GROUND)
/* oActiveParticleFlags */ /* oActiveParticleFlags */
#define ACTIVE_PARTICLE_DUST (1 << 0) // 0x00000001 #define ACTIVE_PARTICLE_DUST (1 << 0) // 0x00000001
@ -971,4 +963,18 @@
#define BOWSER_PUZZLE_ACT_WAIT_FOR_COMPLETE 1 #define BOWSER_PUZZLE_ACT_WAIT_FOR_COMPLETE 1
#define BOWSER_PUZZLE_ACT_DONE 2 #define BOWSER_PUZZLE_ACT_DONE 2
/* Mr Blizzard */
/* oAction */
#define MR_BLIZZARD_ACT_SPAWN_SNOWBALL 0
#define MR_BLIZZARD_ACT_HIDE_UNHIDE 1
#define MR_BLIZZARD_ACT_RISE_FROM_GROUND 2
#define MR_BLIZZARD_ACT_ROTATE 3
#define MR_BLIZZARD_ACT_THROW_SNOWBALL 4
#define MR_BLIZZARD_ACT_BURROW 5
#define MR_BLIZZARD_ACT_DEATH 6
#define MR_BLIZZARD_ACT_JUMP 7
/* oBehParams2ndByte */
#define MR_BLIZZARD_STYPE_NO_CAP 0
#define MR_BLIZZARD_STYPE_JUMPING 1
#endif // OBJECT_CONSTANTS_H #endif // OBJECT_CONSTANTS_H

View File

@ -136,8 +136,6 @@
#define /*0x1C4*/ oDeathSound OBJECT_FIELD_S32(0x4F) #define /*0x1C4*/ oDeathSound OBJECT_FIELD_S32(0x4F)
/* Pathed (see obj_follow_path) */ /* Pathed (see obj_follow_path) */
// TODO: These two 0x0FC fields need merged, one is data and one is a C struct.
#define /*0x0FC*/ oPathedWaypointsS16 OBJECT_FIELD_VPTR(0x1D)
#define /*0x0FC*/ oPathedStartWaypoint OBJECT_FIELD_WAYPOINT(0x1D) #define /*0x0FC*/ oPathedStartWaypoint OBJECT_FIELD_WAYPOINT(0x1D)
#define /*0x100*/ oPathedPrevWaypoint OBJECT_FIELD_WAYPOINT(0x1E) #define /*0x100*/ oPathedPrevWaypoint OBJECT_FIELD_WAYPOINT(0x1E)
#define /*0x104*/ oPathedPrevWaypointFlags OBJECT_FIELD_S32(0x1F) #define /*0x104*/ oPathedPrevWaypointFlags OBJECT_FIELD_S32(0x1F)
@ -966,8 +964,8 @@
#define /*0x110*/ oToadMessageState OBJECT_FIELD_S32(0x22) #define /*0x110*/ oToadMessageState OBJECT_FIELD_S32(0x22)
/* Tox Box */ /* Tox Box */
#define /*0x1AC*/ oToxBoxUnk1AC OBJECT_FIELD_VPTR(0x49) #define /*0x1AC*/ oToxBoxMovementPattern OBJECT_FIELD_VPTR(0x49)
#define /*0x1B0*/ oToxBoxUnk1B0 OBJECT_FIELD_S32(0x4A) #define /*0x1B0*/ oToxBoxMovementStep OBJECT_FIELD_S32(0x4A)
/* TTC Rotating Solid */ /* TTC Rotating Solid */
#define /*0x0F4*/ oTTCRotatingSolidNumTurns OBJECT_FIELD_S32(0x1B) #define /*0x0F4*/ oTTCRotatingSolidNumTurns OBJECT_FIELD_S32(0x1B)

View File

@ -131,7 +131,7 @@ struct GraphNodeObject
/*0x2C*/ Vec3f scale; /*0x2C*/ Vec3f scale;
/*0x38*/ struct GraphNodeObject_sub unk38; /*0x38*/ struct GraphNodeObject_sub unk38;
/*0x4C*/ struct SpawnInfo *unk4C; /*0x4C*/ struct SpawnInfo *unk4C;
/*0x50*/ void *throwMatrix; // matrix ptr /*0x50*/ Mat4 *throwMatrix; // matrix ptr
/*0x54*/ Vec3f cameraToObject; /*0x54*/ Vec3f cameraToObject;
}; };

View File

@ -2120,7 +2120,7 @@ void func_80320A4C(u8 bankIndex, u8 arg1) {
void play_dialog_sound(u8 dialogID) { void play_dialog_sound(u8 dialogID) {
u8 speaker; u8 speaker;
if (dialogID >= 170) { if (dialogID >= DIALOG_COUNT) {
dialogID = 0; dialogID = 0;
} }

View File

@ -10,8 +10,8 @@
#define DMEM_ADDR_TEMP 0x0 #define DMEM_ADDR_TEMP 0x0
#define DMEM_ADDR_UNCOMPRESSED_NOTE 0x180 #define DMEM_ADDR_UNCOMPRESSED_NOTE 0x180
#define DMEM_ADDR_ADPCM_RESAMPLED 0x20 #define DMEM_ADDR_RESAMPLED 0x20
#define DMEM_ADDR_ADPCM_RESAMPLED2 0x160 #define DMEM_ADDR_RESAMPLED2 0x160
#define DMEM_ADDR_NOTE_PAN_TEMP 0x200 #define DMEM_ADDR_NOTE_PAN_TEMP 0x200
#define DMEM_ADDR_STEREO_STRONG_TEMP_DRY 0x200 #define DMEM_ADDR_STEREO_STRONG_TEMP_DRY 0x200
#define DMEM_ADDR_STEREO_STRONG_TEMP_WET 0x340 #define DMEM_ADDR_STEREO_STRONG_TEMP_WET 0x340
@ -99,14 +99,14 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex, s32 reverbIndex)
// Touches both left and right since they are adjacent in memory // Touches both left and right since they are adjacent in memory
osInvalDCache(item->toDownsampleLeft, DEFAULT_LEN_2CH); osInvalDCache(item->toDownsampleLeft, DEFAULT_LEN_2CH);
for (srcPos = 0, dstPos = 0; dstPos < item->lengths[0] / 2; for (srcPos = 0, dstPos = 0; dstPos < item->lengthA / 2;
srcPos += reverb->downsampleRate, dstPos++) { srcPos += reverb->downsampleRate, dstPos++) {
reverb->ringBuffer.left[item->startPos + dstPos] = reverb->ringBuffer.left[item->startPos + dstPos] =
item->toDownsampleLeft[srcPos]; item->toDownsampleLeft[srcPos];
reverb->ringBuffer.right[item->startPos + dstPos] = reverb->ringBuffer.right[item->startPos + dstPos] =
item->toDownsampleRight[srcPos]; item->toDownsampleRight[srcPos];
} }
for (dstPos = 0; dstPos < item->lengths[1] / 2; srcPos += reverb->downsampleRate, dstPos++) { for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += reverb->downsampleRate, dstPos++) {
reverb->ringBuffer.left[dstPos] = item->toDownsampleLeft[srcPos]; reverb->ringBuffer.left[dstPos] = item->toDownsampleLeft[srcPos];
reverb->ringBuffer.right[dstPos] = item->toDownsampleRight[srcPos]; reverb->ringBuffer.right[dstPos] = item->toDownsampleRight[srcPos];
} }
@ -118,14 +118,14 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex, s32 reverbIndex)
excessiveSamples = (nSamples + reverb->nextRingBufferPos) - reverb->bufSizePerChannel; excessiveSamples = (nSamples + reverb->nextRingBufferPos) - reverb->bufSizePerChannel;
if (excessiveSamples < 0) { if (excessiveSamples < 0) {
// There is space in the ring buffer before it wraps around // There is space in the ring buffer before it wraps around
item->lengths[0] = nSamples * 2; item->lengthA = nSamples * 2;
item->lengths[1] = 0; item->lengthB = 0;
item->startPos = (s32) reverb->nextRingBufferPos; item->startPos = (s32) reverb->nextRingBufferPos;
reverb->nextRingBufferPos += nSamples; reverb->nextRingBufferPos += nSamples;
} else { } else {
// Ring buffer wrapped around // Ring buffer wrapped around
item->lengths[0] = (nSamples - excessiveSamples) * 2; item->lengthA = (nSamples - excessiveSamples) * 2;
item->lengths[1] = excessiveSamples * 2; item->lengthB = excessiveSamples * 2;
item->startPos = reverb->nextRingBufferPos; item->startPos = reverb->nextRingBufferPos;
reverb->nextRingBufferPos = excessiveSamples; reverb->nextRingBufferPos = excessiveSamples;
} }
@ -150,14 +150,14 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex) {
// Touches both left and right since they are adjacent in memory // Touches both left and right since they are adjacent in memory
osInvalDCache(item->toDownsampleLeft, DEFAULT_LEN_2CH); osInvalDCache(item->toDownsampleLeft, DEFAULT_LEN_2CH);
for (srcPos = 0, dstPos = 0; dstPos < item->lengths[0] / 2; for (srcPos = 0, dstPos = 0; dstPos < item->lengthA / 2;
srcPos += gReverbDownsampleRate, dstPos++) { srcPos += gReverbDownsampleRate, dstPos++) {
gSynthesisReverb.ringBuffer.left[dstPos + item->startPos] = gSynthesisReverb.ringBuffer.left[dstPos + item->startPos] =
item->toDownsampleLeft[srcPos]; item->toDownsampleLeft[srcPos];
gSynthesisReverb.ringBuffer.right[dstPos + item->startPos] = gSynthesisReverb.ringBuffer.right[dstPos + item->startPos] =
item->toDownsampleRight[srcPos]; item->toDownsampleRight[srcPos];
} }
for (dstPos = 0; dstPos < item->lengths[1] / 2; srcPos += gReverbDownsampleRate, dstPos++) { for (dstPos = 0; dstPos < item->lengthB / 2; srcPos += gReverbDownsampleRate, dstPos++) {
gSynthesisReverb.ringBuffer.left[dstPos] = item->toDownsampleLeft[srcPos]; gSynthesisReverb.ringBuffer.left[dstPos] = item->toDownsampleLeft[srcPos];
gSynthesisReverb.ringBuffer.right[dstPos] = item->toDownsampleRight[srcPos]; gSynthesisReverb.ringBuffer.right[dstPos] = item->toDownsampleRight[srcPos];
} }
@ -168,8 +168,8 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex) {
numSamplesAfterDownsampling = chunkLen / gReverbDownsampleRate; numSamplesAfterDownsampling = chunkLen / gReverbDownsampleRate;
if (((numSamplesAfterDownsampling + gSynthesisReverb.nextRingBufferPos) - gSynthesisReverb.bufSizePerChannel) < 0) { if (((numSamplesAfterDownsampling + gSynthesisReverb.nextRingBufferPos) - gSynthesisReverb.bufSizePerChannel) < 0) {
// There is space in the ring buffer before it wraps around // There is space in the ring buffer before it wraps around
item->lengths[0] = numSamplesAfterDownsampling * 2; item->lengthA = numSamplesAfterDownsampling * 2;
item->lengths[1] = 0; item->lengthB = 0;
item->startPos = (s32) gSynthesisReverb.nextRingBufferPos; item->startPos = (s32) gSynthesisReverb.nextRingBufferPos;
gSynthesisReverb.nextRingBufferPos += numSamplesAfterDownsampling; gSynthesisReverb.nextRingBufferPos += numSamplesAfterDownsampling;
} else { } else {
@ -177,8 +177,8 @@ void prepare_reverb_ring_buffer(s32 chunkLen, u32 updateIndex) {
excessiveSamples = excessiveSamples =
(numSamplesAfterDownsampling + gSynthesisReverb.nextRingBufferPos) - gSynthesisReverb.bufSizePerChannel; (numSamplesAfterDownsampling + gSynthesisReverb.nextRingBufferPos) - gSynthesisReverb.bufSizePerChannel;
nSamples = numSamplesAfterDownsampling - excessiveSamples; nSamples = numSamplesAfterDownsampling - excessiveSamples;
item->lengths[0] = nSamples * 2; item->lengthA = nSamples * 2;
item->lengths[1] = excessiveSamples * 2; item->lengthB = excessiveSamples * 2;
item->startPos = gSynthesisReverb.nextRingBufferPos; item->startPos = gSynthesisReverb.nextRingBufferPos;
gSynthesisReverb.nextRingBufferPos = excessiveSamples; gSynthesisReverb.nextRingBufferPos = excessiveSamples;
} }
@ -348,33 +348,33 @@ u64 *synthesis_execute(u64 *cmdBuf, s32 *writtenCmds, s16 *aiBuf, s32 bufLen) {
#ifdef VERSION_EU #ifdef VERSION_EU
u64 *synthesis_resample_and_mix_reverb(u64 *cmd, s32 bufLen, s16 reverbIndex, s16 updateIndex) { u64 *synthesis_resample_and_mix_reverb(u64 *cmd, s32 bufLen, s16 reverbIndex, s16 updateIndex) {
struct ReverbRingBufferItem *item; struct ReverbRingBufferItem *item;
s16 temp_t9; // sp5a s16 startPad;
s16 sp58; // sp58 s16 paddedLengthA;
item = &gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex]; item = &gSynthesisReverbs[reverbIndex].items[gSynthesisReverbs[reverbIndex].curFrame][updateIndex];
aClearBuffer(cmd++, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH); aClearBuffer(cmd++, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH);
if (gSynthesisReverbs[reverbIndex].downsampleRate == 1) { if (gSynthesisReverbs[reverbIndex].downsampleRate == 1) {
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengths[0], reverbIndex); cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengthA, reverbIndex);
if (item->lengths[1] != 0) { if (item->lengthB != 0) {
cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengths[0], 0, item->lengths[1], reverbIndex); cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengthA, 0, item->lengthB, reverbIndex);
} }
aSetBuffer(cmd++, 0, 0, 0, DEFAULT_LEN_2CH); aSetBuffer(cmd++, 0, 0, 0, DEFAULT_LEN_2CH);
aMix(cmd++, 0, 0x7fff, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_LEFT_CH); aMix(cmd++, 0, 0x7fff, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_LEFT_CH);
aMix(cmd++, 0, 0x8000 + gSynthesisReverbs[reverbIndex].reverbGain, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_WET_LEFT_CH); aMix(cmd++, 0, 0x8000 + gSynthesisReverbs[reverbIndex].reverbGain, DMEM_ADDR_WET_LEFT_CH, DMEM_ADDR_WET_LEFT_CH);
} else { } else {
temp_t9 = (item->startPos % 8u) * 2; startPad = (item->startPos % 8u) * 2;
sp58 = ALIGN(item->lengths[0] + (sp58=temp_t9), 4); paddedLengthA = ALIGN(startPad + item->lengthA, 4);
cmd = synthesis_load_reverb_ring_buffer(cmd, 0x20, (item->startPos - temp_t9 / 2), DEFAULT_LEN_1CH, reverbIndex); cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED, (item->startPos - startPad / 2), DEFAULT_LEN_1CH, reverbIndex);
if (item->lengths[1] != 0) { if (item->lengthB != 0) {
cmd = synthesis_load_reverb_ring_buffer(cmd, 0x20 + sp58, 0, DEFAULT_LEN_1CH - sp58, reverbIndex); cmd = synthesis_load_reverb_ring_buffer(cmd, DMEM_ADDR_RESAMPLED + paddedLengthA, 0, DEFAULT_LEN_1CH - paddedLengthA, reverbIndex);
} }
aSetBuffer(cmd++, 0, temp_t9 + DMEM_ADDR_ADPCM_RESAMPLED, DMEM_ADDR_WET_LEFT_CH, bufLen * 2); aSetBuffer(cmd++, 0, DMEM_ADDR_RESAMPLED + startPad, DMEM_ADDR_WET_LEFT_CH, bufLen * 2);
aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateLeft)); aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateLeft));
aSetBuffer(cmd++, 0, temp_t9 + DMEM_ADDR_ADPCM_RESAMPLED2, DMEM_ADDR_WET_RIGHT_CH, bufLen * 2); aSetBuffer(cmd++, 0, DMEM_ADDR_RESAMPLED2 + startPad, DMEM_ADDR_WET_RIGHT_CH, bufLen * 2);
aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateRight)); aResample(cmd++, gSynthesisReverbs[reverbIndex].resampleFlags, gSynthesisReverbs[reverbIndex].resampleRate, VIRTUAL_TO_PHYSICAL2(gSynthesisReverbs[reverbIndex].resampleStateRight));
aSetBuffer(cmd++, 0, 0, 0, DEFAULT_LEN_2CH); aSetBuffer(cmd++, 0, 0, 0, DEFAULT_LEN_2CH);
@ -396,10 +396,10 @@ u64 *synthesis_save_reverb_samples(u64 *cmdBuf, s16 reverbIndex, s16 updateIndex
} }
if (reverb->downsampleRate == 1) { if (reverb->downsampleRate == 1) {
// Put the oldest samples in the ring buffer into the wet channels // Put the oldest samples in the ring buffer into the wet channels
cmd = cmdBuf = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengths[0], reverbIndex); cmd = cmdBuf = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH, item->startPos, item->lengthA, reverbIndex);
if (item->lengths[1] != 0) { if (item->lengthB != 0) {
// Ring buffer wrapped // Ring buffer wrapped
cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengths[0], 0, item->lengths[1], reverbIndex); cmd = synthesis_save_reverb_ring_buffer(cmd, DMEM_ADDR_WET_LEFT_CH + item->lengthA, 0, item->lengthB, reverbIndex);
cmdBuf = cmd; cmdBuf = cmd;
} }
} else { } else {
@ -512,9 +512,9 @@ u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, u32 updateI
if (gReverbDownsampleRate == 1) { if (gReverbDownsampleRate == 1) {
// Put the oldest samples in the ring buffer into the wet channels // Put the oldest samples in the ring buffer into the wet channels
aSetLoadBufferPair(cmd++, 0, v1->startPos); aSetLoadBufferPair(cmd++, 0, v1->startPos);
if (v1->lengths[1] != 0) { if (v1->lengthB != 0) {
// Ring buffer wrapped // Ring buffer wrapped
aSetLoadBufferPair(cmd++, v1->lengths[0], 0); aSetLoadBufferPair(cmd++, v1->lengthA, 0);
temp = 0; temp = 0;
} }
@ -531,9 +531,9 @@ u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, u32 updateI
// Same as above but upsample the previously downsampled samples used for reverb first // Same as above but upsample the previously downsampled samples used for reverb first
temp = 0; //! jesus christ temp = 0; //! jesus christ
t4 = (v1->startPos & 7) * 2; t4 = (v1->startPos & 7) * 2;
ra = ALIGN(v1->lengths[0] + t4, 4); ra = ALIGN(v1->lengthA + t4, 4);
aSetLoadBufferPair(cmd++, 0, v1->startPos - t4 / 2); aSetLoadBufferPair(cmd++, 0, v1->startPos - t4 / 2);
if (v1->lengths[1] != 0) { if (v1->lengthB != 0) {
// Ring buffer wrapped // Ring buffer wrapped
aSetLoadBufferPair(cmd++, ra, 0); aSetLoadBufferPair(cmd++, ra, 0);
//! We need an empty statement (even an empty ';') here to make the function match (because IDO). //! We need an empty statement (even an empty ';') here to make the function match (because IDO).
@ -552,10 +552,10 @@ u64 *synthesis_do_one_audio_update(s16 *aiBuf, s32 bufLen, u64 *cmd, u32 updateI
} }
cmd = synthesis_process_notes(aiBuf, bufLen, cmd); cmd = synthesis_process_notes(aiBuf, bufLen, cmd);
if (gReverbDownsampleRate == 1) { if (gReverbDownsampleRate == 1) {
aSetSaveBufferPair(cmd++, 0, v1->lengths[0], v1->startPos); aSetSaveBufferPair(cmd++, 0, v1->lengthA, v1->startPos);
if (v1->lengths[1] != 0) { if (v1->lengthB != 0) {
// Ring buffer wrapped // Ring buffer wrapped
aSetSaveBufferPair(cmd++, v1->lengths[0], v1->lengths[1], 0); aSetSaveBufferPair(cmd++, v1->lengthA, v1->lengthB, 0);
} }
} else { } else {
// Downsampling is done later by CPU when RSP is done, therefore we need to have double // Downsampling is done later by CPU when RSP is done, therefore we need to have double
@ -966,26 +966,26 @@ u64 *synthesis_process_notes(s16 *aiBuf, s32 bufLen, u64 *cmd) {
case 2: case 2:
switch (curPart) { switch (curPart) {
case 0: case 0:
aSetBuffer(cmd++, 0, DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, DMEM_ADDR_ADPCM_RESAMPLED, samplesLenAdjusted + 4); aSetBuffer(cmd++, 0, DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, DMEM_ADDR_RESAMPLED, samplesLenAdjusted + 4);
#ifdef VERSION_EU #ifdef VERSION_EU
aResample(cmd++, A_INIT, 0xff60, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->dummyResampleState)); aResample(cmd++, A_INIT, 0xff60, VIRTUAL_TO_PHYSICAL2(synthesisState->synthesisBuffers->dummyResampleState));
#else #else
aResample(cmd++, A_INIT, 0xff60, VIRTUAL_TO_PHYSICAL2(note->synthesisBuffers->dummyResampleState)); aResample(cmd++, A_INIT, 0xff60, VIRTUAL_TO_PHYSICAL2(note->synthesisBuffers->dummyResampleState));
#endif #endif
resampledTempLen = samplesLenAdjusted + 4; resampledTempLen = samplesLenAdjusted + 4;
noteSamplesDmemAddrBeforeResampling = DMEM_ADDR_ADPCM_RESAMPLED + 4; noteSamplesDmemAddrBeforeResampling = DMEM_ADDR_RESAMPLED + 4;
#ifdef VERSION_EU #ifdef VERSION_EU
if (noteSubEu->finished != FALSE) { if (noteSubEu->finished != FALSE) {
#else #else
if (note->finished != FALSE) { if (note->finished != FALSE) {
#endif #endif
aClearBuffer(cmd++, DMEM_ADDR_ADPCM_RESAMPLED + resampledTempLen, samplesLenAdjusted + 0x10); aClearBuffer(cmd++, DMEM_ADDR_RESAMPLED + resampledTempLen, samplesLenAdjusted + 0x10);
} }
break; break;
case 1: case 1:
aSetBuffer(cmd++, 0, DMEM_ADDR_UNCOMPRESSED_NOTE + sp130, aSetBuffer(cmd++, 0, DMEM_ADDR_UNCOMPRESSED_NOTE + sp130,
DMEM_ADDR_ADPCM_RESAMPLED2, DMEM_ADDR_RESAMPLED2,
samplesLenAdjusted + 8); samplesLenAdjusted + 8);
#ifdef VERSION_EU #ifdef VERSION_EU
aResample(cmd++, A_INIT, 0xff60, aResample(cmd++, A_INIT, 0xff60,
@ -996,8 +996,8 @@ u64 *synthesis_process_notes(s16 *aiBuf, s32 bufLen, u64 *cmd) {
VIRTUAL_TO_PHYSICAL2( VIRTUAL_TO_PHYSICAL2(
note->synthesisBuffers->dummyResampleState)); note->synthesisBuffers->dummyResampleState));
#endif #endif
aDMEMMove(cmd++, DMEM_ADDR_ADPCM_RESAMPLED2 + 4, aDMEMMove(cmd++, DMEM_ADDR_RESAMPLED2 + 4,
DMEM_ADDR_ADPCM_RESAMPLED + resampledTempLen, DMEM_ADDR_RESAMPLED + resampledTempLen,
samplesLenAdjusted + 4); samplesLenAdjusted + 4);
break; break;
} }

View File

@ -19,7 +19,8 @@ struct ReverbRingBufferItem
s16 *toDownsampleLeft; s16 *toDownsampleLeft;
s16 *toDownsampleRight; // data pointed to by left and right are adjacent in memory s16 *toDownsampleRight; // data pointed to by left and right are adjacent in memory
s32 startPos; // start pos in ring buffer s32 startPos; // start pos in ring buffer
s16 lengths[2]; // first length in ring buffer (max until end) and second length in ring buffer (from pos 0) s16 lengthA; // first length in ring buffer (from startPos, at most until end)
s16 lengthB; // second length in ring buffer (from pos 0)
}; // size = 0x14 }; // size = 0x14
struct SynthesisReverb struct SynthesisReverb

View File

@ -116,7 +116,7 @@ struct GraphNodePerspective
*/ */
struct DisplayListNode struct DisplayListNode
{ {
void *transform; Mtx *transform;
void *displayList; void *displayList;
struct DisplayListNode *next; struct DisplayListNode *next;
}; };
@ -184,7 +184,7 @@ struct GraphNodeCamera
} config; } config;
/*0x1C*/ Vec3f pos; /*0x1C*/ Vec3f pos;
/*0x28*/ Vec3f focus; /*0x28*/ Vec3f focus;
/*0x34*/ void *matrixPtr; // pointer to look-at matrix of this camera as a Mat4 /*0x34*/ Mat4 *matrixPtr; // pointer to look-at matrix of this camera as a Mat4
/*0x38*/ s16 roll; // roll in look at matrix. Doesn't account for light direction unlike rollScreen. /*0x38*/ s16 roll; // roll in look at matrix. Doesn't account for light direction unlike rollScreen.
/*0x3A*/ s16 rollScreen; // rolls screen while keeping the light direction consistent /*0x3A*/ s16 rollScreen; // rolls screen while keeping the light direction consistent
}; };

View File

@ -19,6 +19,7 @@
#include "game_init.h" #include "game_init.h"
#include "ingame_menu.h" #include "ingame_menu.h"
#include "interaction.h" #include "interaction.h"
#include "level_misc_macros.h"
#include "level_table.h" #include "level_table.h"
#include "level_update.h" #include "level_update.h"
#include "levels/bob/header.h" #include "levels/bob/header.h"
@ -173,7 +174,7 @@ Gfx *geo_move_mario_part_from_parent(s32 run, UNUSED struct GraphNode *node, Mat
if (run == TRUE) { if (run == TRUE) {
sp1C = (struct Object *) gCurGraphNodeObject; sp1C = (struct Object *) gCurGraphNodeObject;
if (sp1C == gMarioObject && sp1C->prevObj != NULL) { if (sp1C == gMarioObject && sp1C->prevObj != NULL) {
create_transformation_from_matrices(sp20, mtx, gCurGraphNodeCamera->matrixPtr); create_transformation_from_matrices(sp20, mtx, *gCurGraphNodeCamera->matrixPtr);
obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj); obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj);
obj_set_gfx_pos_from_pos(sp1C->prevObj); obj_set_gfx_pos_from_pos(sp1C->prevObj);
} }

View File

@ -273,7 +273,7 @@ static s32 boo_update_during_death(void) {
o->oBooTargetOpacity = 0; o->oBooTargetOpacity = 0;
} }
if (o->oTimer > 30 || o->oMoveFlags & 0x200) { if (o->oTimer > 30 || o->oMoveFlags & OBJ_MOVE_HIT_WALL) {
spawn_mist_particles(); spawn_mist_particles();
o->oBooDeathStatus = BOO_DEATH_STATUS_DEAD; o->oBooDeathStatus = BOO_DEATH_STATUS_DEAD;

View File

@ -9,7 +9,7 @@ void bhv_bouncing_fireball_flame_loop(void) {
o->oAnimState = random_float() * 10.0f; o->oAnimState = random_float() * 10.0f;
o->oVelY = 30.0f; o->oVelY = 30.0f;
} }
if (o->oMoveFlags & 1) if (o->oMoveFlags & OBJ_MOVE_LANDED)
o->oAction++; o->oAction++;
break; break;
case 1: case 1:
@ -17,7 +17,7 @@ void bhv_bouncing_fireball_flame_loop(void) {
o->oVelY = 50.0f; o->oVelY = 50.0f;
o->oForwardVel = 30.0f; o->oForwardVel = 30.0f;
} }
if (o->oMoveFlags & (0x40 | 0x10 | 0x2) && o->oTimer > 100) if (o->oMoveFlags & (OBJ_MOVE_UNDERWATER_ON_GROUND | OBJ_MOVE_AT_WATER_SURFACE | OBJ_MOVE_ON_GROUND) && o->oTimer > 100)
obj_mark_for_deletion(o); obj_mark_for_deletion(o);
break; break;
} }

View File

@ -12,19 +12,32 @@ static struct ObjectHitbox sBowlingBallHitbox = {
/* hurtboxHeight: */ 0, /* hurtboxHeight: */ 0,
}; };
// TODO: these are likely Waypoint structs static Trajectory sThiHugeMetalBallTraj[] = {
static s16 D_803315B4[] = { 0x0000, 0xED4E, 0x0065, 0xF78A, 0x0001, 0xEC78, 0x0051, 0xF53F, 0x0002, TRAJECTORY_POS(0, /*pos*/ -4786, 101, -2166),
0xEC50, 0x0021, 0xF0FA, 0x0003, 0xEC9A, 0x0026, 0xEC9A, 0x0004, 0xF053, TRAJECTORY_POS(1, /*pos*/ -5000, 81, -2753),
0xFEFD, 0xECE3, 0x0005, 0xF5F3, 0xFC05, 0xED54, 0x0006, 0xFBE3, 0xFA89, TRAJECTORY_POS(2, /*pos*/ -5040, 33, -3846),
0xED3A, 0x0007, 0x02F8, 0xF99B, 0xED1F, 0x0008, 0x0B32, 0xF801, 0xECEA, TRAJECTORY_POS(3, /*pos*/ -4966, 38, -4966),
0x0009, 0x0D3A, 0xE66E, 0xED1F, 0xFFFF, 0x0000 }; TRAJECTORY_POS(4, /*pos*/ -4013, -259, -4893),
TRAJECTORY_POS(5, /*pos*/ -2573, -1019, -4780),
TRAJECTORY_POS(6, /*pos*/ -1053, -1399, -4806),
TRAJECTORY_POS(7, /*pos*/ 760, -1637, -4833),
TRAJECTORY_POS(8, /*pos*/ 2866, -2047, -4886),
TRAJECTORY_POS(9, /*pos*/ 3386, -6546, -4833),
TRAJECTORY_END(),
};
// TODO: these are likely Waypoint structs static Trajectory sThiTinyMetalBallTraj[] = {
static s16 D_80331608[] = { 0x0000, 0xFA3C, 0x001D, 0xFD58, 0x0001, 0xFA2C, 0x000E, 0xFBD0, TRAJECTORY_POS(0, /*pos*/ -1476, 29, -680),
0x0002, 0xFA24, 0x0003, 0xFACD, 0x0003, 0xFAA2, 0xFFEF, 0xFA09, TRAJECTORY_POS(1, /*pos*/ -1492, 14, -1072),
0x0004, 0xFB66, 0xFFAD, 0xFA28, 0x0005, 0xFEDC, 0xFE58, 0xFA6F, TRAJECTORY_POS(2, /*pos*/ -1500, 3, -1331),
0x0006, 0x00FA, 0xFE15, 0xFA67, 0x0007, 0x035E, 0xFD9B, 0xFA57, TRAJECTORY_POS(3, /*pos*/ -1374, -17, -1527),
0x0008, 0x0422, 0xF858, 0xFA57, 0xFFFF, 0x0000 }; TRAJECTORY_POS(4, /*pos*/ -1178, -83, -1496),
TRAJECTORY_POS(5, /*pos*/ -292, -424, -1425),
TRAJECTORY_POS(6, /*pos*/ 250, -491, -1433),
TRAJECTORY_POS(7, /*pos*/ 862, -613, -1449),
TRAJECTORY_POS(8, /*pos*/ 1058, -1960, -1449),
TRAJECTORY_END(),
};
void bhv_bowling_ball_init(void) { void bhv_bowling_ball_init(void) {
o->oGravity = 5.5f; o->oGravity = 5.5f;
@ -42,23 +55,23 @@ void bowling_ball_set_hitbox(void) {
void bowling_ball_set_waypoints(void) { void bowling_ball_set_waypoints(void) {
switch (o->oBehParams2ndByte) { switch (o->oBehParams2ndByte) {
case BBALL_BP_STYPE_BOB_UPPER: case BBALL_BP_STYPE_BOB_UPPER:
o->oPathedWaypointsS16 = segmented_to_virtual(bob_seg7_metal_ball_path0); o->oPathedStartWaypoint = segmented_to_virtual(bob_seg7_metal_ball_path0);
break; break;
case BBALL_BP_STYPE_TTM: case BBALL_BP_STYPE_TTM:
o->oPathedWaypointsS16 = segmented_to_virtual(ttm_seg7_trajectory_070170A0); o->oPathedStartWaypoint = segmented_to_virtual(ttm_seg7_trajectory_070170A0);
break; break;
case BBALL_BP_STYPE_BOB_LOWER: case BBALL_BP_STYPE_BOB_LOWER:
o->oPathedWaypointsS16 = segmented_to_virtual(bob_seg7_metal_ball_path1); o->oPathedStartWaypoint = segmented_to_virtual(bob_seg7_metal_ball_path1);
break; break;
case BBALL_BP_STYPE_THI_LARGE: case BBALL_BP_STYPE_THI_LARGE:
o->oPathedWaypointsS16 = D_803315B4; o->oPathedStartWaypoint = (struct Waypoint *) sThiHugeMetalBallTraj;
break; break;
case BBALL_BP_STYPE_THI_SMALL: case BBALL_BP_STYPE_THI_SMALL:
o->oPathedWaypointsS16 = D_80331608; o->oPathedStartWaypoint = (struct Waypoint *) sThiTinyMetalBallTraj;
break; break;
} }
} }

View File

@ -106,7 +106,7 @@ s32 bowser_spawn_shockwave(void) {
} }
void bowser_bounce(s32 *a) { void bowser_bounce(s32 *a) {
if (o->oMoveFlags & 1) { if (o->oMoveFlags & OBJ_MOVE_LANDED) {
a[0]++; a[0]++;
if (a[0] < 4) { if (a[0] < 4) {
cur_obj_start_cam_event(o, CAM_EVENT_BOWSER_THROW_BOUNCE); cur_obj_start_cam_event(o, CAM_EVENT_BOWSER_THROW_BOUNCE);
@ -453,7 +453,7 @@ s32 bowser_set_anim_in_air(void) {
} }
s32 bowser_land(void) { s32 bowser_land(void) {
if (o->oMoveFlags & 1) { if (o->oMoveFlags & OBJ_MOVE_LANDED) {
o->oForwardVel = 0; o->oForwardVel = 0;
o->oVelY = 0; o->oVelY = 0;
spawn_mist_particles_variable(0, 0, 60.0f); spawn_mist_particles_variable(0, 0, 60.0f);
@ -627,7 +627,7 @@ void bowser_act_charge_mario(void) {
cur_obj_extend_animation_if_at_end(); cur_obj_extend_animation_if_at_end();
break; break;
} }
if (o->oMoveFlags & 0x400) if (o->oMoveFlags & OBJ_MOVE_HIT_EDGE)
o->oAction = 10; o->oAction = 10;
} }
@ -650,7 +650,7 @@ void bowser_act_thrown_dropped(void)
if (o->oSubAction == 0) { if (o->oSubAction == 0) {
cur_obj_init_animation_with_sound(2); cur_obj_init_animation_with_sound(2);
bowser_bounce(&o->oBowserUnkF8); bowser_bounce(&o->oBowserUnkF8);
if (o->oMoveFlags & 2) { if (o->oMoveFlags & OBJ_MOVE_ON_GROUND) {
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
o->oSubAction++; o->oSubAction++;
} }
@ -780,9 +780,9 @@ void bowser_fly_back_dead(void) {
void bowser_dead_bounce(void) { void bowser_dead_bounce(void) {
o->oBowserEyesShut = 1; o->oBowserEyesShut = 1;
bowser_bounce(&o->oBowserUnkF8); bowser_bounce(&o->oBowserUnkF8);
if (o->oMoveFlags & 1) if (o->oMoveFlags & OBJ_MOVE_LANDED)
cur_obj_play_sound_2(SOUND_OBJ_BOWSER_WALK); cur_obj_play_sound_2(SOUND_OBJ_BOWSER_WALK);
if (o->oMoveFlags & 2) { if (o->oMoveFlags & OBJ_MOVE_ON_GROUND) {
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
o->oSubAction++; o->oSubAction++;
} }
@ -962,7 +962,7 @@ s32 bowser_check_fallen_off_stage(void) // bowser off stage?
if (o->oAction != 2 && o->oAction != 19) { if (o->oAction != 2 && o->oAction != 19) {
if (o->oPosY < o->oHomeY - 1000.0f) if (o->oPosY < o->oHomeY - 1000.0f)
return 1; return 1;
if (o->oMoveFlags & 1) { if (o->oMoveFlags & OBJ_MOVE_LANDED) {
if (o->oFloorType == 1) if (o->oFloorType == 1)
return 1; return 1;
if (o->oFloorType == 10) if (o->oFloorType == 10)
@ -1168,7 +1168,7 @@ Gfx *geo_update_body_rot_from_parent(s32 run, UNUSED struct GraphNode *node, Mat
if (run == TRUE) { if (run == TRUE) {
sp1C = (struct Object *) gCurGraphNodeObject; sp1C = (struct Object *) gCurGraphNodeObject;
if (sp1C->prevObj != NULL) { if (sp1C->prevObj != NULL) {
create_transformation_from_matrices(sp20, mtx, gCurGraphNodeCamera->matrixPtr); create_transformation_from_matrices(sp20, mtx, *gCurGraphNodeCamera->matrixPtr);
obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj); obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj);
obj_set_gfx_pos_from_pos(sp1C->prevObj); obj_set_gfx_pos_from_pos(sp1C->prevObj);
} }
@ -1424,7 +1424,7 @@ void bhv_flame_bowser_loop(void) {
if (o->oAction == 0) { if (o->oAction == 0) {
cur_obj_become_intangible(); cur_obj_become_intangible();
bowser_flame_move(); bowser_flame_move();
if (o->oMoveFlags & 1) { if (o->oMoveFlags & OBJ_MOVE_LANDED) {
o->oAction++; o->oAction++;
if (cur_obj_has_behavior(bhvFlameLargeBurningOut)) if (cur_obj_has_behavior(bhvFlameLargeBurningOut))
o->oFlameUnkF4 = 8.0f; o->oFlameUnkF4 = 8.0f;
@ -1494,7 +1494,7 @@ void bhv_flame_floating_landing_loop(void) {
obj_mark_for_deletion(o); obj_mark_for_deletion(o);
if (o->oVelY < D_8032F748[o->oBehParams2ndByte]) if (o->oVelY < D_8032F748[o->oBehParams2ndByte])
o->oVelY = D_8032F748[o->oBehParams2ndByte]; o->oVelY = D_8032F748[o->oBehParams2ndByte];
if (o->oMoveFlags & 1) { if (o->oMoveFlags & OBJ_MOVE_LANDED) {
if (o->oBehParams2ndByte == 0) if (o->oBehParams2ndByte == 0)
spawn_object(o, MODEL_RED_FLAME, bhvFlameLargeBurningOut); spawn_object(o, MODEL_RED_FLAME, bhvFlameLargeBurningOut);
else else

View File

@ -33,7 +33,7 @@ void bubba_act_0(void) {
o->oBubbaUnkF8 = random_linear_offset(20, 30); o->oBubbaUnkF8 = random_linear_offset(20, 30);
} }
if ((o->oBubbaUnkFC = o->oMoveFlags & 0x00000200) != 0) { if ((o->oBubbaUnkFC = o->oMoveFlags & OBJ_MOVE_HIT_WALL) != 0) {
o->oBubbaUnk1AE = cur_obj_reflect_move_angle_off_wall(); o->oBubbaUnk1AE = cur_obj_reflect_move_angle_off_wall();
} else if (o->oTimer > 30 && o->oDistanceToMario < 2000.0f) { } else if (o->oTimer > 30 && o->oDistanceToMario < 2000.0f) {
o->oAction = 1; o->oAction = 1;
@ -130,8 +130,8 @@ void bhv_bubba_loop(void) {
break; break;
} }
if (o->oMoveFlags & 0x00000078) { if (o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER) {
if (o->oMoveFlags & 0x00000008) { if (o->oMoveFlags & OBJ_MOVE_ENTERED_WATER) {
sp38 = spawn_object(o, MODEL_WATER_SPLASH, bhvWaterSplash); sp38 = spawn_object(o, MODEL_WATER_SPLASH, bhvWaterSplash);
if (sp38 != NULL) { if (sp38 != NULL) {
obj_scale(sp38, 3.0f); obj_scale(sp38, 3.0f);

View File

@ -45,7 +45,7 @@ void bullet_bill_act_2(void) {
cur_obj_play_sound_2(SOUND_OBJ_POUNDING_CANNON); cur_obj_play_sound_2(SOUND_OBJ_POUNDING_CANNON);
cur_obj_shake_screen(SHAKE_POS_SMALL); cur_obj_shake_screen(SHAKE_POS_SMALL);
} }
if (o->oTimer > 150 || o->oMoveFlags & 0x200) { if (o->oTimer > 150 || o->oMoveFlags & OBJ_MOVE_HIT_WALL) {
o->oAction = 3; o->oAction = 3;
spawn_mist_particles(); spawn_mist_particles();
} }

View File

@ -168,7 +168,7 @@ void chuckya_act_3(void) {
} }
void chuckya_act_2(void) { void chuckya_act_2(void) {
if (o->oMoveFlags & (0x200 | 0x40 | 0x20 | 0x10 | 0x8 | 0x1)) { if (o->oMoveFlags & (OBJ_MOVE_HIT_WALL | OBJ_MOVE_MASK_IN_WATER | OBJ_MOVE_LANDED)) {
obj_mark_for_deletion(o); obj_mark_for_deletion(o);
obj_spawn_loot_yellow_coins(o, 5, 20.0f); obj_spawn_loot_yellow_coins(o, 5, 20.0f);
spawn_mist_particles_with_sound(SOUND_OBJ_CHUCKYA_DEATH); spawn_mist_particles_with_sound(SOUND_OBJ_CHUCKYA_DEATH);

View File

@ -93,13 +93,13 @@ void bhv_coin_loop(void) {
obj_mark_for_deletion(o); obj_mark_for_deletion(o);
} }
#ifndef VERSION_JP #ifndef VERSION_JP
if (o->oMoveFlags & OBJ_MOVE_13) { if (o->oMoveFlags & OBJ_MOVE_BOUNCE) {
if (o->oCoinUnk1B0 < 5) if (o->oCoinUnk1B0 < 5)
cur_obj_play_sound_2(0x30364081); cur_obj_play_sound_2(0x30364081);
o->oCoinUnk1B0++; o->oCoinUnk1B0++;
} }
#else #else
if (o->oMoveFlags & OBJ_MOVE_13) if (o->oMoveFlags & OBJ_MOVE_BOUNCE)
cur_obj_play_sound_2(SOUND_GENERAL_COIN_DROP); cur_obj_play_sound_2(SOUND_GENERAL_COIN_DROP);
#endif #endif
if (cur_obj_wait_then_blink(400, 20)) if (cur_obj_wait_then_blink(400, 20))
@ -208,7 +208,7 @@ void bhv_coin_formation_loop(void) {
void coin_inside_boo_act_1(void) { void coin_inside_boo_act_1(void) {
cur_obj_update_floor_and_walls(); cur_obj_update_floor_and_walls();
cur_obj_if_hit_wall_bounce_away(); cur_obj_if_hit_wall_bounce_away();
if (o->oMoveFlags & OBJ_MOVE_13) if (o->oMoveFlags & OBJ_MOVE_BOUNCE)
cur_obj_play_sound_2(SOUND_GENERAL_COIN_DROP); cur_obj_play_sound_2(SOUND_GENERAL_COIN_DROP);
if (o->oTimer > 90 || (o->oMoveFlags & OBJ_MOVE_LANDED)) { if (o->oTimer > 90 || (o->oMoveFlags & OBJ_MOVE_LANDED)) {
obj_set_hitbox(o, &sYellowCoinHitbox); obj_set_hitbox(o, &sYellowCoinHitbox);

View File

@ -41,7 +41,7 @@ void bhv_donut_platform_spawner_update(void) {
} }
void bhv_donut_platform_update(void) { void bhv_donut_platform_update(void) {
if (o->oTimer != 0 && ((o->oMoveFlags & 0x00000003) || o->oDistanceToMario > 2500.0f)) { if (o->oTimer != 0 && ((o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) || o->oDistanceToMario > 2500.0f)) {
o->parentObj->oDonutPlatformSpawnerSpawnedPlatforms = o->parentObj->oDonutPlatformSpawnerSpawnedPlatforms =
o->parentObj->oDonutPlatformSpawnerSpawnedPlatforms o->parentObj->oDonutPlatformSpawnerSpawnedPlatforms
& ((1 << o->oBehParams2ndByte) ^ 0xFFFFFFFF); & ((1 << o->oBehParams2ndByte) ^ 0xFFFFFFFF);

View File

@ -292,7 +292,7 @@ static void eyerok_hand_act_show_eye(void) {
if (o->parentObj->oEyerokBossNumHands != 2) { if (o->parentObj->oEyerokBossNumHands != 2) {
obj_face_yaw_approach(o->oMoveAngleYaw, 0x800); obj_face_yaw_approach(o->oMoveAngleYaw, 0x800);
if (o->oTimer > 10 if (o->oTimer > 10
&& (o->oPosZ - gMarioObject->oPosZ > 0.0f || (o->oMoveFlags & 0x00000400))) { && (o->oPosZ - gMarioObject->oPosZ > 0.0f || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE))) {
o->parentObj->oEyerokBossActiveHand = 0; o->parentObj->oEyerokBossActiveHand = 0;
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
} }
@ -321,7 +321,7 @@ static void eyerok_hand_act_attacked(void) {
o->collisionData = segmented_to_virtual(ssl_seg7_collision_07028274); o->collisionData = segmented_to_virtual(ssl_seg7_collision_07028274);
} }
if (o->oMoveFlags & 0x00000003) { if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
} }
} }
@ -346,7 +346,7 @@ static void eyerok_hand_act_die(void) {
create_sound_spawner(SOUND_OBJ2_EYEROK_SOUND_LONG); create_sound_spawner(SOUND_OBJ2_EYEROK_SOUND_LONG);
} }
if (o->oMoveFlags & 0x00000003) { if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
cur_obj_play_sound_2(SOUND_OBJ_POUNDING_LOUD); cur_obj_play_sound_2(SOUND_OBJ_POUNDING_LOUD);
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
} }
@ -378,7 +378,7 @@ static void eyerok_hand_act_retreat(void) {
static void eyerok_hand_act_target_mario(void) { static void eyerok_hand_act_target_mario(void) {
if (eyerok_check_mario_relative_z(400) != 0 || o->oPosZ - gMarioObject->oPosZ > 0.0f if (eyerok_check_mario_relative_z(400) != 0 || o->oPosZ - gMarioObject->oPosZ > 0.0f
|| o->oPosZ - o->parentObj->oPosZ > 1700.0f || absf(o->oPosX - o->parentObj->oPosX) > 900.0f || o->oPosZ - o->parentObj->oPosZ > 1700.0f || absf(o->oPosX - o->parentObj->oPosX) > 900.0f
|| (o->oMoveFlags & 0x00000200)) { || (o->oMoveFlags & OBJ_MOVE_HIT_WALL)) {
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
if (approach_f32_ptr(&o->oPosY, o->oHomeY + 300.0f, 20.0f)) { if (approach_f32_ptr(&o->oPosY, o->oHomeY + 300.0f, 20.0f)) {
o->oAction = EYEROK_HAND_ACT_SMASH; o->oAction = EYEROK_HAND_ACT_SMASH;
@ -394,7 +394,7 @@ static void eyerok_hand_act_smash(void) {
s16 sp1E; s16 sp1E;
if (o->oTimer > 20) { if (o->oTimer > 20) {
if (o->oMoveFlags & 0x00000003) { if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
if (o->oGravity < -4.0f) { if (o->oGravity < -4.0f) {
eyerok_hand_pound_ground(); eyerok_hand_pound_ground();
o->oGravity = -4.0f; o->oGravity = -4.0f;
@ -418,7 +418,7 @@ static void eyerok_hand_act_smash(void) {
} }
static void eyerok_hand_act_fist_push(void) { static void eyerok_hand_act_fist_push(void) {
if (o->oTimer > 5 && (o->oPosZ - gMarioObject->oPosZ > 0.0f || (o->oMoveFlags & 0x00000400))) { if (o->oTimer > 5 && (o->oPosZ - gMarioObject->oPosZ > 0.0f || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE))) {
o->oAction = EYEROK_HAND_ACT_FIST_SWEEP; o->oAction = EYEROK_HAND_ACT_FIST_SWEEP;
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
@ -433,7 +433,7 @@ static void eyerok_hand_act_fist_push(void) {
} }
static void eyerok_hand_act_fist_sweep(void) { static void eyerok_hand_act_fist_sweep(void) {
if (o->oPosZ - o->parentObj->oPosZ < 1000.0f || (o->oMoveFlags & 0x400)) { if (o->oPosZ - o->parentObj->oPosZ < 1000.0f || (o->oMoveFlags & OBJ_MOVE_HIT_EDGE)) {
o->oAction = EYEROK_HAND_ACT_RETREAT; o->oAction = EYEROK_HAND_ACT_RETREAT;
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
} else { } else {
@ -470,7 +470,7 @@ static void eyerok_hand_act_double_pound(void) {
o->oAction = EYEROK_HAND_ACT_RETREAT; o->oAction = EYEROK_HAND_ACT_RETREAT;
o->parentObj->oEyerokBossUnk1AC = o->oBehParams2ndByte; o->parentObj->oEyerokBossUnk1AC = o->oBehParams2ndByte;
} else if (o->parentObj->oEyerokBossActiveHand == o->oBehParams2ndByte) { } else if (o->parentObj->oEyerokBossActiveHand == o->oBehParams2ndByte) {
if (o->oMoveFlags & 0x00000003) { if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
if (o->oGravity < -15.0f) { if (o->oGravity < -15.0f) {
o->parentObj->oEyerokBossActiveHand = 0; o->parentObj->oEyerokBossActiveHand = 0;
eyerok_hand_pound_ground(); eyerok_hand_pound_ground();

View File

@ -1,7 +1,7 @@
static void fire_spitter_act_idle(void) { static void fire_spitter_act_idle(void) {
approach_f32_ptr(&o->header.gfx.scale[0], 0.2f, 0.002f); approach_f32_ptr(&o->header.gfx.scale[0], 0.2f, 0.002f);
if (o->oTimer > 150 && o->oDistanceToMario < 800.0f && !(o->oMoveFlags & 0x00000078)) { if (o->oTimer > 150 && o->oDistanceToMario < 800.0f && !(o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER)) {
o->oAction = FIRE_SPITTER_ACT_SPIT_FIRE; o->oAction = FIRE_SPITTER_ACT_SPIT_FIRE;
o->oFireSpitterScaleVel = 0.05f; o->oFireSpitterScaleVel = 0.05f;
} }

View File

@ -34,7 +34,7 @@ void bhv_small_piranha_flame_loop(void) {
obj_check_attacks(&sPiranhaPlantFireHitbox, o->oAction); obj_check_attacks(&sPiranhaPlantFireHitbox, o->oAction);
o->oSmallPiranhaFlameUnk104 += o->oSmallPiranhaFlameUnkF4; o->oSmallPiranhaFlameUnk104 += o->oSmallPiranhaFlameUnkF4;
if (o->oSmallPiranhaFlameUnk104 > 1500.0f || (o->oMoveFlags & 0x00000278)) { if (o->oSmallPiranhaFlameUnk104 > 1500.0f || (o->oMoveFlags & (OBJ_MOVE_HIT_WALL | OBJ_MOVE_MASK_IN_WATER))) {
obj_die_if_health_non_positive(); obj_die_if_health_non_positive();
} }
} }

View File

@ -118,7 +118,7 @@ void bhv_flying_bookend_loop(void) {
} }
obj_check_attacks(&sFlyingBookendHitbox, -1); obj_check_attacks(&sFlyingBookendHitbox, -1);
if (o->oAction == -1 || (o->oMoveFlags & 0x00000203)) { if (o->oAction == -1 || (o->oMoveFlags & (OBJ_MOVE_MASK_ON_GROUND | OBJ_MOVE_HIT_WALL))) {
o->oNumLootCoins = 0; o->oNumLootCoins = 0;
obj_die_if_health_non_positive(); obj_die_if_health_non_positive();
} }

View File

@ -118,7 +118,7 @@ void haunted_chair_act_1(void) {
} }
o->oFaceAngleYaw += 0x2710; o->oFaceAngleYaw += 0x2710;
} }
} else if (o->oMoveFlags & 0x00000203) { } else if (o->oMoveFlags & (OBJ_MOVE_MASK_ON_GROUND | OBJ_MOVE_HIT_WALL)) {
obj_die_if_health_non_positive(); obj_die_if_health_non_positive();
} }
} }

View File

@ -89,13 +89,13 @@ void heave_ho_move(void) {
cur_obj_update_floor_and_walls(); cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sHeaveHoActions); cur_obj_call_action_function(sHeaveHoActions);
cur_obj_move_standard(-78); cur_obj_move_standard(-78);
if (o->oMoveFlags & (0x40 | 0x20 | 0x10 | 0x8)) if (o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER)
o->oGraphYOffset = -15.0f; o->oGraphYOffset = -15.0f;
else else
o->oGraphYOffset = 0.0f; o->oGraphYOffset = 0.0f;
if (o->oForwardVel > 3.0f) if (o->oForwardVel > 3.0f)
cur_obj_play_sound_1(SOUND_AIR_HEAVEHO_MOVE); cur_obj_play_sound_1(SOUND_AIR_HEAVEHO_MOVE);
if (o->oAction != 0 && o->oMoveFlags & (0x40 | 0x20 | 0x10 | 0x8)) if (o->oAction != 0 && o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER)
o->oAction = 0; o->oAction = 0;
if (o->oInteractStatus & INT_STATUS_GRABBED_MARIO) { if (o->oInteractStatus & INT_STATUS_GRABBED_MARIO) {
o->oInteractStatus = 0; o->oInteractStatus = 0;

View File

@ -4,7 +4,7 @@ void bhv_horizontal_grindel_init(void) {
} }
void bhv_horizontal_grindel_update(void) { void bhv_horizontal_grindel_update(void) {
if (o->oMoveFlags & 0x00000003) { if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
if (!o->oHorizontalGrindelOnGround) { if (!o->oHorizontalGrindelOnGround) {
cur_obj_play_sound_2(SOUND_OBJ_THWOMP); cur_obj_play_sound_2(SOUND_OBJ_THWOMP);
o->oHorizontalGrindelOnGround = TRUE; o->oHorizontalGrindelOnGround = TRUE;

View File

@ -20,14 +20,14 @@ void jumping_box_act_0(void) {
o->oVelY = random_float() * 5.0f + 15.0f; o->oVelY = random_float() * 5.0f + 15.0f;
o->oSubAction++; o->oSubAction++;
} }
} else if (o->oMoveFlags & 2) { } else if (o->oMoveFlags & OBJ_MOVE_ON_GROUND) {
o->oSubAction = 0; o->oSubAction = 0;
o->oJumpingBoxUnkF8 = random_float() * 60.0f + 30.0f; o->oJumpingBoxUnkF8 = random_float() * 60.0f + 30.0f;
} }
} }
void jumping_box_act_1(void) { void jumping_box_act_1(void) {
if (o->oMoveFlags & (0x200 | 0x40 | 0x20 | 0x10 | 0x8 | 0x1)) { if (o->oMoveFlags & (OBJ_MOVE_HIT_WALL | OBJ_MOVE_MASK_IN_WATER | OBJ_MOVE_LANDED)) {
obj_mark_for_deletion(o); obj_mark_for_deletion(o);
spawn_mist_particles(); spawn_mist_particles();
} }

View File

@ -8,7 +8,7 @@ Gfx *geo_update_held_mario_pos(s32 run, UNUSED struct GraphNode *node, Mat4 mtx)
if (run == TRUE) { if (run == TRUE) {
sp1C = (struct Object *) gCurGraphNodeObject; sp1C = (struct Object *) gCurGraphNodeObject;
if (sp1C->prevObj != NULL) { if (sp1C->prevObj != NULL) {
create_transformation_from_matrices(sp20, mtx, gCurGraphNodeCamera->matrixPtr); create_transformation_from_matrices(sp20, mtx, *gCurGraphNodeCamera->matrixPtr);
obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj); obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj);
obj_set_gfx_pos_from_pos(sp1C->prevObj); obj_set_gfx_pos_from_pos(sp1C->prevObj);
} }
@ -194,7 +194,7 @@ void king_bobomb_act_8(void) {
void king_bobomb_act_4(void) { // bobomb been thrown void king_bobomb_act_4(void) { // bobomb been thrown
if (o->oPosY - o->oHomeY > -100.0f) { // not thrown off hill if (o->oPosY - o->oHomeY > -100.0f) { // not thrown off hill
if (o->oMoveFlags & 1) { if (o->oMoveFlags & OBJ_MOVE_LANDED) {
o->oHealth--; o->oHealth--;
o->oForwardVel = 0; o->oForwardVel = 0;
o->oVelY = 0; o->oVelY = 0;
@ -206,11 +206,11 @@ void king_bobomb_act_4(void) { // bobomb been thrown
} }
} else { } else {
if (o->oSubAction == 0) { if (o->oSubAction == 0) {
if (o->oMoveFlags & 2) { if (o->oMoveFlags & OBJ_MOVE_ON_GROUND) {
o->oForwardVel = 0; o->oForwardVel = 0;
o->oVelY = 0; o->oVelY = 0;
o->oSubAction++; o->oSubAction++;
} else if (o->oMoveFlags & 1) } else if (o->oMoveFlags & OBJ_MOVE_LANDED)
cur_obj_play_sound_2(SOUND_OBJ_KING_BOBOMB); cur_obj_play_sound_2(SOUND_OBJ_KING_BOBOMB);
} else { } else {
if (cur_obj_init_animation_and_check_if_near_end(10)) if (cur_obj_init_animation_and_check_if_near_end(10))

View File

@ -6,6 +6,8 @@ void bhv_volcano_flames_loop(void) {
o->oPosX += o->oVelX; o->oPosX += o->oVelX;
o->oPosZ += o->oVelZ; o->oPosZ += o->oVelZ;
cur_obj_move_y(-4.0f, -0.7f, 2.0f); cur_obj_move_y(-4.0f, -0.7f, 2.0f);
if (o->oMoveFlags & 0x33)
if (o->oMoveFlags & (OBJ_MOVE_MASK_ON_GROUND | OBJ_MOVE_AT_WATER_SURFACE
| OBJ_MOVE_UNDERWATER_OFF_GROUND))
obj_mark_for_deletion(o); obj_mark_for_deletion(o);
} }

View File

@ -1,10 +1,16 @@
// manta_ray.c.inc // manta_ray.c.inc
// TODO: these are likely Waypoint structs static Trajectory sMantaRayTraj[] = {
static s16 D_803316A8[] = { 0x0000, 0xEE6C, 0xFA9C, 0xFFD8, 0x0001, 0xEFE8, 0xF740, 0x02E4, 0x0002, TRAJECTORY_POS(0, /*pos*/ -4500, -1380, -40),
0xF330, 0xF3F8, 0x0410, 0x0003, 0xF740, 0xF308, 0x02D0, 0x0004, 0xF8D0, TRAJECTORY_POS(1, /*pos*/ -4120, -2240, 740),
0xF3BC, 0xFEE8, 0x0005, 0xF6F0, 0xF650, 0xFBB4, 0x0006, 0xF36C, 0xF9C0, TRAJECTORY_POS(2, /*pos*/ -3280, -3080, 1040),
0xFAB0, 0x0007, 0xEFAC, 0xFC04, 0xFBF0, 0xFFFF, 0x0000 }; TRAJECTORY_POS(3, /*pos*/ -2240, -3320, 720),
TRAJECTORY_POS(4, /*pos*/ -1840, -3140, -280),
TRAJECTORY_POS(5, /*pos*/ -2320, -2480, -1100),
TRAJECTORY_POS(6, /*pos*/ -3220, -1600, -1360),
TRAJECTORY_POS(7, /*pos*/ -4180, -1020, -1040),
TRAJECTORY_END(),
};
static struct ObjectHitbox sMantaRayHitbox = { static struct ObjectHitbox sMantaRayHitbox = {
/* interactType: */ INTERACT_DAMAGE, /* interactType: */ INTERACT_DAMAGE,
@ -31,7 +37,7 @@ void manta_ray_move(void) {
s32 sp18; s32 sp18;
sp1E = o->header.gfx.unk38.animFrame; sp1E = o->header.gfx.unk38.animFrame;
gCurrentObject->oPathedWaypointsS16 = &D_803316A8; gCurrentObject->oPathedStartWaypoint = (struct Waypoint *) sMantaRayTraj;
sp18 = cur_obj_follow_path(sp18); sp18 = cur_obj_follow_path(sp18);
o->oMantaUnkF8 = o->oPathedTargetYaw; o->oMantaUnkF8 = o->oPathedTargetYaw;
o->oMantaUnkF4 = o->oPathedTargetPitch; o->oMantaUnkF4 = o->oPathedTargetPitch;

View File

@ -1,3 +1,4 @@
// Mr. Blizzard hitbox
struct ObjectHitbox sMrBlizzardHitbox = { struct ObjectHitbox sMrBlizzardHitbox = {
/* interactType: */ INTERACT_MR_BLIZZARD, /* interactType: */ INTERACT_MR_BLIZZARD,
/* downOffset: */ 24, /* downOffset: */ 24,
@ -10,7 +11,9 @@ struct ObjectHitbox sMrBlizzardHitbox = {
/* hurtboxHeight: */ 170, /* hurtboxHeight: */ 170,
}; };
void mr_blizzard_spawn_white_particles(s8 count, s8 offsetY, s8 forwardVelBase, s8 velYBase, s8 sizeBase) { // Mr. Blizzard particle spawner.
void mr_blizzard_spawn_white_particles(s8 count, s8 offsetY, s8 forwardVelBase, s8 velYBase,
s8 sizeBase) {
static struct SpawnParticlesInfo D_80331A00 = { static struct SpawnParticlesInfo D_80331A00 = {
/* behParam: */ 0, /* behParam: */ 0,
/* count: */ 6, /* count: */ 6,
@ -34,42 +37,66 @@ void mr_blizzard_spawn_white_particles(s8 count, s8 offsetY, s8 forwardVelBase,
cur_obj_spawn_particles(&D_80331A00); cur_obj_spawn_particles(&D_80331A00);
} }
/**
* Mr. Blizzard initialization function.
*/
void bhv_mr_blizzard_init(void) { void bhv_mr_blizzard_init(void) {
if (o->oBehParams2ndByte == 1) { if (o->oBehParams2ndByte == MR_BLIZZARD_STYPE_JUMPING) {
o->oAction = 7; // Jumping Mr. Blizzard.
o->oAction = MR_BLIZZARD_ACT_JUMP;
o->oMrBlizzardGraphYOffset = 24.0f; o->oMrBlizzardGraphYOffset = 24.0f;
o->oMrBlizzardTargetMoveYaw = o->oMoveAngleYaw; o->oMrBlizzardTargetMoveYaw = o->oMoveAngleYaw;
} else { } else {
if (o->oBehParams2ndByte != 0) { if (o->oBehParams2ndByte != MR_BLIZZARD_STYPE_NO_CAP) {
// Cap wearing Mr. Blizzard from SL.
if (save_file_get_flags() & SAVE_FLAG_CAP_ON_MR_BLIZZARD) { if (save_file_get_flags() & SAVE_FLAG_CAP_ON_MR_BLIZZARD) {
o->oAnimState = 1; o->oAnimState = 1;
} }
} }
// Mr. Blizzard starts under the floor holding nothing.
o->oMrBlizzardGraphYOffset = -200.0f; o->oMrBlizzardGraphYOffset = -200.0f;
o->oMrBlizzardHeldObj = NULL; o->oMrBlizzardHeldObj = NULL;
} }
} }
static void mr_blizzard_act_0(void) { /**
* Handler for spawning Mr. Blizzard's snowball.
*/
static void mr_blizzard_act_spawn_snowball(void) {
// If Mr. Blizzard is not holding a snowball, and the animation reaches 5 frames
// spawn the Mr. Blizzard snowball.
if (o->oMrBlizzardHeldObj == NULL && cur_obj_init_anim_check_frame(0, 5)) { if (o->oMrBlizzardHeldObj == NULL && cur_obj_init_anim_check_frame(0, 5)) {
o->oMrBlizzardHeldObj = spawn_object_relative(0, -70, (s32)(o->oMrBlizzardGraphYOffset + 153.0f), 0, o, o->oMrBlizzardHeldObj =
spawn_object_relative(0, -70, (s32)(o->oMrBlizzardGraphYOffset + 153.0f), 0, o,
MODEL_WHITE_PARTICLE, bhvMrBlizzardSnowball); MODEL_WHITE_PARTICLE, bhvMrBlizzardSnowball);
} else if (cur_obj_check_anim_frame(10)) { } else if (cur_obj_check_anim_frame(10)) {
o->prevObj = o->oMrBlizzardHeldObj; o->prevObj = o->oMrBlizzardHeldObj;
} else if (cur_obj_check_if_near_animation_end()) { } else if (cur_obj_check_if_near_animation_end()) {
// If Mr. Blizzard's graphical position is below the ground, move to hide and unhide action.
// Otherwise, move to rotate action.
if (o->oMrBlizzardGraphYOffset < 0.0f) { if (o->oMrBlizzardGraphYOffset < 0.0f) {
o->oAction = 1; o->oAction = MR_BLIZZARD_ACT_HIDE_UNHIDE;
} else { } else {
o->oAction = 3; o->oAction = MR_BLIZZARD_ACT_ROTATE;
} }
} }
} }
static void mr_blizzard_act_1(void) { /**
* Handler for Mario entering or exiting Mr. Blizzard's range.
*/
static void mr_blizzard_act_hide_unhide(void) {
if (o->oDistanceToMario < 1000.0f) { if (o->oDistanceToMario < 1000.0f) {
// If Mario is in range, move to rising action, make Mr. Blizzard visible,
// make Mr. Blizzard tangible, and initialize GraphYVel.
cur_obj_play_sound_2(SOUND_OBJ_SNOW_SAND2); cur_obj_play_sound_2(SOUND_OBJ_SNOW_SAND2);
o->oAction = 2; o->oAction = MR_BLIZZARD_ACT_RISE_FROM_GROUND;
o->oMoveAngleYaw = o->oAngleToMario; o->oMoveAngleYaw = o->oAngleToMario;
o->oMrBlizzardGraphYVel = 42.0f; o->oMrBlizzardGraphYVel = 42.0f;
@ -77,45 +104,69 @@ static void mr_blizzard_act_1(void) {
cur_obj_unhide(); cur_obj_unhide();
cur_obj_become_tangible(); cur_obj_become_tangible();
} else { } else {
// If Mario is not in range, make Mr. Blizzard invisible.
cur_obj_hide(); cur_obj_hide();
} }
} }
static void mr_blizzard_act_2(void) { /**
* Handler for Mr. Blizzard popping up out of the ground.
*/
static void mr_blizzard_act_rise_from_ground(void) {
// If the timer is not 0, decrement by 1 until it reaches 0.
if (o->oMrBlizzardTimer != 0) { if (o->oMrBlizzardTimer != 0) {
o->oMrBlizzardTimer -= 1; o->oMrBlizzardTimer -= 1;
} else if ((o->oMrBlizzardGraphYOffset += o->oMrBlizzardGraphYVel) > 24.0f) { } else if ((o->oMrBlizzardGraphYOffset += o->oMrBlizzardGraphYVel) > 24.0f) {
// Increments GraphYOffset by GraphYVel until it is greater than 24,
// moving Mr. Blizzard's graphical position upward each frame.
// Then, Mr. Blizzard's Y-position is increased by the value of
// GraphYOffset minus 24, GraphYOffset is
// set to 24, VelY is set to GraphYVel and action is moved to rotate.
o->oPosY += o->oMrBlizzardGraphYOffset - 24.0f; o->oPosY += o->oMrBlizzardGraphYOffset - 24.0f;
o->oMrBlizzardGraphYOffset = 24.0f; o->oMrBlizzardGraphYOffset = 24.0f;
mr_blizzard_spawn_white_particles(8, -20, 20, 15, 10); mr_blizzard_spawn_white_particles(8, -20, 20, 15, 10);
o->oAction = 3; o->oAction = MR_BLIZZARD_ACT_ROTATE;
o->oVelY = o->oMrBlizzardGraphYVel; o->oVelY = o->oMrBlizzardGraphYVel;
} else if ((o->oMrBlizzardGraphYVel -= 10.0f) < 0.0f) { } else if ((o->oMrBlizzardGraphYVel -= 10.0f) < 0.0f) {
// Decrement GraphYOffset until it is less than 0.
// When it is less than 0, set it to 47 and set timer to 5.
o->oMrBlizzardGraphYVel = 47.0f; o->oMrBlizzardGraphYVel = 47.0f;
o->oMrBlizzardTimer = 5; o->oMrBlizzardTimer = 5;
} }
} }
static void mr_blizzard_act_3(void) { /**
s16 val06; * Handler for Mr. Blizzard's rotation.
f32 val00; */
if (o->oMoveFlags & 0x00000003) { static void mr_blizzard_act_rotate(void) {
s16 angleDiff;
f32 prevDizziness;
// While Mr. Blizzard is on the ground, rotate toward Mario at
// 8.4375 degrees/frame.
if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x600); cur_obj_rotate_yaw_toward(o->oAngleToMario, 0x600);
val06 = o->oAngleToMario - o->oMoveAngleYaw; // Modify the ChangeInDizziness based on Mario's angle to Mr. Blizzard.
if (val06 != 0) { angleDiff = o->oAngleToMario - o->oMoveAngleYaw;
if (val06 < 0) { if (angleDiff != 0) {
if (angleDiff < 0) {
o->oMrBlizzardChangeInDizziness -= 8.0f; o->oMrBlizzardChangeInDizziness -= 8.0f;
} else { } else {
o->oMrBlizzardChangeInDizziness += 8.0f; o->oMrBlizzardChangeInDizziness += 8.0f;
} }
// Incremement Dizziness by value of ChangeInDizziness
o->oMrBlizzardDizziness += o->oMrBlizzardChangeInDizziness; o->oMrBlizzardDizziness += o->oMrBlizzardChangeInDizziness;
} else if (o->oMrBlizzardDizziness != 0.0f) { } else if (o->oMrBlizzardDizziness != 0.0f) {
val00 = o->oMrBlizzardDizziness; prevDizziness = o->oMrBlizzardDizziness;
// Slowly move Dizziness back to 0 by making ChangeInDizziness positive if Dizziness
// is negative, and making ChangeInDizziness negative if Dizziness is positive.
if (o->oMrBlizzardDizziness < 0.0f) { if (o->oMrBlizzardDizziness < 0.0f) {
approach_f32_ptr(&o->oMrBlizzardChangeInDizziness, 1000.0f, 80.0f); approach_f32_ptr(&o->oMrBlizzardChangeInDizziness, 1000.0f, 80.0f);
} else { } else {
@ -123,43 +174,55 @@ static void mr_blizzard_act_3(void) {
} }
o->oMrBlizzardDizziness += o->oMrBlizzardChangeInDizziness; o->oMrBlizzardDizziness += o->oMrBlizzardChangeInDizziness;
if (val00 * o->oMrBlizzardDizziness < 0.0f) { // If prevDizziness has a different sign than Dizziness,
// set Dizziness and ChangeInDizziness to 0.
if (prevDizziness * o->oMrBlizzardDizziness < 0.0f) {
o->oMrBlizzardDizziness = o->oMrBlizzardChangeInDizziness = 0.0f; o->oMrBlizzardDizziness = o->oMrBlizzardChangeInDizziness = 0.0f;
} }
} }
// If Dizziness is not 0 and Mr. Blizzard's FaceRollAngle has a magnitude greater than
// 67.5 degrees move to death action, delete the snowball, and make Mr. Blizzard intangible.
if (o->oMrBlizzardDizziness != 0.0f) { if (o->oMrBlizzardDizziness != 0.0f) {
if (absi(o->oFaceAngleRoll) > 0x3000) { if (absi(o->oFaceAngleRoll) > 0x3000) {
o->oAction = 6; o->oAction = MR_BLIZZARD_ACT_DEATH;
o->prevObj = o->oMrBlizzardHeldObj = NULL; o->prevObj = o->oMrBlizzardHeldObj = NULL;
cur_obj_become_intangible(); cur_obj_become_intangible();
} }
// If Mario gets too far away, move to burrow action and delete the snowball.
} else if (o->oDistanceToMario > 1500.0f) { } else if (o->oDistanceToMario > 1500.0f) {
o->oAction = 5; o->oAction = MR_BLIZZARD_ACT_BURROW;
o->oMrBlizzardChangeInDizziness = 300.0f; o->oMrBlizzardChangeInDizziness = 300.0f;
o->prevObj = o->oMrBlizzardHeldObj = NULL; o->prevObj = o->oMrBlizzardHeldObj = NULL;
// After 60 frames, if Mario is within 11.25 degrees of Mr. Blizzard, throw snowball action.
} else if (o->oTimer > 60 && abs_angle_diff(o->oAngleToMario, o->oMoveAngleYaw) < 0x800) { } else if (o->oTimer > 60 && abs_angle_diff(o->oAngleToMario, o->oMoveAngleYaw) < 0x800) {
o->oAction = 4; o->oAction = MR_BLIZZARD_ACT_THROW_SNOWBALL;
} }
} }
} }
static void mr_blizzard_act_6(void) { /**
struct Object *val04; * Handler for Mr. Blizzard's death.
*/
static void mr_blizzard_act_death(void) {
struct Object *cap;
if (clamp_f32(&o->oMrBlizzardDizziness, -0x4000, 0x4000)) { if (clamp_f32(&o->oMrBlizzardDizziness, -0x4000, 0x4000)) {
if (o->oMrBlizzardChangeInDizziness != 0.0f) { if (o->oMrBlizzardChangeInDizziness != 0.0f) {
cur_obj_play_sound_2(SOUND_OBJ_SNOW_SAND1); cur_obj_play_sound_2(SOUND_OBJ_SNOW_SAND1);
// If Mr. Blizzard is wearing Mario's cap, clear
// the save flag and spawn Mario's cap.
if (o->oAnimState) { if (o->oAnimState) {
save_file_clear_flags(SAVE_FLAG_CAP_ON_MR_BLIZZARD); save_file_clear_flags(SAVE_FLAG_CAP_ON_MR_BLIZZARD);
val04 = spawn_object_relative(0, 5, 105, 0, o, MODEL_MARIOS_CAP, bhvNormalCap); cap = spawn_object_relative(0, 5, 105, 0, o, MODEL_MARIOS_CAP, bhvNormalCap);
if (val04 != NULL) { if (cap != NULL) {
val04->oMoveAngleYaw = cap->oMoveAngleYaw = o->oFaceAngleYaw + (o->oFaceAngleRoll < 0 ? 0x4000 : -0x4000);
o->oFaceAngleYaw + (o->oFaceAngleRoll < 0 ? 0x4000 : -0x4000); cap->oForwardVel = 10.0f;
val04->oForwardVel = 10.0f;
} }
// Mr. Blizzard no longer spawns with Mario's cap on.
o->oAnimState = 0; o->oAnimState = 0;
} }
@ -175,6 +238,8 @@ static void mr_blizzard_act_6(void) {
o->oMrBlizzardDizziness += o->oMrBlizzardChangeInDizziness; o->oMrBlizzardDizziness += o->oMrBlizzardChangeInDizziness;
} }
// After 30 frames, play the defeat sound once and scale Mr. Blizzard down to 0
// at .03 units per frame. Spawn coins and set the coins to not respawn.
if (o->oTimer >= 30) { if (o->oTimer >= 30) {
if (o->oTimer == 30) { if (o->oTimer == 30) {
cur_obj_play_sound_2(SOUND_OBJ_ENEMY_DEFEAT_SHRINK); cur_obj_play_sound_2(SOUND_OBJ_ENEMY_DEFEAT_SHRINK);
@ -188,10 +253,11 @@ static void mr_blizzard_act_6(void) {
set_object_respawn_info_bits(o, 1); set_object_respawn_info_bits(o, 1);
} }
} }
// Reset Mr. Blizzard if Mario leaves its radius.
} else if (o->oDistanceToMario > 1000.0f) { } else if (o->oDistanceToMario > 1000.0f) {
cur_obj_init_animation_with_sound(1); cur_obj_init_animation_with_sound(1);
o->oAction = 0; o->oAction = MR_BLIZZARD_ACT_SPAWN_SNOWBALL;
o->oMrBlizzardScale = 1.0f; o->oMrBlizzardScale = 1.0f;
o->oMrBlizzardGraphYOffset = -200.0f; o->oMrBlizzardGraphYOffset = -200.0f;
o->oFaceAngleRoll = 0; o->oFaceAngleRoll = 0;
@ -200,16 +266,29 @@ static void mr_blizzard_act_6(void) {
} }
} }
static void mr_blizzard_act_4(void) { /**
* Handler for snowball throw.
*/
static void mr_blizzard_act_throw_snowball(void) {
// Play a sound and set HeldObj to NULL. Then set action to 0.
if (cur_obj_init_anim_check_frame(1, 7)) { if (cur_obj_init_anim_check_frame(1, 7)) {
cur_obj_play_sound_2(SOUND_OBJ2_SCUTTLEBUG_ALERT); cur_obj_play_sound_2(SOUND_OBJ2_SCUTTLEBUG_ALERT);
o->prevObj = o->oMrBlizzardHeldObj = NULL; o->prevObj = o->oMrBlizzardHeldObj = NULL;
} else if (cur_obj_check_if_near_animation_end()) { } else if (cur_obj_check_if_near_animation_end()) {
o->oAction = 0; o->oAction = MR_BLIZZARD_ACT_SPAWN_SNOWBALL;
} }
} }
static void mr_blizzard_act_5(void) { /**
* Mr. Blizzard's going back into the ground function.
*/
static void mr_blizzard_act_burrow(void) {
// Reset Dizziness by increasing ChangeInDizziness if
// dizziness is negative and decreasing it if Dizziness
o->oMrBlizzardDizziness += o->oMrBlizzardChangeInDizziness; o->oMrBlizzardDizziness += o->oMrBlizzardChangeInDizziness;
if (o->oMrBlizzardDizziness < 0.0f) { if (o->oMrBlizzardDizziness < 0.0f) {
@ -217,32 +296,45 @@ static void mr_blizzard_act_5(void) {
} else { } else {
o->oMrBlizzardChangeInDizziness -= 150.0f; o->oMrBlizzardChangeInDizziness -= 150.0f;
} }
// Put Mr. Blizzard's graphical position back below ground
// then move to action 0.
if (approach_f32_ptr(&o->oMrBlizzardGraphYOffset, -200.0f, 4.0f)) { if (approach_f32_ptr(&o->oMrBlizzardGraphYOffset, -200.0f, 4.0f)) {
o->oAction = 0; o->oAction = MR_BLIZZARD_ACT_SPAWN_SNOWBALL;
cur_obj_init_animation_with_sound(1); cur_obj_init_animation_with_sound(1);
} }
} }
static void mr_blizzard_act_7(void) { /**
* Jumping Mr. Blizzard handler function.
*/
static void mr_blizzard_act_jump(void) {
if (o->oMrBlizzardTimer != 0) { if (o->oMrBlizzardTimer != 0) {
cur_obj_rotate_yaw_toward(o->oMrBlizzardTargetMoveYaw, 3400); cur_obj_rotate_yaw_toward(o->oMrBlizzardTargetMoveYaw, 3400);
if (--o->oMrBlizzardTimer == 0) { if (--o->oMrBlizzardTimer == 0) {
cur_obj_play_sound_2(SOUND_OBJ_MR_BLIZZARD_ALERT); cur_obj_play_sound_2(SOUND_OBJ_MR_BLIZZARD_ALERT);
// If Mr. Blizzard is more than 700 units from its home, change its target yaw
// by 180 degrees, jump in the air, set distance from home to 0.
if (o->oMrBlizzardDistFromHome > 700) { if (o->oMrBlizzardDistFromHome > 700) {
o->oMrBlizzardTargetMoveYaw += 0x8000; o->oMrBlizzardTargetMoveYaw += 0x8000;
o->oVelY = 25.0f; o->oVelY = 25.0f;
o->oMrBlizzardTimer = 30; o->oMrBlizzardTimer = 30;
o->oMrBlizzardDistFromHome = 0; o->oMrBlizzardDistFromHome = 0;
// Jump forward.
} else { } else {
o->oForwardVel = 10.0f; o->oForwardVel = 10.0f;
o->oVelY = 50.0f; o->oVelY = 50.0f;
o->oMoveFlags = 0; o->oMoveFlags = 0;
} }
} }
} else if (o->oMoveFlags & 0x00000003) { } else if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
// When Mr. Blizzard lands, play the landing sound, stop Mr. Blizzard, and
// set its timer to 15. If Mr. Blizzard's DistFromHome is not 0,
// set DistFromHome to its current distance from its home.
// Otherwise, set DistFromHome to 700.
cur_obj_play_sound_2(SOUND_OBJ_SNOW_SAND1); cur_obj_play_sound_2(SOUND_OBJ_SNOW_SAND1);
if (o->oMrBlizzardDistFromHome != 0) { if (o->oMrBlizzardDistFromHome != 0) {
o->oMrBlizzardDistFromHome = (s32) cur_obj_lateral_dist_to_home(); o->oMrBlizzardDistFromHome = (s32) cur_obj_lateral_dist_to_home();
@ -255,37 +347,45 @@ static void mr_blizzard_act_7(void) {
} }
} }
/**
* Mr. Blizzard update function.
*/
void bhv_mr_blizzard_update(void) { void bhv_mr_blizzard_update(void) {
cur_obj_update_floor_and_walls(); cur_obj_update_floor_and_walls();
// Behavior loop
switch (o->oAction) { switch (o->oAction) {
case 0: case MR_BLIZZARD_ACT_SPAWN_SNOWBALL:
mr_blizzard_act_0(); mr_blizzard_act_spawn_snowball();
break; break;
case 1: case MR_BLIZZARD_ACT_HIDE_UNHIDE:
mr_blizzard_act_1(); mr_blizzard_act_hide_unhide();
break; break;
case 2: case MR_BLIZZARD_ACT_RISE_FROM_GROUND:
mr_blizzard_act_2(); mr_blizzard_act_rise_from_ground();
break; break;
case 3: case MR_BLIZZARD_ACT_ROTATE:
mr_blizzard_act_3(); mr_blizzard_act_rotate();
break; break;
case 4: case MR_BLIZZARD_ACT_THROW_SNOWBALL:
mr_blizzard_act_4(); mr_blizzard_act_throw_snowball();
break; break;
case 5: case MR_BLIZZARD_ACT_BURROW:
mr_blizzard_act_5(); mr_blizzard_act_burrow();
break; break;
case 6: case MR_BLIZZARD_ACT_DEATH:
mr_blizzard_act_6(); mr_blizzard_act_death();
break; break;
case 7: case MR_BLIZZARD_ACT_JUMP:
mr_blizzard_act_7(); mr_blizzard_act_jump();
break; break;
} }
// Set roll angle equal to dizziness, making Mr. Blizzard
// slowly fall over.
o->oFaceAngleRoll = o->oMrBlizzardDizziness; o->oFaceAngleRoll = o->oMrBlizzardDizziness;
// Mr. Blizzard's graphical position changes by changing the Y offset.
o->oGraphYOffset = o->oMrBlizzardGraphYOffset + absf(20.0f * sins(o->oFaceAngleRoll)) o->oGraphYOffset = o->oMrBlizzardGraphYOffset + absf(20.0f * sins(o->oFaceAngleRoll))
- 40.0f * (1.0f - o->oMrBlizzardScale); - 40.0f * (1.0f - o->oMrBlizzardScale);
@ -294,6 +394,10 @@ void bhv_mr_blizzard_update(void) {
obj_check_attacks(&sMrBlizzardHitbox, o->oAction); obj_check_attacks(&sMrBlizzardHitbox, o->oAction);
} }
/**
* Snowball initial takeoff position handler.
*/
static void mr_blizzard_snowball_act_0(void) { static void mr_blizzard_snowball_act_0(void) {
cur_obj_move_using_fvel_and_gravity(); cur_obj_move_using_fvel_and_gravity();
if (o->parentObj->prevObj == o) { if (o->parentObj->prevObj == o) {
@ -303,26 +407,31 @@ static void mr_blizzard_snowball_act_0(void) {
} }
} }
/**
* Snowball launching action.
*/
static void mr_blizzard_snowball_act_1(void) { static void mr_blizzard_snowball_act_1(void) {
f32 val04; f32 marioDist;
if (o->parentObj->prevObj == NULL) { if (o->parentObj->prevObj == NULL) {
if (o->parentObj->oAction == 4) { if (o->parentObj->oAction == MR_BLIZZARD_ACT_THROW_SNOWBALL) {
val04 = o->oDistanceToMario; marioDist = o->oDistanceToMario;
if (val04 > 800.0f) { if (marioDist > 800.0f) {
val04 = 800.0f; marioDist = 800.0f;
} }
o->oMoveAngleYaw = (s32)(o->parentObj->oMoveAngleYaw + 4000 - val04 * 4.0f); // Launch the snowball relative to Mario's distance from the snowball.
o->oMoveAngleYaw = (s32)(o->parentObj->oMoveAngleYaw + 4000 - marioDist * 4.0f);
o->oForwardVel = 40.0f; o->oForwardVel = 40.0f;
o->oVelY = -20.0f + val04 * 0.075f; o->oVelY = -20.0f + marioDist * 0.075f;
} }
o->oAction = 2; o->oAction = 2;
o->oMoveFlags = 0; o->oMoveFlags = 0;
} }
} }
// Snowball hitbox.
struct ObjectHitbox sMrBlizzardSnowballHitbox = { struct ObjectHitbox sMrBlizzardSnowballHitbox = {
/* interactType: */ INTERACT_MR_BLIZZARD, /* interactType: */ INTERACT_MR_BLIZZARD,
/* downOffset: */ 12, /* downOffset: */ 12,
@ -335,11 +444,17 @@ struct ObjectHitbox sMrBlizzardSnowballHitbox = {
/* hurtboxHeight: */ 25, /* hurtboxHeight: */ 25,
}; };
/**
* Snowball collision function.
*/
static void mr_blizzard_snowball_act_2(void) { static void mr_blizzard_snowball_act_2(void) {
// Set snowball to interact with walls, floors, and Mario.
cur_obj_update_floor_and_walls(); cur_obj_update_floor_and_walls();
obj_check_attacks(&sMrBlizzardSnowballHitbox, -1); obj_check_attacks(&sMrBlizzardSnowballHitbox, -1);
if (o->oAction == -1 || o->oMoveFlags & 0x0000000B) { // If snowball collides with the ground, delete snowball.
if (o->oAction == -1 || o->oMoveFlags & (OBJ_MOVE_MASK_ON_GROUND | OBJ_MOVE_ENTERED_WATER)) {
mr_blizzard_spawn_white_particles(6, 0, 5, 10, 3); mr_blizzard_spawn_white_particles(6, 0, 5, 10, 3);
create_sound_spawner(SOUND_GENERAL_MOVING_IN_SAND); create_sound_spawner(SOUND_GENERAL_MOVING_IN_SAND);
obj_mark_for_deletion(o); obj_mark_for_deletion(o);
@ -348,6 +463,10 @@ static void mr_blizzard_snowball_act_2(void) {
cur_obj_move_standard(78); cur_obj_move_standard(78);
} }
/**
* Snowball behavior loop.
*/
void bhv_mr_blizzard_snowball(void) { void bhv_mr_blizzard_snowball(void) {
switch (o->oAction) { switch (o->oAction) {
case 0: case 0:

View File

@ -17,7 +17,7 @@ void mr_i_piranha_particle_act_0(void) {
cur_obj_update_floor_and_walls(); cur_obj_update_floor_and_walls();
if (0x8000 & o->oInteractStatus) if (0x8000 & o->oInteractStatus)
o->oAction = 1; o->oAction = 1;
else if ((o->oTimer >= 101) || (0x200 & o->oMoveFlags) || o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM) { else if ((o->oTimer >= 101) || (o->oMoveFlags & OBJ_MOVE_HIT_WALL) || o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM) {
obj_mark_for_deletion(o); obj_mark_for_deletion(o);
spawn_mist_particles(); spawn_mist_particles();
} }

View File

@ -88,7 +88,7 @@ static void racing_penguin_act_race(void) {
cur_obj_init_animation_with_sound(1); cur_obj_init_animation_with_sound(1);
cur_obj_rotate_yaw_toward(o->oPathedTargetYaw, (s32)(15.0f * o->oForwardVel)); cur_obj_rotate_yaw_toward(o->oPathedTargetYaw, (s32)(15.0f * o->oForwardVel));
if (cur_obj_check_if_at_animation_end() && (o->oMoveFlags & 0x00000003)) { if (cur_obj_check_if_at_animation_end() && (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND)) {
spawn_object_relative_with_scale(0, 0, -100, 0, 4.0f, o, MODEL_SMOKE, bhvWhitePuffSmoke2); spawn_object_relative_with_scale(0, 0, -100, 0, 4.0f, o, MODEL_SMOKE, bhvWhitePuffSmoke2);
} }
} }
@ -104,7 +104,7 @@ static void racing_penguin_act_race(void) {
static void racing_penguin_act_finish_race(void) { static void racing_penguin_act_finish_race(void) {
if (o->oForwardVel != 0.0f) { if (o->oForwardVel != 0.0f) {
if (o->oTimer > 5 && (o->oMoveFlags & 0x00000200)) { if (o->oTimer > 5 && (o->oMoveFlags & OBJ_MOVE_HIT_WALL)) {
cur_obj_play_sound_2(SOUND_OBJ_POUNDING_LOUD); cur_obj_play_sound_2(SOUND_OBJ_POUNDING_LOUD);
set_camera_shake_from_point(SHAKE_POS_SMALL, o->oPosX, o->oPosY, o->oPosZ); set_camera_shake_from_point(SHAKE_POS_SMALL, o->oPosX, o->oPosY, o->oPosZ);
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;

View File

@ -35,9 +35,9 @@ void bhv_scuttlebug_loop(void) {
o->oScuttlebugUnkF8 = 0; o->oScuttlebugUnkF8 = 0;
switch (o->oSubAction) { switch (o->oSubAction) {
case 0: case 0:
if (o->oMoveFlags & 1) if (o->oMoveFlags & OBJ_MOVE_LANDED)
cur_obj_play_sound_2(SOUND_OBJ_GOOMBA_ALERT); cur_obj_play_sound_2(SOUND_OBJ_GOOMBA_ALERT);
if (o->oMoveFlags & 3) { if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
o->oHomeX = o->oPosX; o->oHomeX = o->oPosX;
o->oHomeY = o->oPosY; o->oHomeY = o->oPosY;
o->oHomeZ = o->oPosZ; o->oHomeZ = o->oPosZ;
@ -85,7 +85,7 @@ void bhv_scuttlebug_loop(void) {
break; break;
case 4: case 4:
o->oForwardVel = -10.0f; o->oForwardVel = -10.0f;
if (o->oMoveFlags & 1) { if (o->oMoveFlags & OBJ_MOVE_LANDED) {
o->oSubAction++; o->oSubAction++;
o->oVelY = 0.0f; o->oVelY = 0.0f;
o->oScuttlebugUnkFC = 0; o->oScuttlebugUnkFC = 0;
@ -105,7 +105,7 @@ void bhv_scuttlebug_loop(void) {
else else
sp18 = 3.0f; sp18 = 3.0f;
cur_obj_init_animation_with_accel_and_sound(0, sp18); cur_obj_init_animation_with_accel_and_sound(0, sp18);
if (o->oMoveFlags & 3) if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND)
set_obj_anim_with_accel_and_sound(1, 23, SOUND_OBJ2_SCUTTLEBUG_WALK); set_obj_anim_with_accel_and_sound(1, 23, SOUND_OBJ2_SCUTTLEBUG_WALK);
if (o->parentObj != o) { if (o->parentObj != o) {
if (obj_is_hidden(o)) if (obj_is_hidden(o))

View File

@ -32,7 +32,7 @@ static void skeeter_spawn_waves(void) {
} }
static void skeeter_act_idle(void) { static void skeeter_act_idle(void) {
if (o->oMoveFlags & 0x00000003) { if (o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND) {
cur_obj_init_animation_with_sound(3); cur_obj_init_animation_with_sound(3);
o->oForwardVel = 0.0f; o->oForwardVel = 0.0f;
@ -42,7 +42,7 @@ static void skeeter_act_idle(void) {
} else { } else {
cur_obj_init_animation_with_sound(1); cur_obj_init_animation_with_sound(1);
if (o->oMoveFlags & 0x00000010) { if (o->oMoveFlags & OBJ_MOVE_AT_WATER_SURFACE) {
skeeter_spawn_waves(); skeeter_spawn_waves();
if (o->oTimer > 60 if (o->oTimer > 60
&& obj_smooth_turn(&o->oSkeeterUnk1AC, &o->oMoveAngleYaw, o->oSkeeterTargetAngle, 0.02f, && obj_smooth_turn(&o->oSkeeterUnk1AC, &o->oMoveAngleYaw, o->oSkeeterTargetAngle, 0.02f,
@ -61,13 +61,13 @@ static void skeeter_act_idle(void) {
} }
static void skeeter_act_lunge(void) { static void skeeter_act_lunge(void) {
if (!(o->oMoveFlags & 0x00000010)) { if (!(o->oMoveFlags & OBJ_MOVE_AT_WATER_SURFACE)) {
o->oAction = SKEETER_ACT_IDLE; o->oAction = SKEETER_ACT_IDLE;
} else { } else {
skeeter_spawn_waves(); skeeter_spawn_waves();
cur_obj_init_animation_with_sound(0); cur_obj_init_animation_with_sound(0);
if (o->oMoveFlags & 0x00000200) { if (o->oMoveFlags & OBJ_MOVE_HIT_WALL) {
o->oMoveAngleYaw = cur_obj_reflect_move_angle_off_wall(); o->oMoveAngleYaw = cur_obj_reflect_move_angle_off_wall();
o->oForwardVel *= 0.3f; o->oForwardVel *= 0.3f;
o->oFlags &= ~0x00000008; o->oFlags &= ~0x00000008;
@ -92,7 +92,7 @@ static void skeeter_act_lunge(void) {
static void skeeter_act_walk(void) { static void skeeter_act_walk(void) {
f32 sp24; f32 sp24;
if (!(o->oMoveFlags & 0x00000003)) { if (!(o->oMoveFlags & OBJ_MOVE_MASK_ON_GROUND)) {
o->oAction = SKEETER_ACT_IDLE; o->oAction = SKEETER_ACT_IDLE;
} else { } else {
obj_forward_vel_approach(o->oSkeeterUnkFC, 0.4f); obj_forward_vel_approach(o->oSkeeterUnkFC, 0.4f);

View File

@ -120,7 +120,7 @@ static void triplet_butterfly_act_explode(void) {
obj_check_attacks(&sTripletButterflyExplodeHitbox, -1); obj_check_attacks(&sTripletButterflyExplodeHitbox, -1);
if (o->oAction == -1 || (o->oMoveFlags & 0x00000200) || o->oTimer >= 158) { if (o->oAction == -1 || (o->oMoveFlags & OBJ_MOVE_HIT_WALL) || o->oTimer >= 158) {
o->oPosY += o->oGraphYOffset; o->oPosY += o->oGraphYOffset;
spawn_object(o, MODEL_EXPLOSION, bhvExplosion); spawn_object(o, MODEL_EXPLOSION, bhvExplosion);
obj_mark_for_deletion(o); obj_mark_for_deletion(o);

View File

@ -48,7 +48,7 @@ Gfx *geo_update_projectile_pos_from_parent_copy(s32 run,UNUSED struct GraphNode
obj = (struct Object*)gCurGraphNodeObject; obj = (struct Object*)gCurGraphNodeObject;
if (obj->prevObj != NULL) { if (obj->prevObj != NULL) {
create_transformation_from_matrices(mtx2, mtx, gCurGraphNodeCamera->matrixPtr); create_transformation_from_matrices(mtx2, mtx, *gCurGraphNodeCamera->matrixPtr);
obj_update_pos_from_parent_transformation(mtx2, obj->prevObj); obj_update_pos_from_parent_transformation(mtx2, obj->prevObj);
obj_set_gfx_pos_from_pos(obj->prevObj); obj_set_gfx_pos_from_pos(obj->prevObj);
} }
@ -299,7 +299,8 @@ void ukiki_act_jump(void) {
if (o->oSubAction == 0) { if (o->oSubAction == 0) {
if (o->oTimer == 0) { if (o->oTimer == 0) {
cur_obj_set_y_vel_and_animation(random_float() * 10.0f + 45.0f, UKIKI_ANIM_JUMP); cur_obj_set_y_vel_and_animation(random_float() * 10.0f + 45.0f, UKIKI_ANIM_JUMP);
} else if (o->oMoveFlags & OBJ_MOVE_MASK_NOT_AIR) { } else if (o->oMoveFlags & (OBJ_MOVE_MASK_ON_GROUND | OBJ_MOVE_AT_WATER_SURFACE
| OBJ_MOVE_UNDERWATER_ON_GROUND)) {
o->oSubAction++; o->oSubAction++;
o->oVelY = 0.0f; o->oVelY = 0.0f;
} }
@ -316,22 +317,20 @@ void ukiki_act_jump(void) {
/** /**
* Waypoints that lead from the top of the mountain to the cage. * Waypoints that lead from the top of the mountain to the cage.
*
* TODO: Convert to an array of waypoints, perhaps? -1 is tricky.
*/ */
s16 sCageUkikiPath[] = { static Trajectory sCageUkikiPath[] = {
0, 1011, 2306, -285, TRAJECTORY_POS(0, /*pos*/ 1011, 2306, -285),
0, 1151, 2304, -510, TRAJECTORY_POS(0, /*pos*/ 1151, 2304, -510),
0, 1723, 1861, -964, TRAJECTORY_POS(0, /*pos*/ 1723, 1861, -964),
0, 2082, 1775, -1128, TRAJECTORY_POS(0, /*pos*/ 2082, 1775, -1128),
0, 2489, 1717, -1141, TRAJECTORY_POS(0, /*pos*/ 2489, 1717, -1141),
0, 2662, 1694, -1140, TRAJECTORY_POS(0, /*pos*/ 2662, 1694, -1140),
0, 2902, 1536, -947, TRAJECTORY_POS(0, /*pos*/ 2902, 1536, -947),
0, 2946, 1536, -467, TRAJECTORY_POS(0, /*pos*/ 2946, 1536, -467),
0, 2924, 1536, 72, TRAJECTORY_POS(0, /*pos*/ 2924, 1536, 72),
0, 2908, 1536, 536, TRAJECTORY_POS(0, /*pos*/ 2908, 1536, 536),
0, 2886, 1536, 783, TRAJECTORY_POS(0, /*pos*/ 2886, 1536, 783),
-1, TRAJECTORY_END(),
}; };
/** /**
@ -359,7 +358,7 @@ void ukiki_act_go_to_cage(void) {
case UKIKI_SUB_ACT_CAGE_RUN_TO_CAGE: case UKIKI_SUB_ACT_CAGE_RUN_TO_CAGE:
cur_obj_init_animation_with_sound(UKIKI_ANIM_RUN); cur_obj_init_animation_with_sound(UKIKI_ANIM_RUN);
o->oPathedWaypointsS16 = sCageUkikiPath; o->oPathedStartWaypoint = (struct Waypoint *) sCageUkikiPath;
if (cur_obj_follow_path(0) != PATH_REACHED_END) { if (cur_obj_follow_path(0) != PATH_REACHED_END) {
o->oForwardVel = 10.0f; o->oForwardVel = 10.0f;

View File

@ -122,13 +122,13 @@ void whomp_act_4(void) {
} }
void whomp_act_5(void) { void whomp_act_5(void) {
if (o->oSubAction == 0 && o->oMoveFlags & 1) { if (o->oSubAction == 0 && o->oMoveFlags & OBJ_MOVE_LANDED) {
cur_obj_play_sound_2(SOUND_OBJ_WHOMP_LOWPRIO); cur_obj_play_sound_2(SOUND_OBJ_WHOMP_LOWPRIO);
cur_obj_shake_screen(SHAKE_POS_SMALL); cur_obj_shake_screen(SHAKE_POS_SMALL);
o->oVelY = 0.0f; o->oVelY = 0.0f;
o->oSubAction++; o->oSubAction++;
} }
if (o->oMoveFlags & 2) if (o->oMoveFlags & OBJ_MOVE_ON_GROUND)
o->oAction = 6; o->oAction = 6;
} }

View File

@ -554,7 +554,7 @@ void debug_print_obj_move_flags(void) {
if (gCurrentObject->oMoveFlags & OBJ_MOVE_IN_AIR) { if (gCurrentObject->oMoveFlags & OBJ_MOVE_IN_AIR) {
print_debug_top_down_objectinfo("SKY %x", gCurrentObject->oMoveFlags); print_debug_top_down_objectinfo("SKY %x", gCurrentObject->oMoveFlags);
} }
if (gCurrentObject->oMoveFlags & OBJ_MOVE_8) { if (gCurrentObject->oMoveFlags & OBJ_MOVE_OUT_SCOPE) {
print_debug_top_down_objectinfo("OUT SCOPE %x", gCurrentObject->oMoveFlags); print_debug_top_down_objectinfo("OUT SCOPE %x", gCurrentObject->oMoveFlags);
} }
#endif #endif

View File

@ -1550,8 +1550,7 @@ void sink_mario_in_quicksand(struct MarioState *m) {
struct Object *o = m->marioObj; struct Object *o = m->marioObj;
if (o->header.gfx.throwMatrix) { if (o->header.gfx.throwMatrix) {
// TODO: throwMatrix should probably be an actual matrix pointer (*o->header.gfx.throwMatrix)[3][1] -= m->quicksandDepth;
*(f32 *) ((u8 *) o->header.gfx.throwMatrix + 0x34) -= m->quicksandDepth;
} }
o->header.gfx.pos[1] -= m->quicksandDepth; o->header.gfx.pos[1] -= m->quicksandDepth;

View File

@ -59,7 +59,7 @@ struct LandingAction sBackflipLandAction = {
4, 0, ACT_FREEFALL, ACT_BACKFLIP_LAND_STOP, ACT_BACKFLIP, ACT_FREEFALL, ACT_BEGIN_SLIDING, 4, 0, ACT_FREEFALL, ACT_BACKFLIP_LAND_STOP, ACT_BACKFLIP, ACT_FREEFALL, ACT_BEGIN_SLIDING,
}; };
Mat4 D_80339F50[2]; Mat4 sFloorAlignMatrix[2];
s16 tilt_body_running(struct MarioState *m) { s16 tilt_body_running(struct MarioState *m) {
s16 pitch = find_floor_slope(m, 0); s16 pitch = find_floor_slope(m, 0);
@ -87,8 +87,8 @@ void play_step_sound(struct MarioState *m, s16 frame1, s16 frame2) {
void align_with_floor(struct MarioState *m) { void align_with_floor(struct MarioState *m) {
m->pos[1] = m->floorHeight; m->pos[1] = m->floorHeight;
mtxf_align_terrain_triangle(D_80339F50[m->unk00], m->pos, m->faceAngle[1], 40.0f); mtxf_align_terrain_triangle(sFloorAlignMatrix[m->unk00], m->pos, m->faceAngle[1], 40.0f);
m->marioObj->header.gfx.throwMatrix = &D_80339F50[m->unk00]; m->marioObj->header.gfx.throwMatrix = &sFloorAlignMatrix[m->unk00];
} }
s32 begin_walking_action(struct MarioState *m, f32 forwardVel, u32 action, u32 actionArg) { s32 begin_walking_action(struct MarioState *m, f32 forwardVel, u32 action, u32 actionArg) {

View File

@ -574,7 +574,7 @@ Gfx *geo_switch_mario_hand_grab_pos(s32 callContext, struct GraphNode *b, Mat4 *
// This is why it won't update during a pause buffered hitstun or when the camera is very far // This is why it won't update during a pause buffered hitstun or when the camera is very far
// away. // away.
get_pos_from_transform_mtx(marioState->marioBodyState->heldObjLastPosition, *curTransform, get_pos_from_transform_mtx(marioState->marioBodyState->heldObjLastPosition, *curTransform,
gCurGraphNodeCamera->matrixPtr); *gCurGraphNodeCamera->matrixPtr);
} }
return NULL; return NULL;
} }

View File

@ -15,6 +15,7 @@
#include "game_init.h" #include "game_init.h"
#include "ingame_menu.h" #include "ingame_menu.h"
#include "interaction.h" #include "interaction.h"
#include "level_misc_macros.h"
#include "level_table.h" #include "level_table.h"
#include "level_update.h" #include "level_update.h"
#include "levels/bob/header.h" #include "levels/bob/header.h"
@ -235,7 +236,7 @@ void obj_orient_graph(struct Object *obj, f32 normalX, f32 normalY, f32 normalZ)
surfaceNormals[2] = normalZ; surfaceNormals[2] = normalZ;
mtxf_align_terrain_normal(*throwMatrix, surfaceNormals, objVisualPosition, obj->oFaceAngleYaw); mtxf_align_terrain_normal(*throwMatrix, surfaceNormals, objVisualPosition, obj->oFaceAngleYaw);
obj->header.gfx.throwMatrix = (void *) throwMatrix; obj->header.gfx.throwMatrix = throwMatrix;
} }
/** /**

View File

@ -42,7 +42,7 @@ Gfx *geo_update_projectile_pos_from_parent(s32 callContext, UNUSED struct GraphN
if (callContext == GEO_CONTEXT_RENDER) { if (callContext == GEO_CONTEXT_RENDER) {
sp1C = (struct Object *) gCurGraphNodeObject; // TODO: change global type to Object pointer sp1C = (struct Object *) gCurGraphNodeObject; // TODO: change global type to Object pointer
if (sp1C->prevObj) { if (sp1C->prevObj) {
create_transformation_from_matrices(sp20, mtx, gCurGraphNodeCamera->matrixPtr); create_transformation_from_matrices(sp20, mtx, *gCurGraphNodeCamera->matrixPtr);
obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj); obj_update_pos_from_parent_transformation(sp20, sp1C->prevObj);
obj_set_gfx_pos_from_pos(sp1C->prevObj); obj_set_gfx_pos_from_pos(sp1C->prevObj);
} }
@ -1285,7 +1285,7 @@ static void cur_obj_move_update_underwater_flags(void) {
} }
static void cur_obj_move_update_ground_air_flags(UNUSED f32 gravity, f32 bounciness) { static void cur_obj_move_update_ground_air_flags(UNUSED f32 gravity, f32 bounciness) {
o->oMoveFlags &= ~OBJ_MOVE_13; o->oMoveFlags &= ~OBJ_MOVE_BOUNCE;
if (o->oPosY < o->oFloorHeight) { if (o->oPosY < o->oFloorHeight) {
// On the first frame that we touch the ground, set OBJ_MOVE_LANDED. // On the first frame that we touch the ground, set OBJ_MOVE_LANDED.
@ -1305,9 +1305,9 @@ static void cur_obj_move_update_ground_air_flags(UNUSED f32 gravity, f32 bouncin
} }
if (o->oVelY > 5.0f) { if (o->oVelY > 5.0f) {
//! If OBJ_MOVE_13 tracks bouncing, it overestimates, since velY //! This overestimates since velY could be > 5 here
// could be > 5 here without bounce (e.g. jump into misa) //! without bounce (e.g. jump into misa).
o->oMoveFlags |= OBJ_MOVE_13; o->oMoveFlags |= OBJ_MOVE_BOUNCE;
} }
} else { } else {
o->oMoveFlags &= ~OBJ_MOVE_LANDED; o->oMoveFlags &= ~OBJ_MOVE_LANDED;
@ -1379,7 +1379,8 @@ void cur_obj_move_y(f32 gravity, f32 bounciness, f32 buoyancy) {
} }
} }
if (o->oMoveFlags & OBJ_MOVE_MASK_33) { if (o->oMoveFlags & (OBJ_MOVE_MASK_ON_GROUND | OBJ_MOVE_AT_WATER_SURFACE
| OBJ_MOVE_UNDERWATER_OFF_GROUND)) {
o->oMoveFlags &= ~OBJ_MOVE_IN_AIR; o->oMoveFlags &= ~OBJ_MOVE_IN_AIR;
} else { } else {
o->oMoveFlags |= OBJ_MOVE_IN_AIR; o->oMoveFlags |= OBJ_MOVE_IN_AIR;
@ -1766,7 +1767,7 @@ static void cur_obj_update_floor_and_resolve_wall_collisions(s16 steepSlopeDegre
if (o->activeFlags & (ACTIVE_FLAG_FAR_AWAY | ACTIVE_FLAG_IN_DIFFERENT_ROOM)) { if (o->activeFlags & (ACTIVE_FLAG_FAR_AWAY | ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {
cur_obj_update_floor(); cur_obj_update_floor();
o->oMoveFlags &= ~OBJ_MOVE_MASK_HIT_WALL_OR_IN_WATER; o->oMoveFlags &= ~(OBJ_MOVE_HIT_WALL | OBJ_MOVE_MASK_IN_WATER);
if (o->oPosY > o->oFloorHeight) { if (o->oPosY > o->oFloorHeight) {
o->oMoveFlags |= OBJ_MOVE_IN_AIR; o->oMoveFlags |= OBJ_MOVE_IN_AIR;
@ -1935,7 +1936,7 @@ void obj_set_throw_matrix_from_transform(struct Object *obj) {
obj_apply_scale_to_transform(obj); obj_apply_scale_to_transform(obj);
} }
obj->header.gfx.throwMatrix = obj->transform; obj->header.gfx.throwMatrix = &obj->transform;
//! Sets scale of gCurrentObject instead of obj. Not exploitable since this //! Sets scale of gCurrentObject instead of obj. Not exploitable since this
// function is only called with obj = gCurrentObject // function is only called with obj = gCurrentObject
@ -1953,7 +1954,7 @@ void obj_build_transform_relative_to_parent(struct Object *obj) {
obj->oPosY = obj->transform[3][1]; obj->oPosY = obj->transform[3][1];
obj->oPosZ = obj->transform[3][2]; obj->oPosZ = obj->transform[3][2];
obj->header.gfx.throwMatrix = obj->transform; obj->header.gfx.throwMatrix = &obj->transform;
//! Sets scale of gCurrentObject instead of obj. Not exploitable since this //! Sets scale of gCurrentObject instead of obj. Not exploitable since this
// function is only called with obj = gCurrentObject // function is only called with obj = gCurrentObject
@ -2246,23 +2247,23 @@ static void stub_obj_helpers_2(void) {
} }
s32 cur_obj_set_direction_table(s8 *a0) { s32 cur_obj_set_direction_table(s8 *a0) {
o->oToxBoxUnk1AC = a0; o->oToxBoxMovementPattern = a0;
o->oToxBoxUnk1B0 = 0; o->oToxBoxMovementStep = 0;
return *(s8 *) o->oToxBoxUnk1AC; return *(s8 *) o->oToxBoxMovementPattern;
} }
s32 cur_obj_progress_direction_table(void) { s32 cur_obj_progress_direction_table(void) {
s8 spF; s8 spF;
s8 *sp8 = o->oToxBoxUnk1AC; s8 *sp8 = o->oToxBoxMovementPattern;
s32 sp4 = o->oToxBoxUnk1B0 + 1; s32 sp4 = o->oToxBoxMovementStep + 1;
if (sp8[sp4] != -1) { if (sp8[sp4] != -1) {
spF = sp8[sp4]; spF = sp8[sp4];
o->oToxBoxUnk1B0++; o->oToxBoxMovementStep++;
} else { } else {
spF = sp8[0]; spF = sp8[0];
o->oToxBoxUnk1B0 = 0; o->oToxBoxMovementStep = 0;
} }
return spF; return spF;
@ -2759,7 +2760,7 @@ void cur_obj_align_gfx_with_floor(void) {
floorNormal[2] = floor->normal.z; floorNormal[2] = floor->normal.z;
mtxf_align_terrain_normal(o->transform, floorNormal, position, o->oFaceAngleYaw); mtxf_align_terrain_normal(o->transform, floorNormal, position, o->oFaceAngleYaw);
o->header.gfx.throwMatrix = o->transform; o->header.gfx.throwMatrix = &o->transform;
} }
} }

View File

@ -267,10 +267,15 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
* range of this node. * range of this node.
*/ */
static void geo_process_level_of_detail(struct GraphNodeLevelOfDetail *node) { static void geo_process_level_of_detail(struct GraphNodeLevelOfDetail *node) {
#ifdef GBI_FLOATS
Mtx *mtx = gMatStackFixed[gMatStackIndex];
s16 distanceFromCam = (s32) -mtx->m[3][2]; // z-component of the translation column
#else
// The fixed point Mtx type is defined as 16 longs, but it's actually 16 // The fixed point Mtx type is defined as 16 longs, but it's actually 16
// shorts for the integer parts followed by 16 shorts for the fraction parts // shorts for the integer parts followed by 16 shorts for the fraction parts
s16 *mtx = (s16 *) gMatStackFixed[gMatStackIndex]; Mtx *mtx = gMatStackFixed[gMatStackIndex];
s16 distanceFromCam = -mtx[14]; // z-component of the translation column s16 distanceFromCam = -GET_HIGH_S16_OF_32(mtx->m[1][3]); // z-component of the translation column
#endif
if (node->minDistance <= distanceFromCam && distanceFromCam < node->maxDistance) { if (node->minDistance <= distanceFromCam && distanceFromCam < node->maxDistance) {
if (node->node.children != 0) { if (node->node.children != 0) {
@ -321,7 +326,7 @@ static void geo_process_camera(struct GraphNodeCamera *node) {
gMatStackFixed[gMatStackIndex] = mtx; gMatStackFixed[gMatStackIndex] = mtx;
if (node->fnNode.node.children != 0) { if (node->fnNode.node.children != 0) {
gCurGraphNodeCamera = node; gCurGraphNodeCamera = node;
node->matrixPtr = gMatStack[gMatStackIndex]; node->matrixPtr = &gMatStack[gMatStackIndex];
geo_process_node_and_siblings(node->fnNode.node.children); geo_process_node_and_siblings(node->fnNode.node.children);
gCurGraphNodeCamera = NULL; gCurGraphNodeCamera = NULL;
} }
@ -646,7 +651,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
if (gCurGraphNodeCamera != NULL && gCurGraphNodeObject != NULL) { if (gCurGraphNodeCamera != NULL && gCurGraphNodeObject != NULL) {
if (gCurGraphNodeHeldObject != NULL) { if (gCurGraphNodeHeldObject != NULL) {
get_pos_from_transform_mtx(shadowPos, gMatStack[gMatStackIndex], get_pos_from_transform_mtx(shadowPos, gMatStack[gMatStackIndex],
gCurGraphNodeCamera->matrixPtr); *gCurGraphNodeCamera->matrixPtr);
shadowScale = node->shadowScale; shadowScale = node->shadowScale;
} else { } else {
vec3f_copy(shadowPos, gCurGraphNodeObject->pos); vec3f_copy(shadowPos, gCurGraphNodeObject->pos);
@ -686,7 +691,7 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
mtx = alloc_display_list(sizeof(*mtx)); mtx = alloc_display_list(sizeof(*mtx));
gMatStackIndex++; gMatStackIndex++;
mtxf_translate(mtxf, shadowPos); mtxf_translate(mtxf, shadowPos);
mtxf_mul(gMatStack[gMatStackIndex], mtxf, gCurGraphNodeCamera->matrixPtr); mtxf_mul(gMatStack[gMatStackIndex], mtxf, *gCurGraphNodeCamera->matrixPtr);
mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]); mtxf_to_mtx(mtx, gMatStack[gMatStackIndex]);
gMatStackFixed[gMatStackIndex] = mtx; gMatStackFixed[gMatStackIndex] = mtx;
if (gShadowAboveWaterOrLava == 1) { if (gShadowAboveWaterOrLava == 1) {
@ -802,7 +807,7 @@ static void geo_process_object(struct Object *node) {
if (node->header.gfx.unk18 == gCurGraphNodeRoot->areaIndex) { if (node->header.gfx.unk18 == gCurGraphNodeRoot->areaIndex) {
if (node->header.gfx.throwMatrix != NULL) { if (node->header.gfx.throwMatrix != NULL) {
mtxf_mul(gMatStack[gMatStackIndex + 1], (void *) node->header.gfx.throwMatrix, mtxf_mul(gMatStack[gMatStackIndex + 1], *node->header.gfx.throwMatrix,
gMatStack[gMatStackIndex]); gMatStack[gMatStackIndex]);
} else if (node->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) { } else if (node->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) {
mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], mtxf_billboard(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex],
@ -814,7 +819,7 @@ static void geo_process_object(struct Object *node) {
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1], mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex + 1],
node->header.gfx.scale); node->header.gfx.scale);
node->header.gfx.throwMatrix = gMatStack[++gMatStackIndex]; node->header.gfx.throwMatrix = &gMatStack[++gMatStackIndex];
node->header.gfx.cameraToObject[0] = gMatStack[gMatStackIndex][3][0]; node->header.gfx.cameraToObject[0] = gMatStack[gMatStackIndex][3][0];
node->header.gfx.cameraToObject[1] = gMatStack[gMatStackIndex][3][1]; node->header.gfx.cameraToObject[1] = gMatStack[gMatStackIndex][3][1];
node->header.gfx.cameraToObject[2] = gMatStack[gMatStackIndex][3][2]; node->header.gfx.cameraToObject[2] = gMatStack[gMatStackIndex][3][2];
@ -885,7 +890,7 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
translation[2] = node->translation[2] / 4.0f; translation[2] = node->translation[2] / 4.0f;
mtxf_translate(mat, translation); mtxf_translate(mat, translation);
mtxf_copy(gMatStack[gMatStackIndex + 1], (void *) gCurGraphNodeObject->throwMatrix); mtxf_copy(gMatStack[gMatStackIndex + 1], *gCurGraphNodeObject->throwMatrix);
gMatStack[gMatStackIndex + 1][3][0] = gMatStack[gMatStackIndex][3][0]; gMatStack[gMatStackIndex + 1][3][0] = gMatStack[gMatStackIndex][3][0];
gMatStack[gMatStackIndex + 1][3][1] = gMatStack[gMatStackIndex][3][1]; gMatStack[gMatStackIndex + 1][3][1] = gMatStack[gMatStackIndex][3][1];
gMatStack[gMatStackIndex + 1][3][2] = gMatStack[gMatStackIndex][3][2]; gMatStack[gMatStackIndex + 1][3][2] = gMatStack[gMatStackIndex][3][2];

View File

@ -5075,7 +5075,7 @@ bool ModuleState::fileModuleHandlesSeeking() const
status ModuleState::setup(AFfilehandle file, Track *track) status ModuleState::setup(AFfilehandle file, Track *track)
{ {
AFframecount fframepos = std::llrint((long double)track->nextvframe * track->f.sampleRate / track->v.sampleRate); AFframecount fframepos = std::llrint(track->nextvframe * track->f.sampleRate / track->v.sampleRate);
bool isReading = file->m_access == _AF_READ_ACCESS; bool isReading = file->m_access == _AF_READ_ACCESS;
if (!track->v.isUncompressed()) if (!track->v.isUncompressed())
@ -5146,11 +5146,11 @@ status ModuleState::setup(AFfilehandle file, Track *track)
if (track->totalfframes == -1) if (track->totalfframes == -1)
track->totalvframes = -1; track->totalvframes = -1;
else else
track->totalvframes = std::llrint((long double)track->totalfframes * track->totalvframes = std::llrint(track->totalfframes *
(track->v.sampleRate / track->f.sampleRate)); (track->v.sampleRate / track->f.sampleRate));
track->nextfframe = fframepos; track->nextfframe = fframepos;
track->nextvframe = std::llrint((long double)fframepos * track->v.sampleRate / track->f.sampleRate); track->nextvframe = std::llrint(fframepos * track->v.sampleRate / track->f.sampleRate);
m_isDirty = false; m_isDirty = false;

View File

@ -53,6 +53,8 @@ static void parse_error(const char *filename, int lineNum, const char *msgfmt, .
// Reads the whole file and returns a null-terminated buffer with its contents // Reads the whole file and returns a null-terminated buffer with its contents
void *read_text_file(const char *filename) void *read_text_file(const char *filename)
{
if (strcmp(filename, "-") != 0)
{ {
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
uint8_t *buffer; uint8_t *buffer;
@ -67,6 +69,8 @@ void *read_text_file(const char *filename)
// allocate buffer // allocate buffer
buffer = malloc(size + 1); buffer = malloc(size + 1);
if (buffer == NULL)
fatal_error("could not allocate buffer of size %u", (uint32_t)(size + 1));
// read file // read file
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
@ -80,6 +84,40 @@ void *read_text_file(const char *filename)
return buffer; return buffer;
} }
else
{
size_t size = 0;
size_t capacity = 1024;
uint8_t *buffer = malloc(capacity + 1);
if (buffer == NULL)
fatal_error("could not allocate buffer of size %u", (uint32_t)(capacity + 1));
for (;;)
{
size += fread(buffer + size, 1, capacity - size, stdin);
if (size == capacity)
{
capacity *= 2;
buffer = realloc(buffer, capacity + 1);
if (buffer == NULL)
fatal_error("could not allocate buffer of size %u", (uint32_t)(capacity + 1));
}
else if (feof(stdin))
{
break;
}
else
{
fatal_error("error reading from stdin: %s", strerror(errno));
}
}
// null-terminate the buffer
buffer[size] = 0;
return buffer;
}
}
static char *skip_whitespace(char *str) static char *skip_whitespace(char *str)
{ {
@ -351,7 +389,7 @@ static char *convert_string(char *pos, FILE *fout, const char *inputFileName, ch
static void convert_file(const char *infilename, const char *outfilename) static void convert_file(const char *infilename, const char *outfilename)
{ {
char *in = read_text_file(infilename); char *in = read_text_file(infilename);
FILE *fout = fopen(outfilename, "wb"); FILE *fout = strcmp(outfilename, "-") != 0 ? fopen(outfilename, "wb") : stdout;
if (fout == NULL) if (fout == NULL)
fatal_error("failed to open file '%s' for writing: %s", strerror(errno)); fatal_error("failed to open file '%s' for writing: %s", strerror(errno));
@ -436,6 +474,7 @@ static void convert_file(const char *infilename, const char *outfilename)
eof: eof:
fwrite(start, pos - start, 1, fout); fwrite(start, pos - start, 1, fout);
if (strcmp(outfilename, "-") != 0)
fclose(fout); fclose(fout);
free(in); free(in);
} }