Wing Commander II
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
game.h
Go to the documentation of this file.
1/*
2 * ============================================================================
3 * | WINGLEADER |
4 * | The 3D space combat simulator |
5 * | |
6 * | A game of interstellar fighter conflict. |
7 * | |
8 * | (c)1989,1990 Chris Roberts. All rights reserved. |
9 * ============================================================================
10 *
11 * Shared declarations for the Wing Commander (Kilrathi Saga, Win32)
12 * reconstruction. The banner above is reproduced from the leaked original
13 * main-module header; the module name in that file was
14 * "MAIN GAME C SOURCE MODULE (Main loop etc.)".
15 *
16 * The core is C, ported from 16-bit DOS sources. `int` was 16 bits in the
17 * original, so nearly all game state is `short` here. Using `int` where the
18 * original used a 16-bit type produces 32-bit operations and breaks the
19 * instruction comparison -- see AGENTS.md.
20 */
21#ifndef GAME_H
22#define GAME_H
23
24#include <windows.h>
25#include <ddraw.h>
26#include <mmsystem.h>
27#include <conio.h>
28#include <direct.h>
29#include <io.h>
30#include <ctype.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <math.h>
34#include <stdarg.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <time.h>
39
40/* The original stores addresses in dwords -- IdentityDword is its identity
41 * helper for them, and the high-memory paragraph is one such address. A dword
42 * is exactly a pointer on Win32; on LP64 it is half of one, so anything that
43 * has to hold an address takes this alias instead and keeps the reference
44 * build's `unsigned int` untouched. */
45typedef unsigned int DwordPtr;
46
47/* The in-flight replay snapshots 0x493130-0x4961A4 -- a contiguous 12404-byte
48 * span of the original's .data -- in single copies, and restores it the same
49 * way. The reconstruction declares that span as several hundred separate C
50 * objects, and no linker is going to lay them out in the original's order, so
51 * the copies would move unrelated memory in either direction. The port leaves
52 * the replay recording alone rather than write the wrong bytes to disk and
53 * read them back over its own globals; restoring it needs the whole span laid
54 * out contiguously first. */
55/* The span runs from g_dwCannedSceneSnapshotStart up to the marker
56 * g_dwCannedSceneSnapshotEnd, which follows
57 * g_asViableTargetDistance just before the sound lists at 0x4961A8.
58 * The original computes the width as the difference of the two marker
59 * addresses (MOV EAX,0x4961A4 / SUB EAX,0x493130 at every use); the port,
60 * whose globals are laid out by the host linker, spells out the width. */
61#define CANNED_SCENE_SNAPSHOT_BYTES \
62 ((char *)&g_dwCannedSceneSnapshotEnd - \
63 (char *)&g_dwCannedSceneSnapshotStart)
64
65/* Loading an object-type record. The record on disk has the original's
66 * layout: 0xF3 bytes, with the animation, shapeSet and shape pointers taking
67 * four bytes each. The reference build's struct matches that exactly, so the
68 * packet is read straight into it. On LP64 the same struct is wider and every
69 * field past `animation` sits four bytes late -- weaponLoadout among them,
70 * which is why a ship loaded with no guns -- so the port unpacks instead. The
71 * three pointer fields are junk in the packet and every caller overwrites them
72 * immediately, so neither path preserves them. */
73#define LOAD_OBJECT_TYPE_RECORD(fileName, section, record) \
74 LoadPacketIntoBuffer((fileName), (section), (record), 0)
75
76/* One mouth position per cinematic frame is what the original animates.
77 * Nearly every entry in the mouth-duration table is a single 60Hz tick, so
78 * without a floor the clock gate only bites at 60 positions a second --
79 * the port has to name a cadence instead of inheriting one from however
80 * fast the host happens to draw, or the mouth runs the line out well
81 * before the speech does. Was 3 ticks (one frame at 20fps, the rate
82 * PlayRawSpeechBuffer sets while speech is playing) -- correct for
83 * voiced lines, where actual audio length is the real pacing reference
84 * regardless of this floor's exact value, but unvoiced lines have
85 * nothing else limiting their pace, and 3 measured twice too fast there.
86 * 6 ticks (10 positions/sec) is the current best empirical value for the
87 * unvoiced case; not derived from a DOS trace. */
88#define CUTSCENE_MOUTH_MIN_TICKS 6
89
90/* Same class of bug as CUTSCENE_MOUTH_MIN_TICKS above, but for the general
91 * sprite/plane wait opcodes (0x44, 0xaa) that every cutscene object -- not
92 * just the speaker's mouth -- uses to pace its own script. A script-authored
93 * wait of a tick or two relied on the DOS host's own draw speed to look
94 * right; the port's clock gate can resolve it dozens of times a second.
95 * Starting from the mouth's proven value as a first guess, not tuned
96 * separately yet. */
97#define CUTSCENE_SPRITE_MIN_TICKS 6
98
99/* Tables of host pointers -- scene and cutscene resources, packet reference
100 * groups -- are sized four bytes an element throughout, because that is what a
101 * pointer was. On LP64 the same table has to be twice as wide or every entry
102 * past the first runs off the end of the allocation. */
103#define HOST_POINTER_SIZE 4
104
105/* Degrees are the angular unit throughout the game core (the constant lives at
106 * DAT_004631b0 in the original); the trig shims convert on the way in. */
107#define DEG2RAD 0.017453292519943295
108
109/* The DirectDraw back end uses this release-and-clear shape for its surfaces. */
110#define COM_RELEASE(surface) \
111 do { if ((surface) != 0) { IDirectDrawSurface_Release(surface); (surface) = 0; } } while (0)
112
113/* --------------------------------------------------------------------------
114 * Original 16-bit-era type spellings.
115 * -------------------------------------------------------------------------- */
116typedef short INT16;
117typedef unsigned short UINT16;
118typedef unsigned char UINT8;
119typedef signed char INT8;
120
121typedef struct IxSound IxSound;
122typedef struct IxSample IxSample;
123
124/* The game-side wave unit inspects the leading public fields and invokes the
125 * selected methods declared here. The IX implementation owns the complete
126 * C++ object layout. */
127struct IxSample {
128 unsigned int flags;
129#ifdef __cplusplus
130 inline void ix_sample_set_looping(int enabled);
131 int ix_sample_load_wav(void *data, int bytes);
132 int ix_sample_load_raw(void *data, int bytes, int frequency,
133 int bitsPerSample, int channels);
134#endif
135};
136
137struct IxSound {
138 unsigned int flags;
140#ifdef __cplusplus
141 void ix_system_sound_set_volume(unsigned short volume);
142 void ix_system_sound_set_pan(unsigned short pan);
143 void ix_sound_set_delete_on_stop(int enabled);
144#endif
145};
146
147/* The DOS rasteriser passes this record to every drawing primitive. Its
148 * offsets are fixed by the accesses in the 0x00440C00-0x00441A8F block. */
149typedef struct Viewport {
150 unsigned char *pixels; /* +0x00 */
151 unsigned short *rowOffsets; /* +0x04 */
152 short left; /* +0x08 */
153 short top; /* +0x0A */
154 short right; /* +0x0C */
155 short bottom; /* +0x0E */
156 unsigned char *allocation; /* +0x10 */
158
159#define SPRITE_ROW_OFFSET(viewport, row) viewport->rowOffsets[row]
160
161/* InflightComputer snapshots 0x005C8470-0x005C8490 with eight MOVSDs and
162 * one MOVSB. The cursor shape is at +0x0D in the allocated copy too. */
163#pragma pack(push, 1)
164typedef struct MouseCursorState {
165 volatile short x; /* +0x00 */
166 volatile short y; /* +0x02 */
167 unsigned char field_4; /* +0x04 */
168 unsigned char field_5; /* +0x05 */
169 unsigned char field_6; /* +0x06 */
170 unsigned short field_7; /* +0x07 */
171 unsigned int field_9; /* +0x09 */
172 unsigned char * volatile shape; /* +0x0D */
173 short frame; /* +0x11 */
174 void *scratchBuffer; /* +0x13 */
175 struct InputPumpContext *context; /* +0x17 */
176 unsigned char field_1b[6]; /* +0x1B */
178
185
186#pragma pack(pop)
187
189 sizeof(MouseCursorState) == 0x21 ? 1 : -1];
190
191/* The event manager keeps a fixed pool of doubly-linked input records. */
192typedef struct InputEvent {
193 short type; /* +0x00 */
194 short x; /* +0x02 */
195 short y; /* +0x04 */
196 short value; /* +0x06 */
197 unsigned int modifiers; /* +0x08 */
198 unsigned int timestamp; /* +0x0C */
199 short primaryButton; /* +0x10 */
200 short secondaryButton; /* +0x12 */
201 unsigned int field_14; /* +0x14 */
202 unsigned int field_18; /* +0x18 */
203 unsigned int status; /* +0x1C */
204 struct InputEvent *next; /* +0x20 */
205 struct InputEvent *previous; /* +0x24 */
207
208/* WC2 widens the event type and aligns the public event record. value and
209 * status are also written together as a 32-bit value at several call sites. */
210typedef struct InputEventState {
211 int type; /* +0x00 */
212 short value; /* +0x04 */
213 short status; /* +0x06 */
214 unsigned int timestamp; /* +0x08 */
215 unsigned short modifiers; /* +0x0C */
216 short x; /* +0x0E */
217 short y; /* +0x10 */
219
220/* One sampled joystick position and its button mask. */
221typedef struct InputDeviceSample {
222 int x;
223 int y;
224 unsigned int buttons;
226
227/* Linear 8-bit raster target and its active clipping rectangle. */
228typedef struct RasterSurface {
229 unsigned char *pixels;
235
243
244/* One transformed corner used by the hand-written RLE scan converter. The
245 * third word is deliberately unused; the retail workspace advances through
246 * these records with a 20-byte stride. */
254
255/* Cached shape frames use the renderer's row-oriented RLE representation.
256 * The four signed bounds are relative to the shape origin; the byte stream
257 * for the first row begins immediately after this 24-byte header. */
258typedef struct RLEFrameHeader {
259 short height;
260 short width;
263 int left;
264 int top;
265 int right;
267}
269
270/* One scratch glyph bitmap used while drawing the packed game fonts. The
271 * renderer stores a pointer-to-pointer to this record in TextContext because
272 * the DOS implementation could move the backing allocation. */
273typedef struct FontWorkspace {
274 int width;
276 unsigned char *pixels;
278
279/* Packed text renderer state. The Win32 port retained the DOS byte layout:
280 * the draw colour is at +0x0C, the optional text pointer at +0x0E and the
281 * horizontal alignment byte at +0x16. */
282#pragma pack(push, 1)
283typedef struct TextContext {
284 Viewport *viewport; /* +0x00 */
285 short cursorX; /* +0x04 */
286 short cursorY; /* +0x06 */
287 unsigned char *font; /* +0x08 */
288 unsigned char colour; /* +0x0C */
289 unsigned char backgroundColour; /* +0x0D */
290 char *text; /* +0x0E */
291 char *textCursor; /* +0x12 */
292 signed char alignment; /* +0x16 */
295
296/* One of six numeric cockpit readouts. The packed ten-byte stride is used
297 * directly by the original renderer at 0x00438454-0x004385B3. */
298typedef struct CockpitReadout {
299 TextContext *context; /* +0x00 */
300 short x; /* +0x04 */
301 short y; /* +0x06 */
302 short previousRight; /* +0x08 */
304
305/* Saved background and text state for the centred modal message panel. The
306 * unaligned Viewports are inherited from the packed DOS layout. */
307typedef struct ModalTextPanel {
308 TextContext context; /* +0x00 */
310 Viewport viewport; /* +0x2F */
312 short left; /* +0x47 */
313 short top; /* +0x49 */
314 short right; /* +0x4B */
315 short bottom; /* +0x4D */
317
318/* One flashing cockpit/VDU message. Two adjacent records begin at
319 * 0x005D1D40; the unaligned text pointer at +0x0D is intentional. */
320typedef struct HudMessageSlot {
321 TextContext *context; /* +0x00 */
322 short x; /* +0x04 */
323 short y; /* +0x06 */
324 short colour; /* +0x08 */
325 short drawColour; /* +0x0A */
326 signed char flashCount; /* +0x0C */
327 const char *text; /* +0x0D */
329#pragma pack(pop)
330
332 sizeof(CockpitReadout) == 0x0a ? 1 : -1];
333
334/* Runtime wave-cache node. The name pointer and next link are established by
335 * the allocation/free paths at 0x0042B1F0 and 0x0042B300; the sample pointer
336 * at +0x08 is established by playWAVE. */
344
345/* One transient IX sound and its link in the game-side active-sound list. */
350
351/* Metadata for allocations surrounded by the 0x400-byte 0xAB guard regions
352 * checked by ReportHeapGuardCorruption. */
358
359/* One pointer retained by the debug heap after the underlying block is freed. */
364
365/* Win32 developer console. The constructor/destructor and member-call ABI in
366 * the shipped image identify this small utility as C++ even though the game
367 * itself remains C. The 0x400-byte formatting area fixes the complete 0x45C
368 * object layout used by the 0x0041C760 debug-overlay unit. */
369typedef struct DebugOverlayConsole {
370 int columns; /* +0x000 */
371 int rows; /* +0x004 */
372 int cursorColumn; /* +0x008 */
373 int cursorRow; /* +0x00C */
374 HWND window; /* +0x010 */
375 char formatBuffer[0x400]; /* +0x014 */
376 char *textBuffer; /* +0x414 */
377 char *dirtyLines; /* +0x418 */
378 int characterWidth; /* +0x41C */
379 int characterHeight; /* +0x420 */
380 int busyWait; /* +0x424 */
381 int reverseVideo; /* +0x428 */
382 COLORREF textColor; /* +0x42C */
383 COLORREF backgroundColor; /* +0x430 */
384 int backgroundMode; /* +0x434 */
385 int field_438; /* +0x438 */
386 int field_43c; /* +0x43C */
387 int field_440; /* +0x440 */
388 int field_444; /* +0x444 */
389 int field_448; /* +0x448 */
390 HANDLE mutex; /* +0x44C */
391 int animationState; /* +0x450 */
392 int spinnerIndex; /* +0x454 */
393 char *spinnerCharacters; /* +0x458 */
394#ifdef __cplusplus
395 DebugOverlayConsole(HINSTANCE module, HWND targetWindow,
396 int columnCount, int rowCount, int waitMode);
398 void Clear(void);
399 void Scroll(void);
400 void DrawPendingLines(void);
401 char WaitForKey(void);
402 void EnableReverseVideo(void);
403 void DisableReverseVideo(void);
404 void SetOverlayTextColor(int red, int green, int blue);
405 void SetOverlayBackgroundColor(int red, int green, int blue);
406 void SetTransparentBackground(void);
407 void SetOpaqueBackground(void);
408 void SetTextPosition(int row, int column);
409 void SetCursorPosition(int column, int row);
410 void Reset(void);
411 unsigned char TakeStepFlag(void);
412 void ClearPauseFlags(void);
413#endif
415
416/*
417 * The DOS source spelled `BOOLEAN window_colored = FALSE;`, but <windows.h>
418 * already provides BOOLEAN (as BYTE) and MSVC 4.2 rejects a redefinition with a
419 * different base type. The Win32 port therefore has to be using the windows.h
420 * one, so do not redeclare it here. TRUE/FALSE likewise come from windows.h.
421 */
422
423/* --------------------------------------------------------------------------
424 * Enumerations named by the leaked main-module source. The tag names and the
425 * first enumerator of each are original:
426 * GAME_MODE Game_Mode = Player;
427 * GAME_STATUS Game_Status = ALIVE;
428 * The remaining enumerators are NOT yet recovered -- do not invent values that
429 * the assembly has not confirmed.
430 * -------------------------------------------------------------------------- */
431typedef enum {
433 /* TODO: remaining GAME_MODE enumerators unknown */
434} GAME_MODE;
435
436typedef enum {
438 /* TODO: remaining GAME_STATUS enumerators unknown */
440
441/* --------------------------------------------------------------------------
442 * Shared utility layer. These were recovered by ranking the call graph by
443 * fan-in; the addresses are the originals.
444 * -------------------------------------------------------------------------- */
445#ifdef __cplusplus
446extern "C" {
447#endif
448
449/* Variadic printers cannot be generated mechanically, so they live here. */
450void ShowOnScreenMessage(short duration, const char *fmt, ...);
451void SoundDebugPrintf(const char *fmt, ...); /* 0x437946 */
452void SystemDebugPrintf(const char *fmt, ...); /* 0x40FDAD */
453
454#include "game_data.h"
455#include "globals.h"
456#include "functions.h"
457#include "externs.h"
458
459#ifdef __cplusplus
460}
461#endif
462
463#endif /* GAME_H */
Declarations for external game and runtime functions.
Declarations for reconstructed game functions.
void SoundDebugPrintf(const char *fmt,...)
Definition mono.c:64
void ShowOnScreenMessage(short duration, const char *format,...)
Definition message.c:151
void SystemDebugPrintf(const char *format,...)
Definition console.cpp:30
unsigned short UINT16
Definition game.h:117
struct IxSample IxSample
Definition game.h:122
struct IxSound IxSound
Definition game.h:121
unsigned int DwordPtr
Definition game.h:45
char MouseCursorState_size_must_be_0x21[sizeof(MouseCursorState)==0x21 ? 1 :-1]
Definition game.h:189
GAME_STATUS
Definition game.h:436
@ ALIVE
Definition game.h:437
short INT16
Definition game.h:116
GAME_MODE
Definition game.h:431
@ Player
Definition game.h:432
char CockpitReadout_size_must_be_0x0a[sizeof(CockpitReadout)==0x0a ? 1 :-1]
Definition game.h:332
signed char INT8
Definition game.h:119
unsigned char UINT8
Definition game.h:118
Game data structures, constants and packed resource formats.
Shared globals and their retail address annotations.
struct ActiveSoundEntry * next
Definition game.h:348
IxSound * sound
Definition game.h:347
short y
Definition game.h:301
short x
Definition game.h:300
short previousRight
Definition game.h:302
TextContext * context
Definition game.h:299
COLORREF backgroundColor
Definition game.h:383
void SetOverlayTextColor(int red, int green, int blue)
Definition debug.cpp:305
char formatBuffer[0x400]
Definition game.h:375
DebugOverlayConsole(HINSTANCE module, HWND targetWindow, int columnCount, int rowCount, int waitMode)
Definition debug.cpp:17
void DrawPendingLines(void)
Definition debug.cpp:227
void SetOverlayBackgroundColor(int red, int green, int blue)
Definition debug.cpp:319
void ClearPauseFlags(void)
Definition console.cpp:117
char * dirtyLines
Definition game.h:377
void SetCursorPosition(int column, int row)
Definition console.cpp:95
void DisableReverseVideo(void)
Definition debug.cpp:285
void SetOpaqueBackground(void)
Definition debug.cpp:343
void Clear(void)
Definition debug.cpp:207
unsigned char TakeStepFlag(void)
Definition console.cpp:107
char WaitForKey(void)
Definition debug.cpp:245
char * textBuffer
Definition game.h:376
char * spinnerCharacters
Definition game.h:393
COLORREF textColor
Definition game.h:382
void Scroll(void)
Definition debug.cpp:217
void SetTransparentBackground(void)
Definition debug.cpp:331
void SetTextPosition(int row, int column)
Definition console.cpp:88
void EnableReverseVideo(void)
Definition debug.cpp:271
int height
Definition game.h:275
unsigned char * pixels
Definition game.h:276
int width
Definition game.h:274
struct FreedHeapBlock * next
Definition game.h:362
void * block
Definition game.h:361
struct GuardedAllocation * next
Definition game.h:356
unsigned int size
Definition game.h:355
void * block
Definition game.h:354
int primaryButton
Definition game.h:182
int secondaryButton
Definition game.h:183
TextContext * context
Definition game.h:321
signed char flashCount
Definition game.h:326
short colour
Definition game.h:324
short drawColour
Definition game.h:325
short x
Definition game.h:322
short y
Definition game.h:323
const char * text
Definition game.h:327
unsigned int buttons
Definition game.h:224
short status
Definition game.h:213
unsigned short modifiers
Definition game.h:215
short value
Definition game.h:212
unsigned int timestamp
Definition game.h:214
unsigned int modifiers
Definition game.h:197
short value
Definition game.h:196
short x
Definition game.h:194
struct InputEvent * next
Definition game.h:204
struct InputEvent * previous
Definition game.h:205
unsigned int status
Definition game.h:203
short secondaryButton
Definition game.h:200
unsigned int field_18
Definition game.h:202
short type
Definition game.h:193
unsigned int field_14
Definition game.h:201
unsigned int timestamp
Definition game.h:198
short y
Definition game.h:195
short primaryButton
Definition game.h:199
void ix_sample_set_looping(int enabled)
Definition sound.c:489
unsigned int flags
Definition game.h:128
unsigned int frequency
Definition ix.h:78
int ix_sample_load_wav(void *data, int bytes)
Definition sample.cpp:199
int ix_sample_load_raw(void *data, int bytes, int frequency, int bitsPerSample, int channels)
Definition sample.cpp:292
unsigned int bitsPerSample
Definition ix.h:73
unsigned int channels
Definition ix.h:74
unsigned short volume
Definition ix.h:119
unsigned short pan
Definition ix.h:120
unsigned int flags
Definition game.h:138
void ix_system_sound_set_pan(unsigned short pan)
Definition sound.cpp:77
IxSample * sample
Definition game.h:139
void ix_system_sound_set_volume(unsigned short volume)
Definition sound.cpp:69
void ix_sound_set_delete_on_stop(int enabled)
Definition sound.cpp:352
TextContext context
Definition game.h:308
short top
Definition game.h:313
TextContext * previousContext
Definition game.h:311
short left
Definition game.h:312
Viewport viewport
Definition game.h:310
short bottom
Definition game.h:315
short right
Definition game.h:314
Viewport savedBackground
Definition game.h:309
unsigned char field_6
Definition game.h:169
void * scratchBuffer
Definition game.h:174
volatile short y
Definition game.h:166
unsigned char *volatile shape
Definition game.h:172
unsigned int field_9
Definition game.h:171
short frame
Definition game.h:173
struct InputPumpContext * context
Definition game.h:175
unsigned char field_1b[6]
Definition game.h:176
unsigned char field_5
Definition game.h:168
unsigned short field_7
Definition game.h:170
unsigned char field_4
Definition game.h:167
volatile short x
Definition game.h:165
short height
Definition game.h:259
short leftExtent
Definition game.h:262
short width
Definition game.h:260
short topExtent
Definition game.h:261
int right
Definition game.h:240
RasterSurface * surface
Definition game.h:237
int top
Definition game.h:239
int bottom
Definition game.h:241
int left
Definition game.h:238
int field_C
Definition game.h:232
int maximumY
Definition game.h:231
int field_10
Definition game.h:233
int maximumX
Definition game.h:230
unsigned char * pixels
Definition game.h:229
unsigned char colour
Definition game.h:288
short cursorY
Definition game.h:286
unsigned char * font
Definition game.h:287
char * text
Definition game.h:290
FontWorkspace ** fontWorkspace
Definition game.h:293
unsigned char backgroundColour
Definition game.h:289
signed char alignment
Definition game.h:292
char * textCursor
Definition game.h:291
short cursorX
Definition game.h:285
Viewport * viewport
Definition game.h:284
unsigned char * pixels
Definition game.h:150
short right
Definition game.h:154
short bottom
Definition game.h:155
unsigned char * allocation
Definition game.h:156
unsigned short * rowOffsets
Definition game.h:151
short left
Definition game.h:152
short top
Definition game.h:153
struct WaveTableEntry * next
Definition game.h:342
int field_4
Definition game.h:339
IxSample * sample
Definition game.h:340
char * name
Definition game.h:338
int field_c
Definition game.h:341