/*
 * fakeRom : This program supports
 *           debugging of ROM
 *           images in RAM.
 *
 */


/* System includes */

#include <stdio.h>
#include <alloc.h>
#include <string.h>
#include <mem.h>


/* Useful defines and type defs */

#define FAKE_ROM_SIZE 65536L

/* Other useful types */
typedef unsigned long ULONG;
typedef unsigned short USHORT;


/* Pointer to void far function */
typedef void (far *FUNCPTR) ();   





/* -- procedures -- */


/*
 * getAddrPart : Return the segment 
 *               or offset of a 
 *               pointer
 *
 */

USHORT getAddrPart
  (void *tptr, char part) {

  /* Overlay for pointer */
  USHORT components[2];

  /* 
   * Overlay far pointer on 
   * two 16-bit words. 
   */

  memcpy ( (void *)components,
           (void *)&tptr, 
           (long) 4 );

  /* 
   * Return segment or offset
   * as requested by user.
   *
   */

  if ( part == 's' )
    return components[1];
  else
    return components[0];

}





/*
 * physAddr : Make a physical 
 *            address from 
 *            segment, offset 
 *
 */

ULONG physAddr (void *tptr) {

  ULONG addr;  /* return value */

  /*  Get segment  */
  addr = getAddrPart(tptr,'s');
  addr = addr << 4;
  
  /* Get offset */
  addr = addr|getAddrPart(tptr,'o');

  /* Return whole thing */
  return addr;

}




/*
 * loadImage : load a file
 *             into a physical
 *             address.
 *
 */

long loadImage ( FILE *fptr,
                 char buffer[],
                 ULONG size)


 {

   /* Local variables */

   long leftToRead;
   int thisRead;
   long actual;
   int  block;

   /* Initialize */

   actual = 0;
   block  = 0;
   leftToRead = size;

   /* Assume 512 blocks */

   while( 1 ) {
     /* Calculate amount to read */
     if ( leftToRead > 512L )
       thisRead = 512L;
     else
       thisRead = leftToRead; 
    
     /* Perform the read */
     block=fread
         (&buffer[actual],
         1,
        thisRead,
         fptr);

     /* End-of-file test */
     if ( block == 0 )
       return (actual);

     /* Update counters */
     actual += (long)block;
     leftToRead -= (long)thisRead;
   }

 } /* END loadImage */




/*
 * main : main routine of ramrom.c
 *
 */

void main () {

/* Local variables */

ULONG phys;
FILE *ifl;
char *fake_rom_p;
static char imageName[128];
long int actSize;
static char answer[4];
ULONG huge *tptr;
ULONG i;



/*
 * Allocate enough memory
 * for the ROM image
 */

fake_rom_p=
  farmalloc(FAKE_ROM_SIZE);
phys = physAddr ( fake_rom_p );



/*
 * Force all the locations that
 * will not be filled during load
 * to have 0xFF in them.  This
 * mimics the actions of an
 * EPROM programming device.
 */

 tptr=(ULONG * huge) fake_rom_p;
 for(i=0;i<(FAKE_ROM_SIZE/4);i++){
   *tptr = 0xFFFFFFFF;
   tptr++;
 }



/* Show address to user and tell
   user what to do with it */

printf("\n\nFake rom address:");
printf(" 0x%08lx\n",phys);
printf("\nINSTRUCTIONS FOR ");
printf("COMPLETING EMULATION\n");
printf("1. Go to development ");
printf("system or window.\n");
printf("2. Perform the final ");
printf("absolute link of the \n");
printf("   code specifying ");
printf("0x%08lx\n",phys);
printf("   as absolute address,");
printf(" instead of\n");
printf("   usual EPROM address.\n");
printf("3. Move final image to");
printf(" where it can be \n");
printf("   loaded by this ");
printf(" debug program.\n");
printf("4. Enter image name.\n");
printf("5. Enter YES when you are");
printf(" ready to run.\n");

printf("\n=====================\n");

ifl = NULL;


/* Load EPROM IMAGE */

while (ifl==NULL) {
  printf("\nEnter image name: ");
  (void) gets(imageName);
  ifl=fopen(imageName,"rb");
  if (ifl==NULL) {
    perror(imageName);
    continue;
  }

  actSize=
    loadImage(ifl,
      fake_rom_p,
      FAKE_ROM_SIZE);
  if ( actSize < 1 ) {
    ifl = NULL;
    fclose(ifl);
    continue;
  }
  fclose(ifl);

} /* while ifl==NULL */


printf("%lu bytes loaded",actSize);
printf(" from %s\n", imageName);


/* Run EPROM IMAGE */

/* 
 * Note: If you set a breakpoint
 * right here, you can examine
 * your loaded EPROM IMAGE in
 * memory.
 */

printf("Run it? YES/NO: ");
(void) gets( answer );
if (strcmp(answer,"YES")==0) {
  (void)(*((FUNCPTR)fake_rom_p)) ();
}


} /* END main() */


