mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-04 19:25:43 -04:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1520205403 | |||
| d2d7459d05 | |||
| c71272af05 |
+1
-1
@@ -2,7 +2,7 @@
|
||||
Language: Cpp
|
||||
Standard: C++03
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignOperands: true
|
||||
|
||||
@@ -100,7 +100,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||
endif ()
|
||||
set(AURORA_ENABLE_DVD ON CACHE BOOL "Enable DVD API support" FORCE)
|
||||
set(AURORA_ENABLE_CARD ON CACHE BOOL "Enable CARD API support" FORCE)
|
||||
set(AURORA_ENABLE_RMLUI ON CACHE BOOL "Enable RmlUi UI support" FORCE)
|
||||
add_subdirectory(extern/aurora EXCLUDE_FROM_ALL)
|
||||
|
||||
add_subdirectory(libs/freeverb)
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||

|
||||

|
||||
|
||||
- ### **[Official Website](https://twilitrealm.dev)**
|
||||
- ### **[Discord](https://discord.gg/QACynxeyna)**
|
||||
|
||||
# Overview
|
||||
Dusk is a reverse-engineered reimplementation of Twilight Princess.
|
||||
It aims to be as accurate as possible to the original while also providing new options, enhancements, and tools to customize your experience.
|
||||
|
||||
# Setup
|
||||
**⚠️ Dusk does NOT provide any copyrighted assets. You must provide your own copy of the game.**
|
||||
|
||||
@@ -31,7 +27,5 @@ First make sure your dump of the game is clean and supported by Dusk. You can do
|
||||
# Building
|
||||
If you'd like to build Dusk from source, please read the [build instructions](docs/building.md).
|
||||
|
||||
Pull Requests are welcomed! Note that we do not accept contributions that are primarily AI generated and will close your PR if we suspect as much.
|
||||
|
||||
# Credits
|
||||
Special thanks to the [TP decompilation](https://github.com/zeldaret/tp) team, the GC/Wii decompilation community, the [Aurora](https://github.com/encounter/aurora) developers, the [TP speedrunning community](https://zsrtp.link), and all [contributors](https://github.com/TwilitRealm/dusk/graphs/contributors).
|
||||
|
||||
Vendored
+1
-1
Submodule extern/aurora updated: 77ad549530...7784b6fc95
+3
-44
@@ -1,7 +1,7 @@
|
||||
|
||||
set(DOLZEL_FILES
|
||||
src/m_Do/m_Do_main.cpp
|
||||
#src/m_Do/m_Do_printf.cpp
|
||||
src/m_Do/m_Do_printf.cpp
|
||||
src/m_Do/m_Do_audio.cpp
|
||||
src/m_Do/m_Do_controller_pad.cpp
|
||||
#src/m_Do/m_Re_controller_pad.cpp
|
||||
@@ -1429,7 +1429,6 @@ set(DUSK_FILES
|
||||
src/dusk/globals.cpp
|
||||
src/dusk/gyro.cpp
|
||||
src/dusk/gamepad_color.cpp
|
||||
src/dusk/autosave.cpp
|
||||
src/dusk/io.cpp
|
||||
src/dusk/layout.cpp
|
||||
src/dusk/logging.cpp
|
||||
@@ -1454,6 +1453,7 @@ set(DUSK_FILES
|
||||
src/dusk/imgui/ImGuiProcessOverlay.cpp
|
||||
src/dusk/imgui/ImGuiCameraOverlay.cpp
|
||||
src/dusk/imgui/ImGuiHeapOverlay.cpp
|
||||
src/dusk/imgui/ImGuiActorSpawner.cpp
|
||||
src/dusk/imgui/ImGuiDebugPad.cpp
|
||||
src/dusk/imgui/ImGuiControllerOverlay.cpp
|
||||
src/dusk/imgui/ImGuiStubLog.cpp
|
||||
@@ -1463,53 +1463,12 @@ set(DUSK_FILES
|
||||
src/dusk/imgui/ImGuiStateShare.cpp
|
||||
src/dusk/imgui/ImGuiAchievements.hpp
|
||||
src/dusk/imgui/ImGuiAchievements.cpp
|
||||
src/dusk/ui/bool_button.cpp
|
||||
src/dusk/ui/bool_button.hpp
|
||||
src/dusk/ui/button.cpp
|
||||
src/dusk/ui/button.hpp
|
||||
src/dusk/ui/component.cpp
|
||||
src/dusk/ui/component.hpp
|
||||
src/dusk/ui/controller_config.cpp
|
||||
src/dusk/ui/controller_config.hpp
|
||||
src/dusk/ui/document.cpp
|
||||
src/dusk/ui/document.hpp
|
||||
src/dusk/ui/editor.cpp
|
||||
src/dusk/ui/editor.hpp
|
||||
src/dusk/ui/event.cpp
|
||||
src/dusk/ui/event.hpp
|
||||
src/dusk/ui/input.cpp
|
||||
src/dusk/ui/input.hpp
|
||||
src/dusk/ui/nav_types.hpp
|
||||
src/dusk/ui/number_button.cpp
|
||||
src/dusk/ui/number_button.hpp
|
||||
src/dusk/ui/overlay.cpp
|
||||
src/dusk/ui/overlay.hpp
|
||||
src/dusk/ui/pane.cpp
|
||||
src/dusk/ui/pane.hpp
|
||||
src/dusk/ui/popup.cpp
|
||||
src/dusk/ui/popup.hpp
|
||||
src/dusk/ui/prelaunch.cpp
|
||||
src/dusk/ui/prelaunch.hpp
|
||||
src/dusk/ui/prelaunch_options.cpp
|
||||
src/dusk/ui/prelaunch_options.hpp
|
||||
src/dusk/ui/select_button.cpp
|
||||
src/dusk/ui/select_button.hpp
|
||||
src/dusk/ui/settings.cpp
|
||||
src/dusk/ui/settings.hpp
|
||||
src/dusk/ui/string_button.cpp
|
||||
src/dusk/ui/string_button.hpp
|
||||
src/dusk/ui/tab_bar.cpp
|
||||
src/dusk/ui/tab_bar.hpp
|
||||
src/dusk/ui/ui.cpp
|
||||
src/dusk/ui/ui.hpp
|
||||
src/dusk/ui/window.cpp
|
||||
src/dusk/ui/window.hpp
|
||||
src/dusk/achievements.cpp
|
||||
src/dusk/iso_validate.cpp
|
||||
src/dusk/livesplit.cpp
|
||||
src/dusk/offset_ptr.cpp
|
||||
src/dusk/vmem.cpp
|
||||
src/dusk/OSContext.cpp
|
||||
src/dusk/OSReport.cpp
|
||||
src/dusk/OSThread.cpp
|
||||
src/dusk/OSMutex.cpp
|
||||
src/dusk/discord_presence.cpp
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
/* 0x17C */ cXyz mViewScale;
|
||||
#if TARGET_PC
|
||||
bool mbReset = false;
|
||||
bool mbHadEntry = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -25,10 +25,6 @@ public:
|
||||
int Draw();
|
||||
int Delete();
|
||||
|
||||
#if TARGET_PC
|
||||
void onInterpCallback();
|
||||
#endif
|
||||
|
||||
enum Param_e {
|
||||
LOCK_e = (1 << 6), NO_BASE_DISP = (1 << 7)
|
||||
};
|
||||
@@ -54,13 +50,6 @@ private:
|
||||
/* 0x1020 */ dCcD_Cyl mCylinderCollider;
|
||||
/* 0x115C */ s32 mStopSwingingFrames;
|
||||
|
||||
#if TARGET_PC
|
||||
cXyz mChainInterpPrev[64];
|
||||
cXyz mChainInterpCurr[64];
|
||||
bool mChainInterpPrevValid;
|
||||
bool mChainInterpCurrValid;
|
||||
#endif
|
||||
|
||||
// Number of chain models
|
||||
u32 getArg0() {
|
||||
return fopAcM_GetParamBit(this, 0, 6);
|
||||
|
||||
@@ -91,10 +91,6 @@ public:
|
||||
void calcCursor();
|
||||
void drawCursor();
|
||||
|
||||
#if TARGET_PC
|
||||
void dMapBgWide();
|
||||
#endif
|
||||
|
||||
void setDPDFloorSelCurPos(s8 i_pos) { field_0xdd6 = i_pos; }
|
||||
|
||||
f32 getMapWidth() { return mMapWidth; }
|
||||
|
||||
@@ -81,10 +81,6 @@ public:
|
||||
void calcDrawPriority();
|
||||
void setArrowPosAxis(f32, f32);
|
||||
|
||||
#if TARGET_PC
|
||||
void fMapBackWide();
|
||||
#endif
|
||||
|
||||
virtual void draw();
|
||||
virtual ~dMenu_Fmap2DBack_c();
|
||||
|
||||
@@ -334,10 +330,6 @@ public:
|
||||
void setHIO(bool);
|
||||
bool isWarpAccept();
|
||||
|
||||
#if TARGET_PC
|
||||
void fMapTopWide();
|
||||
#endif
|
||||
|
||||
virtual void draw();
|
||||
virtual ~dMenu_Fmap2DTop_c();
|
||||
|
||||
|
||||
@@ -67,9 +67,6 @@ public:
|
||||
bool isStaffMessage();
|
||||
bool isSaveMessage();
|
||||
bool isTalkMessage();
|
||||
#if TARGET_PC
|
||||
bool isShopItemMessage();
|
||||
#endif
|
||||
const char* getSmellName();
|
||||
const char* getPortalName();
|
||||
const char* getBombName();
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
@@ -16,7 +14,6 @@ enum class AchievementCategory : uint8_t {
|
||||
Collection,
|
||||
Challenge,
|
||||
Minigame,
|
||||
Misc,
|
||||
Glitched
|
||||
};
|
||||
|
||||
@@ -43,11 +40,6 @@ public:
|
||||
void save();
|
||||
void tick();
|
||||
void clearAll();
|
||||
void clearOne(const char* key);
|
||||
|
||||
// Signals are visible to all achievement checks within the same tick, then cleared.
|
||||
void signal(const char* key);
|
||||
bool hasSignal(const char* key) const;
|
||||
|
||||
std::vector<Achievement> getAchievements() const;
|
||||
bool hasPendingUnlock() const { return !m_pendingUnlocks.empty(); }
|
||||
@@ -65,7 +57,6 @@ private:
|
||||
void processEntry(Entry& e);
|
||||
|
||||
std::vector<Entry> m_entries;
|
||||
std::unordered_set<std::string_view> m_signals;
|
||||
bool m_loaded = false;
|
||||
bool m_dirty = false;
|
||||
std::queue<std::string> m_pendingUnlocks;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef AUTOSAVE_H
|
||||
#define AUTOSAVE_H
|
||||
|
||||
#include <m_Do/m_Do_MemCardRWmng.h>
|
||||
#include <m_Do/m_Do_MemCard.h>
|
||||
|
||||
void noAutoSave();
|
||||
void triggerAutoSave();
|
||||
void updateAutoSave();
|
||||
void enterAutoSave();
|
||||
void autoSaving();
|
||||
void waitingForWrite();
|
||||
void endAutoSave();
|
||||
|
||||
#endif
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef DUSK_MEMORY_H
|
||||
#define DUSK_MEMORY_H
|
||||
|
||||
#if TARGET_PC
|
||||
#define HEAP_SIZE(original, dusk) (dusk)
|
||||
#else
|
||||
#define HEAP_SIZE(original, dusk) (original)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -55,7 +55,6 @@ struct UserSettings {
|
||||
ConfigVar<int> soundEffectsVolume;
|
||||
ConfigVar<int> fanfareVolume;
|
||||
ConfigVar<bool> enableReverb;
|
||||
ConfigVar<bool> enableHrtf;
|
||||
} audio;
|
||||
|
||||
// Game settings
|
||||
@@ -81,7 +80,6 @@ struct UserSettings {
|
||||
ConfigVar<bool> instantSaves;
|
||||
ConfigVar<bool> instantText;
|
||||
ConfigVar<bool> sunsSong;
|
||||
ConfigVar<bool> autoSave;
|
||||
|
||||
// Preferences
|
||||
ConfigVar<bool> enableMirrorMode;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace dusk {
|
||||
#endif
|
||||
|
||||
// Reserve a contiguous virtual address range without committing physical pages
|
||||
void* vmem_reserve(size_t size);
|
||||
|
||||
// Commit physical backing for pages in a previously reserved range, ptr and size should be page-aligned
|
||||
bool vmem_commit(void* ptr, size_t size);
|
||||
|
||||
// Decommit physical pages in a reserved range, releasing RAM without releasing address space
|
||||
void vmem_decommit(void* ptr, size_t size);
|
||||
|
||||
// Release an entire virtual reservation obtained from vmem_reserve
|
||||
void vmem_release(void* ptr, size_t size);
|
||||
|
||||
// Returns the OS page size
|
||||
size_t vmem_page_size();
|
||||
|
||||
// Shared vmem arena
|
||||
// All JKR heap vmem reservations are sub-allocated from a single large reservation,
|
||||
// keeping the total entry count at 1 regardless of how many heaps exist
|
||||
|
||||
// Must be called once before any JKR heap is created
|
||||
void vmem_arena_init();
|
||||
|
||||
// Allocate a slot of size bytes (page-aligned) from the arena
|
||||
void* vmem_arena_alloc(size_t size);
|
||||
|
||||
// Return a slot to the arena and decommit its physical pages
|
||||
void vmem_arena_free(void* ptr, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // namespace dusk
|
||||
|
||||
// Total virtual address space reserved for the shared JKR heap arena
|
||||
inline constexpr size_t JKR_VMEM_ARENA_SIZE = 128ULL * 1024 * 1024 * 1024; // 128 GB
|
||||
|
||||
// Virtual address space reserved per JKR heap (one slot in the shared arena)
|
||||
inline constexpr size_t JKR_HEAP_VIRTUAL_RESERVE = 64ULL * 1024 * 1024; // 64 MB
|
||||
|
||||
// Minimum growth increment when a JKR heap expands into reserved but uncommitted pages
|
||||
inline constexpr size_t JKR_HEAP_GROW_CHUNK = 4ULL * 1024 * 1024; // 4 MB
|
||||
|
||||
// Maximum number of free slots the arena can track (= total slots in the arena)
|
||||
inline constexpr size_t JKR_VMEM_MAX_FREE_SLOTS = JKR_VMEM_ARENA_SIZE / JKR_HEAP_VIRTUAL_RESERVE;
|
||||
|
||||
#endif
|
||||
@@ -59,9 +59,6 @@ public:
|
||||
bool isActive() const { return mSeqList.getNumLinks() != 0; }
|
||||
int getNumActiveSeqs() const { return mSeqList.getNumLinks(); }
|
||||
void pause(bool paused) { mActivity.field_0x0.flags.flag2 = paused; }
|
||||
#if TARGET_PC
|
||||
JSUList<JAISeq>* getSeqList() { return &mSeqList; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
/* 0x08 */ JAIAudience* mAudience;
|
||||
|
||||
@@ -127,6 +127,13 @@ public:
|
||||
[[nodiscard]] const CMemBlock* getFreeHead() const { return mHeadFreeList; }
|
||||
[[nodiscard]] CMemBlock* getUsedHead() { return mHeadUsedList; }
|
||||
[[nodiscard]] const CMemBlock* getUsedHead() const { return mHeadUsedList; }
|
||||
|
||||
void* mVmemBase; // base of VM reservation
|
||||
size_t mVmemCapacity; // total reserved bytes
|
||||
size_t mVmemCommitted; // page-aligned committed bytes so far
|
||||
|
||||
// Commit more pages and splice them into the free list
|
||||
bool growHeap(u32 needed);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -61,6 +61,15 @@ public:
|
||||
static JKRSolidHeap* create(u32, JKRHeap*, bool);
|
||||
|
||||
static void* getState_(TState* state) { return getState_buf_(state); }
|
||||
|
||||
#if TARGET_PC
|
||||
void* mVmemBase; // base of VM reservation
|
||||
size_t mVmemCapacity; // total reserved bytes
|
||||
size_t mVmemCommitted; // page-aligned committed bytes so far
|
||||
|
||||
// Commit more pages and extend the free region
|
||||
bool growHeap(u32 needed);
|
||||
#endif
|
||||
};
|
||||
|
||||
inline JKRSolidHeap* JKRCreateSolidHeap(u32 param_0, JKRHeap* heap, bool param_2) {
|
||||
|
||||
@@ -207,11 +207,4 @@ void JPARegistAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
|
||||
void JPARegistPrmAlpha(JPAEmitterWorkData*, JPABaseParticle*);
|
||||
void JPARegistPrmAlphaEnv(JPAEmitterWorkData*, JPABaseParticle*);
|
||||
|
||||
#if TARGET_PC
|
||||
void JPAInterpBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
||||
void JPAInterpRotBillboard(JPAEmitterWorkData*, JPABaseParticle*);
|
||||
void JPAInterpDirection(JPAEmitterWorkData*, JPABaseParticle*);
|
||||
void JPAInterpRotDirection(JPAEmitterWorkData*, JPABaseParticle*);
|
||||
#endif
|
||||
|
||||
#endif /* JPABASESHAPE_H */
|
||||
|
||||
@@ -24,9 +24,6 @@ public:
|
||||
void init_c(JPAEmitterWorkData*, JPABaseParticle*);
|
||||
bool calc_p(JPAEmitterWorkData*);
|
||||
bool calc_c(JPAEmitterWorkData*);
|
||||
#if TARGET_PC
|
||||
void interp(JPAEmitterWorkData*, void const* drawFunc);
|
||||
#endif
|
||||
bool canCreateChild(JPAEmitterWorkData*);
|
||||
f32 getWidth(JPABaseEmitter const*) const;
|
||||
f32 getHeight(JPABaseEmitter const*) const;
|
||||
|
||||
@@ -40,9 +40,6 @@ public:
|
||||
JUTTransparency getTransparency() const { return JUTTransparency(mTransparency); }
|
||||
u16 getNumColors() const { return mNumColors; }
|
||||
ResTLUT* getColorTable() const { return mColorTable; }
|
||||
#if TARGET_PC
|
||||
void dataUploaded();
|
||||
#endif
|
||||
|
||||
private:
|
||||
/* 0x00 */ GXTlutObj mTlutObj;
|
||||
|
||||
@@ -75,7 +75,6 @@ public:
|
||||
s32 getTransparency() const { return mTexInfo->alphaEnabled; }
|
||||
s32 getWidth() const { return mTexInfo->width; }
|
||||
s32 getHeight() const { return mTexInfo->height; }
|
||||
JUTPalette* getPalette() const { return mPalette; }
|
||||
void setCaptureFlag(bool flag) { mFlags &= 2 | flag; }
|
||||
bool getCaptureFlag() const { return mFlags & 1; }
|
||||
bool getEmbPaletteDelFlag() const { return mFlags & 2; }
|
||||
@@ -83,7 +82,7 @@ public:
|
||||
int getTlutName() const { return mTlutName; }
|
||||
bool operator==(const JUTTexture& other) {
|
||||
return mTexInfo == other.mTexInfo
|
||||
&& mPalette == other.mPalette
|
||||
&& field_0x2c == other.field_0x2c
|
||||
&& mWrapS == other.mWrapS
|
||||
&& mWrapT == other.mWrapT
|
||||
&& mMinFilter == other.mMinFilter
|
||||
@@ -101,7 +100,7 @@ private:
|
||||
/* 0x20 */ const ResTIMG* mTexInfo;
|
||||
/* 0x24 */ void* mTexData;
|
||||
/* 0x28 */ JUTPalette* mEmbPalette;
|
||||
/* 0x2C */ JUTPalette* mPalette;
|
||||
/* 0x2C */ JUTPalette* field_0x2c;
|
||||
/* 0x30 */ u8 mWrapS;
|
||||
/* 0x31 */ u8 mWrapT;
|
||||
/* 0x32 */ u8 mMinFilter;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#include "JSystem/JSystem.h" // IWYU pragma: keep
|
||||
|
||||
#include "JSystem/JAudio2/JASChannel.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/audio/DuskDsp.hpp"
|
||||
#endif
|
||||
#include "JSystem/JAudio2/JASAiCtrl.h"
|
||||
#include "JSystem/JAudio2/JASCalc.h"
|
||||
#include "JSystem/JAudio2/JASDriverIF.h"
|
||||
@@ -173,12 +170,7 @@ void JASChannel::updateEffectorParam(JASDsp::TChannel* i_channel, u16* i_mixerVo
|
||||
|
||||
f32 pan = 0.5f;
|
||||
f32 dolby = 0.0f;
|
||||
#if TARGET_PC
|
||||
u32 effectiveOutputMode = dusk::audio::EnableHrtf ? JAS_OUTPUT_SURROUND : JASDriver::getOutputMode();
|
||||
#else
|
||||
u32 effectiveOutputMode = JASDriver::getOutputMode();
|
||||
#endif
|
||||
switch (effectiveOutputMode) {
|
||||
switch (JASDriver::getOutputMode()) {
|
||||
case JAS_OUTPUT_MONO:
|
||||
break;
|
||||
case JAS_OUTPUT_STEREO:
|
||||
|
||||
@@ -302,6 +302,7 @@ void JASKernel::setupRootHeap(JKRSolidHeap* heap, u32 size) {
|
||||
JKRHEAP_NAME(sSystemHeap, "JASKernel::sSystemHeap");
|
||||
JUT_ASSERT(787, sSystemHeap);
|
||||
sCommandHeap = JKR_NEW_ARGS (heap, 0) JASMemChunkPool<1024, JASThreadingModel::ObjectLevelLockable>;
|
||||
JKRHEAP_NAME(sSystemHeap, "JASKernel::sCommandHeap");
|
||||
JUT_ASSERT(790, sCommandHeap);
|
||||
JASDram = heap;
|
||||
}
|
||||
|
||||
@@ -442,7 +442,6 @@ static JAUSectionHeap* JAUNewSectionHeap(JKRSolidHeap* heap, bool param_1) {
|
||||
JAUSectionHeap* JAUNewSectionHeap(bool param_0) {
|
||||
s32 freeSize = JASDram->getFreeSize();
|
||||
JKRSolidHeap* sectionHeap = JKRCreateSolidHeap(freeSize, JASDram, true);
|
||||
JKRHEAP_NAME(sectionHeap, "sectionHeap");
|
||||
JUT_ASSERT(821, sectionHeap);
|
||||
return JAUNewSectionHeap(sectionHeap, param_0);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
#include "JSystem/JUtility/JUTConsole.h"
|
||||
#include "JSystem/JUtility/JUTException.h"
|
||||
#include <cstdlib>
|
||||
#if TARGET_PC
|
||||
#include "dusk/vmem.h"
|
||||
#include <algorithm>
|
||||
#include "dusk/logging.h"
|
||||
#endif
|
||||
|
||||
JKRExpHeap* JKRExpHeap::createRoot(int maxHeaps, bool errorFlag) {
|
||||
JKRExpHeap* heap = NULL;
|
||||
@@ -71,21 +76,49 @@ JKRExpHeap* JKRExpHeap::create(u32 size, JKRHeap* parent, bool errorFlag) {
|
||||
|
||||
u32 alignedSize = ALIGN_PREV(size, 0x10);
|
||||
|
||||
if (alignedSize < expHeapSize + blockSize)
|
||||
if (alignedSize < expHeapSize + blockSize) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8* memory = (u8*)JKRAllocFromHeap(parent, alignedSize, 0x10);
|
||||
u8* dataPtr = (memory + expHeapSize);
|
||||
#if TARGET_PC
|
||||
u8* vmemBase = (u8*)dusk::vmem_arena_alloc(JKR_HEAP_VIRTUAL_RESERVE);
|
||||
if (!vmemBase) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const size_t pageSize = dusk::vmem_page_size();
|
||||
size_t commitSize = ALIGN_NEXT((size_t)alignedSize, pageSize);
|
||||
if (!dusk::vmem_commit(vmemBase, commitSize)) {
|
||||
dusk::vmem_arena_free(vmemBase, JKR_HEAP_VIRTUAL_RESERVE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8* memory = vmemBase;
|
||||
u8* dataPtr = memory + expHeapSize;
|
||||
|
||||
newHeap = JKR_NEW_ARGS(memory) JKRExpHeap(dataPtr, alignedSize - expHeapSize, parent, errorFlag);
|
||||
if (newHeap == NULL) {
|
||||
dusk::vmem_arena_free(vmemBase, JKR_HEAP_VIRTUAL_RESERVE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newHeap->mVmemBase = vmemBase;
|
||||
newHeap->mVmemCapacity = JKR_HEAP_VIRTUAL_RESERVE;
|
||||
newHeap->mVmemCommitted = commitSize;
|
||||
#else
|
||||
u8* memory = (u8*)JKRAllocFromHeap(parent, alignedSize, 0x10);
|
||||
u8* dataPtr = memory + expHeapSize;
|
||||
if (!memory) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newHeap = JKR_NEW_ARGS (memory) JKRExpHeap(dataPtr, alignedSize - expHeapSize, parent, errorFlag);
|
||||
|
||||
newHeap = JKR_NEW_ARGS(memory) JKRExpHeap(dataPtr, alignedSize - expHeapSize, parent, errorFlag);
|
||||
if (newHeap == NULL) {
|
||||
JKRFree(memory);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
if (newHeap) {
|
||||
u8* local_30 = dataPtr + sizeof(CMemBlock);
|
||||
@@ -102,9 +135,16 @@ JKRExpHeap* JKRExpHeap::create(u32 size, JKRHeap* parent, bool errorFlag) {
|
||||
JKRExpHeap* JKRExpHeap::create(void* ptr, u32 size, JKRHeap* parent, bool errorFlag) {
|
||||
JKRHeap* parent2;
|
||||
if (parent == NULL) {
|
||||
#if TARGET_PC
|
||||
// VM-backed heaps live outside the root heap's address range, so find() fails
|
||||
// findAllHeap() searches the full tree
|
||||
parent2 = getRootHeap()->findAllHeap(ptr);
|
||||
#else
|
||||
parent2 = getRootHeap()->find(ptr);
|
||||
if (!parent2)
|
||||
#endif
|
||||
if (!parent2) {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
parent2 = parent;
|
||||
}
|
||||
@@ -136,6 +176,15 @@ JKRExpHeap* JKRExpHeap::create(void* ptr, u32 size, JKRHeap* parent, bool errorF
|
||||
}
|
||||
|
||||
void JKRExpHeap::do_destroy() {
|
||||
#if TARGET_PC
|
||||
if (mVmemBase) {
|
||||
void* vmemBase = mVmemBase;
|
||||
size_t vmemCapacity = mVmemCapacity;
|
||||
this->~JKRExpHeap();
|
||||
dusk::vmem_arena_free(vmemBase, vmemCapacity);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!field_0x6e) {
|
||||
JKRHeap* heap = getParent();
|
||||
if (heap) {
|
||||
@@ -163,6 +212,11 @@ JKRExpHeap::JKRExpHeap(void* data, u32 size, JKRHeap* parent, bool errorFlag)
|
||||
mHeadFreeList->initiate(NULL, NULL, size - sizeof(CMemBlock), 0, 0);
|
||||
mHeadUsedList = NULL;
|
||||
mTailUsedList = NULL;
|
||||
#if TARGET_PC
|
||||
mVmemBase = nullptr;
|
||||
mVmemCapacity = 0;
|
||||
mVmemCommitted = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
JKRExpHeap::~JKRExpHeap() {
|
||||
@@ -214,6 +268,24 @@ void* JKRExpHeap::do_alloc(u32 size, int alignment) {
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
if (!ptr && mVmemBase) {
|
||||
// Heap is full, commit the next chunk of reserved VM and retry
|
||||
if (growHeap(size)) {
|
||||
if (alignment >= 0) {
|
||||
if (alignment <= 4) {
|
||||
ptr = allocFromHead(size);
|
||||
} else {
|
||||
ptr = allocFromHead(size, alignment);
|
||||
}
|
||||
} else {
|
||||
if (-alignment <= 4) {
|
||||
ptr = allocFromTail(size);
|
||||
} else {
|
||||
ptr = allocFromTail(size, -alignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ptr) {
|
||||
// Allocation failed.
|
||||
OSReport_Error(
|
||||
@@ -222,11 +294,16 @@ void* JKRExpHeap::do_alloc(u32 size, int alignment) {
|
||||
OSReport_Error("Free block list as follows:\n");
|
||||
OSReport_Error("Start | End | Size \n");
|
||||
|
||||
int i = 0;
|
||||
for (const CMemBlock* block = mHeadFreeList; block; block = block->mNext) {
|
||||
if (block->mMagic) {
|
||||
// Allocated, ignore.
|
||||
continue;
|
||||
}
|
||||
if (i++ > 10) {
|
||||
OSReport_Error("<more>\n");
|
||||
break;
|
||||
}
|
||||
|
||||
auto blockStart = (uintptr_t)block - (uintptr_t)mStart;
|
||||
auto blockEnd = (uintptr_t)block + block->size - (uintptr_t)mStart;
|
||||
@@ -234,14 +311,6 @@ void* JKRExpHeap::do_alloc(u32 size, int alignment) {
|
||||
OSReport_Error("%08X | %08X | %08X\n", (u32) blockStart, (u32) blockEnd, (u32) blockSize);
|
||||
}
|
||||
|
||||
OSReport_Error("Child heaps as follows:\n");
|
||||
OSReport_Error("Start | End | Name \n");
|
||||
|
||||
const JSUTree<JKRHeap>& tree = getHeapTree();
|
||||
for (JSUTreeIterator iter(tree.getFirstChild()); iter != tree.getEndChild(); ++iter) {
|
||||
OSReport_Error("%08X | %08X | %s\n", iter->getStartAddr(), iter->getEndAddr(), iter->getName());
|
||||
}
|
||||
|
||||
CRASH("Aborting due to allocation failure!");
|
||||
}
|
||||
#else
|
||||
@@ -494,6 +563,49 @@ static void dummy() {
|
||||
OS_REPORT("newSize > 0");
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
bool JKRExpHeap::growHeap(u32 needed) {
|
||||
// Determine how much to commit
|
||||
// Always grow by at least JKR_HEAP_GROW_CHUNK
|
||||
const size_t pageSize = dusk::vmem_page_size();
|
||||
size_t wantBytes = (size_t)needed + sizeof(CMemBlock);
|
||||
size_t growAmount = std::max(wantBytes, JKR_HEAP_GROW_CHUNK);
|
||||
growAmount = ALIGN_NEXT(growAmount, pageSize);
|
||||
|
||||
size_t remaining = mVmemCapacity - mVmemCommitted;
|
||||
if (growAmount > remaining) {
|
||||
// Clamp to whatever reservation is left
|
||||
growAmount = ALIGN_PREV(remaining, pageSize);
|
||||
if (growAmount < wantBytes) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void* commitBase = (u8*)mVmemBase + mVmemCommitted;
|
||||
if (!dusk::vmem_commit(commitBase, growAmount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Splice the new committed region into the free list as a single block at mEnd
|
||||
CMemBlock* newBlock = (CMemBlock*)mEnd;
|
||||
newBlock->size = (u32)(growAmount - sizeof(CMemBlock));
|
||||
newBlock->mFlags = 0;
|
||||
|
||||
mEnd = (u8*)mEnd + growAmount;
|
||||
mSize += (u32)growAmount;
|
||||
mVmemCommitted += growAmount;
|
||||
|
||||
recycleFreeBlock(newBlock);
|
||||
|
||||
DuskLog.debug("[JKRExpHeap] '{}' grew by {} MB (committed: {} MB / reserved: {} MB)\n",
|
||||
getName(),
|
||||
growAmount / (1024 * 1024),
|
||||
mVmemCommitted / (1024 * 1024),
|
||||
mVmemCapacity / (1024 * 1024));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void JKRExpHeap::do_freeAll() {
|
||||
lock();
|
||||
JKRHeap::callAllDisposer();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "JSystem/JSystem.h" // IWYU pragma: keep
|
||||
#include "JSystem/JSystem.h" // IWYU pragma: keep
|
||||
|
||||
#include "JSystem/JKernel/JKRSolidHeap.h"
|
||||
#include "JSystem/JGadget/binary.h"
|
||||
@@ -7,6 +7,11 @@
|
||||
#include "global.h"
|
||||
#include <stdint.h>
|
||||
#include <cstdlib>
|
||||
#if TARGET_PC
|
||||
#include "dusk/vmem.h"
|
||||
#include <algorithm>
|
||||
#include "dusk/logging.h"
|
||||
#endif
|
||||
|
||||
JKRSolidHeap* JKRSolidHeap::create(u32 size, JKRHeap* heap, bool useErrorHandler) {
|
||||
if (!heap) {
|
||||
@@ -19,18 +24,56 @@ JKRSolidHeap* JKRSolidHeap::create(u32 size, JKRHeap* heap, bool useErrorHandler
|
||||
}
|
||||
|
||||
u32 alignedSize = ALIGN_PREV(size, 0x10);
|
||||
if (alignedSize < solidHeapSize)
|
||||
if (alignedSize < solidHeapSize) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
u8* vmemBase = (u8*)dusk::vmem_arena_alloc(JKR_HEAP_VIRTUAL_RESERVE);
|
||||
if (!vmemBase) {
|
||||
return NULL;
|
||||
}
|
||||
const size_t pageSize = dusk::vmem_page_size();
|
||||
size_t commitSize = ALIGN_NEXT((size_t)alignedSize, pageSize);
|
||||
if (!dusk::vmem_commit(vmemBase, commitSize)) {
|
||||
dusk::vmem_arena_free(vmemBase, JKR_HEAP_VIRTUAL_RESERVE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8* mem = vmemBase;
|
||||
void* dataPtr = mem + solidHeapSize;
|
||||
|
||||
JKRSolidHeap* newHeap = JKR_NEW_ARGS(mem) JKRSolidHeap(dataPtr, alignedSize - solidHeapSize, heap, useErrorHandler);
|
||||
if (newHeap == NULL) {
|
||||
dusk::vmem_arena_free(vmemBase, JKR_HEAP_VIRTUAL_RESERVE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newHeap->mVmemBase = vmemBase;
|
||||
newHeap->mVmemCapacity = JKR_HEAP_VIRTUAL_RESERVE;
|
||||
newHeap->mVmemCommitted = commitSize;
|
||||
return newHeap;
|
||||
#else
|
||||
u8* mem = (u8*)JKRAllocFromHeap(heap, alignedSize, 0x10);
|
||||
void* dataPtr = mem + solidHeapSize;
|
||||
if (!mem)
|
||||
if (!mem) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return JKR_NEW_ARGS (mem) JKRSolidHeap(dataPtr, alignedSize - solidHeapSize, heap, useErrorHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
void JKRSolidHeap::do_destroy(void) {
|
||||
#if TARGET_PC
|
||||
if (mVmemBase) {
|
||||
void* vmemBase = mVmemBase;
|
||||
size_t vmemCapacity = mVmemCapacity;
|
||||
this->~JKRSolidHeap();
|
||||
dusk::vmem_arena_free(vmemBase, vmemCapacity);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
JKRHeap* parent = getParent();
|
||||
if (parent) {
|
||||
this->~JKRSolidHeap();
|
||||
@@ -44,6 +87,11 @@ JKRSolidHeap::JKRSolidHeap(void* start, u32 size, JKRHeap* parent, bool useError
|
||||
mSolidHead = (u8*)mStart;
|
||||
mSolidTail = (u8*)mEnd;
|
||||
field_0x78 = NULL;
|
||||
#if TARGET_PC
|
||||
mVmemBase = nullptr;
|
||||
mVmemCapacity = 0;
|
||||
mVmemCommitted = 0;
|
||||
#endif
|
||||
#if DEBUG
|
||||
if (mDebugFill) {
|
||||
JKRFillMemory(mStart, mSize, JKRValue_DEBUGFILL_NOTUSE);
|
||||
@@ -59,6 +107,15 @@ s32 JKRSolidHeap::adjustSize(void) {
|
||||
int r25 = 0;
|
||||
JKRHeap* parent = getParent();
|
||||
if (parent) {
|
||||
#if TARGET_PC
|
||||
if (mVmemBase) {
|
||||
// VM-backed heap, can't resize in parent, but this is not a failure
|
||||
// Return what the trimmed size would have been so the caller doesn't log an error
|
||||
u32 thisSize = (uintptr_t)mStart - (uintptr_t)this;
|
||||
u32 newSize = ALIGN_NEXT(mSolidHead - mStart, 0x20);
|
||||
return (s32)(thisSize + newSize);
|
||||
}
|
||||
#endif
|
||||
lock();
|
||||
u32 thisSize = (uintptr_t)mStart - (uintptr_t)this;
|
||||
u32 newSize = ALIGN_NEXT(mSolidHead - mStart, 0x20);
|
||||
@@ -110,6 +167,11 @@ void* JKRSolidHeap::allocFromHead(u32 size, int alignment) {
|
||||
void* ptr = NULL;
|
||||
uintptr_t alignedStart = (alignment - 1 + (uintptr_t)mSolidHead) & ~(alignment - 1);
|
||||
u32 totalSize = size + (alignedStart - (uintptr_t)mSolidHead);
|
||||
#if TARGET_PC
|
||||
if (totalSize > mFreeSize && mVmemBase) {
|
||||
growHeap(totalSize);
|
||||
}
|
||||
#endif
|
||||
if (totalSize <= mFreeSize) {
|
||||
#if DEBUG
|
||||
if (mCheckMemoryFilled) {
|
||||
@@ -137,6 +199,15 @@ void* JKRSolidHeap::allocFromTail(u32 size, int alignment) {
|
||||
void* ptr = NULL;
|
||||
uintptr_t alignedStart = ALIGN_PREV((uintptr_t)mSolidTail - size, alignment);
|
||||
u32 totalSize = (uintptr_t)mSolidTail - (uintptr_t)alignedStart;
|
||||
#if TARGET_PC
|
||||
if (totalSize > mFreeSize && mVmemBase) {
|
||||
if (growHeap(totalSize)) {
|
||||
// mSolidTail moved to new mEnd; recompute from the new tail position
|
||||
alignedStart = ALIGN_PREV((uintptr_t)mSolidTail - size, alignment);
|
||||
totalSize = (uintptr_t)mSolidTail - (uintptr_t)alignedStart;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (totalSize <= mFreeSize) {
|
||||
ptr = (void*)alignedStart;
|
||||
mSolidTail -= totalSize;
|
||||
@@ -158,6 +229,47 @@ void* JKRSolidHeap::allocFromTail(u32 size, int alignment) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
bool JKRSolidHeap::growHeap(u32 needed) {
|
||||
// Growth is only safe when no tail allocations exist yet
|
||||
if (mSolidTail != mEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t pageSize = dusk::vmem_page_size();
|
||||
size_t wantBytes = (size_t)needed;
|
||||
size_t growAmount = std::max(wantBytes, JKR_HEAP_GROW_CHUNK);
|
||||
growAmount = ALIGN_NEXT(growAmount, pageSize);
|
||||
|
||||
size_t remaining = mVmemCapacity - mVmemCommitted;
|
||||
if (growAmount > remaining) {
|
||||
growAmount = ALIGN_PREV(remaining, pageSize);
|
||||
if (growAmount < wantBytes) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void* commitBase = (u8*)mVmemBase + mVmemCommitted;
|
||||
if (!dusk::vmem_commit(commitBase, growAmount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extend the heap end and the tail pointer
|
||||
mEnd = (u8*)mEnd + growAmount;
|
||||
mSolidTail = mEnd;
|
||||
mFreeSize += (u32)growAmount;
|
||||
mSize += (u32)growAmount;
|
||||
mVmemCommitted += growAmount;
|
||||
|
||||
DuskLog.debug("[JKRSolidHeap] '{}' grew by {} MB (committed: {} MB / reserved: {} MB)\n",
|
||||
getName(),
|
||||
growAmount / (1024 * 1024),
|
||||
mVmemCommitted / (1024 * 1024),
|
||||
mVmemCapacity / (1024 * 1024));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void JKRSolidHeap::do_free(void* ptr) {
|
||||
JUTWarningConsole_f("free: cannot free memory block (%08x)\n", ptr);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
#include <mtx.h>
|
||||
#include <gx.h>
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
#include "tracy/Tracy.hpp"
|
||||
|
||||
void JPASetPointSize(JPAEmitterWorkData* work) {
|
||||
@@ -421,95 +418,50 @@ static projectionFunc p_prj[3] = {
|
||||
loadPrjAnm,
|
||||
};
|
||||
|
||||
#if TARGET_PC
|
||||
void JPAInterpBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||
Mtx ptclPosMtx;
|
||||
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
|
||||
dusk::frame_interp::record_final_mtx(ptclPosMtx, ptcl);
|
||||
}
|
||||
|
||||
void JPAInterpRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||
Mtx ptclPosMtx;
|
||||
f32 sinRot = JMASSin(ptcl->mRotateAngle);
|
||||
f32 cosRot = JMASCos(ptcl->mRotateAngle);
|
||||
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
|
||||
ptclPosMtx[0][0] = cosRot;
|
||||
ptclPosMtx[0][1] = -sinRot;
|
||||
ptclPosMtx[1][0] = sinRot;
|
||||
ptclPosMtx[1][1] = cosRot;
|
||||
dusk::frame_interp::record_final_mtx(ptclPosMtx, ptcl);
|
||||
}
|
||||
#endif
|
||||
|
||||
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||
void JPADrawBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
|
||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
JGeometry::TVec3<f32> pos;
|
||||
#if TARGET_PC
|
||||
Mtx ptclPosMtx;
|
||||
if (dusk::frame_interp::lookup_replacement(ptcl, ptclPosMtx)) {
|
||||
pos.set(ptclPosMtx[0][3], ptclPosMtx[1][3], ptclPosMtx[2][3]);
|
||||
MTXMultVec(work->mPosCamMtx, &pos, &pos);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
MTXMultVec(work->mPosCamMtx, &ptcl->mPosition, &pos);
|
||||
}
|
||||
Mtx posMtx;
|
||||
posMtx[0][0] = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
|
||||
posMtx[0][3] = pos.x;
|
||||
posMtx[1][1] = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
|
||||
posMtx[1][3] = pos.y;
|
||||
posMtx[2][2] = 1.0f;
|
||||
posMtx[2][3] = pos.z;
|
||||
posMtx[0][1] = posMtx[0][2] = posMtx[1][0] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
|
||||
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
||||
p_prj[work->mPrjType](work, posMtx);
|
||||
JGeometry::TVec3<f32> local_48;
|
||||
MTXMultVec(work->mPosCamMtx, ¶m_1->mPosition, &local_48);
|
||||
Mtx local_38;
|
||||
local_38[0][0] = work->mGlobalPtclScl.x * param_1->mParticleScaleX;
|
||||
local_38[0][3] = local_48.x;
|
||||
local_38[1][1] = work->mGlobalPtclScl.y * param_1->mParticleScaleY;
|
||||
local_38[1][3] = local_48.y;
|
||||
local_38[2][2] = 1.0f;
|
||||
local_38[2][3] = local_48.z;
|
||||
local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[1][2] = local_38[2][0] = local_38[2][1] = 0.0f;
|
||||
GXLoadPosMtxImm(local_38, 0);
|
||||
p_prj[work->mPrjType](work, local_38);
|
||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||
}
|
||||
|
||||
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||
void JPADrawRotBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
|
||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (work->mpRes->getUsrIdx() == 0x89d7) {
|
||||
int a = 0;
|
||||
}
|
||||
JGeometry::TVec3<f32> local_48;
|
||||
MTXMultVec(work->mPosCamMtx, ¶m_1->mPosition, &local_48);
|
||||
f32 sinRot = JMASSin(param_1->mRotateAngle);
|
||||
f32 cosRot = JMASCos(param_1->mRotateAngle);
|
||||
f32 particleX = work->mGlobalPtclScl.x * param_1->mParticleScaleX;
|
||||
f32 particleY = work->mGlobalPtclScl.y * param_1->mParticleScaleY;
|
||||
|
||||
JGeometry::TVec3<f32> pos;
|
||||
f32 sinRot, cosRot;
|
||||
#if TARGET_PC
|
||||
Mtx ptclPosMtx;
|
||||
MTXTrans(ptclPosMtx, ptcl->mPosition.x, ptcl->mPosition.y, ptcl->mPosition.z);
|
||||
if (dusk::frame_interp::lookup_replacement(ptcl, ptclPosMtx)) {
|
||||
pos.set(ptclPosMtx[0][3], ptclPosMtx[1][3], ptclPosMtx[2][3]);
|
||||
sinRot = ptclPosMtx[1][0];
|
||||
cosRot = ptclPosMtx[0][0];
|
||||
MTXMultVec(work->mPosCamMtx, &pos, &pos);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
MTXMultVec(work->mPosCamMtx, &ptcl->mPosition, &pos);
|
||||
sinRot = JMASSin(ptcl->mRotateAngle);
|
||||
cosRot = JMASCos(ptcl->mRotateAngle);
|
||||
}
|
||||
f32 particleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
|
||||
f32 particleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
|
||||
Mtx posMtx;
|
||||
posMtx[0][0] = cosRot * particleX;
|
||||
posMtx[0][1] = -sinRot * particleY;
|
||||
posMtx[0][3] = pos.x;
|
||||
posMtx[1][0] = sinRot * particleX;
|
||||
posMtx[1][1] = cosRot * particleY;
|
||||
posMtx[1][3] = pos.y;
|
||||
posMtx[2][2] = 1.0f;
|
||||
posMtx[2][3] = pos.z;
|
||||
posMtx[0][2] = posMtx[1][2] = posMtx[2][0] = posMtx[2][1] = 0.0f;
|
||||
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
||||
p_prj[work->mPrjType](work, posMtx);
|
||||
Mtx local_38;
|
||||
local_38[0][0] = cosRot * particleX;
|
||||
local_38[0][1] = -sinRot * particleY;
|
||||
local_38[0][3] = local_48.x;
|
||||
local_38[1][0] = sinRot * particleX;
|
||||
local_38[1][1] = cosRot * particleY;
|
||||
local_38[1][3] = local_48.y;
|
||||
local_38[2][2] = 1.0f;
|
||||
local_38[2][3] = local_48.z;
|
||||
local_38[0][2] = local_38[1][2] = local_38[2][0] = local_38[2][1] = 0.0f;
|
||||
GXLoadPosMtxImm(local_38, 0);
|
||||
p_prj[work->mPrjType](work, local_38);
|
||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||
}
|
||||
|
||||
@@ -532,7 +484,7 @@ void JPADrawYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
|
||||
local_38[2][2] = work->mYBBCamMtx[2][2];
|
||||
local_38[2][3] = local_48.z;
|
||||
local_38[0][1] = local_38[0][2] = local_38[1][0] = local_38[2][0] = 0.0f;
|
||||
GXLoadPosMtxImm(local_38, GX_PNMTX0);
|
||||
GXLoadPosMtxImm(local_38, 0);
|
||||
p_prj[work->mPrjType](work, local_38);
|
||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||
}
|
||||
@@ -565,7 +517,7 @@ void JPADrawRotYBillboard(JPAEmitterWorkData* work, JPABaseParticle* param_1) {
|
||||
local_38[2][1] = local_94 * fVar1;
|
||||
local_38[2][2] = local_90;
|
||||
local_38[2][3] = local_48.z;
|
||||
GXLoadPosMtxImm(local_38, GX_PNMTX0);
|
||||
GXLoadPosMtxImm(local_38, 0);
|
||||
p_prj[work->mPrjType](work, local_38);
|
||||
GXCallDisplayList(jpa_dl, sizeof(jpa_dl));
|
||||
}
|
||||
@@ -729,197 +681,103 @@ static u8* p_dl[2] = {
|
||||
jpa_dl_x,
|
||||
};
|
||||
|
||||
#if TARGET_PC
|
||||
void JPAInterpDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||
JGeometry::TVec3<f32> axisY;
|
||||
JGeometry::TVec3<f32> axisZ;
|
||||
p_direction[work->mDirType](work, ptcl, &axisY);
|
||||
|
||||
if (axisY.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
axisY.normalize();
|
||||
axisZ.cross(ptcl->mBaseAxis, axisY);
|
||||
|
||||
if (axisZ.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
axisZ.normalize();
|
||||
ptcl->mBaseAxis.cross(axisY, axisZ);
|
||||
ptcl->mBaseAxis.normalize();
|
||||
Mtx posMtx;
|
||||
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
|
||||
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
|
||||
posMtx[0][0] = ptcl->mBaseAxis.x;
|
||||
posMtx[0][1] = axisY.x;
|
||||
posMtx[0][2] = axisZ.x;
|
||||
posMtx[0][3] = ptcl->mPosition.x;
|
||||
posMtx[1][0] = ptcl->mBaseAxis.y;
|
||||
posMtx[1][1] = axisY.y;
|
||||
posMtx[1][2] = axisZ.y;
|
||||
posMtx[1][3] = ptcl->mPosition.y;
|
||||
posMtx[2][0] = ptcl->mBaseAxis.z;
|
||||
posMtx[2][1] = axisY.z;
|
||||
posMtx[2][2] = axisZ.z;
|
||||
posMtx[2][3] = ptcl->mPosition.z;
|
||||
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
|
||||
dusk::frame_interp::record_final_mtx(posMtx, ptcl);
|
||||
}
|
||||
|
||||
void JPAInterpRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||
f32 sinRot = JMASSin(ptcl->mRotateAngle);
|
||||
f32 cosRot = JMASCos(ptcl->mRotateAngle);
|
||||
JGeometry::TVec3<f32> axisY;
|
||||
JGeometry::TVec3<f32> axisZ;
|
||||
p_direction[work->mDirType](work, ptcl, &axisY);
|
||||
|
||||
if (axisY.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
axisY.normalize();
|
||||
axisZ.cross(ptcl->mBaseAxis, axisY);
|
||||
|
||||
if (axisZ.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
axisZ.normalize();
|
||||
ptcl->mBaseAxis.cross(axisY, axisZ);
|
||||
ptcl->mBaseAxis.normalize();
|
||||
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
|
||||
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
|
||||
Mtx mtx1;
|
||||
Mtx mtx2;
|
||||
p_rot[work->mRotType](sinRot, cosRot, mtx1);
|
||||
p_plane[work->mPlaneType](mtx1, scaleX, scaleY);
|
||||
mtx2[0][0] = ptcl->mBaseAxis.x;
|
||||
mtx2[0][1] = axisY.x;
|
||||
mtx2[0][2] = axisZ.x;
|
||||
mtx2[0][3] = ptcl->mPosition.x;
|
||||
mtx2[1][0] = ptcl->mBaseAxis.y;
|
||||
mtx2[1][1] = axisY.y;
|
||||
mtx2[1][2] = axisZ.y;
|
||||
mtx2[1][3] = ptcl->mPosition.y;
|
||||
mtx2[2][0] = ptcl->mBaseAxis.z;
|
||||
mtx2[2][1] = axisY.z;
|
||||
mtx2[2][2] = axisZ.z;
|
||||
mtx2[2][3] = ptcl->mPosition.z;
|
||||
MTXConcat(mtx2, mtx1, mtx1);
|
||||
dusk::frame_interp::record_final_mtx(mtx1, ptcl);
|
||||
}
|
||||
#endif
|
||||
|
||||
void JPADrawDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||
void JPADrawDirection(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
|
||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZoneScoped;
|
||||
|
||||
Mtx posMtx;
|
||||
#if TARGET_PC
|
||||
if (!dusk::frame_interp::lookup_replacement(ptcl, posMtx))
|
||||
#endif
|
||||
{
|
||||
JGeometry::TVec3<f32> axisY;
|
||||
JGeometry::TVec3<f32> axisZ;
|
||||
p_direction[work->mDirType](work, ptcl, &axisY);
|
||||
JGeometry::TVec3<f32> local_6c;
|
||||
JGeometry::TVec3<f32> local_78;
|
||||
p_direction[param_0->mDirType](param_0, param_1, &local_6c);
|
||||
|
||||
if (axisY.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
axisY.normalize();
|
||||
axisZ.cross(ptcl->mBaseAxis, axisY);
|
||||
|
||||
if (axisZ.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
axisZ.normalize();
|
||||
ptcl->mBaseAxis.cross(axisY, axisZ);
|
||||
ptcl->mBaseAxis.normalize();
|
||||
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
|
||||
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
|
||||
posMtx[0][0] = ptcl->mBaseAxis.x;
|
||||
posMtx[0][1] = axisY.x;
|
||||
posMtx[0][2] = axisZ.x;
|
||||
posMtx[0][3] = ptcl->mPosition.x;
|
||||
posMtx[1][0] = ptcl->mBaseAxis.y;
|
||||
posMtx[1][1] = axisY.y;
|
||||
posMtx[1][2] = axisZ.y;
|
||||
posMtx[1][3] = ptcl->mPosition.y;
|
||||
posMtx[2][0] = ptcl->mBaseAxis.z;
|
||||
posMtx[2][1] = axisY.z;
|
||||
posMtx[2][2] = axisZ.z;
|
||||
posMtx[2][3] = ptcl->mPosition.z;
|
||||
p_plane[work->mPlaneType](posMtx, scaleX, scaleY);
|
||||
if (local_6c.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MTXConcat(work->mPosCamMtx, posMtx, posMtx);
|
||||
GXLoadPosMtxImm(posMtx, GX_PNMTX0);
|
||||
p_prj[work->mPrjType](work, posMtx);
|
||||
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
|
||||
local_6c.normalize();
|
||||
local_78.cross(param_1->mBaseAxis, local_6c);
|
||||
|
||||
if (local_78.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
local_78.normalize();
|
||||
param_1->mBaseAxis.cross(local_6c, local_78);
|
||||
param_1->mBaseAxis.normalize();
|
||||
Mtx local_60;
|
||||
f32 fVar1 = param_0->mGlobalPtclScl.x * param_1->mParticleScaleX;
|
||||
f32 fVar2 = param_0->mGlobalPtclScl.y * param_1->mParticleScaleY;
|
||||
local_60[0][0] = param_1->mBaseAxis.x;
|
||||
local_60[0][1] = local_6c.x;
|
||||
local_60[0][2] = local_78.x;
|
||||
local_60[0][3] = param_1->mPosition.x;
|
||||
local_60[1][0] = param_1->mBaseAxis.y;
|
||||
local_60[1][1] = local_6c.y;
|
||||
local_60[1][2] = local_78.y;
|
||||
local_60[1][3] = param_1->mPosition.y;
|
||||
local_60[2][0] = param_1->mBaseAxis.z;
|
||||
local_60[2][1] = local_6c.z;
|
||||
local_60[2][2] = local_78.z;
|
||||
local_60[2][3] = param_1->mPosition.z;
|
||||
p_plane[param_0->mPlaneType](local_60, fVar1, fVar2);
|
||||
MTXConcat(param_0->mPosCamMtx, local_60, local_60);
|
||||
GXLoadPosMtxImm(local_60, 0);
|
||||
p_prj[param_0->mPrjType](param_0, local_60);
|
||||
GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl));
|
||||
}
|
||||
|
||||
void JPADrawRotDirection(JPAEmitterWorkData* work, JPABaseParticle* ptcl) {
|
||||
if (ptcl->checkStatus(JPAPtclStts_Invisible)) {
|
||||
void JPADrawRotDirection(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
|
||||
if (param_1->checkStatus(JPAPtclStts_Invisible)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZoneScoped;
|
||||
|
||||
Mtx mtx1;
|
||||
Mtx mtx2;
|
||||
#if TARGET_PC
|
||||
if (!dusk::frame_interp::lookup_replacement(ptcl, mtx1))
|
||||
#endif
|
||||
{
|
||||
f32 sinRot = JMASSin(ptcl->mRotateAngle);
|
||||
f32 cosRot = JMASCos(ptcl->mRotateAngle);
|
||||
JGeometry::TVec3<f32> axisY;
|
||||
JGeometry::TVec3<f32> axisZ;
|
||||
p_direction[work->mDirType](work, ptcl, &axisY);
|
||||
f32 sinRot = JMASSin(param_1->mRotateAngle);
|
||||
f32 cosRot = JMASCos(param_1->mRotateAngle);
|
||||
JGeometry::TVec3<f32> local_6c;
|
||||
JGeometry::TVec3<f32> local_78;
|
||||
p_direction[param_0->mDirType](param_0, param_1, &local_6c);
|
||||
|
||||
if (axisY.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
axisY.normalize();
|
||||
axisZ.cross(ptcl->mBaseAxis, axisY);
|
||||
|
||||
if (axisZ.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
axisZ.normalize();
|
||||
ptcl->mBaseAxis.cross(axisY, axisZ);
|
||||
ptcl->mBaseAxis.normalize();
|
||||
f32 scaleX = work->mGlobalPtclScl.x * ptcl->mParticleScaleX;
|
||||
f32 scaleY = work->mGlobalPtclScl.y * ptcl->mParticleScaleY;
|
||||
p_rot[work->mRotType](sinRot, cosRot, mtx1);
|
||||
p_plane[work->mPlaneType](mtx1, scaleX, scaleY);
|
||||
mtx2[0][0] = ptcl->mBaseAxis.x;
|
||||
mtx2[0][1] = axisY.x;
|
||||
mtx2[0][2] = axisZ.x;
|
||||
mtx2[0][3] = ptcl->mPosition.x;
|
||||
mtx2[1][0] = ptcl->mBaseAxis.y;
|
||||
mtx2[1][1] = axisY.y;
|
||||
mtx2[1][2] = axisZ.y;
|
||||
mtx2[1][3] = ptcl->mPosition.y;
|
||||
mtx2[2][0] = ptcl->mBaseAxis.z;
|
||||
mtx2[2][1] = axisY.z;
|
||||
mtx2[2][2] = axisZ.z;
|
||||
mtx2[2][3] = ptcl->mPosition.z;
|
||||
MTXConcat(mtx2, mtx1, mtx1);
|
||||
if (local_6c.isZero()) {
|
||||
return;
|
||||
}
|
||||
MTXConcat(work->mPosCamMtx, mtx1, mtx2);
|
||||
GXLoadPosMtxImm(mtx2, GX_PNMTX0);
|
||||
p_prj[work->mPrjType](work, mtx2);
|
||||
GXCallDisplayList(p_dl[work->mDLType], sizeof(jpa_dl));
|
||||
|
||||
local_6c.normalize();
|
||||
local_78.cross(param_1->mBaseAxis, local_6c);
|
||||
|
||||
if (local_78.isZero()) {
|
||||
return;
|
||||
}
|
||||
|
||||
local_78.normalize();
|
||||
param_1->mBaseAxis.cross(local_6c, local_78);
|
||||
param_1->mBaseAxis.normalize();
|
||||
f32 particleX = param_0->mGlobalPtclScl.x * param_1->mParticleScaleX;
|
||||
f32 particleY = param_0->mGlobalPtclScl.y * param_1->mParticleScaleY;
|
||||
Mtx auStack_80;
|
||||
Mtx local_60;
|
||||
p_rot[param_0->mRotType](sinRot, cosRot, auStack_80);
|
||||
p_plane[param_0->mPlaneType](auStack_80, particleX, particleY);
|
||||
local_60[0][0] = param_1->mBaseAxis.x;
|
||||
local_60[0][1] = local_6c.x;
|
||||
local_60[0][2] = local_78.x;
|
||||
local_60[0][3] = param_1->mPosition.x;
|
||||
local_60[1][0] = param_1->mBaseAxis.y;
|
||||
local_60[1][1] = local_6c.y;
|
||||
local_60[1][2] = local_78.y;
|
||||
local_60[1][3] = param_1->mPosition.y;
|
||||
local_60[2][0] = param_1->mBaseAxis.z;
|
||||
local_60[2][1] = local_6c.z;
|
||||
local_60[2][2] = local_78.z;
|
||||
local_60[2][3] = param_1->mPosition.z;
|
||||
MTXConcat(local_60, auStack_80, auStack_80);
|
||||
MTXConcat(param_0->mPosCamMtx, auStack_80, local_60);
|
||||
GXLoadPosMtxImm(local_60, 0);
|
||||
p_prj[param_0->mPrjType](param_0, local_60);
|
||||
GXCallDisplayList(p_dl[param_0->mDLType], sizeof(jpa_dl));
|
||||
}
|
||||
|
||||
void JPADrawDBillboard(JPAEmitterWorkData* param_0, JPABaseParticle* param_1) {
|
||||
|
||||
@@ -204,28 +204,6 @@ void JPABaseParticle::init_c(JPAEmitterWorkData* work, JPABaseParticle* parent)
|
||||
mTexAnmIdx = 0;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void JPABaseParticle::interp(JPAEmitterWorkData* work, void const* drawFunc) {
|
||||
static bool enable = false;
|
||||
if (!enable)
|
||||
return;
|
||||
|
||||
// don't interpolate the first frame
|
||||
if (mAge == 0)
|
||||
return;
|
||||
|
||||
if (drawFunc == JPADrawBillboard) {
|
||||
JPAInterpBillboard(work, this);
|
||||
} else if (drawFunc == JPADrawRotBillboard) {
|
||||
JPAInterpRotBillboard(work, this);
|
||||
} else if (drawFunc == JPADrawDirection) {
|
||||
JPAInterpDirection(work, this);
|
||||
} else if (drawFunc == JPADrawRotDirection) {
|
||||
JPAInterpRotDirection(work, this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool JPABaseParticle::calc_p(JPAEmitterWorkData* work) {
|
||||
if (++mAge >= mLifeTime) {
|
||||
return true;
|
||||
@@ -269,17 +247,6 @@ bool JPABaseParticle::calc_p(JPAEmitterWorkData* work) {
|
||||
mOffsetPosition.y + mLocalPosition.y * work->mPublicScale.y,
|
||||
mOffsetPosition.z + mLocalPosition.z * work->mPublicScale.z);
|
||||
|
||||
#if TARGET_PC
|
||||
JPABaseShape* pBsp = work->mpRes->getBsp();
|
||||
work->mGlobalPtclScl.x = work->mpEmtr->mGlobalPScl.x * pBsp->getBaseSizeX();
|
||||
work->mGlobalPtclScl.y = work->mpEmtr->mGlobalPScl.y * pBsp->getBaseSizeY();
|
||||
work->mDirType = pBsp->getDirType();
|
||||
work->mRotType = pBsp->getRotType();
|
||||
work->mDLType = pBsp->getType() == 4 || pBsp->getType() == 8;
|
||||
work->mPlaneType = work->mDLType ? 2 : pBsp->getBasePlaneType();
|
||||
interp(work, (void const*)work->mpRes->mpDrawParticleFuncList[0]);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -322,23 +289,6 @@ bool JPABaseParticle::calc_c(JPAEmitterWorkData* work) {
|
||||
mOffsetPosition.y + mLocalPosition.y * work->mPublicScale.y,
|
||||
mOffsetPosition.z + mLocalPosition.z * work->mPublicScale.z);
|
||||
|
||||
#if TARGET_PC
|
||||
JPABaseShape* pBsp = work->mpRes->getBsp();
|
||||
JPAChildShape* pCsp = work->mpRes->getCsp();
|
||||
if (pCsp->isScaleInherited()) {
|
||||
work->mGlobalPtclScl.x = work->mpEmtr->mGlobalPScl.x * pBsp->getBaseSizeX();
|
||||
work->mGlobalPtclScl.y = work->mpEmtr->mGlobalPScl.y * pBsp->getBaseSizeY();
|
||||
} else {
|
||||
work->mGlobalPtclScl.x = work->mpEmtr->mGlobalPScl.x * pCsp->getScaleX();
|
||||
work->mGlobalPtclScl.y = work->mpEmtr->mGlobalPScl.y * pCsp->getScaleY();
|
||||
}
|
||||
work->mDirType = pCsp->getDirType();
|
||||
work->mRotType = pCsp->getRotType();
|
||||
work->mDLType = pCsp->getType() == 4 || pCsp->getType() == 8;
|
||||
work->mPlaneType = work->mDLType ? 2 : pCsp->getBasePlaneType();
|
||||
interp(work, (void const*)work->mpRes->mpDrawParticleChildFuncList[0]);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,3 @@ bool JUTPalette::load() {
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void JUTPalette::dataUploaded() {
|
||||
GXInitTlutObjData(&mTlutObj, (void*)mColorTable);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@ void JUTTexture::storeTIMG(ResTIMG const* param_0, u8 param_1) {
|
||||
mTexData = (void*)((intptr_t)mTexInfo + 0x20);
|
||||
}
|
||||
|
||||
mPalette = NULL;
|
||||
field_0x2c = NULL;
|
||||
mTlutName = 0;
|
||||
mWrapS = mTexInfo->wrapS;
|
||||
mWrapT = mTexInfo->wrapT;
|
||||
@@ -95,7 +95,7 @@ void JUTTexture::storeTIMG(ResTIMG const* param_0, JUTPalette* param_1, GXTlut p
|
||||
}
|
||||
mEmbPalette = param_1;
|
||||
setEmbPaletteDelFlag(false);
|
||||
mPalette = NULL;
|
||||
field_0x2c = NULL;
|
||||
if (param_1 != NULL) {
|
||||
mTlutName = param_2;
|
||||
if (param_2 != param_1->getTlutName()) {
|
||||
@@ -120,11 +120,11 @@ void JUTTexture::storeTIMG(ResTIMG const* param_0, JUTPalette* param_1, GXTlut p
|
||||
void JUTTexture::attachPalette(JUTPalette* param_0) {
|
||||
if (mTexInfo->indexTexture) {
|
||||
if (param_0 == NULL && mEmbPalette != NULL) {
|
||||
mPalette = mEmbPalette;
|
||||
field_0x2c = mEmbPalette;
|
||||
} else {
|
||||
mPalette = param_0;
|
||||
field_0x2c = param_0;
|
||||
}
|
||||
initTexObj(mPalette->getTlutName());
|
||||
initTexObj(field_0x2c->getTlutName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,9 +133,9 @@ void JUTTexture::init() {
|
||||
initTexObj();
|
||||
} else {
|
||||
if (mEmbPalette != NULL) {
|
||||
mPalette = mEmbPalette;
|
||||
field_0x2c = mEmbPalette;
|
||||
|
||||
initTexObj(mPalette->getTlutName());
|
||||
initTexObj(field_0x2c->getTlutName());
|
||||
} else {
|
||||
OS_REPORT("This texture is CI-Format, but EmbPalette is NULL.\n");
|
||||
}
|
||||
@@ -179,8 +179,8 @@ void JUTTexture::initTexObj(GXTlut param_0) {
|
||||
}
|
||||
|
||||
void JUTTexture::load(GXTexMapID param_0) {
|
||||
if (mPalette) {
|
||||
mPalette->load();
|
||||
if (field_0x2c) {
|
||||
field_0x2c->load();
|
||||
}
|
||||
GXLoadTexObj(&mTexObj, param_0);
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 457 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 188 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB |
@@ -1,147 +0,0 @@
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: visible;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-size: 24dp;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.overlay-root {
|
||||
width: 100%;
|
||||
min-height: 45%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: stretch;
|
||||
decorator: vertical-gradient(#00000000 #151610F2);
|
||||
padding: 48dp 0 40dp 0;
|
||||
filter: opacity(0);
|
||||
transition: filter 0.2s linear-in-out;
|
||||
}
|
||||
|
||||
.overlay-root[open] {
|
||||
filter: opacity(1);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
width: 100%;
|
||||
max-width: 1216dp;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24dp;
|
||||
padding: 0 32dp;
|
||||
}
|
||||
|
||||
@media (max-height: 800dp) {
|
||||
.overlay-root {
|
||||
min-height: 38%;
|
||||
padding: 32dp 0 28dp 0;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
gap: 16dp;
|
||||
padding: 0 24dp;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 24dp;
|
||||
}
|
||||
|
||||
.carousel-container {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 18dp;
|
||||
line-height: 22dp;
|
||||
color: rgba(255, 255, 255, 50%);
|
||||
}
|
||||
|
||||
.divider {
|
||||
margin: 1dp 0;
|
||||
border-top: 1dp rgba(217, 217, 217, 50%);
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 24dp;
|
||||
}
|
||||
|
||||
footer-button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 220dp;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-weight: bold;
|
||||
font-size: 20dp;
|
||||
line-height: 24dp;
|
||||
text-transform: uppercase;
|
||||
color: #FFFFFF;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
footer-button.return {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
footer-button.reset {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.stepped-carousel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16dp;
|
||||
width: auto;
|
||||
min-width: 246dp;
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.stepped-carousel-value {
|
||||
line-height: 29dp;
|
||||
min-width: 166dp;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.stepped-carousel-arrow {
|
||||
width: 24dp;
|
||||
height: 24dp;
|
||||
min-width: 24dp;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: visible;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-weight: bold;
|
||||
font-size: 18dp;
|
||||
color: #E0DBC8;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
focus: auto;
|
||||
}
|
||||
|
||||
popup {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
height: 64dp;
|
||||
background-color: rgba(21, 22, 16, 80%);
|
||||
border-bottom: 2dp #92875B;
|
||||
backdrop-filter: blur(5dp);
|
||||
transform: translateY(-64dp);
|
||||
transition: transform 0.2s cubic-in-out;
|
||||
}
|
||||
|
||||
popup[open] {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
popup tab-bar {
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
popup tab-bar tab {
|
||||
opacity: 0.35;
|
||||
color: #E0DBC8;
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: "Fira Sans";
|
||||
font-weight: normal;
|
||||
font-size: 20dp;
|
||||
color: #FFFFFF;
|
||||
background-color: #000000;
|
||||
decorator: image(../prelaunch-bg.png cover left center);
|
||||
filter: opacity(0);
|
||||
transition: filter 1s 0.1s linear-in-out;
|
||||
}
|
||||
|
||||
body[open] {
|
||||
filter: opacity(1);
|
||||
}
|
||||
|
||||
content {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: opacity(0);
|
||||
transition: filter 0.2s linear-in-out;
|
||||
}
|
||||
|
||||
content[open] {
|
||||
filter: opacity(1);
|
||||
}
|
||||
|
||||
menu {
|
||||
position: absolute;
|
||||
left: 96dp;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
/* Scale based on a reference screen width, 428/1216 */
|
||||
width: 35.230264vw;
|
||||
min-width: 428dp;
|
||||
max-width: 856dp;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 48dp;
|
||||
}
|
||||
|
||||
hero {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 8dp;
|
||||
}
|
||||
|
||||
hero img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
font-family: "Alegreya SC";
|
||||
font-size: 32dp;
|
||||
}
|
||||
|
||||
@media (min-width: 1216dp) {
|
||||
.eyebrow {
|
||||
/* Same logic as .menu, 32/1216 */
|
||||
font-size: 2.631579vw;
|
||||
}
|
||||
}
|
||||
|
||||
.eyebrow span {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#menu-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12dp;
|
||||
}
|
||||
|
||||
#menu-list button {
|
||||
width: 428dp;
|
||||
height: 54dp;
|
||||
padding: 8dp 16dp;
|
||||
border-radius: 8dp;
|
||||
text-transform: uppercase;
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-size: 32dp;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
/* Define a fully transparent gradient as the default state, otherwise a white flash occurs */
|
||||
decorator: horizontal-gradient(#00000000 #00000000);
|
||||
}
|
||||
|
||||
#menu-list button.anim-done {
|
||||
transition: decorator color 0.1s linear-in-out;
|
||||
}
|
||||
|
||||
#menu-list button:hover,
|
||||
#menu-list button:focus-visible {
|
||||
color: black;
|
||||
decorator: horizontal-gradient(#FEE685FF #FEE68500);
|
||||
}
|
||||
|
||||
disk-status {
|
||||
position: absolute;
|
||||
left: 96dp;
|
||||
bottom: 72dp;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8dp;
|
||||
}
|
||||
|
||||
version-info {
|
||||
position: absolute;
|
||||
right: 96dp;
|
||||
bottom: 72dp;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8dp;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.status,
|
||||
.version {
|
||||
font-size: 24dp;
|
||||
}
|
||||
|
||||
.status,
|
||||
.update {
|
||||
color: #D8F999;
|
||||
}
|
||||
|
||||
.status[bad] {
|
||||
color: #FFC9C9;
|
||||
}
|
||||
|
||||
/* TODO: Hidden until an actual update checker is introduced */
|
||||
.update {
|
||||
display: none;
|
||||
font-size: 16dp;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.detail,
|
||||
.update span {
|
||||
color: #A6A09B;
|
||||
}
|
||||
|
||||
/* Startup animation */
|
||||
.intro-item {
|
||||
opacity: 0;
|
||||
transform: translateY(10dp);
|
||||
transition: opacity transform 0.3s 0.1s cubic-in-out;
|
||||
}
|
||||
|
||||
body.animate-in .intro-item {
|
||||
opacity: 1;
|
||||
transform: translateY(0dp);
|
||||
}
|
||||
|
||||
.delay-0 {
|
||||
transition: opacity transform 0.3s 0.1s cubic-in-out;
|
||||
}
|
||||
|
||||
.delay-1 {
|
||||
transition: opacity transform 0.3s 0.2s cubic-in-out;
|
||||
}
|
||||
|
||||
.delay-2 {
|
||||
transition: opacity transform 0.3s 0.3s cubic-in-out;
|
||||
}
|
||||
|
||||
.delay-3 {
|
||||
transition: opacity transform 0.3s 0.4s cubic-in-out;
|
||||
}
|
||||
|
||||
.delay-4 {
|
||||
transition: opacity transform 0.3s 0.5s cubic-in-out;
|
||||
}
|
||||
|
||||
.delay-5 {
|
||||
transition: opacity transform 0.3s 0.6s cubic-in-out;
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
tab-bar {
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
overflow: auto hidden;
|
||||
clip: always;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
tab-bar scrollbarhorizontal,
|
||||
tab-bar scrollbarhorizontal sliderarrowdec,
|
||||
tab-bar scrollbarhorizontal sliderarrowinc,
|
||||
tab-bar scrollbarhorizontal slidertrack,
|
||||
tab-bar scrollbarhorizontal sliderbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
tab-bar tab {
|
||||
flex: 0 0 auto;
|
||||
padding: 0 24dp;
|
||||
line-height: 64dp;
|
||||
white-space: nowrap;
|
||||
decorator: vertical-gradient(#c2a42d00 #c2a42d00);
|
||||
transition: decorator 0.1s linear-in-out, opacity 0.1s linear-in-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
tab-bar tab:selected {
|
||||
opacity: 1;
|
||||
border-bottom: 4dp #C2A42D;
|
||||
font-effect: glow(0dp 4dp 0dp 4dp black);
|
||||
}
|
||||
|
||||
tab-bar tab:focus-visible,
|
||||
tab-bar tab:hover {
|
||||
opacity: 1;
|
||||
font-effect: glow(0dp 4dp 0dp 4dp black);
|
||||
decorator: vertical-gradient(#c2a42d00 #c2a42d26);
|
||||
}
|
||||
|
||||
tab-bar tab:active {
|
||||
decorator: vertical-gradient(#c2a42d10 #c2a42d40);
|
||||
}
|
||||
|
||||
tab-bar[closable] tab-end-spacer {
|
||||
display: block;
|
||||
flex: 0 0 64dp;
|
||||
width: 64dp;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
tab-bar[closable] close {
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 8dp;
|
||||
right: 8dp;
|
||||
z-index: 1;
|
||||
width: 48dp;
|
||||
height: 48dp;
|
||||
font-family: "Material Symbols Rounded";
|
||||
font-weight: normal;
|
||||
font-size: 24dp;
|
||||
line-height: 48dp;
|
||||
text-align: center;
|
||||
text-transform: none;
|
||||
color: rgba(224, 219, 200, 70%);
|
||||
backdrop-filter: blur(2dp);
|
||||
border-radius: 6dp;
|
||||
transition: color background-color 0.12s linear-in-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
tab-bar[closable] close:hover,
|
||||
tab-bar[closable] close:focus-visible {
|
||||
color: #fff;
|
||||
background-color: rgba(194, 164, 45, 24%);
|
||||
}
|
||||
|
||||
tab-bar[closable] close:active {
|
||||
color: #fff;
|
||||
background-color: rgba(194, 164, 45, 40%);
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 64dp;
|
||||
font-family: "Fira Sans";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 15dp;
|
||||
color: #E0DBC8;
|
||||
}
|
||||
|
||||
window {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
height: 100%;
|
||||
max-width: 1088dp;
|
||||
max-height: 768dp;
|
||||
margin: auto;
|
||||
border-radius: 14dp;
|
||||
overflow: hidden;
|
||||
border: 2dp #92875B;
|
||||
backdrop-filter: blur(5dp);
|
||||
box-shadow: 0 0 25dp 5dp;
|
||||
background-color: rgba(21, 22, 16, 90%);
|
||||
filter: opacity(0);
|
||||
transform: scale(0.9);
|
||||
transform-origin: center;
|
||||
transition: filter transform 0.2s cubic-in-out;
|
||||
}
|
||||
|
||||
window[open] {
|
||||
filter: opacity(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
@media (max-height: 640dp) {
|
||||
body {
|
||||
padding: 16dp;
|
||||
}
|
||||
window {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
window tab-bar {
|
||||
flex: 0 0 64dp;
|
||||
height: 64dp;
|
||||
background-color: rgba(217, 217, 217, 10%);
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-weight: bold;
|
||||
font-size: 18dp;
|
||||
border-bottom: 2dp #92875B;
|
||||
}
|
||||
|
||||
window tab-bar tab {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
window content {
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
window content pane {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
flex: 1 1 0;
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
padding: 24dp;
|
||||
padding-bottom: 0dp;
|
||||
gap: 8dp;
|
||||
overflow: hidden auto;
|
||||
font-size: 20dp;
|
||||
}
|
||||
|
||||
window content pane:not(:last-of-type) {
|
||||
border-right: 1dp #92875B;
|
||||
}
|
||||
|
||||
window content pane > * {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
window content pane > spacer {
|
||||
display: block;
|
||||
/* Completes the 24dp bottom inset after the pane's 8dp gap. */
|
||||
flex: 0 0 16dp;
|
||||
height: 16dp;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
scrollbarvertical {
|
||||
width: 8dp;
|
||||
margin: 4dp 4dp 4dp 0;
|
||||
}
|
||||
|
||||
scrollbarvertical sliderarrowdec,
|
||||
scrollbarvertical sliderarrowinc {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
scrollbarvertical slidertrack {
|
||||
width: 8dp;
|
||||
}
|
||||
|
||||
scrollbarvertical sliderbar {
|
||||
width: 8dp;
|
||||
min-height: 24dp;
|
||||
background-color: rgba(224, 219, 200, 45%);
|
||||
border-radius: 2dp;
|
||||
transition: background-color 0.2s cubic-in-out;
|
||||
}
|
||||
|
||||
scrollbarvertical sliderbar:hover,
|
||||
scrollbarvertical sliderbar:active {
|
||||
background-color: rgba(194, 164, 45, 80%);
|
||||
}
|
||||
|
||||
scrollbarhorizontal {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
scrollbarhorizontal sliderarrowdec,
|
||||
scrollbarhorizontal sliderarrowinc {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
scrollbarhorizontal slidertrack,
|
||||
scrollbarhorizontal sliderbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.section-heading {
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
font-size: 22dp;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.section-heading:not(:first-of-type) {
|
||||
padding-top: 12dp;
|
||||
}
|
||||
|
||||
button {
|
||||
text-align: center;
|
||||
background-color: rgba(17, 16, 10, 20%);
|
||||
opacity: 0.9;
|
||||
padding: 8dp 16dp;
|
||||
border-radius: 14dp;
|
||||
box-shadow: rgba(146, 135, 91, 25%) 0 0 0 1dp;
|
||||
font-size: 20dp;
|
||||
transition: background-color 0.1s linear-in-out, opacity 0.1s linear-in-out;
|
||||
cursor: pointer;
|
||||
focus: auto;
|
||||
}
|
||||
|
||||
button:not(:disabled):hover,
|
||||
button:not(:disabled):focus-visible {
|
||||
background-color: rgba(204, 184, 119, 20%);
|
||||
box-shadow: #C2A42D 0 0 0 2dp;
|
||||
}
|
||||
|
||||
button:not(:disabled):selected {
|
||||
opacity: 1;
|
||||
background-color: rgba(204, 184, 119, 40%);
|
||||
}
|
||||
|
||||
button:not(:disabled):active {
|
||||
opacity: 1;
|
||||
background-color: rgba(204, 184, 119, 40%);
|
||||
box-shadow: #C2A42D 0 0 0 2dp;
|
||||
}
|
||||
|
||||
select-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8dp;
|
||||
background-color: rgba(17, 16, 10, 20%);
|
||||
opacity: 0.9;
|
||||
padding: 8dp 16dp;
|
||||
border-radius: 14dp;
|
||||
box-shadow: rgba(146, 135, 91, 25%) 0 0 0 1dp;
|
||||
transition: background-color 0.1s linear-in-out, opacity 0.1s linear-in-out;
|
||||
cursor: pointer;
|
||||
focus: auto;
|
||||
}
|
||||
|
||||
select-button:not(:disabled):hover,
|
||||
select-button:not(:disabled):focus-visible {
|
||||
background-color: rgba(204, 184, 119, 20%);
|
||||
box-shadow: #C2A42D 0 0 0 2dp;
|
||||
}
|
||||
|
||||
select-button:not(:disabled):selected {
|
||||
opacity: 1;
|
||||
background-color: rgba(204, 184, 119, 40%);
|
||||
}
|
||||
|
||||
select-button:not(:disabled):active {
|
||||
opacity: 1;
|
||||
background-color: rgba(204, 184, 119, 40%);
|
||||
box-shadow: #C2A42D 0 0 0 2dp;
|
||||
}
|
||||
|
||||
select-button:disabled {
|
||||
opacity: 0.35;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
select-button key {
|
||||
font-family: "Fira Sans Condensed";
|
||||
font-weight: bold;
|
||||
font-size: 18dp;
|
||||
text-transform: uppercase;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
select-button value {
|
||||
margin-left: auto;
|
||||
font-size: 20dp;
|
||||
}
|
||||
|
||||
select-button value.modified {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
select-button input {
|
||||
text-align: right;
|
||||
font-size: 20dp;
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
#include "Z2AudioLib/Z2Audience.h"
|
||||
#include "Z2AudioLib/Z2SoundInfo.h"
|
||||
#if TARGET_PC
|
||||
#include "dusk/audio/DuskDsp.hpp"
|
||||
#include <cmath>
|
||||
#endif
|
||||
#include "Z2AudioLib/Z2Calc.h"
|
||||
#include "Z2AudioLib/Z2Param.h"
|
||||
#include "JSystem/JAudio2/JAISound.h"
|
||||
@@ -738,22 +734,9 @@ f32 Z2Audience::calcRelPosPan(const Vec& param_0, int camID) {
|
||||
|
||||
f32 Z2Audience::calcRelPosDolby(const Vec& param_0, int camID) {
|
||||
f32 fVar1 = param_0.z + mAudioCamera[camID].getDolbyCenterZ();
|
||||
#if TARGET_PC
|
||||
if (dusk::audio::EnableHrtf) {
|
||||
// Normalize the direction so result is purely front/back orientation,
|
||||
// independent of how far away the sound is
|
||||
f32 lenSq = param_0.x * param_0.x + param_0.y * param_0.y + param_0.z * param_0.z;
|
||||
if (lenSq < 0.0001f) {
|
||||
return 0.5f;
|
||||
}
|
||||
f32 zNorm = param_0.z / sqrtf(lenSq);
|
||||
f32 t = (zNorm + 1.0f) * 0.5f;
|
||||
return 0.5f - 0.5f * cosf(t * static_cast<f32>(M_PI));
|
||||
}
|
||||
#endif
|
||||
if (fVar1 > mSetting.field_0x48) {
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (fVar1 < mSetting.field_0x44) {
|
||||
return 0.0f;
|
||||
|
||||
@@ -4962,16 +4962,13 @@ int daAlink_c::create() {
|
||||
|
||||
setArcName(checkWolf());
|
||||
setOriginalHeap(&mpArcHeap, 0xA2800);
|
||||
JKRHEAP_NAME(mpArcHeap, "Alink ArcHeap");
|
||||
if (dComIfG_resLoad(&mPhaseReq, mArcName, mpArcHeap) != cPhs_COMPLEATE_e) {
|
||||
return cPhs_INIT_e;
|
||||
}
|
||||
|
||||
setShieldArcName();
|
||||
setOriginalHeap(&mpShieldArcHeap, 0x7000);
|
||||
JKRHEAP_NAME(mpShieldArcHeap, "Alink ShieldArcHeap");
|
||||
if (dComIfG_resLoad(&mShieldPhaseReq, mShieldArcName, mpShieldArcHeap) != cPhs_COMPLEATE_e)
|
||||
{
|
||||
if (dComIfG_resLoad(&mShieldPhaseReq, mShieldArcName, mpShieldArcHeap) != cPhs_COMPLEATE_e) {
|
||||
return cPhs_INIT_e;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
#include "d/actor/d_a_horse.h"
|
||||
#include "d/actor/d_a_crod.h"
|
||||
#include "d/d_msg_object.h"
|
||||
#ifdef TARGET_PC
|
||||
#include "d/actor/d_a_obj_carry.h"
|
||||
#include "dusk/achievements.h"
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#include "d/d_s_menu.h"
|
||||
@@ -681,15 +677,6 @@ BOOL daAlink_c::checkDamageAction() {
|
||||
}
|
||||
|
||||
setDamagePoint(dmg, at_mtrl == dCcD_MTRL_FIRE || at_mtrl == dCcD_MTRL_ICE, TRUE, 0);
|
||||
|
||||
#ifdef TARGET_PC
|
||||
if (tghit_ac_name == fpcNm_Obj_Carry_e) {
|
||||
auto* carry = static_cast<daObjCarry_c*>(tghit_ac);
|
||||
if (carry->prm_chk_type_ironball() && carry->checkCannon()) {
|
||||
dusk::AchievementSystem::get().signal("iron_ball_hit_player");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (armor_no_dmg && at_mtrl != dCcD_MTRL_ELECTRIC && at_mtrl != dCcD_MTRL_ICE) {
|
||||
setGuardSe(var_r29);
|
||||
|
||||
@@ -18,10 +18,6 @@ enum {
|
||||
};
|
||||
|
||||
void daAlink_c::hsChainShape_c::draw() {
|
||||
if (dusk::getSettings().game.superClawshot) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const int dummy = 0;
|
||||
|
||||
daAlink_c* alink = (daAlink_c*)getUserArea();
|
||||
|
||||
@@ -46,6 +46,7 @@ void daAlink_c::setOriginalHeap(JKRExpHeap** i_ppheap, u32 i_size) {
|
||||
JKRHeap* parent = mDoExt_getGameHeap();
|
||||
|
||||
JKRExpHeap* heap = JKRExpHeap::create(size + (var_r29 + var_r28), parent, true);
|
||||
JKRHEAP_NAME(heap, "Alink original");
|
||||
*i_ppheap = heap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include "JSystem/J2DGraph/J2DAnmLoader.h"
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/memory.h"
|
||||
|
||||
class daCoach2D_HIO_c : public mDoHIO_entry_c {
|
||||
public:
|
||||
struct Param {
|
||||
@@ -155,7 +153,7 @@ int daCoach2D_c::createHeap() {
|
||||
int daCoach2D_c::create() {
|
||||
int phase_state = dComIfG_resLoad(this, l_arcName);
|
||||
if (phase_state == cPhs_COMPLEATE_e) {
|
||||
if (!fopAcM_entrySolidHeap(this, daCoach2D_createHeap, HEAP_SIZE(0x5050, 0x6000))) {
|
||||
if (!fopAcM_entrySolidHeap(this, daCoach2D_createHeap, 0x5050)) {
|
||||
return cPhs_ERROR_e;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,6 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#if TARGET_PC
|
||||
#include <f_ap/f_ap_game.h>
|
||||
#include <dusk/autosave.h>
|
||||
#endif
|
||||
|
||||
char* daDoor20_c::getStopBmdName() {
|
||||
switch (door_param2_c::getKind(this)) {
|
||||
case 3:
|
||||
@@ -201,7 +196,6 @@ void daDoor20_c::setEventPrm() {
|
||||
} else {
|
||||
roomNo = FRoomNo;
|
||||
}
|
||||
|
||||
if (dComIfGp_roomControl_checkStatusFlag(roomNo, 1)) {
|
||||
if (door_param2_c::getKind(this) == 9) {
|
||||
if (daPy_py_c::checkNowWolf()) {
|
||||
@@ -570,11 +564,6 @@ int daDoor20_c::openEnd(int param_1) {
|
||||
openEnd_1();
|
||||
break;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
triggerAutoSave();
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -282,11 +282,6 @@ static void e_th_spin_B(e_th_class* i_this) {
|
||||
i_this->current.pos += spC;
|
||||
|
||||
f32 speed_target;
|
||||
|
||||
#if AVOID_UB
|
||||
speed_target = 0;
|
||||
#endif
|
||||
|
||||
f32 anm_frame = i_this->mpModelMorf->getFrame();
|
||||
|
||||
switch (i_this->mMode) {
|
||||
|
||||
@@ -463,23 +463,6 @@ int daMidna_c::createHeap() {
|
||||
JKRReadIdxResource(mBckHeap[0].getBuffer(), mBckHeap[0].getBufferSize(), 0x1DC, dComIfGp_getAnmArchive());
|
||||
J3DAnmTransform* md_anm = (J3DAnmTransform*)J3DAnmLoaderDataBase::load(mBckHeap[0].getBuffer());
|
||||
modelData = (J3DModelData*)dComIfG_getObjectRes(l_arcName, 14);
|
||||
|
||||
#if TARGET_PC
|
||||
J3DTexture* tex = modelData->getTexture();
|
||||
JUTNameTab* nametable = modelData->getTextureName();
|
||||
if (tex != NULL && nametable != NULL) {
|
||||
for (u16 i = 0; i < tex->getNum(); i++) {
|
||||
const char* name = nametable->getName(i);
|
||||
if (name != NULL && strcmp(name, "midona_eye") == 0) {
|
||||
ResTIMG* timg = tex->getResTIMG(i);
|
||||
timg->mipmapEnabled = false;
|
||||
tex->loadGXTexObj(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
JUT_ASSERT(852, modelData != NULL);
|
||||
mpMorf = JKR_NEW mDoExt_McaMorfSO(modelData, &mMorfCB, NULL, md_anm, J3DFrameCtrl::EMode_LOOP, 1.0f, 0, -1, NULL, 0, 0x11000284);
|
||||
if (mpMorf == NULL || mpMorf->getModel() == NULL) {
|
||||
|
||||
@@ -40,7 +40,6 @@ dMirror_packet_c::dMirror_packet_c() {
|
||||
void dMirror_packet_c::reset() {
|
||||
#if TARGET_PC
|
||||
mbReset = true;
|
||||
mbHadEntry = false;
|
||||
#else
|
||||
mModelCount = 0;
|
||||
#endif
|
||||
@@ -85,21 +84,11 @@ void dMirror_packet_c::calcMinMax() {
|
||||
}
|
||||
|
||||
int dMirror_packet_c::entryModel(J3DModel* i_model) {
|
||||
#if TARGET_PC
|
||||
if (mbReset) {
|
||||
mModelCount = 0;
|
||||
mbReset = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mModelCount >= 0x40) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mModels[mModelCount++] = i_model;
|
||||
#if TARGET_PC
|
||||
mbHadEntry = true;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -603,6 +592,13 @@ int daMirror_c::execute() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (mPacket.mbReset) {
|
||||
mPacket.mModelCount = 0;
|
||||
mPacket.mbReset = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
daPy_py_c* player = daPy_getLinkPlayerActorClass();
|
||||
JUT_ASSERT(0, player != NULL);
|
||||
|
||||
@@ -628,12 +624,6 @@ int daMirror_c::draw() {
|
||||
mDoExt_modelUpdateDL(mpModel);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (mPacket.mbReset && !mPacket.mbHadEntry) {
|
||||
mPacket.mModelCount = 0;
|
||||
}
|
||||
mPacket.mbHadEntry = true;
|
||||
#endif
|
||||
dComIfGd_getOpaListBG()->entryImm(&mPacket, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "d/actor/d_a_obj_automata.h"
|
||||
#include "d/d_msg_object.h"
|
||||
#include "d/actor/d_a_obj_scannon.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include <cstring>
|
||||
|
||||
const daNpc_Toby_HIOParam daNpc_Toby_Param_c::m = {
|
||||
@@ -1399,7 +1398,6 @@ int daNpc_Toby_c::cutRepairSCannon(int arg0) {
|
||||
old.pos = current.pos;
|
||||
setAngle(cM_deg2s(5.0f * f32(mPath.getArg0())));
|
||||
mEventTimer = mPath.getArg2();
|
||||
dusk::frame_interp::request_presentation_sync();
|
||||
}
|
||||
} else if (!mHide) {
|
||||
mHide = 1;
|
||||
|
||||
@@ -62,16 +62,6 @@ void daObj_Balloon_c::saveBestScore() {
|
||||
dComIfGp_setMessageCountNumber(m_balloon_score);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static void minigameReset() {
|
||||
// !@bug d_a_obj_balloon.rel unload used to zero these file-statics; with static linking they dangle across scenes.
|
||||
m_combo_type = 0xFFFFFFFF;
|
||||
m_combo_count = 0;
|
||||
m_combo_next_score = 0;
|
||||
m_balloon_score = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static u8 hio_set;
|
||||
|
||||
static daObj_Balloon_HIO_c l_HIO;
|
||||
@@ -215,6 +205,13 @@ int daObj_Balloon_c::_delete() {
|
||||
Z2GetAudioMgr()->seStop(Z2SE_OBJ_WATERMILL_ROUND, 0);
|
||||
if (mHIOInit) {
|
||||
hio_set = false;
|
||||
#ifdef TARGET_PC
|
||||
// !@bug d_a_obj_balloon.rel unload used to zero these file-statics; with static linking they dangle across scenes.
|
||||
m_combo_type = 0xFFFFFFFF;
|
||||
m_combo_count = 0;
|
||||
m_combo_next_score = 0;
|
||||
m_balloon_score = 0;
|
||||
#endif
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -256,7 +253,6 @@ int daObj_Balloon_c::create() {
|
||||
}
|
||||
|
||||
if (!hio_set) {
|
||||
IF_DUSK(minigameReset());
|
||||
mHIOInit = true;
|
||||
hio_set = true;
|
||||
l_HIO.field_0x04 = -1;
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "d/d_bg_w.h"
|
||||
#include "d/d_cc_uty.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/settings.h"
|
||||
|
||||
struct daObjKLift00_HIO_c : public mDoHIO_entry_c {
|
||||
daObjKLift00_HIO_c();
|
||||
@@ -297,11 +295,6 @@ int daObjKLift00_c::Create() {
|
||||
if(getLock())
|
||||
mStopSwingingFrames = 5;
|
||||
|
||||
#if TARGET_PC
|
||||
mChainInterpPrevValid = false;
|
||||
mChainInterpCurrValid = false;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -443,34 +436,6 @@ int daObjKLift00_c::Execute(Mtx** i_mtx) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static void klift00_interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
static_cast<daObjKLift00_c*>(pUserWork)->onInterpCallback();
|
||||
}
|
||||
|
||||
void daObjKLift00_c::onInterpCallback() {
|
||||
if (!mChainInterpPrevValid || !mChainInterpCurrValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const f32 alpha = dusk::frame_interp::get_interpolation_step();
|
||||
cXyz savedPositions[64];
|
||||
|
||||
for (int i = 0; i < mNumChains; i++) {
|
||||
savedPositions[i] = mChainPositions[i].mCurrentPos;
|
||||
const cXyz& p0 = mChainInterpPrev[i];
|
||||
const cXyz& p1 = mChainInterpCurr[i];
|
||||
mChainPositions[i].mCurrentPos = p0 + (p1 - p0) * alpha;
|
||||
}
|
||||
|
||||
setMtx();
|
||||
|
||||
for (int i = 0; i < mNumChains; i++) {
|
||||
mChainPositions[i].mCurrentPos = savedPositions[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int daObjKLift00_c::Draw() {
|
||||
g_env_light.settingTevStruct(16, ¤t.pos, &tevStr);
|
||||
g_env_light.setLightTevColorType_MAJI(mpLiftPlatform, &tevStr);
|
||||
@@ -492,22 +457,6 @@ int daObjKLift00_c::Draw() {
|
||||
|
||||
dComIfGd_setList();
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
if (mChainInterpCurrValid) {
|
||||
memcpy(mChainInterpPrev, mChainInterpCurr, mNumChains * sizeof(cXyz));
|
||||
mChainInterpPrevValid = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mNumChains; i++) {
|
||||
mChainInterpCurr[i] = mChainPositions[i].mCurrentPos;
|
||||
}
|
||||
|
||||
mChainInterpCurrValid = true;
|
||||
dusk::frame_interp::add_interpolation_callback(&klift00_interp_callback, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+43
-55
@@ -1175,12 +1175,6 @@ bool dCamera_c::Run() {
|
||||
clrFlag(0x200000);
|
||||
}
|
||||
} else {
|
||||
#if TARGET_PC
|
||||
if (mCamParam.Algorythmn(mCamStyle) != 1) {
|
||||
mCamParam.mManualMode = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
sp0F = (this->*engine_tbl[mCamParam.Algorythmn(mCamStyle)])(mCamStyle);
|
||||
|
||||
field_0x170++;
|
||||
@@ -1487,7 +1481,7 @@ void dCamera_c::CalcTrimSize() {
|
||||
mTrimHeight += -mTrimHeight * 0.25f;
|
||||
break;
|
||||
case 2:
|
||||
#if !TARGET_PC && WIDESCREEN_SUPPORT
|
||||
#if WIDESCREEN_SUPPORT
|
||||
if (mDoGph_gInf_c::isWide() && mDoGph_gInf_c::isWideZoom()) {
|
||||
mTrimHeight += (16.0f - mTrimHeight) * 0.25f;
|
||||
break;
|
||||
@@ -3095,6 +3089,10 @@ bool dCamera_c::bumpCheck(u32 i_flags) {
|
||||
field_0x968 *= mMonitor.field_0xc / 5.0f;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (!dusk::getSettings().game.freeCamera || !mCamParam.mManualMode) {
|
||||
#endif
|
||||
|
||||
f32 tmp = field_0x96c * (mIsWolf == 1 ? 30.0f : 30.0f);
|
||||
center += vec3.norm() * (tmp * globe.V().Sin());
|
||||
cSGlobe globe2(vec2 - center);
|
||||
@@ -3108,6 +3106,10 @@ bool dCamera_c::bumpCheck(u32 i_flags) {
|
||||
vec = lin_chk1.GetCross();
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
if (mCamSetup.CheckFlag(0x8000)) {
|
||||
dDbVw_Report(20, 235, " U");
|
||||
@@ -3518,6 +3520,12 @@ void dCamera_c::checkGroundInfo() {
|
||||
}
|
||||
|
||||
bool dCamera_c::chaseCamera(s32 param_0) {
|
||||
#if TARGET_PC
|
||||
if (freeCamera()) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static f32 JumpCushion = 0.9f;
|
||||
f32 charge_latitude = mCamSetup.ChargeLatitude();
|
||||
int charge_timer = mCamSetup.ChargeTimer();
|
||||
@@ -4199,11 +4207,6 @@ bool dCamera_c::chaseCamera(s32 param_0) {
|
||||
chase->field_0x8 -= chase->field_0xc;
|
||||
chase->field_0x8c = 0;
|
||||
chase->field_0x90 = false;
|
||||
|
||||
#if TARGET_PC
|
||||
freeCamera();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4641,11 +4644,6 @@ bool dCamera_c::chaseCamera(s32 param_0) {
|
||||
if (chase->field_0x1c != 0) {
|
||||
chase->field_0x1c--;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
freeCamera();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7093,12 +7091,10 @@ bool dCamera_c::subjectCamera(s32 param_0) {
|
||||
cXyz sp1E0(val0, val2, val1);
|
||||
|
||||
#if TARGET_PC
|
||||
if (sp13) {
|
||||
f32 aspect = mDoGph_gInf_c::getAspect();
|
||||
f32 baseAspect = FB_WIDTH / FB_HEIGHT;
|
||||
if (aspect > baseAspect) {
|
||||
sp1E0.z += (aspect - baseAspect) * 4;
|
||||
}
|
||||
f32 aspect = mDoGph_gInf_c::getAspect();
|
||||
f32 baseAspect = FB_WIDTH / FB_HEIGHT;
|
||||
if (aspect > baseAspect) {
|
||||
sp1E0.z += (aspect - baseAspect) * 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7476,47 +7472,52 @@ bool dCamera_c::test2Camera(s32 param_0) {
|
||||
|
||||
#if TARGET_PC
|
||||
bool dCamera_c::freeCamera() {
|
||||
if (dusk::getSettings().game.freeCamera && mGear == 1) {
|
||||
mGear = 0;
|
||||
}
|
||||
|
||||
if (!dusk::getSettings().game.freeCamera || mCamStyle == 70)
|
||||
{
|
||||
if (!dusk::getSettings().game.freeCamera) {
|
||||
mCamParam.mManualMode = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mCamParam.mManualMode) {
|
||||
mCamParam.freeXAngle = mViewCache.mDirection.mAzimuth.Degree();
|
||||
mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree();
|
||||
}
|
||||
mCamParam.freeXAngle = mViewCache.mDirection.mAzimuth.Degree();
|
||||
mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree();
|
||||
|
||||
cXyz camMovement = {mPadInfo.mCStick.mLastPosX, mPadInfo.mCStick.mLastPosY, 0.0f};
|
||||
f32 magnitude = sqrt(mPadInfo.mCStick.mLastPosX * mPadInfo.mCStick.mLastPosX + mPadInfo.mCStick.mLastPosY * mPadInfo.mCStick.mLastPosY);
|
||||
|
||||
if (mPadInfo.mCStick.mLastPosX != 0 || mPadInfo.mCStick.mLastPosY != 0) {
|
||||
mCamParam.mManualMode = 1;
|
||||
if (!mCamParam.mManualMode) {
|
||||
mCamParam.mManualMode = 1;
|
||||
mCamParam.freeXAngle = mViewCache.mDirection.mAzimuth.Degree();
|
||||
mCamParam.freeYAngle = mViewCache.mDirection.mInclination.Degree();
|
||||
}
|
||||
|
||||
camMovement = camMovement.normalize();
|
||||
camMovement.y *= dusk::getSettings().game.invertCameraYAxis ? 1.0f : -1.0f;
|
||||
mCamParam.freeXAngle += camMovement.x * magnitude * dusk::getSettings().game.freeCameraSensitivity * 5.0f;
|
||||
mCamParam.freeYAngle += camMovement.y * magnitude * dusk::getSettings().game.freeCameraSensitivity * 5.0f;
|
||||
mCamParam.freeXAngle += camMovement.x * magnitude * dusk::getSettings().game.freeCameraSensitivity * 4.0f;
|
||||
mCamParam.freeYAngle += camMovement.y * magnitude * dusk::getSettings().game.freeCameraSensitivity * 4.0f;
|
||||
}
|
||||
|
||||
fopAc_ac_c* player = dComIfGp_getPlayer(0);
|
||||
if (!mCamParam.mManualMode || player == nullptr) {
|
||||
if (!mCamParam.mManualMode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
f32 minYAngle = -30.0f;
|
||||
f32 minYAngle = -10.0f;
|
||||
f32 maxAngle = 50.0f;
|
||||
|
||||
mCamParam.freeYAngle = std::clamp(mCamParam.freeYAngle, minYAngle, maxAngle);
|
||||
mViewCache.mDirection.mAzimuth = cSAngle(mCamParam.freeXAngle);
|
||||
mViewCache.mDirection.mInclination = cSAngle(mCamParam.freeYAngle);
|
||||
f32 currentLerp = (mCamParam.freeYAngle - minYAngle) / (maxAngle - minYAngle);
|
||||
mViewCache.mDirection.mRadius = std::lerp(200.0f, 1000.0f, currentLerp);
|
||||
|
||||
cXyz finalEye = mViewCache.mCenter + mViewCache.mDirection.Xyz();
|
||||
cXyz finalCenter = mpPlayerActor->current.pos;
|
||||
finalCenter.y += mIsWolf ? 90.0f : 100.0f;
|
||||
mViewCache.mCenter = finalCenter;
|
||||
|
||||
cXyz finalEye = finalCenter + mViewCache.mDirection.Xyz();
|
||||
mViewCache.mEye = finalEye;
|
||||
|
||||
mViewCache.mFovy = 60.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -11160,25 +11161,12 @@ static int camera_draw(camera_process_class* i_this) {
|
||||
}
|
||||
#endif
|
||||
|
||||
int trim_height = body->TrimHeight();
|
||||
|
||||
#if TARGET_PC
|
||||
auto trim_height = body->TrimHeight();
|
||||
|
||||
if (mDoGph_gInf_c::isWideZoom()) {
|
||||
const auto target_ar = FB_WIDTH / (FB_HEIGHT - trim_height * 2.0f);
|
||||
const auto current_ar = mDoGph_gInf_c::m_safeWidthF / mDoGph_gInf_c::m_safeHeightF;
|
||||
|
||||
if (current_ar < target_ar) {
|
||||
trim_height = FB_HEIGHT / 2.0f * (1.0f - current_ar / target_ar);
|
||||
} else {
|
||||
trim_height = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
trim_height *= viewport->height / FB_HEIGHT;
|
||||
window->setScissor(0.0f, trim_height, viewport->width, viewport->height - trim_height * 2.0f);
|
||||
#else
|
||||
int trim_height = body->TrimHeight();
|
||||
|
||||
window->setScissor(0.0f, trim_height, FB_WIDTH, FB_HEIGHT - trim_height * 2.0f);
|
||||
#endif
|
||||
|
||||
|
||||
+9
-45
@@ -22,10 +22,6 @@
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/gx_helper.h"
|
||||
#include "dusk/logging.h"
|
||||
|
||||
static const void* getInterpKey(const void* base, int idx) {
|
||||
return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(base) ^ idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
class dDlst_2Dm_c {
|
||||
@@ -1066,15 +1062,7 @@ void dDlst_shadowReal_c::reset() {
|
||||
}
|
||||
|
||||
void dDlst_shadowReal_c::imageDraw(Mtx param_0) {
|
||||
#ifdef TARGET_PC
|
||||
Mtx render_proj_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(getInterpKey(mpModels[0], 2), render_proj_mtx)) {
|
||||
GXSetProjection(render_proj_mtx, GX_ORTHOGRAPHIC);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXSetProjection(mRenderProjMtx, GX_ORTHOGRAPHIC);
|
||||
}
|
||||
GXSetProjection(mRenderProjMtx, GX_ORTHOGRAPHIC);
|
||||
JUT_ASSERT(1916, mModelNum);
|
||||
J3DModelData* model_data;
|
||||
J3DModel** models = mpModels;
|
||||
@@ -1087,15 +1075,7 @@ void dDlst_shadowReal_c::imageDraw(Mtx param_0) {
|
||||
for (u16 j = 0; j < model_data->getShapeNum(); j++) {
|
||||
if (!model_data->getShapeNodePointer(j)->checkFlag(1)) {
|
||||
shape_pkt = (*models)->getShapePacket(j);
|
||||
#ifdef TARGET_PC
|
||||
Mtx view_mtx;
|
||||
if (dusk::frame_interp::lookup_replacement(getInterpKey(mpModels[0], 1), view_mtx)) {
|
||||
shape_pkt->setBaseMtxPtr(&view_mtx);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
shape_pkt->setBaseMtxPtr(&mViewMtx);
|
||||
}
|
||||
shape_pkt->setBaseMtxPtr(&mViewMtx);
|
||||
shape_pkt->drawFast();
|
||||
shape_pkt->setBaseMtxPtr((Mtx*)param_0);
|
||||
}
|
||||
@@ -1116,18 +1096,7 @@ void dDlst_shadowReal_c::draw() {
|
||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetCurrentMtx(GX_PNMTX0);
|
||||
#ifdef TARGET_PC
|
||||
Mtx view_mtx, recv_proj_mtx;
|
||||
const auto have_view_mtx = dusk::frame_interp::lookup_replacement(getInterpKey(mpModels[0], 1), view_mtx);
|
||||
const auto have_recv_proj_mtx = dusk::frame_interp::lookup_replacement(getInterpKey(mpModels[0], 3), recv_proj_mtx);
|
||||
if (have_view_mtx && have_recv_proj_mtx) {
|
||||
cMtx_concat(recv_proj_mtx, view_mtx, recv_proj_mtx);
|
||||
GXLoadTexMtxImm(recv_proj_mtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
}
|
||||
GXLoadTexMtxImm(mReceiverProjMtx, GX_TEXMTX0, GX_MTX3x4);
|
||||
mShadowRealPoly.draw();
|
||||
}
|
||||
|
||||
@@ -1284,13 +1253,6 @@ u8 dDlst_shadowReal_c::setShadowRealMtx(cXyz* param_0, cXyz* param_1, f32 param_
|
||||
cMtx_lookAt(mViewMtx, &local_64, param_1, 0);
|
||||
C_MTXOrtho(mRenderProjMtx, param_2, -param_2, -param_2, param_2, 1.0f, 10000.0f);
|
||||
C_MTXLightOrtho(mReceiverProjMtx, param_2, -param_2, -param_2, param_2, 0.5f, -0.5f, 0.5f, 0.5f);
|
||||
|
||||
#ifdef TARGET_PC
|
||||
const auto keybase = mpModels[0];
|
||||
dusk::frame_interp::record_final_mtx(mViewMtx, getInterpKey(keybase, 1));
|
||||
dusk::frame_interp::record_final_mtx(mRenderProjMtx, getInterpKey(keybase, 2));
|
||||
dusk::frame_interp::record_final_mtx(mReceiverProjMtx, getInterpKey(keybase, 3));
|
||||
#endif
|
||||
cMtx_concat(mReceiverProjMtx, mViewMtx, mReceiverProjMtx);
|
||||
return r29;
|
||||
}
|
||||
@@ -1315,10 +1277,6 @@ u32 dDlst_shadowReal_c::set(u32 i_key, J3DModel* i_model, cXyz* param_2, f32 par
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
// provide a stable key for interpolation
|
||||
mpModels[0] = i_model;
|
||||
#endif
|
||||
field_0x1 = setShadowRealMtx(&sp60, param_2, param_3, param_4, param_7, param_5);
|
||||
|
||||
if (!field_0x1) {
|
||||
@@ -1412,6 +1370,12 @@ void dDlst_shadowSimple_c::draw() {
|
||||
GXCallDisplayList(l_shadowVolumeDL, 0x40);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static const void* getInterpKey(const void* base, int idx) {
|
||||
return reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(base) ^ idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
void dDlst_shadowSimple_c::set(cXyz* param_0, f32 param_1, f32 param_2, cXyz* param_3,
|
||||
s16 param_4, f32 param_5, TGXTexObj* param_6) {
|
||||
if (param_5 < 0.0f) {
|
||||
|
||||
@@ -78,7 +78,14 @@ void dEyeHL_mng_c::remove(dEyeHL_c* i_obj) {
|
||||
next = m_obj;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
// Skip the write if the heap owning m_timg was already destroyed
|
||||
if (JKRHeap::findFromRoot(i_obj->m_timg) != nullptr) {
|
||||
i_obj->m_timg->LODBias = i_obj->m_lodBias;
|
||||
}
|
||||
#else
|
||||
i_obj->m_timg->LODBias = i_obj->m_lodBias;
|
||||
#endif
|
||||
i_obj->m_timg = NULL;
|
||||
i_obj->m_pre = NULL;
|
||||
i_obj->m_next = NULL;
|
||||
|
||||
+1
-2
@@ -6,7 +6,6 @@
|
||||
#include "d/dolzel.h" // IWYU pragma: keep
|
||||
|
||||
#include "d/d_k_wmark.h"
|
||||
#include "dusk/memory.h"
|
||||
#include "JSystem/J3DGraphBase/J3DMaterial.h"
|
||||
#include "SSystem/SComponent/c_math.h"
|
||||
#include "d/actor/d_a_player.h"
|
||||
@@ -34,7 +33,7 @@ int dkWmark_c::create() {
|
||||
mColorType = this->parameters;
|
||||
}
|
||||
|
||||
mpHeap = mDoExt_createSolidHeapFromGameToCurrent(HEAP_SIZE(0x880, 0x1100), 0x20);
|
||||
mpHeap = mDoExt_createSolidHeapFromGameToCurrent(0x880, 0x20);
|
||||
if (mpHeap != NULL) {
|
||||
JKRHEAP_NAME(mpHeap, "dkWmark_c::mpHeap");
|
||||
J3DModelData* modelData = (J3DModelData*)dComIfG_getObjectRes("Alink", 0x23);
|
||||
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
#include "d/dolzel.h" // IWYU pragma: keep
|
||||
|
||||
#include "d/d_kankyo.h"
|
||||
#include "dusk/memory.h"
|
||||
#ifdef __REVOLUTION_SDK__
|
||||
#include <revolution.h>
|
||||
#else
|
||||
@@ -1186,7 +1185,7 @@ static void undwater_init() {
|
||||
J3DModelData* modelData2 = (J3DModelData*)dComIfG_getObjectRes("Always", 0x1D);
|
||||
JUT_ASSERT(1867, modelData2 != NULL);
|
||||
|
||||
g_env_light.undwater_ef_heap = mDoExt_createSolidHeapFromGameToCurrent(HEAP_SIZE(0x600, 0xC00), 0x20);
|
||||
g_env_light.undwater_ef_heap = mDoExt_createSolidHeapFromGameToCurrent(0x600, 0x20);
|
||||
JKRHEAP_NAME(g_env_light.undwater_ef_heap, "g_env_light.undwater_ef_heap");
|
||||
|
||||
if (g_env_light.undwater_ef_heap != NULL) {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#ifdef TARGET_PC
|
||||
constexpr u16 kMapResolutionMultiplier = 4;
|
||||
constexpr u16 kMapCircleSize = 16 * kMapResolutionMultiplier;
|
||||
#endif
|
||||
|
||||
void dMpath_n::dTexObjAggregate_c::create() {
|
||||
@@ -33,48 +32,6 @@ void dMpath_n::dTexObjAggregate_c::create() {
|
||||
JUT_ASSERT(74, image->magFilter == GX_NEAR);
|
||||
mDoLib_setResTimgObj(image, mp_texObj[lp1], 0, NULL);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
auto hqCircle = JKR_NEW TGXTexObj();
|
||||
|
||||
static bool hqCircleDrawn = false;
|
||||
static u8 hqCircleData[kMapCircleSize * kMapCircleSize];
|
||||
|
||||
if (!hqCircleDrawn) {
|
||||
const auto center = kMapCircleSize / 2.0f;
|
||||
const auto radiusSq = center * center;
|
||||
const auto blocksAcross = kMapCircleSize >> 3;
|
||||
const auto totalPixels = sizeof(hqCircleData);
|
||||
|
||||
for (size_t i = 0; i < totalPixels; i++) {
|
||||
// 8x4 block swizzling for I8
|
||||
const auto blockIdx = i >> 5;
|
||||
const auto localIdx = i & 31;
|
||||
|
||||
const auto blockY = blockIdx / blocksAcross;
|
||||
const auto blockX = blockIdx % blocksAcross;
|
||||
|
||||
const auto localY = localIdx >> 3;
|
||||
const auto localX = localIdx & 7;
|
||||
|
||||
const auto x = (blockX << 3) + localX;
|
||||
const auto y = (blockY << 2) + localY;
|
||||
|
||||
const auto dx = (x + 0.5f) - center;
|
||||
const auto dy = (y + 0.5f) - center;
|
||||
|
||||
// the original texture is in I4 format and uses 1 to indicate if inside the circle
|
||||
// so we scale to I8 range: 255 / 15 = 17
|
||||
hqCircleData[i] = (dx * dx + dy * dy < radiusSq) ? 17 : 0;
|
||||
}
|
||||
hqCircleDrawn = true;
|
||||
}
|
||||
|
||||
GXInitTexObj(hqCircle, hqCircleData, kMapCircleSize, kMapCircleSize, GX_TF_I8, GX_CLAMP,
|
||||
GX_CLAMP, GX_FALSE);
|
||||
GXInitTexObjLOD(hqCircle, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
|
||||
mp_texObj[6] = hqCircle;
|
||||
#endif
|
||||
}
|
||||
|
||||
void dMpath_n::dTexObjAggregate_c::remove() {
|
||||
|
||||
@@ -856,46 +856,7 @@ void dMenu_DmapBg_c::decGoldFrameAlphaRate() {
|
||||
setGoldFrameAlphaRate(rate);
|
||||
}
|
||||
|
||||
void dMenu_DmapBg_c::dMapBgWide() {
|
||||
// Scale Base HUD
|
||||
mBaseScreen->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f);
|
||||
mBaseScreen->translate(mDoGph_gInf_c::getSafeMinXF(), 0.0f);
|
||||
|
||||
// Boss Key, Compass & Map icons
|
||||
mBaseScreen->search(MULTI_CHAR('key_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mBaseScreen->search(MULTI_CHAR('con_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mBaseScreen->search(MULTI_CHAR('map_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
|
||||
// Text Header
|
||||
mBaseScreen->search(MULTI_CHAR('t_t00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mBaseScreen->search(MULTI_CHAR('f_t_00'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
|
||||
// C Button
|
||||
mBaseScreen->search(MULTI_CHAR('c_btn2'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
|
||||
// Scale Buttons HUD
|
||||
mButtonScreen->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f);
|
||||
mButtonScreen->translate(mDoGph_gInf_c::getSafeMinXF(), 0.0f);
|
||||
|
||||
// Buttons
|
||||
mButtonScreen->search(MULTI_CHAR('cont_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
|
||||
// C Button
|
||||
mButtonScreen->search(MULTI_CHAR('c_btn'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mButtonScreen->search(MULTI_CHAR('c_text_s'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mButtonScreen->search(MULTI_CHAR('c_text'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mButtonScreen->search(MULTI_CHAR('f_text_s'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
mButtonScreen->search(MULTI_CHAR('f_text'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
|
||||
// Decorations
|
||||
mButtonScreen->search(MULTI_CHAR('kazari_n'))->scale(mDoGph_gInf_c::hudAspectScaleDown, 1.0f);
|
||||
}
|
||||
|
||||
void dMenu_DmapBg_c::draw() {
|
||||
#if TARGET_PC
|
||||
dMapBgWide();
|
||||
#endif
|
||||
|
||||
u32 scissor_left;
|
||||
u32 scissor_top;
|
||||
u32 scissor_width;
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "d/d_msg_object.h"
|
||||
#include "d/d_msg_scrn_explain.h"
|
||||
#include "d/d_stage.h"
|
||||
#include "dusk/memory.h"
|
||||
#include "f_op/f_op_msg_mng.h"
|
||||
|
||||
static dMf_HIO_c g_fmHIO;
|
||||
@@ -190,7 +189,7 @@ dMenu_Fmap_c::dMenu_Fmap_c(JKRExpHeap* i_heap, STControl* i_stick, CSTControl* i
|
||||
field_0x148[i] = 0.0f;
|
||||
}
|
||||
|
||||
mpTalkHeap = JKRCreateExpHeap(HEAP_SIZE(0x32000, 0x40000), mpHeap, false);
|
||||
mpTalkHeap = JKRCreateExpHeap(0x32000, mpHeap, false);
|
||||
JUT_ASSERT(359, mpTalkHeap != NULL);
|
||||
JKRHEAP_NAME(mpTalkHeap, "dMenu_Fmap_c::mpTalkHeap");
|
||||
field_0x200 = 0;
|
||||
|
||||
+1
-34
@@ -20,15 +20,6 @@
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include <cstring>
|
||||
|
||||
#if TARGET_PC
|
||||
void dMenu_Fmap2DBack_c::fMapBackWide() {
|
||||
mpBaseScreen->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f);
|
||||
mpBaseScreen->translate(mDoGph_gInf_c::getSafeMinXF(), 0.0f);
|
||||
mpBackScreen->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f);
|
||||
mpBackScreen->translate(mDoGph_gInf_c::getSafeMinXF(), 0.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
dMenu_Fmap2DBack_c::dMenu_Fmap2DBack_c() {
|
||||
dMeter2Info_setMapDrugFlag(0);
|
||||
|
||||
@@ -276,10 +267,6 @@ dMenu_Fmap2DBack_c::~dMenu_Fmap2DBack_c() {
|
||||
}
|
||||
|
||||
void dMenu_Fmap2DBack_c::draw() {
|
||||
#if TARGET_PC
|
||||
fMapBackWide();
|
||||
#endif
|
||||
|
||||
calcBlink();
|
||||
|
||||
J2DGrafContext* grafPort = dComIfGp_getCurrentGrafPort();
|
||||
@@ -1212,7 +1199,7 @@ f32 dMenu_Fmap2DBack_c::getMapScissorAreaSizeX() {
|
||||
}
|
||||
|
||||
f32 dMenu_Fmap2DBack_c::getMapScissorAreaSizeRealX() {
|
||||
#if PLATFORM_GCN
|
||||
#if PLATFORM_GCN && !TARGET_PC
|
||||
return getMapScissorAreaSizeX();
|
||||
#else
|
||||
return getMapScissorAreaSizeX() * mDoGph_gInf_c::getScale();
|
||||
@@ -1420,11 +1407,6 @@ void dMenu_Fmap2DBack_c::stageTextureDraw() {
|
||||
mpSpotTexture->setAlpha(mAlphaRate * 255.0f * field_0xfa8 * mSpotTextureFadeAlpha);
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
JUTPalette* pPalette = mpSpotTexture->getTexture(0)->getPalette();
|
||||
pPalette->dataUploaded();
|
||||
#endif
|
||||
|
||||
mpSpotTexture->draw(mTransX + getMapScissorAreaLX(), mTransZ + getMapScissorAreaLY(),
|
||||
getMapScissorAreaSizeRealX(), getMapScissorAreaSizeRealY(), false, false,
|
||||
false);
|
||||
@@ -2197,17 +2179,6 @@ void dMenu_Fmap2DBack_c::setArrowPosAxis(f32 i_posX, f32 i_posZ) {
|
||||
control_ypos = 0.0f;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void dMenu_Fmap2DTop_c::fMapTopWide() {
|
||||
mpTitleScreen->search(MULTI_CHAR('spot0_n'))->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f);
|
||||
mpTitleScreen->search(MULTI_CHAR('spot2_n'))->scale(mDoGph_gInf_c::hudAspectScaleUp, 1.0f);
|
||||
mpTitleScreen->search(MULTI_CHAR('name_n'))->translate(mDoGph_gInf_c::ScaleHUDXLeft(-243.0f), -169.0f);
|
||||
mpTitleScreen->search(MULTI_CHAR('sub_n_n'))->translate(mDoGph_gInf_c::ScaleHUDXLeft(-80.0f), -154.0f);
|
||||
mpTitleScreen->search(MULTI_CHAR('btn_i_n'))->translate(mDoGph_gInf_c::ScaleHUDXLeft(-241.0f), 177.0f);
|
||||
mpTitleScreen->search(MULTI_CHAR('cont_n'))->translate(mDoGph_gInf_c::ScaleHUDXRight(515.0f), 83.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
dMenu_Fmap2DTop_c::dMenu_Fmap2DTop_c(JKRExpHeap* i_heap, STControl* i_stick) {
|
||||
mpHeap = i_heap;
|
||||
mTransX = 0.0f;
|
||||
@@ -2601,10 +2572,6 @@ void dMenu_Fmap2DTop_c::setAllAlphaRate(f32 i_rate, bool i_init) {
|
||||
}
|
||||
|
||||
void dMenu_Fmap2DTop_c::draw() {
|
||||
#if TARGET_PC
|
||||
fMapTopWide();
|
||||
#endif
|
||||
|
||||
u32 scissor_left, scissor_top, scissor_width, scissor_height;
|
||||
J2DOrthoGraph* ctx = static_cast<J2DOrthoGraph*>(dComIfGp_getCurrentGrafPort());
|
||||
ctx->setup2D();
|
||||
|
||||
@@ -17,10 +17,6 @@
|
||||
#include "d/d_msg_scrn_arrow.h"
|
||||
#include "d/d_lib.h"
|
||||
|
||||
#ifdef TARGET_PC
|
||||
#include "dusk/achievements.h"
|
||||
#endif
|
||||
|
||||
#if VERSION == VERSION_GCN_JPN
|
||||
#define D_MENU_LETTER_LINE_MAX 9
|
||||
#else
|
||||
@@ -518,10 +514,6 @@ void dMenu_Letter_c::read_open_init() {
|
||||
setAButtonString(0);
|
||||
setBButtonString(0);
|
||||
mpBlackTex->setAlpha(0);
|
||||
|
||||
#ifdef TARGET_PC
|
||||
dusk::AchievementSystem::get().signal("open_letter");
|
||||
#endif
|
||||
}
|
||||
|
||||
void dMenu_Letter_c::read_open_move() {
|
||||
|
||||
+3
-7
@@ -24,16 +24,12 @@
|
||||
#include "d/actor/d_a_horse.h"
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/memory.h"
|
||||
|
||||
#include "dusk/memory.h"
|
||||
|
||||
int dMeter2_c::_create() {
|
||||
stage_stag_info_class* stag_info = dComIfGp_getStageStagInfo();
|
||||
if (dStage_stagInfo_GetUpButton(stag_info) == 1) {
|
||||
mpHeap = fopMsgM_createExpHeap(HEAP_SIZE(0x5A400, 0xA0000), NULL);
|
||||
mpHeap = fopMsgM_createExpHeap(0x5A400, NULL);
|
||||
} else {
|
||||
mpHeap = fopMsgM_createExpHeap(HEAP_SIZE(0x60800, 0xC1000), NULL);
|
||||
mpHeap = fopMsgM_createExpHeap(0x60800, NULL);
|
||||
}
|
||||
JKRHEAP_NAME(mpHeap, "dMeter2_c");
|
||||
|
||||
@@ -236,7 +232,7 @@ int dMeter2_c::_create() {
|
||||
dMeter2Info_setMeterMapClass(mpMap);
|
||||
|
||||
mpHeap->getTotalFreeSize();
|
||||
mpSubHeap = fopMsgM_createExpHeap(HEAP_SIZE(0x5000, 0x6500), mpHeap);
|
||||
mpSubHeap = fopMsgM_createExpHeap(0x5000, mpHeap);
|
||||
JKRHEAP_NAME(mpSubHeap, "dMeter2_c mpSubHeap");
|
||||
field_0x108 = NULL;
|
||||
mpSubContents = NULL;
|
||||
|
||||
@@ -2306,10 +2306,6 @@ void dMeter_drawHIO_c::updateOnWide() {
|
||||
// River Canoe Minigame
|
||||
g_drawHIO.mMiniGame.mCounterPosX[1] = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mMiniGame.mCounterPosX[1]);
|
||||
g_drawHIO.mMiniGame.mIconPosX[1] = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mMiniGame.mIconPosX[1]);
|
||||
|
||||
// Bulblin Count in Hidden Village
|
||||
g_drawHIO.mMiniGame.mCounterPosX[2] = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mMiniGame.mCounterPosX[2]);
|
||||
g_drawHIO.mMiniGame.mIconPosX[2] = mDoGph_gInf_c::ScaleHUDXRight(g_drawHIO.mMiniGame.mIconPosX[2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1987,6 +1987,13 @@ bool jmessage_tSequenceProcessor::do_isReady() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) {
|
||||
field_0xb2 = 1;
|
||||
pReference->setSendTimer(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dComIfGp_checkMesgBgm()) {
|
||||
bool isItemMusicPlaying = true;
|
||||
if (mDoAud_checkPlayingSubBgmFlag() != Z2BGM_ITEM_GET &&
|
||||
@@ -2059,7 +2066,7 @@ bool jmessage_tSequenceProcessor::do_isReady() {
|
||||
case 0:
|
||||
case 5:
|
||||
case 6:
|
||||
if (mDoCPd_c::getTrigA(PAD_1) || field_0xb2 != 0 IF_DUSK(|| (dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)))) {
|
||||
if (mDoCPd_c::getTrigA(PAD_1) || field_0xb2 != 0) {
|
||||
field_0xa4 = 0;
|
||||
pReference->onBatchFlag();
|
||||
pReference->setCharCnt(D_MSG_CLASS_CHAR_CNT_MAX);
|
||||
|
||||
+1
-38
@@ -32,9 +32,6 @@
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/settings.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
static void dMsgObject_addFundRaising(s16 param_0);
|
||||
@@ -1597,7 +1594,7 @@ u8 dMsgObject_c::isSend() {
|
||||
return 2;
|
||||
}
|
||||
} else {
|
||||
if (IF_DUSK((dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0) && !isShopItemMessage()) ||)
|
||||
if (IF_DUSK((dusk::getSettings().game.instantText && mDoCPd_c::getHoldB(0)) ||)
|
||||
mDoCPd_c::getTrigA(0) != 0 || mDoCPd_c::getTrigB(0) != 0) {
|
||||
return 2;
|
||||
}
|
||||
@@ -1869,40 +1866,6 @@ bool dMsgObject_c::isTalkMessage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
bool dMsgObject_c::isShopItemMessage() {
|
||||
|
||||
// Probably a better way to do this than just listing every message id, but this works for now
|
||||
// Note: Keep contents sorted so we can use binary search
|
||||
const auto shopMsgIds = std::to_array<std::vector<s16>>({
|
||||
{},
|
||||
// zel_01.bmg - Seras Shop
|
||||
{7001, 7003, 7004, 7005, 7006, 7007, 7008, 7009, 7010, 7013, 7014, 7022, 7023, 7028, 7029,
|
||||
7044, 7045, 7053},
|
||||
// zel_02.bmg - Kakariko Shops
|
||||
{5251, 5253, 5254, 5256, 5258, 5259, 5653, 5654, 5656, 5660, 5661, 5664, 5665, 5697, 5698,
|
||||
5699, 5803, 5804, 5806, 5810, 5811, 5812, 5814, 5821, 5823, 5824, 5987, 5988, 5989, 5990,
|
||||
5991, 5992, 5993, 5994, 5995, 5996, 5997, 5998, 5999},
|
||||
// zel_03.bmg - Death Mountain Shop
|
||||
{5303, 5304, 5306, 5310, 5311, 5314, 5315, 5322, 5323, 5324, 5496, 5497, 5498, 5499},
|
||||
// zel_04.bmg - Castle Town Shops
|
||||
{5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5431,
|
||||
5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5444, 5449, 5450, 5451, 5452,
|
||||
5462},
|
||||
// zel_05.bmg - Oocca Shop
|
||||
{9428, 9429, 9430, 9431, 9432, 9437, 9443, 9448, 9449, 9451, 9459}
|
||||
});
|
||||
|
||||
u16 id = mMessageID;
|
||||
s16 group = dMsgObject_getGroupID();
|
||||
if (group < shopMsgIds.size()) {
|
||||
return std::ranges::binary_search(shopMsgIds[group], id);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* dMsgObject_c::getSmellName() {
|
||||
JMSMesgInfo_c* info_header_p = (JMSMesgInfo_c*)((char*)mpMsgRes + 0x20);
|
||||
char* data_ptr = (char*)info_header_p + info_header_p->header.size;
|
||||
|
||||
+18
-6
@@ -36,15 +36,27 @@ dRes_info_c::dRes_info_c() {
|
||||
|
||||
dRes_info_c::~dRes_info_c() {
|
||||
if (mDMCommand != NULL) {
|
||||
mDMCommand->destroy();
|
||||
#if TARGET_PC
|
||||
if (JKRHeap::findFromRoot(mDMCommand) != nullptr) {
|
||||
#endif
|
||||
mDMCommand->destroy();
|
||||
#if TARGET_PC
|
||||
}
|
||||
#endif
|
||||
mDMCommand = NULL;
|
||||
} else if (mArchive != NULL) {
|
||||
deleteArchiveRes();
|
||||
if (mDataHeap != NULL) {
|
||||
mDoExt_destroySolidHeap(mDataHeap);
|
||||
mDataHeap = NULL;
|
||||
mArchive->unmount();
|
||||
#if TARGET_PC
|
||||
if (JKRHeap::findFromRoot(mArchive) != nullptr) {
|
||||
#endif
|
||||
deleteArchiveRes();
|
||||
if (mDataHeap != NULL) {
|
||||
mDoExt_destroySolidHeap(mDataHeap);
|
||||
mDataHeap = NULL;
|
||||
mArchive->unmount();
|
||||
}
|
||||
#if TARGET_PC
|
||||
}
|
||||
#endif
|
||||
mRes = NULL;
|
||||
mArchive = NULL;
|
||||
}
|
||||
|
||||
+1
-2
@@ -10,7 +10,6 @@
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/d_s_name.h"
|
||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||
#include "dusk/memory.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "f_op/f_op_overlap_mng.h"
|
||||
#include "f_op/f_op_scene_mng.h"
|
||||
@@ -77,7 +76,7 @@ static s32 resLoad(request_of_phase_process_class* i_phase, char* i_resName) {
|
||||
s32 dScnName_c::create() {
|
||||
int phase_state = resLoad(&phase, "fileSel");
|
||||
if (phase_state == cPhs_COMPLEATE_e) {
|
||||
mHeap = JKRCreateExpHeap(HEAP_SIZE(0x180000, 0x1C0000), mDoExt_getGameHeap(), false);
|
||||
mHeap = JKRCreateExpHeap(0x180000, mDoExt_getGameHeap(), false);
|
||||
JUT_ASSERT(289, mHeap != NULL);
|
||||
JKRHEAP_NAME(mHeap, "File select");
|
||||
|
||||
|
||||
+2
-25
@@ -39,11 +39,6 @@
|
||||
#include "JSystem/JKernel/JKRAram.h"
|
||||
#include "JSystem/JKernel/JKRAramArchive.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/memory.h"
|
||||
#include <dusk/autosave.h>
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#include "d/d_s_menu.h"
|
||||
#include "d/d_debug_pad.h"
|
||||
@@ -701,10 +696,6 @@ static u8 lbl_8074CAE4;
|
||||
static u32 l_sceneChangeStartTick;
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
static BOOL autoSaved;
|
||||
#endif
|
||||
|
||||
static int dScnPly_Execute(dScnPly_c* i_this) {
|
||||
#if DEBUG
|
||||
fapGm_HIO_c::startCpuTimer();
|
||||
@@ -747,15 +738,6 @@ static int dScnPly_Execute(dScnPly_c* i_this) {
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
if (!dComIfGp_event_runCheck() && !fopOvlpM_IsPeek() && !dComIfG_resetToOpening(i_this) &&
|
||||
!dComIfGp_isEnableNextStage() && autoSaved == FALSE)
|
||||
{
|
||||
triggerAutoSave();
|
||||
autoSaved = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
dKy_itudemo_se();
|
||||
|
||||
#if DEBUG
|
||||
@@ -1438,7 +1420,7 @@ static int phase_4(dScnPly_c* i_this) {
|
||||
dComIfGd_setViewport(NULL);
|
||||
dComIfGd_setView(NULL);
|
||||
|
||||
JKRExpHeap* heap = fopMsgM_createExpHeap(HEAP_SIZE(0xBB800, 0x177000), NULL);
|
||||
JKRExpHeap* heap = fopMsgM_createExpHeap(0xBB800, NULL);
|
||||
#if TARGET_PC
|
||||
heap->setName("Scene2DHeap");
|
||||
#endif
|
||||
@@ -1446,7 +1428,7 @@ static int phase_4(dScnPly_c* i_this) {
|
||||
JUT_ASSERT(2704, heap != NULL);
|
||||
dComIfGp_setExpHeap2D(heap);
|
||||
|
||||
JKRExpHeap* heap2 = fopMsgM_createExpHeap(HEAP_SIZE(0xA800, 0x15000), NULL);
|
||||
JKRExpHeap* heap2 = fopMsgM_createExpHeap(0xA800, NULL);
|
||||
#if TARGET_PC
|
||||
heap2->setName("SceneMsgHeap");
|
||||
#endif
|
||||
@@ -1607,11 +1589,6 @@ static int dScnPly_Create(scene_class* i_this) {
|
||||
|
||||
dScnPly_c* a_this = (dScnPly_c*)i_this;
|
||||
int phase_state = dComLbG_PhaseHandler(&a_this->field_0x1c4, l_method, a_this);
|
||||
|
||||
#if TARGET_PC
|
||||
autoSaved = FALSE;
|
||||
#endif
|
||||
|
||||
return phase_state;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,7 @@
|
||||
#include "lingcod/lingcod.h"
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/settings.h"
|
||||
#include <f_ap/f_ap_game.h>
|
||||
#include <dusk/autosave.h>
|
||||
#endif
|
||||
|
||||
static u8 dSv_item_rename(u8 i_itemNo) {
|
||||
switch (i_itemNo) {
|
||||
@@ -349,10 +345,6 @@ void dSv_player_item_c::setItem(int i_slotNo, u8 i_itemNo) {
|
||||
dComIfGp_setSelectItem(i);
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
triggerAutoSave();
|
||||
#endif
|
||||
}
|
||||
|
||||
u8 dSv_player_item_c::getItem(int i_slotNo, bool i_checkCombo) const {
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
#include <memory>
|
||||
|
||||
#include "aurora/lib/logging.hpp"
|
||||
#include "os_report.h"
|
||||
|
||||
aurora::Module Log("dusk::osReport");
|
||||
|
||||
bool dusk::OSReportReallyForceEnable = false;
|
||||
|
||||
u8 __OSReport_disable;
|
||||
|
||||
void OSReportDisable() {
|
||||
__OSReport_disable = true;
|
||||
}
|
||||
|
||||
void OSReportEnable() {
|
||||
__OSReport_disable = false;
|
||||
}
|
||||
|
||||
static bool checkEnabled() {
|
||||
return !__OSReport_disable || dusk::OSReportReallyForceEnable;
|
||||
}
|
||||
|
||||
static std::string FormatToString(const char* msg, va_list list) {
|
||||
int ret = vsnprintf(nullptr, 0, msg, list);
|
||||
if (ret <= 0) {
|
||||
return {};
|
||||
}
|
||||
++ret;
|
||||
std::unique_ptr<char[]> buf(new char[ret]);
|
||||
vsnprintf(buf.get(), ret, msg, list);
|
||||
buf[ret - 1] = '\0';
|
||||
return {buf.get()};
|
||||
}
|
||||
|
||||
void OSReport(const char* fmt, ...) {
|
||||
if (!checkEnabled()) {
|
||||
return;
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
const auto str = FormatToString(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
Log.info("{}", str);
|
||||
}
|
||||
|
||||
void OSPanic(const char* file, int line, const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
const auto str = FormatToString(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
Log.fatal("[{}:{}] {}", file, line, str);
|
||||
}
|
||||
|
||||
void OSReport_Error(const char* fmt, ...) {
|
||||
if (!checkEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
const auto str = FormatToString(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
Log.error("{}", str);
|
||||
}
|
||||
|
||||
void OSReport_FatalError(const char* fmt, ...) {
|
||||
if (!checkEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
const auto str = FormatToString(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
Log.fatal("{}", str);
|
||||
}
|
||||
|
||||
void OSReport_Warning(const char* fmt, ...) {
|
||||
if (!checkEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
const auto str = FormatToString(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
Log.warn("{}", str);
|
||||
}
|
||||
|
||||
void OSReport_System(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
OSVAttention(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void OSVAttention(const char* fmt, va_list args) {
|
||||
if (!checkEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto str = FormatToString(fmt, args);
|
||||
|
||||
Log.info("{}", str);
|
||||
}
|
||||
|
||||
void OSAttention(const char* fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
OSVAttention(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
+8
-127
@@ -8,7 +8,6 @@
|
||||
#include "d/actor/d_a_player.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "f_pc/f_pc_name.h"
|
||||
#include "f_op/f_op_actor_mng.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
@@ -47,21 +46,6 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"plumm_max",
|
||||
"Thank You Berry Much",
|
||||
"Score 61,454 points in the Plumm minigame.",
|
||||
AchievementCategory::Minigame,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_getBalloonScore() >= 61454) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"rollgoal_8",
|
||||
@@ -274,58 +258,6 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"friendly_fire",
|
||||
"Friendly Fire",
|
||||
"Get hit by your own cannonball.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (AchievementSystem::get().hasSignal("iron_ball_hit_player")) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"long_jump_attack",
|
||||
"Long Jump Attack",
|
||||
"Travel more than 20 meters in a single jump attack before landing.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
static bool inJump = false;
|
||||
static float startX = 0.0f, startZ = 0.0f;
|
||||
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr) {
|
||||
inJump = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!inJump) {
|
||||
if (link->mProcID == daAlink_c::PROC_CUT_JUMP) {
|
||||
inJump = true;
|
||||
startX = link->current.pos.x;
|
||||
startZ = link->current.pos.z;
|
||||
}
|
||||
} else if (link->mProcID == daAlink_c::PROC_CUT_JUMP_LAND) {
|
||||
inJump = false;
|
||||
const float dx = link->current.pos.x - startX;
|
||||
const float dz = link->current.pos.z - startZ;
|
||||
if (dx * dx + dz * dz >= 2000.0f * 2000.0f) {
|
||||
a.progress = 1;
|
||||
}
|
||||
} else if (link->mProcID != daAlink_c::PROC_CUT_JUMP) {
|
||||
inJump = false;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"back_in_time",
|
||||
@@ -335,13 +267,18 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
static int titleNoDemoFrames = 0;
|
||||
if (fopAcM_SearchByName(fpcNm_TITLE_e) == nullptr) {
|
||||
titleNoDemoFrames = 0;
|
||||
return;
|
||||
}
|
||||
const auto* player = static_cast<const daPy_py_c*>(daPy_getPlayerActorClass());
|
||||
|
||||
if (player != nullptr && player->mDemo.getDemoMode() == 1) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link != nullptr && dDemo_c::getMode() == 0) {
|
||||
if (++titleNoDemoFrames >= 60) {
|
||||
a.progress = 1;
|
||||
}
|
||||
} else {
|
||||
titleNoDemoFrames = 0;
|
||||
}
|
||||
},
|
||||
{}
|
||||
@@ -408,41 +345,6 @@ std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"email_me",
|
||||
"Email Me",
|
||||
"Read a letter during the Dark Beast Ganon fight.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
void* dbgExists = fopAcM_SearchByName(fpcNm_B_MGN_e);
|
||||
if (dbgExists && AchievementSystem::get().hasSignal("open_letter")) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"heavy-hitter",
|
||||
"Heavy Hitter",
|
||||
"Wear the Iron Boots during the end credits.",
|
||||
AchievementCategory::Misc,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
const auto* link = static_cast<const daAlink_c*>(daPy_getPlayerActorClass());
|
||||
if (link == nullptr || link->mProcID != daAlink_c::PROC_GANON_FINISH) {
|
||||
return;
|
||||
}
|
||||
if (daPy_getPlayerActorClass()->checkEquipHeavyBoots()) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -524,26 +426,6 @@ void AchievementSystem::clearAll() {
|
||||
save();
|
||||
}
|
||||
|
||||
void AchievementSystem::signal(const char* key) {
|
||||
m_signals.insert(key);
|
||||
}
|
||||
|
||||
bool AchievementSystem::hasSignal(const char* key) const {
|
||||
return m_signals.count(key) > 0;
|
||||
}
|
||||
|
||||
void AchievementSystem::clearOne(const char* key) {
|
||||
for (auto& e : m_entries) {
|
||||
if (std::string(e.achievement.key) == key) {
|
||||
e.achievement.progress = 0;
|
||||
e.achievement.unlocked = false;
|
||||
e.extra = {};
|
||||
break;
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
void AchievementSystem::processEntry(Entry& e) {
|
||||
if (e.achievement.unlocked) {
|
||||
return;
|
||||
@@ -576,7 +458,6 @@ void AchievementSystem::tick() {
|
||||
for (auto& e : m_entries) {
|
||||
processEntry(e);
|
||||
}
|
||||
m_signals.clear();
|
||||
if (m_dirty) {
|
||||
save();
|
||||
m_dirty = false;
|
||||
|
||||
@@ -48,20 +48,6 @@ f32 dusk::audio::MasterVolume = 1.0f;
|
||||
f32 dusk::audio::PrevMasterVolume = 1.0f;
|
||||
bool dusk::audio::EnableReverb = true;
|
||||
bool dusk::audio::DumpAudio = false;
|
||||
bool dusk::audio::EnableHrtf = false;
|
||||
f32 dusk::audio::HrtfGain = 0.5f;
|
||||
|
||||
|
||||
// 3dB at 5kHz.
|
||||
static constexpr f32 HRTF_LP_K = 0.75f;
|
||||
static constexpr f32 HRTF_ALLPASS_G = 0.3f;
|
||||
// Front never drops below (1 - HRTF_EXTRACT_MAX).
|
||||
static constexpr f32 HRTF_EXTRACT_MAX = 0.6f;
|
||||
|
||||
static f32 sHrtfLp1 = 0.0f;
|
||||
static f32 sHrtfLp2 = 0.0f;
|
||||
static f32 sHrtfApIn1 = 0.0f;
|
||||
static f32 sHrtfApOut1 = 0.0f;
|
||||
|
||||
/**
|
||||
* Validate that a DSP channel's format is actually something we know how to play.
|
||||
@@ -297,9 +283,6 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
|
||||
DspSubframe reverbInputR = {};
|
||||
bool anyReverbInput = false;
|
||||
|
||||
DspSubframe surroundBus = {};
|
||||
bool anySurroundInput = false;
|
||||
|
||||
for (int i = 0; i < channels.size(); i++) {
|
||||
auto& channel = channels[i];
|
||||
auto& channelAux = ChannelAux[i];
|
||||
@@ -341,21 +324,6 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
|
||||
}
|
||||
}
|
||||
|
||||
if (EnableHrtf && channel.mAutoMixerBeenSet) {
|
||||
f32 dolby = (channel.mAutoMixerPanDolby & 0xFF) / 127.0f;
|
||||
if (dolby > 0.0f) {
|
||||
anySurroundInput = true;
|
||||
f32 extract = dolby * HRTF_EXTRACT_MAX;
|
||||
f32 frontScale = 1.0f - extract;
|
||||
for (int j = 0; j < DSP_SUBFRAME_SIZE; j++) {
|
||||
f32 mono = (channelSubframe.channels[0][j] + channelSubframe.channels[1][j]) * 0.5f;
|
||||
surroundBus[j] += mono * extract;
|
||||
channelSubframe.channels[0][j] *= frontScale;
|
||||
channelSubframe.channels[1][j] *= frontScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DumpAudio && sChannelDumpFiles[i]) {
|
||||
f32 interleaved[DSP_SUBFRAME_SIZE * 2];
|
||||
for (int j = 0; j < DSP_SUBFRAME_SIZE; j++) {
|
||||
@@ -381,28 +349,6 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
|
||||
ReverbHasTail = wetEnergy >= REVERB_ENERGY_EPSILON;
|
||||
}
|
||||
|
||||
if (EnableHrtf && anySurroundInput) {
|
||||
// Two-pole LPF: -12 dB/oct above 3 kHz
|
||||
for (int j = 0; j < DSP_SUBFRAME_SIZE; j++) {
|
||||
sHrtfLp1 = (1.0f - HRTF_LP_K) * sHrtfLp1 + HRTF_LP_K * surroundBus[j];
|
||||
sHrtfLp2 = (1.0f - HRTF_LP_K) * sHrtfLp2 + HRTF_LP_K * sHrtfLp1;
|
||||
surroundBus[j] = sHrtfLp2;
|
||||
}
|
||||
|
||||
// Mix into L and R
|
||||
// L gets the filtered signal directly; R gets it allpass for mild decorrelation
|
||||
for (int j = 0; j < DSP_SUBFRAME_SIZE; j++) {
|
||||
f32 s = surroundBus[j];
|
||||
|
||||
subframe.channels[0][j] += s * HrtfGain;
|
||||
|
||||
f32 r = -HRTF_ALLPASS_G * s + sHrtfApIn1 + HRTF_ALLPASS_G * sHrtfApOut1;
|
||||
sHrtfApIn1 = s;
|
||||
sHrtfApOut1 = r;
|
||||
subframe.channels[1][j] += r * HrtfGain;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& channel : subframe.channels) {
|
||||
ApplyVolume(channel, channel, PrevMasterVolume, MasterVolume);
|
||||
}
|
||||
|
||||
@@ -133,6 +133,4 @@ namespace dusk::audio {
|
||||
extern f32 PrevMasterVolume;
|
||||
extern bool EnableReverb;
|
||||
extern bool DumpAudio;
|
||||
extern bool EnableHrtf;
|
||||
extern f32 HrtfGain;
|
||||
}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
#include "dusk/autosave.h"
|
||||
#include "imgui/ImGuiConsole.hpp"
|
||||
|
||||
u8 mSaveBuffer[QUEST_LOG_SIZE * 3];
|
||||
u8 mAutoSaveProc = 0;
|
||||
int autoSaveWriteState = 0;
|
||||
|
||||
typedef void (*AutoSaveFuncs)();
|
||||
static AutoSaveFuncs AutoSaveFuncsProc[] = {
|
||||
noAutoSave, enterAutoSave, autoSaving, waitingForWrite, endAutoSave,
|
||||
};
|
||||
|
||||
void noAutoSave() {}
|
||||
|
||||
void triggerAutoSave() {
|
||||
if (dusk::getSettings().game.autoSave && mAutoSaveProc == 0 &&
|
||||
strcmp(dComIfGp_getStartStageName(), "F_SP102") != 0)
|
||||
{
|
||||
mAutoSaveProc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void updateAutoSave() {
|
||||
(AutoSaveFuncsProc[mAutoSaveProc])();
|
||||
}
|
||||
|
||||
void writeAutoSave() {
|
||||
int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo());
|
||||
|
||||
dComIfGs_putSave(stageNo);
|
||||
dComIfGs_setMemoryToCard(mSaveBuffer, dComIfGs_getDataNum());
|
||||
mDoMemCdRWm_SetCheckSumGameData(mSaveBuffer, dComIfGs_getDataNum());
|
||||
|
||||
u8* save = mSaveBuffer;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
mDoMemCdRWm_TestCheckSumGameData(save);
|
||||
save += QUEST_LOG_SIZE;
|
||||
}
|
||||
|
||||
g_mDoMemCd_control.save(mSaveBuffer, sizeof(mSaveBuffer), 0);
|
||||
}
|
||||
|
||||
void autoSaving() {
|
||||
int cardState = g_mDoMemCd_control.LoadSync(mSaveBuffer, sizeof(mSaveBuffer), 0);
|
||||
if (cardState != 0) {
|
||||
if (cardState == 2) {
|
||||
mAutoSaveProc = 1;
|
||||
} else if (cardState == 1) {
|
||||
writeAutoSave();
|
||||
mAutoSaveProc = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void enterAutoSave() {
|
||||
u32 cardStatus = g_mDoMemCd_control.getStatus(0);
|
||||
|
||||
if (cardStatus != 14) {
|
||||
switch (cardStatus) {
|
||||
case 2:
|
||||
g_mDoMemCd_control.load();
|
||||
mAutoSaveProc = 2;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
break;
|
||||
default:
|
||||
mAutoSaveProc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void waitingForWrite() {
|
||||
autoSaveWriteState = g_mDoMemCd_control.SaveSync();
|
||||
|
||||
if (autoSaveWriteState == 2) {
|
||||
mAutoSaveProc = 0;
|
||||
} else if (autoSaveWriteState == 1) {
|
||||
mAutoSaveProc = 4;
|
||||
}
|
||||
}
|
||||
|
||||
void endAutoSave() {
|
||||
dusk::g_imguiConsole.AddToast("Saving...", 2.0f);
|
||||
mAutoSaveProc = 0;
|
||||
}
|
||||
@@ -76,8 +76,8 @@ void ImGuiAchievements::draw(bool& open) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(800, 200), ImVec2(1280, 900));
|
||||
ImGui::SetNextWindowSize(ImVec2(800, 480), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(640, 200), ImVec2(800, 900));
|
||||
ImGui::SetNextWindowSize(ImVec2(640, 480), ImGuiCond_FirstUseEver);
|
||||
|
||||
if (!ImGui::Begin(
|
||||
"Achievements", &open,
|
||||
@@ -111,7 +111,6 @@ void ImGuiAchievements::draw(bool& open) {
|
||||
{AchievementCategory::Collection, "Collection", ImVec4(0.3f, 0.85f, 0.4f, 1.0f)},
|
||||
{AchievementCategory::Challenge, "Challenge", ImVec4(1.0f, 0.65f, 0.15f, 1.0f)},
|
||||
{AchievementCategory::Minigame, "Minigame", ImVec4(0.5f, 0.85f, 1.0f, 1.0f)},
|
||||
{AchievementCategory::Misc, "Misc", ImVec4(0.65f, 0.65f, 0.65f, 1.0f)},
|
||||
{AchievementCategory::Glitched, "Glitched", ImVec4(0.75f, 0.4f, 1.0f, 1.0f)},
|
||||
};
|
||||
|
||||
@@ -132,7 +131,7 @@ void ImGuiAchievements::draw(bool& open) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string tabLabel = fmt::format("{} ({}/{})###{}", catInfo.label, catUnlocked, catTotal, catInfo.label);
|
||||
const std::string tabLabel = fmt::format("{} ({}/{})", catInfo.label, catUnlocked, catTotal);
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, catInfo.color);
|
||||
const bool tabOpen = ImGui::BeginTabItem(tabLabel.c_str());
|
||||
@@ -153,7 +152,6 @@ void ImGuiAchievements::draw(bool& open) {
|
||||
continue;
|
||||
}
|
||||
ImGui::PushID(a.key);
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::PushStyleColor(
|
||||
ImGuiCol_Text,
|
||||
@@ -192,21 +190,6 @@ void ImGuiAchievements::draw(bool& open) {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
ImGui::OpenPopup("##ctx");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("##ctx")) {
|
||||
ImGui::TextDisabled("%s", a.name);
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Clear Achievement")) {
|
||||
AchievementSystem::get().clearOne(a.key);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
#include "imgui.h"
|
||||
|
||||
#include "ImGuiMenuTools.hpp"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "f_op/f_op_actor_mng.h"
|
||||
#include "SSystem/SComponent/c_sxyz.h"
|
||||
#include "SSystem/SComponent/c_xyz.h"
|
||||
|
||||
namespace dusk {
|
||||
namespace {
|
||||
|
||||
struct ActorSpawnerState {
|
||||
int actorId = 0;
|
||||
int params = -1;
|
||||
int argument = -1;
|
||||
int angleX = 0;
|
||||
int angleY = 0;
|
||||
int angleZ = 0;
|
||||
float scaleX = 1.0f;
|
||||
float scaleY = 1.0f;
|
||||
float scaleZ = 1.0f;
|
||||
bool usePlayerRoom = true;
|
||||
int manualRoom = 0;
|
||||
int spawnCount = 1;
|
||||
bool hasResult = false;
|
||||
unsigned int lastResult = 0;
|
||||
int lastAttempted = 0;
|
||||
};
|
||||
|
||||
ActorSpawnerState s_state;
|
||||
|
||||
} // namespace
|
||||
|
||||
void ImGuiMenuTools::ShowActorSpawner() {
|
||||
if (!m_showActorSpawner) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ImGui::Begin("Actor Spawner", &m_showActorSpawner)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
daAlink_c* player = (daAlink_c*)dComIfGp_getPlayer(0);
|
||||
|
||||
ImGui::SeparatorText("Actor");
|
||||
ImGui::InputInt("Actor ID", &s_state.actorId);
|
||||
ImGui::InputInt("Params (hex)", &s_state.params, 0, 0, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::InputInt("Argument", &s_state.argument);
|
||||
s_state.argument = (s_state.argument < -128) ? -128 : (s_state.argument > 127) ? 127 : s_state.argument;
|
||||
|
||||
ImGui::SeparatorText("Angle");
|
||||
ImGui::InputInt("Angle X", &s_state.angleX);
|
||||
ImGui::InputInt("Angle Y", &s_state.angleY);
|
||||
ImGui::InputInt("Angle Z", &s_state.angleZ);
|
||||
|
||||
ImGui::SeparatorText("Scale");
|
||||
ImGui::InputFloat("Scale X", &s_state.scaleX, 0.1f, 1.0f);
|
||||
ImGui::InputFloat("Scale Y", &s_state.scaleY, 0.1f, 1.0f);
|
||||
ImGui::InputFloat("Scale Z", &s_state.scaleZ, 0.1f, 1.0f);
|
||||
|
||||
ImGui::SeparatorText("Spawn");
|
||||
ImGui::InputInt("Count", &s_state.spawnCount);
|
||||
if (s_state.spawnCount < 1) {
|
||||
s_state.spawnCount = 1;
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Position");
|
||||
ImGui::Checkbox("Use player room", &s_state.usePlayerRoom);
|
||||
if (!s_state.usePlayerRoom) {
|
||||
ImGui::InputInt("Room No", &s_state.manualRoom);
|
||||
}
|
||||
|
||||
if (player != nullptr) {
|
||||
ImGui::Text("Spawn pos: %.2f, %.2f, %.2f",
|
||||
player->current.pos.x, player->current.pos.y, player->current.pos.z);
|
||||
} else {
|
||||
ImGui::TextDisabled("Player not available");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
bool canSpawn = player != nullptr;
|
||||
if (!canSpawn) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
|
||||
if (ImGui::Button("Spawn", ImVec2(-1, 0))) {
|
||||
cXyz pos = player->current.pos;
|
||||
csXyz angle;
|
||||
angle.set((s16)s_state.angleX, (s16)s_state.angleY, (s16)s_state.angleZ);
|
||||
cXyz scale(s_state.scaleX, s_state.scaleY, s_state.scaleZ);
|
||||
int roomNo = s_state.usePlayerRoom ? player->current.roomNo : s_state.manualRoom;
|
||||
|
||||
layer_class* savedLayer = fpcLy_CurrentLayer();
|
||||
base_process_class* playScene = fpcM_SearchByName(fpcNm_PLAY_SCENE_e);
|
||||
if (playScene != nullptr) {
|
||||
fpcLy_SetCurrentLayer(&((process_node_class*)playScene)->layer);
|
||||
}
|
||||
|
||||
s_state.lastResult = 0;
|
||||
s_state.lastAttempted = s_state.spawnCount;
|
||||
for (int i = 0; i < s_state.spawnCount; ++i) {
|
||||
unsigned int result = fopAcM_create(
|
||||
(s16)s_state.actorId,
|
||||
(u32)s_state.params,
|
||||
&pos,
|
||||
roomNo,
|
||||
&angle,
|
||||
&scale,
|
||||
(s8)s_state.argument
|
||||
);
|
||||
if (result != 0) {
|
||||
s_state.lastResult = result;
|
||||
}
|
||||
}
|
||||
s_state.hasResult = true;
|
||||
|
||||
fpcLy_SetCurrentLayer(savedLayer);
|
||||
}
|
||||
|
||||
if (!canSpawn) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
if (s_state.hasResult) {
|
||||
if (s_state.lastResult != 0) {
|
||||
if (s_state.lastAttempted == 1) {
|
||||
ImGui::Text("Spawned: proc ID %u", s_state.lastResult);
|
||||
} else {
|
||||
ImGui::Text("Spawned %d (last proc ID %u)", s_state.lastAttempted, s_state.lastResult);
|
||||
}
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(1, 0.4f, 0.4f, 1), "Spawn failed (returned 0)");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace dusk
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuTools.hpp"
|
||||
#include <cmath>
|
||||
#include "JSystem/JAudio2/JAISeq.h"
|
||||
#include "JSystem/JAudio2/JAISeMgr.h"
|
||||
#include "JSystem/JAudio2/JAISeqMgr.h"
|
||||
#include "JSystem/JAudio2/JAIStreamMgr.h"
|
||||
@@ -17,24 +15,6 @@ static std::array<u32, DSP_CHANNELS> lastResetCounts = {};
|
||||
|
||||
static bool sortUpdateCount = true;
|
||||
|
||||
static void DrawDirectionGauge(float pan, float dolby) {
|
||||
constexpr float R = 20.0f;
|
||||
constexpr float SIZE = R * 2.0f + 4.0f;
|
||||
|
||||
ImVec2 origin = ImGui::GetCursorScreenPos();
|
||||
ImGui::Dummy(ImVec2(SIZE, SIZE));
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
ImVec2 c = ImVec2(origin.x + SIZE * 0.5f, origin.y + SIZE * 0.5f);
|
||||
|
||||
dl->AddCircle(c, R, IM_COL32(90, 90, 90, 255), 32);
|
||||
|
||||
float dx = (pan - 0.5f) * 2.0f;
|
||||
float dy = dolby * 2.0f - 1.0f;
|
||||
float len = sqrtf(dx * dx + dy * dy);
|
||||
if (len > 1.0f) { dx /= len; dy /= len; }
|
||||
dl->AddLine(c, ImVec2(c.x + dx * R, c.y + dy * R), IM_COL32(255, 200, 50, 255), 1.5f);
|
||||
}
|
||||
|
||||
static void DisplayDspChannel(int i) {
|
||||
using namespace dusk::audio;
|
||||
|
||||
@@ -72,10 +52,8 @@ static void DisplayDspChannel(int i) {
|
||||
auto fxMix = (channel.mAutoMixerFxMix >> 8) / 127.5f;
|
||||
auto volume = VolumeFromU16(channel.mAutoMixerVolume);
|
||||
auto pitch = channel.mPitch / 4096.0f;
|
||||
DrawDirectionGauge(pan, dolby);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(
|
||||
"pan: %.2f dolby: %.2f\nfx: %.2f vol: %.2f pitch: %.2f",
|
||||
"Auto mixer active (pan: %f, dolby: %f, fx: %f, volume: %f, pitch %f)",
|
||||
pan, dolby, fxMix, volume, pitch);
|
||||
} else {
|
||||
ImGui::Text(
|
||||
@@ -205,10 +183,6 @@ static void ShowAllJAISes() {
|
||||
if (ImGui::Button("Pause All")) {
|
||||
category->pause(true);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Resume All")) {
|
||||
category->pause(false);
|
||||
}
|
||||
|
||||
for (auto seLink = category->getSeList()->getFirst(); seLink != nullptr; seLink = seLink->getNext()) {
|
||||
const auto se = seLink->getObject();
|
||||
@@ -222,33 +196,6 @@ static void ShowAllJAISes() {
|
||||
}
|
||||
|
||||
|
||||
static void ShowSeqTracks(JAISeq& seq) {
|
||||
JASTrack& root = seq.inner_.outputTrack;
|
||||
|
||||
for (int group = 0; group < 2; group++) {
|
||||
JASTrack* groupTrack = root.getChild(group);
|
||||
if (groupTrack == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < JASTrack::MAX_CHILDREN; j++) {
|
||||
JASTrack* track = groupTrack->getChild(j);
|
||||
if (track == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int trackIdx = group * 16 + j;
|
||||
char label[64];
|
||||
snprintf(label, sizeof(label), "Track %d (bank %hu, prog %hu)##%p",
|
||||
trackIdx, track->getBankNumber(), track->getProgNumber(), track);
|
||||
bool muted = track->mFlags.mute;
|
||||
if (ImGui::Checkbox(label, &muted)) {
|
||||
track->mute(muted);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ShowAllJAISeqs() {
|
||||
auto& mgr = *JAISeqMgr::getInstance();
|
||||
|
||||
@@ -259,26 +206,6 @@ static void ShowAllJAISeqs() {
|
||||
if (ImGui::Button("Unpause")) {
|
||||
mgr.pause(false);
|
||||
}
|
||||
|
||||
ImGui::Text("Active sequences: %d", mgr.getNumActiveSeqs());
|
||||
|
||||
auto* seqList = mgr.getSeqList();
|
||||
for (auto* link = seqList->getFirst(); link != nullptr; link = link->getNext()) {
|
||||
JAISeq* seq = link->getObject();
|
||||
if (seq == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "%p", seq);
|
||||
|
||||
if (ImGui::BeginChild(buf, ImVec2(), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY)) {
|
||||
ImGui::Text("Seq [%p]", seq);
|
||||
ShowSeqTracks(*seq);
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
void dusk::ImGuiMenuTools::ShowAudioDebug() {
|
||||
|
||||
@@ -320,18 +320,22 @@ namespace dusk {
|
||||
ImGuiMenuGame::ToggleFullscreen();
|
||||
}
|
||||
|
||||
// if (!dusk::IsGameLaunched) {
|
||||
// m_preLaunchWindow.draw();
|
||||
// }
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape) && getSettings().video.enableFullscreen) {
|
||||
ImGuiMenuGame::ToggleFullscreen();
|
||||
}
|
||||
|
||||
if (!dusk::IsGameLaunched) {
|
||||
m_preLaunchWindow.draw();
|
||||
}
|
||||
|
||||
m_isHidden = !getSettings().backend.duskMenuOpen;
|
||||
if (ImGui::GetIO().KeyShift && ImGui::IsKeyPressed(ImGuiKey_F1)) {
|
||||
m_isHidden = !m_isHidden;
|
||||
}
|
||||
bool showMenu = !m_isHidden;
|
||||
if (getSettings().backend.duskMenuOpen != showMenu) {
|
||||
getSettings().backend.duskMenuOpen.setValue(showMenu);
|
||||
Save();
|
||||
bool showMenu = !dusk::IsGameLaunched || !CheckMenuViewToggle(ImGuiKey_F1, m_isHidden);
|
||||
if (dusk::IsGameLaunched) {
|
||||
const bool menuOpen = !m_isHidden;
|
||||
if (getSettings().backend.duskMenuOpen != menuOpen) {
|
||||
getSettings().backend.duskMenuOpen.setValue(menuOpen);
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
// The menu bar renders with ImGuiCol_WindowBg behind it. We just want ImGuiCol_MenuBarBg,
|
||||
@@ -361,10 +365,10 @@ namespace dusk {
|
||||
}
|
||||
|
||||
if (dusk::IsGameLaunched && !m_isLaunchInitialized) {
|
||||
AddToast(ImGui::GetIO().MouseSource == ImGuiMouseSource_TouchScreen ?
|
||||
m_toasts.emplace_back(ImGui::GetIO().MouseSource == ImGuiMouseSource_TouchScreen ?
|
||||
"Tap to toggle menu"s :
|
||||
"Press F1 to toggle menu"s,
|
||||
4.f);
|
||||
2.5f);
|
||||
m_isLaunchInitialized = true;
|
||||
if (getSettings().game.liveSplitEnabled) {
|
||||
dusk::speedrun::connectLiveSplit();
|
||||
@@ -397,6 +401,7 @@ namespace dusk {
|
||||
m_menuTools.ShowAudioDebug();
|
||||
m_menuTools.ShowSaveEditor();
|
||||
m_menuTools.ShowStateShare();
|
||||
m_menuTools.ShowActorSpawner();
|
||||
}
|
||||
m_menuTools.ShowAchievements();
|
||||
DuskDebugPad(); // temporary, remove later
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -44,7 +44,6 @@ static void ApplyPresetDusk() {
|
||||
s.game.enableFrameInterpolation.setValue(true);
|
||||
s.game.sunsSong.setValue(true);
|
||||
s.game.bloomMode.setValue(BloomMode::Dusk);
|
||||
s.game.autoSave.setValue(true);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "JSystem/JFramework/JFWSystem.h"
|
||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "JSystem/JKernel/JKRSolidHeap.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "imgui.h"
|
||||
|
||||
@@ -178,9 +179,9 @@ namespace dusk {
|
||||
}
|
||||
|
||||
void ShowHeapDetailed(JKRHeap* heap, OpenHeapData& data, bool& open) {
|
||||
const char* heapName = data.Safe ? heap->getName() : "INVALID";
|
||||
char title[128];
|
||||
const char* name = data.Safe ? heap->getName() : "INVALID";
|
||||
snprintf(title, sizeof(title), "Heap %s##%p", name, static_cast<const void*>(heap));
|
||||
snprintf(title, sizeof(title), "Heap %s##%p", heapName, static_cast<const void*>(heap));
|
||||
|
||||
if (!ImGui::Begin(title, &open)) {
|
||||
ImGui::End();
|
||||
@@ -195,11 +196,35 @@ namespace dusk {
|
||||
|
||||
heap->lock();
|
||||
|
||||
ImGui::Text("Name: %s", name);
|
||||
ImGui::Text("Name: %s", heap->getName());
|
||||
const auto size = BytesToString(heap->getSize());
|
||||
const auto freeSize = BytesToString(heap->getFreeSize());
|
||||
ImGui::Text("Size: %08X (%s), free: %08X (%s)", heap->getSize(), size.c_str(), heap->getFreeSize(), freeSize.c_str());
|
||||
|
||||
{
|
||||
void* vmemBase = nullptr;
|
||||
size_t vmemCapacity = 0;
|
||||
size_t vmemCommitted = 0;
|
||||
if (heap->getHeapType() == 'EXPH') {
|
||||
auto* h = static_cast<JKRExpHeap*>(heap);
|
||||
vmemBase = h->mVmemBase; vmemCapacity = h->mVmemCapacity; vmemCommitted = h->mVmemCommitted;
|
||||
} else if (heap->getHeapType() == 'SLID') {
|
||||
auto* h = static_cast<JKRSolidHeap*>(heap);
|
||||
vmemBase = h->mVmemBase; vmemCapacity = h->mVmemCapacity; vmemCommitted = h->mVmemCommitted;
|
||||
}
|
||||
if (vmemBase) {
|
||||
ImGui::SeparatorText("Virtual Memory");
|
||||
ImGui::Text("Base: %p", vmemBase);
|
||||
const auto committedStr = BytesToString(vmemCommitted);
|
||||
const auto capacityStr = BytesToString(vmemCapacity);
|
||||
ImGui::Text("Committed: %s / %s reserved", committedStr.c_str(), capacityStr.c_str());
|
||||
float pct = vmemCapacity > 0 ? (float)vmemCommitted / (float)vmemCapacity : 0.0f;
|
||||
char overlayBuf[32];
|
||||
snprintf(overlayBuf, sizeof(overlayBuf), "%.1f%%", pct * 100.0f);
|
||||
ImGui::ProgressBar(pct, ImVec2(-1.0f, 0.0f), overlayBuf);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Button("Check")) {
|
||||
data.HeapCheckFailed = !heap->check();
|
||||
data.HeapCheckRan = true;
|
||||
|
||||
@@ -3,13 +3,31 @@
|
||||
|
||||
#include "ImGuiEngine.hpp"
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiMenuGame.hpp"
|
||||
#include "ImGuiConfig.hpp"
|
||||
|
||||
#include "JSystem/JUtility/JUTGamePad.h"
|
||||
#include "dusk/audio/DuskAudioSystem.h"
|
||||
#include "dusk/audio/DuskDsp.hpp"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/hotkeys.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "dusk/livesplit.h"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
|
||||
#include <aurora/gfx.h>
|
||||
#include <SDL3/SDL_gamepad.h>
|
||||
|
||||
#include "m_Do/m_Do_main.h"
|
||||
|
||||
#include <SDL3/SDL_gamepad.h>
|
||||
namespace {
|
||||
constexpr int kInternalResolutionScaleMax = 12;
|
||||
} // namespace
|
||||
|
||||
namespace aurora::gx {
|
||||
extern bool enableLodBias;
|
||||
}
|
||||
|
||||
namespace dusk {
|
||||
void ImGuiMenuGame::ToggleFullscreen() {
|
||||
@@ -22,17 +40,475 @@ namespace dusk {
|
||||
|
||||
void ImGuiMenuGame::draw() {
|
||||
if (ImGui::BeginMenu("Settings")) {
|
||||
// TODO: Remove this once Controller Config exists in RmlUi
|
||||
drawAudioMenu();
|
||||
drawCheatsMenu();
|
||||
drawGameplayMenu();
|
||||
drawGraphicsMenu();
|
||||
drawInputMenu();
|
||||
drawInterfaceMenu();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Reset", hotkeys::DO_RESET)) {
|
||||
JUTGamePad::C3ButtonReset::sResetSwitchPushing = true;
|
||||
}
|
||||
|
||||
if (!IsMobile && ImGui::MenuItem("Exit")) {
|
||||
dusk::IsRunning = false;
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawGraphicsMenu() {
|
||||
if (ImGui::BeginMenu("Graphics")) {
|
||||
ImGui::SeparatorText("Display");
|
||||
|
||||
if (!IsMobile) {
|
||||
if (ImGui::MenuItem("Toggle Fullscreen", hotkeys::TOGGLE_FULLSCREEN)) {
|
||||
ToggleFullscreen();
|
||||
}
|
||||
|
||||
if (ImGui::Button("Restore Default Window Size")) {
|
||||
getSettings().video.enableFullscreen.setValue(false);
|
||||
VISetWindowFullscreen(false);
|
||||
VISetWindowSize(FB_WIDTH * 2, FB_HEIGHT * 2);
|
||||
VICenterWindow();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
bool vsync = getSettings().video.enableVsync;
|
||||
if (ImGui::Checkbox("Enable VSync", &vsync)) {
|
||||
getSettings().video.enableVsync.setValue(vsync);
|
||||
aurora_enable_vsync(vsync);
|
||||
config::Save();
|
||||
}
|
||||
|
||||
bool lockAspect = getSettings().video.lockAspectRatio;
|
||||
if (ImGui::Checkbox("Force 4:3 Aspect Ratio", &lockAspect)) {
|
||||
getSettings().video.lockAspectRatio.setValue(lockAspect);
|
||||
|
||||
if (lockAspect) {
|
||||
AuroraSetViewportPolicy(AURORA_VIEWPORT_FIT);
|
||||
} else {
|
||||
AuroraSetViewportPolicy(AURORA_VIEWPORT_STRETCH);
|
||||
}
|
||||
|
||||
config::Save();
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Resolution");
|
||||
|
||||
u32 internalResolutionWidth = 0;
|
||||
u32 internalResolutionHeight = 0;
|
||||
AuroraGetRenderSize(&internalResolutionWidth, &internalResolutionHeight);
|
||||
ImGui::TextDisabled("Current internal resolution: %ux%u", internalResolutionWidth,
|
||||
internalResolutionHeight);
|
||||
|
||||
int scale = std::clamp(getSettings().game.internalResolutionScale.getValue(), 0,
|
||||
kInternalResolutionScaleMax);
|
||||
if (ImGui::SliderInt("Internal Resolution", &scale, 0, kInternalResolutionScaleMax,
|
||||
scale == 0 ? "Auto" : "%dx"))
|
||||
{
|
||||
getSettings().game.internalResolutionScale.setValue(scale);
|
||||
VISetFrameBufferScale(static_cast<float>(scale));
|
||||
config::Save();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Auto renders at the native window resolution.\n"
|
||||
"Higher values scale the game's internal framebuffer.");
|
||||
}
|
||||
|
||||
config::ImGuiSliderInt("Shadow Resolution", getSettings().game.shadowResolutionMultiplier, 1, 8, "x%d");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Improves the shadow resolution, making them higher quality.");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Post-Processing");
|
||||
|
||||
constexpr const char* bloomModeNames[] = {"Off", "Classic", "Dusk"};
|
||||
int bloomMode = static_cast<int>(getSettings().game.bloomMode.getValue());
|
||||
if (ImGui::BeginCombo("Bloom", bloomModeNames[bloomMode])) {
|
||||
for (int i = 0; i < IM_ARRAYSIZE(bloomModeNames); i++) {
|
||||
const bool selected = bloomMode == i;
|
||||
if (ImGui::Selectable(bloomModeNames[i], selected)) {
|
||||
getSettings().game.bloomMode.setValue(static_cast<BloomMode>(i));
|
||||
config::Save();
|
||||
}
|
||||
if (selected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
bool bloomOff = bloomMode == static_cast<int>(BloomMode::Off);
|
||||
if (bloomOff) ImGui::BeginDisabled();
|
||||
float mult = getSettings().game.bloomMultiplier.getValue();
|
||||
if (ImGui::SliderFloat("Bloom Brightness", &mult, 0.0f, 1.0f, "%.2f")) {
|
||||
getSettings().game.bloomMultiplier.setValue(mult);
|
||||
config::Save();
|
||||
}
|
||||
if (bloomOff) ImGui::EndDisabled();
|
||||
|
||||
ImGui::SeparatorText("Rendering");
|
||||
|
||||
config::ImGuiCheckbox("Unlock Framerate", getSettings().game.enableFrameInterpolation);
|
||||
const bool frameInterpolationHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.72f, 0.2f, 1.0f));
|
||||
ImGui::TextUnformatted("[EXPERIMENTAL]");
|
||||
ImGui::PopStyleColor();
|
||||
if (frameInterpolationHovered || ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Uses inter-frame interpolation to enable higher frame rates.\nVisual artifacts, animation glitches, or instability may occur.");
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias);
|
||||
|
||||
config::ImGuiCheckbox("Enable Depth of Field", getSettings().game.enableDepthOfField);
|
||||
|
||||
config::ImGuiCheckbox("Enable Mini-Map Shadows", getSettings().game.enableMapBackground);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawGameplayMenu() {
|
||||
if (ImGui::BeginMenu("Gameplay")) {
|
||||
ImGui::SeparatorText("General");
|
||||
|
||||
config::ImGuiCheckbox("Mirror Mode", getSettings().game.enableMirrorMode);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Mirrors the world horizontally, matching the Wii version of the game.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Disable Main HUD", getSettings().game.disableMainHUD);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Disables the main HUD of the game.\n"
|
||||
"Useful for recording or a more immersive experience!");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Restore Wii 1.0 Glitches", getSettings().game.restoreWiiGlitches);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Restores patched glitches from Wii USA 1.0,\n"
|
||||
"the first released version.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Enable Rotating Link Doll", getSettings().game.enableLinkDollRotation);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables rotating Link in the collection menu with the C-Stick");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Difficulty");
|
||||
|
||||
ImGui::BeginDisabled(getSettings().game.speedrunMode);
|
||||
config::ImGuiSliderInt("Damage Multiplier", getSettings().game.damageMultiplier, 1, 8, "x%d");
|
||||
|
||||
config::ImGuiCheckbox("Instant Death", getSettings().game.instantDeath);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Any hit will instantly kill you.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Heart Drops", getSettings().game.noHeartDrops);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Hearts will never drop from enemies,\n"
|
||||
"pots and various other places.");
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SeparatorText("Quality of Life");
|
||||
|
||||
config::ImGuiCheckbox("Bigger Wallets", getSettings().game.biggerWallets);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Wallet sizes are like in the HD version. (500, 1000, 2000)");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Disable Rupee Cutscenes", getSettings().game.disableRupeeCutscenes);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Rupees won't play cutscenes after you've collected them the first time.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Faster Climbing", getSettings().game.fastClimbing);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Quicker climbing on ladders and vines like the HD version.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Faster Tears of Light", getSettings().game.fastTears);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Tears of Light dropped by Shadow Insects pop out faster like the HD version.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Instant Saves", getSettings().game.instantSaves);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the delay when writing to the Memory Card.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Hold B for Instant Text", getSettings().game.instantText);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Make text scroll immediately by holding B.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Climbing Miss Animation", getSettings().game.noMissClimbing);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Prevents Link from playing a struggle animation\n"
|
||||
"when grabbing ledges or climbing on vines.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Rupee Returns", getSettings().game.noReturnRupees);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Always collect Rupees even if your Wallet is too full.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Sword Recoil", getSettings().game.noSwordRecoil);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Link won't recoil when his sword hits walls.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No 2nd Fish for Cat", getSettings().game.no2ndFishForCat);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Only need to fish once for Sera's cat to return.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Skip TV Settings Screen", getSettings().game.hideTvSettingsScreen);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the TV calibration screen shown when loading a save.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Skip Warning Screen", getSettings().game.skipWarningScreen);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Skip the warning screen shown when starting the game.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Sun's Song (R+X)", getSettings().game.sunsSong);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Allows Wolf Link to howl and change the time of day.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Quick Transform (R+Y)", getSettings().game.enableQuickTransform);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Transform instantly by pressing R and Y simultaneously.");
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Speedrunning");
|
||||
if (config::ImGuiCheckbox("Speedrun Mode", getSettings().game.speedrunMode)) {
|
||||
resetForSpeedrunMode();
|
||||
}
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables Speedrunning options, while restricting certain gameplay modifiers.");
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(!getSettings().game.speedrunMode);
|
||||
bool prevLiveSplit = getSettings().game.liveSplitEnabled;
|
||||
config::ImGuiCheckbox("LiveSplit Connection", getSettings().game.liveSplitEnabled);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Connect to LiveSplit server on localhost:16834.");
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if ((bool)getSettings().game.liveSplitEnabled != prevLiveSplit) {
|
||||
if (getSettings().game.liveSplitEnabled) {
|
||||
dusk::speedrun::connectLiveSplit();
|
||||
} else {
|
||||
dusk::speedrun::disconnectLiveSplit();
|
||||
DuskToast("LiveSplit disconnected", 3.f);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawCheatsMenu() {
|
||||
if (ImGui::BeginMenu("Cheats")) {
|
||||
ImGui::BeginDisabled(getSettings().game.speedrunMode);
|
||||
|
||||
ImGui::SeparatorText("Resources");
|
||||
config::ImGuiCheckbox("Infinite Hearts", getSettings().game.infiniteHearts);
|
||||
config::ImGuiCheckbox("Infinite Arrows", getSettings().game.infiniteArrows);
|
||||
config::ImGuiCheckbox("Infinite Bombs", getSettings().game.infiniteBombs);
|
||||
config::ImGuiCheckbox("Infinite Oil", getSettings().game.infiniteOil);
|
||||
config::ImGuiCheckbox("Infinite Oxygen", getSettings().game.infiniteOxygen);
|
||||
config::ImGuiCheckbox("Infinite Rupees", getSettings().game.infiniteRupees);
|
||||
config::ImGuiCheckbox("No Item Timer", getSettings().game.enableIndefiniteItemDrops);
|
||||
ImGui::SetItemTooltip("Item drops such as Rupees, Hearts, etc. will never disappear after they drop.");
|
||||
|
||||
ImGui::SeparatorText("Abilities");
|
||||
config::ImGuiCheckbox("Moon Jump (R+A)", getSettings().game.moonJump);
|
||||
config::ImGuiCheckbox("Super Clawshot", getSettings().game.superClawshot);
|
||||
config::ImGuiCheckbox("Always Greatspin", getSettings().game.alwaysGreatspin);
|
||||
config::ImGuiCheckbox("Fast Iron Boots", getSettings().game.enableFastIronBoots);
|
||||
|
||||
config::ImGuiCheckbox("Can Transform Anywhere", getSettings().game.canTransformAnywhere);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Allows you to transform even if NPCs are looking.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Fast Spinner", getSettings().game.fastSpinner);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Speeds up Spinner movement when holding R.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Free Magic Armor", getSettings().game.freeMagicArmor);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Makes the magic armor work without rupees.");
|
||||
}
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawAudioMenu() {
|
||||
if (ImGui::BeginMenu("Audio")) {
|
||||
|
||||
ImGui::SeparatorText("Volume");
|
||||
|
||||
ImGui::Text("Master Volume");
|
||||
if (config::ImGuiSliderInt("##masterVolume", getSettings().audio.masterVolume, 0, 100)) {
|
||||
dusk::audio::SetMasterVolume(getSettings().audio.masterVolume / 100.0f);
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: Implement additional settings
|
||||
ImGui::Text("Main Music Volume");
|
||||
ImGui::SliderFloat("##mainMusicVolume", &getSettings().audio.mainMusicVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Sub Music Volume");
|
||||
ImGui::SliderFloat("##subMusicVolume", &getSettings().audio.subMusicVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Sound Effects Volume");
|
||||
ImGui::SliderFloat("##soundEffectsVolume", &getSettings().audio.soundEffectsVolume, 0, 100);
|
||||
|
||||
ImGui::Text("Fanfare Volume");
|
||||
ImGui::SliderFloat("##fanfareVolume", &getSettings().audio.fanfareVolume, 0, 100);
|
||||
|
||||
Z2AudioMgr* audioMgr = Z2AudioMgr::getInterface();
|
||||
if (audioMgr != nullptr) {
|
||||
}
|
||||
*/
|
||||
|
||||
ImGui::SeparatorText("Effects");
|
||||
|
||||
if (config::ImGuiCheckbox("Enable Reverb", getSettings().audio.enableReverb)) {
|
||||
dusk::audio::SetEnableReverb(getSettings().audio.enableReverb);
|
||||
}
|
||||
|
||||
|
||||
ImGui::SeparatorText("Tweaks");
|
||||
|
||||
config::ImGuiCheckbox("No Low HP Sound", getSettings().game.noLowHpSound);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Disable the beeping sound when having low health.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Non-Stop Midna's Lament", getSettings().game.midnasLamentNonStop);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Prevents enemy music while Midna's Lament is playing.");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawInputMenu() {
|
||||
if (ImGui::BeginMenu("Input")) {
|
||||
ImGui::SeparatorText("Controller");
|
||||
|
||||
if (ImGui::Button("Configure Controller")){
|
||||
m_showControllerConfig = !m_showControllerConfig;
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Camera");
|
||||
|
||||
config::ImGuiCheckbox("Free Camera", getSettings().game.freeCamera);
|
||||
|
||||
if (getSettings().game.freeCamera) {
|
||||
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
|
||||
config::ImGuiCheckbox("Invert Camera Y Axis", getSettings().game.invertCameraYAxis);
|
||||
config::ImGuiSliderFloat("Free Camera Sensitivity", getSettings().game.freeCameraSensitivity, 0.5f, 2.0f, "%.1f");
|
||||
} else {
|
||||
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Gyro");
|
||||
|
||||
config::ImGuiCheckbox("Gyro Aim", getSettings().game.enableGyroAim);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables the gyroscope on supported controllers\n"
|
||||
"while in look mode (C-Up) and while aiming the\n"
|
||||
"Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s),\n"
|
||||
"Ball and Chain, and Dominion Rod.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Gyro Rollgoal", getSettings().game.enableGyroRollgoal);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables the gyroscope on supported controllers to\n"
|
||||
"tilt the Rollgoal table in Hena's Cabin.");
|
||||
}
|
||||
|
||||
if (getSettings().game.enableGyroAim || getSettings().game.enableGyroRollgoal) {
|
||||
config::ImGuiSliderFloat("Gyro Pitch Sensitivity", getSettings().game.gyroSensitivityY, 0.25f, 4.0f, "%.2f");
|
||||
config::ImGuiSliderFloat("Gyro Yaw Sensitivity", getSettings().game.gyroSensitivityX, 0.25f, 4.0f, "%.2f");
|
||||
|
||||
if (getSettings().game.enableGyroRollgoal) {
|
||||
config::ImGuiSliderFloat("Rollgoal Sensitivity", getSettings().game.gyroSensitivityRollgoal, 0.25f, 4.0f, "%.2f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Additional multiplier for scaling how strongly\n"
|
||||
"the gyroscope affects the Rollgoal table.");
|
||||
}
|
||||
}
|
||||
|
||||
config::ImGuiSliderFloat("Gyro Deadband", getSettings().game.gyroDeadband, 0.0f, 0.5f, "%.3f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Angular rates below this magnitude are treated as zero,\n"
|
||||
"reducing drift and jitter when the controller is still.");
|
||||
}
|
||||
|
||||
config::ImGuiSliderFloat("Gyro Smoothing", getSettings().game.gyroSmoothing, 0.0f, 1.0f, "%.2f");
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Low values track raw gyro input more closely,\n"
|
||||
"while higher values smooth out input over time.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Invert Gyro Pitch", getSettings().game.gyroInvertPitch);
|
||||
config::ImGuiCheckbox("Invert Gyro Yaw", getSettings().game.gyroInvertYaw);
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Tools");
|
||||
|
||||
ImGui::BeginDisabled(getSettings().game.speedrunMode);
|
||||
config::ImGuiCheckbox("Turbo Key", getSettings().game.enableTurboKeybind);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Hold TAB to increase game speed by up to 4x.");
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::Checkbox("Show Input Viewer", &m_showInputViewer);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::drawInterfaceMenu() {
|
||||
if (ImGui::BeginMenu("Interface")) {
|
||||
config::ImGuiCheckbox("Achievement Notifications", getSettings().game.enableAchievementNotifications);
|
||||
config::ImGuiCheckbox("Skip Pre-Launch UI", getSettings().backend.skipPreLaunchUI);
|
||||
config::ImGuiCheckbox("Show Pipeline Compilation", getSettings().backend.showPipelineCompilation);
|
||||
#if DUSK_ENABLE_SENTRY_NATIVE
|
||||
config::ImGuiCheckbox("Enable Crash Reporting", getSettings().backend.enableCrashReporting);
|
||||
#endif
|
||||
if (!IsMobile) {
|
||||
config::ImGuiCheckbox("Pause on Focus Lost", getSettings().game.pauseOnFocusLost);
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
static void drawVirtualStick(const char* id, const ImVec2& stick) {
|
||||
float scale = ImGuiScale();
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 45 * scale, ImGui::GetCursorPos().y + 10));
|
||||
|
||||
@@ -55,6 +55,13 @@ namespace dusk {
|
||||
static void resetForSpeedrunMode();
|
||||
|
||||
private:
|
||||
void drawAudioMenu();
|
||||
void drawInputMenu();
|
||||
void drawGraphicsMenu();
|
||||
void drawGameplayMenu();
|
||||
void drawCheatsMenu();
|
||||
void drawInterfaceMenu();
|
||||
|
||||
struct {
|
||||
int m_selectedPort = 0;
|
||||
bool m_isReading = false;
|
||||
|
||||
@@ -41,10 +41,6 @@ static void OpenDataFolder() {
|
||||
#define DUSK_CAN_OPEN_DATA_FOLDER 0
|
||||
#endif
|
||||
|
||||
namespace aurora::gx {
|
||||
extern bool enableLodBias;
|
||||
}
|
||||
|
||||
namespace dusk {
|
||||
ImGuiMenuTools::ImGuiMenuTools() {}
|
||||
|
||||
@@ -95,7 +91,6 @@ namespace dusk {
|
||||
getSettings().game.disableWaterRefraction.setValue(disableWaterRefraction);
|
||||
config::Save();
|
||||
}
|
||||
ImGui::Checkbox("Enable LOD Bias", &aurora::gx::enableLodBias);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -124,6 +119,7 @@ namespace dusk {
|
||||
ImGui::MenuItem("Audio Debug", hotkeys::SHOW_AUDIO_DEBUG, &m_showAudioDebug);
|
||||
ImGui::MenuItem("Bloom", nullptr, &m_showBloomWindow);
|
||||
ImGui::MenuItem("Stub Log", nullptr, &m_showStubLog);
|
||||
ImGui::MenuItem("Actor Spawner", nullptr, &m_showActorSpawner);
|
||||
|
||||
if (!dusk::IsGameLaunched) {
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace dusk {
|
||||
void ShowStateShare();
|
||||
void ShowAchievements();
|
||||
void notifyAchievement(std::string name);
|
||||
void ShowActorSpawner();
|
||||
|
||||
private:
|
||||
bool m_showDebugOverlay = false;
|
||||
@@ -71,6 +72,8 @@ namespace dusk {
|
||||
|
||||
bool m_showAchievements = false;
|
||||
ImGuiAchievements m_achievementsWindow;
|
||||
|
||||
bool m_showActorSpawner = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "d/actor/d_a_player.h"
|
||||
|
||||
#include <map>
|
||||
#include <bit>
|
||||
|
||||
namespace dusk {
|
||||
enum ItemType {
|
||||
@@ -1296,33 +1295,8 @@ namespace dusk {
|
||||
membit.offDungeonItem(flag);
|
||||
}
|
||||
}
|
||||
|
||||
static void genCommonAreaFlags(dSv_memBit_c& membit) {
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f);
|
||||
|
||||
genDungeonItemCheckbox(membit, "Got Map", dSv_memBit_c::MAP);
|
||||
ImGui::SameLine(230.0f);
|
||||
genDungeonItemCheckbox(membit, "Got Compass", dSv_memBit_c::COMPASS);
|
||||
|
||||
genDungeonItemCheckbox(membit, "Got Boss Key", dSv_memBit_c::BOSS_KEY);
|
||||
ImGui::SameLine(230.0f);
|
||||
genDungeonItemCheckbox(membit, "Saw Boss Demo", dSv_memBit_c::STAGE_BOSS_DEMO);
|
||||
|
||||
genDungeonItemCheckbox(membit, "Got Heart Container", dSv_memBit_c::STAGE_LIFE);
|
||||
ImGui::SameLine(230.0f);
|
||||
genDungeonItemCheckbox(membit, "Defeated Boss", dSv_memBit_c::STAGE_BOSS_ENEMY);
|
||||
|
||||
genDungeonItemCheckbox(membit, "Defeated Miniboss", dSv_memBit_c::STAGE_BOSS_ENEMY_2);
|
||||
ImGui::SameLine(230.0f);
|
||||
genDungeonItemCheckbox(membit, "Got Ooccoo", dSv_memBit_c::OOCCOO_NOTE);
|
||||
|
||||
int keyTemp = membit.getKeyNum();
|
||||
if (ImGui::SliderInt("Keys", &keyTemp, 0, 5)) {
|
||||
membit.setKeyNum(keyTemp);
|
||||
}
|
||||
}
|
||||
|
||||
static void genMembitFlags(const char* id, dSv_memBit_c& membit) {
|
||||
void genMembitFlags(const char* id, dSv_memBit_c& membit) {
|
||||
ImGuiBeginGroupPanel("Chest", { 100, 100 });
|
||||
for (int j = 0; j < 2; j++) {
|
||||
drawFlagList(fmt::format("##_tbox{}", j).c_str(), membit.mTbox[j]);
|
||||
@@ -1348,10 +1322,29 @@ namespace dusk {
|
||||
drawFlagList(fmt::format("##_item{}", j).c_str(), membit.mItem[j]);
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
ImVec2 post_item_custor = ImGui::GetCursorPos();
|
||||
|
||||
ImGui::SetCursorPos({post_item_custor.x, post_switch_cursor.y});
|
||||
// genCommonAreaFlags(membit);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.0f);
|
||||
|
||||
genDungeonItemCheckbox(membit, "Got Map", dSv_memBit_c::MAP);
|
||||
ImGui::SameLine(230.0f);
|
||||
genDungeonItemCheckbox(membit, "Got Compass", dSv_memBit_c::COMPASS);
|
||||
|
||||
genDungeonItemCheckbox(membit, "Got Boss Key", dSv_memBit_c::BOSS_KEY);
|
||||
ImGui::SameLine(230.0f);
|
||||
genDungeonItemCheckbox(membit, "Saw Boss Demo", dSv_memBit_c::STAGE_BOSS_DEMO);
|
||||
|
||||
genDungeonItemCheckbox(membit, "Got Heart Container", dSv_memBit_c::STAGE_LIFE);
|
||||
ImGui::SameLine(230.0f);
|
||||
genDungeonItemCheckbox(membit, "Defeated Boss", dSv_memBit_c::STAGE_BOSS_ENEMY);
|
||||
|
||||
genDungeonItemCheckbox(membit, "Defeated Miniboss", dSv_memBit_c::STAGE_BOSS_ENEMY_2);
|
||||
ImGui::SameLine(230.0f);
|
||||
genDungeonItemCheckbox(membit, "Got Ooccoo", dSv_memBit_c::OOCCOO_NOTE);
|
||||
|
||||
int keyTemp = membit.getKeyNum();
|
||||
if (ImGui::SliderInt("Keys", &keyTemp, 0, 5)) {
|
||||
membit.setKeyNum(keyTemp);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -1399,326 +1392,74 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void genAreaFlagTable(uint8_t areaIndex, dSv_memBit_c& membit) {
|
||||
constexpr auto makeMask = [](uint8_t size) -> uint16_t { return (1 << size) - 1; };
|
||||
constexpr auto getByteIndexFromFlag = [](uint16_t f) -> uint8_t { return f >> 8; };
|
||||
constexpr auto getBitMaskFromFlag = [](uint16_t f) -> uint8_t { return f & 0xff; };
|
||||
constexpr auto getValueSize = [getBitMaskFromFlag](uint16_t f) -> uint8_t {
|
||||
return std::popcount(getBitMaskFromFlag(f));
|
||||
};
|
||||
|
||||
constexpr auto makeEventFlag = [](uint8_t byteIndex, uint8_t bitIndices) -> uint16_t {
|
||||
return (byteIndex << 8) | bitIndices;
|
||||
};
|
||||
|
||||
const auto eventFlagToAreaFlag = [&](uint16_t areaFlag) -> int {
|
||||
auto byteInd = getByteIndexFromFlag(areaFlag);
|
||||
constexpr size_t areaIndexSize = 5;
|
||||
// if we're looking at 0x580, that would be byte 5, and check if 0x80 is set on that byte
|
||||
// the event flags are structured differently than area flags
|
||||
// B is byte index, b is the flag mask to check
|
||||
// event flags are BBBBBBBB bbbbbbbb
|
||||
// for area flags, they check bitIndex, not mask, i is index
|
||||
// also area uses u32 index, not byte index
|
||||
// area flags are BBBiiiii
|
||||
// so we need to convert from bit mask to index
|
||||
// also our byte index has to become a u32 index
|
||||
|
||||
// dividing byte index by sizeof(u32) gets us the u32 index
|
||||
// but in big endian, the first byte is the highest order byte of the u32
|
||||
// so we skip 24 bytes for the first byte, 16 for the second, etc
|
||||
// essentially (3 - (x % 4)), reversing the modulus, 0=3, 1=2
|
||||
auto bitsToSkip = 8 * ((sizeof(u32) - 1) - (byteInd % sizeof(u32)));
|
||||
return ((byteInd / sizeof(u32)) << areaIndexSize) | ((std::countr_zero(areaFlag) + bitsToSkip) & makeMask(areaIndexSize));
|
||||
};
|
||||
|
||||
constexpr uint8_t validTbox = sizeof(membit.mTbox);
|
||||
constexpr uint8_t validSwitch = validTbox + sizeof(membit.mSwitch);
|
||||
constexpr uint8_t validItem = validSwitch + sizeof(membit.mItem);
|
||||
constexpr uint16_t tboxConvert = 0;
|
||||
constexpr uint16_t switchConvert = sizeof(membit.mTbox) << 8;
|
||||
constexpr uint16_t itemConvert = switchConvert + (sizeof(membit.mItem) << 8);
|
||||
|
||||
const auto LoadFlag = [&](uint16_t flag) -> bool {
|
||||
const auto byteIndex = getByteIndexFromFlag(flag);
|
||||
|
||||
if (byteIndex < validTbox) {
|
||||
return membit.isTbox(eventFlagToAreaFlag(flag - tboxConvert));
|
||||
} else if (byteIndex < validSwitch) {
|
||||
return membit.isSwitch(eventFlagToAreaFlag(flag - switchConvert));
|
||||
} else if (byteIndex < validItem) {
|
||||
return membit.isItem(eventFlagToAreaFlag(flag - itemConvert));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto SetFlag = [&](uint16_t flag, bool set) -> void {
|
||||
const auto byteIndex = getByteIndexFromFlag(flag);
|
||||
if (set) {
|
||||
if (byteIndex < validTbox) {
|
||||
membit.onTbox(eventFlagToAreaFlag(flag - tboxConvert));
|
||||
} else if (byteIndex < validSwitch) {
|
||||
membit.onSwitch(eventFlagToAreaFlag(flag - switchConvert));
|
||||
} else if (byteIndex < validItem) {
|
||||
membit.onItem(eventFlagToAreaFlag(flag - itemConvert));
|
||||
}
|
||||
} else {
|
||||
if (byteIndex < validTbox) {
|
||||
membit.offTbox(eventFlagToAreaFlag(flag - tboxConvert));
|
||||
} else if (byteIndex < validSwitch) {
|
||||
membit.offSwitch(eventFlagToAreaFlag(flag - switchConvert));
|
||||
} else if (byteIndex < validItem) {
|
||||
membit.offItem(eventFlagToAreaFlag(flag - itemConvert));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const auto LoadMultiByteFlag = [&](uint16_t flag) -> uint8_t {
|
||||
const auto bitInds = getBitMaskFromFlag(flag);
|
||||
const auto byteIndex = getByteIndexFromFlag(flag);
|
||||
|
||||
const uint16_t startingMask = std::bit_floor(bitInds);
|
||||
uint8_t val = 0;
|
||||
for (uint16_t bitIndexMask = startingMask; (bitInds & bitIndexMask) != 0;
|
||||
bitIndexMask >>= 1)
|
||||
{
|
||||
val <<= 1;
|
||||
if (LoadFlag(makeEventFlag(byteIndex, bitInds & bitIndexMask))) {
|
||||
val |= 1;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
const auto SetMultiByteFlag = [&](uint16_t flag, uint8_t val) -> void {
|
||||
const auto bitInds = getBitMaskFromFlag(flag);
|
||||
const auto byteIndex = getByteIndexFromFlag(flag);
|
||||
|
||||
const uint16_t startingMask = std::bit_floor(bitInds);
|
||||
uint16_t valueMask = 1 << (getValueSize(flag) - 1);
|
||||
|
||||
for (uint16_t bitIndexMask = startingMask; (bitInds & bitIndexMask) != 0;
|
||||
bitIndexMask >>= 1, valueMask >>= 1)
|
||||
{
|
||||
SetFlag(makeEventFlag(byteIndex, bitInds & bitIndexMask), (val & valueMask) != 0);
|
||||
}
|
||||
};
|
||||
|
||||
const auto LoadSpreadMultiByte = [&](uint16_t high, uint16_t low) -> uint8_t {
|
||||
if (low == AREA_FLAG_NONE)
|
||||
return LoadMultiByteFlag(high);
|
||||
return (LoadMultiByteFlag(high) << getValueSize(low)) | LoadMultiByteFlag(low);
|
||||
};
|
||||
|
||||
const auto SetSpreadMultiByte = [&](uint16_t high, uint16_t low, uint8_t value) -> void {
|
||||
if (low == AREA_FLAG_NONE)
|
||||
return SetMultiByteFlag(high, value);
|
||||
const auto lowerSize = getValueSize(low);
|
||||
SetMultiByteFlag(high, value >> lowerSize);
|
||||
SetMultiByteFlag(low, value & makeMask(lowerSize));
|
||||
};
|
||||
|
||||
auto iter = imguiAreaFlagLookup.find(areaIndex);
|
||||
if (iter == imguiAreaFlagLookup.end()) return;
|
||||
|
||||
auto& areaFlags = iter->second;
|
||||
|
||||
static ImGuiTextFilter filter;
|
||||
filter.Draw(); // Search bar
|
||||
|
||||
ImVec2 flagTableSize = {700, 400};
|
||||
if (ImGui::BeginTable("Area Flags", 3,
|
||||
ImGuiTableFlags_ScrollY | ImGuiTableFlags_ScrollX |
|
||||
ImGuiTableFlags_Sortable,
|
||||
flagTableSize))
|
||||
{
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
constexpr int COLUMN_FLAG = 0, COLUMN_BIT = 1, COLUMN_DESC = 2;
|
||||
ImGui::TableSetupColumn("Flag");
|
||||
ImGui::TableSetupColumn("Byte:Bit");
|
||||
ImGui::TableSetupColumn("Description");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
// if we're sorting by whether the flag is set or not,
|
||||
// we want to re-sort whenever a flag updates, which means every frame cuz we don't
|
||||
// know when it changes. otherwise only re-sort when the sort is dirty
|
||||
if (auto* sort = ImGui::TableGetSortSpecs();
|
||||
sort != nullptr && sort->SpecsCount > 0 &&
|
||||
(sort->SpecsDirty || sort->Specs[0].ColumnIndex == COLUMN_FLAG))
|
||||
{
|
||||
const auto column = sort->Specs[0].ColumnIndex;
|
||||
const auto direction = sort->Specs[0].SortDirection;
|
||||
|
||||
// if we're sorting by flags, do special sort, regular sort is bad for sorting
|
||||
// bools it can swap values that are the same, and that causes constant
|
||||
// reordering
|
||||
if (column == COLUMN_FLAG) {
|
||||
if (direction == ImGuiSortDirection_Ascending) {
|
||||
sortByFlags(std::begin(areaFlags.bitFlags), std::end(areaFlags.bitFlags),
|
||||
LoadFlag);
|
||||
} else {
|
||||
sortByFlags(std::rbegin(areaFlags.bitFlags), std::rend(areaFlags.bitFlags),
|
||||
LoadFlag);
|
||||
}
|
||||
} else {
|
||||
const auto cmp = [column](const EventAreaFlags& l,
|
||||
const EventAreaFlags& r) -> bool {
|
||||
switch (column) {
|
||||
case COLUMN_DESC:
|
||||
return l.description < r.description;
|
||||
case COLUMN_BIT:
|
||||
return l.flagID < r.flagID;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (direction == ImGuiSortDirection_Ascending) {
|
||||
std::sort(std::begin(areaFlags.bitFlags), std::end(areaFlags.bitFlags),
|
||||
cmp);
|
||||
} else {
|
||||
std::sort(std::rbegin(areaFlags.bitFlags), std::rend(areaFlags.bitFlags),
|
||||
cmp);
|
||||
}
|
||||
}
|
||||
|
||||
sort->SpecsDirty = false;
|
||||
}
|
||||
|
||||
for (const auto& e : areaFlags.bitFlags) {
|
||||
std::string formattedBitLocation =
|
||||
fmt::format("{0:02X}:{1:02X}", e.byteIndex, e.bitIndex);
|
||||
|
||||
if (!filter.PassFilter(e.description.c_str()) &&
|
||||
!filter.PassFilter(formattedBitLocation.c_str()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
bool flag = LoadFlag(e.flagID);
|
||||
if (ImGui::Checkbox(fmt::format("##_unused_area_flag_{}", e.flagID).c_str(), &flag)) {
|
||||
SetFlag(e.flagID, flag);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(formattedBitLocation.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(e.description.c_str());
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
for (const auto& multiByteFlag : areaFlags.multibyteFlags) {
|
||||
auto flagValue = LoadSpreadMultiByte(multiByteFlag.highOrderflag, multiByteFlag.lowOrderflag);
|
||||
|
||||
const char* currentVal = "UNKNOWN";
|
||||
|
||||
auto enumValIter = multiByteFlag.enumValues.find(flagValue);
|
||||
if (enumValIter != multiByteFlag.enumValues.end()) {
|
||||
currentVal = enumValIter->second;
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo(multiByteFlag.name, currentVal)) {
|
||||
for (const auto& [val, name] : multiByteFlag.enumValues) {
|
||||
if (ImGui::Selectable(name)) {
|
||||
SetSpreadMultiByte(multiByteFlag.highOrderflag, multiByteFlag.lowOrderflag, val);
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
genCommonAreaFlags(membit);
|
||||
}
|
||||
|
||||
static void drawCurrentRegionFlags()
|
||||
{
|
||||
dSv_memBit_c& membit = g_dComIfG_gameInfo.info.mMemory.mBit;
|
||||
auto* stageData = dComIfGp_getStageStagInfo();
|
||||
if (!stageData)
|
||||
return;
|
||||
uint8_t stageIndex = dStage_stagInfo_GetSaveTbl(stageData);
|
||||
|
||||
genAreaFlagTable(stageIndex, membit);
|
||||
|
||||
if (ImGui::TreeNode("Flag Matrix")) {
|
||||
genMembitFlags("##TempSceneFlags", membit);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
stage_stag_info_class* pstag = dComIfGp_getStageStagInfo();
|
||||
if (pstag != nullptr) {
|
||||
int stageNo = dStage_stagInfo_GetSaveTbl(pstag);
|
||||
if (ImGui::Button("Save##SaveTempFlags")) {
|
||||
dComIfGs_putSave(stageNo);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Load##LoadSaveFlags")) {
|
||||
dComIfGs_getSave(stageNo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawFlagsTab() {
|
||||
if (ImGui::TreeNode("Current Region Flags")) {
|
||||
drawCurrentRegionFlags();
|
||||
dSv_memBit_c& membit = g_dComIfG_gameInfo.info.mMemory.mBit;
|
||||
genMembitFlags("##TempSceneFlags", membit);
|
||||
|
||||
stage_stag_info_class* pstag = dComIfGp_getStageStagInfo();
|
||||
if (pstag != nullptr) {
|
||||
int stageNo = dStage_stagInfo_GetSaveTbl(pstag);
|
||||
if (ImGui::Button("Save##SaveTempFlags")) {
|
||||
dComIfGs_putSave(stageNo);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Load##LoadSaveFlags")) {
|
||||
dComIfGs_getSave(stageNo);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Region Saved Flags")) {
|
||||
static const std::map<uint8_t, const char*> regionNames = {
|
||||
{ 0x00, "Ordon" },
|
||||
{ 0x01, "Hyrule Sewers" },
|
||||
{ 0x02, "Faron" },
|
||||
{ 0x03, "Eldin" },
|
||||
{ 0x04, "Lanayru" },
|
||||
{ 0x06, "Hyrule Field" },
|
||||
{ 0x07, "Sacred Grove" },
|
||||
{ 0x08, "Snowpeak" },
|
||||
{ 0x09, "Castle Town" },
|
||||
{ 0x0A, "Gerudo Desert" },
|
||||
{ 0x0B, "Fishing Pond" },
|
||||
{ 0x10, "Forest Temple" },
|
||||
{ 0x11, "Goron Mines" },
|
||||
{ 0x12, "Lakebed Temple" },
|
||||
{ 0x13, "Arbiter's Grounds" },
|
||||
{ 0x14, "Snowpeak Ruins" },
|
||||
{ 0x15, "Temple of Time" },
|
||||
{ 0x16, "City in the Sky" },
|
||||
{ 0x17, "Palace of Twilight" },
|
||||
{ 0x18, "Hyrule Castle" },
|
||||
{ 0x19, "Caves" },
|
||||
{ 0x1A, "Lake Hylia Long Cave"},
|
||||
{ 0x1B, "Grottos" }
|
||||
static std::array<const char*, 27> regionNames = {
|
||||
"Ordon",
|
||||
"Hyrule Sewers",
|
||||
"Faron",
|
||||
"Eldin",
|
||||
"Lanayru",
|
||||
"Reserved",
|
||||
"Hyrule Field",
|
||||
"Sacred Grove",
|
||||
"Snowpeak",
|
||||
"Castle Town",
|
||||
"Gerudo Desert",
|
||||
"Fishing Pond",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Reserved",
|
||||
"Forest Temple",
|
||||
"Goron Mines",
|
||||
"Lakebed Temple",
|
||||
"Arbiter's Grounds",
|
||||
"Snowpeak Ruins",
|
||||
"Temple of Time",
|
||||
"City in the Sky",
|
||||
"Palace of Twilight",
|
||||
"Hyrule Castle",
|
||||
"Caves",
|
||||
"Grottos",
|
||||
};
|
||||
|
||||
if (m_selectedRegion.name == nullptr)
|
||||
{
|
||||
const auto& firstRegion = *regionNames.find(0);
|
||||
m_selectedRegion = { firstRegion.first, firstRegion.second };
|
||||
}
|
||||
if (ImGui::BeginCombo("Region", regionNames[m_selectedRegion])) {
|
||||
for (int i = 0; i < regionNames.size(); i++) {
|
||||
if (strcmp(regionNames[i], "Reserved") == 0) continue;
|
||||
|
||||
if (ImGui::BeginCombo("Region", m_selectedRegion.name)) {
|
||||
for (const auto& [id, name] : regionNames) {
|
||||
if (ImGui::Selectable(name)) {
|
||||
m_selectedRegion = {id, name};
|
||||
if (ImGui::Selectable(regionNames[i])) {
|
||||
m_selectedRegion = i;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
dSv_memBit_c& membit = dComIfGs_getSaveData()->mSave[m_selectedRegion.id].mBit;
|
||||
|
||||
genAreaFlagTable(m_selectedRegion.id, membit);
|
||||
|
||||
if (ImGui::TreeNode("Flag Matrix")) {
|
||||
genMembitFlags("##SaveSceneFlags", membit);
|
||||
|
||||
ImGui::TreePop();
|
||||
dSv_memBit_c* membit = &dComIfGs_getSaveData()->mSave[m_selectedRegion].mBit;
|
||||
if (membit != nullptr) {
|
||||
genMembitFlags("##SaveSceneFlags", *membit);
|
||||
}
|
||||
|
||||
ImGui::TreePop();
|
||||
@@ -1789,9 +1530,7 @@ namespace dusk {
|
||||
}
|
||||
|
||||
for (const auto& e : duskImguiEventFlags) {
|
||||
if (!filter.PassFilter(e.location.c_str()) &&
|
||||
!filter.PassFilter(e.description.c_str()) &&
|
||||
!filter.PassFilter(e.flagName.c_str()))
|
||||
if (!filter.PassFilter((e.location + "\n" + e.description + "\n" + e.flagName).c_str()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -21,10 +21,7 @@ namespace dusk {
|
||||
void drawConfigTab();
|
||||
|
||||
private:
|
||||
struct {
|
||||
uint8_t id;
|
||||
const char* name;
|
||||
} m_selectedRegion = {0, nullptr};
|
||||
int m_selectedRegion = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -101,10 +101,6 @@ ValidationError validate(const char* path) {
|
||||
NodHandleWrapper disc;
|
||||
|
||||
const auto sdlStream = SDL_IOFromFile(path, "rb");
|
||||
if (sdlStream == nullptr) {
|
||||
return ValidationError::IOError;
|
||||
}
|
||||
|
||||
const NodDiscStream nod_stream {
|
||||
.user_data = sdlStream,
|
||||
.read_at = StreamReadAt,
|
||||
|
||||
+21
-48
@@ -1,6 +1,5 @@
|
||||
#include "dusk/logging.h"
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
@@ -33,33 +32,9 @@ static constexpr std::string_view StubFragments[] = {
|
||||
};
|
||||
|
||||
namespace {
|
||||
// On macOS, std::mutex becomes poisoned when its dtor is run.
|
||||
// We use this to check if the LogState is destroyed before attempting to acquire it.
|
||||
std::atomic g_logStateAlive(true);
|
||||
|
||||
struct LogState {
|
||||
std::mutex mutex;
|
||||
FILE* file = nullptr;
|
||||
std::string filePath;
|
||||
|
||||
~LogState() {
|
||||
CloseFile();
|
||||
g_logStateAlive.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
void CloseFile() {
|
||||
if (!g_logStateAlive.load(std::memory_order_acquire)) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard lock(mutex);
|
||||
if (file != nullptr) {
|
||||
std::fflush(file);
|
||||
std::fclose(file);
|
||||
file = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
LogState g_logState;
|
||||
std::mutex g_logMutex;
|
||||
FILE* g_logFile = nullptr;
|
||||
std::string g_logFilePath;
|
||||
|
||||
const char* LogLevelString(AuroraLogLevel level) {
|
||||
switch (level) {
|
||||
@@ -177,10 +152,10 @@ void aurora_log_callback(AuroraLogLevel level, const char* module, const char* m
|
||||
FILE* out = LogStreamForLevel(level);
|
||||
WriteLogLine(out, levelStr, module, message, len);
|
||||
|
||||
if (g_logStateAlive.load(std::memory_order_acquire)) {
|
||||
std::lock_guard lock(g_logState.mutex);
|
||||
if (g_logState.file != nullptr) {
|
||||
WriteLogLine(g_logState.file, levelStr, module, message, len);
|
||||
{
|
||||
std::lock_guard lock(g_logMutex);
|
||||
if (g_logFile != nullptr) {
|
||||
WriteLogLine(g_logFile, levelStr, module, message, len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,11 +169,8 @@ void aurora_log_callback(AuroraLogLevel level, const char* module, const char* m
|
||||
aurora::Module DuskLog("dusk");
|
||||
|
||||
void dusk::InitializeFileLogging(const std::filesystem::path& configDir, AuroraLogLevel logLevel) {
|
||||
if (!g_logStateAlive.load(std::memory_order_acquire)) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard lock(g_logState.mutex);
|
||||
if (g_logState.file != nullptr || configDir.empty()) {
|
||||
std::lock_guard lock(g_logMutex);
|
||||
if (g_logFile != nullptr || configDir.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -212,30 +184,31 @@ void dusk::InitializeFileLogging(const std::filesystem::path& configDir, AuroraL
|
||||
}
|
||||
|
||||
const std::filesystem::path logPath = logsDir / MakeTimestampedLogName();
|
||||
g_logState.file = std::fopen(logPath.string().c_str(), "wb");
|
||||
if (g_logState.file == nullptr) {
|
||||
g_logFile = std::fopen(logPath.string().c_str(), "wb");
|
||||
if (g_logFile == nullptr) {
|
||||
std::fprintf(stderr, "[WARNING | dusk] Failed to open log file '%s'\n",
|
||||
logPath.string().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
g_logState.filePath = logPath.string();
|
||||
g_logFilePath = logPath.string();
|
||||
aurora::g_config.logCallback = &aurora_log_callback;
|
||||
aurora::g_config.logLevel = logLevel;
|
||||
WriteLogLine(g_logState.file, "INFO", "dusk", "File logging initialized", 24);
|
||||
WriteLogLine(g_logFile, "INFO", "dusk", "File logging initialized", 24);
|
||||
}
|
||||
|
||||
void dusk::ShutdownFileLogging() {
|
||||
if (!g_logStateAlive.load(std::memory_order_acquire)) {
|
||||
std::lock_guard lock(g_logMutex);
|
||||
if (g_logFile == nullptr) {
|
||||
return;
|
||||
}
|
||||
g_logState.CloseFile();
|
||||
|
||||
std::fflush(g_logFile);
|
||||
std::fclose(g_logFile);
|
||||
g_logFile = nullptr;
|
||||
}
|
||||
|
||||
const char* dusk::GetLogFilePath() {
|
||||
if (!g_logStateAlive.load(std::memory_order_acquire)) {
|
||||
return nullptr;
|
||||
}
|
||||
std::lock_guard lock(g_logState.mutex);
|
||||
return g_logState.filePath.empty() ? nullptr : g_logState.filePath.c_str();
|
||||
std::lock_guard lock(g_logMutex);
|
||||
return g_logFilePath.empty() ? nullptr : g_logFilePath.c_str();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ UserSettings g_userSettings = {
|
||||
.soundEffectsVolume {"audio.soundEffectsVolume", 100},
|
||||
.fanfareVolume {"audio.fanfareVolume", 100},
|
||||
.enableReverb {"audio.enableReverb", true},
|
||||
.enableHrtf {"audio.enableHrtf", false},
|
||||
},
|
||||
|
||||
.game = {
|
||||
@@ -32,7 +31,7 @@ UserSettings g_userSettings = {
|
||||
.disableRupeeCutscenes {"game.disableRupeeCutscenes", false},
|
||||
.noSwordRecoil {"game.noSwordRecoil", false},
|
||||
.damageMultiplier {"game.damageMultiplier", 1},
|
||||
.noHeartDrops {"game.noHeartDrops", false},
|
||||
.noHeartDrops{"game.noHeartDrops", false},
|
||||
.instantDeath {"game.instantDeath", false},
|
||||
.fastClimbing {"game.fastClimbing", false},
|
||||
.noMissClimbing {"game.noMissClimbing", false},
|
||||
@@ -41,7 +40,6 @@ UserSettings g_userSettings = {
|
||||
.instantSaves {"game.instantSaves", false},
|
||||
.instantText {"game.instantText", false},
|
||||
.sunsSong {"game.sunsSong", false},
|
||||
.autoSave {"game.autoSave", false},
|
||||
|
||||
// Preferences
|
||||
.enableMirrorMode {"game.enableMirrorMode", false},
|
||||
@@ -54,7 +52,7 @@ UserSettings g_userSettings = {
|
||||
.bloomMode {"game.bloomMode", BloomMode::Classic},
|
||||
.bloomMultiplier {"game.bloomMultiplier", 1.0f},
|
||||
.disableWaterRefraction {"game.disableWaterRefraction", false},
|
||||
.enableFrameInterpolation {"game.enableFrameInterpolation", false},
|
||||
.enableFrameInterpolation = {"game.enableFrameInterpolation", false},
|
||||
.internalResolutionScale {"game.internalResolutionScale", 0},
|
||||
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
|
||||
.enableDepthOfField {"game.enableDepthOfField", true},
|
||||
@@ -135,7 +133,6 @@ void registerSettings() {
|
||||
Register(g_userSettings.audio.soundEffectsVolume);
|
||||
Register(g_userSettings.audio.fanfareVolume);
|
||||
Register(g_userSettings.audio.enableReverb);
|
||||
Register(g_userSettings.audio.enableHrtf);
|
||||
|
||||
// Game
|
||||
Register(g_userSettings.game.language);
|
||||
@@ -155,7 +152,6 @@ void registerSettings() {
|
||||
Register(g_userSettings.game.instantSaves);
|
||||
Register(g_userSettings.game.instantText);
|
||||
Register(g_userSettings.game.sunsSong);
|
||||
Register(g_userSettings.game.autoSave);
|
||||
Register(g_userSettings.game.enableMirrorMode);
|
||||
Register(g_userSettings.game.invertCameraXAxis);
|
||||
Register(g_userSettings.game.invertCameraYAxis);
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#include "bool_button.hpp"
|
||||
|
||||
namespace dusk::ui {
|
||||
|
||||
BoolButton::BoolButton(Rml::Element* parent, Props props)
|
||||
: BaseControlledSelectButton(parent, {std::move(props.key)}),
|
||||
mGetValue(std::move(props.getValue)), mSetValue(std::move(props.setValue)),
|
||||
mIsDisabled(std::move(props.isDisabled)), mIsModified(std::move(props.isModified)) {}
|
||||
|
||||
bool BoolButton::modified() const {
|
||||
if (mIsModified) {
|
||||
return mIsModified();
|
||||
}
|
||||
return BaseControlledSelectButton::modified();
|
||||
}
|
||||
|
||||
bool BoolButton::disabled() const {
|
||||
if (mIsDisabled) {
|
||||
return mIsDisabled();
|
||||
}
|
||||
return BaseControlledSelectButton::disabled();
|
||||
}
|
||||
|
||||
Rml::String BoolButton::format_value() {
|
||||
return mGetValue() ? "On" : "Off";
|
||||
}
|
||||
|
||||
bool BoolButton::handle_nav_command(NavCommand cmd) {
|
||||
if (cmd == NavCommand::Confirm || cmd == NavCommand::Left || cmd == NavCommand::Right) {
|
||||
mSetValue(!mGetValue());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace dusk::ui
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
#include "select_button.hpp"
|
||||
|
||||
namespace dusk::ui {
|
||||
|
||||
class BoolButton : public BaseControlledSelectButton {
|
||||
public:
|
||||
struct Props {
|
||||
Rml::String key;
|
||||
std::function<bool()> getValue;
|
||||
std::function<void(bool)> setValue;
|
||||
std::function<bool()> isDisabled;
|
||||
std::function<bool()> isModified;
|
||||
};
|
||||
|
||||
BoolButton(Rml::Element* parent, Props props);
|
||||
|
||||
bool modified() const override;
|
||||
bool disabled() const override;
|
||||
|
||||
protected:
|
||||
Rml::String format_value() override;
|
||||
bool handle_nav_command(NavCommand cmd) override;
|
||||
|
||||
private:
|
||||
std::function<int()> mGetValue;
|
||||
std::function<void(int)> mSetValue;
|
||||
std::function<bool()> mIsDisabled;
|
||||
std::function<bool()> mIsModified;
|
||||
};
|
||||
|
||||
} // namespace dusk::ui
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user