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.  * Routines for paging in/out textures.
  23.  *
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <math.h>
  29. #include <string.h>
  30.  
  31. #include "pstypes.h"
  32. #include "inferno.h"
  33. #include "segment.h"
  34. #include "textures.h"
  35. #include "wall.h"
  36. #include "object.h"
  37. #include "gamemine.h"
  38. #include "dxxerror.h"
  39. #include "console.h"
  40. #include "gameseg.h"
  41. #include "game.h"
  42. #include "piggy.h"
  43. #include "texmerge.h"
  44. #include "paging.h"
  45. #include "laser.h"
  46. #include "robot.h"
  47. #include "vclip.h"
  48. #include "effects.h"
  49. #include "fireball.h"
  50. #include "weapon.h"
  51. #include "palette.h"
  52. #include "timer.h"
  53. #include "text.h"
  54. #include "cntrlcen.h"
  55. #include "gauges.h"
  56. #include "powerup.h"
  57. #include "fuelcen.h"
  58. #include "mission.h"
  59. #include "ai.h"
  60.  
  61. #include "compiler-range_for.h"
  62. #include "partial_range.h"
  63. #include "segiter.h"
  64.  
  65. static void paging_touch_vclip(const vclip &vc, const unsigned line)
  66. #define paging_touch_vclip(V)   paging_touch_vclip(V, __LINE__)
  67. {
  68.         using range_type = partial_range_t<const bitmap_index*>;
  69.         union {
  70.                 uint8_t storage[1];
  71.                 range_type r;
  72.         } u{};
  73.         try
  74.         {
  75.                 new(&u.r) range_type((partial_const_range)(__FILE__, line, "vc.frames", vc.frames, vc.num_frames));
  76.                 static_assert(std::is_trivially_destructible<range_type>::value, "partial_range destructor not called");
  77.         }
  78.         catch (const range_type::partial_range_error &e)
  79.         {
  80.                 con_puts(CON_URGENT, e.what());
  81.                 return;
  82.         }
  83.         range_for (auto &i, u.r)
  84.         {
  85.                 PIGGY_PAGE_IN(i);
  86.         }
  87. }
  88.  
  89. static void paging_touch_wall_effects(const d_eclip_array &Effects, const Textures_array &Textures, const d_vclip_array &Vclip, const int tmap_num)
  90. {
  91.         range_for (auto &i, partial_const_range(Effects, Num_effects))
  92.         {
  93.                 if ( i.changing_wall_texture == tmap_num )      {
  94.                         paging_touch_vclip(i.vc);
  95.  
  96.                         if (i.dest_bm_num < Textures.size())
  97.                                 PIGGY_PAGE_IN( Textures[i.dest_bm_num] );       //use this bitmap when monitor destroyed
  98.                         if ( i.dest_vclip > -1 )
  99.                                 paging_touch_vclip(Vclip[i.dest_vclip]);                  //what vclip to play when exploding
  100.  
  101.                         if ( i.dest_eclip > -1 )
  102.                                 paging_touch_vclip(Effects[i.dest_eclip].vc); //what eclip to play when exploding
  103.  
  104.                         if ( i.crit_clip > -1 )
  105.                                 paging_touch_vclip(Effects[i.crit_clip].vc); //what eclip to play when mine critical
  106.                         break;
  107.                 }
  108.         }
  109. }
  110.  
  111. static void paging_touch_object_effects(const d_eclip_array &Effects, const unsigned tmap_num)
  112. {
  113.         range_for (auto &i, partial_const_range(Effects, Num_effects))
  114.         {
  115.                 if ( i.changing_object_texture == tmap_num )    {
  116.                         paging_touch_vclip(i.vc);
  117.                         break;
  118.                 }
  119.         }
  120. }
  121.  
  122. static void paging_touch_model( int modelnum )
  123. {
  124.         auto &Effects = LevelUniqueEffectsClipState.Effects;
  125.         auto &Polygon_models = LevelSharedPolygonModelState.Polygon_models;
  126.         const auto &pm = Polygon_models[modelnum];
  127.         const uint_fast32_t b = pm.first_texture;
  128.         const uint_fast32_t e = b + pm.n_textures;
  129.         range_for (const auto p, partial_range(ObjBitmapPtrs, b, e))
  130.         {
  131.                 PIGGY_PAGE_IN(ObjBitmaps[p]);
  132.                 paging_touch_object_effects(Effects, p);
  133.         }
  134. }
  135.  
  136. static void paging_touch_weapon(const d_vclip_array &Vclip, const weapon_info &weapon)
  137. {
  138.         // Page in the robot's weapons.
  139.  
  140.         if(weapon.picture.index)
  141.         {
  142.                 PIGGY_PAGE_IN(weapon.picture);
  143.         }              
  144.        
  145.         if (weapon.flash_vclip > -1)
  146.                 paging_touch_vclip(Vclip[weapon.flash_vclip]);
  147.         if (weapon.wall_hit_vclip > -1)
  148.                 paging_touch_vclip(Vclip[weapon.wall_hit_vclip]);
  149.         if (weapon.damage_radius)
  150.         {
  151.                 // Robot_hit_vclips are actually badass_vclips
  152.                 if (weapon.robot_hit_vclip > -1)
  153.                         paging_touch_vclip(Vclip[weapon.robot_hit_vclip]);
  154.         }
  155.  
  156.         switch(weapon.render_type)
  157.         {
  158.         case WEAPON_RENDER_VCLIP:
  159.                 if (weapon.weapon_vclip > -1)
  160.                         paging_touch_vclip(Vclip[weapon.weapon_vclip]);
  161.                 break;
  162.         case WEAPON_RENDER_NONE:
  163.                 break;
  164.         case WEAPON_RENDER_POLYMODEL:
  165.                 paging_touch_model(weapon.model_num);
  166.                 break;
  167.         case WEAPON_RENDER_BLOB:
  168.                 PIGGY_PAGE_IN(weapon.bitmap);
  169.                 break;
  170.         }
  171. }
  172.  
  173. static void paging_touch_weapon(const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const uint_fast32_t weapon_type)
  174. {
  175.         if (weapon_type < N_weapon_types)
  176.                 paging_touch_weapon(Vclip, Weapon_info[weapon_type]);
  177. }
  178.  
  179. const std::array<sbyte, 13> super_boss_gate_type_list{{0, 1, 8, 9, 10, 11, 12, 15, 16, 18, 19, 20, 22}};
  180.  
  181. static void paging_touch_robot(const d_level_shared_robot_info_state::d_robot_info_array &Robot_info, const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const unsigned ridx)
  182. {
  183.         auto &ri = Robot_info[ridx];
  184.         // Page in robot_index
  185.         paging_touch_model(ri.model_num);
  186.         if (ri.exp1_vclip_num > -1)
  187.                 paging_touch_vclip(Vclip[ri.exp1_vclip_num]);
  188.         if (ri.exp2_vclip_num > -1)
  189.                 paging_touch_vclip(Vclip[ri.exp2_vclip_num]);
  190.  
  191.         // Page in his weapons
  192.         paging_touch_weapon(Vclip, Weapon_info, ri.weapon_type);
  193.  
  194.         // A super-boss can gate in robots...
  195.         if (ri.boss_flag == BOSS_SUPER)
  196.         {
  197.                 range_for (const auto i, super_boss_gate_type_list)
  198.                         paging_touch_robot(Robot_info, Vclip, Weapon_info, i);
  199.                 paging_touch_vclip(Vclip[VCLIP_MORPHING_ROBOT]);
  200.         }
  201. }
  202.  
  203. static void paging_touch_object(const d_level_shared_robot_info_state::d_robot_info_array &Robot_info, const Textures_array &Textures, const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const object_base &obj)
  204. {
  205.         int v;
  206.  
  207.         switch (obj.render_type) {
  208.  
  209.                 case RT_NONE:   break;          //doesn't render, like the player
  210.  
  211.                 case RT_POLYOBJ:
  212.                         if (obj.rtype.pobj_info.tmap_override != -1)
  213.                                 PIGGY_PAGE_IN(Textures[obj.rtype.pobj_info.tmap_override]);
  214.                         else
  215.                                 paging_touch_model(obj.rtype.pobj_info.model_num);
  216.                         break;
  217.  
  218.                 case RT_POWERUP:
  219.                         if (obj.rtype.vclip_info.vclip_num > -1)
  220.                         {
  221.                                 paging_touch_vclip(Vclip[obj.rtype.vclip_info.vclip_num]);
  222.                         }
  223.                         break;
  224.  
  225.                 case RT_MORPH:  break;
  226.  
  227.                 case RT_FIREBALL: break;
  228.  
  229.                 case RT_WEAPON_VCLIP: break;
  230.  
  231.                 case RT_HOSTAGE:
  232.                         paging_touch_vclip(Vclip[obj.rtype.vclip_info.vclip_num]);
  233.                         break;
  234.  
  235.                 case RT_LASER: break;
  236.         }
  237.  
  238.         switch (obj.type) {    
  239.                 default:
  240.                         break;
  241.         case OBJ_PLAYER:       
  242.                 v = get_explosion_vclip(obj, explosion_vclip_stage::s0);
  243.                 if ( v > -1 )
  244.                         paging_touch_vclip(Vclip[v]);
  245.                 break;
  246.         case OBJ_ROBOT:
  247.                 paging_touch_robot(Robot_info, Vclip, Weapon_info, get_robot_id(obj));
  248.                 break;
  249.         case OBJ_CNTRLCEN:
  250.                 paging_touch_weapon(Vclip, Weapon_info, weapon_id_type::CONTROLCEN_WEAPON_NUM);
  251.                 if (Dead_modelnums[obj.rtype.pobj_info.model_num] != -1)
  252.                 {
  253.                         paging_touch_model(Dead_modelnums[obj.rtype.pobj_info.model_num]);
  254.                 }
  255.                 break;
  256.         }
  257. }
  258.  
  259.        
  260.  
  261. static void paging_touch_side(const d_eclip_array &Effects, const Textures_array &Textures, const d_vclip_array &Vclip, const cscusegment segp, int sidenum )
  262. {
  263.         auto &Walls = LevelUniqueWallSubsystemState.Walls;
  264.         auto &vcwallptr = Walls.vcptr;
  265.         if (!(WALL_IS_DOORWAY(GameBitmaps, Textures, vcwallptr, segp, sidenum) & WID_RENDER_FLAG))
  266.                 return;
  267.         auto &uside = segp.u.sides[sidenum];
  268.         const auto tmap1 = uside.tmap_num;
  269.         paging_touch_wall_effects(Effects, Textures, Vclip, tmap1);
  270.         if (const auto tmap2 = uside.tmap_num2)
  271.         {
  272.                 texmerge_get_cached_bitmap( tmap1, tmap2 );
  273.                 paging_touch_wall_effects(Effects, Textures, Vclip, tmap2 & 0x3FFF);
  274.         } else  {
  275.                 PIGGY_PAGE_IN( Textures[tmap1] );
  276.         }
  277. }
  278.  
  279. static void paging_touch_robot_maker(const d_level_shared_robot_info_state::d_robot_info_array &Robot_info, const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const shared_segment &segp)
  280. {
  281.         auto &RobotCenters = LevelSharedRobotcenterState.RobotCenters;
  282.                 paging_touch_vclip(Vclip[VCLIP_MORPHING_ROBOT]);
  283.                         const auto &robot_flags = RobotCenters[segp.matcen_num].robot_flags;
  284.                         const std::size_t bits_per_robot_flags = 8 * sizeof(robot_flags[0]);
  285.                         for (uint_fast32_t i = 0; i != robot_flags.size(); ++i)
  286.                         {
  287.                                 auto robot_index = i * bits_per_robot_flags;
  288.                                 uint_fast32_t flags = robot_flags[i];
  289.                                 if (sizeof(flags) >= 2 * sizeof(robot_flags[0]) && i + 1 != robot_flags.size())
  290.                                         flags |= static_cast<uint64_t>(robot_flags[++i]) << bits_per_robot_flags;
  291.                                 while (flags) {
  292.                                         if (flags & 1)  {
  293.                                                 // Page in robot_index
  294.                                                 paging_touch_robot(Robot_info, Vclip, Weapon_info, robot_index);
  295.                                         }
  296.                                         flags >>= 1;
  297.                                         robot_index++;
  298.                                 }
  299.                         }
  300. }
  301.  
  302. static void paging_touch_segment(const d_eclip_array &Effects, const d_level_shared_robot_info_state::d_robot_info_array &Robot_info, const Textures_array &Textures, const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const fvcobjptridx &vcobjptridx, const fvcsegptr &vcsegptr, const vcsegptr_t segp)
  303. {
  304.         if ( segp->special == SEGMENT_IS_ROBOTMAKER )
  305.                 paging_touch_robot_maker(Robot_info, Vclip, Weapon_info, segp);
  306.  
  307.         for (int sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) {
  308.                 paging_touch_side(Effects, Textures, Vclip, segp, sn);
  309.         }
  310.  
  311.         range_for (const object &objp, objects_in(*segp, vcobjptridx, vcsegptr))
  312.                 paging_touch_object(Robot_info, Textures, Vclip, Weapon_info, objp);
  313. }
  314.  
  315. static void paging_touch_walls(const Textures_array &Textures, const wall_animations_array &WallAnims, const fvcwallptr &vcwallptr)
  316. {
  317.         range_for (const auto &&wp, vcwallptr)
  318.         {
  319.                 auto &w = *wp;
  320.                 if ( w.clip_num > -1 )  {
  321.                         const auto &anim = WallAnims[w.clip_num];
  322.                         range_for (auto &j, partial_range(anim.frames, anim.num_frames))
  323.                                 PIGGY_PAGE_IN(Textures[j]);
  324.                 }
  325.         }
  326. }
  327.  
  328. namespace dsx {
  329. void paging_touch_all(const d_vclip_array &Vclip)
  330. {
  331.         auto &Effects = LevelUniqueEffectsClipState.Effects;
  332.         auto &Objects = LevelUniqueObjectState.Objects;
  333.         auto &WallAnims = GameSharedState.WallAnims;
  334.         auto &vcobjptridx = Objects.vcptridx;
  335.         pause_game_world_time p;
  336.  
  337. #if defined(DXX_BUILD_DESCENT_I)
  338.         show_boxed_message(TXT_LOADING, 0);
  339. #endif
  340.         auto &Robot_info = LevelSharedRobotInfoState.Robot_info;
  341.         range_for (const auto &&segp, vcsegptr)
  342.         {
  343.                 paging_touch_segment(Effects, Robot_info, Textures, Vclip, Weapon_info, vcobjptridx, vcsegptr, segp);
  344.         }      
  345.         auto &Walls = LevelUniqueWallSubsystemState.Walls;
  346.         auto &vcwallptr = Walls.vcptr;
  347.         paging_touch_walls(Textures, WallAnims, vcwallptr);
  348.  
  349.         range_for (auto &s, partial_const_range(Powerup_info, N_powerup_types))
  350.         {
  351.                 if ( s.vclip_num > -1 )
  352.                         paging_touch_vclip(Vclip[s.vclip_num]);
  353.         }
  354.  
  355.         range_for (auto &w, partial_const_range(Weapon_info, N_weapon_types))
  356.         {
  357.                 paging_touch_weapon(Vclip, w);
  358.         }
  359.  
  360.         range_for (auto &s, partial_const_range(Powerup_info, N_powerup_types))
  361.         {
  362.                 if ( s.vclip_num > -1 )
  363.                         paging_touch_vclip(Vclip[s.vclip_num]);
  364.         }
  365.  
  366.         range_for (auto &s, Gauges)
  367.         {
  368.                 if ( s.index )  {
  369.                         PIGGY_PAGE_IN( s );
  370.                 }
  371.         }
  372.         paging_touch_vclip(Vclip[VCLIP_PLAYER_APPEARANCE]);
  373.         paging_touch_vclip(Vclip[VCLIP_POWERUP_DISAPPEARANCE]);
  374.  
  375.         reset_cockpit();                //force cockpit redraw next time
  376. }
  377. }
  378.