]> icculus.org git repositories - btb/d2x.git/blob - main/dumpmine.c
fix level number position
[btb/d2x.git] / main / dumpmine.c
1 /* $Id: dumpmine.c,v 1.4 2003-10-10 09:36:34 btb Exp $ */
2 /*
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.
13 */
14
15 /*
16  *
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.
20  *
21  * Old Log:
22  * Revision 1.1  1995/05/16  15:24:16  allender
23  * Initial revision
24  *
25  * Revision 2.1  1995/04/06  12:21:50  mike
26  * Add texture map information to txm files.
27  *
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.
31  *
32  * Revision 1.24  1995/01/23  15:34:43  mike
33  * New diagnostic code, levels.all stuff.
34  *
35  * Revision 1.23  1994/12/20  17:56:36  yuan
36  * Multiplayer object capability.
37  *
38  * Revision 1.22  1994/11/27  23:12:19  matt
39  * Made changes for new mprintf calling convention
40  *
41  * Revision 1.21  1994/11/23  12:19:04  mike
42  * move out level names, stick in gamesave.
43  *
44  * Revision 1.20  1994/11/21  16:54:36  mike
45  * oops.
46  *
47  *
48  * Revision 1.19  1994/11/20  22:12:55  mike
49  * Lotsa new stuff in this fine debug file.
50  *
51  * Revision 1.18  1994/11/17  14:58:09  mike
52  * moved segment validation functions from editor to main.
53  *
54  * Revision 1.17  1994/11/15  21:43:02  mike
55  * texture usage system.
56  *
57  * Revision 1.16  1994/11/15  12:45:59  mike
58  * debug code for dumping texture info.
59  *
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.
63  *
64  * Revision 1.14  1994/10/14  17:33:38  mike
65  * Fix error reporting for number of multiplayer objects in mine.
66  *
67  * Revision 1.13  1994/10/14  13:37:46  mike
68  * Forgot parameter in fprintf, was getting bogus number of excess keys.
69  *
70  * Revision 1.12  1994/10/12  08:05:33  mike
71  * Detect keys contained in objects for error checking (txm file).
72  *
73  * Revision 1.11  1994/10/10  17:02:08  mike
74  * fix fix.
75  *
76  * Revision 1.10  1994/10/10  17:00:37  mike
77  * Add checking for proper number of players.
78  *
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.
81  *
82  * Revision 1.8  1994/09/30  17:15:29  mike
83  * Fix error message, was telling bogus filename.
84  *
85  * Revision 1.7  1994/09/30  11:50:55  mike
86  * More diagnostics.
87  *
88  * Revision 1.6  1994/09/28  17:31:19  mike
89  * More error checking.
90  *
91  * Revision 1.5  1994/09/28  11:14:05  mike
92  * Better checking on bogus walls.
93  *
94  * Revision 1.4  1994/09/28  09:23:50  mike
95  * Change some Error messages to Warnings.
96  *
97  * Revision 1.3  1994/09/27  17:08:31  mike
98  * More mine validation stuff.
99  *
100  * Revision 1.2  1994/09/27  15:43:22  mike
101  * The amazing code to tell you everything and more about our mines!
102  *
103  * Revision 1.1  1994/09/27  10:51:15  mike
104  * Initial revision
105  *
106  *
107  */
108
109 #ifdef HAVE_CONFIG_H
110 #include <conf.h>
111 #endif
112
113 #ifdef RCS
114 static char rcsid[] = "$Id: dumpmine.c,v 1.4 2003-10-10 09:36:34 btb Exp $";
115 #endif
116
117 #include <stdio.h>
118 #include <string.h>
119 #include <stdarg.h>
120 #include <errno.h>
121
122 #include "pstypes.h"
123 #include "mono.h"
124 #include "key.h"
125 #include "gr.h"
126 #include "palette.h"
127
128 #include "inferno.h"
129 #ifdef EDITOR
130 #include "editor/editor.h"
131 #endif
132 #include "error.h"
133 #include "object.h"
134 #include "wall.h"
135 #include "gamemine.h"
136 #include "robot.h"
137 #include "player.h"
138 #include "newmenu.h"
139 #include "textures.h"
140
141 #include "bm.h"
142 #include "menu.h"
143 #include "switch.h"
144 #include "fuelcen.h"
145 #include "powerup.h"
146 #include "gameseq.h"
147 #include "polyobj.h"
148 #include "gamesave.h"
149
150
151 #ifdef EDITOR
152
153 extern ubyte bogus_data[64*64];
154 extern grs_bitmap bogus_bitmap;
155
156 // ----------------------------------------------------------------------------
157 char    *object_types(int objnum)
158 {
159         int     type = Objects[objnum].type;
160
161         Assert((type >= 0) && (type < MAX_OBJECT_TYPES));
162         return  &Object_type_names[type];
163 }
164
165 // ----------------------------------------------------------------------------
166 char    *object_ids(int objnum)
167 {
168         int     type = Objects[objnum].type;
169         int     id = Objects[objnum].id;
170
171         switch (type) {
172                 case OBJ_ROBOT:
173                         return &Robot_names[id];
174                         break;
175                 case OBJ_POWERUP:
176                         return &Powerup_names[id];
177                         break;
178         }
179
180         return  NULL;
181 }
182
183 void err_printf(FILE *my_file, char * format, ... )
184 {
185         va_list args;
186         char            message[256];
187
188         va_start(args, format );
189         vsprintf(message,format,args);
190         va_end(args);
191
192         mprintf((1, "%s", message));
193         fprintf(my_file, "%s", message);
194         Errors_in_mine++;
195 }
196
197 void warning_printf(FILE *my_file, char * format, ... )
198 {
199         va_list args;
200         char            message[256];
201
202         va_start(args, format );
203         vsprintf(message,format,args);
204         va_end(args);
205
206         mprintf((0, "%s", message));
207         fprintf(my_file, "%s", message);
208 }
209
210 // ----------------------------------------------------------------------------
211 void write_exit_text(FILE *my_file)
212 {
213         int     i, j, count;
214
215         fprintf(my_file, "-----------------------------------------------------------------------------\n");
216         fprintf(my_file, "Exit stuff\n");
217
218         //      ---------- Find exit triggers ----------
219         count=0;
220         for (i=0; i<Num_triggers; i++)
221                 if (Triggers[i].type == TT_EXIT) {
222                         int     count2;
223
224                         fprintf(my_file, "Trigger %2i, is an exit trigger with %i links.\n", i, Triggers[i].num_links);
225                         count++;
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);
228
229                         //      Find wall pointing to this trigger.
230                         count2 = 0;
231                         for (j=0; j<Num_walls; j++)
232                                 if (Walls[j].trigger == i) {
233                                         count2++;
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);
235                                 }
236                         if (count2 == 0)
237                                 err_printf(my_file, "Error: Trigger %i is not bound to any wall.\n", i);
238                         else if (count2 > 1)
239                                 err_printf(my_file, "Error: Trigger %i is bound to %i walls.\n", i, count2);
240
241                 }
242
243         if (count == 0)
244                 err_printf(my_file, "Error: No exit trigger in this mine.\n");
245         else if (count != 1)
246                 err_printf(my_file, "Error: More than one exit trigger in this mine.\n");
247         else
248                 fprintf(my_file, "\n");
249
250         //      ---------- Find exit doors ----------
251         count = 0;
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);
256                                 count++;
257                         }
258
259         if (count == 0)
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);
264         } else
265                 fprintf(my_file, "\n");
266 }
267
268 // ----------------------------------------------------------------------------
269 void write_key_text(FILE *my_file)
270 {
271         int     i;
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;
275         int     connect_side;
276
277         fprintf(my_file, "-----------------------------------------------------------------------------\n");
278         fprintf(my_file, "Key stuff:\n");
279
280         red_count = 0;
281         blue_count = 0;
282         gold_count = 0;
283
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;
290                                 blue_count++;
291                         } else {
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);
295                                         blue_count++;
296                                 }
297                         }
298                 }
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;
304                                 red_count++;
305                         } else {
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);
309                                         red_count++;
310                                 }
311                         }
312                 }
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;
318                                 gold_count++;
319                         } else {
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);
323                                         gold_count++;
324                                 }
325                         }
326                 }
327         }
328
329         if (blue_count > 1)
330                 warning_printf(my_file, "Warning: %i doors are keyed to the blue key.\n", blue_count);
331
332         if (red_count > 1)
333                 warning_printf(my_file, "Warning: %i doors are keyed to the red key.\n", red_count);
334
335         if (gold_count > 1)
336                 warning_printf(my_file, "Warning: %i doors are keyed to the gold key.\n", gold_count);
337
338         red_count2 = 0;
339         blue_count2 = 0;
340         gold_count2 = 0;
341
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);
346                                 blue_count2++;
347                         }
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);
351                                 red_count2++;
352                         }
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);
356                                 gold_count2++;
357                         }
358
359                 if (Objects[i].contains_count) {
360                         if (Objects[i].contains_type == OBJ_POWERUP) {
361                                 switch (Objects[i].contains_id) {
362                                         case POW_KEY_BLUE:
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;
365                                                 break;
366                                         case POW_KEY_GOLD:
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;
369                                                 break;
370                                         case POW_KEY_RED:
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;
373                                                 break;
374                                         default:
375                                                 break;
376                                 }
377                         }
378                 }
379         }
380
381         if (blue_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");
384
385         if (red_count)
386                 if (red_count2 == 0)
387                         err_printf(my_file, "Error: There is a door keyed to the red key, but no red key!\n");
388
389         if (gold_count)
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");
392
393         if (blue_count2 > 1)
394                 err_printf(my_file, "Error: There are %i blue keys!\n", blue_count2);
395
396         if (red_count2 > 1)
397                 err_printf(my_file, "Error: There are %i red keys!\n", red_count2);
398
399         if (gold_count2 > 1)
400                 err_printf(my_file, "Error: There are %i gold keys!\n", gold_count2);
401 }
402
403 // ----------------------------------------------------------------------------
404 void write_control_center_text(FILE *my_file)
405 {
406         int     i, count, objnum, count2;
407
408         fprintf(my_file, "-----------------------------------------------------------------------------\n");
409         fprintf(my_file, "Control Center stuff:\n");
410
411         count = 0;
412         for (i=0; i<=Highest_segment_index; i++)
413                 if (Segment2s[i].special == SEGMENT_IS_CONTROLCEN) {
414                         count++;
415                         fprintf(my_file, "Segment %3i is a control center.\n", i);
416                         objnum = Segments[i].objects;
417                         count2 = 0;
418                         while (objnum != -1) {
419                                 if (Objects[objnum].type == OBJ_CNTRLCEN)
420                                         count2++;
421                                 objnum = Objects[objnum].next;
422                         }
423                         if (count2 == 0)
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);
427                 }
428
429         if (count == 0)
430                 err_printf(my_file, "Error: No control center in this mine.\n");
431         else if (count != 1)
432                 err_printf(my_file, "Error: More than one control center in this mine.\n");
433 }
434
435 // ----------------------------------------------------------------------------
436 void write_fuelcen_text(FILE *my_file)
437 {
438         int     i;
439
440         fprintf(my_file, "-----------------------------------------------------------------------------\n");
441         fprintf(my_file, "Fuel Center stuff: (Note: This means fuel, repair, materialize, control centers!)\n");
442
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);
447         }
448 }
449
450 // ----------------------------------------------------------------------------
451 void write_segment_text(FILE *my_file)
452 {
453         int     i, objnum;
454
455         fprintf(my_file, "-----------------------------------------------------------------------------\n");
456         fprintf(my_file, "Segment stuff:\n");
457
458         for (i=0; i<=Highest_segment_index; i++) {
459
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);
463
464                 if (Segment2s[i].matcen_num != -1)
465                         fprintf(my_file, "matcen = %3i, ", Segment2s[i].matcen_num);
466                 
467                 fprintf(my_file, "\n");
468         }
469
470         for (i=0; i<=Highest_segment_index; i++) {
471                 int     depth;
472
473                 objnum = Segments[i].objects;
474                 fprintf(my_file, "Segment %4i: ", i);
475                 depth=0;
476                 if (objnum != -1) {
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;
481                                 if (depth++ > 30) {
482                                         fprintf(my_file, "\nAborted after %i links\n", depth);
483                                         break;
484                                 }
485                         }
486                 }
487                 fprintf(my_file, "\n");
488         }
489 }
490
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)
495 {
496         int     i, j, k;
497
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;
502
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);
505
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]);
509
510                 segnum = Station[fuelcen_num].segnum;
511
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 );
518                                                 trigger_count++;
519                                         }
520                         }
521                 }
522                 fprintf(my_file, "\n");
523
524                 if (trigger_count == 0)
525                         err_printf(my_file, "Error: Matcen %i in segment %i has no trigger!\n", i, segnum);
526
527         }
528 }
529
530 // ----------------------------------------------------------------------------
531 void write_wall_text(FILE *my_file)
532 {
533         int     i, j;
534         byte    wall_flags[MAX_WALLS];
535
536         fprintf(my_file, "-----------------------------------------------------------------------------\n");
537         fprintf(my_file, "Walls:\n");
538         for (i=0; i<Num_walls; i++) {
539                 int     segnum, sidenum;
540
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);
543
544                 if (Walls[i].trigger >= Num_triggers)
545                         fprintf(my_file, "Wall %03d points to invalid trigger %d\n",i,Walls[i].trigger);
546
547                 segnum = Walls[i].segnum;
548                 sidenum = Walls[i].sidenum;
549
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);
552         }
553
554         for (i=0; i<MAX_WALLS; i++)
555                 wall_flags[i] = 0;
556
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);
564                                 else
565                                         wall_flags[sidep->wall_num] = 1;
566                 }
567         }
568
569 }
570
571 //typedef struct trigger {
572 //      byte            type;
573 //      short           flags;
574 //      fix             value;
575 //      fix             time;
576 //      byte            link_num;
577 //      short   num_links;
578 //      short   seg[MAX_WALLS_PER_LINK];
579 //      short           side[MAX_WALLS_PER_LINK];
580 //      } trigger;
581
582 // ----------------------------------------------------------------------------
583 void write_player_text(FILE *my_file)
584 {
585         int     i, num_players=0;
586
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) {
591                         num_players++;
592                         fprintf(my_file, "Player %2i is object #%3i in segment #%3i.\n", Objects[i].id, i, Objects[i].segnum);
593                 }
594         }
595
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);
600 }
601
602 // ----------------------------------------------------------------------------
603 void write_trigger_text(FILE *my_file)
604 {
605         int     i, j, w;
606
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);
612
613                 for (j=0; j<Triggers[i].num_links; j++)
614                         fprintf(my_file, "[%03i:%i] ", Triggers[i].seg[j], Triggers[i].side[j]);
615
616                 //      Find which wall this trigger is connected to.
617                 for (w=0; w<Num_walls; w++)
618                         if (Walls[w].trigger == i)
619                                 break;
620
621                 if (w == Num_walls)
622                         err_printf(my_file, "\nError: Trigger %i is not connected to any wall, so it can never be triggered.\n", i);
623                 else
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);
625
626         }
627
628 }
629
630 // ----------------------------------------------------------------------------
631 void write_game_text_file(char *filename)
632 {
633         char    my_filename[128];
634         int     namelen;
635         FILE    * my_file;
636
637         Errors_in_mine = 0;
638
639         // mprintf((0, "Writing text file for mine [%s]\n", filename));
640
641         namelen = strlen(filename);
642
643         Assert (namelen > 4);
644
645         Assert (filename[namelen-4] == '.');
646
647         strcpy(my_filename, filename);
648         strcpy( &my_filename[namelen-4], ".txm");
649
650         // mprintf((0, "Writing text file [%s]\n", my_filename));
651
652         my_file = fopen( my_filename, "wt" );
653         // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
654
655         if (!my_file)   {
656                 char  ErrorMessage[200];
657
658                 sprintf( ErrorMessage, "ERROR: Unable to open %s\nErrno = %i", my_file, errno );
659                 stop_time();
660                 gr_palette_load(gr_palette);
661                 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
662                 start_time();
663
664                 return;
665         }
666
667         dump_used_textures_level(my_file, 0);
668         say_totals(my_file, Gamesave_current_filename);
669
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");
677
678         write_segment_text(my_file);
679
680         write_fuelcen_text(my_file);
681
682         write_matcen_text(my_file);
683
684         write_player_text(my_file);
685
686         write_wall_text(my_file);
687
688         write_trigger_text(my_file);
689
690         write_exit_text(my_file);
691
692         //      ---------- Find control center segment ----------
693         write_control_center_text(my_file);
694
695         //      ---------- Show keyed walls ----------
696         write_key_text(my_file);
697
698 { int r;
699         r = fclose(my_file);
700         mprintf((1, "Close value = %i\n", r));
701         if (r)
702                 Int3();
703 }
704 }
705
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)
709 // -- {
710 // --   int     i, objnum;
711 // --   polymodel       *po;
712 // --
713 // --   Assert(N_polygon_models);
714 // --
715 // --   for (objnum=0; objnum <= Highest_object_index; objnum++) {
716 // --           int     model_num;
717 // --
718 // --           if (Objects[objnum].render_type == RT_POLYOBJ) {
719 // --                   model_num = Objects[objnum].rtype.pobj_info.model_num;
720 // --
721 // --                   po=&Polygon_models[model_num];
722 // --
723 // --                   for (i=0;i<po->n_textures;i++)  {
724 // --                           int     tli;
725 // --
726 // --                           tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
727 // --                           Assert((tli>=0) && (tli<= Num_tmaps));
728 // --                           tmap_buf[tli]++;
729 // --                   }
730 // --           }
731 // --   }
732 // --
733 // -- }
734
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)
737 // --05/17/95--{
738 // --05/17/95-- int     segnum, sidenum;
739 // --05/17/95-- int     i, j;
740 // --05/17/95--
741 // --05/17/95-- for (i=0; i<max_tmap; i++)
742 // --05/17/95--         tmap_buf[i] = 0;
743 // --05/17/95--
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]);
747 // --05/17/95--         else
748 // --05/17/95--                 load_level(Registered_level_names[level_num]);
749 // --05/17/95-- }
750 // --05/17/95--
751 // --05/17/95-- for (segnum=0; segnum<=Highest_segment_index; segnum++) {
752 // --05/17/95--         segment *segp = &Segments[segnum];
753 // --05/17/95--
754 // --05/17/95--         for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
755 // --05/17/95--                 side    *sidep = &segp->sides[sidenum];
756 // --05/17/95--
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) {
760 // --05/17/95--
761 // --05/17/95--                                 int num_frames = WallAnims[clip_num].num_frames;
762 // --05/17/95--
763 // --05/17/95--                                 wall_buf[clip_num] = 1;
764 // --05/17/95--
765 // --05/17/95--                                 for (j=0; j<num_frames; j++) {
766 // --05/17/95--                                         int     tmap_num;
767 // --05/17/95--
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;
772 // --05/17/95--                                 }
773 // --05/17/95--                         }
774 // --05/17/95--                 }
775 // --05/17/95--
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.
783 // --05/17/95--
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.
791 // --05/17/95--         }
792 // --05/17/95-- }
793 // --05/17/95--}
794
795 //      Adam: Change NUM_ADAM_LEVELS to the number of levels.
796 #define NUM_ADAM_LEVELS 30
797
798 //      Adam: Stick the names here.
799 char *Adam_level_names[NUM_ADAM_LEVELS] = {
800         "D2LEVA-1.LVL",
801         "D2LEVA-2.LVL",
802         "D2LEVA-3.LVL",
803         "D2LEVA-4.LVL",
804         "D2LEVA-S.LVL",
805
806         "D2LEVB-1.LVL",
807         "D2LEVB-2.LVL",
808         "D2LEVB-3.LVL",
809         "D2LEVB-4.LVL",
810         "D2LEVB-S.LVL",
811
812         "D2LEVC-1.LVL",
813         "D2LEVC-2.LVL",
814         "D2LEVC-3.LVL",
815         "D2LEVC-4.LVL",
816         "D2LEVC-S.LVL",
817
818         "D2LEVD-1.LVL",
819         "D2LEVD-2.LVL",
820         "D2LEVD-3.LVL",
821         "D2LEVD-4.LVL",
822         "D2LEVD-S.LVL",
823
824         "D2LEVE-1.LVL",
825         "D2LEVE-2.LVL",
826         "D2LEVE-3.LVL",
827         "D2LEVE-4.LVL",
828         "D2LEVE-S.LVL",
829
830         "D2LEVF-1.LVL",
831         "D2LEVF-2.LVL",
832         "D2LEVF-3.LVL",
833         "D2LEVF-4.LVL",
834         "D2LEVF-S.LVL",
835 };
836
837 typedef struct BitmapFile       {
838         char                    name[15];
839 } BitmapFile;
840
841 extern BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
842
843 int     Ignore_tmap_num2_error;
844
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)
847 {
848         int     segnum, sidenum, objnum=max_tmap;
849         int     i, j;
850
851         Assert(shareware_flag != -17);
852
853         for (i=0; i<MAX_BITMAP_FILES; i++)
854                 tmap_buf[i] = 0;
855
856         if (load_level_flag) {
857                 load_level(Adam_level_names[level_num]);
858         }
859
860
861         //      Process robots.
862         for (objnum=0; objnum<=Highest_object_index; objnum++) {
863                 object *objp = &Objects[objnum];
864
865                 if (objp->render_type == RT_POLYOBJ) {
866                         polymodel *po = &Polygon_models[objp->rtype.pobj_info.model_num];
867
868                         for (i=0; i<po->n_textures; i++) {
869
870                                 int     tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index;
871                                 // -- mprintf((0, "%s  ", AllBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index].name));
872
873                                 if ((tli < MAX_BITMAP_FILES) && (tli >= 0)) {
874                                         tmap_buf[tli]++;
875                                         if (level_tmap_buf[tli] == -1)
876                                                 level_tmap_buf[tli] = level_num;
877                                 } else
878                                         Int3(); //      Hmm, It seems this texture is bogus!
879                         }
880
881                 }
882         }
883
884
885         Ignore_tmap_num2_error = 0;
886
887         //      Process walls and segment sides.
888         for (segnum=0; segnum<=Highest_segment_index; segnum++) {
889                 segment *segp = &Segments[segnum];
890
891                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
892                         side    *sidep = &segp->sides[sidenum];
893
894                         if (sidep->wall_num != -1) {
895                                 int clip_num = Walls[sidep->wall_num].clip_num;
896                                 if (clip_num != -1) {
897
898                                         // -- int num_frames = WallAnims[clip_num].num_frames;
899
900                                         wall_buf[clip_num] = 1;
901
902                                         for (j=0; j<1; j++) {   //      Used to do through num_frames, but don't really want all the door01#3 stuff.
903                                                 int     tmap_num;
904
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;
910                                         }
911                                 }
912                         } else if (segp->children[sidenum] == -1) {
913
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;
920                                         } else
921                                                 Int3(); //      Error, bogus texture map.  Should not be greater than max_tmap.
922
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;
929                                         } else {
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;
934                                         }
935                         }
936                 }
937         }
938 }
939
940 // ----------------------------------------------------------------------------
941 void merge_buffers(int *dest, int *src, int num)
942 {
943         int     i;
944
945         for (i=0; i<num; i++)
946                 if (src[i])
947                         dest[i] += src[i];
948 }
949
950 // ----------------------------------------------------------------------------
951 void say_used_tmaps(FILE *my_file, int *tb)
952 {
953         int     i;
954 // -- mk, 08/14/95 --   int     count = 0;
955
956         for (i=0; i<MAX_BITMAP_FILES; i++)
957                 if (tb[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 --                   }
963                 }
964 }
965
966 // --05/17/95--//       -----------------------------------------------------------------------------
967 // --05/17/95--void say_used_once_tmaps(FILE *my_file, int *tb, byte *tb_lnum)
968 // --05/17/95--{
969 // --05/17/95-- int     i;
970 // --05/17/95-- char    *level_name;
971 // --05/17/95--
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];
981 // --05/17/95--                 }
982 // --05/17/95--
983 // --05/17/95--                 fprintf(my_file, "Texture %3i %8s used only once on level %s\n", i, TmapInfo[i].filename, level_name);
984 // --05/17/95--         }
985 // --05/17/95--}
986
987 // ----------------------------------------------------------------------------
988 void say_used_once_tmaps(FILE *my_file, int *tb, byte *tb_lnum)
989 {
990         int     i;
991         char    *level_name;
992
993         for (i=0; i<MAX_BITMAP_FILES; i++)
994                 if (tb[i] == 1) {
995                         int     level_num = tb_lnum[i];
996                         level_name = Adam_level_names[level_num];
997
998                         fprintf(my_file, "Texture %3i %8s used only once on level %s\n", i, AllBitmaps[i].name, level_name);
999                 }
1000 }
1001
1002 // ----------------------------------------------------------------------------
1003 void say_unused_tmaps(FILE *my_file, int *tb)
1004 {
1005         int     i;
1006         int     count = 0;
1007
1008         for (i=0; i<MAX_BITMAP_FILES; i++)
1009                 if (!tb[i]) {
1010                         if (GameBitmaps[Textures[i].index].bm_data == &bogus_data)
1011                                 fprintf(my_file, "U");
1012                         else
1013                                 fprintf(my_file, " ");
1014
1015                         fprintf(my_file, "[%3i %8s] ", i, AllBitmaps[i].name);
1016                         if (count++ >= 4) {
1017                                 fprintf(my_file, "\n");
1018                                 count = 0;
1019                         }
1020                 }
1021 }
1022
1023 // ----------------------------------------------------------------------------
1024 void say_unused_walls(FILE *my_file, int *tb)
1025 {
1026         int     i;
1027
1028         for (i=0; i<Num_wall_anims; i++)
1029                 if (!tb[i])
1030                         fprintf(my_file, "Wall %3i is unused.\n", i);
1031 }
1032
1033 // ----------------------------------------------------------------------------
1034 say_totals(FILE *my_file, char *level_name)
1035 {
1036         int     i;              //, objnum;
1037         int     total_robots = 0;
1038         int     objects_processed = 0;
1039
1040         int     used_objects[MAX_OBJECTS];
1041
1042         fprintf(my_file, "\nLevel %s\n", level_name);
1043
1044         for (i=0; i<MAX_OBJECTS; i++)
1045                 used_objects[i] = 0;
1046
1047         while (objects_processed < Highest_object_index+1) {
1048                 int     j, objtype, objid, objcount, cur_obj_val, min_obj_val, min_objnum;
1049
1050                 //      Find new min objnum.
1051                 min_obj_val = 0x7fff0000;
1052                 min_objnum = -1;
1053
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) {
1058                                         min_objnum = j;
1059                                         min_obj_val = cur_obj_val;
1060                                 }
1061                         }
1062                 }
1063                 if ((min_objnum == -1) || (Objects[min_objnum].type == 255))
1064                         break;
1065
1066                 objcount = 0;
1067
1068                 objtype = Objects[min_objnum].type;
1069                 objid = Objects[min_objnum].id;
1070
1071                 for (i=0; i<=Highest_object_index; i++) {
1072                         if (!used_objects[i]) {
1073
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)
1079                                                 total_robots++;
1080                                         used_objects[i] = 1;
1081                                         objcount++;
1082                                         objects_processed++;
1083                                 }
1084                         }
1085                 }
1086
1087                 if (objcount) {
1088                         fprintf(my_file, "Object: ");
1089                         fprintf(my_file, "%8s %8s %3i\n", object_types(min_objnum), object_ids(min_objnum), objcount);
1090                 }
1091         }
1092
1093         fprintf(my_file, "Total robots = %3i\n", total_robots);
1094 }
1095
1096 int     First_dump_level = 0;
1097 int     Last_dump_level = NUM_ADAM_LEVELS-1;
1098
1099 // ----------------------------------------------------------------------------
1100 void say_totals_all(void)
1101 {
1102         int     i;
1103         FILE    *my_file;
1104
1105         my_file = fopen( "levels.all", "wt" );
1106         // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
1107
1108         if (!my_file)   {
1109                 char  ErrorMessage[200];
1110
1111                 sprintf( ErrorMessage, "ERROR: Unable to open levels.all\nErrno=%i", errno );
1112                 stop_time();
1113                 gr_palette_load(gr_palette);
1114                 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
1115                 start_time();
1116
1117                 return;
1118         }
1119
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]);
1124         }
1125
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]);
1130 //--05/17/95--  }
1131 //--05/17/95--
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]);
1136 //--05/17/95--  }
1137
1138         fclose(my_file);
1139
1140 }
1141
1142 void dump_used_textures_level(FILE *my_file, int level_num)
1143 {
1144         int     i;
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];
1150
1151         for (i=0; i<MAX_BITMAP_FILES; i++) {
1152                 perm_tmap_buf[i] = 0;
1153                 level_tmap_buf[i] = -1;
1154         }
1155
1156         for (i=0; i<MAX_BITMAP_FILES; i++) {
1157                 perm_wall_buf[i] = 0;
1158         }
1159
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);
1164 }
1165
1166 FILE    *my_file;
1167
1168 // ----------------------------------------------------------------------------
1169 void dump_used_textures_all(void)
1170 {
1171         int     i;
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];
1177
1178 say_totals_all();
1179
1180         my_file = fopen( "textures.dmp", "wt" );
1181         // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
1182
1183         if (!my_file)   {
1184                 char  ErrorMessage[200];
1185
1186                 sprintf( ErrorMessage, "ERROR: Can't open textures.dmp\nErrno=%i", errno);
1187                 stop_time();
1188                 gr_palette_load(gr_palette);
1189                 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
1190                 start_time();
1191
1192                 return;
1193         }
1194
1195         for (i=0; i<MAX_BITMAP_FILES; i++) {
1196                 perm_tmap_buf[i] = 0;
1197                 level_tmap_buf[i] = -1;
1198         }
1199
1200         for (i=0; i<MAX_BITMAP_FILES; i++) {
1201                 perm_wall_buf[i] = 0;
1202         }
1203
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);
1210 // --05/17/95-- }
1211 // --05/17/95--
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);
1214 // --05/17/95--
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);
1217 // --05/17/95--
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);
1220 // --05/17/95--
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);
1223
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);
1229 // --05/17/95-- }
1230 // --05/17/95--
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);
1233 // --05/17/95--
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);
1236
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);
1242         }
1243
1244         fprintf(my_file, "\n\nUsed textures in all (including registered) mines:\n");
1245         say_used_tmaps(my_file, perm_tmap_buf);
1246
1247         fprintf(my_file, "\nUnused textures in all (including registered) mines:\n");
1248         say_unused_tmaps(my_file, perm_tmap_buf);
1249
1250         fclose(my_file);
1251 }
1252
1253 #endif