Wing Commander II
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
gr.c
Go to the documentation of this file.
1/*
2 * Shape decoding, viewport drawing and raster effects.
3 *
4 * Retail object 0x4254C0-0x4288FF (link order; see docs/ORDER.md).
5 */
6/* This unit owns the gr storage declared in globals.h (as statics). */
7#define GR_C
8#include "game.h"
9
10const int g_nViewportStaticRandomRange = 3; /* 0x0048e060 */
11
12unsigned char g_abPaletteTranslation[256] = {
13 0, 1, 2, 3, 4, 5, 6, 7,
14 8, 9, 10, 11, 12, 13, 14, 15,
15 16, 17, 18, 19, 20, 21, 22, 23,
16 24, 25, 26, 27, 28, 29, 30, 31,
17 32, 33, 34, 35, 36, 37, 38, 39,
18 40, 41, 42, 43, 44, 45, 46, 47,
19 48, 49, 50, 51, 52, 53, 54, 55,
20 56, 57, 58, 59, 60, 61, 62, 63,
21 64, 65, 66, 67, 68, 69, 70, 71,
22 72, 73, 74, 75, 76, 77, 78, 79,
23 80, 81, 82, 83, 84, 85, 86, 87,
24 88, 89, 90, 91, 92, 93, 94, 95,
25 96, 97, 98, 99, 100, 101, 102, 103,
26 104, 105, 106, 107, 108, 109, 110, 111,
27 112, 113, 114, 115, 116, 117, 118, 119,
28 120, 121, 122, 123, 124, 125, 126, 127,
29 128, 129, 130, 131, 132, 133, 134, 135,
30 136, 137, 138, 139, 140, 141, 142, 143,
31 144, 145, 146, 147, 148, 149, 150, 151,
32 152, 153, 154, 155, 156, 157, 158, 159,
33 160, 161, 162, 163, 164, 165, 166, 167,
34 168, 169, 170, 171, 172, 173, 174, 175,
35 176, 177, 178, 179, 180, 181, 182, 183,
36 184, 185, 186, 187, 188, 189, 190, 191,
37 192, 193, 194, 195, 196, 197, 198, 199,
38 200, 201, 202, 203, 204, 205, 206, 207,
39 208, 209, 210, 211, 212, 213, 214, 215,
40 216, 217, 218, 219, 220, 221, 222, 223,
41 224, 225, 226, 227, 228, 229, 230, 231,
42 232, 233, 234, 235, 236, 237, 238, 239,
43 240, 241, 242, 243, 244, 245, 246, 247,
44 248, 249, 250, 251, 252, 253, 254, 255
45}; /* 0x00496338 */
46unsigned short g_awAbsoluteCosine[360] = {
47 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 252, 251,
48 250, 250, 248, 247, 246, 245, 243, 242, 241, 239, 237, 236,
49 234, 232, 230, 228, 226, 224, 221, 219, 217, 215, 212, 210,
50 207, 204, 202, 198, 196, 193, 190, 187, 184, 181, 178, 175,
51 171, 168, 165, 161, 158, 154, 150, 147, 143, 139, 136, 131,
52 128, 124, 120, 116, 112, 108, 104, 100, 96, 92, 88, 83,
53 79, 74, 71, 66, 62, 58, 53, 49, 45, 40, 36, 31,
54 27, 22, 18, 13, 9, 4, 0, 4, 9, 13, 18, 22,
55 27, 31, 36, 40, 45, 49, 53, 58, 62, 66, 71, 75,
56 79, 83, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124,
57 128, 131, 136, 139, 143, 147, 150, 154, 158, 161, 165, 168,
58 171, 175, 178, 181, 184, 187, 190, 193, 196, 198, 202, 204,
59 207, 210, 212, 215, 217, 219, 221, 224, 226, 228, 230, 232,
60 234, 236, 237, 239, 241, 242, 243, 245, 246, 247, 248, 250,
61 250, 251, 252, 253, 254, 254, 255, 255, 255, 255, 255, 255,
62 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 252, 251,
63 250, 250, 248, 247, 246, 245, 243, 242, 241, 239, 237, 236,
64 234, 232, 230, 228, 226, 224, 221, 219, 217, 215, 212, 210,
65 207, 204, 202, 198, 196, 193, 190, 187, 184, 181, 178, 175,
66 171, 168, 165, 161, 158, 154, 150, 147, 143, 139, 136, 131,
67 128, 124, 120, 116, 112, 108, 104, 100, 96, 92, 88, 83,
68 79, 74, 71, 66, 62, 58, 53, 49, 45, 40, 36, 31,
69 27, 22, 18, 13, 9, 4, 0, 4, 9, 13, 18, 22,
70 27, 31, 36, 40, 45, 49, 53, 58, 62, 66, 71, 75,
71 79, 83, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124,
72 128, 131, 136, 139, 143, 147, 150, 154, 158, 161, 165, 168,
73 171, 175, 178, 181, 184, 187, 190, 193, 196, 198, 202, 204,
74 207, 210, 212, 215, 217, 219, 221, 224, 226, 228, 230, 232,
75 234, 236, 237, 239, 241, 242, 243, 245, 246, 247, 248, 250,
76 250, 251, 252, 253, 254, 254, 255, 255, 255, 255, 255, 255
77}; /* 0x00496438 */
78unsigned short g_awAbsoluteSine[360] = {
79 0, 4, 9, 13, 18, 22, 27, 31, 36, 40, 45, 49,
80 53, 58, 62, 66, 71, 75, 79, 83, 88, 92, 96, 100,
81 104, 108, 112, 116, 120, 124, 128, 131, 136, 139, 143, 147,
82 150, 154, 158, 161, 165, 168, 171, 175, 178, 181, 184, 187,
83 190, 193, 196, 198, 202, 204, 207, 210, 212, 215, 217, 219,
84 221, 224, 226, 228, 230, 232, 234, 236, 237, 239, 241, 242,
85 243, 245, 246, 247, 248, 250, 250, 251, 252, 253, 254, 254,
86 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
87 255, 254, 254, 253, 252, 251, 250, 250, 248, 247, 246, 245,
88 243, 242, 241, 239, 237, 236, 234, 232, 230, 228, 226, 224,
89 221, 219, 217, 215, 212, 210, 207, 204, 202, 198, 196, 193,
90 190, 187, 184, 181, 178, 175, 171, 168, 165, 161, 158, 154,
91 150, 147, 143, 139, 136, 131, 128, 124, 120, 116, 112, 108,
92 104, 100, 96, 92, 88, 83, 79, 74, 71, 66, 62, 58,
93 53, 49, 45, 40, 36, 31, 27, 22, 18, 13, 9, 4,
94 0, 4, 9, 13, 18, 22, 27, 31, 36, 40, 45, 49,
95 53, 58, 62, 66, 71, 75, 79, 83, 88, 92, 96, 100,
96 104, 108, 112, 116, 120, 124, 128, 131, 136, 139, 143, 147,
97 150, 154, 158, 161, 165, 168, 171, 175, 178, 181, 184, 187,
98 190, 193, 196, 198, 202, 204, 207, 210, 212, 215, 217, 219,
99 221, 224, 226, 228, 230, 232, 234, 236, 237, 239, 241, 242,
100 243, 245, 246, 247, 248, 250, 250, 251, 252, 253, 254, 254,
101 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
102 255, 254, 254, 253, 252, 251, 250, 250, 248, 247, 246, 245,
103 243, 242, 241, 239, 237, 236, 234, 232, 230, 228, 226, 224,
104 221, 219, 217, 215, 212, 210, 207, 204, 202, 198, 196, 193,
105 190, 187, 184, 181, 178, 175, 171, 168, 165, 161, 158, 154,
106 150, 147, 143, 139, 136, 131, 128, 124, 120, 116, 112, 108,
107 104, 100, 96, 92, 88, 83, 79, 74, 71, 66, 62, 58,
108 53, 49, 45, 40, 36, 31, 27, 22, 18, 13, 9, 4
109}; /* 0x00496708 */
110
111/* Function start: 0x4254C0 */
112void CheckHeapBlockSignature(unsigned char *shape)
113{
114 if (*(int *)(shape - 8) != 0x6666656a) {
115 if (IsFreedHeapBlockTracked(shape) != 0)
116 exit_squadron("not jefftep (freed)");
117 else
118 exit_squadron("not jefftep");
119 }
120}
121
122/* Function start: 0x42550E */
123int HasValidShapeAllocationSignature(unsigned char *shape)
124{
125 if (*(int *)(shape - 8) != 0x6666656a)
126 return 0;
127 return 1;
128}
129
130/* Function start: 0x42553A */
131unsigned char *GetPreparedShapeData(unsigned char *shape)
132{
133 return *(unsigned char **)(shape - 4);
134}
135
136/* Function start: 0x425550 */
137short GetShapeFrameCount(unsigned char *shape)
138{
140 return (short)((*(unsigned short *)(shape + 4) >> 2) - 1);
141}
142
143/* Function start: 0x42557C */
144void GetShapeFrameExtents(unsigned char *shape, short frame,
145 short *width, short *height,
146 short *leftExtent, short *topExtent)
147{
148 int right;
149 int top;
150 int left;
151 int bottom;
152 short *frameHeader;
153
154 frame++;
155 frame <<= 2;
156 if (*(unsigned short *)(shape + 4) > frame) {
157 frameHeader = (short *)(*(int *)(shape + frame) + shape);
158 right = *frameHeader++;
159 left = *frameHeader++;
160 top = *frameHeader++;
161 bottom = *frameHeader++;
162 *width = (short)(left + right + 1);
163 *height = (short)(bottom + top + 1);
164 *leftExtent = (short)left;
165 *topExtent = (short)top;
166 }
167}
168
169#pragma function(memcpy, memset)
170/* Function start: 0x425618 */
171void DecodeShapeFrame(unsigned char *shape, short frame,
172 unsigned char *bitmap, int width, int height,
173 int leftExtent, int topExtent)
174{
175 unsigned char *commands;
176 unsigned short rowOp;
177 unsigned char *dest;
178 unsigned char action;
179 unsigned char color;
180 unsigned char *pixels;
181 short span;
182 int endX;
183 short yDelta;
184 short leftmost;
185 short rightmost;
186 short minY;
187 short maxY;
188 int skip;
189 int shapeY;
190 int screenX;
191 short xDelta;
192 int row;
193 int shapeX;
194
195 shapeX = leftExtent;
196 shapeY = topExtent;
197 if (shape == 0)
198 return;
199 if (frame < 0)
200 return;
201 frame++;
202 frame <<= 2;
203 if (*(unsigned short *)(shape + 4) > frame) {
204
205 leftmost = 0;
206 rightmost = (short)(width - 1);
207 minY = 0;
208 maxY = (short)(height - 1);
209 commands = shape + *(int *)(frame + shape);
210 commands += 8;
211 pixels = bitmap;
212 rowOp = *(unsigned short *)commands;
213 commands += 2;
214 while (rowOp != 0) {
215 xDelta = *(short *)commands;
216 commands += 2;
217 yDelta = *(short *)commands;
218 commands += 2;
219 screenX = xDelta + shapeX;
220 row = yDelta + shapeY;
221 dest = row * width + screenX + pixels;
222 if ((rowOp & 1) != 0) {
223 rowOp >>= 1;
224 while (rowOp > 0) {
225 action = *commands;
226 commands++;
227 if ((action & 1) != 0) {
228 action >>= 1;
229 rowOp = (unsigned short)(rowOp - action);
230 color = *commands;
231 commands++;
232 if (minY <= row && maxY >= row) {
233 endX = action + screenX - 1;
234 if (rightmost >= screenX && leftmost <= endX) {
235 span = action;
236 skip = 0;
237 if (leftmost > screenX) {
238 span -= leftmost - screenX;
239 skip += leftmost - screenX;
240 }
241 if (rightmost < endX)
242 span -= endX - rightmost;
243 memset(skip + dest, color, span);
244 }
245 }
246 dest += action;
247 screenX += action;
248 } else {
249 action >>= 1;
250 rowOp = (unsigned short)(rowOp - action);
251 if (minY <= row && maxY >= row) {
252 endX = action + screenX - 1;
253 if (rightmost >= screenX && leftmost <= endX) {
254 span = action;
255 skip = 0;
256 if (leftmost > screenX) {
257 span -= leftmost - screenX;
258 skip += leftmost - screenX;
259 }
260 if (rightmost < endX)
261 span -= endX - rightmost;
262 memcpy(skip + dest, skip + commands,
263 span);
264 }
265 }
266 commands += action;
267 dest += action;
268 screenX += action;
269 }
270 }
271 } else {
272 rowOp >>= 1;
273 if (minY <= row && maxY >= row) {
274 endX = rowOp + screenX - 1;
275 if (rightmost >= screenX && leftmost <= endX) {
276 span = rowOp;
277 skip = 0;
278 if (leftmost > screenX) {
279 span -= leftmost - screenX;
280 skip += leftmost - screenX;
281 }
282 if (rightmost < endX)
283 span -= endX - rightmost;
284 memcpy(skip + dest, skip + commands, span);
285 }
286 }
287 commands += rowOp;
288 }
289 rowOp = *(unsigned short *)commands;
290 commands += 2;
291 }
292 }
293}
294
295#pragma intrinsic(memcpy, memset)
296/* Function start: 0x4259E2 */
297int SignExtendClipCoord(volatile short v)
298{
299 if ((unsigned short)v < 0xfdc0)
300 return (unsigned short)v;
301 return (int)(short)v;
302}
303
304void exit_squadron(const char *msg, ...);
305
306/* Function start: 0x425A16 */
308 RasterClip *clip)
309{
310 int nextOffset;
311 int rowStrideOffset;
312 int offset;
313
314 if (viewport->left < 0)
315 return;
316 if (viewport->pixels != g_101_stScrViewInfo.pixels) {
317 for (offset = 0;
319 g_apViewportAllocations[offset] !=
320 viewport->pixels;
321 offset++) {
322 }
323 if (offset >= g_nViewportAllocationCount)
324 exit_squadron("bad vport");
325 }
326 if (viewport->pixels == g_101_stScrViewInfo.pixels)
327 MarkDibDirty();
328 offset = SignExtendClipCoord(viewport->rowOffsets[viewport->top]);
329 nextOffset = SignExtendClipCoord(
330 viewport->rowOffsets[viewport->top + 1]);
331 rowStrideOffset = SignExtendClipCoord(
332 viewport->rowOffsets[viewport->top]);
333 surface->pixels = viewport->pixels + viewport->left + offset;
334 surface->maximumX = nextOffset - rowStrideOffset - 1;
335 surface->maximumY = viewport->bottom - viewport->top;
336 surface->field_C = 0;
337 surface->field_10 = 0;
338 clip->surface = surface;
339 clip->left = 0;
340 clip->top = 0;
341 clip->right = viewport->right - viewport->left;
342 clip->bottom = viewport->bottom - viewport->top;
343}
344
345/* Function start: 0x425B9E */
351
352#pragma function(memset)
353/* Function start: 0x425BBF */
354void SetSolidColourTranslation(unsigned char colour)
355{
356 memset(g_abSolidColourTranslation, colour, 255);
357 g_abSolidColourTranslation[255] = 0xff;
359}
360
361#pragma function(memcpy)
362/* Function start: 0x425BF6 */
363void PrepareShapeRLEData(unsigned char *shape)
364{
365 int gapRun;
366 int runLength;
367 unsigned char *code;
368 short height;
369 unsigned char *bitmap;
370 unsigned char *pixel;
371 short width;
372 unsigned char *offsetTable;
373 unsigned char *packed;
374 int bytes;
375 int frameOffset;
376 int endX;
377 int row;
378 int startX;
379 int frameNum;
380 unsigned char *emit;
381 int todo;
382 int startY;
383 short leftExtent;
384 short topOffset;
385 int frameLimit;
386 int bottomEdge;
387
389 if (GetPreparedShapeData(shape) != 0)
390 return;
391
393 memcpy(emit, "1.00", 4);
394 emit += 4;
395 frameLimit = GetShapeFrameCount(shape);
396 memcpy(emit, &frameLimit, 4);
397 emit += 4;
398 offsetTable = emit;
399 memset(emit, 0, (unsigned int)(frameLimit << 3));
400 emit += frameLimit << 3;
401
402 for (frameNum = 0; frameNum < frameLimit; frameNum++) {
403 frameOffset = (int)(emit - g_13_abShapeRLEScratch);
404 memcpy(offsetTable, &frameOffset, 4);
405 offsetTable += 8;
406 GetShapeFrameExtents(shape, (short)frameNum, &width, &height,
407 &leftExtent, &topOffset);
408 memcpy(emit, &height, 2);
409 emit += 2;
410 memcpy(emit, &width, 2);
411 emit += 2;
412 memcpy(emit, &topOffset, 2);
413 emit += 2;
414 memcpy(emit, &leftExtent, 2);
415 emit += 2;
416 startX = -leftExtent;
417 startY = -topOffset;
418 endX = width - leftExtent - 1;
419 bottomEdge = height - topOffset - 1;
420 memcpy(emit, &startX, 4);
421 emit += 4;
422 memcpy(emit, &startY, 4);
423 emit += 4;
424 memcpy(emit, &endX, 4);
425 emit += 4;
426 memcpy(emit, &bottomEdge, 4);
427 emit += 4;
428
429 bitmap = AllocateTaggedMemory(
430 (unsigned int)((int)height * width), 0);
431 pixel = bitmap;
432 memset(bitmap, 0xff, (unsigned int)((int)height * width));
433 DecodeShapeFrame(shape, (short)frameNum, bitmap, width, height,
434 leftExtent, topOffset);
435 for (row = 0; height > row; row++) {
436 todo = width;
437 while (todo > 0) {
438 if (*pixel != 0xff) {
439 code = emit;
440 emit++;
441 for (runLength = 0;
442 todo != 0 && runLength < 0x7f &&
443 *pixel != 0xff;
444 runLength++, todo--, emit++, pixel++) {
445 *emit = *pixel;
446 }
447 *code = (unsigned char)(runLength * 2 + 1);
448 } else {
449 for (gapRun = 0;
450 todo != 0 && gapRun < 0xff &&
451 *pixel == 0xff;
452 gapRun++, todo--, pixel++) {
453 }
454 *emit = 1;
455 emit++;
456 *emit = (unsigned char)gapRun;
457 emit++;
458 }
459 }
460 *emit = 0;
461 emit++;
462 }
463 ReleasePacketHandle(bitmap);
464 }
465
466 bytes = (int)(emit - g_13_abShapeRLEScratch);
467 if (bytes > (int)sizeof(g_13_abShapeRLEScratch))
468 exit_squadron("qq copy overflow");
469 packed = AllocateTaggedMemory(bytes, 0);
470 memcpy(packed, g_13_abShapeRLEScratch, bytes);
471 memcpy(shape - 4, &packed, 4);
472}
473
474
475/* Function start: 0x425FB4 */
476void DrawSpriteTransformed(Viewport *viewport, int x, int y,
477 unsigned char *shape, int frame,
478 int angle, int scaleX, int scaleY,
479 int flip, int blendMode)
480{
481 /* Performance-counter samples taken around each stage. */
482 LARGE_INTEGER t0;
483 LARGE_INTEGER t1;
484 LARGE_INTEGER t2;
485 LARGE_INTEGER t3;
486
487 if (shape == 0 || frame < 0 || viewport->pixels == 0 ||
488 viewport->rowOffsets == 0)
489 return;
490 if (frame >= GetShapeFrameCount(shape))
491 return;
492 if (viewport->left < 0)
493 return;
495 PrepareShapeRLEData(shape);
497 ClipViewportToScreen(viewport);
499 if (flip != 0) {
500 if (flip == 0x10) {
501 scaleX = -scaleX;
502 } else if (flip == 0x20) {
503 scaleY = -scaleY;
504 } else if (flip == 0x30) {
505 scaleX = -scaleX;
506 scaleY = -scaleY;
507 } else {
508 exit_squadron("bad flip");
509 }
510 }
511 if (blendMode != 0) {
513 GetPreparedShapeData(shape), frame,
514 x - viewport->left, y - viewport->top,
516 angle * 10, scaleX * 256, scaleY * 256, 1);
517 } else {
519 GetPreparedShapeData(shape), frame,
520 x - viewport->left, y - viewport->top,
522 angle * 10, scaleX * 256, scaleY * 256, 0);
523 }
525 g_nShapePrepareTicks += t1.LowPart - t0.LowPart;
526 g_1_nShapeClipTicksValue += t2.LowPart - t1.LowPart;
527 g_nShapeDrawTicks += t3.LowPart - t2.LowPart;
528 if (viewport->pixels == g_101_stScrViewInfo.pixels)
529 MarkDibDirty();
530}
531
532/* Function start: 0x4261D5 */
533void RasterLineHook(const void *marker)
534{
535 (void)marker;
536 return;
537}
538
539/* Function start: 0x4261E5 */
540void DrawFontGlyph(char character, TextContext *context, int height,
541 int width, int y)
542{
543 int column;
544 int drawY;
545 Viewport *view;
546 unsigned char fg;
547 unsigned char fontFg;
548 unsigned char bg;
549 unsigned char fontBg;
550 unsigned char translatedPixel;
551 unsigned char *dest;
552 int dy;
553 int dx;
554 unsigned char *bitmap;
555
556 drawY = y;
557 view = context->viewport;
558 fg = context->colour;
559 bg = context->backgroundColour;
560 fontFg = context->font[2];
561 fontBg = context->font[3];
562 g_abPaletteTranslation[fontFg] = fg;
563 g_abPaletteTranslation[fontBg] = bg;
564 /* Preserve the retail Win32 port's signed-char comparisons. */
565 if (character == 0x81 || character == 0x84 || character == 0x8e ||
566 character == 0x94 || character == 0x99 || character == 0x9a ||
567 character == 0xe1) {
568 /* The DOS game drew these umlauts from the font workspace; the
569 * Win32 port skips them. */
570 return;
571 bitmap = (*context->fontWorkspace)->pixels;
572 width = (*context->fontWorkspace)->width;
573 height = (*context->fontWorkspace)->height;
574 for (dy = 0; dy < height; dy++) {
575 drawY = y + dy;
576 if (view->top == drawY) {
577 if ((view->rowOffsets[drawY] & 0x8000) != 0)
578 dest = context->cursorX + view->pixels;
579 else
580 dest = view->rowOffsets[drawY] + context->cursorX +
581 view->pixels;
582 } else {
583 dest = view->rowOffsets[drawY] + context->cursorX +
584 view->pixels;
585 }
586 for (dx = 0; dx < width; dx++)
587 dest[dx] = bitmap[width * dy + dx];
588 }
589 context->cursorX += width;
590 } else
591 {
592 bitmap = (context->font[character + 0x204] << 8) +
593 context->font[character + 0x104] + context->font;
594 if (fontFg != fg || fontBg != bg) {
595 while (height-- != 0) {
596 if (view->top == drawY) {
597 if ((view->rowOffsets[drawY] & 0x8000) != 0)
598 dest = context->cursorX + view->pixels;
599 else
600 dest = view->rowOffsets[drawY] + context->cursorX +
601 view->pixels;
602 } else {
603 dest = view->rowOffsets[drawY] + context->cursorX +
604 view->pixels;
605 }
606 for (column = width; column-- != 0;) {
607 translatedPixel = g_abPaletteTranslation[*bitmap];
608 if (translatedPixel != 0xff)
609 *dest = translatedPixel;
610 bitmap++;
611 dest++;
612 }
613 drawY++;
614 }
615 context->cursorX += context->font[character + 4];
616 } else {
617 while (height-- != 0) {
618 if (view->top == drawY) {
619 if ((view->rowOffsets[drawY] & 0x8000) != 0)
620 dest = context->cursorX + view->pixels;
621 else
622 dest = view->rowOffsets[drawY] + context->cursorX +
623 view->pixels;
624 } else {
625 dest = view->rowOffsets[drawY] + context->cursorX +
626 view->pixels;
627 }
628 for (column = width; column-- != 0;) {
629 if (*bitmap != 0xff)
630 *dest = *bitmap;
631 bitmap++;
632 dest++;
633 }
634 drawY++;
635 }
636 context->cursorX += context->font[character + 4];
637 }
638 }
639 g_abPaletteTranslation[fontFg] = fontFg;
640 g_abPaletteTranslation[fontBg] = fontBg;
641 return;
642}
643
644/* Function start: 0x42665A */
645/* Nothing in the shipped executable calls this; the Win32 port only reports
646 * the call to the driver's line copier. */
647void __copyline(void)
648{
649 RasterLineHook("__copyline");
650 return;
651}
652
653/* Function start: 0x426677 */
654/* Nothing in the shipped executable calls this; the Win32 port only reports
655 * the call to the driver's line eraser. */
656void __wipeline(void)
657{
658 RasterLineHook("__wipeline");
659 return;
660}
661
662/* Function start: 0x426694 */
663void EstablishColors(Viewport *viewport, unsigned char *active)
664{
665 RasterLineHook("EstablishColors");
666 return;
667}
668
669/* Function start: 0x4266B1 */
670void GetPaletteEntry(short index, unsigned short *rgb)
671{
672 GetPaletteEntryAsWords(index, rgb);
673}
674
675/* Function start: 0x4266CC */
676void SetPaletteEntry(short index, short *rgb)
677{
678 DIBsetPalette(index, rgb);
679}
680
681/* Function start: 0x4266E7 */
682void DrawSpriteDefault(Viewport *viewport, short x, short y,
683 unsigned char *shape, short frame)
684{
685 if (shape == 0)
686 return;
687 if (frame < 0)
688 return;
689 if (viewport->left < 0)
690 return;
691 if (HasValidShapeAllocationSignature(shape) != 0)
692 DrawSpriteTransformed(viewport, x, y, shape, frame,
693 0, 0x100, 0x100, 0, 0);
694}
695
696short GetTransformedShapeBounds(Viewport *viewport, short x, short y,
697 unsigned char *shape, short frame,
698 short angle, short scale, short flip,
699 short *bounds);
700void FillPolygon(Viewport *viewport, ShortPoint *points, int count,
701 char colour);
702void triangle(Viewport *viewport, ShortPoint *points, int colour);
703
704/* Function start: 0x426769 */
705void CaptureSpriteBackground(Viewport *viewport, unsigned char *background,
706 short x, short y, unsigned char *shape,
707 short frame)
708{
709 unsigned char *commands;
710 unsigned short rowOp;
711 unsigned char *screenRow;
712 unsigned char *pixels;
713 unsigned char action;
714 unsigned char color;
715 unsigned char *original;
716 short span;
717 int endX;
718 short yDelta;
719 short leftmost;
720 short rightmost;
721 short minY;
722 short maxY;
723 int screenX;
724 short xDelta;
725 int row;
726 int skip;
727
728 if (viewport->left < 0)
729 return;
730 if (HasValidShapeAllocationSignature(shape) == 0)
731 return;
732 original = background;
733 if (original == 0)
734 return;
735 if (shape == 0)
736 return;
737 if (frame < 0)
738 return;
739 frame++;
740 frame <<= 2;
741 if (*(unsigned short *)(shape + 4) > frame) {
742 leftmost = viewport->left;
743 rightmost = viewport->right;
744 minY = viewport->top;
745 maxY = viewport->bottom;
746 commands = shape + *(int *)(frame + shape);
747 commands += 8;
748 pixels = viewport->pixels;
749 rowOp = *(unsigned short *)commands;
750 commands += 2;
751 while (rowOp != 0) {
752 xDelta = *(short *)commands;
753 commands += 2;
754 yDelta = *(short *)commands;
755 commands += 2;
756 screenX = x + xDelta;
757 row = y + yDelta;
758 screenRow = viewport->rowOffsets[row] + screenX + pixels;
759 if ((rowOp & 1) != 0) {
760 rowOp >>= 1;
761 while (rowOp > 0) {
762 action = *commands;
763 commands++;
764 if ((action & 1) != 0) {
765 action >>= 1;
766 rowOp = (unsigned short)(rowOp - action);
767 color = *commands;
768 commands++;
769 if (minY <= row && maxY >= row) {
770 endX = action + screenX - 1;
771 if (rightmost >= screenX &&
772 leftmost <= endX) {
773 span = action;
774 skip = 0;
775 if (leftmost > screenX) {
776 span -= leftmost - screenX;
777 skip += leftmost - screenX;
778 }
779 if (rightmost < endX)
780 span -= endX - rightmost;
781 memcpy(original, skip + screenRow, span);
782 original += span;
783 }
784 }
785 screenRow += action;
786 screenX += action;
787 } else {
788 action >>= 1;
789 rowOp = (unsigned short)(rowOp - action);
790 if (minY <= row && maxY >= row) {
791 endX = action + screenX - 1;
792 if (rightmost >= screenX &&
793 leftmost <= endX) {
794 span = action;
795 skip = 0;
796 if (leftmost > screenX) {
797 span -= leftmost - screenX;
798 skip += leftmost - screenX;
799 }
800 if (rightmost < endX)
801 span -= endX - rightmost;
802 memcpy(original, skip + screenRow, span);
803 original += span;
804 }
805 }
806 commands += action;
807 screenRow += action;
808 screenX += action;
809 }
810 }
811 } else {
812 rowOp >>= 1;
813 if (minY <= row && maxY >= row) {
814 endX = rowOp + screenX - 1;
815 if (rightmost >= screenX && leftmost <= endX) {
816 span = rowOp;
817 skip = 0;
818 if (leftmost > screenX) {
819 span -= leftmost - screenX;
820 skip += leftmost - screenX;
821 }
822 if (rightmost < endX)
823 span -= endX - rightmost;
824 memcpy(original, skip + screenRow, span);
825 original += span;
826 }
827 }
828 commands += rowOp;
829 }
830 rowOp = *(unsigned short *)commands;
831 commands += 2;
832 }
833 }
834 (void)color;
835}
836
837/* Forward declarations of this file's later drawing routines. */
838void DrawFilledViewportRect(Viewport *viewport, short left, short top,
839 short right, short bottom, short color);
840void DrawSpriteScaled(Viewport *viewport, short x, short y,
841 unsigned char *shape, short frame, short angle,
842 short scale, short flip);
843int HasValidShapeAllocationSignature(unsigned char *shape);
844
845/* Function start: 0x426B96 */
846void RestoreSpriteBackground(Viewport *viewport, unsigned char *background,
847 short x, short y, unsigned char *shape,
848 short frame)
849{
850 unsigned char *commands;
851 unsigned short rowOp;
852 unsigned char *screenRow;
853 unsigned char *pixels;
854 unsigned char action;
855 unsigned char color;
856 unsigned char *original;
857 short span;
858 int endX;
859 short yDelta;
860 short leftmost;
861 short rightmost;
862 short minY;
863 short maxY;
864 int screenX;
865 short xDelta;
866 int row;
867 int skip;
868
869 original = background;
870 if (original == 0)
871 return;
872 if (shape == 0)
873 return;
874 if (frame < 0)
875 return;
876 if (viewport->left < 0)
877 return;
878 if (HasValidShapeAllocationSignature(shape) == 0)
879 return;
880 frame++;
881 frame <<= 2;
882 if (*(unsigned short *)(shape + 4) > frame) {
883 leftmost = viewport->left;
884 rightmost = viewport->right;
885 minY = viewport->top;
886 maxY = viewport->bottom;
887 commands = shape + *(int *)(frame + shape);
888 commands += 8;
889 pixels = viewport->pixels;
890 rowOp = *(unsigned short *)commands;
891 commands += 2;
892 while (rowOp != 0) {
893 xDelta = *(short *)commands;
894 commands += 2;
895 yDelta = *(short *)commands;
896 commands += 2;
897 screenX = x + xDelta;
898 row = y + yDelta;
899 screenRow = viewport->rowOffsets[row] + screenX + pixels;
900 if ((rowOp & 1) != 0) {
901 rowOp >>= 1;
902 while (rowOp > 0) {
903 action = *commands;
904 commands++;
905 if ((action & 1) != 0) {
906 action >>= 1;
907 rowOp = (unsigned short)(rowOp - action);
908 color = *commands;
909 commands++;
910 if (minY <= row && maxY >= row) {
911 endX = action + screenX - 1;
912 if (rightmost >= screenX &&
913 leftmost <= endX) {
914 span = action;
915 skip = 0;
916 if (leftmost > screenX) {
917 span -= leftmost - screenX;
918 skip += leftmost - screenX;
919 }
920 if (rightmost < endX)
921 span -= endX - rightmost;
922 memcpy(skip + screenRow, original, span);
923 original += span;
924 }
925 }
926 screenRow += action;
927 screenX += action;
928 } else {
929 action >>= 1;
930 rowOp = (unsigned short)(rowOp - action);
931 if (minY <= row && maxY >= row) {
932 endX = action + screenX - 1;
933 if (rightmost >= screenX &&
934 leftmost <= endX) {
935 span = action;
936 skip = 0;
937 if (leftmost > screenX) {
938 span -= leftmost - screenX;
939 skip += leftmost - screenX;
940 }
941 if (rightmost < endX)
942 span -= endX - rightmost;
943 memcpy(skip + screenRow, original, span);
944 original += span;
945 }
946 }
947 commands += action;
948 screenRow += action;
949 screenX += action;
950 }
951 }
952 } else {
953 rowOp >>= 1;
954 if (minY <= row && maxY >= row) {
955 endX = rowOp + screenX - 1;
956 if (rightmost >= screenX && leftmost <= endX) {
957 span = rowOp;
958 skip = 0;
959 if (leftmost > screenX) {
960 span -= leftmost - screenX;
961 skip += leftmost - screenX;
962 }
963 if (rightmost < endX)
964 span -= endX - rightmost;
965 memcpy(skip + screenRow, original, span);
966 original += span;
967 }
968 }
969 commands += rowOp;
970 }
971 rowOp = *(unsigned short *)commands;
972 commands += 2;
973 }
974 }
975 if (viewport->pixels == g_101_stScrViewInfo.pixels)
976 MarkDibDirty();
977 (void)color;
978}
979
980/* Function start: 0x426FD9 */
981void DrawSolidColourSprite(Viewport *viewport, short x, short y,
982 unsigned char *shape, short frame,
983 unsigned short colour)
984{
985 if (viewport->left < 0)
986 return;
988 if (HasValidShapeAllocationSignature(shape) != 0)
989 DrawSpriteTransformed(viewport, x, y, shape, frame, 0,
990 0x100, 0x100, 0, 1);
991}
992
993#pragma function(abs)
994/* Function start: 0x427047 */
995void CopyViewportContents(Viewport *source, Viewport *destination)
996{
997 RasterSurface sourceSurface;
998 RasterClip targetClip;
999 int result;
1000 RasterClip srcClip;
1001 RasterSurface dstSurface;
1002
1003 if (destination->left < 0)
1004 return;
1005 if (source->left < 0)
1006 return;
1007 ValidateViewportBounds(source, &sourceSurface, &srcClip);
1008 ValidateViewportBounds(destination, &dstSurface,
1009 &targetClip);
1010 result = BlitRasterClip(
1011 &srcClip, 0, 0, &targetClip, 0, 0, 0xffffffff);
1012 if (result != 0)
1013 abs(result);
1014 if (g_nCockpitDisplayMode == 9)
1015 return;
1016 if (g_bRenderingSpaceFrame != 0 &&
1018 return;
1019 }
1020 if (GetDIBPixelBuffer() == destination->pixels) {
1021 MarkDibDirty();
1022 DIBslamReal();
1023 }
1024}
1025
1026/* Function start: 0x427123 */
1027void ClearViewport(Viewport *viewport, short colour)
1028{
1029 if (viewport->pixels != 0 && viewport->rowOffsets != 0) {
1030 if (viewport->left < 0)
1031 return;
1032 ClipViewportToScreen(viewport);
1034 }
1035}
1036
1037/* Function start: 0x427179 */
1038void DrawViewportPixel(Viewport *viewport, short x, short y,
1039 short colour)
1040{
1041 if (viewport->left < 0)
1042 return;
1043 ClipViewportToScreen(viewport);
1044 SetRasterClipPixel(&g_stScreenLimits, (int)x - viewport->left,
1045 (int)y - viewport->top, colour);
1046}
1047
1048/* Function start: 0x4271D2 */
1049short GetViewportPixel(Viewport *viewport, short x, short y)
1050{
1051 if (viewport->left < 0)
1052 return 0;
1053 ClipViewportToScreen(viewport);
1055 (int)x - viewport->left,
1056 (int)y - viewport->top);
1057}
1058
1059/* Function start: 0x42722E */
1060void DrawViewportLine(Viewport *viewport, short x1, short y1,
1061 short x2, short y2, short colour)
1062{
1063 if (viewport->left < 0)
1064 return;
1065 ClipViewportToScreen(viewport);
1067 x1 - viewport->left, y1 - viewport->top,
1068 x2 - viewport->left, y2 - viewport->top,
1069 0, colour);
1070}
1071
1072/* Left and right edge of each scanline of the polygon being filled, two
1073 * ints per row. Only FillPolygon uses it; WC1's optimized build kept the
1074 * same 1,648 bytes in gr.c without a reference. */
1075static int g_anPolyExtents[412]; /* 0x004b20a0 */
1076
1077/* Function start: 0x4272A5 */
1078/* Fills a convex polygon: clips it against the viewport's top, right,
1079 * bottom and left edges in turn, scan-converts the clipped outline into
1080 * left and right spans, and fills each span. The Win32 port returns
1081 * before any of it runs; triangle is its only caller. */
1082void FillPolygon(Viewport *viewport, ShortPoint *points, int count,
1083 char colour)
1084{
1085 ShortPoint polyB[8];
1086 int side;
1087 int prev;
1088 unsigned char *row;
1089 int bottomIndex;
1090 int stride;
1091 float denominator;
1092 int countA;
1093 int *rowBounds;
1094 int x;
1095 ShortPoint polyA[8];
1096 int topIndex;
1097 int y1;
1098 int i;
1099 int x0;
1100 int x1;
1101 int k;
1102 int y0;
1103 int countB;
1104 float distance;
1105 float fractionStep;
1106 int j;
1107 float frac;
1108 int crossed;
1109 int y;
1110
1111 return;
1112 countA = 0;
1113 y = viewport->top;
1114 for (i = 0; i < count; i++) {
1115 j = (i + 1) % count;
1116 crossed = 0;
1117 if (points[i].y >= y) {
1118 polyA[countA].x = points[i].x;
1119 polyA[countA].y = points[i].y;
1120 countA++;
1121 if (points[j].y <= y)
1122 crossed = 1;
1123 } else if (points[j].y >= y)
1124 crossed = 1;
1125 if (crossed) {
1126 distance = (float)(y - points[i].y);
1127 denominator = (float)(points[j].y - points[i].y);
1128 frac = distance / denominator;
1129 distance = (float)points[i].x;
1130 denominator = (float)(points[j].x - points[i].x);
1131 x = denominator * frac + distance + 0.5f;
1132 polyA[countA].x = x;
1133 polyA[countA].y = y;
1134 countA++;
1135 }
1136 }
1137 if (countA < 3)
1138 return;
1139
1140 countB = 0;
1141 x = viewport->right;
1142 for (i = 0; i < countA; i++) {
1143 j = (i + 1) % countA;
1144 crossed = 0;
1145 if (polyA[i].x <= x) {
1146 polyB[countB].x = polyA[i].x;
1147 polyB[countB].y = polyA[i].y;
1148 countB++;
1149 if (polyA[j].x >= x)
1150 crossed = 1;
1151 } else if (polyA[j].x <= x)
1152 crossed = 1;
1153 if (crossed) {
1154 distance = (float)(x - polyA[i].x);
1155 denominator = (float)(polyA[j].x - polyA[i].x);
1156 frac = distance / denominator;
1157 distance = (float)polyA[i].y;
1158 denominator = (float)(polyA[j].y - polyA[i].y);
1159 y = denominator * frac + distance + 0.5f;
1160 polyB[countB].x = x;
1161 polyB[countB].y = y;
1162 countB++;
1163 }
1164 }
1165 if (countB < 3)
1166 return;
1167
1168 countA = 0;
1169 y = viewport->bottom;
1170 for (i = 0; i < countB; i++) {
1171 j = (i + 1) % countB;
1172 crossed = 0;
1173 if (polyB[i].y <= y) {
1174 polyA[countA].x = polyB[i].x;
1175 polyA[countA].y = polyB[i].y;
1176 countA++;
1177 if (polyB[j].y >= y)
1178 crossed = 1;
1179 } else if (polyB[j].y <= y)
1180 crossed = 1;
1181 if (crossed) {
1182 distance = (float)(y - polyB[i].y);
1183 denominator = (float)(polyB[j].y - polyB[i].y);
1184 frac = distance / denominator;
1185 distance = (float)polyB[i].x;
1186 denominator = (float)(polyB[j].x - polyB[i].x);
1187 x = denominator * frac + distance + 0.5f;
1188 polyA[countA].x = x;
1189 polyA[countA].y = y;
1190 countA++;
1191 }
1192 }
1193 if (countA < 3)
1194 return;
1195
1196 countB = 0;
1197 x = viewport->left;
1198 for (i = 0; i < countA; i++) {
1199 j = (i + 1) % countA;
1200 crossed = 0;
1201 if (polyA[i].x >= x) {
1202 polyB[countB].x = polyA[i].x;
1203 polyB[countB].y = polyA[i].y;
1204 countB++;
1205 if (polyA[j].x <= x)
1206 crossed = 1;
1207 } else if (polyA[j].x >= x)
1208 crossed = 1;
1209 if (crossed) {
1210 distance = (float)(x - polyA[i].x);
1211 denominator = (float)(polyA[j].x - polyA[i].x);
1212 frac = distance / denominator;
1213 distance = (float)polyA[i].y;
1214 denominator = (float)(polyA[j].y - polyA[i].y);
1215 y = denominator * frac + distance + 0.5f;
1216 polyB[countB].x = x;
1217 polyB[countB].y = y;
1218 countB++;
1219 }
1220 }
1221 if (countB < 3)
1222 return;
1223
1224 bottomIndex = topIndex = 0;
1225 y = countB;
1226 while (y--) {
1227 if (polyB[topIndex].y == polyB[y].y) {
1228 if (polyB[topIndex].x > polyB[y].x)
1229 topIndex = y;
1230 } else if (polyB[topIndex].y > polyB[y].y)
1231 topIndex = y;
1232 else if (polyB[bottomIndex].y < polyB[y].y)
1233 bottomIndex = y;
1234 }
1235
1236 i = prev = topIndex;
1237 side = 0;
1238 crossed = 0;
1239 for (k = 0; k < countB; k++) {
1240 if (--prev < 0)
1241 prev = countB - 1;
1242 x0 = polyB[i].x;
1243 y0 = polyB[i].y;
1244 x1 = polyB[prev].x;
1245 y1 = polyB[prev].y;
1246 if (--i < 0)
1247 i = countB - 1;
1248 if (crossed == 0 && y1 < y0) {
1249 side = 1;
1250 crossed = 1;
1251 }
1252 if (x1 == x0) {
1253 if (y1 < y0) {
1254 x = x0;
1255 x0 = x1;
1256 x1 = x;
1257 y = y0;
1258 y0 = y1;
1259 y1 = y;
1260 }
1261 for (y = y0; y <= y1; y++)
1262 g_anPolyExtents[y * 2 + side] = x0;
1263 } else if (y1 == y0) {
1264 if (x1 > x0) {
1265 g_anPolyExtents[y0 * 2] = x0;
1266 g_anPolyExtents[y0 * 2 + 1] = x1;
1267 } else {
1268 g_anPolyExtents[y0 * 2] = x1;
1269 g_anPolyExtents[y0 * 2 + 1] = x0;
1270 }
1271 } else {
1272 if (y1 < y0) {
1273 x = x0;
1274 x0 = x1;
1275 x1 = x;
1276 y = y0;
1277 y0 = y1;
1278 y1 = y;
1279 }
1280 fractionStep = 1.0f / ((y1 - y0) + 1.0f);
1281 frac = 0;
1282 g_anPolyExtents[y0 * 2 + side] = x0;
1283 for (y = y0; y <= y1; y++) {
1284 g_anPolyExtents[y * 2 + side] =
1285 (x1 - x0) * frac + x0;
1286 frac += fractionStep;
1287 }
1288 g_anPolyExtents[y1 * 2 + side] = x1;
1289 }
1290 }
1291
1292 i = polyB[topIndex].y * 2;
1293 if (g_anPolyExtents[i + 1] < g_anPolyExtents[i]) {
1294 for (y = polyB[topIndex].y; y < polyB[bottomIndex].y; y++) {
1295 i = y * 2;
1296 x0 = g_anPolyExtents[i];
1297 g_anPolyExtents[i] = g_anPolyExtents[i + 1];
1298 g_anPolyExtents[i + 1] = x0;
1299 }
1300 }
1301
1302 stride = viewport->rowOffsets[1];
1303 row = viewport->pixels;
1304 row += (polyB[topIndex].y - viewport->top) * stride;
1305 rowBounds = &g_anPolyExtents[polyB[topIndex].y * 2];
1306 x = viewport->left;
1307 for (y = polyB[topIndex].y; y <= polyB[bottomIndex].y; y++) {
1308 memset(row + (rowBounds[0] - x), colour, abs(rowBounds[1] - rowBounds[0]) + 1);
1309 row += stride;
1310 rowBounds += 2;
1311 }
1312 if (viewport->pixels == g_101_stScrViewInfo.pixels)
1313 MarkDibDirty();
1314}
1315
1316/* Function start: 0x427D9F */
1317/* Nothing in the shipped executable calls this. */
1318void triangle(Viewport *viewport, ShortPoint *points, int colour)
1319{
1320 FillPolygon(viewport, points, 3, colour);
1321 if (viewport->pixels == g_101_stScrViewInfo.pixels)
1322 MarkDibDirty();
1323 RasterLineHook("triangle");
1324 return;
1325}
1326
1327/* Function start: 0x427DE8 */
1328/* Nothing in the shipped executable calls this; the Win32 port does not
1329 * implement the driver's shaded triangle and only reports the call. */
1331{
1332 if (viewport->pixels == g_101_stScrViewInfo.pixels)
1333 MarkDibDirty();
1334 RasterLineHook("shaded_triangle");
1335 return;
1336}
1337
1338/* Function start: 0x427E1B */
1339void DrawFilledViewportRect(Viewport *viewport, short left, short top,
1340 short right, short bottom, short colour)
1341{
1342 int y;
1343 int rows;
1344
1345 rows = bottom - top;
1346 if (viewport->left < 0)
1347 return;
1348 ClipViewportToScreen(viewport);
1349 for (y = 0; y <= rows; y++) {
1351 left - viewport->left,
1352 y + top - viewport->top,
1353 right - viewport->left,
1354 y + top - viewport->top,
1355 0, colour);
1356 }
1357}
1358
1359/* Function start: 0x427EC8 */
1360void DrawViewportBorder(Viewport *viewport, short left, short top,
1361 short right, short bottom, short colour)
1362{
1363 if (viewport->left < 0)
1364 return;
1365 ClipViewportToScreen(viewport);
1367 left - viewport->left, top - viewport->top,
1368 right - viewport->left, top - viewport->top,
1369 0, colour);
1371 left - viewport->left, bottom - viewport->top,
1372 right - viewport->left, bottom - viewport->top,
1373 0, colour);
1375 left - viewport->left, top - viewport->top,
1376 left - viewport->left, bottom - viewport->top,
1377 0, colour);
1379 right - viewport->left, top - viewport->top,
1380 right - viewport->left, bottom - viewport->top,
1381 0, colour);
1382}
1383
1384/* Function start: 0x428023 */
1385void DrawViewportEllipse(Viewport *viewport, short x, short y,
1386 short verticalRadius, short horizontalRadius,
1387 short colour)
1388{
1389 if (viewport->left < 0)
1390 return;
1391 ClipViewportToScreen(viewport);
1392 DrawRasterEllipse(&g_stScreenLimits, x, y, horizontalRadius,
1393 verticalRadius, colour);
1394 if (viewport->pixels == g_101_stScrViewInfo.pixels)
1395 MarkDibDirty();
1396 return;
1397}
1398
1399/* Function start: 0x42808F */
1400void FillViewportEllipse(Viewport *viewport, short x, short y,
1401 short verticalRadius, short horizontalRadius,
1402 short colour)
1403{
1404 if (viewport->left < 0)
1405 return;
1406 ClipViewportToScreen(viewport);
1407 FillRasterEllipse(&g_stScreenLimits, x, y, horizontalRadius,
1408 verticalRadius, colour);
1409 if (viewport->pixels == g_101_stScrViewInfo.pixels)
1410 MarkDibDirty();
1411 return;
1412}
1413
1414/* Function start: 0x4280FB */
1415void DrawViewportEllipseShadow(Viewport *viewport, short x, short y,
1416 short verticalRadius,
1417 short horizontalRadius, short colour)
1418{
1419 if (viewport->left < 0)
1420 return;
1421 ClipViewportToScreen(viewport);
1422 DrawRasterEllipse(&g_stScreenLimits, x, y, horizontalRadius,
1423 verticalRadius, colour);
1424 if (viewport->pixels == g_101_stScrViewInfo.pixels)
1425 MarkDibDirty();
1426 return;
1427}
1428
1429/* Function start: 0x428167 */
1430/* Nothing in the shipped executable calls this; the Win32 port does not
1431 * implement the driver's shadow drawing and only reports the call. */
1432void shadow_draw(Viewport *viewport)
1433{
1434 if (viewport->left < 0)
1435 return;
1436 if (viewport->pixels == g_101_stScrViewInfo.pixels)
1437 MarkDibDirty();
1438 RasterLineHook("shadow_draw");
1439 return;
1440}
1441
1442/* Function start: 0x4281AE */
1443/* Nothing in the shipped executable calls this. Draws a shape frame with
1444 * one scale for both axes. */
1445void DrawShapeFrameScaled(Viewport *viewport, unsigned char *shape,
1446 int frame, int x, int y, int angle, int scale)
1447{
1448 if (viewport->left < 0)
1449 return;
1450 if (shape == 0)
1451 return;
1452 if (frame < 0)
1453 return;
1454 DrawSpriteTransformed(viewport, x, y, shape, frame, angle, scale, scale,
1455 0, 0);
1456}
1457
1458/* Function start: 0x428217 */
1459/* Nothing in the shipped executable calls this. Stores the four corners of
1460 * a shape frame's box, placed at (x, y), as a polygon. */
1461void GetShapeFrameCorners(unsigned char *shape, int frame, int x, int y,
1462 short *points, int *count)
1463{
1464 unsigned char *base;
1465 int right;
1466 int minX;
1467 int minY;
1468 int maxY;
1469
1470 base = shape;
1471 *count = 0;
1473 frame++;
1474 frame <<= 2;
1475 if (*(unsigned short *)(shape + 4) >= frame) {
1476 shape += *(int *)(frame + shape);
1477 right = *(short *)(shape + 2) + x;
1478 minX = *(short *)shape + x;
1479 minY = *(short *)(shape + 4) + y;
1480 maxY = *(short *)(shape + 6) + y;
1481 points[0] = (short)right;
1482 points[1] = (short)minY;
1483 points[2] = (short)right;
1484 points[3] = (short)maxY;
1485 points[4] = (short)minX;
1486 points[5] = (short)maxY;
1487 points[6] = (short)minX;
1488 points[7] = (short)minY;
1489 *count = 4;
1490 }
1491}
1492
1493/* Function start: 0x4282F0 */
1494void DrawSpriteScaled(Viewport *viewport, short x, short y,
1495 unsigned char *shape, short frame, short angle,
1496 short scale, short flip)
1497{
1498 if (HasValidShapeAllocationSignature(shape) != 0) {
1499 DrawSpriteTransformed(viewport, x, y, shape, frame, angle,
1500 scale, scale, flip, 0);
1501 }
1502}
1503
1504/* Function start: 0x428344 */
1505void DrawSolidColourSpriteScaled(Viewport *viewport, short x, short y,
1506 unsigned char *shape, short frame,
1507 short angle, short scale, short flip,
1508 unsigned short colour)
1509{
1511 if (HasValidShapeAllocationSignature(shape) != 0) {
1512 DrawSpriteTransformed(viewport, x, y, shape, frame, angle,
1513 scale, scale, flip, 1);
1514 }
1515}
1516
1517/* Function start: 0x4283A4 */
1518short GetTransformedShapeBounds(Viewport *viewport, short x, short y,
1519 unsigned char *shape, short frame,
1520 short angle, short scale, short flip,
1521 short *bounds)
1522{
1523 int touches;
1524 ShortRect box;
1525 int s;
1526 int transformedHeight;
1527 int framePos;
1528 int frameBottom;
1529 int width;
1530 int right;
1531 int widthSum;
1532 int topExtent;
1533 int fullHeight;
1534 unsigned char *frameHeader;
1535 int topY;
1536 int frameLeft;
1537 int screenLeft;
1538 int cosTerm;
1539
1540 touches = 0;
1541 if (shape == 0) {
1542 if (viewport->left > x || viewport->right < x ||
1543 viewport->top > y || viewport->bottom < y)
1544 touches = 0;
1545 else
1546 touches = 1;
1547 return (short)touches;
1548 }
1549 if (HasValidShapeAllocationSignature(shape) == 0)
1550 return 0;
1552 framePos = frame;
1553 frameHeader = shape;
1554 framePos++;
1555 framePos <<= 2;
1556 if (*(unsigned short *)(frameHeader + 4) >= framePos) {
1557 frameHeader += *(int *)(framePos + frameHeader);
1558 right = *(short *)(frameHeader + 2);
1559 frameLeft = *(short *)frameHeader;
1560 topExtent = *(short *)(frameHeader + 4);
1561 frameBottom = *(short *)(frameHeader + 6);
1562 cosTerm = g_awAbsoluteCosine[angle] * scale;
1563 cosTerm >>= 8;
1564 s = g_awAbsoluteSine[angle] * scale;
1565 s >>= 8;
1566 if (cosTerm == 0)
1567 cosTerm++;
1568 if (s == 0)
1569 s++;
1570 widthSum = frameLeft + right;
1571 fullHeight = frameBottom + topExtent;
1572 /* WC2 rounds each extent up when the 8.8 fraction is not zero. */
1573 transformedHeight = s * widthSum + cosTerm * fullHeight;
1574 if ((transformedHeight & 0xff) != 0)
1575 transformedHeight += 0x100;
1576 transformedHeight >>= 8;
1577 width = s * fullHeight + cosTerm * widthSum;
1578 if ((width & 0xff) != 0)
1579 width += 0x100;
1580 width >>= 8;
1581 if (cosTerm == 0)
1582 cosTerm = 1;
1583 if (s == 0)
1584 s = 1;
1585 screenLeft = (s * topExtent >> 8) + x - (cosTerm * right >> 8);
1586 topY = y - (cosTerm * topExtent >> 8) - (s * right >> 8);
1587 box.top = (short)topY;
1588 box.bottom = (short)(box.top + transformedHeight);
1589 fullHeight = s * fullHeight;
1590 fullHeight >>= 8;
1591 fullHeight++;
1592 fullHeight = screenLeft - fullHeight;
1593 box.left = (short)fullHeight;
1594 box.right = (short)(fullHeight + width);
1595 if (viewport->left > box.right || viewport->right < box.left ||
1596 viewport->top > box.bottom || box.top > viewport->bottom) {
1597 touches = 0;
1598 } else {
1599 bounds[0] = box.left;
1600 bounds[2] = box.right;
1601 bounds[1] = box.top;
1602 bounds[3] = box.bottom;
1603 touches = 1;
1604 }
1605 }
1606 (void)flip;
1607 return (short)touches;
1608}
1609
1610/* Function start: 0x428690 */
1611/* WC2 walks the geometry record as a raw run list: two shorts of header, the
1612 * source origin, then a destinationX/y/span triple per run ending at
1613 * -1. */
1614void CopyViewportRuns(Viewport *source, Viewport *destination,
1615 const short *runs)
1616{
1617 unsigned short span;
1618 short srcLeft;
1619 short srcTop;
1620 short destinationX;
1621 short y;
1622
1623 if (source->pixels == 0 || destination->pixels == 0)
1624 return;
1625 if (destination->left < 0)
1626 return;
1627 runs += 2;
1628 srcLeft = *runs;
1629 runs++;
1630 srcTop = *runs;
1631 runs++;
1632 destinationX = *runs;
1633 runs++;
1634 while (destinationX != -1) {
1635 y = *runs;
1636 runs++;
1637 span = (unsigned short)*runs;
1638 runs++;
1639 memcpy(destination->rowOffsets[y] + destinationX +
1640 destination->pixels,
1641 source->rowOffsets[y - srcTop] + destinationX +
1642 source->pixels - srcLeft,
1643 span);
1644 destinationX = *runs;
1645 runs++;
1646 }
1647 if (destination->pixels == g_101_stScrViewInfo.pixels)
1648 MarkDibDirty();
1649}
1650
1651/* Function start: 0x4287A4 */
1652/* Nothing in the shipped executable calls this; the Win32 port does not
1653 * implement the driver's fizzle fade and only reports the call. */
1654void fizzle_fade(Viewport *source, Viewport *destination)
1655{
1656 if (destination->left < 0)
1657 return;
1658 if (destination->pixels == g_101_stScrViewInfo.pixels)
1659 MarkDibDirty();
1660 RasterLineHook("fizzle_fade");
1661 return;
1662}
1663
1664/* Function start: 0x4287EB */
1665void snow_viewport(Viewport *viewport, int effect,
1666 unsigned short colour)
1667{
1668 int left;
1669 int yLast;
1670 int endX;
1671 unsigned char *dest;
1672 int topY;
1673 int rowWidth;
1674 int y;
1675 int lines;
1676 int countdown;
1677
1678 if (viewport->left < 0)
1679 return;
1680 if (viewport->pixels == g_101_stScrViewInfo.pixels) {
1681 left = viewport->left;
1682 topY = viewport->top;
1683 endX = viewport->right;
1684 yLast = viewport->bottom;
1685 rowWidth = endX - left + 1;
1686 for (y = topY; y < yLast; y++) {
1687 dest = viewport->rowOffsets[y] + viewport->left +
1688 viewport->pixels;
1689 countdown = rowWidth;
1690 while (countdown-- != 0) {
1692 *dest = (unsigned char)colour;
1693 else
1695 dest++;
1696 }
1697 }
1698 MarkDibDirty();
1699 }
1700 RasterLineHook("snow_viewport");
1701 return;
1702}
1703
1704/* Linker commons defined here. LINK lays a unit's commons out by the
1705 * identifiers' hash keys, so these spellings follow the original addresses. */
1706int g_nShapePrepareTicks; /* 0x005d2fd0 */
1707int g_1_nShapeClipTicksValue; /* 0x005d2fd4 */
1708int g_nShapeDrawTicks; /* 0x005d2fd8 */
void(__cdecl *g_pIxFree)(void *)
int FillRasterClip(RasterClip *clip, int colour)
void CheckHeapBlockSignature(unsigned char *shape)
Definition gr.c:112
void DrawViewportLine(Viewport *viewport, short x1, short y1, short x2, short y2, short colour)
Definition gr.c:1060
void PrepareShapeRLEData(unsigned char *shape)
Definition gr.c:363
void DrawViewportEllipseShadow(Viewport *viewport, short x, short y, short verticalRadius, short horizontalRadius, short colour)
Definition gr.c:1415
void snow_viewport(Viewport *viewport, int effect, unsigned short colour)
Definition gr.c:1665
void triangle(Viewport *viewport, ShortPoint *points, int colour)
Definition gr.c:1318
void GetShapeFrameCorners(unsigned char *shape, int frame, int x, int y, short *points, int *count)
Definition gr.c:1461
void SetPaletteEntry(short index, short *rgb)
Definition gr.c:676
int ReadRasterClipPixel(RasterClip *clip, int x, int y)
short GetTransformedShapeBounds(Viewport *viewport, short x, short y, unsigned char *shape, short frame, short angle, short scale, short flip, short *bounds)
Definition gr.c:1518
unsigned int SetRasterClipPixel(RasterClip *clip, int x, int y, int colour)
void DrawSolidColourSpriteScaled(Viewport *viewport, short x, short y, unsigned char *shape, short frame, short angle, short scale, short flip, unsigned short colour)
Definition gr.c:1505
void DrawShapeFrameScaled(Viewport *viewport, unsigned char *shape, int frame, int x, int y, int angle, int scale)
Definition gr.c:1445
unsigned int DrawClippedLine(RasterClip *clip, int x1, int y1, int x2, int y2, int mode, int colour)
void __copyline(void)
Definition gr.c:647
void DrawViewportPixel(Viewport *viewport, short x, short y, short colour)
Definition gr.c:1038
void SetSolidColourTranslation(unsigned char colour)
Definition gr.c:354
unsigned int DrawRasterEllipse(RasterClip *clip, int x, int y, int horizontalRadius, int verticalRadius, int colour)
void DrawSolidColourSprite(Viewport *viewport, short x, short y, unsigned char *shape, short frame, unsigned short colour)
Definition gr.c:981
void DrawSpriteDefault(Viewport *viewport, short x, short y, unsigned char *shape, short frame)
Definition gr.c:682
void GetPaletteEntryAsWords(short i, unsigned short *rgb)
Definition dib.cpp:900
void DIBslamReal(void)
Definition dib.cpp:562
int IsFreedHeapBlockTracked(void *memory)
Definition winmain.c:806
void ValidateViewportBounds(Viewport *viewport, RasterSurface *surface, RasterClip *clip)
Definition gr.c:307
void CopyViewportRuns(Viewport *source, Viewport *destination, const short *runs)
Definition gr.c:1614
void DIBsetPalette(short index, short *rgb)
Definition dib.cpp:854
void ReadPerformanceCounter(LARGE_INTEGER *p)
Definition mono.c:87
void DrawFilledViewportRect(Viewport *viewport, short left, short top, short right, short bottom, short colour)
Definition gr.c:1339
int RotateRLEImage(RasterClip *clip, unsigned char *shape, int frame, int x, int y, unsigned char *scratch, unsigned int angleTenths, int scaleX, int scaleY, unsigned int flags)
int SignExtendClipCoord(volatile short v)
Definition gr.c:297
void * AllocateTaggedMemory(unsigned int size, short flags)
Definition memapi.c:92
void DrawSpriteTransformed(Viewport *viewport, int x, int y, unsigned char *shape, int frame, int angle, int scaleX, int scaleY, int flip, int blendMode)
Definition gr.c:476
void CaptureSpriteBackground(Viewport *viewport, unsigned char *background, short x, short y, unsigned char *shape, short frame)
Definition gr.c:705
void GetShapeFrameExtents(unsigned char *shape, short frame, short *width, short *height, short *leftExtent, short *topExtent)
Definition gr.c:144
void shadow_draw(Viewport *viewport)
Definition gr.c:1432
void ClipViewportToScreen(Viewport *viewport)
Definition gr.c:346
void EstablishColors(Viewport *viewport, unsigned char *active)
Definition gr.c:663
unsigned char * GetDIBPixelBuffer(void)
Definition dib.cpp:779
void RestoreSpriteBackground(Viewport *viewport, unsigned char *background, short x, short y, unsigned char *shape, short frame)
Definition gr.c:846
void FillPolygon(Viewport *viewport, ShortPoint *points, int count, char colour)
Definition gr.c:1082
short RandomBelow(short n)
Definition eventmgr.c:12
void DrawViewportEllipse(Viewport *viewport, short x, short y, short verticalRadius, short horizontalRadius, short colour)
Definition gr.c:1385
void DrawViewportBorder(Viewport *viewport, short left, short top, short right, short bottom, short colour)
Definition gr.c:1360
void SetPaletteTranslationTable(const unsigned char *translation)
void ClearViewport(Viewport *viewport, short colour)
Definition gr.c:1027
void __wipeline(void)
Definition gr.c:656
void RasterLineHook(const void *marker)
Definition gr.c:533
unsigned int FillRasterEllipse(RasterClip *clip, int x, int y, int horizontalRadius, int verticalRadius, int colour)
void GetPaletteEntry(short index, unsigned short *rgb)
Definition gr.c:670
void ReleasePacketHandle(void *handle)
Definition memapi.c:108
void DrawFontGlyph(char character, TextContext *context, int height, int width, int y)
Definition gr.c:540
void DrawSpriteScaled(Viewport *viewport, short x, short y, unsigned char *shape, short frame, short angle, short scale, short flip)
Definition gr.c:1494
void fizzle_fade(Viewport *source, Viewport *destination)
Definition gr.c:1654
void exit_squadron(const char *msg,...)
Definition message.c:44
void shaded_triangle(Viewport *viewport)
Definition gr.c:1330
short GetShapeFrameCount(unsigned char *shape)
Definition gr.c:137
short GetViewportPixel(Viewport *viewport, short x, short y)
Definition gr.c:1049
int HasValidShapeAllocationSignature(unsigned char *shape)
Definition gr.c:123
unsigned char * GetPreparedShapeData(unsigned char *shape)
Definition gr.c:131
void MarkDibDirty(void)
Definition dib.cpp:532
void CopyViewportContents(Viewport *source, Viewport *destination)
Definition gr.c:995
void DecodeShapeFrame(unsigned char *shape, short frame, unsigned char *bitmap, int width, int height, int leftExtent, int topExtent)
Definition gr.c:171
int BlitRasterClip(RasterClip *source, int sourceX, int sourceY, RasterClip *destination, int destinationX, int destinationY, unsigned int colour)
void FillViewportEllipse(Viewport *viewport, short x, short y, short verticalRadius, short horizontalRadius, short colour)
Definition gr.c:1400
Shared Win32 declarations, types and library interfaces.
int g_nCockpitDisplayMode
Definition main.c:1929
GR_STATIC RasterClip g_stScreenLimits
Definition globals.h:994
const int g_nViewportStaticRandomRange
Definition gr.c:10
unsigned char * g_apViewportAllocations[128]
Definition vpfree.c:52
unsigned short g_awAbsoluteSine[360]
Definition gr.c:78
unsigned char g_abPaletteTranslation[256]
Definition gr.c:12
int g_bSceneDisplayUpdateActive
Definition campglob.c:494
int g_nShapeDrawTicks
Definition gr.c:1708
GR_STATIC unsigned char g_13_abShapeRLEScratch[0x100000]
Definition globals.h:996
unsigned char g_cSecondaryViewBufferColour
Definition startup.c:544
GR_STATIC RasterSurface g_1_stRasterBitmap
Definition globals.h:992
int g_nViewportAllocationCount
Definition vpfree.c:51
int g_1_nShapeClipTicksValue
Definition gr.c:1707
GR_STATIC unsigned char g_abSolidColourTranslation[256]
Definition globals.h:995
Viewport g_101_stScrViewInfo
Definition cockpt.c:3831
int g_bRenderingSpaceFrame
Definition main.c:1992
int g_nShapePrepareTicks
Definition gr.c:1706
unsigned short g_awAbsoluteCosine[360]
Definition gr.c:46
GR_STATIC unsigned char g_abShapeTransformScratch[0xfa00]
Definition globals.h:993
static int g_anPolyExtents[412]
Definition gr.c:1075
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
short top
Definition game_data.h:480
short left
Definition game_data.h:479
short right
Definition game_data.h:481
short bottom
Definition game_data.h:482
unsigned char colour
Definition game.h:288
unsigned char * font
Definition game.h:287
FontWorkspace ** fontWorkspace
Definition game.h:293
unsigned char backgroundColour
Definition game.h:289
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 short * rowOffsets
Definition game.h:151
short left
Definition game.h:152
short top
Definition game.h:153