Merge branch 'develop' into 3DProjectiles

This commit is contained in:
Baoulettes 2022-06-20 22:32:45 +02:00 committed by GitHub
commit 14df96eacd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
489 changed files with 125389 additions and 1776 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,21 +1,21 @@
<Root>
<File Name="object_mag" Segment="6">
<Texture Name="gTitleZeldaShieldLogoMQTex" OutName="title_zelda_shield_logo_mq" Format="rgba32" Width="160" Height="160"/>
<Texture Name="gTitleCopyright19982002Tex" OutName="title_copyright_19982002" Format="ia8" Width="160" Height="16"/>
<Texture Name="gTitleCopyright19982003Tex" OutName="title_copyright_19982003" Format="ia8" Width="160" Height="16"/>
<Texture Name="gTitleDiskTex" OutName="title_disk" Format="ia8" Width="48" Height="16"/>
<Texture Name="gTitleEffectMask00Tex" OutName="title_effect_mask_0_0" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask01Tex" OutName="title_effect_mask_0_1" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask02Tex" OutName="title_effect_mask_0_2" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask10Tex" OutName="title_effect_mask_1_0" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask11Tex" OutName="title_effect_mask_1_1" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask12Tex" OutName="title_effect_mask_1_2" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask20Tex" OutName="title_effect_mask_2_0" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask21Tex" OutName="title_effect_mask_2_1" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask22Tex" OutName="title_effect_mask_2_2" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleFlameEffectTex" OutName="title_flame_effect" Format="i8" Width="32" Height="32"/>
<Texture Name="gTitleTheLegendOfTextTex" OutName="title_the_legend_of_text" Format="i8" Width="72" Height="8"/>
<Texture Name="gTitleOcarinaOfTimeTMTextTex" OutName="title_ocarina_of_time_tm_text" Format="i8" Width="96" Height="8"/>
<Texture Name="gTitleTitleJPNTex" OutName="title_title_jpn" Format="i8" Width="128" Height="16"/>
<Texture Name="gTitleZeldaShieldLogoMQTex" OutName="title_zelda_shield_logo_mq" Format="rgba32" Width="160" Height="160" Offset="0x0"/>
<Texture Name="gTitleCopyright19982002Tex" OutName="title_copyright_19982002" Format="ia8" Width="160" Height="16" Offset="0x19000"/>
<Texture Name="gTitleCopyright19982003Tex" OutName="title_copyright_19982003" Format="ia8" Width="160" Height="16" Offset="0x19A00"/>
<Texture Name="gTitleDiskTex" OutName="title_disk" Format="ia8" Width="48" Height="16" Offset="0x1A400"/>
<Texture Name="gTitleEffectMask00Tex" OutName="title_effect_mask_0_0" Format="i4" Width="64" Height="64" Offset="0x1A700"/>
<Texture Name="gTitleEffectMask01Tex" OutName="title_effect_mask_0_1" Format="i4" Width="64" Height="64" Offset="0x1AF00"/>
<Texture Name="gTitleEffectMask02Tex" OutName="title_effect_mask_0_2" Format="i4" Width="64" Height="64" Offset="0x1B700"/>
<Texture Name="gTitleEffectMask10Tex" OutName="title_effect_mask_1_0" Format="i4" Width="64" Height="64" Offset="0x1BF00"/>
<Texture Name="gTitleEffectMask11Tex" OutName="title_effect_mask_1_1" Format="i4" Width="64" Height="64" Offset="0x1C700"/>
<Texture Name="gTitleEffectMask12Tex" OutName="title_effect_mask_1_2" Format="i4" Width="64" Height="64" Offset="0x1CF00"/>
<Texture Name="gTitleEffectMask20Tex" OutName="title_effect_mask_2_0" Format="i4" Width="64" Height="64" Offset="0x1D700"/>
<Texture Name="gTitleEffectMask21Tex" OutName="title_effect_mask_2_1" Format="i4" Width="64" Height="64" Offset="0x1DF00"/>
<Texture Name="gTitleEffectMask22Tex" OutName="title_effect_mask_2_2" Format="i4" Width="64" Height="64" Offset="0x1E700"/>
<Texture Name="gTitleFlameEffectTex" OutName="title_flame_effect" Format="i8" Width="32" Height="32" Offset="0x1EF00"/>
<Texture Name="gTitleTheLegendOfTextTex" OutName="title_the_legend_of_text" Format="i8" Width="72" Height="8" Offset="0x1F300"/>
<Texture Name="gTitleOcarinaOfTimeTMTextTex" OutName="title_ocarina_of_time_tm_text" Format="i8" Width="96" Height="8" Offset="0x1F540"/>
<Texture Name="gTitleTitleJPNTex" OutName="title_title_jpn" Format="i8" Width="128" Height="16" Offset="0x1F840"/>
</File>
</Root>

View file

@ -3,6 +3,9 @@
<Scene Name="sasatest_scene" Offset="0x0"/>
</File>
<File Name="sasatest_room_0" Segment="3">
<Array Name="gSasatestRoom0Vtx_00370" Count="289" Offset="0x370">
<Vtx/>
</Array>
<Room Name="sasatest_room_0" Offset="0x0"/>
</File>
</Root>

File diff suppressed because it is too large Load diff

View file

@ -1,21 +1,21 @@
<Root>
<File Name="object_mag" Segment="6">
<Texture Name="gTitleZeldaShieldLogoMQTex" OutName="title_zelda_shield_logo_mq" Format="rgba32" Width="160" Height="160"/>
<Texture Name="gTitleCopyright19982002Tex" OutName="title_copyright_19982002" Format="ia8" Width="160" Height="16"/>
<Texture Name="gTitleCopyright19982003Tex" OutName="title_copyright_19982003" Format="ia8" Width="160" Height="16"/>
<Texture Name="gTitleDiskTex" OutName="title_disk" Format="ia8" Width="48" Height="16"/>
<Texture Name="gTitleEffectMask00Tex" OutName="title_effect_mask_0_0" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask01Tex" OutName="title_effect_mask_0_1" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask02Tex" OutName="title_effect_mask_0_2" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask10Tex" OutName="title_effect_mask_1_0" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask11Tex" OutName="title_effect_mask_1_1" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask12Tex" OutName="title_effect_mask_1_2" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask20Tex" OutName="title_effect_mask_2_0" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask21Tex" OutName="title_effect_mask_2_1" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleEffectMask22Tex" OutName="title_effect_mask_2_2" Format="i4" Width="64" Height="64"/>
<Texture Name="gTitleFlameEffectTex" OutName="title_flame_effect" Format="i8" Width="32" Height="32"/>
<Texture Name="gTitleTheLegendOfTextTex" OutName="title_the_legend_of_text" Format="i8" Width="72" Height="8"/>
<Texture Name="gTitleOcarinaOfTimeTMTextTex" OutName="title_ocarina_of_time_tm_text" Format="i8" Width="96" Height="8"/>
<Texture Name="gTitleTitleJPNTex" OutName="title_title_jpn" Format="i8" Width="128" Height="16"/>
<Texture Name="gTitleZeldaShieldLogoMQTex" OutName="title_zelda_shield_logo_mq" Format="rgba32" Width="160" Height="160" Offset="0x0"/>
<Texture Name="gTitleCopyright19982002Tex" OutName="title_copyright_19982002" Format="ia8" Width="160" Height="16" Offset="0x19000"/>
<Texture Name="gTitleCopyright19982003Tex" OutName="title_copyright_19982003" Format="ia8" Width="160" Height="16" Offset="0x19A00"/>
<Texture Name="gTitleDiskTex" OutName="title_disk" Format="ia8" Width="48" Height="16" Offset="0x1A400"/>
<Texture Name="gTitleEffectMask00Tex" OutName="title_effect_mask_0_0" Format="i4" Width="64" Height="64" Offset="0x1A700"/>
<Texture Name="gTitleEffectMask01Tex" OutName="title_effect_mask_0_1" Format="i4" Width="64" Height="64" Offset="0x1AF00"/>
<Texture Name="gTitleEffectMask02Tex" OutName="title_effect_mask_0_2" Format="i4" Width="64" Height="64" Offset="0x1B700"/>
<Texture Name="gTitleEffectMask10Tex" OutName="title_effect_mask_1_0" Format="i4" Width="64" Height="64" Offset="0x1BF00"/>
<Texture Name="gTitleEffectMask11Tex" OutName="title_effect_mask_1_1" Format="i4" Width="64" Height="64" Offset="0x1C700"/>
<Texture Name="gTitleEffectMask12Tex" OutName="title_effect_mask_1_2" Format="i4" Width="64" Height="64" Offset="0x1CF00"/>
<Texture Name="gTitleEffectMask20Tex" OutName="title_effect_mask_2_0" Format="i4" Width="64" Height="64" Offset="0x1D700"/>
<Texture Name="gTitleEffectMask21Tex" OutName="title_effect_mask_2_1" Format="i4" Width="64" Height="64" Offset="0x1DF00"/>
<Texture Name="gTitleEffectMask22Tex" OutName="title_effect_mask_2_2" Format="i4" Width="64" Height="64" Offset="0x1E700"/>
<Texture Name="gTitleFlameEffectTex" OutName="title_flame_effect" Format="i8" Width="32" Height="32" Offset="0x1EF00"/>
<Texture Name="gTitleTheLegendOfTextTex" OutName="title_the_legend_of_text" Format="i8" Width="72" Height="8" Offset="0x1F300"/>
<Texture Name="gTitleOcarinaOfTimeTMTextTex" OutName="title_ocarina_of_time_tm_text" Format="i8" Width="96" Height="8" Offset="0x1F540"/>
<Texture Name="gTitleTitleJPNTex" OutName="title_title_jpn" Format="i8" Width="128" Height="16" Offset="0x1F840"/>
</File>
</Root>

View file

@ -1322,18 +1322,9 @@ void SkinMatrix_SetTranslateRotateZYX(MtxF* dest, s16 rotX, s16 rotY, s16 rotZ,
f32 translateZ);
Mtx* SkinMatrix_MtxFToNewMtx(GraphicsContext* gfxCtx, MtxF* src);
void SkinMatrix_SetRotateAxis(MtxF* mf, s16 angle, f32 axisX, f32 axisY, f32 axisZ);
void Sram_InitNewSave(void);
void Sram_InitDebugSave(void);
void Sram_OpenSave(SramContext* sramCtx);
void Sram_WriteSave(SramContext* sramCtx);
void Sram_VerifyAndLoadAllSaves(FileChooseContext* fileChoose, SramContext* sramCtx);
void Sram_InitSave(FileChooseContext* fileChoose, SramContext* sramCtx);
void Sram_EraseSave(FileChooseContext* fileChoose, SramContext* sramCtx);
void Sram_CopySave(FileChooseContext* fileChoose, SramContext* sramCtx);
void Sram_WriteSramHeader(SramContext* sramCtx);
void Sram_InitSram(GameState* gameState, SramContext* sramCtx);
void Sram_Alloc(GameState* gameState, SramContext* sramCtx);
void Sram_Init(GlobalContext* globalCtx, SramContext* sramCtx);
void Sram_OpenSave();
void Sram_InitSave(FileChooseContext* fileChoose);
void Sram_InitSram(GameState* gameState);
void SsSram_ReadWrite(uintptr_t addr, void* dramAddr, size_t size, s32 direction);
void func_800A9F30(PadMgr*, s32);
void func_800A9F6C(f32, u8, u8, u8);

View file

@ -18,11 +18,6 @@
#define _AudiotableSegmentRomStart "Audiotable"
#define _icon_item_gameover_staticSegmentRomStart 0
#define _icon_item_gameover_staticSegmentRomEnd 0
#define _icon_item_staticSegmentRomStart 0
#define _icon_item_staticSegmentRomEnd 0
#define _map_i_staticSegmentRomStart 0

View file

@ -30,7 +30,8 @@
#include "ichain.h"
#include "regs.h"
#define AUDIO_HEAP_SIZE 0x38000
//#define AUDIO_HEAP_SIZE 0x38000
#define AUDIO_HEAP_SIZE 0x3800000 // The original audio heap size was too small. The heap would exceed capacity and corrupt everything in its path.
#define SYSTEM_HEAP_SIZE (1024 * 1024 * 4)
#ifdef __cplusplus
@ -1071,10 +1072,6 @@ typedef struct {
/* 0x01 */ u8 room;
} EntranceEntry;
typedef struct {
/* 0x00 */ u8* readBuff;
} SramContext; // size = 0x4
#define SRAM_SIZE 0x8000
#define SRAM_HEADER_SIZE 0x10
@ -1119,7 +1116,6 @@ typedef struct {
/* 0x0000 */ GameState state;
/* 0x00A4 */ u8* staticSegment;
/* 0x00A8 */ View view;
/* 0x01D0 */ SramContext sramCtx;
/* 0x01D4 */ u16 unk_1D4; // not used in mq dbg (some sort of timer that doesn't seem to affect anything)
/* 0x01D6 */ s16 coverAlpha;
/* 0x01D8 */ s16 addAlpha; // not used in mq dbg
@ -1205,7 +1201,6 @@ typedef struct GlobalContext {
/* 0x01C24 */ ActorContext actorCtx;
/* 0x01D64 */ CutsceneContext csCtx; // "demo_play"
/* 0x01DB4 */ SoundSource soundSources[16];
/* 0x01F74 */ SramContext sramCtx;
/* 0x01F78 */ SkyboxContext skyboxCtx;
/* 0x020D8 */ MessageContext msgCtx; // "message"
/* 0x104F0 */ InterfaceContext interfaceCtx; // "parameter"
@ -1279,7 +1274,6 @@ typedef struct {
/* 0x000AC */ u8* parameterSegment;
/* 0x000B0 */ char unk_B0[0x8];
/* 0x000B8 */ View view;
/* 0x001E0 */ SramContext sramCtx;
/* 0x001E4 */ char unk_1E4[0x4];
/* 0x001E8 */ SkyboxContext skyboxCtx;
/* 0x00348 */ MessageContext msgCtx;
@ -1290,13 +1284,6 @@ typedef struct {
/* 0x1C9EC */ Vtx* keyboardVtx;
/* 0x1C9F0 */ Vtx* nameEntryVtx;
/* 0x1C9F4 */ u8 n64ddFlag;
/* 0x1C9F6 */ u16 deaths[3];
/* 0x1C9FC */ u8 fileNames[3][8];
/* 0x1CA14 */ u16 healthCapacities[3];
/* 0x1CA1C */ u32 questItems[3];
/* 0x1CA28 */ s16 n64ddFlags[3];
/* 0x1CA2E */ s8 defense[3];
/* 0x1CA32 */ u16 health[3];
/* 0x1CA38 */ s16 buttonIndex;
/* 0x1CA3A */ s16 confirmButtonIndex; // 0: yes, 1: quit
/* 0x1CA3C */ s16 menuMode;

View file

@ -18,6 +18,11 @@
#define AIBUF_LEN 0x580
#define CALC_RESAMPLE_FREQ(sampleRate) ((float)sampleRate / (s32)gAudioContext.audioBufferParameters.frequency)
extern bool gUseLegacySD;
extern char* fontMap[256];
typedef enum {
/* 0 */ ADSR_STATE_DISABLED,
/* 1 */ ADSR_STATE_INITIAL,
@ -120,7 +125,8 @@ typedef struct {
/* 0x08 */ s16 book[1]; // size 8 * order * npredictors. 8-byte aligned
} AdpcmBook; // size >= 0x8
typedef struct {
typedef struct
{
union {
struct {
/* 0x00 */ u32 codec : 4;
@ -135,6 +141,8 @@ typedef struct {
/* 0x04 */ u8* sampleAddr;
/* 0x08 */ AdpcmLoop* loop;
/* 0x0C */ AdpcmBook* book;
u32 sampleRateMagicValue; // For wav samples only...
s32 sampleRate; // For wav samples only...
} SoundFontSample; // size = 0x10
typedef struct {
@ -226,6 +234,7 @@ typedef struct {
/* 0x08 */ Instrument** instruments;
/* 0x0C */ Drum** drums;
/* 0x10 */ SoundFontSound* soundEffects;
s32 fntIndex;
} SoundFont; // size = 0x14
typedef struct {
@ -680,7 +689,6 @@ typedef struct {
union{
u32 opArgs;
struct {
// OTRTODO: struct members swapped for quick audio
u8 arg2;
u8 arg1;
u8 arg0;
@ -1061,6 +1069,16 @@ typedef enum {
/* -1 */ OCARINA_NOTE_INVALID = 0xFF
} OcarinaNoteIdx;
typedef struct {
char* seqData;
int32_t seqDataSize;
uint8_t seqNumber;
uint8_t medium;
uint8_t cachePolicy;
int32_t numFonts;
uint8_t fonts[16];
} SequenceData;
#ifdef __cplusplus
extern "C" {
#endif

View file

@ -68,7 +68,6 @@ typedef struct {
/* 0x0010 */ s32 nightFlag;
/* 0x0014 */ s32 totalDays;
/* 0x0018 */ s32 bgsDayCount; // increments with totalDays, can be cleared with `Environment_ClearBgsDayCount`
/* 0x001C */ char newf[6]; // string "ZELDAZ". start of `info` substruct, originally called "information"
/* 0x0022 */ u16 deaths;
/* 0x0024 */ char playerName[8];
/* 0x002C */ s16 n64ddFlag;
@ -80,7 +79,6 @@ typedef struct {
/* 0x0036 */ u16 swordHealth;
/* 0x0038 */ u16 naviTimer;
/* 0x003A */ u8 magicAcquired;
/* 0x003B */ char unk_3B[0x01];
/* 0x003C */ u8 doubleMagic;
/* 0x003D */ u8 doubleDefense;
/* 0x003E */ u8 bgsFlag;
@ -88,30 +86,23 @@ typedef struct {
/* 0x0040 */ ItemEquips childEquips;
/* 0x004A */ ItemEquips adultEquips;
/* 0x0054 */ u32 unk_54; // this may be incorrect, currently used for alignement
/* 0x0058 */ char unk_58[0x0E];
/* 0x0066 */ s16 savedSceneNum;
/* 0x0068 */ ItemEquips equips;
/* 0x0074 */ Inventory inventory;
/* 0x00D4 */ SavedSceneFlags sceneFlags[124];
/* 0x0E64 */ FaroresWindData fw;
/* 0x0E8C */ char unk_E8C[0x10];
/* 0x0E9C */ s32 gsFlags[6];
/* 0x0EB4 */ char unk_EB4[0x4];
/* 0x0EB8 */ s32 highScores[7];
/* 0x0ED4 */ u16 eventChkInf[14]; // "event_chk_inf"
/* 0x0EF0 */ u16 itemGetInf[4]; // "item_get_inf"
/* 0x0EF8 */ u16 infTable[30]; // "inf_table"
/* 0x0F34 */ char unk_F34[0x04];
/* 0x0F38 */ u32 worldMapAreaData; // "area_arrival"
/* 0x0F3C */ char unk_F3C[0x4];
/* 0x0F40 */ u8 scarecrowCustomSongSet;
/* 0x0F41 */ u8 scarecrowCustomSong[0x360];
/* 0x12A1 */ char unk_12A1[0x24];
/* 0x12C5 */ u8 scarecrowSpawnSongSet;
/* 0x12C6 */ u8 scarecrowSpawnSong[0x80];
/* 0x1346 */ char unk_1346[0x02];
/* 0x1348 */ HorseData horseData;
/* 0x1352 */ u16 checksum; // "check_sum"
/* 0x1354 */ s32 fileNum; // "file_no"
/* 0x1358 */ char unk_1358[0x0004];
/* 0x135C */ s32 gameMode;
@ -120,13 +111,11 @@ typedef struct {
/* 0x1368 */ RespawnData respawn[3]; // "restart_data"
/* 0x13BC */ f32 entranceSpeed;
/* 0x13C0 */ u16 entranceSound;
/* 0x13C2 */ char unk_13C2[0x0001];
/* 0x13C3 */ u8 unk_13C3;
/* 0x13C4 */ s16 dogParams;
/* 0x13C6 */ u8 textTriggerFlags;
/* 0x13C7 */ u8 showTitleCard;
/* 0x13C8 */ s16 nayrusLoveTimer;
/* 0x13CA */ char unk_13CA[0x0002];
/* 0x13CC */ s16 rupeeAccumulator;
/* 0x13CE */ s16 timer1State;
/* 0x13D0 */ s16 timer1Value;
@ -134,7 +123,6 @@ typedef struct {
/* 0x13D4 */ s16 timer2Value;
/* 0x13D6 */ s16 timerX[2];
/* 0x13DA */ s16 timerY[2];
/* 0x13DE */ char unk_13DE[0x0002];
/* 0x13E0 */ u8 seqId;
/* 0x13E1 */ u8 natureAmbienceId;
/* 0x13E2 */ u8 buttonStatus[5];
@ -152,14 +140,11 @@ typedef struct {
/* 0x1402 */ u16 mapIndex; // intended for maps/minimaps but commonly used as the dungeon index
/* 0x1404 */ u16 minigameState;
/* 0x1406 */ u16 minigameScore; // "yabusame_total"
/* 0x1408 */ char unk_1408[0x0001];
/* 0x1409 */ u8 language; // NTSC 0: Japanese; 1: English | PAL 0: English; 1: German; 2: French
/* 0x140A */ u8 audioSetting;
/* 0x140B */ char unk_140B[0x0001];
/* 0x140C */ u8 zTargetSetting; // 0: Switch; 1: Hold
/* 0x140E */ u16 forcedSeqId; // immediately start playing the sequence if set
/* 0x1410 */ u8 unk_1410; // transition related
/* 0x1411 */ char unk_1411[0x0001];
/* 0x1412 */ u16 nextCutsceneIndex;
/* 0x1414 */ u8 cutsceneTrigger;
/* 0x1415 */ u8 chamberCutsceneNum;
@ -169,7 +154,6 @@ typedef struct {
/* 0x141A */ u16 skyboxTime;
/* 0x141C */ u8 dogIsLost;
/* 0x141D */ u8 nextTransition;
/* 0x141E */ char unk_141E[0x0002];
/* 0x1420 */ s16 worldMapArea;
/* 0x1422 */ s16 sunsSongState; // controls the effects of suns song
/* 0x1424 */ s16 healthAccumulator;

View file

@ -5,6 +5,7 @@ VisualStudioVersion = 16.0.31112.23
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soh", "soh.vcxproj", "{31348AA7-8DC5-4FA7-955F-E80855CADE9E}"
ProjectSection(ProjectDependencies) = postProject
{78424708-1F6E-4D4B-920C-FB6D26847055} = {78424708-1F6E-4D4B-920C-FB6D26847055}
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8} = {6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}
{A2E01C3E-D647-45D1-9788-043DEBC1A908} = {A2E01C3E-D647-45D1-9788-043DEBC1A908}
EndProjectSection
@ -13,6 +14,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libultraship", "..\libultra
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZAPDUtils", "..\ZAPDTR\ZAPDUtils\ZAPDUtils.vcxproj", "{A2E01C3E-D647-45D1-9788-043DEBC1A908}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib", "..\StormLib\StormLib_vs19.vcxproj", "{78424708-1F6E-4D4B-920C-FB6D26847055}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -45,6 +48,14 @@ Global
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Release|x64.Build.0 = Release|x64
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Release|x86.ActiveCfg = Release|Win32
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Release|x86.Build.0 = Release|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|x64.ActiveCfg = DebugUS|x64
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|x64.Build.0 = DebugUS|x64
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|x86.ActiveCfg = DebugUS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|x86.Build.0 = DebugUS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|x64.ActiveCfg = ReleaseUS|x64
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|x64.Build.0 = ReleaseUS|x64
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|x86.ActiveCfg = ReleaseUS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|x86.Build.0 = ReleaseUS|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -74,13 +74,13 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(ProjectDir)assets;$(ProjectDir)build;$(ProjectDir)include;$(ProjectDir)src;$(ProjectDir);$(ProjectDir)..\libultraship\libultraship\Lib\libjpeg\include;$(ProjectDir)..\libultraship\libultraship;$(ProjectDir)..\libultraship\libultraship\Lib\spdlog\include;$(ProjectDir)..\ZAPDTR\ZAPDUtils;$(ProjectDir)..\libultraship\libultraship\Lib\Fast3D\U64;$(ProjectDir)..\libultraship\libultraship\Lib\Fast3D\U64\PR;$(ProjectDir)..\libultraship\libultraship\Lib\SDL;$(IncludePath)</IncludePath>
<LibraryPath>$(OutDir);$(ProjectDir)..\libultraship\libultraship;$(ProjectDir)..\libultraship\libultraship\Lib\SDL\lib\x86;$(ProjectDir)..\libultraship\libultraship\Lib\GLEW\x86;$(ProjectDir)..\libultraship\libultraship\Lib\GLFW;$(LibraryPath)</LibraryPath>
<LibraryPath>$(OutDir);$(ProjectDir)..\libultraship\libultraship;$(ProjectDir)..\libultraship\libultraship\Lib\SDL\lib\x86;$(ProjectDir)..\libultraship\libultraship\Lib\GLEW\x86;$(ProjectDir)..\libultraship\libultraship\Lib\GLFW;$(ProjectDir)..\StormLib\bin\StormLib\Win32\DebugUS\;$(LibraryPath)</LibraryPath>
<IntDir>$(Configuration)Obj\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(ProjectDir)assets;$(ProjectDir)build;$(ProjectDir)include;$(ProjectDir)src;$(ProjectDir);$(ProjectDir)..\libultraship\libultraship\Lib\libjpeg\include;$(ProjectDir)..\libultraship\libultraship;$(ProjectDir)..\libultraship\libultraship\Lib\spdlog\include;$(ProjectDir)..\ZAPDTR\ZAPDUtils;$(ProjectDir)..\libultraship\libultraship\Lib\Fast3D\U64;$(ProjectDir)..\libultraship\libultraship\Lib\Fast3D\U64\PR;$(ProjectDir)..\libultraship\libultraship\Lib\SDL;$(IncludePath)</IncludePath>
<LibraryPath>$(OutDir);$(ProjectDir)..\libultraship\libultraship;$(ProjectDir)..\libultraship\libultraship\Lib\SDL\lib\x86;$(ProjectDir)..\libultraship\libultraship\Lib\GLEW\x86;$(ProjectDir)..\libultraship\libultraship\Lib\GLFW;$(LibraryPath)</LibraryPath>
<LibraryPath>$(OutDir);$(ProjectDir)..\libultraship\libultraship;$(ProjectDir)..\libultraship\libultraship\Lib\SDL\lib\x86;$(ProjectDir)..\libultraship\libultraship\Lib\GLEW\x86;$(ProjectDir)..\libultraship\libultraship\Lib\GLFW;$(ProjectDir)..\StormLib\bin\StormLib\Win32\ReleaseUS\;$(LibraryPath)</LibraryPath>
<IntDir>$(Configuration)Obj\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -173,6 +173,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="soh\Enhancements\debugger\actorViewer.cpp" />
<ClCompile Include="soh\frame_interpolation.cpp" />
<ClCompile Include="soh\Enhancements\bootcommands.c" />
<ClCompile Include="soh\Enhancements\debugconsole.cpp" />
@ -185,6 +186,7 @@
<ClCompile Include="soh\GbiWrap.cpp" />
<ClCompile Include="soh\gu_pc.c" />
<ClCompile Include="soh\OTRGlobals.cpp" />
<ClCompile Include="soh\SaveManager.cpp" />
<ClCompile Include="soh\stubs.c" />
<ClCompile Include="soh\util.cpp" />
<ClCompile Include="soh\z_message_OTR.cpp" />
@ -879,6 +881,7 @@
<ClCompile Include="src\overlays\misc\ovl_map_mark_data\z_map_mark_data.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="soh\Enhancements\debugger\actorViewer.h" />
<ClInclude Include="soh\frame_interpolation.h" />
<ClInclude Include="include\alloca.h" />
<ClInclude Include="include\bgm.h" />
@ -933,8 +936,10 @@
<ClInclude Include="soh\Enhancements\debugger\debugSaveEditor.h" />
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h" />
<ClInclude Include="soh\gameconsole.h" />
<ClInclude Include="soh\Lib\nlohmann\json.hpp" />
<ClInclude Include="soh\OTRAudio.h" />
<ClInclude Include="soh\OTRGlobals.h" />
<ClInclude Include="soh\SaveManager.h" />
<ClInclude Include="soh\util.h" />
<ClInclude Include="src\overlays\actors\ovl_Arms_Hook\z_arms_hook.h" />
<ClInclude Include="src\overlays\actors\ovl_Arrow_Fire\z_arrow_fire.h" />

View file

@ -82,6 +82,12 @@
<Filter Include="Source Files\soh\Enhancements\debugger">
<UniqueIdentifier>{04fc1c52-49ff-48e2-ae23-2c00867374f8}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\soh\Lib">
<UniqueIdentifier>{dbcf07c4-80b1-4c88-ac54-2bbdd8f53ee4}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\soh\Lib\nlohmann">
<UniqueIdentifier>{9c880c8e-492b-48f6-b230-1fd269ea74b1}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\boot\assert.c">
@ -2184,8 +2190,12 @@
<ClCompile Include="soh\Enhancements\debugger\colViewer.cpp">
<Filter>Source Files\soh\Enhancements\debugger</Filter>
</ClCompile>
<ClCompile Include="soh\Enhancements\debugger\actorViewer.cpp">
<Filter>Source Files\soh\Enhancements\debugger</Filter>
</ClCompile>
<ClCompile Include="soh\Enhancements\debugger\ImGuiHelpers.cpp">
<Filter>Source Files\soh\Enhancements\debugger</Filter>
</ClCompile>
<ClCompile Include="soh\frame_interpolation.cpp">
<Filter>Source Files\soh</Filter>
</ClCompile>
@ -2195,6 +2205,9 @@
<ClCompile Include="soh\Enhancements\savestates.cpp">
<Filter>Source Files\soh\Enhancements</Filter>
</ClCompile>
<ClCompile Include="soh\SaveManager.cpp">
<Filter>Source Files\soh</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\overlays\actors\ovl_kaleido_scope\z_kaleido_scope.h">
@ -3748,8 +3761,12 @@
<ClInclude Include="soh\Enhancements\debugger\colViewer.h">
<Filter>Header Files\soh\Enhancements\debugger</Filter>
</ClInclude>
<ClInclude Include="soh\Enhancements\debugger\actorViewer.h">
<Filter>Header Files\soh\Enhancements\debugger</Filter>
</ClInclude>
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h">
<Filter>Header Files\soh\Enhancements\debugger</Filter>
</ClInclude>
<ClInclude Include="soh\frame_interpolation.h">
<Filter>Header Files\soh</Filter>
</ClInclude>
@ -3759,20 +3776,17 @@
<ClInclude Include="soh\OTRAudio.h">
<Filter>Source Files\soh</Filter>
</ClInclude>
<ClInclude Include="soh\Lib\nlohmann\json.hpp">
<Filter>Source Files\soh\Lib\nlohmann</Filter>
</ClInclude>
<ClInclude Include="soh\SaveManager.h">
<Filter>Source Files\soh</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="include\macro.inc">
<Filter>Header Files\include</Filter>
</None>
<Image Include="SHIPOFHARKINIAN.ico" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Resource.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="SHIPOFHARKINIAN.ico">
<Filter>Resource Files</Filter>
</Image>
<None Include="include\macro.inc" />
</ItemGroup>
</Project>

View file

@ -25,16 +25,22 @@ void BootCommands_Init()
CVar_RegisterS32("gDebugEnabled", 0);
CVar_RegisterS32("gPauseLiveLink", 0);
CVar_RegisterS32("gMinimalUI", 0);
CVar_RegisterS32("gRedGanonBlood", 0);
CVar_RegisterS32("gHoverFishing", 0);
CVar_RegisterS32("gRumbleEnabled", 0);
CVar_RegisterS32("gUniformLR", 1);
CVar_RegisterS32("gUniformLR", 0);
CVar_RegisterS32("gTwoHandedIdle", 0);
CVar_RegisterS32("gDekuNutUpgradeFix", 1);
CVar_RegisterS32("gDekuNutUpgradeFix", 0);
CVar_RegisterS32("gNaviTextFix", 0);
CVar_RegisterS32("gNewDrops", 0);
CVar_RegisterS32("gVisualAgony", 0);
CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French
CVar_RegisterS32("gGravediggingTourFix", 1);
CVar_RegisterS32("gHudColors", 1); //0 = N64 / 1 = NGC / 2 = Custom
CVar_RegisterS32("gUseNaviCol", 0);
CVar_RegisterS32("gUseTunicsCol", 0);
CVar_RegisterS32("gGuardVision", 0);
CVar_RegisterS32("gTimeFlowFileSelect", 0);
}
//void BootCommands_ParseBootArgs(char* str)

View file

@ -0,0 +1,779 @@
#include "actorViewer.h"
#include "../../util.h"
#include "../libultraship/SohImGuiImpl.h"
#include "ImGuiHelpers.h"
#include <array>
#include <bit>
#include <map>
#include <string>
#include <Cvar.h>
extern "C" {
#include <z64.h>
#include "z64math.h"
#include "variables.h"
#include "functions.h"
#include "macros.h"
extern GlobalContext* gGlobalCtx;
#include "textures/icon_item_static/icon_item_static.h"
#include "textures/icon_item_24_static/icon_item_24_static.h"
}
typedef struct {
u16 id;
u16 params;
Vec3f pos;
Vec3s rot;
} ActorInfo;
typedef enum {
LIST,
TARGET,
HELD,
INTERACT
} RetrievalMethod;
std::array<const char*, 12> acMapping = {
"Switch",
"Background (Prop type 1)",
"Player",
"Bomb",
"NPC",
"Enemy",
"Prop type 2",
"Item/Action",
"Misc.",
"Boss",
"Door",
"Chest"
};
// https://wiki.cloudmodding.com/oot/Actor_List_(Variables)
std::map<u16, const char*> actorDescriptions = {
{ ACTOR_PLAYER, "Link" },
{ ACTOR_EN_TEST, "Stalfos" },
{ ACTOR_EN_GIRLA, "Shop Items" },
{ ACTOR_EN_PART, "Body Parts" },
{ ACTOR_EN_LIGHT, "Decorative Flames" },
{ ACTOR_EN_DOOR, "Door" },
{ ACTOR_EN_BOX, "Treasure Chest" },
{ ACTOR_BG_DY_YOSEIZO, "Great Fairy" },
{ ACTOR_BG_HIDAN_FIREWALL, "Proximity activated Fire Wall" },
{ ACTOR_EN_POH, "Poe" },
{ ACTOR_EN_OKUTA, "Octorok" },
{ ACTOR_BG_YDAN_SP, "Webs" },
{ ACTOR_EN_BOM, "Bomb" },
{ ACTOR_EN_WALLMAS, "Wallmaster" },
{ ACTOR_EN_DODONGO, "Dodongo" },
{ ACTOR_EN_FIREFLY, "Keese" },
{ ACTOR_EN_HORSE, "Rideable Horse" },
{ ACTOR_EN_ITEM00, "Collectibles" },
{ ACTOR_EN_ARROW, "Arrow" },
{ ACTOR_EN_ELF, "Fairy" },
{ ACTOR_EN_NIW, "Cucco" },
{ ACTOR_EN_TITE, "Tektite" },
{ ACTOR_EN_REEBA, "Leever" },
{ ACTOR_EN_PEEHAT, "Peahat and Larva" },
{ ACTOR_EN_BUTTE, "Butterfly" },
{ ACTOR_EN_INSECT, "Bugs" },
{ ACTOR_EN_FISH, "Fish" },
{ ACTOR_EN_HOLL, "Room changing plane" },
{ ACTOR_EN_SCENE_CHANGE, "ovl_En_Scene_Change (broken)" },
{ ACTOR_EN_ZF, "Lizalfos and Dinolfos" },
{ ACTOR_EN_HATA, "Wooden Flagpole with Red Cloth" },
{ ACTOR_BOSS_DODONGO, "King Dodongo" },
{ ACTOR_BOSS_GOMA, "Gohma" },
{ ACTOR_EN_ZL1, "Child Princess Zelda (at window)" },
{ ACTOR_EN_VIEWER, "Cutscene Actors" },
{ ACTOR_EN_GOMA, "Gohma Larva" },
{ ACTOR_BG_PUSHBOX, "Cube" },
{ ACTOR_EN_BUBBLE, "Shabom" },
{ ACTOR_DOOR_SHUTTER, "Shutter Door" },
{ ACTOR_EN_DODOJR, "Baby Dodongo" },
{ ACTOR_EN_BDFIRE, "Empty" },
{ ACTOR_EN_BOOM, "Boomerang" },
{ ACTOR_EN_TORCH2, "Dark Link" },
{ ACTOR_EN_BILI, "Biri" },
{ ACTOR_EN_TP, "Electric Tailpasaran" },
{ ACTOR_EN_ST, "Skulltula" },
{ ACTOR_EN_BW, "Torch Slug" },
{ ACTOR_EN_A_OBJ, "Gameplay_keep items" },
{ ACTOR_EN_EIYER, "Stinger (Land)" },
{ ACTOR_EN_RIVER_SOUND, "Ambient Sound Effects" },
{ ACTOR_EN_HORSE_NORMAL, "Horse" },
{ ACTOR_EN_OSSAN, "Shopkeeper" },
{ ACTOR_BG_TREEMOUTH, "Great Deku Tree's Jaw" },
{ ACTOR_BG_DODOAGO, "Dodongo's Cavern Mega Dodongo" },
{ ACTOR_BG_HIDAN_DALM, "Megaton Hammer Statue" },
{ ACTOR_BG_HIDAN_HROCK, "Huge stone spike platform (Fire Temple)" },
{ ACTOR_EN_HORSE_GANON, "Ganondorf's Horse" },
{ ACTOR_BG_HIDAN_ROCK, "Stone Blocks (Fire Temple)" },
{ ACTOR_BG_HIDAN_RSEKIZOU, "Spinning Stone Flamethrower (Fire Temple)" },
{ ACTOR_BG_HIDAN_SEKIZOU, "Stationary Flamethrower Statue (Fire Temple)" },
{ ACTOR_BG_HIDAN_SIMA, "Stone Platform (Fire Temple)" },
{ ACTOR_BG_HIDAN_SYOKU, "Stone Elevator (Fire Temple)" },
{ ACTOR_EN_XC, "Sheik" },
{ ACTOR_BG_HIDAN_CURTAIN, "Flame Circle" },
{ ACTOR_BG_SPOT00_HANEBASI, "Drawbridge Objects" },
{ ACTOR_EN_MB, "Moblins" },
{ ACTOR_EN_BOMBF, "Bombflower" },
{ ACTOR_EN_ZL2, "Adult Zelda (Cutscenes)" },
{ ACTOR_BG_HIDAN_FSLIFT, "Hookshot Elevator Platform (Fire Temple)" },
{ ACTOR_EN_OE2, "Unused NPC" },
{ ACTOR_BG_YDAN_HASI, "Deku Tree Puzzle elements" },
{ ACTOR_BG_YDAN_MARUTA, "Rotating Spiked Log (Deku Tree)" },
{ ACTOR_BOSS_GANONDROF, "Phantom Ganon" },
{ ACTOR_EN_AM, "Armos Statue" },
{ ACTOR_EN_DEKUBABA, "Deku Baba" },
{ ACTOR_EN_M_FIRE1, "Thrown Deku Nut" },
{ ACTOR_EN_M_THUNDER, "Spin Attack" },
{ ACTOR_BG_DDAN_JD, "Rising Stone Platform (Dodongo's Cavern)" },
{ ACTOR_BG_BREAKWALL, "Bombable Wall" },
{ ACTOR_EN_JJ, "Lord Jabu-Jabu" },
{ ACTOR_EN_HORSE_ZELDA, "Zelda's Horse" },
{ ACTOR_BG_DDAN_KD, "Stone Stairs (Dodongo's Cavern)" },
{ ACTOR_DOOR_WARP1, "Warp Portal" },
{ ACTOR_OBJ_SYOKUDAI, "Torch" },
{ ACTOR_ITEM_B_HEART, "Heart container" },
{ ACTOR_EN_DEKUNUTS, "Mad Scrub" },
{ ACTOR_BG_MENKURI_KAITEN, "Rotating Stone Ring Platform" },
{ ACTOR_BG_MENKURI_EYE, "Eye Statue" },
{ ACTOR_EN_VALI, "Bari" },
{ ACTOR_BG_MIZU_MOVEBG, "Water Temple Background Actors" },
{ ACTOR_BG_MIZU_WATER, "Water Plane (Water Temple)" },
{ ACTOR_ARMS_HOOK, "Hookshot" },
{ ACTOR_EN_FHG, "Phantom Ganon's Horse" },
{ ACTOR_BG_MORI_HINERI, "Twisted Hallway Rooms" },
{ ACTOR_EN_BB, "Bubble" },
{ ACTOR_BG_TOKI_HIKARI, "Windows (Temple of Time)" },
{ ACTOR_EN_YUKABYUN, "Flying Floor Tile" },
{ ACTOR_BG_TOKI_SWD, "Master Sword" },
{ ACTOR_EN_FHG_FIRE, "Empty" },
{ ACTOR_BG_MJIN, "Warp Song Pad" },
{ ACTOR_BG_HIDAN_KOUSI, "Sliding Metal Gate" },
{ ACTOR_DOOR_TOKI, "Door of Time Collision" },
{ ACTOR_BG_HIDAN_HAMSTEP, "Stone Steps and Platforms (Fire Temple)" },
{ ACTOR_EN_BIRD, "Brown Bird" },
{ ACTOR_EN_WOOD02, "Trees and Bushes" },
{ ACTOR_EN_LIGHTBOX, "Large noisy stone" },
{ ACTOR_EN_PU_BOX, "Stone cube" },
{ ACTOR_EN_TRAP, "Metal Spike Trap" },
{ ACTOR_EN_AROW_TRAP, "Arrow Trap" },
{ ACTOR_EN_VASE, "Orange Pot" },
{ ACTOR_EN_TA, "Talon" },
{ ACTOR_EN_TK, "Dampe (Alive)" },
{ ACTOR_BG_MORI_BIGST, "Large Round Platform (Forest Temple)" },
{ ACTOR_BG_MORI_ELEVATOR, "Elevator (Forest Temple)" },
{ ACTOR_BG_MORI_KAITENKABE, "Rotatable Walls (Forest Temple)" },
{ ACTOR_BG_MORI_RAKKATENJO, "Falling Ceiling (Forest Temple)" },
{ ACTOR_EN_VM, "Beamos" },
{ ACTOR_DEMO_EFFECT, "Spiritual Stones, Medallions, Triforce" },
{ ACTOR_DEMO_KANKYO, "Temple of Time Objects" },
{ ACTOR_BG_HIDAN_FWBIG, "Large Fire Wall (Fire Temple)" },
{ ACTOR_EN_FLOORMAS, "Floormaster" },
{ ACTOR_EN_HEISHI1, "Castle Courtyard Guards" },
{ ACTOR_EN_RD, "Redead and Gibdo" },
{ ACTOR_EN_PO_SISTERS, "Poe Sisters" },
{ ACTOR_BG_HEAVY_BLOCK, "Golden Gauntlets Pillar" },
{ ACTOR_BG_PO_EVENT, "Poe Sisters' Paintings and Puzzle Block" },
{ ACTOR_OBJ_MURE, "Fish, Bugs, Butterflies Group Spawner" },
{ ACTOR_EN_SW, "Skullwalltula and Gold Skulltulas" },
{ ACTOR_BOSS_FD, "Volvagia (Flying)" },
{ ACTOR_OBJECT_KANKYO, "Environmental Effects" },
{ ACTOR_EN_DU, "Darunia" },
{ ACTOR_EN_FD, "Flare Dancer" },
{ ACTOR_EN_HORSE_LINK_CHILD, "Young Epona" },
{ ACTOR_DOOR_ANA, "Grotto Entrance" },
{ ACTOR_BG_SPOT02_OBJECTS, "Graveyard Actors" },
{ ACTOR_BG_HAKA, "Gravestone" },
{ ACTOR_MAGIC_WIND, "Farore's Wind" },
{ ACTOR_MAGIC_FIRE, "Din's Fire" },
{ ACTOR_EN_RU1, "Ruto (Child)" },
{ ACTOR_BOSS_FD2, "Volvagia (Hole Form)" },
{ ACTOR_EN_FD_FIRE, "Flare Dancer Fire Attack" },
{ ACTOR_EN_DH, "Dead Hand" },
{ ACTOR_EN_DHA, "Dead Hand's Hand" },
{ ACTOR_EN_RL, "Rauru" },
{ ACTOR_EN_ENCOUNT1, "Enemy Spawner" },
{ ACTOR_DEMO_DU, "Darunia (Cutscenes)" },
{ ACTOR_DEMO_IM, "Impa (Cutscenes)" },
{ ACTOR_DEMO_TRE_LGT, "Treasure Chest Light" },
{ ACTOR_EN_FW, "Flare Dancer Core" },
{ ACTOR_BG_VB_SIMA, "Volvagia Platform" },
{ ACTOR_EN_VB_BALL, "Volvagia Rocks and Bones" },
{ ACTOR_BG_HAKA_MEGANE, "Shadow Temple Fake Walls" },
{ ACTOR_BG_HAKA_MEGANEBG, "Platforms (Shadow Temple)" },
{ ACTOR_BG_HAKA_SHIP, "River Boat (Shadow Temple)" },
{ ACTOR_BG_HAKA_SGAMI, "Spinning Scythe Trap" },
{ ACTOR_EN_HEISHI2, "Hyrulian Guards" },
{ ACTOR_EN_ENCOUNT2, "Falling Rock Spawner" },
{ ACTOR_EN_FIRE_ROCK, "Falling Burning Rocks" },
{ ACTOR_EN_BROB, "Flobbery Muscle Block (Jabu-Jabu's Belly)" },
{ ACTOR_MIR_RAY, "Reflectable Light Beam" },
{ ACTOR_BG_SPOT09_OBJ, "Gerudo Valley Objects" },
{ ACTOR_BG_SPOT18_OBJ, "Statue (Darunia's Room)" },
{ ACTOR_BOSS_VA, "Barinade" },
{ ACTOR_BG_HAKA_TUBO, "Giant Skull Jar (Shadow Temple)" },
{ ACTOR_BG_HAKA_TRAP, "Shadow Temple Traps" },
{ ACTOR_BG_HAKA_HUTA, "Coffin Lid" },
{ ACTOR_BG_HAKA_ZOU, "Bird Statue and Wall (Shadow Temple)" },
{ ACTOR_BG_SPOT17_FUNEN, "Smoke Cone (Death Mountain Crater)" },
{ ACTOR_EN_SYATEKI_ITM, "Shooting Gallery Game" },
{ ACTOR_EN_SYATEKI_MAN, "Shooting Gallery Man" },
{ ACTOR_EN_TANA, "Shop Shelves" },
{ ACTOR_EN_NB, "Nabooru" },
{ ACTOR_BOSS_MO, "Morpha" },
{ ACTOR_EN_SB, "Shell Blade" },
{ ACTOR_EN_BIGOKUTA, "Big Octo" },
{ ACTOR_EN_KAREBABA, "Withered Deku Baba" },
{ ACTOR_BG_BDAN_OBJECTS, "Inside Jabu-Jabu's Belly Objects" },
{ ACTOR_DEMO_SA, "Saria (Cutscenes)" },
{ ACTOR_DEMO_GO, "Gorons (Cutscene)" },
{ ACTOR_EN_IN, "Ingo" },
{ ACTOR_EN_TR, "Koume and Kotake" },
{ ACTOR_BG_SPOT16_BOMBSTONE, "Dodongo's Cavern Entrance Blocking Rock" },
{ ACTOR_BG_HIDAN_KOWARERUKABE, "Bombable Walls (Fire Temple)" },
{ ACTOR_BG_BOMBWALL, "2D Bombable Wall" },
{ ACTOR_BG_SPOT08_ICEBLOCK, "Ice Platform (Zora's Fountain)" },
{ ACTOR_EN_RU2, "Ruto (Adult)" },
{ ACTOR_OBJ_DEKUJR, "Deku Tree Sprout" },
{ ACTOR_BG_MIZU_UZU, "Water Vortex Effect (Water Temple)" },
{ ACTOR_BG_SPOT06_OBJECTS, "Lake Hylia Objects" },
{ ACTOR_BG_ICE_OBJECTS, "Pushable Ice Block (Ice Cavern)" },
{ ACTOR_BG_HAKA_WATER, "Bottom of the Well Water Level Changer" },
{ ACTOR_EN_MA2, "Malon (Adult, Ingo's Ranch)" },
{ ACTOR_EN_BOM_CHU, "Bombchu" },
{ ACTOR_EN_HORSE_GAME_CHECK, "Horseback Minigames" },
{ ACTOR_BOSS_TW, "Twinrova" },
{ ACTOR_EN_RR, "Like-Like" },
{ ACTOR_EN_BA, "Tentacle (Inside Jabu-Jabu's Belly)" },
{ ACTOR_EN_BX, "Electrified Tentacle (Inside Jabu-Jabu's Belly)" },
{ ACTOR_EN_ANUBICE, "Anubis (Body)" },
{ ACTOR_EN_ANUBICE_FIRE, "Anubis Fire Attack" },
{ ACTOR_BG_MORI_HASHIGO, "Ladder (Forest Temple)" },
{ ACTOR_BG_MORI_HASHIRA4, "Forest Temple Objects" },
{ ACTOR_BG_MORI_IDOMIZU, "Well Water (Forest Temple)" },
{ ACTOR_BG_SPOT16_DOUGHNUT, "Cloud Ring (Death Mountain)" },
{ ACTOR_BG_BDAN_SWITCH, "Switches (Inside Lord Jabu-Jabu)" },
{ ACTOR_EN_MA1, "Malon (Child)" },
{ ACTOR_BOSS_GANON, "Ganondorf" },
{ ACTOR_BOSS_SST, "Bongo Bongo" },
{ ACTOR_EN_NY, "Spike (Enemy)" },
{ ACTOR_EN_FR, "Frog Song Spot and Frogs" },
{ ACTOR_ITEM_SHIELD, "Deku Shield" },
{ ACTOR_BG_ICE_SHELTER, "Red Ice" },
{ ACTOR_EN_ICE_HONO, "Blue Fire Flames" },
{ ACTOR_ITEM_OCARINA, "Ocarina of Time" },
{ ACTOR_MAGIC_DARK, "Nayru's Love" },
{ ACTOR_DEMO_6K, "Sages, Balls of Light (Cutscene)" },
{ ACTOR_EN_ANUBICE_TAG, "Anubis Spawn" },
{ ACTOR_BG_HAKA_GATE, "Truth Spinner Puzzle (Shadow Temple)" },
{ ACTOR_BG_SPOT15_SAKU, "Hyrule Castle Gate" },
{ ACTOR_BG_JYA_GOROIWA, "Rolling Boulder (Spirit Temple)" },
{ ACTOR_BG_JYA_ZURERUKABE, "Sliding, Climbable Brick Wall (Spirit Temple)" },
{ ACTOR_BG_JYA_COBRA, "Rotatable Cobra Mirror (Spirit Temple)" },
{ ACTOR_BG_JYA_KANAAMI, "Climbable Metal Grating Bridge (Spirit Temple)" },
{ ACTOR_FISHING, "Fishing Pond Man and Fish" },
{ ACTOR_OBJ_OSHIHIKI, "Pushable Block" },
{ ACTOR_BG_GATE_SHUTTER, "Gate to Death Mountain Trail" },
{ ACTOR_EFF_DUST, "Dust Effects" },
{ ACTOR_BG_SPOT01_FUSYA, "Windmill Sails (Kakariko Village)" },
{ ACTOR_BG_SPOT01_IDOHASHIRA, "Well Crossbeam (Kakariko Village)" },
{ ACTOR_BG_SPOT01_IDOMIZU, "Well Water (Kakariko Village)" },
{ ACTOR_BG_PO_SYOKUDAI, "Golden Torch (Poe Sisters)" },
{ ACTOR_BG_GANON_OTYUKA, "Falling Platform (Ganondorf Fight)" },
{ ACTOR_BG_SPOT15_RRBOX, "Milk Crate" },
{ ACTOR_BG_UMAJUMP, "Obstacle Fence (Lon Lon Ranch)" },
{ ACTOR_ARROW_FIRE, "Fire Arrow" },
{ ACTOR_ARROW_ICE, "Ice Arrow" },
{ ACTOR_ARROW_LIGHT, "Light Arrow" },
{ ACTOR_ITEM_ETCETERA, "Collectible Items" },
{ ACTOR_OBJ_KIBAKO, "Small Liftable Crate" },
{ ACTOR_OBJ_TSUBO, "Breakable Pot" },
{ ACTOR_EN_WONDER_ITEM, "Invisible Collectible" },
{ ACTOR_EN_IK, "Iron Knuckle" },
{ ACTOR_DEMO_IK, "Iron Knuckle armor pieces (Spirit Temple Nabooru fight)" },
{ ACTOR_EN_SKJ, "Skullkid" },
{ ACTOR_EN_SKJNEEDLE, "Skullkid Needle Attack" },
{ ACTOR_EN_G_SWITCH, "Silver Rupee" },
{ ACTOR_DEMO_EXT, "Magic Vortex" },
{ ACTOR_DEMO_SHD, "Bongo Bongo's Shadow" },
{ ACTOR_EN_DNS, "Business Scrub" },
{ ACTOR_ELF_MSG, "Navi Message" },
{ ACTOR_EN_HONOTRAP, "Stone Eye (Fire Trap) and Flame" },
{ ACTOR_EN_TUBO_TRAP, "Flying Pot" },
{ ACTOR_OBJ_ICE_POLY, "Ice spawned by red ice? frozen actors" },
{ ACTOR_BG_SPOT03_TAKI, "Zora's River Waterfall" },
{ ACTOR_BG_SPOT07_TAKI, "Zora's Domain Waterfall and Ice" },
{ ACTOR_EN_FZ, "Frezzard" },
{ ACTOR_EN_PO_RELAY, "Dampe's Ghost" },
{ ACTOR_BG_RELAY_OBJECTS, "Windmill Objects" },
{ ACTOR_EN_DIVING_GAME, "Zora Diving Game" },
{ ACTOR_EN_KUSA, "Bush/Grass" },
{ ACTOR_OBJ_BEAN, "Bean Plant Spot" },
{ ACTOR_OBJ_BOMBIWA, "Brown Bombable Boulder" },
{ ACTOR_OBJ_SWITCH, "Switches" },
{ ACTOR_OBJ_ELEVATOR, "Huge Stone Elevator" },
{ ACTOR_OBJ_LIFT, "Square Collapsing Platform" },
{ ACTOR_OBJ_HSBLOCK, "Stone Hookshot Target" },
{ ACTOR_EN_OKARINA_TAG, "Ocarina Music Staff Spot" },
{ ACTOR_EN_YABUSAME_MARK, "Horseback Archery Target" },
{ ACTOR_EN_GOROIWA, "Rolling Boulder" },
{ ACTOR_EN_EX_RUPPY, "Sparkling Rupee" },
{ ACTOR_EN_TORYO, "Boss Carpenter" },
{ ACTOR_EN_DAIKU, "Carpenters" },
{ ACTOR_EN_NWC, "Cucco Chick" },
{ ACTOR_EN_BLKOBJ, "Dark Link's Illusion Room" },
{ ACTOR_ITEM_INBOX, "Zelda's Magic to Open Gates" },
{ ACTOR_EN_GE1, "White Clothed Gerudo" },
{ ACTOR_OBJ_BLOCKSTOP, "Pushblock Stop" },
{ ACTOR_EN_SDA, "Dynamic Shadow" },
{ ACTOR_EN_CLEAR_TAG, "Arwing" },
{ ACTOR_EN_NIW_LADY, "Cucco Lady" },
{ ACTOR_EN_GM, "Medigoron" },
{ ACTOR_EN_MS, "Bean Salesman" },
{ ACTOR_EN_HS, "Carpenter's Son" },
{ ACTOR_BG_INGATE, "Ingo's Gates (Lon Lon Ranch)" },
{ ACTOR_EN_KANBAN, "Square Signpost" },
{ ACTOR_EN_HEISHI3, "Hyrule Castle Guard" },
{ ACTOR_EN_SYATEKI_NIW, "Cucco (Minigames)" },
{ ACTOR_EN_ATTACK_NIW, "Cucco (Attacking)" },
{ ACTOR_BG_SPOT01_IDOSOKO, "Stone Blocking Entrance to Bottom of the Well" },
{ ACTOR_EN_SA, "Saria" },
{ ACTOR_EN_WONDER_TALK, "Checkable Spot (Green Navi)" },
{ ACTOR_BG_GJYO_BRIDGE, "Rainbow Bridge to Ganon's Castle" },
{ ACTOR_EN_DS, "Potion Shop Granny" },
{ ACTOR_EN_MK, "Lakeside Professor" },
{ ACTOR_EN_BOM_BOWL_MAN, "Bombchu Bowling Alley Lady" },
{ ACTOR_EN_BOM_BOWL_PIT, "Bombchu Bowling Alley Final Target" },
{ ACTOR_EN_OWL, "Kaepora Gaebora" },
{ ACTOR_EN_ISHI, "Liftable Rock" },
{ ACTOR_OBJ_HANA, "Uninteractable Flowers, Rocks, Grass" },
{ ACTOR_OBJ_LIGHTSWITCH, "Sun Emblem Switch (Spirit Temple)" },
{ ACTOR_OBJ_MURE2, "Rock/Bush groups" },
{ ACTOR_EN_GO, "Gorons 1" },
{ ACTOR_EN_FU, "Windmill Man" },
{ ACTOR_EN_CHANGER, "Treasure Box Shop Minigame" },
{ ACTOR_BG_JYA_MEGAMI, "Statue Face (Spirit Temple)" },
{ ACTOR_BG_JYA_LIFT, "Chain Platform (Spirit Temple)" },
{ ACTOR_BG_JYA_BIGMIRROR, "Large Circular Mirror (Spirt Temple)" },
{ ACTOR_BG_JYA_BOMBCHUIWA, "Light Blocking Rock (Spirit Temple)" },
{ ACTOR_BG_JYA_AMISHUTTER, "Sliding Circular Metal Grate (Spirit Temple)" },
{ ACTOR_BG_JYA_BOMBIWA, "Bombable Rock Wall (Spirit Temple)" },
{ ACTOR_BG_SPOT18_BASKET, "Big Goron Pot" },
{ ACTOR_EN_GANON_ORGAN, "Ganon's Organ and surroundings" },
{ ACTOR_EN_SIOFUKI, "Water Spout" },
{ ACTOR_EN_STREAM, "Water Vortex" },
{ ACTOR_EN_MM, "Running Man (Child Era)" },
{ ACTOR_EN_KO, "Kokiri Children" },
{ ACTOR_EN_KZ, "King Zora" },
{ ACTOR_EN_WEATHER_TAG, "Proximity Weather Effects" },
{ ACTOR_BG_SST_FLOOR, "Bongo Bongo's Drum" },
{ ACTOR_EN_ANI, "Kakariko Village Rooftop Man" },
{ ACTOR_EN_EX_ITEM, "Minigame Displayed Items" },
{ ACTOR_BG_JYA_IRONOBJ, "Iron Knuckles Room Stuff (Spirit Temple)" },
{ ACTOR_EN_JS, "Magic Carpet Man" },
{ ACTOR_EN_JSJUTAN, "Magic Carpet Man Carpet" },
{ ACTOR_EN_CS, "Graveyard Boy" },
{ ACTOR_EN_MD, "Mido" },
{ ACTOR_EN_HY, "Market NPCs" },
{ ACTOR_EN_GANON_MANT, "Ganondorf's Cape" },
{ ACTOR_EN_OKARINA_EFFECT, "Song of Storms Storm Manager" },
{ ACTOR_EN_MAG, "Title Screen Manager" },
{ ACTOR_DOOR_GERUDO, "Cell Door (Gerudo Fortress)" },
{ ACTOR_ELF_MSG2, "Navi Information Spot (Targetable, Green)" },
{ ACTOR_DEMO_GT, "Ganon's Tower Collapsing (Cutscene Objects)" },
{ ACTOR_EN_PO_FIELD, "Big/Small Poe Spawn Point" },
{ ACTOR_EFC_ERUPC, "Lava Particle Fountain (Death Mountain panorama)" },
{ ACTOR_BG_ZG, "Metal Bars (Ganon's Castle)" },
{ ACTOR_EN_HEISHI4, "Hyrule Guard" },
{ ACTOR_EN_ZL3, "Adult Zelda" },
{ ACTOR_BOSS_GANON2, "Ganon" },
{ ACTOR_EN_KAKASI, "Pierre the Scarecrow" },
{ ACTOR_EN_TAKARA_MAN, "Treasure Box Shop Man" },
{ ACTOR_OBJ_MAKEOSHIHIKI, "Push Block Puzzles" },
{ ACTOR_OCEFF_SPOT, "Sun's Song Effect" },
{ ACTOR_END_TITLE, "The End message" },
{ ACTOR_EN_TORCH, "Grotto Treasure Chest" },
{ ACTOR_DEMO_EC, "Credits Revelers in Lon Lon" },
{ ACTOR_SHOT_SUN, "Lake Hylia Sun Hitbox, Big Fairy Spawner" },
{ ACTOR_EN_DY_EXTRA, "Spiral Beams (Great Fairy Fountains)" },
{ ACTOR_EN_WONDER_TALK2, "Dialog Spot" },
{ ACTOR_EN_GE2, "Patrolling Gerudo" },
{ ACTOR_OBJ_ROOMTIMER, "Room Timer" },
{ ACTOR_EN_SSH, "Cursed Skulltula People" },
{ ACTOR_EN_STH, "Uncursed Skulltula People" },
{ ACTOR_OCEFF_WIPE, "Zelda's Lullaby and Song of Time Ocarina Effect" },
{ ACTOR_OCEFF_STORM, "Song of Storm Ocarina Effect" },
{ ACTOR_EN_WEIYER, "Stinger (Water)" },
{ ACTOR_BG_SPOT05_SOKO, "Sacred Forest Meadow Objects" },
{ ACTOR_BG_JYA_1FLIFT, "Stone Elevator (Spirit Temple)" },
{ ACTOR_BG_JYA_HAHENIRON, "Chunks of Iron Knucle Chair and Pillar" },
{ ACTOR_BG_SPOT12_GATE, "Gerudo Fortress Wooden Gate" },
{ ACTOR_BG_SPOT12_SAKU, "Gerudo Fortress Training Area Gate" },
{ ACTOR_EN_HINTNUTS, "Hint Deku Scrubs (Deku Tree)" },
{ ACTOR_EN_NUTSBALL, "Deku Scrub Nut Attack" },
{ ACTOR_BG_SPOT00_BREAK, "Broken Drawbridge, Fences" },
{ ACTOR_EN_SHOPNUTS, "Grounded Sales Scrub" },
{ ACTOR_EN_IT, "Dampe's Minigame Collectibles" },
{ ACTOR_EN_GELDB, "Gerudo Fighter" },
{ ACTOR_OCEFF_WIPE2, "Epona's Song Ocarina Effect" },
{ ACTOR_OCEFF_WIPE3, "Saria's Song Ocarina Effect" },
{ ACTOR_EN_NIW_GIRL, "Girl Chasing Cucco" },
{ ACTOR_EN_DOG, "Dog" },
{ ACTOR_EN_SI, "Gold Skulltula Token" },
{ ACTOR_BG_SPOT01_OBJECTS2, "Kakariko Village Objects" },
{ ACTOR_OBJ_COMB, "Beehive" },
{ ACTOR_BG_SPOT11_BAKUDANKABE, "Destructible Wall (Desert Colossus)" },
{ ACTOR_OBJ_KIBAKO2, "Large Crate" },
{ ACTOR_EN_DNT_DEMO, "Deku Mask Panel Trigger" },
{ ACTOR_EN_DNT_JIJI, "Deku Mask Panel Head Judge" },
{ ACTOR_EN_DNT_NOMAL, "Deku Game?" },
{ ACTOR_EN_GUEST, "Happy Mask Shop Customer" },
{ ACTOR_BG_BOM_GUARD, "Bombchu Bowling Alley Aiming Area" },
{ ACTOR_EN_HS2, "Carpenter's Son (Child Era)" },
{ ACTOR_DEMO_KEKKAI, "Ganon's Tower Magic Barriers" },
{ ACTOR_BG_SPOT08_BAKUDANKABE, "Destructible Wall (Zora's Fountain)" },
{ ACTOR_BG_SPOT17_BAKUDANKABE, "Destructible Wall (Death Mountain Crater)" },
{ ACTOR_OBJ_MURE3, "Rupee Patterns" },
{ ACTOR_EN_TG, "Entwined Lovers (Honey & Darling)" },
{ ACTOR_EN_MU, "Haggling Townspeople" },
{ ACTOR_EN_GO2, "Gorons 2" },
{ ACTOR_EN_WF, "Wolfos" },
{ ACTOR_EN_SKB, "Stalchild" },
{ ACTOR_DEMO_GJ, "Ganon Battle Rubble" },
{ ACTOR_DEMO_GEFF, "Ganon's Tower Rubble Fragment" },
{ ACTOR_BG_GND_FIREMEIRO, "Sinking Lava Platform (Ganon's Castle)" },
{ ACTOR_BG_GND_DARKMEIRO, "Clear block" },
{ ACTOR_BG_GND_SOULMEIRO, "Web-Blocked Ceiling Hole (Inside Ganon's Castle)" },
{ ACTOR_BG_GND_NISEKABE, "Ganon's Castle Fake Walls" },
{ ACTOR_BG_GND_ICEBLOCK, "Pushable Square Ice Block (Inside Ganon's Castle)" },
{ ACTOR_EN_GB, "Poe Collector and Surroundings" },
{ ACTOR_EN_GS, "Gossip Stone" },
{ ACTOR_BG_MIZU_BWALL, "Bombable Stone Wall" },
{ ACTOR_BG_MIZU_SHUTTER, "Metal Gate (Water Temple)" },
{ ACTOR_EN_DAIKU_KAKARIKO, "Carpenters (Kakariko)" },
{ ACTOR_BG_BOWL_WALL, "Bombchu Bowling Alley Wall" },
{ ACTOR_EN_WALL_TUBO, "Bombchu Bowling Alley Bullseyes" },
{ ACTOR_EN_PO_DESERT, "Poe Guide (Desert Wasteland)" },
{ ACTOR_EN_CROW, "Guay" },
{ ACTOR_DOOR_KILLER, "Fake Door" },
{ ACTOR_BG_SPOT11_OASIS, "Oasis (Desert Colossus)" },
{ ACTOR_BG_SPOT18_FUTA, "Goron Jar Lid" },
{ ACTOR_BG_SPOT18_SHUTTER, "Sliding Doors (Goron City)" },
{ ACTOR_EN_MA3, "Malon (Adult, Lon Lon Ranch)" },
{ ACTOR_EN_COW, "Cow" },
{ ACTOR_BG_ICE_TURARA, "Icicles" },
{ ACTOR_BG_ICE_SHUTTER, "Vertical Ice Bars (Ice Cavern)" },
{ ACTOR_EN_KAKASI2, "Pierre the Scarecrow Spawn" },
{ ACTOR_EN_KAKASI3, "Bonooru the Scarecrow" },
{ ACTOR_OCEFF_WIPE4, "Scarecrow's Song Ocarina Effect" },
{ ACTOR_EN_EG, "Void-out Trigger (Tower Collapse)" },
{ ACTOR_BG_MENKURI_NISEKABE, "False Stone Walls (Gerudo Training Grounds)" },
{ ACTOR_EN_ZO, "Zora" },
{ ACTOR_OBJ_MAKEKINSUTA, "Skulltula Sprouting from Bean Spot" },
{ ACTOR_EN_GE3, "Gerudo Fortress Leader" },
{ ACTOR_OBJ_TIMEBLOCK, "Time Block" },
{ ACTOR_OBJ_HAMISHI, "Bronze Boulder" },
{ ACTOR_EN_ZL4, "Zelda (Child)" },
{ ACTOR_EN_MM2, "Running Man (Adult Era)" },
{ ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" },
{ ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" }
};
const std::string GetActorDescription(u16 id) {
return actorDescriptions[id] != NULL ? actorDescriptions[id] : "???";
}
template <typename T> void DrawGroupWithBorder(T&& drawFunc) {
// First group encapsulates the inner portion and border
ImGui::BeginGroup();
ImVec2 padding = ImGui::GetStyle().FramePadding;
ImVec2 p0 = ImGui::GetCursorScreenPos();
ImGui::SetCursorScreenPos(ImVec2(p0.x + padding.x, p0.y + padding.y));
// Second group encapsulates just the inner portion
ImGui::BeginGroup();
drawFunc();
ImGui::Dummy(padding);
ImGui::EndGroup();
ImVec2 p1 = ImGui::GetItemRectMax();
p1.x += padding.x;
ImVec4 borderCol = ImGui::GetStyle().Colors[ImGuiCol_Border];
ImGui::GetWindowDrawList()->AddRect(
p0, p1, IM_COL32(borderCol.x * 255, borderCol.y * 255, borderCol.z * 255, borderCol.w * 255));
ImGui::EndGroup();
}
void PopulateActorDropdown(int i, std::vector<Actor*>& data) {
if (data.size() != 0) {
data.clear();
}
if (gGlobalCtx != nullptr) {
ActorListEntry currList = gGlobalCtx->actorCtx.actorLists[i];
Actor* currAct = currList.head;
if (currAct != nullptr) {
while (currAct != nullptr) {
data.push_back(currAct);
currAct = currAct->next;
}
}
}
}
void DrawActorViewer(bool& open) {
if (!open) {
CVar_SetS32("gActorViewerEnabled", 0);
return;
}
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Actor Viewer", &open, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}
static Actor display;
static const Actor empty{};
static Actor* fetch = NULL;
static ActorInfo newActor = {0,0, {0, 0, 0}, {0, 0, 0}};
static ActorOverlay* dispOverlay;
static bool needs_reset = false;
static ImU16 one = 1;
static int actor;
static int category = 0;
static RetrievalMethod rm;
static std::string filler = "Please select";
static std::vector<Actor*> list;
static u16 lastSceneId = 0;
if (gGlobalCtx != nullptr) {
needs_reset = lastSceneId != gGlobalCtx->sceneNum;
if (needs_reset) {
display = empty;
fetch = nullptr;
dispOverlay = nullptr;
actor = category = 0;
filler = "Please Select";
list.clear();
needs_reset = false;
}
lastSceneId = gGlobalCtx->sceneNum;
if (ImGui::BeginCombo("Actor Type", acMapping[category])) {
for (int i = 0; i < acMapping.size(); i++) {
if (ImGui::Selectable(acMapping[i])) {
category = i;
PopulateActorDropdown(category, list);
break;
}
}
ImGui::EndCombo();
}
if (ImGui::BeginCombo("Actor", filler.c_str())) {
if (gGlobalCtx != nullptr && lastSceneId != gGlobalCtx->sceneNum) {
PopulateActorDropdown(category, list);
lastSceneId = gGlobalCtx->sceneNum;
}
for (int i = 0; i < list.size(); i++) {
std::string label = std::to_string(i) + ": " + list[i]->overlayEntry->name;
std::string description = GetActorDescription(list[i]->id);
if (description != "")
label += " (" + description + ")";
if (ImGui::Selectable(label.c_str())) {
rm = LIST;
display = *list[i];
actor = i;
filler = label;
break;
}
}
ImGui::EndCombo();
}
if (ImGui::TreeNode("Selected Actor")) {
dispOverlay = display.overlayEntry;
DrawGroupWithBorder([&]() {
ImGui::Text("Name: %s", dispOverlay != nullptr ? dispOverlay->name : "???");
ImGui::Text("Description: %s", dispOverlay != nullptr ? GetActorDescription(display.id).c_str() : "???");
ImGui::Text("Category: %s", dispOverlay != nullptr ? acMapping[display.category] : "???");
ImGui::Text("ID: %d", display.id);
ImGui::Text("Parameters: %d", display.params);
});
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
ImGui::Text("Actor Position");
ImGui::InputScalar("x pos", ImGuiDataType_Float, &display.world.pos.x);
ImGui::SameLine();
ImGui::InputScalar("y pos", ImGuiDataType_Float, &display.world.pos.y);
ImGui::SameLine();
ImGui::InputScalar("z pos", ImGuiDataType_Float, &display.world.pos.z);
});
DrawGroupWithBorder([&]() {
ImGui::Text("Actor Rotation");
ImGui::InputScalar("x rot", ImGuiDataType_S16, &display.world.rot.x);
ImGui::SameLine();
ImGui::InputScalar("y rot", ImGuiDataType_S16, &display.world.rot.y);
ImGui::SameLine();
ImGui::InputScalar("z rot", ImGuiDataType_S16, &display.world.rot.z);
});
if (display.category == ACTORCAT_BOSS || display.category == ACTORCAT_ENEMY) {
ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display.colChkInfo.health);
InsertHelpHoverText("Some actors might not use this!");
}
if (ImGui::Button("Refresh")) {
PopulateActorDropdown(category, list);
switch (rm) {
case INTERACT:
case HELD:
case TARGET:
display = *fetch;
break;
case LIST:
display = *list[actor];
break;
default:
break;
}
}
if (ImGui::Button("Go to Actor")) {
Player* player = GET_PLAYER(gGlobalCtx);
Math_Vec3f_Copy(&player->actor.world.pos, &display.world.pos);
Math_Vec3f_Copy(&player->actor.home.pos, &player->actor.world.pos);
}
if (ImGui::Button("Fetch from Target")) {
Player* player = GET_PLAYER(gGlobalCtx);
fetch = player->targetActor;
if (fetch != NULL) {
display = *fetch;
category = fetch->category;
PopulateActorDropdown(category, list);
rm = TARGET;
}
}
InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies");
if (ImGui::Button("Fetch from Held")) {
Player* player = GET_PLAYER(gGlobalCtx);
fetch = player->heldActor;
if (fetch != NULL) {
display = *fetch;
category = fetch->category;
PopulateActorDropdown(category, list);
rm = HELD;
}
}
InsertHelpHoverText("Grabs actor that Link is holding");
if (ImGui::Button("Fetch from Interaction")) {
Player* player = GET_PLAYER(gGlobalCtx);
fetch = player->interactRangeActor;
if (fetch != NULL) {
display = *fetch;
category = fetch->category;
PopulateActorDropdown(category, list);
rm = INTERACT;
}
}
InsertHelpHoverText("Grabs actor from \"interaction range\"");
ImGui::TreePop();
}
if (ImGui::TreeNode("New...")) {
ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
ImGui::Text(GetActorDescription(newActor.id).c_str());
ImGui::InputScalar("ID", ImGuiDataType_S16, &newActor.id, &one);
ImGui::InputScalar("params", ImGuiDataType_S16, &newActor.params, &one);
ImGui::PushItemWidth(ImGui::GetFontSize() * 6);
DrawGroupWithBorder([&]() {
ImGui::Text("New Actor Position");
ImGui::InputScalar("posX", ImGuiDataType_Float, &newActor.pos.x);
ImGui::SameLine();
ImGui::InputScalar("posY", ImGuiDataType_Float, &newActor.pos.y);
ImGui::SameLine();
ImGui::InputScalar("posZ", ImGuiDataType_Float, &newActor.pos.z);
});
DrawGroupWithBorder([&]() {
ImGui::Text("New Actor Rotation");
ImGui::InputScalar("rotX", ImGuiDataType_S16, &newActor.rot.x);
ImGui::SameLine();
ImGui::InputScalar("rotY", ImGuiDataType_S16, &newActor.rot.y);
ImGui::SameLine();
ImGui::InputScalar("rotZ", ImGuiDataType_S16, &newActor.rot.z);
});
if (ImGui::Button("Fetch from Link")) {
Player* player = GET_PLAYER(gGlobalCtx);
Vec3f newPos = player->actor.world.pos;
Vec3s newRot = player->actor.world.rot;
newActor.pos = newPos;
newActor.rot = newRot;
}
if (ImGui::Button("Spawn")) {
if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX && gActorOverlayTable[newActor.id].initInfo != NULL) {
Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, newActor.id, newActor.pos.x, newActor.pos.y,
newActor.pos.z, newActor.rot.x, newActor.rot.y, newActor.rot.z, newActor.params);
} else {
func_80078884(NA_SE_SY_ERROR);
}
}
if (ImGui::Button("Spawn as Child")) {
Actor* parent = &display;
if (parent != NULL) {
if (newActor.id >= 0 && newActor.id < ACTOR_ID_MAX &&
gActorOverlayTable[newActor.id].initInfo != NULL) {
Actor_SpawnAsChild(&gGlobalCtx->actorCtx, parent, gGlobalCtx, newActor.id, newActor.pos.x,
newActor.pos.y, newActor.pos.z, newActor.rot.x, newActor.rot.y,
newActor.rot.z, newActor.params);
} else {
func_80078884(NA_SE_SY_ERROR);
}
}
}
if (ImGui::Button("Reset")) {
newActor = { 0, 0, { 0, 0, 0 }, { 0, 0, 0 } };
}
ImGui::TreePop();
}
} else {
ImGui::Text("Global Context needed for actor info!");
if (needs_reset) {
fetch = nullptr;
dispOverlay = nullptr;
actor = category = 0;
filler = "Please Select";
list.clear();
needs_reset = false;
}
}
ImGui::End();
}
void InitActorViewer() {
SohImGui::AddWindow("Developer Tools", "Actor Viewer", DrawActorViewer);
}

View file

@ -0,0 +1,3 @@
#pragma once
void InitActorViewer();

View file

@ -6,6 +6,7 @@
#include <vector>
#include <string>
#include <cmath>
#include <Cvar.h>
extern "C" {
#include <z64.h>
@ -15,40 +16,27 @@ extern "C" {
extern GlobalContext* gGlobalCtx;
}
enum class ColRenderSetting {
Disabled,
Solid,
Transparent,
NumSettings
};
enum class ColRenderSetting { Disabled, Solid, Transparent };
std::string ColRenderSettingNames[] = {
std::vector<std::string> ColRenderSettingNames = {
"Disabled",
"Solid",
"Transparent",
};
static ColRenderSetting showSceneColSetting = ColRenderSetting::Disabled;
static ColRenderSetting showBgActorSetting = ColRenderSetting::Disabled;
static ColRenderSetting showColCheckSetting = ColRenderSetting::Disabled;
static ColRenderSetting showWaterboxSetting = ColRenderSetting::Disabled;
ImVec4 scene_col;
ImVec4 hookshot_col;
ImVec4 entrance_col;
ImVec4 specialSurface_col;
ImVec4 interactable_col;
ImVec4 slope_col;
ImVec4 void_col;
static uint32_t sceneColor = 0xFFFFFFFF;
static uint32_t hookshotColor = 0x8080FFFF;
static uint32_t entranceColor = 0x00FF00FF;
static uint32_t specialSurfaceColor = 0xC0FFC0FF;
static uint32_t interactableColor = 0xC000C0FF;
static uint32_t slopeColor = 0xFFFF80FF;
static uint32_t voidColor = 0xFF0000FF;
ImVec4 oc_col;
ImVec4 ac_col;
ImVec4 at_col;
static uint32_t ocColor = 0xFFFFFFFF;
static uint32_t acColor = 0x0000FFFF;
static uint32_t atColor = 0xFF0000FF;
static uint32_t waterboxColor = 0x0000FFFF;
static bool applyAsDecal = false;
static bool isShaded = false;
ImVec4 waterbox_col;
static std::vector<Gfx> opaDl;
static std::vector<Gfx> xluDl;
@ -62,38 +50,10 @@ static std::vector<Vtx> cylinderVtx;
static std::vector<Gfx> sphereGfx;
static std::vector<Vtx> sphereVtx;
// Create a dropdown menu to set a ColRenderSetting
void DrawColRenderSetting(const std::string& name, ColRenderSetting& setting) {
if (ImGui::BeginCombo(name.c_str(), ColRenderSettingNames[static_cast<int>(setting)].c_str())) {
for (int32_t settingIndex = 0; settingIndex < static_cast<int>(ColRenderSetting::NumSettings); settingIndex++) {
if (ImGui::Selectable(ColRenderSettingNames[settingIndex].c_str())) {
setting = static_cast<ColRenderSetting>(settingIndex);
}
}
ImGui::EndCombo();
}
}
// Draw a color picker box
void DrawColorPicker(const std::string& name, uint32_t& color) {
float colorAsFloat[4];
colorAsFloat[0] = ((color >> 24) & 0xFF) / 255.0f;
colorAsFloat[1] = ((color >> 16) & 0xFF) / 255.0f;
colorAsFloat[2] = ((color >> 8) & 0xFF) / 255.0f;
colorAsFloat[3] = (color & 0xFF) / 255.0f;
if (ImGui::ColorEdit4(name.c_str(), colorAsFloat, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) {
color = static_cast<uint8_t>(colorAsFloat[3] * 255) |
static_cast<uint8_t>(colorAsFloat[2] * 255) << 8 |
static_cast<uint8_t>(colorAsFloat[1] * 255) << 16 |
static_cast<uint8_t>(colorAsFloat[0] * 255) << 24;
}
ImGui::SameLine();
ImGui::Text(name.c_str());
}
// Draws the ImGui window for the collision viewer
void DrawColViewerWindow(bool& open) {
if (!open) {
CVar_SetS32("gCollisionViewerEnabled", 0);
return;
}
@ -102,16 +62,17 @@ void DrawColViewerWindow(bool& open) {
ImGui::End();
return;
}
SohImGui::EnhancementCheckbox("Enabled", "gColViewerEnabled");
DrawColRenderSetting("Scene", showSceneColSetting);
DrawColRenderSetting("Bg Actors", showBgActorSetting);
DrawColRenderSetting("Col Check", showColCheckSetting);
DrawColRenderSetting("Waterbox", showWaterboxSetting);
SohImGui::EnhancementCombo("Scene", "gColViewerScene", ColRenderSettingNames);
SohImGui::EnhancementCombo("Bg Actors", "gColViewerBgActors", ColRenderSettingNames);
SohImGui::EnhancementCombo("Col Check", "gColViewerColCheck", ColRenderSettingNames);
SohImGui::EnhancementCombo("Waterbox", "gColViewerWaterbox", ColRenderSettingNames);
ImGui::Checkbox("Apply as decal", &applyAsDecal);
SohImGui::EnhancementCheckbox("Apply as decal", "gColViewerDecal");
InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
"with the scene geometry, but can cause other artifacts.");
ImGui::Checkbox("Shaded", &isShaded);
SohImGui::EnhancementCheckbox("Shaded", "gColViewerShaded");
InsertHelpHoverText("Applies the scene's shading to the collision display.");
// This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered()
@ -119,17 +80,20 @@ void DrawColViewerWindow(bool& open) {
if (ImGui::TreeNode("Colors")) {
InsertHelpHoverText(colorHelpText);
DrawColorPicker("Normal", sceneColor);
DrawColorPicker("Hookshot", hookshotColor);
DrawColorPicker("Entrance", entranceColor);
DrawColorPicker("Special Surface (Grass/Sand/Etc)", specialSurfaceColor);
DrawColorPicker("Interactable (Vines/Crawlspace/Etc)", interactableColor);
DrawColorPicker("Slope", slopeColor);
DrawColorPicker("Void", voidColor);
DrawColorPicker("OC", ocColor);
DrawColorPicker("AC", acColor);
DrawColorPicker("AT", atColor);
DrawColorPicker("Waterbox", waterboxColor);
SohImGui::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false);
SohImGui::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255),
false);
SohImGui::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false);
SohImGui::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface",
specialSurface_col, ImVec4(192, 255, 192, 255), false);
SohImGui::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable",
interactable_col, ImVec4(192, 0, 192, 255), false);
SohImGui::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false);
SohImGui::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false);
SohImGui::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false);
SohImGui::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false);
SohImGui::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false);
SohImGui::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false);
ImGui::TreePop();
} else {
@ -161,13 +125,12 @@ void CalcTriNorm(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3, Vec3f& norm)
.n = {.ob = { x, y, z }, .tc = { qs105(s), qs105(t) }, .n = { nx, ny, nz }, .a = ca } \
}
void CreateCylinderData() {
constexpr int32_t CYL_DIVS = 12;
cylinderGfx.reserve(5 + CYL_DIVS * 2);
cylinderVtx.reserve(2 + CYL_DIVS * 2);
cylinderVtx.push_back(gdSPDefVtxN(0, 0, 0, 0, 0, 0, -127, 0, 0xFF)); // Bottom center vertex
cylinderVtx.push_back(gdSPDefVtxN(0, 0, 0, 0, 0, 0, -127, 0, 0xFF)); // Bottom center vertex
cylinderVtx.push_back(gdSPDefVtxN(0, 128, 0, 0, 0, 0, 127, 0, 0xFF)); // Top center vertex
// Create two rings of vertices
for (int i = 0; i < CYL_DIVS; ++i) {
@ -210,9 +173,10 @@ void CreateCylinderData() {
cylinderGfx.push_back(gsSPEndDisplayList());
}
// This subdivides a face into four tris by placing new verticies at the midpoints of the sides (Like a triforce!), then blowing up the
// verticies so they are on the unit sphere
void CreateSphereFace(std::vector<std::tuple<size_t, size_t, size_t>>& faces, int32_t v0Index, int32_t v1Index, int32_t v2Index) {
// This subdivides a face into four tris by placing new verticies at the midpoints of the sides (Like a triforce!), then
// blowing up the verticies so they are on the unit sphere
void CreateSphereFace(std::vector<std::tuple<size_t, size_t, size_t>>& faces, int32_t v0Index, int32_t v1Index,
int32_t v2Index) {
size_t nextIndex = sphereVtx.size();
size_t v01Index = nextIndex;
@ -248,9 +212,9 @@ void CreateSphereFace(std::vector<std::tuple<size_t, size_t, size_t>>& faces, in
}
}
// Creates a sphere following the idea in here: http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html
// Spcifically, create a icosahedron by realizing that the points can be placed on 3 rectangles that are on each unit plane.
// Then, subdividing each face.
// Creates a sphere following the idea in here:
// http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html Spcifically, create a icosahedron by
// realizing that the points can be placed on 3 rectangles that are on each unit plane. Then, subdividing each face.
void CreateSphereData() {
std::vector<Vec3f> base;
@ -351,7 +315,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
alpha = 0xFF;
}
if (applyAsDecal) {
if (CVar_GetS32("gColViewerDecal", 0) != 0) {
rm |= ZMODE_DEC;
} else if (setting == ColRenderSetting::Transparent) {
rm |= ZMODE_XLU;
@ -363,7 +327,7 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
gfx.push_back(gsDPSetCycleType(G_CYC_1CYCLE));
gfx.push_back(gsDPSetRenderMode(rm | blc1, rm | blc2));
if (isShaded) {
if (CVar_GetS32("gColViewerShaded", 0) != 0) {
gfx.push_back(gsDPSetCombineMode(G_CC_MODULATERGB_PRIM_ENVA, G_CC_MODULATERGB_PRIM_ENVA));
gfx.push_back(gsSPLoadGeometryMode(G_CULL_BACK | G_ZBUFFER | G_LIGHTING));
} else {
@ -376,10 +340,16 @@ void InitGfx(std::vector<Gfx>& gfx, ColRenderSetting setting) {
// Draws a dynapoly structure (scenes or Bg Actors)
void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
uint32_t color = sceneColor;
uint32_t lastColor = color;
dl.push_back(gsDPSetPrimColor(0, 0, (color >> 24) & 0xFF, (color >> 16) & 0xFF, (color >> 8) & 0xFF,
(color >> 0) & 0xFF));
uint32_t colorR = CVar_GetS32("gColViewerColorNormalR", 255);
uint32_t colorG = CVar_GetS32("gColViewerColorNormalG", 255);
uint32_t colorB = CVar_GetS32("gColViewerColorNormalB", 255);
uint32_t colorA = 255;
uint32_t lastColorR = colorR;
uint32_t lastColorG = colorG;
uint32_t lastColorB = colorB;
dl.push_back(gsDPSetPrimColor(0, 0, colorR, colorG, colorB, colorA));
// This keeps track of if we have processed a poly, but not drawn it yet so we can batch them.
// This saves several hundred commands in larger scenes
@ -389,34 +359,49 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
CollisionPoly* poly = &col->polyList[i];
if (SurfaceType_IsHookshotSurface(&gGlobalCtx->colCtx, poly, bgId)) {
color = hookshotColor;
colorR = CVar_GetS32("gColViewerColorHookshotR", 128);
colorG = CVar_GetS32("gColViewerColorHookshotG", 128);
colorB = CVar_GetS32("gColViewerColorHookshotB", 255);
} else if (func_80041D94(&gGlobalCtx->colCtx, poly, bgId) > 0x01) {
color = interactableColor;
colorR = CVar_GetS32("gColViewerColorInteractableR", 192);
colorG = CVar_GetS32("gColViewerColorInteractableG", 0);
colorB = CVar_GetS32("gColViewerColorInteractableB", 192);
} else if (func_80041E80(&gGlobalCtx->colCtx, poly, bgId) == 0x0C) {
color = voidColor;
colorR = CVar_GetS32("gColViewerColorVoidR", 255);
colorG = CVar_GetS32("gColViewerColorVoidG", 0);
colorB = CVar_GetS32("gColViewerColorVoidB", 0);
} else if (SurfaceType_GetSceneExitIndex(&gGlobalCtx->colCtx, poly, bgId) ||
func_80041E80(&gGlobalCtx->colCtx, poly, bgId) == 0x05) {
color = entranceColor;
colorR = CVar_GetS32("gColViewerColorEntranceR", 0);
colorG = CVar_GetS32("gColViewerColorEntranceG", 255);
colorB = CVar_GetS32("gColViewerColorEntranceB", 0);
} else if (func_80041D4C(&gGlobalCtx->colCtx, poly, bgId) != 0 ||
SurfaceType_IsWallDamage(&gGlobalCtx->colCtx, poly, bgId)) {
color = specialSurfaceColor;
colorR = CVar_GetS32("gColViewerColorSpecialSurfaceR", 192);
colorG = CVar_GetS32("gColViewerColorSpecialSurfaceG", 255);
colorB = CVar_GetS32("gColViewerColorSpecialSurfaceB", 192);
} else if (SurfaceType_GetSlope(&gGlobalCtx->colCtx, poly, bgId) == 0x01) {
color = slopeColor;
colorR = CVar_GetS32("gColViewerColorSlopeR", 255);
colorG = CVar_GetS32("gColViewerColorSlopeG", 255);
colorB = CVar_GetS32("gColViewerColorSlopeB", 128);
} else {
color = sceneColor;
colorR = CVar_GetS32("gColViewerColorNormalR", 255);
colorG = CVar_GetS32("gColViewerColorNormalG", 255);
colorB = CVar_GetS32("gColViewerColorNormalB", 255);
}
if (lastColor != color) {
if (colorR != lastColorR || colorG != lastColorG || colorB != lastColorB) {
// Color changed, flush previous poly
if (previousPoly) {
dl.push_back(gsSPVertex((uintptr_t)&vtxDl.at(vtxDl.size() - 3), 3, 0));
dl.push_back(gsSP1Triangle(0, 1, 2, 0));
previousPoly = false;
}
dl.push_back(gsDPSetPrimColor(0, 0, (color >> 24) & 0xFF, (color >> 16) & 0xFF, (color >> 8) & 0xFF,
(color >> 0) & 0xFF));
dl.push_back(gsDPSetPrimColor(0, 0, colorR, colorG, colorB, colorA));
}
lastColor = color;
lastColorR = colorR;
lastColorG = colorG;
lastColorB = colorB;
Vec3s* va = &col->vtxList[COLPOLY_VTX_INDEX(poly->flags_vIA)];
Vec3s* vb = &col->vtxList[COLPOLY_VTX_INDEX(poly->flags_vIB)];
@ -450,7 +435,9 @@ void DrawDynapoly(std::vector<Gfx>& dl, CollisionHeader* col, int32_t bgId) {
// Draws the scene
void DrawSceneCollision() {
if (showSceneColSetting == ColRenderSetting::Disabled) {
ColRenderSetting showSceneColSetting = (ColRenderSetting)CVar_GetS32("gColViewerScene", 0);
if (showSceneColSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) {
return;
}
@ -463,7 +450,8 @@ void DrawSceneCollision() {
// Draws all Bg Actors
void DrawBgActorCollision() {
if (showBgActorSetting == ColRenderSetting::Disabled) {
ColRenderSetting showBgActorSetting = (ColRenderSetting)CVar_GetS32("gColViewerBgActors", 0);
if (showBgActorSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) {
return;
}
@ -489,7 +477,6 @@ void DrawBgActorCollision() {
dl.push_back(gsSPPopMatrix(G_MTX_MODELVIEW));
}
}
}
// Draws a quad
@ -588,7 +575,8 @@ void DrawColCheckList(std::vector<Gfx>& dl, Collider** objects, int32_t count) {
// Draws all Col Check objects
void DrawColCheckCollision() {
if (showColCheckSetting == ColRenderSetting::Disabled) {
ColRenderSetting showColCheckSetting = (ColRenderSetting)CVar_GetS32("gColViewerColCheck", 0);
if (showColCheckSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) {
return;
}
@ -598,16 +586,15 @@ void DrawColCheckCollision() {
CollisionCheckContext& col = gGlobalCtx->colChkCtx;
dl.push_back(gsDPSetPrimColor(0, 0, (ocColor >> 24) & 0xFF, (ocColor >> 16) & 0xFF, (ocColor >> 8) & 0xFF,
(ocColor >> 0) & 0xFF));
dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorOCR", 255), CVar_GetS32("gColViewerColorOCG", 255),
CVar_GetS32("gColViewerColorOCB", 255), 255));
DrawColCheckList(dl, col.colOC, col.colOCCount);
dl.push_back(gsDPSetPrimColor(0, 0, (acColor >> 24) & 0xFF, (acColor >> 16) & 0xFF, (acColor >> 8) & 0xFF,
(acColor >> 0) & 0xFF));
dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorACR", 0), CVar_GetS32("gColViewerColorACG", 0),
CVar_GetS32("gColViewerColorACB", 255), 255));
DrawColCheckList(dl, col.colAC, col.colACCount);
dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorATR", 255), CVar_GetS32("gColViewerColorATG", 0),
CVar_GetS32("gColViewerColorATB", 0), 255));
dl.push_back(gsDPSetPrimColor(0, 0, (atColor >> 24) & 0xFF, (atColor >> 16) & 0xFF, (atColor >> 8) & 0xFF,
(atColor >> 0) & 0xFF));
DrawColCheckList(dl, col.colAT, col.colATCount);
}
@ -641,15 +628,18 @@ extern "C" f32 zdWaterBoxMinY;
// Draws all waterboxes
void DrawWaterboxList() {
if (showWaterboxSetting == ColRenderSetting::Disabled) {
ColRenderSetting showWaterboxSetting = (ColRenderSetting)CVar_GetS32("gColViewerWaterbox", 0);
if (showWaterboxSetting == ColRenderSetting::Disabled || CVar_GetS32("gColViewerEnabled", 0) == 0) {
return;
}
std::vector<Gfx>& dl = (showWaterboxSetting == ColRenderSetting::Transparent) ? xluDl : opaDl;
InitGfx(dl, showWaterboxSetting);
dl.push_back(gsSPMatrix(&gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH));
dl.push_back(gsDPSetPrimColor(0, 0, (waterboxColor >> 24) & 0xFF, (waterboxColor >> 16) & 0xFF,
(waterboxColor >> 8) & 0xFF, (waterboxColor >> 0) & 0xFF));
dl.push_back(gsDPSetPrimColor(0, 0, CVar_GetS32("gColViewerColorWaterboxR", 0),
CVar_GetS32("gColViewerColorWaterboxG", 0),
CVar_GetS32("gColViewerColorWaterboxB", 255), 255));
CollisionHeader* col = gGlobalCtx->colCtx.colHeader;
for (int32_t waterboxIndex = 0; waterboxIndex < col->numWaterBoxes; waterboxIndex++) {
@ -664,8 +654,7 @@ void DrawWaterboxList() {
}
// Resets a vector for the next frame and returns the capacity
template<typename T>
size_t ResetVector(T& vec) {
template <typename T> size_t ResetVector(T& vec) {
size_t oldSize = vec.size();
vec.clear();
// Reserve slightly more space than last frame to account for variance (such as different amounts of bg actors)

View file

@ -7,6 +7,7 @@
#include <bit>
#include <map>
#include <string>
#include <Cvar.h>
extern "C" {
#include <z64.h>
@ -1316,6 +1317,9 @@ void DrawPlayerTab() {
case ITEM_SWORD_BGS:
curSword = "Biggoron's Sword";
break;
case ITEM_FISHING_POLE:
curSword = "Fishing Pole";
break;
case ITEM_NONE:
curSword = "None";
break;
@ -1463,6 +1467,11 @@ void DrawPlayerTab() {
Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_BGS);
}
if (ImGui::Selectable("Fishing Pole")) {
player->currentSwordItem = ITEM_FISHING_POLE;
gSaveContext.equips.buttonItems[0] = ITEM_FISHING_POLE;
Inventory_ChangeEquipment(EQUIP_SWORD, PLAYER_SWORD_MASTER);
}
ImGui::EndCombo();
}
@ -1536,6 +1545,7 @@ void DrawPlayerTab() {
void DrawSaveEditor(bool& open) {
if (!open) {
CVar_SetS32("gSaveEditorEnabled", 0);
return;
}

View file

@ -1,12 +1,14 @@
#include "debugger.h"
#include "debugSaveEditor.h"
#include "colViewer.h"
#include "actorViewer.h"
extern "C" {
void Debug_Init(void) {
InitSaveEditor();
InitColViewer();
InitActorViewer();
}
void Debug_Draw(void) {

View file

@ -264,6 +264,9 @@ typedef struct SaveStateInfo {
uint8_t sKankyoIsSpawned_copy;
int16_t sTrailingFairies_copy;
// z_en_heishi1
uint32_t sHeishi1PlayerIsCaughtCopy;
//Misc static data
// z_map_exp
@ -616,6 +619,8 @@ void SaveState::SaveOverlayStaticData(void) {
info->D_80B5A4BC_copy = D_80B5A4BC;
info->sKankyoIsSpawned_copy = sKankyoIsSpawned;
info->sTrailingFairies_copy = sTrailingFairies;
info->sHeishi1PlayerIsCaughtCopy = sHeishi1PlayerIsCaught;
}
@ -686,6 +691,8 @@ void SaveState::LoadOverlayStaticData(void) {
D_80B5A4BC = info->D_80B5A4BC_copy;
sKankyoIsSpawned = info->sKankyoIsSpawned_copy;
sTrailingFairies = info->sTrailingFairies_copy;
sHeishi1PlayerIsCaught = info->sHeishi1PlayerIsCaughtCopy;
}
void SaveState::SaveMiscCodeData(void) {

View file

@ -200,6 +200,9 @@ extern "C" s16 sPlayerInitialPosX;
extern "C" s16 sPlayerInitialPosZ;
extern "C" s16 sPlayerInitialDirection;
// z_en_heishi1
extern "C" s32 sHeishi1PlayerIsCaught;
// code_800EC960
// Related to ocarina
extern "C" u8 sOcarinaInpEnabled;

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013-2022 Niels Lohmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

22091
soh/soh/Lib/nlohmann/json.hpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
#include "OTRGlobals.h"
#include "OTRAudio.h"
#include <iostream>
#include <filesystem>
#include <locale>
#include <codecvt>
#include "GlobalCtx2.h"
@ -36,14 +37,17 @@
#include <Utils/StringHelper.h>
#include <SDL2/SDL_scancode.h>
#include <Audio.h>
OTRGlobals* OTRGlobals::Instance;
SaveManager* SaveManager::Instance;
OTRGlobals::OTRGlobals() {
context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian");
gSaveStateMgr = std::make_shared<SaveStateMgr>();
context->GetWindow()->Init();
CheckSaveFile(SRAM_SIZE);
}
OTRGlobals::~OTRGlobals() {
@ -57,10 +61,19 @@ extern "C" void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples);
extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
extern "C" int AudioPlayer_Buffered(void);
extern "C" int AudioPlayer_GetDesiredBuffered(void);
extern "C" void ResourceMgr_CacheDirectory(const char* resName);
extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path);
// C->C++ Bridge
extern "C" void OTRAudio_Init()
{
// Precache all our samples, sequences, etc...
ResourceMgr_CacheDirectory("audio");
}
extern "C" void InitOTR() {
OTRGlobals::Instance = new OTRGlobals();
SaveManager::Instance = new SaveManager();
auto t = OTRGlobals::Instance->context->GetResourceManager()->LoadFile("version");
if (!t->bHasLoadError)
@ -72,6 +85,7 @@ extern "C" void InitOTR() {
clearMtx = (uintptr_t)&gMtxClear;
OTRMessage_Init();
OTRAudio_Init();
DebugConsole_Init();
Debug_Init();
}
@ -189,11 +203,16 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
//AudioMgr_ThreadEntry(&gAudioMgr);
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
#define SAMPLES_HIGH 560
#define SAMPLES_LOW 528
//#define SAMPLES_HIGH 560
//#define SAMPLES_LOW 528
// PAL values
//#define SAMPLES_HIGH 656
//#define SAMPLES_LOW 624
// 44KHZ values
#define SAMPLES_HIGH 752
#define SAMPLES_LOW 720
#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1 )
#define NUM_AUDIO_CHANNELS 2
int samples_left = AudioPlayer_Buffered();
@ -312,6 +331,22 @@ extern "C" void ResourceMgr_InvalidateCache() {
OTRGlobals::Instance->context->GetResourceManager()->InvalidateResourceCache();
}
// OTRTODO: There is probably a more elegant way to go about this...
extern "C" char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize) {
auto lst = OTRGlobals::Instance->context->GetResourceManager()->ListFiles(searchMask);
char** result = (char**)malloc(lst->size() * sizeof(char*));
for (int i = 0; i < lst->size(); i++) {
char* str = (char*)malloc(lst.get()[0][i].size() + 1);
memcpy(str, lst.get()[0][i].data(), lst.get()[0][i].size());
str[lst.get()[0][i].size()] = '\0';
result[i] = str;
}
*resultSize = lst->size();
return result;
}
extern "C" void ResourceMgr_LoadFile(const char* resName) {
OTRGlobals::Instance->context->GetResourceManager()->LoadResource(resName);
@ -530,12 +565,249 @@ extern "C" CollisionHeader* ResourceMgr_LoadColByName(const char* path)
return (CollisionHeader*)colHeader;
}
extern "C" Vtx * ResourceMgr_LoadVtxByName(const char* path)
extern "C" Vtx* ResourceMgr_LoadVtxByName(const char* path)
{
auto res = std::static_pointer_cast<Ship::Array>(OTRGlobals::Instance->context->GetResourceManager()->LoadResource(path));
return (Vtx*)res->vertices.data();
}
extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path)
{
auto file = std::static_pointer_cast<Ship::AudioSequence>(OTRGlobals::Instance->context->GetResourceManager()
->LoadResource(path));
SequenceData seqData;
seqData.seqNumber = file->seqNumber;
seqData.medium = file->medium;
seqData.cachePolicy = file->cachePolicy;
seqData.numFonts = file->fonts.size();
for (int i = 0; i < seqData.numFonts; i++)
seqData.fonts[i] = file->fonts[i];
seqData.seqData = file->seqData.data();
seqData.seqDataSize = file->seqData.size();
return seqData;
}
std::map<std::string, SoundFontSample*> cachedCustomSFs;
extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(const char* path)
{
if (std::string(path) == "")
return nullptr;
if (cachedCustomSFs.find(path) != cachedCustomSFs.end())
return cachedCustomSFs[path];
// Check if our file is actually a wav...
auto sampleRaw = OTRGlobals::Instance->context->GetResourceManager()->LoadFile(path);
uint32_t* strem = (uint32_t*)sampleRaw->buffer.get();
uint8_t* strem2 = (uint8_t*)strem;
if (strem2[0] == 'R' && strem2[1] == 'I' && strem2[2] == 'F' && strem2[3] == 'F')
{
SoundFontSample* sampleC = (SoundFontSample*)malloc(sizeof(SoundFontSample));
*strem++; // RIFF
*strem++; // size
*strem++; // WAVE
*strem++; // fmt
int fmtChunkSize = *strem++;
*strem++; // wFormatTag + wChannels
int32_t sampleRate = *strem++; // dwSamplesPerSec
// OTRTODO: Make sure wav format is what the audio driver wants!
strem = (uint32_t*)&strem2[0x0C + fmtChunkSize + 8 + 4];
sampleC->size = *strem++;
sampleC->sampleAddr = (uint8_t*)strem;
sampleC->codec = CODEC_S16;
// OTRTODO: Grab loop data from wav
sampleC->loop = (AdpcmLoop*)malloc(sizeof(AdpcmLoop));
sampleC->loop->start = 0;
sampleC->loop->end = sampleC->size / 2; // OTRTODO: This calculation is probably incorrect... Sometimes it goes past the sample, sometimes it stops too early...
sampleC->loop->count = 0;
sampleC->sampleRateMagicValue = 'RIFF';
sampleC->sampleRate = sampleRate;
cachedCustomSFs[path] = sampleC;
return sampleC;
}
auto sample = std::static_pointer_cast<Ship::AudioSample>(
OTRGlobals::Instance->context->GetResourceManager()->LoadResource(path));
if (sample == nullptr)
return NULL;
if (sample->cachedGameAsset != nullptr)
{
SoundFontSample* sampleC = (SoundFontSample*)sample->cachedGameAsset;
return (SoundFontSample*)sample->cachedGameAsset;
}
else
{
SoundFontSample* sampleC = (SoundFontSample*)malloc(sizeof(SoundFontSample));
sampleC->sampleAddr = sample->data.data();
sampleC->size = sample->data.size();
sampleC->codec = sample->codec;
sampleC->medium = sample->medium;
sampleC->unk_bit26 = sample->unk_bit26;
sampleC->unk_bit25 = sample->unk_bit25;
sampleC->book = (AdpcmBook*)malloc(sizeof(AdpcmBook) + (sample->book.books.size() * sizeof(int16_t)));
sampleC->book->npredictors = sample->book.npredictors;
sampleC->book->order = sample->book.order;
for (int i = 0; i < sample->book.books.size(); i++)
sampleC->book->book[i] = sample->book.books[i];
sampleC->loop = (AdpcmLoop*)malloc(sizeof(AdpcmLoop));
sampleC->loop->start = sample->loop.start;
sampleC->loop->end = sample->loop.end;
sampleC->loop->count = sample->loop.count;
for (int i = 0; i < 16; i++)
sampleC->loop->state[i] = 0;
for (int i = 0; i < sample->loop.states.size(); i++)
sampleC->loop->state[i] = sample->loop.states[i];
sample->cachedGameAsset = sampleC;
return sampleC;
}
}
extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) {
auto soundFont =
std::static_pointer_cast<Ship::AudioSoundFont>(OTRGlobals::Instance->context->GetResourceManager()->LoadResource(path));
if (soundFont == nullptr)
return NULL;
if (soundFont->cachedGameAsset != nullptr)
{
return (SoundFont*)soundFont->cachedGameAsset;
}
else
{
SoundFont* soundFontC = (SoundFont*)malloc(sizeof(SoundFont));
soundFontC->fntIndex = soundFont->id;
soundFontC->numDrums = soundFont->drums.size();
soundFontC->numInstruments = soundFont->instruments.size();
soundFontC->numSfx = soundFont->soundEffects.size();
soundFontC->sampleBankId1 = soundFont->data1 >> 8;
soundFontC->sampleBankId2 = soundFont->data1 & 0xFF;
soundFontC->drums = (Drum**)malloc(sizeof(Drum*) * soundFont->drums.size());
for (int i = 0; i < soundFont->drums.size(); i++)
{
Drum* drum = (Drum*)malloc(sizeof(Drum));
drum->releaseRate = soundFont->drums[i].releaseRate;
drum->pan = soundFont->drums[i].pan;
drum->loaded = 0;
if (soundFont->drums[i].env.size() == 0)
drum->envelope = NULL;
else
{
drum->envelope = (AdsrEnvelope*)malloc(sizeof(AdsrEnvelope) * soundFont->drums[i].env.size());
for (int k = 0; k < soundFont->drums[i].env.size(); k++)
{
drum->envelope[k].delay = BOMSWAP16(soundFont->drums[i].env[k]->delay);
drum->envelope[k].arg = BOMSWAP16(soundFont->drums[i].env[k]->arg);
}
}
drum->sound.sample = ResourceMgr_LoadAudioSample(soundFont->drums[i].sampleFileName.c_str());
drum->sound.tuning = soundFont->drums[i].tuning;
soundFontC->drums[i] = drum;
}
soundFontC->instruments = (Instrument**)malloc(sizeof(Instrument*) * soundFont->instruments.size());
for (int i = 0; i < soundFont->instruments.size(); i++) {
if (soundFont->instruments[i].isValidEntry)
{
Instrument* inst = (Instrument*)malloc(sizeof(Instrument));
inst->loaded = 0;
inst->releaseRate = soundFont->instruments[i].releaseRate;
inst->normalRangeLo = soundFont->instruments[i].normalRangeLo;
inst->normalRangeHi = soundFont->instruments[i].normalRangeHi;
if (soundFont->instruments[i].env.size() == 0)
inst->envelope = NULL;
else
{
inst->envelope = (AdsrEnvelope*)malloc(sizeof(AdsrEnvelope) * soundFont->instruments[i].env.size());
for (int k = 0; k < soundFont->instruments[i].env.size(); k++)
{
inst->envelope[k].delay = BOMSWAP16(soundFont->instruments[i].env[k]->delay);
inst->envelope[k].arg = BOMSWAP16(soundFont->instruments[i].env[k]->arg);
}
}
if (soundFont->instruments[i].lowNotesSound != nullptr)
{
inst->lowNotesSound.sample =
ResourceMgr_LoadAudioSample(soundFont->instruments[i].lowNotesSound->sampleFileName.c_str());
inst->lowNotesSound.tuning = soundFont->instruments[i].lowNotesSound->tuning;
} else {
inst->lowNotesSound.sample = NULL;
inst->lowNotesSound.tuning = 0;
}
if (soundFont->instruments[i].normalNotesSound != nullptr) {
inst->normalNotesSound.sample =
ResourceMgr_LoadAudioSample(soundFont->instruments[i].normalNotesSound->sampleFileName.c_str());
inst->normalNotesSound.tuning = soundFont->instruments[i].normalNotesSound->tuning;
} else {
inst->normalNotesSound.sample = NULL;
inst->normalNotesSound.tuning = 0;
}
if (soundFont->instruments[i].highNotesSound != nullptr) {
inst->highNotesSound.sample =
ResourceMgr_LoadAudioSample(soundFont->instruments[i].highNotesSound->sampleFileName.c_str());
inst->highNotesSound.tuning = soundFont->instruments[i].highNotesSound->tuning;
} else {
inst->highNotesSound.sample = NULL;
inst->highNotesSound.tuning = 0;
}
soundFontC->instruments[i] = inst;
} else
{
soundFontC->instruments[i] = nullptr;
}
}
soundFontC->soundEffects = (SoundFontSound*)malloc(sizeof(SoundFontSound) * soundFont->soundEffects.size());
for (int i = 0; i < soundFont->soundEffects.size(); i++)
{
soundFontC->soundEffects[i].sample = ResourceMgr_LoadAudioSample(soundFont->soundEffects[i]->sampleFileName.c_str());
soundFontC->soundEffects[i].tuning = soundFont->soundEffects[i]->tuning;
}
soundFont->cachedGameAsset = soundFontC;
return soundFontC;
}
}
extern "C" int ResourceMgr_OTRSigCheck(char* imgData)
{
uintptr_t i = (uintptr_t)(imgData);
@ -570,6 +842,7 @@ extern "C" AnimationHeaderCommon* ResourceMgr_LoadAnimByName(const char* path) {
for (int i = 0; i < res->rotationValues.size(); i++)
animNormal->frameData[i] = res->rotationValues[i];
animNormal->jointIndices = (JointIndex*)malloc(res->rotationIndices.size() * sizeof(Vec3s));
for (int i = 0; i < res->rotationIndices.size(); i++) {
@ -814,6 +1087,71 @@ extern "C" s32* ResourceMgr_LoadCSByName(const char* path)
return (s32*)res->commands.data();
}
std::filesystem::path GetSaveFile(Ship::ConfigFile& Conf) {
std::string fileName = Conf.get("SAVE").get("Save Filename");
if (fileName.empty()) {
Conf["SAVE"]["Save Filename"] = "oot_save.sav";
Conf.Save();
}
std::filesystem::path saveFile = std::filesystem::absolute(fileName);
if (!std::filesystem::exists(saveFile.parent_path())) {
std::filesystem::create_directories(saveFile.parent_path());
}
return saveFile;
}
std::filesystem::path GetSaveFile() {
std::shared_ptr<Ship::ConfigFile> pConf = OTRGlobals::Instance->context->GetConfig();
Ship::ConfigFile& Conf = *pConf.get();
return GetSaveFile(Conf);
}
void OTRGlobals::CheckSaveFile(size_t sramSize) {
std::shared_ptr<Ship::ConfigFile> pConf = context->GetConfig();
Ship::ConfigFile& Conf = *pConf.get();
std::filesystem::path savePath = GetSaveFile(Conf);
std::fstream saveFile(savePath, std::fstream::in | std::fstream::out | std::fstream::binary);
if (saveFile.fail()) {
saveFile.open(savePath, std::fstream::in | std::fstream::out | std::fstream::binary | std::fstream::app);
for (int i = 0; i < sramSize; ++i) {
saveFile.write("\0", 1);
}
}
saveFile.close();
}
extern "C" void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size) {
OTRGlobals::Instance->context->ReadSaveFile(GetSaveFile(), addr, dramAddr, size);
}
extern "C" void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size) {
OTRGlobals::Instance->context->WriteSaveFile(GetSaveFile(), addr, dramAddr, size);
}
/* Remember to free after use of value */
extern "C" char* Config_getValue(char* category, char* key) {
std::shared_ptr<Ship::ConfigFile> pConf = OTRGlobals::Instance->context->GetConfig();
Ship::ConfigFile& Conf = *pConf.get();
std::string data = Conf.get(std::string(category)).get(std::string(key));
char* retval = (char*)malloc(data.length()+1);
strcpy(retval, data.c_str());
return retval;
}
extern "C" bool Config_setValue(char* category, char* key, char* value) {
std::shared_ptr<Ship::ConfigFile> pConf = OTRGlobals::Instance->context->GetConfig();
Ship::ConfigFile& Conf = *pConf.get();
Conf[std::string(category)][std::string(key)] = std::string(value);
return Conf.Save();
}
std::wstring StringToU16(const std::string& s) {
std::vector<unsigned long> result;
size_t i = 0;

View file

@ -4,6 +4,7 @@
#pragma once
#include "GlobalCtx2.h"
#include "SaveManager.h"
#ifdef __cplusplus
#include "Enhancements/savestates.h"
@ -19,13 +20,13 @@ public:
~OTRGlobals();
private:
void CheckSaveFile(size_t sramSize);
};
#endif
#ifndef __cplusplus
void InitOTR();
void Graph_ProcessFrame(void (*run_one_game_iter)(void));
void OTRAudio_Init();
void InitAudio();
void Graph_StartFrame();
void Graph_ProcessGfxCommands(Gfx* commands);
void OTRLogString(const char* src);
@ -35,6 +36,7 @@ uint16_t OTRGetPixelDepth(float x, float y);
int32_t OTRGetLastScancode();
uint32_t ResourceMgr_GetGameVersion();
void ResourceMgr_CacheDirectory(const char* resName);
char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize);
void ResourceMgr_LoadFile(const char* resName);
char* ResourceMgr_LoadFileFromDisk(const char* filePath);
char* ResourceMgr_LoadTexByName(const char* texPath);
@ -45,8 +47,17 @@ Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc);
Gfx* ResourceMgr_LoadGfxByName(const char* path);
Gfx* ResourceMgr_PatchGfxByName(const char* path, int size);
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc);
Vtx* ResourceMgr_LoadVtxByName(const char* path);
SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path);
SequenceData ResourceMgr_LoadSeqByName(const char* path);
SoundFontSample* ResourceMgr_LoadAudioSample(const char* path);
CollisionHeader* ResourceMgr_LoadColByName(const char* path);
void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size);
void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size);
char* Config_getValue(char* category, char* key);
bool Config_setValue(char* category, char* key, char* value);
uint64_t GetPerfCounter();
struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path);
int ResourceMgr_OTRSigCheck(char* imgData);

1217
soh/soh/SaveManager.cpp Normal file

File diff suppressed because it is too large Load diff

149
soh/soh/SaveManager.h Normal file
View file

@ -0,0 +1,149 @@
#pragma once
#include <ultra64/gbi.h>
typedef struct {
u8 valid;
u16 deaths;
char playerName[8];
u16 healthCapacity;
u32 questItems;
s8 defense;
u16 health;
u8 n64ddFlag;
} SaveFileMetaInfo;
#ifdef __cplusplus
#include <map>
#include <string>
#include <tuple>
#include <functional>
#include <vector>
#include <filesystem>
#include "Lib/nlohmann/json.hpp"
class SaveManager {
public:
static SaveManager* Instance;
using InitFunc = void(*)(bool isDebug);
using LoadFunc = void(*)();
using SaveFunc = void(*)();
using PostFunc = void(*)(int version);
SaveManager();
void Init();
void InitFile(bool isDebug);
void SaveFile(int fileNum);
void SaveGlobal();
void LoadFile(int fileNum);
// Adds a function that is called when we are intializing a save, including when we are loading a save.
void AddInitFunction(InitFunc func);
// Adds a function to handling loading a section
void AddLoadFunction(const std::string& name, int version, LoadFunc func);
// Adds a function that is called when saving. This should only be called once for each function, the version is filled in automatically.
void AddSaveFunction(const std::string& name, int version, SaveFunc func);
// Adds a function to be called after loading is complete. This is to handle any cleanup required from loading old versions.
void AddPostFunction(const std::string& name, PostFunc func);
void CopyZeldaFile(int from, int to);
void DeleteZeldaFile(int fileNum);
// Use a name of "" to save to an array. You must be in a SaveArray callback.
template<typename T>
void SaveData(const std::string& name, const T& data) {
if (name == "") {
assert((*currentJsonContext).is_array());
(*currentJsonContext).push_back(data);
} else {
(*currentJsonContext)[name.c_str()] = data;
}
}
// In the SaveArrayFunc func, the name must be "" to save to the array.
using SaveArrayFunc = std::function<void(size_t)>;
void SaveArray(const std::string& name, const size_t size, SaveArrayFunc func);
using SaveStructFunc = std::function<void()>;
void SaveStruct(const std::string& name, SaveStructFunc func);
// Use a name of "" to load from an array. You must be in a LoadArray callback.
template<typename T> void LoadData(const std::string& name, T& data, const T& defaultValue = T{}) {
if (name == "") {
if (currentJsonArrayContext == currentJsonContext->end()) {
// This array member is past the data in the json file. Therefore, default construct it
data = defaultValue;
} else {
currentJsonArrayContext.value().get_to(data);
}
} else if (!currentJsonContext->contains(name.c_str())) {
data = defaultValue;
} else {
(*currentJsonContext)[name.c_str()].get_to(data);
}
}
// In the LoadArrayFunc func, the name must be "" to load from the array.
using LoadArrayFunc = std::function<void(size_t)>;
void LoadArray(const std::string& name, const size_t size, LoadArrayFunc func);
using LoadStructFunc = std::function<void()>;
void LoadStruct(const std::string& name, LoadStructFunc func);
static const int MaxFiles = 3;
std::array<SaveFileMetaInfo, MaxFiles> fileMetaInfo;
private:
std::filesystem::path GetFileName(int fileNum);
void ConvertFromUnversioned();
void CreateDefaultGlobal();
void InitMeta(int slotNum);
static void InitFileImpl(bool isDebug);
static void InitFileNormal();
static void InitFileDebug();
static void LoadBaseVersion1();
static void SaveBase();
std::vector<InitFunc> initFuncs;
using SectionLoadHandler = std::map<int, LoadFunc>;
std::map<std::string, SectionLoadHandler> sectionLoadHandlers;
using SectionSaveHandler = std::pair<int, SaveFunc>;
std::map<std::string, SectionSaveHandler> sectionSaveHandlers;
std::map<std::string, PostFunc> postHandlers;
nlohmann::json* currentJsonContext = nullptr;
nlohmann::json::iterator currentJsonArrayContext;
};
#else
// TODO feature parity to the C++ interface. We need Save_AddInitFunction and Save_AddPostFunction at least
typedef void (*Save_LoadFunc)(void);
typedef void (*Save_SaveFunc)(void);
void Save_Init(void);
void Save_InitFile(int isDebug);
void Save_SaveFile(void);
void Save_SaveGlobal(void);
void Save_LoadGlobal(void);
void Save_AddLoadFunction(char* name, int version, Save_LoadFunc func);
void Save_AddSaveFunction(char* name, int version, Save_SaveFunc func);
SaveFileMetaInfo* Save_GetSaveMetaInfo(int fileNum);
void Save_CopyFile(int from, int to);
void Save_DeleteFile(int fileNum);
#endif

View file

@ -445,7 +445,9 @@ void osViExtendVStart(u32 arg0)
}
#if 0
AudioTable gSoundFontTable = { 0 };
#else
AudioTable gSoundFontTable = { 0x0026,
0x0000,
0x00000000,
@ -795,7 +797,11 @@ AudioTable gSoundFontTable = { 0x0026,
},
}
};
#endif
#if 0
AudioTable gSequenceTable = { 0 };
#else
AudioTable gSequenceTable = { 0x006E,
0x0000,
0x00000000,
@ -1585,7 +1591,7 @@ AudioTable gSequenceTable = { 0x006E,
0x0000,
},
{
0x00000028,
0x00000028,
0x00000000,
0x02,
0x02,
@ -1791,9 +1797,12 @@ AudioTable gSequenceTable = { 0x006E,
0x0000,
0x0000,
},
}
};
} };
#endif
#if 0
AudioTable gSampleBankTable = { 0 };
#else
AudioTable gSampleBankTable = { 0x0007,
0x0000,
0x00000000,
@ -1864,7 +1873,11 @@ AudioTable gSampleBankTable = { 0x0007,
},
}
};
#endif
#if 0
u8 gSequenceFontTable[1] = { 0 };
#else
u8 gSequenceFontTable[0x1C0] = {
0xDC,
0x00,
@ -2100,3 +2113,4 @@ u8 gSequenceFontTable[0x1C0] = {
0x03, 0x01, 0x1F, 0x01, 0x20, 0x01, 0x20, 0x01, 0x09, 0x01, 0x21, 0x01, 0x22, 0x01, 0x21, 0x01, 0x09, 0x01, 0x20,
0x01, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#endif

View file

@ -544,16 +544,10 @@ u8 gDefaultShortNoteGateTimeTable[] = {
};
AdsrEnvelope gDefaultEnvelope[] = {
// OTRTODO: Byteswapped manually for quick audio support.
{ 0x0100, 0x007D },
{ 0xE803, 0x007D },
{ 0xFFFF, 0x0000 },
{ 0x0000, 0x0000 },
/* { 1, 32000 },
{ 1000, 32000 },
{ -1, 0 },
{ 0, 0 },
*/
};
NoteSubEu gZeroNoteSub = { 0 };

View file

@ -10,6 +10,8 @@ void AudioHeap_DiscardSampleCaches(void);
void AudioHeap_DiscardSampleBank(s32 sampleBankId);
void AudioHeap_DiscardSampleBanks(void);
extern bool gUseLegacySD;
f32 func_800DDE20(f32 arg0) {
return 256.0f * gAudioContext.audioBufferParameters.unkUpdatesPerFrameScaled / arg0;
}
@ -1201,7 +1203,11 @@ void AudioHeap_DiscardSampleCacheEntry(SampleCacheEntry* entry) {
}
}
void AudioHeap_UnapplySampleCache(SampleCacheEntry* entry, SoundFontSample* sample) {
void AudioHeap_UnapplySampleCache(SampleCacheEntry* entry, SoundFontSample* sample)
{
if (!gUseLegacySD)
return;
if (sample != NULL) {
if (sample->sampleAddr == entry->allocatedAddr) {
sample->sampleAddr = entry->sampleAddr;

View file

@ -10,7 +10,8 @@ const s16 D_8014A6C0[] = {
0x0030, // gTatumsPerBeat
};
const AudioContextInitSizes D_8014A6C4 = { 0x37F00, 0xE0E0, 0xBCE0 };
//const AudioContextInitSizes D_8014A6C4 = { 0x37F00, 0xE0E0, 0xBCE0 };
const AudioContextInitSizes D_8014A6C4 = { 0x37F000, 0xE0E00, 0xBCE00 }; // OTRTODO: This might be overkill...
ReverbSettings D_80133420[][3] = {
{
@ -67,22 +68,22 @@ ReverbSettings D_80133420[][3] = {
};
AudioSpec gAudioSpecs[18] = {
{ 32000, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x4000, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, D_80133420[1], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 23, 4, 0, 0, 2, D_80133420[4], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 23, 4, 0, 0, 2, D_80133420[5], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, D_80133420[6], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, D_80133420[7], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, D_80133420[9], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 28, 3, 0, 0, 2, D_80133420[10], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x2800, 0x2880, 0, 0, 0 },
{ 32000, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0x4800, 0, 0x4000, 0, 0, 0, 0 },
{ 32000, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0, 0, 0x4000, 0x4800, 0, 0, 0 },
{ 32000, 1, 22, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 22, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 16, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x4000, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[1], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[4], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[5], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[6], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[7], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[9], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 23, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 2, D_80133420[10], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x2800, 0x2880, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0x4800, 0, 0x4000, 0, 0, 0, 0 },
{ 44100, 1, 28, 3, 0, 0, 1, D_80133420[11], 0x300, 0x200, 0x7FFF, 0, 0, 0, 0x4000, 0x4800, 0, 0, 0 },
{ 44100, 1, 22, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 22, 4, 0, 0, 2, D_80133420[8], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 44100, 1, 16, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 22050, 1, 24, 4, 0, 0, 2, D_80133420[0], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3800, 0x2880, 0, 0, 0 },
{ 32000, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3600, 0x2600, 0, 0, 0 },
{ 44100, 1, 24, 4, 0, 0, 2, D_80133420[2], 0x300, 0x200, 0x7FFF, 0x7F0, 0xE00, 0, 0x3600, 0x2600, 0, 0, 0 },
};

View file

@ -4,6 +4,7 @@
#include "ultra64.h"
#include "global.h"
#include "soh/OTRGlobals.h"
#define MK_ASYNC_MSG(retData, tableType, id, status) (((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (status))
#define ASYNC_TBLTYPE(v) ((u8)(v >> 16))
@ -37,14 +38,14 @@ void AudioLoad_ProcessAsyncLoads(s32 resetStatus);
void AudioLoad_ProcessAsyncLoadUnkMedium(AudioAsyncLoad* asyncLoad, s32 resetStatus);
void AudioLoad_ProcessAsyncLoad(AudioAsyncLoad* asyncLoad, s32 resetStatus);
void AudioLoad_RelocateFontAndPreloadSamples(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo, s32 temporary);
void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, RelocInfo* relocInfo);
void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, RelocInfo* relocInfo, int fontId);
void AudioLoad_DiscardFont(s32 fontId);
u32 AudioLoad_TrySyncLoadSampleBank(u32 sampleBankId, u32* outMedium, s32 noLoad);
void* AudioLoad_SyncLoad(u32 tableType, u32 tableId, s32* didAllocate);
u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 tableId);
void* AudioLoad_SearchCaches(s32 tableType, s32 id);
AudioTable* AudioLoad_GetLoadTable(s32 tableType);
void AudioLoad_SyncDma(u32 devAddr, u8* addr, size_t size, s32 medium);
void AudioLoad_SyncDma(uintptr_t devAddr, u8* addr, size_t size, s32 medium);
void AudioLoad_SyncDmaUnkMedium(u32 devAddr, u8* addr, size_t size, s32 unkMediumParam);
s32 AudioLoad_Dma(OSIoMesg* mesg, u32 priority, s32 direction, u32 devAddr, void* ramAddr, size_t size,
OSMesgQueue* reqQueue, s32 medium, const char* dmaFuncType);
@ -74,6 +75,14 @@ void* sUnusedHandler = NULL;
s32 gAudioContextInitalized = false;
char* sequenceMap[256];
char* fontMap[256];
uintptr_t fontStart;
uint32_t fontOffsets[8192];
bool gUseLegacySD = false;
void AudioLoad_DecreaseSampleDmaTtls(void) {
u32 i;
@ -278,8 +287,11 @@ void AudioLoad_InitSampleDmaBuffers(s32 arg0) {
}
s32 AudioLoad_IsFontLoadComplete(s32 fontId) {
return true;
if (fontId == 0xFF) {
return true;
} else if (gAudioContext.fontLoadStatus[fontId] >= 2) {
return true;
} else if (gAudioContext.fontLoadStatus[AudioLoad_GetRealTableIndex(FONT_TABLE, fontId)] >= 2) {
@ -352,6 +364,9 @@ void AudioLoad_InitTable(AudioTable* table, uintptr_t romAddr, u16 unkMediumPara
for (i = 0; i < table->numEntries; i++) {
if ((table->entries[i].size != 0) && (table->entries[i].medium == MEDIUM_CART)) {
if (romAddr == fontStart)
fontOffsets[i] = table->entries[i].romAddr;
table->entries[i].romAddr += romAddr;
}
}
@ -360,7 +375,7 @@ void AudioLoad_InitTable(AudioTable* table, uintptr_t romAddr, u16 unkMediumPara
SoundFontData* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outDefaultFontId) {
char pad[0x8];
s32 index;
SoundFontData* font;
SoundFontData* font = NULL;
s32 numFonts;
s32 fontId;
s32 i;
@ -375,6 +390,7 @@ SoundFontData* AudioLoad_SyncLoadSeqFonts(s32 seqId, u32* outDefaultFontId) {
while (numFonts > 0) {
fontId = gAudioContext.sequenceFontTable[index++];
font = AudioLoad_SyncLoadFont(fontId);
numFonts--;
}
@ -400,7 +416,8 @@ void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1) {
s32 AudioLoad_SyncLoadSample(SoundFontSample* sample, s32 fontId) {
void* sampleAddr;
if (sample->unk_bit25 == 1) {
if (sample->unk_bit25 == 1)
{
if (sample->medium != MEDIUM_RAM) {
sampleAddr = AudioHeap_AllocSampleCache(sample->size, fontId, (void*)sample->sampleAddr, sample->medium,
CACHE_PERSISTENT);
@ -466,13 +483,26 @@ void AudioLoad_AsyncLoadFont(s32 fontId, s32 arg1, s32 retData, OSMesgQueue* ret
u8* AudioLoad_GetFontsForSequence(s32 seqId, u32* outNumFonts) {
s32 index;
index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
if (!gUseLegacySD)
{
if (seqId == 255)
return NULL;
*outNumFonts = gAudioContext.sequenceFontTable[index++];
if (*outNumFonts == 0) {
return NULL;
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqId]);
if (sDat.numFonts == 0)
return NULL;
return sDat.fonts;
} else {
index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
*outNumFonts = gAudioContext.sequenceFontTable[index++];
if (*outNumFonts == 0) {
return NULL;
}
return &gAudioContext.sequenceFontTable[index];
}
return &gAudioContext.sequenceFontTable[index];
}
void AudioLoad_DiscardSeqFonts(s32 seqId) {
@ -544,30 +574,52 @@ s32 AudioLoad_SyncInitSeqPlayerInternal(s32 playerIdx, s32 seqId, s32 arg2) {
s32 numFonts;
s32 fontId;
if (seqId >= gAudioContext.numSequences) {
if (gUseLegacySD && seqId >= gAudioContext.numSequences) {
return 0;
}
AudioSeq_SequencePlayerDisable(seqPlayer);
fontId = 0xFF;
index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
numFonts = gAudioContext.sequenceFontTable[index++];
while (numFonts > 0) {
fontId = gAudioContext.sequenceFontTable[index++];
AudioLoad_SyncLoadFont(fontId);
numFonts--;
if (gUseLegacySD) {
index = ((u16*)gAudioContext.sequenceFontTable)[seqId];
numFonts = gAudioContext.sequenceFontTable[index++];
while (numFonts > 0) {
fontId = gAudioContext.sequenceFontTable[index++];
AudioLoad_SyncLoadFont(fontId); // NOTE: If this is commented out, then enemies will play child link sounds...
numFonts--;
}
}
else
{
SequenceData seqData2 = ResourceMgr_LoadSeqByName(sequenceMap[seqId]);
for (int i = 0; i < seqData2.numFonts; i++)
{
fontId = seqData2.fonts[i];
AudioLoad_SyncLoadFont(fontId); // NOTE: If this is commented out, then enemies will play child link sounds...
numFonts--;
}
}
seqData = AudioLoad_SyncLoadSeq(seqId);
if (seqData == NULL) {
return 0;
}
AudioSeq_ResetSequencePlayer(seqPlayer);
seqPlayer->seqId = seqId;
seqPlayer->defaultFont = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId);
if (gUseLegacySD)
seqPlayer->defaultFont = AudioLoad_GetRealTableIndex(FONT_TABLE, fontId);
else
seqPlayer->defaultFont = fontId;
seqPlayer->seqData = seqData;
seqPlayer->enabled = 1;
seqPlayer->scriptState.pc = seqData;
@ -637,8 +689,18 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) {
if (gAudioContext.fontLoadStatus[realFontId] == 1) {
return NULL;
}
sampleBankId1 = gAudioContext.soundFonts[realFontId].sampleBankId1;
sampleBankId2 = gAudioContext.soundFonts[realFontId].sampleBankId2;
if (!gUseLegacySD) {
SoundFont* sf = ResourceMgr_LoadAudioSoundFont
(fontMap[fontId]);
sampleBankId1 = sf->sampleBankId1;
sampleBankId2 = sf->sampleBankId2;
} else {
sampleBankId1 = gAudioContext.soundFonts[realFontId].sampleBankId1;
sampleBankId2 = gAudioContext.soundFonts[realFontId].sampleBankId2;
}
relocInfo.sampleBankId1 = sampleBankId1;
relocInfo.sampleBankId2 = sampleBankId2;
@ -681,13 +743,38 @@ void* AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) {
if (ret != NULL) {
*didAllocate = false;
status = 2;
} else {
table = AudioLoad_GetLoadTable(tableType);
size = table->entries[realId].size;
size = ALIGN16(size);
medium = table->entries[id].medium;
cachePolicy = table->entries[id].cachePolicy;
romAddr = table->entries[realId].romAddr;
} else
{
char* seqData = 0;
SoundFont* fnt;
if (!gUseLegacySD && tableType == SEQUENCE_TABLE)
{
SequenceData sData = ResourceMgr_LoadSeqByName(sequenceMap[id]);
seqData = sData.seqData;
size = sData.seqDataSize;
medium = sData.medium;
cachePolicy = sData.cachePolicy;
romAddr = 0;
}
else if (!gUseLegacySD && tableType == FONT_TABLE)
{
fnt = ResourceMgr_LoadAudioSoundFont(fontMap[id]);
size = sizeof(SoundFont);
medium = 2;
cachePolicy = 0;
romAddr = 0;
}
else
{
table = AudioLoad_GetLoadTable(tableType);
size = table->entries[realId].size;
size = ALIGN16(size);
medium = table->entries[id].medium;
cachePolicy = table->entries[id].cachePolicy;
romAddr = table->entries[realId].romAddr;
}
switch (cachePolicy) {
case 0:
ret = AudioHeap_AllocPermanent(tableType, realId, size);
@ -720,7 +807,14 @@ void* AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) {
if (medium == MEDIUM_UNK) {
AudioLoad_SyncDmaUnkMedium(romAddr, ret, size, (s16)table->unkMediumParam);
} else {
AudioLoad_SyncDma(romAddr, ret, size, medium);
if (!gUseLegacySD && tableType == SEQUENCE_TABLE && seqData != NULL) {
AudioLoad_SyncDma(seqData, ret, size, medium);
} else if (!gUseLegacySD && tableType == FONT_TABLE) {
AudioLoad_SyncDma(fnt, ret, size, medium);
}
else {
AudioLoad_SyncDma(romAddr, ret, size, medium);
}
}
status = cachePolicy == 0 ? 5 : 2;
@ -743,9 +837,16 @@ void* AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) {
return ret;
}
u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 id) {
u32 AudioLoad_GetRealTableIndex(s32 tableType, u32 id)
{
if ((tableType == SEQUENCE_TABLE || tableType == FONT_TABLE) && !gUseLegacySD) {
return id;
}
AudioTable* table = AudioLoad_GetLoadTable(tableType);
// If the size is 0, then this entry actually redirects to another entry.
// The rom address is actually an index into the same table where the "real" data is.
if (table->entries[id].size == 0) {
id = table->entries[id].romAddr;
}
@ -796,29 +897,64 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo
Drum* drum;
SoundFontSound* sfx;
s32 i;
s32 numDrums = gAudioContext.soundFonts[fontId].numDrums;
s32 numInstruments = gAudioContext.soundFonts[fontId].numInstruments;
s32 numSfx = gAudioContext.soundFonts[fontId].numSfx;
SoundFont* sf = NULL;
s32 numDrums = 0;
s32 numInstruments = 0;
s32 numSfx = 0;
if (gUseLegacySD) {
numDrums = gAudioContext.soundFonts[fontId].numDrums;
numInstruments = gAudioContext.soundFonts[fontId].numInstruments;
numSfx = gAudioContext.soundFonts[fontId].numSfx;
} else {
sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
numDrums = sf->numDrums;
numInstruments = sf->numInstruments;
numSfx = sf->numSfx;
}
void** ptrs = (void**)mem;
#define BASE_OFFSET(x) (void*)((u32)(x) + (u32)(mem))
reloc2 = ptrs[0];
if (1) {}
if ((reloc2 != 0) && (numDrums != 0)) {
if ((reloc2 != 0 || !gUseLegacySD) && (numDrums != 0))
{
ptrs[0] = BASE_OFFSET(reloc2);
for (i = 0; i < numDrums; i++) {
reloc = ((Drum**)ptrs[0])[i];
for (i = 0; i < numDrums; i++)
{
if (gUseLegacySD)
reloc = ((Drum**)ptrs[0])[i];
if (reloc != 0) {
reloc = BASE_OFFSET(reloc);
if (reloc != 0 || !gUseLegacySD)
{
if (gUseLegacySD)
{
reloc = BASE_OFFSET(reloc);
((Drum**)ptrs[0])[i] = drum = reloc;
}
((Drum**)ptrs[0])[i] = drum = reloc;
if (!drum->loaded) {
AudioLoad_RelocateSample(&drum->sound, mem, relocInfo);
reloc = drum->envelope;
drum->envelope = BASE_OFFSET(reloc);
drum->loaded = 1;
if (!gUseLegacySD)
drum = sf->drums[i];
if (!drum->loaded)
{
if (!gUseLegacySD)
{
AudioLoad_RelocateSample(&sf->drums[i]->sound, mem, relocInfo, fontOffsets[fontId]);
//reloc = drum->envelope;
drum->loaded = 1;
}
else
{
AudioLoad_RelocateSample(&drum->sound, mem, relocInfo, fontOffsets[fontId]);
reloc = drum->envelope;
drum->envelope = BASE_OFFSET(reloc);
drum->loaded = 1;
}
}
}
}
@ -826,39 +962,56 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo
reloc2 = ptrs[1];
if (1) {}
if ((reloc2 != 0) && (numSfx != 0)) {
if ((reloc2 != 0 || !gUseLegacySD) && (numSfx != 0)) {
ptrs[1] = BASE_OFFSET(reloc2);
for (i = 0; i < numSfx; i++) {
reloc = (SoundFontSound*)ptrs[1] + i;
if (reloc != 0) {
sfx = reloc;
if (sfx->sample != NULL) {
AudioLoad_RelocateSample(sfx, mem, relocInfo);
if (reloc != 0 || !gUseLegacySD)
{
if (!gUseLegacySD) {
AudioLoad_RelocateSample(&sf->soundEffects[i].sample, mem, relocInfo, fontOffsets[fontId]);
} else {
sfx = reloc;
if (sfx->sample != NULL) {
AudioLoad_RelocateSample(sfx, mem, relocInfo, fontOffsets[fontId]);
}
}
}
}
}
if (numInstruments > 0x7E) {
numInstruments = 0x7E;
}
for (i = 2; i <= 2 + numInstruments - 1; i++) {
if (ptrs[i] != NULL) {
int startI = gUseLegacySD ? 2 : 0;
int startEC = gUseLegacySD ? 2 + numInstruments - 1 : numInstruments - 1;
//for (i = 2; i <= 2 + numInstruments - 1; i++) {
for (i = startI; i <= startEC; i++) {
if (!gUseLegacySD || ptrs[i] != NULL)
{
ptrs[i] = BASE_OFFSET(ptrs[i]);
inst = ptrs[i];
if (!inst->loaded) {
if (inst->normalRangeLo != 0) {
AudioLoad_RelocateSample(&inst->lowNotesSound, mem, relocInfo);
if (gUseLegacySD)
inst = ptrs[i];
else
inst = sf->instruments[i];
if (inst != NULL && !inst->loaded) {
if (inst->normalRangeLo != 0)
{
AudioLoad_RelocateSample(&inst->lowNotesSound, mem, relocInfo, fontOffsets[fontId]);
}
AudioLoad_RelocateSample(&inst->normalNotesSound, mem, relocInfo);
AudioLoad_RelocateSample(&inst->normalNotesSound, mem, relocInfo, fontOffsets[fontId]);
if (inst->normalRangeHi != 0x7F) {
AudioLoad_RelocateSample(&inst->highNotesSound, mem, relocInfo);
AudioLoad_RelocateSample(&inst->highNotesSound, mem, relocInfo, fontOffsets[fontId]);
}
reloc = inst->envelope;
inst->envelope = BASE_OFFSET(reloc);
if (gUseLegacySD)
inst->envelope = BASE_OFFSET(reloc);
inst->loaded = 1;
}
}
@ -866,12 +1019,14 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo
#undef BASE_OFFSET
gAudioContext.soundFonts[fontId].drums = ptrs[0];
gAudioContext.soundFonts[fontId].soundEffects = ptrs[1];
gAudioContext.soundFonts[fontId].instruments = (Instrument**)(ptrs + 2);
if (gUseLegacySD) {
gAudioContext.soundFonts[fontId].drums = ptrs[0];
gAudioContext.soundFonts[fontId].soundEffects = ptrs[1];
gAudioContext.soundFonts[fontId].instruments = (Instrument**)(ptrs + 2);
}
}
void AudioLoad_SyncDma(u32 devAddr, u8* addr, size_t size, s32 medium) {
void AudioLoad_SyncDma(uintptr_t devAddr, u8* addr, size_t size, s32 medium) {
OSMesgQueue* msgQueue = &gAudioContext.syncDmaQueue;
OSIoMesg* ioMesg = &gAudioContext.syncDmaIoMesg;
size = ALIGN16(size);
@ -1054,7 +1209,6 @@ s32 AudioLoad_AssertValidAddr(uintptr_t ramAddr, uintptr_t startAddr, size_t siz
#define BASE_ROM_OFFSET(x) (void*)((u32)(x) + (u32)(romAddr))
void AudioLoad_InitSwapFontSampleHeaders(SoundFontSample* sample, uintptr_t romAddr) {
// OTRTODO: This will be removed when we actually extract the data.
size_t maxSoundFontSize = 0x3AA0; // soundFont 0 is the largest size at 0x3AA0
AdpcmLoop* loop;
AdpcmBook* book;
@ -1270,17 +1424,64 @@ void AudioLoad_Init(void* heap, u32 heapSize) {
uintptr_t bankStart = ResourceMgr_LoadFileRaw(_AudiobankSegmentRomStart);
uintptr_t tableStart = ResourceMgr_LoadFileRaw(_AudiotableSegmentRomStart);
// If we have the old audioseq files present (and this is a 32-bit build), use the legacy audio system
if (seqStart != NULL && bankStart != NULL && tableStart != NULL)
gUseLegacySD = true;
fontStart = bankStart;
AudioLoad_InitTable(gAudioContext.sequenceTable, seqStart, 0);
AudioLoad_InitTable(gAudioContext.soundFontTable, bankStart, 0);
AudioLoad_InitTable(gAudioContext.sampleBankTable, tableStart, 0);
numFonts = gAudioContext.soundFontTable->numEntries;
gAudioContext.soundFonts = AudioHeap_Alloc(&gAudioContext.audioInitPool, numFonts * sizeof(SoundFont));
for (i = 0; i < numFonts; i++) {
AudioLoad_InitSoundFontMeta(i);
if (gUseLegacySD)
numFonts = gAudioContext.soundFontTable->numEntries;
if (gUseLegacySD)
{
gAudioContext.soundFonts = AudioHeap_Alloc(&gAudioContext.audioInitPool, numFonts * sizeof(SoundFont));
for (i = 0; i < numFonts; i++) {
AudioLoad_InitSoundFontMeta(i);
}
AudioLoad_InitSwapFont();
} else {
int seqListSize = 0;
char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize);
for (int i = 0; i < seqListSize; i++)
{
SequenceData sDat = ResourceMgr_LoadSeqByName(seqList[i]);
char* str = malloc(strlen(seqList[i]) + 1);
strcpy(str, seqList[i]);
sequenceMap[sDat.seqNumber] = str;
}
free(seqList);
int fntListSize = 0;
char** fntList = ResourceMgr_ListFiles("audio/fonts*", &fntListSize);
for (int i = 0; i < fntListSize; i++)
{
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fntList[i]);
char* str = malloc(strlen(fntList[i]) + 1);
strcpy(str, fntList[i]);
fontMap[sf->fntIndex] = str;
}
numFonts = fntListSize;
free(fntList);
gAudioContext.soundFonts = AudioHeap_Alloc(&gAudioContext.audioInitPool, numFonts * sizeof(SoundFont));
}
AudioLoad_InitSwapFont();
if (temp_v0_3 = AudioHeap_Alloc(&gAudioContext.audioInitPool, D_8014A6C4.permanentPoolSize), temp_v0_3 == NULL) {
// cast away const from D_8014A6C4
@ -1300,7 +1501,6 @@ void AudioLoad_InitSlowLoads(void) {
s32 AudioLoad_SlowLoadSample(s32 fontId, s32 instId, s8* isDone) {
SoundFontSample* sample;
AudioSlowLoad* slowLoad;
sample = AudioLoad_GetFontSample(fontId, instId);
if (sample == NULL) {
*isDone = 0;
@ -1454,28 +1654,42 @@ s32 AudioLoad_SlowLoadSeq(s32 seqId, u8* ramAddr, s8* isDone) {
AudioTable* seqTable;
size_t size;
if (seqId >= gAudioContext.numSequences) {
if (gUseLegacySD && seqId >= gAudioContext.numSequences) {
*isDone = 0;
return -1;
}
seqId = AudioLoad_GetRealTableIndex(SEQUENCE_TABLE, seqId);
seqTable = AudioLoad_GetLoadTable(SEQUENCE_TABLE);
slowLoad = &gAudioContext.slowLoads[gAudioContext.slowLoadPos];
if (slowLoad->status == LOAD_STATUS_DONE) {
slowLoad->status = LOAD_STATUS_WAITING;
}
slowLoad->sample.sampleAddr = NULL;
slowLoad->isDone = isDone;
size = seqTable->entries[seqId].size;
size = ALIGN16(size);
if (!gUseLegacySD)
{
SequenceData sData = ResourceMgr_LoadSeqByName(sequenceMap[seqId]);
char* seqData = sData.seqData;
size = sData.seqDataSize;
slowLoad->curDevAddr = seqData;
slowLoad->medium = sData.medium;
} else {
size = seqTable->entries[seqId].size;
size = ALIGN16(size);
slowLoad->curDevAddr = seqTable->entries[seqId].romAddr;
slowLoad->medium = seqTable->entries[seqId].medium;
}
slowLoad->curRamAddr = ramAddr;
slowLoad->status = LOAD_STATUS_START;
slowLoad->bytesRemaining = size;
slowLoad->ramAddr = ramAddr;
slowLoad->curDevAddr = seqTable->entries[seqId].romAddr;
slowLoad->medium = seqTable->entries[seqId].medium;
slowLoad->seqOrFontId = seqId;
if (slowLoad->medium == MEDIUM_UNK) {
@ -1687,44 +1901,52 @@ void AudioLoad_AsyncDmaUnkMedium(u32 devAddr, void* ramAddr, size_t size, s16 ar
#define RELOC(v, base) (reloc = (void*)((u32)(v) + (u32)(base)))
void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, RelocInfo* relocInfo) {
// OTRTODO: This is hack to detect whether or not the sample has been relocated.
void AudioLoad_RelocateSample(SoundFontSound* sound, SoundFontData* mem, RelocInfo* relocInfo, int fontId) {
size_t maxSoundBankSize = 0x3EB2A0; // sample bank 0 is largest size at 0x3EB2A0
if ((uintptr_t)mem <= maxSoundBankSize) {
// OTRTODO: This can be removed once we have properly byteswapped files on the disk.
assert("mem for sound font bank is too low.");
if (gUseLegacySD)
{
// NOTE: This is hack to detect whether or not the sample has been relocated.
if ((uintptr_t)mem <= maxSoundBankSize) {
assert("mem for sound font bank is too low.");
}
}
SoundFontSample* sample;
void* reloc;
// OTRTODO: Seems precarious to assume the RAM is never <= 0x3EB2A0, but it largely works.
if ((uintptr_t)sound->sample < maxSoundBankSize) {
sample = sound->sample = RELOC(sound->sample, mem);
if (sample->size != 0 && sample->unk_bit25 != 1) {
sample->loop = RELOC(sample->loop, mem);
sample->book = RELOC(sample->book, mem);
// NOTE: Seems precarious to assume the RAM is never <= 0x3EB2A0, but it largely works.
if ((uintptr_t)sound->sample < maxSoundBankSize || !gUseLegacySD)
{
if (!gUseLegacySD) {
SoundFontSample* sample2 = sound;
} else {
sample = sound->sample = RELOC(sound->sample, mem);
// Resolve the sample medium 2-bit bitfield into a real value based on relocInfo.
switch (sample->medium) {
case 0:
sample->sampleAddr = RELOC(sample->sampleAddr, relocInfo->baseAddr1);
sample->medium = relocInfo->medium1;
break;
case 1:
sample->sampleAddr = RELOC(sample->sampleAddr, relocInfo->baseAddr2);
sample->medium = relocInfo->medium2;
break;
case 2:
case 3:
// Invalid? This leaves sample->medium as MEDIUM_CART and MEDIUM_DISK_DRIVE
// respectively, and the sampleAddr unrelocated.
break;
}
if (sample->size != 0 && sample->unk_bit25 != 1) {
sample->loop = RELOC(sample->loop, mem);
sample->book = RELOC(sample->book, mem);
sample->unk_bit25 = 1;
if (sample->unk_bit26 && (sample->medium != MEDIUM_RAM)) {
gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample;
// Resolve the sample medium 2-bit bitfield into a real value based on relocInfo.
switch (sample->medium) {
case 0:
sample->sampleAddr = RELOC(sample->sampleAddr, relocInfo->baseAddr1);
sample->medium = relocInfo->medium1;
break;
case 1:
sample->sampleAddr = RELOC(sample->sampleAddr, relocInfo->baseAddr2);
sample->medium = relocInfo->medium2;
break;
case 2:
case 3:
// Invalid? This leaves sample->medium as MEDIUM_CART and MEDIUM_DISK_DRIVE
// respectively, and the sampleAddr unrelocated.
break;
}
sample->unk_bit25 = 1;
if (sample->unk_bit26 && (sample->medium != MEDIUM_RAM)) {
gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample;
}
}
}
}
@ -1949,8 +2171,10 @@ s32 AudioLoad_GetSamplesForFont(s32 fontId, SoundFontSample** sampleSet) {
void AudioLoad_AddUsedSample(SoundFontSound* sound) {
SoundFontSample* sample = sound->sample;
if ((sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) {
gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample;
if (sample != NULL) {
if ((sample->size != 0) && (sample->unk_bit26) && (sample->medium != MEDIUM_RAM)) {
gAudioContext.usedSamples[gAudioContext.numUsedSamples++] = sample;
}
}
}
@ -1977,9 +2201,17 @@ void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, RelocInfo* relocInfo
gAudioContext.numUsedSamples = 0;
numDrums = gAudioContext.soundFonts[fontId].numDrums;
numInstruments = gAudioContext.soundFonts[fontId].numInstruments;
numSfx = gAudioContext.soundFonts[fontId].numSfx;
if (!gUseLegacySD) {
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
numDrums = sf->numDrums;
numInstruments = sf->numInstruments;
numSfx = sf->numSfx;
} else {
numDrums = gAudioContext.soundFonts[fontId].numDrums;
numInstruments = gAudioContext.soundFonts[fontId].numInstruments;
numSfx = gAudioContext.soundFonts[fontId].numSfx;
}
for (i = 0; i < numInstruments; i++) {
instrument = Audio_GetInstrumentInner(fontId, i);
@ -2024,6 +2256,7 @@ void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, RelocInfo* relocInfo
}
sample = gAudioContext.usedSamples[i];
if (sample->medium == MEDIUM_RAM) {
continue;
}
@ -2100,10 +2333,19 @@ void AudioLoad_LoadPermanentSamples(void) {
for (i = 0; i < gAudioContext.permanentPool.count; i++) {
RelocInfo relocInfo;
if (gAudioContext.permanentCache[i].tableType == FONT_TABLE) {
if (gAudioContext.permanentCache[i].tableType == FONT_TABLE)
{
fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.permanentCache[i].id);
relocInfo.sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1;
relocInfo.sampleBankId2 = gAudioContext.soundFonts[fontId].sampleBankId2;
//fontId = gAudioContext.permanentCache[i].id;
if (!gUseLegacySD) {
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
relocInfo.sampleBankId1 = sf->sampleBankId1;
relocInfo.sampleBankId2 = sf->sampleBankId2;
} else {
relocInfo.sampleBankId1 = gAudioContext.soundFonts[fontId].sampleBankId1;
relocInfo.sampleBankId2 = gAudioContext.soundFonts[fontId].sampleBankId2;
}
if (relocInfo.sampleBankId1 != 0xFF) {
relocInfo.sampleBankId1 = AudioLoad_GetRealTableIndex(SAMPLE_TABLE, relocInfo.sampleBankId1);

View file

@ -1,6 +1,8 @@
#include "global.h"
#include "Cvar.h"
extern bool gUseLegacySD;
void Audio_InitNoteSub(Note* note, NoteSubEu* sub, NoteSubAttributes* attrs) {
f32 volRight, volLeft;
s32 smallPanIndex;
@ -284,7 +286,18 @@ void Audio_ProcessNotes(void) {
}
subAttrs.frequency *= playbackState->vibratoFreqScale * playbackState->portamentoFreqScale;
subAttrs.frequency *= gAudioContext.audioBufferParameters.resampleRate;
f32 resampRate = gAudioContext.audioBufferParameters.resampleRate;
if (!gUseLegacySD && !noteSubEu2->bitField1.isSyntheticWave && noteSubEu2->sound.soundFontSound != NULL &&
noteSubEu2->sound.soundFontSound->sample != NULL &&
noteSubEu2->sound.soundFontSound->sample->sampleRateMagicValue == 'RIFF') {
resampRate = CALC_RESAMPLE_FREQ(noteSubEu2->sound.soundFontSound->sample->sampleRate);
}
subAttrs.frequency *= resampRate;
subAttrs.velocity *= scale;
Audio_InitNoteSub(note, noteSubEu2, &subAttrs);
noteSubEu->bitField1.bookOffset = bookOffset;
@ -307,7 +320,7 @@ SoundFontSound* Audio_InstrumentGetSound(Instrument* instrument, s32 semitone) {
Instrument* Audio_GetInstrumentInner(s32 fontId, s32 instId) {
Instrument* inst;
if (fontId == 0xFF) {
return NULL;
}
@ -317,16 +330,31 @@ Instrument* Audio_GetInstrumentInner(s32 fontId, s32 instId) {
return NULL;
}
if (instId >= gAudioContext.soundFonts[fontId].numInstruments) {
gAudioContext.audioErrorFlags = ((fontId << 8) + instId) + 0x3000000;
return NULL;
int instCnt = 0;
if (gUseLegacySD) {
instCnt = gAudioContext.soundFonts[fontId].numInstruments;
inst = gAudioContext.soundFonts[fontId].instruments[instId];
if (instId >= gAudioContext.soundFonts[fontId].numInstruments)
if (instId >= instCnt) {
gAudioContext.audioErrorFlags = ((fontId << 8) + instId) + 0x3000000;
return NULL;
}
} else {
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
if (instId >= sf->numInstruments)
return NULL;
inst = sf->instruments[instId];
}
inst = gAudioContext.soundFonts[fontId].instruments[instId];
if (inst == NULL) {
gAudioContext.audioErrorFlags = ((fontId << 8) + instId) + 0x1000000;
return inst;
}
return inst;
}
@ -343,12 +371,17 @@ Drum* Audio_GetDrum(s32 fontId, s32 drumId) {
return NULL;
}
if (drumId >= gAudioContext.soundFonts[fontId].numDrums) {
gAudioContext.audioErrorFlags = ((fontId << 8) + drumId) + 0x4000000;
return NULL;
}
if (gUseLegacySD) {
if (drumId >= gAudioContext.soundFonts[fontId].numDrums) {
gAudioContext.audioErrorFlags = ((fontId << 8) + drumId) + 0x4000000;
return NULL;
}
drum = gAudioContext.soundFonts[fontId].drums[drumId];
drum = gAudioContext.soundFonts[fontId].drums[drumId];
} else {
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
drum = sf->drums[drumId];
}
if (drum == NULL) {
gAudioContext.audioErrorFlags = ((fontId << 8) + drumId) + 0x5000000;
@ -369,12 +402,17 @@ SoundFontSound* Audio_GetSfx(s32 fontId, s32 sfxId) {
return NULL;
}
if (sfxId >= gAudioContext.soundFonts[fontId].numSfx) {
gAudioContext.audioErrorFlags = ((fontId << 8) + sfxId) + 0x4000000;
return NULL;
}
if (gUseLegacySD) {
if (sfxId >= gAudioContext.soundFonts[fontId].numSfx) {
gAudioContext.audioErrorFlags = ((fontId << 8) + sfxId) + 0x4000000;
return NULL;
}
sfx = &gAudioContext.soundFonts[fontId].soundEffects[sfxId];
sfx = &gAudioContext.soundFonts[fontId].soundEffects[sfxId];
} else {
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
sfx = &sf->soundEffects[sfxId];
}
if (sfx == NULL) {
gAudioContext.audioErrorFlags = ((fontId << 8) + sfxId) + 0x5000000;

View file

@ -3,6 +3,9 @@
#include "ultra64.h"
#include "global.h"
extern bool gUseLegacySD;
extern char* sequenceMap[256];
#define PORTAMENTO_IS_SPECIAL(x) ((x).mode & 0x80)
#define PORTAMENTO_MODE(x) ((x).mode & ~0x80)
#define PORTAMENTO_MODE_1 1
@ -938,8 +941,16 @@ u8 AudioSeq_GetInstrument(SequenceChannel* channel, u8 instId, Instrument** inst
*instOut = NULL;
return 0;
}
adsr->envelope = inst->envelope;
adsr->releaseRate = inst->releaseRate;
if (inst->envelope != NULL)
{
adsr->envelope = inst->envelope;
adsr->releaseRate = (inst->releaseRate);
}
else {
adsr->envelope = gDefaultEnvelope;
}
*instOut = inst;
instId += 2;
return instId;
@ -1052,9 +1063,15 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
command = (u8)parameters[0];
if (seqPlayer->defaultFont != 0xFF) {
offset = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId];
lowBits = gAudioContext.sequenceFontTable[offset];
command = gAudioContext.sequenceFontTable[offset + lowBits - result];
if (gUseLegacySD) {
offset = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId];
lowBits = gAudioContext.sequenceFontTable[offset];
command = gAudioContext.sequenceFontTable[offset + lowBits - result];
}
else {
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqPlayer->seqId]);
command = sDat.fonts[sDat.numFonts - result - 1];
}
}
if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, command)) {
@ -1162,10 +1179,17 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
result = (u8)parameters[0];
command = (u8)parameters[0];
if (seqPlayer->defaultFont != 0xFF) {
offset = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId];
lowBits = gAudioContext.sequenceFontTable[offset];
command = gAudioContext.sequenceFontTable[offset + lowBits - result];
if (seqPlayer->defaultFont != 0xFF)
{
if (gUseLegacySD) {
offset = ((u16*)gAudioContext.sequenceFontTable)[seqPlayer->seqId];
lowBits = gAudioContext.sequenceFontTable[offset];
command = gAudioContext.sequenceFontTable[offset + lowBits - result];
}
else {
SequenceData sDat = ResourceMgr_LoadSeqByName(sequenceMap[seqPlayer->seqId]);
command = sDat.fonts[sDat.numFonts - result - 1];
}
}
if (AudioHeap_SearchCaches(FONT_TABLE, CACHE_EITHER, command)) {
@ -1322,14 +1346,12 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
break;
case 0xB2:
offset = (u16)parameters[0];
// OTRTODO: Byteswap added for quick audio
channel->unk_22 = BOMSWAP16(*(u16*)(seqPlayer->seqData + (uintptr_t)(offset + scriptState->value * 2)));
break;
case 0xB4:
channel->dynTable = (void*)&seqPlayer->seqData[channel->unk_22];
break;
case 0xB5:
// OTRTODO: Byteswap added for quick audio
channel->unk_22 = BOMSWAP16(((u16*)(channel->dynTable))[scriptState->value]);
break;
case 0xB6:

View file

@ -440,11 +440,11 @@ void func_800DBE64(void) {
void func_800DBE6C(void) {
}
void AudioSynth_LoadFilter(Acmd* cmd, s32 flags, s32 countOrBuf, s32 addr) {
void AudioSynth_LoadFilter(Acmd* cmd, s32 flags, s32 countOrBuf, uintptr_t addr) {
aFilter(cmd, flags, countOrBuf, addr);
}
void AudioSynth_LoadFilterCount(Acmd* cmd, s32 count, s32 addr) {
void AudioSynth_LoadFilterCount(Acmd* cmd, s32 count, uintptr_t addr) {
aFilter(cmd, 2, count, addr);
}
@ -561,6 +561,9 @@ Acmd* AudioSynth_DoOneAudioUpdate(s16* aiBuf, s32 aiBufLen, Acmd* cmd, s32 updat
NoteSubEu* noteSubEu2;
s32 unk14;
//if (aiBufLen == 0)
//return;
t = gAudioContext.numNotes * updateIndex;
count = 0;
if (gAudioContext.numSynthesisReverbs == 0) {
@ -749,8 +752,10 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
cmd = AudioSynth_LoadWaveSamples(cmd, noteSubEu, synthState, nSamplesToLoad);
noteSamplesDmemAddrBeforeResampling = DMEM_UNCOMPRESSED_NOTE + (synthState->samplePosInt * 2);
synthState->samplePosInt += nSamplesToLoad;
} else {
} else
{
audioFontSample = noteSubEu->sound.soundFontSound->sample;
loopInfo = audioFontSample->loop;
loopEndPos = loopInfo->end;
sampleAddr = audioFontSample->sampleAddr;
@ -822,6 +827,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
noteFinished = true;
}
}
switch (audioFontSample->codec) {
case CODEC_ADPCM:
@ -848,6 +854,9 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
goto skip;
case CODEC_S16:
AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20);
AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, ALIGN16(nSamplesToLoad * 2),
audioFontSample->sampleAddr + (synthState->samplePosInt * 2));
flags = A_CONTINUE;
skipBytes = 0;
nSamplesProcessed = samplesLenAdjusted;
@ -860,7 +869,8 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
if (nFramesToDecode != 0) {
frameIndex = (synthState->samplePosInt + skipInitialSamples - nFirstFrameSamplesToIgnore) / 16;
sampleDataOffset = frameIndex * frameSize;
if (audioFontSample->medium == MEDIUM_RAM) {
if (audioFontSample->medium == MEDIUM_RAM)
{
sampleData = (u8*)(sampleDataStart + sampleDataOffset + sampleAddr);
} else if (audioFontSample->medium == MEDIUM_UNK) {
return cmd;
@ -1024,7 +1034,8 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
unk7 = noteSubEu->unk_07;
unkE = noteSubEu->unk_0E;
buf = &synthState->synthesisBuffers->panSamplesBuffer[0x18];
if (unk7 != 0 && noteSubEu->unk_0E != 0) {
if (unk7 != 0 && noteSubEu->unk_0E != 0)
{
AudioSynth_DMemMove(cmd++, DMEM_TEMP, DMEM_SCRATCH2, aiBufLen * 2);
thing = DMEM_SCRATCH2 - unk7;
if (synthState->unk_1A != 0) {

View file

@ -213,11 +213,7 @@ AudioTask* func_800E5000(void) {
task = &gAudioContext.currTask->task.t;
task->type = M_AUDTASK;
task->flags = 0;
//task->ucode_boot = D_801120C0;
task->ucode_boot_size = 0x1000;
//task->ucode_data_size = ((rspAspMainDataEnd - rspAspMainDataStart) * sizeof(u64)) - 1;
//task->ucode = D_801120C0;
//task->ucode_data = rspAspMainDataStart;
task->ucode_size = 0x1000;
task->dram_stack = NULL;
task->dram_stack_size = 0;

View file

@ -363,7 +363,11 @@ void Audio_ProcessSeqCmd(u32 cmd) {
}
}
void Audio_QueueSeqCmd(u32 cmd) {
extern f32 D_80130F24;
extern f32 D_80130F28;
void Audio_QueueSeqCmd(u32 cmd)
{
sAudioSeqCmds[sSeqCmdWrPos++] = cmd;
}

View file

@ -6,6 +6,10 @@ s32 sShrinkWindowVal = 0;
s32 sShrinkWindowCurrentVal = 0;
void ShrinkWindow_SetVal(s32 value) {
if (CVar_GetS32("gDisableBlackBars", 0)) {
sShrinkWindowVal = 0;
return;
}
if (HREG(80) == 0x13 && HREG(81) == 1) {
osSyncPrintf("shrink_window_setval(%d)\n", value);
}
@ -17,6 +21,10 @@ u32 ShrinkWindow_GetVal(void) {
}
void ShrinkWindow_SetCurrentVal(s32 currentVal) {
if (CVar_GetS32("gDisableBlackBars", 0)) {
sShrinkWindowCurrentVal = 0;
return;
}
if (HREG(80) == 0x13 && HREG(81) == 1) {
osSyncPrintf("shrink_window_setnowval(%d)\n", currentVal);
}

View file

@ -339,19 +339,19 @@ void func_8002BF60(TargetContext* targetCtx, Actor* actor, s32 actorCategory, Gl
if (CVar_GetS32("gUseNaviCol",0) != 1 ) {
if (actorCategory == ACTORCAT_PLAYER) {
naviColor->inner.r = 255; naviColor->inner.g = 255; naviColor->inner.b = 255;
naviColor->outer.r = 115; naviColor->outer.g = 230; naviColor->outer.b = 255;
naviColor->outer.r = 0; naviColor->outer.g = 0; naviColor->outer.b = 255;
}
if (actorCategory == ACTORCAT_NPC) {
naviColor->inner.r = 100; naviColor->inner.g = 100; naviColor->inner.b = 255;
naviColor->outer.r = 90; naviColor->outer.g = 90; naviColor->outer.b = 255;
naviColor->inner.r = 150; naviColor->inner.g = 150; naviColor->inner.b = 255;
naviColor->outer.r = 150; naviColor->outer.g = 150; naviColor->outer.b = 255;
}
if (actorCategory == ACTORCAT_BOSS || actorCategory == ACTORCAT_ENEMY) {
naviColor->inner.r = 255; naviColor->inner.g = 255; naviColor->inner.b = 0;
naviColor->outer.r = 220; naviColor->outer.g = 220; naviColor->outer.b = 0;
naviColor->outer.r = 220; naviColor->outer.g = 155; naviColor->outer.b = 0;
}
if (actorCategory == ACTORCAT_PROP) {
naviColor->inner.r = 0; naviColor->inner.g = 255; naviColor->inner.b = 90;
naviColor->outer.r = 0; naviColor->outer.g = 220; naviColor->outer.b = 0;
naviColor->inner.r = 0; naviColor->inner.g = 255; naviColor->inner.b = 0;
naviColor->outer.r = 0; naviColor->outer.g = 255; naviColor->outer.b = 0;
}
} else {
if (actorCategory == ACTORCAT_PLAYER) {
@ -1163,7 +1163,9 @@ void Actor_Init(Actor* actor, GlobalContext* globalCtx) {
actor->uncullZoneForward = 1000.0f;
actor->uncullZoneScale = 350.0f;
actor->uncullZoneDownward = 700.0f;
if (CVar_GetS32("gDisableDrawDistance", 0) != 0) {
if (CVar_GetS32("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room
&& actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence
&& actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA) { // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning
actor->uncullZoneForward = 32767.0f;
actor->uncullZoneScale = 32767.0f;
actor->uncullZoneDownward = 32767.0f;
@ -2690,7 +2692,9 @@ s32 func_800314B0(GlobalContext* globalCtx, Actor* actor) {
s32 func_800314D4(GlobalContext* globalCtx, Actor* actor, Vec3f* arg2, f32 arg3) {
f32 var;
if (CVar_GetS32("gDisableDrawDistance", 0) != 0) {
if (CVar_GetS32("gDisableDrawDistance", 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room
&& actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence
&& actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA) { // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning
return true;
}

View file

@ -7532,7 +7532,7 @@ Vec3s Camera_Update(Camera* camera) {
BINANG_TO_DEGF(camera->camDir.x), camera->camDir.y, BINANG_TO_DEGF(camera->camDir.y));
}
if (camera->timer != -1 && CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_DRIGHT)) {
if (camera->timer != -1 && CHECK_BTN_ALL(D_8015BD7C->state.input[0].press.button, BTN_DRIGHT) && CVar_GetS32("gDebugCamera", 0)) {
camera->timer = 0;
}

View file

@ -2,13 +2,9 @@
#include <string.h>
SaveContext gSaveContext;
u32 D_8015FA88;
u32 D_8015FA8C;
void SaveContext_Init(void) {
memset(&gSaveContext, 0, sizeof(gSaveContext));
D_8015FA88 = 0;
D_8015FA8C = 0;
gSaveContext.seqId = (u8)NA_BGM_DISABLED;
gSaveContext.natureAmbienceId = NATURE_ID_DISABLED;
gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX;

View file

@ -896,6 +896,9 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
if (this->unk_15A > 0) {
this->unk_15A--;
if (CVar_GetS32("gDropsDontDie", 0) && (this->unk_154 <= 0)) {
this->unk_15A++;
}
}
if ((this->unk_15A > 0) && (this->unk_15A < 41) && (this->unk_154 <= 0)) {

View file

@ -2093,9 +2093,14 @@ void func_80075B44(GlobalContext* globalCtx) {
case 7:
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_1 << 4 | NATURE_CHANNEL_CRITTER_3,
CHANNEL_IO_PORT_1, 0);
if (globalCtx->envCtx.unk_EE[0] == 0 && globalCtx->envCtx.unk_F2[0] == 0) {
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_4 << 4 | NATURE_CHANNEL_CRITTER_5,
CHANNEL_IO_PORT_1, 1);
if (globalCtx->envCtx.unk_EE[0] == 0 && globalCtx->envCtx.unk_F2[0] == 0)
{
// OTRTODO: This is where corrupt audio happens. Commenting this out seems to not introduce any side effects?
// Further investigation is needed...
if (gUseLegacySD)
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_4 << 4 | NATURE_CHANNEL_CRITTER_5,
CHANNEL_IO_PORT_1, 1);
}
globalCtx->envCtx.unk_E0++;
break;

View file

@ -755,22 +755,23 @@ void Minimap_Draw(GlobalContext* globalCtx) {
if (((globalCtx->sceneNum != SCENE_SPOT01) && (globalCtx->sceneNum != SCENE_SPOT04) &&
(globalCtx->sceneNum != SCENE_SPOT08)) ||
(LINK_AGE_IN_YEARS != YEARS_ADULT)) {
bool Map0 = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] << 2 == 0;
s16 IconSize = 8;
s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex]+Right_MM_Margin;
s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex]+Bottom_MM_Margin;
s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex] + (Map0 ? 0 : Right_MM_Margin);
s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] + (Map0 ? 0 : Bottom_MM_Margin);
//gFixDungeonMinimapIcon fix both Y position of visible icon and hide these non needed.
if (CVar_GetS32("gFixDungeonMinimapIcon", 1) != 0){
if (CVar_GetS32("gFixDungeonMinimapIcon", 0) != 0){
//No idea why and how Original value work but this does actually fix them all.
PosY = PosY+1024;
}
s16 TopLeftX = OTRGetRectDimensionFromRightEdge(PosX) << 2;
s16 TopLeftX = (Map0 ? OTRGetRectDimensionFromLeftEdge(PosX) : OTRGetRectDimensionFromRightEdge(PosX)) << 2;
s16 TopLeftY = PosY << 2;
s16 TopLeftW = OTRGetRectDimensionFromRightEdge(PosX + IconSize) << 2;
s16 TopLeftW = (Map0 ? OTRGetRectDimensionFromLeftEdge(PosX + IconSize) : OTRGetRectDimensionFromRightEdge(PosX + IconSize)) << 2;
s16 TopLeftH = (PosY + IconSize) << 2;
if ((gMapData->owEntranceFlag[sEntranceIconMapIndex] == 0xFFFF) ||
((gMapData->owEntranceFlag[sEntranceIconMapIndex] != 0xFFFF) &&
(gSaveContext.infTable[26] & gBitFlags[gMapData->owEntranceFlag[mapIndex]]))) {
if (gMapData->owEntranceIconPosY[sEntranceIconMapIndex] << 2 != 0 && CVar_GetS32("gFixDungeonMinimapIcon", 1) != 0){
if (!Map0 || !CVar_GetS32("gFixDungeonMinimapIcon", 0)) {
gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b,
IconSize, IconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);

View file

@ -2935,7 +2935,7 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
}
const s16 rCUpBtnX = OTRGetRectDimensionFromRightEdge(R_C_UP_BTN_X+Right_HUD_Margin);
const s16 rCUPIconX = OTRGetRectDimensionFromRightEdge(R_C_UP_ICON_X+Right_HUD_Margin);
const s16 rCUPIconX = OTRGetRectDimensionFromRightEdge(R_C_UP_ICON_X+Right_HUD_Margin-!!CVar_GetS32("gNaviTextFix", 0));
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp);
} else if (CVar_GetS32("gHudColors", 1) == 1) {

View file

@ -240,7 +240,6 @@ void Gameplay_Init(GameState* thisx) {
globalCtx->cameraPtrs[MAIN_CAM]->uid = 0;
globalCtx->activeCamera = MAIN_CAM;
func_8005AC48(&globalCtx->mainCamera, 0xFF);
Sram_Init(globalCtx, &globalCtx->sramCtx);
func_80112098(globalCtx);
Message_Init(globalCtx);
GameOver_Init(globalCtx);

View file

@ -360,7 +360,8 @@ s32 Player_ActionToModelGroup(Player* this, s32 actionParam) {
void Player_SetModelsForHoldingShield(Player* this) {
if ((this->stateFlags1 & 0x400000) &&
((this->itemActionParam < 0) || (this->itemActionParam == this->heldItemActionParam))) {
if (!Player_HoldsTwoHandedWeapon(this) && !Player_IsChildWithHylianShield(this)) {
if ((CVar_GetS32("gShieldTwoHanded", 0) && (this->heldItemActionParam != PLAYER_AP_STICK) ||
!Player_HoldsTwoHandedWeapon(this)) && !Player_IsChildWithHylianShield(this)) {
this->rightHandType = 10;
this->rightHandDLists = &sPlayerDListGroups[10][(void)0, gSaveContext.linkAge];
if (this->sheathType == 18) {

View file

@ -3,242 +3,14 @@
#include <string.h>
// these are the main substructs of save context.
// we are going to hold off on splitting save context until later on,
// so these temporary structs will live here for now.
typedef struct {
/* 0x00 */ char newf[6]; // string "ZELDAZ"
/* 0x06 */ s16 deaths;
/* 0x08 */ char playerName[8];
/* 0x10 */ s16 n64ddFlag;
/* 0x12 */ s16 healthCapacity; // "max_life"
/* 0x14 */ s16 health; // "now_life"
/* 0x16 */ s8 magicLevel;
/* 0x17 */ s8 magic;
/* 0x18 */ s16 rupees;
/* 0x1A */ u16 swordHealth;
/* 0x1C */ u16 naviTimer;
/* 0x1E */ u8 magicAcquired;
/* 0x1F */ u8 unk_1F;
/* 0x20 */ u8 doubleMagic;
/* 0x21 */ u8 doubleDefense;
/* 0x22 */ u8 bgsFlag;
/* 0x23 */ u8 ocarinaGameRoundNum;
/* 0x24 */ ItemEquips childEquips;
/* 0x2E */ ItemEquips adultEquips;
/* 0x38 */ u32 unk_38; // this may be incorrect, currently used for alignement
/* 0x3C */ char unk_3C[0x0E];
/* 0x4A */ s16 savedSceneNum;
} SavePlayerData; // size = 0x4C
typedef struct {
/* 0x0000 */ SavePlayerData playerData; // "S_Private" substruct name
/* 0x004C */ ItemEquips equips;
/* 0x0058 */ Inventory inventory;
/* 0x00B8 */ SavedSceneFlags sceneFlags[124];
/* 0x0E48 */ FaroresWindData fw;
/* 0x0E70 */ char unk_E70[0x10];
/* 0x0E80 */ s32 gsFlags[6];
/* 0x0E98 */ char unk_E98[0x10];
/* 0x0EA8 */ s32 horseRaceRecord;
/* 0x0EAC */ char unk_EAC[0x0C];
/* 0x0EB8 */ u16 eventChkInf[14]; // "event_chk_inf"
/* 0x0ED4 */ u16 itemGetInf[4]; // "item_get_inf"
/* 0x0EDC */ u16 infTable[30]; // "inf_table"
/* 0x0F18 */ char unk_F18[0x04];
/* 0x0F1C */ u32 worldMapAreaData; // "area_arrival"
/* 0x0F20 */ char unk_F20[0x4];
/* 0x0F24 */ u8 scarecrowCustomSongSet;
/* 0x0F25 */ u8 scarecrowCustomSong[0x360];
/* 0x1285 */ char unk_1285[0x24];
/* 0x12A9 */ u8 scarecrowSpawnSongSet;
/* 0x12AA */ u8 scarecrowSpawnSong[0x80];
/* 0x132A */ char unk_132A[0x02];
/* 0x132C */ HorseData horseData;
/* 0x1336 */ u16 checksum; // "check_sum"
} SaveInfo; // size = 0x1338
typedef struct {
/* 0x00 */ s32 entranceIndex;
/* 0x04 */ s32 linkAge; // 0: Adult; 1: Child
/* 0x08 */ s32 cutsceneIndex;
/* 0x0C */ u16 dayTime; // "zelda_time"
/* 0x10 */ s32 nightFlag;
/* 0x14 */ s32 totalDays;
/* 0x18 */ s32 unk_18; // increments with totalDays, gets reset by goron for bgs and one other use
/* 0x1C */ SaveInfo info; // "information"
} Save; // size = 0x1354
#define SAVE_PLAYER_DATA (*((SavePlayerData*)&gSaveContext.newf))
#define SAVE_INFO (*((SaveInfo*)&gSaveContext.newf))
#define SLOT_SIZE (sizeof(SaveContext) + 0x28)
#define CHECKSUM_SIZE (sizeof(Save) / 2)
#define DEATHS OFFSETOF(SaveContext, deaths)
#define NAME OFFSETOF(SaveContext, playerName)
#define N64DD OFFSETOF(SaveContext, n64ddFlag)
#define HEALTH_CAP OFFSETOF(SaveContext, healthCapacity)
#define QUEST OFFSETOF(SaveContext, inventory.questItems)
#define DEFENSE OFFSETOF(SaveContext, inventory.defenseHearts)
#define HEALTH OFFSETOF(SaveContext, health)
#define SLOT_OFFSET(index) (SRAM_HEADER_SIZE + 0x10 + (index * SLOT_SIZE))
u16 gSramSlotOffsets[] = {
SLOT_OFFSET(0),
SLOT_OFFSET(1),
SLOT_OFFSET(2),
// the latter three saves are backup saves for the former saves
SLOT_OFFSET(3),
SLOT_OFFSET(4),
SLOT_OFFSET(5),
};
static u8 sZeldaMagic[] = { '\0', '\0', '\0', '\x98', '\x09', '\x10', '\x21', 'Z', 'E', 'L', 'D', 'A' };
static SavePlayerData sNewSavePlayerData = {
{ '\0', '\0', '\0', '\0', '\0', '\0' }, // newf
0, // deaths
{ 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E }, // playerName
0, // n64ddFlag
0x30, // healthCapacity
0x30, // defense
0, // magicLevel
0x30, // magic
0, // rupees
0, // swordHealth
0, // naviTimer
0, // magicAcquired
0, // unk_1F
0, // doubleMagic
0, // doubleDefense
0, // bgsFlag
0, // ocarinaGameRoundNum
{
{ ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE }, // buttonItems
{ SLOT_NONE, SLOT_NONE, SLOT_NONE }, // cButtonSlots
0, // equipment
}, // childEquips
{
{ ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE }, // buttonItems
{ SLOT_NONE, SLOT_NONE, SLOT_NONE }, // cButtonSlots
0, // equipment
}, // adultEquips
0, // unk_38
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // unk_3C
0x34, // savedSceneNum
};
static ItemEquips sNewSaveEquips = {
{ ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE }, // buttonItems
{ SLOT_NONE, SLOT_NONE, SLOT_NONE }, // cButtonSlots
0x1100, // equipment
};
static Inventory sNewSaveInventory = {
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // items
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ammo
0x1100, // equipment
0, // upgrades
0, // questItems
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // dungeonItems
{
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
}, // dungeonKeys
0, // defenseHearts
0, // gsTokens
};
static u16 sNewSaveChecksum = 0;
/**
* Initialize new save.
* This save has an empty inventory with 3 hearts and single magic.
*/
void Sram_InitNewSave(void) {
SaveContext* temp = &gSaveContext;
memset(&SAVE_INFO, 0, sizeof(SaveInfo));
gSaveContext.totalDays = 0;
gSaveContext.bgsDayCount = 0;
SAVE_PLAYER_DATA = sNewSavePlayerData;
gSaveContext.equips = sNewSaveEquips;
gSaveContext.inventory = sNewSaveInventory;
temp->checksum = sNewSaveChecksum;
gSaveContext.horseData.scene = SCENE_SPOT00;
gSaveContext.horseData.pos.x = -1840;
gSaveContext.horseData.pos.y = 72;
gSaveContext.horseData.pos.z = 5497;
gSaveContext.horseData.angle = -0x6AD9;
gSaveContext.magicLevel = 0;
gSaveContext.infTable[29] = 1;
gSaveContext.sceneFlags[5].swch = 0x40000000;
Save_InitFile(false);
}
static SavePlayerData sDebugSavePlayerData = {
{ 'Z', 'E', 'L', 'D', 'A', 'Z' }, // newf
0, // deaths
{ 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E }, // playerName ( "LINK" )
0, // n64ddFlag
0xE0, // healthCapacity
0xE0, // health
0, // magicLevel
0x30, // magic
150, // rupees
8, // swordHealth
0, // naviTimer
1, // magicAcquired
0, // unk_1F
0, // doubleMagic
0, // doubleDefense
0, // bgsFlag
0, // ocarinaGameRoundNum
{
{ ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE }, // buttonItems
{ SLOT_NONE, SLOT_NONE, SLOT_NONE }, // cButtonSlots
0, // equipment
}, // childEquips
{
{ ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE }, // buttonItems
{ SLOT_NONE, SLOT_NONE, SLOT_NONE }, // cButtonSlots
0, // equipment
}, // adultEquips
0, // unk_38
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // unk_3C
0x51, // savedSceneNum
};
static ItemEquips sDebugSaveEquips = {
{ ITEM_SWORD_MASTER, ITEM_BOW, ITEM_BOMB, ITEM_OCARINA_FAIRY }, // buttonItems
{ SLOT_BOW, SLOT_BOMB, SLOT_OCARINA }, // cButtonSlots
0x1122, // equipment
};
static Inventory sDebugSaveInventory = {
{
ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_ARROW_FIRE, ITEM_DINS_FIRE,
ITEM_SLINGSHOT, ITEM_OCARINA_FAIRY, ITEM_BOMBCHU, ITEM_HOOKSHOT, ITEM_ARROW_ICE, ITEM_FARORES_WIND,
ITEM_BOOMERANG, ITEM_LENS, ITEM_BEAN, ITEM_HAMMER, ITEM_ARROW_LIGHT, ITEM_NAYRUS_LOVE,
ITEM_BOTTLE, ITEM_POTION_RED, ITEM_POTION_GREEN, ITEM_POTION_BLUE, ITEM_POCKET_EGG, ITEM_WEIRD_EGG,
}, // items
{ 50, 50, 10, 30, 1, 1, 30, 1, 50, 1, 1, 1, 1, 1, 1, 1 }, // ammo
0x7777, // equipment
0x125249, // upgrades
0x1E3FFFF, // questItems
{ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // dungeonItems
{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, // dungeonKeys
0, // defenseHearts
0, // gsTokens
};
static u16 sDebugSaveChecksum = 0;
/**
* Initialize debug save. This is also used on the Title Screen
* This save has a mostly full inventory with 10 hearts and single magic.
@ -249,40 +21,7 @@ static u16 sDebugSaveChecksum = 0;
* and set water level in Water Temple to lowest level.
*/
void Sram_InitDebugSave(void) {
SaveContext* temp = &gSaveContext;
memset(&SAVE_INFO, 0, sizeof(SaveInfo));
gSaveContext.totalDays = 0;
gSaveContext.bgsDayCount = 0;
SAVE_PLAYER_DATA = sDebugSavePlayerData;
gSaveContext.equips = sDebugSaveEquips;
gSaveContext.inventory = sDebugSaveInventory;
temp->checksum = sDebugSaveChecksum;
gSaveContext.horseData.scene = SCENE_SPOT00;
gSaveContext.horseData.pos.x = -1840;
gSaveContext.horseData.pos.y = 72;
gSaveContext.horseData.pos.z = 5497;
gSaveContext.horseData.angle = -0x6AD9;
gSaveContext.infTable[0] |= 0x5009;
gSaveContext.eventChkInf[0] |= 0x123F;
gSaveContext.eventChkInf[8] |= 1;
gSaveContext.eventChkInf[12] |= 0x10;
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KOKIRI;
Inventory_ChangeEquipment(EQUIP_SWORD, 1);
if (gSaveContext.fileNum == 0xFF) {
gSaveContext.equips.buttonItems[1] = ITEM_SLINGSHOT;
gSaveContext.equips.cButtonSlots[0] = SLOT_SLINGSHOT;
Inventory_ChangeEquipment(EQUIP_SHIELD, 1);
}
}
gSaveContext.entranceIndex = 0xCD;
gSaveContext.magicLevel = 0;
gSaveContext.sceneFlags[5].swch = 0x40000000;
Save_InitFile(true);
}
/**
@ -295,7 +34,7 @@ void Sram_InitDebugSave(void) {
* - Give and equip master sword if player is adult and doesnt have kokiri sword (bug?)
* - Revert any trade items that spoil
*/
void Sram_OpenSave(SramContext* sramCtx) {
void Sram_OpenSave() {
static s16 dungeonEntrances[] = {
0x0000, 0x0004, 0x0028, 0x0169, 0x0165, 0x0010, 0x0082, 0x0037,
0x0098, 0x0088, 0x041B, 0x0008, 0x0486, 0x0467, 0x0179, 0x056C,
@ -304,15 +43,7 @@ void Sram_OpenSave(SramContext* sramCtx) {
u16 j;
u8* ptr;
osSyncPrintf("個人File作成\n"); // "Create personal file"
i = gSramSlotOffsets[gSaveContext.fileNum];
osSyncPrintf("ぽいんと=%x(%d)\n", i, gSaveContext.fileNum); // "Point="
memcpy(&gSaveContext, sramCtx->readBuff + i, sizeof(Save));
osSyncPrintf(VT_FGCOL(YELLOW));
osSyncPrintf("SCENE_DATA_ID = %d SceneNo = %d\n", gSaveContext.savedSceneNum,
((void)0, gSaveContext.entranceIndex));
Save_LoadFile();
switch (gSaveContext.savedSceneNum) {
case SCENE_YDAN:
@ -446,232 +177,7 @@ void Sram_OpenSave(SramContext* sramCtx) {
gSaveContext.magicLevel = 0;
}
/**
* Write the contents of the Save Context to a main and backup slot in SRAM.
* Note: The whole Save Context is written even though only the `save` substruct is read back later
*/
void Sram_WriteSave(SramContext* sramCtx) {
u16 offset;
u16 checksum;
u16 j;
u16* ptr;
gSaveContext.checksum = 0;
ptr = (u16*)&gSaveContext;
checksum = 0;
j = 0;
for (offset = 0; offset < CHECKSUM_SIZE; offset++) {
if (++j == 0x20) {
j = 0;
}
checksum += *ptr++;
}
gSaveContext.checksum = checksum;
ptr = (u16*)&gSaveContext;
checksum = 0;
for (offset = 0; offset < CHECKSUM_SIZE; offset++) {
if (++j == 0x20) {
j = 0;
}
checksum += *ptr++;
}
offset = gSramSlotOffsets[gSaveContext.fileNum];
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000) + offset, &gSaveContext, SLOT_SIZE, OS_WRITE);
ptr = (u16*)&gSaveContext;
checksum = 0;
for (offset = 0; offset < CHECKSUM_SIZE; offset++) {
if (++j == 0x20) {
j = 0;
}
checksum += *ptr++;
}
offset = gSramSlotOffsets[gSaveContext.fileNum + 3];
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000) + offset, &gSaveContext, SLOT_SIZE, OS_WRITE);
}
/**
* For all 3 slots, verify that the checksum is correct. If corrupted, attempt to load a backup save.
* If backup is also corrupted, default to a new save (or debug save for slot 0 on debug rom).
*
* After verifying all 3 saves, pass relevant data to File Select to be displayed.
*/
void Sram_VerifyAndLoadAllSaves(FileChooseContext* fileChooseCtx, SramContext* sramCtx) {
u16 i;
u16 newChecksum;
u16 slotNum;
u16 offset;
u16 j;
u16 oldChecksum;
u16* ptr;
u16 dayTime;
osSyncPrintf(" START─LOAD\n");
memset(sramCtx->readBuff,0, SRAM_SIZE);
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_READ);
dayTime = ((void)0, gSaveContext.dayTime);
for (slotNum = 0; slotNum < 3; slotNum++) {
offset = gSramSlotOffsets[slotNum];
osSyncPrintf("ぽいんと=%x(%d) SAVE_MAX=%d\n", offset, gSaveContext.fileNum, sizeof(Save));
memcpy(&gSaveContext, sramCtx->readBuff + offset, sizeof(Save));
oldChecksum = gSaveContext.checksum;
gSaveContext.checksum = 0;
ptr = (u16*)&gSaveContext;
osSyncPrintf("\n %d \n", slotNum);
for (i = newChecksum = j = 0; i < CHECKSUM_SIZE; i++, offset += 2) {
newChecksum += *ptr++;
}
// "SAVE checksum calculation"
osSyncPrintf("\nSAVEチェックサム計算 j=%x mmm=%x ", newChecksum, oldChecksum);
if (newChecksum != oldChecksum) {
// checksum didnt match, try backup save
osSyncPrintf(" %x(%d)\n", gSramSlotOffsets[slotNum], slotNum);
offset = gSramSlotOffsets[slotNum + 3];
memcpy(&gSaveContext, sramCtx->readBuff + offset, sizeof(Save));
oldChecksum = gSaveContext.checksum;
gSaveContext.checksum = 0;
ptr = (u16*)&gSaveContext;
osSyncPrintf("================= BACK─UP ========================\n");
for (i = newChecksum = j = 0; i < CHECKSUM_SIZE; i++, offset += 2) {
newChecksum += *ptr++;
}
// "(B) SAVE checksum calculation"
osSyncPrintf("\n(B)SAVEチェックサム計算 j=%x mmm=%x ", newChecksum, oldChecksum);
if (newChecksum != oldChecksum) {
// backup save didnt work, make new save
osSyncPrintf(" %x(%d+3)\n", gSramSlotOffsets[slotNum + 3], slotNum);
memset(&gSaveContext.entranceIndex, 0, sizeof(s32));
memset(&gSaveContext.linkAge, 0, sizeof(s32));
memset(&gSaveContext.cutsceneIndex, 0, sizeof(s32));
// note that gSaveContext.dayTime is not actually the sizeof(s32)
memset(&gSaveContext.dayTime, 0, sizeof(s32));
memset(&gSaveContext.nightFlag, 0, sizeof(s32));
memset(&gSaveContext.totalDays, 0, sizeof(s32));
memset(&gSaveContext.bgsDayCount, 0, sizeof(s32));
if (!slotNum && CVar_GetS32("gDebugEnabled", 0)) {
Sram_InitDebugSave();
gSaveContext.newf[0] = 'Z';
gSaveContext.newf[1] = 'E';
gSaveContext.newf[2] = 'L';
gSaveContext.newf[3] = 'D';
gSaveContext.newf[4] = 'A';
gSaveContext.newf[5] = 'Z';
osSyncPrintf("newf=%x,%x,%x,%x,%x,%x\n", gSaveContext.newf[0], gSaveContext.newf[1],
gSaveContext.newf[2], gSaveContext.newf[3], gSaveContext.newf[4],
gSaveContext.newf[5]);
} else {
Sram_InitNewSave();
}
ptr = (u16*)&gSaveContext;
osSyncPrintf("\n--------------------------------------------------------------\n");
for (i = newChecksum = j = 0; i < CHECKSUM_SIZE; i++) {
osSyncPrintf("%x ", *ptr);
if (++j == 0x20) {
osSyncPrintf("\n");
j = 0;
}
newChecksum += *ptr++;
}
gSaveContext.checksum = newChecksum;
osSyncPrintf("\nCheck_Sum=%x(%x)\n", gSaveContext.checksum, newChecksum);
i = gSramSlotOffsets[slotNum + 3];
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000) + i, &gSaveContext, SLOT_SIZE, OS_WRITE);
osSyncPrintf("????#%x,%x,%x,%x,%x,%x\n", gSaveContext.newf[0], gSaveContext.newf[1],
gSaveContext.newf[2], gSaveContext.newf[3], gSaveContext.newf[4], gSaveContext.newf[5]);
osSyncPrintf("\nぽいんと=%x(%d+3) check_sum=%x(%x)\n", i, slotNum, gSaveContext.checksum,
newChecksum);
}
i = gSramSlotOffsets[slotNum];
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000) + i, &gSaveContext, SLOT_SIZE, OS_WRITE);
osSyncPrintf("ぽいんと=%x(%d) check_sum=%x(%x)\n", i, slotNum, gSaveContext.checksum, newChecksum);
} else {
osSyncPrintf("\nSAVEデータ \n"); // "SAVE data OK! ! ! !"
}
}
memset(sramCtx->readBuff,0, SRAM_SIZE);
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_READ);
gSaveContext.dayTime = dayTime;
osSyncPrintf("SAVECT=%x, NAME=%x, LIFE=%x, ITEM=%x, 64DD=%x, HEART=%x\n", DEATHS, NAME, HEALTH_CAP, QUEST, N64DD,
DEFENSE);
memcpy(&fileChooseCtx->deaths[0], sramCtx->readBuff + SLOT_OFFSET(0) + DEATHS, sizeof(fileChooseCtx->deaths[0]));
memcpy(&fileChooseCtx->deaths[1], sramCtx->readBuff + SLOT_OFFSET(1) + DEATHS, sizeof(fileChooseCtx->deaths[0]));
memcpy(&fileChooseCtx->deaths[2], sramCtx->readBuff + SLOT_OFFSET(2) + DEATHS, sizeof(fileChooseCtx->deaths[0]));
memcpy(&fileChooseCtx->fileNames[0], sramCtx->readBuff + SLOT_OFFSET(0) + NAME,
sizeof(fileChooseCtx->fileNames[0]));
memcpy(&fileChooseCtx->fileNames[1], sramCtx->readBuff + SLOT_OFFSET(1) + NAME,
sizeof(fileChooseCtx->fileNames[0]));
memcpy(&fileChooseCtx->fileNames[2], sramCtx->readBuff + SLOT_OFFSET(2) + NAME,
sizeof(fileChooseCtx->fileNames[0]));
memcpy(&fileChooseCtx->healthCapacities[0], sramCtx->readBuff + SLOT_OFFSET(0) + HEALTH_CAP,
sizeof(fileChooseCtx->healthCapacities[0]));
memcpy(&fileChooseCtx->healthCapacities[1], sramCtx->readBuff + SLOT_OFFSET(1) + HEALTH_CAP,
sizeof(fileChooseCtx->healthCapacities[0]));
memcpy(&fileChooseCtx->healthCapacities[2], sramCtx->readBuff + SLOT_OFFSET(2) + HEALTH_CAP,
sizeof(fileChooseCtx->healthCapacities[0]));
memcpy(&fileChooseCtx->questItems[0], sramCtx->readBuff + SLOT_OFFSET(0) + QUEST,
sizeof(fileChooseCtx->questItems[0]));
memcpy(&fileChooseCtx->questItems[1], sramCtx->readBuff + SLOT_OFFSET(1) + QUEST,
sizeof(fileChooseCtx->questItems[0]));
memcpy(&fileChooseCtx->questItems[2], sramCtx->readBuff + SLOT_OFFSET(2) + QUEST,
sizeof(fileChooseCtx->questItems[0]));
memcpy(&fileChooseCtx->n64ddFlags[0], sramCtx->readBuff + SLOT_OFFSET(0) + N64DD,
sizeof(fileChooseCtx->n64ddFlags[0]));
memcpy(&fileChooseCtx->n64ddFlags[1], sramCtx->readBuff + SLOT_OFFSET(1) + N64DD,
sizeof(fileChooseCtx->n64ddFlags[0]));
memcpy(&fileChooseCtx->n64ddFlags[2], sramCtx->readBuff + SLOT_OFFSET(2) + N64DD,
sizeof(fileChooseCtx->n64ddFlags[0]));
memcpy(&fileChooseCtx->defense[0], sramCtx->readBuff + SLOT_OFFSET(0) + DEFENSE,
sizeof(fileChooseCtx->defense[0]));
memcpy(&fileChooseCtx->defense[1], sramCtx->readBuff + SLOT_OFFSET(1) + DEFENSE,
sizeof(fileChooseCtx->defense[0]));
memcpy(&fileChooseCtx->defense[2], sramCtx->readBuff + SLOT_OFFSET(2) + DEFENSE,
sizeof(fileChooseCtx->defense[0]));
memcpy(&fileChooseCtx->health[0], sramCtx->readBuff + SLOT_OFFSET(0) + HEALTH, sizeof(fileChooseCtx->health[0]));
memcpy(&fileChooseCtx->health[1], sramCtx->readBuff + SLOT_OFFSET(1) + HEALTH, sizeof(fileChooseCtx->health[0]));
memcpy(&fileChooseCtx->health[2], sramCtx->readBuff + SLOT_OFFSET(2) + HEALTH, sizeof(fileChooseCtx->health[0]));
osSyncPrintf("f_64dd=%d, %d, %d\n", fileChooseCtx->n64ddFlags[0], fileChooseCtx->n64ddFlags[1],
fileChooseCtx->n64ddFlags[2]);
osSyncPrintf("heart_status=%d, %d, %d\n", fileChooseCtx->defense[0], fileChooseCtx->defense[1],
fileChooseCtx->defense[2]);
osSyncPrintf("now_life=%d, %d, %d\n", fileChooseCtx->health[0], fileChooseCtx->health[1], fileChooseCtx->health[2]);
}
void Sram_InitSave(FileChooseContext* fileChooseCtx, SramContext* sramCtx) {
void Sram_InitSave(FileChooseContext* fileChooseCtx) {
u16 offset;
u16 j;
u16* ptr;
@ -693,189 +199,14 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx, SramContext* sramCtx) {
}
for (offset = 0; offset < 8; offset++) {
gSaveContext.playerName[offset] = fileChooseCtx->fileNames[fileChooseCtx->buttonIndex][offset];
gSaveContext.playerName[offset] = Save_GetSaveMetaInfo(fileChooseCtx->buttonIndex)->playerName[offset];
}
gSaveContext.newf[0] = 'Z';
gSaveContext.newf[1] = 'E';
gSaveContext.newf[2] = 'L';
gSaveContext.newf[3] = 'D';
gSaveContext.newf[4] = 'A';
gSaveContext.newf[5] = 'Z';
gSaveContext.n64ddFlag = fileChooseCtx->n64ddFlag;
osSyncPrintf("64DDフラグ=%d\n", fileChooseCtx->n64ddFlag);
osSyncPrintf("newf=%x,%x,%x,%x,%x,%x\n", gSaveContext.newf[0], gSaveContext.newf[1], gSaveContext.newf[2],
gSaveContext.newf[3], gSaveContext.newf[4], gSaveContext.newf[5]);
osSyncPrintf("\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
ptr = (u16*)&gSaveContext;
j = 0;
checksum = 0;
for (offset = 0; offset < CHECKSUM_SIZE; offset++) {
osSyncPrintf("%x ", *ptr);
checksum += *ptr++;
if (++j == 0x20) {
osSyncPrintf("\n");
j = 0;
}
}
gSaveContext.checksum = checksum;
osSyncPrintf("\nチェックサム=%x\n", gSaveContext.checksum); // "Checksum = %x"
offset = gSramSlotOffsets[gSaveContext.fileNum];
osSyncPrintf("I=%x no=%d\n", offset, gSaveContext.fileNum);
memcpy(sramCtx->readBuff + offset, &gSaveContext, sizeof(Save));
offset = gSramSlotOffsets[gSaveContext.fileNum + 3];
osSyncPrintf("I=%x no=%d\n", offset, gSaveContext.fileNum + 3);
memcpy(sramCtx->readBuff + offset, &gSaveContext, sizeof(Save));
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_WRITE);
osSyncPrintf("SAVE終了\n"); // "SAVE end"
osSyncPrintf("z_common_data.file_no = %d\n", gSaveContext.fileNum);
osSyncPrintf("SAVECT=%x, NAME=%x, LIFE=%x, ITEM=%x, SAVE_64DD=%x\n", DEATHS, NAME, HEALTH_CAP, QUEST, N64DD);
j = gSramSlotOffsets[gSaveContext.fileNum];
memcpy(&fileChooseCtx->deaths[gSaveContext.fileNum], sramCtx->readBuff + j + DEATHS,
sizeof(fileChooseCtx->deaths[0]));
memcpy(&fileChooseCtx->fileNames[gSaveContext.fileNum], sramCtx->readBuff + j + NAME,
sizeof(fileChooseCtx->fileNames[0]));
memcpy(&fileChooseCtx->healthCapacities[gSaveContext.fileNum], sramCtx->readBuff + j + HEALTH_CAP,
sizeof(fileChooseCtx->healthCapacities[0]));
memcpy(&fileChooseCtx->questItems[gSaveContext.fileNum], sramCtx->readBuff + j + QUEST,
sizeof(fileChooseCtx->questItems[0]));
memcpy(&fileChooseCtx->n64ddFlags[gSaveContext.fileNum], sramCtx->readBuff + j + N64DD,
sizeof(fileChooseCtx->n64ddFlags[0]));
memcpy(&fileChooseCtx->defense[gSaveContext.fileNum], sramCtx->readBuff + j + DEFENSE,
sizeof(fileChooseCtx->defense[0]));
memcpy(&fileChooseCtx->health[gSaveContext.fileNum], sramCtx->readBuff + j + HEALTH,
sizeof(fileChooseCtx->health[0]));
osSyncPrintf("f_64dd[%d]=%d\n", gSaveContext.fileNum, fileChooseCtx->n64ddFlags[gSaveContext.fileNum]);
osSyncPrintf("heart_status[%d]=%d\n", gSaveContext.fileNum, fileChooseCtx->defense[gSaveContext.fileNum]);
osSyncPrintf("now_life[%d]=%d\n", gSaveContext.fileNum, fileChooseCtx->health[gSaveContext.fileNum]);
Save_SaveFile();
}
void Sram_EraseSave(FileChooseContext* fileChooseCtx, SramContext* sramCtx) {
s32 offset;
void Sram_InitSram(GameState* gameState) {
Save_Init();
Sram_InitNewSave();
offset = gSramSlotOffsets[fileChooseCtx->selectedFileIndex];
memcpy(sramCtx->readBuff + offset, &gSaveContext, sizeof(Save));
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000) + offset, &gSaveContext, SLOT_SIZE, OS_WRITE);
memcpy(&fileChooseCtx->n64ddFlags[fileChooseCtx->selectedFileIndex], sramCtx->readBuff + offset + N64DD,
sizeof(fileChooseCtx->n64ddFlags[0]));
offset = gSramSlotOffsets[fileChooseCtx->selectedFileIndex + 3];
memcpy(sramCtx->readBuff + offset, &gSaveContext, sizeof(Save));
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000) + offset, &gSaveContext, SLOT_SIZE, OS_WRITE);
osSyncPrintf("CLEAR終了\n");
}
void Sram_CopySave(FileChooseContext* fileChooseCtx, SramContext* sramCtx) {
s32 offset;
osSyncPrintf("=%d(%x) =%d(%x)\n", fileChooseCtx->selectedFileIndex,
gSramSlotOffsets[fileChooseCtx->selectedFileIndex], fileChooseCtx->copyDestFileIndex,
gSramSlotOffsets[fileChooseCtx->copyDestFileIndex]);
offset = gSramSlotOffsets[fileChooseCtx->selectedFileIndex];
memcpy(&gSaveContext, sramCtx->readBuff + offset, sizeof(Save));
offset = gSramSlotOffsets[fileChooseCtx->copyDestFileIndex];
memcpy(sramCtx->readBuff + offset, &gSaveContext, sizeof(Save));
offset = gSramSlotOffsets[fileChooseCtx->copyDestFileIndex + 3];
memcpy(sramCtx->readBuff + offset, &gSaveContext, sizeof(Save));
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_WRITE);
offset = gSramSlotOffsets[fileChooseCtx->copyDestFileIndex];
memcpy(&fileChooseCtx->deaths[fileChooseCtx->copyDestFileIndex], sramCtx->readBuff + offset + DEATHS,
sizeof(fileChooseCtx->deaths[0]));
memcpy(&fileChooseCtx->fileNames[fileChooseCtx->copyDestFileIndex], sramCtx->readBuff + offset + NAME,
sizeof(fileChooseCtx->fileNames[0]));
memcpy(&fileChooseCtx->healthCapacities[fileChooseCtx->copyDestFileIndex], sramCtx->readBuff + offset + HEALTH_CAP,
sizeof(fileChooseCtx->healthCapacities[0]));
memcpy(&fileChooseCtx->questItems[fileChooseCtx->copyDestFileIndex], sramCtx->readBuff + offset + QUEST,
sizeof(fileChooseCtx->questItems[0]));
memcpy(&fileChooseCtx->n64ddFlags[fileChooseCtx->copyDestFileIndex], sramCtx->readBuff + offset + N64DD,
sizeof(fileChooseCtx->n64ddFlags[0]));
memcpy(&fileChooseCtx->defense[fileChooseCtx->copyDestFileIndex], sramCtx->readBuff + offset + DEFENSE,
sizeof(fileChooseCtx->defense[0]));
memcpy(&fileChooseCtx->health[fileChooseCtx->copyDestFileIndex], (sramCtx->readBuff + offset) + HEALTH,
sizeof(fileChooseCtx->health[0]));
osSyncPrintf("f_64dd[%d]=%d\n", gSaveContext.fileNum, fileChooseCtx->n64ddFlags[gSaveContext.fileNum]);
osSyncPrintf("heart_status[%d]=%d\n", gSaveContext.fileNum, fileChooseCtx->defense[gSaveContext.fileNum]);
osSyncPrintf("COPY終了\n"); // "Copy end"
}
/**
* Write the first 16 bytes of the read buffer to the SRAM header
*/
void Sram_WriteSramHeader(SramContext* sramCtx) {
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_HEADER_SIZE, OS_WRITE);
}
void Sram_InitSram(GameState* gameState, SramContext* sramCtx) {
u16 i;
osSyncPrintf("sram_initialize( Game *game, Sram *sram )\n");
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_READ);
for (i = 0; i < ARRAY_COUNTU(sZeldaMagic) - 3; i++) {
if (sZeldaMagic[i + SRAM_HEADER_MAGIC] != sramCtx->readBuff[i + SRAM_HEADER_MAGIC]) {
osSyncPrintf("SRAM破壊!!!!!!\n"); // "SRAM destruction! ! ! ! ! !"
gSaveContext.language = CVar_GetS32("gLanguages", 0);
memcpy(sramCtx->readBuff, sZeldaMagic, sizeof(sZeldaMagic));
sramCtx->readBuff[SRAM_HEADER_LANGUAGE] = gSaveContext.language;
Sram_WriteSramHeader(sramCtx);
}
}
gSaveContext.audioSetting = sramCtx->readBuff[SRAM_HEADER_SOUND] & 3;
gSaveContext.zTargetSetting = sramCtx->readBuff[SRAM_HEADER_ZTARGET] & 1;
gSaveContext.language = CVar_GetS32("gLanguages", 0);
if (gSaveContext.language >= LANGUAGE_MAX) {
gSaveContext.language = LANGUAGE_ENG;
sramCtx->readBuff[SRAM_HEADER_LANGUAGE] = gSaveContext.language;
Sram_WriteSramHeader(sramCtx);
}
if (CHECK_BTN_ANY(gameState->input[2].cur.button, BTN_DRIGHT)) {
memset(sramCtx->readBuff, 0,SRAM_SIZE);
for (i = 0; i < CHECKSUM_SIZE; i++) {
sramCtx->readBuff[i] = i;
}
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_WRITE);
osSyncPrintf("SRAM破壊!!!!!!\n"); // "SRAM destruction! ! ! ! ! !"
}
// "GOOD! GOOD! Size = %d + %d = %d"
osSyncPrintf(" サイズ=%d + %d %d\n", sizeof(SaveInfo), 4, sizeof(SaveInfo) + 4);
osSyncPrintf(VT_FGCOL(BLUE));
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);
osSyncPrintf(VT_RST);
func_800F6700(gSaveContext.audioSetting);
}
void Sram_Alloc(GameState* gameState, SramContext* sramCtx) {
sramCtx->readBuff = GameState_Alloc(gameState, SRAM_SIZE, "../z_sram.c", 1294);
ASSERT(sramCtx->readBuff != NULL, "sram->read_buff != NULL", "../z_sram.c", 1295);
}
void Sram_Init(GlobalContext* globalCtx, SramContext* sramCtx) {
}

View file

@ -58,38 +58,13 @@ void SsSram_Dma(void* dramAddr, size_t size, s32 direction) {
void SsSram_ReadWrite(uintptr_t addr, void* dramAddr, size_t size, s32 direction) {
osSyncPrintf("ssSRAMReadWrite:%08x %08x %08x %d\n", addr, (uintptr_t)dramAddr, size, direction);
//Check to see if the file exists
FILE* saveFile;
saveFile = fopen("oot_save.sav", "rb");
if (saveFile == NULL) {
saveFile = fopen("oot_save.sav", "wb");
fseek(saveFile, 0, SEEK_SET);
assert(saveFile != NULL); // OTRTODO LOG
uint8_t zero = 0;
for (uint32_t i = 0; i < SRAM_SIZE; i++) {
fwrite(&zero, 1, 1, saveFile);
}
fclose(saveFile);
} else {
fclose(saveFile);
}
switch (direction) {
case OS_WRITE: {
saveFile = fopen("oot_save.sav", "r+b");
rewind(saveFile);
fseek(saveFile, addr, SEEK_SET);
fwrite(dramAddr, size, 1, saveFile);
fclose(saveFile);
Ctx_WriteSaveFile(addr, dramAddr, size);
} break;
case OS_READ: {
saveFile = fopen("oot_save.sav", "rb+");
rewind(saveFile);
fseek(saveFile, addr, SEEK_SET);
fread(dramAddr, size, 1, saveFile);
fclose(saveFile);
Ctx_ReadSaveFile(addr, dramAddr, size);
} break;
}
//SsSram_Init(addr, DEVICE_TYPE_SRAM, PI_DOMAIN2, 5, 0xD, 2, 0xC, 0);

View file

@ -1209,19 +1209,15 @@ void BossGanon_ShatterWindows(u8 windowShatterState) {
}
void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx) {
const bool originalBlood = CVar_GetS32("gOriginalBlood", 1);
static Color_RGBA8 bloodPrimColor = { 0, 120, 0, 255 };
static Color_RGBA8 bloodEnvColor = { 0, 120, 0, 255 };
static Color_RGBA8 bloodPrimColor = { 120, 0, 0, 255 };
static Color_RGBA8 bloodEnvColor = { 120, 0, 0, 255 };
if(CVar_GetS32("gRedGanonBlood", 0)) {
bloodPrimColor.r = 120;
bloodPrimColor.g = 0;
if(!originalBlood) {
bloodPrimColor.r = 0;
bloodPrimColor.g = 120;
bloodPrimColor.b = 0;
bloodEnvColor.r = 0;
bloodEnvColor.g = 120;
bloodEnvColor.b = 0;
bloodEnvColor.r = 120;
bloodEnvColor.g = 0;
}
s16 i;

View file

@ -1456,6 +1456,17 @@ void func_80901020(BossGanon2* this, GlobalContext* globalCtx) {
void func_8090109C(BossGanon2* this, GlobalContext* globalCtx) {
u8 i;
static Color_RGBA8 sPrimColor = { 0, 120, 0, 255 };
static Color_RGBA8 sEnvColor = { 0, 120, 0, 255 };
if(CVar_GetS32("gRedGanonBlood", 0)) {
sPrimColor.r = 120;
sPrimColor.g = 0;
sEnvColor.r = 120;
sEnvColor.g = 0;
}
for (i = 0; i < 70; i++) {
Vec3f velocity;
Vec3f accel;

View file

@ -238,10 +238,6 @@ static ColliderJntSphInit sJntSphInit2 = {
sJntSphItemsInit2,
};
static Color_RGBA8 sPrimColor = { 0, 120, 0, 255 };
static Color_RGBA8 sEnvColor = { 0, 120, 0, 255 };
static Vec3f D_8090702C[] = {
{ 10.0f, -10.0f, 0.0f },
{ 0.0f, 0.0f, -60.0f },

View file

@ -110,7 +110,7 @@ void ElfMsg_Destroy(Actor* thisx, GlobalContext* globalCtx) {
s32 ElfMsg_GetMessageId(ElfMsg* this) {
// Negative message ID forces link to talk to Navi
if (this->actor.params & 0x8000) {
if (this->actor.params & 0x8000 || CVar_GetS32("gNoForcedNavi", 0) != 0) {
return (this->actor.params & 0xFF) + 0x100;
} else {
return -((this->actor.params & 0xFF) + 0x100);

View file

@ -118,7 +118,7 @@ void EnCow_Init(Actor* thisx, GlobalContext* globalCtx) {
func_809DEE9C(this);
this->actionFunc = func_809DF96C;
if (globalCtx->sceneNum == SCENE_LINK_HOME) {
if (!LINK_IS_ADULT) {
if (!LINK_IS_ADULT && !CVar_GetS32("gCowOfTime", 0)) {
Actor_Kill(&this->actor);
return;
}

View file

@ -452,7 +452,7 @@ s32 EnGirlA_CanBuy_DekuNuts(GlobalContext* globalCtx, EnGirlA* this) {
if (gSaveContext.rupees < this->basePrice) {
return CANBUY_RESULT_NEED_RUPEES;
}
if (Item_CheckObtainability(ITEM_NUT) == ITEM_NONE) {
if ((Item_CheckObtainability(ITEM_NUT) == ITEM_NONE) && !CVar_GetS32("gFastDrops", 0)) {
return CANBUY_RESULT_SUCCESS_FANFARE;
}
return CANBUY_RESULT_SUCCESS;
@ -465,7 +465,7 @@ s32 EnGirlA_CanBuy_DekuSticks(GlobalContext* globalCtx, EnGirlA* this) {
if (gSaveContext.rupees < this->basePrice) {
return CANBUY_RESULT_NEED_RUPEES;
}
if (Item_CheckObtainability(ITEM_STICK) == ITEM_NONE) {
if ((Item_CheckObtainability(ITEM_STICK) == ITEM_NONE) && !CVar_GetS32("gFastDrops", 0)) {
return CANBUY_RESULT_SUCCESS_FANFARE;
}
return CANBUY_RESULT_SUCCESS;
@ -652,7 +652,7 @@ s32 EnGirlA_CanBuy_DekuSeeds(GlobalContext* globalCtx, EnGirlA* this) {
if (gSaveContext.rupees < this->basePrice) {
return CANBUY_RESULT_NEED_RUPEES;
}
if (Item_CheckObtainability(ITEM_SEEDS) == ITEM_NONE) {
if ((Item_CheckObtainability(ITEM_SEEDS) == ITEM_NONE) && !CVar_GetS32("gFastDrops", 0)) {
return CANBUY_RESULT_SUCCESS_FANFARE;
}
return CANBUY_RESULT_SUCCESS;

View file

@ -29,7 +29,7 @@ void EnHeishi1_TurnTowardLink(EnHeishi1* this, GlobalContext* globalCtx);
void EnHeishi1_Kick(EnHeishi1* this, GlobalContext* globalCtx);
void EnHeishi1_WaitNight(EnHeishi1* this, GlobalContext* globalCtx);
static s32 sPlayerIsCaught = false;
s32 sHeishi1PlayerIsCaught = false;
const ActorInit En_Heishi1_InitVars = {
0,
@ -154,7 +154,7 @@ void EnHeishi1_Walk(EnHeishi1* this, GlobalContext* globalCtx) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_KNIGHT_WALK);
}
if (!sPlayerIsCaught) {
if (!sHeishi1PlayerIsCaught) {
path = &globalCtx->setupPathList[this->path];
pointPos = SEGMENTED_TO_VIRTUAL(path->points);
pointPos += this->waypoint;
@ -259,7 +259,7 @@ void EnHeishi1_Wait(EnHeishi1* this, GlobalContext* globalCtx) {
s32 i;
SkelAnime_Update(&this->skelAnime);
if (!sPlayerIsCaught) {
if (!sHeishi1PlayerIsCaught) {
switch (this->headBehaviorDecided) {
case false:
this->headDirection++;
@ -352,7 +352,7 @@ void EnHeishi1_Kick(EnHeishi1* this, GlobalContext* globalCtx) {
globalCtx->nextEntranceIndex = 0x4FA;
globalCtx->sceneLoadFlag = 0x14;
this->loadStarted = true;
sPlayerIsCaught = false;
sHeishi1PlayerIsCaught = false;
globalCtx->fadeTransition = 0x2E;
gSaveContext.nextTransition = 0x2E;
}
@ -413,7 +413,7 @@ void EnHeishi1_Update(Actor* thisx, GlobalContext* globalCtx) {
if (this->type != 5) {
path = this->path * 2;
if ((sCamDataIdxs[path] == activeCam->camDataIdx) || (sCamDataIdxs[path + 1] == activeCam->camDataIdx)) {
if (!sPlayerIsCaught) {
if (!sHeishi1PlayerIsCaught) {
if ((this->actionFunc == EnHeishi1_Walk) || (this->actionFunc == EnHeishi1_Wait)) {
Vec3f searchBallVel;
Vec3f searchBallAccel = { 0.0f, 0.0f, 0.0f };
@ -459,7 +459,7 @@ void EnHeishi1_Update(Actor* thisx, GlobalContext* globalCtx) {
// "Discovered!"
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 発見! ☆☆☆☆☆ \n" VT_RST);
func_8002DF54(globalCtx, &this->actor, 1);
sPlayerIsCaught = true;
sHeishi1PlayerIsCaught = true;
this->actionFunc = EnHeishi1_SetupMoveToLink;
}
}

View file

@ -1080,7 +1080,15 @@ void func_80A98DB4(EnKo* this, GlobalContext* globalCtx) {
dist = this->actor.xzDistToPlayer;
}
Math_SmoothStepToF(&this->modelAlpha, (this->appearDist < dist) ? 0.0f : 255.0f, 0.3f, 40.0f, 1.0f);
if (CVar_GetS32("gDisableKokiriDrawDistance", 0) != 0) {
this->appearDist = 32767.0f;
Math_SmoothStepToF(&this->modelAlpha, (this->appearDist < dist) ? 0.0f : 255.0f, 0.3f, 40.0f, 1.0f);
f32 test = this->appearDist;
} else {
this->appearDist = 180.0f;
Math_SmoothStepToF(&this->modelAlpha, (this->appearDist < dist) ? 0.0f : 255.0f, 0.3f, 40.0f, 1.0f);
}
if (this->modelAlpha < 10.0f) {
this->actor.flags &= ~ACTOR_FLAG_0;
} else {

View file

@ -613,10 +613,18 @@ void func_80AAB5A4(EnMd* this, GlobalContext* globalCtx) {
f32 temp;
if (globalCtx->sceneNum != SCENE_KOKIRI_HOME4) {
temp = (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !(gSaveContext.eventChkInf[1] & 0x1000) &&
(globalCtx->sceneNum == SCENE_SPOT04))
? 100.0f
: 400.0f;
if (CVar_GetS32("gDisableKokiriDrawDistance", 0) != 0) {
temp = (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !(gSaveContext.eventChkInf[1] & 0x1000) &&
(globalCtx->sceneNum == SCENE_SPOT04))
? 100.0f
: 32767.0f;
} else {
temp = (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && !(gSaveContext.eventChkInf[1] & 0x1000) &&
(globalCtx->sceneNum == SCENE_SPOT04))
? 100.0f
: 400.0f;
}
this->alpha = func_80034DD4(&this->actor, globalCtx, this->alpha, temp);
this->actor.shape.shadowAlpha = this->alpha;
} else {

View file

@ -727,7 +727,12 @@ void EnSa_Update(Actor* thisx, GlobalContext* globalCtx) {
}
if (this->actionFunc != func_80AF68E4) {
this->alpha = func_80034DD4(&this->actor, globalCtx, this->alpha, 400.0f);
if (CVar_GetS32("gDisableKokiriDrawDistance", 0) != 0) {
this->alpha = func_80034DD4(&this->actor, globalCtx, this->alpha, 32767);
}
else {
this->alpha = func_80034DD4(&this->actor, globalCtx, this->alpha, 400.0f);
}
} else {
this->alpha = 255;
}

View file

@ -94,7 +94,9 @@ void func_80AFB768(EnSi* this, GlobalContext* globalCtx) {
if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) {
this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER;
Item_Give(globalCtx, ITEM_SKULL_TOKEN);
player->actor.freezeTimer = 10;
if (CVar_GetS32("gSkulltulaFreeze", 0) != 1) {
player->actor.freezeTimer = 20;
}
Message_StartTextbox(globalCtx, 0xB4, NULL);
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
this->actionFunc = func_80AFB950;
@ -116,7 +118,6 @@ void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) {
if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_13)) {
Item_Give(globalCtx, ITEM_SKULL_TOKEN);
player->actor.freezeTimer = 10;
Message_StartTextbox(globalCtx, 0xB4, NULL);
Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET);
this->actionFunc = func_80AFB950;
@ -126,7 +127,7 @@ void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) {
void func_80AFB950(EnSi* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING) {
if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING && CVar_GetS32("gSkulltulaFreeze", 0) != 1) {
player->actor.freezeTimer = 10;
} else {
SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF);

View file

@ -9,6 +9,10 @@
#include "objects/object_tk/object_tk.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
#define COLLECTFLAG_GRAVEDIGGING_HEART_PIECE 0x19
#define ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE 0x1000
bool heartPieceSpawned;
void EnTk_Init(Actor* thisx, GlobalContext* globalCtx);
void EnTk_Destroy(Actor* thisx, GlobalContext* globalCtx);
@ -505,6 +509,7 @@ void EnTk_Init(Actor* thisx, GlobalContext* globalCtx) {
this->currentReward = -1;
this->currentSpot = NULL;
this->actionFunc = EnTk_Rest;
heartPieceSpawned = false;
}
void EnTk_Destroy(Actor* thisx, GlobalContext* globalCtx) {
@ -611,13 +616,23 @@ void EnTk_Dig(EnTk* this, GlobalContext* globalCtx) {
* Upgrade the purple rupee reward to the heart piece if this
* is the first grand prize dig.
*/
if (!(gSaveContext.itemGetInf[1] & 0x1000)) {
gSaveContext.itemGetInf[1] |= 0x1000;
// If vanilla itemGetInf flag is not set, it's impossible for the new flag to be set, so return true.
// Otherwise if the gGravediggingTourFix is enabled and the new flag hasn't been set, return true.
// If true, spawn the heart piece and set the vanilla itemGetInf flag and new temp clear flag.
if (!heartPieceSpawned &&
(!(gSaveContext.itemGetInf[1] & ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE) ||
CVar_GetS32("gGravediggingTourFix", 0) &&
!Flags_GetCollectible(globalCtx, COLLECTFLAG_GRAVEDIGGING_HEART_PIECE))) {
this->currentReward = 4;
gSaveContext.itemGetInf[1] |= ITEMGETINFFLAG_GRAVEDIGGING_HEART_PIECE;
heartPieceSpawned = true;
}
}
Item_DropCollectible(globalCtx, &rewardPos, rewardParams[this->currentReward]);
EnItem00* reward = Item_DropCollectible(globalCtx, &rewardPos, rewardParams[this->currentReward]);
if (this->currentReward == 4) {
reward->collectibleFlag = COLLECTFLAG_GRAVEDIGGING_HEART_PIECE;
}
}
}

View file

@ -140,8 +140,9 @@ void OceffStorm_Draw2(Actor* thisx, GlobalContext* globalCtx) {
gSPDisplayList(POLY_XLU_DISP++, sMaterialDL);
gSPDisplayList(POLY_XLU_DISP++, Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, scroll * 8, scroll * 4, 64, 64, 1,
scroll * 4, scroll * 4, 64, 64));
gSPTextureRectangle(POLY_XLU_DISP++, 0, 0, (SCREEN_WIDTH << 2), (SCREEN_HEIGHT << 2), G_TX_RENDERTILE, 0, 0, 140,
(1 << 15) | (31 << 10) | 884);
gSPWideTextureRectangle(POLY_XLU_DISP++, OTRGetRectDimensionFromLeftEdge(0) << 2, 0,
OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH) << 2, 0x03C0, G_TX_RENDERTILE, 0, 0, 0x008C,
-0x008C);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_oceff_storm.c", 477);
}

View file

@ -351,6 +351,7 @@ s32 func_80852F38(GlobalContext* globalCtx, Player* this);
s32 func_80852FFC(GlobalContext* globalCtx, Actor* actor, s32 csMode);
void func_80853080(Player* this, GlobalContext* globalCtx);
s32 Player_InflictDamage(GlobalContext* globalCtx, s32 damage);
s32 Player_InflictDamageModified(GlobalContext* globalCtx, s32 damage, u8 modified);
void func_80853148(GlobalContext* globalCtx, Actor* actor);
// .bss part 1
@ -2106,10 +2107,10 @@ LinkAnimationHeader* func_808346C4(GlobalContext* globalCtx, Player* this) {
func_808323B4(globalCtx, this);
if (this->unk_870 < 0.5f) {
return D_808543A4[Player_HoldsTwoHandedWeapon(this)];
return D_808543A4[Player_HoldsTwoHandedWeapon(this) && !(CVar_GetS32("gShieldTwoHanded", 0) && (this->heldItemActionParam != PLAYER_AP_STICK))];
}
else {
return D_808543AC[Player_HoldsTwoHandedWeapon(this)];
return D_808543AC[Player_HoldsTwoHandedWeapon(this) && !(CVar_GetS32("gShieldTwoHanded", 0) && (this->heldItemActionParam != PLAYER_AP_STICK))];
}
}
@ -2779,22 +2780,24 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) {
if (actionParam >= PLAYER_AP_BOOTS_KOKIRI) {
u16 bootsValue = actionParam - PLAYER_AP_BOOTS_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_BOOTS) == bootsValue) {
Inventory_ChangeEquipment(EQUIP_BOOTS, 1);
Inventory_ChangeEquipment(EQUIP_BOOTS, PLAYER_BOOTS_KOKIRI + 1);
} else {
Inventory_ChangeEquipment(EQUIP_BOOTS, bootsValue);
}
Player_SetEquipmentData(globalCtx, this);
func_808328EC(this, CUR_EQUIP_VALUE(EQUIP_BOOTS) == PLAYER_BOOTS_IRON + 1 ? NA_SE_PL_WALK_HEAVYBOOTS : NA_SE_PL_CHANGE_ARMS);
return;
}
if (actionParam >= PLAYER_AP_TUNIC_KOKIRI) {
u16 tunicValue = actionParam - PLAYER_AP_TUNIC_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == tunicValue) {
Inventory_ChangeEquipment(EQUIP_TUNIC, 1);
Inventory_ChangeEquipment(EQUIP_TUNIC, PLAYER_TUNIC_KOKIRI + 1);
} else {
Inventory_ChangeEquipment(EQUIP_TUNIC, tunicValue);
}
Player_SetEquipmentData(globalCtx, this);
func_808328EC(this, NA_SE_PL_CHANGE_ARMS);
return;
}
@ -3514,12 +3517,22 @@ void func_80837AFC(Player* this, s32 timer) {
this->unk_88F = 0;
}
s32 func_80837B18(GlobalContext* globalCtx, Player* this, s32 damage) {
s32 func_80837B18_modified(GlobalContext* globalCtx, Player* this, s32 damage, u8 modified) {
if ((this->invincibilityTimer != 0) || (this->actor.category != ACTORCAT_PLAYER)) {
return 1;
}
return Health_ChangeBy(globalCtx, damage);
s32 modifiedDamage = damage;
if (modified)
{
modifiedDamage *= CVar_GetS32("gDamageMul", 1);
}
return Health_ChangeBy(globalCtx, modifiedDamage);
}
s32 func_80837B18(GlobalContext* globalCtx, Player* this, s32 damage) {
return func_80837B18_modified(globalCtx, this, damage, true);
}
void func_80837B60(Player* this) {
@ -3707,7 +3720,7 @@ s32 func_8083816C(s32 arg0) {
}
void func_8083819C(Player* this, GlobalContext* globalCtx) {
if (this->currentShield == PLAYER_SHIELD_DEKU) {
if (this->currentShield == PLAYER_SHIELD_DEKU && (CVar_GetS32("gFireproofDekuShield", 0) == 0)) {
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_ITEM_SHIELD, this->actor.world.pos.x,
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 1);
Inventory_DeleteEquipment(globalCtx, EQUIP_SHIELD);
@ -3745,7 +3758,7 @@ s32 func_808382DC(Player* this, GlobalContext* globalCtx) {
if (this->unk_A86 != 0) {
if (!Player_InBlockingCsMode(globalCtx, this)) {
Player_InflictDamage(globalCtx, -16);
Player_InflictDamageModified(globalCtx, -16 * CVar_GetS32("gVoidDamageMul", 1), false);
this->unk_A86 = 0;
}
}
@ -5468,8 +5481,8 @@ s32 func_8083C6B8(GlobalContext* globalCtx, Player* this) {
sp24 = this->actor.world.pos;
sp24.y += 50.0f;
if (!(this->actor.bgCheckFlags & 1) || (this->actor.world.pos.z > 1300.0f) ||
BgCheck_SphVsFirstPoly(&globalCtx->colCtx, &sp24, 20.0f)) {
if (CVar_GetS32("gHoverFishing", 0) ? 0 : !(this->actor.bgCheckFlags & 1) ||
(this->actor.world.pos.z > 1300.0f) || BgCheck_SphVsFirstPoly(&globalCtx->colCtx, &sp24, 20.0f)) {
func_80078884(NA_SE_SY_ERROR);
return 0;
}
@ -6155,7 +6168,12 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) {
iREG(67) = false;
if ((Item_CheckObtainability(giEntry->itemId) == ITEM_NONE) || (globalCtx->sceneNum == SCENE_BOWLING)) {
s32 drop = giEntry->objectId;
if ((globalCtx->sceneNum == SCENE_BOWLING) || !(CVar_GetS32("gFastDrops", 0) &&
((drop == OBJECT_GI_BOMB_1) || (drop == OBJECT_GI_NUTS) || (drop == OBJECT_GI_STICK) ||
(drop == OBJECT_GI_SEED) || (drop == OBJECT_GI_MAGICPOT) || (drop == OBJECT_GI_ARROW))) &&
(Item_CheckObtainability(giEntry->itemId) == ITEM_NONE)) {
func_808323B4(globalCtx, this);
func_8083AE40(this, giEntry->objectId);
@ -6179,6 +6197,9 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) {
if (this->getItemId != GI_NONE) {
GetItemEntry* giEntry = &sGetItemTable[-this->getItemId - 1];
EnBox* chest = (EnBox*)interactedActor;
if(CVar_GetS32("gFastChests", 0) != 0) {
giEntry->gi = -1 * abs(giEntry->gi);
}
if (giEntry->itemId != ITEM_NONE) {
if (((Item_CheckObtainability(giEntry->itemId) == ITEM_NONE) && (giEntry->field & 0x40)) ||
@ -8274,7 +8295,7 @@ s32 func_80843E64(GlobalContext* globalCtx, Player* this) {
impactInfo = &D_80854600[impactIndex];
if (Player_InflictDamage(globalCtx, impactInfo->damage)) {
if (Player_InflictDamageModified(globalCtx, impactInfo->damage * CVar_GetS32("gFallDamageMul", 1), false)) {
return -1;
}
@ -11621,7 +11642,7 @@ void func_8084BF1C(Player* this, GlobalContext* globalCtx) {
phi_f2 = -1.0f;
}
this->skelAnime.playSpeed = phi_f2 * phi_f0;
this->skelAnime.playSpeed = phi_f2 * phi_f0 + phi_f2 * CVar_GetS32("gClimbSpeed", 0);
if (this->unk_850 >= 0) {
if ((this->actor.wallPoly != NULL) && (this->actor.wallBgId != BGCHECK_SCENE)) {
@ -14824,9 +14845,13 @@ void func_80853080(Player* this, GlobalContext* globalCtx) {
}
s32 Player_InflictDamage(GlobalContext* globalCtx, s32 damage) {
return Player_InflictDamageModified(globalCtx, damage, true);
}
s32 Player_InflictDamageModified(GlobalContext* globalCtx, s32 damage, u8 modified) {
Player* this = GET_PLAYER(globalCtx);
if (!Player_InBlockingCsMode(globalCtx, this) && !func_80837B18(globalCtx, this, damage)) {
if (!Player_InBlockingCsMode(globalCtx, this) && !func_80837B18_modified(globalCtx, this, damage, modified)) {
this->stateFlags2 &= ~PLAYER_STATE2_7;
return 1;
}

View file

@ -5,11 +5,14 @@
*/
#include "z_eff_ss_solder_srch_ball.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include <math.h>
#define rUnused regs[1]
u32 EffectSsSolderSrchBall_Init(GlobalContext* globalCtx, u32 index, EffectSs* this, void* initParamsx);
void EffectSsSolderSrchBall_Update(GlobalContext* globalCtx, u32 index, EffectSs* this);
void EffectSsSolderSrchBall_Draw(GlobalContext* globalCtx, u32 index, EffectSs* this);
EffectSsInit Effect_Ss_Solder_Srch_Ball_InitVars = {
EFFECT_SS_SOLDER_SRCH_BALL,
@ -23,6 +26,7 @@ u32 EffectSsSolderSrchBall_Init(GlobalContext* globalCtx, u32 index, EffectSs* t
this->velocity = initParams->velocity;
this->accel = initParams->accel;
this->update = EffectSsSolderSrchBall_Update;
this->draw = EffectSsSolderSrchBall_Draw;
this->life = 100;
this->rUnused = initParams->unused;
this->actor = initParams->linkDetected; // actor field was incorrectly used as a pointer to something else
@ -53,3 +57,198 @@ void EffectSsSolderSrchBall_Update(GlobalContext* globalCtx, u32 index, EffectSs
}
}
}
static void vtxn_f2l(Vtx* r, Vec3f* v) {
r->n.ob[0] = floorf(0.5f + v->x * 128.f);
r->n.ob[1] = floorf(0.5f + v->y * 128.f);
r->n.ob[2] = floorf(0.5f + v->z * 128.f);
r->n.flag = 0;
r->n.tc[0] = 0;
r->n.tc[1] = 0;
r->n.n[0] = v->x * 127.f;
r->n.n[1] = v->y * 127.f;
r->n.n[2] = v->z * 127.f;
r->n.a = 0xFF;
}
static void ico_sph_subdivide_edge(Vec3f* r, Vec3f* a, Vec3f* b) {
Math_Vec3f_Sum(a, b, r);
Math_Vec3f_Scale(r, (1.0f / Math3D_Vec3fMagnitude(r)));
}
static void draw_ico_sphere(Gfx** p_gfx_p, f32 x, f32 y, f32 z, f32 radius, GraphicsContext* gfxCtx) {
static Gfx* p_sph_gfx = NULL;
static Vtx sph_vtx[42];
static Gfx sph_gfx[45];
Gfx* sph_gfx_p;
s32 i;
if (!p_sph_gfx) {
Vec3f vtx[42];
s32 r0_n = 1, r0_m = r0_n / 5, r0_i = 0 + 0;
s32 r1_n = 5, r1_m = r1_n / 5, r1_i = r0_i + r0_n;
s32 r2_n = 10, r2_m = r2_n / 5, r2_i = r1_i + r1_n;
s32 r3_n = 10, r3_m = r3_n / 5, r3_i = r2_i + r2_n;
s32 r4_n = 10, r4_m = r4_n / 5, r4_i = r3_i + r3_n;
s32 r5_n = 5, r5_m = r5_n / 5, r5_i = r4_i + r4_n;
s32 r6_n = 1, r6_m = r6_n / 5, r6_i = r5_i + r5_n;
vtx[r0_i + (0 * r0_m + 0) % r0_n].x = 0.0f;
vtx[r0_i + (0 * r0_m + 0) % r0_n].y = 1.0f;
vtx[r0_i + (0 * r0_m + 0) % r0_n].z = 0.0f;
vtx[r6_i + (0 * r6_m + 0) % r6_n].x = 0.0f;
vtx[r6_i + (0 * r6_m + 0) % r6_n].y = -1.0f;
vtx[r6_i + (0 * r6_m + 0) % r6_n].z = 0.0f;
for (i = 0; i < 5; ++i) {
f32 a_xz = 2.f * M_PI / 10.f;
f32 a_y = atanf(1.0f / 2.0f);
vtx[r2_i + (i * r2_m + 0) % r2_n].x = cosf(a_xz * (i * r2_m + 0)) * cosf(a_y * 1.f);
vtx[r2_i + (i * r2_m + 0) % r2_n].y = sinf(a_y * 1.f);
vtx[r2_i + (i * r2_m + 0) % r2_n].z = -sinf(a_xz * (i * r2_m + 0)) * cosf(a_y * 1.f);
vtx[r4_i + (i * r4_m + 0) % r4_n].x = cosf(a_xz * (i * r4_m + 1)) * cosf(a_y * -1.f);
vtx[r4_i + (i * r4_m + 0) % r4_n].y = sinf(a_y * -1.f);
vtx[r4_i + (i * r4_m + 0) % r4_n].z = -sinf(a_xz * (i * r4_m + 1)) * cosf(a_y * -1.f);
}
for (i = 0; i < 5; ++i) {
ico_sph_subdivide_edge(&vtx[r1_i + (i * r1_m + 0) % r1_n], &vtx[r0_i + (i * r0_m + 0) % r0_n],
&vtx[r2_i + (i * r2_m + 0) % r2_n]);
ico_sph_subdivide_edge(&vtx[r2_i + (i * r2_m + 1) % r2_n], &vtx[r2_i + (i * r2_m + 0) % r2_n],
&vtx[r2_i + (i * r2_m + 2) % r2_n]);
ico_sph_subdivide_edge(&vtx[r3_i + (i * r3_m + 0) % r3_n], &vtx[r2_i + (i * r2_m + 0) % r2_n],
&vtx[r4_i + (i * r4_m + 0) % r4_n]);
ico_sph_subdivide_edge(&vtx[r3_i + (i * r3_m + 1) % r3_n], &vtx[r4_i + (i * r4_m + 0) % r4_n],
&vtx[r2_i + (i * r2_m + 2) % r2_n]);
ico_sph_subdivide_edge(&vtx[r4_i + (i * r4_m + 1) % r4_n], &vtx[r4_i + (i * r4_m + 0) % r4_n],
&vtx[r4_i + (i * r4_m + 2) % r4_n]);
ico_sph_subdivide_edge(&vtx[r5_i + (i * r5_m + 0) % r5_n], &vtx[r4_i + (i * r4_m + 0) % r4_n],
&vtx[r6_i + (i * r6_m + 0) % r6_n]);
}
for (i = 0; i < 42; ++i)
vtxn_f2l(&sph_vtx[i], &vtx[i]);
p_sph_gfx = sph_gfx;
sph_gfx_p = p_sph_gfx;
gSPSetGeometryMode(sph_gfx_p++, G_CULL_BACK | G_SHADING_SMOOTH);
gSPVertex(sph_gfx_p++, &sph_vtx[r0_i], r0_n + r1_n + r2_n + r3_n, r0_i - r0_i);
r3_i -= r0_i;
r2_i -= r0_i;
r1_i -= r0_i;
r0_i -= r0_i;
for (i = 0; i < 5; ++i) {
s32 v[24];
v[0] = r0_i + (i * r0_m + 0) % r0_n;
v[1] = r1_i + (i * r1_m + 0) % r1_n;
v[2] = r1_i + (i * r1_m + 1) % r1_n;
v[3] = r1_i + (i * r1_m + 0) % r1_n;
v[4] = r2_i + (i * r2_m + 0) % r2_n;
v[5] = r2_i + (i * r2_m + 1) % r2_n;
v[6] = r1_i + (i * r1_m + 0) % r1_n;
v[7] = r2_i + (i * r2_m + 1) % r2_n;
v[8] = r1_i + (i * r1_m + 1) % r1_n;
v[9] = r1_i + (i * r1_m + 1) % r1_n;
v[10] = r2_i + (i * r2_m + 1) % r2_n;
v[11] = r2_i + (i * r2_m + 2) % r2_n;
v[12] = r2_i + (i * r2_m + 0) % r2_n;
v[13] = r3_i + (i * r3_m + 0) % r3_n;
v[14] = r2_i + (i * r2_m + 1) % r2_n;
v[15] = r2_i + (i * r2_m + 1) % r2_n;
v[16] = r3_i + (i * r3_m + 0) % r3_n;
v[17] = r3_i + (i * r3_m + 1) % r3_n;
v[18] = r2_i + (i * r2_m + 1) % r2_n;
v[19] = r3_i + (i * r3_m + 1) % r3_n;
v[20] = r2_i + (i * r2_m + 2) % r2_n;
v[21] = r2_i + (i * r2_m + 2) % r2_n;
v[22] = r3_i + (i * r3_m + 1) % r3_n;
v[23] = r3_i + (i * r3_m + 2) % r3_n;
gSP2Triangles(sph_gfx_p++, v[0], v[1], v[2], 0, v[3], v[4], v[5], 0);
gSP2Triangles(sph_gfx_p++, v[6], v[7], v[8], 0, v[9], v[10], v[11], 0);
gSP2Triangles(sph_gfx_p++, v[12], v[13], v[14], 0, v[15], v[16], v[17], 0);
gSP2Triangles(sph_gfx_p++, v[18], v[19], v[20], 0, v[21], v[22], v[23], 0);
}
gSPVertex(sph_gfx_p++, &sph_vtx[r4_i], r4_n + r5_n + r6_n, r4_i - r4_i);
r6_i -= r4_i;
r5_i -= r4_i;
r4_i -= r4_i;
for (i = 0; i < 5; ++i) {
s32 v[24];
v[0] = r3_i + (i * r3_m + 1) % r3_n;
v[1] = r4_i + (i * r4_m + 0) % r4_n;
v[2] = r4_i + (i * r4_m + 1) % r4_n;
v[3] = r3_i + (i * r3_m + 1) % r3_n;
v[4] = r4_i + (i * r4_m + 1) % r4_n;
v[5] = r3_i + (i * r3_m + 2) % r3_n;
v[6] = r3_i + (i * r3_m + 2) % r3_n;
v[7] = r4_i + (i * r4_m + 1) % r4_n;
v[8] = r4_i + (i * r4_m + 2) % r4_n;
v[9] = r3_i + (i * r3_m + 2) % r3_n;
v[10] = r4_i + (i * r4_m + 2) % r4_n;
v[11] = r3_i + (i * r3_m + 3) % r3_n;
v[12] = r4_i + (i * r4_m + 0) % r4_n;
v[13] = r5_i + (i * r5_m + 0) % r5_n;
v[14] = r4_i + (i * r4_m + 1) % r4_n;
v[15] = r4_i + (i * r4_m + 1) % r4_n;
v[16] = r5_i + (i * r5_m + 0) % r5_n;
v[17] = r5_i + (i * r5_m + 1) % r5_n;
v[18] = r4_i + (i * r4_m + 1) % r4_n;
v[19] = r5_i + (i * r5_m + 1) % r5_n;
v[20] = r4_i + (i * r4_m + 2) % r4_n;
v[21] = r5_i + (i * r5_m + 0) % r5_n;
v[22] = r6_i + (i * r6_m + 0) % r6_n;
v[23] = r5_i + (i * r5_m + 1) % r5_n;
gSP2Triangles(sph_gfx_p++, v[0], v[1], v[2], 0, v[3], v[4], v[5], 0);
gSP2Triangles(sph_gfx_p++, v[6], v[7], v[8], 0, v[9], v[10], v[11], 0);
gSP2Triangles(sph_gfx_p++, v[12], v[13], v[14], 0, v[15], v[16], v[17], 0);
gSP2Triangles(sph_gfx_p++, v[18], v[19], v[20], 0, v[21], v[22], v[23], 0);
}
gSPClearGeometryMode(sph_gfx_p++, G_CULL_BACK | G_SHADING_SMOOTH);
gSPEndDisplayList(sph_gfx_p++);
}
Matrix_Push();
Matrix_Translate(x, y, z, MTXMODE_NEW);
Matrix_Scale(radius / 128.0f, radius / 128.0f, radius / 128.0f, MTXMODE_APPLY);
gSPMatrix((*p_gfx_p)++, Matrix_NewMtx(gfxCtx, __FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH);
gSPDisplayList((*p_gfx_p)++, p_sph_gfx);
gSPPopMatrix((*p_gfx_p)++, G_MTX_MODELVIEW);
Matrix_Pop();
}
void EffectSsSolderSrchBall_Draw(GlobalContext* globalCtx, u32 index, EffectSs* this) {
if (CVar_GetS32("gGuardVision", 0) == 0) {
return;
}
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
u32 rm;
u32 blc1;
u32 blc2;
s16* seenLink = this->actor;
OPEN_DISPS(globalCtx->state.gfxCtx, __FILE__, __LINE__);
rm = Z_CMP | IM_RD | CVG_DST_FULL | FORCE_BL | ZMODE_XLU;
blc1 = GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA);
blc2 = GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA);
gSPLoadGeometryMode(POLY_XLU_DISP++, G_ZBUFFER | G_SHADE | G_LIGHTING);
gSPTexture(POLY_XLU_DISP++, 0, 0, 0, G_TX_RENDERTILE, G_OFF);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetCycleType(POLY_XLU_DISP++, G_CYC_1CYCLE);
gDPSetRenderMode(POLY_XLU_DISP++, rm | blc1, rm | blc2);
gDPSetCombineLERP(POLY_XLU_DISP++, PRIMITIVE, 0, SHADE, 0, 0, 0, 0, ENVIRONMENT, PRIMITIVE, 0, SHADE, 0, 0, 0,
0, ENVIRONMENT);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255);
if (*seenLink) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 0, 0, 255);
}
draw_ico_sphere(&POLY_XLU_DISP, this->pos.x, this->pos.y, this->pos.z, 30.0f, gfxCtx);
CLOSE_DISPS(globalCtx->state.gfxCtx, __FILE__, __LINE__);
}

View file

@ -5,17 +5,6 @@
#include "global.h"
#include "vt.h"
#define GET_NEWF(sramCtx, slotNum, index) (sramCtx->readBuff[gSramSlotOffsets[slotNum] + OFFSETOF(SaveContext, newf[index])])
#define SLOT_OCCUPIED(sramCtx, slotNum) \
((GET_NEWF(sramCtx, slotNum, 0) == 'Z') || \
(GET_NEWF(sramCtx, slotNum, 1) == 'E') || \
(GET_NEWF(sramCtx, slotNum, 2) == 'L') || \
(GET_NEWF(sramCtx, slotNum, 3) == 'D') || \
(GET_NEWF(sramCtx, slotNum, 4) == 'A') || \
(GET_NEWF(sramCtx, slotNum, 5) == 'Z'))
// Init mode: Initial setup as the file select is starting up, fades and slides in various menu elements
// Config mode: Handles the bulk of the file select, various configuration tasks like picking a file, copy/erase, and the options menu
// Select mode: Displays the selected file with various details about it, and allows the player to confirm and open it

View file

@ -64,9 +64,6 @@ void FileChoose_InitModeUpdate(GameState* thisx) {
this->menuMode = FS_MENU_MODE_CONFIG;
this->configMode = CM_FADE_IN_START;
this->nextTitleLabel = FS_TITLE_OPEN_FILE;
osSyncPrintf(" Start─Load 》》》》》 ");
Sram_VerifyAndLoadAllSaves(this, &this->sramCtx);
osSyncPrintf("終了!!!\n");
}
}
@ -80,7 +77,6 @@ void FileChoose_InitModeDraw(GameState* thisx) {
*/
void FileChoose_FadeInMenuElements(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
this->titleAlpha[0] += VREG(1);
@ -89,7 +85,7 @@ void FileChoose_FadeInMenuElements(GameState* thisx) {
for (i = 0; i < 3; i++) {
this->fileButtonAlpha[i] = this->windowAlpha;
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->windowAlpha;
this->connectorAlpha[i] += VREG(1);
if (this->connectorAlpha[i] >= 255) {
@ -176,18 +172,12 @@ void FileChoose_FinishFadeIn(GameState* thisx) {
void FileChoose_UpdateMainMenu(GameState* thisx) {
static u8 emptyName[] = { 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E };
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
Input* input = &this->state.input[0];
bool dpad = CVar_GetS32("gDpadPauseName", 0);
if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_A)) {
if (this->buttonIndex <= FS_BTN_MAIN_FILE_3) {
osSyncPrintf("REGCK_ALL[%x]=%x,%x,%x,%x,%x,%x\n", this->buttonIndex,
GET_NEWF(sramCtx, this->buttonIndex, 0), GET_NEWF(sramCtx, this->buttonIndex, 1),
GET_NEWF(sramCtx, this->buttonIndex, 2), GET_NEWF(sramCtx, this->buttonIndex, 3),
GET_NEWF(sramCtx, this->buttonIndex, 4), GET_NEWF(sramCtx, this->buttonIndex, 5));
if (!SLOT_OCCUPIED(sramCtx, this->buttonIndex)) {
if (!Save_GetSaveMetaInfo(this->buttonIndex)->valid) {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
this->configMode = CM_ROTATE_TO_NAME_ENTRY;
this->kbdButton = FS_KBD_BTN_NONE;
@ -199,16 +189,14 @@ void FileChoose_UpdateMainMenu(GameState* thisx) {
this->newFileNameCharCount = 0;
this->nameEntryBoxPosX = 120;
this->nameEntryBoxAlpha = 0;
memcpy(&this->fileNames[this->buttonIndex][0], &emptyName, 8);
} else if (this->n64ddFlags[this->buttonIndex] == this->n64ddFlag) {
memcpy(Save_GetSaveMetaInfo(this->buttonIndex)->playerName, &emptyName, 8);
} else {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
this->actionTimer = 8;
this->selectMode = SM_FADE_MAIN_TO_SELECT;
this->selectedFileIndex = this->buttonIndex;
this->menuMode = FS_MENU_MODE_SELECT;
this->nextTitleLabel = FS_TITLE_OPEN_FILE;
} else if (!this->n64ddFlags[this->buttonIndex]) {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
}
} else {
if (this->warningLabel == FS_WARNING_NONE) {
@ -254,11 +242,12 @@ void FileChoose_UpdateMainMenu(GameState* thisx) {
}
if (this->buttonIndex == FS_BTN_MAIN_COPY) {
if (!SLOT_OCCUPIED(sramCtx, 0) && !SLOT_OCCUPIED(sramCtx, 1) && !SLOT_OCCUPIED(sramCtx, 2)) {
if (!Save_GetSaveMetaInfo(0)->valid && !Save_GetSaveMetaInfo(1)->valid && !Save_GetSaveMetaInfo(2)->valid) {
this->warningButtonIndex = this->buttonIndex;
this->warningLabel = FS_WARNING_NO_FILE_COPY;
this->emptyFileTextAlpha = 255;
} else if (SLOT_OCCUPIED(sramCtx, 0) && SLOT_OCCUPIED(sramCtx, 1) && SLOT_OCCUPIED(sramCtx, 2)) {
} else if (Save_GetSaveMetaInfo(0)->valid && Save_GetSaveMetaInfo(1)->valid &&
Save_GetSaveMetaInfo(2)->valid) {
this->warningButtonIndex = this->buttonIndex;
this->warningLabel = FS_WARNING_NO_EMPTY_FILES;
this->emptyFileTextAlpha = 255;
@ -266,7 +255,7 @@ void FileChoose_UpdateMainMenu(GameState* thisx) {
this->warningLabel = FS_WARNING_NONE;
}
} else if (this->buttonIndex == FS_BTN_MAIN_ERASE) {
if (!SLOT_OCCUPIED(sramCtx, 0) && !SLOT_OCCUPIED(sramCtx, 1) && !SLOT_OCCUPIED(sramCtx, 2)) {
if (!Save_GetSaveMetaInfo(0)->valid && !Save_GetSaveMetaInfo(1)->valid && !Save_GetSaveMetaInfo(2)->valid) {
this->warningButtonIndex = this->buttonIndex;
this->warningLabel = FS_WARNING_NO_FILE_ERASE;
this->emptyFileTextAlpha = 255;
@ -379,48 +368,6 @@ void FileChoose_PulsateCursor(GameState* thisx) {
static s16 cursorAlphaTargets[] = { 70, 200 };
FileChooseContext* this = (FileChooseContext*)thisx;
s16 alphaStep;
SramContext* sramCtx = &this->sramCtx;
Input* debugInput = &this->state.input[2];
if (CHECK_BTN_ALL(debugInput->press.button, BTN_DLEFT)) {
sramCtx->readBuff[SRAM_HEADER_LANGUAGE] = gSaveContext.language = LANGUAGE_ENG;
*((u8*)0x80000002) = LANGUAGE_ENG;
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, 3, OS_WRITE);
osSyncPrintf("1:read_buff[]=%x, %x, %x, %x\n", sramCtx->readBuff[SRAM_HEADER_SOUND],
sramCtx->readBuff[SRAM_HEADER_ZTARGET], sramCtx->readBuff[SRAM_HEADER_LANGUAGE],
sramCtx->readBuff[SRAM_HEADER_MAGIC]);
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_READ);
osSyncPrintf("read_buff[]=%x, %x, %x, %x\n", sramCtx->readBuff[SRAM_HEADER_SOUND],
sramCtx->readBuff[SRAM_HEADER_ZTARGET], sramCtx->readBuff[SRAM_HEADER_LANGUAGE],
sramCtx->readBuff[SRAM_HEADER_MAGIC]);
} else if (CHECK_BTN_ALL(debugInput->press.button, BTN_DUP)) {
sramCtx->readBuff[SRAM_HEADER_LANGUAGE] = gSaveContext.language = LANGUAGE_GER;
*((u8*)0x80000002) = LANGUAGE_GER;
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, 3, OS_WRITE);
osSyncPrintf("1:read_buff[]=%x, %x, %x, %x\n", sramCtx->readBuff[SRAM_HEADER_SOUND],
sramCtx->readBuff[SRAM_HEADER_ZTARGET], sramCtx->readBuff[SRAM_HEADER_LANGUAGE],
sramCtx->readBuff[SRAM_HEADER_MAGIC]);
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_READ);
osSyncPrintf("read_buff[]=%x, %x, %x, %x\n", sramCtx->readBuff[SRAM_HEADER_SOUND],
sramCtx->readBuff[SRAM_HEADER_ZTARGET], sramCtx->readBuff[SRAM_HEADER_LANGUAGE],
sramCtx->readBuff[SRAM_HEADER_MAGIC]);
} else if (CHECK_BTN_ALL(debugInput->press.button, BTN_DRIGHT)) {
sramCtx->readBuff[SRAM_HEADER_LANGUAGE] = gSaveContext.language = LANGUAGE_FRA;
*((u8*)0x80000002) = LANGUAGE_FRA;
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, 3, OS_WRITE);
osSyncPrintf("1:read_buff[]=%x, %x, %x, %x\n", sramCtx->readBuff[SRAM_HEADER_SOUND],
sramCtx->readBuff[SRAM_HEADER_ZTARGET], sramCtx->readBuff[SRAM_HEADER_LANGUAGE],
sramCtx->readBuff[SRAM_HEADER_MAGIC]);
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_READ);
osSyncPrintf("read_buff[]=%x, %x, %x, %x\n", sramCtx->readBuff[SRAM_HEADER_SOUND],
sramCtx->readBuff[SRAM_HEADER_ZTARGET], sramCtx->readBuff[SRAM_HEADER_LANGUAGE],
sramCtx->readBuff[SRAM_HEADER_MAGIC]);
}
alphaStep = ABS(this->highlightColor[3] - cursorAlphaTargets[this->highlightPulseDir]) / XREG(35);
@ -510,7 +457,6 @@ void FileChoose_SetWindowContentVtx(GameState* thisx) {
s16 phi_a1;
s16 phi_ra;
s16 temp_t1;
SramContext* sramCtx = &this->sramCtx;
this->windowContentVtx = Graph_Alloc(this->state.gfxCtx, 0x288 * sizeof(Vtx));
@ -648,7 +594,7 @@ void FileChoose_SetWindowContentVtx(GameState* thisx) {
phi_ra = 0x2C;
for (phi_t5 = 0; phi_t5 < 3; phi_t5++, phi_ra -= WREG(38)) {
if (SLOT_OCCUPIED(sramCtx, phi_t5)) {
if (Save_GetSaveMetaInfo(phi_t5)->valid) {
phi_t0 = this->windowPosX - WREG(39);
if ((this->configMode == 0xF) && (phi_t5 == this->copyDestFileIndex)) {
@ -822,8 +768,9 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
sNamePrimColors[isActive][2], this->nameAlpha[fileIndex]);
for (i = 0, vtxOffset = 0; vtxOffset < 0x20; i++, vtxOffset += 4) {
FileChoose_DrawCharacter(this->state.gfxCtx,
sp54->fontBuf + this->fileNames[fileIndex][i] * FONT_CHAR_TEX_SIZE, vtxOffset);
FileChoose_DrawCharacter(
this->state.gfxCtx, sp54->fontBuf + Save_GetSaveMetaInfo(fileIndex)->playerName[i] * FONT_CHAR_TEX_SIZE,
vtxOffset);
}
}
@ -834,7 +781,8 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->fileInfoAlpha[fileIndex]);
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex]] + 0x24, 12, 0);
FileChoose_SplitNumber(this->deaths[fileIndex], &deathCountSplit[0], &deathCountSplit[1], &deathCountSplit[2]);
FileChoose_SplitNumber(Save_GetSaveMetaInfo(fileIndex)->deaths, &deathCountSplit[0], &deathCountSplit[1],
&deathCountSplit[2]);
// draw death count
for (i = 0, vtxOffset = 0; i < 3; i++, vtxOffset += 4) {
@ -844,7 +792,7 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
gDPPipeSync(POLY_OPA_DISP++);
heartType = (this->defense[fileIndex] == 0) ? 0 : 1;
heartType = (Save_GetSaveMetaInfo(fileIndex)->defense == 0) ? 0 : 1;
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
@ -854,7 +802,7 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
gDPSetEnvColor(POLY_OPA_DISP++, sHeartEnvColors[heartType][0], sHeartEnvColors[heartType][1],
sHeartEnvColors[heartType][2], 255);
i = this->healthCapacities[fileIndex] / 0x10;
i = Save_GetSaveMetaInfo(fileIndex)->healthCapacity / 0x10;
// draw hearts
for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) {
@ -867,7 +815,7 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
// draw quest items
for (vtxOffset = 0, j = 0; j < 9; j++, vtxOffset += 4) {
if (this->questItems[fileIndex] & gBitFlags[sQuestItemFlags[j]]) {
if (Save_GetSaveMetaInfo(fileIndex)->questItems & gBitFlags[sQuestItemFlags[j]]) {
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x80, 4, 0);
gDPPipeSync(POLY_OPA_DISP++);
gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, sQuestItemRed[j], sQuestItemGreen[j], sQuestItemBlue[j],
@ -976,8 +924,14 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
// draw file info box (large box when a file is selected)
for (fileIndex = 0; fileIndex < 3; fileIndex++, temp += 20) {
gDPPipeSync(POLY_OPA_DISP++);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->fileInfoAlpha[fileIndex]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->fileInfoAlpha[fileIndex]);
}
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[temp], 20, 0);
for (quadVtxIndex = 0, i = 0; i < 5; i++, quadVtxIndex += 4) {
@ -992,27 +946,46 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
// draw file button
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[temp], 20, 0);
isActive = ((this->n64ddFlag == this->n64ddFlags[i]) || (this->nameBoxAlpha[i] == 0)) ? 0 : 1;
isActive = ((this->n64ddFlag == Save_GetSaveMetaInfo(i)->n64ddFlag) || (this->nameBoxAlpha[i] == 0)) ? 0 : 1;
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->fileButtonAlpha[i]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[isActive][0], sWindowContentColors[isActive][1],
sWindowContentColors[isActive][2], this->fileButtonAlpha[i]);
}
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[isActive][0], sWindowContentColors[isActive][1],
sWindowContentColors[isActive][2], this->fileButtonAlpha[i]);
gDPLoadTextureBlock(POLY_OPA_DISP++, sFileButtonTextures[gSaveContext.language][i], G_IM_FMT_IA, G_IM_SIZ_16b,
64, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
// draw file name box
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[isActive][0], sWindowContentColors[isActive][1],
sWindowContentColors[isActive][2], this->nameBoxAlpha[i]);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->nameBoxAlpha[i]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[isActive][0], sWindowContentColors[isActive][1],
sWindowContentColors[isActive][2], this->nameBoxAlpha[i]);
}
gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelNameBoxTex, G_IM_FMT_IA, G_IM_SIZ_16b, 108, 16, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOLOD);
gSP1Quadrangle(POLY_OPA_DISP++, 4, 6, 7, 5, 0);
// draw disk label for 64DD
if (this->n64ddFlags[i]) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[isActive][0], sWindowContentColors[isActive][1],
sWindowContentColors[isActive][2], this->nameAlpha[i]);
if (Save_GetSaveMetaInfo(i)->n64ddFlag) {
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 0),
CVar_GetS32("gCCFileChoosePrimG", 200), CVar_GetS32("gCCFileChoosePrimB", 255),
this->nameAlpha[i]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[isActive][0],
sWindowContentColors[isActive][1], sWindowContentColors[isActive][2],
this->nameAlpha[i]);
}
gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelDISKButtonTex, G_IM_FMT_IA, G_IM_SIZ_16b, 44, 16, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
@ -1020,21 +993,27 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
}
// draw connectors
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[isActive][0], sWindowContentColors[isActive][1],
sWindowContentColors[isActive][2], this->connectorAlpha[i]);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100),
CVar_GetS32("gCCFileChoosePrimG", 150), CVar_GetS32("gCCFileChoosePrimB", 255),
this->connectorAlpha[i]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[isActive][0], sWindowContentColors[isActive][1],
sWindowContentColors[isActive][2], this->connectorAlpha[i]);
}
gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelConnectorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOLOD);
gSP1Quadrangle(POLY_OPA_DISP++, 12, 14, 15, 13, 0);
if (this->n64ddFlags[i]) {
if (Save_GetSaveMetaInfo(i)->n64ddFlag) {
gSP1Quadrangle(POLY_OPA_DISP++, 16, 18, 19, 17, 0);
}
}
// draw file info
for (fileIndex = 0; fileIndex < 3; fileIndex++) {
isActive = ((this->n64ddFlag == this->n64ddFlags[fileIndex]) || (this->nameBoxAlpha[fileIndex] == 0)) ? 0 : 1;
isActive = ((this->n64ddFlag == Save_GetSaveMetaInfo(fileIndex)->n64ddFlag) || (this->nameBoxAlpha[fileIndex] == 0)) ? 0 : 1;
FileChoose_DrawFileInfo(&this->state, fileIndex, isActive);
}
@ -1047,8 +1026,14 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
// draw primary action buttons (copy/erase)
for (quadVtxIndex = 0, i = 0; i < 2; i++, quadVtxIndex += 4) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->actionButtonAlpha[i]);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->actionButtonAlpha[i]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->actionButtonAlpha[i]);
}
gDPLoadTextureBlock(POLY_OPA_DISP++, sActionButtonTextures[gSaveContext.language][i], G_IM_FMT_IA, G_IM_SIZ_16b,
64, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
@ -1061,8 +1046,13 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
for (quadVtxIndex = 0, i = 0; i < 2; i++, quadVtxIndex += 4) {
temp = this->confirmButtonTexIndices[i];
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->confirmButtonAlpha[i]);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->confirmButtonAlpha[i]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->confirmButtonAlpha[i]);
}
gDPLoadTextureBlock(POLY_OPA_DISP++, sActionButtonTextures[gSaveContext.language][temp], G_IM_FMT_IA,
G_IM_SIZ_16b, 64, 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
@ -1071,8 +1061,14 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
// draw options button
gDPPipeSync(POLY_OPA_DISP++);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->optionButtonAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->optionButtonAlpha);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->optionButtonAlpha);
}
gDPLoadTextureBlock(POLY_OPA_DISP++, sOptionsButtonTextures[gSaveContext.language], G_IM_FMT_IA, G_IM_SIZ_16b, 64,
16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
@ -1087,8 +1083,15 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineLERP(POLY_OPA_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0,
PRIMITIVE, 0);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->highlightColor[0], this->highlightColor[1],
this->highlightColor[2], this->highlightColor[3]);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 155),
CVar_GetS32("gCCFileChoosePrimG", 255), CVar_GetS32("gCCFileChoosePrimB", 255),
this->highlightColor[3]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->highlightColor[0], this->highlightColor[1],
this->highlightColor[2], this->highlightColor[3]);
}
gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelBigButtonHighlightTex, G_IM_FMT_I, G_IM_SIZ_8b, 72, 24, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOLOD);
@ -1143,8 +1146,14 @@ void FileChoose_ConfigModeDraw(GameState* thisx) {
if ((this->configMode != CM_NAME_ENTRY) && (this->configMode != CM_START_NAME_ENTRY)) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->windowAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->windowAlpha);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->windowAlpha);
}
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
Matrix_Translate(0.0f, 0.0f, -93.6f, MTXMODE_NEW);
@ -1175,8 +1184,14 @@ void FileChoose_ConfigModeDraw(GameState* thisx) {
if ((this->configMode >= CM_ROTATE_TO_NAME_ENTRY) && (this->configMode <= CM_NAME_ENTRY_TO_MAIN)) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->windowAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->windowAlpha);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->windowAlpha);
}
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
Matrix_Translate(0.0f, 0.0f, -93.6f, MTXMODE_NEW);
@ -1203,8 +1218,14 @@ void FileChoose_ConfigModeDraw(GameState* thisx) {
if ((this->configMode >= CM_MAIN_TO_OPTIONS) && (this->configMode <= CM_OPTIONS_TO_MAIN)) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->windowAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->windowAlpha);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->windowAlpha);
}
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
Matrix_Translate(0.0f, 0.0f, -93.6f, MTXMODE_NEW);
@ -1242,7 +1263,6 @@ void FileChoose_ConfigModeDraw(GameState* thisx) {
*/
void FileChoose_FadeMainToSelect(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
for (i = 0; i < 3; i++) {
@ -1251,7 +1271,7 @@ void FileChoose_FadeMainToSelect(GameState* thisx) {
this->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] =
this->optionButtonAlpha = this->fileButtonAlpha[i];
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->nameAlpha[i] = this->nameBoxAlpha[i] = this->fileButtonAlpha[i];
this->connectorAlpha[i] -= 31;
}
@ -1372,7 +1392,6 @@ void FileChoose_FadeOutFileInfo(GameState* thisx) {
*/
void FileChoose_MoveSelectedFileToSlot(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 yStep;
s16 i;
@ -1394,7 +1413,7 @@ void FileChoose_MoveSelectedFileToSlot(GameState* thisx) {
this->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] =
this->optionButtonAlpha = this->fileButtonAlpha[i];
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
this->connectorAlpha[i] += 31;
}
@ -1445,14 +1464,14 @@ void FileChoose_LoadGame(GameState* thisx) {
if (this->buttonIndex == FS_BTN_SELECT_FILE_1 && CVar_GetS32("gDebugEnabled", 0)) {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
gSaveContext.fileNum = this->buttonIndex;
Sram_OpenSave(&this->sramCtx);
Sram_OpenSave();
gSaveContext.gameMode = 0;
SET_NEXT_GAMESTATE(&this->state, Select_Init, SelectContext);
this->state.running = false;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
gSaveContext.fileNum = this->buttonIndex;
Sram_OpenSave(&this->sramCtx);
Sram_OpenSave();
gSaveContext.gameMode = 0;
SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext);
this->state.running = false;
@ -1555,8 +1574,14 @@ void FileChoose_SelectModeDraw(GameState* thisx) {
FileChoose_SetWindowContentVtx(&this->state);
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->windowAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), this->windowAlpha);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->windowAlpha);
}
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
Matrix_Translate(0.0f, 0.0f, -93.6f, MTXMODE_NEW);
@ -1601,6 +1626,10 @@ void FileChoose_Main(GameState* thisx) {
};
FileChooseContext* this = (FileChooseContext*)thisx;
Input* input = &this->state.input[0];
if (CVar_GetS32("gTimeFlowFileSelect", 0) != 0) {
gSaveContext.skyboxTime += 0x10;
}
OPEN_DISPS(this->state.gfxCtx, "../z_file_choose.c", 2898);
@ -1615,6 +1644,52 @@ void FileChoose_Main(GameState* thisx) {
this->stickRelX = input->rel.stick_x;
this->stickRelY = input->rel.stick_y;
if (CVar_GetS32("gDpadHoldChange", 1) && CVar_GetS32("gDpadPauseName", 0)) {
if (CHECK_BTN_ALL(input->cur.button, BTN_DLEFT)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) {
this->inputTimerX = 10;
this->stickXDir = -1;
} else if (--(this->inputTimerX) < 0) {
this->inputTimerX = XREG(6);
input->press.button |= BTN_DLEFT;
}
} else if (CHECK_BTN_ALL(input->rel.button, BTN_DLEFT)) {
this->stickXDir = 0;
} else if (CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) {
this->inputTimerX = 10;
this->stickXDir = 1;
} else if (--(this->inputTimerX) < 0) {
this->inputTimerX = XREG(6);
input->press.button |= BTN_DRIGHT;
}
} else if (CHECK_BTN_ALL(input->rel.button, BTN_DRIGHT)) {
this->stickXDir = 0;
}
if (CHECK_BTN_ALL(input->cur.button, BTN_DDOWN)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) {
this->inputTimerY = 10;
this->stickYDir = -1;
} else if (--(this->inputTimerY) < 0) {
this->inputTimerY = XREG(6);
input->press.button |= BTN_DDOWN;
}
} else if (CHECK_BTN_ALL(input->rel.button, BTN_DDOWN)) {
this->stickYDir = 0;
} else if (CHECK_BTN_ALL(input->cur.button, BTN_DUP)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) {
this->inputTimerY = 10;
this->stickYDir = -1;
} else if (--(this->inputTimerY) < 0) {
this->inputTimerY = XREG(6);
input->press.button |= BTN_DUP;
}
} else if (CHECK_BTN_ALL(input->rel.button, BTN_DUP)) {
this->stickYDir = 0;
}
}
if (this->stickRelX < -30) {
if (this->stickXDir == -1) {
this->inputTimerX--;
@ -1645,7 +1720,7 @@ void FileChoose_Main(GameState* thisx) {
if (this->stickRelY < -30) {
if (this->stickYDir == -1) {
this->inputTimerY -= 1;
this->inputTimerY--;
if (this->inputTimerY < 0) {
this->inputTimerY = 2;
} else {
@ -1657,7 +1732,7 @@ void FileChoose_Main(GameState* thisx) {
}
} else if (this->stickRelY > 30) {
if (this->stickYDir == 1) {
this->inputTimerY -= 1;
this->inputTimerY--;
if (this->inputTimerY < 0) {
this->inputTimerY = 2;
} else {
@ -1685,7 +1760,14 @@ void FileChoose_Main(GameState* thisx) {
gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 100, 255, 255, this->controlsAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChooseTextPrimR", 0),
CVar_GetS32("gCCFileChooseTextPrimG", 100), CVar_GetS32("gCCFileChooseTextPrimB", 255),
this->controlsAlpha);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 100, 255, 255, this->controlsAlpha);
}
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
gDPLoadTextureBlock(POLY_OPA_DISP++, controlsTextures[gSaveContext.language], G_IM_FMT_IA, G_IM_SIZ_8b, 144, 16,
0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
@ -1704,9 +1786,6 @@ void FileChoose_Main(GameState* thisx) {
void FileChoose_InitContext(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
EnvironmentContext* envCtx = &this->envCtx;
SramContext* sramCtx = &this->sramCtx;
Sram_Alloc(&this->state, sramCtx);
ZREG(7) = 32;
ZREG(8) = 22;
@ -1859,17 +1938,6 @@ void FileChoose_InitContext(GameState* thisx) {
gSaveContext.buttonStatus[0] = gSaveContext.buttonStatus[1] = gSaveContext.buttonStatus[2] =
gSaveContext.buttonStatus[3] = gSaveContext.buttonStatus[4] = BTN_ENABLED;
this->n64ddFlags[0] = this->n64ddFlags[1] = this->n64ddFlags[2] = this->defense[0] = this->defense[1] =
this->defense[2] = 0;
SsSram_ReadWrite(OS_K1_TO_PHYSICAL(0xA8000000), sramCtx->readBuff, SRAM_SIZE, OS_READ);
gSaveContext.language = sramCtx->readBuff[SRAM_HEADER_LANGUAGE];
if (gSaveContext.language >= LANGUAGE_MAX) {
sramCtx->readBuff[SRAM_HEADER_LANGUAGE] = gSaveContext.language = LANGUAGE_ENG;
}
}
void FileChoose_Destroy(GameState* thisx) {

View file

@ -60,7 +60,6 @@ void FileChoose_SetupCopySource(GameState* thisx) {
*/
void FileChoose_SelectCopySource(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
Input* input = &this->state.input[0];
bool dpad = CVar_GetS32("gDpadPauseName", 0);
@ -73,7 +72,7 @@ void FileChoose_SelectCopySource(GameState* thisx) {
this->warningLabel = FS_WARNING_NONE;
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CLOSE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) {
if (SLOT_OCCUPIED(sramCtx, this->buttonIndex)) {
if (Save_GetSaveMetaInfo(this->buttonIndex)->valid) {
this->actionTimer = 8;
this->selectedFileIndex = this->buttonIndex;
this->configMode = CM_SETUP_COPY_DEST_1;
@ -102,7 +101,7 @@ void FileChoose_SelectCopySource(GameState* thisx) {
}
if (this->buttonIndex != FS_BTN_COPY_QUIT) {
if (!SLOT_OCCUPIED(sramCtx, this->buttonIndex)) {
if (!Save_GetSaveMetaInfo(this->buttonIndex)->valid) {
this->warningLabel = FS_WARNING_FILE_EMPTY;
this->warningButtonIndex = this->buttonIndex;
this->emptyFileTextAlpha = 255;
@ -173,7 +172,6 @@ void FileChoose_SetupCopyDest2(GameState* thisx) {
*/
void FileChoose_SelectCopyDest(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
Input* input = &this->state.input[0];
bool dpad = CVar_GetS32("gDpadPauseName", 0);
@ -185,7 +183,7 @@ void FileChoose_SelectCopyDest(GameState* thisx) {
this->configMode = CM_EXIT_TO_COPY_SOURCE_1;
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CLOSE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) {
if (!SLOT_OCCUPIED(sramCtx, this->buttonIndex)) {
if (!Save_GetSaveMetaInfo(this->buttonIndex)->valid) {
this->copyDestFileIndex = this->buttonIndex;
this->nextTitleLabel = FS_TITLE_COPY_CONFIRM;
this->actionTimer = 8;
@ -227,7 +225,7 @@ void FileChoose_SelectCopyDest(GameState* thisx) {
}
if (this->buttonIndex != FS_BTN_COPY_QUIT) {
if (SLOT_OCCUPIED(sramCtx, this->buttonIndex)) {
if (Save_GetSaveMetaInfo(this->buttonIndex)->valid) {
this->warningLabel = FS_WARNING_FILE_IN_USE;
this->warningButtonIndex = this->buttonIndex;
this->emptyFileTextAlpha = 255;
@ -264,7 +262,6 @@ void FileChoose_ExitToCopySource1(GameState* thisx) {
*/
void FileChoose_ExitToCopySource2(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
s16 yStep;
@ -298,7 +295,6 @@ void FileChoose_ExitToCopySource2(GameState* thisx) {
void FileChoose_SetupCopyConfirm1(GameState* thisx) {
static s16 D_808124A4[] = { -56, -40, -24, 0 };
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
s16 yStep;
@ -309,7 +305,7 @@ void FileChoose_SetupCopyConfirm1(GameState* thisx) {
if ((i != this->copyDestFileIndex) && (i != this->selectedFileIndex)) {
this->fileButtonAlpha[i] -= 25;
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->connectorAlpha[i] -= 31;
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
}
@ -359,7 +355,6 @@ void FileChoose_SetupCopyConfirm2(GameState* thisx) {
*/
void FileChoose_CopyConfirm(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
Input* input = &this->state.input[0];
u16 dayTime;
bool dpad = CVar_GetS32("gDpadPauseName", 0);
@ -372,7 +367,7 @@ void FileChoose_CopyConfirm(GameState* thisx) {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CLOSE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) {
dayTime = gSaveContext.dayTime;
Sram_CopySave(this, sramCtx);
Save_CopyFile(this->selectedFileIndex, this->copyDestFileIndex);
gSaveContext.dayTime = dayTime;
this->fileInfoAlpha[this->copyDestFileIndex] = this->nameAlpha[this->copyDestFileIndex] = 0;
this->nextTitleLabel = FS_TITLE_COPY_COMPLETE;
@ -392,7 +387,6 @@ void FileChoose_CopyConfirm(GameState* thisx) {
*/
void FileChoose_ReturnToCopyDest(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
s16 yStep;
@ -404,7 +398,7 @@ void FileChoose_ReturnToCopyDest(GameState* thisx) {
if ((i != this->copyDestFileIndex) && (i != this->selectedFileIndex)) {
this->fileButtonAlpha[i] += 25;
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
this->connectorAlpha[i] += 31;
}
@ -535,7 +529,6 @@ void FileChoose_CopyAnim4(GameState* thisx) {
*/
void FileChoose_CopyAnim5(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
s16 yStep;
@ -553,7 +546,7 @@ void FileChoose_CopyAnim5(GameState* thisx) {
if (i != this->buttonIndex) {
this->fileButtonAlpha[i] += 25;
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
this->connectorAlpha[i] += 31;
}
@ -572,7 +565,7 @@ void FileChoose_CopyAnim5(GameState* thisx) {
this->fileButtonAlpha[i] = 200;
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->connectorAlpha[i];
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->connectorAlpha[i] = 255;
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
}
@ -681,7 +674,6 @@ void FileChoose_SetupEraseSelect(GameState* thisx) {
*/
void FileChoose_EraseSelect(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
Input* input = &this->state.input[0];
bool dpad = CVar_GetS32("gDpadPauseName", 0);
@ -694,7 +686,7 @@ void FileChoose_EraseSelect(GameState* thisx) {
this->warningLabel = FS_WARNING_NONE;
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CLOSE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) {
if (SLOT_OCCUPIED(sramCtx, this->buttonIndex)) {
if (Save_GetSaveMetaInfo(this->buttonIndex)->valid) {
this->actionTimer = 8;
this->selectedFileIndex = this->buttonIndex;
this->configMode = CM_SETUP_ERASE_CONFIRM_1;
@ -721,7 +713,7 @@ void FileChoose_EraseSelect(GameState* thisx) {
}
if (this->buttonIndex != FS_BTN_ERASE_QUIT) {
if (!SLOT_OCCUPIED(sramCtx, this->buttonIndex)) {
if (!Save_GetSaveMetaInfo(this->buttonIndex)->valid) {
this->warningLabel = FS_WARNING_FILE_EMPTY;
this->warningButtonIndex = this->buttonIndex;
this->emptyFileTextAlpha = 255;
@ -741,7 +733,6 @@ void FileChoose_EraseSelect(GameState* thisx) {
void FileChoose_SetupEraseConfirm1(GameState* thisx) {
static s16 D_808124AC[] = { 0, 16, 32 };
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
s16 yStep;
@ -749,7 +740,7 @@ void FileChoose_SetupEraseConfirm1(GameState* thisx) {
if (i != this->buttonIndex) {
this->fileButtonAlpha[i] -= 25;
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->connectorAlpha[i] -= 31;
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
}
@ -775,7 +766,7 @@ void FileChoose_SetupEraseConfirm1(GameState* thisx) {
if (i != this->buttonIndex) {
this->fileButtonAlpha[i] = 0;
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->connectorAlpha[i] = 0;
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i] = 0;
}
@ -831,7 +822,7 @@ void FileChoose_EraseConfirm(GameState* thisx) {
this->actionTimer = 8;
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_CLOSE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) {
this->n64ddFlags[this->selectedFileIndex] = this->connectorAlpha[this->selectedFileIndex] = 0;
Save_GetSaveMetaInfo(this->selectedFileIndex)->n64ddFlag = this->connectorAlpha[this->selectedFileIndex] = 0;
Audio_PlaySoundGeneral(NA_SE_EV_DIAMOND_SWITCH, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
this->actionTimer = 8;
this->configMode = CM_ERASE_ANIM_1;
@ -869,7 +860,6 @@ void FileChoose_ExitToEraseSelect1(GameState* thisx) {
*/
void FileChoose_ExitToEraseSelect2(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
s16 yStep;
@ -885,7 +875,7 @@ void FileChoose_ExitToEraseSelect2(GameState* thisx) {
if (i != this->buttonIndex) {
this->fileButtonAlpha[i] += 25;
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
this->connectorAlpha[i] += 31;
}
@ -915,7 +905,6 @@ void FileChoose_ExitToEraseSelect2(GameState* thisx) {
void FileChoose_EraseAnim1(GameState* thisx) {
static s16 D_80813800;
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
if (sEraseDelayTimer == 0) {
if (this->actionTimer == 8) {
@ -935,7 +924,7 @@ void FileChoose_EraseAnim1(GameState* thisx) {
D_80813800 += 2;
if (this->actionTimer == 0) {
Sram_EraseSave(this, sramCtx);
Save_DeleteFile(this->selectedFileIndex);
this->titleLabel = this->nextTitleLabel;
this->titleAlpha[0] = 255;
this->titleAlpha[1] = this->connectorAlpha[this->selectedFileIndex] = 0;
@ -981,7 +970,6 @@ void FileChoose_EraseAnim2(GameState* thisx) {
*/
void FileChoose_EraseAnim3(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
s16 i;
s16 yStep;
@ -998,7 +986,7 @@ void FileChoose_EraseAnim3(GameState* thisx) {
for (i = 0; i < 3; i++) {
this->fileButtonAlpha[i] += 25;
if (SLOT_OCCUPIED(sramCtx, i)) {
if (Save_GetSaveMetaInfo(i)->valid) {
this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
this->connectorAlpha[i] += 31;
}

View file

@ -113,6 +113,7 @@ void FileChoose_SetNameEntryVtx(GameState* thisx) {
s16 phi_t1;
u8 temp;
s16 phi_v0;
char* filename = Save_GetSaveMetaInfo(this->buttonIndex)->playerName;
if (1) {}
if (1) {}
@ -133,7 +134,14 @@ void FileChoose_SetNameEntryVtx(GameState* thisx) {
phi_s0 = 0x10;
for (phi_t1 = 0; phi_t1 < 2; phi_t1++, phi_s0 += 4) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2], 255);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100), CVar_GetS32("gCCFileChoosePrimG", 150),
CVar_GetS32("gCCFileChoosePrimB", 255), 255);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
255);
}
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
gDPLoadTextureBlock(POLY_OPA_DISP++, sBackspaceEndTextures[gSaveContext.language][phi_t1], G_IM_FMT_IA,
G_IM_SIZ_16b, sBackspaceEndWidths[phi_t1], 16, 0, G_TX_NOMIRROR | G_TX_WRAP,
@ -145,7 +153,7 @@ void FileChoose_SetNameEntryVtx(GameState* thisx) {
for (phi_s0 = 0, phi_t1 = 0; phi_t1 < 44; phi_t1 += 4, phi_s0++) {
if ((phi_s0 > 0) && (phi_s0 < 9)) {
temp = this->fileNames[this->buttonIndex][phi_s0 - 1];
temp = filename[phi_s0 - 1];
this->nameEntryVtx[phi_t1].v.ob[0] = this->nameEntryVtx[phi_t1 + 2].v.ob[0] =
D_808125EC[phi_s0] + this->nameEntryBoxPosX + D_808124C0[temp];
@ -195,8 +203,15 @@ void FileChoose_SetNameEntryVtx(GameState* thisx) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->nameEntryBoxAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100),
CVar_GetS32("gCCFileChoosePrimG", 150), CVar_GetS32("gCCFileChoosePrimB", 255),
this->nameEntryBoxAlpha);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
this->nameEntryBoxAlpha);
}
gSPVertex(POLY_OPA_DISP++, this->nameEntryVtx, 4, 0);
gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelNameBoxTex, G_IM_FMT_IA, G_IM_SIZ_16b, 108, 16, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
@ -209,8 +224,7 @@ void FileChoose_SetNameEntryVtx(GameState* thisx) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->nameEntryBoxAlpha);
for (phi_v0 = 0, phi_s0 = 0; phi_s0 < 0x20; phi_s0 += 4, phi_v0++) {
FileChoose_DrawCharacter(this->state.gfxCtx,
font->fontBuf + this->fileNames[this->buttonIndex][phi_v0] * FONT_CHAR_TEX_SIZE,
FileChoose_DrawCharacter(this->state.gfxCtx, font->fontBuf + filename[phi_v0] * FONT_CHAR_TEX_SIZE,
phi_s0);
}
@ -267,6 +281,7 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
s16 tmp;
u16 dayTime;
s16 validName;
char* filename = Save_GetSaveMetaInfo(this->buttonIndex)->playerName;
OPEN_DISPS(this->state.gfxCtx, "../z_file_nameset_PAL.c", 368);
@ -318,8 +333,15 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineLERP(POLY_OPA_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0,
PRIMITIVE, 0);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->highlightColor[0], this->highlightColor[1], this->highlightColor[2],
this->highlightColor[3]);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, CVar_GetS32("gCCFileChoosePrimR", 100),
CVar_GetS32("gCCFileChoosePrimG", 150), CVar_GetS32("gCCFileChoosePrimB", 255),
this->highlightColor[3]);
} else {
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->highlightColor[0], this->highlightColor[1],
this->highlightColor[2], this->highlightColor[3]);
}
gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelCharHighlightTex, G_IM_FMT_I, G_IM_SIZ_8b, 24, 24, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
G_TX_NOLOD);
@ -354,12 +376,12 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
this->kbdY = 5;
this->kbdX = 4;
} else if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
if ((this->newFileNameCharCount == 7) && (this->fileNames[this->buttonIndex][7] != 0x3E)) {
if ((this->newFileNameCharCount == 7) && (filename[7] != 0x3E)) {
for (i = this->newFileNameCharCount; i < 7; i++) {
this->fileNames[this->buttonIndex][i] = this->fileNames[this->buttonIndex][i + 1];
filename[i] = filename[i + 1];
}
this->fileNames[this->buttonIndex][i] = 0x3E;
filename[i] = 0x3E;
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_S, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else {
this->newFileNameCharCount--;
@ -369,10 +391,10 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
this->configMode = CM_NAME_ENTRY_TO_MAIN;
} else {
for (i = this->newFileNameCharCount; i < 7; i++) {
this->fileNames[this->buttonIndex][i] = this->fileNames[this->buttonIndex][i + 1];
filename[i] = filename[i + 1];
}
this->fileNames[this->buttonIndex][i] = 0x3E;
filename[i] = 0x3E;
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_S, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
}
@ -390,7 +412,7 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_S, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
this->fileNames[this->buttonIndex][this->newFileNameCharCount] = D_808123F0[this->charIndex];
filename[this->newFileNameCharCount] = D_808123F0[this->charIndex];
this->newFileNameCharCount++;
if (this->newFileNameCharCount > 7) {
@ -399,12 +421,12 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
}
} else if (CHECK_BTN_ALL(input->press.button, BTN_A) && (this->charPage != this->kbdButton)) {
if (this->kbdButton == FS_KBD_BTN_BACKSPACE) {
if ((this->newFileNameCharCount == 7) && (this->fileNames[this->buttonIndex][7] != 0x3E)) {
if ((this->newFileNameCharCount == 7) && (filename[7] != 0x3E)) {
for (i = this->newFileNameCharCount; i < 7; i++) {
this->fileNames[this->buttonIndex][i] = this->fileNames[this->buttonIndex][i + 1];
filename[i] = filename[i + 1];
}
this->fileNames[this->buttonIndex][i] = 0x3E;
filename[i] = 0x3E;
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_S, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
} else {
@ -415,10 +437,10 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
}
for (i = this->newFileNameCharCount; i < 7; i++) {
this->fileNames[this->buttonIndex][i] = this->fileNames[this->buttonIndex][i + 1];
filename[i] = filename[i + 1];
}
this->fileNames[this->buttonIndex][i] = 0x3E;
filename[i] = 0x3E;
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_S, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
}
@ -426,7 +448,7 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
validName = false;
for (i = 0; i < 8; i++) {
if (this->fileNames[this->buttonIndex][i] != 0x3E) {
if (filename[i] != 0x3E) {
validName = true;
break;
}
@ -437,7 +459,7 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
&D_801333E8);
gSaveContext.fileNum = this->buttonIndex;
dayTime = ((void)0, gSaveContext.dayTime);
Sram_InitSave(this, &this->sramCtx);
Sram_InitSave(this);
gSaveContext.dayTime = dayTime;
this->configMode = CM_NAME_ENTRY_TO_MAIN;
this->nameBoxAlpha[this->buttonIndex] = this->nameAlpha[this->buttonIndex] = 200;
@ -655,20 +677,15 @@ static u8 sSelectedSetting;
*/
void FileChoose_UpdateOptionsMenu(GameState* thisx) {
FileChooseContext* this = (FileChooseContext*)thisx;
SramContext* sramCtx = &this->sramCtx;
Input* input = &this->state.input[0];
bool dpad = CVar_GetS32("gDpadPauseName", 0);
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
this->configMode = CM_OPTIONS_TO_MAIN;
sramCtx->readBuff[0] = gSaveContext.audioSetting;
sramCtx->readBuff[1] = gSaveContext.zTargetSetting;
osSyncPrintf("");
Sram_WriteSramHeader(sramCtx);
Save_SaveGlobal();
osSyncPrintf(VT_FGCOL(YELLOW));
osSyncPrintf("sram->read_buff[2] = J_N = %x\n", sramCtx->readBuff[2]);
osSyncPrintf("sram->read_buff[2] = J_N = %x\n", &sramCtx->readBuff[2]);
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);
osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting);

View file

@ -224,7 +224,7 @@ void Title_Main(GameState* thisx) {
if (CVar_GetS32("gSkipLogoTitle",0)!=0) {
gSaveContext.language = CVar_GetS32("gLanguages", 0);
Sram_InitSram(&this->state, &this->sramCtx);
Sram_InitSram(&this->state);
s16 selectedfile = CVar_GetS32("gSaveFileID", 0);
if (selectedfile == 4) {
selectedfile = 0xFF;
@ -242,13 +242,13 @@ void Title_Main(GameState* thisx) {
}
if (selectedfile == 0xFF) {
gSaveContext.fileNum = selectedfile;
Sram_OpenSave(&this->sramCtx);
Sram_OpenSave();
gSaveContext.gameMode = 0;
this->state.running = false;
SET_NEXT_GAMESTATE(&this->state, Select_Init, SelectContext);
} else {
gSaveContext.fileNum = selectedfile;
Sram_OpenSave(&this->sramCtx);
Sram_OpenSave();
gSaveContext.gameMode = 0;
this->state.running = false;
//return;
@ -322,7 +322,7 @@ void Title_Main(GameState* thisx) {
void Title_Destroy(GameState* thisx) {
TitleContext* this = (TitleContext*)thisx;
Sram_InitSram(&this->state, &this->sramCtx);
Sram_InitSram(&this->state);
}
void Title_Init(GameState* thisx) {
@ -346,7 +346,6 @@ void Title_Init(GameState* thisx) {
this->state.destroy = Title_Destroy;
this->exit = false;
gSaveContext.fileNum = 0xFF;
Sram_Alloc(&this->state, &this->sramCtx);
this->ult = 0;
this->unk_1D4 = 0x14;
this->coverAlpha = 255;

View file

@ -640,9 +640,13 @@ void KaleidoScope_DrawDebugEditor(GlobalContext* globalCtx) {
// Handles exiting the inventory editor with the L button
// The editor is opened with `debugState` set to 1, and becomes closable after a frame once `debugState` is set to 2
s16 Debug_BTN = BTN_L;
if (CVar_GetS32("gNGCKaleidoSwitcher", 0) != 0) {
Debug_BTN = BTN_Z;
}
if (pauseCtx->debugState == 1) {
pauseCtx->debugState = 2;
} else if ((pauseCtx->debugState == 2) && CHECK_BTN_ALL(input->press.button, BTN_L)) {
} else if ((pauseCtx->debugState == 2) && CHECK_BTN_ALL(input->press.button, Debug_BTN)) {
pauseCtx->debugState = 0;
}

View file

@ -98,8 +98,8 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) {
f32 scale;
Input* input = &globalCtx->state.input[0];
s16 RotationSpeed = 150 * CVar_GetS32("gPauseLiveLinkRotationSpeed", 0);
bool AllowCRotation = (CVar_GetS32("gPauseLiveLinkRotation", 0) == 2) ? true : false;
bool AllowDPadRotation = (CVar_GetS32("gPauseLiveLinkRotation", 0) == 1) ? true : false;
u8 AllowCRotation = (CVar_GetS32("gPauseLiveLinkRotation", 0) == 2) ? true : false;
u8 AllowDPadRotation = (CVar_GetS32("gPauseLiveLinkRotation", 0) == 1) ? true : false;
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
pos.x = 2.0f;
@ -120,19 +120,19 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) {
link_kaleido_rot.x = link_kaleido_rot.z = 0;
if (AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DLEFT) ||
AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CLEFT)) {
if ((AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DLEFT)) ||
(AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CLEFT))) {
link_kaleido_rot.y = link_kaleido_rot.y - RotationSpeed;
} else if (AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT) ||
AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CRIGHT)) {
} else if ((AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT)) ||
(AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CRIGHT))) {
link_kaleido_rot.y = link_kaleido_rot.y + RotationSpeed;
}
if (AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DUP) ||
AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) {
if ((AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DUP)) ||
(AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) {
link_kaleido_rot.y = 32300;
} else if (AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CUP) ||
AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) {
} else if ((AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CUP)) ||
(AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CDOWN))) {
link_kaleido_rot.y = 32300;
}
@ -635,7 +635,8 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) {
KaleidoScope_DrawQuadTextureRGBA32(globalCtx->state.gfxCtx, gBiggoronSwordIconTex, 32, 32, point);
} else if ((i == 0) && (k == 2) && (gBitFlags[bit + 1] & gSaveContext.inventory.equipment)) {
KaleidoScope_DrawQuadTextureRGBA32(globalCtx->state.gfxCtx, gBrokenGiantsKnifeIconTex, 32, 32, point);
} else if (gBitFlags[bit] & gSaveContext.inventory.equipment) {
}
if (gBitFlags[bit] & gSaveContext.inventory.equipment) {
int itemId = ITEM_SWORD_KOKIRI + temp;
bool not_acquired = (gItemAgeReqs[itemId] != 9) && (gItemAgeReqs[itemId] != gSaveContext.linkAge);
if (not_acquired) {

View file

@ -930,7 +930,14 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) {
}
void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) {
if (CVar_GetS32("gDebugEnabled", 0) && (pauseCtx->debugState == 0) && CHECK_BTN_ALL(input->press.button, BTN_L)) {
s16 Debug_BTN = BTN_L;
s16 PageLeft_BTN = BTN_Z;
if (CVar_GetS32("gNGCKaleidoSwitcher", 0) != 0) {
Debug_BTN = BTN_Z;
PageLeft_BTN = BTN_L;
}
if (CVar_GetS32("gDebugEnabled", 0) && (pauseCtx->debugState == 0) && CHECK_BTN_ALL(input->press.button, Debug_BTN)) {
pauseCtx->debugState = 1;
return;
}
@ -940,14 +947,14 @@ void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) {
return;
}
if (CHECK_BTN_ALL(input->press.button, BTN_Z)) {
if (CHECK_BTN_ALL(input->press.button, PageLeft_BTN)) {
KaleidoScope_SwitchPage(pauseCtx, 0);
return;
}
bool dpad = CVar_GetS32("gDpadPauseName", 0);
if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) {
if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->cur.button, BTN_DLEFT))) {
pauseCtx->pageSwitchTimer++;
if ((pauseCtx->pageSwitchTimer >= 10) || (pauseCtx->pageSwitchTimer == 0)) {
KaleidoScope_SwitchPage(pauseCtx, 0);
@ -956,7 +963,7 @@ void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) {
pauseCtx->pageSwitchTimer = -1;
}
} else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) {
if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT))) {
pauseCtx->pageSwitchTimer++;
if ((pauseCtx->pageSwitchTimer >= 10) || (pauseCtx->pageSwitchTimer == 0)) {
KaleidoScope_SwitchPage(pauseCtx, 2);
@ -1115,6 +1122,7 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
static s16 D_8082AD4C = 0;
static s16 D_8082AD50 = 0;
PauseContext* pauseCtx = &globalCtx->pauseCtx;
Input* input = &globalCtx->state.input[0];
s16 stepR;
s16 stepG;
s16 stepB;
@ -1155,6 +1163,52 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
}
}
if (CVar_GetS32("gDpadHoldChange", 1) && CVar_GetS32("gDpadPauseName", 0)) {
if (CHECK_BTN_ALL(input->cur.button, BTN_DLEFT)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) {
D_8082AD44 = XREG(8);
D_8082AD4C = -1;
} else if (--D_8082AD44 < 0) {
D_8082AD44 = XREG(6);
input->press.button |= BTN_DLEFT;
}
} else if (CHECK_BTN_ALL(input->rel.button, BTN_DLEFT)) {
D_8082AD4C = 0;
} else if (CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) {
D_8082AD44 = XREG(8);
D_8082AD4C = 1;
} else if (--D_8082AD44 < 0) {
D_8082AD44 = XREG(6);
input->press.button |= BTN_DRIGHT;
}
} else if (CHECK_BTN_ALL(input->rel.button, BTN_DRIGHT)) {
D_8082AD4C = 0;
}
if (CHECK_BTN_ALL(input->cur.button, BTN_DDOWN)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) {
D_8082AD48 = XREG(8);
D_8082AD50 = -1;
} else if (--D_8082AD48 < 0) {
D_8082AD48 = XREG(6);
input->press.button |= BTN_DDOWN;
}
} else if (CHECK_BTN_ALL(input->rel.button, BTN_DDOWN)) {
D_8082AD50 = 0;
} else if (CHECK_BTN_ALL(input->cur.button, BTN_DUP)) {
if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) {
D_8082AD48 = XREG(8);
D_8082AD50 = 1;
} else if (--D_8082AD48 < 0) {
D_8082AD48 = XREG(6);
input->press.button |= BTN_DUP;
}
} else if (CHECK_BTN_ALL(input->rel.button, BTN_DUP)) {
D_8082AD50 = 0;
}
}
if (pauseCtx->stickRelX < -30) {
if (D_8082AD4C == -1) {
if (--D_8082AD44 < 0) {
@ -3725,7 +3779,7 @@ void KaleidoScope_Update(GlobalContext* globalCtx)
&D_801333E8);
Gameplay_SaveSceneFlags(globalCtx);
gSaveContext.savedSceneNum = globalCtx->sceneNum;
Sram_WriteSave(&globalCtx->sramCtx);
Save_SaveFile();
pauseCtx->unk_1EC = 4;
D_8082B25C = 3;
}
@ -3965,7 +4019,7 @@ void KaleidoScope_Update(GlobalContext* globalCtx)
pauseCtx->promptChoice = 0;
Gameplay_SaveSceneFlags(globalCtx);
gSaveContext.savedSceneNum = globalCtx->sceneNum;
Sram_WriteSave(&globalCtx->sramCtx);
Save_SaveFile();
pauseCtx->state = 0xF;
D_8082B25C = 3;
}