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"
# include "internal.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"
2015-01-29 04:27:36 +00:00
# include "compiler-make_unique.h"
2014-01-18 18:02:02 +00:00
# include "partial_range.h"
2014-12-14 05:22:59 +00:00
array < ubyte , MAX_SOUNDS > Sounds , AltSounds ;
2006-03-20 17:12:09 +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
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
int Marker_model_num = - 1 ;
2016-02-06 22:12:54 +00:00
unsigned N_ObjBitmaps ;
2013-11-10 03:31:22 +00:00
static void bm_free_extra_objbitmaps ( ) ;
2013-03-03 01:03:33 +00:00
# endif
2013-11-10 03:31:22 +00:00
2016-06-25 23:21:36 +00:00
namespace dsx {
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
2015-04-02 02:36:52 +00:00
array < int , MAX_POLYGON_MODELS > Dying_modelnums , Dead_modelnums ;
2016-07-10 04:11:35 +00:00
TmapInfo_array TmapInfo ;
2016-10-02 19:35:34 +00:00
array < bitmap_index , N_COCKPIT_BITMAPS > cockpit_bitmap ;
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 {
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
unsigned Num_tmaps ;
}
2006-03-20 17:12:09 +00:00
//---------------- Variables for wall textures ------------------
//---------------- Variables for object textures ----------------
int First_multi_bitmap_num = - 1 ;
2015-02-14 22:48:30 +00:00
array < bitmap_index , MAX_OBJ_BITMAPS > ObjBitmaps ;
2015-04-02 02:36:52 +00:00
array < ushort , MAX_OBJ_BITMAPS > ObjBitmapPtrs ; // These point back into ObjBitmaps, since some are used twice.
2006-03-20 17:12:09 +00:00
2016-08-25 04:05:32 +00:00
namespace dsx {
2015-12-04 03:36:32 +00:00
void gamedata_close ( )
{
free_polygon_models ( ) ;
# if defined(DXX_BUILD_DESCENT_II)
bm_free_extra_objbitmaps ( ) ;
# endif
free_endlevel_data ( ) ;
rle_cache_close ( ) ;
piggy_close ( ) ;
}
2016-08-25 04:05:32 +00:00
}
2015-12-04 03:36:32 +00:00
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)
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 ) ;
ti . flags = PHYSFSX_readByte ( fp ) ;
ti . lighting = PHYSFSX_readFix ( fp ) ;
ti . damage = PHYSFSX_readFix ( fp ) ;
ti . eclip_num = PHYSFSX_readInt ( fp ) ;
2013-03-03 01:03:33 +00:00
}
//-----------------------------------------------------------------
// Initializes game properties data (including texture caching system) and sound data.
int gamedata_init ( )
{
int retval ;
init_polygon_models ( ) ;
init_endlevel ( ) ; //adb: added, is also in bm_init_use_tbl (Chris: *Was* in bm_init_use_tbl)
retval = properties_init ( ) ; // This calls properties_read_cmp if appropriate
if ( retval )
gamedata_read_tbl ( retval = = PIGGY_PC_SHAREWARE ) ;
piggy_read_sounds ( retval = = PIGGY_PC_SHAREWARE ) ;
return 0 ;
}
// Read compiled properties data from descent.pig
2016-01-09 16:38:14 +00:00
void properties_read_cmp ( PHYSFS_File * fp )
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
2016-07-14 01:59:04 +00:00
PHYSFS_read ( fp , Sounds , sizeof ( Sounds [ 0 ] ) , Sounds . size ( ) ) ;
PHYSFS_read ( fp , AltSounds , sizeof ( AltSounds [ 0 ] ) , AltSounds . size ( ) ) ;
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
N_robot_types = PHYSFSX_readInt ( fp ) ;
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
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
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 )
i = PHYSFSX_readShort ( fp ) ;
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
2016-07-14 01:59:04 +00:00
PHYSFS_read ( fp , Sounds , sizeof ( Sounds [ 0 ] ) , Sounds . size ( ) ) ;
PHYSFS_read ( fp , AltSounds , sizeof ( AltSounds [ 0 ] ) , AltSounds . size ( ) ) ;
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 ) ;
2015-10-09 02:46:09 +00:00
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)
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
{
2014-02-09 18:09:54 +00:00
ti . flags = PHYSFSX_readByte ( fp ) ;
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
}
//-----------------------------------------------------------------
2008-02-11 12:12:57 +00:00
// Initializes game properties data (including texture caching system) and sound data.
int gamedata_init ( )
2006-03-20 17:12:09 +00:00
{
init_polygon_models ( ) ;
2008-02-11 12:12:57 +00:00
init_endlevel ( ) ;
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.
if ( ! gamedata_read_tbl ( 0 ) )
2008-02-11 12:12:57 +00:00
# endif
2012-07-24 09:18:13 +00:00
if ( ! properties_init ( ) ) // This calls properties_read_cmp
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 ;
}
2016-01-09 16:38:14 +00:00
void bm_read_all ( PHYSFS_File * fp )
2006-03-20 17:12:09 +00:00
{
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
2011-06-01 07:59:55 +00:00
N_robot_types = PHYSFSX_readInt ( fp ) ;
2015-01-23 03:55:04 +00:00
range_for ( auto & r , partial_range ( Robot_info , N_robot_types ) )
robot_info_read ( fp , r ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
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
2011-06-01 07:59:55 +00:00
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 ) )
i = PHYSFSX_readShort ( fp ) ;
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
2011-06-01 07:59:55 +00:00
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
if ( Piggy_hamfile_version < 3 ) {
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
}
else
exit_modelnum = destroyed_exit_modelnum = N_polygon_models ;
}
int extra_bitmap_num = 0 ;
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 ;
}
2013-10-27 22:00:14 +00:00
static void bm_free_extra_models ( )
2006-03-20 17:12:09 +00:00
{
2014-09-28 21:51:49 +00:00
auto base = std : : min ( N_D2_POLYGON_MODELS , exit_modelnum ) ;
2017-02-19 19:33:44 +00:00
range_for ( auto & p , partial_range ( Polygon_models , base , exchange ( N_polygon_models , base ) ) )
free_model ( p ) ;
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
{
2016-02-06 22:12:54 +00:00
int t , version ;
2006-03-20 17:12:09 +00:00
2015-01-17 18:31:42 +00:00
auto fp = PHYSFSX_openReadBuffered ( fname ) ;
2012-12-23 22:39:29 +00:00
if ( ! fp )
{
Error ( " Failed to open HAM file \" %s \" " , fname ) ;
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
bm_free_extra_models ( ) ;
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 ) ;
2006-03-20 17:12:09 +00:00
N_robot_types = N_D2_ROBOT_TYPES + t ;
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 ) ;
2015-01-23 03:55:04 +00:00
range_for ( auto & r , partial_range ( Robot_info , N_D2_ROBOT_TYPES , N_robot_types ) )
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 ) ;
2006-03-20 17:12:09 +00:00
N_robot_joints = N_D2_ROBOT_JOINTS + t ;
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 ) ;
2014-12-18 04:12:38 +00:00
range_for ( auto & r , partial_range ( Robot_joints , N_D2_ROBOT_JOINTS , N_robot_joints ) )
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 ) ;
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
{
const auto & & r = partial_range ( Polygon_models , N_D2_POLYGON_MODELS , N_polygon_models ) ;
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
2016-02-06 22:12:54 +00:00
range_for ( auto & i , partial_range ( Dying_modelnums , N_D2_POLYGON_MODELS , N_polygon_models ) )
i = PHYSFSX_readInt ( fp ) ;
range_for ( auto & i , partial_range ( Dead_modelnums , N_D2_POLYGON_MODELS , 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-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 ) ;
2015-02-14 22:48:30 +00:00
bitmap_index_read_n ( fp , partial_range ( ObjBitmaps , N_D2_OBJBITMAPS , 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 ) ;
2016-02-06 22:12:54 +00:00
range_for ( auto & i , partial_range ( ObjBitmapPtrs , N_D2_OBJBITMAPPTRS , N_D2_OBJBITMAPPTRS + t ) )
i = PHYSFSX_readShort ( fp ) ;
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
{
int t , i , j ;
char ifile_name [ FILENAME_LEN ] ;
change_filename_extension ( ifile_name , level_name , " .HXM " ) ;
2015-01-17 18:31:42 +00:00
auto fp = PHYSFSX_openReadBuffered ( ifile_name ) ;
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
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < t ; j + + ) {
2011-06-01 07:59:55 +00:00
i = PHYSFSX_readInt ( fp ) ; //read robot number
2006-03-20 17:12:09 +00:00
if ( i < 0 | | i > = N_robot_types )
2014-07-23 02:27:22 +00:00
Error ( " Robots number (%d) out of range in (%s). Range = [0..%d]. " , 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
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < t ; j + + ) {
2011-06-01 07:59:55 +00:00
i = PHYSFSX_readInt ( fp ) ; //read joint number
2006-03-20 17:12:09 +00:00
if ( i < 0 | | i > = N_robot_joints )
2014-07-23 02:27:22 +00:00
Error ( " Robots joint (%d) out of range in (%s). Range = [0..%d]. " , 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
}
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 + + )
{
2011-06-01 07:59:55 +00:00
i = PHYSFSX_readInt ( fp ) ; //read model number
2006-03-20 17:12:09 +00:00
if ( i < 0 | | i > = N_polygon_models )
2014-07-23 02:27:22 +00:00
Error ( " Polygon model (%d) out of range in (%s). Range = [0..%d]. " , 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 + + ) {
2011-06-01 07:59:55 +00:00
i = PHYSFSX_readInt ( fp ) ; //read objbitmap number
2016-07-10 04:11:35 +00:00
if ( i < 0 | | i > = ObjBitmaps . size ( ) )
2016-07-15 03:43:03 +00:00
Error ( " Object bitmap number (%d) out of range in (%s). Range = [0..% " DXX_PRI_size_type " ]. " , i , static_cast < const char * > ( level_name ) , ObjBitmaps . size ( ) - 1 ) ;
2015-02-14 22:48:30 +00:00
bitmap_index_read ( fp , ObjBitmaps [ i ] ) ;
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 + + ) {
2011-06-01 07:59:55 +00:00
i = PHYSFSX_readInt ( fp ) ; //read objbitmapptr number
2016-07-10 04:11:35 +00:00
if ( i < 0 | | i > = ObjBitmapPtrs . size ( ) )
2016-07-15 03:43:03 +00:00
Error ( " Object bitmap pointer (%d) out of range in (%s). Range = [0..% " DXX_PRI_size_type " ]. " , i , static_cast < const char * > ( level_name ) , ObjBitmapPtrs . size ( ) - 1 ) ;
2011-06-01 07:59:55 +00:00
ObjBitmapPtrs [ i ] = PHYSFSX_readShort ( fp ) ;
2006-03-20 17:12:09 +00:00
}
Robot_replacements_loaded = 1 ;
}
/*
* 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
* don ' t use " extra " robots . . .
*/
// formerly exitmodel_bm_load_sub
2013-10-27 22:00:14 +00:00
static bitmap_index read_extra_bitmap_iff ( const char * filename )
2006-03-20 17:12:09 +00:00
{
bitmap_index bitmap_num ;
2012-11-18 18:21:50 +00:00
grs_bitmap * n = & GameBitmaps [ extra_bitmap_num ] ;
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
bitmap_num . index = 0 ;
//MALLOC( new, grs_bitmap, 1 );
2016-05-28 17:31:27 +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 ) ) ;
2006-03-20 17:12:09 +00:00
return bitmap_num ;
}
2016-10-28 03:39:40 +00:00
gr_remap_bitmap_good ( * n , newpal , iff_has_transparency ? iff_transparent_color : - 1 , 254 ) ;
2006-03-20 17:12:09 +00:00
2012-11-18 18:21:50 +00:00
n - > avg_color = 0 ; //compute_average_pixel(new);
2006-03-20 17:12:09 +00:00
bitmap_num . index = extra_bitmap_num ;
2012-11-18 18:21:50 +00:00
GameBitmaps [ extra_bitmap_num + + ] = * n ;
2006-03-20 17:12:09 +00:00
2012-11-18 18:21:50 +00:00
//d_free( n );
2006-03-20 17:12:09 +00:00
return bitmap_num ;
}
// 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
{
2016-07-10 04:11:35 +00:00
assert ( N_ObjBitmaps < ObjBitmaps . size ( ) ) ;
2006-03-20 17:12:09 +00:00
{
ObjBitmaps [ N_ObjBitmaps ] = read_extra_bitmap_iff ( name ) ;
if ( ObjBitmaps [ N_ObjBitmaps ] . index = = 0 )
{
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 ' ;
ObjBitmaps [ N_ObjBitmaps ] = read_extra_bitmap_d1_pig ( name2 . get ( ) ) ;
2006-03-20 17:12:09 +00:00
}
if ( ObjBitmaps [ N_ObjBitmaps ] . index = = 0 )
return NULL ;
if ( GameBitmaps [ ObjBitmaps [ N_ObjBitmaps ] . index ] . bm_w ! = 64 | | GameBitmaps [ ObjBitmaps [ N_ObjBitmaps ] . index ] . bm_h ! = 64 )
Error ( " Bitmap <%s> is not 64x64 " , name ) ;
ObjBitmapPtrs [ N_ObjBitmaps ] = N_ObjBitmaps ;
N_ObjBitmaps + + ;
2016-07-10 04:11:35 +00:00
assert ( N_ObjBitmaps < ObjBitmaps . size ( ) ) ;
2006-03-20 17:12:09 +00:00
return & GameBitmaps [ ObjBitmaps [ N_ObjBitmaps - 1 ] . index ] ;
}
}
int load_exit_models ( )
{
int start_num ;
bm_free_extra_models ( ) ;
bm_free_extra_objbitmaps ( ) ;
start_num = N_ObjBitmaps ;
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 " ) )
{
2013-12-07 00:47:27 +00:00
con_printf ( CON_NORMAL , " Can't load exit models! " ) ;
2006-03-20 17:12:09 +00:00
return 0 ;
}
2015-01-17 18:31:42 +00:00
if ( auto exit_hamfile = PHYSFSX_openReadBuffered ( " exit.ham " ) )
{
2006-03-20 17:12:09 +00:00
exit_modelnum = N_polygon_models + + ;
destroyed_exit_modelnum = N_polygon_models + + ;
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
}
2016-05-21 17:24:51 +00:00
else if ( ( exit_hamfile = PHYSFSX_openReadBuffered ( D1_PIGFILE ) ) )
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 */
case D1_OEM_PIGSIZE :
case D1_MAC_PIGSIZE :
case D1_MAC_SHARE_PIGSIZE :
2013-12-07 00:47:27 +00:00
con_printf ( 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 ) ;
2006-03-20 17:12:09 +00:00
exit_modelnum = N_polygon_models + + ;
destroyed_exit_modelnum = N_polygon_models + + ;
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 {
2013-12-07 00:47:27 +00:00
con_printf ( CON_NORMAL , " Can't load exit models! " ) ;
2006-03-20 17:12:09 +00:00
return 0 ;
}
return 1 ;
}
2013-03-03 01:03:33 +00:00
# endif
2011-04-12 01:02:51 +00:00
2014-07-19 03:08:19 +00:00
void compute_average_rgb ( grs_bitmap * bm , 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 ) ;
const auto & & buf = make_unique < uint8_t [ ] > ( bm_w ) ;
2015-01-29 04:27:36 +00:00
for ( uint_fast32_t i = 0 ; i ! = bm_h ; + + 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
}
}