# 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 ±267*zoom, y ±200*zoom, 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).