Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Engine: graphics ports

Ports

  • basePort (0x486318-0x4887f4). Ports are QuickDraw's GrafPorts over a GDI DC: 0xc0 bytes, tagged 'Port' after the vtable pointer, in a list from graphics.ports. The port keeps its state (palette, background colour, font, pen, clip region) in its own fields and selects it into the DC only while locked: setupDC (slot 4) reads the DC's depth, maps the frame onto the bounds (MM_ANISOTROPIC when their sizes differ), and selects the palette, colours, pen and font; cleanupDC (slot 7) takes them out again, and unlock (slot 34) deletes the DC at the last unlock. The clip region is converted to an HRGN lazily (prepare, slot 8, before each drawing call). The pen (+0x54) is a position, a colour, a mode (setMode, slot 15, maps modes 0-7 to R2_ codes) and a width (the engine's setPenWidth, 0x48d90c, formerly thought to set a mode). Transfer modes 0-7 map to raster operations through two tables: 0x4a8b18 for bitmaps (SRCCOPY, SRCAND, SRCPAINT, ...) and 0x4a8af8 for brushes (PATCOPY, ...). Mode 8 draws with colour 0 transparent (drawMasked, slot 35: AND with a mask, then OR). The base class's slot 25 (lock) is the runtime's pure-virtual stub.
  • DIB (0x489148-0x48988a). A helper class (RTTI name DIB, 0x30 bytes, 9 virtual methods, no destructor) around a DIB section, which ports use for packed pixels and for flipped stretches that devices might not do. It keeps two headers: one with palette indices for colours (DIB_PAL_COLORS), one with RGB colours. The module also holds the 16.16 fixed-point helpers (makeFixed, fixedToInt, fixedFraction, fixedRound, 0x48988a-0x4898b6).
  • Inline functions out of line. The ports' modules call small functions that are inline in any sensible header: Rect() (0x48ab89), Rect::operator= (0x48ab91), a Rect from a plain rectangle (0x48a667, a memcpy of 8 bytes, used where the game's code expands the same constructor inline), Pt() (0x488786), Pt::operator= (0x4887ab) and the pen's constructors (0x48878e, 0x4887c4). Each exists once, in the module of the last port class that uses it, which is how virdefs (Borland's out-of-line copies of inline functions) would be kept if the linker kept the last copy. Color's copy constructor, meanwhile, is expanded inline in the same modules. decomp/zoombinis.h declares the Rect conversion out of line when RECT_OUT_OF_LINE is defined (the port modules) and inline otherwise.
  • DIBPort and DIB8Port (0x48a720, 0x48990c). A DIBPort draws with GDI into its DIB's section; DIB8Port (kind 1) also draws into the bits itself, one rectangle of the clip region at a time, for copies between 8-bit DIB ports sharing a palette (through a 38th virtual method, drawBits), plain, 1-bit and packed pixels, and filled rectangles, calling GdiFlush first if GDI has drawn since. Its blitters (0x48990c with its inner loop 0x4899ed, 0x489a2d, 0x489aad) are hand-written assembly (rep movs/stos, loop, a jump through ebx to pick the loop, byte-swapped dwords for 1-bit images) and decompiled as functional C++.
  • Startup and exit functions. A global object with a constructor or destructor (iniState and files, whose members are fileSpecs) makes BCC32 compile the calls into unnamed functions after the module's code, listed in the object's _INIT_ and _EXIT_ segments (6-byte entries: a calling convention byte, a priority byte, the address) and run by the startup code; in the game they sit at the end of their modules (0x480763/0x480773, 0x484191/0x4841c2). files (0x4b9b6c) is defined in the file layer's module, whose startup code builds its four fileSpecs.
  • Implicit destructors. Classes that declare no destructor under a base with a virtual one get one from the compiler (37-38 bytes: if this isn't null, call the base destructor with flags 0, then the class's operator delete if bit 0 of the flags is set). BCC32 emits it in each object that needs the class's vtable, and the copy linked is the last module's (displayPort::~displayPort, 0x48dfff, sits in windowPort's module). All 17 in the port and async file classes match, measured through @zoombi32-implicit markers; a modern compiler generates its own from the same declarations.