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