Compare commits

..

2 Commits

Author SHA1 Message Date
TakaRikka a53b363905 Merge branch 'main' of ssh://github.com/TwilitRealm/dusklight into rando-mod 2026-07-30 05:45:18 -07:00
TakaRikka fae9add351 generator / basic mod structure building 2026-07-27 22:33:03 -07:00
230 changed files with 55365 additions and 1955 deletions
+1 -25
View File
@@ -90,7 +90,6 @@ option(DUSK_ENABLE_SENTRY_NATIVE "Enable sentry-native crash reporting support"
option(DUSK_PACKAGE_INSTALL "Install Dusklight with a Linux-native file structure" OFF)
option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT})
option(DUSK_ENABLE_CODE_MODS "Enable code mods" OFF)
option(DUSK_ENABLE_OPUS "Enable loading Opus audio files for mods" ON)
set(DUSK_HAS_FUNCHOOK OFF)
if (DUSK_ENABLE_CODE_MODS AND (NOT APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Darwin"))
@@ -249,25 +248,6 @@ FetchContent_Declare(miniz
)
set(_fetch_content_deps cxxopts json miniz)
if (DUSK_ENABLE_OPUS)
message(STATUS "dusklight: Fetching opusfile")
# Opusfile options
SET(OP_DISABLE_HTTP ON CACHE BOOL "" FORCE)
SET(OP_DISABLE_DOCS ON CACHE BOOL "" FORCE)
SET(OP_DISABLE_EXAMPLES ON CACHE BOOL "" FORCE)
message(STATUS "dusklight: Fetching opusfile")
FetchContent_Declare(
opusfile
GIT_REPOSITORY https://github.com/xiph/opusfile.git
GIT_TAG 6dfd29e7adb87f2e193575fc3fa88cbf1a0b27df
)
list(APPEND _fetch_content_deps opusfile)
endif ()
if (DUSK_HAS_FUNCHOOK)
message(STATUS "dusklight: Fetching funchook")
# cmake/PatchFunchook.cmake patches funchook's cmake/capstone.cmake.in to inject a
@@ -360,10 +340,6 @@ set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::p
if (DUSK_HAS_FUNCHOOK)
list(APPEND GAME_LIBS funchook-static)
endif ()
if (DUSK_ENABLE_OPUS)
list(APPEND GAME_LIBS OpusFile::opusfile)
list(APPEND GAME_COMPILE_DEFS DUSK_OPUS=1)
endif ()
if (DUSK_ENABLE_SENTRY_NATIVE)
list(APPEND GAME_LIBS sentry)
@@ -635,7 +611,7 @@ if (DUSK_ENABLE_CODE_MODS AND CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR
add_subdirectory(mods/ao_mod)
add_subdirectory(mods/shadow_mod)
add_subdirectory(mods/window_demo)
add_subdirectory(mods/audio_mod)
add_subdirectory(mods/randomizer)
endif ()
if (APPLE)
-71
View File
@@ -1,71 +0,0 @@
#pragma endian big
#include "std/sys.pat"
#include "type/magic.pat"
#include "std/array.pat"
/**
* Wrapper for a file-global pointer that allows it to be stored in an array.
*/
struct Offset<T> {
T* offset : u32 [[inline]];
};
struct ItemSoundEffect {
u8 mPriority;
u8 mVolume;
padding[2];
u32 mSwBit;
float mPitch;
};
struct ItemSequence {
u8 mPriority;
u8 mVolume;
u16 mResourceId;
};
struct ItemStream {
u8 mPriority;
u8 mVolume;
u16 mStreamPanParameters;
char* mStreamFilePath[] : u32;
};
struct SoundTableGroupEntry {
u8 mTypeId;
if (mTypeId == 0x51) {
ItemSoundEffect* mOffset : u24 [[inline]];
} else if (mTypeId == 0x60) {
ItemSequence* mOffset : u24 [[inline]];
} else if (mTypeId == 0x70 || mTypeId == 0x71) {
ItemStream* mOffset : u24 [[inline]];
} else {
u24 mOffset;
}
};
struct TGroup {
u32 mNumItems;
padding[4];
SoundTableGroupEntry mEntries[mNumItems];
};
struct TSection {
u32 mNumGroups;
Offset<TGroup> mGroupOffsets[mNumGroups];
};
struct Root {
u32 mSectionNumber;
Offset<TSection> mSectionOffsets[mSectionNumber];
};
struct THeader {
type::Magic<"BST "> mMagic;
padding[8];
Root* mRoot : u32;
};
THeader header @ 0x0;
-228
View File
@@ -1,228 +0,0 @@
#pragma endian big
#include "std/sys.pat"
#include "type/magic.pat"
#include "std/array.pat"
/*
WSYS file
The WSYS file contains roughly two sections: WBCT and WINF.
WBCT contains the mapping of Wave ID -> wave archives.
WINF are the wave archives themselves and their metadata.
*/
/**
* Wrapper for a file-global pointer that allows it to be stored in an array.
*/
struct Offset<T> {
T* offset : u32 [[inline]];
};
/**
* Format that audio data is in..
*/
enum WaveFormat : u8 {
/**
* 16-samples-per-9-bytes custom Nintendo ADPCM.
*/
ADPCM4 = 0,
/**
* 16-samples-per-5-bytes custom Nintendo ADPCM.
*/
ADPCM2 = 1,
/**
* 8-bit-per-sample PCM.
*/
PCM8 = 2,
/**
* 16-bit-per-sample PCM.
*/
PCM16 = 3,
};
/**
* Defines playback info for a single audio "wave".
* This data is stored per archive, making it duplicated (except for mAWOffsetStart)
*/
struct TWave {
padding[1]; // unknown
WaveFormat mWaveFormat;
/**
* Key (as in like, the musical term) this sample is in.
*/
u8 mBaseKey;
padding[1];
/**
* Sample rate of the audio in Hz.
*/
float mSampleRate;
/**
* Position where the sample data starts.
* This is in the .aw file for the archive containing this TWave.
*/
u32 mAWOffsetStart;
/**
* Byte length of the sample data.
*/
u32 mAWLength;
/**
* Indicates whether the sample should loop or not. All bits appear set if so.
*/
u32 mLoopFlags;
/**
* Audio sample at which the loop starts.
*/
u32 mLoopStartSample;
/**
* Audio sample at which the loop ends (and goes back to mLoopStartSample).
*/
u32 mLoopEndSample;
/**
* Total sample count in this wave.
*/
u32 mSampleCount;
/**
* Last sample for continuing ADPCM decode after loop.
*/
s16 mpLast;
/**
* Penult sample for continuing ADPCM decode after loop.
*/
s16 mpPenult;
};
/**
* A single wave archive on disk.
* These are paired 1:1 with TCtrlScene objects.
*/
struct TWaveArchive {
/**
* Filename of the raw sample data on disc. Relative to /Audiores/Waves/
*/
char mFileName[0x70];
/**
* Amount of waves in this archive.
* Matches the count in the paired TCtrl object.
*/
u32 mWaveCount;
/**
* Offsets to the wave metadata (not sample data) in the WSYS.
* These are paired 1:1 to the TCtrlWaves, and the TCtrlWave contains the actual
* "Wave ID" used by the game for lookups.
*/
Offset<TWave> waveOffsets[mWaveCount];
};
/**
* Header containing data for wave archives and their metadata.
*/
struct TWaveArchiveBank {
type::Magic<"WINF"> mMagic;
/**
* Amount of archives in this wave bank.
* Matches the value in TCtrlGroup.
*/
u32 mArchiveCounts;
Offset<TWaveArchive> mArchiveOffsets[mArchiveCounts];
};
/**
* Definition for a single wave in a control group.
*/
struct TCtrlWave {
/**
* Group ID matches the index of the control group this item is referenced by.
*/
u16 mGroupId;
/**
* Wave ID used by the game to look this wave up.
*/
u16 mWaveId;
};
/**
* Contains the actual data for a TCtrlScene.
* Why is this separate? Who knows.
*/
struct TCtrl {
// Other versions of this struct with different magic (C-EX and C-ST) also exist in the file.
// They aren't pointed to so we don't need to worry about them.
type::Magic<"C-DF"> mMagic;
/**
* Amount of waves in this group.
* Matches the value in TWaveArchive.
*/
u32 waveCount;
Offset<TCtrlWave> mWaveOffsets[waveCount];
};
/**
* A single scene or "group" of waves that are loaded at once.
*/
struct TCtrlScene {
type::Magic<"SCNE"> mMagic;
padding[8]; // unknown
TCtrl* mCtrlOffset : u32 [[inline]];
};
/**
* Contains the "control" section of the WSYS.
*/
struct TCtrlGroup {
type::Magic<"WBCT"> mMagic;
padding[4]; // unknown
u32 mGroupCount;
Offset<TCtrlScene> mCtrlSceneOffsets[mGroupCount];
};
struct THeader {
type::Magic<"WSYS"> mMagic;
/**
* Size of WSYS in bytes.
*/
u32 mSize;
/**
* ID of wave bank.
* This matches the value passed to the BAA load command.
* The game originally does not use this value itself, but Dusklight does rely on it.
*/
u32 mId;
/**
* Total amount of waves in this wave bank.
* (not groups! Waves!)
*/
u32 mWaveTableSize;
TWaveArchiveBank* archiveBankOffset : u32;
TCtrlGroup* ctrlGroupOffset : u32;
};
THeader header @ 0x0;
std::assert(
header.archiveBankOffset.mArchiveCounts == header.ctrlGroupOffset.mGroupCount,
"Control group and archive count does not match!");
-90
View File
@@ -1,90 +0,0 @@
# JAudio
**JAudio** is the name for the audio engine used by Twilight Princess (along with many other Nintendo games from the era). TP uses exclusively JAudio v2, while other games use v1 or a mix of v1 and v2 infrastructure. This document will primarily focus on TP's use case, but best efforts will be made to document where behavior is TP-specific.
## Common concepts
Audio is almost exclusively
### `JAISoundID`
A "sound", be that a _sound effect_ or music, is referenced in-code through the `JAISoundID` type. This is a `u32` that the game uses to look up the relevant sound. The actual value is bitpacked (BE) from the following fields:
| Type | Field | Description |
|-------|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `u8` | Section ID | Section of the Sound Table this sound effect is located in. 0 for sound effects, 1 for sequenced music, 2 for streamed music.[^sectionids] |
| `u8` | Group ID | ID of group further used to organize inside the Sound Table's Section. Sound effects are grouped into things like "SYSTEM" and "ENEMY", other sections leave this at 0. |
| `u16` | "Wave ID" | Index inside the group to look up the sound at.<br/>**Note** that the term "wave" in code is extremely confusing[^waveterm]; it does **not** refer to audio samples ("waves") in the wave banks directly. |
[^sectionids]: JAudio itself can seemingly work outside this convention, however it is enforced by some TP-specific game code.
[^waveterm]: Possibly vestigial from JAudio v1, where I believe there were less layers of indirection.
## Disc files
All audio data is stored in `/Audiores` on the disc. Files are as follows:
### `/Audiores/Seqs/Z2SoundSeqs.arc`
Contains the BMS instructions for all BMS-based music and sound effects. Not all data is kept in memory at once.
### `/Audiores/Stream/*.ast`
Contains individual streamed music. Each file is a separate music track. See [this page](https://www.lumasworkshop.com/wiki/AST_(File_Format)) for file format description.
### `/Audiores/Waves/*.aw`
Contains audio sample data for sequenced music and sound effects. These files are pure meat, no bone: they are loaded directly into ARAM and all metadata is stored in the BAA WSYS sections.
Each file contains audio samples for one "scene", with factors like the current level determining what "scenes" are made resident in memory. There is tons of duplicate data between scenes, presumably to increase simplicity and loading performance.
### `/Audiores/Z2Sound.baa`
Contains all remaining metadata for the audio system. This is effectively a container for a bunch of different sub-sections. The file starts with a bunch of "commands" that indicate where other data in the file is. Each command has a 4-character identifier and depending on the command will be followed by some extra arguments before the next command.
The commands used by TP's BAA file are as follows (note that the decompiled code has support for more load commands, which are unused):
| Command/Argument | Value | Description |
|------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------|
| Command | `AA_<` | Start of BAA commands. Must be at the start of the file and only appear once. |
| Command | `>_AA` | End of BAA commands. |
| Command | `ws `[^spaces] | Wave bank/WSYS data. Defines where audio samples are located on disc. |
| Argument | u32 | Wave bank ID, max 255. In TP, 0 is sound effects, 1 is music samples. |
| Argument | u32 | File offset for start of `WSYS` data |
| Argument | u32 | Bit field selecting which groups (= `.aw` files) to load immediately. TP leaves this at zero.[^32ws] |
| Command | `bnk `[^spaces] | Instrument bank/IBNK |
| Argument | u32 | Target wave bank ID |
| Argument | u32 | File offset for start of `IBNK` data |
| Command | `bsc `[^spaces] | Sound effect sequence collection. |
| Argument | u32 | File offset for start of `SC` data. |
| Argument | u32 | File offset for end of `SC` data. |
| Command | `bst `[^spaces] | Sound table. Defines parameters for music and sound effects. |
| Argument | u32 | File offset for start of `BST `[^spaces] data. |
| Argument | u32 | File offset for end of `BST `[^spaces] data. |
| Command | `bstn` | Sound name table. Defines names of all music and sound effects. Present on disc, but loading is disabled on release versions of the game. |
| Argument | u32 | File offset for start of `BSTN` data. |
| Argument | u32 | File offset for end of `BSTN` data. |
| Command | `bfca` | Unknown, something related to initialization of DSP FX data. |
| Argument | u32 | File offset for start of `RARC` data. |
[^spaces]: Padded with spaces.
[^32ws]: Both of TP's wave banks have far more than 32 groups, and seemingly this mechanism would not be able to deal with that.
Following is data descriptions for the remaining data in the `.BAA`, as pointed to by the above commands.
### `WSYS` / Wave banks
`WSYS` / Wave bank data defines where a set of audio samples can be found on disc. Each wave bank is made of multiple "groups", where each group corresponds to one `.aw` file on disc. Each group has a set of "wave IDs" it contains, along with the metadata (e.g. sample rate) and data offset in the `.aw` file.
Multiple groups can contain the same wave ID, thus meaning the raw audio samples can be duplicated on disk.
For the actual binary layout of this data, check [the ImHex pattern](imhex/jaudio/wsys.hexpat)
*Relevant classes: `JASWSParser`, `JASBasicWaveBank`, `JASSimpleWaveBank`.*
## Further reading & credits
* https://www.lumasworkshop.com/wiki/SMR.szs (note that details like the exact layout of the BAA are not the same as TP)
* XAYRGA for doing much RE work and making [JAMTools](https://xayr.gay/tools/SoundModdingToolkit/)
* The decompiled source code, duh.
-5
View File
@@ -1485,10 +1485,6 @@ set(DUSK_FILES
src/dusk/mods/log_buffer.hpp
src/dusk/mods/manifest.cpp
src/dusk/mods/manifest.hpp
src/dusk/mods/svc/audio_res/audio_res.hpp
src/dusk/mods/svc/audio_res/audio_res.cpp
src/dusk/mods/svc/audio_res/wave.cpp
src/dusk/mods/svc/audio_res/opus.cpp
src/dusk/mods/svc/camera.cpp
src/dusk/mods/svc/config.cpp
src/dusk/mods/svc/config.hpp
@@ -1589,7 +1585,6 @@ set(DUSK_FILES
src/helpers/endian.cpp
src/helpers/offset_ptr.cpp
src/helpers/string.cpp
src/helpers/cast.cpp
)
set(DUSK_HTTP_BACKEND_FILES
+43 -86
View File
@@ -9,8 +9,6 @@
#include "JSystem/JAudio2/JAUAudibleParam.h"
#include "JSystem/TPosition3.h"
#define Z2_AUDIO_PLAYERS 1
struct Z2Audible;
struct Z2AudibleAbsPos {
@@ -51,14 +49,10 @@ struct Z2AudioCamera {
f32 getCamDist() const { return mCamDist; }
/* 0x00 */ JGeometry::TPosition3f32 mViewMatrix;
/* 0x00 */ JGeometry::TPosition3f32 field_0x0;
/* 0x30 */ JGeometry::TVec3<f32> mVel;
/* 0x3C */ JGeometry::TVec3<f32> mPos;
/**
*
*/
/* 0x48 */ JGeometry::TVec3<f32> mLastPos;
/* 0x48 */ JGeometry::TVec3<f32> field_0x48;
/* 0x54 */ f32 mFovySin;
/* 0x58 */ f32 mVolCenterZ;
/* 0x5C */ f32 mTargetVolume;
@@ -89,14 +83,14 @@ struct Z2SpotMic {
/* 0x04 */ f32 field_0x4;
/* 0x08 */ f32 field_0x8;
/* 0x0C */ f32 field_0xc;
/* 0x10 */ Z2AudioCamera* field_0x10[Z2_AUDIO_PLAYERS];
/* 0x10 */ Z2AudioCamera* field_0x10[1];
/* 0x14 */ Vec* mPosPtr;
/* 0x18 */ f32 field_0x18[Z2_AUDIO_PLAYERS];
/* 0x18 */ f32 field_0x18[1];
/* 0x1C */ f32 field_0x1c;
/* 0x20 */ f32 field_0x20[Z2_AUDIO_PLAYERS];
/* 0x20 */ f32 field_0x20[1];
/* 0x24 */ bool mIgnoreIfOut;
/* 0x25 */ bool mMicOn;
/* 0x26 */ bool field_0x26[Z2_AUDIO_PLAYERS];
/* 0x26 */ bool field_0x26[1];
}; // Size: 0x28
struct Z2Audience3DSetting {
@@ -108,99 +102,62 @@ struct Z2Audience3DSetting {
void updateDolbyDist(f32, f32);
void calcVolumeFactorAll() {
mDistanceMaxes[1] = 1.25f * mDistanceMaxes[0];
mDistanceMaxes[2] = 1.5f * mDistanceMaxes[0];
mDistanceMaxes[3] = 2.0f * mDistanceMaxes[0];
mDistanceMaxes[4] = 3.0f * mDistanceMaxes[0];
mDistanceMaxes[5] = 4.0f * mDistanceMaxes[0];
mDistanceMaxes[6] = 6.0f * mDistanceMaxes[0];
mDistanceMaxes[7] = 8.0f * mDistanceMaxes[0];
mDistanceMaxes[8] = 0.9f * mDistanceMaxes[0];
mDistanceMaxes[9] = 0.8f * mDistanceMaxes[0];
mDistanceMaxes[10] = 0.7f * mDistanceMaxes[0];
mDistanceMaxes[11] = 0.6f * mDistanceMaxes[0];
mDistanceMaxes[12] = 0.5f * mDistanceMaxes[0];
mDistanceMaxes[13] = 0.4f * mDistanceMaxes[0];
mDistanceMaxes[14] = 0.3f * mDistanceMaxes[0];
field_0x0[1] = 1.25f * field_0x0[0];
field_0x0[2] = 1.5f * field_0x0[0];
field_0x0[3] = 2.0f * field_0x0[0];
field_0x0[4] = 3.0f * field_0x0[0];
field_0x0[5] = 4.0f * field_0x0[0];
field_0x0[6] = 6.0f * field_0x0[0];
field_0x0[7] = 8.0f * field_0x0[0];
field_0x0[8] = 0.9f * field_0x0[0];
field_0x0[9] = 0.8f * field_0x0[0];
field_0x0[10] = 0.7f * field_0x0[0];
field_0x0[11] = 0.6f * field_0x0[0];
field_0x0[12] = 0.5f * field_0x0[0];
field_0x0[13] = 0.4f * field_0x0[0];
field_0x0[14] = 0.3f * field_0x0[0];
for (int i = 0; i < 15; i++) {
mVolumeFactor[i] = (mMinDistanceVolume - 1.0f) / (mDistanceMaxes[i] - mMaxVolumeDistance);
field_0x70[i] = (field_0x40 - 1.0f) / (field_0x0[i] - field_0x3c);
}
}
void calcPriorityFactorAll() {
for (int i = 0; i < 15; i++) {
mPriorityFactor[i] = mMaxDistancePriority / (mDistanceMaxes[i] - mMaxVolumeDistance);
field_0xac[i] = field_0x64 / (field_0x0[i] - field_0x3c);
}
}
void calcFxMixFactorAll() {
for (int i = 0; i < 15; i++) {
mFxMixFactor[i] = (mMaxDistanceFxMix - mMinDistanceFxMix) / (mDistanceMaxes[i] - mMaxVolumeDistance);
field_0xe8[i] = (field_0x54 - field_0x50) / (field_0x0[i] - field_0x3c);
}
}
/**
* Maximum distance a sound can reach before being "far away"
* Being far away affects stuff like culling, lowering its priority, forcibly stopping it, etc.
* Sounds select which entry they use based on their VolBits.
*/
/* 0x000 */ f32 mDistanceMaxes[15];
/**
* Distance at which the max volume of a sound is reached.
* i.e. sounds do *not* get louder if they get closer than this.
*/
/* 0x03C */ f32 mMaxVolumeDistance;
/**
* FX Mix value at maximum distance (@ref mDistanceMaxes)
*/
/* 0x040 */ f32 mMinDistanceVolume;
/* 0x044 */ f32 mDolbyFrontDistanceMax;
/* 0x048 */ f32 mDolbyBehindDistanceMax;
/* 0x04C */ f32 mDolbyCenterValue;
/**
* FX Mix value at minimum distance (@ref mMaxVolumeDistance)
*/
/* 0x050 */ f32 mMinDistanceFxMix;
/**
* FX Mix value at maximum distance (@ref mDistanceMaxes)
*/
/* 0x054 */ f32 mMaxDistanceFxMix;
/* 0x058 */ f32 mPanFactor;
/* 0x05C */ f32 mSonicSpeed; // Used for doppler effect calculations.
/* 0x000 */ f32 field_0x0[15];
/* 0x03C */ f32 field_0x3c;
/* 0x040 */ f32 field_0x40;
/* 0x044 */ f32 field_0x44;
/* 0x048 */ f32 field_0x48;
/* 0x04C */ f32 field_0x4c;
/* 0x050 */ f32 field_0x50;
/* 0x054 */ f32 field_0x54;
/* 0x058 */ f32 field_0x58;
/* 0x05C */ f32 field_0x5c;
/* 0x060 */ f32 field_0x60;
/**
* Priority that sounds receive when "far away".
* @see mDistanceMaxes
*/
/* 0x064 */ u32 mMaxDistancePriority;
/* 0x064 */ u32 field_0x64;
/* 0x068 */ f32 field_0x68;
/* 0x06C */ f32 field_0x6c;
/* 0x070 */ f32 mVolumeFactor[15];
/* 0x0AC */ f32 mPriorityFactor[15];
/* 0x0E8 */ f32 mFxMixFactor[15];
/* 0x070 */ f32 field_0x70[15];
/* 0x0AC */ f32 field_0xac[15];
/* 0x0E8 */ f32 field_0xe8[15];
/* 0x124 */ bool mVolumeDistInit;
/* 0x125 */ bool mDolbyDistInit;
}; // Size: 0x128
struct Z2AudibleRelPos {
/* 0x00 */ JGeometry::TVec3<f32> mCameraRelative;
/**
* Distance from mCameraRelative. This is from the object root and not the
* exact distance used for volume/priority calculations.
*/
/* 0x0C */ f32 mTrueDistance;
/**
* Distance from mCameraRelative but offset by mVolCenterZ.
* This presumably means the distance is more centered on the object than mTrueDistance.
*/
/* 0x10 */ f32 mCenterDistance;
/* 0x00 */ JGeometry::TVec3<f32> field_0x00;
/* 0x0C */ f32 field_0xC;
/* 0x10 */ f32 field_0x10;
};
struct Z2AudibleChannel {
@@ -214,7 +171,7 @@ struct Z2AudibleChannel {
}
/* 0x00 */ JASSoundParams mParams;
/* 0x14 */ Z2AudibleRelPos mRelPos;
/* 0x14 */ Z2AudibleRelPos field_0x14;
/* 0x28 */ f32 field_0x28;
/* 0x2c */ f32 mPan;
/* 0x30 */ f32 mDolby;
@@ -243,8 +200,8 @@ struct Z2Audible : public JAIAudible, public JASPoolAllocObject<Z2Audible> {
/* 0x10 */ JAUAudibleParam mParam;
/* 0x14 */ Z2AudibleAbsPos mAbsPos;
/* 0x2C */ Z2AudibleChannel mChannel[Z2_AUDIO_PLAYERS];
/* 0x64 */ f32 mMicDistances[Z2_AUDIO_PLAYERS];
/* 0x2C */ Z2AudibleChannel mChannel[1];
/* 0x64 */ f32 field_0x64[1];
};
struct Z2Audience : public JAIAudience, public JASGlobalInstance<Z2Audience> {
+1 -1
View File
@@ -47,7 +47,7 @@ public:
s32 getBgmLoadStatus(u32 wave) { return getWaveLoadStatus(wave, 1); }
u8 getDemoSeWaveNum() { return loadedDemoWave; }
private:
// private:
/* 0x00 */ JAISoundID BGM_ID;
/* 0x04 */ int sceneNum;
/* 0x08 */ int timer;
+1
View File
@@ -1291,6 +1291,7 @@ public:
}
void set(const char*, s8, s16, s8, s8, u8);
void offEnable() { enabled = 0; }
void onEnable() { enabled = 1; }
BOOL isEnable() const { return enabled; }
s8 getWipe() const { return wipe; }
u8 getWipeSpeed() const { return wipe_speed; }
-18
View File
@@ -1,18 +0,0 @@
#pragma once
namespace dusk::helpers::alignment {
/**
* Read data from an address that may not be aligned properly.
* @tparam T Type of data to read.
* @param ptr Address to read from.
* @return The copied value.
*/
template <typename T> requires std::is_trivially_copyable_v<T>
[[nodiscard]] constexpr T read_unaligned(u8 const* ptr) {
T copy;
memcpy(&copy, ptr, sizeof(T));
return copy;
}
}
-48
View File
@@ -1,48 +0,0 @@
#pragma once
#include <limits>
#include <utility>
#include <span>
/**
* Helper functions for performing casts.
*/
namespace dusk::helpers::cast {
/**
* Implementation details of dusk::helpers::cast.
*/
namespace _impl {
[[noreturn]] void overrun_high();
[[noreturn]] void overrun_low();
}
template <typename T>
concept IntCastable = std::is_integral_v<T> && std::is_trivially_copyable_v<T>;
/**
* Helper type that allows easily casting between integer types,
* that safely aborts if an overflow were to occur.
* Usage:
* @code
* size_t foobar = 20;
* int real = bounded_cast(foobar);
* @endcode
*/
template <IntCastable Source>
struct bounded_cast {
Source src;
template <IntCastable Target>
[[nodiscard]] constexpr operator Target() const {
if (std::cmp_greater(src, std::numeric_limits<Target>::max())) [[unlikely]] {
_impl::overrun_high();
}
if (std::cmp_less(src, std::numeric_limits<Target>::min())) [[unlikely]] {
_impl::overrun_low();
}
return static_cast<Target>(src);
}
};
}
-1
View File
@@ -285,7 +285,6 @@ inline void be_swap(Mtx& val) {
}
}
#define LE(T) T
#define BE(T) BE<T>
#define BE_HOST(T) (T.host())
#else
@@ -101,7 +101,7 @@ struct JAISoundStatus_ {
bool isMute() const { return field_0x0.flags.mute; }
bool isPaused() const { return field_0x0.flags.paused; }
void pauseWhenOut() {
field_0x1.flags.mPauseWhenOut = 1;
field_0x1.flags.flag3 = 1;
}
/* 0x0 */ union {
@@ -120,9 +120,9 @@ struct JAISoundStatus_ {
/* 0x1 */ union {
u8 value;
struct {
u8 mComesBack : 1;
u8 flag1 : 1;
u8 flag2 : 1;
u8 mPauseWhenOut : 1;
u8 flag3 : 1;
u8 flag4 : 1;
u8 flag5 : 1;
u8 flag6 : 1;
@@ -309,7 +309,7 @@ public:
bool hasLifeTime() const { return status_.field_0x1.flags.flag2; }
void removeLifeTime_() {
status_.field_0x1.flags.mComesBack = false;
status_.field_0x1.flags.flag1 = false;
status_.field_0x1.flags.flag2 = 0;
}
@@ -346,7 +346,7 @@ public:
void setComesBack(bool param_0) {
JUT_ASSERT(354, status_.state.flags.calcedOnce == 0);
status_.field_0x1.flags.mComesBack = 1;
status_.field_0x1.flags.flag1 = 1;
if (param_0) {
status_.pauseWhenOut();
}
@@ -9,14 +9,14 @@
*/
struct JAISoundParamsProperty {
void init() {
mVolume = 1.0f;
mFxMix = 0.0f;
mPitch = 1.0f;
field_0x0 = 1.0f;
field_0x4 = 0.0f;
field_0x8 = 1.0f;
}
/* 0x00 */ f32 mVolume;
/* 0x04 */ f32 mFxMix;
/* 0x08 */ f32 mPitch;
/* 0x00 */ f32 field_0x0;
/* 0x04 */ f32 field_0x4;
/* 0x08 */ f32 field_0x8;
}; // Size: 0xC
/**
@@ -12,27 +12,21 @@ struct JASBasicWaveBank : public JASWaveBank {
struct TWaveHandle : public JASWaveHandle {
TWaveHandle() { mHeap = NULL; }
virtual intptr_t getWavePtr() const;
virtual const JASWaveInfo* getWaveInfo() const { return &mWaveInfo; }
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] void const* getAramBaseAddress() const override { return nullptr; }
#endif
virtual const JASWaveInfo* getWaveInfo() const { return &field_0x4; }
bool compareHeap(JASHeap* heap) const { return mHeap == heap;}
/* 0x04 */ JASWaveInfo mWaveInfo;
/* 0x04 */ JASWaveInfo field_0x4;
/* 0x28 */ JASHeap* mHeap;
};
struct TGroupWaveInfo {
TGroupWaveInfo() {
waveId = 0xffff;
mOffsetStart = -1;
field_0x0 = 0xffff;
field_0x4 = -1;
}
/* 0x00 */ u16 waveId;
/* 0x04 */ int mOffsetStart;
/* 0x00 */ u16 field_0x0;
/* 0x04 */ int field_0x4;
};
struct TWaveGroup : JASWaveArc {
@@ -50,7 +44,7 @@ struct JASBasicWaveBank : public JASWaveBank {
u32 getWaveCount() const { return mWaveCount; }
};
JASBasicWaveBank(IF_DUSK(u32 bankId));
JASBasicWaveBank();
~JASBasicWaveBank();
TWaveGroup* getWaveGroup(u32);
void setGroupCount(u32, JKRHeap*);
@@ -62,7 +56,7 @@ struct JASBasicWaveBank : public JASWaveBank {
JASWaveArc* getWaveArc(u32 param_0) { return getWaveGroup(param_0); }
u32 getArcCount() const { return mGroupCount; }
/* 0x04 */ OSMutex mWaveTableMutex;
/* 0x04 */ OSMutex field_0x4;
/* 0x1C */ TWaveHandle* mWaveTable;
/* 0x20 */ TWaveGroup* mWaveGroupArray;
/* 0x24 */ u16 mHandleCount;
@@ -8,7 +8,6 @@
#include "JSystem/JAudio2/JASWaveInfo.h"
#include "JSystem/JAudio2/JASDSPInterface.h"
#include <os.h>
#include <memory>
struct JASDSPChannel;
@@ -16,20 +15,6 @@ namespace JASDsp {
struct TChannel;
}
#if TARGET_PC
/**
* An object to manage the lifetime of the sample data pointed to by JASChannel.
*
* JASChannel can (optionally) accept an unique_ptr to an object to this type,
* in which case it will be destroyed when the JASChannel is done.
*
* @see JASChannel::mSampleReference
*/
struct JASSampleDataReference {
virtual ~JASSampleDataReference() = default;
};
#endif
/**
* @ingroup jsystem-jaudio
*
@@ -181,23 +166,6 @@ public:
u32 field_0x104;
};
#if TARGET_PC
/**
* Memory address at which this sound effect should consider ARAM to start.
*
* By changing this, sound effects can effectively be played back from anywhere in memory,
* rather than just the emulated ARAM space.
*
* If nullptr, the regular emulated ARAM is used.
*/
void const* mAramBaseAddress;
/**
* @see JASSampleDataReference
*/
std::unique_ptr<JASSampleDataReference> mSampleReference;
#endif
static DUSK_GAME_DATA OSMessageQueue sBankDisposeMsgQ;
static DUSK_GAME_DATA OSMessage sBankDisposeMsg[16];
static DUSK_GAME_DATA OSMessage sBankDisposeList[16];
@@ -109,9 +109,7 @@ namespace JASDsp {
* Pitch shift via changing playback speed.
*/
/* 0x004 */ u16 mPitch;
#if !TARGET_PC
/* 0x006 */ short _unused1;
#endif
/**
* Set to 1 when playback starts, cleared by DSP later,
@@ -120,27 +118,19 @@ namespace JASDsp {
* (Corroborated by fields JASAramStream checks never being cleared explicitly by CPU.)
*/
/* 0x008 */ u16 mResetFlag;
#if !TARGET_PC
/* 0x00A */ u8 _unused2[0x00C - 0x00A];
#endif
/* 0x00C */ s16 mPauseFlag;
#if !TARGET_PC
/* 0x00E */ short _unused3;
#endif
/* 0x010 */ OutputChannelConfig mOutputChannels[DSP_OUTPUT_CHANNELS];
#if !TARGET_PC
/* 0x040 */ u8 _unused4[0x050 - 0x040];
#endif
/* 0x050 */ u16 mAutoMixerPanDolby; // pan is upper 8 bits, dolby lower 8.
/* 0x052 */ u16 mAutoMixerFxMix;
/* 0x054 */ u16 mAutoMixerInitVolume;
/* 0x056 */ u16 mAutoMixerVolume;
/* 0x058 */ u16 mAutoMixerBeenSet;
#if !TARGET_PC
/* 0x05A */ u8 _unused5[0x060 - 0x05A];
/* 0x060 */ short field_0x060; // Only cleared to zero, presumed used by DSP.
/* 0x062 */ u8 _unused6[0x064 - 0x062];
#endif
/**
* Samples per ADPCM frame for ADPCM audio. Seems just set to 1 for PCM formats.
@@ -149,9 +139,7 @@ namespace JASDsp {
/* 0x064 */ u16 mSamplesPerBlock;
/* 0x066 */ short field_0x066; // Only cleared to zero, presumed used by DSP.
/* 0x068 */ u32 mSamplePosition; // Only ever initialized by code, name is guess.
#if !TARGET_PC
/* 0x06C */ u8 _unused7[0x070 - 0x06C];
#endif
/**
* Current audio read position in ARAM. Updated by DSP.
@@ -163,13 +151,11 @@ namespace JASDsp {
* Gets written by DSP, but also CPU.
*/
/* 0x074 */ u32 mSamplesLeft; // Never directly cleared to zero. Seems sus. Cleared by DSP?
#if !TARGET_PC
/* 0x078 */ short field_0x078[4]; // Only cleared to zero, presumed used by DSP.
/* 0x080 */ short field_0x080[20]; // Only cleared to zero, presumed used by DSP.
/* 0x0A8 */ short field_0x0a8[4]; // Only cleared to zero, presumed used by DSP.
/* 0x0B0 */ u16 field_0x0b0[16]; // Only cleared to zero, presumed used by DSP.
/* 0x0D0 */ u8 _unused8[0x100 - 0x0D0];
#endif
/* 0x100 */ u16 mBytesPerBlock;
/* 0x102 */ u16 mLoopFlag;
@@ -190,26 +176,9 @@ namespace JASDsp {
/* 0x118 */ u32 mWaveAramAddress;
/* 0x11C */ int mSampleCount;
/* 0x120 */ s16 fir_filter_params[8];
#if !TARGET_PC
/* 0x130 */ u8 _unused9[0x148 - 0x130];
#endif
/* 0x148 */ s16 iir_filter_params[8];
#if !TARGET_PC
/* 0x158 */ u8 _unused10[0x180 - 0x158];
#endif
#if TARGET_PC
/**
* Memory address at which this sound effect should consider ARAM to start.
* This means fields like mWaveAramAddress will be relative to this pointer instead.
*
* By changing this, sound effects can effectively be played back from anywhere in memory,
* rather than just the emulated ARAM space.
*
* If nullptr, the regular emulated ARAM is used.
*/
void const* mAramBaseAddress;
#endif
};
void boot(void (*)(void*));
@@ -10,18 +10,12 @@ struct JASSimpleWaveBank : JASWaveBank, JASWaveArc {
intptr_t getWavePtr() const;
TWaveHandle();
const JASWaveInfo* getWaveInfo() const;
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] void const* getAramBaseAddress() const override { return nullptr; }
#endif
/* 0x04 */ JASWaveInfo mWaveInfo;
/* 0x28 */ JASHeap* mHeap;
};
JASSimpleWaveBank(IF_DUSK(u32 bankId));
JASSimpleWaveBank();
~JASSimpleWaveBank();
void setWaveTableSize(u32, JKRHeap*);
JASWaveHandle* getWaveHandle(u32) const;
@@ -26,9 +26,7 @@ public:
};
struct TCtrlWave {
// Wave ID in lower half.
// Upper bits appear to be group ID, which is unused by the game code.
/* 0x0 */ BE(u32) mWaveAndGroupId;
/* 0x0 */ BE(u32) _00;
};
struct TWave {
@@ -59,14 +57,13 @@ public:
};
struct TCtrl {
/* 0x0 */ BE(u32) mMagic; // 'C-DF'.
/* 0x0 */ u8 _00[4];
/* 0x4 */ BE(u32) mWaveCount;
/* 0x8 */ TOffset<TCtrlWave> mCtrlWaveOffsets[0];
};
struct TCtrlScene {
/* 0x0 */ BE(u32) mMagic; // 'SCNE'
/* 0x4 */ u8 _00[0x8];
/* 0x0 */ u8 _00[0xC];
/* 0xC */ TOffset<TCtrl> mCtrlOffset;
};
@@ -66,7 +66,7 @@ struct JASWaveArc : JASDisposer {
};
/* 0x04 */ mutable JASHeap mHeap;
/* 0x48 */ u32 mCurrentlyLoaded;
/* 0x48 */ u32 _48;
/* 0x4C */ volatile s32 mStatus;
/* 0x50 */ int mEntryNum;
/* 0x54 */ u32 mFileLength;
@@ -2,11 +2,6 @@
#define JASWAVEINFO_H
#include <types.h>
#include <memory>
#if TARGET_PC
struct JASSampleDataReference;
#endif
struct JASWaveArc;
@@ -22,7 +17,7 @@ struct JASWaveArc;
struct JASWaveInfo {
JASWaveInfo() {
mBaseKey = 0x3c;
mpLoaded = &one;
field_0x20 = &one;
}
/* 0x00 */ u8 mWaveFormat;
@@ -36,7 +31,7 @@ struct JASWaveInfo {
/* 0x18 */ int mSampleCount;
/* 0x1C */ s16 mpLast;
/* 0x1E */ s16 mpPenult;
/* 0x20 */ const u32* mpLoaded;
/* 0x20 */ const u32* field_0x20;
static DUSK_GAME_DATA u32 one;
};
@@ -50,17 +45,6 @@ public:
virtual ~JASWaveHandle() {}
virtual const JASWaveInfo* getWaveInfo() const = 0;
virtual intptr_t getWavePtr() const = 0;
#if TARGET_PC
/**
* @see JASChannel::mAramBaseAddress
*/
[[nodiscard]] virtual void const* getAramBaseAddress() const = 0;
/**
* Create a @ref JASSampleDataReference to keep the sample data for this wave alive.
*/
[[nodiscard]] virtual std::unique_ptr<JASSampleDataReference> getSampleReference() const { return nullptr; }
#endif
};
/**
@@ -69,12 +53,6 @@ public:
*/
class JASWaveBank {
public:
#if TARGET_PC
const u32 bankId;
JASWaveBank(u32 bankId) : bankId(bankId) { }
#endif
virtual ~JASWaveBank() {}
virtual JASWaveHandle* getWaveHandle(u32) const = 0;
virtual JASWaveArc* getWaveArc(u32) = 0;
@@ -10,7 +10,7 @@
*/
struct JAUAudibleParam {
f32 getDopplerPower() const {
return field_0x0.bytes.mDopplerPower * (1.0f / 15.0f);
return field_0x0.bytes.b0_0 * (1.0f / 15.0f);
}
union {
@@ -19,18 +19,14 @@ struct JAUAudibleParam {
BE(u16) f1;
} half;
struct {
u8 mDopplerPower : 4;
u8 mCalculatePriority : 1;
u8 mCalcDistanceVolume : 1;
u8 mCalcFxMix : 1;
u8 mCullAtMaxDistance : 1;
u8 mCalcPan : 1;
u8 mCalcDolby : 1;
/**
* Most bits in this field are unused, 8 indicates clamping of volume
* to ensure it doesn't go below 0.2 in mixChannelOut()
*/
u8 mClampMinVolume : 6;
u8 b0_0 : 4;
u8 b0_4 : 1;
u8 b0_5 : 1;
u8 b0_6 : 1;
u8 b0_7 : 1;
u8 b1_0 : 1;
u8 b1_1 : 1;
u8 b1_2_7 : 6;
u8 b2;
u8 b3;
} bytes;
@@ -5,162 +5,16 @@
#include "JSystem/JAudio2/JASGadget.h"
#include "helpers/endian.h"
// Constants for TypeIDs of JAUSoundTable entries.
/**
* Used as a test to see if the type ID is valid. All other type IDs contain this bit.
*/
#define SOUND_TYPEID_VALID 0x40
/**
* Sound is a sound effect.
*/
#define SOUND_TYPEID_SOUND_EFFECT 0x51
/**
* Sound is a music sequence.
*/
#define SOUND_TYPEID_SEQUENCE 0x60
/**
* Sound is a streamed music file.
*/
#define SOUND_TYPEID_STREAM 0x70
/**
* Sound is a streamed music file. Unsure of difference from SOUND_TYPEID_STREAM
*/
#define SOUND_TYPEID_STREAM_ALT 0x71
//
// Values for mSwBit on sound effect items.
//
/**
* Sound is always calculated as max priority (0).
*/
#define SOUND_SW_ALWAYS_MAX_PRIORITY 0x0000'0001
/**
* Don't calculate volume by distance.
*/
#define SOUND_SW_IGNORE_DISTANCE_VOL 0x0000'0002
/**
* Don't calculate FX mix (reverb) by distance.
*/
#define SOUND_SW_IGNORE_FX_MIX 0x0000'0004
/**
* Offset to shift to access @see SOUND_SW_RANDOM_PITCH_MASK
*/
#define SOUND_SW_RANDOM_PITCH_OFFSET 4
/**
* 4-bit value (0-15) to control the power of pitch randomization on sound playback.
* Code acts different for values above 8, not sure what the exact implication is.
*/
#define SOUND_SW_RANDOM_PITCH_MASK 0x0000'00F0
/**
* Offset to shift to access @see SOUND_SW_DOPPLER_POWER_MASK
*/
#define SOUND_SW_DOPPLER_POWER_OFFSET 8
/**
* 4-bit value (0-15) to scale the power of the Doppler effect for this sound.
*/
#define SOUND_SW_DOPPLER_POWER_MASK 0x0000'0F00
/**
* Don't calculate panning (left/right) values for this sound.
*/
#define SOUND_SW_IGNORE_PAN 0x0000'1000
/**
* Don't calculate Dolby (behind/front) values for this sound.
*/
#define SOUND_SW_IGNORE_DOLBY 0x0000'2000
/**
* 3-bit mask used to select a volume distance/falloff class for this sound.
*/
#define SOUND_SW_VOL_DIST_BIT_MASK 0x0007'0000
/**
* Limit minimum volume of this sound (after distance falloff) to 0.2.
*/
#define SOUND_SW_CLAMP_MIN_VOLUME 0x0008'0000
/**
* 3-bit mask used to select a *different* volume distance/falloff class for this sound.
* @see SOUND_SW_VOL_DIST_BIT_MASK must be zero for this to work.
*/
#define SOUND_SW_VOL_DIST_BIT_2_MASK 0x0070'0000
/**
* Mark sound as "far away" or "culled" when at max distance (selected by distance class).
* This affects a bunch of stuff like culling, automatic stopping, priorities, etc.
*/
#define SOUND_SW_CULL_AT_MAX_DISTANCE 0x0080'0000
/**
* Not sure what this does.
* Something causing volume/pan/dolby adjustment in Z2Audible::setOuterParams?
*/
#define SOUND_SW_VOL_SOMETHING_MASK 0x0F00'0000
/**
* Offset to shift to access @see SOUND_SW_RANDOM_VOLUME_MASK
*/
#define SOUND_SW_RANDOM_VOLUME_OFFSET 28
/**
* 4-bit value (0-15) to control the power of volume randomization on sound playback.
*/
#define SOUND_SW_RANDOM_VOLUME_MASK 0xF000'0000
#define SOUND_VOL_DIST_BIT_MASK_SHIFTED (SOUND_SW_VOL_DIST_BIT_MASK >> 16)
#define SOUND_VOL_DIST_BIT_2_MASK_SHIFTED (SOUND_SW_VOL_DIST_BIT_2_MASK >> 16)
#define SOUND_VOL_SOMETHING_MASK_SHIFTED (SOUND_SW_VOL_SOMETHING_MASK >> 16)
/**
* @ingroup jsystem-jaudio
* A single entry in the sound table.
* Fields are interpreted differently depending on the type ID of the entry,
* which is not stored in this struct.
*
*/
struct JAUSoundTableItem {
u8 mPriority;
u8 mVolume;
union {
/**
* For music sequences: the resource ID of the sequence.
*/
BE(u16) mResourceId;
/**
* For streamed music: bitpacked channel configuration.
*/
BE(u16) mStreamPanParameters;
};
union {
/**
* For sound effects: bitpacked field controlling a *bunch* of audio parameters.
*/
BE(u32) mSwBit;
/**
* For streamed music: offset (relative to start of BST)
* to null-terminated string containing music file path.
*/
BE(u32) mStreamFilePath;
};
/**
* For sound effects: pitch multiplier.
*/
BE(f32) mPitch;
u8 field_0x1;
BE(u16) mResourceId;
BE(u32) field_0x4;
BE(f32) field_0x8;
};
/**
@@ -170,25 +24,23 @@ struct JAUSoundTableItem {
template<typename Root, typename Section, typename Group, typename Typename_0>
struct JAUSoundTable_ {
JAUSoundTable_() {
mData = NULL;
mRoot = 0;
field_0x0 = NULL;
field_0x4 = 0;
}
void reset() {
mData = NULL;
mRoot = NULL;
field_0x0 = NULL;
field_0x4 = NULL;
}
void init(const void* dataStart) {
mData = dataStart;
void init(const void* param_0) {
field_0x0 = param_0;
// magic number is not in debug rom. I'm not sure what this comparison is (maybe some sort of '' number?)
// I also do not know how it is different between JAUSoundTable and JAUSoundNameTable
// Future person here: This is checking for either "BST " or "BSTN", with the second two letters in Root::magicNumber().
// Idk why the operations here are all weird but I can't use objdiff right now.
if (*(BE(u32)*)mData + 0xbdad0000 != Root::magicNumber()) {
mData = NULL;
if (*(BE(u32)*)field_0x0 + 0xbdad0000 != Root::magicNumber()) {
field_0x0 = NULL;
} else {
mRoot = (Root*)((u8*)mData + *((BE(u32)*)mData + 3));
field_0x4 = (Root*)((u8*)field_0x0 + *((BE(u32)*)field_0x0 + 3));
}
}
@@ -196,34 +48,34 @@ struct JAUSoundTable_ {
if (index < 0) {
return NULL;
}
if ((u32)index >= mRoot->mSectionNumber) {
if ((u32)index >= field_0x4->mSectionNumber) {
return NULL;
}
u32 offset = mRoot->mSectionOffsets[index];
u32 offset = field_0x4->mSectionOffsets[index];
if (offset == 0) {
return NULL;
}
return (Section*)((u8*)mData + offset);
return (Section*)((u8*)field_0x0 + offset);
}
Group* getGroup(Section* section, int index) const {
Group* getGroup(Section* param_1, int index) const {
int iVar1;
if (index < 0) {
return NULL;
}
if ((u32)index >= section->mNumGroups) {
if ((u32)index >= param_1->mNumGroups) {
return NULL;
}
u32 offset = section->getGroupOffset(index);
u32 offset = param_1->getGroupOffset(index);
if (offset == 0) {
return NULL;
}
return (Group*)((u8*)mData + offset);
return (Group*)((u8*)field_0x0 + offset);
}
const void* mData;
Root* mRoot;
const void* field_0x0;
Root* field_0x4;
};
/**
@@ -231,7 +83,7 @@ struct JAUSoundTable_ {
*
*/
struct JAUSoundTableRoot {
static inline u32 magicNumber() { return 'T '; } // Second half of "BST "
static inline u32 magicNumber() { return 0x5420; }
BE(u32) mSectionNumber;
BE(u32) mSectionOffsets[0];
};
@@ -282,7 +134,7 @@ struct JAUSoundTableGroup {
BE(u32) mNumItems;
BE(u32) field_0x4;
u8 mTypeIds[0]; // TODO: Should probably be BE(u32), but I can't objdiff rn.
u8 mTypeIds[0];
};
/**
@@ -290,7 +142,7 @@ struct JAUSoundTableGroup {
*
*/
struct JAUSoundTable : public JASGlobalInstance<JAUSoundTable> {
JAUSoundTable(bool setInstance) : JASGlobalInstance<JAUSoundTable>(setInstance) {
JAUSoundTable(bool param_0) : JASGlobalInstance<JAUSoundTable>(param_0) {
}
~JAUSoundTable() {}
@@ -305,11 +157,11 @@ struct JAUSoundTable : public JASGlobalInstance<JAUSoundTable> {
if (offset == 0) {
return NULL;
}
return (JAUSoundTableItem*)((u8*)field_0x0.mData + offset);
return (JAUSoundTableItem*)((u8*)field_0x0.field_0x0 + offset);
}
const void* getResource() const { return field_0x0.mData; }
bool isValid() const { return field_0x0.mData != NULL; }
const void* getResource() const { return field_0x0.field_0x0; }
bool isValid() const { return field_0x0.field_0x0 != NULL; }
JAUSoundTable_<JAUSoundTableRoot,JAUSoundTableSection,JAUSoundTableGroup,void> field_0x0;
};
@@ -319,7 +171,7 @@ struct JAUSoundTable : public JASGlobalInstance<JAUSoundTable> {
*
*/
struct JAUSoundNameTableRoot {
static inline u32 magicNumber() { return 'TN'; } // Second half of "BSTN"
static inline u32 magicNumber() { return 0x544e; }
BE(u32) mSectionNumber;
BE(u32) mSectionOffsets[0];
};
+3 -3
View File
@@ -70,7 +70,7 @@ void JAISe::JAISeCategoryMgr_mixOut_(bool param_0, const JASSoundParams& params,
if (inner_.field_0x26c) {
switch (inner_.track.getStatus()) {
case JASTrack::STATUS_STOPPED:
if (status_.field_0x1.flags.mComesBack) {
if (status_.field_0x1.flags.flag1) {
startTrack_(params);
} else {
stop_JAISound_();
@@ -84,8 +84,8 @@ void JAISe::JAISeCategoryMgr_mixOut_(bool param_0, const JASSoundParams& params,
startTrack_(params);
}
}
} else if (status_.field_0x1.flags.mComesBack) {
if (status_.field_0x1.flags.mPauseWhenOut) {
} else if (status_.field_0x1.flags.flag1) {
if (status_.field_0x1.flags.flag3) {
inner_.track.pause(true);
} else {
stopTrack_();
+11 -11
View File
@@ -167,7 +167,7 @@ JAISeMgr::JAISeMgr(bool setInstance) : JASGlobalInstance<JAISeMgr>(setInstance)
}
bool JAISeMgr::isUsingSeqData(const JAISeqDataRegion& seqDataRegion) {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
if (mCategoryMgrs[i].JAISeCategoryMgr::isUsingSeqData(seqDataRegion)) {
return true;
}
@@ -177,7 +177,7 @@ bool JAISeMgr::isUsingSeqData(const JAISeqDataRegion& seqDataRegion) {
int JAISeMgr::releaseSeqData(const JAISeqDataRegion& seqDataRegion) {
bool r30 = 0;
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
switch (mCategoryMgrs[i].JAISeCategoryMgr::releaseSeqData(seqDataRegion)) {
case 0:
return 0;
@@ -191,14 +191,14 @@ int JAISeMgr::releaseSeqData(const JAISeqDataRegion& seqDataRegion) {
}
void JAISeMgr::setCategoryArrangement(const JAISeCategoryArrangement& arrangement) {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].setMaxActiveSe(arrangement.mItems[i].mMaxActiveSe);
mCategoryMgrs[i].setMaxInactiveSe(arrangement.mItems[i].mMaxInactiveSe);
}
}
void JAISeMgr::getCategoryArrangement(JAISeCategoryArrangement* arrangement) {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
int active = mCategoryMgrs[i].getMaxActiveSe();
JUT_ASSERT(299, active <= 255);
arrangement->mItems[i].mMaxActiveSe = active;
@@ -209,19 +209,19 @@ void JAISeMgr::getCategoryArrangement(JAISeCategoryArrangement* arrangement) {
}
void JAISeMgr::stop() {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].stop();
}
}
void JAISeMgr::stopSoundID(JAISoundID id) {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].stopSoundID(id);
}
}
void JAISeMgr::initParams() {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].getParams()->init();
}
}
@@ -270,16 +270,16 @@ JAISe* JAISeMgr::newSe_(int category, u32 priority) {
void JAISeMgr::calc() {
mParams.calc();
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].JAISeMgr_calc_();
}
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].JAISeMgr_freeDeadSe_();
}
}
void JAISeMgr::mixOut() {
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
mCategoryMgrs[i].JAISeMgr_mixOut_(mParams, mSoundActivity);
}
}
@@ -324,7 +324,7 @@ bool JAISeMgr::startSound(JAISoundID id, JAISoundHandle* handle, const JGeometry
int JAISeMgr::getNumActiveSe() const {
int num = 0;
for (int i = 0; i < NUM_CATEGORIES; i++) {
for (int i = 0; i < 16; i++) {
num += mCategoryMgrs[i].getNumSe();
}
return num;
+4 -4
View File
@@ -54,9 +54,9 @@ s32 JAISoundStatus_::unlockIfLocked() {
}
void JAISoundParams::mixOutAll(const JASSoundParams& inParams, JASSoundParams* outParams, f32 param_2) {
outParams->mVolume = move_.params_.mVolume * (inParams.mVolume * property_.mVolume) * param_2;
outParams->mFxMix = move_.params_.mFxMix + (inParams.mFxMix + property_.mFxMix);
outParams->mPitch = move_.params_.mPitch * (inParams.mPitch * property_.mPitch);
outParams->mVolume = move_.params_.mVolume * (inParams.mVolume * property_.field_0x0) * param_2;
outParams->mFxMix = move_.params_.mFxMix + (inParams.mFxMix + property_.field_0x4);
outParams->mPitch = move_.params_.mPitch * (inParams.mPitch * property_.field_0x8);
outParams->mPan = (inParams.mPan + move_.params_.mPan) - 0.5f;
outParams->mDolby = inParams.mDolby + move_.params_.mDolby;
}
@@ -181,7 +181,7 @@ bool JAISound::calc_JAISound_() {
}
if (audience_ != NULL && audible_ != NULL) {
if ((priority_ = audience_->calcPriority(audible_)) == 0xFFFFFFFF && status_.field_0x1.flags.mComesBack == 0) {
if ((priority_ = audience_->calcPriority(audible_)) == 0xFFFFFFFF && status_.field_0x1.flags.flag1 == 0) {
stop_JAISound_();
}
} else {
+1 -1
View File
@@ -713,7 +713,7 @@ void JASAramStream::channelStart() {
wave_info.mpPenult = 0;
// probably a fake match, this should be set in the JASWaveInfo constructor
static u32 const one = 1;
wave_info.mpLoaded = &one;
wave_info.field_0x20 = &one;
JASChannel* jc = JKR_NEW JASChannel(channelCallback, this);
JUT_ASSERT(963, jc);
jc->setPriority(0x7f7f);
+1 -20
View File
@@ -1,15 +1,11 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JAudio2/JASBank.h"
#include "dusk/mods/svc/audio_res/audio_res.hpp"
#include "JSystem/JAudio2/JASAiCtrl.h"
#include "JSystem/JAudio2/JASBasicInst.h"
#include "JSystem/JAudio2/JASBasicWaveBank.h"
#include "JSystem/JAudio2/JASChannel.h"
using namespace dusk::mods::svc::audio_res;
// NONMATCHING JASPoolAllocObject_MultiThreaded<_> locations
JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8 param_3, u16 param_4,
void (*param_5)(u32, JASChannel*, JASDsp::TChannel*, void*),
@@ -32,23 +28,12 @@ JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8
if (!waveHandle) {
return NULL;
}
#if TARGET_PC
auto const key = AudioWaveKey(static_cast<AudioWaveBank>(waveBank->bankId), stack_60.field_0x1a);
std::lock_guard lock(s_replacements_mutex);
auto const found_replacement = s_replacements.find(key);
if (found_replacement != s_replacements.end()) {
waveHandle = &found_replacement->second;
}
auto const aramBase = waveHandle->getAramBaseAddress();
#endif
const JASWaveInfo* waveInfo = waveHandle->getWaveInfo();
if (!waveInfo) {
return NULL;
}
intptr_t wavePtr = waveHandle->getWavePtr();
if (!wavePtr IF_DUSK(&& !aramBase)) {
if (!wavePtr) {
return NULL;
}
@@ -59,10 +44,6 @@ JASChannel* JASBank::noteOn(JASBank const* param_0, int param_1, u8 param_2, u8
channel->setPriority(param_4);
channel->field_0xdc.mWaveInfo = *waveInfo;
channel->mWaveAramAddress = wavePtr;
#if TARGET_PC
channel->mAramBaseAddress = aramBase;
channel->mSampleReference = waveHandle->getSampleReference();
#endif
channel->field_0xdc.mChannelType = stack_60.field_0x1c;
channel->setBankDisposeID(param_0);
channel->setInitPitch(stack_60.mPitch * (waveInfo->mSampleRate / JASDriver::getDacRate()));
+16 -16
View File
@@ -6,12 +6,12 @@
#include "JSystem/JUtility/JUTAssert.h"
#include <stdint.h>
JASBasicWaveBank::JASBasicWaveBank(IF_DUSK(u32 bankId)) IF_DUSK(: JASWaveBank(bankId)) {
JASBasicWaveBank::JASBasicWaveBank() {
mWaveTable = NULL;
mWaveGroupArray = NULL;
mHandleCount = 0;
mGroupCount = 0;
OSInitMutex(&mWaveTableMutex);
OSInitMutex(&field_0x4);
}
JASBasicWaveBank::~JASBasicWaveBank() {
@@ -44,13 +44,13 @@ void JASBasicWaveBank::setWaveTableSize(u32 param_0, JKRHeap* param_1) {
}
void JASBasicWaveBank::incWaveTable(JASBasicWaveBank::TWaveGroup const* param_0) {
JASMutexLock lock(&mWaveTableMutex);
JASMutexLock lock(&field_0x4);
for (u32 i = 0; i < param_0->getWaveCount(); i++) {
TWaveHandle* handle = mWaveTable + param_0->getWaveID(i);
if (!handle->mHeap) {
handle->mHeap = &param_0->mHeap;
handle->mWaveInfo.mpLoaded = &param_0->mCurrentlyLoaded;
handle->mWaveInfo.mOffsetStart = param_0->mCtrlWaveArray[i].mOffsetStart;
handle->field_0x4.field_0x20 = &param_0->_48;
handle->field_0x4.mOffsetStart = param_0->mCtrlWaveArray[i].field_0x4;
}
}
}
@@ -58,13 +58,13 @@ void JASBasicWaveBank::incWaveTable(JASBasicWaveBank::TWaveGroup const* param_0)
DUSK_GAME_DATA u32 JASBasicWaveBank::mNoLoad;
void JASBasicWaveBank::decWaveTable(JASBasicWaveBank::TWaveGroup const* param_0) {
JASMutexLock lock(&mWaveTableMutex);
JASMutexLock lock(&field_0x4);
for (u32 i = 0; i < param_0->getWaveCount(); i++) {
TWaveHandle* handle = mWaveTable + param_0->getWaveID(i);
if (handle->mHeap == &param_0->mHeap) {
handle->mHeap = NULL;
handle->mWaveInfo.mpLoaded = &mNoLoad;
handle->mWaveInfo.mOffsetStart = -1;
handle->field_0x4.field_0x20 = &mNoLoad;
handle->field_0x4.mOffsetStart = -1;
}
}
}
@@ -80,15 +80,15 @@ JASWaveHandle* JASBasicWaveBank::getWaveHandle(u32 param_0) const {
}
void JASBasicWaveBank::setWaveInfo(JASBasicWaveBank::TWaveGroup* wgrp, int index,
u16 waveId, JASWaveInfo const& param_3) {
u16 param_2, JASWaveInfo const& param_3) {
JUT_ASSERT(204, wgrp);
JUT_ASSERT(205, index < wgrp->mWaveCount);
JUT_ASSERT(206, index >= 0);
mWaveTable[waveId].mWaveInfo = param_3;
mWaveTable[waveId].mWaveInfo.mpLoaded = &mNoLoad;
mWaveTable[waveId].mWaveInfo.mOffsetStart = -1;
wgrp->mCtrlWaveArray[index].waveId = waveId;
wgrp->mCtrlWaveArray[index].mOffsetStart = param_3.mOffsetStart;
mWaveTable[param_2].field_0x4 = param_3;
mWaveTable[param_2].field_0x4.field_0x20 = &mNoLoad;
mWaveTable[param_2].field_0x4.mOffsetStart = -1;
wgrp->mCtrlWaveArray[index].field_0x0 = param_2;
wgrp->mCtrlWaveArray[index].field_0x4 = param_3.mOffsetStart;
}
JASBasicWaveBank::TWaveGroup::TWaveGroup() {
@@ -122,7 +122,7 @@ void JASBasicWaveBank::TWaveGroup::onEraseDone() {
u32 JASBasicWaveBank::TWaveGroup::getWaveID(int index) const {
JUT_ASSERT(298, index < mWaveCount);
JUT_ASSERT(299, index >= 0);
return mCtrlWaveArray[index].waveId;
return mCtrlWaveArray[index].field_0x0;
}
intptr_t JASBasicWaveBank::TWaveHandle::getWavePtr() const {
@@ -131,5 +131,5 @@ intptr_t JASBasicWaveBank::TWaveHandle::getWavePtr() const {
if (base == 0) {
return 0;
}
return (intptr_t)base + mWaveInfo.mOffsetStart;
return (intptr_t)base + field_0x4.mOffsetStart;
}
+2 -8
View File
@@ -26,9 +26,6 @@ JASChannel::JASChannel(Callback i_callback, void* i_callbackData) :
mCallback(i_callback),
mCallbackData(i_callbackData),
mUpdateTimer(0),
#if TARGET_PC
mAramBaseAddress(nullptr),
#endif
mBankDisposeID(NULL),
mKey(0),
mVelocity(0x7f),
@@ -240,7 +237,7 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) {
mCallback(CB_START, this, i_channel, mCallbackData);
}
if (field_0xdc.mWaveInfo.mpLoaded[0] == 0) {
if (field_0xdc.mWaveInfo.field_0x20[0] == 0) {
JUT_WARN_DEVICE(346, 2, "%s", "Lost wave data while playing");
mDspCh->free();
mDspCh = NULL;
@@ -259,9 +256,6 @@ s32 JASChannel::initialUpdateDSPChannel(JASDsp::TChannel* i_channel) {
switch (field_0xdc.mChannelType) {
case 0:
i_channel->setWaveInfo(field_0xdc.mWaveInfo, mWaveAramAddress, mSkipSamples);
#if TARGET_PC
i_channel->mAramBaseAddress = mAramBaseAddress;
#endif
break;
case 2:
i_channel->setOscInfo(mOscillatorSomething);
@@ -321,7 +315,7 @@ s32 JASChannel::updateDSPChannel(JASDsp::TChannel* i_channel) {
mCallback(CB_PLAY, this, i_channel, mCallbackData);
}
if (field_0xdc.mWaveInfo.mpLoaded[0] == 0) {
if (field_0xdc.mWaveInfo.field_0x20[0] == 0) {
JUT_WARN_DEVICE(456, 2, "%s","Lost wave data while playing");
mDspCh->free();
mDspCh = NULL;
@@ -523,12 +523,9 @@ void JASDsp::TChannel::init() {
void JASDsp::TChannel::playStart() {
JUT_ASSERT(508, dspMutex);
field_0x10c = 0;
#if !TARGET_PC
field_0x060 = 0;
#endif
mResetFlag = 1;
field_0x066 = 0;
#if !TARGET_PC
int i;
for (i = 0; i < 4; i++) {
field_0x078[i] = 0;
@@ -537,7 +534,6 @@ void JASDsp::TChannel::playStart() {
for (i = 0; i < 20; i++) {
field_0x080[i] = 0;
}
#endif
mIsActive = 1;
}
@@ -605,11 +601,9 @@ void JASDsp::TChannel::setWaveInfo(JASWaveInfo const& waveInfo, u32 aramAddress,
break;
}
}
#if !TARGET_PC
for (i = 0; i < 16; i++) {
field_0x0b0[i] = 0;
}
#endif
}
}
@@ -3,7 +3,7 @@
#include "JSystem/JAudio2/JASSimpleWaveBank.h"
#include <stdint.h>
JASSimpleWaveBank::JASSimpleWaveBank(IF_DUSK(u32 bankId)) IF_DUSK(: JASWaveBank(bankId)) {
JASSimpleWaveBank::JASSimpleWaveBank() {
mWaveTable = NULL;
mWaveTableSize = 0;
}
@@ -28,7 +28,7 @@ JASWaveHandle* JASSimpleWaveBank::getWaveHandle(u32 no) const {
void JASSimpleWaveBank::setWaveInfo(u32 no, JASWaveInfo const& waveInfo) {
mWaveTable[no].mWaveInfo = waveInfo;
mWaveTable[no].mWaveInfo.mpLoaded = &mCurrentlyLoaded;
mWaveTable[no].mWaveInfo.field_0x20 = &_48;
mWaveTable[no].mHeap = &mHeap;
}
+6 -6
View File
@@ -30,7 +30,7 @@ JASBasicWaveBank* JASWSParser::createBasicWaveBank(void const* stream, JKRHeap*
u32 free_size = heap->getFreeSize();
THeader* header = (THeader*)stream;
JASBasicWaveBank* wave_bank = JKR_NEW_ARGS (heap, 0) JASBasicWaveBank IF_DUSK((header->mId));
JASBasicWaveBank* wave_bank = JKR_NEW_ARGS (heap, 0) JASBasicWaveBank;
if (wave_bank == NULL) {
return NULL;
}
@@ -60,7 +60,7 @@ JASBasicWaveBank* JASWSParser::createBasicWaveBank(void const* stream, JKRHeap*
wave_info.mpLast = wave->mpLast;
wave_info.mpPenult = wave->mpPenult;
TCtrlWave* ctrl_wave = ctrl->mCtrlWaveOffsets[j].ptr(header);
u16 local_74 = JSULoHalf(ctrl_wave->mWaveAndGroupId);
u16 local_74 = JSULoHalf(ctrl_wave->_00);
wave_bank->setWaveInfo(wave_group, j, local_74, wave_info);
}
wave_group->setFileName(archive->mFileName);
@@ -82,7 +82,7 @@ JASSimpleWaveBank* JASWSParser::createSimpleWaveBank(void const* stream, JKRHeap
return NULL;
}
JASSimpleWaveBank* wave_bank = JKR_NEW_ARGS (heap, 0) JASSimpleWaveBank IF_DUSK((header->mId));
JASSimpleWaveBank* wave_bank = JKR_NEW_ARGS (heap, 0) JASSimpleWaveBank;
if (wave_bank == NULL) {
return NULL;
}
@@ -94,7 +94,7 @@ JASSimpleWaveBank* JASWSParser::createSimpleWaveBank(void const* stream, JKRHeap
TWaveArchive* archive = archiveBank->mArchiveOffsets[0].ptr(header);
for (int i = 0; i < ctrl->mWaveCount; i++) {
TCtrlWave* ctrlWave = ctrl->mCtrlWaveOffsets[i].ptr(header);
u32 tmp = JSULoHalf(ctrlWave->mWaveAndGroupId);
u32 tmp = JSULoHalf(ctrlWave->_00);
if (max < tmp) {
max = tmp;
}
@@ -116,8 +116,8 @@ JASSimpleWaveBank* JASWSParser::createSimpleWaveBank(void const* stream, JKRHeap
wave_info.mpLast = wave->mpLast;
wave_info.mpPenult = wave->mpPenult;
TCtrlWave* ctrl_wave = ctrl->mCtrlWaveOffsets[i].ptr(header);
u32 waveId = JSULoHalf(ctrl_wave->mWaveAndGroupId);
wave_bank->setWaveInfo(waveId, wave_info);
u32 tmp = JSULoHalf(ctrl_wave->_00);
wave_bank->setWaveInfo(tmp, wave_info);
}
wave_bank->setFileName(archive->mFileName);
@@ -38,7 +38,7 @@ char* JASWaveArcLoader::getCurrentDir() {
}
JASWaveArc::JASWaveArc() : mHeap(this) {
mCurrentlyLoaded = 0;
_48 = 0;
mStatus = 0;
mEntryNum = -1;
mFileLength = 0;
@@ -57,7 +57,7 @@ bool JASWaveArc::loadSetup(u32 param_0) {
if (mStatus != 1) {
return false;
}
mCurrentlyLoaded = 1;
_48 = 1;
mStatus = 2;
return true;
}
@@ -71,7 +71,7 @@ bool JASWaveArc::eraseSetup() {
mStatus = 0;
return false;
}
mCurrentlyLoaded = 0;
_48 = 0;
mStatus = 0;
return true;
}
@@ -91,7 +91,7 @@ void JASWaveArc::loadToAramCallback(void* this_) {
bool JASWaveArc::sendLoadCmd() {
JASMutexLock mutexLock(&mMutex);
mCurrentlyLoaded = 0;
_48 = 0;
mStatus = 1;
loadToAramCallbackParams commandInfo;
commandInfo.mWavArc = this;
-19
View File
@@ -1,19 +0,0 @@
cmake_minimum_required(VERSION 3.25)
project(audio_mod CXX)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "Path to dusk source root")
option(DUSK_MOD_USE_FULL_TREE "Use full build instead of the minimal mod SDK" OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (DUSK_MOD_USE_FULL_TREE)
add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL)
else ()
add_subdirectory("${DUSK_DIR}/sdk" dusk-sdk EXCLUDE_FROM_ALL)
endif ()
endif ()
add_mod(audio_mod
SOURCES src/mod.cpp
MOD_JSON mod.json
RES_DIR res
)
-7
View File
@@ -1,7 +0,0 @@
{
"id": "dev.twilitrealm.audio_mod",
"name": "[DEMO] Audio Mod",
"version": "1.0.0",
"author": "You, the listener",
"description": "An example Dusklight mod"
}
-1
View File
@@ -1 +0,0 @@
go.opus and go.wav are licensed CC0, from https://kenney.nl/assets/voiceover-pack
Binary file not shown.
Binary file not shown.
-39
View File
@@ -1,39 +0,0 @@
#include "mods/service.hpp"
#include "mods/svc/audio_res.h"
#include "mods/svc/log.h"
DEFINE_MOD();
IMPORT_SERVICE(LogService, svc_log);
IMPORT_SERVICE(AudioResService, svc_audio_res);
extern "C" {
MOD_EXPORT ModResult mod_initialize(ModError*) {
svc_log->info(mod_ctx, "template_mod initialized");
AudioWaveHandle handle;
svc_audio_res->replace_wave(
mod_ctx,
SoundEffects,
4238,
"res/go.opus",
nullptr,
&handle);
svc_audio_res->replace_wave(
mod_ctx,
SoundEffects,
4237,
"res/go.opus",
nullptr,
&handle);
return MOD_OK;
}
MOD_EXPORT ModResult mod_update(ModError*) {
return MOD_OK;
}
MOD_EXPORT ModResult mod_shutdown(ModError*) {
svc_log->info(mod_ctx, "template_mod unloaded");
return MOD_OK;
}
}
+115
View File
@@ -0,0 +1,115 @@
cmake_minimum_required(VERSION 3.25)
project(randomizer CXX)
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(DUSK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../.." CACHE PATH "Path to dusk source root")
option(DUSK_MOD_USE_FULL_TREE "Use full build instead of the minimal mod SDK" OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if (DUSK_MOD_USE_FULL_TREE)
add_subdirectory("${DUSK_DIR}" dusk EXCLUDE_FROM_ALL)
else ()
add_subdirectory("${DUSK_DIR}/sdk" dusk-sdk EXCLUDE_FROM_ALL)
endif ()
endif ()
# Generator dependencies, linked statically into the mod library (no CRT crossing).
include(FetchContent)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "" FORCE)
set(YAML_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
message(STATUS "randomizer: Fetching yaml-cpp")
FetchContent_Declare(
yaml-cpp
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
GIT_TAG yaml-cpp-0.9.0
)
message(STATUS "randomizer: Fetching base64pp")
FetchContent_Declare(
base64pp
GIT_REPOSITORY https://github.com/matheusgomes28/base64pp.git
GIT_TAG v0.2.0-rc0
)
message(STATUS "randomizer: Fetching battery-embed")
FetchContent_Declare(
battery-embed
GIT_REPOSITORY https://github.com/batterycenter/embed.git
GIT_TAG fdbae3f
)
FetchContent_MakeAvailable(yaml-cpp base64pp battery-embed)
set(RANDOMIZER_GENERATOR_SOURCES
generator/logic/area.cpp
generator/logic/dungeon.cpp
generator/logic/entrance.cpp
generator/logic/entrance_shuffle.cpp
generator/logic/fill.cpp
generator/logic/flatten/bits.cpp
generator/logic/flatten/flatten.cpp
generator/logic/flatten/simplify_algebraic.cpp
generator/logic/hints.cpp
generator/logic/item.cpp
generator/logic/item_pool.cpp
generator/logic/location.cpp
generator/logic/plandomizer.cpp
generator/logic/requirement.cpp
generator/logic/search.cpp
generator/logic/spoiler_log.cpp
generator/logic/world.cpp
generator/randomizer.cpp
generator/seedgen/config.cpp
generator/seedgen/seed.cpp
generator/seedgen/settings.cpp
generator/utility/color.cpp
generator/utility/common.cpp
generator/utility/endian.cpp
generator/utility/file.cpp
generator/utility/log.cpp
generator/utility/path.cpp
generator/utility/platform.cpp
generator/utility/random.cpp
generator/utility/string.cpp
generator/utility/text.cpp
generator/utility/time.cpp
)
set(RANDOMIZER_SOURCES
src/flags.cpp
src/messages.cpp
src/randomizer_context.cpp
src/stages.cpp
src/tools.cpp
src/verify_item_functions.cpp
src/paths.cpp
src/session.cpp
)
add_mod(randomizer
FEATURES game
SOURCES src/mod.cpp ${RANDOMIZER_GENERATOR_SOURCES} ${RANDOMIZER_SOURCES}
MOD_JSON mod.json
RES_DIR res
)
target_link_libraries(randomizer PRIVATE yaml-cpp::yaml-cpp base64pp fmt::fmt)
string(LENGTH "${CMAKE_CURRENT_SOURCE_DIR}/" RANDOMIZER_SOURCE_PATH_SIZE)
target_compile_definitions(randomizer PRIVATE
RANDO_DATA_PATH="generator/data/"
SOURCE_PATH_SIZE=${RANDOMIZER_SOURCE_PATH_SIZE}
)
# Embed the generator's YAML data into the mod library. Paths are relative to this
# directory and must match the RANDO_DATA_PATH-based b::embed<> identifiers in code.
file(GLOB_RECURSE RANDOMIZER_DATA RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/generator/data/*")
b_embed(randomizer "res/shadow_crystal.bti")
foreach (RANDOMIZER_FILE IN LISTS RANDOMIZER_DATA)
if (RANDOMIZER_FILE MATCHES "^generator/data/tests")
continue()
endif ()
b_embed(randomizer "${RANDOMIZER_FILE}")
endforeach ()
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,486 @@
# Patches for NPC text flows
# NOTE: All data is expressed in little endian
0: # zel_00.bmg
# Change the following indices of Midna's flows to jump to our custom choices
# instead. These are all the flow jumps that normally determine which "Talk to Midna"
# text is displayed.
- index:
- 0x1
- 0x9
- 0xC
- 0x8F
- 0x192
- 0x1A4
- 0x18F
- 0x197
- 0x1BC
- 0x1C9
type: event
event: 42
parameters: 0x00000000
next node index: Custom Midna Call Begin
#1: # zel_01.bmg
2: # zel_02.bmg
# Patch Barnes branch to see if you can buy the bomb bag to use
# query 54 (custom event check) instead of query 22 (how many bomb bags the player has)
- index: 0x47C
type: branch
num results: 2
query: 53
parameters: 0x004D
next node index: 0x340
#3: # zel_03.bmg
4: # zel_04.bmg - Castle Town
# Patch Charlo to check for 100 rupees instead of 30
- index: 0x34A
type: branch
num results: 2
query: 6
parameters: 0x0064
next node index: 0x222
# Patch Charlo to take 100 rupees from Link instead of 30
- index: 0x34E
type: event
event: 41
parameters: 0x00000064
next node index: 0x226
# Patch Charlo to add 100 rupees to his counter instead of 30
- index: 0x357
type: event
event: 3
parameters: 0x00000064
next node index: 0x22B
# Patch Malo Mart door person to not check for time of day.
# Change from branch node that checks time of day to event node
# that does nothing.
- index: 0x1A5
type: event
event: 42
parameters: 0x00000000
next node index: 0x10C
5: # zel_05.bmg
# Patch Yeta flow to always give the map check even if the player has obtained the Ordon Cheese
- index: 0x8
type: event
event: 42
parameters: 0x00000000
next node index: 0x8
# Patch Yeta flow to always give the map check even if the player has obtained the Ordon Cheese
- index: 0x5
type: event
event: 42
parameters: 0x00000000
next node index: 0x3
# Patch Gor Liggs to not set the flag for the third key shard
# Change event index 17 to event index 42 which does nothing
- index: 0x258
type: event
event: 42
parameters: 0x00000000
next node index: 0x1AC
#6: # zel_06.bmg
#7: # zel_07.bmg
#8: # zel_08.bmg
# Custom Flow Nodes
9:
# Start of custom midna call tree. Begin by checking if we can change time
# of day to see if we show that choice
- name: Custom Midna Call Begin
type: branch
num results: 2
query: 54
parameters: 0x0000
next node index: 0xFFFF
results:
- Custom Midna Call 3 Choice Select Setup # Can change time of day
- Custom Midna Call 2 Choice Select Setup # Can not change time of day
#################################################
# CUSTOM MIDNA CALL 2 CHOICE FLOW #
#################################################
- name: Custom Midna Call 2 Choice Select Setup
type: event
event: 13
parameters: 0x00000003
next node index: Custom Midna Call 2 Choice Intro
- name: Custom Midna Call 2 Choice Intro
type: message
inf index: Custom Midna Call Need Something Text
next flow index: Custom Midna Call 2 Choice
- name: Custom Midna Call 2 Choice
type: message
inf index: Custom Midna Call 2 Choice Text
next flow index: Custom Midna Call 2 Choice Branch
- name: Custom Midna Call 2 Choice Branch
type: branch
num results: 3
query: 35
parameters: 0x0000
next node index: 0xFFFF
results:
- Custom Midna Call Hints # Hints
- Custom Midna Call Return to Spawn Branch # Return to Spawn
- 0xFFFF # (B button pressed)
#################################################
# CUSTOM MIDNA CALL 3 CHOICE FLOW #
#################################################
- name: Custom Midna Call 3 Choice Select Setup
type: event
event: 13
parameters: 0x00000004
next node index: Custom Midna Call 3 Choice Intro
- name: Custom Midna Call 3 Choice Intro
type: message
inf index: Custom Midna Call Need Something Text
next flow index: Custom Midna Call 3 Choice
- name: Custom Midna Call 3 Choice
type: message
inf index: Custom Midna Call 3 Choice Text
next flow index: Custom Midna Call 3 Choice Branch
- name: Custom Midna Call 3 Choice Branch
type: branch
num results: 4
query: 36
parameters: 0x0000
next node index: 0xFFFF
results:
- Custom Midna Call Hints # Hints
- Custom Midna Call Change Time # Change time of day
- Custom Midna Call Return to Spawn Branch # Return to Spawn
- 0xFFFF # (B button pressed)
#################################################
# CUSTOM MIDNA CALL CHOICE OPTIONS #
#################################################
- name: Custom Midna Call Hints
type: message
inf index: Custom Midna Call Hints Text
next flow index: 0xFFFF
- name: Custom Midna Call Change Time
type: event
event: 44
parameters: 0x00000000
next node index: 0x116
- name: Custom Midna Call Return to Spawn Branch
type: branch
num results: 3
query: 55
parameters: 0x0000
next node index: 0xFFFF
results:
- Return to Spawn Dungeon Choice Select Setup
- Return to Spawn Dungeon No Choice Select Setup
- Return to Base Spawn
#################################################
# RETURN TO SPAWN DUNGEON CHOICE FLOW #
#################################################
- name: Return to Spawn Dungeon Choice Select Setup
type: event
event: 13
parameters: 0x00000004
next node index: Return to Spawn Dungeon Choice Intro
- name: Return to Spawn Dungeon Choice Intro
type: message
inf index: Return to Spawn Dungeon Intro Text
next flow index: Return to Spawn Dungeon Choice
- name: Return to Spawn Dungeon Choice
type: message
inf index: Return to Spawn Dungeon Choice Text
next flow index: Return to Spawn Dungeon Choice Branch
- name: Return to Spawn Dungeon Choice Branch
type: branch
num results: 4
query: 36
parameters: 0x0000
next node index: 0xFFFF
results:
- Return to Dungeon Spawn # Dungeon entrance
- 0xFFFF # Nevermind
- Return to Base Spawn # Spawn
- 0xFFFF # (B button pressed)
#################################################
# RETURN TO SPAWN DUNGEON NO CHOICE FLOW #
#################################################
- name: Return to Spawn Dungeon No Choice Select Setup
type: event
event: 13
parameters: 0x00000003
next node index: Return to Spawn Dungeon No Choice Intro
- name: Return to Spawn Dungeon No Choice Intro
type: message
inf index: Return to Spawn Dungeon Intro Text
next flow index: Return to Spawn No Dungeon Choice
- name: Return to Spawn Dungeon No Choice
type: message
inf index: Return to Spawn Dungeon No Choice Text
next flow index: Return to Spawn Dungeon No Choice Branch
- name: Return to Spawn Dungeon No Choice Branch
type: branch
num results: 3
query: 35
parameters: 0x0000
next node index: 0xFFFF
results:
- 0xFFFF # Nevermind
- Return to Base Spawn # Spawn
- 0xFFFF # (B button pressed)
#################################################
# RETURN TO SPAWN EVENTS #
#################################################
# Use custom event index 45 to setup returning to spawn. A non-zero
# parameter value indicates to try and use a place override if one
# exists for the current stage
- name: Return to Dungeon Spawn
type: event
event: 45
parameters: 0x00000001
next node index: 0x116
# Use custom event index 45 to setup returning to spawn. A parameter
# value of zero indicates to always return to the starting spawn
- name: Return to Base Spawn
type: event
event: 45
parameters: 0x00000000
next node index: 0x116
#################################################
# HINT SIGNS #
#################################################
- name: Ordon Hint Sign
index: 21100
type: message
inf index: Ordon Hint Sign Text
next flow index: 0xFFFF
- name: South Faron Woods Hint Sign
index: 21101
type: message
inf index: South Faron Woods Hint Sign Text
next flow index: 0xFFFF
- name: Sacred Grove Hint Sign
index: 21102
type: message
inf index: Sacred Grove Hint Sign Text
next flow index: 0xFFFF
- name: Faron Field Hint Sign
index: 21103
type: message
inf index: Faron Field Hint Sign Text
next flow index: 0xFFFF
- name: Kakariko Gorge Hint Sign
index: 21104
type: message
inf index: Kakariko Gorge Hint Sign Text
next flow index: 0xFFFF
- name: Kakariko Village Hint Sign
index: 21105
type: message
inf index: Kakariko Village Hint Sign Text
next flow index: 0xFFFF
- name: Kakariko Graveyard Hint Sign
index: 21106
type: message
inf index: Kakariko Graveyard Hint Sign Text
next flow index: 0xFFFF
- name: Eldin Field Hint Sign
index: 21107
type: message
inf index: Eldin Field Hint Sign Text
next flow index: 0xFFFF
- name: North Eldin Field Hint Sign
index: 21108
type: message
inf index: North Eldin Field Hint Sign Text
next flow index: 0xFFFF
- name: Hidden Village Hint Sign
index: 21109
type: message
inf index: Hidden Village Hint Sign Text
next flow index: 0xFFFF
- name: Lanayru Field Hint Sign
index: 21110
type: message
inf index: Lanayru Field Hint Sign Text
next flow index: 0xFFFF
- name: Beside Castle Town Hint Sign
index: 21111
type: message
inf index: Beside Castle Town Hint Sign Text
next flow index: 0xFFFF
- name: Castle Town Center Hint Sign
index: 21112
type: message
inf index: Castle Town Center Hint Sign Text
next flow index: 0xFFFF
- name: Outside South Castle Town Hint Sign
index: 21113
type: message
inf index: Outside South Castle Town Hint Sign Text
next flow index: 0xFFFF
- name: Lake Hylia Bridge Hint Sign
index: 21114
type: message
inf index: Lake Hylia Bridge Hint Sign Text
next flow index: 0xFFFF
- name: Lake Hylia Hint Sign
index: 21115
type: message
inf index: Lake Hylia Hint Sign Text
next flow index: 0xFFFF
- name: Lanayru Spring Hint Sign
index: 21116
type: message
inf index: Lanayru Spring Hint Sign Text
next flow index: 0xFFFF
- name: Lake Lantern Cave Hint Sign
index: 21117
type: message
inf index: Lake Lantern Cave Hint Sign Text
next flow index: 0xFFFF
- name: Fishing Hole Hint Sign
index: 21118
type: message
inf index: Fishing Hole Hint Sign Text
next flow index: 0xFFFF
- name: Zoras Domain Hint Sign
index: 21119
type: message
inf index: Zoras Domain Hint Sign Text
next flow index: 0xFFFF
- name: Snowpeak Hint Sign
index: 21120
type: message
inf index: Snowpeak Hint Sign Text
next flow index: 0xFFFF
- name: Gerudo Desert Hint Sign
index: 21121
type: message
inf index: Gerudo Desert Hint Sign Text
next flow index: 0xFFFF
- name: Bulblin Camp Hint Sign
index: 21122
type: message
inf index: Bulblin Camp Hint Sign Text
next flow index: 0xFFFF
- name: Forest Temple Hint Sign
index: 21123
type: message
inf index: Forest Temple Hint Sign Text
next flow index: 0xFFFF
- name: Goron Mines Hint Sign
index: 21124
type: message
inf index: Goron Mines Hint Sign Text
next flow index: 0xFFFF
- name: Lakebed Temple Hint Sign
index: 21125
type: message
inf index: Lakebed Temple Hint Sign Text
next flow index: 0xFFFF
- name: Arbiters Grounds Hint Sign
index: 21126
type: message
inf index: Arbiters Grounds Hint Sign Text
next flow index: 0xFFFF
- name: Snowpeak Ruins Hint Sign
index: 21127
type: message
inf index: Snowpeak Ruins Hint Sign Text
next flow index: 0xFFFF
- name: Temple of Time First Hint Sign
index: 21128
type: message
inf index: Temple of Time First Hint Sign Text
next flow index: 0xFFFF
- name: Temple of Time Second Hint Sign
index: 21129
type: message
inf index: Temple of Time Second Hint Sign Text
next flow index: 0xFFFF
- name: City in the Sky Hint Sign
index: 21130
type: message
inf index: City in the Sky Hint Sign Text
next flow index: 0xFFFF
- name: Palace of Twilight Hint Sign
index: 21131
type: message
inf index: Palace of Twilight Hint Sign Text
next flow index: 0xFFFF
- name: Hyrule Castle Hint Sign
index: 21132
type: message
inf index: Hyrule Castle Hint Sign Text
next flow index: 0xFFFF
- name: Cave of Ordeals Hint Sign
index: 21133
type: message
inf index: Cave of Ordeals Hint Sign Text
next flow index: 0xFFFF
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+256
View File
@@ -0,0 +1,256 @@
# Macros are a way to shorten or make more explicit the logical requirements
# for certain things. Macros can be used on logic statements like any item and do
# not need any code modifications to run. Simply add them here and they can be used
# in the world graph files.
Can Open Doors: Human_Link
Can Climb Ladders: Human_Link
Can Climb Vines: Human_Link
Can Talk to Humans: Human_Link
Can Swing on Monkeys: Human_Link
Can Pickup Bomblings: Human_Link
Can Pull Lakebed Levers: Human_Link
Can Pull Blocks: Human_Link
Can Ride Boars: Human_Link
Can Summon Hawk: Human_Link
Can Talk to Animals: Wolf_Link
Can Use Senses: Wolf_Link
Can Dig: Wolf_Link
Can Howl: Wolf_Link
Can Sniff: Wolf_Link
Can Midna Jump: Wolf_Link
Can Use Tightrope: Wolf_Link
Not Twilight: Human_Link or Wolf_Link
Slingshot: Slingshot and 'Can_Refill_Slingshot_Seeds' and Human_Link
Lantern: Lantern and 'Can_Refill_Lantern_Oil' and Human_Link
Gale Boomerang: Gale_Boomerang and Human_Link
Iron Boots: Iron_Boots and Human_Link
Bow: Progressive_Bow and 'Can_Refill_Arrows' and Human_Link
Regular Bombs: Bomb_Bag and 'Can_Refill_Regular_Bombs' and Human_Link
Water Bombs: Bomb_Bag and 'Can_Refill_Water_Bombs' and Human_Link
Bombs: Regular_Bombs or Water_Bombs
Bomb Arrows: Bow and Bombs
Spinner: Spinner and Human_Link
Ball and Chain: Ball_and_Chain and Human_Link
Zora Armor: Zora_Armor and Human_Link
Magic Armor: Magic_Armor and Human_Link
Shield: Hylian_Shield or 'Can_Buy_Wooden_Shield'
Bottle: Empty_Bottle and Lantern # Can't empty lantern oil from a bottle until you have the lantern
Asheis Sketch: Asheis_Sketch and Human_Link
Aurus Memo: Aurus_Memo and Human_Link
Renados Letter: Renados_Letter and Human_Link
Invoice: Invoice and Human_Link
Wooden Statue: Wooden_Statue and Human_Link
Ilias Charm: Ilias_Charm and Human_Link
Fishing Rod: Progressive_Fishing_Rod and Human_Link
Coral Earring: count(Progressive_Fishing_Rod, 2) and Human_Link
Sword: Progressive_Sword and Human_Link
Ordon Sword: count(Progressive_Sword, 2) and Human_Link
Master Sword: count(Progressive_Sword, 3) and Human_Link
Light Sword: count(Progressive_Sword, 4) and Human_Link
Big Quiver: count(Progressive_Bow, 2) and 'Can_Refill_Arrows' and Human_Link
Giant Quiver: count(Progressive_Bow, 3) and 'Can_Refill_Arrows' and Human_Link
Clawshot: Progressive_Clawshot and Human_Link
Double Clawshots: count(Progressive_Clawshot, 2) and Human_Link
Dominion Rod: Progressive_Dominion_Rod and Human_Link
Restored Dominion Rod: count(Progressive_Dominion_Rod, 2) and Human_Link
Big Wallet: Progressive_Wallet
Giant Wallet: count(Progressive_Wallet, 2)
Collosal Wallet: count(Progressive_Wallet, 3)
Ending Blow: Sword and Progressive_Hidden_Skill
Shield Attack: Shield and count(Progressive_Hidden_Skill, 2)
Back Slice: Sword and count(Progressive_Hidden_Skill, 3)
Helm Splitter: Sword and Shield_Attack and count(Progressive_Hidden_Skill, 4)
Mortal Draw: Sword and count(Progressive_Hidden_Skill, 5)
Jump Strike: Sword and count(Progressive_Hidden_Skill, 6)
Great Spin: Sword and count(Progressive_Hidden_Skill, 7)
Can Use Back Slice as Sword: Back_Slice_as_Sword == On and count(Progressive_Hidden_Skill, 3)
Can Do Niche Stuff: Impossible # TODO: Make settings for all of these
Can Do Difficult Combat: Impossible # TODO: Make settings for all of these
Can Use Hot Spring Water: Bottle and 'Can_Buy_Hot_Spring_Water'
Can Use Bottled Fairy: Bottle and 'Fairy_Access'
# This will have to change if we allow players to start with less than 3 hearts
Can Survive Damage: Logic_Damage_Multiplier != OHKO or Can_Use_Bottled_Fairy
Can Survive One Bonk: Bonks_Do_Damage == Off or Can_Survive_Damage
Can Survive Two Bonks: Bonks_Do_Damage == Off or Logic_Damage_Multiplier != OHKO or
(Can_Use_Bottled_Fairy and count(Empty_Bottle, 2))
Can Survive Three Bonks: Bonks_Do_Damage == Off or Logic_Damage_Multiplier != OHKO or
(Can_Use_Bottled_Fairy and count(Empty_Bottle, 3))
Can Smash: Bombs or Ball_and_Chain
Can Break Webs: Lantern or Bombs or (Ball_and_Chain and Ball_and_Chain_Webs == On)
Can Light Torches: Lantern
Can Extinguish Torches: Gale_Boomerang
Can Launch Bombs: Bombs and (Gale_Boomerang or Bow)
Can Break Monkey Cage: Sword or Iron_Boots or Spinner or Ball_and_Chain or Wolf_Link or Bombs or
Bow or Clawshot or (Can_Do_Niche_Stuff and Shield_Attack)
Can Cut Hanging Web: Clawshot or Bow or Gale_Boomerang or Ball_and_Chain
Can Break Wooden Barrier: Sword or Can_Smash or Wolf_Link or Can_Use_Back_Slice_as_Sword
Can Refill Air: Zora_Armor # or glitched logic water bombs
Can Cross Quicksand: Wolf_Link or Spinner
Can Break Armor: Ball_and_Chain
Can Break Ice: Ball_and_Chain
Can Launch Canonball: Bombs
Can Knock Down Hyrule Castle Painting: Bow or (Can_Do_Niche_Stuff and (Bombs or Jump_Strike))
Can Knock Down Hanging Baba: Bow or Clawshot or Gale_Boomerang or Slingshot
Has Damaging Item: Sword or Ball_and_Chain or Bow or Bombs or Iron_Boots or Wolf_Link or Spinner
Can Hit Crystal Switch: Clawshot or Has_Damaging_Item
Can Hit Crystal Switch at Range: Clawshot or Bow
Can Complete MDH: Skip_Midna's_Desparate_Hour == On or ('Can_Access_Castle_Town_South' and 'Can_Complete_Lakebed_Temple')
# REGULAR ENEMIES
# A lot of enemies use this identical logical requirement
Can Defeat Generic Enemy: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Bombs or
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Shadow Beast: Sword or (Wolf_Link and Can_Complete_MDH)
Can Defeat Keese: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Slingshot or
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Fire Keese: Can_Defeat_Keese
Can Defeat Ice Keese: Can_Defeat_Keese
Can Defeat Shadow Keese: Can_Defeat_Keese
Can Defeat Rat: Slingshot or Can_Defeat_Generic_Enemy
Can Defeat Ghoul Rat: Can_Use_Senses
Can Defeat Bokoblin: Can_Defeat_Generic_Enemy or Slingshot
Can Defeat Red Bokoblin: Sword or Ball_and_Chain or Giant_Quiver or Wolf_Link or Bombs or
Can_Use_Back_Slice_as_Sword or (Can_Do_Difficult_Combat and (Iron_Boots or Spinner))
Can Defeat Bulblin: Can_Defeat_Generic_Enemy
Can Defeat Deku Baba: Sword or Ball_and_Chain or Bow or Spinner or Shield_Attack or Slingshot or Clawshot or Bombs or
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Big Baba: Can_Defeat_Generic_Enemy
Can Defeat Baba Serpent: Can_Defeat_Generic_Enemy
Can Defeat Walltula: Ball_and_Chain or Slingshot or Bow or Gale_Boomerang or Clawshot
Can Defeat Skulltula: Can_Defeat_Generic_Enemy
Can Defeat Deku Like: Bombs
Can Launch Tileworm: Gale_Boomerang
Can Defeat Tileworm: Gale_Boomerang and Can_Defeat_Generic_Enemy
Can Defeat Stalhound: Can_Defeat_Generic_Enemy
Can Defeat Kargarok: Can_Defeat_Generic_Enemy
Can Defeat Goron: Sword or Ball_and_Chain or Bow or Spinner or Shield_Attack or Slingshot or Clawshot or Bombs or
(Can_Do_Niche_Stuff and Iron_Boots) or (Can_Do_Difficult_Combat and Lantern) or Can_Use_Back_Slice_as_Sword
Can Defeat Torch Slug: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs
Can Defeat Dodongo: Can_Defeat_Generic_Enemy
Can Defeat Beamos: Ball_and_Chain or Bow or Bombs
Can Defeat Leever: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Bombs or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Helmasaur: Can_Defeat_Generic_Enemy
Can Defeat Tektite: Can_Defeat_Generic_Enemy
Can Defeat Toado: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link
Can Defeat Water Toadpoli: Sword or Ball_and_Chain or Bow or Shield_Attack or (Can_Do_Difficult_Combat and Wolf_Link)
Can Defeat Shell Blade: Water_Bombs or (Sword and (Iron_Boots or (Can_Do_Niche_Stuff and Magic_Armor)))
Can Defeat Lizalfos: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Dinalfos: Sword or Ball_and_Chain or Wolf_Link
Can Defeat Chu: Can_Defeat_Generic_Enemy or Clawshot
Can Defeat Chu Worm: (Bombs or Clawshot) and (Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Can_Use_Back_Slice_as_Sword)
Can Defeat Bubble: Can_Defeat_Generic_Enemy
Can Defeat Fire Bubble: Can_Defeat_Bubble
Can Defeat Ice Bubble: Can_Defeat_Bubble
Can Defeat Skull Kid: Bow
Can Defeat Poe: Can_Use_Senses
Can Defeat Stalchild: Can_Defeat_Generic_Enemy
Can Defeat Stalfos: Can_Smash
Can Defeat Redead Knight: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat White Wolfos: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Bombs or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Chilfos: Can_Defeat_Generic_Enemy
Can Defeat Mini Freezard: Can_Defeat_Generic_Enemy
Can Defeat Freezard: Ball_and_Chain
Can Defeat Young Gohma: Sword or Ball_and_Chain or Bow or Spinner or Wolf_Link or Bombs or
(Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Baby Gohma: Can_Defeat_Generic_Enemy or Slingshot or Clawshot
Can Defeat Armos: Can_Defeat_Generic_Enemy or Clawshot
Can Defeat Zant Head: Sword or Wolf_Link or Can_Use_Back_Slice_as_Sword
# MINIBOSSES
Can Defeat Ook: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Dangoro: Iron_Boots and (Sword or Wolf_Link or Bomb_Arrows or (Can_Do_Niche_Stuff and Ball_and_Chain))
Can Defeat Deku Toad: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
Can_Use_Back_Slice_as_Sword or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat King Bulblin Desert: Sword or Ball_and_Chain or Wolf_Link or Giant_Quiver or Can_Use_Back_Slice_as_Sword or
(Can_Do_Difficult_Combat and (Spinner or Iron_Boots or Bombs or Big_Quiver))
Can Defeat Deathsword: Can_Use_Senses and Sword and (Clawshot or Bow or Gale_Boomerang)
Can Defeat Darkhammer: Sword or Ball_and_Chain or Bow or Wolf_Link or Bombs or
(Can_Use_Back_Slice_as_Sword and Can_Do_Difficult_Combat) or (Can_Do_Niche_Stuff and Iron_Boots)
Can Defeat Darknut: Sword or (Can_Do_Difficult_Combat and (Bombs or Ball_and_Chain))
Can Defeat Aerolfos: Clawshot and (Sword or Ball_and_Chain or Wolf_Link or (Can_Do_Niche_Stuff and Iron_Boots))
Can Defeat Phantom Zant: Sword or Wolf_Link
Can Defeat King Bulblin Castle: Sword or Ball_and_Chain or Wolf_Link or Big_Quiver or (Can_Do_Difficult_Combat and
(Spinner or Iron_Boots or Bombs or Can_Use_Back_Slice_as_Sword))
# BOSSES
Can Defeat Diababa: Can_Launch_Bombs or (Gale_Boomerang and
(Sword or Ball_and_Chain or Wolf_Link or Bombs or
(Can_Do_Difficult_Combat and Can_Use_Back_Slice_as_Sword) or (Can_Do_Niche_Stuff and Iron_Boots)))
Can Defeat Fyrus: Bow and Iron_Boots and (Sword or (Can_Do_Difficult_Combat and Can_Use_Back_Slice_as_Sword))
Can Defeat Morpheel: Iron_Boots and Clawshot and Sword and Can_Refill_Air
Can Defeat Stallord: Spinner and (Sword or Can_Do_Difficult_Combat)
Can Defeat Blizzeta: Ball_and_Chain
Can Defeat Armogohma: Bow and Dominion_Rod
Can Defeat Argorok: Double_Clawshots and Ordon_Sword and (Iron_Boots or (Can_Do_Niche_Stuff and Magic_Armor))
Can Defeat Zant: Master_Sword and Gale_Boomerang and (Iron_Boots or (Can_Do_Niche_Stuff and Magic_Armor)) and
Can_Refill_Air and Clawshot and Ball_and_Chain
Can Open North Faron Woods Gate: North_Faron_Woods_Gate_Key or Small_Keys == Keysy
Can Complete Prologue: Skip_Prologue == On or (Sword and Slingshot and Can_Open_North_Faron_Woods_Gate)
# You can only use warp portals from certain stages.
# 'Can_Warp' is an event added to any logical area
# which is part of a stage that players can warp from.
Can Use Warp Portals: Wolf_Link and 'Can_Warp' and Can_Complete_Prologue
Can Free All Monkeys in Forest Temple: "'Can_Free_Monkey_in_Entrance_Room' and 'Can_Free_Monkey_on_Totem' and
'Can_Free_Monkey_in_Big_Baba_Room' and 'Can_Free_Monkey_in_West_Tileworm_Room' and
'Can_Free_Monkey_in_East_Tileworm_Room' and 'Can_Free_Monkey_in_Dark_Spider_Room' and
'Can_Free_Monkey_in_North_Deku_Like_Room'"
Has Sword For Temple of Time: Temple_of_Time_Sword_Requirement == None or
(Temple_of_Time_Sword_Requirement == Wooden_Sword and Sword) or
(Temple_of_Time_Sword_Requirement == Ordon_Sword and Ordon_Sword) or
(Temple_of_Time_Sword_Requirement == Master_Sword and Master_Sword) or
(Temple_of_Time_Sword_Requirement == Light_Sword and Light_Sword)
Can Complete Faron Twilight: Faron_Twilight_Cleared == On or count(Faron_Twilight_Tear, 16)
Can Complete Eldin Twilight: Eldin_Twilight_Cleared == On or count(Eldin_Twilight_Tear, 16)
Can Complete Lanayru Twilight: Lanayru_Twilight_Cleared == On or count(Lanayru_Twilight_Tear, 16)
Can Complete All Twilight: Can_Complete_Faron_Twilight and Can_Complete_Eldin_Twilight and Can_Complete_Lanayru_Twilight
Can Defeat Faron Twilit Insect: Twilight
Can Defeat Eldin Twilit Insect: Twilight
Can Defeat Lanayru Twilit Insect: Twilight and Can_Complete_Eldin_Twilight
Can Clear Forest: Can_Complete_Faron_Twilight and ('Can_Complete_Forest_Temple' or Faron_Woods_Logic == Open)
Can Complete All Dungeons: "'Can_Complete_Forest_Temple' and 'Can_Complete_Goron_Mines' and 'Can_Complete_Lakebed_Temple' and
'Can_Complete_Arbiters_Grounds' and 'Can_Complete_Snowpeak_Ruins' and 'Can_Complete_Temple_of_Time' and
'Can_Complete_City_in_the_Sky' and 'Can_Complete_Palace_of_Twilight'"
Can Break Hyrule Castle Barrier: Hyrule_Barrier_Requirements == Open or
(Hyrule_Barrier_Requirements == Vanilla and 'Can_Complete_Palace_of_Twilight') or
(Hyrule_Barrier_Requirements == Fused_Shadows and count(Progressive_Fused_Shadow, Hyrule_Barrier_Fused_Shadows)) or
(Hyrule_Barrier_Requirements == Mirror_Shards and count(Progressive_Mirror_Shard, Hyrule_Barrier_Mirror_Shards)) or
(Hyrule_Barrier_Requirements == Dungeons and dungeons_completed(Hyrule_Barrier_Dungeons)) or
(Hyrule_Barrier_Requirements == Poe_Souls and count(Poe_Soul, Hyrule_Barrier_Poe_Souls)) or
(Hyrule_Barrier_Requirements == Hearts and hearts(Hyrule_Barrier_Hearts))
Can Open Hyrule Castle Big Key Gate: Hyrule_Castle_Big_Key_Requirements == None or
(Hyrule_Castle_Big_Key_Requirements == Fused_Shadows and count(Progressive_Fused_Shadow, Hyrule_Castle_Big_Key_Fused_Shadows)) or
(Hyrule_Castle_Big_Key_Requirements == Mirror_Shards and count(Progressive_Mirror_Shard, Hyrule_Castle_Big_Key_Mirror_Shards)) or
(Hyrule_Castle_Big_Key_Requirements == Dungeons and dungeons_completed(Hyrule_Castle_Big_Key_Dungeons)) or
(Hyrule_Castle_Big_Key_Requirements == Poe_Souls and count(Poe_Soul, Hyrule_Castle_Big_Key_Poe_Souls)) or
(Hyrule_Castle_Big_Key_Requirements == Hearts and hearts(Hyrule_Castle_Big_Key_Hearts))
Can Talk to Springwater Goron: Nothing # TODO
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,561 @@
######################
## Logic Settings ##
######################
- Name: Logic Rules
Default Option: All Locations Reachable
Options:
- All Locations Reachable: "Logic is considered when placing items. Tricks and Glitches can be enabled for consideration below."
- Beatable Only: "Logic is considered when placing items only until the world is beatable. Remaining items are placed without logic consideration. Tricks and Glitches can be enabled for consideration below."
- No Logic: "Maximize randomization, logic is not considered when placing items. MAY BE IMPOSSIBLE TO BEAT."
# - Vanilla: "Items are placed in their vanilla locations."
######################
## Access Options ##
######################
- Name: Hyrule Barrier Requirements
Need In Game: True
Tracker Important: True
Default Option: Vanilla
Options:
- Open: "The barrier around Hyrule Castle is dispelled from the beginning."
- Vanilla: "The barrier will be dispelled once Palace of Twilight is cleared."
- Fused Shadows: "The barrier will be dispelled once the required number of Fused Shadows have been collected."
- Mirror Shards: "The barrier will be dispelled once the required number of Mirror Shards have been collected."
- Dungeons: "The barrier will be dispelled once the required number of Dungeons have been cleared."
- Poe Souls: "The barrier will be dispelled once the required number of Poe Souls have been collected."
- Hearts: "The barrier will be dispelled once the required number of Hearts have been reached."
- Name: Hyrule Barrier Fused Shadows
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-3: No description available.
- Name: Hyrule Barrier Mirror Shards
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-4: No description available.
- Name: Hyrule Barrier Dungeons
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-8: No description available.
- Name: Hyrule Barrier Poe Souls
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-60: No description available.
- Name: Hyrule Barrier Hearts
Need In Game: True
Tracker Important: True
Default Option: 4
Options:
- 4-20: No description available. # Hehe 420
- Name: Palace of Twilight Requirements
Need In Game: True
Tracker Important: True
Default Option: Vanilla
Options:
- Open: "The Mirror of Twilight is open at the start of the game."
- Fused Shadows: "The player must collect all 3 Fused Shadows."
- Mirror Shards: "The player must collect all 4 Mirror Shards."
- Vanilla: "The player must complete City in the Sky."
- Name: Faron Woods Logic
Tracker Important: True
Default Option: Closed
Options:
- Closed: "Midna will block the player from leaving Faron Woods until Forest Temple is completed."
- Open: "Midna will not prevent the player from leaving Faron Woods."
- Name: Mirror Chamber Access
Need In Game: True
Tracker Important: True
Default Option: Open
Options:
- Open: "The entrance is open and operates like normal. If you start with the Mirror Chamber Portal, you can access the Stallord boss fight without going through Arbiter's Grounds."
- Barrier: "A barrier is placed in front of the Mirror Chamber entrance and goes away once Stallord is defeated."
- Closed: "The Mirror Chamber is isolated from the world and cannot be reached from the Stallord boss room. To access it, players will either need the portal or access from Palace of Twilight."
######################
## Item Pool ##
######################
- Name: Golden Bugs
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "The Golden Bug locations across Hyrule will give the golden bug at that location in the base game."
- "On": "The Golden Bug locations across Hyrule will be randomized."
- Name: Sky Characters
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "The Sky Character locations across Hyrule will give Sky Characters."
- "On": "The Sky Character locations across Hyrule will be randomized."
- Name: Gifts From NPCs
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Locations which involve an NPC giving you a gift will give the item expected from the base game."
- "On": "Locations which involve an NPC giving you a gift will be randomized."
- Name: Shop Items
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Shop item locations will contain the item they have in the base game."
- "On": "Shop items will be randomized."
- Name: Hidden Skills
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "The golden wolf locations across Hyrule will give you Hidden Skills. You will be required to get at least one of them to obtain the Ending Blow."
- "On": "The golden wolf locations across Hyrule will be randomized."
- Name: Hidden Rupees
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Rupees hidden in tricky locations will not be randomized."
- "On": "Rupees hidden in tricky locations will be randomized."
- Name: Freestanding Rupees
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Rupees out in the open will not be randomized."
- "On": "Rupees out in the open will be randomized."
- Name: Poe Souls
Tracker Important: True
Default Option: Vanilla
Options:
- Vanilla: "All poes will give poe souls as the item for beating them."
- Overworld: "Overworld poes will give randomized items. Poes in dungeons will still give poe souls."
- Dungeon: "Poes in dungeons will give randomized items. Overworld poes will will give poe souls."
- All: "All poes will be randomized."
- Name: Ilia Memory Quest
Tracker Important: True
Default Option: Vanilla
Options:
- Vanilla: "The Ilia Memory Quest will work the same way as the base game. You'll start it by beating Temple of Time and then talking to Renado in Kakariko Village."
- Letter: "Renado's Letter will be shuffled into the world somewhere. You'll start the quest by finding Renado's Letter and then showing it to Telma in her bar."
- Invoice: "The Invoice will be shuffled into the world somewhere. You'll start the quest by finding the Invoice and showing it to the Doctor in Castle Town."
- Statue: "The Wooden Statue will be shuffled into the world somewhere. You'll start the quest by finding the Wooden Statue and then showing it to Ilia in Kakariko Village."
- Charm: "Ilia's Charm will be shuffled into the world somewhere. You'll start the quest by finding Ilia's Charm and then showing it to Ilia in Kakariko Village to complete the quest."
- Name: Item Scarcity
Default Option: Vanilla
Options:
- Vanilla: "No changes to the item pool."
- Minimal: "Removes unrequired items such as Heart Containers and Pieces, Hawkeye, etc. Has as few items as possible for Bomb Bags, Bows, Hidden Skills, and Wallets. No Magic Armor and 1 Hidden Skill if Glitchless logic."
- Plentiful: "One extra copy of major items. There are 17 Heart Containers but no Pieces of Heart. Extra keys if `Keysanity` or `Any Dungeon`."
- Name: Trap Item Frequency
Default Option: None
Options:
- None: "All items in the game will be genuine."
- Few: "Approximately 12.5% of non-major items will be replaced with 'traps' that don't give the item they appear to be."
- Many: "Approximately 39.1% of non-major items will be replaced with 'traps' that don't give the item they appear to be."
- Mayhem: "Approximately 62.7% of non-major items will be replaced with 'traps' that don't give the item they appear to be."
- Nightmare: "All of the non-major items will be replaced with 'traps' that don't give the item they appear to be."
######################
## Dungeon Items ##
######################
- Name: Small Keys
Tracker Important: True
Default Option: Vanilla
Random Low: Own Dungeon
Random High: Anywhere
Options:
- Vanilla: "Small Keys will appear in their vanilla locations."
- Own Dungeon: "Small Keys will appear inside their respective dungeon."
- Any Dungeon: "Small Keys can appear inside any dungeon."
# - Own Region: "Small Keys will appear in their dungeon's region."
- Overworld: "Small Keys will only appear in the overworld."
- Anywhere: "Small Keys can appear anywhere."
- Keysy: "Small Keys will not appear anywhere in the world and their locks will start opened."
- Name: Big Keys
Tracker Important: True
Default Option: Vanilla
Options:
- Vanilla: "Big Keys will appear in their vanilla locations."
- Own Dungeon: "Big Keys will appear inside their respective dungeon."
- Any Dungeon: "Big Keys can appear inside any dungeon."
# - Own Region: "Big Keys appear in their dungeon's region."
- Overworld: "Big Keys will only appear in the overworld."
- Anywhere: "Big Keys can appear anywhere."
- Keysy: "Big Keys will not appear anywhere in the world and boss doors will start opened."
- Name: Maps and Compasses
Default Option: Vanilla
Options:
- Vanilla: "Maps and Compasses will appear in their vanilla locations."
- Own Dungeon: "Maps and Compasses can appear anywhere inside their respective dungeon."
- Any Dungeon: "Maps and Compasses can appear inside any dungeon."
# - Own Region: "Maps and Compasses will appear in their dungeon's region."
- Overworld: "Maps and Compasses will only appear in the overworld."
- Anywhere: "Maps and Compasses can appear anywhere."
- Start With: "The player starts with all Maps and Compasses."
- Name: Hyrule Castle Big Key Requirements
Need In Game: True
Tracker Important: True
Default Option: None
Options:
- None: "The gate is opened and the key is randomized according to the respective Big Key settings."
- Fused Shadows: "The gate will open once the required number of Fused Shadows have been collected."
- Mirror Shards: "The gate will open once the required number of Mirror Shards have been collected."
- Dungeons: "The gate will open once the required number of Dungeons have been cleared."
- Poe Souls: "The gate will open once the required number of Poe Souls have been collected."
- Hearts: "The gate will open once the required number of Hearts have been reached."
- Name: Hyrule Castle Big Key Fused Shadows
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-3: No description available.
- Name: Hyrule Castle Big Key Mirror Shards
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-4: No description available.
- Name: Hyrule Castle Big Key Dungeons
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-8: No description available.
- Name: Hyrule Castle Big Key Poe Souls
Need In Game: True
Tracker Important: True
Default Option: 1
Options:
- 1-60: No description available.
- Name: Hyrule Castle Big Key Hearts
Need In Game: True
Tracker Important: True
Default Option: 4
Options:
- 4-20: No description available. # Hehe 420
- Name: Dungeon Rewards Can Be Anywhere
Default Option: "Off"
Options:
- "Off": "Dungeon reward items (Fused Shadows and Mirror Shards) will only appear at the end of dungeons."
- "On": "Dungeon reward items (Fused Shadows and Mirror Shards) can appear anywhere."
- Name: No Small Keys on Bosses
Default Option: "Off"
Options:
- "Off": "Small keys will not be placed on boss heart container or dungeon reward checks."
- "On": "Small keys can potentially be placed on boss heart container or dungeon reward checks. You may be expected to defeat a dungeon's boss before progressing further into the dungeon."
- Name: Unrequired Dungeons Are Barren
Tracker Important: True
Default Option: "On"
Options:
- "Off": "Unrequired dungeons may contain items needed to beat the game."
- "On": "Unrequired dungeons will not contain any items necessary to beat the game."
######################
## Timesavers ##
######################
- Name: Skip Prologue
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "You will be required to play through the prologue section of the game to begin the randomizer. This includes everything up to the second goat herding sequence."
- "On": "The prologue section of the game will be completed from the start."
- Name: Faron Twilight Cleared
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "You will be required to complete the Castle Sewers and Faron Twilight section of the game."
- "On": "The Castle Sewers and Faron Twilight section of the game will be completed from the start."
- Name: Eldin Twilight Cleared
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "You will be required to complete the Eldin Twilight section of the game."
- "On": "The Eldin Twilight section of the game will be completed from the start."
- Name: Lanayru Twilight Cleared
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "You will be required to complete the Lanayru Twilight section of the game."
- "On": "The Lanayru Twilight section of the game will be completed from the start."
- Name: Skip Midna's Desparate Hour
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "After completing Lakebed Temple, you will be required to complete the Midna's Desperate Hour section of the game. Note that some overworld poes require Midna's Desperate Hour to be completed before they spawn in."
- "On": "The Midna's Desperate Hour section of the game will be completed from the start."
- Name: Skip Minor Cutscenes
Need In Game: True
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Minor cutscenes such as area introduction cutscenes and Midna text explanations will not be skipped."
- "On": "Minor cutscenes such as area introduction cutscenes and Midna text explanations will not play."
- Name: Skip Major Cutscenes
Need In Game: True
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "If you want to skip a skippable cutscene, you must press the start button twice while the cutscene is playing."
- "On": "The randomizer will automatically skip any skippable cutscene as fast as possible."
- Name: Unlock Map Regions
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "The map will not start filled in at the beginning of the randomizer. You will have to travel to the different sections of the world to get them on the map."
- "On": "The map will start as filled in as possible. Certain sections such as Eldin and Lanayru will only be filled in if their Twilight section is cleared from the start."
- Name: Open Door of Time
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "You will be required to lead the big statue down the Temple of Time to open the big door at the bottom."
- "On": "The big statue will already be set in place at the bottom of the Temple of Time and the door will be opened from the start."
- Name: Active Goron Mines Magnets
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "The switches to activate magnets in Goron Mines will need to be activated manually."
- "On": "The switches to activate magnets in Goron Mines will be activated from the start except for the highest one in the main room."
- Name: Lower Hyrule Castle Chandelier
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "The chandeliers in Hyrule Castle will all need to be lowered manually."
- "On": "One of the chandeliers in the Hyrule Castle main hall will be lowered from the start. This skips requiring Gale Boomerang and either Lantern or Bow to complete Hyrule Castle."
- Name: Skip Bridge Donation
Need In Game: True
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "You will need to donate money at Kakariko Malo Mart to build the bridge between Eldin Field and Castle Town."
- "On": "The bridge between Eldin Field and Castle Town will be automatically built after Eldin and Lanayru Twilight are both completed."
######################
# Additional Settings#
######################
- Name: Starting Form
Tracker Important: True
Default Option: Human
Options:
- Human: Start as Human Link
- Wolf: Start as Wolf Link
- Name: Bonks Do Damage
Tracker Important: True
Default Option: "Off"
Options:
- "Off": No description available.
- "On": No description available.
- Name: Starting Time of Day
Default Option: Noon
Options:
- Morning: "Time of day will start at 9am."
- Noon: "Time of day will start at noon."
- Evening: "Time of day will start at 6pm."
- Night: "Time of day will start at midnight."
- Name: Logic Transform Anywhere
Default Option: "On"
Options:
- "Off": "You will not be expected to transform in places that you normally can't."
- "On": "You may be expected to transform in places that require turning on the Dusklight Transform Anywhere setting."
- Name: Logic Increase Wallet Capacity
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Logic will assume you have the same wallet capacities as the base game."
- "On": "Logic will assume that you have the Bigger Wallets Dusklight setting turned on."
- Name: Logic Damage Multiplier
Default Option: Vanilla
Options:
- Vanilla: "Logic will assume your Dusklight Damage Multiplier is x1."
- Double: "Logic will assume your Dusklight Damage Multiplier is x2."
- Triple: "Logic will assume your Dusklight Damage Multiplier is x3."
- Quadruple: "Logic will assume your Dusklight Damage Multiplier is x4."
- OHKO: "Logic will assume your Dusklight Instant Death setting is turned on."
#############################
# Dungeon Entrance Settings #
#############################
- Name: Lakebed Does Not Require Water Bombs
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "The entrance to Lakebed Temple will be blocked by a boulder and require using Water Bombs to blow up."
- "On": "The rock blocking access to the entrance of Lakebed Temple will be gone, meaning you can get in without Water Bombs."
- Name: Arbiters Does Not Require Bulblin Camp
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Bulblin Camp will have to be completed to access the entrance to Arbiter's Grounds. This will require finding the Gerudo Desert Bulblin Camp Key."
- "On": "Bulblin Camp will be cleared at the start of the randomizer."
- Name: Snowpeak Does Not Require Reekfish Scent
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Getting the reekfish scent will be required for running through the blizzard on Snowpeak Mountain. Getting the reekfish scent requires the Coral Earring."
- "On": "The randomizer will start you with the reekfish scent, meaning you can go through the Snowpeak Mountain blizzard without needing the Coral Earring."
- Name: Sacred Grove Does Not Require Skull Kid
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Getting through the Lost Woods will require completing the Skull Kid chase sequence."
- "On": "The Skull Kid chase sequence in the Lost Woods will start already completed."
- Name: City Does Not Require Filled Skybook
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "The canon to City in the Sky will spawn in Lake Hylia when the Sky Book has been completed."
- "On": "The canon to City in the Sky will be in Lake Hylia from the start."
- Name: Goron Mines Entrance
Tracker Important: True
Default Option: Closed
Options:
- Closed: "Accessing Goron Mines will require climbing up to the Death Mountain Sumo Hall and wrestling with the Goron Elder."
- No Wrestling: "Accessing Goron Mines will require climbing up to the Death Mountain Sumo Hall, but wrestling the Goron Elder will not be necessary."
- Open: "The elevator shortcut to the Death Mountain Sumo Hall will be open, and can be used to access Goron Mines."
- Name: Temple of Time Sword Requirement
Need In Game: True
Tracker Important: True
Default Option: None
Options:
- None: "The door to the past will be open from the start."
- Wooden Sword: "The door to the past will require striking at least the Wooden Sword into the Master Sword pedestal."
- Ordon Sword: "The door to the past will require striking at least the Ordon Sword into the Master Sword pedestal."
- Master Sword: "The door to the past will require striking at least the Master Sword into the Master Sword pedestal."
- Light Sword: "The door to the past will require striking the Light Sword into the Master Sword pedestal."
- Name: Randomize Starting Spawn
Default Option: "Off"
Options:
- "Off": "Link will start outside his house."
- "On": "Link will start in a random area."
- Name: Randomize Dungeon Entrances
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Entering a dungeon will lead to the vanilla dungeon."
- "On": "Entering a dungeon will lead to a random dungeon."
- "On + Hyrule Castle": "Entering a dungeon will lead to a random dungeon. Hyrule Castle's entrance will be shuffled as well."
- Name: Randomize Boss Entrances
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Entering a boss door will lead to the intended boss."
- "On": "Entering a boss door will lead to a random boss."
- Name: Randomize Grotto Entrances
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Entering a grotto will lead to the intended grotto."
- "On": "Entering a grotto will lead to a random grotto."
- Name: Randomize Cave Entrances
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Entering a door or loadzone that leads to a cave area will lead to the intended cave."
- "On": "Entering a door or loadzone that leads to a cave area will lead to a random cave."
- Name: Randomize Interior Entrances
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Entering a door or loadzone that leads to an interior area will lead to the intended area."
- "On": "Entering a door or loadzone that leads to an interior area will lead to a random intended area."
- Name: Randomize Overworld Entrances
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Entering a loadzone that leads to an overworld area will lead to the intended area."
- "On": "Entering a loadzone that leads to an overworld area will lead to a random area."
- Name: Decouple Double Door Entrances
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Entering a left door will lead to the same location as the corresponding right door."
- "On": "Entering a left door may lead somewhere different than the corresponding right door (only if the door's type is randomized)."
- Name: Decouple Entrances
Tracker Important: True
Default Option: "Off"
Options:
- "Off": "Entering a location and taking the entrance behind you will take you back to where you came from."
- "On": "Entering a location and taking the entrance behind you will take you to a random location."
#############################
## Logic Tricks ##
#############################
- Name: Back Slice as Sword
Default Option: "Off"
Options:
- "Off": "Back Slicing without a sword can be logically required to do damage."
- "On": "Back Slicing without a sword can be logically required to do damage."
- Name: Ball and Chain Webs
Default Option: "Off"
Options:
- "Off": "Ball and Chain will not be required to break webs."
- "On": "Ball and Chain may be required to break webs."
@@ -0,0 +1,609 @@
# Flag values taken from: https://github.com/lunarsoap5/Randomizer-Web-Generator-1/blob/development/Generator/Assets/Flags.cs
EventFlags:
- 0x0382 # Gave wooden sword to Talo. Talked to squirrel outside link's house
- 0x0629 # Tame Epona, KB1 trigger activated, Warped Kakariko Bridge Back.
- 0x0F40 # Talked to Doctor for the first time.
- 0x1208 # Can use Sera's Shop.
- 0x1410 # Put Bo outside, ready to wrestle
- 0x0F01 # Got Lantern from Coro (Remove when adding Coro checks)
- 0x0A2F # Bridge of Eldin Stolen, KB1 defeated, KB1 started
- 0x0F68 # Bridge of Eldin Warped Back, forced text when entering dr. clinic, talked to dr before giving invoice
- 0x4088 # Saved monkey from puppets, Visited Gerudo Desert for the first time.
- 0x4118 # Talked to Fado after Faron and Eldin Twilight
- 0x07A0 # Watched Colin CS after KB1, talked to Bo before sumo
- 0x2020 # Master Sword Story Progression
- 0x2010 # Arbiters Grounds Story Progression
- 0x2C10 # Raised the mirror in the Mirror Chamber
- 0x1B38 # Skip Monkey Escort
- 0x1C20 # Talked to Bo after opening boots chest.
- 0x5F20 # Shad leaves sanctuary.
- 0xF701 # Add 256 Rupees to Charlo.
- 0xF8F4 # Add 244 Rupees to Charlo.
- 0x6001 # Talked to Fyer after Lanayru Twilight
- 0x3880 # Talked to Jovani after defeating Poe.
- 0x2208 # Talked to Yeto on top of the mountain after clearing SPR
- 0x3B40 # Won Snowboard race against Yeto.
- 0x2F80 # Talked to Goron outside East Castle Town
- 0x1C10 # Win Sumo round 1 against Bo
- 0x3902 # Released first caught fish in Ordon Day 2
- 0x1002 # Talked to Jaggle after climbing vines.
- 0x0B20 # Talked to Yeta in Snowpeak for the first time
- 0x4308 # Senses unlocked
- 0x4610 # Rode Epona back to Link's House
- 0x0C10 # Midna accompanies Wolf
- Skip_Prologue == On:
- 0x0404 # Talked to Uli Day 1.
- 0x4510 # Saved Talo
- 0x4A60 # Completed Ordon Day 1 and Finished Sword Training.
- 0x1601 # Completed Ordon Day 2.
- 0x1580 # Watched CS for Goats 2 Done.
- Faron_Twilight_Cleared == On:
- 0x057F # Midna Charge Unlocked, Finished Sewers, Met Zelda in swers, Midna cut prison chain, watched sewers intro CS, Escaped Cell in Sewers.
- 0x0610 # Cleared Faron Twilight
- 0x0C08 # Sword and shield removed from wolf's back.
- Eldin_Twilight_Cleared == On:
- 0x0708 # Cleared Eldin Twilight
- 0x0604 # Map Warping unlocked.
- Lanayru_Twilight_Cleared == On:
- 0x0880 # Zora's Domain Thawed.
- 0x0C02 # Lanayru Twilight Story Flag.
- 0x0A10 # Defeated Kargarok Rider at Lake (allows player to howl for Kargorok.);
- Skip_Minor_Cutscenes == On:
- 0x0140 # Talked to Yeto First Time.
- 0x0390 # Jaggle Calls out to Link, talked to Squirrel as Wolf in Ordon.
- 0x06C0 # CS After beating Ordon Shadow, CS after entering Faron Twilight.
- 0x0702 # First Time Talking to Gor Coron in Sumo Hall
- 0x1501 # Talked to Agitha for the first time.
- 0x2001 # Talked to Telma for the first time.
- 0x5E10 # Midna text after beating Forest Temple.
- 0x1D40 # Listened to Fyer at drained lake.
- 0x2201 # Plumm initial CS watched.
- 0x2310 # STAR initial CS watched.
- 0x2602 # Talked to Yeto on Snowpeak.
- 0x2840 # Used Ooccoo for the first time.
- 0x3704 # Postman twilight text.
- 0x3806 # Hena cabin first time CS, talked to Hena first time.
- 0x3A01 # Talked to Ralis in Graveyard for the first time.
- 0x4002 # Agreed to help Rusl after Snowpeak Ruins.
- 0x4205 # Watched post-ToT Ooccoo CS. Watched Cutscene with Rusl in North Faron Woods.
- 0x4508 # Allows postman letters to show up in inventory.
- 0x4A10 # Saw Talo in cage CS.
- 0x3E02 # City Ooccoo CS watched.
- 0x5940 # Met Postman for the first time.
- 0x5D40 # Midna text after Kargarok flight.
- 0x2502 # Watched cutscene with Yeto on top of mountain
- Faron_Woods_Logic == Open:
- 0x0602 # Forest Temple Story Flag
- 0x0C40 # Talked to Farone after clearing Forest Temple
- 0x5E10 # Midna text after Forest Temple completed
- Skip_Midna's_Desparate_Hour == On:
- 0x0C01 # Midna's Desperate Hour started.
- 0x1E08 # Midna's Deseperate Hour Completed.
- Small_Keys == Keysy:
- 0x0850 # Zora Escort started and completed.
- 0x0480 # Told Yeta about pumpkin.
- 0x0003 # Yeto put pumpkin and cheese in soup.
- 0x1460 # Snowpeak Ruins North and West doors unlocked.
- 0x0120 # Told Yeta about cheese
- Hyrule_Barrier_Requirements == Open:
- 0x4208 # Remove Castle Barrier
- Palace_of_Twilight_Requirements == Open:
- 0x2B08 # Mirror of Twilight Repaired.
- Goron_Mines_Entrance != Closed:
- 0x0706 # Talked to Gor Coron, Won Sumo against Gor Coron.
- Arbiters_Does_Not_Require_Bulblin_Camp == On:
- 0x0B40 # Escaped Burning Tent in Bulblin Camp.
- Snowpeak_Does_Not_Require_Reekfish_Scent == On:
- 0x6120 # Got the reekfish and smelled it (removes void in Snowpeak).
- City_Does_Not_Require_Filled_Skybook == On:
- 0x3B08 # Sky Cannon Repaired.
- Randomize_Starting_Spawn == On:
- 0x057A # Finished Sewers, Midna text after entering Faron Twilight, Met Zelda in sewers, Midna cut prison chain, Watched Sewers intro CS, Escaped cell in sewers.
- Ilia_Memory_Quest >= Letter:
- 0x2004 # ToT Story Progression Flag
- 0x0F80 # Renados Letter Check
- Ilia_Memory_Quest >= Statue:
- 0x2710 # Showed Invoice to Doctor
- 0x2F04 # Got Medicine Scent
- 0x2102 # Talked to Louise after Medicine Scent
- 0x2204 # Got Wooden Statue
- Ilia_Memory_Quest >= Charm:
- 0x2340 # Gave statue to Ilia
- 0x2E08 # HV barrier removed
- 0x2280 # Got Ilia's Charm
- Skip_Bridge_Donation == Off:
- 0xF901 # Add 256 Rupees to Malo Mart.
- 0xFAF4 # Add 244 Rupees to Malo Mart.
RegionFlags:
Ordona Province:
Index: 0x00
Flags:
- 0x57 # Spider on Link's Ladder killed.
- 0x63 # Spawn the Chest in Link's House
- 0x7E # Midna jumps to Shop unlocked
- 0x6B # Ordon Spring Portal.
- 0x44 # Midna Text after Ordon Shield (Spawns sword)
- 0x46 # Midna Text after Ordon Sword
- 0x68 # Approach faron wall with Midna
- 0xA0 # Midna allows player to approach Faron Twilight Wall
- 0xBA # Explored area outside Link's house as wolf
- 0x61 # Defeated first bulblin outside link's house
- 0x62 # Defeated second bulblin outside link's house
- 0x60 # Defeated Hugo
- Skip_Minor_Cutscenes == On:
- 0x4A # Ordon Day 3 Intro CS.
- 0x4C # Knocked down Ordon bee nest CS.
- 0x4E # Ordon Ranch first time CS.
- 0x53 # Ilia spring CS watched.
- 0x54 # Ilia spring CS started.
- 0x55 # Ordon Village first time CS.
- 0x56 # Ilia spring CS trigger.
- 0x68 # Approach Faron Twilgiht with Midna CS.
- 0x6E # Enter shield house as wolf CS.
- 0x75 # Midna text after hearing Bo and Jaggle talk about the shield.
- 0x7C # Midna text before jumping to Ordon Shop roof.
- 0x7D # Rusl talking to Uli during wolf night CS.
- 0xB8 # Enter Ordon Village as wolf CS.
Hyrule Castle Sewers and Rooftops:
Index: 0x01
Flags:
- Skip_Minor_Cutscenes == On:
- 0x42 # Midna text after first gate in sewers.
- 0x43 # Midna text after exiting to rooftops.
- 0x51 # Zelda tower intro CS.
- 0x57 # Outside top door intro CS.
- 0x5A # Went to the otherside of the fence in sewers CS.
- 0x5B # Top of stairway intro CS.
- 0x5C # Stairway intro CS.
- 0x7B # Midna text when approaching the rooftop guard.
Faron Woods:
Index: 0x02
Flags:
- 0x63 # Trill lets you shop at his store.
- 0x48 # Talked to Coro after bugs
- 0x60 # Got Lantern Back from Monkey
- 0x61 # Saw bugs move in Coro's house
- 0x7D # Talked to Midna about Coro spirit
- 0x4E # Saved Monkey from Puppets.
- 0x62 # Midna text before jumping to lost woods
- 0x95 # Midna text after warping to North Faron for bridge.
- 0xBF # Burned First cobweb in faron cave
- 0xBE # Burned second cobweb in faron cave
- Skip_Prologue == On:
- 0x4B # North Faron Gate Unlocked
- Skip_Minor_Cutscenes == On:
- 0x74 # Faron intro CS.
- 0x77 # See Faron Light Spirit from afar CS.
- 0x7C # Entered mist area as human.
- Faron_Twilight_Cleared == On:
- 0x46 # Midna jump 1 mist area.
- 0x47 # Midna jump 1 mist area.
- 0x98 # South Faron Portal.
# Re-enable once key situation is sorted out
# - Small_Keys == Keysy:
# - 0x53 # Coro gate unlocked.
# - 0x4B # North Faron Gate Unlocked.
Kakariko and Death Mountain:
Index: 0x03
Flags:
- 0xB9 # Barnes sells water bombs.
- 0xB3 # Colin Rescued CS (Malo Mart is Open).
- 0xA4 # Barnes Sells Bombs.
- 0x42 # Big Rock fell at DMT
- 0xA7 # Unlock Jumps to top of Sanctuary
- 0x9A # Kakariko Village intro CS.
- 0x54 # Custom flag. Sets the sign in Kak Malo mart slot 1 to appear.
- 0x99 # Remove wooden shield from Kak Malo Mart counter.
- Skip_Minor_Cutscenes == On:
- 0x49 # Death mountain intro CS.
- 0x83 # Kakariko Graveyard intro CS.
- 0x8C # Midna text after Meteor fell.
- Eldin_Twilight_Cleared == On:
- 0x14 # Collected Tear From Bomb Storage
- 0x1A # Collected Tear From Bomb Storage
- 0x1B # Collected Tear From Bomb Storage
- 0x67 # Ant house entered from top
- 0x64 # Ant house box pushed
- 0x5E # Defeated Ant house Tears of Light bug
- 0x1E # Collected Tear from Ant house
- 0xBD # Done Midna jumps in ant house.
- Small_Keys == Keysy:
- 0xBA # Followed Rutella to graveyard.
- 0xB6 # Started Rutella escort.
- Goron_Mines_Entrance == Open:
- 0x79 # moved death mountain rock to exit
- 0x8F # moved death mountain rock to hot spring water
- 0xB0 # Goron lets you enter elevator in sumo hall
- Ilia_Memory_Quest >= Charm:
- 0x70 # Darbus destroyed HV rocks
Lake Hylia and Zoras Domain:
Index: 0x04
Flags:
- Skip_Minor_Cutscenes == On:
- 0x58 # Talked to Rutella in Lanayru Twilight.
- 0x5F # Zora's domain intro CS twilight.
- 0x67 # Midna text after jumping to Lake from burning bridge.
- 0x6B # Zora's Domain exit flood water cutscene.
- 0x72 # Midna text after arriving at frozen Upper Zora River.
- 0x91 # Midna text after frozen Zora Domain intro CS.
- 0xB0 # Watched CS of Ooccoo running to Sky Cannon.
- Lanayru_Twilight_Cleared == On:
- 0x7F # Lake Hylia has water on Lake Hylia Map.
- Skip_Midna's_Desparate_Hour == On:
- 0x51 # Set flag for MDH Cutscene in Lake Hylia
- Lakebed_Does_Not_Require_Water_Bombs == On:
- 0x70 # Blew up rock in front of lakebed CS.
- 0x78 # Blew up rock in front of lakebed.
# Not sure what Index 5 is
Hyrule Field:
Index: 0x06
Flags:
- 0x4C # Bridge of Eldin Warped back CS.
- 0x7E # Kakariko Gorge placed CS
- 0x83 # Set the flag for the Ganon Barriers in Hyrule Field during Eldin Twilight.
- Skip_Minor_Cutscenes == On:
- 0x68 # Midna text after warping Gorge bridge.
- 0x7C # Midna text after Lanayru Field twilight CS.
- 0x72 # Faron Field intro CS.
- 0x40 # Twilight Lanayru Field intro CS.
- 0x4F # Cutscene of gate outside Kakariko Village.
- 0xB3 # Midna text after entering Lanayru Twilight.
- 0xB4 # Midna text when seeing Lanayru Twilight from far away.
- 0xB6 # Midna text after entering Eldin Twilight.
- 0xB7 # Midna text when seeing Eldin Twilight from far away.
- Lanayru_Twilight_Cleared == On:
- 0x58 # Lake Hylia has water on Hyrule Field Map
- Ilia_Memory_Quest >= Charm:
- 0x43 # Remove HV rocks from Hyrule field
Lost Woods and Sacred Grove:
Index: 0x07
Flags:
- 0x58 # Sacred Grove MS Pedestal Map
- Skip_Minor_Cutscenes == On:
- 0x42 # Midna text after pushing block shortcut as human after Grove 2.
- 0x43 # cs after pushing block human
- 0x44 # Lost Woods intro CS.
- Temple_of_Time_Sword_Requirement == None:
- 0x49 # Stairs to Temple of time created.
- 0x4A # Struck master sword pedestal with sword.
- 0x4B # Stairs and window appear and work properly (Past).
- 0xBC # Statue in present is gone. (custom flag)
- Sacred_Grove_Does_Not_Require_Skull_Kid == On:
- 0xB6 # Skull Kid - Human defeated.
- 0xB7 # Lost Woods Turns to day after defeating Skull Kid - Human
- 0x5B # Block pushed down
- 0x42 # Midna text after block pushed down
- 0x43 # cs after pushing block human
Snowpeak Province:
Index: 0x08
Flags:
- Skip_Minor_Cutscenes == On:
- 0x45 # Snowpeak Summit intro CS.
- 0x5E # Midna text outside SPR.
- 0x5F # Snowpeak intro CS.
- Snowpeak_Does_Not_Require_Reekfish_Scent == On:
- 0x49 # Snowpeak summit cs.
- 0x45 # Snowpeak Summit intro CS.
Castle Town:
Index: 0x09
Flags:
- 0x40 # Original Jovani Poe killed. It is replaced with a custom actor.
- 0x76 # Jovani Chest CS 2
- 0x7F # Open Chest to Jovani
- 0x7E # Jovani Chest CS
- 0x50 # Set flag for Midna breaking Barrier CS.
- 0xBC # Spawn Gengle by default as his actor interferes with the poe soul
- Skip_Minor_Cutscenes == On:
- 0x55 # STAR Tent intro CS.
- 0x7D # Jovani House intro CS.
- Ilia_Memory_Quest >= Statue:
- 0x56 # Remove invisible wall from Doctor
Gerudo Desert:
Index: 0x0A
Flags:
- 0x99 # Desert Entrance CS.
- 0x20 # Set Freestanding key flag.
- 0x7F # Mirror Raised Cutscene Flag (Places Boar at desert entrance)
- Skip_Minor_Cutscenes == On:
- 0x53 # Mirror Chamber Intro CS.
- Arbiters_Does_Not_Require_Bulblin_Camp == On:
- 0x43 # Explored part 9 of the Bulblin camp area
- 0x44 # Explored part 8 of the Bulblin camp area
- 0x45 # Explored part 7 of the Bulblin camp area
- 0x46 # Explored part 6 of the Bulblin camp area
- 0x47 # Explored part 5 of the Bulblin camp area
- 0x4C # Explored part 2 of the Bulblin camp area
- 0x4D # Explored part 4 of the Bulblin camp area
- 0x4E # Explored part 3 of the Bulblin camp area
Forest Temple:
Index: 0x10
Flags:
- 0x49 # FT Ook Bridge Destroyed
- Skip_Minor_Cutscenes == On:
- 0x41 # Midna text after getting Boomerang.
- 0x42 # Midna text after Ook breaks the bridge.
- 0x47 # Midna text after freeing first monkey.
- 0x49 # Bridge before Ook broken.
- 0x56 # Bokoblins spot Link in windless bridge room.
- 0x57 # Turned bridge in windless bridge room.
- 0x72 # West Tile Worm room intro CS.
- 0x76 # Second monkey room intro CS.
- 0x7C # Big Baba room intro CS.
- 0x7D # Midna text in room before boss room.
- 0x7E # Midna text after saving monkey after defeating Ook.
- 0x85 # Midna text after opening hanging chest.
- 0x83 # East outside room intro CS.
- 0xB6 # Forest Temple intro CS.
- Small_Keys == Keysy:
- 0x54 # Unlocked door to Second Monkey.
- 0x58 # Unlock windless bridge east door.
- 0x61 # Opened big baba monkey cage.
- 0x74 # Opened tile worm monkey cage.
- Big_Keys == Keysy:
- 0x48 # Unlocked Forest Temple Boss Door.
- 0xED # Got Forest Temple Big Key.
- Maps_and_Compasses == Start_With:
- 0xEE # Got Forest Temple Compass.
- 0xEF # Got Forest Temple Dungeon Map.
Goron Mines:
Index: 0x11
Flags:
- Skip_Minor_Cutscenes == On:
- 0x43 # Cut rope of door in outside room CS.
- 0x44 # Pressed second button of the main magnet room of the second floor CS trigger.
- 0x45 # Pressed third button in entrance room CS.
- 0x46 # Pressed second button in entrance room CS.
- 0x47 # Cut rope of door in Toadpoli room CS.
- 0x4A # Pressed first button of the main magnet room on the second floor CS.
- 0x68 # Pressed outside magnet switch for first time CS.
- 0x72 # Main magnet room intro CS.
- 0x73 # Main magnet room intro CS trigger.
- 0x7A # Outside room intro CS.
- 0x80 # Room after Bow chest intro CS.
- 0x81 # Pulled Beamos in outside room CS.
- 0x84 # Open gate in Toadpoli room CS.
- 0x85 # Pressed second button in Toadpoli room CS.
- 0x88 # Magnet maze room intro CS.
- 0x8A # Goron Mines intro CS.
- 0x8B # Pressed first button in entrance room CS.
- 0x8C # Open gate in entrance room CS.
- 0xBC # Main magnet room second floor intro CS.
- 0xBD # Main magnet room second floor intro CS trigger.
- 0xBE # Hit crystal switch in room after bow chest CS.
- 0xBF # Room after Bow chest intro CS trigger.
- Small_Keys == Keysy:
- 0x60 # Unlock north door in toadpoli room.
- 0x62 # Unlock west locked door in main magnet room.
- 0x6C # Unlock east outside door.
- Big_Keys == Keysy:
- 0x48 # Unlocked Goron Mines Boss Door.
- 0xED # Got Goron Mines Big Key.
- Maps_and_Compasses == Start_With:
- 0xEE # Got Goron Mines Compass.
- 0xEF # Got Goron Mines Dungeon Map.
- Active_Goron_Mines_Magnets == On:
- 0xBB # activated magnet from water before first elder
- 0x8F # activated ceiling maze magnet after first elder
- 0x5B # activated main magnet room 1st magnet
- 0x4A # watched main magnet room 1st magnet cs
- 0x61 # activated main magnet room 2nd magnet
- 0x44 # watched main magnet room 2nd magnet cs
- 0x9E # crystal switch room 1st Iron Boots switch pressed
- 0x83 # crystal switch room 1st Iron Boots switch cs shown
- 0x82 # crystal switch room 1st magnet active
- 0x9F # crystal switch room 2nd Iron Boots switch pressed
- 0x85 # crystal switch room 2nd Iron Boots switch cs shown
- 0x86 # crystal switch room 2nd magnet active
- 0x54 # activated outside room magnet
- 0x68 # watched outside room magnet cs
- 0x8d # activated east wing dodongo room magnet
# Note: the final magnet is not activated because there is a
# softlock when you exit the main magnet room through the top door
# as wolf while the gate beyond the door in the Dodongo room is not
# open. Alternatively if we do open this gate, it leads to much
# more complicated logic and some jank where you can walk through
# Dangoro while he sits there (and the gate covering the door
# animation is also a bit jank). Also you can die during the
# Dangoro fight to appear on the north side of his arena. There are
# too many nuances for it to be reasonable for glitchless logic,
# and also every small key door would require 3 keys.
Lakebed Temple:
Index: 0x12
Flags:
- Skip_Minor_Cutscenes == On:
- 0x46 # Midna Stalactite text in second room.
- 0x7E # Horizontal wheel is turning in east room CS.
- 0x7F # Horizontal wheel is turning in east room CS trigger.
- 0xA5 # Central room intro CS.
- 0xA6 # South bridge to main room intro CS.
- 0xA7 # Lakebed Temple intro CS.
- 0xAA # Rotate staircase main room CS.
- 0xB4 # East water supply Chu Worm CS.
- Small_Keys == Keysy:
- 0x6B # Unlock east door main room 2F.
- 0x7B # Unlocked door in second east room 2F.
- 0x7C # Unlocked door before Deku Toad.
- Big_Keys == Keysy:
- 0x8A # Unlocked Lakebed Temple Boss Door.
- 0xED # Got Lakebed Temple Big Key.
- Maps_and_Compasses == Start_With:
- 0xEE # Got Lakebed Temple Compass.
- 0xEF # Got Lakebed Temple Dungeon Map.
Arbiters Grounds:
Index: 0x13
Flags:
- Skip_Minor_Cutscenes == On:
- 0x5A # Turn walls in third room Basement second floor CS.
- 0x73 # Arbiters Grounds intro CS.
- 0x94 # Risen tracks on pilar before boss CS.
- Small_Keys == Keysy:
- 0x78 # Unlocked door in second east room 2F.
- 0x84 # Unlocked door in elevator room 2B.
- 0x85 # Unlocked door in first room.
- 0x92 # Unlocked door in first east room 1F.
- 0x99 # Unlocked door in fourth east room.
- Big_Keys == Keysy:
- 0x47 # Unlocked Arbiter's Grounds Boss Door.
- 0xED # Got Arbiter's Grounds Big Key.
- Maps_and_Compasses == Start_With:
- 0xEE # Got Arbiter's Grounds Compass.
- 0xEF # Got Arbiter's Grounds Dungeon Map.
Snowpeak Ruins:
Index: 0x14
Flags:
- Skip_Minor_Cutscenes == On:
- 0x83 # First Floor Northwest room intro CS.
- 0xA1 # Midna text after finding Bedroom Key.
- 0xA7 # Snowpeak Ruins intro CS.
- 0xAA # Freezard in cage CS.
- 0xAC # Courtyard intro CS.
- 0xAE # Pumpkin room intro CS.
- 0xB2 # Midna text after getting Cheese.
- 0xB4 # Midna text after getting Pumpkin.
- Small_Keys == Keysy:
- 0x4D # Unlock North lobby door.
- 0x4C # Unlock West lobby door.
- 0x6F # Unlock door in southeast room 2F.
- 0x73 # Unlock door in east outside hallway.
- 0x74 # Unlock west door in courtyard.
- 0x70 # Unlock door to lobby from Freezard room.
- Big_Keys == Keysy:
- 0x57 # Unlocked Snowpeak Ruins Boss Door.
- 0xED # Got Snowpeak Ruins Big Key.
- 0x56 # Watched CS of Yeta entering boss room.
- Maps_and_Compasses == Start_With:
- 0xEE # Got Snowpeak Ruins Compass.
- 0xEF # Got Snowpeak Ruins Dungeon Map.
Temple of Time:
Index: 0x15
Flags:
- Skip_Minor_Cutscenes == On:
- 0x40 # Midna text telling you to use your senses on the missing statue.
- 0x41 # Midna text after using senses on missing statue.
- 0x4A # Temple of Time intro CS.
- 0x4B # Scales of Time room intro CS.
- 0x4C # CS after changing the balance on the scales for the first time.
- 0x4D # CS trigger after changing the balance on the scales for the first time.
- 0x90 # Pressed button in room 1 for the first time CS.
- 0x91 # Pressed the button on the seventh floor for the first time CS.
- 0x94 # Pressed the button on the fifth floor for the first time CS.
- 0x95 # Pressed buttons on third floor for the first time CS.
- 0x96 # Pressed the button on the second floor for the first time CS.
- 0x54 # statue getting possessed for the first time cs
- Small_Keys == Keysy:
- 0x44 # Unlock door in room 1.
- 0x42 # Unlock door in room 6 on 8F.
- 0x43 # Unlock door in 5F.
- Big_Keys == Keysy:
- 0x7F # Unlocked Temple of Time Boss Door.
- 0xED # Got Temple of Time Big Key.
- Maps_and_Compasses == Start_With:
- 0xEE # Got Temple of Time Compass.
- 0xEF # Got Temple of Time Dungeon Map.
- Open_Door_of_Time == On:
- 0x59 # deactivate statue slot in room 1 (opens door and deactivates statue)
- 0x80 # open big door in room 1 cs part 2
- 0x81 # open big door in room 1 cs part 1
- 0xBC # big door in room 1 opens
- 0xBE # open big door in room 1 cs part 1 trigger
- 0xBD # open big door in room 1 cs part 2 trigger
- 0xBF # statue placed in slot in room 1
City in the Sky:
Index: 0x16
Flags:
- Skip_Minor_Cutscenes == On:
- 0x64 # North wing main room intro CS.
- 0x65 # East wing fan room second floor intro CS.
- 0x66 # Went beyond first gate outside shop intro CS.
- 0x67 # City in The Sky intro CS.
- 0x6E # East bridge extended CS.
- Small_Keys == Keysy:
- 0x59 # Unlock east bridge door.
- Big_Keys == Keysy:
- 0x58 # Unlocked City in The Sky Boss Door.
- 0xED # Got City in The Sky Big Key.
- Maps_and_Compasses == Start_With:
- 0xEE # Got City in The Sky Compass.
- 0xEF # Got City in The Sky Dungeon Map.
Palace of Twilight:
Index: 0x17
Flags:
- Skip_Minor_Cutscenes == On:
- 0x4D # Phantom Zant 1 CS.
- 0x66 # Midna text when west hand steals sol.
- 0x6F # Midna text about black fog in west room.
- 0x70 # Midna text after finding west sol.
- 0x72 # Midna text trigger when seeing a Twili for the first time.
- 0x78 # Midna text when seeing a Twili for the first time.
- 0x79 # Midna text after Light Sword cutscene.
- 0x95 # Midna text after re-entering west wing after sol was stolen.
- 0x9E # Midna text at dungeon entrance.
- 0xB3 # Watched east wing second room stairs CS.
- Small_Keys == Keysy:
- 0x57 # Unlock door in north room 3.
- 0x58 # Unlock door in east room 2.
- 0x59 # Unlock door in west room 2.
- 0x6C # Unlock door in north room 2.
- 0x7A # Unlock door in norht room 1.
- 0x7B # Unlock door in east room 1.
- 0x7C # Unlock door in west room 1.
- Big_Keys == Keysy:
- 0x56 # Unlocked Palace of Twilight Boss Door.
- 0xED # Got Palace of Twilight Big Key.
- Maps_and_Compasses == Start_With:
- 0xEE # Got Palace of Twilight Compass.
- 0xEF # Got Palace of Twilight Dungeon Map.
Hyrule Castle:
Index: 0x18
Flags:
- 0x4B # Watched CS with Allies in HC.
- Skip_Minor_Cutscenes == On:
- 0x4F # Hyrule Castle Graveyard intro CS.
- 0x8C # East garden intro CS.
- 0x8D # East garden intro CS trigger.
- 0x77 # Midna text at the east end of the east garden.
- 0x82 # South garden intro CS.
- 0x99 # Double Darknut room intro CS
- 0xA4 # Midna text after Owl Statue chest in graveyard.
- 0xB7 # Lit southeast torch in second floor north room for the first time CS.
- 0xB8 # Lit northeast torch in second floor north room for the first time CS.
- Small_Keys == Keysy:
- 0x93 # Unlock door outside 3F.
- 0xB0 # Unlock treasure room door.
- 0xA3 # Unlock door in south garden.
- Big_Keys == Keysy and Hyrule_Castle_Big_Key_Requirements == None:
- 0xA1 # Unlocked Hyrule Castle Boss Door.
- 0xED # Got Hyrule Castle Big Key.
- Maps_and_Compasses == Start_With:
- 0xEE # Got Hyrule Castle Compass.
- 0xEF # Got Hyrule Castle Dungeon Map.
- Lower_Hyrule_Castle_Chandelier == On:
- 0x6F # watched double Dinalfos cs 1
- 0x70 # watched double Dinalfos cs 2
- 0x85 # watched focus on lowered chandelier cs
- 0x9D # lower the main hall chandelier
- 0xAF # defeated double Dinalfos (opens gates both sides)
- Hyrule_Castle_Big_Key_Requirements == None:
- 0x94 # Open HC BK gate
@@ -0,0 +1,66 @@
Seed: TESTTESTTEST
Plandomizer: false
Generate Spoiler Log: true
Arbiters Does Not Require Bulblin Camp: Random
Back Slice as Sword: Random
Ball and Chain Webs: Random
Big Keys: Random
Bonks Do Damage: Random
City Does Not Require Filled Skybook: Random
Damage Multiplier: Random
Dungeon Rewards Can Be Anywhere: Random
Eldin Twilight Cleared: Random
Faron Twilight Cleared: Random
Faron Woods Logic: Random
Fast Iron Boots: Random
Gifts From NPCs: Random
Golden Bugs: Random
Goron Mines Entrance: Random
Hidden Skills: Random
Hyrule Barrier Requirements: Random
Increase Spinner Speed: Random
Increase Wallet Capacity: Random
Instant Message Text: Random
Item Scarcity: Random
Lakebed Does Not Require Water Bombs: Random
Lanayru Twilight Cleared: Random
Logic Rules: Random
Maps and Compasses: Random
No Small Keys on Bosses: Random
Open Door of Time: Random
Palace of Twilight Requirements: Random
Poe Souls: Random
Quick Transform: Random
Random Starting Item Count: 0
Randomize Starting Spawn: Random
Randomize Dungeon Entrances: Random
Randomize Boss Entrances: Random
Randomize Grotto Entrances: Random
Randomize Cave Entrances: Random
Randomize Interior Entrances: Random
Randomize Overworld Entrances: Random
Decouple Double Door Entrances: Random
Decouple Entrances: Random
Sacred Grove Does Not Require Skull Kid: Random
Shop Items: Random
Shops Display The Replaced Item: Random
Skip Major Cutscenes: Random
Skip Midna's Desparate Hour: Random
Skip Minor Cutscenes: Random
Skip Prologue: Random
Sky Characters: Random
Small Keys: Random
Snowpeak Does Not Require Reekfish Scent: Random
Starting Form: Random
Starting Hearts: 3
Starting Time of Day: Random
Temple of Time Sword Requirement: Random
Logic Transform Anywhere: Random
Trap Item Frequency: Random
Unlock Map Regions: Random
Unrequired Dungeons Are Barren: Random
trappable_items: major_items
Starting Inventory:
{}
Excluded Locations:
[]
@@ -0,0 +1,4 @@
Seed: TESTTESTTEST
Small Keys: Any Dungeon
Big Keys: Any Dungeon
Maps and Compasses: Any Dungeon
@@ -0,0 +1,4 @@
Seed: TESTTESTTEST
Small Keys: Anywhere
Big Keys: Anywhere
Maps and Compasses: Anywhere
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Dungeon Rewards Can Be Anywhere: On
@@ -0,0 +1,5 @@
Seed: TESTTESTTEST
Bonks Do Damage: On
Damage Multiplier: OHKO
Eldin Twilight Cleared: On
Lanayru Twilight Cleared: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Eldin Twilight Cleared: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Lanayru Twilight Cleared: On
@@ -0,0 +1 @@
Seed: TESTTESTTEST
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Faron Twilight Cleared: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Freestanding Rupees: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Gifts From NPCs: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Golden Bugs: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Hidden Rupees: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Hidden Skills: On
@@ -0,0 +1,3 @@
Seed: TESTTESTTEST
Hyrule Barrier Requirements: Dungeons
Hyrule Barrier Dungeons: 8
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Hyrule Barrier Requirements: Fused Shadows
@@ -0,0 +1,3 @@
seed: TESTTESTTEST
Hyrule Barrier Requirements: Hearts
Hyrule Barrier Hearts: 13
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Hyrule Barrier Requirements: Mirror Shards
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Hyrule Barrier Requirements: Open
@@ -0,0 +1,3 @@
seed: TESTTESTTEST
Hyrule Barrier Requirements: Poe Souls
Hyrule Barrier Poe Souls: 30
@@ -0,0 +1,4 @@
Seed: TESTTESTTEST
Small Keys: Keysy
Big Keys: Keysy
Maps and Compasses: Start With
@@ -0,0 +1,16 @@
Seed: TESTTESTTEST
Faron Woods Logic: Open
Skip Prologue: On
Faron Twilight Cleared: On
Eldin Twilight Cleared: On
Lanayru Twilight Cleared: On
Skip Midna's Desparate Hour: On
Randomize Starting Spawn: On
Randomize Dungeon Entrances: On
Randomize Boss Entrances: On
Randomize Grotto Entrances: On
Randomize Cave Entrances: On
Randomize Interior Entrances: On
Randomize Overworld Entrances: On
Decouple Double Door Entrances: On
Decouple Entrances: On
@@ -0,0 +1,15 @@
Seed: TESTTESTTEST
Faron Woods Logic: Open
Skip Prologue: On
Faron Twilight Cleared: On
Eldin Twilight Cleared: On
Lanayru Twilight Cleared: On
Skip Midna's Desparate Hour: On
Randomize Starting Spawn: On
Randomize Dungeon Entrances: On
Randomize Grotto Entrances: On
Randomize Cave Entrances: On
Randomize Interior Entrances: On
Randomize Overworld Entrances: On
Mixed Entrance Pools:
[["Dungeon", "Grotto"], ["Overworld", "Cave", "Interior"]]
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Faron Woods Logic: Open
@@ -0,0 +1,7 @@
Seed: TESTTESTTEST
Skip Prologue: On
Faron Woods Logic: Open
Faron Twilight Cleared: On
Eldin Twilight Cleared: On
Lanayru Twilight Cleared: On
Unlock Map Regions: On
@@ -0,0 +1,4 @@
Seed: TESTTESTTEST
Small Keys: Overworld
Big Keys: Overworld
Maps and Compasses: Overworld
@@ -0,0 +1,4 @@
Seed: TESTTESTTEST
Small Keys: Own Dungeon
Big Keys: Own Dungeon
Maps and Compasses: Own Dungeon
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Palace of Twilight Requirements: Fused Shadows
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Palace of Twilight Requirements: Mirror Shards
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Palace of Twilight Requirements: Open
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Poe Souls: All
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Poe Souls: Dungeon
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Poe Souls: Overworld
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Randomize Boss Entrances: On
@@ -0,0 +1,8 @@
Seed: TESTTESTTEST
Faron Woods Logic: Open
Skip Prologue: On
Faron Twilight Cleared: On
Eldin Twilight Cleared: On
Lanayru Twilight Cleared: On
Skip Midna's Desparate Hour: On
Randomize Cave Entrances: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Randomize Dungeon Entrances: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Randomize Grotto Entrances: On
@@ -0,0 +1,8 @@
Seed: TESTTESTTEST
Faron Woods Logic: Open
Skip Prologue: On
Faron Twilight Cleared: On
Eldin Twilight Cleared: On
Lanayru Twilight Cleared: On
Skip Midna's Desparate Hour: On
Randomize Interior Entrances: On
@@ -0,0 +1,8 @@
Seed: TESTTESTTEST
Faron Woods Logic: Open
Skip Prologue: On
Faron Twilight Cleared: On
Eldin Twilight Cleared: On
Lanayru Twilight Cleared: On
Skip Midna's Desparate Hour: On
Randomize Overworld Entrances: On
@@ -0,0 +1,8 @@
Seed: TESTTESTTEST
Faron Woods Logic: Open
Skip Prologue: On
Faron Twilight Cleared: On
Eldin Twilight Cleared: On
Lanayru Twilight Cleared: On
Skip Midna's Desparate Hour: On
Randomize Starting Spawn: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Item Scarcity: Minimal
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Item Scarcity: Plentiful
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Shop Items: On
@@ -0,0 +1,8 @@
Seed: TESTTESTTEST
Lakebed Does Not Require Water Bombs: On
Arbiters Does Not Require Bulblin Camp: On
Snowpeak Does Not Require Reekfish Scent: On
Sacred Grove Does Not Require Skull Kid: On
City Does Not Require Filled Skybook: On
Goron Mines Entrance: On
Temple of Time Sword Requirement: None
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Skip Midna's Desparate Hour: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Skip Prologue: On
@@ -0,0 +1,2 @@
Seed: TESTTESTTEST
Sky Characters: On
@@ -0,0 +1,3 @@
Seed: TESTTESTTEST
Unrequired Dungeons Are Barren: On
Hyrule Barrier Requirements: Mirror Shards
@@ -0,0 +1,4 @@
Seed: TESTTESTTEST
Starting Form: Wolf
Skip Prologue: On
Faron Woods Logic: Open
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

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