]> icculus.org git repositories - btb/d2x.git/blob - main/gamemine.c
2e6b78a6b2336ab9188c8820f95c15e82f487436
[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.19 2003-02-27 04:34:51 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;
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  17; //devil:52
172         case  18:  return  18; //devil: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  66; //devil:15
214         // range handled by default case
215         case 132:  return  108; //devil: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  111; //devil: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  82; //devil:27
238         case 155:  return  66; //devil:126
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  325; //devil: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  366; //devil:380
365         case 331: return 373;
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  370; //devil: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 (New_file_format_load) {
422                         if (d1_tmap_num > 370 && d1_tmap_num < 584)
423                                 return d1_tmap_num + 64;
424                 } else {
425                         if (d1_tmap_num > 370 && d1_tmap_num <= 409)
426                                 return d1_tmap_num + 68;
427                         if (d1_tmap_num >= 410 && d1_tmap_num <= 416)
428                                 return d1_tmap_num + 73;
429                         if (d1_tmap_num >= 417 && d1_tmap_num <= 445)
430                                 return d1_tmap_num + 91;
431                         if (d1_tmap_num >= 446 && d1_tmap_num <= 452)
432                                 return d1_tmap_num + 104;
433                         if (d1_tmap_num >= 453 && d1_tmap_num <= 461)
434                                 return d1_tmap_num + 111;
435                         if (d1_tmap_num >= 462 && d1_tmap_num <= 485)
436                                 return d1_tmap_num + 117;
437                         if (d1_tmap_num >= 486 && d1_tmap_num <= 493)
438                                 return d1_tmap_num + 141;
439                         if (d1_tmap_num >= 494 && d1_tmap_num < 584)
440                                 return d1_tmap_num + 147;
441                 }
442                 { // handle rare case where orientation != 0
443                         short tmap_num = d1_tmap_num &  TMAP_NUM_MASK;
444                         short orient = d1_tmap_num & ~TMAP_NUM_MASK;
445                         if (orient != 0) {
446                                 return orient | convert_d1_tmap_num(tmap_num);
447                         } else {
448                                 Warning("can't convert unknown descent 1 texture #%d.\n", tmap_num);
449                                 return d1_tmap_num;
450                         }
451                 }
452         }
453 }
454
455 #ifdef EDITOR
456
457 static char old_tmap_list[MAX_TEXTURES][FILENAME_LEN];
458 short tmap_xlate_table[MAX_TEXTURES];
459 static short tmap_times_used[MAX_TEXTURES];
460
461 // -----------------------------------------------------------------------------
462 //loads from an already-open file
463 // returns 0=everything ok, 1=old version, -1=error
464 int load_mine_data(CFILE *LoadFile)
465 {
466         int   i, j,oldsizeadjust;
467         short tmap_xlate;
468         int     translate;
469         char    *temptr;
470         int     mine_start = cftell(LoadFile);
471
472         oldsizeadjust=(sizeof(int)*2)+sizeof (vms_matrix);
473         fuelcen_reset();
474
475         for (i=0; i<MAX_TEXTURES; i++ )
476                 tmap_times_used[i] = 0;
477
478         #ifdef EDITOR
479         // Create a new mine to initialize things.
480         //texpage_goto_first();
481         create_new_mine();
482         #endif
483
484         //===================== READ FILE INFO ========================
485
486         // These are the default values... version and fileinfo_sizeof
487         // don't have defaults.
488         mine_fileinfo.header_offset     =   -1;
489         mine_fileinfo.header_size       =   sizeof(mine_header);
490         mine_fileinfo.editor_offset     =   -1;
491         mine_fileinfo.editor_size       =   sizeof(mine_editor);
492         mine_fileinfo.vertex_offset     =   -1;
493         mine_fileinfo.vertex_howmany    =   0;
494         mine_fileinfo.vertex_sizeof     =   sizeof(vms_vector);
495         mine_fileinfo.segment_offset    =   -1;
496         mine_fileinfo.segment_howmany   =   0;
497         mine_fileinfo.segment_sizeof    =   sizeof(segment);
498         mine_fileinfo.newseg_verts_offset     =   -1;
499         mine_fileinfo.newseg_verts_howmany    =   0;
500         mine_fileinfo.newseg_verts_sizeof     =   sizeof(vms_vector);
501         mine_fileinfo.group_offset                =     -1;
502         mine_fileinfo.group_howmany       =     0;
503         mine_fileinfo.group_sizeof                =     sizeof(group);
504         mine_fileinfo.texture_offset    =   -1;
505         mine_fileinfo.texture_howmany   =   0;
506         mine_fileinfo.texture_sizeof    =   FILENAME_LEN;  // num characters in a name
507         mine_fileinfo.walls_offset                =     -1;
508         mine_fileinfo.walls_howmany       =     0;
509         mine_fileinfo.walls_sizeof                =     sizeof(wall);  
510         mine_fileinfo.triggers_offset     =     -1;
511         mine_fileinfo.triggers_howmany  =       0;
512         mine_fileinfo.triggers_sizeof     =     sizeof(trigger);  
513         mine_fileinfo.object_offset             =       -1;
514         mine_fileinfo.object_howmany            =       1;
515         mine_fileinfo.object_sizeof             =       sizeof(object);  
516
517         mine_fileinfo.level_shake_frequency             =       0;
518         mine_fileinfo.level_shake_duration              =       0;
519
520         //      Delta light stuff for blowing out light sources.
521 //      if (mine_top_fileinfo.fileinfo_version >= 19) {
522                 mine_fileinfo.dl_indices_offset         =       -1;
523                 mine_fileinfo.dl_indices_howmany                =       0;
524                 mine_fileinfo.dl_indices_sizeof         =       sizeof(dl_index);  
525
526                 mine_fileinfo.delta_light_offset                =       -1;
527                 mine_fileinfo.delta_light_howmany               =       0;
528                 mine_fileinfo.delta_light_sizeof                =       sizeof(delta_light);  
529
530 //      }
531
532         mine_fileinfo.segment2_offset           = -1;
533         mine_fileinfo.segment2_howmany  = 0;
534         mine_fileinfo.segment2_sizeof    = sizeof(segment2);
535
536         // Read in mine_top_fileinfo to get size of saved fileinfo.
537         
538         memset( &mine_top_fileinfo, 0, sizeof(mine_top_fileinfo) );
539
540         if (cfseek( LoadFile, mine_start, SEEK_SET ))
541                 Error( "Error moving to top of file in gamemine.c" );
542
543         if (cfread( &mine_top_fileinfo, sizeof(mine_top_fileinfo), 1, LoadFile )!=1)
544                 Error( "Error reading mine_top_fileinfo in gamemine.c" );
545
546         if (mine_top_fileinfo.fileinfo_signature != 0x2884)
547                 return -1;
548
549         // Check version number
550         if (mine_top_fileinfo.fileinfo_version < COMPATIBLE_VERSION )
551                 return -1;
552
553         // Now, Read in the fileinfo
554         if (cfseek( LoadFile, mine_start, SEEK_SET ))
555                 Error( "Error seeking to top of file in gamemine.c" );
556
557         if (cfread( &mine_fileinfo, mine_top_fileinfo.fileinfo_sizeof, 1, LoadFile )!=1)
558                 Error( "Error reading mine_fileinfo in gamemine.c" );
559
560         if (mine_top_fileinfo.fileinfo_version < 18) {
561                 mprintf((1, "Old version, setting shake intensity to 0.\n"));
562                 Level_shake_frequency = 0;
563                 Level_shake_duration = 0;
564                 Secret_return_segment = 0;
565                 Secret_return_orient = vmd_identity_matrix;
566         } else {
567                 Level_shake_frequency = mine_fileinfo.level_shake_frequency << 12;
568                 Level_shake_duration = mine_fileinfo.level_shake_duration << 12;
569                 Secret_return_segment = mine_fileinfo.secret_return_segment;
570                 Secret_return_orient = mine_fileinfo.secret_return_orient;
571         }
572
573         //===================== READ HEADER INFO ========================
574
575         // Set default values.
576         mine_header.num_vertices        =   0;
577         mine_header.num_segments        =   0;
578
579         if (mine_fileinfo.header_offset > -1 )
580         {
581                 if (cfseek( LoadFile, mine_fileinfo.header_offset, SEEK_SET ))
582                         Error( "Error seeking to header_offset in gamemine.c" );
583         
584                 if (cfread( &mine_header, mine_fileinfo.header_size, 1, LoadFile )!=1)
585                         Error( "Error reading mine_header in gamemine.c" );
586         }
587
588         //===================== READ EDITOR INFO ==========================
589
590         // Set default values
591         mine_editor.current_seg         =   0;
592         mine_editor.newsegment_offset   =   -1; // To be written
593         mine_editor.newsegment_size     =   sizeof(segment);
594         mine_editor.Curside             =   0;
595         mine_editor.Markedsegp          =   -1;
596         mine_editor.Markedside          =   0;
597
598         if (mine_fileinfo.editor_offset > -1 )
599         {
600                 if (cfseek( LoadFile, mine_fileinfo.editor_offset, SEEK_SET ))
601                         Error( "Error seeking to editor_offset in gamemine.c" );
602         
603                 if (cfread( &mine_editor, mine_fileinfo.editor_size, 1, LoadFile )!=1)
604                         Error( "Error reading mine_editor in gamemine.c" );
605         }
606
607         //===================== READ TEXTURE INFO ==========================
608
609         if ( (mine_fileinfo.texture_offset > -1) && (mine_fileinfo.texture_howmany > 0))
610         {
611                 if (cfseek( LoadFile, mine_fileinfo.texture_offset, SEEK_SET ))
612                         Error( "Error seeking to texture_offset in gamemine.c" );
613
614                 for (i=0; i< mine_fileinfo.texture_howmany; i++ )
615                 {
616                         if (cfread( &old_tmap_list[i], mine_fileinfo.texture_sizeof, 1, LoadFile )!=1)
617                                 Error( "Error reading old_tmap_list[i] in gamemine.c" );
618                 }
619         }
620
621         //=============== GENERATE TEXTURE TRANSLATION TABLE ===============
622
623         translate = 0;
624         
625         Assert (NumTextures < MAX_TEXTURES);
626
627         {
628                 hashtable ht;
629         
630                 hashtable_init( &ht, NumTextures );
631         
632                 // Remove all the file extensions in the textures list
633         
634                 for (i=0;i<NumTextures;i++)     {
635                         temptr = strchr(TmapInfo[i].filename, '.');
636                         if (temptr) *temptr = '\0';
637                         hashtable_insert( &ht, TmapInfo[i].filename, i );
638                 }
639         
640                 // For every texture, search through the texture list
641                 // to find a matching name.
642                 for (j=0;j<mine_fileinfo.texture_howmany;j++)   {
643                         // Remove this texture name's extension
644                         temptr = strchr(old_tmap_list[j], '.');
645                         if (temptr) *temptr = '\0';
646         
647                         tmap_xlate_table[j] = hashtable_search( &ht,old_tmap_list[j]);
648                         if (tmap_xlate_table[j] < 0 )   {
649                                 //tmap_xlate_table[j] = 0;
650                                 // mprintf( (0, "Couldn't find texture '%s'\n", old_tmap_list[j] ));
651                                 ;
652                         }
653                         if (tmap_xlate_table[j] != j ) translate = 1;
654                         if (tmap_xlate_table[j] >= 0)
655                                 tmap_times_used[tmap_xlate_table[j]]++;
656                 }
657         
658                 {
659                         int count = 0;
660                         for (i=0; i<MAX_TEXTURES; i++ )
661                                 if (tmap_times_used[i])
662                                         count++;
663                         mprintf( (0, "This mine has %d unique textures in it (~%d KB)\n", count, (count*4096) /1024 ));
664                 }
665         
666                 // -- mprintf( (0, "Translate=%d\n", translate ));
667         
668                 hashtable_free( &ht );
669         }
670
671         //====================== READ VERTEX INFO ==========================
672
673         // New check added to make sure we don't read in too many vertices.
674         if ( mine_fileinfo.vertex_howmany > MAX_VERTICES )
675                 {
676                 mprintf((0, "Num vertices exceeds maximum.  Loading MAX %d vertices\n", MAX_VERTICES));
677                 mine_fileinfo.vertex_howmany = MAX_VERTICES;
678                 }
679
680         if ( (mine_fileinfo.vertex_offset > -1) && (mine_fileinfo.vertex_howmany > 0))
681         {
682                 if (cfseek( LoadFile, mine_fileinfo.vertex_offset, SEEK_SET ))
683                         Error( "Error seeking to vertex_offset in gamemine.c" );
684
685                 for (i=0; i< mine_fileinfo.vertex_howmany; i++ )
686                 {
687                         // Set the default values for this vertex
688                         Vertices[i].x = 1;
689                         Vertices[i].y = 1;
690                         Vertices[i].z = 1;
691
692                         if (cfread( &Vertices[i], mine_fileinfo.vertex_sizeof, 1, LoadFile )!=1)
693                                 Error( "Error reading Vertices[i] in gamemine.c" );
694                 }
695         }
696
697         //==================== READ SEGMENT INFO ===========================
698
699         // New check added to make sure we don't read in too many segments.
700         if ( mine_fileinfo.segment_howmany > MAX_SEGMENTS ) {
701                 mprintf((0, "Num segments exceeds maximum.  Loading MAX %d segments\n", MAX_SEGMENTS));
702                 mine_fileinfo.segment_howmany = MAX_SEGMENTS;
703                 mine_fileinfo.segment2_howmany = MAX_SEGMENTS;
704         }
705
706         // [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();
707
708         if ( (mine_fileinfo.segment_offset > -1) && (mine_fileinfo.segment_howmany > 0))        {
709
710                 if (cfseek( LoadFile, mine_fileinfo.segment_offset,SEEK_SET ))
711
712                         Error( "Error seeking to segment_offset in gamemine.c" );
713
714                 Highest_segment_index = mine_fileinfo.segment_howmany-1;
715
716                 for (i=0; i< mine_fileinfo.segment_howmany; i++ ) {
717
718                         // Set the default values for this segment (clear to zero )
719                         //memset( &Segments[i], 0, sizeof(segment) );
720
721                         if (mine_top_fileinfo.fileinfo_version < 20) {
722                                 v16_segment v16_seg;
723
724                                 Assert(mine_fileinfo.segment_sizeof == sizeof(v16_seg));
725
726                                 if (cfread( &v16_seg, mine_fileinfo.segment_sizeof, 1, LoadFile )!=1)
727                                         Error( "Error reading segments in gamemine.c" );
728
729                                 #ifdef EDITOR
730                                 Segments[i].segnum = v16_seg.segnum;
731                                 // -- Segments[i].pad = v16_seg.pad;
732                                 #endif
733
734                                 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
735                                         Segments[i].sides[j] = v16_seg.sides[j];
736
737                                 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
738                                         Segments[i].children[j] = v16_seg.children[j];
739
740                                 for (j=0; j<MAX_VERTICES_PER_SEGMENT; j++)
741                                         Segments[i].verts[j] = v16_seg.verts[j];
742
743                                 Segment2s[i].special = v16_seg.special;
744                                 Segment2s[i].value = v16_seg.value;
745                                 Segment2s[i].s2_flags = 0;
746                                 Segment2s[i].matcen_num = v16_seg.matcen_num;
747                                 Segment2s[i].static_light = v16_seg.static_light;
748                                 fuelcen_activate( &Segments[i], Segment2s[i].special );
749
750                         } else  {
751                                 if (cfread( &Segments[i], mine_fileinfo.segment_sizeof, 1, LoadFile )!=1)
752                                         Error("Unable to read segment %i\n", i);
753                         }
754
755                         Segments[i].objects = -1;
756                         #ifdef EDITOR
757                         Segments[i].group = -1;
758                         #endif
759
760                         if (mine_top_fileinfo.fileinfo_version < 15) {  //used old uvl ranges
761                                 int sn,uvln;
762
763                                 for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++)
764                                         for (uvln=0;uvln<4;uvln++) {
765                                                 Segments[i].sides[sn].uvls[uvln].u /= 64;
766                                                 Segments[i].sides[sn].uvls[uvln].v /= 64;
767                                                 Segments[i].sides[sn].uvls[uvln].l /= 32;
768                                         }
769                         }
770
771                         if (translate == 1)
772                                 for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) {
773                                         unsigned short orient;
774                                         tmap_xlate = Segments[i].sides[j].tmap_num;
775                                         Segments[i].sides[j].tmap_num = tmap_xlate_table[tmap_xlate];
776                                         if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG))
777                                                 if (Segments[i].sides[j].tmap_num < 0)  {
778                                                         mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j));
779                                                         Int3();
780                                                         Segments[i].sides[j].tmap_num = NumTextures-1;
781                                                 }
782                                         tmap_xlate = Segments[i].sides[j].tmap_num2 & TMAP_NUM_MASK;
783                                         orient = Segments[i].sides[j].tmap_num2 & (~TMAP_NUM_MASK);
784                                         if (tmap_xlate != 0) {
785                                                 int xlated_tmap = tmap_xlate_table[tmap_xlate];
786
787                                                 if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG))
788                                                         if (xlated_tmap <= 0)   {
789                                                                 mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j));
790                                                                 Int3();
791                                                                 Segments[i].sides[j].tmap_num2 = NumTextures-1;
792                                                         }
793                                                 Segments[i].sides[j].tmap_num2 = xlated_tmap | orient;
794                                         }
795                                 }
796                 }
797
798
799                 if (mine_top_fileinfo.fileinfo_version >= 20)
800                         for (i=0; i<=Highest_segment_index; i++) {
801                                 cfread(&Segment2s[i], sizeof(segment2), 1, LoadFile);
802                                 fuelcen_activate( &Segments[i], Segment2s[i].special );
803                         }
804         }
805
806         //===================== READ NEWSEGMENT INFO =====================
807
808         #ifdef EDITOR
809
810         {               // Default segment created.
811                 vms_vector      sizevec;
812                 med_create_new_segment(vm_vec_make(&sizevec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE));             // New_segment = Segments[0];
813                 //memset( &New_segment, 0, sizeof(segment) );
814         }
815
816         if (mine_editor.newsegment_offset > -1)
817         {
818                 if (cfseek( LoadFile, mine_editor.newsegment_offset,SEEK_SET ))
819                         Error( "Error seeking to newsegment_offset in gamemine.c" );
820                 if (cfread( &New_segment, mine_editor.newsegment_size,1,LoadFile )!=1)
821                         Error( "Error reading new_segment in gamemine.c" );
822         }
823
824         if ( (mine_fileinfo.newseg_verts_offset > -1) && (mine_fileinfo.newseg_verts_howmany > 0))
825         {
826                 if (cfseek( LoadFile, mine_fileinfo.newseg_verts_offset, SEEK_SET ))
827                         Error( "Error seeking to newseg_verts_offset in gamemine.c" );
828                 for (i=0; i< mine_fileinfo.newseg_verts_howmany; i++ )
829                 {
830                         // Set the default values for this vertex
831                         Vertices[NEW_SEGMENT_VERTICES+i].x = 1;
832                         Vertices[NEW_SEGMENT_VERTICES+i].y = 1;
833                         Vertices[NEW_SEGMENT_VERTICES+i].z = 1;
834                         
835                         if (cfread( &Vertices[NEW_SEGMENT_VERTICES+i], mine_fileinfo.newseg_verts_sizeof,1,LoadFile )!=1)
836                                 Error( "Error reading Vertices[NEW_SEGMENT_VERTICES+i] in gamemine.c" );
837
838                         New_segment.verts[i] = NEW_SEGMENT_VERTICES+i;
839                 }
840         }
841
842         #endif
843                                                                                                                         
844         //========================= UPDATE VARIABLES ======================
845
846         #ifdef EDITOR
847
848         // Setting to Markedsegp to NULL ignores Curside and Markedside, which
849         // we want to do when reading in an old file.
850         
851         Markedside = mine_editor.Markedside;
852         Curside = mine_editor.Curside;
853         for (i=0;i<10;i++)
854                 Groupside[i] = mine_editor.Groupside[i];
855
856         if ( mine_editor.current_seg != -1 )
857                 Cursegp = mine_editor.current_seg + Segments;
858         else
859                 Cursegp = NULL;
860
861         if (mine_editor.Markedsegp != -1 ) 
862                 Markedsegp = mine_editor.Markedsegp + Segments;
863         else
864                 Markedsegp = NULL;
865
866         num_groups = 0;
867         current_group = -1;
868
869         #endif
870
871         Num_vertices = mine_fileinfo.vertex_howmany;
872         Num_segments = mine_fileinfo.segment_howmany;
873         Highest_vertex_index = Num_vertices-1;
874         Highest_segment_index = Num_segments-1;
875
876         reset_objects(1);               //one object, the player
877
878         #ifdef EDITOR
879         Highest_vertex_index = MAX_SEGMENT_VERTICES-1;
880         Highest_segment_index = MAX_SEGMENTS-1;
881         set_vertex_counts();
882         Highest_vertex_index = Num_vertices-1;
883         Highest_segment_index = Num_segments-1;
884
885         warn_if_concave_segments();
886         #endif
887
888         #ifdef EDITOR
889                 validate_segment_all();
890         #endif
891
892         //create_local_segment_data();
893
894         //gamemine_find_textures();
895
896         if (mine_top_fileinfo.fileinfo_version < MINE_VERSION )
897                 return 1;               //old version
898         else
899                 return 0;
900
901 }
902 #endif
903
904 #define COMPILED_MINE_VERSION 0
905
906 void read_children(int segnum,ubyte bit_mask,CFILE *LoadFile)
907 {
908         int bit;
909
910         for (bit=0; bit<MAX_SIDES_PER_SEGMENT; bit++) {
911                 if (bit_mask & (1 << bit)) {
912                         Segments[segnum].children[bit] = cfile_read_short(LoadFile);
913                 } else
914                         Segments[segnum].children[bit] = -1;
915         }
916 }
917
918 void read_verts(int segnum,CFILE *LoadFile)
919 {
920         int i;
921         // Read short Segments[segnum].verts[MAX_VERTICES_PER_SEGMENT]
922         for (i = 0; i < MAX_VERTICES_PER_SEGMENT; i++)
923                 Segments[segnum].verts[i] = cfile_read_short(LoadFile);
924 }
925
926 void read_special(int segnum,ubyte bit_mask,CFILE *LoadFile)
927 {
928         if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT)) {
929                 // Read ubyte   Segment2s[segnum].special
930                 Segment2s[segnum].special = cfile_read_byte(LoadFile);
931                 // Read byte    Segment2s[segnum].matcen_num
932                 Segment2s[segnum].matcen_num = cfile_read_byte(LoadFile);
933                 // Read short   Segment2s[segnum].value
934                 Segment2s[segnum].value = cfile_read_short(LoadFile);
935         } else {
936                 Segment2s[segnum].special = 0;
937                 Segment2s[segnum].matcen_num = -1;
938                 Segment2s[segnum].value = 0;
939         }
940 }
941
942 int load_mine_data_compiled(CFILE *LoadFile)
943 {
944         int     i, segnum, sidenum;
945         ubyte   compiled_version;
946         short   temp_short;
947         ushort  temp_ushort;
948         ubyte   bit_mask;
949
950         if (!strcmp(strchr(Gamesave_current_filename, '.'), ".sdl"))
951                 New_file_format_load = 0; // descent 1 shareware
952         else
953                 New_file_format_load = 1;
954
955         //      For compiled levels, textures map to themselves, prevent tmap_override always being gray,
956         //      bug which Matt and John refused to acknowledge, so here is Mike, fixing it.
957 #ifdef EDITOR
958         for (i=0; i<MAX_TEXTURES; i++)
959                 tmap_xlate_table[i] = i;
960 #endif
961
962 //      memset( Segments, 0, sizeof(segment)*MAX_SEGMENTS );
963         fuelcen_reset();
964
965         //=============================== Reading part ==============================
966         compiled_version = cfile_read_byte(LoadFile);
967         //Assert( compiled_version==COMPILED_MINE_VERSION );
968         if (compiled_version!=COMPILED_MINE_VERSION)
969                 mprintf((0,"compiled mine version=%i\n", compiled_version)); //many levels have "wrong" versions.  Theres no point in aborting because of it, I think.
970
971         if (New_file_format_load)
972                 Num_vertices = cfile_read_short(LoadFile);
973         else
974                 Num_vertices = cfile_read_int(LoadFile);
975         Assert( Num_vertices <= MAX_VERTICES );
976
977         if (New_file_format_load)
978                 Num_segments = cfile_read_short(LoadFile);
979         else
980                 Num_segments = cfile_read_int(LoadFile);
981         Assert( Num_segments <= MAX_SEGMENTS );
982
983         for (i = 0; i < Num_vertices; i++)
984                 cfile_read_vector( &(Vertices[i]), LoadFile);
985
986         for (segnum=0; segnum<Num_segments; segnum++ )  {
987
988                 #ifdef EDITOR
989                 Segments[segnum].segnum = segnum;
990                 Segments[segnum].group = 0;
991                 #endif
992
993                 if (New_file_format_load)
994                         bit_mask = cfile_read_byte(LoadFile);
995                 else
996                         bit_mask = 0x7f; // read all six children and special stuff...
997
998                 if (Gamesave_current_version == 5) { // d2 SHAREWARE level
999                         read_special(segnum,bit_mask,LoadFile);
1000                         read_verts(segnum,LoadFile);
1001                         read_children(segnum,bit_mask,LoadFile);
1002                 } else {
1003                         read_children(segnum,bit_mask,LoadFile);
1004                         read_verts(segnum,LoadFile);
1005                         if (Gamesave_current_version <= 1) { // descent 1 level
1006                                 read_special(segnum,bit_mask,LoadFile);
1007                         }
1008                 }
1009
1010                 Segments[segnum].objects = -1;
1011
1012                 if (Gamesave_current_version <= 5) { // descent 1 thru d2 SHAREWARE level
1013                         // Read fix     Segments[segnum].static_light (shift down 5 bits, write as short)
1014                         temp_ushort = cfile_read_short(LoadFile);
1015                         Segment2s[segnum].static_light  = ((fix)temp_ushort) << 4;
1016                         //cfread( &Segments[segnum].static_light, sizeof(fix), 1, LoadFile );
1017                 }
1018
1019                 // Read the walls as a 6 byte array
1020                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ )      {
1021                         Segments[segnum].sides[sidenum].pad = 0;
1022                 }
1023
1024                 if (New_file_format_load)
1025                         bit_mask = cfile_read_byte(LoadFile);
1026                 else
1027                         bit_mask = 0x3f; // read all six sides
1028                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
1029                         ubyte byte_wallnum;
1030
1031                         if (bit_mask & (1 << sidenum)) {
1032                                 byte_wallnum = cfile_read_byte(LoadFile);
1033                                 if ( byte_wallnum == 255 )
1034                                         Segments[segnum].sides[sidenum].wall_num = -1;
1035                                 else
1036                                         Segments[segnum].sides[sidenum].wall_num = byte_wallnum;
1037                         } else
1038                                         Segments[segnum].sides[sidenum].wall_num = -1;
1039                 }
1040
1041                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ )      {
1042
1043                         if ( (Segments[segnum].children[sidenum]==-1) || (Segments[segnum].sides[sidenum].wall_num!=-1) )       {
1044                                 // Read short Segments[segnum].sides[sidenum].tmap_num;
1045                                 if (New_file_format_load) {
1046                                         temp_ushort = cfile_read_short(LoadFile);
1047                                         Segments[segnum].sides[sidenum].tmap_num = temp_ushort & 0x7fff;
1048                                 } else
1049                                         Segments[segnum].sides[sidenum].tmap_num = cfile_read_short(LoadFile);
1050
1051                                 if (Gamesave_current_version <= 1)
1052                                         Segments[segnum].sides[sidenum].tmap_num = convert_d1_tmap_num(Segments[segnum].sides[sidenum].tmap_num);
1053
1054                                 if (New_file_format_load && !(temp_ushort & 0x8000))
1055                                         Segments[segnum].sides[sidenum].tmap_num2 = 0;
1056                                 else {
1057                                         // Read short Segments[segnum].sides[sidenum].tmap_num2;
1058                                         Segments[segnum].sides[sidenum].tmap_num2 = cfile_read_short(LoadFile);
1059                                         if (Gamesave_current_version <= 1 && Segments[segnum].sides[sidenum].tmap_num2 != 0)
1060                                                 Segments[segnum].sides[sidenum].tmap_num2 = convert_d1_tmap_num(Segments[segnum].sides[sidenum].tmap_num2);
1061                                 }
1062
1063                                 // Read uvl Segments[segnum].sides[sidenum].uvls[4] (u,v>>5, write as short, l>>1 write as short)
1064                                 for (i=0; i<4; i++ )    {
1065                                         temp_short = cfile_read_short(LoadFile);
1066                                         Segments[segnum].sides[sidenum].uvls[i].u = ((fix)temp_short) << 5;
1067                                         temp_short = cfile_read_short(LoadFile);
1068                                         Segments[segnum].sides[sidenum].uvls[i].v = ((fix)temp_short) << 5;
1069                                         temp_ushort = cfile_read_short(LoadFile);
1070                                         Segments[segnum].sides[sidenum].uvls[i].l = ((fix)temp_ushort) << 1;
1071                                         //cfread( &Segments[segnum].sides[sidenum].uvls[i].l, sizeof(fix), 1, LoadFile );
1072                                 }
1073                         } else {
1074                                 Segments[segnum].sides[sidenum].tmap_num = 0;
1075                                 Segments[segnum].sides[sidenum].tmap_num2 = 0;
1076                                 for (i=0; i<4; i++ )    {
1077                                         Segments[segnum].sides[sidenum].uvls[i].u = 0;
1078                                         Segments[segnum].sides[sidenum].uvls[i].v = 0;
1079                                         Segments[segnum].sides[sidenum].uvls[i].l = 0;
1080                                 }
1081                         }
1082                 }
1083         }
1084
1085 #if 0
1086         {
1087                 FILE *fp;
1088
1089                 fp = fopen("segments.out", "wt");
1090                 for (i = 0; i <= Highest_segment_index; i++) {
1091                         side    sides[MAX_SIDES_PER_SEGMENT];   // 6 sides
1092                         short   children[MAX_SIDES_PER_SEGMENT];        // indices of 6 children segments, front, left, top, right, bottom, back
1093                         short   verts[MAX_VERTICES_PER_SEGMENT];        // vertex ids of 4 front and 4 back vertices
1094                         int             objects;                                                                // pointer to objects in this segment
1095
1096                         for (j = 0; j < MAX_SIDES_PER_SEGMENT; j++) {
1097                                 byte    type;                                                                   // replaces num_faces and tri_edge, 1 = quad, 2 = 0:2 triangulation, 3 = 1:3 triangulation
1098                                 ubyte   pad;                                                                    //keep us longword alligned
1099                                 short   wall_num;
1100                                 short   tmap_num;
1101                                 short   tmap_num2;
1102                                 uvl             uvls[4];
1103                                 vms_vector      normals[2];                                             // 2 normals, if quadrilateral, both the same.
1104                                 fprintf(fp, "%d\n", Segments[i].sides[j].type);
1105                                 fprintf(fp, "%d\n", Segments[i].sides[j].pad);
1106                                 fprintf(fp, "%d\n", Segments[i].sides[j].wall_num);
1107                                 fprintf(fp, "%d\n", Segments[i].tmap_num);
1108
1109                         }
1110                         fclose(fp);
1111                 }
1112         }
1113 #endif
1114
1115         Highest_vertex_index = Num_vertices-1;
1116         Highest_segment_index = Num_segments-1;
1117
1118         validate_segment_all();                 // Fill in side type and normals.
1119
1120         for (i=0; i<Num_segments; i++) {
1121                 if (Gamesave_current_version > 5)
1122                         segment2_read(&Segment2s[i], LoadFile);
1123                 fuelcen_activate( &Segments[i], Segment2s[i].special );
1124         }
1125
1126         reset_objects(1);               //one object, the player
1127
1128         return 0;
1129 }