mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-04 11:19:58 -04:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f33489465 | |||
| 23a91a37be | |||
| a886f8a2df | |||
| 6df7b1e9cd | |||
| 206c02b527 | |||
| a05d1a9ee6 | |||
| ed0df01b8d | |||
| 0f9d563a3e | |||
| f3fb65495e | |||
| 196f33005e | |||
| 90c0bdded0 | |||
| f856f871bb | |||
| e75ea18ef0 | |||
| 50e2d9d1a7 | |||
| 5c84978c3c | |||
| 3859f39729 | |||
| 3498ded9d9 | |||
| 8784958c40 | |||
| c1231885fe | |||
| 2b65a696dd | |||
| 02924549be | |||
| 6cf94b4491 | |||
| 30aa2dd527 | |||
| 8e121a7e51 | |||
| 34ec362876 | |||
| ba58d2486e | |||
| f7b5350d60 | |||
| 9ddfcc38c9 | |||
| cee66a6fd5 | |||
| 574b6197a2 | |||
| 6fc8628144 | |||
| ca9330b412 | |||
| 1b792eb964 | |||
| 0e5ea0d3b1 | |||
| 977ad16806 | |||
| 41420bc71c | |||
| 5ec5f8864a | |||
| 60e8836968 | |||
| e755148f16 | |||
| 17949e526b | |||
| 4e264d6a22 | |||
| c8e89a0f99 | |||
| c61e32cd4f | |||
| 274bf61b3e | |||
| 05b2a5cbe9 | |||
| aa838c8003 | |||
| d5aabe9f9e | |||
| 171dbdd0a1 | |||
| b2c09d56d6 | |||
| f0e8379fa5 | |||
| 0d76b90144 | |||
| a6690c2052 |
+6
-8
@@ -280,22 +280,16 @@ set(DUSK_COMPANY_NAME "Twilit Realm")
|
||||
set(DUSK_FILE_DESCRIPTION "Dusk")
|
||||
set(DUSK_PRODUCT_NAME "Dusk")
|
||||
set(DUSK_COPYRIGHT "Copyright (C) Twilit Realm contributors")
|
||||
set(DUSK_GAME_NAME "GZ2E")
|
||||
set(DUSK_GAME_VERSION "01")
|
||||
set(DUSK_TP_VERSION ${DUSK_GAME_NAME}${DUSK_GAME_VERSION})
|
||||
|
||||
message(STATUS "dusk: Game Version: ${DUSK_TP_VERSION}")
|
||||
|
||||
source_group("dolzel" FILES ${DOLZEL_FILES} ${Z2AUDIOLIB_FILES} ${REL_FILES})
|
||||
source_group("dusk" FILES ${DUSK_FILES})
|
||||
|
||||
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0
|
||||
DUSK_TP_VERSION="${DUSK_TP_VERSION}" DUSK_GAME_NAME="${DUSK_GAME_NAME}" DUSK_GAME_VERSION="${DUSK_GAME_VERSION}")
|
||||
set(GAME_COMPILE_DEFS TARGET_PC WIDESCREEN_SUPPORT=1 AVOID_UB=1 VERSION=0)
|
||||
|
||||
set(GAME_INCLUDE_DIRS
|
||||
include
|
||||
src
|
||||
assets/${DUSK_TP_VERSION}
|
||||
assets/GZ2E01 # TODO: make this dynamic if needed?
|
||||
libs/JSystem/include
|
||||
libs
|
||||
extern/aurora/include/dolphin
|
||||
@@ -312,6 +306,10 @@ if (DUSK_ENABLE_SENTRY_NATIVE)
|
||||
list(APPEND GAME_COMPILE_DEFS DUSK_ENABLE_SENTRY_NATIVE=1 SENTRY_BUILD_STATIC=1)
|
||||
endif ()
|
||||
|
||||
if (WIN32)
|
||||
list(APPEND GAME_LIBS Ws2_32)
|
||||
endif ()
|
||||
|
||||
if (DUSK_MOVIE_SUPPORT)
|
||||
if (TARGET libjpeg-turbo::turbojpeg-static)
|
||||
list(APPEND GAME_LIBS libjpeg-turbo::turbojpeg-static)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- ### **[Discord](https://discord.gg/QACynxeyna)**
|
||||
|
||||
# Setup
|
||||
**⚠️Dusk does NOT provide any copyrighted assets. You must provide your own copy of the game.**
|
||||
**⚠️ Dusk does NOT provide any copyrighted assets. You must provide your own copy of the game.**
|
||||
|
||||
### 1. Verify your ROM dump
|
||||
First make sure your dump of the game is clean and supported by Dusk. You can do this by checking the sha1 hash of your dump against this list of supported versions.
|
||||
@@ -22,29 +22,10 @@ First make sure your dump of the game is clean and supported by Dusk. You can do
|
||||
- Select Options, then set the ISO Path to your supported game dump
|
||||
- Press Start Game to play!
|
||||
|
||||

|
||||

|
||||
|
||||
# Building
|
||||
If you'd like to build Dusk from source, please read the [build instructions](docs/building.md).
|
||||
|
||||
# Credits
|
||||
- Taka
|
||||
- encounter
|
||||
- Antidote
|
||||
- caseif
|
||||
- CraftyBoss
|
||||
- crowell
|
||||
- dooplecks
|
||||
- gymnast86
|
||||
- Irastris
|
||||
- kipcode66
|
||||
- Lars
|
||||
- LunarSoap
|
||||
- Maddie
|
||||
- MelonSpeedruns
|
||||
- Pheenoh
|
||||
- PJB
|
||||
- Roeming
|
||||
- YunataSavior
|
||||
|
||||
Special thanks to the TP Decomp team, the GC/Wii Decomp community, the Aurora developers, and the TP speedrunning community.
|
||||
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).
|
||||
|
||||
@@ -13,13 +13,3 @@ buildType:
|
||||
short: RelWithDebInfo
|
||||
long: Optimized, with debug symbols
|
||||
buildType: RelWithDebInfo
|
||||
|
||||
tp_version:
|
||||
default: GZ2E01
|
||||
description: TP Version
|
||||
choices:
|
||||
GZ2E01:
|
||||
short: GZ2E01
|
||||
long: GZ2E01
|
||||
settings:
|
||||
DUSK_TP_VERSION: GZ2E01
|
||||
|
||||
Vendored
+1
-1
Submodule extern/aurora updated: 9ff83bcb97...7784b6fc95
@@ -1460,10 +1460,15 @@ set(DUSK_FILES
|
||||
src/dusk/imgui/ImGuiSaveEditor.cpp
|
||||
src/dusk/imgui/ImGuiStateShare.hpp
|
||||
src/dusk/imgui/ImGuiStateShare.cpp
|
||||
src/dusk/imgui/ImGuiAchievements.hpp
|
||||
src/dusk/imgui/ImGuiAchievements.cpp
|
||||
src/dusk/achievements.cpp
|
||||
src/dusk/iso_validate.cpp
|
||||
src/dusk/livesplit.cpp
|
||||
src/dusk/offset_ptr.cpp
|
||||
src/dusk/OSContext.cpp
|
||||
src/dusk/OSThread.cpp
|
||||
src/dusk/OSMutex.cpp
|
||||
src/dusk/discord_presence.cpp
|
||||
src/dusk/version.cpp
|
||||
)
|
||||
|
||||
@@ -188,6 +188,15 @@ public:
|
||||
/* 0x273C */ f32 mKankyoBlend;
|
||||
/* 0x2740 */ u8 field_0x2740;
|
||||
/* 0x2744 */ dMsgFlow_c mMsgFlow;
|
||||
#if TARGET_PC
|
||||
cXyz mReinsInterpPrev[2][16];
|
||||
cXyz mReinsInterpCurr[2][16];
|
||||
cXyz mReinsTexInterpPrev[2];
|
||||
cXyz mReinsTexInterpCurr[2];
|
||||
bool mReinsInterpPrevValid;
|
||||
bool mReinsInterpCurrValid;
|
||||
s8 mDemoCamSyncTicks;
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(b_gnd_class) == 0x2790);
|
||||
|
||||
@@ -44,6 +44,12 @@ public:
|
||||
/* 0x88C */ u8 field_0x88C[0x8C8 - 0x88C];
|
||||
/* 0x8C8 */ s8 field_0x8c8;
|
||||
/* 0x8C9 */ u8 mInitHIO;
|
||||
#if TARGET_PC
|
||||
cXyz mRopeInterpPrev[16];
|
||||
cXyz mRopeInterpCurr[16];
|
||||
bool mRopeInterpPrevValid;
|
||||
bool mRopeInterpCurrValid;
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC_ASSERT(sizeof(e_mb_class) == 0x8cc);
|
||||
|
||||
@@ -58,6 +58,9 @@ public:
|
||||
void setNextPoint();
|
||||
int Draw();
|
||||
int Delete();
|
||||
#if TARGET_PC
|
||||
friend void daL8Lift_interp_callback(bool isSimFrame, void* pUserWork);
|
||||
#endif
|
||||
|
||||
u8 getPthID() { return fopAcM_GetParamBit(this, 0, 8); }
|
||||
u8 getMoveSpeed() { return fopAcM_GetParamBit(this, 8, 4); }
|
||||
|
||||
@@ -143,6 +143,12 @@ public:
|
||||
/* 0x20 */ JORFile mFile;
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
/* 0x24 */ u8 mManualMode;
|
||||
/* 0x25 */ f32 freeXAngle;
|
||||
/* 0x29 */ f32 freeYAngle;
|
||||
#endif
|
||||
|
||||
u32 Id(s32 i_style) { return mCamStyleData[i_style].field_0x0; }
|
||||
int Algorythmn(s32 i_style) { return mCamStyleData[i_style].field_0x4; }
|
||||
int Algorythmn() { return mCurrentStyle->field_0x4; }
|
||||
|
||||
@@ -273,6 +273,8 @@ public:
|
||||
/* 0xA4 */ f32 field_0xa4;
|
||||
/* 0xA8 */ int field_0xa8;
|
||||
/* 0xAC */ f32 field_0xac;
|
||||
f32 xAngle;
|
||||
f32 yAngle;
|
||||
};
|
||||
|
||||
struct LockOnData {
|
||||
@@ -1024,6 +1026,9 @@ public:
|
||||
bool colosseumCamera(s32);
|
||||
bool test1Camera(s32);
|
||||
bool test2Camera(s32);
|
||||
#if TARGET_PC
|
||||
bool freeCamera();
|
||||
#endif
|
||||
bool towerCamera(s32);
|
||||
bool hookshotCamera(s32);
|
||||
bool railCamera(s32);
|
||||
|
||||
@@ -343,6 +343,11 @@ public:
|
||||
/* 0x624 */ f32 mMidonaPosX;
|
||||
/* 0x628 */ f32 mMidonaPosY;
|
||||
/* 0x62C */ f32 mMidonaScale;
|
||||
|
||||
#ifdef TARGET_PC
|
||||
bool mWasListen[2];
|
||||
bool mWasRepeat[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* D_METER_D_METER_BUTTON_H */
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ public:
|
||||
void MojiSelectAnm3();
|
||||
int mojiChange(u8);
|
||||
void selectMojiSet();
|
||||
#if REGION_JPN
|
||||
#if TARGET_PC || REGION_JPN
|
||||
int checkDakuon(int, u8);
|
||||
int setDakuon(int, u8);
|
||||
#endif
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
bool isProgressiveMode();
|
||||
void setRenderMode();
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL || PLATFORM_WII || PLATFORM_SHIELD
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL || PLATFORM_WII || PLATFORM_SHIELD
|
||||
u8 getPalLanguage();
|
||||
#endif
|
||||
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
/* 0x200 */ dDlst_2D_c* mNvLogo;
|
||||
/* 0x204 */ dDlst_2D_c* mMocImg;
|
||||
#endif
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
/* 0x1FC */ mDoDvdThd_mountArchive_c* mpPalLogoResCommand;
|
||||
#endif
|
||||
/* 0x1FC */ request_of_phase_process_class* m_preLoad_dylPhase;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace dusk {
|
||||
|
||||
enum class AchievementCategory : uint8_t {
|
||||
Story,
|
||||
Collection,
|
||||
Challenge,
|
||||
Minigame,
|
||||
Glitched
|
||||
};
|
||||
|
||||
struct Achievement {
|
||||
const char* key;
|
||||
const char* name;
|
||||
const char* description;
|
||||
AchievementCategory category;
|
||||
bool isCounter;
|
||||
int32_t goal;
|
||||
int32_t progress;
|
||||
bool unlocked;
|
||||
};
|
||||
|
||||
// Responsible for updating a.progress.
|
||||
// Use extra for any per-achievement state that must survive across frames or sessions, extra is saved
|
||||
using AchievementCheckFn = std::function<void(Achievement& a, nlohmann::json& extra)>;
|
||||
|
||||
class AchievementSystem {
|
||||
public:
|
||||
static AchievementSystem& get();
|
||||
|
||||
void load();
|
||||
void save();
|
||||
void tick();
|
||||
void clearAll();
|
||||
|
||||
std::vector<Achievement> getAchievements() const;
|
||||
bool hasPendingUnlock() const { return !m_pendingUnlocks.empty(); }
|
||||
std::string consumePendingUnlock();
|
||||
|
||||
private:
|
||||
struct Entry {
|
||||
Achievement achievement;
|
||||
AchievementCheckFn check;
|
||||
nlohmann::json extra;
|
||||
};
|
||||
|
||||
AchievementSystem();
|
||||
static std::vector<Entry> makeEntries();
|
||||
void processEntry(Entry& e);
|
||||
|
||||
std::vector<Entry> m_entries;
|
||||
bool m_loaded = false;
|
||||
bool m_dirty = false;
|
||||
std::queue<std::string> m_pendingUnlocks;
|
||||
};
|
||||
|
||||
} // namespace dusk
|
||||
@@ -1,22 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "dolphin/types.h"
|
||||
#include "version.hpp"
|
||||
|
||||
namespace dusk {
|
||||
|
||||
struct OffsetVersion {
|
||||
version::GameVersion mGameVersion;
|
||||
u32 mOffset;
|
||||
|
||||
constexpr OffsetVersion(const version::GameVersion gameVersion, const u32 offset)
|
||||
: mGameVersion(gameVersion), mOffset(offset) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load bytes from the main DOL by GameCube virtual address
|
||||
*/
|
||||
bool LoadDolAsset(void* dst, u32 virtualAddress, s32 size);
|
||||
bool LoadDolAsset(void* dst, std::initializer_list<OffsetVersion> virtualAddress, s32 size);
|
||||
|
||||
/**
|
||||
* Load bytes from a REL file in the ISO filesystem, dst must be 32-byte aligned
|
||||
*/
|
||||
bool LoadRelAsset(void* dst, const char* dvdPath, s32 offset, s32 size);
|
||||
bool LoadRelAsset(void* dst, const char* dvdPath, std::initializer_list<OffsetVersion> offset, s32 size);
|
||||
|
||||
/**
|
||||
* Load bytes from a REL inside RELS.arc
|
||||
*/
|
||||
bool LoadArchivedRelAsset(void* dst, u32 memType, const char* relFileName, s32 offset, s32 size);
|
||||
bool LoadArchivedRelAsset(void* dst, u32 memType, const char* relFileName, std::initializer_list<OffsetVersion> offset, s32 size);
|
||||
|
||||
} // namespace dusk
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace dusk::speedrun {
|
||||
void onGameFrame();
|
||||
uint64_t getFrameCount();
|
||||
void start();
|
||||
void reset();
|
||||
void connectLiveSplit(const char* host = "127.0.0.1", int port = 16834);
|
||||
void disconnectLiveSplit();
|
||||
bool consumeConnectedEvent();
|
||||
bool consumeDisconnectedEvent();
|
||||
void updateLiveSplit();
|
||||
void shutdown();
|
||||
}
|
||||
+26
-1
@@ -13,12 +13,26 @@ enum class BloomMode : int {
|
||||
Dusk = 2,
|
||||
};
|
||||
|
||||
enum class GameLanguage : u8 {
|
||||
English = OS_LANGUAGE_ENGLISH,
|
||||
German = OS_LANGUAGE_GERMAN,
|
||||
French = OS_LANGUAGE_FRENCH,
|
||||
Spanish = OS_LANGUAGE_SPANISH,
|
||||
Italian = OS_LANGUAGE_ITALIAN,
|
||||
};
|
||||
|
||||
namespace config {
|
||||
template <>
|
||||
struct ConfigEnumRange<BloomMode> {
|
||||
static constexpr auto min = BloomMode::Off;
|
||||
static constexpr auto max = BloomMode::Dusk;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ConfigEnumRange<GameLanguage> {
|
||||
static constexpr auto min = GameLanguage::English;
|
||||
static constexpr auto max = GameLanguage::Italian;
|
||||
};
|
||||
}
|
||||
|
||||
// Persistent user settings
|
||||
@@ -46,6 +60,8 @@ struct UserSettings {
|
||||
// Game settings
|
||||
|
||||
struct {
|
||||
ConfigVar<GameLanguage> language;
|
||||
|
||||
// QoL
|
||||
ConfigVar<bool> enableQuickTransform;
|
||||
ConfigVar<bool> hideTvSettingsScreen;
|
||||
@@ -66,10 +82,10 @@ struct UserSettings {
|
||||
|
||||
// Preferences
|
||||
ConfigVar<bool> enableMirrorMode;
|
||||
ConfigVar<bool> invertCameraXAxis;
|
||||
ConfigVar<bool> disableMainHUD;
|
||||
ConfigVar<bool> pauseOnFocusLost;
|
||||
ConfigVar<bool> enableLinkDollRotation;
|
||||
ConfigVar<bool> enableAchievementNotifications;
|
||||
|
||||
|
||||
// Graphics
|
||||
@@ -80,6 +96,7 @@ struct UserSettings {
|
||||
ConfigVar<int> internalResolutionScale;
|
||||
ConfigVar<int> shadowResolutionMultiplier;
|
||||
ConfigVar<bool> enableDepthOfField;
|
||||
ConfigVar<bool> enableMapBackground;
|
||||
|
||||
// Audio
|
||||
ConfigVar<bool> noLowHpSound;
|
||||
@@ -95,6 +112,10 @@ struct UserSettings {
|
||||
ConfigVar<float> gyroDeadband;
|
||||
ConfigVar<bool> gyroInvertPitch;
|
||||
ConfigVar<bool> gyroInvertYaw;
|
||||
ConfigVar<bool> freeCamera;
|
||||
ConfigVar<bool> invertCameraXAxis;
|
||||
ConfigVar<bool> invertCameraYAxis;
|
||||
ConfigVar<float> freeCameraSensitivity;
|
||||
|
||||
// Cheats
|
||||
ConfigVar<bool> infiniteHearts;
|
||||
@@ -117,6 +138,10 @@ struct UserSettings {
|
||||
|
||||
// Controls
|
||||
ConfigVar<bool> enableTurboKeybind;
|
||||
|
||||
// Tools
|
||||
ConfigVar<bool> speedrunMode;
|
||||
ConfigVar<bool> liveSplitEnabled;
|
||||
} game;
|
||||
|
||||
struct {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef DUSK_VERSION_HPP
|
||||
#define DUSK_VERSION_HPP
|
||||
|
||||
/**
|
||||
* Functionality for switching game behavior based on the loaded game version (e.g. PAL/JPN, GC/Wii)
|
||||
*/
|
||||
namespace dusk::version {
|
||||
enum class GameVersion : u8 {
|
||||
GcnUsa = VERSION_GCN_USA,
|
||||
GcnPal = VERSION_GCN_PAL,
|
||||
GcnJpn = VERSION_GCN_JPN,
|
||||
WiiUsaRev0 = VERSION_WII_USA_R0,
|
||||
WiiUsa = VERSION_WII_USA_R2,
|
||||
WiiPal = VERSION_WII_PAL,
|
||||
WiiJpn = VERSION_WII_JPN,
|
||||
WiiKor = VERSION_WII_KOR,
|
||||
};
|
||||
|
||||
bool isGcn();
|
||||
bool isWii();
|
||||
bool isPalOrAtLeastWiiR2();
|
||||
|
||||
bool isRegionPal();
|
||||
bool isRegionJpn();
|
||||
bool isRegionUsa();
|
||||
|
||||
GameVersion getGameVersion();
|
||||
|
||||
const DVDDiskID& getDiskID();
|
||||
|
||||
void init();
|
||||
|
||||
template<typename T>
|
||||
struct VersionOption {
|
||||
GameVersion mVersion;
|
||||
T mValue;
|
||||
|
||||
constexpr VersionOption(GameVersion version, T value) : mVersion(version), mValue(value) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
const T& versionSelect(const std::initializer_list<VersionOption<T>> options) {
|
||||
const auto version = getGameVersion();
|
||||
for (const auto& opt : options) {
|
||||
if (opt.mVersion == version) {
|
||||
return opt.mValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Unable to find value.
|
||||
abort();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T& versionSelect(const std::initializer_list<VersionOption<T>> options, const T& defaultValue) {
|
||||
const auto version = getGameVersion();
|
||||
for (const auto& opt : options) {
|
||||
if (opt.mVersion == version) {
|
||||
return opt.mValue;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
} // namespace dusk::version
|
||||
|
||||
#endif // DUSK_VERSION_HPP
|
||||
@@ -230,12 +230,16 @@ using std::isnan;
|
||||
// Some basic macros that are more convenient than putting down #if blocks for one-line changes.
|
||||
#if TARGET_PC
|
||||
#define IF_DUSK(statement) statement
|
||||
#define IF_DUSK_BLOCK(cond) if (cond) {
|
||||
#define IF_DUSK_BLOCK_END }
|
||||
#define IF_DUSK_ARG(expr) , expr
|
||||
#define IF_NOT_DUSK(statement)
|
||||
#define DUSK_IF_ELSE(dusk, orig) dusk
|
||||
#else
|
||||
#define IF_DUSK(statement)
|
||||
#define IF_DUSK_ARG(expr)
|
||||
#define IF_DUSK_BLOCK(cond)
|
||||
#define IF_DUSK_BLOCK_END
|
||||
#define IF_NOT_DUSK(statement) statement
|
||||
#define DUSK_IF_ELSE(dusk, orig) orig
|
||||
#endif
|
||||
|
||||
@@ -468,9 +468,20 @@ s16 cLib_targetAngleX(cXyz const* lhs, cXyz const* rhs) {
|
||||
void cLib_offsetPos(cXyz* pdest, cXyz const* psrc, s16 angle, cXyz const* vec) {
|
||||
f32 cos = cM_scos(angle);
|
||||
f32 sin = cM_ssin(angle);
|
||||
// MWCC loads vec members into registers before writing to pdest; other compilers may not,
|
||||
// which corrupts results when pdest and vec alias the same memory.
|
||||
#if !__MWERKS__
|
||||
f32 vx = vec->x;
|
||||
f32 vy = vec->y;
|
||||
f32 vz = vec->z;
|
||||
pdest->x = psrc->x + (vx * cos + vz * sin);
|
||||
pdest->y = psrc->y + vy;
|
||||
pdest->z = psrc->z + (vz * cos - vx * sin);
|
||||
#else
|
||||
pdest->x = psrc->x + (vec->x * cos + vec->z * sin);
|
||||
pdest->y = psrc->y + vec->y;
|
||||
pdest->z = psrc->z + (vec->z * cos - vec->x * sin);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5877,6 +5877,11 @@ void daAlink_c::setItemMatrix(int param_0) {
|
||||
modelCalc(mSheathModel);
|
||||
|
||||
int var_r26;
|
||||
|
||||
#if AVOID_UB
|
||||
var_r26 = 0;
|
||||
#endif
|
||||
|
||||
if (!checkNoResetFlg3(FLG3_UNK_4000000)) {
|
||||
if (mEquipItem == 0x103 || param_0 != 0) {
|
||||
mSwordModel->setBaseTRMtx(mpLinkModel->getAnmMtx(mLeftItemJntNo));
|
||||
@@ -18936,11 +18941,20 @@ void daAlink_c::setDrawHand() {
|
||||
mpLinkHandModel->setBaseTRMtx(mpLinkModel->getBaseTRMtx());
|
||||
mpLinkHandModel->calc();
|
||||
|
||||
#if TARGET_PC
|
||||
// FRAME INTERP NOTE: Always set these, otherwise the hands occasionally zip to origin.
|
||||
// Doing it regardless of interpolation being active seems harmless.
|
||||
mpLinkHandModel->setAnmMtx(1, mpLinkModel->getAnmMtx(9));
|
||||
mpLinkHandModel->setAnmMtx(2, mpLinkModel->getAnmMtx(0xE));
|
||||
#endif
|
||||
|
||||
if (var_r30 == 0xFE || var_r30 == 0xFB) {
|
||||
field_0x06d0 = field_0x06d8;
|
||||
} else {
|
||||
field_0x06d0 = mpLinkHandModel->getModelData()->getMaterialNodePointer(var_r30)->getShape();
|
||||
#if !TARGET_PC
|
||||
mpLinkHandModel->setAnmMtx(1, mpLinkModel->getAnmMtx(9));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (var_r30 == 0xFB) {
|
||||
@@ -18959,7 +18973,9 @@ void daAlink_c::setDrawHand() {
|
||||
field_0x06d4 = field_0x06dc;
|
||||
} else {
|
||||
field_0x06d4 = mpLinkHandModel->getModelData()->getMaterialNodePointer(var_r29)->getShape();
|
||||
#if !TARGET_PC
|
||||
mpLinkHandModel->setAnmMtx(2, mpLinkModel->getAnmMtx(0xE));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (var_r29 == 0xFB) {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "d/actor/d_a_npc_tkc.h"
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||
#include "dusk/settings.h"
|
||||
|
||||
BOOL daAlink_c::checkEventRun() const {
|
||||
@@ -4005,6 +4006,15 @@ int daAlink_c::procGanonFinishInit() {
|
||||
|
||||
field_0x37c8 = current.pos;
|
||||
onEndResetFlg1(ERFLG1_SHIELD_BACKBONE);
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.speedrunMode) {
|
||||
if (dusk::m_speedrunInfo.m_isRunStarted) {
|
||||
dusk::m_speedrunInfo.stopRun();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
#include "Z2AudioLib/Z2Instances.h"
|
||||
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/settings.h"
|
||||
|
||||
class daB_GND_HIO_c : public JORReflexible {
|
||||
public:
|
||||
daB_GND_HIO_c();
|
||||
@@ -279,6 +282,30 @@ static int h_nodeCallBack(J3DJoint* i_joint, int param_2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static void b_gnd_rein_interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
b_gnd_class* i_this = (b_gnd_class*)pUserWork;
|
||||
if (!i_this->mReinsInterpPrevValid || !i_this->mReinsInterpCurrValid) {
|
||||
return;
|
||||
}
|
||||
const f32 alpha = dusk::frame_interp::get_interpolation_step();
|
||||
for (int r = 0; r < 2; r++) {
|
||||
cXyz* dst = i_this->mHorseReins[r].getPos(0);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
const cXyz& p0 = i_this->mReinsInterpPrev[r][i];
|
||||
const cXyz& p1 = i_this->mReinsInterpCurr[r][i];
|
||||
dst[i] = p0 + (p1 - p0) * alpha;
|
||||
}
|
||||
}
|
||||
cXyz* dst = i_this->field_0x21e8.getPos(0);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
const cXyz& p0 = i_this->mReinsTexInterpPrev[i];
|
||||
const cXyz& p1 = i_this->mReinsTexInterpCurr[i];
|
||||
dst[i] = p0 + (p1 - p0) * alpha;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int daB_GND_Draw(b_gnd_class* i_this) {
|
||||
fopAc_ac_c* a_this = (fopAc_ac_c*)i_this;
|
||||
|
||||
@@ -366,6 +393,21 @@ static int daB_GND_Draw(b_gnd_class* i_this) {
|
||||
|
||||
i_this->field_0x21e8.update(2, l_color, &a_this->tevStr);
|
||||
dComIfGd_set3DlineMat(&i_this->field_0x21e8);
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
if (i_this->mReinsInterpCurrValid) {
|
||||
memcpy(i_this->mReinsInterpPrev, i_this->mReinsInterpCurr, sizeof(i_this->mReinsInterpCurr));
|
||||
memcpy(i_this->mReinsTexInterpPrev, i_this->mReinsTexInterpCurr, sizeof(i_this->mReinsTexInterpCurr));
|
||||
i_this->mReinsInterpPrevValid = true;
|
||||
}
|
||||
for (int r = 0; r < 2; r++) {
|
||||
memcpy(i_this->mReinsInterpCurr[r], i_this->mHorseReins[r].getPos(0), 16 * sizeof(cXyz));
|
||||
}
|
||||
memcpy(i_this->mReinsTexInterpCurr, i_this->field_0x21e8.getPos(0), 2 * sizeof(cXyz));
|
||||
i_this->mReinsInterpCurrValid = true;
|
||||
dusk::frame_interp::add_interpolation_callback(&b_gnd_rein_interp_callback, i_this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -1189,10 +1231,16 @@ static void b_gnd_h_end(b_gnd_class* i_this) {
|
||||
|
||||
if (i_this->mDemoCamMode < 32) {
|
||||
i_this->mDemoCamMode = 32;
|
||||
#if TARGET_PC
|
||||
i_this->mDemoCamSyncTicks = 2;
|
||||
#endif
|
||||
} else {
|
||||
i_this->mDemoCamMode = 34;
|
||||
i_this->mDemoCamTimer = 0;
|
||||
i_this->mMoveMode = 2;
|
||||
#if TARGET_PC
|
||||
i_this->mDemoCamSyncTicks = 2;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2887,6 +2935,9 @@ static void demo_camera(b_gnd_class* i_this) {
|
||||
cXyz spF0;
|
||||
|
||||
s8 sp8 = false;
|
||||
#if TARGET_PC
|
||||
const s16 entry_demo_cam_mode = i_this->mDemoCamMode;
|
||||
#endif
|
||||
switch (i_this->mDemoCamMode) {
|
||||
case 0:
|
||||
break;
|
||||
@@ -3725,6 +3776,15 @@ static void demo_camera(b_gnd_class* i_this) {
|
||||
i_this->mDemoCamTimer = 10000;
|
||||
}
|
||||
}
|
||||
#if TARGET_PC
|
||||
if (entry_demo_cam_mode != i_this->mDemoCamMode) {
|
||||
i_this->mDemoCamSyncTicks = 2;
|
||||
}
|
||||
if (i_this->mDemoCamSyncTicks > 0) {
|
||||
dusk::frame_interp::request_presentation_sync();
|
||||
i_this->mDemoCamSyncTicks--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void anm_se_set(b_gnd_class* i_this) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "d/dolzel_rel.h" // IWYU pragma: keep
|
||||
|
||||
#include "d/actor/d_a_balloon_2D.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "JSystem/J2DGraph/J2DGrafContext.h"
|
||||
#include "JSystem/J2DGraph/J2DScreen.h"
|
||||
#include "JSystem/J2DGraph/J2DTextBox.h"
|
||||
@@ -438,7 +439,12 @@ void daBalloon2D_c::setComboAlpha() {
|
||||
void daBalloon2D_c::drawAddScore() {
|
||||
for (s32 i = 19; i >= 0; i--) {
|
||||
if (field_0x5f8[i].field_0xe != 0) {
|
||||
field_0x5f8[i].field_0xe--;
|
||||
#ifdef TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
field_0x5f8[i].field_0xe--;
|
||||
}
|
||||
s32 score3;
|
||||
s32 score2;
|
||||
s32 score = field_0x5f8[i].field_0xc;
|
||||
@@ -446,8 +452,13 @@ void daBalloon2D_c::drawAddScore() {
|
||||
u8 local_88 = 0xff;
|
||||
f32 dVar11 = 30.0f;
|
||||
f32 dVar9 = 30.0f;
|
||||
field_0x5f8[i].field_0x0.x += cM_ssin(temp0) * 0.3f;
|
||||
field_0x5f8[i].field_0x0.y -= 1.0f;
|
||||
#ifdef TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
field_0x5f8[i].field_0x0.x += cM_ssin(temp0) * 0.3f;
|
||||
field_0x5f8[i].field_0x0.y -= 1.0f;
|
||||
}
|
||||
if (field_0x5f8[i].field_0xe < 10) {
|
||||
f32 fVar5 = field_0x5f8[i].field_0xe / 10.0f;
|
||||
local_88 = fVar5 * 255.0f;
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "d/d_bomb.h"
|
||||
#include "c/c_damagereaction.h"
|
||||
#include "Z2AudioLib/Z2Instances.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/settings.h"
|
||||
|
||||
#define ACTION_STANDBY 0
|
||||
#define ACTION_WALK1 1
|
||||
@@ -63,6 +65,22 @@ static void anm_init(e_mb_class* i_this, int i_anmID, f32 i_morf, u8 i_attr, f32
|
||||
i_this->mAnm = i_anmID;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static void e_mb_rope_interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
e_mb_class* i_this = (e_mb_class*)pUserWork;
|
||||
if (!i_this->mRopeInterpPrevValid || !i_this->mRopeInterpCurrValid) {
|
||||
return;
|
||||
}
|
||||
const f32 alpha = dusk::frame_interp::get_interpolation_step();
|
||||
cXyz* dst = i_this->mRopeMat.getPos(0);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
const cXyz& p0 = i_this->mRopeInterpPrev[i];
|
||||
const cXyz& p1 = i_this->mRopeInterpCurr[i];
|
||||
dst[i] = p0 + (p1 - p0) * alpha;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int daE_MB_Draw(e_mb_class* i_this) {
|
||||
fopAc_ac_c* a_this = (fopAc_ac_c*)i_this;
|
||||
|
||||
@@ -86,6 +104,17 @@ static int daE_MB_Draw(e_mb_class* i_this) {
|
||||
static GXColor l_color = {0x14, 0x0F, 0x00, 0xFF};
|
||||
i_this->mRopeMat.update(16, l_color, &a_this->tevStr);
|
||||
dComIfGd_set3DlineMat(&i_this->mRopeMat);
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
if (i_this->mRopeInterpCurrValid) {
|
||||
memcpy(i_this->mRopeInterpPrev, i_this->mRopeInterpCurr, sizeof(i_this->mRopeInterpCurr));
|
||||
i_this->mRopeInterpPrevValid = true;
|
||||
}
|
||||
memcpy(i_this->mRopeInterpCurr, i_this->mRopeMat.getPos(0), 16 * sizeof(cXyz));
|
||||
i_this->mRopeInterpCurrValid = true;
|
||||
dusk::frame_interp::add_interpolation_callback(&e_mb_rope_interp_callback, i_this);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
#include <cstring>
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
class daE_SM2_HIO_c : public fOpAcm_HIO_entry_c {
|
||||
public:
|
||||
daE_SM2_HIO_c();
|
||||
@@ -76,8 +80,62 @@ static int nodeCallBack(J3DJoint* i_joint, int param_1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static void daE_SM2_interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
e_sm2_class* i_this = static_cast<e_sm2_class*>(pUserWork);
|
||||
if (i_this == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
fopAc_ac_c* actor = (fopAc_ac_c*)&i_this->enemy;
|
||||
g_env_light.settingTevStruct(0, &actor->current.pos, &actor->tevStr);
|
||||
|
||||
if (!i_this->isPiece) {
|
||||
if (i_this->modelMorf == NULL) {
|
||||
return;
|
||||
}
|
||||
J3DModel* model = i_this->modelMorf->getModel();
|
||||
if (model == NULL) {
|
||||
return;
|
||||
}
|
||||
g_env_light.setLightTevColorType_MAJI(model, &actor->tevStr);
|
||||
|
||||
J3DMaterial* material = model->getModelData()->getMaterialNodePointer(0);
|
||||
material->getTevKColor(1)->r = i_this->color_R;
|
||||
material->getTevKColor(1)->g = i_this->color_G;
|
||||
material->getTevKColor(1)->b = i_this->color_B;
|
||||
material->getTevKColor(1)->a = 217.0f * i_this->color_alpha;
|
||||
|
||||
if (i_this->pbtk != NULL) {
|
||||
i_this->pbtk->entry(model->getModelData());
|
||||
}
|
||||
} else {
|
||||
if (i_this->pieceModelMorf == NULL) {
|
||||
return;
|
||||
}
|
||||
J3DModel* model = i_this->pieceModelMorf->getModel();
|
||||
if (model == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
J3DMaterial* material = model->getModelData()->getMaterialNodePointer(0);
|
||||
material->getTevKColor(1)->r = i_this->color_R;
|
||||
material->getTevKColor(1)->g = i_this->color_G;
|
||||
material->getTevKColor(1)->b = i_this->color_B;
|
||||
material->getTevKColor(1)->a = 217.0f * i_this->color_alpha;
|
||||
|
||||
g_env_light.setLightTevColorType_MAJI(model, &actor->tevStr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int daE_SM2_Draw(e_sm2_class* i_this) {
|
||||
fopAc_ac_c* actor = (fopAc_ac_c*)&i_this->enemy;
|
||||
|
||||
#if TARGET_PC
|
||||
dusk::frame_interp::add_interpolation_callback(&daE_SM2_interp_callback, i_this);
|
||||
#endif
|
||||
|
||||
g_env_light.settingTevStruct(0, &actor->current.pos, &actor->tevStr);
|
||||
|
||||
J3DModel* model;
|
||||
|
||||
@@ -1069,7 +1069,7 @@ void daE_YM_c::executeDown() {
|
||||
if (mAcch.ChkGroundHit()) {
|
||||
if (mFlyType != 1) {
|
||||
#if TARGET_PC
|
||||
bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 2.0f : 1.0f);
|
||||
bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears ? 2.0f : 1.0f);
|
||||
#else
|
||||
bckSet(6, 0, 0.0f, 1.0f);
|
||||
#endif
|
||||
@@ -1093,7 +1093,7 @@ void daE_YM_c::executeDown() {
|
||||
mSound.startCreatureSound(Z2SE_CM_BODYFALL_WATER_M, 0, -1);
|
||||
mSound.startCreatureSound(Z2SE_EN_YM_MOGAKU, 0, -1);
|
||||
#if TARGET_PC
|
||||
bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 2.0f : 1.0f);
|
||||
bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears ? 2.0f : 1.0f);
|
||||
#else
|
||||
bckSet(6, 0, 0.0f, 1.0f);
|
||||
#endif
|
||||
@@ -1115,7 +1115,7 @@ void daE_YM_c::executeDown() {
|
||||
|| dComIfG_Bgsp().GetGroundCode(gnd_chk) == 5)
|
||||
{
|
||||
#if TARGET_PC
|
||||
bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 2.0f : 1.0f);
|
||||
bckSet(6, 0, 0.0f, dusk::getSettings().game.fastTears ? 2.0f : 1.0f);
|
||||
#else
|
||||
bckSet(6, 0, 0.0f, 1.0f);
|
||||
#endif
|
||||
|
||||
@@ -13,9 +13,12 @@
|
||||
#if TARGET_PC
|
||||
#include "dusk/dvd_asset.hpp"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
static u8* l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", 0x1C00, 0x4000), true); return buf; }
|
||||
static u8* l_Egnd_mantTEX_U_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", 0x5C00, 0x4000), true); return buf; }
|
||||
static u8* l_Egnd_mantPAL_get() { alignas(32) static u8 buf[0x60]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", 0x9C00, 0x60), true); return buf; }
|
||||
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
|
||||
static u8* l_Egnd_mantTEX_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x1C00}, {GameVersion::GcnPal, 0x1C00}}, 0x4000), true); return buf; }
|
||||
static u8* l_Egnd_mantTEX_U_get() { alignas(32) static u8 buf[0x4000]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x5C00}, {GameVersion::GcnPal, 0x5C00}}, 0x4000), true); return buf; }
|
||||
static u8* l_Egnd_mantPAL_get() { alignas(32) static u8 buf[0x60]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0x9C00}, {GameVersion::GcnPal, 0x9C00}}, 0x60), true); return buf; }
|
||||
#define l_Egnd_mantTEX (l_Egnd_mantTEX_get())
|
||||
#define l_Egnd_mantTEX_U (l_Egnd_mantTEX_U_get())
|
||||
#define l_Egnd_mantPAL (l_Egnd_mantPAL_get())
|
||||
@@ -251,7 +254,9 @@ static u32 l_texCoord[338] = {
|
||||
};
|
||||
|
||||
#if TARGET_PC
|
||||
static u8* l_Egnd_mantDL_get() { alignas(32) static u8 buf[0x3EC]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", 0xA9A0, 0x3EC), true); return buf; }
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
|
||||
static u8* l_Egnd_mantDL_get() { alignas(32) static u8 buf[0x3EC]; static bool _ = (dusk::LoadRelAsset(buf, "/rel/Final/Release/d_a_mant.rel", {{GameVersion::GcnUsa, 0xA9A0}, {GameVersion::GcnPal, 0xA9A0}}, 0x3EC), true); return buf; }
|
||||
#define l_Egnd_mantDL (l_Egnd_mantDL_get())
|
||||
#else
|
||||
#include "assets/l_Egnd_mantDL.h"
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "d/d_s_play.h"
|
||||
#include "d/d_vibration.h"
|
||||
#include "f_op/f_op_kankyo_mng.h"
|
||||
#include "dusk/version.hpp"
|
||||
#include <cstring>
|
||||
|
||||
#define ANM_MG_FISH_MOUTH_CLOSE 4
|
||||
@@ -3230,7 +3231,17 @@ static int daMg_Fish_Execute(mg_fish_class* i_this) {
|
||||
|
||||
daPy_py_c* player = daPy_getPlayerActorClass();
|
||||
|
||||
#if VERSION == VERSION_GCN_JPN
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionJpn()) {
|
||||
lit_1008 = 0;
|
||||
} else if (dusk::version::isRegionPal()) {
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_ENGLISH) {
|
||||
lit_1008 = 2;
|
||||
} else {
|
||||
lit_1008 = 0;
|
||||
}
|
||||
}
|
||||
#elif VERSION == VERSION_GCN_JPN
|
||||
lit_1008 = 0;
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_ENGLISH) {
|
||||
@@ -3843,7 +3854,19 @@ static int daMg_Fish_Create(fopAc_ac_c* i_this) {
|
||||
a_this->mResName = "O_gD_bott";
|
||||
}
|
||||
|
||||
#if VERSION == VERSION_GCN_JPN
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionJpn()) {
|
||||
lit_1008 = 0;
|
||||
} else if (dusk::version::isRegionPal()) {
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_ENGLISH) {
|
||||
lit_1008 = 2;
|
||||
} else {
|
||||
lit_1008 = 0;
|
||||
}
|
||||
} else {
|
||||
lit_1008 = 1;
|
||||
}
|
||||
#elif VERSION == VERSION_GCN_JPN
|
||||
lit_1008 = 0;
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_ENGLISH) {
|
||||
|
||||
@@ -5,14 +5,15 @@
|
||||
|
||||
#include "d/dolzel_rel.h" // IWYU pragma: keep
|
||||
|
||||
#include "Z2AudioLib/Z2Instances.h"
|
||||
#include "d/actor/d_a_mg_fish.h"
|
||||
#include "d/actor/d_a_mg_fshop.h"
|
||||
#include "d/actor/d_a_npc_henna.h"
|
||||
#include "d/actor/d_a_mg_fish.h"
|
||||
#include "d/actor/d_a_player.h"
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
#include "d/d_timer.h"
|
||||
#include "d/d_s_play.h"
|
||||
#include "Z2AudioLib/Z2Instances.h"
|
||||
#include "d/d_timer.h"
|
||||
#include "dusk/version.hpp"
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/gyro.h"
|
||||
@@ -1742,7 +1743,18 @@ static int daFshop_Create(fopAc_ac_c* actor) {
|
||||
fopAcM_createChild(fpcNm_FSHOP_e, fopAcM_GetID(actor), 0xFFFFFF23, &actor->current.pos, fopAcM_GetRoomNo(actor), NULL, NULL, -1, NULL);
|
||||
|
||||
u8 sp10;
|
||||
#if VERSION == VERSION_GCN_PAL || VERSION == VERSION_WII_PAL
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionPal()) {
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_ENGLISH) {
|
||||
sp10 = 2;
|
||||
} else {
|
||||
sp10 = 0;
|
||||
}
|
||||
} else {
|
||||
sp10 = 1;
|
||||
}
|
||||
|
||||
#elif VERSION == VERSION_GCN_PAL || VERSION == VERSION_WII_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_ENGLISH) {
|
||||
sp10 = 2;
|
||||
} else {
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/version.hpp"
|
||||
|
||||
class dmg_rod_HIO_c : public JORReflexible {
|
||||
public:
|
||||
dmg_rod_HIO_c();
|
||||
@@ -5734,10 +5736,22 @@ static void play_camera_u(dmg_rod_class* i_this) {
|
||||
static int dmg_rod_Execute(dmg_rod_class* i_this) {
|
||||
fopAc_ac_c* actor = &i_this->actor;
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isPalOrAtLeastWiiR2()) {
|
||||
if (dComIfGs_getPalLanguage() == 0) {
|
||||
data_804BBBD4 = 2;
|
||||
} else {
|
||||
data_804BBBD4 = 0;
|
||||
}
|
||||
} else if (dusk::version::isRegionJpn()) {
|
||||
data_804BBBD4 = 0;
|
||||
} else {
|
||||
data_804BBBD4 = 1;
|
||||
}
|
||||
//TODO: It seems possible that dComIfGs_getPalLanguage returns a constant value for non-PAL
|
||||
// versions (causing the first block to be elided), and it's also possible that the value
|
||||
// being compared against is an enum value with per-version definitions.
|
||||
#if VERSION == VERSION_SHIELD_DEBUG
|
||||
#elif VERSION == VERSION_SHIELD_DEBUG
|
||||
if (dComIfGs_getPalLanguage() == 1) {
|
||||
data_804BBBD4 = 2;
|
||||
} else {
|
||||
@@ -6303,7 +6317,19 @@ static int dmg_rod_Create(fopAc_ac_c* i_this) {
|
||||
heap_size = 0xC9A0;
|
||||
}
|
||||
|
||||
#if VERSION == VERSION_SHIELD_DEBUG
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isPalOrAtLeastWiiR2()) {
|
||||
if (dComIfGs_getPalLanguage() == 0) {
|
||||
data_804BBBD4 = 2;
|
||||
} else {
|
||||
data_804BBBD4 = 0;
|
||||
}
|
||||
} else if (dusk::version::isRegionJpn()) {
|
||||
data_804BBBD4 = 0;
|
||||
} else {
|
||||
data_804BBBD4 = 1;
|
||||
}
|
||||
#elif VERSION == VERSION_SHIELD_DEBUG
|
||||
if (dComIfGs_getPalLanguage() == 1) {
|
||||
data_804BBBD4 = 2;
|
||||
} else {
|
||||
|
||||
@@ -84,13 +84,6 @@ 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;
|
||||
}
|
||||
@@ -599,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);
|
||||
|
||||
|
||||
@@ -205,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;
|
||||
}
|
||||
|
||||
@@ -265,8 +265,8 @@ int daObjDrop_c::modeParentWait() {
|
||||
mModeAction = 1;
|
||||
|
||||
#if TARGET_PC
|
||||
mModeTimer = dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 20 : 40;
|
||||
if (dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0) {
|
||||
mModeTimer = dusk::getSettings().game.fastTears ? 0 : 40;
|
||||
if (dusk::getSettings().game.fastTears) {
|
||||
current.pos.y += 100.0f;
|
||||
} else {
|
||||
current.pos.y += 300.0f;
|
||||
@@ -285,7 +285,7 @@ int daObjDrop_c::modeParentWait() {
|
||||
case 2:
|
||||
createBodyEffect();
|
||||
#if TARGET_PC
|
||||
mModeTimer = dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0 ? 5 : 45;
|
||||
mModeTimer = dusk::getSettings().game.fastTears ? 0 : 45;
|
||||
#else
|
||||
mModeTimer = 45;
|
||||
#endif
|
||||
@@ -331,7 +331,7 @@ int daObjDrop_c::modeWait() {
|
||||
case 2:
|
||||
case 50:
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.fastTears && dComIfGp_event_getMode() == 0) {
|
||||
if (dusk::getSettings().game.fastTears) {
|
||||
f32 player_dist = current.pos.abs(daPy_getPlayerActorClass()->current.pos);
|
||||
f32 home_dist = current.pos.abs(home.pos);
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include "d/d_path.h"
|
||||
#include "d/d_bg_w.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
daL8Lift_HIO_c::daL8Lift_HIO_c() {
|
||||
mStopDisappearTime = 30;
|
||||
mStartMoveTime = 60;
|
||||
@@ -380,7 +384,44 @@ void daL8Lift_c::setNextPoint() {
|
||||
mCurrentPoint = next_point;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
void daL8Lift_interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
daL8Lift_c* lift = static_cast<daL8Lift_c*>(pUserWork);
|
||||
if (lift == NULL || lift->mpModel == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_env_light.settingTevStruct(0x10, &lift->current.pos, &lift->tevStr);
|
||||
g_env_light.setLightTevColorType_MAJI(lift->mpModel, &lift->tevStr);
|
||||
|
||||
J3DModelData* modelData = lift->mpModel->getModelData();
|
||||
J3DMaterial* materialp = modelData->getMaterialNodePointer(0);
|
||||
|
||||
if (materialp->getTexGenBlock()->getTexMtx(1) != NULL) {
|
||||
J3DTexMtxInfo* mtx_info = &materialp->getTexGenBlock()->getTexMtx(1)->getTexMtxInfo();
|
||||
if (mtx_info != NULL) {
|
||||
Mtx m;
|
||||
C_MTXLightOrtho(m, 100.0f, -100.0f, -100.0f, 100.0f, 1.0f, 1.0f, 0.0f, 0.0f);
|
||||
mDoMtx_stack_c::XrotS(0x4000);
|
||||
mDoMtx_stack_c::transM(-lift->current.pos.x, -lift->current.pos.y, -lift->current.pos.z);
|
||||
cMtx_concat(m, mDoMtx_stack_c::get(), mtx_info->mEffectMtx);
|
||||
}
|
||||
}
|
||||
|
||||
lift->mBtk.entry(modelData);
|
||||
|
||||
J3DGXColor* color = materialp->getTevKColor(1);
|
||||
color->r = l_HIO.mColorR;
|
||||
color->g = l_HIO.mColorG;
|
||||
color->b = l_HIO.mColorB;
|
||||
}
|
||||
#endif
|
||||
|
||||
int daL8Lift_c::Draw() {
|
||||
#if TARGET_PC
|
||||
dusk::frame_interp::add_interpolation_callback(&daL8Lift_interp_callback, this);
|
||||
#endif
|
||||
|
||||
g_env_light.settingTevStruct(16, ¤t.pos, &tevStr);
|
||||
g_env_light.setLightTevColorType_MAJI(mpModel, &tevStr);
|
||||
J3DModelData* modelData = mpModel->getModelData();
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "d/d_path.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#endif
|
||||
|
||||
daOptiLift_HIO_c::daOptiLift_HIO_c() {
|
||||
mStopDisappearTime = 30;
|
||||
mStartMoveTime = 30;
|
||||
@@ -412,7 +416,44 @@ void daOptiLift_c::setNextPoint() {
|
||||
mCurrentPoint = next_point;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
static void daOptiLift_interp_callback(bool isSimFrame, void* pUserWork) {
|
||||
daOptiLift_c* lift = static_cast<daOptiLift_c*>(pUserWork);
|
||||
if (lift == NULL || lift->mpModel == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_env_light.settingTevStruct(0x10, &lift->current.pos, &lift->tevStr);
|
||||
g_env_light.setLightTevColorType_MAJI(lift->mpModel, &lift->tevStr);
|
||||
|
||||
J3DModelData* modelData = lift->mpModel->getModelData();
|
||||
J3DMaterial* materialp = modelData->getMaterialNodePointer(0);
|
||||
|
||||
if (materialp->getTexGenBlock()->getTexMtx(1) != NULL) {
|
||||
J3DTexMtxInfo* mtx_info = &materialp->getTexGenBlock()->getTexMtx(1)->getTexMtxInfo();
|
||||
if (mtx_info != NULL) {
|
||||
Mtx m;
|
||||
C_MTXLightOrtho(m, 100.0f, -100.0f, -100.0f, 100.0f, 1.0f, 1.0f, 0.0f, 0.0f);
|
||||
mDoMtx_stack_c::XrotS(0x4000);
|
||||
mDoMtx_stack_c::transM(-lift->current.pos.x, -lift->current.pos.y, -lift->current.pos.z);
|
||||
cMtx_concat(m, mDoMtx_stack_c::get(), mtx_info->mEffectMtx);
|
||||
}
|
||||
}
|
||||
|
||||
lift->mBtk.entry(modelData);
|
||||
|
||||
J3DGXColor* color = materialp->getTevKColor(1);
|
||||
color->r = l_HIO.mColorR;
|
||||
color->g = l_HIO.mColorG;
|
||||
color->b = l_HIO.mColorB;
|
||||
}
|
||||
#endif
|
||||
|
||||
int daOptiLift_c::Draw() {
|
||||
#if TARGET_PC
|
||||
dusk::frame_interp::add_interpolation_callback(&daOptiLift_interp_callback, this);
|
||||
#endif
|
||||
|
||||
g_env_light.settingTevStruct(0x10, ¤t.pos, &tevStr);
|
||||
g_env_light.setLightTevColorType_MAJI(mpModel, &tevStr);
|
||||
|
||||
|
||||
@@ -369,18 +369,17 @@ JKRHeap* daPy_anmHeap_c::setAnimeHeap() {
|
||||
#if !PLATFORM_WII
|
||||
#if TARGET_PC
|
||||
#include "dusk/dvd_asset.hpp"
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
static const u8* l_sightDL_get() {
|
||||
static u8 buf[0x89];
|
||||
static bool _ = (
|
||||
dusk::LoadDolAsset(
|
||||
buf,
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
0x803BBDA0,
|
||||
#elif VERSION == VERSION_GCN_JPN
|
||||
0x803B4220,
|
||||
#elif VERSION == VERSION_GCN_USA
|
||||
0x803BA0C0,
|
||||
#endif
|
||||
{
|
||||
{GameVersion::GcnUsa, 0x803BA0C0},
|
||||
{GameVersion::GcnPal, 0x803BBDA0},
|
||||
{GameVersion::GcnJpn, 0x803B4220}
|
||||
},
|
||||
0x89
|
||||
),
|
||||
true
|
||||
|
||||
+17
-13
@@ -1,21 +1,22 @@
|
||||
#include "d/dolzel_rel.h" // IWYU pragma: keep
|
||||
|
||||
#include "JSystem/J2DGraph/J2DScreen.h"
|
||||
#include "JSystem/J2DGraph/J2DTextBox.h"
|
||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||
#include "JSystem/JKernel/JKRMemArchive.h"
|
||||
#include "d/actor/d_a_title.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "d/d_menu_collect.h"
|
||||
#include "d/d_pane_class_alpha.h"
|
||||
#include "d/d_s_logo.h"
|
||||
#include "d/d_s_play.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "d/d_pane_class_alpha.h"
|
||||
#include "d/d_menu_collect.h"
|
||||
#include "dusk/version.hpp"
|
||||
#include "f_op/f_op_msg_mng.h"
|
||||
#include "f_op/f_op_overlap_mng.h"
|
||||
#include "f_op/f_op_scene_mng.h"
|
||||
#include "m_Do/m_Do_Reset.h"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||
#include "f_op/f_op_overlap_mng.h"
|
||||
#include "f_op/f_op_msg_mng.h"
|
||||
#include "f_op/f_op_scene_mng.h"
|
||||
#include "JSystem/J2DGraph/J2DScreen.h"
|
||||
#include "JSystem/JKernel/JKRMemArchive.h"
|
||||
#include "JSystem/J2DGraph/J2DTextBox.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
|
||||
#ifdef TARGET_PC
|
||||
@@ -49,7 +50,10 @@ static u8 const lit_3772[12] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC
|
||||
using namespace dusk::version;
|
||||
#define l_arcName versionSelect<const char*>({{GameVersion::GcnPal, "TitlePal"}}, "Title")
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
static char const l_arcName[] = "TitlePal";
|
||||
#else
|
||||
static char const l_arcName[] = "Title";
|
||||
@@ -59,7 +63,7 @@ daTit_HIO_c::daTit_HIO_c() {
|
||||
mPSScaleX = 1.0f;
|
||||
mPSScaleY = 1.0f;
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
switch (OSGetLanguage()) {
|
||||
case OS_LANGUAGE_ENGLISH:
|
||||
case OS_LANGUAGE_GERMAN:
|
||||
|
||||
+23
-23
@@ -7,17 +7,13 @@
|
||||
|
||||
#include "dusk/frame_interpolation.h"
|
||||
|
||||
#if TARGET_PC
|
||||
const u16 l_J_Ohana00_64TEX__width = 64;
|
||||
const u16 l_J_Ohana00_64TEX__height = 64;
|
||||
#else
|
||||
const u16 l_J_Ohana00_64TEX__width = 63;
|
||||
const u16 l_J_Ohana00_64TEX__height = 63;
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/dvd_asset.hpp"
|
||||
static u8* l_J_Ohana00_64TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x9060, 0x800), true); return buf; }
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
static u8* l_J_Ohana00_64TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9060}, {GameVersion::GcnPal, 0x9060}}, 0x800), true); return buf; }
|
||||
#define l_J_Ohana00_64TEX (l_J_Ohana00_64TEX_get())
|
||||
#else
|
||||
#include "assets/l_J_Ohana00_64TEX.h"
|
||||
@@ -113,10 +109,12 @@ static u8 l_flowerTexCoord[] = {
|
||||
0x3E, 0xA7, 0x72, 0xD6, 0xBD, 0x2F, 0x46, 0xAA};
|
||||
|
||||
#if TARGET_PC
|
||||
static u8* l_J_hana00DL_get() { static u8 buf[0x150]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x9D20, 0x150), true); return buf; }
|
||||
static u8* l_J_hana00_cDL_get() { static u8 buf[0xDE]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x9E80, 0xDE), true); return buf; }
|
||||
static u8* l_matDL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x9F60, 0x99), true); return buf; }
|
||||
static u8* l_matLight4DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xA000, 0x99), true); return buf; }
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
|
||||
static u8* l_J_hana00DL_get() { static u8 buf[0x150]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9D20}, {GameVersion::GcnPal, 0x9D20}}, 0x150), true); return buf; }
|
||||
static u8* l_J_hana00_cDL_get() { static u8 buf[0xDE]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9E80}, {GameVersion::GcnPal, 0x9E80}}, 0xDE), true); return buf; }
|
||||
static u8* l_matDL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x9F60}, {GameVersion::GcnPal, 0x9F60}}, 0x99), true); return buf; }
|
||||
static u8* l_matLight4DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0xA000}, {GameVersion::GcnPal, 0xA000}}, 0x99), true); return buf; }
|
||||
#define l_J_hana00DL (l_J_hana00DL_get())
|
||||
#define l_J_hana00_cDL (l_J_hana00_cDL_get())
|
||||
#define l_matDL (l_matDL_get())
|
||||
@@ -133,16 +131,12 @@ l_matDL__d_a_grass(l_J_Ohana00_64TEX)
|
||||
l_matLight4DL(l_J_Ohana00_64TEX)
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
const u16 l_J_Ohana01_64128_0419TEX__width = 64;
|
||||
const u16 l_J_Ohana01_64128_0419TEX__height = 128;
|
||||
#else
|
||||
const u16 l_J_Ohana01_64128_0419TEX__width = 63;
|
||||
const u16 l_J_Ohana01_64128_0419TEX__height = 127;
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
static u8* l_J_Ohana01_64128_0419TEX_get() { static u8 buf[0x1000]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xA0A0, 0x1000), true); return buf; }
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
static u8* l_J_Ohana01_64128_0419TEX_get() { static u8 buf[0x1000]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0xA0A0}, {GameVersion::GcnPal, 0xA0A0}}, 0x1000), true); return buf; }
|
||||
#define l_J_Ohana01_64128_0419TEX (l_J_Ohana01_64128_0419TEX_get())
|
||||
#else
|
||||
#include "assets/l_J_Ohana01_64128_0419TEX.h"
|
||||
@@ -274,11 +268,13 @@ static u8 l_flowerTexCoord2[] = {
|
||||
0x40, 0x1B, 0x7D, 0x52, 0x3F, 0x80, 0x3F, 0x79, 0x40, 0x1B, 0x7D, 0x52, 0x3F, 0x51, 0x10, 0x6F};
|
||||
|
||||
#if TARGET_PC
|
||||
static u8* l_J_hana01DL_get() { static u8 buf[0x138]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xB7C0, 0x138), true); return buf; }
|
||||
static u8* l_J_hana01_c_00DL_get() { static u8 buf[0xDE]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xB900, 0xDE), true); return buf; }
|
||||
static u8* l_J_hana01_c_01DL_get() { static u8 buf[0x128]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xB9E0, 0x128), true); return buf; }
|
||||
static u8* l_mat2DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xBB20, 0x99), true); return buf; }
|
||||
static u8* l_mat2Light4DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0xBBC0, 0x99), true); return buf; }
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
|
||||
static u8* l_J_hana01DL_get() { static u8 buf[0x138]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0xB7C0}, {GameVersion::GcnPal, 0xB7C0}}, 0x138), true); return buf; }
|
||||
static u8* l_J_hana01_c_00DL_get() { static u8 buf[0xDE]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0xB900}, {GameVersion::GcnPal, 0xB900}}, 0xDE), true); return buf; }
|
||||
static u8* l_J_hana01_c_01DL_get() { static u8 buf[0x128]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0xB9E0}, {GameVersion::GcnPal, 0xB9E0}}, 0x128), true); return buf; }
|
||||
static u8* l_mat2DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0xBB20}, {GameVersion::GcnPal, 0xBB20}}, 0x99), true); return buf; }
|
||||
static u8* l_mat2Light4DL_get() { static u8 buf[0x99]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0xBBC0}, {GameVersion::GcnPal, 0xBBC0}}, 0x99), true); return buf; }
|
||||
#define l_J_hana01DL (l_J_hana01DL_get())
|
||||
#define l_J_hana01_c_00DL (l_J_hana01_c_00DL_get())
|
||||
#define l_J_hana01_c_01DL (l_J_hana01_c_01DL_get())
|
||||
@@ -586,11 +582,11 @@ dFlower_packet_c::dFlower_packet_c() {
|
||||
|
||||
#if TARGET_PC
|
||||
GXInitTexObj(&mTexObj_l_J_Ohana00_64TEX, l_J_Ohana00_64TEX,
|
||||
l_J_Ohana00_64TEX__width, l_J_Ohana00_64TEX__height, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE
|
||||
l_J_Ohana00_64TEX__width + 1, l_J_Ohana00_64TEX__height + 1, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE
|
||||
);
|
||||
|
||||
GXInitTexObj(&mTexObj_l_J_Ohana01_64128_0419TEX, l_J_Ohana01_64128_0419TEX,
|
||||
l_J_Ohana01_64128_0419TEX__width, l_J_Ohana01_64128_0419TEX__height, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE
|
||||
l_J_Ohana01_64128_0419TEX__width + 1, l_J_Ohana01_64128_0419TEX__height + 1, GX_TF_CMPR, GX_MIRROR, GX_MIRROR, GX_FALSE
|
||||
);
|
||||
#endif
|
||||
|
||||
@@ -789,6 +785,10 @@ void dFlower_packet_c::draw() {
|
||||
|
||||
GXColor sp28;
|
||||
|
||||
#if AVOID_UB
|
||||
sp28 = {1, 1, 1, 1};
|
||||
#endif
|
||||
|
||||
//u8 sp26, sp25, sp24;
|
||||
GXColor sp24;
|
||||
sp24.r = -0.4f * temp_r29->AmbCol.r * var_f29;
|
||||
|
||||
+17
-16
@@ -20,8 +20,9 @@ const u16 l_M_kusa05_RGBATEX__height = 31;
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/dvd_asset.hpp"
|
||||
static u8* l_M_kusa05_RGBATEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x7680, 0x800), true); return buf; }
|
||||
static u8* l_M_Hijiki00TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x7E80, 0x800), true); return buf; }
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
static u8* l_M_kusa05_RGBATEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x7680}, {GameVersion::GcnPal, 0x7680}}, 0x800), true); return buf; }
|
||||
static u8* l_M_Hijiki00TEX_get() { static u8 buf[0x800]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x7E80}, {GameVersion::GcnPal, 0x7E80}}, 0x800), true); return buf; }
|
||||
#define l_M_kusa05_RGBATEX (l_M_kusa05_RGBATEX_get())
|
||||
#define l_M_Hijiki00TEX (l_M_Hijiki00TEX_get())
|
||||
#else
|
||||
@@ -113,12 +114,14 @@ static u8 l_texCoord[160] = {
|
||||
};
|
||||
|
||||
#if TARGET_PC
|
||||
static u8* l_M_Kusa_9qDL_get() { static u8 buf[0xCB]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8B00, 0xCB), true); return buf; }
|
||||
static u8* l_M_Kusa_9q_cDL_get() { static u8 buf[0xCB]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8BE0, 0xCB), true); return buf; }
|
||||
static u8* l_M_TenGusaDL_get() { static u8 buf[0xD4]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8CC0, 0xD4), true); return buf; }
|
||||
static u8* l_Tengusa_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8DA0, 0xA8), true); return buf; }
|
||||
static u8* l_kusa9q_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8E60, 0xA8), true); return buf; }
|
||||
static u8* l_kusa9q_l4_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", 0x8F20, 0xA8), true); return buf; }
|
||||
using GameVersion = dusk::version::GameVersion;
|
||||
|
||||
static u8* l_M_Kusa_9qDL_get() { static u8 buf[0xCB]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x8B00}, {GameVersion::GcnPal, 0x8B00}}, 0xCB), true); return buf; }
|
||||
static u8* l_M_Kusa_9q_cDL_get() { static u8 buf[0xCB]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x8BE0}, {GameVersion::GcnPal, 0x8BE0}}, 0xCB), true); return buf; }
|
||||
static u8* l_M_TenGusaDL_get() { static u8 buf[0xD4]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x8CC0}, {GameVersion::GcnPal, 0x8CC0}}, 0xD4), true); return buf; }
|
||||
static u8* l_Tengusa_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x8DA0}, {GameVersion::GcnPal, 0x8DA0}}, 0xA8), true); return buf; }
|
||||
static u8* l_kusa9q_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x8E60}, {GameVersion::GcnPal, 0x8E60}}, 0xA8), true); return buf; }
|
||||
static u8* l_kusa9q_l4_matDL_get() { static u8 buf[0xA8]; static bool _ = (dusk::LoadArchivedRelAsset(buf, 'AMEM', "d_a_grass.rel", {{GameVersion::GcnUsa, 0x8F20}, {GameVersion::GcnPal, 0x8F20}}, 0xA8), true); return buf; }
|
||||
#define l_M_Kusa_9qDL (l_M_Kusa_9qDL_get())
|
||||
#define l_M_Kusa_9q_cDL (l_M_Kusa_9q_cDL_get())
|
||||
#define l_M_TenGusaDL (l_M_TenGusaDL_get())
|
||||
@@ -491,11 +494,11 @@ dGrass_packet_c::dGrass_packet_c() {
|
||||
|
||||
#if TARGET_PC
|
||||
GXInitTexObj(&mTexObj_l_M_kusa05_RGBATEX, l_M_kusa05_RGBATEX,
|
||||
l_M_kusa05_RGBATEX__width, l_M_kusa05_RGBATEX__height, GX_TF_RGB5A3, GX_REPEAT, GX_CLAMP, GX_FALSE
|
||||
l_M_kusa05_RGBATEX__width + 1, l_M_kusa05_RGBATEX__height + 1, GX_TF_RGB5A3, GX_REPEAT, GX_CLAMP, GX_FALSE
|
||||
);
|
||||
|
||||
GXInitTexObj(&mTexObj_l_M_Hijiki00TEX, l_M_Hijiki00TEX,
|
||||
l_M_Hijiki00TEX__width, l_M_Hijiki00TEX__height, GX_TF_RGB5A3, GX_REPEAT, GX_CLAMP, GX_FALSE
|
||||
l_M_Hijiki00TEX__width + 1, l_M_Hijiki00TEX__height + 1, GX_TF_RGB5A3, GX_REPEAT, GX_CLAMP, GX_FALSE
|
||||
);
|
||||
#endif
|
||||
|
||||
@@ -643,18 +646,14 @@ void dGrass_packet_c::draw() {
|
||||
}
|
||||
|
||||
if (var_r29->field_0x05 <= 3 || var_r29->field_0x05 >= 10) {
|
||||
#if TARGET_PC
|
||||
GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0);
|
||||
#endif
|
||||
IF_DUSK(GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0));
|
||||
if (sp48 <= 3) {
|
||||
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
|
||||
} else {
|
||||
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
|
||||
}
|
||||
} else {
|
||||
#if TARGET_PC
|
||||
GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0);
|
||||
#endif
|
||||
IF_DUSK(GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0));
|
||||
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
|
||||
}
|
||||
|
||||
@@ -680,12 +679,14 @@ void dGrass_packet_c::draw() {
|
||||
|
||||
while (var_r29 != NULL) {
|
||||
if (var_r29->field_0x05 <= 3 || var_r29->field_0x05 >= 10) {
|
||||
IF_DUSK(GXLoadTexObj(&mTexObj_l_M_kusa05_RGBATEX, GX_TEXMAP0));
|
||||
if (sp48 <= 2) {
|
||||
GXCallDisplayList(mp_kusa9q_14_DL, m_kusa9q_DL_14_size);
|
||||
} else {
|
||||
GXCallDisplayList(mp_kusa9q_DL, m_kusa9q_DL_size);
|
||||
}
|
||||
} else {
|
||||
IF_DUSK(GXLoadTexObj(&mTexObj_l_M_Hijiki00TEX, GX_TEXMAP0));
|
||||
GXCallDisplayList(l_Tengusa_matDL, 0xA0);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "JSystem/J2DGraph/J2DScreen.h"
|
||||
#include "JSystem/J2DGraph/J2DTextBox.h"
|
||||
#include "d/d_msg_string.h"
|
||||
#include "dusk/livesplit.h"
|
||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
|
||||
dBrightCheck_c::dBrightCheck_c(JKRArchive* i_archive) {
|
||||
@@ -138,6 +140,17 @@ void dBrightCheck_c::modeWait() {}
|
||||
void dBrightCheck_c::modeMove() {
|
||||
if (mDoCPd_c::getTrigA(PAD_1) || mDoCPd_c::getTrigStart(PAD_1)) {
|
||||
mDoAud_seStart(Z2SE_ENTER_GAME, NULL, 0, 0);
|
||||
#ifdef TARGET_PC
|
||||
dusk::speedrun::start();
|
||||
|
||||
if (dusk::getSettings().game.speedrunMode && !dusk::getSettings().game.hideTvSettingsScreen) {
|
||||
// start a new run if a run isn't already in progress
|
||||
if (!dusk::m_speedrunInfo.m_isRunStarted) {
|
||||
dusk::ImGuiMenuGame::resetForSpeedrunMode();
|
||||
dusk::m_speedrunInfo.startRun();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mCompleteCheck = true;
|
||||
mMode = MODE_WAIT_e;
|
||||
}
|
||||
|
||||
@@ -800,6 +800,10 @@ void dCamera_c::updatePad() {
|
||||
}
|
||||
|
||||
mLockLActive = 1;
|
||||
|
||||
#if TARGET_PC
|
||||
mCamParam.mManualMode = 0;
|
||||
#endif
|
||||
} else {
|
||||
mLockLJustActivated = 0;
|
||||
mLockLActive = 0;
|
||||
@@ -833,6 +837,12 @@ void dCamera_c::updatePad() {
|
||||
mHoldB = mDoCPd_c::getHoldB(mPadID) ? true : false;
|
||||
mTrigB = mDoCPd_c::getTrigB(mPadID) ? true : false;
|
||||
|
||||
#if TARGET_PC
|
||||
if (mCamParam.mManualMode) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool sp6B = true;
|
||||
bool sp6C = true;
|
||||
int temp1;
|
||||
@@ -1167,6 +1177,13 @@ bool dCamera_c::Run() {
|
||||
}
|
||||
} else {
|
||||
sp0F = (this->*engine_tbl[mCamParam.Algorythmn(mCamStyle)])(mCamStyle);
|
||||
|
||||
#if TARGET_PC
|
||||
if (mCamParam.Algorythmn(mCamStyle) != 1) {
|
||||
mCamParam.mManualMode = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
field_0x170++;
|
||||
field_0x160++;
|
||||
mCurCamStyleTimer++;
|
||||
@@ -3078,6 +3095,11 @@ bool dCamera_c::bumpCheck(u32 i_flags) {
|
||||
} else {
|
||||
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);
|
||||
@@ -3091,6 +3113,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");
|
||||
@@ -4604,6 +4630,11 @@ bool dCamera_c::chaseCamera(s32 param_0) {
|
||||
|
||||
sp110 = mViewCache.mDirection.R();
|
||||
mViewCache.mDirection.R(mViewCache.mDirection.R() + (fVar55 - mViewCache.mDirection.R()) * chase->field_0x74);
|
||||
|
||||
#if TARGET_PC
|
||||
freeCamera();
|
||||
#endif
|
||||
|
||||
chase->field_0x64 = mViewCache.mCenter + mViewCache.mDirection.Xyz();
|
||||
mViewCache.mEye = chase->field_0x64;
|
||||
|
||||
@@ -7444,6 +7475,40 @@ bool dCamera_c::test2Camera(s32 param_0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
bool dCamera_c::freeCamera() {
|
||||
if (!dusk::getSettings().game.freeCamera) {
|
||||
mCamParam.mManualMode = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
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) {
|
||||
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 * 4.0f;
|
||||
mCamParam.freeYAngle += camMovement.y * magnitude * dusk::getSettings().game.freeCameraSensitivity * 4.0f;
|
||||
}
|
||||
|
||||
if (mCamParam.mManualMode) {
|
||||
mCamParam.freeYAngle = std::clamp(mCamParam.freeYAngle, -35.0f, 60.0f);
|
||||
mViewCache.mDirection.mAzimuth = cSAngle(mCamParam.freeXAngle);
|
||||
mViewCache.mDirection.mInclination = cSAngle(mCamParam.freeYAngle);
|
||||
mViewCache.mDirection.mRadius = std::clamp((mCamParam.freeYAngle + 35.0f) * 10.0f, 300.0f, 10000.0f);
|
||||
}
|
||||
|
||||
return mCamParam.mManualMode;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool dCamera_c::towerCamera(s32 param_0) {
|
||||
cSAngle stack_444 = cSAngle(mCamSetup.ChargeLatitude());
|
||||
f32 sp224 = mCamSetup.ChargeBRatio();
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/version.hpp"
|
||||
|
||||
dFile_info_c::dFile_info_c(JKRArchive* i_archive, u8 param_1) {
|
||||
mArchive = i_archive;
|
||||
field_0x22 = param_1;
|
||||
@@ -169,7 +171,18 @@ void dFile_info_c::setSaveDate(dSv_save_c* i_savedata) {
|
||||
OSCalendarTime time;
|
||||
OSTicksToCalendarTime(i_savedata->getPlayer().getPlayerStatusB().getDateIpl(), &time);
|
||||
|
||||
#if (VERSION == VERSION_GCN_JPN) || (VERSION == VERSION_WII_JPN)
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionJpn()) {
|
||||
sprintf(mSaveDate, "%d.%02d.%02d %02d:%02d", time.year, time.mon + 1, time.mday,
|
||||
time.hour, time.min);
|
||||
} else if (dusk::version::isRegionPal() && dComIfGs_getPalLanguage() != dSv_player_config_c::LANGUAGE_ENGLISH) {
|
||||
sprintf(mSaveDate, "%02d/%02d/%d %02d:%02d", time.mday, time.mon + 1, time.year, time.hour,
|
||||
time.min);
|
||||
} else {
|
||||
sprintf(mSaveDate, "%02d/%02d/%d %02d:%02d", time.mon + 1, time.mday, time.year, time.hour,
|
||||
time.min);
|
||||
}
|
||||
#elif (VERSION == VERSION_GCN_JPN) || (VERSION == VERSION_WII_JPN)
|
||||
sprintf(mSaveDate, "%d.%02d.%02d %02d:%02d", time.year, time.mon + 1, time.mday,
|
||||
time.hour, time.min);
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
|
||||
+56
-7
@@ -5962,6 +5962,8 @@ static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) {
|
||||
fopAc_ac_c* player = dComIfGp_getPlayer(0);
|
||||
|
||||
if (evil_packet != NULL) {
|
||||
IF_DUSK(GXPushDebugGroup("dKyr_evil_draw2"));
|
||||
|
||||
j3dSys.reinitGX();
|
||||
if (dComIfGd_getView() != NULL) {
|
||||
MTXInverse(dComIfGd_getView()->viewMtxNoTrans, camMtx);
|
||||
@@ -5986,7 +5988,12 @@ static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) {
|
||||
TGXTexObj texobj;
|
||||
dKyr_set_btitex(&texobj, (ResTIMG*)tex[1]);
|
||||
|
||||
rot += 0.7f;
|
||||
#if TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
rot += 0.7f;
|
||||
}
|
||||
MTXRotRad(rotMtx, 'Z', DEG_TO_RAD(rot));
|
||||
MTXConcat(camMtx, rotMtx, camMtx);
|
||||
|
||||
@@ -6037,7 +6044,14 @@ static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) {
|
||||
sp34.y = 80.0f;
|
||||
sp34.z = 80.0f;
|
||||
mDoLib_project(&sp7C, &proj);
|
||||
if (!(proj.x > -sp34.x) || !(proj.x < (FB_WIDTH + sp34.x)) ||
|
||||
#if TARGET_PC
|
||||
f32 cullMinX = mDoGph_gInf_c::getSafeMinXF() - sp34.x;
|
||||
f32 cullMaxX = mDoGph_gInf_c::getSafeMinXF() + mDoGph_gInf_c::getSafeWidthF() + sp34.x;
|
||||
#else
|
||||
f32 cullMinX = -sp34.x;
|
||||
f32 cullMaxX = FB_WIDTH + sp34.x;
|
||||
#endif
|
||||
if (!(proj.x > cullMinX) || !(proj.x < cullMaxX) ||
|
||||
!(proj.y > -sp34.y) || !(proj.y < (458.0f + sp34.z)))
|
||||
{
|
||||
continue;
|
||||
@@ -6150,6 +6164,8 @@ static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) {
|
||||
}
|
||||
}
|
||||
|
||||
IF_DUSK(GXPopDebugGroup());
|
||||
|
||||
GXSetClipMode(GX_CLIP_ENABLE);
|
||||
J3DShape::resetVcdVatCache();
|
||||
}
|
||||
@@ -6187,6 +6203,8 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
|
||||
f32 sp60 = fabsf(cM_ssin(g_Counter.mCounter0 * 215));
|
||||
|
||||
if (evil_packet != NULL) {
|
||||
IF_DUSK(GXPushDebugGroup("dKyr_evil_draw"));
|
||||
|
||||
j3dSys.reinitGX();
|
||||
if (dComIfGd_getView() != NULL) {
|
||||
MTXInverse(dComIfGd_getView()->viewMtxNoTrans, camMtx);
|
||||
@@ -6208,14 +6226,19 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
|
||||
TGXTexObj texobj;
|
||||
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
|
||||
|
||||
rot += 1.0f;
|
||||
#if TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
rot += 1.0f;
|
||||
}
|
||||
MTXRotRad(rotMtx, 'Z', DEG_TO_RAD(rot));
|
||||
MTXConcat(camMtx, rotMtx, camMtx);
|
||||
|
||||
GXLoadPosMtxImm(drawMtx, GX_PNMTX0);
|
||||
GXSetCurrentMtx(GX_PNMTX0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA4, 8);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA4, 8);
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||||
@@ -6238,6 +6261,19 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
|
||||
GXSetClipMode(GX_CLIP_DISABLE);
|
||||
GXSetNumIndStages(0);
|
||||
|
||||
#if TARGET_PC
|
||||
// move color_reg0 to vtx for perf
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
|
||||
GXSetNumChans(1);
|
||||
GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE);
|
||||
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
|
||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
|
||||
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO);
|
||||
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
#endif
|
||||
|
||||
dComIfG_Ccsp()->PrepareMass();
|
||||
|
||||
for (int i = 0; i < g_env_light.field_0x1054; i++) {
|
||||
@@ -6262,7 +6298,14 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
|
||||
sp44.z = 80.0f;
|
||||
|
||||
mDoLib_project(&spA4, &proj);
|
||||
if (!(proj.x > -sp44.x) || !(proj.x < (FB_WIDTH + sp44.x)) ||
|
||||
#if TARGET_PC
|
||||
f32 cullMinX = mDoGph_gInf_c::getSafeMinXF() - sp44.x;
|
||||
f32 cullMaxX = mDoGph_gInf_c::getSafeMinXF() + mDoGph_gInf_c::getSafeWidthF() + sp44.x;
|
||||
#else
|
||||
f32 cullMinX = -sp44.x;
|
||||
f32 cullMaxX = FB_WIDTH + sp44.x;
|
||||
#endif
|
||||
if (!(proj.x > cullMinX) || !(proj.x < cullMaxX) ||
|
||||
!(proj.y > -sp44.y) || !(proj.y < (458.0f + sp44.z)))
|
||||
{
|
||||
continue;
|
||||
@@ -6349,7 +6392,7 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
|
||||
color_reg0.b = (115.0f * sp28) + (15.0f * fabsf(sp2C - sp64));
|
||||
}
|
||||
|
||||
GXSetTevColor(GX_TEVREG0, color_reg0);
|
||||
IF_NOT_DUSK(GXSetTevColor(GX_TEVREG0, color_reg0));
|
||||
GXSetTevColor(GX_TEVREG1, color_reg1);
|
||||
|
||||
spC8 = spA4;
|
||||
@@ -6388,12 +6431,16 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
|
||||
|
||||
GXBegin(GX_QUADS, GX_VTXFMT0, 4);
|
||||
GXPosition3f32(pos[0].x, pos[0].y, pos[0].z);
|
||||
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
|
||||
GXTexCoord2s16(0, 0);
|
||||
GXPosition3f32(pos[1].x, pos[1].y, pos[1].z);
|
||||
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
|
||||
GXTexCoord2s16(0xFF, 0);
|
||||
GXPosition3f32(pos[2].x, pos[2].y, pos[2].z);
|
||||
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
|
||||
GXTexCoord2s16(0xFF, 0xFF);
|
||||
GXPosition3f32(pos[3].x, pos[3].y, pos[3].z);
|
||||
IF_DUSK(GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a));
|
||||
GXTexCoord2s16(0, 0xFF);
|
||||
GXEnd();
|
||||
}
|
||||
@@ -6401,6 +6448,8 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
|
||||
}
|
||||
}
|
||||
|
||||
IF_DUSK(GXPopDebugGroup());
|
||||
|
||||
J3DShape::resetVcdVatCache();
|
||||
GXSetClipMode(GX_CLIP_ENABLE);
|
||||
|
||||
|
||||
+10
-7
@@ -13,6 +13,9 @@
|
||||
#include "SSystem/SComponent/c_math.h"
|
||||
#include "d/actor/d_a_player.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#if TARGET_PC
|
||||
#include <dolphin/gx/GXExtra.h>
|
||||
#endif
|
||||
#include <cstring>
|
||||
|
||||
#if DEBUG
|
||||
@@ -539,17 +542,14 @@ void renderingAmap_c::rendering(dDrawPath_c::poly_class const* i_poly) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Enabling the following definition will modify the following function to
|
||||
* make the map look worse for extra speed in the emulator, especially in large
|
||||
* areas such as hyrule field.
|
||||
*/
|
||||
#define HYRULE_FIELD_SPEEDHACK
|
||||
|
||||
bool renderingAmap_c::isDrawOutSideTrim() {
|
||||
bool rt = false;
|
||||
|
||||
#ifdef HYRULE_FIELD_SPEEDHACK
|
||||
return 0;
|
||||
#if TARGET_PC
|
||||
if (!dusk::getSettings().game.enableMapBackground) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getDispType() == 0 || getDispType() == 4 || getDispType() == 3 || getDispType() == 2 ||
|
||||
@@ -1218,6 +1218,9 @@ void dMap_c::changeTextureSize(int param_1, int param_2, int param_3) {
|
||||
|
||||
void dMap_c::_remove() {
|
||||
if (mImage_p != NULL) {
|
||||
#if TARGET_PC
|
||||
GXDestroyCopyTex(mImage_p);
|
||||
#endif
|
||||
JKR_DELETE_ARRAY(mImage_p);
|
||||
mImage_p = NULL;
|
||||
}
|
||||
|
||||
+26
-8
@@ -497,12 +497,6 @@ void dRenderingFDAmap_c::postRenderingMap() {
|
||||
|
||||
dMpath_n::dTexObjAggregate_c dMpath_n::m_texObjAgg;
|
||||
|
||||
/* Enabling the following definition will modify the following function to
|
||||
* make the map look worse for extra speed in the emulator, especially in large
|
||||
* areas such as hyrule field.
|
||||
*/
|
||||
#define HYRULE_FIELD_SPEEDHACK
|
||||
|
||||
void dRenderingFDAmap_c::renderingDecoration(dDrawPath_c::line_class const* p_line) {
|
||||
s32 width = getDecorationLineWidth(p_line->field_0x1);
|
||||
if (width <= 0) {
|
||||
@@ -527,8 +521,32 @@ void dRenderingFDAmap_c::renderingDecoration(dDrawPath_c::line_class const* p_li
|
||||
lineColor.r = lineColor.r - 4;
|
||||
GXSetTevColor(GX_TEVREG1, lineColor);
|
||||
|
||||
#if TARGET_PC
|
||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0);
|
||||
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_KONST);
|
||||
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
GXBegin(GX_LINESTRIP, GX_VTXFMT0, 2 * (data_num - 1));
|
||||
for (int i = 0; i < data_num - 1; i++) {
|
||||
GXPosition1x16(data_p[i]);
|
||||
GXTexCoord2f32(0, 0);
|
||||
GXPosition1x16(data_p[i + 1]);
|
||||
GXTexCoord2f32(0, 0);
|
||||
}
|
||||
GXEnd();
|
||||
|
||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_KONST, GX_CC_TEXC, GX_CC_C1);
|
||||
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
|
||||
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
GXBegin(GX_POINTS, GX_VTXFMT0, data_num);
|
||||
for (int i = 0; i < data_num; i++) {
|
||||
GXPosition1x16(data_p[i]);
|
||||
GXTexCoord2f32(0, 0);
|
||||
}
|
||||
GXEnd();
|
||||
#else
|
||||
for (int i = 0; i < data_num; i++) {
|
||||
#ifndef HYRULE_FIELD_SPEEDHACK
|
||||
if (i < data_num - 1) {
|
||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0);
|
||||
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE,
|
||||
@@ -547,7 +565,6 @@ void dRenderingFDAmap_c::renderingDecoration(dDrawPath_c::line_class const* p_li
|
||||
GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
|
||||
GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
#endif
|
||||
|
||||
GXBegin(GX_POINTS, GX_VTXFMT0, 1);
|
||||
GXPosition1x16(data_p[0]);
|
||||
@@ -555,6 +572,7 @@ void dRenderingFDAmap_c::renderingDecoration(dDrawPath_c::line_class const* p_li
|
||||
GXEnd();
|
||||
data_p++;
|
||||
}
|
||||
#endif
|
||||
|
||||
setTevSettingNonTextureDirectColor();
|
||||
GXClearVtxDesc();
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include "d/d_menu_dmap_map.h"
|
||||
#include "f_op/f_op_msg_mng.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
#if TARGET_PC
|
||||
#include <dolphin/gx/GXExtra.h>
|
||||
#endif
|
||||
|
||||
struct dMdm_HIO_prm_res_dst_s {
|
||||
static void* m_res;
|
||||
@@ -291,6 +294,9 @@ void dMenu_DmapMap_c::_create(u16 param_0, u16 param_1, u16 param_2, u16 param_3
|
||||
void dMenu_DmapMap_c::_delete() {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (mMapImage_p[i] != NULL) {
|
||||
#if TARGET_PC
|
||||
GXDestroyCopyTex(mMapImage_p[i]);
|
||||
#endif
|
||||
JKR_DELETE_ARRAY(mMapImage_p[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/version.hpp"
|
||||
|
||||
typedef void (dMenu_Fishing_c::*initFunc)();
|
||||
initFunc map_init_process[] = {
|
||||
&dMenu_Fishing_c::wait_init,
|
||||
@@ -135,9 +137,9 @@ bool dMenu_Fishing_c::isSync() {
|
||||
}
|
||||
|
||||
void dMenu_Fishing_c::init() {
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
BOOL isEnglish = FALSE;
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_ENGLISH) {
|
||||
if (dusk::version::isRegionUsa() || (dusk::version::isRegionPal() && dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_ENGLISH)) {
|
||||
isEnglish = TRUE;
|
||||
}
|
||||
#endif
|
||||
@@ -145,7 +147,7 @@ void dMenu_Fishing_c::init() {
|
||||
for (int i = 0; i < MAX_FINDABLE_FISHES; i++) {
|
||||
if (dComIfGs_getFishNum(i) != 0) {
|
||||
// Fish has been caught once, display it along with it's params
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
if (isEnglish) {
|
||||
setFishParam(i, dComIfGs_getFishNum(i), dComIfGs_getFishSize(i) / 2.54f);
|
||||
} else {
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include "d/d_debug_viewer.h"
|
||||
#include "d/d_menu_fmap_map.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
#if TARGET_PC
|
||||
#include <dolphin/gx/GXExtra.h>
|
||||
#endif
|
||||
#include <cstring>
|
||||
|
||||
static u8 twoValueLineInterpolation(u8 i_value1, u8 i_value2, f32 i_param) {
|
||||
@@ -494,6 +497,9 @@ void dMenu_FmapMap_c::_delete() {
|
||||
mResTIMG = NULL;
|
||||
}
|
||||
if (mMapImage_p != NULL) {
|
||||
#if TARGET_PC
|
||||
GXDestroyCopyTex(mMapImage_p);
|
||||
#endif
|
||||
JKR_DELETE_ARRAY(mMapImage_p);
|
||||
mMapImage_p = NULL;
|
||||
}
|
||||
|
||||
@@ -368,8 +368,22 @@ void dMeterButton_c::draw() {
|
||||
}
|
||||
|
||||
if (var_r3) {
|
||||
#ifdef TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending()) {
|
||||
mWasListen[i] = var_r22;
|
||||
mWasRepeat[i] = var_r23;
|
||||
} else {
|
||||
var_r22 = mWasListen[i];
|
||||
var_r23 = mWasRepeat[i];
|
||||
}
|
||||
#endif
|
||||
if (var_r22) {
|
||||
if (field_0x2e8[i] == 18.0f) {
|
||||
#ifdef TARGET_PC
|
||||
if (field_0x2e8[i] == 18.0f && dusk::frame_interp::get_ui_tick_pending())
|
||||
#else
|
||||
if (field_0x2e8[i] == 18.0f)
|
||||
#endif
|
||||
{
|
||||
mDoAud_seStart(Z2SE_SY_HINT_BUTTON_BLINK, NULL, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -307,7 +307,7 @@ static u8 getOutFontNumberType(int param_0) {
|
||||
}
|
||||
}
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
static void setPlayerName(char* i_player_name, u8 param_2) {
|
||||
if (param_2 != 0) {
|
||||
strcpy(i_player_name, dComIfGs_getPlayerName());
|
||||
@@ -1485,7 +1485,7 @@ bool jmessage_tMeasureProcessor::do_tag(u32 i_tag, void const* i_data, u32 i_siz
|
||||
char buffer[40];
|
||||
switch (i_tag & 0xFF00FFFF) {
|
||||
case MSGTAG_PLAYER_GENITIV:
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_GERMAN) {
|
||||
setPlayerName(buffer, 1);
|
||||
} else {
|
||||
@@ -1495,7 +1495,7 @@ bool jmessage_tMeasureProcessor::do_tag(u32 i_tag, void const* i_data, u32 i_siz
|
||||
push_word(buffer);
|
||||
return true;
|
||||
case MSGTAG_HORSE_GENITIV:
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_GERMAN) {
|
||||
setHorseName(buffer, 1);
|
||||
} else {
|
||||
@@ -4270,7 +4270,7 @@ bool jmessage_string_tMeasureProcessor::do_tag(u32 i_tag, void const* i_data, u3
|
||||
char buffer[40];
|
||||
switch (i_tag & 0xFF00FFFF) {
|
||||
case MSGTAG_PLAYER_GENITIV:
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_GERMAN) {
|
||||
setPlayerName(buffer, 1);
|
||||
} else {
|
||||
@@ -4281,7 +4281,7 @@ bool jmessage_string_tMeasureProcessor::do_tag(u32 i_tag, void const* i_data, u3
|
||||
stack_pushCurrent(buffer);
|
||||
break;
|
||||
case MSGTAG_HORSE_GENITIV:
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_GERMAN) {
|
||||
setHorseName(buffer, 1);
|
||||
} else {
|
||||
@@ -4878,7 +4878,7 @@ bool jmessage_string_tRenderingProcessor::do_tag(u32 i_tag, void const* i_data,
|
||||
char buffer[40];
|
||||
switch (i_tag & 0xFF00FFFF) {
|
||||
case MSGTAG_PLAYER_GENITIV:
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_GERMAN) {
|
||||
setPlayerName(buffer, 1);
|
||||
} else {
|
||||
@@ -4889,7 +4889,7 @@ bool jmessage_string_tRenderingProcessor::do_tag(u32 i_tag, void const* i_data,
|
||||
push_word(buffer);
|
||||
break;
|
||||
case MSGTAG_HORSE_GENITIV:
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
if (dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_GERMAN) {
|
||||
setHorseName(buffer, 1);
|
||||
} else {
|
||||
|
||||
+27
-2
@@ -24,9 +24,11 @@
|
||||
#include "f_op/f_op_msg_mng.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||
#include "dusk/version.hpp"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include "m_Do/m_Do_lib.h"
|
||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/settings.h"
|
||||
@@ -1643,7 +1645,30 @@ void dMsgObject_c::readMessageGroupLocal(mDoDvdThd_mountXArchive_c** p_arcMount)
|
||||
#else
|
||||
#if TARGET_PC
|
||||
// Original game UB
|
||||
snprintf(arcName, sizeof(arcName), "/res/Msgus/bmgres%d.arc", msgGroup);
|
||||
|
||||
if (dusk::version::isRegionPal()) {
|
||||
switch (dComIfGs_getPalLanguage()) {
|
||||
case dSv_player_config_c::LANGUAGE_GERMAN:
|
||||
snprintf(arcName, sizeof(arcName), "/res/Msgde/bmgres%d.arc", msgGroup);
|
||||
break;
|
||||
case dSv_player_config_c::LANGUAGE_FRENCH:
|
||||
snprintf(arcName, sizeof(arcName), "/res/Msgfr/bmgres%d.arc", msgGroup);
|
||||
break;
|
||||
case dSv_player_config_c::LANGUAGE_SPANISH:
|
||||
snprintf(arcName, sizeof(arcName), "/res/Msgsp/bmgres%d.arc", msgGroup);
|
||||
break;
|
||||
case dSv_player_config_c::LANGUAGE_ITALIAN:
|
||||
snprintf(arcName, sizeof(arcName), "/res/Msgit/bmgres%d.arc", msgGroup);
|
||||
break;
|
||||
default:
|
||||
snprintf(arcName, sizeof(arcName), "/res/Msguk/bmgres%d.arc", msgGroup);
|
||||
}
|
||||
} else if (dusk::version::isRegionJpn()) {
|
||||
snprintf(arcName, sizeof(arcName), "/res/Msgjp/bmgres%d.arc", msgGroup);
|
||||
} else {
|
||||
snprintf(arcName, sizeof(arcName), "/res/Msgus/bmgres%d.arc", msgGroup);
|
||||
}
|
||||
|
||||
#else
|
||||
sprintf(arcName, "/res/Msgus/bmgres%d.arc", msgGroup);
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "Z2AudioLib/Z2WolfHowlMgr.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/settings.h"
|
||||
#endif
|
||||
|
||||
@@ -580,9 +581,14 @@ void dMsgScrnHowl_c::drawWave() {
|
||||
f17 = local_60;
|
||||
f18 = local_64;
|
||||
} else {
|
||||
field_0x2134++;
|
||||
if (field_0x2134 > 30) {
|
||||
field_0x2134 = 0;
|
||||
#if TARGET_PC
|
||||
if (dusk::frame_interp::get_ui_tick_pending())
|
||||
#endif
|
||||
{
|
||||
field_0x2134++;
|
||||
if (field_0x2134 > 30) {
|
||||
field_0x2134 = 0;
|
||||
}
|
||||
}
|
||||
if (field_0x2134 < 15) {
|
||||
local_dc = field_0x2134 / 15.0f;
|
||||
|
||||
@@ -334,11 +334,11 @@ void dMsgUnit_c::setTag(int i_type, int i_value, char* o_buffer, bool param_4) {
|
||||
vals[1] = ((dMsgUnit_inf1_section_t*)pInfoBlock)->entries[i_type].endFrame;
|
||||
#endif
|
||||
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC || REGION_PAL
|
||||
if (i_value == 1 ||
|
||||
(dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_FRENCH &&
|
||||
i_value == 0)) {
|
||||
#elif !REGION_USA
|
||||
#elif !REGION_USA // Dusk TODO: What? This checks for Spanish when *not* PAL or USA?
|
||||
if (i_value == 1 ||
|
||||
(dComIfGs_getPalLanguage() == dSv_player_config_c::LANGUAGE_SPANISH &&
|
||||
i_value == 0)) {
|
||||
|
||||
+300
-99
@@ -8,9 +8,15 @@
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "JSystem/J2DGraph/J2DAnmLoader.h"
|
||||
#include "dusk/version.hpp"
|
||||
#include "f_op/f_op_msg_mng.h"
|
||||
|
||||
static bool isPalOrJpn() {
|
||||
return dusk::version::isRegionPal() || dusk::version::isRegionJpn();
|
||||
}
|
||||
|
||||
static const char* l_mojiHira[65] = {
|
||||
"あ", "い", "う", "え", "お", "か", "き", "く", "け", "こ", "さ", "し", "す",
|
||||
"せ", "そ", "た", "ち", "つ", "て", "と", "な", "に", "ぬ", "ね", "の", "は",
|
||||
@@ -66,15 +72,31 @@ static const char* l_mojiEisu[65] = {
|
||||
"X", "k", "x", ",", "L", "Y", "l", "y", ".", "M", "Z", "m", "z", " ",
|
||||
};
|
||||
|
||||
#if REGION_PAL
|
||||
static char* l_mojiEisuPal_1[65] = {
|
||||
#if TARGET_PC
|
||||
// The game normally mutates this string list to fill in the real character codes.
|
||||
// That can't work on a modern platform, so instead I've filled them out ahead of time.
|
||||
static const char* l_mojiEisuPal_1[65] = {
|
||||
"A", "N", "\xC0", "\xCF", "1", "B", "O", "\xC1", "\xD0", "2", "C", "P", "\xC2", "\xD1", "3", "D", "Q",
|
||||
"\xC3", "\xD2", "4", "E", "R", "\xC4", "\xD3", "5", "F", "S", "\xC5", "\xD4", "6", "G", "T", "\xC6", "\xD5",
|
||||
"7", "H", "U", "\xC7", "\xD6", "8", "I", "V", "\xC8", "\xD7", "9", "J", "W", "\xC9", "\xD8", "0", "K",
|
||||
"X", "\xCA", "\xD9", ",", "L", "Y", "\xCB", "\xDA", ".", "M", "Z", "\xCC", "\xDB", " ",
|
||||
};
|
||||
|
||||
static const char* l_mojiEisuPal_2[65] = {
|
||||
"a", "n", "\xE0", "\xEF", "1", "b", "o", "\xE1", "\xF0", "2", "c", "p", "\xE2", "\xF1", "3", "d", "q",
|
||||
"\xE3", "\xF2", "4", "e", "r", "\xE4", "\xF3", "5", "f", "s", "\xE5", "\xF4", "6", "g", "t", "\xE6",
|
||||
"\xF5", "7", "h", "u", "\xE7", "\xF6", "8", "i", "v", "\xE8", "\xF7", "9", "j", "w", "\xE9", "\xF8", "0",
|
||||
"k", "x", "\xEA", "\xF9", ",", "l", "y", "\xEB", "\xFA", ".", "m", "z", "\xEC", "\xFB", " ",
|
||||
};
|
||||
#elif REGION_PAL
|
||||
static const char* l_mojiEisuPal_1[65] = {
|
||||
"A", "N", "AA", "BB", "1", "B", "O", "CC", "DD", "2", "C", "P", "EE", "FF", "3", "D", "Q",
|
||||
"GG", "HH", "4", "E", "R", "II", "JJ", "5", "F", "S", "KK", "LL", "6", "G", "T", "MM", "NN",
|
||||
"7", "H", "U", "OO", "PP", "8", "I", "V", "QQ", "RR", "9", "J", "W", "SS", "TT", "0", "K",
|
||||
"X", "UU", "VV", ",", "L", "Y", "WW", "XX", ".", "M", "Z", "YY", "ZZ", " ",
|
||||
};
|
||||
|
||||
static char* l_mojiEisuPal_2[65] = {
|
||||
static const char* l_mojiEisuPal_2[65] = {
|
||||
"a", "n", "aa", "bb", "1", "b", "o", "cc", "dd", "2", "c", "p", "ee", "ff", "3", "d", "q",
|
||||
"gg", "hh", "4", "e", "r", "ii", "jj", "5", "f", "s", "kk", "ll", "6", "g", "t", "mm",
|
||||
"nn", "7", "h", "u", "oo", "pp", "8", "i", "v", "qq", "rr", "9", "j", "w", "ss", "tt", "0",
|
||||
@@ -82,6 +104,16 @@ static char* l_mojiEisuPal_2[65] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if TARGET_PC
|
||||
// ' ' (full-width space)
|
||||
#define SPACE_MAYBE_FULL (dusk::version::isRegionJpn() ? '\x81\x40' : ' ')
|
||||
#elif REGION_JPN
|
||||
// ' ' (full-width space)
|
||||
#define SPACE_MAYBE_FULL '\x81\x40'
|
||||
#else
|
||||
#define SPACE_MAYBE_FULL ' '
|
||||
#endif
|
||||
|
||||
static dNm_HIO_c g_nmHIO;
|
||||
|
||||
typedef void (dName_c::*selProcFunc)(void);
|
||||
@@ -163,13 +195,18 @@ void dName_c::init() {
|
||||
field_0x2ac = mSelProc;
|
||||
field_0x2ad = mSelProc;
|
||||
field_0x2ae = field_0x2ac;
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC
|
||||
mMojiSet = isPalOrJpn() ? MOJI_HIRA : MOJI_EIGO;
|
||||
#elif REGION_PAL || REGION_JPN
|
||||
mMojiSet = MOJI_HIRA;
|
||||
#else
|
||||
mMojiSet = MOJI_EIGO;
|
||||
#endif
|
||||
mPrevMojiSet = 255;
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC
|
||||
mSelMenu = isPalOrJpn() ? MENU_HIRA : MENU_END;
|
||||
mPrevSelMenu = isPalOrJpn() ? MENU_HIRA : MENU_END;
|
||||
#elif REGION_PAL || REGION_JPN
|
||||
mSelMenu = MENU_HIRA;
|
||||
mPrevSelMenu = MENU_HIRA;
|
||||
#else
|
||||
@@ -187,7 +224,8 @@ void dName_c::initial() {
|
||||
mNextNameStr[0] = 0;
|
||||
}
|
||||
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC || REGION_PAL || REGION_JPN
|
||||
IF_DUSK_BLOCK(isPalOrJpn())
|
||||
if (mSelProc == PROC_MOJI_SELECT) {
|
||||
mMenuIcon[mMojiSet]->scale(g_nmHIO.mMenuScale, g_nmHIO.mMenuScale);
|
||||
mMenuText[mMojiSet]->setWhite(JUtility::TColor(0xC8, 0xC8, 0xC8, 0xFF));
|
||||
@@ -196,6 +234,7 @@ void dName_c::initial() {
|
||||
mMenuText[mPrevMojiSet]->setWhite(JUtility::TColor(0x96, 0x96, 0x96, 0xFF));
|
||||
}
|
||||
}
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -230,8 +269,8 @@ void dName_c::_move() {
|
||||
stick->checkTrigger();
|
||||
(this->*SelProc[mSelProc])();
|
||||
|
||||
#if REGION_PAL || REGION_JPN
|
||||
if (mDoCPd_c::getTrigY(PAD_1)) {
|
||||
#if TARGET_PC || REGION_PAL || REGION_JPN
|
||||
if (IF_DUSK(isPalOrJpn() &&) mDoCPd_c::getTrigY(PAD_1)) {
|
||||
mDoAud_seStart(Z2SE_SY_DUMMY, 0, 0, 0);
|
||||
mPrevMojiSet = mMojiSet;
|
||||
mMojiSet++;
|
||||
@@ -245,8 +284,8 @@ void dName_c::_move() {
|
||||
mojiListChange();
|
||||
} else {
|
||||
#endif
|
||||
#if REGION_JPN
|
||||
if (mDoCPd_c::getTrigX(PAD_1)) {
|
||||
#if TARGET_PC || REGION_JPN
|
||||
if (IF_DUSK(dusk::version::isRegionJpn() &&) mDoCPd_c::getTrigX(PAD_1)) {
|
||||
if (mCurPos != 0) {
|
||||
if (mojiChange(mCurPos - 1) == 1) {
|
||||
mDoAud_seStart(Z2SE_SY_DUMMY, 0, 0, 0);
|
||||
@@ -283,12 +322,14 @@ void dName_c::_move() {
|
||||
backSpace();
|
||||
}
|
||||
} else if (mDoCPd_c::getTrigStart(PAD_1)) {
|
||||
#define EIGO_OR_END DUSK_IF_ELSE((dusk::version::isRegionPal() ? MENU_EIGO : MENU_END), MENU_END)
|
||||
|
||||
#if REGION_PAL
|
||||
if ((mSelProc != PROC_MENU_SELECT || mSelMenu != MENU_EIGO) &&
|
||||
(mSelProc == PROC_MENU_SELECT || mSelProc == PROC_MOJI_SELECT))
|
||||
{
|
||||
#else
|
||||
if ((mSelProc != PROC_MENU_SELECT || mSelMenu != MENU_END) &&
|
||||
if ((mSelProc != PROC_MENU_SELECT || mSelMenu != EIGO_OR_END) &&
|
||||
(mSelProc == PROC_MENU_SELECT || mSelProc == PROC_MOJI_SELECT))
|
||||
{
|
||||
#endif
|
||||
@@ -297,7 +338,7 @@ void dName_c::_move() {
|
||||
#if REGION_PAL
|
||||
mSelMenu = MENU_EIGO;
|
||||
#else
|
||||
mSelMenu = MENU_END;
|
||||
mSelMenu = EIGO_OR_END;
|
||||
#endif
|
||||
|
||||
switch (mSelProc) {
|
||||
@@ -314,10 +355,10 @@ void dName_c::_move() {
|
||||
}
|
||||
}
|
||||
}
|
||||
#if REGION_JPN
|
||||
#if TARGET_PC || REGION_JPN
|
||||
}
|
||||
#endif
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC || REGION_PAL || REGION_JPN
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -327,10 +368,9 @@ void dName_c::_move() {
|
||||
int dName_c::nameCheck() {
|
||||
for (int i = 8, len = 7; i > 0; i--) {
|
||||
#if REGION_JPN
|
||||
// ' ' (full-width space)
|
||||
if (mChrInfo[len].mCharacter != ' ' && mChrInfo[len].mCharacter != '\x81\x40') {
|
||||
#else
|
||||
if (mChrInfo[len].mCharacter != ' ') {
|
||||
if (mChrInfo[len].mCharacter != ' ' IF_DUSK(&& (!dusk::version::isRegionJpn() || mChrInfo[len].mCharacter != '\x81\x40'))) {
|
||||
#endif
|
||||
return len + 1;
|
||||
}
|
||||
@@ -344,8 +384,8 @@ void dName_c::playNameSet(int nameLength) {
|
||||
char* str = mInputStr;
|
||||
|
||||
for (int i = 0; i < nameLength; i++) {
|
||||
#if REGION_JPN
|
||||
if (mChrInfo[i].mMojiSet == 2) {
|
||||
#if TARGET_PC || REGION_JPN
|
||||
if (!dusk::version::isRegionJpn() || mChrInfo[i].mMojiSet == 2) {
|
||||
*str = mChrInfo[i].mCharacter;
|
||||
str += 1;
|
||||
} else {
|
||||
@@ -727,7 +767,34 @@ int dName_c::getMoji() {
|
||||
int result = -1;
|
||||
const char* moji;
|
||||
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionPal()) {
|
||||
switch (mMojiSet) {
|
||||
case MOJI_HIRA:
|
||||
moji = l_mojiEisuPal_1[mCharRow + mCharColumn * 5];
|
||||
break;
|
||||
case MOJI_KATA:
|
||||
moji = l_mojiEisuPal_2[mCharRow + mCharColumn * 5];
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
switch (mMojiSet) {
|
||||
case MOJI_HIRA:
|
||||
moji = l_mojiHira[mCharRow + mCharColumn * 5];
|
||||
break;
|
||||
case MOJI_KATA:
|
||||
moji = l_mojikata[mCharRow + mCharColumn * 5];
|
||||
break;
|
||||
case MOJI_EIGO:
|
||||
moji = l_mojiEisu[mCharRow + mCharColumn * 5];
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#elif REGION_PAL
|
||||
switch (mMojiSet) {
|
||||
case MOJI_HIRA:
|
||||
moji = l_mojiEisuPal_1[mCharRow + mCharColumn * 5];
|
||||
@@ -750,7 +817,17 @@ int dName_c::getMoji() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if REGION_JPN
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionJpn()) {
|
||||
if (*(u8*)moji >> 4 == 0x8 || *(u8*)moji >> 4 == 0x9) {
|
||||
result = *(u16*)moji;
|
||||
} else {
|
||||
result = *moji;
|
||||
}
|
||||
} else {
|
||||
result = *moji;
|
||||
}
|
||||
#elif REGION_JPN
|
||||
if (*(u8*)moji >> 4 == 0x8 || *(u8*)moji >> 4 == 0x9) {
|
||||
result = *(u16*)moji;
|
||||
} else {
|
||||
@@ -763,6 +840,14 @@ int dName_c::getMoji() {
|
||||
return result;
|
||||
}
|
||||
|
||||
#if TARGET_PC
|
||||
#define CHAR_TRUNC(val) (dusk::version::isRegionPal() ? val & 0xFF : val)
|
||||
#elif REGION_PAL
|
||||
#define CHAR_TRUNC(val) (val & 0xFF)
|
||||
#else
|
||||
#define CHAR_TRUNC(val) val
|
||||
#endif
|
||||
|
||||
void dName_c::setMoji(int moji) {
|
||||
if (mCurPos == 8 || nameCheck() == 8) {
|
||||
mDoAud_seStart(Z2SE_SYS_ERROR, NULL, 0, 0);
|
||||
@@ -771,24 +856,14 @@ void dName_c::setMoji(int moji) {
|
||||
|
||||
s32 notEmpty = false;
|
||||
for (int i = mCurPos; i < 8; i++) {
|
||||
#if REGION_JPN
|
||||
// ' ' (full-width space)
|
||||
if (mChrInfo[i].mCharacter != '\x81\x40') {
|
||||
#else
|
||||
if (mChrInfo[i].mCharacter != ' ') {
|
||||
#endif
|
||||
if (mChrInfo[i].mCharacter != SPACE_MAYBE_FULL) {
|
||||
notEmpty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (notEmpty) {
|
||||
#if REGION_JPN
|
||||
// ' ' (full-width space)
|
||||
if (mChrInfo[7].mCharacter == '\x81\x40') {
|
||||
#else
|
||||
if (mChrInfo[7].mCharacter == ' ') {
|
||||
#endif
|
||||
if (mChrInfo[7].mCharacter == SPACE_MAYBE_FULL) {
|
||||
for (int i = 6; i >= mCurPos; i--) {
|
||||
mChrInfo[i + 1] = mChrInfo[i];
|
||||
}
|
||||
@@ -797,11 +872,7 @@ void dName_c::setMoji(int moji) {
|
||||
mChrInfo[mCurPos].mRow = mCharRow;
|
||||
mChrInfo[mCurPos].mMojiSet = mMojiSet;
|
||||
mChrInfo[mCurPos].field_0x3 = 1;
|
||||
#if REGION_PAL
|
||||
mChrInfo[mCurPos].mCharacter = moji & 0xFF;
|
||||
#else
|
||||
mChrInfo[mCurPos].mCharacter = moji;
|
||||
#endif
|
||||
mChrInfo[mCurPos].mCharacter = CHAR_TRUNC(moji);
|
||||
|
||||
if (mCurPos != 8) {
|
||||
mLastCurPos = mCurPos;
|
||||
@@ -814,11 +885,7 @@ void dName_c::setMoji(int moji) {
|
||||
mChrInfo[mCurPos].mRow = mCharRow;
|
||||
mChrInfo[mCurPos].mMojiSet = mMojiSet;
|
||||
mChrInfo[mCurPos].field_0x3 = 1;
|
||||
#if REGION_PAL
|
||||
mChrInfo[mCurPos].mCharacter = moji & 0xFF;
|
||||
#else
|
||||
mChrInfo[mCurPos].mCharacter = moji;
|
||||
#endif
|
||||
mChrInfo[mCurPos].mCharacter = CHAR_TRUNC(moji);
|
||||
|
||||
if (mCurPos != 8) {
|
||||
mLastCurPos = mCurPos;
|
||||
@@ -844,13 +911,8 @@ void dName_c::setNameText() {
|
||||
"CR\x1b"
|
||||
"CC[000000]\x1bGM[0]%c\x1bHM\x1b"
|
||||
"CC[ffffff]\x1bGM[0]%c",
|
||||
#if REGION_PAL
|
||||
(u8)mChrInfo[i].mCharacter & 0xFF,
|
||||
(u8)mChrInfo[i].mCharacter & 0xFF
|
||||
#else
|
||||
(u8)mChrInfo[i].mCharacter,
|
||||
(u8)mChrInfo[i].mCharacter
|
||||
#endif
|
||||
CHAR_TRUNC((u8)mChrInfo[i].mCharacter),
|
||||
CHAR_TRUNC((u8)mChrInfo[i].mCharacter)
|
||||
);
|
||||
#if REGION_JPN
|
||||
} else {
|
||||
@@ -889,7 +951,29 @@ void dName_c::nameCursorMove() {
|
||||
|
||||
void dName_c::selectCursorMove() {
|
||||
int idx;
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionPal()) {
|
||||
if (mCharColumn < 3) {
|
||||
idx = 0;
|
||||
} else if (mCharColumn < 6) {
|
||||
idx = 1;
|
||||
} else if (mCharColumn >= 6) {
|
||||
idx = 2;
|
||||
}
|
||||
} else if (dusk::version::isRegionJpn()) {
|
||||
if (mCharColumn < 3) {
|
||||
idx = 0;
|
||||
} else if (mCharColumn < 6) {
|
||||
idx = 1;
|
||||
} else if (mCharColumn < 8) {
|
||||
idx = 2;
|
||||
} else if (mCharColumn >= 8) {
|
||||
idx = 3;
|
||||
}
|
||||
} else {
|
||||
idx = 3;
|
||||
}
|
||||
#elif REGION_PAL
|
||||
if (mCharColumn < 3) {
|
||||
idx = 0;
|
||||
} else if (mCharColumn < 6) {
|
||||
@@ -930,7 +1014,36 @@ void dName_c::selectCursorMove() {
|
||||
|
||||
void dName_c::menuCursorPosSet() {
|
||||
mPrevSelMenu = mSelMenu;
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionPal()) {
|
||||
if (mCharColumn < 3) {
|
||||
mSelMenu = MENU_HIRA;
|
||||
} else if (mCharColumn < 6) {
|
||||
mSelMenu = MENU_KATA;
|
||||
} else if (mCharColumn >= 6) {
|
||||
mSelMenu = MENU_EIGO;
|
||||
}
|
||||
} else if (dusk::version::isRegionJpn()) {
|
||||
if (mCharColumn < 3) {
|
||||
mSelMenu = MENU_HIRA;
|
||||
return;
|
||||
}
|
||||
if (mCharColumn < 6) {
|
||||
mSelMenu = MENU_KATA;
|
||||
return;
|
||||
}
|
||||
if (mCharColumn < 8) {
|
||||
mSelMenu = MENU_EIGO;
|
||||
return;
|
||||
}
|
||||
if (mCharColumn >= 8) {
|
||||
mSelMenu = MENU_END;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
mSelMenu = MENU_END;
|
||||
}
|
||||
#elif REGION_PAL
|
||||
if (mCharColumn < 3) {
|
||||
mSelMenu = MENU_HIRA;
|
||||
} else if (mCharColumn < 6) {
|
||||
@@ -961,28 +1074,28 @@ void dName_c::menuCursorPosSet() {
|
||||
}
|
||||
|
||||
void dName_c::MenuSelect() {
|
||||
#if REGION_PAL || REGION_JPN
|
||||
if (stick->checkRightTrigger()) {
|
||||
#if TARGET_PC || REGION_PAL || REGION_JPN
|
||||
if (isPalOrJpn() && stick->checkRightTrigger()) {
|
||||
mDoAud_seStart(Z2SE_SY_CURSOR_OPTION, NULL, 0, 0);
|
||||
mPrevSelMenu = mSelMenu;
|
||||
mSelMenu++;
|
||||
#if REGION_PAL
|
||||
if (mSelMenu > MENU_EIGO) {
|
||||
#else
|
||||
if (mSelMenu > MENU_END) {
|
||||
if (mSelMenu > EIGO_OR_END) {
|
||||
#endif
|
||||
mSelMenu = MENU_HIRA;
|
||||
}
|
||||
MenuSelectAnmInit();
|
||||
mSelProc = PROC_MENU_SEL_ANM;
|
||||
} else if (stick->checkLeftTrigger()) {
|
||||
} else if (isPalOrJpn() && stick->checkLeftTrigger()) {
|
||||
mDoAud_seStart(Z2SE_SY_CURSOR_OPTION, NULL, 0, 0);
|
||||
mPrevSelMenu = mSelMenu;
|
||||
if (mSelMenu == MENU_HIRA) {
|
||||
#if REGION_JPN
|
||||
mSelMenu = MENU_END;
|
||||
#else
|
||||
mSelMenu = MENU_EIGO;
|
||||
mSelMenu = dusk::version::isRegionJpn() ? MENU_END : MENU_EIGO;
|
||||
#endif
|
||||
} else {
|
||||
mSelMenu--;
|
||||
@@ -1009,7 +1122,7 @@ void dName_c::MenuSelect() {
|
||||
#if REGION_PAL
|
||||
if (mSelMenu == MENU_EIGO) {
|
||||
#else
|
||||
if (mSelMenu == MENU_END) {
|
||||
if (mSelMenu == EIGO_OR_END) {
|
||||
#endif
|
||||
if (nameCheck() != 0) {
|
||||
mDoAud_seStart(Z2SE_SY_NAME_OK, NULL, 0, 0);
|
||||
@@ -1024,7 +1137,7 @@ void dName_c::MenuSelect() {
|
||||
#if REGION_PAL
|
||||
if (mSelMenu == MENU_EIGO) {
|
||||
#else
|
||||
if (mSelMenu == MENU_END) {
|
||||
if (mSelMenu == EIGO_OR_END) {
|
||||
#endif
|
||||
if (nameCheck() != 0) {
|
||||
mDoAud_seStart(Z2SE_SY_NAME_OK, NULL, 0, 0);
|
||||
@@ -1067,9 +1180,11 @@ void dName_c::MenuSelectAnm2() {
|
||||
if (canMove == true) {
|
||||
if (prevMenu_i != mojiSet_i) {
|
||||
mMenuText[prevMenu_i]->setWhite(JUtility::TColor(0x96, 0x96, 0x96, 0xFF));
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC || REGION_PAL || REGION_JPN
|
||||
IF_DUSK_BLOCK(isPalOrJpn())
|
||||
mMenuIcon[mojiSet_i]->scale(g_nmHIO.mMenuScale, g_nmHIO.mMenuScale);
|
||||
mMenuText[mojiSet_i]->setWhite(JUtility::TColor(0xC8, 0xC8, 0xC8, 0xFF));
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
}
|
||||
selectCursorMove();
|
||||
@@ -1081,6 +1196,11 @@ void dName_c::MenuSelectAnm2() {
|
||||
void dName_c::MenuSelectAnm3() {}
|
||||
|
||||
void dName_c::menuAbtnSelect() {
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionPal() && mSelMenu == MENU_EIGO) {
|
||||
goto pal_eigo;
|
||||
}
|
||||
#endif
|
||||
switch (mSelMenu) {
|
||||
case MENU_HIRA:
|
||||
case MENU_KATA:
|
||||
@@ -1098,6 +1218,7 @@ void dName_c::menuAbtnSelect() {
|
||||
#else
|
||||
case MENU_END:
|
||||
#endif
|
||||
IF_DUSK(pal_eigo:)
|
||||
int nameNum = nameCheck();
|
||||
if (nameNum != 0) {
|
||||
playNameSet(nameNum);
|
||||
@@ -1116,44 +1237,33 @@ void dName_c::backSpace() {
|
||||
if (mCurPos != 0) {
|
||||
mDoAud_seStart(Z2SE_SY_NAME_DELETE, NULL, 0, 0);
|
||||
|
||||
#if REGION_JPN
|
||||
// ' ' (full-width space)
|
||||
if (mCurPos == 8 && mChrInfo[7].mCharacter != '\x81\x40') {
|
||||
#else
|
||||
if (mCurPos == 8 && mChrInfo[7].mCharacter != ' ') {
|
||||
#endif
|
||||
if (mCurPos == 8 && mChrInfo[7].mCharacter != SPACE_MAYBE_FULL) {
|
||||
mChrInfo[7].mColumn = 7;
|
||||
mChrInfo[7].mRow = 1;
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC
|
||||
mChrInfo[7].mMojiSet = isPalOrJpn() ? MOJI_HIRA : MOJI_EIGO;
|
||||
#elif REGION_PAL || REGION_JPN
|
||||
mChrInfo[7].mMojiSet = MOJI_HIRA;
|
||||
#else
|
||||
mChrInfo[7].mMojiSet = MOJI_EIGO;
|
||||
#endif
|
||||
mChrInfo[7].field_0x3 = 1;
|
||||
#if REGION_JPN
|
||||
// ' ' (full-width space)
|
||||
mChrInfo[7].mCharacter = '\x81\x40';
|
||||
#else
|
||||
mChrInfo[7].mCharacter = ' ';
|
||||
#endif
|
||||
mChrInfo[7].mCharacter = SPACE_MAYBE_FULL;
|
||||
} else {
|
||||
for (int i = mCurPos - 1; i < 7; i++) {
|
||||
mChrInfo[i] = mChrInfo[i + 1];
|
||||
}
|
||||
mChrInfo[7].mColumn = 7;
|
||||
mChrInfo[7].mRow = 1;
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC
|
||||
mChrInfo[7].mMojiSet = isPalOrJpn() ? MOJI_HIRA : MOJI_EIGO;
|
||||
#elif REGION_PAL || REGION_JPN
|
||||
mChrInfo[7].mMojiSet = MOJI_HIRA;
|
||||
#else
|
||||
mChrInfo[7].mMojiSet = MOJI_EIGO;
|
||||
#endif
|
||||
mChrInfo[7].field_0x3 = 1;
|
||||
#if REGION_JPN
|
||||
// ' ' (full-width space)
|
||||
mChrInfo[7].mCharacter = '\x81\x40';
|
||||
#else
|
||||
mChrInfo[7].mCharacter = ' ';
|
||||
#endif
|
||||
mChrInfo[7].mCharacter = SPACE_MAYBE_FULL;
|
||||
}
|
||||
|
||||
setNameText();
|
||||
@@ -1164,7 +1274,31 @@ void dName_c::backSpace() {
|
||||
}
|
||||
|
||||
void dName_c::mojiListChange() {
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC
|
||||
const char** mojiSet;
|
||||
if (dusk::version::isRegionPal()) {
|
||||
switch (mMojiSet) {
|
||||
case MOJI_HIRA:
|
||||
mojiSet = l_mojiEisuPal_1;
|
||||
break;
|
||||
case MOJI_KATA:
|
||||
mojiSet = l_mojiEisuPal_2;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (mMojiSet) {
|
||||
case MOJI_HIRA:
|
||||
mojiSet = l_mojiHira;
|
||||
break;
|
||||
case MOJI_KATA:
|
||||
mojiSet = l_mojikata;
|
||||
break;
|
||||
case MOJI_EIGO:
|
||||
mojiSet = l_mojiEisu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#elif REGION_PAL
|
||||
char** mojiSet;
|
||||
|
||||
switch (mMojiSet) {
|
||||
@@ -1212,7 +1346,8 @@ void dName_c::mojiListChange() {
|
||||
strcpy(mMojiText[i], buf);
|
||||
}
|
||||
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC || REGION_PAL || REGION_JPN
|
||||
IF_DUSK_BLOCK(isPalOrJpn())
|
||||
if (mSelProc == PROC_MOJI_SELECT) {
|
||||
mMenuIcon[mMojiSet]->scale(g_nmHIO.mMenuScale, g_nmHIO.mMenuScale);
|
||||
mMenuText[mMojiSet]->setWhite(JUtility::TColor(0xC8, 0xC8, 0xC8, 0xFF));
|
||||
@@ -1221,6 +1356,7 @@ void dName_c::mojiListChange() {
|
||||
mMenuText[mPrevMojiSet]->setWhite(JUtility::TColor(0x96, 0x96, 0x96, 0xFF));
|
||||
}
|
||||
}
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1241,9 +1377,11 @@ void dName_c::menuCursorMove2() {
|
||||
if (menu_i != mojiSet_i) {
|
||||
mMenuIcon[menu_i]->scale(g_nmHIO.mMenuScale, g_nmHIO.mMenuScale);
|
||||
mMenuText[menu_i]->setWhite(JUtility::TColor(0xC8, 0xC8, 0xC8, 0xFF));
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC || REGION_PAL || REGION_JPN
|
||||
IF_DUSK_BLOCK(isPalOrJpn())
|
||||
mMenuIcon[mojiSet_i]->scale(1.0f, 1.0f);
|
||||
mMenuText[mojiSet_i]->setWhite(JUtility::TColor(0x96, 0x96, 0x96, 0xFF));
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1265,7 +1403,9 @@ void dName_c::selectCursorPosSet(int row) {
|
||||
mCharColumn = 3;
|
||||
break;
|
||||
case MENU_EIGO:
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC
|
||||
mCharColumn = dusk::version::isRegionPal() ? 8 : 6;
|
||||
#elif REGION_PAL
|
||||
mCharColumn = 8;
|
||||
#else
|
||||
mCharColumn = 6;
|
||||
@@ -1481,9 +1621,11 @@ void dName_c::screenSet() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !(REGION_PAL || REGION_JPN)
|
||||
#if TARGET_PC || !(REGION_PAL || REGION_JPN)
|
||||
IF_DUSK_BLOCK(!isPalOrJpn())
|
||||
mMenuIcon[0]->hide();
|
||||
mMenuIcon[1]->hide();
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
mMojiPane = nameIn.NameInScr->search(MULTI_CHAR('moji_n'));
|
||||
|
||||
@@ -1501,25 +1643,28 @@ void dName_c::screenSet() {
|
||||
((J2DTextBox*)nameTagPane[i])->setFont(nameIn.font);
|
||||
((J2DTextBox*)nameTagPane[i])->setString(72, "");
|
||||
((J2DTextBox*)nameTagPane[i])->setWhite(JUtility::TColor(0xC8, 0xC8, 0xC8, 0xFF));
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC || REGION_PAL
|
||||
IF_DUSK_BLOCK(dusk::version::isRegionPal())
|
||||
((J2DTextBox*)nameTagPane[i])->resize(24.0f, 23.0f);
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
mNameText[i] = ((J2DTextBox*)nameTagPane[i])->getStringPtr();
|
||||
}
|
||||
|
||||
#if REGION_PAL
|
||||
#if REGION_PAL // DUSK version note: this code mutates strings. We just edit the table.
|
||||
IF_DUSK_BLOCK(dusk::version::isRegionPal())
|
||||
int idx = 2;
|
||||
|
||||
static u8 palMoji00[13] = {
|
||||
static const u8 palMoji00[13] = {
|
||||
0xC0, 0xC1, 0xC2, 0xC4, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
|
||||
};
|
||||
static u8 palMoji01[13] = {
|
||||
static const u8 palMoji01[13] = {
|
||||
0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD6, 0x8C, 0xD9, 0xDA, 0xDB, 0xDC, 0x2D,
|
||||
};
|
||||
static u8 palMoji10[13] = {
|
||||
static const u8 palMoji10[13] = {
|
||||
0xE0, 0xE1, 0xE2, 0xE4, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE,
|
||||
};
|
||||
static u8 palMoji11[13] = {
|
||||
static const u8 palMoji11[13] = {
|
||||
0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF6, 0x9C, 0xF9, 0xFA, 0xFB, 0xFC, 0xDF,
|
||||
};
|
||||
|
||||
@@ -1536,6 +1681,7 @@ void dName_c::screenSet() {
|
||||
l_mojiEisuPal_2[idx + 1][0] = palMoji11[i];
|
||||
l_mojiEisuPal_2[idx + 1][1] = 0;
|
||||
}
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
|
||||
mCharColumn = 0;
|
||||
@@ -1574,18 +1720,15 @@ void dName_c::displayInit() {
|
||||
mNameCursor[i]->hide();
|
||||
mChrInfo[i].mColumn = 7;
|
||||
mChrInfo[i].mRow = 1;
|
||||
#if REGION_PAL || REGION_JPN
|
||||
#if TARGET_PC
|
||||
mChrInfo[i].mMojiSet = isPalOrJpn() ? MOJI_HIRA : MOJI_EIGO;
|
||||
#elif REGION_PAL || REGION_JPN
|
||||
mChrInfo[i].mMojiSet = MOJI_HIRA;
|
||||
#else
|
||||
mChrInfo[i].mMojiSet = MOJI_EIGO;
|
||||
#endif
|
||||
mChrInfo[i].field_0x3 = 1;
|
||||
#if REGION_JPN
|
||||
// ' ' (full-width space)
|
||||
mChrInfo[i].mCharacter = '\x81\x40';
|
||||
#else
|
||||
mChrInfo[i].mCharacter = ' ';
|
||||
#endif
|
||||
mChrInfo[i].mCharacter = SPACE_MAYBE_FULL;
|
||||
}
|
||||
|
||||
mIsInputEnd = false;
|
||||
@@ -1596,7 +1739,63 @@ void dName_c::NameStrSet() {
|
||||
|
||||
int i = 0;
|
||||
while (*moji != 0) {
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionPal()) {
|
||||
mChrInfo[i].mCharacter = static_cast<u8>(*moji);
|
||||
|
||||
for (int j = 0; j < 65; j++) {
|
||||
if (mChrInfo[i].mCharacter == *(u8*)l_mojiEisuPal_1[j] ||
|
||||
mChrInfo[i].mCharacter == *(u16*)l_mojiEisuPal_2[j])
|
||||
{
|
||||
mChrInfo[i].mColumn = j / 5;
|
||||
mChrInfo[i].mRow = j % 5;
|
||||
mChrInfo[i].mMojiSet = MOJI_HIRA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
moji++;
|
||||
i++;
|
||||
} else {
|
||||
if (*(u8*)moji >> 4 == 8 || *(u8*)moji >> 4 == 9) {
|
||||
mChrInfo[i].mCharacter = *(u16*)moji;
|
||||
|
||||
for (int j = 0; j < 65; j++) {
|
||||
if (mChrInfo[i].mCharacter == *(u16*)l_mojiHira[j] ||
|
||||
mChrInfo[i].mCharacter == *(u16*)l_mojiHira2[j] ||
|
||||
mChrInfo[i].mCharacter == *(u16*)l_mojiHira3[j])
|
||||
{
|
||||
mChrInfo[i].mColumn = j / 5;
|
||||
mChrInfo[i].mRow = j % 5;
|
||||
mChrInfo[i].mMojiSet = MOJI_HIRA;
|
||||
break;
|
||||
} else if (mChrInfo[i].mCharacter == *(u16*)l_mojikata[j] ||
|
||||
mChrInfo[i].mCharacter == *(u16*)l_mojikata2[j] ||
|
||||
mChrInfo[i].mCharacter == *(u16*)l_mojikata3[j])
|
||||
{
|
||||
mChrInfo[i].mColumn = j / 5;
|
||||
mChrInfo[i].mRow = j % 5;
|
||||
mChrInfo[i].mMojiSet = MOJI_KATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
moji += 2;
|
||||
i++;
|
||||
} else {
|
||||
mChrInfo[i].mCharacter = *moji;
|
||||
|
||||
for (int j = 0; j < 65; j++) {
|
||||
if (mChrInfo[i].mCharacter == *(u8*)l_mojiEisu[j]) {
|
||||
mChrInfo[i].mColumn = j / 5;
|
||||
mChrInfo[i].mRow = j % 5;
|
||||
mChrInfo[i].mMojiSet = MOJI_EIGO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
moji++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#elif REGION_PAL
|
||||
mChrInfo[i].mCharacter = static_cast<u8>(*moji);
|
||||
|
||||
for (int j = 0; j < 65; j++) {
|
||||
@@ -1669,7 +1868,9 @@ s32 dName_c::getMenuPosIdx(u8 selPos) {
|
||||
result = 1;
|
||||
break;
|
||||
case 2:
|
||||
#if REGION_PAL
|
||||
#if TARGET_PC
|
||||
result = dusk::version::isRegionPal() ? 3 : 2;
|
||||
#elif REGION_PAL
|
||||
result = 3;
|
||||
#else
|
||||
result = 2;
|
||||
|
||||
@@ -1972,7 +1972,12 @@ void dPa_light8PcallBack::draw(JPABaseEmitter* param_1, JPABaseParticle* param_2
|
||||
JGeometry::TVec3<f32> local_154;
|
||||
JGeometry::TVec3<f32> local_160;
|
||||
JGeometry::TVec3<f32> local_16c;
|
||||
dPa_setWindPower(param_2);
|
||||
#if TARGET_PC
|
||||
if (dusk::frame_interp::is_sim_frame())
|
||||
#endif
|
||||
{
|
||||
dPa_setWindPower(param_2);
|
||||
}
|
||||
MTXIdentity(local_60);
|
||||
MTXIdentity(auStack_90);
|
||||
param_2->getBaseAxis(&local_10c);
|
||||
|
||||
@@ -102,11 +102,7 @@ static void setIndirectTex(J3DModelData* i_modelData) {
|
||||
texture->setResTIMG(i, *mDoGph_gInf_c::getFrameBufferTimg());
|
||||
}
|
||||
if (memcmp(textureName, "Zbuffer", 8) == 0) {
|
||||
#if !TARGET_PC
|
||||
texture->setResTIMG(i, *mDoGph_gInf_c::getZbufferTimg());
|
||||
#else
|
||||
DuskLog.warn("Zbuffer texture binding not yet supported");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+173
-9
@@ -24,6 +24,7 @@
|
||||
#include "JSystem/JUtility/JUTConsole.h"
|
||||
|
||||
#include "dusk/logging.h"
|
||||
#include "dusk/version.hpp"
|
||||
|
||||
#if !PLATFORM_GCN
|
||||
#include <revolution/os.h>
|
||||
@@ -44,7 +45,12 @@ struct homeBtnData {
|
||||
};
|
||||
#endif
|
||||
|
||||
#if VERSION == VERSION_SHIELD
|
||||
#if TARGET_PC
|
||||
using namespace dusk::version;
|
||||
|
||||
#define LOGO_ARC versionSelect<const char*>({{GameVersion::GcnJpn, "Logo"}, {GameVersion::GcnPal, "LogoPal"}}, "LogoUs")
|
||||
#define MSG_PATH versionSelect<const char*>({{GameVersion::GcnJpn, "/res/Msgjp/bmgres.arc"}}, "/res/Msgus/bmgres.arc")
|
||||
#elif VERSION == VERSION_SHIELD
|
||||
#define LOGO_ARC "LogoUs"
|
||||
#define MSG_PATH "/res/Msgcn/bmgres.arc"
|
||||
#elif VERSION == VERSION_GCN_JPN
|
||||
@@ -789,7 +795,13 @@ dScnLogo_c::~dScnLogo_c() {
|
||||
JKR_DELETE(mProgressiveNo);
|
||||
JKR_DELETE(mProgressiveSel);
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC
|
||||
if (getGameVersion() == GameVersion::GcnPal) {
|
||||
mpPalLogoResCommand->getArchive()->removeResourceAll();
|
||||
mpPalLogoResCommand->getArchive()->unmount();
|
||||
mpPalLogoResCommand->destroy();
|
||||
}
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
mpPalLogoResCommand->getArchive()->removeResourceAll();
|
||||
mpPalLogoResCommand->getArchive()->unmount();
|
||||
mpPalLogoResCommand->destroy();
|
||||
@@ -951,7 +963,8 @@ static int phase_0(dScnLogo_c* i_this) {
|
||||
JUT_ASSERT(1528, i_this->mLogo01Heap != NULL);
|
||||
JKRHEAP_NAME(i_this->mLogo01Heap, "Logo01");
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
IF_DUSK_BLOCK(getGameVersion() == GameVersion::GcnPal)
|
||||
switch (i_this->getPalLanguage()) {
|
||||
case 1:
|
||||
i_this->mpPalLogoResCommand = mDoDvdThd_mountArchive_c::create("/res/Layout/LogoPalGm.arc", 0, NULL);
|
||||
@@ -970,6 +983,7 @@ static int phase_0(dScnLogo_c* i_this) {
|
||||
i_this->mpPalLogoResCommand = mDoDvdThd_mountArchive_c::create("/res/Layout/LogoPalUk.arc", 0, NULL);
|
||||
break;
|
||||
}
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
|
||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||
@@ -990,7 +1004,8 @@ static int phase_1(dScnLogo_c* i_this) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
IF_DUSK_BLOCK(getGameVersion() == GameVersion::GcnPal)
|
||||
if (!mDoDvdThd::SyncWidthSound) {
|
||||
return cPhs_INIT_e;
|
||||
}
|
||||
@@ -998,6 +1013,7 @@ static int phase_1(dScnLogo_c* i_this) {
|
||||
if (!i_this->mpPalLogoResCommand->sync()) {
|
||||
return cPhs_INIT_e;
|
||||
}
|
||||
IF_DUSK_BLOCK_END
|
||||
#endif
|
||||
|
||||
int rt;
|
||||
@@ -1237,7 +1253,113 @@ void dScnLogo_c::logoInitGC() {
|
||||
ResTIMG* dolbyImg = (ResTIMG*)dComIfG_getObjectRes(LOGO_ARC, 3);
|
||||
mDolbyLogo = JKR_NEW dDlst_2D_c(dolbyImg, 189, 150, 232, 112, 255);
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC
|
||||
if (getGameVersion() == GameVersion::GcnPal) {
|
||||
u8 language = getPalLanguage();
|
||||
if (language >= 5) {
|
||||
language = 0;
|
||||
}
|
||||
|
||||
static const char* choice[] = {
|
||||
"50_60_choice_eng.bti",
|
||||
"50_60_choice_ger.bti",
|
||||
"50_60_choice_fra.bti",
|
||||
"50_60_choice_spa.bti",
|
||||
"50_60_choice_ita.bti",
|
||||
};
|
||||
|
||||
static const char* yes[] = {
|
||||
"60_set_eng.bti",
|
||||
"60_set_ger.bti",
|
||||
"60_set_fra.bti",
|
||||
"60_set_spa.bti",
|
||||
"60_set_ita.bti",
|
||||
};
|
||||
|
||||
static const char* no[] = {
|
||||
"50_set_eng.bti",
|
||||
"50_set_ger.bti",
|
||||
"50_set_fra.bti",
|
||||
"50_set_spa.bti",
|
||||
"50_set_ita.bti",
|
||||
};
|
||||
|
||||
static const char* prog[] = {
|
||||
"progressive_pro.bti",
|
||||
"progressive_pro_gm.bti",
|
||||
"progressive_pro_fr.bti",
|
||||
"progressive_pro_sp.bti",
|
||||
"progressive_pro_it.bti",
|
||||
};
|
||||
|
||||
static const char* intr[] = {
|
||||
"progressive_inter.bti",
|
||||
"progressive_inter_gm.bti",
|
||||
"progressive_inter_fr.bti",
|
||||
"progressive_inter_sp.bti",
|
||||
"progressive_inter_it.bti",
|
||||
};
|
||||
|
||||
static const char* warning[] = {
|
||||
"warning.bti",
|
||||
"warning_gm.bti",
|
||||
"warning_fr.bti",
|
||||
"warning_sp.bti",
|
||||
"warning_it.bti",
|
||||
};
|
||||
|
||||
static const char* warningPs[] = {
|
||||
"warning_pstart.bti",
|
||||
"warning_pstart_gm.bti",
|
||||
"warning_pstart_fr.bti",
|
||||
"warning_pstart_sp.bti",
|
||||
"warning_pstart_it.bti",
|
||||
};
|
||||
|
||||
ResTIMG* warningImg = (ResTIMG*)mpPalLogoResCommand->getArchive()->getResource('DAT ', warning[language]);
|
||||
mWarning = JKR_NEW dDlst_2D_c(warningImg, 0, 0, FB_WIDTH, FB_HEIGHT, 255);
|
||||
|
||||
ResTIMG* warnStartImg = (ResTIMG*)mpPalLogoResCommand->getArchive()->getResource('DAT ', warningPs[language]);
|
||||
mWarningStart = JKR_NEW dDlst_2D_c(warnStartImg, 0, 359, FB_WIDTH, 48, 255);
|
||||
|
||||
ResTIMG* progChoiceImg = (ResTIMG*)mpPalLogoResCommand->getArchive()->getResource('DAT ', choice[language]);
|
||||
mProgressiveChoice = JKR_NEW dDlst_2D_c(progChoiceImg, 113, 143, 416, 210, 255);
|
||||
|
||||
ResTIMG* progYesImg = (ResTIMG*)mpPalLogoResCommand->getArchive()->getResource('DAT ', yes[language]);
|
||||
mProgressiveYes = JKR_NEW dDlst_2D_c(progYesImg, 121, 352, 200, 72, 255);
|
||||
mProgressiveYes->getPicture()->setWhite(JUtility::TColor(160, 160, 160, 255));
|
||||
|
||||
ResTIMG* progNoImg = (ResTIMG*)mpPalLogoResCommand->getArchive()->getResource('DAT ', no[language]);
|
||||
mProgressiveNo = JKR_NEW dDlst_2D_c(progNoImg, 320, 352, 200, 72, 255);
|
||||
mProgressiveNo->getPicture()->setWhite(JUtility::TColor(160, 160, 160, 255));
|
||||
|
||||
mProgressivePro = (ResTIMG*)mpPalLogoResCommand->getArchive()->getResource('DAT ', prog[language]);
|
||||
mProgressiveInter = (ResTIMG*)mpPalLogoResCommand->getArchive()->getResource('DAT ', intr[language]);
|
||||
mProgressiveSel = JKR_NEW dDlst_2D_c(mProgressivePro, 153, 309, 336, 88, 255);
|
||||
} else {
|
||||
ResTIMG* warningImg = (ResTIMG*)dComIfG_getObjectRes(LOGO_ARC, 10);
|
||||
mWarning = JKR_NEW dDlst_2D_c(warningImg, 0, 0, FB_WIDTH, FB_HEIGHT, 255);
|
||||
|
||||
ResTIMG* warnStartImg = (ResTIMG*)dComIfG_getObjectRes(LOGO_ARC, 11);
|
||||
mWarningStart = JKR_NEW dDlst_2D_c(warnStartImg, 0, 359, FB_WIDTH, 48, 255);
|
||||
|
||||
ResTIMG* progChoiceImg = (ResTIMG*)dComIfG_getObjectRes(LOGO_ARC, 5);
|
||||
mProgressiveChoice = JKR_NEW dDlst_2D_c(progChoiceImg, 113, 281, 416, 72, 255);
|
||||
|
||||
ResTIMG* progYesImg = (ResTIMG*)dComIfG_getObjectRes(LOGO_ARC, 9);
|
||||
mProgressiveYes = JKR_NEW dDlst_2D_c(progYesImg, 211, 372, 80, 32, 255);
|
||||
mProgressiveYes->getPicture()->setWhite(JUtility::TColor(160, 160, 160, 255));
|
||||
|
||||
ResTIMG* progNoImg = (ResTIMG*)dComIfG_getObjectRes(LOGO_ARC, 7);
|
||||
mProgressiveNo = JKR_NEW dDlst_2D_c(progNoImg, 350, 372, 80, 32, 255);
|
||||
mProgressiveNo->getPicture()->setWhite(JUtility::TColor(160, 160, 160, 255));
|
||||
|
||||
mProgressivePro = (ResTIMG*)dComIfG_getObjectRes(LOGO_ARC, 8);
|
||||
mProgressiveInter = (ResTIMG*)dComIfG_getObjectRes(LOGO_ARC, 6);
|
||||
mProgressiveSel = JKR_NEW dDlst_2D_c(mProgressivePro, 153, 309, 336, 88, 255);
|
||||
}
|
||||
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
u8 language = getPalLanguage();
|
||||
if (language >= 5) {
|
||||
language = 0;
|
||||
@@ -1395,7 +1517,30 @@ void dScnLogo_c::dvdDataLoad() {
|
||||
mpButtonCommand = aramMount(BUTTON_RES_PATH, mDoExt_getJ2dHeap());
|
||||
mpCardIconCommand = aramMount(ICON_RES_PATH, mDoExt_getJ2dHeap());
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC
|
||||
if (getGameVersion() == GameVersion::GcnPal) {
|
||||
switch (getPalLanguage()) {
|
||||
case 1:
|
||||
mpBmgResCommand = onMemMount("/res/Msgde/bmgres.arc");
|
||||
break;
|
||||
case 2:
|
||||
mpBmgResCommand = onMemMount("/res/Msgfr/bmgres.arc");
|
||||
break;
|
||||
case 3:
|
||||
mpBmgResCommand = onMemMount("/res/Msgsp/bmgres.arc");
|
||||
break;
|
||||
case 4:
|
||||
mpBmgResCommand = onMemMount("/res/Msgit/bmgres.arc");
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
mpBmgResCommand = onMemMount("/res/Msguk/bmgres.arc");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
mpBmgResCommand = onMemMount(MSG_PATH);
|
||||
}
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
switch (getPalLanguage()) {
|
||||
case 1:
|
||||
mpBmgResCommand = onMemMount("/res/Msgde/bmgres.arc");
|
||||
@@ -1435,7 +1580,10 @@ void dScnLogo_c::dvdDataLoad() {
|
||||
mpMsgResCommand[1] = aramMount(MSG_RES1_PATH, mDoExt_getJ2dHeap());
|
||||
mpMsgResCommand[2] = aramMount(MSG_RES2_PATH, mDoExt_getJ2dHeap());
|
||||
mpMsgResCommand[3] = aramMount(MSG_RES3_PATH, mDoExt_getJ2dHeap());
|
||||
#if VERSION == VERSION_GCN_JPN
|
||||
#if TARGET_PC
|
||||
const auto res4Path = versionSelect<const char*>({{GameVersion::GcnJpn, "/res/Layout/msgres04.arc"}}, "/res/Layout/msgres04F.arc");
|
||||
mpMsgResCommand[4] = aramMount( res4Path, mDoExt_getJ2dHeap());
|
||||
#elif VERSION == VERSION_GCN_JPN
|
||||
mpMsgResCommand[4] = aramMount("/res/Layout/msgres04.arc", mDoExt_getJ2dHeap());
|
||||
#else
|
||||
mpMsgResCommand[4] = aramMount("/res/Layout/msgres04F.arc", mDoExt_getJ2dHeap());
|
||||
@@ -1445,7 +1593,23 @@ void dScnLogo_c::dvdDataLoad() {
|
||||
|
||||
mpMain2DCommand = onMemMount(MAIN2D_PATH);
|
||||
|
||||
#if VERSION == VERSION_GCN_JPN
|
||||
#if TARGET_PC
|
||||
const auto fontResPath = versionSelect<const char*>(
|
||||
{
|
||||
{GameVersion::GcnJpn, "/res/Fontjp/fontres.arc"},
|
||||
{GameVersion::GcnPal, "/res/Fonteu/fontres.arc"},
|
||||
}, "/res/Fontus/fontres.arc");
|
||||
const auto fontRubyPath = versionSelect<const char*>(
|
||||
{
|
||||
{GameVersion::GcnJpn, "/res/Fontjp/rubyres.arc"},
|
||||
{GameVersion::GcnPal, "/res/Fonteu/rubyres.arc"},
|
||||
}, "/res/Fontus/rubyres.arc");
|
||||
|
||||
// Note: GCN_JPN mounts this archive as tail instead of head.
|
||||
// I'm guessing this is fine since we have more RAM.
|
||||
mpFontResCommand = onMemMount(fontResPath);
|
||||
mpRubyResCommand = onMemMount(fontRubyPath);
|
||||
#elif VERSION == VERSION_GCN_JPN
|
||||
mpFontResCommand = mDoDvdThd_mountXArchive_c::create("/res/Fontjp/fontres.arc", 1, JKRArchive::MOUNT_MEM, NULL);
|
||||
mpRubyResCommand = onMemMount("/res/Fontjp/rubyres.arc");
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
@@ -1545,7 +1709,7 @@ static int dScnLogo_IsDelete(dScnLogo_c* i_this) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL || PLATFORM_WII || PLATFORM_SHIELD
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL || PLATFORM_WII || PLATFORM_SHIELD
|
||||
u8 dScnLogo_c::getPalLanguage() {
|
||||
u8 language;
|
||||
|
||||
|
||||
+16
-5
@@ -5,19 +5,20 @@
|
||||
|
||||
#include "d/dolzel.h" // IWYU pragma: keep
|
||||
|
||||
#include "d/d_s_name.h"
|
||||
#include "JSystem/JKernel/JKRExpHeap.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#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"
|
||||
#include "m_Do/m_Do_Reset.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
#include "m_Do/m_Do_machine.h"
|
||||
#include "m_Do/m_Do_mtx.h"
|
||||
#include "m_Do/m_Do_main.h"
|
||||
#include "f_op/f_op_overlap_mng.h"
|
||||
#include "dusk/memory.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "m_Do/m_Do_mtx.h"
|
||||
|
||||
#if TARGET_PC
|
||||
#define SHOW_TV_SETTINGS_SCREEN (this->mShowTvSettingsScreen)
|
||||
@@ -412,6 +413,16 @@ void dScnName_c::changeGameScene() {
|
||||
dKy_clear_game_init();
|
||||
dComIfGs_resetDan();
|
||||
dComIfGs_setRestartRoomParam(0);
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.speedrunMode && dusk::getSettings().game.hideTvSettingsScreen) {
|
||||
// start a new run on file load if a run isn't already in progress
|
||||
if (!dusk::m_speedrunInfo.m_isRunStarted) {
|
||||
dusk::ImGuiMenuGame::resetForSpeedrunMode();
|
||||
dusk::m_speedrunInfo.startRun();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -16,6 +16,8 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/version.hpp"
|
||||
|
||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||
#include <revolution/sc.h>
|
||||
#include <revolution/wpad.h>
|
||||
@@ -1027,7 +1029,7 @@ void dSv_player_config_c::init() {
|
||||
mAttentionType = 0;
|
||||
mVibration = 1;
|
||||
|
||||
#if DEBUG
|
||||
#if DEBUG // DUSK VERSION SUPPORT: This field isn't used, so we can ignore it.
|
||||
mLanguage = SCGetLanguage();
|
||||
#elif REGION_PAL || VERSION >= VERSION_WII_USA_R2
|
||||
mLanguage = OSGetLanguage();
|
||||
@@ -1072,7 +1074,8 @@ void dSv_player_config_c::setVibration(u8 i_status) {
|
||||
}
|
||||
|
||||
u8 dSv_player_config_c::getPalLanguage() const {
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC || VERSION == VERSION_GCN_PAL
|
||||
IF_DUSK_BLOCK(dusk::version::getGameVersion() == dusk::version::GameVersion::GcnPal)
|
||||
switch (OSGetLanguage()) {
|
||||
case 0:
|
||||
return LANGUAGE_ENGLISH;
|
||||
@@ -1085,6 +1088,7 @@ u8 dSv_player_config_c::getPalLanguage() const {
|
||||
case 4:
|
||||
return LANGUAGE_ITALIAN;
|
||||
}
|
||||
IF_DUSK_BLOCK_END
|
||||
#elif VERSION >= VERSION_WII_USA_R0
|
||||
switch (SCGetLanguage()) {
|
||||
case 1:
|
||||
|
||||
@@ -0,0 +1,467 @@
|
||||
#include "dusk/achievements.h"
|
||||
#include "dusk/io.hpp"
|
||||
#include "dusk/main.h"
|
||||
#include "d/d_com_inf_game.h"
|
||||
#include "d/d_meter2_info.h"
|
||||
#include "d/actor/d_a_alink.h"
|
||||
#include "d/actor/d_a_npc4.h"
|
||||
#include "d/actor/d_a_player.h"
|
||||
#include "d/d_demo.h"
|
||||
#include "f_pc/f_pc_name.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
|
||||
namespace dusk {
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
static void checkGoatHerding(Achievement& a, int32_t threshMs) {
|
||||
if (dMeter2Info_getMaxCount() != 20 || dMeter2Info_getNowCount() != 20) {
|
||||
return;
|
||||
}
|
||||
const int32_t elapsed = dMeter2Info_getTimeMs();
|
||||
if (elapsed > 0 && elapsed <= threshMs) {
|
||||
a.progress = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto ACHIEVEMENTS_FILENAME = "achievements.json";
|
||||
|
||||
std::vector<AchievementSystem::Entry> AchievementSystem::makeEntries() {
|
||||
return {
|
||||
{
|
||||
{
|
||||
"hero_of_twilight",
|
||||
"Hero of Twilight",
|
||||
"Deliver the finishing blow to Ganondorf.",
|
||||
AchievementCategory::Story,
|
||||
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) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"rollgoal_8",
|
||||
"Rollgoal Novice",
|
||||
"Complete the first 8 rollgoal stages.",
|
||||
AchievementCategory::Minigame,
|
||||
true, 8, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = std::min((int)dComIfGs_getEventReg(0xf63f), 8);
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"rollgoal_all",
|
||||
"Lost Your Marbles",
|
||||
"Complete all rollgoal stages.",
|
||||
AchievementCategory::Minigame,
|
||||
true, 64, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_isEventBit(dSv_event_flag_c::KORO2_ALLCLEAR)) {
|
||||
a.progress = 64;
|
||||
} else {
|
||||
a.progress = dComIfGs_getEventReg(0xf63f);
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"goat_30s",
|
||||
"Ranch Hand",
|
||||
"Herd all 20 goats into the pen in under 30 seconds.",
|
||||
AchievementCategory::Minigame,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
checkGoatHerding(a, 30000);
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"goat_20s",
|
||||
"Bane of Howard",
|
||||
"Herd all 20 goats into the pen in under 20 seconds.",
|
||||
AchievementCategory::Minigame,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
checkGoatHerding(a, 20000);
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"goat_18s",
|
||||
"King of the Ranch",
|
||||
"Herd all 20 goats into the pen in under 18 seconds.",
|
||||
AchievementCategory::Minigame,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
checkGoatHerding(a, 18000);
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"cave_of_ordeals",
|
||||
"Conqueror of Ordeals",
|
||||
"Clear all 50 floors of the Cave of Ordeals.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (daNpcF_chkEvtBit(0x1F9)) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"cave_of_ordeals_heartless",
|
||||
"Indomitable",
|
||||
"Clear all 50 floors of the Cave of Ordeals with only 3 heart containers.",
|
||||
AchievementCategory::Challenge,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (daNpcF_chkEvtBit(0x1F9) && dComIfGs_getMaxLife() <= 15) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"speedrun_12h",
|
||||
"Been There Done That",
|
||||
"Defeat Ganondorf with a total save file play time under 12 hours.",
|
||||
AchievementCategory::Challenge,
|
||||
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;
|
||||
}
|
||||
const int64_t ticks = (static_cast<int64_t>(OSGetTime()) - dComIfGs_getSaveStartTime()) + dComIfGs_getSaveTotalTime();
|
||||
if (ticks / OS_TIMER_CLOCK < 12 * 3600) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"speedrun_8h",
|
||||
"Swift Blade",
|
||||
"Defeat Ganondorf with a total save file play time under 6 hours.",
|
||||
AchievementCategory::Challenge,
|
||||
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;
|
||||
}
|
||||
const int64_t ticks = (static_cast<int64_t>(OSGetTime()) - dComIfGs_getSaveStartTime()) + dComIfGs_getSaveTotalTime();
|
||||
if (ticks / OS_TIMER_CLOCK < 8 * 3600) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"princess_of_bugs",
|
||||
"The Princess of Bugs",
|
||||
"Deliver all 24 golden bugs to Agitha.",
|
||||
AchievementCategory::Collection,
|
||||
true, 24, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_checkGetInsectNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_poes",
|
||||
"Poe Collector",
|
||||
"Collect all 60 Poe Souls.",
|
||||
AchievementCategory::Collection,
|
||||
true, 60, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_getPohSpiritNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"hylian_loach",
|
||||
"Legendary Catch",
|
||||
"Catch a Hylian Loach.",
|
||||
AchievementCategory::Collection,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_getFishNum(1) > 0) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"all_fish",
|
||||
"Gone Fishin'",
|
||||
"Catch all 6 species of fish.",
|
||||
AchievementCategory::Collection,
|
||||
true, 6, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
int nUniqueFish = 0;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
if (dComIfGs_getFishNum(i) != 0) {
|
||||
nUniqueFish++;
|
||||
}
|
||||
}
|
||||
a.progress = nUniqueFish;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"a_big_heart",
|
||||
"A Big Heart",
|
||||
"Reach maximum health with all 20 heart containers.",
|
||||
AchievementCategory::Collection,
|
||||
true, 20, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dComIfGs_getMaxLife() / 5;
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"back_in_time",
|
||||
"Back in Time",
|
||||
"Perform the Back in Time glitch to play on the title screen.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
static int titleNoDemoFrames = 0;
|
||||
if (fopAcM_SearchByName(fpcNm_TITLE_e) == nullptr) {
|
||||
titleNoDemoFrames = 0;
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"early_master_sword",
|
||||
"Early Master Sword",
|
||||
"Obtain the Master Sword before completing Midna's Desperate Hour.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_isCollectSword(COLLECT_MASTER_SWORD) && !dComIfGs_isEventBit(0x1E08)) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"earliest_master_sword",
|
||||
"Earliest Master Sword",
|
||||
"Obtain the Master Sword before meeting Midna.",
|
||||
AchievementCategory::Glitched,
|
||||
false, 0, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
if (dComIfGs_isCollectSword(COLLECT_MASTER_SWORD) && !dComIfGs_isTransformLV(0)) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"ultimate_delivery",
|
||||
"The Ultimate Delivery",
|
||||
"Have all 16 postman letters at the same time.",
|
||||
AchievementCategory::Glitched,
|
||||
true, 16, 0, false
|
||||
},
|
||||
[](Achievement& a, json&) {
|
||||
a.progress = dMeter2Info_getRecieveLetterNum();
|
||||
},
|
||||
{}
|
||||
},
|
||||
{
|
||||
{
|
||||
"speedrun_4h",
|
||||
"Hero of Time",
|
||||
"Defeat Ganondorf with a total save file play time under 4 hours.",
|
||||
AchievementCategory::Glitched,
|
||||
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;
|
||||
}
|
||||
const int64_t ticks = (static_cast<int64_t>(OSGetTime()) - dComIfGs_getSaveStartTime()) + dComIfGs_getSaveTotalTime();
|
||||
if (ticks / OS_TIMER_CLOCK < 4 * 3600) {
|
||||
a.progress = 1;
|
||||
}
|
||||
},
|
||||
{}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
AchievementSystem::AchievementSystem() : m_entries(makeEntries()) {}
|
||||
|
||||
AchievementSystem& AchievementSystem::get() {
|
||||
static AchievementSystem instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::string AchievementSystem::consumePendingUnlock() {
|
||||
std::string msg = std::move(m_pendingUnlocks.front());
|
||||
m_pendingUnlocks.pop();
|
||||
return msg;
|
||||
}
|
||||
|
||||
std::vector<Achievement> AchievementSystem::getAchievements() const {
|
||||
std::vector<Achievement> result;
|
||||
result.reserve(m_entries.size());
|
||||
for (const auto& e : m_entries) {
|
||||
result.push_back(e.achievement);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void AchievementSystem::load() {
|
||||
m_loaded = true;
|
||||
const auto filePath = dusk::ConfigPath / ACHIEVEMENTS_FILENAME;
|
||||
if (!std::filesystem::exists(filePath)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
auto data = io::FileStream::ReadAllBytes(filePath.string().c_str());
|
||||
auto j = json::parse(data);
|
||||
if (!j.is_object()) {
|
||||
return;
|
||||
}
|
||||
for (auto& e : m_entries) {
|
||||
if (!j.contains(e.achievement.key)) {
|
||||
continue;
|
||||
}
|
||||
const auto& entry = j[e.achievement.key];
|
||||
if (entry.contains("progress")) {
|
||||
e.achievement.progress = entry["progress"].get<int32_t>();
|
||||
}
|
||||
if (entry.contains("unlocked")) {
|
||||
e.achievement.unlocked = entry["unlocked"].get<bool>();
|
||||
}
|
||||
if (entry.contains("extra")) {
|
||||
e.extra = entry["extra"];
|
||||
}
|
||||
}
|
||||
} catch (const std::exception&) {}
|
||||
}
|
||||
|
||||
void AchievementSystem::save() {
|
||||
json j = json::object();
|
||||
for (const auto& e : m_entries) {
|
||||
json entry = {
|
||||
{"progress", e.achievement.progress},
|
||||
{"unlocked", e.achievement.unlocked},
|
||||
};
|
||||
if (!e.extra.is_null()) {
|
||||
entry["extra"] = e.extra;
|
||||
}
|
||||
j[e.achievement.key] = std::move(entry);
|
||||
}
|
||||
try {
|
||||
io::FileStream::WriteAllText(
|
||||
(dusk::ConfigPath / ACHIEVEMENTS_FILENAME).string().c_str(),
|
||||
j.dump(2)
|
||||
);
|
||||
} catch (const std::exception&) {}
|
||||
}
|
||||
|
||||
void AchievementSystem::clearAll() {
|
||||
m_entries = makeEntries();
|
||||
save();
|
||||
}
|
||||
|
||||
void AchievementSystem::processEntry(Entry& e) {
|
||||
if (e.achievement.unlocked) {
|
||||
return;
|
||||
}
|
||||
const int32_t prevProgress = e.achievement.progress;
|
||||
e.check(e.achievement, e.extra);
|
||||
|
||||
const bool progressChanged = e.achievement.progress != prevProgress;
|
||||
const bool nowUnlocked = e.achievement.isCounter ?
|
||||
e.achievement.progress >= e.achievement.goal :
|
||||
e.achievement.progress > 0;
|
||||
|
||||
if (nowUnlocked) {
|
||||
e.achievement.progress = e.achievement.isCounter ? e.achievement.goal : 1;
|
||||
e.achievement.unlocked = true;
|
||||
m_pendingUnlocks.push(e.achievement.name);
|
||||
m_dirty = true;
|
||||
} else if (progressChanged) {
|
||||
m_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AchievementSystem::tick() {
|
||||
if (!m_loaded) {
|
||||
load();
|
||||
}
|
||||
if (!dusk::IsGameLaunched) {
|
||||
return;
|
||||
}
|
||||
for (auto& e : m_entries) {
|
||||
processEntry(e);
|
||||
}
|
||||
if (m_dirty) {
|
||||
save();
|
||||
m_dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dusk
|
||||
@@ -154,6 +154,7 @@ namespace dusk::config {
|
||||
template class ConfigImpl<f64>;
|
||||
template class ConfigImpl<std::string>;
|
||||
template class ConfigImpl<dusk::BloomMode>;
|
||||
template class ConfigImpl<dusk::GameLanguage>;
|
||||
}
|
||||
|
||||
void dusk::config::Register(ConfigVarBase& configVar) {
|
||||
|
||||
@@ -167,7 +167,6 @@ void InitializeCrashReporting() {
|
||||
|
||||
sentry_set_tag("git_branch", DUSK_WC_BRANCH);
|
||||
sentry_set_tag("build_type", DUSK_BUILD_TYPE);
|
||||
sentry_set_tag("tp_version", DUSK_TP_VERSION);
|
||||
g_sentryInitialized = true;
|
||||
|
||||
DuskLog.info("Initialized Sentry crash reporting");
|
||||
|
||||
+21
-7
@@ -80,8 +80,19 @@ static s32 DolVaToFileOffset(u32 va) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool LoadDolAsset(void* dst, u32 virtualAddress, s32 size) {
|
||||
s32 fileOffset = DolVaToFileOffset(virtualAddress);
|
||||
static u32 GetOffsetForVersion(std::initializer_list<OffsetVersion> version) {
|
||||
const auto gameVersion = dusk::version::getGameVersion();
|
||||
for (auto elem : version) {
|
||||
if (elem.mGameVersion == gameVersion) {
|
||||
return elem.mOffset;
|
||||
}
|
||||
}
|
||||
|
||||
DuskLog.fatal("Unable to find offset for this game version!");
|
||||
}
|
||||
|
||||
bool LoadDolAsset(void* dst, std::initializer_list<OffsetVersion> virtualAddress, s32 size) {
|
||||
s32 fileOffset = DolVaToFileOffset(GetOffsetForVersion(virtualAddress));
|
||||
if (fileOffset < 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -95,13 +106,16 @@ bool LoadDolAsset(void* dst, u32 virtualAddress, s32 size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadRelAsset(void* dst, const char* dvdPath, s32 offset, s32 size) {
|
||||
void* p = JKRDvdRipper::loadToMainRAM(dvdPath, (u8*)dst, EXPAND_SWITCH_UNKNOWN1, (u32)size, nullptr, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, (u32)offset, nullptr, nullptr);
|
||||
if (!p) DuskLog.fatal("dvd_asset: failed to load {} (offset={:#x} size={:#x})", dvdPath, offset, size);
|
||||
bool LoadRelAsset(void* dst, const char* dvdPath, std::initializer_list<OffsetVersion> offset, s32 size) {
|
||||
auto resOffset = GetOffsetForVersion(offset);
|
||||
void* p = JKRDvdRipper::loadToMainRAM(dvdPath, (u8*)dst, EXPAND_SWITCH_UNKNOWN1, (u32)size, nullptr, JKRDvdRipper::ALLOC_DIRECTION_FORWARD, resOffset, nullptr, nullptr);
|
||||
if (!p) DuskLog.fatal("dvd_asset: failed to load {} (offset={:#x} size={:#x})", dvdPath, resOffset, size);
|
||||
return p != nullptr;
|
||||
}
|
||||
|
||||
bool LoadArchivedRelAsset(void* dst, u32 memType, const char* relFileName, s32 offset, s32 size) {
|
||||
bool LoadArchivedRelAsset(void* dst, u32 memType, const char* relFileName, std::initializer_list<OffsetVersion> offset, s32 size) {
|
||||
auto resOffset = GetOffsetForVersion(offset);
|
||||
|
||||
// On TARGET_PC, cDyl_InitCallback skips DynamicModuleControl::initialize() due to static linking
|
||||
// Mount RELS.arc on first use so sArchive is available
|
||||
static bool s_mountAttempted = false;
|
||||
@@ -118,7 +132,7 @@ bool LoadArchivedRelAsset(void* dst, u32 memType, const char* relFileName, s32 o
|
||||
DuskLog.fatal("dvd_asset: {} not found in RELS archive", relFileName); return false;
|
||||
}
|
||||
|
||||
std::memcpy(dst, rel + offset, size);
|
||||
std::memcpy(dst, rel + resOffset, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
#include "ImGuiAchievements.hpp"
|
||||
#include "ImGuiConfig.hpp"
|
||||
#include "dusk/achievements.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "fmt/format.h"
|
||||
#include "imgui.h"
|
||||
|
||||
namespace dusk {
|
||||
|
||||
void ImGuiAchievements::notify(std::string name) {
|
||||
if (m_notifyTimer <= 0.f) {
|
||||
m_notifyName = std::move(name);
|
||||
m_notifyTimer = NOTIFY_DURATION;
|
||||
} else {
|
||||
m_notifyQueue.push(std::move(name));
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiAchievements::showNotification() {
|
||||
if (!getSettings().game.enableAchievementNotifications.getValue()) {
|
||||
return;
|
||||
}
|
||||
if (m_notifyTimer <= 0.f) {
|
||||
if (m_notifyQueue.empty()) {
|
||||
return;
|
||||
}
|
||||
m_notifyName = std::move(m_notifyQueue.front());
|
||||
m_notifyQueue.pop();
|
||||
m_notifyTimer = NOTIFY_DURATION;
|
||||
}
|
||||
|
||||
m_notifyTimer -= ImGui::GetIO().DeltaTime;
|
||||
|
||||
const float alpha = std::min({
|
||||
m_notifyTimer / NOTIFY_FADE_TIME,
|
||||
(NOTIFY_DURATION - m_notifyTimer) / NOTIFY_FADE_TIME,
|
||||
1.0f
|
||||
});
|
||||
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
const float padding = 12.0f;
|
||||
ImGui::SetNextWindowPos(
|
||||
ImVec2(viewport->WorkPos.x + viewport->WorkSize.x - padding, viewport->WorkPos.y + padding),
|
||||
ImGuiCond_Always, ImVec2(1.0f, 0.0f)
|
||||
);
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(alpha * 0.92f);
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.08f, 0.06f, 0.01f, alpha * 0.92f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.0f, 0.8f, 0.1f, alpha));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, alpha));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 2.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(14.0f, 10.0f));
|
||||
|
||||
constexpr ImGuiWindowFlags flags =
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing |
|
||||
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs;
|
||||
|
||||
if (ImGui::Begin("##achievement_notify", nullptr, flags)) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.82f, 0.1f, alpha));
|
||||
ImGui::TextUnformatted("Achievement Unlocked!");
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::Spacing();
|
||||
ImGui::TextUnformatted(m_notifyName.c_str());
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
|
||||
void ImGuiAchievements::draw(bool& open) {
|
||||
showNotification();
|
||||
|
||||
if (!open) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(640, 200), ImVec2(800, 900));
|
||||
ImGui::SetNextWindowSize(ImVec2(640, 480), ImGuiCond_FirstUseEver);
|
||||
|
||||
if (!ImGui::Begin(
|
||||
"Achievements", &open,
|
||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)
|
||||
)
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto achievements = AchievementSystem::get().getAchievements();
|
||||
|
||||
int unlocked = 0;
|
||||
for (const auto& a : achievements) {
|
||||
if (a.unlocked) {
|
||||
++unlocked;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Text("%d / %d achievements unlocked", unlocked, (int)achievements.size());
|
||||
ImGui::SameLine();
|
||||
config::ImGuiCheckbox("Notifications", getSettings().game.enableAchievementNotifications);
|
||||
ImGui::Separator();
|
||||
|
||||
static const struct {
|
||||
AchievementCategory cat;
|
||||
const char* label;
|
||||
ImVec4 color;
|
||||
} ACHIEVEMENT_CATEGORIES[] = {
|
||||
{AchievementCategory::Story, "Story", ImVec4(1.0f, 0.82f, 0.1f, 1.0f)},
|
||||
{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::Glitched, "Glitched", ImVec4(0.75f, 0.4f, 1.0f, 1.0f)},
|
||||
};
|
||||
|
||||
const float footerHeight = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||
|
||||
if (ImGui::BeginTabBar("##achievement_tabs", ImGuiTabBarFlags_FittingPolicyScroll)) {
|
||||
for (const auto& catInfo : ACHIEVEMENT_CATEGORIES) {
|
||||
int catTotal = 0, catUnlocked = 0;
|
||||
for (const auto& a : achievements) {
|
||||
if (a.category == catInfo.cat) {
|
||||
++catTotal;
|
||||
if (a.unlocked) {
|
||||
++catUnlocked;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (catTotal == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string tabLabel = fmt::format("{} ({}/{})", catInfo.label, catUnlocked, catTotal);
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, catInfo.color);
|
||||
const bool tabOpen = ImGui::BeginTabItem(tabLabel.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
if (tabOpen) {
|
||||
ImGui::BeginChild(
|
||||
"##cat_list",
|
||||
ImVec2(0, -footerHeight),
|
||||
ImGuiChildFlags_None,
|
||||
ImGuiWindowFlags_NoBackground
|
||||
);
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
for (const auto& a : achievements) {
|
||||
if (a.category != catInfo.cat) {
|
||||
continue;
|
||||
}
|
||||
ImGui::PushID(a.key);
|
||||
|
||||
ImGui::PushStyleColor(
|
||||
ImGuiCol_Text,
|
||||
a.unlocked ?
|
||||
ImVec4(1.0f, 0.65f, 0.15f, 1.0f) :
|
||||
ImGui::GetStyleColorVec4(ImGuiCol_Text)
|
||||
);
|
||||
|
||||
ImGui::TextUnformatted(a.name);
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
const char* statusLabel = a.unlocked ? "[Unlocked]" : "[Locked]";
|
||||
ImGui::SameLine(
|
||||
ImGui::GetContentRegionMax().x -
|
||||
ImGui::CalcTextSize(statusLabel).x
|
||||
);
|
||||
|
||||
if (a.unlocked) {
|
||||
ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f), "%s", statusLabel);
|
||||
} else {
|
||||
ImGui::TextColored(ImVec4(0.8f, 0.2f, 0.2f, 1.0f), "%s", statusLabel);
|
||||
}
|
||||
|
||||
ImGui::TextDisabled("%s", a.description);
|
||||
|
||||
if (a.isCounter) {
|
||||
const float fraction = a.goal > 0 ? (float)(a.progress) / (float)(a.goal) : 1.0f;
|
||||
const std::string overlay = fmt::format("{} / {}", a.progress, a.goal);
|
||||
ImGui::PushStyleColor(
|
||||
ImGuiCol_PlotHistogram,
|
||||
a.unlocked ?
|
||||
ImVec4(0.4f, 0.7f, 0.1f, 1.0f) :
|
||||
ImVec4(0.2f, 0.45f, 0.8f, 1.0f)
|
||||
);
|
||||
ImGui::ProgressBar(fraction, ImVec2(-1.0f, 0.0f), overlay.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::Button("Clear All Achievements")) {
|
||||
ImGui::OpenPopup("##confirm_clear");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("##confirm_clear")) {
|
||||
ImGui::Text("Reset all achievement progress?");
|
||||
ImGui::Spacing();
|
||||
if (ImGui::Button("Yes, reset all")) {
|
||||
AchievementSystem::get().clearAll();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace dusk
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
namespace dusk {
|
||||
|
||||
class ImGuiAchievements {
|
||||
public:
|
||||
void draw(bool& open);
|
||||
void notify(std::string name);
|
||||
|
||||
private:
|
||||
void showNotification();
|
||||
|
||||
std::string m_notifyName;
|
||||
float m_notifyTimer = 0.f;
|
||||
std::queue<std::string> m_notifyQueue;
|
||||
static constexpr float NOTIFY_DURATION = 4.0f;
|
||||
static constexpr float NOTIFY_FADE_TIME = 0.5f;
|
||||
};
|
||||
|
||||
} // namespace dusk
|
||||
@@ -14,10 +14,12 @@
|
||||
#include "SDL3/SDL_events.h"
|
||||
#include "SDL3/SDL_mouse.h"
|
||||
#include "aurora/lib/window.hpp"
|
||||
#include "dusk/achievements.h"
|
||||
#include "dusk/audio/DuskAudioSystem.h"
|
||||
#include "dusk/config.hpp"
|
||||
#include "dusk/dusk.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/livesplit.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/settings.h"
|
||||
#include "m_Do/m_Do_controller_pad.h"
|
||||
@@ -54,6 +56,21 @@ ImGuiWindow* FindDragScrollWindow(ImGuiWindow* window) {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FocusLastMenuBarItem() {
|
||||
ImGuiContext& g = *ImGui::GetCurrentContext();
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
const ImGuiID itemId = g.LastItemData.ID;
|
||||
if (window == nullptr || itemId == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::FocusWindow(window);
|
||||
ImGui::SetNavID(itemId, ImGuiNavLayer_Menu, g.CurrentFocusScopeId,
|
||||
ImGui::WindowRectAbsToRel(window, g.LastItemData.NavRect));
|
||||
ImGui::SetNavCursorVisibleAfterMove();
|
||||
g.NavHighlightItemUnderNav = true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace dusk {
|
||||
@@ -64,6 +81,10 @@ namespace dusk {
|
||||
ImGui::TextUnformatted(text.data(), text.data() + text.size());
|
||||
}
|
||||
|
||||
void DuskToast(std::string_view message, float duration) {
|
||||
g_imguiConsole.AddToast(message, duration);
|
||||
}
|
||||
|
||||
void ImGuiTextCenter(std::string_view text) {
|
||||
ImGui::NewLine();
|
||||
float fontSize = ImGui::CalcTextSize(
|
||||
@@ -295,6 +316,15 @@ namespace dusk {
|
||||
|
||||
UpdateSettings();
|
||||
|
||||
AchievementSystem::get().tick();
|
||||
while (AchievementSystem::get().hasPendingUnlock()) {
|
||||
if (getSettings().game.enableAchievementNotifications) {
|
||||
m_menuTools.notifyAchievement(AchievementSystem::get().consumePendingUnlock());
|
||||
} else {
|
||||
AchievementSystem::get().consumePendingUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)) &&
|
||||
ImGui::IsKeyPressed(ImGuiKey_R))
|
||||
{
|
||||
@@ -314,7 +344,17 @@ namespace dusk {
|
||||
}
|
||||
|
||||
m_isHidden = !getSettings().backend.duskMenuOpen;
|
||||
bool showMenu = !dusk::IsGameLaunched || !CheckMenuViewToggle(ImGuiKey_F1, m_isHidden);
|
||||
if (dusk::IsGameLaunched) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_F1)) {
|
||||
m_isHidden = !m_isHidden;
|
||||
}
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_GamepadBack)) {
|
||||
m_isHidden = !m_isHidden;
|
||||
m_focusMenuBar = !m_isHidden;
|
||||
}
|
||||
}
|
||||
|
||||
bool showMenu = !dusk::IsGameLaunched || !m_isHidden;
|
||||
if (dusk::IsGameLaunched) {
|
||||
const bool menuOpen = !m_isHidden;
|
||||
if (getSettings().backend.duskMenuOpen != menuOpen) {
|
||||
@@ -328,6 +368,10 @@ namespace dusk {
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
if (showMenu && ImGui::BeginMainMenuBar()) {
|
||||
m_menuGame.draw();
|
||||
if (m_focusMenuBar) {
|
||||
FocusLastMenuBarItem();
|
||||
m_focusMenuBar = false;
|
||||
}
|
||||
m_menuTools.draw();
|
||||
|
||||
const auto fpsLabel =
|
||||
@@ -352,16 +396,29 @@ namespace dusk {
|
||||
if (dusk::IsGameLaunched && !m_isLaunchInitialized) {
|
||||
m_toasts.emplace_back(ImGui::GetIO().MouseSource == ImGuiMouseSource_TouchScreen ?
|
||||
"Tap to toggle menu"s :
|
||||
"Press F1 to toggle menu"s,
|
||||
"Press F1 or Minus/Back to toggle menu"s,
|
||||
2.5f);
|
||||
m_isLaunchInitialized = true;
|
||||
if (getSettings().game.liveSplitEnabled) {
|
||||
dusk::speedrun::connectLiveSplit();
|
||||
}
|
||||
}
|
||||
|
||||
UpdateDragScroll();
|
||||
|
||||
m_menuGame.windowControllerConfig();
|
||||
m_menuGame.windowInputViewer();
|
||||
if (dusk::IsGameLaunched) {
|
||||
m_menuGame.drawSpeedrunTimerOverlay();
|
||||
|
||||
if (getSettings().game.liveSplitEnabled) {
|
||||
dusk::speedrun::updateLiveSplit();
|
||||
if (dusk::speedrun::consumeConnectedEvent())
|
||||
AddToast("LiveSplit connected");
|
||||
else if (dusk::speedrun::consumeDisconnectedEvent())
|
||||
AddToast("LiveSplit disconnected");
|
||||
}
|
||||
|
||||
if (dusk::IsGameLaunched && !dusk::getSettings().game.speedrunMode) {
|
||||
m_menuTools.ShowDebugOverlay();
|
||||
m_menuTools.ShowCameraOverlay();
|
||||
m_menuTools.ShowProcessManager();
|
||||
@@ -372,8 +429,9 @@ namespace dusk {
|
||||
m_menuTools.ShowPlayerInfo();
|
||||
m_menuTools.ShowAudioDebug();
|
||||
m_menuTools.ShowSaveEditor();
|
||||
m_menuTools.ShowStateShare();
|
||||
}
|
||||
m_menuTools.ShowStateShare();
|
||||
m_menuTools.ShowAchievements();
|
||||
DuskDebugPad(); // temporary, remove later
|
||||
|
||||
// Hide mouse cursor if the F1 menu is not open and the cursor is idle for 3 seconds.
|
||||
@@ -545,6 +603,10 @@ namespace dusk {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGuiConsole::AddToast(std::string_view message, float duration) {
|
||||
m_toasts.emplace_back(std::string(message), duration);
|
||||
}
|
||||
|
||||
void ImGuiConsole::ShowToasts() {
|
||||
if (m_toasts.empty()) {
|
||||
return;
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
void PostDraw();
|
||||
|
||||
static bool CheckMenuViewToggle(ImGuiKey key, bool& active);
|
||||
void AddToast(std::string_view message, float duration = 3.f);
|
||||
|
||||
private:
|
||||
struct Toast {
|
||||
@@ -40,6 +41,7 @@ private:
|
||||
float mouseHideTimer = 0.0f;
|
||||
|
||||
bool m_isHidden = true;
|
||||
bool m_focusMenuBar = false;
|
||||
bool m_isLaunchInitialized = false;
|
||||
bool m_touchTapActive = false;
|
||||
bool m_touchTapMoved = false;
|
||||
@@ -70,6 +72,7 @@ std::string BytesToString(size_t bytes);
|
||||
void SetOverlayWindowLocation(int corner);
|
||||
bool ShowCornerContextMenu(int& corner, int avoidCorner);
|
||||
void ImGuiStringViewText(std::string_view text);
|
||||
void DuskToast(std::string_view message, float duration = 3.f);
|
||||
void ImGuiBeginGroupPanel(const char* name, const ImVec2& size);
|
||||
void ImGuiEndGroupPanel();
|
||||
void ImGuiTextCenter(std::string_view text);
|
||||
|
||||
@@ -29,12 +29,14 @@ static void ApplyPresetHD() {
|
||||
s.game.fastTears.setValue(true);
|
||||
s.game.biggerWallets.setValue(true);
|
||||
s.game.invertCameraXAxis.setValue(true);
|
||||
s.game.freeCamera.setValue(true);
|
||||
}
|
||||
|
||||
static void ApplyPresetDusk() {
|
||||
ApplyPresetHD();
|
||||
|
||||
auto& s = getSettings();
|
||||
s.game.enableAchievementNotifications.setValue(true);
|
||||
s.game.enableQuickTransform.setValue(true);
|
||||
s.game.instantSaves.setValue(true);
|
||||
s.game.midnasLamentNonStop.setValue(true);
|
||||
|
||||
@@ -12,14 +12,26 @@
|
||||
#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"
|
||||
|
||||
namespace {
|
||||
constexpr int kInternalResolutionScaleMax = 12;
|
||||
|
||||
bool is_controller_neutral(int port) {
|
||||
if (port < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return PADGetNativeButtonPressed(port) == -1 &&
|
||||
PADGetNativeAxisPulled(port).nativeAxis == -1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace aurora::gx {
|
||||
@@ -167,6 +179,8 @@ namespace dusk {
|
||||
|
||||
config::ImGuiCheckbox("Enable Depth of Field", getSettings().game.enableDepthOfField);
|
||||
|
||||
config::ImGuiCheckbox("Enable Mini-Map Shadows", getSettings().game.enableMapBackground);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
@@ -191,7 +205,7 @@ namespace dusk {
|
||||
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");
|
||||
@@ -199,6 +213,7 @@ namespace dusk {
|
||||
|
||||
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);
|
||||
@@ -211,6 +226,7 @@ namespace dusk {
|
||||
ImGui::SetTooltip("Hearts will never drop from enemies,\n"
|
||||
"pots and various other places.");
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SeparatorText("Quality of Life");
|
||||
|
||||
@@ -280,12 +296,39 @@ namespace dusk {
|
||||
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);
|
||||
@@ -293,8 +336,8 @@ namespace dusk {
|
||||
config::ImGuiCheckbox("Infinite Oil", getSettings().game.infiniteOil);
|
||||
config::ImGuiCheckbox("Infinite Oxygen", getSettings().game.infiniteOxygen);
|
||||
config::ImGuiCheckbox("Infinite Rupees", getSettings().game.infiniteRupees);
|
||||
config::ImGuiCheckbox("Items Don't Despawn", getSettings().game.enableIndefiniteItemDrops);
|
||||
ImGui::SetItemTooltip("Items Don't Despawn Unless You Load A Different Room In Which Case They Do But Even Under Some Circumstances They Don't, It Is Quite Rare Though");
|
||||
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);
|
||||
@@ -317,6 +360,8 @@ namespace dusk {
|
||||
ImGui::SetTooltip("Makes the magic armor work without rupees.");
|
||||
}
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
@@ -383,7 +428,15 @@ namespace dusk {
|
||||
|
||||
ImGui::SeparatorText("Camera");
|
||||
|
||||
config::ImGuiCheckbox("Invert Camera X Axis", getSettings().game.invertCameraXAxis);
|
||||
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");
|
||||
|
||||
@@ -431,10 +484,12 @@ namespace dusk {
|
||||
|
||||
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);
|
||||
|
||||
@@ -444,6 +499,7 @@ namespace dusk {
|
||||
|
||||
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
|
||||
@@ -595,39 +651,90 @@ namespace dusk {
|
||||
|
||||
void ImGuiMenuGame::windowControllerConfig() {
|
||||
if (!m_showControllerConfig) {
|
||||
if (m_controllerConfig.m_isReading ||
|
||||
m_controllerConfig.m_suppressRemapActivationUntilRelease)
|
||||
{
|
||||
m_controllerConfig.m_isReading = false;
|
||||
m_controllerConfig.m_pendingButtonMapping = nullptr;
|
||||
m_controllerConfig.m_pendingAxisMapping = nullptr;
|
||||
m_controllerConfig.m_pendingPort = -1;
|
||||
m_controllerConfig.m_waitForInputRelease = false;
|
||||
m_controllerConfig.m_suppressRemapActivationUntilRelease = false;
|
||||
m_controllerConfig.m_suppressRemapActivationPort = -1;
|
||||
PADBlockInput(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool suppressRemapActivationThisFrame = m_controllerConfig.m_suppressRemapActivationUntilRelease;
|
||||
if (m_controllerConfig.m_suppressRemapActivationUntilRelease &&
|
||||
is_controller_neutral(m_controllerConfig.m_suppressRemapActivationPort))
|
||||
{
|
||||
m_controllerConfig.m_suppressRemapActivationUntilRelease = false;
|
||||
m_controllerConfig.m_suppressRemapActivationPort = -1;
|
||||
PADBlockInput(false);
|
||||
}
|
||||
|
||||
if ((m_controllerConfig.m_pendingButtonMapping != nullptr ||
|
||||
m_controllerConfig.m_pendingAxisMapping != nullptr) &&
|
||||
m_controllerConfig.m_waitForInputRelease)
|
||||
{
|
||||
m_controllerConfig.m_waitForInputRelease =
|
||||
!is_controller_neutral(m_controllerConfig.m_pendingPort);
|
||||
}
|
||||
|
||||
// if pending for a button mapping, check to set new input
|
||||
if (m_controllerConfig.m_pendingButtonMapping != nullptr) {
|
||||
if (m_controllerConfig.m_pendingButtonMapping != nullptr &&
|
||||
!m_controllerConfig.m_waitForInputRelease)
|
||||
{
|
||||
s32 nativeButton = PADGetNativeButtonPressed(m_controllerConfig.m_pendingPort);
|
||||
if (nativeButton != -1) {
|
||||
const int suppressPort = m_controllerConfig.m_pendingPort;
|
||||
m_controllerConfig.m_pendingButtonMapping->nativeButton = nativeButton;
|
||||
m_controllerConfig.m_pendingButtonMapping = nullptr;
|
||||
m_controllerConfig.m_pendingPort = -1;
|
||||
PADBlockInput(false);
|
||||
m_controllerConfig.m_isReading = false;
|
||||
m_controllerConfig.m_waitForInputRelease = false;
|
||||
m_controllerConfig.m_suppressRemapActivationUntilRelease = true;
|
||||
m_controllerConfig.m_suppressRemapActivationPort = suppressPort;
|
||||
suppressRemapActivationThisFrame = true;
|
||||
PADBlockInput(true);
|
||||
PADSerializeMappings();
|
||||
}
|
||||
}
|
||||
|
||||
// if pending for an axis mapping, check to set new input
|
||||
if (m_controllerConfig.m_pendingAxisMapping != nullptr) {
|
||||
if (m_controllerConfig.m_pendingAxisMapping != nullptr &&
|
||||
!m_controllerConfig.m_waitForInputRelease)
|
||||
{
|
||||
auto nativeAxis = PADGetNativeAxisPulled(m_controllerConfig.m_pendingPort);
|
||||
if (nativeAxis.nativeAxis != -1) {
|
||||
const int suppressPort = m_controllerConfig.m_pendingPort;
|
||||
m_controllerConfig.m_pendingAxisMapping->nativeAxis = nativeAxis;
|
||||
m_controllerConfig.m_pendingAxisMapping->nativeButton = -1;
|
||||
m_controllerConfig.m_pendingAxisMapping = nullptr;
|
||||
m_controllerConfig.m_pendingPort = -1;
|
||||
PADBlockInput(false);
|
||||
m_controllerConfig.m_isReading = false;
|
||||
m_controllerConfig.m_waitForInputRelease = false;
|
||||
m_controllerConfig.m_suppressRemapActivationUntilRelease = true;
|
||||
m_controllerConfig.m_suppressRemapActivationPort = suppressPort;
|
||||
suppressRemapActivationThisFrame = true;
|
||||
PADBlockInput(true);
|
||||
PADSerializeMappings();
|
||||
} else {
|
||||
auto nativeButton = PADGetNativeButtonPressed(m_controllerConfig.m_pendingPort);
|
||||
if (nativeButton != -1) {
|
||||
const int suppressPort = m_controllerConfig.m_pendingPort;
|
||||
m_controllerConfig.m_pendingAxisMapping->nativeAxis = {-1, AXIS_SIGN_POSITIVE};
|
||||
m_controllerConfig.m_pendingAxisMapping->nativeButton = nativeButton;
|
||||
m_controllerConfig.m_pendingAxisMapping = nullptr;
|
||||
m_controllerConfig.m_pendingPort = -1;
|
||||
PADBlockInput(false);
|
||||
m_controllerConfig.m_isReading = false;
|
||||
m_controllerConfig.m_waitForInputRelease = false;
|
||||
m_controllerConfig.m_suppressRemapActivationUntilRelease = true;
|
||||
m_controllerConfig.m_suppressRemapActivationPort = suppressPort;
|
||||
suppressRemapActivationThisFrame = true;
|
||||
PADBlockInput(true);
|
||||
PADSerializeMappings();
|
||||
}
|
||||
}
|
||||
@@ -663,6 +770,10 @@ namespace dusk {
|
||||
m_controllerConfig.m_pendingButtonMapping = nullptr;
|
||||
m_controllerConfig.m_pendingAxisMapping = nullptr;
|
||||
m_controllerConfig.m_pendingPort = -1;
|
||||
m_controllerConfig.m_waitForInputRelease = false;
|
||||
m_controllerConfig.m_isReading = false;
|
||||
m_controllerConfig.m_suppressRemapActivationUntilRelease = false;
|
||||
m_controllerConfig.m_suppressRemapActivationPort = -1;
|
||||
PADBlockInput(false);
|
||||
}
|
||||
|
||||
@@ -739,7 +850,7 @@ namespace dusk {
|
||||
|
||||
std::string dispName;
|
||||
if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingButtonMapping == &btnMappingList[i]) {
|
||||
dispName = fmt::format("Press a Key...##{}", btnName);
|
||||
dispName = fmt::format("{}##{}", m_controllerConfig.m_waitForInputRelease ? "Release..." : "Press a Key...", btnName);
|
||||
} else {
|
||||
const char* nativeName = GetNameForGamepadButton(gamepad, btnMappingList[i].nativeButton);
|
||||
if (nativeName == nullptr) {
|
||||
@@ -750,10 +861,11 @@ namespace dusk {
|
||||
bool pressed = ImGui::Button(dispName.c_str(),
|
||||
btnSize);
|
||||
|
||||
if (pressed) {
|
||||
if (pressed && !m_controllerConfig.m_isReading && !suppressRemapActivationThisFrame) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort;
|
||||
m_controllerConfig.m_pendingButtonMapping = &btnMappingList[i];
|
||||
m_controllerConfig.m_waitForInputRelease = true;
|
||||
PADBlockInput(true);
|
||||
}
|
||||
}
|
||||
@@ -783,17 +895,18 @@ namespace dusk {
|
||||
|
||||
std::string dispName;
|
||||
if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingAxisMapping == &axisMappingList[trigger]) {
|
||||
dispName = fmt::format("Press a Key...##{}", axisName);
|
||||
dispName = fmt::format("{}##{}", m_controllerConfig.m_waitForInputRelease ? "Release..." : "Press a Key...", axisName);
|
||||
} else {
|
||||
dispName = fmt::format("{0}##-{1}", PADGetNativeAxisName(axisMappingList[trigger].nativeAxis), trigger);
|
||||
}
|
||||
bool pressed = ImGui::Button(dispName.c_str(),
|
||||
btnSize);
|
||||
|
||||
if (pressed) {
|
||||
if (pressed && !m_controllerConfig.m_isReading && !suppressRemapActivationThisFrame) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort;
|
||||
m_controllerConfig.m_pendingAxisMapping = &axisMappingList[trigger];
|
||||
m_controllerConfig.m_waitForInputRelease = true;
|
||||
PADBlockInput(true);
|
||||
}
|
||||
}
|
||||
@@ -850,7 +963,7 @@ namespace dusk {
|
||||
|
||||
std::string dispName;
|
||||
if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingAxisMapping == &axisMappingList[axis]) {
|
||||
dispName = fmt::format("Press a Key...##{}", label);
|
||||
dispName = fmt::format("{}##{}", m_controllerConfig.m_waitForInputRelease ? "Release..." : "Press a Key...", label);
|
||||
} else {
|
||||
if (axisMappingList[axis].nativeAxis.nativeAxis != -1) {
|
||||
const char* signStr;
|
||||
@@ -869,10 +982,11 @@ namespace dusk {
|
||||
}
|
||||
bool pressed = ImGui::Button(dispName.c_str(), btnSize);
|
||||
|
||||
if (pressed) {
|
||||
if (pressed && !m_controllerConfig.m_isReading && !suppressRemapActivationThisFrame) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort;
|
||||
m_controllerConfig.m_pendingAxisMapping = &axisMappingList[axis];
|
||||
m_controllerConfig.m_waitForInputRelease = true;
|
||||
PADBlockInput(true);
|
||||
}
|
||||
}
|
||||
@@ -913,7 +1027,7 @@ namespace dusk {
|
||||
|
||||
std::string dispName;
|
||||
if (m_controllerConfig.m_isReading && m_controllerConfig.m_pendingAxisMapping == &axisMappingList[axis]) {
|
||||
dispName = fmt::format("Press a Key...##sub{}", label);
|
||||
dispName = fmt::format("{}##sub{}", m_controllerConfig.m_waitForInputRelease ? "Release..." : "Press a Key...", label);
|
||||
} else {
|
||||
if (axisMappingList[axis].nativeAxis.nativeAxis != -1) {
|
||||
const char* signStr;
|
||||
@@ -932,10 +1046,11 @@ namespace dusk {
|
||||
}
|
||||
bool pressed = ImGui::Button(fmt::format("{0}##sub{1}", dispName, label).c_str(), btnSize);
|
||||
|
||||
if (pressed) {
|
||||
if (pressed && !m_controllerConfig.m_isReading && !suppressRemapActivationThisFrame) {
|
||||
m_controllerConfig.m_isReading = true;
|
||||
m_controllerConfig.m_pendingPort = m_controllerConfig.m_selectedPort;
|
||||
m_controllerConfig.m_pendingAxisMapping = &axisMappingList[axis];
|
||||
m_controllerConfig.m_waitForInputRelease = true;
|
||||
PADBlockInput(true);
|
||||
}
|
||||
}
|
||||
@@ -956,7 +1071,7 @@ namespace dusk {
|
||||
ImGui::SameLine();
|
||||
|
||||
// Options panel
|
||||
ImGuiBeginGroupPanel("Options", ImVec2(150 * scale, 20 * scale));
|
||||
ImGuiBeginGroupPanel("Options", ImVec2(150 * scale, -1));
|
||||
|
||||
if (deadZones != nullptr) {
|
||||
if (ImGui::Checkbox("Enable Dead Zones", &deadZones->useDeadzones)) {
|
||||
@@ -967,8 +1082,113 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
if (PADSupportsRumbleIntensity(m_controllerConfig.m_selectedPort)) {
|
||||
ImGuiBeginGroupPanel("Rumble Intensity", ImVec2(150 * scale, -1));
|
||||
u16 low;
|
||||
u16 high;
|
||||
(void)PADGetRumbleIntensity(m_controllerConfig.m_selectedPort, &low, &high);
|
||||
float fLow = (static_cast<float>(low) / 32767.f) * 100.f;
|
||||
bool changed = ImGui::SliderFloat("Low", &fLow, 0.f, 100.f, "%.0f%%");
|
||||
float fHigh = (static_cast<float>(high) / 32767.f) * 100.f;
|
||||
changed |= ImGui::SliderFloat("High", &fHigh, 0.f, 100.f, "%.0f%%");
|
||||
if (changed) {
|
||||
PADSetRumbleIntensity(m_controllerConfig.m_selectedPort,
|
||||
static_cast<u16>((fLow / 100) * 32767),
|
||||
static_cast<u16>((fHigh / 100) * 32767));
|
||||
PADSerializeMappings();
|
||||
}
|
||||
if (ImGui::Button(fmt::format("{0}...##rumbleTest", m_controllerConfig.m_isRumbling ? "Stop": "Test").c_str(), {-1, 0})) {
|
||||
PADControlMotor(m_controllerConfig.m_selectedPort, !m_controllerConfig.m_isRumbling ? PAD_MOTOR_RUMBLE : PAD_MOTOR_STOP_HARD);
|
||||
m_controllerConfig.m_isRumbling ^= 1;
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
}
|
||||
ImGuiEndGroupPanel();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static std::string GetFormattedTime(OSTime ticks) {
|
||||
OSCalendarTime time;
|
||||
OSTicksToCalendarTime(ticks, &time);
|
||||
|
||||
return fmt::format("{0:02}:{1:02}:{2:02}.{3:03}", time.hour, time.min, time.sec, time.msec);
|
||||
}
|
||||
|
||||
void ImGuiMenuGame::resetForSpeedrunMode() {
|
||||
// reset settings that should be off for speedrun mode
|
||||
mDoMain::developmentMode = -1;
|
||||
|
||||
getSettings().game.damageMultiplier.setValue(1);
|
||||
getSettings().game.instantDeath.setValue(false);
|
||||
getSettings().game.noHeartDrops.setValue(false);
|
||||
|
||||
getSettings().game.infiniteHearts.setValue(false);
|
||||
getSettings().game.infiniteArrows.setValue(false);
|
||||
getSettings().game.infiniteBombs.setValue(false);
|
||||
getSettings().game.infiniteOil.setValue(false);
|
||||
getSettings().game.infiniteOxygen.setValue(false);
|
||||
getSettings().game.infiniteRupees.setValue(false);
|
||||
getSettings().game.enableIndefiniteItemDrops.setValue(false);
|
||||
|
||||
getSettings().game.moonJump.setValue(false);
|
||||
getSettings().game.superClawshot.setValue(false);
|
||||
getSettings().game.alwaysGreatspin.setValue(false);
|
||||
getSettings().game.enableFastIronBoots.setValue(false);
|
||||
getSettings().game.canTransformAnywhere.setValue(false);
|
||||
getSettings().game.fastSpinner.setValue(false);
|
||||
getSettings().game.freeMagicArmor.setValue(false);
|
||||
|
||||
getSettings().game.enableTurboKeybind.setValue(false);
|
||||
}
|
||||
|
||||
SpeedrunInfo m_speedrunInfo;
|
||||
|
||||
void ImGuiMenuGame::drawSpeedrunTimerOverlay() {
|
||||
if (!getSettings().game.speedrunMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// L+R+A+Start to reset timer
|
||||
if (mDoCPd_c::getHoldL(PAD_1) && mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getHoldA(PAD_1) && mDoCPd_c::getTrigStart(PAD_1)) {
|
||||
m_speedrunInfo.reset();
|
||||
}
|
||||
|
||||
// L+R+A+Z to manually stop timer
|
||||
if (mDoCPd_c::getHoldL(PAD_1) && mDoCPd_c::getHoldR(PAD_1) && mDoCPd_c::getHoldA(PAD_1) && mDoCPd_c::getTrigZ(PAD_1)) {
|
||||
if (m_speedrunInfo.m_isRunStarted) {
|
||||
m_speedrunInfo.m_endTimestamp = OSGetTime() - m_speedrunInfo.m_startTimestamp;
|
||||
m_speedrunInfo.m_isRunStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||
ImGuiWindowFlags flags =
|
||||
ImGuiWindowFlags_NoResize
|
||||
| ImGuiWindowFlags_NoDocking
|
||||
| ImGuiWindowFlags_NoTitleBar
|
||||
| ImGuiWindowFlags_NoScrollbar;
|
||||
|
||||
if (ImGui::Begin("##SpeedrunTimerWindow", nullptr, flags)) {
|
||||
OSTime elapsedTime = 0;
|
||||
if (m_speedrunInfo.m_isRunStarted) {
|
||||
elapsedTime = OSGetTime() - m_speedrunInfo.m_startTimestamp;
|
||||
} else if (m_speedrunInfo.m_endTimestamp != 0) {
|
||||
elapsedTime = m_speedrunInfo.m_endTimestamp;
|
||||
}
|
||||
|
||||
ImGui::Text("RTA");
|
||||
ImGui::SameLine(60.0f);
|
||||
ImGuiStringViewText(GetFormattedTime(elapsedTime));
|
||||
|
||||
if (!m_speedrunInfo.m_isPauseIGT) {
|
||||
m_speedrunInfo.m_igtTimer = elapsedTime - m_speedrunInfo.m_totalLoadTime;
|
||||
}
|
||||
|
||||
ImGui::Text("IGT");
|
||||
ImGui::SameLine(60.0f);
|
||||
ImGuiStringViewText(GetFormattedTime(m_speedrunInfo.m_igtTimer));
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,39 @@
|
||||
#include "imgui.h"
|
||||
|
||||
namespace dusk {
|
||||
struct SpeedrunInfo {
|
||||
void startRun() {
|
||||
m_isRunStarted = true;
|
||||
m_startTimestamp = OSGetTime();
|
||||
}
|
||||
|
||||
void stopRun() {
|
||||
m_isRunStarted = false;
|
||||
m_endTimestamp = OSGetTime() - m_startTimestamp;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_isRunStarted = false;
|
||||
m_startTimestamp = 0;
|
||||
m_endTimestamp = 0;
|
||||
m_isPauseIGT = false;
|
||||
m_loadStartTimestamp = 0;
|
||||
m_totalLoadTime = 0;
|
||||
m_igtTimer = 0;
|
||||
}
|
||||
|
||||
bool m_isRunStarted = false;
|
||||
OSTime m_startTimestamp = 0;
|
||||
OSTime m_endTimestamp = 0;
|
||||
|
||||
bool m_isPauseIGT = false;
|
||||
OSTime m_loadStartTimestamp = 0;
|
||||
OSTime m_totalLoadTime = 0;
|
||||
OSTime m_igtTimer = 0;
|
||||
};
|
||||
|
||||
extern SpeedrunInfo m_speedrunInfo;
|
||||
|
||||
class ImGuiMenuGame {
|
||||
public:
|
||||
ImGuiMenuGame();
|
||||
@@ -15,9 +48,12 @@ namespace dusk {
|
||||
|
||||
void windowInputViewer();
|
||||
void windowControllerConfig();
|
||||
void drawSpeedrunTimerOverlay();
|
||||
|
||||
static void ToggleFullscreen();
|
||||
|
||||
static void resetForSpeedrunMode();
|
||||
|
||||
private:
|
||||
void drawAudioMenu();
|
||||
void drawInputMenu();
|
||||
@@ -32,6 +68,10 @@ namespace dusk {
|
||||
PADButtonMapping* m_pendingButtonMapping = nullptr;
|
||||
PADAxisMapping* m_pendingAxisMapping = nullptr;
|
||||
int m_pendingPort = -1;
|
||||
bool m_waitForInputRelease = false;
|
||||
bool m_suppressRemapActivationUntilRelease = false;
|
||||
int m_suppressRemapActivationPort = -1;
|
||||
bool m_isRumbling = false;
|
||||
} m_controllerConfig;
|
||||
|
||||
bool m_showControllerConfig = false;
|
||||
@@ -40,6 +80,8 @@ namespace dusk {
|
||||
bool m_showInputViewerGyro = false;
|
||||
int m_inputOverlayCorner = 3;
|
||||
std::string m_controllerName;
|
||||
|
||||
bool m_showTimerWindow = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -50,14 +50,20 @@ namespace dusk {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(getSettings().game.speedrunMode);
|
||||
|
||||
ImGui::MenuItem("Save Editor", hotkeys::SHOW_SAVE_EDITOR, &m_showSaveEditor);
|
||||
ImGui::MenuItem("Map Loader", hotkeys::SHOW_MAP_LOADER, &m_showMapLoader);
|
||||
ImGui::MenuItem("State Share", hotkeys::SHOW_STATE_SHARE, &m_showStateShare);
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (!dusk::IsGameLaunched) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::MenuItem("Achievements", nullptr, &m_showAchievements);
|
||||
|
||||
#if DUSK_CAN_OPEN_DATA_FOLDER
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Open Data Folder")) {
|
||||
@@ -69,6 +75,8 @@ namespace dusk {
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Debug")) {
|
||||
ImGui::BeginDisabled(getSettings().game.speedrunMode);
|
||||
|
||||
bool developmentMode = mDoMain::developmentMode == 1;
|
||||
if (ImGui::Checkbox("Development Mode", &developmentMode)) {
|
||||
mDoMain::developmentMode = developmentMode ? 1 : -1;
|
||||
@@ -117,6 +125,9 @@ namespace dusk {
|
||||
}
|
||||
|
||||
ImGui::MenuItem("OSReport Force", nullptr, &OSReportReallyForceEnable);
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
@@ -252,4 +263,12 @@ namespace dusk {
|
||||
ImGui::End();
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
void ImGuiMenuTools::ShowAchievements() {
|
||||
m_achievementsWindow.draw(m_showAchievements);
|
||||
}
|
||||
|
||||
void ImGuiMenuTools::notifyAchievement(std::string name) {
|
||||
m_achievementsWindow.notify(std::move(name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "ImGuiAchievements.hpp"
|
||||
#include "ImGuiSaveEditor.hpp"
|
||||
#include "ImGuiStateShare.hpp"
|
||||
|
||||
@@ -26,6 +27,8 @@ namespace dusk {
|
||||
void ShowAudioDebug();
|
||||
void ShowSaveEditor();
|
||||
void ShowStateShare();
|
||||
void ShowAchievements();
|
||||
void notifyAchievement(std::string name);
|
||||
|
||||
private:
|
||||
bool m_showDebugOverlay = false;
|
||||
@@ -65,6 +68,9 @@ namespace dusk {
|
||||
|
||||
bool m_showStateShare = false;
|
||||
ImGuiStateShare m_stateShare;
|
||||
|
||||
bool m_showAchievements = false;
|
||||
ImGuiAchievements m_achievementsWindow;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ typedef void (ImGuiPreLaunchWindow::*drawFunc)();
|
||||
|
||||
drawFunc drawTable[2] = {&ImGuiPreLaunchWindow::drawMainMenu, &ImGuiPreLaunchWindow::drawOptions};
|
||||
|
||||
static constexpr std::array<const char*, 5> skLanguageNames = {
|
||||
"English", "German", "French", "Spanish", "Italian"
|
||||
};
|
||||
|
||||
static constexpr std::array<SDL_DialogFileFilter, 2> skGameDiscFileFilters{{
|
||||
{"Game Disc Images", "iso;gcm;ciso;gcz;nfs;rvz;wbfs;wia;tgc"},
|
||||
{"All Files", "*"},
|
||||
@@ -71,6 +75,7 @@ void fileDialogCallback(void* userdata, const char* path, const char* error) {
|
||||
}
|
||||
|
||||
self->m_selectedIsoPath = path;
|
||||
self->m_isPal = iso::isPal(path);
|
||||
getSettings().backend.isoPath.setValue(self->m_selectedIsoPath);
|
||||
config::Save();
|
||||
}
|
||||
@@ -88,6 +93,7 @@ bool ImGuiPreLaunchWindow::isSelectedPathValid() const {
|
||||
void ImGuiPreLaunchWindow::draw() {
|
||||
if (m_IsFirstDraw) {
|
||||
m_selectedIsoPath = getSettings().backend.isoPath;
|
||||
m_isPal = !m_selectedIsoPath.empty() && iso::isPal(m_selectedIsoPath.c_str());
|
||||
m_initialGraphicsBackend = getSettings().backend.graphicsBackend;
|
||||
m_IsFirstDraw = false;
|
||||
}
|
||||
@@ -189,12 +195,26 @@ void ImGuiPreLaunchWindow::drawOptions() {
|
||||
|
||||
ImGui::InputText("Game ISO Path", &m_selectedIsoPath, ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Set")) {
|
||||
if (ImGui::Button(m_selectedIsoPath == "" ? "Set" : "Change")) {
|
||||
ShowFileSelect(&fileDialogCallback, this, aurora::window::get_sdl_window(),
|
||||
skGameDiscFileFilters.data(), int(skGameDiscFileFilters.size()), nullptr,
|
||||
false);
|
||||
}
|
||||
|
||||
if (m_isPal) {
|
||||
auto selectedLanguage = getSettings().game.language.getValue();
|
||||
if (ImGui::BeginCombo("Language", skLanguageNames[static_cast<u8>(selectedLanguage)])) {
|
||||
for (u8 i = 0; i < skLanguageNames.size(); ++i) {
|
||||
if (ImGui::Selectable(skLanguageNames[i])) {
|
||||
getSettings().game.language.setValue(static_cast<GameLanguage>(i));
|
||||
config::Save();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
AuroraBackend configuredBackend = BACKEND_AUTO;
|
||||
const std::string& configuredBackendId = getSettings().backend.graphicsBackend;
|
||||
if (!try_parse_backend(configuredBackendId, configuredBackend)) {
|
||||
|
||||
@@ -18,5 +18,6 @@ public:
|
||||
|
||||
std::string m_selectedIsoPath;
|
||||
std::string m_errorString;
|
||||
bool m_isPal = false;
|
||||
};
|
||||
} // namespace dusk
|
||||
|
||||
@@ -1347,6 +1347,51 @@ namespace dusk {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
concept FlagIter = requires(T t) {
|
||||
++t;
|
||||
--t;
|
||||
t + 1;
|
||||
t < t;
|
||||
{ t->flagID } -> std::convertible_to<u16>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept FlagTester = requires(T t, u16 flagID) {
|
||||
{ t(flagID) } -> std::convertible_to<bool>;
|
||||
};
|
||||
|
||||
static void sortByFlags(FlagIter auto begin, FlagIter auto end, FlagTester auto&& flagTester) {
|
||||
if (begin == end) return;
|
||||
|
||||
FlagIter auto fullEnd = end;
|
||||
|
||||
// We want to find the location of where we can swap our `On` flags to.
|
||||
// We're gonna put the `Off` bits first, and the `On` bits last. 0 < 1
|
||||
// We can achieve this by skipping all the `On` bits at the end.
|
||||
|
||||
// backtrack until we find a bit that is off
|
||||
while (begin < --end && flagTester(end->flagID)) {
|
||||
// move the end pointer back while we find on bits
|
||||
}
|
||||
|
||||
// end should now be pointing to a bit that is off
|
||||
while (begin < end) {
|
||||
// if there's a flag that's on
|
||||
if (flagTester(begin->flagID)) {
|
||||
// move it to the end
|
||||
std::rotate(begin, begin + 1, fullEnd);
|
||||
// move back the end of where we're checking
|
||||
--end;
|
||||
// begin will now point to the next piece of data
|
||||
// because we've rotated the data >= begin to the left
|
||||
} else {
|
||||
// not on, check next flag
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSaveEditor::drawFlagsTab() {
|
||||
if (ImGui::TreeNode("Current Region Flags")) {
|
||||
dSv_memBit_c& membit = g_dComIfG_gameInfo.info.mMemory.mBit;
|
||||
@@ -1446,30 +1491,41 @@ namespace dusk {
|
||||
sort != nullptr && sort->SpecsCount > 0 &&
|
||||
(sort->SpecsDirty || sort->Specs[0].ColumnIndex == COLUMN_FLAG))
|
||||
{
|
||||
auto column = sort->Specs->ColumnIndex;
|
||||
const auto cmp = [&](const duskImguiEventFlagEntry& l,
|
||||
const duskImguiEventFlagEntry& r) -> bool {
|
||||
switch (column) {
|
||||
case COLUMN_FLAG:
|
||||
return (bool)event.isEventBit(l.flagID) <
|
||||
(bool)event.isEventBit(r.flagID);
|
||||
case COLUMN_NAME:
|
||||
return l.flagName < r.flagName;
|
||||
case COLUMN_LOC:
|
||||
return l.location < r.location;
|
||||
case COLUMN_DESC:
|
||||
return l.description < r.description;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto column = sort->Specs[0].ColumnIndex;
|
||||
const auto direction = sort->Specs[0].SortDirection;
|
||||
|
||||
if (direction == ImGuiSortDirection_Ascending) {
|
||||
std::sort(std::begin(duskImguiEventFlags), std::end(duskImguiEventFlags), cmp);
|
||||
// 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) {
|
||||
const auto testEventFunc = [&event](u16 flag) -> bool { return event.isEventBit(flag); };
|
||||
|
||||
if (direction == ImGuiSortDirection_Ascending) {
|
||||
sortByFlags(std::begin(duskImguiEventFlags),
|
||||
std::end(duskImguiEventFlags), testEventFunc);
|
||||
} else {
|
||||
sortByFlags(std::rbegin(duskImguiEventFlags),
|
||||
std::rend(duskImguiEventFlags), testEventFunc);
|
||||
}
|
||||
} else {
|
||||
std::sort(std::rbegin(duskImguiEventFlags), std::rend(duskImguiEventFlags), cmp);
|
||||
const auto cmp = [column](const duskImguiEventFlagEntry& l,
|
||||
const duskImguiEventFlagEntry& r) -> bool {
|
||||
switch (column) {
|
||||
case COLUMN_NAME: return l.flagName < r.flagName;
|
||||
case COLUMN_LOC: return l.location < r.location;
|
||||
case COLUMN_DESC: return l.description < r.description;
|
||||
default: return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (direction == ImGuiSortDirection_Ascending) {
|
||||
std::sort(std::begin(duskImguiEventFlags),
|
||||
std::end(duskImguiEventFlags), cmp);
|
||||
} else {
|
||||
std::sort(std::rbegin(duskImguiEventFlags),
|
||||
std::rend(duskImguiEventFlags), cmp);
|
||||
}
|
||||
}
|
||||
|
||||
sort->SpecsDirty = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,14 @@ constexpr const char* TP_GAME_IDS[] = {
|
||||
"RZDK01", // Wii KOR
|
||||
};
|
||||
|
||||
constexpr const char* PAL_GAME_IDS[] = {
|
||||
"GZ2P01", // GCN PAL
|
||||
"RZDP01", // Wii PAL
|
||||
};
|
||||
|
||||
constexpr const char* SUPPORTED_TP_GAME_IDS[] = {
|
||||
"GZ2E01", // GCN USA
|
||||
"GZ2P01", // GCN PAL
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
@@ -123,4 +129,30 @@ ValidationError validate(const char* path) {
|
||||
|
||||
return ValidationError::Success;
|
||||
}
|
||||
bool isPal(const char* path) {
|
||||
NodHandleWrapper disc;
|
||||
|
||||
const auto sdlStream = SDL_IOFromFile(path, "rb");
|
||||
if (sdlStream == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const NodDiscStream nod_stream{
|
||||
.user_data = sdlStream,
|
||||
.read_at = StreamReadAt,
|
||||
.stream_len = StreamLength,
|
||||
.close = StreamClose,
|
||||
};
|
||||
|
||||
if (nod_disc_open_stream(&nod_stream, nullptr, &disc.handle) != NOD_RESULT_OK || disc.handle == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NodDiscHeader header{};
|
||||
if (nod_disc_header(disc.handle, &header) != NOD_RESULT_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return matches(header.game_id, PAL_GAME_IDS);
|
||||
}
|
||||
} // namespace dusk::iso
|
||||
@@ -13,6 +13,7 @@ namespace dusk::iso {
|
||||
};
|
||||
|
||||
ValidationError validate(const char* path);
|
||||
bool isPal(const char* path);
|
||||
}
|
||||
|
||||
#endif // DUSK_ISO_VALIDATE_HPP
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
#if _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
using socket_t = SOCKET;
|
||||
static void closeSocket(socket_t s) { closesocket(s); }
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
using socket_t = int;
|
||||
static void closeSocket(socket_t s) { close(s); }
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET -1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include "dusk/livesplit.h"
|
||||
#include "f_op/f_op_overlap_mng.h"
|
||||
|
||||
namespace dusk::speedrun {
|
||||
|
||||
static bool running = false;
|
||||
static uint64_t frameCount = 0;
|
||||
static socket_t sock = INVALID_SOCKET;
|
||||
static bool wasLoading = false;
|
||||
static bool connected = false;
|
||||
static bool connectPending = false;
|
||||
static bool disconnectPending = false;
|
||||
|
||||
static void sendCmd(const char* cmd) {
|
||||
if (sock == INVALID_SOCKET) {
|
||||
return;
|
||||
}
|
||||
|
||||
char msg[64];
|
||||
int len = snprintf(msg, sizeof(msg), "%s\r\n", cmd);
|
||||
|
||||
if (send(sock, msg, len, 0) >= 0) {
|
||||
if (!connected) {
|
||||
connected = connectPending = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
int err = WSAGetLastError();
|
||||
if (err == WSAEWOULDBLOCK || err == WSAENOTCONN) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (connected) disconnectPending = true;
|
||||
closeSocket(sock);
|
||||
sock = INVALID_SOCKET;
|
||||
connected = connectPending = false;
|
||||
}
|
||||
|
||||
uint64_t getFrameCount() {
|
||||
return frameCount;
|
||||
}
|
||||
|
||||
void onGameFrame() {
|
||||
if (!running) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool loading = fopOvlpM_IsDoingReq() != 0;
|
||||
|
||||
if (loading != wasLoading) {
|
||||
sendCmd(loading ? "pausegametime" : "unpausegametime");
|
||||
wasLoading = loading;
|
||||
}
|
||||
|
||||
if (!loading) {
|
||||
++frameCount;
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
if (running) {
|
||||
return;
|
||||
}
|
||||
|
||||
running = true;
|
||||
frameCount = 0;
|
||||
wasLoading = false;
|
||||
sendCmd("initgametime");
|
||||
sendCmd("reset");
|
||||
sendCmd("starttimer");
|
||||
}
|
||||
|
||||
void reset() {
|
||||
running = false;
|
||||
frameCount = 0;
|
||||
wasLoading = false;
|
||||
sendCmd("reset");
|
||||
}
|
||||
|
||||
void connectLiveSplit(const char* host, int port) {
|
||||
#if _WIN32
|
||||
WSADATA wd{}; WSAStartup(MAKEWORD(2, 2), &wd);
|
||||
#endif
|
||||
|
||||
if (sock != INVALID_SOCKET) {
|
||||
closeSocket(sock); sock = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (sock == INVALID_SOCKET) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
u_long nb = 1;
|
||||
ioctlsocket(sock, FIONBIO, &nb);
|
||||
#else
|
||||
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
sockaddr_in addr{}; addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons((uint16_t)port);
|
||||
inet_pton(AF_INET, host, &addr.sin_addr);
|
||||
connect(sock, (sockaddr*)&addr, sizeof(addr));
|
||||
sendCmd("initgametime");
|
||||
}
|
||||
|
||||
void disconnectLiveSplit() {
|
||||
if (sock != INVALID_SOCKET) {
|
||||
closeSocket(sock);
|
||||
sock = INVALID_SOCKET;
|
||||
connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool consumeConnectedEvent() { bool v = connectPending; connectPending = false; return v; }
|
||||
bool consumeDisconnectedEvent() { bool v = disconnectPending; disconnectPending = false; return v; }
|
||||
|
||||
void updateLiveSplit() {
|
||||
if (sock == INVALID_SOCKET) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
sendCmd("initgametime");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!running) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t totalMs = frameCount * 1000 / 30;
|
||||
const uint64_t totalSec = totalMs / 1000;
|
||||
char cmd[32];
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "setgametime %u:%02u:%02u.%03u",
|
||||
(uint32_t)(totalSec / 3600),
|
||||
(uint32_t)((totalSec / 60) % 60),
|
||||
(uint32_t)(totalSec % 60),
|
||||
(uint32_t)(totalMs % 1000)
|
||||
);
|
||||
|
||||
sendCmd(cmd);
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
disconnectLiveSplit();
|
||||
#if _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
+21
-2
@@ -20,6 +20,8 @@ UserSettings g_userSettings = {
|
||||
},
|
||||
|
||||
.game = {
|
||||
.language { "game.language", GameLanguage::English },
|
||||
|
||||
// Quality of Life
|
||||
.enableQuickTransform {"game.enableQuickTransform", false},
|
||||
.hideTvSettingsScreen {"game.hideTvSettingsScreen", false},
|
||||
@@ -40,10 +42,10 @@ UserSettings g_userSettings = {
|
||||
|
||||
// Preferences
|
||||
.enableMirrorMode {"game.enableMirrorMode", false},
|
||||
.invertCameraXAxis {"game.invertCameraXAxis", false},
|
||||
.disableMainHUD {"game.disableMainHUD", false},
|
||||
.pauseOnFocusLost {"game.pauseOnFocusLost", false},
|
||||
.enableLinkDollRotation = {"game.enableLinkDollRotation", false },
|
||||
.enableAchievementNotifications {"game.enableAchievementNotifications", false},
|
||||
|
||||
// Graphics
|
||||
.bloomMode {"game.bloomMode", BloomMode::Classic},
|
||||
@@ -53,6 +55,7 @@ UserSettings g_userSettings = {
|
||||
.internalResolutionScale {"game.internalResolutionScale", 0},
|
||||
.shadowResolutionMultiplier {"game.shadowResolutionMultiplier", 1},
|
||||
.enableDepthOfField {"game.enableDepthOfField", true},
|
||||
.enableMapBackground {"game.enableMapBackground", true},
|
||||
|
||||
// Audio
|
||||
.noLowHpSound {"game.noLowHpSound", false},
|
||||
@@ -68,6 +71,10 @@ UserSettings g_userSettings = {
|
||||
.gyroDeadband {"game.gyroDeadband", 0.04f},
|
||||
.gyroInvertPitch {"game.gyroInvertPitch", false},
|
||||
.gyroInvertYaw {"game.gyroInvertYaw", false},
|
||||
.freeCamera {"game.freeCamera", false},
|
||||
.invertCameraXAxis {"game.invertCameraXAxis", false},
|
||||
.invertCameraYAxis {"game.invertCameraYAxis", false},
|
||||
.freeCameraSensitivity {"game.freeCameraSensitivity", 1.0f},
|
||||
|
||||
// Cheats
|
||||
.infiniteHearts {"game.infiniteHearts", false},
|
||||
@@ -89,7 +96,11 @@ UserSettings g_userSettings = {
|
||||
.restoreWiiGlitches {"game.restoreWiiGlitches", false},
|
||||
|
||||
// Controls
|
||||
.enableTurboKeybind {"game.enableTurboKeybind", false}
|
||||
.enableTurboKeybind {"game.enableTurboKeybind", false},
|
||||
|
||||
// Tools
|
||||
.speedrunMode {"game.speedrunMode", false},
|
||||
.liveSplitEnabled {"game.liveSplitEnabled", false}
|
||||
},
|
||||
|
||||
.backend = {
|
||||
@@ -123,6 +134,7 @@ void registerSettings() {
|
||||
Register(g_userSettings.audio.enableReverb);
|
||||
|
||||
// Game
|
||||
Register(g_userSettings.game.language);
|
||||
Register(g_userSettings.game.enableQuickTransform);
|
||||
Register(g_userSettings.game.hideTvSettingsScreen);
|
||||
Register(g_userSettings.game.skipWarningScreen);
|
||||
@@ -140,6 +152,8 @@ void registerSettings() {
|
||||
Register(g_userSettings.game.sunsSong);
|
||||
Register(g_userSettings.game.enableMirrorMode);
|
||||
Register(g_userSettings.game.invertCameraXAxis);
|
||||
Register(g_userSettings.game.invertCameraYAxis);
|
||||
Register(g_userSettings.game.freeCameraSensitivity);
|
||||
Register(g_userSettings.game.disableMainHUD);
|
||||
Register(g_userSettings.game.pauseOnFocusLost);
|
||||
Register(g_userSettings.game.bloomMode);
|
||||
@@ -148,15 +162,19 @@ void registerSettings() {
|
||||
Register(g_userSettings.game.internalResolutionScale);
|
||||
Register(g_userSettings.game.shadowResolutionMultiplier);
|
||||
Register(g_userSettings.game.enableDepthOfField);
|
||||
Register(g_userSettings.game.enableMapBackground);
|
||||
Register(g_userSettings.game.enableFastIronBoots);
|
||||
Register(g_userSettings.game.canTransformAnywhere);
|
||||
Register(g_userSettings.game.freeMagicArmor);
|
||||
Register(g_userSettings.game.restoreWiiGlitches);
|
||||
Register(g_userSettings.game.enableLinkDollRotation);
|
||||
Register(g_userSettings.game.enableAchievementNotifications);
|
||||
Register(g_userSettings.game.noMissClimbing);
|
||||
Register(g_userSettings.game.noLowHpSound);
|
||||
Register(g_userSettings.game.midnasLamentNonStop);
|
||||
Register(g_userSettings.game.enableTurboKeybind);
|
||||
Register(g_userSettings.game.speedrunMode);
|
||||
Register(g_userSettings.game.liveSplitEnabled);
|
||||
Register(g_userSettings.game.fastSpinner);
|
||||
Register(g_userSettings.game.infiniteHearts);
|
||||
Register(g_userSettings.game.infiniteArrows);
|
||||
@@ -178,6 +196,7 @@ void registerSettings() {
|
||||
Register(g_userSettings.game.gyroSmoothing);
|
||||
Register(g_userSettings.game.gyroInvertPitch);
|
||||
Register(g_userSettings.game.gyroInvertYaw);
|
||||
Register(g_userSettings.game.freeCamera);
|
||||
|
||||
Register(g_userSettings.backend.isoPath);
|
||||
Register(g_userSettings.backend.graphicsBackend);
|
||||
|
||||
@@ -1020,10 +1020,6 @@ void GXInitTexCacheRegion(GXTexRegion* region, GXBool is_32b_mipmap, u32 tmem_ev
|
||||
// XXX, this should be some struct?
|
||||
// GXRenderModeObj GXNtsc480IntDf;
|
||||
//GXRenderModeObj GXNtsc480Int;
|
||||
void GXPeekZ(u16 x, u16 y, u32* z) {
|
||||
STUB_LOG();
|
||||
*z = 0;
|
||||
}
|
||||
void GXReadXfRasMetric(u32* xf_wait_in, u32* xf_wait_out, u32* ras_busy, u32* clocks) {
|
||||
STUB_LOG();
|
||||
*xf_wait_in = 0;
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "dusk/version.hpp"
|
||||
|
||||
#include "dusk/logging.h"
|
||||
|
||||
namespace dusk::version {
|
||||
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
static bool versionInitialized;
|
||||
static GameVersion gameVersion;
|
||||
static DVDDiskID diskId;
|
||||
|
||||
void init() {
|
||||
versionInitialized = true;
|
||||
|
||||
if (!DVDLowReadDiskID(&diskId, nullptr)) {
|
||||
DuskLog.fatal("DVDLowReadDiskID failed to return instantly.");
|
||||
}
|
||||
|
||||
std::string_view company(diskId.company, sizeof(diskId.company));
|
||||
std::string_view game(diskId.gameName, sizeof(diskId.gameName));
|
||||
|
||||
if (company != "01"sv) {
|
||||
DuskLog.fatal("Wrong company ID in disc: {}", company);
|
||||
}
|
||||
|
||||
if (game == "GZ2E"sv) {
|
||||
gameVersion = GameVersion::GcnUsa;
|
||||
} else if (game == "GZ2P") {
|
||||
gameVersion = GameVersion::GcnPal;
|
||||
} else {
|
||||
// TODO: Handle remaining valid versions.
|
||||
DuskLog.fatal("Unknown/unsupported game version in disc: {}", game);
|
||||
}
|
||||
|
||||
DuskLog.info("Loaded game disc is {}{}", game, company);
|
||||
}
|
||||
|
||||
bool isGcn() {
|
||||
return getGameVersion() == GameVersion::GcnUsa
|
||||
|| getGameVersion() == GameVersion::GcnPal
|
||||
|| getGameVersion() == GameVersion::GcnJpn;
|
||||
}
|
||||
|
||||
bool isWii() {
|
||||
return getGameVersion() == GameVersion::WiiUsaRev0
|
||||
|| getGameVersion() == GameVersion::WiiUsa
|
||||
|| getGameVersion() == GameVersion::WiiPal
|
||||
|| getGameVersion() == GameVersion::WiiJpn
|
||||
|| getGameVersion() == GameVersion::WiiKor;
|
||||
}
|
||||
|
||||
bool isPalOrAtLeastWiiR2() {
|
||||
return getGameVersion() == GameVersion::GcnPal || getGameVersion() >= GameVersion::WiiUsa;
|
||||
}
|
||||
|
||||
bool isRegionJpn() {
|
||||
return getGameVersion() == GameVersion::WiiJpn || getGameVersion() == GameVersion::GcnJpn;
|
||||
}
|
||||
|
||||
bool isRegionPal() {
|
||||
return getGameVersion() == GameVersion::WiiPal || getGameVersion() == GameVersion::GcnPal;
|
||||
}
|
||||
|
||||
bool isRegionUsa() {
|
||||
return getGameVersion() == GameVersion::WiiUsa || getGameVersion() == GameVersion::WiiUsaRev0
|
||||
|| getGameVersion() == GameVersion::GcnUsa;
|
||||
}
|
||||
|
||||
GameVersion getGameVersion() {
|
||||
if (!versionInitialized) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return gameVersion;
|
||||
}
|
||||
|
||||
const DVDDiskID& getDiskID() {
|
||||
return diskId;
|
||||
}
|
||||
|
||||
} // namespace dusk::version
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "d/d_model.h"
|
||||
#include "d/d_tresure.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
#include "dusk/livesplit.h"
|
||||
#include "dusk/logging.h"
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
#include "f_op/f_op_draw_tag.h"
|
||||
@@ -815,6 +816,9 @@ void fapGm_Execute() {
|
||||
fpcM_ManagementFunc(NULL, fapGm_After);
|
||||
#endif
|
||||
cCt_Counter(0);
|
||||
#ifdef TARGET_PC
|
||||
dusk::speedrun::onGameFrame();
|
||||
#endif
|
||||
}
|
||||
|
||||
fapGm_HIO_c g_HIO;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "f_op/f_op_overlap_req.h"
|
||||
#include "f_pc/f_pc_manager.h"
|
||||
|
||||
#include "dusk/imgui/ImGuiMenuGame.hpp"
|
||||
|
||||
void fopOvlpReq_SetPeektime(overlap_request_class*, u16);
|
||||
|
||||
static int fopOvlpReq_phase_Done(overlap_request_class* i_overlapReq) {
|
||||
@@ -16,6 +18,16 @@ static int fopOvlpReq_phase_Done(overlap_request_class* i_overlapReq) {
|
||||
i_overlapReq->peektime = 0;
|
||||
i_overlapReq->field_0x8 = 0;
|
||||
i_overlapReq->field_0xc = 0;
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.speedrunMode) {
|
||||
if (dusk::m_speedrunInfo.m_isRunStarted) {
|
||||
dusk::m_speedrunInfo.m_isPauseIGT = false;
|
||||
dusk::m_speedrunInfo.m_totalLoadTime += OSGetTime() - dusk::m_speedrunInfo.m_loadStartTimestamp;
|
||||
dusk::m_speedrunInfo.m_loadStartTimestamp = OSGetTime();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return cPhs_NEXT_e;
|
||||
}
|
||||
|
||||
@@ -81,6 +93,14 @@ static int fopOvlpReq_phase_Create(overlap_request_class* i_overlapReq) {
|
||||
fpcLy_SetCurrentLayer(i_overlapReq->layer);
|
||||
i_overlapReq->request_id =
|
||||
fpcM_Create(i_overlapReq->procname, NULL, NULL);
|
||||
|
||||
#if TARGET_PC
|
||||
if (dusk::m_speedrunInfo.m_isRunStarted) {
|
||||
dusk::m_speedrunInfo.m_isPauseIGT = true;
|
||||
dusk::m_speedrunInfo.m_loadStartTimestamp = OSGetTime();
|
||||
}
|
||||
#endif
|
||||
|
||||
return cPhs_NEXT_e;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
*/
|
||||
|
||||
#include "f_op/f_op_scene_req.h"
|
||||
#include <cstdio>
|
||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||
#include "dusk/logging.h"
|
||||
#include "f_op/f_op_overlap_mng.h"
|
||||
#include "f_op/f_op_scene.h"
|
||||
#include "f_op/f_op_scene_pause.h"
|
||||
#include "f_pc/f_pc_executor.h"
|
||||
#include "f_pc/f_pc_manager.h"
|
||||
#include <cstdio>
|
||||
#include "dusk/logging.h"
|
||||
|
||||
static cPhs_Step fopScnRq_phase_ClearOverlap(scene_request_class* i_sceneReq) {
|
||||
return fopOvlpM_ClearOfReq() == 1 ? cPhs_NEXT_e : cPhs_INIT_e;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "os_report.h"
|
||||
#include "dusk/os.h"
|
||||
#include "dusk/main.h"
|
||||
#include "dusk/version.hpp"
|
||||
|
||||
#if PLATFORM_WII || PLATFORM_SHIELD
|
||||
#include <revolution/nand.h>
|
||||
@@ -79,7 +80,11 @@ void mDoMemCd_Ctrl_c::ThdInit() {
|
||||
#if !PLATFORM_SHIELD
|
||||
CARDSetLoadType((CARDFileType)dusk::getSettings().backend.cardFileType.getValue());
|
||||
|
||||
CARDInit(DUSK_GAME_NAME, DUSK_GAME_VERSION);
|
||||
char version[5] = {};
|
||||
char maker[3] = {};
|
||||
std::memcpy(version, dusk::version::getDiskID().gameName, 4);
|
||||
std::memcpy(maker, dusk::version::getDiskID().company, 2);
|
||||
CARDInit(version, maker);
|
||||
#endif
|
||||
|
||||
mCopyToPos = 0;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "dusk/version.hpp"
|
||||
|
||||
#if VERSION == VERSION_GCN_JPN
|
||||
#define HEADER_TITLE "ゼルダの伝説 トワイライトプリンセス"
|
||||
#define HEADER_COMMENT "%d月%d日のセーブデータです"
|
||||
@@ -313,12 +315,44 @@ s32 mDoMemCdRWm_StoreBannerNAND(NANDFileInfo* file) {
|
||||
#endif
|
||||
|
||||
static void mDoMemCdRWm_BuildHeader(mDoMemCdRWm_HeaderData* header) {
|
||||
#if !TARGET_PC
|
||||
snprintf(header->mTitle, sizeof(header->mTitle), HEADER_TITLE);
|
||||
#endif
|
||||
|
||||
OSCalendarTime time;
|
||||
OSTicksToCalendarTime(OSGetTime(), &time);
|
||||
|
||||
#if VERSION == VERSION_GCN_PAL
|
||||
#if TARGET_PC
|
||||
if (dusk::version::isRegionPal()) {
|
||||
snprintf(header->mTitle, sizeof(header->mTitle), HEADER_TITLE);
|
||||
|
||||
switch (dComIfGs_getPalLanguage()) {
|
||||
case dSv_player_config_c::LANGUAGE_ENGLISH:
|
||||
snprintf(header->mComment, sizeof(header->mComment), "%d/%d Save Data", time.mon + 1, time.mday);
|
||||
break;
|
||||
case dSv_player_config_c::LANGUAGE_GERMAN:
|
||||
snprintf(header->mComment, sizeof(header->mComment), "%d/%d Spielstand", time.mday, time.mon + 1);
|
||||
break;
|
||||
case dSv_player_config_c::LANGUAGE_FRENCH:
|
||||
snprintf(header->mComment, sizeof(header->mComment), "Donn%ces de jeu %d/%d", 0xE9, time.mday, time.mon + 1);
|
||||
break;
|
||||
case dSv_player_config_c::LANGUAGE_SPANISH:
|
||||
snprintf(header->mComment, sizeof(header->mComment), "Datos guardados el %d/%d", time.mday, time.mon + 1);
|
||||
break;
|
||||
case dSv_player_config_c::LANGUAGE_ITALIAN:
|
||||
snprintf(header->mComment, sizeof(header->mComment), "Dati salvati: %d/%d", time.mday, time.mon + 1);
|
||||
break;
|
||||
}
|
||||
} else if (dusk::version::isRegionUsa()) {
|
||||
snprintf(header->mTitle, sizeof(header->mTitle), HEADER_TITLE);
|
||||
|
||||
snprintf(header->mComment, sizeof(header->mComment), HEADER_COMMENT, time.mon + 1, time.mday);
|
||||
} else {
|
||||
// TODO JPN SHIFT-JIS
|
||||
// snprintf(header->mTitle, sizeof(header->mTitle), "ゼルダの伝説 トワイライトプリンセス");
|
||||
// snprintf(header->mComment, sizeof(header->mComment), "%d月%d日のセーブデータです", time.mon + 1, time.mday);
|
||||
}
|
||||
#elif VERSION == VERSION_GCN_PAL
|
||||
switch (dComIfGs_getPalLanguage()) {
|
||||
case dSv_player_config_c::LANGUAGE_ENGLISH:
|
||||
snprintf(header->mComment, sizeof(header->mComment), "%d/%d Save Data", time.mon + 1, time.mday);
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "dusk/config.hpp"
|
||||
#include "dusk/imgui/ImGuiConsole.hpp"
|
||||
#include "dusk/settings.h"
|
||||
#include "dusk/version.hpp"
|
||||
#include "dusk/discord_presence.hpp"
|
||||
#include "tracy/Tracy.hpp"
|
||||
#include "f_pc/f_pc_draw.h"
|
||||
@@ -465,6 +466,23 @@ static constexpr PADDefaultMapping defaultPadMapping = {
|
||||
|
||||
static bool mainCalled = false;
|
||||
|
||||
static u8 selectedLanguage;
|
||||
|
||||
u8 OSGetLanguage() {
|
||||
return selectedLanguage;
|
||||
}
|
||||
|
||||
static void LanguageInit() {
|
||||
// Keep language at 0 (English) if not on a PAL disk.
|
||||
// Doubt this matters, but avoid funky shit.
|
||||
if (!dusk::version::isRegionPal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache this to avoid funky shenanigans.
|
||||
selectedLanguage = static_cast<u8>(dusk::getSettings().game.language.getValue());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// PC ENTRY POINT
|
||||
// =========================================================================
|
||||
@@ -597,6 +615,9 @@ int game_main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
dusk::version::init();
|
||||
LanguageInit();
|
||||
|
||||
OSInit();
|
||||
|
||||
mDoMain::sPowerOnTime = OSGetTime();
|
||||
|
||||
Reference in New Issue
Block a user