From 2c1316e81d5971f41e76b5880b4a032715f8d512 Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Sun, 14 Jun 2026 11:48:56 -0700 Subject: [PATCH 1/4] monobj: unify statWatch result into selectedTarget Merging the Pass-2 result accumulator into selectedTarget eliminates a register-bounce (mr r27,r23) and a separate selectedTarget=-1 init, matching the target which reuses the same register for result and selectedTarget. statWatch 96.725->96.905, unit 97.867->97.880. Co-Authored-By: Claude Fable 5 --- src/monobj.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/monobj.cpp b/src/monobj.cpp index b331da9502..b4ff803eed 100644 --- a/src/monobj.cpp +++ b/src/monobj.cpp @@ -1360,7 +1360,7 @@ void CGMonObj::statWatch() *reinterpret_cast(script + 0xCC)); // Pass 2: select target. - int result = -1; + selectedTarget = -1; for (int slot = 0; slot < 4; slot++) { int partyIndex = *reinterpret_cast(mon + slot * 4 + 0x620); CGPartyObj* party = Game.m_partyObjArr[partyIndex]; @@ -1373,7 +1373,7 @@ void CGMonObj::statWatch() ((static_cast(reinterpret_cast(party)->GetCID()) & 0x6D) != 0x6D) || (reinterpret_cast(reinterpret_cast(party)->m_scriptHandle[0xED]) == 0))) { if (monObj->m_partyDistance[partyIndex] < homeRange2) { - result = partyIndex; + selectedTarget = partyIndex; if (targetMode == 0) { break; } @@ -1398,17 +1398,16 @@ void CGMonObj::statWatch() switch (targetMode) { case 1: - result = targetPartyIndex; + selectedTarget = targetPartyIndex; break; case 2: case 3: case 4: if (accum >= 0) { - result = accum; + selectedTarget = accum; } break; } - selectedTarget = result; } if (selectedTarget >= 0) { From e583423aa590d6fd7d902b46b684d8bb54c01f13 Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Sun, 14 Jun 2026 11:55:57 -0700 Subject: [PATCH 2/4] monobj: widen setRepop countC to int The weapon-mode particle count is read from u16 script fields; holding it in a signed short forced extsh + cast, while the target zero-extends (clrlwi) and compares directly. int countC drops the cast and matches the loop bound. setRepop 96.920->97.897, unit 97.880->97.925. Co-Authored-By: Claude Fable 5 --- src/monobj.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/monobj.cpp b/src/monobj.cpp index b4ff803eed..03eb615ea3 100644 --- a/src/monobj.cpp +++ b/src/monobj.cpp @@ -710,12 +710,12 @@ void CGMonObj::setRepop(int mode) reinterpret_cast(this)->endPSlotBit(0x1000); - short countC = (weaponMode != 0) ? + int countC = (weaponMode != 0) ? *reinterpret_cast(reinterpret_cast(object->m_scriptHandle[9]) + 0x1AC) : *reinterpret_cast(reinterpret_cast(object->m_scriptHandle[9]) + 0x1AE); int particleBase = (weaponMode != 0) ? 0x46 : 0x3C; - for (int i = 0; i < static_cast(countC); i++) { + for (int i = 0; i < countC; i++) { int dataNo = object->m_charaModelHandle->GetPdtSlot(); reinterpret_cast(this)->putParticleBindTrace((particleBase + i) | (dataNo << 8), *reinterpret_cast(mon + 0x594), object, kMonObjDefaultScale, 0); } From 9800057ea86230d5883dd92f540db1cfa7798112 Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Sun, 14 Jun 2026 11:57:48 -0700 Subject: [PATCH 3/4] monobj: restructure setRepop particle-base class chain Rewriting the classId dispatch as an explicit (>= 0xA9 -> pbDone) else (pbSet2) chain emits the target's bge branch instead of our blt, matching block layout. setRepop 97.897->97.939, unit 97.925->97.927. Co-Authored-By: Claude Fable 5 --- src/monobj.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/monobj.cpp b/src/monobj.cpp index 03eb615ea3..c3aa2a0232 100644 --- a/src/monobj.cpp +++ b/src/monobj.cpp @@ -670,10 +670,11 @@ void CGMonObj::setRepop(int mode) goto pbDone; } else if (classId == 0xA9) { goto pbSetA9; - } else if (classId < 0xA9) { + } else if (classId >= 0xA9) { + goto pbDone; + } else { goto pbSet2; } - goto pbDone; pbSetA9: particleBase = 0; goto pbDone; From f030f7a8e0035342fdb57f27949f2eac9c592fbf Mon Sep 17 00:00:00 2001 From: Claude Fable 5 Date: Sun, 14 Jun 2026 11:59:39 -0700 Subject: [PATCH 4/4] monobj: cache mlAttackCheck group cursor in wloop The volatile groupCursor was re-read between the groupCount[] index and the increment; reading it once into a local wcursor (keeping the volatile store and the post-store >=8 re-read) matches the target's single-load pattern. mlAttackCheck 96.493->96.702, unit 97.927->97.940. Co-Authored-By: Claude Fable 5 --- src/monobj.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/monobj.cpp b/src/monobj.cpp index c3aa2a0232..c4d14f3980 100644 --- a/src/monobj.cpp +++ b/src/monobj.cpp @@ -1790,12 +1790,15 @@ int CGMonObj::mlAttackCheck(int partyIndex) if (selectorType == 1) { #define groupCursor (*reinterpret_cast(&monObj->m_unk6CC)) wloop: - if (groupCount[groupCursor] == 0) { - groupCursor = groupCursor + 1; - if (groupCursor >= 8) { - groupCursor = 0; + { + int wcursor = groupCursor; + if (groupCount[wcursor] == 0) { + groupCursor = wcursor + 1; + if (groupCursor >= 8) { + groupCursor = 0; + } + goto wloop; } - goto wloop; } int pick = Rand__5CMathFUl(&Math);