Files
sacred_k/docs/widescreen.md
T
khallaandClaude Opus 5.5 b2dc1338d2 Map the world view sizing; add RE tooling
- docs/widescreen.md: render-thread frame, cWorldView0 layout and methods,
  view size = zoom * 1024.0/768.0 float constants and all their users,
  ortho projection extents, open questions (activity radius, buffers).
- tools: find-imm (immediate/regex instruction search), rtti (vtables via
  MSVC RTTI), decompile.ps1 + Ghidra scripts for a persistent project;
  ApplyRtti recovers 410 vtables / ~1200 functions Ghidra misses.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 00:19:52 +02:00

3.6 KiB

Widescreen: how the game sizes its view

Goal: render the world 1:1 at the monitor's native resolution, showing more of the world instead of scaling the 1024x768 image. Render and activity (animation/AI) distance must grow with it. UI keeps its 1024x768 layout.

Frame (render thread)

cEngine::renderThread loop, 0x0060e3f0, per frame:

  1. clear (D3D device +0x28)
  2. updates: 0x401660, 0x640b50, 0x634210, weather 0x417e50/0x41a4d0
  3. world: view->vf14(device) where view = engine[+8 + idx*4] (cWorldView0)
  4. UI: 0x756820()->0x7587b0(device), debug overlays 0x60f3e0/0x60f500
  5. FPS overlay 0x60aa90, DxDriver7::Flip

Skipped entirely while g_appFlags & 0x20000 (app inactive).

World view (cWorldView0, vtable 0x008900f8)

Offset Meaning
+0x14/+0x18 camera position (world pixels)
+0x1c/+0x20 requested camera position (scroll target)
+0xb60 zoom (float, clamped to 0.5 .. 2.0)
+0x96ab0 view width = zoom * 1024.0
+0x96ab4 view height = zoom * 768.0
+0x96ac0 extra rows (4)
+0x96ac8 columns = width/96 + 12
+0x96acc rows = height/48 + 24

Functions:

Address Name Notes
0x00624ae0 cWorldView0::SetupView computes the size fields above from zoom and the float constants 1024.0 (0x0088e6f4) and 768.0 (0x00890040); tile corner offsets ±48.2/zoom, ±24.2/zoom
0x006322b0 cWorldView0::Render (vf14) iso tile grid: tiles 96x48, two staggered half-rows per row (0x62b000), first tile = camera - (width/192, height/96)
0x0062a730 cWorldView0::UpdateCamera (vf0c) scroll blocking against sector edges uses width/2, height/2
0x00628210 cWorldView0::SetZoom clamps zoom, sets the ortho projection for 3D models: x ±267zoom, y ±200zoom, z -600..2500, then calls SetupView
0x00623c40 world -> screen projection x * 1024.0 / (2/P00), y * 768.0 / (2/P11)
0x006426a0 build ortho matrix (l, r, b, t, n, f)

All tile/screen positions are pre-transformed (FVF 0x1c4: XYZRHW, diffuse, specular, tex1); 3D models use the ortho projection.

Users of the 1024.0 / 768.0 float constants

World view (should follow the new size): 0x61e5c2, 0x61e5ec, 0x623c82, 0x623c9c, 0x624af2, 0x624b03, 0x628f65, 0x628f8f, 0x629294, 0x6292bc, 0x62b43a, 0x62dc32, 0x62ea2b, 0x62ea5e, 0x62f30d, 0x62f345, 0x630656, 0x63068a, 0x630f3f, 0x630f77 (mostly on-screen clip tests).

Elsewhere (unknown / UI, leave alone for now): 0x40694a, 0x4ec036, 0x593c25, 0x593c3a, 0x6ccb87, 0x6ce156, 0x758a34, 0x75f79a, 0x75f7b8.

Ortho projection extents (±267 / ±200 pushed as floats)

0x60c1f7, 0x60da54, 0x625039, 0x6283b3, 0x62858d, 0x628d3b.

Renderer

DxDriver7::SetDisplayMode (0x00645390) creates back buffer, z-buffer and D3D viewport from DxDisplayMode::width/height (hardcoded 1024x768 by InitGame, 0x00815620, which also calls ChangeDisplaySettings(1024x768) in fullscreen).

Fixed 1024x768 elsewhere (later)

  • 0x00613710 engine capture (save-game thumbnail), 0x006483f0 TGA writer
  • 0x0060e3f0 GDI BitBlt of a 1024x768 bitmap (startup/movie path)
  • 0x00627260 name/HP labels while Alt is held (no constants, uses view)

Open questions

  • Activity radius: which creatures/objects are updated and animated (cWorld / cSector, 0x00603e90 = player?, 0x005fe060 = object by id).
  • Fixed-size per-view buffers (e.g. +0x80e40, 5 vectors at +0x96ad0 with capacity 0x200) - do they overflow at 3440x1440 (47 columns x 54 rows)?
  • Mouse picking (screen -> world).