/***************************************************************************/
/*                            DATAPATH SIMULATOR                           */
/*                                                                         */
/*                              By Emily Ezust                             */
/*                                   1993				   */
/*                                                                         */
/*                 Based on Andrew Tanenbaum's hypothetical                */
/*                   Complex Instruction Set Computer                      */
/*                                                                         */
/***************************************************************************/

/***************************************************************/
/*                                                             */
/* Copyright (c) 1995 by Emily Ezust                           */
/*                                                             */
/* This software is hereby licensed for non-commercial use     */
/* only.  It may be freely distributed but it may not be used  */
/* for monetary profit.  Commercial use of this software is    */
/* not permitted without an explicit written agreement with    */
/* the author.                                                 */
/*                                                             */
/***************************************************************/

/* display module */

#include <stdio.h>
#include "structs.h"
#include <signal.h>
#include <curses.h>
#include "constants.h"

/* external - from dpcur.c */
extern int current_screen ;
extern int num_inst ;
extern int mcp[CONTROL_STORE_SIZE][INST_LENGTH] ;
extern point screen[24][80] ;
extern int ram[RAM_SIZE] ;
extern int program_size ;
extern int scratch[SCRATCH_LENGTH] ;
extern table_entry ct[23] ;
extern char microcode[MAX_MICROCODE_SIZE][MAX_PSEUDOINST_LENGTH] ;
extern int M_DELAY ;

/* prototypes */

void print_code(int, FILE *, int, int) ;
void dp_screen(void) ;
void menu_screen(void) ;
void message(char []) ;
void message2(char [], int, char[]) ;
void message3(char [], int, char[], int) ;
void emulate_more(int) ;

void emulate_more(int row)
{
  if (row > 1 && !(row % 22))
    {
      printw("Hit return to advance a screenfull...") ;
      refresh() ;
      getch() ;
      clear() ;
      move(0,0) ;
    }
}


void display(int to_display) 
/* possible values for to_display are
   RAM, PROG, and MCP */
{
  int i, j, val ;

  if (to_display == PROG || to_display == MCP)
    {
      clear() ;
      move(0,0) ;
      current_screen = DISPLAY ;
      if (to_display == MCP) {
    
	for (i = 0; i < num_inst; i++)  
	  {
	    printw("%d: ", i) ;
	    for (j = 0 ; j < INST_LENGTH; j++)
	      printw("%d ", mcp[i][j]) ;
	    printw("\n") ;
	    emulate_more(i) ;
	    refresh() ;
	  }
	printw("Hit return when you are finished....") ;
	refresh() ;
	getch() ;
      }
      else
        {
	  for (i = 0 ; i < program_size; i++) 
	    {
	      printw("%d: ", i) ;
	      print_code(i, stdout, RAM, FALSE) ;
	      printw("\n") ;
	      emulate_more(i) ;
	    }
	  printw("Hit return when you are finished....") ;
	  refresh() ;
          getch() ;
	}
    }
  else /* specific location in RAM */ 
    {
      move(22,0) ;
      printw("Enter RAM location: ") ;
      refresh() ;
      scanw("%d", &i) ;
      move(22,0) ;
      clrtoeol() ;
      val = ram[i] ;
      if (neg(val))
	message3("Contents of RAM at ", i, " is ", val - pow2(16)) ;
      else
	message3("Contents of RAM at ", i, " is ", ram[i]) ; 
    }
}

display_program() 
{
  if (program_size > 0)
    display(PROG) ;
  else  
    message("The program has not yet been loaded.") ;
}

display_mic()
{
  if (num_inst > 0)
    display(MCP) ;

  else  
    message("The microprogram has not yet been loaded.") ; 
}

void display_neg(int data)
{
  printw("%-6d", data - pow2(16)) ;
}

void print_code(int index, FILE *fp, int source, int translate)
/* sources: RAM or REGS 
   if translate is TRUE, print the microcode equivalent on line below */
{
  int i, bits[8] ;
  int num ;
  int op = 0;
  int ct_index ;
  int more = TRUE ;
  int addr ;
    
  if (source == RAM)
    num = ram[index] ;
  else
    num = scratch[index] ;

  for (i = 0; i < 8; i++)
    bits[i] = nth_bit(num, i, 15) ;
  for (i = 0; i < 4; i++)
    op = op + bits[i]*pow2(15-i) ;      /* sum of first four bits */
  
  if (bits[0] & bits[1] & bits[2] & bits[3])   /* code starts 1111 */
    if (bits[4] & bits[5])    /* eight-bit code */
      for (i = 4; i < 8; i++)
	op = op + bits[i]*pow2(15-i) ;    /* sum of next four bits */
    else   /* sixteen-bit code */
      {
	op = num ;
	more = FALSE ;
      }
  else /* four-bit code */
    ;
  ct_index = table_search_numeric(op) ;

  if (fp == stdout)
    printw("%s", ct[ct_index].alpha) ;
  else
    fprintf(fp, "%s ", ct[ct_index].alpha) ;
  if (more) 
    {
      addr = num - op ;
      if (fp == stdout)
	printw(" %d", addr) ;
      else
	fprintf(fp, "%-5d", addr) ;
    }
  if (translate) 
    {
      printw("\nEquivalent microcode: ") ;
      al_to_mic(ct[ct_index].alpha, addr) ;
    }
}



void dp_screen()
{
  int i, j ;

  current_screen = DP ;
  clear() ;
  move(0,0) ;
  for (i=0; i< 23; i++) 
    {
      for(j=0; j< 80; j++)
	addch(screen[i][j].chr) ;
      refresh() ;
    }
  screen_update() ;
}


void message(char m[]) 
{
  move(23,0) ;
  clrtoeol() ;
  printw("%s", m) ;
  refresh() ;
  move(23,0) ;
  refresh() ;
  delay(M_DELAY);
/*  clrtoeol(); 
  refresh() ; */
}

void message2(char m1[], int num, char m2[]) 
{
  move(23,0) ;
  clrtoeol() ;
  printw("%s%d%s", m1, num, m2) ;
  refresh() ;
  move(23,0) ;
  refresh() ;
  delay(M_DELAY);
/*  clrtoeol() ; 
  refresh() ; */
}
void message3(char m1[], int num1, char m2[], int num2) 
{
  move(23,0) ;
  clrtoeol() ;
  printw("%s%d%s%d", m1, num1, m2, num2) ;
  refresh() ;
  move(23,0) ;
  refresh() ;
  delay(M_DELAY);
/*  clrtoeol() ;
  refresh() ; */
}

void menu_screen(void)
{
  current_screen = MENU ;
  clear() ;
  move(0,0) ;
  printw("				  Menu") ;
  printw("\n\n0.  This menu.") ;
  printw("\n1.  Enter program editor") ;
  printw("\n2.  Enter microcode editor") ;
  printw("\n3.  Edit contents of specified register") ;
  printw("\n4.  Edit contents of RAM at specified location") ;
  printw("\n5.  Run program in slow motion") ;
  printw("\n6.  Run program at full speed") ;
  printw("\n7.  Set breakpoint") ;
  printw("\n8.  Display contents of RAM") ;
  printw("\n9.  Load microprogram") ;
  printw("\n10. Display microprogram") ;
  printw("\n11. Save microprogram") ;
  printw("\n12. Unload microprogram") ;
  printw("\n13. Load program") ;
  printw("\n14. Display program") ;
  printw("\n15. Save program") ;
  printw("\n16. Unload program ") ;
  printw("\n17. Go to Datapath screen") ;
  printw("\n18. Configure") ;
  printw("\n99. Quit") ;
  refresh() ;
}

