mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-09 12:37:18 -04:00
Merge branch 'main' of https://github.com/TakaRikka/dusk
This commit is contained in:
@@ -68,3 +68,6 @@ Pass the disc image as a positional argument. Supported formats: ISO (GCM), RVZ,
|
||||
build/dusk/dusk /path/to/game.rvz
|
||||
```
|
||||
If no path is specified, Dusk defaults to `game.iso` in the current working directory.
|
||||
|
||||
#### 30 FPS on Debug
|
||||
When compiled fully in a Debug the game runs too slowly to hit playable 30 FPS. To avoid this, you can set a CMake cache variable to optimize specific critical files without hampering debuggability in the rest of the program: `-DDUSK_SELECTED_OPT=ON`. When building for MSVC (Windows) you must also modify `CMAKE_CXX_FLAGS_DEBUG` and `CMAKE_C_FLAGS_DEBUG` to remove `/RTC1` from the flags, like so: `-DCMAKE_CXX_FLAGS_DEBUG="/MDd /Zi /Ob0 /Od" -DCMAKE_C_FLAGS_DEBUG="/MDd /Zi /Ob0 /Od"`
|
||||
|
||||
@@ -1348,6 +1348,7 @@ set(DUSK_FILES
|
||||
src/dusk/imgui/ImGuiControllerOverlay.cpp
|
||||
src/dusk/imgui/ImGuiStubLog.cpp
|
||||
src/dusk/imgui/ImGuiMapLoader.cpp
|
||||
src/dusk/imgui/ImGuiSaveEditor.cpp
|
||||
src/dusk/offset_ptr.cpp
|
||||
src/dusk/OSContext.cpp
|
||||
src/dusk/OSThread.cpp
|
||||
|
||||
@@ -163,7 +163,6 @@ public:
|
||||
u8 getTransformStatus() const { return mTransformStatus; }
|
||||
void setTransformStatus(u8 i_status) { mTransformStatus = i_status; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ BE(u16) mMaxLife;
|
||||
/* 0x02 */ BE(u16) mLife;
|
||||
/* 0x04 */ BE(u16) mRupee;
|
||||
@@ -201,7 +200,6 @@ public:
|
||||
u16 getDate() const { return mDate; }
|
||||
void setDate(u16 i_date) { mDate = i_date; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ BE(OSTime) mDateIpl;
|
||||
/* 0x08 */ u8 mTransformLevelFlag;
|
||||
/* 0x09 */ u8 mDarkClearLevelFlag;
|
||||
@@ -228,7 +226,6 @@ public:
|
||||
const char* getStageName() const { return mName; }
|
||||
s8 getRoomNo() const { return mRoomNo; }
|
||||
|
||||
private:
|
||||
#if TARGET_PC
|
||||
/* 0x00 */ BE(Vec) mPos;
|
||||
#else
|
||||
@@ -248,7 +245,6 @@ public:
|
||||
u8 getPlayerStatus() const { return mPlayerStatus; }
|
||||
s8 getRoomNo() const { return mRoomNo; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ char mName[8];
|
||||
/* 0x08 */ u8 mPlayerStatus;
|
||||
/* 0x09 */ s8 mRoomNo;
|
||||
@@ -277,8 +273,6 @@ public:
|
||||
void offFieldDataExistFlag() { mFieldDataExistFlag = false; }
|
||||
void onFieldDataExistFlag() { mFieldDataExistFlag = true; }
|
||||
|
||||
|
||||
private:
|
||||
#if TARGET_PC
|
||||
/* 0x00 */ BE(Vec) mPos;
|
||||
#else
|
||||
@@ -312,7 +306,6 @@ public:
|
||||
void setWarpAcceptStage(s8 accept) { mWarpAcceptStage = accept; }
|
||||
void resetWarpAcceptStage() { mWarpAcceptStage = -1; }
|
||||
|
||||
private:
|
||||
#if TARGET_PC
|
||||
/* 0x00 */ BE(Vec) mPos;
|
||||
#else
|
||||
@@ -356,7 +349,6 @@ public:
|
||||
static const int BOMB_BAG_MAX = 3;
|
||||
static const int BOTTLE_MAX = 4;
|
||||
|
||||
private:
|
||||
/* 0x00 */ u8 mItems[24];
|
||||
/* 0x18 */ u8 mItemSlots[24];
|
||||
}; // Size: 0x30
|
||||
@@ -368,7 +360,6 @@ public:
|
||||
void offFirstBit(u8 i_itemNo);
|
||||
int isFirstBit(u8 i_itemNo) const;
|
||||
|
||||
private:
|
||||
/* 0x0 */ BE(u32) mItemFlags[8];
|
||||
}; // Size: 0x20
|
||||
|
||||
@@ -386,7 +377,6 @@ public:
|
||||
u8 getPachinkoNum() const { return mPachinkoNum; }
|
||||
void setPachinkoNum(u8 i_num) { mPachinkoNum = i_num; }
|
||||
|
||||
private:
|
||||
/* 0x0 */ u8 mArrowNum;
|
||||
/* 0x1 */ u8 mBombNum[3];
|
||||
/* 0x4 */ u8 mBottleNum[4];
|
||||
@@ -403,7 +393,6 @@ public:
|
||||
u8 getArrowNum() const { return mItemMax[ARROW_MAX]; }
|
||||
void setArrowNum(u8 i_maxNum) { mItemMax[ARROW_MAX] = i_maxNum; }
|
||||
|
||||
private:
|
||||
/* 0x0 */ u8 mItemMax[8];
|
||||
}; // Size: 0x8
|
||||
|
||||
@@ -429,7 +418,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/* 0x0 */ u8 mItem[8];
|
||||
/* 0x8 */ u8 unk8;
|
||||
/* 0x9 */ u8 mCrystal;
|
||||
@@ -443,7 +431,6 @@ class dSv_player_wolf_c {
|
||||
public:
|
||||
void init();
|
||||
|
||||
private:
|
||||
/* 0x0 */ u8 unk0[3];
|
||||
/* 0x3 */ u8 unk3;
|
||||
}; // Size: 0x4
|
||||
@@ -457,7 +444,6 @@ public:
|
||||
void offLightDropGetFlag(u8 i_nowLevel);
|
||||
BOOL isLightDropGetFlag(u8 i_nowLevel) const;
|
||||
|
||||
private:
|
||||
/* 0x0 */ u8 mLightDropNum[4];
|
||||
/* 0x4 */ u8 mLightDropGetFlag;
|
||||
/* 0x5 */ u8 unk5[3];
|
||||
@@ -473,7 +459,6 @@ public:
|
||||
u8 getGetNumber(int i_no) { return mGetNumber[i_no]; }
|
||||
void setGetNumber(int i_no, u8 i_value) { mGetNumber[i_no] = i_value; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ BE(u32) mLetterGetFlags[2];
|
||||
/* 0x08 */ BE(u32) mLetterReadFlags[2];
|
||||
/* 0x10 */ u8 mGetNumber[64];
|
||||
@@ -487,7 +472,6 @@ public:
|
||||
u8 getMaxSize(int i_sizeIndex) const { return mMaxSize[i_sizeIndex]; }
|
||||
void setMaxSize(int i_sizeIndex, u8 i_size) { mMaxSize[i_sizeIndex] = i_size; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ BE(u16) mFishCount[16];
|
||||
/* 0x20 */ u8 mMaxSize[16];
|
||||
}; // Size: 0x34
|
||||
@@ -508,7 +492,6 @@ public:
|
||||
void setHorseName(const char* i_name) { strcpy(mHorseName, i_name); }
|
||||
u8 getClearCount() const { return mClearCount; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ BE(u64) unk0;
|
||||
/* 0x08 */ BE(s64) mTotalTime;
|
||||
/* 0x10 */ BE(u16) unk16;
|
||||
@@ -555,7 +538,6 @@ public:
|
||||
LANGUAGE_ITALIAN,
|
||||
};
|
||||
|
||||
private:
|
||||
/* 0x0 */ u8 mRuby;
|
||||
/* 0x1 */ u8 mSoundMode;
|
||||
/* 0x2 */ u8 mAttentionType; // Lock-On Type; 0 : hold, 1 : switch
|
||||
@@ -682,7 +664,6 @@ public:
|
||||
void offStageBossEnemy2() { offDungeonItem(STAGE_BOSS_ENEMY_2); }
|
||||
s32 isStageBossEnemy2() const { return isDungeonItem(STAGE_BOSS_ENEMY_2); }
|
||||
|
||||
private:
|
||||
/* 0x00 */ BE(u32) mTbox[2];
|
||||
/* 0x08 */ BE(u32) mSwitch[4];
|
||||
/* 0x18 */ BE(u32) mItem[1];
|
||||
@@ -701,7 +682,6 @@ public:
|
||||
|
||||
void* getPEventBit() { return (void*)mEvent; }
|
||||
|
||||
private:
|
||||
/* 0x0 */ u8 mEvent[256];
|
||||
}; // Size: 0x100
|
||||
|
||||
@@ -716,7 +696,6 @@ public:
|
||||
u32 getRaceGameTime() const { return mRaceGameTime; }
|
||||
void setRaceGameTime(u32 i_time) { mRaceGameTime = i_time; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ u8 unk0[1][4];
|
||||
/* 0x04 */ BE(u32) mHookGameTime;
|
||||
/* 0x08 */ BE(u32) mBalloonScore;
|
||||
@@ -732,7 +711,6 @@ public:
|
||||
dSv_memBit_c& getBit() { return mBit; }
|
||||
const dSv_memBit_c& getBit() const { return mBit; }
|
||||
|
||||
private:
|
||||
/* 0x0 */ dSv_memBit_c mBit;
|
||||
}; // Size: 0x20
|
||||
|
||||
@@ -746,7 +724,6 @@ public:
|
||||
void offVisitedRoom(int i_no);
|
||||
BOOL isVisitedRoom(int i_no);
|
||||
|
||||
private:
|
||||
/* 0x0 */ BE(u32) mVisitedRoom[2];
|
||||
}; // Size: 0x8
|
||||
|
||||
@@ -765,7 +742,6 @@ public:
|
||||
|
||||
void reset() { mStageNo = -1; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ s8 mStageNo;
|
||||
/* 0x01 */ u8 unk1;
|
||||
/* 0x04 */ u32 mSwitch[2];
|
||||
@@ -793,7 +769,6 @@ public:
|
||||
void offOneItem(int i_no);
|
||||
BOOL isOneItem(int i_no) const;
|
||||
|
||||
private:
|
||||
/* 0x00 */ BE(u16) mSwitch[2];
|
||||
/* 0x04 */ BE(u16) mRoomSwitch;
|
||||
/* 0x06 */ BE(u16) mItem[2];
|
||||
@@ -810,7 +785,6 @@ public:
|
||||
|
||||
static const int ACTOR_MAX = 0x80;
|
||||
|
||||
private:
|
||||
/* 0x00 */ u32 mActorFlags[4];
|
||||
}; // Size: 0x10
|
||||
|
||||
@@ -826,7 +800,6 @@ public:
|
||||
dSv_zoneActor_c& getActor() { return mActor; }
|
||||
const dSv_zoneActor_c& getActor() const { return mActor; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ s8 mRoomNo;
|
||||
/* 0x01 */ u8 unk1;
|
||||
/* 0x02 */ dSv_zoneBit_c mBit;
|
||||
@@ -855,7 +828,6 @@ public:
|
||||
mLastAngleY = angle;
|
||||
}
|
||||
|
||||
private:
|
||||
/* 0x00 */ s8 mRoomNo;
|
||||
/* 0x01 */ u8 field_0x01[3];
|
||||
/* 0x04 */ s16 mStartPoint;
|
||||
@@ -891,7 +863,6 @@ public:
|
||||
f32 getCameraFvy() const { return mCameraFvy; }
|
||||
void setCameraFvy(f32 i_fvy) { mCameraFvy = i_fvy; }
|
||||
|
||||
private:
|
||||
/* 0x00 */ cXyz mPosition;
|
||||
/* 0x0C */ u32 mParam;
|
||||
/* 0x10 */ s16 mAngleY;
|
||||
@@ -928,7 +899,6 @@ public:
|
||||
static const int STAGE_MAX = 32;
|
||||
static const int STAGE2_MAX = 64;
|
||||
|
||||
// private:
|
||||
/* 0x000 */ dSv_player_c mPlayer;
|
||||
/* 0x1F0 */ dSv_memory_c mSave[STAGE_MAX];
|
||||
/* 0x5F0 */ dSv_memory2_c mSave2[STAGE2_MAX];
|
||||
|
||||
+6
-47
@@ -14,43 +14,6 @@
|
||||
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
|
||||
// ============================================================================
|
||||
// Malloc-based allocator to bypass JKRHeap operator new/delete
|
||||
// Without this, side-table allocations call operator new -> JKRHeap::alloc
|
||||
// -> OSLockMutex -> GetMutexData -> operator new ... infinite recursion.
|
||||
// ============================================================================
|
||||
|
||||
template<typename T>
|
||||
struct MallocAllocator {
|
||||
using value_type = T;
|
||||
MallocAllocator() = default;
|
||||
template<typename U> MallocAllocator(const MallocAllocator<U>&) noexcept {}
|
||||
T* allocate(std::size_t n) {
|
||||
void* p = std::malloc(n * sizeof(T));
|
||||
if (!p) throw std::bad_alloc();
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
void deallocate(T* p, std::size_t) noexcept { std::free(p); }
|
||||
template<typename U> bool operator==(const MallocAllocator<U>&) const noexcept { return true; }
|
||||
template<typename U> bool operator!=(const MallocAllocator<U>&) const noexcept { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MallocDeleter {
|
||||
void operator()(T* p) const {
|
||||
p->~T();
|
||||
std::free(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T, MallocDeleter<T>> make_malloc_unique(Args&&... args) {
|
||||
void* mem = std::malloc(sizeof(T));
|
||||
if (!mem) throw std::bad_alloc();
|
||||
T* obj = JKR_NEW_ARGS (mem) T(std::forward<Args>(args)...);
|
||||
return std::unique_ptr<T, MallocDeleter<T>>(obj);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Side-table: native mutex per OSMutex
|
||||
// ============================================================================
|
||||
@@ -59,17 +22,13 @@ struct PCMutexData {
|
||||
std::recursive_mutex nativeMutex;
|
||||
};
|
||||
|
||||
template<typename K, typename V>
|
||||
using MallocMap = std::unordered_map<K, V, std::hash<K>, std::equal_to<K>,
|
||||
MallocAllocator<std::pair<const K, V>>>;
|
||||
|
||||
// Lazy-initialized to avoid DLL static init crashes
|
||||
static std::mutex& GetMutexMapMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSMutex*, std::unique_ptr<PCMutexData, MallocDeleter<PCMutexData>>>& GetMutexMap() {
|
||||
static MallocMap<OSMutex*, std::unique_ptr<PCMutexData, MallocDeleter<PCMutexData>>> map;
|
||||
static std::unordered_map<OSMutex*, std::unique_ptr<PCMutexData>>& GetMutexMap() {
|
||||
static std::unordered_map<OSMutex*, std::unique_ptr<PCMutexData>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -78,7 +37,7 @@ static PCMutexData& GetMutexData(OSMutex* mutex) {
|
||||
auto& map = GetMutexMap();
|
||||
auto it = map.find(mutex);
|
||||
if (it == map.end()) {
|
||||
auto result = map.emplace(mutex, make_malloc_unique<PCMutexData>());
|
||||
auto result = map.emplace(mutex, std::make_unique<PCMutexData>());
|
||||
return *result.first->second;
|
||||
}
|
||||
return *it->second;
|
||||
@@ -97,8 +56,8 @@ static std::mutex& GetCondMapMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSCond*, std::unique_ptr<PCCondData, MallocDeleter<PCCondData>>>& GetCondMap() {
|
||||
static MallocMap<OSCond*, std::unique_ptr<PCCondData, MallocDeleter<PCCondData>>> map;
|
||||
static std::unordered_map<OSCond*, std::unique_ptr<PCCondData>>& GetCondMap() {
|
||||
static std::unordered_map<OSCond*, std::unique_ptr<PCCondData>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -107,7 +66,7 @@ static PCCondData& GetCondData(OSCond* cond) {
|
||||
auto& map = GetCondMap();
|
||||
auto it = map.find(cond);
|
||||
if (it == map.end()) {
|
||||
auto result = map.emplace(cond, make_malloc_unique<PCCondData>());
|
||||
auto result = map.emplace(cond, std::make_unique<PCCondData>());
|
||||
return *result.first->second;
|
||||
}
|
||||
return *it->second;
|
||||
|
||||
+8
-57
@@ -18,45 +18,6 @@
|
||||
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
|
||||
// ============================================================================
|
||||
// Malloc-based allocator to bypass JKRHeap operator new/delete
|
||||
// ============================================================================
|
||||
|
||||
template<typename T>
|
||||
struct MallocAllocator {
|
||||
using value_type = T;
|
||||
MallocAllocator() = default;
|
||||
template<typename U> MallocAllocator(const MallocAllocator<U>&) noexcept {}
|
||||
T* allocate(std::size_t n) {
|
||||
void* p = std::malloc(n * sizeof(T));
|
||||
if (!p) throw std::bad_alloc();
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
void deallocate(T* p, std::size_t) noexcept { std::free(p); }
|
||||
template<typename U> bool operator==(const MallocAllocator<U>&) const noexcept { return true; }
|
||||
template<typename U> bool operator!=(const MallocAllocator<U>&) const noexcept { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MallocDeleter {
|
||||
void operator()(T* p) const {
|
||||
p->~T();
|
||||
std::free(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T, MallocDeleter<T>> make_malloc_unique(Args&&... args) {
|
||||
void* mem = std::malloc(sizeof(T));
|
||||
if (!mem) throw std::bad_alloc();
|
||||
T* obj = JKR_NEW_ARGS (mem) T(std::forward<Args>(args)...);
|
||||
return std::unique_ptr<T, MallocDeleter<T>>(obj);
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
using MallocMap = std::unordered_map<K, V, std::hash<K>, std::equal_to<K>,
|
||||
MallocAllocator<std::pair<const K, V>>>;
|
||||
|
||||
// ============================================================================
|
||||
// Side-table: native thread data per OSThread
|
||||
// ============================================================================
|
||||
@@ -76,8 +37,8 @@ static std::mutex& GetThreadDataMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSThread*, std::unique_ptr<PCThreadData, MallocDeleter<PCThreadData>>>& GetThreadDataMap() {
|
||||
static MallocMap<OSThread*, std::unique_ptr<PCThreadData, MallocDeleter<PCThreadData>>> map;
|
||||
static std::unordered_map<OSThread*, std::unique_ptr<PCThreadData>>& GetThreadDataMap() {
|
||||
static std::unordered_map<OSThread*, std::unique_ptr<PCThreadData>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -86,8 +47,8 @@ static std::mutex& GetQueueCvMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSThreadQueue*, std::unique_ptr<std::condition_variable, MallocDeleter<std::condition_variable>>>& GetQueueCvMap() {
|
||||
static MallocMap<OSThreadQueue*, std::unique_ptr<std::condition_variable, MallocDeleter<std::condition_variable>>> map;
|
||||
static std::unordered_map<OSThreadQueue*, std::unique_ptr<std::condition_variable>>& GetQueueCvMap() {
|
||||
static std::unordered_map<OSThreadQueue*, std::unique_ptr<std::condition_variable>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -96,7 +57,7 @@ static std::condition_variable& GetQueueCV(OSThreadQueue* queue) {
|
||||
auto& map = GetQueueCvMap();
|
||||
auto it = map.find(queue);
|
||||
if (it == map.end()) {
|
||||
auto result = map.emplace(queue, make_malloc_unique<std::condition_variable>());
|
||||
auto result = map.emplace(queue, std::make_unique<std::condition_variable>());
|
||||
return *result.first->second;
|
||||
}
|
||||
return *it->second;
|
||||
@@ -295,7 +256,7 @@ int OSCreateThread(OSThread* thread, void* (*func)(void*), void* param,
|
||||
|
||||
// Create side-table entry (but don't start the thread yet)
|
||||
{
|
||||
auto data = make_malloc_unique<PCThreadData>();
|
||||
auto data = std::make_unique<PCThreadData>();
|
||||
data->func = func;
|
||||
data->param = param;
|
||||
|
||||
@@ -649,24 +610,14 @@ s32 OSEnableScheduler(void) {
|
||||
// ============================================================================
|
||||
|
||||
BOOL OSDisableInterrupts(void) {
|
||||
GetInterruptMutex().lock();
|
||||
sInterruptLockCount++;
|
||||
return (BOOL)(sInterruptLockCount > 1); // TRUE if was already locked
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL OSRestoreInterrupts(BOOL level) {
|
||||
if (sInterruptLockCount > 0) {
|
||||
sInterruptLockCount--;
|
||||
GetInterruptMutex().unlock();
|
||||
}
|
||||
return level;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL OSEnableInterrupts(void) {
|
||||
if (sInterruptLockCount > 0) {
|
||||
sInterruptLockCount--;
|
||||
GetInterruptMutex().unlock();
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "fmt/format.h"
|
||||
#include "imgui.h"
|
||||
#include "aurora/gfx.h"
|
||||
#include <imgui_internal.h>
|
||||
|
||||
#include "ImGuiConsole.hpp"
|
||||
|
||||
@@ -82,6 +83,91 @@ namespace dusk {
|
||||
return result;
|
||||
}
|
||||
|
||||
// from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444
|
||||
void ImGuiBeginGroupPanel(const char* name, const ImVec2& size) {
|
||||
ImGui::BeginGroup();
|
||||
|
||||
auto cursorPos = ImGui::GetCursorScreenPos();
|
||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
|
||||
auto frameHeight = ImGui::GetFrameHeight();
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImVec2 effectiveSize = size;
|
||||
if (size.x < 0.0f)
|
||||
effectiveSize.x = ImGui::GetContentRegionAvail().x;
|
||||
else
|
||||
effectiveSize.x = size.x;
|
||||
ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f));
|
||||
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::TextUnformatted(name);
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y));
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->Size.x -= frameHeight;
|
||||
|
||||
ImGui::PushItemWidth(effectiveSize.x - frameHeight);
|
||||
}
|
||||
|
||||
// from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444
|
||||
void ImGuiEndGroupPanel() {
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
|
||||
auto frameHeight = ImGui::GetFrameHeight();
|
||||
|
||||
// workaround for incorrect capture of columns/table width by placing
|
||||
// zero-sized dummy element in the same group, this ensure
|
||||
// max X cursor position is updated correctly
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::Dummy(ImVec2(0.0, frameHeight - frameHeight * 0.5f - itemSpacing.y));
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
auto itemMin = ImGui::GetItemRectMin();
|
||||
auto itemMax = ImGui::GetItemRectMax();
|
||||
|
||||
ImVec2 halfFrame = ImVec2((frameHeight * 0.25f) * 0.5f, frameHeight * 0.5f);
|
||||
ImGui::GetWindowDrawList()->AddRect(
|
||||
ImVec2(itemMin.x + halfFrame.x, itemMin.y + halfFrame.y),
|
||||
ImVec2(itemMax.x - halfFrame.x, itemMax.y),
|
||||
ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Border)),
|
||||
halfFrame.x);
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->Size.x += frameHeight;
|
||||
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
ImGuiConsole g_imguiConsole;
|
||||
|
||||
ImGuiConsole::ImGuiConsole() {}
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace dusk {
|
||||
void SetOverlayWindowLocation(int corner);
|
||||
bool ShowCornerContextMenu(int& corner, int avoidCorner);
|
||||
void ImGuiStringViewText(std::string_view text);
|
||||
void ImGuiBeginGroupPanel(const char* name, const ImVec2& size);
|
||||
void ImGuiEndGroupPanel();
|
||||
}
|
||||
|
||||
void DuskDebugPad();
|
||||
|
||||
@@ -12,19 +12,17 @@ namespace dusk {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(300, 0), ImVec2(FLT_MAX, FLT_MAX));
|
||||
|
||||
if (!ImGui::Begin("Map Loader", nullptr, windowFlags)) {
|
||||
if (!ImGui::Begin("Map Loader", &m_showMapLoader, windowFlags)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Map Loader");
|
||||
|
||||
ImGui::Checkbox("Show Internal Names", &m_mapLoaderInfo.showInternalNames);
|
||||
|
||||
const char* previewRegion = "None";
|
||||
|
||||
@@ -73,91 +73,6 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
// from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444
|
||||
void ImGuiBeginGroupPanel(const char* name, const ImVec2& size) {
|
||||
ImGui::BeginGroup();
|
||||
|
||||
auto cursorPos = ImGui::GetCursorScreenPos();
|
||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
|
||||
auto frameHeight = ImGui::GetFrameHeight();
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImVec2 effectiveSize = size;
|
||||
if (size.x < 0.0f)
|
||||
effectiveSize.x = ImGui::GetContentRegionAvail().x;
|
||||
else
|
||||
effectiveSize.x = size.x;
|
||||
ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f));
|
||||
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::TextUnformatted(name);
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y));
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->Size.x -= frameHeight;
|
||||
|
||||
ImGui::PushItemWidth(effectiveSize.x - frameHeight);
|
||||
}
|
||||
|
||||
// from https://github.com/ocornut/imgui/issues/1496#issuecomment-569892444
|
||||
void ImGuiEndGroupPanel() {
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
auto itemSpacing = ImGui::GetStyle().ItemSpacing;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
|
||||
|
||||
auto frameHeight = ImGui::GetFrameHeight();
|
||||
|
||||
// workaround for incorrect capture of columns/table width by placing
|
||||
// zero-sized dummy element in the same group, this ensure
|
||||
// max X cursor position is updated correctly
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
|
||||
ImGui::Dummy(ImVec2(0.0, frameHeight - frameHeight * 0.5f - itemSpacing.y));
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
auto itemMin = ImGui::GetItemRectMin();
|
||||
auto itemMax = ImGui::GetItemRectMax();
|
||||
|
||||
ImVec2 halfFrame = ImVec2((frameHeight * 0.25f) * 0.5f, frameHeight * 0.5f);
|
||||
ImGui::GetWindowDrawList()->AddRect(
|
||||
ImVec2(itemMin.x + halfFrame.x, itemMin.y + halfFrame.y),
|
||||
ImVec2(itemMax.x - halfFrame.x, itemMax.y),
|
||||
ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Border)),
|
||||
halfFrame.x);
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f;
|
||||
ImGui::GetCurrentWindow()->Size.x += frameHeight;
|
||||
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
static void drawVirtualStick(const char* id, const ImVec2& stick) {
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetCursorPos().x + 5, ImGui::GetCursorPos().y));
|
||||
|
||||
@@ -200,7 +115,7 @@ namespace dusk {
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(850, 400), ImVec2(850, 400));
|
||||
|
||||
if (!ImGui::Begin("Controller Config", nullptr, windowFlags)) {
|
||||
if (!ImGui::Begin("Controller Config", &m_showControllerConfig, windowFlags)) {
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace dusk {
|
||||
ImGui::MenuItem("Debug Camera", "F6", &m_showCameraOverlay);
|
||||
ImGui::MenuItem("Map Loader", nullptr, &m_showMapLoader);
|
||||
ImGui::MenuItem("Player Info", nullptr, &m_showPlayerInfo);
|
||||
ImGui::MenuItem("Save Editor", nullptr, &m_showSaveEditor);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -59,6 +60,10 @@ namespace dusk {
|
||||
ShowMapLoader();
|
||||
ShowPlayerInfo();
|
||||
|
||||
if (m_showSaveEditor) {
|
||||
m_saveEditor.draw(m_showSaveEditor);
|
||||
}
|
||||
|
||||
DuskDebugPad(); // temporary, remove later
|
||||
}
|
||||
|
||||
@@ -136,7 +141,7 @@ namespace dusk {
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(300, 200), ImVec2(300, 200));
|
||||
|
||||
if (ImGui::Begin("Player Info", nullptr, windowFlags)) {
|
||||
if (ImGui::Begin("Player Info", &m_showPlayerInfo, windowFlags)) {
|
||||
daAlink_c* player = (daAlink_c*)dComIfGp_getPlayer(0);
|
||||
daHorse_c* horse = dComIfGp_getHorseActor();
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "ImGuiSaveEditor.hpp"
|
||||
|
||||
namespace dusk {
|
||||
class ImGuiMenuTools {
|
||||
@@ -63,6 +64,9 @@ namespace dusk {
|
||||
bool m_showPlayerInfo = false;
|
||||
|
||||
CollisionViewSettings m_collisionViewSettings;
|
||||
|
||||
bool m_showSaveEditor = false;
|
||||
ImGuiSaveEditor m_saveEditor;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace dusk {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::Begin("Processes")) {
|
||||
if (ImGui::Begin("Processes", &m_showProcessManagement)) {
|
||||
if (ImGui::BeginTabBar("Tabs")) {
|
||||
showTreeRecursive = true;
|
||||
if (ImGui::BeginTabItem("Tree")) {
|
||||
|
||||
@@ -0,0 +1,816 @@
|
||||
#include "fmt/format.h"
|
||||
#include "imgui.h"
|
||||
#include "aurora/gfx.h"
|
||||
|
||||
#include "ImGuiConsole.hpp"
|
||||
#include "ImGuiSaveEditor.hpp"
|
||||
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "d/d_item_data.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace dusk {
|
||||
std::map<int, std::string> itemMap = {
|
||||
{dItemNo_HEART_e, "Heart"},
|
||||
{dItemNo_GREEN_RUPEE_e, "Green Rupee"},
|
||||
{dItemNo_BLUE_RUPEE_e, "Blue Rupee"},
|
||||
{dItemNo_YELLOW_RUPEE_e, "Yellow Rupee"},
|
||||
{dItemNo_RED_RUPEE_e, "Red Rupee"},
|
||||
{dItemNo_PURPLE_RUPEE_e, "Purple Rupee"},
|
||||
{dItemNo_ORANGE_RUPEE_e, "Orange Rupee"},
|
||||
{dItemNo_SILVER_RUPEE_e, "Silver Rupee"},
|
||||
{dItemNo_S_MAGIC_e, "Small Magic"},
|
||||
{dItemNo_L_MAGIC_e, "Large Magic"},
|
||||
{dItemNo_BOMB_5_e, "Bombs (5)"},
|
||||
{dItemNo_BOMB_10_e, "Bombs (10)"},
|
||||
{dItemNo_BOMB_20_e, "Bombs (20)"},
|
||||
{dItemNo_BOMB_30_e, "Bombs (30)"},
|
||||
{dItemNo_ARROW_10_e, "Arrows (10)"},
|
||||
{dItemNo_ARROW_20_e, "Arrows (20)"},
|
||||
{dItemNo_ARROW_30_e, "Arrows (30)"},
|
||||
{dItemNo_ARROW_1_e, "Arrows (1)"},
|
||||
{dItemNo_PACHINKO_SHOT_e, "Pumpkin Seeds"},
|
||||
{dItemNo_NOENTRY_19_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_20_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_21_e, "Unknown"},
|
||||
{dItemNo_WATER_BOMB_5_e, "Water Bombs (5)"},
|
||||
{dItemNo_WATER_BOMB_10_e, "Water Bombs (10)"},
|
||||
{dItemNo_WATER_BOMB_20_e, "Water Bombs (20)"},
|
||||
{dItemNo_WATER_BOMB_30_e, "Water Bombs (30)"},
|
||||
{dItemNo_BOMB_INSECT_5_e, "Bomblings (5)"},
|
||||
{dItemNo_BOMB_INSECT_10_e, "Bomblings (10)"},
|
||||
{dItemNo_BOMB_INSECT_20_e, "Bomblings (20)"},
|
||||
{dItemNo_BOMB_INSECT_30_e, "Bomblings (30)"},
|
||||
{dItemNo_RECOVERY_FAILY_e, "Fairy"},
|
||||
{dItemNo_TRIPLE_HEART_e, "Triple Hearts"},
|
||||
{dItemNo_SMALL_KEY_e, "Small Key"},
|
||||
{dItemNo_KAKERA_HEART_e, "Piece of Heart"},
|
||||
{dItemNo_UTAWA_HEART_e, "Heart Container"},
|
||||
{dItemNo_MAP_e, "Map"},
|
||||
{dItemNo_COMPUS_e, "Compass"},
|
||||
{dItemNo_DUNGEON_EXIT_e, "Ooccoo Sr."},
|
||||
{dItemNo_BOSS_KEY_e, "Boss Key"},
|
||||
{dItemNo_DUNGEON_BACK_e, "Ooccoo Jr."},
|
||||
{dItemNo_SWORD_e, "Ordon Sword"},
|
||||
{dItemNo_MASTER_SWORD_e, "Master Sword"},
|
||||
{dItemNo_WOOD_SHIELD_e, "Wooden Shield"},
|
||||
{dItemNo_SHIELD_e, "Ordon Shield"},
|
||||
{dItemNo_HYLIA_SHIELD_e, "Hylian Shield"},
|
||||
{dItemNo_TKS_LETTER_e, "Ooccoo's Letter"},
|
||||
{dItemNo_WEAR_CASUAL_e, "Ordon Clothes"},
|
||||
{dItemNo_WEAR_KOKIRI_e, "Hero's Clothes"},
|
||||
{dItemNo_ARMOR_e, "Magic Armor"},
|
||||
{dItemNo_WEAR_ZORA_e, "Zora Armor"},
|
||||
{dItemNo_MAGIC_LV1_e, "Magic Level 1"},
|
||||
{dItemNo_DUNGEON_EXIT_2_e, "Ooccoo Sr."},
|
||||
{dItemNo_WALLET_LV1_e, "Wallet"},
|
||||
{dItemNo_WALLET_LV2_e, "Big Wallet"},
|
||||
{dItemNo_WALLET_LV3_e, "Giant Wallet"},
|
||||
{dItemNo_NOENTRY_55_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_56_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_57_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_58_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_59_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_60_e, "Unknown"},
|
||||
{dItemNo_ZORAS_JEWEL_e, "Coral Earring"},
|
||||
{dItemNo_HAWK_EYE_e, "Hawkeye"},
|
||||
{dItemNo_WOOD_STICK_e, "Wooden Sword"},
|
||||
{dItemNo_BOOMERANG_e, "Gale Boomerang"},
|
||||
{dItemNo_SPINNER_e, "Spinner"},
|
||||
{dItemNo_IRONBALL_e, "Ball and Chain"},
|
||||
{dItemNo_BOW_e, "Hero's Bow"},
|
||||
{dItemNo_HOOKSHOT_e, "Clawshot"},
|
||||
{dItemNo_HVY_BOOTS_e, "Iron Boots"},
|
||||
{dItemNo_COPY_ROD_e, "Dominion Rod"},
|
||||
{dItemNo_W_HOOKSHOT_e, "Double Clawshots"},
|
||||
{dItemNo_KANTERA_e, "Lantern"},
|
||||
{dItemNo_LIGHT_SWORD_e, "Light Sword"},
|
||||
{dItemNo_FISHING_ROD_1_e, "Fishing Rod"},
|
||||
{dItemNo_PACHINKO_e, "Slingshot"},
|
||||
{dItemNo_COPY_ROD_2_e, "Dominion Rod"},
|
||||
{dItemNo_NOENTRY_77_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_78_e, "Unknown"},
|
||||
{dItemNo_BOMB_BAG_LV2_e, "Giant Bomb Bag"},
|
||||
{dItemNo_BOMB_BAG_LV1_e, "Bomb Bag"},
|
||||
{dItemNo_BOMB_IN_BAG_e, "Bomb Bag"},
|
||||
{dItemNo_NOENTRY_82_e, "Unknown"},
|
||||
{dItemNo_LIGHT_ARROW_e, "Light Arrow"},
|
||||
{dItemNo_ARROW_LV1_e, "Quiver"},
|
||||
{dItemNo_ARROW_LV2_e, "Big Quiver"},
|
||||
{dItemNo_ARROW_LV3_e, "Giant Quiver"},
|
||||
{dItemNo_NOENTRY_87_e, "Unknown"},
|
||||
{dItemNo_LURE_ROD_e, "Fishing Rod (Lure)"},
|
||||
{dItemNo_BOMB_ARROW_e, "Bomb Arrow"},
|
||||
{dItemNo_HAWK_ARROW_e, "Hawk Arrow"},
|
||||
{dItemNo_BEE_ROD_e, "Fishing Rod (Bee Larva)"},
|
||||
{dItemNo_JEWEL_ROD_e, "Fishing Rod (Earring)"},
|
||||
{dItemNo_WORM_ROD_e, "Fishing Rod (Worm)"},
|
||||
{dItemNo_JEWEL_BEE_ROD_e, "Fishing Rod (Earring + Bee Larva)"},
|
||||
{dItemNo_JEWEL_WORM_ROD_e, "Fishing Rod (Earring + Worm)"},
|
||||
{dItemNo_EMPTY_BOTTLE_e, "Empty Bottle"},
|
||||
{dItemNo_RED_BOTTLE_e, "Red Potion"},
|
||||
{dItemNo_GREEN_BOTTLE_e, "Green Potion"},
|
||||
{dItemNo_BLUE_BOTTLE_e, "Blue Potion"},
|
||||
{dItemNo_MILK_BOTTLE_e, "Milk Bottle"},
|
||||
{dItemNo_HALF_MILK_BOTTLE_e, "Half Milk Bottle"},
|
||||
{dItemNo_OIL_BOTTLE_e, "Lantern Oil"},
|
||||
{dItemNo_WATER_BOTTLE_e, "Water Bottle"},
|
||||
{dItemNo_OIL_BOTTLE_2_e, "Oil Bottle"},
|
||||
{dItemNo_RED_BOTTLE_2_e, "Red Potion"},
|
||||
{dItemNo_UGLY_SOUP_e, "Nasty Soup"},
|
||||
{dItemNo_HOT_SPRING_e, "Hotspring Water"},
|
||||
{dItemNo_FAIRY_e, "Fairy"},
|
||||
{dItemNo_HOT_SPRING_2_e, "Hotspring Water"},
|
||||
{dItemNo_OIL2_e, "Lantern Oil"},
|
||||
{dItemNo_OIL_e, "Lantern Oil"},
|
||||
{dItemNo_NORMAL_BOMB_e, "Bombs"},
|
||||
{dItemNo_WATER_BOMB_e, "Water Bombs"},
|
||||
{dItemNo_POKE_BOMB_e, "Bomblings"},
|
||||
{dItemNo_FAIRY_DROP_e, "Great Fairy's Tears"},
|
||||
{dItemNo_WORM_e, "Worm"},
|
||||
{dItemNo_DROP_BOTTLE_e, ""},
|
||||
{dItemNo_BEE_CHILD_e, ""},
|
||||
{dItemNo_CHUCHU_RARE_e, "Rare Chu Jelly"},
|
||||
{dItemNo_CHUCHU_RED_e, "Red Chu Jelly"},
|
||||
{dItemNo_CHUCHU_BLUE_e, "Blue Chu Jelly"},
|
||||
{dItemNo_CHUCHU_GREEN_e, "Green Chu Jelly"},
|
||||
{dItemNo_CHUCHU_YELLOW_e, "Yellow Chu Jelly"},
|
||||
{dItemNo_CHUCHU_PURPLE_e, "Purple Chu Jelly"},
|
||||
{dItemNo_LV1_SOUP_e, "Simple Soup"},
|
||||
{dItemNo_LV2_SOUP_e, "Good Soup"},
|
||||
{dItemNo_LV3_SOUP_e, "Superb Soup"},
|
||||
{dItemNo_LETTER_e, "Renado's Letter"},
|
||||
{dItemNo_BILL_e, "Invoice"},
|
||||
{dItemNo_WOOD_STATUE_e, "Wooden Statue"},
|
||||
{dItemNo_IRIAS_PENDANT_e, "Ilia's Charm"},
|
||||
{dItemNo_HORSE_FLUTE_e, "Horse Call"},
|
||||
{dItemNo_NOENTRY_133_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_134_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_135_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_136_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_137_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_138_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_139_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_140_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_141_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_142_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_143_e, "Unknown"},
|
||||
{dItemNo_RAFRELS_MEMO_e, "Auru's Memo"},
|
||||
{dItemNo_ASHS_SCRIBBLING_e, "Ashei's Sketch"},
|
||||
{dItemNo_NOENTRY_146_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_147_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_148_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_149_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_150_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_151_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_152_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_153_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_154_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_155_e, "Unknown"},
|
||||
{dItemNo_CHUCHU_YELLOW2_e, "Yellow Chu Jelly"},
|
||||
{dItemNo_OIL_BOTTLE3_e, "Lantern Oil"},
|
||||
{dItemNo_SHOP_BEE_CHILD_e, ""},
|
||||
{dItemNo_CHUCHU_BLACK_e, "Black Chu Jelly"},
|
||||
{dItemNo_LIGHT_DROP_e, "Tear of Light"},
|
||||
{dItemNo_DROP_CONTAINER_e, "Vessel of Light (Faron)"},
|
||||
{dItemNo_DROP_CONTAINER02_e, "Vessel of Light (Eldin)"},
|
||||
{dItemNo_DROP_CONTAINER03_e, "Vessel of Light (Lanayru)"},
|
||||
{dItemNo_FILLED_CONTAINER_e, "Vessel of Light (Filled)"},
|
||||
{dItemNo_MIRROR_PIECE_2_e, "Mirror Shard (Snowpeak Ruins)"},
|
||||
{dItemNo_MIRROR_PIECE_3_e, "Mirror Shard (Temple of Time)"},
|
||||
{dItemNo_MIRROR_PIECE_4_e, "Mirror Shard (City in the Sky)"},
|
||||
{dItemNo_NOENTRY_168_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_169_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_170_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_171_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_172_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_173_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_174_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_175_e, "Unknown"},
|
||||
{dItemNo_SMELL_YELIA_POUCH_e, "Scent of Ilia"},
|
||||
{dItemNo_SMELL_PUMPKIN_e, "Pumpkin Scent"},
|
||||
{dItemNo_SMELL_POH_e, "Poe Scent"},
|
||||
{dItemNo_SMELL_FISH_e, "Reekfish Scent"},
|
||||
{dItemNo_SMELL_CHILDREN_e, "Youth's Scent"},
|
||||
{dItemNo_SMELL_MEDICINE_e, "Medicine Scent"},
|
||||
{dItemNo_NOENTRY_182_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_183_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_184_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_185_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_186_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_187_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_188_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_189_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_190_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_191_e, "Unknown"},
|
||||
{dItemNo_M_BEETLE_e, "Beetle ♂"},
|
||||
{dItemNo_F_BEETLE_e, "Beetle ♀"},
|
||||
{dItemNo_M_BUTTERFLY_e, "Butterfly ♂"},
|
||||
{dItemNo_F_BUTTERFLY_e, "Butterfly ♀"},
|
||||
{dItemNo_M_STAG_BEETLE_e, "Stag Beetle ♂"},
|
||||
{dItemNo_F_STAG_BEETLE_e, "Stag Beetle ♀"},
|
||||
{dItemNo_M_GRASSHOPPER_e, "Grasshopper ♂"},
|
||||
{dItemNo_F_GRASSHOPPER_e, "Grasshopper ♀"},
|
||||
{dItemNo_M_NANAFUSHI_e, "Phasmid ♂"},
|
||||
{dItemNo_F_NANAFUSHI_e, "Phasmid ♀"},
|
||||
{dItemNo_M_DANGOMUSHI_e, "Pill Bug ♂"},
|
||||
{dItemNo_F_DANGOMUSHI_e, "Pill Bug ♀"},
|
||||
{dItemNo_M_MANTIS_e, "Mantis ♂"},
|
||||
{dItemNo_F_MANTIS_e, "Mantis ♀"},
|
||||
{dItemNo_M_LADYBUG_e, "Ladybug ♂"},
|
||||
{dItemNo_F_LADYBUG_e, "Ladybug ♀"},
|
||||
{dItemNo_M_SNAIL_e, "Snail ♂"},
|
||||
{dItemNo_F_SNAIL_e, "Snail ♀"},
|
||||
{dItemNo_M_DRAGONFLY_e, "Dragonfly ♂"},
|
||||
{dItemNo_F_DRAGONFLY_e, "Dragonfly ♀"},
|
||||
{dItemNo_M_ANT_e, "Ant ♂"},
|
||||
{dItemNo_F_ANT_e, "Ant ♀"},
|
||||
{dItemNo_M_MAYFLY_e, "Mayfly ♂"},
|
||||
{dItemNo_F_MAYFLY_e, "Mayfly ♀"},
|
||||
{dItemNo_NOENTRY_216_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_217_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_218_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_219_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_220_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_221_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_222_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_223_e, "Unknown"},
|
||||
{dItemNo_POU_SPIRIT_e, ""},
|
||||
{dItemNo_NOENTRY_225_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_226_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_227_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_228_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_229_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_230_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_231_e, "Unknown"},
|
||||
{dItemNo_NOENTRY_232_e, "Unknown"},
|
||||
{dItemNo_ANCIENT_DOCUMENT_e, "Ancient Sky Book"},
|
||||
{dItemNo_AIR_LETTER_e, "Sky Character"},
|
||||
{dItemNo_ANCIENT_DOCUMENT2_e, "Ancient Sky Book (Filled)"},
|
||||
{dItemNo_LV7_DUNGEON_EXIT_e, "Ooccoo Sr. (City in the Sky)"},
|
||||
{dItemNo_LINKS_SAVINGS_e, "Link's Savings"},
|
||||
{dItemNo_SMALL_KEY2_e, ""},
|
||||
{dItemNo_POU_FIRE1_e, ""},
|
||||
{dItemNo_POU_FIRE2_e, ""},
|
||||
{dItemNo_POU_FIRE3_e, ""},
|
||||
{dItemNo_POU_FIRE4_e, ""},
|
||||
{dItemNo_BOSSRIDER_KEY_e, ""},
|
||||
{dItemNo_TOMATO_PUREE_e, ""},
|
||||
{dItemNo_TASTE_e, ""},
|
||||
{dItemNo_LV5_BOSS_KEY_e, "Bedroom Key"},
|
||||
{dItemNo_SURFBOARD_e, ""},
|
||||
{dItemNo_KANTERA2_e, ""},
|
||||
{dItemNo_L2_KEY_PIECES1_e, "Key Shard (1)"},
|
||||
{dItemNo_L2_KEY_PIECES2_e, "Key Shard (2)"},
|
||||
{dItemNo_L2_KEY_PIECES3_e, "Key Shard (3)"},
|
||||
{dItemNo_KEY_OF_CARAVAN_e, "Bulblin Camp Key"},
|
||||
{dItemNo_LV2_BOSS_KEY_e, "Key Shard (Completed)"},
|
||||
{dItemNo_KEY_OF_FILONE_e, "Faron Gate Key"},
|
||||
{dItemNo_NONE_e, "None"},
|
||||
};
|
||||
|
||||
ImGuiSaveEditor::ImGuiSaveEditor() {}
|
||||
|
||||
void ImGuiSaveEditor::draw(bool& open) {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoResize;
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(600, 700), ImVec2(600, 700));
|
||||
|
||||
if (ImGui::Begin("Save Editor", &open, windowFlags)) {
|
||||
if (ImGui::BeginTabBar("SaveEditorTabBar", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
|
||||
if (ImGui::BeginTabItem("Player Status")) {
|
||||
drawPlayerStatusTab();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Location")) {
|
||||
drawLocationTab();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Inventory")) {
|
||||
//DrawInventoryTab();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Collection")) {
|
||||
//DrawFlagsTab();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Flags")) {
|
||||
drawFlagsTab();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Minigame")) {
|
||||
//DrawFlagsTab();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Config")) {
|
||||
drawConfigTab();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void InputScalarBE(const char* label, ImGuiDataType dataType, void* pData) {
|
||||
switch (dataType) {
|
||||
case ImGuiDataType_U16: {
|
||||
u16 temp = *(BE(u16)*)pData;
|
||||
if (ImGui::InputScalar(label, dataType, &temp)) {
|
||||
*(BE(u16)*)pData = temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_S16: {
|
||||
s16 temp = *(BE(s16)*)pData;
|
||||
if (ImGui::InputScalar(label, dataType, &temp)) {
|
||||
*(BE(s16)*)pData = temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_U32: {
|
||||
u32 temp = *(BE(u32)*)pData;
|
||||
if (ImGui::InputScalar(label, dataType, &temp)) {
|
||||
*(BE(u32)*)pData = temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_S32: {
|
||||
s32 temp = *(BE(s32)*)pData;
|
||||
if (ImGui::InputScalar(label, dataType, &temp)) {
|
||||
*(BE(s32)*)pData = temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_U64: {
|
||||
u64 temp = *(BE(u64)*)pData;
|
||||
if (ImGui::InputScalar(label, dataType, &temp)) {
|
||||
*(BE(u64)*)pData = temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_S64: {
|
||||
s64 temp = *(BE(s64)*)pData;
|
||||
if (ImGui::InputScalar(label, dataType, &temp)) {
|
||||
*(BE(s64)*)pData = temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_Float: {
|
||||
f32 temp = *(BE(f32)*)pData;
|
||||
if (ImGui::InputScalar(label, dataType, &temp)) {
|
||||
*(BE(f32)*)pData = temp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void genSelectItemComboBox(const char* label, u8& selectItemData) {
|
||||
dSv_player_status_a_c& statusA = dComIfGs_getSaveData()->getPlayer().getPlayerStatusA();
|
||||
dSv_player_item_c& item = dComIfGs_getSaveData()->getPlayer().getItem();
|
||||
|
||||
int currentSlotNo = selectItemData;
|
||||
std::string defaultLabel =
|
||||
currentSlotNo != 0xFF
|
||||
? fmt::format("Slot {0} ({1})", currentSlotNo, itemMap.find(item.mItems[currentSlotNo])->second)
|
||||
: "None";
|
||||
|
||||
// TODO: live update equips
|
||||
if (ImGui::BeginCombo(label, defaultLabel.c_str())) {
|
||||
if (ImGui::Selectable("None")) {
|
||||
selectItemData = 0xFF;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 24; i++) {
|
||||
u8 itemNo = item.mItems[i];
|
||||
if (ImGui::Selectable(fmt::format("Slot {0} ({1})", i, itemMap.find(itemNo)->second).c_str())) {
|
||||
selectItemData = i;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawPlayerStatusTab() {
|
||||
const char* playerName = dComIfGs_getPlayerName();
|
||||
ImGui::Text("Player Name: ");
|
||||
ImGui::SameLine();
|
||||
char nameBuffer[8];
|
||||
snprintf(nameBuffer, sizeof(nameBuffer), "%s", playerName);
|
||||
if (ImGui::InputText("##PlayerNameInput", nameBuffer, 8)) {
|
||||
strcpy(dComIfGs_getPlayerName(), nameBuffer);
|
||||
}
|
||||
|
||||
const char* horseName = dComIfGs_getHorseName();
|
||||
ImGui::Text("Horse Name: ");
|
||||
ImGui::SameLine();
|
||||
char horseNameBuffer[8];
|
||||
snprintf(horseNameBuffer, sizeof(horseNameBuffer), "%s", horseName);
|
||||
if (ImGui::InputText("##HorseNameInput", horseNameBuffer, 8)) {
|
||||
strcpy(dComIfGs_getHorseName(), horseNameBuffer);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
dSv_player_status_a_c& statusA = dComIfGs_getSaveData()->getPlayer().getPlayerStatusA();
|
||||
dSv_player_status_b_c& statusB = dComIfGs_getSaveData()->getPlayer().getPlayerStatusB();
|
||||
|
||||
InputScalarBE("Max Health", ImGuiDataType_U16, &statusA.mMaxLife);
|
||||
InputScalarBE("Health", ImGuiDataType_U16, &statusA.mLife);
|
||||
InputScalarBE("Rupees", ImGuiDataType_U16, &statusA.mRupee);
|
||||
InputScalarBE("Max Oil", ImGuiDataType_U16, &statusA.mMaxOil);
|
||||
InputScalarBE("Oil", ImGuiDataType_U16, &statusA.mOil);
|
||||
|
||||
genSelectItemComboBox("Equip X", statusA.mSelectItem[0]);
|
||||
genSelectItemComboBox("Equip Y", statusA.mSelectItem[1]);
|
||||
genSelectItemComboBox("Combo Equip X", statusA.mMixItem[0]);
|
||||
genSelectItemComboBox("Combo Equip Y", statusA.mMixItem[1]);
|
||||
|
||||
|
||||
if (ImGui::BeginCombo("Clothes", itemMap.find(statusA.mSelectEquip[0])->second.c_str())) {
|
||||
if (ImGui::Selectable("None")) {
|
||||
statusA.mSelectEquip[0] = dItemNo_NONE_e;
|
||||
}
|
||||
if (ImGui::Selectable("Ordon Clothes")) {
|
||||
statusA.mSelectEquip[0] = dItemNo_WEAR_CASUAL_e;
|
||||
}
|
||||
if (ImGui::Selectable("Hero's Clothes")) {
|
||||
statusA.mSelectEquip[0] = dItemNo_WEAR_KOKIRI_e;
|
||||
}
|
||||
if (ImGui::Selectable("Zora Armor")) {
|
||||
statusA.mSelectEquip[0] = dItemNo_WEAR_ZORA_e;
|
||||
}
|
||||
if (ImGui::Selectable("Magic Armor")) {
|
||||
statusA.mSelectEquip[0] = dItemNo_ARMOR_e;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("Sword", itemMap.find(statusA.mSelectEquip[1])->second.c_str())) {
|
||||
if (ImGui::Selectable("None")) {
|
||||
statusA.mSelectEquip[1] = dItemNo_NONE_e;
|
||||
}
|
||||
if (ImGui::Selectable("Wooden Sword")) {
|
||||
statusA.mSelectEquip[1] = dItemNo_WOOD_STICK_e;
|
||||
}
|
||||
if (ImGui::Selectable("Ordon Sword")) {
|
||||
statusA.mSelectEquip[1] = dItemNo_SWORD_e;
|
||||
}
|
||||
if (ImGui::Selectable("Master Sword")) {
|
||||
statusA.mSelectEquip[1] = dItemNo_MASTER_SWORD_e;
|
||||
}
|
||||
if (ImGui::Selectable("Light Sword")) {
|
||||
statusA.mSelectEquip[1] = dItemNo_LIGHT_SWORD_e;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("Shield", itemMap.find(statusA.mSelectEquip[2])->second.c_str())) {
|
||||
if (ImGui::Selectable("None")) {
|
||||
statusA.mSelectEquip[2] = dItemNo_NONE_e;
|
||||
}
|
||||
if (ImGui::Selectable("Wooden Shield")) {
|
||||
statusA.mSelectEquip[2] = dItemNo_SHIELD_e;
|
||||
}
|
||||
if (ImGui::Selectable("Ordon Shield")) {
|
||||
statusA.mSelectEquip[2] = dItemNo_WOOD_SHIELD_e;
|
||||
}
|
||||
if (ImGui::Selectable("Hylian Shield")) {
|
||||
statusA.mSelectEquip[2] = dItemNo_HYLIA_SHIELD_e;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("Scent", itemMap.find(statusA.mSelectEquip[3])->second.c_str())) {
|
||||
if (ImGui::Selectable("None")) {
|
||||
statusA.mSelectEquip[3] = dItemNo_NONE_e;
|
||||
}
|
||||
if (ImGui::Selectable("Youth's Scent")) {
|
||||
statusA.mSelectEquip[3] = dItemNo_SMELL_CHILDREN_e;
|
||||
}
|
||||
if (ImGui::Selectable("Scent of Ilia")) {
|
||||
statusA.mSelectEquip[3] = dItemNo_SMELL_YELIA_POUCH_e;
|
||||
}
|
||||
if (ImGui::Selectable("Poe Scent")) {
|
||||
statusA.mSelectEquip[3] = dItemNo_SMELL_POH_e;
|
||||
}
|
||||
if (ImGui::Selectable("Reekfish Scent")) {
|
||||
statusA.mSelectEquip[3] = dItemNo_SMELL_FISH_e;
|
||||
}
|
||||
if (ImGui::Selectable("Medicine Scent")) {
|
||||
statusA.mSelectEquip[3] = dItemNo_SMELL_MEDICINE_e;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
const char* walletSizeNames[] = {
|
||||
"Normal",
|
||||
"Big",
|
||||
"Giant",
|
||||
};
|
||||
int walletSize = statusA.getWalletSize();
|
||||
if (ImGui::BeginCombo("Wallet Size", walletSizeNames[walletSize])) {
|
||||
if (ImGui::Selectable(walletSizeNames[WALLET])) {
|
||||
statusA.setWalletSize(WALLET);
|
||||
}
|
||||
if (ImGui::Selectable(walletSizeNames[BIG_WALLET])) {
|
||||
statusA.setWalletSize(BIG_WALLET);
|
||||
}
|
||||
if (ImGui::Selectable(walletSizeNames[GIANT_WALLET])) {
|
||||
statusA.setWalletSize(GIANT_WALLET);
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("Form", statusA.mTransformStatus == 0 ? "Human" : "Wolf")) {
|
||||
if (ImGui::Selectable("Human")) {
|
||||
statusA.mTransformStatus = TF_STATUS_HUMAN;
|
||||
}
|
||||
if (ImGui::Selectable("Wolf")) {
|
||||
statusA.mTransformStatus = TF_STATUS_WOLF;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
s32 hours = dKy_getdaytime_hour();
|
||||
s32 min = dKy_getdaytime_minute();
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2);
|
||||
if (ImGui::InputScalar("##TimeHours", ImGuiDataType_S32, &hours)) {
|
||||
hours = std::clamp(hours, 0, 23);
|
||||
statusB.setTime((hours * 15.0f) + (min / 60.0f * 15.0f));
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(":");
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 2);
|
||||
if (ImGui::InputScalar("Time##TimeMinutes", ImGuiDataType_S32, &min)) {
|
||||
min = std::clamp(min, 0, 59);
|
||||
statusB.setTime((hours * 15.0f) + (min / 60.0f * 15.0f));
|
||||
}
|
||||
|
||||
InputScalarBE("Date", ImGuiDataType_U16, &statusB.mDate);
|
||||
|
||||
int transformLevel = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (statusB.mTransformLevelFlag & (1 << i)) {
|
||||
transformLevel++;
|
||||
}
|
||||
}
|
||||
if (ImGui::SliderInt("Transform Level", &transformLevel, 0, 3)) {
|
||||
u8 newFlags = 0;
|
||||
for (int i = 0; i < transformLevel; i++) {
|
||||
newFlags |= (1 << i);
|
||||
}
|
||||
statusB.mTransformLevelFlag = newFlags;
|
||||
}
|
||||
|
||||
int darkClearLevel = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (statusB.mDarkClearLevelFlag & (1 << i)) {
|
||||
darkClearLevel++;
|
||||
}
|
||||
}
|
||||
if (ImGui::SliderInt("Twilight Clear Level", &darkClearLevel, 0, 3)) {
|
||||
u8 newFlags = 0;
|
||||
for (int i = 0; i < darkClearLevel; i++) {
|
||||
newFlags |= (1 << i);
|
||||
}
|
||||
statusB.mDarkClearLevelFlag = newFlags;
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawLocationTab() {
|
||||
dSv_player_return_place_c& returnPlace = dComIfGs_getSaveData()->getPlayer().getPlayerReturnPlace();
|
||||
dSv_horse_place_c& horsePlace = dComIfGs_getSaveData()->getPlayer().getHorsePlace();
|
||||
ImGui::Text("Save Location");
|
||||
|
||||
ImGui::Text("Stage: ");
|
||||
ImGui::SameLine();
|
||||
char nameBuffer[8];
|
||||
snprintf(nameBuffer, sizeof(nameBuffer), "%s", returnPlace.mName);
|
||||
if (ImGui::InputText("##SaveStageNameInput", nameBuffer, 8)) {
|
||||
strcpy(returnPlace.mName, nameBuffer);
|
||||
}
|
||||
|
||||
ImGui::Text("Room: ");
|
||||
ImGui::SameLine();
|
||||
int tempRoom = returnPlace.mRoomNo;
|
||||
if (ImGui::InputInt("##SaveRoomInput", &tempRoom)) {
|
||||
returnPlace.mRoomNo = tempRoom;
|
||||
}
|
||||
|
||||
ImGui::Text("Spawn ID: ");
|
||||
ImGui::SameLine();
|
||||
int tempSpawn = returnPlace.mPlayerStatus;
|
||||
if (ImGui::InputInt("##SaveSpawnInput", &tempSpawn)) {
|
||||
returnPlace.mPlayerStatus = tempSpawn;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Text("Horse Location");
|
||||
|
||||
ImGui::Text("Position: ");
|
||||
ImGui::SameLine();
|
||||
Vec tempPos = horsePlace.mPos;
|
||||
if (ImGui::InputFloat3("##HorsePosition", &tempPos.x)) {
|
||||
horsePlace.mPos.x = tempPos.x;
|
||||
horsePlace.mPos.y = tempPos.y;
|
||||
horsePlace.mPos.z = tempPos.z;
|
||||
}
|
||||
|
||||
ImGui::Text("Angle: ");
|
||||
ImGui::SameLine();
|
||||
int tempAngle = horsePlace.mAngleY;
|
||||
if (ImGui::InputInt("##HorsePosition", &tempAngle)) {
|
||||
horsePlace.mAngleY = tempAngle;
|
||||
}
|
||||
|
||||
ImGui::Text("Stage: ");
|
||||
ImGui::SameLine();
|
||||
char horseStageBuffer[8];
|
||||
snprintf(horseStageBuffer, sizeof(horseStageBuffer), "%s", horsePlace.mName);
|
||||
if (ImGui::InputText("##HorseStageNameInput", horseStageBuffer, 8)) {
|
||||
strcpy(horsePlace.mName, horseStageBuffer);
|
||||
}
|
||||
|
||||
ImGui::Text("Room: ");
|
||||
ImGui::SameLine();
|
||||
int tempHorseRoom = horsePlace.mRoomNo;
|
||||
if (ImGui::InputInt("##HorseRoomInput", &tempHorseRoom)) {
|
||||
horsePlace.mRoomNo = tempHorseRoom;
|
||||
}
|
||||
|
||||
ImGui::Text("Spawn ID: ");
|
||||
ImGui::SameLine();
|
||||
int tempHorseSpawn = horsePlace.mSpawnId;
|
||||
if (ImGui::InputInt("##HorseSpawnInput", &tempHorseSpawn)) {
|
||||
horsePlace.mSpawnId = tempHorseSpawn;
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawInventoryTab() {
|
||||
|
||||
}
|
||||
|
||||
void drawFlagList(const char* id, BE(u32)& flags) {
|
||||
u32 tempFlagField = flags;
|
||||
|
||||
for (int i = 31; i >= 0; i--) {
|
||||
if ((31 - i) % 8) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
bool flag = tempFlagField & (1 << i);
|
||||
if (ImGui::Checkbox(fmt::format("{0}{1}", id, i).c_str(), &flag)) {
|
||||
if (flag)
|
||||
tempFlagField |= (1 << i);
|
||||
else
|
||||
tempFlagField &= ~(1 << i);
|
||||
|
||||
flags = tempFlagField;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
ImVec2 cursor = ImGui::GetCursorPos();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGuiBeginGroupPanel("Switch", { 100, 100 });
|
||||
for (int j = 0; j < 4; j++) {
|
||||
drawFlagList(fmt::format("##_switch{}", j).c_str(), membit.mSwitch[j]);
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
ImGui::SetCursorPos(cursor);
|
||||
|
||||
ImGuiBeginGroupPanel("Item", { 100, 100 });
|
||||
for (int j = 0; j < 1; j++) {
|
||||
drawFlagList(fmt::format("##_item{}", j).c_str(), membit.mItem[j]);
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawFlagsTab() {
|
||||
if (ImGui::TreeNode("Current Region Flags")) {
|
||||
dSv_memBit_c& membit = g_dComIfG_gameInfo.info.mMemory.mBit;
|
||||
genMembitFlags("##TempSceneFlags", membit);
|
||||
|
||||
int stageNo = dStage_stagInfo_GetSaveTbl(dComIfGp_getStageStagInfo());
|
||||
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 std::array<const char*, 27> regionNames = {
|
||||
"Ordon",
|
||||
"Hyrule Sewers",
|
||||
"Faron",
|
||||
"Eldin",
|
||||
"Lanayru",
|
||||
"Unknown",
|
||||
"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 (ImGui::BeginCombo("Region", regionNames[m_selectedRegion])) {
|
||||
for (int i = 0; i < regionNames.size(); i++) {
|
||||
if (strcmp(regionNames[i], "Reserved") == 0) continue;
|
||||
|
||||
if (ImGui::Selectable(regionNames[i])) {
|
||||
m_selectedRegion = i;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
dSv_memBit_c* membit = &dComIfGs_getSaveData()->mSave[m_selectedRegion].mBit;
|
||||
if (membit != nullptr) {
|
||||
genMembitFlags("##SaveSceneFlags", *membit);
|
||||
}
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Event Flags")) {
|
||||
dSv_event_c& event = dComIfGs_getSaveData()->mEvent;
|
||||
for (int e = 0; e < 255; e++) {
|
||||
ImGui::Text("%03d ", e);
|
||||
ImGui::SameLine();
|
||||
for (int i = 8; i >= 0; i--) {
|
||||
bool flag = event.mEvent[e] & (1 << i);
|
||||
if (ImGui::Checkbox(fmt::format("##event{0}{1}", e, i).c_str(), &flag)) {
|
||||
if (flag)
|
||||
event.mEvent[e] |= (1 << i);
|
||||
else
|
||||
event.mEvent[e] &= ~(1 << i);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::NewLine();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawConfigTab() {
|
||||
dSv_player_config_c& config = dComIfGs_getSaveData()->getPlayer().getConfig();
|
||||
ImGui::Checkbox("Enable Vibration", (bool*)&config.mVibration);
|
||||
if (ImGui::BeginCombo("Target Type", "Hold")) {
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef DUSK_IMGUI_SAVEEDITOR_HPP
|
||||
#define DUSK_IMGUI_SAVEEDITOR_HPP
|
||||
|
||||
#include <aurora/aurora.h>
|
||||
#include <string>
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
namespace dusk {
|
||||
class ImGuiSaveEditor {
|
||||
public:
|
||||
ImGuiSaveEditor();
|
||||
|
||||
void draw(bool& open);
|
||||
void drawPlayerStatusTab();
|
||||
void drawLocationTab();
|
||||
void drawInventoryTab();
|
||||
void drawFlagsTab();
|
||||
void drawConfigTab();
|
||||
|
||||
private:
|
||||
int m_selectedRegion = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // DUSK_IMGUI_SAVEEDITOR_HPP
|
||||
+4
-39
@@ -5,6 +5,7 @@
|
||||
#include <string.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <unordered_map>
|
||||
@@ -55,42 +56,6 @@ u32 OSGetSoundMode() {
|
||||
// Message Queue (thread-safe implementation)
|
||||
// ==========================================================================
|
||||
|
||||
// Malloc-based allocator to bypass JKRHeap operator new/delete
|
||||
template<typename T>
|
||||
struct MallocAllocator {
|
||||
using value_type = T;
|
||||
MallocAllocator() = default;
|
||||
template<typename U> MallocAllocator(const MallocAllocator<U>&) noexcept {}
|
||||
T* allocate(std::size_t n) {
|
||||
void* p = std::malloc(n * sizeof(T));
|
||||
if (!p) throw std::bad_alloc();
|
||||
return static_cast<T*>(p);
|
||||
}
|
||||
void deallocate(T* p, std::size_t) noexcept { std::free(p); }
|
||||
template<typename U> bool operator==(const MallocAllocator<U>&) const noexcept { return true; }
|
||||
template<typename U> bool operator!=(const MallocAllocator<U>&) const noexcept { return false; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MallocDeleter {
|
||||
void operator()(T* p) const {
|
||||
p->~T();
|
||||
std::free(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T, MallocDeleter<T>> make_malloc_unique(Args&&... args) {
|
||||
void* mem = std::malloc(sizeof(T));
|
||||
if (!mem) throw std::bad_alloc();
|
||||
T* obj = new (mem) T(std::forward<Args>(args)...);
|
||||
return std::unique_ptr<T, MallocDeleter<T>>(obj);
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
using MallocMap = std::unordered_map<K, V, std::hash<K>, std::equal_to<K>,
|
||||
MallocAllocator<std::pair<const K, V>>>;
|
||||
|
||||
// Side-table for native synchronization per OSMessageQueue
|
||||
struct PCMessageQueueData {
|
||||
std::mutex mtx;
|
||||
@@ -103,8 +68,8 @@ static std::mutex& GetMsgQueueMapMutex() {
|
||||
static std::mutex mtx;
|
||||
return mtx;
|
||||
}
|
||||
static MallocMap<OSMessageQueue*, std::unique_ptr<PCMessageQueueData, MallocDeleter<PCMessageQueueData>>>& GetMsgQueueMap() {
|
||||
static MallocMap<OSMessageQueue*, std::unique_ptr<PCMessageQueueData, MallocDeleter<PCMessageQueueData>>> map;
|
||||
static std::unordered_map<OSMessageQueue*, std::unique_ptr<PCMessageQueueData>>& GetMsgQueueMap() {
|
||||
static std::unordered_map<OSMessageQueue*, std::unique_ptr<PCMessageQueueData>> map;
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -113,7 +78,7 @@ static PCMessageQueueData& GetMsgQueueData(OSMessageQueue* mq) {
|
||||
auto& map = GetMsgQueueMap();
|
||||
auto it = map.find(mq);
|
||||
if (it == map.end()) {
|
||||
auto result = map.emplace(mq, make_malloc_unique<PCMessageQueueData>());
|
||||
auto result = map.emplace(mq, std::make_unique<PCMessageQueueData>());
|
||||
return *result.first->second;
|
||||
}
|
||||
return *it->second;
|
||||
|
||||
@@ -442,6 +442,14 @@ void darwFilter(GXColor matColor) {
|
||||
GXLoadPosMtxImm(cMtx_getIdentity(), GX_PNMTX0);
|
||||
GXSetChanMatColor(GX_COLOR0A0, matColor);
|
||||
GXSetCurrentMtx(0);
|
||||
|
||||
#if TARGET_PC
|
||||
f32 width = mDoGph_gInf_c::getWidth();
|
||||
f32 height = mDoGph_gInf_c::getHeight();
|
||||
GXSetViewport(0.0f, 0.0f, width, height, 0.0f, 1.0f);
|
||||
GXSetScissor(0, 0, width, height);
|
||||
#endif
|
||||
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_RGB8, 0);
|
||||
@@ -478,7 +486,7 @@ void mDoGph_gInf_c::calcFade() {
|
||||
}
|
||||
|
||||
if (mFadeColor.a != 0) {
|
||||
//darwFilter(mFadeColor);
|
||||
darwFilter(mFadeColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -272,6 +272,7 @@ int game_main(int argc, char* argv[]) {
|
||||
config.logLevel = (AuroraLogLevel)parsed_arg_options["log-level"].as<uint8_t>();
|
||||
config.mem1Size = 256 * 1024 * 1024;
|
||||
config.mem2Size = 24 * 1024 * 1024;
|
||||
config.allowJoystickBackgroundEvents = true;
|
||||
|
||||
auroraInfo = aurora_initialize(argc, argv, &config);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user