fix(ui): night-round review — F8 House not-expired purchase-restriction text

gmHouseUI::DisplayPurchaseTimeText @0x004a3110's not-yet-expired
branch was wrongly marked "unrecoverable from this decomp dump" — a
direct capstone disassembly resolves all three concatenated pieces:
prefix "You may buy another landscape house at " @0x7ab790 (pushed
@0x004a3265), the strftime "%c" format literal @0x7ab7ec (pushed
@0x004a321d) applied to localtime(timestamp + 0x278d00) — the expiry
moment, 30 days after the purchase timestamp — and suffix ". This
restriction does not apply to apartments." @0x7ab7b8 (pushed
@0x004a3235).

Ported in RuntimeHouseState.Recompute, substituting .NET's
culture-default DateTime.ToString() for the CRT's strftime("%c", ...)
(different formatting engine, same "process locale, full date+time"
intent) — filed as register row IA-23 (an approximation, not a gap).
TimeProvider.LocalTimeZone (overridable, defaulting to
TimeZoneInfo.Local in production) keeps the conversion deterministically
testable while matching retail's own localtime() call.

Updated RuntimeHouseStateTests: the not-expired case now asserts the
composed prefix/suffix structure and the exact expiry instant (pinned
via a UTC-fixed test TimeProvider), replacing the old "renders nothing"
assertion. Un-claimed "unrecoverable" in ISSUES #413 item 2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-17 04:50:36 +02:00
parent ab84b54dfa
commit df062d2eda
4 changed files with 110 additions and 22 deletions

View file

@ -26,9 +26,10 @@ What does NOT go here:
## #413 — House tab shows no content (owned-house display, six Display* line builders unported)
**Status:** NARROWED 2026-08-17 (House-tab ownership-text closer session).
Items 1 and 2 below are DONE; item 3 (six owned-house-only builders) remains
OPEN and is the entire remaining scope.
**Status:** NARROWED 2026-08-17 (House-tab ownership-text closer session);
item 2's not-expired branch closed same-day at the night-round review fix
round (F8). Items 1 and 2 below are DONE; item 3 (six owned-house-only
builders) remains OPEN and is the entire remaining scope.
**What's shipped (this session, on top of Batch C's mount + parser
groundwork).**
@ -55,9 +56,20 @@ groundwork).**
character (no `HousePurchaseTimestamp` ever set) shows **exactly one
line**: "You may buy another house immediately." — matching this issue's
OWN original acceptance-test wording below, byte-verified against
`data_7ab7f0` in the decomp. The not-expired `strftime`-formatted branch
stays unported (its format string is BN-unrecoverable) — renders no
line, not a guess.
`data_7ab7f0` in the decomp. **The not-expired `strftime`-formatted
branch is now ALSO ported (night-round review, F8, 2026-08-17) — the
"BN-unrecoverable format string" claim was wrong.** A direct capstone
disassembly of the raw bytes at `gmHouseUI::DisplayPurchaseTimeText`'s
not-expired branch resolves all three literal pieces retail
concatenates: prefix `"You may buy another landscape house at "`
(`data_7ab790`), the `strftime("%c", ...)`-formatted expiry moment
(`timestamp + 0x278d00`, i.e. 30 days after the purchase timestamp), and
suffix `". This restriction does not apply to apartments."`
(`data_7ab7b8`). `RuntimeHouseState.Recompute` now renders this exactly,
substituting .NET's culture-default `DateTime.ToString()` for the CRT's
`strftime("%c", ...)` (a different formatting engine, same "process
locale, full date+time" intent — filed as register row IA-23, an
approximation, not a gap).
**Corrects a framing this session's task brief carried in from outside
this doc**: the brief described retail as ALSO showing a preceding line