/**********************************************************************************************************************************/
/* File         : WADINFO.C                                                                                                       */
/* Executable   : WADINFO.EXE                                                                                                     */
/* Doc file     : WADINFO.DOC                                                                                                     */
/* Version num  : 1.04                                                                                                            */
/* Last changed : 16-09-1994  21:49                                                                                               */
/* Update count : 7                                                                                                               */
/* OS type      : if _AMIGA_ set    : AMIGA (Intuition, multitasking)                                                             */
/*                                    Compiler : Aztec C Version 5.0a  Copyright 1989 by Manx Software Systems Inc. (Jan 9 1990)  */
/*                                    Linker   : Aztec C68K Linker Version 5.0a  Copyright 1989 by Manx Software System Inc.      */
/*                                    LN attr  : -lm -lc                                                                          */
/*                if _AMIGA_ cleared: PC (DOS, singletasking)                                                                     */
/*                                    Compiler : Microsoft (R) Quick C Compiler Version 2.50                                      */
/*                                    Linker   : Microsoft (R) QuickC Linker Version 4.10                                         */
/*                                    QCL attr : /AC /G2 /Ox /F 1000 /link GRAPHICS.LIB                                           */
/* Description  : Information extractor for DOOM (TM) WAD files.                                                                  */
/* Other        : None                                                                                                            */
/*                                                                                                                                */
/*                                   By M. van der Heide of ThunderWare Research Center                                           */
/**********************************************************************************************************************************/

/* Uncomment this line if compiling on the AMIGA */
/* #define _AMIGA_ */


#ifdef _AMIGA_
  #include <intuition/intuition.h>
  #include <graphics/gfxbase.h>
#else
  #pragma  check_pointer      (off)
  #pragma  check_stack        (off)
  #include <stdlib.h>
  #include <graph.h>
  #include <malloc.h>
#endif

#include   <stdio.h>
#include   <ctype.h>
#include   <stdarg.h>
#include   <string.h>
#include   <math.h>

#define    boolean            char

#ifdef _AMIGA_
  #define  dbyte              short                                     /* An 'int' is 4 bytes ('long') in stead of 2 on an Amiga */
#else
  #define  dbyte              int
  #define  TRUE               1
  #define  FALSE              0
#endif

#define    DBLACK             0                                             /* Define names for the standard (VGA) palette colors */
#define    DBLUE              1
#define    DGREEN             2
#define    DCYAN              3
#define    DRED               4
#define    DMAGENTA           5
#define    DYELLOW            6
#define    DWHITE             7
#define    LBLACK             8
#define    LBLUE              9
#define    LGREEN             10
#define    LCYAN              11
#define    LRED               12
#define    LMAGENTA           13
#define    LYELLOW            14
#define    LWHITE             15

#define    NUMEPISODE         3                                             /* Define total number of episodes and levels/episode */
#define    NUMLEVEL           9

#define    MAXCOLORS          2                                          /* Define number of WAD 'directory' identifiers per type */
#define    MAXLEVELS          NUMEPISODE * NUMLEVEL
#define    MAXSPRITES         77
#define    MAXMUSIC           32
#define    MAXSOUNDS          122
#define    MAXGRAPHS          0
#define    MAXINSTRUMENTS     1
#define    MAXSTATUSBAR       2
#define    MAXMENUS           39

#define    MAXLINEDRLF        17                                          /* Define the number of 'important' LineDef type fields */
#define    MAXLINESWITCH      41
#define    MAXLINEEND         4

#define    NEWCOLORS          0x01                                            /* Define bit-wise (storage) values for these types */
#define    NEWSOUNDS          0x02
#define    NEWSPRITES         0x04
#define    NEWMUSIC           0x08
#define    NEWGRAPHS          0x10
#define    NEWINSTRUMENTS     0x20
#define    NEWSTATUSBAR       0x40
#define    NEWMENUS           0x80

#define    THING_PLAYER1      1                                                               /* Define the THINGS to check for : */
#define    THING_PLAYER2      2                                                                                 /* Starting areas */
#define    THING_PLAYER3      3
#define    THING_PLAYER4      4
#define    THING_DEATHMATCH   11

#define    THING_CHAINSAW     2005                                                                                     /* Weapons */
#define    THING_SHOTGUN      2001
#define    THING_CHAINGUN     2002
#define    THING_LAUNCHER     2003
#define    THING_PLASMAGUN    2004
#define    THING_BFG9000      2006

#define    THING_TROOPER      3004                                                                                     /* Enemies */
#define    THING_SARGEANT     9
#define    THING_IMP          3001
#define    THING_DEMON        3002
#define    THING_SPECTRE      58
#define    THING_CACODEMON    3005
#define    THING_LOSTSOUL     3006
#define    THING_BARON        3003
#define    THING_CYBERDEMON   16
#define    THING_SPIDERBOSS   7

#define    TYPE_CHAINSAW      0                                                 /* Define index-values for the THINGS identifiers */
#define    TYPE_SHOTGUN       1
#define    TYPE_CHAINGUN      2
#define    TYPE_LAUNCHER      3
#define    TYPE_PLASMAGUN     4
#define    TYPE_BFG9000       5
#define    TYPE_TROOPER       6
#define    TYPE_SARGEANT      7
#define    TYPE_IMP           8
#define    TYPE_DEMON         9
#define    TYPE_SPECTRE       10
#define    TYPE_CACODEMON     11
#define    TYPE_LOSTSOUL      12
#define    TYPE_BARON         13
#define    TYPE_CYBERDEMON    14
#define    TYPE_SPIDERBOSS    15

#define    WHEN_D12           0x0001                                             /* Define difficulties for when a things appears */
#define    WHEN_D3            0x0002
#define    WHEN_D45           0x0004
#define    WHEN_MULTI         0x0010

struct     WadInfo_s                                                              /* Group the main info on the WAD file together */
{
  char     NewStuff;                                                                          /* Things other than levels patched */
  long     NewLevels;
  dbyte    NewDemos;
};

struct     WadHeader_s                                                           /* The first bytes of a WAD file: the WAD header */
{
  char     Type[4];                                                          /* Should be "PWAD" or "IWAD" for a (valid) WAD file */
  unsigned long DirSize;                                                              /* Number of entries in the WAD 'directory' */
  unsigned long DirStart;                                                              /* Pointer to start of the WAD 'directory' */
};

struct     Directory_s                                                                        /* One entry in the WAD 'directory' */
{
  unsigned long Start;                                                                       /* Pointer to the data of this entry */
  unsigned long Size;                                                                             /* Length of this data in bytes */
  char     Name[8];                                                                                            /* Type identifier */
};

struct     Thing_s                                                            /* One entry of the 'directory' entry type "THINGS" */
{
  dbyte    Xpos;                                                                                           /* Position on the map */
  dbyte    Ypos;
  dbyte    Angle;                                                                        /* Facing direction: north, east, etc... */
  dbyte    Type;                                                                                                    /* Thing type */
  dbyte    When;                                                                                                /* Appears when ? */
};

struct     Vertex_s
{
  dbyte    MapX;
  dbyte    MapY;
};

struct     LineDef_s
{
  dbyte    Start;
  dbyte    End;
  dbyte    Flags;
  dbyte    Type;
  dbyte    Tag;
  dbyte    SideDef1;
  dbyte    SideDef2;
};

struct     SideDef_s
{
  dbyte    OffsetX;
  dbyte    OffsetY;
  char     UpperTexture[8];
  char     LowerTexture[8];
  char     NormalTexture[8];
};

struct     Seg_s
{
  dbyte    Start;
  dbyte    End;
  dbyte    Angle;
  dbyte    LineDef;
  dbyte    Flip;
  dbyte    Distance;
};

struct     Sector_s
{
  dbyte    FloorHeight;
  dbyte    CeilingHeight;
  char     FloorTexture[8];
  char     CeilingTexture[8];
  dbyte    LightLevel;
  dbyte    Special;
  dbyte    Tag;
};

struct     SubSector_s
{
  dbyte    NumberOfSegs;
  dbyte    FirstSeg;
};

struct     Node_s
{
  dbyte    X;
  dbyte    Y;
  dbyte    Dx;
  dbyte    Dy;
  dbyte    FirstUpperBoundY;
  dbyte    FirstLowerBoundY;
  dbyte    FirstUpperBoundX;
  dbyte    FirstLowerBoundX;
  dbyte    SecondUpperBoundY;
  dbyte    SecondLowerBoundY;
  dbyte    SecondUpperBoundX;
  dbyte    SecondLowerBoundX;
  dbyte    Child1;
  dbyte    Child2;
};

struct     BlockMapHeader_s
{
  dbyte    OriginX;
  dbyte    OriginY;
  dbyte    BlockCntX;
  dbyte    BlockCntY;
};

struct     Remember_s
{
  int      PlayerStarts[5];                                                                /* 1-4 = startno, 5 = deathmatch start */
  int      ThingType[16][4];                                                               /* 1 = D12, 2 = D3, 3 = D45, 4 = Multi */
  dbyte    MinMapX;                                                                                                /* Vertex info */
  dbyte    MinMapY;
  dbyte    MaxMapX;
  dbyte    MaxMapY;
  dbyte    MapSizeX;
  dbyte    MapSizeY;
  struct   Directory_s ThingsLoc;
  struct   Directory_s VertexLoc;
  struct   Directory_s LineDefLoc;
  struct   Directory_s SideDefLoc;
  struct   Directory_s SegLoc;
  struct   Directory_s SectorLoc;
  struct   Directory_s SubSectorLoc;
  struct   Directory_s NodeLoc;
  struct   Directory_s RejectDataLoc;
  struct   Directory_s BlockMapLoc;
  boolean  ThingsFilled;
  boolean  StatsFilled;
};

struct     Check_s
{
  dbyte    StartMapX;
  dbyte    StartMapY;
  dbyte    EndMapX;
  dbyte    EndMapY;
};

struct     FieldId_s
{
  char    *IdName;
  char    *Description;
  char     Type;
  boolean  FieldFilled;
};

struct     WadHeader_s WadHeader;
struct     Directory_s Directory;
struct     WadInfo_s   WadInfo;
struct     Thing_s     Thing;
struct     Vertex_s    Vertex;
struct     Remember_s  Remember[27];

char      *Levels[]            = {"E1M1", "E1M2", "E1M3", "E1M4", "E1M5", "E1M6", "E1M7", "E1M8", "E1M9",
                                  "E2M1", "E2M2", "E2M3", "E2M4", "E2M5", "E2M6", "E2M7", "E2M8", "E2M9",
                                  "E3M1", "E3M2", "E3M3", "E3M4", "E3M5", "E3M6", "E3M7", "E3M8", "E3M9"};
char      *Colors[]            = {"PLAYPAL", "COLORMAP"};
char      *StatusBar[]         = {"AMMNUM", "ST"};
char      *Instruments[]       = {"GENMIDI"};
struct     FieldId_s Music[]   = {{"DMXGUS",   "Gravis Ultra Sound driver"      },
                                  {"D_INTRO",  "Introduction music"             },
                                  {"D_INTER",  "Between levels"                 },
                                  {"D_VICTOR", "After completing an episode"    },
                                  {"D_BUNNY",  "While bunny is on the screen"   },
                                  {"D_E1M1",   "Episode 1 Level 1"              },
                                  {"D_E1M2",   "Episode 1 Level 2"              },
                                  {"D_E1M3",   "Episode 1 Level 3"              },
                                  {"D_E1M4",   "Episode 1 Level 4"              },
                                  {"D_E1M5",   "Episode 1 Level 5"              },
                                  {"D_E1M6",   "Episode 1 Level 6"              },
                                  {"D_E1M7",   "Episode 1 Level 7"              },
                                  {"D_E1M8",   "Episode 1 Level 8"              },
                                  {"D_E1M9",   "Episode 1 Level 9"              },
                                  {"D_E2M1",   "Episode 2 Level 1"              },
                                  {"D_E2M2",   "Episode 2 Level 2"              },
                                  {"D_E2M3",   "Episode 2 Level 3"              },
                                  {"D_E2M4",   "Episode 2 Level 4"              },
                                  {"D_E2M5",   "Episode 2 Level 5"              },
                                  {"D_E2M6",   "Episode 2 Level 6"              },
                                  {"D_E2M7",   "Episode 2 Level 7"              },
                                  {"D_E2M8",   "Episode 2 Level 8"              },
                                  {"D_E2M9",   "Episode 2 Level 9"              },
                                  {"D_E3M1",   "Episode 3 Level 1"              },
                                  {"D_E3M2",   "Episode 3 Level 2"              },
                                  {"D_E3M3",   "Episode 3 Level 3"              },
                                  {"D_E3M4",   "Episode 3 Level 4"              },
                                  {"D_E3M5",   "Episode 3 Level 5"              },
                                  {"D_E3M6",   "Episode 3 Level 6"              },
                                  {"D_E3M7",   "Episode 3 Level 7"              },
                                  {"D_E3M8",   "Episode 3 Level 8"              },
                                  {"D_E3M9",   "Episode 3 Level 9"              }};
struct     FieldId_s Menus[]   = {{"M_DOOM",   "DOOM",                         0},
                                  {"M_NGAME",  "New Game",                     0},
                                  {"M_OPTION", "Options",                      0},
                                  {"M_LOADG",  "Load Game",                    0},
                                  {"M_SAVEG",  "Save Game",                    0},
                                  {"M_RDTHIS", "Read This!",                   0},
                                  {"M_QUITG",  "Quit Game",                    0},
                                  {"M_EPISOD", "Which Episode?",               1},
                                  {"M_EPI1",   "Knee-Deep in the Dead",        1},
                                  {"M_EPI2",   "The Shores of Hell",           1},
                                  {"M_EPI3",   "Inferno",                      1},
                                  {"M_NEWG",   "New Game",                     1},
                                  {"M_SKILL",  "Choose a Skill Level",         1},
                                  {"M_JKILL",  "I'm too young to die",         1},
                                  {"M_ROUGH",  "Hey, not too rough",           1},
                                  {"M_HURT",   "Hurt me planty",               1},
                                  {"M_ULTRA",  "Ultra-Violence!",              1},
                                  {"M_NMARE",  "Nightmare",                    1},
                                  {"M_SVOL",   "Sound Volume",                 1},
                                  {"M_SFXVOL", "Sfx Volume",                   1},
                                  {"M_MUSVOL", "Music Volume",                 1},
                                  {"M_ENDGAM", "End Game",                     2},
                                  {"M_PAUSE",  "Pause",                        2},
                                  {"M_MESSG",  "Messages:",                    2},
                                  {"M_MSGON",  "on",                           2},
                                  {"M_MSGOFF", "off",                          2},
                                  {"M_OPTTTL", "Options",                      2},
                                  {"M_DISP",   "Display",                      2},
                                  {"M_MSENS",  "Mouse Sensitivity",            2},
                                  {"M_GDHIGH", "high",                         2},
                                  {"M_GDLOW",  "low",                          2},
                                  {"M_DETAIL", "Graphic Detail",               2},
                                  {"M_DISOPT", "Display options",              2},
                                  {"M_SCRNSZ", "Screen Size",                  2},
                                  {"M_SGTTL",  "Save Game",                    2},
                                  {"M_LGTTL",  "Load Game",                    2},
                                  {"M_SKULL",  "Selection skull",              3},
                                  {"M_THERM",  "Volume slider",                3},
                                  {"M_LS",     "Game name field in load/save", 3}};
struct     FieldId_s Sprites[] = {{"PLAY",     "Player",                       0},
                                  {"POSS",     "Trooper",                      0},
                                  {"SPOS",     "Sargeant",                     0},
                                  {"TROO",     "Imp",                          0},
                                  {"SARG",     "Demon & Spectre",              0},
                                  {"HEAD",     "Caco Demon",                   0},
                                  {"SKUL",     "Lost Soul",                    0},
                                  {"BOSS",     "Baron of Hell",                0},
                                  {"CYBR",     "Cyber Demon",                  0},
                                  {"SPID",     "Spider Demon",                 0},
                                  {"BKEY",     "Blue keycard",                 1},
                                  {"YKEY",     "Yellow keycard",               1},
                                  {"RKEY",     "Red keycard",                  1},
                                  {"BSKU",     "Blue skullkey",                1},
                                  {"YSKU",     "Yellow skullkey",              1},
                                  {"RSKU",     "Red skullkey",                 1},
                                  {"PUN",      "Nothing in hand",              2},
                                  {"SAW",      "Chainsaw in hand",             2},
                                  {"PIS",      "Pistol in hand",               2},
                                  {"SHT",      "Shotgun in hand",              2},
                                  {"CHG",      "Chaingun in hand",             2},
                                  {"PLS",      "Plasmagun in hand",            2},
                                  {"BFG",      "BFG9000 in hand",              2},
                                  {"CSAW",     "Chainsaw",                     2},
                                  {"SHOT",     "Shotgun",                      2},
                                  {"MGUN",     "Chaingun",                     2},
                                  {"LAUN",     "Rocket launcher",              2},
                                  {"PLAS",     "Plasmagun",                    2},
                                  {"BFUG",     "BFG9000",                      2},
                                  {"CLIP",     "Ammoclip",                     3},
                                  {"AMMO",     "Box of ammo",                  3},
                                  {"SHEL",     "Shells",                       3},
                                  {"SBOX",     "Box of shells",                3},
                                  {"ROCK",     "Rockets",                      3},
                                  {"BROK",     "Box of rockets",               3},
                                  {"CELL",     "Cells",                        3},
                                  {"CELP",     "Box of cells",                 3},
                                  {"BPAK",     "Backpack",                     3},
                                  {"BON1",     "Healthbonus",                  4},
                                  {"BON2",     "Armorbonus",                   4},
                                  {"STIM",     "Stimpack",                     4},
                                  {"MEDI",     "Medikit",                      4},
                                  {"ARM1",     "Green armor",                  4},
                                  {"ARM2",     "Blue armor",                   4},
                                  {"SOUL",     "Supercharge",                  4},
                                  {"PINS",     "Invisibility",                 4},
                                  {"PINV",     "Invulnerability",              4},
                                  {"PSTR",     "Berserk",                      4},
                                  {"PMAP",     "Computer area map",            4},
                                  {"PVIS",     "Light amplifier",              4},
                                  {"SUIT",     "Radiation suit",               4},
                                  {"BAR",      "Barrel",                       5},
                                  {"BEXP",     "Barrel exploding",             5},
                                  {"POL",      "Dead body",                    5},
                                  {"GOR",      "Hanging body",                 5},
                                  {"PBU",      NULL,                           6},
                                  {"PSH",      NULL,                           6},
                                  {"BAL",      NULL,                           6},
                                  {"PUF",      NULL,                           6},
                                  {"BLU",      NULL,                           6},
                                  {"MIS",      NULL,                           6},
                                  {"TFO",      NULL,                           6},
                                  {"BFS",      NULL,                           6},
                                  {"BFE",      NULL,                           6},
                                  {"CAND",     NULL,                           7},
                                  {"CBRA",     NULL,                           7},
                                  {"COLU",     NULL,                           7},
                                  {"ELEC",     NULL,                           7},
                                  {"TRED",     NULL,                           7},
                                  {"FSKU",     NULL,                           7},
                                  {"CEYE",     NULL,                           7},
                                  {"SMI",      NULL,                           7},
                                  {"TGRN",     NULL,                           7},
                                  {"TBLU",     NULL,                           7},
                                  {"SMRT",     NULL,                           7},
                                  {"SMBT",     NULL,                           7},
                                  {"SMGT",     NULL,                           7}};
struct     FieldId_s Sounds[]  = {{"DPPISTOL", "Pistol fire      "              },
                                  {"DSPISTOL", NULL                             },
                                  {"DPSHOTGN", "Shotgun fire     "              },
                                  {"DSSHOTGN", NULL                             },
                                  {"DPSGCOCK", "Shotgun cock     "              },
                                  {"DSSGCOCK", NULL                             },
                                  {"DPSAWUP",  "Chainsaw startup "              },
                                  {"DSSAWUP",  NULL                             },
                                  {"DPSAWIDL", "Chainsaw in rest "              },
                                  {"DSSAWIDL", NULL                             },
                                  {"DPSAWFUL", "Chainsaw active  "              },
                                  {"DSSAWFUL", NULL                             },
                                  {"DPSAWHIT", "Chainsaw hitting "              },
                                  {"DSSAWHIT", NULL                             },
                                  {"DPRLAUNC", "Rocket launch    "              },
                                  {"DSRLAUNC", NULL                             },
                                  {"DPRXPLOD", "BFG9000 launch   "              },
                                  {"DSRXPLOD", NULL                             },
                                  {"DPFIRSHT", "Fireball passing "              },
                                  {"DSFIRSHT", NULL                             },
                                  {"DPFIRXPL", "Fireball hitting "              },
                                  {"DSFIRXPL", NULL                             },
                                  {"DPPSTART", "Lift starting    "              },
                                  {"DSPSTART", NULL                             },
                                  {"DPPSTOP",  "Lift stopping    "              },
                                  {"DSPSTOP",  NULL                             },
                                  {"DPDOROPN", "Door opening     "              },
                                  {"DSDOROPN", NULL                             },
                                  {"DPDORCLS", "Door closing     "              },
                                  {"DSDORCLS", NULL                             },
                                  {"DPSTNMOV", "Floor moving     "              },
                                  {"DSSTNMOV", NULL                             },
                                  {"DPSWTCHN", "Switch returning "              },
                                  {"DSSWTCHN", NULL                             },
                                  {"DPSWTCHX", "Switch activated "              },
                                  {"DSSWTCHX", NULL                             },
                                  {"DPPLPAIN", "Player hurt      "              },
                                  {"DSPLPAIN", NULL                             },
                                  {"DPDMPAIN", "Trooper hurt     "              },
                                  {"DSDMPAIN", NULL                             },
                                  {"DPPOPAIN", "Sargeant hurt    "              },
                                  {"DSPOPAIN", NULL                             },
                                  {"DPSLOP",   "Total slaying    "              },
                                  {"DSSLOP",   NULL                             },
                                  {"DPITEMUP", "Item picked up   "              },
                                  {"DSITEMUP", NULL                             },
                                  {"DPWPNUP",  "Weapon picked up "              },
                                  {"DSWPNUP",  NULL                             },
                                  {"DPOOF",    "Player jumping   "              },
                                  {"DSOOF",    NULL                             },
                                  {"DPTELEPT", "Teleporter       "              },
                                  {"DSTELEPT", NULL                             },
                                  {"DPPOSIT1", "Trooper spots (1)"              },
                                  {"DSPOSIT1", NULL                             },
                                  {"DPPOSIT2", "Trooper spots (2)"              },
                                  {"DSPOSIT2", NULL                             },
                                  {"DPPOSIT3", "Trooper spots (3)"              },
                                  {"DSPOSIT3", NULL                             },
                                  {"DPBGSIT1", "Imp spots (1)    "              },
                                  {"DSBGSIT1", NULL                             },
                                  {"DPBGSIT2", "Imp spots (2)    "              },
                                  {"DSBGSIT2", NULL                             },
                                  {"DPSGTSIT", "Spectre spots    "              },
                                  {"DSSGTSIT", NULL                             },
                                  {"DPBRSSIT", "Baron spots      "              },
                                  {"DSBRSSIT", NULL                             },
                                  {"DPSGTATK", "Spectre attacks  "              },
                                  {"DSSGTATK", NULL                             },
                                  {"DPCLAW",   "Spectre hits     "              },
                                  {"DSCLAW",   NULL                             },
                                  {"DPPLDETH", "Player died      "              },
                                  {"DSPLDETH", NULL                             },
                                  {"DPPODTH1", "Trooper died (1) "              },
                                  {"DSPODTH1", NULL                             },
                                  {"DPPODTH2", "Trooper died (2) "              },
                                  {"DSPODTH2", NULL                             },
                                  {"DPPODTH3", "Trooper died (3) "              },
                                  {"DSPODTH3", NULL                             },
                                  {"DPBGDTH1", "Imp died (1)     "              },
                                  {"DSBGDTH1", NULL                             },
                                  {"DPBGDTH2", "Imp died (2)     "              },
                                  {"DSBGDTH2", NULL                             },
                                  {"DPSGTDTH", "Spectre died     "              },
                                  {"DSSGTDTH", NULL                             },
                                  {"DPBRSDTH", "Baron died       "              },
                                  {"DSBRSDTH", NULL                             },
                                  {"DPPOSACT", "Trooper nearby   "              },
                                  {"DSPOSACT", NULL                             },
                                  {"DPBGACT",  "Imp nearby       "              },
                                  {"DSBGACT",  NULL                             },
                                  {"DPDMACT",  "Spectre nearby   "              },
                                  {"DSDMACT",  NULL                             },
                                  {"DPNOWAY",  "Pushed on wall   "              },
                                  {"DSNOWAY",  NULL                             },
                                  {"DPBAREXP", "Barrel exploding "              },
                                  {"DSBAREXP", NULL                             },
                                  {"DPPUNCH",  "Player punching  "              },
                                  {"DSPUNCH",  NULL                             },
                                  {"DPPLASMA", "Plasmagun fire   "              },
                                  {"DSPLASMA", NULL                             },
                                  {"DPBFG",    "BFG9000 fire     "              },
                                  {"DSBFG",    NULL                             },
                                  {"DPCACSIT", "Caco Demon spots "              },
                                  {"DSCACSIT", NULL                             },
                                  {"DPCYBSIT", "Cyber Demon spots"              },
                                  {"DSCYBSIT", NULL                             },
                                  {"DPSPISIT", "Spider spots     "              },
                                  {"DSSPISIT", NULL                             },
                                  {"DPSKLATK", "Lost Soul attacks"              },
                                  {"DSSKLATK", NULL                             },
                                  {"DPCACDTH", "Caco Demon died  "              },
                                  {"DSCACDTH", NULL                             },
                                  {"DPSKLDTH", "Lost Soul died   "              },
                                  {"DSSKLDTH", NULL                             },
                                  {"DPCYBDTH", "Cyber Demon died "              },
                                  {"DSCYBDTH", NULL                             },
                                  {"DPSPIDTH", "Spider Demon died"              },
                                  {"DSSPIDTH", NULL                             },
                                  {"DPHOOF",   "Cyber Demon walks"              },
                                  {"DSHOOF",   NULL                             },
                                  {"DPMETAL",  "Metal (?)        "              },
                                  {"DSMETAL",  NULL                             }};
dbyte LineDefDoorLift[]        =  {  1,  21,  26,  27,  28,  31,  32,  33,  34,  99, 117, 118, 133, 134, 135, 136, 137};
dbyte LineDefSwitch[]          =  {  7,   9,  14,  15,  18,  20,  21,  23,  29,  41,  42,  43,  45,  50,  60,  61,  62,  63,  64,
                                    65,  66,  67,  68,  69,  70,  71, 101, 102, 103, 111, 112, 113, 114, 115, 116, 122, 123, 127,
                                   131, 132, 140};
dbyte LineDefEndLevel[]        =  { 11,  51,  52,  124};

#ifdef _AMIGA_
struct GfxBase       *GfxBase;                                                                     /* Pointer to graphics library */
struct IntuitionBase *IntuitionBase;                                                              /* Pointer to intuition library */
struct Screen        *Screen;                                                                        /* Pointer to current screen */
struct Window        *Window;                                                                        /* Pointer to current window */
struct NewScreen      FirstScreen  = {0, 0, 640, 256, 4, DBLACK, DBLACK, HIRES, CUSTOMSCREEN, NULL, NULL, NULL, NULL};
struct NewScreen      SecondScreen = {0, 0, 640, 512, 4, DBLACK, DBLACK, HIRES | LACE, CUSTOMSCREEN, NULL, NULL, NULL, NULL};
struct NewWindow      FirstWindow  = {0, 0, 640, 256, DBLACK, DBLACK, VANILLAKEY, BORDERLESS | ACTIVATE | SMART_REFRESH, NULL, NULL,
                                      NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN};
struct NewWindow      SecondWindow = {0, 0, 640, 480, DBLACK, DBLACK, VANILLAKEY, BORDERLESS | ACTIVATE | SMART_REFRESH, NULL, NULL,
                                      NULL, NULL, NULL, 0, 0, 0, 0, CUSTOMSCREEN};
struct IntuiMessage  *IntuiMessage;                                                                     /* Message from intuition */
unsigned long         MessageClass;                                                                                  /* 'From' ID */
unsigned short        Code;                                                                               /* Value of the message */
boolean               InLaceMode;
#else
unsigned int          Key;
#endif

void PrText (short Y0, short X0, unsigned char Color, char *Msg, ...)

/**********************************************************************************************************************************/
/* Pre   : 'Y0' and 'X0' hold the coordinates, 'Color' holds the (VGA) color and 'Msg' holds the message to print.                */
/* Post  : If the coordinates were non-zero, then the message is printed at these coordinates in the given color. In case of the  */
/*         AMIGA, the coordinates have been converted from pixel- to textcoordinates.                                             */
/*         If X0 = 0, then the coordinates are not used;                                                                          */
/*         If X0 = -1, then the text is centered on line Y0.                                                                      */
/* Import: None.                                                                                                                  */
/**********************************************************************************************************************************/

{
  char         Message[80];
  va_list      Args;
  int register X1;
  int register Y1;

  va_start (Args, Msg);
  vsprintf (Message, Msg, Args);                                                           /* Convert the message into one string */
  va_end (Args);
#ifdef _AMIGA_
  X1 = X0 * 8;                                                                                           /* Fontwidth is 8 pixels */
  Y1 = Y0 * 8 + 18;                                                     /* Fontheight is 8 pixels, start past the window titlebar */
  if (X0 == -1)
    X1 = ((80 - strlen (Message)) / 2) * 8;
  if (X0 != 0)
    Move (&Screen->RastPort, X1, Y1);
  SetAPen (&Screen->RastPort, Color);
  Text (&Screen->RastPort, Message, strlen (Message));
#else
  if (X0 == -1)
    _settextposition (Y0, (80 - strlen (Message)) / 2);
  if (X0 > 0)
    _settextposition (Y0, X0);
  _settextcolor (Color);
  _outtext (Message);
#endif
}

void ClearScreen (void)

/**********************************************************************************************************************************/
/* Pre   : None.                                                                                                                  */
/* Post  : The screen has been cleared.                                                                                           */
/* Import: PrText.                                                                                                                */
/**********************************************************************************************************************************/

{
#ifdef _AMIGA_
  RectFill (&Screen->RastPort, 0, 0, 640, 256);
#else
  _clearscreen (_GCLEARSCREEN);
#endif
}

#ifdef _AMIGA_

  void CloseAllIntuition (void)

  /********************************************************************************************************************************/
  /* Pre   : None.                                                                                                                */
  /* Post  : All windows and screens have been closed, all libraries have been released.                                          */
  /* Import: None.                                                                                                                */
  /********************************************************************************************************************************/

  {
    if (Window)
      CloseWindow (Window);
    if (Screen)
      CloseScreen (Screen);
    if (IntuitionBase)
      CloseLibrary (IntuitionBase);
    if (GfxBase)
      CloseLibrary (GfxBase);
  }

  void SwapDbyte (dbyte *Number)

  /********************************************************************************************************************************/
  /* Pre   : 'Number' holds a pointer to the dbyte that should be swapped.                                                        */
  /* Post  : The number is converted from Little Endian to Big Endian (or vice versa).                                            */
  /* Import: None.                                                                                                                */
  /********************************************************************************************************************************/

  {
    unsigned char *Cp;
    unsigned char  Temp;
  
    Cp = (unsigned char *)Number;
    Temp = *Cp;
    *Cp = *(Cp + 1);
    *(Cp + 1) = Temp;
  }

  void SwapLong (unsigned long *Number)

  /********************************************************************************************************************************/
  /* Pre   : 'Number' holds a pointer to the long that should be swapped.                                                         */
  /* Post  : The number is converted from Little Endian to Big Endian (or vice versa).                                            */
  /* Import: None.                                                                                                                */
  /********************************************************************************************************************************/

  {
    unsigned char *Cp;
    unsigned char  Temp;
  
    Cp = (unsigned char *)Number;
    Temp = *Cp;                                                                                             /* Swap bytes 0 and 3 */
    *Cp = *(Cp + 3);
    *(Cp + 3) = Temp;
    Temp = *(Cp + 1);                                                                                       /* Swap bytes 1 and 2 */
    *(Cp + 1) = *(Cp + 2);
    *(Cp + 2) = Temp;
  }

#endif

void Bye (char *Message)

/**********************************************************************************************************************************/
/* Pre   : 'Message' holds the errormessage.                                                                                      */
/* Post  : 'Message' has been printed, any open file has been closed and the program is aborted.                                  */
/* Import: CloseAllIntuition.                                                                                                     */
/**********************************************************************************************************************************/

{
  #ifdef _AMIGA_
    CloseAllIntuition ();
  #else
    fcloseall ();
    flushall ();
    _setvideomode (_DEFAULTMODE);
  #endif
  fprintf (stderr, "%s\n", Message);
  exit (0);
}

#ifdef _AMIGA_

  void SetPalette (void)

  /********************************************************************************************************************************/
  /* Pre   : None.                                                                                                                */
  /* Post  : The 16-color palette has been loaded for the current screen. The colors should match the default VGA colors from the */
  /*         PC.                                                                                                                  */
  /* Import: None.                                                                                                                */
  /********************************************************************************************************************************/

  {
    SetRGB4 (&Screen->ViewPort, DBLACK  ,  0,  0,  0);                                /* Convert the palette to standard VGA (PC) */
    SetRGB4 (&Screen->ViewPort, DBLUE   ,  0,  0,  8);
    SetRGB4 (&Screen->ViewPort, DGREEN  ,  0,  8,  0);
    SetRGB4 (&Screen->ViewPort, DCYAN   ,  0,  8,  8);
    SetRGB4 (&Screen->ViewPort, DRED    ,  8,  0,  0);
    SetRGB4 (&Screen->ViewPort, DMAGENTA,  8,  0,  8);
    SetRGB4 (&Screen->ViewPort, DYELLOW ,  8,  8,  0);
    SetRGB4 (&Screen->ViewPort, DWHITE  ,  8,  8,  8);
    SetRGB4 (&Screen->ViewPort, LBLACK  ,  5,  5,  5);
    SetRGB4 (&Screen->ViewPort, LBLUE   ,  0,  0, 15);
    SetRGB4 (&Screen->ViewPort, LGREEN  ,  0, 15,  0);
    SetRGB4 (&Screen->ViewPort, LCYAN   ,  0, 15, 15);
    SetRGB4 (&Screen->ViewPort, LRED    , 15,  0,  0);
    SetRGB4 (&Screen->ViewPort, LMAGENTA, 15,  0, 15);
    SetRGB4 (&Screen->ViewPort, LYELLOW , 15, 15,  0);
    SetRGB4 (&Screen->ViewPort, LWHITE  , 15, 15, 15);
  }

  void OpenAllIntuition (void)

  /********************************************************************************************************************************/
  /* Pre   : None.                                                                                                                */
  /* Post  : First the graphics and intuition libraries have been opened. After this a screen has been opened, in a resolution of */
  /*         640x256x16, without titlebar. After this has a window been opened with the exact same size, which is layed over the  */
  /*         screen. Finally, the palette has been converted to match the standard VGA colors of the PC.                          */
  /* Import: Bye.                                                                                                                 */
  /********************************************************************************************************************************/

  {
    if (!(GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", 0L)))                                /* Open the libraries */
      Bye ("ERROR - Graphics Library not found\n");
    if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library", 0L)))
      Bye ("ERROR - Intuition Library not found\n");
    if (!(Screen = (struct Screen *)OpenScreen (&FirstScreen)))                                                /* Open the screen */
      Bye ("ERROR - Cannot open screen\n");
    FirstWindow.Screen = Screen;                                                                /* Link the window to this screen */
    if (!(Window = (struct Window *)OpenWindow (&FirstWindow)))                                                /* Open the window */
      Bye ("ERROR - Cannot open window\n");
    SetPalette ();
    InLaceMode = FALSE;
  }

#endif

void ListSprites (void)

/**********************************************************************************************************************************/
/* Pre   : None.                                                                                                                  */
/* Post  : The new sprites in this WAD file have been listed on a cleared screen.                                                 */
/* Import: ClearScreen, PrText.                                                                                                   */
/**********************************************************************************************************************************/

{
  int register Cnt;
  int register Xco       = 1;
  int register Yco       = 3;
  boolean      Type6Done = FALSE;
  boolean      Type7Done = FALSE;
  boolean      AdjustCo;

  ClearScreen ();
  PrText (1, -1, LBLUE, "NEW SPRITES IN THIS WAD FILE:");
  for (Cnt = 0 ; Cnt < MAXSPRITES ; Cnt ++)
    if (Sprites[Cnt].FieldFilled)
    {
      AdjustCo = TRUE;
      switch (Sprites[Cnt].Type)
      {
        case 0 : PrText (Yco, Xco, DCYAN, "ENEMY  ");
                 PrText (  0,   0, LCYAN, Sprites[Cnt].Description);
                 break;
        case 1 : PrText (Yco, Xco, DCYAN, "CARD   ");
                 PrText (  0,   0, LCYAN, Sprites[Cnt].Description);
                 break;
        case 2 : PrText (Yco, Xco, DCYAN, "WEAPON ");
                 PrText (  0,   0, LCYAN, Sprites[Cnt].Description);
                 break;
        case 3 : PrText (Yco, Xco, DCYAN, "AMMO   ");
                 PrText (  0,   0, LCYAN, Sprites[Cnt].Description);
                 break;
        case 4 : PrText (Yco, Xco, DCYAN, "BONUS  ");
                 PrText (  0,   0, LCYAN, Sprites[Cnt].Description);
                 break;
        case 5 : PrText (Yco, Xco, DCYAN, "DECOR  ");
                 PrText (  0,   0, LCYAN, Sprites[Cnt].Description);
                 break;
        case 6 : if (!Type6Done)
                 {
                   PrText (Yco, Xco, LCYAN, "Miscelanious weaponfire");
                   Type6Done = TRUE;
                 }
                 else
                   AdjustCo = FALSE;
                 break;
        case 7 : if (!Type7Done)
                 {
                   PrText (Yco, Xco, LCYAN, "Miscelanious decorations");
                   Type7Done = TRUE;
                 }
                 else
                   AdjustCo = FALSE;
                 break;
        default: PrText (Yco, Xco, LRED, "Unknown type %d for %s", Sprites[Cnt].Type, Sprites[Cnt].IdName);
      }
      if (AdjustCo)
        if (++ Yco > 26)
        {
          Yco = 3;
          Xco += 26;
        }
    }
  PrText (28, -1, DYELLOW, "Any key to return...");
}
      
void ListMenus (void)

/**********************************************************************************************************************************/
/* Pre   : None.                                                                                                                  */
/* Post  : The new menu items in this WAD file have been listed on a cleared screen.                                              */
/* Import: ClearScreen, PrText.                                                                                                   */
/**********************************************************************************************************************************/

{
  int register Cnt;
  int register Xco = 1;
  int register Yco = 3;

  ClearScreen ();
  PrText (1, -1, LBLUE, "NEW MENU ITEMS IN THIS WAD FILE:");
  for (Cnt = 0 ; Cnt < MAXMENUS ; Cnt ++)
    if (Menus[Cnt].FieldFilled)
    {
      switch (Menus[Cnt].Type)
      {
        case 0 : PrText (Yco, Xco, DCYAN, "MAIN MENU ");
                 PrText (  0,   0, LCYAN, "\'%s\'", Menus[Cnt].Description);
                 break;
        case 1 : PrText (Yco, Xco, DCYAN, "SUBMENU   ");
                 PrText (  0,   0, LCYAN, "\'%s\'", Menus[Cnt].Description);
                 break;
        case 2 : PrText (Yco, Xco, DCYAN, "PLAYING   ");
                 PrText (  0,   0, LCYAN, "\'%s\'", Menus[Cnt].Description);
                 break;
        case 3 : PrText (Yco, Xco, DCYAN, "MISC      ");
                 PrText (  0,   0, LCYAN, Menus[Cnt].Description);
      }
      if (++ Yco > 26)
      {
        Yco = 3;
        Xco += 36;
      }
    }
  PrText (28, -1, DYELLOW, "Any key to return...");
}
      
void ListMusic (void)

/**********************************************************************************************************************************/
/* Pre   : None.                                                                                                                  */
/* Post  : The new music in this WAD file has been listed on a cleared screen.                                                    */
/* Import: ClearScreen, PrText.                                                                                                   */
/**********************************************************************************************************************************/

{
  int register Cnt;
  int register Xco  = 1;
  int register Yco  = 3;

  ClearScreen ();
  PrText (1, -1, LBLUE, "NEW MUSIC IN THIS WAD FILE:");
  for (Cnt = 0 ; Cnt < MAXMUSIC ; Cnt ++)
    if (Music[Cnt].FieldFilled)
    {
      PrText (Yco, Xco, LCYAN, Music[Cnt].Description);
      if (++ Yco > 26)
      {
        Yco = 3;
        Xco += 36;
      }
    }
  PrText (28, -1, DYELLOW, "Any key to return...");
}
      
void ListSounds (void)

/**********************************************************************************************************************************/
/* Pre   : None.                                                                                                                  */
/* Post  : The new sounds in this WAD file have been listed on a cleared screen.                                                  */
/* Import: ClearScreen, PrText.                                                                                                   */
/**********************************************************************************************************************************/

{
  int register Cnt;
  int register Xco  = 1;
  int register Yco  = 4;

  ClearScreen ();
  PrText (1, -1, LBLUE, "NEW SOUNDS IN THIS WAD FILE:");
  PrText (2, -1, LBLUE, "\'Spectre\' means \'Demon & Spectre\', \'spots\' means \'spots player\'");
  for (Cnt = 0 ; Cnt < MAXSOUNDS ; Cnt += 2)
    if (Sounds[Cnt].FieldFilled || Sounds[Cnt + 1].FieldFilled)
    {
      PrText (Yco, Xco, DCYAN, "[%2d] ", (Cnt / 2) + 1);
      PrText (  0,   0, LCYAN, Sounds[Cnt].Description);
      if (++ Yco > 26)
      {
        Yco = 4;
        Xco += 27;
      }
    }
  PrText (28, -1, DYELLOW, "Any key to return...");
}
      
void ViewLevel (FILE *Fp, dbyte MemNum)

/**********************************************************************************************************************************/
/* Pre   : 'Fp' points to the open WAD file, 'MemNum' holds the ('Remember') level number to check.                               */
/* Post  : The map of the pointed level has been drawn, using different colors for all types of the lines. The colors are:        */
/*         Secret door                         : DGREEN                                                                           */
/*         Regular door (press the door itself): LYELLOW                                                                          */
/*         Switch                              : LBLUE                                                                            */
/*         Level 'ender'                       : LMAGENTA                                                                         */
/*         Regular wall                        : DRED                                                                             */
/*         All others                          : LBLACK                                                                           */
/* Import: ClearScreen, PrText, SwapDbyte, Bye.                                                                                   */
/**********************************************************************************************************************************/

{
  struct LineDef_s  LineDef;
  struct Vertex_s  *VertexInfo;
  dbyte register    N;
  dbyte register    Divider;
  dbyte register    NumberOfVertexes;
  long  register    Entries;
  boolean           More;
  unsigned char     Color;
  short register    OffsetX;
  short register    OffsetY;

#ifdef _AMIGA_
  CloseWindow (Window);                                                                              /* Close the 'normal' screen */
  CloseScreen (Screen);
  if (!(Screen = (struct Screen *)OpenScreen (&SecondScreen)))                      /* Open the interlaced (double-height) screen */
    Bye ("ERROR - Cannot open screen\n");
  SecondWindow.Screen = Screen;
  if (!(Window = (struct Window *)OpenWindow (&SecondWindow)))
    Bye ("ERROR - Cannot open window\n");
  SetPalette ();
  InLaceMode = TRUE;
#else
  ClearScreen ();
#endif
  NumberOfVertexes = Remember[MemNum].VertexLoc.Size / sizeof (struct Vertex_s);
  if ((VertexInfo = ((struct Vertex_s *)malloc ((size_t)(sizeof (struct Vertex_s) * NumberOfVertexes)))) == NULL)
    Bye ("ERROR - Could not allocate enough memory\n");
  if (fseek (Fp, Remember[MemNum].VertexLoc.Start, SEEK_SET))
    Bye ("ERROR - File location error\n");
  if (fread (VertexInfo, 1, sizeof (struct Vertex_s), Fp) != sizeof (struct Vertex_s))                       /* Read first vertex */
    Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
  SwapDbyte (&VertexInfo->MapX);
  SwapDbyte (&VertexInfo->MapY);
#endif
  Remember[MemNum].MinMapX = Remember[MemNum].MaxMapX = VertexInfo->MapX;
  Remember[MemNum].MinMapY = Remember[MemNum].MaxMapY = VertexInfo->MapY;
  N = 1;
  Entries = sizeof (struct Vertex_s);
  while (Entries < Remember[MemNum].VertexLoc.Size)                                                         /* Handle all entries */
  {
    if (fread ((VertexInfo + N), 1, sizeof (struct Vertex_s), Fp) != sizeof (struct Vertex_s))
      Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
    SwapDbyte (&(VertexInfo + N)->MapX);
    SwapDbyte (&(VertexInfo + N)->MapY);
#endif
    if ((VertexInfo + N)->MapX < Remember[MemNum].MinMapX)
      Remember[MemNum].MinMapX = (VertexInfo + N)->MapX;
    if ((VertexInfo + N)->MapX > Remember[MemNum].MaxMapX)
      Remember[MemNum].MaxMapX = (VertexInfo + N)->MapX;
    if ((VertexInfo + N)->MapY < Remember[MemNum].MinMapY)
      Remember[MemNum].MinMapY = (VertexInfo + N)->MapY;
    if ((VertexInfo + N)->MapY > Remember[MemNum].MaxMapY)
      Remember[MemNum].MaxMapY = (VertexInfo + N)->MapY;
    Entries += sizeof (struct Vertex_s);
    N ++;
  }
  Remember[MemNum].MapSizeX = Remember[MemNum].MaxMapX - Remember[MemNum].MinMapX + 1;                       /* Include BOTH ends */
  Remember[MemNum].MapSizeY = Remember[MemNum].MaxMapY - Remember[MemNum].MinMapY + 1;
  Divider = ceil((double)Remember[MemNum].MapSizeX / 640);
  if ((ceil ((double)Remember[MemNum].MapSizeY / 480)) > Divider)
    Divider = ceil ((double)Remember[MemNum].MapSizeY / 480);
  OffsetX = (640 - (Remember[MemNum].MapSizeX / Divider)) / 2;
  OffsetY = (480 - (Remember[MemNum].MapSizeY / Divider)) / 2;
  Entries = 0;
  if (fseek (Fp, Remember[MemNum].LineDefLoc.Start, SEEK_SET))
    Bye ("ERROR - File location error\n");
  while (Entries < Remember[MemNum].LineDefLoc.Size)                                                        /* Handle all entries */
  {
    if (fread (&LineDef, 1, sizeof (struct LineDef_s), Fp) != sizeof (struct LineDef_s))
      Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
    SwapDbyte (&LineDef.Start);
    SwapDbyte (&LineDef.End);
    SwapDbyte (&LineDef.Flags);
    SwapDbyte (&LineDef.Type);
    SwapDbyte (&LineDef.Tag);
    SwapDbyte (&LineDef.SideDef1);
    SwapDbyte (&LineDef.SideDef2);
#endif
    if (LineDef.Flags & 0x0020)                                                                                         /* Secret */
      Color = DGREEN;
    else
      if (LineDef.Flags & 0x0080)                                                                                   /* Not on map */
	Color = LBLACK;
      else
	if (LineDef.Type)
	{
	  More = TRUE;
	  Color = LBLACK;
	  for (N = 0 ; N < MAXLINEDRLF && More; N ++)
	    if (LineDef.Type == LineDefDoorLift[N])
	    {
	      More = FALSE;
	      Color = LYELLOW;
	    }
	  if (More)
	    for (N = 0 ; N < MAXLINESWITCH && More; N ++)
	      if (LineDef.Type == LineDefSwitch[N])
	      {
		More = FALSE;
		Color = LBLUE;
	      }
	  if (More)
	    for (N = 0 ; N < MAXLINEEND && More; N ++)
	      if (LineDef.Type == LineDefEndLevel[N])
	      {
		More = FALSE;
		Color = LMAGENTA;
	      }
	}
	else
	  if ((LineDef.Flags & 0x0018) == 0x0018)                                        /* Both upper and lower texture unpegged */
	    Color = DYELLOW;
	  else
	    if (LineDef.Flags & 0x005E)                                                /* Blocks sound, unpegged and/or two-sided */
	      Color = LBLACK;
	    else
	      Color = DRED;
#ifdef _AMIGA_
    SetAPen (&Screen->RastPort, Color);
    Move (&Screen->RastPort, (short)(((VertexInfo + LineDef.Start)->MapX - Remember[MemNum].MinMapX) / Divider) + OffsetX,
	                     (short)(479 - ((VertexInfo + LineDef.Start)->MapY - Remember[MemNum].MinMapY) / Divider) - OffsetY);
    Draw (&Screen->RastPort, (short)(((VertexInfo + LineDef.End)->MapX - Remember[MemNum].MinMapX) / Divider) + OffsetX,
	                     (short)(479 - ((VertexInfo + LineDef.End)->MapY - Remember[MemNum].MinMapY) / Divider) - OffsetY);
#else
    _setcolor (Color);
    _moveto ((short)(((VertexInfo + LineDef.Start)->MapX - Remember[MemNum].MinMapX) / Divider) + OffsetX,
	     (short)(479 - ((VertexInfo + LineDef.Start)->MapY - Remember[MemNum].MinMapY) / Divider) - OffsetY);
    _lineto ((short)(((VertexInfo + LineDef.End)->MapX - Remember[MemNum].MinMapX) / Divider) + OffsetX,
	     (short)(479 - ((VertexInfo + LineDef.End)->MapY - Remember[MemNum].MinMapY) / Divider) - OffsetY);
#endif
    Entries += sizeof (struct LineDef_s);
  }
  free (VertexInfo);
}

void CheckLevel (FILE *Fp, dbyte MemNum)

/**********************************************************************************************************************************/
/* Pre   : 'Fp' points to the open WAD file, 'MemNum' holds the ('Remember') level number to check.                               */
/* Post  : The following tests have been made:                                                                                    */
/*         - All LINEDEFS have a length of > 0;                                                                                   */
/*         - All LINEDEFS use existing SIDEDEF numbers;                                                                           */
/*         - All LINEDEFS use existing VERTEX numbers for Start and End values;                                                   */
/*         - The BLOCKMAP start is <= lowest VERTEX number;                                                                       */
/*         - The number of blocks in the BLOCKMAP is enough to fit the map;                                                       */
/*         - All blocks contents in the BLOCKMAP start with a 0x0000 and end with a 0xFFFF;                                       */
/*         - All used LINEDEFS in the BLOCKMAP exist;                                                                             */
/*         - All used LINEDEFS in a block of the BLOCKMAP are indeed in the block (starting, ending or crossing);                 */
/*         - The length of the REJECT data is ((number_of_SECTORS ^ 2) / 8), rounded upwards.                                     */
/*         - All THINGS have valid coordinates;                                                                                   */
/*         - All THINGS have valid angles of appearance;                                                                          */
/*         - All THINGS are of known type;                                                                                        */
/* Import: PrText, SwapDbyte, Bye.                                                                                                */
/**********************************************************************************************************************************/

{
  struct BlockMapHeader_s BlockMapHeader;
  struct LineDef_s        LineDef;
  struct Vertex_s        *VertexInfo;
  struct Check_s         *LineInfo;
  dbyte                  *BlockInfo;
  dbyte register          BlockOffset;
  dbyte register          BlockNumber;
  dbyte register          N;
  dbyte                   TestMapX;
  dbyte                   TestMapY;
  dbyte                   TestMapX2;
  dbyte                   TestMapY2;
  dbyte                   NumberOfLineDefs;
  dbyte                   NumberOfSideDefs;
  dbyte                   NumberOfVertexes;
  dbyte                   BlockMinX;
  dbyte                   BlockMinY;
  dbyte                   BlockMaxX;
  dbyte                   BlockMaxY;
  dbyte register          CntX;
  dbyte register          CntY;
  dbyte                   LineDefNumber;
  char                    NextLine;
  long                    Entries;
  size_t                  BlockMapInfoSize;
  boolean                 More;

  for (N = 3 ; N <= 30 ; N ++)
    PrText (N, 40, DBLACK, "                                       ");
  NextLine = 3;
  NumberOfLineDefs = Remember[MemNum].LineDefLoc.Size / sizeof (struct LineDef_s);
  NumberOfSideDefs = Remember[MemNum].SideDefLoc.Size / sizeof (struct SideDef_s);
  NumberOfVertexes = Remember[MemNum].VertexLoc.Size / sizeof (struct Vertex_s);
  if ((LineInfo = ((struct Check_s *)malloc ((size_t)(sizeof (struct Check_s) * NumberOfLineDefs)))) == NULL)
    Bye ("ERROR - Could not allocate enough memory\n");
  if ((VertexInfo = ((struct Vertex_s *)malloc ((size_t)(sizeof (struct Vertex_s) * NumberOfVertexes)))) == NULL)
    Bye ("ERROR - Could not allocate enough memory\n");
  PrText (1, 68, DWHITE, "Loading...");
  if (fseek (Fp, Remember[MemNum].VertexLoc.Start, SEEK_SET))
    Bye ("ERROR - File location error\n");
  if (fread (VertexInfo, 1, sizeof (struct Vertex_s), Fp) != sizeof (struct Vertex_s))                       /* Read first vertex */
    Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
  SwapDbyte (&VertexInfo->MapX);
  SwapDbyte (&VertexInfo->MapY);
#endif
  Remember[MemNum].MinMapX = Remember[MemNum].MaxMapX = VertexInfo->MapX;
  Remember[MemNum].MinMapY = Remember[MemNum].MaxMapY = VertexInfo->MapY;
  N = 1;
  Entries = sizeof (struct Vertex_s);
  while (Entries < Remember[MemNum].VertexLoc.Size)                                                         /* Handle all entries */
  {
    if (fread ((VertexInfo + N), 1, sizeof (struct Vertex_s), Fp) != sizeof (struct Vertex_s))
      Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
    SwapDbyte (&(VertexInfo + N)->MapX);
    SwapDbyte (&(VertexInfo + N)->MapY);
#endif
    if ((VertexInfo + N)->MapX < Remember[MemNum].MinMapX)
      Remember[MemNum].MinMapX = (VertexInfo + N)->MapX;
    if ((VertexInfo + N)->MapX > Remember[MemNum].MaxMapX)
      Remember[MemNum].MaxMapX = (VertexInfo + N)->MapX;
    if ((VertexInfo + N)->MapY < Remember[MemNum].MinMapY)
      Remember[MemNum].MinMapY = (VertexInfo + N)->MapY;
    if ((VertexInfo + N)->MapY > Remember[MemNum].MaxMapY)
      Remember[MemNum].MaxMapY = (VertexInfo + N)->MapY;
    Entries += sizeof (struct Vertex_s);
    N ++;
  }
  Remember[MemNum].MapSizeX = Remember[MemNum].MaxMapX - Remember[MemNum].MinMapX + 1;                       /* Include BOTH ends */
  Remember[MemNum].MapSizeY = Remember[MemNum].MaxMapY - Remember[MemNum].MinMapY + 1;
  PrText (NextLine, 40, DMAGENTA, "LINEDEFS consistency check:");
  if (fseek (Fp, Remember[MemNum].LineDefLoc.Start, SEEK_SET))
    Bye ("ERROR - File location error\n");
  Entries = 0;
  N = 0;
  More = TRUE;
  while (Entries < Remember[MemNum].LineDefLoc.Size)                                                        /* Handle all entries */
  {
    if (fread (&LineDef, 1, sizeof (struct LineDef_s), Fp) != sizeof (struct LineDef_s))
      Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
    SwapDbyte (&LineDef.Start);
    SwapDbyte (&LineDef.End);
    SwapDbyte (&LineDef.Flags);
    SwapDbyte (&LineDef.Type);
    SwapDbyte (&LineDef.Tag);
    SwapDbyte (&LineDef.SideDef1);
    SwapDbyte (&LineDef.SideDef2);
#endif
    if (LineDef.Start == LineDef.End)                                                               /* A LineDef with zero length */
    {
      PrText (NextLine + 1, 42, LRED, "LineDef %d has zero length", N);
      More = FALSE;
    }
    else
      if (LineDef.SideDef1 >= NumberOfSideDefs || (LineDef.SideDef2 != 0xFFFF && LineDef.SideDef2 >= NumberOfSideDefs))
      {                                                                                                 /* Non-existent SideDef ? */
	PrText (NextLine + 1, 42, LRED, "LineDef %d has an unknown SideDef", N);
	More = FALSE;
      }
    if (LineDef.Start >= NumberOfVertexes || LineDef.End >= NumberOfVertexes)                            /* Non-existent Vertex ? */
    {
      if (More)                                                                             /* Already an error-message printed ? */
	PrText (NextLine + 1, 42, LRED, "LineDef %d has an unknown Vertex", N);
      (LineInfo + N)->StartMapX = 0x8000;                                          /* Ensure that the coordinates are off the map */
      (LineInfo + N)->StartMapY = 0x8000;
      (LineInfo + N)->EndMapX = 0x8000;
      (LineInfo + N)->EndMapY = 0x8000;
      More = FALSE;
    }
    else
    {
      (LineInfo + N)->StartMapX = (VertexInfo + LineDef.Start)->MapX;
      (LineInfo + N)->StartMapY = (VertexInfo + LineDef.Start)->MapY;
      (LineInfo + N)->EndMapX = (VertexInfo + LineDef.End)->MapX;
      (LineInfo + N)->EndMapY = (VertexInfo + LineDef.End)->MapY;
    }
    N ++;
    Entries += sizeof (struct LineDef_s);
  }
  if (More)
  {
    PrText (NextLine, 73, LMAGENTA, "Passed");
    NextLine += 2;
  }
  else
  {
    PrText (NextLine, 73, LRED, "FAILED");
    NextLine += 3;
  }
  free (VertexInfo);
  if (fseek (Fp, Remember[MemNum].BlockMapLoc.Start, SEEK_SET))
    Bye ("ERROR - File location error\n");
  if (fread (&BlockMapHeader, 1, sizeof (struct BlockMapHeader_s), Fp) != sizeof (struct BlockMapHeader_s))
    Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
  SwapDbyte (&BlockMapHeader.OriginX);
  SwapDbyte (&BlockMapHeader.OriginY);
  SwapDbyte (&BlockMapHeader.BlockCntX);
  SwapDbyte (&BlockMapHeader.BlockCntY);
#endif
  BlockMapInfoSize = (size_t)(Remember[MemNum].BlockMapLoc.Size - sizeof (struct BlockMapHeader_s));
  if ((BlockInfo = ((dbyte *)malloc (BlockMapInfoSize))) == NULL)
    Bye ("ERROR - Could not allocate enough memory\n");
  if (fread (BlockInfo, 1, BlockMapInfoSize, Fp) != BlockMapInfoSize)
    Bye ("ERROR - File read error\n");
  PrText (1, 68, DWHITE, "          ");
#ifdef _AMIGA_
  for (N = 0 ; N < (BlockMapInfoSize / sizeof (dbyte)) ; N ++)
    SwapDbyte (BlockInfo + N);
#endif
  PrText (NextLine, 40, DMAGENTA, "BLOCKMAP   structure check:");
  More = TRUE;
  PrText (NextLine + 2, 40, LGREEN, "Origin (bottom-left) : (%5d, %5d) ", BlockMapHeader.OriginX, BlockMapHeader.OriginY);
  if (((BlockMapHeader.OriginX <= Remember[MemNum].MinMapX) || (BlockMapHeader.OriginX >= (Remember[MemNum].MinMapX - 0x007F))) &&
      ((BlockMapHeader.OriginY <= Remember[MemNum].MinMapY) || (BlockMapHeader.OriginY >= (Remember[MemNum].MinMapY - 0x007F))))
    PrText (0, 0, LMAGENTA, "+");
  else
  {
    PrText (0, 0, LRED, "X");
    More = FALSE;
  }
  PrText (NextLine + 3, 40, LGREEN, "Number of blocks     :  %5d x%5d  ", BlockMapHeader.BlockCntX, BlockMapHeader.BlockCntY);
  TestMapX = Remember[MemNum].MapSizeX / 0x0080 + ((Remember[MemNum].MapSizeX & 0x007F) ? 1 : 0);
  TestMapY = Remember[MemNum].MapSizeY / 0x0080 + ((Remember[MemNum].MapSizeY & 0x007F) ? 1 : 0);
  if ((BlockMapHeader.BlockCntX >= TestMapX) && (BlockMapHeader.BlockCntY >= TestMapY))
    PrText (0, 0, LMAGENTA, "+");
  else
  {
    PrText (0, 0, LRED, "X");
    More = FALSE;
  }
  if (More)
    PrText (NextLine, 73, LMAGENTA, "Passed");
  else
    PrText (NextLine, 73, LRED, "FAILED");
  More = TRUE;
  NextLine += 5;
  PrText (NextLine, 40, DMAGENTA, "BLOCKMAP consistency check:");
  BlockMinX = BlockMapHeader.OriginX;
  BlockMaxX = BlockMapHeader.OriginX + 0x007F;
  BlockMinY = BlockMapHeader.OriginY;
  BlockMaxY = BlockMapHeader.OriginY + 0x007F;
  for (CntY = 0 ; CntY < BlockMapHeader.BlockCntY && More ; CntY ++)
  {
    for (CntX = 0 ; CntX < BlockMapHeader.BlockCntX && More ; CntX ++)
    {
      BlockNumber = CntY * BlockMapHeader.BlockCntX + CntX;
      BlockOffset = (*(BlockInfo + BlockNumber) - (sizeof (struct BlockMapHeader_s) / sizeof (dbyte)));
      if (*(BlockInfo + BlockOffset) != 0x0000)
      {
	PrText (NextLine + 1, 42, LRED, "Invalid startmarker in block %d", BlockNumber + 1);
	More = FALSE;
      }
      while (*(BlockInfo + (++ BlockOffset)) != 0xFFFF && More)
      {
	LineDefNumber = *(BlockInfo + BlockOffset);
	if (BlockOffset > BlockMapInfoSize)
	{
	  PrText (NextLine + 1, 42, LRED, "Missing endmarker in block %d", BlockNumber + 1);
	  More = FALSE;
	}
	else
	  if (LineDefNumber > NumberOfLineDefs)
	  {
	    PrText (NextLine + 1, 42, LRED, "Unknown LineDef %d in block %d", LineDefNumber, BlockNumber + 1);
	    More = FALSE;
	  }
	  else
	  {
	    TestMapX = (LineInfo + LineDefNumber)->StartMapX;
	    TestMapY = (LineInfo + LineDefNumber)->StartMapY;
	    TestMapX2 = (LineInfo + LineDefNumber)->EndMapX;
	    TestMapY2 = (LineInfo + LineDefNumber)->EndMapY;
	    if (TestMapX < BlockMinX || TestMapX > BlockMaxX)                                   /* Start X is not in this block ? */
	    {
	      if (TestMapX2 < BlockMinX || TestMapX2 > BlockMaxX)                               /* End X also not in this block ? */
		More = FALSE;                                                               /* Signal: LineDef crosses this block */
	      else
		if (TestMapY2 < BlockMinY || TestMapY2 > BlockMaxY)                                   /* End Y not in the block ? */
		  More = FALSE;                                                             /* Signal: LineDef crosses this block */
	    }
	    else
	      if (TestMapY < BlockMinY || TestMapY > BlockMaxY)                                     /* Start Y not in the block ? */
		More = FALSE;                                                               /* Signal: LineDef crosses this block */
	    if (!More)                                                                                      /* Crossing LineDef ? */
	    {                                                                                         /* Test if that is possible */
	      More = TRUE;
	      if (TestMapX > TestMapX2)                                                         /* Line goes from right to left ? */
	      {                                                                                             /* Then flip the line */
		N = TestMapX;
		TestMapX = TestMapX2;
		TestMapX2 = N;
		N = TestMapY;
		TestMapY = TestMapY2;
		TestMapY2 = N;
	      }
	      if (TestMapX < BlockMinX)                                                                      /* Start X lies left */
	      {
		if (TestMapX2 < BlockMinX)                                                                     /* End X also left */
		  More = FALSE;                                                               /* Then the LineDef does NOT cross! */
	      }
	      else
		if (TestMapX > BlockMinX)                                                                   /* Start X lies right */
		  if (TestMapX > BlockMaxX)                                                               /* Even after the block */
		    More = FALSE;                                                             /* Then the LineDef does NOT cross! */
	      if (TestMapY > TestMapY2)                                                            /* Line goes from up to down ? */
	      {                                                                                             /* Then flip the line */
		N = TestMapX;
		TestMapX = TestMapX2;
		TestMapX2 = N;
		N = TestMapY;
		TestMapY = TestMapY2;
		TestMapY2 = N;
	      }
	      if (TestMapY < BlockMinY)                                                                     /* Start Y lies below */
	      {
		if (TestMapY2 < BlockMinY)                                                                    /* End Y also below */
		  More = FALSE;                                                               /* Then the LineDef does NOT cross! */
	      }
	      else
		if (TestMapY > BlockMinY)                                                                   /* Start Y lies above */
		  if (TestMapY > BlockMaxY)                                                               /* Even after the block */
		    More = FALSE;                                                             /* Then the LineDef does NOT cross! */
	      if (!More)
		PrText (NextLine + 1, 42, LRED, "Invalid LineDef %d in block %d", LineDefNumber, BlockNumber + 1);
	    }
	  }
      }
      BlockMinX += 0x0080;
      BlockMaxX += 0x0080;
    }
    BlockMinY += 0x0080;
    BlockMaxY += 0x0080;
    BlockMinX = BlockMapHeader.OriginX;
    BlockMaxX = BlockMapHeader.OriginX + 0x007F;
  }
  if (More)
  {
    PrText (NextLine, 73, LMAGENTA, "Passed");
    NextLine += 2;
  }
  else
  {
    PrText (NextLine, 73, LRED, "FAILED");
    NextLine += 3;
  }
  free (BlockInfo);
  free (LineInfo);
  PrText (NextLine, 40, DMAGENTA, "REJECT   consistency check:");
  if ((long)ceil (pow ((double)(Remember[MemNum].SectorLoc.Size / sizeof (struct Sector_s)), 2) / 8) == Remember[MemNum].RejectDataLoc.Size)
    PrText (NextLine, 73, LMAGENTA, "Passed");
  else
    PrText (NextLine, 73, LRED, "FAILED");
  NextLine += 2;
  PrText (NextLine, 40, DMAGENTA, "THINGS   consistency check:");
  PrText (1, 68, DWHITE, "Loading...");
  if (fseek (Fp, Remember[MemNum].ThingsLoc.Start, SEEK_SET))
    Bye ("ERROR - File location error\n");
  More = TRUE;
  Entries = 0;
  while (Entries < Remember[MemNum].ThingsLoc.Size && More)                                                 /* Handle all entries */
  {
    if (fread (&Thing, 1, sizeof (struct Thing_s), Fp) != sizeof (struct Thing_s))
      Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
    SwapDbyte (&Thing.Xpos);
    SwapDbyte (&Thing.Ypos);
    SwapDbyte (&Thing.Angle);
    SwapDbyte (&Thing.Type);
    SwapDbyte (&Thing.When);
#endif
    if (Thing.Xpos < BlockMapHeader.OriginX || Thing.Xpos > (BlockMapHeader.OriginX + 0x0080 * BlockMapHeader.BlockCntX - 1) ||
	Thing.Ypos < BlockMapHeader.OriginY || Thing.Ypos > (BlockMapHeader.OriginY + 0x0080 * BlockMapHeader.BlockCntY - 1))
    {
      PrText (NextLine + 1, 40, LRED, "Thing located outside the map");
      More = FALSE;
    }
    else
      if (Thing.Angle >= 360)
      {
	PrText (NextLine + 1, 40, LRED, "Unknown angle %d encountered", Thing.Angle);
	More = FALSE;
      }
      else
        if ((Thing.Type > 0x003F && Thing.Type < 0x07D1) ||
             Thing.Type == 0x07D9  ||
            (Thing.Type > 0x07DF && Thing.Type < 0x07E2) ||
            (Thing.Type > 0x07E3 && Thing.Type < 0x07E6) ||
             Thing.Type == 0x07EB  ||
            (Thing.Type > 0x07EC && Thing.Type < 0x07F3) ||
            (Thing.Type > 0x07F3 && Thing.Type < 0x07FD) ||
            (Thing.Type > 0x0801 && Thing.Type < 0x0BB9) ||
             Thing.Type > 0x0BBE)
	{
	  PrText (NextLine + 1, 40, LRED, "Unknown thing %d encountered", Thing.Type);
	  More = FALSE;
	}
    Entries += sizeof (struct Thing_s);
  }
  PrText (1, 68, DWHITE, "          ");
  if (More)
  {
    PrText (NextLine, 73, LMAGENTA, "Passed");
    NextLine += 2;
  }
  else
  {
    PrText (NextLine, 73, LRED, "FAILED");
    NextLine += 3;
  }
}

dbyte main (int argc, char *argv[])

/**********************************************************************************************************************************/
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MAIN ROUTINE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
/* Import: Bye, SwapDbyte, SwapLong, OpenAllIntuition, ClearScreen, ListSprites, ListSounds,CheckLevel, ViewLevel, PrText.        */
/**********************************************************************************************************************************/

{
  FILE         *Fp;
  char          S[80];
  char          T[80];
  char          Last[5];
  char          ThingMem       = -1;
  char register M;
  char register N;
  char register O;
  char register MemNum;
  char register Memory;
  long register Entries;
  boolean       First;
  boolean       New;
  boolean       More;
  boolean       KeyOk;
  boolean       KeySprites     = FALSE;
  boolean       KeySounds      = FALSE;
  boolean       KeyMenus       = FALSE;
  boolean       KeyMusic       = FALSE;
  boolean       KeyNext        = FALSE;
  boolean       KeyPrevious    = FALSE;
  boolean       KeyInfo        = FALSE;
  boolean       KeyCheckLevel  = FALSE;
  boolean       KeyViewLevel   = FALSE;
  boolean       Listing        = FALSE;
  boolean       Checked        = FALSE;
  boolean       LevelInfoType  = TRUE;
  boolean       ReprintAll     = TRUE;
  boolean       ReprintLevels  = TRUE;    
  boolean       ReprintAny     = TRUE;    

#ifdef _AMIGA_
  OpenAllIntuition ();
#else
  _setvideomode (_VRES16COLOR);                                                                   /* Choose video mode 640x480x16 */
#endif
  if (argc != 2)
    Bye ("Usage: WADINFO WADfile\n");
  if (!(Fp = fopen (argv[1], "rb")))                                                                         /* Open the WAD file */
    Bye ("ERROR - File does not exist\n");
  PrText (1, 1, LWHITE, "Analyzing the WAD file...");
  PrText (1, 68, DWHITE, "Loading...");
  if (fread (&WadHeader, 1, sizeof (struct WadHeader_s), Fp) != sizeof (struct WadHeader_s))         /* Go to the WAD 'directory' */
    Bye ("ERROR - File read error\n");
  if (strncmp (WadHeader.Type, "PWAD", 4) && strncmp (WadHeader.Type, "IWAD", 4))
    Bye ("ERROR - Not a WAD file\n");
#ifdef _AMIGA_
  SwapLong (&WadHeader.DirStart);
  SwapLong (&WadHeader.DirSize);
#endif
  if (fseek (Fp, WadHeader.DirStart, SEEK_SET))
    Bye ("ERROR - File location error\n");
  for (M = 0 ; M < 27 ; M ++)
  {
    Remember[M].ThingsFilled = FALSE;
    Remember[M].StatsFilled = FALSE;
  }
  WadInfo.NewStuff = 0x00;
  WadInfo.NewLevels = 0x00000000;
  WadInfo.NewDemos = 0x0000;
  Entries = -1;
  while (++ Entries < WadHeader.DirSize)                                                 /* Handle all entries in the 'directory' */
  {
    if (fread (&Directory, 1, sizeof (struct Directory_s), Fp) != sizeof (struct Directory_s))                   /* Read an entry */
      Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
    SwapLong (&Directory.Start);
    SwapLong (&Directory.Size);
#endif
    for (M = 0 ; M < 8 ; M ++)
      S[M] = toupper (Directory.Name[M]);
    S[8] = '\0';
    More = TRUE;
    for (M = 0 ; M < MAXCOLORS && More ; M ++)
      if (!strncmp (S, Colors[M], strlen (Colors[M])))
      {
        More = FALSE;
        WadInfo.NewStuff |= NEWCOLORS;
      }
    if (More)
      if (!strncmp (S, "DEMO", 4))
        {
          More = FALSE;
          WadInfo.NewDemos |= ((dbyte)1 << (S[4]-'1'));
        }
    if (More)
      for (M = 0 ; M < MAXLEVELS && More ; M ++)
        if (!strncmp (S, Levels[M], strlen (Levels[M])))
        {
          More = FALSE;
          WadInfo.NewLevels |= ((long)1 << M);
          strncpy (Last, S, 4);
          ThingMem ++;
          Last[4] = '\0';
        }
    if (More)
      for (M = 0 ; M < MAXSPRITES && More ; M ++)
        if (!strncmp (S, Sprites[M].IdName, strlen (Sprites[M].IdName)))
        {
          More = FALSE;
          WadInfo.NewStuff |= NEWSPRITES;
          Sprites[M].FieldFilled = TRUE;
        }
    if (More)
      for (M = 0 ; M < MAXMUSIC && More ; M ++)
        if (!strncmp (S, Music[M].IdName, strlen (Music[M].IdName)))
        {
          More = FALSE;
          WadInfo.NewStuff |= NEWMUSIC;
          Music[M].FieldFilled = TRUE;
        }
    if (More)
      for (M = 0 ; M < MAXINSTRUMENTS && More ; M ++)
        if (!strncmp (S, Instruments[M], strlen (Instruments[M])))
        {
          More = FALSE;
          WadInfo.NewStuff |= NEWINSTRUMENTS;
        }
    if (More)
      for (M = 0 ; M < MAXSTATUSBAR && More ; M ++)
        if (!strncmp (S, StatusBar[M], strlen (StatusBar[M])))
        {
          More = FALSE;
          WadInfo.NewStuff |= NEWSTATUSBAR;
        }
    if (More)
      for (M = 0 ; M < MAXMENUS && More ; M ++)
        if (!strncmp (S, Menus[M].IdName, strlen (Menus[M].IdName)))
        {
          More = FALSE;
          WadInfo.NewStuff |= NEWMENUS;
          Menus[M].FieldFilled = TRUE;
        }
    if (More)
      for (M = 0 ; M < MAXSOUNDS && More ; M ++)
        if (!strncmp (S, Sounds[M].IdName, strlen (Sounds[M].IdName)))
        {
          More = FALSE;
          WadInfo.NewStuff |= NEWSOUNDS;
          Sounds[M].FieldFilled = TRUE;
        }
    if (More && !strncmp (S, "THINGS", 6))
    {
      Remember[ThingMem].ThingsLoc.Start = Directory.Start;                   /* The "THINGS" part of a level is dealt with later */
      Remember[ThingMem].ThingsLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].ThingsLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "VERTEXES", 8))
    {
      Remember[ThingMem].VertexLoc.Start = Directory.Start;
      Remember[ThingMem].VertexLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].VertexLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "LINEDEFS", 8))
    {
      Remember[ThingMem].LineDefLoc.Start = Directory.Start;
      Remember[ThingMem].LineDefLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].LineDefLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "SIDEDEFS", 8))
    {
      Remember[ThingMem].SideDefLoc.Start = Directory.Start;
      Remember[ThingMem].SideDefLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].SideDefLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "SEGS", 4))
    {
      Remember[ThingMem].SegLoc.Start = Directory.Start;
      Remember[ThingMem].SegLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].SegLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "SECTORS", 7))
    {
      Remember[ThingMem].SectorLoc.Start = Directory.Start;
      Remember[ThingMem].SectorLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].SectorLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "SSECTORS", 8))
    {
      Remember[ThingMem].SubSectorLoc.Start = Directory.Start;
      Remember[ThingMem].SubSectorLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].SubSectorLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "NODES", 5))
    {
      Remember[ThingMem].NodeLoc.Start = Directory.Start;
      Remember[ThingMem].NodeLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].NodeLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "REJECT", 6))
    {
      Remember[ThingMem].RejectDataLoc.Start = Directory.Start;
      Remember[ThingMem].RejectDataLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].RejectDataLoc.Name, Last);
      More = FALSE;
    }
    if (More && !strncmp (S, "BLOCKMAP", 8))
    {
      Remember[ThingMem].BlockMapLoc.Start = Directory.Start;
      Remember[ThingMem].BlockMapLoc.Size = Directory.Size;
      strcpy (Remember[ThingMem].BlockMapLoc.Name, Last);
      More = FALSE;
    }
    if (More
        && Directory.Start != 0                                                            /* If not a field seperator identifier */
        && S[0] != '\0'                                                                        /* And the identifier is not empty */
        && strcmp (S, "INFOPACK")                           /* (These were found in a lot of WAD files but NOT from Id Software!) */
        && strcmp (S, "PLATFORM"))
      WadInfo.NewStuff |= NEWGRAPHS;
  }
  PrText (1, 1, LWHITE, "                         ");
  PrText (1, 68, DWHITE, "          ");
  ThingMem ++;
  MemNum = 0;
  More = TRUE;
  while (More)
  {
    if (ReprintAny)
    {
      if (ReprintAll)
      {
#ifdef _AMIGA_
        N = strlen (argv[1]);
        while (-- N >= 0 && argv[1][N] != '/' && argv[1][N] != ':')
          ;
        if (N == 0)
          PrText ( 1, 1, LWHITE, "Filename       : %s", argv[1]);
        else
          PrText ( 1, 1, LWHITE, "Filename       : %s", argv[1] + N + 1);
#else
        N = strlen (argv[1]);
        while (-- N >= 0 && argv[1][N] != '\\' && argv[1][N] != ':')
          ;
        if (N == 0)
          PrText ( 1, 1, LWHITE, "Filename       : %s", strupr (argv[1]));
        else
          PrText ( 1, 1, LWHITE, "Filename       : %s", strupr (argv[1] + N + 1));
#endif
        for (N = 0 ; N < 4 ; N ++)                                                                /* Convert the type to a string */
          S[N] = WadHeader.Type[N];
        S[N] = '\0';
        PrText ( 2, 1, LWHITE, "Wadfile type   : %s", S);                                /* Print the WAD 'directory' information */
        PrText ( 3, 1, LWHITE, "Directory start: %08lX", WadHeader.DirStart);
        PrText ( 4, 1, LWHITE, "Directory size : %08lX", WadHeader.DirSize);
        PrText ( 7, 1, LBLUE,  "New Colors     : %s", WadInfo.NewStuff & NEWCOLORS ? "Yes" : "-");
        PrText ( 8, 1, LBLUE,  "New Demos      :");
        if (WadInfo.NewDemos == 0x0000)
          PrText (0, 0, LBLUE, " -");
        for (N = 0 ; N < 10 ; N ++)
          if (WadInfo.NewDemos & ((dbyte)1 << N))
            PrText (0, 0, LBLUE, " %d", N + 1);
        PrText ( 9, 1, LBLUE,  "New Sounds     : %s", WadInfo.NewStuff & NEWSOUNDS ? "Yes" : "-");
        PrText (10, 1, LBLUE,  "New Instruments: %s", WadInfo.NewStuff & NEWINSTRUMENTS ? "Yes" : "-");
        PrText (11, 1, LBLUE,  "New Music      : %s", WadInfo.NewStuff & NEWMUSIC ? "Yes" : "-");
        PrText (12, 1, LBLUE,  "New Sprites    : %s", WadInfo.NewStuff & NEWSPRITES ? "Yes" : "-");
        PrText (13, 1, LBLUE,  "New Status bar : %s", WadInfo.NewStuff & NEWSTATUSBAR ? "Yes" : "-");
        PrText (14, 1, LBLUE,  "New Menu items : %s", WadInfo.NewStuff & NEWMENUS ? "Yes" : "-");
        PrText (15, 1, LBLUE,  "New Graphics   : %s", WadInfo.NewStuff & NEWGRAPHS ? "Yes" : "-");
        PrText (16, 1, LBLUE,  "New Levels     :");
        if (WadInfo.NewLevels != 0x00000000)                                         /* Are their any patch levels in this file ? */
        {
          S[0] = '\0';
          for (N = 0 ; N < NUMEPISODE ; N ++)
          {
            Memory = -1;
            First = TRUE;
            if ((WadInfo.NewLevels & ((long)0x1ff << (N * NUMLEVEL))) == ((long)0x1ff << (N * NUMLEVEL)))
            {                                                                               /* All 9 level-bits of an episode set */
              sprintf (T, " E%d-", N + 1);
              strcat (S, T);
            }
            else                                                                                    /* Possibly a partial episode */
              for (O = 0 ; O < NUMLEVEL ; O ++)                                          /* Handle all level-bits in this episode */
                if (WadInfo.NewLevels & ((long)1 << (N * NUMLEVEL + O)))
                {
                  if (Memory == -1)
                    if (First)
                    {
                      sprintf (T, " E%dM%d", N + 1, O + 1);
                      strcat (S, T);
                      First = FALSE;
                      Memory = 1;
                      New = FALSE;
                    }
                    else
                    {
                      sprintf (T, ",%d", O + 1);
                      strcat (S, T);
                      Memory = O + 1;
                      New = FALSE;
                    }
                  else
                  {
                    Memory ++;
                    New = TRUE;
                  }
                }
                else
                {
                  if (Memory > 0 && New)
                  {
                    sprintf (T, "-%d", Memory);
                    strcat (S, T);
                  }
                  Memory = -1;
                }
            if (Memory > 0 && New)
            {
              sprintf (T, "-%d", Memory);
              strcat (S, T);
            }
          }
          PrText (0, 0, LBLUE, S);
        }                                                                                       /* No new levels in this WAD file */
        else
          PrText (0, 0, LBLUE, " -");
        ReprintLevels = TRUE;
      }
      if (ReprintLevels && ThingMem > 0)                                                                          /* New levels ? */
      {
        PrText (1, 40, LYELLOW, "INFORMATION ON LEVEL %s:", Remember[MemNum].ThingsLoc.Name);
        if (LevelInfoType)
        {
          if (!Remember[MemNum].ThingsFilled)
          {
            PrText (1, 68, DWHITE, "Loading...");
            for (N = 0 ; N < 4 ; N ++)
            {
              Remember[MemNum].PlayerStarts[N] = 0;
              for (O = 0 ; O < 16 ; O ++)
                Remember[MemNum].ThingType[O][N] = 0;
            }
            Remember[MemNum].PlayerStarts[4] = 0;
            if (fseek (Fp, Remember[MemNum].ThingsLoc.Start, SEEK_SET))                            /* Go to the start of the data */
              Bye ("ERROR - File location error\n");
            Entries = 0;
            while (Entries < Remember[MemNum].ThingsLoc.Size)                                               /* Handle all entries */
            {
              if (fread (&Thing, 1, sizeof (struct Thing_s), Fp) != sizeof (struct Thing_s))                     /* Read an entry */
                Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
              SwapDbyte (&Thing.Xpos);
              SwapDbyte (&Thing.Ypos);
              SwapDbyte (&Thing.Angle);
              SwapDbyte (&Thing.Type);
              SwapDbyte (&Thing.When);
#endif
              switch (Thing.Type)                                                          /* Find out if the type is interesting */
              {
                case THING_PLAYER1    : Thing.Type = 0xFFFF; (Remember[MemNum].PlayerStarts[0]) ++; break; /* Handle playerstarts */
                case THING_PLAYER2    : Thing.Type = 0xFFFF; (Remember[MemNum].PlayerStarts[1]) ++; break;
                case THING_PLAYER3    : Thing.Type = 0xFFFF; (Remember[MemNum].PlayerStarts[2]) ++; break;
                case THING_PLAYER4    : Thing.Type = 0xFFFF; (Remember[MemNum].PlayerStarts[3]) ++; break;
                case THING_DEATHMATCH : Thing.Type = 0xFFFF; (Remember[MemNum].PlayerStarts[4]) ++; break;
                case THING_CHAINSAW   : Thing.Type = TYPE_CHAINSAW; break;                         /* Convert type to array index */
                case THING_SHOTGUN    : Thing.Type = TYPE_SHOTGUN; break;
                case THING_CHAINGUN   : Thing.Type = TYPE_CHAINGUN; break;
                case THING_LAUNCHER   : Thing.Type = TYPE_LAUNCHER; break;
                case THING_PLASMAGUN  : Thing.Type = TYPE_PLASMAGUN; break;
                case THING_BFG9000    : Thing.Type = TYPE_BFG9000; break;
                case THING_TROOPER    : Thing.Type = TYPE_TROOPER; break;
                case THING_SARGEANT   : Thing.Type = TYPE_SARGEANT; break;
                case THING_IMP        : Thing.Type = TYPE_IMP; break;
                case THING_DEMON      : Thing.Type = TYPE_DEMON; break;
                case THING_SPECTRE    : Thing.Type = TYPE_SPECTRE; break;
                case THING_CACODEMON  : Thing.Type = TYPE_CACODEMON; break;
                case THING_LOSTSOUL   : Thing.Type = TYPE_LOSTSOUL; break;
                case THING_BARON      : Thing.Type = TYPE_BARON; break;
                case THING_CYBERDEMON : Thing.Type = TYPE_CYBERDEMON; break;
                case THING_SPIDERBOSS : Thing.Type = TYPE_SPIDERBOSS; break;
                default               : Thing.Type = 0xFFFF;
              }
              if (Thing.Type != 0xFFFF)                                                                       /* Unhandled type ? */
              {                                                   /* Update array entry, depending on the appearance (difficulty) */
                (Remember[MemNum].ThingType[Thing.Type][3]) ++;
                if ((Thing.When & WHEN_MULTI) != WHEN_MULTI)         /* If it appears in multi, then the other bits are undefined */
                {
                  if ((Thing.When & WHEN_D12) == WHEN_D12)
                    (Remember[MemNum].ThingType[Thing.Type][0]) ++;
                  if ((Thing.When & WHEN_D3) == WHEN_D3)
                    (Remember[MemNum].ThingType[Thing.Type][1]) ++;
                  if ((Thing.When & WHEN_D45) == WHEN_D45)
                    (Remember[MemNum].ThingType[Thing.Type][2]) ++;
                }
              }
              Entries += sizeof (struct Thing_s);
            }
            Remember[MemNum].ThingsFilled = TRUE;
            PrText (1, 68, DWHITE, "          ");
          }
          if (Remember[MemNum].PlayerStarts[0])                                            /* Print number of found starting pads */
            if (Remember[MemNum].PlayerStarts[1])
              if (Remember[MemNum].PlayerStarts[2])
                if (Remember[MemNum].PlayerStarts[3])
                  PrText (3, 40, LGREEN, "Number of player starts    : 4         ");
                else
                  PrText (3, 40, LGREEN, "Number of player starts    : 3         ");
              else
                PrText (3, 40, LGREEN, "Number of player starts    : 2         ");
            else
              PrText (3, 40, LGREEN, "Number of player starts    : 1         ");
          else
            PrText (3, 40, LGREEN, "Number of player starts    : none     ");
          if (Remember[MemNum].PlayerStarts[4] == 0)
            PrText (4, 40, LGREEN, "Number of deathmatch starts: none     ");
          else
            if (Remember[MemNum].PlayerStarts[4] == 1)
              PrText (4, 40, LGREEN, "Number of deathmatch starts: 1         ");
            else
              PrText (4, 40, LGREEN, "Number of deathmatch starts: %d        ", Remember[MemNum].PlayerStarts[4]);
          PrText ( 5, 40, DBLACK, "                                       ");
          PrText ( 6, 40, DBLACK, "                                       ");
          PrText ( 7, 40, DMAGENTA, "Weapons in this level: D12  D3 D45 MUL ");           /* Print the other recorded information */
          PrText ( 8, 40, DBLACK, "                                       ");
          PrText ( 9, 40, LMAGENTA, "(1) Chainsaw           %3d %3d %3d %3d ", Remember[MemNum].ThingType[0][0],
                                                                               Remember[MemNum].ThingType[0][1],
                                                                               Remember[MemNum].ThingType[0][2],
                                                                               Remember[MemNum].ThingType[0][3]);
          PrText (10, 40, LMAGENTA, "(3) Shotgun            %3d %3d %3d %3d ", Remember[MemNum].ThingType[1][0],
                                                                               Remember[MemNum].ThingType[1][1],
                                                                               Remember[MemNum].ThingType[1][2],
                                                                               Remember[MemNum].ThingType[1][3]);
          PrText (11, 40, LMAGENTA, "(4) Chaingun           %3d %3d %3d %3d ", Remember[MemNum].ThingType[2][0],
                                                                               Remember[MemNum].ThingType[2][1],
                                                                               Remember[MemNum].ThingType[2][2],
                                                                               Remember[MemNum].ThingType[2][3]);
          PrText (12, 40, LMAGENTA, "(5) Rocket launcher    %3d %3d %3d %3d ", Remember[MemNum].ThingType[3][0],
                                                                               Remember[MemNum].ThingType[3][1],
                                                                               Remember[MemNum].ThingType[3][2],
                                                                               Remember[MemNum].ThingType[3][3]);
          PrText (13, 40, LMAGENTA, "(6) Plasmagun          %3d %3d %3d %3d ", Remember[MemNum].ThingType[4][0],
                                                                               Remember[MemNum].ThingType[4][1],
                                                                               Remember[MemNum].ThingType[4][2],
                                                                               Remember[MemNum].ThingType[4][3]);
          PrText (14, 40, LMAGENTA, "(7) BFG9000            %3d %3d %3d %3d ", Remember[MemNum].ThingType[5][0],
                                                                               Remember[MemNum].ThingType[5][1],
                                                                               Remember[MemNum].ThingType[5][2],
                                                                               Remember[MemNum].ThingType[5][3]);
          PrText (15, 40, DBLACK, "                                       ");
          PrText (16, 40, DMAGENTA, "Enemies in this level: D12  D3 D45 MUL ");
          PrText (17, 40, DBLACK, "                                       ");
          PrText (18, 40, LMAGENTA, "Trooper                %3d %3d %3d %3d ", Remember[MemNum].ThingType[6][0],
                                                                               Remember[MemNum].ThingType[6][1],
                                                                               Remember[MemNum].ThingType[6][2],
                                                                               Remember[MemNum].ThingType[6][3]);
          PrText (19, 40, LMAGENTA, "Sargeant               %3d %3d %3d %3d ", Remember[MemNum].ThingType[7][0],
                                                                               Remember[MemNum].ThingType[7][1],
                                                                               Remember[MemNum].ThingType[7][2],
                                                                               Remember[MemNum].ThingType[7][3]);
          PrText (20, 40, LMAGENTA, "Imp                    %3d %3d %3d %3d ", Remember[MemNum].ThingType[8][0],
                                                                               Remember[MemNum].ThingType[8][1],
                                                                               Remember[MemNum].ThingType[8][2],
                                                                               Remember[MemNum].ThingType[8][3]);
          PrText (21, 40, LMAGENTA, "Demon                  %3d %3d %3d %3d ", Remember[MemNum].ThingType[9][0],
                                                                               Remember[MemNum].ThingType[9][1],
                                                                               Remember[MemNum].ThingType[9][2],
                                                                               Remember[MemNum].ThingType[9][3]);
          PrText (22, 40, LMAGENTA, "Spectre                %3d %3d %3d %3d ", Remember[MemNum].ThingType[10][0],
                                                                               Remember[MemNum].ThingType[10][1],
                                                                               Remember[MemNum].ThingType[10][2],
                                                                               Remember[MemNum].ThingType[10][3]);
          PrText (23, 40, LMAGENTA, "Caco Demon             %3d %3d %3d %3d ", Remember[MemNum].ThingType[11][0],
                                                                               Remember[MemNum].ThingType[11][1],
                                                                               Remember[MemNum].ThingType[11][2],
                                                                               Remember[MemNum].ThingType[11][3]);
          PrText (24, 40, LMAGENTA, "Lost soul              %3d %3d %3d %3d ", Remember[MemNum].ThingType[12][0],
                                                                               Remember[MemNum].ThingType[12][1],
                                                                               Remember[MemNum].ThingType[12][2],
                                                                               Remember[MemNum].ThingType[12][3]);
          PrText (25, 40, LMAGENTA, "Baron of Hell          %3d %3d %3d %3d ", Remember[MemNum].ThingType[13][0],
                                                                               Remember[MemNum].ThingType[13][1],
                                                                               Remember[MemNum].ThingType[13][2],
                                                                               Remember[MemNum].ThingType[13][3]);
          PrText (26, 40, LMAGENTA, "Cyber Demon            %3d %3d %3d %3d ", Remember[MemNum].ThingType[14][0],
                                                                               Remember[MemNum].ThingType[14][1],
                                                                               Remember[MemNum].ThingType[14][2],
                                                                               Remember[MemNum].ThingType[14][3]);
          PrText (27, 40, LMAGENTA, "Spider Demon           %3d %3d %3d %3d ", Remember[MemNum].ThingType[15][0],
                                                                               Remember[MemNum].ThingType[15][1],
                                                                               Remember[MemNum].ThingType[15][2],
                                                                               Remember[MemNum].ThingType[15][3]);
          PrText (28, 40, DBLACK, "                                       ");
        }
        else
        {
          if (!Remember[MemNum].StatsFilled)
          {
            PrText (1, 68, DWHITE, "Loading...");
            if (fseek (Fp, Remember[MemNum].VertexLoc.Start, SEEK_SET))
              Bye ("ERROR - File location error\n");
            if (fread (&Vertex, 1, sizeof (struct Vertex_s), Fp) != sizeof (struct Vertex_s))                    /* Read an entry */
              Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
            SwapDbyte (&Vertex.MapX);
            SwapDbyte (&Vertex.MapY);
#endif
            Remember[MemNum].MinMapX = Remember[MemNum].MaxMapX = Vertex.MapX;
            Remember[MemNum].MinMapY = Remember[MemNum].MaxMapY = Vertex.MapY;
            Entries = sizeof (struct Vertex_s);
            while (Entries < Remember[MemNum].VertexLoc.Size)                                               /* Handle all entries */
            {
              if (fread (&Vertex, 1, sizeof (struct Vertex_s), Fp) != sizeof (struct Vertex_s))                  /* Read an entry */
                Bye ("ERROR - File read error\n");
#ifdef _AMIGA_
              SwapDbyte (&Vertex.MapX);
              SwapDbyte (&Vertex.MapY);
#endif
              if (Vertex.MapX < Remember[MemNum].MinMapX)
                Remember[MemNum].MinMapX = Vertex.MapX;
              if (Vertex.MapX > Remember[MemNum].MaxMapX)
                Remember[MemNum].MaxMapX = Vertex.MapX;
              if (Vertex.MapY < Remember[MemNum].MinMapY)
                Remember[MemNum].MinMapY = Vertex.MapY;
              if (Vertex.MapY > Remember[MemNum].MaxMapY)
                Remember[MemNum].MaxMapY = Vertex.MapY;
              Entries += sizeof (struct Vertex_s);
            }
            Remember[MemNum].MapSizeX = Remember[MemNum].MaxMapX - Remember[MemNum].MinMapX + 1;             /* Include BOTH ends */
            Remember[MemNum].MapSizeY = Remember[MemNum].MaxMapY - Remember[MemNum].MinMapY + 1;
            Remember[MemNum].StatsFilled = TRUE;
            PrText (1, 68, DWHITE, "          ");
          }
          PrText ( 3, 40, DGREEN, "THINGS   start : %08lX              ", Remember[MemNum].ThingsLoc.Start);
          PrText ( 4, 40, DGREEN, "         size  : %08lX (%4lu)       ", Remember[MemNum].ThingsLoc.Size,
                                                                          Remember[MemNum].ThingsLoc.Size / sizeof (struct Thing_s));
          PrText ( 5, 40, DGREEN, "VERTEXES start : %08lX              ", Remember[MemNum].VertexLoc.Start);
          PrText ( 6, 40, DGREEN, "         size  : %08lX (%4lu)       ", Remember[MemNum].VertexLoc.Size,
                                                                          Remember[MemNum].VertexLoc.Size / sizeof (struct Vertex_s));
          PrText ( 7, 40, DGREEN, "LINEDEFS start : %08lX              ", Remember[MemNum].LineDefLoc.Start);
          PrText ( 8, 40, DGREEN, "         size  : %08lX (%4lu)       ", Remember[MemNum].LineDefLoc.Size,
                                                                          Remember[MemNum].LineDefLoc.Size / sizeof (struct LineDef_s));
          PrText ( 9, 40, DGREEN, "SIDEDEFS start : %08lX              ", Remember[MemNum].SideDefLoc.Start);
          PrText (10, 40, DGREEN, "         size  : %08lX (%4lu)       ", Remember[MemNum].SideDefLoc.Size,
                                                                          Remember[MemNum].SideDefLoc.Size / sizeof (struct SideDef_s));
          PrText (11, 40, DGREEN, "SEGS     start : %08lX              ", Remember[MemNum].SegLoc.Start);
          PrText (12, 40, DGREEN, "         size  : %08lX (%4lu)       ", Remember[MemNum].SegLoc.Size,
                                                                          Remember[MemNum].SegLoc.Size / sizeof (struct Seg_s));
          PrText (13, 40, DGREEN, "SECTORS  start : %08lX              ", Remember[MemNum].SectorLoc.Start);
          PrText (14, 40, DGREEN, "         size  : %08lX (%4lu)       ", Remember[MemNum].SectorLoc.Size,
                                                                          Remember[MemNum].SectorLoc.Size / sizeof (struct Sector_s));
          PrText (15, 40, DGREEN, "SSECTORS start : %08lX              ", Remember[MemNum].SubSectorLoc.Start);
          PrText (16, 40, DGREEN, "         size  : %08lX (%4lu)       ", Remember[MemNum].SubSectorLoc.Size,
                                                                          Remember[MemNum].SubSectorLoc.Size / sizeof (struct SubSector_s));
          PrText (17, 40, DGREEN, "NODES    start : %08lX              ", Remember[MemNum].NodeLoc.Start);
          PrText (18, 40, DGREEN, "         size  : %08lX (%4lu)       ", Remember[MemNum].NodeLoc.Size,
                                                                          Remember[MemNum].NodeLoc.Size / sizeof (struct Node_s));
          PrText (19, 40, DGREEN, "REJECT   start : %08lX              ", Remember[MemNum].RejectDataLoc.Start);
          PrText (20, 40, DGREEN, "         size  : %08lX              ", Remember[MemNum].RejectDataLoc.Size);
          PrText (21, 40, DGREEN, "BLOCKMAP start : %08lX              ", Remember[MemNum].BlockMapLoc.Start);
          PrText (22, 40, DGREEN, "         size  : %08lX              ", Remember[MemNum].BlockMapLoc.Size);
          PrText (23, 40, DBLACK, "                                       ");
          PrText (24, 40, LMAGENTA, "Top-left map       : (%5d, %5d)    ", Remember[MemNum].MinMapX, Remember[MemNum].MinMapY);
          PrText (25, 40, LMAGENTA, "Bottom-right map   : (%5d, %5d)    ", Remember[MemNum].MaxMapX, Remember[MemNum].MaxMapY);
          PrText (26, 40, LMAGENTA, "Center of map      : (%5d, %5d)    ",
                          Remember[MemNum].MaxMapX - (Remember[MemNum].MapSizeX / 2),
                          Remember[MemNum].MaxMapY - (Remember[MemNum].MapSizeY / 2));
          PrText (27, 40, DBLACK, "                                       ");
          PrText (28, 40, LMAGENTA, "Size of map        : %5d x %5d     ", Remember[MemNum].MapSizeX, Remember[MemNum].MapSizeY);
        }
      }
      PrText (20, 1, DYELLOW, "Press :");
      PrText (21, 1, DYELLOW, "  [Q] to quit                      ");
      if (ThingMem > 0)
      {
        PrText (22, 1, DYELLOW, "  [V] to view this level's map     ");
        KeyViewLevel = TRUE;
      }
      else
      {
        PrText (22, 1, DYELLOW, "                                   ");
        KeyViewLevel = FALSE;
      }
      if (ThingMem > 0)
      {
        PrText (23, 1, DYELLOW, "  [I] to toggle level info type    ");
        KeyInfo = TRUE;
      }
      else
      {
        PrText (23, 1, DYELLOW, "                                   ");
        KeyInfo = FALSE;
      }
      if (ThingMem > 0)
      {
        PrText (24, 1, DYELLOW, "  [C] to check this level          ");
        KeyCheckLevel = TRUE;
      }
      else
      {
        PrText (24, 1, DYELLOW, "                                   ");
        KeyCheckLevel = FALSE;
      }
      if ((ThingMem > 0) && (MemNum < ThingMem - 1))
      {
        PrText (25, 1, DYELLOW, "  [N] for next level               ");
        KeyNext = TRUE;
      }
      else
      {
        PrText (25, 1, DYELLOW, "                                   ");
        KeyNext = FALSE;
      }
      if ((ThingMem > 0) && (MemNum > 0))
      {
        PrText (26, 1, DYELLOW, "  [P] for previous level           ");
        KeyPrevious = TRUE;
      }
      else
      {
        PrText (26, 1, DYELLOW, "                                   ");
        KeyPrevious = FALSE;
      }
      if ((WadInfo.NewStuff & NEWSPRITES) == NEWSPRITES)
      {
        PrText (27, 1, DYELLOW, "  [R] to list the sprites          ");
        KeySprites = TRUE;
      }
      else
        KeySprites = FALSE;
      if ((WadInfo.NewStuff & NEWSOUNDS) == NEWSOUNDS)
      {
        PrText (28, 1, DYELLOW, "  [S] to list the sounds           ");
        KeySounds = TRUE;
      }
      else
        KeySounds = FALSE;
      if ((WadInfo.NewStuff & NEWMUSIC) == NEWMUSIC)
      {
        PrText (29, 1, DYELLOW, "  [M] to list the music            ");
        KeyMusic = TRUE;
      }
      else
        KeyMusic = FALSE;
      if ((WadInfo.NewStuff & NEWMENUS) == NEWMENUS)
      {
        PrText (30, 1, DYELLOW, "  [U] to list the menu items       ");
        KeyMenus = TRUE;
      }
      else
        KeyMenus = FALSE;
      KeyOk = FALSE;
      ReprintAll = FALSE;
      ReprintLevels = FALSE;
      ReprintAny = FALSE;
    }
    while (!KeyOk)
    {
      KeyOk = TRUE;
#ifdef _AMIGA_
      while (KeyOk)
      {
        if (!(IntuiMessage = (struct IntuiMessage *)GetMsg (Window->UserPort)))              /* Wait for a message from intuition */
        {
          Wait (1L << Window->UserPort->mp_SigBit);
          continue;
        }
        MessageClass = IntuiMessage->Class;                                                /* Determine the source of the message */
        Code = IntuiMessage->Code;                                                                /* Read the data of the message */
        ReplyMsg (IntuiMessage);                                                       /* Confirm receipt to the operating system */
        if (MessageClass == VANILLAKEY)
          KeyOK = FALSE;
      }
      KeyOk = TRUE;
      if (Checked)
      {
        Checked = FALSE;
        ReprintLevels = TRUE;
      }
      else
        if (Listing)
        {
          Listing = FALSE;
          if (InLaceMode)
          {
            CloseWindow (Window);
            CloseScreen (Screen);
            if (!(Screen = (struct Screen *)OpenScreen (&FirstScreen)))
              Bye ("ERROR - Cannot open screen\n");
            FirstWindow.Screen = Screen;
            if (!(Window = (struct Window *)OpenWindow (&FirstWindow)))
              Bye ("ERROR - Cannot open window\n");
            SetPalette ()
            InLaceMode = FALSE;
          }
          else
            ClearScreen ();
          ReprintAll = TRUE;
        }
        else
          switch (Code)
#else
      Key = getch ();                                                                                           /* Wait for a key */
      if (Key == 0x0000 || Key == 0x00E0)                          /* Non-ASCII keys (cursor, funtion, etc) give 'extended' first */
        Key = getch ();
      if (Checked)
      {
        Checked = FALSE;
        ReprintLevels = TRUE;
      }
      else
      if (Listing)
      {
        Listing = FALSE;
        ClearScreen ();
        ReprintAll = TRUE;
      }
      else
        switch (tolower ((char)(Key & 0x00FF)))                                                       /* Keep only the ASCII part */
#endif
        {
          case 'q' : More = FALSE;
                     break;
          case 'c' : if (KeyCheckLevel)
                     {
                       CheckLevel (Fp, MemNum);
                       KeyOk = FALSE;
                       Checked = TRUE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          case 'i' : if (KeyInfo)
                     {
                       LevelInfoType = !LevelInfoType;
                       ReprintLevels = TRUE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          case 'n' : if (KeyNext)
                     {
                       MemNum ++;
                       ReprintLevels = TRUE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          case 'p' : if (KeyPrevious)
                     {
                       MemNum --;
                       ReprintLevels = TRUE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          case 'r' : if (KeySprites)
                     {
                       ListSprites ();
                       Listing = TRUE;
                       KeyOk = FALSE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          case 's' : if (KeySounds)
                     {
                       ListSounds ();
                       Listing = TRUE;
                       KeyOk = FALSE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          case 'm' : if (KeyMusic)
                     {
                       ListMusic ();
                       Listing = TRUE;
                       KeyOk = FALSE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          case 'u' : if (KeyMenus)
                     {
                       ListMenus ();
                       Listing = TRUE;
                       KeyOk = FALSE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          case 'v' : if (KeyViewLevel)
                     {
                       ViewLevel (Fp, MemNum);
                       Listing = TRUE;
                       KeyOk = FALSE;
                     }
                     else
                       KeyOk = FALSE;
                     break;
          default  : KeyOk = FALSE;
        }
      }
      ReprintAny = (ReprintAll || ReprintLevels);
  }
  fclose (Fp);
  Bye ("");                                                                                                           /* Shutdown */
}
