PSX Decompilation
This commit is contained in:
parent
56f6099820
commit
bbd29b1f10
25 changed files with 1921 additions and 701 deletions
|
|
@ -231,19 +231,106 @@ Verified first batch landed in the live `CRUSADER.EXE` session on 2026-04-05.
|
|||
- Exercised the new storage-aware prototype route against the two known 16-bit repair cases (`1000:42e2` and `1420:1499`) through the active MCP session. The checked-in source has the new route wiring, but the live GUI plugin still answered with legacy behavior: `/set_function_prototype_storage` returned the old `set_function_prototype` failure body, and `/set_storage_aware_prototype` returned `404 No context found for request`. That confirms the remaining issue is live deployment parity, not endpoint design.
|
||||
- Rechecked the direct callers of `CreateFromSlotIndex`: `Usecode_ItemCallEvent` plus two `Interpreter_NextUsecodeOp` call sites. The `Usecode_ItemCallEvent` path explicitly calls `CreateFromSlotIndex((EntityVmContext *)0x0,0,...)` as an allocate-and-return factory, and the current caller-side uses immediately consume only base `Process`-style fields such as `procid` and termination flags. The two interpreter call sites likewise just store the returned far pointer in `DX:AX` scratch pairs before later base-process handling.
|
||||
- That caller evidence is enough to keep the current conservative return type for now: `CreateFromSlotIndex` is clearly manufacturing an `EntityVmContext`, but promoting the return to `EntityVmContext *` before the inheritance/base-process datatype story is explicit would probably make current caller decompilation less clear rather than more clear.
|
||||
- Verified seventh live batch landed on 2026-04-06 after the refreshed MCP build came up.
|
||||
- Re-exercised `set_function_prototype_storage(...)` in-session on the two known 16-bit repair cases. The route now reaches the real storage-aware implementation and can preserve the explicit `AX:DX` return storage in-session, but two live issues remain: stack offsets at `10` and above currently need `0x` prefixes to avoid landing at `0x10`/`0x12`/`0x14`/`0x16`, and `calling_convention='__cdecl16far'` still normalizes the repaired functions to plain `__cdecl`.
|
||||
- Updated `/Remorse/EntityVmSlotEntry` one step deeper from the `InitSlotOwnerBuffers` and `EnsureSlotChunkLoaded` evidence:
|
||||
- `+0x00 match_key_farptr`
|
||||
- `+0x0a owner_chunk_count`
|
||||
- `+0x12 owner_data_base`
|
||||
- retained the earlier `+0x1e..+0x24` owner-buffer and chunk-state pointer pairs
|
||||
- Updated local variable typing so `AcquireSlotForEntity` now carries `EntityVmSlotEntry *` locals for the current slot cursor/free-slot candidate lane, and `InitSlotOwnerBuffers` now carries an `EntityVmSlotEntry *` local for the owner-metadata scratch object.
|
||||
- The decompiler payoff is immediate: `InitSlotOwnerBuffers` now shows `owner_chunk_count`, `owner_buffer_*`, and `chunk_state_*` directly, and `EnsureSlotChunkLoaded` now shows `owner_data_base` where the slot metadata seeds the later owner-data window.
|
||||
- Tried the stronger storage-aware `Create(this: /Remorse/EntityVmRuntime * @ stack:0x4:4, ...)` model through the new endpoint, but it still fails with `Storage size does not match data type size: 2`. That makes the remaining blocker more precise again: the live MCP route is now good enough to express the desired 4-byte storage, but the current `EntityVmRuntime *` datatype in this 16-bit NE session still resolves to a 2-byte pointer type.
|
||||
- Verified eighth live batch landed on 2026-04-06.
|
||||
- Reloaded the live plugin and re-verified `set_function_prototype_storage(...)` on the two known 16-bit proof cases. The route now works in-session and preserves explicit `AX:DX` return storage cleanly, but `calling_convention='__cdecl16far'` still normalizes both `1000:42e2` and `1420:1499` to plain `__cdecl`.
|
||||
- Renamed `1420:1d72` to `entity_vm_runtime_get_slot_chunk_ptr_at_offset` after confirming from `CreateFromSlotIndex`, `Load`, and `FUN_1418_035f` that it is just a wrapper over `EnsureSlotChunkLoaded` plus a caller-supplied offset.
|
||||
- Renamed `1420:1d8d` to `entity_vm_runtime_release_slot_chunk_ref` after confirming from the `Interpreter_NextUsecodeOp` caller that it decrements one live chunk-state refcount and asserts if the chunk was not retained.
|
||||
- Renamed `1420:1e17` to `entity_vm_runtime_try_unload_slot_chunk` after confirming from `entity_vm_runtime_apply_to_matching_owner_rows` that it only unloads a chunk when the chunk-state count has reached zero, restoring the owner-buffer entry and freeing runtime budget during cleanup/eviction.
|
||||
- Added short decompiler comments to those three helpers so the slot-entry ownership story stays visible in the live database.
|
||||
- Verified ninth live batch landed on 2026-04-06.
|
||||
- Created provisional datatype `/Remorse/EntityVmLoadedChunkRecord` with the current stable cleanup/iterator anchors:
|
||||
- `+0x06 next_offset`
|
||||
- `+0x08 next_segment`
|
||||
- `+0x0e saved_chunk_offset`
|
||||
- `+0x10 saved_chunk_segment`
|
||||
- `+0x12 slot_index`
|
||||
- `+0x14 chunk_index`
|
||||
- Updated `1420:1e17 entity_vm_runtime_try_unload_slot_chunk` so the second parameter is now `EntityVmLoadedChunkRecord * loaded_chunk_record`, and then tightened the return to `byte __cdecl16far` with explicit `AL` storage after caller disassembly at `1420:1f50` and `1420:1fc1` showed both call sites consume only `AL`.
|
||||
- Updated the iterator local `uStack_6` in `1420:1f24 entity_vm_runtime_apply_to_matching_owner_rows` to `EntityVmLoadedChunkRecord *`, so the owner-row cleanup walk now renders `next_*`, `slot_index`, and `chunk_index` directly instead of anonymous stack-pair traffic.
|
||||
- Confirmed the interpreter-side release helper caller at `1418:3330` pushes the live chunk record's `slot_index` / `chunk_index` pair from `ES:[BX+0x32]` / `ES:[BX+0x34]` together with the runtime far pointer before calling `entity_vm_runtime_release_slot_chunk_ref`, which makes the loaded-chunk record a real shared runtime record rather than a one-off cleanup scratch blob.
|
||||
- Verified tenth live batch landed on 2026-04-06.
|
||||
- Renamed local helper `1418:003c` to `interpreter_pop_saved_farptr` after confirming from its only caller in `Interpreter_NextUsecodeOp` that it decrements a saved-farptr stack count at `+0x80` and returns the far pointer stored at the new top entry.
|
||||
- Added short decompiler comments at `1418:003c` and `1418:3330` so the interpreter-side release/restore lane stays visible without overcommitting the restored far pointer to a stronger semantic than the current evidence supports.
|
||||
- Verified eleventh live batch landed on 2026-04-06.
|
||||
- Created class owner `Remorse::EntityVmSlotEntry` in the live database and moved `1420:2040` under it as `CreateOrClear`.
|
||||
- Tightened `Remorse::EntityVmSlotEntry::CreateOrClear` so the single parameter is now named `this` and the explicit far return storage is restored to `AX` for the `EntityVmSlotEntry *` result.
|
||||
- Moved the previously global runtime cleanup helpers under `Remorse::EntityVmRuntime` as real methods:
|
||||
- `1420:1d72` -> `GetSlotChunkPtrAtOffset`
|
||||
- `1420:1d8d` -> `ReleaseSlotChunkRef`
|
||||
- `1420:1cca` -> `DebugDumpSlotMemory`
|
||||
- `1420:1e17` -> `TryUnloadSlotChunk`
|
||||
- `1420:1f24` -> `ApplyToMatchingOwnerRows`
|
||||
- Tightened the `ReleaseSlotChunkRef` parameter names to `runtime_farptr`, `slot_index`, and `chunk_index`, and renamed the `DebugDumpSlotMemory` far-pointer argument to `runtime_farptr` so the runtime-owned chunk/refcount lane reads more like method code than detached helper code.
|
||||
- Verified twelfth live batch landed on 2026-04-06.
|
||||
- Tightened `Remorse::EntityVmRuntime::GetSlotChunkPtrAtOffset` to `dword __stdcall16far GetSlotChunkPtrAtOffset(dword runtime_farptr, int slot_index, int chunk_index, dword intra_chunk_offset)` after re-checking the `CreateFromSlotIndex` and `Load` callers. The current best read is: load/ensure one slot chunk through the runtime, then add a caller-supplied intra-chunk offset pair to the returned far pointer.
|
||||
- Tightened `Remorse::EntityVmRuntime::ApplyToMatchingOwnerRows` to `byte __cdecl16far ApplyToMatchingOwnerRows(dword runtime_farptr, int slot_index_filter, int chunk_index_filter)` after re-checking the `AcquireSlotForEntity` and `EnsureSlotChunkLoaded` callers. The current best read is: iterate the runtime-owned loaded-chunk list either broadly (`-1/-1`) or for one current slot/chunk pair.
|
||||
- Restored explicit return storage after the storage-aware retype pass so `GetSlotChunkPtrAtOffset` still returns its far pointer in `DX:AX` and `ApplyToMatchingOwnerRows` still returns its boolean result in `AL`.
|
||||
- Verified thirteenth live batch landed on 2026-04-06.
|
||||
- Lifted the grouped runtime methods from split-word `runtime_farptr` parameters to explicit 4-byte `EntityVmRuntime * this` storage using `/Remorse/EntityVmRuntime *32` in-session. The live signatures now read as real methods for:
|
||||
- `Create`
|
||||
- `InitSlots`
|
||||
- `ReleaseSlots`
|
||||
- `DebugDumpSlotMemory`
|
||||
- `ReleaseSlotChunkRef`
|
||||
- `GetSlotChunkPtrAtOffset`
|
||||
- `TryUnloadSlotChunk`
|
||||
- `ApplyToMatchingOwnerRows`
|
||||
- `EnsureSlotChunkLoaded`
|
||||
- `Remorse::EntityVmRuntime::Create` is the biggest change in that batch: it no longer needs the old split-word placeholder form and now holds `dword __cdecl16far Create(EntityVmRuntime * this, word owner_type, word owner_id)` with the original `AX:DX` return preserved.
|
||||
- `EnsureSlotChunkLoaded` now also carries the clearer `EntityVmRuntime * this, short slot_index, short chunk_index` signature with the original far-pointer return preserved in `DX:AX`.
|
||||
- `AcquireSlotForEntity` and `InitSlotOwnerBuffers` are now fully over that hurdle too: `AcquireSlotForEntity` returns `EntityVmSlotEntry *32` in `DX:AX`, and `InitSlotOwnerBuffers` now carries `EntityVmSlotEntry *32 slot_entry` as its third parameter.
|
||||
- Verified fourteenth live batch landed on 2026-04-06.
|
||||
- Finished the remaining straightforward VM pointer cleanup outside the hottest runtime helper cluster:
|
||||
- `1430:0000 Remorse::EntityVmOwnerResource::Create` -> `byte __cdecl16far Create(EntityVmOwnerResource * this, dword owner_resource_spec)`
|
||||
- `1430:00fd Remorse::EntityVmOwnerResource::Destroy` -> `Destroy(EntityVmOwnerResource * this, uint destroy_flags)`
|
||||
- `1420:1601 Remorse::EntityVmRuntime::Destroy` -> `byte __cdecl16far Destroy(EntityVmRuntime * this, word destroy_flags)`
|
||||
- `1420:10b6/10da/1162/118f/1278 Remorse::EntityVmContext::{FreeBuffer, SyncGlobalValueAndDispatch, Destroy, Save, Load}` now all carry explicit `EntityVmContext *32 this`
|
||||
- That leaves `CreateFromSlotIndex` as the one clearly still-complex VM signature in this family cluster: the body still shows a far `this`, but the remaining argument pack needs a dedicated caller-side recovery pass rather than another pointer-only rewrite.
|
||||
- Verified fifteenth live batch landed on 2026-04-06.
|
||||
- Recovered the mixed caller pack on `1420:0eec Remorse::EntityVmContext::CreateFromSlotIndex` far enough to replace the old anonymous split arguments with caller-backed names:
|
||||
- `dword owner_source_farptr`
|
||||
- `dword pitemno_farptr`
|
||||
- `word mode_flags`
|
||||
- `word slot_index`
|
||||
- `word value_add_offset`
|
||||
- `word intra_chunk_offset`
|
||||
- `dword ucparam_farptr`
|
||||
- `uint ucparamsize`
|
||||
- Restored explicit far return storage on `CreateFromSlotIndex` to `AX:DX` after the storage-aware apply briefly dropped it.
|
||||
- The same live pass also made the remaining endpoint weakness more concrete again: once the caller-backed custom-storage pack is applied, the endpoint still textualizes the function as plain `dword __cdecl` instead of preserving the earlier higher-level `UsecodeProcess *` / `__stdcall16far` surface, even though the decompiler now keeps the correct argument boundaries and the return really is back in `AX:DX`.
|
||||
- Current best caller-backed read for `CreateFromSlotIndex` is now narrower and more useful than the old placeholder form:
|
||||
- `owner_source_farptr` is a real far-pointer input that is persisted to context `+0x11b/+0x11d`
|
||||
- `ucparam_farptr` is a real far-pointer input copied into the backward-growing buffer at `+0x102`
|
||||
- `slot_index`, `value_add_offset`, and `intra_chunk_offset` are distinct scalar inputs rather than one collapsed anonymous pack
|
||||
- the conservative semantic story is still `factory/setup bridge that returns a far process/context pointer`, not `final inheritance-clean constructor signature`
|
||||
|
||||
Current live datatype state:
|
||||
|
||||
- `/Remorse/EntityVmOwnerResource` is the cleanest landed class in this lane so far.
|
||||
- `/Remorse/EntityVmRuntime` currently only freezes the stable tail fields and helper pointer, not the full slot-entry schema.
|
||||
- `/Remorse/EntityVmSlotEntry` now exists as a bounded helper datatype, but only the stable tail buffer-pair fields are named so far.
|
||||
- `/Remorse/EntityVmSlotEntry` now exists both as a bounded helper datatype and as a live `Remorse` class owner. Its current authored surface is intentionally small: one constructor/clear method plus the stable `match_key_farptr`, `owner_chunk_count`, `owner_data_base`, and owner-buffer / chunk-state pointer anchors.
|
||||
- `/Remorse/EntityVmLoadedChunkRecord` now exists as the shared cleanup/iteration record for the chunk-release and conditional-unload lane, with the currently stable next-link, saved-owner-buffer, slot-index, and chunk-index fields named.
|
||||
- `/Remorse/EntityVmContext` now exists and matches the current owned lifecycle cluster, but it still only records the safest field anchors rather than the full embedded mini-VM layout.
|
||||
- `apply_class_layout` succeeded for `Remorse::EntityVmOwnerResource` but failed for `Remorse::EntityVmRuntime` when the binder tried to apply a `this` type, even though plain ownership moves worked.
|
||||
- The old `apply_class_layout` dry-run null failure for `Remorse::EntityVmContext` no longer reproduces on the current live server, but the actual write-side `this` typing path is still effectively old-build behavior: the real apply and direct `set_function_this_type` calls still fail on the existing `UsecodeProcess *` lifecycle signatures with `Storage size does not match data type size: 2`.
|
||||
- The `EntityVmContext` lifecycle signatures are now locally repaired through PyGhidra: `CreateFromSlotIndex` plus `FreeBuffer` / `SyncGlobalValueAndDispatch` / `Destroy` / `Save` / `Load` all carry `EntityVmContext * this` as their first parameter.
|
||||
- `CreateFromSlotIndex` should still keep its conservative `UsecodeProcess *` return type for the moment. The allocate-and-return behavior is clear, but the known callers currently consume it through base-process fields, and the repo does not yet have an inheritance-aware `EntityVmContext : UsecodeProcess` datatype model that would make a promoted return cleaner across the call sites.
|
||||
- `CreateFromSlotIndex` should still keep a conservative semantic return in the notes for the moment. The active live endpoint now textualizes it as `dword __cdecl` after the caller-packed custom-storage cleanup, but the allocate-and-return behavior is clear, the real return storage is back in `AX:DX`, and the known callers still consume the result through base-process fields rather than through an inheritance-aware `EntityVmContext : UsecodeProcess` datatype model.
|
||||
- The runtime lane is now split more accurately: `InitSlots` and `ReleaseSlots` can carry a direct `EntityVmRuntime * this`, while `Create` still needs the split-word custom-storage form to avoid hidden return-storage breakage.
|
||||
- The first slot-entry prototype batch is tighter now that `EnsureSlotChunkLoaded` carries a real `EntityVmSlotEntry *` local on the acquired-slot path, but the wider slot-entry model is still improved rather than finished.
|
||||
- The runtime lane is grouped more accurately too: the chunk-access, chunk-ref release, debug-dump, conditional-unload, and owner-row iterator helpers now sit under `Remorse::EntityVmRuntime` instead of remaining global free functions.
|
||||
- The runtime lane is also typed more accurately now: the chunk accessor is no longer a five-word anonymous wrapper, and the owner-row iterator no longer pretends its runtime pointer is two independent split-word parameters.
|
||||
- The authored VM lane is now much closer to a real class surface than a namespace grouping: `EntityVmRuntime`, `EntityVmOwnerResource`, `EntityVmContext`, `EntityVmSlotEntry`, and the helper `EntityVmLoadedChunkRecord` all now participate in a mostly far-pointer-correct live type model, with `CreateFromSlotIndex` as the main remaining signature outlier.
|
||||
- The slot-entry model is tighter again: beyond the earlier `owner_buffer_*` and `chunk_state_*` tails, the datatype now also exposes `owner_chunk_count` and `owner_data_base`, which makes the allocator/count path in `InitSlotOwnerBuffers` and the owner-data window math in `EnsureSlotChunkLoaded` read as object state rather than anonymous offset pairs.
|
||||
- The adjacent helper map is tighter too: the slot-entry consumer side now has one pointer-plus-offset accessor, one chunk-ref release helper, one conditional-unload helper, and one named loaded-chunk iterator record instead of a mix of anonymous `1420:` placeholders and anonymous stack-pair scratch state.
|
||||
|
||||
Current scope of that batch stayed intentionally conservative:
|
||||
|
||||
|
|
@ -258,9 +345,14 @@ Best immediate next moves after this landed:
|
|||
- inspect `EnsureSlotChunkLoaded` and adjacent `1420:` helpers again now that `AcquireSlotForEntity` returns `EntityVmSlotEntry *`, and push the slot-entry type one step deeper only where the resulting local/object read is genuinely clearer
|
||||
- decide whether `CreateFromSlotIndex` can safely promote its return type from `UsecodeProcess *` to `EntityVmContext *`, or whether it should stay a factory-style bridge that only types `this`
|
||||
- if the context/base-process inheritance story becomes explicit in datatypes, revisit `CreateFromSlotIndex` return typing then; until that point, keep the current `UsecodeProcess *` return even though the body itself clearly builds an `EntityVmContext`
|
||||
- recover a storage-aware `this`-typing path for `Create` specifically; `InitSlots` and `ReleaseSlots` no longer need to stay in the unresolved set
|
||||
- decide whether `match_key_farptr` at `+0x00` should stay as a neutral far-pointer field or can now be promoted to a stronger entity/owner key name from caller-side evidence
|
||||
- recover a storage-aware `this`-typing path for `Create` specifically; the live route now works well enough to test explicit 4-byte storage, but the remaining blocker is the 2-byte `EntityVmRuntime *` datatype itself rather than endpoint reachability
|
||||
- inspect the broader `Interpreter_NextUsecodeOp` lane around `1418:3330` now that the release call and `interpreter_pop_saved_farptr` are anchored, and decide whether the loaded-chunk record can absorb any more of the surrounding save/restore stack traffic without overfitting transient interpreter locals
|
||||
- redeploy or otherwise verify the live storage-fallback `set_function_this_type` / `apply_class_layout` build, then retry the `EntityVmContext` lifecycle typing pass in-session before dropping back to local PyGhidra
|
||||
- identify one or two additional strongly owned runtime or owner-resource helpers if the live session exposes them cleanly
|
||||
- decide whether `ApplyToMatchingOwnerRows` should keep its current generic split-word parameters under `Remorse::EntityVmRuntime` or whether the first argument pair is now well enough understood to collapse into a typed runtime `this`
|
||||
- decide whether the newly clarified `runtime_farptr` argument on `GetSlotChunkPtrAtOffset` and `ApplyToMatchingOwnerRows` is enough to justify a safe typed-`this` experiment on those methods, or whether the current `EntityVmRuntime *` pointer-size issue still makes the explicit `dword runtime_farptr` form the least misleading representation
|
||||
- use the now-recovered `CreateFromSlotIndex` caller pack as the baseline for any next cleanup, and only chase a prettier return type once the base-process inheritance story is explicit enough to make that promotion a real readability win
|
||||
- keep the masked-create hub and offset-specialized wrapper ladder outside the class until caller-side role recovery is tighter
|
||||
|
||||
## Source-Emission Guidance
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue