1 /* $Id: dumpmine.c,v 1.4 2003-10-10 09:36:34 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Functions to dump text description of mine.
18 * An editor-only function, called at mine load time.
19 * To be read by a human to verify the correctness and completeness of a mine.
22 * Revision 1.1 1995/05/16 15:24:16 allender
25 * Revision 2.1 1995/04/06 12:21:50 mike
26 * Add texture map information to txm files.
28 * Revision 2.0 1995/02/27 11:26:41 john
29 * New version 2.0, which has no anonymous unions, builds with
30 * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
32 * Revision 1.24 1995/01/23 15:34:43 mike
33 * New diagnostic code, levels.all stuff.
35 * Revision 1.23 1994/12/20 17:56:36 yuan
36 * Multiplayer object capability.
38 * Revision 1.22 1994/11/27 23:12:19 matt
39 * Made changes for new mprintf calling convention
41 * Revision 1.21 1994/11/23 12:19:04 mike
42 * move out level names, stick in gamesave.
44 * Revision 1.20 1994/11/21 16:54:36 mike
48 * Revision 1.19 1994/11/20 22:12:55 mike
49 * Lotsa new stuff in this fine debug file.
51 * Revision 1.18 1994/11/17 14:58:09 mike
52 * moved segment validation functions from editor to main.
54 * Revision 1.17 1994/11/15 21:43:02 mike
55 * texture usage system.
57 * Revision 1.16 1994/11/15 12:45:59 mike
58 * debug code for dumping texture info.
60 * Revision 1.15 1994/11/14 20:47:50 john
61 * Attempted to strip out all the code in the game
62 * directory that uses any ui code.
64 * Revision 1.14 1994/10/14 17:33:38 mike
65 * Fix error reporting for number of multiplayer objects in mine.
67 * Revision 1.13 1994/10/14 13:37:46 mike
68 * Forgot parameter in fprintf, was getting bogus number of excess keys.
70 * Revision 1.12 1994/10/12 08:05:33 mike
71 * Detect keys contained in objects for error checking (txm file).
73 * Revision 1.11 1994/10/10 17:02:08 mike
76 * Revision 1.10 1994/10/10 17:00:37 mike
77 * Add checking for proper number of players.
79 * Revision 1.9 1994/10/03 23:37:19 mike
80 * Adapt to clear and rational understanding of matcens as related to fuelcens as related to something that might work.
82 * Revision 1.8 1994/09/30 17:15:29 mike
83 * Fix error message, was telling bogus filename.
85 * Revision 1.7 1994/09/30 11:50:55 mike
88 * Revision 1.6 1994/09/28 17:31:19 mike
89 * More error checking.
91 * Revision 1.5 1994/09/28 11:14:05 mike
92 * Better checking on bogus walls.
94 * Revision 1.4 1994/09/28 09:23:50 mike
95 * Change some Error messages to Warnings.
97 * Revision 1.3 1994/09/27 17:08:31 mike
98 * More mine validation stuff.
100 * Revision 1.2 1994/09/27 15:43:22 mike
101 * The amazing code to tell you everything and more about our mines!
103 * Revision 1.1 1994/09/27 10:51:15 mike
114 static char rcsid[] = "$Id: dumpmine.c,v 1.4 2003-10-10 09:36:34 btb Exp $";
130 #include "editor/editor.h"
135 #include "gamemine.h"
139 #include "textures.h"
148 #include "gamesave.h"
153 extern ubyte bogus_data[64*64];
154 extern grs_bitmap bogus_bitmap;
156 // ----------------------------------------------------------------------------
157 char *object_types(int objnum)
159 int type = Objects[objnum].type;
161 Assert((type >= 0) && (type < MAX_OBJECT_TYPES));
162 return &Object_type_names[type];
165 // ----------------------------------------------------------------------------
166 char *object_ids(int objnum)
168 int type = Objects[objnum].type;
169 int id = Objects[objnum].id;
173 return &Robot_names[id];
176 return &Powerup_names[id];
183 void err_printf(FILE *my_file, char * format, ... )
188 va_start(args, format );
189 vsprintf(message,format,args);
192 mprintf((1, "%s", message));
193 fprintf(my_file, "%s", message);
197 void warning_printf(FILE *my_file, char * format, ... )
202 va_start(args, format );
203 vsprintf(message,format,args);
206 mprintf((0, "%s", message));
207 fprintf(my_file, "%s", message);
210 // ----------------------------------------------------------------------------
211 void write_exit_text(FILE *my_file)
215 fprintf(my_file, "-----------------------------------------------------------------------------\n");
216 fprintf(my_file, "Exit stuff\n");
218 // ---------- Find exit triggers ----------
220 for (i=0; i<Num_triggers; i++)
221 if (Triggers[i].type == TT_EXIT) {
224 fprintf(my_file, "Trigger %2i, is an exit trigger with %i links.\n", i, Triggers[i].num_links);
226 if (Triggers[i].num_links != 0)
227 err_printf(my_file, "Error: Exit triggers must have 0 links, this one has %i links.\n", Triggers[i].num_links);
229 // Find wall pointing to this trigger.
231 for (j=0; j<Num_walls; j++)
232 if (Walls[j].trigger == i) {
234 fprintf(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);
237 err_printf(my_file, "Error: Trigger %i is not bound to any wall.\n", i);
239 err_printf(my_file, "Error: Trigger %i is bound to %i walls.\n", i, count2);
244 err_printf(my_file, "Error: No exit trigger in this mine.\n");
246 err_printf(my_file, "Error: More than one exit trigger in this mine.\n");
248 fprintf(my_file, "\n");
250 // ---------- Find exit doors ----------
252 for (i=0; i<=Highest_segment_index; i++)
253 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
254 if (Segments[i].children[j] == -2) {
255 fprintf(my_file, "Segment %3i, side %i is an exit door.\n", i, j);
260 err_printf(my_file, "Error: No external wall in this mine.\n");
261 else if (count != 1) {
262 // -- warning_printf(my_file, "Warning: %i external walls in this mine.\n", count);
263 // -- warning_printf(my_file, "(If %i are secret exits, then no problem.)\n", count-1);
265 fprintf(my_file, "\n");
268 // ----------------------------------------------------------------------------
269 void write_key_text(FILE *my_file)
272 int red_count, blue_count, gold_count;
273 int red_count2, blue_count2, gold_count2;
274 int blue_segnum=-1, blue_sidenum=-1, red_segnum=-1, red_sidenum=-1, gold_segnum=-1, gold_sidenum=-1;
277 fprintf(my_file, "-----------------------------------------------------------------------------\n");
278 fprintf(my_file, "Key stuff:\n");
284 for (i=0; i<Num_walls; i++) {
285 if (Walls[i].keys & KEY_BLUE) {
286 fprintf(my_file, "Wall %i (seg=%i, side=%i) is keyed to the blue key.\n", i, Walls[i].segnum, Walls[i].sidenum);
287 if (blue_segnum == -1) {
288 blue_segnum = Walls[i].segnum;
289 blue_sidenum = Walls[i].sidenum;
292 connect_side = find_connect_side(&Segments[Walls[i].segnum], &Segments[blue_segnum]);
293 if (connect_side != blue_sidenum) {
294 warning_printf(my_file, "Warning: This blue door at seg %i, is different than the one at seg %i, side %i\n", Walls[i].segnum, blue_segnum, blue_sidenum);
299 if (Walls[i].keys & KEY_RED) {
300 fprintf(my_file, "Wall %i (seg=%i, side=%i) is keyed to the red key.\n", i, Walls[i].segnum, Walls[i].sidenum);
301 if (red_segnum == -1) {
302 red_segnum = Walls[i].segnum;
303 red_sidenum = Walls[i].sidenum;
306 connect_side = find_connect_side(&Segments[Walls[i].segnum], &Segments[red_segnum]);
307 if (connect_side != red_sidenum) {
308 warning_printf(my_file, "Warning: This red door at seg %i, is different than the one at seg %i, side %i\n", Walls[i].segnum, red_segnum, red_sidenum);
313 if (Walls[i].keys & KEY_GOLD) {
314 fprintf(my_file, "Wall %i (seg=%i, side=%i) is keyed to the gold key.\n", i, Walls[i].segnum, Walls[i].sidenum);
315 if (gold_segnum == -1) {
316 gold_segnum = Walls[i].segnum;
317 gold_sidenum = Walls[i].sidenum;
320 connect_side = find_connect_side(&Segments[Walls[i].segnum], &Segments[gold_segnum]);
321 if (connect_side != gold_sidenum) {
322 warning_printf(my_file, "Warning: This gold door at seg %i, is different than the one at seg %i, side %i\n", Walls[i].segnum, gold_segnum, gold_sidenum);
330 warning_printf(my_file, "Warning: %i doors are keyed to the blue key.\n", blue_count);
333 warning_printf(my_file, "Warning: %i doors are keyed to the red key.\n", red_count);
336 warning_printf(my_file, "Warning: %i doors are keyed to the gold key.\n", gold_count);
342 for (i=0; i<=Highest_object_index; i++) {
343 if (Objects[i].type == OBJ_POWERUP)
344 if (Objects[i].id == POW_KEY_BLUE) {
345 fprintf(my_file, "The BLUE key is object %i in segment %i\n", i, Objects[i].segnum);
348 if (Objects[i].type == OBJ_POWERUP)
349 if (Objects[i].id == POW_KEY_RED) {
350 fprintf(my_file, "The RED key is object %i in segment %i\n", i, Objects[i].segnum);
353 if (Objects[i].type == OBJ_POWERUP)
354 if (Objects[i].id == POW_KEY_GOLD) {
355 fprintf(my_file, "The GOLD key is object %i in segment %i\n", i, Objects[i].segnum);
359 if (Objects[i].contains_count) {
360 if (Objects[i].contains_type == OBJ_POWERUP) {
361 switch (Objects[i].contains_id) {
363 fprintf(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[Objects[i].id], Objects[i].segnum);
364 blue_count2 += Objects[i].contains_count;
367 fprintf(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[Objects[i].id], Objects[i].segnum);
368 gold_count2 += Objects[i].contains_count;
371 fprintf(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[Objects[i].id], Objects[i].segnum);
372 red_count2 += Objects[i].contains_count;
382 if (blue_count2 == 0)
383 err_printf(my_file, "Error: There is a door keyed to the blue key, but no blue key!\n");
387 err_printf(my_file, "Error: There is a door keyed to the red key, but no red key!\n");
390 if (gold_count2 == 0)
391 err_printf(my_file, "Error: There is a door keyed to the gold key, but no gold key!\n");
394 err_printf(my_file, "Error: There are %i blue keys!\n", blue_count2);
397 err_printf(my_file, "Error: There are %i red keys!\n", red_count2);
400 err_printf(my_file, "Error: There are %i gold keys!\n", gold_count2);
403 // ----------------------------------------------------------------------------
404 void write_control_center_text(FILE *my_file)
406 int i, count, objnum, count2;
408 fprintf(my_file, "-----------------------------------------------------------------------------\n");
409 fprintf(my_file, "Control Center stuff:\n");
412 for (i=0; i<=Highest_segment_index; i++)
413 if (Segment2s[i].special == SEGMENT_IS_CONTROLCEN) {
415 fprintf(my_file, "Segment %3i is a control center.\n", i);
416 objnum = Segments[i].objects;
418 while (objnum != -1) {
419 if (Objects[objnum].type == OBJ_CNTRLCEN)
421 objnum = Objects[objnum].next;
424 fprintf(my_file, "No control center object in control center segment.\n");
425 else if (count2 != 1)
426 fprintf(my_file, "%i control center objects in control center segment.\n", count2);
430 err_printf(my_file, "Error: No control center in this mine.\n");
432 err_printf(my_file, "Error: More than one control center in this mine.\n");
435 // ----------------------------------------------------------------------------
436 void write_fuelcen_text(FILE *my_file)
440 fprintf(my_file, "-----------------------------------------------------------------------------\n");
441 fprintf(my_file, "Fuel Center stuff: (Note: This means fuel, repair, materialize, control centers!)\n");
443 for (i=0; i<Num_fuelcenters; i++) {
444 fprintf(my_file, "Fuelcenter %i: Type=%i (%s), segment = %3i\n", i, Station[i].Type, Special_names[Station[i].Type], Station[i].segnum);
445 if (Segment2s[Station[i].segnum].special != Station[i].Type)
446 err_printf(my_file, "Error: Conflicting data: Segment %i has special type %i (%s), expected to be %i\n", Station[i].segnum, Segment2s[Station[i].segnum].special, Special_names[Segment2s[Station[i].segnum].special], Station[i].Type);
450 // ----------------------------------------------------------------------------
451 void write_segment_text(FILE *my_file)
455 fprintf(my_file, "-----------------------------------------------------------------------------\n");
456 fprintf(my_file, "Segment stuff:\n");
458 for (i=0; i<=Highest_segment_index; i++) {
460 fprintf(my_file, "Segment %4i: ", i);
461 if (Segment2s[i].special != 0)
462 fprintf(my_file, "special = %3i (%s), value = %3i ", Segment2s[i].special, Special_names[Segment2s[i].special], Segment2s[i].value);
464 if (Segment2s[i].matcen_num != -1)
465 fprintf(my_file, "matcen = %3i, ", Segment2s[i].matcen_num);
467 fprintf(my_file, "\n");
470 for (i=0; i<=Highest_segment_index; i++) {
473 objnum = Segments[i].objects;
474 fprintf(my_file, "Segment %4i: ", i);
477 fprintf(my_file, "Objects: ");
478 while (objnum != -1) {
479 fprintf(my_file, "[%8s %8s %3i] ", object_types(objnum), object_ids(objnum), objnum);
480 objnum = Objects[objnum].next;
482 fprintf(my_file, "\nAborted after %i links\n", depth);
487 fprintf(my_file, "\n");
491 // ----------------------------------------------------------------------------
492 // This routine is bogus. It assumes that all centers are matcens,
493 // which is not true. The setting of segnum is bogus.
494 void write_matcen_text(FILE *my_file)
498 fprintf(my_file, "-----------------------------------------------------------------------------\n");
499 fprintf(my_file, "Materialization centers:\n");
500 for (i=0; i<Num_robot_centers; i++) {
501 int trigger_count=0, segnum, fuelcen_num;
503 fprintf(my_file, "FuelCenter[%02i].Segment = %04i ", i, Station[i].segnum);
504 fprintf(my_file, "Segment2[%04i].matcen_num = %02i ", Station[i].segnum, Segment2s[Station[i].segnum].matcen_num);
506 fuelcen_num = RobotCenters[i].fuelcen_num;
507 if (Station[fuelcen_num].Type != SEGMENT_IS_ROBOTMAKER)
508 err_printf(my_file, "Error: Matcen %i corresponds to Station %i, which has type %i (%s).\n", i, fuelcen_num, Station[fuelcen_num].Type, Special_names[Station[fuelcen_num].Type]);
510 segnum = Station[fuelcen_num].segnum;
512 // Find trigger for this materialization center.
513 for (j=0; j<Num_triggers; j++) {
514 if (Triggers[j].type == TT_MATCEN) {
515 for (k=0; k<Triggers[j].num_links; k++)
516 if (Triggers[j].seg[k] == segnum) {
517 fprintf(my_file, "Trigger = %2i ", j );
522 fprintf(my_file, "\n");
524 if (trigger_count == 0)
525 err_printf(my_file, "Error: Matcen %i in segment %i has no trigger!\n", i, segnum);
530 // ----------------------------------------------------------------------------
531 void write_wall_text(FILE *my_file)
534 byte wall_flags[MAX_WALLS];
536 fprintf(my_file, "-----------------------------------------------------------------------------\n");
537 fprintf(my_file, "Walls:\n");
538 for (i=0; i<Num_walls; i++) {
541 fprintf(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,
542 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);
544 if (Walls[i].trigger >= Num_triggers)
545 fprintf(my_file, "Wall %03d points to invalid trigger %d\n",i,Walls[i].trigger);
547 segnum = Walls[i].segnum;
548 sidenum = Walls[i].sidenum;
550 if (Segments[segnum].sides[sidenum].wall_num != i)
551 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)\n", i, segnum, sidenum, Segments[segnum].sides[sidenum].wall_num);
554 for (i=0; i<MAX_WALLS; i++)
557 for (i=0; i<=Highest_segment_index; i++) {
558 segment *segp = &Segments[i];
559 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) {
560 side *sidep = &segp->sides[j];
561 if (sidep->wall_num != -1)
562 if (wall_flags[sidep->wall_num])
563 err_printf(my_file, "Error: Wall %i appears in two or more segments, including segment %i, side %i.\n", sidep->wall_num, i, j);
565 wall_flags[sidep->wall_num] = 1;
571 //typedef struct trigger {
578 // short seg[MAX_WALLS_PER_LINK];
579 // short side[MAX_WALLS_PER_LINK];
582 // ----------------------------------------------------------------------------
583 void write_player_text(FILE *my_file)
585 int i, num_players=0;
587 fprintf(my_file, "-----------------------------------------------------------------------------\n");
588 fprintf(my_file, "Players:\n");
589 for (i=0; i<=Highest_object_index; i++) {
590 if (Objects[i].type == OBJ_PLAYER) {
592 fprintf(my_file, "Player %2i is object #%3i in segment #%3i.\n", Objects[i].id, i, Objects[i].segnum);
596 if (num_players != MAX_PLAYERS)
597 err_printf(my_file, "Error: %i player objects. %i are required.\n", num_players, MAX_PLAYERS);
598 if (num_players > MAX_MULTI_PLAYERS)
599 err_printf(my_file, "Error: %i player objects. %i are required.\n", num_players, MAX_PLAYERS);
602 // ----------------------------------------------------------------------------
603 void write_trigger_text(FILE *my_file)
607 fprintf(my_file, "-----------------------------------------------------------------------------\n");
608 fprintf(my_file, "Triggers:\n");
609 for (i=0; i<Num_triggers; i++) {
610 fprintf(my_file, "Trigger %03i: type=%02x flags=%04x, value=%08x, time=%8x, num_links=%i ", i,
611 Triggers[i].type, Triggers[i].flags, Triggers[i].value, Triggers[i].time, Triggers[i].num_links);
613 for (j=0; j<Triggers[i].num_links; j++)
614 fprintf(my_file, "[%03i:%i] ", Triggers[i].seg[j], Triggers[i].side[j]);
616 // Find which wall this trigger is connected to.
617 for (w=0; w<Num_walls; w++)
618 if (Walls[w].trigger == i)
622 err_printf(my_file, "\nError: Trigger %i is not connected to any wall, so it can never be triggered.\n", i);
624 fprintf(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);
630 // ----------------------------------------------------------------------------
631 void write_game_text_file(char *filename)
633 char my_filename[128];
639 // mprintf((0, "Writing text file for mine [%s]\n", filename));
641 namelen = strlen(filename);
643 Assert (namelen > 4);
645 Assert (filename[namelen-4] == '.');
647 strcpy(my_filename, filename);
648 strcpy( &my_filename[namelen-4], ".txm");
650 // mprintf((0, "Writing text file [%s]\n", my_filename));
652 my_file = fopen( my_filename, "wt" );
653 // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
656 char ErrorMessage[200];
658 sprintf( ErrorMessage, "ERROR: Unable to open %s\nErrno = %i", my_file, errno );
660 gr_palette_load(gr_palette);
661 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
667 dump_used_textures_level(my_file, 0);
668 say_totals(my_file, Gamesave_current_filename);
670 fprintf(my_file, "\nNumber of segments: %4i\n", Highest_segment_index+1);
671 fprintf(my_file, "Number of objects: %4i\n", Highest_object_index+1);
672 fprintf(my_file, "Number of walls: %4i\n", Num_walls);
673 fprintf(my_file, "Number of open doors: %4i\n", Num_open_doors);
674 fprintf(my_file, "Number of triggers: %4i\n", Num_triggers);
675 fprintf(my_file, "Number of matcens: %4i\n", Num_robot_centers);
676 fprintf(my_file, "\n");
678 write_segment_text(my_file);
680 write_fuelcen_text(my_file);
682 write_matcen_text(my_file);
684 write_player_text(my_file);
686 write_wall_text(my_file);
688 write_trigger_text(my_file);
690 write_exit_text(my_file);
692 // ---------- Find control center segment ----------
693 write_control_center_text(my_file);
695 // ---------- Show keyed walls ----------
696 write_key_text(my_file);
700 mprintf((1, "Close value = %i\n", r));
706 // -- // ---------------
707 // -- // Note: This only works for a loaded level because the objects array must be valid.
708 // -- void determine_used_textures_robots(int *tmap_buf)
713 // -- Assert(N_polygon_models);
715 // -- for (objnum=0; objnum <= Highest_object_index; objnum++) {
718 // -- if (Objects[objnum].render_type == RT_POLYOBJ) {
719 // -- model_num = Objects[objnum].rtype.pobj_info.model_num;
721 // -- po=&Polygon_models[model_num];
723 // -- for (i=0;i<po->n_textures;i++) {
726 // -- tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
727 // -- Assert((tli>=0) && (tli<= Num_tmaps));
728 // -- tmap_buf[tli]++;
735 // --05/17/95--// -----------------------------------------------------------------------------
736 // --05/17/95--void determine_used_textures_level(int load_level_flag, int shareware_flag, int level_num, int *tmap_buf, int *wall_buf, byte *level_tmap_buf, int max_tmap)
738 // --05/17/95-- int segnum, sidenum;
739 // --05/17/95-- int i, j;
741 // --05/17/95-- for (i=0; i<max_tmap; i++)
742 // --05/17/95-- tmap_buf[i] = 0;
744 // --05/17/95-- if (load_level_flag) {
745 // --05/17/95-- if (shareware_flag)
746 // --05/17/95-- load_level(Shareware_level_names[level_num]);
748 // --05/17/95-- load_level(Registered_level_names[level_num]);
751 // --05/17/95-- for (segnum=0; segnum<=Highest_segment_index; segnum++) {
752 // --05/17/95-- segment *segp = &Segments[segnum];
754 // --05/17/95-- for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
755 // --05/17/95-- side *sidep = &segp->sides[sidenum];
757 // --05/17/95-- if (sidep->wall_num != -1) {
758 // --05/17/95-- int clip_num = Walls[sidep->wall_num].clip_num;
759 // --05/17/95-- if (clip_num != -1) {
761 // --05/17/95-- int num_frames = WallAnims[clip_num].num_frames;
763 // --05/17/95-- wall_buf[clip_num] = 1;
765 // --05/17/95-- for (j=0; j<num_frames; j++) {
766 // --05/17/95-- int tmap_num;
768 // --05/17/95-- tmap_num = WallAnims[clip_num].frames[j];
769 // --05/17/95-- tmap_buf[tmap_num]++;
770 // --05/17/95-- if (level_tmap_buf[tmap_num] == -1)
771 // --05/17/95-- level_tmap_buf[tmap_num] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS;
776 // --05/17/95-- if (sidep->tmap_num >= 0)
777 // --05/17/95-- if (sidep->tmap_num < max_tmap) {
778 // --05/17/95-- tmap_buf[sidep->tmap_num]++;
779 // --05/17/95-- if (level_tmap_buf[sidep->tmap_num] == -1)
780 // --05/17/95-- level_tmap_buf[sidep->tmap_num] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS;
781 // --05/17/95-- } else
782 // --05/17/95-- Int3(); // Error, bogus texture map. Should not be greater than max_tmap.
784 // --05/17/95-- if ((sidep->tmap_num2 & 0x3fff) != 0)
785 // --05/17/95-- if ((sidep->tmap_num2 & 0x3fff) < max_tmap) {
786 // --05/17/95-- tmap_buf[sidep->tmap_num2 & 0x3fff]++;
787 // --05/17/95-- if (level_tmap_buf[sidep->tmap_num2 & 0x3fff] == -1)
788 // --05/17/95-- level_tmap_buf[sidep->tmap_num2 & 0x3fff] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS;
789 // --05/17/95-- } else
790 // --05/17/95-- Int3(); // Error, bogus texture map. Should not be greater than max_tmap.
795 // Adam: Change NUM_ADAM_LEVELS to the number of levels.
796 #define NUM_ADAM_LEVELS 30
798 // Adam: Stick the names here.
799 char *Adam_level_names[NUM_ADAM_LEVELS] = {
837 typedef struct BitmapFile {
841 extern BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
843 int Ignore_tmap_num2_error;
845 // ----------------------------------------------------------------------------
846 void determine_used_textures_level(int load_level_flag, int shareware_flag, int level_num, int *tmap_buf, int *wall_buf, byte *level_tmap_buf, int max_tmap)
848 int segnum, sidenum, objnum=max_tmap;
851 Assert(shareware_flag != -17);
853 for (i=0; i<MAX_BITMAP_FILES; i++)
856 if (load_level_flag) {
857 load_level(Adam_level_names[level_num]);
862 for (objnum=0; objnum<=Highest_object_index; objnum++) {
863 object *objp = &Objects[objnum];
865 if (objp->render_type == RT_POLYOBJ) {
866 polymodel *po = &Polygon_models[objp->rtype.pobj_info.model_num];
868 for (i=0; i<po->n_textures; i++) {
870 int tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index;
871 // -- mprintf((0, "%s ", AllBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index].name));
873 if ((tli < MAX_BITMAP_FILES) && (tli >= 0)) {
875 if (level_tmap_buf[tli] == -1)
876 level_tmap_buf[tli] = level_num;
878 Int3(); // Hmm, It seems this texture is bogus!
885 Ignore_tmap_num2_error = 0;
887 // Process walls and segment sides.
888 for (segnum=0; segnum<=Highest_segment_index; segnum++) {
889 segment *segp = &Segments[segnum];
891 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
892 side *sidep = &segp->sides[sidenum];
894 if (sidep->wall_num != -1) {
895 int clip_num = Walls[sidep->wall_num].clip_num;
896 if (clip_num != -1) {
898 // -- int num_frames = WallAnims[clip_num].num_frames;
900 wall_buf[clip_num] = 1;
902 for (j=0; j<1; j++) { // Used to do through num_frames, but don't really want all the door01#3 stuff.
905 tmap_num = Textures[WallAnims[clip_num].frames[j]].index;
906 Assert((tmap_num >= 0) && (tmap_num < MAX_BITMAP_FILES));
907 tmap_buf[tmap_num]++;
908 if (level_tmap_buf[tmap_num] == -1)
909 level_tmap_buf[tmap_num] = level_num;
912 } else if (segp->children[sidenum] == -1) {
914 if (sidep->tmap_num >= 0)
915 if (sidep->tmap_num < MAX_BITMAP_FILES) {
916 Assert(Textures[sidep->tmap_num].index < MAX_BITMAP_FILES);
917 tmap_buf[Textures[sidep->tmap_num].index]++;
918 if (level_tmap_buf[Textures[sidep->tmap_num].index] == -1)
919 level_tmap_buf[Textures[sidep->tmap_num].index] = level_num;
921 Int3(); // Error, bogus texture map. Should not be greater than max_tmap.
923 if ((sidep->tmap_num2 & 0x3fff) != 0)
924 if ((sidep->tmap_num2 & 0x3fff) < MAX_BITMAP_FILES) {
925 Assert(Textures[sidep->tmap_num2 & 0x3fff].index < MAX_BITMAP_FILES);
926 tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index]++;
927 if (level_tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index] == -1)
928 level_tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index] = level_num;
930 if (!Ignore_tmap_num2_error)
931 Int3(); // Error, bogus texture map. Should not be greater than max_tmap.
932 Ignore_tmap_num2_error = 1;
933 sidep->tmap_num2 = 0;
940 // ----------------------------------------------------------------------------
941 void merge_buffers(int *dest, int *src, int num)
945 for (i=0; i<num; i++)
950 // ----------------------------------------------------------------------------
951 void say_used_tmaps(FILE *my_file, int *tb)
954 // -- mk, 08/14/95 -- int count = 0;
956 for (i=0; i<MAX_BITMAP_FILES; i++)
958 fprintf(my_file, "[%3i %8s (%4i)]\n", i, AllBitmaps[i].name, tb[i]);
959 // -- mk, 08/14/95 -- if (count++ >= 4) {
960 // -- mk, 08/14/95 -- fprintf(my_file, "\n");
961 // -- mk, 08/14/95 -- count = 0;
962 // -- mk, 08/14/95 -- }
966 // --05/17/95--// -----------------------------------------------------------------------------
967 // --05/17/95--void say_used_once_tmaps(FILE *my_file, int *tb, byte *tb_lnum)
969 // --05/17/95-- int i;
970 // --05/17/95-- char *level_name;
972 // --05/17/95-- for (i=0; i<Num_tmaps; i++)
973 // --05/17/95-- if (tb[i] == 1) {
974 // --05/17/95-- int level_num = tb_lnum[i];
975 // --05/17/95-- if (level_num >= NUM_SHAREWARE_LEVELS) {
976 // --05/17/95-- Assert((level_num - NUM_SHAREWARE_LEVELS >= 0) && (level_num - NUM_SHAREWARE_LEVELS < NUM_REGISTERED_LEVELS));
977 // --05/17/95-- level_name = Registered_level_names[level_num - NUM_SHAREWARE_LEVELS];
978 // --05/17/95-- } else {
979 // --05/17/95-- Assert((level_num >= 0) && (level_num < NUM_SHAREWARE_LEVELS));
980 // --05/17/95-- level_name = Shareware_level_names[level_num];
983 // --05/17/95-- fprintf(my_file, "Texture %3i %8s used only once on level %s\n", i, TmapInfo[i].filename, level_name);
987 // ----------------------------------------------------------------------------
988 void say_used_once_tmaps(FILE *my_file, int *tb, byte *tb_lnum)
993 for (i=0; i<MAX_BITMAP_FILES; i++)
995 int level_num = tb_lnum[i];
996 level_name = Adam_level_names[level_num];
998 fprintf(my_file, "Texture %3i %8s used only once on level %s\n", i, AllBitmaps[i].name, level_name);
1002 // ----------------------------------------------------------------------------
1003 void say_unused_tmaps(FILE *my_file, int *tb)
1008 for (i=0; i<MAX_BITMAP_FILES; i++)
1010 if (GameBitmaps[Textures[i].index].bm_data == &bogus_data)
1011 fprintf(my_file, "U");
1013 fprintf(my_file, " ");
1015 fprintf(my_file, "[%3i %8s] ", i, AllBitmaps[i].name);
1017 fprintf(my_file, "\n");
1023 // ----------------------------------------------------------------------------
1024 void say_unused_walls(FILE *my_file, int *tb)
1028 for (i=0; i<Num_wall_anims; i++)
1030 fprintf(my_file, "Wall %3i is unused.\n", i);
1033 // ----------------------------------------------------------------------------
1034 say_totals(FILE *my_file, char *level_name)
1037 int total_robots = 0;
1038 int objects_processed = 0;
1040 int used_objects[MAX_OBJECTS];
1042 fprintf(my_file, "\nLevel %s\n", level_name);
1044 for (i=0; i<MAX_OBJECTS; i++)
1045 used_objects[i] = 0;
1047 while (objects_processed < Highest_object_index+1) {
1048 int j, objtype, objid, objcount, cur_obj_val, min_obj_val, min_objnum;
1050 // Find new min objnum.
1051 min_obj_val = 0x7fff0000;
1054 for (j=0; j<=Highest_object_index; j++) {
1055 if (!used_objects[j] && Objects[j].type!=OBJ_NONE) {
1056 cur_obj_val = Objects[j].type * 1000 + Objects[j].id;
1057 if (cur_obj_val < min_obj_val) {
1059 min_obj_val = cur_obj_val;
1063 if ((min_objnum == -1) || (Objects[min_objnum].type == 255))
1068 objtype = Objects[min_objnum].type;
1069 objid = Objects[min_objnum].id;
1071 for (i=0; i<=Highest_object_index; i++) {
1072 if (!used_objects[i]) {
1074 if (((Objects[i].type == objtype) && (Objects[i].id == objid)) ||
1075 ((Objects[i].type == objtype) && (objtype == OBJ_PLAYER)) ||
1076 ((Objects[i].type == objtype) && (objtype == OBJ_COOP)) ||
1077 ((Objects[i].type == objtype) && (objtype == OBJ_HOSTAGE))) {
1078 if (Objects[i].type == OBJ_ROBOT)
1080 used_objects[i] = 1;
1082 objects_processed++;
1088 fprintf(my_file, "Object: ");
1089 fprintf(my_file, "%8s %8s %3i\n", object_types(min_objnum), object_ids(min_objnum), objcount);
1093 fprintf(my_file, "Total robots = %3i\n", total_robots);
1096 int First_dump_level = 0;
1097 int Last_dump_level = NUM_ADAM_LEVELS-1;
1099 // ----------------------------------------------------------------------------
1100 void say_totals_all(void)
1105 my_file = fopen( "levels.all", "wt" );
1106 // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
1109 char ErrorMessage[200];
1111 sprintf( ErrorMessage, "ERROR: Unable to open levels.all\nErrno=%i", errno );
1113 gr_palette_load(gr_palette);
1114 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
1120 for (i=First_dump_level; i<=Last_dump_level; i++) {
1121 mprintf((0, "Level %i\n", i+1));
1122 load_level(Adam_level_names[i]);
1123 say_totals(my_file, Adam_level_names[i]);
1126 //--05/17/95-- for (i=0; i<NUM_SHAREWARE_LEVELS; i++) {
1127 //--05/17/95-- mprintf((0, "Level %i\n", i+1));
1128 //--05/17/95-- load_level(Shareware_level_names[i]);
1129 //--05/17/95-- say_totals(my_file, Shareware_level_names[i]);
1132 //--05/17/95-- for (i=0; i<NUM_REGISTERED_LEVELS; i++) {
1133 //--05/17/95-- mprintf((0, "Level %i\n", i+1+NUM_SHAREWARE_LEVELS));
1134 //--05/17/95-- load_level(Registered_level_names[i]);
1135 //--05/17/95-- say_totals(my_file, Registered_level_names[i]);
1142 void dump_used_textures_level(FILE *my_file, int level_num)
1145 int temp_tmap_buf[MAX_BITMAP_FILES];
1146 int perm_tmap_buf[MAX_BITMAP_FILES];
1147 byte level_tmap_buf[MAX_BITMAP_FILES];
1148 int temp_wall_buf[MAX_BITMAP_FILES];
1149 int perm_wall_buf[MAX_BITMAP_FILES];
1151 for (i=0; i<MAX_BITMAP_FILES; i++) {
1152 perm_tmap_buf[i] = 0;
1153 level_tmap_buf[i] = -1;
1156 for (i=0; i<MAX_BITMAP_FILES; i++) {
1157 perm_wall_buf[i] = 0;
1160 determine_used_textures_level(0, 1, level_num, temp_tmap_buf, temp_wall_buf, level_tmap_buf, MAX_BITMAP_FILES);
1161 // -- determine_used_textures_robots(temp_tmap_buf);
1162 fprintf(my_file, "\nTextures used in [%s]\n", Gamesave_current_filename);
1163 say_used_tmaps(my_file, temp_tmap_buf);
1168 // ----------------------------------------------------------------------------
1169 void dump_used_textures_all(void)
1172 int temp_tmap_buf[MAX_BITMAP_FILES];
1173 int perm_tmap_buf[MAX_BITMAP_FILES];
1174 byte level_tmap_buf[MAX_BITMAP_FILES];
1175 int temp_wall_buf[MAX_BITMAP_FILES];
1176 int perm_wall_buf[MAX_BITMAP_FILES];
1180 my_file = fopen( "textures.dmp", "wt" );
1181 // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
1184 char ErrorMessage[200];
1186 sprintf( ErrorMessage, "ERROR: Can't open textures.dmp\nErrno=%i", errno);
1188 gr_palette_load(gr_palette);
1189 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
1195 for (i=0; i<MAX_BITMAP_FILES; i++) {
1196 perm_tmap_buf[i] = 0;
1197 level_tmap_buf[i] = -1;
1200 for (i=0; i<MAX_BITMAP_FILES; i++) {
1201 perm_wall_buf[i] = 0;
1204 // --05/17/95-- for (i=0; i<NUM_SHAREWARE_LEVELS; i++) {
1205 // --05/17/95-- determine_used_textures_level(1, 1, i, temp_tmap_buf, temp_wall_buf, level_tmap_buf, MAX_BITMAP_FILES);
1206 // --05/17/95-- fprintf(my_file, "\nTextures used in [%s]\n", Shareware_level_names[i]);
1207 // --05/17/95-- say_used_tmaps(my_file, temp_tmap_buf);
1208 // --05/17/95-- merge_buffers(perm_tmap_buf, temp_tmap_buf, MAX_BITMAP_FILES);
1209 // --05/17/95-- merge_buffers(perm_wall_buf, temp_wall_buf, MAX_BITMAP_FILES);
1212 // --05/17/95-- fprintf(my_file, "\n\nUsed textures in all shareware mines:\n");
1213 // --05/17/95-- say_used_tmaps(my_file, perm_tmap_buf);
1215 // --05/17/95-- fprintf(my_file, "\nUnused textures in all shareware mines:\n");
1216 // --05/17/95-- say_unused_tmaps(my_file, perm_tmap_buf);
1218 // --05/17/95-- fprintf(my_file, "\nTextures used exactly once in all shareware mines:\n");
1219 // --05/17/95-- say_used_once_tmaps(my_file, perm_tmap_buf, level_tmap_buf);
1221 // --05/17/95-- fprintf(my_file, "\nWall anims (eg, doors) unused in all shareware mines:\n");
1222 // --05/17/95-- say_unused_walls(my_file, perm_wall_buf);
1224 // --05/17/95-- for (i=0; i<NUM_REGISTERED_LEVELS; i++) {
1225 // --05/17/95-- determine_used_textures_level(1, 0, i, temp_tmap_buf, temp_wall_buf, level_tmap_buf, MAX_BITMAP_FILES);
1226 // --05/17/95-- fprintf(my_file, "\nTextures used in [%s]\n", Registered_level_names[i]);
1227 // --05/17/95-- say_used_tmaps(my_file, temp_tmap_buf);
1228 // --05/17/95-- merge_buffers(perm_tmap_buf, temp_tmap_buf, MAX_BITMAP_FILES);
1231 // --05/17/95-- fprintf(my_file, "\n\nUsed textures in all (including registered) mines:\n");
1232 // --05/17/95-- say_used_tmaps(my_file, perm_tmap_buf);
1234 // --05/17/95-- fprintf(my_file, "\nUnused textures in all (including registered) mines:\n");
1235 // --05/17/95-- say_unused_tmaps(my_file, perm_tmap_buf);
1237 for (i=First_dump_level; i<=Last_dump_level; i++) {
1238 determine_used_textures_level(1, 0, i, temp_tmap_buf, temp_wall_buf, level_tmap_buf, MAX_BITMAP_FILES);
1239 fprintf(my_file, "\nTextures used in [%s]\n", Adam_level_names[i]);
1240 say_used_tmaps(my_file, temp_tmap_buf);
1241 merge_buffers(perm_tmap_buf, temp_tmap_buf, MAX_BITMAP_FILES);
1244 fprintf(my_file, "\n\nUsed textures in all (including registered) mines:\n");
1245 say_used_tmaps(my_file, perm_tmap_buf);
1247 fprintf(my_file, "\nUnused textures in all (including registered) mines:\n");
1248 say_unused_tmaps(my_file, perm_tmap_buf);