1 /*
2 SHAPES.C
3
4 Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 and the "Aleph One" developers.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 This license is contained in the file "COPYING",
18 which is included with this source code; it is available online at
19 http://www.gnu.org/licenses/gpl.html
20
21 Saturday, September 4, 1993 9:26:41 AM
22
23 Thursday, May 19, 1994 9:06:28 AM
24 unification of wall and object shapes complete, new shading table builder.
25 Wednesday, June 22, 1994 11:55:07 PM
26 we now read data from alain�s shape extractor.
27 Saturday, July 9, 1994 3:22:11 PM
28 lightening_table removed; we now build darkening tables on a collection-by-collection basis
29 (one 8k darkening table per clut permutation of the given collection)
30 Monday, October 3, 1994 4:17:15 PM (Jason)
31 compressed or uncompressed collection resources
32 Friday, June 16, 1995 11:34:08 AM (Jason)
33 self-luminescent colors
34
35 Jan 30, 2000 (Loren Petrich):
36 Changed "new" to "_new" to make data structures more C++-friendly
37 Did some typecasts
38
39 Feb 3, 2000 (Loren Petrich):
40 Changed _collection_madd to _collection_vacbob (later changed all "vacbob"'s to "civilian_fusion"'s)
41
42 Feb 4, 2000 (Loren Petrich):
43 Changed halt() to assert(false) for better debugging
44
45 Feb 12, 2000 (Loren Petrich):
46 Set up a fallback strategy for the colors;
47 when there are more colors in all the tables than there are in the general color table,
48 then look for the nearest one.
49
50 Feb 24, 2000 (Loren Petrich):
51 Added get_number_of_collection_frames(), so as to assist in wall-texture error checking
52
53 Mar 14, 2000 (Loren Petrich):
54 Added accessors for number of bitmaps and which bitmap index for a frame index;
55 these will be useful for OpenGL rendering
56
57 Mar 23, 2000 (Loren Petrich):
58 Made infravision tinting more generic and reassignable
59
60 Aug 12, 2000 (Loren Petrich):
61 Using object-oriented file handler
62
63 Aug 14, 2000 (Loren Petrich):
64 Turned collection and shading-table handles into pointers,
65 because handles are needlessly MacOS-specific,
66 and because these are variable-format objects.
67
68 Aug 26, 2000 (Loren Petrich):
69 Moved get_default_shapes_spec() to preprocess_map_mac.c
70
71 Sept 2, 2000 (Loren Petrich):
72 Added shapes-file unpacking.
73
74 Jan 17, 2001 (Loren Petrich):
75 Added support for offsets for OpenGL-rendered substitute textures
76 */
77
78 /*
79 //gracefully handle out-of-memory conditions when loading shapes. it will happen.
80 //get_shape_descriptors() needs to look at high-level instead of low-level shapes when fetching scenery instead of walls/ceilings/floors
81 //get_shape_information() is called often, and is quite slow
82 //it is possible to have more than 255 low-level shapes in a collection, which means the existing shape_descriptor is too small
83 //must build different shading tables for each collection (even in 8-bit, for alternate color tables)
84 */
85
86 #include "cseries.h"
87
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <string.h>
91
92 #include "shell.h"
93 #include "render.h"
94 #include "interface.h"
95 #include "collection_definition.h"
96 #include "screen.h"
97 #include "game_errors.h"
98 #include "FileHandler.h"
99 #include "progress.h"
100 #include "images.h"
101
102 #include "map.h"
103
104 // LP addition: OpenGL support
105 #include "OGL_Render.h"
106 #include "OGL_LoadScreen.h"
107
108 // LP addition: infravision XML setup needs colors
109 #include "InfoTree.h"
110
111 #include "Packing.h"
112 #include "SW_Texture_Extras.h"
113
114 #include <SDL_rwops.h>
115 #include <memory>
116
117 #include <boost/shared_ptr.hpp>
118
119 #include "Plugins.h"
120
121 /* ---------- constants */
122
123 #define iWHITE 1
124 #ifdef SCREAMING_METAL
125 #define iBLACK 255
126 #else
127 #define iBLACK 18
128 #endif
129
130 /* each collection has a tint table which (fully) tints the clut of that collection to whatever it
131 looks like through the light enhancement goggles */
132 #define NUMBER_OF_TINT_TABLES 1
133
134 // Moved from shapes_macintosh.c:
135
136 // Possibly of historical interest:
137 // #define COLLECTIONS_RESOURCE_BASE 128
138 // #define COLLECTIONS_RESOURCE_BASE16 1128
139
140 enum /* collection status */
141 {
142 markNONE,
143 markLOAD= 1,
144 markUNLOAD= 2,
145 markSTRIP= 4 /* we don�t want bitmaps, just high/low-level shape data */,
146 markPATCHED = 8 /* force re-load */
147 };
148
149 enum /* flags */
150 {
151 _collection_is_stripped= 0x0001
152 };
153
154 /* ---------- macros */
155
156 // LP: fake portable-files stuff
memory_error()157 inline short memory_error() {return 0;}
158
159 /* ---------- structures */
160
161 /* ---------- globals */
162
163 extern SDL_Surface* world_pixels;
164
165 #include "shape_definitions.h"
166
167 static pixel16 *global_shading_table16= (pixel16 *) NULL;
168 static pixel32 *global_shading_table32= (pixel32 *) NULL;
169
170 short number_of_shading_tables, shading_table_fractional_bits, shading_table_size;
171
172 // LP addition: opened-shapes-file object
173 static OpenedFile ShapesFile;
174 static OpenedResourceFile M1ShapesFile;
175
176 static enum {
177 M1_SHAPES_VERSION = 1,
178 M2_SHAPES_VERSION
179 } shapes_file_version;
180
shapes_file_is_m1()181 bool shapes_file_is_m1() { return shapes_file_version == M1_SHAPES_VERSION; }
182
183 /* ---------- private prototypes */
184
185 static void update_color_environment(bool is_opengl);
186 static short find_or_add_color(struct rgb_color_value *color, struct rgb_color_value *colors, short *color_count, bool update_flags);
187 static void _change_clut(void (*change_clut_proc)(struct color_table *color_table), struct rgb_color_value *colors, short color_count);
188
189 static void build_shading_tables8(struct rgb_color_value *colors, short color_count, pixel8 *shading_tables);
190 static void build_shading_tables16(struct rgb_color_value *colors, short color_count, pixel16 *shading_tables, byte *remapping_table, bool is_opengl);
191 static void build_shading_tables32(struct rgb_color_value *colors, short color_count, pixel32 *shading_tables, byte *remapping_table, bool is_opengl);
192 static void build_global_shading_table16(void);
193 static void build_global_shading_table32(void);
194
195 static bool get_next_color_run(struct rgb_color_value *colors, short color_count, short *start, short *count);
196 static bool new_color_run(struct rgb_color_value *_new, struct rgb_color_value *last);
197
198 static int32 get_shading_table_size(short collection_code);
199
200 static void build_collection_tinting_table(struct rgb_color_value *colors, short color_count, short collection_index, bool is_opengl);
201 static void build_tinting_table8(struct rgb_color_value *colors, short color_count, pixel8 *tint_table, short tint_start, short tint_count);
202 static void build_tinting_table16(struct rgb_color_value *colors, short color_count, pixel16 *tint_table, struct rgb_color *tint_color);
203 static void build_tinting_table32(struct rgb_color_value *colors, short color_count, pixel32 *tint_table, struct rgb_color *tint_color, bool is_opengl);
204
205 static void precalculate_bit_depth_constants(void);
206
207 static bool collection_loaded(struct collection_header *header);
208 static void unload_collection(struct collection_header *header);
209 static void unlock_collection(struct collection_header *header);
210 static void lock_collection(struct collection_header *header);
211 static bool load_collection(short collection_index, bool strip);
212
213 static void shutdown_shape_handler(void);
214 static void close_shapes_file(void);
215
216 // static byte *make_stripped_collection(byte *collection);
217
218 /* --------- collection accessor prototypes */
219
220 // Modified to return NULL for unloaded collections and out-of-range indices for collection contents.
221 // This is to allow for more graceful degradation.
222
223 static struct collection_header *get_collection_header(short collection_index);
224 /*static*/ struct collection_definition *get_collection_definition(short collection_index);
225 static void *get_collection_shading_tables(short collection_index, short clut_index);
226 static void *get_collection_tint_tables(short collection_index, short tint_index);
227 static struct rgb_color_value *get_collection_colors(short collection_index, short clut_number);
228 static struct high_level_shape_definition *get_high_level_shape_definition(short collection_index, short high_level_shape_index);
229 static struct bitmap_definition *get_bitmap_definition(short collection_index, short bitmap_index);
230
231
232 #include <SDL_endian.h>
233 #include "byte_swapping.h"
234
235 /*
236 * Initialize shapes handling
237 */
238
initialize_pixmap_handler()239 static void initialize_pixmap_handler()
240 {
241 // nothing to do
242 }
243
244
245 /*
246 * Convert shape to surface
247 */
248
249 // ZZZ extension: pass out (if non-NULL) a pointer to a block of pixel data -
250 // caller should free() that storage after freeing the returned surface.
251 // Only needed for RLE-encoded shapes.
252 // Note that default arguments are used to make this function
253 // source-code compatible with existing usage.
254 // Note also that inShrinkImage currently only applies to RLE shapes.
get_shape_surface(int shape,int inCollection,byte ** outPointerToPixelData,float inIllumination,bool inShrinkImage)255 SDL_Surface *get_shape_surface(int shape, int inCollection, byte** outPointerToPixelData, float inIllumination, bool inShrinkImage)
256 {
257 // Get shape information
258 int collection_index = GET_COLLECTION(GET_DESCRIPTOR_COLLECTION(shape));
259 int clut_index = GET_COLLECTION_CLUT(GET_DESCRIPTOR_COLLECTION(shape));
260 int low_level_shape_index = GET_DESCRIPTOR_SHAPE(shape);
261
262 if(inCollection != NONE) {
263 collection_index = GET_COLLECTION(inCollection);
264 clut_index = GET_COLLECTION_CLUT(inCollection);
265 low_level_shape_index = shape;
266 }
267
268 struct collection_definition *collection = get_collection_definition(collection_index);
269 struct low_level_shape_definition *low_level_shape = get_low_level_shape_definition(collection_index, low_level_shape_index);
270 if (!low_level_shape) return NULL;
271 struct bitmap_definition *bitmap;
272 SDL_Color colors[256];
273
274 if(inIllumination >= 0) {
275 assert(inIllumination <= 1.0f);
276
277 // ZZZ: get shading tables to use instead of CLUT, if requested
278 void* shading_tables_as_void;
279 extended_get_shape_bitmap_and_shading_table(BUILD_COLLECTION(collection_index, clut_index), low_level_shape_index,
280 &bitmap, &shading_tables_as_void, _shading_normal);
281 if (!bitmap) return NULL;
282
283 switch(bit_depth) {
284 case 16:
285 {
286 uint16* shading_tables = (uint16*) shading_tables_as_void;
287 shading_tables += 256 * (int)(inIllumination * (number_of_shading_tables - 1));
288
289 // Extract color table - ZZZ change to use shading table rather than CLUT. Hope it works.
290
291 SDL_PixelFormat *fmt = &pixel_format_16;
292 for (int i = 0; i < 256; i++) {
293 SDL_GetRGB(shading_tables[i], fmt, &colors[i].r, &colors[i].g, &colors[i].b);
294 colors[i].a = 0xff;
295 }
296 }
297 break;
298
299 case 32:
300 {
301 uint32* shading_tables = (uint32*) shading_tables_as_void;
302 shading_tables += 256 * (int)(inIllumination * (number_of_shading_tables - 1));
303
304 // Extract color table - ZZZ change to use shading table rather than CLUT. Hope it works.
305 for(int i = 0; i < 256; i++) {
306 colors[i].r = RED32(shading_tables[i]);
307 colors[i].g = GREEN32(shading_tables[i]);
308 colors[i].b = BLUE32(shading_tables[i]);
309 colors[i].a = 0xff;
310 }
311 }
312 break;
313
314 default:
315 vhalt("oops, bit_depth not supported for get_shape_surface with illumination\n");
316 break;
317 }
318
319 } // inIllumination >= 0
320 else { // inIllumination < 0
321 bitmap = get_bitmap_definition(collection_index, low_level_shape->bitmap_index);
322 if(!bitmap) return NULL;
323
324 // Extract color table
325 int num_colors = collection->color_count - NUMBER_OF_PRIVATE_COLORS;
326 rgb_color_value *src_colors = get_collection_colors(collection_index, clut_index) + NUMBER_OF_PRIVATE_COLORS;
327 for (int i=0; i<num_colors && src_colors; i++) {
328 int idx = src_colors[i].value;
329 colors[idx].r = src_colors[i].red >> 8;
330 colors[idx].g = src_colors[i].green >> 8;
331 colors[idx].b = src_colors[i].blue >> 8;
332 colors[idx].a = 0xff;
333 }
334 } // inIllumination < 0
335
336
337 SDL_Surface *s = NULL;
338 if (bitmap->bytes_per_row == NONE) {
339
340 // ZZZ: process RLE-encoded shape
341
342 // Allocate storage for un-RLE'd pixels
343 uint32 theNumberOfStorageBytes = bitmap->width * bitmap->height * sizeof(byte);
344 byte* pixel_storage = (byte*) malloc(theNumberOfStorageBytes);
345 memset(pixel_storage, 0, theNumberOfStorageBytes);
346
347 // Here, a "run" is a row or column. An "element" is a single pixel's data.
348 // We always go forward through the source data. Thus, the offsets for where the next run
349 // or element goes into the destination data area change depending on the circumstances.
350 int16 theNumRuns;
351 int16 theDestDataNextRunOffset;
352 int16 theDestDataNextElementOffset;
353
354 // Is this row-major or column-major?
355 if(bitmap->flags & _COLUMN_ORDER_BIT) {
356 theNumRuns = bitmap->width;
357 theDestDataNextRunOffset = (low_level_shape->flags & _X_MIRRORED_BIT) ? -1 : 1;
358 theDestDataNextElementOffset = (low_level_shape->flags & _Y_MIRRORED_BIT) ? -bitmap->width : bitmap->width;
359 }
360 else {
361 theNumRuns = bitmap->height;
362 theDestDataNextElementOffset = (low_level_shape->flags & _X_MIRRORED_BIT) ? -1 : 1;
363 theDestDataNextRunOffset = (low_level_shape->flags & _Y_MIRRORED_BIT) ? -bitmap->width : bitmap->width;
364 }
365
366 // Figure out where our first byte will be written
367 byte* theDestDataStartAddress = pixel_storage;
368
369 if(low_level_shape->flags & _X_MIRRORED_BIT)
370 theDestDataStartAddress += bitmap->width - 1;
371
372 if(low_level_shape->flags & _Y_MIRRORED_BIT)
373 theDestDataStartAddress += bitmap->width * (bitmap->height - 1);
374
375 // Walk through runs, un-RLE'ing as we go
376 for(int run = 0; run < theNumRuns; run++) {
377 uint16* theLengthData = (uint16*) bitmap->row_addresses[run];
378 uint16 theFirstOpaquePixelElement = SDL_SwapBE16(theLengthData[0]);
379 uint16 theFirstTransparentAfterOpaquePixelElement = SDL_SwapBE16(theLengthData[1]);
380 uint16 theNumberOfOpaquePixels = theFirstTransparentAfterOpaquePixelElement - theFirstOpaquePixelElement;
381
382 byte* theOriginalPixelData = (byte*) &theLengthData[2];
383 byte* theUnpackedPixelData;
384
385 theUnpackedPixelData = theDestDataStartAddress + run * theDestDataNextRunOffset
386 + theFirstOpaquePixelElement * theDestDataNextElementOffset;
387
388 for(int i = 0; i < theNumberOfOpaquePixels; i++) {
389 assert(theUnpackedPixelData >= pixel_storage);
390 assert(theUnpackedPixelData < (pixel_storage + theNumberOfStorageBytes));
391 *theUnpackedPixelData = *theOriginalPixelData;
392 theUnpackedPixelData += theDestDataNextElementOffset;
393 theOriginalPixelData++;
394 }
395 }
396
397 // Let's shrink the image if the user wants us to.
398 // We do this here by discarding every other pixel in each direction.
399 // Really, I guess there's probably a library out there that would do nice smoothing
400 // for us etc. that we should use here. I just want to hack something out now and run with it.
401 int image_width = bitmap->width;
402 int image_height = bitmap->height;
403
404 if(inShrinkImage) {
405 int theLargerWidth = bitmap->width;
406 int theLargerHeight = bitmap->height;
407 byte* theLargerPixelStorage = pixel_storage;
408 int theSmallerWidth = theLargerWidth / 2 + theLargerWidth % 2;
409 int theSmallerHeight = theLargerHeight / 2 + theLargerHeight % 2;
410 byte* theSmallerPixelStorage = (byte*) malloc(theSmallerWidth * theSmallerHeight);
411
412 for(int y = 0; y < theSmallerHeight; y++) {
413 for(int x = 0; x < theSmallerWidth; x++) {
414 theSmallerPixelStorage[y * theSmallerWidth + x] =
415 theLargerPixelStorage[(y * theLargerWidth + x) * 2];
416 }
417 }
418
419 free(pixel_storage);
420
421 pixel_storage = theSmallerPixelStorage;
422 image_width = theSmallerWidth;
423 image_height = theSmallerHeight;
424 }
425
426 // Now we can create a surface from this new storage
427 s = SDL_CreateRGBSurfaceFrom(pixel_storage, image_width, image_height, 8, image_width, 0, 0, 0, 0);
428
429 if(s != NULL) {
430 // If caller is not prepared to take this data, it's a coding error.
431 assert(outPointerToPixelData != NULL);
432 *outPointerToPixelData = pixel_storage;
433
434 // Set color table
435 SDL_SetPaletteColors(s->format->palette, colors, 0, 256);
436
437 // Set transparent pixel (color #0)
438 SDL_SetColorKey(s, SDL_TRUE, 0);
439 }
440
441 } else {
442 // Row-order shape, we can directly create a surface from it
443 if (collection->type == _wall_collection)
444 {
445 s = SDL_CreateRGBSurfaceFrom(bitmap->row_addresses[0], bitmap->height, bitmap->width, 8, bitmap->bytes_per_row, 0, 0, 0, 0);
446 }
447 else
448 {
449 s = SDL_CreateRGBSurfaceFrom(bitmap->row_addresses[0], bitmap->width, bitmap->height, 8, bitmap->bytes_per_row, 0, 0, 0, 0);
450 }
451 // ZZZ: caller should not dispose of any additional data - just free the surface.
452 if(outPointerToPixelData != NULL)
453 *outPointerToPixelData = NULL;
454
455 if(s != NULL) {
456 // Set color table
457 SDL_SetPaletteColors(s->format->palette, colors, 0, 256);
458 }
459 }
460
461 return s;
462 }
463
load_collection_definition(collection_definition * cd,SDL_RWops * p)464 static void load_collection_definition(collection_definition* cd, SDL_RWops *p)
465 {
466 cd->version = SDL_ReadBE16(p);
467 cd->type = SDL_ReadBE16(p);
468 cd->flags = SDL_ReadBE16(p);
469 cd->color_count = SDL_ReadBE16(p);
470 cd->clut_count = SDL_ReadBE16(p);
471 cd->color_table_offset = SDL_ReadBE32(p);
472 cd->high_level_shape_count = SDL_ReadBE16(p);
473 cd->high_level_shape_offset_table_offset = SDL_ReadBE32(p);
474 cd->low_level_shape_count = SDL_ReadBE16(p);
475 cd->low_level_shape_offset_table_offset = SDL_ReadBE32(p);
476 cd->bitmap_count = SDL_ReadBE16(p);
477 cd->bitmap_offset_table_offset = SDL_ReadBE32(p);
478 cd->pixels_to_world = SDL_ReadBE16(p);
479 SDL_ReadBE32(p); // skip size
480 SDL_RWseek(p, 253 * sizeof(int16), SEEK_CUR); // unused
481
482 // resize members
483 cd->color_tables.resize(cd->clut_count * cd->color_count);
484 cd->high_level_shapes.resize(cd->high_level_shape_count);
485 cd->low_level_shapes.resize(cd->low_level_shape_count);
486 cd->bitmaps.resize(cd->bitmap_count);
487
488 }
489
load_clut(rgb_color_value * r,int count,SDL_RWops * p)490 static void load_clut(rgb_color_value *r, int count, SDL_RWops *p)
491 {
492 for (int i = 0; i < count; i++, r++)
493 {
494 SDL_RWread(p, r, 1, 2);
495 r->red = SDL_ReadBE16(p);
496 r->green = SDL_ReadBE16(p);
497 r->blue = SDL_ReadBE16(p);
498 }
499 }
500
load_high_level_shape(std::vector<uint8> & shape,SDL_RWops * p)501 static void load_high_level_shape(std::vector<uint8>& shape, SDL_RWops *p)
502 {
503 int16 type = SDL_ReadBE16(p);
504 int16 flags = SDL_ReadBE16(p);
505 char name[HIGH_LEVEL_SHAPE_NAME_LENGTH + 2];
506 SDL_RWread(p, name, 1, HIGH_LEVEL_SHAPE_NAME_LENGTH + 2);
507 int16 number_of_views = SDL_ReadBE16(p);
508 int16 frames_per_view = SDL_ReadBE16(p);
509
510 // Convert low-level shape index list
511 int num_views;
512 switch (number_of_views) {
513 case _unanimated:
514 case _animated1:
515 num_views = 1;
516 break;
517 case _animated3to4:
518 case _animated4:
519 num_views = 4;
520 break;
521 case _animated3to5:
522 case _animated5:
523 num_views = 5;
524 break;
525 case _animated2to8:
526 case _animated5to8:
527 case _animated8:
528 num_views = 8;
529 break;
530 default:
531 num_views = number_of_views;
532 break;
533 }
534
535 shape.resize(sizeof(high_level_shape_definition) + num_views * frames_per_view * sizeof(int16));
536
537 high_level_shape_definition *d = (high_level_shape_definition *) &shape[0];
538
539 d->type = type;
540 d->flags = flags;
541 memcpy(d->name, name, HIGH_LEVEL_SHAPE_NAME_LENGTH + 2);
542 d->number_of_views = number_of_views;
543 d->frames_per_view = frames_per_view;
544 d->ticks_per_frame = SDL_ReadBE16(p);
545 d->key_frame = SDL_ReadBE16(p);
546 d->transfer_mode = SDL_ReadBE16(p);
547 d->transfer_mode_period = SDL_ReadBE16(p);
548 d->first_frame_sound = SDL_ReadBE16(p);
549 d->key_frame_sound = SDL_ReadBE16(p);
550 d->last_frame_sound = SDL_ReadBE16(p);
551 d->pixels_to_world = SDL_ReadBE16(p);
552 d->loop_frame = SDL_ReadBE16(p);
553 SDL_RWseek(p, 14 * sizeof(int16), SEEK_CUR);
554
555 // Convert low-level shape index list
556 for (int j = 0; j < num_views * d->frames_per_view; j++) {
557 d->low_level_shape_indexes[j] = SDL_ReadBE16(p);
558 }
559 }
560
load_low_level_shape(low_level_shape_definition * d,SDL_RWops * p)561 static void load_low_level_shape(low_level_shape_definition *d, SDL_RWops *p)
562 {
563 d->flags = SDL_ReadBE16(p);
564 d->minimum_light_intensity = SDL_ReadBE32(p);
565 d->bitmap_index = SDL_ReadBE16(p);
566 d->origin_x = SDL_ReadBE16(p);
567 d->origin_y = SDL_ReadBE16(p);
568 d->key_x = SDL_ReadBE16(p);
569 d->key_y = SDL_ReadBE16(p);
570 d->world_left = SDL_ReadBE16(p);
571 d->world_right = SDL_ReadBE16(p);
572 d->world_top = SDL_ReadBE16(p);
573 d->world_bottom = SDL_ReadBE16(p);
574 d->world_x0 = SDL_ReadBE16(p);
575 d->world_y0 = SDL_ReadBE16(p);
576 SDL_RWseek(p, 4 * sizeof(int16), SEEK_CUR);
577 }
578
convert_m1_rle(std::vector<uint8> & bitmap,int scanlines,int scanline_length,SDL_RWops * p)579 static void convert_m1_rle(std::vector<uint8>& bitmap, int scanlines, int scanline_length, SDL_RWops* p)
580 {
581 // std::vector<uint8> bitmap;
582 for (int scanline = 0; scanline < scanlines; ++scanline)
583 {
584 std::vector<uint8> scanline_data(scanline_length + 1);
585 uint8* dst = &scanline_data[0];
586 uint8* sentry = &scanline_data[scanline_length];
587
588 while (true)
589 {
590 int16 opcode = SDL_ReadBE16(p);
591 if (opcode > 0)
592 {
593 assert(dst + opcode <= sentry);
594 SDL_RWread(p, dst, opcode, 1);
595 dst += opcode;
596 }
597 else if (opcode < 0)
598 {
599 assert(dst - opcode <= sentry);
600 dst -= opcode;
601 }
602 else
603 break;
604 }
605
606 assert (dst == sentry);
607
608 // Find M2/oo-format RLE compression;
609 // it needs the first nonblank pixel and the last nonblank one + 1
610 int16 first = 0;
611 int16 last = 0;
612 for (int i = 0; i < scanline_length; ++i)
613 {
614 if (scanline_data[i] != 0)
615 {
616 first = i;
617 break;
618 }
619 }
620
621 for (int i = scanline_length - 1; i >= 0; --i)
622 {
623 if (scanline_data[i] != 0)
624 {
625 last = i + 1;
626 break;
627 }
628 }
629
630 if (last < first) last = first;
631
632 bitmap.push_back(first >> 8);
633 bitmap.push_back(first & 0xff);
634 bitmap.push_back(last >> 8);
635 bitmap.push_back(last & 0xff);
636 bitmap.insert(bitmap.end(), &scanline_data[first], &scanline_data[last]);
637 }
638 }
639
load_bitmap(std::vector<uint8> & bitmap,SDL_RWops * p,int version)640 static void load_bitmap(std::vector<uint8>& bitmap, SDL_RWops *p, int version)
641 {
642 bitmap_definition b;
643
644 // Convert bitmap definition
645 b.width = SDL_ReadBE16(p);
646 b.height = SDL_ReadBE16(p);
647 b.bytes_per_row = SDL_ReadBE16(p);
648 b.flags = SDL_ReadBE16(p);
649 b.bit_depth = SDL_ReadBE16(p);
650
651 // guess how big to make it
652 int rows = (b.flags & _COLUMN_ORDER_BIT) ? b.width : b.height;
653 int row_len = (b.flags & _COLUMN_ORDER_BIT) ? b.height : b.width;
654
655 SDL_RWseek(p, 16, SEEK_CUR);
656
657 // Skip row address pointers
658 SDL_RWseek(p, (rows + 1) * sizeof(uint32), SEEK_CUR);
659
660 if (b.bytes_per_row == NONE)
661 {
662 if (version == M1_SHAPES_VERSION)
663 {
664 // make enough room for the definition, then append as we convert RLE
665 bitmap.resize(sizeof(bitmap_definition) + rows * sizeof(pixel8*));
666 }
667 else
668 {
669 // ugly--figure out how big it's going to be
670
671 int32 size = 0;
672 for (int j = 0; j < rows; j++) {
673 int16 first = SDL_ReadBE16(p);
674 int16 last = SDL_ReadBE16(p);
675 size += 4;
676 SDL_RWseek(p, last - first, SEEK_CUR);
677 size += last - first;
678 }
679
680 bitmap.resize(sizeof(bitmap_definition) + rows * sizeof(pixel8*) + size);
681
682 // Now, seek back
683 SDL_RWseek(p, -size, SEEK_CUR);
684 }
685 }
686 else
687 {
688 bitmap.resize(sizeof(bitmap_definition) + rows * sizeof(pixel8*) + rows * b.bytes_per_row);
689 }
690
691
692 uint8* c = &bitmap[0];
693 bitmap_definition *d = (bitmap_definition *) &bitmap[0];
694 d->width = b.width;
695 d->height = b.height;
696 d->bytes_per_row = b.bytes_per_row;
697 d->flags = b.flags;
698 d->flags &= ~_PATCHED_BIT; // Anvil sets unused flags :( we'll set it later
699 d->bit_depth = b.bit_depth;
700 c += sizeof(bitmap_definition);
701
702 // Skip row address pointers
703 c += rows * sizeof(pixel8 *);
704
705 // Copy bitmap data
706 if (d->bytes_per_row == NONE)
707 {
708 // RLE format
709
710 if (version == M1_SHAPES_VERSION)
711 {
712 convert_m1_rle(bitmap, rows, row_len, p);
713 }
714 else
715 {
716 for (int j = 0; j < rows; j++) {
717 int16 first = SDL_ReadBE16(p);
718 int16 last = SDL_ReadBE16(p);
719 *(c++) = (uint8)(first >> 8);
720 *(c++) = (uint8)(first);
721 *(c++) = (uint8)(last >> 8);
722 *(c++) = (uint8)(last);
723 SDL_RWread(p, c, 1, last - first);
724 c += last - first;
725 }
726 }
727 } else {
728 SDL_RWread(p, c, d->bytes_per_row, rows);
729 c += rows * d->bytes_per_row;
730 }
731
732 }
733
allocate_shading_tables(short collection_index,bool strip)734 static void allocate_shading_tables(short collection_index, bool strip)
735 {
736 collection_header *header = get_collection_header(collection_index);
737 // Allocate enough space for this collection's shading tables
738 if (strip)
739 header->shading_tables = NULL;
740 else {
741 collection_definition *definition = get_collection_definition(collection_index);
742 header->shading_tables = (byte *)malloc(get_shading_table_size(collection_index) * definition->clut_count + shading_table_size * NUMBER_OF_TINT_TABLES);
743 }
744 }
745
746 /*
747 * Load collection
748 */
749
load_collection(short collection_index,bool strip)750 static bool load_collection(short collection_index, bool strip)
751 {
752 SDL_RWops* p;
753 boost::shared_ptr<SDL_RWops> m1_p; // automatic deallocation
754 LoadedResource r;
755 int32 src_offset;
756
757 collection_header *header = get_collection_header(collection_index);
758
759 if (shapes_file_version == M1_SHAPES_VERSION)
760 {
761 // Collections are stored in .256 resources
762 if (!M1ShapesFile.Get('.', '2', '5', '6', 128 + collection_index, r))
763 {
764 return false;
765 }
766
767 m1_p.reset(SDL_RWFromConstMem(r.GetPointer(), r.GetLength()), SDL_FreeRW);
768 p = m1_p.get();
769 src_offset = 0;
770 }
771 else
772 {
773 // Get offset and length of data in source file from header
774
775 if (bit_depth == 8 || header->offset16 == -1) {
776 if (header->offset == -1)
777 {
778 return false;
779 }
780 src_offset = header->offset;
781 } else {
782 src_offset = header->offset16;
783 }
784
785 p = ShapesFile.GetRWops();
786 ShapesFile.SetPosition(0);
787 src_offset += SDL_RWtell(p);
788 }
789
790 // Read collection definition
791 std::unique_ptr<collection_definition> cd(new collection_definition);
792 SDL_RWseek(p, src_offset, RW_SEEK_SET);
793 load_collection_definition(cd.get(), p);
794 header->status &= ~markPATCHED;
795
796 // Convert CLUTS
797 if (cd->clut_count && cd->color_count) {
798 SDL_RWseek(p, src_offset + cd->color_table_offset, RW_SEEK_SET);
799 load_clut(&cd->color_tables[0], cd->clut_count * cd->color_count, p);
800 }
801
802 // Convert high-level shape definitions
803 if (cd->high_level_shape_count) {
804 SDL_RWseek(p, src_offset + cd->high_level_shape_offset_table_offset, RW_SEEK_SET);
805 std::vector<uint32> t(cd->high_level_shape_count);
806 SDL_RWread(p, &t[0], sizeof(uint32), cd->high_level_shape_count);
807 byte_swap_memory(&t[0], _4byte, cd->high_level_shape_count);
808
809 for (int i = 0; i < cd->high_level_shape_count; i++) {
810 SDL_RWseek(p, src_offset + t[i], RW_SEEK_SET);
811 load_high_level_shape(cd->high_level_shapes[i], p);
812 }
813 }
814
815 // Convert low-level shape definitions
816 if (cd->low_level_shape_count) {
817 SDL_RWseek(p, src_offset + cd->low_level_shape_offset_table_offset, RW_SEEK_SET);
818 std::vector<uint32> t(cd->low_level_shape_count);
819 SDL_RWread(p, &t[0], sizeof(uint32), cd->low_level_shape_count);
820 byte_swap_memory(&t[0], _4byte, cd->low_level_shape_count);
821
822 for (int i = 0; i < cd->low_level_shape_count; i++) {
823 SDL_RWseek(p, src_offset + t[i], RW_SEEK_SET);
824 load_low_level_shape(&cd->low_level_shapes[i], p);
825 }
826 }
827
828 // Convert bitmap definitions
829 if (cd->bitmap_count) {
830 SDL_RWseek(p, src_offset + cd->bitmap_offset_table_offset, RW_SEEK_SET);
831 std::vector<uint32> t(cd->bitmap_count);
832 SDL_RWread(p, &t[0], sizeof(uint32), cd->bitmap_count);
833 byte_swap_memory(&t[0], _4byte, cd->bitmap_count);
834
835 for (int i = 0; i < cd->bitmap_count; i++) {
836 SDL_RWseek(p, src_offset + t[i], RW_SEEK_SET);
837 load_bitmap(cd->bitmaps[i], p, shapes_file_version);
838 }
839 }
840
841 header->collection = cd.release();
842
843 if (strip) {
844 //!! don't know what to do
845 fprintf(stderr, "Stripped shapes not implemented\n");
846 abort();
847 }
848
849 allocate_shading_tables(collection_index, strip);
850
851 if (header->shading_tables == NULL) {
852 delete header->collection;
853 header->collection = NULL;
854 return false;
855 }
856
857 // Everything OK
858 return true;
859 }
860
861
862 /*
863 * Unload collection
864 */
865
unload_collection(struct collection_header * header)866 static void unload_collection(struct collection_header *header)
867 {
868 assert(header->collection);
869 delete header->collection;
870 free(header->shading_tables);
871 header->collection = NULL;
872 header->shading_tables = NULL;
873 }
874
875 #define ENDC_TAG FOUR_CHARS_TO_INT('e', 'n', 'd', 'c')
876 #define CLDF_TAG FOUR_CHARS_TO_INT('c', 'l', 'd', 'f')
877 #define HLSH_TAG FOUR_CHARS_TO_INT('h', 'l', 's', 'h')
878 #define LLSH_TAG FOUR_CHARS_TO_INT('l', 'l', 's', 'h')
879 #define BMAP_TAG FOUR_CHARS_TO_INT('b', 'm', 'a', 'p')
880 #define CTAB_TAG FOUR_CHARS_TO_INT('c', 't', 'a', 'b')
881
882 std::vector<uint8> shapes_patch;
set_shapes_patch_data(uint8 * data,size_t length)883 void set_shapes_patch_data(uint8 *data, size_t length)
884 {
885 if (!length)
886 {
887 shapes_patch.clear();
888 }
889 else
890 {
891 shapes_patch.resize(length);
892 memcpy(&shapes_patch[0], data, length);
893 }
894 }
895
get_shapes_patch_data(size_t & length)896 uint8* get_shapes_patch_data(size_t &length)
897 {
898 length = shapes_patch.size();
899 return length ? &shapes_patch[0] : 0;
900 }
901
load_shapes_patch(SDL_RWops * p,bool override_replacements)902 void load_shapes_patch(SDL_RWops *p, bool override_replacements)
903 {
904 std::vector<int16> color_counts(MAXIMUM_COLLECTIONS);
905 int32 start = SDL_RWtell(p);
906 SDL_RWseek(p, 0, SEEK_END);
907 int32 end = SDL_RWtell(p);
908
909 SDL_RWseek(p, start, SEEK_SET);
910
911 bool done = false;
912 while (!done)
913 {
914 // is there more data to read?
915 if (SDL_RWtell(p) < end)
916 {
917 int32 collection_index = SDL_ReadBE32(p);
918 int32 patch_bit_depth = SDL_ReadBE32(p);
919
920 bool collection_end = false;
921 while (!collection_end)
922 {
923 // read a tag
924 int32 tag = SDL_ReadBE32(p);
925 if (tag == ENDC_TAG)
926 {
927 collection_end = true;
928 }
929 else if (tag == CLDF_TAG)
930 {
931 // a collection follows directly
932 collection_header *header = get_collection_header(collection_index);
933 if (collection_loaded(header) && patch_bit_depth == 8)
934 {
935 load_collection_definition(header->collection, p);
936 color_counts[collection_index] = header->collection->color_count;
937 allocate_shading_tables(collection_index, false);
938 header->status|=markPATCHED;
939
940 } else {
941 // get the color count (it's the only way to skip the CTAB_TAG
942 SDL_RWseek(p, 6, SEEK_CUR);
943 color_counts[collection_index] = SDL_ReadBE16(p);
944 SDL_RWseek(p, 544 - 8, SEEK_CUR);
945 }
946 }
947 else if (tag == HLSH_TAG)
948 {
949 collection_definition *cd = get_collection_definition(collection_index);
950 int32 high_level_shape_index = SDL_ReadBE32(p);
951 int32 size = SDL_ReadBE32(p);
952 int32 pos = SDL_RWtell(p);
953 if (cd && patch_bit_depth == 8 && high_level_shape_index < cd->high_level_shapes.size())
954 {
955 load_high_level_shape(cd->high_level_shapes[high_level_shape_index], p);
956 SDL_RWseek(p, pos + size, SEEK_SET);
957
958 }
959 else
960 {
961 SDL_RWseek(p, size, SEEK_CUR);
962 }
963 }
964 else if (tag == LLSH_TAG)
965 {
966 collection_definition *cd = get_collection_definition(collection_index);
967 int32 low_level_shape_index = SDL_ReadBE32(p);
968 if (cd && patch_bit_depth == 8 && low_level_shape_index < cd->low_level_shapes.size())
969 {
970 load_low_level_shape(&cd->low_level_shapes[low_level_shape_index], p);
971 }
972 else
973 {
974 SDL_RWseek(p, 36, SEEK_CUR);
975 }
976 }
977 else if (tag == BMAP_TAG)
978 {
979 collection_definition *cd = get_collection_definition(collection_index);
980 int32 bitmap_index = SDL_ReadBE32(p);
981 int32 size = SDL_ReadBE32(p);
982 if (cd && patch_bit_depth == 8 && bitmap_index < cd->bitmaps.size())
983 {
984 load_bitmap(cd->bitmaps[bitmap_index], p, M2_SHAPES_VERSION);
985 if (override_replacements)
986 {
987 get_bitmap_definition(collection_index, bitmap_index)->flags |= _PATCHED_BIT;
988 }
989 }
990 else
991 {
992 SDL_RWseek(p, size, SEEK_CUR);
993 }
994 }
995 else if (tag == CTAB_TAG)
996 {
997 collection_definition *cd = get_collection_definition(collection_index);
998 int32 color_table_index = SDL_ReadBE32(p);
999 if (cd && patch_bit_depth == 8 && (color_table_index * cd->color_count < cd->color_tables.size()))
1000 {
1001 load_clut(&cd->color_tables[color_table_index], cd->color_count, p);
1002 }
1003 else
1004 {
1005 SDL_RWseek(p, color_counts[collection_index] * sizeof(rgb_color_value), SEEK_CUR);
1006 }
1007 }
1008 else
1009 {
1010 fprintf(stderr, "Unrecognized tag in patch file '%c%c%c%c'\n %x", tag >> 24, tag >> 16, tag >> 8, tag, tag);
1011 }
1012 }
1013
1014
1015 } else {
1016 done = true;
1017 }
1018 }
1019
1020
1021 }
1022
1023 /* ---------- code */
1024
1025 /* --------- private code */
1026
initialize_shape_handler()1027 void initialize_shape_handler()
1028 {
1029 // M1 uses the resource fork, but M2 and Moo use the data fork
1030
1031 FileSpecifier File;
1032 get_default_shapes_spec(File);
1033 open_shapes_file(File);
1034 if (!ShapesFile.IsOpen() && !M1ShapesFile.IsOpen())
1035 alert_bad_extra_file(ShapesFile.GetError());
1036 else
1037 atexit(shutdown_shape_handler);
1038
1039 initialize_pixmap_handler();
1040 }
1041
open_shapes_file(FileSpecifier & File)1042 void open_shapes_file(FileSpecifier& File)
1043 {
1044 bool m1_loaded = false;
1045 if (File.Open(M1ShapesFile) && M1ShapesFile.Check('.','2','5','6',128))
1046 {
1047 shapes_file_version = M1_SHAPES_VERSION;
1048 m1_loaded = true;
1049 }
1050 else
1051 {
1052 M1ShapesFile.Close();
1053 }
1054
1055 if (!m1_loaded && File.Open(ShapesFile))
1056 {
1057 shapes_file_version = M2_SHAPES_VERSION;
1058 // Load the collection headers;
1059 // need a buffer for the packed data
1060 int Size = MAXIMUM_COLLECTIONS*SIZEOF_collection_header;
1061 byte *CollHdrStream = new byte[Size];
1062 if (!ShapesFile.Read(Size,CollHdrStream))
1063 {
1064 ShapesFile.Close();
1065 delete []CollHdrStream;
1066 return;
1067 }
1068
1069 // Unpack them
1070 uint8 *S = CollHdrStream;
1071 int Count = MAXIMUM_COLLECTIONS;
1072 collection_header* ObjPtr = collection_headers;
1073
1074 for (int k = 0; k < Count; k++, ObjPtr++)
1075 {
1076 StreamToValue(S,ObjPtr->status);
1077 StreamToValue(S,ObjPtr->flags);
1078
1079 StreamToValue(S,ObjPtr->offset);
1080 StreamToValue(S,ObjPtr->length);
1081 StreamToValue(S,ObjPtr->offset16);
1082 StreamToValue(S,ObjPtr->length16);
1083
1084 S += 6*2;
1085
1086 ObjPtr->collection = NULL; // so unloading can work properly
1087 ObjPtr->shading_tables = NULL; // so unloading can work properly
1088 }
1089
1090 assert((S - CollHdrStream) == Count*SIZEOF_collection_header);
1091
1092 delete []CollHdrStream;
1093
1094 }
1095 set_shapes_images_file(File);
1096 }
1097
close_shapes_file(void)1098 static void close_shapes_file(void)
1099 {
1100 if (shapes_file_version == M1_SHAPES_VERSION)
1101 {
1102 M1ShapesFile.Close();
1103 }
1104 else
1105 {
1106 ShapesFile.Close();
1107 }
1108 }
1109
shutdown_shape_handler(void)1110 static void shutdown_shape_handler(void)
1111 {
1112 close_shapes_file();
1113 }
1114
1115
collection_loaded(struct collection_header * header)1116 static bool collection_loaded(
1117 struct collection_header *header)
1118 {
1119 return header->collection ? true : false;
1120 }
1121
collection_loaded(short collection_index)1122 bool collection_loaded(short collection_index)
1123 {
1124 collection_header *header = get_collection_header(collection_index);
1125 return collection_loaded(header);
1126 }
1127
can_load_collection(short collection_index)1128 bool can_load_collection(short collection_index)
1129 {
1130 if (collection_index >= 0 && collection_index < NUMBER_OF_COLLECTIONS)
1131 {
1132 collection_header* header = get_collection_header(collection_index);
1133 if (header) {
1134 return (header->offset != -1 || header->offset16 != -1);
1135 }
1136 }
1137
1138 return false;
1139 }
1140
lock_collection(struct collection_header * header)1141 static void lock_collection(
1142 struct collection_header *header)
1143 {
1144 // nothing to do
1145 }
1146
unlock_collection(struct collection_header * header)1147 static void unlock_collection(
1148 struct collection_header *header)
1149 {
1150 // nothing to do
1151 }
1152
1153
unload_all_collections(void)1154 void unload_all_collections(
1155 void)
1156 {
1157 struct collection_header *header;
1158 short collection_index;
1159
1160 for (collection_index= 0, header= collection_headers; collection_index<MAXIMUM_COLLECTIONS; ++collection_index, ++header)
1161 {
1162 if (collection_loaded(header))
1163 {
1164 unload_collection(header);
1165 }
1166 OGL_UnloadModelsImages(collection_index);
1167 }
1168 }
1169
mark_collection(short collection_code,bool loading)1170 void mark_collection(
1171 short collection_code,
1172 bool loading)
1173 {
1174 if (collection_code!=NONE)
1175 {
1176 short collection_index= GET_COLLECTION(collection_code);
1177
1178 assert(collection_index>=0&&collection_index<MAXIMUM_COLLECTIONS);
1179 collection_headers[collection_index].status|= loading ? markLOAD : markUNLOAD;
1180 }
1181 }
1182
strip_collection(short collection_code)1183 void strip_collection(
1184 short collection_code)
1185 {
1186 if (collection_code!=NONE)
1187 {
1188 short collection_index= GET_COLLECTION(collection_code);
1189
1190 assert(collection_index>=0&&collection_index<MAXIMUM_COLLECTIONS);
1191 collection_headers[collection_index].status|= markSTRIP;
1192 }
1193 }
1194
1195 /* returns count, doesn�t fill NULL buffer */
get_shape_descriptors(short shape_type,shape_descriptor * buffer)1196 short get_shape_descriptors(
1197 short shape_type,
1198 shape_descriptor *buffer)
1199 {
1200 short collection_index, low_level_shape_index;
1201 short appropriate_type;
1202 short count;
1203
1204 switch (shape_type)
1205 {
1206 case _wall_shape: appropriate_type= _wall_collection; break;
1207 case _floor_or_ceiling_shape: appropriate_type= _wall_collection; break;
1208 default:
1209 assert(false);
1210 break;
1211 }
1212
1213 count= 0;
1214 for (collection_index=0;collection_index<MAXIMUM_COLLECTIONS;++collection_index)
1215 {
1216 struct collection_definition *collection= get_collection_definition(collection_index);
1217 // Skip over nonexistent collections, frames, and bitmaps.
1218 if (!collection) continue;
1219
1220 if (collection&&collection->type==appropriate_type)
1221 {
1222 for (low_level_shape_index=0;low_level_shape_index<collection->low_level_shape_count;++low_level_shape_index)
1223 {
1224 struct low_level_shape_definition *low_level_shape= get_low_level_shape_definition(collection_index, low_level_shape_index);
1225 if (!low_level_shape) continue;
1226 struct bitmap_definition *bitmap= get_bitmap_definition(collection_index, low_level_shape->bitmap_index);
1227 if (!bitmap) continue;
1228
1229 count+= collection->clut_count;
1230 if (buffer)
1231 {
1232 short clut;
1233
1234 for (clut=0;clut<collection->clut_count;++clut)
1235 {
1236 *buffer++= BUILD_DESCRIPTOR(BUILD_COLLECTION(collection_index, clut), low_level_shape_index);
1237 }
1238 }
1239 }
1240 }
1241 }
1242
1243 return count;
1244 }
1245
extended_get_shape_bitmap_and_shading_table(short collection_code,short low_level_shape_index,struct bitmap_definition ** bitmap,void ** shading_tables,short shading_mode)1246 void extended_get_shape_bitmap_and_shading_table(
1247 short collection_code,
1248 short low_level_shape_index,
1249 struct bitmap_definition **bitmap,
1250 void **shading_tables,
1251 short shading_mode)
1252 {
1253 // if (collection_code==_collection_marathon_control_panels) collection_code= 30, low_level_shape_index= 0;
1254 short collection_index= GET_COLLECTION(collection_code);
1255 short clut_index= GET_COLLECTION_CLUT(collection_code);
1256
1257 // Forget about it if some one managed to call us with the NONE value
1258 assert(!(clut_index+1 == MAXIMUM_CLUTS_PER_COLLECTION &&
1259 collection_index+1 == MAXIMUM_COLLECTIONS &&
1260 low_level_shape_index+1 == MAXIMUM_SHAPES_PER_COLLECTION));
1261
1262 struct low_level_shape_definition *low_level_shape= get_low_level_shape_definition(collection_index, low_level_shape_index);
1263 // Return NULL pointers for bitmap and shading table if the frame does not exist
1264 if (!low_level_shape)
1265 {
1266 *bitmap = NULL;
1267 if (shading_tables) *shading_tables = NULL;
1268 return;
1269 }
1270
1271 if (bitmap) *bitmap= get_bitmap_definition(collection_index, low_level_shape->bitmap_index);
1272 if (shading_tables)
1273 {
1274 switch (shading_mode)
1275 {
1276 case _shading_normal:
1277 *shading_tables= get_collection_shading_tables(collection_index, clut_index);
1278 break;
1279 case _shading_infravision:
1280 *shading_tables= get_collection_tint_tables(collection_index, 0);
1281 break;
1282
1283 default:
1284 assert(false);
1285 break;
1286 }
1287 }
1288 }
1289
extended_get_shape_information(short collection_code,short low_level_shape_index)1290 struct shape_information_data *extended_get_shape_information(
1291 short collection_code,
1292 short low_level_shape_index)
1293 {
1294 if((GET_COLLECTION(collection_code) < 0) || (GET_COLLECTION(collection_code) >= NUMBER_OF_COLLECTIONS)) return NULL; if(low_level_shape_index < 0) return NULL;
1295 short collection_index= GET_COLLECTION(collection_code);
1296 struct low_level_shape_definition *low_level_shape;
1297
1298 low_level_shape= get_low_level_shape_definition(collection_index, low_level_shape_index);
1299 return (struct shape_information_data *) low_level_shape;
1300 }
1301
process_collection_sounds(short collection_code,void (* process_sound)(short sound_index))1302 void process_collection_sounds(
1303 short collection_code,
1304 void (*process_sound)(short sound_index))
1305 {
1306 short collection_index= GET_COLLECTION(collection_code);
1307 struct collection_definition *collection= get_collection_definition(collection_index);
1308 // Skip over processing unloaded collections and sequences
1309 if (!collection) return;
1310
1311 short high_level_shape_index;
1312
1313 for (high_level_shape_index= 0; high_level_shape_index<collection->high_level_shape_count; ++high_level_shape_index)
1314 {
1315 struct high_level_shape_definition *high_level_shape= get_high_level_shape_definition(collection_index, high_level_shape_index);
1316 if (!high_level_shape) return;
1317
1318 process_sound(high_level_shape->first_frame_sound);
1319 process_sound(high_level_shape->key_frame_sound);
1320 process_sound(high_level_shape->last_frame_sound);
1321 }
1322 }
1323
get_shape_animation_data(shape_descriptor shape)1324 struct shape_animation_data *get_shape_animation_data(
1325 shape_descriptor shape)
1326 {
1327 short collection_index, high_level_shape_index;
1328 struct high_level_shape_definition *high_level_shape;
1329
1330 collection_index= GET_COLLECTION(GET_DESCRIPTOR_COLLECTION(shape));
1331 high_level_shape_index= GET_DESCRIPTOR_SHAPE(shape);
1332 high_level_shape= get_high_level_shape_definition(collection_index, high_level_shape_index);
1333 if (!high_level_shape) return NULL;
1334
1335 return (struct shape_animation_data *) &high_level_shape->number_of_views;
1336 }
1337
get_global_shading_table(void)1338 void *get_global_shading_table(
1339 void)
1340 {
1341 void *shading_table= (void *) NULL;
1342
1343 switch (bit_depth)
1344 {
1345 case 8:
1346 {
1347 /* return the last shading_table calculated */
1348 short collection_index;
1349
1350 for (collection_index=MAXIMUM_COLLECTIONS-1;collection_index>=0;--collection_index)
1351 {
1352 struct collection_definition *collection= get_collection_definition(collection_index);
1353
1354 if (collection)
1355 {
1356 shading_table= get_collection_shading_tables(collection_index, 0);
1357 break;
1358 }
1359 }
1360
1361 break;
1362 }
1363
1364 case 16:
1365 build_global_shading_table16();
1366 shading_table= global_shading_table16;
1367 break;
1368
1369 case 32:
1370 build_global_shading_table32();
1371 shading_table= global_shading_table32;
1372 break;
1373
1374 default:
1375 assert(false);
1376 break;
1377 }
1378 assert(shading_table);
1379
1380 return shading_table;
1381 }
1382
load_collections(bool with_progress_bar,bool is_opengl)1383 void load_collections(
1384 bool with_progress_bar,
1385 bool is_opengl)
1386 {
1387 struct collection_header *header;
1388 short collection_index;
1389
1390 if (with_progress_bar)
1391 {
1392 // open_progress_dialog(_loading_collections);
1393 // draw_progress_bar(0, 2*MAXIMUM_COLLECTIONS);
1394 }
1395 precalculate_bit_depth_constants();
1396
1397 free_and_unlock_memory(); /* do our best to get a big, unfragmented heap */
1398
1399 /* first go through our list of shape collections and dispose of any collections which
1400 were marked for unloading. at the same time, unlock all those collections which
1401 will be staying (so the heap can move around) */
1402 for (collection_index= 0, header= collection_headers; collection_index<MAXIMUM_COLLECTIONS; ++collection_index, ++header)
1403 {
1404 // if (with_progress_bar)
1405 // draw_progress_bar(collection_index, 2*MAXIMUM_COLLECTIONS);
1406 if (true)
1407 {
1408 if (collection_loaded(header))
1409 {
1410 unload_collection(header);
1411 }
1412 OGL_UnloadModelsImages(collection_index);
1413 SW_Texture_Extras::instance()->Unload(collection_index);
1414 }
1415 }
1416
1417 /* ... then go back through the list of collections and load any that we were asked to */
1418 for (collection_index= 0, header= collection_headers; collection_index<MAXIMUM_COLLECTIONS; ++collection_index, ++header)
1419 {
1420 // if (with_progress_bar)
1421 // draw_progress_bar(MAXIMUM_COLLECTIONS+collection_index, 2*MAXIMUM_COLLECTIONS);
1422 /* don�t reload collections which are already in memory, but do lock them */
1423 if (collection_loaded(header))
1424 {
1425 // In case the substitute images had been changed by some level-specific MML...
1426 // OGL_LoadModelsImages(collection_index);
1427 lock_collection(header);
1428 }
1429 else
1430 {
1431 if (header->status&markLOAD)
1432 {
1433 /* load and decompress collection */
1434 if (!load_collection(collection_index, (header->status&markSTRIP) ? true : false))
1435 {
1436 if (shapes_file_version != M1_SHAPES_VERSION)
1437 {
1438 alert_out_of_memory();
1439 }
1440 }
1441 // OGL_LoadModelsImages(collection_index);
1442 }
1443 }
1444
1445 /* clear action flags */
1446 header->status= markNONE;
1447 header->flags= 0;
1448 }
1449
1450 Plugins::instance()->load_shapes_patches(is_opengl);
1451
1452 if (shapes_patch.size())
1453 {
1454 SDL_RWops *f = SDL_RWFromMem(&shapes_patch[0], shapes_patch.size());
1455 load_shapes_patch(f, true);
1456 SDL_RWclose(f);
1457 }
1458
1459 /* remap the shapes, recalculate row base addresses, build our new world color table and
1460 (finally) update the screen to reflect our changes */
1461 update_color_environment(is_opengl);
1462
1463 // load software enhancements
1464 if (!is_opengl) {
1465 for (collection_index= 0, header= collection_headers; collection_index < MAXIMUM_COLLECTIONS; ++collection_index, ++header)
1466 {
1467 if (collection_loaded(header))
1468 {
1469 SW_Texture_Extras::instance()->Load(collection_index);
1470 }
1471 }
1472 }
1473 // if (with_progress_bar)
1474 // close_progress_dialog();
1475 }
1476
1477 #ifdef HAVE_OPENGL
1478
count_replacement_collections()1479 int count_replacement_collections()
1480 {
1481 int total_replacements = 0;
1482 short collection_index;
1483 struct collection_header *header;
1484 for (collection_index = 0, header = collection_headers; collection_index < MAXIMUM_COLLECTIONS; ++collection_index, ++header)
1485 {
1486 if (collection_loaded(header))
1487 {
1488 total_replacements += OGL_CountModelsImages(collection_index);
1489 }
1490 }
1491
1492 return total_replacements;
1493 }
1494
load_replacement_collections()1495 void load_replacement_collections()
1496 {
1497 struct collection_header *header;
1498 short collection_index;
1499
1500 for (collection_index= 0, header= collection_headers; collection_index < MAXIMUM_COLLECTIONS; ++collection_index, ++header)
1501 {
1502 if (collection_loaded(header))
1503 {
1504 OGL_LoadModelsImages(collection_index);
1505 }
1506 }
1507 }
1508
1509 #endif
1510
1511 /* ---------- private code */
1512
precalculate_bit_depth_constants(void)1513 static void precalculate_bit_depth_constants(
1514 void)
1515 {
1516 switch (bit_depth)
1517 {
1518 case 8:
1519 number_of_shading_tables= 32;
1520 shading_table_fractional_bits= 5;
1521 // next_shading_table_shift= 8;
1522 shading_table_size= PIXEL8_MAXIMUM_COLORS*sizeof(pixel8);
1523 break;
1524 case 16:
1525 number_of_shading_tables= 64;
1526 shading_table_fractional_bits= 6;
1527 // next_shading_table_shift= 9;
1528 shading_table_size= PIXEL8_MAXIMUM_COLORS*sizeof(pixel16);
1529 break;
1530 case 32:
1531 number_of_shading_tables= 256;
1532 shading_table_fractional_bits= 8;
1533 // next_shading_table_shift= 10;
1534 shading_table_size= PIXEL8_MAXIMUM_COLORS*sizeof(pixel32);
1535 break;
1536 }
1537 }
1538
1539 /* given a list of RGBColors, find out which one, if any, match the given color. if there
1540 aren�t any matches, add a new entry and return that index. */
find_or_add_color(struct rgb_color_value * color,struct rgb_color_value * colors,short * color_count,bool update_flags=true)1541 static short find_or_add_color(
1542 struct rgb_color_value *color,
1543 struct rgb_color_value *colors,
1544 short *color_count,
1545 bool update_flags = true)
1546 {
1547 short i;
1548
1549 // LP addition: save initial color-table pointer, just in case we overflow
1550 struct rgb_color_value *colors_saved = colors;
1551
1552 // = 1 to skip the transparent color
1553 for (i= 1, colors+= 1; i<*color_count; ++i, ++colors)
1554 {
1555 if (colors->red==color->red && colors->green==color->green && colors->blue==color->blue)
1556 {
1557 if (update_flags) colors->flags= color->flags;
1558 return i;
1559 }
1560 }
1561
1562 // LP change: added a fallback strategy; if there were too many colors,
1563 // then find the closest one
1564 if (*color_count >= PIXEL8_MAXIMUM_COLORS)
1565 {
1566 // Set up minimum distance, its index
1567 // Strictly speaking, the distance squared, since that will be
1568 // what we will be calculating.
1569 // The color values are data type "word", which is unsigned short;
1570 // this explains the initial choice of minimum value --
1571 // as greater than any possible such value.
1572 double MinDiffSq = 3*double(65536)*double(65536);
1573 short MinIndx = 0;
1574
1575 // Rescan
1576 colors = colors_saved;
1577 for (i= 1, colors+= 1; i<*color_count; ++i, ++colors)
1578 {
1579 double RedDiff = double(color->red) - double(colors->red);
1580 double GreenDiff = double(color->green) - double(colors->green);
1581 double BlueDiff = double(color->blue) - double(colors->blue);
1582 double DiffSq = RedDiff*RedDiff + GreenDiff*GreenDiff + BlueDiff*BlueDiff;
1583 if (DiffSq < MinDiffSq)
1584 {
1585 MinIndx = i;
1586 MinDiffSq = DiffSq;
1587 }
1588 }
1589 return MinIndx;
1590 }
1591
1592 // assert(*color_count<PIXEL8_MAXIMUM_COLORS);
1593 *colors= *color;
1594
1595 return (*color_count)++;
1596 }
1597
update_color_environment(bool is_opengl)1598 static void update_color_environment(
1599 bool is_opengl)
1600 {
1601 short color_count;
1602 short collection_index;
1603 short bitmap_index;
1604
1605 pixel8 remapping_table[PIXEL8_MAXIMUM_COLORS];
1606 struct rgb_color_value colors[PIXEL8_MAXIMUM_COLORS];
1607
1608 memset(remapping_table, 0, PIXEL8_MAXIMUM_COLORS*sizeof(pixel8));
1609
1610 // dummy color to hold the first index (zero) for transparent pixels
1611 colors[0].red= colors[0].green= colors[0].blue= 65535;
1612 colors[0].flags= colors[0].value= 0;
1613 color_count= 1;
1614
1615 /* loop through all collections, only paying attention to the loaded ones. we�re
1616 depending on finding the gray run (white to black) first; so it�s the responsibility
1617 of the lowest numbered loaded collection to give us this */
1618 for (collection_index=0;collection_index<MAXIMUM_COLLECTIONS;++collection_index)
1619 {
1620 struct collection_definition *collection= get_collection_definition(collection_index);
1621
1622 // dprintf("collection #%d", collection_index);
1623
1624 if (collection && collection->bitmap_count)
1625 {
1626 struct rgb_color_value *primary_colors= get_collection_colors(collection_index, 0)+NUMBER_OF_PRIVATE_COLORS;
1627 assert(primary_colors);
1628 short color_index, clut_index;
1629
1630 // if (collection_index==15) dprintf("primary clut %p", primary_colors);
1631 // dprintf("primary clut %d entries;dm #%d #%d", collection->color_count, primary_colors, collection->color_count*sizeof(ColorSpec));
1632
1633 /* add the colors from this collection�s primary color table to the aggregate color
1634 table and build the remapping table */
1635 for (color_index=0;color_index<collection->color_count-NUMBER_OF_PRIVATE_COLORS;++color_index)
1636 {
1637 primary_colors[color_index].value= remapping_table[primary_colors[color_index].value]=
1638 find_or_add_color(&primary_colors[color_index], colors, &color_count);
1639 }
1640
1641 /* then remap the collection and recalculate the base addresses of each bitmap */
1642 for (bitmap_index= 0; bitmap_index<collection->bitmap_count; ++bitmap_index)
1643 {
1644 struct bitmap_definition *bitmap= get_bitmap_definition(collection_index, bitmap_index);
1645 assert(bitmap);
1646
1647 /* calculate row base addresses ... */
1648 bitmap->row_addresses[0]= calculate_bitmap_origin(bitmap);
1649 precalculate_bitmap_row_addresses(bitmap);
1650
1651 /* ... and remap it */
1652 remap_bitmap(bitmap, remapping_table);
1653 }
1654
1655 /* build a shading table for each clut in this collection */
1656 for (clut_index= 0; clut_index<collection->clut_count; ++clut_index)
1657 {
1658 void *primary_shading_table= get_collection_shading_tables(collection_index, 0);
1659 short collection_bit_depth= collection->type==_interface_collection ? 8 : bit_depth;
1660
1661 if (clut_index)
1662 {
1663 struct rgb_color_value *alternate_colors= get_collection_colors(collection_index, clut_index)+NUMBER_OF_PRIVATE_COLORS;
1664 assert(alternate_colors);
1665 void *alternate_shading_table= get_collection_shading_tables(collection_index, clut_index);
1666 pixel8 shading_remapping_table[PIXEL8_MAXIMUM_COLORS];
1667
1668 memset(shading_remapping_table, 0, PIXEL8_MAXIMUM_COLORS*sizeof(pixel8));
1669
1670 // dprintf("alternate clut %d entries;dm #%d #%d", collection->color_count, alternate_colors, collection->color_count*sizeof(ColorSpec));
1671
1672 /* build a remapping table for the primary shading table which we can use to
1673 calculate this alternate shading table */
1674 for (color_index= 0; color_index<PIXEL8_MAXIMUM_COLORS; ++color_index) shading_remapping_table[color_index]= static_cast<pixel8>(color_index);
1675 for (color_index= 0; color_index<collection->color_count-NUMBER_OF_PRIVATE_COLORS; ++color_index)
1676 {
1677 shading_remapping_table[find_or_add_color(&primary_colors[color_index], colors, &color_count, false)]=
1678 find_or_add_color(&alternate_colors[color_index], colors, &color_count);
1679 }
1680 // shading_remapping_table[iBLACK]= iBLACK; /* make iBLACK==>iBLACK remapping explicit */
1681
1682 switch (collection_bit_depth)
1683 {
1684 case 8:
1685 /* duplicate the primary shading table and remap it */
1686 memcpy(alternate_shading_table, primary_shading_table, get_shading_table_size(collection_index));
1687 map_bytes((unsigned char *)alternate_shading_table, shading_remapping_table, get_shading_table_size(collection_index));
1688 break;
1689
1690 case 16:
1691 build_shading_tables16(colors, color_count, (pixel16 *)alternate_shading_table, shading_remapping_table, is_opengl); break;
1692 break;
1693
1694 case 32:
1695 build_shading_tables32(colors, color_count, (pixel32 *)alternate_shading_table, shading_remapping_table, is_opengl); break;
1696 break;
1697
1698 default:
1699 assert(false);
1700 break;
1701 }
1702 }
1703 else
1704 {
1705 /* build the primary shading table */
1706 switch (collection_bit_depth)
1707 {
1708 case 8: build_shading_tables8(colors, color_count, (unsigned char *)primary_shading_table); break;
1709 case 16: build_shading_tables16(colors, color_count, (pixel16 *)primary_shading_table, (byte *) NULL, is_opengl); break;
1710 case 32: build_shading_tables32(colors, color_count, (pixel32 *)primary_shading_table, (byte *) NULL, is_opengl); break;
1711 default:
1712 assert(false);
1713 break;
1714 }
1715 }
1716 }
1717
1718 build_collection_tinting_table(colors, color_count, collection_index, is_opengl);
1719
1720 /* 8-bit interface, non-8-bit main window; remember interface CLUT separately */
1721 if (collection_index==_collection_interface && interface_bit_depth==8 && bit_depth!=interface_bit_depth) _change_clut(change_interface_clut, colors, color_count);
1722
1723 /* if we�re not in 8-bit, we don�t have to carry our colors over into the next collection */
1724 if (bit_depth!=8) color_count= 1;
1725 }
1726 }
1727
1728 #ifdef DEBUG
1729 // dump_colors(colors, color_count);
1730 #endif
1731
1732 /* change the screen clut and rebuild our shading tables */
1733 _change_clut(change_screen_clut, colors, color_count);
1734 }
1735
_change_clut(void (* change_clut_proc)(struct color_table * color_table),struct rgb_color_value * colors,short color_count)1736 static void _change_clut(
1737 void (*change_clut_proc)(struct color_table *color_table),
1738 struct rgb_color_value *colors,
1739 short color_count)
1740 {
1741 struct color_table color_table;
1742 struct rgb_color *color;
1743 short i;
1744
1745 color= color_table.colors;
1746 color_table.color_count= PIXEL8_MAXIMUM_COLORS;
1747 for (i= 0; i<color_count; ++i, ++color, ++colors)
1748 {
1749 *color= *((struct rgb_color *)&colors->red);
1750 }
1751 for (i= color_count; i<PIXEL8_MAXIMUM_COLORS; ++i, ++color)
1752 {
1753 color->red= color->green= color->blue= 0;
1754 }
1755 change_clut_proc(&color_table);
1756 }
1757
1758 #ifndef SCREAMING_METAL
build_shading_tables8(struct rgb_color_value * colors,short color_count,pixel8 * shading_tables)1759 static void build_shading_tables8(
1760 struct rgb_color_value *colors,
1761 short color_count,
1762 pixel8 *shading_tables)
1763 {
1764 short i;
1765 short start, count, level, value;
1766
1767 objlist_set(shading_tables, iBLACK, PIXEL8_MAXIMUM_COLORS);
1768
1769 start= 0, count= 0;
1770 while (get_next_color_run(colors, color_count, &start, &count))
1771 {
1772 for (i= 0; i<count; ++i)
1773 {
1774 assert(number_of_shading_tables > 1);
1775 short adjust= start ? 1 : 0;
1776
1777 for (level= 0; level<number_of_shading_tables; ++level)
1778 {
1779 struct rgb_color_value *color= colors + start + i;
1780 short multiplier= (color->flags&SELF_LUMINESCENT_COLOR_FLAG) ? (level>>1) : level;
1781
1782 value= i + (multiplier*(count+adjust-i))/(number_of_shading_tables-1);
1783 if (value>=count) value= iBLACK; else value= start+value;
1784 shading_tables[PIXEL8_MAXIMUM_COLORS*(number_of_shading_tables-level-1)+start+i]= value;
1785 }
1786 }
1787 }
1788 }
1789 #else
find_closest_color(struct rgb_color_value * color,struct rgb_color_value * colors,short color_count)1790 short find_closest_color(
1791 struct rgb_color_value *color,
1792 struct rgb_color_value *colors,
1793 short color_count)
1794 {
1795 short i;
1796 int32 closest_delta= INT32_MAX;
1797 short closest_index= 0;
1798
1799 // = 1 to skip the transparent color
1800 for (i= 1, colors+= 1; i<color_count; ++i, ++colors)
1801 {
1802 int32 delta= (int32)ABS(colors->red-color->red) +
1803 (int32)ABS(colors->green-color->green) +
1804 (int32)ABS(colors->blue-color->blue);
1805
1806 if (delta<closest_delta) closest_index= i, closest_delta= delta;
1807 }
1808
1809 return closest_index;
1810 }
1811
build_shading_tables8(struct rgb_color_value * colors,short color_count,pixel8 * shading_tables)1812 static void build_shading_tables8(
1813 struct rgb_color_value *colors,
1814 short color_count,
1815 pixel8 *shading_tables)
1816 {
1817 short i;
1818 short start, count, level;
1819
1820 objlist_set(shading_tables, iBLACK, PIXEL8_MAXIMUM_COLORS);
1821
1822 start= 0, count= 0;
1823 while (get_next_color_run(colors, color_count, &start, &count))
1824 {
1825 for (i= 0; i<count; ++i)
1826 {
1827 for (level= 0; level<number_of_shading_tables; ++level)
1828 {
1829 struct rgb_color_value *color= colors + start + i;
1830 rgb_color_value result;
1831
1832 result.red= (color->red*level)/(number_of_shading_tables-1);
1833 result.green= (color->green*level)/(number_of_shading_tables-1);
1834 result.blue= (color->blue*level)/(number_of_shading_tables-1);
1835 shading_tables[PIXEL8_MAXIMUM_COLORS*level+start+i]=
1836 find_closest_color(&result, colors, color_count);
1837 }
1838 }
1839 }
1840 }
1841 #endif
1842
build_shading_tables16(struct rgb_color_value * colors,short color_count,pixel16 * shading_tables,byte * remapping_table,bool is_opengl)1843 static void build_shading_tables16(
1844 struct rgb_color_value *colors,
1845 short color_count,
1846 pixel16 *shading_tables,
1847 byte *remapping_table,
1848 bool is_opengl)
1849 {
1850 short i;
1851 short start, count, level;
1852
1853 objlist_set(shading_tables, 0, PIXEL8_MAXIMUM_COLORS);
1854
1855 SDL_PixelFormat *fmt = &pixel_format_16;
1856
1857 start= 0, count= 0;
1858 while (get_next_color_run(colors, color_count, &start, &count))
1859 {
1860 for (i=0;i<count;++i)
1861 {
1862 assert(number_of_shading_tables > 1);
1863 for (level= 0; level<number_of_shading_tables; ++level)
1864 {
1865 struct rgb_color_value *color= colors + (remapping_table ? remapping_table[start+i] : (start+i));
1866 short multiplier= (color->flags&SELF_LUMINESCENT_COLOR_FLAG) ? ((number_of_shading_tables>>1)+(level>>1)) : level;
1867 if (!is_opengl)
1868 // Find optimal pixel value for video display
1869 shading_tables[PIXEL8_MAXIMUM_COLORS*level+start+i]=
1870 SDL_MapRGB(fmt,
1871 ((color->red * multiplier) / (number_of_shading_tables-1)) >> 8,
1872 ((color->green * multiplier) / (number_of_shading_tables-1)) >> 8,
1873 ((color->blue * multiplier) / (number_of_shading_tables-1)) >> 8);
1874 else
1875 // Mac xRGB 1555 pixel format
1876 shading_tables[PIXEL8_MAXIMUM_COLORS*level+start+i]=
1877 RGBCOLOR_TO_PIXEL16((color->red*multiplier)/(number_of_shading_tables-1),
1878 (color->green*multiplier)/(number_of_shading_tables-1),
1879 (color->blue*multiplier)/(number_of_shading_tables-1));
1880 }
1881 }
1882 }
1883 }
1884
build_shading_tables32(struct rgb_color_value * colors,short color_count,pixel32 * shading_tables,byte * remapping_table,bool is_opengl)1885 static void build_shading_tables32(
1886 struct rgb_color_value *colors,
1887 short color_count,
1888 pixel32 *shading_tables,
1889 byte *remapping_table,
1890 bool is_opengl)
1891 {
1892 short i;
1893 short start, count, level;
1894
1895 objlist_set(shading_tables, 0, PIXEL8_MAXIMUM_COLORS);
1896
1897 SDL_PixelFormat *fmt = &pixel_format_32;
1898
1899 start= 0, count= 0;
1900 while (get_next_color_run(colors, color_count, &start, &count))
1901 {
1902 for (i= 0; i<count; ++i)
1903 {
1904 assert(number_of_shading_tables > 1);
1905 for (level= 0; level<number_of_shading_tables; ++level)
1906 {
1907 struct rgb_color_value *color= colors + (remapping_table ? remapping_table[start+i] : (start+i));
1908 short multiplier= (color->flags&SELF_LUMINESCENT_COLOR_FLAG) ? ((number_of_shading_tables>>1)+(level>>1)) : level;
1909
1910 if (!is_opengl)
1911 // Find optimal pixel value for video display
1912 shading_tables[PIXEL8_MAXIMUM_COLORS*level+start+i]=
1913 SDL_MapRGB(fmt,
1914 ((color->red * multiplier) / (number_of_shading_tables-1)) >> 8,
1915 ((color->green * multiplier) / (number_of_shading_tables-1)) >> 8,
1916 ((color->blue * multiplier) / (number_of_shading_tables-1)) >> 8);
1917 else
1918 // Mac xRGB 8888 pixel format
1919 shading_tables[PIXEL8_MAXIMUM_COLORS*level+start+i]=
1920 RGBCOLOR_TO_PIXEL32((color->red*multiplier)/(number_of_shading_tables-1),
1921 (color->green*multiplier)/(number_of_shading_tables-1),
1922 (color->blue*multiplier)/(number_of_shading_tables-1));
1923 }
1924 }
1925 }
1926 }
1927
build_global_shading_table16(void)1928 static void build_global_shading_table16(
1929 void)
1930 {
1931 if (!global_shading_table16)
1932 {
1933 short value, shading_table;
1934 pixel16 *write;
1935
1936 SDL_PixelFormat *fmt = &pixel_format_16;
1937
1938 global_shading_table16= (pixel16 *) malloc(sizeof(pixel16)*number_of_shading_tables*NUMBER_OF_COLOR_COMPONENTS*(PIXEL16_MAXIMUM_COMPONENT+1));
1939 assert(global_shading_table16);
1940
1941 write= global_shading_table16;
1942 for (shading_table= 0; shading_table<number_of_shading_tables; ++shading_table)
1943 {
1944 // Under SDL, the components may have different widths and different shifts
1945 int shift = fmt->Rshift + (3 - fmt->Rloss);
1946 for (value=0;value<=PIXEL16_MAXIMUM_COMPONENT;++value)
1947 *write++ = ((value*(shading_table))/(number_of_shading_tables-1))<<shift;
1948 shift = fmt->Gshift + (3 - fmt->Gloss);
1949 for (value=0;value<=PIXEL16_MAXIMUM_COMPONENT;++value)
1950 *write++ = ((value*(shading_table))/(number_of_shading_tables-1))<<shift;
1951 shift = fmt->Bshift + (3 - fmt->Bloss);
1952 for (value=0;value<=PIXEL16_MAXIMUM_COMPONENT;++value)
1953 *write++ = ((value*(shading_table))/(number_of_shading_tables-1))<<shift;
1954 }
1955 }
1956 }
1957
build_global_shading_table32(void)1958 static void build_global_shading_table32(
1959 void)
1960 {
1961 if (!global_shading_table32)
1962 {
1963 short value, shading_table;
1964 pixel32 *write;
1965
1966 SDL_PixelFormat *fmt = &pixel_format_32;
1967
1968 global_shading_table32= (pixel32 *) malloc(sizeof(pixel32)*number_of_shading_tables*NUMBER_OF_COLOR_COMPONENTS*(PIXEL32_MAXIMUM_COMPONENT+1));
1969 assert(global_shading_table32);
1970
1971 write= global_shading_table32;
1972 for (shading_table= 0; shading_table<number_of_shading_tables; ++shading_table)
1973 {
1974 // Under SDL, the components may have different widths and different shifts
1975 int shift = fmt->Rshift - fmt->Rloss;
1976 for (value=0;value<=PIXEL32_MAXIMUM_COMPONENT;++value)
1977 *write++ = ((value*(shading_table))/(number_of_shading_tables-1))<<shift;
1978 shift = fmt->Gshift - fmt->Gloss;
1979 for (value=0;value<=PIXEL32_MAXIMUM_COMPONENT;++value)
1980 *write++ = ((value*(shading_table))/(number_of_shading_tables-1))<<shift;
1981 shift = fmt->Bshift - fmt->Bloss;
1982 for (value=0;value<=PIXEL32_MAXIMUM_COMPONENT;++value)
1983 *write++ = ((value*(shading_table))/(number_of_shading_tables-1))<<shift;
1984 }
1985 }
1986 }
1987
get_next_color_run(struct rgb_color_value * colors,short color_count,short * start,short * count)1988 static bool get_next_color_run(
1989 struct rgb_color_value *colors,
1990 short color_count,
1991 short *start,
1992 short *count)
1993 {
1994 bool not_done= false;
1995 struct rgb_color_value last_color;
1996
1997 if (*start+*count<color_count)
1998 {
1999 *start+= *count;
2000 for (*count=0;*start+*count<color_count;*count+= 1)
2001 {
2002 if (*count)
2003 {
2004 if (new_color_run(colors+*start+*count, &last_color))
2005 {
2006 break;
2007 }
2008 }
2009 last_color= colors[*start+*count];
2010 }
2011
2012 not_done= true;
2013 }
2014
2015 return not_done;
2016 }
2017
new_color_run(struct rgb_color_value * _new,struct rgb_color_value * last)2018 static bool new_color_run(
2019 struct rgb_color_value *_new,
2020 struct rgb_color_value *last)
2021 {
2022 if ((int32)last->red+(int32)last->green+(int32)last->blue<(int32)_new->red+(int32)_new->green+(int32)_new->blue)
2023 {
2024 return true;
2025 }
2026 else
2027 {
2028 return false;
2029 }
2030 }
2031
get_shading_table_size(short collection_code)2032 static int32 get_shading_table_size(
2033 short collection_code)
2034 {
2035 int32 size;
2036
2037 switch (bit_depth)
2038 {
2039 case 8: size= number_of_shading_tables*shading_table_size; break;
2040 case 16: size= number_of_shading_tables*shading_table_size; break;
2041 case 32: size= number_of_shading_tables*shading_table_size; break;
2042 default:
2043 assert(false);
2044 break;
2045 }
2046
2047 return size;
2048 }
2049
2050 /* --------- light enhancement goggles */
2051
2052 enum /* collection tint colors */
2053 {
2054 _tint_collection_red,
2055 _tint_collection_green,
2056 _tint_collection_blue,
2057 _tint_collection_yellow,
2058 NUMBER_OF_TINT_COLORS
2059 };
2060
2061 struct tint_color8_data
2062 {
2063 short start, count;
2064 };
2065
2066 static struct rgb_color tint_colors16[NUMBER_OF_TINT_COLORS]=
2067 {
2068 {65535, 0, 0},
2069 {0, 65535, 0},
2070 {0, 0, 65535},
2071 {65535, 65535, 0},
2072 };
2073
2074 static struct tint_color8_data tint_colors8[NUMBER_OF_TINT_COLORS]=
2075 {
2076 {45, 13},
2077 {32, 13},
2078 {96, 13},
2079 {83, 13},
2080 };
2081
2082
2083 // LP addition to make it more generic;
2084 // the ultimate in this would be to make every collection
2085 // have its own infravision tint.
2086 static short CollectionTints[NUMBER_OF_COLLECTIONS] =
2087 {
2088 // Interface
2089 NONE,
2090 // Weapons in hand
2091 _tint_collection_yellow,
2092 // Juggernaut, tick
2093 _tint_collection_red,
2094 _tint_collection_red,
2095 // Explosion effects
2096 _tint_collection_yellow,
2097 // Hunter
2098 _tint_collection_red,
2099 // Player
2100 _tint_collection_yellow,
2101 // Items
2102 _tint_collection_green,
2103 // Trooper, Pfhor, S'pht'Kr, F'lickta
2104 _tint_collection_red,
2105 _tint_collection_red,
2106 _tint_collection_red,
2107 _tint_collection_red,
2108 // Bob and VacBobs
2109 _tint_collection_yellow,
2110 _tint_collection_yellow,
2111 // Enforcer, Drone
2112 _tint_collection_red,
2113 _tint_collection_red,
2114 // S'pht
2115 _tint_collection_blue,
2116 // Walls
2117 _tint_collection_blue,
2118 _tint_collection_blue,
2119 _tint_collection_blue,
2120 _tint_collection_blue,
2121 _tint_collection_blue,
2122 // Scenery
2123 _tint_collection_blue,
2124 _tint_collection_blue,
2125 _tint_collection_blue,
2126 _tint_collection_blue,
2127 _tint_collection_blue,
2128 // Landscape
2129 _tint_collection_blue,
2130 _tint_collection_blue,
2131 _tint_collection_blue,
2132 _tint_collection_blue,
2133 // Cyborg
2134 _tint_collection_red
2135 };
2136
2137
build_collection_tinting_table(struct rgb_color_value * colors,short color_count,short collection_index,bool is_opengl)2138 static void build_collection_tinting_table(
2139 struct rgb_color_value *colors,
2140 short color_count,
2141 short collection_index,
2142 bool is_opengl)
2143 {
2144 struct collection_definition *collection= get_collection_definition(collection_index);
2145 if (!collection) return;
2146
2147 void *tint_table= get_collection_tint_tables(collection_index, 0);
2148 short tint_color;
2149
2150 /* get the tint color */
2151 // LP change: look up a table
2152 tint_color = CollectionTints[collection_index];
2153 // Idiot-proofing:
2154 if (tint_color >= NUMBER_OF_TINT_COLORS)
2155 tint_color = NONE;
2156 else
2157 tint_color = MAX(tint_color,NONE);
2158
2159 /* build the tint table */
2160 if (tint_color!=NONE)
2161 {
2162 // LP addition: OpenGL support
2163 rgb_color &Color = tint_colors16[tint_color];
2164 #ifdef HAVE_OPENGL
2165 OGL_SetInfravisionTint(collection_index,true,Color.red/65535.0F,Color.green/65535.0F,Color.blue/65535.0F);
2166 #endif
2167 switch (bit_depth)
2168 {
2169 case 8:
2170 build_tinting_table8(colors, color_count, (unsigned char *)tint_table, tint_colors8[tint_color].start, tint_colors8[tint_color].count);
2171 break;
2172 case 16:
2173 build_tinting_table16(colors, color_count, (pixel16 *)tint_table, tint_colors16+tint_color);
2174 break;
2175 case 32:
2176 build_tinting_table32(colors, color_count, (pixel32 *)tint_table, tint_colors16+tint_color, is_opengl);
2177 break;
2178 }
2179 }
2180 else
2181 {
2182 // LP addition: OpenGL support
2183 #ifdef HAVE_OPENGL
2184 OGL_SetInfravisionTint(collection_index,false,1,1,1);
2185 #endif
2186 }
2187 }
2188
build_tinting_table8(struct rgb_color_value * colors,short color_count,pixel8 * tint_table,short tint_start,short tint_count)2189 static void build_tinting_table8(
2190 struct rgb_color_value *colors,
2191 short color_count,
2192 pixel8 *tint_table,
2193 short tint_start,
2194 short tint_count)
2195 {
2196 short start, count;
2197
2198 start= count= 0;
2199 while (get_next_color_run(colors, color_count, &start, &count))
2200 {
2201 short i;
2202
2203 for (i=0; i<count; ++i)
2204 {
2205 short adjust= start ? 0 : 1;
2206 short value= (i*(tint_count+adjust))/count;
2207
2208 value= (value>=tint_count) ? iBLACK : tint_start + value;
2209 tint_table[start+i]= value;
2210 }
2211 }
2212 }
2213
2214 // Return intensity(base)*tint, with M2-style rounding behavior
m2_apply_tint(rgb_color_value base,rgb_color tint)2215 static rgb_color m2_apply_tint(rgb_color_value base, rgb_color tint)
2216 {
2217 const uint16 base_mag = (int32{base.red} + base.green + base.blue) / 3;
2218 auto scale = [base_mag](uint16 comp) { return uint16(int32(1LL*base_mag*comp) / 65535); };
2219 return {scale(tint.red), scale(tint.green), scale(tint.blue)};
2220 }
2221
build_tinting_table16(struct rgb_color_value * colors,short color_count,pixel16 * tint_table,struct rgb_color * tint_color)2222 static void build_tinting_table16(
2223 struct rgb_color_value *colors,
2224 short color_count,
2225 pixel16 *tint_table,
2226 struct rgb_color *tint_color)
2227 {
2228 short i;
2229
2230 SDL_PixelFormat *fmt = &pixel_format_16;
2231
2232 for (i= 0; i<color_count; ++i, ++colors)
2233 {
2234 const rgb_color tinted_color = m2_apply_tint(*colors, *tint_color);
2235
2236 // Find optimal pixel value for video display
2237 *tint_table++ = SDL_MapRGB(fmt, tinted_color.red >> 8, tinted_color.green >> 8, tinted_color.blue >> 8);
2238 }
2239 }
2240
build_tinting_table32(struct rgb_color_value * colors,short color_count,pixel32 * tint_table,struct rgb_color * tint_color,bool is_opengl)2241 static void build_tinting_table32(
2242 struct rgb_color_value *colors,
2243 short color_count,
2244 pixel32 *tint_table,
2245 struct rgb_color *tint_color,
2246 bool is_opengl)
2247 {
2248 short i;
2249
2250 SDL_PixelFormat *fmt = &pixel_format_32;
2251
2252 for (i= 0; i<color_count; ++i, ++colors)
2253 {
2254 const rgb_color tinted_color = m2_apply_tint(*colors, *tint_color);
2255
2256 // Find optimal pixel value for video display
2257 if (!is_opengl)
2258 *tint_table++ = SDL_MapRGB(fmt, tinted_color.red >> 8, tinted_color.green >> 8, tinted_color.blue >> 8);
2259 else
2260 // Mac xRGB 8888 pixel format
2261 *tint_table++ = RGBCOLOR_TO_PIXEL32(tinted_color.red, tinted_color.green, tinted_color.blue);
2262 }
2263 }
2264
2265
2266 /* ---------- collection accessors */
2267 // Some originally from shapes_macintosh.c
2268
get_collection_header(short collection_index)2269 static struct collection_header *get_collection_header(
2270 short collection_index)
2271 {
2272 // This one is intended to bomb because collection indices can only be from 1 to 31,
2273 // short of drastic changes in how collection indices are specified (a bigger structure
2274 // than shape_descriptor, for example).
2275 collection_header *header = GetMemberWithBounds(collection_headers,collection_index,MAXIMUM_COLLECTIONS);
2276 vassert(header,csprintf(temporary,"Collection index out of range: %d",collection_index));
2277
2278 return header;
2279
2280 /*
2281 assert(collection_index>=0 && collection_index<MAXIMUM_COLLECTIONS);
2282
2283 return collection_headers + collection_index;
2284 */
2285 }
2286
get_collection_definition(short collection_index)2287 /*static*/ struct collection_definition *get_collection_definition(
2288 short collection_index)
2289 {
2290 return get_collection_header(collection_index)->collection;
2291 }
2292
get_collection_colors(short collection_index,short clut_number)2293 static struct rgb_color_value *get_collection_colors(
2294 short collection_index,
2295 short clut_number)
2296 {
2297 collection_definition *definition = get_collection_definition(collection_index);
2298 if (!definition) return NULL;
2299 if (!(clut_number >= 0 && clut_number < definition->clut_count))
2300 return NULL;
2301
2302 return &definition->color_tables[clut_number * definition->color_count];
2303 }
2304
get_collection_colors(short collection_index,short clut_number,int & num_colors)2305 struct rgb_color_value *get_collection_colors(
2306 short collection_index,
2307 short clut_number,
2308 int &num_colors)
2309 {
2310 collection_definition *definition = get_collection_definition(collection_index);
2311 if (!definition) return NULL;
2312 if (!(clut_number >=0 && clut_number < definition->clut_count)) return NULL;
2313 num_colors = definition->color_count;
2314 return &definition->color_tables[clut_number * definition->color_count];
2315 }
2316
get_high_level_shape_definition(short collection_index,short high_level_shape_index)2317 static struct high_level_shape_definition *get_high_level_shape_definition(
2318 short collection_index,
2319 short high_level_shape_index)
2320 {
2321 struct collection_definition *definition = get_collection_definition(collection_index);
2322 if (!definition) return NULL;
2323
2324 if (!(high_level_shape_index >= 0 && high_level_shape_index<definition->high_level_shapes.size()))
2325 return NULL;
2326
2327 if (definition->high_level_shapes[high_level_shape_index].empty())
2328 return NULL;
2329
2330 return (high_level_shape_definition *) &definition->high_level_shapes[high_level_shape_index][0];
2331 }
2332
get_low_level_shape_definition(short collection_index,short low_level_shape_index)2333 struct low_level_shape_definition *get_low_level_shape_definition(
2334 short collection_index,
2335 short low_level_shape_index)
2336 {
2337 collection_definition *definition = get_collection_definition(collection_index);
2338 if (!definition) return NULL;
2339 if (low_level_shape_index >= 0 && low_level_shape_index < definition->low_level_shapes.size())
2340 {
2341 return &definition->low_level_shapes[low_level_shape_index];
2342 }
2343 else
2344 return NULL;
2345 }
2346
get_bitmap_definition(short collection_index,short bitmap_index)2347 static struct bitmap_definition *get_bitmap_definition(
2348 short collection_index,
2349 short bitmap_index)
2350 {
2351 collection_definition *definition = get_collection_definition(collection_index);
2352 if (!definition) return NULL;
2353 if (!(bitmap_index >= 0 && bitmap_index < definition->bitmaps.size()))
2354 return NULL;
2355
2356 if (definition->bitmaps[bitmap_index].empty())
2357 return NULL;
2358
2359 return (bitmap_definition *) &definition->bitmaps[bitmap_index][0];
2360 }
2361
get_collection_shading_tables(short collection_index,short clut_index)2362 static void *get_collection_shading_tables(
2363 short collection_index,
2364 short clut_index)
2365 {
2366 void *shading_tables= get_collection_header(collection_index)->shading_tables;
2367
2368 shading_tables = (uint8 *)shading_tables + clut_index*get_shading_table_size(collection_index);
2369
2370 return shading_tables;
2371 }
2372
get_collection_tint_tables(short collection_index,short tint_index)2373 static void *get_collection_tint_tables(
2374 short collection_index,
2375 short tint_index)
2376 {
2377 struct collection_definition *definition= get_collection_definition(collection_index);
2378 if (!definition) return NULL;
2379
2380 void *tint_table= get_collection_header(collection_index)->shading_tables;
2381
2382 tint_table = (uint8 *)tint_table + get_shading_table_size(collection_index)*definition->clut_count + shading_table_size*tint_index;
2383
2384 return tint_table;
2385 }
2386
2387 // LP additions:
2388
2389 // Whether or not collection is present
is_collection_present(short collection_index)2390 bool is_collection_present(short collection_index)
2391 {
2392 collection_header *CollHeader = get_collection_header(collection_index);
2393 if (!CollHeader) return false;
2394 return collection_loaded(CollHeader);
2395 }
2396
2397 // Number of texture frames in a collection (good for wall-texture error checking)
get_number_of_collection_frames(short collection_index)2398 short get_number_of_collection_frames(short collection_index)
2399 {
2400 struct collection_definition *Collection = get_collection_definition(collection_index);
2401 if (!Collection) return 0;
2402 return Collection->low_level_shape_count;
2403 }
2404
2405 // Number of bitmaps in a collection (good for allocating texture information for OpenGL)
get_number_of_collection_bitmaps(short collection_index)2406 short get_number_of_collection_bitmaps(short collection_index)
2407 {
2408 struct collection_definition *Collection = get_collection_definition(collection_index);
2409 if (!Collection) return 0;
2410 return Collection->bitmap_count;
2411 }
2412
2413 // Which bitmap index for a frame (good for OpenGL texture rendering)
get_bitmap_index(short collection_index,short low_level_shape_index)2414 short get_bitmap_index(short collection_index, short low_level_shape_index)
2415 {
2416 struct low_level_shape_definition *low_level_shape= get_low_level_shape_definition(collection_index, low_level_shape_index);
2417 if (!low_level_shape) return NONE;
2418 return low_level_shape->bitmap_index;
2419 }
2420
2421
2422 // XML elements for parsing infravision specification
2423 short *OriginalCollectionTints = NULL;
2424 struct rgb_color *original_tint_colors16 = NULL;
2425
reset_mml_infravision()2426 void reset_mml_infravision()
2427 {
2428 if (original_tint_colors16) {
2429 for (int i = 0; i < NUMBER_OF_TINT_COLORS; i++)
2430 tint_colors16[i] = original_tint_colors16[i];
2431 free(original_tint_colors16);
2432 original_tint_colors16 = NULL;
2433 }
2434
2435 if (OriginalCollectionTints) {
2436 for (int i = 0; i < NUMBER_OF_COLLECTIONS; i++)
2437 CollectionTints[i] = OriginalCollectionTints[i];
2438 free(OriginalCollectionTints);
2439 OriginalCollectionTints = NULL;
2440 }
2441 }
2442
parse_mml_infravision(const InfoTree & root)2443 void parse_mml_infravision(const InfoTree& root)
2444 {
2445 // back up old values first
2446 if (!original_tint_colors16) {
2447 original_tint_colors16 = (struct rgb_color *) malloc(sizeof(struct rgb_color) * NUMBER_OF_TINT_COLORS);
2448 assert(original_tint_colors16);
2449 for (int i = 0; i < NUMBER_OF_TINT_COLORS; i++)
2450 original_tint_colors16[i] = tint_colors16[i];
2451 }
2452
2453 if (!OriginalCollectionTints) {
2454 OriginalCollectionTints = (short *) malloc(sizeof(short) * NUMBER_OF_COLLECTIONS);
2455 assert(OriginalCollectionTints);
2456 for (int i = 0; i < NUMBER_OF_COLLECTIONS; i++)
2457 OriginalCollectionTints[i] = CollectionTints[i];
2458 }
2459
2460 BOOST_FOREACH(InfoTree color, root.children_named("color"))
2461 {
2462 int16 index;
2463 if (!color.read_indexed("index", index, NUMBER_OF_TINT_COLORS))
2464 continue;
2465 color.read_color(tint_colors16[index]);
2466 }
2467
2468 BOOST_FOREACH(InfoTree assign, root.children_named("assign"))
2469 {
2470 int16 coll, color;
2471 if (!assign.read_indexed("coll", coll, NUMBER_OF_COLLECTIONS) ||
2472 !assign.read_indexed("color", color, NUMBER_OF_TINT_COLORS))
2473 continue;
2474 CollectionTints[coll] = color;
2475 }
2476 }
2477