]> icculus.org git repositories - btb/d2x.git/blob - main/gamemine.c
merged endlevel stuff to non-shareware, allow movies/endlevel for alternate missions
[btb/d2x.git] / main / gamemine.c
1 /* $Id: */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 #ifdef HAVE_CONFIG_H
16 #include <conf.h>
17 #endif
18
19 #ifdef RCS
20 static char rcsid[] = "$Id: gamemine.c,v 1.12 2002-08-06 05:06:38 btb Exp $";
21 #endif
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include <string.h>
27
28 #include "pstypes.h"
29 #include "mono.h"
30
31 #include "inferno.h"
32 #include "segment.h"
33 #include "textures.h"
34 #include "wall.h"
35 #include "object.h"
36 #include "gamemine.h"
37 #include "error.h"
38 #include "gameseg.h"
39 #include "switch.h"
40
41 #include "game.h"
42 #include "newmenu.h"
43
44 #ifdef EDITOR
45 #include "editor/editor.h"
46 #endif
47
48 #include "cfile.h"
49 #include "fuelcen.h"
50
51 #include "hash.h"
52 #include "key.h"
53 #include "piggy.h"
54
55 #include "byteswap.h"
56 #include "gamesave.h"
57
58 #define REMOVE_EXT(s)  (*(strchr( (s), '.' ))='\0')
59
60 fix     Level_shake_frequency = 0, Level_shake_duration = 0;
61 int     Secret_return_segment = 0;
62 vms_matrix      Secret_return_orient;
63
64 struct mtfi mine_top_fileinfo;    // Should be same as first two fields below...
65 struct mfi mine_fileinfo;
66 struct mh mine_header;
67 struct me mine_editor;
68
69 typedef struct v16_segment {
70         #ifdef  EDITOR
71         short           segnum;                                                         // segment number, not sure what it means
72         #endif
73         side            sides[MAX_SIDES_PER_SEGMENT];   // 6 sides
74         short           children[MAX_SIDES_PER_SEGMENT];        // indices of 6 children segments, front, left, top, right, bottom, back
75         short           verts[MAX_VERTICES_PER_SEGMENT];        // vertex ids of 4 front and 4 back vertices
76         #ifdef  EDITOR
77         short           group;                                                          // group number to which the segment belongs.
78         #endif
79         short           objects;                                                                // pointer to objects in this segment
80         ubyte           special;                                                                // what type of center this is 
81         byte            matcen_num;                                                     //      which center segment is associated with.
82         short           value;
83         fix             static_light;                                           //average static light in segment
84         #ifndef EDITOR
85         short           pad;                    //make structure longword aligned
86         #endif
87 } v16_segment;
88
89 struct mfi_v19 {
90         ushort  fileinfo_signature;
91         ushort  fileinfo_version;
92         int             fileinfo_sizeof;
93         int             header_offset;          // Stuff common to game & editor
94         int             header_size;
95         int             editor_offset;   // Editor specific stuff
96         int             editor_size;
97         int             segment_offset;
98         int             segment_howmany;
99         int             segment_sizeof;
100         int             newseg_verts_offset;
101         int             newseg_verts_howmany;
102         int             newseg_verts_sizeof;
103         int             group_offset;
104         int             group_howmany;
105         int             group_sizeof;
106         int             vertex_offset;
107         int             vertex_howmany;
108         int             vertex_sizeof;
109         int             texture_offset;
110         int             texture_howmany;
111         int             texture_sizeof;
112         int             walls_offset;
113         int             walls_howmany;
114         int             walls_sizeof;
115         int             triggers_offset;
116         int             triggers_howmany;
117         int             triggers_sizeof;
118         int             links_offset;
119         int             links_howmany;
120         int             links_sizeof;
121         int             object_offset;                          // Object info
122         int             object_howmany;         
123         int             object_sizeof;  
124         int             unused_offset;                  //was: doors_offset
125         int             unused_howmamy;         //was: doors_howmany
126         int             unused_sizeof;                  //was: doors_sizeof
127         short           level_shake_frequency, level_shake_duration;    //      Shakes every level_shake_frequency seconds
128                                                                                                                                                         // for level_shake_duration seconds (on average, random).  In 16ths second.
129         int             secret_return_segment;
130         vms_matrix      secret_return_orient;
131
132         int             dl_indices_offset;
133         int             dl_indices_howmany;
134         int             dl_indices_sizeof;
135
136         int             delta_light_offset;
137         int             delta_light_howmany;
138         int             delta_light_sizeof;
139
140 };
141
142 int CreateDefaultNewSegment();
143
144 /* converts descent 1 texture numbers to descent 2 texture numbers
145  * textures whose names don't match between versions have extra spaces around "return"
146  */
147 short convert_d1_tmap_num(short d1_tmap_num) {
148         switch (d1_tmap_num) {
149         case   0:  return  43; // grey
150         case   1: return 0;
151         case   2:  return  43; // grey
152         case   3: return 1;
153         case   4:  return  43; // grey
154         case   5:  return  43; // grey
155         case   6:  return  270; // blue
156         case   7:  return  271; // yellow
157         case   8: return 2;
158         case   9:  return  62; // purple
159         case  10:  return  272; // red
160         case  11:  return  117; 
161         case  12:  return  12;
162         case  13: return 3;
163         case  14: return 4;
164         case  15: return 5;
165         case  16: return 6;
166         case  17:  return  17;
167         case  18:  return  18;
168         case  19: return 7;
169         case  20:  return  22;
170         case  21:  return  9;
171         case  22: return 8;
172         case  23: return 9;
173         case  24: return 10;
174         case  25:  return  12;
175         case  26: return 11;
176         case  27: return 12;
177         case  28:  return  11;
178         case  29: return 13;
179         case  30: return 14;
180         case  31: return 15;
181         case  32: return 16;
182         case  33: return 17;
183         case  34: return 18;
184         case  35: return 19;
185         case  36: return 20;
186         case  37: return 21;
187         case  38:  return  163;
188         case  39:  return  31;
189         case  40: return 22;
190         case  41:  return  266;
191         case  42: return 23;
192         case  43: return 24;
193         case  44:  return  136;
194         case  45: return 25;
195         case  46: return 26;
196         case  47: return 27;
197         case  48: return 28;
198         case  49:  return  43;
199         case  50:  return  131;
200         case  51: return 29;
201         case  52: return 30;
202         case  53: return 31;
203         case  54: return 32;
204         case  55:  return  165;
205         case  56: return 33;
206         case  57:  return  132;
207         case  58: return 34;
208         case  59: return 35;
209         case  60: return 36;
210         case  61: return 37;
211         case  62: return 38;
212         case  63: return 39;
213         case  64: return 40;
214         case  65: return 41;
215         case  66: return 42;
216         case  67: return 43;
217         case  68: return 44;
218         case  69: return 45;
219         case  70: return 46;
220         case  71: return 47;
221         case  72: return 48;
222         case  73: return 49;
223         case  74: return 50;
224         case  75: return 51;
225         case  76: return 52;
226         case  77: return 53;
227         case  78: return 54;
228         case  79: return 55;
229         case  80: return 56;
230         case  81: return 57;
231         case  82: return 58;
232         case  83: return 59;
233         case  84: return 60;
234         case  85: return 61;
235         case  86: return 62;
236         case  87: return 63;
237         case  88:  return  66;
238         case  89: return 64;
239         case  90: return 65;
240         case  91: return 66;
241         case  92: return 67;
242         case  93: return 68;
243         case  94: return 69;
244         case  95: return 70;
245         case  96: return 71;
246         case  97: return 72;
247         case  98: return 73;
248         case  99: return 74;
249         case 100: return 75;
250         case 101: return 76;
251         case 102: return 77;
252         case 103: return 78;
253         case 104: return 79;
254         case 105: return 80;
255         case 106: return 81;
256         case 107: return 82;
257         case 108: return 83;
258         case 109: return 84;
259         case 110: return 85;
260         case 111: return 86;
261         case 112: return 87;
262         case 113: return 88;
263         case 114: return 89;
264         case 115: return 90;
265         case 116: return 91;
266         case 117: return 92;
267         case 118: return 93;
268         case 119: return 94;
269         case 120: return 95;
270         case 121: return 96;
271         case 122: return 97;
272         case 123: return 98;
273         case 124: return 99;
274         case 125: return 100;
275         case 126: return 101;
276         case 127: return 102;
277         case 128: return 103;
278         case 129: return 104;
279         case 130: return 105;
280         case 131: return 106;
281         case 132:  return  108;
282         case 133: return 107;
283         case 134: return 108;
284         case 135: return 109;
285         case 136: return 110;
286         case 137: return 111;
287         case 138: return 112;
288         case 139: return 113;
289         case 140: return 114;
290         case 141:  return  110;
291         case 142: return 115;
292         case 143: return 116;
293         case 144: return 117;
294         case 145: return 118;
295         case 146: return 119;
296         case 147:  return  111;
297         case 148: return 120;
298         case 149: return 121;
299         case 150: return 122;
300         case 151: return 123;
301         case 152: return 124;
302         case 153: return 125;
303         case 154:  return  82;
304         case 155:  return  66;
305         case 156: return 200;
306         case 157: return 201;
307         case 158:  return  186;
308         case 159:  return  190;
309         case 160:  return  206;
310         case 161:  return  114;
311         case 162: return 202;
312         case 163: return 203;
313         case 164: return 204;
314         case 165: return 205;
315         case 166: return 206;
316         case 167:  return  206;
317         case 168:  return  206;
318         case 169:  return  206;
319         case 170:  return  206;
320         case 171:  return  227;
321         case 172: return 207;
322         case 173: return 208;
323         case 174:  return  202;
324         case 175:  return  206;
325         case 176: return 209;
326         case 177: return 210;
327         case 178: return 211;
328         case 179: return 212;
329         case 180: return 213;
330         case 181: return 214;
331         case 182: return 215;
332         case 183: return 216;
333         case 184: return 217;
334         case 185:  return  325;
335         case 186: return 218;
336         case 187: return 219;
337         case 188: return 220;
338         case 189: return 221;
339         case 190: return 222;
340         case 191: return 223;
341         case 192: return 224;
342         case 193:  return  206;
343         case 194:  return  206;
344         case 195:  return  234;
345         case 196: return 225;
346         case 197: return 226;
347         case 198:  return  225;
348         case 199:  return  206;
349         case 200:  return  206;
350         case 201: return 227;
351         case 202:  return  206;
352         case 203: return 228;
353         case 204: return 229;
354         case 205: return 230;
355         case 206: return 231;
356         case 207: return 232;
357         case 208: return 233;
358         case 209: return 234;
359         case 210:  return  234;
360         case 211:  return  206;
361         case 212: return 235;
362         case 213: return 236;
363         case 214: return 237;
364         case 215: return 238;
365         case 216: return 239;
366         case 217: return 240;
367         case 218: return 241;
368         case 219: return 242;
369         case 220:  return  242;
370         case 221: return 243;
371         case 222: return 244;
372         case 223: return  313;
373         case 224: return 245;
374         case 225: return 246;
375         case 226: return 247;
376         case 227:  return  179;
377         case 228: return 248;
378         case 229:  return  15;
379         case 230:  return  15;
380         case 231: return 249;
381         case 232: return 250;
382         case 233: return 251;
383         case 234: return 252;
384         case 235: return 253;
385         case 236: return 254;
386         case 237: return 255;
387         case 238: return 256;
388         case 239: return 257;
389         case 240:  return  6;
390         case 241:  return  130;
391         case 242:  return  78;
392         case 243:  return  33;
393         case 244: return 258;
394         case 245: return 259;
395         case 246:  return  321;
396         case 247: return 260;
397         case 248: return 261;
398         case 249: return 262;
399         case 250: return  340; // white entrance
400         case 251: return  412; // red entrance
401         case 252: return  410; // blue entrance
402         case 253: return  411; // yellow entrance
403         case 254: return 263;
404         case 255: return 264;
405         case 256: return 265;
406         case 257:  return  246;
407         case 258:  return  246;
408         case 259:  return  246;
409         case 260:  return  246;
410         case 261: return 273;
411         case 262: return 274;
412         case 263:  return  281;
413         case 264: return 275;
414         case 265: return 276;
415         case 266:  return  279;
416         case 267: return 277;
417         case 268: return 278;
418         case 269: return 279;
419         case 270: return 280;
420         case 271: return 281;
421         case 272: return 282;
422         case 273: return 283;
423         case 274: return 284;
424         case 275: return 285;
425         case 276: return 286;
426         case 277: return 287;
427         case 278: return 288;
428         case 279: return 289;
429         case 280: return 290;
430         case 281: return 291;
431         case 282: return 293;
432         case 283:  return  295;
433         case 284: return 295;
434         case 285: return 296;
435         case 286: return 298;
436         case 287: return 300;
437         case 288: return 301;
438         case 289: return 302;
439         case 290: return 303;
440         case 291: return 304;
441         case 292: return 305;
442         case 293: return 306;
443         case 294: return 307;
444         case 295: return 308;
445         case 296: return 309;
446         case 297: return 310;
447         case 298:  return  364;
448         case 299: return 311;
449         case 300: return 312;
450         case 301: return 313;
451         case 302: return 314;
452         case 303: return 315;
453         case 304: return 316;
454         case 305: return 317;
455         case 306: return 318;
456         case 307: return 319;
457         case 308: return 320;
458         case 309: return 321;
459         case 310: return 322;
460         case 311: return 323;
461         case 312: return 324;
462         case 313: return 325;
463         case 314: return 326;
464         case 315:  return  361; // broken producer
465         case 316: return 327;
466         case 317: return 328;
467         case 318: return 329;
468         case 319: return 330;
469         case 320: return 331;
470         case 321: return 332;
471         case 322: return 333;
472         case 323: return 334;
473         case 324: return 335;
474         case 325: return 336;
475         case 326: return 337;
476         case 327: return 352;
477         case 328: return 353;
478         case 329: return 354;
479         case 330:  return  366;
480         case 331: return 373;
481         case 332: return 344;
482         case 333: return   409; // lava
483         case 334: return 356;
484         case 335: return 357;
485         case 336: return 358;
486         case 337: return 359;
487         case 338: return 360;
488         case 339: return 361;
489         case 340: return 362;
490         case 341: return 364;
491         case 342: return 363;
492         case 343: return 366;
493         case 344: return 365;
494         case 345: return 368;
495         //case 346:  return  ;
496         case 347: return 370;
497         case 348: return 367;
498         case 349: return 395;
499         case 350: return 369;
500         case 351: return 429;
501         case 352: return 387;
502         case 353: return 371;
503         case 354: return 425;
504         case 355:  return  408;
505         case 356: return 378; // lava02
506         case 357: return 384;
507         case 358: return 385;
508         case 359: return 386;
509         case 360: return 386;
510         case 361: return 387;
511         case 362:  return  388;
512         case 363: return 388;
513         case 364: return 391;
514         case 365: return 392;
515         case 366: return 393;
516         case 367: return 394;
517         case 368: return 395;
518         case 369: return 396;
519         case 370:  return  392;
520         default: return d1_tmap_num;
521         }
522 }
523
524 #ifdef EDITOR
525
526 static char old_tmap_list[MAX_TEXTURES][FILENAME_LEN];
527 short tmap_xlate_table[MAX_TEXTURES];
528 static short tmap_times_used[MAX_TEXTURES];
529
530 // -----------------------------------------------------------------------------
531 //loads from an already-open file
532 // returns 0=everything ok, 1=old version, -1=error
533 int load_mine_data(CFILE *LoadFile)
534 {
535         int   i, j,oldsizeadjust;
536         short tmap_xlate;
537         int     translate;
538         char    *temptr;
539         int     mine_start = cftell(LoadFile);
540
541         oldsizeadjust=(sizeof(int)*2)+sizeof (vms_matrix);
542         fuelcen_reset();
543
544         for (i=0; i<MAX_TEXTURES; i++ )
545                 tmap_times_used[i] = 0;
546
547         #ifdef EDITOR
548         // Create a new mine to initialize things.
549         //texpage_goto_first();
550         create_new_mine();
551         #endif
552
553         //===================== READ FILE INFO ========================
554
555         // These are the default values... version and fileinfo_sizeof
556         // don't have defaults.
557         mine_fileinfo.header_offset     =   -1;
558         mine_fileinfo.header_size       =   sizeof(mine_header);
559         mine_fileinfo.editor_offset     =   -1;
560         mine_fileinfo.editor_size       =   sizeof(mine_editor);
561         mine_fileinfo.vertex_offset     =   -1;
562         mine_fileinfo.vertex_howmany    =   0;
563         mine_fileinfo.vertex_sizeof     =   sizeof(vms_vector);
564         mine_fileinfo.segment_offset    =   -1;
565         mine_fileinfo.segment_howmany   =   0;
566         mine_fileinfo.segment_sizeof    =   sizeof(segment);
567         mine_fileinfo.newseg_verts_offset     =   -1;
568         mine_fileinfo.newseg_verts_howmany    =   0;
569         mine_fileinfo.newseg_verts_sizeof     =   sizeof(vms_vector);
570         mine_fileinfo.group_offset                =     -1;
571         mine_fileinfo.group_howmany       =     0;
572         mine_fileinfo.group_sizeof                =     sizeof(group);
573         mine_fileinfo.texture_offset    =   -1;
574         mine_fileinfo.texture_howmany   =   0;
575         mine_fileinfo.texture_sizeof    =   FILENAME_LEN;  // num characters in a name
576         mine_fileinfo.walls_offset                =     -1;
577         mine_fileinfo.walls_howmany       =     0;
578         mine_fileinfo.walls_sizeof                =     sizeof(wall);  
579         mine_fileinfo.triggers_offset     =     -1;
580         mine_fileinfo.triggers_howmany  =       0;
581         mine_fileinfo.triggers_sizeof     =     sizeof(trigger);  
582         mine_fileinfo.object_offset             =       -1;
583         mine_fileinfo.object_howmany            =       1;
584         mine_fileinfo.object_sizeof             =       sizeof(object);  
585
586         mine_fileinfo.level_shake_frequency             =       0;
587         mine_fileinfo.level_shake_duration              =       0;
588
589         //      Delta light stuff for blowing out light sources.
590 //      if (mine_top_fileinfo.fileinfo_version >= 19) {
591                 mine_fileinfo.dl_indices_offset         =       -1;
592                 mine_fileinfo.dl_indices_howmany                =       0;
593                 mine_fileinfo.dl_indices_sizeof         =       sizeof(dl_index);  
594
595                 mine_fileinfo.delta_light_offset                =       -1;
596                 mine_fileinfo.delta_light_howmany               =       0;
597                 mine_fileinfo.delta_light_sizeof                =       sizeof(delta_light);  
598
599 //      }
600
601         mine_fileinfo.segment2_offset           = -1;
602         mine_fileinfo.segment2_howmany  = 0;
603         mine_fileinfo.segment2_sizeof    = sizeof(segment2);
604
605         // Read in mine_top_fileinfo to get size of saved fileinfo.
606         
607         memset( &mine_top_fileinfo, 0, sizeof(mine_top_fileinfo) );
608
609         if (cfseek( LoadFile, mine_start, SEEK_SET ))
610                 Error( "Error moving to top of file in gamemine.c" );
611
612         if (cfread( &mine_top_fileinfo, sizeof(mine_top_fileinfo), 1, LoadFile )!=1)
613                 Error( "Error reading mine_top_fileinfo in gamemine.c" );
614
615         if (mine_top_fileinfo.fileinfo_signature != 0x2884)
616                 return -1;
617
618         // Check version number
619         if (mine_top_fileinfo.fileinfo_version < COMPATIBLE_VERSION )
620                 return -1;
621
622         // Now, Read in the fileinfo
623         if (cfseek( LoadFile, mine_start, SEEK_SET ))
624                 Error( "Error seeking to top of file in gamemine.c" );
625
626         if (cfread( &mine_fileinfo, mine_top_fileinfo.fileinfo_sizeof, 1, LoadFile )!=1)
627                 Error( "Error reading mine_fileinfo in gamemine.c" );
628
629         if (mine_top_fileinfo.fileinfo_version < 18) {
630                 mprintf((1, "Old version, setting shake intensity to 0.\n"));
631                 Level_shake_frequency = 0;
632                 Level_shake_duration = 0;
633                 Secret_return_segment = 0;
634                 Secret_return_orient = vmd_identity_matrix;
635         } else {
636                 Level_shake_frequency = mine_fileinfo.level_shake_frequency << 12;
637                 Level_shake_duration = mine_fileinfo.level_shake_duration << 12;
638                 Secret_return_segment = mine_fileinfo.secret_return_segment;
639                 Secret_return_orient = mine_fileinfo.secret_return_orient;
640         }
641
642         //===================== READ HEADER INFO ========================
643
644         // Set default values.
645         mine_header.num_vertices        =   0;
646         mine_header.num_segments        =   0;
647
648         if (mine_fileinfo.header_offset > -1 )
649         {
650                 if (cfseek( LoadFile, mine_fileinfo.header_offset, SEEK_SET ))
651                         Error( "Error seeking to header_offset in gamemine.c" );
652         
653                 if (cfread( &mine_header, mine_fileinfo.header_size, 1, LoadFile )!=1)
654                         Error( "Error reading mine_header in gamemine.c" );
655         }
656
657         //===================== READ EDITOR INFO ==========================
658
659         // Set default values
660         mine_editor.current_seg         =   0;
661         mine_editor.newsegment_offset   =   -1; // To be written
662         mine_editor.newsegment_size     =   sizeof(segment);
663         mine_editor.Curside             =   0;
664         mine_editor.Markedsegp          =   -1;
665         mine_editor.Markedside          =   0;
666
667         if (mine_fileinfo.editor_offset > -1 )
668         {
669                 if (cfseek( LoadFile, mine_fileinfo.editor_offset, SEEK_SET ))
670                         Error( "Error seeking to editor_offset in gamemine.c" );
671         
672                 if (cfread( &mine_editor, mine_fileinfo.editor_size, 1, LoadFile )!=1)
673                         Error( "Error reading mine_editor in gamemine.c" );
674         }
675
676         //===================== READ TEXTURE INFO ==========================
677
678         if ( (mine_fileinfo.texture_offset > -1) && (mine_fileinfo.texture_howmany > 0))
679         {
680                 if (cfseek( LoadFile, mine_fileinfo.texture_offset, SEEK_SET ))
681                         Error( "Error seeking to texture_offset in gamemine.c" );
682
683                 for (i=0; i< mine_fileinfo.texture_howmany; i++ )
684                 {
685                         if (cfread( &old_tmap_list[i], mine_fileinfo.texture_sizeof, 1, LoadFile )!=1)
686                                 Error( "Error reading old_tmap_list[i] in gamemine.c" );
687                 }
688         }
689
690         //=============== GENERATE TEXTURE TRANSLATION TABLE ===============
691
692         translate = 0;
693         
694         Assert (NumTextures < MAX_TEXTURES);
695
696         {
697                 hashtable ht;
698         
699                 hashtable_init( &ht, NumTextures );
700         
701                 // Remove all the file extensions in the textures list
702         
703                 for (i=0;i<NumTextures;i++)     {
704                         temptr = strchr(TmapInfo[i].filename, '.');
705                         if (temptr) *temptr = '\0';
706                         hashtable_insert( &ht, TmapInfo[i].filename, i );
707                 }
708         
709                 // For every texture, search through the texture list
710                 // to find a matching name.
711                 for (j=0;j<mine_fileinfo.texture_howmany;j++)   {
712                         // Remove this texture name's extension
713                         temptr = strchr(old_tmap_list[j], '.');
714                         if (temptr) *temptr = '\0';
715         
716                         tmap_xlate_table[j] = hashtable_search( &ht,old_tmap_list[j]);
717                         if (tmap_xlate_table[j] < 0 )   {
718                                 //tmap_xlate_table[j] = 0;
719                                 // mprintf( (0, "Couldn't find texture '%s'\n", old_tmap_list[j] ));
720                                 ;
721                         }
722                         if (tmap_xlate_table[j] != j ) translate = 1;
723                         if (tmap_xlate_table[j] >= 0)
724                                 tmap_times_used[tmap_xlate_table[j]]++;
725                 }
726         
727                 {
728                         int count = 0;
729                         for (i=0; i<MAX_TEXTURES; i++ )
730                                 if (tmap_times_used[i])
731                                         count++;
732                         mprintf( (0, "This mine has %d unique textures in it (~%d KB)\n", count, (count*4096) /1024 ));
733                 }
734         
735                 // -- mprintf( (0, "Translate=%d\n", translate ));
736         
737                 hashtable_free( &ht );
738         }
739
740         //====================== READ VERTEX INFO ==========================
741
742         // New check added to make sure we don't read in too many vertices.
743         if ( mine_fileinfo.vertex_howmany > MAX_VERTICES )
744                 {
745                 mprintf((0, "Num vertices exceeds maximum.  Loading MAX %d vertices\n", MAX_VERTICES));
746                 mine_fileinfo.vertex_howmany = MAX_VERTICES;
747                 }
748
749         if ( (mine_fileinfo.vertex_offset > -1) && (mine_fileinfo.vertex_howmany > 0))
750         {
751                 if (cfseek( LoadFile, mine_fileinfo.vertex_offset, SEEK_SET ))
752                         Error( "Error seeking to vertex_offset in gamemine.c" );
753
754                 for (i=0; i< mine_fileinfo.vertex_howmany; i++ )
755                 {
756                         // Set the default values for this vertex
757                         Vertices[i].x = 1;
758                         Vertices[i].y = 1;
759                         Vertices[i].z = 1;
760
761                         if (cfread( &Vertices[i], mine_fileinfo.vertex_sizeof, 1, LoadFile )!=1)
762                                 Error( "Error reading Vertices[i] in gamemine.c" );
763                 }
764         }
765
766         //==================== READ SEGMENT INFO ===========================
767
768         // New check added to make sure we don't read in too many segments.
769         if ( mine_fileinfo.segment_howmany > MAX_SEGMENTS ) {
770                 mprintf((0, "Num segments exceeds maximum.  Loading MAX %d segments\n", MAX_SEGMENTS));
771                 mine_fileinfo.segment_howmany = MAX_SEGMENTS;
772                 mine_fileinfo.segment2_howmany = MAX_SEGMENTS;
773         }
774
775         // [commented out by mk on 11/20/94 (weren't we supposed to hit final in October?) because it looks redundant.  I think I'll test it now...]  fuelcen_reset();
776
777         if ( (mine_fileinfo.segment_offset > -1) && (mine_fileinfo.segment_howmany > 0))        {
778
779                 if (cfseek( LoadFile, mine_fileinfo.segment_offset,SEEK_SET ))
780
781                         Error( "Error seeking to segment_offset in gamemine.c" );
782
783                 Highest_segment_index = mine_fileinfo.segment_howmany-1;
784
785                 for (i=0; i< mine_fileinfo.segment_howmany; i++ ) {
786
787                         // Set the default values for this segment (clear to zero )
788                         //memset( &Segments[i], 0, sizeof(segment) );
789
790                         if (mine_top_fileinfo.fileinfo_version < 20) {
791                                 v16_segment v16_seg;
792
793                                 Assert(mine_fileinfo.segment_sizeof == sizeof(v16_seg));
794
795                                 if (cfread( &v16_seg, mine_fileinfo.segment_sizeof, 1, LoadFile )!=1)
796                                         Error( "Error reading segments in gamemine.c" );
797
798                                 #ifdef EDITOR
799                                 Segments[i].segnum = v16_seg.segnum;
800                                 // -- Segments[i].pad = v16_seg.pad;
801                                 #endif
802
803                                 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
804                                         Segments[i].sides[j] = v16_seg.sides[j];
805
806                                 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
807                                         Segments[i].children[j] = v16_seg.children[j];
808
809                                 for (j=0; j<MAX_VERTICES_PER_SEGMENT; j++)
810                                         Segments[i].verts[j] = v16_seg.verts[j];
811
812                                 Segment2s[i].special = v16_seg.special;
813                                 Segment2s[i].value = v16_seg.value;
814                                 Segment2s[i].s2_flags = 0;
815                                 Segment2s[i].matcen_num = v16_seg.matcen_num;
816                                 Segment2s[i].static_light = v16_seg.static_light;
817                                 fuelcen_activate( &Segments[i], Segment2s[i].special );
818
819                         } else  {
820                                 if (cfread( &Segments[i], mine_fileinfo.segment_sizeof, 1, LoadFile )!=1)
821                                         Error("Unable to read segment %i\n", i);
822                         }
823
824                         Segments[i].objects = -1;
825                         #ifdef EDITOR
826                         Segments[i].group = -1;
827                         #endif
828
829                         if (mine_top_fileinfo.fileinfo_version < 15) {  //used old uvl ranges
830                                 int sn,uvln;
831
832                                 for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++)
833                                         for (uvln=0;uvln<4;uvln++) {
834                                                 Segments[i].sides[sn].uvls[uvln].u /= 64;
835                                                 Segments[i].sides[sn].uvls[uvln].v /= 64;
836                                                 Segments[i].sides[sn].uvls[uvln].l /= 32;
837                                         }
838                         }
839
840                         if (translate == 1)
841                                 for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) {
842                                         unsigned short orient;
843                                         tmap_xlate = Segments[i].sides[j].tmap_num;
844                                         Segments[i].sides[j].tmap_num = tmap_xlate_table[tmap_xlate];
845                                         if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG))
846                                                 if (Segments[i].sides[j].tmap_num < 0)  {
847                                                         mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j));
848                                                         Int3();
849                                                         Segments[i].sides[j].tmap_num = NumTextures-1;
850                                                 }
851                                         tmap_xlate = Segments[i].sides[j].tmap_num2 & 0x3FFF;
852                                         orient = Segments[i].sides[j].tmap_num2 & (~0x3FFF);
853                                         if (tmap_xlate != 0) {
854                                                 int xlated_tmap = tmap_xlate_table[tmap_xlate];
855
856                                                 if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG))
857                                                         if (xlated_tmap <= 0)   {
858                                                                 mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j));
859                                                                 Int3();
860                                                                 Segments[i].sides[j].tmap_num2 = NumTextures-1;
861                                                         }
862                                                 Segments[i].sides[j].tmap_num2 = xlated_tmap | orient;
863                                         }
864                                 }
865                 }
866
867
868                 if (mine_top_fileinfo.fileinfo_version >= 20)
869                         for (i=0; i<=Highest_segment_index; i++) {
870                                 cfread(&Segment2s[i], sizeof(segment2), 1, LoadFile);
871                                 fuelcen_activate( &Segments[i], Segment2s[i].special );
872                         }
873         }
874
875         //===================== READ NEWSEGMENT INFO =====================
876
877         #ifdef EDITOR
878
879         {               // Default segment created.
880                 vms_vector      sizevec;
881                 med_create_new_segment(vm_vec_make(&sizevec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE));             // New_segment = Segments[0];
882                 //memset( &New_segment, 0, sizeof(segment) );
883         }
884
885         if (mine_editor.newsegment_offset > -1)
886         {
887                 if (cfseek( LoadFile, mine_editor.newsegment_offset,SEEK_SET ))
888                         Error( "Error seeking to newsegment_offset in gamemine.c" );
889                 if (cfread( &New_segment, mine_editor.newsegment_size,1,LoadFile )!=1)
890                         Error( "Error reading new_segment in gamemine.c" );
891         }
892
893         if ( (mine_fileinfo.newseg_verts_offset > -1) && (mine_fileinfo.newseg_verts_howmany > 0))
894         {
895                 if (cfseek( LoadFile, mine_fileinfo.newseg_verts_offset, SEEK_SET ))
896                         Error( "Error seeking to newseg_verts_offset in gamemine.c" );
897                 for (i=0; i< mine_fileinfo.newseg_verts_howmany; i++ )
898                 {
899                         // Set the default values for this vertex
900                         Vertices[NEW_SEGMENT_VERTICES+i].x = 1;
901                         Vertices[NEW_SEGMENT_VERTICES+i].y = 1;
902                         Vertices[NEW_SEGMENT_VERTICES+i].z = 1;
903                         
904                         if (cfread( &Vertices[NEW_SEGMENT_VERTICES+i], mine_fileinfo.newseg_verts_sizeof,1,LoadFile )!=1)
905                                 Error( "Error reading Vertices[NEW_SEGMENT_VERTICES+i] in gamemine.c" );
906
907                         New_segment.verts[i] = NEW_SEGMENT_VERTICES+i;
908                 }
909         }
910
911         #endif
912                                                                                                                         
913         //========================= UPDATE VARIABLES ======================
914
915         #ifdef EDITOR
916
917         // Setting to Markedsegp to NULL ignores Curside and Markedside, which
918         // we want to do when reading in an old file.
919         
920         Markedside = mine_editor.Markedside;
921         Curside = mine_editor.Curside;
922         for (i=0;i<10;i++)
923                 Groupside[i] = mine_editor.Groupside[i];
924
925         if ( mine_editor.current_seg != -1 )
926                 Cursegp = mine_editor.current_seg + Segments;
927         else
928                 Cursegp = NULL;
929
930         if (mine_editor.Markedsegp != -1 ) 
931                 Markedsegp = mine_editor.Markedsegp + Segments;
932         else
933                 Markedsegp = NULL;
934
935         num_groups = 0;
936         current_group = -1;
937
938         #endif
939
940         Num_vertices = mine_fileinfo.vertex_howmany;
941         Num_segments = mine_fileinfo.segment_howmany;
942         Highest_vertex_index = Num_vertices-1;
943         Highest_segment_index = Num_segments-1;
944
945         reset_objects(1);               //one object, the player
946
947         #ifdef EDITOR
948         Highest_vertex_index = MAX_SEGMENT_VERTICES-1;
949         Highest_segment_index = MAX_SEGMENTS-1;
950         set_vertex_counts();
951         Highest_vertex_index = Num_vertices-1;
952         Highest_segment_index = Num_segments-1;
953
954         warn_if_concave_segments();
955         #endif
956
957         #ifdef EDITOR
958                 validate_segment_all();
959         #endif
960
961         //create_local_segment_data();
962
963         //gamemine_find_textures();
964
965         if (mine_top_fileinfo.fileinfo_version < MINE_VERSION )
966                 return 1;               //old version
967         else
968                 return 0;
969
970 }
971 #endif
972
973 #define COMPILED_MINE_VERSION 0
974
975 void read_children(int segnum,ubyte bit_mask,CFILE *LoadFile)
976 {
977         int bit;
978
979         for (bit=0; bit<MAX_SIDES_PER_SEGMENT; bit++) {
980                 if (bit_mask & (1 << bit)) {
981                         Segments[segnum].children[bit] = cfile_read_short(LoadFile);
982                 } else
983                         Segments[segnum].children[bit] = -1;
984         }
985 }
986
987 void read_verts(int segnum,CFILE *LoadFile)
988 {
989         int i;
990         // Read short Segments[segnum].verts[MAX_VERTICES_PER_SEGMENT]
991         for (i = 0; i < MAX_VERTICES_PER_SEGMENT; i++)
992                 Segments[segnum].verts[i] = cfile_read_short(LoadFile);
993 }
994
995 void read_special(int segnum,ubyte bit_mask,CFILE *LoadFile)
996 {
997         if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT)) {
998                 // Read ubyte   Segment2s[segnum].special
999                 Segment2s[segnum].special = cfile_read_byte(LoadFile);
1000                 // Read byte    Segment2s[segnum].matcen_num
1001                 Segment2s[segnum].matcen_num = cfile_read_byte(LoadFile);
1002                 // Read short   Segment2s[segnum].value
1003                 Segment2s[segnum].value = cfile_read_short(LoadFile);
1004         } else {
1005                 Segment2s[segnum].special = 0;
1006                 Segment2s[segnum].matcen_num = -1;
1007                 Segment2s[segnum].value = 0;
1008         }
1009 }
1010
1011 int load_mine_data_compiled(CFILE *LoadFile)
1012 {
1013         int     i, segnum, sidenum;
1014         ubyte   compiled_version;
1015         short   temp_short;
1016         ushort  temp_ushort;
1017         ubyte   bit_mask;
1018
1019         //      For compiled levels, textures map to themselves, prevent tmap_override always being gray,
1020         //      bug which Matt and John refused to acknowledge, so here is Mike, fixing it.
1021 #ifdef EDITOR
1022         for (i=0; i<MAX_TEXTURES; i++)
1023                 tmap_xlate_table[i] = i;
1024 #endif
1025
1026 //      memset( Segments, 0, sizeof(segment)*MAX_SEGMENTS );
1027         fuelcen_reset();
1028
1029         //=============================== Reading part ==============================
1030         compiled_version = cfile_read_byte(LoadFile);
1031         //Assert( compiled_version==COMPILED_MINE_VERSION );
1032         if (compiled_version!=COMPILED_MINE_VERSION)
1033                 mprintf((0,"compiled mine version=%i\n", compiled_version)); //many levels have "wrong" versions.  Theres no point in aborting because of it, I think.
1034
1035         Num_vertices = cfile_read_short(LoadFile);
1036         Assert( Num_vertices <= MAX_VERTICES );
1037
1038         Num_segments = cfile_read_short(LoadFile);
1039         Assert( Num_segments <= MAX_SEGMENTS );
1040
1041         for (i = 0; i < Num_vertices; i++)
1042                 cfile_read_vector( &(Vertices[i]), LoadFile);
1043
1044         for (segnum=0; segnum<Num_segments; segnum++ )  {
1045
1046                 #ifdef EDITOR
1047                 Segments[segnum].segnum = segnum;
1048                 Segments[segnum].group = 0;
1049                 #endif
1050
1051                 bit_mask = cfile_read_byte(LoadFile);
1052
1053                 if (Gamesave_current_version == 5) { // d2 SHAREWARE level
1054                         read_special(segnum,bit_mask,LoadFile);
1055                         read_verts(segnum,LoadFile);
1056                         read_children(segnum,bit_mask,LoadFile);
1057                 } else {
1058                         read_children(segnum,bit_mask,LoadFile);
1059                         read_verts(segnum,LoadFile);
1060                         if (Gamesave_current_version <= 1) { // descent 1 level
1061                                 read_special(segnum,bit_mask,LoadFile);
1062                         }
1063                 }
1064
1065                 Segments[segnum].objects = -1;
1066
1067                 if (Gamesave_current_version <= 5) { // descent 1 thru d2 SHAREWARE level
1068                         // Read fix     Segments[segnum].static_light (shift down 5 bits, write as short)
1069                         temp_ushort = cfile_read_short(LoadFile);
1070                         Segment2s[segnum].static_light  = ((fix)temp_ushort) << 4;
1071                         //cfread( &Segments[segnum].static_light, sizeof(fix), 1, LoadFile );
1072                 }
1073
1074                 // Read the walls as a 6 byte array
1075                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ )      {
1076                         Segments[segnum].sides[sidenum].pad = 0;
1077                 }
1078
1079                 bit_mask = cfile_read_byte(LoadFile);
1080                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
1081                         ubyte byte_wallnum;
1082
1083                         if (bit_mask & (1 << sidenum)) {
1084                                 byte_wallnum = cfile_read_byte(LoadFile);
1085                                 if ( byte_wallnum == 255 )
1086                                         Segments[segnum].sides[sidenum].wall_num = -1;
1087                                 else
1088                                         Segments[segnum].sides[sidenum].wall_num = byte_wallnum;
1089                         } else
1090                                         Segments[segnum].sides[sidenum].wall_num = -1;
1091                 }
1092
1093                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ )      {
1094
1095                         if ( (Segments[segnum].children[sidenum]==-1) || (Segments[segnum].sides[sidenum].wall_num!=-1) )       {
1096                                 // Read short Segments[segnum].sides[sidenum].tmap_num;
1097                                 temp_ushort = cfile_read_short(LoadFile);
1098                                 Segments[segnum].sides[sidenum].tmap_num = temp_ushort & 0x7fff;
1099
1100
1101                                 if (Gamesave_current_version <= 1)
1102                                   Segments[segnum].sides[sidenum].tmap_num = convert_d1_tmap_num(Segments[segnum].sides[sidenum].tmap_num);
1103
1104                                 if (!(temp_ushort & 0x8000))
1105                                         Segments[segnum].sides[sidenum].tmap_num2 = 0;
1106                                 else {
1107                                         // Read short Segments[segnum].sides[sidenum].tmap_num2;
1108                                         Segments[segnum].sides[sidenum].tmap_num2 = cfile_read_short(LoadFile);
1109                                         if (Gamesave_current_version <= 1)
1110                                           Segments[segnum].sides[sidenum].tmap_num2 = convert_d1_tmap_num(Segments[segnum].sides[sidenum].tmap_num2);
1111                                 }
1112
1113                                 // Read uvl Segments[segnum].sides[sidenum].uvls[4] (u,v>>5, write as short, l>>1 write as short)
1114                                 for (i=0; i<4; i++ )    {
1115                                         temp_short = cfile_read_short(LoadFile);
1116                                         Segments[segnum].sides[sidenum].uvls[i].u = ((fix)temp_short) << 5;
1117                                         temp_short = cfile_read_short(LoadFile);
1118                                         Segments[segnum].sides[sidenum].uvls[i].v = ((fix)temp_short) << 5;
1119                                         temp_ushort = cfile_read_short(LoadFile);
1120                                         Segments[segnum].sides[sidenum].uvls[i].l = ((fix)temp_ushort) << 1;
1121                                         //cfread( &Segments[segnum].sides[sidenum].uvls[i].l, sizeof(fix), 1, LoadFile );
1122                                 }
1123                         } else {
1124                                 Segments[segnum].sides[sidenum].tmap_num = 0;
1125                                 Segments[segnum].sides[sidenum].tmap_num2 = 0;
1126                                 for (i=0; i<4; i++ )    {
1127                                         Segments[segnum].sides[sidenum].uvls[i].u = 0;
1128                                         Segments[segnum].sides[sidenum].uvls[i].v = 0;
1129                                         Segments[segnum].sides[sidenum].uvls[i].l = 0;
1130                                 }
1131                         }
1132                 }
1133         }
1134
1135 #if 0
1136         {
1137                 FILE *fp;
1138
1139                 fp = fopen("segments.out", "wt");
1140                 for (i = 0; i <= Highest_segment_index; i++) {
1141                         side    sides[MAX_SIDES_PER_SEGMENT];   // 6 sides
1142                         short   children[MAX_SIDES_PER_SEGMENT];        // indices of 6 children segments, front, left, top, right, bottom, back
1143                         short   verts[MAX_VERTICES_PER_SEGMENT];        // vertex ids of 4 front and 4 back vertices
1144                         int             objects;                                                                // pointer to objects in this segment
1145
1146                         for (j = 0; j < MAX_SIDES_PER_SEGMENT; j++) {
1147                                 byte    type;                                                                   // replaces num_faces and tri_edge, 1 = quad, 2 = 0:2 triangulation, 3 = 1:3 triangulation
1148                                 ubyte   pad;                                                                    //keep us longword alligned
1149                                 short   wall_num;
1150                                 short   tmap_num;
1151                                 short   tmap_num2;
1152                                 uvl             uvls[4];
1153                                 vms_vector      normals[2];                                             // 2 normals, if quadrilateral, both the same.
1154                                 fprintf(fp, "%d\n", Segments[i].sides[j].type);
1155                                 fprintf(fp, "%d\n", Segments[i].sides[j].pad);
1156                                 fprintf(fp, "%d\n", Segments[i].sides[j].wall_num);
1157                                 fprintf(fp, "%d\n", Segments[i].tmap_num);
1158
1159                         }
1160                         fclose(fp);
1161                 }
1162         }
1163 #endif
1164
1165         Highest_vertex_index = Num_vertices-1;
1166         Highest_segment_index = Num_segments-1;
1167
1168         validate_segment_all();                 // Fill in side type and normals.
1169
1170         for (i=0; i<Num_segments; i++) {
1171                 if (Gamesave_current_version > 5)
1172                         segment2_read(&Segment2s[i], LoadFile);
1173                 fuelcen_activate( &Segments[i], Segment2s[i].special );
1174         }
1175
1176         reset_objects(1);               //one object, the player
1177
1178         return 0;
1179 }