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 .
*/
/*
*
* Functions for managing the pig files .
*
*/
# include <stdio.h>
# include <string.h>
# include "pstypes.h"
# include "strutil.h"
# include "inferno.h"
# include "gr.h"
# include "u_mem.h"
# include "iff.h"
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "sounds.h"
2021-02-05 12:54:08 +00:00
# include "digi.h"
2006-03-20 17:12:09 +00:00
# include "bm.h"
# include "hash.h"
2013-09-24 01:59:09 +00:00
# include "common/2d/bitmap.h"
2006-03-20 17:12:09 +00:00
# include "args.h"
# include "palette.h"
2012-11-11 00:12:17 +00:00
# include "gamepal.h"
2014-07-20 01:09:55 +00:00
# include "physfsx.h"
2006-03-20 17:12:09 +00:00
# include "rle.h"
# include "piggy.h"
# include "gamemine.h"
# include "textures.h"
# include "texmerge.h"
# include "paging.h"
# include "game.h"
# include "text.h"
2018-10-21 00:24:07 +00:00
# include "vclip.h"
2006-03-20 17:12:09 +00:00
# include "makesig.h"
2008-04-06 20:23:28 +00:00
# include "console.h"
2018-08-29 01:47:42 +00:00
# include "compiler-cf_assert.h"
2015-01-28 03:42:53 +00:00
# include "compiler-range_for.h"
2019-05-04 18:27:36 +00:00
# include "d_range.h"
2015-01-28 03:42:53 +00:00
# include "partial_range.h"
2020-05-02 21:18:43 +00:00
# include <memory>
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# include "custom.h"
# include "snddecom.h"
# define DEFAULT_PIGFILE_REGISTERED "descent.pig"
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
# define DEFAULT_PIGFILE_REGISTERED "groupa.pig"
# define DEFAULT_PIGFILE_SHAREWARE "d2demo.pig"
# define DEFAULT_HAMFILE_REGISTERED "descent2.ham"
# define DEFAULT_HAMFILE_SHAREWARE "d2demo.ham"
# define D1_PALETTE "palette.256"
2022-10-09 23:15:20 +00:00
# define DEFAULT_SNDFILE ((Piggy_hamfile_version < pig_hamfile_version::_3) ? DEFAULT_HAMFILE_SHAREWARE : (GameArg.SndDigiSampleRate == SAMPLE_RATE_22K) ? "descent2.s22" : "descent2.s11")
2006-03-20 17:12:09 +00:00
# define MAC_ALIEN1_PIGSIZE 5013035
# define MAC_ALIEN2_PIGSIZE 4909916
# define MAC_FIRE_PIGSIZE 4969035
# define MAC_GROUPA_PIGSIZE 4929684 // also used for mac shareware
# define MAC_ICE_PIGSIZE 4923425
# define MAC_WATER_PIGSIZE 4832403
2022-10-09 23:15:20 +00:00
namespace dsx {
2022-06-11 15:00:02 +00:00
# if DXX_USE_EDITOR
2015-02-14 22:48:27 +00:00
unsigned Num_aliases ;
2020-05-02 21:18:42 +00:00
std : : array < alias , MAX_ALIASES > alias_list ;
2022-06-11 15:00:02 +00:00
# endif
2013-10-06 16:20:00 +00:00
2022-10-09 23:15:20 +00:00
pig_hamfile_version Piggy_hamfile_version ;
uint8_t Pigfile_initialized ;
}
2013-03-03 01:03:33 +00:00
# endif
2013-10-06 16:20:00 +00:00
2022-07-09 13:39:29 +00:00
namespace {
2022-10-02 19:51:35 +00:00
2014-07-24 02:45:47 +00:00
static std : : unique_ptr < ubyte [ ] > BitmapBits ;
2014-07-24 02:45:47 +00:00
static std : : unique_ptr < ubyte [ ] > SoundBits ;
2006-03-20 17:12:09 +00:00
2013-12-22 22:03:07 +00:00
struct SoundFile
{
2022-12-17 13:16:28 +00:00
std : : array < char , 15 > name ;
2013-12-22 22:03:07 +00:00
} ;
2022-07-09 13:39:29 +00:00
}
2006-03-20 17:12:09 +00:00
2015-04-02 02:36:52 +00:00
# if defined(DXX_BUILD_DESCENT_II)
namespace {
# endif
2006-03-20 17:12:09 +00:00
hashtable AllBitmapsNames ;
hashtable AllDigiSndNames ;
2020-08-24 01:31:28 +00:00
std : : array < pig_bitmap_offset , MAX_BITMAP_FILES > GameBitmapOffset ;
2015-04-02 02:36:52 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2022-07-09 13:39:29 +00:00
static std : : unique_ptr < uint8_t [ ] > Bitmap_replacement_data ;
2015-04-02 02:36:52 +00:00
}
# endif
2006-03-20 17:12:09 +00:00
2018-08-26 18:10:36 +00:00
unsigned Num_bitmap_files ;
2006-03-20 17:12:09 +00:00
2015-12-22 04:18:50 +00:00
namespace dsx {
2020-05-02 21:18:42 +00:00
std : : array < digi_sound , MAX_SOUND_FILES > GameSounds ;
2018-06-24 05:06:15 +00:00
GameBitmaps_array GameBitmaps ;
2016-07-14 01:59:05 +00:00
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# define DBM_FLAG_LARGE 128 // Flags added onto the flags struct in b
static
# endif
2020-05-02 21:18:42 +00:00
std : : array < BitmapFile , MAX_BITMAP_FILES > AllBitmaps ;
2022-07-09 13:39:29 +00:00
namespace {
2020-05-02 21:18:42 +00:00
static std : : array < SoundFile , MAX_SOUND_FILES > AllSounds ;
2006-03-20 17:12:09 +00:00
2013-10-06 16:20:00 +00:00
# define DBM_FLAG_ABM 64 // animated bitmap
2006-03-20 17:12:09 +00:00
2015-04-02 02:36:52 +00:00
static int Piggy_bitmap_cache_size ;
static int Piggy_bitmap_cache_next ;
2016-11-19 17:24:52 +00:00
static uint8_t * Piggy_bitmap_cache_data ;
2020-05-02 21:18:42 +00:00
static std : : array < uint8_t , MAX_BITMAP_FILES > GameBitmapFlags ;
static std : : array < uint16_t , MAX_BITMAP_FILES > GameBitmapXlat ;
2022-07-09 13:39:29 +00:00
static RAIIPHYSFS_File Piggy_fp ;
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
# define PIGGY_BUFFER_SIZE (2048*1024)
# elif defined(DXX_BUILD_DESCENT_II)
2013-10-06 16:20:00 +00:00
# define PIGFILE_ID MAKE_SIG('G','I','P','P') //PPIG
# define PIGFILE_VERSION 2
2006-03-20 17:12:09 +00:00
# define PIGGY_BUFFER_SIZE (2400*1024)
2013-03-03 01:03:33 +00:00
# endif
2015-12-24 04:01:26 +00:00
# define PIGGY_SMALL_BUFFER_SIZE (1400*1024) // size of buffer when CGameArg.SysLowMem is set
2006-03-20 17:12:09 +00:00
2013-10-06 16:20:00 +00:00
ubyte bogus_bitmap_initialized = 0 ;
2020-05-02 21:18:42 +00:00
std : : array < uint8_t , 64 * 64 > bogus_data ;
2013-10-06 16:20:00 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
grs_bitmap bogus_bitmap ;
int MacPig = 0 ; // using the Macintosh pigfile?
int PCSharePig = 0 ; // using PC Shareware pigfile?
2022-07-09 13:39:29 +00:00
namespace {
2020-05-02 21:18:42 +00:00
static std : : array < int , MAX_SOUND_FILES > SoundCompressed ;
2022-07-09 13:39:29 +00:00
}
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2013-10-06 16:20:00 +00:00
char Current_pigfile [ FILENAME_LEN ] = " " ;
2006-03-20 17:12:09 +00:00
# define BM_FLAGS_TO_COPY (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT \
| BM_FLAG_NO_LIGHTING | BM_FLAG_RLE | BM_FLAG_RLE_BIG )
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2018-08-26 18:10:36 +00:00
# define DBM_NUM_FRAMES 63
2020-08-24 01:31:28 +00:00
namespace {
2013-12-22 22:03:07 +00:00
struct DiskBitmapHeader
{
2006-03-20 17:12:09 +00:00
char name [ 8 ] ;
ubyte dflags ; // bits 0-5 anim frame num, bit 6 abm flag
ubyte width ; // low 8 bits here, 4 more bits in wh_extra
ubyte height ; // low 8 bits here, 4 more bits in wh_extra
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
ubyte wh_extra ; // bits 0-3 width, bits 4-7 height
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
ubyte flags ;
ubyte avg_color ;
int offset ;
2013-12-22 22:03:07 +00:00
} __pack__ ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2013-11-26 05:03:00 +00:00
static_assert ( sizeof ( DiskBitmapHeader ) = = 0x11 , " sizeof(DiskBitmapHeader) must be 0x11 " ) ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2013-11-26 05:03:00 +00:00
static_assert ( sizeof ( DiskBitmapHeader ) = = 0x12 , " sizeof(DiskBitmapHeader) must be 0x12 " ) ;
2006-03-20 17:12:09 +00:00
# define DISKBITMAPHEADER_D1_SIZE 17 // no wh_extra
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2013-12-22 22:03:07 +00:00
struct DiskSoundHeader
{
2006-03-20 17:12:09 +00:00
char name [ 8 ] ;
int length ;
int data_length ;
int offset ;
2013-12-22 22:03:07 +00:00
} __pack__ ;
2006-03-20 17:12:09 +00:00
2020-08-24 01:31:28 +00:00
}
namespace dsx {
namespace {
2022-06-05 17:44:52 +00:00
static void piggy_bitmap_page_out_all ( ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2020-08-24 01:31:28 +00:00
# define D1_MAX_TMAP_NUM 1630 // 1621 in descent.pig Mac registered
/* the inverse of the d2 Textures array, but for the descent 1 pigfile.
* " Textures " looks up a d2 bitmap index given a d2 tmap_num .
* " d1_tmap_nums " looks up a d1 tmap_num given a d1 bitmap . " -1 " means " None " .
*/
using d1_tmap_nums_t = std : : array < short , D1_MAX_TMAP_NUM > ;
static std : : unique_ptr < d1_tmap_nums_t > d1_tmap_nums ;
static void free_d1_tmap_nums ( )
{
d1_tmap_nums . reset ( ) ;
}
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2022-12-17 13:16:28 +00:00
static int piggy_is_substitutable_bitmap ( std : : span < const char , 13 > name , std : : array < char , 32 > & subst_name ) ;
2022-10-02 19:51:35 +00:00
static void piggy_write_pigfile ( std : : span < const char , FILENAME_LEN > filename ) ;
2016-01-09 16:38:14 +00:00
static void write_int ( int i , PHYSFS_File * file ) ;
2013-09-22 22:26:27 +00:00
# endif
2013-03-03 01:03:33 +00:00
# endif
2020-08-24 01:31:28 +00:00
}
}
2008-11-14 16:56:40 +00:00
2018-08-26 18:10:36 +00:00
namespace dcx {
2022-12-10 18:09:54 +00:00
digi_sound bogus_sound ;
unsigned Num_sound_files ;
2020-08-24 01:31:28 +00:00
namespace {
2018-08-26 18:10:36 +00:00
2020-05-02 21:18:42 +00:00
static void get_bitmap_name_from_header ( std : : array < char , 13 > & output_name , const DiskBitmapHeader & bmh )
2018-08-26 18:10:36 +00:00
{
if ( bmh . dflags & DBM_FLAG_ABM )
snprintf ( output_name . data ( ) , output_name . size ( ) , " %.8s#%d " , bmh . name , bmh . dflags & DBM_NUM_FRAMES ) ;
else
{
memcpy ( output_name . data ( ) , bmh . name , 8 ) ;
output_name [ 8 ] = 0 ;
}
}
2020-08-24 01:31:28 +00:00
static int piggy_is_needed ( const int soundnum )
{
if ( ! CGameArg . SysLowMem )
return 1 ;
constexpr std : : size_t upper_bound = Sounds . size ( ) ;
for ( const auto i : AltSounds )
{
if ( i < upper_bound & & Sounds [ i ] = = soundnum )
return 1 ;
}
return 0 ;
}
}
2018-08-26 18:10:36 +00:00
}
2006-03-20 17:12:09 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads a DiskBitmapHeader structure from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2016-08-25 04:05:32 +00:00
namespace dsx {
2022-07-09 13:39:29 +00:00
namespace {
2022-12-17 13:16:28 +00:00
static DiskBitmapHeader DiskBitmapHeader_read ( PHYSFS_File * fp )
2006-03-20 17:12:09 +00:00
{
2022-12-17 13:16:28 +00:00
DiskBitmapHeader dbh { } ;
PHYSFS_read ( fp , dbh . name , 8 , 1 ) ;
dbh . dflags = PHYSFSX_readByte ( fp ) ;
dbh . width = PHYSFSX_readByte ( fp ) ;
dbh . height = PHYSFSX_readByte ( fp ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2022-12-17 13:16:28 +00:00
dbh . wh_extra = PHYSFSX_readByte ( fp ) ;
2013-03-03 01:03:33 +00:00
# endif
2022-12-17 13:16:28 +00:00
dbh . flags = PHYSFSX_readByte ( fp ) ;
dbh . avg_color = PHYSFSX_readByte ( fp ) ;
dbh . offset = PHYSFSX_readInt ( fp ) ;
return dbh ;
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads a DiskSoundHeader structure from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2016-01-09 16:38:14 +00:00
static void DiskSoundHeader_read ( DiskSoundHeader * dsh , PHYSFS_File * fp )
2006-03-20 17:12:09 +00:00
{
2011-06-01 07:59:55 +00:00
PHYSFS_read ( fp , dsh - > name , 8 , 1 ) ;
dsh - > length = PHYSFSX_readInt ( fp ) ;
dsh - > data_length = PHYSFSX_readInt ( fp ) ;
dsh - > offset = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads a descent 1 DiskBitmapHeader structure from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2016-01-09 16:38:14 +00:00
static void DiskBitmapHeader_d1_read ( DiskBitmapHeader * dbh , PHYSFS_File * fp )
2006-03-20 17:12:09 +00:00
{
2011-06-01 07:59:55 +00:00
PHYSFS_read ( fp , dbh - > name , 8 , 1 ) ;
dbh - > dflags = PHYSFSX_readByte ( fp ) ;
dbh - > width = PHYSFSX_readByte ( fp ) ;
dbh - > height = PHYSFSX_readByte ( fp ) ;
2006-03-20 17:12:09 +00:00
dbh - > wh_extra = 0 ;
2011-06-01 07:59:55 +00:00
dbh - > flags = PHYSFSX_readByte ( fp ) ;
dbh - > avg_color = PHYSFSX_readByte ( fp ) ;
dbh - > offset = PHYSFSX_readInt ( fp ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2022-07-09 13:39:29 +00:00
}
2016-11-19 17:24:52 +00:00
void swap_0_255 ( grs_bitmap & bmp )
2006-03-20 17:12:09 +00:00
{
2014-11-30 22:09:22 +00:00
auto a = [ ] ( uint8_t & c ) {
if ( c = = 0 )
c = 255 ;
else if ( c = = 255 )
c = 0 ;
} ;
2016-11-19 17:24:52 +00:00
auto d = bmp . get_bitmap_data ( ) ;
std : : for_each ( d , d + ( bmp . bm_h * bmp . bm_w ) , a ) ;
2006-03-20 17:12:09 +00:00
}
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-11-19 17:24:53 +00:00
2022-10-02 19:51:35 +00:00
bitmap_index piggy_register_bitmap ( grs_bitmap & bmp , const std : : span < const char > name , const int in_file )
2006-03-20 17:12:09 +00:00
{
2016-07-14 01:59:05 +00:00
assert ( Num_bitmap_files < AllBitmaps . size ( ) ) ;
2022-12-18 18:32:14 +00:00
const bitmap_index temp { static_cast < uint16_t > ( Num_bitmap_files ) } ;
2006-03-20 17:12:09 +00:00
2013-02-21 00:20:26 +00:00
if ( ! in_file ) {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2007-07-15 01:15:36 +00:00
if ( GameArg . EdiMacData )
2016-11-19 17:24:53 +00:00
swap_0_255 ( bmp ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
# endif
2015-12-24 04:01:28 +00:00
if ( CGameArg . DbgNoCompressPigBitmap )
2016-11-19 17:24:53 +00:00
gr_bitmap_rle_compress ( bmp ) ;
2006-03-20 17:12:09 +00:00
}
2018-08-26 18:10:36 +00:00
auto & abn = AllBitmaps [ Num_bitmap_files ] . name ;
2022-10-02 19:51:35 +00:00
std : : memcpy ( abn . data ( ) , name . data ( ) , std : : min ( abn . size ( ) - 1 , name . size ( ) ) ) ;
2018-08-26 18:10:36 +00:00
abn . back ( ) = 0 ;
hashtable_insert ( & AllBitmapsNames , AllBitmaps [ Num_bitmap_files ] . name . data ( ) , Num_bitmap_files ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-11-19 17:24:53 +00:00
GameBitmaps [ Num_bitmap_files ] = bmp ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
if ( ! in_file ) {
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ Num_bitmap_files ] = pig_bitmap_offset : : None ;
2017-01-15 00:03:13 +00:00
GameBitmapFlags [ Num_bitmap_files ] = bmp . get_flags ( ) ;
2006-03-20 17:12:09 +00:00
}
Num_bitmap_files + + ;
return temp ;
}
2015-12-22 04:18:50 +00:00
2022-12-17 13:16:28 +00:00
int piggy_register_sound ( digi_sound & snd , const std : : span < const char > name )
2006-03-20 17:12:09 +00:00
{
int i ;
Assert ( Num_sound_files < MAX_SOUND_FILES ) ;
2022-12-17 13:16:28 +00:00
auto & asn = AllSounds [ Num_sound_files ] . name ;
std : : memcpy ( asn . data ( ) , name . data ( ) , std : : min ( asn . size ( ) - 1 , name . size ( ) ) ) ;
asn . back ( ) = 0 ;
hashtable_insert ( & AllDigiSndNames , asn . data ( ) , Num_sound_files ) ;
2022-12-10 18:09:54 +00:00
auto & gs = GameSounds [ Num_sound_files ] ;
gs = std : : move ( snd ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
//added/moved on 11/13/99 by Victor Rachels to ready for changing freq
//#ifdef ALLEGRO
2022-12-10 18:09:54 +00:00
GameSounds [ Num_sound_files ] . freq = snd . freq ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
i = Num_sound_files ;
Num_sound_files + + ;
return i ;
}
2022-12-17 13:16:28 +00:00
bitmap_index piggy_find_bitmap ( const std : : span < const char > entry_name )
2006-03-20 17:12:09 +00:00
{
2022-12-17 13:16:28 +00:00
auto name = entry_name ;
2022-06-11 15:00:02 +00:00
# if defined(DXX_BUILD_DESCENT_II) && DXX_USE_EDITOR
2013-06-09 17:34:26 +00:00
size_t namelen ;
2022-12-17 13:16:28 +00:00
const auto t = strchr ( name . data ( ) , ' # ' ) ;
if ( t ! = nullptr )
namelen = t - name . data ( ) ;
2013-06-09 17:34:26 +00:00
else
2022-12-17 13:16:28 +00:00
namelen = strlen ( name . data ( ) ) ;
2006-03-20 17:12:09 +00:00
2022-12-17 13:16:28 +00:00
std : : array < char , FILENAME_LEN > temp ;
2016-02-12 04:02:28 +00:00
range_for ( auto & i , partial_const_range ( alias_list , Num_aliases ) )
2022-12-17 13:16:28 +00:00
if ( i . alias_name [ namelen ] = = 0 & & d_strnicmp ( name . data ( ) , i . alias_name , namelen ) = = 0 )
{
2006-03-20 17:12:09 +00:00
if ( t ) { //extra stuff for ABMs
2022-06-11 15:00:02 +00:00
const auto path = d_splitpath ( i . file_name ) ;
2022-12-17 13:16:28 +00:00
snprintf ( temp . data ( ) , temp . size ( ) , " %.*s%s \n " , DXX_ptrdiff_cast_int ( path . base_end - path . base_start ) , path . base_start , t ) ;
2006-03-20 17:12:09 +00:00
name = temp ;
}
else
2015-02-14 22:48:27 +00:00
name = i . file_name ;
2006-03-20 17:12:09 +00:00
break ;
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2022-12-17 13:16:28 +00:00
const auto i = hashtable_search ( & AllBitmapsNames , name . data ( ) ) ;
2006-03-20 17:12:09 +00:00
Assert ( i ! = 0 ) ;
if ( i < 0 )
2022-12-18 18:32:14 +00:00
return bitmap_index { } ;
2006-03-20 17:12:09 +00:00
2022-12-18 18:32:14 +00:00
bitmap_index bmp ;
2006-03-20 17:12:09 +00:00
bmp . index = i ;
return bmp ;
}
2015-12-22 04:18:50 +00:00
}
2022-12-17 13:16:28 +00:00
int piggy_find_sound ( const std : : span < const char > name )
2006-03-20 17:12:09 +00:00
{
2022-12-17 13:16:28 +00:00
const auto i = hashtable_search ( & AllDigiSndNames , name . data ( ) ) ;
2006-03-20 17:12:09 +00:00
if ( i < 0 )
return 255 ;
return i ;
}
2016-08-25 04:05:32 +00:00
namespace dsx {
2022-07-09 13:39:29 +00:00
namespace {
2013-10-27 22:00:14 +00:00
static void piggy_close_file ( )
2006-03-20 17:12:09 +00:00
{
2015-01-17 18:31:42 +00:00
if ( Piggy_fp )
{
Piggy_fp . reset ( ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
Current_pigfile [ 0 ] = 0 ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
}
2022-07-09 13:39:29 +00:00
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2022-07-09 13:39:29 +00:00
int properties_init ( d_level_shared_robot_info_state & LevelSharedRobotInfoState )
2013-03-03 01:03:33 +00:00
{
int sbytes = 0 ;
2020-05-02 21:18:42 +00:00
std : : array < char , 13 > temp_name ;
2013-03-03 01:03:33 +00:00
DiskSoundHeader sndh ;
2020-08-24 01:31:28 +00:00
int N_sounds ;
2016-02-12 04:02:28 +00:00
int size ;
2013-03-03 01:03:33 +00:00
int pigsize ;
int retval ;
2018-08-26 18:10:36 +00:00
GameSounds = { } ;
2013-03-03 01:03:33 +00:00
2016-07-14 01:59:05 +00:00
static_assert ( GameBitmapXlat . size ( ) = = GameBitmaps . size ( ) , " size mismatch " ) ;
for ( unsigned i = 0 ; i < GameBitmaps . size ( ) ; + + i )
2016-02-12 04:02:28 +00:00
{
2013-03-03 01:03:33 +00:00
GameBitmapXlat [ i ] = i ;
2017-01-15 00:03:13 +00:00
GameBitmaps [ i ] . set_flags ( BM_FLAG_PAGED_OUT ) ;
2013-03-03 01:03:33 +00:00
}
if ( ! bogus_bitmap_initialized ) {
ubyte c ;
bogus_bitmap_initialized = 1 ;
c = gr_find_closest_color ( 0 , 0 , 63 ) ;
2015-02-28 19:36:01 +00:00
bogus_data . fill ( c ) ;
2013-03-03 01:03:33 +00:00
c = gr_find_closest_color ( 63 , 0 , 0 ) ;
// Make a big red X !
2019-05-04 18:27:36 +00:00
range_for ( const unsigned i , xrange ( 64u ) )
2016-02-12 04:02:28 +00:00
{
2013-03-03 01:03:33 +00:00
bogus_data [ i * 64 + i ] = c ;
bogus_data [ i * 64 + ( 63 - i ) ] = c ;
}
2016-05-28 17:31:27 +00:00
gr_init_bitmap ( bogus_bitmap , bm_mode : : linear , 0 , 0 , 64 , 64 , 64 , bogus_data . data ( ) ) ;
2016-11-19 17:24:53 +00:00
piggy_register_bitmap ( bogus_bitmap , " bogus " , 1 ) ;
2013-03-03 01:03:33 +00:00
# ifdef ALLEGRO
bogus_sound . len = 64 * 64 ;
# else
bogus_sound . length = 64 * 64 ;
# endif
2022-12-10 18:09:54 +00:00
bogus_sound . data = digi_sound : : allocated_data { bogus_data . data ( ) , game_sound_offset { INT_MAX } } ;
2013-03-03 01:03:33 +00:00
//added on 11/13/99 by Victor Rachels to ready for changing freq
bogus_sound . freq = 11025 ;
//end this section addition - VR
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ 0 ] = pig_bitmap_offset : : None ;
2013-03-03 01:03:33 +00:00
}
2021-07-25 23:00:56 +00:00
Piggy_fp = PHYSFSX_openReadBuffered ( DEFAULT_PIGFILE_REGISTERED ) . first ;
2015-01-17 18:31:42 +00:00
if ( ! Piggy_fp )
2013-03-03 01:03:33 +00:00
{
if ( ! PHYSFSX_exists ( " BITMAPS.TBL " , 1 ) & & ! PHYSFSX_exists ( " BITMAPS.BIN " , 1 ) )
Error ( " Cannot find " DEFAULT_PIGFILE_REGISTERED " or BITMAPS.TBL " ) ;
return 1 ; // need to run gamedata_read_tbl
}
pigsize = PHYSFS_fileLength ( Piggy_fp ) ;
2020-08-24 01:31:28 +00:00
unsigned Pigdata_start ;
2013-03-03 01:03:33 +00:00
switch ( pigsize ) {
case D1_SHARE_BIG_PIGSIZE :
case D1_SHARE_10_PIGSIZE :
case D1_SHARE_PIGSIZE :
PCSharePig = 1 ;
Pigdata_start = 0 ;
break ;
case D1_10_BIG_PIGSIZE :
case D1_10_PIGSIZE :
Pigdata_start = 0 ;
break ;
default :
Warning ( " Unknown size for " DEFAULT_PIGFILE_REGISTERED ) ;
Int3 ( ) ;
2022-01-09 15:25:42 +00:00
[[fallthrough]] ;
2013-03-03 01:03:33 +00:00
case D1_MAC_PIGSIZE :
case D1_MAC_SHARE_PIGSIZE :
MacPig = 1 ;
2022-01-09 15:25:42 +00:00
[[fallthrough]] ;
2013-03-03 01:03:33 +00:00
case D1_PIGSIZE :
case D1_OEM_PIGSIZE :
Pigdata_start = PHYSFSX_readInt ( Piggy_fp ) ;
break ;
}
HiresGFXAvailable = MacPig ; // for now at least
if ( PCSharePig )
retval = PIGGY_PC_SHAREWARE ; // run gamedata_read_tbl in shareware mode
else if ( GameArg . EdiNoBm | | ( ! PHYSFSX_exists ( " BITMAPS.TBL " , 1 ) & & ! PHYSFSX_exists ( " BITMAPS.BIN " , 1 ) ) )
{
2022-07-09 13:39:29 +00:00
properties_read_cmp ( LevelSharedRobotInfoState , Vclip , Piggy_fp ) ; // Note connection to above if!!!
2016-02-12 04:02:28 +00:00
range_for ( auto & i , GameBitmapXlat )
2013-03-03 01:03:33 +00:00
{
2016-02-12 04:02:28 +00:00
i = PHYSFSX_readShort ( Piggy_fp ) ;
2013-03-03 01:03:33 +00:00
if ( PHYSFS_eof ( Piggy_fp ) )
break ;
}
retval = 0 ; // don't run gamedata_read_tbl
}
else
retval = 1 ; // run gamedata_read_tbl
2020-08-24 01:31:28 +00:00
PHYSFS_seek ( Piggy_fp , Pigdata_start ) ;
2013-03-03 01:03:33 +00:00
size = PHYSFS_fileLength ( Piggy_fp ) - Pigdata_start ;
2020-08-24 01:31:28 +00:00
const unsigned N_bitmaps = PHYSFSX_readInt ( Piggy_fp ) ;
2013-03-03 01:03:33 +00:00
size - = sizeof ( int ) ;
N_sounds = PHYSFSX_readInt ( Piggy_fp ) ;
size - = sizeof ( int ) ;
2020-08-24 01:31:28 +00:00
const unsigned header_size = ( N_bitmaps * sizeof ( DiskBitmapHeader ) ) + ( N_sounds * sizeof ( DiskSoundHeader ) ) ;
2013-03-03 01:03:33 +00:00
2020-08-24 01:31:28 +00:00
for ( const unsigned i : xrange ( N_bitmaps ) )
2016-02-12 04:02:28 +00:00
{
2022-12-17 13:16:28 +00:00
const auto bmh = DiskBitmapHeader_read ( Piggy_fp ) ;
2013-03-03 01:03:33 +00:00
2020-08-24 01:31:28 +00:00
GameBitmapFlags [ i + 1 ] = bmh . flags & ( BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT | BM_FLAG_NO_LIGHTING | BM_FLAG_RLE ) ;
2013-03-03 01:03:33 +00:00
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ i + 1 ] = static_cast < pig_bitmap_offset > ( bmh . offset + header_size + ( sizeof ( int ) * 2 ) + Pigdata_start ) ;
2013-03-03 01:03:33 +00:00
Assert ( ( i + 1 ) = = Num_bitmap_files ) ;
//size -= sizeof(DiskBitmapHeader);
2018-08-26 18:10:36 +00:00
get_bitmap_name_from_header ( temp_name , bmh ) ;
2013-03-03 01:03:33 +00:00
2014-07-04 04:15:35 +00:00
grs_bitmap temp_bitmap { } ;
2016-11-19 17:24:53 +00:00
const auto iwidth = ( bmh . dflags & DBM_FLAG_LARGE ) ? bmh . width + 256 : bmh . width ;
2016-05-28 17:31:27 +00:00
gr_init_bitmap ( temp_bitmap , bm_mode : : linear , 0 , 0 ,
2016-11-19 17:24:53 +00:00
iwidth , bmh . height ,
iwidth , Piggy_bitmap_cache_data ) ;
2017-01-15 00:03:13 +00:00
temp_bitmap . add_flags ( BM_FLAG_PAGED_OUT ) ;
2020-05-22 02:40:26 +00:00
# if !DXX_USE_OGL
2013-03-03 01:03:33 +00:00
temp_bitmap . avg_color = bmh . avg_color ;
2020-05-22 02:40:26 +00:00
# endif
2013-03-03 01:03:33 +00:00
if ( MacPig )
{
// HACK HACK HACK!!!!!
2015-01-12 00:26:03 +00:00
if ( ! d_strnicmp ( bmh . name , " cockpit " ) | | ! d_strnicmp ( bmh . name , " status " ) | | ! d_strnicmp ( bmh . name , " rearview " ) ) {
2013-03-03 01:03:33 +00:00
temp_bitmap . bm_w = temp_bitmap . bm_rowsize = 640 ;
if ( GameBitmapFlags [ i + 1 ] & BM_FLAG_RLE )
GameBitmapFlags [ i + 1 ] | = BM_FLAG_RLE_BIG ;
}
2015-01-12 00:26:03 +00:00
if ( ! d_strnicmp ( bmh . name , " cockpit " ) | | ! d_strnicmp ( bmh . name , " rearview " ) )
2013-03-03 01:03:33 +00:00
temp_bitmap . bm_h = 480 ;
}
2022-10-02 19:51:35 +00:00
piggy_register_bitmap ( temp_bitmap , temp_name , 1 ) ;
2013-03-03 01:03:33 +00:00
}
2016-02-12 04:02:28 +00:00
if ( ! MacPig )
{
for ( unsigned i = 0 ; i < N_sounds ; + + i )
{
2013-03-03 01:03:33 +00:00
DiskSoundHeader_read ( & sndh , Piggy_fp ) ;
//size -= sizeof(DiskSoundHeader);
2022-12-10 18:09:54 +00:00
digi_sound temp_sound ;
2013-03-03 01:03:33 +00:00
temp_sound . length = sndh . length ;
//added on 11/13/99 by Victor Rachels to ready for changing freq
temp_sound . freq = 11025 ;
//end this section addition - VR
2022-10-02 19:51:35 +00:00
const game_sound_offset sound_offset { static_cast < int > ( sndh . offset + header_size + ( sizeof ( int ) * 2 ) + Pigdata_start ) } ;
2022-12-10 18:09:54 +00:00
temp_sound . data = digi_sound : : allocated_data { nullptr , sound_offset } ;
2013-03-03 01:03:33 +00:00
if ( PCSharePig )
SoundCompressed [ Num_sound_files ] = sndh . data_length ;
2022-12-17 13:16:28 +00:00
piggy_register_sound ( temp_sound , std : : span ( sndh . name ) . first < 8 > ( ) ) ;
2013-03-03 01:03:33 +00:00
sbytes + = sndh . length ;
}
2020-05-02 21:18:42 +00:00
SoundBits = std : : make_unique < ubyte [ ] > ( sbytes + 16 ) ;
2013-03-03 01:03:33 +00:00
}
# if 1 //def EDITOR
Piggy_bitmap_cache_size = size - header_size - sbytes + 16 ;
Assert ( Piggy_bitmap_cache_size > 0 ) ;
# else
Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE ;
2015-12-24 04:01:26 +00:00
if ( CGameArg . SysLowMem )
2013-03-03 01:03:33 +00:00
Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE ;
# endif
2020-05-02 21:18:42 +00:00
BitmapBits = std : : make_unique < ubyte [ ] > ( Piggy_bitmap_cache_size ) ;
2014-07-24 02:45:47 +00:00
Piggy_bitmap_cache_data = BitmapBits . get ( ) ;
2013-03-03 01:03:33 +00:00
Piggy_bitmap_cache_next = 0 ;
return retval ;
}
# elif defined(DXX_BUILD_DESCENT_II)
2018-08-26 18:10:36 +00:00
2006-03-20 17:12:09 +00:00
//initialize a pigfile, reading headers
//returns the size of all the bitmap data
2012-11-11 00:14:30 +00:00
void piggy_init_pigfile ( const char * filename )
2006-03-20 17:12:09 +00:00
{
int i ;
2020-05-02 21:18:42 +00:00
std : : array < char , 13 > temp_name ;
2020-08-24 01:31:28 +00:00
int header_size , N_bitmaps ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2011-09-26 23:31:19 +00:00
int data_size ;
# endif
2006-03-20 17:12:09 +00:00
piggy_close_file ( ) ; //close old pig if still open
2021-07-25 23:00:56 +00:00
auto & & [ fp , physfserr ] = PHYSFSX_openReadBuffered ( filename ) ;
# if !DXX_USE_EDITOR
auto effective_filename = filename ;
# endif
2007-05-20 02:00:57 +00:00
//try pigfile for shareware
2021-07-25 23:00:56 +00:00
if ( ! fp )
{
auto & & [ fp2 , physfserr2 ] = PHYSFSX_openReadBuffered ( DEFAULT_PIGFILE_SHAREWARE ) ;
if ( ! fp2 )
{
# if DXX_USE_EDITOR
2021-09-12 16:20:52 +00:00
static_cast < void > ( physfserr ) ;
static_cast < void > ( physfserr2 ) ;
2021-07-25 23:00:56 +00:00
return ; //if editor, ok to not have pig, because we'll build one
# else
Error ( " Failed to open required files <%s>, < " DEFAULT_PIGFILE_SHAREWARE " >: \" %s \" , \" %s \" " , filename , PHYSFS_getErrorByCode ( physfserr ) , PHYSFS_getErrorByCode ( physfserr2 ) ) ;
# endif
}
fp = std : : move ( fp2 ) ;
# if !DXX_USE_EDITOR
effective_filename = DEFAULT_PIGFILE_SHAREWARE ;
# endif
}
Piggy_fp = std : : move ( fp ) ;
2006-03-20 17:12:09 +00:00
if ( Piggy_fp ) { //make sure pig is valid type file & is up-to-date
int pig_id , pig_version ;
2011-06-01 07:59:55 +00:00
pig_id = PHYSFSX_readInt ( Piggy_fp ) ;
pig_version = PHYSFSX_readInt ( Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
if ( pig_id ! = PIGFILE_ID | | pig_version ! = PIGFILE_VERSION ) {
2015-01-17 18:31:42 +00:00
Piggy_fp . reset ( ) ; //out of date pig
//..so pretend it's not here
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
return ; //if editor, ok to not have pig, because we'll build one
# else
2021-07-25 23:00:56 +00:00
Error ( " Cannot load PIG file: expected (id=%.8lx version=%.8x), found (id=%.8x version=%.8x) in \" %s \" " , PIGFILE_ID , PIGFILE_VERSION , pig_id , pig_version , effective_filename ) ;
2006-03-20 17:12:09 +00:00
# endif
2021-07-25 23:00:56 +00:00
}
2006-03-20 17:12:09 +00:00
}
2019-05-06 00:36:16 +00:00
strncpy ( Current_pigfile , filename , sizeof ( Current_pigfile ) - 1 ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
N_bitmaps = PHYSFSX_readInt ( Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
header_size = N_bitmaps * sizeof ( DiskBitmapHeader ) ;
2020-08-24 01:31:28 +00:00
const unsigned data_start = header_size + PHYSFS_tell ( Piggy_fp ) ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2011-06-01 07:59:55 +00:00
data_size = PHYSFS_fileLength ( Piggy_fp ) - data_start ;
2011-09-26 23:31:19 +00:00
# endif
2006-03-20 17:12:09 +00:00
Num_bitmap_files = 1 ;
for ( i = 0 ; i < N_bitmaps ; i + + )
2013-02-21 00:20:26 +00:00
{
2006-03-20 17:12:09 +00:00
int width ;
grs_bitmap * bm = & GameBitmaps [ i + 1 ] ;
2022-12-17 13:16:28 +00:00
const auto bmh = DiskBitmapHeader_read ( Piggy_fp ) ;
2018-08-26 18:10:36 +00:00
get_bitmap_name_from_header ( temp_name , bmh ) ;
2016-06-05 01:04:26 +00:00
width = bmh . width + ( static_cast < short > ( bmh . wh_extra & 0x0f ) < < 8 ) ;
gr_init_bitmap ( * bm , bm_mode : : linear , 0 , 0 , width , bmh . height + ( static_cast < short > ( bmh . wh_extra & 0xf0 ) < < 4 ) , width , NULL ) ;
2017-01-15 00:03:13 +00:00
bm - > set_flags ( BM_FLAG_PAGED_OUT ) ;
2020-05-22 02:40:26 +00:00
# if !DXX_USE_OGL
2006-03-20 17:12:09 +00:00
bm - > avg_color = bmh . avg_color ;
2020-05-22 02:40:26 +00:00
# endif
2006-03-20 17:12:09 +00:00
GameBitmapFlags [ i + 1 ] = bmh . flags & BM_FLAGS_TO_COPY ;
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ i + 1 ] = pig_bitmap_offset { bmh . offset + data_start } ;
2006-03-20 17:12:09 +00:00
Assert ( ( i + 1 ) = = Num_bitmap_files ) ;
2022-10-02 19:51:35 +00:00
piggy_register_bitmap ( * bm , temp_name , 1 ) ;
2006-03-20 17:12:09 +00:00
}
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
Piggy_bitmap_cache_size = data_size + ( data_size / 10 ) ; //extra mem for new bitmaps
Assert ( Piggy_bitmap_cache_size > 0 ) ;
# else
Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE ;
2015-12-24 04:01:26 +00:00
if ( CGameArg . SysLowMem )
2006-03-20 17:12:09 +00:00
Piggy_bitmap_cache_size = PIGGY_SMALL_BUFFER_SIZE ;
# endif
2020-05-02 21:18:42 +00:00
BitmapBits = std : : make_unique < ubyte [ ] > ( Piggy_bitmap_cache_size ) ;
2014-07-24 02:45:47 +00:00
Piggy_bitmap_cache_data = BitmapBits . get ( ) ;
2006-03-20 17:12:09 +00:00
Piggy_bitmap_cache_next = 0 ;
Pigfile_initialized = 1 ;
}
//reads in a new pigfile (for new palette)
//returns the size of all the bitmap data
2022-10-02 19:51:35 +00:00
void piggy_new_pigfile ( const std : : span < char , FILENAME_LEN > pigname )
2006-03-20 17:12:09 +00:00
{
int i ;
2020-05-02 21:18:42 +00:00
std : : array < char , 13 > temp_name ;
2020-08-24 01:31:28 +00:00
int header_size , N_bitmaps ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
int must_rewrite_pig = 0 ;
2011-09-26 23:31:19 +00:00
# endif
2006-03-20 17:12:09 +00:00
2022-10-02 19:51:35 +00:00
d_strlwr ( pigname . data ( ) ) ;
2006-03-20 17:12:09 +00:00
2022-10-02 19:51:35 +00:00
if ( d_strnicmp ( Current_pigfile , pigname . data ( ) , sizeof ( Current_pigfile ) ) = = 0 // correct pig already loaded
2006-03-20 17:12:09 +00:00
& & ! Bitmap_replacement_data ) // no need to reload: no bitmaps were altered
return ;
if ( ! Pigfile_initialized ) { //have we ever opened a pigfile?
2022-10-02 19:51:35 +00:00
piggy_init_pigfile ( pigname . data ( ) ) ; //..no, so do initialization stuff
2006-03-20 17:12:09 +00:00
return ;
}
else
piggy_close_file ( ) ; //close old pig if still open
Piggy_bitmap_cache_next = 0 ; //free up cache
2022-10-02 19:51:35 +00:00
strncpy ( Current_pigfile , pigname . data ( ) , sizeof ( Current_pigfile ) - 1 ) ;
2006-03-20 17:12:09 +00:00
2022-10-02 19:51:35 +00:00
auto & & [ fp , physfserr ] = PHYSFSX_openReadBuffered ( pigname . data ( ) ) ;
2021-07-25 23:00:56 +00:00
# if !DXX_USE_EDITOR
2022-10-02 19:51:35 +00:00
const char * effective_filename = pigname . data ( ) ;
2021-07-25 23:00:56 +00:00
# endif
2007-05-20 02:00:57 +00:00
//try pigfile for shareware
2021-07-25 23:00:56 +00:00
if ( ! fp )
{
2022-10-02 19:51:35 +00:00
if ( auto & & [ fp2 , physfserr2 ] = PHYSFSX_openReadBuffered ( DEFAULT_PIGFILE_SHAREWARE ) ; fp2 )
fp = std : : move ( fp2 ) ;
else
2021-07-25 23:00:56 +00:00
{
2022-10-02 19:51:35 +00:00
if constexpr ( DXX_USE_EDITOR )
{
static_cast < void > ( physfserr ) ;
static_cast < void > ( physfserr2 ) ;
}
else
Error ( " Failed to open required files <%s>, < " DEFAULT_PIGFILE_SHAREWARE " >: \" %s \" , \" %s \" " , pigname . data ( ) , PHYSFS_getErrorByCode ( physfserr ) , PHYSFS_getErrorByCode ( physfserr2 ) ) ;
/* In an editor build, a pig can be built. In a non-editor build,
* Error was fatal .
*/
return ;
2021-07-25 23:00:56 +00:00
}
# if !DXX_USE_EDITOR
effective_filename = DEFAULT_PIGFILE_SHAREWARE ;
# endif
}
Piggy_fp = std : : move ( fp ) ;
2006-03-20 17:12:09 +00:00
if ( Piggy_fp ) { //make sure pig is valid type file & is up-to-date
int pig_id , pig_version ;
2011-06-01 07:59:55 +00:00
pig_id = PHYSFSX_readInt ( Piggy_fp ) ;
pig_version = PHYSFSX_readInt ( Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
if ( pig_id ! = PIGFILE_ID | | pig_version ! = PIGFILE_VERSION ) {
2015-01-17 18:31:42 +00:00
Piggy_fp . reset ( ) ; //out of date pig
//..so pretend it's not here
2021-07-25 23:00:56 +00:00
# if DXX_USE_EDITOR
return ; //if editor, ok to not have pig, because we'll build one
# else
Error ( " Cannot load PIG file: expected (id=%.8lx version=%.8x), found (id=%.8x version=%.8x) in \" %s \" " , PIGFILE_ID , PIGFILE_VERSION , pig_id , pig_version , effective_filename ) ;
# endif
2006-03-20 17:12:09 +00:00
}
2011-06-01 07:59:55 +00:00
N_bitmaps = PHYSFSX_readInt ( Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
header_size = N_bitmaps * sizeof ( DiskBitmapHeader ) ;
2020-08-24 01:31:28 +00:00
const unsigned data_start = header_size + PHYSFS_tell ( Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
for ( i = 1 ; i < = N_bitmaps ; i + + )
{
grs_bitmap * bm = & GameBitmaps [ i ] ;
int width ;
2022-12-17 13:16:28 +00:00
const auto bmh = DiskBitmapHeader_read ( Piggy_fp ) ;
2018-08-26 18:10:36 +00:00
get_bitmap_name_from_header ( temp_name , bmh ) ;
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
//Make sure name matches
2018-08-26 18:10:36 +00:00
if ( strcmp ( temp_name . data ( ) , AllBitmaps [ i ] . name . data ( ) ) )
{
2006-03-20 17:12:09 +00:00
//Int3(); //this pig is out of date. Delete it
must_rewrite_pig = 1 ;
}
2011-09-26 23:31:19 +00:00
# endif
2006-03-20 17:12:09 +00:00
2018-08-26 18:10:36 +00:00
AllBitmaps [ i ] . name = temp_name ;
2006-03-20 17:12:09 +00:00
2016-06-05 01:04:26 +00:00
width = bmh . width + ( static_cast < short > ( bmh . wh_extra & 0x0f ) < < 8 ) ;
2014-11-30 22:09:20 +00:00
gr_set_bitmap_data ( * bm , NULL ) ; // free ogl texture
2016-06-05 01:04:26 +00:00
gr_init_bitmap ( * bm , bm_mode : : linear , 0 , 0 , width , bmh . height + ( static_cast < short > ( bmh . wh_extra & 0xf0 ) < < 4 ) , width , NULL ) ;
2017-01-15 00:03:13 +00:00
bm - > set_flags ( BM_FLAG_PAGED_OUT ) ;
2020-05-22 02:40:26 +00:00
# if !DXX_USE_OGL
2006-03-20 17:12:09 +00:00
bm - > avg_color = bmh . avg_color ;
2020-05-22 02:40:26 +00:00
# endif
2006-03-20 17:12:09 +00:00
GameBitmapFlags [ i ] = bmh . flags & BM_FLAGS_TO_COPY ;
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ i ] = pig_bitmap_offset { bmh . offset + data_start } ;
2006-03-20 17:12:09 +00:00
}
}
else
N_bitmaps = 0 ; //no pigfile, so no bitmaps
2016-09-11 18:49:16 +00:00
# if !DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
Assert ( N_bitmaps = = Num_bitmap_files - 1 ) ;
# else
if ( must_rewrite_pig | | ( N_bitmaps < Num_bitmap_files - 1 ) ) {
int size ;
//re-read the bitmaps that aren't in this pig
for ( i = N_bitmaps + 1 ; i < Num_bitmap_files ; i + + ) {
2022-12-17 13:16:28 +00:00
auto & abn = AllBitmaps [ i ] . name ;
if ( const auto p = strchr ( abn . data ( ) , ' # ' ) )
2018-08-26 18:10:36 +00:00
{ // this is an ABM == animated bitmap
2006-03-20 17:12:09 +00:00
char abmname [ FILENAME_LEN ] ;
2012-11-18 18:20:13 +00:00
unsigned fnum ;
2006-03-20 17:12:09 +00:00
int iff_error ; //reference parm to avoid warning message
2013-01-06 21:03:57 +00:00
palette_array_t newpal ;
2012-11-18 18:20:13 +00:00
unsigned nframes ;
2022-12-17 13:16:28 +00:00
snprintf ( abmname , sizeof ( abmname ) , " %.*s.abm " , static_cast < int > ( std : : min < std : : ptrdiff_t > ( p - abn . data ( ) , 8 ) ) , abn . data ( ) ) ;
2006-03-20 17:12:09 +00:00
2020-05-02 21:18:42 +00:00
std : : array < std : : unique_ptr < grs_main_bitmap > , MAX_BITMAPS_PER_BRUSH > bm ;
2014-09-27 23:06:33 +00:00
iff_error = iff_read_animbrush ( abmname , bm , & nframes , newpal ) ;
2006-03-20 17:12:09 +00:00
if ( iff_error ! = IFF_NO_ERROR ) {
Error ( " File %s - IFF error: %s " , abmname , iff_errormsg ( iff_error ) ) ;
}
for ( fnum = 0 ; fnum < nframes ; fnum + + ) {
int SuperX ;
//SuperX = (GameBitmaps[i+fnum].bm_flags&BM_FLAG_SUPER_TRANSPARENT)?254:-1;
SuperX = ( GameBitmapFlags [ i + fnum ] & BM_FLAG_SUPER_TRANSPARENT ) ? 254 : - 1 ;
//above makes assumption that supertransparent color is 254
2016-10-28 03:39:40 +00:00
gr_remap_bitmap_good ( * bm [ fnum ] . get ( ) , newpal , iff_has_transparency ? iff_transparent_color : - 1 , SuperX ) ;
2006-03-20 17:12:09 +00:00
2020-05-22 02:40:26 +00:00
# if !DXX_USE_OGL
2014-09-27 23:14:50 +00:00
bm [ fnum ] - > avg_color = compute_average_pixel ( bm [ fnum ] . get ( ) ) ;
2020-05-22 02:40:26 +00:00
# endif
2006-03-20 17:12:09 +00:00
2007-07-22 20:40:39 +00:00
if ( GameArg . EdiMacData )
2016-11-19 17:24:52 +00:00
swap_0_255 ( * bm [ fnum ] . get ( ) ) ;
2007-08-08 12:38:13 +00:00
2015-12-24 04:01:28 +00:00
if ( CGameArg . DbgNoCompressPigBitmap )
2015-01-29 04:27:37 +00:00
gr_bitmap_rle_compress ( * bm [ fnum ] . get ( ) ) ;
2006-03-20 17:12:09 +00:00
2017-01-15 00:03:13 +00:00
if ( bm [ fnum ] - > get_flag_mask ( BM_FLAG_RLE ) )
2015-06-13 22:42:21 +00:00
size = * reinterpret_cast < const int * > ( bm [ fnum ] - > bm_data ) ;
2006-03-20 17:12:09 +00:00
else
size = bm [ fnum ] - > bm_w * bm [ fnum ] - > bm_h ;
memcpy ( & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] , bm [ fnum ] - > bm_data , size ) ;
2014-12-02 03:24:38 +00:00
d_free ( bm [ fnum ] - > bm_mdata ) ;
bm [ fnum ] - > bm_mdata = & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] ;
2006-03-20 17:12:09 +00:00
Piggy_bitmap_cache_next + = size ;
2014-10-04 15:02:03 +00:00
GameBitmaps [ i + fnum ] = std : : move ( * bm [ fnum ] ) ;
2006-03-20 17:12:09 +00:00
}
i + = nframes - 1 ; //filled in multiple bitmaps
}
else { //this is a BBM
2013-12-08 17:05:51 +00:00
grs_bitmap n ;
2013-01-06 21:03:57 +00:00
palette_array_t newpal ;
2006-03-20 17:12:09 +00:00
int iff_error ;
char bbmname [ FILENAME_LEN ] ;
int SuperX ;
2022-12-17 13:16:28 +00:00
snprintf ( bbmname , sizeof ( bbmname ) , " %.8s.bbm " , abn . data ( ) ) ;
2016-05-28 17:31:27 +00:00
iff_error = iff_read_bitmap ( bbmname , n , & newpal ) ;
2006-03-20 17:12:09 +00:00
if ( iff_error ! = IFF_NO_ERROR ) {
Error ( " File %s - IFF error: %s " , bbmname , iff_errormsg ( iff_error ) ) ;
}
SuperX = ( GameBitmapFlags [ i ] & BM_FLAG_SUPER_TRANSPARENT ) ? 254 : - 1 ;
//above makes assumption that supertransparent color is 254
2016-10-28 03:39:40 +00:00
gr_remap_bitmap_good ( n , newpal , iff_has_transparency ? iff_transparent_color : - 1 , SuperX ) ;
2006-03-20 17:12:09 +00:00
2020-05-22 02:40:26 +00:00
# if !DXX_USE_OGL
2013-12-08 17:05:51 +00:00
n . avg_color = compute_average_pixel ( & n ) ;
2020-05-22 02:40:26 +00:00
# endif
2006-03-20 17:12:09 +00:00
2007-07-22 20:40:39 +00:00
if ( GameArg . EdiMacData )
2016-11-19 17:24:52 +00:00
swap_0_255 ( n ) ;
2007-08-08 12:38:13 +00:00
2015-12-24 04:01:28 +00:00
if ( CGameArg . DbgNoCompressPigBitmap )
2015-01-29 04:27:37 +00:00
gr_bitmap_rle_compress ( n ) ;
2006-03-20 17:12:09 +00:00
2017-01-15 00:03:13 +00:00
if ( n . get_flag_mask ( BM_FLAG_RLE ) )
2015-06-13 22:42:21 +00:00
size = * reinterpret_cast < const int * > ( n . bm_data ) ;
2006-03-20 17:12:09 +00:00
else
2013-12-08 17:05:51 +00:00
size = n . bm_w * n . bm_h ;
2006-03-20 17:12:09 +00:00
2013-12-08 17:05:51 +00:00
memcpy ( & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] , n . bm_data , size ) ;
2014-12-02 03:24:38 +00:00
d_free ( n . bm_mdata ) ;
n . bm_mdata = & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] ;
2006-03-20 17:12:09 +00:00
Piggy_bitmap_cache_next + = size ;
2013-12-08 17:05:51 +00:00
GameBitmaps [ i ] = n ;
2006-03-20 17:12:09 +00:00
}
}
//@@Dont' do these things which are done when writing
//@@for (i=0; i < Num_bitmap_files; i++ ) {
//@@ bitmap_index bi;
//@@ bi.index = i;
//@@ PIGGY_PAGE_IN( bi );
//@@}
//@@
//@@piggy_close_file();
2022-10-02 19:51:35 +00:00
piggy_write_pigfile ( pigname ) ;
2006-03-20 17:12:09 +00:00
Current_pigfile [ 0 ] = 0 ; //say no pig, to force reload
piggy_new_pigfile ( pigname ) ; //read in just-generated pig
}
# endif //ifdef EDITOR
}
# define HAMFILE_ID MAKE_SIG('!','M','A','H') //HAM!
# define HAMFILE_VERSION 3
//version 1 -> 2: save marker_model_num
//version 2 -> 3: removed sound files
# define SNDFILE_ID MAKE_SIG('D','N','S','D') //DSND
# define SNDFILE_VERSION 1
2022-07-09 13:39:29 +00:00
int read_hamfile ( d_level_shared_robot_info_state & LevelSharedRobotInfoState )
2006-03-20 17:12:09 +00:00
{
int ham_id ;
int sound_offset = 0 ;
2008-10-31 13:09:30 +00:00
int shareware = 0 ;
2006-03-20 17:12:09 +00:00
2021-07-25 23:00:56 +00:00
auto ham_fp = PHYSFSX_openReadBuffered ( DEFAULT_HAMFILE_REGISTERED ) . first ;
2007-05-20 02:00:57 +00:00
if ( ! ham_fp )
2008-11-20 12:29:48 +00:00
{
2021-07-25 23:00:56 +00:00
ham_fp = PHYSFSX_openReadBuffered ( DEFAULT_HAMFILE_SHAREWARE ) . first ;
2008-11-20 12:29:48 +00:00
if ( ham_fp )
{
shareware = 1 ;
GameArg . SndDigiSampleRate = SAMPLE_RATE_11K ;
2015-11-24 04:05:36 +00:00
if ( CGameArg . SndDisableSdlMixer )
2013-06-27 09:41:46 +00:00
{
digi_close ( ) ;
digi_init ( ) ;
}
2008-11-20 12:29:48 +00:00
}
}
2006-03-20 17:12:09 +00:00
2015-01-17 18:31:42 +00:00
if ( ! ham_fp ) {
2006-03-20 17:12:09 +00:00
return 0 ;
}
//make sure ham is valid type file & is up-to-date
2011-06-01 07:59:55 +00:00
ham_id = PHYSFSX_readInt ( ham_fp ) ;
2022-10-09 23:15:20 +00:00
/* All code checks only that Piggy_hamfile_version is `< 3` or `! ( < 3 )`,
* so clamp any version higher than 3 to just 3.
*/
Piggy_hamfile_version = static_cast < pig_hamfile_version > ( std : : clamp ( PHYSFSX_readInt ( ham_fp ) , 0 , 3 ) ) ;
2006-03-20 17:12:09 +00:00
if ( ham_id ! = HAMFILE_ID )
2022-10-09 23:15:20 +00:00
Error ( " Failed to load ham file " DEFAULT_HAMFILE_REGISTERED " : expected ham_id=%.8lx, found ham_id=%.8x version=%.8x \n " , HAMFILE_ID , ham_id , underlying_value ( Piggy_hamfile_version ) ) ;
2006-03-20 17:12:09 +00:00
2022-10-09 23:15:20 +00:00
if ( Piggy_hamfile_version < pig_hamfile_version : : _3 ) // hamfile contains sound info, probably PC demo
2008-10-31 13:09:30 +00:00
{
2011-06-01 07:59:55 +00:00
sound_offset = PHYSFSX_readInt ( ham_fp ) ;
2008-10-31 13:09:30 +00:00
if ( shareware ) // deal with interactive PC demo
{
2013-11-10 16:38:06 +00:00
GameArg . GfxSkipHiresGFX = 1 ;
2015-12-24 04:01:26 +00:00
//CGameArg.SysLowMem = 1;
2008-10-31 13:09:30 +00:00
}
}
2006-03-20 17:12:09 +00:00
# if 1 //ndef EDITOR
{
2022-07-09 13:39:29 +00:00
bm_read_all ( LevelSharedRobotInfoState , Vclip , ham_fp ) ;
2011-06-01 07:59:55 +00:00
//PHYSFS_read( ham_fp, GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1 );
2016-07-14 01:59:05 +00:00
range_for ( auto & i , GameBitmapXlat )
2008-11-01 01:19:52 +00:00
{
2016-07-14 01:59:05 +00:00
i = PHYSFSX_readShort ( ham_fp ) ;
2008-11-01 01:19:52 +00:00
if ( PHYSFS_eof ( ham_fp ) )
break ;
}
2006-03-20 17:12:09 +00:00
}
# endif
2022-10-09 23:15:20 +00:00
if ( Piggy_hamfile_version < pig_hamfile_version : : _3 ) {
2006-03-20 17:12:09 +00:00
int N_sounds ;
int sound_start ;
int header_size ;
int i ;
DiskSoundHeader sndh ;
int sbytes = 0 ;
2011-02-24 10:28:59 +00:00
static int justonce = 1 ;
if ( ! justonce )
{
return 1 ;
}
justonce = 0 ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( ham_fp , sound_offset , SEEK_SET ) ;
N_sounds = PHYSFSX_readInt ( ham_fp ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
sound_start = PHYSFS_tell ( ham_fp ) ;
2006-03-20 17:12:09 +00:00
header_size = N_sounds * sizeof ( DiskSoundHeader ) ;
//Read sounds
for ( i = 0 ; i < N_sounds ; i + + ) {
DiskSoundHeader_read ( & sndh , ham_fp ) ;
2022-12-10 18:09:54 +00:00
digi_sound temp_sound ;
2006-03-20 17:12:09 +00:00
temp_sound . length = sndh . length ;
2022-10-02 19:51:35 +00:00
const game_sound_offset sound_offset { sndh . offset + header_size + sound_start } ;
2022-12-10 18:09:54 +00:00
temp_sound . data = digi_sound : : allocated_data { nullptr , sound_offset } ;
2022-12-17 13:16:28 +00:00
piggy_register_sound ( temp_sound , std : : span ( sndh . name ) . first < 8 > ( ) ) ;
2006-03-20 17:12:09 +00:00
if ( piggy_is_needed ( i ) )
sbytes + = sndh . length ;
}
2020-05-02 21:18:42 +00:00
SoundBits = std : : make_unique < ubyte [ ] > ( sbytes + 16 ) ;
2006-03-20 17:12:09 +00:00
}
return 1 ;
}
2021-07-25 23:00:56 +00:00
void read_sndfile ( const int required )
2006-03-20 17:12:09 +00:00
{
int snd_id , snd_version ;
int N_sounds ;
int sound_start ;
int header_size ;
2011-09-26 23:31:19 +00:00
int i ;
2006-03-20 17:12:09 +00:00
DiskSoundHeader sndh ;
int sbytes = 0 ;
2021-07-25 23:00:56 +00:00
const auto filename = DEFAULT_SNDFILE ;
2021-07-25 23:00:56 +00:00
auto & & [ snd_fp , physfserr ] = PHYSFSX_openReadBuffered ( filename ) ;
2015-01-17 18:31:42 +00:00
if ( ! snd_fp )
2021-07-25 23:00:56 +00:00
{
if ( required )
2021-07-25 23:00:56 +00:00
Error ( " Cannot open sound file: %s: %s " , filename , PHYSFS_getErrorByCode ( physfserr ) ) ;
2021-07-25 23:00:56 +00:00
return ;
}
2006-03-20 17:12:09 +00:00
//make sure soundfile is valid type file & is up-to-date
2011-06-01 07:59:55 +00:00
snd_id = PHYSFSX_readInt ( snd_fp ) ;
snd_version = PHYSFSX_readInt ( snd_fp ) ;
2006-03-20 17:12:09 +00:00
if ( snd_id ! = SNDFILE_ID | | snd_version ! = SNDFILE_VERSION ) {
2021-07-25 23:00:56 +00:00
if ( required )
Error ( " Cannot load sound file: expected (id=%.8lx version=%.8x), found (id=%.8x version=%.8x) in \" %s \" " , SNDFILE_ID , SNDFILE_VERSION , snd_id , snd_version , filename ) ;
return ;
2006-03-20 17:12:09 +00:00
}
2011-06-01 07:59:55 +00:00
N_sounds = PHYSFSX_readInt ( snd_fp ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
sound_start = PHYSFS_tell ( snd_fp ) ;
2006-03-20 17:12:09 +00:00
header_size = N_sounds * sizeof ( DiskSoundHeader ) ;
//Read sounds
for ( i = 0 ; i < N_sounds ; i + + ) {
DiskSoundHeader_read ( & sndh , snd_fp ) ;
2022-12-10 18:09:54 +00:00
digi_sound temp_sound ;
2006-03-20 17:12:09 +00:00
temp_sound . length = sndh . length ;
2022-10-02 19:51:35 +00:00
const game_sound_offset sound_offset { sndh . offset + header_size + sound_start } ;
2022-12-10 18:09:54 +00:00
temp_sound . data = digi_sound : : allocated_data { nullptr , sound_offset } ;
2022-12-17 13:16:28 +00:00
piggy_register_sound ( temp_sound , std : : span ( sndh . name ) . first < 8 > ( ) ) ;
2006-03-20 17:12:09 +00:00
if ( piggy_is_needed ( i ) )
2008-12-07 12:26:43 +00:00
sbytes + = sndh . length ;
2006-03-20 17:12:09 +00:00
}
2020-05-02 21:18:42 +00:00
SoundBits = std : : make_unique < ubyte [ ] > ( sbytes + 16 ) ;
2006-03-20 17:12:09 +00:00
}
2022-07-09 13:39:29 +00:00
int properties_init ( d_level_shared_robot_info_state & LevelSharedRobotInfoState )
2006-03-20 17:12:09 +00:00
{
int ham_ok = 0 , snd_ok = 0 ;
2022-09-24 17:47:52 +00:00
GameSounds = { } ;
2016-07-14 01:59:05 +00:00
for ( unsigned i = 0 ; i < GameBitmapXlat . size ( ) ; + + i )
2016-02-12 04:02:28 +00:00
{
2006-03-20 17:12:09 +00:00
GameBitmapXlat [ i ] = i ;
2013-03-03 01:03:33 +00:00
}
2006-03-20 17:12:09 +00:00
if ( ! bogus_bitmap_initialized ) {
ubyte c ;
bogus_bitmap_initialized = 1 ;
c = gr_find_closest_color ( 0 , 0 , 63 ) ;
2015-02-28 19:36:01 +00:00
bogus_data . fill ( c ) ;
2006-03-20 17:12:09 +00:00
c = gr_find_closest_color ( 63 , 0 , 0 ) ;
// Make a big red X !
2019-05-04 18:27:36 +00:00
range_for ( const unsigned i , xrange ( 64u ) )
2016-02-12 04:02:28 +00:00
{
2006-03-20 17:12:09 +00:00
bogus_data [ i * 64 + i ] = c ;
bogus_data [ i * 64 + ( 63 - i ) ] = c ;
}
2016-05-28 17:31:27 +00:00
gr_init_bitmap ( GameBitmaps [ Num_bitmap_files ] , bm_mode : : linear , 0 , 0 , 64 , 64 , 64 , bogus_data . data ( ) ) ;
2016-11-19 17:24:53 +00:00
piggy_register_bitmap ( GameBitmaps [ Num_bitmap_files ] , " bogus " , 1 ) ;
2006-03-20 17:12:09 +00:00
bogus_sound . length = 64 * 64 ;
2022-12-10 18:09:54 +00:00
bogus_sound . data = digi_sound : : allocated_data { bogus_data . data ( ) , game_sound_offset { INT_MAX } } ;
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ 0 ] = pig_bitmap_offset : : None ;
2006-03-20 17:12:09 +00:00
}
2022-07-09 13:39:29 +00:00
snd_ok = ham_ok = read_hamfile ( LevelSharedRobotInfoState ) ;
2006-03-20 17:12:09 +00:00
2022-10-09 23:15:20 +00:00
if ( Piggy_hamfile_version > = pig_hamfile_version : : _3 )
2010-03-26 21:17:56 +00:00
{
2021-07-25 23:00:56 +00:00
read_sndfile ( 1 ) ;
2010-03-26 21:17:56 +00:00
}
2006-03-20 17:12:09 +00:00
return ( ham_ok & & snd_ok ) ; //read ok
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
void piggy_read_sounds ( int pc_shareware )
{
2016-07-14 01:59:02 +00:00
uint8_t * ptr ;
2022-01-07 04:26:22 +00:00
int i ;
2013-03-03 01:03:33 +00:00
if ( MacPig )
{
// Read Mac sounds converted to RAW format (too messy to read them directly from the resource fork code-wise)
char soundfile [ 32 ] = " Sounds/sounds.array " ;
2015-01-17 18:31:42 +00:00
// hack for Mac Demo
2021-07-25 23:00:56 +00:00
if ( auto array = PHYSFSX_openReadBuffered ( soundfile ) . first )
2013-03-03 01:03:33 +00:00
{
2020-09-11 03:08:03 +00:00
/* Sounds.size() is the D2-compatible size, but this
* statement must read a D1 length , so use MAX_SOUNDS .
*/
if ( PHYSFS_read ( array , Sounds , MAX_SOUNDS , 1 ) ! = 1 ) // make the 'Sounds' index array match with the sounds we're about to read in
2013-03-03 01:03:33 +00:00
{
con_printf ( CON_URGENT , " Warning: Can't read Sounds/sounds.array: %s " , PHYSFS_getLastError ( ) ) ;
return ;
}
}
2015-01-17 18:31:41 +00:00
else if ( PHYSFSX_fsize ( DEFAULT_PIGFILE_REGISTERED ) = = D1_MAC_SHARE_PIGSIZE )
{
con_printf ( CON_URGENT , " Warning: Missing Sounds/sounds.array for Mac data files " ) ;
return ;
}
2013-03-03 01:03:33 +00:00
for ( i = 0 ; i < MAX_SOUND_FILES ; i + + )
{
2016-01-03 20:21:36 +00:00
snprintf ( soundfile , sizeof ( soundfile ) , " SND%04d.raw " , i ) ;
2013-03-03 01:03:33 +00:00
if ( ds_load ( 0 , soundfile ) = = 255 )
break ;
}
return ;
}
2014-07-24 02:45:47 +00:00
ptr = SoundBits . get ( ) ;
2013-03-03 01:03:33 +00:00
2021-06-28 03:37:48 +00:00
std : : vector < uint8_t > lastbuf ;
2013-03-03 01:03:33 +00:00
for ( i = 0 ; i < Num_sound_files ; i + + )
{
2022-12-10 18:09:54 +00:00
auto & snd = GameSounds [ i ] ;
auto & d = snd . data . get_deleter ( ) ;
if ( ! d . must_free_buffer ( ) )
2013-03-03 01:03:33 +00:00
{
if ( piggy_is_needed ( i ) )
{
2022-12-10 18:09:54 +00:00
const auto current_sound_offset = d . offset ;
const auto sound_offset = underlying_value ( current_sound_offset ) ;
2022-10-02 19:51:35 +00:00
PHYSFSX_fseek ( Piggy_fp , sound_offset , SEEK_SET ) ;
2013-03-03 01:03:33 +00:00
// Read in the sound data!!!
2022-12-10 18:09:54 +00:00
snd . data = digi_sound : : allocated_data { ptr , current_sound_offset } ;
ptr + = snd . length ;
2013-03-03 01:03:33 +00:00
//Arne's decompress for shareware on all soundcards - Tim@Rikers.org
if ( pc_shareware )
{
2021-06-28 03:37:48 +00:00
const auto compressed_length = SoundCompressed [ i ] ;
lastbuf . resize ( compressed_length ) ;
PHYSFS_read ( Piggy_fp , lastbuf . data ( ) , compressed_length , 1 ) ;
2022-12-10 18:09:54 +00:00
sound_decompress ( lastbuf . data ( ) , compressed_length , snd . data . get ( ) ) ;
2013-03-03 01:03:33 +00:00
}
else
2022-12-10 18:09:54 +00:00
PHYSFS_read ( Piggy_fp , snd . data . get ( ) , snd . length , 1 ) ;
2013-03-03 01:03:33 +00:00
}
}
}
}
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
void piggy_read_sounds ( void )
{
2016-07-14 01:59:02 +00:00
uint8_t * ptr ;
2022-01-07 04:26:22 +00:00
int i ;
2006-03-20 17:12:09 +00:00
2014-07-24 02:45:47 +00:00
ptr = SoundBits . get ( ) ;
2021-07-25 23:00:56 +00:00
auto fp = PHYSFSX_openReadBuffered ( DEFAULT_SNDFILE ) . first ;
2015-01-17 18:31:42 +00:00
if ( ! fp )
2006-03-20 17:12:09 +00:00
return ;
for ( i = 0 ; i < Num_sound_files ; i + + ) {
2022-12-10 18:09:54 +00:00
auto & snd = GameSounds [ i ] ;
auto & d = snd . data . get_deleter ( ) ;
if ( ! d . must_free_buffer ( ) )
2022-10-02 19:51:35 +00:00
{
2006-03-20 17:12:09 +00:00
if ( piggy_is_needed ( i ) ) {
2022-12-10 18:09:54 +00:00
const auto current_sound_offset = snd . data . get_deleter ( ) . offset ;
const auto sound_offset = underlying_value ( current_sound_offset ) ;
2022-10-02 19:51:35 +00:00
PHYSFSX_fseek ( fp , sound_offset , SEEK_SET ) ;
2006-03-20 17:12:09 +00:00
// Read in the sound data!!!
2022-12-10 18:09:54 +00:00
snd . data = digi_sound : : allocated_data { ptr , current_sound_offset } ;
ptr + = snd . length ;
PHYSFS_read ( fp , snd . data . get ( ) , snd . length , 1 ) ;
2006-03-20 17:12:09 +00:00
}
else
2022-12-10 18:09:54 +00:00
snd . data . reset ( ) ;
2006-03-20 17:12:09 +00:00
}
}
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2022-06-05 17:44:52 +00:00
void piggy_bitmap_page_in ( GameBitmaps_array & GameBitmaps , const bitmap_index bitmap )
2006-03-20 17:12:09 +00:00
{
grs_bitmap * bmp ;
2011-09-26 23:31:19 +00:00
int i , org_i ;
2006-03-20 17:12:09 +00:00
org_i = 0 ;
i = bitmap . index ;
Assert ( i > = 0 ) ;
Assert ( i < MAX_BITMAP_FILES ) ;
Assert ( i < Num_bitmap_files ) ;
Assert ( Piggy_bitmap_cache_size > 0 ) ;
if ( i < 1 ) return ;
if ( i > = MAX_BITMAP_FILES ) return ;
if ( i > = Num_bitmap_files ) return ;
2020-08-24 01:31:28 +00:00
if ( GameBitmapOffset [ i ] = = pig_bitmap_offset : : None )
return ; // A read-from-disk bitmap!!!
2006-03-20 17:12:09 +00:00
2015-12-24 04:01:26 +00:00
if ( CGameArg . SysLowMem )
{
2006-03-20 17:12:09 +00:00
org_i = i ;
i = GameBitmapXlat [ i ] ; // Xlat for low-memory settings!
}
bmp = & GameBitmaps [ i ] ;
2017-01-15 00:03:13 +00:00
if ( bmp - > get_flag_mask ( BM_FLAG_PAGED_OUT ) )
{
2015-10-09 02:46:09 +00:00
pause_game_world_time p ;
2006-03-20 17:12:09 +00:00
ReDoIt :
2020-08-24 01:31:28 +00:00
PHYSFS_seek ( Piggy_fp , static_cast < unsigned > ( GameBitmapOffset [ i ] ) ) ;
2006-03-20 17:12:09 +00:00
2014-11-30 22:09:21 +00:00
gr_set_bitmap_flags ( * bmp , GameBitmapFlags [ i ] ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-11-30 22:09:20 +00:00
gr_set_bitmap_data ( * bmp , & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2017-01-15 00:03:13 +00:00
if ( bmp - > get_flag_mask ( BM_FLAG_RLE ) )
{
2013-10-06 16:20:00 +00:00
int zsize = PHYSFSX_readInt ( Piggy_fp ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
// GET JOHN NOW IF YOU GET THIS ASSERT!!!
Assert ( Piggy_bitmap_cache_next + zsize < Piggy_bitmap_cache_size ) ;
if ( Piggy_bitmap_cache_next + zsize > = Piggy_bitmap_cache_size ) {
piggy_bitmap_page_out_all ( ) ;
goto ReDoIt ;
}
memcpy ( & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] , & zsize , sizeof ( int ) ) ;
Piggy_bitmap_cache_next + = sizeof ( int ) ;
PHYSFS_read ( Piggy_fp , & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] , 1 , zsize - 4 ) ;
if ( MacPig )
{
2015-01-29 04:27:37 +00:00
rle_swap_0_255 ( * bmp ) ;
2013-03-03 01:03:33 +00:00
memcpy ( & zsize , bmp - > bm_data , 4 ) ;
}
Piggy_bitmap_cache_next + = zsize - 4 ;
# elif defined(DXX_BUILD_DESCENT_II)
2013-10-06 16:20:00 +00:00
int pigsize = PHYSFS_fileLength ( Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
// GET JOHN NOW IF YOU GET THIS ASSERT!!!
//Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size );
if ( Piggy_bitmap_cache_next + zsize > = Piggy_bitmap_cache_size ) {
Int3 ( ) ;
piggy_bitmap_page_out_all ( ) ;
goto ReDoIt ;
}
2011-09-26 23:31:19 +00:00
PHYSFS_read ( Piggy_fp , & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next + 4 ] , 1 , zsize - 4 ) ;
2017-02-11 21:42:43 +00:00
PUT_INTEL_INT ( & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] , zsize ) ;
2014-11-30 22:09:20 +00:00
gr_set_bitmap_data ( * bmp , & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] ) ;
2006-03-20 17:12:09 +00:00
# ifndef MACDATA
switch ( pigsize ) {
default :
2007-07-22 20:40:39 +00:00
if ( ! GameArg . EdiMacData )
2006-03-20 17:12:09 +00:00
break ;
2022-01-09 15:25:42 +00:00
[[fallthrough]] ;
2006-03-20 17:12:09 +00:00
case MAC_ALIEN1_PIGSIZE :
case MAC_ALIEN2_PIGSIZE :
case MAC_FIRE_PIGSIZE :
case MAC_GROUPA_PIGSIZE :
case MAC_ICE_PIGSIZE :
case MAC_WATER_PIGSIZE :
2015-01-29 04:27:37 +00:00
rle_swap_0_255 ( * bmp ) ;
2006-03-20 17:12:09 +00:00
memcpy ( & zsize , bmp - > bm_data , 4 ) ;
break ;
}
# endif
Piggy_bitmap_cache_next + = zsize ;
if ( Piggy_bitmap_cache_next + zsize > = Piggy_bitmap_cache_size ) {
Int3 ( ) ;
piggy_bitmap_page_out_all ( ) ;
goto ReDoIt ;
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
} else {
// GET JOHN NOW IF YOU GET THIS ASSERT!!!
Assert ( Piggy_bitmap_cache_next + ( bmp - > bm_h * bmp - > bm_w ) < Piggy_bitmap_cache_size ) ;
if ( Piggy_bitmap_cache_next + ( bmp - > bm_h * bmp - > bm_w ) > = Piggy_bitmap_cache_size ) {
piggy_bitmap_page_out_all ( ) ;
goto ReDoIt ;
}
2011-09-26 23:31:19 +00:00
PHYSFS_read ( Piggy_fp , & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] , 1 , bmp - > bm_h * bmp - > bm_w ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
Piggy_bitmap_cache_next + = bmp - > bm_h * bmp - > bm_w ;
if ( MacPig )
2016-11-19 17:24:52 +00:00
swap_0_255 ( * bmp ) ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
int pigsize = PHYSFS_fileLength ( Piggy_fp ) ;
2014-11-30 22:09:20 +00:00
gr_set_bitmap_data ( * bmp , & Piggy_bitmap_cache_data [ Piggy_bitmap_cache_next ] ) ;
2006-03-20 17:12:09 +00:00
Piggy_bitmap_cache_next + = bmp - > bm_h * bmp - > bm_w ;
# ifndef MACDATA
switch ( pigsize ) {
default :
2007-07-22 20:40:39 +00:00
if ( ! GameArg . EdiMacData )
2006-03-20 17:12:09 +00:00
break ;
2022-01-09 15:25:42 +00:00
[[fallthrough]] ;
2006-03-20 17:12:09 +00:00
case MAC_ALIEN1_PIGSIZE :
case MAC_ALIEN2_PIGSIZE :
case MAC_FIRE_PIGSIZE :
case MAC_GROUPA_PIGSIZE :
case MAC_ICE_PIGSIZE :
case MAC_WATER_PIGSIZE :
2016-11-19 17:24:52 +00:00
swap_0_255 ( * bmp ) ;
2006-03-20 17:12:09 +00:00
break ;
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
# endif
}
//@@if ( bmp->bm_selector ) {
//@@#if !defined(WINDOWS) && !defined(MACINTOSH)
//@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
//@@ Error( "Error modifying selector base in piggy.c\n" );
//@@#endif
//@@}
2011-04-12 01:02:51 +00:00
compute_average_rgb ( bmp , bmp - > avg_color_rgb ) ;
2006-03-20 17:12:09 +00:00
}
2015-12-24 04:01:26 +00:00
if ( CGameArg . SysLowMem )
{
2006-03-20 17:12:09 +00:00
if ( org_i ! = i )
GameBitmaps [ org_i ] = GameBitmaps [ i ] ;
}
//@@Removed from John's code:
//@@#ifndef WINDOWS
//@@ if ( bmp->bm_selector ) {
//@@ if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data ))
//@@ Error( "Error modifying selector base in piggy.c\n" );
//@@ }
//@@#endif
}
2022-06-05 17:44:52 +00:00
namespace {
2006-03-20 17:12:09 +00:00
void piggy_bitmap_page_out_all ( )
{
int i ;
Piggy_bitmap_cache_next = 0 ;
texmerge_flush ( ) ;
rle_cache_flush ( ) ;
2013-02-21 00:20:26 +00:00
for ( i = 0 ; i < Num_bitmap_files ; i + + ) {
2020-08-24 01:31:28 +00:00
if ( GameBitmapOffset [ i ] ! = pig_bitmap_offset : : None )
{ // Don't page out bitmaps read from disk!!!
2017-01-15 00:03:13 +00:00
GameBitmaps [ i ] . set_flags ( BM_FLAG_PAGED_OUT ) ;
2016-11-19 17:24:52 +00:00
gr_set_bitmap_data ( GameBitmaps [ i ] , nullptr ) ;
2006-03-20 17:12:09 +00:00
}
}
2016-08-25 04:05:32 +00:00
}
2022-06-05 17:44:52 +00:00
2006-03-20 17:12:09 +00:00
}
void piggy_load_level_data ( )
{
piggy_bitmap_page_out_all ( ) ;
2018-10-21 00:24:07 +00:00
paging_touch_all ( Vclip ) ;
2006-03-20 17:12:09 +00:00
}
2020-08-24 01:31:28 +00:00
namespace {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
2022-10-02 19:51:35 +00:00
static void piggy_write_pigfile ( const std : : span < const char , FILENAME_LEN > filename )
2006-03-20 17:12:09 +00:00
{
int bitmap_data_start , data_offset ;
DiskBitmapHeader bmh ;
int org_offset ;
int i ;
2022-12-18 18:32:14 +00:00
for ( const unsigned n = Num_bitmap_files ; const uint16_t i : xrange ( n ) )
{
const bitmap_index bi { i } ;
2006-03-20 17:12:09 +00:00
PIGGY_PAGE_IN ( bi ) ;
}
piggy_close_file ( ) ;
2022-10-02 19:51:35 +00:00
auto pig_fp = PHYSFSX_openWriteBuffered ( filename . data ( ) ) . first ; //open PIG file
2021-07-25 23:00:56 +00:00
if ( ! pig_fp )
return ;
2006-03-20 17:12:09 +00:00
write_int ( PIGFILE_ID , pig_fp ) ;
write_int ( PIGFILE_VERSION , pig_fp ) ;
Num_bitmap_files - - ;
2010-08-19 13:32:33 +00:00
PHYSFS_write ( pig_fp , & Num_bitmap_files , sizeof ( int ) , 1 ) ;
2006-03-20 17:12:09 +00:00
Num_bitmap_files + + ;
2011-06-01 07:59:55 +00:00
bitmap_data_start = PHYSFS_tell ( pig_fp ) ;
2006-03-20 17:12:09 +00:00
bitmap_data_start + = ( Num_bitmap_files - 1 ) * sizeof ( DiskBitmapHeader ) ;
data_offset = bitmap_data_start ;
2022-10-09 23:15:20 +00:00
std : : array < char , FILENAME_LEN > tname ;
2022-10-09 23:15:20 +00:00
if ( ! change_filename_extension ( tname , filename . data ( ) , " lst " ) )
return ;
2022-10-09 23:15:20 +00:00
auto fp1 = PHYSFSX_openWriteBuffered ( tname . data ( ) ) . first ;
2022-10-09 23:15:20 +00:00
if ( ! change_filename_extension ( tname , filename . data ( ) , " all " ) )
return ;
2022-10-09 23:15:20 +00:00
auto fp2 = PHYSFSX_openWriteBuffered ( tname . data ( ) ) . first ;
2006-03-20 17:12:09 +00:00
2013-02-21 00:20:26 +00:00
for ( i = 1 ; i < Num_bitmap_files ; i + + ) {
2006-03-20 17:12:09 +00:00
grs_bitmap * bmp ;
2022-12-17 13:16:28 +00:00
const std : : span name = AllBitmaps [ i ] . name ;
2013-02-21 00:20:26 +00:00
{
2018-08-26 18:10:36 +00:00
char * p1 ;
2022-12-17 13:16:28 +00:00
if ( const auto p = strchr ( name . data ( ) , ' # ' ) ) { // this is an ABM == animated bitmap
2006-03-20 17:12:09 +00:00
int n ;
p1 = p ; p1 + + ;
n = atoi ( p1 ) ;
* p = 0 ;
if ( fp2 & & n = = 0 )
2022-12-17 13:16:28 +00:00
PHYSFSX_printf ( fp2 , " %s.abm \n " , name . data ( ) ) ;
memcpy ( bmh . name , name . data ( ) , 8 ) ;
2006-03-20 17:12:09 +00:00
Assert ( n < = DBM_NUM_FRAMES ) ;
bmh . dflags = DBM_FLAG_ABM + n ;
* p = ' # ' ;
} else {
if ( fp2 )
2022-12-17 13:16:28 +00:00
PHYSFSX_printf ( fp2 , " %s.bbm \n " , name . data ( ) ) ;
memcpy ( bmh . name , name . data ( ) , 8 ) ;
2006-03-20 17:12:09 +00:00
bmh . dflags = 0 ;
}
}
bmp = & GameBitmaps [ i ] ;
2017-01-15 00:03:13 +00:00
assert ( ! bmp - > get_flag_mask ( BM_FLAG_PAGED_OUT ) ) ;
2006-03-20 17:12:09 +00:00
if ( fp1 )
2022-12-17 13:16:28 +00:00
PHYSFSX_printf ( fp1 , " BMP: %s, size %d bytes " , name . data ( ) , bmp - > bm_rowsize * bmp - > bm_h ) ;
2011-06-01 07:59:55 +00:00
org_offset = PHYSFS_tell ( pig_fp ) ;
2006-03-20 17:12:09 +00:00
bmh . offset = data_offset - bitmap_data_start ;
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( pig_fp , data_offset , SEEK_SET ) ;
2006-03-20 17:12:09 +00:00
2017-01-15 00:03:13 +00:00
if ( bmp - > get_flag_mask ( BM_FLAG_RLE ) )
{
2015-06-13 22:42:21 +00:00
const auto size = reinterpret_cast < const int * > ( bmp - > bm_data ) ;
2010-08-19 13:32:33 +00:00
PHYSFS_write ( pig_fp , bmp - > bm_data , sizeof ( ubyte ) , * size ) ;
2006-03-20 17:12:09 +00:00
data_offset + = * size ;
if ( fp1 )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( fp1 , " , and is already compressed to %d bytes. \n " , * size ) ;
2006-03-20 17:12:09 +00:00
} else {
2010-08-19 13:32:33 +00:00
PHYSFS_write ( pig_fp , bmp - > bm_data , sizeof ( ubyte ) , bmp - > bm_rowsize * bmp - > bm_h ) ;
2006-03-20 17:12:09 +00:00
data_offset + = bmp - > bm_rowsize * bmp - > bm_h ;
if ( fp1 )
2022-10-02 19:51:36 +00:00
PHYSFSX_puts_literal ( fp1 , " . \n " ) ;
2006-03-20 17:12:09 +00:00
}
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( pig_fp , org_offset , SEEK_SET ) ;
2006-03-20 17:12:09 +00:00
Assert ( GameBitmaps [ i ] . bm_w < 4096 ) ;
bmh . width = ( GameBitmaps [ i ] . bm_w & 0xff ) ;
bmh . wh_extra = ( ( GameBitmaps [ i ] . bm_w > > 8 ) & 0x0f ) ;
Assert ( GameBitmaps [ i ] . bm_h < 4096 ) ;
bmh . height = GameBitmaps [ i ] . bm_h ;
bmh . wh_extra | = ( ( GameBitmaps [ i ] . bm_h > > 4 ) & 0xf0 ) ;
2017-01-15 00:03:13 +00:00
bmh . flags = GameBitmaps [ i ] . get_flags ( ) ;
2022-12-17 13:16:28 +00:00
if ( std : : array < char , 32 > subst_name ; piggy_is_substitutable_bitmap ( name , subst_name ) )
2018-08-26 18:10:36 +00:00
{
2022-12-18 18:32:14 +00:00
const auto other_bitmap = piggy_find_bitmap ( subst_name ) ;
2006-03-20 17:12:09 +00:00
GameBitmapXlat [ i ] = other_bitmap . index ;
bmh . flags | = BM_FLAG_PAGED_OUT ;
2013-02-21 00:20:26 +00:00
} else {
2006-03-20 17:12:09 +00:00
bmh . flags & = ~ BM_FLAG_PAGED_OUT ;
}
2020-05-22 02:40:26 +00:00
bmh . avg_color = compute_average_pixel ( & GameBitmaps [ i ] ) ;
2013-02-21 00:20:26 +00:00
PHYSFS_write ( pig_fp , & bmh , sizeof ( DiskBitmapHeader ) , 1 ) ; // Mark as a bitmap
2006-03-20 17:12:09 +00:00
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( fp1 , " Dumped %d assorted bitmaps. \n " , Num_bitmap_files ) ;
2006-03-20 17:12:09 +00:00
}
2016-01-09 16:38:14 +00:00
static void write_int ( int i , PHYSFS_File * file )
2006-03-20 17:12:09 +00:00
{
2010-08-19 13:32:33 +00:00
if ( PHYSFS_write ( file , & i , sizeof ( i ) , 1 ) ! = 1 )
2006-03-20 17:12:09 +00:00
Error ( " Error reading int in gamesave.c " ) ;
}
# endif
2020-08-24 01:31:28 +00:00
/*
* Functions for loading replacement textures
* 1 ) From . pog files
* 2 ) From descent . pig ( for loading d1 levels )
*/
static void free_bitmap_replacements ( )
{
Bitmap_replacement_data . reset ( ) ;
}
2013-03-03 01:03:33 +00:00
# endif
2020-08-24 01:31:28 +00:00
}
2006-03-20 17:12:09 +00:00
void piggy_close ( )
{
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
custom_close ( ) ;
# endif
2006-03-20 17:12:09 +00:00
piggy_close_file ( ) ;
2014-07-24 02:45:47 +00:00
BitmapBits . reset ( ) ;
2014-07-24 02:45:47 +00:00
SoundBits . reset ( ) ;
2022-12-10 18:09:54 +00:00
for ( auto & gs : partial_range ( GameSounds , Num_sound_files ) )
gs . data . reset ( ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2008-11-14 16:56:40 +00:00
free_bitmap_replacements ( ) ;
free_d1_tmap_nums ( ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
}
2020-08-24 01:31:28 +00:00
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2014-08-23 16:27:28 +00:00
void remove_char ( char * s , char c )
{
char * p = strchr ( s , c ) ;
if ( p ) * p = ' \0 ' ;
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2020-08-24 01:31:28 +00:00
namespace dsx {
namespace {
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2018-08-26 18:10:36 +00:00
static const BitmapFile * piggy_does_bitmap_exist_slow ( const char * const name )
2006-03-20 17:12:09 +00:00
{
2018-08-26 18:10:36 +00:00
range_for ( auto & i , partial_const_range ( AllBitmaps , Num_bitmap_files ) )
{
2018-08-26 18:10:36 +00:00
if ( ! strcmp ( i . name . data ( ) , name ) )
2018-08-26 18:10:36 +00:00
return & i ;
2006-03-20 17:12:09 +00:00
}
2018-08-26 18:10:36 +00:00
return nullptr ;
2006-03-20 17:12:09 +00:00
}
2016-07-16 16:52:04 +00:00
constexpr char gauge_bitmap_names [ ] [ 9 ] = {
2013-10-06 16:20:00 +00:00
" gauge01 " ,
" gauge02 " ,
" gauge06 " ,
" targ01 " ,
" targ02 " ,
" targ03 " ,
" targ04 " ,
" targ05 " ,
" targ06 " ,
" gauge18 " ,
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
" targ01pc " ,
" targ02pc " ,
" targ03pc " ,
" gaug18pc "
# elif defined(DXX_BUILD_DESCENT_II)
2013-10-06 16:20:00 +00:00
" gauge01b " ,
" gauge02b " ,
" gauge06b " ,
" targ01b " ,
" targ02b " ,
" targ03b " ,
" targ04b " ,
" targ05b " ,
" targ06b " ,
" gauge18b " ,
" gauss1 " ,
" helix1 " ,
2006-03-20 17:12:09 +00:00
" phoenix1 "
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
} ;
2018-08-26 18:10:36 +00:00
static const char ( * piggy_is_gauge_bitmap ( const char * const base_name ) ) [ 9 ]
2006-03-20 17:12:09 +00:00
{
2018-08-26 18:10:36 +00:00
range_for ( auto & i , gauge_bitmap_names )
{
if ( ! d_stricmp ( base_name , i ) )
return & i ;
2006-03-20 17:12:09 +00:00
}
2018-08-26 18:10:36 +00:00
return nullptr ;
2006-03-20 17:12:09 +00:00
}
2022-12-17 13:16:28 +00:00
static int piggy_is_substitutable_bitmap ( std : : span < const char , 13 > name , std : : array < char , 32 > & subst_name )
2006-03-20 17:12:09 +00:00
{
2022-12-17 13:16:28 +00:00
std : : copy ( name . begin ( ) , name . end ( ) , subst_name . begin ( ) ) ;
if ( const auto p = strchr ( subst_name . data ( ) , ' # ' ) )
{
const int frame = atoi ( & p [ 1 ] ) ;
2006-03-20 17:12:09 +00:00
* p = 0 ;
2022-12-17 13:16:28 +00:00
auto base_name = subst_name ;
if ( ! piggy_is_gauge_bitmap ( base_name . data ( ) ) )
{
snprintf ( subst_name . data ( ) , subst_name . size ( ) , " %.13s#%d " , base_name . data ( ) , frame + 1 ) ;
if ( piggy_does_bitmap_exist_slow ( subst_name . data ( ) ) )
{
2006-03-20 17:12:09 +00:00
if ( frame & 1 ) {
2022-12-17 13:16:28 +00:00
snprintf ( subst_name . data ( ) , subst_name . size ( ) , " %.13s#%d " , base_name . data ( ) , frame - 1 ) ;
2006-03-20 17:12:09 +00:00
return 1 ;
}
}
}
2022-12-17 13:16:28 +00:00
std : : copy ( name . begin ( ) , name . end ( ) , subst_name . begin ( ) ) ;
2006-03-20 17:12:09 +00:00
}
return 0 ;
}
2013-09-22 22:26:27 +00:00
# endif
2006-03-20 17:12:09 +00:00
2020-08-24 01:31:28 +00:00
/* returns nonzero if d1_tmap_num references a texture which isn't available in d2. */
int d1_tmap_num_unique ( uint16_t d1_tmap_num )
{
switch ( d1_tmap_num ) {
case 0 : case 2 : case 4 : case 5 : case 6 : case 7 : case 9 :
case 10 : case 11 : case 12 : case 17 : case 18 :
case 20 : case 21 : case 25 : case 28 :
case 38 : case 39 : case 41 : case 44 : case 49 :
case 50 : case 55 : case 57 : case 88 :
case 132 : case 141 : case 147 :
case 154 : case 155 : case 158 : case 159 :
case 160 : case 161 : case 167 : case 168 : case 169 :
case 170 : case 171 : case 174 : case 175 : case 185 :
case 193 : case 194 : case 195 : case 198 : case 199 :
case 200 : case 202 : case 210 : case 211 :
case 220 : case 226 : case 227 : case 228 : case 229 : case 230 :
case 240 : case 241 : case 242 : case 243 : case 246 :
case 250 : case 251 : case 252 : case 253 : case 257 : case 258 : case 259 :
case 260 : case 263 : case 266 : case 283 : case 298 :
case 315 : case 317 : case 319 : case 320 : case 321 :
case 330 : case 331 : case 332 : case 333 : case 349 :
case 351 : case 352 : case 353 : case 354 :
case 355 : case 357 : case 358 : case 359 :
case 362 : case 370 : return 1 ;
default : return 0 ;
}
}
2006-03-20 17:12:09 +00:00
}
2022-10-09 23:15:20 +00:00
void load_bitmap_replacements ( const std : : span < const char , FILENAME_LEN > level_name )
2006-03-20 17:12:09 +00:00
{
//first, free up data allocated for old bitmaps
free_bitmap_replacements ( ) ;
2022-10-09 23:15:20 +00:00
std : : array < char , FILENAME_LEN > ifile_name ;
2022-10-09 23:15:20 +00:00
if ( ! change_filename_extension ( ifile_name , level_name . data ( ) , " POG " ) )
return ;
2022-10-09 23:15:20 +00:00
if ( auto ifile = PHYSFSX_openReadBuffered ( ifile_name . data ( ) ) . first )
2015-01-17 18:31:42 +00:00
{
2015-01-28 03:42:53 +00:00
int id , version ;
unsigned n_bitmaps ;
2006-03-20 17:12:09 +00:00
int bitmap_data_size ;
2011-06-01 07:59:55 +00:00
id = PHYSFSX_readInt ( ifile ) ;
version = PHYSFSX_readInt ( ifile ) ;
2006-03-20 17:12:09 +00:00
if ( id ! = MAKE_SIG ( ' G ' , ' O ' , ' P ' , ' D ' ) | | version ! = 1 ) {
return ;
}
2011-06-01 07:59:55 +00:00
n_bitmaps = PHYSFSX_readInt ( ifile ) ;
2006-03-20 17:12:09 +00:00
2021-06-28 03:37:49 +00:00
const auto indices = std : : make_unique < uint16_t [ ] > ( n_bitmaps ) ;
2015-01-28 03:42:53 +00:00
range_for ( auto & i , unchecked_partial_range ( indices . get ( ) , n_bitmaps ) )
i = PHYSFSX_readShort ( ifile ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
bitmap_data_size = PHYSFS_fileLength ( ifile ) - PHYSFS_tell ( ifile ) - sizeof ( DiskBitmapHeader ) * n_bitmaps ;
2020-05-02 21:18:42 +00:00
Bitmap_replacement_data = std : : make_unique < ubyte [ ] > ( bitmap_data_size ) ;
2006-03-20 17:12:09 +00:00
2015-05-22 03:33:20 +00:00
range_for ( const auto i , unchecked_partial_range ( indices . get ( ) , n_bitmaps ) )
{
grs_bitmap * bm = & GameBitmaps [ i ] ;
2006-03-20 17:12:09 +00:00
int width ;
2022-12-17 13:16:28 +00:00
const auto bmh = DiskBitmapHeader_read ( ifile ) ;
2006-03-20 17:12:09 +00:00
2016-06-05 01:04:26 +00:00
width = bmh . width + ( static_cast < short > ( bmh . wh_extra & 0x0f ) < < 8 ) ;
2014-11-30 22:09:20 +00:00
gr_set_bitmap_data ( * bm , NULL ) ; // free ogl texture
2016-06-05 01:04:26 +00:00
gr_init_bitmap ( * bm , bm_mode : : linear , 0 , 0 , width , bmh . height + ( static_cast < short > ( bmh . wh_extra & 0xf0 ) < < 4 ) , width , NULL ) ;
2020-05-22 02:40:26 +00:00
# if !DXX_USE_OGL
2006-03-20 17:12:09 +00:00
bm - > avg_color = bmh . avg_color ;
2020-05-22 02:40:26 +00:00
# endif
2016-07-14 01:59:02 +00:00
bm - > bm_data = reinterpret_cast < uint8_t * > ( static_cast < uintptr_t > ( bmh . offset ) ) ;
2006-03-20 17:12:09 +00:00
2014-11-30 22:09:21 +00:00
gr_set_bitmap_flags ( * bm , bmh . flags & BM_FLAGS_TO_COPY ) ;
2006-03-20 17:12:09 +00:00
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ i ] = pig_bitmap_offset : : None ; // don't try to read bitmap from current pigfile
2006-03-20 17:12:09 +00:00
}
2011-06-01 07:59:55 +00:00
PHYSFS_read ( ifile , Bitmap_replacement_data , 1 , bitmap_data_size ) ;
2006-03-20 17:12:09 +00:00
2015-05-22 03:33:20 +00:00
range_for ( const auto i , unchecked_partial_range ( indices . get ( ) , n_bitmaps ) )
2006-03-20 17:12:09 +00:00
{
2015-05-22 03:33:20 +00:00
grs_bitmap * bm = & GameBitmaps [ i ] ;
2016-06-05 01:04:26 +00:00
gr_set_bitmap_data ( * bm , & Bitmap_replacement_data [ reinterpret_cast < uintptr_t > ( bm - > bm_data ) ] ) ;
2006-03-20 17:12:09 +00:00
}
last_palette_loaded_pig [ 0 ] = 0 ; //force pig re-load
texmerge_flush ( ) ; //for re-merging with new textures
}
}
2020-08-24 01:31:28 +00:00
namespace {
2006-03-20 17:12:09 +00:00
/* calculate table to translate d1 bitmaps to current palette,
* return - 1 on error
*/
2020-07-16 02:31:04 +00:00
static int get_d1_colormap ( palette_array_t & d1_palette , std : : array < color_palette_index , 256 > & colormap )
2006-03-20 17:12:09 +00:00
{
2021-07-25 23:00:56 +00:00
auto palette_file = PHYSFSX_openReadBuffered ( D1_PALETTE ) . first ;
2011-06-01 07:59:55 +00:00
if ( ! palette_file | | PHYSFS_fileLength ( palette_file ) ! = 9472 )
2006-03-20 17:12:09 +00:00
return - 1 ;
2013-01-06 21:11:53 +00:00
PHYSFS_read ( palette_file , & d1_palette [ 0 ] , sizeof ( d1_palette [ 0 ] ) , d1_palette . size ( ) ) ;
2018-03-08 04:21:18 +00:00
build_colormap_good ( d1_palette , colormap ) ;
2006-03-20 17:12:09 +00:00
// don't change transparencies:
2020-07-16 02:31:04 +00:00
colormap [ 254 ] = color_palette_index { 254 } ;
colormap [ 255 ] = TRANSPARENCY_COLOR ;
2006-03-20 17:12:09 +00:00
return 0 ;
}
# define JUST_IN_CASE 132 /* is enough for d1 pc registered */
2013-10-27 22:00:14 +00:00
static void bitmap_read_d1 ( grs_bitmap * bitmap , /* read into this bitmap */
2016-01-09 16:38:14 +00:00
PHYSFS_File * d1_Piggy_fp , /* read from this file */
2006-03-20 17:12:09 +00:00
int bitmap_data_start , /* specific to file */
DiskBitmapHeader * bmh , /* header info for bitmap */
2016-07-14 01:59:02 +00:00
uint8_t * * next_bitmap , /* where to write it (if 0, use malloc) */
2013-01-06 21:03:57 +00:00
palette_array_t & d1_palette , /* what palette the bitmap has */
2020-07-16 02:31:04 +00:00
std : : array < color_palette_index , 256 > & colormap ) /* how to translate bitmap's colors */
2006-03-20 17:12:09 +00:00
{
2011-06-01 07:59:55 +00:00
int zsize , pigsize = PHYSFS_fileLength ( d1_Piggy_fp ) ;
2016-07-14 01:59:02 +00:00
uint8_t * data ;
2006-03-20 17:12:09 +00:00
int width ;
2016-06-05 01:04:26 +00:00
width = bmh - > width + ( static_cast < short > ( bmh - > wh_extra & 0x0f ) < < 8 ) ;
2014-11-30 22:09:20 +00:00
gr_set_bitmap_data ( * bitmap , NULL ) ; // free ogl texture
2016-06-05 01:04:26 +00:00
gr_init_bitmap ( * bitmap , bm_mode : : linear , 0 , 0 , width , bmh - > height + ( static_cast < short > ( bmh - > wh_extra & 0xf0 ) < < 4 ) , width , NULL ) ;
2020-05-22 02:40:26 +00:00
# if !DXX_USE_OGL
2006-03-20 17:12:09 +00:00
bitmap - > avg_color = bmh - > avg_color ;
2020-05-22 02:40:26 +00:00
# endif
2014-11-30 22:09:21 +00:00
gr_set_bitmap_flags ( * bitmap , bmh - > flags & BM_FLAGS_TO_COPY ) ;
2006-03-20 17:12:09 +00:00
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( d1_Piggy_fp , bitmap_data_start + bmh - > offset , SEEK_SET ) ;
2006-03-20 17:12:09 +00:00
if ( bmh - > flags & BM_FLAG_RLE ) {
2011-06-01 07:59:55 +00:00
zsize = PHYSFSX_readInt ( d1_Piggy_fp ) ;
PHYSFSX_fseek ( d1_Piggy_fp , - 4 , SEEK_CUR ) ;
2006-03-20 17:12:09 +00:00
} else
zsize = bitmap - > bm_h * bitmap - > bm_w ;
if ( next_bitmap ) {
data = * next_bitmap ;
* next_bitmap + = zsize ;
} else {
2013-10-24 03:08:58 +00:00
MALLOC ( data , ubyte , zsize + JUST_IN_CASE ) ;
2006-03-20 17:12:09 +00:00
}
if ( ! data ) return ;
2011-06-01 07:59:55 +00:00
PHYSFS_read ( d1_Piggy_fp , data , 1 , zsize ) ;
2014-11-30 22:09:20 +00:00
gr_set_bitmap_data ( * bitmap , data ) ;
2006-03-20 17:12:09 +00:00
switch ( pigsize ) {
case D1_MAC_PIGSIZE :
case D1_MAC_SHARE_PIGSIZE :
if ( bmh - > flags & BM_FLAG_RLE )
2015-01-29 04:27:37 +00:00
rle_swap_0_255 ( * bitmap ) ;
2006-03-20 17:12:09 +00:00
else
2016-11-19 17:24:52 +00:00
swap_0_255 ( * bitmap ) ;
2006-03-20 17:12:09 +00:00
}
if ( bmh - > flags & BM_FLAG_RLE )
2015-01-29 04:27:37 +00:00
rle_remap ( * bitmap , colormap ) ;
2006-03-20 17:12:09 +00:00
else
2015-01-25 05:32:45 +00:00
gr_remap_bitmap_good ( * bitmap , d1_palette , TRANSPARENCY_COLOR , - 1 ) ;
2006-03-20 17:12:09 +00:00
if ( bmh - > flags & BM_FLAG_RLE ) { // size of bitmap could have changed!
int new_size ;
memcpy ( & new_size , bitmap - > bm_data , 4 ) ;
if ( next_bitmap ) {
* next_bitmap + = new_size - zsize ;
} else {
Assert ( zsize + JUST_IN_CASE > = new_size ) ;
2016-07-03 00:54:14 +00:00
bitmap - > bm_mdata = reinterpret_cast < uint8_t * > ( d_realloc ( bitmap - > bm_mdata , new_size ) ) ;
2006-03-20 17:12:09 +00:00
Assert ( bitmap - > bm_data ) ;
}
}
}
# define D1_MAX_TEXTURES 800
2016-01-09 16:38:14 +00:00
static void bm_read_d1_tmap_nums ( PHYSFS_File * d1pig )
2006-03-20 17:12:09 +00:00
{
int i , d1_index ;
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( d1pig , 8 , SEEK_SET ) ;
2020-05-02 21:18:42 +00:00
d1_tmap_nums = std : : make_unique < d1_tmap_nums_t > ( ) ;
2014-07-24 03:03:46 +00:00
d1_tmap_nums - > fill ( - 1 ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < D1_MAX_TEXTURES ; i + + ) {
2011-06-01 07:59:55 +00:00
d1_index = PHYSFSX_readShort ( d1pig ) ;
2006-03-20 17:12:09 +00:00
Assert ( d1_index > = 0 & & d1_index < D1_MAX_TMAP_NUM ) ;
2014-07-24 03:03:46 +00:00
( * d1_tmap_nums ) [ d1_index ] = i ;
2008-11-01 01:19:52 +00:00
if ( PHYSFS_eof ( d1pig ) )
break ;
2006-03-20 17:12:09 +00:00
}
}
// this function is at the same position in the d1 shareware piggy loading
// algorithm as bm_load_sub in main/bmread.c
2016-01-09 16:38:14 +00:00
static int get_d1_bm_index ( char * filename , PHYSFS_File * d1_pig ) {
2006-03-20 17:12:09 +00:00
int i , N_bitmaps ;
DiskBitmapHeader bmh ;
if ( strchr ( filename , ' . ' ) )
* strchr ( filename , ' . ' ) = ' \0 ' ; // remove extension
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( d1_pig , 0 , SEEK_SET ) ;
N_bitmaps = PHYSFSX_readInt ( d1_pig ) ;
PHYSFSX_fseek ( d1_pig , 8 , SEEK_SET ) ;
2006-03-20 17:12:09 +00:00
for ( i = 1 ; i < = N_bitmaps ; i + + ) {
DiskBitmapHeader_d1_read ( & bmh , d1_pig ) ;
2012-05-18 23:36:43 +00:00
if ( ! d_strnicmp ( bmh . name , filename , 8 ) )
2006-03-20 17:12:09 +00:00
return i ;
}
return - 1 ;
}
2008-02-11 12:12:57 +00:00
// imitate the algorithm of gamedata_read_tbl in main/bmread.c
2016-01-09 16:38:14 +00:00
static void read_d1_tmap_nums_from_hog ( PHYSFS_File * d1_pig )
2006-03-20 17:12:09 +00:00
{
# define LINEBUF_SIZE 600
int reading_textures = 0 ;
short texture_count = 0 ;
int bitmaps_tbl_is_binary = 0 ;
int i ;
2021-07-25 23:00:56 +00:00
auto & & [ bitmaps , physfserr ] = PHYSFSX_openReadBuffered ( " bitmaps.tbl " ) ;
2006-03-20 17:12:09 +00:00
if ( ! bitmaps ) {
2021-07-25 23:00:56 +00:00
auto & & [ bitmapbin , physfserr2 ] = PHYSFSX_openReadBuffered ( " bitmaps.bin " ) ;
if ( ! bitmapbin )
{
Warning ( " Failed to open \" bitmaps.tbl \" , \" bitmaps.bin \" : \" %s \" , \" %s \" . Descent 1 textures will not be read. " , PHYSFS_getErrorByCode ( physfserr ) , PHYSFS_getErrorByCode ( physfserr2 ) ) ;
return ;
}
bitmaps = std : : move ( bitmapbin ) ;
2006-03-20 17:12:09 +00:00
bitmaps_tbl_is_binary = 1 ;
}
2020-05-02 21:18:42 +00:00
d1_tmap_nums = std : : make_unique < d1_tmap_nums_t > ( ) ;
2014-07-24 03:03:46 +00:00
d1_tmap_nums - > fill ( - 1 ) ;
2006-03-20 17:12:09 +00:00
2014-09-07 19:48:10 +00:00
for ( PHYSFSX_gets_line_t < LINEBUF_SIZE > inputline ; PHYSFSX_fgets ( inputline , bitmaps ) ; )
{
2006-03-20 17:12:09 +00:00
char * arg ;
if ( bitmaps_tbl_is_binary )
decode_text_line ( ( inputline ) ) ;
else
while ( inputline [ ( i = strlen ( inputline ) ) - 2 ] = = ' \\ ' )
2022-10-02 19:51:35 +00:00
{
if ( PHYSFSX_fgets ( inputline , bitmaps , i - 2 ) ) // strip comments
break ;
}
2006-03-20 17:12:09 +00:00
REMOVE_EOL ( inputline ) ;
if ( strchr ( inputline , ' ; ' ) ! = NULL ) REMOVE_COMMENTS ( inputline ) ;
if ( strlen ( inputline ) = = LINEBUF_SIZE - 1 ) {
Warning ( " Possible line truncation in BITMAPS.TBL " ) ;
return ;
}
2015-01-29 04:27:35 +00:00
arg = strtok ( inputline , space_tab ) ;
2006-03-20 17:12:09 +00:00
if ( arg & & arg [ 0 ] = = ' @ ' ) {
arg + + ;
//Registered_only = 1;
}
while ( arg ! = NULL ) {
if ( * arg = = ' $ ' )
reading_textures = 0 ; // default
if ( ! strcmp ( arg , " $TEXTURES " ) ) // BM_TEXTURES
reading_textures = 1 ;
2012-05-18 23:36:43 +00:00
else if ( ! d_stricmp ( arg , " $ECLIP " ) // BM_ECLIP
| | ! d_stricmp ( arg , " $WCLIP " ) ) // BM_WCLIP
2006-03-20 17:12:09 +00:00
texture_count + + ;
else // not a special token, must be a bitmap!
if ( reading_textures ) {
while ( * arg = = ' \t ' | | * arg = = ' ' )
arg + + ; //remove unwanted blanks
if ( * arg = = ' \0 ' )
break ;
if ( d1_tmap_num_unique ( texture_count ) ) {
int d1_index = get_d1_bm_index ( arg , d1_pig ) ;
if ( d1_index > = 0 & & d1_index < D1_MAX_TMAP_NUM ) {
2014-07-24 03:03:46 +00:00
( * d1_tmap_nums ) [ d1_index ] = texture_count ;
2006-03-20 17:12:09 +00:00
//int d2_index = d2_index_for_d1_index(d1_index);
}
}
Assert ( texture_count < D1_MAX_TEXTURES ) ;
texture_count + + ;
}
arg = strtok ( NULL , equal_space ) ;
}
}
}
/* If the given d1_index is the index of a bitmap we have to load
* ( because it is unique to descent 1 ) , then returns the d2_index that
* the given d1_index replaces .
* Returns - 1 if the given d1_index is not unique to descent 1.
*/
2013-10-27 22:00:14 +00:00
static short d2_index_for_d1_index ( short d1_index )
2006-03-20 17:12:09 +00:00
{
Assert ( d1_index > = 0 & & d1_index < D1_MAX_TMAP_NUM ) ;
2014-07-24 03:03:46 +00:00
if ( ! d1_tmap_nums | | ( * d1_tmap_nums ) [ d1_index ] = = - 1
| | ! d1_tmap_num_unique ( ( * d1_tmap_nums ) [ d1_index ] ) )
2006-03-20 17:12:09 +00:00
return - 1 ;
2014-07-24 03:03:46 +00:00
return Textures [ convert_d1_tmap_num ( ( * d1_tmap_nums ) [ d1_index ] ) ] . index ;
2006-03-20 17:12:09 +00:00
}
2020-08-24 01:31:28 +00:00
}
2006-03-20 17:12:09 +00:00
# define D1_BITMAPS_SIZE 300000
void load_d1_bitmap_replacements ( )
{
DiskBitmapHeader bmh ;
int pig_data_start , bitmap_header_start , bitmap_data_start ;
int N_bitmaps ;
short d1_index , d2_index ;
2016-07-14 01:59:02 +00:00
uint8_t * next_bitmap ;
2013-01-06 21:03:57 +00:00
palette_array_t d1_palette ;
2006-03-20 17:12:09 +00:00
char * p ;
int pigsize ;
2021-07-25 23:00:56 +00:00
auto & & [ d1_Piggy_fp , physfserr ] = PHYSFSX_openReadBuffered ( D1_PIGFILE ) ;
2006-03-20 17:12:09 +00:00
# define D1_PIG_LOAD_FAILED "Failed loading " D1_PIGFILE
if ( ! d1_Piggy_fp ) {
2021-07-25 23:00:56 +00:00
Warning ( " Failed to open " D1_PIGFILE " : %s " , PHYSFS_getErrorByCode ( physfserr ) ) ;
2006-03-20 17:12:09 +00:00
return ;
}
//first, free up data allocated for old bitmaps
free_bitmap_replacements ( ) ;
2020-07-16 02:31:04 +00:00
std : : array < color_palette_index , 256 > colormap ;
2006-03-20 17:12:09 +00:00
if ( get_d1_colormap ( d1_palette , colormap ) ! = 0 )
Warning ( " Could not load descent 1 color palette " ) ;
2011-06-01 07:59:55 +00:00
pigsize = PHYSFS_fileLength ( d1_Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
switch ( pigsize ) {
case D1_SHARE_BIG_PIGSIZE :
case D1_SHARE_10_PIGSIZE :
case D1_SHARE_PIGSIZE :
case D1_10_BIG_PIGSIZE :
case D1_10_PIGSIZE :
pig_data_start = 0 ;
2008-02-11 12:12:57 +00:00
// OK, now we need to read d1_tmap_nums by emulating d1's gamedata_read_tbl()
2006-03-20 17:12:09 +00:00
read_d1_tmap_nums_from_hog ( d1_Piggy_fp ) ;
break ;
default :
Warning ( " Unknown size for " D1_PIGFILE ) ;
Int3 ( ) ;
2022-01-09 15:25:42 +00:00
[[fallthrough]] ;
2006-03-20 17:12:09 +00:00
case D1_PIGSIZE :
case D1_OEM_PIGSIZE :
case D1_MAC_PIGSIZE :
case D1_MAC_SHARE_PIGSIZE :
2011-06-01 07:59:55 +00:00
pig_data_start = PHYSFSX_readInt ( d1_Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
bm_read_d1_tmap_nums ( d1_Piggy_fp ) ; //was: bm_read_all_d1(fp);
2011-06-01 07:59:55 +00:00
//for (i = 0; i < 1800; i++) GameBitmapXlat[i] = PHYSFSX_readShort(d1_Piggy_fp);
2006-03-20 17:12:09 +00:00
break ;
}
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( d1_Piggy_fp , pig_data_start , SEEK_SET ) ;
N_bitmaps = PHYSFSX_readInt ( d1_Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
{
2011-06-01 07:59:55 +00:00
int N_sounds = PHYSFSX_readInt ( d1_Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
+ N_sounds * sizeof ( DiskSoundHeader ) ;
bitmap_header_start = pig_data_start + 2 * sizeof ( int ) ;
bitmap_data_start = bitmap_header_start + header_size ;
}
2020-05-02 21:18:42 +00:00
Bitmap_replacement_data = std : : make_unique < ubyte [ ] > ( D1_BITMAPS_SIZE ) ;
2006-03-20 17:12:09 +00:00
if ( ! Bitmap_replacement_data ) {
Warning ( D1_PIG_LOAD_FAILED ) ;
return ;
}
2014-07-24 02:45:47 +00:00
next_bitmap = Bitmap_replacement_data . get ( ) ;
2006-03-20 17:12:09 +00:00
for ( d1_index = 1 ; d1_index < = N_bitmaps ; d1_index + + ) {
d2_index = d2_index_for_d1_index ( d1_index ) ;
// only change bitmaps which are unique to d1
if ( d2_index ! = - 1 ) {
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( d1_Piggy_fp , bitmap_header_start + ( d1_index - 1 ) * DISKBITMAPHEADER_D1_SIZE , SEEK_SET ) ;
2006-03-20 17:12:09 +00:00
DiskBitmapHeader_d1_read ( & bmh , d1_Piggy_fp ) ;
bitmap_read_d1 ( & GameBitmaps [ d2_index ] , d1_Piggy_fp , bitmap_data_start , & bmh , & next_bitmap , d1_palette , colormap ) ;
2014-07-24 02:45:47 +00:00
Assert ( next_bitmap - Bitmap_replacement_data . get ( ) < D1_BITMAPS_SIZE ) ;
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ d2_index ] = pig_bitmap_offset : : None ; // don't try to read bitmap from current d2 pigfile
2006-03-20 17:12:09 +00:00
GameBitmapFlags [ d2_index ] = bmh . flags ;
2018-08-26 18:10:36 +00:00
auto & abname = AllBitmaps [ d2_index ] . name ;
if ( ( p = strchr ( abname . data ( ) , ' # ' ) ) /* d2 BM is animated */
2006-03-20 17:12:09 +00:00
& & ! ( bmh . dflags & DBM_FLAG_ABM ) ) { /* d1 bitmap is not animated */
2018-08-26 18:10:36 +00:00
int i , len = p - abname . data ( ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < Num_bitmap_files ; i + + )
2018-08-26 18:10:36 +00:00
if ( i ! = d2_index & & ! memcmp ( abname . data ( ) , AllBitmaps [ i ] . name . data ( ) , len ) )
2006-03-20 17:12:09 +00:00
{
2014-11-30 22:09:20 +00:00
gr_set_bitmap_data ( GameBitmaps [ i ] , NULL ) ; // free ogl texture
2006-03-20 17:12:09 +00:00
GameBitmaps [ i ] = GameBitmaps [ d2_index ] ;
2020-08-24 01:31:28 +00:00
GameBitmapOffset [ i ] = pig_bitmap_offset : : None ;
2006-03-20 17:12:09 +00:00
GameBitmapFlags [ i ] = bmh . flags ;
}
}
}
}
last_palette_loaded_pig [ 0 ] = 0 ; //force pig re-load
texmerge_flush ( ) ; //for re-merging with new textures
}
/*
* Find and load the named bitmap from descent . pig
* similar to read_extra_bitmap_iff
*/
2022-09-24 17:47:52 +00:00
grs_bitmap * read_extra_bitmap_d1_pig ( const std : : span < const char > name , grs_bitmap & n )
2006-03-20 17:12:09 +00:00
{
{
int pig_data_start , bitmap_header_start , bitmap_data_start ;
2019-08-06 02:59:41 +00:00
int N_bitmaps ;
2013-01-06 21:03:57 +00:00
palette_array_t d1_palette ;
2006-03-20 17:12:09 +00:00
int pigsize ;
2021-07-25 23:00:56 +00:00
auto & & [ d1_Piggy_fp , physfserr ] = PHYSFSX_openReadBuffered ( D1_PIGFILE ) ;
2006-03-20 17:12:09 +00:00
if ( ! d1_Piggy_fp )
{
2021-07-25 23:00:56 +00:00
Warning ( " Failed to open " D1_PIGFILE " : %s " , PHYSFS_getErrorByCode ( physfserr ) ) ;
2020-08-24 01:31:28 +00:00
return nullptr ;
2006-03-20 17:12:09 +00:00
}
2020-07-16 02:31:04 +00:00
std : : array < color_palette_index , 256 > colormap ;
2006-03-20 17:12:09 +00:00
if ( get_d1_colormap ( d1_palette , colormap ) ! = 0 )
Warning ( " Could not load descent 1 color palette " ) ;
2011-06-01 07:59:55 +00:00
pigsize = PHYSFS_fileLength ( d1_Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
switch ( pigsize ) {
case D1_SHARE_BIG_PIGSIZE :
case D1_SHARE_10_PIGSIZE :
case D1_SHARE_PIGSIZE :
case D1_10_BIG_PIGSIZE :
case D1_10_PIGSIZE :
pig_data_start = 0 ;
break ;
default :
Warning ( " Unknown size for " D1_PIGFILE ) ;
Int3 ( ) ;
2022-01-09 15:25:42 +00:00
[[fallthrough]] ;
2006-03-20 17:12:09 +00:00
case D1_PIGSIZE :
case D1_OEM_PIGSIZE :
case D1_MAC_PIGSIZE :
case D1_MAC_SHARE_PIGSIZE :
2011-06-01 07:59:55 +00:00
pig_data_start = PHYSFSX_readInt ( d1_Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
break ;
}
2011-06-01 07:59:55 +00:00
PHYSFSX_fseek ( d1_Piggy_fp , pig_data_start , SEEK_SET ) ;
N_bitmaps = PHYSFSX_readInt ( d1_Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
{
2011-06-01 07:59:55 +00:00
int N_sounds = PHYSFSX_readInt ( d1_Piggy_fp ) ;
2006-03-20 17:12:09 +00:00
int header_size = N_bitmaps * DISKBITMAPHEADER_D1_SIZE
+ N_sounds * sizeof ( DiskSoundHeader ) ;
bitmap_header_start = pig_data_start + 2 * sizeof ( int ) ;
bitmap_data_start = bitmap_header_start + header_size ;
}
2019-08-06 02:59:41 +00:00
for ( unsigned i = 1 ; ; + + i )
2006-03-20 17:12:09 +00:00
{
2019-08-06 02:59:41 +00:00
if ( i > N_bitmaps )
{
2022-09-24 17:47:52 +00:00
con_printf ( CON_DEBUG , " Failed to find bitmap: %s " , name . data ( ) ) ;
2020-08-24 01:31:28 +00:00
return nullptr ;
2019-08-06 02:59:41 +00:00
}
DiskBitmapHeader bmh ;
2006-03-20 17:12:09 +00:00
DiskBitmapHeader_d1_read ( & bmh , d1_Piggy_fp ) ;
2022-09-24 17:47:52 +00:00
if ( ! d_strnicmp ( bmh . name , name . data ( ) , std : : min < std : : size_t > ( 8u , name . size ( ) ) ) )
2019-08-06 02:59:41 +00:00
{
2020-08-24 01:31:28 +00:00
bitmap_read_d1 ( & n , d1_Piggy_fp , bitmap_data_start , & bmh , 0 , d1_palette , colormap ) ;
2006-03-20 17:12:09 +00:00
break ;
2019-08-06 02:59:41 +00:00
}
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(n);
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
}
2020-08-24 01:31:28 +00:00
2020-08-24 01:31:28 +00:00
}
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2020-08-24 01:31:28 +00:00
namespace dcx {
2006-03-20 17:12:09 +00:00
/*
2016-01-09 16:38:14 +00:00
* reads a bitmap_index structure from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2016-01-09 16:38:14 +00:00
void bitmap_index_read ( PHYSFS_File * fp , bitmap_index & bi )
2006-03-20 17:12:09 +00:00
{
2015-02-14 22:48:30 +00:00
bi . index = PHYSFSX_readShort ( fp ) ;
2006-03-20 17:12:09 +00:00
}
/*
2016-01-09 16:38:14 +00:00
* reads n bitmap_index structs from a PHYSFS_File
2006-03-20 17:12:09 +00:00
*/
2016-01-09 16:38:14 +00:00
void bitmap_index_read_n ( PHYSFS_File * fp , const partial_range_t < bitmap_index * > r )
2006-03-20 17:12:09 +00:00
{
2015-02-14 22:48:30 +00:00
range_for ( auto & i , r )
i . index = PHYSFSX_readShort ( fp ) ;
2006-03-20 17:12:09 +00:00
}
2020-08-24 01:31:28 +00:00
}