refresh 4

This commit is contained in:
n64
2019-12-01 21:52:53 -05:00
parent a7c423cb43
commit 04732af90b
729 changed files with 21400 additions and 37110 deletions
+7 -7
View File
@@ -131,9 +131,9 @@ u8 gDefaultShortNoteDurationTable[16] = {
s8 gVibratoCurve[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120 };
struct AdsrEnvelope gDefaultEnvelope[] = {
{ 4, 32000 }, // go from 0 to 32000 over the course of 16ms
{ 1000, 32000 }, // stay there for 4.16 seconds
{ ADSR_HANG, 0 } // then continue staying there
{ BSWAP16(4), BSWAP16(32000) }, // go from 0 to 32000 over the course of 16ms
{ BSWAP16(1000), BSWAP16(32000) }, // stay there for 4.16 seconds
{ BSWAP16(ADSR_HANG), 0 } // then continue staying there
};
s16 sSineWave[0x40] = {
@@ -375,16 +375,16 @@ s8 sUnused8033EF8 = 24;
struct CtlEntry *gCtlEntries;
s32 gAiFrequency;
u32 D_80226D68;
s32 D_80226D6C;
s32 gMaxAudioCmds;
s32 gMaxSimultaneousNotes;
s32 D_80226D74;
s32 gSamplesPerFrameTarget;
s32 gMinAiBufferLength;
s16 gTempoInternalToExternal;
s8 gAudioUpdatesPerFrame;
s8 gSoundMode;
volatile s32 gActiveAudioFrames;
volatile s32 gAudioFrameCount;
volatile s32 gCurrAudioFrameDmaCount;
s32 gAudioTaskIndex;
@@ -402,4 +402,4 @@ s16 gAiBufferLengths[NUMAIBUFFERS];
u32 gUnused80226E58[0x10];
u16 gUnused80226E98[0x10];
u32 D_80226EB8;
u32 gAudioRandom;
+7 -7
View File
@@ -1,5 +1,5 @@
#ifndef _AUDIO_DATA_H
#define _AUDIO_DATA_H
#ifndef AUDIO_DATA_H
#define AUDIO_DATA_H
#include "internal.h"
@@ -46,16 +46,16 @@ extern volatile s32 gAudioLoadLock;
extern struct CtlEntry *gCtlEntries;
extern s32 gAiFrequency;
extern u32 D_80226D68;
extern s32 D_80226D6C;
extern s32 gMaxAudioCmds;
extern s32 gMaxSimultaneousNotes;
extern s32 D_80226D74;
extern s32 gSamplesPerFrameTarget;
extern s32 gMinAiBufferLength;
extern s16 gTempoInternalToExternal;
extern s8 gAudioUpdatesPerFrame; // = 4
extern s8 gSoundMode;
extern volatile s32 gActiveAudioFrames;
extern volatile s32 gAudioFrameCount;
extern volatile s32 gCurrAudioFrameDmaCount; // number of DMAs performed during this frame
extern s32 gAudioTaskIndex;
@@ -73,6 +73,6 @@ extern s16 gAiBufferLengths[NUMAIBUFFERS];
extern u32 gUnused80226E58[0x10];
extern u16 gUnused80226E98[0x10];
extern u32 D_80226EB8;
extern u32 gAudioRandom;
#endif /* _AUDIO_DATA_H */
#endif /* AUDIO_DATA_H */
+4 -4
View File
@@ -57,7 +57,7 @@ void sequence_player_process_sound(struct SequencePlayer *seqPlayer) {
channelVolume =
seqChannel->seqPlayer->fadeVolume * (seqChannel->volume * seqChannel->volumeScale);
if (seqChannel->seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_20) != 0) {
if (seqChannel->seqPlayer->muted && (seqChannel->muteBehavior & MUTE_BEHAVIOR_SOFTEN) != 0) {
channelVolume *= seqChannel->seqPlayer->muteVolumeScale;
}
@@ -257,7 +257,7 @@ s32 adsr_update(struct AdsrState *adsr) {
// fallthrough
case ADSR_STATE_LOOP:
adsr->delay = adsr->envelope[adsr->envIndex].delay;
adsr->delay = BSWAP16(adsr->envelope[adsr->envIndex].delay);
switch (adsr->delay) {
case ADSR_DISABLE:
adsr->state = ADSR_STATE_DISABLED;
@@ -266,14 +266,14 @@ s32 adsr_update(struct AdsrState *adsr) {
adsr->state = ADSR_STATE_HANG;
break;
case ADSR_GOTO:
adsr->envIndex = adsr->envelope[adsr->envIndex].arg;
adsr->envIndex = BSWAP16(adsr->envelope[adsr->envIndex].arg);
break;
case ADSR_RESTART:
adsr->state = ADSR_STATE_INITIAL;
break;
default:
adsr->target = adsr->envelope[adsr->envIndex].arg;
adsr->target = BSWAP16(adsr->envelope[adsr->envIndex].arg);
adsr->velocity = ((adsr->target - adsr->current) << 0x10) / adsr->delay;
adsr->state = ADSR_STATE_FADE;
adsr->envIndex++;
+12 -3
View File
@@ -1,7 +1,8 @@
#ifndef _AUDIO_EFFECTS_H
#define _AUDIO_EFFECTS_H
#ifndef AUDIO_EFFECTS_H
#define AUDIO_EFFECTS_H
#include "internal.h"
#include "platform_info.h"
#define ADSR_STATE_DISABLED 0
#define ADSR_STATE_INITIAL 1
@@ -22,10 +23,18 @@
#define ADSR_GOTO -2
#define ADSR_RESTART -3
// Envelopes are always stored as big endian, to match sequence files which are
// byte blobs and can embed envelopes. Hence this byteswapping macro.
#if IS_BIG_ENDIAN
#define BSWAP16(x) (x)
#else
#define BSWAP16(x) (((x) & 0xff) << 8 | (((x) >> 8) & 0xff))
#endif
void sequence_player_process_sound(struct SequencePlayer *seqPlayer);
void note_vibrato_update(struct Note *note);
void note_vibrato_init(struct Note *note);
void adsr_init(struct AdsrState *adsr, struct AdsrEnvelope *envelope, s16 *volOut);
s32 adsr_update(struct AdsrState *adsr);
#endif /* _AUDIO_EFFECTS_H */
#endif /* AUDIO_EFFECTS_H */
+154 -247
View File
@@ -14,21 +14,27 @@
#include "game/room.h"
#include "game/camera.h"
#include "seq_ids.h"
#include "dialog_ids.h"
#include "level_table.h"
// N.B. sound banks are different from the audio banks referred to in other
// files. We should really fix our naming to be less ambiguous...
#define MAX_BG_MUSIC_QUEUE_SIZE 6
#define SOUND_BANK_COUNT 10
#define MAX_CHANNELS_PER_SOUND 1
#define SEQUENCE_NONE 0xFF
#define SAMPLES_TO_OVERPRODUCE 0x10
#define EXTRA_BUFFERED_AI_SAMPLES_TARGET 0x40
// No-op printf macro which leaves string literals in rodata in IDO. (IDO
// doesn't support variadic macros, so instead they let the parameter list
// expand to a no-op comma expression.) See goddard/gd_main.h.
#ifdef __GNUC__
#define stubbed_printf(...)
#else
// expand to a no-op comma expression.) See also goddard/gd_main.h.
#ifdef __sgi
#define stubbed_printf
#else
#define stubbed_printf(...)
#endif
struct Sound {
@@ -66,7 +72,7 @@ s32 gAudioErrorFlags = 0;
s32 sGameLoopTicked = 0;
// Dialog sounds
// The US difference is the sound for Dialog037 ("I win! You lose! Ha ha ha ha!
// The US difference is the sound for DIALOG_037 ("I win! You lose! Ha ha ha ha!
// You're no slouch, but I'm a better sledder! Better luck next time!"), spoken
// by Koopa instead of the penguin in JP.
@@ -89,7 +95,7 @@ s32 sGameLoopTicked = 0;
#define DIFF TUXIE
#endif
u8 sDialogSpeaker[170] = {
u8 sDialogSpeaker[] = {
// 0 1 2 3 4 5 6 7 8 9
/* 0*/ _, BOMB, BOMB, BOMB, BOMB, KOOPA, KOOPA, KOOPA, _, KOOPA,
/* 1*/ _, _, _, _, _, _, _, KBOMB, _, _,
@@ -110,6 +116,7 @@ u8 sDialogSpeaker[170] = {
/*16*/ _, YOSHI, _, _, _, _, _, _, WIGLR, _
};
#undef _
STATIC_ASSERT(ARRAY_COUNT(sDialogSpeaker) == DIALOG_COUNT, "change this array if you are adding dialogs");
s32 sDialogSpeakerVoice[15] = {
SOUND_OBJ_UKIKI_CHATTER_LONG,
@@ -150,10 +157,11 @@ u8 sSoundRequestCount = 0;
#define MARIO_IS_IN_AREA 6
#define MARIO_IS_IN_ROOM 7
#define DYN1(cond1, val1, res) 1 << (15 - cond1) | res, val1
#define DYN2(cond1, val1, cond2, val2, res) 1 << (15 - cond1) | 1 << (15 - cond2) | res, val1, val2
#define DYN3(cond1, val1, cond2, val2, cond3, val3, res) \
1 << (15 - cond1) | 1 << (15 - cond2) | 1 << (15 - cond3) | res, val1, val2, val3
#define DYN1(cond1, val1, res) (s16)(1 << (15 - cond1) | res), val1
#define DYN2(cond1, val1, cond2, val2, res) \
(s16)(1 << (15 - cond1) | 1 << (15 - cond2) | res), val1, val2
#define DYN3(cond1, val1, cond2, val2, cond3, val3, res) \
(s16)(1 << (15 - cond1) | 1 << (15 - cond2) | 1 << (15 - cond3) | res), val1, val2, val3
s16 sDynBbh[] = {
SEQ_LEVEL_SPOOKY,
@@ -201,167 +209,58 @@ s16 sDynNone[] = { SEQ_SOUND_PLAYER, 0 };
u8 sCurrentMusicDynamic = 0xff;
u8 sBackgroundMusicForDynamics = SEQUENCE_NONE;
#define STUB_LEVEL(_0, _1, _2, _3, _4, _5, _6, leveldyn, _8) leveldyn,
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, _8, leveldyn, _10) leveldyn,
#define _ sDynNone
s16 *sLevelDynamics[] = {
s16 *sLevelDynamics[LEVEL_COUNT] = {
_, // LEVEL_NONE
_, // LEVEL_UNKNOWN_1
_, // LEVEL_UNKNOWN_2
_, // LEVEL_UNKNOWN_3
sDynBbh, // LEVEL_BBH
_, // LEVEL_CCM
_, // LEVEL_CASTLE
sDynHmc, // LEVEL_HMC
_, // LEVEL_SSL
_, // LEVEL_BOB
_, // LEVEL_SL
sDynWdw, // LEVEL_WDW
sDynJrb, // LEVEL_JRB
_, // LEVEL_THI
_, // LEVEL_TTC
_, // LEVEL_RR
_, // LEVEL_CASTLE_GROUNDS
_, // LEVEL_BITDW
_, // LEVEL_VCUTM
_, // LEVEL_BITFS
_, // LEVEL_SA
_, // LEVEL_BITS
_, // LEVEL_LLL
sDynDdd, // LEVEL_DDD
_, // LEVEL_WF
_, // LEVEL_ENDING
_, // LEVEL_CASTLE_COURTYARD
_, // LEVEL_PSS
_, // LEVEL_COTMC
_, // LEVEL_TOTWC
_, // LEVEL_BOWSER_1
_, // LEVEL_WMOTR
_, // LEVEL_UNKNOWN_32
_, // LEVEL_BOWSER_2
_, // LEVEL_BOWSER_3
_, // LEVEL_UNKNOWN_35
_, // LEVEL_TTM
_, // LEVEL_UNKNOWN_37
sDynUnk38, // LEVEL_UNKNOWN_38
#include "levels/level_defines.h"
};
STATIC_ASSERT(ARRAY_COUNT(sLevelDynamics) == LEVEL_COUNT, "change this array if you are adding levels");
#undef _
#undef STUB_LEVEL
#undef DEFINE_LEVEL
struct MusicDynamic {
/*0x0*/ s16 bits1;
/*0x2*/ u8 unused1;
/*0x3*/ u8 volScale1; // maybe this is an u16, loaded as u8?
/*0x2*/ u16 volScale1;
/*0x4*/ s16 dur1;
/*0x6*/ s16 bits2;
/*0x8*/ u8 unused2;
/*0x9*/ u8 volScale2;
/*0x8*/ u16 volScale2;
/*0xA*/ s16 dur2;
}; // size = 0xC
struct MusicDynamic sMusicDynamics[8] = {
{ 0x0000, 0, 127, 100, 0x0e43, 0, 0, 100 }, // SEQ_LEVEL_WATER
{ 0x0003, 0, 127, 100, 0x0e40, 0, 0, 100 }, // SEQ_LEVEL_WATER
{ 0x0e43, 0, 127, 200, 0x0000, 0, 0, 200 }, // SEQ_LEVEL_WATER
{ 0x02ff, 0, 127, 100, 0x0100, 0, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
{ 0x03f7, 0, 127, 100, 0x0008, 0, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
{ 0x0070, 0, 127, 10, 0x0000, 0, 0, 100 }, // SEQ_LEVEL_SPOOKY
{ 0x0000, 0, 127, 100, 0x0070, 0, 0, 10 }, // SEQ_LEVEL_SPOOKY
{ 0xffff, 0, 127, 100, 0x0000, 0, 0, 100 }, // any (unused)
{ 0x0000, 127, 100, 0x0e43, 0, 100 }, // SEQ_LEVEL_WATER
{ 0x0003, 127, 100, 0x0e40, 0, 100 }, // SEQ_LEVEL_WATER
{ 0x0e43, 127, 200, 0x0000, 0, 200 }, // SEQ_LEVEL_WATER
{ 0x02ff, 127, 100, 0x0100, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
{ 0x03f7, 127, 100, 0x0008, 0, 100 }, // SEQ_LEVEL_UNDERGROUND
{ 0x0070, 127, 10, 0x0000, 0, 100 }, // SEQ_LEVEL_SPOOKY
{ 0x0000, 127, 100, 0x0070, 0, 10 }, // SEQ_LEVEL_SPOOKY
{ 0xffff, 127, 100, 0x0000, 0, 100 }, // any (unused)
};
u8 gAreaEchoLevel[][3] = {
#define STUB_LEVEL(_0, _1, _2, _3, echo1, echo2, echo3, _7, _8) { echo1, echo2, echo3 },
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, echo1, echo2, echo3, _9, _10) { echo1, echo2, echo3 },
u8 gAreaEchoLevel[LEVEL_COUNT][3] = {
{ 0x00, 0x00, 0x00 }, // LEVEL_NONE
{ 0x00, 0x00, 0x00 }, // LEVEL_UNKNOWN_1
{ 0x00, 0x00, 0x00 }, // LEVEL_UNKNOWN_2
{ 0x00, 0x00, 0x00 }, // LEVEL_UNKNOWN_3
{ 0x28, 0x28, 0x28 }, // LEVEL_BBH
{ 0x10, 0x38, 0x38 }, // LEVEL_CCM
{ 0x20, 0x20, 0x30 }, // LEVEL_CASTLE
{ 0x28, 0x28, 0x28 }, // LEVEL_HMC
{ 0x08, 0x30, 0x30 }, // LEVEL_SSL
{ 0x08, 0x08, 0x08 }, // LEVEL_BOB
{ 0x10, 0x28, 0x28 }, // LEVEL_SL
{ 0x10, 0x18, 0x18 }, // LEVEL_WDW
{ 0x10, 0x18, 0x18 }, // LEVEL_JRB
{ 0x0c, 0x0c, 0x20 }, // LEVEL_THI
{ 0x18, 0x18, 0x18 }, // LEVEL_TTC
{ 0x20, 0x20, 0x20 }, // LEVEL_RR
{ 0x08, 0x08, 0x08 }, // LEVEL_CASTLE_GROUNDS
{ 0x28, 0x28, 0x28 }, // LEVEL_BITDW
{ 0x28, 0x28, 0x28 }, // LEVEL_VCUTM
{ 0x28, 0x28, 0x28 }, // LEVEL_BITFS
{ 0x10, 0x10, 0x10 }, // LEVEL_SA
{ 0x28, 0x28, 0x28 }, // LEVEL_BITS
{ 0x08, 0x30, 0x30 }, // LEVEL_LLL
{ 0x10, 0x20, 0x20 }, // LEVEL_DDD
{ 0x08, 0x08, 0x08 }, // LEVEL_WF
{ 0x00, 0x00, 0x00 }, // LEVEL_ENDING
{ 0x08, 0x08, 0x08 }, // LEVEL_CASTLE_COURTYARD
{ 0x28, 0x28, 0x28 }, // LEVEL_PSS
{ 0x28, 0x28, 0x28 }, // LEVEL_COTMC
{ 0x20, 0x20, 0x20 }, // LEVEL_TOTWC
{ 0x40, 0x40, 0x40 }, // LEVEL_BOWSER_1
{ 0x28, 0x28, 0x28 }, // LEVEL_WMOTR
{ 0x70, 0x00, 0x00 }, // LEVEL_UNKNOWN_32
{ 0x40, 0x40, 0x40 }, // LEVEL_BOWSER_2
{ 0x40, 0x40, 0x40 }, // LEVEL_BOWSER_3
{ 0x00, 0x00, 0x00 }, // LEVEL_UNKNOWN_35
{ 0x08, 0x08, 0x08 }, // LEVEL_TTM
{ 0x00, 0x00, 0x00 }, // LEVEL_UNKNOWN_37
{ 0x00, 0x00, 0x00 }, // LEVEL_UNKNOWN_38
#include "levels/level_defines.h"
};
STATIC_ASSERT(ARRAY_COUNT(gAreaEchoLevel) == LEVEL_COUNT, "change this array if you are adding levels");
#undef STUB_LEVEL
#undef DEFINE_LEVEL
#ifdef VERSION_JP
#define VAL_DIFF 25000
#else
#define VAL_DIFF 60000
#endif
#define STUB_LEVEL(_0, _1, _2, volume, _4, _5, _6, _7, _8) volume,
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, volume, _6, _7, _8, _9, _10) volume,
u16 D_80332028[] = {
u16 D_80332028[LEVEL_COUNT] = {
20000, // LEVEL_NONE
20000, // LEVEL_UNKNOWN_1
20000, // LEVEL_UNKNOWN_2
20000, // LEVEL_UNKNOWN_3
28000, // LEVEL_BBH
17000, // LEVEL_CCM
20000, // LEVEL_CASTLE
16000, // LEVEL_HMC
15000, // LEVEL_SSL
15000, // LEVEL_BOB
14000, // LEVEL_SL
17000, // LEVEL_WDW
20000, // LEVEL_JRB
20000, // LEVEL_THI
18000, // LEVEL_TTC
20000, // LEVEL_RR
25000, // LEVEL_CASTLE_GROUNDS
16000, // LEVEL_BITDW
30000, // LEVEL_VCUTM
16000, // LEVEL_BITFS
20000, // LEVEL_SA
16000, // LEVEL_BITS
22000, // LEVEL_LLL
17000, // LEVEL_DDD
13000, // LEVEL_WF
20000, // LEVEL_ENDING
20000, // LEVEL_CASTLE_COURTYARD
20000, // LEVEL_PSS
18000, // LEVEL_COTMC
20000, // LEVEL_TOTWC
VAL_DIFF, // LEVEL_BOWSER_1
20000, // LEVEL_WMOTR
20000, // LEVEL_UNKNOWN_32
VAL_DIFF, // LEVEL_BOWSER_2
VAL_DIFF, // LEVEL_BOWSER_3
20000, // LEVEL_UNKNOWN_35
15000, // LEVEL_TTM
20000, // LEVEL_UNKNOWN_37
20000, // LEVEL_UNKNOWN_38
#include "levels/level_defines.h"
};
#undef VAL_DIFF
STATIC_ASSERT(ARRAY_COUNT(D_80332028) == LEVEL_COUNT, "change this array if you are adding levels");
#undef STUB_LEVEL
#undef DEFINE_LEVEL
#define AUDIO_MAX_DISTANCE US_FLOAT(22000.0)
@@ -407,12 +306,12 @@ u8 sBackgroundMusicDefaultVolume[] = {
STATIC_ASSERT(ARRAY_COUNT(sBackgroundMusicDefaultVolume) == SEQ_COUNT,
"change this array if you are adding sequences");
u8 gPlayer0CurSeqId = SEQUENCE_NONE;
u8 sPlayer0CurSeqId = SEQUENCE_NONE;
u8 sMusicDynamicDelay = 0;
u8 D_803320A4[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // pointers to head of list
u8 D_803320B0[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; // pointers to head of list
u8 D_803320BC[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
u8 D_803320C8[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; // sizes of D_80360C38
u8 D_803320BC[SOUND_BANK_COUNT] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // only used for debugging
u8 sMaxChannelsForSoundBank[SOUND_BANK_COUNT] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
// Banks 2 and 7 both grew from 0x30 sounds to 0x40 in size in US.
#ifdef VERSION_JP
@@ -426,8 +325,8 @@ u8 sNumSoundsPerBank[SOUND_BANK_COUNT] = {
#undef BANK27_SIZE
f32 gDefaultSoundArgs[3] = { 0.0f, 0.0f, 0.0f };
f32 gUnusedSoundArgs[3] = { 1.0f, 1.0f, 1.0f };
u8 gSoundBankDisabled[16] = { 0 };
f32 sUnusedSoundArgs[3] = { 1.0f, 1.0f, 1.0f };
u8 sSoundBankDisabled[16] = { 0 };
u8 D_80332108 = 0;
u8 sHasStartedFadeOut = FALSE;
u16 D_80332110 = 0;
@@ -445,8 +344,8 @@ u8 sUnused8033323C = 0; // never read, set to 0
u16 *gCurrAiBuffer;
struct Sound sSoundRequests[0x100];
struct ChannelVolumeScaleFade D_80360928[SEQUENCE_PLAYERS][CHANNELS_MAX];
u8 D_80360C28[SOUND_BANK_COUNT];
u8 D_80360C38[SOUND_BANK_COUNT][1];
u8 sUsedChannelsForSoundBank[SOUND_BANK_COUNT];
u8 sCurrentSound[SOUND_BANK_COUNT][MAX_CHANNELS_PER_SOUND]; // index into gSoundBanks
// list item memory for D_803320A4 and D_803320B0
struct SoundCharacteristics gSoundBanks[SOUND_BANK_COUNT][40];
u8 D_80363808[SOUND_BANK_COUNT];
@@ -538,7 +437,7 @@ void unused_8031E4F0(void) {
}
void unused_8031E568(void) {
stubbed_printf("COUNT %8d\n", gActiveAudioFrames);
stubbed_printf("COUNT %8d\n", gAudioFrameCount);
}
#endif
@@ -627,14 +526,14 @@ static void func_8031D838(s32 player, FadeT fadeInTime, u8 targetVolume) {
}
struct SPTask *create_next_audio_frame_task(void) {
u32 t2;
u32 samplesRemainingInAI;
s32 writtenCmds;
s32 index;
OSTask_t *task;
s32 oldDmaCount;
s32 flags;
gActiveAudioFrames++;
gAudioFrameCount++;
if (gAudioLoadLock != AUDIO_LOCK_NOT_LOADING) {
stubbed_printf("DAC:Lost 1 Frame.\n");
return NULL;
@@ -644,10 +543,19 @@ struct SPTask *create_next_audio_frame_task(void) {
gCurrAiBufferIndex++;
gCurrAiBufferIndex %= NUMAIBUFFERS;
index = (gCurrAiBufferIndex - 2 + NUMAIBUFFERS) % NUMAIBUFFERS;
t2 = osAiGetLength() / 4;
samplesRemainingInAI = osAiGetLength() / 4;
// Graphics lags behind a little, so make sure audio does too by playing the
// sound that was generated two frames ago.
// Audio is triple buffered; the audio interface reads from two buffers
// while the third is being written by the RSP. More precisely, the
// lifecycle is:
// - this function computes an audio command list
// - wait for vblank
// - the command list is sent to the RSP (we could have sent it to the
// RSP before the vblank, but that gives the RSP less time to finish)
// - wait for vblank
// - the RSP is now expected to be finished, and we can send its output
// on to the AI
// Here we thus send to the AI the sound that was generated two frames ago.
if (gAiBufferLengths[index] != 0) {
osAiSetNextBuffer(gAiBuffers[index], gAiBufferLengths[index] * 4);
}
@@ -666,12 +574,13 @@ struct SPTask *create_next_audio_frame_task(void) {
index = gCurrAiBufferIndex;
gCurrAiBuffer = gAiBuffers[index];
gAiBufferLengths[index] = (((D_80226D74 - t2) + 0x40) & 0xfff0) + 0x10;
gAiBufferLengths[index] = ((gSamplesPerFrameTarget - samplesRemainingInAI +
EXTRA_BUFFERED_AI_SAMPLES_TARGET) & ~0xf) + SAMPLES_TO_OVERPRODUCE;
if (gAiBufferLengths[index] < gMinAiBufferLength) {
gAiBufferLengths[index] = gMinAiBufferLength;
}
if (gAiBufferLengths[index] > D_80226D74 + 0x10) {
gAiBufferLengths[index] = D_80226D74 + 0x10;
if (gAiBufferLengths[index] > gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE) {
gAiBufferLengths[index] = gSamplesPerFrameTarget + SAMPLES_TO_OVERPRODUCE;
}
if (sGameLoopTicked != 0) {
@@ -684,7 +593,7 @@ struct SPTask *create_next_audio_frame_task(void) {
flags = 0;
gAudioCmd = synthesis_execute(gAudioCmd, &writtenCmds, gCurrAiBuffer, gAiBufferLengths[index]);
D_80226EB8 = ((D_80226EB8 + gActiveAudioFrames) * gActiveAudioFrames);
gAudioRandom = ((gAudioRandom + gAudioFrameCount) * gAudioFrameCount);
index = gAudioTaskIndex;
gAudioTask->msgqueue = NULL;
@@ -736,7 +645,7 @@ static void process_sound_request(u32 bits, f32 *pos) {
bankIndex = (bits & SOUNDARGS_MASK_BANK) >> SOUNDARGS_SHIFT_BANK;
soundId = (bits & SOUNDARGS_MASK_SOUNDID) >> SOUNDARGS_SHIFT_SOUNDID;
if (soundId >= sNumSoundsPerBank[bankIndex] || gSoundBankDisabled[bankIndex]) {
if (soundId >= sNumSoundsPerBank[bankIndex] || sSoundBankDisabled[bankIndex]) {
return;
}
@@ -882,9 +791,9 @@ static void func_8031E16C(u8 bankIndex) {
(u32) gSoundBanks[bankIndex][soundIndex].distance + 0x4c * (0xff - val);
}
for (i = 0; i < D_803320C8[bankIndex]; i++) {
for (i = 0; i < sMaxChannelsForSoundBank[bankIndex]; i++) {
if (sp98[i] >= gSoundBanks[bankIndex][soundIndex].priority) {
for (j = D_803320C8[bankIndex] - 1; j > i; j--) {
for (j = sMaxChannelsForSoundBank[bankIndex] - 1; j > i; j--) {
sp98[j] = sp98[j - 1];
sp88[j] = sp88[j - 1];
sp78[j] = sp78[j - 1];
@@ -892,7 +801,7 @@ static void func_8031E16C(u8 bankIndex) {
sp98[i] = gSoundBanks[bankIndex][soundIndex].priority;
sp88[i] = soundIndex;
sp78[i] = gSoundBanks[bankIndex][soundIndex].soundStatus;
i = D_803320C8[bankIndex];
i = sMaxChannelsForSoundBank[bankIndex];
}
}
sp77++;
@@ -901,55 +810,55 @@ static void func_8031E16C(u8 bankIndex) {
}
D_803320BC[bankIndex] = sp77;
D_80360C28[bankIndex] = D_803320C8[bankIndex];
sUsedChannelsForSoundBank[bankIndex] = sMaxChannelsForSoundBank[bankIndex];
for (i = 0; i < D_80360C28[bankIndex]; i++) {
for (soundIndex = 0; soundIndex < D_80360C28[bankIndex]; soundIndex++) {
if (sp88[soundIndex] != 0xff && D_80360C38[bankIndex][i] == sp88[soundIndex]) {
for (i = 0; i < sUsedChannelsForSoundBank[bankIndex]; i++) {
for (soundIndex = 0; soundIndex < sUsedChannelsForSoundBank[bankIndex]; soundIndex++) {
if (sp88[soundIndex] != 0xff && sCurrentSound[bankIndex][i] == sp88[soundIndex]) {
sp88[soundIndex] = 0xff;
soundIndex = 0xfe;
}
}
if (soundIndex != 0xff) {
if (D_80360C38[bankIndex][i] != 0xff) {
if (gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundBits == NO_SOUND) {
if (gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundStatus
if (sCurrentSound[bankIndex][i] != 0xff) {
if (gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundBits == NO_SOUND) {
if (gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundStatus
== SOUND_STATUS_PLAYING) {
gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundStatus =
gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundStatus =
SOUND_STATUS_STOPPED;
func_8031DFE8(bankIndex, D_80360C38[bankIndex][i]);
func_8031DFE8(bankIndex, sCurrentSound[bankIndex][i]);
}
}
val2 = gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundBits
val2 = gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundBits
& (SOUND_LO_BITFLAG_UNK8 | SOUNDARGS_MASK_STATUS);
if (val2 >= (SOUND_LO_BITFLAG_UNK8 | SOUND_STATUS_PLAYING)
&& gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundStatus
&& gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundStatus
!= SOUND_STATUS_STOPPED) {
#ifndef VERSION_JP
func_8031E0E4(bankIndex, D_80360C38[bankIndex][i]);
func_8031E0E4(bankIndex, sCurrentSound[bankIndex][i]);
#endif
gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundBits = NO_SOUND;
gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundStatus = SOUND_STATUS_STOPPED;
func_8031DFE8(bankIndex, D_80360C38[bankIndex][i]);
gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundBits = NO_SOUND;
gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundStatus = SOUND_STATUS_STOPPED;
func_8031DFE8(bankIndex, sCurrentSound[bankIndex][i]);
} else {
if (val2 == SOUND_STATUS_PLAYING
&& gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundStatus
&& gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundStatus
!= SOUND_STATUS_STOPPED) {
gSoundBanks[bankIndex][D_80360C38[bankIndex][i]].soundStatus =
gSoundBanks[bankIndex][sCurrentSound[bankIndex][i]].soundStatus =
SOUND_STATUS_STARTING;
}
}
}
D_80360C38[bankIndex][i] = 0xff;
sCurrentSound[bankIndex][i] = 0xff;
}
}
for (soundIndex = 0; soundIndex < D_80360C28[bankIndex]; soundIndex++) {
for (soundIndex = 0; soundIndex < sUsedChannelsForSoundBank[bankIndex]; soundIndex++) {
if (sp88[soundIndex] != 0xff) {
for (i = 0; i < D_80360C28[bankIndex]; i++) {
if (D_80360C38[bankIndex][i] == 0xff) {
D_80360C38[bankIndex][i] = sp88[soundIndex];
for (i = 0; i < sUsedChannelsForSoundBank[bankIndex]; i++) {
if (sCurrentSound[bankIndex][i] == 0xff) {
sCurrentSound[bankIndex][i] = sp88[soundIndex];
gSoundBanks[bankIndex][sp88[soundIndex]].soundBits =
(gSoundBanks[bankIndex][sp88[soundIndex]].soundBits & ~SOUNDARGS_MASK_STATUS)
+ 1;
@@ -1044,7 +953,7 @@ static f32 get_sound_dynamics(u8 bankIndex, u8 item, f32 arg2) {
if (intensity >= 0.08f)
#endif
{
intensity -= (f32)(D_80226EB8 & 0xf) / US_FLOAT(192.0);
intensity -= (f32)(gAudioRandom & 0xf) / US_FLOAT(192.0);
}
}
} else {
@@ -1060,7 +969,7 @@ static f32 get_sound_freq_scale(u8 bankIndex, u8 item) {
if (!(gSoundBanks[bankIndex][item].soundBits & SOUND_PL_BITFLAG_UNK8)) {
f2 = gSoundBanks[bankIndex][item].distance / AUDIO_MAX_DISTANCE;
if (gSoundBanks[bankIndex][item].soundBits & SOUND_PL_BITFLAG_UNK2) {
f2 += (f32)(D_80226EB8 & 0xff) / US_FLOAT(64.0);
f2 += (f32)(gAudioRandom & 0xff) / US_FLOAT(64.0);
}
} else {
f2 = 0.0f;
@@ -1137,8 +1046,8 @@ void update_game_sound(void) {
for (bankIndex = 0; bankIndex < SOUND_BANK_COUNT; bankIndex++) {
func_8031E16C(bankIndex);
for (j = 0; j < 1; j++) {
index = D_80360C38[bankIndex][j];
for (j = 0; j < MAX_CHANNELS_PER_SOUND; j++) {
index = sCurrentSound[bankIndex][j];
if (index < 0xff && gSoundBanks[bankIndex][index].soundStatus != SOUND_STATUS_STOPPED) {
soundStatus = gSoundBanks[bankIndex][index].soundBits & SOUNDARGS_MASK_STATUS;
soundId = (gSoundBanks[bankIndex][index].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
@@ -1313,8 +1222,8 @@ void update_game_sound(void) {
channelIndex++;
}
// D_80360C28[i] = D_803320C8[i] = 1, so this doesn't do anything
channelIndex += D_803320C8[bankIndex] - D_80360C28[bankIndex];
// sUsedChannelsForSoundBank[i] = sMaxChannelsForSoundBank[i] = 1, so this doesn't do anything
channelIndex += sMaxChannelsForSoundBank[bankIndex] - sUsedChannelsForSoundBank[bankIndex];
}
}
@@ -1326,7 +1235,7 @@ void play_sequence(u8 player, u8 seqId, u16 fadeTimer) {
u8 i;
if (player == 0) {
gPlayer0CurSeqId = seqId & 0x7f;
sPlayer0CurSeqId = seqId & 0x7f;
sBackgroundMusicForDynamics = SEQUENCE_NONE;
sCurrentMusicDynamic = 0xff;
sMusicDynamicDelay = 2;
@@ -1351,7 +1260,7 @@ void play_sequence(u8 player, u8 seqId, u16 fadeTimer) {
void sequence_player_fade_out(u8 player, u16 fadeTimer) {
if (player == 0) {
gPlayer0CurSeqId = SEQUENCE_NONE;
sPlayer0CurSeqId = SEQUENCE_NONE;
}
sequence_player_fade_out_internal(player, fadeTimer);
}
@@ -1396,19 +1305,19 @@ void func_8031F96C(u8 player) {
}
#ifdef NON_MATCHING
void process_level_music_dynamics(void) {
u8 musicDynIndex; // sp57
s16 conditionValues[8]; // sp44
u8 conditionTypes[8]; // sp3C
s16 dur1; // sp3A
s16 dur2; // sp38
u32 conditionBits; // s0
u32 tempBits; // v1
u16 bit; // a1
u8 condIndex; // a0 (same as numConditions?)
u8 i; // s1
s32 conditionBits; // s0
u8 musicDynIndex; // sp57 87
u8 j; // v0
u16 bit2; // s0, v1
s16 conditionValues[8]; // sp44 68
u8 conditionTypes[8]; // sp3C 60
s16 dur1; // sp3A 58
s16 dur2; // sp38 56
u16 bit; // a1 (in first loop), s0, v1
u8 i; // s1
u8 condIndex; // a0, v1
u32 tempBits; // v1
func_8031F96C(0);
func_8031F96C(2);
@@ -1416,7 +1325,7 @@ void process_level_music_dynamics(void) {
if (sMusicDynamicDelay != 0) {
sMusicDynamicDelay--;
} else {
sBackgroundMusicForDynamics = gPlayer0CurSeqId;
sBackgroundMusicForDynamics = sPlayer0CurSeqId;
}
if (sBackgroundMusicForDynamics != sLevelDynamics[gCurrLevelNum][0]) {
@@ -1427,12 +1336,9 @@ void process_level_music_dynamics(void) {
musicDynIndex = sLevelDynamics[gCurrLevelNum][1] & 0xff;
i = 2;
while (conditionBits & 0xff00) {
condIndex = 0;
for (j = 0, bit = 0x8000; j<8; j++, bit = bit>> 1) {
for (j = 0, condIndex = 0, bit = 0x8000; j < 8; j++, bit = bit >> 1) {
if (conditionBits & bit) {
s16 val = sLevelDynamics[gCurrLevelNum][i];
conditionValues[condIndex] = val;
i++;
conditionValues[condIndex] = sLevelDynamics[gCurrLevelNum][i++];
conditionTypes[condIndex] = j;
condIndex++;
}
@@ -1440,7 +1346,6 @@ void process_level_music_dynamics(void) {
for (j = 0; j < condIndex; j++) {
// (having all 'temp' share a single variable affects regalloc)
UNUSED s16 temp;
switch (conditionTypes[j]) {
case MARIO_X_GE: {
s16 temp = gMarioStates[0].pos[0];
@@ -1479,14 +1384,14 @@ void process_level_music_dynamics(void) {
break;
}
case MARIO_IS_IN_AREA: {
s16 temp = gCurrAreaIndex;
if (temp != conditionValues[j])
//s16 temp = gCurrAreaIndex;
if (gCurrAreaIndex != conditionValues[j])
j = condIndex + 1;
break;
}
case MARIO_IS_IN_ROOM: {
s16 temp = gMarioCurrentRoom;
if (temp != conditionValues[j])
//s16 temp = gMarioCurrentRoom;
if (gMarioCurrentRoom != conditionValues[j])
j = condIndex + 1;
break;
}
@@ -1497,7 +1402,8 @@ void process_level_music_dynamics(void) {
// The area matches. Break out of the loop.
tempBits = 0;
} else {
tempBits = sLevelDynamics[gCurrLevelNum][i++];
tempBits = sLevelDynamics[gCurrLevelNum][i];
i++;
musicDynIndex = tempBits & 0xff, tempBits &= 0xff00;
}
@@ -1505,7 +1411,7 @@ void process_level_music_dynamics(void) {
}
if (musicDynIndex != sCurrentMusicDynamic) {
bit2 = 1;
bit = 1;
if (sCurrentMusicDynamic == 0xff) {
dur1 = 1;
dur2 = 1;
@@ -1515,13 +1421,13 @@ void process_level_music_dynamics(void) {
}
for (i = 0; i < CHANNELS_MAX; i++) {
if (sMusicDynamics[musicDynIndex].bits1 & bit2) {
if (sMusicDynamics[musicDynIndex].bits1 & bit) {
fade_channel_volume_scale(0, i, sMusicDynamics[musicDynIndex].volScale1, dur1);
}
if (sMusicDynamics[musicDynIndex].bits2 & bit2) {
if (sMusicDynamics[musicDynIndex].bits2 & bit) {
fade_channel_volume_scale(0, i, sMusicDynamics[musicDynIndex].volScale2, dur2);
}
bit2 <<= 1;
bit <<= 1;
}
sCurrentMusicDynamic = musicDynIndex;
@@ -1581,7 +1487,7 @@ u8 func_803200E4(u16 fadeTimer) {
u8 vol = 0xff;
u8 temp;
if (gPlayer0CurSeqId == SEQUENCE_NONE || gPlayer0CurSeqId == SEQ_EVENT_CUTSCENE_CREDITS) {
if (sPlayer0CurSeqId == SEQUENCE_NONE || sPlayer0CurSeqId == SEQ_EVENT_CUTSCENE_CREDITS) {
return 0xff;
}
@@ -1612,7 +1518,7 @@ u8 func_803200E4(u16 fadeTimer) {
if (vol != 0xff) {
func_8031D838(0, fadeTimer, vol);
} else {
gSequencePlayers[0].volume = sBackgroundMusicDefaultVolume[gPlayer0CurSeqId] / 127.0f;
gSequencePlayers[0].volume = sBackgroundMusicDefaultVolume[sPlayer0CurSeqId] / 127.0f;
func_8031D7B0(0, fadeTimer);
}
}
@@ -1636,8 +1542,8 @@ void sound_init(void) {
gSoundBanks[i][j].soundStatus = SOUND_STATUS_STOPPED;
}
for (j = 0; j < 1; j++) {
D_80360C38[i][j] = 0xff;
for (j = 0; j < MAX_CHANNELS_PER_SOUND; j++) {
sCurrentSound[i][j] = 0xff;
}
D_803320A4[i] = 0;
@@ -1674,7 +1580,7 @@ void sound_init(void) {
sCapVolumeTo40 = FALSE;
D_80332110 = 0;
sUnused80332114 = 0;
gPlayer0CurSeqId = 0xff;
sPlayer0CurSeqId = 0xff;
gSoundMode = SOUND_MODE_STEREO;
sBackgroundMusicQueueSize = 0;
D_8033211C = 0;
@@ -1684,22 +1590,23 @@ void sound_init(void) {
sSoundRequestCount = 0;
}
void unused_8032050C(u8 arg0, u8 *arg1, u8 *arg2, u8 *arg3) {
// (unused)
void get_currently_playing_sound(u8 bankIndex, u8 *numPlayingSounds, u8 *arg2, u8 *soundId) {
u8 i;
u8 counter = 0;
u8 count = 0;
for (i = 0; i < D_803320C8[arg0]; i++) {
if (D_80360C38[arg0][i] != 0xff) {
counter++;
for (i = 0; i < sMaxChannelsForSoundBank[bankIndex]; i++) {
if (sCurrentSound[bankIndex][i] != 0xff) {
count++;
}
}
*arg1 = counter;
*arg2 = D_803320BC[arg0];
if (D_80360C38[arg0][0] != 0xff) {
*arg3 = (u8)(gSoundBanks[arg0][D_80360C38[arg0][0]].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
*numPlayingSounds = count;
*arg2 = D_803320BC[bankIndex];
if (sCurrentSound[bankIndex][0] != 0xff) {
*soundId = (u8)(gSoundBanks[bankIndex][sCurrentSound[bankIndex][0]].soundBits >> SOUNDARGS_SHIFT_SOUNDID);
} else {
*arg3 = 0xff;
*soundId = 0xff;
}
}
@@ -1759,7 +1666,7 @@ void sound_banks_disable(UNUSED u8 player, u16 bankMask) {
for (i = 0; i < SOUND_BANK_COUNT; i++) {
if (bankMask & 1) {
gSoundBankDisabled[i] = TRUE;
sSoundBankDisabled[i] = TRUE;
}
bankMask = bankMask >> 1;
}
@@ -1778,7 +1685,7 @@ void sound_banks_enable(UNUSED u8 player, u16 bankMask) {
for (i = 0; i < SOUND_BANK_COUNT; i++) {
if (bankMask & 1) {
gSoundBankDisabled[i] = FALSE;
sSoundBankDisabled[i] = FALSE;
}
bankMask = bankMask >> 1;
}
@@ -1787,7 +1694,7 @@ void sound_banks_enable(UNUSED u8 player, u16 bankMask) {
u8 unused_803209D8(u8 player, u8 channelIndex, u8 arg2) {
u8 ret = 0;
if (gSequencePlayers[player].channels[channelIndex] != &gSequenceChannelNone) {
gSequencePlayers[player].channels[channelIndex]->unk0b10 = arg2;
gSequencePlayers[player].channels[channelIndex]->stopSomething2 = arg2;
ret = arg2;
}
return ret;
@@ -1815,7 +1722,7 @@ void play_dialog_sound(u8 dialogID) {
#ifndef VERSION_JP
// "You've stepped on the (Wing|Metal|Vanish) Cap Switch"
if (dialogID == 10 || dialogID == 11 || dialogID == 12) {
if (dialogID == DIALOG_010 || dialogID == DIALOG_011 || dialogID == DIALOG_012) {
play_puzzle_jingle();
}
#endif
@@ -1961,7 +1868,7 @@ void play_secondary_music(u8 seqId, u8 bgMusicVolume, u8 volume, u16 fadeTimer)
UNUSED u32 dummy;
sUnused80332118 = 0;
if (gPlayer0CurSeqId == 0xff || gPlayer0CurSeqId == SEQ_MENU_TITLE_SCREEN) {
if (sPlayer0CurSeqId == 0xff || sPlayer0CurSeqId == SEQ_MENU_TITLE_SCREEN) {
return;
}
+3 -3
View File
@@ -1,5 +1,5 @@
#ifndef _AUDIO_EXTERNAL_H
#define _AUDIO_EXTERNAL_H
#ifndef AUDIO_EXTERNAL_H
#define AUDIO_EXTERNAL_H
#include "types.h"
@@ -53,4 +53,4 @@ void audio_set_sound_mode(u8 arg0);
void audio_init(void); // in load.c
#endif /* _AUDIO_EXTERNAL_H */
#endif /* AUDIO_EXTERNAL_H */
+14 -13
View File
@@ -1,18 +1,19 @@
#ifndef _AUDIO_INTERNAL_H
#define _AUDIO_INTERNAL_H
#ifndef AUDIO_INTERNAL_H
#define AUDIO_INTERNAL_H
#include <ultra64.h>
#include "types.h"
#define SEQUENCE_PLAYERS 3
#define LAYERS_MAX 4
#define CHANNELS_MAX 16
#define NO_LAYER ((struct SequenceChannelLayer *)(-1))
#define MUTE_BEHAVIOR_80 0x80
#define MUTE_BEHAVIOR_40 0x40
#define MUTE_BEHAVIOR_20 0x20
#define MUTE_BEHAVIOR_STOP_SCRIPT 0x80 // stop processing sequence/channel scripts
#define MUTE_BEHAVIOR_STOP_NOTES 0x40 // prevent further notes from playing
#define MUTE_BEHAVIOR_SOFTEN 0x20 // lower volume, by default to half
#define SEQUENCE_PLAYER_STATE_0 0
#define SEQUENCE_PLAYER_STATE_FADE_OUT 1
@@ -151,7 +152,7 @@ struct Instrument
struct Drum
{
u8 releaseRate;
u8 unk1;
u8 pan;
u8 loaded;
struct AudioBankSound sound;
struct AdsrEnvelope *envelope;
@@ -191,7 +192,7 @@ struct SequencePlayer
/*0x003*/ u8 noteAllocPolicy;
/*0x004*/ u8 muteBehavior;
/*0x005*/ u8 seqId;
/*0x006*/ u8 anyBank[1]; // must be an array to get a comparison
/*0x006*/ u8 defaultBank[1]; // must be an array to get a comparison
// to match; other u8's might also be part of that array
/*0x007*/ u8 loadingBankId;
/*0x008*/ u8 loadingBankNumInstruments;
@@ -260,7 +261,7 @@ struct SequenceChannel
/*0x00*/ u8 enabled : 1;
/*0x00*/ u8 finished : 1;
/*0x00*/ u8 stopScript : 1;
/*0x00*/ u8 unk0b10 : 1;
/*0x00*/ u8 stopSomething2 : 1; // sets SequenceChannelLayer.stopSomething
/*0x00*/ u8 hasInstrument : 1;
/*0x00*/ u8 stereoHeadsetEffects : 1;
/*0x00*/ u8 largeNotes : 1; // notes specify duration and velocity
@@ -292,7 +293,7 @@ struct SequenceChannel
/*0x38*/ struct SequenceChannelLayer *layerUnused; // never read
/*0x3C*/ struct Instrument *instrument;
/*0x40*/ struct SequencePlayer *seqPlayer;
/*0x44*/ struct SequenceChannelLayer *layers[4];
/*0x44*/ struct SequenceChannelLayer *layers[LAYERS_MAX];
/*0x54*/ s8 soundScriptIO[8]; // bridge between sound script and audio lib. For player 2,
// [0] contains enabled, [4] contains sound ID, [5] contains reverb adjustment
/*0x5C*/ struct M64ScriptState scriptState;
@@ -304,9 +305,9 @@ struct SequenceChannelLayer // Maybe SequenceTrack?
{
/*0x00*/ u8 enabled : 1;
/*0x00*/ u8 finished : 1;
/*0x00*/ u8 unk0b20 : 1;
/*0x00*/ u8 unk0b10 : 1;
/*0x01*/ u8 unk1;
/*0x00*/ u8 stopSomething : 1; // ?
/*0x00*/ u8 continuousNotes : 1; // keep the same note for consecutive notes with the same sound
/*0x01*/ u8 status;
/*0x02*/ u8 noteDuration; // set to 0x80
/*0x03*/ u8 portamentoTargetNote;
/*0x04*/ struct Portamento portamento;
@@ -408,4 +409,4 @@ struct AudioSessionSettings
/*0x18*/ u32 temporaryBankMem;
}; // size = 0x1C
#endif /* _AUDIO_INTERNAL_H */
#endif /* AUDIO_INTERNAL_H */
+11 -11
View File
@@ -23,9 +23,9 @@ struct SequencePlayer gSequencePlayers[SEQUENCE_PLAYERS];
struct SequenceChannel gSequenceChannels[32];
#ifdef VERSION_JP
struct SequenceChannelLayer D_802245D8[48];
struct SequenceChannelLayer gSequenceLayers[48];
#else
struct SequenceChannelLayer D_802245D8[52];
struct SequenceChannelLayer gSequenceLayers[52];
#endif
struct SequenceChannel gSequenceChannelNone;
@@ -212,7 +212,7 @@ void *dma_sample_data(uintptr_t devAddr, u32 size, s32 arg2, u8 *arg3) {
}
// called from sound_reset
void func_8031758C(UNUSED s32 arg0) {
void init_sample_dma_buffers(UNUSED s32 arg0) {
s32 i;
s32 j;
@@ -287,7 +287,7 @@ static void unused_80317844(void) {
}
#ifdef NON_MATCHING
void func_8031784C(struct AudioBank *mem, u8 *offset, u32 numInstruments, u32 numDrums) {
void patch_audio_bank(struct AudioBank *mem, u8 *offset, u32 numInstruments, u32 numDrums) {
// Make pointers into real pointers rather than indices
struct Instrument *instrument;
struct Instrument **itInstrs;
@@ -393,7 +393,7 @@ void func_8031784C(struct AudioBank *mem, u8 *offset, u32 numInstruments, u32 nu
}
#else
GLOBAL_ASM("asm/non_matchings/func_8031784C.s")
GLOBAL_ASM("asm/non_matchings/patch_audio_bank.s")
#endif
struct AudioBank *bank_load_immediate(s32 bankId, s32 arg1) {
@@ -419,7 +419,7 @@ struct AudioBank *bank_load_immediate(s32 bankId, s32 arg1) {
numInstruments = buf[0];
numDrums = buf[1];
audio_dma_copy_immediate((uintptr_t)(ctlData + 0x10), ret, alloc);
func_8031784C(ret, gAlTbl->seqArray[bankId].offset, numInstruments, numDrums);
patch_audio_bank(ret, gAlTbl->seqArray[bankId].offset, numInstruments, numDrums);
gCtlEntries[bankId].numInstruments = (u8) numInstruments;
gCtlEntries[bankId].numDrums = (u8) numDrums;
gCtlEntries[bankId].instruments = ret->instruments;
@@ -635,11 +635,11 @@ void load_sequence_internal(u32 player, u32 seqId, s32 loadAsync) {
// @bug This should set the last bank (i.e. the first in the JSON)
// as default, not the missing one. This code path never gets
// taken, though -- all sequence loading is synchronous.
seqPlayer->anyBank[0] = bankId;
} else if (load_banks_immediate(seqId, &seqPlayer->anyBank[0]) == NULL) {
seqPlayer->defaultBank[0] = bankId;
} else if (load_banks_immediate(seqId, &seqPlayer->defaultBank[0]) == NULL) {
return;
}
} else if (load_banks_immediate(seqId, &seqPlayer->anyBank[0]) == NULL) {
} else if (load_banks_immediate(seqId, &seqPlayer->defaultBank[0]) == NULL) {
return;
}
@@ -704,7 +704,7 @@ void audio_init() {
gAiBufferLengths[i] = 0x00a0;
}
gActiveAudioFrames = 0;
gAudioFrameCount = 0;
gAudioTaskIndex = 0;
gCurrAiBufferIndex = 0;
gSoundMode = 0;
@@ -763,6 +763,6 @@ void audio_init() {
gAlBankSets = soundAlloc(&gAudioInitPool, 0x100);
audio_dma_copy_immediate((uintptr_t) gBankSetsData, gAlBankSets, 0x100);
func_8031D4B8();
init_sequence_players();
gAudioLoadLock = AUDIO_LOCK_NOT_LOADING;
}
+7 -7
View File
@@ -1,5 +1,5 @@
#ifndef _AUDIO_LOAD_H
#define _AUDIO_LOAD_H
#ifndef AUDIO_LOAD_H
#define AUDIO_LOAD_H
#include "internal.h"
@@ -21,9 +21,9 @@ extern struct SequencePlayer gSequencePlayers[SEQUENCE_PLAYERS];
extern struct SequenceChannel gSequenceChannels[32];
#ifdef VERSION_JP
extern struct SequenceChannelLayer D_802245D8[48];
extern struct SequenceChannelLayer gSequenceLayers[48];
#else
extern struct SequenceChannelLayer D_802245D8[52];
extern struct SequenceChannelLayer gSequenceLayers[52];
#endif
extern struct SequenceChannel gSequenceChannelNone;
@@ -39,9 +39,9 @@ extern u8 *gAlBankSets;
void audio_dma_partial_copy_async(uintptr_t *devAddr, u8 **vAddr, ssize_t *remaining, OSMesgQueue *queue, OSIoMesg *mesg);
void decrease_sample_dma_ttls(void);
void *dma_sample_data(uintptr_t devAddr, u32 size, s32 arg2, u8 *arg3);
void func_8031758C(s32 arg0);
void func_8031784C(struct AudioBank *mem, u8 *offset, u32 numInstruments, u32 numDrums);
void init_sample_dma_buffers(s32 arg0);
void patch_audio_bank(struct AudioBank *mem, u8 *offset, u32 numInstruments, u32 numDrums);
void preload_sequence(u32 seqId, u8 preloadMask);
void load_sequence(u32 player, u32 seqId, s32 loadAsync);
#endif /* _AUDIO_LOAD_H */
#endif /* AUDIO_LOAD_H */
+19 -14
View File
@@ -47,7 +47,7 @@ u8 gSeqLoadStatus[0x100];
u8 gAudioUnusedBuffer[0x1000];
extern s32 D_80226D6C;
extern s32 gMaxAudioCmds;
void reset_bank_and_seq_load_status(void) {
s32 i;
@@ -109,7 +109,7 @@ void *soundAlloc(struct SoundAllocPool *pool, u32 size) {
}
void sound_alloc_pool_init(struct SoundAllocPool *pool, void *memAddr, u32 size) {
pool->cur = pool->start = (u8 *) (((uintptr_t) memAddr + 0xf) & -0x10);
pool->cur = pool->start = (u8 *) ALIGN16((uintptr_t) memAddr);
pool->size = size;
pool->unused = 0;
}
@@ -374,9 +374,9 @@ void decrease_reverb_gain(void) {
* Waits until a specified number of audio frames have been created
*/
void wait_for_audio_frames(s32 frames) {
gActiveAudioFrames = 0;
// Sound thread will update gActiveAudioFrames
while (gActiveAudioFrames < frames) {
gAudioFrameCount = 0;
// Sound thread will update gAudioFrameCount
while (gAudioFrameCount < frames) {
// spin
}
}
@@ -425,8 +425,13 @@ void audio_reset_session(struct AudioSessionSettings *preset) {
}
}
// Wait for the reverb to finish as well
decrease_reverb_gain();
wait_for_audio_frames(3);
// The audio interface is double buffered; thus, we have to take the
// load lock for 2 frames for the buffers to free up before we can
// repurpose memory. Make that 3 frames, just in case.
gAudioLoadLock = AUDIO_LOCK_LOADING;
wait_for_audio_frames(3);
@@ -450,7 +455,7 @@ void audio_reset_session(struct AudioSessionSettings *preset) {
reverbWindowSize = preset->reverbWindowSize;
gAiFrequency = osAiSetFrequency(preset->frequency);
gMaxSimultaneousNotes = preset->maxSimultaneousNotes;
D_80226D74 = ALIGN16(gAiFrequency / 60);
gSamplesPerFrameTarget = ALIGN16(gAiFrequency / 60);
gReverbDownsampleRate = preset->reverbDownsampleRate;
switch (gReverbDownsampleRate) {
@@ -475,9 +480,9 @@ void audio_reset_session(struct AudioSessionSettings *preset) {
gReverbDownsampleRate = preset->reverbDownsampleRate;
gVolume = preset->volume;
gMinAiBufferLength = D_80226D74 - 0x10;
updatesPerFrame = D_80226D74 / 160 + 1;
gAudioUpdatesPerFrame = D_80226D74 / 160 + 1;
gMinAiBufferLength = gSamplesPerFrameTarget - 0x10;
updatesPerFrame = gSamplesPerFrameTarget / 160 + 1;
gAudioUpdatesPerFrame = gSamplesPerFrameTarget / 160 + 1;
// Compute conversion ratio from the internal unit tatums/tick to the
// external beats/minute (JP) or tatums/minute (US). In practice this is
@@ -488,7 +493,7 @@ void audio_reset_session(struct AudioSessionSettings *preset) {
gTempoInternalToExternal = (u32)(updatesPerFrame * 2880000.0f / gTatumsPerBeat / 16.713f);
#endif
D_80226D6C = gMaxSimultaneousNotes * 20 * updatesPerFrame + 320;
gMaxAudioCmds = gMaxSimultaneousNotes * 20 * updatesPerFrame + 320;
persistentMem = DOUBLE_SIZE_ON_64_BIT(preset->persistentBankMem + preset->persistentSeqMem);
temporaryMem = DOUBLE_SIZE_ON_64_BIT(preset->temporaryBankMem + preset->temporarySeqMem);
totalMem = persistentMem + temporaryMem;
@@ -510,7 +515,7 @@ void audio_reset_session(struct AudioSessionSettings *preset) {
reset_bank_and_seq_load_status();
for (j = 0; j < 2; j++) {
gAudioCmdBuffers[j] = soundAlloc(&gNotesAndBuffersPool, D_80226D6C * 8);
gAudioCmdBuffers[j] = soundAlloc(&gNotesAndBuffersPool, gMaxAudioCmds * sizeof(u64));
}
gNotes = soundAlloc(&gNotesAndBuffersPool, gMaxSimultaneousNotes * sizeof(struct Note));
@@ -537,17 +542,17 @@ void audio_reset_session(struct AudioSessionSettings *preset) {
gSynthesisReverb.unk24 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
gSynthesisReverb.unk28 = soundAlloc(&gNotesAndBuffersPool, 16 * sizeof(s16));
for (i = 0; i < gAudioUpdatesPerFrame; i++) {
mem = soundAlloc(&gNotesAndBuffersPool, 0x280);
mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
gSynthesisReverb.items[0][i].toDownsampleLeft = mem;
gSynthesisReverb.items[0][i].toDownsampleRight = mem + 0xA0;
mem = soundAlloc(&gNotesAndBuffersPool, 0x280);
mem = soundAlloc(&gNotesAndBuffersPool, DEFAULT_LEN_2CH);
gSynthesisReverb.items[1][i].toDownsampleLeft = mem;
gSynthesisReverb.items[1][i].toDownsampleRight = mem + 0xA0;
}
}
}
func_8031758C(gMaxSimultaneousNotes);
init_sample_dma_buffers(gMaxSimultaneousNotes);
osWritebackDCacheAll();
if (gAudioLoadLock != AUDIO_LOCK_UNINITIALIZED) {
gAudioLoadLock = AUDIO_LOCK_NOT_LOADING;
+3 -4
View File
@@ -1,5 +1,5 @@
#ifndef _AUDIO_MEMORY_H
#define _AUDIO_MEMORY_H
#ifndef AUDIO_MEMORY_H
#define AUDIO_MEMORY_H
#include "internal.h"
@@ -49,7 +49,6 @@ struct SoundMultiPool
extern u8 gAudioHeap[];
extern s16 gVolume;
extern s8 gReverbDownsampleRate;
extern u8 sReverbDownsampleRateLog;
extern struct SoundAllocPool gAudioInitPool;
extern struct SoundAllocPool gNotesAndBuffersPool;
extern struct SoundMultiPool gSeqLoadedPool;
@@ -63,4 +62,4 @@ void *alloc_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 size, s32 arg
void *get_bank_or_seq(struct SoundMultiPool *arg0, s32 arg1, s32 arg2);
void audio_reset_session(struct AudioSessionSettings *preset);
#endif /* _AUDIO_MEMORY_H */
#endif /* AUDIO_MEMORY_H */
+15 -16
View File
@@ -11,7 +11,7 @@
s32 note_init_for_layer(struct Note *note, struct SequenceChannelLayer *seqLayer);
void func_80318870(struct Note *note) {
void note_init(struct Note *note) {
if (note->parentLayer->adsr.releaseRate == 0) {
adsr_init(&note->adsr, note->parentLayer->seqChannel->adsr.envelope, &note->adsrVolScale);
} else {
@@ -26,7 +26,7 @@ void note_disable2(struct Note *note) {
note_disable(note);
}
void func_80318908(void) {
void process_notes(void) {
f32 scale;
f32 frequency;
u8 reverb;
@@ -144,7 +144,7 @@ void seq_channel_layer_decay_release_internal(struct SequenceChannelLayer *seqLa
return;
}
seqLayer->unk1 = 0;
seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED;
if (note->adsr.state != ADSR_STATE_DECAY) {
attributes->freqScale = seqLayer->noteFreqScale;
attributes->velocity = seqLayer->noteVelocity;
@@ -183,8 +183,7 @@ void seq_channel_layer_note_release(struct SequenceChannelLayer *seqLayer) {
seq_channel_layer_decay_release_internal(seqLayer, ADSR_STATE_RELEASE);
}
// wave synthesizer
void func_80318F04(struct Note *note, struct SequenceChannelLayer *seqLayer) {
void build_synthetic_wave(struct Note *note, struct SequenceChannelLayer *seqLayer) {
s32 i;
s32 j;
s32 pos;
@@ -239,9 +238,9 @@ void func_80318F04(struct Note *note, struct SequenceChannelLayer *seqLayer) {
osWritebackDCache(note->synthesisBuffers->samples, sizeof(note->synthesisBuffers->samples));
}
void func_80319164(struct Note *note, struct SequenceChannelLayer *seqLayer) {
void init_synthetic_wave(struct Note *note, struct SequenceChannelLayer *seqLayer) {
s32 sampleCount = note->sampleCount;
func_80318F04(note, seqLayer);
build_synthetic_wave(note, seqLayer);
if (sampleCount != 0) {
note->samplePosInt *= note->sampleCount / sampleCount;
} else {
@@ -422,14 +421,14 @@ s32 note_init_for_layer(struct Note *note, struct SequenceChannelLayer *seqLayer
note->bankId = seqLayer->seqChannel->bankId;
note->stereoHeadsetEffects = seqLayer->seqChannel->stereoHeadsetEffects;
note->sound = seqLayer->sound;
seqLayer->unk1 = 3;
seqLayer->status = SOUND_LOAD_STATUS_DISCARDABLE; // "loaded"
seqLayer->note = note;
seqLayer->seqChannel->noteUnused = note;
seqLayer->seqChannel->layerUnused = seqLayer;
if (note->sound == NULL) {
func_80318F04(note, seqLayer);
build_synthetic_wave(note, seqLayer);
}
func_80318870(note);
note_init(note);
return FALSE;
}
@@ -495,7 +494,7 @@ struct Note *alloc_note(struct SequenceChannelLayer *seqLayer) {
if (!(ret = alloc_note_from_disabled(&seqLayer->seqChannel->notePool, seqLayer))
&& !(ret = alloc_note_from_decaying(&seqLayer->seqChannel->notePool, seqLayer))
&& !(ret = alloc_note_from_active(&seqLayer->seqChannel->notePool, seqLayer))) {
seqLayer->unk1 = 0;
seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED;
return NULL;
}
return ret;
@@ -508,7 +507,7 @@ struct Note *alloc_note(struct SequenceChannelLayer *seqLayer) {
&& !(ret = alloc_note_from_decaying(&seqLayer->seqChannel->seqPlayer->notePool, seqLayer))
&& !(ret = alloc_note_from_active(&seqLayer->seqChannel->notePool, seqLayer))
&& !(ret = alloc_note_from_active(&seqLayer->seqChannel->seqPlayer->notePool, seqLayer))) {
seqLayer->unk1 = 0;
seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED;
return NULL;
}
return ret;
@@ -518,7 +517,7 @@ struct Note *alloc_note(struct SequenceChannelLayer *seqLayer) {
if (!(ret = alloc_note_from_disabled(&gNoteFreeLists, seqLayer))
&& !(ret = alloc_note_from_decaying(&gNoteFreeLists, seqLayer))
&& !(ret = alloc_note_from_active(&gNoteFreeLists, seqLayer))) {
seqLayer->unk1 = 0;
seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED;
return NULL;
}
return ret;
@@ -533,13 +532,13 @@ struct Note *alloc_note(struct SequenceChannelLayer *seqLayer) {
&& !(ret = alloc_note_from_active(&seqLayer->seqChannel->notePool, seqLayer))
&& !(ret = alloc_note_from_active(&seqLayer->seqChannel->seqPlayer->notePool, seqLayer))
&& !(ret = alloc_note_from_active(&gNoteFreeLists, seqLayer))) {
seqLayer->unk1 = 0;
seqLayer->status = SOUND_LOAD_STATUS_NOT_LOADED;
return NULL;
}
return ret;
}
void func_80319BC8(void) {
void reclaim_notes(void) {
struct Note *note;
s32 i;
s32 cond;
@@ -559,7 +558,7 @@ void func_80319BC8(void) {
note->priority = NOTE_PRIORITY_STOPPING;
} else if (note->parentLayer->seqChannel->seqPlayer->muted) {
if (note->parentLayer->seqChannel->muteBehavior
& (MUTE_BEHAVIOR_80 | MUTE_BEHAVIOR_40)) {
& (MUTE_BEHAVIOR_STOP_SCRIPT | MUTE_BEHAVIOR_STOP_NOTES)) {
cond = TRUE;
}
} else {
+3 -3
View File
@@ -14,10 +14,10 @@
#define NOTE_ALLOC_SEQ 4
#define NOTE_ALLOC_GLOBAL_FREELIST 8
void func_80318908(void);
void process_notes(void);
void seq_channel_layer_note_decay(struct SequenceChannelLayer *seqLayer);
void seq_channel_layer_note_release(struct SequenceChannelLayer *seqLayer);
void func_80319164(struct Note *note, struct SequenceChannelLayer *seqLayer);
void init_synthetic_wave(struct Note *note, struct SequenceChannelLayer *seqLayer);
void init_note_lists(struct NotePool *pool);
void init_note_free_list(void);
void note_pool_clear(struct NotePool *pool);
@@ -25,7 +25,7 @@ void note_pool_fill(struct NotePool *pool, s32 count);
void audio_list_push_front(struct AudioListItem *list, struct AudioListItem *item);
void audio_list_remove(struct AudioListItem *item);
struct Note *alloc_note(struct SequenceChannelLayer *seqLayer);
void func_80319BC8(void);
void reclaim_notes(void);
void note_init_all(void);
+293 -279
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -11,6 +11,6 @@ void audio_list_push_back(struct AudioListItem *list, struct AudioListItem *item
void *audio_list_pop_back(struct AudioListItem *list);
void process_sequences(s32 iterationsRemaining);
void init_sequence_player(u32 player);
void func_8031D4B8(void);
void init_sequence_players(void);
#endif /* _AUDIO_SEQPLAYER_H */
+6 -9
View File
@@ -21,9 +21,6 @@
#define DMEM_ADDR_WET_LEFT_CH 0x740
#define DMEM_ADDR_WET_RIGHT_CH 0x880
#define DEFAULT_LEN_1CH 0x140
#define DEFAULT_LEN_2CH 0x280
#define aSetLoadBufferPair(pkt, c, off) \
aSetBuffer(pkt, 0, c + DMEM_ADDR_WET_LEFT_CH, 0, DEFAULT_LEN_1CH - c); \
aLoadBuffer(pkt, VIRTUAL_TO_PHYSICAL2(&gSynthesisReverb.ringBuffer.left[off])); \
@@ -49,7 +46,7 @@ struct VolumeChange {
};
u64 *synthesis_do_one_audio_update(u16 *aiBuf, s32 bufLen, u64 *cmd, u32 updateIndex);
u64 *process_notes(u16 *aiBuf, s32 bufLen, u64 *cmd);
u64 *synthesis_process_notes(u16 *aiBuf, s32 bufLen, u64 *cmd);
u64 *load_wave_samples(u64 *cmd, struct Note *note, s32 nSamplesToLoad);
u64 *final_resample(u64 *cmd, struct Note *note, s32 count, u16 pitch, u16 dmemIn, u32 flags);
u64 *process_envelope(u64 *cmd, struct Note *note, s32 nSamples, u16 inBuf, s32 headsetPanSettings,
@@ -185,7 +182,7 @@ u64 *synthesis_do_one_audio_update(u16 *aiBuf, s32 bufLen, u64 *cmd, u32 updateI
if (gSynthesisReverb.useReverb == 0) {
aClearBuffer(cmd++, DMEM_ADDR_LEFT_CH, DEFAULT_LEN_2CH);
cmd = process_notes(aiBuf, bufLen, cmd);
cmd = synthesis_process_notes(aiBuf, bufLen, cmd);
} else {
if (gReverbDownsampleRate == 1) {
// Put the oldest samples in the ring buffer into the wet channels
@@ -224,7 +221,7 @@ u64 *synthesis_do_one_audio_update(u16 *aiBuf, s32 bufLen, u64 *cmd, u32 updateI
/*out*/ DMEM_ADDR_LEFT_CH);
aDMEMMove(cmd++, DMEM_ADDR_LEFT_CH, DMEM_ADDR_WET_LEFT_CH, DEFAULT_LEN_2CH);
}
cmd = process_notes(aiBuf, bufLen, cmd);
cmd = synthesis_process_notes(aiBuf, bufLen, cmd);
if (gReverbDownsampleRate == 1) {
aSetSaveBufferPair(cmd++, 0, v1->lengths[0], v1->startPos);
if (v1->lengths[1] != 0) {
@@ -246,7 +243,7 @@ u64 *synthesis_do_one_audio_update(u16 *aiBuf, s32 bufLen, u64 *cmd, u32 updateI
}
#ifdef NON_MATCHING
u64 *process_notes(u16 *aiBuf, s32 bufLen, u64 *cmd) {
u64 *synthesis_process_notes(u16 *aiBuf, s32 bufLen, u64 *cmd) {
s32 noteIndex; // sp174
struct Note *note; // s7
struct AudioBankSample *audioBookSample; // sp164
@@ -571,9 +568,9 @@ u64 *process_notes(u16 *aiBuf, s32 bufLen, u64 *cmd) {
}
#elif defined(VERSION_JP)
GLOBAL_ASM("asm/non_matchings/process_notes_jp.s")
GLOBAL_ASM("asm/non_matchings/synthesis_process_notes_jp.s")
#else
GLOBAL_ASM("asm/non_matchings/process_notes_us.s")
GLOBAL_ASM("asm/non_matchings/synthesis_process_notes_us.s")
#endif
u64 *load_wave_samples(u64 *cmd, struct Note *note, s32 nSamplesToLoad) {
+6 -3
View File
@@ -1,8 +1,11 @@
#ifndef _AUDIO_SYNTHESIS_H
#define _AUDIO_SYNTHESIS_H
#ifndef AUDIO_SYNTHESIS_H
#define AUDIO_SYNTHESIS_H
#include "internal.h"
#define DEFAULT_LEN_1CH 0x140
#define DEFAULT_LEN_2CH 0x280
#define MAX_UPDATES_PER_FRAME 4
struct ReverbRingBufferItem
@@ -46,4 +49,4 @@ void note_set_frequency(struct Note *note, f32 frequency);
void note_enable(struct Note *note);
void note_disable(struct Note *note);
#endif /* _AUDIO_SYNTHESIS_H */
#endif /* AUDIO_SYNTHESIS_H */
+1 -1
View File
@@ -3,7 +3,7 @@
#include "sm64.h"
// 0x70800 bytes
#if BUGFIXES_CRITICAL
#ifdef AVOID_UB
u16 gFrameBuffers[3][SCREEN_WIDTH * SCREEN_HEIGHT];
#else
u16 gFrameBuffer0[SCREEN_WIDTH * SCREEN_HEIGHT];
+2 -2
View File
@@ -3,8 +3,8 @@
// level_script.c assumes that the frame buffers are adjacent, while game.c's
// -g codegen implies that they are separate variables. This is impossible to
// reconcile without undefined behavior. Avoid that on non-IDO.
#if BUGFIXES_CRITICAL
// reconcile without undefined behavior. Avoid that when possible.
#ifdef AVOID_UB
extern u16 gFrameBuffers[3][SCREEN_WIDTH * SCREEN_HEIGHT];
#define gFrameBuffer0 gFrameBuffers[0]
#define gFrameBuffer1 gFrameBuffers[1]
+5
View File
@@ -0,0 +1,5 @@
#include <ultra64.h>
#include "zbuffer.h"
ALIGNED8 u16 gZBuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
+9
View File
@@ -0,0 +1,9 @@
#ifndef ZBUFFER_H
#define ZBUFFER_H
#include "types.h"
#include "config.h"
extern u16 gZBuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
#endif
+2 -2
View File
@@ -628,7 +628,7 @@ static s32 beh_cmd_scale(void) {
return BEH_CONTINUE;
}
static s32 beh_cmd_obj_set_gravity(void) {
static s32 beh_cmd_obj_set_physics(void) {
UNUSED f32 sp04, sp00;
gCurrentObject->oWallHitboxRadius = (f32)(s16)(gBehCommand[1] >> 16);
@@ -731,7 +731,7 @@ static BehCommandProc BehaviorJumpTable[] = {
beh_cmd_obj_set_pos,
beh_cmd_obj_set_float2,
beh_cmd_interact_type,
beh_cmd_obj_set_gravity,
beh_cmd_obj_set_physics,
Behavior31,
beh_cmd_scale,
beh_cmd_obj_bit_clear_int32,
+3
View File
@@ -34,6 +34,9 @@ extern Vec3s gVec3sOne;
// Whether the node type has a function pointer of type GraphNodeFunc
#define GRAPH_NODE_TYPE_FUNCTIONAL 0x100
// Type used for Bowser and an unused geo function in obj_behaviors.c
#define GRAPH_NODE_TYPE_400 0x400
// The discriminant for different types of geo nodes
#define GRAPH_NODE_TYPE_ROOT 0x001
#define GRAPH_NODE_TYPE_ORTHO_PROJECTION 0x002
+1 -1
View File
@@ -3,9 +3,9 @@
#include "sm64.h"
#include "audio/external.h"
#include "buffers/framebuffers.h"
#include "buffers/zbuffer.h"
#include "game/area.h"
#include "game/display.h"
#include "game/game.h"
#include "game/mario.h"
#include "game/memory.h"
#include "game/object_helpers.h"
+3 -1
View File
@@ -568,7 +568,9 @@ void mtxf_mul_vec3s(Mat4 mtx, Vec3s b) {
* and no crashes occur.
*/
void mtxf_to_mtx(Mtx *dest, Mat4 src) {
#if ENDIAN_IND
#ifdef AVOID_UB
// Avoid type-casting which is technically UB by calling the equivalent
// guMtxF2L function. This helps little-endian systems, as well.
guMtxF2L(src, dest);
#else
s32 asFixedPoint;
+1 -1
View File
@@ -14,7 +14,7 @@
* Thus, for non-IDO compilers we use the standard-compliant version.
*/
extern f32 gSineTable[];
#if BUGFIXES_CRITICAL
#ifdef AVOID_UB
#define gCosineTable (gSineTable + 0x400)
#else
extern f32 gCosineTable[];
+17 -17
View File
@@ -198,7 +198,7 @@ void func_8027A7C4(void) {
if (gCurrentArea != NULL) {
geo_call_global_function_nodes(gCurrentArea->unk04, GEO_CONTEXT_AREA_UNLOAD);
gCurrentArea = NULL;
gWarpTransition.isActive = 0;
gWarpTransition.isActive = FALSE;
}
for (i = 0; i < 8; i++) {
@@ -235,7 +235,7 @@ void func_8027A998(void) {
gCurrentArea->flags = 0;
gCurrentArea = NULL;
gWarpTransition.isActive = 0;
gWarpTransition.isActive = FALSE;
}
}
@@ -298,42 +298,42 @@ void play_transition(s16 transType, s16 time, u8 red, u8 green, u8 blue) {
red = gWarpTransRed, green = gWarpTransGreen, blue = gWarpTransBlue;
}
if (transType < 8) {
if (transType < 8) { // if transition is RGB
gWarpTransition.data.red = red;
gWarpTransition.data.green = green;
gWarpTransition.data.blue = blue;
} else {
} else { // if transition is textured
gWarpTransition.data.red = red;
gWarpTransition.data.green = green;
gWarpTransition.data.blue = blue;
// Both the start and end circles are always located in the middle of the screen.
// Both the start and end textured transition are always located in the middle of the screen.
// If you really wanted to, you could place the start at one corner and the end at
// the opposite corner. This will make the transition image look like it is moving
// across the screen.
gWarpTransition.data.startCircleX = 160;
gWarpTransition.data.startCircleY = 120;
gWarpTransition.data.endCircleX = 160;
gWarpTransition.data.endCircleY = 120;
gWarpTransition.data.startTexX = SCREEN_WIDTH / 2;
gWarpTransition.data.startTexY = SCREEN_HEIGHT / 2;
gWarpTransition.data.endTexX = SCREEN_WIDTH / 2;
gWarpTransition.data.endTexY = SCREEN_HEIGHT / 2;
gWarpTransition.data.unk10 = 0;
gWarpTransition.data.texTimer = 0;
if (transType & 1) // Is the image fading in?
{
gWarpTransition.data.startCircleRadius = 320;
gWarpTransition.data.startTexRadius = SCREEN_WIDTH;
if (transType >= 0x0F) {
gWarpTransition.data.endCircleRadius = 16;
gWarpTransition.data.endTexRadius = 16;
} else {
gWarpTransition.data.endCircleRadius = 0;
gWarpTransition.data.endTexRadius = 0;
}
} else // The image is fading out. (Reverses start & end circles)
{
if (transType >= 0x0E) {
gWarpTransition.data.startCircleRadius = 16;
gWarpTransition.data.startTexRadius = 16;
} else {
gWarpTransition.data.startCircleRadius = 0;
gWarpTransition.data.startTexRadius = 0;
}
gWarpTransition.data.endCircleRadius = 320;
gWarpTransition.data.endTexRadius = SCREEN_WIDTH;
}
}
}
@@ -378,7 +378,7 @@ void render_game(void) {
if (gWarpTransition.isActive) {
if (gWarpTransDelay == 0) {
gWarpTransition.isActive = !func_802CC108(0, gWarpTransition.type, gWarpTransition.time,
gWarpTransition.isActive = !render_screen_transition(0, gWarpTransition.type, gWarpTransition.time,
&gWarpTransition.data);
if (!gWarpTransition.isActive) {
if (gWarpTransition.type & 1) {
+22 -96
View File
@@ -3,95 +3,6 @@
#include "types.h"
enum CourseNum
{
COURSE_NONE, // (0) Overworld (Castle Grounds, etc)
COURSE_MIN,
/* -------------- Main Courses -------------- */
COURSE_STAGES_MIN = COURSE_MIN,
COURSE_BOB = COURSE_STAGES_MIN, // (1) Bob Omb Battlefield
COURSE_WF, // (2) Whomp's Fortress
COURSE_JRB, // (3) Jolly Rodger's Bay
COURSE_CCM, // (4) Cool Cool Mountain
COURSE_BBH, // (5) Big Boo's Haunt
COURSE_HMC, // (6) Hazy Maze Cave
COURSE_LLL, // (7) Lethal Lava Land
COURSE_SSL, // (8) Shifting Sand Land
COURSE_DDD, // (9) Dire Dire Docks
COURSE_SL, // (10) Snowman's Land
COURSE_WDW, // (11) Wet Dry World
COURSE_TTM, // (12) Tall Tall Mountain
COURSE_THI, // (13) Tiny Huge Island
COURSE_TTC, // (14) Tick Tock Clock
COURSE_RR, // (15) Rainbow Ride
COURSE_BONUS_STAGES,
COURSE_STAGES_MAX = COURSE_BONUS_STAGES - 1,
COURSE_STAGES_COUNT = COURSE_STAGES_MAX,
/* -------------- Bonus Courses -------------- */
COURSE_BITDW, // (16) Bowser in the Dark World
COURSE_BITFS, // (17) Bowser in the Fire Sea
COURSE_BITS, // (18) Bowser in the Sky
COURSE_PSS, // (19) Princess's Secret Slide
COURSE_CAP_COURSES,
COURSE_COTMC = COURSE_CAP_COURSES, // (20) Cavern of the Metal Cap
COURSE_TOTWC, // (21) Tower of the Wing Cap
COURSE_VCUTM, // (22) Vanish Cap Under the Moat
COURSE_WMOTR, // (23) Winged Mario over the Rainbow
COURSE_SA, // (24) Secret Aquarium
COURSE_CAKE_END, // (25) The End (Cake Scene)
COURSE_AFTER_END,
COURSE_MAX = COURSE_AFTER_END - 1,
COURSE_COUNT = COURSE_MAX
};
#define COURSE_IS_MAIN_COURSE(cmd) (cmd >= COURSE_STAGES_MIN && cmd <= COURSE_STAGES_MAX)
enum LevelNum
{
LEVEL_NONE, // not indexed
LEVEL_MIN,
LEVEL_UNKNOWN_1 = LEVEL_MIN, // (1) ""
LEVEL_UNKNOWN_2, // (2) ""
LEVEL_UNKNOWN_3, // (3) ""
LEVEL_BBH, // (4) "TERESA OBAKE" Big Boo's Haunt
LEVEL_CCM, // (5) "YYAMA1 % YSLD1" Cool Cool Mountain
LEVEL_CASTLE, // (6) "SELECT ROOM" Castle lobby
LEVEL_HMC, // (7) "HORROR DUNGEON" Hazy Maze Cave
LEVEL_SSL, // (8) "SABAKU % PYRMD" Shifting Sand Land
LEVEL_BOB, // (9) "BATTLE FIELD" Bob Omb Battlefield
LEVEL_SL, // (10) "YUKIYAMA2" Snowman's Land
LEVEL_WDW, // (11) "POOL KAI" Wet Dry World
LEVEL_JRB, // (12) "WTDG % TINBOTU" Jolly Rodger's Bay
LEVEL_THI, // (13) "BIG WORLD" Tiny Huge Island
LEVEL_TTC, // (14) "CLOCK TOWER" Tick Tock Clock
LEVEL_RR, // (15) "RAINBOW CRUISE" Rainbow Ride
LEVEL_CASTLE_GROUNDS, // (16) "MAIN MAP" Castle grounds (outside)
LEVEL_BITDW, // (17) "EXT1 YOKO SCRL" Bowser in the Dark World
LEVEL_VCUTM, // (18) "EXT7 HORI MINI" Vanish Cap under the Moat
LEVEL_BITFS, // (19) "EXT2 TIKA LAVA" Bowser in the Fire Sea
LEVEL_SA, // (20) "EXT9 SUISOU" Secret Aquarium
LEVEL_BITS, // (21) "EXT3 HEAVEN" Bowser in the Sky
LEVEL_LLL, // (22) "FIREB1 % INVLC" Lethal Lava Land
LEVEL_DDD, // (23) "WATER LAND" Dire Dire Docks
LEVEL_WF, // (24) "MOUNTAIN" Whomp's Fortress
LEVEL_ENDING, // (25) "ENDING" (Ending Cutscene)
LEVEL_CASTLE_COURTYARD, // (26) "URANIWA" Castle courtyard (BBH entrance)
LEVEL_PSS, // (27) "EXT4 MINI SLID" Princess's Secret Slide
LEVEL_COTMC, // (28) "IN THE FALL" Cavern of the Metal Cap
LEVEL_TOTWC, // (29) "EXT6 MARIO FLY" Tower of the Wing Cap
LEVEL_BOWSER_1, // (30) "KUPPA1" Bowser in the Dark World (Boss)
LEVEL_WMOTR, // (31) "EXT8 BLUE SKY" Winged Mario over the Rainbow
LEVEL_UNKNOWN_32, // (32) ""
LEVEL_BOWSER_2, // (33) "KUPPA2" Bowser in the Fire Sea (Boss)
LEVEL_BOWSER_3, // (34) "KUPPA3" Bowser in the Sky (Final Boss)
LEVEL_UNKNOWN_35, // (35) ""
LEVEL_TTM, // (36) "DONKEY % SLID2" Tall Tall Mountain
LEVEL_UNKNOWN_37, // (37) ""
LEVEL_UNKNOWN_38, // (38) ""
LEVEL_COUNT,
LEVEL_MAX = LEVEL_COUNT - 1
};
struct WarpNode
{
/*00*/ u8 id;
@@ -203,6 +114,21 @@ struct Area
/*0x38*/ u16 musicParam2;
};
/**
* Helper macro for defining which areas of a level should zoom out the camera when the game is paused.
* Because a mask is used by two levels, the pattern will repeat when more than 4 areas are used by a level.
*/
#define ZOOMOUT_AREA_MASK(level1Area1, level1Area2, level1Area3, level1Area4, \
level2Area1, level2Area2, level2Area3, level2Area4) \
((level2Area4) << 7 | \
(level2Area3) << 6 | \
(level2Area2) << 5 | \
(level2Area1) << 4 | \
(level1Area4) << 3 | \
(level1Area3) << 2 | \
(level1Area2) << 1 | \
(level1Area1) << 0)
// All the transition data to be used in screen_transition.c
struct WarpTransitionData
{
@@ -210,14 +136,14 @@ struct WarpTransitionData
/*0x01*/ u8 green;
/*0x02*/ u8 blue;
/*0x04*/ s16 startCircleRadius;
/*0x06*/ s16 endCircleRadius;
/*0x08*/ s16 startCircleX;
/*0x0A*/ s16 startCircleY;
/*0x0C*/ s16 endCircleX;
/*0x0E*/ s16 endCircleY;
/*0x04*/ s16 startTexRadius;
/*0x06*/ s16 endTexRadius;
/*0x08*/ s16 startTexX;
/*0x0A*/ s16 startTexY;
/*0x0C*/ s16 endTexX;
/*0x0E*/ s16 endTexY;
/*0x10*/ s16 unk10;
/*0x10*/ s16 texTimer; // always 0, does seems to affect transition when disabled
};
#define WARP_TRANSITION_FADE_FROM_COLOR 0x00
+5 -3
View File
@@ -17,6 +17,7 @@
#include "level_update.h"
#include "audio/external.h"
#include "seq_ids.h"
#include "dialog_ids.h"
#include "save_file.h"
#include "area.h"
#include "engine/graph_node.h"
@@ -36,6 +37,7 @@
#include "ingame_menu.h"
#include "room.h"
#include "rendering_graph_node.h"
#include "level_table.h"
#define o gCurrentObject
@@ -186,7 +188,7 @@ void func_802AA618(s32 sp18, s32 sp1C, f32 sp20) {
#include "behaviors/breakable_box.inc.c"
// not sure what this is doing here. not in a behavior file.
s32 Geo18_802B1BB0(s32 run, UNUSED struct GraphNode *node, Mat4 mtx) {
Gfx *Geo18_802B1BB0(s32 run, UNUSED struct GraphNode *node, Mat4 mtx) {
Mat4 sp20;
struct Object *sp1C;
@@ -198,7 +200,7 @@ s32 Geo18_802B1BB0(s32 run, UNUSED struct GraphNode *node, Mat4 mtx) {
func_8029EA0C(sp1C->prevObj);
}
}
return 0;
return NULL;
}
#include "behaviors/heave_ho.inc.c"
@@ -244,7 +246,7 @@ void func_802B2328(
#include "behaviors/lll_volcano_flames.inc.c"
#include "behaviors/lll_hexagonal_ring.inc.c"
#include "behaviors/lll_sinking_rectangle.inc.c"
#include "behaviors/lll_tilting_platform.inc.c"
#include "behaviors/tilting_inverted_pyramid.inc.c"
#include "behaviors/koopa_shell.inc.c"
#include "behaviors/tox_box.inc.c"
#include "behaviors/piranha_plant.inc.c"
+5 -5
View File
@@ -94,8 +94,8 @@ void bhv_ukiki_cage_loop(void);
void bhv_bitfs_sinking_platform_loop(void);
void bhv_bitfs_sinking_cage_platform_loop(void);
void bhv_ddd_moving_pole_loop(void);
void bhv_tilting_platform_init(void);
void bhv_tilting_platform_loop(void);
void bhv_platform_normals_init(void);
void bhv_tilting_inverted_pyramid_loop(void);
void bhv_squishable_platform_loop(void);
void bhv_beta_moving_flames_spawn_loop(void);
void bhv_beta_moving_flames_loop(void);
@@ -548,15 +548,15 @@ void BehDustSmokeLoop(void);
void BehYoshiLoop(void);
void bhvLllVolcanoFallingTrap_loop(void);
extern s32 Geo18_802B1BB0(s32 run, UNUSED struct GraphNode *node, Mat4 mtx);
extern Gfx *Geo18_802B1BB0(s32 run, UNUSED struct GraphNode *node, Mat4 mtx);
// Bowser
extern Gfx *Geo18_802B7D44(s32 a0, struct GraphNode *node, UNUSED s32 a2);
extern Gfx *Geo18_802B798C(s32 run, UNUSED struct GraphNode *node, Mat4 mtx);
extern s32 geo_switch_bowser_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx);
extern Gfx *geo_switch_bowser_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx);
// Tuxie
extern s32 geo_switch_tuxie_mother_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx);
extern Gfx *geo_switch_tuxie_mother_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx);
// Cap switch
extern Gfx *Geo18_802A719C(s32 run, UNUSED struct GraphNode *node, Mat4 mtx);
+1 -1
View File
@@ -225,7 +225,7 @@ void bhv_homing_amp_loop(void) {
break;
}
ObjectStep();
object_step();
// Oscillate
o->oAmpYPhase++;
@@ -59,7 +59,7 @@ void bhv_beta_holdable_object_loop(void) {
switch (o->oHeldState) {
case HELD_FREE:
// Apply standard physics
ObjectStep();
object_step();
break;
case HELD_HELD:
+14 -14
View File
@@ -21,7 +21,7 @@ void bhv_bobomb_init(void) {
void func_802E5B7C(void) {
if (((o->oBehParams >> 8) & 0x1) == 0) {
ObjSpawnYellowCoins(o, 1);
obj_spawn_yellow_coins(o, 1);
o->oBehParams = 0x100;
set_object_respawn_info_bits(o, 1);
}
@@ -71,13 +71,13 @@ void BobombPatrolLoop(void) {
sp22 = o->header.gfx.unk38.animFrame;
o->oForwardVel = 5.0;
collisionFlags = ObjectStep();
if ((ObjLeaveIfMarioIsNearHome(o, o->oHomeX, o->oHomeY, o->oHomeZ, 400) == 1)
&& (func_802E46C0(o->oMoveAngleYaw, o->oAngleToMario, 0x2000) == 1)) {
collisionFlags = object_step();
if ((obj_return_home_if_safe(o, o->oHomeX, o->oHomeY, o->oHomeZ, 400) == 1)
&& (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x2000) == 1)) {
o->oBobombFuseLit = 1;
o->oAction = BOBOMB_ACT_CHASE_MARIO;
}
ObjCheckFloorDeath(collisionFlags, D_803600E0);
obj_check_floor_death(collisionFlags, sObjFloor);
}
void BobombChaseMarioLoop(void) {
@@ -87,18 +87,18 @@ void BobombChaseMarioLoop(void) {
sp1a = ++o->header.gfx.unk38.animFrame;
o->oForwardVel = 20.0;
collisionFlags = ObjectStep();
collisionFlags = object_step();
if (sp1a == 5 || sp1a == 16)
PlaySound2(SOUND_OBJ_BOBOMB_WALK);
obj_turn_toward_object(o, gMarioObject, 16, 0x800);
ObjCheckFloorDeath(collisionFlags, D_803600E0);
obj_check_floor_death(collisionFlags, sObjFloor);
}
void BobombLaunchedLoop(void) {
s16 collisionFlags = 0;
collisionFlags = ObjectStep();
collisionFlags = object_step();
if ((collisionFlags & 0x1) == 1)
o->oAction = BOBOMB_ACT_EXPLODE; /* bit 0 */
}
@@ -122,7 +122,7 @@ void GenericBobombFreeLoop(void) {
break;
case BOBOMB_ACT_LAVA_DEATH:
if (ObjLavaDeath() == 1)
if (obj_lava_death() == 1)
create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000);
break;
@@ -149,7 +149,7 @@ void StationaryBobombFreeLoop(void) {
break;
case BOBOMB_ACT_LAVA_DEATH:
if (ObjLavaDeath() == 1)
if (obj_lava_death() == 1)
create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000);
break;
@@ -293,7 +293,7 @@ void BobombBuddyIdleLoop(void) {
o->oBobombBuddyPosYCopy = o->oPosY;
o->oBobombBuddyPosZCopy = o->oPosZ;
collisionFlags = ObjectStep();
collisionFlags = object_step();
if ((sp1a == 5) || (sp1a == 16))
PlaySound2(SOUND_OBJ_BOBOMB_WALK);
@@ -373,9 +373,9 @@ void BobombBuddyTalkLoop(void) {
case BOBOMB_BUDDY_ROLE_CANNON:
if (gCurrCourseNum == COURSE_BOB)
BobombBuddyCannonLoop(4, 105);
BobombBuddyCannonLoop(DIALOG_004, DIALOG_105);
else
BobombBuddyCannonLoop(47, 106);
BobombBuddyCannonLoop(DIALOG_047, DIALOG_106);
break;
}
}
@@ -408,7 +408,7 @@ void BobombBuddyActionLoop(void) {
break;
}
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
}
void bhv_bobomb_buddy_loop(void) {
+3 -3
View File
@@ -459,16 +459,16 @@ static void ActionBoo4(void) {
// If there are no remaining "minion" boos, show the dialog of the Big Boo
if (obj_nearest_object_with_behavior(bhvGhostHuntBoo) == NULL) {
dialogID = 108;
dialogID = DIALOG_108;
} else {
dialogID = 107;
dialogID = DIALOG_107;
}
if (obj_update_dialog(2, 2, dialogID, 0)) {
create_sound_spawner(SOUND_OBJ_DYING_ENEMY1);
mark_object_for_deletion(o);
if (dialogID == 108) { // If the Big Boo should spawn, play the jingle
if (dialogID == DIALOG_108) { // If the Big Boo should spawn, play the jingle
play_puzzle_jingle();
}
}
+2 -2
View File
@@ -13,7 +13,7 @@ void bhv_big_boulder_init(void) {
void func_802F05DC(void) {
s16 sp1E;
sp1E = func_802E4204();
sp1E = object_step_without_floor_orient();
if ((sp1E & 0x09) == 0x01 && o->oVelY > 10.0f) {
PlaySound2(SOUND_GENERAL_GRINDEL_ROLL);
func_802A3004();
@@ -51,7 +51,7 @@ void bhv_big_boulder_generator_loop(void) {
o->oTimer = 0;
}
if (!func_802E49A4(4) || is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 1500))
if (!current_mario_room_check(4) || is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 1500))
return;
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 6000)) {
+5 -5
View File
@@ -68,7 +68,7 @@ void bhv_bowling_ball_roll_loop(void) {
s32 sp18;
func_802EDA6C();
collisionFlags = ObjectStep();
collisionFlags = object_step();
//! Uninitialzed parameter, but the parameter is unused in the called function
sp18 = obj_follow_path(sp18);
@@ -144,7 +144,7 @@ void bhv_bowling_ball_loop(void) {
if (o->oBehParams2ndByte != 4)
func_8027F440(4, o->oPosX, o->oPosY, o->oPosZ);
SetObjectVisibility(o, 4000);
set_object_visibility(o, 4000);
}
void bhv_generic_bowling_ball_spawner_init(void) {
@@ -215,7 +215,7 @@ void bhv_bob_pit_bowling_ball_init(void) {
void bhv_bob_pit_bowling_ball_loop(void) {
struct FloorGeometry *sp1c;
UNUSED s16 collisionFlags = ObjectStep();
UNUSED s16 collisionFlags = object_step();
find_floor_height_and_data(o->oPosX, o->oPosY, o->oPosZ, &sp1c);
if ((sp1c->normalX == 0) && (sp1c->normalZ == 0))
@@ -224,7 +224,7 @@ void bhv_bob_pit_bowling_ball_loop(void) {
func_802EDA14();
func_8027F440(4, o->oPosX, o->oPosY, o->oPosZ);
PlaySound(SOUND_ENV_UNKNOWN2);
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
}
void bhv_free_bowling_ball_init(void) {
@@ -239,7 +239,7 @@ void bhv_free_bowling_ball_init(void) {
}
void bhv_free_bowling_ball_roll_loop(void) {
s16 collisionFlags = ObjectStep();
s16 collisionFlags = object_step();
func_802EDA14();
if (o->oForwardVel > 10.0f) {
+7 -7
View File
@@ -32,7 +32,7 @@ s8 D_8032F4FC[] = { 7, 8, 9, 12, 13, 14, 15, 4, 3, 16, 17, 19, 3, 3, 3, 3 };
s16 D_8032F50C[] = { 60, 0 };
s16 D_8032F510[] = { 50, 0 };
s8 D_8032F514[] = { 24, 42, 60, -1 };
s16 sBowserDefeatedDialogText[3] = { 119, 120, 121 };
s16 sBowserDefeatedDialogText[3] = { DIALOG_119, DIALOG_120, DIALOG_121 };
s16 D_8032F520[][3] = { { 1, 10, 40 }, { 0, 0, 74 }, { -1, -10, 114 }, { 1, -20, 134 },
{ -1, 20, 154 }, { 1, 40, 164 }, { -1, -40, 174 }, { 1, -80, 179 },
{ -1, 80, 184 }, { 1, 160, 186 }, { -1, -160, 186 }, { 1, 0, 0 }, };
@@ -865,9 +865,9 @@ s32 func_802B6254(void) {
s32 dialogID;
if (o->oBowserUnkF8 < 2) {
if (gHudDisplay.stars < 120)
dialogID = 121;
dialogID = DIALOG_121;
else
dialogID = 163;
dialogID = DIALOG_163;
if (o->oBowserUnkF8 == 0) {
func_8031FFB4(0, 60, 40);
o->oBowserUnkF8++;
@@ -1247,7 +1247,7 @@ void func_802B70C8(struct Object *a0, struct GraphNodeSwitchCase *switchCase) {
* state. Checks whether oBowserEyesShut is TRUE and closes eyes if so and processes
* direction otherwise.
*/
s32 geo_switch_bowser_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx) {
Gfx *geo_switch_bowser_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx) {
UNUSED s16 sp36;
UNUSED s32 unused;
struct Object *obj = (struct Object *) gCurGraphNodeObject;
@@ -1265,7 +1265,7 @@ s32 geo_switch_bowser_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx) {
}
obj->oBowserUnk1AE++;
}
return 0;
return NULL;
}
Gfx *Geo18_802B7D44(s32 a0, struct GraphNode *node, UNUSED s32 a2) {
@@ -1280,9 +1280,9 @@ Gfx *Geo18_802B7D44(s32 a0, struct GraphNode *node, UNUSED s32 a2) {
if (gCurGraphNodeHeldObject != 0)
sp24 = gCurGraphNodeHeldObject->objNode;
if (sp24->oOpacity == 0xFF)
sp20->fnNode.node.flags = (sp20->fnNode.node.flags & 0xFF) | 0x100;
sp20->fnNode.node.flags = (sp20->fnNode.node.flags & 0xFF) | GRAPH_NODE_TYPE_FUNCTIONAL;
else
sp20->fnNode.node.flags = (sp20->fnNode.node.flags & 0xFF) | (0x100 | 0x400);
sp20->fnNode.node.flags = (sp20->fnNode.node.flags & 0xFF) | (GRAPH_NODE_TYPE_FUNCTIONAL | GRAPH_NODE_TYPE_400);
sp28 = sp2C = alloc_display_list(2 * sizeof(Gfx));
if (sp24->oBowserUnk1B2 != 0) {
+1 -1
View File
@@ -15,7 +15,7 @@ void bhv_bowser_bomb_loop(void) {
o->activeFlags = 0;
}
SetObjectVisibility(o, 7000);
set_object_visibility(o, 7000);
}
void bhv_bowser_bomb_explosion_loop(void) {
+4 -4
View File
@@ -29,7 +29,7 @@ void func_802F4CE8(void) {
}
void func_802F4DB4(void) {
s16 sp1E = ObjectStep();
s16 sp1E = object_step();
attack_collided_non_mario_object(o);
if (sp1E == 1)
@@ -44,12 +44,12 @@ void func_802F4DB4(void) {
if (sp1E & 2) {
func_802A3004();
spawn_triangle_break_particles(20, 138, 0.7f, 3);
ObjSpawnYellowCoins(o, 3);
obj_spawn_yellow_coins(o, 3);
create_sound_spawner(SOUND_GENERAL_BREAK_BOX);
o->activeFlags = 0;
}
ObjCheckFloorDeath(sp1E, D_803600E0);
obj_check_floor_death(sp1E, sObjFloor);
}
void breakable_box_small_released_loop(void) {
@@ -77,7 +77,7 @@ void breakable_box_small_idle_loop(void) {
break;
case 100:
ObjLavaDeath();
obj_lava_death();
break;
case 101:
+8 -8
View File
@@ -164,10 +164,10 @@ void PlayBullyStompingSound(void) {
void BullyStep(void) {
s16 collisionFlags = 0;
collisionFlags = ObjectStep();
collisionFlags = object_step();
BullyBackUpCheck(collisionFlags);
PlayBullyStompingSound();
ObjCheckFloorDeath(collisionFlags, D_803600E0);
obj_check_floor_death(collisionFlags, sObjFloor);
if (o->oBullySubtype & BULLY_STYPE_CHILL) {
if (o->oPosY < 1030.0f)
@@ -189,7 +189,7 @@ void BullySpawnCoin(void) {
}
void BullyLavaDeath(void) {
if (ObjLavaDeath() == 1) {
if (obj_lava_death() == 1) {
if (o->oBehParams2ndByte == BULLY_BP_SIZE_SMALL) {
if (o->oBullySubtype == BULLY_STYPE_MINION)
o->parentObj->oBullyKBTimerAndMinionKOCounter++;
@@ -223,7 +223,7 @@ void bhv_bully_loop(void) {
case BULLY_ACT_PATROL:
o->oForwardVel = 5.0;
if (ObjLeaveIfMarioIsNearHome(o, o->oHomeX, o->oPosY, o->oHomeZ, 800) == 1) {
if (obj_return_home_if_safe(o, o->oHomeX, o->oPosY, o->oHomeZ, 800) == 1) {
o->oAction = BULLY_ACT_CHASE_MARIO;
SetObjAnimation(1);
}
@@ -255,7 +255,7 @@ void bhv_bully_loop(void) {
break;
}
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
}
// sp38 = arg0
@@ -283,7 +283,7 @@ void bhv_big_bully_with_minions_init(void) {
}
void BigBullyWithMinionsLavaDeath(void) {
if (ObjLavaDeath() == 1) {
if (obj_lava_death() == 1) {
func_802A3004();
create_star(3700.0f, 600.0f, -5500.0f);
}
@@ -306,7 +306,7 @@ void bhv_big_bully_with_minions_loop(void) {
case BULLY_ACT_PATROL:
o->oForwardVel = 5.0;
if (ObjLeaveIfMarioIsNearHome(o, o->oHomeX, o->oPosY, o->oHomeZ, 1000) == 1) {
if (obj_return_home_if_safe(o, o->oHomeX, o->oPosY, o->oHomeZ, 1000) == 1) {
o->oAction = BULLY_ACT_CHASE_MARIO;
SetObjAnimation(1);
}
@@ -343,7 +343,7 @@ void bhv_big_bully_with_minions_loop(void) {
break;
case BULLY_ACT_ACTIVATE_AND_FALL:
collisionFlags = ObjectStep();
collisionFlags = object_step();
if ((collisionFlags & 0x9) == 0x9) /* bits 0 and 3 */
o->oAction = BULLY_ACT_PATROL;
+1 -1
View File
@@ -108,5 +108,5 @@ void bhv_butterfly_loop(void) {
break;
}
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
}
+6 -6
View File
@@ -115,7 +115,7 @@ static void camera_lakitu_intro_act_show_dialog(void) {
}
}
}
} else if (obj_update_dialog_with_cutscene(2, DIALOG_UNK2_FLAG_0, CUTSCENE_DIALOG_1, 34) != 0) {
} else if (obj_update_dialog_with_cutscene(2, DIALOG_UNK2_FLAG_0, CUTSCENE_DIALOG_1, DIALOG_034) != 0) {
o->oCameraLakituFinishedDialog = TRUE;
}
}
@@ -151,15 +151,15 @@ void bhv_camera_lakitu_update(void) {
break;
}
} else {
f32 val0C = (f32) 0x875C3D / 0x800 - gCameraStatus.camFocAndPosCurrAndGoal[0][3];
if (gCameraStatus.camFocAndPosCurrAndGoal[0][3] < 1700.0f || val0C < 0.0f) {
f32 val0C = (f32) 0x875C3D / 0x800 - gCameraStatus.camFocAndPosCurrAndGoal[1][0];
if (gCameraStatus.camFocAndPosCurrAndGoal[1][0] < 1700.0f || val0C < 0.0f) {
obj_hide();
} else {
obj_unhide();
o->oPosX = gCameraStatus.camFocAndPosCurrAndGoal[0][3];
o->oPosY = gCameraStatus.camFocAndPosCurrAndGoal[0][4];
o->oPosZ = gCameraStatus.camFocAndPosCurrAndGoal[0][5];
o->oPosX = gCameraStatus.camFocAndPosCurrAndGoal[1][0];
o->oPosY = gCameraStatus.camFocAndPosCurrAndGoal[1][1];
o->oPosZ = gCameraStatus.camFocAndPosCurrAndGoal[1][2];
o->oHomeX = gCameraStatus.camFocAndPosCurrAndGoal[0][0];
o->oHomeZ = gCameraStatus.camFocAndPosCurrAndGoal[0][2];
+13 -13
View File
@@ -25,15 +25,15 @@ s32 func_802F0904(void) {
void func_802F0978(void) {
if (o->oTimer > 300) {
ObjFlickerAndDisappear(o, 300);
obj_flicker_and_disappear(o, 300);
}
}
void func_802F09C0(void) {
if (D_803600E0 == NULL)
if (sObjFloor == NULL)
return;
switch (D_803600E0->type) {
switch (sObjFloor->type) {
case SURFACE_DEATH_PLANE:
o->activeFlags = 0;
break;
@@ -49,8 +49,8 @@ void func_802F09C0(void) {
case SURFACE_SHALLOW_MOVING_QUICKSAND:
case SURFACE_MOVING_QUICKSAND:
o->oAction = 11;
o->oMoveAngleYaw = (D_803600E0->force & 0xFF) << 8;
o->oForwardVel = -((D_803600E0->force & 0xff00) >> 8) * 2 + 8;
o->oMoveAngleYaw = (sObjFloor->force & 0xFF) << 8;
o->oForwardVel = -((sObjFloor->force & 0xff00) >> 8) * 2 + 8;
break;
case SURFACE_INSTANT_QUICKSAND:
@@ -60,8 +60,8 @@ void func_802F09C0(void) {
case SURFACE_INSTANT_MOVING_QUICKSAND:
o->oAction = 13;
o->oMoveAngleYaw = (D_803600E0->force & 0xFF) << 8;
o->oForwardVel = -((D_803600E0->force & 0xff00) >> 8) * 2 + 8;
o->oMoveAngleYaw = (sObjFloor->force & 0xFF) << 8;
o->oForwardVel = -((sObjFloor->force & 0xff00) >> 8) * 2 + 8;
break;
}
}
@@ -121,7 +121,7 @@ void func_802F0E0C(void) {
s16 sp1E;
o->oFaceAngleYaw += o->oForwardVel * 128.0f;
sp1E = ObjectStep();
sp1E = object_step();
if (sp1E & 0x01) {
func_802F09C0();
if (o->oVelY != 0.0f) {
@@ -141,7 +141,7 @@ void bhv_wing_vanish_cap_loop(void) {
break;
default:
ObjectStep();
object_step();
func_802F0B68();
break;
}
@@ -164,7 +164,7 @@ void func_802F0FE0(void) {
s16 sp1E;
o->oFaceAngleYaw += o->oForwardVel * 128.0f;
sp1E = ObjectStep();
sp1E = object_step();
if (sp1E & 0x01)
func_802F09C0();
}
@@ -176,7 +176,7 @@ void bhv_metal_cap_loop(void) {
break;
default:
ObjectStep();
object_step();
func_802F0B68();
break;
}
@@ -224,7 +224,7 @@ void func_802F1234(void) {
o->oFaceAngleYaw += o->oForwardVel * 128.0f;
o->oFaceAnglePitch += o->oForwardVel * 80.0f;
sp1E = ObjectStep();
sp1E = object_step();
if (sp1E & 0x01) {
func_802F09C0();
@@ -246,7 +246,7 @@ void bhv_normal_cap_loop(void) {
break;
default:
ObjectStep();
object_step();
func_802F0B68();
break;
}
+14 -14
View File
@@ -30,7 +30,7 @@ void bhv_controllable_platform_sub_loop(void) {
if (gMarioObject->platform == o) {
D_80331694 = o->oBehParams2ndByte;
o->oAction = 1;
PlaySound2(SOUND_GENERAL_SWITCH3);
PlaySound2(SOUND_GENERAL_MOVING_PLATFORM_SWITCH);
}
break;
@@ -167,33 +167,33 @@ void bhv_controllable_platform_loop(void) {
case 1:
o->oVelZ = 10.0f;
sp54[0] = func_802E478C(sp48, o->oPosX + 250.0, o->oPosY, o->oPosZ + 300.0, 50.0f);
sp54[1] = func_802E478C(sp3C, o->oPosX, o->oPosY, o->oPosZ + 300.0, 50.0f);
sp54[2] = func_802E478C(sp30, o->oPosX - 250.0, o->oPosY, o->oPosZ + 300.0, 50.0f);
sp54[0] = obj_find_wall_displacement(sp48, o->oPosX + 250.0, o->oPosY, o->oPosZ + 300.0, 50.0f);
sp54[1] = obj_find_wall_displacement(sp3C, o->oPosX, o->oPosY, o->oPosZ + 300.0, 50.0f);
sp54[2] = obj_find_wall_displacement(sp30, o->oPosX - 250.0, o->oPosY, o->oPosZ + 300.0, 50.0f);
func_802F3FD8(2, sp54, sp48, sp3C, sp30);
break;
case 2:
o->oVelZ = -10.0f;
sp54[0] = func_802E478C(sp48, o->oPosX + 250.0, o->oPosY, o->oPosZ - 300.0, 50.0f);
sp54[1] = func_802E478C(sp3C, o->oPosX, o->oPosY, o->oPosZ - 300.0, 50.0f);
sp54[2] = func_802E478C(sp30, o->oPosX - 250.0, o->oPosY, o->oPosZ - 300.0, 50.0f);
sp54[0] = obj_find_wall_displacement(sp48, o->oPosX + 250.0, o->oPosY, o->oPosZ - 300.0, 50.0f);
sp54[1] = obj_find_wall_displacement(sp3C, o->oPosX, o->oPosY, o->oPosZ - 300.0, 50.0f);
sp54[2] = obj_find_wall_displacement(sp30, o->oPosX - 250.0, o->oPosY, o->oPosZ - 300.0, 50.0f);
func_802F3FD8(1, sp54, sp48, sp3C, sp30);
break;
case 3:
o->oVelX = 10.0f;
sp54[0] = func_802E478C(sp48, o->oPosX + 300.0, o->oPosY, o->oPosZ + 250.0, 50.0f);
sp54[1] = func_802E478C(sp3C, o->oPosX + 300.0, o->oPosY, o->oPosZ, 50.0f);
sp54[2] = func_802E478C(sp30, o->oPosX + 300.0, o->oPosY, o->oPosZ - 250.0, 50.0f);
sp54[0] = obj_find_wall_displacement(sp48, o->oPosX + 300.0, o->oPosY, o->oPosZ + 250.0, 50.0f);
sp54[1] = obj_find_wall_displacement(sp3C, o->oPosX + 300.0, o->oPosY, o->oPosZ, 50.0f);
sp54[2] = obj_find_wall_displacement(sp30, o->oPosX + 300.0, o->oPosY, o->oPosZ - 250.0, 50.0f);
func_802F3FD8(4, sp54, sp48, sp3C, sp30);
break;
case 4:
o->oVelX = -10.0f;
sp54[0] = func_802E478C(sp48, o->oPosX - 300.0, o->oPosY, o->oPosZ + 250.0, 50.0f);
sp54[1] = func_802E478C(sp3C, o->oPosX - 300.0, o->oPosY, o->oPosZ, 50.0f);
sp54[2] = func_802E478C(sp30, o->oPosX - 300.0, o->oPosY, o->oPosZ - 250.0, 50.0f);
sp54[0] = obj_find_wall_displacement(sp48, o->oPosX - 300.0, o->oPosY, o->oPosZ + 250.0, 50.0f);
sp54[1] = obj_find_wall_displacement(sp3C, o->oPosX - 300.0, o->oPosY, o->oPosZ, 50.0f);
sp54[2] = obj_find_wall_displacement(sp30, o->oPosX - 300.0, o->oPosY, o->oPosZ - 250.0, 50.0f);
func_802F3FD8(3, sp54, sp48, sp3C, sp30);
break;
@@ -203,7 +203,7 @@ void bhv_controllable_platform_loop(void) {
break;
case 6:
if (ObjFlickerAndDisappear(o, 150))
if (obj_flicker_and_disappear(o, 150))
spawn_object_abs_with_rot(o, 0, MODEL_HMC_METAL_PLATFORM, bhvControllablePlatform,
o->oHomeX, o->oHomeY, o->oHomeZ, 0, 0, 0);
break;
+2 -2
View File
@@ -63,7 +63,7 @@ static void eyerok_boss_act_wake_up(void) {
}
static void eyerok_boss_act_show_intro_text(void) {
if (obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG_1, 117)) {
if (obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG_1, DIALOG_117)) {
o->oAction = EYEROK_BOSS_ACT_FIGHT;
}
}
@@ -117,7 +117,7 @@ static void eyerok_boss_act_fight(void) {
static void eyerok_boss_act_die(void) {
if (o->oTimer == 60) {
if (obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG_1, 118)) {
if (obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG_1, DIALOG_118)) {
create_star(0.0f, -900.0f, -3700.0f);
} else {
o->oTimer -= 1;
+2 -2
View File
@@ -79,7 +79,7 @@ void bhv_falling_pillar_loop(void) {
break;
case FALLING_PILLAR_ACT_TURNING:
func_802E4204();
object_step_without_floor_orient();
// Calculate angle in front of Mario and turn towards it.
angleInFrontOfMario = bhv_falling_pillar_calculate_angle_in_front_of_mario();
@@ -91,7 +91,7 @@ void bhv_falling_pillar_loop(void) {
break;
case FALLING_PILLAR_ACT_FALLING:
func_802E4204();
object_step_without_floor_orient();
// Start falling slowly, with increasing acceleration each frame.
o->oFallingPillarPitchAcceleration += 4.0f;
+1 -1
View File
@@ -40,7 +40,7 @@ void bhv_hidden_star_trigger_loop(void) {
if (hiddenStar != NULL) {
hiddenStar->oHiddenStarTriggerCounter++;
if (hiddenStar->oHiddenStarTriggerCounter != 5) {
SpawnOrangeNumber(hiddenStar->oHiddenStarTriggerCounter, 0, 0, 0);
spawn_orange_number(hiddenStar->oHiddenStarTriggerCounter, 0, 0, 0);
}
#ifdef VERSION_JP
+3 -3
View File
@@ -188,7 +188,7 @@ void HootActionLoop(void) {
if (o->oPosY < 2700.0f) {
set_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS);
if (cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, 45)) {
if (cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, DIALOG_045)) {
clear_time_stop_flags(TIME_STOP_ENABLED | TIME_STOP_MARIO_AND_DOORS);
o->oAction = HOOT_ACT_TIRED;
@@ -240,7 +240,7 @@ void HootAwakeLoop(void) {
o->oTimer = 0;
}
SetObjectVisibility(o, 2000);
set_object_visibility(o, 2000);
}
void bhv_hoot_loop(void) {
@@ -255,7 +255,7 @@ void bhv_hoot_loop(void) {
case HOOT_AVAIL_WANTS_TO_TALK:
HootAwakeLoop();
if (set_mario_npc_dialog(2) == 2 && cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, 44)) {
if (set_mario_npc_dialog(2) == 2 && cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, DIALOG_044)) {
set_mario_npc_dialog(0);
obj_become_tangible();
+3 -3
View File
@@ -19,7 +19,7 @@ void ActionKingBobomb0(void) {
o->oSubAction++;
func_8031FFB4(0, 60, 40);
}
} else if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, 17)) {
} else if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, DIALOG_017)) {
o->oAction = 2;
o->oFlags |= OBJ_FLAG_HOLDABLE;
}
@@ -154,7 +154,7 @@ void ActionKingBobomb6(void) {
void ActionKingBobomb7(void) {
set_obj_animation_and_sound_state(2);
if (obj_update_dialog_with_cutscene(2, 2, CUTSCENE_DIALOG_1, 116)) {
if (obj_update_dialog_with_cutscene(2, 2, CUTSCENE_DIALOG_1, DIALOG_116)) {
create_sound_spawner(SOUND_OBJ_KING_WHOMP_DEATH);
obj_hide();
obj_become_intangible();
@@ -246,7 +246,7 @@ void ActionKingBobomb5() { // bobomb returns home
o->oSubAction++;
break;
case 4:
if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, 128))
if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, DIALOG_128))
o->oAction = 2;
break;
}
+3 -1
View File
@@ -144,8 +144,10 @@ static void klepto_circle_target(f32 radius, f32 targetSpeed) {
o->oKleptoYawToTarget += turnAmount;
func_8030F218();
//! The multiplied value is sometimes out of range for an s16 during the s32 -> s16 cast,
// which might invert sign.
turnAmount =
(s16)(abs_angle_diff(o->oKleptoYawToTarget, o->oMoveAngleYaw) * (0.03f * o->oKleptoSpeed));
(s16)(s32)(abs_angle_diff(o->oKleptoYawToTarget, o->oMoveAngleYaw) * (0.03f * o->oKleptoSpeed));
clamp_s16(&turnAmount, 400, 700);
obj_rotate_yaw_and_bounce_off_walls(o->oKleptoYawToTarget, turnAmount);
+6 -6
View File
@@ -52,7 +52,7 @@ static u8 sKoopaShelledAttackHandlers[] = {
*/
struct KoopaTheQuickProperties {
s16 initText;
s16 unk02;
s16 winText;
void *path;
Vec3s starPos;
};
@@ -61,8 +61,8 @@ struct KoopaTheQuickProperties {
* Properties for the BoB race and the THI race.
*/
static struct KoopaTheQuickProperties sKoopaTheQuickProperties[] = {
{ 5, 7, bob_seg7_trajectory_koopa, { 3030, 4500, -4600 } },
{ 9, 31, thi_seg7_trajectory_koopa, { 7100, -1300, -6000 } }
{ DIALOG_005, DIALOG_007, bob_seg7_trajectory_koopa, { 3030, 4500, -4600 } },
{ DIALOG_009, DIALOG_031, thi_seg7_trajectory_koopa, { 7100, -1300, -6000 } }
};
/**
@@ -717,15 +717,15 @@ static void koopa_the_quick_act_after_race(void) {
if (o->parentObj->oKoopaRaceEndpointRaceStatus < 0) {
// Mario cheated
o->parentObj->oKoopaRaceEndpointRaceStatus = 0;
o->parentObj->oKoopaRaceEndpointUnk100 = 6;
o->parentObj->oKoopaRaceEndpointUnk100 = DIALOG_006;
} else {
// Mario won
o->parentObj->oKoopaRaceEndpointUnk100 =
sKoopaTheQuickProperties[o->oKoopaTheQuickRaceIndex].unk02;
sKoopaTheQuickProperties[o->oKoopaTheQuickRaceIndex].winText;
}
} else {
// KtQ won
o->parentObj->oKoopaRaceEndpointUnk100 = 41;
o->parentObj->oKoopaRaceEndpointUnk100 = DIALOG_041;
}
o->oFlags &= ~OBJ_FLAG_ACTIVE_FROM_AFAR;
@@ -1,94 +0,0 @@
// lll_tilting_platform.c.inc
void func_802BC544(Mat4 a0, f32 a1, f32 a2, f32 a3) {
Vec3f sp24;
Vec3f sp18;
sp18[0] = o->oPosX;
sp18[1] = o->oPosY;
sp18[2] = o->oPosZ;
sp24[0] = a1;
sp24[1] = a2;
sp24[2] = a3;
mtxf_align_terrain_normal(a0, sp24, sp18, 0);
}
void bhv_tilting_platform_init(void) {
Mat4 *sp1C = &o->transform;
o->oTiltingPlatformUnkF4 = 0.0f;
o->oTiltingPlatformUnkF8 = 1.0f;
o->oTiltingPlatformUnkFC = 0.0f;
func_802BC544(*sp1C, 0.0f, 1.0f, 0.0f);
}
f32 func_802BC66C(f32 a0, f32 a1, f32 a2) {
f32 sp4;
if (a1 <= a0) {
if (a0 - a1 < a2)
sp4 = a0;
else
sp4 = a1 + a2;
} else if (a0 - a1 > -a2)
sp4 = a0;
else
sp4 = a1 - a2;
return sp4;
}
void bhv_tilting_platform_loop(void) {
f32 dx;
f32 dy;
f32 dz;
f32 d;
Vec3f dist;
Vec3f sp58;
Vec3f sp4C;
f32 mx;
f32 my;
f32 mz;
s32 sp3C = 0;
UNUSED s32 unused;
Mat4 *sp34 = &o->transform;
UNUSED s32 unused2[7];
if (gMarioObject->platform == o) {
get_mario_pos(&mx, &my, &mz);
dist[0] = gMarioObject->oPosX - o->oPosX;
dist[1] = gMarioObject->oPosY - o->oPosY;
dist[2] = gMarioObject->oPosZ - o->oPosZ;
linear_mtxf_mul_vec3f(*sp34, sp58, dist);
dx = gMarioObject->oPosX - o->oPosX;
dy = 500.0f;
dz = gMarioObject->oPosZ - o->oPosZ;
d = sqrtf(dx * dx + dy * dy + dz * dz);
if (d != 0.0f) // Normalizing
{
d = 1.0 / d;
dx *= d;
dy *= d;
dz *= d;
} else {
dx = 0.0f;
dy = 1.0f;
dz = 0.0f;
}
if (o->oTiltingPlatformUnk10C == 1)
sp3C++;
o->oTiltingPlatformUnk10C = 1;
} else {
dx = 0.0f;
dy = 1.0f;
dz = 0.0f;
o->oTiltingPlatformUnk10C = 0;
}
o->oTiltingPlatformUnkF4 = func_802BC66C(dx, o->oTiltingPlatformUnkF4, 0.01f);
o->oTiltingPlatformUnkF8 = func_802BC66C(dy, o->oTiltingPlatformUnkF8, 0.01f);
o->oTiltingPlatformUnkFC = func_802BC66C(dz, o->oTiltingPlatformUnkFC, 0.01f);
func_802BC544(*sp34, o->oTiltingPlatformUnkF4, o->oTiltingPlatformUnkF8, o->oTiltingPlatformUnkFC);
if (sp3C != 0) {
linear_mtxf_mul_vec3f(*sp34, sp4C, dist);
mx += sp4C[0] - sp58[0];
my += sp4C[1] - sp58[1];
mz += sp4C[2] - sp58[2];
set_mario_pos(mx, my, mz);
}
o->header.gfx.throwMatrix = sp34;
}
+7 -7
View File
@@ -66,7 +66,7 @@ s16 bhv_mips_find_furthest_waypoint_to_mario(void) {
z = waypoint->pos[2];
// Is the waypoint within 800 units of MIPS?
if (IsPointCloseToObject(o, x, y, z, 800)) {
if (is_point_close_to_object(o, x, y, z, 800)) {
// Is this further from Mario than the last waypoint?
distanceToMario =
sqr(x - gMarioObject->header.gfx.pos[0]) + sqr(z - gMarioObject->header.gfx.pos[2]);
@@ -89,7 +89,7 @@ void bhv_mips_act_wait_for_nearby_mario(void) {
UNUSED s16 collisionFlags = 0;
o->oForwardVel = 0.0f;
collisionFlags = ObjectStep();
collisionFlags = object_step();
// If Mario is within 500 units...
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 500)) {
@@ -129,7 +129,7 @@ void bhv_mips_act_follow_path(void) {
o->oForwardVel = 45.0f;
#endif
o->oMoveAngleYaw = o->oPathedTargetYaw;
collisionFlags = ObjectStep();
collisionFlags = object_step();
// If we are at the end of the path, do idle animation and wait for Mario.
if (followStatus == PATH_REACHED_END) {
@@ -166,7 +166,7 @@ void bhv_mips_act_fall_down(void) {
s16 collisionFlags = 0;
#endif
collisionFlags = ObjectStep();
collisionFlags = object_step();
o->header.gfx.unk38.animFrame = 0;
if ((collisionFlags & OBJ_COL_FLAG_GROUNDED) == 1) {
@@ -187,7 +187,7 @@ void bhv_mips_act_idle(void) {
UNUSED s16 collisionFlags = 0;
o->oForwardVel = 0;
collisionFlags = ObjectStep();
collisionFlags = object_step();
// Spawn a star if he was just picked up for the first time.
if (o->oMipsStarStatus == MIPS_STAR_STATUS_SHOULD_SPAWN_STAR) {
@@ -238,9 +238,9 @@ void bhv_mips_held(void) {
if (o->oMipsStarStatus == MIPS_STAR_STATUS_HAVENT_SPAWNED_STAR) {
// Choose dialog based on which MIPS encounter this is.
if (o->oBehParams2ndByte == 0)
dialogID = 84;
dialogID = DIALOG_084;
else
dialogID = 162;
dialogID = DIALOG_162;
if (set_mario_npc_dialog(1) == 2) {
o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP;
+5 -5
View File
@@ -110,9 +110,9 @@ void MoneybagJump(s8 collisionFlags) {
void MoneybagMoveAroundLoop(void) {
s16 collisionFlags;
ObjDisplaceHome(o, o->oHomeX, o->oHomeY, o->oHomeZ, 200);
obj_return_and_displace_home(o, o->oHomeX, o->oHomeY, o->oHomeZ, 200);
collisionFlags = ObjectStep();
collisionFlags = object_step();
if (((collisionFlags & OBJ_COL_FLAGS_LANDED) == OBJ_COL_FLAGS_LANDED)
&& (o->oMoneybagJumpState == MONEYBAG_JUMP_LANDING)) {
@@ -138,7 +138,7 @@ void MoneybagReturnHomeLoop(void) {
s16 sp22 = atan2s(sp24, sp28);
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, sp22, 0x800);
collisionFlags = ObjectStep();
collisionFlags = object_step();
if (((collisionFlags & OBJ_COL_FLAGS_LANDED) == OBJ_COL_FLAGS_LANDED)
&& (o->oMoneybagJumpState == MONEYBAG_JUMP_LANDING))
o->oMoneybagJumpState = MONEYBAG_JUMP_WALK_HOME;
@@ -146,7 +146,7 @@ void MoneybagReturnHomeLoop(void) {
MoneybagJump(collisionFlags);
MoneybagCheckMarioCollision();
if (IsPointCloseToObject(o, o->oHomeX, o->oHomeY, o->oHomeZ, 100)) {
if (is_point_close_to_object(o, o->oHomeX, o->oHomeY, o->oHomeZ, 100)) {
spawn_object(o, MODEL_YELLOW_COIN, bhvMoneybagHidden);
#ifndef VERSION_JP
PlaySound2(SOUND_GENERAL_VANISH_SFX);
@@ -172,7 +172,7 @@ void MoneybagDisappearLoop(void) {
void MoneybagDeathLoop(void) {
if (o->oTimer == 1) {
ObjSpawnYellowCoins(o, 5);
obj_spawn_yellow_coins(o, 5);
create_sound_spawner(SOUND_GENERAL_SPLATTERING);
func_802A3004();
o->activeFlags = 0;
+9 -9
View File
@@ -27,9 +27,9 @@ static struct ObjectHitbox sMovingBlueCoinHitbox = {
};
s32 CoinStep(s16 *collisionFlagsPtr) {
*collisionFlagsPtr = ObjectStep();
*collisionFlagsPtr = object_step();
ObjCheckFloorDeath(*collisionFlagsPtr, D_803600E0);
obj_check_floor_death(*collisionFlagsPtr, sObjFloor);
if ((*collisionFlagsPtr & 0x1) != 0 && (*collisionFlagsPtr & 0x8) == 0) /* bit 0, bit 3 */
{
@@ -44,7 +44,7 @@ void MovingCoinFlickerLoop(void) {
s16 collisionFlags;
CoinStep(&collisionFlags);
ObjFlickerAndDisappear(o, 0);
obj_flicker_and_disappear(o, 0);
}
void CoinCollected(void) {
@@ -117,7 +117,7 @@ void bhv_moving_blue_coin_loop(void) {
break;
case MOV_BCOIN_ACT_MOVING:
collisionFlags = ObjectStep();
collisionFlags = object_step();
if ((collisionFlags & 0x1) != 0) /* bit 0 */
{
o->oForwardVel += 25.0f;
@@ -129,7 +129,7 @@ void bhv_moving_blue_coin_loop(void) {
if (o->oForwardVel > 75.0)
o->oForwardVel = 75.0f;
ObjFlickerAndDisappear(o, 600);
obj_flicker_and_disappear(o, 600);
break;
}
@@ -183,7 +183,7 @@ void bhv_blue_coin_sliding_loop(void) {
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 500) == 1)
o->oAction = 1;
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
break;
case 1:
@@ -192,7 +192,7 @@ void bhv_blue_coin_sliding_loop(void) {
case 2:
func_802E54DC();
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
break;
case 3:
@@ -231,7 +231,7 @@ void bhv_blue_coin_jumping_loop(void) {
o->oVelY = 50.0;
}
ObjectStep();
object_step();
if (o->oTimer == 15) {
obj_become_tangible();
@@ -245,7 +245,7 @@ void bhv_blue_coin_jumping_loop(void) {
case 2:
func_802E54DC();
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
break;
case 3:
+20 -20
View File
@@ -64,7 +64,7 @@ void func_802F2F8C(s16 sp1A) {
}
void bhv_1up_walking_loop(void) {
ObjectStep();
object_step();
switch (o->oAction) {
case 0:
@@ -91,18 +91,18 @@ void bhv_1up_walking_loop(void) {
break;
case 2:
ObjFlickerAndDisappear(o, 30);
obj_flicker_and_disappear(o, 30);
bhv_1up_interact();
break;
}
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
}
void bhv_1up_running_away_loop(void) {
s16 sp26;
sp26 = ObjectStep();
sp26 = object_step();
switch (o->oAction) {
case 0:
if (o->oTimer >= 18)
@@ -126,18 +126,18 @@ void bhv_1up_running_away_loop(void) {
break;
case 2:
ObjFlickerAndDisappear(o, 30);
obj_flicker_and_disappear(o, 30);
bhv_1up_interact();
break;
}
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
}
void func_802F3328(void) {
s16 sp1E;
sp1E = ObjectStep();
sp1E = object_step();
if (sp1E & 0x01) {
o->oForwardVel += 25.0f;
o->oVelY = 0;
@@ -155,7 +155,7 @@ void func_802F3328(void) {
void bhv_1up_sliding_loop(void) {
switch (o->oAction) {
case 0:
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 1000))
o->oAction = 1;
break;
@@ -165,7 +165,7 @@ void bhv_1up_sliding_loop(void) {
break;
case 2:
ObjFlickerAndDisappear(o, 30);
obj_flicker_and_disappear(o, 30);
bhv_1up_interact();
break;
}
@@ -176,7 +176,7 @@ void bhv_1up_sliding_loop(void) {
void bhv_1up_loop(void) {
bhv_1up_interact();
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
}
void bhv_1up_jump_on_approach_loop(void) {
@@ -191,19 +191,19 @@ void bhv_1up_jump_on_approach_loop(void) {
break;
case 1:
sp26 = ObjectStep();
sp26 = object_step();
func_802F2F8C(sp26);
spawn_object(o, MODEL_NONE, bhvSparkleSpawn);
break;
case 2:
sp26 = ObjectStep();
sp26 = object_step();
bhv_1up_interact();
ObjFlickerAndDisappear(o, 30);
obj_flicker_and_disappear(o, 30);
break;
}
SetObjectVisibility(o, 3000);
set_object_visibility(o, 3000);
}
void bhv_1up_hidden_loop(void) {
@@ -220,19 +220,19 @@ void bhv_1up_hidden_loop(void) {
break;
case 1:
sp26 = ObjectStep();
sp26 = object_step();
func_802F2F8C(sp26);
spawn_object(o, MODEL_NONE, bhvSparkleSpawn);
break;
case 2:
sp26 = ObjectStep();
sp26 = object_step();
bhv_1up_interact();
ObjFlickerAndDisappear(o, 30);
obj_flicker_and_disappear(o, 30);
break;
case 3:
sp26 = ObjectStep();
sp26 = object_step();
if (o->oTimer >= 18)
spawn_object(o, MODEL_NONE, bhvSparkleSpawn);
@@ -273,11 +273,11 @@ void bhv_1up_hidden_in_pole_loop(void) {
case 1:
func_802F2E18();
sp26 = ObjectStep();
sp26 = object_step();
break;
case 3:
sp26 = ObjectStep();
sp26 = object_step();
if (o->oTimer >= 18)
spawn_object(o, MODEL_NONE, bhvSparkleSpawn);
+1 -1
View File
@@ -132,7 +132,7 @@ void bhv_pyramid_top_fragment_init(void) {
* deactivate it.
*/
void bhv_pyramid_top_fragment_loop(void) {
ObjectStep();
object_step();
o->oFaceAngleYaw += 0x1000;
o->oFaceAnglePitch += 0x1000;
+5 -5
View File
@@ -5,8 +5,8 @@ struct RacingPenguinData {
};
static struct RacingPenguinData sRacingPenguinData[] = {
{ 55, 200.0f, 200.0f },
{ 164, 350.0f, 250.0f },
{ DIALOG_055, 200.0f, 200.0f },
{ DIALOG_164, 350.0f, 250.0f },
};
void bhv_racing_penguin_init(void) {
@@ -125,13 +125,13 @@ static void racing_penguin_act_show_final_text(void) {
if (obj_is_mario_in_range_and_ready_to_speak(400.0f, 400.0f)) {
if (o->oRacingPenguinMarioWon) {
if (o->oRacingPenguinMarioCheated) {
o->oRacingPenguinFinalTextbox = 0x84;
o->oRacingPenguinFinalTextbox = DIALOG_132;
o->oRacingPenguinMarioWon = FALSE;
} else {
o->oRacingPenguinFinalTextbox = 0x38;
o->oRacingPenguinFinalTextbox = DIALOG_056;
}
} else {
o->oRacingPenguinFinalTextbox = 0x25;
o->oRacingPenguinFinalTextbox = DIALOG_037;
}
}
} else {
+38 -12
View File
@@ -1,5 +1,12 @@
// red_coin.c.inc
/**
* This file contains the initialization and behavior for red coins.
* Behavior controls audio and the orange number spawned, as well as interacting with
* the course's red coin star.
*/
/**
* Red coin's hitbox details.
*/
static struct ObjectHitbox sRedCoinHitbox = {
/* interactType: */ INTERACT_COIN,
/* downOffset: */ 0,
@@ -12,36 +19,54 @@ static struct ObjectHitbox sRedCoinHitbox = {
/* hurtboxHeight: */ 0,
};
/**
* Red coin initialization function. Sets the coin's hitbox and parent object.
*/
void bhv_red_coin_init(void) {
struct Surface *sp24;
UNUSED f32 sp20 = find_floor(o->oPosX, o->oPosY, o->oPosZ, &sp24);
struct Object *sp1C;
// This floor and floor height are unused. Perhaps for orange number spawns originally?
struct Surface *dummyFloor;
UNUSED f32 floorHeight = find_floor(o->oPosX, o->oPosY, o->oPosZ, &dummyFloor);
sp1C = obj_nearest_object_with_behavior(bhvHiddenRedCoinStar);
if (sp1C != NULL)
o->parentObj = sp1C;
struct Object *hiddenRedCoinStar;
// Set the red coins to have a parent of the closest red coin star.
hiddenRedCoinStar = obj_nearest_object_with_behavior(bhvHiddenRedCoinStar);
if (hiddenRedCoinStar != NULL)
o->parentObj = hiddenRedCoinStar;
else {
sp1C = obj_nearest_object_with_behavior(bhvBowserCourseRedCoinStar);
if (sp1C != NULL)
o->parentObj = sp1C;
else
hiddenRedCoinStar = obj_nearest_object_with_behavior(bhvBowserCourseRedCoinStar);
if (hiddenRedCoinStar != NULL) {
o->parentObj = hiddenRedCoinStar;
} else {
o->parentObj = NULL;
}
}
set_object_hitbox(o, &sRedCoinHitbox);
}
/**
* Main behavior for red coins. Primarily controls coin collection noise and spawning
* the orange number counter.
*/
void bhv_red_coin_loop(void) {
// If Mario interacted with the object...
if (o->oInteractStatus & INT_STATUS_INTERACTED) {
// ...and there is a red coin star in the level...
if (o->parentObj != NULL) {
// ...increment the star's counter.
o->parentObj->oHiddenStarTriggerCounter++;
// For JP version, play an identical sound for all coins.
#ifdef VERSION_JP
create_sound_spawner(SOUND_GENERAL_RED_COIN);
#endif
// Spawn the orange number counter, as long as it isn't the last coin.
if (o->parentObj->oHiddenStarTriggerCounter != 8) {
SpawnOrangeNumber(o->parentObj->oHiddenStarTriggerCounter, 0, 0, 0);
spawn_orange_number(o->parentObj->oHiddenStarTriggerCounter, 0, 0, 0);
}
// On all versions but the JP version, each coin collected plays a higher noise.
#ifndef VERSION_JP
play_sound(SOUND_MENU_COLLECT_RED_COIN
+ (((u8) o->parentObj->oHiddenStarTriggerCounter - 1) << 16),
@@ -50,6 +75,7 @@ void bhv_red_coin_loop(void) {
}
CoinCollected();
// Despawn the coin.
o->oInteractStatus = 0;
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ void func_802F238C(void) {
if (o->oAngleVelPitch < -0x200)
o->oAngleVelPitch = -0x200;
} else {
if (IsPointCloseToObject(o, o->oHomeX, o->oHomeY, o->oHomeZ, 100)) {
if (is_point_close_to_object(o, o->oHomeX, o->oHomeY, o->oHomeZ, 100)) {
if (o->oAngleVelPitch != 0) {
if (o->oAngleVelPitch > 0)
o->oAngleVelPitch -= 0x10;
+11 -11
View File
@@ -56,7 +56,7 @@ void func_802EFC44(void) {
UNUSED s16 sp1E;
o->oPathedStartWaypoint = segmented_to_virtual(&ccm_seg7_trajectory_snowman);
sp26 = func_802E4204();
sp26 = object_step_without_floor_orient();
sp20 = obj_follow_path(sp20);
o->oSnowmansBottomUnkF8 = o->oPathedTargetYaw;
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oSnowmansBottomUnkF8, 0x400);
@@ -66,7 +66,7 @@ void func_802EFC44(void) {
if (sp20 == -1) {
sp1E = (u16) o->oAngleToMario - (u16) o->oMoveAngleYaw;
if (func_802E46C0(o->oMoveAngleYaw, o->oAngleToMario, 0x2000) == 1 && o->oSnowmansBottomUnk1AC == 1) {
if (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x2000) == 1 && o->oSnowmansBottomUnk1AC == 1) {
o->oSnowmansBottomUnkF8 = o->oAngleToMario;
} else {
o->oSnowmansBottomUnkF8 = o->oMoveAngleYaw;
@@ -78,12 +78,12 @@ void func_802EFC44(void) {
void func_802EFDA0(void) {
UNUSED s16 sp26;
sp26 = func_802E4204();
sp26 = object_step_without_floor_orient();
if (o->oForwardVel > 70.0)
o->oForwardVel = 70.0f;
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oSnowmansBottomUnkF8, 0x400);
if (IsPointCloseToObject(o, -4230.0f, -1344.0f, 1813.0f, 300)) {
if (is_point_close_to_object(o, -4230.0f, -1344.0f, 1813.0f, 300)) {
func_802AA618(0, 0, 70.0f);
o->oMoveAngleYaw = atan2s(1813.0f - o->oPosZ, -4230.0f - o->oPosX);
o->oVelY = 80.0f;
@@ -104,7 +104,7 @@ void func_802EFDA0(void) {
void func_802EFF58(void) {
UNUSED s16 sp1E;
sp1E = func_802E4204();
sp1E = object_step_without_floor_orient();
if ((sp1E & 0x09) == 0x09) {
o->oAction = 4;
obj_become_intangible();
@@ -125,7 +125,7 @@ void bhv_snowmans_bottom_loop(void) {
case 0:
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 400) == 1
&& set_mario_npc_dialog(1) == 2) {
sp1E = cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, 110);
sp1E = cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, DIALOG_110);
if (sp1E) {
o->oForwardVel = 10.0f;
o->oAction = 1;
@@ -156,7 +156,7 @@ void bhv_snowmans_bottom_loop(void) {
}
func_802EFB2C();
SetObjectVisibility(o, 8000);
set_object_visibility(o, 8000);
obj_scale(o->oSnowmansBottomUnkF4);
o->oGraphYOffset = o->oSnowmansBottomUnkF4 * 180.0f;
}
@@ -190,7 +190,7 @@ void bhv_snowmans_head_loop(void) {
switch (o->oAction) {
case 0:
if (func_802E4A38(&o->oSnowmansHeadUnkF4, 109, 400.0f, 1))
if (trigger_obj_dialog_when_facing(&o->oSnowmansHeadUnkF4, DIALOG_109, 400.0f, 1))
o->oAction = 1;
break;
@@ -198,13 +198,13 @@ void bhv_snowmans_head_loop(void) {
break;
case 2:
sp1C = func_802E4204();
sp1C = object_step_without_floor_orient();
if (sp1C & 0x08)
o->oAction = 3;
break;
case 3:
func_802E4204();
object_step_without_floor_orient();
if (o->oPosY < -994.0f) {
o->oPosY = -994.0f;
o->oAction = 4;
@@ -214,7 +214,7 @@ void bhv_snowmans_head_loop(void) {
break;
case 4:
if (func_802E4A38(&o->oSnowmansHeadUnkF4, 111, 700.0f, 2)) {
if (trigger_obj_dialog_when_facing(&o->oSnowmansHeadUnkF4, DIALOG_111, 700.0f, 2)) {
func_802A3004();
create_star(-4700.0f, -1024.0f, 1890.0f);
o->oAction = 1;
+1 -1
View File
@@ -15,7 +15,7 @@ void bhv_snowman_wind_blowing_loop(void) {
o->oSubAction++;
func_802B8F7C(&o->oPosX, pos);
} else if (o->oSubAction == 1) {
if (obj_update_dialog(2, 2, 153, 0))
if (obj_update_dialog(2, 2, DIALOG_153, 0))
o->oSubAction++;
} else if (o->oDistanceToMario < 1500.0f && absf(gMarioObject->oPosY - o->oHomeY) < 500.0f) {
if ((sp32 = o->oAngleToMario - o->oSnowmanWindBlowingUnkF4) > 0) {
+8 -8
View File
@@ -27,7 +27,7 @@ static void swoop_act_idle(void) {
set_obj_animation_and_sound_state(1);
if (approach_f32_ptr(&o->header.gfx.scale[0], 1.0f, 0.05f) && o->oDistanceToMario < 1500.0f) {
if (obj_rotate_yaw_toward(o->oAngleToMario, 0x320)) {
if (obj_rotate_yaw_toward(o->oAngleToMario, 800)) {
PlaySound2(SOUND_OBJ2_SWOOP);
o->oAction = SWOOP_ACT_MOVE;
o->oVelY = -12.0f;
@@ -49,7 +49,7 @@ static void swoop_act_move(void) {
if (o->oForwardVel == 0.0f) {
// If we haven't started moving yet, begin swooping
if (obj_face_roll_approach(0, 0x9C4)) {
if (obj_face_roll_approach(0, 2500)) {
o->oForwardVel = 10.0f;
o->oVelY = -10.0f;
}
@@ -74,23 +74,23 @@ static void swoop_act_move(void) {
obj_y_vel_approach(-10.0f, 0.5f);
}
} else if (o->oMoveFlags & OBJ_MOVE_HIT_WALL) {
// Bounce off walls and get stunned for a second
// Bounce off a wall and don't bounce again for 30 frames.
o->oSwoopTargetYaw = obj_reflect_move_angle_off_wall();
o->oSwoopBonkCountdown = 30;
}
// Tilt upward when approaching mario
if ((o->oSwoopTargetPitch = obj_get_pitch_from_vel()) == 0) {
o->oSwoopTargetPitch += o->oForwardVel * 0x1F4;
o->oSwoopTargetPitch += o->oForwardVel * 500;
}
obj_move_pitch_approach(o->oSwoopTargetPitch, 0x8C);
obj_move_pitch_approach(o->oSwoopTargetPitch, 140);
// Jitter yaw a bit
obj_rotate_yaw_toward(o->oSwoopTargetYaw + (s32)(0xBB8 * coss(0xFA0 * gGlobalTimer)), 0x4B0);
obj_roll_to_match_yaw_turn(o->oSwoopTargetYaw, 0x3000, 0x1F4);
obj_rotate_yaw_toward(o->oSwoopTargetYaw + (s32)(3000 * coss(4000 * gGlobalTimer)), 1200);
obj_roll_to_match_yaw_turn(o->oSwoopTargetYaw, 0x3000, 500);
// Jitter roll a bit
o->oFaceAngleRoll += (s32)(0x3E8 * coss(0x4E20 * gGlobalTimer));
o->oFaceAngleRoll += (s32)(1000 * coss(20000 * gGlobalTimer));
}
}
@@ -0,0 +1,138 @@
/**
* This is the behavior file for the tilting inverted pyramids in BitFS/LLL.
* The object essentially just tilts and moves Mario with it.
*/
/**
* Creates a transform matrix on a variable passed in from given normals
* and the object's position.
*/
void create_transform_from_normals(Mat4 transform, f32 xNorm, f32 yNorm, f32 zNorm) {
Vec3f normal;
Vec3f pos;
pos[0] = o->oPosX;
pos[1] = o->oPosY;
pos[2] = o->oPosZ;
normal[0] = xNorm;
normal[1] = yNorm;
normal[2] = zNorm;
mtxf_align_terrain_normal(transform, normal, pos, 0);
}
/**
* Initialize the object's transform matrix with Y being up.
*/
void bhv_platform_normals_init(void) {
Mat4 *transform = &o->transform;
o->oTiltingPyramidNormalX = 0.0f;
o->oTiltingPyramidNormalY = 1.0f;
o->oTiltingPyramidNormalZ = 0.0f;
create_transform_from_normals(*transform, 0.0f, 1.0f, 0.0f);
}
/**
* Returns a value that is src incremented/decremented by inc towards goal
* until goal is reached. Does not overshoot.
*/
f32 approach_by_increment(f32 goal, f32 src, f32 inc) {
f32 newVal;
if (src <= goal) {
if (goal - src < inc) {
newVal = goal;
} else {
newVal = src + inc;
}
} else if (goal - src > -inc) {
newVal = goal;
} else {
newVal = src - inc;
}
return newVal;
}
/**
* Main behavior for the tilting pyramids in LLL/BitFS. These platforms calculate rough normals from Mario's position,
* then gradually tilt back moving Mario with them.
*/
void bhv_tilting_inverted_pyramid_loop(void) {
f32 dx;
f32 dy;
f32 dz;
f32 d;
Vec3f dist;
Vec3f posBeforeRotation;
Vec3f posAfterRotation;
// Mario's position
f32 mx;
f32 my;
f32 mz;
s32 marioOnPlatform = FALSE;
UNUSED s32 unused;
Mat4 *transform = &o->transform;
UNUSED s32 unused2[7];
if (gMarioObject->platform == o) {
get_mario_pos(&mx, &my, &mz);
dist[0] = gMarioObject->oPosX - o->oPosX;
dist[1] = gMarioObject->oPosY - o->oPosY;
dist[2] = gMarioObject->oPosZ - o->oPosZ;
linear_mtxf_mul_vec3f(*transform, posBeforeRotation, dist);
dx = gMarioObject->oPosX - o->oPosX;
dy = 500.0f;
dz = gMarioObject->oPosZ - o->oPosZ;
d = sqrtf(dx * dx + dy * dy + dz * dz);
//! Always true since dy = 500, making d >= 500.
if (d != 0.0f) {
// Normalizing
d = 1.0 / d;
dx *= d;
dy *= d;
dz *= d;
} else {
dx = 0.0f;
dy = 1.0f;
dz = 0.0f;
}
if (o->oTiltingPyramidMarioOnPlatform == TRUE)
marioOnPlatform++;
o->oTiltingPyramidMarioOnPlatform = TRUE;
} else {
dx = 0.0f;
dy = 1.0f;
dz = 0.0f;
o->oTiltingPyramidMarioOnPlatform = FALSE;
}
// Approach the normals by 0.01f towards the new goal, then create a transform matrix and orient the object.
// Outside of the other conditionals since it needs to tilt regardless of whether Mario is on.
o->oTiltingPyramidNormalX = approach_by_increment(dx, o->oTiltingPyramidNormalX, 0.01f);
o->oTiltingPyramidNormalY = approach_by_increment(dy, o->oTiltingPyramidNormalY, 0.01f);
o->oTiltingPyramidNormalZ = approach_by_increment(dz, o->oTiltingPyramidNormalZ, 0.01f);
create_transform_from_normals(*transform, o->oTiltingPyramidNormalX, o->oTiltingPyramidNormalY, o->oTiltingPyramidNormalZ);
// If Mario is on the platform, adjust his position for the platform tilt.
if (marioOnPlatform != FALSE) {
linear_mtxf_mul_vec3f(*transform, posAfterRotation, dist);
mx += posAfterRotation[0] - posBeforeRotation[0];
my += posAfterRotation[1] - posBeforeRotation[1];
mz += posAfterRotation[2] - posBeforeRotation[2];
set_mario_pos(mx, my, mz);
}
o->header.gfx.throwMatrix = transform;
}
+2 -2
View File
@@ -39,7 +39,7 @@ void bhv_treasure_chest_top_loop(void) {
o->oFaceAnglePitch = -0x4000;
o->oAction++;
if (o->parentObj->oBehParams2ndByte != 4)
SpawnOrangeNumber(o->parentObj->oBehParams2ndByte, 0, -40, 0);
spawn_orange_number(o->parentObj->oBehParams2ndByte, 0, -40, 0);
}
break;
@@ -65,7 +65,7 @@ void bhv_treasure_chest_bottom_init(void) {
void bhv_treasure_chest_bottom_loop(void) {
switch (o->oAction) {
case 0:
if (func_802E46C0(o->oMoveAngleYaw, gMarioObject->header.gfx.angle[1] + 0x8000, 0x3000)) {
if (obj_check_if_facing_toward_angle(o->oMoveAngleYaw, gMarioObject->header.gfx.angle[1] + 0x8000, 0x3000)) {
if (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 150)) {
if (!o->parentObj->oTreasureChestUnkF8) {
if (o->parentObj->oTreasureChestUnkF4 == o->oBehParams2ndByte) {
+1 -1
View File
@@ -36,7 +36,7 @@ void bhv_ttc_pendulum_update(void) {
// Play sound
if (o->oTTCPendulumSoundTimer != 0) {
if (--o->oTTCPendulumSoundTimer == 0) {
PlaySound2(SOUND_GENERAL_SWITCH1);
PlaySound2(SOUND_GENERAL_PENDULUM_SWING);
}
}
+6 -6
View File
@@ -62,11 +62,11 @@ void ActionTuxiesMother1(void) {
sp2C = (o->oBehParams >> 0x10) & 0xFF;
sp28 = (o->prevObj->oBehParams >> 0x10) & 0xFF;
if (sp2C == sp28)
dialogID = 58;
dialogID = DIALOG_058;
else
dialogID = 59;
dialogID = DIALOG_059;
if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, dialogID)) {
if (dialogID == 58)
if (dialogID == DIALOG_058)
o->oSubAction = 1;
else
o->oSubAction = 2;
@@ -128,7 +128,7 @@ void ActionTuxiesMother0(void) {
o->oSubAction++;
break;
case 1:
if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, 57))
if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, DIALOG_057))
o->oSubAction++;
break;
case 2:
@@ -294,7 +294,7 @@ void bhv_small_penguin_loop(void) {
/** Geo switch logic for Tuxie's mother's eyes. Cases 0-4. Interestingly, case
* 4 is unused, and is the eye state seen in Shoshinkai 1995 footage.
*/
s32 geo_switch_tuxie_mother_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx) {
Gfx *geo_switch_tuxie_mother_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *mtx) {
struct Object *obj;
struct GraphNodeSwitchCase *switchCase;
s32 timer;
@@ -323,5 +323,5 @@ s32 geo_switch_tuxie_mother_eyes(s32 run, struct GraphNode *node, UNUSED Mat4 *m
if (obj->oForwardVel > 5.0f)
switchCase->selectedCase = 3;
}
return 0;
return NULL;
}
+4 -4
View File
@@ -384,7 +384,7 @@ void ukiki_act_go_to_cage(void) {
case UKIKI_SUB_ACT_CAGE_TALK_TO_MARIO:
set_obj_animation_and_sound_state(UKIKI_ANIM_HANDSTAND);
if (obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG_1, 80)) {
if (obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG_1, DIALOG_080)) {
o->oSubAction++;
}
break;
@@ -518,7 +518,7 @@ void cage_ukiki_held_loop(void) {
switch(o->oUkikiTextState) {
case UKIKI_TEXT_DEFAULT:
if (set_mario_npc_dialog(2) == 2) {
create_dialog_box_with_response(79);
create_dialog_box_with_response(DIALOG_079);
o->oUkikiTextState = UKIKI_TEXT_CAGE_TEXTBOX;
}
break;
@@ -568,7 +568,7 @@ void hat_ukiki_held_loop(void) {
break;
case UKIKI_TEXT_STEAL_HAT:
if (obj_update_dialog(2, 2, 100, 0)) {
if (obj_update_dialog(2, 2, DIALOG_100, 0)) {
o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY;
o->oUkikiTextState = UKIKI_TEXT_STOLE_HAT;
}
@@ -578,7 +578,7 @@ void hat_ukiki_held_loop(void) {
break;
case UKIKI_TEXT_HAS_HAT:
if (obj_update_dialog(2, 18, 101, 0)) {
if (obj_update_dialog(2, 18, DIALOG_101, 0)) {
mario_retrieve_cap();
set_mario_npc_dialog(0);
o->oUkikiHasHat &= ~UKIKI_HAT_ON;
+4 -4
View File
@@ -48,7 +48,7 @@ void CheckWaterRingCollection(f32 avgScale, struct Object *ringManager) {
f32 marioDistInFront = WaterRingCalcMarioDistInFront();
struct Object *ringSpawner;
if (!IsPointCloseToObject(o, gMarioObject->header.gfx.pos[0],
if (!is_point_close_to_object(o, gMarioObject->header.gfx.pos[0],
gMarioObject->header.gfx.pos[1] + 80.0f, gMarioObject->header.gfx.pos[2],
(avgScale + 0.2) * 120.0)) {
o->oWaterRingMarioDistInFront = marioDistInFront;
@@ -62,7 +62,7 @@ void CheckWaterRingCollection(f32 avgScale, struct Object *ringManager) {
|| (ringSpawner->oWaterRingSpawnerRingsCollected == 0)) {
ringSpawner->oWaterRingSpawnerRingsCollected++;
if (ringSpawner->oWaterRingSpawnerRingsCollected < 6) {
SpawnOrangeNumber(ringSpawner->oWaterRingSpawnerRingsCollected, 0, -40, 0);
spawn_orange_number(ringSpawner->oWaterRingSpawnerRingsCollected, 0, -40, 0);
#ifdef VERSION_JP
play_sound(SOUND_MENU_STAR_SOUND, gDefaultSoundArgs);
#else
@@ -124,7 +124,7 @@ void JetStreamWaterRingNotCollectedLoop(void) {
o->oPosY += 10.0f;
o->oFaceAngleYaw += 0x100;
SetObjectVisibility(o, 5000);
set_object_visibility(o, 5000);
if (ringSpawner->oWaterRingSpawnerRingsCollected == 4
&& o->oWaterRingIndex == ringManager->oWaterRingMgrLastRingCollected + 1)
@@ -212,7 +212,7 @@ void MantaRayWaterRingNotCollectedLoop(void) {
CheckWaterRingCollection(avgScale, ringManager);
SetWaterRingScale(avgScale);
SetObjectVisibility(o, 5000);
set_object_visibility(o, 5000);
if (ringSpawner->oWaterRingSpawnerRingsCollected == 4
&& o->oWaterRingIndex == ringManager->oWaterRingMgrLastRingCollected + 1)
+1 -1
View File
@@ -31,7 +31,7 @@ void func_802E70DC(void) {
f32 normalX = sinRoll * cosPitch;
f32 normalY = cosPitch * cosRoll;
f32 normalZ = sinPitch;
ObjOrientGraph(o, normalX, normalY, normalZ);
obj_orient_graph(o, normalX, normalY, normalZ);
}
void bhv_whirlpool_loop(void) {
+2 -2
View File
@@ -28,7 +28,7 @@ void ActionWhomp0(void) {
obj_set_pos_to_home();
o->oHealth = 3;
}
} else if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, 114))
} else if (obj_update_dialog_with_cutscene(2, 1, CUTSCENE_DIALOG_1, DIALOG_114))
o->oAction = 2;
} else if (o->oDistanceToMario < 500.0f)
o->oAction = 1;
@@ -209,7 +209,7 @@ void ActionWhomp6(void) {
void ActionWhomp8(void) {
if (o->oBehParams2ndByte != 0) {
if (obj_update_dialog_with_cutscene(2, 2, CUTSCENE_DIALOG_1, 115)) {
if (obj_update_dialog_with_cutscene(2, 2, CUTSCENE_DIALOG_1, DIALOG_115)) {
set_object_angle(o, 0, 0, 0);
obj_hide();
obj_become_intangible();
+8 -3
View File
@@ -224,13 +224,14 @@ static void wiggler_act_walk(void) {
// If Mario is positioned below the wiggler, assume he entered through the
// lower cave entrance, so don't display text.
if (gMarioObject->oPosY < o->oPosY || obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG_1, 150) != 0) {
if (gMarioObject->oPosY < o->oPosY || obj_update_dialog_with_cutscene(2, 0, CUTSCENE_DIALOG_1, DIALOG_150) != 0) {
o->oWigglerTextStatus = WIGGLER_TEXT_STATUS_COMPLETED_DIALOG;
}
} else {
//! Every object's health is initially 2048, and wiggler's doesn't change
// to 4 until after this runs the first time. It indexes out of bounds
// and uses the value 113762.3 for one frame on US.
// and uses the value 113762.3 for one frame on US. This is fixed down
// below in bhv_wiggler_update if AVOID_UB is defined.
obj_forward_vel_approach(sWigglerSpeeds[o->oHealth - 1], 1.0f);
if (o->oWigglerWalkAwayFromWallTimer != 0) {
@@ -286,7 +287,7 @@ static void wiggler_act_walk(void) {
*/
static void wiggler_act_jumped_on(void) {
// Text to show on first, second, and third attack.
s32 attackText[3] = { 0x98, 0xA8, 0x97 };
s32 attackText[3] = { DIALOG_152, DIALOG_168, DIALOG_151 };
// Shrink until the squish speed becomes 0, then unisquish
if (approach_f32_ptr(&o->oWigglerSquishSpeed, 0.0f, 0.05f)) {
@@ -398,6 +399,10 @@ void bhv_wiggler_update(void) {
// PARTIAL_UPDATE
if (o->oAction == WIGGLER_ACT_UNINITIALIZED) {
#ifdef AVOID_UB
// See comment in wiggler_act_walk
o->oHealth = 4;
#endif
wiggler_init_segments();
} else {
if (o->oAction == WIGGLER_ACT_FALL_THROUGH_FLOOR) {
+7 -7
View File
@@ -11,7 +11,7 @@ void bhv_yoshi_init(void) {
o->oBuoyancy = 1.3f;
o->oInteractionSubtype = INT_SUBTYPE_NPC;
if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24) < 120 || D_80331508 == 1) {
if (save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24) < 120 || sYoshiDead == TRUE) {
o->activeFlags = 0;
}
}
@@ -21,9 +21,9 @@ void yoshi_walk_loop(void) {
s16 sp24 = o->header.gfx.unk38.animFrame;
o->oForwardVel = 10.0f;
sp26 = ObjectStep();
sp26 = object_step();
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oYoshiTargetYaw, 0x500);
if (IsPointCloseToObject(o, o->oHomeX, 3174.0f, o->oHomeZ, 200))
if (is_point_close_to_object(o, o->oHomeX, 3174.0f, o->oHomeZ, 200))
o->oAction = YOSHI_ACT_IDLE;
SetObjAnimation(1);
@@ -76,7 +76,7 @@ void yoshi_talk_loop(void) {
SetObjAnimation(0);
if (set_mario_npc_dialog(1) == 2) {
o->activeFlags |= 0x20;
if (cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, 161)) {
if (cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, DIALOG_161)) {
o->activeFlags &= ~0x20;
o->oInteractStatus = 0;
o->oHomeX = sYoshiHomeLocations[2];
@@ -96,13 +96,13 @@ void yoshi_walk_and_jump_off_roof_loop(void) {
s16 sp26 = o->header.gfx.unk38.animFrame;
o->oForwardVel = 10.0f;
ObjectStep();
object_step();
SetObjAnimation(1);
if (o->oTimer == 0)
cutscene_object(CUTSCENE_STAR_SPAWN, o);
o->oMoveAngleYaw = approach_s16_symmetric(o->oMoveAngleYaw, o->oYoshiTargetYaw, 0x500);
if (IsPointCloseToObject(o, o->oHomeX, 3174.0f, o->oHomeZ, 200)) {
if (is_point_close_to_object(o, o->oHomeX, 3174.0f, o->oHomeZ, 200)) {
SetObjAnimation(2);
PlaySound2(SOUND_GENERAL_ENEMY_ALERT1);
o->oForwardVel = 50.0f;
@@ -123,7 +123,7 @@ void yoshi_finish_jumping_and_despawn_loop(void) {
if (o->oPosY < 2100.0f) {
set_mario_npc_dialog(0);
gCutsceneActive = 1;
D_80331508 = 1;
sYoshiDead = 1;
o->activeFlags = 0;
}
}
+72 -63
View File
@@ -5,6 +5,7 @@
#include "sm64.h"
#include "camera.h"
#include "seq_ids.h"
#include "dialog_ids.h"
#include "audio/external.h"
#include "mario_misc.h"
#include "game.h"
@@ -28,6 +29,7 @@
#include "paintings.h"
#include "prevent_bss_reordering.h"
#include "engine/graph_node.h"
#include "level_table.h"
#define CBUTTON_MASK (U_CBUTTONS | D_CBUTTONS | L_CBUTTONS | R_CBUTTONS)
@@ -2640,7 +2642,7 @@ void init_camera(struct LevelCamera *c) {
c->storedYaw = gCameraStatus.trueYaw;
}
extern u8 D_8032E910[20];
extern u8 zoomOutAreaMasks[20];
void func_80287404(struct GraphNodeCamera *a) {
UNUSED u8 unused1[8];
@@ -2651,13 +2653,13 @@ void func_80287404(struct GraphNodeCamera *a) {
s32 sp28 = gCurrLevelArea / 32;
s32 sp24 = 1 << (((gCurrLevelArea & 0x10) / 4) + (((gCurrLevelArea & 0xF) - 1) & 3));
if (sp28 >= ARRAY_COUNT(D_8032E910) - 1) {
if (sp28 >= ARRAY_COUNT(zoomOutAreaMasks) - 1) {
sp28 = 0;
sp24 = 0;
}
if (gCameraMovementFlags & CAM_MOVE_PAUSE_SCREEN) {
if (gFramesPaused >= 2) {
if (D_8032E910[sp28] & sp24) {
if (zoomOutAreaMasks[sp28] & sp24) {
a->to[0] = gCurrLevelCamera->xFocus;
a->to[1] = (sMarioStatusForCamera->pos[1] + gCurrLevelCamera->unk68) / 2.f;
a->to[2] = gCurrLevelCamera->zFocus;
@@ -5125,48 +5127,24 @@ struct TableCamera TableCameraBBH[61] = {
TABLE_EMPTY
};
struct TableCamera *TableLevelCinematicCamera[40] = {
NULL,
NULL,
NULL,
NULL,
TableCameraBBH,
TableCameraCCM,
TableCameraInside,
TableCameraHMC,
TableCameraSSL,
NULL,
TableCameraSL,
NULL,
NULL,
TableCameraTHI,
NULL,
TableCameraRR,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
TableCameraCotMC,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
#define _ NULL
#define STUB_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, cameratable) cameratable,
#define DEFINE_LEVEL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, cameratable) cameratable,
/*
* This table has an extra 2 levels after the last unknown_38 stub level. What I think
* the programmer was thinking was that the table is null terminated and so used the
* level count as a coorespondance to the ID of the final level, but the enum represents
* an ID *after* the last stub lebel, not before or during it.
*/
struct TableCamera *TableLevelCinematicCamera[LEVEL_COUNT + 1] = {
NULL,
#include "levels/level_defines.h"
};
#undef _
#undef STUB_LEVEL
#undef DEFINE_LEVEL
struct CutsceneSplinePoint sIntroStartToPipePosition[23] = {
{ 0, 0, { 2122, 8762, 9114 } }, { 0, 0, { 2122, 8762, 9114 } }, { 1, 0, { 2122, 7916, 9114 } },
@@ -5608,7 +5586,7 @@ s16 cutscene_object_with_dialog(u8 cutsceneTable, struct Object *o, s16 dialogID
if (dialogID != -1) {
D_8033B320 = dialogID;
} else {
D_8033B320 = 1;
D_8033B320 = DIALOG_001;
}
} else {
sp1E = D_8032CFFC;
@@ -6533,13 +6511,13 @@ CmdRet bowser_fight_intro_dialog(UNUSED struct LevelCamera *c) {
switch (gCurrLevelNum) {
case LEVEL_BOWSER_1:
dialog = 67;
dialog = DIALOG_067;
break;
case LEVEL_BOWSER_2:
dialog = 92;
dialog = DIALOG_092;
break;
default:
dialog = 93;
dialog = DIALOG_093;
}
create_dialog_box(dialog);
@@ -7458,7 +7436,7 @@ CmdRet CutsceneCapSwitchPress0_3(struct LevelCamera *c) {
}
CmdRet CutsceneCapSwitchPress0_6(UNUSED struct LevelCamera *c) {
create_dialog_box_with_response(gCutsceneFocus->oBehParams2ndByte + 10);
create_dialog_box_with_response(gCutsceneFocus->oBehParams2ndByte + DIALOG_010);
}
static void unused_802968E8(struct LevelCamera *c) {
@@ -7570,7 +7548,7 @@ s32 intro_peach_move_camera_start_to_pipe(struct LevelCamera *c, struct Cutscene
}
CmdRet peach_letter_text(UNUSED struct LevelCamera *c) {
create_dialog_box(20);
create_dialog_box(DIALOG_020);
}
#ifndef VERSION_JP
@@ -7621,7 +7599,7 @@ CmdRet CutsceneIntroPeach3_3(UNUSED struct LevelCamera *c) {
}
CmdRet intro_pipe_exit_text(UNUSED struct LevelCamera *c) {
create_dialog_box(33);
create_dialog_box(DIALOG_033);
}
#ifndef VERSION_JP
@@ -8359,20 +8337,51 @@ struct CutsceneTableEntry TableCutsceneReadMessage[3] = { { CutsceneReadMessage0
{ CutsceneReadMessage1, 15 },
{ CutsceneReadMessage2, 0 } };
u8 D_8032E8A4[27][4] = {
{ 0x44, 0x44, 0x44, 0x04 }, { 0x00, 0x20, 0x22, 0x04 }, { 0x00, 0x00, 0x02, 0x04 },
{ 0x22, 0x22, 0x22, 0x04 }, { 0x00, 0x22, 0x00, 0x04 }, { 0x22, 0x22, 0x22, 0x04 },
{ 0x22, 0x22, 0x22, 0x04 }, { 0x12, 0x12, 0x12, 0x04 }, { 0x02, 0x22, 0x22, 0x04 },
{ 0x22, 0x22, 0x22, 0x04 }, { 0x20, 0x20, 0x20, 0x04 }, { 0x22, 0x01, 0x22, 0x04 },
{ 0x00, 0x00, 0x00, 0x04 }, { 0x11, 0x11, 0x12, 0x04 }, { 0x22, 0x22, 0x22, 0x04 },
{ 0x00, 0x00, 0x00, 0x04 }, { 0x43, 0x44, 0x44, 0x04 }, { 0x43, 0x44, 0x44, 0x04 },
{ 0x43, 0x44, 0x44, 0x04 }, { 0x42, 0x44, 0x44, 0x04 }, { 0x44, 0x44, 0x44, 0x04 },
{ 0x40, 0x44, 0x44, 0x04 }, { 0x42, 0x44, 0x44, 0x04 }, { 0x40, 0x44, 0x44, 0x04 },
{ 0x42, 0x44, 0x44, 0x04 }, { 0x44, 0x44, 0x44, 0x04 }, { 0x44, 0x44, 0x44, 0x04 }
};
#define DEFINE_COURSE(_0, i1, i2, i3, i4) { i1, i2, i3, i4 },
#define DEFINE_COURSES_END()
#define DEFINE_BONUS_COURSE(_0, i1, i2, i3, i4) { i1, i2, i3, i4 },
u8 D_8032E910[20] = { 0x00, 0x00, 0x10, 0x00, 0x11, 0x11, 0x30, 0x10, 0x11, 0x10,
0x10, 0x01, 0x01, 0x00, 0x10, 0x11, 0x10, 0x01, 0x01, 0x00 };
u8 D_8032E8A4[27][4] = {
{ 0x44, 0x44, 0x44, 0x04 }, // (0) Course Hub (Castle Grounds)
#include "levels/course_defines.h"
{ 0x44, 0x44, 0x44, 0x04 } // an extra course, hmm...
};
#undef DEFINE_COURSE
#undef DEFINE_COURSES_END
#undef DEFINE_BONUS_COURSE
/**
* These masks set whether or not the camera zooms out when game is paused.
*
* Each entry is used by two levels. Even levels use the low 4 bits, odd levels use the high 4 bits
* Because areas are 1-indexed, a mask of 0x1 will make area 1 (not area 0) zoom out.
*
* In zoom_out_if_paused_and_outside(), the current area is converted to a shift.
* Then the value of (1 << shift) is &'d with the level's mask,
* and if the result is non-zero, the camera will zoom out.
*/
u8 zoomOutAreaMasks[20] = {
ZOOMOUT_AREA_MASK(0,0,0,0, 0,0,0,0), // Unused | Unused
ZOOMOUT_AREA_MASK(0,0,0,0, 0,0,0,0), // Unused | Unused
ZOOMOUT_AREA_MASK(0,0,0,0, 1,0,0,0), // BBH | CCM
ZOOMOUT_AREA_MASK(0,0,0,0, 0,0,0,0), // CASTLE_INSIDE | HMC
ZOOMOUT_AREA_MASK(1,0,0,0, 1,0,0,0), // SSL | BOB
ZOOMOUT_AREA_MASK(1,0,0,0, 1,0,0,0), // SL | WDW
ZOOMOUT_AREA_MASK(0,0,0,0, 1,1,0,0), // JRB | THI
ZOOMOUT_AREA_MASK(0,0,0,0, 1,0,0,0), // TTC | RR
ZOOMOUT_AREA_MASK(1,0,0,0, 1,0,0,0), // CASTLE_GROUNDS | BITDW
ZOOMOUT_AREA_MASK(0,0,0,0, 1,0,0,0), // VCUTM | BITFS
ZOOMOUT_AREA_MASK(0,0,0,0, 1,0,0,0), // SA | BITS
ZOOMOUT_AREA_MASK(1,0,0,0, 0,0,0,0), // LLL | DDD
ZOOMOUT_AREA_MASK(1,0,0,0, 0,0,0,0), // WF | ENDING
ZOOMOUT_AREA_MASK(0,0,0,0, 0,0,0,0), // COURTYARD | PSS
ZOOMOUT_AREA_MASK(0,0,0,0, 1,0,0,0), // COTMC | TOTWC
ZOOMOUT_AREA_MASK(1,0,0,0, 1,0,0,0), // BOWSER_1 | WMOTR
ZOOMOUT_AREA_MASK(0,0,0,0, 1,0,0,0), // Unused | BOWSER_2
ZOOMOUT_AREA_MASK(1,0,0,0, 0,0,0,0), // BOWSER_3 | Unused
ZOOMOUT_AREA_MASK(1,0,0,0, 0,0,0,0), // TTM | Unused
ZOOMOUT_AREA_MASK(0,0,0,0, 0,0,0,0), // Unused | Unused
};
struct CutsceneSplinePoint sBobCreditsCameraPositions[5] = { { 1, 0, { 5984, 3255, 4975 } },
{ 2, 0, { 4423, 3315, 1888 } },
+48 -44
View File
@@ -6,52 +6,56 @@
#include "engine/geo_layout.h"
#include "engine/graph_node.h"
#include "level_table.h"
#define ABS(x) ((x) > 0.f ? (x) : -(x))
#define ABS2(x) ((x) >= 0.f ? (x) : -(x))
#define AREA_BBH 0x0041
#define AREA_CCM_OUTSIDE 0x0051
#define AREA_CCM_SLIDE 0x0052
#define AREA_CASTLE_LOBBY 0x0061
#define AREA_CASTLE_TIPPY 0x0062
#define AREA_CASTLE_BASTEMENT 0x0063
#define AREA_HMC 0x0071
#define AREA_SSL_OUTSIDE 0x0081
#define AREA_SSL_PYRAMID 0x0082
#define AREA_SSL_EYEROK 0x0083
#define AREA_BOB 0x0091
#define AREA_SL_OUTSIDE 0x00A1
#define AREA_SL_IGLOO 0x00A2
#define AREA_WDW_MAIN 0x00B1
#define AREA_WDW_TOWN 0x00B2
#define AREA_JRB_MAIN 0x00C1
#define AREA_JRB_SHIP 0x00C2
#define AREA_THI_HUGE 0x00D1
#define AREA_THI_TINY 0x00D2
#define AREA_THI_WIGGLER 0x00D3
#define AREA_TTC 0x00E1
#define AREA_RR 0x00F1
#define AREA_OUTSIDE_CASTLE 0x0101
#define AREA_BITDW 0x0111
#define AREA_VCUTM 0x0121
#define AREA_BITFS 0x0131
#define AREA_SA 0x0141
#define AREA_BITS 0x0151
#define AREA_LLL_OUTSIDE 0x0161
#define AREA_LLL_VOLCANO 0x0162
#define AREA_DDD_WHIRLPOOL 0x0171
#define AREA_DDD_SUB 0x0172
#define AREA_WF 0x0181
#define AREA_ENDING 0x0191
#define AREA_COURTYARD 0x01A1
#define AREA_PSS 0x01B1
#define AREA_COTMC 0x01C1
#define AREA_TOTWC 0x01D1
#define AREA_BOWSER_1 0x01E1
#define AREA_WMOTR 0x01F1
#define AREA_BOWSER_2 0x0211
#define AREA_BOWSER_3 0x0221
#define AREA_TTM_OUTSIDE 0x0241
#define LEVEL_AREA_INDEX(levelNum, areaNum) ((levelNum << 4) + areaNum)
#define AREA_BBH LEVEL_AREA_INDEX(LEVEL_BBH, 1)
#define AREA_CCM_OUTSIDE LEVEL_AREA_INDEX(LEVEL_CCM, 1)
#define AREA_CCM_SLIDE LEVEL_AREA_INDEX(LEVEL_CCM, 2)
#define AREA_CASTLE_LOBBY LEVEL_AREA_INDEX(LEVEL_CASTLE, 1)
#define AREA_CASTLE_TIPPY LEVEL_AREA_INDEX(LEVEL_CASTLE, 2)
#define AREA_CASTLE_BASTEMENT LEVEL_AREA_INDEX(LEVEL_CASTLE, 3)
#define AREA_HMC LEVEL_AREA_INDEX(LEVEL_HMC, 1)
#define AREA_SSL_OUTSIDE LEVEL_AREA_INDEX(LEVEL_SSL, 1)
#define AREA_SSL_PYRAMID LEVEL_AREA_INDEX(LEVEL_SSL, 2)
#define AREA_SSL_EYEROK LEVEL_AREA_INDEX(LEVEL_SSL, 3)
#define AREA_BOB LEVEL_AREA_INDEX(LEVEL_BOB, 1)
#define AREA_SL_OUTSIDE LEVEL_AREA_INDEX(LEVEL_SL, 1)
#define AREA_SL_IGLOO LEVEL_AREA_INDEX(LEVEL_SL, 2)
#define AREA_WDW_MAIN LEVEL_AREA_INDEX(LEVEL_WDW, 1)
#define AREA_WDW_TOWN LEVEL_AREA_INDEX(LEVEL_WDW, 2)
#define AREA_JRB_MAIN LEVEL_AREA_INDEX(LEVEL_JRB, 1)
#define AREA_JRB_SHIP LEVEL_AREA_INDEX(LEVEL_JRB, 2)
#define AREA_THI_HUGE LEVEL_AREA_INDEX(LEVEL_THI, 1)
#define AREA_THI_TINY LEVEL_AREA_INDEX(LEVEL_THI, 2)
#define AREA_THI_WIGGLER LEVEL_AREA_INDEX(LEVEL_THI, 3)
#define AREA_TTC LEVEL_AREA_INDEX(LEVEL_TTC, 1)
#define AREA_RR LEVEL_AREA_INDEX(LEVEL_RR, 1)
#define AREA_OUTSIDE_CASTLE LEVEL_AREA_INDEX(LEVEL_CASTLE_GROUNDS, 1)
#define AREA_BITDW LEVEL_AREA_INDEX(LEVEL_BITDW, 1)
#define AREA_VCUTM LEVEL_AREA_INDEX(LEVEL_VCUTM, 1)
#define AREA_BITFS LEVEL_AREA_INDEX(LEVEL_BITFS, 1)
#define AREA_SA LEVEL_AREA_INDEX(LEVEL_SA, 1)
#define AREA_BITS LEVEL_AREA_INDEX(LEVEL_BITS, 1)
#define AREA_LLL_OUTSIDE LEVEL_AREA_INDEX(LEVEL_LLL, 1)
#define AREA_LLL_VOLCANO LEVEL_AREA_INDEX(LEVEL_LLL, 2)
#define AREA_DDD_WHIRLPOOL LEVEL_AREA_INDEX(LEVEL_DDD, 1)
#define AREA_DDD_SUB LEVEL_AREA_INDEX(LEVEL_DDD, 2)
#define AREA_WF LEVEL_AREA_INDEX(LEVEL_WF, 1)
#define AREA_ENDING LEVEL_AREA_INDEX(LEVEL_ENDING, 1)
#define AREA_COURTYARD LEVEL_AREA_INDEX(LEVEL_CASTLE_COURTYARD, 1)
#define AREA_PSS LEVEL_AREA_INDEX(LEVEL_PSS, 1)
#define AREA_COTMC LEVEL_AREA_INDEX(LEVEL_COTMC, 1)
#define AREA_TOTWC LEVEL_AREA_INDEX(LEVEL_TOTWC, 1)
#define AREA_BOWSER_1 LEVEL_AREA_INDEX(LEVEL_BOWSER_1, 1)
#define AREA_WMOTR LEVEL_AREA_INDEX(LEVEL_WMOTR, 1)
#define AREA_BOWSER_2 LEVEL_AREA_INDEX(LEVEL_BOWSER_2, 1)
#define AREA_BOWSER_3 LEVEL_AREA_INDEX(LEVEL_BOWSER_3, 1)
#define AREA_TTM_OUTSIDE LEVEL_AREA_INDEX(LEVEL_TTM, 1)
#define CAM_MODE_MARIO_ACTIVE 0x01
#define CAM_MODE_LAKITU_WAS_ZOOMED_OUT 0x02
@@ -217,7 +221,7 @@ struct Struct8033B2B8
// actually return a value. This causes undefined behavior, which we'd rather
// avoid on modern GCC. Hence, typedef. Interestingly, the void vs s32
// difference doesn't affect -g codegen, only -O2.
#if BUGFIXES_CRITICAL
#ifdef AVOID_UB
typedef void CmdRet;
#else
typedef s32 CmdRet;
+1 -1
View File
@@ -55,7 +55,7 @@ void my_rsp_init(void) {
gSPSetGeometryMode(gDisplayListHead++, G_SHADE | G_SHADING_SMOOTH | G_CULL_BACK | G_LIGHTING);
gSPNumLights(gDisplayListHead++, 1);
gSPNumLights(gDisplayListHead++, NUMLIGHTS_1);
gSPTexture(gDisplayListHead++, 0, 0, 0, G_TX_RENDERTILE, G_OFF);
// @bug Nintendo did not explicitly define the clipping ratio.
+3 -3
View File
@@ -12,15 +12,15 @@ extern u8 _translation_de_mio0SegmentRomStart[];
extern u8 _translation_de_mio0SegmentRomEnd[];
extern void *dialog_table_eu_en[];
extern void *level_name_table_eu_en[];
extern void *course_name_table_eu_en[];
extern void *act_name_table_eu_en[];
extern void *dialog_table_eu_fr[];
extern void *level_name_table_eu_fr[];
extern void *course_name_table_eu_fr[];
extern void *act_name_table_eu_fr[];
extern void *dialog_table_eu_de[];
extern void *level_name_table_eu_de[];
extern void *course_name_table_eu_de[];
extern void *act_name_table_eu_de[];
#endif /* EU_TRANSLATION_H */
+1
View File
@@ -3,6 +3,7 @@
#include "sm64.h"
#include "audio/external.h"
#include "buffers/framebuffers.h"
#include "buffers/zbuffer.h"
#include "engine/level_script.h"
#include "main.h"
#include "memory.h"
-1
View File
@@ -48,7 +48,6 @@ extern u16 func_802495B0(u32);
extern struct MarioAnimation D_80339D10;
extern struct MarioAnimation gDemo;
extern u16 gZBuffer[SCREEN_WIDTH * SCREEN_HEIGHT];
extern u8 gMarioAnims[];
extern u8 gDemoInputs[];
+1 -1
View File
@@ -127,7 +127,7 @@ void render_dl_power_meter(s16 numHealthWedges) {
gSPDisplayList(gDisplayListHead++, &dl_power_meter_health_segments_end);
}
gSPPopMatrix(gDisplayListHead++, 0);
gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW);
}
/**
+32 -31
View File
@@ -5,6 +5,7 @@
#include "types.h"
#include "audio/external.h"
#include "seq_ids.h"
#include "dialog_ids.h"
#include "game.h"
#include "save_file.h"
#include "level_update.h"
@@ -340,7 +341,7 @@ struct MultiTextEntry {
#define TEXT_THE_RAW ASCII_TO_DIALOG('t'), ASCII_TO_DIALOG('h'), ASCII_TO_DIALOG('e'), 0x00
#define TEXT_YOU_RAW ASCII_TO_DIALOG('y'), ASCII_TO_DIALOG('o'), ASCII_TO_DIALOG('u'), 0x00
enum MutliStringIDs { STRING_THE, STRING_YOU };
enum MultiStringIDs { STRING_THE, STRING_YOU };
/*
* Place the multi-text string according to the ID passed. (US, EU)
@@ -970,7 +971,7 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) {
// convert the speed into angle
create_dl_rotation_matrix(MENU_MTX_NOPUSH, gDialogBoxOpenTimer * 4.0f, 0, 0, 1.0f);
}
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 0x96);
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 150);
break;
case DIALOG_TYPE_ZOOM: // Renders a dialog white box with zoom
if (gDialogBoxState == DIALOG_STATE_OPENING || gDialogBoxState == DIALOG_STATE_CLOSING) {
@@ -978,7 +979,7 @@ void render_dialog_box_type(struct DialogEntry *dialog, s8 linesPerBox) {
(40.0 / gDialogBoxScale) - 40, 0);
create_dl_scale_matrix(MENU_MTX_NOPUSH, 1.0 / gDialogBoxScale, 1.0 / gDialogBoxScale, 1.0f);
}
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 0x96);
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 150);
break;
}
@@ -2201,15 +2202,15 @@ void render_pause_my_score_coins(void) {
u8 textUnfilledStar[] = { TEXT_UNFILLED_STAR };
u8 strCourseNum[4];
void **levelNameTbl;
u8 *levelName;
void **courseNameTbl;
u8 *courseName;
void **actNameTbl;
u8 *actName;
u8 courseIndex;
u8 starFlags;
#ifndef VERSION_EU
levelNameTbl = segmented_to_virtual(seg2_level_name_table);
courseNameTbl = segmented_to_virtual(seg2_course_name_table);
actNameTbl = segmented_to_virtual(seg2_act_name_table);
#endif
@@ -2220,15 +2221,15 @@ void render_pause_my_score_coins(void) {
switch (gInGameLanguage) {
case LANGUAGE_ENGLISH:
actNameTbl = segmented_to_virtual(act_name_table_eu_en);
levelNameTbl = segmented_to_virtual(level_name_table_eu_en);
courseNameTbl = segmented_to_virtual(course_name_table_eu_en);
break;
case LANGUAGE_FRENCH:
actNameTbl = segmented_to_virtual(act_name_table_eu_fr);
levelNameTbl = segmented_to_virtual(level_name_table_eu_fr);
courseNameTbl = segmented_to_virtual(course_name_table_eu_fr);
break;
case LANGUAGE_GERMAN:
actNameTbl = segmented_to_virtual(act_name_table_eu_de);
levelNameTbl = segmented_to_virtual(level_name_table_eu_de);
courseNameTbl = segmented_to_virtual(course_name_table_eu_de);
break;
}
#endif
@@ -2250,7 +2251,7 @@ void render_pause_my_score_coins(void) {
print_generic_string(MYSCORE_X, 121, textMyScore);
}
levelName = segmented_to_virtual(levelNameTbl[courseIndex]);
courseName = segmented_to_virtual(courseNameTbl[courseIndex]);
if (courseIndex < COURSE_STAGES_COUNT) {
#ifdef VERSION_EU
@@ -2274,19 +2275,19 @@ void render_pause_my_score_coins(void) {
}
print_generic_string(ACT_NAME_X, 140, actName);
#ifndef VERSION_JP
print_generic_string(LVL_NAME_X, 157, &levelName[3]);
print_generic_string(LVL_NAME_X, 157, &courseName[3]);
#endif
}
#ifndef VERSION_JP
else {
#ifdef VERSION_US
print_generic_string(94, 157, &levelName[3]);
print_generic_string(94, 157, &courseName[3]);
#elif defined(VERSION_EU)
print_generic_string(get_str_x_pos_from_center(159, &levelName[3], 10.0f), 157, &levelName[3]);
print_generic_string(get_str_x_pos_from_center(159, &courseName[3], 10.0f), 157, &courseName[3]);
#endif
}
#else
print_generic_string(117, 157, &levelName[3]);
print_generic_string(117, 157, &courseName[3]);
#endif
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
}
@@ -2498,9 +2499,9 @@ void render_pause_castle_course_stars(s16 x, s16 y, s16 fileNum, s16 courseNum)
void render_pause_castle_main_strings(s16 x, s16 y) {
#ifdef VERSION_EU
void **levelNameTbl;
void **courseNameTbl;
#else
void **levelNameTbl = segmented_to_virtual(seg2_level_name_table);
void **courseNameTbl = segmented_to_virtual(seg2_course_name_table);
#endif
#ifdef VERSION_EU
@@ -2510,7 +2511,7 @@ void render_pause_castle_main_strings(s16 x, s16 y) {
u8 textCoin[] = { TEXT_COIN_X };
#endif
void *levelName;
void *courseName;
u8 strVal[8];
s16 starNum = gDialogLineNum;
@@ -2518,13 +2519,13 @@ void render_pause_castle_main_strings(s16 x, s16 y) {
#ifdef VERSION_EU
switch (gInGameLanguage) {
case LANGUAGE_ENGLISH:
levelNameTbl = segmented_to_virtual(level_name_table_eu_en);
courseNameTbl = segmented_to_virtual(course_name_table_eu_en);
break;
case LANGUAGE_FRENCH:
levelNameTbl = segmented_to_virtual(level_name_table_eu_fr);
courseNameTbl = segmented_to_virtual(course_name_table_eu_fr);
break;
case LANGUAGE_GERMAN:
levelNameTbl = segmented_to_virtual(level_name_table_eu_de);
courseNameTbl = segmented_to_virtual(course_name_table_eu_de);
break;
}
#endif
@@ -2558,7 +2559,7 @@ void render_pause_castle_main_strings(s16 x, s16 y) {
gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha);
if (gDialogLineNum < COURSE_STAGES_COUNT) {
levelName = segmented_to_virtual(levelNameTbl[gDialogLineNum]);
courseName = segmented_to_virtual(courseNameTbl[gDialogLineNum]);
render_pause_castle_course_stars(x, y, gCurrSaveFileNum - 1, gDialogLineNum);
print_generic_string(x + 34, y - 5, textCoin);
#ifdef VERSION_EU
@@ -2567,21 +2568,21 @@ void render_pause_castle_main_strings(s16 x, s16 y) {
int_to_str(save_file_get_course_coin_score(gCurrSaveFileNum - 1, gDialogLineNum), strVal);
print_generic_string(x + 54, y - 5, strVal);
#ifdef VERSION_EU
print_generic_string(x - 17, y + 30, levelName);
print_generic_string(x - 17, y + 30, courseName);
#endif
} else {
u8 textStarX[] = { TEXT_STAR_X };
levelName = segmented_to_virtual(levelNameTbl[COURSE_MAX]);
courseName = segmented_to_virtual(courseNameTbl[COURSE_MAX]);
print_generic_string(x + 40, y + 13, textStarX);
int_to_str(save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_BONUS_STAGES - 1, COURSE_MAX - 1), strVal);
print_generic_string(x + 60, y + 13, strVal);
#ifdef VERSION_EU
print_generic_string(get_str_x_pos_from_center(x + 51, levelName, 10.0f), y + 30, levelName);
print_generic_string(get_str_x_pos_from_center(x + 51, courseName, 10.0f), y + 30, courseName);
#endif
}
#ifndef VERSION_EU
print_generic_string(x - 9, y + 30, levelName);
print_generic_string(x - 9, y + 30, courseName);
#endif
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
@@ -2816,7 +2817,7 @@ void render_course_complete_lvl_info_and_hud_str(void) {
#endif
void **actNameTbl;
void **levelNameTbl;
void **courseNameTbl;
u8 *name;
u8 strCourseNum[4];
@@ -2826,20 +2827,20 @@ void render_course_complete_lvl_info_and_hud_str(void) {
switch (gInGameLanguage) {
case LANGUAGE_ENGLISH:
actNameTbl = segmented_to_virtual(act_name_table_eu_en);
levelNameTbl = segmented_to_virtual(level_name_table_eu_en);
courseNameTbl = segmented_to_virtual(course_name_table_eu_en);
break;
case LANGUAGE_FRENCH:
actNameTbl = segmented_to_virtual(act_name_table_eu_fr);
levelNameTbl = segmented_to_virtual(level_name_table_eu_fr);
courseNameTbl = segmented_to_virtual(course_name_table_eu_fr);
break;
case LANGUAGE_GERMAN:
actNameTbl = segmented_to_virtual(act_name_table_eu_de);
levelNameTbl = segmented_to_virtual(level_name_table_eu_de);
courseNameTbl = segmented_to_virtual(course_name_table_eu_de);
break;
}
#else
actNameTbl = segmented_to_virtual(seg2_act_name_table);
levelNameTbl = segmented_to_virtual(seg2_level_name_table);
courseNameTbl = segmented_to_virtual(seg2_course_name_table);
#endif
if (gLastCompletedCourseNum <= COURSE_STAGES_MAX) {
@@ -2862,7 +2863,7 @@ void render_course_complete_lvl_info_and_hud_str(void) {
print_generic_string(CRS_NUM_X3, 167, strCourseNum);
gSPDisplayList(gDisplayListHead++, dl_ia_text_end);
} else if (gLastCompletedCourseNum == COURSE_BITDW || gLastCompletedCourseNum == COURSE_BITFS) {
name = segmented_to_virtual(levelNameTbl[gLastCompletedCourseNum - 1]);
name = segmented_to_virtual(courseNameTbl[gLastCompletedCourseNum - 1]);
gSPDisplayList(gDisplayListHead++, dl_ia_text_begin);
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, gDialogTextAlpha);
#ifdef VERSION_EU
+11 -9
View File
@@ -17,6 +17,8 @@
#include "behavior_actions.h"
#include "audio/external.h"
#include "behavior_data.h"
#include "dialog_ids.h"
#include "course_table.h"
#define INT_GROUND_POUND_OR_TWIRL (1 << 0) // 0x00000001
#define INT_PUNCH (1 << 1) // 0x00000002
@@ -857,7 +859,7 @@ u32 interact_warp_door(struct MarioState *m, UNUSED u32 interactType, struct Obj
if (!(saveFlags & SAVE_FLAG_HAVE_KEY_2)) {
if (!sDisplayingDoorText) {
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG,
(saveFlags & SAVE_FLAG_HAVE_KEY_1) ? 0x17 : 0x16);
(saveFlags & SAVE_FLAG_HAVE_KEY_1) ? DIALOG_023 : DIALOG_022);
}
sDisplayingDoorText = TRUE;
@@ -872,7 +874,7 @@ u32 interact_warp_door(struct MarioState *m, UNUSED u32 interactType, struct Obj
if (!sDisplayingDoorText) {
// Moat door skip was intended confirmed
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG,
(saveFlags & SAVE_FLAG_HAVE_KEY_2) ? 0x17 : 0x16);
(saveFlags & SAVE_FLAG_HAVE_KEY_2) ? DIALOG_023 : DIALOG_022);
}
sDisplayingDoorText = TRUE;
@@ -972,26 +974,26 @@ u32 interact_door(struct MarioState *m, UNUSED u32 interactType, struct Object *
return set_mario_action(m, enterDoorAction, actionArg);
} else if (!sDisplayingDoorText) {
u32 text = 0x00160000;
u32 text = DIALOG_022 << 16;
switch (requiredNumStars) {
case 1:
text = 0x00180000;
text = DIALOG_024 << 16;
break;
case 3:
text = 0x00190000;
text = DIALOG_025 << 16;
break;
case 8:
text = 0x001A0000;
text = DIALOG_026 << 16;
break;
case 30:
text = 0x001B0000;
text = DIALOG_027 << 16;
break;
case 50:
text = 0x001C0000;
text = DIALOG_028 << 16;
break;
case 70:
text = 0x001D0000;
text = DIALOG_029 << 16;
break;
}
+6 -4
View File
@@ -2,6 +2,7 @@
#include "sm64.h"
#include "seq_ids.h"
#include "dialog_ids.h"
#include "audio/external.h"
#include "level_update.h"
#include "game.h"
@@ -24,6 +25,7 @@
#include "memory.h"
#include "eu_translation.h"
#endif
#include "level_table.h"
#define PLAY_MODE_NORMAL 0
#define PLAY_MODE_PAUSED 2
@@ -227,15 +229,15 @@ void func_8024980C(u32 arg) {
u32 dialogID = gCurrentArea->dialog[arg];
switch (dialogID) {
case 129:
case DIALOG_129:
gotAchievement = save_file_get_flags() & SAVE_FLAG_HAVE_VANISH_CAP;
break;
case 130:
case DIALOG_130:
gotAchievement = save_file_get_flags() & SAVE_FLAG_HAVE_METAL_CAP;
break;
case 131:
case DIALOG_131:
gotAchievement = save_file_get_flags() & SAVE_FLAG_HAVE_WING_CAP;
break;
@@ -1246,7 +1248,7 @@ s32 lvl_init_from_save_file(UNUSED s16 arg0, s32 levelNum) {
disable_warp_checkpoint();
save_file_move_cap_to_default_location();
select_mario_cam_mode();
func_802E2F40();
set_yoshi_as_not_dead();
return levelNum;
}
+8 -7
View File
@@ -30,12 +30,13 @@
#include "save_file.h"
#include "sound_init.h"
#include "engine/surface_collision.h"
#include "level_table.h"
u32 unused80339F10;
s8 filler80339F1C[20];
/**************************************************
* ANIMATIONS *
* ANIMATIONS *
**************************************************/
/**
@@ -229,7 +230,7 @@ s16 return_mario_anim_y_translation(struct MarioState *m) {
}
/**************************************************
* AUDIO *
* AUDIO *
**************************************************/
/**
@@ -249,11 +250,11 @@ void play_mario_jump_sound(struct MarioState *m) {
if (!(m->flags & MARIO_MARIO_SOUND_PLAYED)) {
#ifndef VERSION_JP
if (m->action == ACT_TRIPLE_JUMP) {
play_sound(SOUND_MARIO_YAHOO_WAHA_YIPPEE + ((D_80226EB8 % 5) << 16),
play_sound(SOUND_MARIO_YAHOO_WAHA_YIPPEE + ((gAudioRandom % 5) << 16),
m->marioObj->header.gfx.cameraToObject);
} else {
#endif
play_sound(SOUND_MARIO_YAH_WAH_HOO + ((D_80226EB8 % 3) << 16),
play_sound(SOUND_MARIO_YAH_WAH_HOO + ((gAudioRandom % 3) << 16),
m->marioObj->header.gfx.cameraToObject);
#ifndef VERSION_JP
}
@@ -364,7 +365,7 @@ void play_mario_sound(struct MarioState *m, s32 actionSound, s32 marioSound) {
}
/**************************************************
* ACTIONS *
* ACTIONS *
**************************************************/
/**
@@ -1658,7 +1659,7 @@ void mario_update_hitbox_and_cap_model(struct MarioState *m) {
*/
static void debug_update_mario_cap(u16 button, s32 flags, u16 capTimer, u16 capMusic) {
// This checks for Z_TRIG instead of Z_DOWN flag
//(which is also what other debug functions do),
// (which is also what other debug functions do),
// so likely debug behavior rather than unused behavior.
if ((gPlayer1Controller->buttonDown & Z_TRIG) && (gPlayer1Controller->buttonPressed & button)
&& ((gMarioState->flags & flags) == 0)) {
@@ -1758,7 +1759,7 @@ s32 execute_mario_action(UNUSED struct Object *o) {
}
/**************************************************
* INITIALIZATION *
* INITIALIZATION *
**************************************************/
void init_mario(void) {
+1 -1
View File
@@ -3,7 +3,7 @@
#include "types.h"
extern u32 D_80226EB8;
extern u32 gAudioRandom;
extern struct Object *gMarioObject;
extern struct Object *gLuigiObject;
+13 -1
View File
@@ -385,6 +385,15 @@ u32 common_air_action_step(struct MarioState *m, u32 landAction, s32 animation,
m->vel[1] = 0.0f;
}
//! Hands-free holding. Bonking while no wall is referenced
// sets Mario's action to a non-holding action without
// dropping the object, causing the hands-free holding
// glitch. This can be achieved using an exposed ceiling,
// out of bounds, grazing the bottom of a wall while
// falling such that the final quarter step does not find a
// wall collision, or by rising into the top of a wall such
// that the final quarter step detects a ledge, but you are
// not able to ledge grab it.
if (m->forwardVel >= 38.0f) {
m->particleFlags |= PARTICLE_1;
set_mario_action(m, ACT_BACKWARD_AIR_KB, 0);
@@ -1277,6 +1286,9 @@ s32 act_air_hit_wall(struct MarioState *m) {
return set_mario_action(m, ACT_SOFT_BONK, 0);
}
#ifdef AVOID_UB
return
#endif
set_mario_animation(m, MARIO_ANIM_START_WALLKICK);
//! Missing return statement. The returned value is the result of the call
@@ -1750,7 +1762,7 @@ s32 act_flying(struct MarioState *m) {
if (startPitch <= 0 && m->faceAngle[0] > 0 && m->forwardVel >= 48.0f) {
play_sound(SOUND_ACTION_FLYING_FAST, m->marioObj->header.gfx.cameraToObject);
#ifndef VERSION_JP
play_sound(SOUND_MARIO_YAHOO_WAHA_YIPPEE + ((D_80226EB8 % 5) << 16),
play_sound(SOUND_MARIO_YAHOO_WAHA_YIPPEE + ((gAudioRandom % 5) << 16),
m->marioObj->header.gfx.cameraToObject);
#endif
}
+1
View File
@@ -14,6 +14,7 @@
#include "engine/surface_collision.h"
#include "interaction.h"
#include "camera.h"
#include "level_table.h"
#define POLE_NONE 0
#define POLE_TOUCHED_FLOOR 1
+11 -9
View File
@@ -23,6 +23,8 @@
#include "engine/behavior_script.h"
#include "behavior_data.h"
#include "object_list_processor.h"
#include "level_table.h"
#include "dialog_ids.h"
// TODO: put this elsewhere
enum SaveOption { SAVE_OPT_SAVE_AND_CONTINUE = 1, SAVE_OPT_SAVE_AND_QUIT, SAVE_OPT_CONTINUE_DONT_SAVE };
@@ -230,7 +232,7 @@ static void Unknown80256FF8(u16 *a0) {
/**
* get_star_collection_dialog: Determine what dialog should show when Mario
** collects a star.
* collects a star.
* Determines if Mario has collected enough stars to get a dialog for it, and
* if so, return the dialog ID. Otherwise, return 0
*/
@@ -242,7 +244,7 @@ s32 get_star_collection_dialog(struct MarioState *m) {
for (i = 0; i < 6; i++) {
numStarsRequired = sStarsNeededForDialog[i];
if (m->unkB8 < numStarsRequired && m->numStars >= numStarsRequired) {
dialogID = i + 0x8D;
dialogID = i + DIALOG_141;
break;
}
}
@@ -411,7 +413,7 @@ s32 act_reading_npc_dialog(struct MarioState *m) {
if (m->flags & MARIO_CAP_IN_HAND) {
set_mario_action(m, ACT_PUTTING_ON_CAP, 0);
} else {
set_mario_action(m, m->heldObj == NULL ? ACT_IDLE : ACT_UNKNOWN_007, 0);
set_mario_action(m, m->heldObj == NULL ? ACT_IDLE : ACT_HOLD_IDLE, 0);
}
}
vec3f_copy(m->marioObj->header.gfx.pos, m->pos);
@@ -624,7 +626,7 @@ void general_star_dance_handler(struct MarioState *m, s32 isInWater) {
level_trigger_warp(m, WARP_OP_STAR_EXIT);
} else {
enable_time_stop();
create_dialog_box_with_response(gLastCompletedStarNum == 7 ? 13 : 14);
create_dialog_box_with_response(gLastCompletedStarNum == 7 ? DIALOG_013 : DIALOG_014);
m->actionState = 1;
}
break;
@@ -800,10 +802,10 @@ s32 act_unlocking_key_door(struct MarioState *m) {
switch (m->marioObj->header.gfx.unk38.animFrame) {
case 79:
play_sound(SOUND_GENERAL_SWITCH4, m->marioObj->header.gfx.cameraToObject);
play_sound(SOUND_GENERAL_DOOR_INSERT_KEY, m->marioObj->header.gfx.cameraToObject);
break;
case 111:
play_sound(SOUND_GENERAL_SWITCH2, m->marioObj->header.gfx.cameraToObject);
play_sound(SOUND_GENERAL_DOOR_TURN_KEY, m->marioObj->header.gfx.cameraToObject);
break;
}
@@ -852,7 +854,7 @@ s32 act_unlocking_star_door(struct MarioState *m) {
case 3:
if (is_anim_at_end(m)) {
save_file_set_flags(get_door_save_file_flag(m->usedObj));
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, 38);
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, DIALOG_038);
}
break;
}
@@ -972,7 +974,7 @@ s32 act_warp_door_spawn(struct MarioState *m) {
}
} else if (m->usedObj->oAction == 0) {
if (gShouldNotPlayCastleMusic == TRUE && gCurrLevelNum == LEVEL_CASTLE) {
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, 21);
set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, DIALOG_021);
} else {
set_mario_action(m, ACT_IDLE, 0);
}
@@ -1822,7 +1824,7 @@ static s32 jumbo_star_cutscene_taking_off(struct MarioState *m) {
switch (animFrame) {
case 3:
play_sound(SOUND_MARIO_YAH_WAH_HOO + (D_80226EB8 % 3 << 16),
play_sound(SOUND_MARIO_YAH_WAH_HOO + (gAudioRandom % 3 << 16),
m->marioObj->header.gfx.cameraToObject);
break;
+17 -2
View File
@@ -539,6 +539,7 @@ void func_802652F0(struct MarioState *m) {
if (val04 > 8.0f) {
m->actionTimer = 2;
} else {
//! (Speed Crash) If Mario's speed is more than 2^17.
if ((val14 = (s32)(val04 / 4.0f * 0x10000)) < 0x1000) {
val14 = 0x1000;
}
@@ -556,6 +557,7 @@ void func_802652F0(struct MarioState *m) {
if (val04 > 8.0f) {
m->actionTimer = 2;
} else {
//! (Speed Crash) If Mario's speed is more than 2^17.
if ((val14 = (s32)(val04 * 0x10000)) < 0x1000) {
val14 = 0x1000;
}
@@ -572,6 +574,7 @@ void func_802652F0(struct MarioState *m) {
} else if (val04 > 22.0f) {
m->actionTimer = 3;
} else {
//! (Speed Crash) If Mario's speed is more than 2^17.
val14 = (s32)(val04 / 4.0f * 0x10000);
set_mario_anim_with_accel(m, MARIO_ANIM_WALKING, val14);
func_80263AD4(m, 10, 49);
@@ -584,6 +587,7 @@ void func_802652F0(struct MarioState *m) {
if (val04 < 18.0f) {
m->actionTimer = 2;
} else {
//! (Speed Crash) If Mario's speed is more than 2^17.
val14 = (s32)(val04 / 4.0f * 0x10000);
set_mario_anim_with_accel(m, MARIO_ANIM_RUNNING, val14);
func_80263AD4(m, 9, 45);
@@ -618,6 +622,7 @@ void func_8026570C(struct MarioState *m) {
if (val04 > 6.0f) {
m->actionTimer = 1;
} else {
//! (Speed Crash) Crashes if Mario's speed exceeds or equals 2^15.
val0C = (s32)(val04 * 0x10000);
set_mario_anim_with_accel(m, MARIO_ANIM_SLOW_WALK_WITH_LIGHT_OBJ, val0C);
func_80263AD4(m, 12, 62);
@@ -632,6 +637,7 @@ void func_8026570C(struct MarioState *m) {
} else if (val04 > 11.0f) {
m->actionTimer = 2;
} else {
//! (Speed Crash) Crashes if Mario's speed exceeds or equals 2^15.
val0C = (s32)(val04 * 0x10000);
set_mario_anim_with_accel(m, MARIO_ANIM_WALK_WITH_LIGHT_OBJ, val0C);
func_80263AD4(m, 12, 62);
@@ -644,6 +650,7 @@ void func_8026570C(struct MarioState *m) {
if (val04 < 8.0f) {
m->actionTimer = 1;
} else {
//! (Speed Crash) Crashes if Mario's speed exceeds or equals 2^16.
val0C = (s32)(val04 / 2.0f * 0x10000);
set_mario_anim_with_accel(m, MARIO_ANIM_RUN_WITH_LIGHT_OBJ, val0C);
func_80263AD4(m, 10, 49);
@@ -667,6 +674,7 @@ void func_802659E8(struct MarioState *m, Vec3f startPos) {
f32 dx = m->pos[0] - startPos[0];
f32 dz = m->pos[2] - startPos[2];
f32 movedDistance = sqrtf(dx * dx + dz * dz);
//! (Speed Crash) If a wall is after moving 16384 distance, this crashes.
s32 val04 = (s32)(movedDistance * 2.0f * 0x10000);
if (m->forwardVel > 6.0f) {
@@ -711,6 +719,8 @@ void func_80265C28(struct MarioState *m, s16 startYaw) {
if (animID == MARIO_ANIM_WALKING || animID == MARIO_ANIM_RUNNING) {
dYaw = m->faceAngle[1] - startYaw;
//! (Speed Crash) These casts can cause a crash if (dYaw * forwardVel / 12) or
//! (forwardVel * 170) exceed or equal 2^31.
val02 = -(s16)(dYaw * m->forwardVel / 12.0f);
val00 = (s16)(m->forwardVel * 170.0f);
@@ -741,6 +751,9 @@ void func_80265DBC(struct MarioState *m, s16 startYaw) {
struct MarioBodyState *val0C = m->marioBodyState;
struct Object *marioObj = m->marioObj;
s16 dYaw = m->faceAngle[1] - startYaw;
//! (Speed Crash) These casts can cause a crash if (dYaw * forwardVel / 12) or
//! (forwardVel * 170) exceed or equal 2^31. Harder (if not impossible to do)
//! while on a Koopa Shell making this less of an issue.
s16 val04 = -(s16)(dYaw * m->forwardVel / 12.0f);
s16 val02 = (s16)(m->forwardVel * 170.0f);
@@ -928,7 +941,7 @@ s32 act_hold_heavy_walking(struct MarioState *m) {
}
if (m->input & INPUT_UNKNOWN_5) {
return set_mario_action(m, ACT_UNKNOWN_008, 0);
return set_mario_action(m, ACT_HOLD_HEAVY_IDLE, 0);
}
m->intendedMag *= 0.1f;
@@ -1111,6 +1124,7 @@ s32 act_decelerating(struct MarioState *m) {
adjust_sound_for_speed(m);
m->particleFlags |= PARTICLE_DUST;
} else {
// (Speed Crash) Crashes if speed exceeds 2^17.
if ((val0C = (s32)(m->forwardVel / 4.0f * 0x10000)) < 0x1000) {
val0C = 0x1000;
}
@@ -1151,7 +1165,7 @@ s32 act_hold_decelerating(struct MarioState *m) {
}
if (update_decelerating_speed(m)) {
return set_mario_action(m, ACT_UNKNOWN_007, 0);
return set_mario_action(m, ACT_HOLD_IDLE, 0);
}
m->intendedMag *= 0.4f;
@@ -1176,6 +1190,7 @@ s32 act_hold_decelerating(struct MarioState *m) {
adjust_sound_for_speed(m);
m->particleFlags |= PARTICLE_DUST;
} else {
//! (Speed Crash) This crashes if Mario has more speed than 2^15 speed.
if ((val0C = (s32)(m->forwardVel * 0x10000)) < 0x1000) {
val0C = 0x1000;
}
+6 -3
View File
@@ -195,13 +195,13 @@ s32 act_picking_up(struct MarioState *m) {
m->marioBodyState->grabPos = GRAB_POS_HEAVY_OBJ;
set_mario_animation(m, MARIO_ANIM_GRAB_HEAVY_OBJECT);
if (is_anim_at_end(m)) {
set_mario_action(m, ACT_UNKNOWN_008, 0);
set_mario_action(m, ACT_HOLD_HEAVY_IDLE, 0);
}
} else {
m->marioBodyState->grabPos = GRAB_POS_LIGHT_OBJ;
set_mario_animation(m, MARIO_ANIM_PICK_UP_LIGHT_OBJ);
if (is_anim_at_end(m)) {
set_mario_action(m, ACT_UNKNOWN_007, 0);
set_mario_action(m, ACT_HOLD_IDLE, 0);
}
}
}
@@ -215,6 +215,9 @@ s32 act_dive_picking_up(struct MarioState *m) {
return drop_and_set_mario_action(m, ACT_UNKNOWN_026, 0);
}
//! Hands-free holding. Landing on a slope or being pushed off a ledge while
// landing from a dive grab sets mario's action to a non-holding action
// without dropping the object, causing the hands-free holding glitch.
if (m->input & INPUT_OFF_FLOOR) {
return set_mario_action(m, ACT_FREEFALL, 0);
}
@@ -223,7 +226,7 @@ s32 act_dive_picking_up(struct MarioState *m) {
return set_mario_action(m, ACT_BEGIN_SLIDING, 0);
}
animated_stationary_ground_step(m, MARIO_ANIM_STOP_SLIDE_LIGHT_OBJ, ACT_UNKNOWN_007);
animated_stationary_ground_step(m, MARIO_ANIM_STOP_SLIDE_LIGHT_OBJ, ACT_HOLD_IDLE);
return FALSE;
}
+11 -11
View File
@@ -441,7 +441,7 @@ s32 act_coughing(struct MarioState *m) {
return 0;
}
s32 func_802615C4(struct MarioState *m) {
s32 act_hold_idle(struct MarioState *m) {
if (segmented_to_virtual(&bhvJumpingBox) == m->heldObj->behavior) {
return set_mario_action(m, ACT_CRAZY_BOX_BOUNCE, 0);
}
@@ -463,7 +463,7 @@ s32 func_802615C4(struct MarioState *m) {
return 0;
}
s32 func_802616C4(struct MarioState *m) {
s32 act_hold_heavy_idle(struct MarioState *m) {
if (m->input & INPUT_UNKNOWN_10) {
return drop_and_set_mario_action(m, ACT_UNKNOWN_026, 0);
}
@@ -582,7 +582,7 @@ s32 act_panting(struct MarioState *m) {
}
if (set_mario_animation(m, MARIO_ANIM_WALK_PANTING) == 1) {
play_sound(SOUND_MARIO_PANTING + ((D_80226EB8 % 3U) << 0x10),
play_sound(SOUND_MARIO_PANTING + ((gAudioRandom % 3U) << 0x10),
m->marioObj->header.gfx.cameraToObject);
}
@@ -591,7 +591,7 @@ s32 act_panting(struct MarioState *m) {
return 0;
}
s32 func_80261C74(struct MarioState *m) {
s32 act_hold_panting_unused(struct MarioState *m) {
if (m->marioObj->oInteractStatus & INT_STATUS_MARIO_DROP_OBJECT) {
return drop_and_set_mario_action(m, ACT_PANTING, 0);
}
@@ -601,7 +601,7 @@ s32 func_80261C74(struct MarioState *m) {
}
if (m->health >= 0x500) {
return set_mario_action(m, ACT_UNKNOWN_007, 0);
return set_mario_action(m, ACT_HOLD_IDLE, 0);
}
if (func_802606DC(m) != 0) {
@@ -678,7 +678,7 @@ s32 func_80261F8C(struct MarioState *m) {
return set_mario_action(m, ACT_THROWING, 0);
}
func_80261D70(m, MARIO_ANIM_STAND_UP_FROM_SLIDING_WITH_LIGHT_OBJ, ACT_UNKNOWN_007);
func_80261D70(m, MARIO_ANIM_STAND_UP_FROM_SLIDING_WITH_LIGHT_OBJ, ACT_HOLD_IDLE);
return 0;
}
@@ -963,7 +963,7 @@ s32 func_80262CEC(struct MarioState *m) {
return set_mario_action(m, ACT_THROWING, 0);
}
func_802627B8(m, MARIO_ANIM_JUMP_LAND_WITH_LIGHT_OBJ, ACT_UNKNOWN_007);
func_802627B8(m, MARIO_ANIM_JUMP_LAND_WITH_LIGHT_OBJ, ACT_HOLD_IDLE);
return 0;
}
@@ -983,7 +983,7 @@ s32 func_80262DE4(struct MarioState *m) {
if (m->input & INPUT_B_PRESSED) {
return set_mario_action(m, ACT_THROWING, 0);
}
func_802627B8(m, MARIO_ANIM_FALL_LAND_WITH_LIGHT_OBJ, ACT_UNKNOWN_007);
func_802627B8(m, MARIO_ANIM_FALL_LAND_WITH_LIGHT_OBJ, ACT_HOLD_IDLE);
return 0;
}
@@ -1130,9 +1130,9 @@ s32 mario_execute_stationary_action(struct MarioState *m) {
case ACT_SLEEPING: sp24 = act_sleeping(m); break;
case ACT_WAKING_UP: sp24 = act_waking_up(m); break;
case ACT_PANTING: sp24 = act_panting(m); break;
case ACT_UNKNOWN_006: sp24 = func_80261C74(m); break;
case ACT_UNKNOWN_007: sp24 = func_802615C4(m); break;
case ACT_UNKNOWN_008: sp24 = func_802616C4(m); break;
case ACT_HOLD_PANTING_UNUSED: sp24 = act_hold_panting_unused(m); break;
case ACT_HOLD_IDLE: sp24 = act_hold_idle(m); break;
case ACT_HOLD_HEAVY_IDLE: sp24 = act_hold_heavy_idle(m); break;
case ACT_IN_QUICKSAND: sp24 = act_in_quicksand(m); break;
case ACT_STANDING_AGAINST_WALL: sp24 = act_standing_against_wall(m); break;
case ACT_COUGHING: sp24 = act_coughing(m); break;
+1
View File
@@ -14,6 +14,7 @@
#include "camera.h"
#include "audio/external.h"
#include "behavior_data.h"
#include "level_table.h"
#define MIN_SWIM_STRENGTH 160
#define MIN_SWIM_SPEED 16.0f
+39 -11
View File
@@ -23,6 +23,34 @@
#include "skybox.h"
#include "interaction.h"
#include "object_list_processor.h"
#include "dialog_ids.h"
#define TOAD_STAR_1_REQUIREMENT 12
#define TOAD_STAR_2_REQUIREMENT 25
#define TOAD_STAR_3_REQUIREMENT 35
#define TOAD_STAR_1_DIALOG DIALOG_082
#define TOAD_STAR_2_DIALOG DIALOG_076
#define TOAD_STAR_3_DIALOG DIALOG_083
#define TOAD_STAR_1_DIALOG_AFTER DIALOG_154
#define TOAD_STAR_2_DIALOG_AFTER DIALOG_155
#define TOAD_STAR_3_DIALOG_AFTER DIALOG_156
enum ToadMessageStates {
TOAD_MESSAGE_FADED,
TOAD_MESSAGE_OPAQUE,
TOAD_MESSAGE_OPACIFYING,
TOAD_MESSAGE_FADING,
TOAD_MESSAGE_TALKING
};
enum UnlockDoorStarStates {
UNLOCK_DOOR_STAR_RISING,
UNLOCK_DOOR_STAR_WAITING,
UNLOCK_DOOR_STAR_SPAWNING_PARTICLES,
UNLOCK_DOOR_STAR_DONE
};
static s8 D_8032CDF0[7] = { 0x01, 0x02, 0x01, 0x00, 0x01, 0x02, 0x01 };
static s8 D_8032CDF8[] = { 0x0a, 0x0c, 0x10, 0x18, 0x0a, 0x0a, 0x0a, 0x0e, 0x14, 0x1e,
@@ -80,20 +108,20 @@ static void bhvToadMessage_opaque(void) {
}
static void bhvToadMessage_talking(void) {
if (obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG_1, gCurrentObject->oToadMessageDialogNum) != 0) {
if (obj_update_dialog_with_cutscene(3, 1, CUTSCENE_DIALOG_1, gCurrentObject->oToadMessageDialogId) != 0) {
gCurrentObject->oToadMessageRecentlyTalked = 1;
gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADING;
switch (gCurrentObject->oToadMessageDialogNum) {
switch (gCurrentObject->oToadMessageDialogId) {
case TOAD_STAR_1_DIALOG:
gCurrentObject->oToadMessageDialogNum = TOAD_STAR_1_DIALOG_AFTER;
gCurrentObject->oToadMessageDialogId = TOAD_STAR_1_DIALOG_AFTER;
bhv_spawn_star_objects(0);
break;
case TOAD_STAR_2_DIALOG:
gCurrentObject->oToadMessageDialogNum = TOAD_STAR_2_DIALOG_AFTER;
gCurrentObject->oToadMessageDialogId = TOAD_STAR_2_DIALOG_AFTER;
bhv_spawn_star_objects(1);
break;
case TOAD_STAR_3_DIALOG:
gCurrentObject->oToadMessageDialogNum = TOAD_STAR_3_DIALOG_AFTER;
gCurrentObject->oToadMessageDialogId = TOAD_STAR_3_DIALOG_AFTER;
bhv_spawn_star_objects(2);
break;
}
@@ -138,31 +166,31 @@ void bhvToadMessage_loop(void) {
void bhvToadMessage_init(void) {
s32 saveFlags = save_file_get_flags();
s32 starCount = save_file_get_total_star_count(gCurrSaveFileNum - 1, 0, 24);
s32 dialogNum = (gCurrentObject->oBehParams >> 24) & 0xFF;
s32 dialogId = (gCurrentObject->oBehParams >> 24) & 0xFF;
s32 enoughStars = TRUE;
switch (dialogNum) {
switch (dialogId) {
case TOAD_STAR_1_DIALOG:
enoughStars = (starCount >= TOAD_STAR_1_REQUIREMENT);
if (saveFlags & (1 << 24)) {
dialogNum = TOAD_STAR_1_DIALOG_AFTER;
dialogId = TOAD_STAR_1_DIALOG_AFTER;
}
break;
case TOAD_STAR_2_DIALOG:
enoughStars = (starCount >= TOAD_STAR_2_REQUIREMENT);
if (saveFlags & (1 << 25)) {
dialogNum = TOAD_STAR_2_DIALOG_AFTER;
dialogId = TOAD_STAR_2_DIALOG_AFTER;
}
break;
case TOAD_STAR_3_DIALOG:
enoughStars = (starCount >= TOAD_STAR_3_REQUIREMENT);
if (saveFlags & (1 << 26)) {
dialogNum = TOAD_STAR_3_DIALOG_AFTER;
dialogId = TOAD_STAR_3_DIALOG_AFTER;
}
break;
}
if (enoughStars) {
gCurrentObject->oToadMessageDialogNum = dialogNum;
gCurrentObject->oToadMessageDialogId = dialogId;
gCurrentObject->oToadMessageRecentlyTalked = 0;
gCurrentObject->oToadMessageState = TOAD_MESSAGE_FADED;
gCurrentObject->oOpacity = 81;
-28
View File
@@ -3,34 +3,6 @@
#include "types.h"
#define TOAD_STAR_1_REQUIREMENT 12
#define TOAD_STAR_2_REQUIREMENT 25
#define TOAD_STAR_3_REQUIREMENT 35
#define TOAD_STAR_1_DIALOG 82
#define TOAD_STAR_2_DIALOG 76
#define TOAD_STAR_3_DIALOG 83
#define TOAD_STAR_1_DIALOG_AFTER 154
#define TOAD_STAR_2_DIALOG_AFTER 155
#define TOAD_STAR_3_DIALOG_AFTER 156
enum ToadMessageStates {
TOAD_MESSAGE_FADED,
TOAD_MESSAGE_OPAQUE,
TOAD_MESSAGE_OPACIFYING,
TOAD_MESSAGE_FADING,
TOAD_MESSAGE_TALKING
};
enum UnlockDoorStarStates {
UNLOCK_DOOR_STAR_RISING,
UNLOCK_DOOR_STAR_WAITING,
UNLOCK_DOOR_STAR_SPAWNING_PARTICLES,
UNLOCK_DOOR_STAR_DONE
};
extern struct GraphNodeObject D_80339FE0;
extern struct MarioBodyState gBodyStates[2];
+1 -1
View File
@@ -445,7 +445,7 @@ Gfx *movtex_gen_from_quad(s16 y, struct MovtexQuad *quad) {
// Only add commands to change the texture when necessary
if (textureId != gMovetexLastTextureId) {
if (textureId == TEXTURE_MIST) { // an G_IM_FMT_IA texture
if (textureId == TEXTURE_MIST) { // an ia16 texture
if (0) {
}
gDPSetTextureImage(gfx++, G_IM_FMT_IA, G_IM_SIZ_16b, 1, gMovtexIdToTexture[textureId]);
+348 -278
View File
@@ -27,62 +27,98 @@
#include "envfx_bubbles.h"
#include "ingame_menu.h"
#include "interaction.h"
#include "level_table.h"
#include "dialog_ids.h"
#include "course_table.h"
/**
* @file obj_behaviors.c
* This file contains a portion of the obj behaviors and many helper functions for those
* specific behaviors. Few functions besides the bhv_ functions are used elsewhere in the repo.
*/
#define o gCurrentObject
#define OBJ_COL_FLAG_GROUNDED (1 << 0)
#define OBJ_COL_FLAG_HIT_WALL (1 << 1)
#define OBJ_COL_FLAG_GROUNDED (1 << 0)
#define OBJ_COL_FLAG_HIT_WALL (1 << 1)
#define OBJ_COL_FLAG_UNDERWATER (1 << 2)
#define OBJ_COL_FLAG_NO_Y_VEL (1 << 3)
#define OBJ_COL_FLAGS_LANDED (OBJ_COL_FLAG_GROUNDED | OBJ_COL_FLAG_NO_Y_VEL)
#define OBJ_COL_FLAG_NO_Y_VEL (1 << 3)
#define OBJ_COL_FLAGS_LANDED (OBJ_COL_FLAG_GROUNDED | OBJ_COL_FLAG_NO_Y_VEL)
struct Surface *D_803600E0;
/**
* Current object floor as defined in object_step.
*/
static struct Surface *sObjFloor;
/* DATA */
s8 D_80331500 = 1;
s16 D_80331504 = 0;
s8 D_80331508 = 0;
s8 D_8033150C = 0;
s8 D_80331510 = 0;
/**
* Set to false when an object close to the floor should not be oriented in reference
* to it. Happens with boulder, falling pillar, and the rolling snowman body.
*/
static s8 sOrientObjWithFloor = TRUE;
/**
* Keeps track of Mario's previous non-zero room.
* Helps keep track of room when Mario is over an object.
*/
s16 sPrevCheckMarioRoom = 0;
/**
* Tracks whether or not Yoshi has walked/jumped off the roof.
*/
s8 sYoshiDead = FALSE;
extern void *ccm_seg7_trajectory_snowman;
extern void *inside_castle_seg7_trajectory_mips;
void func_802E2F40(void) {
D_80331508 = 0;
/**
* Resets yoshi as spawned/despawned upon new file select.
* Possibly a function with stubbed code.
*/
void set_yoshi_as_not_dead(void) {
sYoshiDead = FALSE;
}
Gfx *func_802E2F58(s32 arg0, struct Object *arg1, UNUSED s32 arg2) {
Gfx *sp34;
Gfx *sp30;
struct Object *sp2c;
struct Object *sp28;
UNUSED struct Object *sp24;
UNUSED s32 sp20;
/**
* An unused geo function. Bears strong similarity to Geo18_802B7D44, and relates something
* of the opacity of an object to something else. Perhaps like, giving a parent object the same
* opacity?
*/
Gfx UNUSED *geo_obj_transparency_something(s32 callContext, struct GraphNode *node, UNUSED Mat4 *mtx) {
Gfx *gfxHead;
Gfx *gfx;
struct Object *heldObject;
struct Object *obj;
UNUSED struct Object *unusedObject;
UNUSED s32 pad;
gfxHead = NULL;
if (callContext == GEO_CONTEXT_RENDER) {
heldObject = (struct Object *) gCurGraphNodeObject;
obj = (struct Object *) node;
unusedObject = (struct Object *) node;
sp34 = NULL;
if (arg0 == 1) {
sp2c = (struct Object *) gCurGraphNodeObject;
sp28 = arg1;
sp24 = arg1;
if (gCurGraphNodeHeldObject != NULL) {
sp2c = gCurGraphNodeHeldObject->objNode;
heldObject = gCurGraphNodeHeldObject->objNode;
}
sp34 = alloc_display_list(3 * sizeof(Gfx));
sp30 = sp34;
sp28->header.gfx.node.flags =
(sp28->header.gfx.node.flags & 0xFF) | 0x500; // sets bits 8, 10 and zeros upper byte
gfxHead = alloc_display_list(3 * sizeof(Gfx));
gfx = gfxHead;
obj->header.gfx.node.flags =
(obj->header.gfx.node.flags & 0xFF) | (GRAPH_NODE_TYPE_FUNCTIONAL | GRAPH_NODE_TYPE_400); // sets bits 8, 10 and zeros upper byte
gDPSetEnvColor(sp30++, 0xFF, 0xFF, 0xFF, sp2c->oOpacity);
gDPSetEnvColor(gfx++, 255, 255, 255, heldObject->oOpacity);
gSPEndDisplayList(sp30);
gSPEndDisplayList(gfx);
}
return sp34;
return gfxHead;
}
/**
* An absolute value function.
*/
f32 absf_2(f32 f) {
if (f < 0) {
f *= -1.0f;
@@ -90,31 +126,22 @@ f32 absf_2(f32 f) {
return f;
}
// f12 = objVelX
// f14 = objVelZ
// sp8 = nX
// spc = nY
// sp10 = nZ
// sp14 = objYawX
void TurnObjAwayFromSurface(f32 objVelX, f32 objVelZ, f32 nX, UNUSED f32 nY, f32 nZ, f32 *objYawX,
/**
* Turns an object away from floors/walls that it runs into.
*/
void turn_obj_away_from_surface(f32 velX, f32 velZ, f32 nX, UNUSED f32 nY, f32 nZ, f32 *objYawX,
f32 *objYawZ) {
*objYawX = (nZ * nZ - nX * nX) * objVelX / (nX * nX + nZ * nZ)
- 2 * objVelZ * (nX * nZ) / (nX * nX + nZ * nZ);
*objYawX = (nZ * nZ - nX * nX) * velX / (nX * nX + nZ * nZ)
- 2 * velZ * (nX * nZ) / (nX * nX + nZ * nZ);
*objYawZ = (nX * nX - nZ * nZ) * objVelZ / (nX * nX + nZ * nZ)
- 2 * objVelX * (nX * nZ) / (nX * nX + nZ * nZ);
*objYawZ = (nX * nX - nZ * nZ) * velZ / (nX * nX + nZ * nZ)
- 2 * velX * (nX * nZ) / (nX * nX + nZ * nZ);
}
// sp78 = objVelX
// sp7c = objVelZ
// sp70, f12 = objNewX
// sp74, f14 = objY
// sp80 = objNewZ
// sp38 = objVelXCopy
// sp34 = objVelZCopy
s32 ObjFindWall(f32 objNewX, f32 objY, f32 objNewZ, f32 objVelX, f32 objVelZ) {
/**
* Finds any wall collisions, applies them, and turns away from the surface.
*/
s32 obj_find_wall(f32 objNewX, f32 objY, f32 objNewZ, f32 objVelX, f32 objVelZ) {
struct WallCollisionData hitbox;
f32 wall_nX, wall_nY, wall_nZ, objVelXCopy, objVelZCopy, objYawX, objYawZ;
@@ -128,87 +155,93 @@ s32 ObjFindWall(f32 objNewX, f32 objY, f32 objNewZ, f32 objVelX, f32 objVelZ) {
o->oPosX = hitbox.x;
o->oPosY = hitbox.y;
o->oPosZ = hitbox.z;
wall_nX = hitbox.walls[0]->normal.x;
wall_nY = hitbox.walls[0]->normal.y;
wall_nZ = hitbox.walls[0]->normal.z;
objVelXCopy = objVelX;
objVelZCopy = objVelZ;
TurnObjAwayFromSurface(objVelXCopy, objVelZCopy, wall_nX, wall_nY, wall_nZ, &objYawX, &objYawZ);
// Turns away from the first wall only.
turn_obj_away_from_surface(objVelXCopy, objVelZCopy, wall_nX, wall_nY, wall_nZ, &objYawX, &objYawZ);
o->oMoveAngleYaw = atan2s(objYawZ, objYawX);
return 0;
return FALSE;
}
return 1;
return TRUE;
}
// sp48 = objFloor
// sp4c = floorY
// sp50 = objVelX
// sp54 = objVelZ
// sp38 = objVelXCopy
// sp34 = objVelZCopy
s32 TurnObjAwayFromAwkwardFloor(struct Surface *objFloor, f32 floorY, f32 objVelX, f32 objVelZ) {
/**
* Turns an object away from steep floors, similarly to walls.
*/
s32 turn_obj_away_from_steep_floor(struct Surface *objFloor, f32 floorY, f32 objVelX, f32 objVelZ) {
f32 floor_nX, floor_nY, floor_nZ, objVelXCopy, objVelZCopy, objYawX, objYawZ;
if (objFloor == NULL) {
//! TRUNC overflow exception after 36 minutes
//! (OOB Object Crash) TRUNC overflow exception after 36 minutes
o->oMoveAngleYaw += 32767.999200000002; /* ¯\_(ツ)_/¯ */
return 0;
return FALSE;
}
floor_nX = objFloor->normal.x;
floor_nY = objFloor->normal.y;
floor_nZ = objFloor->normal.z;
// If the floor is steep and we are below it (i.e. walking into it), turn away from the floor.
if (floor_nY < 0.5 && floorY > o->oPosY) {
objVelXCopy = objVelX;
objVelZCopy = objVelZ;
TurnObjAwayFromSurface(objVelXCopy, objVelZCopy, floor_nX, floor_nY, floor_nZ, &objYawX,
turn_obj_away_from_surface(objVelXCopy, objVelZCopy, floor_nX, floor_nY, floor_nZ, &objYawX,
&objYawZ);
o->oMoveAngleYaw = atan2s(objYawZ, objYawX);
return 0;
return FALSE;
}
return 1;
return TRUE;
}
// sp38 = obj
// sp3c = normalX
// sp40 = normalY
// sp44 = normalZ
void ObjOrientGraph(struct Object *obj, f32 normalX, f32 normalY, f32 normalZ) {
Vec3f sp2c, sp20;
/**
* Orients an object with the given normals, typically the surface under the object.
*/
void obj_orient_graph(struct Object *obj, f32 normalX, f32 normalY, f32 normalZ) {
Vec3f objVisualPosition, surfaceNormals;
Mat4 *throwMatrix;
if (D_80331500 == 0) {
// Passes on orienting certain objects that shouldn't be oriented, like boulders.
if (sOrientObjWithFloor == FALSE) {
return;
}
if ((obj->header.gfx.node.flags & 0x4) != 0) {
return; // bit 2
// Passes on orienting billboard objects, i.e. coins, trees, etc.
if ((obj->header.gfx.node.flags & GRAPH_RENDER_BILLBOARD) != 0) {
return;
}
throwMatrix = alloc_display_list(sizeof(*throwMatrix));
// If out of memory, fail to try orienting the object.
if (throwMatrix == NULL) {
return;
}
sp2c[0] = obj->oPosX;
sp2c[1] = obj->oPosY + obj->oGraphYOffset;
sp2c[2] = obj->oPosZ;
objVisualPosition[0] = obj->oPosX;
objVisualPosition[1] = obj->oPosY + obj->oGraphYOffset;
objVisualPosition[2] = obj->oPosZ;
sp20[0] = normalX;
sp20[1] = normalY;
sp20[2] = normalZ;
surfaceNormals[0] = normalX;
surfaceNormals[1] = normalY;
surfaceNormals[2] = normalZ;
mtxf_align_terrain_normal(*throwMatrix, sp20, sp2c, obj->oFaceAngleYaw);
mtxf_align_terrain_normal(*throwMatrix, surfaceNormals, objVisualPosition, obj->oFaceAngleYaw);
obj->header.gfx.throwMatrix = (void *) throwMatrix;
}
// sp4 = floor_nY
void CalcObjFriction(f32 *objFriction, f32 floor_nY) {
/**
* Determines an object's forward speed multiplier.
*/
void calc_obj_friction(f32 *objFriction, f32 floor_nY) {
if (floor_nY < 0.2 && o->oFriction < 0.9999) {
*objFriction = 0;
} else {
@@ -216,20 +249,16 @@ void CalcObjFriction(f32 *objFriction, f32 floor_nY) {
}
}
// sp28 = objFloor
// sp2c = objFloorY
// sp30 = objVelX
// sp34 = objVelZ
// sp24 = floor_nX
// sp20 = floor_nY
// sp1c = floor_nZ
void CalcNewObjVelAndPosY(struct Surface *objFloor, f32 objFloorY, f32 objVelX, f32 objVelZ) {
/**
* Updates an objects speed for gravity and updates Y position.
*/
void calc_new_obj_vel_and_pos_y(struct Surface *objFloor, f32 objFloorY, f32 objVelX, f32 objVelZ) {
f32 floor_nX = objFloor->normal.x;
f32 floor_nY = objFloor->normal.y;
f32 floor_nZ = objFloor->normal.z;
f32 objFriction;
// Caps vertical speed with a "terminal velocity".
o->oVelY -= o->oGravity;
if (o->oVelY > 75.0) {
o->oVelY = 75.0;
@@ -239,8 +268,12 @@ void CalcNewObjVelAndPosY(struct Surface *objFloor, f32 objFloorY, f32 objVelX,
}
o->oPosY += o->oVelY;
//Snap the object up to the floor.
if (o->oPosY < objFloorY) {
o->oPosY = objFloorY;
// Bounces an object if the ground is hit fast enough.
if (o->oVelY < -17.5) {
o->oVelY = -(o->oVelY / 2.0f);
} else {
@@ -248,15 +281,18 @@ void CalcNewObjVelAndPosY(struct Surface *objFloor, f32 objFloorY, f32 objVelX,
}
}
//! potential TRUNC crash
//! (Obj Position Crash) If you got an object with height past 2^31, the game would crash.
if ((s32) o->oPosY >= (s32) objFloorY && (s32) o->oPosY < (s32) objFloorY + 37) {
ObjOrientGraph(o, floor_nX, floor_nY, floor_nZ);
obj_orient_graph(o, floor_nX, floor_nY, floor_nZ);
// Adds horizontal component of gravity for horizontal speed.
objVelX += floor_nX * (floor_nX * floor_nX + floor_nZ * floor_nZ)
/ (floor_nX * floor_nX + floor_nY * floor_nY + floor_nZ * floor_nZ) * o->oGravity
* 2;
objVelZ += floor_nZ * (floor_nX * floor_nX + floor_nZ * floor_nZ)
/ (floor_nX * floor_nX + floor_nY * floor_nY + floor_nZ * floor_nZ) * o->oGravity
* 2;
if (objVelX < 0.000001 && objVelX > -0.000001) {
objVelX = 0;
}
@@ -268,22 +304,12 @@ void CalcNewObjVelAndPosY(struct Surface *objFloor, f32 objFloorY, f32 objVelX,
o->oMoveAngleYaw = atan2s(objVelZ, objVelX);
}
CalcObjFriction(&objFriction, floor_nY);
calc_obj_friction(&objFriction, floor_nY);
o->oForwardVel = sqrtf(objVelX * objVelX + objVelZ * objVelZ) * objFriction;
}
}
// sp28 = objFloor
// sp2c = floorY
// sp30 = objVelX
// sp34 = objVelZ
// sp38 = waterY
// sp24 = floor_nX
// sp20 = floor_nY
// sp1c = floor_nZ
// sp18 = netYAccel
void CalcNewObjVelAndPosYUnderwater(struct Surface *objFloor, f32 floorY, f32 objVelX, f32 objVelZ,
void calc_new_obj_vel_and_pos_y_underwater(struct Surface *objFloor, f32 floorY, f32 objVelX, f32 objVelZ,
f32 waterY) {
f32 floor_nX = objFloor->normal.x;
f32 floor_nY = objFloor->normal.y;
@@ -291,6 +317,8 @@ void CalcNewObjVelAndPosYUnderwater(struct Surface *objFloor, f32 floorY, f32 ob
f32 netYAccel = (1.0f - o->oBuoyancy) * (-1.0f * o->oGravity);
o->oVelY -= netYAccel;
// Caps vertical speed with a "terminal velocity".
if (o->oVelY > 75.0) {
o->oVelY = 75.0;
}
@@ -299,8 +327,12 @@ void CalcNewObjVelAndPosYUnderwater(struct Surface *objFloor, f32 floorY, f32 ob
}
o->oPosY += o->oVelY;
//Snap the object up to the floor.
if (o->oPosY < floorY) {
o->oPosY = floorY;
// Bounces an object if the ground is hit fast enough.
if (o->oVelY < -17.5) {
o->oVelY = -(o->oVelY / 2);
} else {
@@ -308,12 +340,15 @@ void CalcNewObjVelAndPosYUnderwater(struct Surface *objFloor, f32 floorY, f32 ob
}
}
if (o->oForwardVel > 12.5 && (waterY + 30.0f) > o->oPosY && waterY - 30.0f < o->oPosY) {
// If moving fast near the surface of the water, flip vertical speed? To emulate skipping?
if (o->oForwardVel > 12.5 && (waterY + 30.0f) > o->oPosY && (waterY - 30.0f) < o->oPosY) {
o->oVelY = -o->oVelY;
}
if ((s32) o->oPosY >= (s32) floorY && (s32) o->oPosY < (s32) floorY + 37) {
ObjOrientGraph(o, floor_nX, floor_nY, floor_nZ);
obj_orient_graph(o, floor_nX, floor_nY, floor_nZ);
// Adds horizontal component of gravity for horizontal speed.
objVelX += floor_nX * (floor_nX * floor_nX + floor_nZ * floor_nZ)
/ (floor_nX * floor_nX + floor_nY * floor_nY + floor_nZ * floor_nZ) * netYAccel * 2;
objVelZ += floor_nZ * (floor_nX * floor_nX + floor_nZ * floor_nZ)
@@ -334,14 +369,17 @@ void CalcNewObjVelAndPosYUnderwater(struct Surface *objFloor, f32 floorY, f32 ob
if (objVelX != 0 || objVelZ != 0) {
o->oMoveAngleYaw = atan2s(objVelZ, objVelX);
}
// Decreases both vertical velocity and forward velocity. Likely so that skips above
// don't loop infinitely.
o->oForwardVel = sqrtf(objVelX * objVelX + objVelZ * objVelZ) * 0.8;
o->oVelY *= 0.8;
}
// sp4 = xVel
// sp0 = zVel
void ObjUpdatePosVelXZ(void) {
/**
* Updates an objects position from oForwardVel and oMoveAngleYaw.
*/
void obj_update_pos_vel_xz(void) {
f32 xVel = o->oForwardVel * sins(o->oMoveAngleYaw);
f32 zVel = o->oForwardVel * coss(o->oMoveAngleYaw);
@@ -349,92 +387,105 @@ void ObjUpdatePosVelXZ(void) {
o->oPosZ += zVel;
}
// sp20 = waterY
// sp24 = objY
// sp1c = globalTimer
void ObjSplash(s32 waterY, s32 objY) {
/**
* Generates splashes if at surface of water, entering water, or bubbles
* if underwater.
*/
void obj_splash(s32 waterY, s32 objY) {
u32 globalTimer = gGlobalTimer;
// Spawns waves if near surface of water and plays a noise if entering.
if ((f32)(waterY + 30) > o->oPosY && o->oPosY > (f32)(waterY - 30)) {
spawn_object(o, MODEL_WATER_WAVES_SURF, bhvObjectWaterWave);
if (o->oVelY < -20.0f) {
PlaySound2(SOUND_OBJ_DIVING_INTO_WATER);
}
}
// Spawns bubbles if underwater.
if ((objY + 50) < waterY && (globalTimer & 0x1F) == 0) {
spawn_object(o, MODEL_WHITE_PARTICLE_SMALL, bhvObjectBubble); /* 0x1F is bits 4-0 */
spawn_object(o, MODEL_WHITE_PARTICLE_SMALL, bhvObjectBubble);
}
}
// sp3c = objX
// sp38 = objY
// sp34 = objZ
// sp28 = objVelX
// sp24 = objVelZ
// sp30 = floorY
// sp2c = waterY
// sp22 = collisionFlags
s32 ObjectStep(void) {
/**
* Generic object move function. Handles walls, water, floors, and gravity.
* Returns flags for certain interactions.
*/
s32 object_step(void) {
f32 objX = o->oPosX;
f32 objY = o->oPosY;
f32 objZ = o->oPosZ;
f32 floorY;
f32 waterY = -10000.0;
f32 objVelX = o->oForwardVel * sins(o->oMoveAngleYaw);
f32 objVelZ = o->oForwardVel * coss(o->oMoveAngleYaw);
s16 collisionFlags = 0;
if (ObjFindWall(objX + objVelX, objY, objZ + objVelZ, objVelX, objVelZ) == 0) {
// Find any wall collisions, receive the push, and set the flag.
if (obj_find_wall(objX + objVelX, objY, objZ + objVelZ, objVelX, objVelZ) == 0) {
collisionFlags += OBJ_COL_FLAG_HIT_WALL;
}
floorY = find_floor(objX + objVelX, objY, objZ + objVelZ, &D_803600E0);
if (TurnObjAwayFromAwkwardFloor(D_803600E0, floorY, objVelX, objVelZ) == 1) {
floorY = find_floor(objX + objVelX, objY, objZ + objVelZ, &sObjFloor);
if (turn_obj_away_from_steep_floor(sObjFloor, floorY, objVelX, objVelZ) == 1) {
waterY = find_water_level(objX + objVelX, objZ + objVelZ);
if (waterY > objY) {
CalcNewObjVelAndPosYUnderwater(D_803600E0, floorY, objVelX, objVelZ, waterY);
calc_new_obj_vel_and_pos_y_underwater(sObjFloor, floorY, objVelX, objVelZ, waterY);
collisionFlags += OBJ_COL_FLAG_UNDERWATER;
} else {
CalcNewObjVelAndPosY(D_803600E0, floorY, objVelX, objVelZ);
calc_new_obj_vel_and_pos_y(sObjFloor, floorY, objVelX, objVelZ);
}
} else {
// Treat any awkward floors similar to a wall.
collisionFlags +=
((collisionFlags & OBJ_COL_FLAG_HIT_WALL) ^ OBJ_COL_FLAG_HIT_WALL); /* bit 1 = 1 */
((collisionFlags & OBJ_COL_FLAG_HIT_WALL) ^ OBJ_COL_FLAG_HIT_WALL);
}
ObjUpdatePosVelXZ();
obj_update_pos_vel_xz();
if ((s32) o->oPosY == (s32) floorY) {
collisionFlags += OBJ_COL_FLAG_GROUNDED;
}
if ((s32) o->oVelY == 0) {
collisionFlags += OBJ_COL_FLAG_NO_Y_VEL;
}
ObjSplash((s32) waterY, (s32) o->oPosY);
// Generate a splash if in water.
obj_splash((s32) waterY, (s32) o->oPosY);
return collisionFlags;
}
// sp1e = collisionFlags
s32 func_802E4204(void) {
/**
* Takes an object step but does not orient with the object's floor.
* Used for boulders, falling pillars, and the rolling snowman body.
*
* TODO: Fix fake EU matching.
*/
s32 object_step_without_floor_orient(void) {
#ifdef VERSION_EU
s32 collisionFlags = 0;
#else
s16 collisionFlags = 0;
#endif
D_80331500 = 0;
collisionFlags = ObjectStep();
D_80331500 = 1;
sOrientObjWithFloor = FALSE;
collisionFlags = object_step();
sOrientObjWithFloor = TRUE;
return collisionFlags;
}
/**
Uses an object's forward velocity and yaw to move its X, Y, and Z positions.
This does accept an object as an argument, though it is always called with `o`.
If it wasn't called with `o`, it would modify `o`'s X and Z velocities based on
`obj`'s forward velocity and yaw instead of `o`'s, and wouldn't update `o`'s
position.
*/
* Uses an object's forward velocity and yaw to move its X, Y, and Z positions.
* This does accept an object as an argument, though it is always called with `o`.
* If it wasn't called with `o`, it would modify `o`'s X and Z velocities based on
* `obj`'s forward velocity and yaw instead of `o`'s, and wouldn't update `o`'s
* position.
*/
void obj_move_xyz_using_fvel_and_yaw(struct Object *obj) {
o->oVelX = obj->oForwardVel * sins(obj->oMoveAngleYaw);
o->oVelZ = obj->oForwardVel * coss(obj->oMoveAngleYaw);
@@ -444,8 +495,9 @@ void obj_move_xyz_using_fvel_and_yaw(struct Object *obj) {
obj->oPosZ += o->oVelZ;
}
// sp18 = arg2
/**
* Checks if a point is within distance from Mario's graphical position. Test is exclusive.
*/
s32 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist) {
f32 mGfxX = gMarioObject->header.gfx.pos[0];
f32 mGfxY = gMarioObject->header.gfx.pos[1];
@@ -453,75 +505,64 @@ s32 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist) {
if ((x - mGfxX) * (x - mGfxX) + (y - mGfxY) * (y - mGfxY) + (z - mGfxZ) * (z - mGfxZ)
< (f32)(dist * dist)) {
return 1;
return TRUE;
}
return 0;
return FALSE;
}
// sp14 = x
// sp18 = y
// sp1c = z
// spc = objX
// sp8 = objY
// sp4 = objZ
s32 IsPointCloseToObject(struct Object *obj, f32 x, f32 y, f32 z, s32 dist) {
/**
* Checks whether a point is within distance of a given point. Test is exclusive.
*/
s32 is_point_close_to_object(struct Object *obj, f32 x, f32 y, f32 z, s32 dist) {
f32 objX = obj->oPosX;
f32 objY = obj->oPosY;
f32 objZ = obj->oPosZ;
if ((x - objX) * (x - objX) + (y - objY) * (y - objY) + (z - objZ) * (z - objZ)
< (f32)(dist * dist)) {
return 1;
return TRUE;
}
return 0;
return FALSE;
}
// sp28 = obj
// sp2c = arg1
// sp24 = objX
// sp20 = objY
// sp1c = objZ
void SetObjectVisibility(struct Object *obj, s32 arg1) {
/**
* Sets an object as visible if within a certain distance of Mario's graphical position.
*/
void set_object_visibility(struct Object *obj, s32 dist) {
f32 objX = obj->oPosX;
f32 objY = obj->oPosY;
f32 objZ = obj->oPosZ;
if (is_point_within_radius_of_mario(objX, objY, objZ, arg1) == 1) {
obj->header.gfx.node.flags &= ~0x10; /* bit 4 = 0 */
if (is_point_within_radius_of_mario(objX, objY, objZ, dist) == TRUE) {
obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
} else {
obj->header.gfx.node.flags |= 0x10; /* bit 4 = 1 */
obj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
}
}
// sp28 = obj
// sp2c = homeX
// sp30 = y
// sp34 = homeZ
s32 ObjLeaveIfMarioIsNearHome(struct Object *obj, f32 homeX, f32 y, f32 homeZ, s32 dist) {
/**
* Turns an object towards home if Mario is not near to it.
*/
s32 obj_return_home_if_safe(struct Object *obj, f32 homeX, f32 y, f32 homeZ, s32 dist) {
f32 homeDistX = homeX - obj->oPosX;
f32 homeDistZ = homeZ - obj->oPosZ;
s16 angleAwayFromHome = atan2s(homeDistZ, homeDistX);
s16 angleTowardsHome = atan2s(homeDistZ, homeDistX);
if (is_point_within_radius_of_mario(homeX, y, homeZ, dist) == 1) {
return 1;
if (is_point_within_radius_of_mario(homeX, y, homeZ, dist) == TRUE) {
return TRUE;
} else {
obj->oMoveAngleYaw = approach_s16_symmetric(obj->oMoveAngleYaw, angleAwayFromHome, 320);
obj->oMoveAngleYaw = approach_s16_symmetric(obj->oMoveAngleYaw, angleTowardsHome, 320);
}
return 0;
return FALSE;
}
// sp28 = obj
// sp2c = homeX
// sp30 = homeY
// sp34 = homeZ
void ObjDisplaceHome(struct Object *obj, f32 homeX, UNUSED f32 homeY, f32 homeZ, s32 baseDisp) {
/**
* Randomly displaces an objects home if RNG says to, and turns the object towards its home.
*/
void obj_return_and_displace_home(struct Object *obj, f32 homeX, UNUSED f32 homeY, f32 homeZ, s32 baseDisp) {
s16 angleToNewHome;
f32 homeDistX, homeDistZ;
@@ -536,24 +577,25 @@ void ObjDisplaceHome(struct Object *obj, f32 homeX, UNUSED f32 homeY, f32 homeZ,
obj->oMoveAngleYaw = approach_s16_symmetric(obj->oMoveAngleYaw, angleToNewHome, 320);
}
s32 func_802E46C0(u32 arg0, u32 arg1, s16 arg2) {
s16 sp6 = (u16) arg1 - (u16) arg0;
/**
* A series of checks using sin and cos to see if a given angle is facing in the same direction
* of a given angle, within a certain range.
*/
s32 obj_check_if_facing_toward_angle(u32 base, u32 goal, s16 range) {
s16 dAngle = (u16) goal - (u16) base;
if (((f32) sins(-arg2) < (f32) sins(sp6)) && ((f32) sins(sp6) < (f32) sins(arg2))
&& (coss(sp6) > 0)) {
return 1;
if (((f32) sins(-range) < (f32) sins(dAngle)) && ((f32) sins(dAngle) < (f32) sins(range))
&& (coss(dAngle) > 0)) {
return TRUE;
}
return 0;
return FALSE;
}
// sp60= arg0
// sp64 = x
// sp68 = y
// sp6c = z
// sp38 = hitbox
s32 func_802E478C(Vec3f dist, f32 x, f32 y, f32 z, f32 arg4) {
/**
* Finds any wall collisions and returns what the displacement vector would be.
*/
s32 obj_find_wall_displacement(Vec3f dist, f32 x, f32 y, f32 z, f32 radius) {
struct WallCollisionData hitbox;
UNUSED u8 filler[0x20];
@@ -561,21 +603,23 @@ s32 func_802E478C(Vec3f dist, f32 x, f32 y, f32 z, f32 arg4) {
hitbox.y = y;
hitbox.z = z;
hitbox.offsetY = 10.0f;
hitbox.radius = arg4;
hitbox.radius = radius;
if (find_wall_collisions(&hitbox) != 0) {
dist[0] = hitbox.x - x;
dist[1] = hitbox.y - y;
dist[2] = hitbox.z - z;
return 1;
return TRUE;
} else {
return 0;
return FALSE;
}
}
// sp20 = obj
// sp24 = nCoins
void ObjSpawnYellowCoins(struct Object *obj, s8 nCoins) {
/**
* Spawns a number of coins at the location of an object
* with a random forward velocity, y velocity, and direction.
*/
void obj_spawn_yellow_coins(struct Object *obj, s8 nCoins) {
struct Object *coin;
s8 count;
@@ -587,65 +631,73 @@ void ObjSpawnYellowCoins(struct Object *obj, s8 nCoins) {
}
}
s32 ObjFlickerAndDisappear(struct Object *obj, s16 arg1) {
if (obj->oTimer < arg1) {
return 0;
/**
* Controls whether certain objects should flicker/when to despawn.
*/
s32 obj_flicker_and_disappear(struct Object *obj, s16 lifeSpan) {
if (obj->oTimer < lifeSpan) {
return FALSE;
}
if (obj->oTimer < arg1 + 40) {
if (obj->oTimer < lifeSpan + 40) {
if (obj->oTimer % 2 != 0) {
obj->header.gfx.node.flags |= 0x10; /* bit 4 = 1 */
obj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
} else {
obj->header.gfx.node.flags &= ~0x10; /* bit 4 = 0 */
obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
}
} else {
obj->activeFlags = 0;
return 1;
return TRUE;
}
return 0;
return FALSE;
}
s8 func_802E49A4(s16 arg0) {
s16 sp6;
/**
* Checks if a given room is Mario's current room, even if on an object.
*/
s8 current_mario_room_check(s16 room) {
s16 result;
// Since object surfaces have room 0, this tests if the surface is an
// object first and uses the last room if so.
if (gMarioCurrentRoom == 0) {
if (arg0 == D_80331504) {
return 1;
if (room == sPrevCheckMarioRoom) {
return TRUE;
} else {
return 0;
return FALSE;
}
} else {
if (arg0 == gMarioCurrentRoom) {
sp6 = 1;
if (room == gMarioCurrentRoom) {
result = TRUE;
} else {
sp6 = 0;
result = FALSE;
}
D_80331504 = gMarioCurrentRoom;
sPrevCheckMarioRoom = gMarioCurrentRoom;
}
return sp6;
return result;
}
// sp20 = arg0
// sp24 = arg1
// sp28 = arg2
// sp2c = arg3
/**
* Triggers dialog when Mario is facing an object and controls it while in the dialog.
*/
s16 trigger_obj_dialog_when_facing(s32 *inDialog, s16 dialogID, f32 dist, s32 actionArg) {
s16 dialogueResponse;
s16 func_802E4A38(s32 *arg0, s16 dialogID, f32 arg2, s32 arg3) {
s16 sp1e;
if ((is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, (s32) dist) == 1
&& obj_check_if_facing_toward_angle(o->oFaceAngleYaw, gMarioObject->header.gfx.angle[1] + 0x8000, 0x1000) == 1
&& obj_check_if_facing_toward_angle(o->oMoveAngleYaw, o->oAngleToMario, 0x1000) == 1)
|| (*inDialog == 1)) {
*inDialog = 1;
if ((is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, (s32) arg2) == 1
&& func_802E46C0(o->oFaceAngleYaw, gMarioObject->header.gfx.angle[1] + 0x8000, 0x1000) == 1
&& func_802E46C0(o->oMoveAngleYaw, o->oAngleToMario, 0x1000) == 1)
|| (*arg0 == 1)) {
*arg0 = 1;
if (set_mario_npc_dialog(arg3) == 2) {
sp1e = cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, dialogID);
if (sp1e != 0) {
if (set_mario_npc_dialog(actionArg) == 2) { //If Mario is speaking.
dialogueResponse = cutscene_object_with_dialog(CUTSCENE_DIALOG_1, o, dialogID);
if (dialogueResponse != 0) {
set_mario_npc_dialog(0);
*arg0 = 0;
return sp1e;
*inDialog = 0;
return dialogueResponse;
}
return 0;
}
@@ -654,17 +706,21 @@ s16 func_802E4A38(s32 *arg0, s16 dialogID, f32 arg2, s32 arg3) {
return 0;
}
void ObjCheckFloorDeath(s16 collisionFlags, struct Surface *floor) {
/**
*Checks if a floor is one that should cause an object to "die".
*/
void obj_check_floor_death(s16 collisionFlags, struct Surface *floor) {
if (floor == NULL) {
return;
}
if ((collisionFlags & 0x1) == 1) /* bit 0 */
if ((collisionFlags & OBJ_COL_FLAG_GROUNDED) == 1)
{
switch (floor->type) {
case SURFACE_BURNING:
o->oAction = OBJ_ACT_LAVA_DEATH;
break;
//! @BUG Doesn't check for the vertical wind death floor.
case SURFACE_DEATH_PLANE:
o->oAction = OBJ_ACT_DEATH_PLANE_DEATH;
break;
@@ -674,15 +730,18 @@ void ObjCheckFloorDeath(s16 collisionFlags, struct Surface *floor) {
}
}
// sp10 = arg0
s32 ObjLavaDeath(void) {
/**
* Controls an object dying in lava by creating smoke, sinking the object, playing
* audio, and eventually despawning it. Returns TRUE when the obj is dead.
*/
s32 obj_lava_death(void) {
struct Object *deathSmoke;
if (o->oTimer >= 31) {
o->activeFlags = 0;
return 1;
return TRUE;
} else {
// Sinking effect
o->oPosY -= 10.0f;
}
@@ -695,42 +754,53 @@ s32 ObjLavaDeath(void) {
deathSmoke->oForwardVel = RandomFloat() * 10.0f;
}
return 0;
return FALSE;
}
// sp30 = arg0
// sp34 = arg1
// sp38 = arg2
// sp3c = arg3
void SpawnOrangeNumber(s8 arg0, s16 arg1, s16 arg2, s16 arg3) {
/**
* Spawns an orange number object relatively, such as those that count up for secrets.
*/
void spawn_orange_number(s8 behParam, s16 relX, s16 relY, s16 relZ) {
struct Object *orangeNumber;
if (arg0 >= 10) {
if (behParam >= 10) {
return;
}
orangeNumber = spawn_object_relative(arg0, arg1, arg2, arg3, o, MODEL_NUMBER, bhvOrangeNumber);
orangeNumber = spawn_object_relative(behParam, relX, relY, relZ, o, MODEL_NUMBER, bhvOrangeNumber);
orangeNumber->oPosY += 25.0f;
}
s32 Unknown802E4DF4(s16 *arg0) {
if (*(arg0 + D_8033150C) == 0) {
D_8033150C = 0;
return 1;
/**
* Unused variables for debug_sequence_tracker.
*/
s8 sDebugSequenceTracker = 0;
s8 sDebugTimer = 0;
/**
* Unused presumably debug function that tracks for a sequence of inputs,
* perhaps for the Konami code sequence of inputs.
*/
s32 UNUSED debug_sequence_tracker(s16 debugInputSequence[]) {
// If end of sequence reached, return true.
if (debugInputSequence[sDebugSequenceTracker] == 0) {
sDebugSequenceTracker = 0;
return TRUE;
}
if ((*(arg0 + D_8033150C) & gPlayer3Controller->buttonPressed) != 0) {
D_8033150C++;
D_80331510 = 0;
} else if (D_80331510 == 10 || gPlayer3Controller->buttonPressed != 0) {
D_8033150C = 0;
D_80331510 = 0;
return 0;
// If the third controller button pressed is next in sequence, reset timer and progress to next value.
if ((debugInputSequence[sDebugSequenceTracker] & gPlayer3Controller->buttonPressed) != 0) {
sDebugSequenceTracker++;
sDebugTimer = 0;
// If wrong input or timer reaches 10, reset sequence progress.
} else if (sDebugTimer == 10 || gPlayer3Controller->buttonPressed != 0) {
sDebugSequenceTracker = 0;
sDebugTimer = 0;
return FALSE;
}
D_80331510++;
sDebugTimer++;
return 0;
return FALSE;
}
#include "behaviors/moving_coin.inc.c"
+2 -47
View File
@@ -5,48 +5,12 @@
#include "object_helpers2.h"
#include "engine/surface_collision.h"
extern struct Surface *D_803600E0;
extern s8 D_80331500;
extern s16 D_80331504;
extern s8 D_80331508;
extern s8 D_8033150C;
extern s8 D_80331510;
extern u8 bob_seg7_metal_ball_path0[];
extern u8 ttm_seg7_trajectory_070170A0[];
extern u8 bob_seg7_metal_ball_path1[];
void func_802E2F40(void);
Gfx *func_802E2F58(s32 arg0, struct Object *arg1, UNUSED s32 arg2); /* unused */
f32 absf_2(f32 f);
void TurnObjAwayFromSurface(f32 objVelX, f32 objVelZ, f32 nX, UNUSED f32 nY, f32 nZ, f32 *objYawX, f32 *objYawZ);
s32 ObjFindWall(f32 objNewX, f32 objY, f32 objNewZ, f32 objVelX, f32 objVelZ);
s32 TurnObjAwayFromAwkwardFloor(struct Surface *objFloor, f32 floorY, f32 objVelX, f32 objVelZ);
void ObjOrientGraph(struct Object *obj, f32 normalX, f32 normalY, f32 normalZ);
void CalcObjFriction(f32 *objFriction, f32 floor_nY);
void CalcNewObjVelAndPosY(struct Surface* objFloor, f32 objFloorY, f32 objVelX, f32 arg3);
void CalcNewObjVelAndPosYUnderwater(struct Surface* objFloor, f32 floorY, f32 objVelX, f32 objVelZ, f32 waterY);
void ObjUpdatePosVelXZ(void);
void ObjSplash(s32 waterY, s32 objY);
s32 ObjectStep(void);
s32 func_802E4204(void);
void obj_move_xyz_using_fvel_and_yaw(struct Object* obj);
s32 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist);
s32 IsPointCloseToObject(struct Object* obj, f32 x, f32 y, f32 z, s32 dist);
void SetObjectVisibility(struct Object* obj, s32 arg1);
s32 ObjLeaveIfMarioIsNearHome(struct Object* obj, f32 arg1, f32 arg2, f32 arg3, s32 arg4);
void ObjDisplaceHome(struct Object* obj, f32 homeX, UNUSED f32 homeY, f32 homeZ, s32 baseDisp);
s32 func_802E46C0(u32 arg0, u32 arg1, s16 arg2);
s32 func_802E478C(Vec3f dist, f32 x, f32 y, f32 z, f32 arg4);
void ObjSpawnYellowCoins(struct Object *obj, s8 nCoins);
s32 ObjFlickerAndDisappear(struct Object *obj, s16 arg1);
s8 func_802E49A4(s16 arg0);
s16 func_802E4A38(s32 *arg0, s16 arg1, f32 arg2, s32 arg3);
void ObjCheckFloorDeath(s16 collisionFlags, struct Surface *floor);
s32 ObjLavaDeath(void);
void SpawnOrangeNumber(s8 arg0, s16 arg1, s16 arg2, s16 arg3);
s32 Unknown802E4DF4(s16 *arg0); /* unused */
void set_yoshi_as_not_dead(void);
s32 CoinStep(s16 *collisionFlagsPtr);
void MovingCoinFlickerLoop(void);
void CoinCollected(void);
@@ -93,15 +57,8 @@ void WhirlpoolOrientGraph(void);
void bhv_whirlpool_loop(void);
void bhv_jet_stream_loop(void);
void bhv_homing_amp_init(void);
//void check_amp_attack(void);
//void homing_amp_appear_loop(void);
//void homing_amp_chase_loop(void);
//void homing_amp_give_up_loop(void);
//void amp_attack_cooldown_loop(void);
void bhv_homing_amp_loop(void);
void bhv_circling_amp_init(void);
//void fixed_circling_amp_idle_loop(void);
//void circling_amp_idle_loop(void);
void bhv_circling_amp_loop(void);
void bhv_butterfly_init(void);
void ButterflyStep(s32 speed);
@@ -123,8 +80,6 @@ void HootTurnToHome(void);
void HootAwakeLoop(void);
void bhv_hoot_loop(void);
void bhv_beta_holdable_object_init(void); /* unused */
//void beta_holdable_object_drop(void); /* unused */
//void beta_holdable_object_throw(void); /* unused */
void bhv_beta_holdable_object_loop(void); /* unused */
void bhv_object_bubble_init(void);
void bhv_object_bubble_loop(void);
+2
View File
@@ -15,6 +15,7 @@
#include "obj_behaviors_2.h"
#include "audio/external.h"
#include "seq_ids.h"
#include "dialog_ids.h"
#include "level_update.h"
#include "memory.h"
#include "platform_displacement.h"
@@ -28,6 +29,7 @@
#include "geo_misc.h"
#include "save_file.h"
#include "room.h"
#include "level_table.h"
extern struct Animation *wiggler_seg5_anims_0500C874[];
extern struct Animation *spiny_egg_seg5_anims_050157E4[];
+19 -9
View File
@@ -24,6 +24,8 @@
#include "interaction.h"
#include "object_list_processor.h"
#include "room.h"
#include "level_table.h"
#include "dialog_ids.h"
#include "object_helpers.h"
#include "object_helpers2.h"
@@ -63,7 +65,7 @@ Gfx *Geo18_8029D890(s32 run, UNUSED struct GraphNode *node, f32 mtx[4][4]) {
return NULL;
}
Gfx *Geo18_8029D924(s32 run, struct GraphNode *node, UNUSED s32 sp48) {
Gfx *Geo18_8029D924(s32 run, struct GraphNode *node, UNUSED void *context) {
Gfx *sp3C, *sp38;
struct Object *sp34;
struct GraphNodeGenerated *sp30;
@@ -128,7 +130,7 @@ Gfx *Geo18_8029D924(s32 run, struct GraphNode *node, UNUSED s32 sp48) {
#endif
}
gDPSetEnvColor(sp38++, 0xFF, 0xFF, 0xFF, sp28);
gDPSetEnvColor(sp38++, 255, 255, 255, sp28);
gSPEndDisplayList(sp38);
}
@@ -141,7 +143,11 @@ Gfx *Geo18_8029D924(s32 run, struct GraphNode *node, UNUSED s32 sp48) {
* executor passes the 3rd argument to a function that doesn't declare it. This is
* undefined behavior, but harmless in practice due to the o32 calling convention.
*/
s32 geo_switch_anim_state(s32 run, struct GraphNode *node) {
#ifdef AVOID_UB
Gfx *geo_switch_anim_state(s32 run, struct GraphNode *node, UNUSED void *context) {
#else
Gfx *geo_switch_anim_state(s32 run, struct GraphNode *node) {
#endif
struct Object *obj;
struct GraphNodeSwitchCase *switchCase;
@@ -166,11 +172,15 @@ s32 geo_switch_anim_state(s32 run, struct GraphNode *node) {
switchCase->selectedCase = obj->oAnimState;
}
return 0;
return NULL;
}
//! @bug Same issue as geo_switch_anim_state.
s32 geo_switch_area(s32 run, struct GraphNode *node) {
#ifdef AVOID_UB
Gfx *geo_switch_area(s32 run, struct GraphNode *node, UNUSED void *context) {
#else
Gfx *geo_switch_area(s32 run, struct GraphNode *node) {
#endif
s16 sp26;
struct Surface *sp20;
UNUSED struct Object *sp1C =
@@ -199,7 +209,7 @@ s32 geo_switch_area(s32 run, struct GraphNode *node) {
switchCase->selectedCase = 0;
}
return 0;
return NULL;
}
void func_8029D558(Mat4 a0, struct Object *a1) {
@@ -2058,7 +2068,7 @@ f32 random_f32_around_zero(f32 diameter) {
return RandomFloat() * diameter - diameter / 2.0f;
}
f32 scale_object_random(struct Object *obj, f32 rangeLength, f32 minScale) {
void scale_object_random(struct Object *obj, f32 rangeLength, f32 minScale) {
f32 scale = RandomFloat() * rangeLength + minScale;
scale_object_xyz(obj, scale, scale, scale);
}
@@ -2336,7 +2346,7 @@ s32 func_802A362C(s32 a0) {
return 0;
}
s32 obj_call_action_function(void (*actionFunctions[])(void)) {
void obj_call_action_function(void (*actionFunctions[])(void)) {
void (*actionFunction)(void) = actionFunctions[o->oAction];
actionFunction();
}
@@ -2781,7 +2791,7 @@ s32 mario_is_within_rectangle(s16 minX, s16 maxX, s16 minZ, s16 maxZ) {
return TRUE;
}
s32 ShakeScreen(s32 sp18) {
void ShakeScreen(s32 sp18) {
func_8027F440(sp18, o->oPosX, o->oPosY, o->oPosZ);
}
+9 -4
View File
@@ -165,9 +165,14 @@ extern s8 dddStatus;
// extern ? D_8033670C;
extern Gfx *Geo18_8029D890(s32 run, UNUSED struct GraphNode *node, f32 mtx[4][4]);
extern Gfx *Geo18_8029D924(s32 run, struct GraphNode *node, UNUSED s32 sp48);
extern s32 geo_switch_anim_state(s32 run, struct GraphNode *node);
extern s32 geo_switch_area(s32 run, struct GraphNode *node);
extern Gfx *Geo18_8029D924(s32 run, struct GraphNode *node, UNUSED void *context);
#ifdef AVOID_UB
extern Gfx *geo_switch_anim_state(s32 run, struct GraphNode *node, void *context);
extern Gfx *geo_switch_area(s32 run, struct GraphNode *node, void *context);
#else
extern Gfx *geo_switch_anim_state(s32 run, struct GraphNode *node);
extern Gfx *geo_switch_area(s32 run, struct GraphNode *node);
#endif
extern void func_8029D558(Mat4, struct Object *);
void apply_object_scale_to_matrix(struct Object *, Mat4, Mat4);
extern void func_8029D704(Mat4,Mat4,Mat4);
@@ -319,7 +324,7 @@ void obj_rotate_face_angle_using_vel(void);
extern s32 obj_follow_path(UNUSED s32);
extern void chain_segment_init(struct ChainSegment *);
extern f32 random_f32_around_zero(f32);
f32 scale_object_random(struct Object*,f32,f32);
void scale_object_random(struct Object*,f32,f32);
extern void translate_object_xyz_random(struct Object *, f32);
extern void translate_object_xz_random(struct Object *, f32);
// extern ? func_802A297C(?);

Some files were not shown because too many files have changed in this diff Show More