]> icculus.org git repositories - btb/d2x.git/blob - main/dumpmine.c
no warn for using address of packed members
[btb/d2x.git] / main / dumpmine.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Functions to dump text description of mine.
17  * An editor-only function, called at mine load time.
18  * To be read by a human to verify the correctness and completeness of a mine.
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <conf.h>
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <errno.h>
30
31 #include "mono.h"
32 #include "key.h"
33 #include "gr.h"
34 #include "inferno.h"
35 #ifdef EDITOR
36 #include "editor/editor.h"
37 #endif
38 #include "error.h"
39
40
41 #ifdef EDITOR
42
43 extern ubyte bogus_data[64*64];
44
45 void dump_used_textures_level(FILE *my_file, int level_num);
46 static void say_totals(FILE *my_file, const char *level_name);
47
48 // ----------------------------------------------------------------------------
49 char    *object_types(int objnum)
50 {
51         int     type = Objects[objnum].type;
52
53         Assert((type >= 0) && (type < MAX_OBJECT_TYPES));
54         return Object_type_names[type];
55 }
56
57 // ----------------------------------------------------------------------------
58 char    *object_ids(int objnum)
59 {
60         int     type = Objects[objnum].type;
61         int     id = Objects[objnum].id;
62
63         switch (type) {
64                 case OBJ_ROBOT:
65                         return Robot_names[id];
66                         break;
67                 case OBJ_POWERUP:
68                         return Powerup_names[id];
69                         break;
70         }
71
72         return  NULL;
73 }
74
75 void err_printf(FILE *my_file, char * format, ... )
76 {
77         va_list args;
78         char            message[256];
79
80         va_start(args, format );
81         vsprintf(message,format,args);
82         va_end(args);
83
84         mprintf((1, "%s", message));
85         fprintf(my_file, "%s", message);
86         Errors_in_mine++;
87 }
88
89 void warning_printf(FILE *my_file, char * format, ... )
90 {
91         va_list args;
92         char            message[256];
93
94         va_start(args, format );
95         vsprintf(message,format,args);
96         va_end(args);
97
98         mprintf((0, "%s", message));
99         fprintf(my_file, "%s", message);
100 }
101
102 // ----------------------------------------------------------------------------
103 void write_exit_text(FILE *my_file)
104 {
105         int     i, j, count;
106
107         fprintf(my_file, "-----------------------------------------------------------------------------\n");
108         fprintf(my_file, "Exit stuff\n");
109
110         //      ---------- Find exit triggers ----------
111         count=0;
112         for (i=0; i<Num_triggers; i++)
113                 if (Triggers[i].type == TT_EXIT) {
114                         int     count2;
115
116                         fprintf(my_file, "Trigger %2i, is an exit trigger with %i links.\n", i, Triggers[i].num_links);
117                         count++;
118                         if (Triggers[i].num_links != 0)
119                                 err_printf(my_file, "Error: Exit triggers must have 0 links, this one has %i links.\n", Triggers[i].num_links);
120
121                         //      Find wall pointing to this trigger.
122                         count2 = 0;
123                         for (j=0; j<Num_walls; j++)
124                                 if (Walls[j].trigger == i) {
125                                         count2++;
126                                         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);
127                                 }
128                         if (count2 == 0)
129                                 err_printf(my_file, "Error: Trigger %i is not bound to any wall.\n", i);
130                         else if (count2 > 1)
131                                 err_printf(my_file, "Error: Trigger %i is bound to %i walls.\n", i, count2);
132
133                 }
134
135         if (count == 0)
136                 err_printf(my_file, "Error: No exit trigger in this mine.\n");
137         else if (count != 1)
138                 err_printf(my_file, "Error: More than one exit trigger in this mine.\n");
139         else
140                 fprintf(my_file, "\n");
141
142         //      ---------- Find exit doors ----------
143         count = 0;
144         for (i=0; i<=Highest_segment_index; i++)
145                 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++)
146                         if (Segments[i].children[j] == -2) {
147                                 fprintf(my_file, "Segment %3i, side %i is an exit door.\n", i, j);
148                                 count++;
149                         }
150
151         if (count == 0)
152                 err_printf(my_file, "Error: No external wall in this mine.\n");
153         else if (count != 1) {
154                 // -- warning_printf(my_file, "Warning: %i external walls in this mine.\n", count);
155                 // -- warning_printf(my_file, "(If %i are secret exits, then no problem.)\n", count-1);
156         } else
157                 fprintf(my_file, "\n");
158 }
159
160 // ----------------------------------------------------------------------------
161 void write_key_text(FILE *my_file)
162 {
163         int     i;
164         int     red_count, blue_count, gold_count;
165         int     red_count2, blue_count2, gold_count2;
166         int     blue_segnum=-1, blue_sidenum=-1, red_segnum=-1, red_sidenum=-1, gold_segnum=-1, gold_sidenum=-1;
167         int     connect_side;
168
169         fprintf(my_file, "-----------------------------------------------------------------------------\n");
170         fprintf(my_file, "Key stuff:\n");
171
172         red_count = 0;
173         blue_count = 0;
174         gold_count = 0;
175
176         for (i=0; i<Num_walls; i++) {
177                 if (Walls[i].keys & KEY_BLUE) {
178                         fprintf(my_file, "Wall %i (seg=%i, side=%i) is keyed to the blue key.\n", i, Walls[i].segnum, Walls[i].sidenum);
179                         if (blue_segnum == -1) {
180                                 blue_segnum = Walls[i].segnum;
181                                 blue_sidenum = Walls[i].sidenum;
182                                 blue_count++;
183                         } else {
184                                 connect_side = find_connect_side(&Segments[Walls[i].segnum], &Segments[blue_segnum]);
185                                 if (connect_side != blue_sidenum) {
186                                         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);
187                                         blue_count++;
188                                 }
189                         }
190                 }
191                 if (Walls[i].keys & KEY_RED) {
192                         fprintf(my_file, "Wall %i (seg=%i, side=%i) is keyed to the red key.\n", i, Walls[i].segnum, Walls[i].sidenum);
193                         if (red_segnum == -1) {
194                                 red_segnum = Walls[i].segnum;
195                                 red_sidenum = Walls[i].sidenum;
196                                 red_count++;
197                         } else {
198                                 connect_side = find_connect_side(&Segments[Walls[i].segnum], &Segments[red_segnum]);
199                                 if (connect_side != red_sidenum) {
200                                         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);
201                                         red_count++;
202                                 }
203                         }
204                 }
205                 if (Walls[i].keys & KEY_GOLD) {
206                         fprintf(my_file, "Wall %i (seg=%i, side=%i) is keyed to the gold key.\n", i, Walls[i].segnum, Walls[i].sidenum);
207                         if (gold_segnum == -1) {
208                                 gold_segnum = Walls[i].segnum;
209                                 gold_sidenum = Walls[i].sidenum;
210                                 gold_count++;
211                         } else {
212                                 connect_side = find_connect_side(&Segments[Walls[i].segnum], &Segments[gold_segnum]);
213                                 if (connect_side != gold_sidenum) {
214                                         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);
215                                         gold_count++;
216                                 }
217                         }
218                 }
219         }
220
221         if (blue_count > 1)
222                 warning_printf(my_file, "Warning: %i doors are keyed to the blue key.\n", blue_count);
223
224         if (red_count > 1)
225                 warning_printf(my_file, "Warning: %i doors are keyed to the red key.\n", red_count);
226
227         if (gold_count > 1)
228                 warning_printf(my_file, "Warning: %i doors are keyed to the gold key.\n", gold_count);
229
230         red_count2 = 0;
231         blue_count2 = 0;
232         gold_count2 = 0;
233
234         for (i=0; i<=Highest_object_index; i++) {
235                 if (Objects[i].type == OBJ_POWERUP)
236                         if (Objects[i].id == POW_KEY_BLUE) {
237                                 fprintf(my_file, "The BLUE key is object %i in segment %i\n", i, Objects[i].segnum);
238                                 blue_count2++;
239                         }
240                 if (Objects[i].type == OBJ_POWERUP)
241                         if (Objects[i].id == POW_KEY_RED) {
242                                 fprintf(my_file, "The RED key is object %i in segment %i\n", i, Objects[i].segnum);
243                                 red_count2++;
244                         }
245                 if (Objects[i].type == OBJ_POWERUP)
246                         if (Objects[i].id == POW_KEY_GOLD) {
247                                 fprintf(my_file, "The GOLD key is object %i in segment %i\n", i, Objects[i].segnum);
248                                 gold_count2++;
249                         }
250
251                 if (Objects[i].contains_count) {
252                         if (Objects[i].contains_type == OBJ_POWERUP) {
253                                 switch (Objects[i].contains_id) {
254                                         case POW_KEY_BLUE:
255                                                 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);
256                                                 blue_count2 += Objects[i].contains_count;
257                                                 break;
258                                         case POW_KEY_GOLD:
259                                                 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);
260                                                 gold_count2 += Objects[i].contains_count;
261                                                 break;
262                                         case POW_KEY_RED:
263                                                 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);
264                                                 red_count2 += Objects[i].contains_count;
265                                                 break;
266                                         default:
267                                                 break;
268                                 }
269                         }
270                 }
271         }
272
273         if (blue_count)
274                 if (blue_count2 == 0)
275                         err_printf(my_file, "Error: There is a door keyed to the blue key, but no blue key!\n");
276
277         if (red_count)
278                 if (red_count2 == 0)
279                         err_printf(my_file, "Error: There is a door keyed to the red key, but no red key!\n");
280
281         if (gold_count)
282                 if (gold_count2 == 0)
283                         err_printf(my_file, "Error: There is a door keyed to the gold key, but no gold key!\n");
284
285         if (blue_count2 > 1)
286                 err_printf(my_file, "Error: There are %i blue keys!\n", blue_count2);
287
288         if (red_count2 > 1)
289                 err_printf(my_file, "Error: There are %i red keys!\n", red_count2);
290
291         if (gold_count2 > 1)
292                 err_printf(my_file, "Error: There are %i gold keys!\n", gold_count2);
293 }
294
295 // ----------------------------------------------------------------------------
296 void write_control_center_text(FILE *my_file)
297 {
298         int     i, count, objnum, count2;
299
300         fprintf(my_file, "-----------------------------------------------------------------------------\n");
301         fprintf(my_file, "Control Center stuff:\n");
302
303         count = 0;
304         for (i=0; i<=Highest_segment_index; i++)
305                 if (Segment2s[i].special == SEGMENT_IS_CONTROLCEN) {
306                         count++;
307                         fprintf(my_file, "Segment %3i is a control center.\n", i);
308                         objnum = Segments[i].objects;
309                         count2 = 0;
310                         while (objnum != -1) {
311                                 if (Objects[objnum].type == OBJ_CNTRLCEN)
312                                         count2++;
313                                 objnum = Objects[objnum].next;
314                         }
315                         if (count2 == 0)
316                                 fprintf(my_file, "No control center object in control center segment.\n");
317                         else if (count2 != 1)
318                                 fprintf(my_file, "%i control center objects in control center segment.\n", count2);
319                 }
320
321         if (count == 0)
322                 err_printf(my_file, "Error: No control center in this mine.\n");
323         else if (count != 1)
324                 err_printf(my_file, "Error: More than one control center in this mine.\n");
325 }
326
327 // ----------------------------------------------------------------------------
328 void write_fuelcen_text(FILE *my_file)
329 {
330         int     i;
331
332         fprintf(my_file, "-----------------------------------------------------------------------------\n");
333         fprintf(my_file, "Fuel Center stuff: (Note: This means fuel, repair, materialize, control centers!)\n");
334
335         for (i=0; i<Num_fuelcenters; i++) {
336                 fprintf(my_file, "Fuelcenter %i: Type=%i (%s), segment = %3i\n", i, Station[i].Type, Special_names[Station[i].Type], Station[i].segnum);
337                 if (Segment2s[Station[i].segnum].special != Station[i].Type)
338                         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);
339         }
340 }
341
342 // ----------------------------------------------------------------------------
343 void write_segment_text(FILE *my_file)
344 {
345         int     i, objnum;
346
347         fprintf(my_file, "-----------------------------------------------------------------------------\n");
348         fprintf(my_file, "Segment stuff:\n");
349
350         for (i=0; i<=Highest_segment_index; i++) {
351
352                 fprintf(my_file, "Segment %4i: ", i);
353                 if (Segment2s[i].special != 0)
354                         fprintf(my_file, "special = %3i (%s), value = %3i ", Segment2s[i].special, Special_names[Segment2s[i].special], Segment2s[i].value);
355
356                 if (Segment2s[i].matcen_num != -1)
357                         fprintf(my_file, "matcen = %3i, ", Segment2s[i].matcen_num);
358                 
359                 fprintf(my_file, "\n");
360         }
361
362         for (i=0; i<=Highest_segment_index; i++) {
363                 int     depth;
364
365                 objnum = Segments[i].objects;
366                 fprintf(my_file, "Segment %4i: ", i);
367                 depth=0;
368                 if (objnum != -1) {
369                         fprintf(my_file, "Objects: ");
370                         while (objnum != -1) {
371                                 fprintf(my_file, "[%8s %8s %3i] ", object_types(objnum), object_ids(objnum), objnum);
372                                 objnum = Objects[objnum].next;
373                                 if (depth++ > 30) {
374                                         fprintf(my_file, "\nAborted after %i links\n", depth);
375                                         break;
376                                 }
377                         }
378                 }
379                 fprintf(my_file, "\n");
380         }
381 }
382
383 // ----------------------------------------------------------------------------
384 // This routine is bogus.  It assumes that all centers are matcens,
385 // which is not true.  The setting of segnum is bogus.
386 void write_matcen_text(FILE *my_file)
387 {
388         int     i, j, k;
389
390         fprintf(my_file, "-----------------------------------------------------------------------------\n");
391         fprintf(my_file, "Materialization centers:\n");
392         for (i=0; i<Num_robot_centers; i++) {
393                 int     trigger_count=0, segnum, fuelcen_num;
394
395                 fprintf(my_file, "FuelCenter[%02i].Segment = %04i  ", i, Station[i].segnum);
396                 fprintf(my_file, "Segment2[%04i].matcen_num = %02i  ", Station[i].segnum, Segment2s[Station[i].segnum].matcen_num);
397
398                 fuelcen_num = RobotCenters[i].fuelcen_num;
399                 if (Station[fuelcen_num].Type != SEGMENT_IS_ROBOTMAKER)
400                         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]);
401
402                 segnum = Station[fuelcen_num].segnum;
403
404                 //      Find trigger for this materialization center.
405                 for (j=0; j<Num_triggers; j++) {
406                         if (Triggers[j].type == TT_MATCEN) {
407                                 for (k=0; k<Triggers[j].num_links; k++)
408                                         if (Triggers[j].seg[k] == segnum) {
409                                                 fprintf(my_file, "Trigger = %2i  ", j );
410                                                 trigger_count++;
411                                         }
412                         }
413                 }
414                 fprintf(my_file, "\n");
415
416                 if (trigger_count == 0)
417                         err_printf(my_file, "Error: Matcen %i in segment %i has no trigger!\n", i, segnum);
418
419         }
420 }
421
422 // ----------------------------------------------------------------------------
423 void write_wall_text(FILE *my_file)
424 {
425         int     i, j;
426         sbyte wall_flags[MAX_WALLS];
427
428         fprintf(my_file, "-----------------------------------------------------------------------------\n");
429         fprintf(my_file, "Walls:\n");
430         for (i=0; i<Num_walls; i++) {
431                 int     segnum, sidenum;
432
433                 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,
434                         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);
435
436                 if (Walls[i].trigger >= Num_triggers)
437                         fprintf(my_file, "Wall %03d points to invalid trigger %d\n",i,Walls[i].trigger);
438
439                 segnum = Walls[i].segnum;
440                 sidenum = Walls[i].sidenum;
441
442                 if (Segments[segnum].sides[sidenum].wall_num != i)
443                         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);
444         }
445
446         for (i=0; i<MAX_WALLS; i++)
447                 wall_flags[i] = 0;
448
449         for (i=0; i<=Highest_segment_index; i++) {
450                 segment *segp = &Segments[i];
451                 for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) {
452                         side    *sidep = &segp->sides[j];
453                         if (sidep->wall_num != -1)
454                         {
455                                 if (wall_flags[sidep->wall_num])
456                                         err_printf(my_file, "Error: Wall %i appears in two or more segments, including segment %i, side %i.\n", sidep->wall_num, i, j);
457                                 else
458                                         wall_flags[sidep->wall_num] = 1;
459                         }
460                 }
461         }
462
463 }
464
465 //typedef struct trigger {
466 //      sbyte   type;
467 //      short           flags;
468 //      fix             value;
469 //      fix             time;
470 //      sbyte   link_num;
471 //      short   num_links;
472 //      short   seg[MAX_WALLS_PER_LINK];
473 //      short           side[MAX_WALLS_PER_LINK];
474 //      } trigger;
475
476 // ----------------------------------------------------------------------------
477 void write_player_text(FILE *my_file)
478 {
479         int     i, num_players=0;
480
481         fprintf(my_file, "-----------------------------------------------------------------------------\n");
482         fprintf(my_file, "Players:\n");
483         for (i=0; i<=Highest_object_index; i++) {
484                 if (Objects[i].type == OBJ_PLAYER) {
485                         num_players++;
486                         fprintf(my_file, "Player %2i is object #%3i in segment #%3i.\n", Objects[i].id, i, Objects[i].segnum);
487                 }
488         }
489
490         if (num_players != MAX_PLAYERS)
491                 err_printf(my_file, "Error: %i player objects.  %i are required.\n", num_players, MAX_PLAYERS);
492         if (num_players > MAX_MULTI_PLAYERS)
493                 err_printf(my_file, "Error: %i player objects.  %i are required.\n", num_players, MAX_PLAYERS);
494 }
495
496 // ----------------------------------------------------------------------------
497 void write_trigger_text(FILE *my_file)
498 {
499         int     i, j, w;
500
501         fprintf(my_file, "-----------------------------------------------------------------------------\n");
502         fprintf(my_file, "Triggers:\n");
503         for (i=0; i<Num_triggers; i++) {
504                 fprintf(my_file, "Trigger %03i: type=%02x flags=%04x, value=%08x, time=%8x, num_links=%i ", i,
505                         Triggers[i].type, Triggers[i].flags, Triggers[i].value, Triggers[i].time, Triggers[i].num_links);
506
507                 for (j=0; j<Triggers[i].num_links; j++)
508                         fprintf(my_file, "[%03i:%i] ", Triggers[i].seg[j], Triggers[i].side[j]);
509
510                 //      Find which wall this trigger is connected to.
511                 for (w=0; w<Num_walls; w++)
512                         if (Walls[w].trigger == i)
513                                 break;
514
515                 if (w == Num_walls)
516                         err_printf(my_file, "\nError: Trigger %i is not connected to any wall, so it can never be triggered.\n", i);
517                 else
518                         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);
519
520         }
521
522 }
523
524 // ----------------------------------------------------------------------------
525 void write_game_text_file(char *filename)
526 {
527         char    my_filename[128];
528         int     namelen;
529         FILE    * my_file;
530
531         Errors_in_mine = 0;
532
533         // mprintf((0, "Writing text file for mine [%s]\n", filename));
534
535         namelen = (int)strlen(filename);
536
537         Assert (namelen > 4);
538
539         Assert (filename[namelen-4] == '.');
540
541         strcpy(my_filename, filename);
542         strcpy( &my_filename[namelen-4], ".txm");
543
544         // mprintf((0, "Writing text file [%s]\n", my_filename));
545
546         my_file = fopen( my_filename, "wt" );
547         // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
548
549         if (!my_file)   {
550                 char  ErrorMessage[200];
551
552                 sprintf(ErrorMessage, "ERROR: Unable to open %s\nErrno = %i", my_filename, errno);
553                 stop_time();
554                 gr_palette_load(gr_palette);
555                 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
556                 start_time();
557
558                 return;
559         }
560
561         dump_used_textures_level(my_file, 0);
562         say_totals(my_file, Gamesave_current_filename);
563
564         fprintf(my_file, "\nNumber of segments:   %4i\n", Highest_segment_index+1);
565         fprintf(my_file, "Number of objects:    %4i\n", Highest_object_index+1);
566         fprintf(my_file, "Number of walls:      %4i\n", Num_walls);
567         fprintf(my_file, "Number of open doors: %4i\n", Num_open_doors);
568         fprintf(my_file, "Number of triggers:   %4i\n", Num_triggers);
569         fprintf(my_file, "Number of matcens:    %4i\n", Num_robot_centers);
570         fprintf(my_file, "\n");
571
572         write_segment_text(my_file);
573
574         write_fuelcen_text(my_file);
575
576         write_matcen_text(my_file);
577
578         write_player_text(my_file);
579
580         write_wall_text(my_file);
581
582         write_trigger_text(my_file);
583
584         write_exit_text(my_file);
585
586         //      ---------- Find control center segment ----------
587         write_control_center_text(my_file);
588
589         //      ---------- Show keyed walls ----------
590         write_key_text(my_file);
591
592 { int r;
593         r = fclose(my_file);
594         mprintf((1, "Close value = %i\n", r));
595         if (r)
596                 Int3();
597 }
598 }
599
600 // -- //        ---------------
601 // -- //        Note: This only works for a loaded level because the objects array must be valid.
602 // -- void determine_used_textures_robots(int *tmap_buf)
603 // -- {
604 // --   int     i, objnum;
605 // --   polymodel       *po;
606 // --
607 // --   Assert(N_polygon_models);
608 // --
609 // --   for (objnum=0; objnum <= Highest_object_index; objnum++) {
610 // --           int     model_num;
611 // --
612 // --           if (Objects[objnum].render_type == RT_POLYOBJ) {
613 // --                   model_num = Objects[objnum].rtype.pobj_info.model_num;
614 // --
615 // --                   po=&Polygon_models[model_num];
616 // --
617 // --                   for (i=0;i<po->n_textures;i++)  {
618 // --                           int     tli;
619 // --
620 // --                           tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
621 // --                           Assert((tli>=0) && (tli<= Num_tmaps));
622 // --                           tmap_buf[tli]++;
623 // --                   }
624 // --           }
625 // --   }
626 // --
627 // -- }
628
629 // --05/17/95--//       -----------------------------------------------------------------------------
630 // --05/17/95--void determine_used_textures_level(int load_level_flag, int shareware_flag, int level_num, int *tmap_buf, int *wall_buf, sbyte *level_tmap_buf, int max_tmap)
631 // --05/17/95--{
632 // --05/17/95-- int     segnum, sidenum;
633 // --05/17/95-- int     i, j;
634 // --05/17/95--
635 // --05/17/95-- for (i=0; i<max_tmap; i++)
636 // --05/17/95--         tmap_buf[i] = 0;
637 // --05/17/95--
638 // --05/17/95-- if (load_level_flag) {
639 // --05/17/95--         if (shareware_flag)
640 // --05/17/95--                 load_level(Shareware_level_names[level_num]);
641 // --05/17/95--         else
642 // --05/17/95--                 load_level(Registered_level_names[level_num]);
643 // --05/17/95-- }
644 // --05/17/95--
645 // --05/17/95-- for (segnum=0; segnum<=Highest_segment_index; segnum++) {
646 // --05/17/95--         segment *segp = &Segments[segnum];
647 // --05/17/95--
648 // --05/17/95--         for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
649 // --05/17/95--                 side    *sidep = &segp->sides[sidenum];
650 // --05/17/95--
651 // --05/17/95--                 if (sidep->wall_num != -1) {
652 // --05/17/95--                         int clip_num = Walls[sidep->wall_num].clip_num;
653 // --05/17/95--                         if (clip_num != -1) {
654 // --05/17/95--
655 // --05/17/95--                                 int num_frames = WallAnims[clip_num].num_frames;
656 // --05/17/95--
657 // --05/17/95--                                 wall_buf[clip_num] = 1;
658 // --05/17/95--
659 // --05/17/95--                                 for (j=0; j<num_frames; j++) {
660 // --05/17/95--                                         int     tmap_num;
661 // --05/17/95--
662 // --05/17/95--                                         tmap_num = WallAnims[clip_num].frames[j];
663 // --05/17/95--                                         tmap_buf[tmap_num]++;
664 // --05/17/95--                                         if (level_tmap_buf[tmap_num] == -1)
665 // --05/17/95--                                                 level_tmap_buf[tmap_num] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS;
666 // --05/17/95--                                 }
667 // --05/17/95--                         }
668 // --05/17/95--                 }
669 // --05/17/95--
670 // --05/17/95--                 if (sidep->tmap_num >= 0)
671 // --05/17/95--                         if (sidep->tmap_num < max_tmap) {
672 // --05/17/95--                                 tmap_buf[sidep->tmap_num]++;
673 // --05/17/95--                                 if (level_tmap_buf[sidep->tmap_num] == -1)
674 // --05/17/95--                                         level_tmap_buf[sidep->tmap_num] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS;
675 // --05/17/95--                         } else
676 // --05/17/95--                                 Int3(); //      Error, bogus texture map.  Should not be greater than max_tmap.
677 // --05/17/95--
678 // --05/17/95--                 if ((sidep->tmap_num2 & 0x3fff) != 0)
679 // --05/17/95--                         if ((sidep->tmap_num2 & 0x3fff) < max_tmap) {
680 // --05/17/95--                                 tmap_buf[sidep->tmap_num2 & 0x3fff]++;
681 // --05/17/95--                                 if (level_tmap_buf[sidep->tmap_num2 & 0x3fff] == -1)
682 // --05/17/95--                                         level_tmap_buf[sidep->tmap_num2 & 0x3fff] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS;
683 // --05/17/95--                         } else
684 // --05/17/95--                                 Int3(); //      Error, bogus texture map.  Should not be greater than max_tmap.
685 // --05/17/95--         }
686 // --05/17/95-- }
687 // --05/17/95--}
688
689 //      Adam: Change NUM_ADAM_LEVELS to the number of levels.
690 #define NUM_ADAM_LEVELS 30
691
692 //      Adam: Stick the names here.
693 static const char *const Adam_level_names[NUM_ADAM_LEVELS] = {
694         "D2LEVA-1.LVL",
695         "D2LEVA-2.LVL",
696         "D2LEVA-3.LVL",
697         "D2LEVA-4.LVL",
698         "D2LEVA-S.LVL",
699
700         "D2LEVB-1.LVL",
701         "D2LEVB-2.LVL",
702         "D2LEVB-3.LVL",
703         "D2LEVB-4.LVL",
704         "D2LEVB-S.LVL",
705
706         "D2LEVC-1.LVL",
707         "D2LEVC-2.LVL",
708         "D2LEVC-3.LVL",
709         "D2LEVC-4.LVL",
710         "D2LEVC-S.LVL",
711
712         "D2LEVD-1.LVL",
713         "D2LEVD-2.LVL",
714         "D2LEVD-3.LVL",
715         "D2LEVD-4.LVL",
716         "D2LEVD-S.LVL",
717
718         "D2LEVE-1.LVL",
719         "D2LEVE-2.LVL",
720         "D2LEVE-3.LVL",
721         "D2LEVE-4.LVL",
722         "D2LEVE-S.LVL",
723
724         "D2LEVF-1.LVL",
725         "D2LEVF-2.LVL",
726         "D2LEVF-3.LVL",
727         "D2LEVF-4.LVL",
728         "D2LEVF-S.LVL",
729 };
730
731 typedef struct BitmapFile       {
732         char                    name[15];
733 } BitmapFile;
734
735 extern BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
736
737 int     Ignore_tmap_num2_error;
738
739 // ----------------------------------------------------------------------------
740 void determine_used_textures_level(int load_level_flag, int shareware_flag, int level_num, int *tmap_buf, int *wall_buf, sbyte *level_tmap_buf, int max_tmap)
741 {
742         int     segnum, sidenum, objnum=max_tmap;
743         int     i, j;
744
745         Assert(shareware_flag != -17);
746
747         for (i=0; i<MAX_BITMAP_FILES; i++)
748                 tmap_buf[i] = 0;
749
750         if (load_level_flag) {
751                 load_level(Adam_level_names[level_num]);
752         }
753
754
755         //      Process robots.
756         for (objnum=0; objnum<=Highest_object_index; objnum++) {
757                 object *objp = &Objects[objnum];
758
759                 if (objp->render_type == RT_POLYOBJ) {
760                         polymodel *po = &Polygon_models[objp->rtype.pobj_info.model_num];
761
762                         for (i=0; i<po->n_textures; i++) {
763
764                                 int     tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index;
765                                 // -- mprintf((0, "%s  ", AllBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index].name));
766
767                                 if ((tli < MAX_BITMAP_FILES) && (tli >= 0)) {
768                                         tmap_buf[tli]++;
769                                         if (level_tmap_buf[tli] == -1)
770                                                 level_tmap_buf[tli] = level_num;
771                                 } else
772                                         Int3(); //      Hmm, It seems this texture is bogus!
773                         }
774
775                 }
776         }
777
778
779         Ignore_tmap_num2_error = 0;
780
781         //      Process walls and segment sides.
782         for (segnum=0; segnum<=Highest_segment_index; segnum++) {
783                 segment *segp = &Segments[segnum];
784
785                 for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
786                         side    *sidep = &segp->sides[sidenum];
787
788                         if (sidep->wall_num != -1) {
789                                 int clip_num = Walls[sidep->wall_num].clip_num;
790                                 if (clip_num != -1) {
791
792                                         // -- int num_frames = WallAnims[clip_num].num_frames;
793
794                                         wall_buf[clip_num] = 1;
795
796                                         for (j=0; j<1; j++) {   //      Used to do through num_frames, but don't really want all the door01#3 stuff.
797                                                 int     tmap_num;
798
799                                                 tmap_num = Textures[WallAnims[clip_num].frames[j]].index;
800                                                 Assert((tmap_num >= 0) && (tmap_num < MAX_BITMAP_FILES));
801                                                 tmap_buf[tmap_num]++;
802                                                 if (level_tmap_buf[tmap_num] == -1)
803                                                         level_tmap_buf[tmap_num] = level_num;
804                                         }
805                                 }
806                         } else if (segp->children[sidenum] == -1) {
807
808                                 if (sidep->tmap_num >= 0)
809                                 {
810                                         if (sidep->tmap_num < MAX_BITMAP_FILES) {
811                                                 Assert(Textures[sidep->tmap_num].index < MAX_BITMAP_FILES);
812                                                 tmap_buf[Textures[sidep->tmap_num].index]++;
813                                                 if (level_tmap_buf[Textures[sidep->tmap_num].index] == -1)
814                                                         level_tmap_buf[Textures[sidep->tmap_num].index] = level_num;
815                                         } else
816                                                 Int3(); //      Error, bogus texture map.  Should not be greater than max_tmap.
817                                 }
818
819                                 if ((sidep->tmap_num2 & 0x3fff) != 0)
820                                 {
821                                         if ((sidep->tmap_num2 & 0x3fff) < MAX_BITMAP_FILES) {
822                                                 Assert(Textures[sidep->tmap_num2 & 0x3fff].index < MAX_BITMAP_FILES);
823                                                 tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index]++;
824                                                 if (level_tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index] == -1)
825                                                         level_tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index] = level_num;
826                                         } else {
827                                                 if (!Ignore_tmap_num2_error)
828                                                         Int3(); //      Error, bogus texture map.  Should not be greater than max_tmap.
829                                                 Ignore_tmap_num2_error = 1;
830                                                 sidep->tmap_num2 = 0;
831                                         }
832                                 }
833                         }
834                 }
835         }
836 }
837
838 // ----------------------------------------------------------------------------
839 void merge_buffers(int *dest, int *src, int num)
840 {
841         int     i;
842
843         for (i=0; i<num; i++)
844                 if (src[i])
845                         dest[i] += src[i];
846 }
847
848 // ----------------------------------------------------------------------------
849 void say_used_tmaps(FILE *my_file, int *tb)
850 {
851         int     i;
852 // -- mk, 08/14/95 --   int     count = 0;
853
854         for (i=0; i<MAX_BITMAP_FILES; i++)
855                 if (tb[i]) {
856                         fprintf(my_file, "[%3i %8s (%4i)]\n", i, AllBitmaps[i].name, tb[i]);
857 // -- mk, 08/14/95 --                   if (count++ >= 4) {
858 // -- mk, 08/14/95 --                           fprintf(my_file, "\n");
859 // -- mk, 08/14/95 --                           count = 0;
860 // -- mk, 08/14/95 --                   }
861                 }
862 }
863
864 // --05/17/95--//       -----------------------------------------------------------------------------
865 // --05/17/95--void say_used_once_tmaps(FILE *my_file, int *tb, sbyte *tb_lnum)
866 // --05/17/95--{
867 // --05/17/95-- int     i;
868 // --05/17/95-- char    *level_name;
869 // --05/17/95--
870 // --05/17/95-- for (i=0; i<Num_tmaps; i++)
871 // --05/17/95--         if (tb[i] == 1) {
872 // --05/17/95--                 int     level_num = tb_lnum[i];
873 // --05/17/95--                 if (level_num >= NUM_SHAREWARE_LEVELS) {
874 // --05/17/95--                         Assert((level_num - NUM_SHAREWARE_LEVELS >= 0) && (level_num - NUM_SHAREWARE_LEVELS < NUM_REGISTERED_LEVELS));
875 // --05/17/95--                         level_name = Registered_level_names[level_num - NUM_SHAREWARE_LEVELS];
876 // --05/17/95--                 } else {
877 // --05/17/95--                         Assert((level_num >= 0) && (level_num < NUM_SHAREWARE_LEVELS));
878 // --05/17/95--                         level_name = Shareware_level_names[level_num];
879 // --05/17/95--                 }
880 // --05/17/95--
881 // --05/17/95--                 fprintf(my_file, "Texture %3i %8s used only once on level %s\n", i, TmapInfo[i].filename, level_name);
882 // --05/17/95--         }
883 // --05/17/95--}
884
885 // ----------------------------------------------------------------------------
886 void say_used_once_tmaps(FILE *my_file, int *tb, sbyte *tb_lnum)
887 {
888         int     i;
889         const char *level_name;
890
891         for (i=0; i<MAX_BITMAP_FILES; i++)
892                 if (tb[i] == 1) {
893                         int     level_num = tb_lnum[i];
894                         level_name = Adam_level_names[level_num];
895
896                         fprintf(my_file, "Texture %3i %8s used only once on level %s\n", i, AllBitmaps[i].name, level_name);
897                 }
898 }
899
900 // ----------------------------------------------------------------------------
901 void say_unused_tmaps(FILE *my_file, int *tb)
902 {
903         int     i;
904         int     count = 0;
905
906         for (i=0; i<MAX_BITMAP_FILES; i++)
907                 if (!tb[i]) {
908                         if (GameBitmaps[Textures[i].index].bm_data == bogus_data)
909                                 fprintf(my_file, "U");
910                         else
911                                 fprintf(my_file, " ");
912
913                         fprintf(my_file, "[%3i %8s] ", i, AllBitmaps[i].name);
914                         if (count++ >= 4) {
915                                 fprintf(my_file, "\n");
916                                 count = 0;
917                         }
918                 }
919 }
920
921 // ----------------------------------------------------------------------------
922 void say_unused_walls(FILE *my_file, int *tb)
923 {
924         int     i;
925
926         for (i=0; i<Num_wall_anims; i++)
927                 if (!tb[i])
928                         fprintf(my_file, "Wall %3i is unused.\n", i);
929 }
930
931 // ----------------------------------------------------------------------------
932 static void say_totals(FILE *my_file, const char *level_name)
933 {
934         int     i;              //, objnum;
935         int     total_robots = 0;
936         int     objects_processed = 0;
937
938         int     used_objects[MAX_OBJECTS];
939
940         fprintf(my_file, "\nLevel %s\n", level_name);
941
942         for (i=0; i<MAX_OBJECTS; i++)
943                 used_objects[i] = 0;
944
945         while (objects_processed < Highest_object_index+1) {
946                 int     j, objtype, objid, objcount, cur_obj_val, min_obj_val, min_objnum;
947
948                 //      Find new min objnum.
949                 min_obj_val = 0x7fff0000;
950                 min_objnum = -1;
951
952                 for (j=0; j<=Highest_object_index; j++) {
953                         if (!used_objects[j] && Objects[j].type!=OBJ_NONE) {
954                                 cur_obj_val = Objects[j].type * 1000 + Objects[j].id;
955                                 if (cur_obj_val < min_obj_val) {
956                                         min_objnum = j;
957                                         min_obj_val = cur_obj_val;
958                                 }
959                         }
960                 }
961                 if ((min_objnum == -1) || (Objects[min_objnum].type == 255))
962                         break;
963
964                 objcount = 0;
965
966                 objtype = Objects[min_objnum].type;
967                 objid = Objects[min_objnum].id;
968
969                 for (i=0; i<=Highest_object_index; i++) {
970                         if (!used_objects[i]) {
971
972                                 if (((Objects[i].type == objtype) && (Objects[i].id == objid)) ||
973                                                 ((Objects[i].type == objtype) && (objtype == OBJ_PLAYER)) ||
974                                                 ((Objects[i].type == objtype) && (objtype == OBJ_COOP)) ||
975                                                 ((Objects[i].type == objtype) && (objtype == OBJ_HOSTAGE))) {
976                                         if (Objects[i].type == OBJ_ROBOT)
977                                                 total_robots++;
978                                         used_objects[i] = 1;
979                                         objcount++;
980                                         objects_processed++;
981                                 }
982                         }
983                 }
984
985                 if (objcount) {
986                         fprintf(my_file, "Object: ");
987                         fprintf(my_file, "%8s %8s %3i\n", object_types(min_objnum), object_ids(min_objnum), objcount);
988                 }
989         }
990
991         fprintf(my_file, "Total robots = %3i\n", total_robots);
992 }
993
994 int     First_dump_level = 0;
995 int     Last_dump_level = NUM_ADAM_LEVELS-1;
996
997 // ----------------------------------------------------------------------------
998 void say_totals_all(void)
999 {
1000         int     i;
1001         FILE    *my_file;
1002
1003         my_file = fopen( "levels.all", "wt" );
1004         // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
1005
1006         if (!my_file)   {
1007                 char  ErrorMessage[200];
1008
1009                 sprintf( ErrorMessage, "ERROR: Unable to open levels.all\nErrno=%i", errno );
1010                 stop_time();
1011                 gr_palette_load(gr_palette);
1012                 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
1013                 start_time();
1014
1015                 return;
1016         }
1017
1018         for (i=First_dump_level; i<=Last_dump_level; i++) {
1019                 mprintf((0, "Level %i\n", i+1));
1020                 load_level(Adam_level_names[i]);
1021                 say_totals(my_file, Adam_level_names[i]);
1022         }
1023
1024 //--05/17/95--  for (i=0; i<NUM_SHAREWARE_LEVELS; i++) {
1025 //--05/17/95--          mprintf((0, "Level %i\n", i+1));
1026 //--05/17/95--          load_level(Shareware_level_names[i]);
1027 //--05/17/95--          say_totals(my_file, Shareware_level_names[i]);
1028 //--05/17/95--  }
1029 //--05/17/95--
1030 //--05/17/95--  for (i=0; i<NUM_REGISTERED_LEVELS; i++) {
1031 //--05/17/95--          mprintf((0, "Level %i\n", i+1+NUM_SHAREWARE_LEVELS));
1032 //--05/17/95--          load_level(Registered_level_names[i]);
1033 //--05/17/95--          say_totals(my_file, Registered_level_names[i]);
1034 //--05/17/95--  }
1035
1036         fclose(my_file);
1037
1038 }
1039
1040 void dump_used_textures_level(FILE *my_file, int level_num)
1041 {
1042         int     i;
1043         int     temp_tmap_buf[MAX_BITMAP_FILES];
1044         int     perm_tmap_buf[MAX_BITMAP_FILES];
1045         sbyte level_tmap_buf[MAX_BITMAP_FILES];
1046         int     temp_wall_buf[MAX_BITMAP_FILES];
1047         int     perm_wall_buf[MAX_BITMAP_FILES];
1048
1049         for (i=0; i<MAX_BITMAP_FILES; i++) {
1050                 perm_tmap_buf[i] = 0;
1051                 level_tmap_buf[i] = -1;
1052         }
1053
1054         for (i=0; i<MAX_BITMAP_FILES; i++) {
1055                 perm_wall_buf[i] = 0;
1056         }
1057
1058         determine_used_textures_level(0, 1, level_num, temp_tmap_buf, temp_wall_buf, level_tmap_buf, MAX_BITMAP_FILES);
1059 // --   determine_used_textures_robots(temp_tmap_buf);
1060         fprintf(my_file, "\nTextures used in [%s]\n", Gamesave_current_filename);
1061         say_used_tmaps(my_file, temp_tmap_buf);
1062 }
1063
1064 FILE    *my_file;
1065
1066 // ----------------------------------------------------------------------------
1067 void dump_used_textures_all(void)
1068 {
1069         int     i;
1070         int     temp_tmap_buf[MAX_BITMAP_FILES];
1071         int     perm_tmap_buf[MAX_BITMAP_FILES];
1072         sbyte level_tmap_buf[MAX_BITMAP_FILES];
1073         int     temp_wall_buf[MAX_BITMAP_FILES];
1074         int     perm_wall_buf[MAX_BITMAP_FILES];
1075
1076 say_totals_all();
1077
1078         my_file = fopen( "textures.dmp", "wt" );
1079         // -- mprintf((1, "Fileno = %i\n", fileno(my_file)));
1080
1081         if (!my_file)   {
1082                 char  ErrorMessage[200];
1083
1084                 sprintf( ErrorMessage, "ERROR: Can't open textures.dmp\nErrno=%i", errno);
1085                 stop_time();
1086                 gr_palette_load(gr_palette);
1087                 nm_messagebox( NULL, 1, "Ok", ErrorMessage );
1088                 start_time();
1089
1090                 return;
1091         }
1092
1093         for (i=0; i<MAX_BITMAP_FILES; i++) {
1094                 perm_tmap_buf[i] = 0;
1095                 level_tmap_buf[i] = -1;
1096         }
1097
1098         for (i=0; i<MAX_BITMAP_FILES; i++) {
1099                 perm_wall_buf[i] = 0;
1100         }
1101
1102 // --05/17/95-- for (i=0; i<NUM_SHAREWARE_LEVELS; i++) {
1103 // --05/17/95--         determine_used_textures_level(1, 1, i, temp_tmap_buf, temp_wall_buf, level_tmap_buf, MAX_BITMAP_FILES);
1104 // --05/17/95--         fprintf(my_file, "\nTextures used in [%s]\n", Shareware_level_names[i]);
1105 // --05/17/95--         say_used_tmaps(my_file, temp_tmap_buf);
1106 // --05/17/95--         merge_buffers(perm_tmap_buf, temp_tmap_buf, MAX_BITMAP_FILES);
1107 // --05/17/95--         merge_buffers(perm_wall_buf, temp_wall_buf, MAX_BITMAP_FILES);
1108 // --05/17/95-- }
1109 // --05/17/95--
1110 // --05/17/95-- fprintf(my_file, "\n\nUsed textures in all shareware mines:\n");
1111 // --05/17/95-- say_used_tmaps(my_file, perm_tmap_buf);
1112 // --05/17/95--
1113 // --05/17/95-- fprintf(my_file, "\nUnused textures in all shareware mines:\n");
1114 // --05/17/95-- say_unused_tmaps(my_file, perm_tmap_buf);
1115 // --05/17/95--
1116 // --05/17/95-- fprintf(my_file, "\nTextures used exactly once in all shareware mines:\n");
1117 // --05/17/95-- say_used_once_tmaps(my_file, perm_tmap_buf, level_tmap_buf);
1118 // --05/17/95--
1119 // --05/17/95-- fprintf(my_file, "\nWall anims (eg, doors) unused in all shareware mines:\n");
1120 // --05/17/95-- say_unused_walls(my_file, perm_wall_buf);
1121
1122 // --05/17/95-- for (i=0; i<NUM_REGISTERED_LEVELS; i++) {
1123 // --05/17/95--         determine_used_textures_level(1, 0, i, temp_tmap_buf, temp_wall_buf, level_tmap_buf, MAX_BITMAP_FILES);
1124 // --05/17/95--         fprintf(my_file, "\nTextures used in [%s]\n", Registered_level_names[i]);
1125 // --05/17/95--         say_used_tmaps(my_file, temp_tmap_buf);
1126 // --05/17/95--         merge_buffers(perm_tmap_buf, temp_tmap_buf, MAX_BITMAP_FILES);
1127 // --05/17/95-- }
1128 // --05/17/95--
1129 // --05/17/95-- fprintf(my_file, "\n\nUsed textures in all (including registered) mines:\n");
1130 // --05/17/95-- say_used_tmaps(my_file, perm_tmap_buf);
1131 // --05/17/95--
1132 // --05/17/95-- fprintf(my_file, "\nUnused textures in all (including registered) mines:\n");
1133 // --05/17/95-- say_unused_tmaps(my_file, perm_tmap_buf);
1134
1135         for (i=First_dump_level; i<=Last_dump_level; i++) {
1136                 determine_used_textures_level(1, 0, i, temp_tmap_buf, temp_wall_buf, level_tmap_buf, MAX_BITMAP_FILES);
1137                 fprintf(my_file, "\nTextures used in [%s]\n", Adam_level_names[i]);
1138                 say_used_tmaps(my_file, temp_tmap_buf);
1139                 merge_buffers(perm_tmap_buf, temp_tmap_buf, MAX_BITMAP_FILES);
1140         }
1141
1142         fprintf(my_file, "\n\nUsed textures in all (including registered) mines:\n");
1143         say_used_tmaps(my_file, perm_tmap_buf);
1144
1145         fprintf(my_file, "\nUnused textures in all (including registered) mines:\n");
1146         say_unused_tmaps(my_file, perm_tmap_buf);
1147
1148         fclose(my_file);
1149 }
1150
1151 #endif