/* vim: set filetype=c:
 *
 * printhex.c86  -  Print a hex memory dump
 *
 * Copyright (C) 1998-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: printhex.c86,v 1.6 2007/01/06 18:31:21 gkminix Exp $
 */

#include <common.h86>
#include <i386/conio.h86>
#include <i386/ctype.h86>
#include <i386/string.h86>
#include "romcheck.h86"



/*
 * Some useful defines
 */
#define MAXLINES	16	/* number of lines to print on one screen */
#define LINESIZE	16	/* number of hex values per line */



/*
 * Print one line of hex code
 */
static void printline(unsigned short seg)
{
  static __u8 buf[LINESIZE + 1];
  size_t i;

  /* Fill buffer from rom memory */
  movemem(far2linear(MK_FP(seg, 0)),
          far2linear(MK_FP(getds(), (int)(buf))),
          LINESIZE);

  /* Print buffer in hex and convert it into a printable string */
  printf("%04hX0  ", seg);
  for (i = 0; i < LINESIZE; i++) {
	printf(" %02hX", (unsigned short)(buf[i] & 0xff));
	if (!isprint(buf[i] & 0xff))
		buf[i] = '.';
  }
  buf[LINESIZE] = '\0';
  printf("   %s\n", buf);
}



/*
 * Print a rom area or the whole memory as a hex dump.
 */
void printhex(const struct scaninfo *sip)
{
  unsigned short memstart, memend;
  unsigned short curpos, i;
  unsigned short index;
  char c;

  /* Ask the user about which area to print */
  if (sip->signum == 0)
	index = 0;
  else {
	printf("\n\n");
	index = readint("Enter rom area number, 0 for whole memory",
						0, (int)(sip->signum), 0);
  }
  if (index > 0) {
	index--;
	memstart = sip->sigsegs[index];
	memend = sip->sigsegs[index] + sip->sigsize[index];
  } else {
	memstart = readhex("Enter start segment",
					STARTSEG, ENDSEG - 1, STARTSEG);
	memend = readhex("Enter end segment",
					memstart + 1, ENDSEG, memstart + 1);
  }
  curpos = memstart;

  /* Print one page of output and ask user what to do next */
  while (TRUE) {
	printf("\n\n");
	for (i = curpos; i < (curpos + MAXLINES) && i < memend; i++)
		printline(i);
	printf("\nPress <q> to exit");
	if (i < (memend - 1))
		printf(", <space> or <e> to continue");
	if (curpos > memstart)
		printf(", <b> or <t> to go back");
	do {
		c = waitchar();
		switch (c) {
			case 'q':
				putchar('\n');
				return;
			case 'b':
				if (curpos > memstart) {
					if ((curpos - memstart) < MAXLINES)
						curpos = memstart;
					else
						curpos -= MAXLINES;
				} else
					c = '\0';	/* invalid command */
				break;
			case 't':
				if (curpos > memstart)
					curpos = memstart;
				else
					c = '\0';	/* invalid command */
				break;
			case ' ':
				if (i < (memend - 1))
					curpos = i;
				else
					c = '\0';	/* invalid command */
				break;
			case 'e':
				if (i < (memend - 1)) {
					if ((memend - memstart) < MAXLINES)
						curpos = memstart;
					else
						curpos = memend - MAXLINES;
				} else
					c = '\0';	/* invalid command */
				break;
			default:
				c = '\0';		/* invalid command */
				break;
		}
	} while (!c);
  }
}

