2006-03-20 17:12:09 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING . txt .
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below .
* See COPYING . txt for license details .
2006-03-20 17:12:09 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ( " PARALLAX " ) . PARALLAX , IN DISTRIBUTING THE CODE TO
END - USERS , AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN , GRANTS A
ROYALTY - FREE , PERPETUAL LICENSE TO SUCH END - USERS FOR USE BY SUCH END - USERS
IN USING , DISPLAYING , AND CREATING DERIVATIVE WORKS THEREOF , SO LONG AS
SUCH USE , DISPLAY OR CREATION IS FOR NON - COMMERCIAL , ROYALTY OR REVENUE
FREE PURPOSES . IN NO EVENT SHALL THE END - USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE - BEARING PURPOSES . THE END - USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE .
COPYRIGHT 1993 - 1999 PARALLAX SOFTWARE CORPORATION . ALL RIGHTS RESERVED .
*/
/*
*
* Bitmap and palette loading functions .
*
*/
2015-10-09 02:46:09 +00:00
# include <algorithm>
2006-03-20 17:12:09 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "pstypes.h"
# include "inferno.h"
# include "gr.h"
# include "bm.h"
# include "u_mem.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "object.h"
# include "vclip.h"
# include "effects.h"
# include "polyobj.h"
# include "wall.h"
# include "textures.h"
# include "game.h"
# include "multi.h"
# include "iff.h"
# include "powerup.h"
# include "sounds.h"
# include "piggy.h"
# include "aistruct.h"
# include "robot.h"
# include "weapon.h"
# include "gauges.h"
# include "player.h"
# include "endlevel.h"
# include "cntrlcen.h"
# include "makesig.h"
# include "interp.h"
2008-04-06 20:23:28 +00:00
# include "console.h"
2008-11-14 16:56:40 +00:00
# include "rle.h"
2012-11-11 00:14:30 +00:00
# include "physfsx.h"
2013-12-26 04:18:28 +00:00
# include "strutil.h"
2006-03-20 17:12:09 +00:00
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2013-03-03 01:03:33 +00:00
# include "editor/texpage.h"
# endif
2014-01-18 18:02:02 +00:00
# include "compiler-range_for.h"
2019-05-04 18:27:37 +00:00
# include "d_range.h"
2014-01-18 18:02:02 +00:00
# include "partial_range.h"
2020-05-02 21:18:43 +00:00
# include <memory>
2014-01-18 18:02:02 +00:00
2015-01-29 04:27:35 +00:00
unsigned NumTextures ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
int Num_object_subtypes = 1 ;
# endif
2020-01-18 21:57:39 +00:00
namespace dsx {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
int Num_total_object_types ;
sbyte ObjType [ MAX_OBJTYPE ] ;
sbyte ObjId [ MAX_OBJTYPE ] ;
fix ObjStrength [ MAX_OBJTYPE ] ;
# elif defined(DXX_BUILD_DESCENT_II)
2013-11-10 03:31:22 +00:00
//the polygon model number to use for the marker
2016-02-06 22:12:54 +00:00
unsigned N_ObjBitmaps ;
2020-10-07 03:59:14 +00:00
namespace {
2020-08-24 01:31:28 +00:00
static int extra_bitmap_num ;
2013-11-10 03:31:22 +00:00
static void bm_free_extra_objbitmaps ( ) ;
2020-10-07 03:59:14 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2013-11-10 03:31:22 +00:00
2016-07-10 04:11:35 +00:00
Textures_array Textures ; // All textures.
2006-03-20 17:12:09 +00:00
//for each model, a model number for dying & dead variants, or -1 if none
2020-05-02 21:18:42 +00:00
std : : array < int , MAX_POLYGON_MODELS > Dying_modelnums , Dead_modelnums ;
2016-06-25 23:21:36 +00:00
}
2006-03-20 17:12:09 +00:00
//right now there's only one player ship, but we can have another by
//adding an array and setting the pointer to the active ship.
2016-10-02 19:35:34 +00:00
namespace dcx {
2020-08-24 01:31:28 +00:00
std : : array < uint8_t , : : d2x : : MAX_SOUNDS > Sounds , AltSounds ;
2013-11-17 00:50:32 +00:00
player_ship only_player_ship ;
2006-03-20 17:12:09 +00:00
//----------------- Miscellaneous bitmap pointers ---------------
2015-02-14 22:48:30 +00:00
unsigned Num_cockpits ;
2016-10-02 19:35:34 +00:00
}
2006-03-20 17:12:09 +00:00
//---------------- Variables for wall textures ------------------
//---------------- Variables for object textures ----------------
int First_multi_bitmap_num = - 1 ;
2020-10-07 03:59:14 +00:00
namespace dsx {
2022-02-12 18:57:12 +00:00
enumerated_array < bitmap_index , N_COCKPIT_BITMAPS , cockpit_mode_t > cockpit_bitmap ;
2020-10-07 03:59:14 +00:00
enumerated_array < bitmap_index , MAX_OBJ_BITMAPS , object_bitmap_index > ObjBitmaps ;
std : : array < object_bitmap_index , MAX_OBJ_BITMAPS > ObjBitmapPtrs ; // These point back into ObjBitmaps, since some are used twice.
2006-03-20 17:12:09 +00:00
2015-12-04 03:36:32 +00:00
void gamedata_close ( )
{
2020-08-24 01:31:28 +00:00
free_polygon_models ( LevelSharedPolygonModelState ) ;
2015-12-04 03:36:32 +00:00
# if defined(DXX_BUILD_DESCENT_II)
bm_free_extra_objbitmaps ( ) ;
# endif
free_endlevel_data ( ) ;
rle_cache_close ( ) ;
piggy_close ( ) ;
}
2006-03-20 17:12:09 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads n tmap_info structs from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2020-12-26 21:17:29 +00:00
namespace {
2016-01-09 16:38:14 +00:00
static void tmap_info_read ( tmap_info & ti , PHYSFS_File * fp )
2013-03-03 01:03:33 +00:00
{
2014-02-09 18:09:54 +00:00
PHYSFS_read ( fp , ti . filename , 13 , 1 ) ;
2021-11-01 03:37:20 +00:00
uint8_t flags ;
PHYSFS_read ( fp , & flags , 1 , 1 ) ;
ti . flags = tmapinfo_flags { flags } ;
2014-02-09 18:09:54 +00:00
ti . lighting = PHYSFSX_readFix ( fp ) ;
ti . damage = PHYSFSX_readFix ( fp ) ;
ti . eclip_num = PHYSFSX_readInt ( fp ) ;
2013-03-03 01:03:33 +00:00
}
2020-12-26 21:17:29 +00:00
}
2013-03-03 01:03:33 +00:00
//-----------------------------------------------------------------
// Initializes game properties data (including texture caching system) and sound data.
2022-07-09 13:39:29 +00:00
int gamedata_init ( d_level_shared_robot_info_state & LevelSharedRobotInfoState )
2013-03-03 01:03:33 +00:00
{
int retval ;
2020-08-24 01:31:28 +00:00
init_polygon_models ( LevelSharedPolygonModelState ) ;
2022-07-09 13:39:29 +00:00
retval = properties_init ( LevelSharedRobotInfoState ) ; // This calls properties_read_cmp if appropriate
2013-03-03 01:03:33 +00:00
if ( retval )
2022-07-09 13:39:29 +00:00
gamedata_read_tbl ( LevelSharedRobotInfoState , Vclip , retval = = PIGGY_PC_SHAREWARE ) ;
2013-03-03 01:03:33 +00:00
piggy_read_sounds ( retval = = PIGGY_PC_SHAREWARE ) ;
return 0 ;
}
// Read compiled properties data from descent.pig
2019-12-12 15:25:11 +00:00
// (currently only ever called if D1)
2022-07-09 13:39:29 +00:00
void properties_read_cmp ( d_level_shared_robot_info_state & LevelSharedRobotInfoState , d_vclip_array & Vclip , PHYSFS_File * fp )
2013-03-03 01:03:33 +00:00
{
2019-03-03 00:31:09 +00:00
auto & Effects = LevelUniqueEffectsClipState . Effects ;
2018-12-30 00:43:59 +00:00
auto & Robot_joints = LevelSharedRobotJointState . Robot_joints ;
2018-12-30 00:43:59 +00:00
auto & TmapInfo = LevelUniqueTmapInfoState . TmapInfo ;
2020-04-04 19:30:22 +00:00
auto & WallAnims = GameSharedState . WallAnims ;
2013-03-03 01:03:33 +00:00
// bitmap_index is a short
NumTextures = PHYSFSX_readInt ( fp ) ;
2015-02-14 22:48:30 +00:00
bitmap_index_read_n ( fp , Textures ) ;
2014-02-09 18:09:54 +00:00
range_for ( tmap_info & ti , TmapInfo )
tmap_info_read ( ti , fp ) ;
2013-03-03 01:03:33 +00:00
2020-08-24 01:31:28 +00:00
PHYSFS_read ( fp , Sounds , sizeof ( Sounds [ 0 ] ) , MAX_SOUNDS ) ;
PHYSFS_read ( fp , AltSounds , sizeof ( AltSounds [ 0 ] ) , MAX_SOUNDS ) ;
2013-03-03 01:03:33 +00:00
Num_vclips = PHYSFSX_readInt ( fp ) ;
2014-01-18 18:02:02 +00:00
range_for ( vclip & vc , Vclip )
vclip_read ( fp , vc ) ;
2013-03-03 01:03:33 +00:00
Num_effects = PHYSFSX_readInt ( fp ) ;
2014-01-18 18:02:02 +00:00
range_for ( eclip & ec , Effects )
eclip_read ( fp , ec ) ;
2013-03-03 01:03:33 +00:00
Num_wall_anims = PHYSFSX_readInt ( fp ) ;
2014-02-02 05:30:48 +00:00
range_for ( auto & w , WallAnims )
wclip_read ( fp , w ) ;
2013-03-03 01:03:33 +00:00
2018-12-30 00:43:59 +00:00
LevelSharedRobotInfoState . N_robot_types = PHYSFSX_readInt ( fp ) ;
2018-12-30 00:43:59 +00:00
auto & Robot_info = LevelSharedRobotInfoState . Robot_info ;
2015-01-23 03:55:04 +00:00
range_for ( auto & r , Robot_info )
robot_info_read ( fp , r ) ;
2013-03-03 01:03:33 +00:00
2020-08-24 01:31:28 +00:00
LevelSharedRobotJointState . N_robot_joints = PHYSFSX_readInt ( fp ) ;
2014-12-18 04:12:38 +00:00
range_for ( auto & r , Robot_joints )
jointpos_read ( fp , r ) ;
2013-03-03 01:03:33 +00:00
N_weapon_types = PHYSFSX_readInt ( fp ) ;
weapon_info_read_n ( Weapon_info , MAX_WEAPON_TYPES , fp , 0 ) ;
N_powerup_types = PHYSFSX_readInt ( fp ) ;
2014-01-18 18:02:02 +00:00
range_for ( auto & p , Powerup_info )
powerup_type_info_read ( fp , p ) ;
2013-03-03 01:03:33 +00:00
2018-12-30 00:43:59 +00:00
auto & Polygon_models = LevelSharedPolygonModelState . Polygon_models ;
2020-08-24 01:31:28 +00:00
const auto N_polygon_models = LevelSharedPolygonModelState . N_polygon_models = PHYSFSX_readInt ( fp ) ;
2016-02-06 22:12:54 +00:00
{
const auto & & r = partial_range ( Polygon_models , N_polygon_models ) ;
range_for ( auto & p , r )
2014-02-09 18:09:54 +00:00
polymodel_read ( & p , fp ) ;
2013-03-03 01:03:33 +00:00
2016-02-06 22:12:54 +00:00
range_for ( auto & p , r )
2014-02-09 18:09:54 +00:00
polygon_model_data_read ( & p , fp ) ;
2016-02-06 22:12:54 +00:00
}
2013-03-03 01:03:33 +00:00
2016-02-06 22:12:54 +00:00
bitmap_index_read_n ( fp , partial_range ( Gauges , MAX_GAUGE_BMS ) ) ;
2013-03-03 01:03:33 +00:00
2015-10-09 02:46:09 +00:00
range_for ( auto & i , Dying_modelnums )
i = PHYSFSX_readInt ( fp ) ;
range_for ( auto & i , Dead_modelnums )
i = PHYSFSX_readInt ( fp ) ;
2013-03-03 01:03:33 +00:00
2016-02-06 22:12:54 +00:00
bitmap_index_read_n ( fp , ObjBitmaps ) ;
2015-10-09 02:46:09 +00:00
range_for ( auto & i , ObjBitmapPtrs )
2020-10-07 03:59:14 +00:00
{
const auto oi = static_cast < object_bitmap_index > ( PHYSFSX_readShort ( fp ) ) ;
if ( ObjBitmaps . valid_index ( oi ) )
i = oi ;
else
i = { } ;
}
2013-03-03 01:03:33 +00:00
player_ship_read ( & only_player_ship , fp ) ;
Num_cockpits = PHYSFSX_readInt ( fp ) ;
2016-02-06 22:12:54 +00:00
bitmap_index_read_n ( fp , cockpit_bitmap ) ;
2013-03-03 01:03:33 +00:00
2020-08-24 01:31:28 +00:00
PHYSFS_read ( fp , Sounds , sizeof ( Sounds [ 0 ] ) , MAX_SOUNDS ) ;
PHYSFS_read ( fp , AltSounds , sizeof ( AltSounds [ 0 ] ) , MAX_SOUNDS ) ;
2013-03-03 01:03:33 +00:00
Num_total_object_types = PHYSFSX_readInt ( fp ) ;
PHYSFS_read ( fp , ObjType , sizeof ( ubyte ) , MAX_OBJTYPE ) ;
PHYSFS_read ( fp , ObjId , sizeof ( ubyte ) , MAX_OBJTYPE ) ;
2015-10-09 02:46:09 +00:00
range_for ( auto & i , ObjStrength )
i = PHYSFSX_readFix ( fp ) ;
2013-03-03 01:03:33 +00:00
First_multi_bitmap_num = PHYSFSX_readInt ( fp ) ;
Reactors [ 0 ] . n_guns = PHYSFSX_readInt ( fp ) ;
2014-12-05 03:08:10 +00:00
range_for ( auto & i , Reactors [ 0 ] . gun_points )
PHYSFSX_readVector ( fp , i ) ;
range_for ( auto & i , Reactors [ 0 ] . gun_dirs )
PHYSFSX_readVector ( fp , i ) ;
2013-03-03 01:03:33 +00:00
exit_modelnum = PHYSFSX_readInt ( fp ) ;
destroyed_exit_modelnum = PHYSFSX_readInt ( fp ) ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2013-03-03 01:03:33 +00:00
//Build tmaplist
2016-02-12 04:02:28 +00:00
auto & & effect_range = partial_const_range ( Effects , Num_effects ) ;
2018-12-30 00:43:59 +00:00
LevelUniqueTmapInfoState . Num_tmaps = TextureEffects + std : : count_if ( effect_range . begin ( ) , effect_range . end ( ) , [ ] ( const eclip & e ) { return e . changing_wall_texture > = 0 ; } ) ;
2013-03-03 01:03:33 +00:00
# endif
}
# elif defined(DXX_BUILD_DESCENT_II)
2020-12-26 21:17:29 +00:00
namespace {
2016-01-09 16:38:14 +00:00
static void tmap_info_read ( tmap_info & ti , PHYSFS_File * fp )
2006-03-20 17:12:09 +00:00
{
2021-11-01 03:37:20 +00:00
uint8_t flags ;
PHYSFS_read ( fp , & flags , 1 , 1 ) ;
ti . flags = tmapinfo_flags { flags } ;
2014-07-23 02:09:33 +00:00
PHYSFSX_readByte ( fp ) ;
PHYSFSX_readByte ( fp ) ;
PHYSFSX_readByte ( fp ) ;
2014-02-09 18:09:54 +00:00
ti . lighting = PHYSFSX_readFix ( fp ) ;
ti . damage = PHYSFSX_readFix ( fp ) ;
ti . eclip_num = PHYSFSX_readShort ( fp ) ;
ti . destroyed = PHYSFSX_readShort ( fp ) ;
ti . slide_u = PHYSFSX_readShort ( fp ) ;
ti . slide_v = PHYSFSX_readShort ( fp ) ;
2006-03-20 17:12:09 +00:00
}
2020-12-26 21:17:29 +00:00
}
2006-03-20 17:12:09 +00:00
//-----------------------------------------------------------------
2008-02-11 12:12:57 +00:00
// Initializes game properties data (including texture caching system) and sound data.
2022-07-09 13:39:29 +00:00
int gamedata_init ( d_level_shared_robot_info_state & LevelSharedRobotInfoState )
2006-03-20 17:12:09 +00:00
{
2020-08-24 01:31:28 +00:00
init_polygon_models ( LevelSharedPolygonModelState ) ;
2006-03-20 17:12:09 +00:00
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2012-07-24 09:18:13 +00:00
// The pc_shareware argument is currently unused for Descent 2,
// but *may* be useful for loading Descent 1 Shareware texture properties.
2022-07-09 13:39:29 +00:00
if ( ! gamedata_read_tbl ( LevelSharedRobotInfoState , Vclip , 0 ) )
2008-02-11 12:12:57 +00:00
# endif
2022-07-09 13:39:29 +00:00
if ( ! properties_init ( LevelSharedRobotInfoState ) ) // This calls properties_read_cmp
2012-07-24 09:18:13 +00:00
Error ( " Cannot open ham file \n " ) ;
2006-03-20 17:12:09 +00:00
2008-02-11 12:12:57 +00:00
piggy_read_sounds ( ) ;
2006-03-20 17:12:09 +00:00
return 0 ;
}
2022-07-09 13:39:29 +00:00
void bm_read_all ( d_level_shared_robot_info_state & LevelSharedRobotInfoState , d_vclip_array & Vclip , PHYSFS_File * fp )
2006-03-20 17:12:09 +00:00
{
2019-03-03 00:31:09 +00:00
auto & Effects = LevelUniqueEffectsClipState . Effects ;
2018-12-30 00:43:59 +00:00
auto & Robot_joints = LevelSharedRobotJointState . Robot_joints ;
2018-12-30 00:43:59 +00:00
auto & TmapInfo = LevelUniqueTmapInfoState . TmapInfo ;
2020-04-04 19:30:22 +00:00
auto & WallAnims = GameSharedState . WallAnims ;
2016-02-06 22:12:54 +00:00
unsigned t ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
NumTextures = PHYSFSX_readInt ( fp ) ;
2015-02-14 22:48:30 +00:00
bitmap_index_read_n ( fp , partial_range ( Textures , NumTextures ) ) ;
2014-02-09 18:09:54 +00:00
range_for ( tmap_info & ti , partial_range ( TmapInfo , NumTextures ) )
tmap_info_read ( ti , fp ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ;
PHYSFS_read ( fp , Sounds , sizeof ( ubyte ) , t ) ;
PHYSFS_read ( fp , AltSounds , sizeof ( ubyte ) , t ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
Num_vclips = PHYSFSX_readInt ( fp ) ;
2014-01-18 18:02:02 +00:00
range_for ( vclip & vc , partial_range ( Vclip , Num_vclips ) )
vclip_read ( fp , vc ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
Num_effects = PHYSFSX_readInt ( fp ) ;
2014-01-18 18:02:02 +00:00
range_for ( eclip & ec , partial_range ( Effects , Num_effects ) )
eclip_read ( fp , ec ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
Num_wall_anims = PHYSFSX_readInt ( fp ) ;
2014-02-02 05:30:48 +00:00
range_for ( auto & w , partial_range ( WallAnims , Num_wall_anims ) )
wclip_read ( fp , w ) ;
2006-03-20 17:12:09 +00:00
2018-12-30 00:43:59 +00:00
auto & Robot_info = LevelSharedRobotInfoState . Robot_info ;
2018-12-30 00:43:59 +00:00
LevelSharedRobotInfoState . N_robot_types = PHYSFSX_readInt ( fp ) ;
range_for ( auto & r , partial_range ( Robot_info , LevelSharedRobotInfoState . N_robot_types ) )
2015-01-23 03:55:04 +00:00
robot_info_read ( fp , r ) ;
2006-03-20 17:12:09 +00:00
2020-08-24 01:31:28 +00:00
const auto N_robot_joints = LevelSharedRobotJointState . N_robot_joints = PHYSFSX_readInt ( fp ) ;
2014-12-18 04:12:38 +00:00
range_for ( auto & r , partial_range ( Robot_joints , N_robot_joints ) )
jointpos_read ( fp , r ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
N_weapon_types = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
weapon_info_read_n ( Weapon_info , N_weapon_types , fp , Piggy_hamfile_version ) ;
2011-06-01 07:59:55 +00:00
N_powerup_types = PHYSFSX_readInt ( fp ) ;
2014-01-18 18:02:02 +00:00
range_for ( auto & p , partial_range ( Powerup_info , N_powerup_types ) )
powerup_type_info_read ( fp , p ) ;
2006-03-20 17:12:09 +00:00
2018-12-30 00:43:59 +00:00
auto & Polygon_models = LevelSharedPolygonModelState . Polygon_models ;
2020-08-24 01:31:28 +00:00
const auto N_polygon_models = LevelSharedPolygonModelState . N_polygon_models = PHYSFSX_readInt ( fp ) ;
2016-02-06 22:12:54 +00:00
{
const auto & & r = partial_range ( Polygon_models , N_polygon_models ) ;
range_for ( auto & p , r )
2014-02-09 18:09:54 +00:00
polymodel_read ( & p , fp ) ;
2006-03-20 17:12:09 +00:00
2016-02-06 22:12:54 +00:00
range_for ( auto & p , r )
2014-02-09 18:09:54 +00:00
polygon_model_data_read ( & p , fp ) ;
2016-02-06 22:12:54 +00:00
}
2006-03-20 17:12:09 +00:00
2016-02-06 22:12:54 +00:00
range_for ( auto & i , partial_range ( Dying_modelnums , N_polygon_models ) )
i = PHYSFSX_readInt ( fp ) ;
range_for ( auto & i , partial_range ( Dead_modelnums , N_polygon_models ) )
i = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ;
2016-02-06 22:12:54 +00:00
bitmap_index_read_n ( fp , partial_range ( Gauges , t ) ) ;
bitmap_index_read_n ( fp , partial_range ( Gauges_hires , t ) ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
N_ObjBitmaps = PHYSFSX_readInt ( fp ) ;
2016-02-06 22:12:54 +00:00
bitmap_index_read_n ( fp , partial_range ( ObjBitmaps , N_ObjBitmaps ) ) ;
range_for ( auto & i , partial_range ( ObjBitmapPtrs , N_ObjBitmaps ) )
2020-10-07 03:59:14 +00:00
{
const auto oi = static_cast < object_bitmap_index > ( PHYSFSX_readShort ( fp ) ) ;
if ( ObjBitmaps . valid_index ( oi ) )
i = oi ;
else
i = { } ;
}
2006-03-20 17:12:09 +00:00
player_ship_read ( & only_player_ship , fp ) ;
2011-06-01 07:59:55 +00:00
Num_cockpits = PHYSFSX_readInt ( fp ) ;
2016-02-06 22:12:54 +00:00
bitmap_index_read_n ( fp , partial_range ( cockpit_bitmap , Num_cockpits ) ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
//@@ PHYSFS_read( fp, &Num_total_object_types, sizeof(int), 1 );
//@@ PHYSFS_read( fp, ObjType, sizeof(byte), Num_total_object_types );
//@@ PHYSFS_read( fp, ObjId, sizeof(byte), Num_total_object_types );
//@@ PHYSFS_read( fp, ObjStrength, sizeof(fix), Num_total_object_types );
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
First_multi_bitmap_num = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
Num_reactors = PHYSFSX_readInt ( fp ) ;
2015-02-28 19:36:01 +00:00
reactor_read_n ( fp , partial_range ( Reactors , Num_reactors ) ) ;
2006-03-20 17:12:09 +00:00
2020-08-24 01:31:28 +00:00
LevelSharedPolygonModelState . Marker_model_num = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
//@@PHYSFS_read( fp, &N_controlcen_guns, sizeof(int), 1 );
//@@PHYSFS_read( fp, controlcen_gun_points, sizeof(vms_vector), N_controlcen_guns );
//@@PHYSFS_read( fp, controlcen_gun_dirs, sizeof(vms_vector), N_controlcen_guns );
2006-03-20 17:12:09 +00:00
2019-12-18 11:39:07 +00:00
if ( Piggy_hamfile_version < 3 ) { // D1
2011-06-01 07:59:55 +00:00
exit_modelnum = PHYSFSX_readInt ( fp ) ;
destroyed_exit_modelnum = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
}
2019-12-18 11:39:07 +00:00
else // D2: to be loaded later
2006-03-20 17:12:09 +00:00
exit_modelnum = destroyed_exit_modelnum = N_polygon_models ;
}
2020-10-07 03:59:14 +00:00
namespace {
2020-08-24 01:31:28 +00:00
// this and below only really used for D2
2019-12-18 11:39:07 +00:00
bool Exit_bitmaps_loaded ;
2019-12-19 13:33:58 +00:00
unsigned Exit_bitmap_index ;
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
static void bm_free_extra_objbitmaps ( )
2006-03-20 17:12:09 +00:00
{
int i ;
if ( ! extra_bitmap_num )
extra_bitmap_num = Num_bitmap_files ;
for ( i = Num_bitmap_files ; i < extra_bitmap_num ; i + + )
{
N_ObjBitmaps - - ;
2014-12-02 03:24:38 +00:00
d_free ( GameBitmaps [ i ] . bm_mdata ) ;
2006-03-20 17:12:09 +00:00
}
extra_bitmap_num = Num_bitmap_files ;
2019-12-18 11:39:07 +00:00
Exit_bitmaps_loaded = false ;
2006-03-20 17:12:09 +00:00
}
2020-08-24 01:31:28 +00:00
static void bm_free_extra_models ( d_level_shared_polygon_model_state & LevelSharedPolygonModelState )
2006-03-20 17:12:09 +00:00
{
2020-08-24 01:31:28 +00:00
LevelSharedPolygonModelState . Exit_models_loaded = false ;
2017-10-14 17:10:30 +00:00
const auto base = std : : min ( N_D2_POLYGON_MODELS . value , exit_modelnum ) ;
2020-08-24 01:31:28 +00:00
for ( auto & p : partial_range ( LevelSharedPolygonModelState . Polygon_models , base , std : : exchange ( LevelSharedPolygonModelState . N_polygon_models , base ) ) )
2017-02-19 19:33:44 +00:00
free_model ( p ) ;
2006-03-20 17:12:09 +00:00
}
2020-10-07 03:59:14 +00:00
}
2006-03-20 17:12:09 +00:00
//type==1 means 1.1, type==2 means 1.2 (with weapons)
2016-01-09 16:38:09 +00:00
void bm_read_extra_robots ( const char * fname , Mission : : descent_version_type type )
2006-03-20 17:12:09 +00:00
{
2018-12-30 00:43:59 +00:00
auto & Robot_joints = LevelSharedRobotJointState . Robot_joints ;
2016-02-06 22:12:54 +00:00
int t , version ;
2006-03-20 17:12:09 +00:00
2021-07-25 23:00:56 +00:00
auto & & [ fp , physfserr ] = PHYSFSX_openReadBuffered ( fname ) ;
2012-12-23 22:39:29 +00:00
if ( ! fp )
{
2021-07-25 23:00:56 +00:00
Error ( " Failed to open HAM file \" %s \" : %s " , fname , PHYSFS_getErrorByCode ( physfserr ) ) ;
2012-12-23 22:39:29 +00:00
return ;
}
2006-03-20 17:12:09 +00:00
2016-01-09 16:38:09 +00:00
if ( type = = Mission : : descent_version_type : : descent2z )
{
2006-03-20 17:12:09 +00:00
int sig ;
2011-06-01 07:59:55 +00:00
sig = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
if ( sig ! = MAKE_SIG ( ' X ' , ' H ' , ' A ' , ' M ' ) )
return ;
2011-06-01 07:59:55 +00:00
version = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
}
else
version = 0 ;
2011-09-26 21:00:24 +00:00
( void ) version ; // NOTE: we do not need it, but keep it for possible further use
2006-03-20 17:12:09 +00:00
2020-08-24 01:31:28 +00:00
bm_free_extra_models ( LevelSharedPolygonModelState ) ;
2006-03-20 17:12:09 +00:00
bm_free_extra_objbitmaps ( ) ;
//read extra weapons
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
N_weapon_types = N_D2_WEAPON_TYPES + t ;
2014-09-27 17:55:46 +00:00
weapon_info_read_n ( Weapon_info , N_weapon_types , fp , 3 , N_D2_WEAPON_TYPES ) ;
2006-03-20 17:12:09 +00:00
//now read robot info
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ;
2018-12-30 00:43:59 +00:00
const auto N_robot_types = LevelSharedRobotInfoState . N_robot_types = N_D2_ROBOT_TYPES + t ;
2006-03-20 17:12:09 +00:00
if ( N_robot_types > = MAX_ROBOT_TYPES )
Error ( " Too many robots (%d) in <%s>. Max is %d. " , t , fname , MAX_ROBOT_TYPES - N_D2_ROBOT_TYPES ) ;
2018-12-30 00:43:59 +00:00
auto & Robot_info = LevelSharedRobotInfoState . Robot_info ;
2017-10-14 17:10:30 +00:00
range_for ( auto & r , partial_range ( Robot_info , N_D2_ROBOT_TYPES . value , N_robot_types ) )
2015-01-23 03:55:04 +00:00
robot_info_read ( fp , r ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ;
2020-08-24 01:31:28 +00:00
const auto N_robot_joints = LevelSharedRobotJointState . N_robot_joints = N_D2_ROBOT_JOINTS + t ;
2006-03-20 17:12:09 +00:00
if ( N_robot_joints > = MAX_ROBOT_JOINTS )
Error ( " Too many robot joints (%d) in <%s>. Max is %d. " , t , fname , MAX_ROBOT_JOINTS - N_D2_ROBOT_JOINTS ) ;
2017-10-14 17:10:30 +00:00
range_for ( auto & r , partial_range ( Robot_joints , N_D2_ROBOT_JOINTS . value , N_robot_joints ) )
2014-12-18 04:12:38 +00:00
jointpos_read ( fp , r ) ;
2006-03-20 17:12:09 +00:00
2014-07-26 04:01:49 +00:00
unsigned u = PHYSFSX_readInt ( fp ) ;
2018-12-30 00:43:59 +00:00
auto & Polygon_models = LevelSharedPolygonModelState . Polygon_models ;
2020-08-24 01:31:28 +00:00
const auto N_polygon_models = LevelSharedPolygonModelState . N_polygon_models = N_D2_POLYGON_MODELS + u ;
2006-03-20 17:12:09 +00:00
if ( N_polygon_models > = MAX_POLYGON_MODELS )
2014-07-26 04:01:49 +00:00
Error ( " Too many polygon models (%d) in <%s>. Max is %d. " , u , fname , MAX_POLYGON_MODELS - N_D2_POLYGON_MODELS ) ;
2016-02-06 22:12:54 +00:00
{
2017-10-14 17:10:30 +00:00
const auto & & r = partial_range ( Polygon_models , N_D2_POLYGON_MODELS . value , N_polygon_models ) ;
2016-02-06 22:12:54 +00:00
range_for ( auto & p , r )
2014-07-26 04:01:49 +00:00
polymodel_read ( & p , fp ) ;
2006-03-20 17:12:09 +00:00
2016-02-06 22:12:54 +00:00
range_for ( auto & p , r )
polygon_model_data_read ( & p , fp ) ;
}
2006-03-20 17:12:09 +00:00
2017-10-14 17:10:30 +00:00
range_for ( auto & i , partial_range ( Dying_modelnums , N_D2_POLYGON_MODELS . value , N_polygon_models ) )
2016-02-06 22:12:54 +00:00
i = PHYSFSX_readInt ( fp ) ;
2017-10-14 17:10:30 +00:00
range_for ( auto & i , partial_range ( Dead_modelnums , N_D2_POLYGON_MODELS . value , N_polygon_models ) )
2016-02-06 22:12:54 +00:00
i = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ;
2016-07-10 04:11:35 +00:00
if ( N_D2_OBJBITMAPS + t > = ObjBitmaps . size ( ) )
2016-10-08 18:02:34 +00:00
Error ( " Too many object bitmaps (%d) in <%s>. Max is % " DXX_PRI_size_type " . " , t , fname , ObjBitmaps . size ( ) - N_D2_OBJBITMAPS ) ;
2017-10-14 17:10:30 +00:00
bitmap_index_read_n ( fp , partial_range ( ObjBitmaps , N_D2_OBJBITMAPS . value , N_D2_OBJBITMAPS + t ) ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ;
2016-07-10 04:11:35 +00:00
if ( N_D2_OBJBITMAPPTRS + t > = ObjBitmapPtrs . size ( ) )
2016-10-08 18:02:34 +00:00
Error ( " Too many object bitmap pointers (%d) in <%s>. Max is % " DXX_PRI_size_type " . " , t , fname , ObjBitmapPtrs . size ( ) - N_D2_OBJBITMAPPTRS ) ;
2017-10-14 17:10:30 +00:00
range_for ( auto & i , partial_range ( ObjBitmapPtrs , N_D2_OBJBITMAPPTRS . value , N_D2_OBJBITMAPPTRS + t ) )
2020-10-07 03:59:14 +00:00
{
const auto oi = static_cast < object_bitmap_index > ( PHYSFSX_readShort ( fp ) ) ;
if ( ObjBitmaps . valid_index ( oi ) )
i = oi ;
else
i = { } ;
}
2006-03-20 17:12:09 +00:00
}
int Robot_replacements_loaded = 0 ;
2014-07-23 02:27:22 +00:00
void load_robot_replacements ( const d_fname & level_name )
2006-03-20 17:12:09 +00:00
{
2018-12-30 00:43:59 +00:00
auto & Robot_joints = LevelSharedRobotJointState . Robot_joints ;
2020-08-24 01:31:28 +00:00
int t , j ;
2006-03-20 17:12:09 +00:00
char ifile_name [ FILENAME_LEN ] ;
change_filename_extension ( ifile_name , level_name , " .HXM " ) ;
2021-07-25 23:00:56 +00:00
auto fp = PHYSFSX_openReadBuffered ( ifile_name ) . first ;
2006-03-20 17:12:09 +00:00
if ( ! fp ) //no robot replacement file
return ;
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ; //read id "HXM!"
2006-03-20 17:12:09 +00:00
if ( t ! = 0x21584d48 )
Error ( " ID of HXM! file incorrect " ) ;
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ; //read version
2006-03-20 17:12:09 +00:00
if ( t < 1 )
Error ( " HXM! version too old (%d) " , t ) ;
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ; //read number of robots
2018-12-30 00:43:59 +00:00
auto & Robot_info = LevelSharedRobotInfoState . Robot_info ;
2018-12-30 00:43:59 +00:00
const auto N_robot_types = LevelSharedRobotInfoState . N_robot_types ;
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < t ; j + + ) {
2020-08-24 01:31:28 +00:00
const unsigned i = PHYSFSX_readInt ( fp ) ; //read robot number
if ( i > = N_robot_types )
Error ( " Robots number (%u) out of range in (%s). Range = [0..%u]. " , i , static_cast < const char * > ( level_name ) , N_robot_types - 1 ) ;
2015-01-23 03:55:04 +00:00
robot_info_read ( fp , Robot_info [ i ] ) ;
2006-03-20 17:12:09 +00:00
}
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ; //read number of joints
2020-08-24 01:31:28 +00:00
const auto N_robot_joints = LevelSharedRobotJointState . N_robot_joints ;
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < t ; j + + ) {
2020-08-24 01:31:28 +00:00
const unsigned i = PHYSFSX_readInt ( fp ) ; //read joint number
if ( i > = N_robot_joints )
Error ( " Robots joint (%u) out of range in (%s). Range = [0..%u]. " , i , static_cast < const char * > ( level_name ) , N_robot_joints - 1 ) ;
2014-12-18 04:12:38 +00:00
jointpos_read ( fp , Robot_joints [ i ] ) ;
2006-03-20 17:12:09 +00:00
}
2018-12-30 00:43:59 +00:00
auto & Polygon_models = LevelSharedPolygonModelState . Polygon_models ;
2020-08-24 01:31:28 +00:00
const auto N_polygon_models = LevelSharedPolygonModelState . N_polygon_models ;
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ; //read number of polygon models
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < t ; j + + )
{
2020-08-24 01:31:28 +00:00
const unsigned i = PHYSFSX_readInt ( fp ) ; //read model number
if ( i > = N_polygon_models )
Error ( " Polygon model (%u) out of range in (%s). Range = [0..%u]. " , i , static_cast < const char * > ( level_name ) , N_polygon_models - 1 ) ;
2006-03-20 17:12:09 +00:00
2017-02-19 19:33:44 +00:00
free_model ( Polygon_models [ i ] ) ;
2006-03-20 17:12:09 +00:00
polymodel_read ( & Polygon_models [ i ] , fp ) ;
polygon_model_data_read ( & Polygon_models [ i ] , fp ) ;
2011-06-01 07:59:55 +00:00
Dying_modelnums [ i ] = PHYSFSX_readInt ( fp ) ;
Dead_modelnums [ i ] = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
}
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ; //read number of objbitmaps
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < t ; j + + ) {
2020-10-07 03:59:14 +00:00
const auto oi = static_cast < object_bitmap_index > ( PHYSFSX_readInt ( fp ) ) ; //read objbitmap number
if ( ! ObjBitmaps . valid_index ( oi ) )
Error ( " Object bitmap number (%u) out of range in (%s). Range = [0..% " DXX_PRI_size_type " ]. " , static_cast < unsigned > ( oi ) , static_cast < const char * > ( level_name ) , ObjBitmaps . size ( ) - 1 ) ;
bitmap_index_read ( fp , ObjBitmaps [ oi ] ) ;
2006-03-20 17:12:09 +00:00
}
2011-06-01 07:59:55 +00:00
t = PHYSFSX_readInt ( fp ) ; //read number of objbitmapptrs
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < t ; j + + ) {
2020-08-24 01:31:28 +00:00
const unsigned i = PHYSFSX_readInt ( fp ) ; //read objbitmapptr number
if ( i > = ObjBitmapPtrs . size ( ) )
Error ( " Object bitmap pointer (%u) out of range in (%s). Range = [0..% " DXX_PRI_size_type " ]. " , i , static_cast < const char * > ( level_name ) , ObjBitmapPtrs . size ( ) - 1 ) ;
2020-10-07 03:59:14 +00:00
const auto oi = static_cast < object_bitmap_index > ( PHYSFSX_readShort ( fp ) ) ;
if ( ! ObjBitmaps . valid_index ( oi ) )
Error ( " Object bitmap number (%u) out of range in (%s). Range = [0..% " DXX_PRI_size_type " ]. " , static_cast < unsigned > ( oi ) , static_cast < const char * > ( level_name ) , ObjBitmaps . size ( ) - 1 ) ;
ObjBitmapPtrs [ i ] = oi ;
2006-03-20 17:12:09 +00:00
}
Robot_replacements_loaded = 1 ;
}
2020-10-07 03:59:14 +00:00
namespace {
2006-03-20 17:12:09 +00:00
/*
* Routines for loading exit models
*
* Used by d1 levels ( including some add - ons ) , and by d2 shareware .
* Could potentially be used by d2 add - on levels , but only if they
2019-12-18 11:39:07 +00:00
* don ' t use " extra " robots . . . or maybe they do
2006-03-20 17:12:09 +00:00
*/
// formerly exitmodel_bm_load_sub
2020-08-24 01:31:28 +00:00
static grs_bitmap * read_extra_bitmap_iff ( const char * filename , grs_bitmap & n )
2006-03-20 17:12:09 +00:00
{
2013-01-06 21:03:57 +00:00
palette_array_t newpal ;
2006-03-20 17:12:09 +00:00
int iff_error ; //reference parm to avoid warning message
//MALLOC( new, grs_bitmap, 1 );
2020-08-24 01:31:28 +00:00
iff_error = iff_read_bitmap ( filename , n , & newpal ) ;
2006-03-20 17:12:09 +00:00
if ( iff_error ! = IFF_NO_ERROR ) {
2013-12-07 00:47:27 +00:00
con_printf ( CON_DEBUG , " Error loading exit model bitmap <%s> - IFF error: %s " , filename , iff_errormsg ( iff_error ) ) ;
2020-08-24 01:31:28 +00:00
return nullptr ;
2006-03-20 17:12:09 +00:00
}
2020-08-24 01:31:28 +00:00
gr_remap_bitmap_good ( n , newpal , iff_has_transparency ? iff_transparent_color : - 1 , 254 ) ;
2006-03-20 17:12:09 +00:00
2020-05-22 02:40:26 +00:00
# if !DXX_USE_OGL
2020-08-24 01:31:28 +00:00
n . avg_color = 0 ; //compute_average_pixel(new);
2020-05-22 02:40:26 +00:00
# endif
2020-08-24 01:31:28 +00:00
return & n ;
2006-03-20 17:12:09 +00:00
}
// formerly load_exit_model_bitmap
2013-10-27 22:00:14 +00:00
static grs_bitmap * bm_load_extra_objbitmap ( const char * name )
2006-03-20 17:12:09 +00:00
{
2020-10-07 03:59:14 +00:00
const auto oi = static_cast < object_bitmap_index > ( N_ObjBitmaps ) ;
if ( ! ObjBitmaps . valid_index ( oi ) )
return nullptr ;
2006-03-20 17:12:09 +00:00
{
2020-10-07 03:59:14 +00:00
auto & bitmap_idx = ObjBitmaps [ oi ] ;
2020-08-24 01:31:28 +00:00
const auto bitmap_store_index = bitmap_index { static_cast < uint16_t > ( extra_bitmap_num ) } ;
grs_bitmap & n = GameBitmaps [ bitmap_store_index . index ] ;
if ( ! read_extra_bitmap_iff ( name , n ) )
2006-03-20 17:12:09 +00:00
{
2015-01-28 03:42:53 +00:00
RAIIdmem < char [ ] > name2 ( d_strdup ( name ) ) ;
2015-02-17 03:52:59 +00:00
* strrchr ( name2 . get ( ) , ' . ' ) = ' \0 ' ;
2020-08-24 01:31:28 +00:00
if ( const auto r = read_extra_bitmap_d1_pig ( name2 . get ( ) , n ) ; ! r )
return r ;
2006-03-20 17:12:09 +00:00
}
2020-08-24 01:31:28 +00:00
bitmap_idx = bitmap_store_index ;
+ + extra_bitmap_num ;
2006-03-20 17:12:09 +00:00
2020-08-24 01:31:28 +00:00
if ( n . bm_w ! = 64 | | n . bm_h ! = 64 )
2006-03-20 17:12:09 +00:00
Error ( " Bitmap <%s> is not 64x64 " , name ) ;
2020-10-07 03:59:14 +00:00
ObjBitmapPtrs [ N_ObjBitmaps ] = oi ;
2006-03-20 17:12:09 +00:00
N_ObjBitmaps + + ;
2016-07-10 04:11:35 +00:00
assert ( N_ObjBitmaps < ObjBitmaps . size ( ) ) ;
2020-08-24 01:31:28 +00:00
return & n ;
2006-03-20 17:12:09 +00:00
}
}
2019-12-18 11:39:07 +00:00
static void bm_unload_last_objbitmaps ( unsigned count )
2019-12-12 15:25:11 +00:00
{
2019-12-18 11:39:07 +00:00
assert ( N_ObjBitmaps > = count ) ;
unsigned new_N_ObjBitmaps = N_ObjBitmaps - count ;
range_for ( auto & o , partial_range ( ObjBitmaps , new_N_ObjBitmaps , N_ObjBitmaps ) )
d_free ( GameBitmaps [ o . index ] . bm_mdata ) ;
N_ObjBitmaps = new_N_ObjBitmaps ;
2019-12-12 15:25:11 +00:00
}
2020-10-07 03:59:14 +00:00
}
2019-12-18 11:39:07 +00:00
// only called for D2 registered, but there is a D1 check anyway for
// possible later use
2006-03-20 17:12:09 +00:00
int load_exit_models ( )
{
int start_num ;
2019-12-12 15:25:11 +00:00
/*
2019-12-21 21:29:41 +00:00
don ' t free extra models in native D2 mode - - ziplantil . it ' s our
responsibility to make sure the exit stuff is already loaded rather than
loading it all again .
however , in D1 mode , we always need to reload everything due to how
the exit data is loaded ( which is different from D2 native mode )
2019-12-12 15:25:11 +00:00
*/
2019-12-21 21:29:41 +00:00
if ( EMULATING_D1 ) // D1?
{
2020-08-24 01:31:28 +00:00
bm_free_extra_models ( LevelSharedPolygonModelState ) ;
2019-12-21 21:29:41 +00:00
bm_free_extra_objbitmaps ( ) ;
}
2020-11-29 19:48:52 +00:00
else if ( ! Exit_bitmaps_loaded )
{
extra_bitmap_num = Num_bitmap_files ;
}
2006-03-20 17:12:09 +00:00
2019-12-12 15:34:42 +00:00
// make sure there is enough space to load textures and models
2019-12-18 11:39:07 +00:00
if ( ! Exit_bitmaps_loaded & & N_ObjBitmaps > ObjBitmaps . size ( ) - 6 )
2019-12-12 15:34:42 +00:00
{
return 0 ;
}
2020-08-24 01:31:28 +00:00
if ( ! LevelSharedPolygonModelState . Exit_models_loaded & & LevelSharedPolygonModelState . N_polygon_models > MAX_POLYGON_MODELS - 2 )
2019-12-12 15:34:42 +00:00
{
return 0 ;
}
2006-03-20 17:12:09 +00:00
start_num = N_ObjBitmaps ;
2019-12-19 13:33:58 +00:00
if ( ! Exit_bitmaps_loaded )
2006-03-20 17:12:09 +00:00
{
2019-12-19 13:33:58 +00:00
if ( ! bm_load_extra_objbitmap ( " steel1.bbm " ) | |
! bm_load_extra_objbitmap ( " rbot061.bbm " ) | |
! bm_load_extra_objbitmap ( " rbot062.bbm " ) | |
! bm_load_extra_objbitmap ( " steel1.bbm " ) | |
! bm_load_extra_objbitmap ( " rbot061.bbm " ) | |
! bm_load_extra_objbitmap ( " rbot063.bbm " ) )
{
// unload the textures that we already loaded
bm_unload_last_objbitmaps ( N_ObjBitmaps - start_num ) ;
con_puts ( CON_NORMAL , " Can't load exit models! " ) ;
return 0 ;
}
Exit_bitmap_index = start_num ;
2006-03-20 17:12:09 +00:00
}
2019-12-18 11:39:07 +00:00
2019-12-19 13:33:58 +00:00
auto & Polygon_models = LevelSharedPolygonModelState . Polygon_models ;
2020-08-24 01:31:28 +00:00
if ( LevelSharedPolygonModelState . Exit_models_loaded & & exit_modelnum < LevelSharedPolygonModelState . N_polygon_models & & destroyed_exit_modelnum < LevelSharedPolygonModelState . N_polygon_models )
2019-12-18 11:39:07 +00:00
{
2019-12-19 13:33:58 +00:00
// already loaded, just adjust texture indexes
Polygon_models [ exit_modelnum ] . first_texture = Exit_bitmap_index ;
Polygon_models [ destroyed_exit_modelnum ] . first_texture = Exit_bitmap_index + 3 ;
2019-12-18 11:39:07 +00:00
return 1 ;
}
2021-07-25 23:00:56 +00:00
if ( auto exit_hamfile = PHYSFSX_openReadBuffered ( " exit.ham " ) . first )
2015-01-17 18:31:42 +00:00
{
2020-08-24 01:31:28 +00:00
exit_modelnum = LevelSharedPolygonModelState . N_polygon_models + + ;
destroyed_exit_modelnum = LevelSharedPolygonModelState . N_polygon_models + + ;
2006-03-20 17:12:09 +00:00
polymodel_read ( & Polygon_models [ exit_modelnum ] , exit_hamfile ) ;
polymodel_read ( & Polygon_models [ destroyed_exit_modelnum ] , exit_hamfile ) ;
Polygon_models [ exit_modelnum ] . first_texture = start_num ;
Polygon_models [ destroyed_exit_modelnum ] . first_texture = start_num + 3 ;
polygon_model_data_read ( & Polygon_models [ exit_modelnum ] , exit_hamfile ) ;
polygon_model_data_read ( & Polygon_models [ destroyed_exit_modelnum ] , exit_hamfile ) ;
2011-06-01 07:59:55 +00:00
} else if ( PHYSFSX_exists ( " exit01.pof " , 1 ) & & PHYSFSX_exists ( " exit01d.pof " , 1 ) ) {
2006-03-20 17:12:09 +00:00
exit_modelnum = load_polygon_model ( " exit01.pof " , 3 , start_num , NULL ) ;
destroyed_exit_modelnum = load_polygon_model ( " exit01d.pof " , 3 , start_num + 3 , NULL ) ;
2016-09-24 18:06:11 +00:00
# if DXX_USE_OGL
2006-03-20 17:12:09 +00:00
ogl_cache_polymodel_textures ( exit_modelnum ) ;
ogl_cache_polymodel_textures ( destroyed_exit_modelnum ) ;
# endif
}
2021-07-25 23:00:56 +00:00
else if ( ( exit_hamfile = PHYSFSX_openReadBuffered ( D1_PIGFILE ) . first ) )
2006-03-20 17:12:09 +00:00
{
int offset , offset2 ;
int hamsize ;
2011-06-01 07:59:55 +00:00
hamsize = PHYSFS_fileLength ( exit_hamfile ) ;
2006-03-20 17:12:09 +00:00
switch ( hamsize ) { //total hack for loading models
case D1_PIGSIZE :
offset = 91848 ; /* and 92582 */
offset2 = 383390 ; /* and 394022 */
break ;
default :
case D1_SHARE_BIG_PIGSIZE :
case D1_SHARE_10_PIGSIZE :
case D1_SHARE_PIGSIZE :
case D1_10_BIG_PIGSIZE :
case D1_10_PIGSIZE :
Int3 ( ) ; /* exit models should be in .pofs */
2022-01-09 15:25:42 +00:00
[[fallthrough]] ;
2006-03-20 17:12:09 +00:00
case D1_OEM_PIGSIZE :
case D1_MAC_PIGSIZE :
case D1_MAC_SHARE_PIGSIZE :
2019-12-12 15:25:11 +00:00
// unload the textures that we already loaded
bm_unload_last_objbitmaps ( N_ObjBitmaps - start_num ) ;
2017-12-05 05:29:55 +00:00
con_puts ( CON_NORMAL , " Can't load exit models! " ) ;
2006-03-20 17:12:09 +00:00
return 0 ;
}
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( exit_hamfile , offset , SEEK_SET ) ;
2020-08-24 01:31:28 +00:00
exit_modelnum = LevelSharedPolygonModelState . N_polygon_models + + ;
destroyed_exit_modelnum = LevelSharedPolygonModelState . N_polygon_models + + ;
2006-03-20 17:12:09 +00:00
polymodel_read ( & Polygon_models [ exit_modelnum ] , exit_hamfile ) ;
polymodel_read ( & Polygon_models [ destroyed_exit_modelnum ] , exit_hamfile ) ;
Polygon_models [ exit_modelnum ] . first_texture = start_num ;
Polygon_models [ destroyed_exit_modelnum ] . first_texture = start_num + 3 ;
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( exit_hamfile , offset2 , SEEK_SET ) ;
2006-03-20 17:12:09 +00:00
polygon_model_data_read ( & Polygon_models [ exit_modelnum ] , exit_hamfile ) ;
polygon_model_data_read ( & Polygon_models [ destroyed_exit_modelnum ] , exit_hamfile ) ;
} else {
2019-12-12 15:25:11 +00:00
// unload the textures that we already loaded
bm_unload_last_objbitmaps ( N_ObjBitmaps - start_num ) ;
2017-12-05 05:29:55 +00:00
con_puts ( CON_NORMAL , " Can't load exit models! " ) ;
2006-03-20 17:12:09 +00:00
return 0 ;
}
2019-12-21 21:29:41 +00:00
// set to be loaded, but only on D2 - always reload the data on D1
2020-08-24 01:31:28 +00:00
LevelSharedPolygonModelState . Exit_models_loaded = Exit_bitmaps_loaded = ! EMULATING_D1 ;
2006-03-20 17:12:09 +00:00
return 1 ;
}
2020-10-07 03:59:14 +00:00
# endif
2020-01-18 21:57:39 +00:00
}
2011-04-12 01:02:51 +00:00
2020-05-02 21:18:42 +00:00
void compute_average_rgb ( grs_bitmap * bm , std : : array < fix , 3 > & rgb )
2011-04-12 01:02:51 +00:00
{
2014-07-19 03:08:19 +00:00
rgb = { } ;
2015-01-29 04:27:36 +00:00
if ( unlikely ( ! bm - > get_bitmap_data ( ) ) )
return ;
const uint_fast32_t bm_h = bm - > bm_h ;
const uint_fast32_t bm_w = bm - > bm_w ;
if ( unlikely ( ! bm_h ) | | unlikely ( ! bm_w ) )
2011-04-12 01:02:51 +00:00
return ;
2015-01-29 04:27:36 +00:00
const auto process_one = [ & rgb ] ( uint8_t color ) {
if ( color = = TRANSPARENCY_COLOR )
return ;
auto & t_rgb = gr_palette [ color ] ;
if ( t_rgb . r = = t_rgb . g & & t_rgb . r = = t_rgb . b )
return ;
rgb [ 0 ] + = t_rgb . r ;
rgb [ 1 ] + = t_rgb . g ;
rgb [ 2 ] + = t_rgb . b ;
} ;
2017-01-15 00:03:13 +00:00
if ( bm - > get_flag_mask ( BM_FLAG_RLE ) )
{
2017-02-11 21:42:30 +00:00
bm_rle_expand expander ( * bm ) ;
2020-05-02 21:18:42 +00:00
const auto & & buf = std : : make_unique < uint8_t [ ] > ( bm_w ) ;
2019-05-04 18:27:37 +00:00
range_for ( const uint_fast32_t i , xrange ( bm_h ) )
2015-01-29 04:27:36 +00:00
{
2019-05-04 18:27:36 +00:00
( void ) i ;
2017-02-11 21:42:30 +00:00
const auto & & range = unchecked_partial_range ( buf . get ( ) , bm_w ) ;
if ( expander . step ( bm_rle_expand_range ( range . begin ( ) , range . end ( ) ) ) ! = bm_rle_expand : : again )
break ;
range_for ( const auto color , range )
2015-01-29 04:27:36 +00:00
process_one ( color ) ;
2011-04-12 01:02:51 +00:00
}
}
else
{
2015-02-05 03:03:49 +00:00
range_for ( const auto color , unchecked_partial_range ( bm - > bm_data , bm_w * bm_h ) )
2015-01-29 04:27:36 +00:00
process_one ( color ) ;
2011-04-12 01:02:51 +00:00
}
}