
/*
   This software is copyright 1989 by John Dunning.  See the file
   'COPYLEFT.JRD' for the full copyright notice.
*/

/* obj file dumper */

#include <stdio.h>
#include <file.h>
#include "symtab.h"
#include "obj.h"

#ifdef M6502
#define malloc pmalloc
#endif

int obj_fd;
struct relfile rf;
struct sym ** syms;
int eof = 0;
int nbytes_read;

char litbuf[32];

USHORT read8()
{
  char foo;
  if (read(obj_fd, &foo, 1) != 1)
	eof = 1;
    else
	nbytes_read++;
  return(foo);
}

USHORT read16()
{
  return(read8() | (read8() << 8));
}

struct sym * readsym()
{
  char len;
  struct sym * sym;

  read(obj_fd, &len, 1);
  sym = malloc(sizeof (struct sym) + len);
  read(obj_fd, sym->name, len);
  sym->name[len] = '\0';
  sym->value = read16();
  sym->flags = read16();
  return(sym);
}


main(argc, argv)
int argc;
char ** argv;
{
  int i, j, pc;
  char op;
  
  if (argc < 2)
	{
	printf("printobj what?\n");
	exit(1);
	}
  obj_fd = open(argv[1], O_RDONLY);
  if (obj_fd < 0)
  	{
	printf("can't open %s\n", argv[1]);
	exit(1);
	}
  rf.header = read16();
  rf.nb_sym = read16();
  rf.nb_seg = read16();
  rf.nb_segdata = read16();
  rf.n_sym = read16();
  printf("header %X\n", rf.header);
  if (rf.header != OBJ_HEADER)
  	{
	printf("%s is not an object file\n", argv[1]);
	close(obj_fd);
	exit(1);
	}
  printf("Object file %s:\n", argv[1]);
  printf("  %d symbols in %d bytes\n", rf.n_sym, rf.nb_sym);
  printf("  #x%04x bytes segment data in %d bytes\n", rf.nb_seg, rf.nb_segdata);
/* allocate symbol vector */
  syms = (struct sym ** )malloc(rf.n_sym * sizeof (struct sym *));
/* read them in */
  for (i = 0 ; i < rf.n_sym ; i++)
	syms[i] = readsym();

/* now dump data */
  i = 0;			/* our index in seg data */
  pc = nbytes_read = 0;
  while (pc < rf.nb_seg)
	{
	printf("%04x: ", pc);
	read(obj_fd, &op, 1);
	switch (op & OP_GEN_MASK)
		{
		case OP_LIT:
			{
			if (op == 0)
				op = 32;
			printf("Literal: %2d bytes\n\t", op);
			read(obj_fd, litbuf, op);
			nbytes_read += op;
			for (j = 0 ; j < op ; j++)
				printf(" %02x", litbuf[j] & 0xFF);
			printf("\n");
			pc += op;
			break;
			}
		case OP_REL:
			{
			switch(op)
				{
				case OP_REL:
					{
					printf("Word:    %04x + segment base\n", read16());
					pc += 2;
					break;
					}
				case OP_REL_HI:
					{
					printf("Hi byte: %04x + segment base\n", read16());
					pc += 1;
					break;
					}
				case OP_REL_LO:
					{
					printf("Lo byte: %04x + segment base\n", read16());
					pc += 1;
					break;
					}
				}
			break;
			}
		default:		/* must be a sym */
			{
			j = op & 0x1F;
			if (op & OP_SYM_EMASK)
				j = (j << 8) | read8();
			switch (op & OP_SYM_MASK)
				{
				case OP_SYM:
					{
					printf("Word:    %04x + %s\n", read16(),
						syms[j]->name);
					pc += 2;
					break;
					}
				case OP_SYM_HI:
					{
					printf("Hi byte: %04x + %s\n", read16(),
						syms[j]->name);
					pc += 1;
					break;
					}
				case OP_SYM_LO:
					{
					printf("Lo byte: %04x + %s\n", read16(),
						syms[j]->name);
					pc += 1;
					break;
					}
				}
			break;
			}
		}
	}
  i = read8();
  if (!eof)
	{
	printf("Extra bytes at eof!");
	printf("  %02x\n", i);
	for ( ; !eof ; )
		{
		i = read8();
		if (!eof)
			printf("  %02x\n", i);
		}
	}
  if (nbytes_read != rf.nb_segdata)
  	printf("Byte count mismatch: header says %d bytes, read %d\n",
		rf.nb_segdata, nbytes_read);
  close(obj_fd);
}


