Skip to content

Writing a Glide 2 replacement for an early Glide game ​

What to know ​

A game that draws everything through Glide can be drawn at any resolution by replacing the library: the game passes screen coordinates, colours and texture memory, and nothing else depends on the Voodoo's 640 × 480. POD's 3dfx build runs unchanged through GameFrame's wrappers/glide (Rust, built for 32-bit Windows, OpenGL). What mattered, each observed or measured there:

  • The file and the names. Early Glide 2 games import glide.dll, not glide2x.dll, by decorated __stdcall names (_grGlideInit@0, _grSstOpen@24). Export exactly those: list them with peinfo --imports and strings, and write them into the .def file.
  • No window. The early grSstOpen(res, refresh, format, origin, smoothing, buffers) takes no window handle: a Voodoo drew full screen. Find the game's own window (by class, even while hidden: POD calls Glide before it shows the window) and draw into it.
  • List the calls with their arguments first. A capstone scan of every call site, reading the constants pushed before it, gives the game's whole use of the card in one table (POD: 47 calls, 360 sites): which combiner settings, blend factors, depth mode, fog, texture formats and LFB modes need to be right, and which never occur.
  • More than one thread. Games call Glide from a loading thread too. An OpenGL context belongs to one thread: record every call as a command and replay on one render thread, answering only queries (grSstScreenWidth, grTexCalcMemRequired, grLfbGetReadPtr) at once.
  • The LFB. The write pointer has a fixed stride of 1024 pixels (2048 bytes at 16 bits, 4096 at 32), and a game may set the write mode after taking the pointer. Hand out a buffer filled with a marker and read what changed at grLfbEnd. Reads of the depth buffer exist (POD's lens flare tests for 0xffff): copy the depth down to the game's resolution.
  • Depth. Map the W buffer to 1 - oow and the Z buffer to ooz / 65535, so Glide's compare functions are OpenGL's as they are; turn on depth clamping.
  • Texture coordinates. sow/tow run 0–256 across the longer side, divided by w; pass s·w as a perspective-correct varying and the colours noperspective, as Glide does.
  • Gamma belongs in the final copy to the window (the Voodoo's output table), not in the blending.
  • Software OpenGL under an emulator is slow. Mesa's llvmpipe in a QEMU-emulated PC drew the menus at 2–5 frames a second; LP_NATIVE_VECTOR_WIDTH=128 roughly doubled it. Log frames per second and where the time goes from the start.

Code: Apache 2.0. Content: CC0 1.0. No game material: bring your own copy.