Merge branch 'main' of https://github.com/TwilitRealm/dusk into randomizer

This commit is contained in:
gymnast86
2026-06-05 21:11:36 -07:00
27 changed files with 826 additions and 45 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get -y install ninja-build clang lld openssl libcurl4-openssl-dev \
sudo apt-get -y install ninja-build clang lld mold openssl libcurl4-openssl-dev \
zlib1g-dev libglu1-mesa-dev libdbus-1-dev libvulkan-dev libxi-dev libxrandr-dev libasound2-dev \
libpulse-dev libudev-dev libpng-dev libncurses5-dev libx11-xcb-dev libfreetype-dev \
libxinerama-dev libxcursor-dev python3-markupsafe libgtk-3-dev libssl-dev \
+23 -12
View File
@@ -19,7 +19,19 @@
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded"
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL"
}
},
{
"name": "release",
"hidden": true,
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDLL",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": {
"type": "BOOL",
"value": true
}
}
},
{
@@ -292,24 +304,21 @@
"type": "BOOL",
"value": false
},
"ENABLE_ARC": {
"type": "BOOL",
"value": false
},
"Rust_CARGO_TARGET": "aarch64-apple-tvos",
"Rust_TOOLCHAIN": "nightly",
"BUILD_SHARED_LIBS": {
"type": "BOOL",
"value": false
},
"CMAKE_DISABLE_FIND_PACKAGE_BZip2": {
"CMAKE_DISABLE_FIND_PACKAGE_PkgConfig": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_LibLZMA": {
"type": "BOOL",
"value": true
},
"CMAKE_DISABLE_FIND_PACKAGE_zstd": {
"type": "BOOL",
"value": true
}
"CMAKE_IGNORE_PREFIX_PATH": "/opt/homebrew"
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": {
@@ -370,7 +379,8 @@
"hidden": true,
"inherits": [
"android-base",
"ci"
"ci",
"release"
],
"cacheVariables": {
"DUSK_ENABLE_SENTRY_NATIVE": {
@@ -398,7 +408,8 @@
"ci"
],
"cacheVariables": {
"AURORA_SDL3_PROVIDER": "vendor"
"AURORA_SDL3_PROVIDER": "vendor",
"CMAKE_LINKER_TYPE": "MOLD"
}
},
{
+1 -1
+4
View File
@@ -88,6 +88,10 @@ public:
/* 0x02C */ cXyz field_0x2c;
/* 0x038 */ cXyz field_0x38[60];
/* 0x308 */ cXyz field_0x308[60];
#if TARGET_PC
TGXTexObj mBlurTexObj;
ResTIMG* mpCachedBlurTex = nullptr;
#endif
}; // Size = 0x5D8
class dAlink_bottleWaterPcallBack_c : public JPAParticleCallBack {
+4
View File
@@ -50,6 +50,10 @@ public:
/* 0x14 */ Mtx mProjMtx;
/* 0x44 */ ResTIMG* mpImg;
/* 0x48 */ u8* mpData;
#if TARGET_PC
TGXTexObj mTexObj;
ResTIMG* mpCachedImg = nullptr;
#endif
};
class daPy_boomerangMove_c {
+17
View File
@@ -43,8 +43,25 @@ public:
static_assert(sizeof(GXTexObjRAII) == sizeof(GXTexObj),
"GXTexObjRAII should have the same size as GXTexObj");
typedef GXTexObjRAII TGXTexObj;
class GXTlutObjRAII : public GXTlutObj {
public:
GXTlutObjRAII() : GXTlutObj() {}
~GXTlutObjRAII() { GXDestroyTlutObj(this); }
void reset() { GXDestroyTlutObj(this); }
GXTlutObjRAII(const GXTlutObjRAII&) = delete;
GXTlutObjRAII& operator=(const GXTlutObjRAII&) = delete;
GXTlutObjRAII(GXTlutObjRAII&&) = delete;
GXTlutObjRAII& operator=(GXTlutObjRAII&&) = delete;
};
static_assert(sizeof(GXTlutObjRAII) == sizeof(GXTlutObj),
"GXTlutObjRAII should have the same size as GXTlutObj");
typedef GXTlutObjRAII TGXTlutObj;
#else
typedef GXTexObj TGXTexObj;
typedef GXTlutObj TGXTlutObj;
#endif
struct GXScopedDebugGroup {
+1
View File
@@ -163,6 +163,7 @@ struct UserSettings {
// Preferences
ConfigVar<bool> enableMirrorMode;
ConfigVar<bool> minimalHUD;
ConfigVar<float> hudScale;
ConfigVar<bool> pauseOnFocusLost;
ConfigVar<bool> enableLinkDollRotation;
ConfigVar<bool> enableAchievementToasts;
+1 -1
View File
@@ -44,7 +44,7 @@ struct mDoLib_clipper {
void mDoLib_project(Vec* src, Vec* dst);
u32 mDoLib_setResTimgObj(ResTIMG const* res, TGXTexObj* o_texObj, u32 tlut_name,
GXTlutObj* o_tlutObj);
TGXTlutObj* o_tlutObj);
void mDoLib_pos2camera(Vec* src, Vec* dst);
#if PLATFORM_WII
@@ -1,6 +1,7 @@
#ifndef J3DSHAPEDRAW_H
#define J3DSHAPEDRAW_H
#include <gx.h>
#include <types.h>
/**
@@ -12,6 +13,9 @@ public:
u32 countVertex(u32);
void addTexMtxIndexInDL(u32, u32, u32);
J3DShapeDraw(u8 const*, u32);
#if TARGET_PC
J3DShapeDraw(u8 const*, u32, const GXVtxDescList*);
#endif
void draw() const;
virtual ~J3DShapeDraw();
+339 -4
View File
@@ -1,15 +1,310 @@
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include "JSystem/JSystem.h" // IWYU pragma: keep
#include <cstring>
#include <gx.h>
#include <stdint.h>
#include "JSystem/J3DGraphBase/J3DShapeDraw.h"
#include "JSystem/JKernel/JKRHeap.h"
#include <cstring>
#include <stdint.h>
#include <gx.h>
#if TARGET_PC
#include <algorithm>
#include <tracy/Tracy.hpp>
#include <vector>
#include "dusk/logging.h"
namespace {
u16 read_be16(const u8* data) {
return (u16(data[0]) << 8) | data[1];
}
void append_be16(std::vector<u8>& out, u16 value) {
out.push_back(value >> 8);
out.push_back(value & 0xFF);
}
void append_bytes(std::vector<u8>& out, const u8* data, u32 size) {
out.insert(out.end(), data, data + size);
}
bool is_matrix_idx_attr(GXAttr attr) {
return attr >= GX_VA_PNMTXIDX && attr <= GX_VA_TEX7MTXIDX;
}
bool is_draw_opcode(u8 opcode) {
return opcode == GX_QUADS || opcode == GX_TRIANGLES || opcode == GX_TRIANGLESTRIP ||
opcode == GX_TRIANGLEFAN || opcode == GX_LINES || opcode == GX_LINESTRIP ||
opcode == GX_POINTS;
}
bool is_mergeable_draw_opcode(u8 opcode) {
return opcode == GX_QUADS || opcode == GX_TRIANGLES || opcode == GX_TRIANGLESTRIP ||
opcode == GX_TRIANGLEFAN;
}
bool calc_vtx_stride(const GXVtxDescList* vtxDesc, u32& stride) {
stride = 0;
for (; vtxDesc->attr != GX_VA_NULL; vtxDesc++) {
switch (vtxDesc->type) {
case GX_NONE:
break;
case GX_DIRECT:
if (!is_matrix_idx_attr(vtxDesc->attr)) {
return false;
}
stride += 1;
break;
case GX_INDEX8:
stride += 1;
break;
case GX_INDEX16:
stride += 2;
break;
default:
return false;
}
}
return stride != 0;
}
bool get_command_size(const u8* dlStart, u32 dlSize, u32 offset, u32 stride, u32& cmdSize) {
if (offset >= dlSize) {
return false;
}
const u8 cmd = dlStart[offset];
const u8 opcode = cmd & GX_OPCODE_MASK;
switch (opcode) {
case GX_NOP:
case GX_CMD_INVL_VC:
cmdSize = 1;
return true;
case (GX_LOAD_BP_REG & GX_OPCODE_MASK):
cmdSize = 5;
return offset + cmdSize <= dlSize;
case GX_LOAD_CP_REG:
cmdSize = 6;
return offset + cmdSize <= dlSize;
case GX_LOAD_XF_REG: {
if (offset + 5 > dlSize) {
return false;
}
const u16 count = read_be16(dlStart + offset + 1) + 1;
cmdSize = 5 + count * 4;
return offset + cmdSize <= dlSize;
}
case GX_LOAD_INDX_A:
case GX_LOAD_INDX_B:
case GX_LOAD_INDX_C:
case GX_LOAD_INDX_D:
cmdSize = 5;
return offset + cmdSize <= dlSize;
case GX_CMD_CALL_DL:
cmdSize = 9;
return offset + cmdSize <= dlSize;
default:
if (is_draw_opcode(opcode)) {
if (offset + 3 > dlSize) {
return false;
}
const u16 vtxCount = read_be16(dlStart + offset + 1);
cmdSize = 3 + vtxCount * stride;
return offset + cmdSize <= dlSize;
}
return false;
}
}
struct MergeRun {
u8 cmd = 0;
u16 vtxCount = 0;
std::vector<u8> vertices;
};
void flush_merge_run(std::vector<u8>& out, MergeRun& run) {
if (run.vtxCount == 0) {
return;
}
out.push_back(run.cmd);
append_be16(out, run.vtxCount);
append_bytes(out, run.vertices.data(), run.vertices.size());
run.vertices.clear();
run.vtxCount = 0;
}
void append_vertex(std::vector<u8>& out, const u8* vertices, u32 stride, u16 idx) {
append_bytes(out, vertices + idx * stride, stride);
}
bool triangulate_draw(
std::vector<u8>& out, u8 opcode, const u8* vertices, u32 stride, u16 vtxCount) {
switch (opcode) {
case GX_TRIANGLES:
append_bytes(out, vertices, vtxCount * stride);
return true;
case GX_TRIANGLEFAN:
if (vtxCount < 3) {
return false;
}
for (u16 v = 2; v < vtxCount; v++) {
append_vertex(out, vertices, stride, 0);
append_vertex(out, vertices, stride, v - 1);
append_vertex(out, vertices, stride, v);
}
return true;
case GX_TRIANGLESTRIP:
if (vtxCount < 3) {
return false;
}
for (u16 v = 2; v < vtxCount; v++) {
if ((v & 1) == 0) {
append_vertex(out, vertices, stride, v - 2);
append_vertex(out, vertices, stride, v - 1);
} else {
append_vertex(out, vertices, stride, v - 1);
append_vertex(out, vertices, stride, v - 2);
}
append_vertex(out, vertices, stride, v);
}
return true;
case GX_QUADS:
if ((vtxCount & 3) != 0) {
return false;
}
for (u16 v = 0; v < vtxCount; v += 4) {
append_vertex(out, vertices, stride, v);
append_vertex(out, vertices, stride, v + 1);
append_vertex(out, vertices, stride, v + 2);
append_vertex(out, vertices, stride, v + 2);
append_vertex(out, vertices, stride, v + 3);
append_vertex(out, vertices, stride, v);
}
return true;
default:
return false;
}
}
void append_triangles_to_run(
std::vector<u8>& out, MergeRun& run, u8 cmd, const std::vector<u8>& vertices, u32 stride) {
u32 offset = 0;
u32 remaining = vertices.size() / stride;
while (remaining != 0) {
if (run.vtxCount != 0 && run.cmd != cmd) {
flush_merge_run(out, run);
}
if (run.vtxCount == 0) {
run.cmd = cmd;
}
u32 available = 0xFFFF - run.vtxCount;
if (available == 0) {
flush_merge_run(out, run);
continue;
}
u32 toCopy = std::min(remaining, available);
append_bytes(run.vertices, vertices.data() + offset * stride, toCopy * stride);
run.vtxCount += toCopy;
offset += toCopy;
remaining -= toCopy;
if (run.vtxCount == 0xFFFF) {
flush_merge_run(out, run);
}
}
}
bool optimize_display_list(const u8* dlStart, u32 dlSize, u32 stride, std::vector<u8>& out) {
MergeRun run;
out.reserve(dlSize);
for (u32 offset = 0; offset < dlSize;) {
u32 cmdSize = 0;
if (!get_command_size(dlStart, dlSize, offset, stride, cmdSize)) {
return false;
}
const u8 cmd = dlStart[offset];
const u8 opcode = cmd & GX_OPCODE_MASK;
if (opcode == GX_NOP) {
offset += cmdSize;
continue;
}
if (!is_draw_opcode(opcode)) {
flush_merge_run(out, run);
append_bytes(out, dlStart + offset, cmdSize);
offset += cmdSize;
continue;
}
if (!is_mergeable_draw_opcode(opcode)) {
flush_merge_run(out, run);
append_bytes(out, dlStart + offset, cmdSize);
offset += cmdSize;
continue;
}
const u16 vtxCount = read_be16(dlStart + offset + 1);
const u8* vertices = dlStart + offset + 3;
std::vector<u8> triangles;
if (!triangulate_draw(triangles, opcode, vertices, stride, vtxCount)) {
flush_merge_run(out, run);
append_bytes(out, dlStart + offset, cmdSize);
offset += cmdSize;
continue;
}
append_triangles_to_run(out, run, (GX_TRIANGLES | (cmd & GX_VAT_MASK)), triangles, stride);
offset += cmdSize;
}
flush_merge_run(out, run);
return true;
}
void set_display_list_copy(void*& displayList, u32& displayListSize, const u8* data, u32 size) {
const u32 alignedSize = ALIGN_NEXT(size, 0x20);
u8* newDL = JKR_NEW_ARRAY_ARGS(u8, alignedSize, 0x20);
if (size != 0) {
std::memcpy(newDL, data, size);
}
for (u32 i = size; i < alignedSize; i++) {
newDL[i] = 0;
}
displayList = newDL;
displayListSize = alignedSize;
DCStoreRange(newDL, displayListSize);
}
} // namespace
#endif
u32 J3DShapeDraw::countVertex(u32 stride) {
u32 count = 0;
u8* dlStart = (u8*)getDisplayList();
#if TARGET_PC
for (u32 offset = 0; offset < getDisplayListSize();) {
u8 cmd = dlStart[offset];
u8 opcode = cmd & GX_OPCODE_MASK;
u32 cmdSize = 0;
if (!get_command_size(dlStart, getDisplayListSize(), offset, stride, cmdSize)) {
break;
}
if (!is_draw_opcode(opcode)) {
offset += cmdSize;
continue;
}
int vtxNum = be16(*reinterpret_cast<u16*>(dlStart + offset + 1));
count += vtxNum;
offset += 3 + stride * vtxNum;
}
#else
for (u8* dl = dlStart; (dl - dlStart) < getDisplayListSize();) {
u8 cmd = *(u8*)dl;
dl++;
@@ -20,6 +315,7 @@ u32 J3DShapeDraw::countVertex(u32 stride) {
count += vtxNum;
dl = (u8*)dl + stride * vtxNum;
}
#endif
return count;
}
@@ -34,13 +330,32 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
u8* newDL = newDLStart;
for (; (oldDL - oldDLStart) < mDisplayListSize;) {
#if TARGET_PC
u32 oldOffset = oldDL - oldDLStart;
u32 cmdSize = 0;
if (!get_command_size(oldDLStart, mDisplayListSize, oldOffset, stride, cmdSize)) {
memcpy(newDL, oldDL, mDisplayListSize - oldOffset);
newDL += mDisplayListSize - oldOffset;
break;
}
#endif
// Copy command
u8 cmd = *(u8*)oldDL;
oldDL++;
*newDL++ = cmd;
#if TARGET_PC
u8 opcode = cmd & GX_OPCODE_MASK;
if (!is_draw_opcode(opcode)) {
memcpy(newDL, oldDL, cmdSize - 1);
oldDL += cmdSize - 1;
newDL += cmdSize - 1;
continue;
}
#else
if (cmd != GX_TRIANGLEFAN && cmd != GX_TRIANGLESTRIP)
break;
#endif
// Copy count
int vtxNum = *(u16*)oldDL;
@@ -71,11 +386,31 @@ void J3DShapeDraw::addTexMtxIndexInDL(u32 stride, u32 attrOffs, u32 valueBase) {
}
J3DShapeDraw::J3DShapeDraw(const u8* displayList, u32 displayListSize) {
#if TARGET_PC
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
#else
mDisplayList = (void*)displayList;
mDisplayListSize = displayListSize;
#endif
}
#if TARGET_PC
J3DShapeDraw::J3DShapeDraw(
const u8* displayList, u32 displayListSize, const GXVtxDescList* vtxDesc) {
u32 stride = 0;
std::vector<u8> optimized;
if (calc_vtx_stride(vtxDesc, stride) &&
optimize_display_list(displayList, displayListSize, stride, optimized))
{
set_display_list_copy(mDisplayList, mDisplayListSize, optimized.data(), optimized.size());
} else {
set_display_list_copy(mDisplayList, mDisplayListSize, displayList, displayListSize);
}
}
#endif
void J3DShapeDraw::draw() const {
ZoneScoped;
GXCallDisplayList(mDisplayList, mDisplayListSize);
}
@@ -132,7 +132,12 @@ J3DShapeDraw* J3DShapeFactory::newShapeDraw(int shapeNo, int mtxGroupNo) const {
const J3DShapeInitData& shapeInitData = mShapeInitData[mIndexTable[shapeNo]];
const J3DShapeDrawInitData& drawInitData =
(&mDrawInitData[shapeInitData.mDrawInitDataIndex])[mtxGroupNo];
#if TARGET_PC
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize,
getVtxDescList(shapeNo));
#else
shapeDraw = JKR_NEW J3DShapeDraw(&mDisplayListData[drawInitData.mDisplayListIndex], drawInitData.mDisplayListSize);
#endif
J3D_ASSERT_ALLOCMEM(193, shapeDraw);
return shapeDraw;
}
@@ -154,7 +159,7 @@ s32 J3DShapeFactory::calcSize(int shapeNo, u32 flag) {
for (u32 i = 0; i < mtxGroupNo; i++) {
size += calcSizeShapeMtx(flag, shapeNo, i);
size += 0x0C;
size += sizeof(J3DShapeDraw);
}
return size;
+1 -2
View File
@@ -206,8 +206,7 @@ void JPABaseParticle::init_c(JPAEmitterWorkData* work, JPABaseParticle* parent)
#if TARGET_PC
void JPABaseParticle::interp(JPAEmitterWorkData* work, void const* drawFunc) {
static bool enable = false;
if (!enable)
if (!dusk::frame_interp::is_enabled())
return;
// don't interpolate the first frame
@@ -761,6 +761,15 @@ bool JPAResource::calc(JPAEmitterWorkData* work, JPABaseEmitter* emtr) {
}
}
#ifdef TARGET_PC
if (((pBsp && pBsp->getDirType() == 3) || (pCsp && pCsp->getDirType() == 3)) &&
dusk::frame_interp::is_enabled())
{
// ensure mGlobalEmtrDir is valid
calcWorkData_d(work);
}
#endif
JPANode<JPABaseParticle>* next = NULL;
for (JPANode<JPABaseParticle>* node = emtr->mAlivePtclBase.getFirst(); node != emtr->mAlivePtclBase.getEnd(); node = next) {
next = node->getNext();
+15 -3
View File
@@ -2031,9 +2031,7 @@ void daAlink_blur_c::draw() {
ZoneScoped;
j3dSys.reinitGX();
#ifdef TARGET_PC
TGXTexObj texObj;
#else
#if !TARGET_PC
static TGXTexObj texObj;
#endif
static GXColor nColor0 = {0xFF, 0xFF, 0xFF, 0x14};
@@ -2041,11 +2039,25 @@ void daAlink_blur_c::draw() {
GXSetNumIndStages(0);
nColor0.a = field_0x20;
#if TARGET_PC
if (mpCachedBlurTex != m_blurTex) {
mBlurTexObj.reset();
GXInitTexObj(&mBlurTexObj,
reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(m_blurTex) + m_blurTex->imageOffset),
16, 4, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(
&mBlurTexObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1);
mpCachedBlurTex = m_blurTex;
}
GXLoadTexObj(&mBlurTexObj, GX_TEXMAP0);
#else
GXInitTexObj(&texObj, (void*)((uintptr_t)m_blurTex + m_blurTex->imageOffset), 16, 4, GX_TF_I4,
GX_CLAMP, GX_CLAMP, GX_FALSE);
GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE,
GX_ANISO_1);
GXLoadTexObj(&texObj, GX_TEXMAP0);
#endif
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBA4, 8);
GXClearVtxDesc();
+26 -4
View File
@@ -419,15 +419,36 @@ void daMant_packet_c::draw() {
GXSetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K3_A);
GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
#if TARGET_PC
static bool textureObjsInitialized = false;
static TGXTlutObj tlutObj;
static TGXTexObj mainTexObj;
static TGXTexObj undersideTexObj;
if (!textureObjsInitialized) {
GXInitTlutObj(&tlutObj, lut, GX_TL_RGB5A3, 0x100);
GXInitTexObjCI(&mainTexObj, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&mainTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
GXInitTexObjCI(
&undersideTexObj, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&undersideTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
textureObjsInitialized = true;
}
#else
GXTlutObj GStack_80;
GXInitTlutObj(&GStack_80, lut, GX_TL_RGB5A3, 0x100);
TGXTexObj GStack_74;
GXInitTexObjCI(&GStack_74, image, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&GStack_74, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
#endif
GXLoadTlut(&GStack_80, 0);
#if TARGET_PC
GXLoadTlut(&tlutObj, GX_TLUT0);
GXLoadTexObj(&mainTexObj, GX_TEXMAP0);
#else
GXLoadTlut(&GStack_80, GX_TLUT0);
GXLoadTexObj(&GStack_74, GX_TEXMAP0);
#endif
GXSetCullMode(GX_CULL_BACK);
@@ -443,12 +464,13 @@ void daMant_packet_c::draw() {
GXLoadNrmMtxImm(MStack_54, GX_PNMTX0);
GXCallDisplayList(l_Egnd_mantDL, 0x3e0);
#ifdef TARGET_PC
GStack_74.reset();
#endif
#if TARGET_PC
GXLoadTexObj(&undersideTexObj, GX_TEXMAP0);
#else
GXInitTexObjCI(&GStack_74, l_Egnd_mantTEX_U, 0x80, 0x80, GX_TF_C8, GX_CLAMP, GX_CLAMP, 0, 0);
GXInitTexObjLOD(&GStack_74, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, 0, 0, GX_ANISO_1);
GXLoadTexObj(&GStack_74, GX_TEXMAP0);
#endif
GXSetTevColor(GX_TEVREG0, COMPOUND_LITERAL(GXColor){0, 0, 0, 0});
GXSetTevKColor(GX_KCOLOR0, COMPOUND_LITERAL(GXColor){0, 0, 0, 0});
+16
View File
@@ -393,7 +393,9 @@ static const u8* l_sightDL_get() {
void daPy_sightPacket_c::draw() {
ZoneScoped;
#if !TARGET_PC
TGXTexObj texObj;
#endif
j3dSys.reinitGX();
GXSetNumIndStages(0);
@@ -408,10 +410,24 @@ void daPy_sightPacket_c::draw() {
GXSetTevColor(GX_TEVREG0, reg0);
GXSetTevColor(GX_TEVREG1, reg1);
#if TARGET_PC
if (mpCachedImg != mpImg) {
mTexObj.reset();
GXInitTexObj(&mTexObj, mpData, mpImg->width, mpImg->height,
static_cast<GXTexFmt>(mpImg->format), static_cast<GXTexWrapMode>(mpImg->wrapS),
static_cast<GXTexWrapMode>(mpImg->wrapT),
mpImg->mipmapCount > 1 ? GX_ENABLE : GX_DISABLE);
GXInitTexObjLOD(
&mTexObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, GX_FALSE, GX_FALSE, GX_ANISO_1);
mpCachedImg = mpImg;
}
GXLoadTexObj(&mTexObj, GX_TEXMAP0);
#else
GXInitTexObj(&texObj, mpData, mpImg->width, mpImg->height, (GXTexFmt)mpImg->format,
(GXTexWrapMode)mpImg->wrapS, (GXTexWrapMode)mpImg->wrapT, mpImg->mipmapCount > 1 ? GX_ENABLE : GX_DISABLE);
GXInitTexObjLOD(&texObj, GX_LINEAR, GX_LINEAR, 0.0, 0.0, 0.0, GX_FALSE, GX_FALSE, GX_ANISO_1);
GXLoadTexObj(&texObj, GX_TEXMAP0);
#endif
GXLoadPosMtxImm(mProjMtx, GX_PNMTX0);
GXSetCurrentMtx(0);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
+4 -4
View File
@@ -41,12 +41,12 @@ public:
/* 0x14 */ GXColor field_0x14;
/* 0x18 */ GXColor field_0x18;
/* 0x1C */ TGXTexObj field_0x1c;
/* 0x3C */ GXTlutObj field_0x3c;
/* 0x3C */ TGXTlutObj field_0x3c;
/* 0x48 */ s16 field_0x48;
/* 0x4A */ s16 field_0x4a;
/* 0x4C */ u8 field_0x4c;
/* 0x50 */ TGXTexObj field_0x50;
/* 0x70 */ GXTlutObj field_0x70;
/* 0x70 */ TGXTlutObj field_0x70;
/* 0x7C */ s16 field_0x7c;
/* 0x7E */ s16 field_0x7e;
/* 0x80 */ u8 field_0x80;
@@ -100,7 +100,7 @@ public:
u8 check() { return field_0x0; }
int getCI() { return mCI; }
TGXTexObj* getTexObj() { return &mTexObj; }
GXTlutObj* getTlutObj() { return &mTlutObj; }
TGXTlutObj* getTlutObj() { return &mTlutObj; }
GXColor* getColor() { return &mColor; }
f32 getS() { return mS; }
f32 getT() { return mT; }
@@ -110,7 +110,7 @@ public:
/* 0x00 */ u8 field_0x0;
/* 0x01 */ u8 mCI;
/* 0x04 */ TGXTexObj mTexObj;
/* 0x24 */ GXTlutObj mTlutObj;
/* 0x24 */ TGXTlutObj mTlutObj;
/* 0x30 */ GXColor mColor;
/* 0x34 */ f32 mS;
/* 0x38 */ f32 mT;
+149 -4
View File
@@ -94,6 +94,39 @@ static void dKyr_set_btitex(TGXTexObj* i_obj, ResTIMG* i_img) {
dKyr_set_btitex_common(i_obj, i_img, GX_TEXMAP0);
}
#if TARGET_PC
template <int N>
struct CachedTexObjs {
TGXTexObj texObj[N];
ResTIMG* timg[N] = {};
};
template <int N>
static GXTexObj* load_cached_tex(CachedTexObjs<N>& cache, ResTIMG* img, GXTexMapID mapID) {
for (int i = 0; i < N; i++) {
if (img != nullptr && cache.timg[i] == img) {
GXLoadTexObj(&cache.texObj[i], mapID);
return &cache.texObj[i];
}
}
int slot = 0;
for (int i = 0; i < N; i++) {
if (cache.timg[i] == nullptr) {
slot = i;
break;
}
}
if (cache.timg[slot] != nullptr) {
cache.texObj[slot].reset();
}
cache.timg[slot] = img;
dKyr_set_btitex_common(&cache.texObj[slot], img, mapID);
return &cache.texObj[slot];
}
#endif
void dKyr_lenzflare_move() {
dKankyo_sun_Packet* sun_packet = g_env_light.mpSunPacket;
dKankyo_sunlenz_Packet* lenz_packet = g_env_light.mpSunLenzPacket;
@@ -2133,10 +2166,17 @@ static void dKyr_draw_rev_moon(Mtx drawMtx, u8** tex) {
return;
}
#if TARGET_PC
static CachedTexObjs<8> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
load_cached_tex(texobj, (ResTIMG*)tex[1], GX_TEXMAP1);
load_cached_tex(texobj, (ResTIMG*)tex[texidx + 2], GX_TEXMAP2);
#else
TGXTexObj texobj;
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[1], GX_TEXMAP1);
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[texidx + 2], GX_TEXMAP2);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
@@ -2216,7 +2256,11 @@ static void dKyr_draw_rev_moon(Mtx drawMtx, u8** tex) {
for (int i = 0; i < 2; i++) {
if (i == 1) {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)lenz_packet->mpResBall, GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)lenz_packet->mpResBall);
#endif
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
@@ -2481,10 +2525,17 @@ void dKyr_drawSun(Mtx drawMtx, cXyz* ppos, GXColor& unused, u8** tex) {
return;
}
#if TARGET_PC
static CachedTexObjs<8> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
load_cached_tex(texobj, (ResTIMG*)tex[1], GX_TEXMAP1);
load_cached_tex(texobj, (ResTIMG*)tex[texidx + 2], GX_TEXMAP2);
#else
TGXTexObj texobj;
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[1], GX_TEXMAP1);
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[texidx + 2], GX_TEXMAP2);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
@@ -2578,7 +2629,11 @@ void dKyr_drawSun(Mtx drawMtx, cXyz* ppos, GXColor& unused, u8** tex) {
for (int i = 0; i < 2; i++) {
if (i == 1) {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)lenz_packet->mpResBall, GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)lenz_packet->mpResBall);
#endif
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
@@ -2742,8 +2797,13 @@ void dKyr_drawLenzflare(Mtx drawMtx, cXyz* ppos, GXColor& param_2, u8** tex) {
j3dSys.reinitGX();
#if TARGET_PC
static CachedTexObjs<3> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
GXSetTevColor(GX_TEVREG1, color_reg1);
@@ -3048,11 +3108,23 @@ void dKyr_drawLenzflare(Mtx drawMtx, cXyz* ppos, GXColor& param_2, u8** tex) {
}
if (i == 1) {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[2], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[2]);
#endif
} else if (i == 2) {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[3], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[3]);
#endif
} else {
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
}
spE4.x = -var_f31;
@@ -3143,8 +3215,13 @@ void dKyr_drawRain(Mtx drawMtx, u8** tex) {
return;
}
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
GXSetNumTexGens(1);
@@ -3308,8 +3385,13 @@ void dKyr_drawSibuki(Mtx drawMtx, u8** tex) {
color.b = 0xC8;
color.a = rain_packet->mSibukiAlpha * alphaFade;
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[1], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[1]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color);
GXSetTevColor(GX_TEVREG1, color);
@@ -3397,7 +3479,11 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
Mtx camMtx;
Mtx rotMtx;
cXyz pos[4];
#if TARGET_PC
static CachedTexObjs<1> texobj;
#else
TGXTexObj spDC;
#endif
cXyz spD0;
Vec spC4;
Vec spB8;
@@ -3484,7 +3570,11 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
f32 temp_f24 = 6.5f;
for (int i = 0; i < 1; i++) {
dKyr_set_btitex(&spDC, (ResTIMG*)*tex);
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)*tex, GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)*tex);
#endif
#if TARGET_PC
GXSetNumChans(1);
GXSetChanCtrl(GX_COLOR0, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE);
@@ -3582,7 +3672,7 @@ void dKyr_drawHousi(Mtx drawMtx, u8** tex) {
block_14:
#if !TARGET_PC // GXLoadTextObj does nothing, TEV colors replaced with vertex colors
GXLoadTexObj(&spDC, GX_TEXMAP0);
GXLoadTexObj(&texobj, GX_TEXMAP0);
GXSetTevColor(GX_TEVREG0, color_reg0);
#endif
@@ -3842,8 +3932,13 @@ void dKyr_drawSnow(Mtx drawMtx, u8** tex) {
}
if (tex[0] != NULL) {
TGXTexObj spA0;
dKyr_set_btitex(&spA0, (ResTIMG*)tex[0]);
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
#if TARGET_PC
// Dusklight optimization: enable draw call merging
// by using vertex color instead of GX_TEVREG0
@@ -4445,7 +4540,12 @@ void drawCloudShadow(Mtx drawMtx, u8** tex) {
GXSetClipMode(GX_CLIP_DISABLE);
#if TARGET_PC
static CachedTexObjs<1> texobj;
TGXTexObj fb_texobj;
#else
TGXTexObj texobj, fb_texobj;
#endif
if (g_env_light.mMoyaMode < 50) {
dKy_ParticleColor_get_bg(&camera->view.lookat.eye, NULL, &sp48, &sp44, &sp40, &sp3C, 0.0f);
f32 temp_f30 = 0.4f;
@@ -4458,7 +4558,11 @@ void drawCloudShadow(Mtx drawMtx, u8** tex) {
color_reg1.g = (0.45f * sp38.g) + (0.55f * sp44.g);
color_reg1.b = (0.45f * sp38.b) + (0.55f * sp44.b);
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
GXSetTevColor(GX_TEVREG1, color_reg1);
@@ -4503,7 +4607,11 @@ void drawCloudShadow(Mtx drawMtx, u8** tex) {
color_reg1.b = 0;
color_reg1.a = 0xFF;
#if TARGET_PC
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP1);
#else
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[0], GX_TEXMAP1);
#endif
ResTIMG* fb_timg = mDoGph_gInf_c::getFrameBufferTimg();
dDlst_window_c* window = dComIfGp_getWindow(0);
@@ -4650,7 +4758,11 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) {
Mtx camMtx;
Mtx rotMtx;
#if TARGET_PC
static CachedTexObjs<3> texobj;
#else
TGXTexObj texobj;
#endif
cXyz proj;
f32 rot;
@@ -4760,7 +4872,11 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) {
color_reg1.r = 0;
color_reg1.g = 0;
color_reg1.b = 0;
#if TARGET_PC
auto* loaded_texobj = load_cached_tex(texobj, (ResTIMG*)tex[j], GX_TEXMAP0);
#else
dKyr_set_btitex(&texobj, (ResTIMG*)tex[j]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color);
@@ -4865,7 +4981,11 @@ void drawVrkumo(Mtx drawMtx, GXColor& color, u8** tex) {
}
if (!(vrkumo_packet->mVrkumoEff[k].mAlpha <= 0.000001f)) {
#if TARGET_PC
GXLoadTexObj(loaded_texobj, GX_TEXMAP0);
#else
GXLoadTexObj(&texobj, GX_TEXMAP0);
#endif
GXSetTevColor(GX_TEVREG0, color);
sp60 = sp68 * (0.2f + (0.2f * (k / 100.0f)));
@@ -5487,8 +5607,14 @@ void dKyr_odour_draw(Mtx drawMtx, u8** tex) {
break;
}
#if TARGET_PC
static CachedTexObjs<1> texobj;
TGXTexObj fb_texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP1);
#else
TGXTexObj texobj, fb_texobj;
dKyr_set_btitex_common(&texobj, (ResTIMG*)tex[0], GX_TEXMAP1);
#endif
ResTIMG* fb_timg = mDoGph_gInf_c::getFrameBufferTimg();
dDlst_window_c* window = dComIfGp_getWindow(0);
@@ -5891,8 +6017,13 @@ void dKyr_mud_draw(Mtx drawMtx, u8** tex) {
if (g_env_light.camera_water_in_status == 0) {
for (int i = 0; i < 1; i++) {
#if TARGET_PC
static CachedTexObjs<1> texobj_cache;
auto* texobj = load_cached_tex(texobj_cache, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
GXSetNumChans(0);
GXSetTevColor(GX_TEVREG0, color_reg0);
@@ -5932,7 +6063,11 @@ void dKyr_mud_draw(Mtx drawMtx, u8** tex) {
color_reg0.a = mud_packet->mEffect[j].field_0x38 * var_f31;
#if TARGET_PC
GXLoadTexObj(texobj, GX_TEXMAP0);
#else
GXLoadTexObj(&texobj, GX_TEXMAP0);
#endif
GXSetTevColor(GX_TEVREG0, color_reg0);
f32 sp30 = 1.0f;
@@ -6054,8 +6189,13 @@ static void dKyr_evil_draw2(Mtx drawMtx, u8** tex) {
color_reg0.b = 0x87;
color_reg0.a = 0xFF;
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[1], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[1]);
#endif
#if TARGET_PC
if (dusk::frame_interp::get_ui_tick_pending())
@@ -6293,8 +6433,13 @@ void dKyr_evil_draw(Mtx drawMtx, u8** tex) {
color_reg1.b = 10;
color_reg1.a = 255;
#if TARGET_PC
static CachedTexObjs<1> texobj;
load_cached_tex(texobj, (ResTIMG*)tex[0], GX_TEXMAP0);
#else
TGXTexObj texobj;
dKyr_set_btitex(&texobj, (ResTIMG*)tex[0]);
#endif
#if TARGET_PC
if (dusk::frame_interp::get_ui_tick_pending())
+161
View File
@@ -23,6 +23,39 @@
#include "dusk/frame_interpolation.h"
#include <cstring>
#if TARGET_PC
#include "dusk/settings.h"
#include <algorithm>
namespace {
// Reads the user HUD scale setting, clamped to a safe range.
f32 dGetUserHudScale() {
return std::clamp(dusk::getSettings().game.hudScale.getValue(), 0.5f, 2.0f);
}
// The screen corner each HUD group is anchored to. A pane scales around its own origin,
// so without correction it drifts away from the screen edge; this names the corner that
// must stay put.
enum class HudCorner { TopLeft, TopRight, BottomLeft, BottomRight };
// Adds the paneTrans offset that keeps i_corner pinned in place while the user HUD scale
// grows or shrinks the pane. The shift is half the change in size pushed toward the
// anchor corner, so it depends only on the pane's size (not its on-screen position) and
// works whether the HUD is scaled down or up. i_pull < 1 applies a partial horizontal
// push for a pane whose content sits inset from its box edge (the heart row).
void dAnchorHudScale(CPaneMgr* i_pane, HudCorner i_corner, f32* io_x, f32* io_y, f32 i_pull = 1.0f) {
const f32 half = (1.0f - dGetUserHudScale()) * 0.5f;
const f32 dirX =
(i_corner == HudCorner::TopRight || i_corner == HudCorner::BottomRight) ? 1.0f : -1.0f;
const f32 dirY =
(i_corner == HudCorner::BottomLeft || i_corner == HudCorner::BottomRight) ? 1.0f : -1.0f;
*io_x += dirX * i_pane->getInitSizeX() * half * i_pull;
*io_y += dirY * i_pane->getInitSizeY() * half;
}
} // namespace
#endif
dMeter2Draw_c::dMeter2Draw_c(JKRExpHeap* mp_heap) {
OS_REPORT("enter dMeter2Draw_c::dMeter2Draw_c(JKRExpHeap *mp_heap)\n");
@@ -536,6 +569,12 @@ void dMeter2Draw_c::init() {
}
void dMeter2Draw_c::exec(u32 i_status) {
#if TARGET_PC
// n_all keeps the vanilla scale. Scaling the root pane shrinks every child toward
// its centred origin; per-child scaling in each drawXxx() path keeps each HUD group
// anchored to its own pane origin and also pulls it toward the screen corner.
const f32 userHudScale = dGetUserHudScale();
#endif
if (mParentScale != g_drawHIO.mParentScale) {
mParentScale = g_drawHIO.mParentScale;
mpParent->scale(g_drawHIO.mParentScale, g_drawHIO.mParentScale);
@@ -546,6 +585,39 @@ void dMeter2Draw_c::exec(u32 i_status) {
mpParent->setAlphaRate(g_drawHIO.mParentAlpha);
}
#if TARGET_PC
if (i_status & 0x1000000) {
f32 ringPosX = g_drawHIO.mRingHUDButtonsPosX;
f32 ringPosY = g_drawHIO.mRingHUDButtonsPosY;
dAnchorHudScale(mpButtonParent, HudCorner::TopRight, &ringPosX, &ringPosY);
if (mButtonsPosX != ringPosX || mButtonsPosY != ringPosY) {
mButtonsPosX = ringPosX;
mButtonsPosY = ringPosY;
mpButtonParent->paneTrans(ringPosX, ringPosY);
}
const f32 ringButtonsScale = g_drawHIO.mRingHUDButtonsScale * userHudScale;
if (mButtonsScale != ringButtonsScale) {
mButtonsScale = ringButtonsScale;
mpButtonParent->scale(ringButtonsScale, ringButtonsScale);
}
} else {
f32 mainPosX = g_drawHIO.mMainHUDButtonsPosX;
f32 mainPosY = g_drawHIO.mMainHUDButtonsPosY;
dAnchorHudScale(mpButtonParent, HudCorner::TopRight, &mainPosX, &mainPosY);
if (mButtonsPosX != mainPosX || mButtonsPosY != mainPosY) {
mButtonsPosX = mainPosX;
mButtonsPosY = mainPosY;
mpButtonParent->paneTrans(mainPosX, mainPosY);
}
const f32 mainButtonsScale = g_drawHIO.mMainHUDButtonsScale * userHudScale;
if (mButtonsScale != mainButtonsScale) {
mButtonsScale = mainButtonsScale;
mpButtonParent->scale(mainButtonsScale, mainButtonsScale);
}
}
#else
if (i_status & 0x1000000) {
if (mButtonsPosX != g_drawHIO.mRingHUDButtonsPosX ||
mButtonsPosY != g_drawHIO.mRingHUDButtonsPosY)
@@ -574,6 +646,7 @@ void dMeter2Draw_c::exec(u32 i_status) {
mpButtonParent->scale(g_drawHIO.mMainHUDButtonsScale, g_drawHIO.mMainHUDButtonsScale);
}
}
#endif
}
void dMeter2Draw_c::draw() {
@@ -588,6 +661,9 @@ void dMeter2Draw_c::draw() {
if (mpItemXY[i] != NULL) {
for (int j = 0; j < 3; j++) {
f32 temp_f30 = mItemParams[i].num_scale * 16.0f;
#if TARGET_PC
temp_f30 *= dGetUserHudScale();
#endif
Vec vtx0 = mpItemXY[i]->getPanePtr()->getGlbVtx(0);
Vec vtx3 = mpItemXY[i]->getPanePtr()->getGlbVtx(3);
@@ -1478,7 +1554,12 @@ void dMeter2Draw_c::drawLife(s16 i_maxLife, s16 i_life, f32 i_posX, f32 i_posY)
}
}
#if TARGET_PC
const f32 lifeParentScale = g_drawHIO.mLifeParentScale * dGetUserHudScale();
mpLifeParent->scale(lifeParentScale, lifeParentScale);
#else
mpLifeParent->scale(g_drawHIO.mLifeParentScale, g_drawHIO.mLifeParentScale);
#endif
for (int i = 0; i < 20; i++) {
mpHeartMark[i]->scale(g_drawHIO.mHeartMarkScale, g_drawHIO.mHeartMarkScale);
@@ -1488,7 +1569,16 @@ void dMeter2Draw_c::drawLife(s16 i_maxLife, s16 i_life, f32 i_posX, f32 i_posY)
mpBigHeart->scale(g_drawHIO.mBigHeartScale, g_drawHIO.mBigHeartScale);
}
#if TARGET_PC
f32 lifePosX = i_posX;
f32 lifePosY = i_posY;
// The heart row sits inset from its box's left edge, so use a partial horizontal pull
// to keep it from jamming against the screen edge.
dAnchorHudScale(mpLifeParent, HudCorner::TopLeft, &lifePosX, &lifePosY, 0.6f);
mpLifeParent->paneTrans(lifePosX, lifePosY);
#else
mpLifeParent->paneTrans(i_posX, i_posY);
#endif
}
void dMeter2Draw_c::setAlphaLifeChange(bool param_0) {
@@ -1601,9 +1691,22 @@ void dMeter2Draw_c::drawKanteraScreen(u8 i_meterType) {
mpMagicMeter->resize(field_0x584[i_meterType], field_0x590[i_meterType]);
mpMagicFrameR->move(field_0x59c[i_meterType], field_0x5a8[i_meterType]);
mpMagicBase->resize(field_0x5b4[i_meterType], field_0x5c0[i_meterType]);
#if TARGET_PC
const f32 magicUserScale = dGetUserHudScale();
mpMagicParent->scale(field_0x5cc[i_meterType] * magicUserScale,
field_0x5d8[i_meterType] * magicUserScale);
f32 magicPosX = field_0x5e4[i_meterType];
f32 magicPosY = field_0x5f0[i_meterType];
// The oil/magic bar sits inset within its pane box, so use a reduced horizontal pull
// (like the heart row) to keep it from overshooting off the left edge when shrunk.
dAnchorHudScale(mpMagicParent, HudCorner::TopLeft, &magicPosX, &magicPosY, 0.3f);
mpMagicParent->paneTrans(magicPosX, magicPosY);
#else
mpMagicParent->scale(field_0x5cc[i_meterType], field_0x5d8[i_meterType]);
mpMagicParent->paneTrans(field_0x5e4[i_meterType], field_0x5f0[i_meterType]);
#endif
mpKanteraScreen->draw(0.0f, 0.0f, graf_ctx);
}
@@ -1867,10 +1970,21 @@ void dMeter2Draw_c::drawLightDrop(u8 i_num, u8 i_needNum, f32 i_posX, f32 i_posY
field_0x6fc = param_5;
mLightDropVesselScale = i_vesselScale;
#if TARGET_PC
const f32 lightDropUserScale = dGetUserHudScale();
const f32 lightDropScale = mLightDropVesselScale * field_0x6f8 * lightDropUserScale;
mpLightDropParent->scale(lightDropScale, lightDropScale);
f32 lightDropPosX = i_posX;
f32 lightDropPosY = i_posY;
dAnchorHudScale(mpLightDropParent, HudCorner::TopRight, &lightDropPosX, &lightDropPosY);
mpLightDropParent->paneTrans(lightDropPosX, lightDropPosY);
#else
mpLightDropParent->scale(mLightDropVesselScale * field_0x6f8,
mLightDropVesselScale * field_0x6f8);
mpLightDropParent->paneTrans(i_posX, i_posY);
#endif
}
void dMeter2Draw_c::setAlphaLightDropChange(bool unused) {}
@@ -1943,8 +2057,13 @@ void dMeter2Draw_c::setAlphaLightDropAnimeMax() {
field_0x6f8 = 1.0f;
}
#if TARGET_PC
const f32 dropAnimScale = mLightDropVesselScale * field_0x6f8 * dGetUserHudScale();
mpLightDropParent->scale(dropAnimScale, dropAnimScale);
#else
mpLightDropParent->scale(mLightDropVesselScale * field_0x6f8,
mLightDropVesselScale * field_0x6f8);
#endif
if (g_drawHIO.mLightDrop.mDropGetScaleAnimFrameNum == mpLightDropParent->getAlphaTimer()) {
dMeter2Info_setLightDropGetFlag(dComIfGp_getStartStageDarkArea(), 0xFF);
@@ -2015,10 +2134,22 @@ void dMeter2Draw_c::drawRupee(s16 i_rupeeNum) {
static_cast<J2DPicture*>(mpRupeeTexture[0][0]->getPanePtr())->changeTexture(timg, 0);
static_cast<J2DPicture*>(mpRupeeTexture[0][1]->getPanePtr())->changeTexture(timg, 0);
#if TARGET_PC
const f32 rupeeKeyUserScale = dGetUserHudScale();
const f32 rupeeKeyScale = g_drawHIO.mRupeeKeyScale * field_0x718 * rupeeKeyUserScale;
mpRupeeKeyParent->scale(rupeeKeyScale, rupeeKeyScale);
f32 rupeeKeyPosX = g_drawHIO.mRupeeKeyPosX;
f32 rupeeKeyPosY = g_drawHIO.mRupeeKeyPosY;
// Rupees/keys read better anchored to the bottom-right corner than the top-right.
dAnchorHudScale(mpRupeeKeyParent, HudCorner::BottomRight, &rupeeKeyPosX, &rupeeKeyPosY);
mpRupeeKeyParent->paneTrans(rupeeKeyPosX, rupeeKeyPosY);
#else
mpRupeeKeyParent->scale(g_drawHIO.mRupeeKeyScale * field_0x718,
g_drawHIO.mRupeeKeyScale * field_0x718);
mpRupeeKeyParent->paneTrans(g_drawHIO.mRupeeKeyPosX, g_drawHIO.mRupeeKeyPosY);
#endif
mpRupeeParent[0]->scale(g_drawHIO.mRupeeScale, g_drawHIO.mRupeeScale);
mpRupeeParent[0]->paneTrans(g_drawHIO.mRupeePosX, g_drawHIO.mRupeePosY);
@@ -2137,8 +2268,18 @@ void dMeter2Draw_c::drawKey(s16 i_keyNum) {
}
}
#if TARGET_PC
const f32 keyScale = g_drawHIO.mKeyScale * dGetUserHudScale();
mpKeyParent->scale(keyScale, keyScale);
f32 keyPosX = g_drawHIO.mKeyPosX;
f32 keyPosY = g_drawHIO.mKeyPosY;
dAnchorHudScale(mpKeyParent, HudCorner::BottomRight, &keyPosX, &keyPosY);
mpKeyParent->paneTrans(keyPosX, keyPosY);
#else
mpKeyParent->scale(g_drawHIO.mKeyScale, g_drawHIO.mKeyScale);
mpKeyParent->paneTrans(g_drawHIO.mKeyPosX, g_drawHIO.mKeyPosY);
#endif
}
void dMeter2Draw_c::setAlphaKeyChange(bool param_0) {
@@ -2596,11 +2737,24 @@ f32 dMeter2Draw_c::getButtonCrossParentInitTransY() {
}
void dMeter2Draw_c::drawButtonCross(f32 i_posX, f32 i_posY) {
#if TARGET_PC
const f32 buttonCrossUserScale = dGetUserHudScale();
const f32 buttonCrossScale = g_drawHIO.mButtonCrossScale * buttonCrossUserScale;
mpButtonCrossParent->scale(buttonCrossScale, buttonCrossScale);
#else
mpButtonCrossParent->scale(g_drawHIO.mButtonCrossScale, g_drawHIO.mButtonCrossScale);
#endif
mpTextI->scale(g_drawHIO.mButtonCrossTextScale, g_drawHIO.mButtonCrossTextScale);
mpTextM->scale(g_drawHIO.mButtonCrossTextScale, g_drawHIO.mButtonCrossTextScale);
#if TARGET_PC
f32 buttonCrossPosX = i_posX;
f32 buttonCrossPosY = i_posY;
dAnchorHudScale(mpButtonCrossParent, HudCorner::TopLeft, &buttonCrossPosX, &buttonCrossPosY);
mpButtonCrossParent->paneTrans(buttonCrossPosX, buttonCrossPosY);
#else
mpButtonCrossParent->paneTrans(i_posX, i_posY);
#endif
}
void dMeter2Draw_c::setAlphaButtonCrossAnimeMin() {
@@ -3505,9 +3659,16 @@ void dMeter2Draw_c::drawKanteraMeter(u8 i_button, f32 i_alphaRate) {
Vec vtx0 = pane->getPanePtr()->getGlbVtx(0);
Vec vtx3 = pane->getPanePtr()->getGlbVtx(3);
#if TARGET_PC
const f32 oilUserScale = dGetUserHudScale();
mpKanteraMeter[i_button]->setPos(((vtx0.x + vtx3.x) * 0.5f) + 9.0f * oilUserScale + sp10[i_button],
vtx3.y + sp8[i_button]);
mpKanteraMeter[i_button]->setScale(0.6f * oilUserScale, 0.6f * oilUserScale);
#else
mpKanteraMeter[i_button]->setPos(((vtx0.x + vtx3.x) * 0.5f) + 9.0f + sp10[i_button],
vtx3.y + sp8[i_button]);
mpKanteraMeter[i_button]->setScale(0.6f, 0.6f);
#endif
mpKanteraMeter[i_button]->setNowGauge(dComIfGs_getMaxOil(), dComIfGs_getOil());
mpKanteraMeter[i_button]->setAlphaRate(i_alphaRate);
}
+14 -2
View File
@@ -16,6 +16,10 @@
#include "f_op/f_op_overlap_mng.h"
#include "m_Do/m_Do_controller_pad.h"
#include "d/d_camera.h"
#if TARGET_PC
#include "dusk/settings.h"
#include <algorithm>
#endif
#include <cstring>
#if (PLATFORM_WII || PLATFORM_SHIELD)
@@ -621,8 +625,16 @@ void dMeterMap_c::draw() {
mMapJ2DPicture->setAlpha(alpha);
#if TARGET_PC
mMapJ2DPicture->draw(mDoGph_gInf_c::ScaleHUDXLeft(drawPosX), drawPosY, sizeX, sizeY, false,
false, false);
// Scale the minimap with the user HUD scale and shift down so its bottom-left
// corner stays anchored to the same screen position as at scale 1.0.
const f32 userHudScale =
std::clamp(dusk::getSettings().game.hudScale.getValue(), 0.5f, 2.0f);
const f32 scaledSizeX = sizeX * userHudScale;
const f32 scaledSizeY = sizeY * userHudScale;
const f32 mapBottomShift = sizeY - scaledSizeY;
mMapJ2DPicture->draw(mDoGph_gInf_c::ScaleHUDXLeft(drawPosX),
drawPosY + mapBottomShift, scaledSizeX, scaledSizeY,
false, false, false);
#else
mMapJ2DPicture->draw(drawPosX, drawPosY, sizeX, sizeY, false, false, false);
#endif
+2 -1
View File
@@ -34,6 +34,7 @@
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#include <mach-o/loader.h>
#include <TargetConditionals.h>
#else
#include <elf.h>
#include <link.h>
@@ -929,7 +930,7 @@ void install() {
SymInitialize(GetCurrentProcess(), nullptr, TRUE);
#endif
g_prevFilter = SetUnhandledExceptionFilter(&windowsHandler);
#else
#elif !defined(__APPLE__) || !TARGET_OS_TV
Dl_info moduleInfo;
if (dladdr(reinterpret_cast<void*>(&install), &moduleInfo) != 0) {
g_ctx.moduleBase = reinterpret_cast<uintptr_t>(moduleInfo.dli_fbase);
+5 -3
View File
@@ -49,7 +49,9 @@ namespace dusk {
dCam->Reset(center, eye);
}
ImGui::InputFloat("Camera FOV", &dCam->mFovy);
if (ImGui::InputFloat("Camera FOV", &dCam->mFovy)) {
dCam->mFovy = std::clamp(dCam->mFovy, 0.1f, 179.9f);
}
ImGui::SeparatorText("Options");
@@ -75,12 +77,12 @@ namespace dusk {
if (!getSettings().game.debugFlyCam) {
ImGui::BeginDisabled();
}
config::ImGuiCheckbox("Lock Events", getSettings().game.debugFlyCamLockEvents);
config::ImGuiCheckbox("Freeze Time", getSettings().game.debugFlyCamLockEvents);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
if (!getSettings().game.debugFlyCam) {
ImGui::SetTooltip("Enable Fly Mode first.");
} else {
ImGui::SetTooltip("Freeze game events while flying.");
ImGui::SetTooltip("Freezes the game while flying.");
}
}
if (!getSettings().game.debugFlyCam) {
+2
View File
@@ -51,6 +51,7 @@ UserSettings g_userSettings = {
// Preferences
.enableMirrorMode {"game.enableMirrorMode", false},
.minimalHUD {"game.minimalHUD", false},
.hudScale {"game.hudScale", 1.0f},
.pauseOnFocusLost {"game.pauseOnFocusLost", false},
.enableLinkDollRotation {"game.enableLinkDollRotation", false},
.enableAchievementToasts {"game.enableAchievementToasts", true},
@@ -240,6 +241,7 @@ void registerSettings() {
Register(g_userSettings.game.freeCameraXSensitivity);
Register(g_userSettings.game.freeCameraYSensitivity);
Register(g_userSettings.game.minimalHUD);
Register(g_userSettings.game.hudScale);
Register(g_userSettings.game.pauseOnFocusLost);
Register(g_userSettings.game.enableDiscordPresence);
Register(g_userSettings.game.bloomMode);
+1 -1
View File
@@ -217,7 +217,7 @@ void AchievementsWindow::updateTotal() {
return;
}
const auto all = AchievementSystem::get().getAchievements();
int total = static_cast<int>(all.size());
const int total = std::count_if(all.begin(), all.end(), [](const Achievement& achievement){ return achievement.category != AchievementCategory::Glitched;});
int unlocked = 0;
for (const auto& a : all) {
if (a.unlocked) {
+5
View File
@@ -1113,6 +1113,11 @@ SettingsWindow::SettingsWindow(bool prelaunch) : mPrelaunch(prelaunch) {
addOption("Minimal HUD", getSettings().game.minimalHUD,
"Disables the elements of the main HUD of the game.<br/>Useful for a more immersive "
"experience.");
config_percent_select(leftPane, rightPane, getSettings().game.hudScale,
"HUD Scale",
"Scales the size of the gameplay HUD (hearts, buttons, mini-map, etc.). Does not affect dialog boxes or menus.",
50, 200, 5,
[] { return getSettings().game.minimalHUD.getValue(); });
addOption("Restore Wii 1.0 Glitches", getSettings().game.restoreWiiGlitches,
"Restores patched glitches from Wii USA 1.0, the first released version.");
addOption("Enable Rotating Link Doll", getSettings().game.enableLinkDollRotation,
+11
View File
@@ -36,9 +36,20 @@ static int fopCam_Execute(camera_class* i_this) {
fapGm_HIO_c::startCpuTimer();
#endif
#if TARGET_PC
if (dusk::getSettings().game.debugFlyCam && dusk::getSettings().game.debugFlyCamLockEvents) {
dScnPly_c::setPauseTimer(1);
ret = fpcMtd_Execute((process_method_class*)i_this->submethod, i_this);
} else {
if (!dComIfGp_isPauseFlag() && !dScnPly_c::isPause()) {
ret = fpcMtd_Execute((process_method_class*)i_this->submethod, i_this);
}
}
#else
if (!dComIfGp_isPauseFlag() && !dScnPly_c::isPause()) {
ret = fpcMtd_Execute((process_method_class*)i_this->submethod, i_this);
}
#endif
#if DEBUG
fapGm_HIO_c::stopCpuTimer("カメラ(計算処理)"); // Camera (computational processing)
+4 -1
View File
@@ -11,12 +11,15 @@
#include <types.h>
u32 mDoLib_setResTimgObj(ResTIMG const* i_img, TGXTexObj* o_texObj, u32 tlut_name,
GXTlutObj* o_tlutObj) {
TGXTlutObj* o_tlutObj) {
#ifdef TARGET_PC
o_texObj->reset();
#endif
if (i_img->indexTexture) {
JUT_ASSERT(44, o_tlutObj != NULL);
#ifdef TARGET_PC
o_tlutObj->reset();
#endif
GXInitTlutObj(o_tlutObj, (void*)((u8*)i_img + i_img->paletteOffset),
(GXTlutFmt)i_img->colorFormat, (u16)i_img->numColors);
GXInitTexObjCI(o_texObj, (void*)((u8*)i_img + i_img->imageOffset), i_img->width, i_img->height,