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