/*****************************************************************************

			       XCopilot

This code is part of XCopilot, a port of copilot

     Portions of this code are Copyright (C) 1997 Ivan A. Curtis
		       icurtis@radlogic.com.au

The original MS-Windows95 copilot emulator was written by Greg Hewgill.
The following copyright notice appeared on the original copilot sources:

		  Copyright (c) 1996 Greg Hewgill

 MC68000 Emulation code is from Bernd Schmidt's Unix Amiga Emulator.
       The following copyright notice appeared in those files:

	  Original UAE code Copyright (c) 1995 Bernd Schmidt

This code must not be distributed without these copyright notices intact.

*******************************************************************************
*******************************************************************************

Filename:	pilotcpu.c

Description:	Copilot cpu interface module

Update History:   (most recent first)
   I. Curtis   5-Mar-97 21:06 -- added cpu_loadapp procedure
   I. Curtis  ??-Mar-97 ??:?? -- reorganized main loop in CPU()

******************************************************************************/
#include <unistd.h>
#include <stdio.h>

#include "sysdeps.h"
#include "shared.h"
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
#include "pilotcpu.h"
#include "fakecall.h"

int CPU(shared_img *shptr)
{
  shptr->CpuState = cpuStopped;
  do {
    switch (shptr->CpuReq) {
    case cpuStart:
      shptr->CpuReq = cpuNone;	            /* clear request */
      /*
       *       fprintf(stderr, "I - CPU Started\n");
       *       fflush(stderr);
       */
      MC68000_run();
      break;
    case cpuStop:
      shptr->CpuReq = cpuNone;
      shptr->CpuState = cpuStopped;
      /*
       *       fprintf(stderr, "I - CPU Stopped\n");
       *       fflush(stderr);
       */
      break;
    case cpuReset:
      shptr->CpuReq = cpuNone;
      MC68000_reset();
      /*
       *       fprintf(stderr, "I - CPU Reset\n");
       *       fflush(stderr);
       */
      break;
    case cpuLoadApp:
      shptr->CpuReq = cpuNone;
      CPU_loadapp(shptr);
      shptr->CpuState = cpuLoaded;
      break;
    case cpuExit:
      break;
    default:
      usleep(1000);		            /* sleep for 1 ms */
    }
  }
  while (shptr->CpuReq != cpuExit);
  /*
   *   fprintf(stderr, "I - CPU Exiting\n");
   *   fflush(stderr);
   */
  return 0;
}

int CPU_init(shared_img *shptr, int ramsize)
{
  int r;
  /*
   *   fprintf(stderr, "I - initializing memory\n");
   *   fflush(stderr);
   */
  r = memory_init(ramsize);
  if (r != 0) {
    return r;
  }

  /*
   *   fprintf(stderr, "I - doing custom initialization\n");
   *   fflush(stderr);
   */
  custom_init(shptr);

  /*
   *   fprintf(stderr, "I - doing m68k initialization\n");
   *   fflush(stderr);
   */
  MC68000_init(shptr);

  /*
   *   fprintf(stderr, "I - doing m68k reset\n");
   *   fflush(stderr);
   */
  MC68000_reset();

  return 0;
}

void CPU_reset(shared_img *shptr)
{
  /*
   *   fprintf(stderr, "I - Resetting CPU..\n");
   *   fflush(stderr);
   */
  shptr->CpuReq = cpuReset;
  while (shptr->CpuState != cpuStopped) {
    usleep(1000);
  }
}

void CPU_start(shared_img *shptr)
{
  /*
   *   fprintf(stderr, "I - Starting CPU..\n");
   *   fflush(stderr);
   */
  shptr->CpuReq = cpuStart;
  while (shptr->CpuState != cpuRunning) {
    usleep(1000);
  }
}

void CPU_stop(shared_img *shptr)
{
  /*
   *   fprintf(stderr, "I - Stopping CPU..\n");
   *   fflush(stderr);
   */
  shptr->CpuReq = cpuStop;
  while (shptr->CpuState != cpuStopped) {
    usleep(1000);
  }
}

void CPU_wait(shared_img *shptr)
{
  /*
   *   fprintf(stderr, "I - Waiting for CPU to Stop\n");
   *   fflush(stderr);
   */
  while (shptr->CpuState == cpuRunning) {
    usleep(1000);
  }
}

char *CPU_getstate(shared_img *shptr)
{
  switch (shptr->CpuState) {
  case cpuInitial: return "Initial";
  case cpuRunning: return "Running";
  case cpuStopped: return "Stopped";
  case cpuBreakpoint: return "Breakpoint";
  case cpuException: return "Exception";
  default: return "UNKNOWN-ERROR";
  }
}

void *CPU_getmemptr(CPTR addr)
{
  return get_real_address(addr);
}

void CPU_getregs(shared_img *shptr, struct regstruct *r)
{
  *r = shptr->regs;
  r->pc = MC68000_getpc();
}

void CPU_setregs(shared_img *shptr, struct regstruct *r)
{
  shptr->regs = *r;
  MakeFromSR();
  MC68000_setpc(r->pc);
}

int CPU_setexceptionflag(shared_img *shptr, int exception, int flag)
{
  int r;
  if (exception < 0 || exception >= 48) {
    return 0;
  }
  r = shptr->ExceptionFlags[exception];
  shptr->ExceptionFlags[exception] = flag;
  return r;
}

void CPU_putbyte(CPTR addr, UBYTE x)
{
  put_byte(addr, x);
}

void CPU_putword(CPTR addr, UWORD x)
{
  put_word(addr, x);
}

void CPU_putlong(CPTR addr, ULONG x)
{
  put_long(addr, x);
}

UBYTE CPU_getbyte(CPTR addr)
{
  return get_byte(addr);
}

UWORD CPU_getword(CPTR addr)
{
  return get_word(addr);
}

ULONG CPU_getlong(CPTR addr)
{
  return get_long(addr);
}

void CPU_loadapp(shared_img *shptr)
{
  int err = 0;
  int dbid;
  /*
   *   fprintf(stderr, "I - CPU Loading..\n");
   *   fflush(stderr);
   */
  {
    FakeCall *fc;
    fc = fc_New(shptr);
    fc_PushLong(fc, 0x00010006); /* nameP */
    fc_PushWord(fc, 0);	   /* cardNo */
    /*
     *     fprintf(stderr, "I - making fake call (FindDatabase)..\n");
     *     fflush(stderr);
     */
    fc_Call(fc, shptr, sysTrapDmFindDatabase, 0);
    dbid = fc_GetResultD0(fc);
    /*
     *     fprintf(stderr, "I - result was %d\n", dbid);
     *     fflush(stderr);
     */
    fc_Dispose(fc, shptr);
  }

  if (dbid) {
    FakeCall *fc;
    fc = fc_New(shptr);
    fc_PushLong(fc, dbid);	/* dbID */
    fc_PushWord(fc, 0);	/* cardNo */
    /*
     *     fprintf(stderr, "I - making fake call (DeleteDatabase)..\n");
     *     fflush(stderr);
     */
    fc_Call(fc, shptr, sysTrapDmDeleteDatabase, 0);
    err = fc_GetResultD0(fc);
    /*
     *     fprintf(stderr, "I - result was %d\n", err);
     */
    fc_Dispose(fc, shptr);
  }
  if (err == 0) {
    FakeCall *fc;
    fc = fc_New(shptr);
    fc_PushLong(fc, 0x00010006);
    /*
     *     fprintf(stderr, "I - making fake call (CreateDatabaseFromImage)..\n");
     *     fflush(stderr);
     */
    fc_Call(fc, shptr, sysTrapDmCreateDatabaseFromImage, 0);
    dbid = fc_GetResultD0(fc);
    /*
     *     fprintf(stderr, "I - result was %d\n", dbid);
     */
    fc_Dispose(fc, shptr);
  }

  shptr->ErrNo = err;
  /**********************************************************************
  if (err == 0) {
    fprintf(stderr, "Application loaded successfully!\n");
  } else {
    switch (err) {
    case memErrNotEnoughSpace:
      fprintf(stderr, "Not enough free memory to load app");
      break;
    case dmErrDatabaseOpen:
      fprintf(stderr, "Application is currently in use");
      break;
    default:
      fprintf(stderr, "Unknown error 0x%x loading application.", err);
      break;
    }
  }
  fflush(stderr);
  ********************************************************/
}
