/* debug.cpp
 */


#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "exception.h"
#include "symtab.h"

#ifndef FALSE
#define FALSE 0
#define TRUE  (!FALSE)
#endif

typedef unsigned char byte;

/* ************************************************************ */
/* Public members                                               */
/* ************************************************************ */

void Debug::readCip (int start, int end)
{
int n, d;
  if (start < 0 || start >= 0x10000) {
    prt->printf ("L'inizio deve esssere compreso tra 0000 ed fffff (%04x)\n", start);
    return;
  }
  if (end < 0 || end >= 0x10000) {
    prt->printf ("La fine deve esssere compreso tra 0000 ed fffff (%04x)\n", end);
    return;
  }
  if (start >= end) {
    prt->printf ("Fine prima dellinizio (%04x >= %04x)\n", start, end);
    return;
  }

  if (resetVector (NULL)) {
    prt->printf ("La scrittura e' abilitata\n");
  } else {
    prt->printf ("La scrittura e' disabilitata - occorre cancellare il Chip\n");
  }

  start &= 0xfff0;
  for (n = start; n <= end; n++) {
    if ((n % 0x10) == 0) {
      prt->printf ("\n%04x %02X",n, read (n));
    } else {
      d = iread ();
      if (n % 0x10 < 0xf) {
        prt->printf (" %02X %02X", d >> 8, d & 0xff);
        n ++;
      } else {
        prt->printf (" %02X", d >> 8);
      }
    }
  }
  prt->printf ("\n");
}

void Debug::testChip (void)
{
int n, d, i;
int start = 0x80;
int num = 0x21;
int nh, nl;

  d = 0;
  while (1) {
    try {
      i = schGetc (500000);
    } catch (void *e) {
      continue;
    }
    switch (d) {
      case 0: // start;
        switch (i) {
          case 0x4a:  // Read ; nh, nl, -res
          case 0x49:  // Write ; nh, nl, d
          case 0x1a:  // Iread ; -resH, -resL
          case 0x19:  // Iwrite ; d
          case 0x0c:  // ReadSP ; -sph, -spl
          case 0x28:  // Run
            d = i << 8;
            break;
          default:
            prt->printf ("%02X\n",i);
            break;
        }
        break;
      case 0x4a00:  // Read ; nh, nl, -res
      case 0x4900:  // Write ; nh, nl, d
      case 0x1a00:  // Iread ; -resH, -resL
      case 0x1900:  // Iwrite ; d
      case 0x0c00:  // ReadSP ; -sph, -spl
      case 0x2800:  // Run
        // Echo comando
        if (i != (d >> 8)) {
          prt->printf ("%02x %02x\n", d >> 8, i);
          d = 0;
        } else {
          if (d == 0x2800) {
            prt->printf ("Run\n");
            d = 0;
          } else {
            d++;
          }
        }
        break;
      case 0x4a01:  // Read ; nh, nl, -res
      case 0x4901:  // Write ; nh, nl, d
      case 0x1901:  // Iwrite ; d
      case 0x1a01:  // Iread ; -resH, -resL
      case 0x0c01:  // ReadSP ; -sph, -spl
        // Primo parametro trasmesso o ricevuto
        nh = i;
        d++;
        break;
      case 0x4a02:  // Read ; nh, nl, -res
      case 0x4902:  // Write ; nh, nl, d
      case 0x1902:  // Iwrite ; d
        // Eco primo dato
        if (i == nh) {
          if (d == 0x1902) {
            prt->printf ("Iwrite %02x\n", nh);
            d = 0;
          } else {
            d ++;
          }
        } else {
          prt->printf ("%02x %02x [%02x]\n", d >> 8, nh, i);
          d = 0;
        }
        break;
      case 0x1a02:  // Iread ; -resH, -resL
        prt->printf ("Iead = %02x %02x\n", nh, i);
        d = 0;
        break;
      case 0x0c02:  // ReadSP ; -sph, -spl
        prt->printf ("ReadSP %02x%02x\n", nh, i);
        d = 0;
        break;
      case 0x4a03:  // Read ; nh, nl, -res
      case 0x4903:  // Write ; nh, nl, d
        // Secondo parametro trasmesso
        nl = i;
        d++;
        break;
      case 0x4a04:  // Read ; nh, nl, -res
      case 0x4904:  // Write ; nh, nl, d
        // Echo secondo parametro
        if (i != nl) {
          prt->printf ("%02x %02x %02x [%02x]\n", d >> 8, nh, nl , i);
          d = 0;
        } else {
          d++;
        }
        break;
      case 0x4a05:  // Read ; nh, nl, -res
        prt->printf ("Read %02x%02x = %02x\n", nh, nl, i);
        d = 0;
        break;
      case 0x4905:  // Write ; nh, nl, d
        // Dato trasmesso
        n = i;
        d++;
        break;
      case 0x4906:  // Write ; nh, nl, d
        // Echo dato trasmesso
        if (i != n) {
          prt->printf ("%02x %02x %02x %02X [%02x}\n", d >> 8, nh, nl, n , i);
        } else {
          prt->printf ("Write %02x%02x %02x\n", nh, nl, n);
        }
        d = 0;
        break;
      default:
        prt->printf ("Stato %04x nh %02x, nl %02x, n %02x, i %02x\n", d, nh, nl, n, i);
        d = 0;
        break;
    }
  }
}

/* Trace fatta da P&E Micro
Legge dec1 : c7 ff ff               Legge dec4 : 20 23 (PC)
Legge fe09 : debf                   Legge fe09 : debf
scrive fe09 : dec4                  Scrive fe09 : dee9  BRKH/BRKL
Scrive fe0b : 80                    Scive fe0b : 80     BRKSCR (BRKE, /BRKA)
Run                                 Run
[Break]                             [Break]

ReadSP 012a                         ReadSP 012a
Read 012e : de c4                   Read 012e : dee9    SP[5] -> PC
Write fe0b : 00                     Write fe0b : 00     BRKSCR - Break Status and Control
Write fe09 : de bf                  write fe09 : de bf  BRKH/BRKL
ReadSP 012a                         ReadSP 012a
Read 12a : de 6d ff 00 de c4        Read 12a : de 6d ff 00 de e9  - H (de) CCR (6d) A (ff) X (00) PC (dee9)
Read fe01 : 00                      Read fe01 : 00      SRSR - SIM Reset Status Register
Read feeb : 1f                      Read feeb : 1f
Read fe0a : bf                      Read fe0a : bf      BRKL
Write fe0a : 55                     Write fe0a : 55
Read fe0a : 55                      Read fe0a : 55
Write fe0a : bf                     Write fe0a : bf
Read deb0 : 38 6e ff 05 1c 01 1e 01 Read dee0 : 23 03 1d 01 65 1c 01 1e
     deb8 : 6e 60 3f 6e a1 3c 81 ad      dee8 : 01 0f 3c d5 20 d8 00 00
     dec0 : e2 c7 ff ff 20 23 b6 3e      def0 : ff ff ff ff ff ff ff ff
     dec8 : a1 bf 23 04 1d 01 20 08      def8 : ff ff ff ff ff ff ff ff
Read 0130 : cd 9c 67 6f 2f cc 6c 9b Read 0130 : cd 9c 67 6f 2f cc 6c 9b
     0138 : 82 4f 21 82 9b ee f9 c8      0138 : 82 4f 21 82 9b ee f9 c8
     0140 : cd cd cd cd cd cd cd cd      0140 : cd cd cd cd cd cd cd cd
     0148 : cd cd cd cd cd cd cd cd      0148 : cd cd cd cd cd cd cd cd
Read 0080 : 7f 8c ff fe 00 02 00 0a Read 0080 : 7f 8c ff fe 00 02 00 0a
     0088 : 40 0a ff ff de 8c 1d 01      0088 : 40 0a ff ff de 8c 1d 01
     0090 : 65 1c 01 1e 01 0f 3c d5      0090 : 65 1c 01 1e 01 0f 3c d5
     0098 : 20 d8 00 00 b6 3e a1 7f      0098 : 20 d8 00 00 b6 3e a1 7f
 */

void Debug::stepPgm (const char *hexfile)
{
int i, l = 0;
int n = 0;
int s, sp;
int a, hx, ccr, d;
int caller;
unsigned char prog [PROTCVECTORLEN];
SymTab sym;

  readS19 (hexfile, PROTVECTOR, PROTCVECTORLEN, prog, NULL);

  n = isErased (prog); // Vettore di sicurezza letto ($FFF6­$FFFD)
  if (!n) {
    throw (new Exception ("La ROM e' cancellata - non posso eseguire\n"));
  } else if (n == -1) {
    prt->printf ("La ROM e' prgrammata\n");
  }

  sym.loadSymTab (hexfile);

  // Leggo il vettore di reset
  s = (prog [PROTCVECTORLEN-2] << 8) + prog [PROTCVECTORLEN-1]; // Reset vector
prt->printf ("Reset Vector = (%04X)\n", s);
  // Lancio pi programma dal vettore di reset
  setPc (s);    // Points PC to start of program (reset vector)
  // Loop echo tastiera/seriale
  while (1) {
  SymNode *line;
    prt->printf ("%4d %s ", l++, step (RUN_STEP_INTO));
    while (!runEnded ()) {}
    endStep ();
    s = getPc ();
    sp = getSp ();
    caller = (read (sp+6)<<8) + read (sp+7);
    line = sym.getSymFromAddr (s, GET_FIRST);
    if (line) {
      prt->printf ("[%s %d] ", line->getFile (), line->getLine ());
    }
    prt->printf ("PC=%04X a=%02x CCR=%02x HX=%04X SP=%04x Caller=%04x\n", s, getA (), getCcr (), getHx (), getSp (), caller);
    fflush (stdout);
  }

  prt->printf ("\n");
}

void Debug::runPgm (const char *hexfile)
{
int i;
int n = 0;
int s;
unsigned char prog [PROTCVECTORLEN];

  readS19 (hexfile, PROTVECTOR, PROTCVECTORLEN, prog, NULL);

  n = isErased (prog); // Vettore di sicurezza letto ($FFF6­$FFFD)
  if (!n) {
    throw (new Exception ("La ROM e' cancellata - non posso eseguire\n"));
  } else if (n == -1) {
    prt->printf ("La ROM e' prgrammata\n");
  }

  // Leggo il vettore di reset
  s = (prog [PROTCVECTORLEN-2] << 8) + prog [PROTCVECTORLEN-1]; // Reset vector
prt->printf ("Reset Vector = (%04X)\n", s);
  // Lancio pi programma dal vettore di reset
  go (s);
  // Loop echo tastiera/seriale
  term ();
}


