/* $Id: platform.c,v 1.2 2002/03/03 21:01:57 richdawe Exp $ */

/*
 *  platform.c - Platform detection routines for zippo
 *  Copyright (C) 1999-2001 by Richard Dawe
 *      
 *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "common.h"

#include <string.h>

#ifdef __DJGPP__
/* Added for the os detection routines */
#include <dpmi.h>
#include <go32.h>
#include <dos.h>
#include <sys/movedata.h>
#endif /* __DJGPP__ */

/* libzippo includes */
#include <libzippo/util.h>

#include "platform.h"

/* -------------------
 * - detect_platform -
 * ------------------- */

/* let's attempt to determine the os zippo is running under.. */
/* NOTE -: This uses DJGPP specific routines...hence the #ifdef */

platform_t
detect_platform (void)
{
#ifdef __DJGPP__
  __dpmi_regs r;
  union REGS regs;
  char buf[16];
#endif /* __DJGPP__ */

  /* For non-DJGPP platforms, display a warning saying that zippo doesn't
   * support OS detection on this platform (e.g. Linux). */
#ifndef __DJGPP__
  warn("No support for OS detection on this platform");
  return(PLATFORM_NONE);
#endif /* __DJGPP__ */

#ifdef __DJGPP__
  /* Check which OS we are running under */
  r.x.ax = 0x1600; 
  __dpmi_int(0x2F, &r);
  if (   (r.h.al != 0)    && (r.h.al != 1)
      && (r.h.al != 0x80) && (r.h.al != 0xFF)) {
    /* Windows 3.1, '95, '98 or ME */
    if (r.h.al == 4) {
      if (r.h.ah < 10) 
	return PLATFORM_WIN95; /* Windoze 95 */
      else if (r.h.ah < 90)
	return PLATFORM_WIN98; /* Windoze 98 */
      else
	return PLATFORM_WINME; /* Windows ME */
    } else {
      return PLATFORM_WIN3; /* Windows 3.x */
    }
  } else {
    if (_get_dos_version(1) == 0x0532) {
      return PLATFORM_WINNT4;				    
    } else {	
      /*
       * Check for Linux DOSEMU using the method described in Ralph Brown's
       * Interrupt List:
       *
       * INT E6 - Linux DOSEMU - INSTALLATION CHECK
       * AH = 00h
       * Return: AX = AA55h if installed
       * BH = major version number
       * BL = minor version number
       * CX = patchlevel
       *
       * Notes: check for the BIOS date string "02/25/93" at
       * F000:FFF5 before calling this function. In addition,
       * the segment address of this vector should be F000h
       * (for existing versions of DOSemu, the vector is
       * F000h:0E60h
       */
      dosmemget(0xFFFF5, 10, buf); 
      buf[8] = 0;
      if (!strcmp(buf, "02/25/93")) {
	regs.x.ax = 0;
	int86(0xE6, &regs, &regs);
	if (regs.x.ax == 0xAA55) {
	  return PLATFORM_DOSEMU;
	}
      }
    }
  }
	
  /* Well I think it is now safe to assume that we are running under
   * Normal DOS */
  return PLATFORM_MSDOS;
#endif /* __DJGPP__ */
}

/* -------------------------
 * - detect_platform_class -
 * ------------------------- */

/* Detect a platform class, e.g. DOS, Win16, Win32, Linux. */

platform_class_t
detect_platform_class (void)
{
  platform_t detected_platform;

  detected_platform = detect_platform();

  switch(detected_platform) {
  case PLATFORM_MSDOS:
  case PLATFORM_DOSEMU:
    return(PLATFORM_CLASS_DOS);

  case PLATFORM_WIN3:
    return(PLATFORM_CLASS_WIN16);

  case PLATFORM_WIN95:
  case PLATFORM_WIN98:
  case PLATFORM_WINME:
  case PLATFORM_WINNT4:
  case PLATFORM_WIN2K:
  case PLATFORM_WINXP:
    return(PLATFORM_CLASS_WIN32);

  default:
  case PLATFORM_NONE:
    return(PLATFORM_CLASS_NONE);
  }
}
