Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. /*
  21.  *
  22.  * Functions for loading mines in the game
  23.  *
  24.  */
  25.  
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <math.h>
  30. #include <string.h>
  31.  
  32. #include "pstypes.h"
  33. #include "inferno.h"
  34. #include "segment.h"
  35. #include "textures.h"
  36. #include "wall.h"
  37. #include "object.h"
  38. #include "gamemine.h"
  39. #include "dxxerror.h"
  40. #include "gameseg.h"
  41. #include "physfsx.h"
  42. #include "switch.h"
  43. #include "game.h"
  44. #include "newmenu.h"
  45. #if DXX_USE_EDITOR
  46. #include "editor/editor.h"
  47. #include "editor/esegment.h"
  48. #include "d_range.h"
  49. #endif
  50. #include "fuelcen.h"
  51. #include "hash.h"
  52. #include "key.h"
  53. #include "piggy.h"
  54. #include "gamesave.h"
  55. #include "compiler-poison.h"
  56. #include "compiler-range_for.h"
  57. #include "partial_range.h"
  58.  
  59. #define REMOVE_EXT(s)  (*(strchr( (s), '.' ))='\0')
  60.  
  61. int New_file_format_load = 1; // "new file format" is everything newer than d1 shareware
  62.  
  63. namespace dsx {
  64.  
  65. /*
  66.  * reads a segment2 structure from a PHYSFS_File
  67.  */
  68. static void segment2_read(const msmusegment s2, PHYSFS_File *fp)
  69. {
  70.         s2.s.special = PHYSFSX_readByte(fp);
  71.         s2.s.matcen_num = PHYSFSX_readByte(fp);
  72.         /* station_idx is overwritten by the caller in some cases, but set
  73.          * it here for compatibility with how the game previously worked */
  74.         s2.s.station_idx = PHYSFSX_readByte(fp);
  75.         const auto s2_flags = PHYSFSX_readByte(fp);
  76. #if defined(DXX_BUILD_DESCENT_I)
  77.         (void)s2_flags; // descent 2 ambient sound handling
  78.         if (s2.s.special >= MAX_CENTER_TYPES)
  79.                 s2.s.special = SEGMENT_IS_NOTHING; // remove goals etc.
  80. #elif defined(DXX_BUILD_DESCENT_II)
  81.         s2.s.s2_flags = s2_flags;
  82. #endif
  83.         s2.u.static_light = PHYSFSX_readFix(fp);
  84. }
  85.  
  86. #if defined(DXX_BUILD_DESCENT_I)
  87. #elif defined(DXX_BUILD_DESCENT_II)
  88.  
  89. int d1_pig_present = 0; // can descent.pig from descent 1 be loaded?
  90.  
  91. /* returns nonzero if d1_tmap_num references a texture which isn't available in d2. */
  92. int d1_tmap_num_unique(short d1_tmap_num) {
  93.         switch (d1_tmap_num) {
  94.         case   0: case   2: case   4: case   5: case   6: case   7: case   9:
  95.         case  10: case  11: case  12: case  17: case  18:
  96.         case  20: case  21: case  25: case  28:
  97.         case  38: case  39: case  41: case  44: case  49:
  98.         case  50: case  55: case  57: case  88:
  99.         case 132: case 141: case 147:
  100.         case 154: case 155: case 158: case 159:
  101.         case 160: case 161: case 167: case 168: case 169:
  102.         case 170: case 171: case 174: case 175: case 185:
  103.         case 193: case 194: case 195: case 198: case 199:
  104.         case 200: case 202: case 210: case 211:
  105.         case 220: case 226: case 227: case 228: case 229: case 230:
  106.         case 240: case 241: case 242: case 243: case 246:
  107.         case 250: case 251: case 252: case 253: case 257: case 258: case 259:
  108.         case 260: case 263: case 266: case 283: case 298:
  109.         case 315: case 317: case 319: case 320: case 321:
  110.         case 330: case 331: case 332: case 333: case 349:
  111.         case 351: case 352: case 353: case 354:
  112.         case 355: case 357: case 358: case 359:
  113.         case 362: case 370: return 1;
  114.         default: return 0;
  115.         }
  116. }
  117.  
  118. /* Converts descent 1 texture numbers to descent 2 texture numbers.
  119.  * Textures from d1 which are unique to d1 have extra spaces around "return".
  120.  * If we can load the original d1 pig, we make sure this function is bijective.
  121.  * This function was updated using the file config/convtabl.ini from devil 2.2.
  122.  */
  123. short convert_d1_tmap_num(short d1_tmap_num) {
  124.         switch (d1_tmap_num) {
  125.         case 0: case 2: case 4: case 5:
  126.                 // all refer to grey rock001 (exception to bijectivity rule)
  127.                 return  d1_pig_present ? 137 : 43; // (devil:95)
  128.         case   1: return 0;
  129.         case   3: return 1; // rock021
  130.         case   6:  return  270; // blue rock002
  131.         case   7:  return  271; // yellow rock265
  132.         case   8: return 2; // rock004
  133.         case   9:  return  d1_pig_present ? 138 : 62; // purple (devil:179)
  134.         case  10:  return  272; // red rock006
  135.         case  11:  return  d1_pig_present ? 139 : 117;
  136.         case  12:  return  d1_pig_present ? 140 : 12; //devil:43
  137.         case  13: return 3; // rock014
  138.         case  14: return 4; // rock019
  139.         case  15: return 5; // rock020
  140.         case  16: return 6;
  141.         case  17:  return  d1_pig_present ? 141 : 52;
  142.         case  18:  return  129;
  143.         case  19: return 7;
  144.         case  20:  return  d1_pig_present ? 142 : 22;
  145.         case  21:  return  d1_pig_present ? 143 : 9;
  146.         case  22: return 8;
  147.         case  23: return 9;
  148.         case  24: return 10;
  149.         case  25:  return  d1_pig_present ? 144 : 12; //devil:35
  150.         case  26: return 11;
  151.         case  27: return 12;
  152.         case  28:  return  d1_pig_present ? 145 : 11; //devil:43
  153.         //range handled by default case, returns 13..21 (- 16)
  154.         case  38:  return  163; //devil:27
  155.         case  39:  return  147; //31
  156.         case  40: return 22;
  157.         case  41:  return  266;
  158.         case  42: return 23;
  159.         case  43: return 24;
  160.         case  44:  return  136; //devil:135
  161.         case  45: return 25;
  162.         case  46: return 26;
  163.         case  47: return 27;
  164.         case  48: return 28;
  165.         case  49:  return  d1_pig_present ? 146 : 43; //devil:60
  166.         case  50:  return  131; //devil:138
  167.         case  51: return 29;
  168.         case  52: return 30;
  169.         case  53: return 31;
  170.         case  54: return 32;
  171.         case  55:  return  165; //devil:193
  172.         case  56: return 33;
  173.         case  57:  return  132; //devil:119
  174.         // range handled by default case, returns 34..63 (- 24)
  175.         case  88:  return  197; //devil:15
  176.         // range handled by default case, returns 64..106 (- 25)
  177.         case 132:  return  167;
  178.         // range handled by default case, returns 107..114 (- 26)
  179.         case 141:  return  d1_pig_present ? 148 : 110; //devil:106
  180.         case 142: return 115;
  181.         case 143: return 116;
  182.         case 144: return 117;
  183.         case 145: return 118;
  184.         case 146: return 119;
  185.         case 147:  return  d1_pig_present ? 149 : 93;
  186.         case 148: return 120;
  187.         case 149: return 121;
  188.         case 150: return 122;
  189.         case 151: return 123;
  190.         case 152: return 124;
  191.         case 153: return 125; // rock263
  192.         case 154:  return  d1_pig_present ? 150 : 27;
  193.         case 155:  return  126; // rock269
  194.         case 156: return 200; // metl002
  195.         case 157: return 201; // metl003
  196.         case 158:  return  186; //devil:227
  197.         case 159:  return  190; //devil:246
  198.         case 160:  return  d1_pig_present ? 151 : 206;
  199.         case 161:  return  d1_pig_present ? 152 : 114; //devil:206
  200.         case 162: return 202;
  201.         case 163: return 203;
  202.         case 164: return 204;
  203.         case 165: return 205;
  204.         case 166: return 206;
  205.         case 167:  return  d1_pig_present ? 153 : 206;
  206.         case 168:  return  d1_pig_present ? 154 : 206;
  207.         case 169:  return  d1_pig_present ? 155 : 206;
  208.         case 170:  return  d1_pig_present ? 156 : 227;//206;
  209.         case 171:  return  d1_pig_present ? 157 : 206;//227;
  210.         case 172: return 207;
  211.         case 173: return 208;
  212.         case 174:  return  d1_pig_present ? 158 : 202;
  213.         case 175:  return  d1_pig_present ? 159 : 206;
  214.         // range handled by default case, returns 209..217 (+ 33)
  215.         case 185:  return  d1_pig_present ? 160 : 217;
  216.         // range handled by default case, returns 218..224 (+ 32)
  217.         case 193:  return  d1_pig_present ? 161 : 206;
  218.         case 194:  return  d1_pig_present ? 162 : 203;//206;
  219.         case 195:  return  d1_pig_present ? 166 : 234;
  220.         case 196: return 225;
  221.         case 197: return 226;
  222.         case 198:  return  d1_pig_present ? 193 : 225;
  223.         case 199:  return  d1_pig_present ? 168 : 206; //devil:204
  224.         case 200:  return  d1_pig_present ? 169 : 206; //devil:204
  225.         case 201: return 227;
  226.         case 202:  return  d1_pig_present ? 170 : 206; //devil:227
  227.         // range handled by default case, returns 228..234 (+ 25)
  228.         case 210:  return  d1_pig_present ? 171 : 234; //devil:242
  229.         case 211:  return  d1_pig_present ? 172 : 206; //devil:240
  230.         // range handled by default case, returns 235..242 (+ 23)
  231.         case 220:  return  d1_pig_present ? 173 : 242; //devil:240
  232.         case 221: return 243;
  233.         case 222: return 244;
  234.         case 223:  return  d1_pig_present ? 174 : 313;
  235.         case 224: return 245;
  236.         case 225: return 246;
  237.         case 226:  return  164;//247; matching names but not matching textures
  238.         case 227:  return  179; //devil:181
  239.         case 228:  return  196;//248; matching names but not matching textures
  240.         case 229:  return  d1_pig_present ? 175 : 15; //devil:66
  241.         case 230:  return  d1_pig_present ? 176 : 15; //devil:66
  242.         // range handled by default case, returns 249..257 (+ 18)
  243.         case 240:  return  d1_pig_present ? 177 : 6; //devil:132
  244.         case 241:  return  130; //devil:131
  245.         case 242:  return  d1_pig_present ? 178 : 78; //devil:15
  246.         case 243:  return  d1_pig_present ? 180 : 33; //devil:38
  247.         case 244: return 258;
  248.         case 245: return 259;
  249.         case 246:  return  d1_pig_present ? 181 : 321; // grate metl127
  250.         case 247: return 260;
  251.         case 248: return 261;
  252.         case 249: return 262;
  253.         case 250:  return  340; //  white doorframe metl126
  254.         case 251:  return  412; //    red doorframe metl133
  255.         case 252:  return  410; //   blue doorframe metl134
  256.         case 253:  return  411; // yellow doorframe metl135
  257.         case 254: return 263; // metl136
  258.         case 255: return 264; // metl139
  259.         case 256: return 265; // metl140
  260.         case 257:  return  d1_pig_present ? 182 : 249;//246; brig001
  261.         case 258:  return  d1_pig_present ? 183 : 251;//246; brig002
  262.         case 259:  return  d1_pig_present ? 184 : 252;//246; brig003
  263.         case 260:  return  d1_pig_present ? 185 : 256;//246; brig004
  264.         case 261: return 273; // exit01
  265.         case 262: return 274; // exit02
  266.         case 263:  return  d1_pig_present ? 187 : 281; // ceil001
  267.         case 264: return 275; // ceil002
  268.         case 265: return 276; // ceil003
  269.         case 266:  return  d1_pig_present ? 188 : 279; //devil:291
  270.         // range handled by default case, returns 277..291 (+ 10)
  271.         case 282: return 293;
  272.         case 283:  return  d1_pig_present ? 189 : 295;
  273.         case 284: return 295;
  274.         case 285: return 296;
  275.         case 286: return 298;
  276.         // range handled by default case, returns 300..310 (+ 13)
  277.         case 298:  return  d1_pig_present ? 191 : 364; // devil:374 misc010
  278.         // range handled by default case, returns 311..326 (+ 12)
  279.         case 315:  return  d1_pig_present ? 192 : 361; // bad producer misc044
  280.         // range handled by default case,  returns  327..337 (+ 11)
  281.         case 327: return 352; // arw01
  282.         case 328: return 353; // misc17
  283.         case 329: return 354; // fan01
  284.         case 330:  return  380; // mntr04
  285.         case 331:  return  379;//373; matching names but not matching textures
  286.         case 332:  return  355;//344; matching names but not matching textures
  287.         case 333:  return  409; // lava misc11 //devil:404
  288.         case 334: return 356; // ctrl04
  289.         case 335: return 357; // ctrl01
  290.         case 336: return 358; // ctrl02
  291.         case 337: return 359; // ctrl03
  292.         case 338: return 360; // misc14
  293.         case 339: return 361; // producer misc16
  294.         case 340: return 362; // misc049
  295.         case 341: return 364; // misc060
  296.         case 342: return 363; // blown01
  297.         case 343: return 366; // misc061
  298.         case 344: return 365;
  299.         case 345: return 368;
  300.         case 346: return 376;
  301.         case 347: return 370;
  302.         case 348: return 367;
  303.         case 349:  return  372;
  304.         case 350: return 369;
  305.         case 351:  return  374;//429; matching names but not matching textures
  306.         case 352:  return  375;//387; matching names but not matching textures
  307.         case 353:  return  371;
  308.         case 354:  return  377;//425; matching names but not matching textures
  309.         case 355:  return  408;
  310.         case 356: return 378; // lava02
  311.         case 357:  return  383;//384; matching names but not matching textures
  312.         case 358:  return  384;//385; matching names but not matching textures
  313.         case 359:  return  385;//386; matching names but not matching textures
  314.         case 360: return 386;
  315.         case 361: return 387;
  316.         case 362:  return  d1_pig_present ? 194 : 388; // mntr04b (devil: -1)
  317.         case 363: return 388;
  318.         case 364: return 391;
  319.         case 365: return 392;
  320.         case 366: return 393;
  321.         case 367: return 394;
  322.         case 368: return 395;
  323.         case 369: return 396;
  324.         case 370:  return  d1_pig_present ? 195 : 392; // mntr04d (devil: -1)
  325.         // range 371..584 handled by default case (wall01 and door frames)
  326.         default:
  327.                 // ranges:
  328.                 if (d1_tmap_num >= 29 && d1_tmap_num <= 37)
  329.                         return d1_tmap_num - 16;
  330.                 if (d1_tmap_num >= 58 && d1_tmap_num <= 87)
  331.                         return d1_tmap_num - 24;
  332.                 if (d1_tmap_num >= 89 && d1_tmap_num <= 131)
  333.                         return d1_tmap_num - 25;
  334.                 if (d1_tmap_num >= 133 && d1_tmap_num <= 140)
  335.                         return d1_tmap_num - 26;
  336.                 if (d1_tmap_num >= 176 && d1_tmap_num <= 184)
  337.                         return d1_tmap_num + 33;
  338.                 if (d1_tmap_num >= 186 && d1_tmap_num <= 192)
  339.                         return d1_tmap_num + 32;
  340.                 if (d1_tmap_num >= 203 && d1_tmap_num <= 209)
  341.                         return d1_tmap_num + 25;
  342.                 if (d1_tmap_num >= 212 && d1_tmap_num <= 219)
  343.                         return d1_tmap_num + 23;
  344.                 if (d1_tmap_num >= 231 && d1_tmap_num <= 239)
  345.                         return d1_tmap_num + 18;
  346.                 if (d1_tmap_num >= 267 && d1_tmap_num <= 281)
  347.                         return d1_tmap_num + 10;
  348.                 if (d1_tmap_num >= 287 && d1_tmap_num <= 297)
  349.                         return d1_tmap_num + 13;
  350.                 if (d1_tmap_num >= 299 && d1_tmap_num <= 314)
  351.                         return d1_tmap_num + 12;
  352.                 if (d1_tmap_num >= 316 && d1_tmap_num <= 326)
  353.                          return  d1_tmap_num + 11; // matching names but not matching textures
  354.                 // wall01 and door frames:
  355.                 if (d1_tmap_num > 370 && d1_tmap_num < 584) {
  356.                         if (New_file_format_load) return d1_tmap_num + 64;
  357.                         // d1 shareware needs special treatment:
  358.                         if (d1_tmap_num < 410) return d1_tmap_num + 68;
  359.                         if (d1_tmap_num < 417) return d1_tmap_num + 73;
  360.                         if (d1_tmap_num < 446) return d1_tmap_num + 91;
  361.                         if (d1_tmap_num < 453) return d1_tmap_num + 104;
  362.                         if (d1_tmap_num < 462) return d1_tmap_num + 111;
  363.                         if (d1_tmap_num < 486) return d1_tmap_num + 117;
  364.                         if (d1_tmap_num < 494) return d1_tmap_num + 141;
  365.                         if (d1_tmap_num < 584) return d1_tmap_num + 147;
  366.                 }
  367.                 { // handle rare case where orientation != 0
  368.                         short tmap_num = d1_tmap_num &  TMAP_NUM_MASK;
  369.                         short orient = d1_tmap_num & ~TMAP_NUM_MASK;
  370.                         if (orient != 0) {
  371.                                 return orient | convert_d1_tmap_num(tmap_num);
  372.                         } else {
  373.                                 Warning("can't convert unknown descent 1 texture #%d.\n", tmap_num);
  374.                                 return d1_tmap_num;
  375.                         }
  376.                 }
  377.         }
  378. }
  379. #endif
  380.  
  381. }
  382.  
  383. #if DXX_USE_EDITOR
  384. namespace dsx {
  385. tmap_xlate_table_array tmap_xlate_table;
  386. }
  387. struct mtfi mine_top_fileinfo; // Should be same as first two fields below...
  388. struct mfi mine_fileinfo;
  389. struct mh mine_header;
  390. struct me mine_editor;
  391.  
  392. // -----------------------------------------------------------------------------
  393. //loads from an already-open file
  394. // returns 0=everything ok, 1=old version, -1=error
  395. namespace dsx {
  396. int load_mine_data(PHYSFS_File *LoadFile)
  397. {
  398.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  399.         auto &Vertices = LevelSharedVertexState.get_vertices();
  400.         auto &TmapInfo = LevelUniqueTmapInfoState.TmapInfo;
  401.         char old_tmap_list[MAX_TEXTURES][FILENAME_LEN];
  402.         int     translate;
  403.         char    *temptr;
  404.         int     mine_start = PHYSFS_tell(LoadFile);
  405.  
  406.         fuelcen_reset();
  407.  
  408. #if DXX_USE_EDITOR
  409.         // Create a new mine to initialize things.
  410.         //texpage_goto_first();
  411.         create_new_mine();
  412.         #endif
  413.  
  414.         //===================== READ FILE INFO ========================
  415.  
  416.         // These are the default values... version and fileinfo_sizeof
  417.         // don't have defaults.
  418.         mine_fileinfo.header_offset     =   -1;
  419.         mine_fileinfo.header_size       =   sizeof(mine_header);
  420.         mine_fileinfo.editor_offset     =   -1;
  421.         mine_fileinfo.editor_size       =   sizeof(mine_editor);
  422.         mine_fileinfo.vertex_offset     =   -1;
  423.         mine_fileinfo.vertex_howmany    =   0;
  424.         mine_fileinfo.vertex_sizeof     =   sizeof(vms_vector);
  425.         mine_fileinfo.segment_offset    =   -1;
  426.         mine_fileinfo.segment_howmany   =   0;
  427.         mine_fileinfo.segment_sizeof    =   sizeof(segment);
  428.         mine_fileinfo.newseg_verts_offset     =   -1;
  429.         mine_fileinfo.newseg_verts_howmany    =   0;
  430.         mine_fileinfo.newseg_verts_sizeof     =   sizeof(vms_vector);
  431.         mine_fileinfo.group_offset                =     -1;
  432.         mine_fileinfo.group_howmany       =     0;
  433.         mine_fileinfo.group_sizeof                =     sizeof(group);
  434.         mine_fileinfo.texture_offset    =   -1;
  435.         mine_fileinfo.texture_howmany   =   0;
  436.         mine_fileinfo.texture_sizeof    =   FILENAME_LEN;  // num characters in a name
  437.         mine_fileinfo.walls_offset                =     -1;
  438.         mine_fileinfo.walls_howmany       =     0;
  439.         mine_fileinfo.walls_sizeof                =     sizeof(wall);  
  440.         mine_fileinfo.triggers_offset     =     -1;
  441.         mine_fileinfo.triggers_howmany  =       0;
  442.         mine_fileinfo.triggers_sizeof     =     sizeof(trigger);  
  443.         mine_fileinfo.object_offset             =       -1;
  444.         mine_fileinfo.object_howmany            =       1;
  445.         mine_fileinfo.object_sizeof             =       sizeof(object);  
  446.  
  447. #if defined(DXX_BUILD_DESCENT_II)
  448.         mine_fileinfo.level_shake_frequency             =       0;
  449.         mine_fileinfo.level_shake_duration              =       0;
  450.  
  451.         //      Delta light stuff for blowing out light sources.
  452. //      if (mine_top_fileinfo.fileinfo_version >= 19) {
  453.                 mine_fileinfo.dl_indices_offset         =       -1;
  454.                 mine_fileinfo.dl_indices_howmany                =       0;
  455.                 mine_fileinfo.dl_indices_sizeof         =       sizeof(dl_index);  
  456.  
  457.                 mine_fileinfo.delta_light_offset                =       -1;
  458.                 mine_fileinfo.delta_light_howmany               =       0;
  459.                 mine_fileinfo.delta_light_sizeof                =       sizeof(delta_light);  
  460.  
  461. //      }
  462.  
  463.         mine_fileinfo.segment2_offset           = -1;
  464.         mine_fileinfo.segment2_howmany  = 0;
  465.         mine_fileinfo.segment2_sizeof    = 0;
  466. #endif
  467.  
  468.         // Read in mine_top_fileinfo to get size of saved fileinfo.
  469.        
  470.         mine_top_fileinfo = {};
  471.  
  472.         if (PHYSFSX_fseek( LoadFile, mine_start, SEEK_SET ))
  473.                 Error( "Error moving to top of file in gamemine.c" );
  474.  
  475.         if (PHYSFS_read( LoadFile, &mine_top_fileinfo, sizeof(mine_top_fileinfo), 1 )!=1)
  476.                 Error( "Error reading mine_top_fileinfo in gamemine.c" );
  477.  
  478.         if (mine_top_fileinfo.fileinfo_signature != 0x2884)
  479.                 return -1;
  480.  
  481.         // Check version number
  482.         if (mine_top_fileinfo.fileinfo_version < COMPATIBLE_VERSION )
  483.                 return -1;
  484.  
  485.         // Now, Read in the fileinfo
  486.         if (PHYSFSX_fseek( LoadFile, mine_start, SEEK_SET ))
  487.                 Error( "Error seeking to top of file in gamemine.c" );
  488.  
  489.         if (PHYSFS_read( LoadFile, &mine_fileinfo, mine_top_fileinfo.fileinfo_sizeof, 1 )!=1)
  490.                 Error( "Error reading mine_fileinfo in gamemine.c" );
  491.  
  492. #if defined(DXX_BUILD_DESCENT_II)
  493.         if (mine_top_fileinfo.fileinfo_version < 18) {
  494.                 LevelSharedSeismicState.Level_shake_frequency = 0;
  495.                 LevelSharedSeismicState.Level_shake_duration = 0;
  496.                 LevelSharedSegmentState.Secret_return_segment = segment_first;
  497.                 LevelSharedSegmentState.Secret_return_orient = vmd_identity_matrix;
  498.         } else {
  499.                 LevelSharedSeismicState.Level_shake_frequency = mine_fileinfo.level_shake_frequency << 12;
  500.                 LevelSharedSeismicState.Level_shake_duration = mine_fileinfo.level_shake_duration << 12;
  501.                 LevelSharedSegmentState.Secret_return_segment = mine_fileinfo.secret_return_segment;
  502.                 LevelSharedSegmentState.Secret_return_orient = mine_fileinfo.secret_return_orient;
  503.         }
  504. #endif
  505.  
  506.         //===================== READ HEADER INFO ========================
  507.  
  508.         // Set default values.
  509.         mine_header.num_vertices        =   0;
  510.         mine_header.num_segments        =   0;
  511.  
  512.         if (mine_fileinfo.header_offset > -1 )
  513.         {
  514.                 if (PHYSFSX_fseek( LoadFile, mine_fileinfo.header_offset, SEEK_SET ))
  515.                         Error( "Error seeking to header_offset in gamemine.c" );
  516.        
  517.                 if (PHYSFS_read( LoadFile, &mine_header, mine_fileinfo.header_size, 1 )!=1)
  518.                         Error( "Error reading mine_header in gamemine.c" );
  519.         }
  520.  
  521.         //===================== READ EDITOR INFO ==========================
  522.  
  523.         // Set default values
  524.         mine_editor.current_seg         =   0;
  525.         mine_editor.newsegment_offset   =   -1; // To be written
  526.         mine_editor.newsegment_size     =   sizeof(segment);
  527.         mine_editor.Curside             =   0;
  528.         mine_editor.Markedsegp          =   -1;
  529.         mine_editor.Markedside          =   0;
  530.  
  531.         if (mine_fileinfo.editor_offset > -1 )
  532.         {
  533.                 if (PHYSFSX_fseek( LoadFile, mine_fileinfo.editor_offset, SEEK_SET ))
  534.                         Error( "Error seeking to editor_offset in gamemine.c" );
  535.        
  536.                 if (PHYSFS_read( LoadFile, &mine_editor, mine_fileinfo.editor_size, 1 )!=1)
  537.                         Error( "Error reading mine_editor in gamemine.c" );
  538.         }
  539.  
  540.         //===================== READ TEXTURE INFO ==========================
  541.  
  542.         if ( (mine_fileinfo.texture_offset > -1) && (mine_fileinfo.texture_howmany > 0))
  543.         {
  544.                 if (PHYSFSX_fseek( LoadFile, mine_fileinfo.texture_offset, SEEK_SET ))
  545.                         Error( "Error seeking to texture_offset in gamemine.c" );
  546.  
  547.                 for (int i=0; i< mine_fileinfo.texture_howmany; i++ )
  548.                 {
  549.                         if (PHYSFS_read( LoadFile, &old_tmap_list[i], mine_fileinfo.texture_sizeof, 1 )!=1)
  550.                                 Error( "Error reading old_tmap_list[i] in gamemine.c" );
  551.                 }
  552.         }
  553.  
  554.         //=============== GENERATE TEXTURE TRANSLATION TABLE ===============
  555.  
  556.         translate = 0;
  557.        
  558.         Assert (NumTextures < MAX_TEXTURES);
  559.  
  560.         {
  561.                 hashtable ht;
  562.                 // Remove all the file extensions in the textures list
  563.        
  564.                 for (uint_fast32_t i = 0; i < NumTextures;i++)  {
  565.                         temptr = strchr(&TmapInfo[i].filename[0u], '.');
  566.                         if (temptr) *temptr = '\0';
  567.                         hashtable_insert( &ht, &TmapInfo[i].filename[0u], i );
  568.                 }
  569.        
  570.                 // For every texture, search through the texture list
  571.                 // to find a matching name.
  572.                 for (int j=0;j<mine_fileinfo.texture_howmany;j++) {
  573.                         // Remove this texture name's extension
  574.                         temptr = strchr(old_tmap_list[j], '.');
  575.                         if (temptr) *temptr = '\0';
  576.        
  577.                         tmap_xlate_table[j] = hashtable_search( &ht,old_tmap_list[j]);
  578.                         if (tmap_xlate_table[j] < 0 )   {
  579.                                 ;
  580.                         }
  581.                         if (tmap_xlate_table[j] != j ) translate = 1;
  582.                 }
  583.         }
  584.  
  585.         //====================== READ VERTEX INFO ==========================
  586.  
  587.         // New check added to make sure we don't read in too many vertices.
  588.         if ( mine_fileinfo.vertex_howmany > MAX_VERTICES )
  589.                 mine_fileinfo.vertex_howmany = MAX_VERTICES;
  590.  
  591.         if ( (mine_fileinfo.vertex_offset > -1) && (mine_fileinfo.vertex_howmany > 0))
  592.         {
  593.                 if (PHYSFSX_fseek( LoadFile, mine_fileinfo.vertex_offset, SEEK_SET ))
  594.                         Error( "Error seeking to vertex_offset in gamemine.c" );
  595.  
  596.                 range_for (auto &i, partial_range(Vertices, mine_fileinfo.vertex_howmany))
  597.                 {
  598.                         // Set the default values for this vertex
  599.                         i.x = 1;
  600.                         i.y = 1;
  601.                         i.z = 1;
  602.  
  603.                         if (PHYSFS_read(LoadFile, &i, mine_fileinfo.vertex_sizeof, 1) != 1)
  604.                                 Error( "Error reading Vertices[i] in gamemine.c" );
  605.                 }
  606.         }
  607.  
  608.         //==================== READ SEGMENT INFO ===========================
  609.  
  610.         // New check added to make sure we don't read in too many segments.
  611.         if ( mine_fileinfo.segment_howmany > MAX_SEGMENTS ) {
  612.                 mine_fileinfo.segment_howmany = MAX_SEGMENTS;
  613. #if defined(DXX_BUILD_DESCENT_II)
  614.                 mine_fileinfo.segment2_howmany = MAX_SEGMENTS;
  615. #endif
  616.         }
  617.  
  618.         // [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();
  619.  
  620.         auto &Walls = LevelUniqueWallSubsystemState.Walls;
  621.         auto &vcwallptr = Walls.vcptr;
  622.         if ( (mine_fileinfo.segment_offset > -1) && (mine_fileinfo.segment_howmany > 0))        {
  623.  
  624.                 if (PHYSFSX_fseek( LoadFile, mine_fileinfo.segment_offset,SEEK_SET ))
  625.  
  626.                         Error( "Error seeking to segment_offset in gamemine.c" );
  627.  
  628.                 Segments.set_count(mine_fileinfo.segment_howmany);
  629.  
  630.                 for (segnum_t ii = 0; ii < mine_fileinfo.segment_howmany; ++ii)
  631.                 {
  632.                         const auto &i = vmsegptridx(ii);
  633.  
  634.                         // Set the default values for this segment (clear to zero )
  635.                         //memset( &Segments[i], 0, sizeof(segment) );
  636.  
  637. #if defined(DXX_BUILD_DESCENT_II)
  638.                         if (mine_top_fileinfo.fileinfo_version >= 20)
  639.                         {
  640.                                 /*
  641.                                  * The format of v20 segment once matched `struct segment`, but
  642.                                  * this was not enforced with a `static_assert` or even
  643.                                  * commented.  The layout of `struct segment` has since changed
  644.                                  * at least five times.  See commit
  645.                                  * 2665869c24855040837b1864daedd4cc13ab1793 for details.
  646.                                  */
  647.                                 Error("Sorry, v20 segment support is broken.");
  648.                         }
  649.                         else
  650. #endif
  651.                         if (mine_top_fileinfo.fileinfo_version >= 16)
  652.                         {
  653.                                 Error("Sorry, v16 segment support is broken.");
  654. #if 0
  655.                                 v16_segment v16_seg;
  656.  
  657.                                 Assert(mine_fileinfo.segment_sizeof == sizeof(v16_seg));
  658.  
  659. #if defined(DXX_BUILD_DESCENT_I)
  660.                                 *i = v16_seg;
  661. #elif defined(DXX_BUILD_DESCENT_II)
  662.                                 i->segnum = v16_seg.segnum;
  663.                                 // -- Segments[i].pad = v16_seg.pad;
  664.  
  665.                                 for (int j=0; j<MAX_SIDES_PER_SEGMENT; j++)
  666.                                         i->sides[j] = v16_seg.sides[j];
  667.  
  668.                                 for (int j=0; j<MAX_SIDES_PER_SEGMENT; j++)
  669.                                         i->children[j] = v16_seg.children[j];
  670.  
  671.                                 for (int j=0; j<MAX_VERTICES_PER_SEGMENT; j++)
  672.                                         i->verts[j] = v16_seg.verts[j];
  673.  
  674.                                 i->special = v16_seg.special;
  675.                                 i->station_idx = v16_seg.value;
  676.                                 i->s2_flags = 0;
  677.                                 i->matcen_num = v16_seg.matcen_num;
  678.                                 i->static_light = v16_seg.static_light;
  679. #endif
  680. #endif
  681.                                 fuelcen_activate(i);
  682.                         }
  683.                         else
  684.                                 Error("Invalid mine version");
  685.  
  686.                         i->objects = object_none;
  687. #if DXX_USE_EDITOR
  688.                         i->group = -1;
  689.                         #endif
  690.  
  691.                         if (translate == 1)
  692.                                 for (int j=0;j<MAX_SIDES_PER_SEGMENT;j++) {
  693.                                         unsigned short orient;
  694.                                         auto &iusidej = i->unique_segment::sides[j];
  695.                                         const auto tmap_xlate = iusidej.tmap_num;
  696.                                         iusidej.tmap_num = tmap_xlate_table[tmap_xlate];
  697.                                         const auto render = (WALL_IS_DOORWAY(GameBitmaps, Textures, vcwallptr, i, j) & WID_RENDER_FLAG);
  698.                                         if (render)
  699.                                                 if (iusidej.tmap_num < 0)       {
  700.                                                         Int3();
  701.                                                         iusidej.tmap_num = NumTextures-1;
  702.                                                 }
  703.                                         orient = iusidej.tmap_num2 & (~TMAP_NUM_MASK);
  704.                                         if (const auto tmap2_xlate = iusidej.tmap_num2 & TMAP_NUM_MASK)
  705.                                         {
  706.                                                 int xlated_tmap = tmap_xlate_table[tmap2_xlate];
  707.  
  708.                                                 iusidej.tmap_num2 = xlated_tmap | orient;
  709.                                                 if (render)
  710.                                                         if (xlated_tmap <= 0)   {
  711.                                                                 Int3();
  712.                                                                 iusidej.tmap_num2 = NumTextures-1;
  713.                                                         }
  714.                                         }
  715.                                 }
  716.                 }
  717.  
  718. #if defined(DXX_BUILD_DESCENT_II)
  719.                 if (mine_top_fileinfo.fileinfo_version >= 20)
  720.                         range_for (const auto &&segp, vmsegptridx)
  721.                         {
  722.                                 segment2_read(segp, LoadFile);
  723.                                 fuelcen_activate(segp);
  724.                         }
  725. #endif
  726.         }
  727.  
  728.         //===================== READ NEWSEGMENT INFO =====================
  729.  
  730. #if DXX_USE_EDITOR
  731.  
  732.         {               // Default segment created.
  733.                 med_create_new_segment({DEFAULT_X_SIZE, DEFAULT_Y_SIZE, DEFAULT_Z_SIZE});               // New_segment = Segments[0];
  734.                 //memset( &New_segment, 0, sizeof(segment) );
  735.         }
  736.  
  737.         if (mine_editor.newsegment_offset > -1)
  738.         {
  739.                 if (PHYSFSX_fseek( LoadFile, mine_editor.newsegment_offset,SEEK_SET ))
  740.                         Error( "Error seeking to newsegment_offset in gamemine.c" );
  741.                 Error("Sorry, v20 segment support is broken.");
  742.         }
  743.  
  744.         if ( (mine_fileinfo.newseg_verts_offset > -1) && (mine_fileinfo.newseg_verts_howmany > 0))
  745.         {
  746.                 if (PHYSFSX_fseek( LoadFile, mine_fileinfo.newseg_verts_offset, SEEK_SET ))
  747.                         Error( "Error seeking to newseg_verts_offset in gamemine.c" );
  748.                 auto &vmvertptr = Vertices.vmptr;
  749.                 for (unsigned i = 0; i < mine_fileinfo.newseg_verts_howmany; ++i)
  750.                 {
  751.                         // Set the default values for this vertex
  752.                         auto &v = *vmvertptr(NEW_SEGMENT_VERTICES+i);
  753.                         v.x = 1;
  754.                         v.y = 1;
  755.                         v.z = 1;
  756.                         if (PHYSFS_read(LoadFile, &v, mine_fileinfo.newseg_verts_sizeof, 1) != 1)
  757.                                 Error( "Error reading Vertices[NEW_SEGMENT_VERTICES+i] in gamemine.c" );
  758.  
  759.                         New_segment.verts[i] = NEW_SEGMENT_VERTICES+i;
  760.                 }
  761.         }
  762.  
  763.         #endif
  764.                                                                                                                        
  765.         //========================= UPDATE VARIABLES ======================
  766.  
  767. #if DXX_USE_EDITOR
  768.  
  769.         // Setting to Markedsegp to NULL ignores Curside and Markedside, which
  770.         // we want to do when reading in an old file.
  771.        
  772.         Markedside = mine_editor.Markedside;
  773.         Curside = mine_editor.Curside;
  774.         range_for (const int i, xrange(10u))
  775.                 Groupside[i] = mine_editor.Groupside[i];
  776.  
  777.         Cursegp = mine_editor.current_seg != -1 ? imsegptridx(static_cast<segnum_t>(mine_editor.current_seg)) : imsegptridx(segment_first);
  778.         Markedsegp = mine_editor.Markedsegp != -1 ? imsegptridx(static_cast<segnum_t>(mine_editor.Markedsegp)) : segment_none;
  779.  
  780.         num_groups = 0;
  781.         current_group = -1;
  782.  
  783.         #endif
  784.  
  785.         LevelSharedVertexState.Num_vertices = mine_fileinfo.vertex_howmany;
  786.         Vertices.set_count(LevelSharedVertexState.Num_vertices);
  787.         LevelSharedSegmentState.Num_segments = mine_fileinfo.segment_howmany;
  788.         Segments.set_count(LevelSharedSegmentState.Num_segments);
  789.  
  790.         reset_objects(LevelUniqueObjectState, 1);               //one object, the player
  791.  
  792. #if DXX_USE_EDITOR
  793.         Vertices.set_count(MAX_SEGMENT_VERTICES);
  794.         Segments.set_count(MAX_SEGMENTS);
  795.         set_vertex_counts();
  796.         Vertices.set_count(LevelSharedVertexState.Num_vertices);
  797.         Segments.set_count(LevelSharedSegmentState.Num_segments);
  798.  
  799.         warn_if_concave_segments();
  800.         #endif
  801.  
  802. #if DXX_USE_EDITOR
  803.         validate_segment_all(LevelSharedSegmentState);
  804.         #endif
  805.  
  806.         //create_local_segment_data();
  807.  
  808.         //gamemine_find_textures();
  809.  
  810.         if (mine_top_fileinfo.fileinfo_version < MINE_VERSION )
  811.                 return 1;               //old version
  812.         else
  813.                 return 0;
  814.  
  815. }
  816. }
  817. #endif
  818.  
  819. #define COMPILED_MINE_VERSION 0
  820.  
  821. static void read_children(shared_segment &segp, const unsigned bit_mask, PHYSFS_File *const LoadFile)
  822. {
  823.         for (int bit=0; bit<MAX_SIDES_PER_SEGMENT; bit++) {
  824.                 if (bit_mask & (1 << bit)) {
  825.                         segp.children[bit] = PHYSFSX_readShort(LoadFile);
  826.                 } else
  827.                         segp.children[bit] = segment_none;
  828.         }
  829. }
  830.  
  831. static void read_verts(shared_segment &segp, PHYSFS_File *const LoadFile)
  832. {
  833.         // Read short Segments[segnum].verts[MAX_VERTICES_PER_SEGMENT]
  834.         range_for (auto &i, segp.verts)
  835.                 i = PHYSFSX_readShort(LoadFile);
  836. }
  837.  
  838. static void read_special(shared_segment &segp, const unsigned bit_mask, PHYSFS_File *const LoadFile)
  839. {
  840.         if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT)) {
  841.                 // Read ubyte   Segments[segnum].special
  842.                 segp.special = PHYSFSX_readByte(LoadFile);
  843.                 // Read byte    Segments[segnum].matcen_num
  844.                 segp.matcen_num = PHYSFSX_readByte(LoadFile);
  845.                 // Read short   Segments[segnum].value
  846.                 segp.station_idx = PHYSFSX_readShort(LoadFile);
  847.         } else {
  848.                 segp.special = 0;
  849.                 segp.matcen_num = -1;
  850.                 segp.station_idx = station_none;
  851.         }
  852. }
  853.  
  854. namespace dsx {
  855.  
  856. int load_mine_data_compiled(PHYSFS_File *LoadFile, const char *const Gamesave_current_filename)
  857. {
  858.         auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
  859.         auto &Vertices = LevelSharedVertexState.get_vertices();
  860.         ubyte   compiled_version;
  861.         short   temp_short;
  862.         ushort  temp_ushort = 0;
  863.         ubyte   bit_mask;
  864.  
  865. #if defined(DXX_BUILD_DESCENT_II)
  866.         LevelSharedSeismicState.Level_shake_frequency = 0;
  867.         LevelSharedSeismicState.Level_shake_duration = 0;
  868.         d1_pig_present = PHYSFSX_exists(D1_PIGFILE,1);
  869. #endif
  870.         if (!strcmp(strchr(Gamesave_current_filename, '.'), ".sdl"))
  871.                 New_file_format_load = 0; // descent 1 shareware
  872.         else
  873.                 New_file_format_load = 1;
  874.  
  875.         //      For compiled levels, textures map to themselves, prevent tmap_override always being gray,
  876.         //      bug which Matt and John refused to acknowledge, so here is Mike, fixing it.
  877.         //
  878.         // Although in a cloud of arrogant glee, he forgot to ifdef it on EDITOR!
  879.         // (Matt told me to write that!)
  880. #if DXX_USE_EDITOR
  881.         for (int i=0; i<MAX_TEXTURES; i++)
  882.                 tmap_xlate_table[i] = i;
  883. #endif
  884.  
  885. //      memset( Segments, 0, sizeof(segment)*MAX_SEGMENTS );
  886.         fuelcen_reset();
  887.  
  888.         //=============================== Reading part ==============================
  889.         compiled_version = PHYSFSX_readByte(LoadFile);
  890.         (void)compiled_version;
  891.  
  892.         DXX_POISON_VAR(Vertices, 0xfc);
  893.         if (New_file_format_load)
  894.                 LevelSharedVertexState.Num_vertices = PHYSFSX_readShort(LoadFile);
  895.         else
  896.                 LevelSharedVertexState.Num_vertices = PHYSFSX_readInt(LoadFile);
  897.         assert(LevelSharedVertexState.Num_vertices <= MAX_VERTICES);
  898.  
  899.         DXX_POISON_VAR(Segments, 0xfc);
  900.         if (New_file_format_load)
  901.                 LevelSharedSegmentState.Num_segments = PHYSFSX_readShort(LoadFile);
  902.         else
  903.                 LevelSharedSegmentState.Num_segments = PHYSFSX_readInt(LoadFile);
  904.         assert(LevelSharedSegmentState.Num_segments <= MAX_SEGMENTS);
  905.  
  906.         range_for (auto &i, partial_range(Vertices, LevelSharedVertexState.Num_vertices))
  907.                 PHYSFSX_readVector(LoadFile, i);
  908.  
  909.         const auto Num_segments = LevelSharedSegmentState.Num_segments;
  910.         for (segnum_t segnum=0; segnum < Num_segments; segnum++ )       {
  911.                 const auto segp = vmsegptr(segnum);
  912.  
  913. #if DXX_USE_EDITOR
  914.                 segp->segnum = segnum;
  915.                 segp->group = 0;
  916.                 #endif
  917.  
  918.                 if (New_file_format_load)
  919.                         bit_mask = PHYSFSX_readByte(LoadFile);
  920.                 else
  921.                         bit_mask = 0x7f; // read all six children and special stuff...
  922.  
  923.                 if (Gamesave_current_version == 5) { // d2 SHAREWARE level
  924.                         read_special(segp,bit_mask,LoadFile);
  925.                         read_verts(segp,LoadFile);
  926.                         read_children(segp,bit_mask,LoadFile);
  927.                 } else {
  928.                         read_children(segp,bit_mask,LoadFile);
  929.                         read_verts(segp,LoadFile);
  930.                         if (Gamesave_current_version <= 1) { // descent 1 level
  931.                                 read_special(segp,bit_mask,LoadFile);
  932.                         }
  933.                 }
  934.  
  935.                 segp->objects = object_none;
  936.  
  937.                 if (Gamesave_current_version <= 5) { // descent 1 thru d2 SHAREWARE level
  938.                         // Read fix     Segments[segnum].static_light (shift down 5 bits, write as short)
  939.                         temp_ushort = PHYSFSX_readShort(LoadFile);
  940.                         segp->static_light      = static_cast<fix>(temp_ushort) << 4;
  941.                         //PHYSFS_read( LoadFile, &Segments[segnum].static_light, sizeof(fix), 1 );
  942.                 }
  943.  
  944.                 // Read the walls as a 6 byte array
  945.                 if (New_file_format_load)
  946.                         bit_mask = PHYSFSX_readByte(LoadFile);
  947.                 else
  948.                         bit_mask = 0x3f; // read all six sides
  949.                 for (int sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
  950.                         ubyte byte_wallnum;
  951.  
  952.                         auto &sside = segp->shared_segment::sides[sidenum];
  953.                         if (bit_mask & (1 << sidenum)) {
  954.                                 byte_wallnum = PHYSFSX_readByte(LoadFile);
  955.                                 if ( byte_wallnum == 255 )
  956.                                         sside.wall_num = wall_none;
  957.                                 else
  958.                                         sside.wall_num = byte_wallnum;
  959.                         } else
  960.                                         sside.wall_num = wall_none;
  961.                 }
  962.  
  963.                 for (int sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++ ) {
  964.                         auto &uside = segp->unique_segment::sides[sidenum];
  965.                         if (segp->children[sidenum] == segment_none || segp->shared_segment::sides[sidenum].wall_num != wall_none)      {
  966.                                 // Read short Segments[segnum].sides[sidenum].tmap_num;
  967.                                 temp_ushort = PHYSFSX_readShort(LoadFile);
  968. #if defined(DXX_BUILD_DESCENT_I)
  969.                                 uside.tmap_num = convert_tmap(temp_ushort & 0x7fff);
  970.  
  971.                                 if (New_file_format_load && !(temp_ushort & 0x8000))
  972.                                         uside.tmap_num2 = 0;
  973.                                 else {
  974.                                         // Read short Segments[segnum].sides[sidenum].tmap_num2;
  975.                                         uside.tmap_num2 = PHYSFSX_readShort(LoadFile);
  976.                                         uside.tmap_num2 =
  977.                                                 (convert_tmap(uside.tmap_num2 & 0x3fff)) |
  978.                                                 (uside.tmap_num2 & 0xc000);
  979.                                 }
  980. #elif defined(DXX_BUILD_DESCENT_II)
  981.                                 if (New_file_format_load) {
  982.                                         uside.tmap_num = temp_ushort & 0x7fff;
  983.                                 } else
  984.                                         uside.tmap_num = temp_ushort;
  985.  
  986.                                 if (Gamesave_current_version <= 1)
  987.                                         uside.tmap_num = convert_d1_tmap_num(uside.tmap_num);
  988.  
  989.                                 if (New_file_format_load && !(temp_ushort & 0x8000))
  990.                                         uside.tmap_num2 = 0;
  991.                                 else {
  992.                                         // Read short Segments[segnum].sides[sidenum].tmap_num2;
  993.                                         uside.tmap_num2 = PHYSFSX_readShort(LoadFile);
  994.                                         if (Gamesave_current_version <= 1 && uside.tmap_num2 != 0)
  995.                                                 uside.tmap_num2 = convert_d1_tmap_num(uside.tmap_num2);
  996.                                 }
  997. #endif
  998.  
  999.                                 // Read uvl Segments[segnum].sides[sidenum].uvls[4] (u,v>>5, write as short, l>>1 write as short)
  1000.                                 range_for (auto &i, uside.uvls) {
  1001.                                         temp_short = PHYSFSX_readShort(LoadFile);
  1002.                                         i.u = static_cast<fix>(temp_short) << 5;
  1003.                                         temp_short = PHYSFSX_readShort(LoadFile);
  1004.                                         i.v = static_cast<fix>(temp_short) << 5;
  1005.                                         temp_ushort = PHYSFSX_readShort(LoadFile);
  1006.                                         i.l = static_cast<fix>(temp_ushort) << 1;
  1007.                                         //PHYSFS_read( LoadFile, &i.l, sizeof(fix), 1 );
  1008.                                 }
  1009.                         } else {
  1010.                                 uside.tmap_num = 0;
  1011.                                 uside.tmap_num2 = 0;
  1012.                                 uside.uvls = {};
  1013.                         }
  1014.                 }
  1015.         }
  1016.  
  1017.         Vertices.set_count(LevelSharedVertexState.Num_vertices);
  1018.         Segments.set_count(Num_segments);
  1019.  
  1020.         validate_segment_all(LevelSharedSegmentState);                  // Fill in side type and normals.
  1021.  
  1022.         range_for (const auto &&pi, vmsegptridx)
  1023.         {
  1024.                 if (Gamesave_current_version > 5)
  1025.                         segment2_read(pi, LoadFile);
  1026.                 fuelcen_activate(pi);
  1027.         }
  1028.  
  1029.         reset_objects(LevelUniqueObjectState, 1);               //one object, the player
  1030.  
  1031.         return 0;
  1032. }
  1033. }
  1034.