]> icculus.org git repositories - btb/d2x.git/blob - main/gamemine.c
load d1 levels
[btb/d2x.git] / main / gamemine.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 #ifdef HAVE_CONFIG_H
15 #include <conf.h>
16 #endif
17
18 #ifdef RCS
19 static char rcsid[] = "$Id: gamemine.c,v 1.8 2002-08-01 23:28:57 btb Exp $";
20 #endif
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #include <string.h>
26
27 #include "pstypes.h"
28 #include "mono.h"
29
30 #include "inferno.h"
31 #include "segment.h"
32 #include "textures.h"
33 #include "wall.h"
34 #include "object.h"
35 #include "gamemine.h"
36 #include "error.h"
37 #include "gameseg.h"
38 #include "switch.h"
39
40 #include "game.h"
41 #include "newmenu.h"
42
43 #ifdef EDITOR
44 #include "editor/editor.h"
45 #endif
46
47 #include "cfile.h"              
48 #include "fuelcen.h"
49
50 #include "hash.h"
51 #include "key.h"
52 #include "piggy.h"
53
54 #include "byteswap.h"
55
56 #define REMOVE_EXT(s)  (*(strchr( (s), '.' ))='\0')
57
58 fix     Level_shake_frequency = 0, Level_shake_duration = 0;
59 int     Secret_return_segment = 0;
60 vms_matrix      Secret_return_orient;
61
62 struct mtfi mine_top_fileinfo;    // Should be same as first two fields below...
63 struct mfi mine_fileinfo;
64 struct mh mine_header;
65 struct me mine_editor;
66
67 typedef struct v16_segment {
68         #ifdef  EDITOR
69         short           segnum;                                                         // segment number, not sure what it means
70         #endif
71         side            sides[MAX_SIDES_PER_SEGMENT];   // 6 sides
72         short           children[MAX_SIDES_PER_SEGMENT];        // indices of 6 children segments, front, left, top, right, bottom, back
73         short           verts[MAX_VERTICES_PER_SEGMENT];        // vertex ids of 4 front and 4 back vertices
74         #ifdef  EDITOR
75         short           group;                                                          // group number to which the segment belongs.
76         #endif
77         short           objects;                                                                // pointer to objects in this segment
78         ubyte           special;                                                                // what type of center this is 
79         byte            matcen_num;                                                     //      which center segment is associated with.
80         short           value;
81         fix             static_light;                                           //average static light in segment
82         #ifndef EDITOR
83         short           pad;                    //make structure longword aligned
84         #endif
85 } v16_segment;
86
87 struct mfi_v19 {
88         ushort  fileinfo_signature;
89         ushort  fileinfo_version;
90         int             fileinfo_sizeof;
91         int             header_offset;          // Stuff common to game & editor
92         int             header_size;
93         int             editor_offset;   // Editor specific stuff
94         int             editor_size;
95         int             segment_offset;
96         int             segment_howmany;
97         int             segment_sizeof;
98         int             newseg_verts_offset;
99         int             newseg_verts_howmany;
100         int             newseg_verts_sizeof;
101         int             group_offset;
102         int             group_howmany;
103         int             group_sizeof;
104         int             vertex_offset;
105         int             vertex_howmany;
106         int             vertex_sizeof;
107         int             texture_offset;
108         int             texture_howmany;
109         int             texture_sizeof;
110         int             walls_offset;
111         int             walls_howmany;
112         int             walls_sizeof;
113         int             triggers_offset;
114         int             triggers_howmany;
115         int             triggers_sizeof;
116         int             links_offset;
117         int             links_howmany;
118         int             links_sizeof;
119         int             object_offset;                          // Object info
120         int             object_howmany;         
121         int             object_sizeof;  
122         int             unused_offset;                  //was: doors_offset
123         int             unused_howmamy;         //was: doors_howmany
124         int             unused_sizeof;                  //was: doors_sizeof
125         short           level_shake_frequency, level_shake_duration;    //      Shakes every level_shake_frequency seconds
126                                                                                                                                                         // for level_shake_duration seconds (on average, random).  In 16ths second.
127         int             secret_return_segment;
128         vms_matrix      secret_return_orient;
129
130         int             dl_indices_offset;
131         int             dl_indices_howmany;
132         int             dl_indices_sizeof;
133
134         int             delta_light_offset;
135         int             delta_light_howmany;
136         int             delta_light_sizeof;
137
138 };
139
140 int CreateDefaultNewSegment();
141
142 #ifdef EDITOR
143
144 static char old_tmap_list[MAX_TEXTURES][FILENAME_LEN];
145 short tmap_xlate_table[MAX_TEXTURES];
146 static short tmap_times_used[MAX_TEXTURES];
147
148 // -----------------------------------------------------------------------------
149 //loads from an already-open file
150 // returns 0=everything ok, 1=old version, -1=error
151 int load_mine_data(CFILE *LoadFile)
152 {
153         int   i, j,oldsizeadjust;
154         short tmap_xlate;
155         int     translate;
156         char    *temptr;
157         int     mine_start = cftell(LoadFile);
158
159         oldsizeadjust=(sizeof(int)*2)+sizeof (vms_matrix);
160         fuelcen_reset();
161
162         for (i=0; i<MAX_TEXTURES; i++ )
163                 tmap_times_used[i] = 0;
164
165         #ifdef EDITOR
166         // Create a new mine to initialize things.
167         //texpage_goto_first();
168         create_new_mine();
169         #endif
170
171         //===================== READ FILE INFO ========================
172
173         // These are the default values... version and fileinfo_sizeof
174         // don't have defaults.
175         mine_fileinfo.header_offset     =   -1;
176         mine_fileinfo.header_size       =   sizeof(mine_header);
177         mine_fileinfo.editor_offset     =   -1;
178         mine_fileinfo.editor_size       =   sizeof(mine_editor);
179         mine_fileinfo.vertex_offset     =   -1;
180         mine_fileinfo.vertex_howmany    =   0;
181         mine_fileinfo.vertex_sizeof     =   sizeof(vms_vector);
182         mine_fileinfo.segment_offset    =   -1;
183         mine_fileinfo.segment_howmany   =   0;
184         mine_fileinfo.segment_sizeof    =   sizeof(segment);
185         mine_fileinfo.newseg_verts_offset     =   -1;
186         mine_fileinfo.newseg_verts_howmany    =   0;
187         mine_fileinfo.newseg_verts_sizeof     =   sizeof(vms_vector);
188         mine_fileinfo.group_offset                =     -1;
189         mine_fileinfo.group_howmany       =     0;
190         mine_fileinfo.group_sizeof                =     sizeof(group);
191         mine_fileinfo.texture_offset    =   -1;
192         mine_fileinfo.texture_howmany   =   0;
193         mine_fileinfo.texture_sizeof    =   FILENAME_LEN;  // num characters in a name
194         mine_fileinfo.walls_offset                =     -1;
195         mine_fileinfo.walls_howmany       =     0;
196         mine_fileinfo.walls_sizeof                =     sizeof(wall);  
197         mine_fileinfo.triggers_offset     =     -1;
198         mine_fileinfo.triggers_howmany  =       0;
199         mine_fileinfo.triggers_sizeof     =     sizeof(trigger);  
200         mine_fileinfo.object_offset             =       -1;
201         mine_fileinfo.object_howmany            =       1;
202         mine_fileinfo.object_sizeof             =       sizeof(object);  
203
204         mine_fileinfo.level_shake_frequency             =       0;
205         mine_fileinfo.level_shake_duration              =       0;
206
207         //      Delta light stuff for blowing out light sources.
208 //      if (mine_top_fileinfo.fileinfo_version >= 19) {
209                 mine_fileinfo.dl_indices_offset         =       -1;
210                 mine_fileinfo.dl_indices_howmany                =       0;
211                 mine_fileinfo.dl_indices_sizeof         =       sizeof(dl_index);  
212
213                 mine_fileinfo.delta_light_offset                =       -1;
214                 mine_fileinfo.delta_light_howmany               =       0;
215                 mine_fileinfo.delta_light_sizeof                =       sizeof(delta_light);  
216
217 //      }
218
219         mine_fileinfo.segment2_offset           = -1;
220         mine_fileinfo.segment2_howmany  = 0;
221         mine_fileinfo.segment2_sizeof    = sizeof(segment2);
222
223         // Read in mine_top_fileinfo to get size of saved fileinfo.
224         
225         memset( &mine_top_fileinfo, 0, sizeof(mine_top_fileinfo) );
226
227         if (cfseek( LoadFile, mine_start, SEEK_SET ))
228                 Error( "Error moving to top of file in gamemine.c" );
229
230         if (cfread( &mine_top_fileinfo, sizeof(mine_top_fileinfo), 1, LoadFile )!=1)
231                 Error( "Error reading mine_top_fileinfo in gamemine.c" );
232
233         if (mine_top_fileinfo.fileinfo_signature != 0x2884)
234                 return -1;
235
236         // Check version number
237         if (mine_top_fileinfo.fileinfo_version < COMPATIBLE_VERSION )
238                 return -1;
239
240         // Now, Read in the fileinfo
241         if (cfseek( LoadFile, mine_start, SEEK_SET ))
242                 Error( "Error seeking to top of file in gamemine.c" );
243
244         if (cfread( &mine_fileinfo, mine_top_fileinfo.fileinfo_sizeof, 1, LoadFile )!=1)
245                 Error( "Error reading mine_fileinfo in gamemine.c" );
246
247         if (mine_top_fileinfo.fileinfo_version < 18) {
248                 mprintf((1, "Old version, setting shake intensity to 0.\n"));
249                 Level_shake_frequency = 0;
250                 Level_shake_duration = 0;
251                 Secret_return_segment = 0;
252                 Secret_return_orient = vmd_identity_matrix;
253         } else {
254                 Level_shake_frequency = mine_fileinfo.level_shake_frequency << 12;
255                 Level_shake_duration = mine_fileinfo.level_shake_duration << 12;
256                 Secret_return_segment = mine_fileinfo.secret_return_segment;
257                 Secret_return_orient = mine_fileinfo.secret_return_orient;
258         }
259
260         //===================== READ HEADER INFO ========================
261
262         // Set default values.
263         mine_header.num_vertices        =   0;
264         mine_header.num_segments        =   0;
265
266         if (mine_fileinfo.header_offset > -1 )
267         {
268                 if (cfseek( LoadFile, mine_fileinfo.header_offset, SEEK_SET ))
269                         Error( "Error seeking to header_offset in gamemine.c" );
270         
271                 if (cfread( &mine_header, mine_fileinfo.header_size, 1, LoadFile )!=1)
272                         Error( "Error reading mine_header in gamemine.c" );
273         }
274
275         //===================== READ EDITOR INFO ==========================
276
277         // Set default values
278         mine_editor.current_seg         =   0;
279         mine_editor.newsegment_offset   =   -1; // To be written
280         mine_editor.newsegment_size     =   sizeof(segment);
281         mine_editor.Curside             =   0;
282         mine_editor.Markedsegp          =   -1;
283         mine_editor.Markedside          =   0;
284
285         if (mine_fileinfo.editor_offset > -1 )
286         {
287                 if (cfseek( LoadFile, mine_fileinfo.editor_offset, SEEK_SET ))
288                         Error( "Error seeking to editor_offset in gamemine.c" );
289         
290                 if (cfread( &mine_editor, mine_fileinfo.editor_size, 1, LoadFile )!=1)
291                         Error( "Error reading mine_editor in gamemine.c" );
292         }
293
294         //===================== READ TEXTURE INFO ==========================
295
296         if ( (mine_fileinfo.texture_offset > -1) && (mine_fileinfo.texture_howmany > 0))
297         {
298                 if (cfseek( LoadFile, mine_fileinfo.texture_offset, SEEK_SET ))
299                         Error( "Error seeking to texture_offset in gamemine.c" );
300
301                 for (i=0; i< mine_fileinfo.texture_howmany; i++ )
302                 {
303                         if (cfread( &old_tmap_list[i], mine_fileinfo.texture_sizeof, 1, LoadFile )!=1)
304                                 Error( "Error reading old_tmap_list[i] in gamemine.c" );
305                 }
306         }
307
308         //=============== GENERATE TEXTURE TRANSLATION TABLE ===============
309
310         translate = 0;
311         
312         Assert (NumTextures < MAX_TEXTURES);
313
314         {
315                 hashtable ht;
316         
317                 hashtable_init( &ht, NumTextures );
318         
319                 // Remove all the file extensions in the textures list
320         
321                 for (i=0;i<NumTextures;i++)     {
322                         temptr = strchr(TmapInfo[i].filename, '.');
323                         if (temptr) *temptr = '\0';
324                         hashtable_insert( &ht, TmapInfo[i].filename, i );
325                 }
326         
327                 // For every texture, search through the texture list
328                 // to find a matching name.
329                 for (j=0;j<mine_fileinfo.texture_howmany;j++)   {
330                         // Remove this texture name's extension
331                         temptr = strchr(old_tmap_list[j], '.');
332                         if (temptr) *temptr = '\0';
333         
334                         tmap_xlate_table[j] = hashtable_search( &ht,old_tmap_list[j]);
335                         if (tmap_xlate_table[j] < 0 )   {
336                                 //tmap_xlate_table[j] = 0;
337                                 // mprintf( (0, "Couldn't find texture '%s'\n", old_tmap_list[j] ));
338                                 ;
339                         }
340                         if (tmap_xlate_table[j] != j ) translate = 1;
341                         if (tmap_xlate_table[j] >= 0)
342                                 tmap_times_used[tmap_xlate_table[j]]++;
343                 }
344         
345                 {
346                         int count = 0;
347                         for (i=0; i<MAX_TEXTURES; i++ )
348                                 if (tmap_times_used[i])
349                                         count++;
350                         mprintf( (0, "This mine has %d unique textures in it (~%d KB)\n", count, (count*4096) /1024 ));
351                 }
352         
353                 // -- mprintf( (0, "Translate=%d\n", translate ));
354         
355                 hashtable_free( &ht );
356         }
357
358         //====================== READ VERTEX INFO ==========================
359
360         // New check added to make sure we don't read in too many vertices.
361         if ( mine_fileinfo.vertex_howmany > MAX_VERTICES )
362                 {
363                 mprintf((0, "Num vertices exceeds maximum.  Loading MAX %d vertices\n", MAX_VERTICES));
364                 mine_fileinfo.vertex_howmany = MAX_VERTICES;
365                 }
366
367         if ( (mine_fileinfo.vertex_offset > -1) && (mine_fileinfo.vertex_howmany > 0))
368         {
369                 if (cfseek( LoadFile, mine_fileinfo.vertex_offset, SEEK_SET ))
370                         Error( "Error seeking to vertex_offset in gamemine.c" );
371
372                 for (i=0; i< mine_fileinfo.vertex_howmany; i++ )
373                 {
374                         // Set the default values for this vertex
375                         Vertices[i].x = 1;
376                         Vertices[i].y = 1;
377                         Vertices[i].z = 1;
378
379                         if (cfread( &Vertices[i], mine_fileinfo.vertex_sizeof, 1, LoadFile )!=1)
380                                 Error( "Error reading Vertices[i] in gamemine.c" );
381                 }
382         }
383
384         //==================== READ SEGMENT INFO ===========================
385
386         // New check added to make sure we don't read in too many segments.
387         if ( mine_fileinfo.segment_howmany > MAX_SEGMENTS ) {
388                 mprintf((0, "Num segments exceeds maximum.  Loading MAX %d segments\n", MAX_SEGMENTS));
389                 mine_fileinfo.segment_howmany = MAX_SEGMENTS;
390                 mine_fileinfo.segment2_howmany = MAX_SEGMENTS;
391         }
392
393         // [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();
394
395         if ( (mine_fileinfo.segment_offset > -1) && (mine_fileinfo.segment_howmany > 0))        {
396
397                 if (cfseek( LoadFile, mine_fileinfo.segment_offset,SEEK_SET ))
398
399                         Error( "Error seeking to segment_offset in gamemine.c" );
400
401                 Highest_segment_index = mine_fileinfo.segment_howmany-1;
402
403                 for (i=0; i< mine_fileinfo.segment_howmany; i++ ) {
404
405                         // Set the default values for this segment (clear to zero )
406                         //memset( &Segments[i], 0, sizeof(segment) );
407
408                         if (mine_top_fileinfo.fileinfo_version < 20) {
409                                 v16_segment v16_seg;
410
411                                 Assert(mine_fileinfo.segment_sizeof == sizeof(v16_seg));
412
413                                 if (cfread( &v16_seg, mine_fileinfo.segment_sizeof, 1, LoadFile )!=1)
414                                         Error( "Error reading segments in gamemine.c" );
415
416                                 #ifdef EDITOR
417                                 Segments[i].segnum = v16_seg.segnum;
418                                 // -- Segments[i].pad = v16_seg.pad;
419                                 #endif
420
421                                 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
422                                         Segments[i].sides[j] = v16_seg.sides[j];
423
424                                 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
425                                         Segments[i].children[j] = v16_seg.children[j];
426
427                                 for (j=0; j<MAX_VERTICES_PER_SEGMENT; j++)
428                                         Segments[i].verts[j] = v16_seg.verts[j];
429
430                                 Segment2s[i].special = v16_seg.special;
431                                 Segment2s[i].value = v16_seg.value;
432                                 Segment2s[i].s2_flags = 0;
433                                 Segment2s[i].matcen_num = v16_seg.matcen_num;
434                                 Segment2s[i].static_light = v16_seg.static_light;
435                                 fuelcen_activate( &Segments[i], Segment2s[i].special );
436
437                         } else  {
438                                 if (cfread( &Segments[i], mine_fileinfo.segment_sizeof, 1, LoadFile )!=1)
439                                         Error("Unable to read segment %i\n", i);
440                         }
441
442                         Segments[i].objects = -1;
443                         #ifdef EDITOR
444                         Segments[i].group = -1;
445                         #endif
446
447                         if (mine_top_fileinfo.fileinfo_version < 15) {  //used old uvl ranges
448                                 int sn,uvln;
449
450                                 for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++)
451                                         for (uvln=0;uvln<4;uvln++) {
452                                                 Segments[i].sides[sn].uvls[uvln].u /= 64;
453                                                 Segments[i].sides[sn].uvls[uvln].v /= 64;
454                                                 Segments[i].sides[sn].uvls[uvln].l /= 32;
455                                         }
456                         }
457
458                         if (translate == 1)
459                                 for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) {
460                                         unsigned short orient;
461                                         tmap_xlate = Segments[i].sides[j].tmap_num;
462                                         Segments[i].sides[j].tmap_num = tmap_xlate_table[tmap_xlate];
463                                         if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG))
464                                                 if (Segments[i].sides[j].tmap_num < 0)  {
465                                                         mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j));
466                                                         Int3();
467                                                         Segments[i].sides[j].tmap_num = NumTextures-1;
468                                                 }
469                                         tmap_xlate = Segments[i].sides[j].tmap_num2 & 0x3FFF;
470                                         orient = Segments[i].sides[j].tmap_num2 & (~0x3FFF);
471                                         if (tmap_xlate != 0) {
472                                                 int xlated_tmap = tmap_xlate_table[tmap_xlate];
473
474                                                 if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG))
475                                                         if (xlated_tmap <= 0)   {
476                                                                 mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j));
477                                                                 Int3();
478                                                                 Segments[i].sides[j].tmap_num2 = NumTextures-1;
479                                                         }
480                                                 Segments[i].sides[j].tmap_num2 = xlated_tmap | orient;
481                                         }
482                                 }
483                 }
484
485
486                 if (mine_top_fileinfo.fileinfo_version >= 20)
487                         for (i=0; i<=Highest_segment_index; i++) {
488                                 cfread(&Segment2s[i], sizeof(segment2), 1, LoadFile);
489                                 fuelcen_activate( &Segments[i], Segment2s[i].special );
490                         }
491         }
492
493         //===================== READ NEWSEGMENT INFO =====================
494
495         #ifdef EDITOR
496
497         {               // Default segment created.
498                 vms_vector      sizevec;
499                 med_create_new_segment(vm_vec_make(&sizevec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE));             // New_segment = Segments[0];
500                 //memset( &New_segment, 0, sizeof(segment) );
501         }
502
503         if (mine_editor.newsegment_offset > -1)
504         {
505                 if (cfseek( LoadFile, mine_editor.newsegment_offset,SEEK_SET ))
506                         Error( "Error seeking to newsegment_offset in gamemine.c" );
507                 if (cfread( &New_segment, mine_editor.newsegment_size,1,LoadFile )!=1)
508                         Error( "Error reading new_segment in gamemine.c" );
509         }
510
511         if ( (mine_fileinfo.newseg_verts_offset > -1) && (mine_fileinfo.newseg_verts_howmany > 0))
512         {
513                 if (cfseek( LoadFile, mine_fileinfo.newseg_verts_offset, SEEK_SET ))
514                         Error( "Error seeking to newseg_verts_offset in gamemine.c" );
515                 for (i=0; i< mine_fileinfo.newseg_verts_howmany; i++ )
516                 {
517                         // Set the default values for this vertex
518                         Vertices[NEW_SEGMENT_VERTICES+i].x = 1;
519                         Vertices[NEW_SEGMENT_VERTICES+i].y = 1;
520                         Vertices[NEW_SEGMENT_VERTICES+i].z = 1;
521                         
522                         if (cfread( &Vertices[NEW_SEGMENT_VERTICES+i], mine_fileinfo.newseg_verts_sizeof,1,LoadFile )!=1)
523                                 Error( "Error reading Vertices[NEW_SEGMENT_VERTICES+i] in gamemine.c" );
524
525                         New_segment.verts[i] = NEW_SEGMENT_VERTICES+i;
526                 }
527         }
528
529         #endif
530                                                                                                                         
531         //========================= UPDATE VARIABLES ======================
532
533         #ifdef EDITOR
534
535         // Setting to Markedsegp to NULL ignores Curside and Markedside, which
536         // we want to do when reading in an old file.
537         
538         Markedside = mine_editor.Markedside;
539         Curside = mine_editor.Curside;
540         for (i=0;i<10;i++)
541                 Groupside[i] = mine_editor.Groupside[i];
542
543         if ( mine_editor.current_seg != -1 )
544                 Cursegp = mine_editor.current_seg + Segments;
545         else
546                 Cursegp = NULL;
547
548         if (mine_editor.Markedsegp != -1 ) 
549                 Markedsegp = mine_editor.Markedsegp + Segments;
550         else
551                 Markedsegp = NULL;
552
553         num_groups = 0;
554         current_group = -1;
555
556         #endif
557
558         Num_vertices = mine_fileinfo.vertex_howmany;
559         Num_segments = mine_fileinfo.segment_howmany;
560         Highest_vertex_index = Num_vertices-1;
561         Highest_segment_index = Num_segments-1;
562
563         reset_objects(1);               //one object, the player
564
565         #ifdef EDITOR
566         Highest_vertex_index = MAX_SEGMENT_VERTICES-1;
567         Highest_segment_index = MAX_SEGMENTS-1;
568         set_vertex_counts();
569         Highest_vertex_index = Num_vertices-1;
570         Highest_segment_index = Num_segments-1;
571
572         warn_if_concave_segments();
573         #endif
574
575         #ifdef EDITOR
576                 validate_segment_all();
577         #endif
578
579         //create_local_segment_data();
580
581         //gamemine_find_textures();
582
583         if (mine_top_fileinfo.fileinfo_version < MINE_VERSION )
584                 return 1;               //old version
585         else
586                 return 0;
587
588 }
589 #endif
590
591 #define COMPILED_MINE_VERSION 0
592
593 void read_children(int segnum,ubyte bit_mask,CFILE *LoadFile)
594 {
595         int bit;
596
597         for (bit=0; bit<MAX_SIDES_PER_SEGMENT; bit++) {
598                 if (bit_mask & (1 << bit)) {
599                         Segments[segnum].children[bit] = cfile_read_short(LoadFile);
600                 } else
601                         Segments[segnum].children[bit] = -1;
602         }
603 }
604
605 void read_verts(int segnum,CFILE *LoadFile)
606 {
607         int i;
608         // Read short Segments[segnum].verts[MAX_VERTICES_PER_SEGMENT]
609         for (i = 0; i < MAX_VERTICES_PER_SEGMENT; i++)
610                 Segments[segnum].verts[i] = cfile_read_short(LoadFile);
611 }
612
613 void read_special(int segnum,ubyte bit_mask,CFILE *LoadFile)
614 {
615         if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT)) {
616                 // Read ubyte   Segment2s[segnum].special
617                 Segment2s[segnum].special = cfile_read_byte(LoadFile);
618                 // Read byte    Segment2s[segnum].matcen_num
619                 Segment2s[segnum].matcen_num = cfile_read_byte(LoadFile);
620                 // Read short   Segment2s[segnum].value
621                 Segment2s[segnum].value = cfile_read_short(LoadFile);
622         } else {
623                 Segment2s[segnum].special = 0;
624                 Segment2s[segnum].matcen_num = -1;
625                 Segment2s[segnum].value = 0;
626         }
627 }
628
629 int load_mine_data_compiled(CFILE *LoadFile, int file_version)
630 {
631         int     i, segnum, sidenum;
632         ubyte   compiled_version;
633         short   temp_short;
634         ushort  temp_ushort;
635         ubyte   bit_mask;
636
637         //      For compiled levels, textures map to themselves, prevent tmap_override always being gray,
638         //      bug which Matt and John refused to acknowledge, so here is Mike, fixing it.
639 #ifdef EDITOR
640         for (i=0; i<MAX_TEXTURES; i++)
641                 tmap_xlate_table[i] = i;
642 #endif
643
644 //      memset( Segments, 0, sizeof(segment)*MAX_SEGMENTS );
645         fuelcen_reset();
646
647         //=============================== Reading part ==============================
648         compiled_version = cfile_read_byte(LoadFile);
649         Assert( compiled_version==COMPILED_MINE_VERSION );
650
651         Num_vertices = cfile_read_short(LoadFile);
652         Assert( Num_vertices <= MAX_VERTICES );
653
654         Num_segments = cfile_read_short(LoadFile);
655         Assert( Num_segments <= MAX_SEGMENTS );
656
657         for (i = 0; i < Num_vertices; i++)
658                 cfile_read_vector( &(Vertices[i]), LoadFile);
659
660         for (segnum=0; segnum<Num_segments; segnum++ )  {
661
662                 #ifdef EDITOR
663                 Segments[segnum].segnum = segnum;
664                 Segments[segnum].group = 0;
665                 #endif
666
667                 bit_mask = cfile_read_byte(LoadFile);
668
669 #if defined(SHAREWARE) && !defined(MACINTOSH)
670                 read_special(segnum,bit_mask,LoadFile);
671                 read_verts(segnum,LoadFile);
672                 read_children(segnum,bit_mask,LoadFile);
673 #else
674                 read_children(segnum,bit_mask,LoadFile);
675                 read_verts(segnum,LoadFile);
676                 if (file_version <= 1) { // descent 1 level
677                         read_special(segnum,bit_mask,LoadFile);
678                 }
679 #endif
680
681                 Segments[segnum].objects = -1;
682
683 #ifndef SHAREWARE
684                 if (file_version <= 1) { // descent 1 level
685 #endif
686                         // Read fix     Segments[segnum].static_light (shift down 5 bits, write as short)
687                         temp_ushort = cfile_read_short(LoadFile);
688                         Segment2s[segnum].static_light  = ((fix)temp_ushort) << 4;
689                         //cfread( &Segments[segnum].static_light, sizeof(fix), 1, LoadFile );
690 #ifndef SHAREWARE
691                 }
692 #endif
693
694                 // Read the walls as a 6 byte array
695                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ )      {
696                         Segments[segnum].sides[sidenum].pad = 0;
697                 }
698
699                 bit_mask = cfile_read_byte(LoadFile);
700                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
701                         ubyte byte_wallnum;
702
703                         if (bit_mask & (1 << sidenum)) {
704                                 byte_wallnum = cfile_read_byte(LoadFile);
705                                 if ( byte_wallnum == 255 )
706                                         Segments[segnum].sides[sidenum].wall_num = -1;
707                                 else
708                                         Segments[segnum].sides[sidenum].wall_num = byte_wallnum;
709                         } else
710                                         Segments[segnum].sides[sidenum].wall_num = -1;
711                 }
712
713                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ )      {
714
715                         if ( (Segments[segnum].children[sidenum]==-1) || (Segments[segnum].sides[sidenum].wall_num!=-1) )       {
716                                 // Read short Segments[segnum].sides[sidenum].tmap_num;
717                                 temp_ushort = cfile_read_short(LoadFile);
718                                 Segments[segnum].sides[sidenum].tmap_num = temp_ushort & 0x7fff;
719
720                                 if (!(temp_ushort & 0x8000))
721                                         Segments[segnum].sides[sidenum].tmap_num2 = 0;
722                                 else {
723                                         // Read short Segments[segnum].sides[sidenum].tmap_num2;
724                                         Segments[segnum].sides[sidenum].tmap_num2 = cfile_read_short(LoadFile);
725                                 }
726
727                                 // Read uvl Segments[segnum].sides[sidenum].uvls[4] (u,v>>5, write as short, l>>1 write as short)
728                                 for (i=0; i<4; i++ )    {
729                                         temp_short = cfile_read_short(LoadFile);
730                                         Segments[segnum].sides[sidenum].uvls[i].u = ((fix)temp_short) << 5;
731                                         temp_short = cfile_read_short(LoadFile);
732                                         Segments[segnum].sides[sidenum].uvls[i].v = ((fix)temp_short) << 5;
733                                         temp_ushort = cfile_read_short(LoadFile);
734                                         Segments[segnum].sides[sidenum].uvls[i].l = ((fix)temp_ushort) << 1;
735                                         //cfread( &Segments[segnum].sides[sidenum].uvls[i].l, sizeof(fix), 1, LoadFile );
736                                 }
737                         } else {
738                                 Segments[segnum].sides[sidenum].tmap_num = 0;
739                                 Segments[segnum].sides[sidenum].tmap_num2 = 0;
740                                 for (i=0; i<4; i++ )    {
741                                         Segments[segnum].sides[sidenum].uvls[i].u = 0;
742                                         Segments[segnum].sides[sidenum].uvls[i].v = 0;
743                                         Segments[segnum].sides[sidenum].uvls[i].l = 0;
744                                 }
745                         }
746                 }
747         }
748
749 #if 0
750         {
751                 FILE *fp;
752
753                 fp = fopen("segments.out", "wt");
754                 for (i = 0; i <= Highest_segment_index; i++) {
755                         side    sides[MAX_SIDES_PER_SEGMENT];   // 6 sides
756                         short   children[MAX_SIDES_PER_SEGMENT];        // indices of 6 children segments, front, left, top, right, bottom, back
757                         short   verts[MAX_VERTICES_PER_SEGMENT];        // vertex ids of 4 front and 4 back vertices
758                         int             objects;                                                                // pointer to objects in this segment
759
760                         for (j = 0; j < MAX_SIDES_PER_SEGMENT; j++) {
761                                 byte    type;                                                                   // replaces num_faces and tri_edge, 1 = quad, 2 = 0:2 triangulation, 3 = 1:3 triangulation
762                                 ubyte   pad;                                                                    //keep us longword alligned
763                                 short   wall_num;
764                                 short   tmap_num;
765                                 short   tmap_num2;
766                                 uvl             uvls[4];
767                                 vms_vector      normals[2];                                             // 2 normals, if quadrilateral, both the same.
768                                 fprintf(fp, "%d\n", Segments[i].sides[j].type);
769                                 fprintf(fp, "%d\n", Segments[i].sides[j].pad);
770                                 fprintf(fp, "%d\n", Segments[i].sides[j].wall_num);
771                                 fprintf(fp, "%d\n", Segments[i].tmap_num);
772
773                         }
774                         fclose(fp);
775                 }
776         }
777 #endif
778
779         Highest_vertex_index = Num_vertices-1;
780         Highest_segment_index = Num_segments-1;
781
782         validate_segment_all();                 // Fill in side type and normals.
783
784         for (i=0; i<Num_segments; i++) {
785 #ifndef SHAREWARE
786                 if (file_version > 1)
787                         segment2_read(&Segment2s[i], LoadFile);
788 #endif
789                 fuelcen_activate( &Segments[i], Segment2s[i].special );
790         }
791
792         reset_objects(1);               //one object, the player
793
794         return 0;
795 }