9.3 KiB
Editor-Object Visibility In Retail Crusader
Question
Investigate whether the retail game explicitly hides editor-only map objects during gameplay, and whether any built-in debug, cheat, or command-line switch can enable those objects in the normal in-game renderer.
Active analysis target for the binary side was live CRUSADER.EXE in the Ghidra MCP session.
Result
Current best answer:
- Yes, the retail executable explicitly hides editor-tagged shapes in the normal world-item render path, with at least two recovered
SI_EDITORgates. - No built-in retail flag, cheat, or command-line switch has been recovered so far that re-enables those editor objects in the normal in-game renderer.
- The closest confirmed "show editor items" toggle is in ScummVM/Pentagram, not in the original retail executable.
Binary Findings In CRUSADER.EXE
1. The downstream sprite painter explicitly skips SI_EDITOR
The strongest direct proof is live function Item_PaintSprite at 1198:02e4.
Verified decompile behavior:
- It loads the current item's shape number from
g_itemShapeNos. - It resolves the matching
ShapeDataentry fromg_shapeData. - It immediately checks
local_8->flags2 & 1. - When that bit is set, the function returns before caching or drawing the shape.
Relevant instruction window at 1198:0332..033d:
1198:0332 MOV AL,byte ptr ES:[BX + 0x6]
1198:0336 AND AX,0x1
1198:0339 OR AX,AX
1198:033b JZ 1198:0340
1198:033d JMP 1198:0959
1198:0959 is the function epilogue, so the branch is an unconditional early-out for bit 0 of shape byte 6.
This aligns with the existing SI_EDITOR comment at 1198:0339 and with the open-source Crusader typeflag decoders, where Crusader TYPEFLAG.DAT byte 6, bit 0 maps to SI_EDITOR.
2. The paired setup path still processes those items
The neighboring helper Item_SetScreenBoxAndWorldCoords at 1198:095d still computes:
- world coordinates,
- projected screen coordinates,
- bounding boxes,
- and weapon-overlay extents.
That function does not perform an SI_EDITOR check.
Current safest read after the first pass was:
- editor objects remain present in the live item/cache/display-list setup state,
- but the normal sprite paint stage refuses to draw them.
That read turned out to be incomplete rather than wrong.
3. The active world-item render-list builder also skips SI_EDITOR earlier
Follow-up tracing from the live camera redraw path into segment 1180 found a more important upstream gate in the world-item render-list builder.
Relevant instruction window at 1180:0951..095c:
1180:0951 MOV AL,byte ptr ES:[BX + 0x6]
1180:0955 AND AX,0x1
1180:0958 OR AX,AX
1180:095a JZ 1180:095f
1180:095c JMP 1180:0bec
This is the same Crusader TYPEFLAG.DAT byte 6, bit 0 test, but here the consequence is stronger than in Item_PaintSprite: the builder skips the world-item draw-node allocation path entirely before that item can ever reach the normal draw dispatch.
That closes the runtime discrepancy from the first patch attempt. Patching only the later 1198:033b branch changed a real live draw method, but it did not make editor objects visible in-game because the active renderer had already filtered them out earlier at 1180:0951..095c.
4. Why the first executable patch appeared to do nothing
The first public patch only flipped the downstream Item_PaintSprite branch:
1198:033b JZ 1198:0340 -> EB 03
That patch was not dead code. Export relocation evidence still shows the draw-node method slot at 1478:2c1f dispatching to 1198:02e4, so the downstream painter is a real live node callback.
But the active world-item renderer never reached that callback for editor-tagged shapes, because the upstream builder branch at 1180:095a..095c had already skipped node creation.
Current patching implication:
- patching
1198:033balone is insufficient, - the upstream
1180:095abranch is the controlling visibility gate for normal world-item rendering, - and a practical visibility patch should flip both recovered
SI_EDITORbranches together.
5. The recovered item-flag helpers match the same shape-bit model
Item_GetTypeFlagCrusader reads arbitrary shape/typeflag bits from the per-shape ShapeData records.
Additional direct flag helpers nearby include:
Item_IsTargetable, which readsflags2 & 0x10Item_IsShapeFlagOccl, which readsflags0 & 0x10
That supports the interpretation that Item_PaintSprite is not testing some temporary per-item state. It is reading a stable per-shape editor flag.
Negative Search For A Retail "Show Editor Items" Toggle
I checked the known retail debug/cheat/control lanes already documented in the live database and repo notes.
-debug
Retail -debug is live at 1048:0a93, but the current closed behavior is:
- raise
g_debugMsgLevelto10 - print
Debugging mode ON. - set
1478:0845 - enable the seg1468 video-player timing overlay via
1478:0859
No recovered link from -debug reaches the SI_EDITOR skip in Item_PaintSprite or enables a parallel item-paint path.
Cheat/debug hotkeys
Recovered cheat/debug hotkeys do toggle several overlays, but the confirmed ones are unrelated to editor-shape rendering:
Ctrl+F7at13e8:1a20toggles1478:0ee0, the egg-hatcher trigger-range overlay.Alt+F7at13e8:1a50toggles1478:2bc9, another cheat-gated overlay lane.- The remaining F7-family toggle uses
1478:2bcafor the coarse grid overlay.
Those paths force camera redraws, but the recovered behavior is overlay drawing, not "draw editor-tagged world items."
Hidden usecode debugger / Laurie lane
The hidden seg109/seg1408 usecode-debugger lane remains real, and -laurie plus the cheat/debug latches still enable related hidden behavior. But no recovered debugger-side state or menu action currently bypasses the Item_PaintSprite editor skip, and no candidate global has been found that matches ScummVM's later showEditorItems concept.
Event 0x410
This lane remains unrelated.
Current live conclusion is unchanged:
- retail
0x410toggles the CD transfer display state, - it is not the immortality toggle,
- and it is not an editor-object visibility switch.
Cross-Check Against Open-Source Engine Behavior
ScummVM and Pentagram both independently preserve the same semantic meaning for the Crusader editor flag.
Flag mapping
In both codebases, Crusader TYPEFLAG.DAT byte 6, bit 0 maps to SI_EDITOR.
ScummVM type_flags.cpp:
if (data[6] & 0x01) si._flags |= ShapeInfo::SI_EDITOR;
Pentagram TypeFlags.cpp:
if (data[6] & 0x01) si.flags |= ShapeInfo::SI_EDITOR;
Runtime treatment
ScummVM game_map_gump.cpp shows the exact higher-level behavior one would expect from the retail binary finding:
if (!showEditorItems && item->getShapeInfo()->is_editor())
continue;
Pentagram documents the same meaning directly in docs/u8typeflag.txt:
bit 4 : editor shape (don't render in-game)
For Crusader, the bit location differs in the later 9-byte Crusader format, but the semantic meaning is the same.
Important limit of this cross-check
ScummVM exposes its own engine variable and debugger command:
- engine field:
_showEditorItems - setter:
setShowEditorItems(bool flag) - debugger command:
showEditorItems [on|off]
That is useful as behavioral confirmation, but it is not evidence that retail CRUSADER.EXE ships with an equivalent built-in toggle.
Conclusion
The retail executable does contain explicit logic to hide editor-only objects during ordinary gameplay rendering.
Current best model:
- map/editor objects exist in the same broad world-item/runtime data flow as ordinary items,
- the active world-item builder in segment
1180checksSI_EDITORand skips draw-node allocation when that bit is set, - if such an item still reached the standard sprite painter,
Item_PaintSpritewould also early-out on the same bit, - and no recovered retail debug/cheat/argument lane currently bypasses either gate.
I did not recover any retail equivalent of:
- a
showEditorItemsglobal, - a command-line switch that enables editor-object rendering,
- a cheat/debug hotkey that enables editor-object rendering,
- or a hidden debugger command that obviously bypasses the
SI_EDITORskip.
So the present evidence supports:
- explicit retail hiding behavior exists,
- but no official or currently recovered internal toggle exists to reveal those objects in the shipped game.
If the goal is to see them in the original executable, the most direct current path is no longer searching cheats or args first. It is either:
- finding a second, debug-only display-list builder that bypasses the
1180:0951gate, or - patching both recovered
SI_EDITORbranches in a writable copy.
Next RE Follow-Up If Revisited
- Recover the exact containing function and wider caller chain for the
1180:0951world-item builder skip and check whether any alternate debug-only builder exists. - Inspect the segment
1180redraw/display-list builders for a second path that draws world items outside the normal world-item allocation branch. - If a runtime proof is wanted, patch both recovered
SI_EDITORbranches only on a writable executable copy and test whether editor shapes become visible without destabilizing collision or selection.