home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / cpem8010.zip / bios.cc < prev    next >
C/C++ Source or Header  |  1995-02-16  |  9KB  |  402 lines

  1. //     $Id: bios.cc 1.5 1995/02/16 22:54:33 rg Exp $    
  2. //      Copyright (c) 1994 by R. Griech
  3. //
  4. //  Bios Simulation
  5. //  ---------------
  6. //  Simulation of the BIOS part of a CP/M machine.  This is very simple, because
  7. //  currently only char-I/O is handled.  One more or less difficult thing is the
  8. //  terminal emulation, because the ESC-sequences have to be catched and interpreted
  9. //  and then the appropriate termcap function have to be called.  Be aware, that
  10. //  most standard ANSI-drivers wont handle INS/DEL-line sequences (ANSICALL.DLL of
  11. //  OS/2 2.x, ANSI.SYS of D@*!).  But e.g. ZANSI.SYS is a good choice for D@*!.
  12. //
  13. //  terminal emulation
  14. //  ------------------
  15. //  - this file contains also the terminal emulation, it is based on termcap
  16. //  - the terminal emulation is tested only with the OS/2 ansi emulation available
  17. //    under OS/2 (DOSCALL.DLL), the ANSI.SYS of D@*! and ZANSI.SYS for the same
  18. //    program loader
  19. //  - take care, that the TERM/TERMCAP refer your terminal in the DOS / OS/2 world,
  20. //    and the terminal-type in the emulators commandline to the terminal, the CP/M
  21. //    program is EXPECTING.  This terminals shoud be compatible to obtain good results
  22. //    (i.e. height/width, line wrapping should have the same behavior)
  23. //  - termcap is initialized on the first usage of itself.  I hope this doesn't interfer
  24. //    with the previously sent character
  25. //  - the emulations are far from complete (and far from optimal)
  26. //  - one possible problem area is, that usual (good old) terminal only have 24 lines...
  27. //
  28.  
  29.  
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <termcap.h>
  35. #include <termios.h>
  36. #include "glob.h"
  37.  
  38.  
  39.  
  40. typedef enum {none,tvi920,debug} Terminals;
  41.  
  42. static int KbdBuff = -1;
  43. static Terminals Terminal = none;
  44. static int TermCapUsed = 0;
  45. static int OutBufDownCnt = 0;
  46.  
  47.  
  48.  
  49. //
  50. //
  51. //  get termcap entry
  52. //
  53. static char *TermCapGetEntry( char *entry )
  54. {
  55.    char *res = tgetstr( entry,0 );
  56.    if (res == 0) {
  57.       fprintf( stderr,"terminal knows nothing about termcaps '%s'   \r\n",entry );
  58.       fprintf( stderr,"sorry, but your terminal (or your termcap entry) is to dumb   \r\n" );
  59.       ExitCode = 3;
  60.    }
  61.    return( res );
  62. }   // TermCapGetEntry
  63.  
  64.  
  65.  
  66. //
  67. //
  68. //  send a character to the terminal (intended for termcap)
  69. //
  70. #define TermPutc( ch )  (putchar( ch ))
  71.  
  72.  
  73.  
  74. //
  75. //
  76. //  send a string to the terminal (intended for termcap)
  77. //
  78. static void TermPuts( char *s )
  79. {
  80.    if (s) {
  81.       while (*s)
  82.      TermPutc( *(s++) );
  83.    }
  84. }   // TermPuts
  85.  
  86.  
  87.  
  88. static void TermPutsTi( void )
  89. {
  90.    // don't use TermCapGetEntry here (endless loop on failure)
  91.    TermPuts( tgetstr("ti",0) );
  92. }   // TermPutsTi
  93.  
  94.  
  95.  
  96. static void TermPutsTe( void )
  97. {
  98.    // don't use TermCapGetEntry here (endless loop on failure)
  99.    TermPuts( tgetstr("te",0) );
  100. }   // TermPutsTe
  101.  
  102.  
  103.  
  104. //
  105. //
  106. //  init the terminal + termcap
  107. //
  108. static void TermCapInit( void )
  109. {
  110.    char *termtype = getenv ("TERM");
  111.    int success;
  112.      
  113.    if (TermCapUsed)
  114.       return;
  115.    TermCapUsed = 1;
  116.  
  117.    //
  118.    //
  119.    //  fetch termcap entry
  120.    //
  121.    {
  122.       if (termtype == 0)
  123.          fatal ("Specify a terminal type with `setenv TERM <yourtype>'.\n");
  124.      
  125.       success = tgetent ( NULL, termtype);
  126.       if (success < 0)
  127.          fatal ("Could not access the termcap data base.\n");
  128.       if (success == 0)
  129.          fatal ("Terminal type `%s' is not defined.\n", termtype);
  130.    }
  131.  
  132.    //
  133.    //
  134.    //  init the thingie
  135.    //
  136.    TermPutsTi();
  137. }   // TermCapInit
  138.  
  139.  
  140.  
  141. //
  142. //
  143. //  exit the termcap
  144. //
  145. static void TermCapExit( void )
  146. {
  147.    if (!TermCapUsed)
  148.       return;
  149.    TermCapUsed = 0;
  150.    TermPutsTe();
  151. }   // TermCapExit
  152.  
  153.  
  154.  
  155. //
  156. //
  157. //  position the cursor
  158. //
  159. static int TermPutsCm( int x, int y )
  160. {
  161.    static char *cm = NULL;
  162.    char TermBuf[50];
  163.  
  164.    if (!TermCapUsed)
  165.       TermCapInit();
  166.    if (cm == NULL)
  167.       cm = TermCapGetEntry( "cm" );
  168.    TermPuts( tparam(cm,TermBuf,sizeof(TermBuf),x,y) );
  169. }   // TermGoto
  170.  
  171.  
  172.  
  173. //
  174. //
  175. //  generate subroutines for termcap calls (names will be TermPuts #TYP)
  176. //
  177. #define TermPutsXx( TYP )            \
  178. static void TermPuts ## TYP( void )        \
  179. {                        \
  180.    static char *TYP = NULL;            \
  181.                         \
  182.    if (!TermCapUsed)                \
  183.       TermCapInit();                \
  184.    if (TYP == NULL)                \
  185.       TYP = TermCapGetEntry( #TYP );        \
  186.    TermPuts( TYP );                \
  187. }   // TermPutXx
  188.  
  189. TermPutsXx( al )
  190. TermPutsXx( ce )
  191. TermPutsXx( cl )
  192. TermPutsXx( dl )
  193. TermPutsXx( me )
  194. TermPutsXx( md )
  195.  
  196.  
  197.  
  198. static void EmuTvi920( unsigned char ch )
  199. {
  200.    static int EscDownCounter = 0;
  201.    static int EscAdvance, EscNdx;
  202.    static unsigned char EscBuffer[4];
  203.  
  204.    if (EscDownCounter == 0) {
  205.       switch (ch)
  206.      {
  207.      case 0x00:
  208.         break;
  209.      case 0x0a:
  210.         TermPutc( '\n' );
  211.         break;
  212.      case 0x0d:
  213.         TermPutc( '\r' );
  214.         break;
  215.      case 0x1a:
  216.         TermPutscl();
  217.         break;
  218.      case 0x1b:
  219.         EscDownCounter = 1;
  220.         EscAdvance     = 0;
  221.         EscNdx         = 0;
  222.         break;
  223.      default:
  224.         TermPutc( ch );
  225.         break;
  226.      }
  227.    }
  228.    else {
  229.       EscBuffer[EscNdx++] = ch;
  230.       if (--EscDownCounter == 0) {
  231.      switch (EscBuffer[0])
  232.         {
  233.         case '=':
  234.            if (EscAdvance == 0)
  235.           EscDownCounter = 2;
  236.            else
  237.           TermPutsCm( EscBuffer[1]-' ',EscBuffer[2]-' ' );
  238.            break;
  239.         case '(':
  240.            TermPutsmd();
  241.            break;
  242.         case ')':
  243.            TermPutsme();
  244.            break;
  245.         case 'B':                // don't know ??
  246.            if (EscAdvance == 0)
  247.           EscDownCounter = 1;
  248.            else
  249.           TermPutsmd();
  250.            break;
  251.         case 'C':                // don't know ??
  252.            if (EscAdvance == 0)
  253.           EscDownCounter = 1;
  254.            else
  255.           TermPutsme();
  256.            break;
  257.         case 'E':
  258.            TermPutsal();
  259.            break;
  260.         case 'R':
  261.            TermPutsdl();
  262.            break;
  263.         case 'T':
  264.            TermPutsce();
  265.            break;
  266.         default:
  267.            TermPuts( "<esc>" );
  268.            TermPutc( EscBuffer[0] );
  269.            break;
  270.         }
  271.      if (EscDownCounter)
  272.         ++EscAdvance;
  273.       }
  274.    }
  275. }   // EmuTvi920
  276.  
  277.  
  278.  
  279. static void DoConOut( unsigned char ch )
  280. {
  281.    switch (Terminal)
  282.       {
  283.       case none:
  284.      putchar( ch );
  285.      break;
  286.       case debug:
  287.      if (ch < ' ')
  288.         printf( "<%02x>",ch );
  289.      else
  290.         putchar( ch );
  291.      break;
  292.       case tvi920:
  293.      EmuTvi920( ch );
  294.      break;
  295.       default:
  296.      fprintf( stderr,"fatal:  seems, that terminal '%s' is not yet implemented\r\n",
  297.          (char *)opt_Term );
  298.      exit( 3 );
  299.       }
  300. }   // DoConOut
  301.  
  302.  
  303.  
  304. void Bios( REGS *preg )
  305. {
  306.    REGS r = *preg;
  307.  
  308. #ifdef DEBUG
  309.    if (opt_BsCalls)
  310.       RegisterDump( r,"BIOS call",0 );
  311. #endif
  312.  
  313.    switch (r.w.PC - BIOS_BEG) {
  314.       case 0x03:                                                // WBOOT
  315.          ExitCode = -10;
  316.          break;
  317.       case 0x06:                                                // CONST
  318.          r.b.A = 0x00;
  319.          if (KbdBuff >= 0)
  320.             r.b.A = 0xff;
  321.          else {
  322.             if ((KbdBuff = _read_kbd(0,0,0)) >= 0)
  323.                r.b.A = 0xff;
  324.          }
  325.      if (opt_OutBuf  &&  --OutBufDownCnt < 0) {
  326.         OutBufDownCnt = opt_OutBuf;
  327.         fflush( stdout );
  328.      }
  329.          break;
  330.       case 0x09:                                                // CONIN
  331.      if (opt_OutBuf)
  332.         fflush( stdout );
  333.          if (KbdBuff >= 0) {
  334.             r.b.A = KbdBuff;
  335.             KbdBuff = -1;
  336.          } else
  337.             r.b.A = _read_kbd(0,1,0);
  338.          break;
  339.       case 0x0c:                                                // CONOUT
  340.      DoConOut( r.b.C );
  341.          break;
  342.       default:
  343.          RegisterDump( r,"BIOS function not implemented",0 );
  344.          ExitCode = 3;
  345.          break;
  346.    }
  347.    *preg = r;
  348. }   // Bios
  349.  
  350.  
  351.  
  352. void BiosInit( void )
  353. {
  354.    int i;
  355.  
  356.    if (opt_Verbose)
  357.       fprintf( stderr,"BiosInit...\r\n" );
  358.  
  359.    if (opt_Verbose)
  360.       fprintf( stderr,"clearing memory\r\n" );
  361.    memset( Mem,0,sizeof(Mem) );
  362.  
  363.    if (opt_Verbose)
  364.       fprintf( stderr,"setting up BIOS jumps at 0x%x and 0x0000\r\n",BIOS_BEG );
  365.    for (i = 0;  i <=32;  i++) {
  366.       B(Mem+BIOS_BEG+3*i+0) = 0xc3;
  367.       W(Mem+BIOS_BEG+3*i+1) = BIOS_BEG + 3*i;
  368.    }
  369.    B(Mem+0) = 0xc3;
  370.    W(Mem+1) = BIOS_BEG+3;
  371.  
  372.    //
  373.    //
  374.    //  determine terminal type
  375.    //
  376.    if (opt_Term == ""  ||  opt_Term == "NONE")
  377.       Terminal = none;
  378.    else if (opt_Term == "920"  ||  opt_Term == "TVI920") {
  379.       struct termios ioflags;
  380.       tcgetattr( 0,&ioflags );
  381.       ioflags.c_cc[VINTR] = 0;
  382.       ioflags.c_lflag &= ~ISIG;
  383.       tcsetattr( 0,TCSANOW,&ioflags );
  384.       Terminal = tvi920;
  385.    }
  386.    else if (opt_Term == "DEBUG")
  387.       Terminal = debug;
  388.    else {
  389.       fprintf( stderr,"fatal:  terminal type '%s' not defined\r\n",(char *)opt_Term );
  390.       fprintf( stderr,"currently only 'tvi920'/'920', 'DEBUG', 'NONE' defined (sorry)\r\n" );
  391.       exit( 3 );
  392.    }
  393. }   // BiosInit
  394.  
  395.  
  396.  
  397. void BiosExit( void )
  398. {
  399.    ////   printf("stub BiosExit()\r\n");
  400.    TermCapExit();
  401. }   // BiosExit
  402.