- Megamap / TAB map zoomed view: heroes' markers and the other symbols (integer 200h centre immediates) follow the view's centre. - Map reveal: the hero's reveal stamp scaled 10x (mods/mapreveal.cpp, docs/map-reveal.md); creatures on the zoomed map shown within 10x the sight range. - Load / save progress screen drawn on the rock background across the full width, the picture blended over it (mods/loadingscreen.cpp); the classic 1024x768 frame is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
6.1 KiB
16:9 menu screens
Request (2026-10-20): the game's menu screens are laid out for 1024x768; we
design our own UIs for them. There is no 16:9 artwork for the game, so the
background is our own, and the approach is shared by all menu screens. The
background (user, 2026-10-20: "textured dark", the flat gradient looked
black): the options window's rock wall, GUI_OPTION_BACKGROUND<row><column>.TGA
(4 x 3 tiles of 256), scaled to cover the render target, tinted down,
shaded towards the bottom and the sides. Game textures by name:
game/ui/texture.h, drawn with game::DrawTextured (game/ui/draw.h). Target: 16:9, 1920x1080, which is
1365x768 in UI units; wider screens only get more background at the sides
(not designed for ultrawide).
How a screen works
mods/screen.{h,cpp}: a screen replaces a full-screen window's drawing and mouse handling. Its render hook callsscreen::Render(window, device, body, context): the background across the whole render target, then the body in canvas coordinates (1365x768, centred:hud::RenderCanvas, the HUD layer's offset machinery withAnchor::Canvas; drawing, the cursor and the window's hit tests shifted alike). Mouse events go throughscreen::Handle(hud::HandleCanvas). Keys stay the window's.- The main menu thread renders the full width (no 4:3 frame any more).
- Parts:
screen::Panel(dark backdrop and the game's frame,cUI_Frame, game/ui/frame.h, made anew when its rect changes),screen::Button(a button of the game's with the look of one of the window's,game::NewButtonLike),screen::Text,screen::Fill,screen::DoubleClick. Spacing constants from measurements: frames reach 0x20 beyond their rects and need a height of about 0x40, buttons reach 0x21. Frames are built of 64-unit pieces: widths and heights in steps of 64 (screen::kFrameStep), other sizes leave gaps (screenshot 2026-10-20). - Fonts (logged 2026-10-20): font 0 is another class (no line height field); the TrueType fonts 1..7 have line heights 20, 19, 25, 31, 25, 28, 13. Screens use font 1; 4 or 6 would suit headings.
- Inside the canvas scope the HUD layer does not stretch "full 1024 layout"
quads (
g_canvasScope).
Main menu frame (2026-10-20)
Request: the background on all screens, the main menu's and the options window's own pictures removed.
- cUI_Manager's UI render (
0x7587b0, hooked in mods/screen.cpp) on the menu thread: the background first, thenhud::RenderMenuFrameruns the render with drawing shifted by (render width - 1024) / 2 and a viewport on the frame (3D parts). Windows inside draw in frame coordinates (their own HUD scopes are nested, so they do nothing). - Mouse positions are given to the game in frame coordinates: the
borderless mod's
ToGamesubtractshud::MenuFrameOffsetX. The cursor sprite (cMouseCursor::DrawItem0x6555e0, drawn after the UI) is shifted by drawing only. - While a 16:9 screen is shown the frame is not shifted (offset 0): the screen draws itself across the width.
- Full-screen windows in a game (options,
hud::RenderFramed) get the background beside the frame instead of black. - The windows' pictures are left out by texture: the HUD layer tracks the
texture bound to stage 0 (
SetTexture, device vtable 35) and skips quads drawn with a hidden one (hud::SetHiddenTextures). Logged on the menu thread (texture ids requested from the cache, by caller; names by trying the names in the texture pak): main menu GUI_UW_OPTION1..12 + UI_MAIN_SKY, options UW_OPTION_1_01..12. This install uses the Underworld versions; the Ancaria ones (GUI_OPTION1..12, ...) were not seen and are not listed. - The main menu's 3D scene (sky UI_UW_MAIN_CENTER, water with the SACRED logo UI_MAIN_REF; render 0x75e620 on the scene object 0x75df10) is called from cUI_MainMenu::Render (0x7122c0) at 0x712bd9; that call is redirected to an empty function. cUI_Character (0x70f41b) still draws it.
- Logo top left (2026-10-21), 48 from the edges, 124 high: FX_SACREDLOGO.TGA,
the emblem (horns around a ring of runes) glowing blue on black without
alpha, drawn added (blend ONE/ONE,
game::DrawTexturedAdded) as the game's effects draw it. Other candidates: GUI_MAIN_LOGO (plain golden lettering), SACREDSYMBOL01/02 (model atlases), the emblem on the loading pictures (PAK\loading*.bmp, not in the paks). Screens may overlap it.
Screens
- Spielen (the load window, cUI_Savegame): docs/characters.md, "Spielen screen".
Fixes (2026-10-21)
- The main menu came back unframed (old pictures, frame at the left) after a
game: the set of shown 16:9 screens kept a window of the in-game UI that
was destroyed while shown. Now only screens drawn on the menu thread count,
and an entry expires after 2 menu frames without being drawn
(
screen::BeginMenuFrame). - Dialogs over a 16:9 screen in the main menu (e.g. "Spielstand laden?") sat
at the left with the dimming 1024 wide:
hud::OffsetForgave every window offset 0 while the menu showed. Now only while the menu frame is drawn centred (it shifts the windows itself); otherwise dialogs are centred and their full-layout dimming stretched, as in a game.
Load / save progress screen (2026-10-25)
Request: the progress screen shown while loading / saving should use the
menu screens' background. The game's screen (DxDriver7::LoadingScreen
0x6469d0, thiscall (progress, text)) draws with GDI into the back buffer's
DC (surface +0xbc, GetDC vf 0x44 / ReleaseDC vf 0x68): the 1024x768 picture
(HBITMAP +0x200) at 0, 0, the bar (+0x204 / +0x208) and the text at y 700,
then Flip; it redraws only when the bar moves. Until now it was presented as
a 1024x768 "classic" frame scaled to the monitor.
mods/loadingscreen.cpp: before the game's drawing, DrawBackground across
the whole render width in a scene of its own (DxDriver7 BeginScene
0x646f50 / EndScene 0x646fd0); the game's GDI drawing is moved to the
centred 1024 frame with SetViewportOrgEx on the back buffer's DC, caught in
CreateCompatibleDC(hdc) which the game calls right after getting it. Every
frame is now presented at the full render width (borderless.cpp has one
layout).