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