]> icculus.org git repositories - btb/d2x.git/blob - main/bm.c
remove rcs tags
[btb/d2x.git] / main / bm.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Bitmap and palette loading functions.
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "pstypes.h"
29 #include "inferno.h"
30 #include "gr.h"
31 #include "bm.h"
32 #include "u_mem.h"
33 #include "mono.h"
34 #include "error.h"
35 #include "object.h"
36 #include "vclip.h"
37 #include "effects.h"
38 #include "polyobj.h"
39 #include "wall.h"
40 #include "textures.h"
41 #include "game.h"
42 #ifdef NETWORK
43 #include "multi.h"
44 #endif
45 #include "iff.h"
46 #include "cfile.h"
47 #include "powerup.h"
48 #include "sounds.h"
49 #include "piggy.h"
50 #include "aistruct.h"
51 #include "robot.h"
52 #include "weapon.h"
53 #include "gauges.h"
54 #include "player.h"
55 #include "endlevel.h"
56 #include "cntrlcen.h"
57 #include "makesig.h"
58 #include "interp.h"
59
60 ubyte Sounds[MAX_SOUNDS];
61 ubyte AltSounds[MAX_SOUNDS];
62
63 #ifdef EDITOR
64 int Num_object_subtypes = 1;
65 #endif
66
67 //for each model, a model number for dying & dead variants, or -1 if none
68 int Dying_modelnums[MAX_POLYGON_MODELS];
69 int Dead_modelnums[MAX_POLYGON_MODELS];
70
71 //the polygon model number to use for the marker
72 int     Marker_model_num = -1;
73
74 //right now there's only one player ship, but we can have another by
75 //adding an array and setting the pointer to the active ship.
76 player_ship only_player_ship,*Player_ship=&only_player_ship;
77
78 //----------------- Miscellaneous bitmap pointers ---------------
79 int             Num_cockpits = 0;
80 bitmap_index    cockpit_bitmap[N_COCKPIT_BITMAPS];
81
82 //---------------- Variables for wall textures ------------------
83 int             Num_tmaps;
84 tmap_info       TmapInfo[MAX_TEXTURES];
85
86 //---------------- Variables for object textures ----------------
87
88 int             First_multi_bitmap_num=-1;
89
90 int             N_ObjBitmaps;
91 bitmap_index    ObjBitmaps[MAX_OBJ_BITMAPS];
92 ushort          ObjBitmapPtrs[MAX_OBJ_BITMAPS];     // These point back into ObjBitmaps, since some are used twice.
93
94 #ifdef FAST_FILE_IO
95 #define tmap_info_read_n(ti, n, fp) cfread(ti, TMAP_INFO_SIZE, n, fp)
96 #else
97 /*
98  * reads n tmap_info structs from a CFILE
99  */
100 int tmap_info_read_n(tmap_info *ti, int n, CFILE *fp)
101 {
102         int i;
103
104         for (i = 0; i < n; i++) {
105                 ti[i].flags = cfile_read_byte(fp);
106                 ti[i].pad[0] = cfile_read_byte(fp);
107                 ti[i].pad[1] = cfile_read_byte(fp);
108                 ti[i].pad[2] = cfile_read_byte(fp);
109                 ti[i].lighting = cfile_read_fix(fp);
110                 ti[i].damage = cfile_read_fix(fp);
111                 ti[i].eclip_num = cfile_read_short(fp);
112                 ti[i].destroyed = cfile_read_short(fp);
113                 ti[i].slide_u = cfile_read_short(fp);
114                 ti[i].slide_v = cfile_read_short(fp);
115         }
116         return i;
117 }
118 #endif
119
120 int tmap_info_read_n_d1(tmap_info *ti, int n, CFILE *fp)
121 {
122         int i;
123
124         for (i = 0; i < n; i++) {
125                 cfseek(fp, 13, SEEK_CUR);// skip filename
126                 ti[i].flags = cfile_read_byte(fp);
127                 ti[i].lighting = cfile_read_fix(fp);
128                 ti[i].damage = cfile_read_fix(fp);
129                 ti[i].eclip_num = cfile_read_int(fp);
130         }
131         return i;
132 }
133
134
135 //-----------------------------------------------------------------
136 // Read data from piggy.
137 // This is called when the editor is OUT.
138 // If editor is in, bm_init_use_table() is called.
139 int bm_init()
140 {
141         init_polygon_models();
142         if (! piggy_init())                             // This calls bm_read_all
143                 Error("Cannot open pig and/or ham file");
144
145         piggy_read_sounds();
146
147         init_endlevel();                //this is in bm_init_use_tbl(), so I gues it goes here
148
149         return 0;
150 }
151
152 void bm_read_all(CFILE * fp)
153 {
154         int i,t;
155
156         NumTextures = cfile_read_int(fp);
157         bitmap_index_read_n(Textures, NumTextures, fp );
158         tmap_info_read_n(TmapInfo, NumTextures, fp);
159
160         t = cfile_read_int(fp);
161         cfread( Sounds, sizeof(ubyte), t, fp );
162         cfread( AltSounds, sizeof(ubyte), t, fp );
163
164         Num_vclips = cfile_read_int(fp);
165         vclip_read_n(Vclip, Num_vclips, fp);
166
167         Num_effects = cfile_read_int(fp);
168         eclip_read_n(Effects, Num_effects, fp);
169
170         Num_wall_anims = cfile_read_int(fp);
171         wclip_read_n(WallAnims, Num_wall_anims, fp);
172
173         N_robot_types = cfile_read_int(fp);
174         robot_info_read_n(Robot_info, N_robot_types, fp);
175
176         N_robot_joints = cfile_read_int(fp);
177         jointpos_read_n(Robot_joints, N_robot_joints, fp);
178
179         N_weapon_types = cfile_read_int(fp);
180         weapon_info_read_n(Weapon_info, N_weapon_types, fp, Piggy_hamfile_version);
181
182         N_powerup_types = cfile_read_int(fp);
183         powerup_type_info_read_n(Powerup_info, N_powerup_types, fp);
184
185         N_polygon_models = cfile_read_int(fp);
186         polymodel_read_n(Polygon_models, N_polygon_models, fp);
187
188         for (i=0; i<N_polygon_models; i++ )
189                 polygon_model_data_read(&Polygon_models[i], fp);
190
191         for (i = 0; i < N_polygon_models; i++)
192                 Dying_modelnums[i] = cfile_read_int(fp);
193         for (i = 0; i < N_polygon_models; i++)
194                 Dead_modelnums[i] = cfile_read_int(fp);
195
196         t = cfile_read_int(fp);
197         bitmap_index_read_n(Gauges, t, fp);
198         bitmap_index_read_n(Gauges_hires, t, fp);
199
200         N_ObjBitmaps = cfile_read_int(fp);
201         bitmap_index_read_n(ObjBitmaps, N_ObjBitmaps, fp);
202         for (i = 0; i < N_ObjBitmaps; i++)
203                 ObjBitmapPtrs[i] = cfile_read_short(fp);
204
205         player_ship_read(&only_player_ship, fp);
206
207         Num_cockpits = cfile_read_int(fp);
208         bitmap_index_read_n(cockpit_bitmap, Num_cockpits, fp);
209
210 //@@    cfread( &Num_total_object_types, sizeof(int), 1, fp );
211 //@@    cfread( ObjType, sizeof(byte), Num_total_object_types, fp );
212 //@@    cfread( ObjId, sizeof(byte), Num_total_object_types, fp );
213 //@@    cfread( ObjStrength, sizeof(fix), Num_total_object_types, fp );
214
215         First_multi_bitmap_num = cfile_read_int(fp);
216
217         Num_reactors = cfile_read_int(fp);
218         reactor_read_n(Reactors, Num_reactors, fp);
219
220         Marker_model_num = cfile_read_int(fp);
221
222         //@@cfread( &N_controlcen_guns, sizeof(int), 1, fp );
223         //@@cfread( controlcen_gun_points, sizeof(vms_vector), N_controlcen_guns, fp );
224         //@@cfread( controlcen_gun_dirs, sizeof(vms_vector), N_controlcen_guns, fp );
225
226         if (Piggy_hamfile_version < 3) {
227                 exit_modelnum = cfile_read_int(fp);
228                 destroyed_exit_modelnum = cfile_read_int(fp);
229         }
230         else
231                 exit_modelnum = destroyed_exit_modelnum = N_polygon_models;
232 }
233
234 // the following is old code for reading descent 1 textures.
235 #if 0
236
237 #define D1_MAX_TEXTURES 800
238 #define D1_MAX_SOUNDS 250
239 #define D1_MAX_VCLIPS 70
240 #define D1_MAX_EFFECTS 60
241 #define D1_MAX_WALL_ANIMS 30
242 #define D1_MAX_ROBOT_TYPES 30
243 #define D1_MAX_ROBOT_JOINTS 600
244 #define D1_MAX_WEAPON_TYPES 30
245 #define D1_MAX_POWERUP_TYPES 29
246 #define D1_MAX_GAUGE_BMS 80
247 #define D1_MAX_OBJ_BITMAPS 210
248 #define D1_MAX_COCKPIT_BITMAPS 4
249 #define D1_MAX_OBJTYPE 100
250 #define D1_MAX_POLYGON_MODELS 85
251
252 #define D1_TMAP_INFO_SIZE 26
253 #define D1_VCLIP_SIZE 66
254 #define D1_ROBOT_INFO_SIZE 486
255 #define D1_WEAPON_INFO_SIZE 115
256
257 #define D1_LAST_STATIC_TMAP_NUM 324
258
259 // store the Textures[] array as read from the descent 2 pig.
260 short *d2_Textures_backup = NULL;
261
262 void undo_bm_read_all_d1() {
263         if (d2_Textures_backup) {
264                 int i;
265                 for (i = 0; i < D1_LAST_STATIC_TMAP_NUM; i++)
266                         Textures[i].index = d2_Textures_backup[i];
267                 d_free(d2_Textures_backup);
268                 d2_Textures_backup = NULL;
269         }
270 }
271
272 /*
273  * used by piggy_d1_init to read in descent 1 pigfile
274  */
275 void bm_read_all_d1(CFILE * fp)
276 {
277         int i;
278
279         atexit(undo_bm_read_all_d1);
280
281         /*NumTextures = */ cfile_read_int(fp);
282         //bitmap_index_read_n(Textures, D1_MAX_TEXTURES, fp );
283         //for (i = 0; i < D1_MAX_TEXTURES; i++)
284         //      Textures[i].index = cfile_read_short(fp) + 600;  
285         //cfseek(fp, D1_MAX_TEXTURES * sizeof(short), SEEK_CUR);
286         MALLOC(d2_Textures_backup, short, D1_LAST_STATIC_TMAP_NUM);
287         for (i = 0; i < D1_LAST_STATIC_TMAP_NUM; i++) {
288                 d2_Textures_backup[i] = Textures[i].index;
289                 Textures[i].index = cfile_read_short(fp) + 521;
290         }
291         cfseek(fp, (D1_MAX_TEXTURES - D1_LAST_STATIC_TMAP_NUM) * sizeof(short), SEEK_CUR);
292
293         //tmap_info_read_n_d1(TmapInfo, D1_MAX_TEXTURES, fp);
294         cfseek(fp, D1_MAX_TEXTURES * D1_TMAP_INFO_SIZE, SEEK_CUR);
295
296         /*
297         cfread( Sounds, sizeof(ubyte), D1_MAX_SOUNDS, fp );
298         cfread( AltSounds, sizeof(ubyte), D1_MAX_SOUNDS, fp );
299         */cfseek(fp, D1_MAX_SOUNDS * 2, SEEK_CUR);
300
301         /*Num_vclips = */ cfile_read_int(fp);
302         //vclip_read_n(Vclip, D1_MAX_VCLIPS, fp);
303         cfseek(fp, D1_MAX_VCLIPS * D1_VCLIP_SIZE, SEEK_CUR);
304
305         /*
306         Num_effects = cfile_read_int(fp);
307         eclip_read_n(Effects, D1_MAX_EFFECTS, fp);
308
309         Num_wall_anims = cfile_read_int(fp);
310         wclip_read_n_d1(WallAnims, D1_MAX_WALL_ANIMS, fp);
311         */
312
313         /*
314         N_robot_types = cfile_read_int(fp);
315         //robot_info_read_n(Robot_info, D1_MAX_ROBOT_TYPES, fp);
316         cfseek(fp, D1_MAX_ROBOT_TYPES * D1_ROBOT_INFO_SIZE, SEEK_CUR);
317
318         N_robot_joints = cfile_read_int(fp);
319         jointpos_read_n(Robot_joints, D1_MAX_ROBOT_JOINTS, fp);
320
321         N_weapon_types = cfile_read_int(fp);
322         //weapon_info_read_n(Weapon_info, D1_MAX_WEAPON_TYPES, fp, Piggy_hamfile_version);
323         cfseek(fp, D1_MAX_WEAPON_TYPES * D1_WEAPON_INFO_SIZE, SEEK_CUR);
324
325         N_powerup_types = cfile_read_int(fp);
326         powerup_type_info_read_n(Powerup_info, D1_MAX_POWERUP_TYPES, fp);
327         */
328
329         /* in the following code are bugs, solved by hack
330         N_polygon_models = cfile_read_int(fp);
331         polymodel_read_n(Polygon_models, N_polygon_models, fp);
332         for (i=0; i<N_polygon_models; i++ )
333                 polygon_model_data_read(&Polygon_models[i], fp);
334         */cfseek(fp, 521490-160, SEEK_SET); // OK, I admit, this is a dirty hack
335         //bitmap_index_read_n(Gauges, D1_MAX_GAUGE_BMS, fp);
336         cfseek(fp, D1_MAX_GAUGE_BMS * sizeof(bitmap_index), SEEK_CUR);
337
338         /*
339         for (i = 0; i < D1_MAX_POLYGON_MODELS; i++)
340                 Dying_modelnums[i] = cfile_read_int(fp);
341         for (i = 0; i < D1_MAX_POLYGON_MODELS; i++)
342                 Dead_modelnums[i] = cfile_read_int(fp);
343         */ cfseek(fp, D1_MAX_POLYGON_MODELS * 8, SEEK_CUR);
344
345         //bitmap_index_read_n(ObjBitmaps, D1_MAX_OBJ_BITMAPS, fp);
346         cfseek(fp, D1_MAX_OBJ_BITMAPS * sizeof(bitmap_index), SEEK_CUR);
347         for (i = 0; i < D1_MAX_OBJ_BITMAPS; i++)
348                 cfseek(fp, 2, SEEK_CUR);//ObjBitmapPtrs[i] = cfile_read_short(fp);
349
350         //player_ship_read(&only_player_ship, fp);
351         cfseek(fp, sizeof(player_ship), SEEK_CUR);
352
353         /*Num_cockpits = */ cfile_read_int(fp);
354         //bitmap_index_read_n(cockpit_bitmap, D1_MAX_COCKPIT_BITMAPS, fp);
355         cfseek(fp, D1_MAX_COCKPIT_BITMAPS * sizeof(bitmap_index), SEEK_CUR);
356
357         /*
358         cfread( Sounds, sizeof(ubyte), D1_MAX_SOUNDS, fp );
359         cfread( AltSounds, sizeof(ubyte), D1_MAX_SOUNDS, fp );
360         */cfseek(fp, D1_MAX_SOUNDS * 2, SEEK_CUR);
361
362         /*Num_total_object_types = */ cfile_read_int( fp );
363         /*
364         cfread( ObjType, sizeof(byte), D1_MAX_OBJTYPE, fp );
365         cfread( ObjId, sizeof(byte), D1_MAX_OBJTYPE, fp );
366         for (i=0; i<D1_MAX_OBJTYPE; i++ )
367                 ObjStrength[i] = cfile_read_int( fp );
368         */ cfseek(fp, D1_MAX_OBJTYPE * 6, SEEK_CUR);
369
370         /*First_multi_bitmap_num =*/ cfile_read_int(fp);
371         /*Reactors[0].n_guns = */ cfile_read_int( fp );
372         /*for (i=0; i<4; i++)
373                 cfile_read_vector(&(Reactors[0].gun_points[i]), fp);
374         for (i=0; i<4; i++)
375                 cfile_read_vector(&(Reactors[0].gun_dirs[i]), fp);
376         */cfseek(fp, 8 * 12, SEEK_CUR);
377
378         /*exit_modelnum = */ cfile_read_int(fp);
379         /*destroyed_exit_modelnum = */ cfile_read_int(fp);
380 }
381
382 #endif // if 0, old code for reading descent 1 textures
383
384 //these values are the number of each item in the release of d2
385 //extra items added after the release get written in an additional hamfile
386 #define N_D2_ROBOT_TYPES                66
387 #define N_D2_ROBOT_JOINTS               1145
388 #define N_D2_POLYGON_MODELS     166
389 #define N_D2_OBJBITMAPS                 422
390 #define N_D2_OBJBITMAPPTRS              502
391 #define N_D2_WEAPON_TYPES               62
392
393 extern int Num_bitmap_files;
394 int extra_bitmap_num = 0;
395
396 void bm_free_extra_objbitmaps()
397 {
398         int i;
399
400         if (!extra_bitmap_num)
401                 extra_bitmap_num = Num_bitmap_files;
402
403         for (i = Num_bitmap_files; i < extra_bitmap_num; i++)
404         {
405                 N_ObjBitmaps--;
406                 d_free(GameBitmaps[i].bm_data);
407         }
408         extra_bitmap_num = Num_bitmap_files;
409 }
410
411 void bm_free_extra_models()
412 {
413         while (N_polygon_models > N_D2_POLYGON_MODELS)
414                 free_model(&Polygon_models[--N_polygon_models]);
415         while (N_polygon_models > exit_modelnum)
416                 free_model(&Polygon_models[--N_polygon_models]);
417 }
418
419 //type==1 means 1.1, type==2 means 1.2 (with weapons)
420 void bm_read_extra_robots(char *fname,int type)
421 {
422         CFILE *fp;
423         int t,i;
424         int version;
425
426         fp = cfopen(fname,"rb");
427
428         if (type == 2) {
429                 int sig;
430
431                 sig = cfile_read_int(fp);
432                 if (sig != MAKE_SIG('X','H','A','M'))
433                         return;
434                 version = cfile_read_int(fp);
435         }
436         else
437                 version = 0;
438
439         bm_free_extra_models();
440         bm_free_extra_objbitmaps();
441
442         //read extra weapons
443
444         t = cfile_read_int(fp);
445         N_weapon_types = N_D2_WEAPON_TYPES+t;
446         if (N_weapon_types >= MAX_WEAPON_TYPES)
447                 Error("Too many weapons (%d) in <%s>.  Max is %d.",t,fname,MAX_WEAPON_TYPES-N_D2_WEAPON_TYPES);
448         weapon_info_read_n(&Weapon_info[N_D2_WEAPON_TYPES], t, fp, 3);
449
450         //now read robot info
451
452         t = cfile_read_int(fp);
453         N_robot_types = N_D2_ROBOT_TYPES+t;
454         if (N_robot_types >= MAX_ROBOT_TYPES)
455                 Error("Too many robots (%d) in <%s>.  Max is %d.",t,fname,MAX_ROBOT_TYPES-N_D2_ROBOT_TYPES);
456         robot_info_read_n(&Robot_info[N_D2_ROBOT_TYPES], t, fp);
457
458         t = cfile_read_int(fp);
459         N_robot_joints = N_D2_ROBOT_JOINTS+t;
460         if (N_robot_joints >= MAX_ROBOT_JOINTS)
461                 Error("Too many robot joints (%d) in <%s>.  Max is %d.",t,fname,MAX_ROBOT_JOINTS-N_D2_ROBOT_JOINTS);
462         jointpos_read_n(&Robot_joints[N_D2_ROBOT_JOINTS], t, fp);
463
464         t = cfile_read_int(fp);
465         N_polygon_models = N_D2_POLYGON_MODELS+t;
466         if (N_polygon_models >= MAX_POLYGON_MODELS)
467                 Error("Too many polygon models (%d) in <%s>.  Max is %d.",t,fname,MAX_POLYGON_MODELS-N_D2_POLYGON_MODELS);
468         polymodel_read_n(&Polygon_models[N_D2_POLYGON_MODELS], t, fp);
469
470         for (i=N_D2_POLYGON_MODELS; i<N_polygon_models; i++ )
471                 polygon_model_data_read(&Polygon_models[i], fp);
472
473         for (i = N_D2_POLYGON_MODELS; i < N_polygon_models; i++)
474                 Dying_modelnums[i] = cfile_read_int(fp);
475         for (i = N_D2_POLYGON_MODELS; i < N_polygon_models; i++)
476                 Dead_modelnums[i] = cfile_read_int(fp);
477
478         t = cfile_read_int(fp);
479         if (N_D2_OBJBITMAPS+t >= MAX_OBJ_BITMAPS)
480                 Error("Too many object bitmaps (%d) in <%s>.  Max is %d.",t,fname,MAX_OBJ_BITMAPS-N_D2_OBJBITMAPS);
481         bitmap_index_read_n(&ObjBitmaps[N_D2_OBJBITMAPS], t, fp);
482
483         t = cfile_read_int(fp);
484         if (N_D2_OBJBITMAPPTRS+t >= MAX_OBJ_BITMAPS)
485                 Error("Too many object bitmap pointers (%d) in <%s>.  Max is %d.",t,fname,MAX_OBJ_BITMAPS-N_D2_OBJBITMAPPTRS);
486         for (i = N_D2_OBJBITMAPPTRS; i < (N_D2_OBJBITMAPPTRS + t); i++)
487                 ObjBitmapPtrs[i] = cfile_read_short(fp);
488
489         cfclose(fp);
490 }
491
492 int Robot_replacements_loaded = 0;
493
494 void load_robot_replacements(char *level_name)
495 {
496         CFILE *fp;
497         int t,i,j;
498         char ifile_name[FILENAME_LEN];
499
500         change_filename_extension(ifile_name, level_name, ".HXM" );
501
502         fp = cfopen(ifile_name,"rb");
503
504         if (!fp)                //no robot replacement file
505                 return;
506
507         t = cfile_read_int(fp);                 //read id "HXM!"
508         if (t!= 0x21584d48)
509                 Error("ID of HXM! file incorrect");
510
511         t = cfile_read_int(fp);                 //read version
512         if (t<1)
513                 Error("HXM! version too old (%d)",t);
514
515         t = cfile_read_int(fp);                 //read number of robots
516         for (j=0;j<t;j++) {
517                 i = cfile_read_int(fp);         //read robot number
518                 if (i<0 || i>=N_robot_types)
519                         Error("Robots number (%d) out of range in (%s).  Range = [0..%d].",i,level_name,N_robot_types-1);
520                 robot_info_read_n(&Robot_info[i], 1, fp);
521         }
522
523         t = cfile_read_int(fp);                 //read number of joints
524         for (j=0;j<t;j++) {
525                 i = cfile_read_int(fp);         //read joint number
526                 if (i<0 || i>=N_robot_joints)
527                         Error("Robots joint (%d) out of range in (%s).  Range = [0..%d].",i,level_name,N_robot_joints-1);
528                 jointpos_read_n(&Robot_joints[i], 1, fp);
529         }
530
531         t = cfile_read_int(fp);                 //read number of polygon models
532         for (j=0;j<t;j++)
533         {
534                 i = cfile_read_int(fp);         //read model number
535                 if (i<0 || i>=N_polygon_models)
536                         Error("Polygon model (%d) out of range in (%s).  Range = [0..%d].",i,level_name,N_polygon_models-1);
537
538                 free_model(&Polygon_models[i]);
539                 polymodel_read(&Polygon_models[i], fp);
540                 polygon_model_data_read(&Polygon_models[i], fp);
541
542                 Dying_modelnums[i] = cfile_read_int(fp);
543                 Dead_modelnums[i] = cfile_read_int(fp);
544         }
545
546         t = cfile_read_int(fp);                 //read number of objbitmaps
547         for (j=0;j<t;j++) {
548                 i = cfile_read_int(fp);         //read objbitmap number
549                 if (i<0 || i>=MAX_OBJ_BITMAPS)
550                         Error("Object bitmap number (%d) out of range in (%s).  Range = [0..%d].",i,level_name,MAX_OBJ_BITMAPS-1);
551                 bitmap_index_read(&ObjBitmaps[i], fp);
552         }
553
554         t = cfile_read_int(fp);                 //read number of objbitmapptrs
555         for (j=0;j<t;j++) {
556                 i = cfile_read_int(fp);         //read objbitmapptr number
557                 if (i<0 || i>=MAX_OBJ_BITMAPS)
558                         Error("Object bitmap pointer (%d) out of range in (%s).  Range = [0..%d].",i,level_name,MAX_OBJ_BITMAPS-1);
559                 ObjBitmapPtrs[i] = cfile_read_short(fp);
560         }
561
562         cfclose(fp);
563         Robot_replacements_loaded = 1;
564 }
565
566
567 /*
568  * Routines for loading exit models
569  *
570  * Used by d1 levels (including some add-ons), and by d2 shareware.
571  * Could potentially be used by d2 add-on levels, but only if they
572  * don't use "extra" robots...
573  */
574
575 // formerly exitmodel_bm_load_sub
576 bitmap_index read_extra_bitmap_iff( char * filename )
577 {
578         bitmap_index bitmap_num;
579         grs_bitmap * new = &GameBitmaps[extra_bitmap_num];
580         ubyte newpal[256*3];
581         int iff_error;          //reference parm to avoid warning message
582
583         bitmap_num.index = 0;
584
585         //MALLOC( new, grs_bitmap, 1 );
586         iff_error = iff_read_bitmap(filename,new,BM_LINEAR,newpal);
587         new->bm_handle=0;
588         if (iff_error != IFF_NO_ERROR)          {
589                 con_printf(CON_DEBUG, "Error loading exit model bitmap <%s> - IFF error: %s\n", filename, iff_errormsg(iff_error));
590                 return bitmap_num;
591         }
592
593         if ( iff_has_transparency )
594                 gr_remap_bitmap_good( new, newpal, iff_transparent_color, 254 );
595         else
596                 gr_remap_bitmap_good( new, newpal, -1, 254 );
597
598         new->avg_color = 0;     //compute_average_pixel(new);
599
600         bitmap_num.index = extra_bitmap_num;
601
602         GameBitmaps[extra_bitmap_num++] = *new;
603
604         //d_free( new );
605         return bitmap_num;
606 }
607
608 // formerly load_exit_model_bitmap
609 grs_bitmap *bm_load_extra_objbitmap(char *name)
610 {
611         Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
612
613         {
614                 ObjBitmaps[N_ObjBitmaps] = read_extra_bitmap_iff(name);
615
616                 if (ObjBitmaps[N_ObjBitmaps].index == 0)
617                 {
618                         char *name2 = d_strdup(name);
619                         *strrchr(name2, '.') = '\0';
620                         ObjBitmaps[N_ObjBitmaps] = read_extra_bitmap_d1_pig(name2);
621                         d_free(name2);
622                 }
623                 if (ObjBitmaps[N_ObjBitmaps].index == 0)
624                         return NULL;
625
626                 if (GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_w!=64 || GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_h!=64)
627                         Error("Bitmap <%s> is not 64x64",name);
628                 ObjBitmapPtrs[N_ObjBitmaps] = N_ObjBitmaps;
629                 N_ObjBitmaps++;
630                 Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
631                 return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index];
632         }
633 }
634
635 #ifdef OGL
636 void ogl_cache_polymodel_textures(int model_num);
637 #endif
638
639 int load_exit_models()
640 {
641         CFILE *exit_hamfile;
642         int start_num;
643
644         bm_free_extra_models();
645         bm_free_extra_objbitmaps();
646
647         start_num = N_ObjBitmaps;
648         if (!bm_load_extra_objbitmap("steel1.bbm") ||
649                 !bm_load_extra_objbitmap("rbot061.bbm") ||
650                 !bm_load_extra_objbitmap("rbot062.bbm") ||
651                 !bm_load_extra_objbitmap("steel1.bbm") ||
652                 !bm_load_extra_objbitmap("rbot061.bbm") ||
653                 !bm_load_extra_objbitmap("rbot063.bbm"))
654         {
655                 con_printf(CON_NORMAL, "Can't load exit models!\n");
656                 return 0;
657         }
658
659         exit_hamfile = cfopen("exit.ham","rb");
660         if (exit_hamfile) {
661                 exit_modelnum = N_polygon_models++;
662                 destroyed_exit_modelnum = N_polygon_models++;
663                 polymodel_read(&Polygon_models[exit_modelnum], exit_hamfile);
664                 polymodel_read(&Polygon_models[destroyed_exit_modelnum], exit_hamfile);
665                 Polygon_models[exit_modelnum].first_texture = start_num;
666                 Polygon_models[destroyed_exit_modelnum].first_texture = start_num+3;
667
668                 polygon_model_data_read(&Polygon_models[exit_modelnum], exit_hamfile);
669
670                 polygon_model_data_read(&Polygon_models[destroyed_exit_modelnum], exit_hamfile);
671
672                 cfclose(exit_hamfile);
673
674         } else if (cfexist("exit01.pof") && cfexist("exit01d.pof")) {
675
676                 exit_modelnum = load_polygon_model("exit01.pof", 3, start_num, NULL);
677                 destroyed_exit_modelnum = load_polygon_model("exit01d.pof", 3, start_num + 3, NULL);
678
679 #ifdef OGL
680                 ogl_cache_polymodel_textures(exit_modelnum);
681                 ogl_cache_polymodel_textures(destroyed_exit_modelnum);
682 #endif
683         }
684         else if (cfexist(D1_PIGFILE))
685         {
686                 int offset, offset2;
687                 int hamsize;
688
689                 exit_hamfile = cfopen(D1_PIGFILE, "rb");
690                 hamsize = cfilelength(exit_hamfile);
691                 switch (hamsize) { //total hack for loading models
692                 case D1_PIGSIZE:
693                         offset = 91848;     /* and 92582  */
694                         offset2 = 383390;   /* and 394022 */
695                         break;
696                 default:
697                 case D1_SHARE_BIG_PIGSIZE:
698                 case D1_SHARE_10_PIGSIZE:
699                 case D1_SHARE_PIGSIZE:
700                 case D1_10_BIG_PIGSIZE:
701                 case D1_10_PIGSIZE:
702                         Int3();             /* exit models should be in .pofs */
703                 case D1_OEM_PIGSIZE:
704                 case D1_MAC_PIGSIZE:
705                 case D1_MAC_SHARE_PIGSIZE:
706                         con_printf(CON_NORMAL, "Can't load exit models!\n");
707                         return 0;
708                 }
709                 cfseek(exit_hamfile, offset, SEEK_SET);
710                 exit_modelnum = N_polygon_models++;
711                 destroyed_exit_modelnum = N_polygon_models++;
712                 polymodel_read(&Polygon_models[exit_modelnum], exit_hamfile);
713                 polymodel_read(&Polygon_models[destroyed_exit_modelnum], exit_hamfile);
714                 Polygon_models[exit_modelnum].first_texture = start_num;
715                 Polygon_models[destroyed_exit_modelnum].first_texture = start_num+3;
716
717                 cfseek(exit_hamfile, offset2, SEEK_SET);
718                 polygon_model_data_read(&Polygon_models[exit_modelnum], exit_hamfile);
719                 polygon_model_data_read(&Polygon_models[destroyed_exit_modelnum], exit_hamfile);
720
721                 cfclose(exit_hamfile);
722         } else {
723                 con_printf(CON_NORMAL, "Can't load exit models!\n");
724                 return 0;
725         }
726
727         atexit(bm_free_extra_objbitmaps);
728
729         return 1;
730 }