Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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
}