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