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 .
*
*/
# 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"
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"
# ifdef EDITOR
# 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"
# 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
# ifdef EDITOR
2013-09-22 22:26:27 +00:00
static void dump_used_textures_level ( PHYSFS_file * my_file , int level_num ) ;
2012-07-22 23:17:54 +00:00
static void say_totals ( PHYSFS_file * my_file , const char * level_name ) ;
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2013-11-28 00:23:24 +00:00
static const char * object_types ( int objnum )
2006-03-20 17:12:09 +00:00
{
int type = Objects [ objnum ] . type ;
2012-04-14 09:42:44 +00:00
Assert ( ( type = = OBJ_NONE ) | | ( ( type > = 0 ) & & ( type < MAX_OBJECT_TYPES ) ) ) ;
2006-03-20 17:12:09 +00:00
return Object_type_names [ type ] ;
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static char * object_ids ( int objnum )
2006-03-20 17:12:09 +00:00
{
int type = Objects [ objnum ] . type ;
switch ( type ) {
case OBJ_ROBOT :
2013-10-07 23:52:33 +00:00
return Robot_names [ get_robot_id ( & Objects [ objnum ] ) ] ;
2006-03-20 17:12:09 +00:00
break ;
case OBJ_POWERUP :
2013-10-07 23:52:33 +00:00
return Powerup_names [ get_powerup_id ( & Objects [ objnum ] ) ] ;
2006-03-20 17:12:09 +00:00
break ;
}
return NULL ;
}
2013-12-19 22:55:34 +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 )
# 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 >
static void err_puts_literal ( PHYSFS_file * f , const char ( & str ) [ len ] ) __attribute_nonnull ( ) ;
template < size_t len >
static void err_puts_literal ( PHYSFS_file * f , const char ( & str ) [ len ] )
{
err_puts ( f , str , len ) ;
}
2013-09-02 23:21:13 +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
}
2013-12-19 22:55:34 +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 )
# 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 >
static void warning_puts_literal ( PHYSFS_file * f , const char ( & str ) [ len ] ) __attribute_nonnull ( ) ;
template < size_t len >
static void warning_puts_literal ( PHYSFS_file * f , const char ( & str ) [ len ] )
{
warning_puts ( f , str , len ) ;
}
2013-09-02 23:21:13 +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
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void write_exit_text ( PHYSFS_file * my_file )
2006-03-20 17:12:09 +00:00
{
int i , j , count ;
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 ;
for ( i = 0 ; i < Num_triggers ; i + + )
2013-10-06 16:20:00 +00:00
if ( trigger_is_exit ( & Triggers [ i ] ) ) {
2006-03-20 17:12:09 +00:00
int count2 ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Trigger %2i, is an exit trigger with %i links. \n " , i , Triggers [ i ] . num_links ) ;
2006-03-20 17:12:09 +00:00
count + + ;
if ( Triggers [ i ] . num_links ! = 0 )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Exit triggers must have 0 links, this one has %i links. " , Triggers [ i ] . num_links ) ;
2006-03-20 17:12:09 +00:00
// Find wall pointing to this trigger.
count2 = 0 ;
for ( j = 0 ; j < Num_walls ; j + + )
if ( Walls [ j ] . trigger = = i ) {
count2 + + ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Exit trigger %i is in segment %i, on side %i, bound to wall %i \n " , i , Walls [ j ] . segnum , Walls [ j ] . sidenum , j ) ;
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
}
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 ;
for ( i = 0 ; i < = Highest_segment_index ; i + + )
for ( j = 0 ; j < MAX_SIDES_PER_SEGMENT ; j + + )
if ( Segments [ i ] . children [ j ] = = - 2 ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Segment %3i, side %i is an exit door. \n " , i , j ) ;
2006-03-20 17:12:09 +00:00
count + + ;
}
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
}
// ----------------------------------------------------------------------------
2013-10-27 22:00: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 ;
int blue_segnum = - 1 , blue_sidenum = - 1 , red_segnum = - 1 , red_sidenum = - 1 , gold_segnum = - 1 , gold_sidenum = - 1 ;
int connect_side ;
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 ) ;
2006-03-20 17:12:09 +00:00
if ( blue_segnum = = - 1 ) {
blue_segnum = Walls [ i ] . segnum ;
blue_sidenum = Walls [ i ] . sidenum ;
blue_count + + ;
} else {
connect_side = find_connect_side ( & Segments [ Walls [ i ] . segnum ] , & Segments [ blue_segnum ] ) ;
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 ) ;
2006-03-20 17:12:09 +00:00
if ( red_segnum = = - 1 ) {
red_segnum = Walls [ i ] . segnum ;
red_sidenum = Walls [ i ] . sidenum ;
red_count + + ;
} else {
connect_side = find_connect_side ( & Segments [ Walls [ i ] . segnum ] , & Segments [ red_segnum ] ) ;
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 ) ;
2006-03-20 17:12:09 +00:00
if ( gold_segnum = = - 1 ) {
gold_segnum = Walls [ i ] . segnum ;
gold_sidenum = Walls [ i ] . sidenum ;
gold_count + + ;
} else {
connect_side = find_connect_side ( & Segments [ Walls [ i ] . segnum ] , & Segments [ gold_segnum ] ) ;
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 ;
for ( i = 0 ; i < = Highest_object_index ; i + + ) {
if ( Objects [ i ] . type = = OBJ_POWERUP )
2013-10-07 23:52:33 +00:00
if ( get_powerup_id ( & Objects [ i ] ) = = POW_KEY_BLUE ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " The BLUE key is object %i in segment %i \n " , i , Objects [ i ] . segnum ) ;
2006-03-20 17:12:09 +00:00
blue_count2 + + ;
}
if ( Objects [ i ] . type = = OBJ_POWERUP )
2013-10-07 23:52:33 +00:00
if ( get_powerup_id ( & Objects [ i ] ) = = POW_KEY_RED ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " The RED key is object %i in segment %i \n " , i , Objects [ i ] . segnum ) ;
2006-03-20 17:12:09 +00:00
red_count2 + + ;
}
if ( Objects [ i ] . type = = OBJ_POWERUP )
2013-10-07 23:52:33 +00:00
if ( get_powerup_id ( & Objects [ i ] ) = = POW_KEY_GOLD ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " The GOLD key is object %i in segment %i \n " , i , Objects [ i ] . segnum ) ;
2006-03-20 17:12:09 +00:00
gold_count2 + + ;
}
if ( Objects [ i ] . contains_count ) {
if ( Objects [ i ] . contains_type = = OBJ_POWERUP ) {
switch ( Objects [ i ] . contains_id ) {
case POW_KEY_BLUE :
2013-10-07 23:52:33 +00:00
PHYSFSX_printf ( my_file , " The BLUE key is contained in object %i (a %s %s) in segment %i \n " , i , Object_type_names [ Objects [ i ] . type ] , Robot_names [ get_robot_id ( & Objects [ i ] ) ] , Objects [ i ] . segnum ) ;
2006-03-20 17:12:09 +00:00
blue_count2 + = Objects [ i ] . contains_count ;
break ;
case POW_KEY_GOLD :
2013-10-07 23:52:33 +00:00
PHYSFSX_printf ( my_file , " The GOLD key is contained in object %i (a %s %s) in segment %i \n " , i , Object_type_names [ Objects [ i ] . type ] , Robot_names [ get_robot_id ( & Objects [ i ] ) ] , Objects [ i ] . segnum ) ;
2006-03-20 17:12:09 +00:00
gold_count2 + = Objects [ i ] . contains_count ;
break ;
case POW_KEY_RED :
2013-10-07 23:52:33 +00:00
PHYSFSX_printf ( my_file , " The RED key is contained in object %i (a %s %s) in segment %i \n " , i , Object_type_names [ Objects [ i ] . type ] , Robot_names [ get_robot_id ( & Objects [ i ] ) ] , Objects [ i ] . segnum ) ;
2006-03-20 17:12:09 +00:00
red_count2 + = Objects [ i ] . contains_count ;
break ;
default :
break ;
}
}
}
}
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
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void write_control_center_text ( PHYSFS_file * my_file )
2006-03-20 17:12:09 +00:00
{
int i , count , objnum , count2 ;
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 ;
for ( i = 0 ; i < = Highest_segment_index ; i + + )
2013-10-06 16:20:00 +00:00
if ( Segments [ i ] . special = = SEGMENT_IS_CONTROLCEN ) {
2006-03-20 17:12:09 +00:00
count + + ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Segment %3i is a control center. \n " , i ) ;
2006-03-20 17:12:09 +00:00
objnum = Segments [ i ] . objects ;
count2 = 0 ;
while ( objnum ! = - 1 ) {
if ( Objects [ objnum ] . type = = OBJ_CNTRLCEN )
count2 + + ;
objnum = Objects [ objnum ] . next ;
}
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
}
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
}
// ----------------------------------------------------------------------------
2013-10-27 22:00: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
}
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void write_segment_text ( PHYSFS_file * my_file )
2006-03-20 17:12:09 +00:00
{
int i , objnum ;
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
for ( i = 0 ; i < = Highest_segment_index ; i + + ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Segment %4i: " , i ) ;
2013-10-06 16:20:00 +00:00
if ( Segments [ i ] . special ! = 0 )
PHYSFSX_printf ( my_file , " special = %3i (%s), value = %3i " , Segments [ i ] . special , Special_names [ Segments [ i ] . special ] , Segments [ i ] . value ) ;
2006-03-20 17:12:09 +00:00
2013-10-06 16:20:00 +00:00
if ( Segments [ i ] . matcen_num ! = - 1 )
PHYSFSX_printf ( my_file , " matcen = %3i, " , Segments [ i ] . matcen_num ) ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n " ) ;
2006-03-20 17:12:09 +00:00
}
for ( i = 0 ; i < = Highest_segment_index ; i + + ) {
int depth ;
objnum = Segments [ i ] . objects ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Segment %4i: " , i ) ;
2006-03-20 17:12:09 +00:00
depth = 0 ;
if ( objnum ! = - 1 ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Objects: " ) ;
2006-03-20 17:12:09 +00:00
while ( objnum ! = - 1 ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " [%8s %8s %3i] " , object_types ( objnum ) , object_ids ( objnum ) , objnum ) ;
2006-03-20 17:12:09 +00:00
objnum = Objects [ objnum ] . next ;
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.
2013-10-27 22:00:14 +00:00
static void write_matcen_text ( PHYSFS_file * my_file )
2006-03-20 17:12:09 +00:00
{
int i , j , k ;
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 + + ) {
int trigger_count = 0 , segnum , fuelcen_num ;
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
segnum = Station [ fuelcen_num ] . segnum ;
// Find trigger for this materialization center.
for ( j = 0 ; j < Num_triggers ; j + + ) {
2013-10-06 16:20:00 +00:00
if ( trigger_is_matcen ( & Triggers [ j ] ) ) {
2006-03-20 17:12:09 +00:00
for ( k = 0 ; k < Triggers [ j ] . num_links ; k + + )
if ( Triggers [ j ] . seg [ 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
}
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void write_wall_text ( PHYSFS_file * my_file )
2006-03-20 17:12:09 +00:00
{
int i , j ;
sbyte wall_flags [ MAX_WALLS ] ;
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 + + ) {
int segnum , sidenum ;
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
segnum = Walls [ i ] . segnum ;
sidenum = Walls [ i ] . sidenum ;
if ( Segments [ segnum ] . sides [ sidenum ] . wall_num ! = i )
2013-12-19 22:49:25 +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 = %i) " , i , segnum , sidenum , Segments [ segnum ] . sides [ sidenum ] . wall_num ) ;
2006-03-20 17:12:09 +00:00
}
2013-03-03 01:03:33 +00:00
for ( unsigned i = 0 ; i < sizeof ( wall_flags ) / sizeof ( wall_flags [ 0 ] ) ; i + + )
2006-03-20 17:12:09 +00:00
wall_flags [ i ] = 0 ;
for ( i = 0 ; i < = Highest_segment_index ; i + + ) {
segment * segp = & Segments [ i ] ;
for ( j = 0 ; j < MAX_SIDES_PER_SEGMENT ; j + + ) {
side * sidep = & segp - > sides [ j ] ;
if ( sidep - > wall_num ! = - 1 )
{
if ( wall_flags [ sidep - > wall_num ] )
2013-12-19 22:49:25 +00:00
err_printf ( my_file , " Error: Wall %i appears in two or more segments, including segment %i, side %i. " , sidep - > wall_num , i , j ) ;
2006-03-20 17:12:09 +00:00
else
wall_flags [ sidep - > wall_num ] = 1 ;
}
}
}
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void write_player_text ( PHYSFS_file * my_file )
2006-03-20 17:12:09 +00:00
{
int i , num_players = 0 ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Players: \n " ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < = Highest_object_index ; i + + ) {
if ( Objects [ i ] . type = = OBJ_PLAYER ) {
num_players + + ;
2013-10-07 23:52:33 +00:00
PHYSFSX_printf ( my_file , " Player %2i is object #%3i in segment #%3i. \n " , get_player_id ( & Objects [ i ] ) , i , Objects [ i ] . 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
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void write_trigger_text ( PHYSFS_file * my_file )
2006-03-20 17:12:09 +00:00
{
int i , j , w ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " ----------------------------------------------------------------------------- \n " ) ;
PHYSFSX_printf ( my_file , " Triggers: \n " ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < Num_triggers ; i + + ) {
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
PHYSFSX_printf ( my_file , " Trigger %03i: type=%3i flags=%04x, value=%08x, time=%8x, linknum=%i, num_links=%i " , i ,
Triggers [ i ] . type , Triggers [ i ] . flags , ( unsigned int ) ( Triggers [ i ] . value ) , ( unsigned int ) ( Triggers [ i ] . time ) , Triggers [ i ] . link_num , Triggers [ i ] . num_links ) ;
# 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 ,
2006-03-20 17:12:09 +00:00
Triggers [ i ] . type , Triggers [ i ] . flags , Triggers [ i ] . value , Triggers [ i ] . time , Triggers [ i ] . num_links ) ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
for ( j = 0 ; j < Triggers [ i ] . num_links ; j + + )
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " [%03i:%i] " , Triggers [ i ] . seg [ j ] , Triggers [ i ] . 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
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Attached to seg:side = %i:%i, wall %i \n " , Walls [ w ] . segnum , Walls [ w ] . sidenum , Segments [ Walls [ w ] . segnum ] . sides [ Walls [ w ] . sidenum ] . wall_num ) ;
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 ;
2010-08-19 13:32:33 +00:00
PHYSFS_file * my_file ;
2006-03-20 17:12:09 +00:00
Errors_in_mine = 0 ;
namelen = strlen ( filename ) ;
Assert ( namelen > 4 ) ;
Assert ( filename [ namelen - 4 ] = = ' . ' ) ;
strcpy ( my_filename , filename ) ;
strcpy ( & my_filename [ namelen - 4 ] , " .txm " ) ;
2010-08-19 13:32:33 +00:00
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 ) ;
2012-04-14 06:13:01 +00:00
{
int r ;
r = PHYSFS_close ( my_file ) ;
if ( ! r )
Int3 ( ) ;
}
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
// Adam: Change NUM_ADAM_LEVELS to the number of levels.
# define NUM_ADAM_LEVELS 30
// Adam: Stick the names here.
2013-11-28 00:21:41 +00:00
static const 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 " ,
} ;
int Ignore_tmap_num2_error ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void determine_used_textures_level ( int load_level_flag , int shareware_flag , int level_num , int * tmap_buf , int * wall_buf , sbyte * level_tmap_buf , int max_tmap )
2006-03-20 17:12:09 +00:00
{
2013-03-03 01:03:33 +00:00
int segnum , sidenum ;
2006-03-20 17:12:09 +00:00
int i , j ;
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
for ( i = 0 ; i < max_tmap ; i + + )
tmap_buf [ i ] = 0 ;
if ( load_level_flag ) {
if ( shareware_flag )
load_level ( Shareware_level_names [ level_num ] ) ;
else
load_level ( Registered_level_names [ level_num ] ) ;
}
for ( segnum = 0 ; segnum < = Highest_segment_index ; segnum + + )
{
segment * segp = & Segments [ segnum ] ;
for ( sidenum = 0 ; sidenum < MAX_SIDES_PER_SEGMENT ; sidenum + + )
{
side * sidep = & segp - > sides [ sidenum ] ;
if ( sidep - > wall_num ! = - 1 ) {
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)
int objnum = max_tmap ;
2006-03-20 17:12:09 +00:00
Assert ( shareware_flag ! = - 17 ) ;
for ( i = 0 ; i < MAX_BITMAP_FILES ; i + + )
tmap_buf [ i ] = 0 ;
if ( load_level_flag ) {
load_level ( Adam_level_names [ level_num ] ) ;
}
// Process robots.
for ( objnum = 0 ; objnum < = Highest_object_index ; objnum + + ) {
object * objp = & Objects [ objnum ] ;
if ( objp - > render_type = = RT_POLYOBJ ) {
polymodel * po = & Polygon_models [ objp - > rtype . pobj_info . model_num ] ;
for ( i = 0 ; i < po - > n_textures ; i + + ) {
int tli = ObjBitmaps [ ObjBitmapPtrs [ po - > first_texture + i ] ] . index ;
if ( ( tli < MAX_BITMAP_FILES ) & & ( tli > = 0 ) ) {
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.
for ( segnum = 0 ; segnum < = Highest_segment_index ; segnum + + ) {
segment * segp = & Segments [ segnum ] ;
for ( sidenum = 0 ; sidenum < MAX_SIDES_PER_SEGMENT ; sidenum + + ) {
side * sidep = & segp - > sides [ sidenum ] ;
if ( sidep - > wall_num ! = - 1 ) {
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.
int tmap_num ;
tmap_num = Textures [ WallAnims [ clip_num ] . frames [ j ] ] . index ;
Assert ( ( tmap_num > = 0 ) & & ( tmap_num < MAX_BITMAP_FILES ) ) ;
tmap_buf [ tmap_num ] + + ;
if ( level_tmap_buf [ tmap_num ] = = - 1 )
level_tmap_buf [ tmap_num ] = level_num ;
}
}
} else if ( segp - > children [ sidenum ] = = - 1 ) {
if ( sidep - > tmap_num > = 0 )
{
if ( sidep - > tmap_num < MAX_BITMAP_FILES ) {
Assert ( Textures [ sidep - > tmap_num ] . index < MAX_BITMAP_FILES ) ;
tmap_buf [ Textures [ sidep - > tmap_num ] . index ] + + ;
if ( level_tmap_buf [ Textures [ sidep - > tmap_num ] . index ] = = - 1 )
level_tmap_buf [ Textures [ sidep - > tmap_num ] . index ] = level_num ;
} 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_BITMAP_FILES ) {
Assert ( Textures [ sidep - > tmap_num2 & 0x3fff ] . index < MAX_BITMAP_FILES ) ;
tmap_buf [ Textures [ sidep - > tmap_num2 & 0x3fff ] . index ] + + ;
if ( level_tmap_buf [ Textures [ sidep - > tmap_num2 & 0x3fff ] . index ] = = - 1 )
level_tmap_buf [ Textures [ sidep - > tmap_num2 & 0x3fff ] . index ] = level_num ;
} 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
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void merge_buffers ( int * dest , int * src , int num )
2006-03-20 17:12:09 +00:00
{
int i ;
for ( i = 0 ; i < num ; i + + )
if ( src [ i ] )
dest [ i ] + = src [ i ] ;
}
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void say_used_tmaps ( PHYSFS_file * my_file , int * 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 ] ) {
PHYSFSX_printf ( my_file , " [%3i %8s (%4i)] " , i , TmapInfo [ i ] . filename , tb [ i ] ) ;
if ( count + + > = 4 ) {
PHYSFSX_printf ( my_file , " \n " ) ;
count = 0 ;
}
}
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < MAX_BITMAP_FILES ; i + + )
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
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
// -----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void say_used_once_tmaps ( PHYSFS_file * my_file , int * tb , sbyte * 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 ] ;
}
PHYSFSX_printf ( my_file , " Texture %3i %8s used only once on level %s \n " , i , TmapInfo [ i ] . filename , level_name ) ;
}
}
# endif
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void say_unused_tmaps ( PHYSFS_file * my_file , int * 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)
for ( i = 0 ; i < Num_tmaps ; i + + )
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < MAX_BITMAP_FILES ; i + + )
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
if ( ! tb [ i ] ) {
if ( GameBitmaps [ Textures [ i ] . index ] . bm_data = = bogus_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)
PHYSFSX_printf ( my_file , " [%3i %8s] " , i , TmapInfo [ i ] . filename ) ;
# 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 ;
}
}
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
2006-03-20 17:12:09 +00:00
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void say_unused_walls ( PHYSFS_file * my_file , int * 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
2012-07-22 23:17:54 +00:00
static void say_totals ( PHYSFS_file * my_file , const char * level_name )
2006-03-20 17:12:09 +00:00
{
int i ; //, objnum;
int total_robots = 0 ;
int objects_processed = 0 ;
int used_objects [ MAX_OBJECTS ] ;
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " \n Level %s \n " , level_name ) ;
2006-03-20 17:12:09 +00:00
for ( i = 0 ; i < MAX_OBJECTS ; i + + )
used_objects [ i ] = 0 ;
while ( objects_processed < Highest_object_index + 1 ) {
int j , objtype , objid , objcount , cur_obj_val , min_obj_val , min_objnum ;
// Find new min objnum.
min_obj_val = 0x7fff0000 ;
min_objnum = - 1 ;
for ( j = 0 ; j < = Highest_object_index ; j + + ) {
if ( ! used_objects [ j ] & & Objects [ j ] . type ! = OBJ_NONE ) {
cur_obj_val = Objects [ j ] . type * 1000 + Objects [ j ] . id ;
if ( cur_obj_val < min_obj_val ) {
min_objnum = j ;
min_obj_val = cur_obj_val ;
}
}
}
if ( ( min_objnum = = - 1 ) | | ( Objects [ min_objnum ] . type = = 255 ) )
break ;
objcount = 0 ;
objtype = Objects [ min_objnum ] . type ;
objid = Objects [ min_objnum ] . id ;
for ( i = 0 ; i < = Highest_object_index ; i + + ) {
if ( ! used_objects [ i ] ) {
if ( ( ( Objects [ i ] . type = = objtype ) & & ( Objects [ i ] . id = = objid ) ) | |
( ( Objects [ i ] . type = = objtype ) & & ( objtype = = OBJ_PLAYER ) ) | |
( ( Objects [ i ] . type = = objtype ) & & ( objtype = = OBJ_COOP ) ) | |
( ( Objects [ i ] . type = = objtype ) & & ( objtype = = OBJ_HOSTAGE ) ) ) {
if ( Objects [ i ] . type = = OBJ_ROBOT )
total_robots + + ;
used_objects [ i ] = 1 ;
objcount + + ;
objects_processed + + ;
}
}
}
if ( objcount ) {
2010-08-19 13:32:33 +00:00
PHYSFSX_printf ( my_file , " Object: " ) ;
PHYSFSX_printf ( my_file , " %8s %8s %3i \n " , object_types ( min_objnum ) , object_ids ( min_objnum ) , 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
// ----------------------------------------------------------------------------
2013-10-27 22:00:14 +00:00
static void say_totals_all ( void )
2006-03-20 17:12:09 +00:00
{
int i ;
2010-08-19 13:32:33 +00:00
PHYSFS_file * my_file ;
2006-03-20 17:12:09 +00:00
2010-08-19 13:32:33 +00:00
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
2010-08-19 13:32:33 +00:00
PHYSFS_close ( my_file ) ;
2006-03-20 17:12:09 +00:00
}
2013-10-06 16:20:00 +00:00
static void dump_used_textures_level ( PHYSFS_file * my_file , int level_num )
2006-03-20 17:12:09 +00:00
{
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
int temp_tmap_buf [ MAX_TEXTURES ] ;
sbyte level_tmap_buf [ MAX_TEXTURES ] ;
int temp_wall_buf [ MAX_WALL_ANIMS ] ;
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
int temp_tmap_buf [ MAX_BITMAP_FILES ] ;
sbyte level_tmap_buf [ MAX_BITMAP_FILES ] ;
int temp_wall_buf [ MAX_BITMAP_FILES ] ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
2013-10-06 16:20:00 +00:00
for ( unsigned i = 0 ; i < ( sizeof ( level_tmap_buf ) / sizeof ( level_tmap_buf [ 0 ] ) ) ; i + + )
2006-03-20 17:12:09 +00:00
level_tmap_buf [ i ] = - 1 ;
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 ) ;
}
// ----------------------------------------------------------------------------
void dump_used_textures_all ( void )
{
2013-10-06 16:20:00 +00:00
PHYSFS_file * my_file ;
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 temp_tmap_buf [ MAX_TEXTURES ] ;
int perm_tmap_buf [ MAX_TEXTURES ] ;
sbyte level_tmap_buf [ MAX_TEXTURES ] ;
int temp_wall_buf [ MAX_WALL_ANIMS ] ;
int perm_wall_buf [ MAX_WALL_ANIMS ] ;
# elif defined(DXX_BUILD_DESCENT_II)
2006-03-20 17:12:09 +00:00
int temp_tmap_buf [ MAX_BITMAP_FILES ] ;
int perm_tmap_buf [ MAX_BITMAP_FILES ] ;
sbyte level_tmap_buf [ MAX_BITMAP_FILES ] ;
int temp_wall_buf [ MAX_BITMAP_FILES ] ;
2013-03-03 01:03:33 +00:00
# endif
2006-03-20 17:12:09 +00:00
say_totals_all ( ) ;
2010-08-19 13:32:33 +00:00
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 ;
}
2013-03-03 01:03:33 +00:00
for ( unsigned i = 0 ; i < sizeof ( perm_tmap_buf ) / sizeof ( perm_tmap_buf [ 0 ] ) ; i + + ) {
2006-03-20 17:12:09 +00:00
perm_tmap_buf [ i ] = 0 ;
level_tmap_buf [ i ] = - 1 ;
}
2013-03-03 01:03:33 +00:00
# if defined(DXX_BUILD_DESCENT_I)
for ( i = 0 ; i < MAX_WALL_ANIMS ; i + + ) {
perm_wall_buf [ i ] = 0 ;
}
for ( i = 0 ; i < NUM_SHAREWARE_LEVELS ; i + + ) {
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 ) ;
merge_buffers ( perm_tmap_buf , temp_tmap_buf , MAX_TEXTURES ) ;
merge_buffers ( perm_wall_buf , temp_wall_buf , MAX_WALL_ANIMS ) ;
}
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
{
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 ) ;
2013-10-06 16:20:00 +00:00
merge_buffers ( perm_tmap_buf , temp_tmap_buf , sizeof ( perm_tmap_buf ) / sizeof ( perm_tmap_buf [ 0 ] ) ) ;
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 ) ;
2010-08-19 13:32:33 +00:00
PHYSFS_close ( my_file ) ;
2006-03-20 17:12:09 +00:00
}
# endif