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