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