paldos.cc

//*************************************************************************
//  MODULE : Pal - Program Abstraction Layer for the RCOS system          *
//  AUTHOR : Ron Chernich                                                 *
//  PURPOSE: Definition of a class to provide platform dependant services *
//           for timer interrupts, raw keyboard buffer access and low     *
//           level mouse events.                                          *
//  HISTORY:                                                              *
//   22-MAR-93  ISR made a friend to beat Borland compiler quirk          *
//   08-APR-93  Start/Stop added and GetTicks adjusted for 1mS (hah!)     *
//   14-MAY-93  Sentinal to prevent starting a stopped timer              *
//   29-OCT-93  Created to make "Timer" more platform independant         *
//   04-FEB-94  Timer class body moved here from "timer"                  *
//*************************************************************************

#include "pal.hh"


//////////////////////////////////////////////////////////////////////////
// Amazing! 3 DOS compilers all implement these the same way!
//
#if defined(MSC700) || defined(BC31) || defined(SC60)

  #include 

  #pragma check_stack (off)

  #ifdef BC20
  #define __MSC
  #endif

  /////////////
  // Raw key data waiting
  // RETURNS:  TRUE .. Yes, there is
  //          FALSE .. No, there 'aint
  //
  BOOL PalKeyReady (void)
  {
    #if defined(BC31)
	return (BOOL)(bioskey( 1 ));
    #else
      return (BOOL)(_bios_keybrd(_NKEYBRD_READY) != 0);
    #endif
  }

  ////////////
  // Get raw key data - caller must ensure there is something to get first!
  // RETURNS: lo byte = ASCII value; hi byte = keyboard scan code
  //
  UINT16 PalGetKey (void)
  {
    #if defined(BC31)
	return (UINT16)(bioskey(0));
    #else
	return (UINT16)_bios_keybrd(_NKEYBRD_READ);
    #endif
  }

  #pragma check_stack (on)

#endif


//////////////////////////////////////////////////////////////////////////
// Microsoft specific ways of doing the job
//
#ifdef MSC700

  #include 
  #include 
  #include 

  #define ASM   __asm

  //////////
  // get the address of the passed interrupt vector
  // RETURNS: address as a 32 bit value (CS:Offset)
  //
  UINT32 PalGetVec (UINT16 nVec)
  {
    void (__cdecl __interrupt __far *pvec)(void);
    pvec = _dos_getvect(nVec);
    return (UINT32)pvec;
  }

  //////////
  // Change the interrupt vector to that passed
  //
  void PalSetVec (UINT16 nVec, UINT32 uFp)
  {
    _dos_setvect(nVec, (void (__cdecl __interrupt __far*)(void))uFp);
  }

  ////////
  // Prepare the DOS clock for 1mS resolution
  //
  void PalInitClk (void)
  {
    return;
  }

  ////////
  // Restore the DOS clock to 10mS resolution
  //
  void PalResetClk (void)
  {
    return;
  }

  ///////////
  // Get system time since midnight in milliseconds
  //
  UINT32 PalGetTime (void)
  {
    struct _timeb tb;
    _ftime(&tb);
    return (UINT32)(tb.time * 1000) + (UINT32)tb.millitm;
  }

#endif


//////////////////////////////////////////////////////////////////////////
// The Borland way..
//
#ifdef BC31

  #include 

  #define ASM   asm     // changed to a common format for later re-use

  //////////
  // get the address of the passed interrupt vector
  // RETURNS: address as a 32 bit value (CS:Offset)
  //
  UINT32 PalGetVec (UINT16 nVec)
  {
    #ifndef BC31
	void interrupt (far *pvec)(...);
	pvec = _dos_getvect(nVec);
    #else
	void *pvec;
	pvec = getvect( nVec );
    #endif
    return (UINT32)pvec;
  }

  //////////
  // Change the interrupt vector to that passed
  //
  void PalSetVec (UINT16 nVec, UINT32 uFp)
  {
    setvect(nVec, (void interrupt (far*)(...))uFp);
  }

  ////////
  // Prepare the DOS clock for 1mS resolution
  //
  void PalInitClk (void)
  {
    return;
  }

  ////////
  // Restore the DOS clock to 10mS resolution
  //
  void PalResetClk (void)
  {
    return;
  }

  ///////////
  // Get system time since midnight in milliseconds
  //
  UINT32 PalGetTime (void)
  {
    #ifndef BC31
	struct dostime_t tb;
	_dos_gettime(&tb);
	return (UINT32)(tb.second * 1000) + (UINT32)tb.hsecond;
    #else
	struct time tb;
	gettime( &tb );
	return (UINT32)(tb.ti_sec*1000) + (UINT32)tb.ti_hund;
    #endif
  }

#endif


//////////////////////////////////////////////////////////////////////////
// And Symantic (why bother? Symantic has no DOS graphics, so we'll
// need to "borrow" them from Microsoft anyway!)
//
#ifdef SC60

  //////////
  // get the address of the passed interrupt vector
  // RETURNS: address as a 32 bit value (CS:Offset)
  //
  UINT32 PalGetVec (UINT16 nVec)
  {
    unsigned seg, ofs;
    int_getvector(nVec, &ofs, &seg);
    return (UINT32)seg << 16 + (UINT32)ofs;
  }

  //////////
  // Change the interrupt vector to that passed
  //
  void PalSetVec (UINT16 nVec, UINT32 uFn)
  {
    int_setvector(nVec, (unsigned)(uFn >> 16), (unsigned)(uFn & 0xffff));
  }

  ////////
  // Prepare the DOS clock for 1mS resolution
  //
  void PalInitClk (void)
  {
    return;
  }

  ////////
  // Restore the DOS clock to 10mS resolution
  //
  void PalResetClk (void)
  {
    return;
  }

  ///////////
  // Get system time since midnight in milliseconds.
  //
  UINT32 PalGetTime (void)
  {
    struct dostime_t tb;
    dos_gettime(&tb)
    return (UINT32)(tb.second * 1000) + (UINT32)tb.hsecond;
  }

#endif

//////////////////////////////////////////////////////////////////////////
// And now for the mouse (Microsoft and Borland are the same)..
//
#if defined(MSC700) || defined(BC31)

  //////////
  // These Globals are local to this module so that the mouse driver
  // invoked service routine can pass info to the Pal routine..
  //
  static UINT16 _x, _y, _event;

  //////////
  // proto for a local function..
  //
  void _loadds MouseTrap (void);

  /////////////
  // Determine if a driver is present by looking at the software interrupt
  // vector.  If it is null, or points to an IRET op-code, there's a good
  // chance of no mouse.  If we've got one we'll set up a call back to our
  // info gathering friend func and start monitoring for any Left Button
  // Down events..
  //
  BOOL PalMouseInit (void)
  {
    UINT32 uMp = PalGetVec(MM_Driver);
//    if ((void __far*)uMp /* && (*(char __far*)uMp && 0xff == 0xCF) */) {
    if ((void FAR *)uMp /* && (*(char __far*)uMp && 0xff == 0xCF) */) {
      union REGS regs;
      struct SREGS sregs;
      segread(&sregs);
      regs.x.ax = MM_SetISR;
      regs.x.bx = 0;
      regs.x.cx = MM_LBdown;
      regs.x.dx = (unsigned)((UINT32)MouseTrap & (UINT32)0xffff);
      sregs.es = (unsigned)((UINT32)MouseTrap >> 16 & (UINT32)0xffff);
      int86x(MM_Driver, ®s, ®s, &sregs);
      return TRUE;
    }
    return FALSE;
  }

  /////////////
  // restore default mouse operation
  //
  void PalMouseReset (void)
  {
    union REGS regs;
    regs.x.ax = MM_Reset;
    int86(MM_Driver, ®s, ®s);
  }

  ///////////////
  // Get the location of the last mouse event (stored by handler call-back)
  //
  BOOL PalMouseEvent (INT16 *px, INT16 *py)
  {
    BOOL bRes = (BOOL)(_event && MM_LBdown == MM_LBdown);
    *px = _x, *py = _y, _event = 0;
    return bRes;
  }

  ////////////
  // Turn on the mouse pointer (under DOS, this increments a driver
  // internal counter.. the pointer appears when it reaches zero)
  //
  void PalMousePointerOn (void)
  {
    union REGS regs;
    regs.x.ax = MM_Show;
    int86(MM_Driver, ®s, ®s);
  }

  //////////////
  // If x1 is less than zero (ie, it defaulted), unconditionally turn
  // off the pointer.  Otherwise, use "smart" hiding (if available).
  //
  void PalMousePointerOff (INT16 x1, INT16 y1, INT16 x2, INT16 y2)
  {
    union REGS regs;
    if (x1 < 0)
      regs.x.ax = MM_Hide;
    else {
      regs.x.ax = MM_Smart;
      regs.x.cx = x1, regs.x.dx = y1, regs.x.si = x2, regs.x.di = y2;
    }
    int86(MM_Driver, ®s, ®s);
  }

  ////////////////
  // User mouse subroutine called on events as specified by call to SetISR.
  // Now this is really crude.  We are looking for button down events only
  // and we will only store the most recent one in "local globals" where
  // they can be retreived by a call to .
  //
  // A future revision should at least buffer a few events and monitor
  // (initially) for button down.  When that occurs, If the click is inside
  // a control rect region, we should shift the graphic and change to
  // monitoring for move and release events.  If the pointer moves outside
  // the control region, we restore the graphic but resister "no click" -
  // a release inside the control is a real activation; *sigh* maybe later.
  //
  #pragma check_stack (off)
  void _loadds MouseTrap (void)
  {
    ASM {
      mov _event,bx     // the in-line assembler won't/can't
      mov _y,dx         // reference class members,
      mov _x,cx         // hence this kluge.
    }
  }
  #pragma check_stack (on)

#endif

//////////////////////////////////////////////////////////////////////////
// Symantic thoughtfully supplies low level mouse library functions,
// but no DOS graphics library fns - You figure it out, it's beyond me!
//
#ifdef SC60

  #include 


  /////////////
  // Protos for low level mouse services
  //
  BOOL PalMouseInit (void)
  {
    return (msm_init()) ? TRUE : FALSE;
  }

  /////////////
  // restore default mouse operation
  //
  void PalMouseReset (void)
  {
    msm_term();
  }

  ///////////////
  // Get the location of the last mouse left button down event
  //
  BOOL PalMouseEvent (INT16 *px, INT16 *py)
  {
    unsigned n = 0;
    msm_getpress(&n, px, py);
    return ((n) ? TRUE : FALSE);
  }

  ////////////
  // Turn on the mouse pointer (under DOS, this increments a driver
  // internal counter.. the pointer appears when it reaches zero)
  //
  void PalMousePointerOn (void)
  {
    msm_showcursor();
  }

  //////////////
  // If x1 is less than zero (ie, it defaulted), unconditionally turn
  // off the pointer.  Otherwise, use "smart" hiding (if available).
  //
  void PalMousePointerOff (INT16 x1 = -1, INT16 y1 = -1,
			   INT16 x2 = -1, INT16 y2 = -1)
  {
    if (x1 == -1)
      msm_hidecursor();
    else
      msm_condoff(x1, y1, x2, y2);
  }

#endif


/********************************** eof **********************************/