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 to dump text description of mine .
* An editor - only function , called at mine load time .
* To be read by a human to verify the correctness and completeness of a mine .
*
*/
2014-10-02 03:02:34 +00:00
# include <bitset>
2006-03-20 17:12:09 +00:00
# include <stdio.h>
# include <string.h>
# include <stdarg.h>
# include <errno.h>
# include "pstypes.h"
2008-04-06 20:23:28 +00:00
# include "console.h"
2014-07-20 01:09:55 +00:00
# include "physfsx.h"
2006-03-20 17:12:09 +00:00
# include "key.h"
# include "gr.h"
# include "palette.h"
2013-12-08 23:37:40 +00:00
# include "fmtcheck.h"
2006-03-20 17:12:09 +00:00
# include "inferno.h"
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2006-03-20 17:12:09 +00:00
# include "editor/editor.h"
# endif
2012-07-07 18:35:06 +00:00
# include "dxxerror.h"
2006-03-20 17:12:09 +00:00
# include "object.h"
# include "wall.h"
# include "gamemine.h"
2013-12-26 04:18:28 +00:00
# include "gameseg.h"
2006-03-20 17:12:09 +00:00
# include "robot.h"
# include "player.h"
# include "newmenu.h"
# include "textures.h"
# include "bm.h"
# include "menu.h"
# include "switch.h"
# include "fuelcen.h"
# include "powerup.h"
# include "gameseq.h"
# include "polyobj.h"
# include "gamesave.h"
2012-11-11 00:14:30 +00:00
# include "piggy.h"
2006-03-20 17:12:09 +00:00
2014-07-30 02:52:33 +00:00
# include "compiler-range_for.h"
2014-12-14 21:02:40 +00:00
# include "partial_range.h"
2014-07-30 02:52:33 +00:00
# include "segiter.h"
2016-09-11 18:49:16 +00:00
# if DXX_USE_EDITOR
2016-05-22 17:49:30 +00:00
namespace dsx {
namespace {
# if defined(DXX_BUILD_DESCENT_I)
using perm_tmap_buffer_type = array < int , MAX_TEXTURES > ;
using level_tmap_buffer_type = array < int8_t , MAX_TEXTURES > ;
using wall_buffer_type = array < int , MAX_WALL_ANIMS > ;
# elif defined(DXX_BUILD_DESCENT_II)
using perm_tmap_buffer_type = array < int , MAX_BITMAP_FILES > ;
using level_tmap_buffer_type = array < int8_t , MAX_BITMAP_FILES > ;
using wall_buffer_type = array < int , MAX_BITMAP_FILES > ;
# endif
}
}
namespace dcx {
2015-04-02 02:36:56 +00:00
const array < char [ 10 ] , 7 > Wall_names { {
" NORMAL " ,
" BLASTABLE " ,
" DOOR " ,
" ILLUSION " ,
" OPEN " ,
" CLOSED " ,
" EXTERNAL "
} } ;
2016-05-22 17:49:30 +00:00
}
2015-04-02 02:36:56 +00:00
2016-01-09 16:38:14 +00:00
static void dump_used_textures_level ( PHYSFS_File * my_file , int level_num ) ;
static void say_totals ( PHYSFS_File * my_file , const char * level_name ) ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
namespace dsx {
2015-03-22 18:49:21 +00:00
const array < char [ 9 ] , MAX_OBJECT_TYPES > Object_type_names { {
" WALL " ,
" FIREBALL " ,
" ROBOT " ,
" HOSTAGE " ,
" PLAYER " ,
" WEAPON " ,
" CAMERA " ,
" POWERUP " ,
" DEBRIS " ,
" CNTRLCEN " ,
" FLARE " ,
" CLUTTER " ,
" GHOST " ,
" LIGHT " ,
" COOP " ,
# if defined(DXX_BUILD_DESCENT_II)
" MARKER " ,
# endif
} } ;
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-05-22 17:49:30 +00:00
static const char * object_types ( const object_base & objp )
2006-03-20 17:12:09 +00:00
{
2016-05-22 17:49:30 +00:00
const auto type = objp . type ;
2015-05-28 03:08:39 +00:00
assert ( type = = OBJ_NONE | | type < MAX_OBJECT_TYPES ) ;
2014-11-23 04:36:58 +00:00
return & Object_type_names [ type ] [ 0 ] ;
2006-03-20 17:12:09 +00:00
}
2016-05-22 17:49:30 +00:00
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-28 22:41:48 +00:00
static const char * object_ids ( const object_base & objp )
2006-03-20 17:12:09 +00:00
{
2016-08-28 22:41:48 +00:00
switch ( objp . type )
2015-05-28 03:08:39 +00:00
{
2006-03-20 17:12:09 +00:00
case OBJ_ROBOT :
2016-07-09 17:58:34 +00:00
return Robot_names [ get_robot_id ( objp ) ] . data ( ) ;
2006-03-20 17:12:09 +00:00
case OBJ_POWERUP :
2016-07-09 17:58:34 +00:00
return Powerup_names [ get_powerup_id ( objp ) ] . data ( ) ;
2006-03-20 17:12:09 +00:00
}
return NULL ;
}
2016-01-09 16:38:14 +00:00
static void err_puts ( PHYSFS_File * f , const char * str , size_t len ) __attribute_nonnull ( ) ;
static void err_puts ( PHYSFS_File * f , const char * str , size_t len )
2013-12-19 22:55:34 +00:00
# define err_puts(A1,S,...) (err_puts(A1,S, _dxx_call_puts_parameter2(1, ## __VA_ARGS__, strlen(S))))
2013-12-08 23:37:40 +00:00
{
2013-12-19 22:55:34 +00:00
con_puts ( CON_CRITICAL , str , len ) ;
PHYSFSX_puts ( f , str ) ;
2013-12-08 23:37:40 +00:00
Errors_in_mine + + ;
}
2013-12-19 22:55:34 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static void err_puts_literal ( PHYSFS_File * f , const char ( & str ) [ len ] ) __attribute_nonnull ( ) ;
2013-12-19 22:55:34 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static void err_puts_literal ( PHYSFS_File * f , const char ( & str ) [ len ] )
2013-12-19 22:55:34 +00:00
{
err_puts ( f , str , len ) ;
}
2016-01-09 16:38:14 +00:00
static void err_printf ( PHYSFS_File * my_file , const char * format , . . . ) __attribute_format_printf ( 2 , 3 ) ;
static void err_printf ( PHYSFS_File * my_file , const char * format , . . . )
2013-12-19 22:55:34 +00:00
# define err_printf(A1,F,...) dxx_call_printf_checked(err_printf,err_puts_literal,(A1),(F),##__VA_ARGS__)
2006-03-20 17:12:09 +00:00
{
va_list args ;
char message [ 256 ] ;
va_start ( args , format ) ;
2013-12-19 22:55:34 +00:00
size_t len = vsnprintf ( message , sizeof ( message ) , format , args ) ;
2006-03-20 17:12:09 +00:00
va_end ( args ) ;
2013-12-19 22:55:34 +00:00
err_puts ( my_file , message , len ) ;
2006-03-20 17:12:09 +00:00
}
2016-01-09 16:38:14 +00:00
static void warning_puts ( PHYSFS_File * f , const char * str , size_t len ) __attribute_nonnull ( ) ;
static void warning_puts ( PHYSFS_File * f , const char * str , size_t len )
2013-12-19 22:55:34 +00:00
# define warning_puts(A1,S,...) (warning_puts(A1,S, _dxx_call_puts_parameter2(1, ## __VA_ARGS__, strlen(S))))
2013-12-08 23:37:40 +00:00
{
2013-12-19 22:55:34 +00:00
con_puts ( CON_URGENT , str , len ) ;
2013-12-08 23:37:40 +00:00
PHYSFSX_puts ( f , str ) ;
}
2013-12-19 22:55:34 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static void warning_puts_literal ( PHYSFS_File * f , const char ( & str ) [ len ] ) __attribute_nonnull ( ) ;
2013-12-19 22:55:34 +00:00
template < size_t len >
2016-01-09 16:38:14 +00:00
static void warning_puts_literal ( PHYSFS_File * f , const char ( & str ) [ len ] )
2013-12-19 22:55:34 +00:00
{
warning_puts ( f , str , len ) ;
}
2016-01-09 16:38:14 +00:00
static void warning_printf ( PHYSFS_File * my_file , const char * format , . . . ) __attribute_format_printf ( 2 , 3 ) ;
static void warning_printf ( PHYSFS_File * my_file , const char * format , . . . )
2013-12-19 22:55:34 +00:00
# define warning_printf(A1,F,...) dxx_call_printf_checked(warning_printf,warning_puts_literal,(A1),(F),##__VA_ARGS__)
2006-03-20 17:12:09 +00:00
{
va_list args ;
char message [ 256 ] ;
va_start ( args , format ) ;
2012-06-30 05:05:33 +00:00
vsnprintf ( message , sizeof ( message ) , format , args ) ;
2006-03-20 17:12:09 +00:00
va_end ( args ) ;
2013-12-08 23:37:40 +00:00
warning_puts ( my_file , message ) ;
2006-03-20 17:12:09 +00:00
}
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:14 +00:00
static void write_exit_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2016-02-06 22:12:54 +00:00
int j , count ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Exit stuff \n " ) ;
2006-03-20 17:12:09 +00:00
// ---------- Find exit triggers ----------
count = 0 ;
2016-02-06 22:12:54 +00:00
for ( trgnum_t i = 0 ; i < Num_triggers ; i + + )
{
const auto & & t = vctrgptr ( i ) ;
if ( trigger_is_exit ( t ) )
{
2006-03-20 17:12:09 +00:00
int count2 ;
2016-02-06 22:12:54 +00:00
PHYSFSX_printf ( my_file , " Trigger %2i, is an exit trigger with %i links. \n " , i , t - > num_links ) ;
2006-03-20 17:12:09 +00:00
count + + ;
2016-02-06 22:12:54 +00:00
if ( t - > num_links ! = 0 )
err_printf ( my_file , " Error: Exit triggers must have 0 links, this one has %i links. " , t - > num_links ) ;
2006-03-20 17:12:09 +00:00
// Find wall pointing to this trigger.
count2 = 0 ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & w , vcwallptridx )
{
if ( w - > trigger = = i )
{
2006-03-20 17:12:09 +00:00
count2 + + ;
2016-02-12 04:02:28 +00:00
PHYSFSX_printf ( my_file , " Exit trigger %i is in segment %i, on side %i, bound to wall %i \n " , i , w - > segnum , w - > sidenum , static_cast < wallnum_t > ( w ) ) ;
2006-03-20 17:12:09 +00:00
}
2016-02-12 04:02:28 +00:00
}
2006-03-20 17:12:09 +00:00
if ( count2 = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Trigger %i is not bound to any wall. " , i ) ;
2006-03-20 17:12:09 +00:00
else if ( count2 > 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Trigger %i is bound to %i walls. " , i , count2 ) ;
2006-03-20 17:12:09 +00:00
}
2016-02-06 22:12:54 +00:00
}
2006-03-20 17:12:09 +00:00
if ( count = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: No exit trigger in this mine. " ) ;
2006-03-20 17:12:09 +00:00
else if ( count ! = 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: More than one exit trigger in this mine. " ) ;
2006-03-20 17:12:09 +00:00
else
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
// ---------- Find exit doors ----------
count = 0 ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2015-06-13 22:42:16 +00:00
{
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < MAX_SIDES_PER_SEGMENT ; j + + )
2015-06-13 22:42:16 +00:00
if ( segp - > children [ j ] = = segment_exit )
2015-05-28 03:08:39 +00:00
{
2015-12-22 04:18:51 +00:00
PHYSFSX_printf ( my_file , " Segment %3hu, side %i is an exit door. \n " , static_cast < uint16_t > ( segp ) , j ) ;
2006-03-20 17:12:09 +00:00
count + + ;
}
2015-06-13 22:42:16 +00:00
}
2006-03-20 17:12:09 +00:00
if ( count = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: No external wall in this mine. " ) ;
2006-03-20 17:12:09 +00:00
else if ( count ! = 1 ) {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2013-12-19 22:49:25 +00:00
warning_printf ( my_file , " Warning: %i external walls in this mine. " , count ) ;
warning_printf ( my_file , " (If %i are secret exits, then no problem.) " , count - 1 ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
} else
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
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
static void write_key_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
int i ;
int red_count , blue_count , gold_count ;
int red_count2 , blue_count2 , gold_count2 ;
2013-12-29 04:28:07 +00:00
int blue_sidenum = - 1 , red_sidenum = - 1 , gold_sidenum = - 1 ;
segnum_t blue_segnum = segment_none , red_segnum = segment_none , gold_segnum = segment_none ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Key stuff: \n " ) ;
2006-03-20 17:12:09 +00:00
red_count = 0 ;
blue_count = 0 ;
gold_count = 0 ;
for ( i = 0 ; i < Num_walls ; i + + ) {
if ( Walls [ i ] . keys & KEY_BLUE ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Wall %i (seg=%i, side=%i) is keyed to the blue key. \n " , i , Walls [ i ] . segnum , Walls [ i ] . sidenum ) ;
2013-12-26 22:21:16 +00:00
if ( blue_segnum = = segment_none ) {
2006-03-20 17:12:09 +00:00
blue_segnum = Walls [ i ] . segnum ;
blue_sidenum = Walls [ i ] . sidenum ;
blue_count + + ;
} else {
2015-07-12 01:04:19 +00:00
const auto & & connect_side = find_connect_side ( vcsegptridx ( Walls [ i ] . segnum ) , vcsegptr ( blue_segnum ) ) ;
2006-03-20 17:12:09 +00:00
if ( connect_side ! = blue_sidenum ) {
2013-12-19 22:49:25 +00:00
warning_printf ( my_file , " Warning: This blue door at seg %i, is different than the one at seg %i, side %i " , Walls [ i ] . segnum , blue_segnum , blue_sidenum ) ;
2006-03-20 17:12:09 +00:00
blue_count + + ;
}
}
}
if ( Walls [ i ] . keys & KEY_RED ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Wall %i (seg=%i, side=%i) is keyed to the red key. \n " , i , Walls [ i ] . segnum , Walls [ i ] . sidenum ) ;
2013-12-26 22:21:16 +00:00
if ( red_segnum = = segment_none ) {
2006-03-20 17:12:09 +00:00
red_segnum = Walls [ i ] . segnum ;
red_sidenum = Walls [ i ] . sidenum ;
red_count + + ;
} else {
2015-07-12 01:04:19 +00:00
const auto & & connect_side = find_connect_side ( vcsegptridx ( Walls [ i ] . segnum ) , vcsegptr ( red_segnum ) ) ;
2006-03-20 17:12:09 +00:00
if ( connect_side ! = red_sidenum ) {
2013-12-19 22:49:25 +00:00
warning_printf ( my_file , " Warning: This red door at seg %i, is different than the one at seg %i, side %i " , Walls [ i ] . segnum , red_segnum , red_sidenum ) ;
2006-03-20 17:12:09 +00:00
red_count + + ;
}
}
}
if ( Walls [ i ] . keys & KEY_GOLD ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Wall %i (seg=%i, side=%i) is keyed to the gold key. \n " , i , Walls [ i ] . segnum , Walls [ i ] . sidenum ) ;
2013-12-26 22:21:16 +00:00
if ( gold_segnum = = segment_none ) {
2006-03-20 17:12:09 +00:00
gold_segnum = Walls [ i ] . segnum ;
gold_sidenum = Walls [ i ] . sidenum ;
gold_count + + ;
} else {
2015-07-12 01:04:19 +00:00
const auto & & connect_side = find_connect_side ( vcsegptridx ( Walls [ i ] . segnum ) , vcsegptr ( gold_segnum ) ) ;
2006-03-20 17:12:09 +00:00
if ( connect_side ! = gold_sidenum ) {
2013-12-19 22:49:25 +00:00
warning_printf ( my_file , " Warning: This gold door at seg %i, is different than the one at seg %i, side %i " , Walls [ i ] . segnum , gold_segnum , gold_sidenum ) ;
2006-03-20 17:12:09 +00:00
gold_count + + ;
}
}
}
}
if ( blue_count > 1 )
2013-12-19 22:49:25 +00:00
warning_printf ( my_file , " Warning: %i doors are keyed to the blue key. " , blue_count ) ;
2006-03-20 17:12:09 +00:00
if ( red_count > 1 )
2013-12-19 22:49:25 +00:00
warning_printf ( my_file , " Warning: %i doors are keyed to the red key. " , red_count ) ;
2006-03-20 17:12:09 +00:00
if ( gold_count > 1 )
2013-12-19 22:49:25 +00:00
warning_printf ( my_file , " Warning: %i doors are keyed to the gold key. " , gold_count ) ;
2006-03-20 17:12:09 +00:00
red_count2 = 0 ;
blue_count2 = 0 ;
gold_count2 = 0 ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2015-06-13 22:42:16 +00:00
if ( objp - > type = = OBJ_POWERUP )
2016-09-04 19:10:42 +00:00
{
const char * color ;
const auto id = get_powerup_id ( objp ) ;
if (
( id = = POW_KEY_BLUE & & ( + + blue_count2 , color = " BLUE " , true ) ) | |
( id = = POW_KEY_RED & & ( + + red_count2 , color = " RED " , true ) ) | |
( id = = POW_KEY_GOLD & & ( + + gold_count2 , color = " GOLD " , true ) )
)
{
PHYSFSX_printf ( my_file , " The %s key is object %hu in segment %i \n " , color , static_cast < objnum_t > ( objp ) , objp - > segnum ) ;
2006-03-20 17:12:09 +00:00
}
2016-09-04 19:10:42 +00:00
}
2006-03-20 17:12:09 +00:00
2016-09-04 19:10:42 +00:00
if ( const auto contains_count = objp - > contains_count )
2015-06-13 22:42:16 +00:00
{
if ( objp - > contains_type = = OBJ_POWERUP )
{
2016-09-04 19:10:42 +00:00
const char * color ;
const auto id = objp - > contains_id ;
if (
( id = = POW_KEY_BLUE & & ( blue_count2 + = contains_count , color = " BLUE " , true ) ) | |
( id = = POW_KEY_RED & & ( red_count2 + = contains_count , color = " RED " , true ) ) | |
( id = = POW_KEY_GOLD & & ( gold_count2 + = contains_count , color = " GOLD " , true ) )
)
PHYSFSX_printf ( my_file , " The %s key is contained in object %hu (a %s %s) in segment %hu \n " , color , static_cast < objnum_t > ( objp ) , object_types ( objp ) , Robot_names [ get_robot_id ( objp ) ] . data ( ) , objp - > segnum ) ;
2006-03-20 17:12:09 +00:00
}
}
}
if ( blue_count )
if ( blue_count2 = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: There is a door keyed to the blue key, but no blue key! " ) ;
2006-03-20 17:12:09 +00:00
if ( red_count )
if ( red_count2 = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: There is a door keyed to the red key, but no red key! " ) ;
2006-03-20 17:12:09 +00:00
if ( gold_count )
if ( gold_count2 = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: There is a door keyed to the gold key, but no gold key! " ) ;
2006-03-20 17:12:09 +00:00
if ( blue_count2 > 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: There are %i blue keys! " , blue_count2 ) ;
2006-03-20 17:12:09 +00:00
if ( red_count2 > 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: There are %i red keys! " , red_count2 ) ;
2006-03-20 17:12:09 +00:00
if ( gold_count2 > 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: There are %i gold keys! " , gold_count2 ) ;
2006-03-20 17:12:09 +00:00
}
// ----------------------------------------------------------------------------
2016-01-09 16:38:14 +00:00
static void write_control_center_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2014-10-12 23:10:05 +00:00
int count , count2 ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Control Center stuff: \n " ) ;
2006-03-20 17:12:09 +00:00
count = 0 ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2015-06-13 22:42:16 +00:00
{
if ( segp - > special = = SEGMENT_IS_CONTROLCEN )
{
2006-03-20 17:12:09 +00:00
count + + ;
2015-12-22 04:18:51 +00:00
PHYSFSX_printf ( my_file , " Segment %3hu is a control center. \n " , static_cast < uint16_t > ( segp ) ) ;
2006-03-20 17:12:09 +00:00
count2 = 0 ;
2015-06-13 22:42:16 +00:00
range_for ( const auto objp , objects_in ( segp ) )
2014-07-30 02:52:33 +00:00
{
if ( objp - > type = = OBJ_CNTRLCEN )
2006-03-20 17:12:09 +00:00
count2 + + ;
}
if ( count2 = = 0 )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " No control center object in control center segment. \n " ) ;
2006-03-20 17:12:09 +00:00
else if ( count2 ! = 1 )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " %i control center objects in control center segment. \n " , count2 ) ;
2006-03-20 17:12:09 +00:00
}
2015-06-13 22:42:16 +00:00
}
2006-03-20 17:12:09 +00:00
if ( count = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: No control center in this mine. " ) ;
2006-03-20 17:12:09 +00:00
else if ( count ! = 1 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: More than one control center in this mine. " ) ;
2006-03-20 17:12:09 +00:00
}
// ----------------------------------------------------------------------------
2016-01-09 16:38:14 +00:00
static void write_fuelcen_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
int i ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Fuel Center stuff: (Note: This means fuel, repair, materialize, control centers!) \n " ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < Num_fuelcenters ; i + + ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Fuelcenter %i: Type=%i (%s), segment = %3i \n " , i , Station [ i ] . Type , Special_names [ Station [ i ] . Type ] , Station [ i ] . segnum ) ;
2013-10-06 16:20:00 +00:00
if ( Segments [ Station [ i ] . segnum ] . special ! = Station [ i ] . Type )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Conflicting data: Segment %i has special type %i (%s), expected to be %i " , Station [ i ] . segnum , Segments [ Station [ i ] . segnum ] . special , Special_names [ Segments [ Station [ i ] . segnum ] . special ] , Station [ i ] . Type ) ;
2006-03-20 17:12:09 +00:00
}
}
// ----------------------------------------------------------------------------
2016-01-09 16:38:14 +00:00
static void write_segment_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Segment stuff: \n " ) ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2014-10-12 23:10:05 +00:00
{
2015-12-22 04:18:51 +00:00
PHYSFSX_printf ( my_file , " Segment %4hu: " , static_cast < uint16_t > ( segp ) ) ;
2015-06-13 22:42:16 +00:00
if ( segp - > special ! = 0 )
PHYSFSX_printf ( my_file , " special = %3i (%s), value = %3i " , segp - > special , Special_names [ segp - > special ] , segp - > value ) ;
if ( segp - > matcen_num ! = - 1 )
PHYSFSX_printf ( my_file , " matcen = %3i, " , segp - > matcen_num ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
}
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptridx )
2014-10-12 23:10:05 +00:00
{
2006-03-20 17:12:09 +00:00
int depth ;
2015-12-22 04:18:51 +00:00
PHYSFSX_printf ( my_file , " Segment %4hu: " , static_cast < uint16_t > ( segp ) ) ;
2006-03-20 17:12:09 +00:00
depth = 0 ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Objects: " ) ;
2015-06-13 22:42:16 +00:00
range_for ( const auto objp , objects_in ( segp ) )
2014-07-30 02:52:33 +00:00
{
short objnum = objp ;
2015-05-28 03:08:39 +00:00
PHYSFSX_printf ( my_file , " [%8s %8s %3i] " , object_types ( objp ) , object_ids ( objp ) , objnum ) ;
2006-03-20 17:12:09 +00:00
if ( depth + + > 30 ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Aborted after %i links \n " , depth ) ;
2006-03-20 17:12:09 +00:00
break ;
}
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
}
}
// ----------------------------------------------------------------------------
// This routine is bogus. It assumes that all centers are matcens,
// which is not true. The setting of segnum is bogus.
2016-01-09 16:38:14 +00:00
static void write_matcen_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2016-02-06 22:12:54 +00:00
int i ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Materialization centers: \n " ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < Num_robot_centers ; i + + ) {
2013-12-29 04:28:07 +00:00
int trigger_count = 0 , fuelcen_num ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " FuelCenter[%02i].Segment = %04i " , i , Station [ i ] . segnum ) ;
2013-10-06 16:20:00 +00:00
PHYSFSX_printf ( my_file , " Segment[%04i].matcen_num = %02i " , Station [ i ] . segnum , Segments [ Station [ i ] . segnum ] . matcen_num ) ;
2006-03-20 17:12:09 +00:00
fuelcen_num = RobotCenters [ i ] . fuelcen_num ;
if ( Station [ fuelcen_num ] . Type ! = SEGMENT_IS_ROBOTMAKER )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Matcen %i corresponds to Station %i, which has type %i (%s). " , i , fuelcen_num , Station [ fuelcen_num ] . Type , Special_names [ Station [ fuelcen_num ] . Type ] ) ;
2006-03-20 17:12:09 +00:00
2014-11-20 03:00:36 +00:00
auto segnum = Station [ fuelcen_num ] . segnum ;
2006-03-20 17:12:09 +00:00
// Find trigger for this materialization center.
2016-02-06 22:12:54 +00:00
for ( trgnum_t j = 0 ; j < Num_triggers ; j + + )
{
const auto & & t = vctrgptr ( j ) ;
if ( trigger_is_matcen ( t ) )
2014-12-14 21:02:40 +00:00
{
2016-02-12 04:02:28 +00:00
range_for ( auto & k , partial_const_range ( t - > seg , t - > num_links ) )
2014-12-14 21:02:40 +00:00
if ( k = = segnum )
{
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Trigger = %2i " , j ) ;
2006-03-20 17:12:09 +00:00
trigger_count + + ;
}
}
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
if ( trigger_count = = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Matcen %i in segment %i has no trigger! " , i , segnum ) ;
2006-03-20 17:12:09 +00:00
}
}
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:14 +00:00
static void write_wall_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
int i , j ;
2016-05-22 17:49:30 +00:00
array < int8_t , MAX_WALLS > wall_flags ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Walls: \n " ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < Num_walls ; i + + ) {
2013-12-29 04:28:07 +00:00
int sidenum ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Wall %03i: seg=%3i, side=%2i, linked_wall=%3i, type=%s, flags=%4x, hps=%3i, trigger=%2i, clip_num=%2i, keys=%2i, state=%i \n " , i ,
2006-03-20 17:12:09 +00:00
Walls [ i ] . segnum , Walls [ i ] . sidenum , Walls [ i ] . linked_wall , Wall_names [ Walls [ i ] . type ] , Walls [ i ] . flags , Walls [ i ] . hps > > 16 , Walls [ i ] . trigger , Walls [ i ] . clip_num , Walls [ i ] . keys , Walls [ i ] . state ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
if ( Walls [ i ] . trigger > = Num_triggers )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Wall %03d points to invalid trigger %d \n " , i , Walls [ i ] . trigger ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2014-11-20 03:00:36 +00:00
auto segnum = Walls [ i ] . segnum ;
2006-03-20 17:12:09 +00:00
sidenum = Walls [ i ] . sidenum ;
if ( Segments [ segnum ] . sides [ sidenum ] . wall_num ! = i )
2014-10-04 17:30:18 +00:00
err_printf ( my_file , " Error: Wall %i points at segment %i, side %i, but that segment doesn't point back (it's wall_num = %hi) " , i , segnum , sidenum , static_cast < int16_t > ( Segments [ segnum ] . sides [ sidenum ] . wall_num ) ) ;
2006-03-20 17:12:09 +00:00
}
2016-05-22 17:49:30 +00:00
wall_flags = { } ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptr )
2014-10-12 23:10:05 +00:00
{
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < MAX_SIDES_PER_SEGMENT ; j + + ) {
2015-06-13 22:42:16 +00:00
const auto sidep = & segp - > sides [ j ] ;
2014-10-04 15:04:44 +00:00
if ( sidep - > wall_num ! = wall_none )
2006-03-20 17:12:09 +00:00
{
if ( wall_flags [ sidep - > wall_num ] )
2014-10-12 23:10:05 +00:00
err_printf ( my_file , " Error: Wall %hu appears in two or more segments, including segment %hu, side %i. " , static_cast < int16_t > ( sidep - > wall_num ) , static_cast < int16_t > ( i ) , j ) ;
2006-03-20 17:12:09 +00:00
else
wall_flags [ sidep - > wall_num ] = 1 ;
}
}
}
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:14 +00:00
static void write_player_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2014-10-12 23:05:46 +00:00
int num_players = 0 ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Players: \n " ) ;
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2015-06-13 22:42:16 +00:00
if ( objp - > type = = OBJ_PLAYER )
{
2006-03-20 17:12:09 +00:00
num_players + + ;
2015-12-22 04:18:51 +00:00
PHYSFSX_printf ( my_file , " Player %2i is object #%3hu in segment #%3i. \n " , get_player_id ( objp ) , static_cast < uint16_t > ( objp ) , objp - > segnum ) ;
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
if ( num_players ! = MAX_PLAYERS )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: %i player objects. %i are required. " , num_players , MAX_PLAYERS ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
if ( num_players > MAX_MULTI_PLAYERS )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: %i player objects. %i are required. " , num_players , MAX_PLAYERS ) ;
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-08-25 04:05:32 +00:00
namespace dsx {
2016-01-09 16:38:14 +00:00
static void write_trigger_text ( PHYSFS_File * my_file )
2006-03-20 17:12:09 +00:00
{
2016-02-06 22:12:54 +00:00
int w ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Triggers: \n " ) ;
2016-02-06 22:12:54 +00:00
for ( trgnum_t i = 0 ; i < Num_triggers ; i + + )
{
const auto & & t = vctrgptr ( i ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-02-08 23:25:29 +00:00
PHYSFSX_printf ( my_file , " Trigger %03i: flags=%04x, value=%08x, time=%8x, linknum=%i, num_links=%i " , i ,
2016-02-06 22:12:55 +00:00
t - > flags , static_cast < unsigned > ( t - > value ) , 0 , t - > link_num , t - > num_links ) ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Trigger %03i: type=%02x flags=%04x, value=%08x, time=%8x, num_links=%i " , i ,
2016-02-06 22:12:55 +00:00
t - > type , t - > flags , t - > value , 0 , t - > num_links ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2016-02-06 22:12:54 +00:00
for ( unsigned j = 0 ; j < t - > num_links ; + + j )
PHYSFSX_printf ( my_file , " [%03i:%i] " , t - > seg [ j ] , t - > side [ j ] ) ;
2006-03-20 17:12:09 +00:00
// Find which wall this trigger is connected to.
for ( w = 0 ; w < Num_walls ; w + + )
if ( Walls [ w ] . trigger = = i )
break ;
if ( w = = Num_walls )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Trigger %i is not connected to any wall, so it can never be triggered. " , i ) ;
2006-03-20 17:12:09 +00:00
else
2014-10-04 17:30:18 +00:00
PHYSFSX_printf ( my_file , " Attached to seg:side = %i:%i, wall %hi \n " , Walls [ w ] . segnum , Walls [ w ] . sidenum , static_cast < int16_t > ( Segments [ Walls [ w ] . segnum ] . sides [ Walls [ w ] . sidenum ] . wall_num ) ) ;
2006-03-20 17:12:09 +00:00
}
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2013-06-08 22:24:17 +00:00
void write_game_text_file ( const char * filename )
2006-03-20 17:12:09 +00:00
{
char my_filename [ 128 ] ;
int namelen ;
Errors_in_mine = 0 ;
namelen = strlen ( filename ) ;
Assert ( namelen > 4 ) ;
Assert ( filename [ namelen - 4 ] = = ' . ' ) ;
strcpy ( my_filename , filename ) ;
strcpy ( & my_filename [ namelen - 4 ] , " .txm " ) ;
2015-01-17 18:31:42 +00:00
auto my_file = PHYSFSX_openWriteBuffered ( my_filename ) ;
2006-03-20 17:12:09 +00:00
if ( ! my_file ) {
gr_palette_load ( gr_palette ) ;
2013-12-04 22:19:04 +00:00
nm_messagebox ( NULL , 1 , " Ok " , " ERROR: Unable to open %s \n Errno = %i " , my_filename , errno ) ;
2006-03-20 17:12:09 +00:00
return ;
}
dump_used_textures_level ( my_file , 0 ) ;
say_totals ( my_file , Gamesave_current_filename ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Number of segments: %4i \n " , Highest_segment_index + 1 ) ;
PHYSFSX_printf ( my_file , " Number of objects: %4i \n " , Highest_object_index + 1 ) ;
PHYSFSX_printf ( my_file , " Number of walls: %4i \n " , Num_walls ) ;
PHYSFSX_printf ( my_file , " Number of open doors: %4i \n " , Num_open_doors ) ;
PHYSFSX_printf ( my_file , " Number of triggers: %4i \n " , Num_triggers ) ;
PHYSFSX_printf ( my_file , " Number of matcens: %4i \n " , Num_robot_centers ) ;
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
write_segment_text ( my_file ) ;
write_fuelcen_text ( my_file ) ;
write_matcen_text ( my_file ) ;
write_player_text ( my_file ) ;
write_wall_text ( my_file ) ;
write_trigger_text ( my_file ) ;
write_exit_text ( my_file ) ;
// ---------- Find control center segment ----------
write_control_center_text ( my_file ) ;
// ---------- Show keyed walls ----------
write_key_text ( my_file ) ;
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
// Adam: Change NUM_ADAM_LEVELS to the number of levels.
# define NUM_ADAM_LEVELS 30
// Adam: Stick the names here.
2016-07-16 16:52:04 +00:00
constexpr char Adam_level_names [ NUM_ADAM_LEVELS ] [ 13 ] = {
2006-03-20 17:12:09 +00:00
" D2LEVA-1.LVL " ,
" D2LEVA-2.LVL " ,
" D2LEVA-3.LVL " ,
" D2LEVA-4.LVL " ,
" D2LEVA-S.LVL " ,
" D2LEVB-1.LVL " ,
" D2LEVB-2.LVL " ,
" D2LEVB-3.LVL " ,
" D2LEVB-4.LVL " ,
" D2LEVB-S.LVL " ,
" D2LEVC-1.LVL " ,
" D2LEVC-2.LVL " ,
" D2LEVC-3.LVL " ,
" D2LEVC-4.LVL " ,
" D2LEVC-S.LVL " ,
" D2LEVD-1.LVL " ,
" D2LEVD-2.LVL " ,
" D2LEVD-3.LVL " ,
" D2LEVD-4.LVL " ,
" D2LEVD-S.LVL " ,
" D2LEVE-1.LVL " ,
" D2LEVE-2.LVL " ,
" D2LEVE-3.LVL " ,
" D2LEVE-4.LVL " ,
" D2LEVE-S.LVL " ,
" D2LEVF-1.LVL " ,
" D2LEVF-2.LVL " ,
" D2LEVF-3.LVL " ,
" D2LEVF-4.LVL " ,
" D2LEVF-S.LVL " ,
} ;
2015-05-05 03:20:42 +00:00
static int Ignore_tmap_num2_error ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-05-22 17:49:30 +00:00
static void determine_used_textures_level ( int load_level_flag , int shareware_flag , int level_num , perm_tmap_buffer_type & tmap_buf , wall_buffer_type & wall_buf , level_tmap_buffer_type & level_tmap_buf , int max_tmap )
2006-03-20 17:12:09 +00:00
{
2013-12-29 04:28:07 +00:00
int sidenum ;
2016-05-22 17:49:30 +00:00
int j ;
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-05-22 17:49:30 +00:00
tmap_buf = { } ;
2013-03-03 01:03:33 +00:00
if ( load_level_flag ) {
2016-05-22 17:49:30 +00:00
load_level ( shareware_flag ? Shareware_level_names [ level_num ] : Registered_level_names [ level_num ] ) ;
2013-03-03 01:03:33 +00:00
}
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vcsegptr )
2013-03-03 01:03:33 +00:00
{
for ( sidenum = 0 ; sidenum < MAX_SIDES_PER_SEGMENT ; sidenum + + )
{
2015-06-13 22:42:16 +00:00
const auto sidep = & segp - > sides [ sidenum ] ;
2014-09-21 22:11:51 +00:00
if ( sidep - > wall_num ! = wall_none ) {
2013-03-03 01:03:33 +00:00
int clip_num = Walls [ sidep - > wall_num ] . clip_num ;
if ( clip_num ! = - 1 ) {
int num_frames = WallAnims [ clip_num ] . num_frames ;
wall_buf [ clip_num ] = 1 ;
for ( j = 0 ; j < num_frames ; j + + ) {
int tmap_num ;
tmap_num = WallAnims [ clip_num ] . frames [ j ] ;
tmap_buf [ tmap_num ] + + ;
if ( level_tmap_buf [ tmap_num ] = = - 1 )
level_tmap_buf [ tmap_num ] = level_num + ( ! shareware_flag ) * NUM_SHAREWARE_LEVELS ;
}
}
}
if ( sidep - > tmap_num > = 0 )
{
if ( sidep - > tmap_num < max_tmap )
{
tmap_buf [ sidep - > tmap_num ] + + ;
if ( level_tmap_buf [ sidep - > tmap_num ] = = - 1 )
level_tmap_buf [ sidep - > tmap_num ] = level_num + ( ! shareware_flag ) * NUM_SHAREWARE_LEVELS ;
}
else
{
Int3 ( ) ; // Error, bogus texture map. Should not be greater than max_tmap.
}
}
if ( ( sidep - > tmap_num2 & 0x3fff ) ! = 0 )
{
if ( ( sidep - > tmap_num2 & 0x3fff ) < max_tmap ) {
tmap_buf [ sidep - > tmap_num2 & 0x3fff ] + + ;
if ( level_tmap_buf [ sidep - > tmap_num2 & 0x3fff ] = = - 1 )
level_tmap_buf [ sidep - > tmap_num2 & 0x3fff ] = level_num + ( ! shareware_flag ) * NUM_SHAREWARE_LEVELS ;
} else
Int3 ( ) ; // Error, bogus texture map. Should not be greater than max_tmap.
}
}
}
# elif defined(DXX_BUILD_DESCENT_II)
2015-01-18 01:58:33 +00:00
( void ) max_tmap ;
2015-05-05 03:20:42 +00:00
( void ) shareware_flag ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
tmap_buf = { } ;
2006-03-20 17:12:09 +00:00
if ( load_level_flag ) {
load_level ( Adam_level_names [ level_num ] ) ;
}
// Process robots.
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptr )
2014-10-12 23:05:46 +00:00
{
2006-03-20 17:12:09 +00:00
if ( objp - > render_type = = RT_POLYOBJ ) {
polymodel * po = & Polygon_models [ objp - > rtype . pobj_info . model_num ] ;
2016-05-22 17:49:30 +00:00
for ( unsigned i = 0 ; i < po - > n_textures ; + + i )
{
2016-07-14 01:59:05 +00:00
unsigned tli = ObjBitmaps [ ObjBitmapPtrs [ po - > first_texture + i ] ] . index ;
2006-03-20 17:12:09 +00:00
2016-07-14 01:59:05 +00:00
if ( tli < tmap_buf . size ( ) )
{
2006-03-20 17:12:09 +00:00
tmap_buf [ tli ] + + ;
if ( level_tmap_buf [ tli ] = = - 1 )
level_tmap_buf [ tli ] = level_num ;
} else
Int3 ( ) ; // Hmm, It seems this texture is bogus!
}
}
}
Ignore_tmap_num2_error = 0 ;
// Process walls and segment sides.
2016-02-12 04:02:28 +00:00
range_for ( const auto & & segp , vsegptr )
2014-10-12 23:10:05 +00:00
{
2006-03-20 17:12:09 +00:00
for ( sidenum = 0 ; sidenum < MAX_SIDES_PER_SEGMENT ; sidenum + + ) {
2015-06-13 22:42:16 +00:00
const auto sidep = & segp - > sides [ sidenum ] ;
2014-09-21 22:11:51 +00:00
if ( sidep - > wall_num ! = wall_none ) {
2006-03-20 17:12:09 +00:00
int clip_num = Walls [ sidep - > wall_num ] . clip_num ;
if ( clip_num ! = - 1 ) {
// -- int num_frames = WallAnims[clip_num].num_frames;
wall_buf [ clip_num ] = 1 ;
for ( j = 0 ; j < 1 ; j + + ) { // Used to do through num_frames, but don't really want all the door01#3 stuff.
2016-07-14 01:59:05 +00:00
unsigned tmap_num = Textures [ WallAnims [ clip_num ] . frames [ j ] ] . index ;
Assert ( tmap_num < tmap_buf . size ( ) ) ;
2006-03-20 17:12:09 +00:00
tmap_buf [ tmap_num ] + + ;
if ( level_tmap_buf [ tmap_num ] = = - 1 )
level_tmap_buf [ tmap_num ] = level_num ;
}
}
2013-12-26 22:21:16 +00:00
} else if ( segp - > children [ sidenum ] = = segment_none ) {
2006-03-20 17:12:09 +00:00
if ( sidep - > tmap_num > = 0 )
{
2016-07-14 01:59:05 +00:00
if ( sidep - > tmap_num < Textures . size ( ) ) {
const auto ti = Textures [ sidep - > tmap_num ] . index ;
assert ( ti < tmap_buf . size ( ) ) ;
+ + tmap_buf [ ti ] ;
if ( level_tmap_buf [ ti ] = = - 1 )
level_tmap_buf [ ti ] = level_num ;
2006-03-20 17:12:09 +00:00
} else
Int3 ( ) ; // Error, bogus texture map. Should not be greater than max_tmap.
}
2016-07-14 01:59:05 +00:00
if ( const auto masked_tmap_num2 = ( sidep - > tmap_num2 & 0x3fff ) )
2006-03-20 17:12:09 +00:00
{
2016-07-14 01:59:05 +00:00
if ( masked_tmap_num2 < Textures . size ( ) )
{
const auto ti = Textures [ masked_tmap_num2 ] . index ;
assert ( ti < tmap_buf . size ( ) ) ;
+ + tmap_buf [ ti ] ;
if ( level_tmap_buf [ ti ] = = - 1 )
level_tmap_buf [ ti ] = level_num ;
2006-03-20 17:12:09 +00:00
} else {
if ( ! Ignore_tmap_num2_error )
Int3 ( ) ; // Error, bogus texture map. Should not be greater than max_tmap.
Ignore_tmap_num2_error = 1 ;
sidep - > tmap_num2 = 0 ;
}
}
}
}
}
2013-03-03 01:03:33 +00:00
# endif
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-05-22 17:49:30 +00:00
template < std : : size_t N >
static void merge_buffers ( array < int , N > & dest , const array < int , N > & src )
2006-03-20 17:12:09 +00:00
{
2016-05-22 17:49:30 +00:00
std : : transform ( dest . begin ( ) , dest . end ( ) , src . begin ( ) , dest . begin ( ) , std : : plus < int > ( ) ) ;
2006-03-20 17:12:09 +00:00
}
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-05-22 17:49:30 +00:00
static void say_used_tmaps ( PHYSFS_File * const my_file , const perm_tmap_buffer_type & tb )
2006-03-20 17:12:09 +00:00
{
int i ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
int count = 0 ;
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
for ( i = 0 ; i < Num_tmaps ; i + + )
if ( tb [ i ] ) {
2014-07-26 22:45:01 +00:00
PHYSFSX_printf ( my_file , " [%3i %8s (%4i)] " , i , static_cast < const char * > ( TmapInfo [ i ] . filename ) , tb [ i ] ) ;
2013-03-03 01:03:33 +00:00
if ( count + + > = 4 ) {
PHYSFSX_printf ( my_file , " \n " ) ;
count = 0 ;
}
}
# elif defined(DXX_BUILD_DESCENT_II)
2016-07-14 01:59:05 +00:00
for ( i = 0 ; i < tb . size ( ) ; + + i )
2006-03-20 17:12:09 +00:00
if ( tb [ i ] ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " [%3i %8s (%4i)] \n " , i , AllBitmaps [ i ] . name , tb [ i ] ) ;
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
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
// -----------------------------------------------------------------------------
2016-05-22 17:49:30 +00:00
static void say_used_once_tmaps ( PHYSFS_File * const my_file , const perm_tmap_buffer_type & tb , const level_tmap_buffer_type & tb_lnum )
2013-03-03 01:03:33 +00:00
{
int i ;
const char * level_name ;
for ( i = 0 ; i < Num_tmaps ; i + + )
if ( tb [ i ] = = 1 ) {
int level_num = tb_lnum [ i ] ;
if ( level_num > = NUM_SHAREWARE_LEVELS ) {
Assert ( ( level_num - NUM_SHAREWARE_LEVELS > = 0 ) & & ( level_num - NUM_SHAREWARE_LEVELS < NUM_REGISTERED_LEVELS ) ) ;
level_name = Registered_level_names [ level_num - NUM_SHAREWARE_LEVELS ] ;
} else {
Assert ( ( level_num > = 0 ) & & ( level_num < NUM_SHAREWARE_LEVELS ) ) ;
level_name = Shareware_level_names [ level_num ] ;
}
2014-07-26 22:45:01 +00:00
PHYSFSX_printf ( my_file , " Texture %3i %8s used only once on level %s \n " , i , static_cast < const char * > ( TmapInfo [ i ] . filename ) , level_name ) ;
2013-03-03 01:03:33 +00:00
}
}
# endif
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2016-05-22 17:49:30 +00:00
static void say_unused_tmaps ( PHYSFS_File * my_file , perm_tmap_buffer_type & tb )
2006-03-20 17:12:09 +00:00
{
int i ;
int count = 0 ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-05-03 22:08:51 +00:00
const unsigned bound = Num_tmaps ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2014-05-03 22:08:51 +00:00
const unsigned bound = MAX_BITMAP_FILES ;
2013-03-03 01:03:33 +00:00
# endif
2014-05-03 22:08:51 +00:00
for ( i = 0 ; i < bound ; i + + )
2006-03-20 17:12:09 +00:00
if ( ! tb [ i ] ) {
2015-02-28 19:36:01 +00:00
if ( GameBitmaps [ Textures [ i ] . index ] . bm_data = = bogus_data . data ( ) )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " U " ) ;
2006-03-20 17:12:09 +00:00
else
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " " ) ;
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2014-07-26 22:45:01 +00:00
PHYSFSX_printf ( my_file , " [%3i %8s] " , i , static_cast < const char * > ( TmapInfo [ i ] . filename ) ) ;
2013-03-03 01:03:33 +00:00
# elif defined(DXX_BUILD_DESCENT_II)
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " [%3i %8s] " , i , AllBitmaps [ i ] . name ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
if ( count + + > = 4 ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
count = 0 ;
}
}
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-05-22 17:49:30 +00:00
static void say_unused_walls ( PHYSFS_File * my_file , const wall_buffer_type & tb )
2013-03-03 01:03:33 +00:00
{
int i ;
for ( i = 0 ; i < Num_wall_anims ; i + + )
if ( ! tb [ i ] )
PHYSFSX_printf ( my_file , " Wall %3i is unused. \n " , i ) ;
}
# endif
2016-01-09 16:38:14 +00:00
static void say_totals ( PHYSFS_File * my_file , const char * level_name )
2006-03-20 17:12:09 +00:00
{
int total_robots = 0 ;
int objects_processed = 0 ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Level %s \n " , level_name ) ;
2014-10-02 03:02:34 +00:00
std : : bitset < MAX_OBJECTS > used_objects ;
2006-03-20 17:12:09 +00:00
while ( objects_processed < Highest_object_index + 1 ) {
2016-08-28 22:41:48 +00:00
int objtype , objid , objcount , min_obj_val ;
2006-03-20 17:12:09 +00:00
// Find new min objnum.
min_obj_val = 0x7fff0000 ;
2016-08-28 22:41:48 +00:00
const object_base * min_objp = nullptr ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2015-12-22 04:18:51 +00:00
if ( ! used_objects [ objp ] & & objp - > type ! = OBJ_NONE )
2015-06-13 22:42:16 +00:00
{
2016-08-28 22:41:48 +00:00
const auto cur_obj_val = ( objp - > type < < 10 ) + objp - > id ;
2006-03-20 17:12:09 +00:00
if ( cur_obj_val < min_obj_val ) {
2016-08-28 22:41:48 +00:00
min_objp = & * objp ;
2006-03-20 17:12:09 +00:00
min_obj_val = cur_obj_val ;
}
}
}
2016-08-28 22:41:48 +00:00
if ( ! min_objp | | min_objp - > type = = OBJ_NONE )
2006-03-20 17:12:09 +00:00
break ;
objcount = 0 ;
2016-08-28 22:41:48 +00:00
objtype = min_objp - > type ;
objid = min_objp - > id ;
2006-03-20 17:12:09 +00:00
2016-02-12 04:02:28 +00:00
range_for ( const auto & & objp , vcobjptridx )
2014-10-12 23:05:46 +00:00
{
2015-12-22 04:18:51 +00:00
if ( ! used_objects [ objp ] ) {
2015-06-13 22:42:16 +00:00
if ( ( objp - > type = = objtype & & objp - > id = = objid ) | |
( objp - > type = = objtype & & objtype = = OBJ_PLAYER ) | |
( objp - > type = = objtype & & objtype = = OBJ_COOP ) | |
( objp - > type = = objtype & & objtype = = OBJ_HOSTAGE ) ) {
if ( objp - > type = = OBJ_ROBOT )
2006-03-20 17:12:09 +00:00
total_robots + + ;
2015-12-22 04:18:51 +00:00
used_objects [ objp ] = true ;
2006-03-20 17:12:09 +00:00
objcount + + ;
objects_processed + + ;
}
}
}
if ( objcount ) {
2016-08-28 22:41:48 +00:00
PHYSFSX_printf ( my_file , " Object: %8s %8s %3i \n " , object_types ( * min_objp ) , object_ids ( * min_objp ) , objcount ) ;
2006-03-20 17:12:09 +00:00
}
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Total robots = %3i \n " , total_robots ) ;
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
int First_dump_level = 0 ;
int Last_dump_level = NUM_ADAM_LEVELS - 1 ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2013-10-27 22:00:14 +00:00
static void say_totals_all ( void )
2006-03-20 17:12:09 +00:00
{
int i ;
2015-01-17 18:31:42 +00:00
auto my_file = PHYSFSX_openWriteBuffered ( " levels.all " ) ;
2006-03-20 17:12:09 +00:00
if ( ! my_file ) {
gr_palette_load ( gr_palette ) ;
2013-12-04 22:19:04 +00:00
nm_messagebox ( NULL , 1 , " Ok " , " ERROR: Unable to open levels.all \n Errno=%i " , errno ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
for ( i = 0 ; i < NUM_SHAREWARE_LEVELS ; i + + ) {
load_level ( Shareware_level_names [ i ] ) ;
say_totals ( my_file , Shareware_level_names [ i ] ) ;
}
for ( i = 0 ; i < NUM_REGISTERED_LEVELS ; i + + ) {
load_level ( Registered_level_names [ i ] ) ;
say_totals ( my_file , Registered_level_names [ i ] ) ;
}
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
for ( i = First_dump_level ; i < = Last_dump_level ; i + + ) {
load_level ( Adam_level_names [ i ] ) ;
say_totals ( my_file , Adam_level_names [ i ] ) ;
}
2013-03-03 01:03:33 +00:00
# endif
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
static void dump_used_textures_level ( PHYSFS_File * my_file , int level_num )
2006-03-20 17:12:09 +00:00
{
2016-05-22 17:49:30 +00:00
perm_tmap_buffer_type temp_tmap_buf ;
level_tmap_buffer_type level_tmap_buf ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
level_tmap_buf . fill ( - 1 ) ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
wall_buffer_type temp_wall_buf ;
2013-10-06 16:20:00 +00:00
determine_used_textures_level ( 0 , 1 , level_num , temp_tmap_buf , temp_wall_buf , level_tmap_buf , sizeof ( level_tmap_buf ) / sizeof ( level_tmap_buf [ 0 ] ) ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Textures used in [%s] \n " , Gamesave_current_filename ) ;
2006-03-20 17:12:09 +00:00
say_used_tmaps ( my_file , temp_tmap_buf ) ;
}
// ----------------------------------------------------------------------------
2016-08-25 04:05:32 +00:00
namespace dsx {
2006-03-20 17:12:09 +00:00
void dump_used_textures_all ( void )
{
int i ;
say_totals_all ( ) ;
2015-01-17 18:31:42 +00:00
auto my_file = PHYSFSX_openWriteBuffered ( " textures.dmp " ) ;
2006-03-20 17:12:09 +00:00
if ( ! my_file ) {
gr_palette_load ( gr_palette ) ;
2013-12-04 22:19:04 +00:00
nm_messagebox ( NULL , 1 , " Ok " , " ERROR: Can't open textures.dmp \n Errno=%i " , errno ) ;
2006-03-20 17:12:09 +00:00
return ;
}
2016-05-22 17:49:30 +00:00
perm_tmap_buffer_type perm_tmap_buf { } ;
level_tmap_buffer_type level_tmap_buf ;
level_tmap_buf . fill ( - 1 ) ;
2006-03-20 17:12:09 +00:00
2016-05-22 17:49:30 +00:00
perm_tmap_buffer_type temp_tmap_buf ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2016-05-22 17:49:30 +00:00
wall_buffer_type perm_wall_buf { } ;
2013-03-03 01:03:33 +00:00
for ( i = 0 ; i < NUM_SHAREWARE_LEVELS ; i + + ) {
2016-05-22 17:49:30 +00:00
wall_buffer_type temp_wall_buf ;
2013-03-03 01:03:33 +00:00
determine_used_textures_level ( 1 , 1 , i , temp_tmap_buf , temp_wall_buf , level_tmap_buf , sizeof ( level_tmap_buf ) / sizeof ( level_tmap_buf [ 0 ] ) ) ;
PHYSFSX_printf ( my_file , " \n Textures used in [%s] \n " , Shareware_level_names [ i ] ) ;
say_used_tmaps ( my_file , temp_tmap_buf ) ;
2016-05-22 17:49:30 +00:00
merge_buffers ( perm_tmap_buf , temp_tmap_buf ) ;
merge_buffers ( perm_wall_buf , temp_wall_buf ) ;
2013-03-03 01:03:33 +00:00
}
PHYSFSX_printf ( my_file , " \n \n Used textures in all shareware mines: \n " ) ;
say_used_tmaps ( my_file , perm_tmap_buf ) ;
PHYSFSX_printf ( my_file , " \n Unused textures in all shareware mines: \n " ) ;
say_unused_tmaps ( my_file , perm_tmap_buf ) ;
PHYSFSX_printf ( my_file , " \n Textures used exactly once in all shareware mines: \n " ) ;
say_used_once_tmaps ( my_file , perm_tmap_buf , level_tmap_buf ) ;
PHYSFSX_printf ( my_file , " \n Wall anims (eg, doors) unused in all shareware mines: \n " ) ;
say_unused_walls ( my_file , perm_wall_buf ) ;
for ( i = 0 ; i < NUM_REGISTERED_LEVELS ; i + + )
# elif defined(DXX_BUILD_DESCENT_II)
2013-10-06 16:20:00 +00:00
for ( i = First_dump_level ; i < = Last_dump_level ; i + + )
2013-03-03 01:03:33 +00:00
# endif
2013-10-06 16:20:00 +00:00
{
2016-05-22 17:49:30 +00:00
wall_buffer_type temp_wall_buf ;
2013-10-06 16:20:00 +00:00
determine_used_textures_level ( 1 , 0 , i , temp_tmap_buf , temp_wall_buf , level_tmap_buf , sizeof ( level_tmap_buf ) / sizeof ( level_tmap_buf [ 0 ] ) ) ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
PHYSFSX_printf ( my_file , " \n Textures used in [%s] \n " , Registered_level_names [ i ] ) ;
# elif defined(DXX_BUILD_DESCENT_II)
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Textures used in [%s] \n " , Adam_level_names [ i ] ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
say_used_tmaps ( my_file , temp_tmap_buf ) ;
2016-05-22 17:49:30 +00:00
merge_buffers ( perm_tmap_buf , temp_tmap_buf ) ;
2006-03-20 17:12:09 +00:00
}
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n \n Used textures in all (including registered) mines: \n " ) ;
2006-03-20 17:12:09 +00:00
say_used_tmaps ( my_file , perm_tmap_buf ) ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Unused textures in all (including registered) mines: \n " ) ;
2006-03-20 17:12:09 +00:00
say_unused_tmaps ( my_file , perm_tmap_buf ) ;
}
2016-08-25 04:05:32 +00:00
}
2006-03-20 17:12:09 +00:00
# endif