]> icculus.org git repositories - btb/d2x.git/blob - main/editor/mine.c
make sure the correct font is used (whoops)
[btb/d2x.git] / main / editor / mine.c
1 /* $Id: mine.c,v 1.9 2005-06-22 09:42:04 chris Exp $ */
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-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Mine specific editing functions, such as load_mine, save_mine
18  *
19  */
20
21 #ifdef RCS
22 static char rcsid[] = "$Id: mine.c,v 1.9 2005-06-22 09:42:04 chris Exp $";
23 #endif
24
25 #ifdef HAVE_CONFIG_H
26 #include "conf.h"
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <math.h>
32 #include <string.h>
33
34 #include "physfsx.h"
35 #include "nocfile.h"
36 #include "mono.h"
37 #include "key.h"
38 #include "gr.h"
39
40 #include "bm.h"                 // for MAX_TEXTURES
41
42 #include "inferno.h"
43 #include "segment.h"
44 #include "editor.h"
45 #include "error.h"
46 #include "textures.h"
47 #include "object.h"
48
49 #include "gamemine.h"
50 #include "gamesave.h"
51 #include "gameseg.h"
52
53 #include "ui.h"                 // Because texpage.h need UI_WINDOW type
54 #include "texpage.h"            // For texpage_goto_first
55                          
56 #include "medwall.h"
57 #include "switch.h"
58
59 #include "fuelcen.h"
60
61 #define REMOVE_EXT(s)  (*(strchr( (s), '.' ))='\0')
62
63 int CreateDefaultNewSegment();
64 int save_mine_data(CFILE * SaveFile);
65
66 static char      current_tmap_list[MAX_TEXTURES][13];
67
68 int     New_file_format_save = 1;
69
70 // Converts descent 2 texture numbers back to descent 1 texture numbers.
71 // Only works properly when the full Descent 1 texture set (descent.pig) is available.
72 short convert_to_d1_tmap_num(short tmap_num)
73 {
74         switch (tmap_num)
75         {
76                 case 137: return   0; // grey rock001
77                 case   0: return   1;
78                 case   1: return   3; // rock021
79                 case 270: return   6; // blue rock002
80                 case 271: return   7; // yellow rock265
81                 case   2: return   8; // rock004
82                 case 138: return   9; // purple (devil:179)
83                 case 272: return  10; // red rock006
84                 case 139: return  11;
85                 case 140: return  12; //devil:43
86                 case   3: return  13; // rock014
87                 case   4: return  14; // rock019
88                 case   5: return  15; // rock020
89                 case   6: return  16;
90                 case 141: return  17;
91                 case 129: return  18;
92                 case   7: return  19;
93                 case 142: return  20;
94                 case 143: return  21;
95                 case   8: return  22;
96                 case   9: return  23;
97                 case  10: return  24;
98                 case 144: return  25; //devil:35
99                 case  11: return  26;
100                 case  12: return  27;
101                 case 145: return  28; //devil:43
102                 //range handled by default case, returns 13..21 (- 16)
103                 case 163: return  38; //devil:27
104                 case 147: return  39; //31
105                 case  22: return  40;
106                 case 266: return  41;
107                 case  23: return  42;
108                 case  24: return  43;
109                 case 136: return  44; //devil:135
110                 case  25: return  45;
111                 case  26: return  46;
112                 case  27: return  47;
113                 case  28: return  48;
114                 case 146: return  49; //devil:60
115                 case 131: return  50; //devil:138
116                 case  29: return  51;
117                 case  30: return  52;
118                 case  31: return  53;
119                 case  32: return  54;
120                 case 165: return  55; //devil:193
121                 case  33: return  56;
122                 case 132: return  57; //devil:119
123                 // range handled by default case, returns 58..88 (+ 24)
124                 case 197: return  88; //devil:15
125                 // range handled by default case, returns 89..106 (- 25)
126                 case 167: return 132;
127                 // range handled by default case, returns 107..114 (- 26)
128                 case 148: return 141; //devil:106
129                 case 115: return 142;
130                 case 116: return 143;
131                 case 117: return 144;
132                 case 118: return 145;
133                 case 119: return 146;
134                 case 149: return 147;
135                 case 120: return 148;
136                 case 121: return 149;
137                 case 122: return 150;
138                 case 123: return 151;
139                 case 124: return 152;
140                 case 125: return 153; // rock263
141                 case 150: return 154;
142                 case 126: return 155; // rock269
143                 case 200: return 156; // metl002
144                 case 201: return 157; // metl003
145                 case 186: return 158; //devil:227
146                 case 190: return 159; //devil:246
147                 case 151: return 160;
148                 case 152: return 161; //devil:206
149                 case 202: return 162;
150                 case 203: return 163;
151                 case 204: return 164;
152                 case 205: return 165;
153                 case 206: return 166;
154                 case 153: return 167;
155                 case 154: return 168;
156                 case 155: return 169;
157                 case 156: return 170;//206;
158                 case 157: return 171;//227;
159                 case 207: return 172;
160                 case 208: return 173;
161                 case 158: return 174;
162                 case 159: return 175;
163                 // range handled by default case, returns 209..217 (+ 33)
164                 case 160: return 185;
165                 // range handled by default case, returns 218..224 (+ 32)
166                 case 161: return 193;
167                 case 162: return 194;//206;
168                 case 166: return 195;
169                 case 225: return 196;
170                 case 226: return 197;
171                 case 193: return 198;
172                 case 168: return 199; //devil:204
173                 case 169: return 200; //devil:204
174                 case 227: return 201;
175                 case 170: return 202; //devil:227
176                 // range handled by default case, returns 228..234 (+ 25)
177                 case 171: return 210; //devil:242
178                 case 172: return 211; //devil:240
179                 // range handled by default case, returns 235..242 (+ 23)
180                 case 173: return 220; //devil:240
181                 case 243: return 221;
182                 case 244: return 222;
183                 case 174: return 223;
184                 case 245: return 224;
185                 case 246: return 225;
186                 case 164: return 226;//247; matching names but not matching textures
187                 case 179: return 227; //devil:181
188                 case 196: return 228;//248; matching names but not matching textures
189                 case 175: return 229; //devil:66
190                 case 176: return 230; //devil:66
191                 // range handled by default case, returns 249..257 (+ 18)
192                 case 177: return 240; //devil:132
193                 case 130: return 241; //devil:131
194                 case 178: return 242; //devil:15
195                 case 180: return 243; //devil:38
196                 case 258: return 244;
197                 case 259: return 245;
198                 case 181: return 246; // grate metl127
199                 case 260: return 247;
200                 case 261: return 248;
201                 case 262: return 249;
202                 case 340: return 250; //  white doorframe metl126
203                 case 412: return 251; //    red doorframe metl133
204                 case 410: return 252; //   blue doorframe metl134
205                 case 411: return 253; // yellow doorframe metl135
206                 case 263: return 254; // metl136
207                 case 264: return 255; // metl139
208                 case 265: return 256; // metl140
209                 case 182: return 257;//246; brig001
210                 case 183: return 258;//246; brig002
211                 case 184: return 259;//246; brig003
212                 case 185: return 260;//246; brig004
213                 case 273: return 261; // exit01
214                 case 274: return 262; // exit02
215                 case 187: return 263; // ceil001
216                 case 275: return 264; // ceil002
217                 case 276: return 265; // ceil003
218                 case 188: return 266; //devil:291
219                 // range handled by default case, returns 277..291 (+ 10)
220                 case 293: return 282;
221                 case 189: return 283;
222                 case 295: return 284;
223                 case 296: return 285;
224                 case 298: return 286;
225                 // range handled by default case, returns 300..310 (+ 13)
226                 case 191: return 298; // devil:374 misc010
227                 // range handled by default case, returns 311..326 (+ 12)
228                 case 192: return 315; // bad producer misc044
229                 // range handled by default case,  returns  327..337 (+ 11)
230                 case 352: return 327; // arw01
231                 case 353: return 328; // misc17
232                 case 354: return 329; // fan01
233                 case 380: return 330; // mntr04
234                 case 379: return 331;//373; matching names but not matching textures
235                 case 355: return 332;//344; matching names but not matching textures
236                 case 409: return 333; // lava misc11 //devil:404
237                 case 356: return 334; // ctrl04
238                 case 357: return 335; // ctrl01
239                 case 358: return 336; // ctrl02
240                 case 359: return 337; // ctrl03
241                 case 360: return 338; // misc14
242                 case 361: return 339; // producer misc16
243                 case 362: return 340; // misc049
244                 case 364: return 341; // misc060
245                 case 363: return 342; // blown01
246                 case 366: return 343; // misc061
247                 case 365: return 344;
248                 case 368: return 345;
249                 case 376: return 346;
250                 case 370: return 347;
251                 case 367: return 348;
252                 case 372: return 349;
253                 case 369: return 350;
254                 case 374: return 351;//429; matching names but not matching textures
255                 case 375: return 352;//387; matching names but not matching textures
256                 case 371: return 353;
257                 case 377: return 354;//425; matching names but not matching textures
258                 case 408: return 355;
259                 case 378: return 356; // lava02
260                 case 383: return 357;//384; matching names but not matching textures
261                 case 384: return 358;//385; matching names but not matching textures
262                 case 385: return 359;//386; matching names but not matching textures
263                 case 386: return 360;
264                 case 387: return 361;
265                 case 194: return 362; // mntr04b (devil: -1)
266                 case 388: return 363;
267                 case 391: return 364;
268                 case 392: return 365;
269                 case 393: return 366;
270                 case 394: return 367;
271                 case 395: return 368;
272                 case 396: return 369;
273                 case 195: return 370; // mntr04d (devil: -1)
274                 // range 371..584 handled by default case (wall01 and door frames)
275                 default:
276                         // ranges:
277                         if (tmap_num >= 13 && tmap_num <= 21)
278                                 return tmap_num + 16;
279                         if (tmap_num >= 34 && tmap_num <= 63)
280                                 return tmap_num + 24;
281                         if (tmap_num >= 64 && tmap_num <= 106)
282                                 return tmap_num + 25;
283                         if (tmap_num >= 107 && tmap_num <= 114)
284                                 return tmap_num + 26;
285                         if (tmap_num >= 209 && tmap_num <= 217)
286                                 return tmap_num - 33;
287                         if (tmap_num >= 218 && tmap_num <= 224)
288                                 return tmap_num - 32;
289                         if (tmap_num >= 228 && tmap_num <= 234)
290                                 return tmap_num - 25;
291                         if (tmap_num >= 235 && tmap_num <= 242)
292                                 return tmap_num - 23;
293                         if (tmap_num >= 249 && tmap_num <= 257)
294                                 return tmap_num - 18;
295                         if (tmap_num >= 277 && tmap_num <= 291)
296                                 return tmap_num - 10;
297                         if (tmap_num >= 300 && tmap_num <= 310)
298                                 return tmap_num - 13;
299                         if (tmap_num >= 311 && tmap_num <= 326)
300                                 return tmap_num - 12;
301                         if (tmap_num >= 327 && tmap_num <= 337)
302                                 return tmap_num - 11; // matching names but not matching textures
303                         // wall01 and door frames:
304                         if (tmap_num > 434 && tmap_num < 731)
305                         {
306                                 if (New_file_format_save) return tmap_num - 64;
307                                 // d1 shareware needs special treatment:
308                                 if (tmap_num < 478) return tmap_num - 68;
309                                 if (tmap_num < 490) return tmap_num - 73;
310                                 if (tmap_num < 537) return tmap_num - 91;
311                                 if (tmap_num < 557) return tmap_num - 104;
312                                 if (tmap_num < 573) return tmap_num - 111;
313                                 if (tmap_num < 603) return tmap_num - 117;
314                                 if (tmap_num < 635) return tmap_num - 141;
315                                 if (tmap_num < 731) return tmap_num - 147;
316                         }
317                         { // handle rare case where orientation != 0
318                                 short tmap_num_part = tmap_num &  TMAP_NUM_MASK;
319                                 short orient = tmap_num & ~TMAP_NUM_MASK;
320                                 if (orient != 0)
321                                         return orient | convert_to_d1_tmap_num(tmap_num_part);
322                                 else
323                                 {
324                                         Warning("can't convert unknown texture #%d to descent 1.\n", tmap_num_part);
325                                         return tmap_num;
326                                 }
327                         }
328         }
329 }
330
331 // -----------------------------------------------------------------------------
332 // Save mine will:
333 // 1. Write file info, header info, editor info, vertex data, segment data,
334 //    and new_segment in that order, marking their file offset.
335 // 2. Go through all the fields and fill in the offset, size, and sizeof
336 //    values in the headers.
337
338 int med_save_mine(char * filename)
339 {
340         FILE * SaveFile;
341         char ErrorMessage[256];
342
343         SaveFile = cfopen( filename, CF_WRITE_MODE );
344         if (!SaveFile)
345         {
346 #if 0 //ndef __linux__
347                 char fname[20];
348                 _splitpath( filename, NULL, NULL, fname, NULL );
349
350                 sprintf( ErrorMessage, \
351                         "ERROR: Cannot write to '%s'.\nYou probably need to check out a locked\nversion of the file. You should save\nthis under a different filename, and then\ncheck out a locked copy by typing\n\'co -l %s.lvl'\nat the DOS prompt.\n" 
352                         , filename, fname);
353 #endif
354                 sprintf( ErrorMessage, "ERROR: Unable to open %s\n", filename );
355                 MessageBox( -2, -2, 1, ErrorMessage, "Ok" );
356                 return 1;
357         }
358
359         save_mine_data(SaveFile);
360         
361         //==================== CLOSE THE FILE =============================
362         cfclose(SaveFile);
363
364         return 0;
365
366 }
367
368 // -----------------------------------------------------------------------------
369 // saves to an already-open file
370 int save_mine_data(CFILE * SaveFile)
371 {
372         int  header_offset, editor_offset, vertex_offset, segment_offset, doors_offset, texture_offset, walls_offset, triggers_offset; //, links_offset;
373         int  newseg_verts_offset;
374         int  newsegment_offset;
375         int  i;
376
377         med_compress_mine();
378         warn_if_concave_segments();
379         
380         for (i=0;i<NumTextures;i++)
381                 strncpy(current_tmap_list[i], TmapInfo[i].filename, 13);
382
383         //=================== Calculate offsets into file ==================
384
385         header_offset = cftell(SaveFile) + sizeof(mine_fileinfo);
386         editor_offset = header_offset + sizeof(mine_header);
387         texture_offset = editor_offset + sizeof(mine_editor);
388         vertex_offset  = texture_offset + (13*NumTextures);
389         segment_offset = vertex_offset + (sizeof(vms_vector)*Num_vertices);
390         newsegment_offset = segment_offset + (sizeof(segment)*Num_segments);
391         newseg_verts_offset = newsegment_offset + sizeof(segment);
392         walls_offset = newseg_verts_offset + (sizeof(vms_vector)*8);
393         triggers_offset =       walls_offset + (sizeof(wall)*Num_walls);
394         doors_offset = triggers_offset + (sizeof(trigger)*Num_triggers);
395
396         //===================== SAVE FILE INFO ========================
397
398         mine_fileinfo.fileinfo_signature=       0x2884;
399         mine_fileinfo.fileinfo_version  =   MINE_VERSION;
400         mine_fileinfo.fileinfo_sizeof   =   sizeof(mine_fileinfo);
401         mine_fileinfo.header_offset     =   header_offset;
402         mine_fileinfo.header_size       =   sizeof(mine_header);
403         mine_fileinfo.editor_offset     =   editor_offset;
404         mine_fileinfo.editor_size       =   sizeof(mine_editor);
405         mine_fileinfo.vertex_offset     =   vertex_offset;
406         mine_fileinfo.vertex_howmany    =   Num_vertices;
407         mine_fileinfo.vertex_sizeof     =   sizeof(vms_vector);
408         mine_fileinfo.segment_offset    =   segment_offset;
409         mine_fileinfo.segment_howmany   =   Num_segments;
410         mine_fileinfo.segment_sizeof    =   sizeof(segment);
411         mine_fileinfo.newseg_verts_offset     =   newseg_verts_offset;
412         mine_fileinfo.newseg_verts_howmany    =   8;
413         mine_fileinfo.newseg_verts_sizeof     =   sizeof(vms_vector);
414         mine_fileinfo.texture_offset    =   texture_offset;
415         mine_fileinfo.texture_howmany   =   NumTextures;
416         mine_fileinfo.texture_sizeof    =   13;  // num characters in a name
417         mine_fileinfo.walls_offset                =     walls_offset;
418         mine_fileinfo.walls_howmany       =     Num_walls;
419         mine_fileinfo.walls_sizeof                =     sizeof(wall);  
420         mine_fileinfo.triggers_offset     =     triggers_offset;
421         mine_fileinfo.triggers_howmany  =       Num_triggers;
422         mine_fileinfo.triggers_sizeof     =     sizeof(trigger);  
423
424         // Write the fileinfo
425         cfwrite( &mine_fileinfo, sizeof(mine_fileinfo), 1, SaveFile );
426
427         //===================== SAVE HEADER INFO ========================
428
429         mine_header.num_vertices        =   Num_vertices;
430         mine_header.num_segments        =   Num_segments;
431
432         // Write the editor info
433         if (header_offset != cftell(SaveFile))
434                 Error( "OFFSETS WRONG IN MINE.C!" );
435
436         cfwrite( &mine_header, sizeof(mine_header), 1, SaveFile );
437
438         //===================== SAVE EDITOR INFO ==========================
439         mine_editor.current_seg         =   Cursegp - Segments;
440         mine_editor.newsegment_offset   =   newsegment_offset; 
441         mine_editor.newsegment_size     =   sizeof(segment);
442
443         // Next 3 vars added 10/07 by JAS
444         mine_editor.Curside             =   Curside;
445         if (Markedsegp)
446                 mine_editor.Markedsegp       =   Markedsegp - Segments;
447         else                                                                      
448                 mine_editor.Markedsegp       =   -1;
449         mine_editor.Markedside          =   Markedside;
450         for (i=0;i<10;i++)
451                 mine_editor.Groupsegp[i]          =     Groupsegp[i] - Segments;
452         for (i=0;i<10;i++)
453                 mine_editor.Groupside[i]     =  Groupside[i];
454
455         if (editor_offset != cftell(SaveFile))
456                 Error( "OFFSETS WRONG IN MINE.C!" );
457         cfwrite( &mine_editor, sizeof(mine_editor), 1, SaveFile );
458
459         //===================== SAVE TEXTURE INFO ==========================
460
461         if (texture_offset != cftell(SaveFile))
462                 Error( "OFFSETS WRONG IN MINE.C!" );
463         cfwrite( current_tmap_list, 13, NumTextures, SaveFile );
464         
465         //===================== SAVE VERTEX INFO ==========================
466
467         if (vertex_offset != cftell(SaveFile))
468                 Error( "OFFSETS WRONG IN MINE.C!" );
469         cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile );
470
471         //===================== SAVE SEGMENT INFO =========================
472
473         if (segment_offset != cftell(SaveFile))
474                 Error( "OFFSETS WRONG IN MINE.C!" );
475         cfwrite( Segments, sizeof(segment), Num_segments, SaveFile );
476
477         //===================== SAVE NEWSEGMENT INFO ======================
478
479         if (newsegment_offset != cftell(SaveFile))
480                 Error( "OFFSETS WRONG IN MINE.C!" );
481         cfwrite( &New_segment, sizeof(segment), 1, SaveFile );
482
483         if (newseg_verts_offset != cftell(SaveFile))
484                 Error( "OFFSETS WRONG IN MINE.C!" );
485         cfwrite( &Vertices[New_segment.verts[0]], sizeof(vms_vector), 8, SaveFile );
486
487         //==================== CLOSE THE FILE =============================
488
489         return 0;
490
491 }
492
493
494
495 #define COMPILED_MINE_VERSION 0
496
497 void dump_fix_as_short( fix value, int nbits, PHYSFS_file *SaveFile )
498 {
499         int int_value=0; 
500         short short_value;
501
502         int_value = (int)(value>>nbits);
503         if( int_value > 0x7fff ) {
504                 short_value = 0x7fff;
505                 mprintf((1, "Warning: Fix (%8x) won't fit in short.  Saturating to %8x.\n", int_value, short_value<<nbits));
506         }
507         else if( int_value < -0x7fff ) {
508                 short_value = -0x7fff;
509                 mprintf((1, "Warning: Fix (%8x) won't fit in short.  Saturating to %8x.\n", int_value, short_value<<nbits));
510         }
511         else
512                 short_value = (short)int_value;
513
514         PHYSFS_writeSLE16(SaveFile, short_value);
515 }
516
517 //version of dump for unsigned values
518 void dump_fix_as_ushort( fix value, int nbits, PHYSFS_file *SaveFile )
519 {
520         uint int_value=0;
521         ushort short_value;
522
523         if (value < 0) {
524                 mprintf((1, "Warning: fix (%8x) is signed...setting to zero.\n", value));
525                 Int3();         //hey---show this to Matt
526                 value = 0;
527         }
528         else
529                 int_value = value >> nbits;
530
531         if( int_value > 0xffff ) {
532                 short_value = 0xffff;
533                 mprintf((1, "Warning: Fix (%8x) won't fit in unsigned short.  Saturating to %8x.\n", int_value, short_value<<nbits));
534         }
535         else
536                 short_value = int_value;
537
538         PHYSFS_writeULE16(SaveFile, short_value);
539 }
540
541 void write_children(segment *seg, ubyte bit_mask, PHYSFS_file *SaveFile)
542 {
543         int bit;
544
545         for (bit = 0; bit < MAX_SIDES_PER_SEGMENT; bit++)
546         {
547                 if (bit_mask & (1 << bit))
548                         PHYSFS_writeSLE16(SaveFile, seg->children[bit]);
549         }
550 }
551
552 void write_verts(segment *seg, PHYSFS_file *SaveFile)
553 {
554         int i;
555
556         for (i = 0; i < MAX_VERTICES_PER_SEGMENT; i++)
557                 PHYSFS_writeSLE16(SaveFile, seg->verts[i]);
558 }
559
560 void write_special(segment2 *seg2, ubyte bit_mask, PHYSFS_file *SaveFile)
561 {
562         if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT))
563         {
564                 PHYSFSX_writeU8(SaveFile, seg2->special);
565                 PHYSFSX_writeU8(SaveFile, seg2->matcen_num);
566                 PHYSFS_writeSLE16(SaveFile, seg2->value);
567         }
568 }
569 // -----------------------------------------------------------------------------
570 // saves compiled mine data to an already-open file...
571 int save_mine_data_compiled(PHYSFS_file *SaveFile)
572 {
573         short           i, segnum, sidenum;
574         ubyte   version = COMPILED_MINE_VERSION;
575         ubyte           bit_mask = 0;
576
577         med_compress_mine();
578         warn_if_concave_segments();
579
580         if (Highest_segment_index >= MAX_SEGMENTS) {
581                 char    message[128];
582                 sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_SEGMENTS);
583                 MessageBox( -2, -2, 1, message, "Ok" );
584         }
585
586         if (Highest_vertex_index >= MAX_VERTICES) {
587                 char    message[128];
588                 sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_VERTICES);
589                 MessageBox( -2, -2, 1, message, "Ok" );
590         }
591
592         //=============================== Writing part ==============================
593         PHYSFSX_writeU8(SaveFile, version);                                             // 1 byte = compiled version
594         if (New_file_format_save)
595         {
596                 PHYSFS_writeSLE16(SaveFile, Num_vertices);                                      // 2 bytes = Num_vertices
597                 PHYSFS_writeSLE16(SaveFile, Num_segments);                                      // 2 bytes = Num_segments
598         }
599         else
600         {
601                 PHYSFS_writeSLE32(SaveFile, Num_vertices);                                      // 4 bytes = Num_vertices
602                 PHYSFS_writeSLE32(SaveFile, Num_segments);                                      // 4 bytes = Num_segments
603         }
604
605         for (i = 0; i < Num_vertices; i++)
606                 PHYSFSX_writeVector(SaveFile, &(Vertices[i]));
607         
608         for (segnum = 0; segnum < Num_segments; segnum++)
609         {
610                 segment *seg = &Segments[segnum];
611                 segment2 *seg2 = &Segment2s[segnum];
612
613                 for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++)
614                 {
615                         if (seg->children[sidenum] != -1)
616                                 bit_mask |= (1 << sidenum);
617                 }
618
619                 if ((seg2->special != 0) || (seg2->matcen_num != 0) || (seg2->value != 0))
620                         bit_mask |= (1 << MAX_SIDES_PER_SEGMENT);
621
622                 if (New_file_format_save)
623                         PHYSFSX_writeU8(SaveFile, bit_mask);
624                 else
625                         bit_mask = 0x7F;
626
627                 if (Gamesave_current_version == 5)      // d2 SHAREWARE level
628                 {
629                         write_special(seg2, bit_mask, SaveFile);
630                         write_verts(seg, SaveFile);
631                         write_children(seg, bit_mask, SaveFile);
632                 }
633                 else
634                 {
635                         write_children(seg, bit_mask, SaveFile);
636                         write_verts(seg, SaveFile);
637                         if (Gamesave_current_version <= 1) // descent 1 level
638                                 write_special(seg2, bit_mask, SaveFile);
639                 }
640
641                 if (Gamesave_current_version <= 5) // descent 1 thru d2 SHAREWARE level
642                         dump_fix_as_ushort(seg2->static_light, 4, SaveFile);
643         
644                 // Write the walls as a 6 byte array
645                 bit_mask = 0;
646                 for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++)
647                 {
648                         uint wallnum;
649
650                         if (seg->sides[sidenum].wall_num >= 0)
651                         {
652                                 bit_mask |= (1 << sidenum);
653                                 wallnum = seg->sides[sidenum].wall_num;
654                                 Assert( wallnum < 255 );                // Get John or Mike.. can only store up to 255 walls!!! 
655                         }
656                 }
657                 if (New_file_format_save)
658                         PHYSFSX_writeU8(SaveFile, bit_mask);
659                 else
660                         bit_mask = 0x3F;
661
662                 for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++)
663                 {
664                         if (bit_mask & (1 << sidenum))
665                                 PHYSFSX_writeU8(SaveFile, seg->sides[sidenum].wall_num);
666                 }
667
668                 for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++)
669                 {
670                         if ((seg->children[sidenum] == -1) || (seg->sides[sidenum].wall_num != -1))
671                         {
672                                 ushort  tmap_num, tmap_num2;
673
674                                 tmap_num = seg->sides[sidenum].tmap_num;
675                                 tmap_num2 = seg->sides[sidenum].tmap_num2;
676
677                                 if (Gamesave_current_version <= 3)      // convert texture numbers back to d1
678                                 {
679                                         tmap_num = convert_to_d1_tmap_num(tmap_num);
680                                         if (tmap_num2)
681                                                 tmap_num2 = convert_to_d1_tmap_num(tmap_num2);
682                                 }
683
684                                 if (tmap_num2 != 0 && New_file_format_save)
685                                         tmap_num |= 0x8000;
686
687                                 PHYSFS_writeSLE16(SaveFile, tmap_num);
688                                 if (tmap_num2 != 0 || !New_file_format_save)
689                                         PHYSFS_writeSLE16(SaveFile, tmap_num2);
690
691                                 for (i = 0; i < 4; i++)
692                                 {
693                                         dump_fix_as_short(seg->sides[sidenum].uvls[i].u, 5, SaveFile);
694                                         dump_fix_as_short(seg->sides[sidenum].uvls[i].v, 5, SaveFile);
695                                         dump_fix_as_ushort(seg->sides[sidenum].uvls[i].l, 1, SaveFile);
696                                 }       
697                         }
698                 }
699
700         }
701
702         if (Gamesave_current_version > 5)
703                 for (i = 0; i < Num_segments; i++)
704                         segment2_write(&Segment2s[i], SaveFile);
705
706         return 0;
707 }
708
709