
/***********/
/** bin.c **/
/***********/

/* (c) 1996-97 by Sidney Cadot */

#include <stdio.h>
#include <stdlib.h>

int
main (int argc, char *argv[])

{
  FILE *f;
  unsigned char MEM[0x10000L];  /* old Borland C will barf on this one! */
  unsigned short START, END;
  unsigned long OFFSET;
  int LO, HI, HAS_FFFF, SEG_COUNT;

  if (argc != 2)                /* usage */
    {
      puts ("\nUsage: BIN <file>");
      return EXIT_FAILURE;
    }

  printf ("\n----------------------------------------------------------------"
          " %s\n", argv[1]);

  f = fopen (argv[1], "rb");    /* open file in binary mode */

  if (f == NULL)                /* no go - an error occurred */
    {
      printf ("ERROR: %s (while opening file).\n", argv[1]);
      return EXIT_FAILURE;
    }

  LO = fgetc (f);               /* these should both be $FF $FF */
  HI = fgetc (f);

  if ((LO == EOF) || (HI == EOF))       /* ouch! no go! */
    {
      printf ("ERROR: %s (while reading first 2 bytes).\n", argv[1]);
      return EXIT_FAILURE;
    }

  START = LO + 0x100U * HI;     /* first word read */

  if (START != 0xFFFF)          /* first two bytes are not $FF $FF */
    {
      printf ("ERROR: %s (first 2 bytes not $FFFF).\n", argv[1]);
      return EXIT_FAILURE;
    }

  SEG_COUNT = 0;                /* counts the number of segments */
  OFFSET = 0;                   /* offset from start-of-file     */

  for (;;)
    {

      HAS_FFFF = (START == 0xFFFF);

      if (HAS_FFFF)
        {

          LO = fgetc (f);
          HI = fgetc (f);

          if ((LO == EOF) || (HI == EOF))
            {
              printf ("ERROR: %s (while reading BLOCK-START address).\n",
                      argv[1]);
              return EXIT_FAILURE;
            }

          START = LO + 0x100U * HI;

        }

      LO = fgetc (f);
      HI = fgetc (f);

      if ((LO == EOF) || (HI == EOF))
        {
          printf ("ERROR: %s (while reading BLOCK-END address).\n", argv[1]);
          return EXIT_FAILURE;
        }

      END = LO + 0x100U * HI;

      if (START > END)
        {
          printf ("ERROR: %s (BLOCK-START > BLOCK-END).\n", argv[1]);
          return EXIT_FAILURE;
        }

      printf ("%04lX | %c | %04hX-%04hX:%6u", OFFSET,
              (HAS_FFFF ? '*' : ' '), START, END, END - START + 1);

      if (fread (MEM + START, 1, END - START + 1, f) != END - START + 1)
        {
          putchar ('\n');
          printf ("ERROR: %s (while reading block).\n", argv[1]);
          puts ("Error, unexpected end of file");
          return EXIT_FAILURE;
        }

      OFFSET = ftell (f);

      printf (" | %6lu |", OFFSET);

      if ((START <= 0x2E0) && (END >= 0x2E1))
        printf (" [Exec: %04lX]", MEM[0x2E0] + MEM[0x2E1] * 0x100UL);
      if ((START <= 0x2E2) && (END >= 0x2E3))
        printf (" [Init: %04lX]", MEM[0x2E2] + MEM[0x2E3] * 0x100UL);

      putchar ('\n');

      ++SEG_COUNT;

      /* AT THIS POINT, A JSR (INITADR) WILL OCCUR */

      LO = fgetc (f);

      if (LO == EOF)
        break;                  /* we're finished! */

      HI = fgetc (f);

      if (HI == EOF)
        {
          printf ("ERROR: %s (while reading next block header).\n", argv[1]);
          return EXIT_FAILURE;
        }

      START = LO + 0x100U * HI;

    }

  printf ("----------------------------------------------------------------"
          "\n{%3d} %s\n", SEG_COUNT, argv[1]);

  /* AT THIS POINT, A JSR(RUNADR) WILL OCCUR */

  return EXIT_SUCCESS;

}
