/*

  P-Code interpreter (to run the apple pascal system)
  Copyright (C) 2000 Mario Klebsch

  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
  (at your option) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


  $Log: native6502.c,v $
  Revision 1.4  2001/06/06 23:14:19  mario
  Turtlegraphics wird jetzt mit einem #define aktiviert

  Revision 1.3  2001/05/26 15:13:29  mario
  Diverse kleine Fehler behoben, fehlende #includes, Labels ohne Statement
  dahinter, ...

  Revision 1.2  2001/05/20 13:12:02  mario
  CVS-Idents und Logs eingefügt


*/

#ident "$Id: native6502.c,v 1.4 2001/06/06 23:14:19 mario Exp $";

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "psystem.h"
#include "pcode.h"
#include "Memory.h"
#include "Array.h"
#include "Term.h"

static void IdSearch(word EntryPoint)
{
  word	BufPtr    = Pop();
  word	Arg2Ptr   = Pop();

  CspIdSearch(BufPtr, Arg2Ptr);
}

static byte IdSearchSig[]=
{ 0x68, 0x85, 0x7e, 0x68, 0x85, 0x7f, 0x68, 0xa8, 0x68, 0xaa,
  0x68, 0x85, 0x94, 0x68, 0x85, 0x95, 0x98, 0xa0, 0x00, 0x18,
  0x71, 0x94, 0x85, 0x96, 0x8a, 0xc8, 0x71, 0x94, 0x85, 0x97,
  0xa9, 0x20, 0xa2, 0x07, 0x95, 0x88, 0xca, 0xd0, 0xfb, 0x88,
  0xb1, 0x96, 0xc9, 0x61, 0x90, 0x07, 0xc9, 0x7b, 0xb0, 0x03 };

static void TreeSearch(word EntryPoint)
{
  word	TokenBuf;
  word	ResultPtr;
  word	NodePtr;

  Pop(); Pop();
  TokenBuf  = Pop();
  ResultPtr = Pop();
  NodePtr   = Pop();			/* initialize with root node addr   */

  Push(CspTreeSearch(TokenBuf, ResultPtr, NodePtr));
}

static void Randomize(word EntryPoint)
{
  srand(time(0L));
}

static byte RandomizeSig1[]=
{ 0xad, 0x13, 0xbf, 0x8d, 0x3f, 0x02, 0x8d, 0x40,
  0x02, 0xad, 0x14, 0xbf, 0x8d, 0x41, 0x02, 0x8d,
  0x42, 0x02, 0x0d, 0x3f, 0x02, 0xd0, 0x05, 0xa9,
  0x55, 0x8d, 0x42, 0x02, 0x60, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x1e, 0x00, 0x1d, 0x00, 0x19, 0x00,
  0x18, 0x00, 0x17, 0x00, 0x12, 0x00, 0x06, 0x00,
  0x00, 0x00, 0x32, 0x00 };

static byte RandomizeSig2[]=
{ 0xad, 0x13, 0xbf, 0x8d, 0x25, 0x02, 0x8d, 0x26,
  0x02, 0xad, 0x14, 0xbf, 0x8d, 0x27, 0x02, 0x8d,
  0x28, 0x02, 0x0d, 0x25, 0x02, 0xd0, 0x05, 0xa9,
  0x55, 0x8d, 0x28, 0x02, 0x60, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x1e, 0x00, 0x1d, 0x00, 0x19, 0x00,
  0x18, 0x00, 0x17, 0x00, 0x12, 0x00, 0x06, 0x00,
  0x00, 0x00, 0x32, 0x00 };

static void Keypress(word EntryPoint)
{
  Pop();
  Pop();
  Push(TermStat());
}

static byte KeypressSig[]=
{  0x68, 0x85, 0x00, 0x68, 0x85, 0x01, 0x68, 0x68,
   0x68, 0x68, 0xa9, 0x00, 0x48, 0xad, 0x21, 0xbf,
   0xd0, 0x06, 0x20, 0x5c, 0xff, 0x4c, 0x1b, 0x00,
   0x20, 0x0a, 0xbf, 0xad, 0x18, 0xbf, 0xcd, 0x19,
   0xbf, 0xf0, 0x04, 0xa9, 0x01, 0xd0, 0x02, 0xa9,
   0x00, 0x48, 0xa5, 0x01, 0x48, 0xa5, 0x00, 0x48,
   0x60, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x01, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x3c, 0x00 };

static void Random(word EntryPoint)
{
  Pop();
  Pop();
  Push(rand()&0x7fff);
}

static byte RandomSig[]=
{  0x68, 0x85, 0x00, 0x68, 0x85, 0x01, 0x68, 0x68,
   0x68, 0x68, 0xa0, 0x07, 0x0e, 0x39, 0x00, 0x08,
   0x2e, 0x3a, 0x00, 0x2e, 0x3b, 0x00, 0x2e, 0x3c,
   0x00, 0x30, 0x05, 0x28, 0x10, 0x08, 0x30, 0x03,
   0x28, 0x30, 0x03, 0xee, 0x39, 0x00, 0x88, 0xd0,
   0xe3, 0xad, 0x39, 0x00, 0x4a, 0x48, 0xad, 0x3b,
   0x00, 0x48, 0xa5, 0x01, 0x48, 0xa5, 0x00, 0x48,
   0x60, 0x5a, 0xb2, 0xf6, 0x93, 0x00, 0x00, 0x00,
   0x33, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2f, 0x00,
   0x24, 0x00, 0x20, 0x00, 0x1d, 0x00, 0x07, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x54, 0x00 };

static byte TreeSearchSig[]=
{ 0x68, 0x85, 0x84, 0x68, 0x85, 0x85, 0x68, 0x68, 0x68, 0x68,
  0x68, 0x85, 0x82, 0x68, 0x85, 0x83, 0x68, 0x85, 0x7e, 0x68,
  0x85, 0x7f, 0x68, 0x85, 0x80, 0x68, 0x85, 0x81, 0xa2, 0x08,
  0xa0, 0xff, 0xca, 0x30, 0x37, 0xc8, 0xb1, 0x82, 0xd1, 0x80,
  0xf0, 0xf6, 0x30, 0x17, 0xa0, 0x08, 0xb1, 0x80, 0xaa, 0xc8,
  0xb1, 0x80, 0xc9, 0x00, 0xd0, 0x04, 0xe0, 0x00, 0xf0, 0x2c,
  0x86, 0x80, 0x85, 0x81, 0x4c, 0x1c };

#ifdef TURTLEGRAPHICS
extern void TurtleGraphics(word EntryPoint);
static byte TurtleSig[16]="TURTLEGRAPHICS::";
#endif

struct
{
  byte	*Sig;
  int	SigLen;
  void	(*Proc)(word);
} Routines[]={ { IdSearchSig, sizeof(IdSearchSig),	IdSearch},
	       { TreeSearchSig, sizeof(TreeSearchSig),	TreeSearch},
#ifdef TURTLEGRAPHICS
	       { TurtleSig, sizeof(TurtleSig),		TurtleGraphics},
#endif
	       { RandomizeSig1, sizeof(RandomizeSig1),	Randomize},
	       { RandomizeSig2, sizeof(RandomizeSig2),	Randomize},
	       { RandomSig, sizeof(RandomSig),		Random},
	       { KeypressSig, sizeof(KeypressSig),	Keypress}
};

#define NUM_ROUTINES (sizeof(Routines)/sizeof(Routines[0]))

static inline word SelfRelPtr(word Addr)
{
#ifdef WORD_MEMORY
  return(Addr-MemRd(Addr)/2);
#else
  return(Addr-MemRd(Addr));
#endif
}

static inline word ProcBase(word JTab)
{
  PointerCheck(JTab);
  return (SelfRelPtr(WordIndexed(JTab,-1)));
}

void ProcessNative(word JTab)
{
  word EntryPoint=ProcBase(JTab);
  int i;
  for (i=0; i<NUM_ROUTINES; i++)
    {
      int j;
      for (j=0; j<Routines[i].SigLen; j++)
	if (MemRdByte(EntryPoint,j)!=Routines[i].Sig[j])
	  goto next;
      Routines[i].Proc(EntryPoint);
      return;
    next:
      ;
    }

#ifdef XXX
  TermClose();
  for (i=0;WordIndexed(EntryPoint,i)<JTab; i++)
    {
      word w=MemRd(WordIndexed(EntryPoint,i));
      printf(" 0x%02x, 0x%02x,", w&0xff, w>>8);
      if ((i&3)==3)
	printf("\n");
    }
  printf("\n");
  panic("ProcessNative: unsupported native routine at 0x%04x", EntryPoint);
#else
  XeqError(XNOTIMP);
#endif
}

