summaryrefslogtreecommitdiffstats
path: root/private/mvdm/softpc.new/host/src
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/softpc.new/host/src
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/mvdm/softpc.new/host/src')
-rw-r--r--private/mvdm/softpc.new/host/src/config.c1293
-rw-r--r--private/mvdm/softpc.new/host/src/copy_fnc.c195
-rw-r--r--private/mvdm/softpc.new/host/src/cpucstbs.c32
-rw-r--r--private/mvdm/softpc.new/host/src/fprt.c233
-rw-r--r--private/mvdm/softpc.new/host/src/makefile6
-rw-r--r--private/mvdm/softpc.new/host/src/makefile.inc6
-rw-r--r--private/mvdm/softpc.new/host/src/nt_aorc.c861
-rw-r--r--private/mvdm/softpc.new/host/src/nt_bop.c960
-rw-r--r--private/mvdm/softpc.new/host/src/nt_cga.c1193
-rw-r--r--private/mvdm/softpc.new/host/src/nt_com.c2206
-rw-r--r--private/mvdm/softpc.new/host/src/nt_cprgs.c2351
-rw-r--r--private/mvdm/softpc.new/host/src/nt_cpu.c344
-rw-r--r--private/mvdm/softpc.new/host/src/nt_det.c1611
-rw-r--r--private/mvdm/softpc.new/host/src/nt_ega.c2144
-rw-r--r--private/mvdm/softpc.new/host/src/nt_emm.c817
-rw-r--r--private/mvdm/softpc.new/host/src/nt_eoi.c545
-rw-r--r--private/mvdm/softpc.new/host/src/nt_error.c1190
-rw-r--r--private/mvdm/softpc.new/host/src/nt_ertbl.c24
-rw-r--r--private/mvdm/softpc.new/host/src/nt_event.c1918
-rw-r--r--private/mvdm/softpc.new/host/src/nt_fdisk.c760
-rw-r--r--private/mvdm/softpc.new/host/src/nt_fulsc.c2415
-rw-r--r--private/mvdm/softpc.new/host/src/nt_graph.c2314
-rw-r--r--private/mvdm/softpc.new/host/src/nt_hfx.c195
-rw-r--r--private/mvdm/softpc.new/host/src/nt_hosts.c343
-rw-r--r--private/mvdm/softpc.new/host/src/nt_hunt.c250
-rw-r--r--private/mvdm/softpc.new/host/src/nt_input.c128
-rw-r--r--private/mvdm/softpc.new/host/src/nt_inthk.c249
-rw-r--r--private/mvdm/softpc.new/host/src/nt_keycd.c605
-rw-r--r--private/mvdm/softpc.new/host/src/nt_lpt.c698
-rw-r--r--private/mvdm/softpc.new/host/src/nt_mem.c1456
-rw-r--r--private/mvdm/softpc.new/host/src/nt_mess.c27
-rw-r--r--private/mvdm/softpc.new/host/src/nt_mouse.c2630
-rw-r--r--private/mvdm/softpc.new/host/src/nt_msscs.c1416
-rw-r--r--private/mvdm/softpc.new/host/src/nt_munge.c556
-rw-r--r--private/mvdm/softpc.new/host/src/nt_nls.c128
-rw-r--r--private/mvdm/softpc.new/host/src/nt_ntfun.c592
-rw-r--r--private/mvdm/softpc.new/host/src/nt_pif.c442
-rw-r--r--private/mvdm/softpc.new/host/src/nt_reset.c422
-rw-r--r--private/mvdm/softpc.new/host/src/nt_rez.c187
-rw-r--r--private/mvdm/softpc.new/host/src/nt_rflop.c2036
-rw-r--r--private/mvdm/softpc.new/host/src/nt_sas.c148
-rw-r--r--private/mvdm/softpc.new/host/src/nt_sec.c158
-rw-r--r--private/mvdm/softpc.new/host/src/nt_smenu.c87
-rw-r--r--private/mvdm/softpc.new/host/src/nt_sound.c420
-rw-r--r--private/mvdm/softpc.new/host/src/nt_term.c81
-rw-r--r--private/mvdm/softpc.new/host/src/nt_thred.c162
-rw-r--r--private/mvdm/softpc.new/host/src/nt_timer.c982
-rw-r--r--private/mvdm/softpc.new/host/src/nt_umb.c1119
-rw-r--r--private/mvdm/softpc.new/host/src/nt_unix.c459
-rw-r--r--private/mvdm/softpc.new/host/src/nt_vdd.c821
-rw-r--r--private/mvdm/softpc.new/host/src/nt_vflop.c604
-rw-r--r--private/mvdm/softpc.new/host/src/nt_vga.c2188
-rw-r--r--private/mvdm/softpc.new/host/src/nt_wcom.c438
-rw-r--r--private/mvdm/softpc.new/host/src/nt_yoda.c1200
-rw-r--r--private/mvdm/softpc.new/host/src/sim32.c462
-rw-r--r--private/mvdm/softpc.new/host/src/sources111
-rw-r--r--private/mvdm/softpc.new/host/src/stf_conf.c927
-rw-r--r--private/mvdm/softpc.new/host/src/stubs.c614
-rw-r--r--private/mvdm/softpc.new/host/src/x86_emm.c948
59 files changed, 47707 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/host/src/config.c b/private/mvdm/softpc.new/host/src/config.c
new file mode 100644
index 000000000..1115980b6
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/config.c
@@ -0,0 +1,1293 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+
+#include "windows.h"
+#include "host_def.h"
+#include "insignia.h"
+/*
+ * config.c - config for the NT port.
+ *
+ * A happy chainsaw production by Ade Brownlow
+ *
+ * This file is a hacked down (seriously) version of the 3.0 config.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vdmapi.h"
+
+#include "xt.h"
+#include "error.h"
+#include "config.h"
+#include "sas.h"
+
+#include "spcfile.h"
+#include "umb.h"
+
+#include "nt_pif.h" /* PIF file interrogation data structure types */
+#include "trace.h"
+
+#include "conapi.h"
+#include "nt_graph.h"
+#include "gfi.h"
+#include "floppy.h"
+
+#include "ntddvdeo.h"
+#include "host_rrr.h"
+#include "nt_fulsc.h"
+#include "nt_uis.h"
+#include "nt_event.h"
+#include "nt_reset.h"
+#include "nt_fdisk.h"
+
+#ifdef LIM
+#include "emm.h"
+#endif
+
+#include "oemuni.h"
+
+#include "pmvdm.h"
+
+#ifdef HUNTER
+
+#include "ckmalloc.h"
+#include "debug.h"
+#endif //HUNTER
+
+
+/*================================================================
+External references
+================================================================*/
+IMPORT SHORT gfi_floppy_active (UTINY hostID, BOOL active, CHAR *err);
+IMPORT ULONG xmsMemorySize;
+
+#ifdef HUNTER
+/*
+ * ===========================================================================
+ * LOCAL DATA STRUCTURES
+ * ===========================================================================
+ */
+
+typedef struct {
+ ConfigValues *data;
+ OptionDescription *def;
+} ConfTabEntry;
+
+/*
+ * ===========================================================================
+ * LOCAL FUNCTIONS
+ * ===========================================================================
+ */
+VOID build_data_table(VOID);
+VOID read_trapper_variables(VOID);
+VOID convert_arg(CHAR *, OptionDescription *, ConfigValues *);
+SHORT check_value(OptionDescription *, ConfigValues *);
+
+/*
+ * ===========================================================================
+ * IMPORTED DATA STRUCTURES
+ * ===========================================================================
+ */
+
+IMPORT OptionDescription host_defs[]; /* From hunt_conf.c */
+
+/*
+ * ===========================================================================
+ * LOCAL DATA
+ * ===========================================================================
+ */
+
+/* Dummy `common_defs' to pass to `host_config_init' */
+LOCAL OptionDescription common_defs[] =
+{
+ { NULL, NULL, NULL, NULL, NULL, -1, C_RECORD_DELETE }
+};
+LOCAL ConfTabEntry *conf_tab = NULL;
+
+#endif /* HUNTER */
+
+
+PIF_DATA pfdata; /* data structure for holding all the relavent information
+ from the PIF file interrogated */
+/* must be unsigned because they can be over 32768 */
+USHORT PIFExtendMemSize = 0; /* save value of extend mem from PIF file */
+USHORT PIFEMSMemSize = 0; /* save value of LIM mem from PIF file */
+ULONG emsMemorySize;
+
+#ifdef LIM
+LIM_CONFIG_DATA lim_config_data = {FALSE, 0, 0, 640 * 1024 / 16, FALSE};
+#endif
+
+APPKEY Shortkey; /* PIF Shortcut key settings */
+BYTE ReserveKey; /* PIF Reserved key setting */
+int nShortKeys;
+/*
+ * ===========================================================================
+ * GLOBAL DATA
+ * ===========================================================================
+ */
+GLOBAL SHORT Npx_enabled = TRUE; //For Jazz CPU support
+GLOBAL BOOL IdleDisabledFromPIF = FALSE;//Flag showing idledetection wishes
+GLOBAL UTINY number_of_floppy = 0; // number of floppy drives
+
+
+/*================================================================
+Local defines
+================================================================*/
+/* command definitions for read_profile_int */
+
+#define PROFILE_LPT_AUTOCLOSE_DELAY 0
+#define PROFILE_COM_AUTOCLOSE_DELAY 1
+#define PROFILE_LPT_AUTOFLUSH_DELAY 2
+#define PROFILE_COM_SYNCWRITE 3
+#define PROFILE_COM_TXBUFFER_SIZE 4
+#define PROFILE_MAX_INDEX PROFILE_COM_TXBUFFER_SIZE + 1
+
+#define EMBITSET 0x4
+
+#define ONEMEG 0x100000L
+#define ONEKB 0x400L
+
+#define RESERVED_LENGTH 129
+#define PMVDM_NTVDM_NAME "ntvdm."
+#define PMVDM_NTVDM_NAME_LENGTH 6 /* doesn't include NULL */
+
+#define XMS_DEFAULT_MEMORY_SIZE 15*1024
+#define EMS_DEFAULT_MEMORY_SIZE 4*1024
+#define DPMI_DEFAULT_MEMORY_SIZE_FOR_DOS 8*1024
+#define DPMI_DEFAULT_MEMORY_SIZE_FOR_WOW 16*1024
+/* maximum ems memory size */
+#define EMS_MAX_MEMORY_SIZE 32 * 1024 /* from EMM 4.0 specification */
+
+int read_profile_int(int index);
+ULONG GetVDMSize(BOOL);
+ULONG GetDefaultVDMSize(BOOL);
+void InitNtCpuInfo(void);
+
+/*
+ * ===========================================================================
+ * GLOBAL FUNCTIONS
+ * ===========================================================================
+ */
+
+VOID host_fdisk_active(UTINY hostID, BOOL active, CHAR *errString);
+VOID host_fdisk_valid
+ (UTINY hostID, ConfigValues *vals, NameTable *table, CHAR *errStr);
+
+/* This routine is called when the DOS VDM runs its first binary. The
+ parameter points to full path name of the dos app. This routine does'nt
+ get called on subsequent dos apps in the same console window. It is not
+ called on wow apps.
+ Read PIF file and update VDM and console state from settings.
+*/
+
+VOID process_pif_exe (char *PifName)
+{
+#ifdef X86GFX
+ COORD scrSize;
+ DWORD flags;
+#endif
+
+ GetPIFData(&pfdata, PifName);
+
+ // get app specific LIM memory size
+ PIFEMSMemSize = pfdata.emsdes;
+
+ // get app specific Extended memory size
+ PIFExtendMemSize = pfdata.xmsdes;
+
+ // store pif setting for AllowCloseOnExit
+ if (pfdata.menuclose == 1) {
+ CntrlHandlerState |= CNTRL_PIFALLOWCLOSE;
+ }
+
+ /* set app reserved key only if it has a new console;
+ set app short cut keys only if it has a new console
+ and there are not short cut keys come along with CreateProcess
+ Reserved key must be set before set console display mode
+ */
+ nShortKeys = 0;
+ ReserveKey = 0;
+ if (DosSessionId || (pfdata.AppHasPIFFile && pfdata.SubSysId == SUBSYS_DOS))
+ {
+ ReserveKey = pfdata.reskey;
+ if (!pfdata.IgnoreShortKeyInPIF) {
+ Shortkey.Modifier = pfdata.ShortMod;
+ Shortkey.ScanCode = pfdata.ShortScan;
+ nShortKeys = (Shortkey.Modifier || Shortkey.ScanCode) ? 1 : 0;
+ }
+ if (ReserveKey || nShortKeys)
+ SetConsoleKeyShortcuts(TRUE,
+ ReserveKey,
+ (nShortKeys) ? &Shortkey : NULL,
+ nShortKeys
+ );
+ }
+
+ if (pfdata.idledetect == 1)
+ IdleDisabledFromPIF = FALSE;
+ else
+ IdleDisabledFromPIF = TRUE;
+#ifdef X86GFX
+ if (DosSessionId) /* Only check screen state if we are in a NEW_CONSOLE */
+ {
+ /* Check to see if we are currently running windowed or full-screen. */
+ if (!GetConsoleDisplayMode(&flags))
+ ErrorExit();
+
+ /* If PIF is telling us to switch to a different state, do so. */
+ if (flags & CONSOLE_FULLSCREEN_HARDWARE)
+ {
+ if (pfdata.fullorwin == PF_WINDOWED)
+ {
+#ifndef PROD
+ fprintf(trace_file, "Going windowed...\n");
+#endif /* PROD */
+ if (!SetConsoleDisplayMode(sc.OutputHandle,
+ CONSOLE_WINDOWED_MODE,
+ &scrSize))
+ ErrorExit();
+ }
+ }
+ else /* WINDOWED */
+ {
+ if (pfdata.fullorwin == PF_FULLSCREEN)
+ {
+#ifndef PROD
+ fprintf(trace_file, "Going fullscreen...\n");
+#endif /* PROD */
+ if (!SetConsoleDisplayMode(sc.OutputHandle,
+ CONSOLE_FULLSCREEN_MODE,
+ &scrSize))
+ {
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
+ RcErrorDialogBox(ED_INITFSCREEN, NULL, NULL);
+ }
+ else {
+ ErrorExit();
+ }
+ }
+ }
+ }
+ }
+#endif /* X86GFX */
+
+}
+
+/* Turn off the PIF reserved & shortcut keys - on block and quit */
+void DisablePIFKeySetup(void)
+{
+ /* only doing this if the application was launched from a new console */
+ if (ReserveKey || nShortKeys)
+ SetConsoleKeyShortcuts(TRUE, 0, (APPKEY *)0, 0);
+}
+
+/* Turn on the PIF reserved & shortcut keys - on resume */
+void EnablePIFKeySetup(void)
+{
+ /* only doing this if the app has a new console.*/
+ if (ReserveKey || nShortKeys)
+ SetConsoleKeyShortcuts(TRUE,
+ ReserveKey,
+ (nShortKeys) ? &Shortkey : NULL,
+ nShortKeys
+ );
+
+}
+
+
+GLOBAL VOID config( VOID )
+{
+ VDMINFO GetPIF;
+ char UniqueTitle[64];
+ char Title[MAX_PATH];
+ char PifName[MAX_PATH + 1];
+ char CurDir[MAX_PATH + 1];
+ char Reserved[RESERVED_LENGTH];
+ char achRoot[] = "=?:";
+ char ch, *pch, *pch1;
+ UTINY hostID;
+ int i;
+ DWORD dw;
+ char achPIF[] = ".pif";
+ ULONG dpmiMemorySize, vdmMemorySize;
+
+#ifdef HUNTER
+
+ /* Build table in which to store config data. */
+ build_data_table();
+
+ /* Initialise optionName fields of host_defs table. */
+ host_config_init(common_defs);
+
+ /* Read in trapper variables from environment. */
+ read_trapper_variables();
+
+#endif /* HUNTER */
+
+ /*
+ * Set the window title to a unique string, to get
+ * the Consoles Window Handle, we will retrieve
+ * the window handle later when user server has
+ * had a chance to think about it.
+ */
+ Title[0] = '\0';
+ if (!VDMForWOW) {
+ if (!DosSessionId && !GetConsoleTitle(Title, MAX_PATH))
+ Title[0] = '\0';
+ sprintf(UniqueTitle, "ntvdm-%lx.%lx.%lx",
+ GetCurrentProcessId(), GetCurrentThreadId(),
+ NtCurrentPeb()->ProcessParameters->ConsoleHandle);
+ SetConsoleTitle(UniqueTitle);
+ }
+ else {
+ strcpy(Title, "Hidden Console of WOW VDM");
+ }
+
+
+ /*
+ * Register with srvvdm
+ * Get PifName, ExecName
+ */
+ GetPIF.PifFile = PifName;
+ GetPIF.PifLen = MAX_PATH;
+ GetPIF.EnviornmentSize = 0;
+ GetPIF.Enviornment = NULL;
+
+ if (fSeparateWow) {
+ GetPIF.VDMState = ASKING_FOR_PIF | ASKING_FOR_SEPWOW_BINARY;
+ }
+ else if (VDMForWOW) {
+ GetPIF.VDMState = ASKING_FOR_PIF | ASKING_FOR_WOW_BINARY;
+ }
+ else {
+ GetPIF.VDMState = ASKING_FOR_PIF | ASKING_FOR_DOS_BINARY;
+ }
+
+ GetPIF.CmdLine = NULL;
+ GetPIF.CmdSize = 0;
+ GetPIF.AppName = NULL;
+ GetPIF.AppLen = 0;
+ GetPIF.iTask = DosSessionId;
+ GetPIF.Desktop = NULL;
+ GetPIF.DesktopLen = 0;
+ GetPIF.ReservedLen = (VDMForWOW) ? 0 : RESERVED_LENGTH;
+ GetPIF.Reserved = (VDMForWOW) ? NULL : Reserved;
+ GetPIF.CurDirectoryLen = MAX_PATH + 1;
+ GetPIF.CurDirectory = CurDir;
+
+ // ask for title if we don't already have one
+ if (!*Title) {
+ GetPIF.Title = Title;
+ GetPIF.TitleLen = MAX_PATH;
+ }
+ else {
+ GetPIF.Title = NULL;
+ GetPIF.TitleLen = 0;
+ }
+
+ PifName[0] = '\0';
+ pfdata.IgnoreTitleInPIF = 0;
+ pfdata.IgnoreStartDirInPIF = 0;
+ pfdata.IgnoreShortKeyInPIF = 0;
+ if (GetNextVDMCommand(&GetPIF)) {
+ /* parsing the reserve field to decide if
+ we should take StartDir, Title and hotkey from
+ pif file. See windows\inc\pmvdm.h for the detail
+ */
+
+ Reserved[GetPIF.ReservedLen] = '\0';
+ if (!VDMForWOW && GetPIF.ReservedLen &&
+ (pch = strstr(Reserved, PMVDM_NTVDM_NAME)) != NULL)
+ {
+ pch += PMVDM_NTVDM_NAME_LENGTH;
+ pch1 = pch;
+ dw = 0;
+ while(*pch >= '0' && *pch <= '9')
+ pch++;
+ if (pch1 != pch) {
+ ch = *pch;
+ *pch = '\0';
+ dw = (DWORD) strtol(pch1, (char **)NULL, 10);
+ *pch = ch;
+ if (dw & PROPERTY_HAS_CURDIR)
+ pfdata.IgnoreStartDirInPIF = 1;
+ if (dw & PROPERTY_HAS_HOTKEY)
+ pfdata.IgnoreShortKeyInPIF = 1;
+ if (dw & PROPERTY_HAS_TITLE)
+ pfdata.IgnoreTitleInPIF = 1;
+ }
+ }
+ if (GetPIF.CurDirectoryLen) {
+ achRoot[1] = CurDir[0];
+
+ /* these needs to be ANSI calls not OEM as server passes
+ the informatio in ANSI*/
+
+ SetEnvironmentVariable(achRoot, CurDir);
+ SetCurrentDirectory(CurDir);
+
+ }
+ }
+
+
+ pfdata.IgnoreCmdLineInPIF = 0;
+ pfdata.IgnoreConfigAutoexec = 0;
+ pfdata.AppHasPIFFile = PifName[0] ? 1 : 0;
+
+ if(VDMForWOW){
+ DosSessionId = 0; // Wow has hidden console !
+ pfdata.IgnoreCmdLineInPIF =
+ pfdata.IgnoreTitleInPIF =
+ pfdata.IgnoreStartDirInPIF = 1;
+ pfdata.IgnoreShortKeyInPIF = 1;
+ }
+
+ process_pif_exe(PifName);
+
+ sas_term ();
+
+ //
+ // Calculate how big xms and ems will be.
+ // XMS and EMS memory sizes are either taken from a PIF file, or
+ // supplied from default values.
+ //
+
+ if (VDMForWOW) {
+
+ //
+ // For WOW, we don't need any EMS, and we just need enough
+ // XMS to satisfy win16 apps looking at the real machine size
+ //
+ emsMemorySize = 0;
+ xmsMemorySize = 8192;
+ dpmiMemorySize = DPMI_DEFAULT_MEMORY_SIZE_FOR_WOW;
+ } else {
+
+ emsMemorySize = PIFEMSMemSize == (USHORT)(-1)
+ ? EMS_DEFAULT_MEMORY_SIZE
+ : PIFEMSMemSize;
+
+ /* maximum size is 63MB */
+ xmsMemorySize = PIFExtendMemSize == (USHORT)(-1)
+ ? XMS_DEFAULT_MEMORY_SIZE
+ : PIFExtendMemSize;
+
+ /* put a upper limit on ems memory size based on EMM 4.0 spec */
+ if (emsMemorySize > EMS_MAX_MEMORY_SIZE)
+ emsMemorySize = EMS_MAX_MEMORY_SIZE;
+
+ // Force at least 1 megabyte xms to keep himem and dosx working.
+ if (xmsMemorySize < 1024) {
+ xmsMemorySize = 1024;
+ }
+ dpmiMemorySize = DPMI_DEFAULT_MEMORY_SIZE_FOR_DOS;
+ }
+
+#ifdef LIM
+ /* !!!! THIS MUST BE DONE BEFORE CALLING SAS_INIT !!!!!! */
+ if(!VDMForWOW && config_inquire(C_LIM_SIZE, NULL) &&
+ init_lim_configuration_data(&lim_config_data))
+ lim_config_data.initialized = TRUE;
+
+#endif
+
+ //
+ // Add everything up to decide how much physically installed memory
+ // the virtual machine needs. On RISC platforms, we may create a
+ // larger machine than xms or ems would call for to provide for
+ // dpmi memory. We get this size from the registry.
+ //
+
+#ifdef i386
+ // adding 1024 below is for conventional memory
+ vdmMemorySize = xmsMemorySize + emsMemorySize + 1024;
+#else
+ vdmMemorySize = GetVDMSize(VDMForWOW);
+
+ // Extend the vdm size if the user asks for it through a .PIF.
+ // Also make sure we have at least appropriate size of dpmi
+ // memory.
+ //
+ if ((xmsMemorySize + emsMemorySize + 1024 + dpmiMemorySize) >
+ vdmMemorySize)
+ {
+ vdmMemorySize = xmsMemorySize + emsMemorySize + 1024 +
+ dpmiMemorySize;
+ }
+#endif
+
+#ifndef PROD
+ dpmiMemorySize = vdmMemorySize - (xmsMemorySize + emsMemorySize + 1024);
+
+ printf("NTVDM: %dK Memory: %dK XMS, %dK EMS, %dK DPMI\n",
+ vdmMemorySize, xmsMemorySize, emsMemorySize, dpmiMemorySize);
+#endif
+
+ sas_init(vdmMemorySize*ONEKB);
+
+
+#ifdef CPU_40_STYLE
+
+ /* sas_init has initialised Gdp, so now we can set up the pointers */
+ /* to the Gdp variables that hold register values. This is to */
+ /* allow NTSD debugger extensions to display those values. */
+ InitNtCpuInfo();
+
+#endif
+
+
+#ifdef X86GFX
+ GetROMsMapped(); /* before anyone else can toy with memory */
+
+ locateNativeBIOSfonts(); /* get fonts from page 0 */
+#endif
+
+ // Now see if we can get the console window handle
+ if (!VDMForWOW) {
+ i = 6;
+ do {
+ hWndConsole = FindWindow("ConsoleWindowClass", UniqueTitle);
+ if (!hWndConsole && i)
+ Sleep(10);
+ } while (!hWndConsole && i--);
+ if (!hWndConsole) {
+ hWndConsole = HWND_DESKTOP;
+#ifndef PROD
+ printf("NTVDM: using HWND_DESKTOP\n");
+#endif
+ }
+ }
+
+ // set the initial console title
+ if (*Title)
+ SetConsoleTitle(Title);
+
+
+
+// Create UMB list (both MIPS and x86) -- williamh
+ InitUMBList();
+//
+ host_runtime_init(); /* initialise the runtime system */
+
+
+ /* Do not attempt to initialise printer system here */
+// activate(open) floppy drives if there are any
+ number_of_floppy = 0;
+ for (i = 0, hostID = C_FLOPPY_A_DEVICE; i < MAX_FLOPPY; i++, hostID++)
+ if ((gfi_floppy_active(hostID, 1, NULL)) == C_CONFIG_OP_OK)
+ number_of_floppy++;
+}
+
+GLOBAL VOID *
+config_inquire(UTINY hostID, ConfigValues *values)
+{
+ /* Must be a static because returned to called */
+ // BUGBUG should be change (caller provides buffer!!!)
+ static ConfigValues tmp_vals;
+
+ if(!values) values = &tmp_vals;
+
+ /*:::::::::::::::::::::::::::::::::::::: Hardwire the config stuff */
+
+ switch (hostID)
+ {
+ case C_HARD_DISK1_NAME:
+ //
+ // this dubious practice will satisfy the disk
+ // bios to exist quietly enough for initialisation
+ // after which, DOS emulation should ensure no more
+ // disk bios calls are made.
+ //
+ host_using_fdisk(FALSE); // tell fdisk it's ok to fail
+ strcpy (values->string, "?");
+ return ((VOID *) values->string);
+
+
+ case C_HARD_DISK2_NAME:
+ strcpy (values->string, "");
+ {
+ char tmp[100];
+ host_fdisk_valid (hostID, values, NULL, tmp);
+ host_fdisk_change (hostID, TRUE);
+ host_fdisk_active (hostID, TRUE, tmp);
+ }
+
+ return ((VOID *) values->string);
+
+
+ case C_GFX_ADAPTER:
+ values->index = VGA;
+ return ((VOID *)VGA);
+
+ case C_WIN_SIZE:
+ values->index = 2; /* 2, 3 or 4. */
+ return ((VOID *) values->index);
+
+ case C_EXTENDED_MEM_SIZE:
+ values->index = (SHORT)(xmsMemorySize/1024);
+ return ((VOID *)values->index);
+
+ case C_LIM_SIZE:
+ values->index = (SHORT)(emsMemorySize/1024);
+ return ((VOID *)values->index);
+
+ case C_MEM_LIMIT:
+ values->index = 640;
+ return ((VOID *)values->index);
+
+ case C_COM1_NAME:
+ strcpy (values->string, "COM1");
+ values->index = (short)read_profile_int(PROFILE_COM_AUTOCLOSE_DELAY);
+ return ((VOID *) values->string);
+
+ case C_COM2_NAME:
+ strcpy (values->string, "COM2");
+ values->index = (short)read_profile_int(PROFILE_COM_AUTOCLOSE_DELAY);
+ return ((VOID *) values->string);
+
+ case C_COM3_NAME:
+ strcpy (values->string, "COM3");
+ values->index = (short)read_profile_int(PROFILE_COM_AUTOCLOSE_DELAY);
+ return ((VOID *) values->string);
+
+ case C_COM4_NAME:
+ strcpy (values->string, "COM4");
+ values->index = (short)read_profile_int(PROFILE_COM_AUTOCLOSE_DELAY);
+ return ((VOID *) values->string);
+
+ case C_LPT1_NAME:
+ strcpy (values->string, "LPT1");
+ values->index = (short)read_profile_int(PROFILE_LPT_AUTOCLOSE_DELAY);
+ return ((VOID *) values->string);
+
+ case C_LPT2_NAME:
+ strcpy (values->string, "LPT2");
+ values->index = (short)read_profile_int(PROFILE_LPT_AUTOCLOSE_DELAY);
+ return ((VOID *) values->string);
+
+ case C_LPT3_NAME:
+ strcpy (values->string, "LPT3");
+ values->index = (short)read_profile_int(PROFILE_LPT_AUTOCLOSE_DELAY);
+ return ((VOID *) values->string);
+
+
+/* Auto flush closes the port after 'n' seconds of inactivaty */
+
+ case C_AUTOFLUSH:
+ values->index = TRUE;
+ return ((VOID *)values->index);
+
+ case C_AUTOFLUSH_DELAY:
+ values->index = read_profile_int(PROFILE_LPT_AUTOFLUSH_DELAY); //Delay in secs
+ return((VOID *)values->index);
+
+//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+
+
+ case C_FSA_DIRECTORY:
+ strcpy (values->string, "\\");
+ return ((VOID *) values->string);
+
+ case C_VDMLPT1_NAME:
+ strcpy(values->string, "\\\\.\\$VDMLPT1");
+ return ((VOID *)values->string);
+ case C_VDMLPT2_NAME:
+ strcpy(values->string, "\\\\.\\$VDMLPT2");
+ return ((VOID *)values->string);
+ case C_VDMLPT3_NAME:
+ strcpy(values->string, "\\\\.\\$VDMLPT3");
+ return ((VOID *)values->string);
+
+
+#ifdef HUNTER
+
+ case C_HU_FILENAME:
+ case C_HU_MODE:
+ case C_HU_BIOS:
+ case C_HU_REPORT:
+ case C_HU_SDTYPE:
+ case C_HU_CHKMODE:
+ case C_HU_CHATTR:
+ case C_HU_SETTLNO:
+ case C_HU_FUDGENO:
+ case C_HU_DELAY:
+ case C_HU_GFXERR:
+ case C_HU_TS:
+ case C_HU_NUM:
+ switch (conf_tab[hostID].def->flags & C_TYPE_MASK)
+ {
+ case C_STRING_RECORD:
+ strcpy(values->string,
+ conf_tab[hostID].data->string);
+ return ((VOID *) values->string);
+ case C_NAME_RECORD:
+ case C_NUMBER_RECORD:
+ values->index = conf_tab[hostID].data->index;
+ return ((VOID *) values->index);
+ default:
+ break;
+ }
+ break;
+
+#endif /* HUNTER */
+
+ case C_COM_SYNCWRITE:
+ values->index = (short)read_profile_int(PROFILE_COM_SYNCWRITE);
+ return ((VOID *)values->index);
+
+ case C_COM_TXBUFFER_SIZE:
+ values->index = (short)read_profile_int(PROFILE_COM_TXBUFFER_SIZE);
+ return ((VOID *)values->index);
+
+ default: /* ie everything else */
+ /* fail */
+ break;
+ }
+ /* setup dummy values to stop loud explosions */
+ strcpy (values->string, "");
+
+ return ((VOID *) values->string);
+
+}
+
+GLOBAL VOID config_set_active(UTINY hostID, BOOL state)
+{
+ UNREFERENCED_FORMAL_PARAMETER(hostID);
+ UNREFERENCED_FORMAL_PARAMETER(state);
+ /* do nothing */
+}
+
+GLOBAL CHAR *convert_to_external(UTINY hostID)
+{
+ UNREFERENCED_FORMAL_PARAMETER(hostID);
+ return (NULL);
+}
+
+GLOBAL CHAR *
+find_optionname(UTINY hostID)
+{
+
+ UNREFERENCED_FORMAL_PARAMETER(hostID);
+ return (NULL);
+}
+
+GLOBAL BOOL
+config_get_active(UTINY hostID)
+{
+
+
+ UNREFERENCED_FORMAL_PARAMETER(hostID);
+ /* It worked whatever it was supposed to do */
+ return (TRUE);
+}
+
+GLOBAL VOID
+config_activate(UTINY hostID, BOOL reqState)
+{
+
+ UNREFERENCED_FORMAL_PARAMETER(hostID);
+ UNREFERENCED_FORMAL_PARAMETER(reqState);
+
+ /* do bugger all */
+}
+
+GLOBAL char * host_expand_environment_vars IFN1(const char *, string)
+{
+
+ /* we're not going to use the environment for lookups */
+ return ((char *)string);
+}
+
+/********************************************************/
+/* host runtime stuff */
+struct
+{
+ short mouse_attached;
+ short config_verbose;
+ short npx_enabled;
+ short sound_on;
+} runtime_status = {
+ FALSE, FALSE, TRUE, TRUE};
+
+void host_runtime_init()
+{
+#ifdef MONITOR
+ CONTEXT txt;
+
+ // get Floating point info for system.
+ txt.ContextFlags = CONTEXT_FLOATING_POINT;
+ if (! GetThreadContext(GetCurrentThread(), &txt) )
+ {
+ runtime_status.npx_enabled = FALSE; //dont know for sure so be safe
+ }
+ else
+ {
+#if 0 /* if the correct fix ever is made... */
+ if (txt.FloatSave.Cr0NpxState & EMBITSET)
+ runtime_status.npx_enabled = FALSE; //EM only on if no NPX
+ else
+ runtime_status.npx_enabled = TRUE; //NPX present.
+#endif
+
+ // If no coprocessor, the CONTEXT_F_P bit will have been cleared
+ if ((txt.ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
+ runtime_status.npx_enabled = TRUE; //EM only on if no NPX
+ else
+ runtime_status.npx_enabled = FALSE;
+ }
+#else
+ runtime_status.npx_enabled = TRUE;
+#endif
+}
+
+short host_runtime_inquire IFN1(UTINY, what)
+{
+ switch (what)
+ {
+ case C_MOUSE_ATTACHED:
+ return (runtime_status.mouse_attached);
+ case C_NPX_ENABLED:
+ return (runtime_status.npx_enabled);
+ case C_SOUND_ON:
+ return (runtime_status.sound_on);
+ default:
+#ifndef PROD
+ fprintf (trace_file,"host_runtime_inquire : Unknown option %d\n",what);
+#endif
+ ;
+ }
+}
+
+void host_runtime_set IFN2(UTINY, what, SHORT, val)
+{
+ switch (what)
+ {
+ case C_MOUSE_ATTACHED:
+ runtime_status.mouse_attached = val;
+ break;
+ case C_NPX_ENABLED:
+ runtime_status.npx_enabled = val;
+ break;
+ case C_SOUND_ON:
+ runtime_status.sound_on = val;
+ break;
+ default:
+#ifndef PROD
+ fprintf (trace_file,"host_runtime_set : Unknown option %d\n",what);
+#endif
+ ;
+ }
+}
+
+
+
+#ifdef HUNTER
+
+/*
+ * ==========================================================================
+ * Function: translate_to_string.
+ *
+ * Taken from `conf_util.c' which we don't use. Takes a SHORT and returns
+ * the corresponding string in the `NameTable'.
+ * ==========================================================================
+ */
+GLOBAL CHAR *
+translate_to_string(SHORT value, NameTable table[])
+{
+ FAST NameTable *nameTabP;
+
+ for (nameTabP = table; nameTabP->string; nameTabP++)
+ if (nameTabP->value == value)
+ break;
+
+ return nameTabP->string;
+}
+
+/*
+ * ==========================================================================
+ * Function: translate_to_value.
+ *
+ * Taken from `conf_util.c' which we don't use. Takes a string and returns
+ * the corresponding SHORT in the `NameTable'.
+ * ==========================================================================
+ */
+GLOBAL SHORT
+translate_to_value(CHAR *string, NameTable table[])
+{
+ FAST NameTable *nameTabP;
+
+ for (nameTabP = table; nameTabP->string; nameTabP++)
+ if(!strcmp(string, nameTabP->string))
+ break;
+
+ return (!nameTabP->string)? C_CONFIG_NOT_VALID : nameTabP->value;
+}
+
+/*
+ * ==========================================================================
+ * Function: validate_item.
+ *
+ * Taken from `conf_def.c' which we don't use. Needed because `hunt_conf.c'
+ * uses it as the validation routine for several `config' variables (see
+ * `host_defs' table in `hunt_conf.c').
+ * ==========================================================================
+ */
+GLOBAL SHORT
+validate_item(UTINY hostID, ConfigValues *value,
+ NameTable *table, CHAR *err)
+{
+ char *what;
+
+ if (!(what = translate_to_string(value->index, table)))
+ {
+ *err = '\0';
+ return EG_BAD_VALUE;
+ }
+ return C_CONFIG_OP_OK;
+}
+
+/*
+ * ==========================================================================
+ * Function: add_resource_node.
+ *
+ * Stubbed add_resource_node added to satisfy reference in unused
+ * `host_read_resource_file' in `hunt_cnf.c'. Needed in order to make trapper
+ * SoftPC link when using Microsoft `config'.
+ * ==========================================================================
+ */
+GLOBAL LineNode *
+add_resource_node(CHAR *str)
+{
+ always_trace0("Stubbed add_resource_node called");
+ return((LineNode *) NULL);
+}
+
+#endif /* HUNTER */
+
+/*
+ * ===========================================================================
+ * LOCAL FUNCTIONS
+ * ===========================================================================
+ */
+
+#ifdef HUNTER
+
+VOID
+build_data_table(VOID)
+{
+ SHORT maxHostID = 0;
+ OptionDescription *defP;
+
+ /* Don't do it more than once. */
+ if (conf_tab != NULL)
+ return;
+
+ /* Find out how big the table needs to be. */
+ for (defP = host_defs; defP->optionName; defP++)
+ if (defP->hostID > maxHostID)
+ maxHostID = defP->hostID;
+ maxHostID++;
+
+ /* Create the table. */
+ check_malloc(conf_tab, maxHostID, ConfTabEntry);
+}
+
+VOID
+read_trapper_variables(VOID)
+{
+ CHAR arg[MAXPATHLEN],
+ *vp;
+ OptionDescription *defP;
+ ConfigValues data,
+ *cvp;
+ ErrData errData;
+
+ /* Read all the variables required by trapper from the environment. */
+ for (defP = host_defs; defP->optionName; defP++)
+ {
+
+ /*
+ * Ignore `host_defs' entries designed to override `common_defs'
+ * entries as we have an empty common_defs table.
+ */
+ if ((defP->flags & C_TYPE_MASK) == C_RECORD_DELETE)
+ continue;
+
+ /* Get the variable. */
+ vp = host_getenv(defP->optionName);
+ if (vp != NULL)
+ strcpy(arg, vp);
+ else
+ arg[0] = '\0';
+
+ /*
+ * Convert variable and store in ConfigValues structure for use by
+ * validation routine.
+ */
+ convert_arg(arg, defP, &data);
+ errData.string_1 = arg;
+ errData.string_2 = defP->optionName;
+ while (check_value(defP, &data))
+ {
+ if (host_error_ext(EG_BAD_CONF, ERR_QU_CO, &errData) == ERR_CONT)
+ convert_arg(arg, defP, &data);
+ }
+
+ /* Store the value in the data table. */
+ check_malloc(cvp, 1, ConfigValues);
+ conf_tab[defP->hostID].data = cvp;
+ conf_tab[defP->hostID].def = defP;
+ switch (defP->flags & C_TYPE_MASK)
+ {
+ case C_STRING_RECORD:
+ always_trace2("read_trapper_variables: %s set to %s",
+ defP->optionName, data.string);
+ strcpy(cvp->string, data.string);
+ break;
+
+ case C_NAME_RECORD:
+ case C_NUMBER_RECORD:
+ always_trace2("read_trapper_variables: %s set to %d",
+ defP->optionName, data.index);
+ cvp->index = data.index;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+VOID
+convert_arg(CHAR *arg, OptionDescription *defP, ConfigValues *dataP)
+{
+ switch (defP->flags & C_TYPE_MASK)
+ {
+ case C_STRING_RECORD:
+ strcpy(dataP->string, arg);
+ break;
+
+ case C_NAME_RECORD:
+ dataP->index = translate_to_value(arg, defP->table);
+ break;
+
+ case C_NUMBER_RECORD:
+ dataP->index = atoi(arg);
+ break;
+
+ default:
+ (VOID) host_error(EG_OWNUP, ERR_QUIT, "Invalid TYPE");
+ break;
+ }
+}
+
+SHORT
+check_value(OptionDescription *defP, ConfigValues *dataP)
+{
+ SHORT status;
+ CHAR errbuf[MAXPATHLEN];
+
+ if (defP->valid)
+ status = (*defP->valid)(defP->hostID, dataP, defP->table, errbuf);
+ else
+ status = C_CONFIG_OP_OK;
+ return(status);
+}
+
+#endif /* HUNTER */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Read auto close time ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+#define APPNAME "Dos Emulation"
+
+/* These are entries uder "WOW" section in the system registry to control
+ * LPT and COM devices behaviors.
+ *
+ * "PrinterAutoClose=n" -- the printer port will be closed if there are
+ * not activities on the port for n seconds
+ * "CommsAutoClose=n" -- the comm port will be closed(suspended" if there
+ * there are not activities on the port for
+ * n s. 0 means auto close is disabled.
+ * "LPT_timeout=n" -- the printer port will be flushed every n seconds
+ * "COM_SyncWrite=[0,1]" -- if 0, write to comm port(tx) if performed in
+ * async way(using overlapped i/o). If 1, then
+ * data will be written to the port in synchrounously.
+ * "COM_TxBuffer_Size=n" -- comm tx queue buffer size. It also used to control
+ * the tx threshold -- setting the buffer size to
+ * 1 effectively disables tx queuing.
+ */
+struct { char *keyword; int def; } ProfileStrings[] =
+{
+ { "PrinterAutoClose", 15 },
+ { "CommsAutoClose", 0 },
+ { "LPT_timeout", 15},
+ { "COM_SyncWrite", },
+ { "COM_TxBuffer_Size", 200}
+};
+
+int read_profile_int(int index)
+{
+ CHAR CmdLine[100];
+ ULONG CmdLineSize = 100;
+ HKEY hWowKey;
+ int Value;
+
+ ASSERT((unsigned int) index < PROFILE_MAX_INDEX);
+ /* make sure we have right index constants */
+ ASSERT(PROFILE_LPT_AUTOCLOSE_DELAY == 0 &&
+ PROFILE_COM_AUTOCLOSE_DELAY == 1 &&
+ PROFILE_LPT_AUTOFLUSH_DELAY == 2 &&
+ PROFILE_COM_SYNCWRITE == 3 &&
+ PROFILE_COM_TXBUFFER_SIZE == 4);
+
+ if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\WOW",
+ 0,
+ KEY_QUERY_VALUE,
+ &hWowKey
+ ) != 0)
+ {
+ /* wow key doesn't exist, use default value */
+ return(ProfileStrings[index].def);
+ }
+
+ if (RegQueryValueEx (hWowKey,
+ ProfileStrings[index].keyword,
+ NULL,
+ NULL,
+ (LPBYTE)&CmdLine,
+ &CmdLineSize) != 0)
+ {
+ /* if the value doesn't exist, use the default value */
+ Value = ProfileStrings[index].def;
+ }
+ else
+ Value = (int)atoi(CmdLine);
+
+ RegCloseKey (hWowKey);
+
+ return Value;
+}
+
+
+
+#ifdef LIM
+boolean get_lim_configuration_data(PLIM_CONFIG_DATA buffer)
+{
+ if (lim_config_data.initialized){
+ *buffer = lim_config_data;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+#endif
+
+
+#ifdef MONITOR
+/* this function returns the backfill starting segment to monitor
+ *
+ * VERT IMPORTANT !!!!
+ * the backfill segment must be available before sas_init.
+ *
+ */
+
+unsigned short get_lim_backfill_segment(void)
+{
+#ifdef LIM
+ if (lim_config_data.initialized)
+ return lim_config_data.base_segment;
+ else
+ return 640 * 1024 / 16;
+#else
+ return 640 * 1024 / 16;
+#endif
+
+}
+#endif
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Get VDM Memory Size :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+#define REGISTRY_BUFFER_SIZE 512
+
+// Returns the size in K.
+
+ULONG
+GetVDMSize (BOOL fwow)
+{
+ CHAR CmdLine[REGISTRY_BUFFER_SIZE];
+ PCHAR pCmdLine,KeywordName;
+ ULONG CmdLineSize = REGISTRY_BUFFER_SIZE;
+ HKEY WowKey;
+
+ //
+ // Get Vdm size
+ //
+
+ if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\WOW",
+ 0,
+ KEY_QUERY_VALUE,
+ &WowKey
+ ) != 0){
+ return GetDefaultVDMSize (fwow); // returns in K
+ }
+
+ if (fwow) {
+ KeywordName = "wowsize" ;
+ } else {
+ KeywordName = "size" ;
+ }
+
+ if (RegQueryValueEx (WowKey,
+ KeywordName,
+ NULL,
+ NULL,
+ (LPBYTE)&CmdLine,
+ &CmdLineSize) != 0){
+ RegCloseKey (WowKey);
+ return GetDefaultVDMSize (fwow); // returns in K
+ }
+
+ RegCloseKey (WowKey);
+
+ CmdLineSize = 1024L * atoi(CmdLine);
+
+ if (CmdLineSize == 0)
+ CmdLineSize = GetDefaultVDMSize (fwow); // returns in K
+
+ return (CmdLineSize);
+ }
+
+#define VDM_SMALL_SYSTEM (12*1024*1024)
+#define VDM_MEDIUM_SYSTEM (16*1024*1024)
+
+ULONG
+GetDefaultVDMSize ( BOOL fwow )
+{
+ MEMORYSTATUS MemoryStatus;
+
+ GlobalMemoryStatus (&MemoryStatus);
+
+ //
+ // System Size < 12Mb is small = VDM Size = 3MB
+ // System Size = 12-16 is medium = VDM Size = 6MB
+ // System Size = > 16 is large = VDM Size = 8Mb
+ //
+
+ if (MemoryStatus.dwTotalPhys < VDM_SMALL_SYSTEM )
+ return 8L * 1024L;
+
+ if (MemoryStatus.dwTotalPhys <= VDM_MEDIUM_SYSTEM )
+ return 12L * 1024L;
+ else
+ return 16L * 1024L;
+}
diff --git a/private/mvdm/softpc.new/host/src/copy_fnc.c b/private/mvdm/softpc.new/host/src/copy_fnc.c
new file mode 100644
index 000000000..a7e4382df
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/copy_fnc.c
@@ -0,0 +1,195 @@
+/* static char SccsID[] = " @(#)copy_func.c 1.6 6/24/91 Copyright Insignia Solutions Ltd."; */
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "host_def.h"
+#include "insignia.h"
+#include "xt.h"
+
+void
+bwdcopy(
+ char *src,
+ char *dest,
+ int len
+ )
+{
+#if 0
+register int loop;
+ for(loop = 0; loop < len; loop++)
+ *dest-- = *src--;
+
+#else
+ int i;
+
+ i = len - 1;
+ memcpy(dest - i , src - i, len);
+
+#endif
+}
+
+
+void
+bwd_dest_copy(
+ char *src,
+ char *dest,
+ int len
+ )
+{
+ int loop;
+
+ for(loop = 0; loop < len; loop++)
+ *dest-- = *src++;
+}
+
+
+void
+memfill(
+ unsigned char data,
+ unsigned char *l_addr_in,
+ unsigned char *h_addr_in
+ )
+{
+ unsigned int len;
+
+ len = h_addr_in + 1 - l_addr_in;
+ memset(l_addr_in, data, len);
+
+#if 0
+ unsigned int data4;
+ unsigned char *l_addr = l_addr_in;
+ unsigned char *h_addr = h_addr_in;
+ unsigned int *l_addr4,*h_addr4;
+
+ l_addr4 = (unsigned int *)(((unsigned int)l_addr+3) & (~3));
+ h_addr4 = (unsigned int *)(((unsigned int)h_addr+1) & (~3));
+ if(h_addr4 > l_addr4)
+ {
+ data4 = data*0x01010101; // 0x61 * 0x01010101 = 0x61616161
+ for(;(unsigned int *)l_addr < l_addr4;l_addr++)
+ *l_addr = data;
+ do {
+ *l_addr4++ = data4;
+ } while (h_addr4 > l_addr4);
+
+ l_addr = (unsigned char *)l_addr4;
+ }
+ for(;l_addr <= h_addr;l_addr++)*l_addr = data;
+#endif
+}
+
+void
+fwd_word_fill(
+ unsigned short data,
+ unsigned char *l_addr_in,
+ int len
+ )
+{
+ unsigned int data4, count;
+ unsigned char *l_addr = l_addr_in;
+ unsigned char *h_addr = l_addr_in+(len<<1);
+ unsigned int *l_addr4,*h_addr4;
+
+ l_addr4 = (unsigned int *)(((unsigned int)l_addr+3) & (~3));
+ h_addr4 = (unsigned int *)(((unsigned int)h_addr) & (~3));
+#ifdef LITTLEND
+ data = ((data >> 8) & 0xff) | ((data << 8) & 0xff00);
+#endif
+ if(h_addr4 > l_addr4)
+ {
+ switch((unsigned char *)l_addr4-l_addr)
+ {
+ case 3:
+ data = (data>>8) | (data<<8);
+ *l_addr++ = (unsigned char)(data);
+ case 2:
+ *(unsigned short *)l_addr = data;
+ break;
+ case 1:
+ data = (data>>8) | (data<<8);
+ *l_addr = (unsigned char)data;
+ }
+ data4 = data+(data<<16);
+
+#if 0
+ do *l_addr4++ = data4; while (h_addr4 > l_addr4);
+ l_addr = (unsigned char *)l_addr4;
+#else
+ count = h_addr4 - l_addr4;
+ RtlFillMemoryUlong(l_addr4, count, data4);
+ l_addr = (unsigned char *)l_addr4;
+ l_addr += count;
+#endif
+
+ }
+ switch(h_addr-l_addr)
+ {
+ case 5:
+/*
+ data = (data>>8) | (data<<8);
+*/
+ data = ((data >> 8) & 0xff) | ((data << 8) & 0xff00);
+ *l_addr++ = (unsigned char)data;
+ *(unsigned int *)l_addr = data | (data<<16);
+ break;
+ case 7:
+/*
+ data = (data>>8) | (data<<8);
+*/
+ data = ((data >> 8) & 0xff) | ((data << 8) & 0xff00);
+ *l_addr++ = (unsigned char)data;
+ case 6:
+ *l_addr++ = (unsigned char)data;
+ *l_addr++ = data >> 8;
+ case 4:
+ *l_addr++ = (unsigned char)data;
+ *l_addr++ = data >> 8;
+ *l_addr++ = (unsigned char)data;
+ *l_addr++ = data >> 8;
+ break;
+ case 3:
+/*
+ data = (data>>8) | (data<<8);
+*/
+ data = ((data >> 8) & 0xff) | ((data << 8) & 0xff00);
+ *l_addr++ = (unsigned char)(data);
+ case 2:
+ *l_addr++ = (unsigned char)data;
+ *l_addr++ = data >> 8;
+ break;
+ case 1:
+/*
+ data = (data>>8) | (data<<8);
+*/
+ data = ((data >> 8) & 0xff) | ((data << 8) & 0xff00);
+ *l_addr = (unsigned char)data;
+ }
+}
+
+
+
+
+void
+memset4(
+ unsigned int data,
+ unsigned int *laddr,
+ unsigned int count
+ )
+{
+#if 0
+ while( count -- )
+ {
+ *laddr++ = data;
+ }
+#else
+
+ /*
+ * The argument, count, as passed to this function is the number of 4-byte
+ * items to fill, all RtlFill type functions need their count in bytes, so
+ * multiply count by 4. (JJS - 6/9/95).
+ */
+ RtlFillMemoryUlong(laddr, count << 2, data);
+
+#endif
+}
diff --git a/private/mvdm/softpc.new/host/src/cpucstbs.c b/private/mvdm/softpc.new/host/src/cpucstbs.c
new file mode 100644
index 000000000..b70c14339
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/cpucstbs.c
@@ -0,0 +1,32 @@
+#ifndef MONITOR
+#ifdef A3CPU
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "insignia.h"
+#include "host_def.h"
+#include "xt.h"
+#include "ica.h"
+
+void npx_interrupt_line_waggled()
+{
+ ica_hw_interrupt(1, 5, 1);
+}
+
+// MIPS interface from CPU cacheflush request
+void cacheflush(long base_addr, long length)
+{
+ // should check return, but what is correct action (Exit??) if failure?
+ NtFlushInstructionCache(GetCurrentProcess(), (PVOID) base_addr, length);
+}
+
+void host_sigio_event()
+{
+}
+
+
+#endif /* A3CPU */
+#endif /* ! MONITOR */
diff --git a/private/mvdm/softpc.new/host/src/fprt.c b/private/mvdm/softpc.new/host/src/fprt.c
new file mode 100644
index 000000000..0968d5f66
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/fprt.c
@@ -0,0 +1,233 @@
+#include "windows.h"
+#include "insignia.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "stdarg.h"
+#ifdef HUNTER
+#include "nt_hunt.h"
+#endif /* HUNTER */
+
+void OutputString(char *);
+
+int _CRTAPI1 printf(const char *str, ...)
+{
+#ifndef PROD
+ va_list ap;
+ char buf[500];
+
+ va_start(ap,str);
+ vsprintf(buf, str, ap);
+ OutputString(buf);
+ va_end(ap);
+#endif
+ return(0);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+static HANDLE pipe=NULL;
+
+void OutputString(char *str)
+{
+#ifndef PROD
+ char StrSizeStr[2];
+ int StrSize;
+ DWORD BytesWritten;
+
+ /*............................................ Connect to debug pipe */
+
+ if(pipe == NULL && getenv("PIPE") != NULL)
+ {
+ pipe = CreateFile(getenv("PIPE"),GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(pipe == (HANDLE) -1)
+ OutputDebugString("ntvdm : Failed to connect to debug pipe\n");
+ }
+
+ /*.................................................... Output string */
+
+ if(pipe != NULL && pipe != (HANDLE) -1)
+ {
+ StrSize = strlen(str);
+ StrSizeStr[0] = (char) (StrSize % 256);
+ StrSizeStr[1] = (char) (StrSize / 256);
+
+ WriteFile(pipe, StrSizeStr, 2, &BytesWritten, NULL);
+ WriteFile(pipe, str, StrSize, &BytesWritten, NULL);
+ }
+ else
+ OutputDebugString(str);
+
+#endif
+#ifdef HUNTER
+ if (TrapperDump != (HANDLE) -1)
+ WriteFile(TrapperDump, str, strlen(str), &BytesWritten, NULL);
+#endif /* HUNTER */
+}
+
+#define WACKY_INPUT "[BOB&SIMON'SCHEESYINPUT]"
+#define WACKY_INPUTLEN 0xff
+
+#define INPUT_API_SIG 0xdefaced
+
+VOID InputString(char *str, int len)
+{
+#ifndef PROD
+
+ char input_request[2];
+ DWORD BytesWritten, BytesRead;
+ int StringSize;
+ UNALIGNED DWORD *addsig;
+ char *inorout;
+ IMPORT ULONG DbgPrompt(char *, char *, ULONG);
+
+ if(pipe != NULL && pipe != (HANDLE) -1)
+ {
+ input_request[0] = (char)0xff; input_request[1] = (char)0xff;
+ WriteFile(pipe, input_request, 2, &BytesWritten, NULL);
+
+ ReadFile(pipe, str, 2, &BytesRead, NULL);
+ StringSize = (str[0]&0xff) + ((str[1]&0xff)*256);
+
+ if(StringSize >= len)
+ OutputDebugString("ntvdm : PIPE BUFFER OVERFLOW [FATAL]\n");
+
+ ReadFile(pipe, str, StringSize, &BytesRead, NULL);
+ }
+ else
+ {
+/*
+ We used to do this...
+ DbgPrompt("",str,len);
+ but foozle dust now does this...
+
+ Call OutputDebugString with the following:
+
+ "Message" | 0xdefaced | len | inBuffer
+
+where "Message" is printed
+ 0xdefaced is a magic (DWORD) signature
+ len is a byte length of,,,
+ inBuffer which the reply to 'Message will appear in.
+*/
+ /* do this so we can add prompt passing if we wish */
+ StringSize = strlen("") + 1;
+ inorout = malloc(len + StringSize + 5);
+ if (!inorout)
+ {
+ printf("\nmemory allocation failure - getting input via kd\n");
+ DbgPrompt("NTVDM>> ", str, len);
+ return;
+ }
+ strcpy(inorout, "");
+ addsig = (PDWORD)&inorout[StringSize];
+ *addsig = INPUT_API_SIG;
+ *(inorout + StringSize+4) = (BYTE)len;
+ *(inorout + StringSize+5) = (BYTE)0xff; // success flag
+ OutputDebugString(inorout);
+ // check for no debugger or debugger that can't speak foozle
+ if (*(inorout + StringSize + 5) == 0xff)
+ DbgPrompt("", str, len);
+ else
+ strcpy(str, inorout + StringSize + 5);
+ free(inorout);
+ }
+
+#endif
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+int _CRTAPI2 fprintf(FILE *tf, const char *str, ...)
+{
+#ifndef PROD
+ va_list ap;
+ char buf[500];
+
+ if (getenv("TRACE") == NULL) //JonLu request to limit debugs
+ return(0);
+
+ va_start(ap,str);
+ vsprintf(buf, str, ap);
+ va_end(ap);
+ OutputString(buf);
+#endif
+ return(0);
+}
+
+char *nt_fgets(char *buffer, int len, void *input_stream)
+{
+ /* Get Line from debug terminal */
+ buffer[0] = 0;
+ InputString(buffer,len);
+
+ return(buffer);
+}
+
+char *nt_gets(char *buffer)
+{
+ return(nt_fgets(buffer, 500, (void *) 0));
+}
+
+#ifndef HUNTER
+char * _CRTAPI1 fgets(char *buffer, int len, FILE *input_stream)
+{
+ int blen;
+
+ // If not processing call to STDIN pass on to standard library function
+ if(input_stream != stdin)
+ {
+ char *ptr = buffer;
+ int chr;
+
+ while(--len && (chr = fgetc(input_stream)) != EOF)
+ {
+ *ptr++ = (char) chr;
+ if(chr == '\n') break;
+ }
+
+ *ptr = (char) 0;
+ return(chr == EOF ? NULL : buffer);
+
+ }
+
+ // clear buffer...
+ for(blen = 0; blen < len; blen++)
+ buffer[blen] = 0;
+ nt_fgets(buffer, len, input_stream);
+ blen = strlen(buffer);
+ if (blen + 1 < len)
+ {
+ buffer[blen] = '\n'; /* fgets adds newline */
+ buffer[blen+1] = '\0';
+ }
+ return(buffer);
+}
+
+char * _CRTAPI1 gets(char *buffer)
+{
+ return(nt_fgets(buffer, 500, (void *) 0));
+}
+
+int _CRTAPI1 puts(const char *buffer)
+{
+ OutputString((char *)buffer);
+ return(1);
+}
+
+size_t _CRTAPI1 fwrite(const void *buf, size_t size, size_t len, FILE *stream)
+{
+ char *tmp_buf; // Screw the compiler into avoiding const chk
+
+ tmp_buf = (char *)((DWORD)buf);
+
+ tmp_buf[len] = 0; // Bullshit write into a const ptr!
+#ifndef PROD
+ OutputString((char *)buf);
+#endif /* PROD */
+ return(len);
+}
+#endif /* HUNTER */
diff --git a/private/mvdm/softpc.new/host/src/makefile b/private/mvdm/softpc.new/host/src/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/mvdm/softpc.new/host/src/makefile.inc b/private/mvdm/softpc.new/host/src/makefile.inc
new file mode 100644
index 000000000..a9dd941dc
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/makefile.inc
@@ -0,0 +1,6 @@
+#dummy file to be included
+
+{obj\$(TARGET_DIRECTORY)\}fprt.obj : fprt.c
+
+$(SOFTPC_DEST)\obj\$(TARGET_DIRECTORY)\fprt.obj : obj\$(TARGET_DIRECTORY)\fprt.OBJ
+ copy $** $@
diff --git a/private/mvdm/softpc.new/host/src/nt_aorc.c b/private/mvdm/softpc.new/host/src/nt_aorc.c
new file mode 100644
index 000000000..71d5e0bd2
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_aorc.c
@@ -0,0 +1,861 @@
+/*
+============================== nt_a_or_c.c ===================================
+
+ This file provides a crude means of mapping a cpu specific function
+ to a generically used function. Microsoft libraries to which we do not
+ have the source, call getXX and setXX functions directly and thus a mapping
+ is required if a C emulator is built or an assembly language variant is
+ used.
+
+ For example:
+
+ If CCPU is defined, then getAX() maps to c_getAX(),
+ If A3CPU is defined, then getAX() maps to a3_getAX(),
+
+ Unfortunately, this does not allow a pigger to build.
+
+ Andy Watson 3/11/94
+
+==============================================================================
+*/
+
+#include "insignia.h"
+#include "host_def.h"
+#define CPU_PRIVATE
+#include "cpu4.h"
+#include "sas.h"
+
+#ifdef CCPU
+
+/*
+ *
+ * CCPU interface to the emulator registers.
+ *
+ */
+
+#undef getAL
+GLOBAL half_word getAL()
+{
+ return c_getAL();
+}
+
+#undef getBL
+GLOBAL half_word getBL()
+{
+ return c_getBL();
+}
+
+#undef getCL
+GLOBAL half_word getCL()
+{
+ return c_getCL();
+}
+
+#undef getDL
+GLOBAL half_word getDL()
+{
+ return c_getDL();
+}
+
+#undef getAH
+GLOBAL half_word getAH()
+{
+ return c_getAH();
+}
+
+#undef getBH
+GLOBAL half_word getBH()
+{
+ return c_getBH();
+}
+
+#undef getCH
+GLOBAL half_word getCH()
+{
+ return c_getCH();
+}
+
+#undef getDH
+GLOBAL half_word getDH()
+{
+ return c_getDH();
+}
+
+#undef getAX
+GLOBAL word getAX()
+{
+ return c_getAX();
+}
+
+#undef getBX
+GLOBAL word getBX()
+{
+ return c_getBX();
+}
+
+#undef getCX
+GLOBAL word getCX()
+{
+ return c_getCX();
+}
+
+#undef getDX
+GLOBAL word getDX()
+{
+ return c_getDX();
+}
+
+#undef getSP
+GLOBAL word getSP()
+{
+ return c_getSP();
+}
+
+#undef getBP
+GLOBAL word getBP()
+{
+ return c_getBP();
+}
+
+#undef getSI
+GLOBAL word getSI()
+{
+ return c_getSI();
+}
+
+#undef getDI
+GLOBAL word getDI()
+{
+ return c_getDI();
+}
+
+#undef getIP
+GLOBAL word getIP()
+{
+ return c_getIP();
+}
+
+#undef getEIP
+GLOBAL IU32 getEIP()
+{
+ return c_getEIP();
+}
+
+#undef getESP
+GLOBAL IU32 getESP()
+{
+ return c_getESP();
+}
+
+#undef getEFLAGS
+GLOBAL IU32 getEFLAGS()
+{
+ return c_getEFLAGS();
+}
+
+
+
+#undef GetInstructionPointer
+GLOBAL IU32 GetInstructionPointer()
+{
+ return (IU32) c_getIP();
+}
+
+#undef getCS
+GLOBAL word getCS()
+{
+ return c_getCS();
+}
+
+#undef getDS
+GLOBAL word getDS()
+{
+ return c_getDS();
+}
+
+#undef getES
+GLOBAL word getES()
+{
+ return c_getES();
+}
+
+#undef getSS
+GLOBAL word getSS()
+{
+ return c_getSS();
+}
+
+
+#undef getAF
+GLOBAL word getAF()
+{
+ return c_getAF();
+}
+
+#undef getCF
+GLOBAL word getCF()
+{
+ return c_getCF();
+}
+
+#undef getDF
+GLOBAL word getDF()
+{
+ return c_getDF();
+}
+
+#undef getIF
+GLOBAL word getIF()
+{
+ return c_getIF();
+}
+
+#undef getOF
+GLOBAL word getOF()
+{
+ return c_getOF();
+}
+
+#undef getPF
+GLOBAL word getPF()
+{
+ return c_getPF();
+}
+
+#undef getSF
+GLOBAL word getSF()
+{
+ return c_getSF();
+}
+
+#undef getTF
+GLOBAL word getTF()
+{
+ return c_getTF();
+}
+
+#undef getZF
+GLOBAL word getZF()
+{
+ return c_getZF();
+}
+
+#undef getMSW
+GLOBAL word getMSW()
+{
+ return c_getMSW();
+}
+#undef getCPL
+GLOBAL word getCPL()
+{
+ return c_getCPL();
+}
+
+#undef setAL
+GLOBAL VOID setAL(val)
+half_word val;
+{
+ setAX( (getAX() & 0xFF00) | (val & 0xFF) );
+}
+
+
+#undef setCL
+GLOBAL VOID setCL(val)
+half_word val;
+{
+ setCX( (getCX() & 0xFF00) | (val & 0xFF) );
+}
+
+
+#undef setDL
+GLOBAL VOID setDL(val)
+half_word val;
+{
+ setDX( (getDX() & 0xFF00) | (val & 0xFF) );
+}
+
+
+#undef setBL
+GLOBAL VOID setBL(val)
+half_word val;
+{
+ setBX( (getBX() & 0xFF00) | (val & 0xFF) );
+}
+
+
+#undef setAH
+GLOBAL VOID setAH(val)
+half_word val;
+{
+ setAX( getAL() | ((val & 0xFF) << 8) );
+}
+
+
+#undef setCH
+GLOBAL VOID setCH(val)
+half_word val;
+{
+ setCX( getCL() | ((val & 0xFF) << 8) );
+}
+
+
+#undef setDH
+GLOBAL VOID setDH(val)
+half_word val;
+{
+ setDX( getDL() | ((val & 0xFF) << 8) );
+}
+
+
+#undef setBH
+GLOBAL VOID setBH(val)
+half_word val;
+{
+ setBX( getBL() | ((val & 0xFF) << 8) );
+}
+
+
+#undef setAX
+GLOBAL VOID setAX(val)
+word val;
+{
+ c_setAX(val);
+}
+
+#undef setBX
+GLOBAL VOID setBX(val)
+word val;
+{
+ c_setBX(val);
+}
+
+
+#undef setCX
+GLOBAL VOID setCX(val)
+word val;
+{
+ c_setCX(val);
+}
+
+
+#undef setDX
+GLOBAL VOID setDX(val)
+word val;
+{
+ c_setDX(val);
+}
+
+
+
+#undef setSP
+GLOBAL VOID setSP(val)
+word val;
+{
+ c_setSP(val);
+}
+
+
+#undef setBP
+GLOBAL VOID setBP(val)
+word val;
+{
+ c_setBP(val);
+}
+
+
+#undef setSI
+GLOBAL VOID setSI(val)
+word val;
+{
+ c_setSI(val);
+}
+
+
+#undef setDI
+GLOBAL VOID setDI(val)
+word val;
+{
+ c_setDI(val);
+}
+
+
+#undef setIP
+GLOBAL VOID setIP(val)
+word val;
+{
+ c_setIP(val);
+}
+
+#undef setES
+GLOBAL setES(val)
+word val;
+{
+ return c_setES(val);
+}
+
+
+#undef setCS
+GLOBAL setCS(val)
+word val;
+{
+ return c_setCS(val);
+}
+
+#undef setSS
+GLOBAL setSS(val)
+word val;
+{
+ return c_setSS(val);
+}
+
+
+#undef setDS
+GLOBAL setDS(val)
+word val;
+{
+ return c_setDS(val);
+}
+
+
+
+#undef setCF
+GLOBAL VOID setCF(val)
+word val;
+{
+ c_setCF(val);
+}
+
+
+#undef setPF
+GLOBAL VOID setPF(val)
+word val;
+{
+ c_setPF(val);
+}
+
+
+#undef setAF
+GLOBAL VOID setAF(val)
+word val;
+{
+ c_setAF(val);
+}
+
+
+#undef setZF
+GLOBAL VOID setZF(val)
+word val;
+{
+ c_setZF(val);
+}
+
+
+#undef setSF
+GLOBAL VOID setSF(val)
+word val;
+{
+ c_setSF(val);
+}
+
+
+#undef setTF
+GLOBAL VOID setTF(val)
+word val;
+{
+ c_setTF(val);
+}
+
+
+#undef setIF
+GLOBAL VOID setIF(val)
+word val;
+{
+ c_setIF(val);
+}
+
+
+#undef setDF
+GLOBAL VOID setDF(val)
+word val;
+{
+ c_setDF(val);
+}
+
+
+#undef setOF
+GLOBAL VOID setOF(val)
+word val;
+{
+ c_setOF(val);
+}
+
+#undef setMSW
+GLOBAL VOID setMSW(val)
+word val;
+{
+ c_setMSW(val);
+}
+
+
+#undef setEIP
+GLOBAL VOID setEIP(val)
+IU32 val;
+{
+ c_setEIP(val);
+}
+
+#undef setEFLAGS
+GLOBAL void setEFLAGS(val)
+IU32 val;
+{
+ c_setEFLAGS(val);
+}
+
+#if 0
+#undef setFLAGS
+GLOBAL void setFLAGS(val)
+IU32 val;
+{
+ c_setEFLAGS(val);
+}
+#endif
+
+#undef setESP
+void setESP(val)
+IU32 val;
+{
+ c_setESP(val);
+}
+
+
+/* fiddle for building prod version */
+
+#undef getSS_BASE
+GLOBAL word getSS_BASE()
+{
+ return c_getSS_BASE();
+}
+
+#undef getSS_AR
+GLOBAL word getSS_AR()
+{
+ return c_getSS_AR();
+}
+
+#undef setSS_BASE_LIMIT_AR
+void setSS_BASE_LIMIT_AR(base,limit,ar)
+IU32 base,limit;
+IU16 ar;
+{
+ c_setSS_BASE_LIMIT_AR(base,limit,ar);
+}
+
+
+#endif /* CCPU */
+
+#ifdef CPU_40_STYLE
+#if defined(PROD) && !defined(CCPU)
+
+
+#undef setAL
+void setAL(IU8 val) {(*(Cpu.SetAL))(val); }
+#undef setAH
+void setAH(IU8 val) {(*(Cpu.SetAH))(val); }
+#undef setAX
+void setAX(IU16 val) {(*(Cpu.SetAX))(val); }
+#undef setBL
+void setBL(IU8 val) {(*(Cpu.SetBL))(val); }
+#undef setBH
+void setBH(IU8 val) {(*(Cpu.SetBH))(val); }
+#undef setBX
+void setBX(IU16 val) {(*(Cpu.SetBX))(val); }
+#undef setCL
+void setCL(IU8 val) {(*(Cpu.SetCL))(val); }
+#undef setCH
+void setCH(IU8 val) {(*(Cpu.SetCH))(val); }
+#undef setCX
+void setCX(IU16 val) {(*(Cpu.SetCX))(val); }
+#undef setDL
+void setDL(IU8 val) {(*(Cpu.SetDL))(val); }
+#undef setDH
+void setDH(IU8 val) {(*(Cpu.SetDH))(val); }
+#undef setDX
+void setDX(IU16 val) {(*(Cpu.SetDX))(val); }
+#undef setSI
+void setSI(IU16 val) {(*(Cpu.SetSI))(val); }
+#undef setDI
+void setDI(IU16 val) {(*(Cpu.SetDI))(val); }
+#undef setSP
+void setSP(IU16 val) {(*(Cpu.SetSP))(val); }
+#undef setBP
+void setBP(IU16 val) {(*(Cpu.SetBP))(val); }
+#undef setIP
+void setIP(IU16 val) {(*(Cpu.SetIP))(val); }
+#undef setCS
+void setCS(IU16 val) {(*(Cpu.SetCS))(val); }
+#undef setSS
+void setSS(IU16 val) {(*(Cpu.SetSS))(val); }
+#undef setDS
+void setDS(IU16 val) {(*(Cpu.SetDS))(val); }
+#undef setES
+void setES(IU16 val) {(*(Cpu.SetES))(val); }
+#undef setFS
+void setFS(IU16 val) {(*(Cpu.SetFS))(val); }
+#undef setGS
+void setGS(IU16 val) {(*(Cpu.SetGS))(val); }
+
+
+#undef setEAX
+void setEAX(val) {(*(Cpu.SetEAX))(val); }
+#undef setEBX
+void setEBX(val) {(*(Cpu.SetEBX))(val); }
+#undef setECX
+void setECX(val) {(*(Cpu.SetECX))(val); }
+#undef setEDX
+void setEDX(val) {(*(Cpu.SetEDX))(val); }
+#undef setESI
+void setESI(val) {(*(Cpu.SetESI))(val); }
+#undef setEDI
+void setEDI(val) {(*(Cpu.SetEDI))(val); }
+#undef setESP
+void setESP(val) {(*(Cpu.SetESP))(val); }
+#undef setEBP
+void setEBP(val) {(*(Cpu.SetEBP))(val); }
+#undef setEIP
+void setEIP(val) {(*(Cpu.SetEIP))(val); }
+
+
+
+#undef setEFLAGS
+void setEFLAGS(val) {(*(Cpu.SetEFLAGS))(val); }
+#undef setFLAGS
+void setFLAGS(val) {(*(Cpu.SetEFLAGS))(val); }
+#undef setSTATUS
+void setSTATUS(val) {(*(Cpu.SetSTATUS))(val); }
+#undef setIOPL
+void setIOPL(val) {(*(Cpu.SetIOPL))(val); }
+#undef setMSW
+void setMSW(val) {(*(Cpu.SetMSW))(val); }
+#undef setCR0
+void setCR0(val) {(*(Cpu.SetCR0))(val); }
+#undef setCR2
+void setCR2(val) {(*(Cpu.SetCR2))(val); }
+#undef setCR3
+void setCR3(val) {(*(Cpu.SetCR3))(val); }
+#undef setCF
+void setCF(IU16 val) {(*(Cpu.SetCF))(val); }
+#undef setPF
+void setPF(IU16 val) {(*(Cpu.SetPF))(val); }
+#undef setAF
+void setAF(IU16 val) {(*(Cpu.SetAF))(val); }
+#undef setZF
+void setZF(IU16 val) {(*(Cpu.SetZF))(val); }
+#undef setSF
+void setSF(IU16 val) {(*(Cpu.SetSF))(val); }
+#undef setTF
+void setTF(IU16 val) {(*(Cpu.SetTF))(val); }
+#undef setIF
+void setIF(IU16 val) {(*(Cpu.SetIF))(val); }
+#undef setDF
+void setDF(IU16 val) {(*(Cpu.SetDF))(val); }
+#undef setOF
+void setOF(IU16 val) {(*(Cpu.SetOF))(val); }
+#undef setNT
+void setNT(IU16 val) {(*(Cpu.SetNT))(val); }
+#undef setRF
+void setRF(IU16 val) {(*(Cpu.SetRF))(val); }
+#undef setVM
+void setVM(IU16 val) {(*(Cpu.SetVM))(val); }
+#undef setAC
+void setAC(IU16 val) {(*(Cpu.SetAC))(val); }
+#undef setPE
+void setPE(IU16 val) {(*(Cpu.SetPE))(val); }
+#undef setMP
+void setMP(IU16 val) {(*(Cpu.SetMP))(val); }
+#undef setEM
+void setEM(IU16 val) {(*(Cpu.SetEM))(val); }
+#undef setTS
+void setTS(IU16 val) {(*(Cpu.SetTS))(val); }
+#undef setPG
+void setPG(IU16 val) {(*(Cpu.SetPG))(val); }
+#undef setLDT_SELECTOR
+void setLDT_SELECTOR(val) {(*(Cpu.SetLDT_SELECTOR))(val); }
+#undef setTR_SELECTOR
+void setTR_SELECTOR(val) {(*(Cpu.SetTR_SELECTOR))(val); }
+
+#undef getAL
+IU8 getAL() { return (*(Cpu.GetAL))(); }
+#undef getAH
+IU8 getAH() { return (*(Cpu.GetAH))(); }
+#undef getAX
+IU16 getAX() { return (*(Cpu.GetAX))(); }
+#undef getBL
+IU8 getBL() { return (*(Cpu.GetBL))(); }
+#undef getBH
+IU8 getBH() { return (*(Cpu.GetBH))(); }
+#undef getBX
+IU16 getBX() { return (*(Cpu.GetBX))(); }
+#undef getCL
+IU8 getCL() { return (*(Cpu.GetCL))(); }
+#undef getCH
+IU8 getCH() { return (*(Cpu.GetCH))(); }
+#undef getCX
+IU16 getCX() { return (*(Cpu.GetCX))(); }
+#undef getDL
+IU8 getDL() { return (*(Cpu.GetDL))(); }
+#undef getDH
+IU8 getDH() { return (*(Cpu.GetDH))(); }
+#undef getDX
+IU16 getDX() { return (*(Cpu.GetDX))(); }
+#undef getSI
+IU16 getSI() { return (*(Cpu.GetSI))(); }
+#undef getDI
+IU16 getDI() { return (*(Cpu.GetDI))(); }
+#undef getSP
+IU16 getSP() { return (*(Cpu.GetSP))(); }
+#undef getBP
+IU16 getBP() { return (*(Cpu.GetBP))(); }
+#undef getIP
+IU16 getIP() { return (*(Cpu.GetIP))(); }
+#undef getCS
+IU16 getCS() { return (*(Cpu.GetCS))(); }
+#undef getSS
+IU16 getSS() { return (*(Cpu.GetSS))(); }
+#undef getDS
+IU16 getDS() { return (*(Cpu.GetDS))(); }
+#undef getES
+IU16 getES() { return (*(Cpu.GetES))(); }
+#undef getFS
+IU16 getFS() { return (*(Cpu.GetFS))(); }
+#undef getGS
+IU16 getGS() { return (*(Cpu.GetGS))(); }
+
+
+#undef getEAX
+getEAX() {return ((*(Cpu.GetEAX))()); }
+#undef getEBX
+getEBX() {return ((*(Cpu.GetEBX))()); }
+#undef getECX
+getECX() {return ((*(Cpu.GetECX))()); }
+#undef getEDX
+getEDX() {return ((*(Cpu.GetEDX))()); }
+#undef getESI
+getESI() {return ((*(Cpu.GetESI))()); }
+#undef getEDI
+getEDI() {return ((*(Cpu.GetEDI))()); }
+#undef getESP
+getESP() {return ((*(Cpu.GetESP))()); }
+#undef getEBP
+getEBP() {return ((*(Cpu.GetEBP))()); }
+#undef getEIP
+getEIP() {return ((*(Cpu.GetEIP))()); }
+
+
+
+#undef getEFLAGS
+IU32 getEFLAGS() { return (*(Cpu.GetEFLAGS))(); }
+#undef getSTATUS
+IU16 getSTATUS() { return (*(Cpu.GetSTATUS))(); }
+#undef getIOPL
+IU8 getIOPL() { return (*(Cpu.GetIOPL))(); }
+#undef getMSW
+IU16 getMSW() { return (*(Cpu.GetMSW))(); }
+#undef getCR0
+IU32 getCR0() { return (*(Cpu.GetCR0))(); }
+#undef getCR2
+IU32 getCR2() { return (*(Cpu.GetCR2))(); }
+#undef getCR3
+IU32 getCR3() { return (*(Cpu.GetCR3))(); }
+#undef getCF
+IBOOL getCF() { return (*(Cpu.GetCF))(); }
+#undef getPF
+IBOOL getPF() { return (*(Cpu.GetPF))(); }
+#undef getAF
+IBOOL getAF() { return (*(Cpu.GetAF))(); }
+#undef getZF
+IBOOL getZF() { return (*(Cpu.GetZF))(); }
+#undef getSF
+IBOOL getSF() { return (*(Cpu.GetSF))(); }
+#undef getTF
+IBOOL getTF() { return (*(Cpu.GetTF))(); }
+#undef getIF
+IBOOL getIF() { return (*(Cpu.GetIF))(); }
+#undef getDF
+IBOOL getDF() { return (*(Cpu.GetDF))(); }
+#undef getOF
+IBOOL getOF() { return (*(Cpu.GetOF))(); }
+#undef getNT
+IBOOL getNT() { return (*(Cpu.GetNT))(); }
+#undef getRF
+IBOOL getRF() { return (*(Cpu.GetRF))(); }
+#undef getVM
+IBOOL getVM() { return (*(Cpu.GetVM))(); }
+#undef getAC
+IBOOL getAC() { return (*(Cpu.GetAC))(); }
+#undef getPE
+IBOOL getPE() { return (*(Cpu.GetPE))(); }
+#undef getMP
+IBOOL getMP() { return (*(Cpu.GetMP))(); }
+#undef getEM
+IBOOL getEM() { return (*(Cpu.GetEM))(); }
+#undef getTS
+IBOOL getTS() { return (*(Cpu.GetTS))(); }
+#undef getET
+IBOOL getET() { return (*(Cpu.GetET))(); }
+#undef getNE
+IBOOL getNE() { return (*(Cpu.GetNE))(); }
+#undef getWP
+IBOOL getWP() { return (*(Cpu.GetWP))(); }
+#undef getPG
+IBOOL getPG() { return (*(Cpu.GetPG))(); }
+#undef getGDT_BASE
+IU32 getGDT_BASE() { return (*(Cpu.GetGDT_BASE))(); }
+#undef getGDT_LIMIT
+IU16 getGDT_LIMIT() { return (*(Cpu.GetGDT_LIMIT))(); }
+#undef getIDT_BASE
+IU32 getIDT_BASE() { return (*(Cpu.GetIDT_BASE))(); }
+#undef getIDT_LIMIT
+IU16 getIDT_LIMIT() { return (*(Cpu.GetIDT_LIMIT))(); }
+#undef getLDT_SELECTOR
+IU16 getLDT_SELECTOR() { return (*(Cpu.GetLDT_SELECTOR))(); }
+#undef getLDT_BASE
+IU32 getLDT_BASE() { return (*(Cpu.GetLDT_BASE))(); }
+#undef getLDT_LIMIT
+IU16 getLDT_LIMIT() { return (*(Cpu.GetLDT_LIMIT))(); }
+#undef getTR_SELECTOR
+IU16 getTR_SELECTOR() { return (*(Cpu.GetTR_SELECTOR))(); }
+#undef getTR_BASE
+IU32 getTR_BASE() { return (*(Cpu.GetTR_BASE))(); }
+#undef getTR_LIMIT
+IU16 getTR_LIMIT() { return (*(Cpu.GetTR_LIMIT))(); }
+#undef getTR_AR
+IU16 getTR_AR() { return (*(Cpu.GetTR_AR))(); }
+#undef setCPL
+void setCPL IFN1 (IUH, prot) { ((Cpu.Private)->SetCPL)(prot); }
+
+#undef getSS_BASE
+IU32 getSS_BASE IFN0()
+{ return (*((*(Cpu.Private)).GetSS_BASE))(); }
+
+#undef getSS_AR
+IU16 getSS_AR IFN0()
+{ return (*((*(Cpu.Private)).GetSS_AR))(); }
+
+#undef setSS_BASE_LIMIT_AR
+IBOOL setSS_BASE_LIMIT_AR IFN3(IU32, base, IU32, limit, IU16, ar)
+{ return (*((*(Cpu.Private)).SetSS_BASE_LIMIT_AR))(base, limit, ar); }
+
+
+/*** SAS stuff required for PROD. ***/
+
+#undef sas_enable_20_bit_wrapping
+void sas_enable_20_bit_wrapping() { (*(Sas.Sas_enable_20_bit_wrapping))(); }
+#undef sas_disable_20_bit_wrapping
+void sas_disable_20_bit_wrapping() { (*(Sas.Sas_disable_20_bit_wrapping))(); }
+#undef sas_twenty_bit_wrapping_enabled
+IBOOL sas_twenty_bit_wrapping_enabled() { return (*(Sas.Sas_twenty_bit_wrapping_enabled))(); }
+#undef sas_overwrite_memory
+void sas_overwrite_memory(IU32 addr, IU32 length) {(*(Sas.Sas_overwrite_memory))(addr, length);}
+
+#endif /* PROD && !CCPU */
+#endif /* CPU_40_STYLE */
diff --git a/private/mvdm/softpc.new/host/src/nt_bop.c b/private/mvdm/softpc.new/host/src/nt_bop.c
new file mode 100644
index 000000000..999663cc4
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_bop.c
@@ -0,0 +1,960 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <vdm.h>
+#include "insignia.h"
+#include "host_def.h"
+#include <nt_thred.h>
+
+#ifndef MONITOR
+#include <gdpvar.h>
+#endif
+
+/* INSIGNIA MODULE SPECIFICATION
+ -----------------------------
+
+
+ THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
+ CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MUST
+ NOT BE DISCLOSED TO ANY OTHER PARTIES WITHOUT THE EXPRESS
+ AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS LTD.
+
+
+DESIGNER : Jim Hatfield
+
+REVISION HISTORY :
+First version : 29th August 1988
+Second version : 18th May 1991
+
+MODULE NAME : nt_bop
+
+SOURCE FILE NAME : nt_bop.c
+
+PURPOSE : Supply the NT-specific BOP FF operations.
+
+-------------------------------------------------------------------------
+[1.2 DATATYPES FOR [1.1] (if not basic C types)]
+
+ STRUCTURES/TYPEDEFS/ENUMS:
+
+-------------------------------------------------------------------------
+[1.3 INTERMODULE IMPORTS]
+
+ PROCEDURES: None
+ DATA: None
+
+-------------------------------------------------------------------------
+[1.4 DESCRIPTION OF INTERMODULE INTERFACE]
+
+[1.4.1 IMPORTED OBJECTS]
+
+DATA OBJECTS : None
+
+
+/*=======================================================================
+[3.INTERMODULE INTERFACE DECLARATIONS]
+=========================================================================
+
+[3.1 INTERMODULE IMPORTS] */
+
+/* [3.1.1 #INCLUDES] */
+
+#include "stdio.h"
+
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "error.h"
+#include "config.h"
+#include "cntlbop.h"
+#include "host_bop.h"
+#include "demexp.h"
+#include "xmsexp.h"
+#include "sim32.h"
+#include "idetect.h"
+#include "bios.h"
+#include "nt_reset.h"
+#include "nt_eoi.h"
+#include <nt_com.h>
+#include "yoda.h"
+
+
+/* [3.1.2 DECLARATIONS] */
+
+/* [3.2 INTERMODULE EXPORTS] */
+
+
+/*
+5.MODULE INTERNALS : (not visible externally,global internally)]
+
+[5.1 LOCAL DECLARATIONS] */
+
+/* [5.1.1 #DEFINES] */
+
+/* [5.1.2 TYPEDEF, STRUCTURE, ENUM DECLARATIONS] */
+
+//
+// MYFARPROC
+//
+
+typedef ULONG (*MYFARPROC)();
+
+/* [5.1.3 PROCEDURE() DECLARATIONS] */
+
+/* -----------------------------------------------------------------------
+[5.2 LOCAL DEFINITIONS]
+
+ [5.2.1 INTERNAL DATA DEFINITIONS */
+
+
+/* [5.2.2 INTERNAL PROCEDURE DEFINITIONS] */
+
+/*
+7.INTERMODULE INTERFACE IMPLEMENTATION :
+ */
+
+VOID WaitIfIdle(VOID), WakeUpNow(VOID);
+VOID to_com_driver(VOID);
+VOID call_ica_hw_interrupt(int, half_word, int);
+VOID ica_enable_iret_hook(int, int, int);
+VOID ica_iret_hook_called(int);
+
+/*
+[7.1 INTERMODULE DATA DEFINITIONS] */
+
+
+#define SEGOFF(seg,off) (((ULONG)(seg) << 16) + ((off)))
+
+
+/********************************************************/
+/* GLOBALS */
+
+void UMBNotify(unsigned char);
+VOID demDasdInit(VOID);
+
+control_bop_array host_bop_table[] =
+{
+ 0, NULL
+};
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::;:::::: MS BOP stubs :::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+// DOS EMULATION BOP
+void MS_bop_0(void) {
+ ULONG DemCmd;
+
+ DemCmd = (ULONG)(*Sim32GetVDMPointer(SEGOFF(getCS(),getIP()),
+ 1,
+ FALSE
+ ));
+ DemDispatch( DemCmd );
+ setIP((USHORT)(getIP() + 1));
+
+ // we need to prevent the idle system from going off on intensive file
+ // reads. However, we don't want to disable it for continuous 'Get Time'
+ // calls (command 0x15). Nor for Get Date (0x15).
+ if (DemCmd != 0x15 && DemCmd != 0x14)
+ IDLE_disk();
+}
+
+// WOW BOP
+HANDLE hWOWDll;
+
+MYFARPROC WOWDispatchEntry;
+MYFARPROC WOWInitEntry;
+VOID (*pW32HungAppNotifyThread)(UINT) = NULL;
+
+static BOOL WowModeInitialized = FALSE;
+
+void MS_bop_1(void) {
+
+ if (!WowModeInitialized) {
+ //Load the WOW DLL
+ if ((hWOWDll = SafeLoadLibrary("WOW32")) == NULL)
+ {
+#ifndef PROD
+ HostDebugBreak();
+#endif
+ TerminateVDM();
+ return;
+ }
+
+ // Get the init entry point and dispatch entry point
+ if ((WOWInitEntry = (MYFARPROC)GetProcAddress(hWOWDll, "W32Init")) == NULL)
+ {
+#ifndef PROD
+ HostDebugBreak();
+#endif
+ FreeLibrary(hWOWDll);
+ TerminateVDM();
+ return;
+ }
+
+ if ((WOWDispatchEntry = GetProcAddress(hWOWDll, "W32Dispatch")) == NULL)
+ {
+#ifndef PROD
+ HostDebugBreak();
+#endif
+ FreeLibrary(hWOWDll);
+ TerminateVDM();
+ return;
+ }
+
+ //Get Comms functions
+ if ((GetCommHandle = (GCHfn) GetProcAddress(hWOWDll, "GetCommHandle")) == NULL)
+ {
+#ifndef PROD
+ HostDebugBreak();
+#endif
+ FreeLibrary(hWOWDll);
+ TerminateVDM();
+ return;
+ }
+
+ if ((GetCommShadowMSR = (GCSfn) GetProcAddress(hWOWDll, "GetCommShadowMSR")) == NULL)
+ {
+#ifndef PROD
+ HostDebugBreak();
+#endif
+ FreeLibrary(hWOWDll);
+ TerminateVDM();
+ return;
+ }
+
+ //Get hung app Notification routine
+ pW32HungAppNotifyThread = (VOID(*)(UINT))GetProcAddress( hWOWDll,
+ "W32HungAppNotifyThread");
+ if (!pW32HungAppNotifyThread)
+ {
+#ifndef PROD
+ HostDebugBreak();
+#endif
+ FreeLibrary(hWOWDll);
+ TerminateVDM();
+ return;
+ }
+
+
+ // Call the init routine
+ if ((*WOWInitEntry)() == FALSE)
+ {
+#ifndef PROD
+ HostDebugBreak();
+#endif
+ TerminateVDM();
+ return;
+ }
+
+ WowModeInitialized = TRUE;
+ }
+
+#if !defined(CPU_40_STYLE) || defined(CCPU)
+ (*WOWDispatchEntry)();
+#else
+ // Dispatch to WOW dispatcher
+ {
+ static BYTE **AddressOfLocal;
+ BYTE *localSimulateContext = GLOBAL_SimulateContext;
+
+ AddressOfLocal = &localSimulateContext;
+
+ (*WOWDispatchEntry)();
+
+ SET_GLOBAL_SimulateContext(localSimulateContext);
+
+ if(AddressOfLocal != &localSimulateContext)
+ {
+ //Thread switch detected via stack change, force CPU to
+ //abort the current fragment, reseting GDP var's refering
+ //to the host stack
+
+ setEIP(getEIP());
+ }
+ }
+#endif /* CPU_40_STYLE */
+}
+
+
+// XMS BOP
+void MS_bop_2(void) {
+ XMSDispatch((ULONG)(*Sim32GetVDMPointer(SEGOFF(getCS(),getIP()),
+ 1,
+ FALSE
+ )));
+
+ setIP((USHORT)(getIP() + 1));
+}
+
+
+// DEBUGGING BOP
+void MS_bop_int3(void) {
+
+#ifndef PROD
+ force_yoda();
+#endif
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+// MONITOR DPMI BOP
+
+void MS_bop_3(void)
+{
+ IMPORT VOID DpmiDispatch(VOID);
+
+ DpmiDispatch();
+}
+
+// SCS BOP
+/* CMD dispatcher, this BOP will only work in real mode */
+
+void MS_bop_4(void)
+{
+ half_word Command;
+ IMPORT BOOL CmdDispatch(ULONG);
+
+ sas_load( ((ULONG)getCS()<<4) + getIP(), &Command);
+ CmdDispatch((ULONG) Command);
+ setIP((USHORT)(getIP() + 1));
+}
+
+
+//
+// MsBop6 - used to dispatch to debugger support functions
+//
+
+void MS_bop_6()
+{
+ IMPORT VOID DBGDispatch(VOID);
+ /*
+ ** All of the parameters for the debugger support
+ ** should be on the VDMs stack.
+ */
+ DBGDispatch();
+}
+
+//
+// DefaultVrInitialized - calls to VrInitialized (through a pointer to a routine)
+// will return FALSE until the VDMREDIR DLL has been successfully loaded and
+// initialized
+//
+
+ULONG DefaultVrInitialized(VOID);
+ULONG DefaultVrInitialized() {
+ return FALSE;
+}
+
+//
+// publicly accessible routine addresses. These are not expected to be called
+// until VrInitialized points at the real VrInitialized routine inside VdmRedir
+//
+
+#if DBG
+ULONG DefaultVrError(VOID);
+ULONG DefaultVrError() {
+ printf("MS_bop_7: Error: function called without VDMREDIR loaded!\n");
+ HostDebugBreak();
+ return 0;
+}
+MYFARPROC VrDispatch = &DefaultVrError;
+MYFARPROC VrInitialized = &DefaultVrInitialized;
+MYFARPROC VrReadNamedPipe = &DefaultVrError;
+MYFARPROC VrWriteNamedPipe = &DefaultVrError;
+MYFARPROC VrIsNamedPipeName = &DefaultVrError;
+MYFARPROC VrIsNamedPipeHandle = &DefaultVrError;
+MYFARPROC VrAddOpenNamedPipeInfo = &DefaultVrError;
+MYFARPROC VrConvertLocalNtPipeName = &DefaultVrError;
+MYFARPROC VrRemoveOpenNamedPipeInfo = &DefaultVrError;
+#else
+MYFARPROC VrDispatch;
+MYFARPROC VrInitialized = DefaultVrInitialized;
+MYFARPROC VrReadNamedPipe;
+MYFARPROC VrWriteNamedPipe;
+MYFARPROC VrIsNamedPipeName;
+MYFARPROC VrIsNamedPipeHandle;
+MYFARPROC VrAddOpenNamedPipeInfo;
+MYFARPROC VrConvertLocalNtPipeName;
+MYFARPROC VrRemoveOpenNamedPipeInfo;
+#endif
+
+BOOL LoadVdmRedir(VOID);
+
+VOID
+MS_bop_7(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Calls Vdm Redir Dispatcher. If the VDMREDIR DLL is not loaded, tries to
+ load it before calling Dispatcher. If the DLL could not be loaded (or
+ couldn't be loaded in the past) return an ERROR_INVALID_FUNCTION
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ static int VdmRedirLoadState = 0; // tristate:
+ // 0 = not loaded, first attempt
+ // 1 = loaded
+ // 2 = tried loading already, failed
+
+ //
+ // new: VdmRedir support is now a DLL. Try to load it. If it can't be loaded
+ // for whatever reason, return an error to the DOS program. Since it is
+ // trying to call a Redir function, we will return ERROR_INVALID_FUNCTION
+ //
+
+ switch (VdmRedirLoadState) {
+ case 0:
+
+ //
+ // the DLL is not yet loaded. If we can't load it and get the entry
+ // points for any reason, return ERROR_INVALID_FUNCTION. From now on,
+ // net support (including DLC, NetBIOS, named pipes and mailslots) will
+ // not be available to DOS programs in this session (running as part of
+ // this NTVDM process), but the rest of DOS functionality will be OK
+ //
+
+ if (LoadVdmRedir()) {
+ VdmRedirLoadState = 1;
+ } else {
+ VdmRedirLoadState = 2;
+ goto returnError;
+ }
+
+ //
+ // fall through to dispatcher in case 1
+ //
+
+ case 1:
+
+ //
+ // VdmRedir is loaded: do it
+ //
+
+ VrDispatch((ULONG)(*Sim32GetVDMPointer(SEGOFF(getCS(),getIP()),
+ 1,
+ (UCHAR)(getMSW() & MSW_PE ? TRUE : FALSE)
+ )));
+ break;
+
+ case 2:
+
+ //
+ // we tried to load VdmRedir once, but the wheels fell off, so we don't
+ // try it any more - just return an error, OK?
+ //
+
+returnError:
+ setCF(1);
+ setAX(ERROR_INVALID_FUNCTION);
+ break;
+
+#if DBG
+ default:
+ printf("MS_bop_7: BAD: VdmRedirLoadState=%d???\n", VdmRedirLoadState);
+#endif
+ }
+
+ //
+ // irrespective of whether the DLL is/was loaded or not, we must bump the
+ // VDM ip past the BOP
+ //
+
+ setIP((USHORT)(getIP() + 1));
+}
+
+HANDLE hVdmRedir;
+BOOL VdmRedirLoaded = FALSE;
+
+BOOL IsVdmRedirLoaded() {
+ return VdmRedirLoaded;
+}
+
+BOOL LoadVdmRedir() {
+
+#if DBG
+ LPSTR funcName = "";
+#endif
+
+ if (VdmRedirLoaded) {
+ return TRUE;
+ }
+ if (hVdmRedir = SafeLoadLibrary("VDMREDIR")) {
+
+ //
+ // get addresses of procedures called by functions in dos\dem\demfile.c
+ // and dos\dem\demhndl.c
+ //
+
+ if ((VrDispatch = (MYFARPROC)GetProcAddress(hVdmRedir, "VrDispatch")) == NULL) {
+#if DBG
+ funcName = "VrDispatch";
+#endif
+ goto closeAndReturnError;
+ }
+ if ((VrInitialized = (MYFARPROC)GetProcAddress(hVdmRedir, "VrInitialized")) == NULL) {
+#if DBG
+ funcName = "VrInitialized";
+#endif
+ goto closeAndReturnError;
+ }
+ if ((VrReadNamedPipe = (MYFARPROC)GetProcAddress(hVdmRedir, "VrReadNamedPipe")) == NULL) {
+#if DBG
+ funcName = "VrReadNamedPipe";
+#endif
+ goto closeAndReturnError;
+ }
+ if ((VrWriteNamedPipe = (MYFARPROC)GetProcAddress(hVdmRedir, "VrWriteNamedPipe")) == NULL) {
+#if DBG
+ funcName = "VrWriteNamedPipe";
+#endif
+ goto closeAndReturnError;
+ }
+ if ((VrIsNamedPipeName = (MYFARPROC)GetProcAddress(hVdmRedir, "VrIsNamedPipeName")) == NULL) {
+#if DBG
+ funcName = "VrIsNamedPipeName";
+#endif
+ goto closeAndReturnError;
+ }
+ if ((VrIsNamedPipeHandle = (MYFARPROC)GetProcAddress(hVdmRedir, "VrIsNamedPipeHandle")) == NULL) {
+#if DBG
+ funcName = "VrIsNamedPipeHandle";
+#endif
+ goto closeAndReturnError;
+ }
+ if ((VrAddOpenNamedPipeInfo = (MYFARPROC)GetProcAddress(hVdmRedir, "VrAddOpenNamedPipeInfo")) == NULL) {
+#if DBG
+ funcName = "VrAddOpenNamedPipeInfo";
+#endif
+ goto closeAndReturnError;
+ }
+ if ((VrConvertLocalNtPipeName = (MYFARPROC)GetProcAddress(hVdmRedir, "VrConvertLocalNtPipeName")) == NULL) {
+#if DBG
+ funcName = "VrConvertLocalNtPipeName";
+#endif
+ goto closeAndReturnError;
+ }
+ if ((VrRemoveOpenNamedPipeInfo = (MYFARPROC)GetProcAddress(hVdmRedir, "VrRemoveOpenNamedPipeInfo")) == NULL) {
+#if DBG
+ funcName = "VrRemoveOpenNamedPipeInfo";
+#endif
+ goto closeAndReturnError;
+ }
+ VdmRedirLoaded = TRUE;
+ return TRUE;
+ }
+
+closeAndReturnError:
+
+#if DBG
+ printf("MS_bop_7: Error: cannot locate entry point %s in VDMREDIR.DLL\n", funcName);
+#endif
+
+ CloseHandle(hVdmRedir);
+ return FALSE;
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::: More MS BOP stubs */
+
+void MS_bop_5(void)
+{
+ IMPORT VOID ms_bop(VOID);
+
+ ms_bop();
+}
+
+//
+// MS_BOP_8 : Third Party Bop
+//
+void ISV_RegisterModule (BOOL);
+void ISV_DeRegisterModule (void);
+void ISV_DispatchCall (void);
+
+void MS_bop_8 (void)
+{
+ ULONG iFunc;
+ UCHAR uchMode = getMSW() & MSW_PE ? TRUE : FALSE;
+
+
+ // Get the Function Number
+ iFunc = (ULONG)(*Sim32GetVDMPointer(SEGOFF(getCS(),getIP()),
+ 1,
+ uchMode
+ ));
+
+ switch (iFunc) {
+ case 0: /* RegisterModule */
+ ISV_RegisterModule (uchMode);
+ break;
+ case 1: /* DeRegisterModule */
+ ISV_DeRegisterModule ();
+ break;
+ case 2: /* DispatchCall */
+ ISV_DispatchCall ();
+ break;
+ default:
+ setCF(1);
+ }
+ setIP((USHORT)(getIP() + 1));
+ return;
+}
+
+
+//
+// MS_BOP_9 : Direct Access Error bop. An app has tried to do something
+// dubious. Tell the user about it. Picks up the type of the error from
+// AX.
+//
+void MS_bop_9(void)
+{
+ host_direct_access_error((ULONG)getAX());
+}
+
+//
+// MS_BOP_A : Idle control from VDD.
+// AX == 0: VDD wants VDM to idle. It will (briefly - 10ms) provided it
+// has not just seen some counter idle indication.
+// AX == 1: VDD wants VDM to wake up if still idling.
+//
+void MS_bop_A(void)
+{
+ word control;
+
+ control = getAX();
+
+ if (control == 0)
+ WaitIfIdle();
+ else
+ if (control == 1)
+ WakeUpNow();
+#ifndef PROD
+ else
+ printf("NTVDM:Idle control from VDD bop passed bad AX value (%d)\n", control);
+#endif
+}
+
+
+/*
+ * DbgBreakPoint Jonle
+ * A very simple way to break into the debugger from 16 bit
+ * Apps registers are unmodified
+ * Uses the safe DbgBreakPoint in ntvdm.c
+ * On a free build when we are not being debugged, nothing will happen.
+ * On a checked build when we are not being debugged, access violate
+ * With debugger running breaks into 32 bit debugger
+ */
+void MS_bop_B(void)
+{
+ OutputDebugString("NTVDM:BOP_DBGBREAKPOINT\n");
+ DbgBreakPoint();
+}
+
+
+//timing bop
+
+void MS_bop_C(void)
+{
+ illegal_bop();
+}
+
+
+/*:::::::::::::::::::::::::::::::::: This bop is used to control iret hooks */
+
+void MS_bop_D(void)
+{
+#ifdef MONITOR
+ extern VOID MonitorEndIretHook(VOID);
+ half_word iret_index;
+
+
+ // get iret index
+ iret_index = *Sim32GetVDMPointer(SEGOFF(getCS(),getIP()),
+ 1,
+ (UCHAR)(getPE() ? TRUE : FALSE)
+ );
+
+ // Tell ica that an iret bop has been called
+ ica_iret_hook_called((int) iret_index);
+
+ //
+ // Clean up stack, and resume normal code path
+ //
+ MonitorEndIretHook();
+#else
+ illegal_bop();
+#endif
+
+}
+
+// Notification bop
+// currently defined notification code is
+// 00 -- config.sys processing completed.
+//
+extern LARGE_INTEGER CounterStart, FrequenceStart;
+
+void MS_bop_E(void)
+{
+ unsigned char code;
+
+ code = getAL();
+ if (code == 0) {
+ UMBNotify(0);
+ demDasdInit();
+ }
+ else {
+#ifndef PROD
+ printf("Invalid notification bop\n");
+#endif
+ }
+}
+
+
+void MS_bop_F(void)
+{
+ extern void kb_setup_vectors(void);
+
+
+ kb_setup_vectors();
+
+
+#ifdef MONITOR
+
+ AddrIretBopTable = ( ((ULONG)getDS() << 16) | (ULONG)getDI() );
+
+#ifndef PROD
+ if (getCX() != VDM_RM_IRETBOPSIZE) {
+ OutputDebugString("NTVDM:spacing != VDM_RM_IRETBOPSIZE\n");
+ DebugBreak();
+ }
+#endif
+#endif
+
+ /*
+ * Now that spckbd is loaded, and the ivt rom vectors are hooked
+ * we can allow hw interrupts.
+ */
+ // nt_init_event_thread will resume the event thread after it
+ // sync up BIOS led states with the system
+ // ResumeThread(ThreadInfo.EventMgr.Handle);
+ host_ica_lock();
+ DelayIrqLine = 0;
+ if (!ica_restart_interrupts(ICA_SLAVE))
+ ica_restart_interrupts(ICA_MASTER);
+ host_ica_unlock();
+
+#ifdef MONITOR
+ setCF(1);
+#else
+ setCF(0);
+#endif
+}
+
+
+#define MAX_ISV_BOP 10
+
+typedef struct _ISVBOP {
+ FARPROC fpDispatch;
+ HANDLE hDll;
+} ISVBOP;
+
+#define MAX_PROC_NAME 64
+char procbuffer [MAX_PROC_NAME];
+
+ISVBOP isvbop_table [MAX_ISV_BOP];
+
+void ISV_RegisterModule (BOOL fMode)
+{
+ char *pchDll,*pchInit,*pchDispatch;
+ HANDLE hDll;
+ FARPROC DispatchEntry;
+ FARPROC InitEntry;
+ ULONG i;
+ UCHAR uchMode;
+
+ // Check if we have free space in bop table.
+ for (i=0; i<MAX_ISV_BOP; i++) {
+ if (isvbop_table[i].hDll == 0)
+ break;
+ }
+
+ if (i == MAX_ISV_BOP) {
+ setCF (1);
+ setAX(4);
+ return;
+ }
+
+ uchMode = fMode ? TRUE : FALSE;
+
+ pchDll = (PCHAR) Sim32GetVDMPointer (SEGOFF(getDS(),getSI()),
+ 1,
+ uchMode
+ );
+ if (pchDll == NULL) {
+ setCF (1);
+ setAX(1);
+ return;
+ }
+ pchInit = (PCHAR) Sim32GetVDMPointer(SEGOFF(getES(),getDI()),
+ 1,
+ uchMode
+ );
+
+ pchDispatch = (PCHAR) Sim32GetVDMPointer(SEGOFF(getDS(),getBX()),
+ 1,
+ uchMode
+ );
+ if (pchDispatch == NULL) {
+ setCF (1);
+ setAX(2);
+ return;
+ }
+
+ if ((hDll = SafeLoadLibrary(pchDll)) == NULL){
+ setCF (1);
+ setAX(1);
+ return;
+ }
+
+ // Get the init entry point and dispatch entry point
+ if (pchInit){
+ if ((ULONG)pchInit < 64*1024){
+ if (strlen (pchInit) >= MAX_PROC_NAME) {
+ FreeLibrary(hDll);
+ setCF (1);
+ setAX(4);
+ return;
+ }
+ strcpy (procbuffer,pchInit);
+ pchInit = procbuffer;
+ }
+
+ if ((InitEntry = (MYFARPROC)GetProcAddress(hDll, pchInit)) == NULL){
+ FreeLibrary(hDll);
+ setCF(1);
+ setAX(3);
+ return;
+ }
+ }
+
+ if ((ULONG)pchDispatch < 64*1024){
+ if (strlen (pchDispatch) >= MAX_PROC_NAME) {
+ FreeLibrary(hDll);
+ setCF (1);
+ setAX(4);
+ return;
+ }
+ strcpy (procbuffer,pchDispatch);
+ pchDispatch = procbuffer;
+ }
+
+ if ((DispatchEntry = (MYFARPROC)GetProcAddress(hDll, pchDispatch)) == NULL){
+ FreeLibrary(hDll);
+ setCF(1);
+ setAX(2);
+ return;
+ }
+
+ // Call the init routine
+ if (pchInit) {
+ (*InitEntry)();
+ }
+
+ // Fill up the bop table
+ isvbop_table[i].hDll = hDll;
+ isvbop_table[i].fpDispatch = DispatchEntry;
+
+ i++;
+
+ setAX((USHORT)i);
+
+ return;
+}
+
+void ISV_DeRegisterModule (void)
+{
+ ULONG Handle;
+ HANDLE hDll;
+
+ Handle = (ULONG)getAX();
+ if (Handle == 0 || Handle > MAX_ISV_BOP){
+#ifndef PROD
+ printf("Invalid BOP Handle Passed to DeRegisterModule");
+#endif
+ TerminateVDM();
+ return;
+ }
+ Handle--;
+ hDll = isvbop_table[Handle].hDll;
+ FreeLibrary (hDll);
+ isvbop_table[Handle].hDll = 0;
+ isvbop_table[Handle].fpDispatch = NULL;
+ return;
+}
+
+void ISV_DispatchCall (void)
+{
+ ULONG Handle;
+ FARPROC DispatchEntry;
+
+ Handle = (ULONG)getAX();
+ if (Handle == 0 || Handle > MAX_ISV_BOP){
+#ifndef PROD
+ printf("Invalid BOP Handle Passed to DispatchCall");
+#endif
+ TerminateVDM();
+ return;
+ }
+ Handle--;
+
+ DispatchEntry = isvbop_table[Handle].fpDispatch;
+ (*DispatchEntry)();
+ return;
+}
+
+#ifdef i386
+/*
+ * "Safe" version of LoadLibrary which preserves floating-point state
+ * across the load. This is critical on x86 because the FP state being
+ * preserved is the 16-bit app's state. MSVCRT.DLL is one offender which
+ * changes the Precision bits in its Dll init routine.
+ *
+ * On RISC, this is an alias for LoadLibrary
+ *
+ */
+HINSTANCE SafeLoadLibrary(char *name)
+{
+ HINSTANCE hInst;
+ BYTE FpuState[108];
+
+ // Save the 487 state
+ _asm {
+ lea ecx, [FpuState]
+ fsave [ecx]
+ }
+
+ hInst = LoadLibrary(name);
+
+ // Restore the 487 state
+ _asm {
+ lea ecx, [FpuState]
+ frstor [ecx]
+ }
+
+ return hInst;
+}
+#endif //i386
diff --git a/private/mvdm/softpc.new/host/src/nt_cga.c b/private/mvdm/softpc.new/host/src/nt_cga.c
new file mode 100644
index 000000000..512ee3ac8
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_cga.c
@@ -0,0 +1,1193 @@
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : Win32 CGA Graphics Module
+ *
+ * Description :
+ *
+ * This modules contain the Win32 specific functions required
+ * to support CGA emulations.
+ *
+ * Author : Jerry Sexton (based on module by John Shanly)
+ *
+ * Notes :
+ *
+ */
+
+#include <windows.h>
+#include <string.h>
+
+#include "insignia.h"
+#include "host_def.h"
+
+#include "xt.h"
+#include "gvi.h"
+#include "gmi.h"
+#include "sas.h"
+#include "gfx_upd.h"
+
+#include "error.h"
+#include <stdio.h>
+#include "trace.h"
+#include "debug.h"
+#include "config.h"
+#include "host_rrr.h"
+#include "conapi.h"
+
+#include "nt_graph.h"
+#include "nt_cga.h"
+#include "nt_cgalt.h"
+#include "nt_det.h"
+
+#ifdef MONITOR
+#include <ntddvdeo.h>
+#include "nt_fulsc.h"
+#endif /* MONITOR */
+
+/* Externs */
+
+
+extern char *image_buffer;
+
+/* Statics */
+
+static unsigned int cga_med_graph_hi_nyb[256];
+static unsigned int cga_med_graph_lo_nyb[256];
+#ifdef BIGWIN
+static unsigned int cga_med_graph_hi_lut_big[256];
+static unsigned int cga_med_graph_mid_lut_big[256];
+static unsigned int cga_med_graph_lo_lut_big[256];
+
+static unsigned int cga_med_graph_lut4_huge[256];
+static unsigned int cga_med_graph_lut3_huge[256];
+static unsigned int cga_med_graph_lut2_huge[256];
+static unsigned int cga_med_graph_lut1_huge[256];
+#endif
+
+/*
+ * cga_graph_inc_val depends on whether data is interleaved ( EGA/VGA )
+ * or not ( CGA ). Currently always interleaved.
+ */
+#define CGA_GRAPH_INCVAL 4
+
+// likewise for TEXT_INCVAL
+// for x86 we have 2 bytes per character (char and attr)
+// for risc we have 4 bytes per character because of vga interleaving
+//
+#ifdef MONITOR
+#define TEXT_INCVAL 2
+#else
+#define TEXT_INCVAL 4
+#endif
+
+
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Initialise CGA text output ::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_text()
+{
+ half_word misc;
+ IMPORT void vga_misc_inb(io_addr, half_word *);
+
+ /*::::::::::::::::::::::::::::::::::::: Tell trace program were we are */
+
+ sub_note_trace0(HERC_HOST_VERBOSE, "nt_init_text");
+
+#ifdef X86GFX
+if (sc.ScreenState == WINDOWED) //fullscreen valid - mouse buffer
+#endif //X86GFX
+ closeGraphicsBuffer(); /* Tim Oct 92 */
+
+#ifdef MONITOR
+ vga_misc_inb(0x3cc, &misc);
+ if (misc & 1)
+ set_screen_ptr((UTINY *)CGA_REGEN_BUFF); //point screen to regen not planes
+ else
+ set_screen_ptr((UTINY *)MDA_REGEN_BUFF); //0xb0000 not 0xb8000
+#endif //MONITOR
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Init CGA mono graph ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_cga_mono_graph()
+{
+ sub_note_trace0(CGA_HOST_VERBOSE,"nt_init_cga_mono_graph - NOT SUPPORTED");
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Init CGA colour med graphics:::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+void nt_init_cga_colour_med_graph()
+{
+ static boolean cga_colour_med_deja_vu = FALSE;
+ unsigned int i,
+ byte1,
+ byte2,
+ byte3,
+ byte4;
+
+ sub_note_trace0(CGA_HOST_VERBOSE, "nt_init_cga_colour_med_graph");
+
+ /* Set up bits-per-pixel for current mode. */
+ sc.BitsPerPixel = CGA_BITS_PER_PIXEL;
+
+ /* Initialise look-up table for first call. */
+ if( !cga_colour_med_deja_vu )
+ {
+ for (i = 0; i < 256; i++)
+ {
+ byte1 = i & 0x03;
+ byte2 = ( i & 0x0C ) >> 2;
+ byte3 = ( i & 0x30 ) >> 4;
+ byte4 = ( i & 0xC0 ) >> 6;
+
+#ifdef BIGEND
+ cga_med_graph_hi_nyb[i]
+ = ( byte4 << 24 ) | ( byte4 << 16)
+ | ( byte3 << 8 ) | byte3;
+ cga_med_graph_lo_nyb[i]
+ = ( byte2 << 24 ) | ( byte2 << 16)
+ | ( byte1 << 8 ) | byte1;
+
+#ifdef BIGWIN
+ cga_med_graph_hi_lut_big[i]
+ = ( byte4 << 24 ) | ( byte4 << 16)
+ | ( byte4 << 8 ) | byte3;
+ cga_med_graph_mid_lut_big[i]
+ = ( byte3 << 24) | ( byte3 << 16 )
+ | ( byte2 << 8 ) | byte2;
+ cga_med_graph_lo_lut_big[i]
+ = ( byte2 << 24 ) | ( byte1 << 16)
+ | ( byte1 << 8 ) | byte1;
+
+ cga_med_graph_lut4_huge[i]
+ = ( byte4 << 24 ) | ( byte4 << 16)
+ | ( byte4 << 8 ) | byte4;
+
+ cga_med_graph_lut3_huge[i]
+ = ( byte3 << 24 ) | ( byte3 << 16)
+ | ( byte3 << 8 ) | byte3;
+
+ cga_med_graph_lut2_huge[i]
+ = ( byte2 << 24 ) | ( byte2 << 16)
+ | ( byte2 << 8 ) | byte2;
+
+ cga_med_graph_lut1_huge[i]
+ = ( byte1 << 24 ) | ( byte1 << 16)
+ | ( byte1 << 8 ) | byte1;
+#endif /* BIGWIN */
+#endif /* BIGEND */
+
+#ifdef LITTLEND
+ cga_med_graph_hi_nyb[i]
+ = ( byte3 << 24 ) | ( byte3 << 16)
+ | ( byte4 << 8 ) | byte4;
+ cga_med_graph_lo_nyb[i]
+ = ( byte1 << 24 ) | ( byte1 << 16)
+ | ( byte2 << 8 ) | byte2;
+
+#ifdef BIGWIN
+ cga_med_graph_hi_lut_big[i]
+ = ( byte3 << 24 ) | ( byte4 << 16)
+ | ( byte4 << 8 ) | byte4;
+ cga_med_graph_mid_lut_big[i]
+ = ( byte2 << 24) | ( byte2 << 16 )
+ | ( byte3 << 8 ) | byte3;
+ cga_med_graph_lo_lut_big[i]
+ = ( byte1 << 24 ) | ( byte1 << 16)
+ | ( byte1 << 8 ) | byte2;
+
+ cga_med_graph_lut4_huge[i]
+ = ( byte4 << 24 ) | ( byte4 << 16)
+ | ( byte4 << 8 ) | byte4;
+
+ cga_med_graph_lut3_huge[i]
+ = ( byte3 << 24 ) | ( byte3 << 16)
+ | ( byte3 << 8 ) | byte3;
+
+ cga_med_graph_lut2_huge[i]
+ = ( byte2 << 24 ) | ( byte2 << 16)
+ | ( byte2 << 8 ) | byte2;
+
+ cga_med_graph_lut1_huge[i]
+ = ( byte1 << 24 ) | ( byte1 << 16)
+ | ( byte1 << 8 ) | byte1;
+#endif /* BIGWIN */
+#endif /* LITTLEND */
+
+ }
+
+ cga_colour_med_deja_vu = TRUE;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::: Init CGA colour hi graphics:::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+void nt_init_cga_colour_hi_graph()
+{
+ sub_note_trace0(CGA_HOST_VERBOSE,"nt_init_cga_colour_hi_graph");
+
+ /* Set up bits-per-pixel for current mode. */
+ sc.BitsPerPixel = MONO_BITS_PER_PIXEL;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::: Output CGA text :::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+IMPORT int now_height, now_width;
+
+void nt_text(int ScreenOffset, int ScreenX, int ScreenY,
+ int len, int height)
+{
+ int org_clen, org_height;
+ int clen=len/2;
+ int lines;
+ SMALL_RECT WriteRegion;
+ PBYTE to;
+ PBYTE pScreenText = get_screen_ptr(ScreenOffset);
+
+ /*:::::::::::::::::::::::::::::::::::::::::::: Output trace information */
+
+ sub_note_trace6( CGA_HOST_VERBOSE,
+ "nt_cga_text off=%d x=%d y=%d len=%d h=%d o=%#x",
+ ScreenOffset, ScreenX, ScreenY, len, height, pScreenText );
+
+ /*:::::::::::::: Adjust re-paint start location from pixels to characters */
+
+#ifndef MONITOR
+ /* Adjust for RISC parameters being in pixels */
+ ScreenX = ScreenX / get_pix_char_width();
+ ScreenY = ScreenY / get_host_char_height();
+#endif
+
+ /*:: Clip requested re-paint region to currently selected console buffer */
+
+ //Clip width
+ if(ScreenX + clen > now_width)
+ {
+ /* Is it possible to adjust the repaint regions width */
+ if(ScreenX+1 >= now_width)
+ {
+ assert4(NO,"VDM: nt_text() repaint region out of ranged x:%d y:%d w:%d h:%d\n",
+ ScreenX, ScreenY, clen, height);
+ return;
+ }
+
+ //Calculate maximum width
+ org_clen = clen;
+ clen = now_width - ScreenX;
+
+ assert2(NO,"VDM: nt_text() repaint region width clipped from %d to %d\n",
+ org_clen,clen);
+ }
+
+ //Clip height
+ if(ScreenY + height > now_height)
+ {
+ /* Is it possible to adjust the repaint regions height */
+ if(ScreenY+1 >= now_height)
+ {
+ assert4(NO,"VDM: nt_text() repaint region out of ranged x:%d y:%d w:%d h:%d\n",
+ ScreenX, ScreenY, clen, height);
+ return;
+ }
+
+ //Calculate maximum height
+ org_height = height;
+ height = now_height - ScreenY;
+
+ assert2(NO,"VDM: nt_text() repaint region height clipped from %d to %d\n",
+ org_height,clen);
+ }
+
+ if (get_chars_per_line() == 80)
+ {
+ //
+ // Slam Dunk Screen text buffer into shared buffer
+ // by copying full width blocks instead of subrecs.
+ //
+ RtlCopyMemory(&textBuffer[(ScreenY*get_offset_per_line()/2 + ScreenX)*TEXT_INCVAL],
+ pScreenText,
+ (((height - 1)*get_offset_per_line()/2) + clen)*TEXT_INCVAL
+ );
+ }
+ else
+ {
+ // the sharing buffer width never changes((80 chars, decided at the
+ // moment we make the RegisterConsoleVDM call to the console).
+ // We have to do some transformation when our screen width is not
+ // 80.
+
+ // note that the sharing buffer has different format on x86 and RISC
+ // platforms. On x86, a cell is defined as:
+ // typedef _x86cell {
+ // byte char;
+ // byte attributes;
+ // }
+ // on RISC, a cell is defined as:
+ // typedef _RISCcell {
+ // byte char;
+ // byte attributes;
+ // byte reserved_1;
+ // byte reserved_2;
+ // }
+ // the size of each cell was defined by TEXT_INCVAL
+ //
+ // this is done so we can use memcpy for each line.
+ //
+
+
+ /*::::::::::::::::::::::::::::::::::::::::::::: Construct output buffer */
+ //Start location of repaint region
+ to = &textBuffer[(ScreenY*80 + ScreenX) * TEXT_INCVAL];
+
+ for(lines = height; lines; lines--)
+ {
+ RtlCopyMemory(to, pScreenText, clen * TEXT_INCVAL); // copy this line
+ pScreenText += get_chars_per_line() * TEXT_INCVAL; // update src ptr
+ to += 80 * TEXT_INCVAL; // update dst ptr
+ }
+ }
+
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::: Calculate write region */
+
+ WriteRegion.Left = ScreenX;
+ WriteRegion.Top = ScreenY;
+
+ WriteRegion.Bottom = WriteRegion.Top + height - 1;
+ WriteRegion.Right = WriteRegion.Left + clen - 1;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::: Display characters */
+
+ sub_note_trace4( CGA_HOST_VERBOSE, "t=%d l=%d b=%d r=%d",
+ WriteRegion.Top, WriteRegion.Left,
+ WriteRegion.Bottom, WriteRegion.Right,
+ );
+
+ if(!InvalidateConsoleDIBits(sc.OutputHandle, &WriteRegion)){
+ /*
+ ** We get a rare failure here due to the WriteRegion
+ ** rectangle being bigger than the screen.
+ ** Dump out some values and see if it tells us anything.
+ ** Have also attempted to fix it by putting a delay between
+ ** the start of a register level mode change and window resize.
+ */
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ assert4( NO, "VDM: rectangle t:%d l:%d b:%d r:%d",
+ WriteRegion.Top, WriteRegion.Left,
+ WriteRegion.Bottom, WriteRegion.Right
+ );
+ assert2( NO, "VDM: bpl=%d sl=%d",
+ get_bytes_per_line(), get_screen_length() );
+ }
+
+} /* end of nt_text() */
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::: Paints CGA graphics for a mono monitor, in a standard window :::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_mono_graph_std(int offset, int screen_x, int screen_y,
+ int len, int height )
+{
+sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_mono_graph_std off=%d x=%d y=%d len=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, len, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::: Paints CGA graphics for a mono monitor, in a big window :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_mono_graph_big(int offset, int screen_x, int screen_y,
+ int len, int height)
+{
+sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_mono_graph_big off=%d x=%d y=%d len=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, len, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::: Paints CGA graphics for a mono monitor, in a huge window ::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_mono_graph_huge(int offset, int screen_x, int screen_y,
+ int len, int height)
+{
+sub_note_trace5( CGA_HOST_VERBOSE,
+ "nt_cga_mono_graph_huge off=%d x=%d y=%d len=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, len, height );
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Paints CGA medium res graphics for a colour monitor,in a standard window */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_colour_med_graph_std(int offset, int screen_x, int screen_y,
+ int len, int height)
+{
+ UTINY *intelmem_ptr;
+ ULONG *graph_ptr;
+ LONG local_len,
+ bytes_per_scanline,
+ longs_per_scanline;
+ ULONG inc;
+ SMALL_RECT rect;
+ static int rejections=0; /* Stop floods of rejected messages */
+
+ sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_colour_med_graph_std off=%d x=%d y=%d len=%d height=%d\n",
+ offset, screen_x, screen_y, len, height );
+
+ /*
+ ** Tim Jan 93, rapid mode changes cause mismatch between update and
+ ** paint rountines. Ignore paint request when invalid parameter
+ ** causes crash.
+ */
+ if( screen_y > 400 ){
+ assert1( NO, "VDM: med gfx std rejected y=%d\n", screen_y );
+ return;
+ }
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ if( rejections==0 ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ rejections = 1;
+ }
+ return;
+ }else{
+ rejections = 0;
+ }
+
+ /* Clip image to screen */
+ if(height > 1 || len > 80)
+ height = 1;
+ if (len>80)
+ len = 80;
+
+ /* Work out the width of a line (ie 640 pixels) in chars and ints. */
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+
+ /* Build up DIB. */
+ inc = offset & 1 ? 3 : 1;
+ intelmem_ptr = get_screen_ptr(offset);
+ graph_ptr = (ULONG *) ((UTINY *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y * bytes_per_scanline + screen_x));
+ local_len = len;
+ do
+ {
+ *(graph_ptr + longs_per_scanline) = *graph_ptr =
+ cga_med_graph_hi_nyb[*intelmem_ptr];
+ graph_ptr++;
+
+ *(graph_ptr + longs_per_scanline) = *graph_ptr =
+ cga_med_graph_lo_nyb[*intelmem_ptr];
+ graph_ptr++;
+
+ intelmem_ptr += inc;
+ inc ^= 2;
+ }
+ while( --local_len );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (len << 3) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ {
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:: Paints CGA medium res graphics for a colour monitor, in a big window ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_colour_med_graph_big(int offset, int screen_x, int screen_y,
+ int len, int height)
+{
+#ifdef BIGWIN
+ UTINY *intelmem_ptr;
+ ULONG *graph_ptr;
+ LONG local_len,
+ bytes_per_scanline,
+ longs_per_scanline;
+ ULONG inc;
+ SMALL_RECT rect;
+
+ sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_colour_med_graph_big off=%d x=%d y=%d len=%d height=%d\n",
+ offset, screen_x, screen_y, len, height);
+
+ /*
+ ** Tim Jan 93, rapid mode changes cause mismatch between update and
+ ** paint rountines. Ignore paint request when invalid parameter
+ ** causes crash.
+ */
+ if( screen_y > 400 ){
+ assert1( NO, "VDM: med gfx big rejected y=%d\n", screen_y );
+ return;
+ }
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* Clip to window */
+ height = 1;
+ if (len > 80)
+ len = 80;
+
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ inc = offset & 1 ? 3 : 1;
+ intelmem_ptr = get_screen_ptr(offset);
+ graph_ptr = (ULONG *) ((UTINY *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y * bytes_per_scanline + screen_x));
+ local_len = len;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ *(graph_ptr + 2 * longs_per_scanline) =
+ *(graph_ptr + longs_per_scanline) =
+ *graph_ptr =
+ cga_med_graph_hi_lut_big[*intelmem_ptr];
+ graph_ptr++;
+
+ *(graph_ptr + 2 * longs_per_scanline) =
+ *(graph_ptr + longs_per_scanline) =
+ *graph_ptr =
+ cga_med_graph_mid_lut_big[*intelmem_ptr];
+ graph_ptr++;
+
+ *(graph_ptr + 2 * longs_per_scanline) =
+ *(graph_ptr + longs_per_scanline) =
+ *graph_ptr =
+ cga_med_graph_lo_lut_big[*intelmem_ptr];
+ graph_ptr++;
+
+ intelmem_ptr += inc;
+ inc ^= 2;
+ }
+ while( --local_len );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(len << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*: Paints CGA medium res graphics for a colour monitor, in a huge window. :*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_colour_med_graph_huge(int offset, int screen_x, int screen_y,
+ int len, int height)
+{
+#ifdef BIGWIN
+ UTINY *intelmem_ptr;
+ ULONG *graph_ptr;
+ LONG local_len,
+ bytes_per_scanline,
+ longs_per_scanline;
+ ULONG inc;
+ SMALL_RECT rect;
+
+ sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_colour_med_graph_huge off=%d x=%d y=%d len=%d height=%d\n",
+ offset, screen_x, screen_y, len, height );
+
+ /*
+ ** Tim Jan 93, rapid mode changes cause mismatch between update and
+ ** paint rountines. Ignore paint request when invalid parameter
+ ** causes crash.
+ */
+ if( screen_y > 400 ){
+ assert1( NO, "VDM: med gfx huge rejected y=%d\n", screen_y );
+ return;
+ }
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* Clip to window */
+ height = 1;
+ if (len > 80)
+ len = 80;
+
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ inc = offset & 1 ? 3 : 1;
+ intelmem_ptr = get_screen_ptr(offset);
+ graph_ptr = (ULONG *) ((UTINY *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y * bytes_per_scanline + screen_x));
+ local_len = len;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ *(graph_ptr + 3 * longs_per_scanline) =
+ *(graph_ptr + 2 * longs_per_scanline) =
+ *(graph_ptr + longs_per_scanline) =
+ *graph_ptr = cga_med_graph_lut4_huge[*intelmem_ptr];
+ graph_ptr++;
+
+ *(graph_ptr + 3 * longs_per_scanline) =
+ *(graph_ptr + 2 * longs_per_scanline) =
+ *(graph_ptr + longs_per_scanline) =
+ *graph_ptr = cga_med_graph_lut3_huge[*intelmem_ptr];
+ graph_ptr++;
+
+ *(graph_ptr + 3 * longs_per_scanline) =
+ *(graph_ptr + 2 * longs_per_scanline) =
+ *(graph_ptr + longs_per_scanline) =
+ *graph_ptr = cga_med_graph_lut2_huge[*intelmem_ptr];
+ graph_ptr++;
+
+ *(graph_ptr + 3 * longs_per_scanline) =
+ *(graph_ptr + 2 * longs_per_scanline) =
+ *(graph_ptr + longs_per_scanline) =
+ *graph_ptr = cga_med_graph_lut1_huge[*intelmem_ptr];
+ graph_ptr++;
+
+ intelmem_ptr += inc;
+ inc ^= 2;
+ }
+ while(--local_len);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(len << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*: Paints CGA high res graphics for a colour monitor, in a standard window */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_colour_hi_graph_std(int offset, int screen_x, int screen_y,
+ int len, int height)
+{
+ register char *intelmem,
+ *bufptr;
+ register int i;
+ int bytes_per_scanline;
+ SMALL_RECT rect;
+ static int rejections=0; /* Stop floods of rejected messages */
+
+ sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_colour_hi_graph_std off=%d x=%d y=%d len=%d height=%d\n",
+ offset, screen_x, screen_y, len, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ if( rejections == 0 ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ rejections = 1;
+ }
+ return;
+ }else
+ rejections=0;
+
+ /* Clip to window */
+ height = 1;
+ if (len > 80)
+ len = 80;
+
+ /* Work out offset, in bytes, of pixel directly below current pixel. */
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /*
+ * Build up DIB data. In 200-line CGA mode, pixels are double height so
+ * one line of PC pixels is equivalent to two lines of host pixels.
+ * Note: `height' parameter is always 1 when this function is called so
+ * only 1 line at a time is updated.
+ */
+ intelmem = (char *) get_screen_ptr(offset);
+
+ bufptr = (char *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * bytes_per_scanline +
+ (screen_x >> 3);
+ for( i = len; i > 0; i-- )
+ {
+ *(bufptr + bytes_per_scanline) = *bufptr = *intelmem;
+ intelmem += CGA_GRAPH_INCVAL;
+ bufptr++;
+ }
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (len << 3) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Paints CGA high res graphics for a colour monitor, in a big window :::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_colour_hi_graph_big(int offset, int screen_x, int screen_y,
+ int len, int height)
+{
+#ifdef BIGWIN
+ register char *intelmem,
+ *bufptr;
+ register int i;
+ char *buffer;
+ int bytes_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_colour_hi_graph_big off=%d x=%d y=%d len=%d height=%d\n",
+ offset, screen_x, screen_y, len, height );
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* Clip to window */
+ height = 1;
+ if (len > 80)
+ len = 80;
+
+ /*
+ * In this mode each byte becomes 12 bits (1.5 screen size) so if screen_x
+ * is on an odd byte boundary the resulting bitmap starts on a half-byte
+ * boundary. To avoid this set screen_x to the previous even byte.
+ */
+ if (screen_x & 8)
+ {
+ screen_x -= 8;
+ offset -= CGA_GRAPH_INCVAL;
+ len++;
+ }
+
+ /* `len' must be even for `high_stretch3' to work. */
+ if (len & 1)
+ len++;
+
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ bufptr = buffer = (char *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y * bytes_per_scanline + (screen_x >> 3));
+ intelmem = (char *) get_screen_ptr(offset);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ for(i = len; i > 0; i--)
+ {
+ *bufptr = *intelmem;
+ intelmem += CGA_GRAPH_INCVAL;
+ bufptr++;
+ }
+
+ high_stretch3((unsigned char *) buffer, len);
+
+ memcpy(buffer + bytes_per_scanline, buffer, SCALE(len));
+ memcpy(buffer + 2 * bytes_per_scanline, buffer, SCALE(len));
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(len << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Paints CGA high res graphics for a colour monitor, in a huge window ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_colour_hi_graph_huge(int offset, int screen_x, int screen_y,
+ int len, int height )
+{
+#ifdef BIGWIN
+ register char *intelmem,
+ *bufptr;
+ char *buffer;
+ register int i;
+ int bytes_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_colour_hi_graph_huge off=%d x=%d y=%d len=%d height=%d\n",
+ offset, screen_x, screen_y, len, height );
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* Clip to window */
+ height = 1;
+ if (len > 80)
+ len = 80;
+
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ intelmem = (char *) get_screen_ptr(offset);
+ bufptr = buffer = (char *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y * bytes_per_scanline + (screen_x >> 3));
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ for( i = len; i > 0; i-- )
+ {
+ *bufptr = *intelmem;
+ intelmem += CGA_GRAPH_INCVAL;
+ bufptr++;
+ }
+
+ high_stretch4((unsigned char *) buffer, len);
+
+ memcpy(buffer + bytes_per_scanline, buffer, SCALE(len));
+ memcpy(buffer + 2 * bytes_per_scanline, buffer, SCALE(len));
+ memcpy(buffer + 3 * bytes_per_scanline, buffer, SCALE(len));
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(len << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+#ifdef MONITOR
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Paints CGA medium res graphics frozen window. */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_med_frozen_std(int offset, int screen_x, int screen_y, int len,
+ int height)
+{
+ UTINY *plane1_ptr,
+ *plane2_ptr,
+ data;
+ ULONG *graph_ptr,
+ longs_per_scanline,
+ local_len,
+ mem_x = screen_x >> 3,
+ mem_y = screen_y >> 1,
+ max_width = sc.PC_W_Width >> 3,
+ max_height = sc.PC_W_Height >> 1;
+ SMALL_RECT rect;
+
+ sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_med_frozen_std off=%d x=%d y=%d len=%d height=%d\n",
+ offset, screen_x, screen_y, len, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((mem_x >= max_width) || (mem_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_cga_med_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (mem_x + len > max_width)
+ len = max_width - mem_x;
+ if (mem_y + height > max_height)
+ height = max_height - mem_y;
+
+ /* Work out the width of a line (ie 640 pixels) in ints. */
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+
+ /* memory in this routine liable to be removed by fullscreen switch */
+ try
+ {
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Set up data pointers. */
+ graph_ptr = (ULONG *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * longs_per_scanline + (screen_x >> 2);
+ plane1_ptr = GET_OFFSET(Plane1Offset);
+ plane2_ptr = GET_OFFSET(Plane2Offset);
+
+ /* Each iteration of the loop processes 2 host bytes. */
+ local_len = len >> 1;
+
+ /* 'offset' is designed for interleaved planes. */
+ offset >>= 1;
+
+ /* 'height' is always 1 so copy a line to the bitmap. */
+ do
+ {
+ data = *(plane1_ptr + offset);
+ *(graph_ptr + longs_per_scanline) = *graph_ptr =
+ cga_med_graph_hi_nyb[data];
+ graph_ptr++;
+ *(graph_ptr + longs_per_scanline) = *graph_ptr =
+ cga_med_graph_lo_nyb[data];
+ graph_ptr++;
+ data = *(plane2_ptr + offset);
+ *(graph_ptr + longs_per_scanline) = *graph_ptr =
+ cga_med_graph_hi_nyb[data];
+ graph_ptr++;
+ *(graph_ptr + longs_per_scanline) = *graph_ptr =
+ cga_med_graph_lo_nyb[data];
+ graph_ptr++;
+ offset += 2;
+ }
+ while (--local_len);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (len << 3) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ {
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ }
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "Handled fault in nt_cga_med_frozen_std. fs switch?");
+ return;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Paints CGA high res graphics frozen window. */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_cga_hi_frozen_std(int offset, int screen_x, int screen_y, int len,
+ int height)
+{
+ UTINY *plane1_ptr,
+ *graph_ptr;
+ ULONG bytes_per_scanline,
+ local_len,
+ mem_x = screen_x >> 3,
+ mem_y = screen_y >> 1,
+ max_width = sc.PC_W_Width >> 3,
+ max_height = sc.PC_W_Height >> 1;
+ SMALL_RECT rect;
+
+ sub_note_trace5(CGA_HOST_VERBOSE,
+ "nt_cga_hi_frozen_std off=%d x=%d y=%d len=%d height=%d\n",
+ offset, screen_x, screen_y, len, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((mem_x >= max_width) || (mem_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_cga_hi_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (mem_x + len > max_width)
+ len = max_width - mem_x;
+ if (mem_y + height > max_height)
+ height = max_height - mem_y;
+
+ /* memory here liable to be removed by fullscreen switch */
+ try
+ {
+ /* Work out the width of a line (ie 640 pixels) in ints. */
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+
+ /* 'offset' is designed for interleaved planes. */
+ offset >>= 2;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Set up data pointers. */
+ graph_ptr = (UTINY *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * bytes_per_scanline + screen_x;
+ plane1_ptr = GET_OFFSET(Plane1Offset) + offset;
+
+ /* 'height' is always 1 so copy a line to the bitmap. */
+ local_len = len;
+ do
+ {
+ *(graph_ptr + bytes_per_scanline) = *graph_ptr = *plane1_ptr++;
+ graph_ptr++;
+ }
+ while (--local_len);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (len << 3) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ {
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ }
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "Handled fault in nt_ega_hi_frozen_std. fs switch?");
+ return;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Dummy paint routine for frozen screens. ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_dummy_frozen(int offset, int screen_x, int screen_y, int len,
+ int height)
+{
+ assert0(NO, "Frozen screen error - dummy paint routine called.");
+}
+#endif /* MONITOR */
diff --git a/private/mvdm/softpc.new/host/src/nt_com.c b/private/mvdm/softpc.new/host/src/nt_com.c
new file mode 100644
index 000000000..4900c27ca
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_com.c
@@ -0,0 +1,2206 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntddser.h>
+#include <windows.h>
+#include <vdm.h>
+#include "ptypes32.h"
+#include "insignia.h"
+#include "host_def.h"
+
+/*
+ * Ade Brownlow
+ * Wed Jul 10 91
+ *
+ * nt_com.c
+ *
+ *
+ */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */
+
+#include "xt.h"
+#include "rs232.h"
+#include "error.h"
+#include "config.h"
+#include "ica.h"
+#include "ios.h"
+#include "host_com.h"
+#include "host_trc.h"
+#include "debug.h"
+#include "idetect.h"
+#include "nt_com.h"
+
+#include <math.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <excpt.h>
+#include <nt_timer.h>
+#include <nt_eoi.h>
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::: Standard host com interface */
+
+GLOBAL void host_com_init(int);
+GLOBAL CPU void host_com_close IPT1(int, adapter);
+GLOBAL RXCPU VOID host_com_read IPT3(int, adapter, UTINY *, data, int *, error);
+GLOBAL RXCPU void host_com_write IPT2(int, adapter, char, data);
+GLOBAL void host_com_ioctl(int, int, long);
+GLOBAL void host_com_reset(int);
+
+GLOBAL void host_com_lock(int adapter);
+GLOBAL void host_com_unlock(int adapter);
+GLOBAL int host_com_open(int);
+
+#if 0
+GLOBAL boolean host_com_suspend(int adapter);
+GLOBAL boolean host_com_resume(int adapter);
+#endif
+
+/* autoflush stub */
+GLOBAL void host_setup_aflush (int);
+GLOBAL DWORD nt_poll_comms(DWORD);
+DWORD PollCommsThread(PVOID pv);
+
+/*:::::::::::::::::::::::::::::: TX flush and control functions and defines */
+
+#define TX_MAX_BUFFER (200)
+#define TX_SCALING_TRIGGER (2)
+
+typedef enum { XOFF_TRIGGER, TIMER_TRIGGER, TXFULL_TRIGGER, CLOSE_TRIGGER } FLUSHTYPE;
+
+/*::::::::::::::::::::::::::::::::::::::::: Local adaptor control structure */
+
+#define MAX_PENDING_WRITES (3)
+// this is the buffer size we ask the serial driver to allocate
+// for its isr buffer(nopaged pool with quota). TonyE said it is no harm
+// to give it a bigger one(a big smile, eh). 4KB already gave us lots
+// of trouble, especially, on a slow machine.
+#define INPUT_QUEUE_SIZE (8*1024)
+#define OUTPUT_QUEUE_SIZE 100
+
+// this is the buffer size we use to receive rx data from serial driver
+// it should be big enough to prevent the serial driver from overflowing its
+// ISR buffer. The speed we delivery rx data to the application can not
+// keep up with the speed that serial driver can handle.
+
+#define BUFFER_SIZE INPUT_QUEUE_SIZE *2
+
+
+// this is the max number of chars we delivery to the application
+// before the CPU thread gives the RX thread a taste of CPU.
+// Too small, we waste too much time doing context switching and deliverying
+// too many unnecessary rda interrupts to some smart application ISR,
+// thus, reduce the overall throughput. Too big, we choke the application
+// (because we immediately delivery another rda interrupt to the
+// application as soon as the application IRET).
+// Application RX buffer size can be anywhere and depends how smart the
+// appllication ISR is, we may make the application really angry.
+// Some application ISR read LSR register after it gets the first char
+// and if the LSR indicates that there is another bytes ready,
+// it reads it immediately without waiting for the other int.
+// Some application set the IER after EOI an RDA int and expects
+// another interrupt.
+#define DEFAULT_RXWINDOW_SIZE 256
+
+
+#define ADAPTER_NULL 0 /* NULL device (/dev/null) */
+#define ADAPTER_REAL 1 /* Real comm port device */
+#define ADAPTER_SUSPENDED 2 /* Real device suspended */
+
+typedef struct _COM_STATES {
+ UCHAR Break;
+ UCHAR DTR;
+ UCHAR RTS;
+ UCHAR Parity;
+ UCHAR StopBits;
+ UCHAR DataBits;
+ DWORD BaudRate;
+}COM_STATES, *PCOM_STATES;
+
+
+#define ESCAPECHAR ((UCHAR)(-1))
+typedef struct _host_com
+{
+ HANDLE handle; /* Device handle */
+ int type; /* hopefully NULL or a device */
+ BOOL rx;
+ BOOL dcbValid; /* TRUE if dcbBeforeOpen contains a valid DCB */
+ DCB dcbBeforeOpen; /* device control block before open*/
+ DWORD modem_status; /* modem status line settings */
+ HANDLE ModemEvent; /* Get modem status control event */
+
+ int controller; /* ICA control used */
+ int line; /* ICA line */
+
+ /*..................................... Error display control variables */
+
+ BOOL DisplayError; /* Enabled/Disabled */
+
+ /*......................................... RX buffer control variables */
+ UCHAR * buffer; /* rx buffer */
+ int head_inx; /* Next place to add char to */
+ int tail_inx; /* Next place to remove char from */
+ int bytes_in_rxbuf; /* Number of bytes in buffer */
+ int rxwindow_size; /* rx buffer sliding window size */
+ int bytes_in_rxwindow; /* bytes in the rx window */
+ int EscapeCount;
+ int EscapeType;
+
+ BOOL CharReadFromUART;
+ int RXFlushTrigger;
+
+ HANDLE RXControlObject;
+ DWORD SignalRXThread;
+
+ /*......................................... TX buffer control variables */
+
+ unsigned char TXBuffer[TX_MAX_BUFFER];
+ int no_tx_chars; /* Chars in tx buffer */
+ int tx_threshold; /* Current flush threshold */
+ int max_tx_threshold; /* Max flush threshold */
+
+ int tx_flush_count; /* No. of flushs of below size */
+ int tx_heart_beat_count;
+ int tx_timer_flush_count; /* Consecutive timer flush counts */
+ int todate_timer_flush_total;
+
+ OVERLAPPED DWOV[MAX_PENDING_WRITES];/* Delayed writes */
+ int DWOVInx; /* Delayed writes index */
+
+ /*.............................................. Access control objects */
+
+ CRITICAL_SECTION CSEvent; /* Used to control access to above */
+ CRITICAL_SECTION AdapterLock;
+ int AdapterLockCnt; /* Adapter lock count */
+
+ volatile BOOL TerminateRXThread;
+
+ int ReOpenCounter; /* Counter to prevent to many open attempts */
+ int RX_in_Control;
+
+ /*.......................................... XON/XOFF control variables */
+
+ HANDLE XOFFEvent; /* XOFF ioctl competion event */
+ BOOL XOFFInProgress; /* XOFF currently in progress */
+
+ void *firstStatusBlock; /* first block in IO status block linked list */
+ void *lastStatusBlock; /* last block in IO staus block linked list */
+
+ /*...................................... Overlapped I/O control handles */
+
+ HANDLE RXEvent; /* Overlapped read complete event */
+ HANDLE TXEvent[MAX_PENDING_WRITES]; /* Overlapped write complete event */
+
+ HANDLE EvtHandle; /* Used by WaitCommEvent */
+
+ /*............................................. RX thread handle and ID */
+
+ DWORD RXThreadID; /* RX thread ID */
+ HANDLE RXThreadHandle; /* RX thread handle */
+ COM_STATES ComStates; /* Com device states as we know it */
+ int SuspendTimeoutTicks; /* auto close ticks setting */
+ int SuspendTickCounter; /* auto close tick counter */
+ BOOL SyncWrite; /* TRUE if we should write data synchrounously */
+ BOOL Suspended; /* TRUE if the port has been suspended */
+ BOOL Suspending; /* TRUE when the port is being suspended */
+ DWORD TickCount;
+
+} HOST_COM, *PHOST_COM;
+
+#define BUMP_TAIL_INX(t,c) (c)--;if(++(t) == BUFFER_SIZE) (t) = 0;
+
+typedef enum { RXCHAR, CHARINERROR, RXERROR, MODEMSTATE, RXBUFEMPTY, UNKNOWN} RXBUFCHARTYPE;
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::: Local function protocols */
+
+DWORD GetCharsFromDriver(int adaptor);
+void RX GetErrorFromDriver(int adapter);
+CPU int SendXOFFIoctlToDriver(int adapter);
+
+DWORD ReadWaitTimeOut(int adapter);
+int MapHostToBaseError(UCHAR host_error);
+
+void RX WaitForAllXOFFsToComplete(int adapter);
+BOOL RX RemoveCompletedXOFFs(int adapter);
+void SendDataToDriver(int adatper, char data);
+
+void CPU FlushTXBuffer(int adapter, FLUSHTYPE FlushReason);
+void ScaleTXThreshold(register HOST_COM *current, FLUSHTYPE FlushReason);
+
+GLOBAL void host_com_EOI_hook(long adapter);
+GLOBAL void CPU host_com_poll(int adapter);
+
+RXBUFCHARTYPE GetCharacterTypeInBuffer(register HOST_COM *current);
+void CPU EmptyRXBuffer(int adapter);
+void GetCharFromRXBuffer(HOST_COM *current, RXBUFCHARTYPE type,
+ UCHAR *data, UCHAR *error);
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: LOCAL DATA */
+
+LOCAL HOST_COM host_com[4]; /* 4 comm ports - the insignia MAX */
+
+LOCAL PHOST_COM host_com_ptr[4] = { &host_com[0], &host_com[1],&host_com[2],
+ &host_com[3]};
+
+LOCAL int disable_open[4] = { FALSE, FALSE, FALSE, FALSE };
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Local defines */
+
+#define CURRENT_ADAPTER() register HOST_COM *current = host_com_ptr[adapter]
+
+#define EV_MODEM (EV_CTS | EV_DSR | EV_RING | EV_RLSD)
+//#define EV_MODEM (EV_DSR | EV_RING | EV_RLSD)
+
+#define XON_CHARACTER (17) /* XON character, Cntrl-Q */
+#define XOFF_CHARACTER (19) /* XOFF character, Cntrl-S */
+#define XOFF_TIMEOUT (2*1000) /* Timeout in milliseconds */
+#define XOFF_RXCHARCNT (5) /* RX character count */
+
+#define REOPEN_DELAY (36) /* Reopen delay in 55ms (2 secs) */
+#define RXFLUSHTRIGGER (36) /* RX flush trigger (2 secs), if a
+ character is not read from the
+ UART within this time the RX buffer
+ is flushed */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Init comms system ::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+#include "error.h"
+#include "host_rrr.h"
+#include "nt_uis.h"
+
+
+GLOBAL CPU void host_com_init IFN1(int, adapter)
+{
+ UNUSED(adapter);
+
+ // Comms ports are only opened when they are accessed.
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Disable Open :::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+//This is called at the start of the adapter init code to prevent the comm
+//port being opened during com_init()
+
+void host_com_disable_open IFN2(int, adapter, int, DisableOpen)
+{
+ disable_open[adapter] = DisableOpen;
+}
+
+
+#ifdef NTVDM
+boolean host_com_check_adapter(int adapter)
+{
+ CURRENT_ADAPTER();
+ return (current->type == ADAPTER_REAL);
+
+}
+#endif
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Open comms port ::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Called first time port is written to ! */
+
+GLOBAL CPU int host_com_open(int adapter)
+{
+ COMMTIMEOUTS comout; /* Comm port time out settings */
+ DIVISOR_LATCH divisor_latch; /* Current latch settings */
+ LINE_CONTROL_REG LCR_reg; /* Current LCR status */
+ int i;
+ DCB LocalDCB;
+ ConfigValues ComConfigValues;
+
+ CURRENT_ADAPTER(); /* Define and setup pointer to adapter */
+
+ /*:::::::::::::::::::::::::::::::::::::::::: Is the port already open ? */
+
+ if(current->type == ADAPTER_REAL)
+ return(TRUE); /* Exit port already open */
+
+ /*::::::::::: Attempting to open the port to soon after a failed open ? */
+
+ if(current->ReOpenCounter || disable_open[adapter])
+ return(FALSE); /* Yes */
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+ always_trace1("HOST_COM_OPEN adapter= %d\n", adapter);
+
+ /*::::::::::::::::::::::::::::::::::::::::::::: Check for a NULL device */
+
+ if(adapter > 3 || adapter < 0)
+ {
+ current->type = ADAPTER_NULL;
+ current->ReOpenCounter = REOPEN_DELAY; /* Delay next open attempt */
+ return(FALSE); /* Open attempt failed */
+ }
+
+ /*::::::::::::::::::::::::::: We have a vaild adapter so try to open it */
+ config_inquire((UTINY)(C_COM1_NAME + adapter),
+ &ComConfigValues);
+ current->handle = CreateFile(ComConfigValues.string,
+ GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
+ NULL);
+
+ /*............................................... Validate open attempt */
+
+ if(current->handle == (HANDLE) -1)
+ {
+ always_trace1("Cannot open comms port '%s'\n",
+ (CHAR*) config_inquire((UTINY)(C_COM1_NAME+adapter),NULL));
+
+ if(current->DisplayError) {
+ RcErrorBoxPrintf(EHS_ERR_OPENING_COM_PORT,
+ (CHAR*) config_inquire((UTINY)(C_COM1_NAME+adapter),NULL));
+ current->DisplayError = FALSE; //Error only display once per session
+ }
+
+ current->ReOpenCounter = REOPEN_DELAY; /* Delay next open attempt */
+ current->type = ADAPTER_NULL; /* Unable to open adapter */
+ return(FALSE);
+ }
+
+
+ /* allocate rx buffer and initialize rx queue size */
+
+ current->buffer = (UCHAR *) malloc(BUFFER_SIZE);
+ if (current->buffer == NULL) {
+ CloseHandle(current->handle);
+ current->type = ADAPTER_NULL;
+ return FALSE;
+ }
+ current->rxwindow_size = DEFAULT_RXWINDOW_SIZE;
+ current->bytes_in_rxwindow = 0;
+ current->SyncWrite = (BOOL)config_inquire(C_COM_SYNCWRITE, NULL);
+ /*:: Find out which ICA controller and line are used by this comms port */
+
+ com_int_data(adapter, &current->controller, &current->line);
+
+ /*::::::::::::::::::::::::::::::: Enable IRET hooks for comms interrupt */
+
+#ifdef MONITOR
+ ica_iret_hook_control(current->controller, current->line, TRUE);
+#endif
+
+ /*:::::::::::::::::::::: Create objects used to control comms activity */
+
+ current->ModemEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+ current->RXControlObject = CreateEvent(NULL,FALSE,FALSE,NULL);
+ current->RXEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+ current->EvtHandle = CreateEvent(NULL,TRUE,FALSE,NULL);
+ current->DWOVInx = 0;
+
+ //Create objects used to control multipe overlapping writes
+ for(i=0; i < MAX_PENDING_WRITES; i++)
+ {
+ //Objects must be created in the signalled state for the closedown
+ //routine to function correctly
+
+ current->TXEvent[i] = CreateEvent(NULL,TRUE,TRUE,NULL);
+ current->DWOV[i].hEvent = NULL;
+ }
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::: Empty RX/TX buffers */
+
+ current->head_inx = current->tail_inx = 0;
+ current->EscapeCount = current->bytes_in_rxbuf = current->no_tx_chars = 0;
+
+ current->CharReadFromUART = FALSE;
+ current->RXFlushTrigger = RXFLUSHTRIGGER;
+ current->RX_in_Control = TRUE;
+ current->SignalRXThread = (DWORD) 0;
+ /*:::::::::::::::::::::::::::::::::::::::::::: Get TX buffer thresholds */
+
+ current->max_tx_threshold = (short)config_inquire(C_COM_TXBUFFER_SIZE, NULL);
+ if (!current->max_tx_threshold || current->max_tx_threshold > TX_MAX_BUFFER)
+ current->max_tx_threshold = TX_MAX_BUFFER;
+
+ //Setup other delayed write control variables
+ if (current->max_tx_threshold == 1)
+ current->tx_threshold = 0;
+ current->tx_flush_count = 0; // No. of flushs of below size
+ /*::::::::::::::::::::::::::: Extended control variables used by adaper */
+
+ current->type = ADAPTER_REAL; /* Adapter type */
+ current->TerminateRXThread = FALSE; /* RX thread termination flag */
+
+ /*:::::::::::::::::::::::::::::::: Initialise the XOFF control varibles */
+
+ current->XOFFInProgress = FALSE;
+ current->XOFFEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+ current->firstStatusBlock = current->lastStatusBlock = NULL;
+
+ /*:::: Init critical sections used to sync access to host functions, data */
+
+ /* critical section used to control access to adapters data structure */
+ InitializeCriticalSection(&current->CSEvent);
+
+ /* critical section used to lock access to adapter from the base */
+ InitializeCriticalSection(&current->AdapterLock);
+ current->AdapterLockCnt = 0;
+
+ /* NULL thread handle because host_com_close() may be called before
+ the comms RX thread is created */
+
+ current->RXThreadHandle = NULL;
+ current->dcbValid = FALSE;
+ /*::::::::::::::::::::::::::::::::::::::: Set Comms port to binary mode */
+
+ if(!GetCommState(current->handle, &(current->dcbBeforeOpen)))
+ {
+ always_trace0("ntvdm : GetCommState failed on open\n");
+ host_com_close(adapter); /* turn it into a NULL adapter */
+ current->ReOpenCounter = REOPEN_DELAY; /* Delay next open attempt */
+ return(FALSE);
+ }
+
+ current->dcbValid = TRUE;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Setup DCB */
+
+
+ /* we make a local copy of DCB because we have to reset the DCB
+ * to whatever it was before we opened it. This function is the only place
+ * we ever touch DCB.
+ */
+
+ LocalDCB = current->dcbBeforeOpen;
+ LocalDCB.fBinary = 1; /* Run in RAW mode */
+ LocalDCB.fOutxCtsFlow = FALSE; /* Disable CTS */
+ LocalDCB.fOutxDsrFlow = FALSE; /* Disable DSR */
+ LocalDCB.fDtrControl = DTR_CONTROL_DISABLE;
+ LocalDCB.fOutX = FALSE; /* Disable XON/XOFF */
+ LocalDCB.fInX = FALSE;
+ LocalDCB.fRtsControl = RTS_CONTROL_DISABLE;
+
+ LocalDCB.XonChar = XON_CHARACTER; /* Define XON/XOFF chars */
+ LocalDCB.XoffChar = XOFF_CHARACTER;
+ LocalDCB.fErrorChar = FALSE; /* Turn off error char replacement */
+ /* if we are resuming the device, initialize DCB parameters to
+ * what they were before suspended
+ */
+ if (current->Suspended) {
+ LocalDCB.BaudRate = current->ComStates.BaudRate;
+ LocalDCB.Parity = current->ComStates.Parity;
+ LocalDCB.StopBits = current->ComStates.StopBits;
+ LocalDCB.ByteSize = current->ComStates.DataBits;
+ LocalDCB.fParity = (LocalDCB.Parity == NOPARITY);
+ }
+ /* initialize the ComStates by copying data from DCB */
+ else {
+ current->ComStates.BaudRate = current->dcbBeforeOpen.BaudRate;
+ current->ComStates.Parity = current->dcbBeforeOpen.Parity;
+ current->ComStates.StopBits = current->dcbBeforeOpen.StopBits;
+ current->ComStates.DataBits = current->dcbBeforeOpen.ByteSize;
+ current->ComStates.Break = 0;
+ }
+ ASSERT(LocalDCB.BaudRate != 0);
+
+ /*::::::::::::::::::::::::::::::::::: Sync base to current line settings */
+
+ if(!SyncLineSettings(NULL, &(LocalDCB), &divisor_latch, &LCR_reg))
+ {
+ always_trace0("ntvdm : Unable to sync line states\n");
+
+ host_com_close(adapter);
+ current->ReOpenCounter = REOPEN_DELAY; /* Delay next open attempt */
+ return(FALSE);
+ }
+
+ SyncBaseLineSettings(adapter,&divisor_latch, &LCR_reg);
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::: Set Comms port state */
+
+ if(!SetCommState(current->handle, &(LocalDCB)))
+ {
+ always_trace0("ntvdm : SetCommState failed on open\n");
+
+ host_com_close(adapter);
+ current->ReOpenCounter = REOPEN_DELAY; /* Delay next open attempt */
+ return(FALSE);
+ }
+
+ /*::::::::::::::::::::: Put the driver into streaming MSR,LSR, RX mode */
+
+ if(!EnableMSRLSRRXmode(current->handle, current->ModemEvent,
+ (unsigned char) ESCAPECHAR))
+ {
+ always_trace0("ntvdm : GetCommState failed on open\n");
+ host_com_close(adapter); /* turn it into a NULL adapter */
+ current->ReOpenCounter = REOPEN_DELAY; /* Delay next open attempt */
+ return(FALSE);
+ }
+
+ /*::::::::::::::::::::::::::::::::::::::::: Setup comm port queue sizes */
+
+ if(!SetupComm(current->handle,INPUT_QUEUE_SIZE,OUTPUT_QUEUE_SIZE))
+ {
+ always_trace1("ntvdm : SetupComm failed, %d\n",GetLastError());
+
+ host_com_close(adapter);
+ current->ReOpenCounter = REOPEN_DELAY; /* Delay next open attempt */
+ return(FALSE);
+ }
+
+ /*::::::::::::::::::::: Set communication port up for non-blocking read */
+
+ GetCommTimeouts(current->handle,&comout);
+
+ comout.ReadIntervalTimeout = (DWORD) -1;
+ comout.ReadTotalTimeoutMultiplier = 0;
+ comout.ReadTotalTimeoutConstant = 0;
+
+ SetCommTimeouts(current->handle,&comout);
+
+ /* restore device states in case of resume */
+ if (current->Suspended) {
+ /* break line */
+ if (current->ComStates.Break)
+ SetCommBreak(current->handle);
+ else
+ ClearCommBreak(current->handle);
+ /* Data Terminal Ready line */
+ if (current->ComStates.DTR)
+ EscapeCommFunction(current->handle, SETDTR);
+ else
+ EscapeCommFunction(current->handle, CLRDTR);
+ /* Request To Send line */
+ if (current->ComStates.RTS)
+ EscapeCommFunction(current->handle, SETRTS);
+ else
+ EscapeCommFunction(current->handle, CLRRTS);
+
+ /* parity, stop bits and data bits */
+ FastCommSetLineControl(current->handle,
+ current->ComStates.StopBits,
+ current->ComStates.Parity,
+ current->ComStates.DataBits
+ );
+ /* baud rate */
+ FastCommSetBaudRate(current->handle, current->ComStates.BaudRate);
+
+ /* we are no longer in suspended state */
+ current->Suspended = FALSE;
+
+ }
+ else {
+ /*::::::::::::::::::::::::::::::::::::::::::::: Setup RTS and DTR states */
+ setup_RTSDTR(adapter);
+ }
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::: Create Comms RX thread */
+
+ if(!(current->RXThreadHandle = CreateThread(NULL,
+ 8192,
+ PollCommsThread,
+ (LPVOID)adapter,
+ 0,
+ &current->RXThreadID)))
+ {
+ always_trace1("ntvdm : Failed comms thread for %d\n", adapter);
+ host_com_close(adapter); /* Unable to create RX thread */
+ current->ReOpenCounter = REOPEN_DELAY; /* Delay next open attempt */
+ return(FALSE);
+ }
+ /* reset the counter */
+ current->SuspendTimeoutTicks = ComConfigValues.index * 1000;
+ current->SuspendTickCounter = current->SuspendTimeoutTicks;
+ current->TickCount = 0;
+ return(TRUE);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::: Close all open comms ports :::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL CPU void host_com_close_all(void)
+{
+ int adapter;
+
+ for(adapter = 0; adapter < 4; adapter++)
+ {
+ host_com[adapter].DisplayError = TRUE; //Enable error displaying
+ host_com_close(adapter);
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::: Close comms port ::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL CPU void host_com_close IFN1(int, adapter)
+{
+ CURRENT_ADAPTER();
+ int i;
+
+ /*:::::::::::::::::::::::::::::::::::::::: Dealing with NULL adapter ? */
+
+ if(current->type != ADAPTER_NULL)
+ {
+ always_trace1("Closing comms port %d\n",adapter);
+
+ /* only touch the device if we own the device */
+ if (current->type == ADAPTER_REAL) {
+ /*....... Flush any delayed writes and wait for writes to complete */
+ if (current->no_tx_chars)
+ FlushTXBuffer(adapter,CLOSE_TRIGGER);
+ WaitForMultipleObjects(MAX_PENDING_WRITES,current->TXEvent,TRUE,INFINITE);
+ /* reset DCB to whatever it was before open */
+ if (current->dcbValid) {
+ SetCommState(current->handle, &current->dcbBeforeOpen);
+ current->dcbValid = FALSE;
+ }
+
+ }
+
+
+ /* keep the base adapter states intact if we are suspending the device */
+ if (!current->Suspending)
+ /*........................................ Reset base comms adatper */
+ com_init(adapter); /* Initialise base comms adapter */
+
+ /*................................................. Close RX thread */
+
+ if(current->RXThreadHandle)
+ {
+ /*................................. Tell RX thread to terminate */
+
+ current->TerminateRXThread = TRUE; // Tell RX thread to terminate
+ current->RX_in_Control = TRUE;
+ SetEvent(current->RXControlObject);
+
+ /* Wait for RX thread to close itself, max wait 30 seconds */
+
+ WaitForSingleObject(current->RXThreadHandle,30000);
+ CloseHandle(current->RXThreadHandle);
+
+ current->RXThreadHandle = NULL; // Mark thread as closed
+ }
+ /* now it is safe to close the device */
+ CloseHandle(current->handle); current->handle = NULL;
+
+ /*............... Delete RX critical section and RX control objects */
+
+ DeleteCriticalSection(&current->CSEvent);
+ DeleteCriticalSection(&current->AdapterLock);
+
+ /*............................................. Close event objects */
+
+ CloseHandle(current->ModemEvent);
+ CloseHandle(current->RXControlObject);
+ CloseHandle(current->RXEvent); // Overlapped read wait object
+ for(i=0; i < MAX_PENDING_WRITES; i++)
+ {
+ CloseHandle(current->TXEvent[i]); // Overlapped write wait object
+ current->TXEvent[i] = NULL;
+ }
+
+ CloseHandle(current->EvtHandle); // WaitCommEvent wait object
+ CloseHandle(current->XOFFEvent);
+
+ current->XOFFEvent = current->RXEvent = current->EvtHandle = NULL;
+
+ /*.......................... Disable IRET hooks for comms interrupt */
+
+#ifdef MONITOR
+ ica_iret_hook_control(current->controller, current->line, FALSE);
+#endif
+
+ /*. This makes sure that the next access to the port will reopen it */
+ current->ReOpenCounter = 0;
+
+ free(current->buffer);
+ current->buffer = NULL;
+ current->type = ADAPTER_NULL; /* Mark adapter as closed */
+ }
+ else if (current->Suspended) {
+ /* the application is terminating while the port is suspended.
+ * first we turn the disable-open on so that we will not try
+ * to physical touch the port. Then we call base to reset the
+ * adapter
+ */
+
+ BOOL DisableOpen;
+ DisableOpen = disable_open[adapter];
+ disable_open[adapter] = TRUE;
+ com_init(adapter);
+ disable_open[adapter] = DisableOpen;
+ current->Suspended = FALSE;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::: Request from base for character :::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+#ifdef FIFO_ON
+GLOBAL CPU UTINY host_com_read_char( int adapter, FIFORXDATA * buffer, UTINY count)
+{
+ CURRENT_ADAPTER();
+ UCHAR host_error;
+ RXBUFCHARTYPE CharType;
+ UTINY RetCount = count;
+ /* if xoff is in progress, don't read nothing */
+ if (!current->XOFFInProgress) {
+ while (count) {
+ CharType = GetCharacterTypeInBuffer(current);
+ if (CharType == RXCHAR || CharType == CHARINERROR) {
+ buffer->error = 0;
+ GetCharFromRXBuffer(current, CharType, &buffer->data, &host_error);
+ if (!host_error)
+ buffer->error = MapHostToBaseError(host_error);
+ buffer++;
+ count--;
+ }
+ else
+ break;
+ }
+ }
+ /* Tell comms idle system that there has been comms activity */
+ IDLE_comlpt();
+ current->SuspendTickCounter = current->SuspendTimeoutTicks;
+ return (RetCount - count);
+
+}
+GLOBAL CPU void host_com_fifo_char_read(int adapter)
+{
+ CURRENT_ADAPTER();
+ current->CharReadFromUART = TRUE;
+}
+#endif
+
+GLOBAL RXCPU VOID host_com_read IFN3(int, adapter, UTINY *, data, int *, error)
+{
+ CURRENT_ADAPTER();
+ UCHAR host_error;
+ RXBUFCHARTYPE CharType;
+ BOOL MoreToProcess = TRUE;
+ /*::::::::::::::::::::::::::::::::::::::::: Dealing with NULL adapter ? */
+
+ if(current->type != ADAPTER_REAL && !host_com_open(adapter))
+ return; /* Exit, unable to open adapter */
+
+ /*::::::::::::::::::::::: Get next character from input character queue */
+
+
+ while(MoreToProcess)
+ {
+
+ CharType = GetCharacterTypeInBuffer(current);
+
+ //Process next character in buffer
+ switch(CharType)
+ {
+ //................................................Process character
+
+ case RXCHAR:
+ case CHARINERROR:
+ host_error = 0;
+ GetCharFromRXBuffer(current,CharType,(UCHAR *)data,&host_error);
+
+ //error reading character
+ if(host_error)
+ *error = MapHostToBaseError(host_error); /* Get error */
+ MoreToProcess = FALSE;
+ break;
+
+ //.....................Process receive error, no character available
+
+ case RXERROR:
+ com_lsr_change(adapter);
+ break;
+
+ //...................................... Process modem state changes
+
+ case MODEMSTATE:
+ com_modem_change(adapter);
+ break;
+
+ //..................................................RX buffer empty
+
+ case RXBUFEMPTY:
+ always_trace0("Read requested on empty RX buffer");
+ *error = 0; *data = (UTINY)-1; //Buffer empty
+ MoreToProcess = FALSE;
+ break;
+
+ case UNKNOWN:
+ GetCharFromRXBuffer(current,CharType,(UCHAR *)data,&host_error);
+ *error = MapHostToBaseError(host_error); /* Get error */
+ MoreToProcess = FALSE;
+ break;
+
+ }
+ }
+
+ /* Tell comms idle system that there has been comms activity */
+ IDLE_comlpt();
+ current->SuspendTickCounter = current->SuspendTimeoutTicks;
+}
+
+/*:::::::::::::::::::::::::: Comms read returned to application by the base */
+// This function is called after each character is read from the comms port
+
+int CPU host_com_char_read(int adapter, int data_available_ints)
+{
+ CURRENT_ADAPTER();
+
+ current->CharReadFromUART = TRUE; //Char read from UART
+ if(data_available_ints)
+ host_com_EOI_hook((long) adapter);
+ else
+ host_com_poll(adapter);
+
+ return(0);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::: Map host error to base error ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+int RXCPU MapHostToBaseError(UCHAR host_error)
+{
+ int base_error = 0;
+ LINE_STATUS_REG LSR;
+
+ LSR.all = host_error;
+ if(LSR.bits.framing_error) base_error |= HOST_COM_FRAMING_ERROR;
+ if(LSR.bits.parity_error) base_error |= HOST_COM_PARITY_ERROR;
+ if(LSR.bits.break_interrupt) base_error |= HOST_COM_BREAK_RECEIVED;
+ if(LSR.bits.overrun_error) base_error |= HOST_COM_OVERRUN_ERROR;
+
+ return(base_error);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::: Write to comms port :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL RXCPU void host_com_write IFN2(int, adapter, char, data)
+{
+ CURRENT_ADAPTER();
+
+ /*:::::::::::::::::::::::::::::::::: Are we dealing with a NULL adapter */
+
+ if(current->type != ADAPTER_REAL && !host_com_open(adapter))
+ return; /* Exit, unable to open adapter */
+
+ if(data == XOFF_CHARACTER || data == XON_CHARACTER)
+ sub_note_trace1(HOST_COM_VERBOSE,"XO%s sent",data == XOFF_CHARACTER ? "FF" : "N");
+
+ /*::::::::::::::::::::::::::::::::::::::::: Is the user sending an XOFF */
+
+
+ if(data == XOFF_CHARACTER)
+ {
+ if(current->no_tx_chars) FlushTXBuffer(adapter,XOFF_TRIGGER);
+ SendXOFFIoctlToDriver(adapter);
+ }
+ else
+ SendDataToDriver(adapter,data);
+
+ /*::::::::::: Tell comms idle system that there has been comms activity */
+
+ IDLE_comlpt();
+ current->SuspendTickCounter = current->SuspendTimeoutTicks;
+ /* tell base that the tx holding register is empty */
+ tx_holding_register_empty(adapter);
+ /* async write mode -> tell base that the tx shift register is empty
+ * sync mode -> FlushTxBuffer will do the signaling.
+ */
+ if (!current->SyncWrite)
+ tx_shift_register_empty(adapter);
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::: Write data to driver */
+
+void SendDataToDriver(int adapter, char data)
+{
+ DWORD BytesWritten, error = 0;
+ OVERLAPPED OV;
+ CURRENT_ADAPTER();
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::: Delay write ? */
+
+ if(current->tx_threshold)
+ {
+ //Add char to tx buffer queue
+ current->TXBuffer[current->no_tx_chars++] = (unsigned char) data;
+
+
+ //Write threshold reached ?
+ if(current->tx_threshold <= current->no_tx_chars ||
+ current->XOFFInProgress)
+ FlushTXBuffer(adapter,(current->XOFFInProgress) ?
+ XOFF_TRIGGER : TXFULL_TRIGGER);
+ return;
+ }
+
+
+ /*:::::::::::::::::::::::::::::: Setup overlapped I/O control structure */
+
+ OV.hEvent = current->TXEvent[0]; /* Event used to signal completion */
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::: Write character */
+
+ if(!WriteFile(current->handle, &data, 1, &BytesWritten, &OV))
+ {
+ if((error = GetLastError()) == ERROR_IO_PENDING)
+ {
+ /* Write request pending wait for it to complete */
+ if(GetOverlappedResult(current->handle,&OV,&BytesWritten,TRUE))
+ error = 0; /* Write successful */
+ else
+ error = GetLastError();
+ }
+
+ /* Reset comms port, clear error */
+ if(error) ClearCommError(current->handle,&error,NULL);
+ }
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::: Display error */
+
+#ifndef PROD
+ if(error)
+ always_trace2("host_com_write error, adapter %d,%d\n",adapter,error);
+#endif
+ /* tell base that the tx shift register is empty */
+ tx_shift_register_empty(adapter);
+
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::: Send magic XOFF ioctl */
+
+CPU int SendXOFFIoctlToDriver(int adapter)
+{
+ CURRENT_ADAPTER();
+ void *newIOStatusBlock;
+ int rtn;
+
+ /*.................... Allocate new IOstatus block, used by magic ioctl */
+
+ newIOStatusBlock = AllocStatusElement();
+
+ /*.............................................. Issue magic xoff IOCTL */
+
+ if(SendXOFFIoctl(current->handle, // Handle of comms port
+ current->XOFFEvent, // Event to signal completion on
+ XOFF_TIMEOUT, // Timeout in milliseconds
+ XOFF_RXCHARCNT, // RX character count
+ XOFF_CHARACTER, // XOFF character
+ newIOStatusBlock)) // IO status block for ioctl
+
+ {
+ /*............................. Add new status block to linked list */
+
+ EnterCriticalSection(&current->CSEvent);
+
+ AddNewIOStatusBlockToList(&current->firstStatusBlock,
+ &current->lastStatusBlock, newIOStatusBlock);
+
+ current->XOFFInProgress = TRUE;
+ LeaveCriticalSection(&current->CSEvent);
+ rtn =TRUE; // XOFF ioctl successful
+ }
+ else
+ {
+ /* Error, XOFF ioctl failed */
+ free(newIOStatusBlock);
+ rtn = FALSE; // XOFF ioctl failed
+ }
+
+ return(rtn);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+GLOBAL RXCPU void host_com_ioctl IFN3(int, adapter, int, request, long, arg)
+{
+ UCHAR host_modem, error;
+ MODEM_STATUS_REG MSR;
+ char BaudRateStr[100];
+ ULONG ModemState;
+ UCHAR DataBits, StopBits, Parity;
+
+ CURRENT_ADAPTER(); /* Define and set 'current' adaptor pointer */
+
+ /*:::::::::::::::::::::::::::::::::: Are we dealing with a null adapter */
+
+ if(current->type != ADAPTER_REAL)
+ {
+ // Attempt to open adapter !
+
+ if(request == HOST_COM_FLUSH || request == HOST_COM_INPUT_READY ||
+ request == HOST_COM_MODEM || !host_com_open(adapter))
+ {
+ return;
+ }
+ }
+ /*:::::::::::::::::::::::::::::::::::::::::::::: Identify ioctl request */
+
+
+ switch(request)
+ {
+
+ case HOST_COM_LSR:
+ if(GetCharacterTypeInBuffer(current) == RXERROR)
+ {
+ GetCharFromRXBuffer(current, RXERROR, NULL, &error);
+ *(DWORD *)arg = (DWORD)error;
+ }
+ break;
+
+ /*:::::::::::::::::::::::::::::::::::::::::: Process break requests */
+
+ case HOST_COM_SBRK: /* Set BREAK */
+ sub_note_trace0(HOST_COM_VERBOSE, "set BREAK");
+ SetCommBreak(current->handle);
+ current->ComStates.Break = 1;
+ break;
+
+ case HOST_COM_CBRK: /* Clear BREAK */
+ sub_note_trace0(HOST_COM_VERBOSE, "clear BREAK");
+ ClearCommBreak(current->handle);
+ current->ComStates.Break = 0;
+ break;
+
+ /*::::::::::::::::::::::::::::::::::::::::: Process baud rate change */
+
+ case HOST_COM_BAUD:
+
+ if (!FastCommSetBaudRate(current->handle, arg))
+ {
+ sprintf(BaudRateStr, "(%d)", arg);
+ host_error(EHS_UNSUPPORTED_BAUD, ERR_CONT, BaudRateStr);
+ always_trace1("set BAUD failed - SetBaudRate:%d", arg);
+ }
+ current->ComStates.BaudRate = (DWORD)arg;
+
+ break;
+
+ /*:::::::::::::::::::::::::::::::::::::::: Process DTR line requests */
+
+ case HOST_COM_SDTR: /* Set DTR line */
+ //printf("Set DTR\n");
+ sub_note_trace0(HOST_COM_VERBOSE, "set DTR");
+ if(!EscapeCommFunction (current->handle, SETDTR))
+ sub_note_trace0(HOST_COM_VERBOSE, "set DTR FAILED");
+ current->ComStates.DTR = 1;
+ break;
+
+ case HOST_COM_CDTR: /* Clear DTR line */
+ //printf("Clear DTR\n");
+ sub_note_trace0(HOST_COM_VERBOSE, "clear DTR");
+ if(!EscapeCommFunction (current->handle, CLRDTR))
+ sub_note_trace0(HOST_COM_VERBOSE, "clear DTR FAILED");
+ current->ComStates.DTR = 0;
+ break;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::: flush comms port */
+
+ case HOST_COM_FLUSH: /* Flush comms port */
+ sub_note_trace0(HOST_COM_VERBOSE, "Flush comms port");
+ break;
+
+ /*:::::::::::::::::::::::::::::::::::::::: Process RTS line requests */
+
+ case HOST_COM_CRTS: /* Clear RTS */
+ //printf("Clear RTS\n");
+ sub_note_trace0(HOST_COM_VERBOSE, "clear RTS");
+ if(!EscapeCommFunction (current->handle, CLRRTS))
+ sub_note_trace0(HOST_COM_VERBOSE, "clear RTS FAILED");
+ current->ComStates.RTS = 0;
+ break;
+
+ case HOST_COM_SRTS:
+ //printf("Set RTS\n");
+ sub_note_trace0(HOST_COM_VERBOSE, "set RTS");
+ if(!EscapeCommFunction (current->handle, SETRTS))
+ sub_note_trace0(HOST_COM_VERBOSE, "set RTS FAILED");
+ current->ComStates.RTS = 1;
+ break;
+
+ /*::::::::::::::::::::::::::::::::::: Return status of the RX buffer */
+
+ case HOST_COM_INPUT_READY:
+ *(long *)arg = current->rx; /* check the port for data */
+ break;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::: Return modem status */
+
+ case HOST_COM_MODEM: /* Get modem state */
+
+ current->modem_status = 0;
+ if(GetCharacterTypeInBuffer(current) == MODEMSTATE)
+ {
+ GetCharFromRXBuffer(current, MODEMSTATE, &host_modem, &error);
+ MSR.all = host_modem;
+
+ if(MSR.bits.CTS) current->modem_status |= HOST_COM_MODEM_CTS;
+ if(MSR.bits.RI) current->modem_status |= HOST_COM_MODEM_RI;
+ if(MSR.bits.DSR) current->modem_status |= HOST_COM_MODEM_DSR;
+ if(MSR.bits.RLSD) current->modem_status |= HOST_COM_MODEM_RLSD;
+ }
+ else
+ {
+ //.......................Get modem data from the serial driver ?
+
+ FastGetCommModemStatus(current->handle, current->ModemEvent,
+ &ModemState);
+
+ if(ModemState & MS_CTS_ON)
+ current->modem_status |= HOST_COM_MODEM_CTS;
+
+ if(ModemState & MS_RING_ON)
+ current->modem_status |= HOST_COM_MODEM_RI;
+
+ if(ModemState & MS_DSR_ON)
+ current->modem_status |= HOST_COM_MODEM_DSR;
+
+ if(ModemState & MS_RLSD_ON)
+ current->modem_status |= HOST_COM_MODEM_RLSD;
+ }
+
+ //.......................Return modem change information to the base
+
+ sub_note_trace4(HOST_COM_VERBOSE, "CTS:%s RI:%s DSR:%s RLSD:%s",
+ current->modem_status & HOST_COM_MODEM_CTS ? "ON" : "OFF",
+ current->modem_status & HOST_COM_MODEM_RI ? "ON" : "OFF",
+ current->modem_status & HOST_COM_MODEM_DSR ? "ON" : "OFF",
+ current->modem_status & HOST_COM_MODEM_RLSD ? "ON" : "OFF");
+
+ *(long *)arg = current->modem_status;
+ break;
+
+ /*::::::::::::::::::::::::::::::::::::::::: Setup number of stop bits */
+
+ case HOST_COM_STOPBITS:
+ sub_note_trace1(HOST_COM_VERBOSE, "Setting Stop bits %d", arg);
+ if (FastCommGetLineControl(current->handle, &StopBits, &Parity,
+ &DataBits))
+ {
+ switch (arg)
+ {
+ case 1:
+ StopBits = ONESTOPBIT;
+ break;
+ case 2:
+ StopBits = DataBits == 5 ? ONE5STOPBITS : TWOSTOPBITS;
+ break;
+
+ default:
+ always_trace1("STOPBITS strange request %d\n", arg);
+ break;
+ }
+
+ if(!FastCommSetLineControl(current->handle, StopBits, Parity, DataBits))
+ {
+
+ always_trace1("set STOPBITS failed- FastCommSetLineControl:%d",arg);
+ }
+ }
+ else {
+
+ always_trace1("set STOPBITS failed- FastCommGetLineControl:%d",arg);
+ }
+ current->ComStates.StopBits = StopBits;
+ break;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::::::: Setup parity */
+
+ case HOST_COM_PARITY:
+ if (FastCommGetLineControl(current->handle, &StopBits, &Parity, &DataBits))
+ {
+ switch(arg)
+ {
+ case HOST_COM_PARITY_EVEN:
+ sub_note_trace0(HOST_COM_VERBOSE, "Set EVEN Parity");
+ Parity=EVENPARITY;
+ break;
+
+ case HOST_COM_PARITY_ODD:
+ sub_note_trace0(HOST_COM_VERBOSE, "Set ODD Parity");
+ Parity=ODDPARITY;
+ break;
+
+ case HOST_COM_PARITY_MARK:
+ sub_note_trace0(HOST_COM_VERBOSE, "Set MARK Parity");
+ Parity=MARKPARITY;
+ break;
+
+ case HOST_COM_PARITY_SPACE:
+ sub_note_trace0(HOST_COM_VERBOSE, "Set SPACE Parity");
+ Parity=SPACEPARITY;
+ break;
+
+ case HOST_COM_PARITY_NONE:
+ sub_note_trace0(HOST_COM_VERBOSE, "Set DISABLE Parity");
+ Parity=NOPARITY;
+ break;
+ }
+ if(!FastCommSetLineControl(current->handle, StopBits, Parity, DataBits))
+ {
+ always_trace1("set PARITY failed - FastCommSetLineControl :%d",arg);
+ }
+ }
+ else {
+
+ always_trace1("set STOPBITS failed- FastCommGetLineControl:%d",arg);
+ }
+ current->ComStates.Parity = Parity;
+ break;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::: Setup data bits */
+
+ case HOST_COM_DATABITS:
+ sub_note_trace1(HOST_COM_VERBOSE, "Setting data bits %d",arg);
+ if (FastCommGetLineControl(current->handle, &StopBits, &Parity, &DataBits))
+ {
+ DataBits = (UCHAR)arg;
+ if(!FastCommSetLineControl(current->handle, StopBits, Parity, DataBits))
+ {
+ always_trace1("set DATABITS failed - FastCommSetLineControl:%d",arg);
+ }
+ }
+ else {
+
+ always_trace1("set STOPBITS failed- FastCommGetLineControl:%d",arg);
+ }
+ current->ComStates.DataBits = DataBits;
+ break;
+
+ /*::::::::::::::::::::::::::::::::::::::: Unrecognised host_com ioctl */
+
+ default:
+ always_trace0("Bad host_com_ioctl\n");
+ sub_note_trace0(HOST_COM_VERBOSE, "Bad host_com_ioctl");
+ break;
+ }
+
+ /* Tell comms idle system that there has been comms activity */
+ IDLE_comlpt();
+ current->SuspendTickCounter = current->SuspendTimeoutTicks;
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::: Host comms reset ????? */
+
+GLOBAL void host_com_reset IFN1(int, adapter)
+{
+ int controller, line;
+ half_word IMR_value;
+
+ com_int_data(adapter, &controller, &line);
+
+ always_trace3("com reset Adapter %d, controller %d, line %d\n",adapter,controller,line);
+
+ //Disable interrupts on port being reset
+ ica_inb((io_addr) (controller ? ICA1_PORT_1 : ICA0_PORT_1), &IMR_value);
+ IMR_value |= 1 << line;
+ ica_outb((io_addr) (controller ? ICA1_PORT_1 : ICA0_PORT_1), IMR_value);
+
+ //Enable error displaying
+ host_com[adapter].DisplayError = TRUE;
+ host_com[adapter].Suspended = FALSE;
+ host_com[adapter].Suspending = FALSE;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Autoflush */
+
+GLOBAL void host_setup_aflush IFN1(int, state)
+{
+ UNREFERENCED_FORMAL_PARAMETER(state);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: RX buffer handling routines :::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/*:::::::::::::::::::::::::::::::::::::::: Get chars from the serial driver */
+
+
+DWORD RX GetCharsFromDriver(int adapter)
+{
+ CURRENT_ADAPTER();
+ DWORD bytesread = 0, bytestoread;
+ OVERLAPPED OV;
+ DWORD CommError;
+ DWORD bytes_before_wrap;
+ DWORD total_bytes_read = 0;
+
+
+ OV.hEvent = current->RXEvent; /* Event to signal completion on */
+ EnterCriticalSection(&current->CSEvent);
+
+ bytestoread = BUFFER_SIZE - current->bytes_in_rxbuf;
+ bytes_before_wrap = BUFFER_SIZE - current->head_inx;
+ if (bytes_before_wrap < bytestoread){
+ OV.Offset = 0; /* reset offset or ReadFile can fail */
+ OV.OffsetHigh = 0;
+ if (!ReadFile(current->handle, &current->buffer[current->head_inx],
+ bytes_before_wrap, &bytesread, &OV))
+ {
+ // we have zero timeout for the read operation
+ // this pending check may be redundant??????
+ if (GetLastError() == ERROR_IO_PENDING) {
+ GetOverlappedResult(current->handle, &OV,
+ &bytesread, TRUE);
+ }
+ else {
+ ClearCommError(current->handle, &CommError, NULL);
+ bytesread = 0;
+ }
+ }
+
+ if (bytesread) {
+ total_bytes_read = bytesread;
+ current->bytes_in_rxbuf += bytesread;
+ if (bytesread == bytes_before_wrap) {
+ current->head_inx = 0;
+ bytestoread -= bytesread;
+ }
+ else {
+ current->head_inx += bytesread;
+ bytestoread = 0;
+
+ }
+ }
+ else
+ bytestoread = 0;
+ }
+ if (bytestoread){
+ OV.Offset = 0; /* reset offset or ReadFile can fail */
+ OV.OffsetHigh = 0;
+ if (!ReadFile(current->handle, &current->buffer[current->head_inx],
+ bytestoread, &bytesread, &OV))
+ {
+ if (GetLastError() == ERROR_IO_PENDING) {
+ GetOverlappedResult(current->handle, &OV,
+ &bytesread, TRUE);
+ }
+ else {
+ ClearCommError(current->handle, &CommError, NULL);
+ bytesread = 0;
+ }
+ }
+ if (bytesread) {
+ current->bytes_in_rxbuf += bytesread;
+ current->head_inx += bytesread;
+ total_bytes_read += bytesread;
+ }
+ }
+ LeaveCriticalSection(&current->CSEvent);
+
+ return (total_bytes_read);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::: RX thread, one per comm port :::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+DWORD PollCommsThread(PVOID pv)
+{
+ DWORD adapter = (DWORD)pv;
+ DWORD dwRet = (WORD)-1;
+
+ try {
+ dwRet = nt_poll_comms(adapter);
+ }
+ except(VdmUnhandledExceptionFilter(GetExceptionInformation())) {
+ ; // we shouldn't arrive here
+ }
+
+ return dwRet;
+}
+
+
+
+DWORD CPU nt_poll_comms IFN1(DWORD, adapter)
+{
+ CURRENT_ADAPTER(); /* Setup ptr to current adapter */
+ DWORD EvtMask; /* Comms event mask */
+ ULONG SignalledObj = (ULONG) -1;
+ HANDLE WaitTable[3];
+ HANDLE SetCommEvt; /* Handle used by FastSetCommEvent */
+
+ BOOL CheckDriverForChars = FALSE; /* Check driver for characters */
+ RXBUFCHARTYPE CharType;
+
+ /*::::::::::::::::::::::::::::::::: Setup table of event signal objects */
+
+ WaitTable[0] = current->EvtHandle;
+ WaitTable[1] = current->RXControlObject;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::: Setup comm wait mask */
+
+ SetCommEvt = CreateEvent(NULL,TRUE,FALSE,NULL);
+
+ FastSetCommMask(current->handle,SetCommEvt,EV_RXCHAR | EV_ERR | EV_MODEM);
+
+ //Initialise FastWaitCommsOrCpuEvent function
+ FastWaitCommsOrCpuEvent(NULL, NULL, 0, NULL, NULL);
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::: Enter read loop */
+
+ while(TRUE)
+ {
+ /*::::::::::::::::: Wait for communications events then process them */
+
+ if(SignalledObj != 1)
+ {
+ if(!FastWaitCommsOrCpuEvent(current->handle, WaitTable, 0, &EvtMask,
+ &SignalledObj))
+ {
+ // Error getting comms/CPU thread event ?
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ }
+ }
+
+ /*::::::::::::::::::::: Is the CPU thread returning control to us ? */
+
+ if(SignalledObj == 1 || current->TerminateRXThread)
+ {
+ // The CPU thread is trying to tell us something.
+
+ /*..................... Is it time to terminate this thread !!! */
+
+ if(current->TerminateRXThread)
+ {
+ FastSetCommMask(current->handle,SetCommEvt,0);
+ WaitForAllXOFFsToComplete(adapter); // Complete ioctl's
+ CloseHandle(SetCommEvt);
+ return(0); // Terminate thread
+ }
+
+ /* we have 3 reasons why we are here:
+ (1). the CPU thread has emptied the current rx window
+ (2). XOFF is in progress
+ */
+ }
+
+ if (SignalledObj == 0 || current->bytes_in_rxwindow == 0)
+ GetCharsFromDriver(adapter);
+ /*:::::::::::::::::::::::::::::::: Is there data to pass to the base */
+
+ if((CharType = GetCharacterTypeInBuffer(current)) != RXBUFEMPTY)
+ {
+ if (CharType == RXCHAR || CharType == CHARINERROR) {
+ WaitForAllXOFFsToComplete(adapter);
+ }
+
+ // slid the window. Note that there may be some character left in
+ // the window(because of XOFF). It is no harm to slid
+ // the window.
+ //
+ EnterCriticalSection(&current->CSEvent);
+ if (current->bytes_in_rxbuf > current->rxwindow_size)
+ current->bytes_in_rxwindow = current->rxwindow_size;
+ else
+ current->bytes_in_rxwindow = current->bytes_in_rxbuf;
+ LeaveCriticalSection(&current->CSEvent);
+
+ host_com_lock(adapter);
+
+ if(CharType == MODEMSTATE)
+ com_modem_change(adapter);
+ else if (CharType == RXERROR)
+ com_lsr_change(adapter);
+ else {
+ com_recv_char(adapter);
+ /*
+ * reset rx flush counter so we won't flush Rx buffer.
+ * current->RXFlushTrigger may have been RXFLUSHTRIGGER - 1
+ * at this moment and when we switch context to main thread
+ * another timer tick may have come which would trigger
+ * EmptyRxBuffer and cause unwantted overrun.
+ */
+ current->RXFlushTrigger = RXFLUSHTRIGGER;
+ current->RX_in_Control = FALSE;
+ current->SignalRXThread = 0;
+ }
+ host_com_unlock(adapter);
+
+ //Wait for CPU thread to return control
+ if(CharType != MODEMSTATE && CharType != RXERROR)
+ {
+ WaitForSingleObject(current->RXControlObject, INFINITE);
+ }
+
+ SignalledObj = 1;
+ }
+ else
+ SignalledObj = (ULONG) -1;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::: Wait for XOFF ioctl's to complete ::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+
+void RX WaitForAllXOFFsToComplete(int adapter)
+{
+ CURRENT_ADAPTER();
+ int PendingXOFF;
+
+ if(current->firstStatusBlock == NULL && current->lastStatusBlock == NULL)
+ return; //list of pending ioctrl's empty
+
+ /*::::::::::::::::::::::: Wait for all pending xoff ioctl's to complete */
+
+ do
+ {
+ PendingXOFF = RemoveCompletedXOFFs(adapter);
+
+ /*................................... Are there any ioctl's pending */
+
+ if(PendingXOFF)
+ WaitForSingleObject(current->XOFFEvent,XOFF_TIMEOUT); // wait for ioctl
+ }
+ while(PendingXOFF);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::: Removed completed XOFF ioctl's :::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+BOOL RX RemoveCompletedXOFFs(int adapter)
+{
+ CURRENT_ADAPTER();
+ int PendingXOFF;
+
+ /*........................................ Remove completed ioctl's */
+
+ EnterCriticalSection(&current->CSEvent);
+
+ PendingXOFF = RemoveCompletedIOCTLs(&current->firstStatusBlock,
+ &current->lastStatusBlock);
+
+ if(!PendingXOFF) current->XOFFInProgress = FALSE;
+
+ LeaveCriticalSection(&current->CSEvent);
+
+ return((BOOL) PendingXOFF);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::: Enter critical section for adapter :::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void RXCPU host_com_lock(int adapter)
+{
+ CURRENT_ADAPTER();
+ if(current->type != ADAPTER_REAL) return; /* Exit, NULL adapter */
+
+ EnterCriticalSection(&current->AdapterLock);
+ current->AdapterLockCnt++;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::: Leave critical section for adapter :::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void RXCPU host_com_unlock(int adapter)
+{
+ CURRENT_ADAPTER();
+
+ if(current->type != ADAPTER_REAL || current->AdapterLockCnt == 0)
+ return; /* Exit, NULL adapter */
+
+ current->AdapterLockCnt--;
+ LeaveCriticalSection(&current->AdapterLock);
+
+ //Have we been requested to signal the RX thread. After the SetEvent()
+ //function call the RX thread, which is blocked on the
+ //current->RXControlObject object, will run. If the SetEvent() function
+ //is called from within the critical section, then because it is highly
+ //likely that the RX thread will attempt to perform a host_com_lock(). The
+ //RX thread will block in the host_com_lock() function until another time
+ //slice is given to the CPU thread.
+
+ // do not set the event if RX thread already in control
+ if(current->SignalRXThread &&
+ current->SignalRXThread == GetCurrentThreadId())
+ {
+ current->RX_in_Control = TRUE;
+ SetEvent(current->RXControlObject);
+ current->SignalRXThread = (DWORD) 0;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::: Host coms heart beat ::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+//This function is called approximately every 55ms.
+
+GLOBAL void CPU host_com_heart_beat()
+{
+ register int adapter; /* Adapter no of adapter being processed */
+ register HOST_COM *current; /* Ptr to current adapter being processed */
+ DWORD TickCount;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+ for(adapter = 0; adapter < (sizeof(host_com)/sizeof(HOST_COM)); adapter++)
+ {
+ current = host_com_ptr[adapter]; /* Ptr to current adapter */
+
+ if(current->type == ADAPTER_NULL)
+ {
+ if(current->ReOpenCounter) current->ReOpenCounter--;
+ }
+ else if (current->type == ADAPTER_REAL)
+ {
+ if(current->no_tx_chars) FlushTXBuffer(adapter,TIMER_TRIGGER);
+ current->tx_heart_beat_count++;
+
+ if(current->RXFlushTrigger == 0 && !current->CharReadFromUART)
+ EmptyRXBuffer(adapter); //Empty RX buffer
+ else
+ if(current->CharReadFromUART)
+ {
+ current->RXFlushTrigger = 0; //Force trigger reset
+ current->CharReadFromUART = FALSE;
+ }
+
+ //Update RX flush trigger counter
+ if(--current->RXFlushTrigger < 0)
+ current->RXFlushTrigger = RXFLUSHTRIGGER;
+ /* if auto close is enable, decrement the counter and
+ * suspend the adapter is time out
+ */
+
+ if (current->SuspendTimeoutTicks) {
+ TickCount = GetTickCount();
+
+ if (current->TickCount) {
+ current->SuspendTickCounter -= TickCount - current->TickCount;
+ }
+ else {
+ /* we have not yet initialize the tick count yet,
+ * presume that it is 55ms
+ */
+ current->SuspendTickCounter -= 55;
+ }
+ current->TickCount = TickCount;
+
+ /* time out, suspend the port */
+ if (current->SuspendTickCounter <= 27) {
+ /* make sure host_com_close won't reset the adapter because
+ * we want to keep the adapter current states
+ */
+ current->Suspending = TRUE;
+ host_com_close(adapter);
+ current->Suspended = TRUE;
+ current->Suspending = FALSE;
+ }
+ }
+ }
+ }
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::: Flush TX buffer ::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void CPU FlushTXBuffer(int adapter, FLUSHTYPE FlushReason)
+{
+ CURRENT_ADAPTER();
+ DWORD BytesWritten, error = 0;
+
+ /*................................................. Scale TX threshold */
+
+ ScaleTXThreshold(current, FlushReason);
+
+ if (current->SyncWrite) {
+ if (!WriteFile(current->handle, current->TXBuffer,
+ current->no_tx_chars, &BytesWritten,
+ &current->DWOV[0])) {
+ error = GetLastError();
+ if (error == ERROR_IO_PENDING) {
+ if (!GetOverlappedResult(current->handle,
+ &current->DWOV[0],
+ &BytesWritten,
+ TRUE))
+ error = GetLastError();
+ else
+ error = ERROR_SUCCESS;
+ }
+ }
+ if (error != ERROR_SUCCESS) {
+ ClearCommError(current->handle, &error, NULL);
+#ifndef PROD
+ always_trace2("host_com_write error, adapter %d,%d\n", adapter, error);
+#endif
+ }
+ tx_shift_register_empty(adapter);
+ current->no_tx_chars = 0;
+ return;
+ }
+ /*...Clear pending writes on the OV structure that we are about to use*/
+
+ if(current->DWOV[current->DWOVInx].hEvent)
+ {
+ if(GetOverlappedResult(current->handle,
+ &current->DWOV[current->DWOVInx],
+ &BytesWritten,TRUE))
+ {
+ error = 0; /* Write successful */
+ }
+ else
+ {
+ error = GetLastError();
+ }
+
+#ifndef PROD
+ if(error)
+ always_trace2("host_com_write error, adapter %d,%d\n",adapter,error);
+#endif
+
+ }
+ else
+ current->DWOV[current->DWOVInx].hEvent = current->TXEvent[current->DWOVInx];
+
+ /*..................................................... Write characters */
+
+
+ if(!WriteFile(current->handle, current->TXBuffer, current->no_tx_chars,
+ &BytesWritten, &current->DWOV[current->DWOVInx]))
+ {
+ if((error = GetLastError()) == ERROR_IO_PENDING)
+ error = 0; //ignore IO PENDING
+
+ /* Reset comms port, clear error */
+ if(error)
+ {
+ ClearCommError(current->handle,&error,NULL);
+#ifndef PROD
+ always_trace2("host_com_write error, adapter %d,%d\n",adapter,
+ error);
+#endif
+ }
+ }
+
+ if(++current->DWOVInx == MAX_PENDING_WRITES) current->DWOVInx =0;
+ current->no_tx_chars = 0;
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::: Scale TX threshold :::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+void ScaleTXThreshold(register HOST_COM *current,FLUSHTYPE FlushReason)
+{
+
+ if(FlushReason != TIMER_TRIGGER)
+ {
+ current->tx_timer_flush_count = 0;
+ current->todate_timer_flush_total = 0;
+ }
+
+ /*....................................................................*/
+
+ switch(FlushReason)
+ {
+ // Comms heart beat caused flush
+
+ case TIMER_TRIGGER:
+ //printf("T%d",current->no_tx_chars);
+ if(++current->tx_timer_flush_count == 3)
+ {
+ //printf("X");
+ // three consecutive timer trigged flushes, this maybe because
+ // the TX threshold is to high. If the threshold is to high
+ // then we are wasting time waiting for the communications
+ // heart beat to flush the buffer. Reduce TX threshold.
+
+ current->todate_timer_flush_total += current->no_tx_chars;
+ current->tx_threshold = current->todate_timer_flush_total/3;
+
+ //printf("[%dT]",current->tx_threshold);
+
+ // Reset TXFULL_TRIGGER control variables
+ current->tx_heart_beat_count = 0;
+ current->tx_flush_count = 0;
+
+ // Reset TIMER_TRIGGER control variables
+ current->tx_timer_flush_count = 0;
+ current->todate_timer_flush_total = 0;
+ }
+ else
+ {
+ current->todate_timer_flush_total += current->no_tx_chars;
+ }
+
+ break;
+
+ // TX threshold reached
+
+ case TXFULL_TRIGGER:
+
+ //printf("F");
+ //TX scaling trigger triggered ?????
+ if(current->tx_heart_beat_count <= 3 &&
+ current->tx_flush_count++ == TX_SCALING_TRIGGER)
+ {
+ current->tx_threshold = current->tx_threshold*2 > current->max_tx_threshold
+ ? current->max_tx_threshold
+ : current->tx_threshold*2;
+
+ //printf("[%dF]",current->tx_threshold);
+ current->tx_flush_count = 0;
+ }
+ else
+ if(current->tx_heart_beat_count > 3)
+ {
+ current->tx_heart_beat_count = 0;
+ current->tx_flush_count = 0;
+ }
+
+ break;
+
+ // XOFF triggered or close triggered flush
+
+ case XOFF_TRIGGER:
+ case CLOSE_TRIGGER:
+ break;
+
+ } /* End of switch statement */
+}
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::: Comms character read hook ::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+//This function is called after a character has been read out of the comms
+//adapter (com.c). This function is always called from within an adapter
+//critical section, host_com_lock().
+
+void CPU host_com_EOI_hook(long adapter)
+{
+ CURRENT_ADAPTER();
+ RXBUFCHARTYPE CharType;
+
+ if (!current->XOFFInProgress && current->bytes_in_rxwindow)
+ {
+ while ((CharType = GetCharacterTypeInBuffer(current)) != RXBUFEMPTY){
+ if (CharType == MODEMSTATE)
+ com_modem_change(adapter);
+ else if (CharType == RXERROR)
+ com_lsr_change(adapter);
+ else {
+ com_recv_char((int) adapter);
+ return;
+ }
+ }
+ }
+ //Request host_com_unlock() to signal the RX thread. This will
+ //return responsibility for interrupt generation to the RX thread.
+
+ current->SignalRXThread = GetCurrentThreadId();
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: Polling applications LSR hook ::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+// This following function is only called from the comms adapter if data
+// available interrupts are disabled and the adapters receive buffer is
+// empty. Being called under these circumstances indicates that we
+// are dealing with a application that is polling the comms adapter.
+
+// This function is always called from within an adapter critical section
+
+
+void CPU host_com_poll(int adapter)
+{
+ CURRENT_ADAPTER();
+ RXBUFCHARTYPE CharType;
+
+ /*:::::::::::::::::::::::::::::::::: Are we dealing with a null adapter */
+
+ if(current->type != ADAPTER_REAL && !host_com_open(adapter))
+ return; /* Exit, unable to open adapter */
+
+ /*::::::::::::::::: Has an XOFF character stop the generation of ints */
+
+ if(current->XOFFInProgress)
+ {
+ // XOFF in process, pass no more characters to the base and return
+ // control to the RX thread.
+
+ current->SignalRXThread = GetCurrentThreadId();
+ return;
+ }
+
+ // If the RX buffer is empty see if there are any characters hanging
+ // around in the serial driver
+
+ if(current->bytes_in_rxbuf == 0) GetCharsFromDriver(adapter);
+
+ /*:::::::::::::::::::::: Are there any characters to pass to the base ? */
+
+ if(current->bytes_in_rxbuf == 0 ||
+ (CharType = GetCharacterTypeInBuffer(current)) == RXBUFEMPTY)
+ {
+ current->SignalRXThread = GetCurrentThreadId();
+ }
+ else
+ {
+ //Process modem state characters
+ while(CharType == MODEMSTATE || CharType == RXERROR)
+ {
+ if (CharType == MODEMSTATE)
+ com_modem_change(adapter);
+ else
+ com_lsr_change(adapter);
+ CharType = GetCharacterTypeInBuffer(current);
+ }
+
+ if(CharType != RXBUFEMPTY)
+ {
+ com_recv_char((int)adapter);
+ }
+ else
+ current->SignalRXThread = GetCurrentThreadId();
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::: Comms adapter data available interrupt hook ::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+// The comms adapter calls this function when the status of the data available
+// interrupt has changed. The adapter lock is in affect
+
+void CPU host_com_da_int_change(int adapter, int data_int_state, int data_state)
+{
+ CURRENT_ADAPTER();
+
+ /*:::::::::::::::::::::::::::::::::: Are we dealing with a null adapter */
+
+ if(current->type != ADAPTER_REAL)
+ {
+ // Only attempt to open a null adapter if data available interrupts
+ // are being enabled
+
+ if(data_int_state == 0 || !host_com_open(adapter))
+ return;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::: Get the type of character in tail of RX buffer :::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+RXBUFCHARTYPE GetCharacterTypeInBuffer(register HOST_COM *current)
+{
+ int tail_inx = current->tail_inx;
+ int bytes_in_buf = current->bytes_in_rxbuf;
+ RXBUFCHARTYPE rtn;
+
+ //Buffer empty ?
+
+ if(bytes_in_buf == 0) return(RXBUFEMPTY);
+
+ //Escape character at head of buffer
+
+ if(current->buffer[tail_inx] == ESCAPECHAR && bytes_in_buf > 1)
+ {
+ BUMP_TAIL_INX(tail_inx,bytes_in_buf);
+
+ switch(current->buffer[tail_inx])
+ {
+ case SERIAL_LSRMST_ESCAPE :
+ rtn = RXCHAR;
+ break;
+
+ case SERIAL_LSRMST_LSR_NODATA :
+ rtn = bytes_in_buf > 1 ? RXERROR : RXBUFEMPTY;
+ break;
+
+ case SERIAL_LSRMST_LSR_DATA :
+ rtn = bytes_in_buf > 2 ? CHARINERROR : RXBUFEMPTY;
+ break;
+
+ case SERIAL_LSRMST_MST :
+ rtn = bytes_in_buf > 1 ? MODEMSTATE : RXBUFEMPTY;
+ break;
+ // receive an invalid escape id
+ default:
+ rtn = UNKNOWN;
+ break;
+ }
+ }
+ else
+ {
+ rtn = current->buffer[tail_inx] == ESCAPECHAR ? RXBUFEMPTY : RXCHAR;
+ }
+
+ return(rtn);
+}
+
+
+//::::::::::::::::::::::::::::::::::::Get the next character from the RX buffer.
+
+void GetCharFromRXBuffer(register HOST_COM *current, RXBUFCHARTYPE type,
+ UCHAR *data, UCHAR *error)
+{
+ EnterCriticalSection(&current->CSEvent);
+
+ switch(type)
+ {
+ //................................................. Return modem status
+
+ case MODEMSTATE :
+ // Skip escape character and type marker
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+
+ *data = current->buffer[current->tail_inx];
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ current->bytes_in_rxwindow -= 3;
+ break;
+
+ //.................................................... Return character
+
+ case RXCHAR :
+ if(current->buffer[current->tail_inx] == ESCAPECHAR)
+ {
+ //Skip ESCAPE character
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ current->bytes_in_rxwindow--;
+ *data = ESCAPECHAR;
+ }
+ else
+ *data = current->buffer[current->tail_inx];
+
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ current->bytes_in_rxwindow--;
+ break;
+
+ //...........................................Return character and error
+
+ case CHARINERROR :
+ // Skip escape character and type marker
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+
+ *error = current->buffer[current->tail_inx];
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ *data = current->buffer[current->tail_inx];
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ current->bytes_in_rxwindow -= 4;
+ break;
+
+ //................................Return line status error with no data
+
+ case RXERROR :
+ // Skip escape character and type marker
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+
+ // Get linr status error
+ *error = current->buffer[current->tail_inx];
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ current->bytes_in_rxwindow -= 3;
+ break;
+ case UNKNOWN:
+ // The only case we will hit an unknown type is unsupport escape
+ // id. Dump the escape char, return the byte follows the escape
+ // characater and post an overrun error
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ *data = current->buffer[current->tail_inx];
+ BUMP_TAIL_INX(current->tail_inx, current->bytes_in_rxbuf);
+ current->bytes_in_rxwindow -= 2;
+ *error = 2;
+ break;
+
+ }
+
+ LeaveCriticalSection(&current->CSEvent);
+}
+
+//::::::Empty RX buffer, processing characters and changing in the modem status
+
+void CPU EmptyRXBuffer(int adapter)
+{
+ RXBUFCHARTYPE CharType;
+ CURRENT_ADAPTER();
+
+ if(!current->RX_in_Control && current->SignalRXThread == (DWORD)0)
+ {
+ always_trace0("Char not removed from UART, RX buffer flushed\n");
+
+ host_com_lock(adapter);
+
+ while((CharType = GetCharacterTypeInBuffer(current)) != RXBUFEMPTY)
+ {
+ if(CharType == MODEMSTATE)
+ com_modem_change(adapter);
+ else if (CharType == RXERROR)
+ com_lsr_change(adapter);
+ else
+ com_recv_char(adapter);
+ }
+
+ host_com_unlock(adapter);
+
+ //Buffer empty return control to the RX thread
+ current->RX_in_Control = TRUE;
+ SetEvent(current->RXControlObject);
+ }
+}
+
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ DEBUG functions
+
+
+#if 0
+void host_com_state(int adapter)
+{
+
+ CURRENT_ADAPTER();
+
+ printf("Adapter %d\n\n",adapter);
+ printf("RX in control %s\n", current->RX_in_Control ? "TRUE" : "FALSE");
+ printf("XOFFInProgress %s\n", current->XOFFInProgress ? "TRUE" : "FALSE");
+
+ printf("Head buffer ptr %xh\n",current->head_inx);
+ printf("Tail buffer ptr %xh\n",current->tail_inx);
+ printf("Bytes in buffer %d\n",current->bytes_in_rxbuf);
+
+ printf("Bytes in TX buf %d\n",current->no_tx_chars);
+ printf("TX buf threshold %d\n",current->tx_threshold);
+ printf("TX threshold max %d\n",current->max_tx_threshold);
+ printf("TX flush count %d\n",current->tx_flush_count);
+ printf("TX timer count %d\n",current->tx_heart_beat_count);
+
+ if(current->AdapterLock.DebugInfo)
+ {
+ printf("Adapter CS count %d\n",current->AdapterLock.DebugInfo->ContentionCount);
+ printf("Data CS count %d\n",current->CSEvent.DebugInfo->ContentionCount);
+ }
+
+ printf("Bytes RX to date %d\n",byte_count);
+ printf("Last read size %d\n",lastread);
+ printf("Avg read size %d\n",byte_count && readcount ? byte_count/readcount : 0);
+ printf("Zero reads %d\n",zeroreads);
+
+ zeroreads = readcount = byte_count=0;
+
+ com_reg_dump();
+}
+#endif
diff --git a/private/mvdm/softpc.new/host/src/nt_cprgs.c b/private/mvdm/softpc.new/host/src/nt_cprgs.c
new file mode 100644
index 000000000..247c546e8
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_cprgs.c
@@ -0,0 +1,2351 @@
+/*
+ SccsID = @(#)sun4_cpuregs.c 1.12 3/27/91 Copyright Insignia Solutions Ltd.
+*/
+#include "host_def.h"
+#include "insignia.h"
+#include "xt.h"
+#include CpuH
+
+#include <stdio.h>
+
+
+/*
+ * --- SUN_VA CPU Interface Functions ---
+ *
+ * There are two sections here. Compile-time define
+ * the one that is right for you!
+ *
+ * CCPU - use the C CPU when HW is not available
+ * A2CPU - use the assembler CPU when HW is not available
+ *
+ */
+
+
+/* HW and SW HOST_SIMULATE functions. */
+extern void sw_host_simulate (); /* in ccpu.o AND a2cpu.o */
+extern void hw_host_simulate (); /* in hcpu/host/hostsim.c */
+
+/*
+ * The function pointers...
+ */
+#ifdef CCPU
+GLOBAL VOID (*setLDTR_func ) ();
+GLOBAL word (*getTR_func ) ();
+GLOBAL INT (*getTS_func ) ();
+GLOBAL VOID (*setEM_func ) ();
+GLOBAL VOID (*setGDTR_limit_func ) ();
+GLOBAL VOID (*setIDTR_limit_func ) ();
+GLOBAL VOID (*setIOPL_func ) ();
+GLOBAL VOID (*setGDTR_base_func ) ();
+GLOBAL word (*getLDTR_func ) ();
+GLOBAL VOID (*setTR_func ) ();
+GLOBAL VOID (*setTS_func ) ();
+GLOBAL INT (*getPE_func ) ();
+GLOBAL sys_addr (*getGDTR_base_func ) ();
+GLOBAL word (*getMSW_reserved_func ) ();
+GLOBAL int (*getCPL_func ) ();
+GLOBAL INT (*getMP_func ) ();
+GLOBAL VOID (*setPE_func ) ();
+GLOBAL word (*getGDTR_limit_func ) ();
+GLOBAL word (*getIDTR_limit_func ) ();
+GLOBAL VOID (*setMSW_reserved_func) ();
+GLOBAL VOID (*setMP_func) ();
+GLOBAL VOID (*setIDTR_base_func) ();
+GLOBAL word (*getNT_func) ();
+GLOBAL VOID (*setCPL_func) ();
+GLOBAL INT (*getEM_func) ();
+GLOBAL VOID (*setNT_func ) ();
+GLOBAL sys_addr (*getIDTR_base_func) ();
+#endif
+
+GLOBAL word (*getAX_func) ();
+GLOBAL half_word (*getAH_func) ();
+GLOBAL half_word (*getAL_func) ();
+GLOBAL word (*getBX_func) ();
+GLOBAL half_word (*getBH_func) ();
+GLOBAL half_word (*getBL_func) ();
+GLOBAL word (*getCX_func) ();
+GLOBAL half_word (*getCH_func) ();
+GLOBAL half_word (*getCL_func) ();
+GLOBAL word (*getDX_func) ();
+GLOBAL half_word (*getDH_func) ();
+GLOBAL half_word (*getDL_func) ();
+GLOBAL word (*getSP_func) ();
+GLOBAL word (*getBP_func) ();
+GLOBAL word (*getSI_func) ();
+GLOBAL word (*getDI_func) ();
+GLOBAL word (*getIP_func) ();
+GLOBAL word (*getCS_func) ();
+GLOBAL word (*getDS_func) ();
+GLOBAL word (*getES_func) ();
+GLOBAL word (*getSS_func) ();
+GLOBAL word (*getMSW_func) ();
+
+#ifdef CCPU
+GLOBAL INT (*getDF_func) ();
+GLOBAL INT (*getIF_func) ();
+GLOBAL INT (*getTF_func) ();
+GLOBAL INT (*getPF_func) ();
+GLOBAL INT (*getAF_func) ();
+GLOBAL INT (*getSF_func) ();
+GLOBAL INT (*getZF_func) ();
+GLOBAL INT (*getOF_func) ();
+GLOBAL INT (*getCF_func) ();
+GLOBAL INT (*getIOPL_func ) ();
+#endif
+
+#ifdef A3CPU
+GLOBAL word (*getDF_func) ();
+GLOBAL word (*getIF_func) ();
+GLOBAL word (*getTF_func) ();
+GLOBAL word (*getPF_func) ();
+GLOBAL word (*getAF_func) ();
+GLOBAL word (*getSF_func) ();
+GLOBAL word (*getZF_func) ();
+GLOBAL word (*getOF_func) ();
+GLOBAL word (*getCF_func) ();
+GLOBAL word (*getIOPL_func ) ();
+#endif
+
+GLOBAL word (*getSTATUS_func) ();
+
+GLOBAL double_word (*getOPA_func) ();
+GLOBAL double_word (*getOPB_func) ();
+GLOBAL double_word (*getOPR_func) ();
+GLOBAL sys_addr (*getSSD_func) ();
+GLOBAL sys_addr (*getDSD_func) ();
+
+GLOBAL VOID (*setAX_func) ();
+GLOBAL VOID (*setAH_func) ();
+GLOBAL VOID (*setAL_func) ();
+GLOBAL VOID (*setBX_func) ();
+GLOBAL VOID (*setBH_func) ();
+GLOBAL VOID (*setBL_func) ();
+GLOBAL VOID (*setCX_func) ();
+GLOBAL VOID (*setCH_func) ();
+GLOBAL VOID (*setCL_func) ();
+GLOBAL VOID (*setDX_func) ();
+GLOBAL VOID (*setDH_func) ();
+GLOBAL VOID (*setDL_func) ();
+GLOBAL VOID (*setSP_func) ();
+GLOBAL VOID (*setBP_func) ();
+GLOBAL VOID (*setSI_func) ();
+GLOBAL VOID (*setDI_func) ();
+GLOBAL VOID (*setIP_func) ();
+GLOBAL INT (*setCS_func) ();
+GLOBAL INT (*setDS_func) ();
+GLOBAL INT (*setES_func) ();
+GLOBAL INT (*setSS_func) ();
+GLOBAL VOID (*setMSW_func) ();
+GLOBAL VOID (*setDF_func) ();
+GLOBAL VOID (*setIF_func) ();
+GLOBAL VOID (*setTF_func) ();
+GLOBAL VOID (*setPF_func) ();
+GLOBAL VOID (*setAF_func) ();
+GLOBAL VOID (*setSF_func) ();
+GLOBAL VOID (*setZF_func) ();
+GLOBAL VOID (*setOF_func) ();
+GLOBAL VOID (*setCF_func) ();
+
+GLOBAL VOID (*setOPLEN_func) ();
+GLOBAL VOID (*setOPA_func) ();
+GLOBAL VOID (*setOPB_func) ();
+GLOBAL VOID (*setOPR_func) ();
+
+GLOBAL VOID (*host_simulate_func) ();
+
+#ifdef CPU_30_STYLE
+
+#ifdef CCPU
+
+GLOBAL VOID load_sw_cpu_access_functions()
+{
+ IMPORT VOID c_cpu_simulate();
+
+ fprintf (stderr,"[load_sw_cpu_access_functions] init READ/WRITE functions.\n");
+
+ /* READ functions */
+ getAX_func = c_getAX;
+ getAH_func = c_getAH;
+ getAL_func = c_getAL;
+ getBX_func = c_getBX;
+ getBH_func = c_getBH;
+ getBL_func = c_getBL;
+ getCX_func = c_getCX;
+ getCH_func = c_getCH;
+ getCL_func = c_getCL;
+ getDX_func = c_getDX;
+ getDH_func = c_getDH;
+ getDL_func = c_getDL;
+ getSP_func = c_getSP;
+ getBP_func = c_getBP;
+ getSI_func = c_getSI;
+ getDI_func = c_getDI;
+ getIP_func = c_getIP;
+ getCS_func = c_getCS;
+ getDS_func = c_getDS;
+ getES_func = c_getES;
+ getSS_func = c_getSS;
+ getMSW_func = c_getMSW;
+ getDF_func = c_getDF;
+ getIF_func = c_getIF;
+ getTF_func = c_getTF;
+ getPF_func = c_getPF;
+ getAF_func = c_getAF;
+ getSF_func = c_getSF;
+ getZF_func = c_getZF;
+ getOF_func = c_getOF;
+ getCF_func = c_getCF;
+
+
+ /* WRITE functions */
+ setAX_func = c_setAX;
+ setAH_func = c_setAH;
+ setAL_func = c_setAL;
+ setBX_func = c_setBX;
+ setBH_func = c_setBH;
+ setBL_func = c_setBL;
+ setCX_func = c_setCX;
+ setCH_func = c_setCH;
+ setCL_func = c_setCL;
+ setDX_func = c_setDX;
+ setDH_func = c_setDH;
+ setDL_func = c_setDL;
+ setSP_func = c_setSP;
+ setBP_func = c_setBP;
+ setSI_func = c_setSI;
+ setDI_func = c_setDI;
+ setIP_func = c_setIP;
+ setDF_func = c_setDF;
+ setIF_func = c_setIF;
+ setTF_func = c_setTF;
+ setPF_func = c_setPF;
+ setAF_func = c_setAF;
+ setSF_func = c_setSF;
+ setZF_func = c_setZF;
+ setOF_func = c_setOF;
+ setCF_func = c_setCF;
+ setSS_func = c_setSS;
+ setDS_func = c_setDS;
+ setES_func = c_setES;
+ setCS_func = c_setCS;
+
+ /* SW HOST_SIMULATE function */
+ host_simulate_func = c_cpu_simulate;
+}
+#endif /* CCPU */
+
+
+/* Temporary 3.0 stubs... */
+#ifdef A3CPU
+
+LOCAL double_word a3_na_gOPA()
+{
+ printf ("%s:%d - getOPA() not supported.\n", __FILE__, __LINE__);
+ return 0;
+}
+LOCAL double_word a3_na_gOPB()
+{
+ printf ("%s:%d - getOPB() not supported.\n", __FILE__, __LINE__);
+ return 0;
+}
+LOCAL double_word a3_na_gOPR ()
+{
+ printf ("%s:%d - getOPR() not supported.\n", __FILE__, __LINE__);
+ return 0;
+}
+LOCAL sys_addr a3_na_gSSD()
+{
+ printf ("%s:%d - getSSD() not supported.\n", __FILE__, __LINE__);
+ return 0;
+}
+LOCAL sys_addr a3_na_gDSD()
+{
+ printf ("%s:%d - getDSD() not supported.\n", __FILE__, __LINE__);
+ return 0;
+}
+LOCAL VOID a3_na_sOPLEN()
+{
+ printf ("%s:%d - setOPLEN() not supported.\n", __FILE__, __LINE__);
+}
+LOCAL VOID a3_na_sOPA()
+{
+ printf ("%s:%d - setOPA() not supported.\n", __FILE__, __LINE__);
+}
+LOCAL VOID a3_na_sOPB()
+{
+ printf ("%s:%d - setOPB() not supported.\n", __FILE__, __LINE__);
+}
+LOCAL VOID a3_na_sOPR()
+{
+ printf ("%s:%d - setOPR() not supported.\n", __FILE__, __LINE__);
+}
+LOCAL VOID a3_na_sMSW()
+{
+ printf ("%s:%d - setMSW() not supported.\n", __FILE__, __LINE__);
+}
+
+GLOBAL VOID load_sw_cpu_access_functions ()
+{
+ IMPORT VOID _asm_simulate();
+
+ fprintf (stderr,"[load_sw_cpu_access_functions] init READ/WRITE functions.\n");
+
+ /* READ functions */
+ getAX_func = a3_getAX;
+ getAH_func = a3_getAH;
+ getAL_func = a3_getAL;
+ getBX_func = a3_getBX;
+ getBH_func = a3_getBH;
+ getBL_func = a3_getBL;
+ getCX_func = a3_getCX;
+ getCH_func = a3_getCH;
+ getCL_func = a3_getCL;
+ getDX_func = a3_getDX;
+ getDH_func = a3_getDH;
+ getDL_func = a3_getDL;
+ getSP_func = a3_getSP;
+ getBP_func = a3_getBP;
+ getSI_func = a3_getSI;
+ getDI_func = a3_getDI;
+ getIP_func = a3_getIP;
+ getOPA_func = a3_na_gOPA;
+ getOPB_func = a3_na_gOPB;
+ getOPR_func = a3_na_gOPR;
+ getSSD_func = a3_na_gSSD;
+ getDSD_func = a3_na_gDSD;
+ getCS_func = a3_getCS;
+ getDS_func = a3_getDS;
+ getES_func = a3_getES;
+ getSS_func = a3_getSS;
+ getMSW_func = a3_getMSW;
+ getDF_func = a3_getDF;
+ getIF_func = a3_getIF;
+ getTF_func = a3_getTF;
+ getPF_func = a3_getPF;
+ getAF_func = a3_getAF;
+ getSF_func = a3_getSF;
+ getZF_func = a3_getZF;
+ getOF_func = a3_getOF;
+ getCF_func = a3_getCF;
+
+
+ /* WRITE functions */
+ setAX_func = a3_setAX;
+ setAH_func = a3_setAH;
+ setAL_func = a3_setAL;
+ setBX_func = a3_setBX;
+ setBH_func = a3_setBH;
+ setBL_func = a3_setBL;
+ setCX_func = a3_setCX;
+ setCH_func = a3_setCH;
+ setCL_func = a3_setCL;
+ setDX_func = a3_setDX;
+ setDH_func = a3_setDH;
+ setDL_func = a3_setDL;
+ setSP_func = a3_setSP;
+ setBP_func = a3_setBP;
+ setSI_func = a3_setSI;
+ setDI_func = a3_setDI;
+ setIP_func = a3_setIP;
+ setMSW_func = a3_na_sMSW;
+ setDF_func = a3_setDF;
+ setIF_func = a3_setIF;
+ setTF_func = a3_setTF;
+ setPF_func = a3_setPF;
+ setAF_func = a3_setAF;
+ setSF_func = a3_setSF;
+ setZF_func = a3_setZF;
+ setOF_func = a3_setOF;
+ setCF_func = a3_setCF;
+ setOPLEN_func = a3_na_sOPLEN;
+ setOPA_func = a3_na_sOPA;
+ setOPB_func = a3_na_sOPB;
+ setOPR_func = a3_na_sOPR;
+ setSS_func = a3_setSS;
+ setDS_func = a3_setDS;
+ setES_func = a3_setES;
+ setCS_func = a3_setCS;
+
+ /* SW HOST_SIMULATE function */
+ host_simulate_func = _asm_simulate;
+}
+#endif /* A3CPU */
+
+#else /* CPU_30_STYLE */
+
+
+#ifdef CCPU
+/*
+ * ----------------------------------------
+ * ---- SUN_VA Soft CCPU Interface ----
+ * ----------------------------------------
+ */
+
+extern reg A;
+extern reg B;
+extern reg C;
+extern reg D;
+extern reg SP;
+extern reg BP;
+extern reg SI;
+extern reg DI;
+extern reg CS;
+extern reg DS;
+extern reg SS;
+extern reg ES;
+extern reg IP;
+
+extern word m_s_w;
+
+extern void ext_load_CS();
+extern void ext_load_DS();
+extern void ext_load_ES();
+extern void ext_load_SS();
+
+
+word soft_ccpu_getAX ()
+{
+ return (A.X);
+}
+
+half_word soft_ccpu_getAH ()
+{
+ return (A.byte.high);
+}
+
+half_word soft_ccpu_getAL ()
+{
+ return (A.byte.low);
+}
+
+word soft_ccpu_getBX ()
+{
+ return (B.X);
+}
+
+half_word soft_ccpu_getBH ()
+{
+ return (B.byte.high);
+}
+
+half_word soft_ccpu_getBL ()
+{
+ return (B.byte.low);
+}
+
+word soft_ccpu_getCX ()
+{
+ return (C.X);
+}
+
+half_word soft_ccpu_getCH ()
+{
+ return (C.byte.high);
+}
+
+half_word soft_ccpu_getCL ()
+{
+ return (C.byte.low);
+}
+
+word soft_ccpu_getDX ()
+{
+ return (D.X);
+}
+
+half_word soft_ccpu_getDH ()
+{
+ return (D.byte.high);
+}
+
+half_word soft_ccpu_getDL ()
+{
+ return (D.byte.low);
+}
+
+word soft_ccpu_getSP ()
+{
+ return (SP.X);
+}
+
+word soft_ccpu_getBP ()
+{
+ return (BP.X);
+}
+
+word soft_ccpu_getSI ()
+{
+ return (SI.X);
+}
+
+word soft_ccpu_getDI ()
+{
+ return (DI.X);
+}
+
+word soft_ccpu_getIP ()
+{
+ return (IP.X);
+}
+
+word soft_ccpu_getCS ()
+{
+ return (CS.X);
+}
+
+word soft_ccpu_getDS ()
+{
+ return (DS.X);
+}
+
+word soft_ccpu_getES ()
+{
+ return (ES.X);
+}
+
+word soft_ccpu_getSS ()
+{
+ return (SS.X);
+}
+
+word soft_ccpu_getMSW ()
+{
+ return ((m_s_w));
+}
+
+word soft_ccpu_getDF ()
+{
+ return (STATUS_DF);
+}
+
+word soft_ccpu_getIF ()
+{
+ return (STATUS_IF);
+}
+
+word soft_ccpu_getTF ()
+{
+ return (STATUS_TF);
+}
+
+word soft_ccpu_getPF ()
+{
+ return (STATUS_PF);
+}
+
+word soft_ccpu_getAF ()
+{
+ return (STATUS_AF);
+}
+
+word soft_ccpu_getSF ()
+{
+ return (STATUS_SF);
+}
+
+word soft_ccpu_getZF ()
+{
+ return (STATUS_ZF);
+}
+
+word soft_ccpu_getOF ()
+{
+ return (STATUS_OF);
+}
+
+word soft_ccpu_getCF ()
+{
+ return (STATUS_CF);
+}
+
+word soft_ccpu_getSTATUS ()
+{
+ return (getCF() |
+ getOF() << 11 |
+ getZF() << 6 |
+ getSF() << 7 |
+ getAF() << 4 |
+ getPF() << 2 |
+ getTF() << 8 |
+ getIF() << 9 |
+ getDF() << 10 |
+ getIOPL() << 12 |
+ getNT() << 14);
+}
+
+int soft_ccpu_getCPL ()
+{
+ return (CPL);
+}
+
+sys_addr soft_ccpu_getGDTR_base ()
+{
+ return (GDTR_base);
+}
+
+sys_addr soft_ccpu_getIDTR_base ()
+{
+ return (IDTR_base);
+}
+
+word soft_ccpu_getGDTR_limit ()
+{
+ return (GDTR_limit);
+}
+
+word soft_ccpu_getIDTR_limit ()
+{
+ return (IDTR_limit);
+}
+
+word soft_ccpu_getLDTR ()
+{
+ return (LDTR.X);
+}
+
+word soft_ccpu_getTR ()
+{
+ return (TR.X);
+}
+
+word soft_ccpu_getMSW_reserved ()
+{
+ return (MSW.reserved);
+}
+
+word soft_ccpu_getTS ()
+{
+ return (MSW.TS);
+}
+
+word soft_ccpu_getEM ()
+{
+ return (MSW.EM);
+}
+
+word soft_ccpu_getMP ()
+{
+ return (MSW.MP);
+}
+
+word soft_ccpu_getPE ()
+{
+ return (MSW.PE);
+}
+
+word soft_ccpu_getNT ()
+{
+ return (STATUS_NT);
+}
+
+word soft_ccpu_getIOPL ()
+{
+ return (STATUS_IOPL);
+}
+
+void soft_ccpu_setAX (val)
+unsigned int val;
+{
+ A.X = val;
+}
+
+void soft_ccpu_setAH (val)
+unsigned int val;
+{
+ A.byte.high = val;
+}
+
+void soft_ccpu_setAL (val)
+unsigned int val;
+{
+ A.byte.low = val;
+}
+
+void soft_ccpu_setBX (val)
+unsigned int val;
+{
+ B.X = val;
+}
+
+void soft_ccpu_setBH (val)
+unsigned int val;
+{
+ B.byte.high = val;
+}
+
+void soft_ccpu_setBL (val)
+unsigned int val;
+{
+ B.byte.low = val;
+}
+
+void soft_ccpu_setCX (val)
+unsigned int val;
+{
+ C.X = val;
+}
+
+void soft_ccpu_setCH (val)
+unsigned int val;
+{
+ C.byte.high = val;
+}
+
+void soft_ccpu_setCL (val)
+unsigned int val;
+{
+ C.byte.low = val;
+}
+
+void soft_ccpu_setDX (val)
+unsigned int val;
+{
+ D.X = val;
+}
+
+void soft_ccpu_setDH (val)
+unsigned int val;
+{
+ D.byte.high = val;
+}
+
+void soft_ccpu_setDL (val)
+unsigned int val;
+{
+ D.byte.low = val;
+}
+
+void soft_ccpu_setSP (val)
+unsigned int val;
+{
+ SP.X = val;
+}
+
+void soft_ccpu_setBP (val)
+unsigned int val;
+{
+ BP.X = val;
+}
+
+void soft_ccpu_setSI (val)
+unsigned int val;
+{
+ SI.X = val;
+}
+
+void soft_ccpu_setDI (val)
+unsigned int val;
+{
+ DI.X = val;
+}
+
+void soft_ccpu_setIP (val)
+unsigned int val;
+{
+ IP.X = val;
+}
+
+void soft_ccpu_setMSW (val)
+unsigned int val;
+{
+ m_s_w = val;
+}
+
+void soft_ccpu_setDF (val)
+unsigned int val;
+{
+ STATUS_DF = val;
+}
+
+void soft_ccpu_setIF (val)
+unsigned int val;
+{
+ STATUS_IF = val;
+}
+
+void soft_ccpu_setTF (val)
+unsigned int val;
+{
+ STATUS_TF = val;
+}
+
+void soft_ccpu_setPF (val)
+unsigned int val;
+{
+ STATUS_PF = val;
+}
+
+void soft_ccpu_setAF (val)
+unsigned int val;
+{
+ STATUS_AF = val;
+}
+
+void soft_ccpu_setSF (val)
+unsigned int val;
+{
+ STATUS_SF = val;
+}
+
+void soft_ccpu_setZF (val)
+unsigned int val;
+{
+ STATUS_ZF = val;
+}
+
+void soft_ccpu_setOF (val)
+unsigned int val;
+{
+ STATUS_OF = val;
+}
+
+void soft_ccpu_setCF (val)
+unsigned int val;
+{
+ STATUS_CF = val;
+}
+
+void soft_ccpu_setCPL ( val )
+int val;
+{
+ CPL = val;
+}
+
+void soft_ccpu_setGDTR_base ( val )
+sys_addr val;
+{
+ GDTR_base = val;
+}
+
+void soft_ccpu_setIDTR_base ( val )
+sys_addr val;
+{
+ IDTR_base = val;
+}
+
+void soft_ccpu_setGDTR_limit ( val )
+word val;
+{
+ GDTR_limit = val;
+}
+
+void soft_ccpu_setIDTR_limit ( val )
+word val;
+{
+ IDTR_limit = val;
+}
+
+void soft_ccpu_setLDTR ( val )
+word val;
+{
+ LDTR.X = val;
+}
+
+void soft_ccpu_setTR ( val )
+word val;
+{
+ TR.X = val;
+}
+
+void soft_ccpu_setMSW_reserved ( val )
+word val;
+{
+ MSW.reserved = val;
+}
+
+void soft_ccpu_setTS ( val )
+word val;
+{
+ MSW.TS = val;
+}
+
+void soft_ccpu_setEM ( val )
+word val;
+{
+ MSW.EM = val;
+}
+
+void soft_ccpu_setMP ( val )
+word val;
+{
+ MSW.MP = val;
+}
+
+void soft_ccpu_setPE ( val )
+word val;
+{
+ MSW.PE = val;
+}
+
+void soft_ccpu_setNT ( val )
+word val;
+{
+ STATUS_NT = val;
+}
+
+void soft_ccpu_setIOPL ( val )
+word val;
+{
+ STATUS_IOPL = val;
+}
+
+
+
+
+
+void
+load_sw_cpu_access_functions ()
+{
+ /* READ functions */
+ getAX_func = soft_ccpu_getAX;
+ getAH_func = soft_ccpu_getAH;
+ getAL_func = soft_ccpu_getAL;
+ getBX_func = soft_ccpu_getBX;
+ getBH_func = soft_ccpu_getBH;
+ getBL_func = soft_ccpu_getBL;
+ getCX_func = soft_ccpu_getCX;
+ getCH_func = soft_ccpu_getCH;
+ getCL_func = soft_ccpu_getCL;
+ getDX_func = soft_ccpu_getDX;
+ getDH_func = soft_ccpu_getDH;
+ getDL_func = soft_ccpu_getDL;
+ getSP_func = soft_ccpu_getSP;
+ getBP_func = soft_ccpu_getBP;
+ getSI_func = soft_ccpu_getSI;
+ getDI_func = soft_ccpu_getDI;
+ getIP_func = soft_ccpu_getIP;
+ getCS_func = soft_ccpu_getCS;
+ getDS_func = soft_ccpu_getDS;
+ getES_func = soft_ccpu_getES;
+ getSS_func = soft_ccpu_getSS;
+ getMSW_func = soft_ccpu_getMSW;
+ getDF_func = soft_ccpu_getDF;
+ getIF_func = soft_ccpu_getIF;
+ getTF_func = soft_ccpu_getTF;
+ getPF_func = soft_ccpu_getPF;
+ getAF_func = soft_ccpu_getAF;
+ getSF_func = soft_ccpu_getSF;
+ getZF_func = soft_ccpu_getZF;
+ getOF_func = soft_ccpu_getOF;
+ getCF_func = soft_ccpu_getCF;
+ getSTATUS_func = soft_ccpu_getSTATUS; /* not used in a2CPU */
+ getCPL_func = soft_ccpu_getCPL; /* not used in a2CPU */
+ getGDTR_base_func = soft_ccpu_getGDTR_base; /* not used in a2CPU */
+ getGDTR_limit_func = soft_ccpu_getGDTR_limit; /* not used in a2CPU */
+ getIDTR_base_func = soft_ccpu_getIDTR_base; /* not used in a2CPU */
+ getIDTR_limit_func = soft_ccpu_getIDTR_limit; /* not used in a2CPU */
+ getLDTR_func = soft_ccpu_getLDTR; /* not used in a2CPU */
+ getTR_func = soft_ccpu_getTR; /* not used in a2CPU */
+ getMSW_reserved_func = soft_ccpu_getMSW_reserved; /* not used in a2CPU */
+ getTS_func = soft_ccpu_getTS; /* not used in a2CPU */
+ getEM_func = soft_ccpu_getEM; /* not used in a2CPU */
+ getMP_func = soft_ccpu_getMP; /* not used in a2CPU */
+ getPE_func = soft_ccpu_getPE; /* not used in a2CPU */
+ getNT_func = soft_ccpu_getNT; /* not used in a2CPU */
+ getIOPL_func = soft_ccpu_getIOPL; /* not used in a2CPU */
+
+
+ /* WRITE functions */
+ setAX_func = soft_ccpu_setAX;
+ setAH_func = soft_ccpu_setAH;
+ setAL_func = soft_ccpu_setAL;
+ setBX_func = soft_ccpu_setBX;
+ setBH_func = soft_ccpu_setBH;
+ setBL_func = soft_ccpu_setBL;
+ setCX_func = soft_ccpu_setCX;
+ setCH_func = soft_ccpu_setCH;
+ setCL_func = soft_ccpu_setCL;
+ setDX_func = soft_ccpu_setDX;
+ setDH_func = soft_ccpu_setDH;
+ setDL_func = soft_ccpu_setDL;
+ setSP_func = soft_ccpu_setSP;
+ setBP_func = soft_ccpu_setBP;
+ setSI_func = soft_ccpu_setSI;
+ setDI_func = soft_ccpu_setDI;
+ setIP_func = soft_ccpu_setIP;
+ setCS_func = ext_load_CS;
+ setDS_func = ext_load_DS;
+ setES_func = ext_load_ES;
+ setSS_func = ext_load_SS;
+ setMSW_func = soft_ccpu_setMSW;
+ setDF_func = soft_ccpu_setDF;
+ setIF_func = soft_ccpu_setIF;
+ setTF_func = soft_ccpu_setTF;
+ setPF_func = soft_ccpu_setPF;
+ setAF_func = soft_ccpu_setAF;
+ setSF_func = soft_ccpu_setSF;
+ setZF_func = soft_ccpu_setZF;
+ setOF_func = soft_ccpu_setOF;
+ setCF_func = soft_ccpu_setCF;
+ setCPL_func = soft_ccpu_setCPL; /* not used in a2CPU */
+ setGDTR_base_func = soft_ccpu_setGDTR_base; /* not used in a2CPU */
+ setGDTR_limit_func = soft_ccpu_setGDTR_limit; /* not used in a2CPU */
+ setIDTR_base_func = soft_ccpu_setIDTR_base; /* not used in a2CPU */
+ setIDTR_limit_func = soft_ccpu_setIDTR_limit; /* not used in a2CPU */
+ setLDTR_func = soft_ccpu_setLDTR; /* not used in a2CPU */
+ setTR_func = soft_ccpu_setTR; /* not used in a2CPU */
+ setMSW_reserved_func = soft_ccpu_setMSW_reserved; /* not used in a2CPU */
+ setTS_func = soft_ccpu_setTS; /* not used in a2CPU */
+ setEM_func = soft_ccpu_setEM; /* not used in a2CPU */
+ setMP_func = soft_ccpu_setMP; /* not used in a2CPU */
+ setPE_func = soft_ccpu_setPE; /* not used in a2CPU */
+ setNT_func = soft_ccpu_setNT; /* not used in a2CPU */
+ setIOPL_func = soft_ccpu_setIOPL; /* not used in a2CPU */
+
+ /* SW HOST_SIMULATE function */
+ host_simulate_func = sw_host_simulate;
+}
+#endif CCPU
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifdef A2CPU
+/*
+ * --------------------------------------------
+ * ---- SUN_VA Assember CCPU Interface ----
+ * --------------------------------------------
+ */
+
+/* need extern definition for M[] */
+#include "sas.h"
+
+extern sreg INTEL_STATUS;
+extern void (*R_ROUTE)();
+extern int R_INTR;
+extern reg R_AX; /* Accumulator */
+extern reg R_BX; /* Base */
+extern reg R_CX; /* Count */
+extern reg R_DX; /* Data */
+extern reg R_SP; /* Stack Pointer */
+extern reg R_BP; /* Base pointer */
+extern reg R_SI; /* Source Index */
+extern reg R_DI; /* Destination Index */
+
+extern double_word R_OPA;
+extern double_word R_OPB;
+extern double_word R_OPR;
+extern int R_MISC_FLAGS;
+
+extern sys_addr R_IP; /* Instruction Pointer */
+
+extern sys_addr R_ACT_CS; /* Code Segment */
+extern sys_addr R_ACT_DS; /* Data Segment */
+extern sys_addr R_ACT_SS; /* Stack Segment */
+extern sys_addr R_ACT_ES; /* Extra Segment */
+
+extern sys_addr R_DEF_SS; /* Default SS register */
+extern sys_addr R_DEF_DS; /* Default DS register */
+
+extern void do_setSF();
+extern void do_setOF();
+extern void do_setPF();
+extern void do_setZF();
+extern void do_setCF();
+
+
+word soft_a2cpu_getAX ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getAX\n");
+#endif MIKE_DEBUG
+ return (R_AX.X);
+}
+
+half_word soft_a2cpu_getAH ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getAH\n");
+#endif MIKE_DEBUG
+ return (R_AX.byte.high);
+}
+
+half_word soft_a2cpu_getAL ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getAL\n");
+#endif MIKE_DEBUG
+ return (R_AX.byte.low);
+}
+
+word soft_a2cpu_getBX ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getBX\n");
+#endif MIKE_DEBUG
+ return (R_BX.X);
+}
+
+half_word soft_a2cpu_getBH ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getBH\n");
+#endif MIKE_DEBUG
+ return (R_BX.byte.high);
+}
+
+half_word soft_a2cpu_getBL ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getBL\n");
+#endif MIKE_DEBUG
+ return (R_BX.byte.low);
+}
+
+word soft_a2cpu_getCX ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getCX\n");
+#endif MIKE_DEBUG
+ return (R_CX.X);
+}
+
+half_word soft_a2cpu_getCH ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getCH\n");
+#endif MIKE_DEBUG
+ return (R_CX.byte.high);
+}
+
+half_word soft_a2cpu_getCL ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getCL\n");
+#endif MIKE_DEBUG
+ return (R_CX.byte.low);
+}
+
+word soft_a2cpu_getDX ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getDX\n");
+#endif MIKE_DEBUG
+ return (R_DX.X);
+}
+
+half_word soft_a2cpu_getDH ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getDH\n");
+#endif MIKE_DEBUG
+ return (R_DX.byte.high);
+}
+
+half_word soft_a2cpu_getDL ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getDL\n");
+#endif MIKE_DEBUG
+ return (R_DX.byte.low);
+}
+
+word soft_a2cpu_getSP ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getSP\n");
+#endif MIKE_DEBUG
+ return (R_SP.X);
+}
+
+word soft_a2cpu_getBP ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getBP\n");
+#endif MIKE_DEBUG
+ return (R_BP.X);
+}
+
+word soft_a2cpu_getSI ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getSI\n");
+#endif MIKE_DEBUG
+ return (R_SI.X);
+}
+
+word soft_a2cpu_getDI ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getDI\n");
+#endif MIKE_DEBUG
+ return (R_DI.X);
+}
+
+word soft_a2cpu_getIP ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getIP\n");
+#endif MIKE_DEBUG
+ return (R_IP - (sys_addr)M - (sys_addr)(getCS() << 4) );
+}
+
+
+double_word soft_a2cpu_getOPA ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getOPA\n");
+#endif MIKE_DEBUG
+ return (R_OPA);
+}
+
+double_word soft_a2cpu_getOPB ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getOPB\n");
+#endif MIKE_DEBUG
+ return (R_OPB);
+}
+
+double_word soft_a2cpu_getOPR ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getOPR=0x%x\n",R_OPR);
+#endif MIKE_DEBUG
+ return (R_OPR);
+}
+
+sys_addr soft_a2cpu_getSSD ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getSSD\n");
+#endif MIKE_DEBUG
+ return ((R_ACT_SS - (sys_addr)M) >> 4);
+}
+
+sys_addr soft_a2cpu_getDSD ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getDSD\n");
+#endif MIKE_DEBUG
+ return ((R_ACT_DS - (sys_addr)M) >> 4);
+}
+
+word soft_a2cpu_getCS ()
+{
+#ifdef MIKE_DEBUG
+unsigned int tmp;
+
+ tmp = ((R_ACT_CS - (sys_addr)M) >> 4);
+ fprintf (stderr,"getCS, return=0x%x [M=0x%x R_ACT_CS=0x%x]\n",tmp,M,R_ACT_CS);
+#endif MIKE_DEBUG
+ return ((R_ACT_CS - (sys_addr)M) >> 4);
+}
+
+word soft_a2cpu_getDS ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getDS\n");
+#endif MIKE_DEBUG
+ return (getDSD());
+}
+
+word soft_a2cpu_getES ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getES\n");
+#endif MIKE_DEBUG
+ return ((R_ACT_ES - (sys_addr)M) >> 4);
+}
+
+word soft_a2cpu_getSS ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getSS\n");
+#endif MIKE_DEBUG
+ return (getSSD());
+}
+
+word soft_a2cpu_getMSW ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getMSW\n");
+#endif MIKE_DEBUG
+ return ((m_s_w));
+}
+
+word soft_a2cpu_getDF ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getDF\n");
+#endif MIKE_DEBUG
+ return (INTEL_STATUS.DF);
+}
+
+word soft_a2cpu_getIF ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getIF\n");
+#endif MIKE_DEBUG
+ return (INTEL_STATUS.IF);
+}
+
+word soft_a2cpu_getTF ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getTF\n");
+#endif MIKE_DEBUG
+ return (INTEL_STATUS.TF);
+}
+
+word soft_a2cpu_getPF ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getPF=0x%x\n",pf_table[getOPR() & 0xff]);
+#endif MIKE_DEBUG
+ return (pf_table[getOPR() & 0xff]);
+}
+
+word soft_a2cpu_getAF ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getAF\n");
+#endif MIKE_DEBUG
+ return (((((getOPA()) ^ (getOPB())) ^ (getOPR())) >> 4) & 1);
+}
+
+word soft_a2cpu_getSF ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getSF\n");
+#endif MIKE_DEBUG
+ return ((IS_BYTE_OP ? getOPR() >> 7 : getOPR() >> 15 ) & 1);
+}
+
+word soft_a2cpu_getZF ()
+{
+#ifdef MIKE_DEBUG
+word tmp;
+
+ tmp = (REALLY_ZERO ? 1 : (IS_BYTE_OP ? ((getOPR() & 0xff) ? 0 : 1) : ((getOPR() & 0xffff) ? 0 : 1)));
+ fprintf (stderr,"getZF=0x%x\n",tmp);
+#endif MIKE_DEBUG
+ return (REALLY_ZERO ? 1 : (IS_BYTE_OP ? ((getOPR() & 0xff) ? 0 : 1) : ((getOPR() & 0xffff) ? 0 : 1)));
+}
+
+word soft_a2cpu_getOF ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getOF\n");
+#endif MIKE_DEBUG
+ return ((IS_BYTE_OP ? (((getOPR() ^ getOPA() ^ getOPB()) ^ (getOPR() >> 1)) >> 7) & 1 : ((getOPR() ^ getOPA() ^ getOPB()) ^ (getOPR() >> 1)) >> 15 ) & 1 );
+}
+
+word soft_a2cpu_getCF ()
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"getCF\n");
+#endif MIKE_DEBUG
+ return ((IS_BYTE_OP ? getOPR() >> 8 : getOPR() >> 16) & 1);
+}
+
+
+#define getRET()
+#define setRET(x)
+
+
+void soft_a2cpu_setAX (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setAX\n");
+#endif MIKE_DEBUG
+ R_AX.X = val;
+}
+
+void soft_a2cpu_setAH (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setAH\n");
+#endif MIKE_DEBUG
+ R_AX.byte.high = val;
+}
+
+void soft_a2cpu_setAL (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setAL\n");
+#endif MIKE_DEBUG
+ R_AX.byte.low = val;
+}
+
+void soft_a2cpu_setBX (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setBX\n");
+#endif MIKE_DEBUG
+ R_BX.X = val;
+}
+
+void soft_a2cpu_setBH (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setBH\n");
+#endif MIKE_DEBUG
+ R_BX.byte.high = val;
+}
+
+void soft_a2cpu_setBL (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setBL\n");
+#endif MIKE_DEBUG
+ R_BX.byte.low = val;
+}
+
+void soft_a2cpu_setCX (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setCX\n");
+#endif MIKE_DEBUG
+ R_CX.X = val;
+}
+
+void soft_a2cpu_setCH (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setCH\n");
+#endif MIKE_DEBUG
+ R_CX.byte.high = val;
+}
+
+void soft_a2cpu_setCL (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setCL\n");
+#endif MIKE_DEBUG
+ R_CX.byte.low = val;
+}
+
+void soft_a2cpu_setDX (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setDX\n");
+#endif MIKE_DEBUG
+ R_DX.X = val;
+}
+
+void soft_a2cpu_setDH (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setDH\n");
+#endif MIKE_DEBUG
+ R_DX.byte.high = val;
+}
+
+void soft_a2cpu_setDL (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setDL\n");
+#endif MIKE_DEBUG
+ R_DX.byte.low = val;
+}
+
+void soft_a2cpu_setSP (val)
+unsigned int val;
+{
+ R_SP.X = val;
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setSP to 0x%x [val=0x%x]\n",R_SP.X,val);
+#endif MIKE_DEBUG
+}
+
+void soft_a2cpu_setBP (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setBP\n");
+#endif MIKE_DEBUG
+ R_BP.X = val;
+}
+
+void soft_a2cpu_setSI (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setSI\n");
+#endif MIKE_DEBUG
+ R_SI.X = val;
+}
+
+void soft_a2cpu_setDI (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setDI\n");
+#endif MIKE_DEBUG
+ R_DI.X = val;
+}
+
+void soft_a2cpu_setIP (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+unsigned int tmp;
+#endif MIKE_DEBUG
+
+ R_IP = val + (sys_addr)M +(sys_addr) (getCS() << 4);
+#ifdef MIKE_DEBUG
+ tmp = getCS ();
+ fprintf (stderr,"setIP to 0x%x [M=0x%x getCS()=0x%x]\n",R_IP,M,tmp);
+#endif MIKE_DEBUG
+}
+
+void soft_a2cpu_setMSW (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setMSW\n");
+#endif MIKE_DEBUG
+ m_s_w = val;
+}
+
+void soft_a2cpu_setDF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setDF\n");
+#endif MIKE_DEBUG
+ INTEL_STATUS.DF = val;
+}
+
+void soft_a2cpu_setIF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setIF\n");
+#endif MIKE_DEBUG
+ INTEL_STATUS.IF = val;
+}
+
+void soft_a2cpu_setTF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setTF\n");
+#endif MIKE_DEBUG
+ INTEL_STATUS.TF = val;
+}
+
+void soft_a2cpu_setPF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+word tmp;
+#endif MIKE_DEBUG
+
+ do_setPF (val);
+#ifdef MIKE_DEBUG
+ tmp = soft_a2cpu_getPF();
+ fprintf (stderr,"setPF to 0x%x. Read back as 0x%x\n",val,tmp);
+#endif MIKE_DEBUG
+}
+
+void soft_a2cpu_setAF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setAF\n");
+#endif MIKE_DEBUG
+ setOPA (val << 4);
+ setOPB (getOPR() & 0x7f);
+}
+
+void soft_a2cpu_setSF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setSF\n");
+#endif MIKE_DEBUG
+ do_setSF (val);
+}
+
+void soft_a2cpu_setZF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setZF\n");
+#endif MIKE_DEBUG
+ do_setZF (val);
+}
+
+void soft_a2cpu_setOF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setOF\n");
+#endif MIKE_DEBUG
+ do_setOF (val);
+}
+
+void soft_a2cpu_setCF (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setCF\n");
+#endif MIKE_DEBUG
+ do_setCF (val);
+}
+
+void soft_a2cpu_setOPLEN (val)
+unsigned int val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setOPLEN\n");
+#endif MIKE_DEBUG
+ R_MISC_FLAGS &= 0x7fffffff;
+ R_MISC_FLAGS |= val;
+}
+
+void soft_a2cpu_setOPA (val)
+double_word val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setOPA\n");
+#endif MIKE_DEBUG
+ R_OPA = val;
+}
+
+void soft_a2cpu_setOPB (val)
+double_word val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setOPB\n");
+#endif MIKE_DEBUG
+ R_OPB = val;
+}
+
+void soft_a2cpu_setOPR (val)
+double_word val;
+{
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setOPR\n");
+#endif MIKE_DEBUG
+ R_OPR = val;
+}
+
+void soft_a2cpu_setSS (val)
+sys_addr val;
+{
+ R_ACT_SS = (sys_addr)M + (val << 4);
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setSS to 0x%x [M=0x%x,val=0x%x]\n",R_ACT_SS,M,val);
+#endif MIKE_DEBUG
+}
+
+void soft_a2cpu_setDS (val)
+sys_addr val;
+{
+ R_ACT_DS = (sys_addr)M + (val << 4);
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setDS to 0x%x [M=0x%x val=0x%x]\n",R_ACT_DS,M,val);
+#endif MIKE_DEBUG
+}
+
+void soft_a2cpu_setES (val)
+sys_addr val;
+{
+ R_ACT_ES = ((sys_addr)M + (val << 4));
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setES to 0x%x [M=0x%x val=0x%x]\n",R_ACT_ES,M,val);
+#endif MIKE_DEBUG
+}
+
+void soft_a2cpu_setCS (val)
+sys_addr val;
+{
+ R_ACT_CS = (sys_addr)M + (val << 4);
+#ifdef MIKE_DEBUG
+ fprintf (stderr,"setCS to 0x%x [M=0x%x val=0x%x]\n",R_ACT_CS,M,val);
+#endif MIKE_DEBUG
+}
+
+
+
+
+void
+load_sw_cpu_access_functions ()
+{
+ fprintf (stderr,"[load_sw_cpu_access_functions] init READ/WRITE functions.\n");
+
+ /* READ functions */
+ getAX_func = soft_a2cpu_getAX;
+ getAH_func = soft_a2cpu_getAH;
+ getAL_func = soft_a2cpu_getAL;
+ getBX_func = soft_a2cpu_getBX;
+ getBH_func = soft_a2cpu_getBH;
+ getBL_func = soft_a2cpu_getBL;
+ getCX_func = soft_a2cpu_getCX;
+ getCH_func = soft_a2cpu_getCH;
+ getCL_func = soft_a2cpu_getCL;
+ getDX_func = soft_a2cpu_getDX;
+ getDH_func = soft_a2cpu_getDH;
+ getDL_func = soft_a2cpu_getDL;
+ getSP_func = soft_a2cpu_getSP;
+ getBP_func = soft_a2cpu_getBP;
+ getSI_func = soft_a2cpu_getSI;
+ getDI_func = soft_a2cpu_getDI;
+ getIP_func = soft_a2cpu_getIP;
+ getOPA_func = soft_a2cpu_getOPA; /* not used in CCPU */
+ getOPB_func = soft_a2cpu_getOPB; /* not used in CCPU */
+ getOPR_func = soft_a2cpu_getOPR; /* not used in CCPU */
+ getSSD_func = soft_a2cpu_getSSD; /* not used in CCPU */
+ getDSD_func = soft_a2cpu_getDSD; /* not used in CCPU */
+ getCS_func = soft_a2cpu_getCS;
+ getDS_func = soft_a2cpu_getDS;
+ getES_func = soft_a2cpu_getES;
+ getSS_func = soft_a2cpu_getSS;
+ getMSW_func = soft_a2cpu_getMSW;
+ getDF_func = soft_a2cpu_getDF;
+ getIF_func = soft_a2cpu_getIF;
+ getTF_func = soft_a2cpu_getTF;
+ getPF_func = soft_a2cpu_getPF;
+ getAF_func = soft_a2cpu_getAF;
+ getSF_func = soft_a2cpu_getSF;
+ getZF_func = soft_a2cpu_getZF;
+ getOF_func = soft_a2cpu_getOF;
+ getCF_func = soft_a2cpu_getCF;
+
+
+ /* WRITE functions */
+ setAX_func = soft_a2cpu_setAX;
+ setAH_func = soft_a2cpu_setAH;
+ setAL_func = soft_a2cpu_setAL;
+ setBX_func = soft_a2cpu_setBX;
+ setBH_func = soft_a2cpu_setBH;
+ setBL_func = soft_a2cpu_setBL;
+ setCX_func = soft_a2cpu_setCX;
+ setCH_func = soft_a2cpu_setCH;
+ setCL_func = soft_a2cpu_setCL;
+ setDX_func = soft_a2cpu_setDX;
+ setDH_func = soft_a2cpu_setDH;
+ setDL_func = soft_a2cpu_setDL;
+ setSP_func = soft_a2cpu_setSP;
+ setBP_func = soft_a2cpu_setBP;
+ setSI_func = soft_a2cpu_setSI;
+ setDI_func = soft_a2cpu_setDI;
+ setIP_func = soft_a2cpu_setIP;
+ setMSW_func = soft_a2cpu_setMSW;
+ setDF_func = soft_a2cpu_setDF;
+ setIF_func = soft_a2cpu_setIF;
+ setTF_func = soft_a2cpu_setTF;
+ setPF_func = soft_a2cpu_setPF;
+ setAF_func = soft_a2cpu_setAF;
+ setSF_func = soft_a2cpu_setSF;
+ setZF_func = soft_a2cpu_setZF;
+ setOF_func = soft_a2cpu_setOF;
+ setCF_func = soft_a2cpu_setCF;
+ setOPLEN_func = soft_a2cpu_setOPLEN; /* not used in CCPU */
+ setOPA_func = soft_a2cpu_setOPA; /* not used in CCPU */
+ setOPB_func = soft_a2cpu_setOPB; /* not used in CCPU */
+ setOPR_func = soft_a2cpu_setOPR; /* not used in CCPU */
+ setSS_func = soft_a2cpu_setSS;
+ setDS_func = soft_a2cpu_setDS;
+ setES_func = soft_a2cpu_setES;
+ setCS_func = soft_a2cpu_setCS;
+
+ /* SW HOST_SIMULATE function */
+ host_simulate_func = sw_host_simulate;
+}
+#endif A2CPU
+
+
+#endif /* CPU_30_STYLE */
+
+
+
+
+
+
+
+
+
+
+#ifdef SUN_VA
+/*
+ * ---- SUN_VA HARDWARE SUPPORT ----
+ * needed regardless which softCPU is being used.
+ * ---- ----
+ */
+
+
+extern union SDOS_XTSS *sdos_xtss_ptr;
+
+/*
+ * The XTSS fields are stored in i486 format. SWAP the fields
+ * when accessed from Host-side before writes and after reads.
+ */
+
+#define FLAGS_CF 0x00000001
+#define FLAGS_PF 0x00000004
+#define FLAGS_AF 0x00000010
+#define FLAGS_ZF 0x00000040
+#define FLAGS_SF 0x00000080
+#define FLAGS_TF 0x00000100
+#define FLAGS_IF 0x00000200
+#define FLAGS_DF 0x00000400
+#define FLAGS_OF 0x00000800
+#define FLAGS_IOPL 0x00003000
+#define FLAGS_NT 0x00004000
+#define FLAGS_RF 0x00010000
+#define FLAGS_VM 0x00020000
+
+
+static word word_reg;
+static half_word hword_reg;
+
+word hard_cpu_getAX ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.ax), &word_reg);
+ return (word_reg);
+}
+
+half_word hard_cpu_getAH ()
+{
+ sas_load (&(sdos_xtss_ptr->h.ah), &hword_reg);
+ return (hword_reg);
+}
+
+half_word hard_cpu_getAL ()
+{
+ sas_load (&(sdos_xtss_ptr->h.al), &hword_reg);
+ return (hword_reg);
+}
+
+word hard_cpu_getBX ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.bx), &word_reg);
+ return (word_reg);
+}
+
+half_word hard_cpu_getBH ()
+{
+ sas_load (&(sdos_xtss_ptr->h.bh), &hword_reg);
+ return (hword_reg);
+}
+
+half_word hard_cpu_getBL ()
+{
+ sas_load (&(sdos_xtss_ptr->h.bl), &hword_reg);
+ return (hword_reg);
+}
+
+word hard_cpu_getCX ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.cx), &word_reg);
+ return (word_reg);
+}
+
+half_word hard_cpu_getCH ()
+{
+ sas_load (&(sdos_xtss_ptr->h.ch), &hword_reg);
+ return (hword_reg);
+}
+
+half_word hard_cpu_getCL ()
+{
+ sas_load (&(sdos_xtss_ptr->h.cl), &hword_reg);
+ return (hword_reg);
+}
+
+word hard_cpu_getDX ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.dx), &word_reg);
+ return (word_reg);
+}
+
+half_word hard_cpu_getDH ()
+{
+ sas_load (&(sdos_xtss_ptr->h.dh), &hword_reg);
+ return (hword_reg);
+}
+
+half_word hard_cpu_getDL ()
+{
+ sas_load (&(sdos_xtss_ptr->h.dl), &hword_reg);
+ return (hword_reg);
+}
+
+word hard_cpu_getSP ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.sp), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getBP ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.bp), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getSI ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.si), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getDI ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.di), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getIP ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.ip), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getCS ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.cs), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getDS ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.ds), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getES ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.es), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getSS ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.ss), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getMSW ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ return (word_reg);
+}
+
+word hard_cpu_getDF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_DF)
+ return (1);
+ else
+ return (0);
+}
+
+word hard_cpu_getIF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_IF)
+ return (1);
+ else
+ return (0);
+}
+
+word hard_cpu_getTF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_TF)
+ return (1);
+ else
+ return (0);
+}
+
+word hard_cpu_getPF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_PF)
+ return (1);
+ else
+ return (0);
+}
+
+word hard_cpu_getAF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_AF)
+ return (1);
+ else
+ return (0);
+}
+
+word hard_cpu_getSF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_SF)
+ return (1);
+ else
+ return (0);
+}
+
+word hard_cpu_getZF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_ZF)
+ return (1);
+ else
+ return (0);
+}
+
+word hard_cpu_getOF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_OF)
+ return (1);
+ else
+ return (0);
+}
+
+word hard_cpu_getCF ()
+{
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &word_reg);
+ if (word_reg & FLAGS_CF)
+ return (1);
+ else
+ return (0);
+}
+
+
+
+
+void hard_cpu_setAX (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.ax), val);
+}
+
+void hard_cpu_setAH (val)
+unsigned int val;
+{
+ sas_store (&(sdos_xtss_ptr->h.ah), val);
+}
+
+void hard_cpu_setAL (val)
+unsigned int val;
+{
+ sas_store (&(sdos_xtss_ptr->h.al), val);
+}
+
+void hard_cpu_setBX (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.bx), val);
+}
+
+void hard_cpu_setBH (val)
+unsigned int val;
+{
+ sas_store (&(sdos_xtss_ptr->h.bh), val);
+}
+
+void hard_cpu_setBL (val)
+unsigned int val;
+{
+ sas_store (&(sdos_xtss_ptr->h.bl), val);
+}
+
+void hard_cpu_setCX (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.cx), val);
+}
+
+void hard_cpu_setCH (val)
+unsigned int val;
+{
+ sas_store (&(sdos_xtss_ptr->h.ch), val);
+}
+
+void hard_cpu_setCL (val)
+unsigned int val;
+{
+ sas_store (&(sdos_xtss_ptr->h.cl), val);
+}
+
+void hard_cpu_setDX (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.dx), val);
+}
+
+void hard_cpu_setDH (val)
+unsigned int val;
+{
+ sas_store (&(sdos_xtss_ptr->h.dh), val);
+}
+
+void hard_cpu_setDL (val)
+unsigned int val;
+{
+ sas_store (&(sdos_xtss_ptr->h.dl), val);
+}
+
+void hard_cpu_setSP (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.sp), val);
+}
+
+void hard_cpu_setBP (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.bp), val);
+}
+
+void hard_cpu_setSI (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.si), val);
+}
+
+void hard_cpu_setDI (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.di), val);
+}
+
+void hard_cpu_setIP (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.ip), val);
+}
+
+void hard_cpu_setCS (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.cs), val);
+}
+
+void hard_cpu_setDS (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.ds), val);
+}
+
+void hard_cpu_setES (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.es), val);
+}
+
+void hard_cpu_setSS (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.ss), val);
+}
+
+void hard_cpu_setMSW (val)
+unsigned int val;
+{
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), val);
+}
+
+void hard_cpu_setDF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_DF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_DF)));
+}
+
+void hard_cpu_setIF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_IF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_IF)));
+}
+
+void hard_cpu_setTF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_TF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_TF)));
+}
+
+void hard_cpu_setPF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_PF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_PF)));
+}
+
+void hard_cpu_setAF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_AF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_AF)));
+}
+
+void hard_cpu_setSF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_SF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_SF)));
+}
+
+void hard_cpu_setZF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_ZF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_ZF)));
+}
+
+void hard_cpu_setOF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_OF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_OF)));
+}
+
+void hard_cpu_setCF (val)
+unsigned int val;
+{
+unsigned short temp;
+
+ sas_loadw_swap (&(sdos_xtss_ptr->x.flags), &temp);
+ if (val)
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp | FLAGS_CF));
+ else
+ sas_storew_swap (&(sdos_xtss_ptr->x.flags), (temp & (~FLAGS_CF)));
+}
+
+
+
+/* these routines load the CPU access functions pointers for HW and SW. */
+void load_hw_cpu_access_functions ()
+{
+ /* READ functions */
+ getAX_func = hard_cpu_getAX;
+ getAH_func = hard_cpu_getAH;
+ getAL_func = hard_cpu_getAL;
+ getBX_func = hard_cpu_getBX;
+ getBH_func = hard_cpu_getBH;
+ getBL_func = hard_cpu_getBL;
+ getCX_func = hard_cpu_getCX;
+ getCH_func = hard_cpu_getCH;
+ getCL_func = hard_cpu_getCL;
+ getDX_func = hard_cpu_getDX;
+ getDH_func = hard_cpu_getDH;
+ getDL_func = hard_cpu_getDL;
+ getSP_func = hard_cpu_getSP;
+ getBP_func = hard_cpu_getBP;
+ getSI_func = hard_cpu_getSI;
+ getDI_func = hard_cpu_getDI;
+ getIP_func = hard_cpu_getIP;
+ getCS_func = hard_cpu_getCS;
+ getDS_func = hard_cpu_getDS;
+ getES_func = hard_cpu_getES;
+ getSS_func = hard_cpu_getSS;
+ getMSW_func = hard_cpu_getMSW;
+ getDF_func = hard_cpu_getDF;
+ getIF_func = hard_cpu_getIF;
+ getTF_func = hard_cpu_getTF;
+ getPF_func = hard_cpu_getPF;
+ getAF_func = hard_cpu_getAF;
+ getSF_func = hard_cpu_getSF;
+ getZF_func = hard_cpu_getZF;
+ getOF_func = hard_cpu_getOF;
+ getCF_func = hard_cpu_getCF;
+
+ /* WRITE functions */
+ setAX_func = hard_cpu_setAX;
+ setAH_func = hard_cpu_setAH;
+ setAL_func = hard_cpu_setAL;
+ setBX_func = hard_cpu_setBX;
+ setBH_func = hard_cpu_setBH;
+ setBL_func = hard_cpu_setBL;
+ setCX_func = hard_cpu_setCX;
+ setCH_func = hard_cpu_setCH;
+ setCL_func = hard_cpu_setCL;
+ setDX_func = hard_cpu_setDX;
+ setDH_func = hard_cpu_setDH;
+ setDL_func = hard_cpu_setDL;
+ setSP_func = hard_cpu_setSP;
+ setBP_func = hard_cpu_setBP;
+ setSI_func = hard_cpu_setSI;
+ setDI_func = hard_cpu_setDI;
+ setIP_func = hard_cpu_setIP;
+ setCS_func = hard_cpu_setCS;
+ setDS_func = hard_cpu_setDS;
+ setES_func = hard_cpu_setES;
+ setSS_func = hard_cpu_setSS;
+ setMSW_func = hard_cpu_setMSW;
+ setDF_func = hard_cpu_setDF;
+ setIF_func = hard_cpu_setIF;
+ setTF_func = hard_cpu_setTF;
+ setPF_func = hard_cpu_setPF;
+ setAF_func = hard_cpu_setAF;
+ setSF_func = hard_cpu_setSF;
+ setZF_func = hard_cpu_setZF;
+ setOF_func = hard_cpu_setOF;
+ setCF_func = hard_cpu_setCF;
+
+ /* HW HOST_SIMULATE function */
+ host_simulate_func = hw_host_simulate;
+}
+
+#endif SUN_VA
diff --git a/private/mvdm/softpc.new/host/src/nt_cpu.c b/private/mvdm/softpc.new/host/src/nt_cpu.c
new file mode 100644
index 000000000..7dd303d9d
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_cpu.c
@@ -0,0 +1,344 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include "insignia.h"
+#include "host_def.h"
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : NT 3.0 CPU initialization
+ *
+ * Description : Initialize the CPU and its registers.
+ *
+ * Author : Paul Huckle / Henry Nash
+ *
+ * Notes : None
+ */
+
+static char SccsID[]="@(#)sun4_a3cpu.c 1.2 5/24/91 Copyright Insignia Solutions Ltd.";
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <malloc.h>
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "ios.h"
+#include "bios.h"
+#include "trace.h"
+#include "yoda.h"
+#include "debug.h"
+
+#include "sim32.h"
+
+#ifdef CPU_40_STYLE
+#include "cpu_c.h"
+#endif
+
+GLOBAL quick_event_delays host_delays;
+GLOBAL host_addr Start_of_M_area;
+GLOBAL IHPE Length_of_M_area;
+#ifdef A2CPU
+extern void route_on();
+extern void route_on_fragment_no_interrupt_check();
+extern void service_int();
+#endif
+
+#ifdef I286
+extern word m_s_w;
+word protected_mode;
+word gdt_limit;
+long gdt_base;
+word idt_limit;
+long idt_base;
+#endif
+
+#define setBASE(base, value) base = (0xff000000 | (value & 0xffffff))
+#define setLIMIT(limit, value) limit = value
+
+#ifndef PROD
+ extern RTL_CRITICAL_SECTION IcaLock;
+#endif
+
+
+
+
+/*
+ Host_start_cpu: This function starts up the cpu emulation if
+ we are running a software emulation, or if a 486 is present,
+ starts up this emulation.
+*/
+void host_start_cpu()
+{
+ cpu_simulate ();
+}
+
+
+/*
+ host_simulate: This function starts up the cpu emulation
+ for recursive CPU calls from the Insignia BIOS
+*/
+void host_simulate()
+{
+ ASSERT(IcaLock.OwningThread != NtCurrentTeb()->ClientId.UniqueThread);
+
+#ifdef _ALPHA_
+ //
+ // For Alpha AXP, set the arithmetic trap ignore bit since the code
+ // generators are incapable of generating proper Alpha instructions
+ // that follow trap shadow rules.
+ //
+ // N.B. In this mode all floating point arithmetic traps are ignored.
+ // Imprecise exceptions are not converted to precise exceptions
+ // and correct IEEE results are not stored in the destination
+ // registers of trapping instructions. Only the hardware FPCR
+ // status bits can be used to determine if any traps occurred.
+ //
+
+ ((PSW_FPCR)&(NtCurrentTeb()->FpSoftwareStatusRegister))->ArithmeticTrapIgnore = 1;
+#endif
+
+ cpu_simulate ();
+
+ ASSERT(IcaLock.OwningThread != NtCurrentTeb()->ClientId.UniqueThread);
+}
+
+
+/*
+ Host_set_hw_int: Cause a hardware interrupt to be generated. For
+ software cpu this just means setting a bit in cpu_interrupt_map.
+*/
+void host_set_hw_int()
+{
+ cpu_interrupt(CPU_HW_INT, 0);
+}
+
+/*
+ Host_clear_hw_int: Cause a hardware interrupt to be cleared. For
+ software cpu this just means clearing a bit in cpu_interrupt_map.
+ Monitor has it's own version, a3 cpu has it's own (differently named
+ version).
+*/
+#ifndef MONITOR
+void host_clear_hw_int()
+{
+#ifndef CCPU
+#ifdef CPU_40_STYLE
+
+ cpu_clearHwInt();
+#else
+ IMPORT void a3_cpu_clear_hw_int();
+
+ a3_cpu_clear_hw_int();
+#endif /* CPU_40_STYLE */
+#endif /* not CCPU */
+}
+#endif
+
+
+#ifdef CCPU
+
+void host_cpu_init() {}
+
+#endif
+
+#ifdef A3CPU
+void host_cpu_init()
+{
+ host_delays.com_delay = 10;
+ host_delays.keyba_delay = 8;
+ host_delays.timer_delay = 7;
+ host_delays.fdisk_delay_1 = 100;
+ host_delays.fdisk_delay_2 = 750;
+ host_delays.fla_delay = 0;
+}
+
+void setSTATUS(word flags)
+{
+ setNT((flags >> 14) & 1);
+ setIOPL((flags >> 12) & 3);
+ setOF((flags >> 11) & 1);
+ setDF((flags >> 10) & 1);
+ setIF((flags >> 9) & 1);
+ setTF((flags >> 8) & 1);
+ setSF((flags >> 7) & 1);
+ setZF((flags >> 6) & 1);
+ setAF((flags >> 4) & 1);
+ setPF((flags >> 2) & 1);
+ setCF(flags & 1);
+}
+
+/*
+ * Do the Iret for the benefit of the Iret hooks.
+ * Unwind stack for flags, cs & ip.
+ * Seems too simple - does the CPU require more cleanup information???
+ * or will the unwinding bop sort it out??
+ */
+VOID EmulatorEndIretHook()
+{
+ UNALIGNED word *sptr;
+
+ /* Stack points at CS:IP & Flags of interrupted instruction */
+ sptr = (word *)Sim32GetVDMPointer( (getSS() << 16)|getSP(), 2, (UCHAR)(getPE() ? TRUE : FALSE));
+ if (sptr)
+ {
+ setIP(*sptr++);
+ setCS(*sptr++);
+ setSTATUS(*sptr);
+ setSP(getSP()+6);
+ }
+#ifndef PROD
+ else
+ printf("NTVDM extreme badness - can't get stack pointer %x:%x mode:%d\n",getSS(), getSP(), getPE());
+#endif /* PROD */
+}
+#endif /* A3CPU */
+
+void host_cpu_reset()
+{
+}
+
+
+void host_cpu_interrupt()
+{
+}
+
+#ifdef CPU_40_STYLE
+
+typedef struct NT_CPU_REG {
+ IU32 *nano_reg; /* where the nano CPU keeps the register */
+ IU32 *reg; /* where the light compiler keeps the reg */
+ IU32 *saved_reg; /* where currently unused bits are kept */
+ IU32 universe_8bit_mask;/* is register in 8-bit form? */
+ IU32 universe_16bit_mask;/* is register in 16-bit form? */
+} NT_CPU_REG;
+
+typedef struct NT_CPU_INFO {
+ /* Variables for deciding what mode we're in */
+ BOOL *in_nano_cpu; /* is the Nano CPU executing? */
+ IU32 *universe; /* the mode that the CPU is in */
+
+ /* General purpose register pointers */
+ NT_CPU_REG eax, ebx, ecx, edx, esi, edi, ebp;
+
+ /* Variables for getting SP or ESP. */
+ BOOL *stack_is_big; /* is the stack 32-bit? */
+ IU32 *nano_esp; /* where the Nano CPU keeps ESP */
+ IU8 **host_sp; /* ptr to variable holding stack pointer as a
+ host address */
+ IU8 **ss_base; /* ptr to variables holding base of SS as a
+ host address */
+ IU32 *esp_sanctuary; /* top 16 bits of ESP if we're now using SP */
+
+ IU32 *eip;
+
+ /* Segment registers. */
+ IU16 *cs, *ds, *es, *fs, *gs, *ss;
+
+ IU32 *flags;
+
+ /* CR0, mainly to let us figure out if we're in real or protect mode */
+ IU32 *cr0;
+} NT_CPU_INFO;
+
+GLOBAL NT_CPU_INFO nt_cpu_info;
+
+LOCAL void initNtCpuRegInfo IFN6(
+ NT_CPU_REG *, info,
+ IU32 *, nano_reg,
+ IU32 *, main_reg,
+ IU32 *, saved_reg,
+ IU32, in_8bit_form,
+ IU32, in_16bit_form
+)
+{
+ info->nano_reg = nano_reg;
+ info->reg = main_reg;
+ info->saved_reg = saved_reg;
+ info->universe_8bit_mask = in_8bit_form;
+ info->universe_16bit_mask = in_16bit_form;
+}
+
+
+
+GLOBAL void InitNtCpuInfo IFN0()
+{
+ BOOL *gdp_bool;
+
+ /* Variables for deciding what mode we're in, and hence where the */
+ /* register values are kept. */
+
+ /* Horrible hack, part 1. InNanoCpu is a BOOL, so GLOBAL_InNanoCpu */
+ /* is not an l-value, hence we can't take its address. */
+#ifdef ALPHA
+ nt_cpu_info.in_nano_cpu = (BOOL *) ((IHPE) GDP_PTR + 1223);
+#else /* ALPHA */
+ nt_cpu_info.in_nano_cpu = (BOOL *) ((IHPE) GDP_PTR + 631);
+#endif /* ALPHA */
+#ifndef PROD
+ gdp_bool = (BOOL *) ((IHPE) GDP_PTR + GdpOffsetFromName("InNanoCpu"));
+ if (nt_cpu_info.in_nano_cpu != gdp_bool) {
+ always_trace0("InNanoCpu GDP offset will be wrong in PROD builds");
+ }
+ nt_cpu_info.in_nano_cpu = gdp_bool;
+#endif
+
+ nt_cpu_info.universe = &GLOBAL_CurrentUniverse;
+
+ /* Variables needed to get the value SP or ESP. */
+
+ /* Horrible hack, part 2: as for InNanoCpu, so for stackIsBig. */
+#ifdef ALPHA
+ nt_cpu_info.stack_is_big = (BOOL *) ((IHPE) GDP_PTR + 7047);
+#else /* ALPHA */
+ nt_cpu_info.stack_is_big = (BOOL *) ((IHPE) GDP_PTR + 4355);
+#endif /* ALPHA */
+#ifndef PROD
+ gdp_bool = (BOOL *) ((IHPE) GDP_PTR + GdpOffsetFromName("stackIsBig"));
+ if (nt_cpu_info.stack_is_big != gdp_bool) {
+ always_trace0("stackIsBig GDP offset will be wrong in PROD builds");
+ }
+ nt_cpu_info.stack_is_big = gdp_bool;
+#endif
+
+ nt_cpu_info.nano_esp = &GLOBAL_nanoEsp;
+ nt_cpu_info.host_sp = &GLOBAL_HSP;
+ nt_cpu_info.ss_base = &GLOBAL_notionalSsBase;
+ nt_cpu_info.esp_sanctuary = &GLOBAL_ESPsanctuary;
+
+ /* Pointers to the segment registers. */
+ nt_cpu_info.cs = &GLOBAL_CsSel;
+ nt_cpu_info.ds = &GLOBAL_DsSel;
+ nt_cpu_info.es = &GLOBAL_EsSel;
+ nt_cpu_info.fs = &GLOBAL_FsSel;
+ nt_cpu_info.gs = &GLOBAL_GsSel;
+ nt_cpu_info.ss = &GLOBAL_SsSel;
+
+ /* EIP & flags, neither of which are likely to be very reliable. */
+ nt_cpu_info.eip = &GLOBAL_CleanedRec;
+ nt_cpu_info.flags = &GLOBAL_EFLAGS;
+
+ nt_cpu_info.cr0 = &GLOBAL_R_CR0;
+ /* General purpose registers. */
+ initNtCpuRegInfo(&nt_cpu_info.eax, &GLOBAL_nanoEax, &GLOBAL_R_EAX,
+ &GLOBAL_EAXsaved, 1 << ConstraintRAL_LS8,
+ 1 << ConstraintRAX_LS16);
+ initNtCpuRegInfo(&nt_cpu_info.ebx, &GLOBAL_nanoEbx, &GLOBAL_R_EBX,
+ &GLOBAL_EBXsaved, 1 << ConstraintRBL_LS8,
+ 1 << ConstraintRBX_LS16);
+ initNtCpuRegInfo(&nt_cpu_info.ecx, &GLOBAL_nanoEcx, &GLOBAL_R_ECX,
+ &GLOBAL_ECXsaved, 1 << ConstraintRCL_LS8,
+ 1 << ConstraintRCX_LS16);
+ initNtCpuRegInfo(&nt_cpu_info.edx, &GLOBAL_nanoEdx, &GLOBAL_R_EDX,
+ &GLOBAL_EDXsaved, 1 << ConstraintRDL_LS8,
+ 1 << ConstraintRDX_LS16);
+ initNtCpuRegInfo(&nt_cpu_info.esi, &GLOBAL_nanoEsi, &GLOBAL_R_ESI,
+ &GLOBAL_ESIsaved, 0, 1 << ConstraintRSI_LS16);
+ initNtCpuRegInfo(&nt_cpu_info.edi, &GLOBAL_nanoEdi, &GLOBAL_R_EDI,
+ &GLOBAL_EDIsaved, 0, 1 << ConstraintRDI_LS16);
+ initNtCpuRegInfo(&nt_cpu_info.ebp, &GLOBAL_nanoEbp, &GLOBAL_R_EBP,
+ &GLOBAL_EBPsaved, 0, 1 << ConstraintRBP_LS16);
+}
+
+#endif /* CPU_40_STYLE */
diff --git a/private/mvdm/softpc.new/host/src/nt_det.c b/private/mvdm/softpc.new/host/src/nt_det.c
new file mode 100644
index 000000000..398907e66
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_det.c
@@ -0,0 +1,1611 @@
+#include <windows.h>
+#include "host_def.h"
+#include "insignia.h"
+#include "vdm.h"
+
+/*
+ * ==========================================================================
+ * Name: nt_det.c
+ * Author: Jerry Sexton
+ * Derived From:
+ * Created On: 6th August 1992
+ * Purpose: This module contains the code for the thread which
+ * detects transitions between windowed and full-screen.
+ *
+ * (c)Copyright Insignia Solutions Ltd., 1992. All rights reserved.
+ * ==========================================================================
+ *
+ * Modifications:
+ *
+ * Tim August 92. Full-screen and windowed transitions now switch between
+ * SoftPC video BIOS and host PC video BIOS.
+ *
+ */
+
+/*
+ * ==========================================================================
+ * Other includes
+ * ==========================================================================
+ */
+#include <stdlib.h>
+#include <ntddvdeo.h>
+#include "xt.h"
+#include CpuH
+#include "gmi.h"
+#include "gvi.h"
+#include "ios.h"
+#include "sas.h"
+#include "gfx_upd.h"
+#include "egacpu.h"
+#include "egaports.h"
+#include "egamode.h"
+#include "egagraph.h"
+#include "video.h"
+#include "conapi.h"
+#include "host_rrr.h"
+#include "debug.h"
+#include "error.h"
+#include "config.h"
+#include "idetect.h"
+#include "nt_uis.h"
+#include "nt_fulsc.h"
+#include "nt_graph.h"
+#include "nt_mouse.h"
+#include "nt_thred.h"
+#include "nt_reset.h"
+#include "nt_eoi.h"
+#include "nt_event.h"
+
+/*
+ * ==========================================================================
+ * Macros
+ * ==========================================================================
+ */
+#define SUSP_FAILURE 0xffffffff
+
+
+//
+// A bunch of imports
+//
+extern DISPLAY_MODE choose_mode[];
+
+
+
+/*
+ * ==========================================================================
+ * Global data
+ * ==========================================================================
+ */
+
+/* Size of video save block. */
+GLOBAL DWORD stateLength;
+
+/* Video save block pointer. */
+GLOBAL PVIDEO_HARDWARE_STATE_HEADER videoState;
+GLOBAL PVOID textState; // Tim Oct 92.
+
+/* Name of the shared video block. */
+GLOBAL WCHAR_STRING videoSection;
+GLOBAL WCHAR_STRING textSection; // Tim Oct 92
+
+#ifdef X86GFX
+/* Hand-shaking events. */
+GLOBAL HANDLE hStartHardwareEvent;
+GLOBAL HANDLE hEndHardwareEvent;
+#endif
+
+/* Flag to stop host_simulates on this thread executing timer tick code. */
+GLOBAL BOOL NoTicks;
+
+/*
+** Tim Oct 92.
+** New strategy for windowed graphics updates. A shared buffer with Console
+** will remove need to copy the new data over, just pass a rectangle co-ord
+** instead. But we still need to copy into the buffer.
+*/
+GLOBAL PBYTE *textBuffer;
+GLOBAL COORD textBufferSize; // Dimensions of the shared buffer
+
+GLOBAL BOOL Frozen256Packed = FALSE; // use packed 256 mode paint routine
+
+
+
+
+/*
+ * ==========================================================================
+ * Local data
+ * ==========================================================================
+ */
+
+/* Variable that indicates if we are in a non-standard VGA mode. */
+LOCAL BOOL inAFunnyMode = FALSE;
+LOCAL BOOL ModeSetBatch = FALSE;
+
+/* Storage for the frozen-window thread handle. */
+LOCAL HANDLE freezeHandle = (HANDLE)0;
+
+
+
+/*
+ * ==========================================================================
+ * Local function declarations
+ * ==========================================================================
+ */
+
+#undef LOCAL
+#define LOCAL
+
+LOCAL VOID getCursorInfo(word *, half_word *, half_word *, half_word *);
+LOCAL VOID setCursorInfo(word, half_word, half_word, half_word);
+LOCAL VOID windowedToFullScreen(SHORT, BOOL);
+LOCAL VOID fullScreenToWindowed(VOID);
+LOCAL VOID syncHardwareToVGAEmulation(SHORT);
+LOCAL VOID syncVGAEmulationToHardware(VOID);
+LOCAL BOOL funnyMode(VOID);
+LOCAL VOID freezeWindow(VOID);
+#ifndef PROD
+LOCAL VOID dumpBlock(VOID);
+LOCAL VOID dumpPlanes(UTINY *, UTINY *, UTINY *, UTINY *);
+#endif /* PROD */
+
+/*
+ * ==========================================================================
+ * Global functions
+ * ==========================================================================
+ */
+
+/*
+** Tim Oct 92
+** Centralised Console funx.
+*/
+
+GLOBAL VOID doNullRegister()
+{
+ DWORD dummylen;
+ PVOID dummyptr;
+ COORD dummycoord;
+
+ if( !RegisterConsoleVDM( CONSOLE_UNREGISTER_VDM,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ &dummylen,
+ &dummyptr,
+ NULL,
+ 0,
+ dummycoord,
+ &dummyptr
+ )
+ )
+ ErrorExit();
+#ifdef X86GFX
+ sc.Registered = FALSE;
+#endif
+
+}
+
+/*
+*******************************************************************
+** initTextSection()
+*******************************************************************
+*/
+GLOBAL VOID initTextSection(VOID)
+{
+ DWORD flags;
+
+ //
+ // VideoSection size is determined by nt video driver
+ // TextSectionSize is 80 * 50 * BytesPerCharacter
+ // on risc BytesPerCharacter is 4 (interleaved vga planes)
+ // on x86 BytesPerCharacter is 2 (only char\attr)
+ //
+ textBufferSize.X = 80;
+ textBufferSize.Y = 50;
+
+#ifdef X86GFX
+ /*
+ * Deallocate the regen area if we start up fullscreen. We have to do this
+ * before we call RegisterConsoleVDM. Note that's right before the register
+ * call to make sure no one tries to allocate any memory (eg create a
+ * section) that could nick bits of the video hole, causing bye-byes.
+ */
+ if (!GetConsoleDisplayMode(&flags))
+ ErrorExit();
+ savedScreenState = sc.ScreenState = (flags & CONSOLE_FULLSCREEN_HARDWARE) ?
+ FULLSCREEN : WINDOWED;
+ sas_store_no_check((int10_seg << 4) + useHostInt10, (half_word)sc.ScreenState);
+
+ if (sc.ScreenState == FULLSCREEN)
+ LoseRegenMemory();
+
+#else
+ sc.ScreenState = WINDOWED;
+#endif
+
+ if( !RegisterConsoleVDM( VDMForWOW ?
+ CONSOLE_REGISTER_WOW : CONSOLE_REGISTER_VDM,
+#ifdef X86GFX
+ hStartHardwareEvent,
+ hEndHardwareEvent,
+#else
+ NULL,
+ NULL,
+#endif
+ NULL, // sectionname no longer used
+ 0, // sectionnamelen no longer used
+ &stateLength,
+ (PVOID *) &videoState,
+ NULL, // sectionname no longer used
+ 0, // sectionnamelen no longer used
+ textBufferSize,
+ (PVOID *) &textBuffer
+ )
+ )
+ ErrorExit();
+
+#ifdef X86GFX
+ /* stateLength can be 0 if fullscreen is disabled in the console */
+ if(stateLength)
+ RtlZeroMemory((BYTE *)videoState, sizeof(VIDEO_HARDWARE_STATE_HEADER));
+ sc.Registered = TRUE;
+#endif
+
+} /* end initTextSection() */
+
+#ifdef X86GFX
+
+/***************************************************************************
+ * Function: *
+ * InitDetect *
+ * *
+ * Description: *
+ * Does detection initialisation. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID InitDetect(VOID)
+{
+
+ /*
+ * Register start and end events with the console. These events are used
+ * when gaining or losing control of the hardware.
+ */
+ hStartHardwareEvent = CreateEvent((LPSECURITY_ATTRIBUTES) NULL,
+ FALSE,
+ FALSE,
+ NULL);
+ hEndHardwareEvent = CreateEvent((LPSECURITY_ATTRIBUTES) NULL,
+ FALSE,
+ FALSE,
+ NULL);
+ if ((hStartHardwareEvent == NULL) || (hEndHardwareEvent == NULL))
+ ErrorExit();
+
+ /* Poll the event to try and get rid of any console queued sets
+ * This shouldn't be needed (or shouldn't work) but something along
+ * those lines seems to be happening at the moment.
+ */
+ WaitForSingleObject(hStartHardwareEvent, 0);
+
+
+#ifdef SEPARATE_DETECT_THREAD
+ /* Go into hand-shaking loop. */
+ while (WaitForSingleObject(hStartHardwareEvent, (DWORD) -1) == 0)
+ DoHandShake();
+
+ /* We have exited the loop so something funny must have happened. */
+ ErrorExit();
+#endif
+
+}
+#ifdef SEPARATE_DETECT_THREAD
+
+/***************************************************************************
+ * Function: *
+ * CreateDetectThread *
+ * *
+ * Description: *
+ * Creates the detection thread. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID CreateDetectThread(VOID)
+{
+ DWORD detectID;
+ HANDLE detectHandle;
+
+
+ /*
+ * If this codes is activated you must close the thread handle
+ * 28-Feb-1993 Jonle
+ */
+
+
+ /* Create the detection thread. */
+ detectHandle = CreateThread((LPSECURITY_ATTRIBUTES) NULL,
+ DETECT_THREAD_SIZE,
+ (LPTHREAD_START_ROUTINE) InitDetect,
+ (LPVOID) NULL,
+ (DWORD) 0,
+ &detectID);
+ if (detectHandle == -1)
+ ErrorExit();
+}
+#endif /* SEPARATE_DETECT_THREAD */
+
+/***************************************************************************
+ * Function: *
+ * DoHandShake *
+ * *
+ * Description: *
+ * Does the hand-shaking with the console server. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID DoHandShake(VOID)
+{
+ /*
+ * ICA in's and out's cause a critical section to be entered. As some
+ * video register out's do ICA out's, we don't want the main thread to be
+ * suspended while doing ICA in's or out's as this will cause a race
+ * when the the switching code starts writing to the relevant video
+ * registers. So wait until the main thread is out of the critical section
+ * before suspending it.
+ */
+ host_ica_lock();
+
+ /*
+ * To stop video memory and registers being updated while we are in the
+ * middle of hand-shaking, suspend the main thread, which is the one that
+ * does the updates.
+ */
+ if(SuspendThread(MainThread) == SUSP_FAILURE)
+ ErrorExit();
+
+
+ if(!VDMForWOW && (SuspendThread(ThreadInfo.EventMgr.Handle)==SUSP_FAILURE))
+ ErrorExit();
+
+ NoTicks = TRUE;
+ /*
+ * We have the event telling us to switch so if we are windowed go
+ * full-screen or if we full-screen go windowed.
+ */
+ if (sc.ScreenState == FULLSCREEN)
+ {
+ fullScreenToWindowed();
+ }
+ else
+ {
+ windowedToFullScreen(TEXT, BiosModeChange);
+
+ }
+
+ /* Now resume the main thread. */
+ NoTicks = FALSE;
+
+ if(!VDMForWOW && ResumeThread(ThreadInfo.EventMgr.Handle) == SUSP_FAILURE)
+ ErrorExit();
+ if(ResumeThread(MainThread) == SUSP_FAILURE)
+ ErrorExit();
+
+ /* Leave ICA critical section. */
+ host_ica_unlock();
+}
+
+/***************************************************************************
+ * Function: *
+ * GetDetectEvent *
+ * *
+ * Description: *
+ * Returns the handle to the event which detects a fullscreen switch *
+ * has occurred. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * hStartHardwareEvent *
+ * *
+ ***************************************************************************/
+GLOBAL HANDLE GetDetectEvent(VOID)
+{
+ return(hStartHardwareEvent);
+}
+
+/*
+ * ==========================================================================
+ * Local functions
+ * ==========================================================================
+ */
+
+/*
+***************************************************************************
+** getCursorInfo() - use BIOS funcs to get cursor position and other stuff
+***************************************************************************
+** The BIOS could be the SoftPC video BIOS or the host PC's real video BIOS.
+** Cursor information needs to be communicated between the two BIOSes when
+** a windowed/full-screen transition occurs.
+** Tim July 92.
+*/
+LOCAL VOID getCursorInfo(word *type, half_word *column, half_word *row,
+ half_word *page)
+{
+
+ /* Get active page. */
+ *page = sas_hw_at_no_check(vd_current_page);
+
+ /* Get cursor position */
+ *type = sas_w_at_no_check(VID_CURMOD);
+ *column = sas_hw_at_no_check(current_cursor_col);
+ *row = sas_hw_at_no_check(current_cursor_row);
+}
+
+/*
+***************************************************************************
+** setCursorInfo() - use BIOS funcs to set cursor position and other stuff
+***************************************************************************
+** The BIOS could be the SoftPC video BIOS or the host PC's real video BIOS.
+** Cursor information needs to be communicated between the two BIOSes when
+** a windowed/full-screen transition occurs.
+** Tim July 92.
+*/
+LOCAL VOID setCursorInfo(word type, half_word column, half_word row, half_word page)
+{
+
+ /* Set active page. */
+ sas_store_no_check(vd_current_page, page);
+
+ /* Set cursor position. */
+ sas_storew_no_check(VID_CURMOD, type);
+ sas_store_no_check(current_cursor_col, column);
+ sas_store_no_check(current_cursor_row, row);
+}
+
+/***************************************************************************
+ * Function: *
+ * windowedToFullScreen *
+ * *
+ * Description: *
+ * Called when the user or SoftPC requests that the console goes *
+ * fullscreen. It disables screen updates, synchronises the hardware *
+ * to SoftPC's video planes and signals the console when it is *
+ * finished. *
+ * *
+ * Parameters: *
+ * dataType - the type of data stored in the video planes, set to *
+ * either TEXT or GRAPHICS. *
+ * biosModeChange - TRUE means call host BIOS to do mode change. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+LOCAL VOID windowedToFullScreen(SHORT dataType, BOOL biosModeChange)
+{
+ word cursorType;
+ half_word cursorCol, cursorRow, activePage;
+
+ /* Disable the Idling system when Fullscreen as we cannot detect video
+ * updates and thus would always idle.
+ */
+ IDLE_ctl(FALSE);
+
+ /* Pass the current state of our VGA emulation to the hardware. */
+ syncHardwareToVGAEmulation(dataType);
+
+ /*
+ ** A variable in K.SYS decides whether
+ ** to call the host INT 10, or do a video BOP.
+ ** Set the variable directly and subsequent INT 10's go to host
+ ** video BIOS.
+ */
+ sas_store_no_check((int10_seg << 4) + useHostInt10, FULLSCREEN);
+
+ /*
+ ** Tim August 92. Transfer to host video BIOS.
+ */
+ getCursorInfo(&cursorType, &cursorCol, &cursorRow, &activePage);
+
+ setCursorInfo(cursorType, cursorCol, cursorRow, activePage);
+
+ /*
+ * We only want to call the host bios to do a mode change if the current
+ * screen switch is due to a bios mode change.
+ */
+ if (biosModeChange)
+ {
+ always_trace1("Host BIOS mode change to mode %x.",
+ sas_hw_at_no_check(vd_video_mode));
+
+ /*
+ ** Tim August 92. Transfer to host video BIOS.
+ */
+ getCursorInfo(&cursorType, &cursorCol, &cursorRow, &activePage);
+
+ setCursorInfo(cursorType, cursorCol, cursorRow, activePage);
+ }
+}
+
+/***************************************************************************
+ * Function: *
+ * syncHardwareToVGAEmulation *
+ * *
+ * Description: *
+ * Copies the contents of SoftPC's video registers and regen buffer *
+ * to the real hardware on a transition to full-screen. *
+ * *
+ * Parameters: *
+ * dataType - the type of data stored in the video planes, set to *
+ * either TEXT or GRAPHICS. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+LOCAL VOID syncHardwareToVGAEmulation(SHORT dataType)
+{
+ ULONG memLoc;
+ UTINY *regPtr,
+ *egaPlanePtr,
+ *regenptr,
+ *fontptr,
+ *plane1Ptr,
+ *plane2Ptr,
+ *plane3Ptr,
+ *plane4Ptr;
+ half_word dummy,
+ acModeControl,
+ acIndex,
+ index,
+ value,
+ rgb;
+ USHORT dacIndex;
+ BOOL monoMode;
+ VIDEO_HARDWARE_STATE stateChange;
+ DWORD bitmapLen = sizeof(VIDEO_HARDWARE_STATE);
+ DWORD timo;
+
+ /* If we timed out during switch (stress!!), the videoState buffer will
+ * be removed by console. Check for this before accessing structure and
+ * take error path down to rest of handshake which will time out and report
+ * error cleanly.
+ */
+ try {
+ videoState->ExtendedSequencerOffset = 0;
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "NTVDM:VideoState has valid pointer, but no memory at that address");
+ goto syncHandshake;
+ }
+ /*
+ ** If it's a text mode
+ ** zero the extended fields in the shared saved/restore structure.
+ ** Kipper, Tim Nov 92.
+ */
+
+ /* initialize the video state header if we haven't done it yet.
+ if it is initialized, leave it alone.
+ */
+ if (videoState->Length == 0) {
+ videoState->Length = STATELENGTH;
+ videoState->BasicSequencerOffset = BASICSEQUENCEROFFSET;
+ videoState->BasicCrtContOffset = BASICCRTCONTOFFSET;
+ videoState->BasicGraphContOffset = BASICGRAPHCONTOFFSET;
+ videoState->BasicAttribContOffset = BASICATTRIBCONTOFFSET;
+ videoState->BasicDacOffset = BASICDACOFFSET;
+ videoState->BasicLatchesOffset = BASICLATCHESOFFSET;
+ videoState->PlaneLength = PLANELENGTH;
+ videoState->Plane1Offset = PLANE1OFFSET;
+ videoState->Plane2Offset = PLANE2OFFSET;
+ videoState->Plane3Offset = PLANE3OFFSET;
+ videoState->Plane4Offset = PLANE4OFFSET;
+ }
+ /* Save the current state of the attribute controller index register. */
+ inb(EGA_AC_INDEX_DATA, &acIndex);
+
+ /* Enable palette */
+ acIndex |= 0x20;
+
+ /*
+ * Find out if we are running in mono mode as CRTC registers are different
+ * if we are.
+ */
+ inb(EGA_IPSTAT1_REG, &dummy);
+ outb(EGA_AC_INDEX_DATA, AC_MODE_CONTROL_REG);
+ inb(EGA_AC_SECRET, &acModeControl);
+ monoMode = acModeControl & DISPLAY_TYPE;
+
+ /* Restore the state of the attribute controller index register. */
+ inb(EGA_IPSTAT1_REG, &dummy);
+ outb(EGA_AC_INDEX_DATA, acIndex);
+
+ /*
+ * Store values to be written to each of the real registers to synchronise
+ * them to the current state of the registers in the VDD.
+ */
+ if (monoMode)
+ {
+ /* Port 0x3b4 */
+ inb(0x3b4, (half_word *)&videoState->PortValue[0x4]);
+ /* Port 0x3b5 */
+ inb(0x3b5, (half_word *)&videoState->PortValue[0x5]);
+ }
+
+ /* Port 0x3c0 */
+ videoState->PortValue[0x10] = acIndex;
+
+ /* Port 0x3c1 */
+ inb(EGA_AC_SECRET, (half_word *)&videoState->PortValue[0x11]);
+
+ /* Port 0x3c2 */
+ inb(VGA_MISC_READ_REG, (half_word *)&videoState->PortValue[0x12]);
+
+ videoState->PortValue[0x13] = 0xff; /* Testing */
+
+ /* Port 0x3c4 */
+ inb(EGA_SEQ_INDEX, (half_word *)&videoState->PortValue[0x14]);
+
+ /* Port 0x3c5 */
+ inb(EGA_SEQ_DATA, (half_word *)&videoState->PortValue[0x15]);
+
+ /* Port 0x3c6 */
+ inb(VGA_DAC_MASK, (half_word *)&videoState->PortValue[0x16]);
+
+ /* Port 0x3c7 */
+ videoState->PortValue[0x17] = get_vga_DAC_rd_addr();
+
+ /* Port 0x3c8 */
+ inb(VGA_DAC_WADDR, (half_word *)&videoState->PortValue[0x18]);
+
+ /* Port 0x3c9 */
+ inb(VGA_DAC_DATA, (half_word *)&videoState->PortValue[0x19]);
+
+ /* Port 0x3ce */
+ inb(EGA_GC_INDEX, (half_word *)&videoState->PortValue[0x1e]);
+
+ /* Port 0x3cf */
+ inb(EGA_GC_DATA, (half_word *)&videoState->PortValue[0x1f]);
+
+ if (!monoMode)
+ {
+ /* Port 0x3d4 */
+ inb(EGA_CRTC_INDEX, (half_word *)&videoState->PortValue[0x24]);
+ /* Port 0x3d5 */
+ inb(EGA_CRTC_DATA, (half_word *)&videoState->PortValue[0x25]);
+ }
+
+ /* Port 0x3da */
+ inb(VGA_FEAT_READ_REG, (half_word *)&videoState->PortValue[0x2a]);
+
+ /* Store INDEX/DATA etc. register pairs. */
+
+ /* Initialise `regPtr'. */
+ regPtr = GET_OFFSET(BasicSequencerOffset);
+
+ /* Sequencer registers. */
+ for (index = 0; index < NUM_SEQ_REGS; index++)
+ {
+ outb(EGA_SEQ_INDEX, index);
+ inb(EGA_SEQ_DATA, &value);
+ *regPtr++ = value;
+ }
+
+ /* CRTC registers. */
+ regPtr = GET_OFFSET(BasicCrtContOffset);
+ for (index = 0; index < NUM_CRTC_REGS; index++)
+ {
+ outb(EGA_CRTC_INDEX, index);
+ inb(EGA_CRTC_DATA, &value);
+ *regPtr++ = value;
+ }
+
+ /* Graphics controller registers. */
+ regPtr = GET_OFFSET(BasicGraphContOffset);
+ for (index = 0; index < NUM_GC_REGS; index++)
+ {
+ outb(EGA_GC_INDEX, index);
+ inb(EGA_GC_DATA, &value);
+ *regPtr++ = value;
+ }
+
+ /* Attribute controller registers. */
+ regPtr = GET_OFFSET(BasicAttribContOffset);
+ for (index = 0; index < NUM_AC_REGS; index++)
+ {
+ inb(EGA_IPSTAT1_REG, &dummy); /* Reading 3DA sets 3C0 to index. */
+ outb(EGA_AC_INDEX_DATA, index); /* Writing to 3C0 sets it to data. */
+ inb(EGA_AC_SECRET, &value);
+ *regPtr++ = value;
+ }
+ inb(EGA_IPSTAT1_REG, &dummy); // re-enable video...
+ outb(EGA_AC_INDEX_DATA, 0x20);
+
+ /* DAC registers. */
+ regPtr = GET_OFFSET(BasicDacOffset);
+ outb(VGA_DAC_RADDR, (UTINY) 0);
+ for (dacIndex = 0; dacIndex < NUM_DAC_REGS; dacIndex++)
+ {
+
+ /* Get 3 values for each port corresponding to red, green and blue. */
+ for (rgb = 0; rgb < 3; rgb++)
+ {
+ inb(VGA_DAC_DATA, &value);
+ *regPtr++ = value;
+ }
+ }
+
+ /* Latches (which we always set to 0) */
+ regPtr = GET_OFFSET(BasicLatchesOffset);
+ *regPtr++ = 0;
+ *regPtr++ = 0;
+ *regPtr++ = 0;
+ *regPtr++ = 0;
+
+ if (!BiosModeChange) {
+ /* if this windowed->fullscreen switch was because of video mode change
+ do not change anything in the code buffer and the font because
+ the ROM bios set mode will clear them anyway. If "not clear VRAM"
+ bit was set(int 10h, ah = mode | 0x80), the application will take care
+ the VRAM refreshing and restoring because if it doesn't the screen
+ would look funnny as we just swtch mode from TEXT to GRAPHICS and the
+ video planar chaining conditions are changed.
+ */
+ /* set up pointer to regen memory where the real data lies */
+ regenptr = (UTINY *)0xb8000;
+
+ /* and one to the fonts living in the base of the regen area */
+ fontptr = (UTINY *)0xa0000;
+
+ plane1Ptr = GET_OFFSET(Plane1Offset);
+ plane2Ptr = GET_OFFSET(Plane2Offset);
+ plane3Ptr = GET_OFFSET(Plane3Offset);
+ plane4Ptr = GET_OFFSET(Plane4Offset);
+
+
+// if we go to fullscreen graphics from text window then the regen contents
+// is probably junk??? except when previous save... We can detect this
+// transition, so should we save time and just store blank planes???
+
+ if (dataType == TEXT)
+ {
+ // Surprise of the week - the individual planes 0 & 1 actually appear
+ // to be interleaved with 0's when dumped. Go with this for now, until
+ // we can suss if that's correct or whether we're not programming up
+ // the save and restore states properly.
+ // Probably good on further thoughts as fontplane doesn't show same
+ // interleave.
+ //
+ for (memLoc = 0; memLoc < (0xc0000 - 0xb8000); memLoc++)
+ {
+ *plane1Ptr++ = *regenptr++;
+ *plane1Ptr++ = 0; //char interleave
+ *plane2Ptr++ = *regenptr++;
+ *plane2Ptr++ = 0; //attr interleave
+ }
+ for (memLoc = 0; memLoc < 0x4000; memLoc++)
+ {
+ *plane3Ptr++ = *fontptr++;
+ *plane3Ptr++ = *fontptr++;
+ *plane3Ptr++ = *fontptr++;
+ *plane3Ptr++ = *fontptr++;
+ }
+ }
+ else //only true if restoring previous fullscreen graphics save
+ {
+ /*
+ * Get a copy of the video planes which are inter-leaved in one big
+ * plane - byte 0 = plane 0, byte 1 = plane 1, byte 2 = plane 2,
+ * byte 3 = plane 3, byte 4 = plane 0, etc.
+ */
+ /* Set up a pointer to the video planes. */
+ egaPlanePtr = EGA_planes;
+
+ for (memLoc = 0; memLoc < videoState->PlaneLength; memLoc++)
+ {
+ *plane1Ptr++ = *egaPlanePtr++;
+ *plane2Ptr++ = *egaPlanePtr++;
+ *plane3Ptr++ = *egaPlanePtr++;
+ *plane4Ptr++ = *egaPlanePtr++;
+ }
+ }
+ }
+
+ /* Now pass the data on to the hardware via the console. */
+ stateChange.StateHeader = videoState;
+ stateChange.StateLength = videoState->Plane4Offset +
+ videoState->PlaneLength;
+
+#ifndef PROD
+ dumpBlock();
+#endif
+
+ /* Transfer to this label only occurs if console has removed videostate */
+syncHandshake:
+
+ // do this here to ensure no surprises if get conflict with timer stuff
+ sc.ScreenState = FULLSCREEN;
+
+ /* make room for the real video memory */
+ LoseRegenMemory();
+
+ if (!SetEvent(hEndHardwareEvent)) // tell console memory's gone
+ ErrorExit();
+
+ // wait for console to tell us we can go on. Timeout after 60s
+ timo = WaitForSingleObject(hStartHardwareEvent, 60000);
+
+ if (timo != 0) // 0 is 'signalled'
+ {
+#ifndef PROD
+ if (timo == WAIT_TIMEOUT)
+ printf("NTVDM:Waiting for console to map frame buffer Timed Out\n");
+#endif
+ SetLastError(ERROR_SERVICE_REQUEST_TIMEOUT);
+ ErrorExit();
+ }
+ // tell console it can go on.
+ if (!SetEvent(hEndHardwareEvent))
+ ErrorExit();
+
+}
+
+/***************************************************************************
+ * Function: *
+ * fullScreenToWindowed *
+ * *
+ * Description: *
+ * When hStartHardwareEvent is detected by the timer thread the user *
+ * wants to go windowed. This function is then called to get the *
+ * current state of the hardware and send it to the VGA emulation. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+
+int BlockModeChange=0; /* Tim, when set stop nt_set_paint_routine() calling */
+ /* TextToGraphics() */
+
+LOCAL VOID fullScreenToWindowed(VOID)
+{
+
+ BlockModeChange = 1; /* Temp. disable TextToGraphics calls in the */
+ /* following syncVGA... cos it chucks display */
+ /* back into full-screen */
+
+ /* Pass the current state of the hardware to our VGA emulation. */
+ syncVGAEmulationToHardware();
+
+ /*
+ ** Tim August 92. Switch to SoftPC video BIOS.
+ */
+ BlockModeChange = 0; /* Temp. disable cos it don't work! */
+
+ /*
+ ** Set the K.SYS variable which determines whether to use the host
+ ** video BIOS or do a video BOP. Writing zero means use SoftPC BIOS.
+ */
+ sas_store_no_check((int10_seg << 4) + useHostInt10, (half_word)sc.ScreenState);
+
+ /* Enable the Idling system when return to Windowed */
+ /* Only do the following stuff if we are really in windowed mode.
+ this can happen: (fullscreen ->windowed(frozen) -> fullscreen) */
+ if (sc.ScreenState != FULLSCREEN) {
+ /*
+ ** Force re-paint of windowed image.
+ */
+ RtlFillMemory(&video_copy[0], 0x7fff, 0xff);
+
+ IDLE_ctl(TRUE);
+ IDLE_init(); /* and reset triggers */
+
+ /*
+ * Clear the old pointer box that has been left befind from
+ * fullscreen
+ */
+
+ CleanUpMousePointer();
+
+ resetNowCur(); /* reset static vars holding cursor pos. */
+ }
+} /* end of fullScreenToWindowed() */
+
+/***************************************************************************
+ * Function: *
+ * syncVGAEmulationToHardware *
+ * *
+ * Description: *
+ * Copies the real hardware state to SoftPC's video registers and *
+ * regen buffer on a transition from full-screen to windowed, *
+ * freezing if we are currently running in a graphics mode. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+LOCAL VOID syncVGAEmulationToHardware(VOID)
+{
+ ULONG memLoc,
+ StateFlags;
+ UTINY *regPtr,
+ *plane1Ptr,
+ *plane2Ptr,
+ *plane3Ptr,
+ *plane4Ptr,
+ *RegenPtr,
+ index,
+ dummy,
+ rgb;
+ USHORT dacIndex;
+ DWORD bitmapLen = 0, timo;
+ BOOL changing_to_graphics_mode = FALSE;
+
+ /* Tell console we've got the hardware state. */
+ if (!SetEvent(hEndHardwareEvent))
+ ErrorExit();
+
+ /* Wait for console to unmap memory. */
+ timo = WaitForSingleObject(hStartHardwareEvent, 60000);
+
+ if (timo != 0) /* 0 is 'signalled' */
+ {
+#ifndef PROD
+ if (timo == WAIT_TIMEOUT)
+ printf("NTVDM:Waiting for console to unmap frame buffer Timed Out\n");
+#endif
+ SetLastError(ERROR_SERVICE_REQUEST_TIMEOUT);
+ ErrorExit();
+ }
+
+ /* Put some memory back into the regen area. */
+ RegainRegenMemory();
+
+ /* used to free console here - now must wait as may need to do gfx first */
+
+ /* Store sequencer values */
+ regPtr = GET_OFFSET(BasicSequencerOffset);
+ for (index = 0; index < NUM_SEQ_REGS; index++)
+ {
+ outb(EGA_SEQ_INDEX, index);
+ outb(EGA_SEQ_DATA, *regPtr++);
+ }
+
+ /* disable CRTC port locking */
+ outb(EGA_CRTC_INDEX, 0x11);
+ outb(EGA_CRTC_DATA, 0);
+
+ /* Store CRTC values */
+ regPtr = GET_OFFSET(BasicCrtContOffset);
+ for (index = 0; index < NUM_CRTC_REGS; index++)
+ {
+ outb(EGA_CRTC_INDEX, index);
+ outb(EGA_CRTC_DATA, *regPtr++);
+ }
+
+
+ /* Store graphics context values */
+ regPtr = GET_OFFSET(BasicGraphContOffset);
+ for (index = 0; index < NUM_GC_REGS; index++)
+ {
+ outb(EGA_GC_INDEX, index);
+ outb(EGA_GC_DATA, *regPtr++);
+ }
+
+
+ /* Store attribute context values */
+ regPtr = GET_OFFSET(BasicAttribContOffset);
+ inb(EGA_IPSTAT1_REG, &dummy); /* Reading 3DA sets 3C0 to index. */
+ for (index = 0; index < NUM_AC_REGS; index++)
+ {
+ outb(EGA_AC_INDEX_DATA, index);
+ outb(EGA_AC_INDEX_DATA, *regPtr++);
+ }
+
+
+ /* Store DAC values. */
+ regPtr = GET_OFFSET(BasicDacOffset);
+ outb(VGA_DAC_WADDR, (UTINY) 0);
+ for (dacIndex = 0; dacIndex < NUM_DAC_REGS; dacIndex++)
+ {
+ for (rgb = 0; rgb < 3; rgb++)
+ outb(VGA_DAC_DATA, *regPtr++);
+ }
+
+
+ /* Store single value registers. */
+ outb( (io_addr)0x3b4, (half_word)videoState->PortValue[0x3b4 - 0x3b0]); //Mono crtc ind
+ outb( (io_addr)0x3ba, (half_word)videoState->PortValue[0x3ba - 0x3b0]); //Mono Feat
+ outb( (io_addr)0x3c2, (half_word)videoState->PortValue[0x3c2 - 0x3b0]); //Misc Output
+ outb( (io_addr)0x3c4, (half_word)videoState->PortValue[0x3c4 - 0x3b0]); //Seq Index
+ outb( (io_addr)0x3c6, (half_word)videoState->PortValue[0x3c6 - 0x3b0]); //DAC mask
+ outb( (io_addr)0x3c7, (half_word)videoState->PortValue[0x3c7 - 0x3b0]); //DAC read
+ outb( (io_addr)0x3c8, (half_word)videoState->PortValue[0x3c8 - 0x3b0]); //DAC write
+ outb( (io_addr)0x3ce, (half_word)videoState->PortValue[0x3ce - 0x3b0]); //GC Index
+ outb( (io_addr)0x3d4, (half_word)videoState->PortValue[0x3d4 - 0x3b0]); //CRTC index
+
+ /* Set up pointers to the planes in the video save block. */
+ plane1Ptr = GET_OFFSET(Plane1Offset);
+ plane2Ptr = GET_OFFSET(Plane2Offset);
+ plane3Ptr = GET_OFFSET(Plane3Offset);
+ plane4Ptr = GET_OFFSET(Plane4Offset);
+
+#ifndef PROD
+ dumpPlanes(plane1Ptr, plane2Ptr, plane3Ptr, plane4Ptr);
+#endif /* PROD */
+
+ /*
+ * Here is where we need to start making decisions about what mode the above
+ * has put us into as it effects what we do with the plane data - into regen
+ * or into ega planes.
+ */
+ StateFlags = videoState->VGAStateFlags;
+
+ ModeSetBatch = FALSE;
+
+ /*
+ * This actually indicates that the save/restore included all extended
+ * registers which increases the chances of a mode not being what it
+ * appears to be from the VGA registers. We need to tighten up the 'funny
+ * mode' detection. (But not now - too much chance of things).
+ *
+ * if (StateFlags & VIDEO_STATE_NON_STANDARD_VGA)
+ * {
+ * always_trace0("NTVDM:Non standard VGA - freeze state \n");
+ * ModeSetBatch = TRUE;
+ * }
+ */
+
+ if (StateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE)
+ {
+ always_trace0("NTVDM:Unemulated VGA State - freeze\n");
+ ModeSetBatch = TRUE;
+ }
+
+ if (StateFlags & VIDEO_STATE_PACKED_CHAIN4_MODE)
+ {
+ always_trace0("NTVDM:will need packed 256 colour paint\n");
+ Frozen256Packed = TRUE;
+ }
+ else
+ Frozen256Packed = FALSE;
+
+
+ if (!ModeSetBatch)
+ {
+ (*choose_display_mode)();
+ /* screen switching can happen when the BIOS is in the middle
+ of set mode. The video driver only batches the protected registers(we
+ will get VIDEO_STATE_UNEMULATED_VGA_STATE, which will set ModeSetBatch).
+ When we are out of set mode batch and a screen switch happens,
+ the choose_display_mode would choose a wrong mode(different what the
+ the bios says) and the parameters setup in base code could be wrong
+ (we calculate those parameters as it is in TEXT mode while we are in
+ graphic mode.
+
+ For example, the base code calculate the screen length as:
+
+ screen length = offset_per_line * screen_height_resolution / font_height
+
+ if the bios video mode is graphic mode 4(320 * 200), then
+ font_height = 2
+ screen_height_resolution = 200
+ offset_per_line = 80
+ the screen_lenght = 80 * 200 / 2 = 8000 bytes which means
+ the screen has 8000 / 80 = 100 lines!!!!
+
+ Treat it like we are in mode set batch process, so we go to iconized.
+ */
+ if (sc.ModeType == getModeType()) {
+
+ /* Write data to video planes if we are in a graphics mode. */
+ if (sc.ModeType == GRAPHICS)
+ {
+
+ /*
+ * 'choose_display_mode' calls 'host_set_paint_routine' and in so doing
+ * sets up 'sc.ModeType'. We now know we have a graphics mode so
+ * select the frozen paint routines and call 'host_set_paint_routine'
+ * again to get the required frozen routine.
+ */
+ select_frozen_routines();
+ host_set_paint_routine(choose_mode[get_munged_index()],
+ get_screen_height());
+ }
+ else /* TEXT */
+ {
+ /* Double check not race on graphics mode change */
+
+ if (sas_hw_at((int10_seg << 4) + changing_mode_flag) == 1)
+ {
+ /* In middle of mode change - may actually be graphics any second */
+ if ((sas_hw_at(vd_video_mode) > 3) && (sas_hw_at(vd_video_mode) != 7))
+ changing_to_graphics_mode = TRUE;
+ }
+ /* Now copy the data to the regen buffer. */
+ RegenPtr = (UTINY *)0xb8000;
+ for(memLoc = 0; memLoc < 0x4000; memLoc++) /* 16k of text data. */
+ {
+ *RegenPtr++ = *plane1Ptr++; /* char */
+ plane1Ptr++; /* skip interleave */
+ *RegenPtr++ = *plane2Ptr++; /* attr */
+ plane2Ptr++; /* skip interleave */
+ }
+
+ /* Now the font. */
+ RegenPtr = (UTINY *)0xa0000;
+ for(memLoc = 0; memLoc < 0x4000; memLoc++) /* Up to 64k of font data. */
+ {
+ *RegenPtr++ = *plane3Ptr++;
+ *RegenPtr++ = *plane3Ptr++;
+ *RegenPtr++ = *plane3Ptr++;
+ *RegenPtr++ = *plane3Ptr++;
+ }
+ }
+
+ /* Re-enable vga attribute palette. */
+ inb(EGA_IPSTAT1_REG, &dummy); /* Reading 3DA sets 3C0 to index. */
+ outb(EGA_AC_INDEX_DATA, 0x20);
+ }
+ else {
+ ModeSetBatch = TRUE;
+#ifndef PROD
+ OutputDebugString("fullscreen->windowed switching in set mode\n");
+#endif
+
+ }
+
+ } /* modesetbatch */
+ /*
+ * If the state returned by the hardware is one we don't recognise iconify
+ * the window. If, however, the hardware returns a graphics mode, the
+ * current image will be displayed. In both cases the app will be frozen
+ * until the user changes back to fullscreen.
+ */
+ if (ModeSetBatch || (inAFunnyMode = funnyMode()) || (sc.ModeType == GRAPHICS) || changing_to_graphics_mode)
+ {
+
+#ifndef PROD
+ dumpBlock();
+#endif /* PROD */
+
+ /* if in middle of mode change, don't want to draw screen */
+ if (changing_to_graphics_mode)
+ inAFunnyMode = TRUE;
+
+ /* Must do this before resize function. */
+ sc.ScreenState = WINDOWED;
+
+ /* Once we've done this, the VGA emulation is pushed into a graphics
+ * mode. If we restart windowed, we must ensure it forces itself
+ * back to a text mode for correct display & so correct screen buffer
+ * is active. This will be cancelled if we return to a text window.
+ */
+ blocked_in_gfx_mode = TRUE;
+
+ /*
+ * freezewindow used to run in its own thread. Unfortunately, due to
+ * console sync problems with video restore on XGA, this did unpleasant
+ * things to the screen. Thus now this is has become a valid and *Only*
+ * place in fullscreen switching where console permits us to make
+ * console API calls.
+ * I'm sorry, did you say 'Quack', Oh no, I see...
+ */
+
+ freezeWindow();
+
+ /* Tell console we're done. */
+ if (!SetEvent(hEndHardwareEvent))
+ ErrorExit();
+
+ /* We block here until user switches us fullscreen again. */
+ WaitForSingleObject(hStartHardwareEvent, INFINITE);
+
+ /* Prevent updates which would cause hang. */
+ sc.ScreenState = FULLSCREEN;
+
+ savedScreenState = WINDOWED; /* won't have been changed by timer fn */
+
+ inAFunnyMode = TRUE;
+
+ /* Put video section back as passed to us as we have not changed it. */
+ LoseRegenMemory();
+
+ /* Tell console memory's gone. */
+ if (!SetEvent(hEndHardwareEvent))
+ ErrorExit();
+
+ /* Wait for console to tell us we can go on. Timeout after 60s */
+ timo = WaitForSingleObject(hStartHardwareEvent, 60000);
+
+ if (timo != 0) /* 0 is 'signalled' */
+ {
+#ifndef PROD
+ if (timo == WAIT_TIMEOUT)
+ printf("NTVDM:Waiting for console to map frame buffer Timed Out\n");
+#endif
+ SetLastError(ERROR_SERVICE_REQUEST_TIMEOUT);
+ ErrorExit();
+ }
+
+ Frozen256Packed = FALSE;
+
+ sas_connect_memory(0xb8000, 0xbffff, SAS_VIDEO);
+ // tell console server it can go on
+ if (!SetEvent(hEndHardwareEvent))
+ ErrorExit();
+ }
+ else /* TEXT */
+ {
+ /* Tell console we're done. */
+ if (!SetEvent(hEndHardwareEvent))
+ ErrorExit();
+
+ /* Set up screen-state variable. */
+ sc.ScreenState = WINDOWED;
+
+ blocked_in_gfx_mode = FALSE; /* save restart mode switch */
+#ifndef PROD
+ /* Dump out a view of the state block as it might be useful. */
+ dumpBlock();
+#endif /* PROD */
+ }
+
+ do_new_cursor(); /* sync emulation about cursor state */
+}
+
+/***************************************************************************
+ * Function: *
+ * funnyMode *
+ * *
+ * Description: *
+ * Detects whether the state of the video hardware returned when *
+ * switching from fullscreen is one that our VGA emulation *
+ * understands. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * TRUE if it is a funny state, otherwise FALSE. *
+ * *
+ ***************************************************************************/
+LOCAL BOOL funnyMode(VOID)
+{
+
+ /*
+ * If the screen is of a higher resolution than 640 x 480 we have a
+ * non-standard VGA mode.
+ */
+ if ((get_bytes_per_line() > 80) || (get_screen_height() > 480)){
+ return( FALSE ); /* Tim, don't like it, see what happens other way! */
+ /* return(TRUE); */
+ }
+
+ /*
+ * If 'nt_set_paint_routine' was called with 'mode' set to one of the
+ * "funny" values e.g. TEXT_40_FUN we assume that the mode the hardware
+ * is currently in is not compatible with the VGA emulation.
+ */
+ if (FunnyPaintMode){
+ return(TRUE);
+ }
+
+ /* We have a standard VGA mode. */
+ return(FALSE);
+}
+
+/***************************************************************************
+ * Function: *
+ * freezeWindow *
+ * *
+ * Description: *
+ * This function is the entry point for the temporary thread which *
+ * does console calls when the main thread is frozen on a fullscreen *
+ * to windowed transition. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+LOCAL VOID freezeWindow(VOID)
+{
+
+ DWORD Dummy;
+
+ /* Add -FROZEN to the window title. */
+ FreezeWinTitle();
+
+ /* Turn off any active sounds (eg flight simulator engine noise) */
+ InitSound(FALSE);
+
+ /* Iconify if we are in a funny mode, otherwise paint the screen. */
+ if (ModeSetBatch || inAFunnyMode)
+ VDMConsoleOperation(VDM_HIDE_WINDOW, &Dummy);
+ else
+ {
+
+
+ /* Set the screen size. */
+ graphicsResize();
+
+ //
+ // Remove the Hide Mouse Pointer message from the
+ // system menu so the user cannot apply this option
+ // the screen is frozen.
+ // Andy!
+
+ MouseDetachMenuItem(TRUE);
+
+ /*
+ * Set up the palette as DAC registers may have changed and we
+ * won't get any more timer ticks after this one until we
+ * unfreeze (the palette is not set up until 2 timer ticks after
+ * 'choose_display_mode' has been called).
+ */
+ set_the_vlt();
+
+ /*
+ * Full window graphics paint - relies on paint routines to check
+ * for memory overflow.
+ */
+ VGLOBS->dirty_flag = (ULONG) 0xffffffff;
+ (*update_alg.calc_update)();
+ }
+ /* Unblock frozen-window thread creation. */
+ freezeHandle = 0;
+}
+
+#ifndef PROD
+
+/***************************************************************************
+ * Function: *
+ * dumpBlock *
+ * *
+ * Description: *
+ * Dumps the contents of the video state block. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+int dumpit = 0;
+LOCAL VOID dumpBlock(VOID)
+{
+ USHORT i,
+ dacIndex;
+ UTINY *regPtr,
+ index,
+ rgb;
+
+ if (dumpit == 0) return;
+
+ /* Dump out single value registers. */
+ printf("\nSingle value registers:\n");
+ for (i = 0; i < 0x30; i++)
+ printf("\tPort %#x = %#x\n", i, videoState->PortValue[i]);
+
+ /* Dump sequencer values */
+ regPtr = GET_OFFSET(BasicSequencerOffset);
+ printf("Sequencer registers: (addr %#x)\n",regPtr);
+ for (index = 0; index < NUM_SEQ_REGS; index++)
+ {
+ printf(" %#x = %#x\t", index, *regPtr++);
+ }
+ printf("\n");
+
+ /* Dump CRTC values */
+ regPtr = GET_OFFSET(BasicCrtContOffset);
+ printf("CRTC registers: (addr %#x)\n",regPtr);
+ for (index = 0; index < NUM_CRTC_REGS; index++)
+ {
+ printf(" %#x = %#x\t", index, *regPtr++);
+ }
+ printf("\n");
+
+ /* Dump graphics context values */
+ regPtr = GET_OFFSET(BasicGraphContOffset);
+ printf("Graphics context registers: (addr %#x)\n",regPtr);
+ for (index = 0; index < NUM_GC_REGS; index++)
+ {
+ printf(" %#x = %#x\t", index, *regPtr++);
+ }
+ printf("\n");
+
+ /* Dump attribute context values */
+ regPtr = GET_OFFSET(BasicAttribContOffset);
+ printf("Attribute context registers: (addr %#x)\n",regPtr);
+ for (index = 0; index < NUM_AC_REGS; index++)
+ {
+ printf(" %#x = %#x\t", index, *regPtr++);
+ }
+ printf("\n");
+
+ /* Dump DACs. First few only otherwise too slow & console times out! */
+ regPtr = GET_OFFSET(BasicDacOffset);
+ printf("DAC registers:\n");
+ for (dacIndex = 0; dacIndex < NUM_DAC_REGS/8; dacIndex++)
+ {
+ printf("Ind:%#02x: ", dacIndex);
+ for (rgb = 0; rgb < 3; rgb++)
+ {
+ printf("R:%#02x G:%#02x B:%#02x\t", *regPtr++, *regPtr++, *regPtr++);
+ }
+ if ((dacIndex % 4) == 0) printf("\n");
+ }
+}
+
+int doPlaneDump = 0;
+LOCAL VOID dumpPlanes(UTINY *plane1Ptr, UTINY *plane2Ptr, UTINY *plane3Ptr,
+ UTINY *plane4Ptr)
+{
+ HANDLE outFile;
+ char planeBuffer[256],
+ *bufptr;
+ DWORD i,
+ j,
+ k,
+ plane,
+ nBytes,
+ bytesWritten;
+ UTINY *planes[4];
+ FAST UTINY *tempPlanePtr;
+
+ if (doPlaneDump)
+ {
+
+ /* Dump out plane(s). */
+ outFile = CreateFile("PLANE",
+ GENERIC_WRITE,
+ (DWORD) 0,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ (HANDLE) NULL);
+ if (outFile == INVALID_HANDLE_VALUE)
+ ErrorExit();
+ planes[0] = plane1Ptr;
+ planes[1] = plane2Ptr;
+ planes[2] = plane3Ptr;
+ planes[3] = plane4Ptr;
+ for (plane = 0; plane < 4; plane++)
+ {
+ tempPlanePtr = planes[plane];
+ sprintf(planeBuffer, "Plane %d\n", plane);
+ strcat(planeBuffer, "-------\n");
+ if (!WriteFile(outFile,
+ planeBuffer,
+ strlen(planeBuffer),
+ &bytesWritten,
+ (LPOVERLAPPED) NULL))
+ ErrorExit();
+ for (i = 0; i < 0x10000; i += 0x10)
+ {
+ sprintf(planeBuffer, "%04x\t", i);
+ bufptr = planeBuffer + strlen(planeBuffer);
+ for (j = 0; j < 2; j++)
+ {
+ for (k = 0; k < 8; k++)
+ {
+ LOCAL char numTab[] =
+ {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+ FAST UTINY temp;
+
+ temp = *tempPlanePtr++;
+ *bufptr++ = numTab[(temp >> 4) & 0xf];
+ *bufptr++ = numTab[temp & 0xf];
+ *bufptr++ = ' ';
+ }
+ if (j == 0)
+ {
+ *bufptr++ = '-';
+ *bufptr++ = ' ';
+ }
+ }
+ *bufptr++ = '\n';
+ *bufptr++ = '\0';
+ nBytes = strlen(planeBuffer);
+ if (!WriteFile(outFile,
+ planeBuffer,
+ nBytes,
+ &bytesWritten,
+ (LPOVERLAPPED) NULL))
+ ErrorExit();
+ }
+ if (!WriteFile(outFile,
+ "\n",
+ 1,
+ &bytesWritten,
+ (LPOVERLAPPED) NULL))
+ ErrorExit();
+ }
+ CloseHandle(outFile);
+ }
+}
+
+#endif /* PROD */
+#endif /* X86GFX */
+
+#ifdef PLANEDUMPER
+extern half_word *vidpl16;
+void planedumper()
+{
+ char filen[50];
+ half_word outs[100];
+ HANDLE pfh;
+ int loop, curoff;
+ char *format = "0123456789abcdef";
+ half_word *pl, ch;
+
+ printf("planedumper for plane %d\n", *vidpl16 - 1);
+ strcpy(filen, "plane ");
+ filen[5] = '0' + *vidpl16 - 1;
+ pfh = CreateFile(filen,
+ GENERIC_WRITE,
+ (DWORD) 0,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ (HANDLE) NULL);
+ if (pfh == INVALID_HANDLE_VALUE)
+ {
+ printf("Can't create file %s\n", filen);
+ return;
+ }
+
+ pl = (half_word *)0xa0000;
+
+ curoff = 0;
+ for(loop = 0; loop < 64*1024; loop++)
+ {
+ ch = *pl++;
+ outs[curoff++] = *(format + (ch >> 4));
+ outs[curoff++] = *(format + (ch & 0xf));
+ outs[curoff++] = ' ';
+
+ if (curoff == 78)
+ {
+ outs[curoff] = '\n';
+
+ WriteFile(pfh, outs, 80, &curoff, (LPOVERLAPPED) NULL);
+ curoff = 0;
+ }
+ }
+ outs[curoff] = '\n';
+
+ WriteFile(pfh, outs, curoff, &curoff, (LPOVERLAPPED) NULL);
+
+ CloseHandle(pfh);
+}
+#endif
diff --git a/private/mvdm/softpc.new/host/src/nt_ega.c b/private/mvdm/softpc.new/host/src/nt_ega.c
new file mode 100644
index 000000000..db83e95f2
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_ega.c
@@ -0,0 +1,2144 @@
+
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : Win32 EGA Graphics Module
+ *
+ * Description :
+ *
+ * This modules contain the Win32 specific functions required
+ * to support the EGA emulation.
+ *
+ * Author : Dave Bartlett (based on X_ega.c)
+ *
+ * Notes :
+ *
+ */
+
+#include <windows.h>
+#include <string.h>
+#include <memory.h>
+
+#include "insignia.h"
+#include "host_def.h"
+
+#include "xt.h"
+#include "gvi.h"
+#include "gmi.h"
+#include "sas.h"
+#include "gfx_upd.h"
+#include <stdio.h>
+#include "trace.h"
+#include "debug.h"
+#include "egagraph.h"
+#include "egacpu.h"
+#include "egaports.h"
+#include "host_rrr.h"
+
+#include "conapi.h"
+#include "nt_graph.h"
+#include "nt_ega.h"
+#include "nt_egalt.h"
+
+#ifdef MONITOR
+#include <ntddvdeo.h>
+#include "nt_fulsc.h"
+#endif /* MONITOR */
+
+/* Statics */
+
+static unsigned int ega_lo_graph_0_0[256];
+static unsigned int ega_lo_graph_0_1[256];
+static unsigned int ega_lo_graph_0_2[256];
+static unsigned int ega_lo_graph_0_3[256];
+static unsigned int ega_lo_graph_1_0[256];
+static unsigned int ega_lo_graph_1_1[256];
+static unsigned int ega_lo_graph_1_2[256];
+static unsigned int ega_lo_graph_1_3[256];
+static unsigned int ega_lo_graph_2_0[256];
+static unsigned int ega_lo_graph_2_1[256];
+static unsigned int ega_lo_graph_2_2[256];
+static unsigned int ega_lo_graph_2_3[256];
+static unsigned int ega_lo_graph_3_0[256];
+static unsigned int ega_lo_graph_3_1[256];
+static unsigned int ega_lo_graph_3_2[256];
+static unsigned int ega_lo_graph_3_3[256];
+
+#ifdef BIGWIN
+static unsigned int ega_lo_graph_0_0_big[256];
+static unsigned int ega_lo_graph_0_1_big[256];
+static unsigned int ega_lo_graph_0_2_big[256];
+static unsigned int ega_lo_graph_0_3_big[256];
+static unsigned int ega_lo_graph_1_0_big[256];
+static unsigned int ega_lo_graph_1_1_big[256];
+static unsigned int ega_lo_graph_1_2_big[256];
+static unsigned int ega_lo_graph_1_3_big[256];
+static unsigned int ega_lo_graph_2_0_big[256];
+static unsigned int ega_lo_graph_2_1_big[256];
+static unsigned int ega_lo_graph_2_2_big[256];
+static unsigned int ega_lo_graph_2_3_big[256];
+static unsigned int ega_lo_graph_3_0_big[256];
+static unsigned int ega_lo_graph_3_1_big[256];
+static unsigned int ega_lo_graph_3_2_big[256];
+static unsigned int ega_lo_graph_3_3_big[256];
+static unsigned int ega_lo_graph_4_0_big[256];
+static unsigned int ega_lo_graph_4_1_big[256];
+static unsigned int ega_lo_graph_4_2_big[256];
+static unsigned int ega_lo_graph_4_3_big[256];
+static unsigned int ega_lo_graph_5_0_big[256];
+static unsigned int ega_lo_graph_5_1_big[256];
+static unsigned int ega_lo_graph_5_2_big[256];
+static unsigned int ega_lo_graph_5_3_big[256];
+
+static unsigned int ega_lo_graph_0_0_huge[256];
+static unsigned int ega_lo_graph_0_1_huge[256];
+static unsigned int ega_lo_graph_0_2_huge[256];
+static unsigned int ega_lo_graph_0_3_huge[256];
+static unsigned int ega_lo_graph_1_0_huge[256];
+static unsigned int ega_lo_graph_1_1_huge[256];
+static unsigned int ega_lo_graph_1_2_huge[256];
+static unsigned int ega_lo_graph_1_3_huge[256];
+static unsigned int ega_lo_graph_2_0_huge[256];
+static unsigned int ega_lo_graph_2_1_huge[256];
+static unsigned int ega_lo_graph_2_2_huge[256];
+static unsigned int ega_lo_graph_2_3_huge[256];
+static unsigned int ega_lo_graph_3_0_huge[256];
+static unsigned int ega_lo_graph_3_1_huge[256];
+static unsigned int ega_lo_graph_3_2_huge[256];
+static unsigned int ega_lo_graph_3_3_huge[256];
+static unsigned int ega_lo_graph_4_0_huge[256];
+static unsigned int ega_lo_graph_4_1_huge[256];
+static unsigned int ega_lo_graph_4_2_huge[256];
+static unsigned int ega_lo_graph_4_3_huge[256];
+static unsigned int ega_lo_graph_5_0_huge[256];
+static unsigned int ega_lo_graph_5_1_huge[256];
+static unsigned int ega_lo_graph_5_2_huge[256];
+static unsigned int ega_lo_graph_5_3_huge[256];
+static unsigned int ega_lo_graph_6_0_huge[256];
+static unsigned int ega_lo_graph_6_1_huge[256];
+static unsigned int ega_lo_graph_6_2_huge[256];
+static unsigned int ega_lo_graph_6_3_huge[256];
+static unsigned int ega_lo_graph_7_0_huge[256];
+static unsigned int ega_lo_graph_7_1_huge[256];
+static unsigned int ega_lo_graph_7_2_huge[256];
+static unsigned int ega_lo_graph_7_3_huge[256];
+#endif
+
+static unsigned int ega_med_and_hi_graph_luts[2048];
+
+#ifdef BIGWIN
+static unsigned int ega_med_and_hi_graph_luts_big[3072];
+
+static unsigned int ega_med_and_hi_graph_luts_huge[5120];
+#endif
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::: Initialise EGA mono low graphics :::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_ega_mono_lo_graph()
+{
+sub_note_trace0(EGA_HOST_VERBOSE,"nt_init_ega_mono_lo_graph - NOT SUPPORTED");
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::: Initialise EGA colour low res graphics :::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_ega_lo_graph()
+{
+ static boolean ega_colour_lo_graph_deja_vu = FALSE;
+ unsigned int i,
+ byte0,
+ byte1,
+ byte2,
+ byte3,
+ byte4,
+ byte5,
+ byte6,
+ byte7,
+ or_of_bytes01,
+ or_of_bytes23,
+ or_of_bytes45,
+ or_of_bytes67;
+#ifdef BIGWIN
+ unsigned int or_of_bytes89,
+ or_of_bytesab,
+ or_of_bytescd,
+ or_of_bytesef;
+#endif /* BIGWIN */
+
+ sub_note_trace0(EGA_HOST_VERBOSE,"nt_init_ega_lo_graph");
+
+ /* Set up bits-per-pixel for current mode. */
+ sc.BitsPerPixel = EGA_BITS_PER_PIXEL;
+
+ /* Initialise look-up table for first call. */
+ if( !ega_colour_lo_graph_deja_vu )
+ {
+ for( i = 0; i < 256; i++ )
+ {
+ byte0 = i & 0x1;
+ byte1 = ( i & 0x2 ) >> 1;
+ byte2 = ( i & 0x4 ) >> 2;
+ byte3 = ( i & 0x8 ) >> 3;
+ byte4 = ( i & 0x10 ) >> 4;
+ byte5 = ( i & 0x20 ) >> 5;
+ byte6 = ( i & 0x40 ) >> 6;
+ byte7 = ( i & 0x80 ) >> 7;
+
+#ifdef BIGEND
+ or_of_bytes01 = ( byte1 << 24 ) | ( byte1 << 16 ) |
+ ( byte0 << 8 ) | byte0;
+ or_of_bytes23 = ( byte3 << 24 ) | ( byte3 << 16 ) |
+ ( byte2 << 8 ) | byte2;
+ or_of_bytes45 = ( byte5 << 24 ) | ( byte5 << 16 ) |
+ ( byte4 << 8 ) | byte4;
+ or_of_bytes67 = ( byte7 << 24 ) | ( byte7 << 16 ) |
+ ( byte6 << 8 ) | byte6;
+#endif /* BIGEND */
+
+#ifdef LITTLEND
+ or_of_bytes01 = ( byte0 << 24 ) | ( byte0 << 16 ) |
+ ( byte1 << 8 ) | byte1;
+ or_of_bytes23 = ( byte2 << 24 ) | ( byte2 << 16 ) |
+ ( byte3 << 8 ) | byte3;
+ or_of_bytes45 = ( byte4 << 24 ) | ( byte4 << 16 ) |
+ ( byte5<< 8 ) | byte5;
+ or_of_bytes67 = ( byte6 << 24 ) | ( byte6 << 16 ) |
+ ( byte7 << 8 ) | byte7;
+#endif /* LITTLEND */
+
+ ega_lo_graph_0_0[i] = or_of_bytes01;
+ ega_lo_graph_0_1[i] = or_of_bytes01 << 1;
+ ega_lo_graph_0_2[i] = or_of_bytes01 << 2;
+ ega_lo_graph_0_3[i] = or_of_bytes01 << 3;
+
+ ega_lo_graph_1_0[i] = or_of_bytes23;
+ ega_lo_graph_1_1[i] = or_of_bytes23 << 1;
+ ega_lo_graph_1_2[i] = or_of_bytes23 << 2;
+ ega_lo_graph_1_3[i] = or_of_bytes23 << 3;
+
+ ega_lo_graph_2_0[i] = or_of_bytes45;
+ ega_lo_graph_2_1[i] = or_of_bytes45 << 1;
+ ega_lo_graph_2_2[i] = or_of_bytes45 << 2;
+ ega_lo_graph_2_3[i] = or_of_bytes45 << 3;
+
+ ega_lo_graph_3_0[i] = or_of_bytes67;
+ ega_lo_graph_3_1[i] = or_of_bytes67 << 1;
+ ega_lo_graph_3_2[i] = or_of_bytes67 << 2;
+ ega_lo_graph_3_3[i] = or_of_bytes67 << 3;
+
+#ifdef BIGWIN
+#ifdef BIGEND
+
+ or_of_bytes01 = ( byte1 << 24 ) | ( byte0 << 16 ) |
+ ( byte0 << 8 ) | byte0;
+ or_of_bytes23 = ( byte2 << 24 ) | ( byte2 << 16 ) |
+ ( byte1 << 8 ) | byte1;
+ or_of_bytes45 = ( byte3 << 24 ) | ( byte3 << 16 ) |
+ ( byte3 << 8 ) | byte2;
+ or_of_bytes67 = ( byte5 << 24 ) | ( byte4 << 16 ) |
+ ( byte4 << 8 ) | byte4;
+ or_of_bytes89 = ( byte6 << 24 ) | ( byte6 << 16 ) |
+ ( byte5 << 8 ) | byte5;
+ or_of_bytesab = ( byte7 << 24 ) | ( byte7 << 16 ) |
+ ( byte7 << 8 ) | byte6;
+
+#endif /* BIGEND */
+
+#ifdef LITTLEND
+
+ or_of_bytes01 = ( byte0 << 24 ) | ( byte0 << 16 ) |
+ ( byte0 << 8 ) | byte1;
+ or_of_bytes23 = ( byte1 << 24 ) | ( byte1 << 16 ) |
+ ( byte2 << 8 ) | byte2;
+ or_of_bytes45 = ( byte2 << 24 ) | ( byte3 << 16 ) |
+ ( byte3 << 8 ) | byte3;
+ or_of_bytes67 = ( byte4 << 24 ) | ( byte4 << 16 ) |
+ ( byte4 << 8 ) | byte5;
+ or_of_bytes89 = ( byte5 << 24 ) | ( byte5 << 16 ) |
+ ( byte6 << 8 ) | byte6;
+ or_of_bytesab = ( byte6 << 24 ) | ( byte7 << 16 ) |
+ ( byte7 << 8 ) | byte7;
+
+#endif /* LITTLEND */
+
+ ega_lo_graph_0_0_big[i] = or_of_bytes01;
+ ega_lo_graph_0_1_big[i] = or_of_bytes01 << 1;
+ ega_lo_graph_0_2_big[i] = or_of_bytes01 << 2;
+ ega_lo_graph_0_3_big[i] = or_of_bytes01 << 3;
+
+ ega_lo_graph_1_0_big[i] = or_of_bytes23;
+ ega_lo_graph_1_1_big[i] = or_of_bytes23 << 1;
+ ega_lo_graph_1_2_big[i] = or_of_bytes23 << 2;
+ ega_lo_graph_1_3_big[i] = or_of_bytes23 << 3;
+
+ ega_lo_graph_2_0_big[i] = or_of_bytes45;
+ ega_lo_graph_2_1_big[i] = or_of_bytes45 << 1;
+ ega_lo_graph_2_2_big[i] = or_of_bytes45 << 2;
+ ega_lo_graph_2_3_big[i] = or_of_bytes45 << 3;
+
+ ega_lo_graph_3_0_big[i] = or_of_bytes67;
+ ega_lo_graph_3_1_big[i] = or_of_bytes67 << 1;
+ ega_lo_graph_3_2_big[i] = or_of_bytes67 << 2;
+ ega_lo_graph_3_3_big[i] = or_of_bytes67 << 3;
+
+ ega_lo_graph_4_0_big[i] = or_of_bytes89;
+ ega_lo_graph_4_1_big[i] = or_of_bytes89 << 1;
+ ega_lo_graph_4_2_big[i] = or_of_bytes89 << 2;
+ ega_lo_graph_4_3_big[i] = or_of_bytes89 << 3;
+
+ ega_lo_graph_5_0_big[i] = or_of_bytesab;
+ ega_lo_graph_5_1_big[i] = or_of_bytesab << 1;
+ ega_lo_graph_5_2_big[i] = or_of_bytesab << 2;
+ ega_lo_graph_5_3_big[i] = or_of_bytesab << 3;
+
+ or_of_bytes01 = ( byte0 << 24 ) | ( byte0 << 16 ) |
+ ( byte0 << 8 ) | byte0;
+ or_of_bytes23 = ( byte1 << 24 ) | ( byte1 << 16 ) |
+ ( byte1 << 8 ) | byte1;
+ or_of_bytes45 = ( byte2 << 24 ) | ( byte2 << 16 ) |
+ ( byte2 << 8 ) | byte2;
+ or_of_bytes67 = ( byte3 << 24 ) | ( byte3 << 16 ) |
+ ( byte3 << 8 ) | byte3;
+ or_of_bytes89 = ( byte4 << 24 ) | ( byte4 << 16 ) |
+ ( byte4 << 8 ) | byte4;
+ or_of_bytesab = ( byte5 << 24 ) | ( byte5 << 16 ) |
+ ( byte5 << 8 ) | byte5;
+ or_of_bytescd = ( byte6 << 24 ) | ( byte6 << 16 ) |
+ ( byte6 << 8 ) | byte6;
+ or_of_bytesef = ( byte7 << 24 ) | ( byte7 << 16 ) |
+ ( byte7 << 8 ) | byte7;
+
+ ega_lo_graph_0_0_huge[i] = or_of_bytes01;
+ ega_lo_graph_0_1_huge[i] = or_of_bytes01 << 1;
+ ega_lo_graph_0_2_huge[i] = or_of_bytes01 << 2;
+ ega_lo_graph_0_3_huge[i] = or_of_bytes01 << 3;
+
+ ega_lo_graph_1_0_huge[i] = or_of_bytes23;
+ ega_lo_graph_1_1_huge[i] = or_of_bytes23 << 1;
+ ega_lo_graph_1_2_huge[i] = or_of_bytes23 << 2;
+ ega_lo_graph_1_3_huge[i] = or_of_bytes23 << 3;
+
+ ega_lo_graph_2_0_huge[i] = or_of_bytes45;
+ ega_lo_graph_2_1_huge[i] = or_of_bytes45 << 1;
+ ega_lo_graph_2_2_huge[i] = or_of_bytes45 << 2;
+ ega_lo_graph_2_3_huge[i] = or_of_bytes45 << 3;
+
+ ega_lo_graph_3_0_huge[i] = or_of_bytes67;
+ ega_lo_graph_3_1_huge[i] = or_of_bytes67 << 1;
+ ega_lo_graph_3_2_huge[i] = or_of_bytes67 << 2;
+ ega_lo_graph_3_3_huge[i] = or_of_bytes67 << 3;
+
+ ega_lo_graph_4_0_huge[i] = or_of_bytes89;
+ ega_lo_graph_4_1_huge[i] = or_of_bytes89 << 1;
+ ega_lo_graph_4_2_huge[i] = or_of_bytes89 << 2;
+ ega_lo_graph_4_3_huge[i] = or_of_bytes89 << 3;
+
+ ega_lo_graph_5_0_huge[i] = or_of_bytesab;
+ ega_lo_graph_5_1_huge[i] = or_of_bytesab << 1;
+ ega_lo_graph_5_2_huge[i] = or_of_bytesab << 2;
+ ega_lo_graph_5_3_huge[i] = or_of_bytesab << 3;
+
+ ega_lo_graph_6_0_huge[i] = or_of_bytescd;
+ ega_lo_graph_6_1_huge[i] = or_of_bytescd << 1;
+ ega_lo_graph_6_2_huge[i] = or_of_bytescd << 2;
+ ega_lo_graph_6_3_huge[i] = or_of_bytescd << 3;
+
+ ega_lo_graph_7_0_huge[i] = or_of_bytesef;
+ ega_lo_graph_7_1_huge[i] = or_of_bytesef << 1;
+ ega_lo_graph_7_2_huge[i] = or_of_bytesef << 2;
+ ega_lo_graph_7_3_huge[i] = or_of_bytesef << 3;
+
+#endif /* BIGWIN */
+ }
+
+ ega_colour_lo_graph_deja_vu = TRUE;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::: Initialise EGA med/hi res graphics :::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_ega_med_and_hi_graph_luts()
+{
+ static boolean init_ega_med_and_hi_graph_luts_deja_vu = FALSE;
+ unsigned int i,
+ byte0,
+ byte1,
+ byte2,
+ byte3,
+ byte4,
+ byte5,
+ byte6,
+ byte7,
+ or_of_bytes1,
+ or_of_bytes2,
+ *lut0_ptr = &ega_med_and_hi_graph_luts[0],
+ *lut1_ptr = lut0_ptr + LUT_OFFSET,
+ *lut2_ptr = lut1_ptr + LUT_OFFSET,
+ *lut3_ptr = lut2_ptr + LUT_OFFSET;
+#ifdef BIGWIN
+ unsigned int or_of_bytes3,
+ or_of_bytes4,
+ *lut0_big_ptr = &ega_med_and_hi_graph_luts_big[0],
+ *lut1_big_ptr = lut0_big_ptr + BIG_LUT_OFFSET,
+ *lut2_big_ptr = lut1_big_ptr + BIG_LUT_OFFSET,
+ *lut3_big_ptr = lut2_big_ptr + BIG_LUT_OFFSET,
+ *lut0_huge_ptr = &ega_med_and_hi_graph_luts_huge[0],
+ *lut1_huge_ptr = lut0_huge_ptr + HUGE_LUT_OFFSET,
+ *lut2_huge_ptr = lut1_huge_ptr + HUGE_LUT_OFFSET,
+ *lut3_huge_ptr = lut2_huge_ptr + HUGE_LUT_OFFSET,
+ *lut4_huge_ptr = lut3_huge_ptr + HUGE_LUT_OFFSET;
+#endif /* BIGWIN */
+
+ sub_note_trace0(EGA_HOST_VERBOSE, "nt_init_ega_med_and_hi_graph_luts");
+
+ if (init_ega_med_and_hi_graph_luts_deja_vu)
+ return;
+
+ init_ega_med_and_hi_graph_luts_deja_vu = TRUE;
+
+ for(i = 0; i < 256; i++)
+ {
+ byte0 = i & 0x1;
+ byte1 = (i & 0x2) >> 1;
+ byte2 = (i & 0x4) >> 2;
+ byte3 = (i & 0x8) >> 3;
+ byte4 = (i & 0x10) >> 4;
+ byte5 = (i & 0x20) >> 5;
+ byte6 = (i & 0x40) >> 6;
+ byte7 = (i & 0x80) >> 7;
+
+#ifdef BIGEND
+
+ or_of_bytes1 = (byte3 << 24) | (byte2 << 16) | (byte1 << 8) | byte0;
+ or_of_bytes2 = (byte7 << 24) | (byte6 << 16) | (byte5 << 8) | byte4;
+
+#endif /* BIGEND */
+
+#ifdef LITTLEND
+
+ or_of_bytes1 = (byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3;
+ or_of_bytes2 = (byte4 << 24) | (byte5 << 16) | (byte6 << 8) | byte7;
+
+#endif /* LITTLEND */
+
+
+ lut0_ptr[2*i] = or_of_bytes2;
+ lut0_ptr[2*i+1] = or_of_bytes1;
+ lut1_ptr[2*i] = or_of_bytes2 << 1;
+ lut1_ptr[2*i+1] = or_of_bytes1 << 1;
+ lut2_ptr[2*i] = or_of_bytes2 << 2;
+ lut2_ptr[2*i+1] = or_of_bytes1 << 2;
+ lut3_ptr[2*i] = or_of_bytes2 << 3;
+ lut3_ptr[2*i+1] = or_of_bytes1 << 3;
+
+#ifdef BIGWIN
+#ifdef BIGEND
+
+ or_of_bytes1 = (byte2 << 24) | (byte1 << 16) | (byte0 << 8) | byte0;
+ or_of_bytes2 = (byte4 << 24) | (byte4 << 16) | (byte3 << 8) | byte2;
+ or_of_bytes3 = (byte7 << 24) | (byte6 << 16) | (byte6 << 8) | byte5;
+
+#endif /*BIGEND */
+
+#ifdef LITTLEND
+
+ or_of_bytes1 = (byte0 << 24) | (byte0 << 16) | (byte1 << 8) | byte2;
+ or_of_bytes2 = (byte2 << 24) | (byte3 << 16) | (byte4 << 8) | byte4;
+ or_of_bytes3 = (byte5 << 24) | (byte6 << 16) | (byte6 << 8) | byte7;
+
+#endif /* LITTLEND */
+
+ lut0_big_ptr[3*i] = or_of_bytes3;
+ lut0_big_ptr[3*i+1] = or_of_bytes2;
+ lut0_big_ptr[3*i+2] = or_of_bytes1;
+ lut1_big_ptr[3*i] = or_of_bytes3 << 1;
+ lut1_big_ptr[3*i+1] = or_of_bytes2 << 1;
+ lut1_big_ptr[3*i+2] = or_of_bytes1 << 1;
+ lut2_big_ptr[3*i] = or_of_bytes3 << 2;
+ lut2_big_ptr[3*i+1] = or_of_bytes2 << 2;
+ lut2_big_ptr[3*i+2] = or_of_bytes1 << 2;
+ lut3_big_ptr[3*i] = or_of_bytes3 << 3;
+ lut3_big_ptr[3*i+1] = or_of_bytes2 << 3;
+ lut3_big_ptr[3*i+2] = or_of_bytes1 << 3;
+
+#ifdef BIGEND
+
+ or_of_bytes1 = (byte1 << 24) | (byte1 << 16) | (byte0 << 8) | byte0;
+ or_of_bytes2 = (byte3 << 24) | (byte3 << 16) | (byte2 << 8) | byte2;
+ or_of_bytes3 = (byte5 << 24) | (byte5 << 16) | (byte4 << 8) | byte4;
+ or_of_bytes4 = (byte7 << 24) | (byte7 << 16) | (byte6 << 8) | byte6;
+
+#endif /* BIGEND */
+
+#ifdef LITTLEND
+
+ or_of_bytes1 = (byte0 << 24) | (byte0 << 16) | (byte1 << 8) | byte1;
+ or_of_bytes2 = (byte2 << 24) | (byte2 << 16) | (byte3 << 8) | byte3;
+ or_of_bytes3 = (byte4 << 24) | (byte4 << 16) | (byte5 << 8) | byte5;
+ or_of_bytes4 = (byte6 << 24) | (byte6 << 16) | (byte7 << 8) | byte7;
+
+#endif /* LITTLEND */
+
+ lut0_huge_ptr[4*i] = or_of_bytes4;
+ lut0_huge_ptr[4*i+1] = or_of_bytes3;
+ lut0_huge_ptr[4*i+2] = or_of_bytes2;
+ lut0_huge_ptr[4*i+3] = or_of_bytes1;
+ lut1_huge_ptr[4*i] = or_of_bytes4 << 1;
+ lut1_huge_ptr[4*i+1] = or_of_bytes3 << 1;
+ lut1_huge_ptr[4*i+2] = or_of_bytes2 << 1;
+ lut1_huge_ptr[4*i+3] = or_of_bytes1 << 1;
+ lut2_huge_ptr[4*i] = or_of_bytes4 << 2;
+ lut2_huge_ptr[4*i+1] = or_of_bytes3 << 2;
+ lut2_huge_ptr[4*i+2] = or_of_bytes2 << 2;
+ lut2_huge_ptr[4*i+3] = or_of_bytes1 << 2;
+ lut3_huge_ptr[4*i] = or_of_bytes4 << 3;
+ lut3_huge_ptr[4*i+1] = or_of_bytes3 << 3;
+ lut3_huge_ptr[4*i+2] = or_of_bytes2 << 3;
+ lut3_huge_ptr[4*i+3] = or_of_bytes1 << 3;
+ lut4_huge_ptr[4*i] = or_of_bytes4 << 4;
+ lut4_huge_ptr[4*i+1] = or_of_bytes3 << 4;
+ lut4_huge_ptr[4*i+2] = or_of_bytes2 << 4;
+ lut4_huge_ptr[4*i+3] = or_of_bytes1 << 4;
+#endif /* BIGWIN */
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::: Initialise EGA med res graphics ::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_ega_med_graph()
+{
+ sub_note_trace0(EGA_HOST_VERBOSE, "nt_init_ega_med_graph");
+
+ /* Set up the number of bits per pixel for this mode. */
+ sc.BitsPerPixel = EGA_BITS_PER_PIXEL;
+
+ /* Initialise the medium- and high-resolution look-up tables. */
+ nt_init_ega_med_and_hi_graph_luts();
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::: Initialise hi res graphics :::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_ega_hi_graph()
+{
+
+ sub_note_trace0(EGA_HOST_VERBOSE, "nt_init_ega_hi_graph");
+
+ /* Set up the number of bits per pixel for this mode. */
+ sc.BitsPerPixel = EGA_BITS_PER_PIXEL;
+
+ /* Initialise the medium- and high-resolution look-up tables. */
+ nt_init_ega_med_and_hi_graph_luts();
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::: Paint EGA screen with user defined font ::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void ega_nt_text_with_user_font(int offset,int cur_xpos,int cur_ypos,int len)
+{
+ int a = offset = cur_xpos = cur_ypos = len;
+
+sub_note_trace0(EGA_HOST_VERBOSE,"ega_nt_text_with_user_font - NOT SUPPORTED");
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::: Paint EGA screen with user defined font ::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void ega_nt_big_text_with_user_font(int offset, int cur_xpos,
+ int cur_ypos, int len)
+{
+ int a = offset = cur_xpos = cur_ypos = len;
+
+ sub_note_trace0(EGA_HOST_VERBOSE,
+ "ega_nt_big_text_with_user_font - NOT SUPPORTED");
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::: Paint screen with EGA text ::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint win32 screen (MODE 13: PC 320x200. SoftPC 640x400) ::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_lo_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ unsigned int *p0,
+ *ref_p0,
+ *dest_ptr,
+ *save_dest_ptr,
+ data0,
+ data1,
+ data2,
+ data3;
+ int local_width,
+ local_height,
+ longs_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_lo_graph_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>200 || width>40 ){
+ assert2( NO, "VDM: nt_ega_lo_graph_std() w=%d h=%d", width, height );
+ return;
+ }
+
+
+ /* Get source and destination data pointers. */
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_p0 = (unsigned int *) get_regen_ptr(0, offset << 2);
+ save_dest_ptr = (unsigned int *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y << 1) * longs_per_scanline +
+ (screen_x >> 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /*
+ * Build up DIB: 4 consecutive bytes in video memory correspond to 8
+ * pixels, the first byte containing plane 0 bits, the second byte plane 1
+ * and so on. This mode is low resolution so each pixel in video memory
+ * becomes a block of 4 pixels on the PC screen.
+ * The DIB contains the bottom line of pixels first, then second bottom
+ * so on.
+ */
+ local_height = height;
+ do
+ {
+ p0 = ref_p0;
+ local_width = width;
+ dest_ptr = save_dest_ptr;
+
+ do
+ {
+ data0 = *p0++;
+ data3 = HIBYTE(HIWORD(data0));
+ data2 = LOBYTE(HIWORD(data0));
+ data1 = HIBYTE(LOWORD(data0));
+ data0 = LOBYTE(LOWORD(data0));
+
+ *(dest_ptr + longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_3_0[data0] | ega_lo_graph_3_1[data1]
+ | ega_lo_graph_3_2[data2] | ega_lo_graph_3_3[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_2_0[data0] | ega_lo_graph_2_1[data1]
+ | ega_lo_graph_2_2[data2] | ega_lo_graph_2_3[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_1_0[data0] | ega_lo_graph_1_1[data1]
+ | ega_lo_graph_1_2[data2] | ega_lo_graph_1_3[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_0_0[data0] | ega_lo_graph_0_1[data1]
+ | ega_lo_graph_0_2[data2] | ega_lo_graph_0_3[data3];
+ dest_ptr++;
+
+ }
+ while(--local_width);
+
+ save_dest_ptr += 2 * longs_per_scanline;
+ ref_p0 += get_offset_per_line();
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x << 1;
+ rect.Top = screen_y << 1;
+ rect.Right = rect.Left + (width << 4) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint win32 screen (MODE 13: PC 320x200. SoftPC 960x600) ::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_lo_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+#ifdef BIGWIN
+ unsigned int *p0,
+ *ref_p0,
+ *dest_ptr,
+ *save_dest_ptr,
+ data0,
+ data1,
+ data2,
+ data3;
+ int local_width,
+ local_height,
+ longs_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_lo_graph_big off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>200 || width>40 ){
+ assert2( NO, "VDM: nt_ega_lo_graph_big() w=%d h=%d", width, height );
+ return;
+ }
+
+
+ /* Get source and destination data pointers. */
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_p0 = (unsigned int *) get_regen_ptr(0, offset << 2);
+ save_dest_ptr = (unsigned int *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y << 1) * longs_per_scanline +
+ SCALE(screen_x >> 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Build up DIB. */
+ local_height = height;
+ do
+ {
+ p0 = ref_p0;
+ local_width = width;
+ dest_ptr = save_dest_ptr;
+
+ do
+ {
+ data0 = *p0++;
+ data3 = HIBYTE(HIWORD(data0));
+ data2 = LOBYTE(HIWORD(data0));
+ data1 = HIBYTE(LOWORD(data0));
+ data0 = LOBYTE(LOWORD(data0));
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2*longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_5_0_big[data0]
+ | ega_lo_graph_5_1_big[data1]
+ | ega_lo_graph_5_2_big[data2]
+ | ega_lo_graph_5_3_big[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2*longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_4_0_big[data0]
+ | ega_lo_graph_4_1_big[data1]
+ | ega_lo_graph_4_2_big[data2]
+ | ega_lo_graph_4_3_big[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2*longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_3_0_big[data0]
+ | ega_lo_graph_3_1_big[data1]
+ | ega_lo_graph_3_2_big[data2]
+ | ega_lo_graph_3_3_big[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2*longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_2_0_big[data0]
+ | ega_lo_graph_2_1_big[data1]
+ | ega_lo_graph_2_2_big[data2]
+ | ega_lo_graph_2_3_big[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2*longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_1_0_big[data0]
+ | ega_lo_graph_1_1_big[data1]
+ | ega_lo_graph_1_2_big[data2]
+ | ega_lo_graph_1_3_big[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2*longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_0_0_big[data0]
+ | ega_lo_graph_0_1_big[data1]
+ | ega_lo_graph_0_2_big[data2]
+ | ega_lo_graph_0_3_big[data3];
+ dest_ptr++;
+
+ }
+ while( --local_width );
+
+ save_dest_ptr += 3 * longs_per_scanline;
+ ref_p0 += get_offset_per_line();
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x << 1);
+ rect.Top = SCALE(screen_y << 1);
+ rect.Right = rect.Left + SCALE(width << 4) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ /* Display the DIB. */
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint win32 screen (MODE 13: PC 320x200. SoftPC 1280x800) ::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_lo_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height )
+{
+#ifdef BIGWIN
+ unsigned int *p0,
+ *ref_p0,
+ *dest_ptr,
+ *save_dest_ptr,
+ data0,
+ data1,
+ data2,
+ data3;
+ int local_width,
+ local_height,
+ longs_per_scanline;
+ SMALL_RECT rect;
+
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_lo_graph_huge off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>200 || width>40 ){
+ assert2( NO, "VDM: nt_ega_lo_graph_huge() w=%d h=%d", width, height );
+ return;
+ }
+
+
+ /* Get source and destination data pointers. */
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_p0 = (unsigned int *) get_regen_ptr(0, offset << 2);
+ save_dest_ptr = (unsigned int *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y << 1) * longs_per_scanline +
+ SCALE(screen_x >> 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Build up DIB. */
+ local_height = height;
+ do
+ {
+ p0 = ref_p0;
+ local_width = width;
+ dest_ptr = save_dest_ptr;
+
+ do
+ {
+ data0 = *p0++;
+ data3 = HIBYTE(HIWORD(data0));
+ data2 = LOBYTE(HIWORD(data0));
+ data1 = HIBYTE(LOWORD(data0));
+ data0 = LOBYTE(LOWORD(data0));
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2 * longs_per_scanline)
+ = *(dest_ptr + 3 * longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_7_0_huge[data0]
+ | ega_lo_graph_7_1_huge[data1]
+ | ega_lo_graph_7_2_huge[data2]
+ | ega_lo_graph_7_3_huge[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2 * longs_per_scanline)
+ = *(dest_ptr + 3 * longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_6_0_huge[data0]
+ | ega_lo_graph_6_1_huge[data1]
+ | ega_lo_graph_6_2_huge[data2]
+ | ega_lo_graph_6_3_huge[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2 * longs_per_scanline)
+ = *(dest_ptr + 3 * longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_5_0_huge[data0]
+ | ega_lo_graph_5_1_huge[data1]
+ | ega_lo_graph_5_2_huge[data2]
+ | ega_lo_graph_5_3_huge[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2 * longs_per_scanline)
+ = *(dest_ptr + 3 * longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_4_0_huge[data0]
+ | ega_lo_graph_4_1_huge[data1]
+ | ega_lo_graph_4_2_huge[data2]
+ | ega_lo_graph_4_3_huge[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2 * longs_per_scanline)
+ = *(dest_ptr + 3 * longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_3_0_huge[data0]
+ | ega_lo_graph_3_1_huge[data1]
+ | ega_lo_graph_3_2_huge[data2]
+ | ega_lo_graph_3_3_huge[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2 * longs_per_scanline)
+ = *(dest_ptr + 3 * longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_2_0_huge[data0]
+ | ega_lo_graph_2_1_huge[data1]
+ | ega_lo_graph_2_2_huge[data2]
+ | ega_lo_graph_2_3_huge[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2 * longs_per_scanline)
+ = *(dest_ptr + 3 * longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_1_0_huge[data0]
+ | ega_lo_graph_1_1_huge[data1]
+ | ega_lo_graph_1_2_huge[data2]
+ | ega_lo_graph_1_3_huge[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *(dest_ptr + 2 * longs_per_scanline)
+ = *(dest_ptr + 3 * longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_0_0_huge[data0]
+ | ega_lo_graph_0_1_huge[data1]
+ | ega_lo_graph_0_2_huge[data2]
+ | ega_lo_graph_0_3_huge[data3];
+ dest_ptr++;
+
+ }
+ while( --local_width );
+
+ save_dest_ptr += 4 * longs_per_scanline;
+ ref_p0 += get_offset_per_line();
+ } while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x << 1);
+ rect.Top = SCALE(screen_y << 1);
+ rect.Right = rect.Left + SCALE(width << 4) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ /* Display the DIB. */
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint Win32 screen (MODE 14: PC 640x200. SoftPC 640x400) :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_med_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ register unsigned int *p0;
+ register char *dest_ptr;
+ register int local_height;
+ int bytes_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_med_graph_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>200 || width>80 ){
+ assert2( NO, "VDM: nt_ega_med_graph_std() w=%d h=%d", width, height );
+ return;
+ }
+
+
+ /*
+ * Build up device-independent bitmap: one PC pixel is represented by two
+ * host pixels, one above the other.
+ */
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ p0 = (unsigned int *) get_regen_ptr(0, offset << 2);
+ local_height = height;
+ dest_ptr = (char *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y << 1) * bytes_per_scanline +
+ screen_x;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Build up the bitmap. */
+ do
+ {
+ ega_colour_hi_munge((unsigned char *) p0,
+ width,
+ (unsigned int *) dest_ptr,
+ ega_med_and_hi_graph_luts,
+ TWO_SCANLINES,
+ bytes_per_scanline);
+ p0 += get_offset_per_line();
+ dest_ptr += TWO_SCANLINES * bytes_per_scanline;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y << 1;
+ rect.Right = rect.Left + (width << 3) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint Win32 screen MODE 14: PC 640x200. SoftPC 960x600 :::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_med_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+#ifdef BIGWIN
+ register unsigned int *p0;
+ register char *dest_ptr;
+ register int local_height;
+ int bytes_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_med_graph_big off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>200 || width>80 ){
+ assert2( NO, "VDM: nt_ega_med_graph_big() w=%d h=%d", width, height );
+ return;
+ }
+
+
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ p0 = (unsigned int *) get_regen_ptr(0, offset << 2);
+ local_height = height;
+ dest_ptr = (char *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y << 1) * bytes_per_scanline +
+ SCALE(screen_x);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ ega_colour_hi_munge_big( (unsigned char *) p0,
+ width,
+ (unsigned int *) dest_ptr,
+ ega_med_and_hi_graph_luts_big,
+ THREE_SCANLINES,
+ bytes_per_scanline);
+ p0 += get_offset_per_line();
+ dest_ptr += THREE_SCANLINES * bytes_per_scanline;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = SCALE(screen_y << 1);
+ rect.Right = rect.Left + SCALE(width << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint Win32 screen MODE 14: PC 640x200. SoftPC 1280x800 :::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_med_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height )
+{
+#ifdef BIGWIN
+ register unsigned int *p0;
+ register char *dest_ptr;
+ register int local_height;
+ int bytes_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_med_graph_huge off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>200 || width>80 ){
+ assert2( NO, "VDM: nt_ega_med_graph_huge() w=%d h=%d", width, height );
+ return;
+ }
+
+
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ p0 = (unsigned int *) get_regen_ptr(0, offset << 2);
+ local_height = height;
+ dest_ptr = (char *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y << 1) * bytes_per_scanline +
+ SCALE(screen_x);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ ega_colour_hi_munge_huge( (unsigned char *) p0,
+ width,
+ (unsigned int *) dest_ptr,
+ ega_med_and_hi_graph_luts_huge,
+ FOUR_SCANLINES,
+ bytes_per_scanline);
+ p0 += get_offset_per_line();
+ dest_ptr += FOUR_SCANLINES * bytes_per_scanline;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = SCALE(screen_y << 1);
+ rect.Right = rect.Left + SCALE(width << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint Win32 screen (MODE 16: PC 640x350. SoftPC 960x375) :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_hi_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ register unsigned int *p0;
+ register char *dest_ptr;
+ register int local_height;
+ int bytes_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_hi_graph_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>480 || width>80 ){
+ assert2( NO, "VDM: nt_ega_hi_graph_std() w=%d h=%d", width, height );
+ return;
+ }
+
+ /* Build up the device independent bitmap. */
+ p0 = ( unsigned int *) get_regen_ptr( 0, offset << 2 );
+ local_height = height;
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ dest_ptr = (char *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * bytes_per_scanline +
+ screen_x;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ ega_colour_hi_munge((unsigned char *) p0,
+ width,
+ (unsigned int *) dest_ptr,
+ ega_med_and_hi_graph_luts,
+ ONE_SCANLINE,
+ 0);
+ p0 += get_offset_per_line();
+ dest_ptr += bytes_per_scanline;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (width << 3) - 1;
+ rect.Bottom = rect.Top + height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint Win32 screen (MODE 16: PC 640x350. SoftPC 960x525) :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_hi_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+#ifdef BIGWIN
+ register unsigned int *p0;
+ register char *dest_ptr;
+ register int local_height;
+ register int local_screen_y;
+ register int scale_width_in_bits;
+ int bytes_per_scanline;
+ BOOL two_lines;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_hi_graph_big off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>480 || width>80 ){
+ assert2( NO, "VDM: nt_ega_hi_graph_big() w=%d h=%d", width, height );
+ return;
+ }
+
+
+ /* Get pointer to video memory. */
+ p0 = (unsigned int *) get_regen_ptr(0, offset << 2);
+
+ /*
+ * Get pointer into bitmap, which alternates 2 lines and 1 line so that,
+ * memory line 0 -> bitmap 0,
+ * 1 -> 2,
+ * 2 -> 3,
+ * 3 -> 5,
+ * 4 -> 6 etc.
+ * hence the local_screen_y assignment.
+ */
+ local_screen_y = SCALE(screen_y + 1) - 1;
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ dest_ptr = (char *) sc.ConsoleBufInfo.lpBitMap +
+ local_screen_y * bytes_per_scanline +
+ SCALE(screen_x);
+
+ /*
+ * 2 lines are output to the SoftPC screen if this is an odd line, 1 line
+ * if it is even.
+ */
+ two_lines = screen_y & 1 ? FALSE : TRUE;
+
+ /*
+ * One bit in video memory planes corresponds to one pixel. Each pixel
+ * is represented by one byte in the bitmap. Two pixels are scaled to
+ * three in the bitmap. `scale_width_in_bits' is the number of bytes that
+ * will be output to a bitmap line.
+ */
+ scale_width_in_bits = SCALE(width << 3);
+
+ /* Storage for actual number of lines in bitmap. */
+ local_height = 0;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ ega_colour_hi_munge_big((unsigned char *) p0,
+ width,
+ (unsigned int *) dest_ptr,
+ ega_med_and_hi_graph_luts_big,
+ ONE_SCANLINE,
+ 0);
+
+ /* one line done, alternate ones have to be doubled */
+ if(two_lines)
+ {
+ memcpy(dest_ptr + bytes_per_scanline,
+ dest_ptr,
+ scale_width_in_bits);
+ dest_ptr += 2 * bytes_per_scanline;
+ local_height += 2;
+ }
+ else
+ {
+ dest_ptr += bytes_per_scanline;
+ local_height++;
+ }
+ two_lines = !two_lines;
+
+ p0 += get_offset_per_line();
+ }
+ while(--height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = local_screen_y;
+ rect.Right = rect.Left + scale_width_in_bits - 1;
+ rect.Bottom = rect.Top + local_height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint Win32 screen (MODE 16: PC 640x350. SoftPC 1280x700) :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_hi_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+#ifdef BIGWIN
+ register unsigned int *p0;
+ register char *dest_ptr;
+ register int local_height;
+ int bytes_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_hi_graph_huge off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>480 || width>80 ){
+ assert2( NO, "VDM: nt_ega_hi_graph_huge() w=%d h=%d", width, height );
+ return;
+ }
+
+
+ p0 = (unsigned int *) get_regen_ptr(0, offset << 2);
+ local_height = height;
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ dest_ptr = (char *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y) * bytes_per_scanline +
+ SCALE(screen_x);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ ega_colour_hi_munge_huge((unsigned char *) p0,
+ width,
+ (unsigned int *) dest_ptr,
+ ega_med_and_hi_graph_luts_huge,
+ ONE_SCANLINE,
+ 0);
+
+ p0 += get_offset_per_line();
+ memcpy(dest_ptr + bytes_per_scanline, dest_ptr, SCALE(width << 3));
+ dest_ptr += 2 * bytes_per_scanline;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(width << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint Win32 screen (MODE : EGA mono low res graphics) ::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_lo_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_lo_graph_std off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::: Paint function for EGA mono low res graphics on big screen ::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_lo_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height )
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_lo_graph_big off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::: Paint function for EGA mono low res graphics on huge screen :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_lo_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height )
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_lo_graph_huge off=%d x=%d y=%d width=%d h=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height );
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::: Paint function for EGA mono med res graphics :::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_med_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_med_graph_std off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::: Paint function for EGA mono med res graphics on big screen ::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_med_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_med_graph_big off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::: Paint function for EGA mono med res graphics on huge screen :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_med_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_med_graph_huge off=%d x=%d y=%d width=%d h=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::: Paint function for EGA mono hi res graphics :::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_hi_graph_std_byte(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_hi_graph_std_byte off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::: Paint function for EGA mono hi res graphics (long):::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_hi_graph_std_long(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_hi_graph_std_long off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::: Paint function for EGA mono hi res graphics :::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_hi_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_hi_graph_std off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::: Paint function for EGA mono hi res graphics on big screen::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_hi_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_hi_graph_big off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::: Paint function for EGA mono hi res graphics on huge screen:::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_mono_hi_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height )
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_mono_hi_graph_huge off=%d x=%d y=%d width=%d h=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+#ifdef MONITOR
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint frozen screen (MODE 13: PC 320x200. SoftPC 640x400) :::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_lo_frozen_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ UTINY *plane1_ptr,
+ *plane2_ptr,
+ *plane3_ptr,
+ *plane4_ptr;
+ ULONG *dest_ptr,
+ *save_dest_ptr,
+ mem_loc,
+ data0,
+ data1,
+ data2,
+ data3,
+ local_width,
+ local_height,
+ longs_per_scanline,
+ bpl = get_bytes_per_line(),
+ mem_x = screen_x >> 3,
+ max_width = sc.PC_W_Width >> 4,
+ max_height = sc.PC_W_Height >> 1;
+ SMALL_RECT rect;
+ BOOL fMutexTaken = FALSE;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_lo_frozen_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((mem_x >= max_width) || ((ULONG) screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_ega_lo_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (mem_x + width > max_width)
+ width = max_width - mem_x;
+ if ((ULONG) (screen_y + height) > max_height)
+ height = max_height - screen_y;
+
+ /* memory involved here liable to be suddenly removed due to fs switch */
+ try
+ {
+ /* Get source and destination data pointers. */
+ plane1_ptr = GET_OFFSET(Plane1Offset);
+ plane2_ptr = GET_OFFSET(Plane2Offset);
+ plane3_ptr = GET_OFFSET(Plane3Offset);
+ plane4_ptr = GET_OFFSET(Plane4Offset);
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ save_dest_ptr = (unsigned int *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y << 1) * longs_per_scanline +
+ (screen_x >> 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ fMutexTaken = TRUE;
+
+ /*
+ * Build up DIB: 4 consecutive bytes in video memory correspond to 8
+ * pixels the first byte containing plane 0, the second byte plane 1
+ * and so on. This mode is low resolution so each pixel in video memory
+ * becomes a block of 4 pixels on the PC screen.
+ * The DIB contains the bottom line of pixels first, then second bottom
+ * so on.
+ */
+ local_height = height;
+ do
+ {
+ local_width = width;
+ dest_ptr = save_dest_ptr;
+ mem_loc = offset;
+ do
+ {
+ data0 = *(plane1_ptr + mem_loc);
+ data1 = *(plane2_ptr + mem_loc);
+ data2 = *(plane3_ptr + mem_loc);
+ data3 = *(plane4_ptr + mem_loc);
+
+ *(dest_ptr + longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_3_0[data0] | ega_lo_graph_3_1[data1]
+ | ega_lo_graph_3_2[data2] | ega_lo_graph_3_3[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_2_0[data0] | ega_lo_graph_2_1[data1]
+ | ega_lo_graph_2_2[data2] | ega_lo_graph_2_3[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_1_0[data0] | ega_lo_graph_1_1[data1]
+ | ega_lo_graph_1_2[data2] | ega_lo_graph_1_3[data3];
+ dest_ptr++;
+
+ *(dest_ptr + longs_per_scanline)
+ = *dest_ptr
+ = ega_lo_graph_0_0[data0] | ega_lo_graph_0_1[data1]
+ | ega_lo_graph_0_2[data2] | ega_lo_graph_0_3[data3];
+ dest_ptr++;
+ mem_loc++;
+ }
+ while(--local_width);
+ save_dest_ptr += 2 * longs_per_scanline;
+ offset += bpl;
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ fMutexTaken = FALSE;
+
+ /* Display the new image. */
+ rect.Left = screen_x << 1;
+ rect.Top = screen_y << 1;
+ rect.Right = rect.Left + (width << 4) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "Handled fault in nt_ega_lo_frozen_std. fs switch?");
+ if (fMutexTaken)
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+ return;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint frozen screen (MODE 14: PC 640x200. SoftPC 640x400) :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_med_frozen_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ ULONG local_height,
+ local_width,
+ longs_per_scanline,
+ *dest_ptr,
+ *ref_dest_ptr,
+ *lut0_ptr = ega_med_and_hi_graph_luts,
+ *lut1_ptr = lut0_ptr + LUT_OFFSET,
+ *lut2_ptr = lut1_ptr + LUT_OFFSET,
+ *lut3_ptr = lut2_ptr + LUT_OFFSET,
+ *l_ptr,
+ hi_res,
+ lo_res,
+ mem_loc,
+ bpl = get_bytes_per_line(),
+ plane_mask = get_plane_mask(),
+ mem_x = screen_x >> 3,
+ max_width = sc.PC_W_Width >> 3,
+ max_height = sc.PC_W_Height >> 1;
+ UTINY *plane1_ptr,
+ *plane2_ptr,
+ *plane3_ptr,
+ *plane4_ptr;
+ SMALL_RECT rect;
+ BOOL fMutexTaken = FALSE;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_med_frozen_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((mem_x >= max_width) || ((ULONG) screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_ega_med_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (mem_x + width > max_width)
+ width = max_width - mem_x;
+ if ((ULONG) (screen_y + height) > max_height)
+ height = max_height - screen_y;
+
+ /* memory involved here liable to be suddenly removed due to fs switch */
+ try
+ {
+ /*
+ * Build up device-independent bitmap: one PC pixel is represented by
+ * two host pixels, one above the other.
+ */
+ plane1_ptr = GET_OFFSET(Plane1Offset);
+ plane2_ptr = GET_OFFSET(Plane2Offset);
+ plane3_ptr = GET_OFFSET(Plane3Offset);
+ plane4_ptr = GET_OFFSET(Plane4Offset);
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (ULONG *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y << 1) * longs_per_scanline +
+ (screen_x >> 2);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ fMutexTaken = TRUE;
+
+ /* Build up the bitmap. */
+ local_height = height;
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ mem_loc = offset;
+ local_width = width;
+ do
+ {
+ hi_res = 0;
+ lo_res = 0;
+
+ /* Get 8 bytes of output data from 1 byte of plane 0 data. */
+ if (plane_mask & 1)
+ {
+ l_ptr = &lut0_ptr[*(plane1_ptr + mem_loc) << 1];
+ hi_res = *l_ptr++;
+ lo_res = *l_ptr;
+ }
+
+ /* Or in the output data from plane 1 */
+ if (plane_mask & 2)
+ {
+ l_ptr = &lut1_ptr[*(plane2_ptr + mem_loc) << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+
+ /* Or in the output data from plane 2 */
+ if (plane_mask & 4)
+ {
+ l_ptr = &lut2_ptr[*(plane3_ptr + mem_loc) << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+
+ /* Or in the output data from plane 3 */
+ if (plane_mask & 8)
+ {
+ l_ptr = &lut3_ptr[*(plane4_ptr + mem_loc) << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+
+ /* Now store it in the bitmap. */
+ *(dest_ptr + longs_per_scanline) = *dest_ptr = hi_res;
+ dest_ptr++;
+ *(dest_ptr + longs_per_scanline) = *dest_ptr = lo_res;
+ *dest_ptr++;
+ mem_loc++;
+ }
+ while (--local_width);
+ ref_dest_ptr += 2 * longs_per_scanline;
+ offset += bpl;
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ fMutexTaken = FALSE;
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y << 1;
+ rect.Right = rect.Left + (width << 3) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "Handled fault in nt_ega_med_frozen_std. fs switch?");
+ if (fMutexTaken)
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+ return;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Paint frozen screen (MODE 16: PC 640x350. SoftPC 640x350) ::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_ega_hi_frozen_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ ULONG local_height,
+ local_width,
+ longs_per_scanline,
+ *dest_ptr,
+ *ref_dest_ptr,
+ *lut0_ptr = ega_med_and_hi_graph_luts,
+ *lut1_ptr = lut0_ptr + LUT_OFFSET,
+ *lut2_ptr = lut1_ptr + LUT_OFFSET,
+ *lut3_ptr = lut2_ptr + LUT_OFFSET,
+ *l_ptr,
+ hi_res,
+ lo_res,
+ mem_loc,
+ bpl = get_bytes_per_line(),
+ plane_mask = get_plane_mask(),
+ mem_x = screen_x >> 3,
+ max_width = sc.PC_W_Width >> 3,
+ max_height = sc.PC_W_Height;
+ UTINY *plane1_ptr,
+ *plane2_ptr,
+ *plane3_ptr,
+ *plane4_ptr;
+ SMALL_RECT rect;
+ BOOL fMutexTaken = FALSE;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_ega_hi_frozen_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((mem_x >= max_width) || ((ULONG) screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_ega_hi_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (mem_x + width > max_width)
+ width = max_width - mem_x;
+ if ((ULONG) (screen_y + height) > max_height)
+ height = max_height - screen_y;
+
+ /* memory involved here liable to be suddenly removed due to fs switch */
+ try
+ {
+
+ /* Build up the device independent bitmap. */
+ local_height = height;
+ plane1_ptr = GET_OFFSET(Plane1Offset);
+ plane2_ptr = GET_OFFSET(Plane2Offset);
+ plane3_ptr = GET_OFFSET(Plane3Offset);
+ plane4_ptr = GET_OFFSET(Plane4Offset);
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (ULONG *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * longs_per_scanline +
+ (screen_x >> 2);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ fMutexTaken = TRUE;
+
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ local_width = width;
+ mem_loc = offset;
+ do
+ {
+
+ /* Get 8 bytes of output data from 1 byte of plane 0 data. */
+ if (plane_mask & 1)
+ {
+ l_ptr = &lut0_ptr[*(plane1_ptr + mem_loc) << 1];
+ hi_res = *l_ptr++;
+ lo_res = *l_ptr;
+ }
+
+ /* Or in the output data from plane 1 */
+ if (plane_mask & 2)
+ {
+ l_ptr = &lut1_ptr[*(plane2_ptr + mem_loc) << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+
+ /* Or in the output data from plane 2 */
+ if (plane_mask & 4)
+ {
+ l_ptr = &lut2_ptr[*(plane3_ptr + mem_loc) << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+
+ /* Or in the output data from plane 3 */
+ if (plane_mask & 8)
+ {
+ l_ptr = &lut3_ptr[*(plane4_ptr + mem_loc) << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+
+ /* Now store it in the bitmap. */
+ *dest_ptr++ = hi_res;
+ *dest_ptr++ = lo_res;
+ mem_loc++;
+ }
+ while (--local_width);
+ ref_dest_ptr += longs_per_scanline;
+ offset += bpl;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ fMutexTaken = FALSE;
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (width << 3) - 1;
+ rect.Bottom = rect.Top + height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "Handled fault in nt_ega_hi_frozen_std. fs switch?");
+ if (fMutexTaken)
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+ return;
+ }
+}
+#endif /* MONITOR */
diff --git a/private/mvdm/softpc.new/host/src/nt_emm.c b/private/mvdm/softpc.new/host/src/nt_emm.c
new file mode 100644
index 000000000..79a8204ab
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_emm.c
@@ -0,0 +1,817 @@
+/* INSIGNIA MODULE SPECIFICATION
+ -----------------------------
+
+MODULE NAME : 'Lower layer' of Expanded Memory Manager
+
+ THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
+ CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MUST
+ NOT BE DISCLOSED TO ANY OTHER PARTIES WITHOUT THE EXPRESS
+ AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS INC.
+
+DESIGNER : J.P.Box
+DATE : April '88
+
+PURPOSE : NT specific code for EMS LIM rev 4.0
+ implementation.
+
+The Following Routines are defined:
+ 1. host_initialise_EM()
+ 2. host_deinitialise_EM()
+ 3. host_allocate_storage()
+ 4. host_free_storage()
+ 5. host_reallocate_storage()
+ 6. host_map_page()
+ 7. host_unmap_page()
+ 8. host_alloc_page()
+ 9. host_free_page()
+ 10. host_copy_con_to_con()
+ 11. host_copy_con_to_EM()
+ 12. host_copy_EM_to_con()
+ 13. host_copy_EM_to_EM()
+ 14. host_exchg_con_to_con()
+ 15. host_exchg_con_to_EM()
+ 16. host_exchg_EM_to_EM()
+ 17. host_get_access_key()
+
+*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include "insignia.h"
+#include "host_def.h"
+
+#ifdef LIM
+
+#ifndef MONITOR
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "timeval.h"
+#include "xt.h"
+#include "emm.h"
+#include "sas.h"
+#include "debug.h"
+#include "umb.h"
+#include "host_emm.h"
+#include "nt_mem.h"
+
+
+/* Global Variables */
+
+/* Forward Declarations */
+
+/* ExternalDeclarations */
+
+/* Local Variables */
+
+UTINY *EM_pagemap_address = 0; /* address of start of pagemap */
+sys_addr EM_base_address; /* EM base intel address */
+host_addr EM_host_base_address = 0; /* EM base host address */
+
+LOCAL LONG EM_size = 0;
+
+ sys_addr emm_start;
+ unsigned int emm_len;
+unsigned short EM_starting_page_no;
+
+/*
+Support for backwards LIM to speed up backwards M ports
+
+Defines are:
+ EM_host_address(offset), returns host address of offset bytes
+ into the LIM memory area
+ EM_loads(from, to, length), copies length bytes from intel 24 bit
+ address from, to host 32 bit address to
+ EM_stores(to, from, length), copies length bytes from host 32 bit
+ address from to intel 24 bit address to
+ EM_moves(from, to, length), copies length bytes from intel 24 bit
+ address from to intel 24 bit address to
+ EM_memcpy(to, from, length), copies length bytes from host 32 bit
+ address from to host 32 bit address to
+ EM_pointer(ptr, length), returns a forwards or backwards type
+ pointer to ptr for a buffer of size length
+*/
+
+
+#define unix_memmove(dst,src,len) memmove((dst),(src),(len))
+
+#ifdef BACK_M
+#define EM_host_address(offset) (EM_host_base_address + EM_size - offset)
+#define EM_loads(from, to, length) memcpy(to - (length) + 1, get_byte_addr(from) - (length) + 1, length)
+#define EM_stores(to, from, length) \
+ sas_overwrite_memory(to, length); \
+ CopyMemory(get_byte_addr(to) - (length) + 1, from - (length) + 1, length)
+#define EM_moves(from,to,length) \
+ sas_overwrite_memory(to, length); \
+ MoveMemory(get_byte_addr(to) - (length) + 1, get_byte_addr(from) - (length) + 1, length)
+#define EM_memcpy(to, from, length) \
+ MoveMemory((to) - (length) + 1, (from) - (length) + 1, length)
+#define EM_pointer(ptr, length) (ptr + length - 1)
+#else
+#define EM_host_address(offset) (EM_host_base_address + offset)
+#define EM_loads(from, to, length) memcpy(to, get_byte_addr(from), length)
+#define EM_stores(to, from, length) \
+ sas_overwrite_memory(to, length); \
+ CopyMemory(get_byte_addr(to), from, length)
+#define EM_moves(from,to,length) \
+ sas_overwrite_memory(to, length); \
+ MoveMemory(get_byte_addr(to), get_byte_addr(from), length)
+#define EM_memcpy(to, from, length) \
+ MoveMemory(to, from, length)
+#define EM_pointer(ptr, length) (ptr)
+#endif
+
+#define EM_PAGE_ADDRESS(page_no) (EM_base_address + page_no * EMM_PAGE_SIZE)
+
+
+/*
+===========================================================================
+
+FUNCTION : host_initialise_EM
+
+PURPOSE : allocates the area of memory that is used for
+ expanded memory and sets up an area of memory to be used
+ for the logical pagemap allocation table.
+
+
+RETURNED STATUS : SUCCESS - memory allocated successfully
+ FAILURE - unable to allocate required space
+
+DESCRIPTION :
+
+
+=========================================================================
+*/
+int host_initialise_EM(short size)
+
+/* IN short size size of area required in megabytes */
+
+
+{
+ long *pagemap_ptr; /* temp ptr. to logical pagemap */
+ short i; /* loop counter */
+ NTSTATUS status;
+
+ status = VdmAllocateVirtualMemory(&EM_base_address, size * 0x100000, FALSE);
+ if (!NT_SUCCESS(status)) {
+#ifdef EMM_DEBUG
+ printf("Couldn't allocate virtual memory for EMM, error code = %lx\n",
+ status);
+#endif
+ return FAILURE;
+ }
+#ifdef EMM_DEBUG
+ printf("EMM base address = %lx\n", ((sys_addr)EM_base_address);
+#endif
+
+ /* pagemap requires 1 bit per 16K page - i.e. 8 bytes per meg */
+
+ if((EM_pagemap_address = (byte *)host_malloc(size * 8)) == (byte *)0)
+ return(FAILURE);
+
+ /* initialise pagemap to 0's */
+
+ pagemap_ptr = (long *)EM_pagemap_address;
+ for(i = 0; i < size * 2; i++)
+ *pagemap_ptr++ = 0;
+
+ EM_size = ((long) size) * 0x100000;
+ EM_starting_page_no = (unsigned short)(EM_base_address / INTEL_PAGE_SIZE);
+ EM_host_base_address = get_byte_addr((sys_addr)EM_base_address);
+
+ return(SUCCESS);
+
+
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_deinitialise_EM
+
+PURPOSE : frees the area of memory that was used for
+ expanded memory and memory used
+ for the logical pagemap allocation table.
+
+
+RETURNED STATUS : SUCCESS - memory freed successfully
+ FAILURE - error ocurred in freeing memory
+
+DESCRIPTION :
+
+
+=========================================================================
+*/
+int host_deinitialise_EM()
+
+{
+
+ if(EM_base_address != 0)
+ VdmFreeVirtualMemory(EM_base_address);
+
+ if(EM_pagemap_address != (UTINY *)0)
+ free(EM_pagemap_address);
+
+ EM_size = 0;
+
+ return(SUCCESS);
+
+
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_allocate_storage
+
+PURPOSE : allocates an area of memory of requested size, to be
+ used as a general data storage area. The area is
+ to zeros.
+
+RETURNED STATUS : storage_ID - (in this case a pointer)
+ NULL - failure to allocate enough space.
+
+
+DESCRIPTION : calloc is similar to malloc but returns memory
+ initialised to zeros.
+ The storage ID returned is a value used to later reference
+ the storage area allocated. The macro USEBLOCK in
+ "host_emm.h" is used by the manager routines to convert
+ this ID into a char pointer
+
+=========================================================================
+*/
+long host_allocate_storage(int no_bytes)
+
+/* IN int no_bytes no. of bytes required */
+
+{
+ return ((long)calloc(1, no_bytes));
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_free_storage
+
+PURPOSE : frees the area of memory that was used for
+ data storage
+
+
+RETURNED STATUS : SUCCESS - memory freed successfully
+ FAILURE - error ocurred in freeing memory
+
+DESCRIPTION : In this implementation storage_ID is simply a pointer
+
+
+=========================================================================
+*/
+int host_free_storage(long storage_ID)
+
+/* IN long storage_ID ptr to area of memory */
+
+{
+
+ if(storage_ID != (long) 0)
+ free((char *)storage_ID);
+
+ return(SUCCESS);
+
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_reallocate_storage
+
+PURPOSE : increases the size of memory allocated, maintaining the
+ contents of the original memory block
+
+
+RETURNED STATUS : storage_ID - memory reallocated successfully
+ NULL - error ocurred in reallocating memory
+
+DESCRIPTION : In this implementation storage_ID is simply a pointer
+ Note the value of storage_ID returned may or may not be the
+ same as the value given
+
+=========================================================================
+*/
+long host_reallocate_storage(long storage_ID, int size, int new_size)
+
+/* IN
+long storage_ID ptr to area of memory
+int size original size - not used in this version
+ new_size new size required
+*/
+{
+ return((long)realloc((char *)storage_ID, new_size));
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_map_page
+
+PURPOSE : produces mapping from an Expanded Memory page to a
+ page in Intel physical address space
+
+
+RETURNED STATUS : SUCCESS - mapping completed succesfully
+ FAILURE - error ocurred in mapping
+
+DESCRIPTION : Mapping achieved by simply copying data from the
+ expanded memory to Intel memory
+
+=========================================================================
+*/
+int host_map_page(short EM_page_no, unsigned short segment)
+
+/* IN
+short EM_page_no; Expanded Memory page to be mapped in
+unsigned short segment; segment in physical address space to
+ map into
+*/
+
+{
+ ULONG DosIntelPageNo, VdmIntelPageNo;
+ NTSTATUS Status;
+
+ DosIntelPageNo = SEGMENT_TO_INTEL_PAGE(segment);
+ VdmIntelPageNo = EMM_PAGE_TO_INTEL_PAGE(EM_page_no) +
+ EM_starting_page_no;
+
+
+ note_trace2(LIM_VERBOSE,"map page %d to segment 0x%4x", EM_page_no, segment);
+ Status = VdmMapDosMemory(DosIntelPageNo,
+ VdmIntelPageNo,
+ EMM_PAGE_SIZE / INTEL_PAGE_SIZE
+ );
+#ifdef EMM_DEBUG
+ printf("host_map_page, segment=%x, EMpage=%x, Dospage=%x, VdmPage=%x\n",
+ segment, EM_page_no, DosIntelPageNo, VdmIntelPageNo);
+#endif
+ if (NT_SUCCESS(Status)) {
+ return(SUCCESS);
+ }
+ else
+ return(FAILURE);
+
+
+}
+
+/*
+===========================================================================
+
+FUNCTION : host_unmap_page
+
+PURPOSE :unmaps pages from Intel physical address space to an
+ Expanded Memory page
+
+RETURNED STATUS : SUCCESS - unmapping completed succesfully
+ FAILURE - error ocurred in mapping
+
+DESCRIPTION : Unmapping achieved by simply copying data from Intel
+ memory to expanded memory
+
+=========================================================================
+*/
+int host_unmap_page(unsigned short segment, short EM_page_no)
+
+/* IN
+unsigned short segment segment in physical address space to
+ unmap
+short EM_page_no Expanded Memory page currently
+ mapped in
+*/
+
+{
+ ULONG DosIntelPageNo, VdmIntelPageNo;
+ NTSTATUS Status;
+
+ DosIntelPageNo = SEGMENT_TO_INTEL_PAGE(segment);
+ VdmIntelPageNo = EMM_PAGE_TO_INTEL_PAGE(EM_page_no) +
+ EM_starting_page_no;
+
+#ifdef EMM_DEBUG
+ printf("host_unmap_page, segment=%x, EMpage=%x, Dospage=%x, VdmPage=%x\n",
+ segment, EM_page_no, DosIntelPageNo, VdmIntelPageNo);
+#endif
+ Status = VdmUnmapDosMemory(DosIntelPageNo,
+ EMM_PAGE_SIZE / INTEL_PAGE_SIZE
+ );
+
+ note_trace2(LIM_VERBOSE,"unmap page %d from segment 0x%.4x\n",EM_page_no,segment);
+ if (NT_SUCCESS(Status))
+ return (SUCCESS);
+ else
+ return(FAILURE);
+
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_alloc_page
+
+PURPOSE : searches the pagemap looking for a free page, allocates
+ that page and returns the EM page no.
+
+RETURNED STATUS :
+ SUCCESS - Always see note below
+
+DESCRIPTION : Steps through the Expanded memory Pagemap looking for
+ a clear bit, which indicates a free page. When found,
+ sets that bit and returns the page number.
+ For access purposes the pagemap is divided into long
+ word(32bit) sections
+
+NOTE : The middle layer calling routine (alloc_page()) checks
+ that all pages have not been allocated and therefore in
+ this implementation the returned status will always be
+ SUCCESS.
+ However alloc_page still checks for a return status of
+ SUCCESS, as some implementations may wish to allocate pages
+ dynamically and that may fail.
+=========================================================================
+*/
+short host_alloc_page()
+
+{
+ short EM_page_no; /* page number returned */
+ long *ptr; /* ptr to 32 bit sections in */
+ /* pagemap */
+ short i; /* index into 32 bit section */
+
+ NTSTATUS status;
+
+ ptr = (long *)EM_pagemap_address;
+ i =0;
+ EM_page_no = 0;
+
+ while(*ptr & (MSB >> i++))
+ {
+ EM_page_no++;
+
+ if(i == 32)
+ /*
+ * start on next section
+ */
+ {
+ ptr++;
+ i = 0;
+ }
+ }
+ /*
+ * Set bit to show that page is allocated
+ */
+ *ptr = *ptr | (MSB >> --i);
+
+ /* commit memory to the page */
+ status = VdmCommitVirtualMemory(EM_PAGE_ADDRESS(EM_page_no),
+ EMM_PAGE_SIZE
+ );
+
+ if (!NT_SUCCESS(status))
+ return FAILURE;
+ return(EM_page_no);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_free_page
+
+PURPOSE : marks the page indicated as being free for further
+ allocation
+
+RETURNED STATUS :
+ SUCCESS - Always - see note below
+
+DESCRIPTION : clears the relevent bit in the pagemap.
+
+ For access purposes the pagemap is divided into long
+ word(32bit) sections.
+
+NOTE : The middle layer calling routine (free_page()) always
+ checks for invalid page numbers so in this implementation
+ the routine will always return SUCCESS.
+ However free_page() still checks for a return of SUCCESS
+ as other implementations may wish to use it.
+=========================================================================
+*/
+int host_free_page(short EM_page_no)
+
+/* IN short EM_page_no page number to be cleared */
+
+
+{
+ long *ptr; /* ptr to 32 bit sections in */
+ /* pagemap */
+ short i; /* index into 32 bit section */
+
+
+ NTSTATUS status;
+
+ status = VdmDeCommitVirtualMemory(EM_PAGE_ADDRESS(EM_page_no),
+ EMM_PAGE_SIZE
+ );
+
+ if (!NT_SUCCESS(status))
+ return FAILURE;
+ /*
+ * Set pointer to correct 32 bit section and index to correct bit
+ */
+
+ ptr = (long *)EM_pagemap_address;
+ ptr += (EM_page_no / 32);
+ i = EM_page_no % 32;
+
+ /*
+ * clear bit
+ */
+ *ptr = *ptr & ~(MSB >> i);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_copy routines
+ host_copy_con_to_con()
+ host_copy_con_to_EM()
+ host_copy_EM_to_con()
+ host_copy_EM_to_EM()
+
+PURPOSE : copies between conventional and expanded memory
+
+
+RETURNED STATUS :
+ SUCCESS - Always - see note below
+
+DESCRIPTION :
+ The middle layer calling routine always checks for a
+ return of SUCCESS as other implementations may
+ return FAILURE.
+=========================================================================
+*/
+int host_copy_con_to_con(int length, unsigned short src_seg,
+ unsigned short src_off, unsigned short dst_seg,
+ unsigned short dst_off)
+
+/* IN
+int length number of bytes to copy
+
+unsigned short src_seg source segment address
+ src_off source offset address
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ sys_addr from, to; /* pointers used for copying */
+
+ from = effective_addr(src_seg, src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_moves(from, to, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_con_to_EM(int length, unsigned short src_seg,
+ unsigned short src_off, unsigned short dst_page,
+ unsigned short dst_off)
+
+/* IN
+int length number of bytes to copy
+
+unsigned short src_seg source segment address
+ src_off source offset address
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ unsigned char *to; /* pointers used for copying */
+ sys_addr from;
+
+ from = effective_addr(src_seg, src_off);
+ to = EM_host_address(dst_page * EMM_PAGE_SIZE + dst_off);
+
+ EM_loads(from, to, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_EM_to_con(int length, unsigned short src_page,
+ unsigned short src_off, unsigned short dst_seg,
+ unsigned short dst_off)
+
+/* IN
+int length number of bytes to copy
+
+unsigned short src_page source page number
+ src_off source offset within page
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ unsigned char *from; /* pointers used for copying */
+ sys_addr to;
+
+ from = EM_host_address(src_page * EMM_PAGE_SIZE + src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_stores(to, from, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_EM_to_EM(int length, unsigned short src_page,
+ unsigned short src_off, unsigned short dst_page,
+ unsigned short dst_off)
+
+/* IN
+int length number of bytes to copy
+
+unsigned short src_page source page number
+ src_off source offset within page
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ unsigned char *from, *to; /* pointers used for copying */
+
+ from = EM_host_address(src_page * EMM_PAGE_SIZE + src_off);
+ to = EM_host_address(dst_page * EMM_PAGE_SIZE + dst_off);
+
+ EM_memcpy(to, from, length);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_exchange routines
+ host_exchg_con_to_con()
+ host_exchg_con_to_EM()
+ host_exchg_EM_to_EM()
+
+PURPOSE : exchanges data between conventional and expanded memory
+
+
+RETURNED STATUS :
+ SUCCESS - Everything ok
+ FAILURE - Memory allocation failure
+
+DESCRIPTION :
+
+=========================================================================
+*/
+int host_exchg_con_to_con(int length, unsigned short src_seg,
+ unsigned short src_off, unsigned short dst_seg,
+ unsigned short dst_off)
+
+/* IN
+int length number of bytes to copy
+
+unsigned short src_seg source segment address
+ src_off source offset address
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ unsigned char *temp, *pointer;/* pointers used for copying */
+ sys_addr to, from;
+
+ if ((temp = (unsigned char *)host_malloc(length)) == (unsigned char *)0)
+ return(FAILURE);
+
+ pointer = EM_pointer(temp, length);
+
+ from = effective_addr(src_seg, src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_loads(from, pointer, length); /* source -> temp */
+ EM_moves(to, from, length); /* dst -> source */
+ EM_stores(to, pointer, length); /* temp -> dst */
+
+ free(temp);
+
+ return(SUCCESS);
+}
+
+int host_exchg_con_to_EM(int length, unsigned short src_seg,
+ unsigned short src_off, unsigned short dst_page,
+ unsigned short dst_off)
+
+/* IN
+int length number of bytes to copy
+
+unsigned short src_seg source segment address
+ src_off source offset address
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ unsigned char *to, *temp, *pointer;/* pointers used for copying */
+ sys_addr from;
+
+ if ((temp = (unsigned char *)host_malloc(length)) == (unsigned char *)0)
+ return(FAILURE);
+
+ pointer = EM_pointer(temp, length);
+
+ from = effective_addr(src_seg, src_off);
+ to = EM_host_address(dst_page * EMM_PAGE_SIZE + dst_off);
+
+ EM_loads(from, pointer, length);
+ EM_stores(from, to, length);
+ EM_memcpy(to, pointer, length);
+
+ free(temp);
+
+ return(SUCCESS);
+}
+
+int host_exchg_EM_to_EM(int length, unsigned short src_page,
+ unsigned short src_off, unsigned short dst_page,
+ unsigned short dst_off)
+
+/* IN
+int length number of bytes to copy
+
+unsigned short src_page source page number
+ src_off source offset within page
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ unsigned char *from, *to, *temp, *pointer;
+ /* pointers used for copying */
+
+ if ((temp = (unsigned char *)host_malloc(length)) == (unsigned char *)0)
+ return(FAILURE);
+
+ pointer = EM_pointer(temp, length);
+
+ from = EM_host_address(src_page * EMM_PAGE_SIZE + src_off);
+ to = EM_host_address(dst_page * EMM_PAGE_SIZE + dst_off);
+
+ EM_memcpy(pointer, from, length);
+ EM_memcpy(from, to, length);
+ EM_memcpy(to, pointer, length);
+
+ free(temp);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_get_access_key
+
+PURPOSE : produces a random access key for use with LIM function 30
+ 'Enable/Disable OS/E Function Set Functions'
+
+RETURNED STATUS : none
+
+DESCRIPTION : Two 16 bit random values are required for the 'access key'
+ We use the microsecond field from the get time of day routine
+ to provide this.
+
+=========================================================================
+*/
+void host_get_access_key(unsigned short access_key[2])
+
+/* OUT unsigned short access_key[2] source segment address */
+
+{
+ struct host_timeval time; /* structure for holding time */
+
+ host_GetSysTime(&time);
+
+ access_key[0] = time.tv_usec & 0xffff;
+ access_key[1] = (time.tv_usec >> 3) & 0xffff;
+
+ return;
+}
+
+#endif /* MONITOR */
+
+#endif /* LIM */
diff --git a/private/mvdm/softpc.new/host/src/nt_eoi.c b/private/mvdm/softpc.new/host/src/nt_eoi.c
new file mode 100644
index 000000000..05653c2d5
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_eoi.c
@@ -0,0 +1,545 @@
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : Host EOI hook controller
+ *
+ * Description : This module handles host specific ica code
+ * - EOI hook
+ * - ICA lock
+ *
+ * Author : D.A.Bartlett
+ *
+ * Notes : 30-Oct-1993 Jonle , Rewrote it
+ */
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */
+
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntexapi.h>
+#include <windows.h>
+#include <stdio.h>
+#include <vdm.h>
+#include "insignia.h"
+#include "host_def.h"
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "quick_ev.h"
+#include "ica.h"
+#include "host_rrr.h"
+#include "error.h"
+#include "nt_uis.h"
+#include "nt_reset.h"
+#include "nt_eoi.h"
+
+// from monitor.lib
+HANDLE ThreadLookUp(PVOID);
+extern PVOID CurrentMonitorTeb;
+
+// from nt_timer.c
+extern ULONG GetPerfCounter(VOID);
+
+
+RTL_CRITICAL_SECTION IcaLock; // ICA critical section lock
+ULONG UndelayIrqLine=0;
+ULONG DelayIrqLine=0xffffffff; // all ints are blocked until, spckbd loaded
+
+#ifdef MONITOR
+ULONG iretHookActive=0;
+ULONG iretHookMask =0;
+ULONG AddrIretBopTable=0; // seg:offset
+#endif
+
+HANDLE hWowIdleEvent = INVALID_HANDLE_VALUE;
+
+/*
+ * EOI defines, types, global data
+ *
+ */
+static EOIHOOKPROC EoiHooks[16]={NULL}; // must be init to NULL
+
+
+#ifndef MONITOR
+void DelayIrqQuickEvent(long param);
+q_ev_handle DelayHandle[16];
+#define pNtVDMState ((PULONG)(Start_of_M_area + FIXED_NTVDMSTATE_LINEAR))
+
+LARGE_INTEGER BlockTime = {0,0};
+extern LARGE_INTEGER CurrHeartBeat;
+void host_TimeStamp(PLARGE_INTEGER pliTime);
+#endif
+
+
+/*
+ * Called by wow32 to fetch the hWowIdleEvent, which wowexec waits on
+ * in the wow nonpreemptive scheduler.
+ */
+HANDLE RegisterWOWIdle(VOID)
+{
+ return hWowIdleEvent;
+}
+
+/*
+ * Called by WOW32 to inform the WOW idle code that the current WOW
+ * task may be scheduled\descheduled.
+ */
+
+void
+BlockWOWIdle(
+ BOOL Blocking
+ )
+{
+ host_ica_lock();
+
+ if (Blocking) {
+ *pNtVDMState |= VDM_WOWBLOCKED;
+
+#ifndef MONITOR
+ BlockTime = CurrHeartBeat;
+#endif
+
+ }
+ else {
+ *pNtVDMState &= ~VDM_WOWBLOCKED;
+
+
+
+#ifndef MONITOR
+ if (BlockTime.QuadPart &&
+ (CurrHeartBeat.QuadPart >= BlockTime.QuadPart + SYSTEM_TICK_INTV/2))
+ {
+ BlockTime.QuadPart = 0;
+ host_ica_unlock();
+
+ ActivityCheckAfterTimeSlice();
+ return;
+ }
+#endif
+ }
+
+ host_ica_unlock();
+}
+
+
+
+/*
+ * (WOWIdle)...check if an app requires hw interrupts servicing but all WOW
+ * threads are blocked. If so then the call will cause wowexec to awaken
+ * to handle them. Called from ica interrupt routines. NB. Default action
+ * of routine is to check state and return as fast as possible.
+ */
+void
+WOWIdle(
+ BOOL Force
+ )
+{
+ if (VDMForWOW && (Force || (*pNtVDMState & VDM_WOWBLOCKED))) {
+ SetEvent(hWowIdleEvent);
+ }
+
+}
+
+
+
+
+/* RegisterEoiHook
+ *
+ * Registers an call back function to be invoked upon eoi of
+ * a hardware interrupt.
+ *
+ * entry: IrqLine - IrqNumber to register
+ * EoiHookProc - function pointer to be called upon eoi
+ *
+ * returns FALSE if the the IrqLine already has an eoi hook registered
+ */
+BOOL RegisterEOIHook(int IrqLine, EOIHOOKPROC EoiHookProc)
+{
+
+ if (!EoiHooks[IrqLine]) {
+ EoiHooks[IrqLine] = EoiHookProc;
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+
+
+/* RemoveEOIHook
+ *
+ * entry: IrqLine - IrqNumber to remove
+ * EoiHookProc - function pointer previously registered
+ */
+BOOL RemoveEOIHook(int IrqLine, EOIHOOKPROC EoiHookProc)
+{
+ if (EoiHooks[IrqLine] == EoiHookProc) {
+ EoiHooks[IrqLine] = NULL;
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+
+
+/* host_EOI_hook
+ *
+ * base callback function to invoke device specific Eoi Hook routines
+ *
+ * Entry: IrqLine - Line number
+ * CallCount - The ica Call count for this Irq
+ * If the Call count is -1 then a pending
+ * interrupt is being canceled.
+ *
+ */
+VOID host_EOI_hook(int IrqLine, int CallCount)
+{
+ if ((ULONG)IrqLine >= sizeof(EoiHooks)/sizeof(EOIHOOKPROC)) {
+#if DBG
+ DbgPrint("ntvdm.Eoi_hook: Invalid IrqLine=%lx\n", (ULONG)IrqLine);
+#endif
+ return;
+ }
+
+ if (EoiHooks[IrqLine]) {
+ (*EoiHooks[IrqLine])(IrqLine, CallCount);
+ }
+}
+
+
+/* host_DelayHwInterrupt
+ *
+ * base callback function to queue a HW interrupt at a later time
+ *
+ * entry: IrqLineNum - Irq Line Number
+ * CallCount - Number of interrupts, May be Zero
+ * Delay - Delay time in usecs
+ * if Delay is 0xFFFFFFFF then per IrqLine data
+ * structures are freed, use for cleanup when
+ * the IrqLine is no longer needed for DelayedInterrupts
+ *
+ * Notes: The expected granularity is around 1 msec, but varies depending
+ * on the platform.
+ *
+ *
+ */
+BOOL host_DelayHwInterrupt(int IrqLineNum, int CallCount, ULONG Delay)
+{
+ int adapter;
+ ULONG IrqLine;
+
+#ifdef MONITOR
+ NTSTATUS status;
+ VDMDELAYINTSDATA DelayIntsData;
+#else
+ ULONG TicCount;
+#endif
+
+ host_ica_lock();
+
+ //
+ // Anything to do (only one delayed Irql at a time)
+ //
+
+ IrqLine = 1 << IrqLineNum;
+ if (!(DelayIrqLine & IrqLine) || Delay == 0xffffffff) {
+
+ //
+ // force a minimum delay of 1 ms
+ //
+ if (Delay < 1000) {
+ Delay = 1000;
+ }
+
+#ifdef MONITOR
+
+ //
+ // Set Kernel timer for this IrqLine
+ //
+ DelayIntsData.Delay = Delay;
+ DelayIntsData.DelayIrqLine = IrqLineNum;
+ DelayIntsData.hThread = ThreadLookUp(CurrentMonitorTeb);
+ if (DelayIntsData.hThread) {
+ status = NtVdmControl(VdmDelayInterrupt, &DelayIntsData);
+ if (!NT_SUCCESS(status)) {
+#if DBG
+ DbgPrint("NtVdmControl.VdmDelayInterrupt status=%lx\n",status);
+#endif
+ host_ica_unlock();
+ return FALSE;
+ }
+
+ }
+
+#else
+
+ //
+ // Cancel delay hw interrupt, delete quick event if any
+ //
+ if (Delay == 0xFFFFFFFF) {
+ if (DelayHandle[IrqLineNum]) {
+ delete_q_event(DelayHandle[IrqLineNum]);
+ DelayIrqLine &= ~IrqLine;
+ DelayHandle[IrqLineNum] = 0;
+ }
+ host_ica_unlock();
+ return TRUE;
+ }
+
+
+ //
+ // Mark The IrqLine as delayed until timer fires and queue a quick
+ // event, (a bit early for overhead in dispatching quick events).
+ //
+ DelayIrqLine |= IrqLine;
+ DelayHandle[IrqLineNum] = add_q_event_i(DelayIrqQuickEvent,
+ Delay - 200,
+ IrqLineNum
+ );
+
+ //
+ // Keep Wow Tasks active
+ //
+ WOWIdle(TRUE);
+
+
+
+#endif
+ }
+
+
+ //
+ // If we have more interrupts to generate, register them
+ //
+ if (CallCount) {
+ adapter = IrqLineNum >> 3;
+ ica_hw_interrupt(adapter,
+ (UCHAR)(IrqLineNum - (adapter << 3)),
+ CallCount
+ );
+ }
+
+
+ host_ica_unlock();
+ return TRUE;
+}
+
+
+
+#ifndef MONITOR
+/*
+ * QuickEvent call back function
+ *
+ */
+void DelayIrqQuickEvent(long param)
+{
+ ULONG IrqLineNum = param;
+
+ host_ica_lock();
+
+ DelayHandle[IrqLineNum] = 0;
+ ica_RestartInterrupts(1 << IrqLineNum);
+
+ host_ica_unlock();
+
+}
+#endif
+
+
+
+// ICA critical section locking code
+// This is needed to control access to the ICA from different threads.
+
+void host_ica_lock(void)
+{
+ RtlEnterCriticalSection(&IcaLock);
+}
+
+void host_ica_unlock(void)
+{
+ RtlLeaveCriticalSection(&IcaLock);
+}
+
+void InitializeIcaLock(void)
+{
+ RtlInitializeCriticalSection(&IcaLock);
+
+
+ if (VDMForWOW) {
+ if(!(hWowIdleEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ TerminateVDM();
+ }
+ }
+}
+
+
+
+#ifdef MONITOR
+//
+// Force creation of the LazyCreate LockSemaphore
+// for the ica lock.
+// It is assumed that:
+// the cpu thread Owns the critsect
+// the HeartBeat Thread will wait on the critsect creating contention
+//
+// This is done by polling for a lock count greater than zero
+// and verifying that the lock semaphore has been created.
+// If these conditions are not met we will end up polling infinitely.
+// Sounds dangerous but it is okay, since we will either get a
+// CreateSemaphore or a timeout(deadlock) error from the rtl critical
+// section code, which will result in an exception.
+//
+VOID WaitIcaLockFullyInitialized(VOID)
+{
+ DWORD Delay = 0;
+
+ do {
+ Sleep(Delay++);
+ } while (IcaLock.LockCount < 1 || !IcaLock.LockSemaphore);
+}
+#endif
+
+
+
+// The following routines are used to support IRET hooks. If an interrupt
+// uses an IRET hook then the ICA will not generate a interrupt of that
+// type until the IRET hook has been called.
+
+
+// Exported for vdmredir
+
+void SoftPcEoi(int Adapter, int* Line) {
+ ica_eoi(Adapter, Line, 0);
+}
+
+
+
+
+//
+// Restart delayed interrupts
+// IcaLock should be held upon entry
+//
+
+BOOL ica_restart_interrupts(int adapter)
+{
+ int i;
+
+ if((i = ica_scan_irr(adapter)) & 0x80) {
+ ica_interrupt_cpu(adapter, i &= 0x07);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+//New ICA interrupt state reset function
+
+void ica_reset_interrupt_state(void)
+{
+ int line_no;
+
+ host_ica_lock();
+
+ for(line_no = 0; line_no < 8; line_no++) {
+ VirtualIca[ICA_MASTER].ica_count[line_no] =
+ VirtualIca[ICA_SLAVE].ica_count[line_no] = 0;
+ ica_clear_int(ICA_MASTER,line_no);
+ ica_clear_int(ICA_SLAVE,line_no);
+ }
+
+
+ //Clear interrupt counters
+ VirtualIca[ICA_MASTER].ica_cpu_int =
+ VirtualIca[ICA_SLAVE].ica_cpu_int = FALSE;
+
+#ifdef MONITOR
+ iretHookActive = 0;
+#endif
+ DelayIrqLine = 0;
+
+ //Tell CPU to remove any pending interrupts
+ host_clear_hw_int();
+
+ host_ica_unlock();
+}
+
+
+/*
+ * Handle callout from DPMI to say that an app has asked DPMI to switch it
+ * to protected mode. We use this as an indicator that a protected mode app
+ * will work with the Iret Hook system. If an app does it's own thing with
+ * selectors et al, the BOP table will be hidden, swallowed and generally
+ * lost. Attempts then to transfer control to it will fault.
+ * Known examples of such unfriendliness are the DOS Lotus 123 r3 series.
+ */
+VOID EnableEmulatorIretHooks(void)
+{
+ ; // obsolete
+}
+
+/*
+ * The app is closing - turn off the Iret Hooks in case the next app is
+ * iret hook unfriendly. If it's a friendly app, we'll be called again
+ * via the Enable... routine above.
+ */
+VOID DisableEmulatorIretHooks(void)
+{
+ ; // obsolete
+}
+
+//
+// Retry DelayInts (not iret hooks!)
+//
+// IrqLine - IrqLineBitMask, to be cleared
+//
+VOID ica_RestartInterrupts(ULONG IrqLine)
+{
+#ifdef MONITOR
+
+ //
+ // on x86 we may get multiple bits set
+ // so check both slave and master
+ //
+ UndelayIrqLine = 0;
+
+ if (!ica_restart_interrupts(ICA_SLAVE))
+ ica_restart_interrupts(ICA_MASTER);
+#else
+ host_ica_lock();
+
+ DelayIrqLine &= ~IrqLine;
+
+ ica_restart_interrupts(IrqLine >> 3 ? ICA_SLAVE : ICA_MASTER);
+
+ host_ica_unlock();
+#endif
+}
+
+#ifdef MONITOR
+extern IU16 getMSW(void);
+
+IU32 host_iret_bop_table_addr(IU32 line)
+{
+ ULONG AddrBopTable, IretBopSize;
+
+ ASSERT(line <= 15);
+
+ if (!(iretHookMask & (1 << line))) {
+ return 0;
+ }
+
+ if (getMSW() & 1) {
+ AddrBopTable = (VDM_PM_IRETBOPSEG << 16) | VDM_PM_IRETBOPOFF;
+ IretBopSize = VDM_PM_IRETBOPSIZE;
+ }
+ else {
+ AddrBopTable = AddrIretBopTable;
+ IretBopSize = VDM_RM_IRETBOPSIZE;
+ }
+ return AddrBopTable + IretBopSize * line;
+
+}
+#endif /* MONITOR */
diff --git a/private/mvdm/softpc.new/host/src/nt_error.c b/private/mvdm/softpc.new/host/src/nt_error.c
new file mode 100644
index 000000000..9f8757655
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_error.c
@@ -0,0 +1,1190 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntstatus.h>
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <conapi.h>
+#include "insignia.h"
+#include "host_def.h"
+/*
+ * SoftPC Revision 2.0
+ *
+ * Title : General Error Handler
+ *
+ * Description : General purpose error handler. It handles both
+ * general SoftPC errors (error numbers 0 - 999) and
+ * host specific errors (error numbers >= 1000)
+ *
+ * Author(s) : Dave Bartlett (based on module by John Shanly)
+ *
+ * Parameters : int used to index an array of error messages
+ * held in message.c, and a bit mask indicating
+ * the user's possible options:
+ * Quit, Reset, Continue, Setup
+ *
+ */
+
+
+#include <sys/types.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdio.h>
+
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "bios.h"
+#include "ios.h"
+#include "gvi.h"
+#include "error.h"
+#include "config.h"
+#include "dterm.h"
+#include "host_rrr.h"
+#include "host_nls.h"
+
+#include "nt_graph.h"
+#include "nt_uis.h"
+#include "nt_reset.h"
+#include "ckmalloc.h"
+
+#include "trace.h"
+#include "nt_event.h"
+
+
+
+extern VOID (*pW32HungAppNotifyThread)(UINT);
+int error_window_options = 0;
+
+VOID SuspendTimerThread(VOID);
+VOID ResumeTimerThread(VOID);
+
+
+/*::::::::::::::::::::::::::::::::: Internally used variables and functions */
+
+typedef struct _ErrorDialogBoxInfo{
+ DWORD dwOptions;
+ DWORD dwReply;
+ HWND hWndCon;
+ char *message;
+ char *pEdit;
+ char Title[MAX_PATH];
+ }ERRORDIALOGINFO, *PERRORDIALOGINFO;
+
+char achPERIOD[]=". ";
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: STDOUT macro */
+
+#define ERRORMSG OutputDebugString
+#define HIDEDLGITM(d,b) ShowWindow(GetDlgItem(d,b),SW_HIDE);
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+int ErrorDialogBox(char *message, char *Edit, DWORD dwOptions);
+DWORD ErrorDialogBoxThread(VOID *pv);
+int WowErrorDialogEvents(ERRORDIALOGINFO *pedgi);
+LONG APIENTRY ErrorDialogEvents(HWND hDlg,WORD wMsg,LONG wParam,LONG lParam);
+void SwpButtons(HWND hDlg, DWORD dwOptions);
+void SwpDosDialogs(HWND hDlg, HWND hWndCon,HWND SwpInsert, UINT SwpFlags);
+DWORD OemMessageToAnsiMessage(CHAR *, CHAR *);
+DWORD AnsiMessageToOemMessage(CHAR *pBuff, CHAR *pMsg);
+ULONG WOWpSysErrorBox(LPSTR,LPSTR,USHORT,USHORT,USHORT);
+
+
+#ifndef MONITOR
+
+ /*
+ * Do things the old fashioned way for some of the cpu building tools
+ * which cannot be changed to match our host
+ */
+
+
+#ifdef host_error_ext
+#undef host_error_ext
+#endif
+SHORT host_error_ext(int error_num, int options, ErrDataPtr data)
+{
+ return host_error(error_num, options, NULL);
+}
+
+#ifdef host_error
+#undef host_error
+#endif
+SHORT host_error(int error_num, int options, char *extra_char);
+
+#ifdef host_error_conf
+#undef host_error_conf
+#endif
+SHORT host_error_conf(int config_panel, int error_num, int options,
+ char *extra_char)
+{
+ return host_error(error_num, options, extra_char);
+}
+
+ERRORFUNCS nt_error_funcs = { host_error_conf,host_error,host_error_ext};
+ERRORFUNCS *working_error_funcs = &nt_error_funcs;
+#endif
+
+
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Display error, terminate ::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+int DisplayErrorTerm(int ErrorNo, /* Softpc Error number */
+ DWORD OSErrno, /* OS Error number */
+ char *Filename, /* File name of file containing err */
+ int Lineno) /* LIne number of error */
+{
+ char Msg[EHS_MSG_LEN];
+ DWORD errno, len;
+
+ UNUSED(ErrorNo); //Always internal error
+
+#ifndef PROD
+ sprintf(Msg,"NTVDM:ErrNo %#x, %s:%d\n", OSErrno, Filename, Lineno);
+ OutputDebugString(Msg);
+#endif
+
+ // assume NT error if either of top two bits set (err or warning).
+ // this means we'll confuse some of the lesser NT errors but we get a
+ // second chance if the mapping fails.
+ if (OSErrno & 0xc0000000)
+ errno = RtlNtStatusToDosError(OSErrno);
+ else
+ errno = OSErrno;
+
+ // Now get message from system
+ len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ errno,
+ 0,
+ Msg,
+ EHS_MSG_LEN,
+ NULL
+ );
+ if (!len) {
+ sprintf(Msg, "%s %lxh", szSysErrMsg, OSErrno);
+ }
+
+ return(host_error(EHS_SYSTEM_ERROR, ERR_QUIT, Msg));
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::: Display host error ::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+SHORT host_error(int error_num, int options, char *extra_char)
+{
+ char message[EHS_MSG_LEN];
+
+ host_nls_get_msg(error_num, message, EHS_MSG_LEN);
+
+ if (extra_char && *extra_char) {
+ strcat(message,"\n");
+ strcat(message,extra_char);
+ }
+
+
+#ifndef PROD
+ OutputDebugString(message);
+ if (extra_char) {
+ OutputDebugString("\n");
+ }
+#endif
+
+ ErrorDialogBox(message, NULL, RMB_ICON_STOP | RMB_ABORT | RMB_IGNORE);
+
+ return ERR_CONT;
+}
+
+
+DWORD TlsDirectError;
+//
+// Called directly from C or via bop. Type checked against global 'DirectError'
+// to see if called already in this app. 'DirectError' cleared on VDM resume.
+//
+// This function is expected to be called by 16 bit threads
+// which is doing the unsupported service. For DosApps this is
+// the CPU thread, For WOW this is one of the individual 16 bit tasks.
+//
+//
+VOID host_direct_access_error(ULONG type)
+{
+ CHAR message[EHS_MSG_LEN];
+ CHAR acctype[EHS_MSG_LEN];
+ CHAR dames[EHS_MSG_LEN];
+ DWORD dwDirectError;
+
+
+ /*
+ * Get the direct error record for the current thread
+ * if TlsGetValue returns NULL
+ * - could be invalid index (TlsAlloc failed)
+ * - actual value is 0, (no bits set)
+ * In both cases we will go ahead with the popup
+ */
+ dwDirectError = (DWORD)TlsGetValue(TlsDirectError);
+
+ // don't annoy user with repeated popups
+ if ((dwDirectError & (1<<type)) != 0)
+ return;
+
+ TlsSetValue(TlsDirectError, (LPVOID)(dwDirectError | (1 << type)));
+
+ if (LoadString(GetModuleHandle(NULL), D_A_MESS,
+ dames, sizeof(dames)/sizeof(CHAR)) &&
+ LoadString(GetModuleHandle(NULL), D_A_MESS + type + 1,
+ acctype, sizeof(acctype)/sizeof(CHAR)) )
+ {
+ sprintf(message, dames, acctype);
+ }
+ else {
+ strcpy(message, szDoomMsg);
+ }
+
+
+ ErrorDialogBox(message, NULL, RMB_ICON_STOP | RMB_ABORT | RMB_IGNORE);
+}
+
+
+/*
+ * RcErrorDialogBox
+ *
+ * Displays standard dialog Box for errors and warnings
+ * Looks up the error message from ntvdm's reource string table
+ *
+ * entry: UINT wId - string table resource index
+ * CHAR *msg1 - Optional OEM strings which are displayed
+ * CHAR *msg2 before the main error message. Each string
+ * is limited to MAX_PATH inclusive of NULL,
+ * (auto-truncate).
+ *
+ * exit:
+ *
+ */
+void RcErrorDialogBox(UINT wId, CHAR *msg1, CHAR *msg2)
+{
+ DWORD dw, dwTotal;
+ CHAR ErrMsg[MAX_PATH*4];
+
+ dwTotal = 0;
+ dw = OemMessageToAnsiMessage(ErrMsg, msg1);
+ if (dw) {
+ dwTotal += dw;
+ strcpy(&ErrMsg[dwTotal], achPERIOD);
+ dwTotal += sizeof(achPERIOD) - 1;
+ }
+
+ dw = OemMessageToAnsiMessage(&ErrMsg[dwTotal], msg2);
+ if (dw) {
+ dwTotal += dw;
+ strcpy(&ErrMsg[dwTotal], achPERIOD);
+ dwTotal += sizeof(achPERIOD) - 1;
+ }
+
+ if (!LoadString(GetModuleHandle(NULL), wId, &ErrMsg[dwTotal], MAX_PATH))
+ {
+ strcpy(ErrMsg, szDoomMsg);
+ }
+
+ ErrorDialogBox(ErrMsg, NULL, RMB_ICON_STOP | RMB_ABORT | RMB_IGNORE);
+}
+
+
+
+/*
+ * RcMessageBox
+ *
+ * Displays standard dialog Box for errors and warnings
+ * Looks up the error message from ntvdm's reource string table
+ *
+ * Optionally shows an edit dialog control. The edit control
+ * is placed just below the first line of the message text,
+ * leaving only enuf space to display a one line message.
+ *
+ * entry: UINT wId - string table resource index
+ * CHAR *msg1 - Optional OEM strings which are displayed
+ * CHAR *msg2 before the main error message. Each string
+ * is limited to MAX_PATH inclusive of NULL,
+ * (auto-truncate).
+ *
+ * If RMB_EDIT is specified msg2 is NOT used for messages
+ * to be displayed, rather is used for the default string for the
+ * edit control. The hiword of dwOPtions is used as max size of
+ * edit buffer, and must be less than MAX_PATH
+ *
+ * DWORD dwOptions - accepts
+ * RMB_ABORT
+ * RMB_RETRY
+ * RMB_IGNORE msg box equivalent
+ * RMB_ICON_INFO - IDI_ASTERICK
+ * RMB_ICON_BANG - IDI_EXCLAMATION
+ * RMB_ICON_STOP - IDI_HAND
+ * RMB_ICON_WHAT - IDI_QUESTION
+ * RMB_EDIT - edit dialog control
+ *
+ * exit: returns RMB_ABORT RMB_RETRY RMB_IGNORE RMB_EDIT
+ * If RMB_EDIT is specified msg2 is used to return
+ * the contents of the edit control
+ *
+ */
+int RcMessageBox(UINT wId, CHAR *msg1, CHAR *msg2, DWORD dwOptions)
+
+{
+ DWORD dw, dwTotal;
+ char *pEdit;
+ CHAR ErrMsg[MAX_PATH*4];
+ CHAR Edit[MAX_PATH];
+ int i;
+
+ dwTotal = 0;
+ dw = OemMessageToAnsiMessage(ErrMsg, msg1);
+ if (dw) {
+ dwTotal += dw;
+ strcpy(&ErrMsg[dwTotal], achPERIOD);
+ dwTotal += sizeof(achPERIOD) - 1;
+ }
+
+ if (dwOptions & RMB_EDIT) {
+ dw = OemMessageToAnsiMessage(Edit, msg2);
+ pEdit = Edit;
+ }
+ else {
+ dw = OemMessageToAnsiMessage(&ErrMsg[dwTotal], msg2);
+ if (dw) {
+ dwTotal += dw;
+ strcpy(&ErrMsg[dwTotal], achPERIOD);
+ dwTotal += sizeof(achPERIOD) - 1;
+ }
+ pEdit = NULL;
+ }
+
+ if (!LoadString(GetModuleHandle(NULL), wId, &ErrMsg[dwTotal], MAX_PATH))
+ {
+ strcpy(ErrMsg, szDoomMsg);
+ }
+
+ i = ErrorDialogBox(ErrMsg, pEdit, dwOptions);
+
+ if (pEdit) {
+ AnsiMessageToOemMessage(msg2, pEdit);
+ }
+
+ return i;
+}
+
+
+
+/*
+ * AnsiMessageToOemMessage
+ *
+ * converts string messages from ansi to oem strings, for display output
+ *
+ * entry: CHAR *msg
+ * Each string is limited to MAX_PATH inclusive of NULL,
+ * (auto-truncate).
+ *
+ * CHAR *pBuff - destination buffer, must be at least MAX_PATH
+ *
+ * exit: returns string len
+ */
+DWORD AnsiMessageToOemMessage(CHAR *pBuff, CHAR *pMsg)
+{
+ PUNICODE_STRING pUnicode;
+ ANSI_STRING AnsiString;
+ OEM_STRING OemString;
+
+ if (!pBuff)
+ return 0;
+
+ if (!pMsg || !*pMsg) {
+ *pBuff = '\0';
+ return 0;
+ }
+
+ RtlInitString(&AnsiString, pMsg);
+ if (AnsiString.Length > MAX_PATH) {
+ AnsiString.Length = MAX_PATH-1;
+ AnsiString.MaximumLength = MAX_PATH;
+ }
+
+ OemString.MaximumLength = AnsiString.MaximumLength;
+ OemString.Buffer = pBuff;
+ *(OemString.Buffer+AnsiString.Length) = '\0';
+ pUnicode = &NtCurrentTeb()->StaticUnicodeString;
+ if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(pUnicode,
+ &AnsiString,
+ FALSE)) ||
+ !NT_SUCCESS(RtlUnicodeStringToOemString((POEM_STRING)&OemString,
+ pUnicode,
+ FALSE)) )
+ {
+ OemString.Length = 0;
+ }
+
+ return OemString.Length;
+}
+
+
+/*
+ * OemMessageToAnsiMessage
+ *
+ * converts string messages from oem to ansi strings, for display output
+ *
+ * entry: CHAR *msg
+ * Each string is limited to MAX_PATH inclusive of NULL,
+ * (auto-truncate).
+ *
+ * CHAR *pBuff - destination buffer, must be at least MAX_PATH
+ *
+ * exit: returns string len
+ */
+DWORD OemMessageToAnsiMessage(CHAR *pBuff, CHAR *pMsg)
+{
+ PUNICODE_STRING pUnicode;
+ ANSI_STRING AnsiString;
+ OEM_STRING OemString;
+
+ if (!pBuff)
+ return 0;
+
+ if (!pMsg || !*pMsg) {
+ *pBuff = '\0';
+ return 0;
+ }
+
+ RtlInitString(&OemString, pMsg);
+ if (OemString.Length > MAX_PATH) {
+ OemString.Length = MAX_PATH-1;
+ OemString.MaximumLength = MAX_PATH;
+ }
+ AnsiString.MaximumLength = OemString.MaximumLength;
+ AnsiString.Buffer = pBuff;
+ *(AnsiString.Buffer+OemString.Length) = '\0';
+ pUnicode = &NtCurrentTeb()->StaticUnicodeString;
+ if (!NT_SUCCESS(RtlOemStringToUnicodeString(pUnicode,
+ &OemString,
+ FALSE)) ||
+ !NT_SUCCESS(RtlUnicodeStringToAnsiString((POEM_STRING)&AnsiString,
+ pUnicode,
+ FALSE)) )
+ {
+ AnsiString.Length = 0;
+ }
+
+ return AnsiString.Length;
+}
+
+
+/*
+ * Thread call back function for EnumThreadWindows
+ * entry: HWND hWnd - window handle to verify
+ * LPARAM lParam - address of edgi->hWnd == ThreadID
+ *
+ * exit: TRUE - to continue enumeration
+ * FALSE - edgi->hWnd has window handle for TopLevelWindow of thread
+ *
+ */
+BOOL CALLBACK GetThreadTopLevelWindow(HWND hWnd, LPARAM lParam)
+{
+ PDWORD pdw = (PDWORD)lParam;
+
+ if (GetWindowThreadProcessId(hWnd, NULL) == *pdw)
+ {
+ *pdw = (DWORD)hWnd;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/* ErrorDialogBox
+ *
+ * Displays standard dialog Box for errors and warnings
+ *
+ */
+int ErrorDialogBox(char *message, char *pEdit, DWORD dwOptions)
+{
+ static BOOL bCalled=0;
+ HANDLE hThread = NULL;
+ HWND hWndApp;
+ DWORD dwThreadID, dw;
+ ERRORDIALOGINFO edgi;
+
+
+ if (bCalled) { // recursive call, so stop annoying the user
+ return RMB_IGNORE;
+ }
+ bCalled++;
+
+
+ /* Raid HotFix 3381 - alpha stress hang. All RISC implementations.
+ * If we leave the heartbeat generating timer hardware interrupts
+ * all of the time, we will continually add quick events which
+ * don't go off until the popup is dismissed. This will suck up
+ * local heap and CPU at a hipriority.
+ */
+ SuspendTimerThread();
+
+ // init err dialog info
+ edgi.message = message;
+ edgi.dwReply = 0;
+ edgi.hWndCon = hWndConsole;
+ edgi.dwOptions = dwOptions;
+ edgi.pEdit = pEdit;
+
+ // get window handle for the offending app
+ if (VDMForWOW) {
+ hWndApp = (HWND)GetCurrentThreadId();
+ EnumWindows((WNDENUMPROC)GetThreadTopLevelWindow,(LPARAM)&hWndApp);
+ if (hWndApp == (HWND)GetCurrentThreadId()) {
+ hWndApp = HWND_DESKTOP;
+ }
+ }
+ else {
+ hWndApp = edgi.hWndCon;
+ }
+
+ //
+ // get title of app, using DefWindowProc in lieu of
+ // GetWindowText to avoid callbacks into threads window proc
+ //
+ if (hWndApp == HWND_DESKTOP ||
+ !DefWindowProc(hWndApp, WM_GETTEXT,
+ (WPARAM) (sizeof(edgi.Title)-1),
+ (LPARAM) edgi.Title) )
+ {
+ edgi.Title[0] = '\0';
+ }
+
+
+ //
+ // spin off a separate thread, why ?
+ // For DOS, to avoid suspended threads during full screen switching
+ // For Wow required for task termination if user chooses terminate.
+ //
+ dw = 5;
+ do {
+ hThread = CreateThread(NULL, // security
+ 0, // stack size
+ ErrorDialogBoxThread, // start address
+ &edgi, // thread argument
+ 0, // flags
+ &dwThreadID // gets thread ID
+ );
+ if (hThread)
+ break;
+ else
+ Sleep(2000);
+ } while (dw--);
+
+ if (hThread) {
+ do {
+ dw = WaitForSingleObject(hThread, 1000);
+ } while (dw == WAIT_TIMEOUT && !edgi.dwReply);
+ CloseHandle(hThread);
+ ResumeTimerThread();
+
+
+ if (edgi.dwReply == RMB_ABORT)
+ //
+ // The wow termination will occur via the ErrorDialogBoxThread
+ // as it calls the HungAppNotifyThread. Befotrewe return give
+ // wow a chance to set up for termination.
+ //
+ if (VDMForWOW) {
+ Sleep(10);
+ }
+
+ //
+ // If a dos app terminate now!
+ //
+ else {
+ TerminateVDM();
+ }
+ }
+
+ else {
+#ifndef PROD
+ printf("CreateThread(ErrorDialogBoxThread) GLE=%d\n", GetLastError());
+ printf("NTVDM:<%s>\n<%s>\n", edgi.Title, edgi.message );
+ HostDebugBreak();
+#endif
+ ResumeTimerThread();
+
+ //
+ // If we can't create a thread, we are in a pretty bad way
+ // wow: ignore error, since not alllowed to kill WOW ssystem
+ // dos: terminate the VDM
+ //
+ if (!VDMForWOW)
+ TerminateVDM();
+ }
+
+ bCalled--;
+ return (int) edgi.dwReply;
+}
+
+
+
+
+
+/* ErrorDialogBoxThread
+ *
+ * Worker routine for ErrorDialogBox. In WOW VDMs this function is
+ * run as its own thread. For other VDMs it is called directly.
+ *
+ * WOW: If the user chooses terminate, it will not return.
+ *
+ * exit: fills in pedgi.dwReply with ret code from DialogBoxParam
+ * IDB_QUIT, IDB_CONTINUE
+ */
+DWORD ErrorDialogBoxThread(VOID *pv)
+{
+ int i;
+ ERRORDIALOGINFO *pedgi = pv;
+ char *pch;
+ char *pLast;
+
+
+ // skip leading white space
+ pch = pedgi->Title;
+ while (*pch && !isgraph(*pch)) {
+ pch++;
+ }
+
+ // move string to beg of buffer, strip trailing white space
+ i = 0;
+ pLast = pedgi->Title;
+ while (*pch) {
+ pedgi->Title[i++] = *pch;
+ if (isgraph(*pch)) {
+ pLast = &pedgi->Title[i];
+ }
+ pch++;
+ }
+ *pLast = '\0';
+
+
+ if (VDMForWOW) {
+ i = WowErrorDialogEvents(pedgi);
+ }
+ else {
+ if (pedgi->hWndCon != HWND_DESKTOP) {
+ SetForegroundWindow(pedgi->hWndCon);
+ }
+
+ i = DialogBoxParam(GetModuleHandle(NULL),
+ "ERRORPANEL",
+ GetDesktopWindow(),
+ (DLGPROC) ErrorDialogEvents,
+ (LPARAM) pedgi
+ );
+ }
+
+ if (i == RMB_ABORT || i == -1) {
+ pedgi->dwReply = RMB_ABORT;
+ if (VDMForWOW && pW32HungAppNotifyThread) {
+ (*pW32HungAppNotifyThread)(0); // we won't return from this
+ }
+ }
+ else {
+ pedgi->dwReply = i;
+ }
+
+
+ return 0;
+}
+
+
+
+
+
+LONG APIENTRY ErrorDialogEvents(HWND hDlg,WORD wMsg,LONG wParam,LONG lParam)
+{
+ ERRORDIALOGINFO *pedgi;
+ CHAR szBuff[MAX_PATH];
+ int i;
+ LPSTR lpstr;
+ LONG l;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::::: Process messages */
+ switch(wMsg)
+ {
+ /*:::::::::::::::::::::::::::::::::::::: Initialise Dialog controls */
+ case WM_INITDIALOG:
+ pedgi = (PERRORDIALOGINFO) lParam;
+
+ // set the desired icon
+ switch (pedgi->dwOptions & (RMB_ICON_INFO | RMB_ICON_BANG |
+ RMB_ICON_STOP | RMB_ICON_WHAT))
+ {
+ case RMB_ICON_STOP: lpstr = NULL; break;
+ case RMB_ICON_INFO: lpstr = IDI_ASTERISK; break;
+ case RMB_ICON_BANG: lpstr = IDI_EXCLAMATION; break;
+ case RMB_ICON_WHAT: lpstr = IDI_QUESTION; break;
+ default: lpstr = IDI_APPLICATION; break;
+ }
+ if (lpstr) { // default is STOP sign
+ SendDlgItemMessage(hDlg, IDE_ICON, STM_SETICON,
+ (WPARAM)LoadIcon(NULL,lpstr), 0);
+ }
+
+ SwpButtons(hDlg, pedgi->dwOptions);
+
+ // set Edit control message if we have one
+ if (pedgi->dwOptions & RMB_EDIT) {
+ SetWindowText(GetDlgItem(hDlg,IDE_EDIT), pedgi->pEdit);
+ if (*pedgi->pEdit) {
+ SendDlgItemMessage(hDlg, IDE_EDIT,
+ EM_SETSEL,
+ (WPARAM)0,
+ (LPARAM)strlen(pedgi->pEdit));
+ }
+ SendDlgItemMessage(hDlg, IDE_EDIT,
+ EM_LIMITTEXT,
+ (WPARAM)HIWORD(pedgi->dwOptions),
+ (LPARAM)0);
+ }
+ else {
+ ShowWindow(GetDlgItem(hDlg,IDE_EDIT), SW_HIDE);
+ }
+
+ // set err message text
+ SetWindowText(GetDlgItem(hDlg,IDE_ERRORMSG), pedgi->message);
+
+ // set app title text
+ if (*pedgi->Title) {
+ sprintf(szBuff,
+ strlen(pedgi->Title) < 80 ? "\n%s" : "%s",
+ pedgi->Title);
+ SetWindowText(GetDlgItem(hDlg,IDE_APPTITLE), szBuff);
+ }
+
+ SwpDosDialogs(hDlg, pedgi->hWndCon, HWND_TOPMOST, 0);
+
+ SetWindowLong(hDlg, DWL_USER, (LONG)pedgi);
+
+ break;
+
+
+ /*:::::::::::::::::::::::::::::::: Trap and process button messages */
+ case WM_COMMAND:
+ pedgi = (PERRORDIALOGINFO)GetWindowLong(hDlg,DWL_USER);
+ i = (int) LOWORD(wParam);
+ switch (i) {
+ case IDB_QUIT:
+ if (pedgi->pEdit) {
+ *pedgi->pEdit = '\0';
+ }
+ EndDialog(hDlg,RMB_ABORT);
+ break;
+
+ case IDB_RETRY:
+ if (pedgi->pEdit) {
+ *pedgi->pEdit = '\0';
+ }
+ EndDialog(hDlg,RMB_RETRY);
+ break;
+
+ case IDCANCEL:
+ case IDB_CONTINUE:
+ if (pedgi->pEdit) {
+ *pedgi->pEdit = '\0';
+ }
+ EndDialog(hDlg,RMB_IGNORE);
+ break;
+
+ case IDB_OKEDIT:
+ if (pedgi->pEdit) {
+ l = SendDlgItemMessage(hDlg, IDE_EDIT,
+ WM_GETTEXT,
+ (WPARAM)HIWORD(pedgi->dwOptions),
+ (LPARAM)pedgi->pEdit);
+ if (!l)
+ *(pedgi->pEdit) = '\0';
+ }
+ EndDialog(hDlg, RMB_EDIT);
+ break;
+
+ default:
+ return(FALSE);
+ }
+ /*:::::::::::::::::::::::::::::::::::::::::: Not processing message */
+ default:
+ return(FALSE); /* Message not processed */
+ }
+ return TRUE;
+}
+
+
+
+/*
+ * SwpButtons - SetWindowPos\showstate for the vraious buttons
+ *
+ * entry: HWND hDlg, - DialogBox window handle
+ * DWORD dwOptions
+ *
+ */
+void SwpButtons(HWND hDlg, DWORD dwOptions)
+{
+ RECT rect;
+ POINT point;
+ long DlgWidth, ButWidth, xOrg, xIncr, yClientPos;
+ WORD wButtons;
+
+ // count number of buttons being shown
+ wButtons = 0;
+ if (dwOptions & RMB_ABORT) {
+ wButtons++;
+ }
+ if (dwOptions & RMB_RETRY) {
+ wButtons++;
+ }
+ if (dwOptions & RMB_IGNORE) {
+ wButtons++;
+ }
+ if (dwOptions & RMB_EDIT) {
+ wButtons++;
+ }
+
+ // figure out where first button goes,
+ // and how much space between buttons
+
+ GetWindowRect(GetDlgItem(hDlg,IDB_QUIT), &rect);
+ point.x = rect.left;
+ point.y = rect.top;
+ ScreenToClient(hDlg, &point);
+ DlgWidth = point.x;
+ GetWindowRect(GetDlgItem(hDlg,IDB_OKEDIT), &rect);
+ point.x = rect.right;
+ point.y = rect.top;
+ ScreenToClient(hDlg, &point);
+ DlgWidth = point.x - DlgWidth;
+ yClientPos = point.y;
+
+ ButWidth = rect.right - rect.left;
+ xIncr = ButWidth + ButWidth/2;
+
+ if (wButtons & 1) { // odd number of buttons
+ xOrg = (DlgWidth - ButWidth)/2;
+ if (wButtons > 1)
+ xOrg -= xIncr;
+ }
+ else { // even number of buttons
+ xOrg = DlgWidth/2 - (ButWidth + ButWidth/4);
+ if (wButtons == 4)
+ xOrg -= xIncr;
+ }
+
+
+ // set each of the buttons in their correct place
+
+
+ if (dwOptions & RMB_ABORT) {
+ SetWindowPos(GetDlgItem(hDlg,IDB_QUIT), 0,
+ xOrg, yClientPos, 0,0,
+ SWP_NOSIZE | SWP_NOZORDER);
+ xOrg += xIncr;
+ }
+ else {
+ ShowWindow(GetDlgItem(hDlg,IDB_QUIT), SW_HIDE);
+ }
+
+ if (dwOptions & RMB_RETRY) {
+ SetWindowPos(GetDlgItem(hDlg,IDB_RETRY), 0,
+ xOrg, yClientPos, 0,0,
+ SWP_NOSIZE | SWP_NOZORDER);
+ xOrg += xIncr;
+ }
+ else {
+ ShowWindow(GetDlgItem(hDlg,IDB_RETRY), SW_HIDE);
+ }
+
+ if (dwOptions & RMB_IGNORE) {
+ SetWindowPos(GetDlgItem(hDlg,IDB_CONTINUE), 0,
+ xOrg, yClientPos, 0,0,
+ SWP_NOSIZE | SWP_NOZORDER);
+ xOrg += xIncr;
+ }
+ else {
+ ShowWindow(GetDlgItem(hDlg,IDB_CONTINUE), SW_HIDE);
+ }
+
+ if (dwOptions & RMB_EDIT) {
+ SetWindowPos(GetDlgItem(hDlg,IDB_OKEDIT), 0,
+ xOrg, yClientPos, 0,0,
+ SWP_NOSIZE | SWP_NOZORDER);
+ xOrg += xIncr;
+ // if we have edit control, its button is awlays
+ // the default button
+ SendMessage(hDlg, DM_SETDEFID,
+ (WPARAM)IDB_OKEDIT,
+ (LPARAM)0);
+ }
+ else {
+ ShowWindow(GetDlgItem(hDlg,IDB_OKEDIT), SW_HIDE);
+ }
+}
+
+
+/*
+ * SwpDosDialogs - SetWindowPos for Dos Dialogs
+ *
+ * used by Dos dialog procedures to position themselves
+ * relative to the current Dos session
+ *
+ * entry: HWND hDlg, - DialogBox window handle
+ * HWND hWndCon, - Window handle for dos session
+ * HWND SwpInsert, - SetWindowPos's placement order handle
+ * UINT SwpFlags - SetWindowPos's window positioning flags
+ */
+void SwpDosDialogs(HWND hDlg, HWND hWndCon,
+ HWND SwpInsert, UINT SwpFlags)
+{
+ RECT rDeskTop, rDosSess;
+ long DlgWidth,DlgHeight;
+
+ GetWindowRect(GetDesktopWindow(), &rDeskTop);
+ GetWindowRect(hDlg, &rDosSess);
+ DlgWidth = rDosSess.right - rDosSess.left;
+ DlgHeight = rDosSess.bottom - rDosSess.top;
+
+
+ // center the dialog, if no hWnd for console
+ if (hWndCon == HWND_DESKTOP) {
+ rDosSess.left = (rDeskTop.right - DlgWidth)/2;
+ rDosSess.top = (rDeskTop.bottom - DlgHeight)/2;
+ }
+ // pos relative to console window, staying on screen
+ else {
+ GetWindowRect(hWndCon, &rDosSess);
+ rDosSess.left += (rDosSess.right - rDosSess.left - DlgWidth)/3;
+ if (rDosSess.left + DlgWidth > rDeskTop.right) {
+ rDosSess.left = rDeskTop.right - DlgWidth - GetSystemMetrics(SM_CXICONSPACING)/2;
+ }
+ if (rDosSess.left < rDeskTop.left) {
+ rDosSess.left = rDeskTop.left + GetSystemMetrics(SM_CXICONSPACING)/2;
+ }
+
+ rDosSess.top += DlgHeight/4;
+ if (rDosSess.top + DlgHeight > rDeskTop.bottom) {
+ rDosSess.top = rDeskTop.bottom - DlgHeight - GetSystemMetrics(SM_CYICONSPACING)/2;
+ }
+ if (rDosSess.top < rDeskTop.top) {
+ rDosSess.top = rDeskTop.top + GetSystemMetrics(SM_CYICONSPACING)/2;
+ }
+ }
+
+ SetWindowPos(hDlg, SwpInsert,
+ rDosSess.left, rDosSess.top,0,0,
+ SWP_NOSIZE | SwpFlags);
+}
+
+
+
+/*
+ * WowErrorDialogEvents
+ *
+ * Uses WOWpSysErrorBox, to safely create a message box on WOW
+ * Replaces the functionality of the User mode DialogBox
+ * "ErrorDialogEvents"
+ */
+int WowErrorDialogEvents(ERRORDIALOGINFO *pedgi)
+{
+ CHAR szTitle[MAX_PATH];
+ CHAR szMsg[EHS_MSG_LEN];
+ USHORT wButt1, wButt2, wButt3;
+
+ if (*pedgi->Title) {
+ sprintf(szMsg, "%s\n", pedgi->Title);
+ }
+ else {
+ szMsg[0] = '\0';
+ }
+
+ strcat(szMsg, pedgi->message);
+ strcat(szMsg, " ");
+
+ if (!LoadString(GetModuleHandle(NULL), ED_WOWPROMPT,
+ szTitle, sizeof(szTitle) - 1))
+ {
+ szTitle[0] = '\0';
+ }
+ strcat(szMsg, szTitle);
+
+
+ if (!LoadString(GetModuleHandle(NULL), ED_WOWTITLE,
+ szTitle, sizeof(szTitle) - 1))
+ {
+ szTitle[0] = '\0';
+ }
+
+ wButt1 = pedgi->dwOptions & RMB_ABORT ? SEB_CLOSE : 0;
+ wButt2 = pedgi->dwOptions & RMB_RETRY ? SEB_RETRY : 0;
+ wButt3 = pedgi->dwOptions & RMB_IGNORE ? SEB_IGNORE : 0;
+
+ if (wButt1) {
+ wButt1 |= SEB_DEFBUTTON;
+ }
+ else if (wButt2) {
+ wButt1 |= SEB_DEFBUTTON;
+ }
+ else if (wButt3) {
+ wButt2 |= SEB_DEFBUTTON;
+ }
+
+ switch (WOWpSysErrorBox(szTitle,
+ szMsg,
+ wButt1,
+ wButt2,
+ wButt3) )
+ {
+ case 1:
+ return RMB_ABORT;
+ case 2:
+ return RMB_RETRY;
+ case 3:
+ return RMB_IGNORE;
+ }
+ return RMB_ABORT;
+}
+
+
+
+
+
+
+
+
+/*++
+ * WOWpSysErrorBox
+ *
+ * 32-bit Implementation of of SysErrorBox, which doesn't exist in Win32
+ * This is the only safe way to raise a message box for WOW, and is also
+ * safe to use for dos apps.
+ *
+ * History:
+ * 23-Mar-93 DaveHart Created
+--*/
+ULONG WOWpSysErrorBox(
+ LPSTR szTitle,
+ LPSTR szMessage,
+ USHORT wBtn1,
+ USHORT wBtn2,
+ USHORT wBtn3)
+{
+ NTSTATUS Status;
+ ULONG dwParameters[4];
+ ULONG dwResponse;
+ ANSI_STRING AnsiString;
+ UNICODE_STRING UnicodeTitle;
+ UNICODE_STRING UnicodeMessage;
+
+ RtlInitAnsiString(&AnsiString, szTitle);
+ RtlAnsiStringToUnicodeString(&UnicodeTitle, &AnsiString, TRUE);
+
+ RtlInitAnsiString(&AnsiString, szMessage);
+ RtlAnsiStringToUnicodeString(&UnicodeMessage, &AnsiString, TRUE);
+
+ dwParameters[0] = ((ULONG)TRUE << 16) | (ULONG) wBtn1;
+ dwParameters[1] = ((ULONG)wBtn2 << 16) | (ULONG) wBtn3;
+ dwParameters[2] = (ULONG)&UnicodeTitle;
+ dwParameters[3] = (ULONG)&UnicodeMessage;
+
+ //
+ // OR in 0x10000000 to force the hard error through even if
+ // SetErrorMode has been called.
+ //
+
+ Status = NtRaiseHardError(
+ STATUS_VDM_HARD_ERROR | 0x10000000,
+ 4,
+ 1 << 2 | 1 << 3,
+ dwParameters,
+ 0,
+ &dwResponse
+ );
+
+ RtlFreeUnicodeString(&UnicodeTitle);
+ RtlFreeUnicodeString(&UnicodeMessage);
+
+ return NT_SUCCESS(Status) ? dwResponse : 0;
+}
+
+
+/*
+ * Exported routine for wow32 to invoke a system error box
+ * Uses WowpSysErrorBox
+ */
+
+ULONG WOWSysErrorBox(
+ LPSTR szTitle,
+ LPSTR szMessage,
+ USHORT wBtn1,
+ USHORT wBtn2,
+ USHORT wBtn3)
+{
+ ULONG ulRet;
+
+ SuspendTimerThread();
+
+ ulRet = WOWpSysErrorBox(szTitle,
+ szMessage,
+ wBtn1,
+ wBtn2,
+ wBtn3);
+
+ ResumeTimerThread();
+
+ return ulRet;
+}
+
+
+
+
+
+
+
+
+
+#ifndef PROD
+/*
+ * HostDebugBreak
+ *
+ * Raises a breakpoint by creating an access violation
+ * to give us a chance to get into a user mode debugger
+ *
+ */
+void HostDebugBreak(void)
+{
+ DbgBreakPoint();
+}
+#endif
+
+VOID RcErrorBoxPrintf(UINT wId, CHAR *szMsg)
+{
+ CHAR message[EHS_MSG_LEN];
+ CHAR acctype[EHS_MSG_LEN];
+ CHAR dames[EHS_MSG_LEN];
+
+
+ OemMessageToAnsiMessage(acctype, szMsg);
+
+ if (LoadString(GetModuleHandle(NULL),wId,
+ dames, sizeof(dames)/sizeof(CHAR)))
+ {
+ sprintf(message, dames, acctype);
+ }
+ else {
+ strcpy(message, szDoomMsg);
+ }
+
+ ErrorDialogBox(message, NULL, RMB_ICON_STOP | RMB_ABORT | RMB_IGNORE);
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_ertbl.c b/private/mvdm/softpc.new/host/src/nt_ertbl.c
new file mode 100644
index 000000000..9c0785ab1
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_ertbl.c
@@ -0,0 +1,24 @@
+#include "host_def.h"
+#include "insignia.h"
+/*[
+ Name: nt_ertbl.c
+ Derived From: New Development
+ Author: apg
+ Created On: 15 Apr 1991
+ Sccs ID: @(#)sun4_ertbl.c 1.1 4/17/91
+ Purpose: NT specific error types.
+
+ (c)Copyright Insignia Solutions Ltd., 1991. All rights reserved.
+]*/
+
+static char SccsID[]="@(#)sun4_ertbl.c 1.1 4/17/91 Copyright Insignia Solutions Ltd.";
+
+#include "error.h"
+
+GLOBAL ERROR_STRUCT host_errors[] =
+{
+ { EH_ERROR, EV_EXTRA_CHAR }, /* FUNC_FAILED */
+ { EH_ERROR, EV_EXTRA_CHAR }, /* SYSTEM ERROR */
+ { EH_ERROR, EV_EXTRA_CHAR }, /* UNSUPPORT BAUD RATE */
+ { EH_ERROR, 0 }, /* Error opening com port */
+};
diff --git a/private/mvdm/softpc.new/host/src/nt_event.c b/private/mvdm/softpc.new/host/src/nt_event.c
new file mode 100644
index 000000000..9e746c102
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_event.c
@@ -0,0 +1,1918 @@
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : Win32 Input Module.
+ *
+ * Description : This module contains data and functions that
+ * process Win32 messages.
+ *
+ * Author : D.A.Bartlett
+ *
+ * Notes :
+ */
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <vdmapi.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <excpt.h>
+#include <ntddvdeo.h>
+#include <ntddkbd.h>
+#include <winuserp.h>
+#include "conapi.h"
+#include "conroute.h"
+#include "insignia.h"
+
+#include "host_def.h"
+#include "xt.h"
+#include "sas.h"
+#include CpuH
+#include "bios.h"
+#include "gvi.h"
+#include "error.h"
+#include "config.h"
+#include "keyboard.h"
+#include "keyba.h"
+#include "idetect.h"
+#include "gmi.h"
+#include "gfx_upd.h"
+#include "nt_graph.h"
+#include "nt_uis.h"
+#include <stdio.h>
+#include "trace.h"
+#include "video.h"
+#include "debug.h"
+#include "ckmalloc.h"
+#include "mouse.h"
+#include "mouse_io.h"
+#include "ica.h"
+
+#include "nt_mouse.h"
+#include "nt_event.h"
+#include "nt_vdd.h"
+#include "nt_timer.h"
+
+#include "host.h"
+#include "host_hfx.h"
+#include "host_nls.h"
+#include "spcfile.h"
+#include "host_rrr.h"
+
+#include "nt_thred.h"
+#include "nt_uis.h"
+
+#include "ntcheese.h"
+#include "nt_reset.h"
+#include "nt_fulsc.h"
+#include <vdm.h>
+#include "nt_eoi.h"
+#include "nt_com.h"
+#include "nt_pif.h"
+#include "yoda.h"
+/*================================================================
+External references.
+================================================================*/
+
+
+// Jonle Mod
+// defined in base\keymouse\keyba.c
+VOID KbdResume(VOID);
+VOID RaiseAllDownKeys(VOID);
+int IsKeyDown(int Key);
+
+HANDLE hWndConsole;
+HANDLE hKbdHdwMutex;
+ULONG KbdHdwFull; // contains num of keys in 6805 buffer
+#ifndef MONITOR
+WORD BWVKey = 0;
+char achES[]="EyeStrain";
+#endif
+#ifdef YODA
+BOOL bYoda;
+#endif
+BOOL stdoutRedirected=FALSE;
+ULONG CntrlHandlerState=0;
+
+IMPORT void RestoreKbdLed(void);
+
+
+/*::::::::::::::::::::::::::::::::::: Key history control variables/defines */
+
+#define MAX_KEY_EVENTS (100)
+static PKEY_EVENT_RECORD key_history_head, key_history_tail;
+static PKEY_EVENT_RECORD key_history;
+static key_history_count;
+
+int GetHistoryKeyEvent(PKEY_EVENT_RECORD LastKeyEvent, int KeyNumber);
+void update_key_history(INPUT_RECORD *InputRecords, DWORD RecordsRead);
+void InitKeyHistory();
+void InitQueue(void);
+void ReturnUnusedKeyEvents(int UnusedKeyEvents);
+int CalcNumberOfUnusedKeyEvents(void);
+
+
+/*:::::::::::::::::::::::::::::: Local static data and defines for keyboard */
+
+void nt_key_down_action(PKEY_EVENT_RECORD KeyEvent);
+void nt_key_up_action(PKEY_EVENT_RECORD KeyEvent);
+
+void nt_process_keys(PKEY_EVENT_RECORD KeyEvent);
+void nt_process_mouse(PMOUSE_EVENT_RECORD MouseEvent);
+void nt_process_focus(PFOCUS_EVENT_RECORD FocusEvent);
+void nt_process_menu(PMENU_EVENT_RECORD MenuEvent);
+void nt_process_suspend_event();
+void nt_process_screen_scale(void);
+
+
+//
+// keyboard control state syncronization
+//
+KEY_EVENT_RECORD fake_shift = { TRUE, 1, VK_SHIFT, 0x2a, 0, SHIFT_PRESSED };
+KEY_EVENT_RECORD fake_caps = { TRUE, 1, VK_CAPITAL, 0x3a, 0, CAPSLOCK_ON };
+KEY_EVENT_RECORD fake_ctl = { TRUE, 1, VK_CONTROL, 0x1d, 0, 0 };
+KEY_EVENT_RECORD fake_alt = { TRUE, 1, VK_MENU, 0x38, 0, 0 };
+KEY_EVENT_RECORD fake_numlck = { TRUE, 1, VK_NUMLOCK, 0x45, 0, ENHANCED_KEY };
+KEY_EVENT_RECORD fake_scroll = { TRUE, 1, VK_SCROLL, 0x46, 0, 0};
+DWORD ToggleKeyState = NUMLOCK_ON; // default state on dos boot up
+
+void AltUpDownUp(void);
+
+
+/*::::::::::::::::::::::::::::::::::: Key message passing control variables */
+
+int EventStatus = ES_NOEVENTS;
+
+/*:::::::::::::::::::::::::::: Mouse positions and current button states */
+
+BOOL SetNextMouseEvent(void);
+BOOL PointerAttachedWindowed = FALSE; /* So re-attached on FS switch */
+BOOL DelayedReattachMouse = FALSE; /* but ClientRect wrong so delay attach*/
+
+
+#define MOUSEEVENTBUFFERSIZE (32)
+
+int MouseEBufNxtFreeInx; /* Index to next free entry in event buffer */
+int MouseEBufNxtEvtInx; /* Index to next event to use in mouse evt buf */
+int MouseEventCount=0;
+
+struct
+{
+ POINT mouse_pos; /* Mouse postion */
+ UCHAR mouse_button_left; /* State of left button */
+ UCHAR mouse_button_right; /* State of right button */
+} MouseEventBuffer[MOUSEEVENTBUFFERSIZE];
+
+
+ULONG NoMouseTics;
+
+ULONG event_thread_blocked_reason = 0xFFFFFFFF;
+
+
+HCURSOR cur_cursor = NULL; /* Current cursor handle */
+#ifdef X86GFX
+half_word saved_text_lines; /* No of lines for last SelectMouseBuffer. */
+#endif /* X86GFX */
+
+
+/*@ACW========================================================================
+Flag to keep track of whether or not the Hide Pointer system menu item is
+greyed (i.e. the window is iconised) or enabled.
+============================================================================*/
+BOOL bGreyed=FALSE;
+
+
+/*::::::::::::::::::::::::::::: Variables used to control key message Queue */
+
+#define KEY_QUEUE_SIZE (25)
+
+typedef struct { BYTE ATcode; BOOL UpKey; } KeyQEntry;
+
+typedef struct
+{
+ short KeyCount; /* Number of keys in the queue */
+ short QHead; /* Head of queue */
+ short QTail; /* Tail of queue */
+ KeyQEntry Keys[KEY_QUEUE_SIZE]; /* Keys in queue */
+} KeyQueueData;
+
+static KeyQueueData KeyQueue;
+
+
+
+
+static volatile BOOL InitComplete;
+
+/*:::::: Variables used to control blocking and unblocking the event thread */
+
+BOOL fEventThreadBlock = FALSE; /* Event thread blocked ??? */
+HANDLE hConsoleWait; /* Console block mutex */
+HANDLE hConsoleWaitStall; /* Object used to sync threads on block */
+HANDLE hConsoleSuspend;
+/*::::::::::::: Variable to hold current screen scale ::::::::::::::::::::::*/
+
+int savedScale;
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Local functions */
+
+DWORD nt_event_loop(void);
+BOOL CntrlHandler(ULONG CtrlType);
+void send_up_keys(void);
+
+
+VOID ReturnBiosBufferKeys(VOID);
+DWORD ConsoleEventThread(PVOID pv);
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: Start event processing thread ::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_start_event_thread(void)
+{
+ //
+ // create kbd hardware mutex and kbd not full event
+ //
+ if(!(hKbdHdwMutex = CreateMutex(NULL, FALSE, NULL)))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+ //
+ // Create Event Thread,
+ // events to block\resume console input
+ // event queue
+ //
+ // The Event Thread is created suspended to prevent us
+ // from receiving input before the DOS is ready
+ //
+ if (!VDMForWOW) {
+
+ //
+ // Register Control 'C' handler, for DOS only
+ //
+ if(!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CntrlHandler,TRUE))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+ ThreadInfo.EventMgr.Handle = CreateThread(NULL,
+ 8192,
+ ConsoleEventThread,
+ NULL,
+ CREATE_SUSPENDED,
+ &ThreadInfo.EventMgr.ID);
+
+ if(!ThreadInfo.EventMgr.Handle)
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+ if(!(hConsoleWait = CreateEvent(NULL, FALSE, FALSE, NULL)))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+ if(!(hConsoleWaitStall = CreateEvent(NULL, FALSE, FALSE, NULL)))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+ if(!(hConsoleSuspend = CreateEvent(NULL, FALSE, FALSE, NULL)))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+
+ InitQueue();
+ check_malloc(key_history,MAX_KEY_EVENTS,KEY_EVENT_RECORD);
+ InitKeyHistory();
+ }
+
+ return;
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: Start event processing thread ::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_remove_event_thread(void)
+{
+ /* Must make sure that the thread has terminated */
+ if (!VDMForWOW && ThreadInfo.EventMgr.Handle) {
+ NtAlertThread(ThreadInfo.EventMgr.Handle);
+ }
+}
+
+
+
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::: Process events ::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+DWORD ConsoleEventThread(PVOID pv)
+{
+
+ DWORD dwRet = (DWORD)-1;
+
+ try {
+
+ SetThreadPriority(ThreadInfo.EventMgr.Handle, THREAD_PRIORITY_HIGHEST);
+ DelayMouseEvents(2);
+
+ dwRet = nt_event_loop();
+
+ CloseHandle(ThreadInfo.EventMgr.Handle);
+ CloseHandle(hConsoleWait);
+ CloseHandle(hConsoleSuspend);
+ ThreadInfo.EventMgr.Handle = NULL;
+ ThreadInfo.EventMgr.ID = 0;
+ }
+ except(VdmUnhandledExceptionFilter(GetExceptionInformation())) {
+ ; // we shouldn't arrive here
+ }
+
+ return dwRet;
+}
+
+
+
+DWORD nt_event_loop(void)
+{
+ DWORD RecordsRead;
+ DWORD loop;
+ NTSTATUS status;
+ HANDLE Events[2];
+
+ /*
+ * The con server is optimized to avoid extra CaptureBuffer allocations
+ * when the number of InputRecords is less than "INPUT_RECORD_BUFFER_SIZE".
+ * Currently INPUT_RECORD_BUFFER_SIZE is defined internally to the
+ * con server as Five records. See ntcon\client\iostubs.c.
+ */
+
+ INPUT_RECORD InputRecord[5];
+
+
+ /* the console input handle shouldn't get changed during the lifetime
+ of the ntvdm
+ */
+ Events[0] = GetConsoleInputWaitHandle(); ////sc.InputHandle
+ Events[1] = hConsoleSuspend;
+ /*:::::::::::::::::::::::::::::::::::::::::::::: Get and process events */
+
+ while (TRUE) {
+
+ //
+ // Wait for the InputHandle to be signalled, or a suspend event.
+ //
+ status = NtWaitForMultipleObjects(2,
+ Events,
+ WaitAny,
+ TRUE,
+ NULL
+ );
+
+ //
+ // Input handle was signaled, Read the input, without
+ // waiting (otherwise we may get blocked and be unable to
+ // handle the suspend event).
+ //
+ if (!status) {
+ if (ReadConsoleInputExW(sc.InputHandle,
+ &InputRecord[0],
+ sizeof(InputRecord)/sizeof(INPUT_RECORD),
+ &RecordsRead,
+ CONSOLE_READ_NOWAIT
+ ))
+ {
+ if (!RecordsRead) {
+ continue;
+ }
+
+ update_key_history(&InputRecord[0], RecordsRead);
+ }
+ else {
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ break; //Read from console failed
+ }
+ }
+
+ //
+ // Console Suspend event was signaled
+ //
+ else if (status == 1) {
+ nt_process_suspend_event();
+ continue;
+ }
+
+ //
+ // alerted or User apc, This means to terminate
+ // Got an error, inform the user.
+ //
+ else {
+ if (!NT_SUCCESS(status)) {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ }
+ return 0;
+ }
+
+
+ //
+ // Process the Input Events
+ //
+ for (loop = 0; loop < RecordsRead; loop++) {
+ switch(InputRecord[loop].EventType) {
+
+ case MOUSE_EVENT:
+ nt_process_mouse(&InputRecord[loop].Event.MouseEvent);
+ break;
+
+
+ case KEY_EVENT:
+
+ if (WaitKbdHdw(0x50000)) {
+ return(0);
+ }
+
+ do {
+
+ if (KbdHdwFull > 8) {
+ ULONG Delay = KbdHdwFull;
+
+ HostReleaseKbd();
+ HostIdleNoActivity();
+ Sleep(Delay);
+ if (WaitKbdHdw(0x50000))
+ return (0);
+ }
+
+ nt_process_keys(&InputRecord[loop].Event.KeyEvent);
+
+ } while (++loop < RecordsRead &&
+ InputRecord[loop].EventType == KEY_EVENT);
+ loop--;
+ HostReleaseKbd();
+ HostIdleNoActivity();
+ break;
+
+ case MENU_EVENT:
+ nt_process_menu(&InputRecord[loop].Event.MenuEvent);
+ break;
+
+
+ case FOCUS_EVENT:
+ nt_process_focus(&InputRecord[loop].Event.FocusEvent);
+ break;
+
+ case WINDOW_BUFFER_SIZE_EVENT:
+ nt_mark_screen_refresh();
+ break;
+
+ default:
+ fprintf(trace_file,"Undocumented event from console\n");
+ break;
+ }
+ }
+
+ //
+ // encourage the console to pack events together
+ //
+
+ Sleep(10);
+
+ }
+
+ return 0;
+}
+
+
+/*:::::::::::::::::::::: Update key history buffer ::::::::::::::::::::::::*/
+
+void update_key_history(register INPUT_RECORD *InputRecords,
+ register DWORD RecordsRead)
+{
+ for(;RecordsRead--;InputRecords++)
+ {
+ if(InputRecords->EventType == KEY_EVENT)
+ {
+
+ //Transfer key event to history buffer
+ *key_history_tail = InputRecords->Event.KeyEvent;
+
+ //Update ptrs to history buffer
+
+ if(++key_history_tail >= &key_history[MAX_KEY_EVENTS])
+ key_history_tail = key_history;
+
+ //Check for buffer overflow
+
+ if(key_history_tail == key_history_head)
+ {
+ //Buffer overflow, bump head ptr and loss oldest key
+
+ if(++key_history_head >= &key_history[MAX_KEY_EVENTS])
+ key_history_head = key_history;
+ }
+
+ //Update history counter
+
+ if(key_history_count != MAX_KEY_EVENTS)
+ key_history_count++;
+ }
+ }
+ return;
+}
+
+/*:::::::::::::::: Remove last key added to key history buffer ::::::::::::::*/
+
+int GetHistoryKeyEvent(PKEY_EVENT_RECORD LastKeyEvent, int KeyNumber)
+{
+ int KeyReturned = FALSE;
+ int KeysBeforeWrap = key_history_tail-key_history;
+
+ if(key_history_count >= KeyNumber)
+ {
+ if(KeysBeforeWrap < KeyNumber)
+ {
+ //Wrap
+
+ *LastKeyEvent = key_history[MAX_KEY_EVENTS -
+ (KeyNumber - KeysBeforeWrap)];
+ }
+ else
+ {
+ //No warp
+ *LastKeyEvent = key_history_tail[0-KeyNumber];
+ }
+
+ KeyReturned = TRUE;
+ }
+
+ return(KeyReturned);
+}
+
+/*:::::::::::::::::::: Init key history buffer ::::::::::::::::::::::::::::::*/
+
+void InitKeyHistory()
+{
+ key_history_head = key_history_tail = key_history;
+ key_history_count = 0;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Process menu events :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_process_focus(PFOCUS_EVENT_RECORD FocusEvent)
+{
+
+ BOOL slow;
+
+ sc.Focus = FocusEvent->bSetFocus;
+
+ if(sc.Focus )
+ {
+ /* input focus acquired */
+ AltUpDownUp();
+
+ MouseInFocus();
+ if (PointerAttachedWindowed && sc.ScreenState == WINDOWED)
+ {
+ MouseHide();
+ PointerAttachedWindowed = FALSE; /* only used in switch */
+ DelayedReattachMouse = TRUE;
+ }
+ /* set the event in case waiting for focus to go fullscreen */
+ if(sc.FocusEvent != NULL) PulseEvent(sc.FocusEvent);
+#ifndef MONITOR
+ if (sc.ModeType == GRAPHICS)
+ host_mark_screen_refresh();
+#endif
+ }
+ else /* input focus lost */
+ {
+
+ slow = savedScreenState != sc.ScreenState;
+
+ MouseOutOfFocus(); /* turn off mouse 'attachment' */
+
+#ifndef PROD
+ fprintf(trace_file,"Focus lost\n");
+#endif
+ }
+
+
+
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Process menu events :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+void nt_process_menu(PMENU_EVENT_RECORD MenuEvent)
+{
+
+/*================================================================
+Code to handle the event resulting from the user choosing the
+Settings... menu option from the system menu.
+
+Andrew Watson 6/2/92
+Ammended to do the mouse attach/detach menu stuff 26/8/92
+Ammended to do Alt key processing.
+12-Apr-1994 Jonle fixed key processing
+
+================================================================*/
+
+ switch(MenuEvent->dwCommandId)
+ {
+ // consrv sends when it gets an initmenu, and indicates
+ // that a sys menu is coming up, and we are losing kbd focus
+ case WM_INITMENU:
+ AltUpDownUp();
+ /* stop cursor cliping */
+ MouseSystemMenuON();
+ break;
+
+ // consrv sends when it gets a MENUSELECT with
+ // HIWORD(wParam) == MF_MAINMENU (0xffff). I think
+ // it means we are regaining kbd focus
+ case WM_MENUSELECT:
+ MouseSystemMenuOFF();
+ break;
+
+ case IDM_POINTER:
+ {
+ BOOL bIcon;
+
+ VDMConsoleOperation(VDM_IS_ICONIC,&bIcon);
+
+ /* is the SoftPC window NOT an icon? */
+ if(!bIcon)
+ {
+ if(bPointerOff) /* if the pointer is not visible */
+ {
+ MouseDisplay();
+ }
+ else/* hide the pointer */
+ {
+ MouseHide();
+ }
+ }
+ break;
+ }
+
+ } /* End of switch */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::: Process suspend event thread event ::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_process_suspend_event()
+{
+ NTSTATUS Status;
+
+ //Tell the CPU thread that we have blocked
+ SetEvent(hConsoleWaitStall);
+
+ //
+ // Wait for the resume routine to wake us up
+ //
+ Status = NtWaitForSingleObject(hConsoleWait, TRUE, NULL);
+
+ // If error, probably cause handle was closed, so exit
+ // if alerted signal to exit
+ if (Status) {
+ ExitThread(0);
+ }
+}
+
+
+
+/*
+ * Resets the vdm's toggle key state according to the
+ * Current incoming key state from console by sending
+ * fake keys to the vdm as needed.
+ * the caller must be holding the keyboard mutex.
+ */
+
+void SyncToggleKeys(WORD wVirtualKeyCode, DWORD dwControlKeyState)
+{
+ DWORD CurrKeyState;
+
+ CurrKeyState = dwControlKeyState;
+
+ //
+ // If the key is one of the toggles, and changed state
+ // invert the current state, since want we really want
+ // is the toggle state before this key was pressed.
+ //
+ if (wVirtualKeyCode == VK_SHIFT &&
+ (CurrKeyState & SHIFT_PRESSED) != (ToggleKeyState & SHIFT_PRESSED))
+ {
+ CurrKeyState ^= SHIFT_PRESSED;
+ }
+
+ if (wVirtualKeyCode == VK_NUMLOCK &&
+ (CurrKeyState & NUMLOCK_ON) != (ToggleKeyState & NUMLOCK_ON))
+ {
+ CurrKeyState ^= NUMLOCK_ON;
+ }
+
+ if (wVirtualKeyCode == VK_SCROLL &&
+ (CurrKeyState & SCROLLLOCK_ON) != (ToggleKeyState & SCROLLLOCK_ON))
+ {
+ CurrKeyState ^= SCROLLLOCK_ON;
+ }
+
+ if (wVirtualKeyCode == VK_CAPITAL &&
+ (CurrKeyState & CAPSLOCK_ON) != (ToggleKeyState & CAPSLOCK_ON))
+ {
+ /*
+ * KbdBios does not toggle capslock if Ctl is down.
+ * Nt does the opposite always toggling capslock state.
+ * Force NT conform behaviour by sending:
+ * Ctl up, Caps Dn, Caps Up, Ctl dn
+ * so that KbdBios will toggle its caps state
+ * before processing the current Ctl-Caps keyevent.
+ */
+ if (dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
+ {
+ nt_key_up_action(&fake_ctl);
+ if (IsKeyDown(30)) { // capslock
+ nt_key_up_action(&fake_caps);
+ }
+ nt_key_down_action(&fake_caps);
+ nt_key_up_action(&fake_caps);
+ nt_key_down_action(&fake_ctl);
+ }
+
+ CurrKeyState ^= CAPSLOCK_ON;
+ }
+
+
+ if ((CurrKeyState & SHIFT_PRESSED) &&
+ !(ToggleKeyState & SHIFT_PRESSED))
+ {
+ nt_key_down_action(&fake_shift);
+ }
+ else if ((CurrKeyState & SHIFT_PRESSED) &&
+ !(ToggleKeyState & SHIFT_PRESSED) )
+ {
+ nt_key_up_action(&fake_shift);
+ }
+
+
+ if ((CurrKeyState & NUMLOCK_ON) != (ToggleKeyState & NUMLOCK_ON))
+ {
+ if (IsKeyDown(90)) {
+ nt_key_up_action(&fake_numlck);
+ }
+ nt_key_down_action(&fake_numlck);
+ nt_key_up_action(&fake_numlck);
+ }
+
+ if ((CurrKeyState & CAPSLOCK_ON) != (ToggleKeyState & CAPSLOCK_ON))
+ {
+ if (IsKeyDown(30)) { // capslock
+ nt_key_up_action(&fake_caps);
+ }
+ nt_key_down_action(&fake_caps);
+ nt_key_up_action(&fake_caps);
+ }
+
+ if ((CurrKeyState & SCROLLLOCK_ON) != (ToggleKeyState & SCROLLLOCK_ON))
+ {
+ if (IsKeyDown(125)) { // scrolllock
+ nt_key_up_action(&fake_scroll);
+ }
+ nt_key_down_action(&fake_scroll);
+ nt_key_up_action(&fake_scroll);
+ }
+}
+
+
+
+
+/*
+ * AltUpDownUp - Ensures all kbdhdw keys are in the up state
+ *
+ * Does handling for CW apps with alt triggerred menus
+ * to force them out of the menu state.
+ *
+ * This works for ALT-Esc, Alt-Enter, Alt-Space because we
+ * we haven't received an Alt-up when we receive the lose focus
+ * event. (We actually never receive the alt-up). Thus we can
+ * detect when a dos app might be in its alt triggered menu.
+ *
+ * Alt-TAB does not work, because user32 got ?smart? and sends an
+ * alt-up before switching focus, breaking our detection algorithm.
+ * Also other hot keys which are meaning ful to various dos apps
+ * are not handled. Note that this is the same detection algorithm
+ * used by win 3.1.
+ *
+ */
+void AltUpDownUp(void)
+{
+
+ Sleep(100);
+ if (WaitKbdHdw(0xffffffff))
+ return;
+
+ if (IsKeyDown(60) || IsKeyDown(62)) { // left alt, right alt
+
+ nt_key_up_action(&fake_alt); // Alt Up
+
+ HostReleaseKbd();
+ Sleep(100);
+ if (WaitKbdHdw(0xffffffff))
+ ExitThread(1);
+
+ nt_key_down_action(&fake_alt); // Alt Down
+
+ HostReleaseKbd();
+ Sleep(100);
+ if (WaitKbdHdw(0xffffffff))
+ ExitThread(1);
+
+ nt_key_up_action(&fake_alt); // Alt Up
+
+ HostReleaseKbd();
+ Sleep(20);
+ if (WaitKbdHdw(0xffffffff))
+ ExitThread(1);
+
+ }
+
+ RaiseAllDownKeys();
+
+ HostReleaseKbd();
+
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::: Process event, Class registered message handler :::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+#define TOGGLEKEYBITS (SHIFT_PRESSED | NUMLOCK_ON | SCROLLLOCK_ON | CAPSLOCK_ON)
+
+VOID nt_process_keys(PKEY_EVENT_RECORD KeyEvent)
+{
+
+ // Check the last toggle key states, for change
+ if ((ToggleKeyState & TOGGLEKEYBITS)
+ != (KeyEvent->dwControlKeyState & TOGGLEKEYBITS))
+ {
+ SyncToggleKeys(KeyEvent->wVirtualKeyCode, KeyEvent->dwControlKeyState);
+ ToggleKeyState = KeyEvent->dwControlKeyState & TOGGLEKEYBITS;
+ }
+
+ /*............................... Maintain shift states in case of pastes */
+
+ if(KeyEvent->bKeyDown) {
+
+
+#ifndef MONITOR
+ //
+ // Check for windowed graphics resize
+ //
+ if (BWVKey && (KeyEvent->wVirtualKeyCode == BWVKey))
+ {
+ nt_process_screen_scale();
+ }
+#endif
+
+
+ switch(KeyEvent->wVirtualKeyCode) {
+#ifdef YODA
+ case VK_F11:
+ if (getenv("YODA")) {
+ EventStatus |= ~ES_YODA;
+ }
+ break;
+#endif
+
+ case VK_SHIFT:
+ fake_shift = *KeyEvent;
+ break;
+
+ case VK_MENU:
+ fake_alt = *KeyEvent;
+ break;
+
+ case VK_CONTROL:
+ fake_ctl = *KeyEvent;
+ break;
+ }
+
+ nt_key_down_action(KeyEvent);
+
+ } else { /* ! KeyEvent->bKeyDown */
+
+ /*
+ * We don't get a CTRL-Break key make code cause console
+ * eats it when it invokes the CntrlHandler. We must fake
+ * it here, rather than in the CntrlHandler, cause
+ * CntrlHandler is asynchronous and we may lose the state
+ * of the Cntrl-Key.
+ * 25-Aug-1992 Jonle
+ * Also SysRq/Printscreen key. Simon May 93
+ */
+ if (KeyEvent->wVirtualKeyCode == VK_CANCEL ||
+ KeyEvent->wVirtualKeyCode == VK_SNAPSHOT )
+ {
+ nt_key_down_action(KeyEvent);
+ }
+
+ nt_key_up_action(KeyEvent); /* Key up */
+
+ } /* ! KeyEvent->bKeyDown */
+
+} /* nt_process_keys */
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::: Process key down event :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_key_down_action(PKEY_EVENT_RECORD KeyEvent)
+{
+ BYTE ATcode;
+
+ ATcode = KeyMsgToKeyCode(KeyEvent);
+
+ if(ATcode)
+ (*host_key_down_fn_ptr)(ATcode);
+
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::: Process keyup event ::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_key_up_action(PKEY_EVENT_RECORD KeyEvent)
+{
+ BYTE ATcode;
+
+ ATcode = KeyMsgToKeyCode(KeyEvent);
+
+ if(ATcode)
+ (*host_key_up_fn_ptr)(ATcode);
+
+}
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::: Process mouse button and movement events :::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+
+void nt_process_mouse(PMOUSE_EVENT_RECORD MouseEvent)
+{
+ int LastMouseInx;
+ POINT mouse_pos;
+ UCHAR mouse_button_left, mouse_button_right;
+
+ host_ica_lock();
+
+ if (NoMouseTics) {
+ ULONG CurrTic;
+ CurrTic = NtGetTickCount();
+ if (CurrTic > NoMouseTics ||
+ (NoMouseTics == 0xffffffff && CurrTic < (0xffffffff >> 1)) )
+ {
+ NoMouseTics = 0;
+ MouseEBufNxtEvtInx = MouseEBufNxtFreeInx = 0;
+ }
+ else {
+ host_ica_unlock();
+ return;
+ }
+ }
+
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::: Setup button state */
+
+ mouse_button_left = MouseEvent->dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED
+ ? 1 : 0;
+
+ mouse_button_right = MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED
+ ? 1 : 0;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::: Get new mouse postion */
+
+ mouse_pos.x = MouseEvent->dwMousePosition.X; /* Mouse X */
+ mouse_pos.y = MouseEvent->dwMousePosition.Y; /* Mouse Y */
+
+ /*
+ * Fix for the case where mouse events are still delivered when the cursor
+ * is outside the window because one of the mouse buttons is down. This can
+ * cause negative numbers in mouse_pos which can cause divide overflow in
+ * mouse interrupt handler code.
+ */
+#ifdef X86GFX
+ if (sc.ScreenState == WINDOWED)
+#endif /* X86GFX */
+ {
+ ULONG maxWidth = sc.PC_W_Width,
+ maxHeight = sc.PC_W_Height;
+
+ if ((sc.ModeType == TEXT) && get_pix_char_width() &&
+ get_host_char_height())
+ {
+ maxWidth /= get_pix_char_width();
+ maxHeight /= get_host_char_height();
+ }
+ if (mouse_pos.x < 0)
+ mouse_pos.x = 0;
+ else if ((ULONG)mouse_pos.x >= maxWidth)
+ mouse_pos.x = maxWidth - 1;
+ if (mouse_pos.y < 0)
+ mouse_pos.y = 0;
+ else if ((ULONG)mouse_pos.y >= maxHeight)
+ mouse_pos.y = maxHeight - 1;
+ }
+
+
+ LastMouseInx = MouseEBufNxtFreeInx ? MouseEBufNxtFreeInx - 1
+ : MOUSEEVENTBUFFERSIZE - 1;
+
+ //
+ // If the previous mouse event is the same as the last
+ // then drop the event.
+ //
+ if (MouseEBufNxtEvtInx != MouseEBufNxtFreeInx &&
+ MouseEventBuffer[LastMouseInx].mouse_pos.x == mouse_pos.x &&
+ MouseEventBuffer[LastMouseInx].mouse_pos.y == mouse_pos.y &&
+ MouseEventBuffer[LastMouseInx].mouse_button_left == mouse_button_left &&
+ MouseEventBuffer[LastMouseInx].mouse_button_right == mouse_button_right )
+ {
+ host_ica_unlock();
+ return;
+ }
+
+
+ //
+ // If not too many events in the mouse buffer
+ // or no outstanding mouse events
+ // or the mouse button state has changed.
+ // Add the current mouse data to the next free position in
+ // the MouseEventBuffer
+ //
+
+
+ if(MouseEventCount <= MOUSEEVENTBUFFERSIZE/2 ||
+ MouseEBufNxtEvtInx == MouseEBufNxtFreeInx ||
+ MouseEventBuffer[LastMouseInx].mouse_button_left != mouse_button_left ||
+ MouseEventBuffer[LastMouseInx].mouse_button_right != mouse_button_right)
+
+ {
+ LastMouseInx = MouseEBufNxtFreeInx;
+ if(++MouseEBufNxtFreeInx == MOUSEEVENTBUFFERSIZE) {
+ MouseEBufNxtFreeInx = 0;
+ }
+
+ MouseEventCount++;
+
+ //
+ // if the buffer is full drop the oldest event
+ //
+ if (MouseEBufNxtFreeInx == MouseEBufNxtEvtInx) {
+ always_trace0("Mouse event input buffer overflow");
+ if(++MouseEBufNxtEvtInx == MOUSEEVENTBUFFERSIZE)
+ MouseEBufNxtEvtInx = 0;
+ }
+ }
+
+
+ MouseEventBuffer[LastMouseInx].mouse_pos = mouse_pos;
+ MouseEventBuffer[LastMouseInx].mouse_button_left = mouse_button_left;
+ MouseEventBuffer[LastMouseInx].mouse_button_right = mouse_button_right;
+
+ DoMouseInterrupt();
+
+ host_ica_unlock();
+}
+
+
+/* MoreMouseEvents - returns TRUE if there are more mousevents
+ * to be retrieved.
+ *
+ * Assumes caller has the IcaLock
+ */
+BOOL MoreMouseEvents(void)
+{
+ return MouseEBufNxtEvtInx != MouseEBufNxtFreeInx;
+}
+
+
+/*
+ * GetNextMouseEvent - copies the next available Mouse Event to
+ * the global data structure os_pointer. if there are no new events
+ * nothing is copied.
+ *
+ * Assumes caller has the IcaLock
+ */
+void GetNextMouseEvent(void)
+{
+
+ if (MouseEBufNxtEvtInx != MouseEBufNxtFreeInx) {
+ os_pointer_data.x = (SHORT)MouseEventBuffer[MouseEBufNxtEvtInx].mouse_pos.x;
+ os_pointer_data.y = (SHORT)MouseEventBuffer[MouseEBufNxtEvtInx].mouse_pos.y;
+ os_pointer_data.button_l = MouseEventBuffer[MouseEBufNxtEvtInx].mouse_button_left;
+ os_pointer_data.button_r = MouseEventBuffer[MouseEBufNxtEvtInx].mouse_button_right;
+
+ if (++MouseEBufNxtEvtInx == MOUSEEVENTBUFFERSIZE)
+ MouseEBufNxtEvtInx = 0;
+
+ MouseEventCount--;
+ }
+
+}
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::Flush all outstanding mouse events :::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void FlushMouseEvents(void)
+{
+ host_ica_lock();
+ MouseEBufNxtEvtInx = MouseEBufNxtFreeInx = 0;
+ host_ica_unlock();
+}
+
+//
+// count == ticks to throwaway, mouse events
+//
+VOID DelayMouseEvents(ULONG count)
+{
+ host_ica_lock();
+
+ NoMouseTics = NtGetTickCount();
+ count = 110 *(count+1);
+ count = NoMouseTics + count;
+ if (count > NoMouseTics)
+ NoMouseTics = count;
+ else
+ NoMouseTics = 0xffffffff; // wrap!
+
+ MouseEBufNxtEvtInx = MouseEBufNxtFreeInx = 0;
+ host_ica_unlock();
+}
+
+
+#ifndef X86GFX
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::: Process screen scale event :::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_process_screen_scale(void)
+{
+ SAVED BOOL init = FALSE;
+
+
+ host_ica_lock();
+ if (!init)
+ {
+ init = TRUE;
+ savedScale = get_screen_scale();
+ }
+ if (savedScale == 4)
+ savedScale = 2;
+ else
+ savedScale++;
+ EventStatus |= ES_SCALEVENT;
+ host_ica_unlock();
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::: See if there is a scale event and if so return the new scale :::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+GLOBAL void GetScaleEvent(void)
+{
+ int Scale;
+
+ if (EventStatus & ES_SCALEVENT)
+ {
+ host_ica_lock();
+ Scale = savedScale;
+ EventStatus &= ~ES_SCALEVENT;
+ host_ica_unlock();
+ host_set_screen_scale(Scale);
+ }
+}
+#endif
+
+
+#ifdef YODA
+void CheckForYodaEvents(void)
+{
+ static HANDLE YodaEvent = NULL;
+
+ /*:::::::::::::::::::::::::::::::::: check for Yoda event object signal */
+
+ if(YodaEvent == NULL)
+ {
+ if((YodaEvent = OpenEvent(EVENT_ALL_ACCESS,FALSE,"YodaEvent")) == NULL)
+ {
+ always_trace0("Failed to open Yoda event object\n");
+ YodaEvent = (HANDLE) -1;
+ }
+ }
+
+ if(YodaEvent && YodaEvent != (HANDLE) -1)
+ {
+ if(!WaitForSingleObject(YodaEvent,0))
+ {
+ ResetEvent(YodaEvent);
+ Enter_yoda();
+ }
+ }
+
+ // check for yoda kbd event
+ if (EventStatus & ES_YODA) {
+ EventStatus &= ~ES_YODA;
+ Enter_yoda();
+ }
+
+}
+#endif
+
+
+// Host funcs to support base keyboard Mods. (Prevents Windows calls from
+// appearing in base).
+/* WaitKbdHdw
+ *
+ * Synchronizes access to kbd hardware
+ * between event thread and cpu thread
+ *
+ * entry: DWORD dwTimeOut - Millisecs to wait
+ *
+ * exit: DWORD dwRc - return code from WaitForSingleObject()
+ *
+ */
+DWORD WaitKbdHdw(DWORD dwTime)
+{
+ DWORD dwRc, dwErr;
+
+ dwErr = dwRc = WaitForSingleObject(hKbdHdwMutex, dwTime);
+ if (dwRc == WAIT_TIMEOUT) {
+ if (dwTime < 0x10000) {
+ dwErr = 0;
+ }
+ }
+ else if (dwRc == 0xFFFFFFFF) {
+ dwErr = GetLastError();
+ }
+
+ if (dwErr) {
+ DisplayErrorTerm(EHS_FUNC_FAILED,dwErr,__FILE__,__LINE__);
+ }
+
+ return dwRc;
+}
+
+GLOBAL VOID HostReleaseKbd(VOID)
+{
+ ReleaseMutex(hKbdHdwMutex);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: Register new cursor :::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void RegisterDisplayCursor(HCURSOR newC)
+{
+ cur_cursor = newC;
+ //if(GetFocus() == sc.Display) SetCursor(newC);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::: Initialise event queue :::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void InitQueue(void)
+{
+ /*:::::::::::::::::::::::::::::: Initialise key queue control variables */
+
+ KeyQueue.KeyCount = KeyQueue.QHead = KeyQueue.QTail = 0;
+ EventStatus = ES_NOEVENTS;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Control handler */
+
+BOOL CntrlHandler(ULONG CtrlType)
+{
+ switch (CtrlType) {
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+ break;
+
+ case SYSTEM_ROOT_CONSOLE_EVENT:
+ //
+ // top most console process is going away
+ // remember this so we will terminate the vdm in
+ // nt_block_event, when the dos app voluntarily exits
+ //
+ CntrlHandlerState |= CNTRL_SYSTEMROOTCONSOLE;
+
+ // fall thru to see if we should terminate now
+
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+#ifndef PROD
+ if (VDMForWOW) { // shouldn't happen
+ printf("WOW: Received EndTask Notice, but we shouldn't\n");
+ break;
+ }
+#endif
+ if (CntrlHandlerState & CNTRL_PUSHEXIT) {
+ ExitProcess(0);
+ return FALSE;
+ }
+
+ if ( (CntrlHandlerState & CNTRL_PIFALLOWCLOSE) ||
+ (!(CntrlHandlerState & CNTRL_SHELLCOUNT) &&
+ (CntrlHandlerState & CNTRL_VDMBLOCKED)) )
+ {
+ TerminateVDM();
+ return FALSE;
+ }
+
+ break;
+
+#ifndef PROD
+ default: // shouldn't happen
+ printf("NTVDM: Received unknown CtrlType=%lu\n",CtrlType);
+#endif
+ }
+ return TRUE;
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::: Functions to block/resume the event thread :::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Currently param is only used to indicate whether the command is exiting but
+ * the PIF setting shows window should not close.
+ */
+
+ void nt_block_event_thread(ULONG BlockFlags)
+ {
+ DWORD dw;
+ int UnusedKeyEvents;
+ COORD scrSize;
+
+ nt_init_event_thread(); // does nothing if init already
+
+ /* remember the reason why we are blocked.
+ * 0 == the application is not being terminated, instead, it is
+ * executing either a 32 bits application or command.com(TSR installed
+ * or shell out).
+ * 1 == application is terminating.
+ * if the application is terminating, we are safe to re-enable
+ * stream io on nt_resume_event_thread.
+ */
+ event_thread_blocked_reason = BlockFlags;
+
+ // Send notification message for VDDs */
+ VDDBlockUserHook();
+
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::: Turn off sound */
+ InitSound(FALSE);
+
+ /*::::::::::::::::::::::::::::::::::::::::::::: Block the event thread */
+
+ if (!VDMForWOW) {
+
+ ResetMouseOnBlock(); // remove mouse pointer menu item
+
+ SetEvent(hConsoleSuspend);
+
+ //Wait for the event thread to block
+ dw = WaitForSingleObject(hConsoleWaitStall, 360000);
+ if (dw) {
+ if (dw == WAIT_TIMEOUT)
+ SetLastError(ERROR_SERVICE_REQUEST_TIMEOUT);
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+ TerminateVDM();
+ }
+
+
+ /*::::::::::::::::::::::::::::::::: Flush screen output, reset console */
+
+
+ if (sc.ScreenState == STREAM_IO)
+ stream_io_update();
+ else {
+ if (sc.ScreenState != FULLSCREEN)
+ (*update_alg.calc_update)();
+ // Put Console back the way it was when we started up
+ ResetConsoleState();
+
+ // Ensure system pointer visible.
+ while(ShowConsoleCursor(sc.OutputHandle,TRUE) < 0)
+ ;
+
+#ifdef MONITOR
+ if(sc.ScreenState == FULLSCREEN) RegainRegenMemory();
+#endif
+
+ /* If keeping window open when exiting and fullscreen, return to desktop */
+ /* Transition made simple as VDM de-registered from console */
+ if (BlockFlags == 1 && sc.ScreenState == FULLSCREEN)
+ {
+ SetConsoleDisplayMode(sc.OutputHandle, CONSOLE_WINDOWED_MODE, &scrSize);
+ }
+ }
+
+ // Turn off PIF Reserved & ShortCut Keys
+ DisablePIFKeySetup();
+
+
+ /*::: Push unused key events from kbd hardware back into the console */
+
+ UnusedKeyEvents = CalcNumberOfUnusedKeyEvents();
+
+ ReturnUnusedKeyEvents(UnusedKeyEvents);
+
+ /*::: Push unused keys from 16 bit bios buffer back into the console */
+ ReturnBiosBufferKeys();
+
+ /*::: Flush outstanding mouse events */
+
+ FlushMouseEvents();
+
+ /*::: Restore Console modes */
+
+ if(!SetConsoleMode(sc.InputHandle,sc.OrgInConsoleMode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+
+ if(!SetConsoleMode(sc.OutputHandle,sc.OrgOutConsoleMode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+
+ if (!(CntrlHandlerState & CNTRL_SHELLCOUNT) &&
+ CntrlHandlerState & CNTRL_SYSTEMROOTCONSOLE) {
+ TerminateVDM();
+ }
+ //
+ // Reset the Active buffer field in sc.
+ //
+ sc.ActiveOutputBufferHandle = sc.OutputHandle;
+ MouseDetachMenuItem(FALSE);
+ }
+
+ // clear kbd state flags in biosdata area
+ sas_store (kb_flag,0);
+ sas_store (kb_flag_1,0);
+ sas_store (kb_flag_2,0);
+ sas_store (kb_flag_3,KBX);
+ sas_store (alt_input,0);
+
+
+ /*::: Suspend timer thread */
+
+ SuspendTimerThread();
+
+
+ /*::: Close printer ports and comms ports */
+
+ host_lpt_close_all(); /* Close all open printer ports */
+
+ if (!(CntrlHandlerState & CNTRL_SHELLCOUNT))
+ host_com_close_all(); /* Close all open comms ports */
+
+ fEventThreadBlock = TRUE;
+
+ CntrlHandlerState |= CNTRL_VDMBLOCKED;
+#ifndef PROD
+ fprintf(trace_file,"Blocked event thread\n");
+#endif
+
+}
+
+/*::::::::::::::::::::::::::::::::::::: Resume event and heart beat threads */
+
+void nt_resume_event_thread(void)
+{
+ IMPORT DWORD TlsDirectError; //Direct access 'used' flag
+
+ //
+ // If wow enters here we are in a really bad way
+ // since it means they are trying to reload
+ //
+ if (VDMForWOW) {
+ TerminateVDM();
+ return;
+ }
+
+ /* re-enable stream io if the application is terminating */
+
+ if (event_thread_blocked_reason == 1 &&
+ StreamIoSwitchOn && !host_stream_io_enabled) {
+ /* renew the screen buffer and window size */
+ if (!GetConsoleScreenBufferInfo(sc.OutputHandle,
+ &sc.ConsoleBuffInfo))
+
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+
+ enable_stream_io();
+#ifdef X86GFX
+ /* tell video bios we are back to stream io */
+ sas_store_no_check( (int10_seg<<4)+useHostInt10, STREAM_IO);
+#endif
+
+ }
+ nt_init_event_thread(); // does nothing if init already
+
+ CntrlHandlerState &= ~CNTRL_VDMBLOCKED;
+#ifndef PROD
+ fprintf(trace_file,"Resume event thread\n");
+#endif
+
+ // Setup Console modes
+ SetupConsoleMode();
+
+ // Turn PIF Reserved & ShortCut Keys back on
+ EnablePIFKeySetup();
+
+ //
+ // re-enable direct access error panels.
+ TlsSetValue(TlsDirectError, 0);
+
+ ica_reset_interrupt_state();
+
+ // Send notification message for VDDs */
+ VDDResumeUserHook();
+
+ if (sc.ScreenState != STREAM_IO) {
+ DoFullScreenResume();
+ MouseAttachMenuItem(sc.ActiveOutputBufferHandle);
+ }
+ ResumeTimerThread(); /* Restart timer thread */
+
+ // set kbd state flags in biosdata area
+ if (!VDMForWOW) {
+ SyncBiosKbdLedToKbdDevice();
+ }
+
+ KbdResume();
+
+ SetEvent(hConsoleWait); /* Restart event thread */
+}
+
+
+
+void
+SyncBiosKbdLedToKbdDevice(
+ void
+ )
+{
+ NTSTATUS Status;
+ UNICODE_STRING UnicodeString;
+ OBJECT_ATTRIBUTES ObjAttr;
+ IO_STATUS_BLOCK IoStatus;
+ KEYBOARD_INDICATOR_PARAMETERS kip;
+ KEYBOARD_UNIT_ID_PARAMETER kuid;
+ HANDLE hKeyboard = 0;
+ HANDLE KeyboardEvent = 0;
+ ULONG ControlKeyState;
+
+ unsigned char KbdLed;
+
+
+ ControlKeyState = ToggleKeyState & (CAPSLOCK_ON | NUMLOCK_ON | SCROLLLOCK_ON);
+
+ RtlInitUnicodeString(&UnicodeString, DD_KEYBOARD_DEVICE_NAME_U L"0");
+ InitializeObjectAttributes(&ObjAttr, &UnicodeString, 0, NULL, NULL);
+
+ Status = NtCreateFile(&hKeyboard,
+ FILE_READ_DATA | SYNCHRONIZE,
+ &ObjAttr,
+ &IoStatus,
+ NULL, 0, 0, FILE_OPEN_IF, 0, NULL, 0
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ hKeyboard = 0;
+ goto GiveUp;
+ }
+ else {
+ KeyboardEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!KeyboardEvent) {
+ goto GiveUp;
+ }
+ }
+
+ kuid.UnitId = 0;
+ Status = NtDeviceIoControlFile(hKeyboard,
+ KeyboardEvent,
+ NULL, NULL, // apcrtn, apccontext
+ &IoStatus,
+ IOCTL_KEYBOARD_QUERY_INDICATORS,
+ &kuid, sizeof(kuid),
+ &kip, sizeof(kip)
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ goto GiveUp;
+ }
+
+
+ Status = NtWaitForSingleObject(KeyboardEvent, FALSE, NULL);
+ if (Status != STATUS_SUCCESS) {
+ goto GiveUp;
+ }
+
+
+ ControlKeyState = 0;
+ if (kip.LedFlags & KEYBOARD_CAPS_LOCK_ON) {
+ ControlKeyState |= CAPSLOCK_ON;
+ }
+
+ if (kip.LedFlags & KEYBOARD_NUM_LOCK_ON) {
+ ControlKeyState |= NUMLOCK_ON;
+ }
+
+ if (kip.LedFlags & KEYBOARD_SCROLL_LOCK_ON) {
+ ControlKeyState |= SCROLLLOCK_ON;
+ }
+
+GiveUp:
+
+ if (hKeyboard) {
+ NtClose(hKeyboard);
+ }
+
+ if (KeyboardEvent) {
+ NtClose(KeyboardEvent);
+ }
+
+
+ ToggleKeyState = ControlKeyState;
+ KbdLed = 0;
+ if (ToggleKeyState & NUMLOCK_ON) {
+ KbdLed |= NUM_STATE;
+ }
+ if (ToggleKeyState & CAPSLOCK_ON) {
+ KbdLed |= CAPS_STATE;
+ }
+ if (ToggleKeyState & SCROLLLOCK_ON) {
+ KbdLed |= SCROLL_STATE;
+ }
+
+ sas_store (kb_flag,KbdLed);
+ sas_store (kb_flag_2,(unsigned char)(KbdLed >> 4));
+
+ return;
+}
+
+
+
+#define NUMBBIRECS 32
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::: Return keys in BIOS buffer ::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+VOID ReturnBiosBufferKeys(VOID)
+{
+ int i;
+ DWORD dwRecs;
+ word BufferHead;
+ word BufferTail;
+ word BufferEnd;
+ word BufferStart;
+ word w;
+ USHORT usKeyState;
+ UCHAR AsciiChar, Digit;
+ WCHAR UnicodeChar;
+
+ INPUT_RECORD InputRecord[NUMBBIRECS];
+
+ sas_loadw(BIOS_KB_BUFFER_HEAD, &BufferHead);
+ sas_loadw(BIOS_KB_BUFFER_TAIL, &BufferTail);
+ sas_loadw(BIOS_KB_BUFFER_END, &BufferEnd);
+ sas_loadw(BIOS_KB_BUFFER_START,&BufferStart);
+
+ i = NUMBBIRECS - 1;
+ while (BufferHead != BufferTail) {
+
+ /*
+ * Get Scode\char from bios buffer, starting from
+ * the last key entered.
+ */
+ BufferTail -= 2;
+ if (BufferTail < BufferStart) {
+ BufferTail = BufferEnd-2;
+ }
+ sas_loadw(BIOS_VAR_START + BufferTail, &w);
+
+ InputRecord[i].EventType = KEY_EVENT;
+ InputRecord[i].Event.KeyEvent.wVirtualScanCode = w >> 8;
+ AsciiChar = (UCHAR)w & 0xFF;
+ (UCHAR)InputRecord[i].Event.KeyEvent.uChar.AsciiChar = AsciiChar;
+
+ /*
+ * Translate the character stuff in InputRecord.
+ * we start filling InputRecord from the bottom
+ * we are working from the last key entered, towards
+ * the oldest key.
+ */
+ if (!BiosKeyToInputRecord(&InputRecord[i].Event.KeyEvent)) {
+ ; // error in translation skip it
+ }
+
+ // normal case
+ else if (InputRecord[i].Event.KeyEvent.wVirtualScanCode) {
+ InputRecord[i].Event.KeyEvent.bKeyDown = FALSE;
+ InputRecord[i-1] = InputRecord[i];
+ i--;
+ InputRecord[i--].Event.KeyEvent.bKeyDown = TRUE;
+ }
+
+ // Special character codes with no scan code are
+ // generated by simulating the alt-num pad entry
+ else if (InputRecord[i].Event.KeyEvent.uChar.AsciiChar)
+ {
+ UnicodeChar = InputRecord[i].Event.KeyEvent.uChar.UnicodeChar;
+
+ // write out what we have, ensuring we have space
+ if (i != NUMBBIRECS - 1) {
+ WriteConsoleInputVDMW(sc.InputHandle,
+ &InputRecord[i+1],
+ NUMBBIRECS - i - 1,
+ &dwRecs);
+ i = NUMBBIRECS - 1;
+ }
+
+
+
+ // restore NUMLOCK state if needed
+ usKeyState = (USHORT)GetKeyState(VK_NUMLOCK);
+ if (!(usKeyState & 1)) {
+ InputRecord[i].EventType = KEY_EVENT;
+ InputRecord[i].Event.KeyEvent.wVirtualScanCode = 0x45;
+ InputRecord[i].Event.KeyEvent.uChar.UnicodeChar = 0;
+ InputRecord[i].Event.KeyEvent.wVirtualKeyCode = VK_NUMLOCK;
+ InputRecord[i].Event.KeyEvent.dwControlKeyState = NUMLOCK_ON;
+ InputRecord[i].Event.KeyEvent.wRepeatCount = 1;
+ InputRecord[i--].Event.KeyEvent.bKeyDown = FALSE;
+ InputRecord[i] = InputRecord[0];
+ InputRecord[i--].Event.KeyEvent.bKeyDown = TRUE;
+ }
+
+ // alt up
+ InputRecord[i].EventType = KEY_EVENT;
+ InputRecord[i].Event.KeyEvent.wVirtualScanCode = 0x38;
+ InputRecord[i].Event.KeyEvent.uChar.UnicodeChar = UnicodeChar;
+ InputRecord[i].Event.KeyEvent.wVirtualKeyCode = VK_MENU;
+ InputRecord[i].Event.KeyEvent.dwControlKeyState = NUMLOCK_ON;
+ InputRecord[i].Event.KeyEvent.wRepeatCount = 1;
+ InputRecord[i--].Event.KeyEvent.bKeyDown = FALSE;
+
+ // up/down for each digits, starting with lsdigit
+ while (AsciiChar) {
+ Digit = AsciiChar % 10;
+ AsciiChar /= 10;
+
+ InputRecord[i].EventType = KEY_EVENT;
+ InputRecord[i].Event.KeyEvent.uChar.UnicodeChar = 0;
+ InputRecord[i].Event.KeyEvent.wVirtualScanCode= aNumPadSCode[Digit];
+ InputRecord[i].Event.KeyEvent.wVirtualKeyCode = VK_NUMPAD0+Digit;
+ InputRecord[i].Event.KeyEvent.dwControlKeyState = NUMLOCK_ON | LEFT_ALT_PRESSED;
+ InputRecord[i].Event.KeyEvent.bKeyDown = FALSE;
+ InputRecord[i-1] = InputRecord[i];
+ i--;
+ InputRecord[i--].Event.KeyEvent.bKeyDown = TRUE;
+ }
+
+ // send alt down
+ InputRecord[i].EventType = KEY_EVENT;
+ InputRecord[i].Event.KeyEvent.wVirtualScanCode = 0x38;
+ InputRecord[i].Event.KeyEvent.uChar.UnicodeChar = 0;
+ InputRecord[i].Event.KeyEvent.wVirtualKeyCode = VK_MENU;
+ InputRecord[i].Event.KeyEvent.dwControlKeyState = NUMLOCK_ON | LEFT_ALT_PRESSED;
+ InputRecord[i].Event.KeyEvent.wRepeatCount = 1;
+ InputRecord[i--].Event.KeyEvent.bKeyDown = TRUE;
+
+
+ // toggel numpad state if needed
+ if (!(usKeyState & 1)) {
+ InputRecord[i].EventType = KEY_EVENT;
+ InputRecord[i].Event.KeyEvent.wVirtualScanCode = 0x45;
+ InputRecord[i].Event.KeyEvent.uChar.UnicodeChar = 0;
+ InputRecord[i].Event.KeyEvent.wVirtualKeyCode = VK_NUMLOCK;
+ InputRecord[i].Event.KeyEvent.dwControlKeyState = NUMLOCK_ON;
+ InputRecord[i].Event.KeyEvent.wRepeatCount = 1;
+ InputRecord[i].Event.KeyEvent.bKeyDown = FALSE;
+ InputRecord[i-1] = InputRecord[i];
+ i--;
+ InputRecord[i--].Event.KeyEvent.bKeyDown = TRUE;
+ }
+ }
+
+
+
+
+ /* If buffer is full or
+ * bios buffer is empty and got stuff in buffer
+ * Write it out
+ */
+ if ((BufferHead == BufferTail && i != NUMBBIRECS - 1) || i < 0)
+ {
+ WriteConsoleInputVDMW(sc.InputHandle,
+ &InputRecord[i+1],
+ NUMBBIRECS - i - 1,
+ &dwRecs);
+ i = NUMBBIRECS - 1;
+ }
+ }
+
+
+ sas_storew(BIOS_KB_BUFFER_TAIL, BufferTail);
+
+ return;
+}
+
+
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::: Return key to the console input buffer ::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void ReturnUnusedKeyEvents(int UnusedKeyEvents)
+{
+ INPUT_RECORD InputRecords[MAX_KEY_EVENTS];
+ DWORD RecsWrt;
+ int KeyToRtn, KeyInx;
+
+ /* Return keys to console input buffer */
+
+ if(UnusedKeyEvents)
+ {
+ for(KeyToRtn = 1, KeyInx = UnusedKeyEvents-1;
+ KeyToRtn <= UnusedKeyEvents &&
+ GetHistoryKeyEvent(&InputRecords[KeyInx].Event.KeyEvent,KeyToRtn);
+ KeyToRtn++,KeyInx--)
+ {
+ InputRecords[KeyToRtn - 1].EventType = KEY_EVENT;
+ }
+
+ if(!WriteConsoleInputVDMW(sc.InputHandle,InputRecords,KeyToRtn,&RecsWrt))
+ always_trace0("Console write failed\n");
+ }
+
+ /* Clear down key history buffer and event queue */
+ InitKeyHistory();
+ InitQueue();
+}
+
+
+/*
+ * Attempts to terminate this console group
+ */
+void cmdPushExitInConsoleBuffer (void)
+{
+ if (VDMForWOW) {
+ return;
+ }
+ CntrlHandlerState |= CNTRL_PUSHEXIT;
+
+ /*
+ * Signal all processes in this group that they should be
+ * terminating. Do this by posting a WM_CLOSE message to
+ * the console window, which causes console to send control
+ * close event to all processes.
+ *
+ * The vdm must be able to receive control events from the
+ * console after posting the WM_CLOSE msg since the vdm's
+ * CntrlHandler is still registered. To be safe we do
+ * vdm specific cleanup first, and let the CntrlHandler
+ * do the ExitProcess(). This avoids possible deadlock\race
+ * conditions with the console.
+ */
+ host_applClose();
+ ExitVDM(FALSE,0);
+ PostMessage(hWndConsole, WM_CLOSE, 0,0);
+ ExitThread(0);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::: Calculate no. of keys to return to console input buffer :::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+extern int keys_in_6805_buff(int *part_key_transferred);
+
+int CalcNumberOfUnusedKeyEvents()
+{
+ int part_key_transferred;
+
+ //Get the number of keys in the 6805 buffer
+ return (keys_in_6805_buff(&part_key_transferred) + KeyQueue.KeyCount);
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_fdisk.c b/private/mvdm/softpc.new/host/src/nt_fdisk.c
new file mode 100644
index 000000000..915b26f03
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_fdisk.c
@@ -0,0 +1,760 @@
+
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdddisk.h>
+#include <windows.h>
+#include "insignia.h"
+#include "host_def.h"
+
+/*
+ * [ Product: SoftPC-AT Revision 3.0
+ *
+ * Name: nt_fdisk.c
+ *
+ * Derived From: unix_fdisk.c (Andrew Guthrie/Ade Brownlow)
+ *
+ * Authors: Jerry Sexton
+ *
+ * Created On: 7th August 1991
+ *
+ * Purpose: This module handles the host side of opening, closing,
+ * verfiying and locking hard disks.
+ *
+ * (c)Copyright Insignia Solutions Ltd., 1991. All rights reserved.
+ *
+ * ] */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys\types.h>
+#include "xt.h"
+#include "config.h"
+#include "trace.h"
+#include "error.h"
+#include "nt_uis.h"
+#include "nt_reset.h"
+#include "nt_fdisk.h"
+
+/********************************************************/
+/*
+ * Maximum disk size is 32 Megabytes for DOS. Our disk geometry is based upon
+ * a variable number of cylinders (as per user request when creating a virgin
+ * hard disk) with bytes per sector, sectors per track and heads per drive
+ * fixed as per above. Since a real disk always contains an integral number
+ * of cylinders and since we allow the user to specify disk size at a
+ * granularity of 1 Megabyte, this means we allocate disk space in terms of
+ * an integral number of 30 cylinders (30,60, ...). (30 cylinders is
+ * approximately 1 Megabyte). One disk allocation unit = 30 cylinders. The
+ * max.number of allocation units is 32. For the AT, it is possible to have
+ * larger disks (e.g up to 1024 cylinders and 16 heads). For compatability
+ * with SoftPC Rev.1, we still use Rev.1 limitations on disk geometry
+ */
+#define ONEMEG 1024 * 1024
+#define HD_MAX_DISKALLOCUN 32
+#define HD_SECTORS_PER_TRACK 17
+#define HD_HEADS_PER_DRIVE 4
+#define HD_BYTES_PER_SECTOR 512
+#define HD_SECTORS_PER_CYL (HD_HEADS_PER_DRIVE * HD_SECTORS_PER_TRACK)
+#define HD_BYTES_PER_CYL (HD_BYTES_PER_SECTOR * HD_SECTORS_PER_CYL)
+#define HD_DISKALLOCUNSIZE (HD_BYTES_PER_CYL * 30)
+#define MIN_PARSIZE (HD_SECTORS_PER_TRACK * HD_HEADS_PER_DRIVE * 30)
+#define MAX_PARSIZE (MIN_PARSIZE * HD_MAX_DISKALLOCUN)
+#define SECTORS 0x0c /* offset in buffer for sectors in partition
+ * marker */
+#define MAX_PARTITIONS 5
+#define START_PARTITION 0x1be
+#define SIZE_PARTITION 16
+#define SIGNATURE_LEN 2
+
+
+/*
+ * drive information ... indication of whether file is open; the file
+ * descriptor, and the current file pointer value
+ */
+typedef struct
+{
+ int fd;
+ int valid_fd;
+ int curoffset;
+ SHORT n_cyl;
+ SHORT valid_n_cyl;
+ UTINY n_heads;
+ UTINY valid_n_heads;
+ int n_sect;
+ int valid_n_sect;
+ BOOL open;
+ BOOL valid_open;
+ BOOL readonly;
+ BOOL valid_readonly;
+} DrvInfo;
+
+LOCAL DrvInfo fdiskAdapt[2];
+
+// fail nicely if this is set - should only need to be used for initialisation
+// support. Set in config dependant on CONT_FILE environment var
+//
+LOCAL BOOL DiskValid = FALSE;
+
+GLOBAL VOID host_using_fdisk(BOOL status)
+{
+ DiskValid = status;
+}
+
+GLOBAL SHORT
+host_fdisk_valid
+ (UTINY hostID, ConfigValues *vals, NameTable *table, CHAR *errStr)
+{
+ DrvInfo *adaptP;
+
+ adaptP = fdiskAdapt + (hostID - C_HARD_DISK1_NAME);
+
+ adaptP->n_cyl = (SHORT) 30;
+ adaptP->n_heads = 4;
+ adaptP->n_sect = 17;
+ return C_CONFIG_OP_OK;
+
+}
+
+GLOBAL VOID
+host_fdisk_change(UTINY hostID, BOOL apply)
+{
+ return; // don't bother if no disk.
+}
+
+GLOBAL SHORT
+host_fdisk_active(UTINY hostID, BOOL active, CHAR *errString)
+{
+ return C_CONFIG_OP_OK; // just say it's there...
+}
+
+GLOBAL VOID
+host_fdisk_term(VOID)
+{
+ host_fdisk_change(C_HARD_DISK1_NAME, FALSE);
+ host_fdisk_change(C_HARD_DISK2_NAME, FALSE);
+}
+
+GLOBAL VOID
+host_fdisk_get_params(int driveid, int *n_cyl, int *n_heads, int *n_sect)
+{
+ DrvInfo *adaptP = &fdiskAdapt[driveid];
+
+ *n_cyl = adaptP->n_cyl;
+ *n_heads = adaptP->n_heads;
+ *n_sect = adaptP->n_sect;
+}
+
+GLOBAL VOID
+host_fdisk_seek0(driveid)
+int driveid;
+{
+
+ return; // don't bother if no disk.
+}
+
+/********************************************************/
+/*
+ * Read and write routines (called from diskbios.c & fdisk.c
+ */
+int
+host_fdisk_rd(int driveid, int offset, int nsecs, char *buf)
+{
+ return(0); // no disk...no data
+}
+
+int
+host_fdisk_wt(int driveid, int offset, int nsecs, char *buf)
+{
+ return(0); // no disk...no data
+}
+
+// FDISK support
+
+
+#pragma pack(1)
+
+#define MAX_FDISK_NAME 9
+typedef struct _FDISKDATA {
+ BYTE drive;
+ BYTE idle_counter;
+ CHAR drive_letter;
+ BOOLEAN auto_locked;
+ HANDLE fdisk_fd;
+ DWORD num_heads;
+ LARGE_INTEGER num_cylinders;
+ DWORD sectors_per_track;
+ DWORD bytes_per_sector;
+ DWORD align_factor;
+ USHORT owner_pdb;
+ CHAR device_name[MAX_FDISK_NAME];
+} FDISKDATA, *PFDISKDATA;
+
+
+// Bios Parameter Block (BPB)
+// copied from DEMDASD.H
+typedef struct A_BPB {
+WORD SectorSize; // sector size in bytes
+BYTE ClusterSize; // cluster size in sectors
+WORD ReservedSectors; // number of reserved sectors
+BYTE FATs; // number of FATs
+WORD RootDirs; // number of root directory entries
+WORD Sectors; // number of sectors
+BYTE MediaID; // media descriptor
+WORD FATSize; // FAT size in sectors
+WORD TrackSize; // track size in sectors;
+WORD Heads; // number of heads
+DWORD HiddenSectors; // number of hidden sectors
+DWORD BigSectors; // number of sectors for big media
+} BPB, *PBPB;
+
+typedef struct _BOOTSECTOR {
+ BYTE Jump;
+ BYTE Target[2];
+ BYTE OemName[8];
+ BPB bpb;
+} BOOTSECTOR, * PBOOTSECTOR;
+
+#pragma pack()
+
+
+
+// this is the cylinder size of a 2.88 diskette
+#define MAX_DISKIO_SIZE 0x9000
+#define FDISK_IDLE_PERIOD 30
+PFDISKDATA fdisk_data_table = NULL;
+BYTE number_of_fdisk = 0;
+DWORD max_align_factor = 0;
+DWORD disk_buffer_pool = 0;
+DWORD cur_align_factor;
+WORD fdisk_open_count = 0;
+
+WORD * pFDAccess = 0;
+
+extern USHORT * pusCurrentPDB;
+
+extern int DiskOpenRetry(CHAR);
+
+
+BOOL nt_fdisk_init(
+ BYTE drive,
+ PBPB bpb,
+ PDISK_GEOMETRY disk_geometry
+);
+
+
+
+BOOL nt_fdisk_close(BYTE drive);
+
+PFDISKDATA get_fdisk_data(
+ BYTE drive
+);
+
+BOOL get_fdisk_handle(
+ PFDISKDATA fdisk_data,
+ USHORT pdb,
+ BOOL auto_lock
+);
+
+
+VOID FdiskTerminatePDB(USHORT PDB);
+VOID HostFdiskReset(VOID);
+
+BOOL close_fdisk(
+ PFDISKDATA fdisk_data
+);
+
+
+BOOL nt_fdisk_init(BYTE drive, PBPB bpb, PDISK_GEOMETRY disk_geometry)
+{
+ PFDISKDATA fdisk_data;
+ PUNICODE_STRING unicode_string;
+ ANSI_STRING ansi_string;
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES fdisk_obj;
+ IO_STATUS_BLOCK io_status_block;
+ FSCTL_QUERY_FAT_BPB_BUFFER boot_sector_first_0x24_bytes;
+ HANDLE fd;
+ FILE_ALIGNMENT_INFORMATION align_info;
+ CHAR dos_device_name[] = "\\\\.\\?:";
+ CHAR nt_device_name[] = "\\DosDevices\\?:";
+
+ nt_device_name[12] =
+ dos_device_name[4] = drive + 'A';
+ RtlInitAnsiString( &ansi_string, nt_device_name);
+
+ unicode_string = &NtCurrentTeb()->StaticUnicodeString;
+
+ status = RtlAnsiStringToUnicodeString(unicode_string,
+ &ansi_string,
+ FALSE
+ );
+ if ( !NT_SUCCESS(status) )
+ return FALSE;
+
+
+ InitializeObjectAttributes(
+ &fdisk_obj,
+ unicode_string,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+ status = NtOpenFile(
+ &fd,
+ FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+ &fdisk_obj,
+ &io_status_block,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
+ );
+
+ if (!NT_SUCCESS(status))
+ return FALSE;
+
+ // get geomerty information, the caller wants this
+ status = NtDeviceIoControlFile(fd,
+ 0,
+ NULL,
+ NULL,
+ &io_status_block,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ disk_geometry,
+ sizeof (DISK_GEOMETRY)
+ );
+ if (!NT_SUCCESS(status)) {
+ NtClose(fd);
+ return FALSE;
+ }
+ // get alignment factor
+ status = NtQueryInformationFile(fd,
+ &io_status_block,
+ &align_info,
+ sizeof(FILE_ALIGNMENT_INFORMATION),
+ FileAlignmentInformation
+ );
+
+ if (!NT_SUCCESS(status)) {
+ NtClose(fd);
+ return(FALSE);
+ }
+ if (align_info.AlignmentRequirement > max_align_factor)
+ max_align_factor = align_info.AlignmentRequirement;
+
+
+ /* get BPB, it will fail if the drive is not a FAT partition */
+ status = NtFsControlFile(fd,
+ 0,
+ NULL,
+ NULL,
+ &io_status_block,
+ FSCTL_QUERY_FAT_BPB,
+ NULL,
+ 0,
+ &boot_sector_first_0x24_bytes,
+ sizeof(boot_sector_first_0x24_bytes)
+ );
+ if (!NT_SUCCESS(status)) {
+ NtClose(fd);
+ return (FALSE);
+ }
+
+ *bpb = ((PBOOTSECTOR)&boot_sector_first_0x24_bytes)->bpb;
+
+
+ // enlarge the table
+ fdisk_data = (PFDISKDATA) realloc(fdisk_data_table,
+ (number_of_fdisk + 1) * sizeof(FDISKDATA)
+ );
+ if(fdisk_data == NULL) {
+ NtClose(fd);
+ return FALSE;
+ }
+ fdisk_data_table = fdisk_data;
+ fdisk_data += number_of_fdisk;
+ fdisk_data->drive_letter = drive + 'A';
+ fdisk_data->drive = number_of_fdisk;
+ fdisk_data->fdisk_fd = INVALID_HANDLE_VALUE;
+ fdisk_data->num_heads = disk_geometry->TracksPerCylinder;
+ fdisk_data->sectors_per_track = disk_geometry->SectorsPerTrack;
+ fdisk_data->bytes_per_sector = disk_geometry->BytesPerSector;
+ fdisk_data->num_cylinders = disk_geometry->Cylinders;
+ fdisk_data->align_factor = align_info.AlignmentRequirement;
+ strcpy(fdisk_data->device_name, dos_device_name);
+ number_of_fdisk++;
+ NtClose(fd);
+ return TRUE;
+}
+
+
+ULONG nt_fdisk_read(
+ BYTE drive,
+ PLARGE_INTEGER offset,
+ ULONG size,
+ PBYTE buffer
+)
+{
+ PFDISKDATA fdisk_data;
+ ULONG size_returned = 0;
+
+ if ((fdisk_data = get_fdisk_data(drive)) == NULL)
+ return 0;
+ if (get_fdisk_handle(fdisk_data, *pusCurrentPDB, FALSE))
+ return(disk_read(fdisk_data->fdisk_fd,
+ offset,
+ size,
+ buffer));
+}
+
+
+ULONG nt_fdisk_write(
+ BYTE drive,
+ PLARGE_INTEGER offset,
+ ULONG size,
+ PBYTE buffer
+)
+{
+ PFDISKDATA fdisk_data;
+ ULONG size_returned = 0;
+
+ if ((fdisk_data = get_fdisk_data(drive)) == NULL)
+ return 0;
+
+ if (get_fdisk_handle(fdisk_data, *pusCurrentPDB, TRUE)) {
+ // must lock the drive. This is very important.
+ size_returned = disk_write(fdisk_data->fdisk_fd,
+ offset,
+ size,
+ buffer);
+ }
+ return size_returned;
+}
+
+
+BOOL nt_fdisk_verify(
+ BYTE drive,
+ PLARGE_INTEGER offset,
+ ULONG size
+)
+{
+
+ PFDISKDATA fdisk_data;
+ ULONG size_returned = 0;
+ VERIFY_INFORMATION verify_info;
+
+ if ((fdisk_data = get_fdisk_data(drive)) == NULL)
+ return FALSE;
+
+ if (get_fdisk_handle(fdisk_data, *pusCurrentPDB, FALSE)) {
+ verify_info.StartingOffset = *offset;
+ verify_info.Length = size;
+ return(DeviceIoControl(fdisk_data->fdisk_fd,
+ IOCTL_DISK_VERIFY,
+ &verify_info,
+ sizeof(VERIFY_INFORMATION),
+ NULL,
+ 0,
+ &size_returned,
+ NULL
+ ));
+ }
+
+}
+
+
+
+BOOL nt_fdisk_close(BYTE drive)
+{
+ PFDISKDATA fdisk_data;
+ if ((fdisk_data = get_fdisk_data(drive)) == NULL)
+ return FALSE;
+ return(close_fdisk(fdisk_data));
+}
+
+
+BOOL close_fdisk(PFDISKDATA fdisk_data)
+{
+
+ if (fdisk_data->fdisk_fd != INVALID_HANDLE_VALUE){
+ CloseHandle(fdisk_data->fdisk_fd);
+ fdisk_data->auto_locked = FALSE;
+ fdisk_data->fdisk_fd = INVALID_HANDLE_VALUE;
+ fdisk_data->owner_pdb = 0;
+ (*(pFDAccess))--;
+ fdisk_open_count--;
+ }
+ return TRUE;
+}
+
+
+
+PFDISKDATA get_fdisk_data(BYTE drive)
+{
+
+ WORD i;
+
+ for (i = 0; i < number_of_fdisk; i++)
+ if (fdisk_data_table[i].drive == drive)
+ return &fdisk_data_table[i];
+ return NULL;
+}
+
+
+BOOL get_fdisk_handle(PFDISKDATA fdisk_data, USHORT pdb, BOOL auto_lock)
+{
+
+ DWORD share_access;
+ DWORD last_error;
+
+
+
+ if (fdisk_data->fdisk_fd != INVALID_HANDLE_VALUE &&
+ ((auto_lock && !fdisk_data->auto_locked) || fdisk_data->owner_pdb != pdb))
+
+ close_fdisk(fdisk_data);
+
+ share_access = (auto_lock) ? FILE_SHARE_READ :
+ FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ while (fdisk_data->fdisk_fd == INVALID_HANDLE_VALUE) {
+
+ fdisk_data->fdisk_fd = CreateFile (fdisk_data->device_name,
+ SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
+ share_access,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ 0
+ );
+ if (fdisk_data->fdisk_fd != INVALID_HANDLE_VALUE) {
+ fdisk_data->auto_locked = auto_lock;
+ fdisk_data->owner_pdb = pdb;
+ fdisk_open_count++;
+ (*(pFDAccess))++;
+ break;
+ }
+ else {
+ last_error = GetLastError();
+
+ if (last_error == ERROR_SHARING_VIOLATION &&
+ DiskOpenRetry(fdisk_data->drive_letter) == RMB_RETRY)
+ continue;
+ else if (last_error == ERROR_ACCESS_DENIED) {
+ /* the user doesn't have enough privilege to
+ * directly access the drive, display the pop up
+ * "terminate" ->terminate ntvdm process
+ * "ignore" -> fail the call and let application
+ * handles the error.
+ */
+
+ host_direct_access_error((ULONG)NOSUPPORT_HARDDISK);
+ break;
+ }
+ else
+ /* simply fail the call for other error conditions */
+ break;
+
+ }
+
+ }
+
+ if(fdisk_data->fdisk_fd != INVALID_HANDLE_VALUE) {
+ // have the current align factor updated
+ cur_align_factor = fdisk_data->align_factor;
+ }
+ fdisk_data->idle_counter = FDISK_IDLE_PERIOD;
+
+ return(!(fdisk_data->fdisk_fd == INVALID_HANDLE_VALUE));
+}
+
+void fdisk_heart_beat(void)
+{
+ WORD i;
+ PFDISKDATA fdisk_data;
+ if (fdisk_open_count != 0) {
+ for (i = 0; i < number_of_fdisk; i++) {
+ fdisk_data = &fdisk_data_table[i];
+ if(fdisk_data->fdisk_fd != INVALID_HANDLE_VALUE &&
+ --fdisk_data->idle_counter == 0){
+ close_fdisk(fdisk_data);
+ }
+ }
+ }
+}
+
+
+VOID HostFdiskReset(VOID)
+{
+ FdiskTerminatePDB((USHORT)0);
+}
+
+VOID FdiskTerminatePDB(USHORT PDB)
+{
+ WORD i;
+ PFDISKDATA fdisk_data;
+
+ if (fdisk_open_count != 0) {
+ for(i = 0; i < number_of_fdisk; i++) {
+ fdisk_data = &fdisk_data_table[i];
+ if (fdisk_data->fdisk_fd != INVALID_HANDLE_VALUE &&
+ (PDB == 0 || fdisk_data->owner_pdb == PDB)) {
+ close_fdisk(fdisk_data);
+ }
+ }
+ }
+
+
+}
+// Generic disk read.
+// this function takes care of buffer alignment requirement(cur_align_factor)
+// and split the calls to file system if the given size is larger than
+// MAX_DISKIO_SIZE -- File system may fail the request if the size
+// is too big. We create a buffer worhty for 36KB(cylinder size of a
+// 2.88 floppy) the first time application touch disks.
+
+ULONG disk_read(
+ HANDLE fd,
+ PLARGE_INTEGER offset,
+ DWORD size,
+ PBYTE buffer
+)
+{
+ PBYTE read_buffer;
+ DWORD block_size;
+ DWORD size_returned;
+ DWORD read_size;
+
+ if (fd == INVALID_HANDLE_VALUE ||
+ (SetFilePointer(fd, offset->LowPart, &offset->HighPart,
+ FILE_BEGIN) == 0xFFFFFFFF))
+ {
+ return 0;
+ }
+ block_size = (size <= MAX_DISKIO_SIZE) ? size : MAX_DISKIO_SIZE;
+
+ // if the given buffer is not aligned, use our buffer and do a
+ // double copy
+ if (cur_align_factor != 0) {
+ read_buffer = get_aligned_disk_buffer();
+ if (read_buffer == NULL)
+ return 0;
+ }
+ else {
+ read_buffer = buffer;
+ }
+ read_size = 0;
+ while (size != 0) {
+ if (size < block_size)
+ block_size = size;
+ if (!ReadFile(fd, (PVOID)read_buffer, block_size, &size_returned, 0)
+ || size_returned != block_size)
+ break;
+ if(cur_align_factor != 0) {
+ // read operation, read and then copy
+ memcpy(buffer, (PVOID)read_buffer, block_size);
+ buffer += block_size;
+ }
+ else
+ read_buffer += block_size;
+ size -= block_size;
+ read_size += block_size;
+ }
+ return read_size;
+}
+
+ULONG disk_write(
+ HANDLE fd,
+ PLARGE_INTEGER offset,
+ DWORD size,
+ PBYTE buffer
+)
+{
+ PBYTE write_buffer;
+ DWORD block_size;
+ DWORD size_returned;
+ DWORD written_size;
+
+ if (fd == INVALID_HANDLE_VALUE ||
+ (SetFilePointer(fd, offset->LowPart, &offset->HighPart,
+ FILE_BEGIN) == 0xFFFFFFFF))
+ {
+ return 0;
+ }
+ block_size = (size <= MAX_DISKIO_SIZE) ? size : MAX_DISKIO_SIZE;
+
+ // if the given buffer is not aligned, use our buffer and do a
+ // double copy
+ if (cur_align_factor != 0 &&
+ (write_buffer = get_aligned_disk_buffer()) == NULL)
+ return 0;
+ written_size = 0;
+ while (size != 0) {
+ if (size < block_size)
+ block_size = size;
+ if(cur_align_factor != 0)
+ // write operation, copy and then write
+ memcpy((PVOID)write_buffer, buffer, block_size);
+ else
+ write_buffer = buffer;
+
+ if (!WriteFile(fd, (PVOID)write_buffer, block_size, &size_returned, 0)
+ || size_returned != block_size)
+ break;
+ size -= block_size;
+ buffer += block_size;
+ written_size += block_size;
+ }
+ return written_size;
+}
+
+// Hard disk verify actually goes to file system directly because
+// the IOCTL_DISK_VERIFY will do the work. This ioctl doesn't work for
+// floppy. This function is mainly provided for floppy verify.
+BOOL disk_verify(
+ HANDLE fd,
+ PLARGE_INTEGER offset,
+ DWORD size
+)
+{
+ PBYTE verify_buffer;
+ DWORD block_size;
+ DWORD size_returned;
+
+ if (fd == INVALID_HANDLE_VALUE ||
+ (SetFilePointer(fd, offset->LowPart, &offset->HighPart,
+ FILE_BEGIN) == 0xFFFFFFFF))
+ {
+ return FALSE;
+ }
+ block_size = (size <= MAX_DISKIO_SIZE) ? size : MAX_DISKIO_SIZE;
+ // if this is the first time application do a real work,
+ // allocate the buffer
+ if ((verify_buffer = get_aligned_disk_buffer()) == NULL)
+ return FALSE;
+ while (size != 0) {
+ if (size < block_size)
+ block_size = size;
+ if (!ReadFile(fd, (PVOID)verify_buffer, block_size, &size_returned, 0)
+ || size_returned != block_size)
+ {
+ return FALSE;
+ }
+ size -= block_size;
+ }
+ return TRUE;
+}
+
+PBYTE get_aligned_disk_buffer(void)
+{
+ // if we don't have the buffer yet, get it
+ if (disk_buffer_pool == 0) {
+ disk_buffer_pool = (DWORD) malloc(MAX_DISKIO_SIZE + max_align_factor);
+ if (disk_buffer_pool == 0)
+ return NULL;
+ }
+ return((PBYTE)((disk_buffer_pool + cur_align_factor) & ~(cur_align_factor)));
+
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_fulsc.c b/private/mvdm/softpc.new/host/src/nt_fulsc.c
new file mode 100644
index 000000000..1fbe4ced0
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_fulsc.c
@@ -0,0 +1,2415 @@
+#include <windows.h>
+#include "host_def.h"
+#include "insignia.h"
+
+/*
+ * ==========================================================================
+ * Name: nt_fulsc.c
+ * Author: Jerry Sexton
+ * Derived From:
+ * Created On: 27th January 1992
+ * Purpose: This module contains the code required to handle
+ * transitions between graphics and text modes, and
+ * windowed and full-screen displays for SoftPC running
+ * under the x86 monitor.
+ *
+ * (c)Copyright Insignia Solutions Ltd., 1992. All rights reserved.
+ * ==========================================================================
+ */
+
+/*
+ * ==========================================================================
+ * Other Includes
+ * ==========================================================================
+ */
+#ifdef X86GFX
+#include <ntddvdeo.h>
+#endif
+#include <vdm.h>
+#include <stdlib.h>
+#include <string.h>
+#include "conapi.h"
+
+#include "xt.h"
+#include CpuH
+#include "gvi.h"
+#include "gmi.h"
+#include "gfx_upd.h"
+#include "video.h"
+#include "egacpu.h"
+#include "egavideo.h"
+#include "egagraph.h"
+#include "egaports.h"
+#include "egamode.h"
+#include "ckmalloc.h"
+#include "sas.h"
+#include "ica.h"
+#include "ios.h"
+#include "config.h"
+#include "idetect.h"
+#include "debug.h"
+
+#include "nt_thred.h"
+#include "nt_fulsc.h"
+#include "nt_graph.h"
+#include "nt_uis.h"
+#include "host_rrr.h"
+#include "nt_det.h"
+#include "nt_mouse.h"
+#include "nt_event.h"
+#include "ntcheese.h"
+#include "nt_eoi.h"
+#include "nt_reset.h"
+
+/*
+ * ==========================================================================
+ * Global Data
+ * ==========================================================================
+ */
+GLOBAL BOOL ConsoleInitialised = FALSE;
+GLOBAL BOOL ConsoleNoUpdates = FALSE;
+#ifdef X86GFX
+GLOBAL BOOL BiosModeChange = FALSE;
+GLOBAL DWORD mouse_buffer_width = 0,
+ mouse_buffer_height = 0;
+#endif /* X86GFX */
+GLOBAL BOOL blocked_in_gfx_mode = FALSE; /* need to force text mode? */
+#ifndef PROD
+GLOBAL UTINY FullScreenDebug = FALSE;
+#endif /* PROD */
+
+/* We have to prevent bad values from oddball video cards (eg Prodesigner II
+ * EISA) from blatting us before we can load our private baby mode table in
+ * ntio.sys. We have to keep another copy to be copied into memory to prevent
+ * this. We should only need modes 3 & b.
+ */
+GLOBAL UTINY tempbabymode[] =
+/* 80x25 stuff */
+ {
+ 0x50, 0x18, 0x10, 0x00, 0x10, 0x00, 0x03, 0x00, 0x02, 0x67,
+ 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f,
+ 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x8e, 0x8f, 0x28,
+ 0x1f, 0x96, 0xb9, 0xa3, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+ 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x0e, 0x00, 0xff,
+/* mode b stuff */
+ 0x5e, 0x32, 0x08, 0x00, 0x97, 0x01, 0x0f, 0x00, 0x06, 0xe7,
+ 0x6d, 0x5d, 0x5e, 0x90, 0x61, 0x8f, 0xbf, 0x1f, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x8e, 0x99, 0x2f,
+ 0x00, 0xa1, 0xb9, 0xe3, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+ 0x3f, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x05, 0x0f, 0xff
+};
+
+/*
+ * ==========================================================================
+ * Local Data
+ * ==========================================================================
+ */
+
+/* The resolution and font-size at start-up. */
+LOCAL COORD startUpResolution;
+LOCAL COORD startUpFontSize;
+
+/* General purpose console buffer. */
+LOCAL CHAR_INFO consoleBuffer[MAX_CONSOLE_SIZE];
+
+LOCAL BOOL WinFrozen = FALSE;
+
+/* Console info from startup which is needed for synchronisation */
+LOCAL int ConVGAHeight;
+LOCAL int ConTopLine;
+
+/* saved information for console re-integration */
+LOCAL CONSOLE_SCREEN_BUFFER_INFO ConsBufferInfo;
+LOCAL StartupCharHeight;
+
+LOCAL half_word saved_text_lines; /* No of lines for last SelectMouseBuffer. */
+
+
+/* Variable to check for changes in screen state. */
+GLOBAL DWORD savedScreenState;
+BOOL nt_init_called = 0;
+
+IMPORT CONSOLE_CURSOR_INFO StartupCursor;
+
+IMPORT void low_set_mode(int);
+IMPORT VOID recalc_text(int);
+IMPORT VOID enable_gfx_update_routines(VOID);
+IMPORT VOID disable_gfx_update_routines(VOID);
+#ifdef X86GFX
+IMPORT void vga_misc_inb(io_addr, half_word *);
+#endif /* X86GFX */
+
+
+/*
+ * ==========================================================================
+ * Local Function Declarations
+ * ==========================================================================
+ */
+VOID enableUpdates(VOID);
+VOID disableUpdates(VOID);
+VOID copyConsoleToRegen(SHORT, SHORT, SHORT, SHORT);
+VOID getVDMCursorPosition(VOID);
+VOID setVDMCursorPosition(UTINY, PCOORD);
+VOID waitForInputFocus(VOID);
+GLOBAL int getModeType(VOID);
+#ifdef X86GFX
+VOID AddTempIVTFixups(VOID);
+VOID GfxReset(VOID);
+#endif /* X86GFX */
+
+/*
+ * ==========================================================================
+ * Global Functions
+ * ==========================================================================
+ */
+
+GLOBAL VOID nt_init_event_thread(VOID)
+{
+ note_entrance0("nt_init_event_thread");
+
+ /*
+ * May be called more than once, if event thread enters
+ * resume\block code before normally intialized
+ */
+ if (nt_init_called)
+ return;
+ else
+ nt_init_called++;
+
+
+ if (sc.ScreenState != STREAM_IO) {
+ /*
+ ** Copy the console buffer to the regen buffer.
+ ** Don't want to adjust the copy from top of console window, console
+ ** does it itself if we resize the window. Tim September 92.
+ */
+ copyConsoleToRegen(0, 0, VGA_WIDTH, (SHORT)ConVGAHeight);
+
+ /*
+ ** Tim September 92, adjust cursor position if console window size is
+ ** adjusted.
+ */
+ ConsBufferInfo.dwCursorPosition.Y -= ConTopLine;
+
+ /* Set up SoftPC's cursor. */
+ setVDMCursorPosition((UTINY)StartupCharHeight,
+ &ConsBufferInfo.dwCursorPosition);
+
+ if (sc.ScreenState == WINDOWED)
+ enableUpdates();
+ }
+ else
+ enableUpdates();
+
+ // set kbd state flags in biosdata area, according to the real kbd Leds
+ if (!VDMForWOW) {
+ SyncBiosKbdLedToKbdDevice();
+ // we have sync up the BIOS led states with the system, we now let the
+ // event thread go
+ ResumeThread(ThreadInfo.EventMgr.Handle);
+ }
+
+ KbdResume(); // JonLe Mod
+}
+
+
+#ifdef X86GFX
+/*
+* Find the address of the ROM font, load it up into the correct
+* portion of the regen area and set Int 43 to point to it.
+*
+* Size of font we are loading is known, so don't listen to what
+* the native BIOS returns to us in CX. BIOS might be returning
+* character height we set in recalc_text() above. Tim Oct 92.
+*/
+
+NativeFontAddr nativeFontAddresses[6]; /* pointers to native BIOS ROM fonts */
+ /* 8x14, 8x8 pt1, 8x8 pt2, 9x14, 8x16 and 9x16 */
+
+
+#define GET_BIOS_FONT_ADDRESS(FontIndex) \
+ (((sys_addr)nativeFontAddresses[FontIndex].seg << 4) + \
+ (sys_addr)nativeFontAddresses[FontIndex].off)
+
+/*
+*****************************************************************************
+** locateNativeBIOSfonts() X86 only.
+*****************************************************************************
+** Get the addresses of the BIOS ROM fonts. (Insignia video ROM not loaded)
+** ntdetect.com runs the INT 10 to look the addresses up on system boot and
+** stores them in page 0 at 700.
+** This function is called once on startup X86 only. It gets the addresses of
+** the native ROM fonts and stores them in the nativeFontAddresses[] array.
+*/
+VOID locateNativeBIOSfonts IFN0()
+{
+ int i;
+ sys_addr font_off = 0x700; /* Magic place used by ntdetect.com */
+
+ for(i = 0; i < 6; i++)
+ {
+ sas_loadw(font_off, &nativeFontAddresses[i].off);
+ sas_loadw(font_off+2, &nativeFontAddresses[i].seg);
+ font_off += 4;
+ }
+} /* end of locateNativeBIOSfonts() */
+
+/*
+****************************************************************************
+** loadNativeBIOSfont() X86 only.
+****************************************************************************
+** Loads the appropriate font, specified by current window size, into the
+** font area in video RAM.
+** This function is called on every windowed startup and resume. *Never* on
+** a full-screen startup or resume. The font is loaded so that it will be
+** available for full-screen text mode, but easier to load when windowed.
+** Remember a mode change will load the corect font.
+*/
+VOID loadNativeBIOSfont IFN1( int, vgaHeight )
+{
+ sys_addr fontadd; // location of font
+ UTINY *regenptr; // destination in video
+ int cellsize; // individual character size
+ int skip; // gap between characters
+ int loop, pool;
+ UINT OutputCP;
+
+
+ /*
+ ** ordered this way as 80x50 console is default
+ ** VGA_HEIGHT_4 = 50
+ ** VGA_HEIGHT_3 = 43
+ ** VGA_HEIGHT_2 = 28
+ ** VGA_HEIGHT_1 = 25
+ ** VGA_HEIGHT_0 = 22
+ */
+ if (vgaHeight == VGA_HEIGHT_4 || vgaHeight == VGA_HEIGHT_3){
+ cellsize = 8;
+ fontadd = GET_BIOS_FONT_ADDRESS(F8x8pt1);
+ }else
+ if (vgaHeight == VGA_HEIGHT_2){
+ cellsize = 14;
+ fontadd = GET_BIOS_FONT_ADDRESS(F8x14);
+ }else{
+ cellsize = 16;
+ fontadd = GET_BIOS_FONT_ADDRESS(F8x16);
+ }
+
+ // set Int 43 to point to font
+ sas_storew(0x43 * 4, (word)(fontadd & 0xffff));
+ sas_storew(0x43 * 4 + 2, (word)(fontadd >> 4 & 0xf000));
+
+/* BUGBUG, williamh
+ We should have set int43 to the new font read from the CPI font.
+ This would require at least 4KB buffer in real mode address space.
+ The question is who is going to use this vector? So far, we haven't found
+ any applications use the vector(ROM BIOS is okay because the set video mode
+ function will reset the font and our new font will be lost anyway).
+
+*/
+
+ if (!sc.Registered || (OutputCP = GetConsoleOutputCP()) == 437 ||
+ !LoadCPIFont(OutputCP, (WORD)8, (WORD)cellsize)) {
+ // now load it into the regen memory. We load it in at a0000 where
+ // an app will have to get to it. Luckily, this means we don't
+ // conflict with the text on the screen
+
+ skip = 32 - cellsize;
+
+ regenptr = (half_word *)0xa0000;
+
+ if (cellsize == 8) /* 8x8 font comes in two halves */
+ {
+ for (loop = 0; loop < 128; loop++)
+ {
+ for (pool = 0; pool < cellsize; pool++)
+ *regenptr++ = *(UTINY *)fontadd++;
+ regenptr += skip;
+ }
+ fontadd = GET_BIOS_FONT_ADDRESS(F8x8pt2);
+ for (loop = 0; loop < 128; loop++)
+ {
+ for (pool = 0; pool < cellsize; pool++)
+ *regenptr++ = *(UTINY *)fontadd++;
+ regenptr += skip;
+ }
+ }
+ else
+ {
+ for (loop = 0; loop < 256; loop++)
+ {
+ for (pool = 0; pool < cellsize; pool++)
+ *regenptr++ = *(UTINY *)fontadd++;
+ regenptr += skip;
+ }
+ }
+ }
+} /* end of loadNativeBIOSfont() */
+
+/* this function loads font data from EGA.CPI file located at %systemroot%\system32.
+ It is the same file console server used to load ROM font when the video
+ is in full screen. This function covers code page 437(ROM default). However,
+ the caller should make its best decision to call this function if the
+ output code page is not 437. This function doesn't care what code page
+ was provided.
+ The font size are limitted to(an assumption made by nt video driver and
+ the console server):
+ ** width must be 8 pixels.
+ ** Height must less or equal to 16 pixels.
+
+*/
+
+
+
+BOOL LoadCPIFont(UINT CodePageID, WORD FontWidth, WORD FontHeight)
+{
+ BYTE Buffer[16 * 256];
+ DWORD dw, BytesRead, FilePtr;
+ BYTE *VramAddr, *pSrc;
+ DWORD nChars;
+ PCPIFILEHEADER pCPIFileHeader = (PCPIFILEHEADER)Buffer;
+ PCPICODEPAGEHEADER pCPICodePageHeader = (PCPICODEPAGEHEADER) Buffer;
+ PCPICODEPAGEENTRY pCPICodePageEntry = (PCPICODEPAGEENTRY) Buffer;
+ PCPIFONTHEADER pCPIFontHeader = (PCPIFONTHEADER) Buffer;
+ PCPIFONTDATA pCPIFontData = (PCPIFONTDATA) Buffer;
+ BOOL bDOSCPI = FALSE;
+ HANDLE hCPIFile;
+
+ /* max font height is 16 pixels and font width must be 8 pixels */
+ if (FontHeight > 16 || FontWidth != 8)
+ return FALSE;
+ dw = GetSystemDirectoryA((CHAR *)Buffer, sizeof(Buffer));
+ if (dw == 0 || dw + CPI_FILENAME_LENGTH > sizeof(Buffer))
+ return FALSE;
+ RtlMoveMemory(&Buffer[dw], CPI_FILENAME, CPI_FILENAME_LENGTH);
+ // the file must be opened in READONLY mode or the CreateFileA will fail
+ // because the console sevrer always keeps an opened handle to the file
+ // and the file is opened READONLY.
+
+ hCPIFile = CreateFileA(Buffer, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (hCPIFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!ReadFile(hCPIFile, Buffer, sizeof(CPIFILEHEADER), &BytesRead, NULL) ||
+ BytesRead != sizeof(CPIFILEHEADER)) {
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ if (memcmp(pCPIFileHeader->Signature, CPI_SIGNATURE_NT, CPI_SIGNATURE_LENGTH))
+ {
+ if (memcmp(pCPIFileHeader->Signature, CPI_SIGNATURE_DOS,CPI_SIGNATURE_LENGTH))
+ {
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ else
+ bDOSCPI = TRUE;
+ }
+
+ // move the file pointer to the code page table header
+ FilePtr = pCPIFileHeader->OffsetToCodePageHeader;
+ if (SetFilePointer(hCPIFile, FilePtr, NULL, FILE_BEGIN) == (DWORD) -1){
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+
+ if (!ReadFile(hCPIFile, Buffer, sizeof(CPICODEPAGEHEADER), &BytesRead, NULL) ||
+ BytesRead != sizeof(CPICODEPAGEHEADER)) {
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ // how many code page entries in the file
+ dw = pCPICodePageHeader->NumberOfCodePages;
+ FilePtr += BytesRead;
+
+ // serach for the specific code page
+ while (dw > 0 &&
+ ReadFile(hCPIFile, Buffer, sizeof(CPICODEPAGEENTRY), &BytesRead, NULL) &&
+ BytesRead == sizeof(CPICODEPAGEENTRY)) {
+ if (pCPICodePageEntry->CodePageID == CodePageID)
+ break;
+ if (dw > 1) {
+ if (!bDOSCPI)
+ FilePtr += pCPICodePageEntry->OffsetToNextCodePageEntry;
+ else
+ FilePtr = pCPICodePageEntry->OffsetToNextCodePageEntry;
+
+ if (SetFilePointer(hCPIFile, FilePtr, NULL, FILE_BEGIN) == (DWORD) -1) {
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ }
+ dw--;
+ }
+ if (dw == 0) {
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ // seek to the font header for the code page
+ if (!bDOSCPI)
+ FilePtr += pCPICodePageEntry->OffsetToFontHeader;
+ else
+ FilePtr = pCPICodePageEntry->OffsetToFontHeader;
+ if (SetFilePointer(hCPIFile, FilePtr, NULL, FILE_BEGIN) == (DWORD) -1) {
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ if (!ReadFile(hCPIFile, Buffer, sizeof(CPIFONTHEADER), &BytesRead, NULL) ||
+ BytesRead != sizeof(CPIFONTHEADER)){
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ // number of fonts with the specific code page
+ dw = pCPIFontHeader->NumberOfFonts;
+
+ while(dw != 0 &&
+ ReadFile(hCPIFile, Buffer, sizeof(CPIFONTDATA), &BytesRead, NULL) &&
+ BytesRead == sizeof(CPIFONTDATA))
+ {
+ if (pCPIFontData->FontHeight == FontHeight &&
+ pCPIFontData->FontWidth == FontWidth)
+ {
+ nChars = pCPIFontData->NumberOfCharacters;
+ if (ReadFile(hCPIFile, Buffer, nChars * FontHeight, &BytesRead, NULL) &&
+ BytesRead == nChars * FontHeight)
+ break;
+ else {
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ }
+ else {
+ if (SetFilePointer(hCPIFile,
+ (DWORD)pCPIFontData->NumberOfCharacters * (DWORD)pCPIFontData->FontHeight,
+ NULL,
+ FILE_CURRENT) == (DWORD) -1) {
+ CloseHandle(hCPIFile);
+ return FALSE;
+ }
+ dw--;
+ }
+ }
+ if (dw != 0) {
+ VramAddr = (BYTE *)0xa0000;
+ pSrc = Buffer;
+ for(dw = nChars; dw > 0; dw--) {
+ RtlMoveMemory(VramAddr, pSrc, FontHeight);
+ pSrc += FontHeight;
+ // font in VRAM is always 32 bytes
+ VramAddr += 32;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+#endif /* X86GFX */
+
+/*
+***************************************************************************
+** calcScreenParams(), setup our screen screen parameters as determined
+** by current Console state.
+** Called from ConsoleInit() and DoFullScreenResume().
+** Returns current character height (8,14,16) and lines (22-50).
+** Tim Jan 93, extracted common code from init and resume funx.
+***************************************************************************
+*/
+GLOBAL VOID calcScreenParams IFN2( USHORT *, pCharHeight, USHORT *, pVgaHeight )
+{
+ USHORT consoleWidth,
+ consoleHeight,
+ vgaHeight,
+ charHeight,
+ scanLines;
+ half_word temp;
+
+ /* Get console information. */
+ if (!GetConsoleScreenBufferInfo(sc.OutputHandle, &ConsBufferInfo))
+ ErrorExit();
+
+ /* Now sync the SoftPC screen to the console. */
+ if (sc.ScreenState == WINDOWED)
+ {
+ consoleWidth = ConsBufferInfo.srWindow.Right -
+ ConsBufferInfo.srWindow.Left + 1;
+ consoleHeight = ConsBufferInfo.srWindow.Bottom -
+ ConsBufferInfo.srWindow.Top + 1;
+ }
+#ifdef X86GFX
+ else /* FULLSCREEN */
+ {
+ if (!GetConsoleHardwareState(sc.OutputHandle,
+ &startUpResolution,
+ &startUpFontSize))
+ ErrorExit();
+ consoleWidth = startUpResolution.X / startUpFontSize.X;
+ consoleHeight = startUpResolution.Y / startUpFontSize.Y;
+ }
+#endif
+
+ /*
+ * Set the display to the nearest VGA text mode size, which is one of
+ * 80x22, 80x25, 80x28, 80x43 or 80x50.
+ */
+ if (consoleHeight <= MID_VAL(VGA_HEIGHT_0, VGA_HEIGHT_1))
+ {
+ /* 22 lines */
+ vgaHeight = VGA_HEIGHT_0;
+ scanLines = 351;
+ charHeight = 16;
+ }
+ else if (consoleHeight <= MID_VAL(VGA_HEIGHT_1, VGA_HEIGHT_2))
+ {
+ /* 25 lines */
+ vgaHeight = VGA_HEIGHT_1;
+ scanLines = 399;
+ charHeight = 16;
+ }
+ else if (consoleHeight <= MID_VAL(VGA_HEIGHT_2, VGA_HEIGHT_3))
+ {
+ /* 28 lines */
+ vgaHeight = VGA_HEIGHT_2;
+ scanLines = 391;
+ charHeight = 14;
+ }
+ else if (consoleHeight <= MID_VAL(VGA_HEIGHT_3, VGA_HEIGHT_4))
+ {
+ /* 43 lines */
+ vgaHeight = VGA_HEIGHT_3;
+ scanLines = 349;
+ charHeight = 8;
+ }
+ else
+ {
+ /* 50 lines */
+ vgaHeight = VGA_HEIGHT_4;
+ scanLines = 399;
+ charHeight = 8;
+ }
+
+ if (sc.ScreenState == WINDOWED)
+ {
+ /* The app may have shutdown in a gfx mode - force text mode back */
+ if (blocked_in_gfx_mode)
+ {
+ low_set_mode(3);
+ inb(EGA_IPSTAT1_REG,&temp);
+ outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE); /* re-enable video */
+ (*choose_display_mode)();
+ blocked_in_gfx_mode = FALSE;
+ }
+ /*
+ * Set screen height appropriately for current window size.
+ * Now call video routine to set the character height, updating the
+ * BIOS RAM as it does so.
+ */
+ set_screen_height_recal( scanLines ); /* Tim Oct 92 */
+ recalc_text(charHeight);
+
+ /* badly written apps assume 25 line mode page len is 4096 */
+ if (vgaHeight == 25)
+ sas_storew_no_check(VID_LEN, 0x1000);
+#ifdef X86GFX
+ loadNativeBIOSfont( vgaHeight );
+#endif /* X86GFX */
+
+ }
+#ifdef X86GFX
+ else /* FULLSCREEN */
+ {
+ // Can't see why we wouldn't want this for resume too.
+ // set_char_height( startUpFontSize.Y ); /* Tim Oct 92 */
+
+ /* clear this condition on fullscreen resume */
+ blocked_in_gfx_mode = FALSE;
+
+ /*
+ ** Adjust height appropriately, Tim September 92.
+ ** In full-screen lines is 21 cos 22x16=352, slightly too big.
+ */
+ if( vgaHeight==22 )
+ vgaHeight = 21;
+ charHeight = startUpFontSize.Y;
+ sas_store_no_check(ega_char_height, (half_word) charHeight);
+ sas_store_no_check(vd_rows_on_screen, (half_word) (vgaHeight - 1));
+ /* compatibility with bios 80x25 startup */
+ if (vgaHeight == 25)
+ sas_storew_no_check(VID_LEN, 0x1000);
+ else
+ sas_storew_no_check(VID_LEN, (word) ((vgaHeight + 1) *
+ sas_w_at_no_check(VID_COLS) * 2));
+ }
+#endif /* X86GFX */
+ sas_storew_no_check(VID_COLS, 80); // fixup from 40 char shutdown
+ *pCharHeight = charHeight;
+ *pVgaHeight = vgaHeight;
+
+} /* end of calcScreenParams() */
+
+/***************************************************************************
+ * Function: *
+ * ConsoleInit *
+ * *
+ * Description: *
+ * Does all the graphics work required on SoftPC start-up. *
+ * Will split or modify later to accomodate the SCS initialisation *
+ * that loses the config.sys etc output. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID ConsoleInit(VOID)
+{
+ USHORT charHeight, vgaHeight, cursorLine, topLine;
+
+ note_entrance0("ConsoleInit");
+
+#ifdef X86GFX
+
+ /* Now GetROMsMapped called from config after sas_init */
+
+ /*
+ * Set emulation to a known state when starting up windowed. This has to
+ * be done after the ROMS are mapped but before we start to look at
+ * things like BIOS variables.
+ */
+ GfxReset();
+
+#endif
+ initTextSection();
+
+ /*
+ * Set up input focus details (we do it here as the fullscreen stuff
+ * is what is really interested in it).
+ */
+ sc.Focus = TRUE;
+ sc.FocusEvent = CreateEvent((LPSECURITY_ATTRIBUTES) NULL,
+ FALSE,
+ FALSE,
+ NULL);
+
+#ifdef X86GFX
+#ifdef SEPARATE_DETECT_THREAD
+ /* Create screen state transition detection thread. */
+ CreateDetectThread();
+#endif /* SEPARATE_DETECT_THREAD */
+#endif /* X86GFX */
+
+ /*
+ * We don't want to call paint routines until config.sys processed or if
+ * the monitor is writing directly to the frame buffer (fullscreen), so...
+ */
+ disableUpdates();
+
+ /*
+ ** Get console window size and set up our stuff accordingly.
+ */
+ calcScreenParams( &charHeight, &vgaHeight );
+
+ StartupCharHeight = charHeight;
+#ifdef X86GFX
+ if( sc.ScreenState != WINDOWED )
+ {
+ /*
+ * Do we need to update the emulation? If we don't do this here then
+ * a later state dump of the VGA registers to the VGA emulation may
+ * ignore an equal value of the char height and get_chr_height() will
+ * be out of step.
+ */
+ if (get_char_height() != startUpFontSize.Y)
+ {
+ half_word newht;
+
+ outb(EGA_CRTC_INDEX, 9); /* select char ht reg */
+ inb(EGA_CRTC_DATA, &newht); /* preserve current top 3 bits */
+ newht = (newht & 0xe0) | (startUpFontSize.Y & 0x1f);
+ outb(EGA_CRTC_DATA, newht);
+ }
+ set_char_height( startUpFontSize.Y ); /* Tim Oct 92 */
+
+ /*
+ * Select a graphics screen buffer so we get mouse coordinates in
+ * pixels.
+ */
+ //SelectMouseBuffer(); //Tim. moved to nt_std_handle_notification().
+
+ /*
+ * Prevent mode change happening to ensure dummy paint funcs
+ * are kept. (mode change set from bios mode set up).
+ */
+ set_mode_change_required(FALSE);
+ }
+#endif //X86GFX
+
+ /*
+ * Work out the top line to be displayed in the VGA window, which is line
+ * zero of the console unless the cursor would not be displayed, in which
+ * case the window is moved down until the cursor is on the bottom line.
+ */
+ cursorLine = ConsBufferInfo.dwCursorPosition.Y;
+ if (cursorLine < vgaHeight)
+ topLine = 0;
+ else
+ topLine = cursorLine - vgaHeight + (SHORT) 1;
+
+ ConVGAHeight = vgaHeight;
+ ConTopLine = topLine;
+
+ ConsoleInitialised = TRUE;
+}
+
+
+/***************************************************************************
+ * Function: *
+ * GfxReset *
+ * *
+ * Description: *
+ * Called from ConsoleInit to program up the vga hardware into some *
+ * known state. This compensates on the X86 for not initialising via *
+ * our bios. Essential for windowed running, but probably needed *
+ * for the what-mode-am-i-in stuff as well. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID GfxReset(VOID)
+{
+#ifdef X86GFX
+ half_word temp;
+ DWORD flags;
+
+ /* Check to see if we are currently running windowed or full-screen. */
+ if (!GetConsoleDisplayMode(&flags))
+ ErrorExit();
+ savedScreenState = sc.ScreenState = (flags & CONSOLE_FULLSCREEN_HARDWARE) ?
+ FULLSCREEN : WINDOWED;
+
+ /* Do windowed specific stuff. */
+ if(sc.ScreenState == WINDOWED)
+ {
+ /* Don't need this now cos we use our video BIOS in windowed */
+ /* Tim August 92: low_set_mode(3); */
+ /* sas_fillsw(0xb8000, 0x0720, 16000); */
+ inb(EGA_IPSTAT1_REG,&temp);
+
+ outb(EGA_AC_INDEX_DATA, EGA_PALETTE_ENABLE); /* re-enable video */
+
+ /* Turn off the VTRACE interrupt, enabled by low_set_mode(3)
+ this is a dirty hack and must be fixed properly */
+
+ ega_int_enable = 0;
+ }
+
+#endif
+}
+
+/***************************************************************************
+ * Function: *
+ * ResetConsoleState *
+ * *
+ * Description: *
+ * Attempts to put the console window back to the state in which *
+ * it started up. *
+ * *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID ResetConsoleState(VOID)
+{
+#ifdef X86GFX
+ /*
+ * Table of valid hardware states to be passed to
+ * SetConsoleHardwareState. NOTE: this table is a copy of a static table
+ * in SrvSetConsoleHardwareState, and so must be updated if that table
+ * changes.
+ */
+ SAVED HARDWARE_STATE validStates[] =
+ {
+ ///Now 21{ 22, { 640, 350 }, { 8, 16 } }, /* 80 x 22 mode. */
+ { 21, { 640, 350 }, { 8, 16 } }, /* 80 x 21 mode. */
+ { 25, { 720, 400 }, { 8, 16 } }, /* 80 x 25 mode. */
+ { 28, { 720, 400 }, { 8, 14 } }, /* 80 x 28 mode. */
+ { 43, { 640, 350 }, { 8, 8 } }, /* 80 x 43 mode. */
+#define MODE_50_INDEX 4
+ { 50, { 720, 400 }, { 8, 8 } } /* 80 x 50 mode. */
+ };
+ COORD cursorPos;
+ CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
+ ULONG i,
+ j,
+ videoWidth,
+ mode,
+ tableLen;
+ half_word *from,
+ *videoLine,
+ currentPage,
+ misc;
+ static COORD screenRes; /* value provided by GetConsHwState() */
+ static COORD fontSize; /* value provided by GetConsHwState() */
+
+ PCHAR_INFO to;
+ ULONG videoHeight,
+ nChars;
+ COORD bufferCoord,
+ bufferSize;
+ SMALL_RECT writeRegion;
+
+#endif /* X86GFX */
+ SMALL_RECT newWin;
+ BOOL itfailed = FALSE;
+
+#ifdef X86GFX
+ if (sc.ScreenState == WINDOWED)
+ {
+#endif /* X86GFX */
+
+ closeGraphicsBuffer();
+
+ if (StreamIoSwitchOn && !host_stream_io_enabled) {
+ /* restore screen buffer and window size */
+ SetConsoleScreenBufferSize(sc.OutputHandle, sc.ConsoleBuffInfo.dwSize);
+ newWin.Top = newWin.Left = 0;
+ newWin.Bottom = sc.ConsoleBuffInfo.srWindow.Bottom -
+ sc.ConsoleBuffInfo.srWindow.Top;
+ newWin.Right = sc.ConsoleBuffInfo.srWindow.Right -
+ sc.ConsoleBuffInfo.srWindow.Left;
+ SetConsoleWindowInfo(sc.OutputHandle, TRUE, &newWin);
+ }
+ /*
+ ** Tim September 92, don't resize window on way out of DOS app cos
+ ** MS (Sudeep) said so. Don't want to do the associated recalc_text()
+ ** either.
+ ** This keeps the window re-sizing issue nice and simple, but there'll
+ ** be people who don't like having a DOS window size forced upon them.
+ */
+#if 0
+ /* Now resize the window to start-up size. */
+ newWin.Top = newWin.Left = 0;
+ newWin.Bottom = ConsBufferInfo.srWindow.Bottom -
+ ConsBufferInfo.srWindow.Top;
+ newWin.Right = ConsBufferInfo.srWindow.Right -
+ ConsBufferInfo.srWindow.Left;
+
+ if(!SetConsoleWindowInfo(sc.OutputHandle, TRUE, &newWin))
+ itfailed = TRUE;
+
+ if(!SetConsoleScreenBufferSize(sc.OutputHandle,ConsBufferInfo.dwSize))
+ ErrorExit();
+ if (itfailed) //try 'it' again...
+ if(!SetConsoleWindowInfo(sc.OutputHandle, TRUE, &newWin))
+ ErrorExit();
+
+ /*
+ * Now call video routine to set the character height, updating the
+ * BIOS RAM as it does so.
+ */
+ recalc_text(StartupCharHeight);
+#endif //Zero
+
+#if 0
+ /* williamh. If we really want to do the following thing,
+ we have to copy regen to console buffer.
+ since we are runniing in windowed TEXT mode
+ the console always has our up-to-date regen
+ content, the following actually is not necessary
+ It worked before taking this out it because console
+ doesn't verify the parameters we passed. No console
+ has the checking and we are in trouble if we continue
+ to do so.
+ */
+
+ /* Clear the undisplayed part of the console buffer. */
+ bufferSize.X = MAX_CONSOLE_WIDTH;
+ bufferSize.Y = MAX_CONSOLE_HEIGHT;
+ videoHeight = (SHORT) (sas_hw_at_no_check(vd_rows_on_screen) + 1);
+ to = consoleBuffer + bufferSize.X * videoHeight;
+ nChars = bufferSize.X * ( bufferSize.Y - videoHeight );
+
+ while (nChars--)
+ {
+ to->Char.AsciiChar = 0x20;
+ to->Attributes = 7;
+ to++;
+ }
+ bufferCoord.X = 0;
+ bufferCoord.Y = (SHORT)videoHeight;
+ writeRegion.Left = 0;
+ writeRegion.Top = (SHORT)videoHeight;
+ writeRegion.Right = MAX_CONSOLE_WIDTH-1;
+ writeRegion.Bottom = bufferSize.Y-1;
+ if (!WriteConsoleOutput(sc.OutputHandle,
+ consoleBuffer,
+ bufferSize,
+ bufferCoord,
+ &writeRegion))
+ ErrorExit();
+#endif
+ /*
+ ** Tim, September 92. Put the Console cursor to the same place as the
+ ** SoftPC cursor. We already do this in full-screen text mode below.
+ ** Specifcally to fix weird cursor position problem with 16-bit nmake,
+ ** but seems like a good safety idea anyway.
+ */
+ getVDMCursorPosition();
+
+ doNullRegister(); /* revert console back to ordinary window */
+
+#ifdef X86GFX
+ }
+ else /* FULLSCREEN */
+ {
+ /*
+ * If SoftPC blocks in a text mode, sync console srceen buffer to regen
+ * area.
+ */
+ if (getModeType() == TEXT)
+ {
+ /* Get the current screen buffer info. */
+ if (!GetConsoleScreenBufferInfo(sc.OutputHandle, &bufferInfo))
+ ErrorExit();
+
+ /* Get nearest screen size SetConsoleHardwareState will allow. */
+ tableLen = sizeof(validStates) / sizeof(HARDWARE_STATE);
+ for (mode = 0; mode < tableLen; mode++)
+ if (validStates[mode].LinesOnScreen ==
+ bufferInfo.srWindow.Bottom - bufferInfo.srWindow.Top + 1)
+ break;
+
+ /* Set it to 50 line mode if we had a funny number of lines. */
+ if (mode == tableLen)
+ {
+ assert0(FALSE,
+ "Non standard lines on blocking - setting 50 lines");
+ mode = MODE_50_INDEX;
+ }
+
+ /*
+ ** Tim September 92, if the console hardware state is the same as
+ ** we are about to set it, do not bother setting it.
+ ** This should stop the screen from flashing.
+ */
+ if( !GetConsoleHardwareState(sc.OutputHandle,
+ &screenRes,
+ &fontSize) )
+ assert1( NO,"VDM: GetConsHwState() failed:%#x",GetLastError() );
+
+ /* Sync the console to the regen buffer. */
+ currentPage = sas_hw_at_no_check(vd_current_page);
+ vga_misc_inb(0x3cc, &misc);
+ if (misc & 1) // may be mono mode
+ videoLine = (half_word *) CGA_REGEN_START +
+ (VIDEO_PAGE_SIZE * currentPage);
+ else
+ videoLine = (half_word *) MDA_REGEN_START +
+ (VIDEO_PAGE_SIZE * currentPage);
+ to = consoleBuffer;
+ videoWidth = sas_w_at_no_check(VID_COLS);
+ videoHeight = (SHORT) (sas_hw_at_no_check(vd_rows_on_screen) + 1);
+ bufferSize.X = MAX_CONSOLE_WIDTH;
+ bufferSize.Y = MAX_CONSOLE_HEIGHT;
+ if (bufferSize.X * bufferSize.Y > MAX_CONSOLE_SIZE)
+ {
+ assert1(FALSE, "Buffer size, %d, too large",
+ bufferSize.X * bufferSize.Y);
+ ErrorExit();
+ }
+ for (i = 0; i < videoHeight; i++)
+ {
+ from = videoLine;
+ for (j = 0; j < videoWidth; j++)
+ {
+ to->Char.AsciiChar = *from++;
+ to->Attributes = *from++;
+ to++;
+ }
+ for (; j < (ULONG)bufferSize.X; j++)
+ {
+ to->Char.AsciiChar = 0x20;
+ to->Attributes = 7;
+ to++;
+ }
+ videoLine += videoWidth * 2;
+ }
+ for (; i < (ULONG)bufferSize.Y; i++)
+ for (j = 0; j < (ULONG)bufferSize.X; j++)
+ {
+ to->Char.AsciiChar = 0x20;
+ to->Attributes = 7;
+ to++;
+ }
+ bufferCoord.X = bufferCoord.Y = 0;
+ writeRegion.Left = writeRegion.Top = 0;
+ writeRegion.Right = bufferSize.X - 1;
+ writeRegion.Bottom = bufferSize.Y - 1;
+
+ doNullRegister(); /* revert back to normal console */
+
+ if( screenRes.X != validStates[mode].Resolution.X ||
+ screenRes.Y != validStates[mode].Resolution.Y ||
+ fontSize.X != validStates[mode].FontSize.X ||
+ fontSize.Y != validStates[mode].FontSize.Y ||
+ sas_hw_at_no_check(VID_COLS) == 40 ||
+ fontSize.Y != sas_hw_at_no_check(ega_char_height))
+ {
+ /* Set up the screen. */
+ if( !SetConsoleHardwareState( sc.OutputHandle,
+ validStates[mode].Resolution,
+ validStates[mode].FontSize) ){
+ /*
+ ** Tim Sept 92, attempt a recovery.
+ */
+ assert1( NO, "VDM: SetConsoleHwState() failed:%#x",
+ GetLastError() );
+ }
+ }
+
+
+ /* put VDM screen onto console screen */
+ if (!WriteConsoleOutput(sc.OutputHandle,
+ consoleBuffer,
+ bufferSize,
+ bufferCoord,
+ &writeRegion))
+ ErrorExit();
+
+#if 0 //STF removed with new mouse stuff??
+ /*
+ ** Tim, September 92.
+ ** Try this after the WriteConsoleOutput(), can now copy the
+ ** right stuff from video memory to console.
+ ** For mouse purposes we have selected a graphics buffer, so now
+ ** we must reselect the text buffer.
+ */
+ if (!SetConsoleActiveScreenBuffer(sc.OutputHandle))
+ ErrorExit();
+#endif //STF
+
+ /*
+ * Get the cursor position from the BIOS RAM and tell the
+ * console.
+ * Set up variables getVDMCursorPosition() needs. Tim Jan 93.
+ */
+ sc.PC_W_Height = screenRes.Y;
+ sc.CharHeight = fontSize.Y;
+ getVDMCursorPosition();
+ }
+ else /* GRAPHICS */
+ {
+ /*
+ ** A tricky issue. If we were just in a full-screen graphics
+ ** mode, we are just about to lose the VGA state and can't get
+ ** it back very easily. So do we pretend we are still in the
+ ** graphics mode or pretend we are in a standard text mode?
+ ** Seems like standard text mode is more sensible. Tim Feb 93.
+ */
+ sas_store_no_check( vd_video_mode, 0x3 );
+ blocked_in_gfx_mode = TRUE;
+
+#if 0 //STF removed with new mouse stuff??
+ /*
+ ** Tim, September 92, think we want one of these here too.
+ ** Change to the normal console text buffer.
+ */
+ if (!SetConsoleActiveScreenBuffer(sc.OutputHandle))
+ ErrorExit();
+#endif //STF
+
+ /* Get the current screen buffer info. */
+ if (!GetConsoleScreenBufferInfo(sc.OutputHandle, &bufferInfo))
+ ErrorExit();
+
+ /* Get nearest screen size SetConsoleHardwareState will allow. */
+ tableLen = sizeof(validStates) / sizeof(HARDWARE_STATE);
+ for (mode = 0; mode < tableLen; mode++)
+ if (validStates[mode].LinesOnScreen ==
+ bufferInfo.srWindow.Bottom - bufferInfo.srWindow.Top + 1)
+ break;
+
+ /* Set it to 50 line mode if we had a funny number of lines. */
+ if (mode == tableLen)
+ {
+ assert0(FALSE,
+ "Non standard lines on blocking - setting 50 lines");
+ mode = MODE_50_INDEX;
+ }
+
+ /* Clear the console buffer. */
+ bufferSize.X = MAX_CONSOLE_WIDTH;
+ bufferSize.Y = MAX_CONSOLE_HEIGHT;
+ nChars = bufferSize.X * bufferSize.Y;
+ if (nChars > MAX_CONSOLE_SIZE)
+ {
+ assert1(FALSE, "Buffer size, %d, too large", nChars);
+ ErrorExit();
+ }
+ to = consoleBuffer;
+ while (nChars--)
+ {
+ to->Char.AsciiChar = 0x20;
+ to->Attributes = 7;
+ to++;
+ }
+ bufferCoord.X = bufferCoord.Y = 0;
+ writeRegion.Left = writeRegion.Top = 0;
+ writeRegion.Right = MAX_CONSOLE_WIDTH-1;
+ writeRegion.Bottom = bufferSize.Y-1;
+
+ doNullRegister(); /* revert back to normal console */
+
+ if (!WriteConsoleOutput(sc.OutputHandle,
+ consoleBuffer,
+ bufferSize,
+ bufferCoord,
+ &writeRegion))
+ ErrorExit();
+
+ /* Set the cursor to the top left corner. */
+ cursorPos.X = 0;
+ cursorPos.Y = 0;
+ if (!SetConsoleCursorPosition(sc.OutputHandle, cursorPos))
+ ErrorExit();
+#ifndef PROD
+ if (sc.ScreenState == WINDOWED) // transient switch??
+ assert0(NO, "Mismatched screenstate on shutdown");
+#endif
+
+ /* Set up the screen. */
+ SetConsoleHardwareState(sc.OutputHandle,
+ validStates[mode].Resolution,
+ validStates[mode].FontSize);
+ }
+ /*
+ ** Tim September 92, close graphics screen buffer on way out when in
+ ** full-screen.
+ */
+ closeGraphicsBuffer();
+ }
+#endif /* X86GFX */
+
+ /*Put console's cursor back to the shape it was on startup.*/
+ SetConsoleCursorInfo(sc.OutputHandle, &StartupCursor);
+
+ /* reset the current_* variables in nt_graph.c */
+ resetWindowParams();
+}
+
+
+#ifdef X86GFX
+
+/***************************************************************************
+ * Function: *
+ * TextToGraphics *
+ * *
+ * Description: *
+ * Handles transitions from text to graphics modes when running *
+ * windowed. Waits until the window has input focus and then requests *
+ * a transition to full-screen operation as graphics modes cannot be *
+ * run in a window. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID TextToGraphics(VOID)
+{
+ DWORD flags;
+ SAVED COORD scrSize;
+
+ /* Freeze until the window receives input focus. */
+ //if (! sc.Focus ) //awaiting console fix.
+ if (GetForegroundWindow() != hWndConsole)
+ {
+
+ FreezeWinTitle(); /* Add `-FROZEN' to the console title. */
+
+ /* Now wait until input focus is received. */
+ waitForInputFocus();
+
+ UnFreezeWinTitle(); /* Remove frozen message */
+ }
+
+ /*
+ * We are about to go full-screen but there will be a delay while the
+ * detection thread does its hand-shaking. So disable screen writes before
+ * we switch to prevent inadvertent updates while running full-screen.
+ */
+ disableUpdates();
+
+ /*
+ * Sanity Check for stress problem where forced fullscreen after INT 10
+ * mode change has already started so can apparently go fullscreen twice.
+ */
+ if (!GetConsoleDisplayMode(&flags))
+ ErrorExit();
+
+ /* make sure we haven't been taken back fullscreen */
+ if ((flags & CONSOLE_FULLSCREEN_HARDWARE) == CONSOLE_FULLSCREEN_HARDWARE)
+ {
+#ifndef PROD
+ assert0(NO,"NTVDM:rejected fullscreen switch as console already FS");
+#endif
+ return;
+ }
+
+ /* check for iconified FS console. Only under extreme conditions (stress) */
+ if ((flags & CONSOLE_FULLSCREEN) == CONSOLE_FULLSCREEN)
+ {
+ SetForegroundWindow(hWndConsole); /* focus will send us back FS */
+ }
+ else /* desktop window */
+ {
+ /* The window now has input focus so request to go full-screen. */
+ BiosModeChange = TRUE;
+ if (!SetConsoleDisplayMode(sc.OutputHandle,
+ CONSOLE_FULLSCREEN_MODE,
+ &scrSize))
+ {
+ if (GetLastError() == ERROR_INVALID_PARAMETER)
+ {
+ RcErrorDialogBox(ED_INITFSCREEN, NULL, NULL);
+ }
+ else
+ {
+ ErrorExit();
+ }
+ }
+ BiosModeChange = FALSE;
+ }
+}
+
+/***************************************************************************
+ * Function: *
+ * CheckForFullscreenSwitch *
+ * *
+ * Description: *
+ * Checks to see if there has been a transition between windowed and *
+ * fullscreen and does any console calls necessary. This is called *
+ * on a timer tick before the graphics tick code. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID CheckForFullscreenSwitch(VOID)
+{
+ half_word mode,
+ lines;
+
+ if (sc.ScreenState == STREAM_IO)
+ return;
+
+ /*
+ * Do any console calls relating to screen state changes. They have to be
+ * done now as they cannot be done on the same thread as the screen switch
+ * hand-shaking.
+ */
+ if (sc.ScreenState != savedScreenState)
+ {
+ if (sc.ScreenState == WINDOWED)
+ {
+ if (sc.ModeType == TEXT)
+ {
+
+ /* Remove frozen window indicator if necessary. */
+ UnFreezeWinTitle();
+
+#if 0 //STF removed with new mouse stuff??
+ /* Revert to text buffer. */
+ closeGraphicsBuffer(); /* Tim Oct 92 */
+#endif //STF
+
+ /* Get Window to correct shape */
+ textResize();
+
+ /* Enable screen updates. */
+ enableUpdates();
+
+ /*
+ * Now get the image on the screen (timer updates currently
+ * disabled).
+ */
+ (void)(*update_alg.calc_update)();
+
+ }
+ }
+ else /* FULLSCREEN */
+ {
+ int cnt = 0; /* Counter to break out of the cursor off loop. */
+
+ /* Disable screen updates*/
+ disableUpdates();
+
+ /* Disable mouse 'attached'ness if enabled */
+ if (bPointerOff)
+ {
+ PointerAttachedWindowed = TRUE;
+ MouseDisplay();
+ }
+
+#if 0 //STF removed with new mouse stuff
+ /* remove any graphics buffer from frozen screen */
+ closeGraphicsBuffer();
+#endif
+
+ /* Do mouse scaling */
+ mode = sas_hw_at_no_check(vd_video_mode);
+ lines = sas_hw_at_no_check(vd_rows_on_screen) + 1;
+ SelectMouseBuffer(mode, lines);
+
+ /* force mouse */
+ ica_hw_interrupt(AT_CPU_MOUSE_ADAPTER, AT_CPU_MOUSE_INT, 1);
+
+ /*
+ * Now turn off console cursor - otherwise can ruin screen trying to
+ * draw system's cursor. The VDM will have to worry about the mouse
+ * image.
+ */
+ // while(ShowConsoleCursor(sc.OutputHandle, FALSE) >=0 && cnt++ < 200);
+ } /* FULLSCREEN */
+
+ /* Update saved variable. */
+ savedScreenState = sc.ScreenState;
+ }
+ /* Delayed Client Rect query */
+ if (DelayedReattachMouse)
+ {
+ DelayedReattachMouse = FALSE;
+ MovePointerToWindowCentre();
+ }
+}
+
+/*
+***************************************************************************
+** getNtScreenState() - return 0 for windowed, 1 for full-screen.
+***************************************************************************
+** Tim July 92.
+*/
+GLOBAL UTINY getNtScreenState IFN0()
+{
+ return( (UTINY) sc.ScreenState );
+}
+
+/*
+***************************************************************************
+** hostModeChange() - called from video bios, ega_vide.c:ega_set_mode()
+***************************************************************************
+**
+** When changing to a graphics mode action the transition to full-screen if
+** we are currently windowed.
+**
+** On entry AX should still contain the value when the video BIOS set mode
+** function was called.
+** Call to TextToGraphics() with parameter indicating whether we want a
+** clear screen with the impending host video BIOS mode change.
+**
+** Return a boolean indicating to the real BIOS whether the mode change
+** has occured.
+**
+** Tim August 92.
+*/
+GLOBAL BOOL hostModeChange IFN0()
+{
+ half_word vid_mode;
+
+ vid_mode = getAL() & 0x7f;
+
+ if(getNtScreenState() == WINDOWED)
+ {
+ if (vid_mode > 3 && vid_mode != 7)
+ {
+ /*
+ * We have to tell the hand-shaking code the BIOS is causing
+ * the mode change so that it can do a BIOS mode change when
+ * the switch has been done. This has to be implemented as a
+ * global variable because the hand-shaking is on a different
+ * thread.
+ */
+ TextToGraphics();
+ // rapid Window to full screen and back cause this to fail,
+ // remove call since it will get done on the next timer
+ // event. 28-Feb-1993 Jonle
+ // SelectMouseBuffer();
+ return( TRUE );
+ }
+ else
+ return(FALSE);
+ }
+ else
+ return( FALSE );
+
+} /* end hostModeChange() */
+#endif /* X86GFX */
+
+/***************************************************************************
+ * Function: *
+ * DoFullScreenResume *
+ * *
+ * Description: *
+ * Called by SCS to restart SoftPC when a DOS application restarts *
+ * after being suspended or starts up for the first time after SoftPC *
+ * has been booted by another application which has since terminated. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+
+GLOBAL VOID DoFullScreenResume(VOID)
+{
+ USHORT vgaHeight, height;
+#ifndef X86GFX
+ PVOID pDummy;
+#endif
+
+#ifdef X86GFX
+ DWORD flags;
+
+ /*
+ ** Tim July 92.
+ ** Set sc.ScreenState, a windowed/full-screen transition might
+ ** have happenened when SoftPC was inactive.
+ ** Copied from GfxReset().
+ */
+ if( !GetConsoleDisplayMode(&flags) )
+ ErrorExit();
+ sc.ScreenState = (flags & CONSOLE_FULLSCREEN_HARDWARE) ? FULLSCREEN : WINDOWED;
+
+ /* Put the regen memory in the correct state. */
+ if (sc.ScreenState != savedScreenState)
+ {
+ if (sc.ScreenState == WINDOWED)
+ {
+ enableUpdates(); /* Tim September 92, allow graphics ticks */
+ /*
+ ** Tim Jan 93. Get the next nt_graphics_tick() to decide
+ ** what the current display mode is, set the update and
+ ** paint funx appropriately and redraw the screen.
+ */
+ set_mode_change_required( TRUE );
+
+ /* Ensure idling system enabled & reset */
+ IDLE_ctl(TRUE);
+ IDLE_init();
+ }
+ else
+ {
+ disableUpdates(); /* Tim September 92, stop graphics ticks */
+
+ /* Ensure idling system disabled as can't detect fullscreen idling*/
+ IDLE_ctl(FALSE);
+ }
+ savedScreenState = sc.ScreenState;
+ }
+
+ /* Select a graphics buffer for the mouse if we are running fullscreen. */
+ if (sc.ScreenState == FULLSCREEN)
+ {
+ //SelectMouseBuffer(); //Tim. moved to nt_std_handle_notification().
+
+ /* Lose the regen memory. */
+ LoseRegenMemory();
+ }
+
+ /*
+ ** Tim July 92:
+ ** set the KEYBOARD.SYS internal variable to 0 for windowed and
+ ** 1 for full-screen.
+ ** If a transition has happened when SoftPC was inactive we
+ ** need to get into the appropriate state.
+ */
+ {
+ if( sc.ScreenState==WINDOWED ){
+ sas_store_no_check( (int10_seg<<4)+useHostInt10, WINDOWED );
+ }else{
+ sas_store_no_check( (int10_seg<<4)+useHostInt10, FULLSCREEN );
+ }
+ }
+#endif /* X86GFX */
+
+ // re-register with console for fullscreen switching.
+ if( !RegisterConsoleVDM( VDMForWOW ?
+ CONSOLE_REGISTER_WOW : CONSOLE_REGISTER_VDM,
+#ifdef X86GFX
+ hStartHardwareEvent,
+ hEndHardwareEvent,
+#else
+ NULL,
+ NULL,
+#endif
+
+ NULL, // sectionname no longer used
+ 0, // sectionname no longer used
+ &stateLength,
+#ifndef X86GFX
+ &pDummy,
+#else
+ (PVOID *) &videoState,
+#endif
+ NULL, // sectionname no longer used
+ 0, // sectionname no longer used
+ textBufferSize,
+ (PVOID *) &textBuffer
+ )
+ )
+ ErrorExit();
+
+#ifdef X86GFX
+ sc.Registered = TRUE;
+ /* stateLength can be 0 if fullscreen is disabled in the console */
+ if(stateLength)
+ RtlZeroMemory(videoState, sizeof(VIDEO_HARDWARE_STATE_HEADER));
+#else
+ /*
+ ** Create graphics buffer if we need one. Tim Oct 92.
+ */
+ if( sc.ModeType==GRAPHICS )
+ graphicsResize();
+#endif
+ /*
+ ** Tim September 92.
+ ** If window size is not suitable for a DOS app, snap-to-fit
+ ** appropriately. Put cursor in correct place.
+ ** Do the ConsoleInit() and nt_init_event_thread() type of things.
+ ** Leave full-screen as it was.
+ */
+ if (sc.ScreenState != WINDOWED) {
+ /* Get console info, including the current cursor position. */
+ if (!GetConsoleScreenBufferInfo(sc.OutputHandle, &ConsBufferInfo))
+ ErrorExit();
+ /* Hard-wired for f-s resume - needs to be set properly. */
+ height = 8;
+ /* Set up BIOS variables etc. */
+ setVDMCursorPosition( (UTINY)height,
+ &ConsBufferInfo.dwCursorPosition);
+ /* Copy the console buffer to the regen buffer. */
+ copyConsoleToRegen(0, 0, VGA_WIDTH, (SHORT)ConVGAHeight);
+ }
+
+ /*
+ ** Get console window size and set up our stuff accordingly.
+ */
+ calcScreenParams( &height, &vgaHeight );
+
+ /*
+ ** Window resize code copied out of nt_graph.c:textResize().
+ */
+ {
+ resizeWindow( 80, vgaHeight );
+ }
+
+ /* Copy the console buffer to the regen buffer. */
+ copyConsoleToRegen(0, 0, VGA_WIDTH, vgaHeight);
+
+ /*
+ ** Make sure cursor is not below bottom line.
+ */
+ if( ConsBufferInfo.dwCursorPosition.Y >= vgaHeight ){
+ ConsBufferInfo.dwCursorPosition.Y = vgaHeight-1;
+ }
+ setVDMCursorPosition(( UTINY)height, &ConsBufferInfo.dwCursorPosition);
+
+} /* end of DoFullScreenResume() */
+
+/***************************************************************************
+ * Function: *
+ * GfxCloseDown *
+ * *
+ * Description: *
+ * Hook from host_terminate to ensure section closed so can then start*
+ * more VDMs. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID (Errors handled internally in CloseSection) *
+ * *
+ ***************************************************************************/
+GLOBAL VOID GfxCloseDown(VOID)
+{
+ /* Text and Video sections previously closed here... */
+}
+
+#ifdef X86GFX
+/***************************************************************************
+ * Function: *
+ * FreezeWinTitle *
+ * *
+ * Description: *
+ * Adds -FROZEN to the relevant console window title *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID FreezeWinTitle(VOID)
+{
+ CHAR title[MAX_TITLE_LEN],*ptr;
+ SHORT max;
+ ULONG len;
+
+ if (WinFrozen)
+ return;
+
+ //
+ // The buffer contains the string plus the terminating null.
+ // So keep the string length less the null in len.
+ // Console can fail this call with silly error codes in low memory cases
+ // or if original title contains dubious chars.
+ //
+
+ len = strlen(szFrozenString);
+
+ max = (SHORT) (MAX_TITLE_LEN - len);
+ if (!GetConsoleTitle(title, max))
+ title[0] = '\0';
+
+ //
+ // Remove any trailing spaces or tabs from the title string
+ //
+
+ if(len = strlen(title))
+ {
+ ptr = title + len - 1;
+ while(*ptr == ' ' || *ptr == '\t')
+ *ptr-- = '\0';
+ }
+
+ //
+ // Add " - FROZEN" or the international equivalent to
+ // the end of the title string.
+ //
+
+ strcat(title, szFrozenString);
+ if (!SetConsoleTitle(title))
+ ErrorExit();
+ WinFrozen = TRUE;
+
+}
+
+/***************************************************************************
+ * Function: *
+ * UnFreezeWinTitle *
+ * *
+ * Description: *
+ * Removes -FROZEN from the relevant console window title *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID UnFreezeWinTitle(VOID)
+{
+ CHAR title[MAX_TITLE_LEN];
+ ULONG len,orglen;
+
+ if (! WinFrozen)
+ return;
+
+ if (!GetConsoleTitle(title, MAX_TITLE_LEN))
+ ErrorExit();
+
+
+ //
+ // The buffer contains the string plus the terminating null.
+ // So keep the string length less the null in len.
+ //
+
+ len = strlen(szFrozenString);
+ orglen = strlen(title);
+ title[orglen - len] = '\0';
+ if (!SetConsoleTitle(title))
+ ErrorExit();
+ WinFrozen = FALSE;
+
+ //
+ // Now that we're thawing, put the mouse menu item
+ // back into the system menu.
+ // Andy!
+
+ MouseAttachMenuItem(sc.ActiveOutputBufferHandle);
+}
+#endif
+
+
+/*
+ * ==========================================================================
+ * Local Functions
+ * ==========================================================================
+ */
+
+/***************************************************************************
+ * Function: *
+ * enableUpdates *
+ * *
+ * Description: *
+ * Restarts the reflection of regen buffer updates to paint routines. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+VOID enableUpdates(VOID)
+{
+ enable_gfx_update_routines();
+ ConsoleNoUpdates = FALSE;
+}
+
+/***************************************************************************
+ * Function: *
+ * disableUpdates *
+ * *
+ * Description: *
+ * Stops changes to the regen buffer being reflected to paint *
+ * routines. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+VOID disableUpdates(VOID)
+{
+ disable_gfx_update_routines();
+ ConsoleNoUpdates = TRUE;
+}
+
+/***************************************************************************
+ * Function: *
+ * copyConsoleToRegen *
+ * *
+ * Description: *
+ * Copies the contents of the console buffer to the video regen *
+ * buffer. *
+ * *
+ * Parameters: *
+ * startCol - start column of console buffer *
+ * startLine - start line of console buffer *
+ * width - width of console buffer *
+ * height - height of console buffer *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+VOID copyConsoleToRegen(SHORT startCol, SHORT startLine, SHORT width,
+ SHORT height)
+{
+ CHAR_INFO *from;
+ COORD bufSize,
+ bufCoord;
+ LONG nChars;
+ SMALL_RECT readRegion;
+
+ register half_word *to;
+#ifdef X86GFX
+ half_word misc;
+ register half_word *vc;
+#endif
+
+
+ /* Allocate the buffer to get the console data into */
+ nChars = width * height;
+ assert0(nChars <= MAX_CONSOLE_SIZE, "Console buffer overflow");
+
+ /* Get the console data. */
+ bufSize.X = width;
+ bufSize.Y = height;
+ bufCoord.X = 0;
+ bufCoord.Y = 0;
+ readRegion.Left = startCol;
+ readRegion.Top = startLine;
+ readRegion.Right = startCol + width - (SHORT) 1;
+ readRegion.Bottom = startLine + height - (SHORT) 1;
+ if (!ReadConsoleOutput(sc.OutputHandle,
+ consoleBuffer,
+ bufSize,
+ bufCoord,
+ &readRegion))
+ ErrorExit();
+
+ /* Copy the console data to the regen buffer. */
+ from = consoleBuffer;
+
+#ifndef X86GFX // on MIPS we actually want to write to the VGA bitplanes.
+ to = EGA_planes;
+ while(nChars--)
+ {
+ *to++ = from->Char.AsciiChar;
+ *to = (half_word) from->Attributes;
+ from++;
+ to += 3; // skipping interleaved font planes.
+ }
+ host_mark_screen_refresh();
+#else
+
+ /*
+ * In V86 mode PC memory area is mapped to the bottom 1M of virtual memory,
+ * so the following is legal.
+ */
+ vga_misc_inb(0x3cc, &misc);
+ if (misc & 1) // may be mono mode
+ to = (half_word *) CGA_REGEN_START;
+ else
+ to = (half_word *) MDA_REGEN_START;
+
+ vc = (half_word *) video_copy;
+
+ while (nChars--)
+ {
+ *to++ = *vc++ = from->Char.AsciiChar;
+ *to++ = *vc++ = (half_word) from->Attributes;
+ from++;
+ }
+#endif
+}
+
+/***************************************************************************
+ * Function: *
+ * getVDMCursorPosition *
+ * *
+ * Description: *
+ * Gets the cursor position from BIOS variables and tells the console *
+ * where to place its cursor. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+VOID getVDMCursorPosition(VOID)
+{
+ half_word currentPage;
+ word cursorWord;
+ COORD cursorPos;
+ BOOL setok;
+
+ /* Get the current video page. */
+ currentPage = sas_hw_at_no_check(vd_current_page);
+
+ /* Store cursor position in BIOS variables. */
+ cursorWord = sas_w_at_no_check(VID_CURPOS + (currentPage * 2));
+
+ /* Set the console cursor. */
+ cursorPos.X = (SHORT) (cursorWord & 0xff);
+ cursorPos.Y = (cursorWord >> 8) & (SHORT) 0xff;
+
+ if ((sc.CharHeight * cursorPos.Y) > sc.PC_W_Height)
+ cursorPos.Y = (sc.PC_W_Height / sc.CharHeight) - 1;
+
+ if( !stdoutRedirected ) {
+ setok = SetConsoleCursorPosition(sc.OutputHandle, cursorPos);
+ if (!setok) {
+
+ if (GetLastError() != ERROR_INVALID_HANDLE) // ie. output redirected
+ ErrorExit();
+ }
+ }
+}
+
+/***************************************************************************
+ * Function: *
+ * setVDMCursorPosition *
+ * *
+ * Description: *
+ * Positions SoftPC's cursor, setting the relevant BIOS variables. *
+ * *
+ * Parameters: *
+ * height - the current character height *
+ * cursorPos - the coordinates of the cursor *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+VOID setVDMCursorPosition(UTINY height, PCOORD cursorPos)
+{
+ CONSOLE_CURSOR_INFO cursorInfo;
+ ULONG port6845,
+ cursorStart,
+ cursorEnd,
+ colsOnScreen,
+ videoLen,
+ pageOffset,
+ cursorWord;
+ UTINY currentPage;
+
+ /* Get cursor size. */
+ if(!GetConsoleCursorInfo(sc.OutputHandle, &cursorInfo))
+ ErrorExit();
+
+ /* Work out cursor start and end pixels. */
+ cursorStart = height - (height * cursorInfo.dwSize / 100);
+ if (cursorStart == height)
+ cursorStart--;
+ cursorEnd = height - 1;
+
+ if (sc.ScreenState == WINDOWED)
+ {
+
+ /* Pass cursor size to video ports. */
+ port6845 = sas_w_at_no_check(VID_INDEX);
+ outb((io_addr) port6845, R10_CURS_START);
+ outb((io_addr) (port6845 + 1), (half_word) cursorStart);
+ outb((io_addr) port6845, R11_CURS_END);
+ outb((io_addr) (port6845 + 1), (half_word) cursorEnd);
+ }
+
+ /* Get the current video page. */
+ currentPage = sas_hw_at_no_check(vd_current_page);
+
+ /* Set BIOS variables. */
+ sas_storew_no_check(VID_CURMOD,
+ (word) ((cursorStart << 8) | (cursorEnd & 0xff)));
+
+ /* Work out cursor position. */
+ colsOnScreen = sas_w_at_no_check(VID_COLS);
+ videoLen = sas_w_at_no_check(VID_LEN);
+ pageOffset = cursorPos->Y * colsOnScreen * 2 + (cursorPos->X << 1);
+ cursorWord = (currentPage * videoLen + pageOffset) / 2;
+
+ if (sc.ScreenState == WINDOWED)
+ {
+
+ /* Send cursor position to video ports. */
+ outb((io_addr) port6845, R14_CURS_ADDRH);
+ outb((io_addr) (port6845 + 1), (half_word) (cursorWord >> 8));
+ outb((io_addr) port6845, R15_CURS_ADDRL);
+ outb((io_addr) (port6845 + 1), (half_word) (cursorWord & 0xff));
+ }
+
+ /* Store cursor position in BIOS variables. */
+ sas_storew_no_check(VID_CURPOS + (currentPage * 2),
+ (word) ((cursorPos->Y << 8) | (cursorPos->X & 0xff)));
+
+ if (sc.ScreenState == WINDOWED)
+ {
+#ifdef MONITOR
+ resetNowCur(); /* reset static vars holding cursor pos. */
+#endif
+ do_new_cursor(); /* make sure the emulation knows about it */
+ }
+}
+
+VOID waitForInputFocus()
+{
+ if (WaitForSingleObject(sc.FocusEvent, INFINITE))
+ ErrorExit();
+}
+
+VOID AddTempIVTFixups()
+{
+ /* BOP 17, IRET */
+ UTINY code[] = { 0xc4, 0xc4, 0x17, 0xcf };
+
+ //location is random but should be safe until DOS is initialised!!!
+ sas_stores(0x40000, code, sizeof(code)); // new Int 17 code
+ sas_storew(0x17*4, 0); // Int 17h offset
+ sas_storew((0x17*4) + 2, 0x4000); // Int 17h segment
+}
+
+/***************************************************************************
+ * Function: *
+ * getModeType *
+ * *
+ * Description: *
+ * Look up video mode to determine whether the VGA current mode is *
+ * graphics or text. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * int - TEXT or GRAPHICS. *
+ * *
+ ***************************************************************************/
+int getModeType(VOID)
+{
+ half_word mode;
+ int modeType;
+
+ mode = sas_hw_at_no_check(vd_video_mode);
+ switch(mode)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 7:
+ case 0x20:
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ modeType = TEXT;
+ break;
+ default:
+ modeType = GRAPHICS;
+ break;
+ }
+ return(modeType);
+}
+
+#ifdef X86GFX
+/***************************************************************************
+ * Function: *
+ * host_check_mouse_buffer *
+ * *
+ * Description: *
+ * Called when an INT 10h, AH = 11h is being executed, this function *
+ * checks to see if the number of lines on the screen for a text mode *
+ * has changed and if so selects a new mouse buffer. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID host_check_mouse_buffer(VOID)
+{
+ half_word mode,
+ sub_func,
+ font_height,
+ text_lines;
+ IU16 scan_lines;
+
+ /* Get the current video mode. */
+ mode = sas_hw_at_no_check(vd_video_mode);
+#ifdef V7VGA
+ if (mode > 0x13)
+ mode += 0x4c;
+ else if ((mode == 1) && (extensions_controller.foreground_latch_1))
+ mode = extensions_controller.foreground_latch_1;
+#endif /* V7VGA */
+
+ /*
+ * Check to see if we are in a text mode whose mouse virtual coordinates
+ * are affected by the number of lines on the screen.
+ */
+ if ((mode == 0x2) || (mode == 0x3) || (mode == 0x7))
+ {
+
+ /* Work out the font height being set. */
+ sub_func = getAL();
+ switch (sub_func)
+ {
+ case 0x10:
+ font_height = getBH();
+ break;
+ case 0x11:
+ font_height = 14;
+ break;
+ case 0x12:
+ font_height = 8;
+ break;
+ case 0x14:
+ font_height = 16;
+ break;
+ default:
+
+ /*
+ * The above are the only functions that re-program the no. of lines
+ * on the screen, so do nothing if we have something else.
+ */
+ return;
+ }
+
+ /* Get the number of scan lines for this mode. */
+ if(!(get_EGA_switches() & 1) && (mode < 4))
+ {
+ scan_lines = 200; /* Low res text mode */
+ }
+ else
+ {
+ switch (get_VGA_lines())
+ {
+ case S200:
+ scan_lines = 200;
+ break;
+ case S350:
+ scan_lines = 350;
+ break;
+ case S400:
+ scan_lines = 400;
+ break;
+ default:
+
+ /* Dodgy value in BIOS data area - don't do anything. */
+ assert0(NO, "invalid VGA lines in BIOS data");
+ return;
+ }
+ }
+
+ /* Now work out the number of text lines on the screen. */
+ text_lines = scan_lines / font_height;
+
+ /* If the number of lines has changed, select a new mouse buffer. */
+ if (text_lines != saved_text_lines)
+ SelectMouseBuffer(mode, text_lines);
+
+ } /* if ((mode == 0x2) || (mode == 0x3) || (mode == 0x7)) */
+}
+
+/***************************************************************************
+ * Function: *
+ * SelectMouseBuffer *
+ * *
+ * Description: *
+ * Selects the correct screen ratio for the video mode.at the *
+ * *
+ * Parameters: *
+ * mode - the video mode for which we are setting a screen buffer. *
+ * lines - for text modes: the number of character lines on the *
+ * screen, 0 denotes the default for this mode. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID SelectMouseBuffer(half_word mode, half_word lines)
+{
+ DWORD width,
+ height;
+
+
+ /*
+ ** When stdout is being redirected we must not set up the graphics
+ ** buffer for the mouse. Otherwise 32-bit progs like MORE crash
+ ** cos they ask console for the active console handle and get
+ ** confused. We get told by DOS Em. when stdout is being
+ ** redirected and do not set up the buffer.
+ ** Tim Jan 93.
+ */
+ if( stdoutRedirected )
+ return;
+
+ /* Work out the screen resolution. */
+ switch (mode & 0x7f)
+ {
+ case 0x0:
+ case 0x1:
+ width = 640;
+ height = 200;
+ break;
+ case 0x2:
+ case 0x3:
+ case 0x7:
+ switch (lines)
+ {
+ case 0:
+ case 25:
+ saved_text_lines = 25;
+ width = 640;
+ height = 200;
+ break;
+ case 43:
+ saved_text_lines = 43;
+ width = 640;
+ height = 344;
+ break;
+ case 50:
+ saved_text_lines = 50;
+ width = 640;
+ height = 400;
+ break;
+ default:
+ assert1(NO, "strange number of lines for text mode - %d", lines);
+ return;
+ }
+ break;
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0xd:
+ case 0xe:
+ width = 640;
+ height = 200;
+ break;
+ case 0xf:
+ case 0x10:
+ width = 640;
+ height = 350;
+ break;
+ case 0x11:
+ case 0x12:
+ width = 640;
+ height = 480;
+ break;
+ case 0x13:
+ width = 640;
+ height = 200;
+ break;
+ case 0x40:
+ width = 640;
+ height = 400;
+ break;
+ case 0x41:
+ case 0x42:
+ width = 1056;
+ height = 344;
+ break;
+ case 0x43:
+ width = 640;
+ height = 480;
+ break;
+ case 0x44:
+ width = 800;
+ height = 480;
+ break;
+ case 0x45:
+ width = 1056;
+ height = 392;
+ break;
+ case 0x60:
+ width = 752;
+ height = 408;
+ break;
+ case 0x61:
+ width = 720;
+ height = 536;
+ break;
+ case 0x62:
+ width = 800;
+ height = 600;
+ break;
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ width = 1024;
+ height = 768;
+ break;
+ case 0x66:
+ width = 640;
+ height = 400;
+ break;
+ case 0x67:
+ width = 640;
+ height = 480;
+ break;
+ case 0x68:
+ width = 720;
+ height = 540;
+ break;
+ case 0x69:
+ width = 800;
+ height = 600;
+ break;
+ default:
+
+ /* No change if we get an unknown mode. */
+ assert1(NO, "unknown mode - %d", mode);
+ return;
+ }
+
+ //
+ // Set the variables to let apps like Word and Works which call
+ // INT 33h AX = 26h to find out the size of the current virtual
+ // screen.
+ // Andy!
+
+ VirtualX = (word)width;
+ VirtualY = (word)height;
+
+ /* Save current dimensions. */
+ mouse_buffer_width = width;
+ mouse_buffer_height = height;
+
+}
+#endif /* X86GFX */
+
+void host_enable_stream_io(void)
+{
+ sc.ScreenState = STREAM_IO;
+ host_stream_io_enabled = TRUE;
+
+}
+void host_disable_stream_io(void)
+{
+ DWORD mode;
+
+ if(!GetConsoleMode(sc.InputHandle, &mode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+ mode |= (ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
+ if(!SetConsoleMode(sc.InputHandle,mode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+
+
+ if(!GetConsoleMode(sc.OutputHandle, &mode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ if(!stdoutRedirected)
+ {
+ mode &= ~(ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_PROCESSED_OUTPUT);
+
+ if(!SetConsoleMode(sc.OutputHandle,mode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+ }
+
+ ConsoleInit();
+ (void)(*choose_display_mode)();
+ /*
+ ** Copy the console buffer to the regen buffer.
+ ** Don't want to adjust the copy from top of console window, console
+ ** does it itself if we resize the window. Tim September 92.
+ */
+ copyConsoleToRegen(0, 0, VGA_WIDTH, (SHORT)ConVGAHeight);
+
+ /*
+ ** Tim September 92, adjust cursor position if console window size is
+ ** adjusted.
+ */
+ ConsBufferInfo.dwCursorPosition.Y -= ConTopLine;
+
+ /* Set up SoftPC's cursor. */
+ setVDMCursorPosition((UTINY)StartupCharHeight,
+ &ConsBufferInfo.dwCursorPosition);
+
+ if (sc.ScreenState == WINDOWED)
+ enableUpdates();
+
+ MouseAttachMenuItem(sc.ActiveOutputBufferHandle);
+ host_stream_io_enabled = FALSE;
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_graph.c b/private/mvdm/softpc.new/host/src/nt_graph.c
new file mode 100644
index 000000000..a0a56df31
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_graph.c
@@ -0,0 +1,2314 @@
+#include <windows.h>
+#include "host_def.h"
+#include "insignia.h"
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ Name: nt_graph.c
+ Author: Dave Bartlett (based on module by John Shanly)
+ Derived From: X_graph.c
+ Created On: 10/5/1991
+ Sccs ID: @(#)nt_graph.c 1.29 04/17/91
+ Purpose:
+ This modules contain all Win32 specific functions required to
+ support HERC, CGA and EGA emulations. It is by definition
+ Win32 specific. It contains full support for the Host
+ Graphics Interface (HGI).
+
+ This module handles all graphics output to the screen.
+
+ (c)Copyright Insignia Solutions Ltd., 1990. All rights reserved.
+
+ Modifications:
+ Tim August 92. nt_set_paint_routine() no longer calls TextToGraphics()
+ during a full-screen to windowed transition.
+ Tim September 92. New function resizeWindow(), called from textResize()
+ for resizing the console window.
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */
+
+#ifdef X86GFX
+#include <ntddvdeo.h>
+#endif
+#include <sys\types.h>
+
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "ica.h"
+#include "gvi.h"
+#include "cga.h"
+#include "gmi.h"
+#include "gfx_upd.h"
+#include "egagraph.h"
+#include "egacpu.h"
+#include "egaports.h"
+#include "egamode.h"
+#include "host.h"
+#include "host_rrr.h"
+#include "error.h"
+#include "config.h" /* For definition of HERC, CGA, EGA, VGA */
+#include "idetect.h"
+#include "video.h"
+#include "ckmalloc.h"
+#include "conapi.h"
+
+#include "nt_graph.h"
+#include "nt_cga.h"
+#include "nt_ega.h"
+#include "nt_event.h"
+#include "nt_mouse.h"
+#include "ntcheese.h"
+#include "nt_uis.h"
+#include "nt_fulsc.h"
+#include "nt_det.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include "trace.h"
+#include "debug.h"
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: IMPORTS */
+
+/* Globals used in various functions to synchronise the display */
+
+#ifdef EGG
+extern int ega_int_enable;
+#endif
+
+extern byte *video_copy;
+
+static int flush_count = 0; /*count of graphic ticks since last flush*/
+
+// DIB_PAL_INDICES shouldn't be used, use CreateDIBSECTION to get better
+// performance characteristics.
+
+#define DIB_PAL_INDICES 2
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: EXPORTS */
+
+SCREEN_DESCRIPTION sc;
+
+#ifdef BIGWIN
+int horiz_lut[256];
+#endif
+int host_screen_scale;
+int host_display_depth = 8;
+int top_plane;
+char *DIBData;
+PBITMAPINFO MonoDIB;
+PBITMAPINFO CGADIB;
+PBITMAPINFO EGADIB;
+PBITMAPINFO VGADIB;
+
+void (*paint_screen)();
+BOOL FunnyPaintMode;
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Paint functions */
+
+static PAINTFUNCS std_mono_paint_funcs =
+{
+ nt_text,
+ nt_cga_mono_graph_std,
+ nt_cga_mono_graph_std,
+ nt_text,
+ nt_ega_mono_lo_graph_std,
+ nt_ega_mono_med_graph_std,
+ nt_ega_mono_hi_graph_std,
+ nt_vga_mono_graph_std,
+ nt_vga_mono_med_graph_std,
+ nt_vga_mono_hi_graph_std,
+#ifdef V7VGA
+ nt_v7vga_mono_hi_graph_std,
+#endif /* V7VGA */
+};
+
+static PAINTFUNCS big_mono_paint_funcs =
+{
+ nt_text,
+ nt_cga_mono_graph_big,
+ nt_cga_mono_graph_big,
+ nt_text,
+ nt_ega_mono_lo_graph_big,
+ nt_ega_mono_med_graph_big,
+ nt_ega_mono_hi_graph_big,
+ nt_vga_mono_graph_big,
+ nt_vga_mono_med_graph_big,
+ nt_vga_mono_hi_graph_big,
+#ifdef V7VGA
+ nt_v7vga_mono_hi_graph_big,
+#endif /* V7VGA */
+};
+
+static PAINTFUNCS huge_mono_paint_funcs =
+{
+ nt_text,
+ nt_cga_mono_graph_huge,
+ nt_cga_mono_graph_huge,
+ nt_text,
+ nt_ega_mono_lo_graph_huge,
+ nt_ega_mono_med_graph_huge,
+ nt_ega_mono_hi_graph_huge,
+ nt_vga_mono_graph_huge,
+ nt_vga_mono_med_graph_huge,
+ nt_vga_mono_hi_graph_huge,
+#ifdef V7VGA
+ nt_v7vga_mono_hi_graph_huge,
+#endif /* V7VGA */
+};
+
+static PAINTFUNCS std_colour_paint_funcs =
+{
+ nt_text,
+ nt_cga_colour_med_graph_std,
+ nt_cga_colour_hi_graph_std,
+ nt_text,
+ nt_ega_lo_graph_std,
+ nt_ega_med_graph_std,
+ nt_ega_hi_graph_std,
+ nt_vga_graph_std,
+ nt_vga_med_graph_std,
+ nt_vga_hi_graph_std,
+#ifdef V7VGA
+ nt_v7vga_hi_graph_std,
+#endif /* V7VGA */
+};
+
+static PAINTFUNCS big_colour_paint_funcs =
+{
+ nt_text,
+ nt_cga_colour_med_graph_big,
+ nt_cga_colour_hi_graph_big,
+ nt_text,
+ nt_ega_lo_graph_big,
+ nt_ega_med_graph_big,
+ nt_ega_hi_graph_big,
+ nt_vga_graph_big,
+ nt_vga_med_graph_big,
+ nt_vga_hi_graph_big,
+#ifdef V7VGA
+ nt_v7vga_hi_graph_big,
+#endif /* V7VGA */
+};
+
+static PAINTFUNCS huge_colour_paint_funcs =
+{
+ nt_text,
+ nt_cga_colour_med_graph_huge,
+ nt_cga_colour_hi_graph_huge,
+ nt_text,
+ nt_ega_lo_graph_huge,
+ nt_ega_med_graph_huge,
+ nt_ega_hi_graph_huge,
+ nt_vga_graph_huge,
+ nt_vga_med_graph_huge,
+ nt_vga_hi_graph_huge,
+#ifdef V7VGA
+ nt_v7vga_hi_graph_huge,
+#endif /* V7VGA */
+};
+
+#ifdef MONITOR
+static PAINTFUNCS std_frozen_paint_funcs =
+{
+ nt_dummy_frozen,
+ nt_cga_med_frozen_std,
+ nt_cga_hi_frozen_std,
+ nt_dummy_frozen,
+ nt_ega_lo_frozen_std,
+ nt_ega_med_frozen_std,
+ nt_ega_hi_frozen_std,
+ nt_vga_frozen_std,
+ nt_vga_med_frozen_std,
+ nt_vga_hi_frozen_std,
+#ifdef V7VGA
+ nt_dummy_frozen,
+#endif /* V7VGA */
+};
+
+static PAINTFUNCS big_frozen_paint_funcs =
+{
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+#ifdef V7VGA
+ nt_dummy_frozen,
+#endif /* V7VGA */
+};
+
+static PAINTFUNCS huge_frozen_paint_funcs =
+{
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+ nt_dummy_frozen,
+#ifdef V7VGA
+ nt_dummy_frozen,
+#endif /* V7VGA */
+};
+#endif /* MONITOR */
+
+static INITFUNCS mono_init_funcs =
+{
+ nt_init_text,
+ nt_init_cga_mono_graph,
+ nt_init_cga_mono_graph,
+ nt_init_text,
+ nt_init_ega_mono_lo_graph,
+ nt_init_ega_med_graph,
+ nt_init_ega_hi_graph,
+ nt_init_vga_hi_graph,
+};
+
+static INITFUNCS colour_init_funcs =
+{
+ nt_init_text,
+ nt_init_cga_colour_med_graph,
+ nt_init_cga_colour_hi_graph,
+ nt_init_text,
+ nt_init_ega_lo_graph,
+ nt_init_ega_med_graph,
+ nt_init_ega_hi_graph,
+ nt_init_vga_hi_graph,
+};
+
+#ifdef MONITOR
+static INITFUNCS frozen_init_funcs =
+{
+ nt_init_text,
+ nt_init_cga_colour_med_graph,
+ nt_init_cga_colour_hi_graph,
+ nt_init_text,
+ nt_init_ega_lo_graph,
+ nt_init_ega_med_graph,
+ nt_init_ega_hi_graph,
+ nt_init_vga_hi_graph,
+};
+#endif /* MONITOR */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::: Adaptor function protocol */
+
+void nt_init_screen (void);
+void nt_init_adaptor (int, int);
+void nt_change_mode (void);
+void nt_set_screen_scale(int);
+void nt_set_palette(PC_palette *, int);
+void nt_set_border_colour(int);
+void nt_clear_screen (void);
+void nt_flush_screen (void);
+void nt_mark_screen_refresh (void);
+void nt_graphics_tick (void);
+void nt_start_update (void);
+void nt_end_update (void);
+void nt_paint_cursor IPT3(int, cursor_x, int, cursor_y, half_word, attr);
+
+void nt_set_paint_routine(DISPLAY_MODE, int);
+void nt_change_plane_mask(int);
+void nt_update_fonts (void);
+void nt_select_fonts(int, int);
+void nt_free_font(int);
+
+void nt_mode_select_changed(int);
+void nt_color_select_changed(int);
+void nt_screen_address_changed(int, int);
+void nt_cursor_size_changed(int, int);
+void nt_scroll_complete (void);
+void make_cursor_change(void);
+
+boolean nt_scroll_up(int, int, int, int, int, int);
+boolean nt_scroll_down(int, int, int, int, int, int);
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+static PAINTFUNCS *nt_paint_funcs; /* Function ptrs for paint functions */
+static INITFUNCS *nt_init_funcs; /* Function ptrs for init functions */
+
+VIDEOFUNCS nt_video_funcs =
+{
+ nt_init_screen,
+ nt_init_adaptor,
+ nt_change_mode,
+ nt_set_screen_scale,
+ nt_set_palette,
+ nt_set_border_colour,
+ nt_clear_screen,
+ nt_flush_screen,
+ nt_mark_screen_refresh,
+ nt_graphics_tick,
+ nt_start_update,
+ nt_end_update,
+ nt_scroll_up,
+ nt_scroll_down,
+ nt_paint_cursor,
+ nt_set_paint_routine,
+ nt_change_plane_mask,
+ nt_update_fonts,
+ nt_select_fonts,
+ nt_free_font,
+ nt_mode_select_changed,
+ nt_color_select_changed,
+ nt_screen_address_changed,
+ nt_cursor_size_changed,
+ nt_scroll_complete
+};
+
+static int current_char_height = 0;
+static int current_height; /* Use to avoid redundant resizing */
+static int current_width; /* Use to avoid redundant resizing */
+static int current_bits_per_pixel;
+static int current_mode_type = TEXT;
+static int current_mode;
+static int current_scale;
+static int palette_size; /* Size of PC palette */
+static PC_palette *the_palette; /* Pointer to PC palette structure */
+static int update_vlt = FALSE; /* TRUE when new one needed */
+static int host_plane_mask = 0xf;
+static int plane_masks[4];
+
+#ifdef BIGWIN
+
+/*
+ * * tiny_lut[] is the building block of all the strecthing fuctions. * It
+ * performs a two to three bit mapping. * The four entries are three bits
+ * wide. The outside two bits in * each entry are the original bits, the
+ * inside bit is the new bit. * There are two methods to create the new bit: *
+ * 1) Logical Op upon the two old bits eg. OR, AND * 2) Copy one of the bits
+ * eg. New bit will be a copy of the left bit. * static short tiny_lut[4] = {
+ * 0, 3, 6, 7 }; This is an OR * static short tiny_lut[4] = { 0, 1, 6, 7 };
+ * This is a left bit copy * Potential advantage of copy instead of logical
+ * op is that there is no * bias towards white or black versions of the same
+ * image. * eg. when a menu entry is highlighted by inversion. *
+ *
+ * 00 -> 000 * 01 -> 001 * 10 -> 110 * 11 -> 111
+ */
+
+/* favours black if 0, 1, 4, 7, or white if 0, 3, 6, 7 */
+static short tiny_lut[4] =
+{
+ 0, 1, 6, 7
+};
+
+/*
+ * dubble_up is used for simple byte doubling for x2 size windows
+ */
+static word dubble_up[] = {
+ 0x0000, 0x0003, 0x000c, 0x000f, 0x0030, 0x0033, 0x003c, 0x003f, 0x00c0,
+ 0x00c3, 0x00cc, 0x00cf, 0x00f0, 0x00f3, 0x00fc, 0x00ff, 0x0300, 0x0303,
+ 0x030c, 0x030f, 0x0330, 0x0333, 0x033c, 0x033f, 0x03c0, 0x03c3, 0x03cc,
+ 0x03cf, 0x03f0, 0x03f3, 0x03fc, 0x03ff, 0x0c00, 0x0c03, 0x0c0c, 0x0c0f,
+ 0x0c30, 0x0c33, 0x0c3c, 0x0c3f, 0x0cc0, 0x0cc3, 0x0ccc, 0x0ccf, 0x0cf0,
+ 0x0cf3, 0x0cfc, 0x0cff, 0x0f00, 0x0f03, 0x0f0c, 0x0f0f, 0x0f30, 0x0f33,
+ 0x0f3c, 0x0f3f, 0x0fc0, 0x0fc3, 0x0fcc, 0x0fcf, 0x0ff0, 0x0ff3, 0x0ffc,
+ 0x0fff, 0x3000, 0x3003, 0x300c, 0x300f, 0x3030, 0x3033, 0x303c, 0x303f,
+ 0x30c0, 0x30c3, 0x30cc, 0x30cf, 0x30f0, 0x30f3, 0x30fc, 0x30ff, 0x3300,
+ 0x3303, 0x330c, 0x330f, 0x3330, 0x3333, 0x333c, 0x333f, 0x33c0, 0x33c3,
+ 0x33cc, 0x33cf, 0x33f0, 0x33f3, 0x33fc, 0x33ff, 0x3c00, 0x3c03, 0x3c0c,
+ 0x3c0f, 0x3c30, 0x3c33, 0x3c3c, 0x3c3f, 0x3cc0, 0x3cc3, 0x3ccc, 0x3ccf,
+ 0x3cf0, 0x3cf3, 0x3cfc, 0x3cff, 0x3f00, 0x3f03, 0x3f0c, 0x3f0f, 0x3f30,
+ 0x3f33, 0x3f3c, 0x3f3f, 0x3fc0, 0x3fc3, 0x3fcc, 0x3fcf, 0x3ff0, 0x3ff3,
+ 0x3ffc, 0x3fff, 0xc000, 0xc003, 0xc00c, 0xc00f, 0xc030, 0xc033, 0xc03c,
+ 0xc03f, 0xc0c0, 0xc0c3, 0xc0cc, 0xc0cf, 0xc0f0, 0xc0f3, 0xc0fc, 0xc0ff,
+ 0xc300, 0xc303, 0xc30c, 0xc30f, 0xc330, 0xc333, 0xc33c, 0xc33f, 0xc3c0,
+ 0xc3c3, 0xc3cc, 0xc3cf, 0xc3f0, 0xc3f3, 0xc3fc, 0xc3ff, 0xcc00, 0xcc03,
+ 0xcc0c, 0xcc0f, 0xcc30, 0xcc33, 0xcc3c, 0xcc3f, 0xccc0, 0xccc3, 0xcccc,
+ 0xcccf, 0xccf0, 0xccf3, 0xccfc, 0xccff, 0xcf00, 0xcf03, 0xcf0c, 0xcf0f,
+ 0xcf30, 0xcf33, 0xcf3c, 0xcf3f, 0xcfc0, 0xcfc3, 0xcfcc, 0xcfcf, 0xcff0,
+ 0xcff3, 0xcffc, 0xcfff, 0xf000, 0xf003, 0xf00c, 0xf00f, 0xf030, 0xf033,
+ 0xf03c, 0xf03f, 0xf0c0, 0xf0c3, 0xf0cc, 0xf0cf, 0xf0f0, 0xf0f3, 0xf0fc,
+ 0xf0ff, 0xf300, 0xf303, 0xf30c, 0xf30f, 0xf330, 0xf333, 0xf33c, 0xf33f,
+ 0xf3c0, 0xf3c3, 0xf3cc, 0xf3cf, 0xf3f0, 0xf3f3, 0xf3fc, 0xf3ff, 0xfc00,
+ 0xfc03, 0xfc0c, 0xfc0f, 0xfc30, 0xfc33, 0xfc3c, 0xfc3f, 0xfcc0, 0xfcc3,
+ 0xfccc, 0xfccf, 0xfcf0, 0xfcf3, 0xfcfc, 0xfcff, 0xff00, 0xff03, 0xff0c,
+ 0xff0f, 0xff30, 0xff33, 0xff3c, 0xff3f, 0xffc0, 0xffc3, 0xffcc, 0xffcf,
+ 0xfff0, 0xfff3, 0xfffc, 0xffff
+};
+#endif /* BIGWIN */
+
+/*:::::::::: Temporary colour table to make colours work :::::::::::::::*/
+extern BYTE Red[];
+extern BYTE Green[];
+extern BYTE Blue[];
+
+GLOBAL BOOL host_stream_io_enabled = FALSE;
+
+GLOBAL COLOURTAB defaultColours =
+ {
+ DEFAULT_NUM_COLOURS,
+ Red,
+ Green,
+ Blue,
+ };
+
+BYTE Mono[] = { 0, 0xff };
+
+GLOBAL COLOURTAB monoColours =
+ {
+ MONO_COLOURS,
+ Mono,
+ Mono,
+ Mono,
+ };
+
+/*
+ * Bit masks for attribute bytes
+ */
+
+#define BOLD 0x08 /* Bold bit */
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::: Useful Constants */
+
+#define MOUSE_DELAY 2
+#define TICKS_PER_FLUSH 2 /* PC ticks per screen flush */
+
+/*:::::::::::::::::::::::::::::::::::::::::: Not supporting v7vga mode, yet */
+
+#undef is_v7vga_mode
+#define is_v7vga_mode(x) (FALSE)
+
+static int mode_change_now;
+static int ega_tick_delay;
+static BOOL CursorResizeNeeded = FALSE;
+
+/*:::::::::::: Definition of local functions declared later in file ????????*/
+void set_screen_sizes();
+void check_win_size();
+void select_paint_routines();
+void dummy_paint_screen();
+#ifdef BIGWIN
+void init_lut();
+#endif
+void prepare_surface();
+
+
+
+
+/*
+ * ================================================================
+ * Functions supporting the Host Graphics Interface (HGI)
+ * ================================================================
+ */
+
+/*
+*****************************************************************************
+** closeGraphicsBuffer()
+*****************************************************************************
+** Centralised place to close (and destroy) graphics buffer. For X86 and JAZZ
+** Tim October 92.
+**
+** sc.ScreenBufHandle is handle to the graphics buffer
+** sc.OutputHandle is handle to the text buffer
+**
+** Important to set the successfully closed handle to NULL.
+** Safety first, set the active handle to sc.OutputHandle before attempting
+** to close the graphics buffer handle.
+**
+** Small change: only do this if sc.ScreenBufHandle is set, otherwise bad
+** things happen. Screen flashes when we suspend in full-screen and during
+** a transition to full-screen in text mode, whatever is on screen gets
+** written to B800 - not a good idea if page 2 is active (This happens
+** in Brief). Tim and DAB Jan 93.
+*/
+GLOBAL VOID closeGraphicsBuffer IFN0()
+{
+ if( sc.ScreenBufHandle != (HANDLE)0 ){
+
+ MouseDetachMenuItem(TRUE);
+
+ if( !SetConsoleActiveScreenBuffer( sc.OutputHandle ) ){
+ assert2( NO, "VDM: SCASB() failed:%#x H=%#x",
+ GetLastError(), sc.OutputHandle );
+ }
+
+ /*
+ * Cleanup ALL handles associated with screen buffer
+ * 01-Mar-1993 Jonle
+ */
+ CloseHandle(sc.ScreenBufHandle);
+ sc.ScreenBufHandle = (HANDLE)0;
+ sc.ColPalette = (HPALETTE)0;
+
+ /*
+ * Point to the current output handle.
+ */
+ sc.ActiveOutputBufferHandle = sc.OutputHandle;
+ MouseAttachMenuItem(sc.ActiveOutputBufferHandle);
+
+#ifndef MONITOR
+ //
+ // Turn the pointer back on when going from graphics
+ // to text mode since the selected buffer has changed
+ //
+
+ MouseDisplay();
+#endif // MONITOR
+
+ CloseHandle(sc.ConsoleBufInfo.hMutex);
+ sc.ConsoleBufInfo.hMutex = 0;
+#ifdef X86GFX
+
+ /*
+ * Make sure a buffer is selected next time SelectMouseBuffer
+ * is called.
+ */
+ mouse_buffer_width = 0;
+ mouse_buffer_height = 0;
+#endif /* X86GFX */
+ }
+} /* end of closeGraphicsBuffer() */
+
+GLOBAL void resetWindowParams()
+{
+ /*
+ * Reset saved video params
+ */
+ current_height = current_width = 0;
+ current_char_height = 0;
+ current_mode_type = TEXT;
+ current_bits_per_pixel = 0;
+ current_scale = 0;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::: Initialise screen :::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_screen(void)
+{
+ static int med_res_swapped = FALSE;
+ static boolean already_called = FALSE;
+
+#ifdef X86GFX
+ sc.Registered = FALSE;
+#endif
+ sub_note_trace0(ALL_ADAPT_VERBOSE, "nt_init_screen\n");
+
+ /* If an error occurs before the user interface has been initialised then
+ host_error makes a call to nt_init_screen. Thus a check is made here to
+ see if the user interface has already been initialised. If it has then
+ this function should simply return. */
+
+ if(already_called) return;
+
+ already_called = TRUE;
+
+#ifdef BIGWIN
+ /* set up the look-up-table for fast horizontal stretching */
+ init_lut();
+#endif
+
+ /*:::::::::::::::::::::::::::::::::::::::::: Allocate video copy buffer */
+
+#ifdef MONITOR
+ if(!video_copy) video_copy = (byte *) host_malloc(0x8000);
+#else
+ if(!video_copy) video_copy = (byte *) host_malloc(0x20000);
+#endif
+
+ /*::::::::::::::::::::::::::::::::: Allocate DAC and EGA planes buffers */
+
+ if(!EGA_planes) EGA_planes = (byte *) host_malloc(4*EGA_PLANE_SIZE);
+ if(!DAC) DAC = (PC_palette *) host_malloc(sizeof(PC_palette) * VGA_DAC_SIZE);
+
+ if (video_copy == NULL || EGA_planes == NULL || DAC == NULL)
+ host_error(EG_MALLOC_FAILURE, ERR_QUIT, "");
+
+ /* Set current screen height to prevent the window changing shape between
+ init_screen and init_adaptor */
+
+ video_adapter = (half_word) config_inquire(C_GFX_ADAPTER, NULL);
+ switch (video_adapter)
+ {
+ case CGA:
+ current_height = CGA_WIN_HEIGHT; current_width = CGA_WIN_WIDTH;
+ break;
+
+ case EGA:
+ current_height = EGA_WIN_HEIGHT; current_width = EGA_WIN_WIDTH;
+ break;
+ }
+
+ /*::::::::::::::::: Setup the screen dimensions for the initial adaptor */
+
+ host_set_screen_scale((SHORT) config_inquire(C_WIN_SIZE, NULL));
+ set_screen_sizes(video_adapter);
+
+ /*:::: Set pixel values to be used for FG and BG (mainly in mono modes) */
+
+ sc.PCForeground = RGB(255,255,255); /* White RGB */
+ sc.PCBackground = RGB(0,0,0); /* Black RGB */
+
+ /* Choose the routines appropriate for the monitor and window size. */
+ select_paint_routines();
+}
+
+#ifdef MONITOR
+/* The mouse calls this func when it sees a mode change. If we're windowed
+ * we pass it off to the softpc bios (who may want to switch to fullscreen).
+ * If we're fullscreen we do nothing as the native bios will take care of
+ * everything.
+ */
+void host_call_bios_mode_change(void)
+{
+ extern void ega_video_io();
+ half_word mode;
+
+ if (sc.ScreenState == WINDOWED)
+ {
+ ega_video_io();
+ }
+ else
+ {
+
+ /*
+ * We have a fullscreen mode change so we need to change the mouse
+ * buffer so that we get mouse coordinates of the correct resolution.
+ */
+ mode = getAL();
+ SelectMouseBuffer(mode, 0);
+ }
+}
+#endif /* MONITOR */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::: Initialise adaptor ::::::::::::::::::::::::::::*/
+
+void nt_init_adaptor(int adaptor, int height)
+{
+ sub_note_trace2(ALL_ADAPT_VERBOSE,
+ "nt_init_adaptor adapt=%d height=%d\n", adaptor, height);
+
+ /*Avoid delaying mode changes,otherwise update may use old paint routines*/
+
+ if((adaptor == EGA) || (adaptor == VGA))
+ mode_change_now = ega_tick_delay = 0;
+
+ // Lose for console integration
+ // set_screen_sizes(adaptor);
+ // check_win_size(height);
+ // prepare_surface();
+ // nt_change_mode();
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::: Called at every mode change to initialise fonts etc ::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_change_mode(void)
+{
+ /*::::::::::::::::::::::::::::::::::::: Display current postion in code */
+
+ sub_note_trace0(ALL_ADAPT_VERBOSE, "nt_change_mode");
+
+ /*:::::::::::::::::::: Setup update vectors and initialise paint system */
+
+ switch(video_adapter)
+ {
+ /*::::::::::::::::::::::::::::::::::::::::::::::: CGA mode selected */
+
+ case CGA: // Adapter is always VGA on NT
+ break;
+
+ /*::::::::::::::::::::::::::::::::::::::: EGA or VGA modes selected */
+
+ case EGA: case VGA:
+ break;
+
+ /*::::::::::::::::::::::::::::::::::::::::::: Unknown viseo adaptor */
+
+ default:
+ sub_note_trace0(ALL_ADAPT_VERBOSE,"**** Unknown video adaptor ****");
+ break;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::: Clear screen :::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_clear_screen(void)
+{
+ CONSOLE_SCREEN_BUFFER_INFO ScreenInfo;
+ COORD coord;
+ DWORD nCharWritten;
+ IMPORT int soft_reset;
+
+ if ((! ConsoleInitialised) || (! soft_reset)) // ignore startup stuff
+ return;
+
+ if (ConsoleNoUpdates)
+ return;
+
+ sub_note_trace0(ALL_ADAPT_VERBOSE, "nt_clear_screen");
+
+ if(sc.ScreenBufHandle) return;
+
+#ifndef X86GFX
+ if (sc.ScreenState == FULLSCREEN) // don't want sudden screen clears
+ return;
+#endif
+
+ /*::::::::::::::::::::::::::::: Get information on current screen size */
+
+ GetConsoleScreenBufferInfo(sc.OutputHandle,&ScreenInfo);
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::: Clear characters */
+
+ coord.X = coord.Y = 0;
+ FillConsoleOutputCharacter(sc.OutputHandle, ' ',
+ ScreenInfo.dwSize.X * ScreenInfo.dwSize.Y,
+ coord,&nCharWritten);
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::: Clear Attributes */
+
+ coord.X = coord.Y = 0;
+ FillConsoleOutputAttribute(sc.OutputHandle, (WORD) sc.PCBackground,
+ ScreenInfo.dwSize.X * ScreenInfo.dwSize.Y,
+ coord,&nCharWritten);
+#ifdef MONITOR
+ /*
+ ** Called during a mode change...
+ ** Trash video copy so future updates will know what has changed.
+ ** Alternatively mon_text_update() could listen to dirty_flag.
+ */
+ memfill( 0xff, &video_copy[ 0 ], &video_copy[ 0x7fff ] ); /* Tim Oct 92 */
+#endif
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::: Flush screen :::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_flush_screen(void)
+{
+ sub_note_trace0(ALL_ADAPT_VERBOSE, "nt_flush_screen");
+
+ if (ConsoleInitialised == TRUE && ConsoleNoUpdates == FALSE &&
+ !get_mode_change_required())
+#ifdef X86GFX
+ if (sc.ScreenState == WINDOWED)
+#endif
+ (void)(*update_alg.calc_update)();
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Mark screen for refresh :::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_mark_screen_refresh(void)
+{
+ sub_note_trace0(ALL_ADAPT_VERBOSE, "nt_mark_screen_refresh");
+
+ screen_refresh_required();
+ update_vlt = TRUE;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::: Handle graphics ticks ::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_graphics_tick(void)
+{
+
+ if (sc.ScreenState == STREAM_IO) {
+ if (++flush_count == TICKS_PER_FLUSH){
+ stream_io_update();
+ flush_count = 0;
+ }
+ return;
+ }
+
+#ifdef EGG
+ if((video_adapter == EGA) || (video_adapter == VGA))
+ {
+ /* two timer ticks since mode_change_required became true ?
+ (really need same stuff for CGA, but not done yet)
+ Now just delay screen update, & only if display REALLY changed */
+
+ /*
+ ** When VGA registers get hit during a mode change, postpone
+ ** the call to *choose_display_mode() by EGA_TICK_DELAY ticks.
+ ** This will delay window resizing and eliminate possibility
+ ** of doing it more than once per mode change. Tim Jan 93.
+ */
+
+ /*Has mode_change_required been set (implying EGA regs have changed)*/
+ if (mode_change_now) {
+ if (--mode_change_now == 0) {
+ (void)(*choose_display_mode)();
+ // must do this after video mode has been selected
+ // otherwise, the mouse code can come in and update the
+ // screen. See nt_flush_screen
+ set_mode_change_required(FALSE);
+ }
+ }
+ else if (get_mode_change_required()) {
+ mode_change_now = EGA_TICK_DELAY - 1;
+ /* Delay mouse input and flush all pending mouse events. */
+ DelayMouseEvents(MOUSE_DELAY);
+ }
+ else
+ {
+ /*................ Only update if a mode change is not imminent */
+
+ if(++flush_count == TICKS_PER_FLUSH)
+ {
+
+ if(update_vlt || get_palette_change_required())
+ set_the_vlt();
+
+ if (ConsoleInitialised == TRUE && ConsoleNoUpdates == FALSE)
+#ifdef X86GFX
+ if (sc.ScreenState == WINDOWED)
+#endif
+ (void)(*update_alg.calc_update)();
+
+ ega_tick_delay = EGA_TICK_DELAY;
+
+ /* batch cursor changes as some naffola apps (Word) change
+ * cursor around every char!!
+ */
+ if (CursorResizeNeeded)
+ make_cursor_change();
+
+ flush_count = 0;
+ }
+ }
+ }
+ else
+#endif /* EGG */
+ {
+ /*:::::::::: Update the screen as required for mda and cga and herc */
+
+ if(++flush_count == TICKS_PER_FLUSH)
+ {
+ if(update_vlt) set_the_vlt();
+
+ if (ConsoleInitialised == TRUE && ConsoleNoUpdates == FALSE)
+#ifdef X86GFX
+ if (sc.ScreenState == WINDOWED)
+#endif
+ (void)(*update_alg.calc_update)();
+
+ flush_count = 0;
+ }
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Start screen update ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_start_update(void)
+{
+ IDLE_video();
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: End screen update ::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_end_update(void) { }
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::: Scroll screen up :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+boolean nt_scroll_up(int tlx, int tly, int brx, int bry, int amount, int col)
+{
+ CONSOLE_SCREEN_BUFFER_INFO ScreenInfo;
+ COORD dwDestinationOrigin; /* Location of rectangle */
+ SMALL_RECT ScrollRectangle; /* Rectangle to scroll */
+ CHAR_INFO Fill; /* Fill exposed region with */
+
+ return(FALSE);
+
+ /*::::::::::::::::::::::::::::::::: Tell the outside world where we are */
+
+ sub_note_trace6(ALL_ADAPT_VERBOSE,
+ "nt_scroll_up tlx=%d tly=%d brx=%d bry=%d amount=%d col=%d\n",
+ tlx, tly, brx, bry, amount, col);
+
+ if(sc.ScreenBufHandle || sc.ModeType == GRAPHICS)
+ return(FALSE); //Screen buffer undefined or in graphics mode
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+#ifdef BIGWIN
+ tlx = SCALE(tlx);
+ tly = SCALE(tly);
+ brx = brx & 1 ? SCALE(brx + 1) - 1 : SCALE(brx);
+ bry = bry & 1 ? SCALE(bry + 1) - 1 : SCALE(bry);
+
+ /* odd numbers don't multiply by 1.5 very accurately */
+ amount = SCALE(amount);
+#endif
+
+
+ /* is this a scroll or just an area fill? */
+ if (bry - tly - amount + 1 == 0)
+ {
+ //DbgPrint("F");
+ return(FALSE); // its just a fill HACK - should do this with host fill
+ }
+
+ /*:::::::::::::::::::::::::::::::::::::: Get Console screen information */
+
+ GetConsoleScreenBufferInfo(sc.OutputHandle, &ScreenInfo);
+
+ /*::::::::::::::::::::::::::::::::::::::: Calculate rectangle to scroll */
+
+ ScrollRectangle.Top = (tly + amount) / get_char_height();
+ ScrollRectangle.Left = tlx / get_pix_char_width();
+
+ ScrollRectangle.Bottom = bry / get_char_height();
+ ScrollRectangle.Right = brx / get_pix_char_width();
+
+ /*::::::::::::::::::::::::::::::::::::: Calculate destination rectangle */
+
+ dwDestinationOrigin.Y = tly / get_char_height();
+ dwDestinationOrigin.X = ScrollRectangle.Left;
+
+ /*::::: Setup fill character information for area exposed by the scroll */
+
+ Fill.Char.AsciiChar = ' ';
+ Fill.Attributes = col << 4;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::: Scroll screen */
+
+ //DbgPrint(".");
+ ScrollConsoleScreenBuffer(sc.OutputHandle, &ScrollRectangle,
+ NULL, dwDestinationOrigin, &Fill);
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::: Fill in exposed area */
+
+ return(TRUE);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Scroll screen down :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+boolean nt_scroll_down(int tlx,int tly,int brx,int bry,int amount,int col)
+{
+ CONSOLE_SCREEN_BUFFER_INFO ScreenInfo;
+ COORD dwDestinationOrigin; /* Location of rectangle */
+ SMALL_RECT ScrollRectangle; /* Rectangle to scroll */
+ CHAR_INFO Fill; /* Fill exposed region with */
+
+ /*::::::::::::::::::::::::::::::::: Tell the outside world where we are */
+
+ sub_note_trace6(ALL_ADAPT_VERBOSE,
+ "nt_scroll_down tlx=%d tly=%d brx=%d bry=%d amount=%d col=%d\n",
+ tlx, tly, brx, bry, amount, col);
+
+ return(FALSE);
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+ if(sc.ScreenBufHandle) return(FALSE);
+
+#ifdef BIGWIN
+ tlx = SCALE(tlx);
+ tly = SCALE(tly);
+ brx = brx & 1 ? SCALE(brx + 1) - 1 : SCALE(brx);
+ bry = bry & 1 ? SCALE(bry + 1) - 1 : SCALE(bry);
+
+ /* odd numbers don't multiply by 1.5 very accurately */
+ amount = SCALE(amount);
+#endif
+ if (sc.ModeType == GRAPHICS)
+ return(FALSE); // don't think console can scroll graphics
+
+ /* is this a scroll or just an area fill? */
+ if (bry - tly - amount + 1 == 0) {
+ return(FALSE); // its just a fill HACK - should do this with host fill
+ }
+
+ /*:::::::::::::::::::::::::::::::::::::: Get Console screen information */
+
+ GetConsoleScreenBufferInfo(sc.OutputHandle, &ScreenInfo);
+
+ /*::::::::::::::::::::::::::::::::::::::: Calculate rectangle to scroll */
+
+ ScrollRectangle.Top = tly / get_char_height();
+ ScrollRectangle.Left = tlx / get_pix_char_width();
+
+ ScrollRectangle.Bottom = (bry - amount) / get_char_height();
+ ScrollRectangle.Right = brx / get_pix_char_width();
+
+ /*::::::::::::::::::::::::::::::::::::: Calculate destination rectangle */
+
+ dwDestinationOrigin.Y = ScrollRectangle.Top + (amount / get_char_height());
+ dwDestinationOrigin.X = ScrollRectangle.Left;
+
+ /*::::: Setup fill character information for area exposed by the scroll */
+
+ Fill.Char.AsciiChar = ' ';
+ Fill.Attributes = col << 4;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::: Scroll screen */
+
+ ScrollConsoleScreenBuffer(sc.OutputHandle, &ScrollRectangle,
+ NULL, dwDestinationOrigin, &Fill);
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::: Fill in exposed area */
+
+ return(TRUE);
+
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Paint cursor :::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_paint_cursor IFN3(int, cursor_x, int, cursor_y, half_word, attr)
+{
+ COORD CursorPos;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::: Guess where we are */
+
+ sub_note_trace3(ALL_ADAPT_VERBOSE, "nt_paint_cursor x=%d, y=%d, attr=%d\n",
+ cursor_x, cursor_y, attr);
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::: Update cursor */
+
+ if(is_cursor_visible() && (get_screen_height() > cursor_y))
+ {
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::: Draw cursor */
+
+ if(get_cursor_height() > 0)
+ {
+ /*...................................... Set new cursor postion */
+
+ CursorPos.X = cursor_x; CursorPos.Y = cursor_y;
+ SetConsoleCursorPosition(sc.OutputHandle,CursorPos);
+ }
+ }
+}
+
+void nt_cursor_size_changed(int lo, int hi)
+{
+ UNREFERENCED_FORMAL_PARAMETER(lo);
+ UNREFERENCED_FORMAL_PARAMETER(hi);
+ CursorResizeNeeded = TRUE;
+}
+
+void make_cursor_change(void)
+{
+ CONSOLE_CURSOR_INFO CursorInfo;
+ CONSOLE_FONT_INFO font;
+ COORD fontsize;
+
+ SAVED DWORD CurrentCursorSize = (DWORD)-1;
+ SAVED BOOL CurNowOff = FALSE;
+
+ if(sc.ScreenState == FULLSCREEN) return;
+
+ CursorResizeNeeded = FALSE;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::: Update cursor */
+
+ if(is_cursor_visible())
+ {
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::: Draw cursor */
+
+ if(get_cursor_height() > 0)
+ {
+ /*...........................................Change cursor size */
+
+ if(get_cursor_height())
+ {
+ /* value has to be percentage of block filled */
+ CursorInfo.dwSize = (get_cursor_height() * 100)/get_char_height();
+ /* %age may be too small on smaller fonts, check size */
+ fontsize.X = fontsize.Y = 0;
+
+ /* get font index */
+ if (GetCurrentConsoleFont(sc.OutputHandle, TRUE, &font) == FALSE)
+ CursorInfo.dwSize = 20; /* min 20% */
+ else
+ {
+ fontsize = GetConsoleFontSize(sc.OutputHandle, font.nFont);
+ if (fontsize.Y != 0) /* what's the error return???? */
+ {
+ if(((WORD)(100 / fontsize.Y)) >= CursorInfo.dwSize)
+ CursorInfo.dwSize = (DWORD) (100/fontsize.Y + 1);
+ }
+ else
+ CursorInfo.dwSize = (DWORD)20; /* min 20% */
+ }
+
+ if(CurrentCursorSize != CursorInfo.dwSize || CurNowOff)
+ {
+ CurrentCursorSize = CursorInfo.dwSize;
+ CurNowOff = FALSE;
+ CursorInfo.bVisible = TRUE;
+ SetConsoleCursorInfo(sc.OutputHandle,&CursorInfo);
+ }
+ }
+ }
+ }
+ else /* Turn cursor image off */
+ {
+ if (CurNowOff == FALSE)
+ {
+ CursorInfo.dwSize = 1;
+ CursorInfo.bVisible = FALSE;
+ SetConsoleCursorInfo(sc.OutputHandle,&CursorInfo);
+ CurNowOff = TRUE;
+ }
+ }
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::: Set up the appropriate paint routine :::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_set_paint_routine(DISPLAY_MODE mode, int height)
+{
+ int oldModeType;
+
+ /* Tracing message. */
+ sub_note_trace2(ALL_ADAPT_VERBOSE, "nt_set_paint_routine mode=%d height=%d", mode, height);
+
+ /* Save old mode type for checking for text -> graphics transition. */
+ oldModeType = sc.ModeType;
+
+ /* For freezing. */
+ FunnyPaintMode = FALSE;
+
+ /* Set up paint vectors. */
+ switch((int) mode)
+ {
+
+ /* CGA modes (40 columns). */
+ case TEXT_40_FUN:
+ assert1(NO,"Funny text mode selected %s",get_mode_string(mode));
+ FunnyPaintMode = TRUE;
+ case CGA_TEXT_40_SP:
+ case CGA_TEXT_40_SP_WR:
+ case CGA_TEXT_40:
+ case CGA_TEXT_40_WR:
+ sc.ModeType = TEXT;
+ paint_screen = nt_paint_funcs->cga_text;
+ (*nt_init_funcs->cga_text) ();
+ break;
+
+ /* CGA modes (80 columns). */
+ case TEXT_80_FUN:
+ assert1(NO,"Funny text mode selected %s",get_mode_string(mode));
+ FunnyPaintMode = TRUE;
+ case CGA_TEXT_80_SP:
+ case CGA_TEXT_80_SP_WR:
+ case CGA_TEXT_80:
+ case CGA_TEXT_80_WR:
+ sc.ModeType = TEXT;
+ paint_screen = nt_paint_funcs->cga_text;
+ (*nt_init_funcs->cga_text) ();
+ break;
+
+ /* CGA modes (graphics). */
+ case CGA_MED_FUN:
+ assert1(NO,"Funny graphics mode %s",get_mode_string(mode));
+ FunnyPaintMode = TRUE;
+ case CGA_MED:
+ sc.ModeType = GRAPHICS;
+ paint_screen = nt_paint_funcs->cga_med_graph;
+ (*nt_init_funcs->cga_med_graph)();
+ break;
+
+ case CGA_HI_FUN:
+ assert1(NO,"Funny graphics mode %s",get_mode_string(mode));
+ FunnyPaintMode = TRUE;
+ case CGA_HI:
+ sc.ModeType = GRAPHICS;
+ paint_screen = nt_paint_funcs->cga_hi_graph;
+ (*nt_init_funcs->cga_hi_graph)();
+ break;
+
+ /* EGA modes (40 columns). */
+ case EGA_TEXT_40_SP:
+ case EGA_TEXT_40_SP_WR:
+ case EGA_TEXT_40:
+ case EGA_TEXT_40_WR:
+ sc.ModeType = TEXT;
+ paint_screen = nt_paint_funcs->ega_text;
+ (*nt_init_funcs->ega_text) ();
+ break;
+
+ /* EGA modes (80 columns) */
+ case EGA_TEXT_80_SP:
+ case EGA_TEXT_80_SP_WR:
+ case EGA_TEXT_80:
+ case EGA_TEXT_80_WR:
+ sc.ModeType = TEXT;
+ paint_screen = nt_paint_funcs->ega_text;
+ (*nt_init_funcs->ega_text) ();
+ break;
+
+ /* EGA modes (graphics). */
+ case EGA_HI_FUN:
+ assert1(NO, "Funny graphics mode %s", get_mode_string(mode));
+ FunnyPaintMode = TRUE;
+ case EGA_HI:
+ case EGA_HI_WR:
+ case EGA_HI_SP:
+ case EGA_HI_SP_WR:
+ sc.ModeType = GRAPHICS;
+ if(get_256_colour_mode())
+ {
+#ifdef V7VGA
+ if (get_seq_chain4_mode() && get_chain4_mode())
+ {
+ paint_screen = nt_paint_funcs->v7vga_hi_graph;
+ (*nt_init_funcs->vga_hi_graph)();
+ }
+ else
+#endif /* V7VGA */
+ {
+ if (get_chain4_mode())
+ {
+#ifdef MONITOR
+ if (nt_paint_funcs == &std_frozen_paint_funcs)
+ if (Frozen256Packed) //2 possible frozen formats
+ paint_screen = nt_vga_frozen_pack_std;
+ else
+ paint_screen = nt_paint_funcs->vga_graph;
+ else
+#endif /* MONITOR */
+ paint_screen = nt_paint_funcs->vga_graph;
+ }
+ else
+ {
+ if (get_char_height() == 2)
+ paint_screen = nt_paint_funcs->vga_med_graph;
+ else
+ paint_screen = nt_paint_funcs->vga_hi_graph;
+ }
+ (*nt_init_funcs->vga_hi_graph)();
+ }
+ }
+ else
+ {
+ paint_screen = nt_paint_funcs->ega_hi_graph;
+ (*nt_init_funcs->ega_hi_graph)();
+ }
+ break;
+
+ case EGA_MED_FUN:
+ assert1(NO, "Funny graphics mode %s", get_mode_string(mode));
+ FunnyPaintMode = TRUE;
+ case EGA_MED:
+ case EGA_MED_WR:
+ case EGA_MED_SP:
+ case EGA_MED_SP_WR:
+ sc.ModeType = GRAPHICS;
+ paint_screen = nt_paint_funcs->ega_med_graph;
+ (*nt_init_funcs->ega_med_graph)();
+ break;
+
+ case EGA_LO_FUN:
+ assert1(NO, "Funny graphics mode %s", get_mode_string(mode));
+ FunnyPaintMode = TRUE;
+ case EGA_LO:
+ case EGA_LO_WR:
+ case EGA_LO_SP:
+ case EGA_LO_SP_WR:
+ sc.ModeType = GRAPHICS;
+ paint_screen = nt_paint_funcs->ega_lo_graph;
+ (*nt_init_funcs->ega_lo_graph)();
+ break;
+
+ default:
+ assert1(NO,"bad mode for host paint routine selection %d\n",(int)mode);
+ paint_screen = dummy_paint_screen;
+ break;
+ }
+
+#ifdef X86GFX
+ /*
+ * Display a message for the user if changing from a text mode to a
+ * graphics mode while windowed. This is because graphics modes must be
+ * run full-screen.
+ */
+ {
+ /*
+ ** Tim August 92. Do not want to do a TextToGraphics() during a
+ ** full-screen to windowed transition. Otherwise the display gets
+ ** set back to full-screen!
+ */
+ extern int BlockModeChange; /* Tim August 92, in nt_fulsc.c */
+ if ((BlockModeChange == 0) &&
+ (sc.ScreenState == WINDOWED) &&
+ (oldModeType == TEXT) &&
+ (sc.ModeType == GRAPHICS))
+ {
+ TextToGraphics();
+ }
+ else
+ {
+
+ /* No call to TextToGraphics() */
+ check_win_size(height);
+ }
+ }
+#else
+
+ /*................................................... Apply mode change */
+ check_win_size(height);
+#endif /* X86GFX */
+ current_mode = mode;
+}
+
+#ifdef BIGWIN
+/* creates lut for medium or high resolution bit map stretching */
+
+static void
+init_lut()
+
+{
+ long i;
+
+ for (i = 0; i < 256; i++)
+ {
+ horiz_lut[i] = ((tiny_lut[i & 3])
+ + (tiny_lut[(i >> 2) & 3] << 3)
+ + (tiny_lut[(i >> 4) & 3] << 6)
+ + (tiny_lut[(i >> 6) & 3] << 9));
+ }
+}
+
+
+/* 8 bit lut version */
+/* expands a high resolution bitmap by a half horizontally */
+
+void high_stretch3(buffer, length)
+
+unsigned char *buffer;
+int length;
+{
+ int inp, outp;
+ register long temp;
+
+ outp = SCALE(length) - 1;
+
+ for(inp = length - 1; inp > 0;)
+ {
+ temp = horiz_lut[buffer[inp]] | (horiz_lut[buffer[inp - 1]] << 12);
+ inp -= 2;
+
+ buffer[outp--] = (unsigned char) temp;
+ buffer[outp--] = (unsigned char) (temp >> 8);
+ buffer[outp--] = (unsigned char) (temp >> 16);
+ }
+}
+
+void high_stretch4(buffer, length)
+
+unsigned char *buffer;
+int length;
+{
+ int inp, outp;
+ word temp;
+
+ outp = SCALE(length - 1);
+
+ for(inp = length - 1; inp >= 0; inp--, outp -= 2)
+ {
+ temp = dubble_up[buffer[inp]];
+ buffer[outp+1] = (unsigned char) (temp & 0xff);
+ buffer[outp] = (unsigned char) ((temp >> 8) & 0xff);
+ }
+}
+#endif /* BIGWIN */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Select paint routines :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+static void select_paint_routines(void)
+{
+ /*::::::::::::::::::::::::::::::::::::::::::: Display trace information */
+
+ sub_note_trace2((CGA_HOST_VERBOSE | EGA_HOST_VERBOSE),
+ "select_paint_routine scale=%d depth=%d",
+ get_screen_scale(), host_display_depth);
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::: Select paint routines */
+
+ if(host_display_depth > 1)
+ {
+ if (get_screen_scale() == 2)
+ nt_paint_funcs = &std_colour_paint_funcs;
+ else if (get_screen_scale() == 3)
+ nt_paint_funcs = &big_colour_paint_funcs;
+ else
+ nt_paint_funcs = &huge_colour_paint_funcs;
+
+ nt_init_funcs = &colour_init_funcs;
+ }
+ else
+ {
+ if (get_screen_scale() == 2)
+ nt_paint_funcs = &std_mono_paint_funcs;
+ else if (get_screen_scale() == 3)
+ nt_paint_funcs = &big_mono_paint_funcs;
+ else
+ nt_paint_funcs = &huge_mono_paint_funcs;
+
+ nt_init_funcs = &mono_init_funcs;
+ }
+}
+
+#ifdef MONITOR
+GLOBAL void select_frozen_routines(void)
+{
+ if (get_screen_scale() == 2)
+ nt_paint_funcs = &std_frozen_paint_funcs;
+ else if (get_screen_scale() == 3)
+ nt_paint_funcs = &big_frozen_paint_funcs;
+ else
+ nt_paint_funcs = &huge_frozen_paint_funcs;
+
+ nt_init_funcs = &frozen_init_funcs;
+}
+#endif /* MONITOR */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::: Prepare surface :::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void prepare_surface(void)
+{
+ CONSOLE_SCREEN_BUFFER_INFO ScreenInfo;
+ COORD coord;
+ DWORD nCharWritten;
+
+ sub_note_trace0(ALL_ADAPT_VERBOSE, "prepare surface");
+
+ /*:::::::::::::::::::::::::::::: Get information on current screen size */
+
+ GetConsoleScreenBufferInfo(sc.OutputHandle,&ScreenInfo);
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::::: Clear characters */
+
+ coord.X = coord.Y = 0;
+ FillConsoleOutputCharacter(sc.OutputHandle, ' ',
+ ScreenInfo.dwSize.X * ScreenInfo.dwSize.Y,
+ coord,&nCharWritten);
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::::: Clear Attributes */
+
+ coord.X = coord.Y = 0;
+ FillConsoleOutputAttribute(sc.OutputHandle, (WORD) sc.PCBackground,
+ ScreenInfo.dwSize.X * ScreenInfo.dwSize.Y,
+ coord,&nCharWritten);
+
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Global function to tell anybody what the screen scale is :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+int get_screen_scale(void) { return(host_screen_scale); }
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Reverse word :::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+half_word reverser(register half_word value)
+{
+ return( (half_word)
+ (((value & 1) << 7) |
+ ((value & 2) << 5) |
+ ((value & 4) << 3) |
+ ((value & 8) << 1) |
+ ((value & 16) >> 1) |
+ ((value & 32) >> 3) |
+ ((value & 64) >> 5) |
+ ((value & 128) >> 7)));
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Check window size ::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+static void check_win_size(register int height)
+{
+ register int width;
+ extern int soft_reset;
+
+ if (! soft_reset) // we want top get the chance to integrate with
+ return; // console before changing size
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::: Calculate screen width */
+
+ if(sas_hw_at(vd_video_mode) > 0x10)
+ {
+ if(alpha_num_mode())
+ width = get_chars_per_line() * get_pix_char_width();
+ else
+ width = get_chars_per_line() * get_char_width() *
+ (get_256_colour_mode() ? 2 : 1);
+ if (width == 0)
+ width = CGA_WIN_WIDTH;
+ }
+ else
+ width = CGA_WIN_WIDTH;
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::::: Resize window */
+
+ if (sc.ModeType == TEXT)
+ {
+ if((current_mode_type != TEXT) ||
+ (get_char_height() != current_char_height) ||
+ (current_height != height) ||
+ (current_width != width))
+ {
+
+ /* Get width and height. Note no SCALE for text modes. */
+ sc.PC_W_Width = width;
+ sc.PC_W_Height = height*get_host_pix_height();
+ textResize();
+
+ current_height = height;
+ current_width = width;
+ current_mode_type = TEXT;
+ current_char_height = get_char_height();
+ }
+ }
+ else
+ {
+ if((current_mode_type != GRAPHICS) ||
+ (current_height != height) ||
+ (current_width != width) ||
+ (current_bits_per_pixel != sc.BitsPerPixel) ||
+ (current_scale != host_screen_scale))
+ {
+ sc.PC_W_Width = SCALE(width);
+ sc.PC_W_Height = SCALE(height*get_host_pix_height());
+ graphicsResize();
+
+ current_height = height;
+ current_width = width;
+ current_mode_type = GRAPHICS;
+ current_bits_per_pixel = sc.BitsPerPixel;
+ current_scale = host_screen_scale;
+ }
+ }
+
+ sc.CharHeight = current_char_height;
+
+ /*::::::::::::::::::::::::::::::::::::::::::: Display trace information */
+
+ sub_note_trace2(ALL_ADAPT_VERBOSE,
+ "check_win_size width = %d, height = %d",
+ width, height);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::: Set the VLT ??? ::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void set_the_vlt(void)
+{
+ PALETTEENTRY vga_color[VGA_DAC_SIZE];
+ int i, ind;
+ byte mask, top_bit;
+
+ /*::::::::::::::::: Map DAC specified colour value to Win32 palette */
+
+ if(video_adapter == VGA)
+ {
+ if(get_256_colour_mode())
+ {
+ /*.......... In 256 colour mode, create new palette entries */
+
+ for (i = 0; i < VGA_DAC_SIZE; i++)
+ {
+ ind = i & get_DAC_mask();
+
+ vga_color[i].peFlags = 0;
+
+ vga_color[i].peRed = (BYTE) (DAC[ind].red * 4);
+ vga_color[i].peGreen = (BYTE) (DAC[ind].green * 4);
+ vga_color[i].peBlue = (BYTE) (DAC[ind].blue * 4);
+ }
+
+ /*..................... Apply new colours to output palette */
+
+ SetPaletteEntries(sc.ColPalette, 0, VGA_DAC_SIZE, &vga_color[0]);
+
+ /* Progs that cycle the DACs get hit by idle detect unless..*/
+
+ IDLE_video();
+ }
+ else
+ {
+ /* if not in 256 colour mode then... if bit 7 of attr mode
+ register set then... video bits 7 & 6 = bits 3 & 2 of pixel
+ padding reg ('top_bit') video bits 5-0 from palette reg.
+ (establish by 'mask') if bit 7 of attr mode register clear
+ then... video bits 7 - 4 = bits 3 - 0 of pixel padding reg
+ ('top_bit') video bits 3-0 from palette reg. (establish by
+ 'mask') */
+
+ /*.................................... Set mask and top bit */
+
+ if(get_colour_select())
+ {
+ mask = 0xf;
+ top_bit = (byte) ((get_top_pixel_pad() << 6)
+ | (get_mid_pixel_pad() << 4));
+ }
+ else
+ {
+ mask = 0x3f;
+ top_bit = (byte) (get_top_pixel_pad() << 6);
+ }
+
+ /*..................... Construct new Win32 palette entries */
+
+ for (i = 0; i < VGA_DAC_SIZE; i++)
+ {
+ /*...................... Calculate palette index number */
+
+ ind = i & host_plane_mask;
+
+ /*
+ * If attribute controller, mode select, blink bit set in
+ * graphics mode, pixels 0-7 select palette entries 8-15
+ * i.e. bit 3, 0->1.
+ */
+ if ((sc.ModeType == GRAPHICS) && (bg_col_mask == 0x70))
+ ind |= 8;
+
+ ind = get_palette_val(ind);
+ ind = top_bit | (ind & mask);
+ ind &= get_DAC_mask();
+
+ /*........................ Construct next palette entry */
+
+ vga_color[i].peFlags = 0;
+ vga_color[i].peRed = (BYTE) (DAC[ind].red * 4);
+ vga_color[i].peGreen = (BYTE) (DAC[ind].green * 4);
+ vga_color[i].peBlue = (BYTE) (DAC[ind].blue * 4);
+ }
+
+ SetPaletteEntries(sc.ColPalette, 0, VGA_DAC_SIZE, &vga_color[0]);
+ }
+
+ set_palette_change_required(FALSE);
+ }
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::::::::: Display changes */
+
+ if (sc.ScreenBufHandle) // only sensible in gfx context
+ {
+ /*
+ ** For extra safety, cos set_the_vlt() can get called in text mode.
+ */
+ if( !SetConsoleActiveScreenBuffer( sc.ScreenBufHandle ) ){
+ assert2( NO, "VDM: SCASB() failed:%#x H=%#x",
+ GetLastError(), sc.ScreenBufHandle );
+ return;
+ }
+ if(!SetConsolePalette(sc.ScreenBufHandle, sc.ColPalette, SYSPAL_STATIC))
+ assert1( NO, "SetConsolePalette() failed:%#x\n", GetLastError() );
+ }
+
+ update_vlt = FALSE;
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::: Set screen sizes - update the screen description structure :::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+static void set_screen_sizes(int adaptor)
+{
+ UNUSED(adaptor);
+
+ sc.PC_W_Width = SCALE(CGA_WIN_WIDTH);
+ sc.PC_W_Height = SCALE(CGA_WIN_HEIGHT);
+ sc.CharWidth = CGA_CHAR_WIDTH;
+ sc.CharHeight = CGA_CHAR_HEIGHT;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::; Change to plane mask ::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_change_plane_mask(int plane_mask)
+{
+ if (host_plane_mask != plane_mask) host_plane_mask = 0xf;
+
+ update_vlt = TRUE;
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::: Dummy Paint Routines for all the IBM screen modes :::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+static void dummy_paint_screen(int offset, int host_x, int host_y,
+ int width, int height)
+{
+ UNUSED(offset);
+ UNUSED(host_x);
+ UNUSED(host_y);
+ UNUSED(width);
+ UNUSED(height);
+
+ sub_note_trace5((CGA_HOST_VERBOSE | EGA_HOST_VERBOSE),
+ "dummy_paint_screen off=%d x=%d y=%d width=%d h=%d",
+ offset, host_x, host_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: Set downloaded font ???? :::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_set_downloaded_font(int value)
+{
+ UNUSED(value);
+
+ sub_note_trace1((CGA_HOST_VERBOSE | EGA_HOST_VERBOSE),
+ "host_set_downloaded_font value=%d", value);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::: Free Font ::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_free_font(int index)
+{
+ UNUSED(index);
+
+ sub_note_trace0(EGA_HOST_VERBOSE,"nt_free_font - NOT SUPPORTED");
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::: Select font :::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_select_fonts(int font1, int font2)
+{
+ UNUSED(font1);
+ UNUSED(font2);
+
+ sub_note_trace0(EGA_HOST_VERBOSE,"nt_select_fonts - NOT SUPPORTED");
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::: Update fonts ::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_update_fonts(void) { }
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::: Set palette :::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_set_palette(PC_palette *palette, int size)
+{
+ UNUSED(palette);
+ UNUSED(size);
+
+ sub_note_trace0(EGA_HOST_VERBOSE,"nt_set_palette - NOT SUPPORTED");
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::: Set screen scale ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_set_screen_scale(int scale)
+{
+ if (scale != host_screen_scale)
+ {
+ host_screen_scale = scale;
+
+ /*
+ * Don't want to do any painting if this is called on initialisation
+ * and sc.PC_W_Width is as good a variable as any to check for this.
+ */
+ if (sc.PC_W_Width)
+ {
+ select_paint_routines();
+ nt_set_paint_routine(current_mode, current_height);
+ nt_mark_screen_refresh();
+ }
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::: Set border colour ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_set_border_colour(int colour)
+{
+ UNUSED(colour);
+
+ sub_note_trace0(ALL_ADAPT_VERBOSE,"nt_set_border_colour - NOT SUPPORTED");
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::: Resize window :::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/*
+*****************************************************************************
+** windowSize() resizes the console window to the specified height and width.
+*****************************************************************************
+** Called from resizeWindow() below.
+*/
+VOID windowSize IFN4( int, w, int, h, int, top, int, left )
+{
+ SMALL_RECT WinSize;
+
+ WinSize.Top = top;
+ WinSize.Left = left;
+ WinSize.Bottom = top + h - 1;
+ WinSize.Right = left + w - 1;
+
+#ifndef PROD
+ //fprintf(trace_file, "newW: %d.%d at %d.%d\n", h, w, top, left);
+#endif
+ if( !SetConsoleWindowInfo( sc.OutputHandle, TRUE, &WinSize ) )
+ assert3( NO, "VDM: SetConsoleWindowInfo() w=%d h=%d failed:%#x",
+ w, h, GetLastError() );
+}
+
+/*
+*****************************************************************************
+** bufferSize() resizes the console buffer to the specified height and width.
+*****************************************************************************
+** Called from resizeWindow() below.
+*/
+VOID bufferSize IFN2( int, w, int, h )
+{
+ COORD ScrSize;
+
+ ScrSize.X = w;
+ ScrSize.Y = h;
+#ifndef PROD
+ //fprintf(trace_file, "newB: %d.%d\n", h, w);
+#endif
+ if( !SetConsoleScreenBufferSize( sc.OutputHandle, ScrSize ) )
+ assert3( NO, "VDM: SetCons...BufferSize() w=%d h=%d failed:%#x",
+ w, h, GetLastError() );
+}
+
+/*
+*****************************************************************************
+* resizeWindow()
+*****************************************************************************
+* Sizes the console window and buffer as appropriate.
+*
+* The buffer must be able at all times to keep everything displayed
+* in the window.
+* So we check if the displayed portion would fall out of the buffer
+* and shrink the window appropriately.
+*
+* Then allocate the new buffer. This may affect the maximum window
+* size, so retrieve these values.
+*
+* Now the desired proportions of the Window are clipped to the
+* (eventually just updated) maximum, and if different from what
+* we have already, the change is made.
+*
+* In order to keep "screen flashing" to a minimum, try to restore
+* the displayed portion (top and left) of the buffer.
+*/
+VOID resizeWindow IFN2( int, w, int, h )
+{
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+ int oldTop, oldLeft; /* present values */
+ int newTop, newLeft;/* new values */
+ COORD oldW, /* present window size */
+ oldB; /* present buffer size */
+ CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
+
+ if( h > 50 ){
+ /* Shouldn't get this anymore said Tim */
+ assert1( NO, "VDM: resizeWindow() clipping height:%d", h );
+ h = 50;
+ }
+ if( !GetConsoleScreenBufferInfo( sc.OutputHandle, &bufferInfo) )
+ assert1( NO, "VDM: GetConsoleScreenBufferInfo() failed:%#x",
+ GetLastError() );
+
+ oldTop = bufferInfo.srWindow.Top;
+ oldLeft = bufferInfo.srWindow.Left;
+
+ oldW.X = bufferInfo.srWindow.Right - bufferInfo.srWindow.Left + 1;
+ oldW.Y = bufferInfo.srWindow.Bottom - bufferInfo.srWindow.Top + 1;
+ oldB = bufferInfo.dwSize;
+#ifndef PROD
+ //fprintf(trace_file, "resz: %d.%d\n", h, w);
+ //fprintf(trace_file, "oldW: %d.%d\n", oldW.Y, oldW.X);
+ //fprintf(trace_file, "maxW: %d.%d\n", bufferInfo.dwMaximumWindowSize.Y, bufferInfo.dwMaximumWindowSize.X);
+ //fprintf(trace_file, "oldB: %d.%d\n", oldB.Y, oldB.X);
+#endif
+ /*
+ * Reduce window width and height as necessary:
+ */
+ if ( bufferInfo.srWindow.Bottom >= h
+ || bufferInfo.srWindow.Right >= w ) {
+ windowSize( MIN(w,oldW.X), MIN(h,oldW.Y), 0, 0);
+ }
+
+ /*
+ * Change Buffer width and height as required.
+ */
+ if ( oldB.X || h != oldB.Y ) {
+ bufferSize( w, h );
+
+ /*
+ * This increase in Buffer size may have affected maximum
+ * possible window sizes:
+ */
+ if( !GetConsoleScreenBufferInfo( sc.OutputHandle, &bufferInfo) )
+ assert1( NO, "VDM: GetConsoleScreenBufferInfo() failed:%#x",
+ GetLastError() );
+#ifndef PROD
+ //fprintf(trace_file, "maxW: %d.%d\n", bufferInfo.dwMaximumWindowSize.Y, bufferInfo.dwMaximumWindowSize.X);
+#endif
+ }
+ /*
+ ** Clip requested values to Window maximum and
+ ** compute new (possible) top and left values.
+ */
+
+ newLeft = w - bufferInfo.dwMaximumWindowSize.X;
+ if ( newLeft > 0 ) {
+ w = bufferInfo.dwMaximumWindowSize.X;
+ } else
+ newLeft = 0;
+
+ newTop = h - bufferInfo.dwMaximumWindowSize.Y;
+ if ( newTop > 0 ) {
+ h = bufferInfo.dwMaximumWindowSize.Y;
+ } else
+ newTop = 0;
+
+ /*
+ * Check if we need to enlarge the window now.
+ * Settle for old top and left if they were smaller.
+ * This avoids unnecessary updates in the window.
+ */
+ if ( w > oldW.X || h > oldW.Y )
+ windowSize( w, h, MIN(newTop,oldTop), MIN(newLeft,oldLeft) );
+
+} /* end of resizeWindow() */
+
+/*
+** Controls the size of the window when in a text mode.
+** scale=2 selects normal (small) size
+** scale=3 selects bit 1.5x
+** If this function is called before the SoftPC window has been created,
+** the "sv_screen_scale" variable needs to be changed. This governs
+** the SCALE() macro, which is used just to specify the window
+** dimensions at creation. If the SoftPC window already exists then the
+** size is changed by a more complex sequence.
+*/
+
+//Used by the text paint functions
+GLOBAL int now_height = 80, now_width = 50;
+
+void textResize(void)
+{
+
+ if(sc.PC_W_Height && sc.PC_W_Width &&
+ get_host_char_height() && get_pix_char_width())
+ {
+ now_height = sc.PC_W_Height/get_host_char_height();
+ now_width = sc.PC_W_Width / get_pix_char_width();
+
+ select_paint_routines();
+ nt_change_mode();
+
+ resizeWindow(now_width, now_height); /* Tim, September 92 */
+ }
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:: ::*/
+/*:: graphicsResize: ::*/
+/*:: ::*/
+/*:: Resize SoftPC window when in a graphics mode by selecting a new ::*/
+/*:: active screen buffer. ::*/
+/*:: ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+void graphicsResize(void)
+{
+ DWORD headerSize;
+ LPBITMAPINFO infoStructPtr;
+
+ if (sc.ScreenState == FULLSCREEN)
+ return;
+
+ /* Destroy previous data. */
+ closeGraphicsBuffer(); /* Tim Oct 92 */
+
+ if (sc.ConsoleBufInfo.lpBitMapInfo != NULL)
+ free((char *) sc.ConsoleBufInfo.lpBitMapInfo);
+
+ /*
+ * Create a `BITMAPINFO' structure - sc.PC_W_Width pixels x
+ * sc.PC_W_Height pixels x sc.BitsPerPixel bits-per-pixel.
+ */
+ headerSize = CreateSpcDIB(sc.PC_W_Width,
+ sc.PC_W_Height,
+ sc.BitsPerPixel,
+ DIB_PAL_COLORS,
+ 0,
+ (COLOURTAB *) NULL,
+ &infoStructPtr);
+
+ /* Initialise the console info structure. */
+ sc.ConsoleBufInfo.dwBitMapInfoLength = headerSize;
+ sc.ConsoleBufInfo.lpBitMapInfo = infoStructPtr;
+ sc.ConsoleBufInfo.dwUsage = DIB_PAL_COLORS;
+
+ /* Create a screen buffer using the above `BITMAPINFO' structure. */
+ sc.ScreenBufHandle =
+ CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CONSOLE_GRAPHICS_BUFFER,
+ &sc.ConsoleBufInfo);
+
+ if (sc.ScreenBufHandle == (HANDLE)-1)
+ {
+ sc.ScreenBufHandle = NULL;
+ assert1( NO, "VDM: graphics screen buffer creation failed:%#x\n",
+ GetLastError());
+ }
+
+ /* 'cos old palette discarded with close buffer */
+ if (sc.ColPalette == (HPALETTE)0)
+ {
+ CreateDisplayPalette();
+ set_palette_change_required(TRUE);
+ }
+
+ /* save the handle away to a useful place */
+ MouseDetachMenuItem(TRUE);
+ sc.ActiveOutputBufferHandle = sc.ScreenBufHandle;
+ MouseAttachMenuItem(sc.ActiveOutputBufferHandle);
+
+ /*
+ * Make it the current screen buffer, which resizes the window
+ * on the display.
+ */
+ SetConsoleActiveScreenBuffer(sc.ScreenBufHandle);
+
+ /*
+ * Get a pointer to the last line of the bitmap to build
+ * upside-down pictures.
+ */
+ sc.BitmapLastLine = (char *) sc.ConsoleBufInfo.lpBitMap +
+ (sc.PC_W_Height - 1) *
+ BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:: ::*/
+/*:: CreateSpcDIB: ::*/
+/*:: ::*/
+/*:: Create a new SoftPC device independent bitmap. ::*/
+/*:: Parameters: ::*/
+/*:: width - width of the bitmap in pixels. ::*/
+/*:: height - height of the bitmap in pixels. ::*/
+/*:: bitsPerPixel - number of bits representing one pixel in the ::*/
+/*:: bitmap. ::*/
+/*:: wUsage - type of bitmap to create, can be DIB_PAL_COLORS,::*/
+/*:: DIB_RGB_COLORS or DIB_PAL_INDICES. ::*/
+/*:: DIBColours - Only interrogated for DIB_RGB_COLORS bitmaps, ::*/
+/*:: defines the number of entries in the colour ::*/
+/*:: table. If set to USE_COLOURTAB the colour table ::*/
+/*:: contains the same number of entries as the ::*/
+/*:: `colours' table, otherwise DIBColours contains ::*/
+/*:: the actual number of entries to be used. ::*/
+/*:: colours - Only interrogated for DIB_RGB_COLORS bitmaps, ::*/
+/*:: points to a COLOURTAB structure which contains ::*/
+/*:: the RGB values to be loaded into the bitmap's ::*/
+/*:: colour table. ::*/
+/*:: infoPtr - The address in which to return a pointer to the ::*/
+/*:: BITMAPINFO structure allocated by this routine. ::*/
+/*:: ::*/
+/*:: Return value: ::*/
+/*:: The size of the BITMAPINFO structure allocated on success, -1 ::*/
+/*:: on failure. ::*/
+/*:: ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL DWORD CreateSpcDIB(int width, int height, int bitsPerPixel,
+ WORD wUsage, int DIBColours,
+ COLOURTAB *colours, BITMAPINFO **infoPtr)
+{
+ PBITMAPINFO pDibInfo; /* Returned data structure. */
+ int i, /* Counting variable. */
+ maxColours, /* Maximum number of colours. */
+ coloursUsed, /* Value to be put in biClrUsed field. */
+ nActualColours, /* Number of colours in RGB_COLOURS bitmap. */
+ tabSize; /* Size of colour table to allocate. */
+ DWORD allocSize; /* Total size to allocate. */
+
+ /* Work out size of DIB colour table. */
+ maxColours = 1 << bitsPerPixel;
+ switch (wUsage)
+ {
+
+ case DIB_PAL_COLORS:
+ tabSize = maxColours * sizeof(WORD);
+ coloursUsed = 0;
+ break;
+
+ case DIB_RGB_COLORS:
+ if (colours == NULL)
+ return((DWORD) -1);
+ nActualColours = (DIBColours == USE_COLOURTAB) ?
+ colours->count :
+ DIBColours;
+ tabSize = nActualColours * sizeof(RGBQUAD);
+ coloursUsed = nActualColours;
+ break;
+
+ case DIB_PAL_INDICES:
+ tabSize = 0;
+ coloursUsed = 0;
+ break;
+
+ default:
+ always_trace0("Illegal wUsage parameter passed to CreateSpcDIB.");
+ return((DWORD) -1);
+
+ }
+
+ /* Allocate space for the BITMAPINFO structure. */
+ allocSize = sizeof(BITMAPINFOHEADER) + tabSize;
+ check_malloc(pDibInfo, allocSize, BITMAPINFO);
+
+ /* Initialise BITMAPINFOHEADER. */
+ pDibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pDibInfo->bmiHeader.biWidth = width;
+ pDibInfo->bmiHeader.biHeight = -height;
+ pDibInfo->bmiHeader.biPlanes = 1;
+ pDibInfo->bmiHeader.biBitCount = (WORD) bitsPerPixel;
+ pDibInfo->bmiHeader.biCompression = BI_RGB;
+ pDibInfo->bmiHeader.biSizeImage = width * height / 8 * bitsPerPixel;
+ pDibInfo->bmiHeader.biXPelsPerMeter = 0;
+ pDibInfo->bmiHeader.biYPelsPerMeter = 0;
+ pDibInfo->bmiHeader.biClrUsed = coloursUsed;
+ pDibInfo->bmiHeader.biClrImportant = 0;
+
+ /* Initialise colour table. */
+ switch (wUsage)
+ {
+
+ case DIB_PAL_COLORS:
+
+ /*
+ * Colour table is an array of WORD indexes into currently realized
+ * palette.
+ */
+ for (i = 0; i < maxColours; i++)
+ ((WORD *) pDibInfo->bmiColors)[i] = (WORD) i;
+ break;
+
+ case DIB_RGB_COLORS:
+
+ /*
+ * Colour table is an array of RGBQUAD structures. If the `colours'
+ * array contains fewer than `nActualColours' entries the colour
+ * table will not be completely filled. In this case `colours' is
+ * repeated until the table is full.
+ */
+ for (i = 0; i < nActualColours; i++)
+ {
+ pDibInfo->bmiColors[i].rgbBlue =
+ colours->blue[i % colours->count];
+ pDibInfo->bmiColors[i].rgbGreen =
+ colours->green[i % colours->count];
+ pDibInfo->bmiColors[i].rgbRed =
+ colours->red[i % colours->count];
+ pDibInfo->bmiColors[i].rgbReserved = 0;
+ }
+ break;
+
+ case DIB_PAL_INDICES:
+
+ /* No colour table DIB uses system palette. */
+ break;
+
+ default:
+ break;
+
+ }
+ *infoPtr = pDibInfo;
+ return(allocSize);
+}
+
+
+/* Holding place for stub functions */
+
+void nt_mode_select_changed(int dummy)
+{
+ UNUSED(dummy);
+#ifndef PROD
+ fprintf(trace_file, "WARNING - nt_mode_select_changed\n");
+#endif
+}
+
+void nt_color_select_changed(int dummy)
+{
+ UNUSED(dummy);
+#ifndef PROD
+ fprintf(trace_file, "WARNING - nt_color_select_changed\n");
+#endif
+}
+
+void nt_screen_address_changed(int lo, int hi)
+{
+ UNUSED(lo);
+ UNUSED(hi);
+
+ sub_note_trace0(EGA_HOST_VERBOSE, "WARNING - nt_screen_address_changed\n");
+}
+
+void nt_scroll_complete() { }
+
+void host_stream_io_update(half_word * buffer, word count)
+{
+ DWORD dwBytesWritten;
+
+ WriteConsoleA(sc.OutputHandle,
+ buffer,
+ count,
+ &dwBytesWritten,
+ NULL
+ );
+ flush_count = 0;
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_hfx.c b/private/mvdm/softpc.new/host/src/nt_hfx.c
new file mode 100644
index 000000000..fc2bd0f59
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_hfx.c
@@ -0,0 +1,195 @@
+#include "host_def.h"
+#include "insignia.h"
+/*
+ * SoftPC Revision 2.0
+ *
+ * Title : unix_hfx.c
+ *
+ * Description : Stubbs for HFX
+ *
+ */
+
+#include <stdio.h>
+#include "xt.h"
+#include "host_hfx.h"
+#include "hfx.h"
+#include "debug.h"
+
+void get_hostname IFN2(int, fd, char *, name)
+{
+}
+
+void get_host_fd IFN2(char *, name,int, fd)
+{
+}
+
+void init_fd_hname()
+{
+}
+
+void host_concat IFN3(char *, path,char *, name,char *, result)
+{
+}
+
+word host_create IFN4(char *, name, word, attr, half_word, create_new, word *, fd)
+{
+ return (0);
+}
+
+void host_to_dostime IFN3(long, secs_since_70, word *, date, word *, time)
+{
+}
+
+long host_get_datetime IFN2(word *, date,word *, thetime)
+{
+ return (0);
+}
+
+int host_set_time IFN2(word, fd, long, hosttime)
+{
+ return (0);
+}
+
+
+word host_open IFN6(char *, name, half_word, attrib, word *, fd, double_word *, size, word *, date, word *, thetime)
+{
+ return (0);
+}
+
+/* General purpose file move function. This was added for use by the new
+ general purpose truncate code. It can copy between file systems, can
+ overwrite the existing destination file, and can pad the destination
+ file to the given length if the source file is less than that length. */
+int mvfile IFN3(char *, from, char *, to, int, length)
+{
+ return (0);
+}
+
+word host_truncate IFN2(word, fd, long, size)
+{
+ return (0);
+}
+
+word host_close IFN1(word, fd)
+{
+ word xen_err = 0;
+ return(0);
+}
+
+word host_commit IFN1(word, fd)
+{
+ return(0);
+}
+
+word host_write IFN4(word, fd, unsigned char *, buf, word, num, word *, count)
+{
+ return (0);
+}
+
+word host_read IFN4(word, fd, unsigned char *, buf, word, num, word *, count)
+{
+ return(0);
+}
+
+word host_delete IFN1(char *, name)
+{
+ return(0);
+}
+
+int hfx_rename IFN2(char *, from,char *, to)
+{
+ return(0);
+}
+
+
+word host_rename IFN2(char *, from, char *, to)
+{
+ word xen_err = 0;
+ return(0);
+}
+
+
+half_word host_getfattr IFN1(char *, name)
+{
+ half_word attr;
+ return(0);
+}
+
+word host_get_file_info IFN4(char *, name, word *, thetime, word *, date, double_word *, size)
+{
+ return(0);
+}
+
+word host_set_file_attr IFN2(char *, name, half_word, attr)
+{
+ return(0);
+}
+
+word host_lseek IFN4(word, fd, double_word, offset,int, whence, double_word *, position)
+{
+ return(0);
+}
+
+word host_lock IFN3(word, fd, double_word, start, double_word, length)
+{
+ return(0);
+}
+
+word host_unlock IFN3(word, fd, double_word, start, double_word, length)
+{
+ return(0);
+}
+
+host_check_lock()
+{
+ return(0);
+}
+
+void host_disk_info IFN2(DOS_DISK_INFO *, disk_info, int, drive)
+{
+}
+/*
+ *
+ * Remove directory function.
+ */
+word host_rmdir IFN1(char *, host_path)
+{
+ return (0);
+}
+
+/*
+ *
+ * Make directory function.
+ */
+word host_mkdir IFN1(char *, host_path)
+{
+ return (0);
+}
+
+/*
+ *
+ * Change directory function. This function only validates the path
+ * given. DOS decides whether to actually change directory at a higher
+ * level. Success is returned if the path exists and is a directory.
+ * If the path exists but the file is not a directory, then a special
+ * code is returned, as to return error_path_not_found would be
+ * ambiguous.
+ */
+word host_chdir IFN1(char *, host_path)
+{
+ return (0);
+}
+
+
+/*
+ *
+ * Function to return the volume ID of a network drive.
+ * Eleven characters are available for the name to be output.
+ *
+ * The last field in the network drive path it output unless it
+ * is more than eleven characters long in which case ten characters
+ * are output with an appended tilde.
+ */
+void host_get_volume_id IFN2(char *, net_path, char *, volume_id)
+{
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_hosts.c b/private/mvdm/softpc.new/host/src/nt_hosts.c
new file mode 100644
index 000000000..bbf99e7a5
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_hosts.c
@@ -0,0 +1,343 @@
+/***************************************************************************
+ * *
+ * PROGRAM : HOST_UIS.c *
+ * *
+ * PURPOSE : Host UI code *
+ * *
+ ****************************************************************************/
+
+
+#include <windows.h>
+#include "conapi.h"
+#include "insignia.h"
+#include "host_def.h"
+
+#include "xt.h"
+#include "gvi.h"
+#include "gmi.h"
+#include <stdio.h>
+#include "trace.h"
+#include "debug.h"
+#include "host_rrr.h"
+
+#include "nt_graph.h"
+#include "nt_event.h"
+#include "nt_uis.h"
+#include "nt_reset.h"
+
+#ifdef HUNTER
+#include "nt_hunt.h"
+#endif /*HUNTER*/
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::: Global variables */
+
+HANDLE InstHandle;
+
+
+CONSOLE_CURSOR_INFO StartupCursor;
+
+/*:::::::::::::::::::::::::::::::::::::::: Fast graphics associated defines */
+
+BYTE Red[] = { 0, 0, 0, 0, 128, 128, 128, 192, 128, 0, 0,
+ 0, 255, 255, 255, 255 };
+
+BYTE Green[]={ 0, 0, 128, 128, 0, 0, 128, 192, 128, 0, 255,
+ 255, 0, 0, 255, 255 };
+
+BYTE Blue[] ={ 0, 128, 0, 128, 0, 128, 0, 192, 128, 255, 0,
+ 255, 0, 255, 0, 255 };
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::: External functions */
+
+LONG nt_process_event(HWND hWnd, WORD message, LONG wParam, LONG lParam);
+
+/*::::::::::::::::::::::::::::::::::::::::::::: Internal function protocols */
+
+BOOL SoftInit(void);
+WORD HeartBeat(HWND hWnd, WORD msg, int nIDEvent, DWORD dwTime);
+
+PSTR String(WORD StrResID);
+void InitScreenDesc(void);
+
+#ifdef HUNTER
+void HunterMenuMake(void);
+#endif /* HUNTER */
+
+HANDLE SCS_hStdIn=0;
+HANDLE SCS_hStdOut=0;
+HANDLE SCS_hStdErr=0;
+
+/****************************************************************************
+ * *
+ * FUNCTION : init_host_uis() *
+ * *
+ * PURPOSE : Creates the main app. window, calls an initialization *
+ * functions *
+ * *
+ ****************************************************************************/
+
+int init_host_uis()
+{
+ InitScreenDesc();
+
+ if(CreateDisplayPalette())
+ {
+ SelectPalette(sc.DispDC,sc.ColPalette,0);/* Select foreground palette */
+ }
+
+ return(1);
+}
+
+/****************************************************************************
+ * *
+ * FUNCTION : SetupConsoleMode() *
+ * *
+ * PURPOSE : Setup console mode and get handles *
+ * *
+ ****************************************************************************/
+
+void SetupConsoleMode(void)
+{
+ DWORD mode;
+
+ /*::::::::::::::::::::::::::::::::::::::::::: Set console input mode */
+
+ if(!GetConsoleMode(sc.InputHandle, &sc.OrgInConsoleMode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ mode = sc.OrgInConsoleMode &
+ ~(ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
+ if (!host_stream_io_enabled)
+ mode |= (ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
+
+ /*.............................................. Set new console mode */
+
+ if(!SetConsoleMode(sc.InputHandle,mode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+ /*::::::::::::::::::::::::::::::::::::::::::: Set console output mode */
+
+ if(!GetConsoleMode(sc.OutputHandle, &sc.OrgOutConsoleMode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+ /*.............................................. Set new console mode */
+
+ if(!stdoutRedirected && !host_stream_io_enabled)
+ {
+ mode = sc.OrgOutConsoleMode &
+ ~(ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_PROCESSED_OUTPUT);
+
+ if(!SetConsoleMode(sc.OutputHandle,mode))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+ }
+
+ if(!GetConsoleCursorInfo(sc.OutputHandle, &StartupCursor))
+ {
+ assert1(NO, "NTVDM:can't get initial cursor size. Err %d", GetLastError());
+ /* add own defaults */
+ StartupCursor.dwSize = 20;
+ StartupCursor.bVisible = TRUE;
+ }
+ if(!GetConsoleScreenBufferInfo(sc.OutputHandle, &sc.ConsoleBuffInfo))
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(), __FILE__,__LINE__);
+
+}
+
+
+/****************************************************************************
+ * *
+ * FUNCTION : InitScreenDesc *
+ * *
+ * PURPOSE : Initialise screen description structure *
+ * *
+ ****************************************************************************/
+
+void InitScreenDesc(void)
+{
+SECURITY_ATTRIBUTES sa;
+
+ /*::::::::::::::::::::::::::::::::::::::::::: Get console output handle */
+
+ if((sc.OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE)
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ //
+ // Save this handle as the active handle until a new one is
+ // selected.
+ //
+
+ sc.ActiveOutputBufferHandle = sc.OutputHandle;
+ sc.ScreenBufHandle = (HANDLE)0;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::: Get console input handle */
+
+ if((sc.InputHandle = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE)
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+
+ /*:::::::::::::::::::::::::::::: check out if stdin has been redirected */
+
+ if(GetFileType(sc.InputHandle) != FILE_TYPE_CHAR)
+ {
+ sa.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+ sc.InputHandle = CreateFile("CONIN$",GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ &sa,OPEN_EXISTING, 0, NULL);
+
+ if(sc.InputHandle == (HANDLE)-1)
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ else{
+ SetStdHandle (STD_INPUT_HANDLE,sc.InputHandle);
+ }
+ }
+
+ /*:::::::::::::::::::::::::::: check out if stdout has been redirected */
+
+ if(GetFileType(sc.OutputHandle) != FILE_TYPE_CHAR)
+ {
+ stdoutRedirected = TRUE;
+ sa.nLength = sizeof (SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+ sc.OutputHandle = CreateFile("CONOUT$",GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ &sa,OPEN_EXISTING, 0, NULL);
+
+ if(sc.OutputHandle == (HANDLE)-1)
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ else {
+ SetStdHandle (STD_OUTPUT_HANDLE,sc.OutputHandle);
+ SetStdHandle (STD_ERROR_HANDLE,sc.OutputHandle);
+ }
+ }
+
+ // Keep SCS in sync with these handles for starting non-dos binaries
+ SCS_hStdIn = sc.InputHandle;
+ SCS_hStdOut = sc.OutputHandle;
+ SCS_hStdErr = sc.OutputHandle;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::: Setup console mode */
+
+ SetupConsoleMode();
+
+#ifdef HUNTER
+ HunterMenuMake();
+#endif /*HUNTER*/
+
+ /*::::::::::::::::::::::::::: Tell console to post us a closedown event */
+
+ // we only want notification for DOS NTVDM runnig on an existing console
+ if (!VDMForWOW && !DosSessionId)
+ SetLastConsoleEventActive();
+ sc.StaticPalette = TRUE;
+ sc.FontsAreOpen = FALSE;
+}
+/****************************************************************************
+ * *
+ * FUNCTION : BOOL CreateDisplayPalette(void) *
+ * *
+ * PURPOSE : Create logical palette *
+ * Assumes Colour monitor supporting 16 colours *
+ * *
+ ****************************************************************************/
+
+BOOL CreateDisplayPalette(void)
+{
+ register int i;
+ register PALETTEENTRY *PalEntry;
+ NPLOGPALETTE LogPalette; /* Pointer to logical palette */
+
+ /*::::::: Allocate memory for a logical palette with PALETTESIZE entries */
+
+ LogPalette = (NPLOGPALETTE) LocalAlloc(LMEM_FIXED,
+ (sizeof(LOGPALETTE) +
+ (sizeof(PALETTEENTRY) * PALETTESIZE)));
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::: Allocation failed !! */
+
+ if(!LogPalette) return(FALSE); /* Function failed, no memory */
+
+ /*::: Set the size and version fields of the logical palette structure. */
+
+ LogPalette->palVersion = 0x300;
+ LogPalette->palNumEntries = PALETTESIZE;
+
+ /*::::::::::::::::::: Fill in intensities for all palette entry colors */
+
+ for(i=0,PalEntry=LogPalette->palPalEntry; i < PALETTESIZE;i++,PalEntry++)
+ {
+ if(i < sizeof(Red)/sizeof(BYTE))
+ {
+ PalEntry->peRed = Red[i]; PalEntry->peGreen = Green[i];
+ PalEntry->peBlue = Blue[i];
+ }
+ else
+ {
+ PalEntry->peRed = PalEntry->peGreen = PalEntry->peBlue = 0;
+ }
+
+ PalEntry->peFlags = sc.StaticPalette ? 0 : PC_RESERVED;
+ }
+
+ /*:::::::: Create a logical color palette from the LOGPALETTE structure */
+
+ sc.ColPalette = CreatePalette((LPLOGPALETTE) LogPalette);
+ LocalFree((HANDLE)LogPalette);
+
+ return(sc.ColPalette ? TRUE : FALSE);
+}
+
+
+/*============================================================================
+Function to display a menu option on the Console system menu. This is used for
+the control of Trapper.
+============================================================================*/
+
+#ifdef HUNTER
+void HunterMenuMake(void)
+{
+HMENU hTest,hTrapperPopup,hMainPopup,hErrorPopup;
+static BOOL bTrapperMenuFlag=FALSE;
+
+if(!bTrapperMenuFlag)
+ {
+ /*========================================================================
+ The Menus have been drawn once already. Need to delete these and reappend
+ them to the Console menu for the new output buffer. Isn't Console just such
+ a bore?
+ ========================================================================*/
+
+ DestroyMenu(hTrapperPopup);
+ DestroyMenu(hMainPopup);
+ DestroyMenu(hErrorPopup);
+ }
+
+hTrapperPopup = CreateMenu();
+hMainPopup = CreateMenu();
+hErrorPopup = CreateMenu();
+
+AppendMenu(hMainPopup,MF_STRING,IDM_MFAST,"&Fast forward");
+AppendMenu(hMainPopup,MF_STRING,IDM_MNEXT,"&Next screen");
+AppendMenu(hMainPopup,MF_STRING,IDM_MPREV,"&Prev screen");
+AppendMenu(hMainPopup,MF_STRING,IDM_MSHOW,"&Show screen");
+AppendMenu(hMainPopup,MF_STRING,IDM_MCONT,"&Continue");
+AppendMenu(hMainPopup,MF_STRING,IDM_MABOR,"&Abort");
+
+AppendMenu(hErrorPopup,MF_STRING,IDM_EFLIP,"&Flip screen");
+AppendMenu(hErrorPopup,MF_STRING,IDM_ENEXT,"&Next error");
+AppendMenu(hErrorPopup,MF_STRING,IDM_EPREV,"&Prev error");
+AppendMenu(hErrorPopup,MF_STRING,IDM_EALL,"&All errors");
+AppendMenu(hErrorPopup,MF_STRING,IDM_ECLEA,"&Clear errors");
+
+AppendMenu(hTrapperPopup,MF_POPUP,hMainPopup,"&Main");
+AppendMenu(hTrapperPopup,MF_POPUP,hErrorPopup,"&Error");
+
+/* if graphics mode, then use sc.ScreenBuffer */
+
+/* hTest = ConsoleMenuControl(sc.ScreenBuffer,IDM_TRAPPER,IDM_ECLEA); */
+
+/* else text mode, then use sc.OutputHandle */
+hTest = ConsoleMenuControl(sc.OutputHandle,IDM_TRAPPER,IDM_ECLEA);
+
+AppendMenu(hTest,MF_POPUP,hTrapperPopup,"&Trapper");
+bTrapperMenuFlag=TRUE; /* draw the trapper menu just once */
+}
+#endif /* HUNTER */
diff --git a/private/mvdm/softpc.new/host/src/nt_hunt.c b/private/mvdm/softpc.new/host/src/nt_hunt.c
new file mode 100644
index 000000000..bc28e18ea
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_hunt.c
@@ -0,0 +1,250 @@
+#include "windows.h"
+#include "host_def.h"
+#include "insignia.h"
+/*[
+Name: hunt.c
+ Derived From: X_hunt.c ( base 2.0 )
+ Author: gvdl ( Original by Mike McCusker )
+ Created On: 3 May 1991
+Sccs ID: 07/29/91 @(#)hunt.c 1.7
+ Purpose: Contains all host_dependent code for hunter
+
+ (c)Copyright Insignia Solutions Ltd., 1990. All rights reserved.
+
+]*/
+
+#include <stdio.h>
+#include <errno.h>
+#include TypesH
+
+
+#include "xt.h"
+#include "ios.h"
+#include CpuH
+#include "sas.h"
+#include "bios.h"
+#include "gvi.h"
+#include "cga.h"
+#include "error.h"
+#include "config.h"
+#include "nt_uis.h"
+
+
+
+#include "debug.h"
+
+#ifdef HUNTER
+#include "hunter.h"
+
+
+extern HANDLE InstHandle;
+
+/*
+* ============================================================================
+* Global Defines and Declarations
+* ============================================================================
+*/
+GLOBAL HANDLE TrapperDump = -1;
+
+LOCAL VOID nt_hunter_init IPT1(SHORT, mode);
+LOCAL VOID nt_hunter_activate_menus IPT0();
+LOCAL VOID host_flip_video_ind IPT0();
+LOCAL VOID nt_hunter_mark_error IPT2(int, x, int, y);
+LOCAL VOID nt_hunter_erase_error IPT0();
+LOCAL VOID nt_hunter_draw_box IPT1(BOX *, b);
+LOCAL ULONG nt_hunter_image_check IPT0();
+LOCAL VOID nt_hunter_display_image IPT0();
+
+
+
+DWORD CreateTrapperWindow IPT0();
+LONG FAR PASCAL TrapperWindowEvents IPT4(HWND, hTrapWnd, WORD, message, LONG, wParam, LONG, lParam);
+
+
+
+
+
+GLOBAL HUNTER_HOST_FUNCS hunter_host_funcs =
+{
+nt_hunter_init,
+nt_hunter_activate_menus,
+host_flip_video_ind,
+nt_hunter_mark_error,
+nt_hunter_mark_error,
+nt_hunter_draw_box,
+nt_hunter_draw_box,
+nt_hunter_image_check,
+nt_hunter_display_image,
+};
+
+
+LOCAL BOX lastBox; /* last box drawn during movement */
+
+HWND hTrapWnd;
+
+LOCAL VOID nt_hunter_activate_menus IFN0()
+{
+printf("nt_hunter_activate_menus() called\n");
+}
+
+LOCAL VOID host_flip_video_ind IFN0()
+{
+printf("host_flip_video() called\n");
+}
+
+
+
+LOCAL VOID nt_hunter_init IFN1(SHORT, mode)
+{
+ char *dumpFile;
+
+ /* Read environment to see if we have a trapper file to open. */
+ if ((dumpFile = host_getenv("HUDUMPFILE")) != NULL)
+ {
+ TrapperDump = CreateFile((LPCTSTR) dumpFile,
+ (DWORD) GENERIC_WRITE,
+ (DWORD) 0,
+ (LPSECURITY_ATTRIBUTES) NULL,
+ (DWORD) CREATE_ALWAYS,
+ (DWORD) FILE_ATTRIBUTE_NORMAL,
+ (HANDLE) 0);
+ if (TrapperDump == (HANDLE) -1)
+ printf("Failed to open trapper file \"%s\".\n", dumpFile);
+ }
+}
+
+LOCAL VOID nt_hunter_draw_box IFN1(BOX *, b)
+{
+HDC hDC;
+HPEN hPen;
+int x1,x2,y1,y2;
+
+
+x1=(b->top_x >> 1);
+y1=(b->top_y >> 1);
+x2=(b->bot_x >> 1);
+y2=(b->bot_y >> 1);
+
+hDC=GetDC(hTrapWnd);
+SetROP2(hDC,R2_COPYPEN);
+hPen=CreatePen(PS_SOLID,0,RGB(0,255,0));
+SelectObject(hDC,hPen);
+
+MoveToEx(hDC,x1,y1,NULL);
+LineTo(hDC,x1,y2);
+LineTo(hDC,x2,y2);
+LineTo(hDC,x2,y1);
+LineTo(hDC,x1,y1);
+DeleteObject(hPen);
+ReleaseDC(hTrapWnd,hDC);
+}
+
+
+LOCAL VOID nt_hunter_mark_error IFN2(int, x, int, y)
+{
+int x1,x2,y1,y2;
+HPEN hPen;
+HDC hDC;
+
+
+x1=x-4;
+y1=y-4;
+x2=x+4;
+y2=y+4;
+
+
+hDC=GetDC(hTrapWnd);
+SetROP2(hDC,R2_XORPEN);
+hPen=CreatePen(PS_SOLID,0,RGB(0,255,0));
+SelectObject(hDC,hPen);
+
+/*
+* Draw cross in the approximate region of error
+*/
+
+MoveToEx(hDC,x1,y,NULL);
+LineTo(hDC,x2,y);
+MoveToEx(hDC,x,y1,NULL);
+LineTo(hDC,x,y2);
+DeleteObject(hPen);
+ReleaseDC(hTrapWnd,hDC);
+
+}
+
+LOCAL VOID nt_hunter_erase_error IFN0()
+{
+InvalidateRect(hTrapWnd,NULL,TRUE);
+}
+
+LOCAL ULONG nt_hunter_image_check IFN0()
+{
+printf("nt_hunter_image_check() called\n");
+return FALSE;
+}
+
+LOCAL VOID nt_hunter_display_image IFN0()
+{
+printf("nt_hunter_display_image() called\n");
+}
+
+
+DWORD CreateTrapperWindow IFN0()
+{
+WNDCLASS WndCls;
+MSG msg;
+HDC hDC;
+HPEN hPen;
+
+
+WndCls.style = CS_HREDRAW | CS_VREDRAW;
+WndCls.lpfnWndProc = (WNDPROC) TrapperWindowEvents;
+WndCls.hInstance = GetModuleHandle(NULL);
+WndCls.hIcon = NULL;
+WndCls.hCursor = LoadCursor(NULL,IDC_ARROW);
+WndCls.hbrBackground = GetStockObject(BLACK_BRUSH);
+WndCls.lpszMenuName = NULL;
+WndCls.lpszClassName = (LPSTR) "Trapper";
+WndCls.cbClsExtra = 0;
+WndCls.cbWndExtra = 0;
+
+RegisterClass(&WndCls);
+
+hTrapWnd = CreateWindow("Trapper", "Trapper",WS_THICKFRAME | WS_OVERLAPPED |
+ WS_CAPTION,
+ 200,200,520,440, (HWND) NULL, NULL,
+ GetModuleHandle(NULL), (LPSTR) NULL);
+
+ShowWindow(hTrapWnd,SW_SHOWNORMAL);
+UpdateWindow(hTrapWnd);
+
+while(GetMessage(&msg, NULL, NULL, NULL))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg); /* Dispatch Message to event handler */
+ }
+
+}
+
+/*============================================================================
+
+Function to handle the messages passed to the trapper monitor window.
+Since we send no messages to it, the function responds with default action
+to any that it does get.
+
+============================================================================*/
+
+
+LONG FAR PASCAL TrapperWindowEvents IFN4(HWND, hTrapWnd, WORD, message, LONG, wParam, LONG, lParam)
+{
+PAINTSTRUCT ps;
+
+switch(message)
+ {
+ case WM_PAINT:
+ BeginPaint(hTrapWnd,&ps);
+ EndPaint(hTrapWnd,&ps);
+ return 0;
+ }
+return(DefWindowProc(hTrapWnd, message, wParam, lParam));
+}
+#endif /*HUNTER*/
diff --git a/private/mvdm/softpc.new/host/src/nt_input.c b/private/mvdm/softpc.new/host/src/nt_input.c
new file mode 100644
index 000000000..3b89d83d3
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_input.c
@@ -0,0 +1,128 @@
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : Win32 Input Module.
+ *
+ * Description : This module contains data and functions to
+ * implement the SoftPC keyboard/mouse input subsystem.
+ *
+ * Author : D.A.Bartlett (based on X_input.c)
+ *
+ * Notes : HELP!!!!!!
+ * Mods : Tim May 28, 92. Yoda break now on F11 if set YODA=1.
+ */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <ntddkbd.h>
+
+#include "insignia.h"
+#include "host_def.h"
+#include "xt.h"
+#include "keyboard.h"
+#include "keyba.h"
+#include "ica.h"
+#include "error.h"
+#include "config.h"
+#include "keyba.h"
+#include "gmi.h"
+#include "nt_uis.h"
+#include "sas.h"
+#include <stdio.h>
+#include "trace.h"
+#include "video.h"
+#include "debug.h"
+#include "nt_event.h"
+#include "nt_reset.h"
+#include "bios.h"
+#include CpuH
+
+#include "host.h"
+#include "host_hfx.h"
+#include "host_nls.h"
+#include "spcfile.h"
+
+
+// The command bits for the kbd light (same as real hardware)
+#define CAPS_LOCK 0x04
+#define NUM_LOCK 0x02
+#define SCROLL_LOCK 0x01
+
+// functions available thru the keyb functions table
+void nt_kb_prepare(void) {}
+
+
+#if NOTUSEDNOTUSED
+void nt_kb_light_off IFN1(half_word, kyLight) {}
+void nt_kb_restore(void) {}
+#endif
+
+void nt_kb_light_on(UCHAR);
+void nt_kb_init(void);
+void nt_kb_shutdown(void);
+
+
+// the keyb functions table
+KEYBDFUNCS nt_keybd_funcs = {nt_kb_prepare, // not implemented
+ nt_kb_prepare, // not implemented
+ nt_kb_prepare, // not implemented
+ nt_kb_prepare, // not implemented
+ nt_kb_light_on,
+ nt_kb_light_on // not implemented
+ };
+
+
+/*
+ * nt_kb_light_on
+ *
+ * This code gets called whenever kbdhdw tries to change the kbd leds.
+ * We cannot allow changes to the real leds because this would get us
+ * out of sync with user32 physical keyboard state. So what we do is
+ * to send fake keys to the kbd hdw to reset the state to what the
+ * the latest state is according to the console input
+ *
+ * Caller should hold the kbd mutex
+ */
+void nt_kb_light_on (unsigned char kyLight)
+{
+ DWORD KeyState;
+ unsigned char ChangeBits;
+
+ ChangeBits = kyLight >> 4;
+
+ KeyState = (ToggleKeyState & ~(CAPSLOCK_ON | NUMLOCK_ON | SCROLLLOCK_ON));
+
+ if(ChangeBits & CAPS_LOCK) {
+ if (kyLight & CAPS_LOCK)
+ KeyState |= CAPSLOCK_ON;
+ }
+ else {
+ KeyState |= ToggleKeyState & CAPSLOCK_ON;
+ }
+
+ if(ChangeBits & NUM_LOCK) {
+ if(kyLight & NUM_LOCK)
+ KeyState |= NUMLOCK_ON;
+ }
+ else {
+ KeyState |= ToggleKeyState & NUMLOCK_ON;
+ }
+
+
+ if(ChangeBits & SCROLL_LOCK) {
+ if(kyLight & SCROLL_LOCK)
+ KeyState |= SCROLLLOCK_ON;
+ }
+ else {
+ KeyState |= ToggleKeyState & SCROLLLOCK_ON;
+ }
+
+ if (ToggleKeyState != KeyState) {
+ SyncToggleKeys( 0, KeyState);
+ }
+
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_inthk.c b/private/mvdm/softpc.new/host/src/nt_inthk.c
new file mode 100644
index 000000000..a6e723212
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_inthk.c
@@ -0,0 +1,249 @@
+/*[
+ *
+ * Name: nt_inthk.c
+ *
+ * Derived From: (original)
+ *
+ * Author: Dave Bartlett
+ *
+ * Created On: 11 Jan 1995
+ *
+ * Coding Stds: 2.4
+ *
+ * Purpose: This module implements the memory management functions
+ * required for 486 NT.
+ *
+ * Include File: nt_inthk.h
+ *
+ * Copyright Insignia Solutions Ltd., 1994. All rights reserved.
+ *
+]*/
+
+
+#ifdef CPU_40_STYLE
+
+/* Need all of the following to include nt.h and windows.h in the same file. */
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "insignia.h"
+#include "host_def.h"
+
+#include "gdpvar.h"
+#include "nt_inthk.h"
+#include "debug.h"
+
+/* Make local symbols visible if debugging. */
+#ifndef PROD
+#define LOCAL
+#endif /* not PROD */
+
+/* Macros and typedefs. */
+
+
+/* Hardware interrupt handler */
+LOCAL BOOL (*HWIntHandler)(ULONG) = NULL;
+
+#if defined(CCPU) || !defined(PROD)
+/* Software interrupt handler */
+LOCAL BOOL (*SWIntHandler)(ULONG) = NULL;
+
+/* Exception interrupt handler */
+LOCAL BOOL (*EXIntHandler)(ULONG,ULONG) = NULL;
+
+#endif /* CCPU */
+
+/* Global Functions. */
+
+/*(
+============================= host_hwint_hook =================================
+PURPOSE:
+ This function is called from the ICA during the process of ACKing an
+ hardware interrupt. This function will call a hardware interrupt handler
+ if one is defined.
+
+INPUT:
+ Interrupt vector number generated from hardware interrupt
+OUTPUT:
+ Return value - TRUE hardware interrupt processed
+ FALSE process hardware interrupt in normal way
+================================================================================
+)*/
+
+
+#if defined(CCPU) || !defined(PROD)
+GLOBAL BOOL host_hwint_hook IFN1(IS32, int_no)
+{
+ BOOL returnStatus = FALSE;
+
+ /* hardware interrupt handler defined ? */
+ if(HWIntHandler)
+ {
+ returnStatus = (HWIntHandler)((ULONG) int_no);
+
+#ifndef PROD
+ if(!returnStatus)
+ always_trace0("Hardware interrupt handler failed");
+
+#endif /* PROD */
+ }
+
+ return( returnStatus );
+}
+#endif
+
+/*(
+======================= VdmInstallHardwareIntHandler ===========================
+PURPOSE:
+ Register a hardware interrupt handler called before the CPU dispatches
+ the interrupt.
+
+INPUT:
+ Hardware interrupt handler function
+
+OUTPUT:
+ Return value - NTSTATUS
+
+================================================================================
+)*/
+
+GLOBAL NTSTATUS VdmInstallHardwareIntHandler IFN1(PVOID, HardwareIntHandler)
+{
+#ifdef CCPU
+ HWIntHandler = HardwareIntHandler;
+#else
+ GLOBAL_VDM_HwIntHandler = HardwareIntHandler;
+#endif
+ return(STATUS_SUCCESS);
+}
+
+/*(
+============================= host_swint_hook =================================
+PURPOSE:
+ This function is called from the CCPU prior to provessing a software
+ interrupt. This function will call a software interrupt handler
+ if one is defined.
+
+INPUT:
+ Interrupt number
+OUTPUT:
+ Return value - TRUE software interrupt processed
+ FALSE process software interrupt in normal way
+
+================================================================================
+)*/
+
+
+#if defined(CCPU) || !defined(PROD)
+GLOBAL BOOL host_swint_hook IFN1(IS32, int_no)
+{
+ BOOL returnStatus = FALSE;
+
+ /* software interrupt handler defined ? */
+ if(SWIntHandler)
+ {
+ returnStatus = (SWIntHandler)((ULONG) int_no);
+
+#ifndef PROD
+
+ if(!returnStatus)
+ always_trace0("Software interrupt handler failed");
+
+#endif /* PROD */
+ }
+
+ return( returnStatus );
+}
+#endif /* CCPU */
+
+/*(
+======================= VdmInstallSoftwareIntHandler ===========================
+PURPOSE:
+ Register a software interrupt handler called before the CPU dispatches
+ the software interrupt.
+
+INPUT:
+ Software interrupt handler function
+
+OUTPUT:
+ Return value - NTSTATUS
+================================================================================
+)*/
+
+GLOBAL NTSTATUS VdmInstallSoftwareIntHandler IFN1(PVOID, SoftwareIntHandler)
+{
+#ifdef CCPU
+ SWIntHandler = SoftwareIntHandler;
+#else
+ GLOBAL_VDM_SoftIntHandler = SoftwareIntHandler;
+#endif
+ return(STATUS_SUCCESS);
+}
+
+/*(
+============================= host_exint_hook =================================
+PURPOSE:
+ This function is called from the CPU prior to processing a CPU
+ exception interrupt. This function will call a exception interrupt
+ handler if one is defined.
+
+INPUT:
+ Exception number
+ Exception error code
+OUTPUT:
+ Return value - TRUE hardware interrupt processed
+ FALSE process hardware interrupt in normal way
+
+================================================================================
+)*/
+
+
+#if defined(CCPU) || !defined(PROD)
+GLOBAL BOOL host_exint_hook IFN2(IS32, exp_no, IS32, error_code)
+{
+ BOOL returnStatus = FALSE;
+
+ /* exception interrupt handler defined ? */
+ if(EXIntHandler)
+ {
+ returnStatus = (EXIntHandler)((ULONG) exp_no, (ULONG) error_code);
+
+#ifndef PROD
+
+ if(!returnStatus)
+ always_trace0("Exception interrupt handler failed (%x)");
+
+#endif /* PROD */
+ }
+
+ return( returnStatus );
+}
+#endif /* CCPU */
+
+/*(
+======================= VdmInstallFaultHandler ===========================
+PURPOSE:
+ Register a CPU exception interrupt handler called before the CPU
+ dispatches the exceptioninterrupt.
+
+INPUT:
+ Exception interrupt handler function
+
+OUTPUT:
+ Return value - NTSTATUS
+================================================================================
+)*/
+
+GLOBAL NTSTATUS VdmInstallFaultHandler IFN1(PVOID, FaultHandler)
+{
+#ifdef CCPU
+ EXIntHandler = FaultHandler;
+#else
+ GLOBAL_VDM_FaultHandler = FaultHandler;
+#endif
+ return(STATUS_SUCCESS);
+}
+
+#endif /* CPU_40_STYLE */
diff --git a/private/mvdm/softpc.new/host/src/nt_keycd.c b/private/mvdm/softpc.new/host/src/nt_keycd.c
new file mode 100644
index 000000000..2d1f80423
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_keycd.c
@@ -0,0 +1,605 @@
+/***************************************************************************
+ * *
+ * MODULE : nt_keycd.c *
+ * *
+ * PURPOSE : Convert a windows key message to a PC keyboard number *
+ * *
+ * FUNCTIONS : KeyMsgToKeyCode() *
+ * *
+ ****************************************************************************/
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+
+#include "windows.h"
+
+//
+// OEM Scancode to (ie Scancode set 1) to keynum table.
+// Somehow this has to end up being loaded rather than compiled in...
+//
+#define UNDEFINED 0
+
+/*@ACW=======================================================================
+
+Microsoft now use scan code set 1 as their base scan code set. This means that
+we had to change ours also. Not only that, two tables are needed now: one to
+hold the regular keyset, the other to hold the ENHANCED key options. Scan code
+set 1 differs to scan code set 3 in that some scan codes are the same for
+different keystrokes. So when an enhanced bit is set in the KEY_EVENT_RECORD.
+dwControlKeyState, a second (very sparse) table is substituted for the regular
+one.
+A small, teensy, weensy detail... All the key numbers are mapped to different
+scancode values for the regular keys just to make life a little more fun!
+
+============================================================================*/
+
+BYTE Scan1ToKeynum[] =
+{
+ // Keynum Scancode US encoding
+
+
+ UNDEFINED, // 0x0
+ 110, // 0x1 Escape
+ 2, // 0x2 1 !
+ 3, // 0x3 2 @
+ 4, // 0x4 3 #
+ 5, // 0x5 4 $
+ 6, // 0x6 5 %
+ 7, // 0x7 6 ^
+ 8, // 0x8 7 &
+ 9, // 0x9 8 *
+ 10, // 0xa 9 (
+ 11, // 0xb 0 )
+ 12, // 0xc - _
+ 13, // 0xd = +
+ 15, // 0xe Backspace
+ 16, // 0xf Tab
+ 17, // 0x10 q Q
+ 18, // 0x11 w W
+ 19, // 0x12 e E
+ 20, // 0x13 r R
+ 21, // 0x14 t T
+ 22, // 0x15 y Y
+ 23, // 0x16 u U
+ 24, // 0x17 i I
+ 25, // 0x18 o O
+ 26, // 0x19 p P
+ 27, // 0x1a [ {
+ 28, // 0x1b ] }
+ 43, // 0x1c Enter
+ 58, // 0x1d Left Control
+ 31, // 0x1e a A
+ 32, // 0x1f s S
+ 33, // 0x20 d D
+ 34, // 0x21 f F
+ 35, // 0x22 g G
+ 36, // 0x23 h H
+ 37, // 0x24 j J
+ 38, // 0x25 k K
+ 39, // 0x26 l L
+ 40, // 0x27 ; :
+ 41, // 0x28 ' "
+ 1, // 0x29 ` ~
+ 44, // 0x2a Left Shift
+ 42, // 0x2b \ | or International Key UK = ~ #
+ 46, // 0x2c z Z
+ 47, // 0x2d x X
+ 48, // 0x2e c C
+ 49, // 0x2f v V
+ 50, // 0x30 b B
+ 51, // 0x31 n N
+ 52, // 0x32 m M
+ 53, // 0x33 , <
+ 54, // 0x34 . >
+ 55, // 0x35 / ?
+ 57, // 0x36 Right Shift (see extended table)
+ 100, // 0x37 Keypad *
+ 60, // 0x38 Left Alt
+ 61, // 0x39 Space
+ 30, // 0x3a Caps Lock
+ 112, // 0x3b F1
+ 113, // 0x3c F2
+ 114, // 0x3d F3
+ 115, // 0x3e F4
+ 116, // 0x3f F5
+ 117, // 0x40 F6
+ 118, // 0x41 F7
+ 119, // 0x42 F8
+ 120, // 0x43 F9
+ 121, // 0x44 F10
+ 126, // 0x45 Break Key
+ 125, // 0x46 Scroll Lock
+ 91, // 0x47 Keypad Home 7
+ 96, // 0x48 Keypad Up 8
+ 101, // 0x49 Keypad Pg Up
+ 105, // 0x4a Keypad -
+ 92, // 0x4b Keypad Left 4
+ 97, // 0x4c Keypad 5
+ 102, // 0x4d Keypad Right 6
+ 106, // 0x4e Keypad +
+ 93, // 0x4f Keypad End 1
+ 98, // 0x50 Keypad Down 2
+ 103, // 0x51 Keypad Pg Down 3
+ 99, // 0x52 Keypad Ins 0
+ 104, // 0x53 Keypad Del .
+ UNDEFINED, // 0x54
+ UNDEFINED, // 0x55
+ 45, // 0x56 International Key UK = \ |
+ 122, // 0x57 F11
+ 123, // 0x58 F12
+ UNDEFINED, // 0x59
+ UNDEFINED, // 0x5a
+ UNDEFINED, // 0x5b
+ UNDEFINED, // 0x5c
+ UNDEFINED, // 0x5d
+ UNDEFINED, // 0x5e
+ UNDEFINED, // 0x5f
+ UNDEFINED, // 0x60
+ UNDEFINED, // 0x61
+ UNDEFINED, // 0x62
+ UNDEFINED, // 0x63
+ UNDEFINED, // 0x64
+ UNDEFINED, // 0x65
+ UNDEFINED, // 0x66
+ UNDEFINED, // 0x67
+ UNDEFINED, // 0x68
+ UNDEFINED, // 0x69
+ UNDEFINED, // 0x6a
+ UNDEFINED, // 0x6b
+ UNDEFINED, // 0x6c
+ UNDEFINED, // 0x6d
+ UNDEFINED, // 0x6e
+ UNDEFINED, // 0x6f
+ UNDEFINED, // 0x70
+ UNDEFINED, // 0x71
+ UNDEFINED, // 0x72
+ 56, // 0x73 Brazilian ABNT / ?
+ UNDEFINED, // 0x74
+ UNDEFINED, // 0x75
+ UNDEFINED, // 0x76
+ UNDEFINED, // 0x77
+ UNDEFINED, // 0x78
+ UNDEFINED, // 0x79
+ UNDEFINED, // 0x7a
+ UNDEFINED, // 0x7b
+ 94, // 0x7c Extended kbd (IBM 122 key)
+ 14, // 0x7d Extended kbd (IBM 122 key)
+ 107, // 0x7e Brazilian ABNT numpad .
+ UNDEFINED, // 0x7f
+ UNDEFINED, // 0x80
+ UNDEFINED, // 0x81
+ UNDEFINED, // 0x82
+ UNDEFINED, // 0x83
+ UNDEFINED // 0x84
+};
+
+/*@ACW====================================================================
+
+Note that in the following extended keyboard table, the shift key values
+have also been given an entry because these keys can be used as modifiers
+for the other extended keys.
+
+========================================================================*/
+
+
+BYTE Scan1ToKeynumExtended[] =
+{
+ // Keynum Scancode US encoding
+
+ 31, // 0x0
+ UNDEFINED, // 0x1
+ UNDEFINED, // 0x2
+ UNDEFINED, // 0x3
+ UNDEFINED, // 0x4
+ UNDEFINED, // 0x5
+ UNDEFINED, // 0x6
+ UNDEFINED, // 0x7
+ UNDEFINED, // 0x8
+ UNDEFINED, // 0x9
+ UNDEFINED, // 0xa
+ UNDEFINED, // 0xb
+ UNDEFINED, // 0xc
+ UNDEFINED, // 0xd
+ UNDEFINED, // 0xe
+ UNDEFINED, // 0xf
+ UNDEFINED, // 0x10
+ UNDEFINED, // 0x11
+ UNDEFINED, // 0x12
+ UNDEFINED, // 0x13
+ UNDEFINED, // 0x14
+ UNDEFINED, // 0x15
+ UNDEFINED, // 0x16
+ UNDEFINED, // 0x17
+ UNDEFINED, // 0x18
+ UNDEFINED, // 0x19
+ UNDEFINED, // 0x1a
+ UNDEFINED, // 0x1b
+ 108, // 0x1c Extended 1c Num Enter
+ 64, // 0x1d Extended 1d Right Ctrl
+ UNDEFINED, // 0x1e
+ UNDEFINED, // 0x1f
+ UNDEFINED, // 0x20
+ UNDEFINED, // 0x21
+ UNDEFINED, // 0x22
+ UNDEFINED, // 0x23
+ UNDEFINED, // 0x24
+ UNDEFINED, // 0x25
+ UNDEFINED, // 0x26
+ UNDEFINED, // 0x27
+ UNDEFINED, // 0x28
+ UNDEFINED, // 0x29
+ 44, // 0x2a Extended 2a left shift
+ UNDEFINED, // 0x2b
+ UNDEFINED, // 0x2c
+ UNDEFINED, // 0x2d
+ UNDEFINED, // 0x2e
+ UNDEFINED, // 0x2f
+ UNDEFINED, // 0x30
+ UNDEFINED, // 0x31
+ UNDEFINED, // 0x32
+ UNDEFINED, // 0x33
+ UNDEFINED, // 0x34
+ 95, // 0x35 Extended 35 keypad /
+ 57, // 0x36 Extended 36 right shift
+ 124, // 0x37 PrintScreen
+ 62, // 0x38 Extended 38 right alt
+ UNDEFINED, // 0x39
+ UNDEFINED, // 0x3a
+ UNDEFINED, // 0x3b
+ UNDEFINED, // 0x3c
+ UNDEFINED, // 0x3d
+ UNDEFINED, // 0x3e
+ UNDEFINED, // 0x3f
+ UNDEFINED, // 0x40
+ UNDEFINED, // 0x41
+ UNDEFINED, // 0x42
+ UNDEFINED, // 0x43
+ UNDEFINED, // 0x44
+ 90, // 0x45 Num Lock
+ 126, // 0x46
+ 80, // 0x47 Extended 47 Home
+ 83, // 0x48 Extended 48 Up
+ 85, // 0x49 Extended 49 Page up
+ UNDEFINED, // 0x4a
+ 79, // 0x4b Extended 4b Left
+ UNDEFINED, // 0x4c
+ 89, // 0x4d Extended 4d Right
+ UNDEFINED, // 0x4e
+ 81, // 0x4f Extended 4f End
+ 84, // 0x50 Extended 50 Down
+ 86, // 0x51 Extended 51 Page Down
+ 75, // 0x52 Extended 52 Insert
+ 76, // 0x53 Extended 53 Delete
+
+};
+
+
+
+/*
+ * Table for translating BiosBuffer scan codes with special
+ * NULL ascii chars, and their associated control flags
+ * If it is not in this table The Bios scan code should
+ * be the same as the win32 Scan code.
+ */
+#define FIRST_NULLCHARSCAN 0x54
+#define LAST_NULLCHARSCAN 0xa6
+
+typedef struct _NullAsciiCharScan {
+ WORD wWinSCode;
+ DWORD dwControlState;
+} NULLCHARSCAN;
+
+NULLCHARSCAN aNullCharScan[] =
+{
+// WinSCode dwControlState BiosSCode Keys
+
+ 0x3b, SHIFT_PRESSED, // 0x54 Shift+F1
+ 0x3c, SHIFT_PRESSED, // 0x55 Shift+F2
+ 0x3d, SHIFT_PRESSED, // 0x56 Shift+F3
+ 0x3e, SHIFT_PRESSED, // 0x57 Shift+F4
+ 0x3f, SHIFT_PRESSED, // 0x58 Shift+F5
+ 0x40, SHIFT_PRESSED, // 0x59 Shift+F6
+ 0x41, SHIFT_PRESSED, // 0x5a Shift+F7
+ 0x42, SHIFT_PRESSED, // 0x5b Shift+F8
+ 0x43, SHIFT_PRESSED, // 0x5c Shift+F9
+ 0x44, SHIFT_PRESSED, // 0x5d Shift+F10
+ 0x3b, LEFT_CTRL_PRESSED, // 0x5e Ctrl+F1
+ 0x3c, LEFT_CTRL_PRESSED, // 0x5f Ctrl+F2
+ 0x3d, LEFT_CTRL_PRESSED, // 0x60 Ctrl+F3
+ 0x3e, LEFT_CTRL_PRESSED, // 0x61 Ctrl+F4
+ 0x3f, LEFT_CTRL_PRESSED, // 0x62 Ctrl+F5
+ 0x40, LEFT_CTRL_PRESSED, // 0x63 Ctrl+F6
+ 0x41, LEFT_CTRL_PRESSED, // 0x64 Ctrl+F7
+ 0x42, LEFT_CTRL_PRESSED, // 0x65 Ctrl+F8
+ 0x43, LEFT_CTRL_PRESSED, // 0x66 Ctrl+F9
+ 0x44, LEFT_CTRL_PRESSED, // 0x67 Ctrl+F10
+ 0x3b, LEFT_ALT_PRESSED, // 0x68 Alt+F1
+ 0x3c, LEFT_ALT_PRESSED, // 0x69 Alt+F2
+ 0x3d, LEFT_ALT_PRESSED, // 0x6a Alt+F3
+ 0x3e, LEFT_ALT_PRESSED, // 0x6b Alt+F4
+ 0x3f, LEFT_ALT_PRESSED, // 0x6c Alt+F5
+ 0x40, LEFT_ALT_PRESSED, // 0x6d Alt+F6
+ 0x41, LEFT_ALT_PRESSED, // 0x6e Alt+F7
+ 0x42, LEFT_ALT_PRESSED, // 0x6f Alt+F8
+ 0x43, LEFT_ALT_PRESSED, // 0x70 Alt+F9
+ 0x44, LEFT_ALT_PRESSED, // 0x71 Alt+F10
+ 0, 0, // 0x72 Ctrl+PrtSc
+ 0x4b, LEFT_CTRL_PRESSED, // 0x73 Ctrl+Left
+ 0x4d, LEFT_CTRL_PRESSED, // 0x74 Ctrl+Right
+ 0x4f, LEFT_CTRL_PRESSED, // 0x75 Ctrl+End
+ 0x51, LEFT_CTRL_PRESSED, // 0x76 Ctrl+PgDn
+ 0x47, LEFT_CTRL_PRESSED, // 0x77 Ctrl+Home
+ 0x2, LEFT_ALT_PRESSED, // 0x78 Alt+1
+ 0x3, LEFT_ALT_PRESSED, // 0x79 Alt+2
+ 0x4, LEFT_ALT_PRESSED, // 0x7a Alt+3
+ 0x5, LEFT_ALT_PRESSED, // 0x7b Alt+4
+ 0x6, LEFT_ALT_PRESSED, // 0x7c Alt+5
+ 0x7, LEFT_ALT_PRESSED, // 0x7d Alt+6
+ 0x8, LEFT_ALT_PRESSED, // 0x7e Alt+7
+ 0x9, LEFT_ALT_PRESSED, // 0x7f Alt+8
+ 0xa, LEFT_ALT_PRESSED, // 0x80 Alt+9
+ 0xb, LEFT_ALT_PRESSED, // 0x81 Alt+0
+ 0xc, LEFT_ALT_PRESSED, // 0x82 Alt+-
+ 0xd, LEFT_ALT_PRESSED, // 0x83 Alt+=
+ 0x49, LEFT_CTRL_PRESSED, // 0x84 Ctrl+PgUp
+ 0, 0, // 0x85 ?????
+ 0, 0, // 0x86 ?????
+ 0x85, SHIFT_PRESSED, // 0x87 Shift+F11
+ 0x86, SHIFT_PRESSED, // 0x88 Shift+F12
+ 0x85, LEFT_CTRL_PRESSED, // 0x89 Ctrl+F11
+ 0x86, LEFT_CTRL_PRESSED, // 0x8a Ctrl+F12
+ 0x85, LEFT_ALT_PRESSED, // 0x8b Alt+F11
+ 0x86, LEFT_ALT_PRESSED, // 0x8c Alt+F12
+ 0x48, LEFT_CTRL_PRESSED, // 0x8d Ctrl+Up
+ 0x4a, LEFT_CTRL_PRESSED, // 0x8e Ctrl+-
+ 0x4c, LEFT_CTRL_PRESSED, // 0x8f Ctrl+5
+ 0x4e, LEFT_CTRL_PRESSED, // 0x90 Ctrl++
+ 0x50, LEFT_CTRL_PRESSED, // 0x91 Ctrl+Down
+ 0x52, LEFT_CTRL_PRESSED, // 0x92 Ctrl+Ins
+ 0x53, LEFT_CTRL_PRESSED, // 0x93 Ctrl+Del
+ 0, 0, // 0x94 ?????
+ 0, 0, // 0x95 ?????
+ 0, 0, // 0x96 ?????
+ 0x47, LEFT_ALT_PRESSED, // 0x97 Alt+Home
+ 0x48, LEFT_ALT_PRESSED, // 0x98 Alt+Up
+ 0x49, LEFT_ALT_PRESSED, // 0x99 Alt+PgUp
+ 0, 0, // 0x9a ?????
+ 0x4b, LEFT_ALT_PRESSED, // 0x9b Alt+Left
+ 0, 0, // 0x9c ?????
+ 0x4d, LEFT_ALT_PRESSED, // 0x9d Alt+Right
+ 0, 0, // 0x9e ?????
+ 0x4f, LEFT_ALT_PRESSED, // 0x9f Alt+End
+ 0x50, LEFT_ALT_PRESSED, // 0xa0 Alt+Down
+ 0x51, LEFT_ALT_PRESSED, // 0xa1 Alt+PgDn
+ 0x52, LEFT_ALT_PRESSED, // 0xa2 Alt+Ins
+ 0x53, LEFT_ALT_PRESSED, // 0xa3 Alt+Del
+ 0, 0, // 0xa4 ?????
+ 0xf, LEFT_ALT_PRESSED, // 0xa5 Alt+Tab
+ 0x1c, LEFT_ALT_PRESSED // 0xa6 Alt+Enter
+};
+
+
+WORD aNumPadSCode[] = // index by VK_NUMPAD0 as zero offset
+{
+ 0x52, // VK_NUMPAD0 - 60
+ 0x4f, // VK_NUMPAD1 61
+ 0x50, // VK_NUMPAD2 62
+ 0x51, // VK_NUMPAD3 63
+ 0x4b, // VK_NUMPAD4 64
+ 0x4c, // VK_NUMPAD5 65
+ 0x4d, // VK_NUMPAD6 66
+ 0x47, // VK_NUMPAD7 67
+ 0x48, // VK_NUMPAD8 68
+ 0x49 // VK_NUMPAD9 69
+};
+
+
+
+
+
+
+ /****************************************************************************
+ * *
+ * FUNCTIONS : BYTE KeyMsgToKeyCode(WORD vKey, DWORD KeyFlags) *
+ * *
+ * PURPOSE : Convert a windows key message to a PC keyboard number *
+ * Return 0 if not mapped. *
+ * *
+ ****************************************************************************/
+
+BYTE KeyMsgToKeyCode(PKEY_EVENT_RECORD KeyEvent)
+{
+ /*:::::::::::::::::::::::::::::::::::: do we need the enhanced key set ? */
+
+ if(!(KeyEvent->dwControlKeyState & ENHANCED_KEY))
+ {
+
+ /*............................... the regular keyset is what we need */
+
+ return KeyEvent->wVirtualScanCode > sizeof(Scan1ToKeynum)
+ ? 0
+ : Scan1ToKeynum[KeyEvent->wVirtualScanCode];
+ }
+ else
+ {
+ /*.................................. we do need the extended key set */
+
+
+ return KeyEvent->wVirtualScanCode > sizeof(Scan1ToKeynumExtended)
+ ? 0
+ : Scan1ToKeynumExtended[KeyEvent->wVirtualScanCode];
+ }
+}
+
+
+
+
+
+/* BiosKeyToInputRecord
+ *
+ * Translates Bios Buffer Keys to win32 console type of key_events.
+ *
+ * entry: pKeyEvent - addr of KEY_EVENT structure
+ * pKeyEvent->uChar.AsciiChar - Bios Buffer character
+ * pKeyEvent->wVirtualScanCode - Bios Buffer scan code
+ *
+ * exit: all KEY_EVENT fields are filled in.
+ * The AsciiChar has been converted to unicode
+ *
+ * If a character is not in the current keyboard layout
+ * we return TRUE with: dwControlKeyState |= NUMLOCK_ON;
+ * wVirtualKeyCode = VK_MENU;
+ * wVirtualScanCode = 0x38;
+ * OemChar (not unicode)
+ */
+BOOL BiosKeyToInputRecord(PKEY_EVENT_RECORD pKeyEvent)
+{
+ USHORT KeyState;
+ NTSTATUS Status;
+ UCHAR AsciiChar=(UCHAR)pKeyEvent->uChar.AsciiChar;
+ WCHAR UnicodeChar;
+
+ pKeyEvent->wRepeatCount = 1;
+ pKeyEvent->wVirtualKeyCode = 0;
+ pKeyEvent->dwControlKeyState = 0;
+
+ // we treat 0xF0 Ascii Char as NULL char just like the bios
+ if (AsciiChar == 0xF0 && pKeyEvent->wVirtualScanCode) {
+ AsciiChar = 0;
+ }
+
+
+ // convert oem char to unicode character, cause we can do it more
+ // efficiently than console (already going thru char by char).
+ Status = RtlOemToUnicodeN(&UnicodeChar,
+ sizeof(WCHAR),
+ NULL,
+ &AsciiChar,
+ 1 );
+ if (!NT_SUCCESS(Status)) {
+ return FALSE;
+ }
+
+
+
+ // Convert BiosBuffer ScanCode for NULL asciiChars to
+ // windows scan code
+ if ( (!AsciiChar) &&
+ pKeyEvent->wVirtualScanCode >= FIRST_NULLCHARSCAN &&
+ pKeyEvent->wVirtualScanCode <= LAST_NULLCHARSCAN )
+ {
+ pKeyEvent->wVirtualScanCode -= FIRST_NULLCHARSCAN;
+ pKeyEvent->dwControlKeyState = aNullCharScan[pKeyEvent->wVirtualScanCode].dwControlState;
+ pKeyEvent->wVirtualScanCode = aNullCharScan[pKeyEvent->wVirtualScanCode].wWinSCode;
+ }
+
+
+ // Some CTRL-Extended keys have special bios scan codes
+ // These scan codes are not recognized by windows. Change
+ // to a windows compatible scan code, and set CTRL flag
+ else if (AsciiChar == 0xE0 && pKeyEvent->wVirtualScanCode) {
+ pKeyEvent->dwControlKeyState = ENHANCED_KEY;
+ if (AsciiChar == 0xE0) {
+ pKeyEvent->dwControlKeyState |= LEFT_CTRL_PRESSED;
+ switch (pKeyEvent->wVirtualScanCode) {
+ case 0x73: pKeyEvent->wVirtualScanCode = 0x4B;
+ break;
+ case 0x74: pKeyEvent->wVirtualScanCode = 0x4D;
+ break;
+ case 0x75: pKeyEvent->wVirtualScanCode = 0x4f;
+ break;
+ case 0x76: pKeyEvent->wVirtualScanCode = 0x51;
+ break;
+ case 0x77: pKeyEvent->wVirtualScanCode = 0x47;
+ break;
+ case 0x84: pKeyEvent->wVirtualScanCode = 0x49;
+ break;
+ case 0x8D: pKeyEvent->wVirtualScanCode = 0x48;
+ break;
+ case 0x91: pKeyEvent->wVirtualScanCode = 0x50;
+ break;
+ case 0x92: pKeyEvent->wVirtualScanCode = 0x52;
+ break;
+ case 0x93: pKeyEvent->wVirtualScanCode = 0x53;
+ break;
+
+ default: // the rest should have correct scan codes
+ // but not CTRL bit
+ pKeyEvent->dwControlKeyState &= ~LEFT_CTRL_PRESSED;
+ }
+ }
+
+ AsciiChar = 0;
+ UnicodeChar = 0;
+ }
+
+
+ // The keypad "/" and the keypad "enter" special cases
+
+ else if (pKeyEvent->wVirtualScanCode == 0xE0) {
+ pKeyEvent->dwControlKeyState = ENHANCED_KEY;
+ if (AsciiChar == 0x2f) { // is keypad "/"
+ pKeyEvent->wVirtualScanCode = 0x35;
+ pKeyEvent->wVirtualKeyCode = VK_DIVIDE;
+ }
+ else { // is keypad enter chars == 0xd, 0xa
+ pKeyEvent->wVirtualScanCode = 0x1C;
+ pKeyEvent->wVirtualKeyCode = VK_RETURN;
+ if (AsciiChar == 0xA) {
+ pKeyEvent->dwControlKeyState |= LEFT_CTRL_PRESSED;
+ }
+ }
+ }
+
+
+
+ // get control flags\VirtualKey for normal ascii characters,
+
+ else if (AsciiChar &&
+ pKeyEvent->wVirtualScanCode != 0x01 && // ESC
+ pKeyEvent->wVirtualScanCode != 0x0E && // Backspace
+ pKeyEvent->wVirtualScanCode != 0x0F && // Tab
+ pKeyEvent->wVirtualScanCode != 0x1C ) // Enter
+ {
+
+ KeyState = (USHORT) VkKeyScanW(UnicodeChar);
+
+ if (KeyState == 0xFFFF) {
+ /* fail means not a physical key (ALT-NUMPAD entry sequence)
+ * Proper emeulation requires that we generate it by doing
+ * ALT-NUMLOCK-xxx-NUMLOCK-ALT.
+ * We shortcut this by sending console, the final key event.
+ * hoping that apps won't notice the difference.
+ */
+ pKeyEvent->wVirtualScanCode = 0;
+ pKeyEvent->wVirtualKeyCode = VK_MENU; // dummy opt
+ }
+ else {
+ pKeyEvent->wVirtualKeyCode = (WORD)LOBYTE(KeyState);
+ if (KeyState & 0x100)
+ pKeyEvent->dwControlKeyState |= SHIFT_PRESSED;
+ if (KeyState & 0x200)
+ pKeyEvent->dwControlKeyState |= LEFT_CTRL_PRESSED;
+ if (KeyState & 0x400)
+ pKeyEvent->dwControlKeyState |= LEFT_ALT_PRESSED;
+
+ // some keys get mapped to different scan codes (NUMPAD)
+ // so get matching scan code
+ pKeyEvent->wVirtualScanCode = MapVirtualKey(pKeyEvent->wVirtualKeyCode,0);
+ }
+ }
+
+
+ // Get a Virtual KeyCode, if we don't have one yet
+ if (!pKeyEvent->wVirtualKeyCode) {
+ pKeyEvent->wVirtualKeyCode = MapVirtualKey(pKeyEvent->wVirtualScanCode,3);
+ if (!pKeyEvent->wVirtualKeyCode) {
+ return FALSE;
+ }
+ }
+
+ pKeyEvent->uChar.UnicodeChar = UnicodeChar;
+
+
+ return TRUE;
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_lpt.c b/private/mvdm/softpc.new/host/src/nt_lpt.c
new file mode 100644
index 000000000..083ca7586
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_lpt.c
@@ -0,0 +1,698 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntddvdm.h>
+#include <windows.h>
+#include "insignia.h"
+#include "host_def.h"
+#include <malloc.h>
+
+
+/*
+ * Name: nt_lpt.c
+ * Derived From: Sun 2.0 sun4_lpt.c
+ * Author: D A Bartlett
+ * Created On:
+ * Purpose: NT specific parallel port functions
+ *
+ * (c)Copyright Insignia Solutions Ltd., 1991. All rights reserved.
+ *
+
+ * Note. This port is unlike most ports because the config system has been
+ * removed. It was the job of the config system to validate and open the
+ * printer ports. The only calls to the host printer system are now
+ * make from printer.c. and consist of the following calls.
+ *
+ *
+ * 1) host_print_byte
+ * 2) host_print_auto_feed
+ * 3) host_print_doc
+ * 4) host_lpt_status
+ *
+ *
+ * On the Microsoft model the printer ports will be opened when they are
+ * written to.
+ *
+ * Modifications:
+ *
+ * Tim June 92. Amateur attempt at buffered output to speed things up.
+ *
+ */
+
+
+/*
+
+
+Work outstanding on this module,
+
+1) Check the usage of port_state
+2) Check error handling in write function
+3) host_print_doc() always flushs the port, is this correct ?
+4) host_print_auto_feed - what should this function do ?
+5) Error handling in host_printer_open(), UIF needed ?
+
+*/
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */
+
+#ifdef PRINTER
+
+/* SoftPC include files */
+#include "xt.h"
+#include "error.h"
+#include "config.h"
+#include "timer.h"
+#include "host_lpt.h"
+#include "hostsync.h"
+#include "host_rrr.h"
+#include "gfi.h"
+#include "debug.h"
+#include "idetect.h"
+#include "sas.h"
+#include "printer.h"
+#ifndef PROD
+#include "trace.h"
+#endif
+
+boolean flushBuffer IFN1(int, adapter);
+#ifdef MONITOR
+extern BOOLEAN MonitorInitializePrinterInfo(WORD, PWORD, PUCHAR, PUCHAR, PUCHAR, PUCHAR);
+extern BOOLEAN MonitorEnablePrinterDirectAccess(WORD, HANDLE, BOOLEAN);
+extern BOOLEAN MonitorPrinterWriteData(WORD Adapter, BYTE Value);
+
+extern sys_addr lp16BitPrtBuf;
+extern sys_addr lp16BitPrtCount;
+extern sys_addr lp16BitPrtId;
+boolean host_print_buffer(int adapter);
+#endif
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: Macros ::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+#ifdef MONITOR
+
+sys_addr lpt_status_addr;
+
+#define get_lpt_status(adap) \
+ (sas_hw_at_no_check(lpt_status_addr+(adap)))
+#define set_lpt_status(adap,val) \
+ (sas_store_no_check(lpt_status_addr+(adap), (val)))
+
+#else /* MONITOR */
+
+#define get_lpt_status(adap) (host_lpt[(adap)].port_status)
+#define set_lpt_status(adap,val) (host_lpt[(adap)].port_status = (val))
+
+#endif /* MONITOR */
+
+#define KBUFFER_SIZE 1024 // Buffering macros
+#define HIGH_WATER 1020
+#define DIRECT_ACCESS_HIGH_WATER 1020
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: Structure for host specific state data ::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+typedef struct
+{
+ ULONG port_status; // Port status
+ HANDLE handle; // Printer handle
+ int inactive_counter; // Inactivate counter
+ int inactive_trigger; // When equal to inactive_counter close port
+ int bytesInBuffer; // current size of buffer
+ int flushThreshold; //
+ DWORD FileType; // DISK, CHAR, PIPE etc.
+ BOOLEAN active; // Printer open and active
+ BOOLEAN dos_opened; // printer opened with DOS open
+ byte *kBuffer; // output buffer
+ BOOLEAN direct_access;
+ BOOLEAN no_device_attached;
+} HOST_LPT;
+
+HOST_LPT host_lpt[NUM_PARALLEL_PORTS];
+
+#ifdef MONITOR
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::: On x86 machines the host_lpt_status table is kept on the 16-bit ::::*/
+/*:::: side in order to reduce the number of expensive BOPs. Here we ::::*/
+/*:::: are passed the address of the table. ::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL void host_printer_setup_table(sys_addr table_addr, word nPorts, word * portAddr)
+{
+ lpt_status_addr = table_addr + 3 * NUM_PARALLEL_PORTS;
+ // Now fill in the TIB entries for printer_info
+ MonitorInitializePrinterInfo (nPorts,
+ portAddr,
+ (LPBYTE)(table_addr + NUM_PARALLEL_PORTS),
+ (LPBYTE)(table_addr + 2 * NUM_PARALLEL_PORTS),
+ (LPBYTE)(table_addr),
+ (LPBYTE)(lpt_status_addr)
+ );
+
+
+}
+
+#endif /* MONITOR */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::: Set auto close trigger :::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+VOID host_set_inactivate_counter(int adapter)
+{
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+ int close_in_ms; // Flush rate in milliseconds
+
+ /*::::::::::::::::::::::::::::::::::::::::::::::: Is auto close enabled */
+
+
+ if(!config_inquire(C_AUTOFLUSH, NULL))
+ {
+ lpt->inactive_trigger = 0; /* Disable auto flush */
+ return; /* Autoflush not active */
+ }
+
+ /*::::::::::::::::::::::::::::::::::::::::::: Calculate closedown count */
+
+ close_in_ms = ((int) config_inquire(C_AUTOFLUSH_DELAY, NULL)) * 1000;
+
+ lpt->inactive_trigger = close_in_ms / (SYSTEM_TICK_INTV/1000);
+
+ lpt->inactive_counter = 0; //Reset close down counter
+ lpt->no_device_attached = FALSE;
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::: Open printer :::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+SHORT host_lpt_open(int adapter, BOOLEAN direct_access)
+{
+ DWORD BytesReturn;
+
+ FAST HOST_LPT *lpt = &host_lpt[adapter]; // Adapter control structure
+ CHAR *lptName; // Adapter filename
+
+ if (!direct_access)
+ lpt->no_device_attached = FALSE;
+ else if (lpt->no_device_attached)
+ return FALSE;
+
+ lpt->bytesInBuffer = 0; // Init output buffer index
+
+ /*::::::::::::::::::::::::::::::::::::::::: Get printer name for Config */
+
+ /* use a different device name for DONGLE support */
+ lptName = (CHAR *) config_inquire((UTINY)((direct_access ? C_VDMLPT1_NAME :
+ C_LPT1_NAME)
+ + adapter), NULL);
+
+#ifndef PROD
+ fprintf(trace_file, "Opening printer port %s (%d)\n",lptName,adapter);
+#endif
+
+ if ((lpt->kBuffer = (byte *)host_malloc (KBUFFER_SIZE)) == NULL) {
+ // dont put a popup here as the caller of this routine handles it
+ return(FALSE);
+ }
+ lpt->flushThreshold = HIGH_WATER;
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::: Open printer */
+
+
+ lpt->direct_access = FALSE;
+ lpt->active = FALSE;
+
+ lpt->handle = CreateFile(lptName,
+ GENERIC_WRITE,
+ direct_access ? 0 : FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::::: Valid open request */
+
+ if(lpt->handle == (HANDLE) -1)
+ {
+ host_free (lpt->kBuffer);
+ // UIF needed to inform user that the open attempt failed
+#ifndef PROD
+ fprintf(trace_file, "Failed to open printer port\n");
+#endif
+ if (direct_access && GetLastError() == ERROR_FILE_NOT_FOUND)
+ lpt->no_device_attached = TRUE;
+
+ return(FALSE);
+ }
+
+
+ /*::::::::::::::::::::::::::::::::::::::Activate port and reset status */
+
+ lpt->FileType = GetFileType(lpt->handle);
+ // can not open direct_access access to a redirected device.
+ if (direct_access && lpt->FileType != FILE_TYPE_CHAR) {
+ CloseHandle(lpt->handle);
+ return FALSE;
+ }
+ lpt->active = TRUE;
+ set_lpt_status(adapter, 0);
+ lpt->direct_access = direct_access;
+ if (lpt->direct_access) {
+ lpt->flushThreshold = DIRECT_ACCESS_HIGH_WATER;
+#ifdef MONITOR
+ MonitorEnablePrinterDirectAccess((WORD)adapter, lpt->handle, TRUE);
+#endif
+ }
+
+ /*:::::::::::::::::::::::::::::::::::::::::: Setup auto close counters */
+
+ host_set_inactivate_counter(adapter);
+
+ return(TRUE);
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: Close all printer ports ::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+GLOBAL void host_lpt_close_all(void)
+{
+ FAST HOST_LPT *lpt;
+ FAST int i;
+
+ /*::::::::::: Scan through printer adapters updating auto flush counters */
+
+
+ for(i=0, lpt = &host_lpt[0]; i < NUM_PARALLEL_PORTS; i++, lpt++)
+ {
+
+ if(lpt->active)
+ host_lpt_close(i); /* Close printer port */
+ }
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::: Close printer :::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+VOID host_lpt_close(int adapter)
+{
+ DWORD BytesReturn;
+
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+
+ if (lpt->direct_access)
+ printer_is_being_closed(adapter);
+
+#ifdef MONITOR
+ if (sas_hw_at_no_check(lp16BitPrtId) == adapter){
+ host_print_buffer (adapter);
+ sas_store_no_check(lp16BitPrtId,0xff);
+ }
+#endif
+ /*::::::::::::::::::::::::::::::::::::::::: Is the printer port active */
+
+ if(lpt->active)
+ {
+ /*
+ ** Tim June 92. Flush output buffer to get the last output out.
+ ** If there's an error I think we've got to ignore it.
+ */
+ (void)flushBuffer(adapter);
+
+#ifndef PROD
+ fprintf(trace_file, "Closing printer port (%d)\n",adapter);
+#endif
+
+#ifdef MONITOR
+ if (lpt->direct_access)
+ MonitorEnablePrinterDirectAccess((WORD)adapter, lpt->handle, FALSE);
+#endif
+ CloseHandle(lpt->handle); /* Close printer port */
+ host_free (lpt->kBuffer);
+ lpt->handle = (HANDLE) -1; /* Mark device as closed */
+
+ lpt->active = FALSE; /* Deactive printer port */
+ set_lpt_status(adapter, 0); /* Reset port status */
+
+#ifndef PROD
+ fprintf(trace_file, "Counter expired, closing LPT%d\n", adapter+1);
+#endif
+ }
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::: Return the status of the lpt channel for an adapter :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL ULONG host_lpt_status(int adapter)
+{
+ return(get_lpt_status(adapter));
+}
+
+GLOBAL UCHAR host_read_printer_status_port(int adapter)
+{
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+ UCHAR PrinterStatus;
+ DWORD BytesReturn;
+
+
+ if(!lpt->active)
+ {
+ /*:::::::::::::::::::::::::::: Port inactive, attempt to reopen it */
+
+ if(!host_lpt_open(adapter, TRUE))
+ {
+#ifndef PROD
+ fprintf(trace_file, "file open error %d\n", GetLastError());
+#endif
+ set_lpt_status(adapter, HOST_LPT_BUSY);
+ return(FALSE); /* exit, printer not active !!!! */
+ }
+ }
+ if (lpt->bytesInBuffer)
+ flushBuffer(adapter);
+ if (!DeviceIoControl(lpt->handle,
+ IOCTL_VDM_PAR_READ_STATUS_PORT,
+ NULL, // no input buffer
+ 0,
+ &PrinterStatus,
+ sizeof(PrinterStatus),
+ &BytesReturn,
+ NULL // no overlap
+ )) {
+
+#ifndef PROD
+ fprintf(trace_file,
+ "host_read_printer_status_port failed, error = %ld\n",
+ GetLastError()
+ );
+#endif
+ PrinterStatus = 0;
+ }
+ return(PrinterStatus);
+}
+
+BOOLEAN host_set_lpt_direct_access(int adapter, BOOLEAN direct_access)
+{
+ DWORD BytesReturn;
+
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+
+ host_lpt_close(adapter);
+ host_lpt_open(adapter, direct_access);
+ if (!lpt->active)
+ set_lpt_status(adapter, HOST_LPT_BUSY);
+ return (lpt->active);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::: Print a byte ::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/*
+** Buffer up bytes before they are printed.
+** Strategy:
+** Save each requested byte in the buffer.
+** When the buffer gets full or there's a close request write the
+** buffered stuff out.
+** Don't forget about errors, eg if the write fails. What about a write
+** failure during the close request though? Tough said Tim.
+*/
+/*
+** flushBuffer()
+** Finally write what is in the buffer to the parallel port. It could be a
+** real port or a networked printer.
+** Input parameter is the parallel port adapter number 0=LPT1
+** Return value of TRUE means write was OK.
+*/
+boolean flushBuffer IFN1( int, adapter )
+{
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+ DWORD BytesWritten;
+
+ if (lpt->direct_access) {
+ DeviceIoControl(lpt->handle,
+ IOCTL_VDM_PAR_WRITE_DATA_PORT,
+ lpt->kBuffer,
+ lpt->bytesInBuffer,
+ NULL,
+ 0,
+ &BytesWritten,
+ NULL
+ );
+
+ lpt->bytesInBuffer = 0;
+ return TRUE;
+
+ }
+
+
+ if( !WriteFile( lpt->handle, lpt->kBuffer,
+ lpt->bytesInBuffer, &BytesWritten, NULL )
+ ){
+#ifndef PROD
+ fprintf(trace_file, "lpt write error %d\n", GetLastError());
+#endif
+ lpt->bytesInBuffer = 0;
+ return(FALSE);
+ }else{
+ lpt->bytesInBuffer = 0;
+
+
+ /*
+ * If the print job is being spooled, the spooler can
+ * take a long time to get started, because of the spoolers
+ * low priority. This is especially bad for dos apps in which
+ * idle detection fails or in full screen idle detection is
+ * inactive. To help push the print job thru the system,
+ * idle a bit now.
+ */
+ if (lpt->FileType == FILE_TYPE_PIPE) {
+ Sleep(10);
+ }
+ return( TRUE );
+ }
+
+} /* end of flushBuffer() */
+
+/*
+** Put another byte in to the buffer. If the buffer is full call the
+** flush function.
+** Return value of TRUE means OK, return FALSE means did a flush and
+** it failed.
+*/
+boolean toBuffer IFN2( int, adapter, BYTE, b )
+{
+ HOST_LPT *lpt = &host_lpt[adapter];
+ boolean status = TRUE;
+
+ lpt->kBuffer[lpt->bytesInBuffer++] = b;
+
+ if( lpt->bytesInBuffer >= lpt->flushThreshold ){
+ status = flushBuffer( adapter );
+ }
+ return( status );
+} /* end of toBuffer() */
+
+GLOBAL BOOL host_print_byte(int adapter, byte value)
+{
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+
+ /*:::::::::::::::::::::::::::::::::::::::::::: Is the printer active ? */
+
+ if(!lpt->active)
+ {
+ /*:::::::::::::::::::::::::::: Port inactive, attempt to reopen it */
+
+ if(!host_lpt_open(adapter, FALSE))
+ {
+#ifndef PROD
+ fprintf(trace_file, "file open error %d\n", GetLastError());
+#endif
+ set_lpt_status(adapter, HOST_LPT_BUSY);
+ return(FALSE); /* exit, printer not active !!!! */
+ }
+ }
+#if defined(MONITOR)
+ if (lpt->direct_access) {
+ MonitorPrinterWriteData((WORD)adapter, value);
+ }
+ else
+#endif
+ {
+
+ /*:::::::::::::::::::::::::::::::::::::::::::::::: Send byte to printer */
+
+ if(toBuffer(adapter, (BYTE) value) == FALSE)
+ {
+ set_lpt_status(adapter, HOST_LPT_BUSY);
+ return(FALSE);
+ }
+ }
+
+ /*::::::::::::::::::::::::::: Update idle and activate control variables */
+
+ lpt->inactive_counter = 0; /* Reset inactivity counter */
+ IDLE_comlpt(); /* Tell Idle system there is printer activate */
+
+ return(TRUE);
+}
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: LPT heart beat call ::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+GLOBAL void host_lpt_heart_beat(void)
+{
+ FAST HOST_LPT *lpt = &host_lpt[0];
+ int i;
+
+
+ /*::::::::::: Scan through printer adapters updating auto close counters */
+
+
+ for(i=0; i < NUM_PARALLEL_PORTS; i++, lpt++)
+ {
+
+ /*:::::::::::::::::::::::::::::::::::::::: Check auto close counters */
+
+ if(lpt->active && lpt->inactive_trigger &&
+ ++lpt->inactive_counter == lpt->inactive_trigger)
+ {
+ host_lpt_close(i); /* Close printer port */
+ }
+ }
+}
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::: Flush the printer port ::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+#if 0
+GLOBAL boolean host_print_doc(int adapter)
+{
+ if(host_lpt[adapter].active) host_lpt_close(adapter); /* Close printer port */
+
+ return(TRUE);
+}
+#endif
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::: Reset the printer port ::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL void host_reset_print(int adapter)
+{
+ if(host_lpt[adapter].active)
+ host_lpt_close(adapter); /* Close printer port */
+}
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::: host_print_auto_feed :::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL void host_print_auto_feed(int adapter, BOOL value)
+{
+ UNREFERENCED_FORMAL_PARAMETER(adapter);
+ UNREFERENCED_FORMAL_PARAMETER(value);
+}
+
+#ifdef MONITOR
+
+GLOBAL boolean host_print_buffer(int adapter)
+{
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+ word cb;
+ byte i,ch;
+
+ cb = sas_w_at_no_check(lp16BitPrtCount);
+ if (!cb)
+ return (TRUE);
+
+ /*:::::::::::::::::::::::::::::::::::::::::::: Is the printer active ? */
+
+ if(!lpt->active)
+ {
+ /*:::::::::::::::::::::::::::: Port inactive, attempt to reopen it */
+
+ if(!host_lpt_open(adapter, FALSE))
+ {
+#ifndef PROD
+ fprintf(trace_file, "file open error %d\n", GetLastError());
+#endif
+ set_lpt_status(adapter, HOST_LPT_BUSY);
+ return(FALSE); /* exit, printer not active !!!! */
+ }
+ }
+
+ if (!lpt->direct_access) {
+ /*:::::::::::::::::::::::::::::::::::::::::::::::: Send byte to printer */
+
+ for (i=0; i <cb; i++) {
+ ch = sas_hw_at_no_check(lp16BitPrtBuf+i);
+ if(toBuffer(adapter, ch) == FALSE)
+ {
+ set_lpt_status(adapter, HOST_LPT_BUSY);
+ return(FALSE);
+ }
+ }
+ }
+ else {
+ // we must no have any int 17 printing data waiting when we
+ // we in direct access mode
+ ASSERT(cb == 0);
+ return FALSE;
+ }
+ /*::::::::::::::::::::::::::: Update idle and activate control variables */
+
+ lpt->inactive_counter = 0; /* Reset inactivity counter */
+ IDLE_comlpt(); /* Tell Idle system there is printer activate */
+
+ return(TRUE);
+}
+#endif // MONITOR
+
+GLOBAL void host_lpt_dos_open(int adapter)
+{
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+
+ lpt->dos_opened = TRUE;
+}
+
+GLOBAL void host_lpt_dos_close(int adapter)
+{
+ FAST HOST_LPT *lpt = &host_lpt[adapter];
+
+ if (lpt->active)
+ host_lpt_close(adapter); /* Close printer port */
+ lpt->dos_opened = FALSE;
+}
+
+GLOBAL void host_lpt_flush_initialize()
+{
+ FAST HOST_LPT *lpt;
+ FAST int i;
+
+ for(i=0, lpt = &host_lpt[0]; i < NUM_PARALLEL_PORTS; i++, lpt++)
+ lpt->dos_opened = FALSE;
+
+}
+
+#endif /* PRINTER */
diff --git a/private/mvdm/softpc.new/host/src/nt_mem.c b/private/mvdm/softpc.new/host/src/nt_mem.c
new file mode 100644
index 000000000..73578a04b
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_mem.c
@@ -0,0 +1,1456 @@
+/*[
+ *
+ * Name: nt_mem.c
+ *
+ * Derived From: (original)
+ *
+ * Author: Jerry Sexton
+ *
+ * Created On: 7 December 1994
+ *
+ * Coding Stds: 2.4
+ *
+ * Purpose: This module implements the memory management functions
+ * required for 486 NT.
+ *
+ * Include File: nt_mem.h
+ *
+ * Copyright Insignia Solutions Ltd., 1994. All rights reserved.
+ *
+]*/
+
+#ifdef CPU_40_STYLE
+
+#if defined(DBG)
+#define DEBUG_MEM YES_PLEASE
+//#define DEBUG_MEM_DUMP 1
+#endif
+
+/* Need all of the following to include nt.h and windows.h in the same file. */
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "insignia.h"
+#include "host_def.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "nt_mem.h"
+#include "debug.h"
+#include "sas.h"
+
+/* Make local symbols visible if debugging. */
+#ifdef DEBUG_MEM
+#define LOCAL
+
+GLOBAL VOID DumpAllocationHeaders IFN1();
+
+#endif /* DEBUG_MEM */
+
+/* Macros and typedefs. */
+
+/* Entry in header table describing sections of memory. */
+typedef struct _SECTION_HEADER
+{
+ struct _SECTION_HEADER *prev; /* Previous header in linked list. */
+ IU8 flags; /* Is header valid/allocated? */
+ IU8 *address; /* Address of corresponding section. */
+ IU32 size; /* Size of corresponding section. */
+ struct _SECTION_HEADER *next; /* Next header in linked list. */
+} SECTION_HEADER;
+
+/* Possible values for 'flags' field of SECTION_HEADER structure. */
+#define HDR_VALID_FLAG 0x1 /* Header points to the beginning of a chunk
+ or free section. */
+#define HDR_ALLOC_FLAG 0x2 /* Header points to an allocated chunk. */
+#define HDR_COMMITTED_FLAG 0x4 /* Header points to committed chunk, not moveable */
+#define HDR_REMAP_FLAG 0x8 /* chunk is remapped by "AddVirtualMemory" */
+
+#define HDR_VALID_ALLOC (HDR_VALID_FLAG|HDR_ALLOC_FLAG)
+ /* Header points to a section that is valid
+ and allocated. */
+
+#define SECTION_IS_FREE(ptr) (!((ptr)->flags & HDR_ALLOC_FLAG))
+ /* Is a section's allocated flag set? */
+
+#define SECTION_IS_UNCOMMITTED(ptr) (!((ptr)->flags & HDR_COMMITTED_FLAG))
+ /* Is a section's committed flag set? */
+
+/* Enumerated type to pass to header management functions. */
+typedef enum
+{
+ SECT_ALLOC,
+ SECT_FREE
+} SECT_TYPE;
+
+#define ONE_K (1<<10) /* Speaks for itself. */
+#define ONE_MEG (1<<20) /* Ditto. */
+#define PAGE_SIZE (4 * ONE_K) /* Intel memory page granularity. */
+#define PAGE_MASK (PAGE_SIZE - 1) /* Mask used in rounding to boundary. */
+#define PAGE_SHIFT 12 /* Amount to shift by to get page. */
+
+// The following two defines have been replace with MaxIntelMemorySize and
+//MaxIntelMemorySize/PAGE_SIZE
+//#define MAX_XMS_SIZE (128 * ONE_MEG) /* Maximum memory size. */
+//#define MAX_HEADER_SIZE (MAX_XMS_SIZE / PAGE_SIZE)
+
+#define A20_WRAP_SIZE (0xfff0) /* Size of A20 wrap area beyond 1M. */
+
+/* Convert header table entries to addresses. */
+#define HEADER_TO_ADDRESS(header) \
+ (intelMem + (((header) - headerTable) << PAGE_SHIFT))
+
+/* Convert addresses to header table entries. */
+#define ADDRESS_TO_HEADER(address) \
+ (headerTable + (((address) - intelMem) >> PAGE_SHIFT))
+
+/* Local variables. */
+LOCAL IBOOL memInit = FALSE;
+ /* Is memory system initialised? */
+LOCAL IU8 *intelMem; /* Pointer to intel memory block. */
+LOCAL SECTION_HEADER *headerTable; /* Table of memory section headers. */
+LOCAL IU32 totalFree; /* Total amount of free memory. */
+LOCAL IU32 commitShift; /* Shift to get commitment granularity */
+LOCAL int ZapValue; /* Value to set allocated memory to */
+LOCAL IU32 WOWforceIncrAlloc = 0; /* Force increasing linear address */
+LOCAL SECTION_HEADER *lastAllocPtr = NULL; /* Last chunk allocated. */
+
+/* Prototypes for local functions. */
+LOCAL SECTION_HEADER *addHeaderEntry IPT5(
+ SECTION_HEADER *, prevHeader,
+ SECTION_HEADER *, nextHeader,
+ SECT_TYPE, allocFree,
+ IU8 *, intelAddr,
+ IU32, size);
+LOCAL IBOOL deleteHeaderEntry IPT1(
+ SECTION_HEADER *, header);
+LOCAL void exclusiveHeaderPages IPT5(
+ IHPE, tableAddress,
+ IHPE, prev,
+ IHPE, next,
+ IHP *, allocAddr,
+ IU32 *, allocSize);
+LOCAL void exclusiveChunkPages IPT4(
+ SECTION_HEADER *, chunkHeader,
+ IHP *, allocAddr,
+ IU32 *, allocSize,
+ BOOL, Commit);
+LOCAL void exclusiveAllocPages IPT6(
+ IHPE, address,
+ IU32, size,
+ IHPE, prevAllocLastAddr,
+ IHPE, nextAllocFirstAddr,
+ IHP *, allocAddr,
+ IU32 *, allocSize);
+
+/* Global Functions. */
+
+/*(
+============================== InitIntelMemory =================================
+PURPOSE:
+ This function reserves the entire Intel address space, committing the
+ first 1 meg and leaving the rest to be committed as and when required
+ when new chunks are allocated.
+INPUT:
+ None.
+OUTPUT:
+ Return value - pointer to beginning of intel memory.
+================================================================================
+)*/
+GLOBAL IU8 *InitIntelMemory IFN1(IU32, MaxIntelMemorySize)
+{
+ SYSTEM_INFO SystemInfo; /* Passed to GetSystemInfo API. */
+ DWORD tabSize; /* Max. size of header table in bytes. */
+ IS32 commitGran; /* Commitment granularity. */
+ IU32 temp, /* Used in computing commitShift. */
+ initialCommitSize; /* Size of real mode area to commit. */
+ SECTION_HEADER *entryPtr; /* Header entry for real mode area. */
+
+#ifdef DEBUG_MEM
+ printf("NTVDM:InitIntelMemory(%lx [%dK])\n",
+ MaxIntelMemorySize, MaxIntelMemorySize/ONE_K);
+#endif
+
+ /*
+ * Setup the value to initalise allocated memory with
+ */
+ {
+ char *env;
+
+ if((env = getenv("CPU_INITIALISE_MEMORY")) != 0)
+ ZapValue = strtol(env, 0, 16);
+ else
+ ZapValue = 0xf4; /* HLT instruction */
+
+ }
+
+ /*
+ * Find out machine's commitment granularity, and store it as a number of
+ * bits to shift an address right to give the allocation page it is in.
+ * This assumes the allocation granularity is a power of two so complain
+ * if it isn't.
+ */
+ GetSystemInfo(&SystemInfo);
+ commitGran = (IS32) SystemInfo.dwPageSize;
+ if ((-commitGran & commitGran) != commitGran)
+ {
+ always_trace1("Commitment granularity %#x not a power of two",
+ commitGran);
+ return((IU8 *) NULL);
+ }
+#ifdef DEBUG_MEM
+ printf("NTVDM:Commitment granularity is %lx\n", commitGran);
+#endif
+ commitShift = 0;
+ for (temp = commitGran; temp > 1; temp >>= 1)
+ commitShift++;
+
+ /* Reserve the entire memory space. */
+ intelMem = (IU8 *) VirtualAlloc((LPVOID) NULL,
+ (DWORD) MaxIntelMemorySize,
+ (DWORD) MEM_RESERVE,
+ (DWORD) PAGE_READWRITE);
+ if (!intelMem)
+ {
+ always_trace1("Failed to reserve %dM of memory", MaxIntelMemorySize >> 20);
+ return((IU8 *) NULL);
+ }
+
+ /*
+ * Allocate the bottom 1 megabyte plus the 20-bit wrap area. Round this
+ * to an Intel page boundary as this is the granularity of this system.
+ */
+ initialCommitSize = (ONE_MEG + A20_WRAP_SIZE + PAGE_MASK) &
+ (IU32) ~PAGE_MASK;
+ if (VirtualAlloc((LPVOID) intelMem,
+ (DWORD) initialCommitSize,
+ (DWORD) MEM_COMMIT,
+ (DWORD) PAGE_READWRITE) == NULL)
+ {
+ always_trace0("Could not commit real mode area");
+ VirtualFree (intelMem, 0, MEM_RELEASE); /* Free Intel memory */
+ return((IU8 *) NULL);
+ }
+
+ /* Reserve enough space for the entire header table. */
+ tabSize = (MaxIntelMemorySize/PAGE_SIZE) * sizeof(SECTION_HEADER);
+ headerTable = (SECTION_HEADER *) VirtualAlloc((LPVOID) NULL,
+ tabSize,
+ (DWORD) MEM_RESERVE,
+ (DWORD) PAGE_READWRITE);
+
+ if (!headerTable)
+ {
+ always_trace0("Failed to reserve header table");
+ VirtualFree (intelMem, 0, MEM_RELEASE); /* Free Intel memory */
+ return((IU8 *) NULL);
+ }
+
+ /*
+ * Initialise linked list with pointers to initial 1M and remaining free
+ * space and store initial size of free space.
+ */
+ entryPtr = addHeaderEntry((SECTION_HEADER *) NULL, (SECTION_HEADER *) NULL,
+ SECT_ALLOC, intelMem, initialCommitSize);
+
+ entryPtr->flags |= HDR_COMMITTED_FLAG;
+ totalFree = MaxIntelMemorySize - initialCommitSize;
+
+ (void) addHeaderEntry(entryPtr, (SECTION_HEADER *) NULL, SECT_FREE,
+ intelMem + initialCommitSize, totalFree);
+
+ /* Return the address of the start of memory. */
+ memInit = TRUE;
+ return(intelMem);
+}
+
+/*(
+============================== FreeIntelMemory =================================
+PURPOSE:
+ This function frees the entire Intel address space
+INPUT:
+ None.
+OUTPUT:
+ None.
+================================================================================
+)*/
+
+GLOBAL VOID FreeIntelMemory IFN0()
+{
+#ifdef DEBUG_MEM
+ printf("NTVDM:FreeIntelMemory\n");
+#endif
+
+ /* Free Intel memory */
+ VirtualFree (intelMem, 0, MEM_RELEASE);
+
+ /* Free allocation control structure */
+ VirtualFree (headerTable, 0, MEM_RELEASE);
+}
+
+/*(
+============================ SetWOWforceIncrAlloc ===============================
+PURPOSE:
+ When TRUE is passed, this function sets the WOWforceIncrAlloc variable to
+ the current thread ID. This will force VdmAllocateVirtualMemory to allocate
+ blocks of memory with ever increasing linear address's for this thread only.
+ When FALSE is passed, WOWforceIncrAlloc is cleared and the default
+ allocation scheme is used. This function is called by WOW based on an app
+ compatibility flag at start task time and end task time. Power Builder 4
+ depends on this. This is not a general solution for multiple threads. Since
+ the problem we're trying to work around occurs at load time, the allocation
+ strategy is applied to the most recent thread only. This might not work if
+ multiple instances of the app are started at the same time.
+
+INPUT:
+ None.
+OUTPUT:
+ None.
+================================================================================
+)*/
+
+GLOBAL VOID SetWOWforceIncrAlloc IFN1(IBOOL, iEnable)
+{
+ if (iEnable) {
+ WOWforceIncrAlloc = GetCurrentThreadId();
+ }
+ else {
+ WOWforceIncrAlloc = 0;
+ }
+#ifdef DEBUG_MEM
+ printf("NTVDM:SetWOWforceIncrAlloc, WOWforceIncrAlloc: %X\n", WOWforceIncrAlloc);
+#endif
+}
+
+
+/*(
+========================= VdmAllocateVirtualMemory =============================
+PURPOSE:
+ This interface will allocate the specified number of bytes of virtual
+ memory, returning the Intel linear address in the variable pointed to
+ by the Address parameter. The Intel linear address will be page
+ aligned (this is important). In the event that the memory is
+ allocated, STATUS_SUCCESS will be returned. In the event of failure,
+ an appropriate NTSTATUS code will be returned. (In the event that
+ there is a failure in the cpu for which there is not an appropriate
+ code, STATUS_UNSUCCESSFUL can be returned. I just want to have an
+ opportunity to get more information.)
+INPUT:
+ Size - size of memory chunk required in bytes (must be a
+ multiple of 4K).
+
+ Commit - Commit virtual memory ?
+OUTPUT:
+ Address - INTEL linear address of allocated chunk.
+ Return value - STATUS_SUCCESS, if the memory is allocated, or an
+ appropriate NTSTATUS code if not (if there is no
+ appropriate code STATUS_UNSUCCESSFUL is returned).
+================================================================================
+)*/
+GLOBAL NTSTATUS VdmAllocateVirtualMemory IFN3(PULONG, INTELAddress,
+ ULONG, Size,
+ BOOL, Commit)
+{
+ SECTION_HEADER *headerPtr,
+ *newHeader;
+ IHP retAddr,
+ commitAddr;
+ IU32 commitSize;
+
+#ifdef DEBUG_MEM
+ printf("NTVDM:VdmAllocateVirtualMemory(%lx [%dK],%s)\n",
+ Size, Size/ONE_K, Commit ? "COMMIT" : "DONOT_COMMIT");
+#endif
+
+ /* Make sure memory system is initialised. */
+ assert0(memInit, "Called VdmAllocateVirtualMemory before initialisation");
+
+ /* Round Size up to a multiple of 4K. */
+
+ if (Size & PAGE_MASK)
+ Size = (Size + PAGE_MASK) & (~PAGE_MASK);
+
+
+ /* Search for a chunk of the required size. If WOWforceIncrAlloc is our */
+ /* current thread ID and lastAllocPtr is intialized, force returned */
+ /* chunks to have ever increasing linear address's. */
+ if ((WOWforceIncrAlloc != 0) && lastAllocPtr
+ && (GetCurrentThreadId() == WOWforceIncrAlloc)) {
+#ifdef DEBUG_MEM
+ printf("\nNTVDM:VdmAllocateVirtualMemory, using increasing linear address strategy.\n");
+#endif
+ headerPtr = lastAllocPtr;
+ } else {
+ headerPtr = &headerTable[0];
+ }
+ while (headerPtr != NULL)
+ {
+ if (SECTION_IS_FREE(headerPtr) && (headerPtr->size >= Size))
+ break;
+ headerPtr = headerPtr->next;
+ }
+
+ /* Return failure if there is no chunk of the required size. */
+ if (headerPtr == NULL)
+ return(STATUS_NO_MEMORY);
+
+ /* Mark the header as an allocated chunk */
+ headerPtr->flags |= HDR_ALLOC_FLAG;
+ lastAllocPtr = headerPtr;
+
+ /* Add committed status to header. */
+ if(Commit)
+ headerPtr->flags |= HDR_COMMITTED_FLAG;
+ else
+ headerPtr->flags &= ~HDR_COMMITTED_FLAG;
+
+ /* Create a new header if there is any space left below the new chunk. */
+ if (headerPtr->size > Size)
+ {
+ newHeader = addHeaderEntry(headerPtr,
+ headerPtr->next,
+ SECT_FREE,
+ headerPtr->address + Size,
+ headerPtr->size - Size);
+ headerPtr->size = Size;
+ }
+
+ /* Commit any pages that are unique to this chunk. */
+ exclusiveChunkPages(headerPtr, &commitAddr, &commitSize, TRUE);
+ if (commitSize && Commit)
+ {
+ retAddr = VirtualAlloc((LPVOID) commitAddr,
+ (DWORD) commitSize,
+ (DWORD) MEM_COMMIT,
+ (DWORD) PAGE_READWRITE);
+
+ if (retAddr != commitAddr)
+ {
+ always_trace2("Could not commit %dK at addr %#x",
+ commitSize / ONE_K, commitAddr);
+ return(STATUS_NOT_COMMITTED);
+ }
+ }
+
+ /*
+ * Success, so update total free space store and return the address of
+ * the new chunk to the caller.
+ */
+ totalFree -= Size;
+ *INTELAddress = ((ULONG) (IHPE) headerPtr->address) - (ULONG) intelMem;
+
+#ifdef DEBUG_MEM
+ printf(" => alloc %lxh, commit %lxh\n",
+ ((ULONG) (IHPE)headerPtr->address) - (ULONG)intelMem,
+ ((ULONG) (IHPE)commitAddr) - (ULONG)intelMem);
+
+#ifdef DEBUG_MEM_DUMP
+ DumpAllocationHeaders("after allocate");
+#endif
+#endif
+
+ return(STATUS_SUCCESS);
+}
+
+/*(
+========================== VdmCommitVirtualMemory =============================
+PURPOSE:
+ Commit memory within a previously allocated chunk
+INPUT:
+ Address Intel linear address of memory to commit
+ Size Size of memory to commit
+OUTPUT:
+ Return value - STATUS_SUCCESS, if the memory is allocated, or an
+ appropriate NTSTATUS code if not.
+===============================================================================
+)*/
+
+GLOBAL NTSTATUS VdmCommitVirtualMemory IFN2(ULONG, INTELAddress,
+ ULONG, Size)
+{
+ IHP retAddr;
+
+#ifdef DEBUG_MEM
+ printf("NTVDM:VdmCommitVirtualMemory(%lxh,%lxh)\n",INTELAddress, Size);
+#endif
+
+ retAddr = VirtualAlloc((LPVOID) (intelMem + INTELAddress),
+ (DWORD) Size,
+ (DWORD) MEM_COMMIT,
+ (DWORD) PAGE_READWRITE);
+
+ if(retAddr != (intelMem + INTELAddress))
+ {
+ always_trace2("Could not commit %dK at addr %#x",
+ Size / ONE_K, INTELAddress);
+
+ return(STATUS_NOT_COMMITTED);
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+/*(
+======================== VdmDeCommitVirtualMemory =============================
+PURPOSE:
+ Decommit memory within a previously allocated chunk
+INPUT:
+ Address Intel linear address of memory to decommit
+ Size Size of memory to commit
+OUTPUT:
+ Return value - STATUS_SUCCESS, if the memory is allocated, or an
+ appropriate NTSTATUS code if not.
+===============================================================================
+)*/
+
+GLOBAL NTSTATUS VdmDeCommitVirtualMemory IFN2(ULONG, INTELAddress,
+ ULONG, Size)
+{
+#ifdef DEBUG_MEM
+ printf("NTVDM:VdmDeCommitVirtualMemory(%lxh,%lxh)\n",INTELAddress, Size);
+#endif
+
+
+ sas_overwrite_memory(INTELAddress, Size);
+ if (!VirtualFree((LPVOID) (intelMem + INTELAddress),
+ (DWORD) Size,
+ (DWORD) MEM_DECOMMIT))
+ {
+ always_trace2("Could not decommit %dK at addr %#x",
+ Size / ONE_K, INTELAddress);
+
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+/*(
+============================ VdmFreeVirtualMemory ==============================
+PURPOSE:
+ This interface will free the allocation at the specified Intel linear
+ address. The above notes on return value apply.
+INPUT:
+ INTELAddress - INTEL address to be freed.
+OUTPUT:
+ Return value - STATUS_SUCCESS, if the memory is allocated, or an
+ appropriate NTSTATUS code if not (if there is no
+ appropriate code STATUS_UNSUCCESSFUL is returned).
+================================================================================
+)*/
+GLOBAL NTSTATUS VdmFreeVirtualMemory IFN1(ULONG, INTELAddress)
+{
+ SECTION_HEADER *headerPtr;
+ IU32 size,
+ decommitSize;
+ IHP decommitAddr;
+ ULONG Address;
+
+
+ /* Make sure memory system is initialised. */
+ assert0(memInit, "Called VdmFreeVirtualMemory before initialisation");
+
+#ifdef DEBUG_MEM
+ printf("NTVDM:VdmFreeVirtualMemory(%lxh)\n",INTELAddress);
+#endif
+
+ /* Calculate chunk address */
+ Address = INTELAddress + (ULONG)intelMem;
+
+ /* Get header table entry for address. */
+ headerPtr = ADDRESS_TO_HEADER((IU8 *) Address);
+
+ /*
+ * Check address is correctly aligned and at the top of an allocated
+ * chunk.
+ */
+ if ((Address & PAGE_MASK) ||
+ (headerPtr->flags & HDR_VALID_ALLOC != HDR_VALID_ALLOC))
+ {
+ always_trace0("Tried to free invalid address");
+ return(STATUS_MEMORY_NOT_ALLOCATED);
+ }
+
+ /* Don't allow freeing of bottom 1 Meg. */
+ if (headerPtr == &headerTable[0])
+ {
+ always_trace0("Tried to free real mode area");
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ /* DON'T free if still mapped to another area of host memory by
+ * VdmAddVirtualMemory() - ie the PhysRecStructs are in a munged
+ * state. Free can get called before Remove, and Remove will
+ * unflag it and call here later.
+ */
+ if (headerPtr->flags & HDR_REMAP_FLAG)
+ {
+ always_trace0("Tried to free remapped area");
+ return(STATUS_SUCCESS);
+ }
+
+
+ /* Save the size of the chunk before decommitting it. */
+ size = headerPtr->size;
+
+ /* Tell the CPU that the contents of the memory are no longer valid. */
+ sas_overwrite_memory(INTELAddress, size);
+
+ /* Decommit any memory that is unique to this chunk. */
+ exclusiveChunkPages(headerPtr, &decommitAddr, &decommitSize, FALSE);
+ if (decommitSize)
+ {
+ if (!VirtualFree((LPVOID) decommitAddr,
+ (DWORD) decommitSize,
+ (DWORD) MEM_DECOMMIT))
+ {
+ always_trace2("Could not decommit %dK at addr %#x",
+ decommitSize / ONE_K, decommitAddr);
+ return(STATUS_UNABLE_TO_DECOMMIT_VM);
+ }
+ }
+
+ /*
+ * If chunk is adjacent to a free section absorb this chunk into it.
+ * Start with next chunk so we don't trash current one before we are
+ * finished with it.
+ */
+ if (headerPtr->next && SECTION_IS_FREE(headerPtr->next))
+ {
+ headerPtr->size += headerPtr->next->size;
+ deleteHeaderEntry(headerPtr->next);
+ }
+
+ /* Absorb into previous section if that is free. */
+ if (headerPtr->prev && SECTION_IS_FREE(headerPtr->prev))
+ {
+ headerPtr->prev->size += headerPtr->size;
+ deleteHeaderEntry(headerPtr);
+ }
+ else
+ {
+
+ /* Otherwise just mark this chunk as free. */
+ headerPtr->flags &= (IU32) ~HDR_ALLOC_FLAG;
+ }
+
+ /* Success, so update total free space store and return. */
+ totalFree += size;
+
+
+#ifdef DEBUG_MEM
+#ifdef DEBUG_MEM_DUMP
+ DumpAllocationHeaders("after free");
+#endif
+#endif
+
+ return(STATUS_SUCCESS);
+}
+
+/*(
+========================== VdmQueryFreeVirtualMemory ===========================
+PURPOSE:
+ This interface returns information about free memory. The total number
+ of allocatable free bytes is returned in the variable pointed to by
+ FreeBytes. LargestFreeBlock returns the size of the largest contiguous
+ block that can be allocated at the present time. This value is
+ potentially all of the available virtual memory. It may change over
+ time due to other activities in the system. The above notes on return
+ value apply.
+INPUT:
+ None.
+OUTPUT:
+ FreeBytes - the total number of allocatable free bytes.
+ LargestFreeBlock - the size of the largest contiguous block that can
+ be allocated at the present time.
+ Return value - STATUS_SUCCESS, if the memory is allocated, or an
+ appropriate NTSTATUS code if not (if there is no
+ appropriate code STATUS_UNSUCCESSFUL is returned).
+================================================================================
+)*/
+GLOBAL NTSTATUS VdmQueryFreeVirtualMemory IFN2(PULONG, FreeBytes,
+ PULONG, LargestFreeBlock)
+{
+ IU32 maxFree = 0; /* Local storage for maximum. */
+ SECTION_HEADER *headerPtr; /* Pointer for searching through linked list. */
+
+ /* Make sure memory system is initialised. */
+ assert0(memInit, "Called VdmQueryFreeVirtualMemory before initialisation");
+
+ /*
+ * Use a linear search through the linked list to find the largest
+ * contiguous free space. (This information could be updated as chunks are
+ * allocated and freed but do it this way for now.)
+ */
+
+ for(headerPtr = &headerTable[0] ;
+ headerPtr != NULL ;
+ headerPtr = headerPtr->next)
+ {
+ if (SECTION_IS_FREE(headerPtr) && (headerPtr->size > maxFree))
+ maxFree = headerPtr->size;
+ }
+
+ *FreeBytes = (ULONG) totalFree;
+ *LargestFreeBlock = (ULONG) maxFree;
+
+#ifdef DEBUG_MEM
+ printf("NTVDM:VdmQueryFreeVirtualMemory() Total %lx [%dK], Largest %lx[%dK]\n",
+ *FreeBytes, *FreeBytes/ONE_K, *LargestFreeBlock, *LargestFreeBlock/ONE_K);
+#endif
+
+ return(STATUS_SUCCESS);
+}
+
+/*(
+========================== VdmReallocateVirtualMemory ==========================
+PURPOSE:
+ This interface will reallocate the block of memory at the specified
+ Intel linear address. The size of the new block is specified by
+ NewSize. The new address is returned in the variable pointed to by
+ NewAddress. The new address must be page aligned (this is important).
+ If the new size is smaller than the old size, the new address must be
+ the same as the old address (this is also important). The original
+ data from the reallocated memory must be preserved to
+ min(old size, new size). The state of any data beyond NewSize is
+ indeterminate.
+INPUT:
+ INTELOriginalAddress - INTEL address of the chunk to be reallocated.
+ NewSize - size in bytes the chunk needs to be changed to.
+OUTPUT:
+ INTELNewAddress - new INTEL address of the chunk.
+================================================================================
+)*/
+GLOBAL NTSTATUS VdmReallocateVirtualMemory IFN3(ULONG, INTELOriginalAddress,
+ PULONG, INTELNewAddress,
+ ULONG, NewSize)
+{
+ SECTION_HEADER *headerPtr;
+ IBOOL nextSectIsFree;
+ IU32 oldSize,
+ maxSize;
+ ULONG newAddr;
+ NTSTATUS status;
+ ULONG OriginalAddress;
+
+
+#ifdef DEBUG_MEM
+ printf("NTVDM:VdmReallocateVirtualMemory(%lx [%dK] at %lx)\n",
+ NewSize, NewSize/ONE_K, INTELOriginalAddress);
+#endif
+
+ /* Round NewSize up to a multiple of 4K. */
+ if (NewSize & PAGE_MASK)
+ NewSize = (NewSize + PAGE_MASK) & (~PAGE_MASK);
+
+ /* Calculate chunk address */
+ OriginalAddress = INTELOriginalAddress + (ULONG)intelMem;
+
+ /* Make sure memory system is initialised. */
+ assert0(memInit, "Called VdmReallocateVirtualMemory before initialisation");
+
+ /* Get header table entry for address. */
+ headerPtr = ADDRESS_TO_HEADER((IU8 *) OriginalAddress);
+
+
+ /* Unable to reallocate sparsely commit chunk */
+ if(!(headerPtr->flags & HDR_COMMITTED_FLAG))
+ {
+ always_trace0("Tried to reallocate sparsely committed chunk");
+ return(STATUS_MEMORY_NOT_ALLOCATED);
+ }
+
+
+ /*
+ * Check address is correctly aligned and at the top of an allocated
+ * chunk.
+ */
+ if ((OriginalAddress & PAGE_MASK) ||
+ (headerPtr->flags & HDR_VALID_ALLOC != HDR_VALID_ALLOC))
+ {
+ always_trace0("Tried to reallocate invalid address");
+ return(STATUS_MEMORY_NOT_ALLOCATED);
+ }
+
+ /* If size is the same there is nothing to do. */
+ if (NewSize == headerPtr->size)
+ {
+ always_trace0("New size equals old size in VdmReallocateVirtualMemory");
+ *INTELNewAddress = INTELOriginalAddress;
+ return(STATUS_SUCCESS);
+ }
+
+ /* Don't allow reallocation of bottom 1 Meg. */
+ if (headerPtr == &headerTable[0])
+ {
+ always_trace0("Tried to reallocate real mode area");
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ /* ... or if still mapped to another area of host memory by
+ * VdmAddVirtualMemory() - ouch!
+ */
+ if (headerPtr->flags & HDR_REMAP_FLAG)
+ {
+ always_trace0("Tried to reallocate remapped area");
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ /* Save old size for later. */
+ oldSize = headerPtr->size;
+
+ /* Work out whether the chunk needs to be moved. */
+ maxSize = headerPtr->size;
+ if (headerPtr->next && SECTION_IS_FREE(headerPtr->next))
+ {
+ maxSize += headerPtr->next->size;
+ nextSectIsFree = TRUE;
+ }
+ else
+ {
+ nextSectIsFree = FALSE;
+ }
+ if (NewSize > maxSize)
+ {
+
+ /* Chunk must move, so allocate a new one. */
+ status = VdmAllocateVirtualMemory(&newAddr, NewSize, TRUE);
+ if (status != STATUS_SUCCESS)
+ return(status);
+
+ /* Copy old chunk. */
+ memcpy((void *) (newAddr + intelMem), (void *) OriginalAddress,
+ (size_t) oldSize);
+
+ /* Free old chunk. */
+ sas_overwrite_memory(INTELOriginalAddress, oldSize);
+ status = VdmFreeVirtualMemory(INTELOriginalAddress);
+ if (status != STATUS_SUCCESS)
+ return(status);
+
+ /* Inform caller of new address. */
+ *INTELNewAddress = newAddr;
+ }
+ else
+ {
+ IHP commitAddr;
+ IU32 commitSize;
+
+ /* Adjust size of current chunk. */
+ headerPtr->size = NewSize;
+
+ /* Remove old pointer to free space if there is one. */
+ if (nextSectIsFree)
+ deleteHeaderEntry(headerPtr->next);
+
+ /* Add new pointer to free space if one is required. */
+ if (NewSize < maxSize)
+ {
+ (void) addHeaderEntry(headerPtr,
+ headerPtr->next,
+ SECT_FREE,
+ (IU8 *) (OriginalAddress + NewSize),
+ maxSize - NewSize);
+ }
+
+ /* If this chunk is committed, commit the memory now covered by it */
+ /* in case its size has increased, or decommit the freed up memory */
+ if (headerPtr->flags & HDR_COMMITTED_FLAG)
+ {
+ if (oldSize < NewSize) {
+ exclusiveChunkPages(headerPtr, &commitAddr, &commitSize, TRUE);
+ if (commitSize)
+ (void) VirtualAlloc((LPVOID) commitAddr,
+ (DWORD) commitSize,
+ (DWORD) MEM_COMMIT,
+ (DWORD) PAGE_READWRITE);
+ } else {
+ /* Chunk has shrunk, so free up excess */
+ exclusiveChunkPages(headerPtr->next, &commitAddr, &commitSize, FALSE);
+ if (commitSize)
+ (void) VirtualFree((LPVOID) commitAddr,
+ (DWORD) commitSize,
+ (DWORD) MEM_DECOMMIT);
+ }
+ }
+
+ /* Inform caller address has not changed. */
+ *INTELNewAddress = OriginalAddress - (ULONG)intelMem;
+
+ /* Update total free space store. */
+ totalFree += NewSize - oldSize;
+ }
+
+#ifdef DEBUG_MEM
+ printf("to %lx\n", *INTELNewAddress);
+#ifdef DEBUG_MEM_DUMP
+ DumpAllocationHeaders("after realloc");
+#endif
+#endif
+ /* Success. */
+ return(STATUS_SUCCESS);
+}
+
+/*(
+============================ VdmAddVirtualMemory ===============================
+PURPOSE:
+ In investigating the things we need to support with the 386, I've come
+ across an interesting one called dib.drv. Support for this involves calling
+ CreateDibSection, which returns a pointer to a DIB. The applications then
+ edit the bits in the dib directly, as well as operating on it using GDI
+ calls. At least that's my understanding. In view of this, and the potential
+ for people to create other api with similar properties, it appears that we
+ need to be able to notify the cpu that a particular region of memory needs
+ to be added to the intel address space.
+
+ This interface adds virtual memory allocated by the system to the intel
+ address space. The host linear address of the block to be added is
+ specified by HostAddress. The pages at this address have already been
+ allocated and initialized. The CPU should not modify the contents of these
+ pages, except as part of executing emulated code. The Intel linear address
+ may be specified by IntelAddress. If IntelAddress is non-NULL, it specifies
+ the Intel address that the memory should be added at. If IntelAddress is
+ NULL, the CPU may select the Intel address the memory is at. In all events,
+ upon return from VdmAddVirtualMemory, IntelAddress will contain the Intel
+ address of the block of memory. If the function cannot be performed, and
+ appropriate NTSTATUS code should be returned.
+
+ / The ability to specify Intel Address may be unecessary. I included it for
+ completeness /
+INPUT:
+ HostAddress - the host linear address of the block to be added.
+ Size - the size of the block in bytes.
+OUTPUT:
+ IntelAddress - the intel address the block is mapped to.
+================================================================================
+)*/
+GLOBAL NTSTATUS VdmAddVirtualMemory IFN3(ULONG, HostAddress,
+ ULONG, Size,
+ PULONG, IntelAddress)
+{
+ IU32 alignfix;
+
+#ifdef DEBUG_MEM
+ printf("NTVDM:VdmAddVirtualMemory (%lx [%dK]) at %lx)\n",
+ Size, Size/ONE_K, HostAddress);
+#endif
+
+ /* Make sure memory system is initialised. */
+ assert0(memInit, "Called VdmAddVirtualMemory before initialisation");
+
+ /* Calculate shift required to DWORD align HostAddress */
+ if ((alignfix = HostAddress & 0x3) != 0) {
+ Size += alignfix;
+ HostAddress -= alignfix;
+ }
+
+ /* Round Size up to a multiple of 4K. */
+
+ if (Size & PAGE_MASK)
+ Size = (Size + PAGE_MASK) & (~PAGE_MASK);
+
+ /* step 1 - reserve the intel address space */
+
+ if (VdmAllocateVirtualMemory(IntelAddress,Size,FALSE) != STATUS_SUCCESS)
+ return (STATUS_NO_MEMORY);
+
+ /* step 2 - flush the caches */
+
+ sas_overwrite_memory(*IntelAddress, Size);
+
+ /* step 3 - replace the PhysicalPageREC.translation entries */
+
+ VdmSetPhysRecStructs(HostAddress, *IntelAddress, Size);
+ ADDRESS_TO_HEADER(*IntelAddress+intelMem)->flags |= HDR_REMAP_FLAG;
+
+ /* adjust IntelAddress if HostAddress not DWORD aligned */
+
+ *IntelAddress += alignfix;
+
+#ifdef DEBUG_MEM
+#ifdef DEBUG_MEM_DUMP
+ DumpAllocationHeaders("after Add");
+#endif
+ printf("NTVDM:VdmAddVirtualMemory => *IntelAddress=%lx\n", *IntelAddress);
+#endif
+
+ return(STATUS_SUCCESS);
+}
+
+/*(
+========================== VdmRemoveVirtualMemory ==============================
+PURPOSE:
+ This interface undoes an address mapping that was performed using
+ VdmAddVirtualMemory.
+INPUT:
+ IntelAddress - address of block to be removed.
+================================================================================
+)*/
+GLOBAL NTSTATUS VdmRemoveVirtualMemory IFN1(ULONG, IntelAddress)
+{
+ SECTION_HEADER * headerPtr;
+ ULONG HostAddress,Size;
+ NTSTATUS status;
+
+#ifdef DEBUG_MEM
+ printf("NTVDM:VdmRemoveVirtualMemory at %lx)\n", IntelAddress);
+#ifdef DEBUG_MEM_DUMP
+ DumpAllocationHeaders("before remove");
+#endif
+#endif
+
+ /* Make sure memory system is initialised. */
+ assert0(memInit, "Called VdmRemoveVirtualMemory before initialisation");
+
+ /* Make sure IntelAddress is page aligned */
+ IntelAddress &= ~PAGE_MASK;
+
+ HostAddress = IntelAddress + (ULONG)intelMem;
+
+ /* Get header table entry for address. */
+ headerPtr = ADDRESS_TO_HEADER((IU8 *) HostAddress);
+
+ Size = headerPtr->size;
+
+ /* step 1 - flush the caches */
+
+ sas_overwrite_memory(IntelAddress, Size);
+
+ /* step 2 - reset the PhysicalPageREC.translation entries */
+
+#ifdef DEBUG_MEM
+ if (Size==0) {
+ printf("NTVDM:VdmRemoveVirtualMemory WARNING, Size==0\n");
+ }
+#endif
+ VdmSetPhysRecStructs(HostAddress, IntelAddress, Size);
+ ADDRESS_TO_HEADER(IntelAddress+intelMem)->flags &= ~HDR_REMAP_FLAG;
+
+ /* step 3 - free the reserved intel address space */
+
+#ifdef DEBUG_MEM
+#ifdef DEBUG_MEM_DUMP
+ DumpAllocationHeaders("after remove (now calling free)");
+#endif
+#endif
+ return VdmFreeVirtualMemory(IntelAddress);
+}
+
+/* Local Functions. */
+
+/*
+=============================== addHeaderEntry =================================
+PURPOSE:
+ Add an entry in the header table, corresponding to 'intelAddr'. The
+ entry will sit between 'prevHeader' and 'nextHeader' in the linked
+ list. If 'prevHeader' is NULL, the new entry will be the first in the
+ list. If 'nextHeader' is NULL, the new entry will be the last in the
+ list. The 'allocFree' parameter states whether the section is to be
+ marked as allocated or free. The 'size' parameter gives the new
+ section's size. Returns a pointer to the new header on success, NULL
+ on failure.
+INPUT:
+ prevHeader - previous header in linked list - may be NULL if the new
+ header is to be the first in the list.
+ nextHeader - next header in linked list - may be NULL if the new
+ header is to be the last in the list.
+ allocFree - is the new header to be marked as allocated or free?
+ intelAddr - address of the new entry.
+ size - size of the new section in bytes.
+OUTPUT:
+ return val - pointer to new section or NULL if there is a problem.
+================================================================================
+ */
+LOCAL SECTION_HEADER *addHeaderEntry IFN5(SECTION_HEADER *, prevHeader,
+ SECTION_HEADER *, nextHeader,
+ SECT_TYPE, allocFree,
+ IU8 *, intelAddr,
+ IU32, size)
+{
+ SECTION_HEADER *newHeader = ADDRESS_TO_HEADER(intelAddr);
+ /* New header table entry. */
+ IHP retAddr,
+ commitAddr;
+ IU32 commitSize;
+
+#ifndef PROD
+ if (prevHeader)
+ assert0(newHeader > prevHeader, "prevHeader invalid");
+ if (nextHeader)
+ assert0(newHeader < nextHeader, "nextHeader invalid");
+#endif /* !PROD */
+
+ /* Commit and zero table header entries if necessary. */
+ exclusiveHeaderPages((IHPE) newHeader, (IHPE) prevHeader,
+ (IHPE) nextHeader, &commitAddr, &commitSize);
+ if (commitSize)
+ {
+ retAddr = VirtualAlloc((LPVOID) commitAddr,
+ (DWORD) commitSize,
+ (DWORD) MEM_COMMIT,
+ (DWORD) PAGE_READWRITE);
+
+ if(retAddr != commitAddr)
+ {
+ printf("V.Allocate failed (%xh) [%lxh :%xh]\n",GetLastError(),commitAddr,commitSize);
+ }
+
+
+ if (retAddr == commitAddr)
+ memset((void *) commitAddr, ZapValue, (size_t) commitSize);
+ else
+ return((SECTION_HEADER *) NULL);
+ }
+
+ /* Fill in header's fields. */
+ newHeader->flags = HDR_VALID_FLAG;
+ if (allocFree == SECT_ALLOC)
+ newHeader->flags |= HDR_ALLOC_FLAG;
+ newHeader->address = intelAddr;
+ newHeader->size = size;
+
+ /* Add it to linked list. */
+ if (prevHeader)
+ prevHeader->next = newHeader;
+ if (nextHeader)
+ nextHeader->prev = newHeader;
+ newHeader->prev = prevHeader;
+ newHeader->next = nextHeader;
+
+ /* Success. */
+ return(newHeader);
+}
+
+/*
+=========================== deleteHeaderEntry ==================================
+PURPOSE:
+ Delete an entry in the header table and remove it from the linked list.
+ If this entry is in an allocation page on its own, decommit the whole
+ page, otherwise zero the entry. Return TRUE on success, FALSE on
+ failure.
+INPUT:
+ header - pointer to entry to be removed.
+OUTPUT:
+ return val - TRUE on success, FALSE on failure.
+================================================================================
+ */
+LOCAL IBOOL deleteHeaderEntry IFN1(SECTION_HEADER *, header)
+{
+ IHP decommitAddr;
+ IU32 decommitSize;
+
+ /* If trying to delete the last allocated chunk, invalidate lastAllocPtr. */
+ if (header == lastAllocPtr) {
+ lastAllocPtr = NULL;
+ }
+
+ /* Find out which pages can be decommitted after this header is freed. */
+ exclusiveHeaderPages((IHPE) header, (IHPE) header->prev,
+ (IHPE) header->next, &decommitAddr, &decommitSize);
+
+ /* Remove header from linked list. */
+ if (header->prev)
+ header->prev->next = header->next;
+ if (header->next)
+ header->next->prev = header->prev;
+
+ if (decommitSize)
+ {
+
+ /* Decommit any allocation pages exclusively covered by 'header'. */
+ if (!VirtualFree((LPVOID) decommitAddr,
+ (DWORD) decommitSize,
+ (DWORD) MEM_DECOMMIT))
+ {
+ always_trace2("Could not decommit %dK at addr %#x",
+ decommitSize / ONE_K, decommitAddr);
+ return(FALSE);
+ }
+ }
+ else
+ {
+
+ /* Zero header's fields. */
+ header->prev = (SECTION_HEADER *) NULL;
+ header->flags = 0;
+ header->address = 0;
+ header->size = 0;
+ header->next = (SECTION_HEADER *) NULL;
+ }
+}
+
+/*
+========================== exclusiveHeaderPages ================================
+PURPOSE:
+ Find the allocation pages EXCLUSIVELY covered by the table entry
+ pointed to by 'header'. The previous and next headers in the table
+ are pointed to by 'prev' and 'next', which may be NULL if there is
+ no corresponding table entry. The address of the first page exclusive
+ to the entry is returned in 'allocAddr', the size in bytes of exclusive
+ pages is returned in 'allocSize'. If 'allocSize' is zero 'allocAddr'
+ is undefined.
+INPUT:
+ tableAddress - address of table entry about to be used or removed.
+ prevAddress - address of previous entry in list.
+ nextAddress - address of next entry in list.
+OUTPUT:
+ allocAddr - pointer to first byte that needs to be
+ committed/decommitted (undefined if allocSize is 0).
+ allocSize - size in bytes that needs to be committed/decommitted.
+================================================================================
+ */
+LOCAL void exclusiveHeaderPages IFN5(IHPE, tableAddress,
+ IHPE, prevAddress,
+ IHPE, nextAddress,
+ IHP *, allocAddr,
+ IU32 *, allocSize)
+{
+ IHPE prevHeaderLastAddr,
+ nextHeaderFirstAddr;
+
+ /*
+ * Find out which allocation pages are exclusively covered by the table
+ * entry pointed to by 'header'.
+ */
+ if (prevAddress)
+ prevHeaderLastAddr = prevAddress + sizeof(SECTION_HEADER) - 1;
+ else
+ prevHeaderLastAddr = (IHPE) 0;
+ nextHeaderFirstAddr = nextAddress;
+ exclusiveAllocPages(tableAddress,
+ (IU32) sizeof(SECTION_HEADER),
+ prevHeaderLastAddr,
+ nextHeaderFirstAddr,
+ allocAddr,
+ allocSize);
+}
+
+/*
+=========================== exclusiveChunkPages ================================
+PURPOSE:
+ Return any allocation pages EXCLUSIVELY covered by the section of
+ memory pointed to by 'chunkHeader'. The 'allocAddr' parameter points
+ at the variable in which to store the address the first allocation
+ page so covered. The 'allocSize' parameter points at the variable in
+ which to store the size in bytes of these these pages. This routine
+ calls 'exclusiveAllocPages' which returns zero in 'allocSize' if there
+ are no exclusive pages, 'allocAddr' being undefined. The same is
+ therefore true of this routine.
+ If we are committing, we must commit any (potentially) uncommitted
+ pages. If uncommitting, we must not uncommit any pages that are alloced,
+ as they may be committed also.
+INPUT:
+ chunkHeader - The header table entry pointing at the section of memory
+ that may need committing/decommitting.
+OUTPUT:
+ allocAddr - pointer to first byte that needs to be
+ committed/decommitted (undefined if allocSize is 0).
+ allocSize - size in bytes that needs to be committed/decommitted.
+ Commit - are we going to commit (true) or decommit this header.
+================================================================================
+ */
+LOCAL void exclusiveChunkPages IFN4(SECTION_HEADER *, chunkHeader,
+ IHP *, allocAddr,
+ IU32 *, allocSize,
+ BOOL, Commit)
+{
+ IHPE prevChunkLastAddr, /* Last page previous chunk touches. */
+ nextChunkFirstAddr; /* First page next chunk touches. */
+ SECTION_HEADER *prevHeader, /* Pointer to previous allocated chunk. */
+ *nextHeader; /* Pointer to next allocated chunk. */
+
+ /* Find previous allocated chunk. */
+ prevHeader = chunkHeader->prev;
+ while ((prevHeader != NULL) &&
+ (Commit?SECTION_IS_UNCOMMITTED(prevHeader):SECTION_IS_FREE(prevHeader)))
+ prevHeader = prevHeader->prev;
+
+ /* Work out end address of previous chunk. */
+ if (prevHeader)
+ prevChunkLastAddr = (IHPE) prevHeader->address + prevHeader->size - 1;
+ else
+ prevChunkLastAddr = (IHPE) 0;
+
+ /* Find next allocated chunk. */
+ nextHeader = chunkHeader->next;
+ while ((nextHeader != NULL) &&
+ (Commit?SECTION_IS_UNCOMMITTED(nextHeader):SECTION_IS_FREE(nextHeader)))
+ nextHeader = nextHeader->next;
+
+ /* Work out start address of next chunk. */
+ if (nextHeader)
+ nextChunkFirstAddr = (IHPE) nextHeader->address;
+ else
+ nextChunkFirstAddr = (IHPE) 0;
+
+ /*
+ * Find the address range of pages that need to be committed and pass them
+ * straight up to the caller.
+ */
+ exclusiveAllocPages((IHPE) chunkHeader->address,
+ chunkHeader->size,
+ prevChunkLastAddr,
+ nextChunkFirstAddr,
+ allocAddr,
+ allocSize);
+#ifdef DEBUG_MEM
+ printf("NTVDM:Exclusive range to %s %lx+%lx is %lx+%lx\n",
+ Commit ? "COMMIT" : "DECOMMIT", chunkHeader->address,chunkHeader->size,
+ *allocAddr, *allocSize);
+#endif
+}
+
+/*
+============================= exclusiveAllocPages ==============================
+PURPOSE:
+ For a given memory range, find out which allocation pages need to be
+ committed in order for memory accesses to be allowed across the entire
+ range. To do this we need to know the address and size of the memory
+ range. These are passed in 'address' and 'size'. We also need to know
+ the addresses of the previous and next allocated memory ranges to find
+ out which allocation pages are already committed. This information is
+ passed to the function in 'prevAllocLastAddr' and 'nextAllocFirstAddr'.
+ If there is no previous or next chunk, 'prevAllocLastAddr' or
+ 'nextAllocFirstAddr' is zero. The address and size that need to be
+ committed are returned in 'commitAddr' and 'commitSize'. Note that if
+ 'commitSize' is zero, no memory needs to be committed and 'commitAddr'
+ is undefined.
+INPUT:
+ address - address of object being checked.
+ size - size of object being checked.
+ prevAllocLastAddr - address of last byte of previous allocated
+ object (or zero if there is none).
+ nextAllocFirstAddr - address of first byte of next allocated object
+ (or zero if there is none).
+OUTPUT:
+ allocAddr - pointer to first byte that needs to be
+ committed/decommitted (undefined if allocSize
+ is 0).
+ allocSize - size in bytes that needs to be
+ committed/decommitted.
+================================================================================
+ */
+LOCAL void exclusiveAllocPages IFN6(IHPE, address,
+ IU32, size,
+ IHPE, prevAllocLastAddr,
+ IHPE, nextAllocFirstAddr,
+ IHP *, allocAddr,
+ IU32 *, allocSize)
+{
+ IU32 prevAllocLastPage, /* Last page previous chunk touches. */
+ currentAllocFirstPage, /* First page current chunk touches. */
+ currentAllocLastPage, /* Last page current chunk touches. */
+ nextAllocFirstPage, /* First page next chunk touches. */
+ firstPage, /* First page that needs committing. */
+ lastPage; /* Last page that needs committing. */
+
+#ifndef PROD
+
+ /* Check for sensible parameters. */
+ if (prevAllocLastAddr)
+ assert0(address > prevAllocLastAddr, "address out of range");
+ if (nextAllocFirstAddr)
+ assert0(address < nextAllocFirstAddr, "address out of range");
+#endif /* !PROD */
+
+ /*
+ * Work out first and last pages of new memory block that need to be
+ * committed.
+ */
+ currentAllocFirstPage = address >> commitShift;
+ currentAllocLastPage = (address + size - 1) >> commitShift;
+ firstPage = currentAllocFirstPage;
+
+/* Fix horrid nano lookahead bug, but leaves memory leak ?
+ * Also insufficient anyway in general case
+ */
+#ifdef PIG
+ lastPage = currentAllocLastPage+1;
+#else
+ lastPage = currentAllocLastPage;
+#endif
+
+ /*
+ * Now check to see if first or last pages of this allocation are already
+ * committed by adjacent allocations.
+ */
+ if (prevAllocLastAddr)
+ {
+
+ /* See if first page of current allocation is already committed. */
+ prevAllocLastPage = prevAllocLastAddr >> commitShift;
+ if (prevAllocLastPage == currentAllocFirstPage)
+ firstPage++;
+ }
+ if (nextAllocFirstAddr)
+ {
+
+ /* See if last page of current chunk is already committed. */
+ nextAllocFirstPage = nextAllocFirstAddr >> commitShift;
+ if (nextAllocFirstPage == currentAllocLastPage)
+ lastPage--;
+ }
+
+ /*
+ * If first page is less than or equal to last page we have some pages to
+ * allocate. Return the addrees and size to caller (zero size if nothing
+ * do.
+ */
+ if (firstPage <= lastPage)
+ {
+ *allocAddr = (void *) (firstPage << commitShift);
+ *allocSize = (lastPage - firstPage + 1) << commitShift;
+ }
+ else
+ *allocSize = 0;
+}
+
+
+#ifdef DEBUG_MEM
+
+
+/*
+=========================== Dump Header Linked List ===========================
+PURPOSE:
+ Dump the headers linked list controlling allocated blocks
+
+
+INPUT: None
+OUTPUT: Via printf
+
+================================================================================
+*/
+
+GLOBAL VOID DumpAllocationHeaders IFN1(char*, where)
+{
+
+ SECTION_HEADER *headerPtr; /* Pointer for searching through linked list. */
+
+ /* Dump headers */
+ printf("NTVDM: Dump Allocation Headers %s\n", where);
+ printf("ptr address status size (k) commit\n");
+
+ for(headerPtr = &headerTable[0] ;
+ headerPtr != NULL ;
+ headerPtr = headerPtr->next)
+ {
+ printf("%08lxh: %08lxh [%s] %08lxh (%05dK)%s%s\n",
+ headerPtr,
+ headerPtr->address - intelMem,
+ SECTION_IS_FREE(headerPtr) ? "FREE" : "USED",
+ headerPtr->size, headerPtr->size / ONE_K,
+ headerPtr->flags & HDR_COMMITTED_FLAG ? " COMMITTED" : "",
+ headerPtr->flags & HDR_REMAP_FLAG ? " REMAPPED" : "");
+ }
+
+ printf("\n");
+}
+
+
+#endif DEBUG_MEM
+
+
+#endif /* CPU_40_STYLE */
diff --git a/private/mvdm/softpc.new/host/src/nt_mess.c b/private/mvdm/softpc.new/host/src/nt_mess.c
new file mode 100644
index 000000000..40fa77b30
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_mess.c
@@ -0,0 +1,27 @@
+#include "host_def.h"
+/*
+ *
+ * Title : Win32 specific error messages
+ *
+ * Description : Text of Win32 specific error messages.
+ *
+ * Author : M.McCusker
+ *
+ * Notes : Add new error message to array. Message should
+ * not be longer than 100 characters.
+ *
+ * These messages should have an entry in hs_error.h
+ * and are offset by 1000
+ *
+ * Mods: (r2.3) : Modified the text of the comms error messages.
+ */
+
+/* For Internationalization purposes it my be a good idea to move these
+ message to the resource file. (Dave Bartlett) */
+
+char *hs_err_message[] = {
+/* 0 1 2 3 4 5 6 7 8 9 * */
+/* 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 */
+/* FUNC_FAILED */ "Function failed",
+/* EHS_SYSTEM_ERROR */ "NTVDM has encountered a System Error",
+};
diff --git a/private/mvdm/softpc.new/host/src/nt_mouse.c b/private/mvdm/softpc.new/host/src/nt_mouse.c
new file mode 100644
index 000000000..2fbb3a9c8
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_mouse.c
@@ -0,0 +1,2630 @@
+#include "windows.h"
+#include "insignia.h"
+#include "host_def.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include "conapi.h"
+#include "xt.h"
+#include CpuH
+#include "egacpu.h"
+#include "trace.h"
+#include "debug.h"
+#include "gvi.h"
+#include "error.h"
+#include "config.h"
+#include "bios.h"
+#include "mouse_io.h"
+#include "video.h"
+#include "nt_graph.h"
+#include "host_nls.h"
+#include "sas.h"
+#include "ica.h"
+#include "idetect.h"
+#include "host_rrr.h"
+#include "nt_mouse.h"
+#include "ntcheese.h"
+#include "nt_uis.h"
+#include "nt_reset.h"
+#include "nt_eoi.h"
+#include "nt_event.h"
+#include <ntddvdeo.h>
+#include "nt_fulsc.h"
+
+
+#define TEXT_MODE 1
+#define GRAPHICS_MODE 2
+#define NOTHING 0xff
+#define NOT_INSTALLED 0
+#define INSTALLED 1
+
+#define get_pix_height() (get_pc_pix_height() * get_host_pix_height())
+
+
+GLOBAL BOOL pointer_emulation_status = POINTER_EMULATION_OS;
+GLOBAL word VirtualX,VirtualY;
+GLOBAL BOOL bPointerOff=FALSE;
+GLOBAL MOUSE_STATUS os_pointer_data;
+
+IMPORT word DRAW_FS_POINTER_SEGMENT, DRAW_FS_POINTER_OFFSET;
+IMPORT word POINTER_OFF_SEGMENT, POINTER_OFF_OFFSET;
+IMPORT word POINTER_ON_SEGMENT, POINTER_ON_OFFSET;
+IMPORT word CP_X_S, CP_X_O, CP_Y_S, CP_Y_O;
+IMPORT sys_addr conditional_off_sysaddr;
+
+IMPORT word F9_SEGMENT,F9_OFFSET;
+IMPORT word savedtextoffset,savedtextsegment;
+
+#ifdef X86GFX
+IMPORT sys_addr mouseCFsysaddr; // sas address of internal cursor flag
+IMPORT word button_off,button_seg;
+IMPORT boolean mouse_io_interrupt_busy;
+
+#define cursor_in_black_hole(cpx, cpy) \
+ (cpx >= black_hole.top_left.x && \
+ cpx <= black_hole.bottom_right.x && \
+ cpy >= black_hole.top_left.y && \
+ cpy <= black_hole.bottom_right.y)
+
+#endif //X86GFX
+
+
+LOCAL BOOL mouse_state;
+LOCAL BOOL bFullscTextBkgrndSaved = FALSE;
+LOCAL BOOL bPointerInSamePlace = FALSE;
+LOCAL word text_ptr_bkgrnd=0; // safe place for screen background
+LOCAL sys_addr old_text_addr;
+RECT WarpBorderRect; // in screen coordinates
+RECT WarpClientRect; // in client coordinates
+
+LOCAL POINT pMiddle; // centre point of the current Console window
+LOCAL POINT pLast = {0,0};
+LOCAL BOOL bAlertMessage=TRUE;
+LOCAL BOOL b256mode=FALSE;
+LOCAL int old_x=319; // previous pointer state (position)
+LOCAL int old_y=99; // in virtual coordinates.
+LOCAL short m2pX=8,m2pY=16; // Mickey to pixel ratios
+LOCAL BOOL bFunctionZeroReset = TRUE;
+LOCAL BOOL bFunctionFour = FALSE;
+LOCAL IS16 newF4x,newF4y;
+
+
+
+GLOBAL VOID host_os_mouse_pointer(MOUSE_CURSOR_STATUS *,MOUSE_CALL_MASK *,
+
+ MOUSE_VECTOR *);
+
+FORWARD BOOL WarpSystemPointer(IS16 *,IS16 *);
+FORWARD void MovePointerToWindowCentre(void);
+FORWARD void host_mouse_install1(void);
+FORWARD void host_mouse_install2(void);
+FORWARD void mouse_restore_cursor(void);
+FORWARD void deinstall_host_mouse(void);
+FORWARD BOOL mouse_installed(void);
+FORWARD BOOL mouse_in_use(void);
+FORWARD void mouse_reset(void);
+FORWARD void mouse_set_position(USHORT,USHORT);
+FORWARD void mouse_cursor_display(void);
+FORWARD void mouse_cursor_undisplay(void);
+FORWARD void mouse_cursor_mode_change(void);
+FORWARD BOOL HasConsoleClientRectChanged(void);
+FORWARD void MouseDisplay();
+FORWARD void CToS(RECT *);
+FORWARD void MouseDetachMenuItem(BOOL);
+FORWARD void MouseAttachMenuItem(HANDLE);
+FORWARD void MouseReattachMenuItem(HANDLE);
+FORWARD void ResetMouseOnBlock(void);
+FORWARD void ScaleToWindowedVirtualCoordinates(IS16 *,IS16 *,MOUSE_VECTOR *);
+FORWARD void host_m2p_ratio(word *,word *,word *,word *);
+FORWARD void host_x_range(word *,word *,word *,word *);
+FORWARD void host_y_range(word *,word *,word *,word *);
+FORWARD void EmulateCoordinates(half_word,IS16,IS16,IS16 *,IS16 *);
+FORWARD void AssembleCallMask(MOUSE_CALL_MASK *);
+FORWARD void FullscTextPtr(int, int);
+FORWARD void WindowedGraphicsScale(half_word,IS16,IS16,IS16 *,IS16 *);
+FORWARD void dummy(short *,short *,unsigned short *);
+FORWARD void LimitCoordinates(half_word,IS16 *,IS16 *);
+#ifdef X86GFX
+FORWARD void CleanUpMousePointer();
+FORWARD void FullscreenWarpSystemPointer(POINT *);
+FORWARD void ScaleToFullscreenVirtualCoordinates(IS16 *,IS16 *,MOUSE_VECTOR *);
+#endif //X86GFX
+FORWARD void TextScale(IS16 *,IS16 *,IS16 *, IS16 *);
+
+void LazyMouseInterrupt();
+VOID MouseEoiHook(int IrqLine, int CallCount);
+BOOLEAN bSuspendMouseInterrupts=FALSE;
+
+
+GLOBAL HOSTMOUSEFUNCS the_mouse_funcs =
+{
+ mouse_restore_cursor,
+ deinstall_host_mouse,
+ mouse_installed,
+ mouse_in_use,
+ mouse_reset,
+ mouse_set_position,
+ dummy,
+ mouse_cursor_display,
+ mouse_cursor_undisplay,
+ mouse_cursor_mode_change
+};
+
+BOOL bMouseMenuItemAdded=FALSE;
+HMENU hM;
+
+//
+// look up table to convert the video mode number to a mode type indicator
+//
+
+LOCAL half_word TextOrGraphicsModeLUT[] =
+ {
+ TEXT_MODE, TEXT_MODE, TEXT_MODE, TEXT_MODE, GRAPHICS_MODE,
+ GRAPHICS_MODE,GRAPHICS_MODE,NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, GRAPHICS_MODE,GRAPHICS_MODE,
+ GRAPHICS_MODE,GRAPHICS_MODE,GRAPHICS_MODE,GRAPHICS_MODE,GRAPHICS_MODE,
+ GRAPHICS_MODE,NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, TEXT_MODE, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, TEXT_MODE,
+ TEXT_MODE, TEXT_MODE, TEXT_MODE, TEXT_MODE, TEXT_MODE,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, NOTHING, NOTHING, NOTHING, NOTHING,
+ NOTHING, GRAPHICS_MODE,GRAPHICS_MODE,GRAPHICS_MODE
+ };
+
+
+LOCAL int VirtualScrCtrLUTx[] =
+ {
+ 319, // mode 0
+ 319, // mode 1
+ 319, // mode 2
+ 319, // mode 3
+ 319, // mode 4
+ 319, // mode 5
+ 319, // mode 6
+ 319, // mode 7
+ 319, // mode 8
+ 319, // mode 9
+ 319, // mode a
+ 319, // mode b
+ 319, // mode c
+ 319, // mode d
+ 319, // mode e
+ 319, // mode f
+ 319, // mode 10
+ 319, // mode 11
+ 319, // mode 12
+ 159 // mode 13
+ };
+LOCAL int VirtualScrCtrLUTy[] =
+ {
+ 99, // mode 0
+ 99, // mode 1
+ 99, // mode 2
+ 99, // mode 3
+ 99, // mode 4
+ 99, // mode 5
+ 99, // mode 6
+ 99, // mode 7
+ 99, // mode 8
+ 99, // mode 9
+ 99, // mode a
+ 99, // mode b
+ 99, // mode c
+ 99, // mode d
+ 99, // mode e
+ 174, // mode f
+ 174, // mode 10
+ 239, // mode 11
+ 239, // mode 12
+ 99 // mode 13
+ };
+
+//
+// A look up table to convert a console cell location to a virtual pixel
+// coordinate.
+//
+
+int ConsoleTextCellToVPCellLUT[] =
+ {
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 64, 72, 80, 88, 96, 104, 112, 120,
+ 128, 136, 144, 152, 160, 168, 176, 184,
+ 192, 200, 208, 216, 224, 232, 240, 248,
+ 256, 264, 272, 280, 288, 296, 304, 312,
+ 320, 328, 336, 344, 352, 360, 368, 376,
+ 384, 392, 400, 408, 416, 424, 432, 440,
+ 448, 456, 464, 472, 480, 488, 496, 504,
+ 512, 520, 528, 536, 544, 552, 560, 568,
+ 576, 584, 592, 600, 608, 616, 624, 632,
+ 640, 648, 656, 664, 672, 680, 688, 696
+ };
+
+
+//
+// This structure holds the information provided by int 33h functions 7 and 8.
+// If one of these functions have been called, then the appropriate flag in
+// the structure is set and the handler for this will ignore the default bounds
+// for the current video mode and will use the values in the structure instead.
+// The flags will clear if a mode change has been detected too.
+//
+
+struct
+ {
+ word xmin;
+ word ymin;
+ word xmax;
+ word ymax;
+ BOOL bF7;
+ BOOL bF8;
+ } confine = {0,0,639,199,FALSE,FALSE};
+//
+// Mouse interrupt regulation mechanisms
+//
+BOOLEAN bMseEoiPending = FALSE;
+ULONG MseIntLazyCount = 0;
+
+//
+//
+// The code starts here
+//
+//
+
+GLOBAL void host_mouse_install1(void)
+{
+mouse_state = INSTALLED;
+RegisterEOIHook(9, MouseEoiHook);
+mouse_install1();
+}
+
+
+GLOBAL void host_mouse_install2(void)
+{
+mouse_install2();
+}
+
+
+GLOBAL void mouse_restore_cursor()
+{
+/* If mouse not in use exit */
+
+if(!mouse_in_use())
+ return;
+
+}
+
+GLOBAL void deinstall_host_mouse()
+{
+mouse_state = NOT_INSTALLED;
+}
+
+
+GLOBAL BOOL mouse_installed()
+{
+return (mouse_state);
+}
+
+void dummy(short *pooh1,short *pooh2, unsigned short *pooh3)
+{
+}
+
+GLOBAL BOOL mouse_in_use()
+{
+return(mouse_state == INSTALLED && in_text_mode() == FALSE);
+}
+
+GLOBAL void mouse_reset()
+{
+#ifdef X86GFX
+
+half_word vm;
+word xx,yy;
+
+//
+// Set the internal cursor flag to "just off"
+// the real driver sets the internal cursor flag to -1
+// so do I.
+//
+
+sas_store(mouseCFsysaddr,0xff); // cursor hidden
+
+//
+// Set the fast track position words in the 16 bit driver.
+// First igure out the video mode, and from this, the virtual
+// screen centre.
+//
+
+sas_load(0x449,&vm);
+xx = (word)VirtualScrCtrLUTx[vm];
+yy = (word)VirtualScrCtrLUTy[vm];
+
+//
+// The values for the confining virtual pixel coordinate rectangle
+// as set up by int 33h functions 7 and 8 are now released and the
+// default virtual bounds are used.
+//
+
+confine.bF7 = FALSE; // reset the flag indicating a int 33h function 7
+confine.bF8 = FALSE; // reset the flag indicating a int 33h function 8
+
+bFunctionZeroReset = TRUE;
+
+//
+// write the centre position data back to the 16 bit driver.
+//
+
+if(sc.ScreenState == FULLSCREEN)
+ {
+ //
+ // Force a host_os_mouse_pointer call to do the
+ // write back into the 16 bit driver.
+ //
+ LazyMouseInterrupt();
+ }
+#endif /*X86GFX */
+
+//
+// Set the default Mickey to pixel ratios
+// This is set to 8 pixels to 8 Mickeys in the horizontal direction
+// and 16 pixels to 8 Mickeys in the vertical.
+//
+
+m2pX = 8;
+m2pY = 16;
+
+}
+
+
+GLOBAL void mouse_set_position IFN2(USHORT, newx, USHORT, newy)
+{
+#ifdef X86GFX
+word currentCS, currentIP, currentCX, currentDX;
+boolean currentIF;
+half_word internalCF;
+
+ //
+ // write the new position to the 16 bit driver for the fast
+ // int33hf3 calls on X86.
+ //
+
+ sas_storew(effective_addr(button_seg,((word)(button_off+2))),(word)newx);
+ sas_storew(effective_addr(button_seg,((word)(button_off+4))),(word)newy);
+
+#endif //X86GFX
+
+
+//
+// Both Fullscreen and MouseHidePointer enabled windowed mode
+// mouse emulations are driven by a set of emulated counters.
+// X,Y values are held independently to these counters and rely
+// on this function to set up absolute values for X and Y. Note:
+// reset does this too.
+//
+
+if(sc.ScreenState == WINDOWED && bPointerOff)
+ {
+ newF4x = (IS16)newx;
+ newF4y = (IS16)newy;
+ bFunctionFour = TRUE;
+ return;
+ }
+#ifdef X86GFX
+else if(sc.ScreenState == FULLSCREEN)
+ {
+ //
+ // The values that are passed in are hot and fresh from the app.
+ // Since they have not been tainted by the base, they are still
+ // in virtual coordinates which is cool.
+ //
+
+ //
+ // Get the internal cursor flag from the 16 bit driver
+ //
+
+ sas_load(mouseCFsysaddr,&internalCF);
+
+ //
+ // Only draw the pointer if the internal cursor flag
+ // is zero. Note: less than zero == don't draw.
+ //
+
+ if(!internalCF)
+ {
+ /* if conditional off is diabled or the cursor is outside the
+ * conditional off rectangle, move the cursor
+ */
+
+ if (sas_hw_at_no_check(conditional_off_sysaddr) == 0 ||
+ !cursor_in_black_hole(newx, newy))
+ {
+ currentCS=getCS();
+ currentIP=getIP();
+ currentCX=getCX();
+ currentDX=getDX();
+ currentIF=getIF();
+ setCS(DRAW_FS_POINTER_SEGMENT); // sacrificial data
+ setIP(DRAW_FS_POINTER_OFFSET);
+ setCX((word)newx);
+ setDX((word)newy);
+ setIF(FALSE);
+ //
+ // call back to 16bits move cursor code.
+ //
+
+ host_simulate();
+
+ //
+ // Tidy up
+ //
+
+ setCX(currentCX);
+ setDX(currentDX);
+ setCS(currentCS);
+ setIP(currentIP);
+ setIF(currentIF);
+ }
+ else {
+ /* the cursor was moved into the conditional rectangle, hide it */
+ sas_store(mouseCFsysaddr, 0xff);
+ host_hide_pointer();
+ }
+ }
+ newF4x = (IS16)newx;
+ newF4y = (IS16)newy;
+ bFunctionFour = TRUE;
+
+ //
+ // update the last mouse position global locators
+ //
+
+ old_x = newx;
+ old_y = newy;
+ }
+#endif //X86GFX
+}
+
+GLOBAL void mouse_cursor_display()
+{
+}
+
+GLOBAL void mouse_cursor_undisplay()
+{
+}
+
+GLOBAL void mouse_cursor_mode_change()
+{
+}
+
+
+GLOBAL void host_mouse_conditional_off_enabled(void)
+{
+#ifdef X86GFX
+ word x, y;
+
+ /* hide the cursor if
+ * (1). we are in full screen and
+ * (2). the cursor is on and is in the conditional area
+ */
+ if (sc.ScreenState == FULLSCREEN &&
+ !sas_hw_at_no_check(mouseCFsysaddr)) {
+
+ x = sas_w_at_no_check(effective_addr(CP_X_S, CP_X_O));
+ y = sas_w_at_no_check(effective_addr(CP_Y_S, CP_Y_O));
+ if (cursor_in_black_hole(x, y)) {
+ sas_store(mouseCFsysaddr, 0xff);
+ host_hide_pointer();
+ }
+ }
+#endif
+
+
+}
+//==============================================================================
+// Hook function that forms the communication transition between
+// the host and the base for os pointer emulation. This function
+// is called by mouse_int1() which lives in mouse_io.c
+//==============================================================================
+
+
+VOID host_os_mouse_pointer(MOUSE_CURSOR_STATUS *mcs,MOUSE_CALL_MASK *call_mask,
+ MOUSE_VECTOR *counter)
+{
+#ifdef X86GFX
+sys_addr int33f3addr;
+#endif // X86GFX
+
+host_ica_lock(); // synch with the event thread
+
+GetNextMouseEvent();
+
+#ifdef X86GFX
+
+if(sc.ScreenState == FULLSCREEN)
+ {
+ ScaleToFullscreenVirtualCoordinates(&mcs->position.x,&mcs->position.y,counter);
+ }
+else
+#endif // X86GFX
+ {
+ ScaleToWindowedVirtualCoordinates(&mcs->position.x,&mcs->position.y,counter);
+ }
+
+//
+// Create a condition mask for use by any call back installed
+// by the application.
+//
+
+AssembleCallMask(call_mask);
+
+//
+// Tell the base about the button state
+//
+
+mcs->button_status=os_pointer_data.button_l | os_pointer_data.button_r<<1;
+
+host_ica_unlock(); // synch with the event thread
+
+
+//
+// Has the pointer moved since the last mouse interrupt.
+// This can happen if a button press occurs but no physical
+// movement of the mouse body takes place.
+//
+
+if(bPointerInSamePlace)
+ {
+ //
+ // The mouse has not moved since the last mouse
+ // hardware interrupt.
+ //
+
+ *call_mask &= ~1;
+ }
+else
+ {
+#ifdef X86GFX
+ half_word internalCF;
+#endif // X86GFX
+
+ //
+ // The mouse has moved.
+ //
+
+ *call_mask |= 1;
+
+#ifdef X86GFX
+
+ //
+ // Inquire from the 16 bit driver whether or not the
+ // pointer can be drawn.
+ // internalCF < 0 -> cannot draw
+ // internalCF == 0 okay to draw.
+ //
+
+ sas_load(mouseCFsysaddr,&internalCF);
+
+ //
+ // If the system has fullscreen capabilities and is in fullscreen
+ // mode, then if the pointer has been switched on, draw it on the
+ // fullscreen display.
+ //
+
+ if(sc.ScreenState == FULLSCREEN && !internalCF)
+ {
+ half_word v;
+ static half_word hwLastModeType;
+
+ if (sas_hw_at_no_check(conditional_off_sysaddr) == 0 ||
+ !cursor_in_black_hole(mcs->position.x, mcs->position.y))
+ {
+ //
+ // Get the current BIOS video mode a la B.D.A.
+ //
+
+ sas_load(0x449,&v);
+
+ if((hwLastModeType = TextOrGraphicsModeLUT[v]) == GRAPHICS_MODE)
+ {
+ word currentCS,currentIP; // save those interesting Intel registers
+ word currentCX,currentDX;
+ boolean currentIF;
+
+ //
+ // Do the host simulate here to draw the cursor image
+ // for the full screen graphics
+ //
+
+ currentCS=getCS();
+ currentIP=getIP();
+ currentCX=getCX();
+ currentDX=getDX();
+ currentIF=getIF();
+ setCS(DRAW_FS_POINTER_SEGMENT);
+ setIP(DRAW_FS_POINTER_OFFSET);
+ setCX(mcs->position.x);
+ setDX(mcs->position.y);
+ setIF(FALSE);
+ //
+ // call to 16bits move cursor code
+ //
+
+ host_simulate();
+
+ //
+ // Restore the 16 bit context.
+ //
+
+ setCX(currentCX);
+ setDX(currentDX);
+ setCS(currentCS);
+ setIP(currentIP);
+ setIF(currentIF);
+ }
+ else // TEXT_MODE
+ {
+ //
+ // if there has been a switch from graphics mode to text mode
+ // then there cannot have been a backround saved.
+ //
+
+ if(hwLastModeType == GRAPHICS_MODE)
+ {
+ bFullscTextBkgrndSaved = FALSE;
+ hwLastModeType = TEXT_MODE;
+ }
+
+ //
+ // Use some 32 bit code to draw the text pointer because
+ // no hardware i/o is involved and we need only to write to
+ // the display buffer (16 bit code is needed to do video
+ // i/os in fullscreen mode).
+ //
+
+ FullscTextPtr(mcs->position.x,mcs->position.y);
+ }
+ }
+ else {
+ sas_store(mouseCFsysaddr, 0xff);
+ host_hide_pointer();
+ }
+ }
+#endif // X86GFX
+ }
+
+
+//
+// Write data to the 16 bit driver for int 33h function 3 to pick up
+// without having to BOP to the 32 bit side.
+// Int 33h function 3 requires this data:
+// BX = button status
+// CX = virtual pixel position in x
+// DX = virtual pixel position in y
+//
+
+#ifdef X86GFX
+int33f3addr = effective_addr(button_seg,button_off);
+sas_storew(int33f3addr,mcs->button_status);
+sas_storew(int33f3addr+=2, (word)(mcs->position.x));
+sas_storew(int33f3addr+=2, (word)(mcs->position.y));
+#endif //X86GFX
+}
+
+//==============================================================================
+// Function to munge the status register value for the InPort adapter.
+// Nothing much else to say about it really.
+//
+//==============================================================================
+
+void AssembleCallMask(MOUSE_CALL_MASK *call_mask)
+{
+static int old_l_button=0; // previous mouse button state
+static int old_r_button=0;
+
+
+//
+// add in the left button current status
+//
+
+if(os_pointer_data.button_l)
+ {
+ //
+ // Left button is down.
+ //
+
+ if(!old_l_button)
+ {
+ //
+ // The button has just been pressed
+ //
+
+ *call_mask |= (1<<1);
+ }
+ else
+ {
+ //
+ // The button was down on the last hardware interrupt, so
+ // release the edge detect.
+ //
+
+ *call_mask &= ~(1<<1);
+ }
+ }
+else
+ {
+ //
+ // Left button is up.
+ //
+
+ if(old_l_button)
+ {
+ //
+ // The button has just been released
+ //
+
+ *call_mask |= (1<<2);
+ }
+ else
+ {
+ //
+ // The button was up on the last hardware interrupt, so
+ // release the edge detect.
+ //
+
+ *call_mask &= ~(1<<2);
+ }
+ }
+
+//
+// add in the right button current status
+//
+
+if(os_pointer_data.button_r)
+ {
+ //
+ // Right button is down.
+ //
+
+ if(!old_r_button)
+ {
+ //
+ // The button has just been pressed
+ //
+
+ *call_mask |= (1<<3);
+ }
+ else
+ {
+ //
+ // The button was down on the last hardware interrupt, so
+ // release the edge detect.
+ //
+
+ *call_mask &= ~(1<<3);
+ }
+ }
+else
+ {
+ //
+ // Right button is up.
+ //
+
+ if(old_r_button)
+ {
+ //
+ // The button has just been released
+ //
+
+ *call_mask |= (1<<4);
+ }
+ else
+ {
+ //
+ // The button was up on the last hardware interrupt, so
+ // release the edge detect.
+ //
+
+ *call_mask &= ~(1<<4);
+ }
+ }
+
+//
+//
+// save the current mouse button status.
+//
+
+old_l_button = os_pointer_data.button_l;
+old_r_button = os_pointer_data.button_r;
+
+}
+
+#ifdef X86GFX
+//=========================================================================
+// Function to scale mouse coordinates as retrieved from USER
+// to virtual coordinates as defined by the Microsoft Mouse
+// Programmer's Reference.
+//=========================================================================
+
+void ScaleToFullscreenVirtualCoordinates(IS16 *outx,IS16 *outy,
+ MOUSE_VECTOR *counter)
+{
+half_word video_mode,textorgraphics;
+IS16 internalX = 0, internalY = 0;
+static IS16 lastinternalX=0, lastinternalY=0;
+POINT vector; // Magnitude and direction since last call
+
+
+//
+// Manage the system pointer so that it never sticks to a system
+// imposed boundary. Also get a relative displacement of the mouse.
+//
+
+FullscreenWarpSystemPointer(&vector);
+
+//
+// return the internal counter values back to the base
+// code for it to use to generate the counters there.
+//
+
+counter->x = (MOUSE_SCALAR)vector.x;
+counter->y = (MOUSE_SCALAR)vector.y;
+
+//
+// Get the current BIOS video mode from the B.D.A. This comes
+// in handy in a couple of places later.
+//
+
+sas_load(0x449,&video_mode);
+
+//
+// checkout some global flags with indicate if one of the int 33h
+// functions which are capable of changing the position of the
+// DOS mouse driver pointer have been called since the last mouse
+// hardware interrupt.
+//
+
+if(bFunctionZeroReset)
+ {
+ //
+ // Calculate the centre of the default virtual screen
+ // and set the current generated coordinates to it.
+ //
+
+ internalX = (IS16)VirtualScrCtrLUTx[video_mode];
+ internalY = (IS16)VirtualScrCtrLUTy[video_mode];
+
+ bFunctionZeroReset = FALSE;
+ }
+else if(bFunctionFour)
+ {
+ //
+ // The application has set the pointer to a new location.
+ // Tell the internal cartesian coordinate system about this.
+ //
+
+ internalX = newF4x; // This is where the pointer was set to
+ internalY = newF4y; // by the app on the last pending call to f4
+
+ //
+ // Don't come in here again until the next function 4.
+ //
+
+ bFunctionFour = FALSE;
+ }
+else
+ {
+ //
+ // The most frequent case. Determine the new, raw pointer position
+ // by adding the system pointer movement vector to the last position
+ // of the emulated pointer.
+ //
+
+ internalX = lastinternalX + (IS16)vector.x;
+ internalY = lastinternalY + (IS16)vector.y;
+ }
+
+//
+// use the video mode to determine if we're running text or graphics
+//
+
+textorgraphics=TextOrGraphicsModeLUT[video_mode];
+
+//
+// Scale the coordinates appropriately for the current video mode
+// and the type (text or graphics) that it is.
+//
+
+if(textorgraphics == TEXT_MODE)
+ {
+ //
+ // The virtual cell block is 8 by 8 virtual pixels for any text mode.
+ // This means that the cell coordinates in virtual pixels increments
+ // by 8 in the positive x and y directions and the top left hand corner
+ // of the cell starts at 0,0 and has the virtual pixel value for the
+ // whole text cell.
+ //
+
+ TextScale(&internalX,&internalY,outx,outy);
+ }
+
+else // GRAPHICS_MODE
+ {
+ LimitCoordinates(video_mode,&internalX,&internalY);
+ *outx = internalX;
+ *outy = internalY;
+ }
+
+//
+// Set up the current emulated position for next time through
+// this function.
+//
+
+lastinternalX = internalX;
+lastinternalY = internalY;
+
+//
+// Signal that the pointer hasn't moved, if it hasn't
+//
+
+bPointerInSamePlace = (!vector.x && !vector.y) ? TRUE : FALSE;
+
+//
+// save the current position for next time.
+//
+
+old_x = *outx;
+old_y = *outy;
+}
+
+//==============================================================================
+// Function to make sure that the system pointer can be made to move in a
+// given cartesian direction without hitting and finite boundaries as specified
+// by the operating system.
+//==============================================================================
+void FullscreenWarpSystemPointer(POINT *vector)
+{
+static POINT pLast; // System pointer position data from last time through
+POINT pCurrent;
+
+//
+// Get a system mouse pointer absolute position value back from USER.
+//
+
+GetCursorPos(&pCurrent);
+
+//
+// Calculate the vector displacement of the system pointer since
+// the last call to this function.
+//
+
+vector->x = pCurrent.x - pLast.x;
+vector->y = pCurrent.y - pLast.y;
+
+//
+// Has the system pointer hit a border? If so, warp the system pointer
+// back to the convienient location of 0,0.
+//
+
+
+if(pCurrent.x >= (LONG)1000 || pCurrent.x <= (LONG)-1000 ||
+ pCurrent.y >= (LONG)1000 || pCurrent.y <= (LONG)-1000)
+ {
+ //
+ // If the counters have warped, set the system pointer
+ // to the relavent position.
+ //
+
+ SetCursorPos(0,0);
+ pLast.x = 0L; // prevent a crazy warp
+ pLast.y = 0L;
+ }
+else
+ {
+ //
+ // update the last position data of the
+ // system pointer for next time through.
+ //
+ pLast = pCurrent;
+ }
+}
+
+#endif // X86GFX
+
+//=========================================================================
+// Function to scale mouse coordinates as returned by the event loop
+// mechanism to virtual coordinates as defined by the Microsoft Mouse
+// Programmer's Reference. The method used for scaling depends on the style
+// of mouse buffer selected, the current video mode and if (for X86) the
+// video system is operating in full screen or windowed mode.
+//
+// Output: Virtual cartesian coordinates in the same pointers
+//=========================================================================
+
+void ScaleToWindowedVirtualCoordinates(IS16 *outx,IS16 *outy,
+ MOUSE_VECTOR *counter)
+{
+half_word video_mode,textorgraphics;
+SAVED SHORT last_text_good_x = 0, last_text_good_y = 0;
+
+sas_load(0x449,&video_mode);
+
+//
+// Follow different code paths if the user has the system pointer
+// hidden or displayed.
+//
+
+if(!bPointerOff)
+ {
+ //
+ // The pointer has not been hidden by the user, so use the
+ // x,y values as got from the system pointer via the Windows
+ // messaging system.
+ //
+
+ //
+ // get the video mode to determine if we're running text or graphics
+ //
+
+ textorgraphics=TextOrGraphicsModeLUT[video_mode];
+
+ if(textorgraphics == TEXT_MODE)
+ {
+ //
+ // validate received data to ensure not graphics mode coords
+ // received during mode switch.
+ //
+
+ if(os_pointer_data.x > 87)
+ {
+ *outx = last_text_good_x;
+ }
+ else
+ {
+ *outx = ConsoleTextCellToVPCellLUT[os_pointer_data.x];
+ last_text_good_x = *outx;
+ }
+ if(os_pointer_data.y > 87)
+ {
+ *outy = last_text_good_y;
+ }
+ else
+ {
+ *outy = ConsoleTextCellToVPCellLUT[os_pointer_data.y];
+ last_text_good_y = *outy;
+ }
+ }
+ else // GRAPHICS_MODE
+ {
+ //
+ // If the mouse is NOT in a warping mode, then x,y's as received
+ // from the console are scaled if they are for a low resolution
+ // video mode and these are what the application sees and the
+ // system pointer image is in the correct place to simulate the
+ // 16 bit pointer.
+ // If the application decides to extend the x,y bounds returned
+ // from the driver beyond the limits of the console being used,
+ // these x,y's are not appropriate, and the mouse must be switched
+ // into warp mode by the user and the code will emulate the x,y
+ // generation.
+ //
+
+ WindowedGraphicsScale(video_mode,(IS16)(os_pointer_data.x),
+ (IS16)(os_pointer_data.y),outx,outy);
+ }
+
+ //
+ // No warping, so set up the old_x and old_y values directly.
+ // Signal that the pointer hasn't moved, if it hasn't
+ //
+
+ bPointerInSamePlace = (old_x == *outx && old_y == *outy) ? TRUE : FALSE;
+
+ //
+ // Set these statics for the next time through.
+ //
+
+ old_x = *outx;
+ old_y = *outy;
+ }
+else
+ {
+ //
+ // The user has set the system pointer to be hidden via the
+ // console's system menu.
+ // Handle by emulating the counters and generating absolute x,y
+ // data from this.
+ //
+
+ IS16 move_x,move_y;
+
+ //
+ // Get positional data from the system pointer and maintain some
+ // counters.
+ //
+
+ if(WarpSystemPointer(&move_x,&move_y))
+ {
+ //
+ // The mouse moved.
+ // Generate some new emulated absolute position information.
+ //
+
+ EmulateCoordinates(video_mode,move_x,move_y,outx,outy);
+
+ //
+ // Save up the current emulated position for next time through.
+ //
+
+
+ old_x = *outx;
+ old_y = *outy;
+
+ //
+ // Send back the relative motion since last time through.
+ //
+
+ counter->x = move_x;
+ counter->y = move_y;
+
+ bPointerInSamePlace = FALSE;
+ }
+ else
+ {
+ //
+ // No recorded movement of the mouse.
+ //
+
+ *outx = old_x;
+ *outy = old_y;
+ counter->x = counter->y = 0;
+ bPointerInSamePlace = TRUE;
+ }
+ }
+}
+
+
+//==============================================================================
+// Function to scale the incoming fullscreen coordinates to mouse motion (both
+// absolute and relative) for fullscreen text mode.
+// Note: if the application chooses to, it can reset the virtual coordinate
+// bounds of the virtual screen. This function checks the bound flags and either
+// selects the default values or the app imposed values.
+//
+// This function is also used to modify the coordinates produced directly from
+// the motion counters in windowed text mode.
+//==============================================================================
+
+void TextScale(IS16 *iX,IS16 *iY,IS16 *oX, IS16 *oY)
+{
+half_word no_of_rows;
+
+//
+// Calculate the current system pointer location in virtual
+// pixels for the application.
+//
+
+if(confine.bF7)
+ {
+ //
+ // Limits have been imposed by the application.
+ //
+
+ if(*iX < confine.xmin)
+ {
+ *iX = confine.xmin;
+ }
+ else if(*iX > confine.xmax)
+ {
+ *iX = confine.xmax;
+ }
+ }
+else // use the default virtual screen constraints.
+ {
+ //
+ // No limits have been imposed by the application.
+ // x is always 0 -> 639 virtual pixels for text mode
+ //
+
+ if(*iX < 0)
+ {
+ *iX = 0;
+ }
+ else if(*iX > 639)
+ {
+ *iX = 639;
+ }
+ }
+
+//
+// Bind the y cartesian coordinate appropriately
+//
+
+if(confine.bF8)
+ {
+ //
+ // Limits have been imposed by the application.
+ //
+
+ if(*iY < confine.ymin)
+ {
+ *iY = confine.ymin;
+ }
+ else if(*iY > confine.ymax)
+ {
+ *iY = confine.ymax;
+ }
+ }
+else
+ {
+ //
+ // The application has not imposed constraints on the Y virtual pixel
+ // motion, so confine the Y movement to the default virtual pixel size
+ // of the virtual screen for the current video mode.
+ //
+
+ if(*iY < 0)
+ {
+ *iY = 0;
+ }
+ else
+ {
+ //
+ // Get the number of text rows minus one, from the B.D.A.
+ //
+
+ sas_load(0x484,&no_of_rows);
+
+ switch(no_of_rows)
+ {
+ case 24:
+ {
+ //
+ // 25 rows, so there are 200 vertical virtual pixels
+ //
+ if(*iY > 199)
+ {
+ *iY = 199;
+ }
+ break;
+ }
+ case 42:
+ {
+ //
+ // 43 rows, so there are 344 vertical virtual pixels
+ //
+ if(*iY > 343)
+ {
+ *iY = 343;
+ }
+ break;
+ }
+ case 49:
+ {
+ //
+ // 50 rows, so there are 400 vertical virtual pixels
+ //
+ if(*iY > 399)
+ {
+ *iY = 399;
+ }
+ break;
+ }
+ default:
+ {
+ //
+ // default - assume 25 rows, so there are
+ // 200 vertical virtual pixels
+ //
+ if(*iY > 199)
+ {
+ *iY = 199;
+ }
+ break;
+ }
+ }
+ }
+ }
+*oX = *iX;
+*oY = *iY;
+}
+
+
+//==============================================================================
+// Fit the raw x,y coordinates generated from the counters to the bounds of
+// the virtual screen that is currently set up. This can be set up either by
+// the application (in the confine structure) or as set by the mouse driver
+// as default.
+//==============================================================================
+
+void LimitCoordinates(half_word vm,IS16 *iX,IS16 *iY)
+{
+//
+// Select the appropriate conditioning code for
+// the current video mode.
+//
+switch(vm)
+ {
+
+ //
+ // Do the common text modes.
+ //
+
+ case(2):
+ case(3):
+ case(7):
+ {
+ IS16 oX,oY;
+
+ //
+ // Scale the generated coordinates for the given text mode
+ // and the number of rows of text displayed on the screen.
+ //
+
+ TextScale(iX,iY, &oX, &oY);
+ *iX = oX;
+ *iY = oY;
+ break;
+ }
+
+ //
+ // The regular VGA supported graphics video modes.
+ //
+ // The following modes are all 640 x 200 virtual pixels
+ //
+ case(4):
+ case(5):
+ case(6):
+ case(0xd):
+ case(0xe):
+ case(0x13):
+ {
+ if(confine.bF7)
+ {
+ //
+ // Limits have been imposed by the application.
+ //
+
+ if(*iX < confine.xmin)
+ {
+ *iX = confine.xmin;
+ }
+ else if(*iX > confine.xmax)
+ {
+ *iX = confine.xmax;
+ }
+ }
+ else
+ {
+ //
+ // The application has not imposed limits, so use
+ // the default virtual screen bounds as defined byt
+ // the mouse driver.
+ //
+
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 639)
+ *iX = 639;
+ }
+
+ if(confine.bF8)
+ {
+ //
+ // Limits have been imposed by the application.
+ //
+
+ if(*iY < confine.ymin)
+ {
+ *iY = confine.ymin;
+ }
+ else if(*iY > confine.ymax)
+ {
+ *iY = confine.ymax;
+ }
+ }
+ else
+ {
+ //
+ // The application has not imposed limits, so use
+ // the default virtual screen bounds as defined byt
+ // the mouse driver.
+ //
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 199)
+ *iY = 199;
+ }
+ break;
+ }
+ //
+ // The following modes are all 640 x 350 virtual pixels
+ //
+ case(0xf):
+ case(0x10):
+ {
+ if(confine.bF7)
+ {
+ //
+ // Limits have been imposed by the application.
+ //
+
+ if(*iX < confine.xmin)
+ {
+ *iX = confine.xmin;
+ }
+ else if(*iX > confine.xmax)
+ {
+ *iX = confine.xmax;
+ }
+ }
+ else
+ {
+ //
+ // The application has not imposed limits, so use
+ // the default virtual screen bounds as defined byt
+ // the mouse driver.
+ //
+
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 639)
+ *iX = 639;
+ }
+
+ if(confine.bF8)
+ {
+ //
+ // Limits have been imposed by the application.
+ //
+
+ if(*iY < confine.ymin)
+ {
+ *iY = confine.ymin;
+ }
+ else if(*iY > confine.ymax)
+ {
+ *iY = confine.ymax;
+ }
+ }
+ else
+ {
+ //
+ // The application has not imposed limits, so use
+ // the default virtual screen bounds as defined byt
+ // the mouse driver.
+ //
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 349)
+ *iY = 349;
+ }
+ break;
+ }
+ //
+ // The following modes are all 640 x 480 virtual pixels
+ //
+ case(0x11):
+ case(0x12):
+ {
+ if(confine.bF7)
+ {
+ //
+ // Limits have been imposed by the application.
+ //
+
+ if(*iX < confine.xmin)
+ {
+ *iX = confine.xmin;
+ }
+ else if(*iX > confine.xmax)
+ {
+ *iX = confine.xmax;
+ }
+ }
+ else
+ {
+ //
+ // The application has not imposed limits, so use
+ // the default virtual screen bounds as defined byt
+ // the mouse driver.
+ //
+
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 639)
+ *iX = 639;
+ }
+
+ if(confine.bF8)
+ {
+ //
+ // Limits have been imposed by the application.
+ //
+
+ if(*iY < confine.ymin)
+ {
+ *iY = confine.ymin;
+ }
+ else if(*iY > confine.ymax)
+ {
+ *iY = confine.ymax;
+ }
+ }
+ else
+ {
+ //
+ // The application has not imposed limits, so use
+ // the default virtual screen bounds as defined byt
+ // the mouse driver.
+ //
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 479)
+ *iY = 479;
+ }
+ break;
+ }
+
+ //
+ // From here on down are the Video7 modes
+ //
+
+ case(0x60):
+ {
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 751)
+ *iX = 751;
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 407)
+ *iY = 407;
+ break;
+ }
+ case(0x61):
+ {
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 719)
+ *iX = 719;
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 535)
+ *iY = 535;
+ break;
+ }
+ case(0x62):
+ case(0x69):
+ {
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 799)
+ *iX = 799;
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 599)
+ *iY = 599;
+ break;
+ }
+ case(0x63):
+ case(0x64):
+ case(0x65):
+ {
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 1023)
+ *iX = 1023;
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 767)
+ *iY = 767;
+ break;
+ }
+ case(0x66):
+ {
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 639)
+ *iX = 639;
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 399)
+ *iY = 399;
+ break;
+ }
+ case(0x67):
+ {
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 639)
+ *iX = 639;
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 479)
+ *iY = 479;
+ break;
+ }
+ case(0x68):
+ {
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 719)
+ *iX = 719;
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 539)
+ *iY = 539;
+ break;
+ }
+ default:
+ {
+ if(*iX < 0)
+ *iX = 0;
+ else if(*iX > 639)
+ *iX = 639;
+
+ if(*iY < 0)
+ *iY = 0;
+ else if(*iY > 199)
+ *iY = 199;
+ break;
+ }
+ }
+}
+
+//==============================================================================
+// Function to scale the incoming windowed coordinates since the window size
+// can be larger (for the low resolution modes) than the virtual screen size
+// for that mode.
+//==============================================================================
+
+void WindowedGraphicsScale(half_word vm,IS16 iX,IS16 iY,IS16 *oX, IS16 *oY)
+{
+switch(vm)
+ {
+ //
+ // The following modes are all 640 x 200 virtual pixels
+ //
+ case(4):
+ case(5):
+ case(6):
+ case(0xd):
+ case(0xe):
+ case(0x13):
+ {
+ //
+ // Low resolution graphics modes. The window is 640 x 400 real host
+ // pixels, but the virtual screen resolution is 640 x 200. Hence
+ // must divide the y value by 2 to scale appropriately.
+ //
+
+ iY >> 1;
+ break;
+ }
+ }
+//
+// prepare the cartesian coordinate values to return.
+//
+
+*oX = iX;
+*oY = iY;
+}
+
+//===========================================================================
+// Function to turn on the mouse cursor in FULLSCREEN mode.
+// Note: This function only gets called after the 16 bit code checks
+// to see if the internal cursor flag is zero. The 16 bit code does
+// not do the BOP if, after incrementing this counter, the above is
+// true.
+//===========================================================================
+
+void host_show_pointer()
+{
+#ifdef X86GFX
+
+if(sc.ScreenState == FULLSCREEN)
+ {
+ half_word v;
+ sas_load(0x449,&v);
+
+ if(TextOrGraphicsModeLUT[v] == GRAPHICS_MODE)
+ {
+ word currentCS,currentIP; // save those interesting Intel registers
+ boolean currentIF;
+
+ sas_storew(effective_addr(CP_X_S,CP_X_O),(word)old_x);
+ sas_storew(effective_addr(CP_Y_S,CP_Y_O),(word)old_y);
+ currentCS=getCS();
+ currentIP=getIP();
+ currentIF=getIF();
+ setCS(POINTER_ON_SEGMENT);
+ setIP(POINTER_ON_OFFSET);
+ setIF(FALSE);
+ host_simulate();
+
+ setCS(currentCS);
+ setIP(currentIP);
+ setIF(currentIF);
+ }
+ else //TEXT_MODE
+ {
+ FullscTextPtr(old_x,old_y);
+ }
+
+ LazyMouseInterrupt();
+ }
+#endif // X86GFX
+}
+
+//===========================================================================
+// Function to turn off the mouse cursor in FULLSCREEN mode.
+// Note: This function only gets called after the 16 bit code checks
+// to see if the internal cursor flag is zero. The 16 bit code does
+// not do the BOP if, after decrementing this counter, the above is
+// true.
+//===========================================================================
+
+void host_hide_pointer()
+{
+#ifdef X86GFX
+
+if(sc.ScreenState == FULLSCREEN)
+ {
+ half_word v;
+
+ sas_load(0x449,&v);
+
+ if(TextOrGraphicsModeLUT[v] == GRAPHICS_MODE)
+ {
+ word currentCS,currentIP; // save those interesting Intel registers
+ boolean currentIF;
+
+ currentCS=getCS();
+ currentIP=getIP();
+ currentIF=getIF();
+ setCS(POINTER_OFF_SEGMENT);
+ setIP(POINTER_OFF_OFFSET);
+ setIF(FALSE);
+ host_simulate();
+
+ setCS(currentCS);
+ setIP(currentIP);
+ setIF(currentIF);
+ }
+ else //TEXT_MODE
+ {
+ if(bFullscTextBkgrndSaved)
+ {
+ sas_storew(old_text_addr,text_ptr_bkgrnd);
+ bFullscTextBkgrndSaved = FALSE;
+ }
+ }
+ LazyMouseInterrupt();
+ }
+#endif // X86GFX
+}
+
+//=========================================================================
+// Function to remove the mouse pointer item from the console system menu
+// when SoftPC lets an application quit or iconise.
+// If the system pointer is OFF i.e. clipped to a region in the current window,
+// then relinquish it to the system.
+//
+// bForce allows the code which gets called when there is a fullscreen to
+// windowed graphics switch on x86 to force the menu item off.
+//=========================================================================
+
+void MouseDetachMenuItem(BOOL bForce)
+{
+if(bMouseMenuItemAdded || bForce)
+ {
+ DeleteMenu(hM,IDM_POINTER,MF_BYCOMMAND);
+ bMouseMenuItemAdded=FALSE;
+ ClipCursor(NULL);
+ }
+bAlertMessage=TRUE; // blocking, so reset the int33h f11 alert mechanism
+}
+
+void MouseAttachMenuItem(HANDLE hBuff)
+{
+if(!bMouseMenuItemAdded)
+ {
+ //
+ // Read in the relavent string from resource
+ //
+
+ hM = ConsoleMenuControl(hBuff,IDM_POINTER,IDM_POINTER);
+ AppendMenu(hM,MF_STRING,IDM_POINTER,szHideMouseMenuStr);
+ bMouseMenuItemAdded=TRUE;
+
+ //
+ // initial state -> system pointer is ON
+ //
+
+ bPointerOff=FALSE;
+ }
+}
+
+//=========================================================================
+// Function to determine if the active output buffer has changed if the VDM
+// has done something weird like resized or gone from graphics to fullscreen
+// or vice versa. If so, a new handle to the new buffer must be got, and the
+// old menu item deleted and a new menu item attach so that the new buffer
+// "knows" about the menu item I.D.
+//=========================================================================
+
+void MouseReattachMenuItem(HANDLE hBuff)
+{
+static HANDLE hOld = 0; // The handle for the last buffer selected.
+
+//
+// If the output buffer has not changed, then don't do anything.
+//
+
+if(hOld == hBuff)
+ return;
+
+//
+// First thing, remove the old menu item.
+//
+
+MouseDetachMenuItem(TRUE);
+
+//
+// Next, Add in the new menu item for the current buffer.
+//
+
+MouseAttachMenuItem(hBuff);
+
+//
+// Record the value of the latest buffer for next time.
+//
+
+hOld = hBuff;
+}
+
+void MouseHide(void)
+{
+
+ModifyMenu(hM,IDM_POINTER,MF_BYCOMMAND,IDM_POINTER,
+ (LPTSTR)szDisplayMouseMenuStr);
+
+//
+// Clip the pointer to a region inside the console window
+// and move the pointer to the window centre
+//
+
+while(ShowConsoleCursor(sc.ActiveOutputBufferHandle,FALSE)>=0)
+ ;
+MovePointerToWindowCentre();
+bPointerOff=TRUE;
+}
+
+void MouseDisplay(void)
+{
+
+ModifyMenu(hM,IDM_POINTER,MF_BYCOMMAND,IDM_POINTER,
+ (LPTSTR)szHideMouseMenuStr);
+
+//
+// Let the pointer move anywhere on the screen
+//
+
+ClipCursor(NULL);
+while(ShowConsoleCursor(sc.ActiveOutputBufferHandle,TRUE)<0)
+ ;
+bPointerOff=FALSE;
+}
+
+void MovePointerToWindowCentre(void)
+{
+RECT rTemp;
+
+//
+// Get current console client rectangle, set the clipping region to match
+// the client rect. Retrieve the new clipping rect from the system (is
+// different from what we requested!) and save it.
+//
+VDMConsoleOperation(VDM_CLIENT_RECT,&WarpClientRect);
+rTemp = WarpClientRect;
+CToS(&rTemp);
+ClipCursor(&rTemp);
+GetClipCursor(&WarpBorderRect);
+
+//
+// Note : LowerRight clip point is exclusive, UpperLeft point is inclusive
+//
+WarpBorderRect.right--;
+WarpBorderRect.bottom--;
+
+pMiddle.x = ((WarpBorderRect.right - WarpBorderRect.left)>>1)
+ +WarpBorderRect.left;
+pMiddle.y = ((WarpBorderRect.bottom - WarpBorderRect.top)>>1)
+ +WarpBorderRect.top;
+//
+// move the pointer to the centre of the client area
+//
+
+SetCursorPos((int)pMiddle.x,(int)pMiddle.y);
+
+//
+// Prevent the next counter calculation from resulting in a
+// large warp.
+//
+
+pLast = pMiddle;
+}
+
+//=============================================================================
+// Function to convert a rectangle structure from client coordinates to
+// screen coordinates.
+//=============================================================================
+
+void CToS(RECT *r)
+{
+POINT pt;
+
+//
+// Sort out the top, lefthand corner of the rectangle.
+//
+
+pt.x = r->left;
+pt.y = r->top;
+VDMConsoleOperation(VDM_CLIENT_TO_SCREEN,(LPVOID)&pt);
+r->left = pt.x;
+r->top = pt.y;
+
+//
+// Now do the bottom, right hand corner.
+//
+
+pt.x = r->right;
+pt.y = r->bottom;
+VDMConsoleOperation(VDM_CLIENT_TO_SCREEN,(LPVOID)&pt);
+r->right = pt.x;
+r->bottom = pt.y;
+}
+
+
+//=============================================================================
+//
+// Function - EmulateCoordinates.
+// Purpose - When the mouse is hidden by the user in windowed mode, this
+// function generate absolute x,y values from the relative motion
+// of the system pointer between mouse hardware interrupts
+//
+// Returns - Nothing.
+//
+//
+//
+// Author - Andrew Watson.
+// Date - 19-Mar-1994.
+//
+//=============================================================================
+
+void EmulateCoordinates(half_word video_mode,IS16 move_x,IS16 move_y,IS16 *x,IS16 *y)
+{
+static IS16 lastinternalX=0,lastinternalY=0;
+IS16 internalX,internalY;
+
+//
+// If the application has reset the mouse, set the x,y position to
+// the centre of the default virtual screen for the current video mode.
+//
+
+
+if(bFunctionZeroReset)
+ {
+ //
+ // Calculate the centre of the default virtual screen
+ // and set the current generated coordinates to it.
+ //
+
+ internalX = (VirtualX >> 1) - 1;
+ internalY = (VirtualY >> 1) - 1;
+
+ bFunctionZeroReset = FALSE;
+ }
+else if(bFunctionFour)
+ {
+ //
+ // The application has set the pointer to a new location.
+ // Tell the counter emulation about this.
+ //
+
+ internalX = newF4x;
+ internalY = newF4y;
+
+ //
+ // Don't come in here again until the next function 4.
+ //
+
+ bFunctionFour = FALSE;
+ }
+else
+ {
+ //
+ // Generate the new x,y position based on the counter change and
+ // clip to whatever boundary (default or application imposed) has
+ // been selected.
+ //
+
+ internalX = lastinternalX + move_x;
+ internalY = lastinternalY + move_y;
+ LimitCoordinates(video_mode,&internalX,&internalY);
+ }
+
+//
+// Set up the current emulated position for next time through
+// this function.
+//
+
+lastinternalX = internalX;
+lastinternalY = internalY;
+
+//
+// set up the return x,y values.
+//
+
+*x = internalX;
+*y = internalY;
+}
+
+//=============================================================================
+// Function which hooks into the base mechanism for dealing with int 33h and
+// catches the function (AX=0xf) when the application tries to set the default
+// mickey to pixel ratio.
+//=============================================================================
+
+void host_m2p_ratio(word *a, word *b, word *CX, word *DX)
+{
+m2pX = *(short *)CX;
+m2pY = *(short *)DX;
+}
+
+
+//=============================================================================
+//
+// Function - WarpSystem Pointer
+// Purpose - Allows movement vectors to be calculated from the movement of
+// the operating system pointer. This function will not let the
+// the system pointer move out of the client area. This, plus the
+// warping mechanism ensures that the emulated pointer can move
+// forever in any given direction.
+//
+// Returns - TRUE if the system pointer has moved, FALSE if not.
+//
+//
+//
+// Author - Andrew Watson.
+// Date - 19-Mar-1994.
+//
+//=============================================================================
+
+BOOL WarpSystemPointer(IS16 *move_x,IS16 *move_y)
+{
+POINT pt;
+
+//
+// Is the Console window in the same place or changed
+// Update the client rect data accordingly
+//
+
+HasConsoleClientRectChanged();
+
+//
+// Get the current position of the system pointer
+//
+
+GetCursorPos(&pt);
+
+
+//
+// How far has the system pointer moved since the last call.
+//
+
+*move_x = (IS16)(pt.x - pLast.x);
+*move_y = (IS16)(pt.y - pLast.y);
+
+//
+// Do a fast exit if no movement has been determined.
+//
+
+if(*move_x || *move_y)
+ {
+
+ //
+ // The system mouse pointer has moved.
+ // See if the pointer has reached the client area boundary(s)
+ //
+
+ if(pt.y <= WarpBorderRect.top || pt.y >= WarpBorderRect.bottom ||
+ pt.x >= WarpBorderRect.right || pt.x <= WarpBorderRect.left)
+ {
+ //
+ // if the boundary(s) was/were met, warp the pointer to the
+ // client area centre.
+ //
+
+ SetCursorPos((int)pMiddle.x,(int)pMiddle.y);
+
+ //
+ // The current position is now the centre of the client rectangle.
+ // Save this as the counter delta start point for next time.
+ //
+
+ pLast = pMiddle;
+ }
+ else
+ {
+ //
+ // There wasn't a warp.
+ // Update the last known position data for next time through.
+ //
+
+ pLast = pt;
+ }
+ //
+ // The cursor has to moved as determined from the previous and current
+ // system pointer positions.
+ //
+
+ return TRUE;
+ }
+//
+// No movement, so return appropriately.
+//
+
+return FALSE;
+}
+
+//==============================================================================
+// Function to detect if the Console window has moved/resized. If it has, this
+// function updates the WarpBorderRect and the pMiddle structures to reflect
+// this.
+//
+// Returns TRUE if moved/resized, FALSE if not.
+//==============================================================================
+
+BOOL HasConsoleClientRectChanged(void)
+{
+RECT tR;
+
+//
+// If console client rectangle has changed, reset the mouse clipping
+// else nothing to do!
+//
+VDMConsoleOperation(VDM_CLIENT_RECT,&tR);
+
+if (tR.top != WarpClientRect.top ||
+ tR.bottom != WarpClientRect.bottom ||
+ tR.right != WarpClientRect.right ||
+ tR.left != WarpClientRect.left)
+ {
+ CToS(&tR);
+
+#ifdef MONITOR
+ //
+ // Is the warp region an Icon in fullscreen graphics?
+ // Note: An icon has a client rect of 36 x 36 pixels.
+ //
+
+ if((tR.right - tR.left) == 36 && (tR.bottom - tR.top) == 36)
+ {
+ //
+ // Make the warp region the same size as the selected buffer.
+ // The warp rectangle is thus originated about the top, left
+ // hand corner of the screen.
+ //
+
+ tR.top = 0;
+ tR.bottom = mouse_buffer_height;
+ tR.left = 0;
+ tR.right = mouse_buffer_width;
+ CToS(&tR);
+ }
+#endif //MONITOR
+
+ //
+ // Clip the pointer to the new client rectangle, and retrive
+ // the new clipping borders.
+ //
+ ClipCursor(&tR);
+ GetClipCursor(&WarpBorderRect);
+
+ //
+ // Note: LowerRight clip point is exclusive, UpperLeft point is inclusive
+ //
+ WarpBorderRect.right--;
+ WarpBorderRect.bottom--;
+
+
+
+ //
+ // determine the middle point in the new client rectangle
+ //
+
+ pMiddle.x = ((WarpBorderRect.right - WarpBorderRect.left)>>1)
+ +WarpBorderRect.left;
+ pMiddle.y = ((WarpBorderRect.bottom - WarpBorderRect.top)>>1)
+ +WarpBorderRect.top;
+ return TRUE;
+ }
+
+return FALSE;
+}
+
+//==============================================================================
+// Focus sensing routines for the pointer clipping system. Focus events come
+// via the main event loop where the following two modules are called. If
+// the application is using int33hf11, this is detected, and on focus gain or
+// loss, the routines clip or unclip the pointer to the console window.
+//==============================================================================
+
+void MouseInFocus(void)
+{
+MouseAttachMenuItem(sc.ActiveOutputBufferHandle);
+
+//
+// only do when app. uses int33hf11
+//
+
+if(!bPointerOff)
+ return;
+MovePointerToWindowCentre();
+
+//
+// Lose system pointer image again
+//
+
+ShowConsoleCursor(sc.ActiveOutputBufferHandle, FALSE);
+}
+
+void MouseOutOfFocus(void)
+{
+//
+// only do when app. uses int33hf11
+//
+
+if(!bPointerOff)
+ {
+ MouseDetachMenuItem(FALSE);
+ return;
+ }
+
+//
+// Clip the pointer to the whole world (but leave its mother alone)
+//
+
+ClipCursor(NULL);
+
+//
+// Re-enable system pointer image
+//
+
+ShowConsoleCursor(sc.ActiveOutputBufferHandle, TRUE);
+}
+
+/* system memu active, stop cursor clipping */
+void MouseSystemMenuON (void)
+{
+ if (bPointerOff)
+ ClipCursor(NULL);
+}
+/* system menu off, restore clipping */
+void MouseSystemMenuOFF(void)
+{
+ if (bPointerOff)
+ ClipCursor(&WarpBorderRect);
+}
+void ResetMouseOnBlock(void)
+{
+host_ica_lock();
+
+os_pointer_data.x=0;
+os_pointer_data.y=0;
+
+host_ica_unlock();
+}
+#ifdef X86GFX
+
+//============================================================================
+// Function which is called from the 32 bit side (x86 only) when there is
+// a transition from fullscreen text to windowed text. The function restores
+// the background to the last mouse pointer position. This stops a pointer
+// block from remaining in the image, corrupting the display when the system
+// pointer is being used.
+//
+// This function looks into the 16 bit driver's space and points to 4, 16 bit
+// words of data from it, viz:
+//
+// dw offset of pointer into video buffer.
+// dw unused.
+// dw image data to be restored.
+// dw flag = 0 if the background is stored
+//
+// Note: that during a fullscreen switch, 16 bit code cannot be executed,
+// thus the patching of the buffer is done here.
+//============================================================================
+
+void CleanUpMousePointer()
+{
+half_word vm;
+
+//
+// Only execute this routine fully if in TEXT mode
+//
+
+sas_load(0x449,&vm); // Get the current video mode according to the B.D.A.
+
+if(TextOrGraphicsModeLUT[(int)vm] != TEXT_MODE)
+ return;
+
+//
+// If there is a backround stored for the text pointer when it was
+// in fullscreen land, then restore it to the place it came from
+// when windowed.
+//
+
+if(bFullscTextBkgrndSaved)
+ {
+ sas_storew(old_text_addr,text_ptr_bkgrnd);
+
+ //
+ // No background saved now.
+ //
+
+ bFullscTextBkgrndSaved = FALSE;
+ }
+}
+
+#endif //X86GFX
+
+//===========================================================================
+// Function to display the text cursor image for fullscreen text mode.
+// INPUT: x,y pointer virtual cartesian coordinates for text screen buffer.
+// Note: the Y coordinates are received in the sequence 0, 8, 16, 24, 32, ...
+// since a virtual text cell is 8 virtual pixels square.
+//===========================================================================
+
+
+void FullscTextPtr(int x,int y)
+{
+#ifdef X86GFX
+sys_addr text_addr;
+word current_display_page;
+
+//
+// Work out the offset to the current video display page.
+// Grovel around the B.D.A. to find out where the page starts.
+//
+
+sas_loadw(effective_addr(0x40,0x4e),&current_display_page);
+x = (int)((DWORD)x & 0xFFFFFFF8);
+y = (int)((DWORD)y & 0xFFFFFFF8);
+
+//
+// save the character cell behind the next pointer
+// Note: The text cell offset calculated below is based on
+// the following concepts:
+// The virtual character cell size is 8 x 8 virtual pixels.
+// The input data to this function is in virtual pixels.
+// There are 80 text cells in a row = 80 (CHAR:ATTR) words.
+// The >>3<<1 on the x value ensures that the location
+// in the buffer to be modified occurs on a word boundary to
+// get the masking correct!
+//
+
+x &= 0xfffc; // remove the top to prevent funny shifts.
+x >>= 2; // get the word address for the current row
+y &= 0xffff; // work out the total number of locations for all the y rows
+y *= 20; //
+
+//
+// Generate the address in the display buffer at which the pointer
+// should be drawn.
+//
+
+text_addr = effective_addr(0xb800,(word)(current_display_page + x + y)); // assemble the cell address
+
+//
+// only restore the background if there is a background to restore!
+//
+
+if(bFullscTextBkgrndSaved)
+ {
+ sas_storew(old_text_addr,text_ptr_bkgrnd);
+ }
+
+//
+// Load up the background from the new address
+//
+
+sas_loadw(text_addr,&text_ptr_bkgrnd); // read from that place
+bFullscTextBkgrndSaved=TRUE;
+
+//
+// Write the pointer to the video buffer.
+// Use some standard masks and forget what the app wants to
+// do cos that really isn't important and it's slow plus not
+// very many apps want to change the text pointer shape anyway.
+//
+
+sas_storew(text_addr,(word)((text_ptr_bkgrnd & 0x77ff) ^ 0x7700));
+
+//
+// save the static variables to be used next time through the routine
+//
+
+old_text_addr=text_addr;
+
+#endif // X86GFX
+}
+
+//==============================================================================
+// Function to get the maximum and minimum possible virtual pixel locations
+// in X as requested by the application through int 33h function 7.
+//==============================================================================
+
+void host_x_range(word *blah, word *blah2,word *CX,word *DX)
+{
+confine.bF7 = TRUE;
+confine.xmin = *CX;
+confine.xmax = *DX;
+
+//
+// Force a mouse interrupt to make it happen.
+//
+
+ LazyMouseInterrupt();
+}
+
+//==============================================================================
+// Function to get the maximum and minimum possible virtual pixel locations
+// in Y as requested by the application through int 33h function 8.
+//==============================================================================
+
+void host_y_range(word *blah, word *blah2,word *CX,word *DX)
+{
+confine.bF8 = TRUE;
+confine.ymin = *CX;
+confine.ymax = *DX;
+
+//
+// Force a mouse interrupt to make it happen.
+//
+
+ LazyMouseInterrupt();
+}
+
+
+
+/*
+ * LazyMouseInterrupt -
+ *
+ */
+void LazyMouseInterrupt(void)
+{
+ host_ica_lock();
+ if (!bMseEoiPending && !bSuspendMouseInterrupts) {
+ if (MseIntLazyCount)
+ MseIntLazyCount--;
+ bMseEoiPending = TRUE;
+ ica_hw_interrupt(AT_CPU_MOUSE_ADAPTER,AT_CPU_MOUSE_INT,1);
+ HostIdleNoActivity();
+ }
+ else if (!MseIntLazyCount) {
+ MseIntLazyCount++;
+ }
+ host_ica_unlock();
+}
+
+
+/* SuspendMouseInterrupts
+ *
+ * Prevents Mouse Interrupts from occuring until
+ * ResumeMouseInterrupts is called
+ *
+ */
+void SuspendMouseInterrupts(void)
+{
+ host_ica_lock();
+ bSuspendMouseInterrupts = TRUE;
+ host_ica_unlock();
+}
+
+
+/*
+ * ResumeMouseInterrupts
+ *
+ */
+void ResumeMouseInterrupts(void)
+{
+ host_ica_lock();
+ bSuspendMouseInterrupts = FALSE;
+
+ if (!bMseEoiPending &&
+ (MseIntLazyCount || MoreMouseEvents()) )
+ {
+ if (MseIntLazyCount)
+ MseIntLazyCount--;
+ bMseEoiPending = TRUE;
+ host_DelayHwInterrupt(9, // AT_CPU_MOUSE_ADAPTER,AT_CPU_MOUSE_INT
+ 1, // count
+ 10000 // Delay
+ );
+ HostIdleNoActivity();
+ }
+
+ host_ica_unlock();
+}
+
+
+
+/*
+ * DoMouseInterrupt, assumes we are holding the ica lock
+ *
+ */
+void DoMouseInterrupt(void)
+{
+
+ if (bMseEoiPending || bSuspendMouseInterrupts) {
+ MseIntLazyCount++;
+ return;
+ }
+
+ if (MseIntLazyCount)
+ MseIntLazyCount--;
+ bMseEoiPending = TRUE;
+ ica_hw_interrupt(AT_CPU_MOUSE_ADAPTER,AT_CPU_MOUSE_INT,1);
+ HostIdleNoActivity();
+}
+
+
+/*
+ * MouseEoiHook, assumes we are holding the ica lock
+ *
+ */
+VOID MouseEoiHook(int IrqLine, int CallCount)
+{
+
+ if (CallCount < 0) { // interrupts were cancelled
+ MseIntLazyCount = 0;
+ FlushMouseEvents();
+ bMseEoiPending = FALSE;
+ return;
+ }
+
+ if (!bSuspendMouseInterrupts &&
+ (MseIntLazyCount || MoreMouseEvents()))
+ {
+ if (MseIntLazyCount)
+ MseIntLazyCount--;
+ bMseEoiPending = TRUE;
+ host_DelayHwInterrupt(9, // AT_CPU_MOUSE_ADAPTER,AT_CPU_MOUSE_INT
+ 1, // count
+ 10000 // Delay usecs
+ );
+ HostIdleNoActivity();
+ }
+ else {
+ bMseEoiPending = FALSE;
+ }
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_msscs.c b/private/mvdm/softpc.new/host/src/nt_msscs.c
new file mode 100644
index 000000000..d9286056a
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_msscs.c
@@ -0,0 +1,1416 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <vdmapi.h>
+#include <vdm.h>
+#include "insignia.h"
+#include "host_def.h"
+#include "conapi.h"
+#include "ctype.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+#include <io.h>
+#include <fcntl.h>
+
+#include "xt.h"
+#include CpuH
+#include "error.h"
+#include "sas.h"
+#include "ios.h"
+#include "umb.h"
+#include "gvi.h"
+#include "sim32.h"
+#include "bios.h"
+
+#include "nt_eoi.h"
+#include "nt_uis.h"
+#include "nt_event.h"
+#include "nt_graph.h"
+#include "nt_event.h"
+#include "nt_reset.h"
+#include "config.h"
+#include <nt_vdd.h> // DO NOT USE vddsvc.h
+#include <nt_vddp.h>
+#include <host_emm.h>
+#include "emm.h"
+#include <demexp.h>
+#include <vint.h>
+
+PMEM_HOOK_DATA MemHookHead = NULL;
+PVDD_USER_HANDLERS UserHookHead= NULL;
+
+extern BOOL CMDInit (int argc,char *argv[]);
+extern BOOL XMSInit (int argc,char *argv[]);
+extern BOOL DBGInit (int argc,char *argv[]);
+extern DWORD TlsDirectError;
+extern VOID FloppyTerminatePDB(USHORT PDB);
+extern VOID FdiskTerminatePDB(USHORT PDB);
+
+// internal function prototypes
+VOID SetupInstallableVDD (VOID);
+void AddSystemFiles(void);
+
+void scs_init(int argc, char **argv)
+{
+ PSZ psz;
+ BOOL IsFirst;
+
+ IsFirst = GetNextVDMCommand(NULL);
+ if (IsFirst) {
+ AddSystemFiles();
+ }
+
+ // Initialize SCS
+
+ CMDInit (argc,argv);
+
+ // Initialize DOSEm
+
+ if(!DemInit (argc,argv)) {
+ host_error(EG_OWNUP, ERR_QUIT, "NTVDM:DemInit fails");
+ TerminateVDM();
+ }
+
+ // Initialize XMS
+
+ if(!XMSInit (argc,argv)) {
+ host_error(EG_OWNUP, ERR_QUIT, "NTVDM:XMSInit fails");
+ TerminateVDM();
+ }
+
+ // Initialize DBG
+
+ if(!DBGInit (argc,argv)) {
+#ifndef PROD
+ printf("NTVDM:DBGInit fails\n");
+ HostDebugBreak();
+#endif
+ TerminateVDM();
+ }
+}
+
+//
+// This routine contains the Dos Emulation initialisation code, called from
+// main(). We currently do not support container files.
+//
+
+
+InitialiseDosEmulation(int argc, char **argv)
+{
+ HANDLE hFile;
+ DWORD FileSize;
+ DWORD BytesRead;
+ DWORD dw;
+ ULONG fVirtualInt;
+ host_addr pDOSAddr;
+ CHAR buffer[MAX_PATH*2];
+#ifdef LIM
+ LIM_CONFIG_DATA lim_config_data;
+#endif
+
+ //
+ // first order of bussiness, initialize virtual interrupt flag in
+ // dos arena. this has to be done here before it gets changed
+ // by reading in ntio.sys
+ //
+
+ sas_loads((ULONG)FIXED_NTVDMSTATE_LINEAR,
+ (PCHAR)&fVirtualInt,
+ FIXED_NTVDMSTATE_SIZE
+ );
+#ifndef i386
+ fVirtualInt |= MIPS_BIT_MASK;
+#else
+ fVirtualInt &= ~MIPS_BIT_MASK;
+#endif
+ sas_storedw((ULONG)FIXED_NTVDMSTATE_LINEAR,fVirtualInt);
+
+ io_init();
+
+ //
+ // Allocate per thread local storage.
+ // Currently we only need to store one DWORD, so we
+ // don't need any per thread memory.
+ //
+ TlsDirectError = TlsAlloc();
+#ifndef PROD
+ if (TlsDirectError == 0xFFFFFFFF)
+ printf("NTVDM: TlsDirectError==0xFFFFFFFF GLE=%ld\n", GetLastError);
+#endif
+
+
+ // SetupInstallableVDD ();
+
+ /*................................................... Execute reset */
+ reset();
+
+ SetupInstallableVDD ();
+ /* reserve lim block after all vdd are installed.
+ the pif file settings tell us if it is necessary to
+ reserve the block
+ */
+
+#ifdef LIM
+ /* initialize lim page frames after all vdd are installed.
+ the pif file settings tell us if it is necessary to
+ reserve the block.
+ */
+ if (get_lim_configuration_data(&lim_config_data))
+ lim_page_frame_init(&lim_config_data);
+
+#endif
+
+ scs_init(argc, argv); // Initialise single command shell
+
+ /*................................................. Load DOSEM code */
+
+ dw = GetSystemDirectory(buffer, sizeof(buffer));
+ if (!dw || dw >= sizeof(buffer)) {
+ host_error(EG_OWNUP, ERR_QUIT, "NTVDM:InitialiseDosEmulation fails");
+ TerminateVDM();
+ }
+
+ strcat(buffer, "\\ntio.sys");
+
+ hFile = CreateFile(buffer,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+
+ if (hFile == INVALID_HANDLE_VALUE ||
+ !(FileSize = GetFileSize(hFile, &BytesRead)) ||
+ BytesRead )
+ {
+#ifndef PROD
+ printf("NTVDM:Fatal Error, Invalid file or missing - %s\n",buffer);
+#endif
+ host_error(EG_SYS_MISSING_FILE, ERR_QUIT, buffer);
+ if (hFile != INVALID_HANDLE_VALUE) {
+ CloseHandle(hFile);
+ }
+ return (-1);
+ }
+
+
+ pDOSAddr = get_byte_addr(((NTIO_LOAD_SEGMENT<<4)+NTIO_LOAD_OFFSET));
+
+ if (!ReadFile(hFile, pDOSAddr, FileSize, &BytesRead, NULL) ||
+ FileSize != BytesRead)
+ {
+
+#ifndef PROD
+ printf("NTVDM:Fatal Error, Read file error - %s\n",buffer);
+#endif
+ host_error(EG_SYS_MISSING_FILE, ERR_QUIT, buffer);
+ CloseHandle(hFile);
+ return (-1);
+ }
+
+ CloseHandle(hFile);
+
+ // oops ... restore the virtual interrupt state,
+ // which we just overwrote in the file read, and reset.
+ sas_storedw((ULONG)FIXED_NTVDMSTATE_LINEAR, fVirtualInt);
+
+ setCS(NTIO_LOAD_SEGMENT);
+ setIP(NTIO_LOAD_OFFSET); // Start CPU at DosEm initialisation entry point
+
+
+ //
+ // Ensure that WOW VDM runs at NORMAL priorty
+ //
+ if (VDMForWOW) {
+ SetPriorityClass (NtCurrentProcess(), NORMAL_PRIORITY_CLASS);
+ }
+
+ //
+ // Don't allow dos vdm to run at realtime
+ //
+ else if (GetPriorityClass(NtCurrentProcess()) == REALTIME_PRIORITY_CLASS)
+ {
+ SetPriorityClass(NtCurrentProcess(), HIGH_PRIORITY_CLASS);
+ }
+
+
+ return 0;
+}
+
+
+/*
+ * AddSystemFiles
+ *
+ * If the system file IBMDOS.SYS|MSDOS.SYS doesn't exist
+ * in the root of c: create zero len MSDOS.SYS
+ *
+ * If the system file IO.SYS does not exist create
+ * a zero len IO.SYS
+ *
+ * This hack is put in especially for the Brief 3.1 install
+ * program which looks for the system files, and if they are
+ * not found screws up the config.sys file.
+ *
+ */
+void AddSystemFiles(void)
+{
+ HANDLE hFile, hFind;
+ WIN32_FIND_DATA wfd;
+ char *pchIOSYS ="C:\\IO.SYS";
+ char *pchMSDOSSYS ="C:\\MSDOS.SYS";
+
+
+ hFind = FindFirstFile(pchMSDOSSYS, &wfd);
+ if (hFind == INVALID_HANDLE_VALUE) {
+ hFind = FindFirstFile("C:\\IBMDOS.SYS", &wfd);
+ }
+
+ if (hFind != INVALID_HANDLE_VALUE) {
+ FindClose(hFind);
+ }
+ else {
+ hFile = CreateFile(pchMSDOSSYS,
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_READONLY,
+ 0);
+ if (hFile != INVALID_HANDLE_VALUE) { // not much we can do if fails
+ CloseHandle(hFile);
+ }
+
+ }
+
+ hFind = FindFirstFile(pchIOSYS, &wfd);
+ if (hFind == INVALID_HANDLE_VALUE) {
+ hFind = FindFirstFile("C:\\IBMBIO.SYS", &wfd);
+ }
+
+ if (hFind != INVALID_HANDLE_VALUE) {
+ FindClose(hFind);
+ }
+ else {
+ hFile = CreateFile(pchIOSYS,
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_READONLY,
+ 0);
+ if (hFile != INVALID_HANDLE_VALUE) { // not much we can do if fails
+ CloseHandle(hFile);
+ }
+
+ }
+}
+
+
+#ifdef LIM
+/* parse EMM= line in config.nt to collect EMM parameters. The EMM line has
+ * the following syntax:
+ * EMM=[a=altregs][b=segment][i=segment1-segment2][x=segment1-segment2] [RAM]
+ * where "a=altregs" specifies how many alternative mapping register set
+ * "b=segment" specifies the backfill starting segment address.
+ * "RAM" indicates that the system should only allocate 64KB from
+ * UMB to use as EMM page frame.
+ * "i=segment1 - segment2" specifies a particular range of
+ * address that the system should include as EMM page frame
+ * "x=segment1 - segment2" specifies a particular range of
+ * address that the system should NOT use as page frame.
+ *
+ * input: pointer to LIM_PARAMS
+ * output: LIM_PARAMS is filled with data
+ *
+ */
+
+#define IS_EOL_CHAR(c) (c == '\n' || c == '\r' || c == '\0')
+#define SKIP_WHITE_CHARS(size, ptr) while (size && isspace(*ptr)) \
+ { ptr++; size--; }
+
+#define TOINT(c) ((c >= '0' && c <= '9') ? (c - '0') : \
+ ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) : \
+ ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) : 0) \
+ )\
+ )
+
+boolean init_lim_configuration_data(PLIM_CONFIG_DATA lim_data)
+{
+ char config_sys_pathname[MAX_PATH];
+ HANDLE handle;
+ DWORD file_size, bytes_read, size;
+ char *buffer, *ptr;
+ short lim_size, base_segment, total_altreg_sets;
+ boolean ram_flag_found, reserve_umb_status, parsing_error;
+ sys_addr page_frame;
+ int i;
+
+
+ /* initialize some default values */
+ base_segment = 0x4000;
+ total_altreg_sets = 8;
+ ram_flag_found = FALSE;
+
+ parsing_error = FALSE;
+
+ /* if we can not find config.nt, we can not go on */
+ GetPIFConfigFiles(TRUE, config_sys_pathname);
+ if (*config_sys_pathname == '\0')
+ return FALSE;
+
+ handle = CreateFile(config_sys_pathname,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if (handle == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ file_size = GetFileSize(handle, NULL);
+ if (file_size == 0 || file_size == 0xFFFFFFFF) {
+ CloseHandle(handle);
+ return FALSE;
+ }
+ buffer = malloc(file_size);
+ if (buffer == NULL) {
+ CloseHandle(handle);
+ host_error(EG_MALLOC_FAILURE, ERR_QUIT, "");
+ return FALSE;
+ }
+ if (!ReadFile(handle, buffer, file_size, &bytes_read, NULL) ||
+ bytes_read != file_size)
+ {
+ CloseHandle(handle);
+ free(buffer);
+ return FALSE;
+ }
+ CloseHandle(handle);
+
+ ptr = buffer;
+
+ while(file_size) {
+ /* skip leading white characters on each line */
+ SKIP_WHITE_CHARS(file_size, ptr);
+ /* nothing meaningful in the file, break */
+ if (!file_size)
+ break;
+ /* looking for EMM */
+ if (file_size < 3 || toupper(ptr[0]) != 'E' ||
+ toupper(ptr[1]) != 'M' || toupper(ptr[2]) != 'M')
+ {
+ /* we don't want this line, skip it by looking for the first EOL
+ * char in the line
+ */
+ do {
+ file_size--;
+ ptr++;
+ } while(file_size && !IS_EOL_CHAR(*ptr));
+
+ /* either there are nothing left in the file or we have EOL
+ * char(s) in the line, loop through to skip all consecutive
+ * EOL char(s)
+ */
+ while(file_size && IS_EOL_CHAR(*ptr)) {
+ file_size--;
+ ptr++;
+ }
+ }
+ else {
+ /* got "EMM", looking for '=' */
+ file_size -= 3;
+ ptr += 3;
+ SKIP_WHITE_CHARS(file_size, ptr);
+ if (!file_size || *ptr != '=')
+ parsing_error = TRUE;
+ else {
+ file_size--;
+ ptr++;
+ SKIP_WHITE_CHARS(file_size, ptr);
+ /* "EMM=" is a valid EMM command line */
+ }
+ break;
+ }
+ }
+ /* we have three possibilities here:
+ * (1). we found pasring error while we were looking for "EMM="
+ * (2). no "EMM=" line was found
+ * (3). "EMM=" was found and ptr points to the first nonwhite
+ * char after '='.
+ */
+ while (file_size && !parsing_error && !IS_EOL_CHAR(*ptr)) {
+ SKIP_WHITE_CHARS(file_size, ptr);
+ switch (*ptr) {
+ case 'a':
+ case 'A':
+
+ /* no white chars allowed between 'a' and its
+ * parameter
+ */
+ if (!(--file_size) || *(++ptr) != '='){
+ parsing_error = TRUE;
+ break;
+ }
+ file_size--;
+ ptr++;
+ /* about to parsing 'a=' switch, reset the preset value to 0 */
+ total_altreg_sets = 0;
+
+ while(file_size && isdigit(*ptr)) {
+ total_altreg_sets = total_altreg_sets * 10 + (*ptr - '0');
+ file_size--;
+ ptr++;
+ if (total_altreg_sets > 255) {
+ parsing_error = TRUE;
+ break;
+ }
+ }
+ if (!total_altreg_sets || total_altreg_sets > 255)
+ parsing_error = TRUE;
+ break;
+
+ case 'b':
+ case 'B':
+ /* no white chars allowed between 'b' and its
+ * parameter
+ */
+ if (!(--file_size) || *(++ptr) != '='){
+ parsing_error = TRUE;
+ break;
+ }
+ file_size--;
+ ptr++;
+ base_segment = 0;
+ while(file_size && isxdigit(*ptr)) {
+ base_segment = (base_segment << 4) + TOINT(*ptr);
+ file_size--;
+ ptr++;
+ if (base_segment > 0x4000) {
+ parsing_error = TRUE;
+ break;
+ }
+ }
+ /* x01000 <= base_segment <= 0x4000 */
+
+ if (base_segment >= 0x1000 && base_segment <= 0x4000)
+ /* round down the segment to EMM_PAGE_SIZE boundary */
+ base_segment = ((((ULONG)base_segment * 16) / EMM_PAGE_SIZE)
+ * EMM_PAGE_SIZE) / 16;
+ else
+ parsing_error = TRUE;
+ break;
+
+ case 'r':
+ case 'R':
+ if (file_size >= 3 &&
+ (ptr[1] == 'a' || ptr[1] == 'A') &&
+ (ptr[2] == 'm' || ptr[2] == 'M'))
+ {
+ file_size -= 3;
+ ptr += 3;
+ ram_flag_found = TRUE;
+ break;
+ }
+ /* fall through if it is not RAM */
+
+ default:
+ parsing_error = TRUE;
+ break;
+ } /* switch */
+
+ } /* while */
+
+ free(buffer);
+ if (parsing_error) {
+ host_error(EG_BAD_EMM_LINE, ERR_QUIT, "");
+ /* reset parameters because the emm command line is not reliable */
+ base_segment = 0x4000;
+ total_altreg_sets = 8;
+ ram_flag_found = FALSE;
+ }
+
+ /* we got here if (1). no parsing error or (2). user opted to ignore
+ * the parsing error
+ */
+
+ lim_data->total_altreg_sets = total_altreg_sets;
+
+ lim_data->backfill = (640 * 1024) - (base_segment * 16);
+
+ lim_data->base_segment = base_segment;
+ lim_data->use_all_umb = !ram_flag_found;
+
+#ifdef EMM_DEBUG
+ printf("base segment=%x, backfill =%lx; altreg sets=%d\n",
+ base_segment, lim_data->backfill, total_altreg_sets);
+#endif
+
+ return TRUE;
+}
+
+unsigned short get_lim_page_frames(USHORT * page_table,
+ PLIM_CONFIG_DATA lim_data
+ )
+{
+
+ USHORT total_phys_pages, base_segment, i;
+ BOOL reserve_umb_status;
+ ULONG page_frame, size;
+
+ /* we search for the primary EMM page frame first from 0xE0000.
+ * if we can not find it there, then look for anywhere in UMB area.
+ * if the primary EMM page frame is found, and RAM is not specified,
+ * collect every possible page frame in the UMB.
+ * if RAM has been specified, only allocate the primary page frame.
+ */
+ total_phys_pages = 0;
+ base_segment = lim_data->base_segment;
+ reserve_umb_status = FALSE;
+
+ /* specificaly ask for 0xE0000 */
+ page_frame = 0xE0000;
+ /* primary page frames are always EMM_PAGE_SIZE * 4 */
+ size = EMM_PAGE_SIZE * 4;
+ reserve_umb_status = ReserveUMB(UMB_OWNER_EMM, (PVOID *)&page_frame, &size);
+ /* if failed to find the primary page frame at 0xE0000, search for anywhere
+ * available in the UMB area
+ */
+ if (!reserve_umb_status) {
+ page_frame = 0;
+ size = 0x10000;
+ reserve_umb_status = ReserveUMB(UMB_OWNER_EMM, (PVOID *)&page_frame, &size);
+ }
+ if (!reserve_umb_status) {
+#ifdef EMM_DEBUG
+ printf("couldn't find primary page frame\n");
+#endif
+ return FALSE;
+ }
+ page_table[0] = (short)(page_frame / 16);
+ page_table[1] = (short)((page_frame + 1 * EMM_PAGE_SIZE) / 16);
+ page_table[2] = (short)((page_frame + 2 * EMM_PAGE_SIZE) / 16);
+ page_table[3] = (short)((page_frame + 3 * EMM_PAGE_SIZE) / 16);
+
+
+ total_phys_pages = 4;
+
+ /* now add back fill page frames */
+ for (i = lim_data->backfill / EMM_PAGE_SIZE; i != 0 ; i--) {
+ page_table[total_phys_pages++] = base_segment;
+ base_segment += EMM_PAGE_SIZE / 16;
+ }
+
+ /* RAM is not specified in the command line, grab every possible
+ * page frame from UMB
+ */
+ if (lim_data->use_all_umb) {
+ while (TRUE) {
+ page_frame = 0;
+ size = EMM_PAGE_SIZE;
+ if (ReserveUMB(UMB_OWNER_EMM, (PVOID *)&page_frame, &size))
+ page_table[total_phys_pages++] = (short)(page_frame / 16);
+ else
+ break;
+ }
+ }
+
+#ifdef EMM_DEBUG
+ printf("page frames:\n");
+ for (i = 0; i < total_phys_pages; i++)
+ printf("page number %d, segment %x\n",i, page_table[i]);
+#endif
+ return total_phys_pages;
+}
+#endif /* LIM */
+
+
+VOID SetupInstallableVDD (VOID)
+{
+HANDLE hVDD;
+HKEY VDDKey;
+CHAR szClass [MAX_CLASS_LEN];
+DWORD dwClassLen = MAX_CLASS_LEN;
+DWORD nKeys,cbMaxKey,cbMaxClass,nValues=0,cbMaxValueName,cbMaxValueData,dwSec;
+DWORD dwType;
+PCHAR pszName,pszValue;
+FILETIME ft;
+PCHAR pKeyName = "SYSTEM\\CurrentControlSet\\Control\\VirtualDeviceDrivers";
+
+ if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE,
+ pKeyName,
+ 0,
+ KEY_QUERY_VALUE,
+ &VDDKey
+ ) != ERROR_SUCCESS){
+ RcErrorDialogBox(ED_REGVDD, pKeyName, NULL);
+ return;
+ }
+
+ pszName = "VDD";
+
+ // get size of VDD value
+ if (RegQueryInfoKey (VDDKey,
+ (LPTSTR)szClass,
+ &dwClassLen,
+ NULL,
+ &nKeys,
+ &cbMaxKey,
+ &cbMaxClass,
+ &nValues,
+ &cbMaxValueName,
+ &cbMaxValueData,
+ &dwSec,
+ &ft
+ ) != ERROR_SUCCESS) {
+ RcErrorDialogBox(ED_REGVDD, pKeyName, pszName);
+ RegCloseKey (VDDKey);
+ return;
+ }
+
+
+ // alloc temp memory for the VDD value (multi-string)
+ if ((pszValue = (PCHAR) malloc (cbMaxValueData)) == NULL) {
+ RcErrorDialogBox(ED_MEMORYVDD, pKeyName, pszName);
+ RegCloseKey (VDDKey);
+ return;
+ }
+
+
+ // finally get the VDD value (multi-string)
+ if (RegQueryValueEx (VDDKey,
+ (LPTSTR)pszName,
+ NULL,
+ &dwType,
+ (LPBYTE)pszValue,
+ &cbMaxValueData
+ ) != ERROR_SUCCESS || dwType != REG_MULTI_SZ) {
+ RcErrorDialogBox(ED_REGVDD, pKeyName, pszName);
+ RegCloseKey (VDDKey);
+ free (pszValue);
+ return;
+ }
+
+ pszName = pszValue;
+
+ while (*pszValue) {
+ if ((hVDD = SafeLoadLibrary(pszValue)) == NULL){
+ RcErrorDialogBox(ED_LOADVDD, pszValue, NULL);
+ }
+ pszValue =(PCHAR)strchr (pszValue,'\0') + 1;
+ }
+
+ RegCloseKey (VDDKey);
+ free (pszName);
+ return;
+}
+
+/*** VDDInstallMemoryHook - This service is provided for VDDs to hook the
+ * Memory Mapped IO addresses they are resposible
+ * for.
+ *
+ * INPUT:
+ * hVDD : VDD Handle
+ * addr : Starting linear address
+ * count : Number of bytes
+ * MemoryHandler : VDD handler for the memory addresses
+ *
+ *
+ * OUTPUT
+ * SUCCESS : Returns TRUE
+ * FAILURE : Returns FALSE
+ * GetLastError has the extended error information.
+ *
+ * NOTES
+ * 1. The first one to hook an address will get the control. There
+ * is no concept of chaining the hooks. VDD should grab the
+ * memory range in its initialization routine. After all
+ * the VDDs are loaded, EMM will eat up all the remaining
+ * memory ranges for UMB support.
+ *
+ * 2. Memory handler will be called with the address on which the
+ * page fault occured. It wont say whether it was a read operation
+ * or write operation or what were the operand value. If a VDD
+ * is interested in such information it has to get the CS:IP and
+ * decode the instruction.
+ *
+ * 3. On returning from the hook handler it will be assumed that
+ * the page fault was handled and the return will go back to the
+ * VDM.
+ *
+ * 4. Installing a hook on a memory range will result in the
+ * consumption of memory based upon page boundaries. The Starting
+ * address is rounded down, and the count is rounded up to the
+ * next page boundary. The VDD's memory hook handler will be
+ * invoked for all addreses within the page(s) hooked. The page(s)
+ * will be set aside as mapped reserved sections, and will no
+ * longer be available for use by NTVDM or other VDDs. The VDD is
+ * permitted to manipulate the memory (commit, free, etc) as needed.
+ *
+ * 5. After calling the MemoryHandler, NTVDM will return to the
+ * faulting cs:ip in the 16bit app. If the VDD does'nt want
+ * that to happen it should adjust cs:ip appropriatly by using
+ * setCS and setIP.
+ */
+
+BOOL VDDInstallMemoryHook (
+ HANDLE hVDD,
+ PVOID pStart,
+ DWORD count,
+ PVDD_MEMORY_HANDLER MemoryHandler
+ )
+{
+PMEM_HOOK_DATA pmh = MemHookHead,pmhNew,pmhLast=NULL;
+
+ DWORD dwStart;
+
+
+ if (count == 0 || pStart == (PVOID)NULL || count > 0x20000) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ // round addr down to next page boundary
+ // round count up to next page boundary
+ dwStart = (DWORD)pStart & ~(HOST_PAGE_SIZE-1);
+ count += (DWORD)pStart - dwStart;
+ count = (count + HOST_PAGE_SIZE - 1) & ~(HOST_PAGE_SIZE-1);
+
+ if (dwStart < 0xC0000) {
+ SetLastError (ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ while (pmh) {
+ // the requested block can never be overlapped with any other
+ // existing blocks
+ if(dwStart >= pmh->StartAddr + pmh->Count ||
+ dwStart + count <= pmh->StartAddr){
+ pmhLast = pmh;
+ pmh = pmh->next;
+ continue;
+ }
+
+ // failure case
+ SetLastError (ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ if ((pmhNew = (PMEM_HOOK_DATA) malloc (sizeof(MEM_HOOK_DATA))) == NULL) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ // the request block is not overlapped with existing blocks,
+ // request the UMB managing function to allocate the block
+ if (!ReserveUMB(UMB_OWNER_VDD, (PVOID *)&dwStart, &count)) {
+ free(pmhNew);
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ // now set up the new node to get to know it
+ pmhNew->Count = count;
+ pmhNew->StartAddr = dwStart;
+ pmhNew->hvdd = hVDD;
+ pmhNew->MemHandler = MemoryHandler;
+ pmhNew->next = NULL;
+
+ // Check if the record is to be added in the begining
+ if (MemHookHead == NULL || pmhLast == NULL) {
+ MemHookHead = pmhNew;
+ return TRUE;
+ }
+
+ pmhLast->next = pmhNew;
+ return TRUE;
+}
+
+/*** VDDDeInstallMemoryHook - This service is provided for VDDs to unhook the
+ * Memory Mapped IO addresses.
+ *
+ * INPUT:
+ * hVDD : VDD Handle
+ * addr : Starting linear address
+ * count : Number of addresses
+ *
+ * OUTPUT
+ * None
+ *
+ * NOTES
+ * 1. On Deinstalling a hook, the memory range becomes invalid.
+ * VDM's access of this memory range will cause a page fault.
+ *
+ */
+
+BOOL VDDDeInstallMemoryHook (
+ HANDLE hVDD,
+ PVOID pStart,
+ DWORD count
+ )
+{
+PMEM_HOOK_DATA pmh = MemHookHead,pmhLast=NULL;
+
+ DWORD dwStart;
+
+ if (count == 0 || pStart == (PVOID)NULL || count > 0x20000) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ // round addr down to next page boundary
+ // round count up to next page boundary
+ dwStart = (DWORD)pStart & ~(HOST_PAGE_SIZE-1);
+ count += (DWORD)pStart - dwStart;
+ count = (count + HOST_PAGE_SIZE - 1) & ~(HOST_PAGE_SIZE-1);
+ while (pmh) {
+ if (pmh->hvdd == hVDD &&
+ pmh->StartAddr == dwStart &&
+ pmh->Count == count ) {
+ if (pmhLast)
+ pmhLast->next = pmh->next;
+ else
+ MemHookHead = pmh->next;
+
+ // free the UMB for other purpose.
+ // Note that VDDs may have committed memory for their memory
+ // hook and forgot to decommit the memory before calling
+ // this function. If that is the case, the ReleaseUMB will take
+ // care of this. It is because we want to maintain a single
+ // version of VDD support routines while move platform depedend
+ // routines into the other module.
+ if (ReleaseUMB(UMB_OWNER_VDD,(PVOID)dwStart, count)) {
+ // free the node.
+ free(pmh);
+ return TRUE;
+ }
+ else {
+ printf("Failed to release VDD memory\n");
+ }
+ }
+ pmhLast = pmh;
+ pmh = pmh->next;
+ }
+ SetLastError (ERROR_INVALID_PARAMETER);
+ return FALSE;
+}
+
+
+
+BOOL
+VDDAllocMem(
+HANDLE hVDD,
+PVOID pStart,
+DWORD count
+)
+{
+ PMEM_HOOK_DATA pmh = MemHookHead;
+ DWORD dwStart;
+
+ if (count == 0 || pStart == (PVOID)NULL || count > 0x20000) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+ // round addr down to next page boundary
+ // round count up to next page boundary
+ dwStart = (DWORD)pStart & ~(HOST_PAGE_SIZE-1);
+ count += (DWORD)pStart - dwStart;
+ count = (count + HOST_PAGE_SIZE - 1) & ~(HOST_PAGE_SIZE-1);
+
+ while(pmh) {
+ if (pmh->hvdd == hVDD &&
+ pmh->StartAddr <= dwStart &&
+ pmh->StartAddr + pmh->Count >= dwStart + count)
+ return(VDDCommitUMB((PVOID)dwStart, count));
+ pmh = pmh->next;
+ }
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+}
+
+
+BOOL
+VDDFreeMem(
+HANDLE hVDD,
+PVOID pStart,
+DWORD count
+)
+{
+ PMEM_HOOK_DATA pmh = MemHookHead;
+ DWORD dwStart;
+
+
+ if (count == 0 || pStart == (PVOID)NULL || count > 0x20000) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+ // round addr down to next page boundary
+ // round count up to next page boundary
+ dwStart = (DWORD)pStart & ~(HOST_PAGE_SIZE-1);
+ count += (DWORD)pStart - dwStart;
+ count = (count + HOST_PAGE_SIZE - 1) & ~(HOST_PAGE_SIZE-1);
+
+ while(pmh) {
+ if (pmh->hvdd == hVDD &&
+ pmh->StartAddr <= dwStart &&
+ pmh->StartAddr + pmh->Count >= dwStart + count)
+ return(VDDDeCommitUMB((PVOID)dwStart, count));
+ pmh = pmh->next;
+ }
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+}
+
+
+ // Will publish the following two functions someday.
+ // Please change ntvdm.def, nt_vdd.h and nt_umb.c
+ // if you remove the #if 0
+BOOL
+VDDIncludeMem(
+HANDLE hVDD,
+PVOID pStart,
+DWORD count
+)
+{
+ DWORD dwStart;
+
+ if (count == 0 || pStart == NULL){
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+ // round addr down to next page boundary
+ // round count up to next page boundary
+ dwStart = (DWORD)pStart & ~(HOST_PAGE_SIZE-1);
+ count += (DWORD)pStart - dwStart;
+ count = (count + HOST_PAGE_SIZE - 1) & ~(HOST_PAGE_SIZE-1);
+ return(ReserveUMB(UMB_OWNER_NONE, (PVOID *) &dwStart, &count));
+}
+
+BOOL
+VDDExcludeMem(
+HANDLE hVDD,
+PVOID pStart,
+DWORD count
+)
+{
+
+ DWORD dwStart;
+
+ if (count == 0 || pStart == NULL) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+ // round addr down to next page boundary
+ // round count up to next page boundary
+ dwStart = (DWORD)pStart & ~(HOST_PAGE_SIZE-1);
+ count += (DWORD)pStart - dwStart;
+ count = (count + HOST_PAGE_SIZE - 1) & ~(HOST_PAGE_SIZE-1);
+ return(ReserveUMB(UMB_OWNER_ROM, (PVOID *) &dwStart, &count));
+}
+
+
+
+VOID
+VDDTerminateVDM()
+{
+ TerminateVDM();
+}
+
+VOID DispatchPageFault (
+ ULONG FaultAddr,
+ ULONG RWMode
+ )
+{
+PMEM_HOOK_DATA pmh = MemHookHead;
+
+ // dispatch intel linear address always
+ FaultAddr -= (ULONG)Sim32GetVDMPointer(0, 0, FALSE);
+ // Find the VDD and its handler which is to be called for this fault
+ while (pmh) {
+ if (pmh->StartAddr <= FaultAddr &&
+ FaultAddr <= (pmh->StartAddr + pmh->Count)) {
+
+ // Call the VDD's memory hook handler
+ (*pmh->MemHandler) ((PVOID)FaultAddr, RWMode);
+ return;
+ }
+ else {
+ pmh = pmh->next;
+ continue;
+ }
+ }
+
+ // A page fault occured on an address for which we could'nt find a
+ // VDD. Raise the exception.
+ RaiseException ((DWORD)STATUS_ACCESS_VIOLATION,
+ EXCEPTION_NONCONTINUABLE,
+ 0,
+ NULL);
+
+}
+
+
+/**
+ *
+ * Input - TRUE means redirection is effective
+ * FALSE means no redirection
+ *
+ * This routine will get called after every GetNextVDMCommand i.e.
+ * on every DOS app that a user runs from the prompt. I think
+ * you can safely ignore this callout for WOW.
+ *
+ **/
+void nt_std_handle_notification (BOOL fIsRedirection)
+{
+ /*
+ ** Set global so we know when redirection is active.
+ */
+
+ stdoutRedirected = fIsRedirection;
+
+#ifdef X86GFX
+
+ if( !fIsRedirection && sc.ScreenState==FULLSCREEN )
+ {
+ half_word mode = 3,
+ lines = 0;
+
+ //
+ // WORD 6 and other apps cause this code path to be followed
+ // on application startup. now if line==0, SelectMouseBuffer
+ // causes a 640 x 200 buffer to be selected. This is not
+ // correct if the app is in a 43 or 50 text line mode.
+ // Therefore, since the BIOS data area location 40:84 holds
+ // the number of rows - 1 at this point (if the app uses int 10h
+ // function 11 to change mode) then pick up the correct value
+ // from here. Andy!
+
+ if(sc.ModeType == TEXT)
+ {
+ sas_load(0x484,&lines);
+
+ //
+ // The value is pulled from the BIOS data area.
+ // This is one less than the number of rows. So
+ // increment to give SelectMouseBuffer what it
+ // expects. Let this function do the necessary
+ // handling of non 25, 43 and 50 values.
+ //
+
+ lines++;
+ }
+
+ SelectMouseBuffer(mode, lines);
+ }
+#endif //X86GFX
+}
+
+/*** VDDInstallUserHook
+ *
+ * This service is provided for VDDs to hook callback events.
+ * These callback events include, PDB (DOS Process) creation, PDB
+ * termination, VDM block and VDM resume. Whenever DOS creates (
+ * for example int21/exec) or terminates (for example int21/exit)
+ * a 16bit process VDD could get a notification for that. A VDM in
+ * which a DOS app runs, is attached to the console window in which
+ * the DOS app is running. VDM gets created when first DOS binary
+ * runs in that console. When that DOS binary terminates, VDM stays
+ * with the console window and waits for the next DOS binary to be
+ * launched. When VDM is waiting for this next DOS binary all its
+ * components including VDDs should block. For this purpose, VDDs
+ * could hook VDM Block and Resume events. On Block event VDDs
+ * should block all their worker threads and cleanup any other
+ * operation they might have started. On resume they can restart
+ * worker threads.
+ *
+ * INPUT:
+ * hVDD : VDD Handle
+ * Ucr_handler: handle on creating function (OPTIONAL)
+ * Entry - 16bit DOS PDB
+ * EXIT - None
+ * Uterm_handler: handle on terminating function (OPTIONAL)
+ * Entry - 16bit DOS PDB
+ * EXIT - None
+ * Ublock_handler: handle on block (of ntvdm) function (OPTIONAL)
+ * Entry - None
+ * EXIT - None
+ * Uresume_handler: handle on resume (of ntvdm) function (OPTIONAL)
+ * Entry - None
+ * EXIT - None
+ *
+ * OUTPUT
+ * SUCCESS : Returns TRUE
+ * FAILURE : Returns FALSE
+ * GetLastError has the extended error information.
+ *
+ * NOTES:
+ * If hvdd in not valid it will return ERROR_INVALID_PARAMETER.
+ * VDD can provide whatever event hook they may choose. Not providing
+ * any handler has no effect. There are lots of requests in DOS world
+ * for which there is no explicit Close operation. For instance
+ * printing via int17h. A VDD supporting printing will never be able to
+ * detect when to flush the int17 characters, if its spolling them.
+ * But with the help of PDB create/terminate the VDD can achieve it.
+ */
+
+BOOL VDDInstallUserHook (
+ HANDLE hVDD,
+ PFNVDD_UCREATE Ucr_Handler,
+ PFNVDD_UTERMINATE Uterm_Handler,
+ PFNVDD_UBLOCK Ublock_handler,
+ PFNVDD_URESUME Uresume_handler
+)
+{
+ PVDD_USER_HANDLERS puh = UserHookHead;
+ PVDD_USER_HANDLERS puhNew;
+
+
+ if (!hVDD) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if ((puhNew = (PVDD_USER_HANDLERS) malloc (sizeof(VDD_USER_HANDLERS))) == NULL) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ // now set up the new node to get to know it
+ puhNew->hvdd = hVDD;
+ puhNew->ucr_handler = Ucr_Handler;
+ puhNew->uterm_handler = Uterm_Handler;
+ puhNew->ublock_handler = Ublock_handler;
+ puhNew->uresume_handler = Uresume_handler;
+
+ // Check if the record is to be added in the begining
+ if (UserHookHead == NULL) {
+ puhNew->next = NULL;
+ UserHookHead = puhNew;
+ return TRUE;
+ }
+
+ puhNew->next = UserHookHead;
+ UserHookHead = puhNew;
+ return TRUE;
+}
+
+/*** VDDDeInstallUserHook
+ *
+ * This service is provided for VDDs to unhook callback events.
+ *
+ * INPUT:
+ * hVDD : VDD Handle
+ *
+ * OUTPUT
+ * SUCCESS : Returns TRUE
+ * FAILURE : Returns FALSE
+ * GetLastError has the extended error information.
+ *
+ * NOTES
+ * This service will deinstall all the events hooked earlier
+ * using VDDInstallUserHook.
+ */
+
+BOOL VDDDeInstallUserHook (
+ HANDLE hVDD)
+{
+
+ PVDD_USER_HANDLERS puh = UserHookHead;
+ PVDD_USER_HANDLERS puhLast = NULL;
+
+
+ if (!hVDD) {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ while (puh) {
+ if (puh->hvdd == hVDD) {
+
+ if (puhLast)
+ puhLast->next = puh->next;
+ else
+ UserHookHead = puh->next;
+
+ free(puh);
+ return TRUE;
+ }
+ puhLast = puh;
+ puh = puh->next;
+ }
+
+ SetLastError (ERROR_INVALID_PARAMETER);
+ return FALSE;
+}
+
+/*** VDDTerminateUserHook - This service is provided for VDDs to hook
+ * for callback services
+ *
+ * INPUT:
+ * USHORT DosPDB
+ *
+ * OUTPUT
+ * None
+ *
+ */
+
+VOID VDDTerminateUserHook(USHORT DosPDB)
+{
+
+ PVDD_USER_HANDLERS puh = UserHookHead;
+
+ while(puh) {
+ if(puh->uterm_handler)
+ (puh->uterm_handler)(DosPDB);
+ puh = puh->next;
+ }
+ return;
+}
+
+/*** VDDCreateUserHook - This service is provided for VDDs to hook
+ * for callback services
+ *
+ * INPUT:
+ * USHORT DosPDB
+ *
+ * OUTPUT
+ * None
+ *
+ */
+
+VOID VDDCreateUserHook(USHORT DosPDB)
+{
+
+ PVDD_USER_HANDLERS puh = UserHookHead;
+
+ while(puh) {
+ if(puh->ucr_handler)
+ (puh->ucr_handler)(DosPDB);
+ puh = puh->next;
+ }
+ return;
+}
+
+/*** VDDBlockUserHook - This service is provided for VDDs to hook
+ * for callback services
+ *
+ * INPUT:
+ * None
+ *
+ * OUTPUT
+ * None
+ *
+ */
+
+VOID VDDBlockUserHook(VOID)
+{
+
+ PVDD_USER_HANDLERS puh = UserHookHead;
+
+ while(puh) {
+ if(puh->ublock_handler)
+ (puh->ublock_handler)();
+ puh = puh->next;
+ }
+ return;
+}
+
+/*** VDDResumeUserHook - This service is provided for VDDs to hook
+ * for callback services
+ *
+ * INPUT:
+ * None
+ *
+ * OUTPUT
+ * None
+ *
+ */
+
+VOID VDDResumeUserHook(VOID)
+{
+
+ PVDD_USER_HANDLERS puh = UserHookHead;
+
+ while(puh) {
+ if(puh->uresume_handler)
+ (puh->uresume_handler)();
+ puh = puh->next;
+ }
+ return;
+}
+
+/*** VDDSimulate16
+ *
+ * This service causes the simulation of intel instructions to start.
+ *
+ * INPUT
+ * None
+ *
+ * OUTPUT
+ * None
+ *
+ * NOTES
+ * This service is similar to VDDSimulateInterrupt except that
+ * it does'nt require a hardware interrupt to be supported by the
+ * 16bit stub device driver. This service allows VDD to execute
+ * a routine in its 16bit driver and come back when its done, kind
+ * of a far call. Before calling VDDSimulate16, VDD should preserve
+ * all the 16bit registers which its routine might destroy. Minimally
+ * it should at least preserve cs and ip. Then it should set the
+ * cs and ip for the 16bit routine. VDD could also use registers
+ * like ax,bx.. to pass parametrs to its 16bit routines. At the
+ * end of the 16bit routine VDDUnSimulate16 macro should be used
+ * which will send the control back to the VDD just after the
+ * call VDDSimulate16. Note very carefully that this simulation
+ * to 16bit is synchronous, i.e. VDD gets blocked in VDDSimulate16
+ * and only comes back when stub-driver does a VDDUnSimulate16.
+ * Here is an example:
+ *
+ * vdd:
+ * SaveCS = getCS();
+ * SaveIP = getIP();
+ * SaveAX = getAX();
+ * setCS (16BitRoutineCS);
+ * setIP (16BitRoutineIP);
+ * setAX (DO_X_OPERATION);
+ * VDDSimulate16 ();
+ * setCS (SavwCS);
+ * setIP (SaveIP);
+ * setAX (SaveAX);
+ * ..
+ * ..
+ *
+ * Stub Driver: (Initialization part)
+ *
+ * RegisterModule ; Loads VDD
+ * push cs
+ * pop ax
+ * mov bx, offset Simulate16
+ * DispatchCall ; Passes the address of worker
+ * ; routine to VDD in ax:bx.
+ *
+ * Stub Driver (Run Time)
+ *
+ * Simulate16:
+ * ..
+ * .. ; do the operation index passed in ax
+ *
+ * VDDUnSimulate16
+ *
+ */
+
+VOID VDDSimulate16(VOID)
+{
+ cpu_simulate();
+}
+
+VOID HostTerminatePDB(USHORT PDB)
+{
+ FloppyTerminatePDB(PDB);
+ FdiskTerminatePDB(PDB);
+
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_munge.c b/private/mvdm/softpc.new/host/src/nt_munge.c
new file mode 100644
index 000000000..5c48df4ee
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_munge.c
@@ -0,0 +1,556 @@
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : Win32 mungeing routines.
+ *
+ * Description : This module contains the functions required to produce
+ * destination compatible pixel patterns from SoftPC video
+ * memory.
+ *
+ * Author : Jerry Sexton (based on X_munge.c)
+ *
+ * Notes :
+ *
+ */
+
+#include <windows.h>
+#include "insignia.h"
+#include "host_def.h"
+
+#include "xt.h"
+#include "gvi.h"
+#include "gmi.h"
+#include "gfx_upd.h"
+#include "egagraph.h"
+#include <conapi.h>
+#include "nt_graph.h"
+
+/*(
+========================= ega_colour_hi_munge =============================
+
+PURPOSE: Munge interleaved EGA plane data to bitmap form using lookup tables.
+INPUT: (unsigned char *) plane0_ptr - ptr to plane0 data
+ (int) width - # of groups of 4 bytes on the line
+ (unsigned int *) dest_ptr - ptr to output buffer
+ (unsigned int *) lut0_ptr - munging luts
+ (int) height - # of scanlines to output (1 or 2)
+ (int) line_offset - distance to next scanline
+OUTPUT: A nice bitmap in dest_ptr
+
+===========================================================================
+)*/
+
+GLOBAL VOID
+ega_colour_hi_munge(unsigned char *plane0_ptr, int width,
+ unsigned int *dest_ptr, unsigned int *lut0_ptr,
+ int height, int line_offset)
+{
+ unsigned int *lut1_ptr = lut0_ptr + LUT_OFFSET;
+ unsigned int *lut2_ptr = lut1_ptr + LUT_OFFSET;
+ unsigned int *lut3_ptr = lut2_ptr + LUT_OFFSET;
+ FAST unsigned int hi_res;
+ FAST unsigned int lo_res;
+ FAST unsigned int *l_ptr;
+ FAST half_word *data;
+
+ /* make sure we get the line offset in ints not bytes */
+ line_offset /= sizeof(int);
+ data = (half_word *) plane0_ptr;
+
+ /* convert each input byte in turn */
+ if (get_plane_mask() == 0xf) /* all planes enabled */
+ {
+ for ( ; width > 0; width--)
+ {
+ /* Get 8 bytes (2 longs) of output data from 1 byte of plane 0
+ ** data
+ */
+
+ l_ptr = &lut0_ptr [*data++ << 1];
+ hi_res = *l_ptr++;
+ lo_res = *l_ptr;
+
+ /* Or in the output data from plane 1 */
+ l_ptr = &lut1_ptr [*data++ << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+
+ /* Or in the output data from plane 2 */
+ l_ptr = &lut2_ptr [*data++ << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+
+ /* Or in the output data from plane 3 */
+ l_ptr = &lut3_ptr [*data++ << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+
+ /* Output the data to the buffer */
+ if (height == 2)
+ {
+ /* scanline doubling */
+ *(dest_ptr + line_offset) = hi_res;
+ *dest_ptr++ = hi_res;
+ *(dest_ptr + line_offset) = lo_res;
+ *dest_ptr++ = lo_res;
+ }
+ else
+ {
+ /* not scanline doubling */
+ *dest_ptr++ = hi_res;
+ *dest_ptr++ = lo_res;
+ }
+ }
+ }
+ else
+ {
+ for ( ; width > 0; width--)
+ {
+ /* Get 8 bytes (2 longs) of output data from 1 byte of plane 0
+ ** data
+ */
+
+ if (get_plane_mask() & 1)
+ {
+ l_ptr = &lut0_ptr [*data++ << 1];
+ hi_res = *l_ptr++;
+ lo_res = *l_ptr;
+ }
+ else
+ {
+ hi_res = 0;
+ lo_res = 0;
+ data++;
+ }
+
+ /* Conditionally Or in the output data from plane 1 */
+ if (get_plane_mask() & 2)
+ {
+ l_ptr = &lut1_ptr [*data++ << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Conditionally Or in the output data from plane 2 */
+ if (get_plane_mask() & 4)
+ {
+ l_ptr = &lut2_ptr [*data++ << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Conditionally Or in the output data from plane 3 */
+ if (get_plane_mask() & 8)
+ {
+ l_ptr = &lut3_ptr [*data++ << 1];
+ hi_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Output the data to the buffer */
+ if (height == 2)
+ {
+ /* scanline doubling */
+ *(dest_ptr + line_offset) = hi_res;
+ *dest_ptr++ = hi_res;
+ *(dest_ptr + line_offset) = lo_res;
+ *dest_ptr++ = lo_res;
+ }
+ else
+ {
+ /* not scanline doubling */
+ *dest_ptr++ = hi_res;
+ *dest_ptr++ = lo_res;
+ }
+ }
+ }
+} /* ega_colour_hi_munge */
+
+#ifdef BIGWIN
+/*(
+========================= ega_colour_hi_munge_big ===========================
+
+PURPOSE: Munge interleaved EGA plane data to bitmap data for big windows.
+INPUT: (unsigned char *) plane0_ptr - ptr to EGA plane 0 data
+ (int) width - number of bytes to convert
+ (unsigned int *) dest_ptr - output buffer ptr
+ (unsigned int *) lut0_ptr - ptr to luts
+ (int) height - # of scanlines to output (1 or 3)
+ (int) line_offset - distance to next scanline
+OUTPUT: A nice bitmap in the output buffer
+
+=============================================================================
+)*/
+
+GLOBAL VOID
+ega_colour_hi_munge_big(unsigned char *plane0_ptr, int width,
+ unsigned int *dest_ptr, unsigned int *lut0_ptr,
+ int height, int line_offset)
+{
+ unsigned int *lut1_ptr = lut0_ptr + BIG_LUT_OFFSET;
+ unsigned int *lut2_ptr = lut1_ptr + BIG_LUT_OFFSET;
+ unsigned int *lut3_ptr = lut2_ptr + BIG_LUT_OFFSET;
+ FAST unsigned int hi_res;
+ FAST unsigned int med_res;
+ FAST unsigned int lo_res;
+ FAST unsigned int *l_ptr;
+ FAST half_word *data;
+
+ /* make sure we get the line offset in ints not bytes */
+ line_offset /= sizeof(int);
+ data = (half_word *) plane0_ptr;
+
+ if (get_plane_mask() == 0xf)
+ {
+ for ( ; width > 0; width--)
+ {
+ /* From one byte of input data in plane 0, get 12 bytes
+ ** of output data.
+ */
+
+ l_ptr = &lut0_ptr [*data++ * 3];
+ hi_res = *l_ptr++;
+ med_res = *l_ptr++;
+ lo_res = *l_ptr;
+
+ /* Or in the stuff from plane 1 */
+ l_ptr = &lut1_ptr [*data++ * 3];
+ hi_res |= *l_ptr++;
+ med_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+
+ /* Or in the stuff from plane 2 */
+ l_ptr = &lut2_ptr [*data++ * 3];
+ hi_res |= *l_ptr++;
+ med_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+
+ /* Or in the stuff from plane 3 */
+ l_ptr = &lut3_ptr [*data++ * 3];
+ hi_res |= *l_ptr++;
+ med_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+
+ /* Output the munged data */
+ if (height == 3)
+ {
+ /* triple the scanlines */
+ *(dest_ptr + 2*line_offset) = hi_res;
+ *(dest_ptr + line_offset) = hi_res;
+ *dest_ptr++ = hi_res;
+ *(dest_ptr + 2*line_offset) = med_res;
+ *(dest_ptr + line_offset) = med_res;
+ *dest_ptr++ = med_res;
+ *(dest_ptr + 2*line_offset) = lo_res;
+ *(dest_ptr + line_offset) = lo_res;
+ *dest_ptr++ = lo_res;
+ }
+ else
+ {
+ /* just one scanline */
+ *dest_ptr++ = hi_res;
+ *dest_ptr++ = med_res;
+ *dest_ptr++ = lo_res;
+ }
+ }
+ }
+ else
+ {
+ for ( ; width > 0; width--)
+ {
+ /* From one byte of input data in plane 0, get 12 bytes
+ ** of output data.
+ */
+
+ if (get_plane_mask() & 1)
+ {
+ l_ptr = &lut0_ptr [*data++ * 3];
+ hi_res = *l_ptr++;
+ med_res = *l_ptr++;
+ lo_res = *l_ptr;
+ }
+ else
+ {
+ data++;
+ hi_res = 0;
+ med_res = 0;
+ lo_res = 0;
+ }
+
+ /* Or in the stuff from plane 1 */
+ if (get_plane_mask() & 2)
+ {
+ l_ptr = &lut1_ptr [*data++ * 3];
+ hi_res |= *l_ptr++;
+ med_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Or in the stuff from plane 2 */
+ if (get_plane_mask() & 4)
+ {
+ l_ptr = &lut2_ptr [*data++ * 3];
+ hi_res |= *l_ptr++;
+ med_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Or in the stuff from plane 3 */
+ if (get_plane_mask() & 8)
+ {
+ l_ptr = &lut3_ptr [*data++ * 3];
+ hi_res |= *l_ptr++;
+ med_res |= *l_ptr++;
+ lo_res |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Output the munged data */
+ if (height == 3)
+ {
+ /* triple the scanlines */
+ *(dest_ptr + 2*line_offset) = hi_res;
+ *(dest_ptr + line_offset) = hi_res;
+ *dest_ptr++ = hi_res;
+ *(dest_ptr + 2*line_offset) = med_res;
+ *(dest_ptr + line_offset) = med_res;
+ *dest_ptr++ = med_res;
+ *(dest_ptr + 2*line_offset) = lo_res;
+ *(dest_ptr + line_offset) = lo_res;
+ *dest_ptr++ = lo_res;
+ }
+ else
+ {
+ /* just one scanline */
+ *dest_ptr++ = hi_res;
+ *dest_ptr++ = med_res;
+ *dest_ptr++ = lo_res;
+ }
+ }
+ }
+} /* ega_colour_hi_munge_big */
+
+/*(
+========================= ega_colour_hi_munge_huge ========================
+
+PURPOSE: Munge interleaved EGA plane data to bitmap form using lookup tables.
+INPUT: (unsigned char *) plane0_ptr - ptr to plane0 data
+ (int) width - # of bytes on the line
+ (unsigned int *) dest_ptr - ptr to output buffer
+ (unsigned int *) lut0_ptr - munging luts
+ (int) height - # of scanlines to output (1 or 2)
+ (int) line_offset - distance to next scanline
+OUTPUT: A nice X image in dest_ptr
+
+===========================================================================
+)*/
+
+GLOBAL VOID
+ega_colour_hi_munge_huge(unsigned char *plane0_ptr, int width,
+ unsigned int *dest_ptr, unsigned int *lut0_ptr,
+ int height, int line_offset)
+{
+ unsigned int *lut1_ptr = lut0_ptr + HUGE_LUT_OFFSET;
+ unsigned int *lut2_ptr = lut1_ptr + HUGE_LUT_OFFSET;
+ unsigned int *lut3_ptr = lut2_ptr + HUGE_LUT_OFFSET;
+ FAST unsigned int res4;
+ FAST unsigned int res3;
+ FAST unsigned int res2;
+ FAST unsigned int res1;
+ FAST unsigned int *l_ptr;
+ FAST half_word *data;
+
+ /* make sure we get the line offset in ints not bytes */
+ line_offset /= sizeof(int);
+ data = (half_word *) plane0_ptr;
+
+ /* convert each input byte in turn */
+ if (get_plane_mask() == 0xf)
+ {
+ for ( ; width > 0; width--)
+ {
+ /* Get 16 bytes of output data from 1 byte of plane 0
+ ** data
+ */
+
+ l_ptr = &lut0_ptr [*data++ << 2];
+ res4 = *l_ptr++;
+ res3 = *l_ptr++;
+ res2 = *l_ptr++;
+ res1 = *l_ptr;
+
+ /* Or in the output data from plane 1 */
+ l_ptr = &lut1_ptr [*data++ << 2];
+ res4 |= *l_ptr++;
+ res3 |= *l_ptr++;
+ res2 |= *l_ptr++;
+ res1 |= *l_ptr;
+
+ /* Or in the output data from plane 2 */
+ l_ptr = &lut2_ptr [*data++ << 2];
+ res4 |= *l_ptr++;
+ res3 |= *l_ptr++;
+ res2 |= *l_ptr++;
+ res1 |= *l_ptr;
+
+ /* Or in the output data from plane 3 */
+ l_ptr = &lut3_ptr [*data++ << 2];
+ res4 |= *l_ptr++;
+ res3 |= *l_ptr++;
+ res2 |= *l_ptr++;
+ res1 |= *l_ptr;
+
+ /* Output the data to the buffer */
+ if (height == 4)
+ {
+ /* scanline doubling */
+ *(dest_ptr + 3*line_offset) = res4;
+ *(dest_ptr + 2*line_offset) = res4;
+ *(dest_ptr + line_offset) = res4;
+ *dest_ptr++ = res4;
+ *(dest_ptr + 3*line_offset) = res3;
+ *(dest_ptr + 2*line_offset) = res3;
+ *(dest_ptr + line_offset) = res3;
+ *dest_ptr++ = res3;
+ *(dest_ptr + 3*line_offset) = res2;
+ *(dest_ptr + 2*line_offset) = res2;
+ *(dest_ptr + line_offset) = res2;
+ *dest_ptr++ = res2;
+ *(dest_ptr + 3*line_offset) = res1;
+ *(dest_ptr + 2*line_offset) = res1;
+ *(dest_ptr + line_offset) = res1;
+ *dest_ptr++ = res1;
+ }
+ else
+ {
+ /* not scanline doubling */
+ *dest_ptr++ = res4;
+ *dest_ptr++ = res3;
+ *dest_ptr++ = res2;
+ *dest_ptr++ = res1;
+ }
+ }
+ }
+ else
+ {
+ for ( ; width > 0; width--)
+ {
+ /* Get 16 bytes of output data from 1 byte of plane 0
+ ** data
+ */
+
+ if (get_plane_mask() & 1)
+ {
+ l_ptr = &lut0_ptr [*data++ << 2];
+ res4 = *l_ptr++;
+ res3 = *l_ptr++;
+ res2 = *l_ptr++;
+ res1 = *l_ptr;
+ }
+ else
+ {
+ res4 = 0;
+ res3 = 0;
+ res2 = 0;
+ res1 = 0;
+ data++;
+ }
+
+ /* Or in the output data from plane 1 */
+ if (get_plane_mask() & 2)
+ {
+ l_ptr = &lut1_ptr [*data++ << 2];
+ res4 |= *l_ptr++;
+ res3 |= *l_ptr++;
+ res2 |= *l_ptr++;
+ res1 |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Or in the output data from plane 2 */
+ if (get_plane_mask() & 4)
+ {
+ l_ptr = &lut2_ptr [*data++ << 2];
+ res4 |= *l_ptr++;
+ res3 |= *l_ptr++;
+ res2 |= *l_ptr++;
+ res1 |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Or in the output data from plane 3 */
+ if (get_plane_mask() & 8)
+ {
+ l_ptr = &lut3_ptr [*data++ << 2];
+ res4 |= *l_ptr++;
+ res3 |= *l_ptr++;
+ res2 |= *l_ptr++;
+ res1 |= *l_ptr;
+ }
+ else
+ {
+ data++;
+ }
+
+ /* Output the data to the buffer */
+ if (height == 4)
+ {
+ /* scanline doubling */
+ *(dest_ptr + 3*line_offset) = res4;
+ *(dest_ptr + 2*line_offset) = res4;
+ *(dest_ptr + line_offset) = res4;
+ *dest_ptr++ = res4;
+ *(dest_ptr + 3*line_offset) = res3;
+ *(dest_ptr + 2*line_offset) = res3;
+ *(dest_ptr + line_offset) = res3;
+ *dest_ptr++ = res3;
+ *(dest_ptr + 3*line_offset) = res2;
+ *(dest_ptr + 2*line_offset) = res2;
+ *(dest_ptr + line_offset) = res2;
+ *dest_ptr++ = res2;
+ *(dest_ptr + 3*line_offset) = res1;
+ *(dest_ptr + 2*line_offset) = res1;
+ *(dest_ptr + line_offset) = res1;
+ *dest_ptr++ = res1;
+ }
+ else
+ {
+ /* not scanline doubling */
+ *dest_ptr++ = res4;
+ *dest_ptr++ = res3;
+ *dest_ptr++ = res2;
+ *dest_ptr++ = res1;
+ }
+ }
+ }
+} /* ega_colour_hi_munge_huge */
+#endif /* BIGWIN */
diff --git a/private/mvdm/softpc.new/host/src/nt_nls.c b/private/mvdm/softpc.new/host/src/nt_nls.c
new file mode 100644
index 000000000..eda6a1021
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_nls.c
@@ -0,0 +1,128 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntstatus.h>
+#include <windows.h>
+#include "host_def.h"
+#include "insignia.h"
+/*[
+ Name: nt_nls.c
+ Derived From: X_nls.c (Justin Koprowski)
+ Author: Jerry Sexton
+ Created On: 8th August 1991
+ Purpose:
+ This modules contains strings that are required for the
+ .SoftPC file and the user interface. In addition it also
+ contains a routine, host_nls_get_msg, for retrieving strings
+ from the appropriate array, for ports that do not have native
+ language support.
+
+The following tables and routines are defined:
+ 1. config_message
+ 2. uis_message
+ 3. host_nls_get_msg
+
+ (c)Copyright Insignia Solutions Ltd., 1990. All rights reserved.
+
+]*/
+
+/* Global include files */
+#include <stdio.h>
+#include <string.h>
+#include "xt.h"
+#include "error.h"
+#include "host_rrr.h"
+#include "host_nls.h"
+#include "nt_uis.h"
+
+char szDoomMsg[MAX_PATH]="";
+char szSysErrMsg[MAX_PATH]="";
+#ifdef X86GFX
+char szFrozenString[32];
+#endif
+char szHideMouseMenuStr[64];
+char szDisplayMouseMenuStr[64];
+
+
+
+/****************************************************************************
+ Function: host_nls_get_message()
+ Purpose: Returns the required string from the
+ resource file.
+ Return Status: None.
+ Description: This routine is supplied with a message
+ number which falls in the following ranges:
+ 0-1000: base error messages
+ 1001-2000: host error message
+******************************************************************************/
+
+VOID
+host_nls_get_msg(
+ int message_number,
+ CHAR *message_buffer,
+ int buf_len
+ )
+/* int message_number, Number of SoftPC message.
+ * buf_len; The maximum length of message, i.e.
+ * the size of message_buffer
+ * char *message_buffer; Pointer to a buffer into which the
+ * message is to be written
+ */
+{
+ if (!LoadString(GetModuleHandle(NULL),
+ message_number,
+ message_buffer,
+ buf_len))
+ {
+ strncpy(message_buffer, szDoomMsg, buf_len);
+ message_buffer[buf_len-1] = '\0';
+ }
+}
+
+void nls_init(void)
+{
+
+ if (!LoadString(GetModuleHandle(NULL),
+ EHS_SYSTEM_ERROR,
+ szSysErrMsg,
+ sizeof(szSysErrMsg)/sizeof(CHAR)
+ )
+ ||
+ !FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ ERROR_NOT_ENOUGH_MEMORY,
+ 0,
+ szDoomMsg,
+ sizeof(szDoomMsg)/sizeof(CHAR),
+ NULL
+ )
+#ifdef X86GFX
+ ||
+ !LoadString(GetModuleHandle(NULL),
+ IDS_BURRRR,
+ szFrozenString,
+ sizeof(szFrozenString)/sizeof(CHAR)
+ )
+#endif
+ ||
+ !LoadString(GetModuleHandle(NULL),
+ SM_HIDE_MOUSE,
+ szHideMouseMenuStr,
+ sizeof(szHideMouseMenuStr)/sizeof(char)
+ )
+ ||
+ !LoadString(GetModuleHandle(NULL),
+ SM_DISPLAY_MOUSE,
+ szDisplayMouseMenuStr,
+ sizeof(szDisplayMouseMenuStr)/sizeof(char)
+ ))
+ {
+ RaiseException((DWORD)STATUS_INSUFFICIENT_RESOURCES,
+ EXCEPTION_NONCONTINUABLE,
+ 0,
+ NULL
+ );
+ }
+
+ return;
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_ntfun.c b/private/mvdm/softpc.new/host/src/nt_ntfun.c
new file mode 100644
index 000000000..8d98c959d
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_ntfun.c
@@ -0,0 +1,592 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <ntddser.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "insignia.h"
+#include "trace.h"
+#include "host_trc.h"
+#include "debug.h"
+#include "nt_com.h"
+#include "nt_reset.h"
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Defines */
+
+#define SETUPLASTERROR(NtStatus) SetLastError(RtlNtStatusToDosError(NtStatus))
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::: Magic xoff ioctl and associated functions ::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+typedef struct IoStatusElement
+{
+ struct IoStatusElement *NxtStatusBlock; //Ptr to next status block
+ IO_STATUS_BLOCK ioStatusBlock;
+} IOSTATUSLIST, *PIOSTATUSLIST ;
+
+
+int SendXOFFIoctl(
+
+HANDLE FileHandle, // Handle of comms port to send xoff ioctl to
+HANDLE Event, // Event to signal completion of ioctl on
+int Timeout, // Ioctl timeout
+int Count, // Ioctl RX character count value
+int XoffChar, // XOFF character
+void *StatusElem) // Ptr to IO status block element
+{
+ int exitcode;
+ NTSTATUS rtn; // Return code from IOCTL
+ SERIAL_XOFF_COUNTER ioctl; // XOFF IOCTL
+
+ /*................................................... Setup XOFF ioctl */
+
+ ioctl.Timeout = Timeout; // IOCTL timeout in milliseconds
+ ioctl.Counter = (LONG) Count; // RX count
+ ioctl.XoffChar = (UCHAR) XoffChar; // XOFF character
+
+ /*............................................. issue magic xoff ioctl */
+
+ if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL,
+ &(((PIOSTATUSLIST) StatusElem)->ioStatusBlock),
+ IOCTL_SERIAL_XOFF_COUNTER,
+ (PVOID) &ioctl, sizeof(ioctl), NULL, 0)))
+ {
+ // Should display an error here
+ fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn);
+ exitcode = FALSE;
+ }
+ else
+ exitcode = TRUE;
+
+ return(exitcode);
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::: Allocate IO status element */
+
+void *AllocStatusElement()
+{
+ void *new;
+
+ /*:::::::::::::::::::::::::::::: Allocate space for new io status block */
+
+ if((new = calloc(1,sizeof(IOSTATUSLIST))) == NULL)
+ {
+ // Allocation error do something about it
+ ;
+ }
+ else
+ ((PIOSTATUSLIST) new)->ioStatusBlock.Status = -1;
+
+ return(new);
+}
+
+/*:::::::::::::::::::::::::::::::::::: Add new iostatusblock to linked list */
+
+void *AddNewIOStatusBlockToList(void **firstBlock, void **lastBlock, void *new)
+{
+
+ /*:::::::::::::::::::::::::::::::::::::::: Add new block to linked list */
+
+ if(*lastBlock)
+ ((PIOSTATUSLIST)*lastBlock)->NxtStatusBlock = (PIOSTATUSLIST) new;
+
+ /*:::::::::::::::::: Update first and last linked list element pointers */
+
+ if(!*firstBlock) *firstBlock = new; // First item in list
+
+ *lastBlock = new; // Update last item pointer
+
+ return((void *) new);
+}
+
+/*:::::::::::::::::::::::::: Remove completed XOFF ioctl's from linked list */
+
+int RemoveCompletedIOCTLs(void **firstBlock, void **lastBlock)
+{
+ PIOSTATUSLIST remove, nxt = (PIOSTATUSLIST) *firstBlock;
+
+ /*::::::::::::::::::::::::: Scan linked list removing completed ioctl's */
+
+ while(nxt && nxt->ioStatusBlock.Status != -1)
+ {
+ /*......................... IOCTL completed, remove io status block */
+
+ remove = nxt; // Element to remove
+ nxt = nxt->NxtStatusBlock; // Next element to process
+
+#ifndef PROD
+ switch(remove->ioStatusBlock.Status)
+ {
+ case STATUS_SUCCESS:
+ sub_note_trace0(HOST_COM_VERBOSE,"XOFF (counter)\n");
+ break;
+
+ case STATUS_SERIAL_MORE_WRITES:
+ sub_note_trace0(HOST_COM_VERBOSE,"XOFF (more writes)\n");
+ break;
+
+ case STATUS_SERIAL_COUNTER_TIMEOUT:
+ sub_note_trace0(HOST_COM_VERBOSE,"XOFF (timeout)\n");
+ break;
+
+ default:
+ sub_note_trace0(HOST_COM_VERBOSE,"XOFF (unknown)\n");
+ break;
+ }
+#endif
+
+ free(remove); // Deallocate element
+ }
+
+ /*::::::::::::::::::::::::::::::: Update first and last element pointers */
+
+ if(!nxt)
+ {
+ // List empty reset first/last pointers
+ *firstBlock = *lastBlock = NULL;
+ }
+ else
+ {
+ // Setup new first pointer
+ *firstBlock = (void *) nxt;
+ }
+
+
+ // Returns true if there are still outstanding XOFF ioctl's
+ return(nxt ? TRUE : FALSE);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+int FastSetUpComms(
+
+HANDLE FileHandle, // Handle of comms port to send xoff ioctl to
+HANDLE Event, // Event to signal completion of ioctl on
+int InputQueueSize,
+int OutputQueueSize)
+{
+ NTSTATUS rtn;
+ SERIAL_QUEUE_SIZE ioctl;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ /*........................................................ Setup ioctl */
+
+ ioctl.InSize = InputQueueSize;
+ ioctl.OutSize = OutputQueueSize;
+
+ /*............................................. issue magic xoff ioctl */
+
+ if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL,
+ &ioStatusBlock,
+ IOCTL_SERIAL_SET_QUEUE_SIZE,
+ (PVOID) &ioctl, sizeof(ioctl), NULL, 0)))
+ {
+ // Should display an error here
+#ifndef PROD
+ fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__);
+ fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn);
+#endif
+ return(FALSE);
+ }
+
+ /*......................................... Wait for IOCTL to complete */
+
+ if(rtn == STATUS_PENDING)
+ NtWaitForSingleObject(Event, FALSE, NULL);
+
+ /*............................................ Check completion status */
+
+#ifndef PROD
+ if(ioStatusBlock.Status != STATUS_SUCCESS)
+ fprintf(trace_file, "FastSetupComm failed (%x)\n",ioStatusBlock.Status);
+#endif
+
+ return(ioStatusBlock.Status == STATUS_SUCCESS ? TRUE : FALSE);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::: Fast track SetCommMask call ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+int FastSetCommMask(
+
+HANDLE FileHandle, // Handle of comms port to send ioctl to
+HANDLE Event, // Event to signal completion of ioctl on
+ULONG CommMask)
+{
+ NTSTATUS rtn;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ /*.......................................... issue set comm mask ioctl */
+
+ if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL,
+ &ioStatusBlock,
+ IOCTL_SERIAL_SET_WAIT_MASK,
+ (PVOID) &CommMask, sizeof(CommMask), NULL, 0)))
+ {
+ // Should display an error here
+#ifndef PROD
+ fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__);
+ fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn);
+#endif
+ return(FALSE);
+ }
+
+ /*......................................... Wait for IOCTL to complete */
+
+ if(rtn == STATUS_PENDING)
+ NtWaitForSingleObject(Event, FALSE, NULL);
+
+ /*............................................ Check completion status */
+
+#ifndef PROD
+ if(ioStatusBlock.Status != STATUS_SUCCESS)
+ fprintf(trace_file,"FastSetCommMask failed (%x)\n",ioStatusBlock.Status);
+#endif
+
+ return(ioStatusBlock.Status == STATUS_SUCCESS ? TRUE : FALSE);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::: Fast track GetCommModemStatus call ::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+int FastGetCommModemStatus(
+
+HANDLE FileHandle, // Handle of comms port to send ioctl to
+HANDLE Event, // Event to signal completion of ioctl on
+PULONG ModemStatus)
+{
+ NTSTATUS rtn;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ /*.......................................... issue set comm mask ioctl */
+
+ if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL,
+ &ioStatusBlock,
+ IOCTL_SERIAL_GET_MODEMSTATUS,
+ NULL, 0,
+ (PVOID) ModemStatus, sizeof(ModemStatus))))
+ {
+ // Should display an error here
+#ifndef PROD
+ fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__);
+ fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn);
+#endif
+ return(FALSE);
+ }
+
+ /*......................................... Wait for IOCTL to complete */
+
+ if(rtn == STATUS_PENDING)
+ NtWaitForSingleObject(Event, FALSE, NULL);
+
+ /*............................................ Check completion status */
+
+#ifndef PROD
+ if(ioStatusBlock.Status != STATUS_SUCCESS)
+ fprintf(trace_file,"GetCommModemStatus failed (%x)\n",ioStatusBlock.Status);
+#endif
+
+ return(ioStatusBlock.Status == STATUS_SUCCESS ? TRUE : FALSE);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::: Wait for a wakeup call from the CPU thread or serial driver :::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+//WARNING : This function can only be called from one thread within a process
+
+
+BOOL FastWaitCommsOrCpuEvent(
+HANDLE FileHandle, //File handle or communications port
+PHANDLE CommsCPUWaitEvents, //Table or CPU thread and comms wait events
+int CommsEventInx, //Index in above table to comms event
+PULONG EvtMask, //Return Comms completion mask there
+PULONG SignalledObj)
+{
+ NTSTATUS rtn;
+ static IO_STATUS_BLOCK ioStatusBlock;
+ static BOOL WaitCommEventOutStanding = FALSE;
+
+ /*................................................ Is this a init call */
+
+ if(FileHandle == NULL)
+ {
+ WaitCommEventOutStanding = FALSE;
+ return(TRUE); //Init successful
+ }
+
+ /*......................... Do we need to issue a new WaitComm ioctl ? */
+
+ if(!WaitCommEventOutStanding)
+ {
+
+ /*...................................... Issue WaitCommEvent ioctl */
+
+ if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle,
+ CommsCPUWaitEvents[CommsEventInx],
+ NULL,
+ NULL,
+ &ioStatusBlock,
+ IOCTL_SERIAL_WAIT_ON_MASK,
+ NULL,
+ 0,
+ EvtMask,
+ sizeof(ULONG))) )
+ {
+ // Should display an error here
+#ifndef PROD
+ fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__);
+ fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn);
+#endif
+ SETUPLASTERROR(rtn);
+ return(FALSE);
+ }
+ else
+ WaitCommEventOutStanding = TRUE;
+ }
+ else
+ rtn = STATUS_PENDING; // Already pending WaitCommEvent ioctl
+
+ /*.......................... Wait for communication or CPU thread event */
+
+ if(rtn == STATUS_PENDING)
+ {
+ *SignalledObj = NtWaitForMultipleObjects(2,
+ CommsCPUWaitEvents,
+ WaitAny,
+ FALSE,
+ NULL
+ );
+
+ /*........... Did wait complete because of a communications event ? */
+
+ if(*SignalledObj == (ULONG)CommsEventInx)
+ {
+ // Get result from WaitCommEvent ioctl
+
+ WaitCommEventOutStanding = FALSE;
+ if(ioStatusBlock.Status != STATUS_SUCCESS)
+ {
+ SETUPLASTERROR(ioStatusBlock.Status);
+ return(FALSE);
+ }
+ }
+ }
+ else
+ {
+ //WaitCommEvent completed instantly
+ *SignalledObj = CommsEventInx;
+ WaitCommEventOutStanding = FALSE;
+ }
+
+ return(TRUE);
+}
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::: Turn on MSR,LSR, RX streaming mode :::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+
+BOOL EnableMSRLSRRXmode(
+
+HANDLE FileHandle, // Handle of comms port to send ioctl to
+HANDLE Event, // Event to signal completion of ioctl on
+unsigned char EscapeChar)
+{
+ NTSTATUS rtn;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ /*........................................................ issue ioctl */
+
+ if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL,
+ &ioStatusBlock,
+ IOCTL_SERIAL_LSRMST_INSERT,
+ &EscapeChar, sizeof(unsigned char),NULL,0)))
+ {
+#ifndef PROD
+ fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__);
+ fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn);
+#endif
+ return(FALSE);
+ }
+
+ /*......................................... Wait for IOCTL to complete */
+
+ if (rtn == STATUS_PENDING)
+ NtWaitForSingleObject(Event, FALSE, NULL);
+
+
+ /*............................................ Check completion status */
+
+#ifndef PROD
+ if(ioStatusBlock.Status != STATUS_SUCCESS)
+ fprintf(trace_file,"IOCTL_SERIAL_LSRMST_INSERT ioctl failed (%x)\n",
+ ioStatusBlock.Status);
+#endif
+
+ return(ioStatusBlock.Status == STATUS_SUCCESS ? TRUE : FALSE);
+}
+
+
+/* Function to set a new baudrate for the comm device.
+ * Input: FileHandle -- file handle to the comm device
+ * BaudRate -- new baudrate to be set for the comm device
+ * output: TRUE if the function succeed
+ * FALSE if the function failed
+**/
+
+
+BOOL FastCommSetBaudRate(HANDLE FileHandle, int BaudRate)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE SyncEvent;
+ SERIAL_BAUD_RATE LocalBaud;
+
+ SyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (SyncEvent == NULL)
+ return FALSE;
+
+ LocalBaud.BaudRate = (ULONG)BaudRate;
+
+ Status = NtDeviceIoControlFile(FileHandle,
+ SyncEvent,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ IOCTL_SERIAL_SET_BAUD_RATE,
+ &LocalBaud,
+ sizeof(LocalBaud),
+ NULL,
+ 0
+ );
+ if (Status == STATUS_PENDING)
+ NtWaitForSingleObject(SyncEvent, FALSE, NULL);
+ CloseHandle(SyncEvent);
+ return(NT_SUCCESS(IoStatusBlock.Status));
+}
+
+/* Function to set the new line control to the given comm device
+ * Input: FileHanlde -- file handle to the comm device
+ * StopBits -- new Stopbits
+ * Parity -- new parity
+ * DataBits -- new databits
+ * Output:
+ * TRUE if the function succeed.
+ * FALSE if the function failed.
+**/
+BOOL FastCommSetLineControl(HANDLE FileHandle, UCHAR StopBits, UCHAR Parity,
+ UCHAR DataBits)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE SyncEvent;
+ SERIAL_LINE_CONTROL LocalLC;
+
+
+ /* make sure Windows and NT has the same definiation because
+ * the caller only deal with WINDOWS value while we will be returning
+ * NT values(NO_PARITY, STOP_BIT_1 and etc).
+ */
+ ASSERT(NOPARITY == NO_PARITY && ODDPARITY == ODD_PARITY &&
+ EVENPARITY == EVEN_PARITY && MARKPARITY == MARK_PARITY &&
+ SPACEPARITY == SPACE_PARITY);
+ ASSERT(ONESTOPBIT == STOP_BIT_1 && ONE5STOPBITS == STOP_BITS_1_5 &&
+ TWOSTOPBITS == STOP_BITS_2);
+
+ /* Create an event to wait for the NT call */
+ SyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (SyncEvent == NULL)
+ return FALSE;
+
+ LocalLC.StopBits = StopBits;
+ LocalLC.Parity = Parity;
+ LocalLC.WordLength = DataBits;
+
+ Status = NtDeviceIoControlFile(FileHandle,
+ SyncEvent,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ IOCTL_SERIAL_SET_LINE_CONTROL,
+ &LocalLC,
+ sizeof(LocalLC),
+ NULL,
+ 0
+ );
+ if (Status == STATUS_PENDING)
+ NtWaitForSingleObject(SyncEvent, FALSE, NULL);
+
+ CloseHandle(SyncEvent);
+ return(NT_SUCCESS(IoStatusBlock.Status));
+}
+
+/* Function to retrieve the given comm device current line control setting
+ * Input: FileHandle -- file handle to the comm device
+ * StopBits, Parity and DataBits are pointers to the placeholders
+ * to receive Stop bits, Parity and Data bits repectively.
+ * Output:
+ * TRUE if the function succeed
+ * FALSE if the function failed.
+**/
+
+BOOL FastCommGetLineControl(HANDLE FileHandle, UCHAR *StopBits, UCHAR *Parity,
+ UCHAR *DataBits)
+{
+ NTSTATUS Status;
+ SERIAL_LINE_CONTROL LocalLC;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE SyncEvent;
+
+ /* make sure Windows and NT has the same definiation because
+ * the parameters we received from the caller are WINDOWS value
+ * while we will be calling NT API using NT values
+ */
+ ASSERT(NOPARITY == NO_PARITY && ODDPARITY == ODD_PARITY &&
+ EVENPARITY == EVEN_PARITY && MARKPARITY == MARK_PARITY &&
+ SPACEPARITY == SPACE_PARITY);
+ ASSERT(ONESTOPBIT == STOP_BIT_1 && ONE5STOPBITS == STOP_BITS_1_5 &&
+ TWOSTOPBITS == STOP_BITS_2);
+
+ ASSERT(StopBits != NULL && Parity != NULL && DataBits != NULL);
+
+ SyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (SyncEvent == NULL)
+ return FALSE;
+ Status = NtDeviceIoControlFile(FileHandle,
+ SyncEvent,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ IOCTL_SERIAL_GET_LINE_CONTROL,
+ NULL,
+ 0,
+ &LocalLC,
+ sizeof(LocalLC)
+ );
+ if (Status == STATUS_PENDING)
+ NtWaitForSingleObject(SyncEvent, FALSE, NULL);
+
+ CloseHandle(SyncEvent);
+
+ if (NT_SUCCESS(IoStatusBlock.Status)) {
+ *StopBits = LocalLC.StopBits;
+ *Parity = LocalLC.Parity;
+ *DataBits = LocalLC.WordLength;
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_pif.c b/private/mvdm/softpc.new/host/src/nt_pif.c
new file mode 100644
index 000000000..84371ef2f
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_pif.c
@@ -0,0 +1,442 @@
+/*================================================================
+
+nt_pif.c
+
+Code to read the relevant data fields from a Windows Program
+Information File for use with the SoftPC / NT configuration
+system.
+
+Andrew Watson 31/1/92
+This line causes this file to be build with a checkin of NT_PIF.H
+
+================================================================*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "insignia.h"
+#include "host_def.h"
+
+#include <pif.h>
+#include "nt_pif.h"
+#include "nt_reset.h"
+#include <oemuni.h>
+#include "error.h"
+
+
+ //
+ // holds config.sys and autoexec name from pif file
+ // if none specifed, then NULL.
+ //
+static char *pchConfigFile=NULL;
+static char *pchAutoexecFile=NULL;
+VOID GetPIFConfigFiles(BOOL bConfig, char *pchFileName);
+
+DWORD dwWNTPifFlags;
+UCHAR WNTPifFgPr = 100;
+UCHAR WNTPifBgPr = 100;
+
+char achSlash[] ="\\";
+char achConfigNT[] ="config.nt";
+char achAutoexecNT[]="autoexec.nt";
+
+
+/* GetPIFConfigFile
+ *
+ * Copies PIF file specified name of config.sys\autoexec.bat
+ * to be used if none specified then uses
+ * "WindowsDir\config.nt" or "WindowsDir\autoexec.nt"
+ *
+ * ENTRY: BOOLEAN bConfig - TRUE retrieve config.sys
+ * FALSE retrieve autoexec.bat
+ *
+ * char *pchFile - destination for path\file name
+ *
+ * The input buffer must be at least MAX_PATH + 8.3 BaseName in len
+ *
+ * This routine cannot fail, but it may return a bad file name!
+ */
+VOID GetPIFConfigFiles(BOOL bConfig, char *pchFileName)
+{
+ DWORD dw;
+ char **ppch;
+
+
+ ppch = bConfig ? &pchConfigFile : &pchAutoexecFile;
+ if (!*ppch)
+ {
+ dw = GetSystemDirectory(pchFileName, MAX_PATH);
+ if (!dw || *(pchFileName+dw-1) != achSlash[0])
+ strcat(pchFileName, achSlash);
+ strcat(pchFileName, bConfig ? achConfigNT : achAutoexecNT);
+ }
+ else {
+ dw = ExpandEnvironmentStringsOem(*ppch, pchFileName, MAX_PATH+12);
+ if (!dw || dw > MAX_PATH+12) {
+ *pchFileName = '\0';
+ }
+ free(*ppch);
+ *ppch = NULL;
+ }
+}
+
+
+void SetPifDefaults(PIF_DATA *);
+
+/*===============================================================
+
+Function: GetPIFData()
+
+Purpose: This function gets the PIF data from the PIF file
+ associated with the executable that SoftPC is trying
+ to run.
+
+Input: FullyQualified PifFileName,
+ if none supplied _default.pif will be used
+
+Output: A structure containing data that config needs.
+
+Returns: TRUE if the data has been gleaned successfully, FALSE
+ if not.
+
+================================================================*/
+
+BOOL GetPIFData(PIF_DATA * pd, char *PifName)
+{
+ DWORD dw;
+ CHAR achDef[]="\\_default.pif";
+ PIFEXTHDR exthdr;
+ STDPIF pif286;
+ W386PIF30 ext386;
+ W286PIF30 ext286;
+ WNTPIF31 extWNT;
+ WENHPIF40 extWin95;
+ HFILE filehandle;
+ char pathBuff[MAX_PATH*2];
+ BOOL bGot386, bGotWin95;
+ int index;
+ char *CmdLine;
+ WORD IdleSensitivity;
+
+ CmdLine = NULL;
+ dwWNTPifFlags = 0;
+
+ //
+ // set the defaults in case of error or in case we can't find
+ // all of the pif settings information now for easy error exit
+ //
+ SetPifDefaults(pd);
+
+ // if no PifName, use %windir%\_default.pif
+ if (!*PifName) {
+ dw = GetWindowsDirectory(pathBuff, sizeof(pathBuff) - sizeof(achDef));
+ if (!dw || dw > sizeof(pathBuff) - sizeof(achDef)) {
+ return FALSE; // give it up... use default settings
+ }
+ strcat(pathBuff, achDef);
+ PifName = pathBuff;
+ }
+
+
+/*================================================================
+Open the file whose name was passed as a parameter to GetPIFData()
+and if an invalid handle to the file is returned (-1), then quit.
+The file specified is opened for reading only.
+================================================================*/
+
+if((filehandle=_lopen(PifName,OF_READ)) == (HFILE) -1)
+ {
+ /* must be an invalid handle ! */
+ return FALSE;
+ }
+
+
+/*================================================================
+Get the main block of data from the PIF file.
+================================================================*/
+
+/* Read in the main block of file data into the structure */
+if(_llseek(filehandle,0,0) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+if(_lread(filehandle,(LPSTR)&pif286,sizeof(pif286)) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+
+/*==============================================================
+Go to the PIF extension signature area and try to read the
+header in.
+==============================================================*/
+
+if (_lread(filehandle,(LPSTR)&exthdr,sizeof(exthdr)) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+
+ // do we have any extended headers ?
+if (!strcmp(exthdr.extsig, STDHDRSIG))
+ {
+ bGot386 = FALSE;
+ bGotWin95 = FALSE;
+ while (exthdr.extnxthdrfloff != LASTHEADER)
+ {
+ //
+ // move to next extended header and read it in
+ //
+ if (_llseek(filehandle,exthdr.extnxthdrfloff,0) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+ if (_lread(filehandle,(LPSTR)&exthdr,sizeof(exthdr)) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+
+ //
+ // Get 286 extensions, note that 386 extensions take precedence
+ //
+ if (!strcmp(exthdr.extsig, W286HDRSIG) && !bGot386)
+ {
+ if(_llseek(filehandle, exthdr.extfileoffset, 0) == -1 ||
+ _lread(filehandle,(LPSTR)&ext286,sizeof(ext286)) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+ pd->xmsdes =ext286.PfMaxXmsK;
+ pd->xmsreq =ext286.PfMinXmsK;
+ pd->reskey =ext286.PfW286Flags & 3;
+ pd->reskey |= (ext286.PfW286Flags << 2) & 0x70;
+ }
+ //
+ // Get 386 extensions
+ //
+ else if (!strcmp(exthdr.extsig, W386HDRSIG30))
+ {
+ if(_llseek(filehandle, exthdr.extfileoffset, 0) == -1 ||
+ _lread(filehandle,(LPSTR)&ext386,sizeof(ext386)) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+ bGot386 = TRUE;
+ pd->emsdes=ext386.PfMaxEMMK;
+ pd->emsreq=ext386.PfMinEMMK;
+ pd->xmsdes=ext386.PfMaxXmsK;
+ pd->xmsreq=ext386.PfMinXmsK;
+ if (!bGotWin95 && ext386.PfFPriority < 100) {
+ WNTPifFgPr = (UCHAR)ext386.PfFPriority; // Foreground priority
+ }
+ if (!bGotWin95 && ext386.PfBPriority < 50) {
+ WNTPifBgPr = (UCHAR)ext386.PfBPriority; // Background priority
+ WNTPifBgPr <<= 1; // set def 50 to 100
+ }
+ pd->reskey = (char)((ext386.PfW386Flags >> 5) & 0x7f); // bits 5 - 11 are reskeys
+ pd->menuclose = (char)(ext386.PfW386Flags & 1); // bottom bit sensitive
+ pd->ShortScan = ext386.PfHotKeyScan; // scan code of shortcut key
+ pd->ShortMod = ext386.PfHotKeyShVal; // modifier code of shortcut key
+ if (!bGotWin95)
+ pd->idledetect = (char)((ext386.PfW386Flags >> 12) & 1);
+ pd->fullorwin = (WORD)((ext386.PfW386Flags & fFullScreen) >> 3);
+ bPifFastPaste = (ext386.PfW386Flags & fINT16Paste) != 0;
+ CmdLine = ext386.PfW386params;
+ }
+ //
+ // Get Windows Nt extensions
+ //
+ else if (!strcmp(exthdr.extsig, WNTEXTSIG))
+ {
+ if(_llseek(filehandle, exthdr.extfileoffset, 0) == -1 ||
+ _lread(filehandle,(LPSTR)&extWNT, sizeof(extWNT)) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+
+ dwWNTPifFlags = extWNT.nt31Prop.dwWNTFlags;
+ pd->SubSysId = (char) (dwWNTPifFlags & NTPIF_SUBSYSMASK);
+
+ /* take autoexec.nt and config.nt from .pif file
+ only if we are running on a new console or it is from
+ forcedos/wow
+ */
+ if (!pd->IgnoreConfigAutoexec)
+ {
+ pchConfigFile = ch_malloc(PIFDEFPATHSIZE);
+ extWNT.nt31Prop.achConfigFile[PIFDEFPATHSIZE-1] = '\0';
+ if (pchConfigFile) {
+ strcpy(pchConfigFile, extWNT.nt31Prop.achConfigFile);
+ }
+
+ pchAutoexecFile = ch_malloc(PIFDEFPATHSIZE);
+ extWNT.nt31Prop.achAutoexecFile[PIFDEFPATHSIZE-1] = '\0';
+ if (pchAutoexecFile) {
+ strcpy(pchAutoexecFile, extWNT.nt31Prop.achAutoexecFile);
+ }
+ }
+
+ }
+ //
+ // Get Win95 extenstion
+ //
+ else if (!strcmp(exthdr.extsig, WENHHDRSIG40))
+ {
+ bGotWin95 = TRUE;
+ if(_llseek(filehandle, exthdr.extfileoffset, 0) == -1 ||
+ _lread(filehandle,(LPSTR)&extWin95, sizeof(extWin95)) == -1)
+ {
+ _lclose(filehandle);
+ return FALSE;
+ }
+ IdleSensitivity = extWin95.tskProp.wIdleSensitivity;
+ if (IdleSensitivity < 10) {
+ // disable idle detection completely
+ pd->idledetect = 0;
+ }
+ else if (IdleSensitivity > 50 && IdleSensitivity <= 100) {
+ //
+ // 10 <= priority <= 100 (yeild rate = 90% ~ 0%)
+ //
+ WNTPifFgPr =
+ WNTPifBgPr = 10 + (100 - IdleSensitivity) * 9 / 5;
+ }
+ else {
+ WNTPifFgPr =
+ WNTPifBgPr = 100;
+ }
+ // TSK_BACKGROUND means "do not suspend the application
+ // when it is running in background"
+ if (!(extWin95.tskProp.flTsk & TSK_BACKGROUND)) {
+ WNTPifBgPr = 10;
+ }
+
+ }
+ } // while !lastheader
+
+ /* pif file handling strategies on NT:
+ (1). application was launched from a new created console
+ Take everything from the pif file.
+
+ (2). application was launched from an existing console
+ if (ForceDos pif file)
+ take everything
+ else
+ only take softpc stuff and ignore every name strings in the
+ pif file such as
+ * wintitle
+ * startup directory
+ * optional parameters
+ * startup file
+ * autoexec.nt
+ * config.nt and
+
+ some softpc setting:
+
+ * close on exit.
+ * full screen and windowed mode
+
+ Every name strings in a pif file is in OEM character set.
+
+ */
+
+ if (DosSessionId ||
+ (pfdata.AppHasPIFFile && pd->SubSysId == SUBSYS_DOS))
+ {
+ if (pif286.appname[0] && !pd->IgnoreTitleInPIF) {
+ /* grab wintitle from the pif file. Note that the title
+ in the pif file is not a NULL terminated string. It always
+ starts from a non-white character then the real
+ title(can have white characters between words) and finally
+ append with SPACE characters. The total length is 30 characters.
+ */
+ for (index = 29; index >= 0; index-- )
+ if (pif286.appname[index] != ' ')
+ break;
+ if (index >= 0 && (pd->WinTitle = ch_malloc(MAX_PATH + 1))) {
+ RtlMoveMemory(pd->WinTitle, pif286.appname, index + 1);
+ pd->WinTitle[index + 1] = '\0';
+ }
+ }
+ if (pif286.defpath[0] && !pd->IgnoreStartDirInPIF &&
+ (pd->StartDir = ch_malloc(MAX_PATH + 1)))
+ strcpy(pd->StartDir, pif286.defpath);
+
+ if (!pd->IgnoreCmdLineInPIF) {
+ CmdLine = (CmdLine) ? CmdLine : pif286.params;
+ if (CmdLine && *CmdLine && (pd->CmdLine = ch_malloc(MAX_PATH + 1)))
+ strcpy(pd->CmdLine, CmdLine);
+ }
+ if (DosSessionId)
+ pd->CloseOnExit = (pif286.MSflags & 0x10) ? 1 : 0;
+
+ /* if the app has a pif file, grab the program name.
+ This can be discarded if it turns out the application itself
+ is not a pif file.
+ */
+ if (pd->AppHasPIFFile) {
+ pd->StartFile = ch_malloc(MAX_PATH + 1);
+ if (pd->StartFile)
+ strcpy(pd->StartFile, pif286.startfile);
+ }
+ }
+ }
+
+_lclose(filehandle);
+return TRUE;
+
+}
+
+
+
+/*===============================================================
+Function to set up the default options for memory state.
+The default options are defined in nt_pif.h
+===============================================================*/
+
+void SetPifDefaults(PIF_DATA *pd)
+{
+ pd->memreq = DEFAULTMEMREQ;
+ pd->memdes = DEFAULTMEMDES;
+ pd->emsreq = DEFAULTEMSREQ;
+ pd->emsdes = DEFAULTEMSLMT;
+ pd->xmsreq = DEFAULTXMSREQ;
+ pd->xmsdes = DEFAULTXMSLMT;
+ pd->graphicsortext = DEFAULTVIDMEM;
+ pd->fullorwin = DEFAULTDISPUS;
+ pd->menuclose = 1;
+ pd->idledetect = 1;
+ pd->ShortMod = 0; // No shortcut keys
+ pd->ShortScan = 0;
+ pd->reskey = 0; // No reserve keys
+ pd->CloseOnExit = 1;
+ pd->WinTitle = NULL;
+ pd->CmdLine = NULL;
+ pd->StartFile = NULL;
+ pd->StartDir = NULL;
+ pd->SubSysId = SUBSYS_DEFAULT;
+}
+
+/*
+ * Allocate NumBytes memory and exit cleanly on failure.
+ */
+void *ch_malloc(unsigned int NumBytes)
+{
+
+ unsigned char *p = NULL;
+
+ while ((p = malloc(NumBytes)) == NULL) {
+ if(RcMessageBox(EG_MALLOC_FAILURE, "", "",
+ RMB_ABORT | RMB_RETRY | RMB_IGNORE |
+ RMB_ICON_STOP) == RMB_IGNORE)
+ break;
+ }
+ return(p);
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_reset.c b/private/mvdm/softpc.new/host/src/nt_reset.c
new file mode 100644
index 000000000..8b004fe9e
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_reset.c
@@ -0,0 +1,422 @@
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : NT reset functions
+ *
+ * Description : This function is called by the standard reset function to
+ * set up any specific devices used by the Sun4 implementation.
+ *
+ * Author : SoftPC team
+ *
+ * Notes :
+ */
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <vdm.h>
+#include <vdmapi.h>
+#include "insignia.h"
+#include "host_def.h"
+
+#ifdef X86GFX
+#include <ntddvdeo.h>
+#endif
+
+#include <sys\types.h>
+#include "xt.h"
+#include "sas.h"
+#include "bios.h"
+#include "keyboard.h"
+#include "gmi.h"
+#include "gfx_upd.h"
+#include "gvi.h"
+#include "mouse_io.h"
+#include "error.h"
+#include "config.h"
+#include "host.h"
+#include "timer.h"
+#include "idetect.h"
+#include CpuH
+#include "debug.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <conapi.h>
+#include "nt_timer.h"
+#include "nt_graph.h"
+#include "ntcheese.h"
+#include "nt_uis.h"
+#include "nt_com.h"
+#include "nt_reset.h"
+#include "nt_event.h"
+#include "nt_fulsc.h"
+#include "nt_eoi.h"
+#include "video.h"
+#include "nt_thred.h"
+
+
+VOID DeleteConfigFiles(VOID); // from command.lib
+void ShowStartGlass (DWORD); // private user api
+
+extern VIDEOFUNCS nt_video_funcs;
+extern KEYBDFUNCS nt_keybd_funcs;
+extern HOSTMOUSEFUNCS the_mouse_funcs;
+
+#ifndef MONITOR
+extern WORD BWVKey;
+extern char achES[];
+#endif
+
+#ifdef MONITOR
+extern VOID AddTempIVTFixups(VOID);
+#endif
+
+extern IU8 lcifo[];
+
+/*
+ * Exported Data
+ */
+GLOBAL BOOL VDMForWOW = FALSE;
+GLOBAL BOOL fSeparateWow = FALSE; // TRUE if CREATE_SEPARATE_WOW_VDM flag
+GLOBAL HANDLE MainThread;
+GLOBAL ULONG DosSessionId = 0;
+GLOBAL UINT VdmExitCode = 0xFF;
+GLOBAL BOOL StreamIoSwitchOn = TRUE;
+
+/*
+ *
+ * ============================================================================
+ * External functions
+ * ===========================================================================
+ * =
+ */
+
+void
+host_reset()
+{
+
+#ifdef X86GFX
+ InitDetect();
+#endif
+
+ if (host_stream_io_enabled) {
+ sc.ScreenState = STREAM_IO;
+ ConsoleInitialised = TRUE;
+ }
+ else {
+
+ ConsoleInit();
+ MouseAttachMenuItem(sc.ActiveOutputBufferHandle);
+ /*::::::::::::::::::::::::::::::::::::::::::::::::: Enable idle detect */
+ }
+
+#ifdef MONITOR
+ /* Borrow the end of this routine to add temp code that hooks certain
+ * Ints back to the VDM and not into the native BIOS. These will only
+ * be active for the DOSEM initialisation ie until keyboard.sys can
+ * come along and do it properly. We must do this though as some real
+ * BIOS' can hang on certain initialisation functions. eg Dec 486/50
+ * will hang on printer init as it is waiting for a responce from a
+ * 'private' port.
+ */
+ AddTempIVTFixups();
+#endif /* MONITOR */
+
+
+ //
+ // Let the heartbeat thread run and release the ica lock,
+ // on x86 needed now, for fullscreen switch notification.
+ //
+ ResumeThread(ThreadInfo.HeartBeat.Handle);
+
+#ifdef MONITOR
+ WaitIcaLockFullyInitialized();
+#endif
+
+ host_ica_unlock();
+
+#ifdef HUNTER
+ IDLE_ctl(FALSE); /* makes Trapper too slow */
+#else /* ! ( HUNTER ) */
+ if (sc.ScreenState == FULLSCREEN) // initialised in ConsoleInit()
+ IDLE_ctl(FALSE);
+ else
+ IDLE_ctl(TRUE); // can't idle detect fullscreen
+
+ host_idle_init(); // host sleep event creation
+#endif /* HUNTER */
+
+
+}
+
+
+/*
+ * =========================================================================
+ *
+ * FUNCTION : host_applInit
+ *
+ * PURPOSE : Sets up the keyboard, lpt and error panels.
+ *
+ * RETURNED STATUS : None.
+ *
+ * DESCRIPTION : Called from main.c. The keyboard and other GWI pointer
+ * sets are initialised here. The command line arguments are
+ * parsed for those flags that need processing early (ie before
+ * config() is called).
+ *
+ * =======================================================================
+ */
+#define HOUR_BOOST_FOR_WOW 20*1000 // 20 seconds
+
+void host_applInit(int argc,char *argv[])
+{
+ char *psz;
+ int temp_argc = argc;
+ char **temp_argv = argv;
+ BOOL bSwitchF = FALSE;
+
+ working_video_funcs = &nt_video_funcs;
+ working_keybd_funcs = &nt_keybd_funcs;
+ working_mouse_funcs = &the_mouse_funcs;
+
+ // check that someone has'nt started ntvdm from the cmd prompt. In such a
+ // case we should kill ntvdm as we support it only when createprocess
+ // executes it. We are checking a this with the argc although lots of
+ // fancy things can be done. If a user is bent upon running ntvdm directly
+ // they can always fool this code. We are only checking the presence of
+ // -f switch.
+
+
+// Check if the VDM Is for WOW
+// Check is for new console session
+ while (--temp_argc > 0) {
+ psz = *++temp_argv;
+ if (*psz == '-' || *psz == '/') {
+ psz++;
+
+ if (*psz == 'f') {
+ bSwitchF = TRUE;
+ continue;
+ }
+#ifndef MONITOR
+ //
+ // Check for windowed graphics resize
+ //
+ if (*psz == 'E') {
+ int i;
+
+ i = strlen(achES);
+ if (!strncmp(psz, achES, i) && strlen(psz) == (size_t)i+2) {
+ psz += i;
+ BWVKey = (WORD)strtoul(psz, NULL, 16);
+ if (BWVKey > 0xFE)
+ BWVKey = 0;
+ }
+ }
+ else
+#endif
+ if(tolower(*psz) == 'w'){
+ VDMForWOW = TRUE;
+ if (bSwitchF)
+ break;
+ }
+ else if (*psz == 'o'){
+ StreamIoSwitchOn = FALSE;
+ }
+ else if (*psz++ == 'i' && *psz) {
+ DosSessionId = strtoul(psz, NULL, 16);
+ }
+
+ }
+ }
+
+
+ if (bSwitchF == FALSE)
+ ExitProcess (0);
+
+ // If VDM Is for WOW keep showing the glass
+ if (VDMForWOW) {
+ if (DosSessionId) {
+ fSeparateWow = TRUE;
+ }
+
+ ShowStartGlass (HOUR_BOOST_FOR_WOW);
+ StreamIoSwitchOn = FALSE;
+ }
+ else if (StreamIoSwitchOn)
+ enable_stream_io();
+
+ /*
+ * Get a handle to the main thread so it can be suspended during
+ * hand-shaking.
+ */
+ DuplicateHandle(GetCurrentProcess(),
+ GetCurrentThread(),
+ GetCurrentProcess(),
+ &MainThread,
+ (DWORD) 0,
+ FALSE,
+ (DWORD) DUPLICATE_SAME_ACCESS);
+
+ InitializeIcaLock();
+ host_ica_lock();
+
+ init_host_uis(); /* console setup */
+ nt_start_event_thread(); /* Start event processing thread */
+}
+
+
+/*
+ * =========================================================================
+ *
+ * FUNCTION : host_applClose
+ *
+ * PURPOSE : The last chance to close down.
+ *
+ * RETURNED STATUS : None.
+ *
+ * DESCRIPTION : Called from main.c.
+ *
+ *
+ * =======================================================================
+ */
+
+void
+host_applClose(void)
+{
+ nt_remove_event_thread();
+ InitSound(FALSE);
+ TerminateHeartBeat();
+
+ GfxCloseDown(); // ensure video section destroyed
+#ifdef X86GFX
+ if (sc.ScreenBufHandle)
+ CloseHandle(sc.ScreenBufHandle);
+#endif // X86GFX
+
+
+
+ host_lpt_close_all(); /* Close all open printer ports */
+ host_com_close_all(); /* Close all open comms ports */
+ MouseDetachMenuItem(TRUE); /* Force the menu item away on quit */
+
+ DeleteConfigFiles(); // make sure temp config files are deleted
+}
+
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::: Closedown the VDM */
+
+
+/*
+ * host_terminate
+ *
+ * This function does not return it exits
+ * Most of softpc has been shutdown by the time this
+ * code is reached, as host_applClose has already been
+ * invoked.
+ *
+ */
+void host_terminate(void)
+{
+
+#ifdef HUNTER
+ if (TrapperDump != (HANDLE) -1)
+ CloseHandle(TrapperDump);
+#endif /* HUNTER */
+
+ if(VDMForWOW)
+ ExitVDM(VDMForWOW,(ULONG)-1); // Kill everything for WOW VDM
+ else
+ ExitVDM(FALSE,0);
+
+ ExitProcess(VdmExitCode);
+}
+
+
+
+/* TerminateVDM - used by host to initiate shutdown
+ *
+ * Request to start shutting down
+ *
+ */
+VOID TerminateVDM(void)
+{
+
+ /*
+ * Do base sepcific cleanup thru terminate().
+ * NOTE: terminate will call host_applClose and host_terminate
+ * after doing base cleanup
+ */
+ terminate();
+}
+
+
+
+
+
+#ifdef NOTUSEDNOTUSED
+void
+manager_files_init()
+{
+
+ assert0(NO,"manager_files_init stubbed\n");
+}
+
+
+#ifndef PROD
+/*
+ * =========================================================================
+ *
+ * FUNCTION : host_symb_debug_init
+ *
+ * PURPOSE : Does nothing
+ *
+ * RETURNED STATUS : None.
+ *
+ * DESCRIPTION : Called from main.c.
+ *
+ *
+ * =======================================================================
+ */
+
+void
+host_symb_debug_init IFN1(char *, name)
+{
+}
+#endif /* nPROD */
+
+
+void
+host_supply_dfa_filename IFN1(char *, filename)
+
+{
+}
+
+static BOOL bool_dummy_func() {}
+static SHORT short_dummy_func() {}
+static VOID void_dummy_func() {}
+
+
+ERRORFUNCS dummy_error_funcs =
+{
+
+ short_dummy_func,
+ short_dummy_func,
+ short_dummy_func
+
+};
+
+KEYBDFUNCS dummy_keybd_funcs =
+{
+
+ void_dummy_func,
+ void_dummy_func,
+ void_dummy_func,
+ void_dummy_func,
+ void_dummy_func,
+ void_dummy_func
+
+};
+#endif
diff --git a/private/mvdm/softpc.new/host/src/nt_rez.c b/private/mvdm/softpc.new/host/src/nt_rez.c
new file mode 100644
index 000000000..fd6b94a23
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_rez.c
@@ -0,0 +1,187 @@
+#include "insignia.h"
+#include "host_def.h"
+
+/* INSIGNIA MODULE SPECIFICATION
+ -----------------------------
+
+FILE NAME : nt_rez.c
+MODULE NAME : nt CMOS read/write routines
+
+ THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
+ CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MAY
+ ONLY BE DISCLOSED TO PERSONS EMPLOYED BY THE CUSTOMER WHO
+ REQUIRE A KNOWLEDGE OF THE SOFTWARE CODING TO CARRY OUT
+ THEIR JOB. DISCLOSURE TO ANY OTHER PERSON MUST HAVE PRIOR
+ AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS INC.
+
+DESIGNER :
+DATE :
+
+PURPOSE :
+
+
+
+The Following Routines are defined:
+ 1. host_read_resource
+ 2. host_write_resource
+
+=========================================================================
+
+AMENDMENTS :
+
+=========================================================================
+*/
+
+
+#include <stdio.h>
+#include <io.h>
+#include <sys\types.h>
+#include <fcntl.h>
+#include <sys\stat.h>
+
+#include "xt.h"
+#include "error.h"
+#include "spcfile.h"
+#include "timer.h"
+
+
+/*
+ * Allow a suitable default for the CMOS file name.
+ */
+
+#ifndef CMOS_FILE_NAME
+#define CMOS_FILE_NAME "cmos.ram"
+#endif
+
+long host_read_resource(int type, char *name, byte *addr, int maxsize, int display_error)
+/* int type; Unused */
+/* char *name; Name of resource */
+/* byte *addr; Address to read data into */
+/* int maxsize; Max size that should be read */
+/* int display_error; Flag to control error message output */
+{
+
+ int file_fd;
+ long size=0;
+ char full_path[MAXPATHLEN];
+ extern char *host_find_file(char *name, char *path, int disp_err);
+
+ type = 0; // To stop unreferenced formal parameter errors
+
+#ifdef DELTA //STF - make change to 8.3 compatible name
+ if (strcmp(name, ".spcprofile") == 0)
+ name = "profile.spc";
+#endif
+
+ file_fd = _open(host_find_file (name, full_path, display_error), O_RDONLY|O_BINARY);
+
+ if (file_fd != -1) /* Opened successfully */ {
+ /* seek to end to get size */
+ size = _lseek (file_fd, 0L, 2);
+
+ if (size > maxsize) // corrupted file???
+ return(0);
+
+ /* Seek back to start before reading! */
+ _lseek (file_fd, 0L, 0);
+
+ _read(file_fd,addr,size);
+ _close(file_fd);
+ }
+
+ return (size);
+}
+
+
+
+/********************************************************/
+
+void host_write_resource(type,name,addr,size)
+int type; /* Unused */
+char *name; /* Name of resource */
+byte *addr; /* Address of data to write */
+long size; /* Quantity of data to write */
+{
+ int file_fd;
+ char full_path[MAXPATHLEN];
+ char *hff_ret;
+ extern char *host_find_file(char *name, char *path, int disp_err);
+
+ type = 0; // To stop unreferenced formal parameter errors
+
+ host_block_timer ();
+
+#ifdef DELTA //STF - make change to 8.3 compatible name
+ if (strcmp(name, ".spcprofile") == 0)
+ name = "profile.spc";
+#endif
+
+ hff_ret = host_find_file (name,full_path,SILENT);
+
+ if (hff_ret != NULL)
+ {
+ file_fd = _open (hff_ret,O_WRONLY);
+
+ if (file_fd != -1)
+ {
+ _write (file_fd, addr, size);
+ _close (file_fd);
+ }
+ else
+ {
+
+#ifndef HUNTER
+ host_error (EG_REZ_UPDATE,ERR_CONT,name);
+#endif
+
+ /* Continuing => try to create a new file */
+ file_fd = _open(name,O_RDWR|O_CREAT,S_IREAD|S_IWRITE);
+
+ if (file_fd != -1)
+ {
+ _write (file_fd, addr, size);
+ _close (file_fd);
+ }
+
+#ifndef HUNTER
+ else
+ {
+ /* Tell the user we cannot update */
+ host_error (EG_NO_REZ_UPDATE, ERR_CONT, CMOS_FILE_NAME);
+ }
+#endif
+
+ }
+ }
+ else
+ {
+ /* host find file has failed and we have
+ * reached this point with no error panels
+ */
+
+#ifndef HUNTER
+ host_error (EG_REZ_UPDATE,(ERR_QUIT|ERR_CONT),name);
+#endif
+
+ /* Continuing => try to create a new file */
+ file_fd = _open(name,O_RDWR|O_CREAT,S_IREAD|S_IWRITE);
+
+ if (file_fd != -1)
+ {
+ _write (file_fd, addr, size);
+ _close (file_fd);
+ }
+
+#ifndef HUNTER
+ else
+ {
+ /* Tell the user we cannot update */
+ host_error (EG_NO_REZ_UPDATE, ERR_CONT,
+ CMOS_FILE_NAME);
+ }
+#endif
+
+ }
+
+ host_release_timer ();
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_rflop.c b/private/mvdm/softpc.new/host/src/nt_rflop.c
new file mode 100644
index 000000000..ec6444f5f
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_rflop.c
@@ -0,0 +1,2036 @@
+/*
+ * Name: nt_flop.c
+ * Derived From: DEC begat M88K begat NeXT finally begat Generic.
+ * Author: Jason Proctor
+ * Created On: Nov 8 1990
+ * Sccs ID: 10/13/92 @(#)nt_flop.c 1.9
+ * Purpose: nt real floppy server.
+ *
+ * (c)Copyright Insignia Solutions Ltd., 1990. All rights reserved.
+ *
+ * Notes:
+ * Updated for 3.0 base by Jerry Richemont.
+ * Further updated by Ian Reid to support two floppy
+ * drives. Support is compile time dependant on the
+ * standard SoftPC defines.
+ *
+ * This implementation requires that you provide a
+ * host_rflop_drive_type() function which knows what kind of drive(s)
+ * your machine has; ie returns GFI_DRIVE_TYPE_xxxx.
+ */
+
+/********************************************************/
+
+/* INCLUDES */
+
+#include "nt.h"
+#include "ntrtl.h"
+#include "nturtl.h"
+#include "ntdddisk.h"
+#include "windows.h"
+
+#include "insignia.h"
+#include "host_def.h"
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys\types.h>
+
+#include "xt.h"
+#include CpuH
+#include "trace.h"
+#include "error.h"
+#include "fla.h"
+#include "dma.h"
+#include "config.h"
+#include "debug.h"
+#include "lock.h"
+#include "timer.h"
+#include "floppy.h"
+#include "cmos.h"
+#include "gfi.h"
+
+#include "nt_uis.h"
+#include "nt_reset.h"
+#include "nt_fdisk.h"
+/********************************************************/
+
+/* DEFINES */
+
+#ifdef min
+#undef min
+#endif
+#define min(a,b) (a > b ? b : a)
+
+#define PC_MAX_DRIVE_TYPES 2
+#define PC_MAX_DENSITY_TYPES 2
+#define PC_MAX_FLOPPY_TYPES (PC_MAX_DRIVE_TYPES * PC_MAX_DENSITY_TYPES)
+
+#define PC_HEADS_PER_DISKETTE 2
+#define PC_N_VALUE 2
+#define PC_BYTES_PER_SECTOR 512
+
+/* disk buffer size, in bytes */
+// KEEP SYNC WITH MAX_DISKIO_SIZE defined in nt_fdisk.c
+#define BS_DISK_BUFFER_SIZE 0x9000
+
+/* double stepping factor */
+#define DOUBLE_STEP_FACTOR 1
+
+/* density types */
+#define DENSITY_LOW 0
+#define DENSITY_HIGH 1
+#define DENSITY_EXTENDED 2
+#define DENSITY_UNKNOWN 100
+/* motor states */
+#define MOTOR_OFF 0
+#define MOTOR_ON 1
+
+#ifndef PROD
+#define BREAK_ON_AND 0x01
+#define BREAK_ON_OR 0x02
+#define BREAK_ON_XOR 0x03
+
+UTINY break_cylinder = 0xff;
+UTINY break_head = 0xff;
+UTINY break_sector = 0xff;
+#endif
+
+#ifndef PROD
+DWORD rflop_dbg = 0;
+
+#define RFLOP_READ 0x01
+#define RFLOP_WRITE 0x02
+#define RFLOP_FORMAT 0x04
+#define RFLOP_SEEK 0x08
+#define RFLOP_READID 0x10
+#define RFLOP_RESET 0x20
+#define RFLOP_SPECIFY 0x40
+#define RFLOP_READTRACK 0x80
+#define RFLOP_RECAL 0x100
+#define RFLOP_SENSEDRV 0x200
+#define RFLOP_RATE 0x1000
+#define RFLOP_CHANGE 0x2000
+#define RFLOP_DRIVE_ON 0x4000
+#define RFLOP_DRIVE_OFF 0x8000
+#define RFLOP_OPEN 0x10000
+#define RFLOP_CLOSE 0x20000
+#define RFLOP_GUESS_MEDIA 0x40000
+
+#define RFLOP_BREAK 0x80000000
+
+#endif
+
+/********************************************************/
+
+/* TYPEDEFS */
+
+struct flop_struct
+{
+ int trks_per_disk;
+ int secs_per_trk;
+};
+
+/*
+ * This structure contains all the drive specific information. That is
+ * status which is unique to each drive, and must therefore be maintained
+ * on a per drive basis.
+ */
+typedef struct floppy_info
+{
+ HANDLE diskette_fd;
+
+/*
+ * drive_type - the highest density format which this drive supports,
+ * e.g. GFI_DRIVE_TYPE_144, GFI_DRIVE_TYPE_288
+ * flop_type - the basic drive type, expressed as the lowest density
+ * possible for this format. For 5.25" disks this is
+ * GFI_DRIVE_TYPE_360, for 3.5" it is GFI_DRIVE_TYPE_720.
+ */
+ USHORT drive_type;
+ USHORT flop_type;
+ USHORT last_seek;
+ USHORT last_head_seek;
+/*
+ * Change line state.
+ * This is a heuristic to try to fake up the correct change line behaviour
+ * without having a change line. The state of the change line is returned
+ * as CHANGED unless the diskette motor has been continuously ON since the
+ * last reset.
+ */
+ BOOLEAN change_line_state;
+ BOOLEAN auto_locked;
+ USHORT owner_pdb;
+ SHORT motor_state;
+ SHORT media_density;
+ USHORT max_track;
+
+ USHORT secs_per_trk;
+ USHORT trks_per_disk;
+ DWORD align_factor;
+ UTINY idle_counter;
+ UTINY C;
+ UTINY H;
+ UTINY R;
+ UTINY N;
+ char device_name[MAX_PATH]; /* device name */
+} FL, *FLP;
+
+#define FLOPPY_IDLE_PERIOD 0xFF
+
+
+/* parameter passed from main thread to FDC thread */
+typedef struct _FDC_PARMS{
+FDC_CMD_BLOCK * command_block;
+FDC_RESULT_BLOCK * result_block;
+USHORT owner_pdb;
+BOOLEAN auto_lock;
+
+} FDC_PARMS, *PFDC_PARMS;
+
+
+/********************************************************/
+
+
+/* routines used internally */
+
+/* routines called via vector table: all the prototypes are in gfi.h
+** so everybody matches. If you want to use this file to base a
+** host floppy module on, you know that all the functions that must
+** be declared properly for gfi to work will be.
+** GM.
+ */
+ULONG nt_floppy_read (UTINY drive, ULONG Offset, ULONG Size, PBYTE Buffer);
+ULONG nt_floppy_write (UTINY drive, ULONG Offset, ULONG Size, PBYTE Buffer);
+BOOL nt_floppy_verify (UTINY drive, ULONG Offset, ULONG Size);
+MEDIA_TYPE nt_floppy_get_media_type(BYTE drive, WORD cylinders, WORD sectors, WORD heads);
+BOOL nt_floppy_format (UTINY drive, WORD Cylinder, WORD Head, MEDIA_TYPE media);
+BOOL nt_floppy_close (UTINY drive);
+BOOL nt_floppy_media_check (UTINY drive);
+BOOL dismount_drive(FLP flp);
+
+
+#ifndef PROD
+VOID nt_rflop_break(VOID);
+#endif
+
+void fdc_command_completed (BYTE drive, BYTE fdc_command);
+void fdc_thread (PFDC_PARMS fdc_parms);
+
+BOOL nt_gfi_rdiskette_init IPT1( UTINY, drive );
+VOID nt_gfi_rdiskette_term IPT1( FLP, flp );
+SHORT nt_rflop_drive_on IPT1( UTINY, drive );
+SHORT nt_rflop_drive_off IPT1( UTINY, drive );
+SHORT nt_rflop_change IPT1( UTINY, drive );
+SHORT nt_rflop_drive_type IPT1( UTINY, drive );
+SHORT nt_rflop_rate IPT2( UTINY, drive, half_word, rate);
+SHORT nt_rflop_reset IPT2( FDC_RESULT_BLOCK *, res, UTINY, drive );
+SHORT nt_rflop_command IPT2( FDC_CMD_BLOCK *, ip, FDC_RESULT_BLOCK *, res);
+HANDLE nt_rdiskette_open_drive IPT1 ( UTINY, drive );
+SHORT guess_media_density IPT1 (UTINY, drive);
+VOID set_floppy_parms IPT1 (FLP, flp);
+BOOL dos_compatible
+ IPT5 (FLP, flp, UTINY, cyl, UTINY, hd, UTINY, sec, UTINY, n);
+int dos_offset
+ IPT4 (FLP, flp, UTINY, cyl, UTINY, hd, UTINY, sec);
+VOID update_chrn(FLP flp, UTINY mt, UTINY eot, UTINY sector_count);
+HANDLE get_drive_handle (UTINY drive, USHORT pdb, BOOL auto_lock);
+SHORT fdc_read_write ( FDC_CMD_BLOCK * ip, FDC_RESULT_BLOCK * res);
+VOID floppy_close_down(USHORT, BOOL);
+VOID HostFloppyReset(VOID);
+VOID FloppyTerminatePDB(USHORT);
+int DiskOpenRetry(CHAR);
+
+extern USHORT * pusCurrentPDB;
+
+#ifdef EJECT_FLOPPY
+GLOBAL void host_floppy_eject IFN1(UTINY, drive)
+#endif
+
+
+/********************************************************/
+
+/* STATIC GLOBALS */
+
+
+FL floppy_data[MAX_FLOPPY];
+
+ struct flop_struct floppy_tksc [6] =
+{
+ {0, 0}, /* GFI_DRIVE_TYPE_NULL */
+ {40, 9}, /* GFI_DRIVE_TYPE_360 */
+ {80, 15}, /* GFI_DRIVE_TYPE_12 */
+ {80, 9}, /* GFI_DRIVE_TYPE_720 */
+ {80, 18}, /* GFI_DRIVE_TYPE_144 */
+ {80, 36} /* GFI_DRIVE_TYPE_288 */
+};
+// table used to convert GFI diskette type to NT diskette type
+static MEDIA_TYPE media_table[GFI_DRIVE_TYPE_MAX] = {
+ Unknown,
+ F5_360_512,
+ F5_1Pt2_512,
+ F3_720_512,
+ F3_1Pt44_512,
+ F3_2Pt88_512
+ };
+
+SHORT density_state;
+BOOL density_changed = TRUE;
+UTINY last_drive = 0xff;
+BOOL fdc_reset = FALSE;
+HANDLE fdc_thread_handle = NULL;
+extern UTINY number_of_floppy;
+FDC_PARMS fdc_parms;
+ULONG floppy_open_count = 0;
+
+
+
+/*
+ * Debugging info only, for non-prod cases
+ */
+#ifndef PROD
+ CHAR *cmd_name [] =
+{
+ "Invalid command (00)", /* 00 */
+ "Invalid command (01)", /* 01 */
+ "Read a Track", /* 02 */
+ "Specify", /* 03 */
+ "Sense Drive Status", /* 04 */
+ "Write Data", /* 05 */
+ "Read Data", /* 06 */
+ "Recalibrate", /* 07 */
+ "Sense Interrupt Status", /* 08 */
+ "Write Deleted Data", /* 09 */
+ "Read ID", /* 0A */
+ "Invalid Command (0B)", /* 0B */
+ "Read Deleted Data", /* 0C */
+ "Format a Track", /* 0D */
+ "Invalid Command (0E)", /* 0E */
+ "Seek", /* 0F */
+ "Invalid Command (10)", /* 10 */
+ "Scan Equal", /* 11 */
+ "Invalid Command (12)", /* 12 */
+ "Invalid Command (13)", /* 13 */
+ "Invalid Command (14)", /* 14 */
+ "Invalid Command (15)", /* 15 */
+ "Invalid Command (16)", /* 16 */
+ "Invalid Command (17)", /* 17 */
+ "Invalid Command (18)", /* 18 */
+ "Scan Low or Equal", /* 19 */
+ "Invalid Command (1A)", /* 1A */
+ "Invalid Command (1B)", /* 1B */
+ "Invalid Command (1C)", /* 1C */
+ "Scan High or Equal", /* 1D */
+ "Invalid Command (1E)", /* 1E */
+ "Invalid Command (1F)", /* 1F */
+};
+#endif /* PROD */
+
+char dump_buf[256];
+
+
+/* the disk buffer, there is only one, even though there may be two
+ * drives. Should be O.K. as floppy disk accesses will be single
+ * threaded.
+ */
+ UTINY *disk_buffer;
+
+/* Report any errors in open_diskette() */
+ int last_error = C_CONFIG_OP_OK;
+
+/********************************************************/
+
+/* GLOBAL FUNCTIONS */
+
+/* These functions called by config/UIF/startup now form the only
+** interface between SoftPC and a floppy module. XXX_active() will
+** turn the floppy emmulation in the module on by loading the global
+** gfi_function_table[] with pointers to appropriate functions
+** defined in this module.
+** The floppy supported here is turned off by asking the empty floppy
+** module to turn itself on in its place.
+**
+** This makes a nice orthogonal interface which keeps everything save
+** the three control functions (private). The functions that are put
+** in the table are defined only in gfi.h as typedefs so they are easy to
+** get right.
+**
+** This enabling/disabling via the gfi_function_table[] does not
+** take place instead of any host ioctls/opens/closes etc that are needed
+** to actually open or close the device, it forms the interface for SoftPC.
+**
+** Really, this approach is a small tidy up of the way things are
+** already done; existing host floppy code will require very small changes.
+**
+** GM
+*/
+
+/********************************************************/
+
+/* Turn the floppy on and off. Off means release the driver so another
+** process can use it.
+*/
+
+GLOBAL SHORT
+host_gfi_rdiskette_active IFN3(UTINY, hostID, BOOL, active, CHAR *, err)
+{
+ UTINY drive = hostID - C_FLOPPY_A_DEVICE;
+ FLP flp = &floppy_data[drive];
+
+ if(active)
+ {
+ if (!nt_gfi_rdiskette_init(drive))
+ {
+ /* Device is not a valid floppy */
+
+ return( C_CONFIG_NOT_VALID );
+ }
+ return(C_CONFIG_OP_OK);
+ }
+ else
+ {
+#ifdef EJECT_FLOPPY
+ host_floppy_eject(drive);
+#endif /* EJECT_FLOPPY */
+ nt_gfi_rdiskette_term(flp); /* shutdown process */
+ gfi_empty_active(hostID,TRUE,err); /* Tell gfi 'empty' is now active */
+ return(C_CONFIG_OP_OK);
+ }
+}
+
+/********************************************************/
+
+
+/* Validate the floppy device name passed from the config system.
+** Empty string is valid; it means 'no floppy'. Otherwise return OK is
+** the name is 'probably' a valid device. It cannot be opened at this
+** stage because if there is no floppy in the drive, the open will fail.
+**
+** GM.
+*/
+
+GLOBAL SHORT
+host_gfi_rdiskette_valid IFN3(UTINY,hostID,ConfigValues *,vals,CHAR *,err)
+{
+#ifndef NTVDM
+ UTINY cmos_byte;
+ UTINY drive = hostID - C_FLOPPY_A_DEVICE;
+ FLP flp = &floppy_data[drive];
+
+ if(!strcmp(vals->string,""))
+ return(C_CONFIG_OP_OK);
+
+ strcpy(flp->device_name, host_expand_environment_vars(vals->string));
+
+ if(!host_validate_pathname(flp->device_name))
+ {
+ strcpy(err, host_strerror(errno));
+ flp->device_name[0] = '\0';
+ return( EG_MISSING_FILE );
+ }
+ if(!host_file_is_char_dev(flp->device_name))
+ {
+ flp->device_name[0] = '\0';
+ return( EG_NOT_CHAR_DEV );
+ }
+
+ /* Check the CMOS RAM values */
+ cmos_read_byte(CMOS_DISKETTE, &cmos_byte);
+ if (drive == 0)
+ cmos_byte >>= 4;
+
+ cmos_byte &= 0xf; /* compare nibble value only */
+ flp->drive_type = host_rflop_drive_type(drive);
+ if (cmos_byte != flp->drive_type)
+ vals->rebootReqd = TRUE;
+#endif
+ return(C_CONFIG_OP_OK);
+}
+
+/********************************************************/
+
+GLOBAL VOID
+host_gfi_rdiskette_change IFN2(UTINY, hostID, BOOL, apply)
+{
+#ifndef NTVDM
+ FLP flp = &floppy_data[hostID - C_FLOPPY_A_DEVICE];
+
+ if (apply)
+ {
+ nt_gfi_rdiskette_term(flp);
+ }
+#endif
+}
+
+/********************************************************/
+
+#ifdef EJECT_FLOPPY
+GLOBAL void host_floppy_eject IFN1(UTINY, drive)
+{
+ CHAR *ebuf;
+ FLP flp = &floppy_data[drive];
+ BOOL device_was_closed = FALSE;
+
+ /* open the device */
+ if (flp->diskette_fd == INVALID_HANDLE_VALUE)
+ {
+ device_was_closed = TRUE;
+ (void) nt_rdiskette_open_drive(drive);
+ }
+
+ /* Do the ioctl, put your ioctl here
+
+ if (ioctl(flp->diskette_fd, SMFDEJECT) < 0)
+ {
+ ebuf = host_strerror(errno);
+ assert1(NO, "host_eject_floppy: %s", ebuf);
+ }*/
+
+ /* Close the device if it wasn't open */
+
+ if (device_was_closed)
+ {
+ nt_gfi_rdiskette_term(flp);
+ }
+ else
+ {
+ /* Line change ONLY if device was actively open */
+ flp->change_line_state = TRUE;
+ }
+}
+
+#endif /* EJECT_FLOPPY */
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::: FLOPPY heart beat call ::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+GLOBAL void host_flpy_heart_beat(void)
+{
+
+ UTINY drive;
+ FLP flp;
+
+ if (pFDAccess && *pFDAccess) {
+ if (floppy_open_count) {
+ for (drive = 0; drive < number_of_floppy; drive++) {
+ flp = & floppy_data[drive];
+ if (flp->diskette_fd != INVALID_HANDLE_VALUE &&
+ --flp->idle_counter == 0) {
+ nt_floppy_close(drive);
+
+ }
+ }
+
+ }
+ if (number_of_fdisk != 0)
+ fdisk_heart_beat();
+ }
+}
+
+
+
+
+/********************************************************/
+
+/* initialise GFI function table */
+BOOL nt_gfi_rdiskette_init IFN1(UTINY, drive)
+{
+ FLP flp;
+ DISK_GEOMETRY disk_geometry[20];
+ ULONG media_types;
+ CHAR DeviceName[] = "\\\\.\\A:";
+ NTSTATUS status;
+ IO_STATUS_BLOCK io_status_block;
+ FILE_ALIGNMENT_INFORMATION align_info;
+
+ flp = &floppy_data[drive];
+ flp->diskette_fd = INVALID_HANDLE_VALUE;
+
+ DeviceName[4] += drive;
+ strcpy(flp->device_name, (const char *)DeviceName);
+ /*
+ * Initialise the floppy on the required drive:
+ *
+ * 0 - Drive A, 1 - Drive B
+ */
+
+ flp->drive_type = GFI_DRIVE_TYPE_NULL;
+ /* open the device */
+ if ((flp->diskette_fd = nt_rdiskette_open_drive (drive)) == NULL) {
+ return FALSE;
+ }
+ // get alignment factor
+ status = NtQueryInformationFile(flp->diskette_fd,
+ &io_status_block,
+ &align_info,
+ sizeof(FILE_ALIGNMENT_INFORMATION),
+ FileAlignmentInformation
+ );
+ if (!NT_SUCCESS(status)) {
+ nt_gfi_rdiskette_term(flp);
+ return(FALSE);
+ }
+ flp->align_factor = align_info.AlignmentRequirement;
+ if (flp->align_factor > max_align_factor)
+ max_align_factor = flp->align_factor;
+
+
+ // enumerate possible supported media for this drive
+ // to figure out the drive type.
+ status = NtDeviceIoControlFile(flp->diskette_fd,
+ NULL,
+ NULL,
+ NULL,
+ &io_status_block,
+ IOCTL_DISK_GET_MEDIA_TYPES,
+ NULL,
+ 0L,
+ (PVOID)&disk_geometry,
+ sizeof(disk_geometry)
+ );
+ if (!NT_SUCCESS(status)) {
+ nt_gfi_rdiskette_term(flp);
+ return FALSE;
+ }
+ nt_gfi_rdiskette_term(flp);
+ media_types = io_status_block.Information / sizeof(DISK_GEOMETRY);
+
+ for (; media_types != 0; media_types--) {
+ switch (disk_geometry[media_types - 1].MediaType) {
+ case F5_360_512:
+ if (flp->drive_type != GFI_DRIVE_TYPE_12)
+ flp->drive_type = GFI_DRIVE_TYPE_360;
+ break;
+ case F5_1Pt2_512:
+ flp->drive_type = GFI_DRIVE_TYPE_12;
+ break;
+ case F3_720_512:
+ if (flp->drive_type != GFI_DRIVE_TYPE_144 &&
+ flp->drive_type != GFI_DRIVE_TYPE_288)
+ flp->drive_type = GFI_DRIVE_TYPE_720;
+ break;
+ case F3_1Pt44_512:
+ if (flp->drive_type != GFI_DRIVE_TYPE_288)
+ flp->drive_type = GFI_DRIVE_TYPE_144;
+ break;
+ case F3_2Pt88_512:
+ flp->drive_type = GFI_DRIVE_TYPE_288;
+ break;
+ }
+ }
+ if (flp->drive_type == GFI_DRIVE_TYPE_NULL)
+ return FALSE;
+ /* configure its vectors here */
+ gfi_function_table[drive].command_fn = nt_rflop_command;
+ gfi_function_table[drive].drive_on_fn = nt_rflop_drive_on;
+ gfi_function_table[drive].drive_off_fn = nt_rflop_drive_off;
+ gfi_function_table[drive].reset_fn = nt_rflop_reset;
+ gfi_function_table[drive].high_fn = nt_rflop_rate;
+ gfi_function_table[drive].drive_type_fn= nt_rflop_drive_type;
+ gfi_function_table[drive].change_fn = nt_rflop_change;
+ flp->C = flp->H = 0;
+ flp->R = 1;
+ flp->N = PC_N_VALUE;
+ flp->auto_locked = FALSE;
+ flp->owner_pdb = 0;
+ return TRUE;
+}
+
+/********************************************************/
+
+/* reset GFI function table */
+/* currently drive is ignored */
+VOID nt_gfi_rdiskette_term IFN1(FLP, flp)
+{
+
+ // NtOpenFile returns NULL if we can not open a handle
+ // while win32 OpenFile/CreateFile returns INVALID_HANDLE_VALUE
+ // if failed to open/create the file.
+ if (flp->diskette_fd != NULL)
+ {
+// host_clear_lock(flp->diskette_fd);
+ NtClose(flp->diskette_fd);
+ flp->diskette_fd = INVALID_HANDLE_VALUE;
+ }
+}
+
+/********************************************************/
+
+/* open the floppy device file */
+HANDLE nt_rdiskette_open_drive IFN1(UTINY, drive)
+{
+
+ CHAR NtDeviceName[] = "\\DosDevices\\A:";
+ PUNICODE_STRING Unicode;
+ ANSI_STRING DeviceNameA;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES FloppyObj;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE fd;
+
+ NtDeviceName[12] += drive;
+
+ RtlInitAnsiString( &DeviceNameA, NtDeviceName);
+
+ Unicode = &NtCurrentTeb()->StaticUnicodeString;
+
+ Status = RtlAnsiStringToUnicodeString(Unicode,
+ &DeviceNameA,
+ FALSE
+ );
+ if ( !NT_SUCCESS(Status) )
+ return NULL;
+
+
+ InitializeObjectAttributes(
+ &FloppyObj,
+ Unicode,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+ Status = NtOpenFile(
+ &fd,
+ (ACCESS_MASK) FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+ &FloppyObj,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
+ );
+
+ if (!NT_SUCCESS(Status))
+ return NULL;
+ else
+ return fd;
+
+}
+
+
+ULONG nt_floppy_read(BYTE drive, ULONG Offset, ULONG Size, PBYTE Buffer)
+{
+ HANDLE fd;
+ LARGE_INTEGER large_integer;
+
+ fd = get_drive_handle(drive, *pusCurrentPDB, FALSE);
+
+ if (fd == INVALID_HANDLE_VALUE)
+ return 0;
+ large_integer.LowPart = Offset;
+ large_integer.HighPart = 0;
+ return(disk_read(fd, &large_integer, Size, Buffer));
+}
+
+
+ULONG nt_floppy_write(BYTE drive, ULONG Offset, ULONG Size, PBYTE Buffer)
+{
+ HANDLE fd;
+ LARGE_INTEGER large_integer;
+ ULONG size_returned;
+
+ fd = get_drive_handle(drive, *pusCurrentPDB, TRUE);
+ if (fd == INVALID_HANDLE_VALUE)
+ return 0;
+
+ large_integer.LowPart = Offset;
+ large_integer.HighPart = 0;
+ size_returned = disk_write(fd, &large_integer, Size, Buffer);
+ return (size_returned);
+}
+
+BOOL nt_floppy_format(BYTE drive, WORD Cylinder, WORD Head, MEDIA_TYPE Media)
+{
+ FORMAT_PARAMETERS fmt;
+ WORD bad_track;
+ ULONG size_returned;
+ HANDLE fd;
+ BOOL result;
+
+ result = FALSE;
+ fmt.MediaType = Media;
+ fmt.StartHeadNumber = fmt.EndHeadNumber = Head;
+ fmt.StartCylinderNumber = fmt.EndCylinderNumber = Cylinder;
+ fd = get_drive_handle(drive, *pusCurrentPDB,TRUE);
+ if (fd == INVALID_HANDLE_VALUE)
+ return FALSE;
+ result = DeviceIoControl(fd,
+ IOCTL_DISK_FORMAT_TRACKS,
+ (PVOID) &fmt,
+ sizeof(fmt),
+ &bad_track,
+ sizeof(bad_track),
+ &size_returned,
+ NULL
+ );
+ return result;
+}
+
+// for floppy, the ioctl call DISK_VERIFY doesn't work
+// we have to use read for verification
+BOOL nt_floppy_verify(BYTE drive, DWORD Offset, DWORD Size)
+{
+ HANDLE fd;
+ LARGE_INTEGER large_integer;
+
+ fd = get_drive_handle(drive, *pusCurrentPDB, FALSE);
+ if (fd != INVALID_HANDLE_VALUE) {
+ large_integer.LowPart = Offset;
+ large_integer.HighPart = 0;
+ return(disk_verify(fd,
+ &large_integer,
+ Size
+ ));
+ }
+ else
+ return FALSE;
+}
+
+int DiskOpenRetry(char chDrive)
+{
+ char FormatString[32];
+ char DriveLetter[32];
+
+ if (!LoadString(GetModuleHandle(NULL), ED_DRIVENUM,
+ FormatString,sizeof(FormatString)) )
+ {
+ strcpy(FormatString,"Drive %c: ");
+ }
+ sprintf(DriveLetter, FormatString, chDrive);
+ return(RcMessageBox(ED_LOCKDRIVE, DriveLetter, NULL,
+ RMB_ABORT | RMB_RETRY | RMB_IGNORE | RMB_ICON_BANG
+ ));
+}
+
+
+HANDLE get_drive_handle(UTINY drive, USHORT pdb, BOOL auto_lock)
+{
+ FLP flp;
+ DWORD share_access;
+
+
+ flp = &floppy_data[drive];
+ // assign new alignment factor and grab the buffer
+ cur_align_factor = flp->align_factor;
+ if ((disk_buffer = get_aligned_disk_buffer()) == NULL)
+ return (INVALID_HANDLE_VALUE);
+
+
+ if (flp->diskette_fd != INVALID_HANDLE_VALUE &&
+ (fdc_reset || (auto_lock && !flp->auto_locked) ||
+ flp->owner_pdb != pdb))
+ {
+ nt_floppy_close(drive);
+ fdc_reset = FALSE;
+ }
+ share_access = auto_lock ? FILE_SHARE_READ :
+ FILE_SHARE_READ | FILE_SHARE_WRITE;
+ while(flp->diskette_fd == INVALID_HANDLE_VALUE) {
+ flp->diskette_fd = CreateFile ((const char *)flp->device_name,
+ GENERIC_READ | GENERIC_WRITE,
+ share_access,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ 0
+ );
+ if (flp->diskette_fd != INVALID_HANDLE_VALUE) {
+ floppy_open_count++;
+ flp->auto_locked = auto_lock;
+ flp->owner_pdb = pdb;
+ (*(pFDAccess))++;
+ break;
+ }
+ if (auto_lock && GetLastError() == ERROR_SHARING_VIOLATION &&
+ DiskOpenRetry((char)(drive + (UTINY)'A')) == RMB_RETRY)
+ continue;
+ else
+ break;
+
+ }
+ flp->idle_counter = FLOPPY_IDLE_PERIOD;
+ return (flp->diskette_fd);
+}
+
+
+
+VOID HostFloppyReset(VOID)
+{
+ FloppyTerminatePDB((USHORT)0);
+}
+
+VOID FloppyTerminatePDB(USHORT PDB)
+{
+ UTINY drive;
+ FLP flp;
+
+ if (floppy_open_count) {
+ for (drive = 0; drive < number_of_floppy; drive++) {
+ flp = &floppy_data[drive];
+ if (flp->diskette_fd != INVALID_HANDLE_VALUE &&
+ (PDB == 0 || flp->owner_pdb == PDB))
+ nt_floppy_close(drive);
+ }
+
+ }
+}
+
+BOOL nt_floppy_close(UTINY drive)
+{
+ FLP flp;
+ flp = &floppy_data[drive];
+
+#ifndef PROD
+ if (rflop_dbg & RFLOP_CLOSE)
+ sprintf(dump_buf, "Close drive %C: handle\n", drive + 'A');
+ OutputDebugString(dump_buf);
+#endif
+
+ if (flp->diskette_fd != INVALID_HANDLE_VALUE) {
+ CloseHandle(flp->diskette_fd);
+ flp->diskette_fd = INVALID_HANDLE_VALUE;
+ (*(pFDAccess))--;
+ flp->auto_locked = FALSE;
+ flp->owner_pdb = 0;
+ floppy_open_count--;
+ }
+ density_changed = TRUE;
+ return TRUE;
+}
+
+
+MEDIA_TYPE
+nt_floppy_get_media_type
+(
+BYTE drive,
+WORD cylinders,
+WORD sectors,
+WORD heads
+)
+{
+ FLP flp;
+ USHORT index;
+
+ flp = &floppy_data[drive];
+ if (heads == 2){
+ index = flp->drive_type;
+ switch (index) {
+ case GFI_DRIVE_TYPE_12:
+ if (cylinders == floppy_tksc[index].trks_per_disk &&
+ sectors == floppy_tksc[index].secs_per_trk)
+ break;
+ index = GFI_DRIVE_TYPE_360;
+
+ case GFI_DRIVE_TYPE_360:
+ if (cylinders != floppy_tksc[index].trks_per_disk ||
+ sectors != floppy_tksc[index].secs_per_trk)
+ index = GFI_DRIVE_TYPE_NULL;
+ break;
+
+ case GFI_DRIVE_TYPE_288:
+ if (cylinders == floppy_tksc[index].trks_per_disk &&
+ sectors == floppy_tksc[index].secs_per_trk)
+ break;
+ index = GFI_DRIVE_TYPE_144;
+
+ case GFI_DRIVE_TYPE_144:
+ if (cylinders == floppy_tksc[index].trks_per_disk &&
+ sectors == floppy_tksc[index].secs_per_trk)
+ break;
+ index = GFI_DRIVE_TYPE_720;
+
+ case GFI_DRIVE_TYPE_720:
+ if (cylinders == floppy_tksc[index].trks_per_disk &&
+ sectors == floppy_tksc[index].secs_per_trk)
+ break;
+ default:
+ index = GFI_DRIVE_TYPE_NULL;
+ }
+ }
+ else
+ index = GFI_DRIVE_TYPE_NULL;
+ return(media_table[index]);
+
+}
+
+BOOL nt_floppy_media_check (UTINY drive)
+{
+ FLP flp;
+ ULONG size_returned;
+
+ flp = &floppy_data[drive];
+ if (flp->diskette_fd == INVALID_HANDLE_VALUE)
+ return FALSE;
+ return(DeviceIoControl(flp->diskette_fd,
+ IOCTL_DISK_CHECK_VERIFY,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ &size_returned,
+ NULL
+ ));
+}
+
+/********************************************************/
+
+/* perform an FDC command */
+ SHORT
+nt_rflop_command
+ IFN2(FDC_CMD_BLOCK *, command_block, FDC_RESULT_BLOCK *,result_block)
+{
+ UTINY drive;
+ FLP flp;
+ BOOL failed = FALSE;
+ UTINY C, H, N, S, D;
+ DWORD fdc_thread_id;
+ BYTE fdc_command;
+ BOOL auto_lock;
+
+
+ note_trace1 (GFI_VERBOSE, "FDC: %s command",
+ cmd_name [get_type_cmd (command_block)]);
+
+ drive = get_type_drive(command_block);
+
+ flp = &floppy_data[drive];
+ flp->idle_counter = FLOPPY_IDLE_PERIOD;
+
+ /* Clear result status registers */
+ put_r0_ST0 (result_block, 0);
+ put_r0_ST1 (result_block, 0);
+ put_r0_ST2 (result_block, 0);
+
+ fdc_command = get_type_cmd(command_block);
+ /* for those commands which need a valid floppy be inserted
+ we may have to create an independent thread to perform
+ the real operation if there is currenly no media
+ in the drive. The reason of this independent thread is that
+ the FDC is always in its execution phase even though there is
+ not media in the drive. As soon as you insert a media(bad or
+ good), it then performs its operation, terminates the phase,
+ raises interrupt and enters result phase. Some applications just
+ do a read id and then wait the interrupt to occur no matter how
+ long the user will take to insert a media. To do this I broke up
+ the fdc_command routine so that both main and the fdc thread can
+ use the same code. There is not a good point that we can close the
+ thread handle as soon as it terminated. Therefore, we close the
+ handle on next fdc command
+ */
+ if (fdc_thread_handle != NULL) {
+ CloseHandle(fdc_thread_handle);
+ fdc_thread_handle = NULL;
+ }
+
+ if ( (auto_lock = (fdc_command == FDC_WRITE_DATA || fdc_command == FDC_FORMAT_TRACK)) ||
+ fdc_command == FDC_READ_DATA ||
+ fdc_command == FDC_READ_ID ||
+ fdc_command == FDC_READ_TRACK) {
+ // this might fail due to media changed and from FDC point of
+ // view, media change is meaningless. Therefore, we close the
+ // handle to the drive and reopen it so that the file system
+ // will mount a new volume for us. Then we check the the
+ // media again. If it still fails, we are sure that there is
+ // no media in the drive so we go ahead to create a thread.
+ if (!nt_floppy_media_check(drive)) {
+ nt_floppy_close(drive);
+ get_drive_handle(drive, *pusCurrentPDB, auto_lock);
+ if (!nt_floppy_media_check(drive)) {
+ fdc_parms.auto_lock = auto_lock;
+ fdc_parms.command_block = command_block;
+ fdc_parms.result_block = result_block;
+ fdc_parms.owner_pdb = *pusCurrentPDB;
+ fdc_thread_handle = CreateThread(NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)fdc_thread,
+ (PVOID)&fdc_parms,
+ 0,
+ &fdc_thread_id
+ );
+ return FAILURE;
+ }
+ else { // media changed
+ fdc_read_write(command_block, result_block);
+ return SUCCESS;
+ }
+
+ }
+ else {
+ fdc_read_write(command_block, result_block);
+ return SUCCESS;
+ }
+ }
+
+ /* get disk bumpf */
+ C = get_c0_cyl (command_block);
+ H = get_c0_hd (command_block);
+ S = get_c0_sector (command_block);
+ N = get_c0_N (command_block);
+
+ /* block timer to prevent interrupted system calls */
+ host_block_timer ();
+
+ switch (get_type_cmd (command_block))
+ {
+
+ case FDC_SPECIFY:
+#ifndef PROD
+ if (rflop_dbg & RFLOP_SPECIFY) {
+ OutputDebugString("Specify\n");
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+ break;
+
+
+ case FDC_SENSE_DRIVE_STATUS:
+
+#ifndef PROD
+ if (rflop_dbg & RFLOP_SENSEDRV)
+ OutputDebugString("Sense Drive Status\n");
+#endif
+ D = get_c7_drive (command_block);
+ put_r2_ST3_fault (result_block,0);
+ put_r2_ST3_ready (result_block,1);
+ put_r2_ST3_track_0 (result_block,(flp->last_head_seek == 0?1:0));
+ put_r2_ST3_two_sided (result_block,1);
+ put_r2_ST3_head_address (result_block,0);
+ put_r2_ST3_unit (result_block,D);
+ break;
+
+ /* RECALIBRATE and SEEK do not really return any results */
+ /* However, we return results here which are used by gfi.c */
+ /* to construct the results for any following SenseInterruptStatus command */
+ case FDC_RECALIBRATE:
+
+#ifndef PROD
+ if (rflop_dbg & RFLOP_RECAL)
+ OutputDebugString("Recalibrate\n");
+#endif
+ D = get_c5_drive (command_block);
+ put_r3_ST0 (result_block,0);
+ put_r1_ST0_int_code (result_block,0);
+ put_r1_ST0_seek_end (result_block,1);
+ put_r1_ST0_unit (result_block,D);
+ put_r3_PCN (result_block,0);
+ flp->last_seek = flp->last_head_seek = 0;
+ flp->C = 0;
+ break;
+
+ case FDC_SEEK:
+
+ D = get_c8_drive (command_block);
+ C = get_c8_new_cyl (command_block);
+
+#ifndef PROD
+ if (rflop_dbg & RFLOP_SEEK) {
+ sprintf(dump_buf, "Seek: D C = %d %d \n", D, C);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+
+ put_r3_ST0(result_block,0);
+ put_r1_ST0_head_address(result_block,1);
+ put_r1_ST0_seek_end(result_block,1);
+ put_r1_ST0_int_code(result_block,0);
+ put_r1_ST0_unit(result_block,D);
+ put_r3_PCN(result_block,C);
+ flp->last_seek = C;
+ flp->last_head_seek = min(flp->last_seek,flp->max_track);
+ flp->C = C;
+ break;
+
+ default:
+
+#ifndef PROD
+ sprintf(dump_buf, "Receive unsupported command: command = %d\n",
+ get_type_cmd(command_block));
+ OutputDebugString(dump_buf);
+#endif
+
+ put_r0_ST0 (result_block, 0);
+ put_r1_ST0_int_code (result_block, 2);
+
+ note_trace1 (GFI_VERBOSE,"FDC: Unimplemented command, type %d",
+ get_type_cmd (command_block));
+ }
+
+
+#ifndef PROD
+ if (io_verbose & GFI_VERBOSE) {
+ fprintf(trace_file,
+ "FDC: results %02x %02x %02x %02x %02x %02x %02x\n\n",
+ result_block[0], result_block[1], result_block[2],
+ result_block[3], result_block[4], result_block[5],
+ result_block[6]);
+ }
+#endif /* !PROD */
+
+ host_release_timer ();
+
+ return SUCCESS;
+}
+
+/********************************************************/
+
+/* turn the motor on */
+SHORT
+nt_rflop_drive_on IFN1(UTINY, drive)
+{
+ FLP flp = &floppy_data[drive];
+
+ note_trace0 (GFI_VERBOSE, "FDC: Drive on command");
+#ifndef PROD
+ if (rflop_dbg & RFLOP_DRIVE_ON) {
+ sprintf(dump_buf, "drive on: drive = %d\n", drive);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+
+ if (drive >= number_of_floppy)
+ {
+ note_trace1 (GFI_VERBOSE,
+ "FDC: Invalid drive %d accessed", drive);
+
+ return (FAILURE);
+ }
+
+ flp->motor_state = MOTOR_ON;
+
+ return (SUCCESS);
+}
+
+/********************************************************/
+
+/* turn the motor off */
+SHORT
+nt_rflop_drive_off IFN1(UTINY, drive)
+{
+ FLP flp = &floppy_data[drive];
+ note_trace0 (GFI_VERBOSE, "FDC: Drive off command");
+#ifndef PROD
+ if (rflop_dbg & RFLOP_DRIVE_OFF) {
+ sprintf(dump_buf, "drive off: drive = %d\n", drive);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+
+ if (drive >= number_of_floppy)
+ {
+ note_trace1 (GFI_VERBOSE,
+ "FDC: Invalid drive %d accessed", drive);
+
+ return (FAILURE);
+ }
+
+ flp->motor_state = MOTOR_OFF;
+
+ /* I believe the line below makes booting off of low density
+ * diskettes problematical, particularly after restarts.
+ * Make your own mind up, the DEC code does it, the Sparc
+ * doesn't (as at 11/9/92)
+// we have no reason to do so in NT. As far as change line concerned,
+// the file system will tell us "media has been changed" when we ask
+// it to do some real work.
+// flp->change_line_state = TRUE;
+ */
+
+ return (SUCCESS);
+}
+
+/********************************************************/
+
+/* set the data transfer rate
+ * This controls the "density" of the floppy: the rate MUST
+ * match the actual media density for the disk controller to
+ * be able to read the sectors.
+ */
+SHORT
+nt_rflop_rate IFN2(UTINY, drive, half_word, rate)
+{
+ short new_density;
+// basically, "set rate applied to every drive since we have
+// only one FDC(and mutiple drive).
+
+#if 0
+ FLP flp = &floppy_data[drive];
+
+ switch (rate)
+ {
+ /* 2.88M high-density floppies */
+ case DCR_RATE_1000:
+
+ flp->density_state = DENSITY_EXTENDED;
+ set_floppy_parms (flp);
+ break;
+
+ /* 1.2M or 1.44M high-density floppies */
+ case DCR_RATE_500:
+
+ flp->density_state = DENSITY_HIGH;
+ set_floppy_parms (flp);
+ break;
+
+ /* 360K or 720K low-density floppies */
+ case DCR_RATE_250:
+ case DCR_RATE_300:
+
+ flp->density_state = DENSITY_LOW;
+ set_floppy_parms (flp);
+ break;
+
+ /* crapola density passed */
+ default:
+
+ return FAILURE;
+ }
+ note_trace2 (GFI_VERBOSE, "FDC: Set rate %0x => density %d",
+ rate, flp->density_state);
+ /* read floppy's boot sector */
+ /* to determine the real density */
+// guess_media_density (drive);
+#endif
+#ifndef PROD
+ if (rflop_dbg & RFLOP_RATE) {
+ sprintf(dump_buf, "set rate: rate = %d\n", rate);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+
+ switch (rate) {
+ case DCR_RATE_1000:
+ new_density = DENSITY_EXTENDED;
+ break;
+ case DCR_RATE_500:
+ new_density = DENSITY_HIGH;
+ break;
+ case DCR_RATE_300:
+ case DCR_RATE_250:
+ new_density = DENSITY_LOW;
+ break;
+ default:
+ return FAILURE;
+
+ }
+ if (new_density != density_state) {
+ density_state = new_density;
+ density_changed = TRUE;
+ }
+ return SUCCESS;
+}
+
+
+/********************************************************/
+
+/* return the state of the change line */
+SHORT
+nt_rflop_change IFN1(UTINY, drive)
+{
+ FLP flp = &floppy_data[drive];
+ note_trace1 (GFI_VERBOSE, "FDC: change_line %c",
+ flp->change_line_state? 'T':'F');
+
+ // if fla has been reset or the current change line is on(no media),
+ // close the drive and reopen it. This is done because
+ // nt_floppy_media_check(IOCTL_DISK_CHECK_VERIFY) will continue
+ // to report media change even the users have a new disketter inserted.
+ //
+ if (fdc_reset || flp->change_line_state) {
+ fdc_reset = FALSE;
+ nt_floppy_close(drive);
+ }
+ get_drive_handle(drive, *pusCurrentPDB, FALSE);
+ flp->change_line_state = !nt_floppy_media_check(drive);
+
+#ifndef PROD
+ if (rflop_dbg & RFLOP_CHANGE) {
+ sprintf(dump_buf, "Check Change Line: line = %d\n", flp->change_line_state);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+
+ return(flp->change_line_state);
+}
+
+/********************************************************/
+
+/* return the type of the drive */
+SHORT
+nt_rflop_drive_type IFN1(UTINY, drive)
+{
+ FLP flp = &floppy_data[drive];
+
+
+/* setup base media type depending on drive type */
+// I don't understand why we have to do this stuff every time.
+ switch (flp->drive_type)
+ {
+ /* 5.25" drives */
+ case GFI_DRIVE_TYPE_360:
+ case GFI_DRIVE_TYPE_12:
+
+ flp->flop_type = GFI_DRIVE_TYPE_360;
+ break;
+
+ /* 3.5" drives */
+ case GFI_DRIVE_TYPE_720:
+ case GFI_DRIVE_TYPE_144:
+ case GFI_DRIVE_TYPE_288:
+
+ flp->flop_type = GFI_DRIVE_TYPE_720;
+ break;
+
+ default:
+ break;
+ }
+
+ set_floppy_parms(flp);
+ note_trace2 (GFI_VERBOSE, "FDC: flop_type %d density %d",
+ flp->flop_type, flp->drive_type - flp->flop_type);
+
+ return (flp->drive_type);
+}
+
+/********************************************************/
+
+/* close and reopen the device */
+SHORT
+nt_rflop_reset IFN2(FDC_RESULT_BLOCK *, result_block, UTINY, drive)
+{
+ FLP flp = &floppy_data[drive];
+
+ note_trace0 (GFI_VERBOSE, "FDC: Reset command");
+
+#ifndef PROD
+ if (rflop_dbg & RFLOP_RESET) {
+ OutputDebugString("reset\n");
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+ /* clear change line */
+ flp->change_line_state = FALSE;
+ fdc_reset = TRUE;
+
+ if (fdc_thread_handle) { // signal thread to exit
+ CloseHandle(fdc_thread_handle);
+ fdc_thread_handle = NULL;
+ }
+ return (SUCCESS);
+}
+
+
+// this is the independent thread which performs FDC operation.
+// this thread is not created from the beginning, instead, it was
+// created on demand.
+void fdc_thread(PFDC_PARMS fdc_parms)
+{
+ BYTE drive, fdc_command;
+ FDC_CMD_BLOCK * command_block;
+ BOOL auto_lock;
+ USHORT pdb;
+ command_block = fdc_parms->command_block;
+ auto_lock = fdc_parms->auto_lock;
+ pdb = fdc_parms->owner_pdb;
+ drive = get_type_drive(command_block);
+ fdc_command = get_type_cmd(command_block);
+ while (TRUE) {
+ // if there is media inserted, perform the operation
+ // and enter result phase.
+ if (get_drive_handle(drive, pdb, auto_lock) != INVALID_HANDLE_VALUE &&
+ nt_floppy_media_check(drive)) {
+ // force the file system to remount the volume
+ nt_floppy_close(drive);
+ // and then perform the operation
+ fdc_read_write (command_block, fdc_parms->result_block);
+ // raise an interrupt
+ fdc_command_completed(drive, fdc_command);
+ break;
+ }
+ // if reset happen, quit
+ if (fdc_thread_handle == NULL)
+ break;
+ }
+}
+
+SHORT
+fdc_read_write (
+FDC_CMD_BLOCK * command_block,
+FDC_RESULT_BLOCK * result_block
+)
+{
+
+ USHORT transfer_count; /* Surely counts cannot be negative? GM */
+ FLP flp;
+ BOOL failed = FALSE;
+ UTINY C, H, N, S, D, drive, fdc_command;
+ USHORT dma_size;
+ ULONG transfer_size;
+ ULONG transferred_size;
+ long transfer_start;
+ sys_addr dma_address;
+
+ drive = get_type_drive(command_block);
+ fdc_command = get_type_cmd(command_block);
+
+ /* get disk bumpf */
+ C = get_c0_cyl (command_block);
+ H = get_c0_hd (command_block);
+ S = get_c0_sector (command_block);
+ N = get_c0_N (command_block);
+
+ flp = &floppy_data[drive];
+ /* block timer to prevent interrupted system calls */
+ host_block_timer ();
+ if (fdc_command != FDC_FORMAT_TRACK) {
+ if ((density_changed || drive != last_drive) &&
+ guess_media_density(drive) != DENSITY_UNKNOWN) {
+ set_floppy_parms(flp);
+ density_changed = FALSE;
+ last_drive = drive;
+ }
+ if (density_state != flp->media_density) {
+ put_r0_ST0 (result_block, 0x40);
+ put_r0_ST1 (result_block, 0);
+ put_r1_ST1_no_address_mark (result_block,1);
+ put_r0_ST2 (result_block, 0);
+#ifndef PROD
+ sprintf(dump_buf, "density mismatch: %d <-> %d\n", density_state,
+ flp->media_density);
+ OutputDebugString(dump_buf);
+#endif
+ goto fdc_read_write_exit;
+ }
+ }
+
+
+ /*
+ * Do common setup processing, if read or write
+ */
+ if (fdc_command == FDC_READ_DATA ||
+ fdc_command == FDC_WRITE_DATA) {
+ /*
+ * Find out how much gunk to transfer
+ */
+ dma_enquire (DMA_DISKETTE_CHANNEL, &dma_address, &dma_size);
+ transfer_size = dma_size + 1;
+#ifndef PROD
+ if (transfer_size > BS_DISK_BUFFER_SIZE)
+ always_trace2("FDC: transfer size ( %d ) greater than disk buffer size %d\n", transfer_size, BS_DISK_BUFFER_SIZE);
+#endif /* PROD */
+ /* check params passed are DOS compatible */
+ if (! dos_compatible (flp, C, H, S, N) ||
+ density_state != flp->media_density) {
+ sprintf(dump_buf, "Incompatible DOS diskette, C H R N = %d %d %d %d\n",
+ C, H, S, N);
+ OutputDebugString(dump_buf);
+// do not pop up this annoy message because some applications are simply
+// "probing" the diskette. We just fail the call.
+// host_direct_access_error((ULONG) NOSUPPORT_FLOPPY);
+#ifndef PROD
+
+ if (!dos_compatible (flp, C, H, S, N)) {
+ note_trace0 (GFI_VERBOSE,
+ "Refused: not DOS compatible");
+ }
+ if (density_state != flp->media_density) {
+ note_trace0 (GFI_VERBOSE,
+ "Refused: density mismatch");
+ }
+#endif /* !PROD */
+ /* Sector not found or wrong size */
+ put_r0_ST0 (result_block,0x40);
+ put_r0_ST1 (result_block,0);
+ if (density_state != flp->media_density) {
+ put_r1_ST1_no_address_mark (result_block,1);
+ } else {
+ put_r1_ST1_no_data (result_block,1);
+ }
+ put_r0_ST2 (result_block,0);
+ goto fdc_read_write_exit;
+ }
+ /* work out start position on floppy and sector count */
+ transfer_start = dos_offset (flp, C, H, S);
+ transfer_count = (USHORT)(transfer_size / PC_BYTES_PER_SECTOR);
+#ifndef PROD
+ if (rflop_dbg & (RFLOP_READ | RFLOP_WRITE)) {
+ sprintf(dump_buf, "Read/Write Sector: start offset = 0x%lx\n",
+ transfer_start);
+ OutputDebugString(dump_buf);
+ sprintf(dump_buf, "Read/Write Sector: size = 0x%x bytes\n", transfer_size);
+ OutputDebugString(dump_buf);
+ }
+#endif
+
+ }
+
+ switch (fdc_command)
+ {
+ case FDC_READ_DATA:
+#ifndef PROD
+ if (rflop_dbg & RFLOP_READ) {
+ sprintf(dump_buf, "Read Sectors: C H R N = %d %d %d %d\n",
+ C, H, S, N);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+
+ if (!failed) {
+ transferred_size = nt_floppy_read(drive,
+ transfer_start,
+ transfer_size,
+ disk_buffer
+ );
+ if (transferred_size != transfer_size) {
+ last_error = GetLastError();
+ sprintf(dump_buf, "Read Error, code = %lx\n", last_error);
+ OutputDebugString(dump_buf);
+ failed = TRUE;
+ }
+ else {
+ dma_request (DMA_DISKETTE_CHANNEL,
+ (char *)disk_buffer, (USHORT)transfer_size);
+ }
+ }
+
+ if (failed){
+ put_r0_ST0 (result_block, 0x40);
+ put_r0_ST1 (result_block, 0);
+ put_r1_ST1_no_data (result_block, 1);
+ put_r0_ST2 (result_block, 0);
+ }
+ else {
+ put_r0_ST0 (result_block, 0x04);
+ put_r0_ST1 (result_block, 0);
+ put_r0_ST2 (result_block, 0);
+ put_r1_ST0_unit (result_block, drive);
+ put_r1_ST0_head_address(result_block, H);
+ }
+
+ flp->C = C;
+ flp->H = H;
+ flp->R = S;
+ flp->N = N;
+ update_chrn (flp,
+ (UTINY)(get_c0_MT(command_block)),
+ (UTINY)(get_c0_EOT(command_block)),
+ (UTINY)transfer_count
+ );
+ /* What should these really be? */
+ put_r0_cyl (result_block, flp->C);
+ put_r0_head (result_block, flp->H);
+ put_r0_sector (result_block, flp->R);
+ put_r0_N (result_block, flp->N);
+ break;
+
+ case FDC_WRITE_DATA:
+#ifndef PROD
+ if (rflop_dbg & RFLOP_WRITE) {
+ sprintf(dump_buf, "Write Sectors: C H R N = %d %d %d %d\n",
+ C, H, S, N);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+ if (!failed) {
+ /* copy from Intel space */
+ dma_request (DMA_DISKETTE_CHANNEL, (char *) disk_buffer,
+ (USHORT)transfer_size);
+ transferred_size = nt_floppy_write(drive,
+ transfer_start,
+ transfer_size,
+ disk_buffer
+ );
+ if (transferred_size != transfer_size) {
+ last_error = GetLastError();
+ sprintf(dump_buf, "Write Error, code = %lx\n", last_error);
+ OutputDebugString(dump_buf);
+ failed = TRUE;
+ }
+ }
+
+ /* Clear down result bytes */
+ put_r0_ST0 (result_block, 0);
+ put_r0_ST1 (result_block, 0);
+ put_r0_ST2 (result_block, 0);
+
+ if (failed)
+ {
+ put_r1_ST0_int_code (result_block, 1);
+
+ /* make sure we get the correct error for EROFS */
+ if (last_error == ERROR_WRITE_PROTECT)
+ put_r1_ST1_write_protected (result_block, 1);
+ else
+ put_r1_ST1_no_data (result_block, 1);
+ }
+ else
+ {
+ put_r1_ST0_head_address (result_block, H);
+ put_r1_ST0_unit(result_block, drive);
+ }
+
+ flp->C = C;
+ flp->H = H;
+ flp->R = S;
+ flp->N = N;
+
+ update_chrn (flp,
+ (UTINY)(get_c1_MT(command_block)),
+ (UTINY)(get_c1_EOT(command_block)),
+ (UTINY)transfer_count
+ );
+ put_r0_cyl (result_block, flp->C);
+ put_r0_head (result_block, flp->H);
+ put_r0_sector (result_block, flp->R);
+ put_r0_N (result_block, flp->N);
+ break;
+
+ case FDC_READ_TRACK:
+#ifndef PROD
+ if (rflop_dbg & RFLOP_READTRACK) {
+ OutputDebugString("Read Tracks\n");
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+
+ break;
+
+ case FDC_FORMAT_TRACK:
+
+ dma_enquire (DMA_DISKETTE_CHANNEL, &dma_address, &dma_size);
+ transfer_size = dma_size + 1;
+ /* copy from Intel space */
+ dma_request (DMA_DISKETTE_CHANNEL, (char *) disk_buffer,
+ (USHORT)transfer_size);
+
+ D = get_c8_drive(command_block);
+ H = get_c8_head(command_block);
+ flp = &floppy_data[D];
+#ifndef PROD
+ if (rflop_dbg & RFLOP_FORMAT) {
+ sprintf(dump_buf, "Format Track: C H Media = %d %d %d \n",
+ flp->last_seek, H, flp->flop_type + density_state);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+ if (!nt_floppy_format(D,
+ flp->last_seek,
+ H,
+ media_table[flp->flop_type + density_state]
+ )) {
+ last_error = GetLastError();
+ sprintf(dump_buf, "Format Error, code = %lx\n", last_error);
+ OutputDebugString(dump_buf);
+ failed = TRUE;
+ }
+ if (!failed) {
+ put_r0_ST0 (result_block, 0);
+ put_r0_ST1 (result_block, 0);
+ put_r0_ST2 (result_block, 0);
+ // C H R N are meaningless on formatting
+ }
+ else {
+ put_r0_ST0 (result_block, 0x40);
+ put_r1_ST0_head_address (result_block, H);
+ put_r1_ST0_unit(result_block, D);
+ put_r0_ST1 (result_block, 0);
+ if (last_error == ERROR_WRITE_PROTECT) {
+ put_r1_ST1_write_protected (result_block, 1);
+ }
+ put_r0_ST2 (result_block, 0);
+ }
+ break;
+
+ case FDC_READ_ID:
+
+ H = get_c4_head(command_block);
+ /* check if cylinder number massaging required */
+ if ((flp->flop_type + density_state) == GFI_DRIVE_TYPE_360)
+ {
+ /* 5.25" low density, 40 tracks */
+ C = (UTINY) (flp->last_seek / 2);
+ put_c0_cyl (result_block, C);
+
+ }
+ else
+ {
+ /* no massage required, 80 tracks */
+ C = (UTINY)flp->last_seek;
+ put_r0_cyl (result_block, C);
+
+ }
+ if (flp->C < flp->trks_per_disk) {
+ put_r1_ST0_unit(result_block, drive);
+ put_r1_ST0_head_address(result_block, H);
+ put_r0_head (result_block, H);
+ put_r0_sector (result_block, flp->R);
+ put_r0_N (result_block, flp->N);
+ C = flp->C;
+ put_r0_cyl(result_block, flp->C);
+ }
+ else
+ C = flp->trks_per_disk - 1;
+
+ put_r0_cyl(result_block, C);
+#ifndef PROD
+ if (rflop_dbg & RFLOP_READID) {
+ sprintf(dump_buf, "Read ID: C H R N = %d %d %d %d\n",
+ C, H, flp->R, flp->N);
+ OutputDebugString(dump_buf);
+ if (rflop_dbg & RFLOP_BREAK)
+ nt_rflop_break();
+ }
+#endif
+ }
+
+ if (failed)
+ density_changed = TRUE;
+fdc_read_write_exit:
+
+ return SUCCESS;
+
+}
+/********************************************************/
+
+/* INTERNALLY USED FUNCTIONS */
+
+/* In order to read the data on the floppy, the floppy controller must
+ * be set to the same density (rate) as was used to write the data.
+ * A mismatch in densities will cause read failures, and DOS uses these
+ * failures as a way to probe the diskette for the correct density.
+ *
+ * To emulate the floppy controller correctly, we must somehow
+ * guess the density of the media and produce fake "read failures" if the
+ * controller density doesn't match the media density.
+ *
+ * On the assumption that the operating system has already done this,
+ * and that we are looking at a DOS floppy, nt_flop.c can read the
+ * "total number of sectors" value from the boot sector and guess
+ * the density accordingly. There should be no need for this function
+ * if you have fairly direct access to the disk controller.
+ */
+ int probelist[] = { 720-1, 1440-1, 2400-1, 2880-1, 5760-1, 0-1};
+
+ SHORT
+guess_media_density IFN1(UTINY, drive)
+{
+ int total_sectors;
+ int *probe;
+ FLP flp;
+ ULONG transferred_size;
+
+ flp = &floppy_data[drive];
+ transferred_size = nt_floppy_read(drive,
+ 0L,
+ PC_BYTES_PER_SECTOR,
+ (PBYTE) disk_buffer
+ );
+
+ if (transferred_size != PC_BYTES_PER_SECTOR) {
+ last_error = GetLastError();
+ OutputDebugString("Unknown Media\n");
+ /* assume that the disk is unformatted */
+ return(flp->media_density = DENSITY_UNKNOWN);/* impossible value */
+ }
+
+
+ /* check for a DOS boot block
+ *
+ * AccessPC has shown that 0x55, 0xaa is not the only magic
+ * number in use, and it might be better to check the total_sectors
+ * number itself for a valid size. This algorithm is safe, but may
+ * do unnecessary disk reads if an different magic number is used.
+ */
+
+ /* the AA, 55 signature sometime doesn't work at all, It should
+ be done as DOS */
+
+ if ((disk_buffer[0] == 0x69 || disk_buffer[0] == 0xE9 ||
+ (disk_buffer[0] == 0xEB && disk_buffer[2] == 0x90)) &&
+ (disk_buffer[21] & 0xF0) == 0xF0 ) {
+ /* read total number of sectors, and thus deduce density
+ */
+ total_sectors = disk_buffer [20] * 256 + disk_buffer [19];
+ } else {
+ note_trace2 (GFI_VERBOSE,
+ "not a DOS boot block: magic = %02x %02x",
+ disk_buffer[510], disk_buffer[511]);
+
+ /* probe disk by reading last sectors for each size
+ * (in order) until the read fails.
+ */
+ total_sectors = 0;
+ for (probe=probelist; *probe != 0; probe++) {
+ transferred_size = nt_floppy_read(drive,
+ (*probe)*PC_BYTES_PER_SECTOR,
+ PC_BYTES_PER_SECTOR,
+ disk_buffer
+ );
+ if (transferred_size != PC_BYTES_PER_SECTOR)
+ break; /* out of the for loop */
+ total_sectors = (*probe) + 1;
+ }
+ }
+
+ switch (total_sectors)
+ {
+ case 0:
+ note_trace0( GFI_VERBOSE, "total_sectors = 0 - unformatted");
+ flp->media_density = DENSITY_UNKNOWN; /* impossible value */
+ break;
+
+ case 720:
+ case 1440:
+ flp->media_density = DENSITY_LOW;
+ break;
+
+ case 2400:
+ case 2880:
+ flp->media_density = DENSITY_HIGH;
+ break;
+
+ case 5760:
+ flp->media_density = DENSITY_EXTENDED;
+ break;
+
+ default:
+ note_trace1 (GFI_VERBOSE,
+ "total sectors = %d? Assume high density",
+ total_sectors);
+ flp->media_density = DENSITY_HIGH;
+ break;
+ }
+
+#ifndef PROD
+ note_trace1 (GFI_VERBOSE, "guess_media_density %d",
+ flp->media_density);
+ if (flp->media_density != density_state) {
+ note_trace0 (GFI_VERBOSE,
+ "media & controller densities are incompatible!\n");
+ }
+#endif /* !PROD */
+ return(flp->media_density);
+}
+
+/********************************************************/
+
+/*
+ * dos_offset() calculates the offset in bytes of the required sector
+ * from the start of the nt virtual disk file for a given track
+ * and sector. This maps the floppy data onto the nt file in an
+ * interleaved format with the data for each head adjacent for a
+ * given cylinder.
+ */
+
+int
+dos_offset IFN4(FLP, flp, UTINY, cyl, UTINY, hd, UTINY, sec)
+{
+ int ret;
+
+ ret = (((cyl * PC_HEADS_PER_DISKETTE * flp->secs_per_trk)
+ + (hd * flp->secs_per_trk)
+ + (sec - 1)) * PC_BYTES_PER_SECTOR) ;
+
+ note_trace1(GFI_VERBOSE, "Dos offset %d", ret);
+ return (ret);
+}
+
+/********************************************************/
+
+/*
+ * dos_compatible() returns TRUE if the command block's
+ * cylinder/head/sector is DOS-compatible
+ */
+
+BOOL
+dos_compatible IFN5(FLP, flp, UTINY, cyl, UTINY, hd, UTINY, sec, UTINY, n)
+{
+ BOOL ret;
+
+ ret = ((hd <= PC_HEADS_PER_DISKETTE)
+ && (cyl < flp->trks_per_disk)
+ && (sec <= flp->secs_per_trk)
+ && (n == PC_N_VALUE));
+
+ return (ret);
+}
+
+/********************************************************/
+
+VOID
+set_floppy_parms IFN1(FLP, flp)
+{
+ int index = flp->flop_type + density_state;
+
+ flp->secs_per_trk =
+ floppy_tksc [index].secs_per_trk;
+
+ flp->trks_per_disk =
+ floppy_tksc [index].trks_per_disk;
+
+ flp->max_track = flp->trks_per_disk - 1;
+ note_trace2(GFI_VERBOSE, "set_floppy_parms: secs_per_trk %d, trks_per_disk %d", flp->secs_per_trk, flp->trks_per_disk);
+
+}
+
+/********************************************************/
+
+
+#ifndef PROD
+VOID nt_rflop_break(VOID)
+{
+}
+
+#endif
+
+VOID update_chrn (
+FLP flp,
+UTINY mt,
+UTINY eot,
+UTINY sector_count
+)
+{
+ UTINY new_sector;
+
+#ifndef PROD
+ if (flp->C == break_cylinder &&
+ flp->H == break_head &&
+ flp->R == break_sector)
+ nt_rflop_break();
+#endif
+
+ new_sector = flp->R + sector_count - 1;
+ if (new_sector > eot && mt != 0) {
+ flp->H = 1;
+ new_sector >>= 1;
+ }
+ flp->R = (new_sector == eot) ? 1 : new_sector + 1;
+
+ if (mt != 0 && new_sector == eot) {
+ if(flp->H == 1)
+ flp->C++;
+ flp->H ^= 1;
+ }
+ else {
+ if (new_sector == eot)
+ flp->C++;
+ }
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_sas.c b/private/mvdm/softpc.new/host/src/nt_sas.c
new file mode 100644
index 000000000..ff2d706ae
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_sas.c
@@ -0,0 +1,148 @@
+#include "insignia.h"
+#include "host_def.h"
+/*
+ * VPC-XT Revision 1.0
+ *
+ * Title : Sun4 SAS initialization
+ *
+ * Description : Initialize the host side of sas.
+ *
+ * Author : A. Guthrie
+ *
+ * Notes : None
+ */
+
+static char SccsID[]="@(#)sun4_sas.c 1.3 5/7/91 Copyright Insignia Solutions Ltd.";
+
+#include <sys/types.h>
+#include "xt.h"
+#include "sas.h"
+#include "debug.h"
+
+LOCAL UTINY *reserve_for_M = NULL;
+
+//
+// Temporary pointer to the start of M.
+//
+
+#ifdef SUN_VA
+GLOBAL UTINY *M;
+IMPORT UTINY *self_modify;
+#endif
+
+#ifdef HOST_SAS
+
+#undef sas_load
+#undef sas_loadw
+#undef sas_store
+#undef sas_storew
+#undef sas_fills
+#undef sas_fillsw
+#undef sas_hw_at
+#undef sas_w_at
+#undef sas_dw_at
+#undef sas_loads
+#undef sas_stores
+#undef sas_move_bytes_forward
+#undef sas_move_words_forward
+#undef sas_move_bytes_backward
+#undef sas_move_words_backward
+#undef get_byte_addr
+#undef inc_M_ptr
+#undef M_get_dw_ptr
+
+IMPORT VOID sas_load();
+IMPORT VOID sas_store();
+#ifdef SUN_VA
+IMPORT VOID sas_loadw_swap();
+IMPORT VOID sas_storew_swap();
+#else
+IMPORT VOID sas_loadw();
+IMPORT VOID sas_storew();
+#endif
+IMPORT VOID sas_fills();
+IMPORT VOID sas_fillsw();
+IMPORT half_word sas_hw_at();
+IMPORT word sas_w_at();
+IMPORT double_word sas_dw_at();
+IMPORT VOID sas_loads();
+IMPORT VOID sas_stores();
+IMPORT VOID sas_move_bytes_forward();
+IMPORT VOID sas_move_words_forward();
+IMPORT VOID sas_move_bytes_backward();
+IMPORT VOID sas_move_words_backward();
+IMPORT host_addr Start_of_M_area;
+
+LOCAL host_addr forward_get_addr(addr)
+host_addr addr;
+{
+ return( (host_addr)((long)Start_of_M_area + (long)addr));
+}
+
+LOCAL host_addr forward_inc_M_ptr(p, off)
+host_addr p;
+host_addr off;
+{
+ return( (host_addr)((long)p + (long)off) );
+}
+
+GLOBAL SAS_FUNCTIONS host_sas_funcs =
+{
+ sas_load,
+#ifdef SUN_VA
+ sas_loadw_swap,
+#else
+ sas_loadw,
+#endif
+ sas_store,
+#ifdef SUN_VA
+ sas_storew_swap,
+#else
+ sas_storew,
+#endif
+ sas_fills,
+ sas_fillsw,
+ sas_hw_at,
+ sas_w_at,
+ sas_dw_at,
+ sas_loads,
+ sas_stores,
+ sas_move_bytes_forward,
+ sas_move_words_forward,
+ sas_move_bytes_backward,
+ sas_move_words_backward,
+ forward_get_addr,
+ forward_inc_M_ptr,
+ forward_get_addr,
+};
+
+#endif /* HOST_SAS */
+
+/*
+ Host_sas_init: allocate intel memory space
+*/
+
+#define SIXTY_FOUR_K (1024*64) /* For scratch buffer */
+
+//UTINY *host_sas_init(size)
+//sys_addr size;
+//{
+// return(NULL);
+//}
+
+#ifdef SUN_VA
+/* This is temporary until removed from sdos.o */
+UTINY *host_as_init()
+{
+ assert0(NO,"host_as_init is defunct - call can be removed");
+ return( 0 );
+}
+#endif /* SUN_VA */
+
+//UTINY *host_sas_term()
+//{
+// if(reserve_for_M) free(reserve_for_M);
+//
+// return(reserve_for_M = NULL);
+//}
+
diff --git a/private/mvdm/softpc.new/host/src/nt_sec.c b/private/mvdm/softpc.new/host/src/nt_sec.c
new file mode 100644
index 000000000..dd0a9f818
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_sec.c
@@ -0,0 +1,158 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <vdm.h>
+#include "insignia.h"
+#include "host_def.h"
+#include "wchar.h"
+#include "stdio.h"
+
+#include "ntstatus.h"
+#include <ntddvdeo.h>
+
+#include "nt_fulsc.h"
+#include "nt_det.h"
+#include "nt_thred.h"
+#include "nt_eoi.h"
+#include "host_rrr.h"
+#include "nt_uis.h"
+
+/*
+ * ==========================================================================
+ * Name: nt_sec.c
+ * Author: Jerry Sexton
+ * Derived From:
+ * Created On: 5th February 1992
+ * Purpose: This module contains the function CreateVideoSection
+ * which creates and maps a section which is used to
+ * save and restore video hardware data. It can't be in
+ * nt_fulsc.c because files that include nt.h can't
+ * include windows.h as well.
+ *
+ * (c)Copyright Insignia Solutions Ltd., 1992. All rights reserved.
+ *
+ * 03-May-1994 Jonle
+ * videosection creation has been moved to consrv for security
+ * removed all dead code associated with section maintenance
+ *
+ * ==========================================================================
+ */
+
+
+
+IMPORT int DisplayErrorTerm(int, DWORD, char *, int);
+
+/***************************************************************************
+ * Function: *
+ * LoseRegenMemory *
+ * *
+ * Description: *
+ * Lose the memory that will be remapped as vga regen. NOTE: need to *
+ * make this 'if fullscreen' only. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID LoseRegenMemory(VOID)
+{
+ int a = 0xa0000;
+ ULONG len = 0x20000;
+ NTSTATUS status;
+
+ status = NtFreeVirtualMemory(
+ (HANDLE)GetCurrentProcess(),
+ (PVOID *)&a,
+ &len,
+ MEM_RELEASE);
+ if (!NT_SUCCESS(status))
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+}
+
+
+/***************************************************************************
+ * Function: *
+ * RegainRegenMemory *
+ * *
+ * Description: *
+ * When we switch back from fullscreen to windowed, the real regen *
+ * memory is removed and we are left with a gap. We have to put some *
+ * memory back into that gap before continuing windowed. *
+ * *
+ * Parameters: *
+ * None. *
+ * *
+ * Return value: *
+ * VOID *
+ * *
+ ***************************************************************************/
+GLOBAL VOID RegainRegenMemory(VOID)
+{
+ int regen = 0xa0000;
+ ULONG len = 0x20000;
+ HANDLE processHandle;
+ NTSTATUS status;
+
+ if (!(processHandle = NtCurrentProcess()))
+ DisplayErrorTerm(EHS_FUNC_FAILED,(DWORD)processHandle,__FILE__,__LINE__);
+
+ status = NtAllocateVirtualMemory(
+ processHandle,
+ (PVOID *) &regen,
+ 0,
+ &len,
+ MEM_COMMIT | MEM_RESERVE,
+ PAGE_EXECUTE_READWRITE);
+ if (! NT_SUCCESS(status) )
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+}
+
+
+#ifdef X86GFX
+
+extern RTL_CRITICAL_SECTION IcaLock;
+extern HANDLE hWowIdleEvent;
+
+
+/*****************************************************************************
+ * Function: *
+ * GetROMsMapped *
+ * *
+ * Description: *
+ * Calls NT to get the ROMS of the host machine mapped into place in *
+ * emulated memory. The bottom page (4k) of PC memory is copied into *
+ * the bottom of emulated memory to provide the correct IVT & bios data *
+ * area setup for the mapped bios. (Which will have been initialised). *
+ * *
+ * Parameters: *
+ * None *
+ * *
+ * Return Value: *
+ * None - fails internally on NT error. *
+ * *
+ *****************************************************************************/
+GLOBAL VOID GetROMsMapped(VOID)
+{
+ NTSTATUS status;
+ VDMICAUSERDATA IcaUserData;
+
+ IcaUserData.pIcaLock = &IcaLock;
+ IcaUserData.pIcaMaster = &VirtualIca[0];
+ IcaUserData.pIcaSlave = &VirtualIca[1];
+ IcaUserData.pDelayIrq = &DelayIrqLine;
+ IcaUserData.pUndelayIrq = &UndelayIrqLine;
+ IcaUserData.pDelayIret = &iretHookActive;
+ IcaUserData.pIretHooked = &iretHookMask;
+ IcaUserData.pAddrIretBopTable = &AddrIretBopTable;
+ IcaUserData.phWowIdleEvent = &hWowIdleEvent;
+
+ status = NtVdmControl(VdmInitialize, &IcaUserData);
+ if (!NT_SUCCESS(status))
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+
+}
+#endif //X86GFX
diff --git a/private/mvdm/softpc.new/host/src/nt_smenu.c b/private/mvdm/softpc.new/host/src/nt_smenu.c
new file mode 100644
index 000000000..5d51268ad
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_smenu.c
@@ -0,0 +1,87 @@
+#include <windows.h>
+#include <conapi.h>
+#include "insignia.h"
+#include "xt.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <process.h>
+#include "nt_graph.h"
+#include "nt_smenu.h"
+
+/*================================================================
+Shared data.
+================================================================*/
+BOOL bKillFlag = FALSE; /* shared with nt_input so the application can be */
+ /* terminated in the input thread */
+
+/*================================================================
+Function prototypes.
+================================================================*/
+
+void nt_settings_menu();
+BOOL FAR PASCAL DosDlgProc(HWND hDlg,WORD mess,LONG wParam,LONG lParam);
+
+/*================================================================
+Global data for this file only.
+================================================================*/
+
+static HANDLE InstHandle;
+
+/*================================================================
+The code starts here.
+================================================================*/
+
+void nt_settings_menu()
+{
+InstHandle=GetModuleHandle(NULL);
+if(DialogBox(InstHandle,"DosBox",NULL,(FARPROC)DosDlgProc) == -1)
+ DbgPrint("DialogBox() failed\n");
+}
+
+BOOL FAR PASCAL DosDlgProc(HWND hDlg,WORD mess,LONG wParam,LONG lParam)
+{
+int nItem;
+
+switch(mess)
+ {
+ case WM_INITDIALOG:
+ return TRUE;
+ case WM_COMMAND:
+ {
+ switch(wParam)
+ {
+ case IDD_TERMINATE:
+ {
+ EndDialog(hDlg,0);
+ nItem=MessageBox(hDlg,"WARNING!!!!\n"
+ "Termination is a last resort. You\n"
+ "should end applications by using the\n"
+ "application's quit or exit command",
+ "Termination",
+ MB_OKCANCEL | MB_ICONSTOP |
+ MB_DEFBUTTON2 | MB_SYSTEMMODAL);
+ if(nItem==IDOK)
+ {
+ DbgPrint("Close down the application\n");
+ bKillFlag = TRUE;
+ }
+ }
+ break;
+ case IDD_DGBOX:
+ {
+ }
+ break;
+ case IDD_FULLSCREEN:
+ {
+ }
+ break;
+ case IDOK:
+ case IDCANCEL:
+ EndDialog(hDlg,0);
+ }
+ return TRUE;
+ }
+ break;
+ }
+return FALSE;
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_sound.c b/private/mvdm/softpc.new/host/src/nt_sound.c
new file mode 100644
index 000000000..10cc043ef
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_sound.c
@@ -0,0 +1,420 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntddbeep.h>
+#include <windows.h>
+#include "insignia.h"
+#include "host_def.h"
+/*
+ * VPC-XT Revision 2.0
+ *
+ * Title : sg_sound.c
+ *
+ * Description : This module provides functions to control sound. The
+ * functions are defined:
+ *
+ * host_ring_bell(duration)
+ * host_alarm(duration)
+ * host_timer2_waveform(delay,lowclocks,hiclocks,lohi,repeat)
+ * host_enable_timer2_sound()
+ * host_disable_timer2_sound()
+ *
+ * Author :
+ *
+ * Notes :
+ */
+
+#include "xt.h"
+#include "config.h"
+#include "debug.h"
+#include "error.h"
+#include <stdio.h>
+#include "trace.h"
+#include "video.h"
+#include "debug.h"
+
+
+IMPORT ULONG GetPerfCounter(VOID);
+
+ULONG FreqT2 = 0;
+BOOL PpiState = FALSE;
+BOOL T2State = FALSE;
+ULONG LastPpi = 0;
+ULONG FreqPpi = 0;
+ULONG ET2TicCount=0;
+ULONG PpiCounting = 0;
+
+HANDLE hBeepDevice = 0;
+ULONG BeepCloseCount = 0;
+ULONG BeepLastFreq = 0;
+ULONG BeepLastDuration = 0;
+
+
+// human frequency audible sound range
+#define AUDIBLE_MIN 10
+#define AUDIBLE_MAX 20000
+#define CLICK 100
+
+VOID LazyBeep(ULONG Freq, ULONG Duration);
+void PulsePpi(void);
+
+/*============================================================================
+
+ host_alarm - ring bell irrespective of configuration (used on keyboard
+ buffer overflow for example).
+
+=============================================================================*/
+
+void host_alarm(duration)
+long int duration;
+{
+MessageBeep(MB_OK);
+}
+
+/*========================================================================
+
+ host_ring_bell - ring bell if configured (used by video on output
+ of ^G, for example).
+
+=========================================================================*/
+
+void host_ring_bell(duration)
+long int duration;
+{
+if( host_runtime_inquire(C_SOUND_ON))
+ {
+ host_alarm(duration);
+ }
+}
+
+
+ /* assumes caller holds ica lock */
+
+VOID InitSound( BOOL bInit)
+{
+ if (!bInit) {
+ host_ica_lock();
+ LazyBeep(0L, 0L);
+ if (hBeepDevice && hBeepDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hBeepDevice);
+ hBeepDevice = 0;
+ }
+ host_ica_unlock();
+ return;
+ }
+}
+
+
+HANDLE OpenBeepDevice(void)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING NameString;
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatus;
+ HANDLE hBeep;
+
+ RtlInitUnicodeString( &NameString, DD_BEEP_DEVICE_NAME_U );
+ InitializeObjectAttributes( &ObjectAttributes,
+ &NameString,
+ 0,
+ NULL,
+ NULL
+ );
+
+ Status = NtCreateFile( &hBeep,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatus,
+ NULL,
+ 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN_IF,
+ 0,
+ (PVOID) NULL,
+ 0
+ );
+
+ if (!NT_SUCCESS( Status )) {
+#ifndef PROD
+ printf("NTVDM: OpenBeepDevice Status=%lx\n",Status);
+#endif
+ hBeep = INVALID_HANDLE_VALUE;
+ }
+
+
+ return hBeep;
+}
+
+
+
+
+/*
+ * LazyBeep -
+ * Calls Beep Device Driver asynchronously
+ *
+ * Acceptable parameters are:
+ * (Freq,Dur) Action
+ * (0,0) - stop sound
+ * (nonzero, INFINITE) - play a freq
+ *
+ * not multithreaded safe
+ *
+ */
+VOID LazyBeep(ULONG Freq, ULONG Duration)
+{
+ IO_STATUS_BLOCK IoStatus;
+ BEEP_SET_PARAMETERS bps;
+
+ if (Freq != BeepLastFreq || Duration != BeepLastDuration) {
+ bps.Frequency = Freq;
+ bps.Duration = Duration;
+
+ //
+ // If the duration is < 10 ms, then we assume sound is being
+ // off so remember the state as 0,0 so that we won't turn it
+ // off again.
+ //
+ if (Duration < 10) {
+ BeepLastFreq = 0;
+ BeepLastDuration = 0;
+ }
+ else {
+ BeepLastFreq = Freq;
+ BeepLastDuration = Duration;
+ }
+
+ if (!hBeepDevice) {
+ hBeepDevice = OpenBeepDevice();
+ }
+
+ if (hBeepDevice == INVALID_HANDLE_VALUE) {
+ return;
+ }
+
+ NtDeviceIoControlFile( hBeepDevice,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatus,
+ IOCTL_BEEP_SET,
+ &bps,
+ sizeof(bps),
+ NULL,
+ 0
+ );
+
+ BeepCloseCount = 1000;
+
+ }
+
+
+}
+
+
+
+
+
+/*
+ * PlaySound
+ */
+void PlaySound(BOOL bPulsedPpi)
+{
+ if (PpiState && T2State && FreqT2) {
+ LazyBeep(FreqT2, INFINITE);
+ }
+ else if (FreqPpi > AUDIBLE_MIN) {
+ LazyBeep(FreqPpi,INFINITE);
+ }
+ else if (bPulsedPpi && PpiCounting) {
+ LazyBeep(CLICK,1);
+ }
+ else {
+ LazyBeep(0,0);
+ }
+}
+
+
+
+
+/*
+ * host_timer2_waveform - output specified sound waveform
+ * assumes caller holds ica lock (see base\timer.c)
+ */
+void host_timer2_waveform(int delay,
+ ULONG loclocks,
+ ULONG hiclocks,
+ int lohi,
+ int repeat)
+{
+ ULONG ul;
+
+ if (loclocks == INFINITE || hiclocks == INFINITE) {
+ FreqT2 = 0;
+ }
+ else {
+ ul = loclocks + hiclocks;
+ if (!ul)
+ ul++;
+ FreqT2 = 1193180/ul;
+
+ if (FreqT2 >= AUDIBLE_MAX) {
+ hiclocks = INFINITE;
+ FreqT2 = 0;
+ }
+ else if (FreqT2 <= AUDIBLE_MIN) {
+ loclocks = INFINITE;
+ FreqT2 = 0;
+ }
+ }
+
+ PlaySound(FALSE);
+}
+
+
+
+/*
+ * Updates the hosts Ppi sound state
+ */
+void HostPpiState(BYTE PortValue)
+{
+ BOOL bPpi;
+
+ host_ica_lock();
+
+ T2State = PortValue & 1 ? TRUE: FALSE;
+ bPpi = PortValue & 2 ? TRUE: FALSE;
+
+ if (bPpi != PpiState) {
+ PpiState = bPpi;
+ if (PpiState) {
+ PulsePpi();
+ }
+
+ PlaySound(PpiState);
+ }
+
+ host_ica_unlock();
+}
+
+
+
+
+void PulsePpi(void)
+{
+ static ULONG PpiTicStart=0;
+ static ULONG PpiCycles =0;
+ ULONG ul,Elapsed;
+ ULONG PrevTicCount;
+
+
+ PrevTicCount = ET2TicCount;
+ ET2TicCount = GetTickCount();
+ Elapsed = ET2TicCount > PrevTicCount
+ ? ET2TicCount - PrevTicCount
+ : 0xFFFFFFFF - ET2TicCount + PrevTicCount;
+
+ if (Elapsed > 200) {
+ if (PpiCounting) {
+ PpiCounting = 0;
+ LastPpi = 0;
+ FreqPpi = 0;
+ }
+ return;
+ }
+
+
+ if (!PpiCounting) {
+ PpiCounting = GetPerfCounter();
+ PpiCycles = 0;
+ LastPpi = 0;
+ FreqPpi = 0;
+ PpiTicStart = ET2TicCount;
+ return;
+ }
+
+ if (PpiTicStart + 200 >= ET2TicCount) {
+ PpiCycles++;
+ return;
+ }
+
+
+ ul = GetPerfCounter();
+ Elapsed = ul >= PpiCounting
+ ? ul - PpiCounting
+ : 0xFFFFFFFF - PpiCounting + ul;
+ if (!Elapsed) // insurance!
+ Elapsed++;
+ PpiCounting = ul;
+ PpiTicStart = ET2TicCount;
+
+ /*
+ * Calculate the new avergae Ppi, rounding off to keep
+ * signal from wavering.
+ */
+ ul = (10000 * PpiCycles)/Elapsed;
+ if ((ul & 0x0f) > 7)
+ ul += 0x10;
+ ul &= ~0x0f;
+ ul += 0x10; // fudge factor
+
+ if (!LastPpi)
+ LastPpi = ul;
+ if (!FreqPpi)
+ FreqPpi = LastPpi;
+
+ /*
+ * New Average Ppi is derived from previous AveragePpi,
+ * plus last Ppi sample count plus current Ppi sample
+ * count to get a frequency which has minimal variation
+ * and at the same time responsive to change in the
+ * apps pulse rate.
+ */
+ FreqPpi = ((FreqPpi << 2) + LastPpi + ul)/6;
+ if ((FreqPpi & 0x0f) > 7)
+ FreqPpi += 0x10;
+ FreqPpi &= ~0x0f;
+
+ LastPpi = ul;
+ PpiCycles = 0;
+
+}
+
+
+
+/*============================================================
+
+Function: PlayContinuousTone()
+Called by: The SoftPC timer.
+
+==============================================================*/
+
+void PlayContinuousTone(void)
+{
+ ULONG Elapsed;
+
+ host_ica_lock();
+
+ if (PpiCounting) {
+ Elapsed = GetTickCount();
+ Elapsed = Elapsed > ET2TicCount ? Elapsed - ET2TicCount
+ : 0xFFFFFFFF - ET2TicCount + Elapsed;
+ if (Elapsed > 200) {
+ PpiCounting = 0;
+ LastPpi = 0;
+ FreqPpi = 0;
+ }
+ }
+
+ PlaySound(FALSE);
+
+ if (!BeepLastFreq && !BeepLastDuration &&
+ BeepCloseCount && !--BeepCloseCount)
+ {
+ if (hBeepDevice && hBeepDevice != INVALID_HANDLE_VALUE) {
+ CloseHandle(hBeepDevice);
+ hBeepDevice = 0;
+ }
+ }
+
+ host_ica_unlock();
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_term.c b/private/mvdm/softpc.new/host/src/nt_term.c
new file mode 100644
index 000000000..6a36e8147
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_term.c
@@ -0,0 +1,81 @@
+#include <windows.h>
+#include <vdmapi.h>
+#include "host_def.h"
+#include "insignia.h"
+
+/*
+ * ==========================================================================
+ * Name: nt_term.c
+ * Author: Simon Frost
+ * Derived From:
+ * Created On: 7th May 1992
+ * Purpose: This code moved from stubs.c and split to support
+ * the tidy up code and the actual exit code.
+ *
+ * (c)Copyright Insignia Solutions Ltd., 1992. All rights reserved.
+ * ==========================================================================
+ */
+
+#include <conapi.h>
+#include "xt.h"
+#include "nt_graph.h"
+#ifdef HUNTER
+#include "nt_hunt.h"
+#endif /* HUNTER */
+#include "ntcheese.h"
+
+
+IMPORT VOID DeleteConfigFiles(VOID); // from command.lib
+
+/*::::::::::::::::::::::::::::::::::::::::: Do host cleanup before exiting */
+/*:::::::::::::::: Also called from reset() if VDM 'rebooted' */
+
+void host_term_cleanup()
+{
+ GfxCloseDown(); // ensure video section destroyed
+#ifdef X86GFX
+ if (sc.ScreenBufHandle) //dont want to leave console in graphics mode
+ CloseHandle(sc.ScreenBufHandle);
+#endif // X86GFX
+
+ /*:::::::::::::::::::::::::::::::::: Close open printer and comms ports */
+
+ host_lpt_close_all(); /* Close all open printer ports */
+ host_com_close_all(); /* Close all open comms ports */
+ MouseDetachMenuItem(TRUE); /* Force the menu item away on quit */
+
+ DeleteConfigFiles(); // make sure temp config files are deleted
+
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::: Closedown the VDM */
+void host_terminate()
+{
+
+ host_term_cleanup();
+#ifdef HUNTER
+ if (TrapperDump != (HANDLE) -1)
+ CloseHandle(TrapperDump);
+#endif /* HUNTER */
+
+ if(VDMForWOW)
+ ExitVDM(VDMForWOW,(ULONG)-1); // Kill everything for WOW VDM
+ else
+ ExitVDM(FALSE,0);
+
+ ExitProcess(0);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Terminate VDM */
+
+VOID TerminateVDM(void)
+{
+
+ /*
+ * Do base sepcific cleanup thru terminate().
+ * NOTE: terminate will call host_terminate to do host
+ * specific cleanup
+ */
+
+ terminate();
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_thred.c b/private/mvdm/softpc.new/host/src/nt_thred.c
new file mode 100644
index 000000000..c50740952
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_thred.c
@@ -0,0 +1,162 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ nt_thred.c
+
+Abstract:
+
+ Contains entry points for thread creation and destruction. These
+ entry points only need to be used for threads that will execute in
+ application mode.
+
+Author:
+
+ Dave Hastings (daveh) 17-Apr-1992
+
+Revision History:
+
+--*/
+
+#include <windows.h>
+#include <excpt.h>
+#include <stdlib.h>
+#include "nt_timer.h"
+#include "monregs.h"
+
+typedef struct _ThreadStartUpParameters {
+ LPTHREAD_START_ROUTINE lpStartAddress;
+ LPVOID lpParameter;
+} THREADSTARTUPPARAMETERS, *PTHREADSTARTUPPARAMETERS;
+
+DWORD ThreadStartupRoutine(PVOID pv);
+
+
+HANDLE
+WINAPI
+host_CreateThread(
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter,
+ DWORD dwCreationFlags,
+ LPDWORD lpThreadId
+ )
+/*++
+
+Routine Description:
+
+ This routine creates a thread that will later be used to execute
+ 16 bit application instructions. The parameters and end results
+ are the same as the Win 32 CreateThread function. This function
+ allows the IEU to take appropriate action on thread creation.
+
+Arguments:
+
+ lpThreadAttributes -- Supplies the security attributes for the thread
+ dwStackSize -- Supplies the size fo the threads stack
+ lpStartAddress -- Supplies the starting address for the thread
+ lpParameter -- Supplies a parameter to the thread
+ dwCreationFlags -- Supplies flags that control the creation of the thread
+ lpThreadId -- Returns the Id of the thread
+
+Return Value:
+
+ A handle to the thread if successful,
+ 0 otherwise.
+
+--*/
+{
+ HANDLE Thread;
+ PTHREADSTARTUPPARAMETERS ptsp;
+
+ ptsp = (PTHREADSTARTUPPARAMETERS) malloc(sizeof(THREADSTARTUPPARAMETERS));
+ if (!ptsp) {
+ return 0;
+ }
+
+ ptsp->lpStartAddress = lpStartAddress;
+ ptsp->lpParameter = lpParameter;
+
+ Thread = CreateThread(
+ lpThreadAttributes,
+ dwStackSize,
+ ThreadStartupRoutine,
+ ptsp,
+ CREATE_SUSPENDED,
+ lpThreadId
+ );
+
+ if (Thread) {
+/****************************** STF ********************************/
+#if defined(CCPU) || defined(PIG)
+ ccpu386newthread();
+#endif
+/****************************** STF ********************************/
+#ifdef MONITOR
+ cpu_createthread(Thread);
+#endif
+ if (!(dwCreationFlags & CREATE_SUSPENDED))
+ ResumeThread(Thread);
+
+ } else {
+ free(ptsp);
+ }
+
+ return Thread;
+}
+
+
+DWORD ThreadStartupRoutine(PVOID pv)
+{
+ PTHREADSTARTUPPARAMETERS ptsp=pv;
+ THREADSTARTUPPARAMETERS tsp;
+ DWORD dwRet = (DWORD)-1;
+
+ try {
+ tsp = *ptsp;
+ free(ptsp);
+ dwRet = tsp.lpStartAddress(tsp.lpParameter);
+ } except(VdmUnhandledExceptionFilter(GetExceptionInformation())) {
+ ; // we shouldn't arrive here
+ }
+
+ return dwRet;
+}
+
+
+VOID
+WINAPI
+host_ExitThread(
+ DWORD dwExitCode
+ )
+/*++
+
+Routine Description:
+
+ This routine exits a thread. It allows the IEU to take appropriate
+ acction on thread terminiation. This routine only needs to be called
+ for threads have been created with host_CreateThread
+
+Arguments:
+
+ dwExitCode -- Supplies the exit code for the thread.
+
+Return Value:
+
+ None.
+
+--*/
+{
+/****************************** STF ********************************/
+#if defined(CCPU) || defined(PIG)
+ ccpu386exitthread();
+#endif
+/****************************** STF ********************************/
+#ifdef MONITOR
+ cpu_exitthread();
+#endif
+ ExitThread(dwExitCode);
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_timer.c b/private/mvdm/softpc.new/host/src/nt_timer.c
new file mode 100644
index 000000000..bb4c75043
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_timer.c
@@ -0,0 +1,982 @@
+/* INSIGNIA MODULE SPECIFICATION
+ -----------------------------
+
+
+ THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
+ CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MUST
+ NOT BE DISCLOSED TO ANY OTHER PARTIES WITHOUT THE EXPRESS
+ AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS LTD.
+
+DOCUMENT :
+
+RELATED DOCS :
+
+DESIGNER : Dave Bartlett
+
+REVISION HISTORY :
+First version : 20 May 1991 Dave Bartlett
+
+SUBMODULE NAME : nt_timer
+
+SOURCE FILE NAME : nt_timer.c
+
+PURPOSE : To provide the source of timing information
+ for the Win32 SoftPC, so that actions which
+ need to be taken at regular intervals may be
+ correctly scheduled.
+*/
+
+
+/*
+[1.INTERMODULE INTERFACE SPECIFICATION]
+
+[1.0 INCLUDE FILE NEEDED TO ACCESS THIS INTERFACE FROM OTHER SUBMODULES]
+
+ INCLUDE FILE : nt_time.h
+
+[1.1 INTERMODULE EXPORTS]
+
+ PROCEDURES() : int nt_timer_init()
+ int nt_timer_setup()
+ int nt_timer_shutdown()
+ int nt_timer_event()
+
+-------------------------------------------------------------------------
+[1.2 DATATYPES FOR [1.1]
+
+ STRUCTURES/TYPEDEFS/ENUMS:
+
+-------------------------------------------------------------------------
+[1.3 INTERMODULE IMPORTS]
+
+ PROCEDURES() : do_key_repeats() (module keyboard)
+
+-------------------------------------------------------------------------
+=========================================================================
+PROCEDURE : int nt_timer_init()
+
+PURPOSE : To initialise the host timing subsystem
+
+PARAMETERS : none
+
+GLOBALS : none
+
+RETURNED VALUE : 0 => failure
+ : ~0 => success
+
+DESCRIPTION : This function initialises the timing subsystem
+
+ERROR INDICATIONS : return value
+
+ERROR RECOVERY : Timing subsystem has not been initialised
+=========================================================================
+PROCEDURE : int nt_timer_setup()
+
+PURPOSE : To start the host timing subsystem
+
+PARAMETERS : none
+
+GLOBALS : none
+
+RETURNED VALUE : 0 => failure
+ : ~0 => success
+
+DESCRIPTION : This function starts the timing subsystem
+
+ERROR INDICATIONS : return value
+
+ERROR RECOVERY : Timing subsystem has not been started
+=========================================================================
+PROCEDURE : int nt_timer_shutdown()
+
+PURPOSE : To stop the host timing subsystem
+
+PARAMETERS : none
+
+GLOBALS : none
+
+RETURNED VALUE : 0 => failure
+ : ~0 => success
+
+DESCRIPTION : This function stops the timing subsystem
+
+ERROR INDICATIONS : return value
+
+ERROR RECOVERY : Timing subsystem has not been stopped
+=========================================================================
+PROCEDURE : int nt_timer_event()
+
+PURPOSE : To indicate to the timing subsystem that a timer
+ event may now take place, and to cause any time-based
+ activities to occur.
+
+PARAMETERS : none
+
+GLOBALS : none
+
+DESCRIPTION : All functions implementing time-based functions
+ are called if their turn has arrived.
+
+ERROR INDICATIONS : none
+
+ERROR RECOVERY : errors are ignored
+/*=======================================================================
+[3.INTERMODULE INTERFACE DECLARATIONS]
+========================================================================*/
+
+/* [3.1 INTERMODULE IMPORTS] */
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files*/
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "insignia.h"
+#include "host_def.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <time.h>
+#include <excpt.h>
+
+#include "xt.h"
+#include CpuH
+#include "bios.h"
+#include "sas.h"
+#include "timer.h"
+#include "tmstrobe.h"
+#include "gmi.h"
+#include "gfx_upd.h"
+#include "timeval.h"
+#include "timestmp.h"
+#include "host_rrr.h"
+#include "error.h"
+#include "quick_ev.h"
+#include "nt_timer.h"
+#include "nt_uis.h"
+#include "idetect.h"
+
+#include "debug.h"
+#ifndef PROD
+#include "trace.h"
+#include "host_trc.h"
+#endif
+
+#include "ica.h"
+#include "nt_uis.h"
+#include "nt_thred.h"
+#include "nt_com.h"
+#include <ntddvdeo.h>
+#include "conapi.h"
+#include "nt_fulsc.h"
+#include "nt_graph.h"
+#include "nt_det.h"
+#include "nt_reset.h"
+#include "nt_pif.h"
+#include "nt_eoi.h"
+#include "nt_event.h"
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::: INTERMODULE EXPORTS */
+
+IMPORT void ReinitIdealTime(struct host_timeval *);
+THREAD_DATA ThreadInfo;
+CRITICAL_SECTION TimerTickCS;
+CRITICAL_SECTION HBSuspendCS;
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::: Local Declarations */
+
+DWORD Win32_host_timer(void);
+NTSTATUS DelayHeartBeat(LONG Delay);
+VOID host_init_bda_timer(void);
+GLOBAL void rtc_init IFN0();
+VOID InitPerfCounter(VOID);
+DWORD HeartBeatThread(PVOID pv);
+void CreepAdjust(LARGE_INTEGER DiffTime);
+void DemHeartBeat(void);
+
+#ifndef MONITOR
+void quick_tick_recalibrate(void);
+#endif
+
+void rtc_init(void);
+void RtcTick(struct host_timeval *time);
+
+/*::::::::::::::::::::::::::::::::::::::::::::::: INTERNAL DATA DEFINITIONS */
+
+//
+// Perfcounter frequency calculation constants
+//
+ULONG ulFreqHusec;
+ULONG ulFreqSec;
+
+
+//
+// Events for resuming\suspending heartbeat
+//
+HANDLE hHBResumeEvent;
+HANDLE hHBSuspendEvent;
+
+//
+// HeartBeat TimeStamps in usec
+//
+LARGE_INTEGER CurrHeartBeat;
+LARGE_INTEGER TimerEventUSec;
+LARGE_INTEGER CumUSec;
+LARGE_INTEGER CreepUSec;
+LARGE_INTEGER CreepTicCount;
+
+int HeartBeatResumes=0;
+BOOL bDoingTicInterrupt=FALSE;
+BOOL bUpdateRtc;
+
+
+
+
+#if defined (MONITOR) && defined (X86GFX)
+HANDLE SuspendEventObjects[2];
+#endif
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::: NT timer initialise ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void host_timer_init(void)
+{
+
+ ThreadInfo.HeartBeat.Handle = CreateThread(
+ NULL,
+ 8192,
+ HeartBeatThread,
+ NULL,
+ CREATE_SUSPENDED,
+ &ThreadInfo.HeartBeat.ID
+ );
+
+ if(!ThreadInfo.HeartBeat.Handle) {
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ TerminateVDM();
+ }
+
+ InitSound(TRUE);
+
+ return;
+}
+
+/*
+ * TimerInit
+ *
+ * Some of the timerinit stuff was split off, because it needs to be
+ * done before any chance of calling vdm error popups.
+ * Until I understand why creating the heartbeat thread very early
+ * causes a console-ntvdm deadlock, the functions should remain split
+ *
+ */
+void TimerInit(void)
+{
+
+ if(!(hHBResumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ TerminateVDM();
+ }
+
+ if(!(hHBSuspendEvent = CreateEvent(NULL, FALSE, TRUE, NULL))) {
+ DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+ TerminateVDM();
+ }
+
+ InitializeCriticalSection(&TimerTickCS);
+ InitializeCriticalSection(&HBSuspendCS);
+
+ InitPerfCounter();
+
+}
+
+
+/*
+ * HeartBeat Termination
+ *
+ */
+void TerminateHeartBeat(void)
+{
+ NtAlertThread(ThreadInfo.HeartBeat.Handle);
+ if (ThreadInfo.HeartBeat.ID != GetCurrentThreadId())
+ WaitForSingleObjectEx(ThreadInfo.HeartBeat.Handle, 10000, TRUE);
+
+ return;
+}
+
+
+//
+// Initialized by base, initialize frequencies for perf counter
+//
+VOID InitPerfCounter(VOID)
+{
+ LARGE_INTEGER li, liFreq;
+
+
+ NtQueryPerformanceCounter(&li, &liFreq);
+ /* we assumed the frequency never goes beyond 4Ghz(32bits)
+ * if it does someday, this assumption must be removed
+ * and code must be rewritten
+ */
+ ASSERT(liFreq.HighPart == 0);
+ ulFreqSec = liFreq.LowPart;
+ ulFreqHusec = liFreq.LowPart / 10000;
+
+}
+
+//
+// returns perf counter in 100's usecs (0.1 millisec)
+//
+//
+ULONG GetPerfCounter(VOID)
+{
+ LARGE_INTEGER li;
+
+ NtQueryPerformanceCounter(&li, NULL);
+ li = RtlExtendedLargeIntegerDivide(li, ulFreqHusec, NULL);
+ return(li.LowPart);
+}
+
+
+
+//
+// returns perf counter in usec
+//
+//
+void GetPerfCounterUsecs(struct host_timeval *time, PLARGE_INTEGER pliTime)
+{
+ LARGE_INTEGER liSecs;
+ LARGE_INTEGER liUsecs;
+
+ // get time in secs and usecs
+ NtQueryPerformanceCounter(&liSecs, NULL);
+ liSecs = RtlExtendedLargeIntegerDivide(liSecs, ulFreqSec, &liUsecs.LowPart);
+ liUsecs.QuadPart = Int32x32To64(liUsecs.LowPart, 1000000);
+ liUsecs = RtlExtendedLargeIntegerDivide(liUsecs, ulFreqSec, NULL);
+
+ // fill in time if specified
+ if (time) {
+ time->tv_usec = liUsecs.LowPart;
+ time->tv_sec = liSecs.LowPart;
+ }
+
+ // fill in pliTime if specified
+ if (pliTime) {
+ pliTime->QuadPart = liUsecs.QuadPart + liSecs.QuadPart * 1000000;
+ }
+ return;
+}
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::: Timer Event Code :::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::;::::::::::::::::*/
+void host_timer_event()
+{
+
+ if (!VDMForWOW) {
+ unsigned char FgBgPriority;
+
+#ifdef X86GFX
+ /* Don't do timer tick while in fullscreen switch code. */
+ if (NoTicks)
+ return;
+
+ /* Do console calls related to fullscreen switching. */
+ CheckForFullscreenSwitch();
+
+#endif /* X86GFX */
+
+ host_graphics_tick(); // video graphics stuff
+
+
+#ifndef X86GFX
+ /* Are there any screen scale events to process. */
+ GetScaleEvent();
+#endif
+
+ IDLE_tick(); // IDLE accounting
+
+ /*
+ * We can't detect idling on all apps (eg Multiplan). For these apps
+ * a PIF setting for 'Foreground Priority' of < 100% is recomended.
+ * Where this happens, we idle for the 'unwanted' portion of a tick
+ * period.
+ */
+ FgBgPriority = sc.Focus ? WNTPifFgPr : WNTPifBgPr;
+ if (FgBgPriority < 100)
+ PrioWaitIfIdle(FgBgPriority);
+ }
+
+#ifndef MONITOR
+ quick_tick_recalibrate();
+#endif
+
+
+
+#ifdef YODA
+ CheckForYodaEvents();
+#endif
+
+ host_com_heart_beat(); // com device
+
+ host_lpt_heart_beat(); // printer devuce
+
+ host_flpy_heart_beat(); // direct floppy device
+
+ DemHeartBeat();
+
+ time_strobe(); // time/date etc. (NOT time ticks)
+
+ PlayContinuousTone(); // sound emulation
+
+}
+
+
+/*
+ * Called to set up the Bios Data area time update vars.
+ * and the heart beat's counters
+ */
+VOID host_init_bda_timer(void)
+{
+ SYSTEMTIME TimeDate;
+ ULONG Ticks;
+ struct host_timeval time;
+
+
+ CreepTicCount.QuadPart = NtGetTickCount();
+ GetPerfCounterUsecs(&time, &CumUSec);
+ GetLocalTime(&TimeDate);
+
+ Ticks = (ULONG)TimeDate.wHour * 65543 +
+ (ULONG)TimeDate.wMinute * 1092 +
+ (ULONG)TimeDate.wSecond * 18 ;
+
+ if (TimeDate.wHour)
+ Ticks += (ULONG)TimeDate.wHour/3;
+ if (TimeDate.wMinute)
+ Ticks += (ULONG)(TimeDate.wMinute*4)/10;
+ if (TimeDate.wSecond)
+ Ticks += (ULONG)TimeDate.wSecond/5;
+ if (TimeDate.wMilliseconds)
+ Ticks += ((ULONG)TimeDate.wMilliseconds)/54;
+
+ Ticks++; // fudge factor!
+
+ CreepUSec = CumUSec;
+ TimerEventUSec.QuadPart = CumUSec.QuadPart + SYSTEM_TICK_INTV;
+ ReinitIdealTime(&time);
+
+
+ /*
+ * BUGBUG with sas strange errors when writing from non cpu thread
+ *
+ * sas_storew(TIMER_LOW, BDA & 0xffff);
+ * sas_storew(TIMER_HIGH, (BDA >> 16) & 0xffff);
+ * sas_store(TIMER_OVFL, 0x01);
+ */
+ * (word *)(Start_of_M_area + TIMER_HIGH) = (word)(Ticks >> 16);
+ * (word *)(Start_of_M_area + TIMER_LOW) = (word)Ticks;
+ * (half_word *)(Start_of_M_area + TIMER_OVFL) = (half_word)0;
+
+
+ // reset the Real Time Clock
+ rtc_init();
+
+#ifndef MONITOR
+ q_event_init();
+#endif
+
+}
+
+
+
+/* host_GetSysTime, replacement for the base function
+ *
+ *
+ * This routine does not return the system's time of day.
+ * Uses the NT performance counter to obtain time stamping
+ * information for the base to use. The resolution is microsecs.
+ *
+ * Returns nothing, fills in time structure
+ *
+ */
+void host_GetSysTime(struct host_timeval *time)
+{
+ LARGE_INTEGER liTime;
+
+ // Don't call kernel unless we have to.
+ if (bDoingTicInterrupt) {
+ liTime = RtlExtendedLargeIntegerDivide(
+ CurrHeartBeat,
+ 1000000,
+ &time->tv_usec);
+ time->tv_sec = liTime.LowPart;
+ }
+ else {
+ GetPerfCounterUsecs(time, NULL);
+ }
+}
+
+
+/* host_TimeStamp
+ *
+ * This routine does not return the system's time of day.
+ * Uses the NT performance counter to obtain time stamping
+ * information for the base to use. Returns LARGE_INTEGER
+ * with time since boot in usecs.
+ *
+ */
+void host_TimeStamp(PLARGE_INTEGER pliTime)
+{
+ host_ica_lock();
+
+ if (bDoingTicInterrupt) {
+ *pliTime = CurrHeartBeat;
+ }
+ else {
+ GetPerfCounterUsecs(NULL, pliTime);
+ }
+
+ host_ica_unlock();
+}
+
+
+
+
+
+
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::: Win32 timer function entry point :::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+DWORD HeartBeatThread(PVOID pv)
+{
+ DWORD dwRet = (DWORD)-1;
+
+ try {
+
+#ifdef MONITOR
+ //
+ // On x86 we have to force the creation of the critsect lock semaphore
+ // When the heartbeat thread start running the cpu thread holds the
+ // ica lock forcing contention (and creation). See ConsoleInit.
+ //
+ host_ica_lock(); // take ica lock to force creation of critsect
+#endif
+
+
+ //
+ // Set our priority above normal, and wait for signal to
+ // start heartbeat pulses.
+ //
+ // For Wow we raise to time critical because wow apps can
+ // easily invoke a tight client-csr-server bound loop with
+ // boosted priority starving the heartbeat thread. Winbench 311
+ // shows this problem when doing polylines test.
+ //
+ SetThreadPriority(ThreadInfo.HeartBeat.Handle,
+ !(dwWNTPifFlags & COMPAT_TIMERTIC)
+ ? THREAD_PRIORITY_TIME_CRITICAL
+ : THREAD_PRIORITY_HIGHEST
+ );
+
+#ifdef X86GFX
+ SuspendEventObjects[0] = hHBSuspendEvent;
+
+ /* Get the switching event handle. */
+ if (!VDMForWOW) {
+ SuspendEventObjects[1] = GetDetectEvent();
+ }
+ else {
+ SuspendEventObjects[1] = INVALID_HANDLE_VALUE;
+ }
+#endif
+
+#ifdef MONITOR
+ host_ica_unlock();
+#endif
+
+ dwRet = Win32_host_timer();
+
+ }
+ except(VdmUnhandledExceptionFilter(GetExceptionInformation())) {
+ ; // we shouldn't arrive here
+ }
+
+ return dwRet;
+}
+
+
+#ifdef PIG
+int TimerCount = 20;
+#endif /* PIG */
+
+DWORD Win32_host_timer(void)
+{
+ NTSTATUS status;
+#ifdef PIG
+ int count = 0;
+#endif /* PIG */
+ LONG DelayPeriod;
+ LARGE_INTEGER DiffTime;
+ LARGE_INTEGER SystemTickIntv;
+ LARGE_INTEGER SecIntv;
+ LARGE_INTEGER HalfSysIntv;
+ LARGE_INTEGER CreepIntv;
+
+
+ struct host_timeval time;
+
+ DelayPeriod = 50000;
+ SystemTickIntv.QuadPart = SYSTEM_TICK_INTV;
+ HalfSysIntv.QuadPart = SYSTEM_TICK_INTV/2;
+ SecIntv.QuadPart = SYSTEM_TICK_INTV*18;
+ CreepIntv.QuadPart = Int32x32To64(SYSTEM_TICK_INTV, 1200); // >1 hr
+
+
+ /* Start timing loop. */
+ while(1) {
+ status = DelayHeartBeat(DelayPeriod);
+ if (!status) { // reinitialize counters
+HBresume:
+ host_ica_lock();
+ host_init_bda_timer();
+ DelayPeriod = SYSTEM_TICK_INTV - 6000;
+ host_ica_unlock();
+ continue;
+ }
+
+ host_ica_lock();
+ bDoingTicInterrupt = TRUE;
+ /*
+ * Get the current perf counter time, We ignore wrap
+ * since it only happens every few hundred years.
+ */
+ GetPerfCounterUsecs(&time, &CurrHeartBeat);
+
+ /*
+ * Increment the cumulative counter
+ */
+ CumUSec.QuadPart = CumUSec.QuadPart + SYSTEM_TICK_INTV;
+
+ /*
+ * if we have passed the creep interval, Adjust the cumulative
+ * counter for drift between perfcounter and tic counter.
+ */
+ DiffTime.QuadPart = CurrHeartBeat.QuadPart - CreepUSec.QuadPart;
+ if (DiffTime.QuadPart > CreepIntv.QuadPart) {
+ CreepAdjust(DiffTime);
+ }
+
+ /*
+ * Calculate Next Delay Period, based on how far
+ * behind we are. ie CurrTime - CumTime.
+ */
+ DiffTime.QuadPart = CurrHeartBeat.QuadPart - CumUSec.QuadPart;
+
+ if (DiffTime.QuadPart > SecIntv.QuadPart)
+ {
+ DelayPeriod = 13000;
+ }
+ else if (DiffTime.QuadPart > SYSTEM_TICK_INTV)
+ {
+ DelayPeriod = SYSTEM_TICK_INTV/3;
+ }
+ else if (DiffTime.QuadPart >= HalfSysIntv.QuadPart)
+ {
+ DiffTime.QuadPart = (LONGLONG)SYSTEM_TICK_INTV - DiffTime.QuadPart;
+ DelayPeriod = DiffTime.LowPart - 6000;
+ }
+ else {
+ DelayPeriod = SYSTEM_TICK_INTV - 6000 - DiffTime.LowPart;
+ }
+
+
+
+ /*
+ * Update the VirtualTimerHardware
+ */
+#ifdef PIG
+ if (++count >= TimerCount)
+ {
+ time_tick();
+ count = 0;
+ }
+#else
+ time_tick();
+#endif /* PIG */
+
+
+ /*
+ * Update the Real Time Clock
+ */
+ RtcTick(&time);
+
+ bDoingTicInterrupt = FALSE;
+ host_ica_unlock();
+
+
+ /* Timer Event should occur around 18 times per sec
+ * The count doesn't have to be all that accurate, so we
+ * don't try to make up for lost events, and we do this last
+ * to give a chance for hw interrupts to get thru first.
+ */
+ if (TimerEventUSec.QuadPart <= CurrHeartBeat.QuadPart) {
+ TimerEventUSec.QuadPart = CurrHeartBeat.QuadPart + SYSTEM_TICK_INTV;
+ cpu_interrupt(CPU_TIMER_TICK, 0);
+ WOWIdle(TRUE);
+ }
+ }
+
+ return(1);
+}
+
+
+/*
+ * DelayHeartBeat
+ *
+ * waits the Delay as required by caller
+ * while also checking for the following:
+ * - suspend\resume events
+ * - screen switching event (x86 graphics)
+ *
+ * entry : delay time in micro secs
+ * exit : TRUE - reinit counters
+ */
+
+NTSTATUS DelayHeartBeat(LONG Delay)
+{
+ NTSTATUS status;
+ LARGE_INTEGER liDelay;
+
+
+ liDelay.QuadPart = Int32x32To64(Delay, -10);
+
+#ifdef MONITOR
+
+RewaitSuspend:
+ status = NtWaitForMultipleObjects(VDMForWOW ? 1 : 2,
+ SuspendEventObjects,
+ WaitAny,
+ TRUE,
+ &liDelay);
+
+ // delay time has expired
+ if (status == STATUS_TIMEOUT) {
+ return status;
+ }
+
+#ifdef X86GFX // screen switch event
+ if (status == 1) {
+ DoHandShake();
+ liDelay.QuadPart = -10;
+ goto RewaitSuspend;
+ }
+#endif
+
+ // suspend event
+ if (!status) {
+ SuspendEventObjects[0] = hHBResumeEvent;
+ ica_hw_interrupt_cancel(ICA_MASTER,CPU_TIMER_INT);
+ host_DelayHwInterrupt(CPU_TIMER_INT, 0, 0xFFFFFFFF);
+
+RewaitResume:
+ status = NtWaitForMultipleObjects(VDMForWOW ? 1 : 2,
+ SuspendEventObjects,
+ WaitAny,
+ TRUE,
+ NULL);
+
+ // resume event
+ if (!status) {
+ SuspendEventObjects[0] = hHBSuspendEvent;
+ return status;
+ }
+
+
+#ifdef X86GFX // screen switch event
+ if (status == 1) {
+ DoHandShake();
+ goto RewaitResume;
+ }
+#endif
+ }
+
+
+#else // ndef MONITOR
+//
+// On Risc platforms we only have to deal with the
+// HeartBeat Resume\Suspend objects so things are much simpler
+//
+
+ status = NtWaitForSingleObject(hHBSuspendEvent,
+ TRUE,
+ &liDelay);
+
+ if (status == STATUS_TIMEOUT) {
+ return status;
+ }
+
+ if (status == STATUS_SUCCESS) { // suspend event
+ status = NtWaitForSingleObject(hHBResumeEvent, TRUE, NULL);
+ if (status == STATUS_SUCCESS) {
+ return status;
+ }
+ }
+
+#endif
+
+ // alerted to die
+ if (status == STATUS_ALERTED) {
+ CloseHandle(ThreadInfo.HeartBeat.Handle);
+ ThreadInfo.HeartBeat.Handle = NULL;
+ ThreadInfo.HeartBeat.ID = 0;
+ ExitThread(0);
+ }
+
+
+ // Must be an error, announce it to the world
+ DisplayErrorTerm(EHS_FUNC_FAILED, status,__FILE__,__LINE__);
+ TerminateVDM();
+ return status;
+}
+
+/*
+ * CreepAdjust
+ *
+ * Adjusts the perfcounter cum time stamp for drift from system time of
+ * day (Kernel Tick Count)
+ */
+void CreepAdjust(LARGE_INTEGER DiffTime)
+{
+ LARGE_INTEGER DiffTicCount;
+ ULONG ulTicCount;
+
+ // Calculate the elapsed ticcount in usecs
+ ulTicCount = NtGetTickCount();
+ DiffTicCount.LowPart = ulTicCount;
+ DiffTicCount.HighPart = CreepTicCount.HighPart;
+ if (DiffTicCount.LowPart < CreepTicCount.LowPart) {
+ DiffTicCount.HighPart++;
+ }
+ DiffTicCount.QuadPart = DiffTicCount.QuadPart - CreepTicCount.QuadPart;
+ DiffTicCount = RtlExtendedIntegerMultiply(DiffTicCount, 1000);
+
+ // Adjust the CumUsec perfcounter time by the diff
+ // between tick count and perfcounter.
+ DiffTicCount.QuadPart = DiffTicCount.QuadPart - DiffTime.QuadPart;
+ CumUSec.QuadPart = CumUSec.QuadPart - DiffTicCount.QuadPart;
+
+ // Reset the Creep Time stamps
+ CreepTicCount.QuadPart = ulTicCount;
+ CreepUSec = CurrHeartBeat;
+}
+
+
+/* SuspendTimerThread\ResumeTimerThread
+ *
+ * functions to supsend\resume the heartbeat thread
+ * - used by ntvdm when dos apps exit
+ * - used by wow when only wowexec is running
+ * - used by wow for tasks requiring timer tics\BDA tic count updates
+ *
+ * These two functions keep an internal suspend counter, to manage
+ * wows multiple tasks, some which require tics, some don't. As long
+ * as one task requires tics\bda updates, we will deliver them for all
+ * tasks.
+ *
+ */
+
+
+/* SuspendTimerThread
+ *
+ * Blocks the timer thread on an event
+ * Increments internal suspend count
+ *
+ * This function will NOT wait until the heartbeat is safely blocked
+ * before returning.
+ *
+ * entry: void
+ * exit: void
+ *
+ */
+GLOBAL VOID SuspendTimerThread(VOID)
+{
+ RtlEnterCriticalSection(&HBSuspendCS);
+
+ if (!--HeartBeatResumes) {
+ SetEvent(hHBSuspendEvent);
+ }
+
+ RtlLeaveCriticalSection(&HBSuspendCS);
+}
+
+
+
+/* ResumeTimerThread
+ *
+ * restarts the heart beat thread, by setting event
+ * decrements internal suspend count
+ *
+ * entry: void
+ * exit: void
+ *
+ */
+GLOBAL VOID ResumeTimerThread(VOID)
+{
+ RtlEnterCriticalSection(&HBSuspendCS);
+
+ if (!HeartBeatResumes++) {
+ SetEvent(hHBResumeEvent);
+ }
+
+ RtlLeaveCriticalSection(&HBSuspendCS);
+}
+
+
+
+/*
+ * This function handles all of the toplevel
+ * exceptions for all ntvdm threads which are known.
+ * This includes the event thread, heartbeat thread, comms thread,
+ * and all application threads (those which use host_CreateThread()).
+ *
+ * Threads which are not covered are those created by unknown Vdds.
+ *
+ * If the UnHandleExecptionFilter api returns EXECEPTION_EXECUTE_HANDLER
+ * the process will be terminated and this routine will not return.
+ *
+ */
+LONG
+VdmUnhandledExceptionFilter(
+ struct _EXCEPTION_POINTERS *ExceptionInfo
+ )
+{
+ LONG lRet;
+
+ SuspendTimerThread();
+
+ lRet = UnhandledExceptionFilter(ExceptionInfo);
+
+ if (lRet == EXCEPTION_EXECUTE_HANDLER) {
+ NtTerminateProcess(NtCurrentProcess(),
+ ExceptionInfo->ExceptionRecord->ExceptionCode
+ );
+ }
+
+ ResumeTimerThread();
+ return lRet;
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_umb.c b/private/mvdm/softpc.new/host/src/nt_umb.c
new file mode 100644
index 000000000..d6c9a4ffa
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_umb.c
@@ -0,0 +1,1119 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ UMB.C
+
+Abstract:
+
+ UMB management functions for NT MVDM
+
+Author:
+
+ William Hsieh (williamh) Created 21-Sept-1992
+
+[Environment:]
+
+ User Mode, running in the context of MVDM
+
+[Notes:]
+
+ optional-notes
+
+Revision History:
+
+--*/
+#include "nt.h"
+#include "ntrtl.h" // for romdump
+#include "nturtl.h"
+#include "windows.h"
+#include "host_def.h"
+#include "insignia.h"
+#include "stdlib.h"
+#include "xt.h"
+#include CpuH
+#include "error.h"
+#include "sas.h"
+#include "ios.h"
+#include "umb.h"
+
+#include <nt_vdd.h>
+#include <nt_vddp.h>
+#include <emm.h>
+
+PUMBNODE
+SpliceUMB(
+PUMBNODE UMB,
+DWORD dwBase,
+DWORD Size,
+WORD Owner
+);
+
+BOOL
+VDDReserveUMB(
+DWORD dwBase,
+DWORD Size,
+PUMBNODE UMB
+);
+VOID
+xmsReleaseUMBNotify(
+PVOID Address,
+DWORD Size
+);
+PUMBNODE UMBList;
+
+HANDLE UMBSectionHandle;
+
+// This function allocate a address space from the UMB area.
+// Depends on the requester, this function changes the given address
+// space reservation/commitment and ownership states of the block.
+// From the very beginning, InitUMBList reserves every possible UMB and
+// each unused UMB has owner of UMB_OWNER_NONE or UMB_OWNER_ROM.
+// An UMB_OWNER_NONE block is freed and can be claimed by anybody;
+// An UMB_OWNER_ROM is mapped to system ROM area and nobody can
+// claim it except UMB_OWNER_NONE which includes the ROM UMB as
+// usual UMB so that its address space can be used for other purpose.
+// This exception was added for VDDs(trusted requesters) only.
+// An UMB_OWNER_RAM block is reserved and committed. Nobody can claim
+// it except UMB_OWNER_XMS(and UMB_OWNER_XMS can only claim UMB_OWNER_RAM).
+// An UMB_OWNER_EMM block is simply reserved.
+// An UMB_OWNER_XMS block is reserved, committed and under XMS control.
+// An UMB_OWNER_VDD block is claimed by a VDD via VDDInstallMemoryHook.
+// VDD block got special treatment because memory are committed to and
+// decommitted from within the block dynamycally, depends on how the
+// VDD wants to manipulate it.
+//
+// WARNING: The given Size and Address must on system page boundary.
+//
+BOOL
+ReserveUMB(
+WORD Owner,
+PVOID *Address,
+DWORD *Size
+)
+{
+
+#ifdef MONITOR
+ NTSTATUS Status;
+#endif
+
+ PUMBNODE UMB;
+ LARGE_INTEGER SectionOffset;
+
+ DWORD dwBase;
+
+ dwBase = (DWORD)*Address;
+
+ // get the UMB list header
+ UMB = UMBList;
+ SectionOffset.HighPart = 0;
+
+ switch (Owner) {
+ case UMB_OWNER_RAM:
+ // commit memory to every free UMB in the list
+ // this is the only case which works on multiple blocks
+ while (UMB != NULL) {
+ if (UMB->Owner == UMB_OWNER_NONE) {
+#ifndef MONITOR
+ // Is this necessary?
+ sas_connect_memory(UMB->Base, UMB->Base + UMB->Size - 1, SAS_RAM);
+
+#else
+ Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+ (PVOID *)&UMB->Base,
+ 0,
+ &UMB->Size,
+ MEM_COMMIT,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+#endif
+ UMB->Owner = UMB_OWNER_RAM;
+ }
+ UMB = UMB->Next;
+ }
+ break;
+
+ case UMB_OWNER_EMM:
+
+ while (UMB != NULL) {
+ if (UMB->Owner == UMB_OWNER_NONE &&
+ UMB->Size >= *Size &&
+ (dwBase == 0 || (dwBase >= UMB->Base &&
+ (dwBase + *Size) <= UMB->Base + UMB->Size))
+ )
+ break;
+ UMB = UMB->Next;
+ }
+ if (UMB == NULL) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ if (dwBase == 0)
+ dwBase = UMB->Base;
+
+ // the found block may be too big for the request
+ // we have to splice the block if that is the case
+ UMB = SpliceUMB(UMB, dwBase, *Size, UMB_OWNER_EMM);
+ // if failed to do something, simple fail
+ if (UMB == NULL) {
+ return FALSE;
+ }
+#ifdef MONITOR
+ SectionOffset.HighPart = 0;
+ SectionOffset.LowPart = UMB->Base - UMB_BASE_ADDRESS;
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *) &UMB->Base,
+ 0,
+ 0,
+ &SectionOffset,
+ &UMB->Size,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+#endif
+ // return the block address
+ *Address = (PVOID)UMB->Base;
+ break;
+
+ case UMB_OWNER_XMS:
+ // search UMB_OWNER_RAM and claim the ownership
+ while (UMB != NULL && UMB->Owner != UMB_OWNER_RAM) {
+ UMB = UMB->Next;
+ }
+ if (UMB == NULL) {
+ // don't set last error here
+ return FALSE;
+ }
+ else {
+ UMB->Owner = UMB_OWNER_XMS;
+ *Address = (PVOID)UMB->Base;
+ *Size = UMB->Size;
+ }
+ break;
+
+ case UMB_OWNER_VDD:
+ return(VDDReserveUMB(dwBase, *Size, UMB));
+
+// VDDExcludeMem and VDDIncludeMem support cases
+ case UMB_OWNER_NONE:
+ //call to change a rom block to a free UMB block
+ //the given address and size must exactly match
+
+#ifndef MONITOR
+ // on MIPS, rom blocks are BIOS and VIDEO. No reason to change it
+ return FALSE;
+#else
+ while(UMB != NULL && (UMB->Owner != UMB_OWNER_ROM ||
+ UMB->Base != dwBase ||
+ UMB->Size != *Size)) {
+ UMB = UMB->Next;
+ }
+ if (UMB == NULL) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ // unmap the rom first. Kernel map it into a unknown section
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ (PVOID)UMB->Base
+ );
+ if (NT_SUCCESS(Status)) {
+ *Address = (PVOID)UMB->Base;
+ SectionOffset.LowPart = UMB->Base - UMB_BASE_ADDRESS;
+ *Size = UMB->Size;
+ // map the address into our section(reserved)
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ Address,
+ 0,
+ 0,
+ &SectionOffset,
+ Size,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ UMB->Owner = UMB_OWNER_NONE;
+ }
+ break;
+#endif
+
+ case UMB_OWNER_ROM:
+ // case to excluede a UMB
+ while (UMB != NULL && (UMB->Owner != UMB_OWNER_NONE ||
+ UMB->Base > dwBase + *Size ||
+ UMB->Base + UMB->Size < dwBase + *Size)) {
+ UMB = UMB->Next;
+ }
+ if (UMB == NULL) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ UMB = SpliceUMB(UMB, dwBase, *Size, UMB_OWNER_ROM);
+ if (UMB == NULL) {
+ return FALSE;
+ }
+#ifdef MONITOR
+
+ // reserve and commit the block
+ SectionOffset.LowPart = UMB->Base - UMB_BASE_ADDRESS;
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *)&UMB->Base,
+ 0,
+ UMB->Size,
+ &SectionOffset,
+ &UMB->Size,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+#endif
+ UMB->Owner = UMB_OWNER_ROM;
+ break;
+
+
+ default:
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// This function reclaims the given UMB.
+// Note that every reclaimed UMB is set to UMB_OWNER_RAM, reserved and
+// committed. After the call, the UMB can be claimed by XMS driver.
+// A VDD will find that it can not reserve an UMB second time. This is
+// because we have to put the address space into committed states so
+// that we won't get access violation and crach VDM(remember we are
+// simulating DOS machine, a machine where applications can do whatever
+// they want).
+
+BOOL
+ReleaseUMB(
+WORD Owner,
+PVOID Address,
+DWORD Size
+)
+{
+
+#ifdef MONITOR
+ USHORT Count;
+ NTSTATUS Status;
+#endif
+
+ PUMBNODE UMB;
+ LARGE_INTEGER SectionOffset;
+ DWORD SizeView, dwBase;
+
+
+
+ dwBase = (DWORD)Address;
+
+ UMB = UMBList;
+ // size, address and owner must match before releasing
+ while (UMB != NULL && (UMB->Owner != Owner ||
+ dwBase != UMB->Base ||
+ Size != UMB->Size)) {
+ UMB = UMB->Next;
+ }
+ if (UMB == NULL) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+ SizeView = UMB->Size;
+ SectionOffset.HighPart = 0;
+ SectionOffset.LowPart = dwBase - UMB_BASE_ADDRESS;
+
+ switch (Owner) {
+ case UMB_OWNER_EMM:
+#ifndef MONITOR
+ sas_connect_memory(UMB->Base, UMB->Base + UMB->Size - 1, SAS_RAM);
+#else
+ //commit the meory block
+ Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+ (PVOID *) &dwBase,
+ 0,
+ &SizeView,
+ MEM_COMMIT,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+#endif
+ UMB->Owner = UMB_OWNER_RAM;
+ xmsReleaseUMBNotify((PVOID)UMB->Base, UMB->Size);
+ break;
+
+ case UMB_OWNER_VDD:
+#ifndef MONITOR
+ sas_connect_memory(dwBase, dwBase + Size - 1, SAS_RAM);
+#else
+ Count = (USHORT)(SizeView / HOST_PAGE_SIZE);
+ SizeView = HOST_PAGE_SIZE;
+ // unmap every page
+ for (; Count > 0; Count--, dwBase += HOST_PAGE_SIZE) {
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ (PVOID)dwBase
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ }
+ SectionOffset.LowPart = UMB->Base - UMB_BASE_ADDRESS;
+ dwBase = UMB->Base;
+ SizeView = UMB->Size;
+ // reserve and commit the meory(the entire block)
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *) &dwBase,
+ 0,
+ SizeView,
+ &SectionOffset,
+ &SizeView,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+#endif
+ UMB->Owner = UMB_OWNER_RAM;
+ xmsReleaseUMBNotify((PVOID)UMB->Base, UMB->Size);
+ break;
+
+ default:
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+ return TRUE;
+
+}
+// This function commit memory to the specific address space
+// for VDD.
+BOOL
+VDDCommitUMB(
+PVOID Address,
+DWORD Size
+)
+{
+
+#ifdef MONITOR
+ NTSTATUS Status;
+ DWORD Mask, SizeView;
+ USHORT Count;
+ LARGE_INTEGER SectionOffset;
+#endif
+
+ PUMBNODE UMB;
+ DWORD dwBase;
+
+ UMB = UMBList;
+
+ dwBase = (DWORD)Address;
+ while(UMB != NULL && (UMB->Owner != UMB_OWNER_VDD ||
+ UMB->Base + UMB->Size < dwBase + Size ||
+ UMB->Base > dwBase + Size)) {
+ UMB = UMB->Next;
+ }
+
+ if (UMB == NULL){
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+#ifndef MONITOR
+ sas_connect_memory(dwBase, dwBase + Size - 1, SAS_RAM);
+#else
+ Mask = 1 << ((dwBase - UMB->Base) / HOST_PAGE_SIZE);
+ SizeView = HOST_PAGE_SIZE;
+ Count = (USHORT)(Size / HOST_PAGE_SIZE);
+ SectionOffset.HighPart = 0;
+ SectionOffset.LowPart = dwBase - UMB_BASE_ADDRESS;
+
+ for (; Count > 0; Count--, Mask <<= 1) {
+ // Commit memory if didn't do this before
+ if ((UMB->Mask & Mask) == 0) {
+ Status = NtAllocateVirtualMemory(NtCurrentProcess(),
+ (PVOID *)&dwBase,
+ 0,
+ &SizeView,
+ MEM_COMMIT,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ UMB->Mask |= Mask;
+ }
+ else {
+ // the section has memory for it,
+ // first unmap it and then map it with correct commit size
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ (PVOID)dwBase
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *)&dwBase,
+ 0,
+ HOST_PAGE_SIZE,
+ &SectionOffset,
+ &SizeView,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ }
+ SectionOffset.LowPart += HOST_PAGE_SIZE;
+ dwBase += HOST_PAGE_SIZE;
+ }
+#endif
+
+ return TRUE;
+}
+// This function decommit memory from the specific address space
+// WARNING: We can never really decommit the memory. We just
+// change the address space states from committed to reserve so
+// that VDD will get page fault.
+BOOL
+VDDDeCommitUMB(
+PVOID Address,
+DWORD Size
+)
+{
+#ifdef MONITOR
+ NTSTATUS Status;
+ DWORD PageSize, PageMask;
+ USHORT PageCount;
+ LARGE_INTEGER SectionOffset;
+
+#endif
+
+ PUMBNODE UMB;
+ DWORD dwBase;
+
+
+
+ dwBase = (DWORD)Address;
+ UMB = UMBList;
+ while(UMB != NULL && (UMB->Owner != UMB_OWNER_VDD ||
+ UMB->Base + UMB->Size < dwBase + Size ||
+ UMB->Base > dwBase + Size)) {
+ UMB = UMB->Next;
+ }
+
+ if (UMB == NULL) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+#ifndef MONITOR
+ sas_connect_memory(dwBase, dwBase + Size - 1, SAS_VDD);
+#else
+ PageSize = HOST_PAGE_SIZE;
+ PageCount = (USHORT)(Size / HOST_PAGE_SIZE);
+ PageMask = 1 << ((dwBase - UMB->Base) / HOST_PAGE_SIZE);
+ SectionOffset.HighPart = 0;
+ SectionOffset.LowPart = dwBase - UMB->Base;
+ for (; PageCount > 0; PageCount--, PageMask <<= 1) {
+ if ((UMB->Mask & PageMask) != 0) {
+ // this page has memory committed, unmap it first
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ (PVOID)dwBase
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ // finally make a view for the page without commitment
+ Status= NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *) &dwBase,
+ 0,
+ 0,
+ &SectionOffset,
+ &PageSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ }
+ SectionOffset.LowPart += HOST_PAGE_SIZE;
+ dwBase += HOST_PAGE_SIZE;
+ }
+#endif
+
+ return TRUE;
+}
+
+VOID UMBNotify(
+unsigned char code
+)
+{
+ return;
+}
+
+// This function release the reserved EMM memory space to the caller
+// After the call is made, the address space is FREE and the caller
+// has to map the space immediately so that it won't be used by
+// the system for storage allocation.
+BOOL
+GetUMBForEMM(VOID)
+{
+#ifdef MONITOR
+ PUMBNODE UMB;
+ NTSTATUS Status;
+ UMB = UMBList;
+
+ while (UMB!= NULL) {
+ if (UMB->Owner == UMB_OWNER_EMM) {
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ (PVOID)UMB->Base
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ }
+ UMB = UMB->Next;
+ }
+#endif
+ return TRUE;
+}
+// This function reserves an address space for VDD
+// Here we map a view of section for each page within the requested
+// block. This was done because the VDD may want to allocate/deallocate
+// physical memory page by page.
+BOOL
+VDDReserveUMB(
+DWORD dwBase,
+DWORD Size,
+PUMBNODE UMB
+)
+{
+
+#ifdef MONITOR
+ USHORT Count;
+ LARGE_INTEGER SectionOffset;
+ DWORD SizeView;
+ NTSTATUS Status;
+#endif
+
+ while (UMB != NULL) {
+ if (UMB->Owner == UMB_OWNER_NONE &&
+ UMB->Base <= dwBase &&
+ UMB->Base + UMB->Size >= dwBase + Size)
+
+ break;
+ else
+ UMB = UMB->Next;
+ }
+ if (UMB == NULL){
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+ UMB = SpliceUMB(UMB, dwBase, Size, UMB_OWNER_VDD);
+ if (UMB == NULL) {
+ return FALSE;
+ }
+#ifndef MONITOR
+ sas_connect_memory(dwBase, dwBase + Size - 1, SAS_VDD);
+#else
+ Count = (USHORT)(Size / HOST_PAGE_SIZE);
+ SizeView = HOST_PAGE_SIZE;
+ SectionOffset.HighPart = 0;
+ SectionOffset.LowPart = dwBase - UMB_BASE_ADDRESS;
+ // map a view for each page. This is done becuase VDDs may commit
+ // and decommit memory for/from their memory hook and the system
+ // has 64KB alignment restriction for virtual memory APIs.
+ for (; Count > 0; Count--, dwBase += HOST_PAGE_SIZE,
+ SectionOffset.LowPart += HOST_PAGE_SIZE) {
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *)&dwBase,
+ 0,
+ 0,
+ &SectionOffset,
+ &SizeView,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ return FALSE;
+ }
+ }
+#endif
+ return TRUE;
+}
+
+// This helper function splice the given block into multiple
+// sublocks(max, 3) and reserves each newly created subblock
+
+PUMBNODE
+SpliceUMB(
+PUMBNODE UMB,
+DWORD dwBase,
+DWORD Size,
+WORD Owner
+)
+{
+#ifdef MONITOR
+ DWORD SizeView;
+ NTSTATUS Status;
+ LARGE_INTEGER SectionOffset;
+#endif
+
+ DWORD SizeBefore, SizeAfter;
+ PUMBNODE UMBBefore, UMBAfter;
+
+
+
+ SizeBefore = dwBase - UMB->Base;
+ SizeAfter = UMB->Size - Size - SizeBefore;
+ UMBBefore = UMB;
+ if (SizeAfter > 0) {
+ // allocate new node(s) before we unmap the block
+ UMBAfter = (PUMBNODE) malloc(sizeof(UMBNODE));
+ if (UMBAfter == NULL) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+ UMBAfter->Size = SizeAfter;
+ UMBAfter->Base = dwBase + Size;
+ UMBAfter->Owner = UMB_OWNER_NONE;
+ UMBAfter->Next = UMB->Next;
+ UMB->Next = UMBAfter;
+ UMB->Size -= SizeAfter;
+ }
+
+ if (SizeBefore > 0) {
+ UMBBefore = (PUMBNODE) malloc(sizeof(UMBNODE));
+ if (UMBBefore == NULL) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+
+ UMBBefore->Size = Size;
+ UMBBefore->Base = dwBase;
+ UMBBefore->Owner = Owner;
+ UMBBefore->Next = UMB->Next;
+ UMB->Next = UMBBefore;
+ UMB->Size = SizeBefore;
+ UMB->Owner = UMB_OWNER_NONE;
+ }
+ else {
+ UMB->Owner = Owner;
+ }
+
+#ifdef MONITOR
+ // unmap the entire block because we gona map a view for each subblock
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ (PVOID)UMB->Base
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return NULL;
+ }
+ SectionOffset.HighPart = 0;
+
+ if (SizeBefore > 0) {
+ SizeView = UMB->Size;
+ dwBase = UMB->Base;
+ SectionOffset.LowPart = dwBase - UMB_BASE_ADDRESS;
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *) &dwBase,
+ 0,
+ 0,
+ &SectionOffset,
+ &SizeView,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return NULL;
+ }
+ }
+ if (SizeAfter > 0){
+ dwBase = UMBAfter->Base;
+ SectionOffset.LowPart = dwBase - UMB_BASE_ADDRESS;
+ SizeView = UMBAfter->Size;
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *)&dwBase,
+ 0,
+ 0,
+ &SectionOffset,
+ &SizeView,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ UMB_PAGE_PROTECTION
+ );
+ if (!NT_SUCCESS(Status)) {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return NULL;
+ }
+ }
+#endif
+ return UMBBefore;
+}
+
+// This function initialize UMB list. Every block in the UMA
+// area are chained together in a single list
+// Each node in the list is either UMB_OWNER_NONE or UMB_OWNER_ROM.
+#ifndef MONITOR
+BOOL
+InitUMBList(VOID)
+{
+ PUMBNODE UMB, UMBNew;
+ static DWORD ROMs[] = { EGA_ROM_START, EGA_ROM_END,
+ BIOS_START, 0x100000
+ };
+ DWORD CurAddress;
+ USHORT Index;
+
+ UMBList = NULL;
+
+ CurAddress = UMB_BASE_ADDRESS;
+ Index = 0;
+ while (CurAddress < UMB_BASE_ADDRESS + UMB_MAX_OFFSET) {
+ UMBNew = (PUMBNODE) malloc(sizeof(UMBNODE));
+ if (UMBNew == NULL) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ UMBNew->Base = CurAddress;
+ if (CurAddress == ROMs[Index]) {
+ UMBNew->Owner = UMB_OWNER_ROM;
+ UMBNew->Size = ROMs[Index + 1] - CurAddress;
+ Index += 2;
+ }
+ else {
+ UMBNew->Owner = UMB_OWNER_NONE;
+ UMBNew->Size = ROMs[Index] - CurAddress;
+ }
+ CurAddress += UMBNew->Size;
+ if (UMBList == NULL) {
+ UMBList = UMBNew;
+ }
+ else {
+ UMB->Next = UMBNew;
+ }
+ UMBNew->Next = NULL;
+ UMB = UMBNew;
+
+ }
+}
+
+#else
+// this is for X86 environment
+BOOL
+InitUMBList(VOID)
+
+{
+ OBJECT_ATTRIBUTES UMBObjAttr;
+ LARGE_INTEGER UMBSecSize;
+ NTSTATUS Status;
+ DWORD CurAddress, RomAddress, RomSize;
+ PUMBNODE UMB, UMBNew;
+ USHORT Index;
+
+ UNICODE_STRING WorkString;
+ UCHAR KeyValueBuffer[KEY_VALUE_BUFFER_SIZE];
+ HANDLE RegistryHandle;
+ ULONG ResultLength;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor;
+ PCM_ROM_BLOCK BiosBlock;
+
+ RtlInitUnicodeString(
+ &WorkString,
+ L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM"
+ );
+
+ //
+ // Set up and open KeyPath
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &WorkString,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ Status = NtOpenKey(
+ &RegistryHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("InitUMBList: can't open \\Registry\\Machine\\Hardware\\Description\\System\n");
+#endif
+ return FALSE;
+ }
+
+ //
+ // Get the data for the rom information
+ //
+
+ RtlInitUnicodeString(
+ &WorkString,
+ CONFIG_DATA_STRING
+ );
+
+ Status = NtQueryValueKey(
+ RegistryHandle,
+ &WorkString,
+ KeyValueFullInformation,
+ (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer,
+ KEY_VALUE_BUFFER_SIZE,
+ &ResultLength
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("InitUMBList: Got nothing from Configuration Data\n");
+#endif
+ NtClose(RegistryHandle);
+ return FALSE;
+ }
+
+ // Locate registry data for this key
+ ResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)KeyValueBuffer
+ + ((PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer)->DataOffset);
+
+ // Verify data returned is large enough to contaim partial resource
+ // descriptor.
+ if ((((PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer)->DataLength <
+ sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) ||
+ (ResourceDescriptor->PartialResourceList.Count < 2))
+ {
+ Index = 0;
+ } else {
+ PartialResourceDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) (
+ (PUCHAR)ResourceDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR)
+ + ResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize);
+
+
+ //Verify that there is a 2nd partial resource descriptor, and that it is
+ //large enough to contain a ROM block description
+ if (((PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer)->DataLength <
+ ((PUCHAR)PartialResourceDescriptor -
+ (PUCHAR)ResourceDescriptor +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof(CM_ROM_BLOCK)))
+ {
+ NtClose(RegistryHandle);
+ return FALSE;
+ }
+
+ //get pointer to the first rom desciption
+ BiosBlock = (PCM_ROM_BLOCK)((PUCHAR)PartialResourceDescriptor +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+ // how many rom blocks we have
+ Index = (USHORT) (PartialResourceDescriptor->u.DeviceSpecificData.DataSize /
+ sizeof(CM_ROM_BLOCK));
+
+ }
+
+ InitializeObjectAttributes(&UMBObjAttr,
+ NULL,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+
+ UMBSecSize.LowPart = UMB_MAX_OFFSET;
+ UMBSecSize.HighPart = 0;
+
+ // create a section for the UMB area. Note that the section
+ // includes ROM blocks. This was done because we will allow
+ // VDDs to put ROM blocks into UMB free list for other users.
+ Status = NtCreateSection(&UMBSectionHandle,
+ SECTION_MAP_WRITE|SECTION_MAP_EXECUTE,
+ &UMBObjAttr,
+ &UMBSecSize,
+ UMB_PAGE_PROTECTION,
+ SEC_RESERVE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("UMB:Unable to create UMB section, Status = %lx\n",
+ Status);
+#endif
+ return(FALSE);
+ }
+
+ // Now we go through the whole 256KB area to create a list for
+ // each UMB(including ROM blocks)
+
+ // This global variable points to the first node in the list
+ UMBList = NULL;
+ CurAddress = UMB_BASE_ADDRESS;
+
+ while (Index > 0) {
+ // round down address to the previous page boundary
+ RomAddress = BiosBlock->Address & ~(HOST_PAGE_SIZE - 1);
+ // round up the size to next page boundary
+ RomSize = (BiosBlock->Size +
+ BiosBlock->Address - RomAddress +
+ HOST_PAGE_SIZE - 1
+ ) & ~(HOST_PAGE_SIZE - 1);
+ // combine two blocks together if they overlap in page
+ if (Index > 1 && (RomAddress + RomSize) > BiosBlock[1].Address) {
+ BiosBlock[1].Size += BiosBlock[1].Address - BiosBlock->Address;
+ BiosBlock[1].Address = BiosBlock->Address;
+ BiosBlock++;
+ Index--;
+ continue;
+ }
+
+
+ if (CurAddress == RomAddress) {
+ UMBNew = CreateNewUMBNode(CurAddress, RomSize, UMB_OWNER_ROM);
+ if (UMBNew == NULL)
+ return FALSE;
+ CurAddress += RomSize;
+ BiosBlock++;
+ Index--;
+ }
+ else {
+ // make sure the block is in UMB area
+ if (RomAddress > CurAddress &&
+ RomAddress <= UMB_BASE_ADDRESS + UMB_MAX_OFFSET){
+
+ UMBNew = CreateNewUMBNode(CurAddress,
+ RomAddress - CurAddress,
+ UMB_OWNER_NONE
+ );
+ if (UMBNew == NULL)
+ return FALSE;
+ CurAddress = RomAddress;
+ }
+ // this block is not in UMB area, discard it
+ else {
+ BiosBlock++;
+ Index--;
+ continue;
+ }
+ }
+ if (UMBList == NULL)
+ UMBList = UMBNew;
+ else
+ UMB->Next = UMBNew;
+
+ UMB = UMBNew;
+ }
+ if (CurAddress < UMB_BASE_ADDRESS + UMB_MAX_OFFSET) {
+
+ UMBNew = CreateNewUMBNode(CurAddress,
+ UMB_BASE_ADDRESS + UMB_MAX_OFFSET - CurAddress,
+ UMB_OWNER_NONE
+ );
+ if (UMBNew == NULL)
+ return FALSE;
+ if (UMBList == NULL)
+ UMBList = UMBNew;
+ else
+ UMB->Next = UMBNew;
+ }
+}
+
+// create a new node for the new UMB block
+// map the given address space to the UMB section if
+// the umb is a RAM(owner = NONE)
+
+PUMBNODE CreateNewUMBNode
+(
+DWORD BaseAddress,
+DWORD Size,
+WORD Owner
+)
+{
+ PUMBNODE UMBNew;
+ LARGE_INTEGER SectionOffset;
+ NTSTATUS Status;
+
+ if ((UMBNew = (PUMBNODE) malloc(sizeof(UMBNODE))) != NULL) {
+ UMBNew->Base = BaseAddress;
+ UMBNew->Size = Size;
+ UMBNew->Mask = 0;
+ UMBNew->Owner = Owner;
+ UMBNew->Next = NULL;
+
+ if (Owner == UMB_OWNER_NONE) {
+ SectionOffset.HighPart = 0;
+ SectionOffset.LowPart = BaseAddress - UMB_BASE_ADDRESS;
+ Status = NtMapViewOfSection(UMBSectionHandle,
+ NtCurrentProcess(),
+ (PVOID *)&BaseAddress,
+ 0, //zero bits
+ 0, // commit size
+ &SectionOffset, // section offset
+ &Size, // view size
+ ViewUnmap,
+ MEM_DOS_LIM, //
+ UMB_PAGE_PROTECTION
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("InitUMBList failed to map, Status = %lx\n",
+ Status);
+#endif
+ free(UMBNew);
+ UMBNew = NULL;
+ }
+ }
+
+ }
+ return UMBNew;
+}
+
+#endif
diff --git a/private/mvdm/softpc.new/host/src/nt_unix.c b/private/mvdm/softpc.new/host/src/nt_unix.c
new file mode 100644
index 000000000..e89b10b81
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_unix.c
@@ -0,0 +1,459 @@
+/*****************************************************************************
+* nt_unix.c - miscellaneous stuff that may be needed. *
+* File derived from hp_unix.c by Philippa Watson. *
+* *
+* This version is written/ported for New Technology OS/2 *
+* by Andrew Watson *
+* *
+* Date pending due to ignorance *
+* *
+* (c) Copyright Insignia Solutions 1991 *
+* *
+*****************************************************************************/
+
+#include <windows.h>
+#include "host_def.h"
+#include "insignia.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <io.h>
+#include <string.h>
+#include <time.h>
+#include <sys\types.h>
+#include "xt.h"
+#include CpuH
+#include "timeval.h"
+#include "error.h"
+#include "sas.h"
+#include "spcfile.h"
+#include "idetect.h"
+#include "debug.h"
+#include "nt_reset.h"
+#include "nt_pif.h"
+
+
+/*****************************************************************************
+* local #define used for stubbing out functions *
+*****************************************************************************/
+
+#define STUBBED 1
+
+/**** externally visible global variable declarations ****/
+
+extern char *_sys_errlist[];
+extern int _sys_nerr;
+
+
+/* Exported Data */
+GLOBAL BOOL ExternalWaitRequest = FALSE;
+
+
+/* Local Module Data */
+HANDLE IdleEvent = NULL;
+DWORD MainThreadId = 0;
+BOOL NowWaiting = FALSE;
+
+/*****************************************************************************
+* Function: host_get_system_error() *
+* This routine processes an error returned by SoftPC. *
+* Returns a pointer to an error message (located in a table) that *
+* corresponds to the error number passed as a parameter. *
+*****************************************************************************/
+
+LPSTR host_get_system_error(filename, line, error)
+LPSTR filename;
+DWORD line;
+DWORD error;
+{
+static BYTE buf[256];
+
+if (error > (DWORD)_sys_nerr)
+ {
+ sprintf(buf, "System error %d occurred in %s (line %d)",
+ error, filename, line);
+ return(buf);
+ }
+else
+ return(_sys_errlist[error]);
+}
+
+
+/* This section contains host side of idling system */
+
+/*****************************************************************************
+* Function: host_idle_init() *
+* Create Event used in Idling Wait *
+*****************************************************************************/
+void host_idle_init(void)
+{
+ if (IdleEvent != NULL)
+ return; //Called already
+
+ MainThreadId = GetCurrentThreadId();
+
+ IdleEvent = CreateEvent((LPSECURITY_ATTRIBUTES) NULL, FALSE, FALSE, NULL);
+
+#ifndef PROD
+ if (IdleEvent == NULL)
+ printf("NTVDM:Idlling Event creation failed. Err %d\n",GetLastError());
+#endif
+}
+
+/*****************************************************************************
+* Function: WaitIfIdle() *
+* If no counter indications (video, com etc) then do short idle *
+* *
+*****************************************************************************/
+void WaitIfIdle(void)
+{
+ DWORD idletime;
+
+ if (IdleDisabledFromPIF) {
+ return;
+ }
+
+
+ /*
+ * If its not wow make sure the main thread also gets idled.
+ */
+ if (!VDMForWOW && GetCurrentThreadId() != MainThreadId)
+ {
+ ExternalWaitRequest = TRUE;
+ }
+
+
+ //
+ // Check for invalid conditions
+ //
+ if (!IdleEvent || !IdleNoActivity) {
+ Sleep(0);
+ return;
+ }
+
+ NowWaiting = TRUE;
+ idletime = ienabled ? 10 : 1;
+
+ if (WaitForSingleObject(IdleEvent, idletime) == WAIT_FAILED) {
+ Sleep(0);
+ idletime = 0;
+ }
+ NowWaiting = FALSE;
+
+#ifndef MONITOR
+ if (idletime) {
+ ActivityCheckAfterTimeSlice();
+ }
+#endif
+
+}
+
+
+/*****************************************************************************
+* Function: WakeUpNow() *
+* The paired counterpart to WaitIfIdle() - the event that was worth waiting *
+* for has arrived. Wake CPU up so it can deal with it. *
+*****************************************************************************/
+void WakeUpNow(void)
+{
+ HostIdleNoActivity();
+}
+
+
+
+/* HostIdleNoActivity
+ *
+ * Set Indicator that video\disk\com\lpt activity
+ * has happened and wake up sleeping CPU if appears to be sleeping.
+ */
+void HostIdleNoActivity(void)
+{
+
+ IdleNoActivity=0;
+
+ if (NowWaiting) // critical path do inline....
+ PulseEvent(IdleEvent);
+}
+
+
+
+/*****************************************************************************
+* Function: host_release_timeslice() *
+*****************************************************************************/
+void host_release_timeslice(void)
+{
+ DWORD idletime;
+
+ //
+ // If there is counter idle activity no idling so return immediatly
+ //
+ if (!IdleNoActivity || IdleDisabledFromPIF) {
+ return;
+ }
+
+ //
+ // Check for invalid or unsafe conditions
+ //
+ if (!IdleEvent || !ienabled) {
+ Sleep(0);
+ return;
+ }
+
+ //
+ // If pif Foreground priority is set to less than 100 on every timer
+ // event PrioWaitIfIdle will do a wait, so use minimum delay here.
+ //
+ if (WNTPifFgPr < 100) {
+ idletime = 0;
+ }
+
+ //
+ // Normal idling condition, so use sig portion of 55 ms time tick
+ //
+ else {
+ idletime = 25;
+ }
+
+ NowWaiting = TRUE;
+ if (WaitForSingleObject(IdleEvent, idletime) == WAIT_FAILED) {
+ idletime = 0;
+ Sleep(0);
+ }
+ NowWaiting = FALSE;
+
+#ifndef MONITOR
+ if (idletime) {
+ ActivityCheckAfterTimeSlice();
+ }
+#endif
+
+
+
+}
+
+
+
+/*****************************************************************************
+* Function: PrioWaitIfIdle(Percentage) *
+* unsigned char Percentage - Percent of cpu usage desired
+* The smaller the number the bigger the delay time
+*
+*****************************************************************************/
+void PrioWaitIfIdle(unsigned char Percentage)
+{
+ DWORD idletime;
+
+
+ //
+ // If there is counter idle activity no idling so return immediatly
+ //
+ if (!IdleNoActivity) {
+ return;
+ }
+
+ //
+ // Check for invalid conditions
+ //
+ if (!IdleEvent) {
+ Sleep(0);
+ return;
+ }
+
+
+ idletime = (100 - Percentage) >> 1; // percent of 55ms time tick
+
+
+ //
+ // If idle is disabled, we can't depend on the IdleNoActivity flag
+ // or if the delay time is less than the system's time slice
+ // shorten the idle so we don't oversleep
+ //
+ if (!ienabled)
+ idletime >>= 2;
+
+ if (idletime < 10)
+ idletime >>= 1;
+
+ if (idletime) {
+ NowWaiting = TRUE;
+ if (WaitForSingleObject(IdleEvent, idletime) == WAIT_FAILED) {
+ idletime = 0;
+ Sleep(0);
+ }
+ NowWaiting = FALSE;
+ }
+ else {
+ Sleep(0);
+ }
+
+#ifndef MONITOR
+ if (idletime) {
+ ActivityCheckAfterTimeSlice();
+ }
+#endif
+
+}
+
+
+
+
+/*****************************************************************************
+* function: host_memset() *
+* This function does what the traditional memset standard library function*
+* does ... i.e. fills a portion of memory with the character represented *
+* in val. *
+* Returns nothing. *
+*****************************************************************************/
+
+void host_memset(addr, val, size)
+register char * addr;
+register char val;
+unsigned int size;
+{
+memset(addr, val, size);
+}
+
+
+
+#ifdef NO_LONGER_USED
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+ * Host-specific equivalent of the Unix function localtime().
+ ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+struct host_tm *host_localtime(clock)
+long *clock;
+{
+ SYSTEMTIME now;
+ SAVED struct host_tm host_now;
+
+ UNUSED(clock);
+ GetLocalTime(&now);
+ host_now.tm_sec = (int) now.wSecond;
+ host_now.tm_min = (int) now.wMinute;
+ host_now.tm_hour = (int) now.wHour;
+ host_now.tm_mday = (int) now.wDay;
+ host_now.tm_mon = (int) now.wMonth - 1; // Unix has 0 based months,NT 1
+ host_now.tm_year = (int) now.wYear;
+ host_now.tm_wday = (int) now.wDayOfWeek;
+
+ host_now.tm_yday = (int) 0; // the base doesn't require these.
+ host_now.tm_isdst = (int) 0;
+ return(&host_now);
+}
+#endif
+
+/*
+ * Host-specific equivalent of the Unix function time().
+ */
+
+long host_time(tloc)
+long *tloc;
+{
+ UNUSED(tloc);
+ return((long) GetTickCount() / 1000 );
+}
+
+/*
+ * Check that the file is a character special device.
+ */
+boolean host_file_is_char_dev(path)
+char *path;
+{
+ return(FALSE);
+}
+
+
+/*
+ * Looks for a given file name in the 'ntvdm' subdirectory of the
+ * windows system directory. The full path to the first one found is returned
+ * in the 'full_path' variable, and as the result of the function.
+ */
+char *host_find_file(file,full_path,display_error)
+char *file,*full_path;
+int display_error;
+{
+ char buffer[MAXPATHLEN];
+ WIN32_FIND_DATA match;
+ HANDLE gotit;
+ static char sysdir[MAX_PATH];
+ static int first = 1;
+
+ if (first)
+ {
+ first = 0;
+ if (GetSystemDirectory(sysdir, MAXPATHLEN) == 0)
+ {
+ sysdir[0] = '\0';
+ host_error(EG_SYS_MISSING_FILE, ERR_QUIT, file);
+ return(NULL);
+ }
+ }
+
+ if (sysdir[0] != '\0')
+ {
+ strcpy(buffer, sysdir);
+ strcat(buffer, "\\");
+ strcat(buffer, file);
+ }
+
+ if ((gotit = FindFirstFile(buffer, &match)) != (HANDLE)-1)
+ {
+ FindClose(gotit); // should check (BOOL) return & then ??
+ strcpy(full_path, buffer);
+ return (full_path);
+ }
+
+ /* Haven't managed to find the file. Oh dear... */
+ switch( display_error )
+ {
+ case SILENT:
+ return( NULL );
+ break;
+
+ case STANDARD:
+ case CONT_AND_QUIT:
+ host_error(EG_SYS_MISSING_FILE, ERR_CONT | ERR_QUIT, file);
+ break;
+
+ default:
+ host_error(EG_SYS_MISSING_FILE, ERR_QUIT, file);
+ break;
+ }
+
+ return (NULL);
+}
+
+
+
+//
+// this stuff needs to be removed
+//
+static char temp_copyright[] = "SoftPC-AT Version 3\n\r(C)Copyright Insignia Solutions Inc. 1987-1992";
+
+static int block_level = 0;
+
+GLOBAL void host_block_timer()
+{
+ if(block_level) return;
+ block_level++;
+}
+
+GLOBAL void host_release_timer()
+{
+ block_level=0;
+}
+GLOBAL CHAR * host_get_years()
+{
+return ("1987 - 1992");
+}
+GLOBAL CHAR * host_get_version()
+{
+return("3.00");
+}
+GLOBAL CHAR * host_get_unpublished_version()
+{
+return("");
+}
+GLOBAL CHAR * host_get_copyright()
+{
+return("");
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_vdd.c b/private/mvdm/softpc.new/host/src/nt_vdd.c
new file mode 100644
index 000000000..6396f8cd2
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_vdd.c
@@ -0,0 +1,821 @@
+/********************************************************/
+/*
+ * nt_vdd.c - NT support for VDD DLLs
+ *
+ * Ade Brownlow
+ *
+ * 19/11/91
+ *
+ */
+
+#include "windows.h"
+#include "insignia.h"
+#include "host_def.h"
+
+#include <stdio.h>
+
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "error.h"
+#include "config.h"
+
+#include "ios.h"
+#include "dma.h"
+#include "nt_vdd.h"
+#include "nt_vddp.h"
+
+
+#ifdef ANSI
+
+/* MS bop grabbing stuff */
+GLOBAL half_word get_MS_bop_index (void *);
+GLOBAL void free_MS_bop_index (half_word);
+GLOBAL void ms_bop (void);
+LOCAL void ms_not_a_bop (void);
+
+/* IO slot grabbers */
+GLOBAL half_word io_get_spare_slot (void);
+GLOBAL void io_release_spare_slot (half_word);
+#else
+/* MS bop grabbing stuff */
+GLOBAL half_word get_MS_bop_index ();
+GLOBAL void free_MS_bop_index ();
+GLOBAL void ms_bop ();
+LOCAL void ms_not_a_bop ();
+
+/* IO slot grabbers */
+GLOBAL half_word io_get_spare_slot ();
+GLOBAL void io_release_spare_slot ();
+#endif
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::: Local data structures */
+
+#define MAX_SLOTS (10)
+
+LOCAL void (*MS_bop_tab[MAX_SLOTS])(); /* MS bop table */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Microsoft BOP vectoring code references MS_bop_tab above and calls function
+ * as directed by AH */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL void ms_bop () /* called from MS_bop_5 ie bop 0x55 */
+{
+ half_word ah = getAH(); /* get the value in AH */
+
+ /*........................................Valid then call the MS function */
+
+ if(ah >= MAX_SLOTS || MS_bop_tab[ah] == NULL)
+ ms_not_a_bop();
+ else
+ (*MS_bop_tab[ah])();
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::: Dummy for unset AH values - stops us zipping into hyperspace :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+LOCAL void ms_not_a_bop()
+{
+#ifndef PROD
+ printf ("AH=%x, This is not a valid value for an MS BOP\n", getAH());
+ illegal_bop();
+#ifdef YODA
+ force_yoda ();
+#endif
+#endif
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Give an index to our table which can be used for the passed function :::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL half_word get_ms_bop_index (void (*func)())
+{
+ register half_word index;
+
+ for(index = 0; index < MAX_SLOTS; index++)
+ {
+ if(MS_bop_tab[index] == NULL)
+ {
+ MS_bop_tab[index] = func;
+ break;
+ }
+ }
+
+ return (index == MAX_SLOTS ? (half_word) 0xff : index);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::: free the bop index passed :::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+GLOBAL void free_MS_bop_index IFN1(half_word, index)
+{
+ MS_bop_tab[index] = NULL;
+}
+
+
+/*
+ * ==========================================================================
+ * Imports
+ * ==========================================================================
+ */
+IMPORT VOID host_ica_lock(), host_ica_unlock();
+
+/********************************************************/
+/* IO stuff */
+
+
+ // VddAdapter Table (Adapter X hVdd table)
+ // there is only one adapter per VDD
+HANDLE VddAdapter[NUMBER_SPARE_ADAPTERS];
+
+#define MAX_IRQ_LINE 15
+// Bugbug need to initialize this cleanly
+HANDLE IrqLines[MAX_IRQ_LINE+1] = {(HANDLE)1, (HANDLE)1, (HANDLE)1, (HANDLE)1,
+ (HANDLE)1, (HANDLE)1, (HANDLE)1, (HANDLE)1,
+ (HANDLE)1, (HANDLE)1, (HANDLE)1, (HANDLE)0,
+ (HANDLE)0, (HANDLE)1, (HANDLE)1, (HANDLE)0};
+
+
+/* GetVddAdapter
+ *
+ * Retrieves the current adapter number for the Vdd
+ * If none is assigned, then one is assigned
+ *
+ * entry: HANDLE hVdd - handle forthe vdd
+ * exit : WORD wAdaptor - Assigned Adaptor Num
+ * (Zero for failure)
+ * WinLastError Codes:
+ *
+ * ERROR_ALREADY_EXISTS - Adaptor already exists for the Vdd
+ * ERROR_OUTOFMEMORY - No adaptor slots available
+ *
+ */
+WORD GetVddAdapter(HANDLE hVdd)
+{
+ WORD w;
+
+ //
+ // search VddAdapter table to see if adapter already assigned
+ //
+ for (w = 0; w < NUMBER_SPARE_ADAPTERS; w++)
+ {
+ if (VddAdapter[w] == hVdd) {
+ SetLastError(ERROR_ALREADY_EXISTS);
+ return 0;
+ }
+ }
+
+ //
+ // assume not assigned, so look for first available slot
+ //
+ for (w = 0; w < NUMBER_SPARE_ADAPTERS; w++)
+ {
+ if (VddAdapter[w] == 0) {
+ VddAdapter[w] = hVdd;
+ return (w + SPARE_ADAPTER1);
+ }
+ }
+
+ // none found return error
+ SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
+}
+
+
+
+/* FreeVddAdapter
+ *
+ * Frees the current adaptor for the specified VDD
+ *
+ * entry: HANDLE hVdd
+ * exit: WORD AdaptorNumber that was freed,
+ * Zero for not found
+ *
+ */
+WORD FreeVddAdapter(HANDLE hVdd)
+{
+ WORD w;
+
+ //
+ // search VddAdapter table by hVdd for adaptor
+ // and mark it as available
+ //
+ w = NUMBER_SPARE_ADAPTERS;
+ while (w--)
+ {
+ if (VddAdapter[w] == hVdd) {
+ VddAdapter[w] = 0;
+ return w;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef MONITOR
+extern BOOLEAN MonitorVddConnectPrinter(WORD Adapter, HANDLE hVdd, BOOLEAN Connect);
+#endif /* MONITOR */
+
+
+/*** VDDInstallIOHook - This service is provided for VDDs to hook the
+ * IO ports they are responsible for.
+ *
+ * INPUT:
+ * hVDD ; VDD Handle
+ * cPortRange; Number of VDD_IO_PORTRANGE structures
+ * pPortRange; Pointer to array of VDD_IO_PORTRANGE
+ * IOhandler : VDD handler for the ports.
+ *
+ * OUTPUT
+ * SUCCESS : Returns TRUE
+ * FAILURE : Returns FALSE
+ * GetLastError has the extended error information.
+ *
+ * NOTES:
+ * 1. The first one to hook a port will get control. Subsequent
+ * requests will be failed. There is no concept of chaining
+ * the hooks.
+ *
+ * 2. IOHandler must atleast provide a byte read and a byte write
+ * handler. Others can be NULL.
+ *
+ * 3. If word or string handlers are not provided, their effect
+ * will be emulated using byte handlers.
+ *
+ * 4. VDDs should not hook DMA ports. NTVDM manages it for all
+ * the clients and services are provided to perform DMA
+ * operations and to access and modify DMA data.
+ *
+ * 5. VDDs should not hook video ports as well. Such a hooking
+ * will succeed but there is no gurantee that the IO handler will
+ * get called.
+ *
+ * 6. Each Vdd is allowed to install only one set of IO hooks
+ * at a time.
+ *
+ * 7. Extended Error codes:
+ *
+ * ERROR_ACCESS_DENIED - One of the requested ports is already hooked
+ * ERROR_ALREADY_EXISTS - Vdd already has active IO port handlers
+ * ERROR_OUTOFMEMORY - Insufficient resources for additional VDD
+ * Port handler set.
+ * ERROR_INVALID_ADDRESS - One of the IO port handlers has an invalid
+ * address.
+ */
+BOOL VDDInstallIOHook (
+ HANDLE hVdd,
+ WORD cPortRange,
+ PVDD_IO_PORTRANGE pPortRange,
+ PVDD_IO_HANDLERS pIOFn)
+{
+ WORD w, i;
+ WORD wAdapter;
+ PVDD_IO_PORTRANGE pPRange;
+#ifdef MONITOR
+ WORD lptAdapter = 0;
+#endif
+
+
+ // check parameters
+ // the inb and outb handlers must be valid
+ // the rest must be either NULL or valid
+ //
+ if (IsBadCodePtr((FARPROC)pIOFn->inb_handler) ||
+ IsBadCodePtr((FARPROC)pIOFn->outb_handler))
+ {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+
+ if ((pIOFn->inw_handler && IsBadCodePtr((FARPROC)pIOFn->inw_handler)) ||
+ (pIOFn->insb_handler && IsBadCodePtr((FARPROC)pIOFn->insb_handler)) ||
+ (pIOFn->insw_handler && IsBadCodePtr((FARPROC)pIOFn->insw_handler)) ||
+ (pIOFn->outw_handler && IsBadCodePtr((FARPROC)pIOFn->outw_handler)) ||
+ (pIOFn->outsb_handler && IsBadCodePtr((FARPROC)pIOFn->outsb_handler))||
+ (pIOFn->outsw_handler && IsBadCodePtr((FARPROC)pIOFn->outsw_handler)) )
+ {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+
+ // Get an adapter
+ wAdapter = GetVddAdapter(hVdd);
+ if (!wAdapter) {
+ return FALSE;
+ }
+
+ // register io handlers for this adapter
+ io_define_in_routines((half_word)wAdapter,
+ pIOFn->inb_handler,
+ pIOFn->inw_handler,
+ pIOFn->insb_handler,
+ pIOFn->insw_handler);
+
+ io_define_out_routines((half_word)wAdapter,
+ pIOFn->outb_handler,
+ pIOFn->outw_handler,
+ pIOFn->outsb_handler,
+ pIOFn->outsw_handler);
+
+ // register ports for this adapter\vdd
+ i = cPortRange;
+ pPRange = pPortRange;
+ while (i) {
+ for (w = pPRange->First; w <= pPRange->Last; w++)
+ {
+#ifdef MONITOR
+ // watch out for lpt ports
+ // note that the vdd must hook every port assoicated with
+ // the lpt. Just imanging that the vdd traps the control
+ // port while leaves the rest for softpc-- we are going
+ // to screw up badly and so does the vdd.
+ // QUESTION: How can we enforece this????
+ if (w >= LPT1_PORT_START && w < LPT1_PORT_END)
+ lptAdapter |= 1;
+ else if (w >= LPT2_PORT_START && w < LPT2_PORT_END)
+ lptAdapter |= 2;
+ else if (w >= LPT3_PORT_START && w < LPT3_PORT_END)
+ lptAdapter |= 4;
+#endif
+ if (!io_connect_port(w, (half_word)wAdapter, IO_READ_WRITE))
+ {
+ // if one of the port connects failed
+ // undo the connects that succeeded and ret error
+ i = w;
+ while (pPortRange < pPRange) {
+ for (w = pPortRange->First; w <= pPortRange->Last; w++)
+ {
+ io_disconnect_port(w, (half_word)wAdapter);
+ }
+ pPortRange++;
+ }
+
+ for (w = pPortRange->First; w < i; w++)
+ {
+ io_disconnect_port(w, (half_word)wAdapter);
+ }
+
+ FreeVddAdapter(hVdd);
+
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ }
+ pPRange++;
+ i--;
+ }
+
+#ifdef MONITOR
+// i/o ports are hooked successfully, stop printer status port
+// kernel emulation if the they are in the hooked range
+ if (lptAdapter & 1)
+ MonitorVddConnectPrinter(0, hVdd, TRUE);
+ if (lptAdapter & 2)
+ MonitorVddConnectPrinter(1, hVdd, TRUE);
+ if (lptAdapter & 4)
+ MonitorVddConnectPrinter(2, hVdd, TRUE);
+#endif /* MONITOR */
+ return TRUE;
+}
+
+
+
+/*** VDDDeInstallIOHook - This service is provided for VDDs to unhook the
+ * IO ports they have hooked.
+ *
+ * INPUT:
+ * hVDD : VDD Handle
+ *
+ * OUTPUT
+ * None
+ *
+ * NOTES
+ *
+ * 1. On Deinstalling a hook, the defult hook is placed back on
+ * those ports. Default hook returns 0xff on reading
+ * and ignores the write operations.
+ *
+ */
+VOID VDDDeInstallIOHook (
+ HANDLE hVdd,
+ WORD cPortRange,
+ PVDD_IO_PORTRANGE pPortRange)
+{
+ WORD w;
+ WORD wAdapter;
+#ifdef MONITOR
+ WORD lptAdapter = 0;
+#endif
+
+
+ wAdapter = FreeVddAdapter(hVdd);
+ if (!wAdapter) {
+ return;
+ }
+
+
+ // deregister ports for this adapter\vdd
+ while (cPortRange--) {
+ for (w = pPortRange->First; w <= pPortRange->Last; w++)
+ {
+#ifdef MONITOR
+ // watch out for lpt status ports
+ // note that the vdd must unhook every port assoicated with
+ // the lpt. Just imanging that the vdd traps the control
+ // port while leaves the rest for softpc-- we are going
+ // to screw up badly and so does the vdd.
+ // QUESTION: How can we enforece this????
+ if (w >= LPT1_PORT_START && w < LPT1_PORT_END)
+ lptAdapter |= 1;
+ else if (w >= LPT2_PORT_START && w < LPT2_PORT_END)
+ lptAdapter |= 2;
+ else if (w >= LPT3_PORT_START && w < LPT3_PORT_END)
+ lptAdapter |= 4;
+#endif
+ io_disconnect_port(w, (half_word)wAdapter);
+ }
+ pPortRange++;
+ }
+
+#ifdef MONITOR
+// i/o ports are Unhooked successfully, resume printer status port
+// kernel emulation if the they are in the hooked range
+ if (lptAdapter & 1)
+ MonitorVddConnectPrinter(0, hVdd, FALSE);
+ if (lptAdapter & 2)
+ MonitorVddConnectPrinter(1, hVdd, FALSE);
+ if (lptAdapter & 4)
+ MonitorVddConnectPrinter(2, hVdd, FALSE);
+#endif /* MONITOR */
+}
+
+
+/*** VDDReserveIrqLine - This service resolves contention between VDDs
+ * over Irq lines.
+ *
+ * Parameters:
+ * hVDD : VDD Handle
+ * IrqLine ; the specific IrqLine number to reserve, or -1 to search for
+ * a free line.
+ *
+ * Return Value
+ * VDDReserveIrqLine returns the IrqLine number (0-15) if successful.
+ * Otherwise, this function returns 0xFFFF and logs an error. The
+ * extended error code will be ERROR_INVALID_PARAMETER.
+ *
+ * Comments:
+ * The value of an IrqLine number may range from 0-15 and correspond to
+ * the irq line numbers of the virtual PICs (8259) emulated by the ntvdm
+ * subsystem. Many of the line numbers are already used by the system
+ * (e.g. for Timer, Keyboard, etc.), but there are a few free lines. VDDs
+ * can take advantage of this and use the VDDSimulateInterrupt service to
+ * reflect virtual interrupts specific to that VDD. This service provides
+ * a way to manage the contention for the free irq lines.
+ *
+ * This service does not prevent VDDs that do not own a given IrqLine from
+ * calling VDDSimulateInterrupt specifying that IrqLine. So it is important
+ * to rely on this service, rather than expecting VDDSimulateInterrupt to
+ * fail, to determine that a given IrqLine is available for use.
+ *
+ * This service may be called at any time. Typically, VDDs will use this
+ * service at init time, and pass the number of the reserved IrqLine to
+ * the vdm application/driver code. This code can then hook the corresponding
+ * interrupt vector (8-15, 70-77) using the DOS Set Vector function
+ * (Int 21h, func 25h) in order to handle the interrupts generated with
+ * the VDDSimulateInterrupt service.
+ */
+WORD VDDReserveIrqLine (
+ HANDLE hVdd,
+ WORD IrqLine)
+{
+
+ WORD ReturnValue = 0xFFFF;
+
+ if ((!hVdd) ||
+ ((IrqLine > MAX_IRQ_LINE) && (IrqLine != 0xFFFF)) ) {
+
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return(ReturnValue);
+ }
+
+ host_ica_lock(); // acquire critical section
+
+ if (IrqLine == 0xFFFF) {
+
+ for (IrqLine = MAX_IRQ_LINE; IrqLine < 0xFFFF; IrqLine--) {
+ if (IrqLines[IrqLine] == 0) {
+ IrqLines[IrqLine] = hVdd;
+ ReturnValue = IrqLine;
+ break;
+ }
+ }
+
+ } else if (IrqLines[IrqLine] == 0) {
+
+ IrqLines[IrqLine] = hVdd;
+ ReturnValue = IrqLine;
+ }
+
+ host_ica_unlock();
+
+ if (ReturnValue == 0xFFFF)
+ SetLastError(ERROR_INVALID_PARAMETER);
+
+ return(ReturnValue);
+}
+
+/*** VDDReleaseIrqLine - This service releases a lock on an Irq Line
+ * obtained with VDDReserveIrqLine
+ *
+ * Parameters:
+ * hVDD : VDD Handle
+ * IrqLine : The specific IrqLine number (0-15) to release.
+ *
+ * Return Value:
+ * VDDReleaseIrqLine returns TRUE if successful.
+ * Otherwise, this function returns FALSE and logs an error. The
+ * extended error code will be ERROR_INVALID_PARAMETER.
+ *
+ * Comments:
+ * Upon successful execution of this function, the specified IrqLine will
+ * be available to other VDDs.
+ *
+ * This service may be called at any time.
+ */
+BOOL VDDReleaseIrqLine (
+ HANDLE hVdd,
+ WORD IrqLine)
+{
+
+ BOOL Status = FALSE;
+
+ if ((!hVdd) ||
+ (IrqLine > MAX_IRQ_LINE) ) {
+
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+
+ }
+
+ host_ica_lock(); // acquire critical section
+
+ if (IrqLines[IrqLine] == hVdd) {
+ IrqLines[IrqLine] = 0;
+ Status = TRUE;
+ }
+
+ host_ica_unlock();
+
+ if (!Status)
+ SetLastError(ERROR_INVALID_PARAMETER);
+
+ return(Status);
+}
+
+
+/********************************************************/
+/* DMA stuff */
+
+
+
+/*** VDDRequestDMA - This service is provided for VDDs to request a DMA
+ * transfer.
+ *
+ * INPUT:
+ * hVDD VDD Handle
+ * iChannel DMA Channel on which the operation to take place
+ * Buffer Buffer where to or from transfer to take place
+ * length Transfer Count (in bytes)
+ *
+ * If Zero, returns the Current VDMA transfer count
+ * in bytes.
+ *
+ * OUTPUT
+ * DWORD returns bytes transferred
+ * if Zero check GetLastError to determine if the
+ * call failed or succeeded
+ * GetLastError has the extended error information.
+ *
+ * NOTES
+ * 1. This service is intended for those VDDs which do not want to
+ * carry on the DMA operation on their own. Carrying on a DMA
+ * operation involves understanding all the DMA registers and
+ * figuring out what has to be copied, from where and how much.
+ *
+ * 2. This service will be slower than using VDDQueryDMA/VDDSetDMA and
+ * doing the transfer on your own.
+ *
+ * 3. Extended Error codes:
+ *
+ * ERROR_ALREADY_EXISTS - Vdd already has active IO port handlers
+ * ERROR_OUTOFMEMORY - Insufficient resources for additional VDD
+ * Port handler set.
+ * ERROR_INVALID_ADDRESS - One of the IO port handlers has an invalid
+ * address.
+ *
+ */
+DWORD VDDRequestDMA (
+ HANDLE hVDD,
+ WORD iChannel,
+ PVOID Buffer,
+ DWORD length )
+{
+ DMA_ADAPT *pDmaAdp;
+ DMA_CNTRL *pDcp;
+ WORD Chan;
+ WORD Size;
+ WORD tCount;
+ BOOL bMore;
+
+
+ if (iChannel > DMA_CONTROLLER_CHANNELS*DMA_ADAPTOR_CONTROLLERS) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+
+ pDmaAdp = dmaGetAdaptor();
+ pDcp = &pDmaAdp->controller[dma_physical_controller(iChannel)];
+ Chan = dma_physical_channel(iChannel);
+ Size = dma_unit_size(iChannel);
+
+ // if the controller or the channel is disabled, return 0
+ if (pDcp->command.bits.controller_disable == 1 ||
+ (pDcp->mask & (1 << Chan)) == 0)
+ return (0);
+
+ tCount = ((WORD)pDcp->current_count[Chan][1] << 8)
+ | (WORD)pDcp->current_count[Chan][0];
+
+ SetLastError(0); // assume success
+
+ // return requested transfer count (in bytes)
+ if (!length) {
+ return (DWORD)Size*((DWORD)tCount + 1);
+ }
+
+ length = length/Size - 1;
+
+ if (length > 0xFFFF) {
+ length = 0xFFFF;
+ }
+
+ try {
+ bMore = (BOOL) dma_request((half_word)iChannel,
+ Buffer,
+ (word) length);
+ }
+ except(EXCEPTION_EXECUTE_HANDLER) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return 0;
+ }
+
+ if (!bMore) { // terminal count has been reached
+ return ((DWORD)tCount+1) * (DWORD)Size;
+ }
+
+ tCount -= ((WORD)pDcp->current_count[Chan][1] << 8)
+ | (WORD)pDcp->current_count[Chan][0];
+
+ return ((DWORD)tCount + 1) * (DWORD)Size;
+}
+
+
+
+
+
+/*** VDDQueryDMA - This service is provided for VDDs to collect all the DMA
+ * data.
+ *
+ * INPUT:
+ * hVDD VDD Handle
+ * iChannel DMA Channel for which to query
+ * Buffer Buffer where information will be returned
+ *
+ * OUTPUT
+ * SUCCESS : Returns TRUE
+ * FAILURE : Returns FALSE
+ * GetLastError has the extended error information.
+ *
+ *
+ * NOTES
+ * 1. This service is intended for those VDD which are doing
+ * performance critical work. These VDD can do their own DMA
+ * transfers and avoid one extra buffer copying which is a
+ * overhead in using VDDRequestDMA.
+ *
+ * 2. VDDs should use VDDSetDMA to properly update the state of
+ * DMA after carrying on the operation.
+ *
+ * 3. Extended Error codes:
+ *
+ * ERROR_INVALID_ADDRESS - Invalid channel
+ *
+ */
+BOOL VDDQueryDMA (
+ HANDLE hVDD,
+ WORD iChannel,
+ PVDD_DMA_INFO pDmaInfo)
+{
+ DMA_ADAPT *pDmaAdp;
+ DMA_CNTRL *pDcp;
+ WORD Chan;
+
+
+ if (iChannel > DMA_CONTROLLER_CHANNELS*DMA_ADAPTOR_CONTROLLERS) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+
+ pDmaAdp = dmaGetAdaptor();
+ pDcp = &pDmaAdp->controller[dma_physical_controller(iChannel)];
+ Chan = dma_physical_channel(iChannel);
+
+
+ pDmaInfo->addr = ((WORD)pDcp->current_address[Chan][1] << 8)
+ | (WORD)pDcp->current_address[Chan][0];
+
+ pDmaInfo->count = ((WORD)pDcp->current_count[Chan][1] << 8)
+ | (WORD)pDcp->current_count[Chan][0];
+
+ pDmaInfo->page = (WORD) pDmaAdp->pages.page[iChannel];
+ pDmaInfo->status = (BYTE) pDcp->status.all;
+ pDmaInfo->mode = (BYTE) pDcp->mode[Chan].all;
+ pDmaInfo->mask = (BYTE) pDcp->mask;
+
+
+ return TRUE;
+}
+
+
+
+
+/*** VDDSetDMA - This service is provided for VDDs to set the DMA data.
+ *
+ * INPUT:
+ * hVDD VDD Handle
+ * iChannel DMA Channel for which to query
+ * fDMA Bit Mask indicating which DMA data fields are to be set
+ * VDD_DMA_ADDR
+ * VDD_DMA_COUNT
+ * VDD_DMA_PAGE
+ * VDD_DMA_STATUS
+ * Buffer Buffer with DMA data
+ *
+ * OUTPUT
+ * SUCCESS : Returns TRUE
+ * FAILURE : Returns FALSE
+ * GetLastError has the extended error information.
+ *
+ * NOTES
+ *
+ * 1. Extended Error codes:
+ *
+ * ERROR_INVALID_ADDRESS - Invalid channel
+ *
+ */
+BOOL VDDSetDMA (
+ HANDLE hVDD,
+ WORD iChannel,
+ WORD fDMA,
+ PVDD_DMA_INFO pDmaInfo)
+{
+ DMA_ADAPT *pDmaAdp;
+ DMA_CNTRL *pDcp;
+ WORD Chan;
+
+
+ if (iChannel > DMA_CONTROLLER_CHANNELS*DMA_ADAPTOR_CONTROLLERS) {
+ SetLastError(ERROR_INVALID_ADDRESS);
+ return FALSE;
+ }
+
+
+ pDmaAdp = dmaGetAdaptor();
+ pDcp = &pDmaAdp->controller[dma_physical_controller(iChannel)];
+ Chan = dma_physical_channel(iChannel);
+
+ if (fDMA & VDD_DMA_ADDR) {
+ pDcp->current_address[Chan][1] = (half_word)HIBYTE(pDmaInfo->addr);
+ pDcp->current_address[Chan][0] = (half_word)LOBYTE(pDmaInfo->addr);
+ }
+
+ if (fDMA & VDD_DMA_COUNT) {
+ pDcp->current_count[Chan][1] = (half_word)HIBYTE(pDmaInfo->count);
+ pDcp->current_count[Chan][0] = (half_word)LOBYTE(pDmaInfo->count);
+ }
+
+ if (fDMA & VDD_DMA_PAGE) {
+ pDmaAdp->pages.page[iChannel] = (half_word)pDmaInfo->page;
+ }
+
+ if (fDMA & VDD_DMA_STATUS) {
+ pDcp->status.all = (BYTE) pDmaInfo->status;
+ }
+
+
+ return TRUE;
+}
diff --git a/private/mvdm/softpc.new/host/src/nt_vflop.c b/private/mvdm/softpc.new/host/src/nt_vflop.c
new file mode 100644
index 000000000..48726d4e0
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_vflop.c
@@ -0,0 +1,604 @@
+#include "host_dfs.h"
+
+
+#ifdef VFLOPPY
+/*****************************************************************************
+* nt_vflop.c - virtual floppy disk provision for Microsoft(tm). *
+* *
+* File derived from gfi_vflop.c by Henry Nash. *
+* *
+* This version is written/ported for New Technology OS/2 *
+* by Andrew Watson *
+* *
+* Modified so that only a single drive (B:) is available to prevent *
+* an accidental floppy boot. *
+* *
+* Date pending due to ignorance *
+* *
+* (c) Copyright Insignia Solutions 1991 *
+* *
+*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+
+#define L_SET 0
+
+/*
+ * SoftPC include files
+ */
+#include "xt.h"
+#include CpuH
+#include "sas.h"
+#include "bios.h"
+#include "ios.h"
+#include "trace.h"
+#include "fla.h"
+#include "dma.h"
+#include "gfi.h"
+#include "config.h"
+
+extern boolean gain_ownership();
+extern void release_ownership();
+
+/*
+ * First - description of the PC disk/diskette in standard PC-DOS format
+ */
+
+#define PC_BYTES_PER_SECTOR 512
+#define PC_TRACKS_PER_DISKETTE 40
+#define PC_HEADS_PER_DISKETTE 2
+#define PC_SECTORS_PER_DISKETTE_TRACK 9
+
+/*
+ * The Maximum number of sectors per diskette that the FDC will support
+ */
+
+#define PC_MAX_SECTORS_PER_DISKETTE_TRACK 12
+#define PC_MAX_BYTES_PER_SECTOR 4096
+
+
+
+/*
+ * ... and where the diskettes resides under UNIX
+ */
+
+#define BS_DISKETTE_NAME "c:\\softpc\\pctool.A"
+
+#define BS_DISKETTE_DOS_SID_NAME "c:\\softpc\\dos.SID"
+#define BS_DISKETTE_SID_NAME "c:\\softpc\\pctool.SID"
+
+
+/*
+ * The disk buffer used for moving between memory and the UNIX file.
+ * Currently this can opnly be one sector - but this could be easily
+ * increased if performance dictates.
+ */
+
+#define BS_DISK_BUFFER_SIZE 1 /* in sectors */
+
+half_word bs_disk_buffer[PC_MAX_BYTES_PER_SECTOR * BS_DISK_BUFFER_SIZE];
+
+/*
+ * Each virtual disk has a flag to say if the UNIX file is open
+ */
+
+static int bs_diskette_open = FALSE;
+
+/*
+ * Each virtual disk has a file descriptor
+ */
+
+static int bs_diskette_fd;
+
+/*
+ * A virtual disk is read only if the Unix protection flag dictate it.
+ */
+
+static boolean diskette_read_only;
+
+
+/*
+ * The structure of an entry in the Sector Mapping Table
+ */
+
+typedef struct
+ {
+ half_word no_of_sectors;
+ half_word sector_ID[PC_MAX_SECTORS_PER_DISKETTE_TRACK];
+ word bytes_per_sector;
+ double_word start_position;
+ }
+SID_ENTRY;
+
+/*
+ * The table itself - an entry for each track and head combination.
+ * It is filled in by the fl_read_SID() function at run time.
+ */
+
+static SID_ENTRY fl_track_index[PC_TRACKS_PER_DISKETTE][PC_HEADS_PER_DISKETTE];
+
+/*
+ * Table to convert the N format number into bytes per sector. The first
+ * location is not used as N starts at 1.
+ */
+
+static word fl_sector_sizes[] = {0,256,512,1024,2048,4096} ;
+static void fl_read_SID();
+static short fl_sector_check();
+
+/*
+ * Global variable for name of diskette file
+ */
+char diskette_name[256];
+
+/*
+ * A macro to calculate the sector offset from the start of the UNIX virtual
+ * diskette file for a given track and sector. This uses the track mapping
+ * table to find the start of the track.
+ */
+
+#define diskette_position(track, head, sector, bytes_per_sector) \
+ (fl_track_index[track][head].start_position + \
+ ((sector - 1) * bytes_per_sector))
+
+/*
+ * A macro returning TRUE if the drive is empty
+ */
+
+#define drive_empty() (strcmp(diskette_name, "empty drive") == 0)
+
+static char *prog_name ="gfi_vfloppy:";
+
+static int gfi_vdiskette_command();
+static int gfi_vdiskette_drive_on();
+static int gfi_vdiskette_drive_off();
+static int gfi_vdiskette_reset();
+
+
+/*
+ * ============================================================================
+ * External functions
+ * ============================================================================
+ */
+
+
+void gfi_vdiskette_init(drive)
+int drive;
+{
+/*
+ * Allow only the use of drive B:
+ *
+ * 1 - Drive A
+ * 1 - Drive B
+ */
+
+if(drive!=1)
+ drive=1;
+
+gfi_function_table[drive].command_fn = gfi_vdiskette_command;
+gfi_function_table[drive].drive_on_fn = gfi_vdiskette_drive_on;
+gfi_function_table[drive].drive_off_fn = gfi_vdiskette_drive_off;
+gfi_function_table[drive].reset_fn = gfi_vdiskette_reset;
+}
+
+
+void gfi_vdiskette_term(drive)
+int drive; /* Currently parameter is ignored */
+{
+if (bs_diskette_open)
+ {
+ release_ownership(bs_diskette_fd);
+ close(bs_diskette_fd);
+ bs_diskette_open = FALSE;
+ }
+}
+
+void fl_int_reset()
+{
+/*
+ * Reset function for use by the 'Change Diskette function'
+ * and the standard floppy reset function. Also called by
+ * 'X_input.c' by 'new_disk()' when a new diskette is
+ * selected.
+ * No PC registers are modified in this function.
+ *
+ * Reset the virtual diskette by re-opening the file.
+ *
+ * First, if the file is open - close it.
+ */
+char dpath[MAXPATHLEN];
+
+if (bs_diskette_open)
+ {
+ release_ownership(bs_diskette_fd);
+ close(bs_diskette_fd);
+ bs_diskette_open = FALSE;
+ }
+strcpy(dpath, configuration.cf_fl_dir);
+strcat(dpath, "\\");
+strcat(dpath, diskette_name);
+
+
+bs_diskette_open = TRUE; /* Assume success */
+diskette_read_only = FALSE; /* Assume read/write */
+
+bs_diskette_fd = open(dpath,O_RDWR,0);
+
+if (bs_diskette_fd < 0)
+ {
+ bs_diskette_fd = open(dpath, O_RDONLY,0);
+ if (bs_diskette_fd >= 0)
+ diskette_read_only = TRUE;
+ else
+ {
+ bs_diskette_open = FALSE;
+ fprintf(trace_file, "%s open error: %s\n", prog_name, dpath);
+ return;
+ }
+ }
+
+/*
+ * Now open the Sector ID file
+ */
+
+fl_read_SID(diskette_name);
+}
+/*
+ * ============================================================================
+ * Internal functions
+ * ============================================================================
+ */
+
+static int gfi_vdiskette_command(command_block, result_block)
+FDC_CMD_BLOCK *command_block;
+FDC_RESULT_BLOCK *result_block;
+{
+ half_word temp;
+ int source_start;
+ sys_addr destination_start;
+ sys_addr dma_address;
+ sys_addr pos;
+ int transfer_count;
+ int status;
+ int sector_index;
+ int bytes_per_sector;
+ int sector_count = 0;
+ word dma_size;
+ half_word C, H, R, N;
+ int track_info;
+ int i;
+ int ret_stat = SUCCESS;
+ boolean failed = FALSE;
+
+ switch(command_block->type.cmd) {
+ case FDC_READ_DATA:
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file,"%s Read Data Command \n", prog_name);
+ dma_enquire(DMA_DISKETTE_CHANNEL, &dma_address, &dma_size);
+ sector_index = fl_sector_check(command_block->c0.cyl,
+ command_block->c0.hd,
+ command_block->c0.sector);
+ if (sector_index == -1) {
+ /*
+ * Sector not found
+ */
+ result_block->c0.ST0 = 0x40;
+ result_block->c0.ST1 = 0x00;
+ result_block->c1.ST1_no_data = 1;
+ result_block->c0.ST2 = 0x00;
+ }
+ else {
+ bytes_per_sector = fl_sector_sizes[command_block->c0.N];
+ source_start = diskette_position(command_block->c0.cyl,
+ command_block->c0.hd,
+ sector_index,
+ bytes_per_sector);
+ transfer_count = (dma_size + 1) / bytes_per_sector;
+
+ /*
+ * First SEEK to the start position
+ */
+
+ if (lseek(bs_diskette_fd, source_start, L_SET) < 0)
+ fprintf(trace_file, "%s Seek failed\n", prog_name);
+ else {
+ gain_ownership(bs_diskette_fd);
+ while(!failed && sector_count < transfer_count) {
+ /*
+ * Read sectors one by one into memory
+ * via the disk buffer
+ */
+ status = read(bs_diskette_fd,
+ bs_disk_buffer, bytes_per_sector);
+ if (status != bytes_per_sector)
+ fprintf(trace_file, "%s Read failed\n", prog_name);
+ else
+ dma_request(DMA_DISKETTE_CHANNEL,
+ bs_disk_buffer, bytes_per_sector);
+ sector_count++;
+ }
+ }
+ result_block->c0.ST0 = 0x04;
+ result_block->c0.ST1 = 0x00;
+ result_block->c0.ST2 = 0x00;
+ }
+ result_block->c0.cyl = command_block->c0.cyl;
+ result_block->c0.head = command_block->c0.hd;
+ result_block->c0.sector = ((command_block->c0.sector - 1 + transfer_count) % PC_SECTORS_PER_DISKETTE_TRACK) + 1;
+ result_block->c0.N = command_block->c0.N;
+ break;
+
+ case FDC_WRITE_DATA:
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file,"%s Write Data Command \n", prog_name);
+
+ dma_enquire(DMA_DISKETTE_CHANNEL, &dma_address, &dma_size);
+ sector_index = fl_sector_check(command_block->c0.cyl,
+ command_block->c0.hd,
+ command_block->c0.sector);
+ bytes_per_sector = fl_sector_sizes[command_block->c0.N];
+ destination_start = diskette_position(command_block->c0.cyl,
+ command_block->c0.hd,
+ sector_index,
+ bytes_per_sector);
+ transfer_count = (dma_size + 1) / bytes_per_sector;
+
+ /*
+ * First SEEK to the start position
+ */
+
+ if (lseek(bs_diskette_fd, destination_start, L_SET) < 0)
+ fprintf(trace_file, "%s Seek failed\n", prog_name);
+ else {
+ gain_ownership(bs_diskette_fd);
+ while(!failed && sector_count < transfer_count) {
+ /*
+ * Write sectors one by one from memory via the disk buffer
+ */
+ dma_request(DMA_DISKETTE_CHANNEL,
+ bs_disk_buffer, bytes_per_sector);
+ status = write(bs_diskette_fd,
+ bs_disk_buffer, bytes_per_sector);
+ if (status != bytes_per_sector) {
+ failed = TRUE;
+ }
+ sector_count++;
+ }
+ }
+ result_block->c0.ST0 = 0x00; /* Clear down result bytes */
+ result_block->c0.ST1 = 0x00;
+
+ if (failed) {
+ result_block->c1.ST0_int_code = 1;
+ result_block->c1.ST1_write_protected = 1;
+ }
+ else {
+ result_block->c1.ST0_head_address = 1;
+ result_block->c0.ST1 = 0x00;
+ }
+ result_block->c0.ST2 = 0x00;
+ result_block->c0.cyl = command_block->c0.cyl;
+ result_block->c0.head = command_block->c0.hd;
+ result_block->c0.sector = ((command_block->c0.sector - 1 + transfer_count) % PC_SECTORS_PER_DISKETTE_TRACK) + 1;
+ result_block->c0.N = command_block->c0.N;
+ break;
+
+ case FDC_READ_TRACK:
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file,"%s Read Track Command \n", prog_name);
+
+ break;
+
+ case FDC_SPECIFY:
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file, "%s Specify command\n", prog_name);
+ break;
+
+ case FDC_RECALIBRATE:
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file, "%s Recalibrate command\n", prog_name);
+
+ result_block->c3.ST0 = 0;
+ result_block->c1.ST0_int_code = 0;
+ result_block->c1.ST0_seek_end = 0;
+ result_block->c1.ST0_unit = command_block->c5.drive;
+ result_block->c3.PCN = 0;
+ break;
+
+ case FDC_SENSE_DRIVE_STATUS:
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file, "%s Sense Drive Status command\n", prog_name);
+
+ result_block->c2.ST3_fault = 0;
+ result_block->c2.ST3_write_protected = diskette_read_only;
+ result_block->c2.ST3_ready = 1;
+ result_block->c2.ST3_track_0 = 0;
+ result_block->c2.ST3_two_sided = 1;
+ result_block->c2.ST3_head_address = 0;
+ result_block->c2.ST3_unit = command_block->c7.drive;
+ break;
+
+ case FDC_SEEK:
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file, "%s Seek command\n", prog_name);
+ result_block->c3.ST0 = 0;
+
+ if (drive_empty()) {
+ result_block->c1.ST0_int_code = 1;
+ result_block->c1.ST0_seek_end = 0;
+ result_block->c1.ST0_unit = command_block->c8.drive;
+ ret_stat = FAILURE;
+ }
+ else {
+ result_block->c1.ST0_int_code = 0;
+ result_block->c1.ST0_seek_end = 1;
+ result_block->c1.ST0_unit = command_block->c8.drive;
+ result_block->c3.PCN = command_block->c8.new_cyl;
+ }
+ break;
+
+ case FDC_FORMAT_TRACK:
+ if (diskette_read_only) {
+ result_block->c1.ST0_int_code = 1;
+ result_block->c1.ST1_write_protected = 1;
+ }
+ else {
+ dma_enquire(DMA_DISKETTE_CHANNEL, &dma_address, &dma_size);
+ for ( i=0; i<command_block->c3.SC; i++) {
+ sas_load(dma_address++, &C);
+ sas_load(dma_address++, &H);
+ sas_load(dma_address++, &R);
+ sas_load(dma_address++, &N);
+ fprintf(trace_file,
+ "%s Format track: trk %x hd %x sector %x N_format %x\n",
+ prog_name, C, H, R, N);
+ }
+ }
+ break;
+
+ default:
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file, "%s Un-implemented command, type %x\n",
+ prog_name, command_block->type.cmd);
+ }
+
+ return(ret_stat);
+}
+
+
+static int gfi_vdiskette_drive_on(drive)
+int drive;
+{
+#ifndef PROD
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file, "%s Drive on command - drive %x\n", prog_name, drive);
+#endif
+
+ return(SUCCESS);
+}
+
+static int gfi_vdiskette_drive_off(drive)
+int drive;
+{
+#ifndef PROD
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file, "%s Drive off command - drive %x\n", prog_name, drive);
+#endif
+
+ return(SUCCESS);
+}
+
+
+static int gfi_vdiskette_reset(result_block)
+FDC_RESULT_BLOCK *result_block;
+{
+#ifndef PROD
+ if (io_verbose & GFI_VERBOSE)
+ fprintf(trace_file, "%s Reset command\n", prog_name);
+#endif
+
+ /*
+ * First reset the virtual diskette by closing and opening the file
+ */
+
+ fl_int_reset();
+
+ /*
+ * Fake up the Sense Interrupt Status result phase. We don't know the
+ * Present Cylinder No, so leave as zero.
+ */
+
+ result_block->c3.ST0 = 0;
+ result_block->c3.PCN = 0;
+
+ return(SUCCESS);
+}
+
+
+static short fl_sector_check(track, head, sector)
+half_word track;
+half_word head;
+half_word sector;
+{
+ /*
+ * Check the sector ID's in the mapping table for this track and head.
+ * Return -1 if the sector is not found, else the sector index with
+ * respect to the start of the track.
+ */
+
+ int i = 0;
+ int found = FALSE;
+
+ while (i < fl_track_index[track][head].no_of_sectors && !found)
+ {
+ if (fl_track_index[track][head].sector_ID[i] == sector)
+ found = TRUE;
+ else
+ i++;
+ }
+
+ if (found)
+ return(i + 1); /* sectors start at 1 */
+ else
+ return(-1);
+}
+
+
+static void fl_read_SID(sidname)
+char *sidname;
+{
+ /*
+ * Attempt to read the sector ID file. If found load the
+ * information into the track mapping table, else load in
+ * the standard DOS format.
+ */
+
+ FILE *fptr = NULL;
+ double_word cur_position = 0;
+ int track, head, no_of_sectors, N_format, sector_ID;
+ char buf[80];
+ char sector_nos[80];
+ char rest[80];
+ int i;
+ char sidpath[MAXPATHLEN];
+
+
+ if (fptr == NULL)
+ {
+ fptr = fopen(BS_DISKETTE_DOS_SID_NAME, "r");
+ if (fptr == NULL)
+ {
+ printf("Can't open standard DOS sector ID file - %s\n", BS_DISKETTE_DOS_SID_NAME);
+ return;
+ }
+ }
+
+ while(fgets(buf,80,fptr) != NULL)
+ {
+ if (buf[0] != '#')
+ {
+ sscanf(buf, "%d %d %d %d %[^\n]", &track, &head, &N_format,
+ &no_of_sectors, sector_nos);
+ fl_track_index[track][head].no_of_sectors = no_of_sectors;
+ fl_track_index[track][head].bytes_per_sector = fl_sector_sizes[N_format];
+ fl_track_index[track][head].start_position = cur_position;
+
+ for( i = 0; i < no_of_sectors; i++)
+ {
+ sscanf(sector_nos, "%d %[^\n]", &sector_ID, rest);
+ fl_track_index[track][head].sector_ID[i] = sector_ID;
+ strcpy(sector_nos, rest);
+ }
+
+ cur_position += (fl_track_index[track][head].bytes_per_sector * no_of_sectors);
+ }
+ }
+
+ fclose(fptr);
+}
+#endif /* VFLOPPY */
diff --git a/private/mvdm/softpc.new/host/src/nt_vga.c b/private/mvdm/softpc.new/host/src/nt_vga.c
new file mode 100644
index 000000000..a5c97c34f
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_vga.c
@@ -0,0 +1,2188 @@
+/*
+ * SoftPC Revision 3.0
+ *
+ * Title : Win32 VGA Graphics Module
+ *
+ * Description :
+ *
+ * This modules contain the Win32 specific functions required
+ * to support the VGA emulation.
+ *
+ * Author : Jerry Sexton (based on X_vga.c)
+ *
+ * Notes :
+ *
+ */
+
+#include <windows.h>
+#include "insignia.h"
+#include "host_def.h"
+
+#include "xt.h"
+#include "gvi.h"
+#include "gmi.h"
+#include "gfx_upd.h"
+#include <stdio.h>
+#include "trace.h"
+#include "debug.h"
+#include "egagraph.h"
+#include "egacpu.h"
+#include "egaports.h"
+#include "host_rrr.h"
+#include "conapi.h"
+
+#include "nt_graph.h"
+
+#ifdef MONITOR
+#include <ntddvdeo.h>
+#include "nt_fulsc.h"
+#endif /* MONITOR */
+
+IMPORT int DisplayErrorTerm(int, DWORD, char *, int);
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::: Initialise VGA hi res graphics ::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_init_vga_hi_graph()
+{
+ sub_note_trace0(EGA_HOST_VERBOSE, "nt_init_vga_hi_graph");
+
+ /* Set up the number of bits per pixel for this mode. */
+ sc.BitsPerPixel = VGA_BITS_PER_PIXEL;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::: Paint function (256 colour mode PC 320x200. SoftPC 640x400.):::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height )
+{
+ register unsigned short *dest_ptr;
+ register unsigned short *ref_dest_ptr;
+ register unsigned char *data_ptr;
+ register unsigned char *ref_data_ptr;
+ register int local_height;
+ register int i, temp, bpl, shorts_per_scanline;
+ int max_width = sc.PC_W_Width >> 1,
+ max_height = sc.PC_W_Height >> 1;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_graph_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((screen_x >= max_width) || (screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_graph_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > max_width)
+ width = max_width - screen_x;
+ if (screen_y + height > max_height)
+ height = max_height - screen_y;
+
+ /*
+ * Build up the bitmap: each PC pixel is stored in video memory as one
+ * byte (i.e. 8 bits-per-pixel); each PC pixel is translated to a square
+ * block of 4 host pixels.
+ */
+ bpl = get_bytes_per_line();
+ shorts_per_scanline = SHORTS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ local_height = height;
+ ref_data_ptr = &EGA_plane0123[offset];
+ ref_dest_ptr = (unsigned short *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y << 1) * shorts_per_scanline + screen_x;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Build up the bitmap. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ data_ptr = ref_data_ptr;
+
+ for( i = 0; i < width; i++ )
+ {
+ temp = *data_ptr++;
+ *(dest_ptr + shorts_per_scanline) = *dest_ptr =
+ (unsigned short)((temp << 8) | temp);
+ dest_ptr++;
+ }
+ ref_dest_ptr += 2 * shorts_per_scanline;
+ ref_data_ptr += bpl;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x << 1;
+ rect.Top = screen_y << 1;
+ rect.Right = rect.Left + (width << 1) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*Paint function (256 colour mode PC 320x200. SoftPC 640x400.) on big screen*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+#ifdef BIGWIN
+ register unsigned short *dest_ptr;
+ register unsigned short *ref_dest_ptr;
+ register unsigned char *data_ptr;
+ register unsigned char *ref_data_ptr;
+ register int local_height;
+ register int i;
+ register int temp1;
+ register int temp2;
+ register int half_width;
+ register int bpl;
+ int shorts_per_scanline;
+ int max_width = UNSCALE(sc.PC_W_Width) >> 1,
+ max_height = UNSCALE(sc.PC_W_Height) >> 1;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_graph_big off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((screen_x >= max_width) || (screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_med_graph_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > max_width)
+ width = max_width - screen_x;
+ if (screen_y + height > max_height)
+ height = max_height - screen_y;
+
+ bpl = get_bytes_per_line();
+ shorts_per_scanline = SHORTS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ local_height = height;
+ ref_data_ptr = &EGA_plane0123[offset];
+ ref_dest_ptr = (unsigned short *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y << 1) * shorts_per_scanline +
+ SCALE(screen_x);
+ half_width = width >> 1;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ data_ptr = ref_data_ptr;
+
+ for( i = 0; i < half_width; i++ )
+ {
+ temp1 = *data_ptr++;
+ temp2 = *data_ptr++;
+
+ *(dest_ptr + 2 * shorts_per_scanline) =
+ *(dest_ptr + shorts_per_scanline) =
+ *dest_ptr = (unsigned short) ((temp1 << 8) | temp1);
+
+ *(dest_ptr + (2 * shorts_per_scanline) + 1) =
+ *(dest_ptr + shorts_per_scanline + 1) =
+#ifdef BIGEND
+ *(dest_ptr + 1) = (unsigned short) ((temp1 << 8) | temp2);
+#endif /* BIGEND */
+#ifdef LITTLEND
+ *(dest_ptr + 1) = (unsigned short) ((temp2 << 8) | temp1);
+#endif /* LITTLEND */
+
+ *(dest_ptr + (2 * shorts_per_scanline) + 2) =
+ *(dest_ptr + shorts_per_scanline + 2) =
+ *(dest_ptr + 2) = (unsigned short) ((temp2 << 8) | temp2);
+
+ dest_ptr += 3;
+ }
+
+ ref_dest_ptr += 3 * shorts_per_scanline;
+ ref_data_ptr += bpl;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x << 1);
+ rect.Top = SCALE(screen_y << 1);
+ rect.Right = rect.Left + SCALE(width << 1) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*: Paint function (256 colour mode PC 320x200. SoftPC 1280x800.) on huge :*/
+/*: screen. :*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+#ifdef BIGWIN
+ unsigned char *dest_ptr;
+ unsigned char *line_ptr;
+ unsigned char *ref_dest_ptr;
+ unsigned char *data_ptr;
+ unsigned char *ref_data_ptr;
+ int local_height;
+ int i;
+ byte temp;
+ int bpl;
+ int max_width = UNSCALE(sc.PC_W_Width) >> 1,
+ max_height = UNSCALE(sc.PC_W_Height) >> 1;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_graph_huge off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((screen_x >= max_width) || (screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_med_graph_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > max_width)
+ width = max_width - screen_x;
+ if (screen_y + height > max_height)
+ height = max_height - screen_y;
+
+ bpl = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ local_height = height;
+ ref_data_ptr = &EGA_plane0123[offset];
+ ref_dest_ptr = (unsigned char *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y << 1) * bpl +
+ SCALE(screen_x << 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ line_ptr = ref_dest_ptr;
+ data_ptr = ref_data_ptr;
+
+ for(i = 0; i < width; i++)
+ {
+ dest_ptr = line_ptr;
+ temp = *data_ptr++;
+
+ /* line 1 */
+ *dest_ptr++ = temp;
+ *dest_ptr++ = temp;
+ *dest_ptr++ = temp;
+ *dest_ptr = temp;
+
+ dest_ptr = line_ptr + bpl;
+
+ /* line 2 */
+ *dest_ptr++ = temp;
+ *dest_ptr++ = temp;
+ *dest_ptr++ = temp;
+ *dest_ptr = temp;
+
+ dest_ptr = line_ptr + 2 * bpl;
+
+ /* line 3 */
+ *dest_ptr++ = temp;
+ *dest_ptr++ = temp;
+ *dest_ptr++ = temp;
+ *dest_ptr = temp;
+
+ dest_ptr = line_ptr + 3 * bpl;
+
+ /* line 4 */
+ *dest_ptr++ = temp;
+ *dest_ptr++ = temp;
+ *dest_ptr++ = temp;
+ *dest_ptr = temp;
+
+ line_ptr += 4;
+ }
+
+ ref_dest_ptr += FOUR_SCANLINES * bpl;
+ ref_data_ptr += 320;
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x << 1);
+ rect.Top = SCALE(screen_y << 1);
+ rect.Right = rect.Left + SCALE(width << 1) - 1;
+ rect.Bottom = rect.Top + SCALE(height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+#endif /* BIGWIN */
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*Paint function (256 colour mode PC 320x200. SoftPC 640x400.) */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/* The data for this mode is split over all four vga planes and is interlaced
+ 4 way onto the screen. Hence 4 pixels horizontally for every pixel that the
+ base detects. Pixels are not doubled vertically. */
+
+void nt_vga_med_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ ULONG *p0,
+ *ref_p0,
+ *dest_ptr,
+ *ref_dest_ptr,
+ data;
+ UTINY data0,
+ data1,
+ data2,
+ data3;
+ int local_height,
+ i,
+ longs_per_scanline;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_med_graph_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* This mode doubles vertically so, multiply vertical parameters by 2. */
+ screen_y <<= 1;
+ height <<= 1;
+
+ /* If the image is completely outside the display area do nothing. */
+ if (((screen_x << 3) >= sc.PC_W_Width) || (screen_y >= sc.PC_W_Height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_med_graph_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (((screen_x + width) << 3) > sc.PC_W_Width)
+ width = (sc.PC_W_Width >> 3) - screen_x;
+ if (screen_y + height > sc.PC_W_Height)
+ height = sc.PC_W_Height - screen_y;
+
+ /* local_height is number of lines in video memory. */
+ local_height = height >> 1;
+
+ /* Get pointer to video memory. */
+ ref_p0 = (ULONG *) get_regen_ptr(0, offset << 2);
+
+ /* Get pointer to bitmap. */
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (ULONG *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * longs_per_scanline + (screen_x << 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Munge. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ p0 = ref_p0;
+
+ for(i = 0; i < width; i++)
+ {
+
+ /*
+ * Get data and output to screen buffer. NOTE little endian
+ * dependent code.
+ */
+ data = *p0++;
+ data0 = (UTINY) (data & 0xff);
+ data1 = (UTINY) ((data >> 8) & 0xff);
+ data2 = (UTINY) ((data >> 16) & 0xff);
+ data3 = (UTINY) (data >> 24);
+
+ *(dest_ptr + longs_per_scanline) = *dest_ptr =
+ (data1 << 24) | (data1 << 16) | (data0 << 8) | data0;
+ dest_ptr++;
+ *(dest_ptr + longs_per_scanline) = *dest_ptr =
+ (data3 << 24) | (data3 << 16) | (data2 << 8) | data2;
+ dest_ptr++;
+ }
+
+ ref_dest_ptr += 2 * longs_per_scanline;
+ ref_p0 += get_offset_per_line();
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x << 3;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (width << 3) - 1;
+ rect.Bottom = rect.Top + height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*Paint function (256 colour mode PC 320x200. SoftPC 960x600.) */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/* The data for this mode is split over all four vga planes and is interlaced
+ 4 way onto the screen. Hence 4 pixels horizontally for every pixel that the
+ base detects. Pixels are not doubled vertically. */
+
+void nt_vga_med_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ ULONG *p0,
+ *ref_p0,
+ *dest_ptr,
+ *ref_dest_ptr,
+ data;
+ UTINY data0,
+ data1,
+ data2,
+ data3;
+ int local_height,
+ i,
+ longs_per_scanline,
+ max_width = UNSCALE(sc.PC_W_Width) >> 3,
+ max_height = UNSCALE(sc.PC_W_Height);
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_med_graph_big off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* This mode doubles vertically so, multiply vertical parameters by 2. */
+ screen_y <<= 1;
+ height <<= 1;
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((screen_x >= max_width) || (screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_med_graph_big() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > max_width)
+ width = max_width - screen_x;
+ if (screen_y + height > max_height)
+ height = max_height - screen_y;
+
+ /* local_height is number of lines in video memory. */
+ local_height = height >> 1;
+
+ /* Get pointer to video memory. */
+ ref_p0 = (ULONG *) get_regen_ptr(0, offset << 2);
+
+ /* Get pointer to bitmap. */
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (ULONG *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y) * longs_per_scanline + SCALE(screen_x << 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Munge. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ p0 = ref_p0;
+
+ for(i = 0; i < width; i++)
+ {
+
+ /*
+ * Get data and output to screen buffer. NOTE little endian
+ * dependent code.
+ */
+ data = *p0++;
+ data0 = (UTINY) (data & 0xff);
+ data1 = (UTINY) ((data >> 8) & 0xff);
+ data2 = (UTINY) ((data >> 16) & 0xff);
+ data3 = (UTINY) (data >> 24);
+
+ *(dest_ptr + 2 * longs_per_scanline) =
+ *(dest_ptr + longs_per_scanline) =
+ *dest_ptr =
+ (data1 << 24) | (data0 << 16) | (data0 << 8) | data0;
+ dest_ptr++;
+ *(dest_ptr + 2 * longs_per_scanline) =
+ *(dest_ptr + longs_per_scanline) =
+ *dest_ptr =
+ (data2 << 24) | (data2 << 16) | (data1 << 8) | data1;
+ dest_ptr++;
+ *(dest_ptr + 2 * longs_per_scanline) =
+ *(dest_ptr + longs_per_scanline) =
+ *dest_ptr =
+ (data3 << 24) | (data3 << 16) | (data3 << 8) | data2;
+ dest_ptr++;
+ }
+
+ ref_dest_ptr += 3 * longs_per_scanline;
+ ref_p0 += get_offset_per_line();
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x << 3);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(width << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*Paint function (256 colour mode PC 320x200. SoftPC 1080x800.) */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/* The data for this mode is split over all four vga planes and is interlaced
+ 4 way onto the screen. Hence 4 pixels horizontally for every pixel that the
+ base detects. Pixels are not doubled vertically. */
+
+void nt_vga_med_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ ULONG *p0,
+ *ref_p0,
+ *dest_ptr,
+ *ref_dest_ptr,
+ data;
+ UTINY data0,
+ data1,
+ data2,
+ data3;
+ int local_height,
+ i,
+ longs_per_scanline,
+ max_width = UNSCALE(sc.PC_W_Width) >> 3,
+ max_height = UNSCALE(sc.PC_W_Height);
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_med_graph_huge off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* This mode doubles vertically so, multiply vertical parameters by 2. */
+ screen_y <<= 1;
+ height <<= 1;
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((screen_x >= max_width) || (screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_med_graph_huge() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > max_width)
+ width = max_width - screen_x;
+ if (screen_y + height > max_height)
+ height = max_height - screen_y;
+
+ /* local_height is number of lines in video memory. */
+ local_height = height >> 1;
+
+ /* Get pointer to video memory. */
+ ref_p0 = (ULONG *) get_regen_ptr(0, offset << 2);
+
+ /* Get pointer to bitmap. */
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (ULONG *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y) * longs_per_scanline + SCALE(screen_x << 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Munge. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ p0 = ref_p0;
+
+ for(i = 0; i < width; i++)
+ {
+
+ /*
+ * Get data and output to screen buffer. NOTE little endian
+ * dependent code.
+ */
+ data = *p0++;
+ data0 = (UTINY) (data & 0xff);
+ data1 = (UTINY) ((data >> 8) & 0xff);
+ data2 = (UTINY) ((data >> 16) & 0xff);
+ data3 = (UTINY) (data >> 24);
+
+ *(dest_ptr + 3 * longs_per_scanline) =
+ *(dest_ptr + 2 * longs_per_scanline) =
+ *(dest_ptr + longs_per_scanline) =
+ *dest_ptr =
+ (data0 << 24) | (data0 << 16) | (data0 << 8) | data0;
+ dest_ptr++;
+ *(dest_ptr + 3 * longs_per_scanline) =
+ *(dest_ptr + 2 * longs_per_scanline) =
+ *(dest_ptr + longs_per_scanline) =
+ *dest_ptr =
+ (data1 << 24) | (data1 << 16) | (data1 << 8) | data1;
+ dest_ptr++;
+ *(dest_ptr + 3 * longs_per_scanline) =
+ *(dest_ptr + 2 * longs_per_scanline) =
+ *(dest_ptr + longs_per_scanline) =
+ *dest_ptr =
+ (data2 << 24) | (data2 << 16) | (data2 << 8) | data2;
+ dest_ptr++;
+ *(dest_ptr + 3 * longs_per_scanline) =
+ *(dest_ptr + 2 * longs_per_scanline) =
+ *(dest_ptr + longs_per_scanline) =
+ *dest_ptr =
+ (data3 << 24) | (data3 << 16) | (data3 << 8) | data3;
+ dest_ptr++;
+ }
+
+ ref_dest_ptr += 4 * longs_per_scanline;
+ ref_p0 += get_offset_per_line();
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x << 3);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(width << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*Paint function (256 colour mode PC 320x400. SoftPC 640x400.) */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/* The data for this mode is split over all four vga planes and is interlaced
+ 4 way onto the screen. Hence 4 pixels horizontally for every pixel that the
+ base detects. Pixels are not doubled vertically. */
+
+void nt_vga_hi_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ unsigned char *p0,
+ *ref_p0,
+ *dest_ptr,
+ *ref_dest_ptr,
+ data0,
+ data1,
+ data2,
+ data3;
+ int local_height,
+ i,
+ bpl,
+ max_width = sc.PC_W_Width >> 3;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_hi_graph_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((screen_x >= max_width) || (screen_y >= sc.PC_W_Height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_hi_graph_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > max_width)
+ width = max_width - screen_x;
+ if (screen_y + height > sc.PC_W_Height)
+ height = sc.PC_W_Height - screen_y;
+
+ /* local_height is number of lines in video memory. */
+ local_height = height;
+
+ /* Get pointer to video memory. */
+ ref_p0 = get_regen_ptr(0, offset << 2);
+
+ /* Get pointer to bitmap. */
+ bpl = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (unsigned char *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * bpl + (screen_x << 3);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Munge. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ p0 = ref_p0;
+
+ for(i = 0; i < width; i++)
+ {
+ data0 = *p0++;
+ data1 = *p0++;
+ data2 = *p0++;
+ data3 = *p0++;
+
+ *dest_ptr = data0;
+ *(dest_ptr + 1) = data0;
+ *(dest_ptr + 2) = data1;
+ *(dest_ptr + 3) = data1;
+ *(dest_ptr + 4) = data2;
+ *(dest_ptr + 5) = data2;
+ *(dest_ptr + 6) = data3;
+ *(dest_ptr + 7) = data3;
+ dest_ptr += 8;
+ }
+
+ ref_dest_ptr += bpl;
+ ref_p0 += 4 * get_offset_per_line();
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x << 3;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (width << 3) - 1;
+ rect.Bottom = rect.Top + height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::Paint function (256 colour mode PC 320(360)x400. SoftPC 920(1080)x600)::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_hi_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ unsigned char *p0,
+ *ref_p0,
+ *dest_ptr,
+ *nl_dest_ptr,
+ *ref_dest_ptr,
+ data0,
+ data1,
+ data2,
+ data3;
+ int local_height,
+ draw_height,
+ local_screen_y,
+ i,
+ bpl,
+ max_width = UNSCALE(sc.PC_W_Width) >> 3,
+ max_height = UNSCALE(sc.PC_W_Height);
+ BOOL two_lines;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_hi_graph_big off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((screen_x >= max_width) || (screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_hi_graph_big() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > max_width)
+ width = max_width - screen_x;
+ if (screen_y + height > max_height)
+ height = max_height - screen_y;
+
+ /* Get pointer to video memory. */
+ ref_p0 = get_regen_ptr(0, offset << 2);
+
+ /* Get pointer to bitmap. */
+ local_screen_y = SCALE(screen_y + 1) - 1;
+ bpl = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (unsigned char *) sc.ConsoleBufInfo.lpBitMap +
+ local_screen_y * bpl +
+ SCALE(screen_x << 3);
+
+ /* Set up local parameters. */
+ local_height = height;
+ draw_height = 0;
+
+ /*
+ * 2 lines are output to the SoftPC screen if this is an odd line, 1 line
+ * if it is even.
+ */
+ two_lines = screen_y & 1 ? FALSE : TRUE;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Munge. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ p0 = ref_p0;
+
+ for( i = 0; i < width; i++ )
+ {
+ data0 = *p0++;
+ data1 = *p0++;
+ data2 = *p0++;
+ data3 = *p0++;
+
+ *dest_ptr = data0;
+ *(dest_ptr + 1) = data0;
+ *(dest_ptr + 2) = data0;
+ *(dest_ptr + 3) = data1;
+ *(dest_ptr + 4) = data1;
+ *(dest_ptr + 5) = data1;
+ *(dest_ptr + 6) = data2;
+ *(dest_ptr + 7) = data2;
+ *(dest_ptr + 8) = data2;
+ *(dest_ptr + 9) = data3;
+ *(dest_ptr + 10) = data3;
+ *(dest_ptr + 11) = data3;
+
+ if (two_lines)
+ {
+ nl_dest_ptr = dest_ptr + bpl;
+
+ *nl_dest_ptr = data0;
+ *(nl_dest_ptr + 1) = data0;
+ *(nl_dest_ptr + 2) = data0;
+ *(nl_dest_ptr + 3) = data1;
+ *(nl_dest_ptr + 4) = data1;
+ *(nl_dest_ptr + 5) = data1;
+ *(nl_dest_ptr + 6) = data2;
+ *(nl_dest_ptr + 7) = data2;
+ *(nl_dest_ptr + 8) = data2;
+ *(nl_dest_ptr + 9) = data3;
+ *(nl_dest_ptr + 10) = data3;
+ *(nl_dest_ptr + 11) = data3;
+ }
+ dest_ptr += 12;
+ }
+
+ if (two_lines)
+ {
+ draw_height += 2;
+ ref_dest_ptr += 2 * bpl;
+ }
+ else
+ {
+ draw_height++;
+ ref_dest_ptr += bpl;
+ }
+ two_lines = !two_lines;
+
+ ref_p0 += 4 * get_offset_per_line();
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x << 3);
+ rect.Top = local_screen_y;
+ rect.Right = rect.Left + SCALE(width << 3) - 1;
+ rect.Bottom = rect.Top + draw_height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::Paint function (256 colour mode PC 320(360)x400. SoftPC 1280(1440)x800::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_hi_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height )
+{
+ unsigned char *p0,
+ *ref_p0,
+ *dest_ptr,
+ *nl_dest_ptr,
+ *ref_dest_ptr,
+ data0,
+ data1,
+ data2,
+ data3;
+ int local_height,
+ i,
+ bpl,
+ max_width = UNSCALE(sc.PC_W_Width) >> 3,
+ max_height = UNSCALE(sc.PC_W_Height);
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_hi_graph_huge off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if ((screen_x >= max_width) || (screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_hi_graph_huge() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > max_width)
+ width = max_width - screen_x;
+ if (screen_y + height > max_height)
+ height = max_height - screen_y;
+
+ /* local_height is number of lines in video memory. */
+ local_height = height;
+
+ /* Get pointer to video memory. */
+ ref_p0 = get_regen_ptr(0, offset << 2);
+
+ /* Get pointer to bitmap. */
+ bpl = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (unsigned char *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y) * bpl +
+ SCALE(screen_x << 3);
+
+ /* Munge. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ p0 = ref_p0;
+
+ for(i = 0; i < width; i++)
+ {
+ data0 = *p0++;
+ data1 = *p0++;
+ data2 = *p0++;
+ data3 = *p0++;
+
+ nl_dest_ptr = dest_ptr + bpl;
+
+ *dest_ptr = *nl_dest_ptr = data0;
+ *(dest_ptr + 1) = *(nl_dest_ptr + 1) = data0;
+ *(dest_ptr + 2) = *(nl_dest_ptr + 2) = data0;
+ *(dest_ptr + 3) = *(nl_dest_ptr + 3) = data0;
+ *(dest_ptr + 4) = *(nl_dest_ptr + 4) = data1;
+ *(dest_ptr + 5) = *(nl_dest_ptr + 5) = data1;
+ *(dest_ptr + 6) = *(nl_dest_ptr + 6) = data1;
+ *(dest_ptr + 7) = *(nl_dest_ptr + 7) = data1;
+ *(dest_ptr + 8) = *(nl_dest_ptr + 8) = data2;
+ *(dest_ptr + 9) = *(nl_dest_ptr + 9) = data2;
+ *(dest_ptr + 10) = *(nl_dest_ptr + 10) = data2;
+ *(dest_ptr + 11) = *(nl_dest_ptr + 11) = data2;
+ *(dest_ptr + 12) = *(nl_dest_ptr + 12) = data3;
+ *(dest_ptr + 13) = *(nl_dest_ptr + 13) = data3;
+ *(dest_ptr + 14) = *(nl_dest_ptr + 14) = data3;
+ *(dest_ptr + 15) = *(nl_dest_ptr + 15) = data3;
+
+ dest_ptr += 16;
+ }
+
+ ref_dest_ptr += 2 * bpl;
+ ref_p0 += 4 * get_offset_per_line();
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x << 3);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(width << 3) - 1;
+ rect.Bottom = rect.Top + SCALE(height) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::: Paint function (256 colour mode: PC 320x200. SoftPC 640x400 ::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_mono_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_graph_std off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*Paint function (256 colour mode: PC 320x200. SoftPC 960x600) on big screen*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_mono_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_graph_big off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*: Paint function (256 colour mode: PC 320x200. SoftPC 1280x800) on huge :*/
+/*: screen. :*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_mono_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_graph_huge off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Paint function (256Col mode : PC 320(360)x400. SoftPC 640(720)x400) ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/* The data for this mode is split over all four vga planes and is interlaced
+ 4 way onto the screen. Hence 4 pixels horizontally for every pixel that the
+ base detects. Pixels are not doubled vertically. */
+
+
+void nt_vga_mono_med_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_med_graph_std off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Paint function (256Col mode : PC 320(360)x400. SoftPC 920(1080)x600 ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_mono_med_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_med_graph_big off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Paint function (256Col mode: PC 320(360)x400. SoftPC 1280(1440)x400 ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_mono_med_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_med_graph_huge off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height );
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Paint function (256Col mode : PC 320(360)x400. SoftPC 640(720)x400) ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+/* The data for this mode is split over all four vga planes and is interlaced
+ 4 way onto the screen. Hence 4 pixels horizontally for every pixel that the
+ base detects. Pixels are not doubled vertically. */
+
+
+void nt_vga_mono_hi_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_hi_graph_std off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Paint function (256Col mode : PC 320(360)x400. SoftPC 920(1080)x600 ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_mono_hi_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_hi_graph_big off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Paint function (256Col mode: PC 320(360)x400. SoftPC 1280(1440)x400 ::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_mono_hi_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_mono_hi_graph_huge off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height );
+}
+
+#ifdef V7VGA
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::: 256 colour mode: PC 640x400, 640x480, 720x540, 800x600. :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_v7vga_hi_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ register unsigned char *dest_ptr;
+ register unsigned char *ref_dest_ptr;
+ register unsigned char *data_ptr;
+ register unsigned char *ref_data_ptr;
+ register int local_height;
+ register int i;
+ int bytes_per_line;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_v7vga_hi_graph_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim Septemver 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>400 || width>640 ){
+ assert2( NO, "VDM: nt_v7vga_hi_graph_std() w=%d h=%d", width, height );
+ return;
+ }
+
+ local_height = height;
+ bytes_per_line = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_data_ptr = &EGA_plane0123[offset];
+ ref_dest_ptr = (unsigned char *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * bytes_per_line +
+ screen_x;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ data_ptr = ref_data_ptr;
+
+ for(i = 0; i < width; i++)
+ *dest_ptr++ = *data_ptr++;
+
+ ref_dest_ptr += bytes_per_line;
+ ref_data_ptr += get_offset_per_line();
+ }
+ while( --local_height );
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x;
+ rect.Top = screen_y;
+ rect.Right = rect.Left + width - 1;
+ rect.Bottom = rect.Top + height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::: 256 colour mode: PC 640x400, 640x480, 720x540, 800x600. :::::::::*/
+/*:::::::: SoftPC 960x600, 960x720, 1080x810, 1200x900. :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_v7vga_hi_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ register unsigned char *dest_ptr;
+ register unsigned char *ref_dest_ptr;
+ register unsigned char *data_ptr;
+ register unsigned char *ref_data_ptr;
+ register int local_height=0;
+ register int i, temp1, temp2;
+ register int half_width = width >> 1;
+ int bytes_per_line;
+ int local_screen_y;
+ BOOL two_lines;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_v7vga_hi_graph_big off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>400 || width>640 ){
+ assert2( NO, "VDM: nt_v7vga_hi_graph_big() w=%d h=%d", width, height );
+ return;
+ }
+
+ /* Get pointer to data in EGA_planes. */
+ ref_data_ptr = (unsigned char *) &EGA_plane0123[offset] +
+ (height - 1) * get_offset_per_line();
+
+ /*
+ * Get pointer into bitmap, which alternates 2 lines and 1 line so that,
+ * memory line 0 -> bitmap 0,
+ * 1 -> 2,
+ * 2 -> 3,
+ * 3 -> 5,
+ * 4 -> 6 etc.
+ * hence the local_screen_y assignment.
+ */
+ local_screen_y = SCALE(screen_y + 1) - 1;
+ bytes_per_line = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (unsigned char *) sc.ConsoleBufInfo.lpBitMap +
+ local_screen_y * bytes_per_line +
+ SCALE(screen_x);
+
+ /* Decide whether to start with 1 or 2 scanlines. */
+ two_lines = screen_y & 1 ? FALSE : TRUE;
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ data_ptr = ref_data_ptr;
+
+ for(i = 0; i < half_width; i++)
+ {
+ temp1 = *data_ptr++;
+ temp2 = *data_ptr++;
+ *dest_ptr = (unsigned char) temp1;
+ *(dest_ptr+2) = (unsigned char) temp2;
+
+ if (two_lines)
+ {
+ *(dest_ptr+1) = (unsigned char) temp1;
+ *(dest_ptr + bytes_per_line) = (unsigned char) temp1;
+ *(dest_ptr + bytes_per_line + 1) = (unsigned char) temp2;
+ *(dest_ptr + bytes_per_line + 2) = (unsigned char) temp2;
+ }
+ else
+ {
+ *(dest_ptr+1) = (unsigned char) temp2;
+ }
+ dest_ptr+=3;
+
+ }
+
+ ref_data_ptr += get_offset_per_line();
+ if (two_lines)
+ {
+ local_height += 2;
+ ref_dest_ptr += 2 * bytes_per_line;
+ }
+ else
+ {
+ local_height++;
+ ref_dest_ptr += bytes_per_line;
+ }
+ two_lines = !two_lines;
+ }
+ while(--height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = local_screen_y;
+ rect.Right = rect.Left + SCALE(width) - 1;
+ rect.Bottom = rect.Top + local_height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::: 256 colour mode: PC 640x400, 640x480, 720x540, 800x600. :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_v7vga_hi_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ register unsigned char *dest_ptr;
+ register unsigned char *ref_dest_ptr;
+ register unsigned char *data_ptr;
+ register unsigned char *ref_data_ptr;
+ register int local_height;
+ register int i;
+ int bytes_per_line;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_v7vga_hi_graph_huge off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+ /*
+ ** Tim September 92, sanity check parameters, if they're too big
+ ** it can cause a crash.
+ */
+ if( height>400 || width>640 ){
+ assert2( NO, "VDM: nt_v7vga_hi_graph_huge() w=%d h=%d", width, height );
+ return;
+ }
+
+ local_height = height;
+ bytes_per_line = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_data_ptr = &EGA_plane0123[offset];
+ ref_dest_ptr = (unsigned char *) sc.ConsoleBufInfo.lpBitMap +
+ SCALE(screen_y) * bytes_per_line +
+ SCALE(screen_x);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ data_ptr = ref_data_ptr;
+
+ for(i = 0; i < width; i++)
+ {
+ *dest_ptr = *(dest_ptr + bytes_per_line) = *data_ptr;
+ *(dest_ptr + 1) = *(dest_ptr + 1 + bytes_per_line) = *data_ptr++;
+ dest_ptr += 2;
+ }
+
+ ref_dest_ptr -= 2 * bytes_per_line;
+ ref_data_ptr += get_offset_per_line();
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = SCALE(screen_x);
+ rect.Top = SCALE(screen_y);
+ rect.Right = rect.Left + SCALE(width) - 1;
+ rect.Bottom = rect.Top + SCALE(height) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ //DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::: 256 colour mode: PC 640x400, 640x480, 720x540, 800x600. :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_v7vga_mono_hi_graph_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_v7vga_mono_hi_graph_std off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::: 256 colour mode: PC 640x400, 640x480, 720x540, 800x600. :::::::::*/
+/*:::::::: SoftPC 960x600, 960x720, 1080x810, 1200x900. :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_v7vga_mono_hi_graph_big(int offset, int screen_x, int screen_y,
+ int width, int height )
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_v7vga_mono_hi_graph_big off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height );
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::: 256 colour mode: PC 640x400, 640x480, 720x540, 800x600. :::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_v7vga_mono_hi_graph_huge(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_v7vga_mono_hi_graph_huge off=%d x=%d y=%d width=%d height=%d - NOT SUPPORTED\n",
+ offset, screen_x, screen_y, width, height);
+}
+#endif /* V7VGA */
+
+#ifdef MONITOR
+/* There are 2 possible formats for the standard 256 colour VGA mode. One (VGA,
+ * S3, Ultra etc) has shape 1/ below, the other (ET4000, WD) has a packed
+ * format more like emulation /2.
+ * The Miniport sets a flag to tell use which format to use.
+ *
+ * 1/ uses paint routine nt_vga_frozen_std
+ * Regen Memory: XYABJKLM
+ * Plane 0: X...J...
+ * Plane 1: Y...K...
+ * Plane 2: A...L...
+ * Plane 3: B...M...
+ * (plus a 1 byte skip every 16k).
+ *
+ * 2/ uses paint routine nt_vga_frozen_pack_std
+ * Regen Memory: XYABJKLM
+ * Plane 0: XJ..
+ * Plane 1: YK..
+ * Plane 2: AL..
+ * Plane 3: BM..
+ *
+ */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::: Frozen paint function (256 colour mode PC 320x200. SoftPC 640x400.):::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_frozen_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ USHORT *dest_ptr,
+ *ref_dest_ptr;
+ UTINY *plane1_ptr,
+ *plane2_ptr,
+ *plane3_ptr,
+ *plane4_ptr;
+ ULONG width_loc,
+ mem_loc,
+ shorts_per_scanline,
+ max_width = sc.PC_W_Width >> 1,
+ max_height = sc.PC_W_Height >> 1;
+
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_frozen_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if (((ULONG)screen_x >= max_width) || ((ULONG) screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > (int)max_width)
+ width = max_width - screen_x;
+ if ((ULONG) (screen_y + height) > max_height)
+ height = max_height - screen_y;
+
+ rect.Left = screen_x << 1;
+ rect.Top = screen_y << 1;
+ rect.Right = rect.Left + (width << 1) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+
+
+
+ /* memory involved here liable to be suddenly removed due to fs switch */
+ try
+ {
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /*
+ * Build up the bitmap: each PC pixel is stored in video memory as one
+ * byte (i.e. 8 bits-per-pixel); each PC pixel is translated to a square
+ * block of 4 host pixels.
+ */
+ shorts_per_scanline = SHORTS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ width >>= 2;
+ ref_dest_ptr = (unsigned short *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y << 1) * shorts_per_scanline + screen_x;
+
+
+ /* Set up the plane pointers. */
+ plane1_ptr = GET_OFFSET(Plane1Offset);
+ plane2_ptr = GET_OFFSET(Plane2Offset);
+ plane3_ptr = GET_OFFSET(Plane3Offset);
+ plane4_ptr = GET_OFFSET(Plane4Offset);
+
+ /* Build up the bitmap. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ ref_dest_ptr += shorts_per_scanline << 1;
+ mem_loc = offset;
+ offset += width;
+ width_loc = width;
+
+ do
+ {
+ ULONG PlaneOffset;
+ USHORT Tmp;
+
+ //
+ // Doubleword addressing mode...
+ //
+ PlaneOffset = ((mem_loc & 0x3fff) << 2) +
+ ((mem_loc++ & 0x3000) >> 12);
+
+ Tmp = *(plane1_ptr + PlaneOffset);
+ *dest_ptr =
+ *(dest_ptr + shorts_per_scanline) = (Tmp << 8) | Tmp;
+ dest_ptr++;
+
+ Tmp = *(plane2_ptr + PlaneOffset);
+ *dest_ptr =
+ *(dest_ptr + shorts_per_scanline) = (Tmp << 8) | Tmp;
+ dest_ptr++;
+
+ Tmp = *(plane3_ptr + PlaneOffset);
+ *dest_ptr =
+ *(dest_ptr + shorts_per_scanline) = (Tmp << 8) | Tmp;
+ dest_ptr++;
+
+ Tmp = *(plane4_ptr + PlaneOffset);
+ *dest_ptr =
+ *(dest_ptr + shorts_per_scanline) = (Tmp << 8) | Tmp;
+ dest_ptr++;
+
+ } while (--width_loc);
+
+ } while(--height);
+
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+ assert0(NO, "Handled fault in nt_vga_frozen_std. fs switch?");
+ return;
+ }
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Frozen paint function (256 colour mode packed. PC 320x200 SoftPC 640x400.)*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+void nt_vga_frozen_pack_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ USHORT *dest_ptr,
+ *ref_dest_ptr;
+ UTINY *plane1_ptr,
+ *plane2_ptr,
+ *plane3_ptr,
+ *plane4_ptr;
+ ULONG local_width,
+ local_height,
+ mem_loc,
+ temp,
+ bpl,
+ shorts_per_scanline,
+ max_width = sc.PC_W_Width >> 1,
+ max_height = sc.PC_W_Height >> 1;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_frozen_pack_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height );
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if (((ULONG)screen_x >= max_width) || ((ULONG) screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > (int)max_width)
+ width = max_width - screen_x;
+ if ((ULONG) (screen_y + height) > max_height)
+ height = max_height - screen_y;
+
+ /* memory involved here liable to be suddenly removed due to fs switch */
+ try
+ {
+ /*
+ * Build up the bitmap: each PC pixel is stored in video memory as one
+ * byte (i.e. 8 bits-per-pixel); each PC pixel is translated to a square
+ * block of 4 host pixels.
+ */
+ bpl = get_bytes_per_line() >> 2;
+ shorts_per_scanline = SHORTS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ local_height = height;
+ ref_dest_ptr = (unsigned short *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y << 1) * shorts_per_scanline + screen_x;
+
+ /* Set up the plane pointers. */
+ plane1_ptr = GET_OFFSET(Plane1Offset);
+ plane2_ptr = GET_OFFSET(Plane2Offset);
+ plane3_ptr = GET_OFFSET(Plane3Offset);
+ plane4_ptr = GET_OFFSET(Plane4Offset);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Build up the bitmap. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ mem_loc = offset;
+ local_width = width >> 2;
+
+ do
+ {
+
+ temp = *(plane1_ptr + mem_loc);
+ *(dest_ptr + shorts_per_scanline) = *dest_ptr =
+ (unsigned short)((temp << 8) | temp);
+ dest_ptr++;
+ temp = *(plane2_ptr + mem_loc);
+ *(dest_ptr + shorts_per_scanline) = *dest_ptr =
+ (unsigned short)((temp << 8) | temp);
+ dest_ptr++;
+ temp = *(plane3_ptr + mem_loc);
+ *(dest_ptr + shorts_per_scanline) = *dest_ptr =
+ (unsigned short)((temp << 8) | temp);
+ dest_ptr++;
+ temp = *(plane4_ptr + mem_loc);
+ *(dest_ptr + shorts_per_scanline) = *dest_ptr =
+ (unsigned short)((temp << 8) | temp);
+ dest_ptr++;
+ mem_loc ++;
+ }
+ while (--local_width);
+ ref_dest_ptr += 2 * shorts_per_scanline;
+ offset += bpl;
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x << 1;
+ rect.Top = screen_y << 1;
+ rect.Right = rect.Left + (width << 1) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "Handled fault in nt_vga_frozen_std. fs switch?");
+ return;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Frozen paint function (256 colour mode PC 320x200. SoftPC 640x400.) */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_med_frozen_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ ULONG *dest_ptr,
+ *ref_dest_ptr,
+ max_width = sc.PC_W_Width >> 3,
+ max_height = sc.PC_W_Height >> 1,
+ bpl,
+ local_height,
+ local_width,
+ longs_per_scanline,
+ mem_loc;
+ UTINY data0,
+ data1,
+ data2,
+ data3,
+ *plane1_ptr,
+ *plane2_ptr,
+ *plane3_ptr,
+ *plane4_ptr;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_med_frozen_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if (((ULONG)screen_x >= max_width) || ((ULONG) screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_med_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > (int)max_width)
+ width = max_width - screen_x;
+ if ((ULONG) (screen_y + height) > max_height)
+ height = max_height - screen_y;
+
+ /* local_height is number of lines in video memory. */
+ local_height = height;
+
+ /* memory involved here liable to be suddenly removed due to fs switch */
+ try
+ {
+ /* Get pointer to video memory. */
+ bpl = get_bytes_per_line();
+ plane1_ptr = GET_OFFSET(Plane1Offset);
+ plane2_ptr = GET_OFFSET(Plane2Offset);
+ plane3_ptr = GET_OFFSET(Plane3Offset);
+ plane4_ptr = GET_OFFSET(Plane4Offset);
+
+ /* Get pointer to bitmap. */
+ longs_per_scanline = LONGS_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (ULONG *) sc.ConsoleBufInfo.lpBitMap +
+ (screen_y << 1) * longs_per_scanline + (screen_x << 1);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Munge. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ mem_loc = offset;
+ local_width = width;
+
+ do
+ {
+
+ /*
+ * Get data and output to screen buffer. NOTE little endian
+ * dependent code.
+ */
+ data0 = *(plane1_ptr + mem_loc);
+ data1 = *(plane2_ptr + mem_loc);
+ data2 = *(plane3_ptr + mem_loc);
+ data3 = *(plane4_ptr + mem_loc);
+
+ *(dest_ptr + longs_per_scanline) = *dest_ptr =
+ (data1 << 24) | (data1 << 16) | (data0 << 8) | data0;
+ dest_ptr++;
+ *(dest_ptr + longs_per_scanline) = *dest_ptr =
+ (data3 << 24) | (data3 << 16) | (data2 << 8) | data2;
+ dest_ptr++;
+ mem_loc++;
+ }
+ while (--local_width);
+
+ ref_dest_ptr += 2 * longs_per_scanline;
+ offset += bpl;
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = screen_x << 3;
+ rect.Top = screen_y << 1;
+ rect.Right = rect.Left + (width << 3) - 1;
+ rect.Bottom = rect.Top + (height << 1) - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "Handled fault in nt_vga_med_frozen_std. fs switch?");
+ return;
+ }
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/* Hi-res frozen paint func (256 colour mode PC 320x400. SoftPC 640x400.) */
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+void nt_vga_hi_frozen_std(int offset, int screen_x, int screen_y,
+ int width, int height)
+{
+ UTINY *dest_ptr,
+ *ref_dest_ptr,
+ *plane1_ptr,
+ *plane2_ptr,
+ *plane3_ptr,
+ *plane4_ptr;
+ ULONG local_height,
+ local_width,
+ mem_loc,
+ bytes_per_scanline,
+ bpl,
+ max_width = sc.PC_W_Width >> 3,
+ max_height = sc.PC_W_Height;
+ SMALL_RECT rect;
+
+ sub_note_trace5(EGA_HOST_VERBOSE,
+ "nt_vga_hi_frozen_std off=%d x=%d y=%d width=%d height=%d\n",
+ offset, screen_x, screen_y, width, height);
+
+ /*
+ ** Tim September 92, bounce call if handle to screen buffer is null.
+ ** This can happen when VDM session is about to suspend, buffer has
+ ** been closed, but still get a paint request.
+ */
+ if( sc.ScreenBufHandle == (HANDLE)NULL ){
+ assert0( NO, "VDM: rejected paint request due to NULL handle" );
+ return;
+ }
+
+ /* If the image is completely outside the display area do nothing. */
+ if (((ULONG)screen_x >= max_width) || ((ULONG) screen_y >= max_height))
+ {
+ sub_note_trace2(EGA_HOST_VERBOSE,
+ "VDM: nt_vga_hi_frozen_std() x=%d y=%d",
+ screen_x, screen_y);
+ return;
+ }
+
+ /*
+ * If image partially overlaps display area clip it so we don't start
+ * overwriting invalid pieces of memory.
+ */
+ if (screen_x + width > (int)max_width)
+ width = max_width - screen_x;
+ if ((ULONG) (screen_y + height) > max_height)
+ height = max_height - screen_y;
+
+ /* memory involved here liable to be suddenly removed due to fs switch */
+ try
+ {
+ /* local_height is number of lines in video memory. */
+ local_height = height;
+
+ /* Get pointer to bitmap. */
+ bpl = get_bytes_per_line();
+ bytes_per_scanline = BYTES_PER_SCANLINE(sc.ConsoleBufInfo.lpBitMapInfo);
+ ref_dest_ptr = (UTINY *) sc.ConsoleBufInfo.lpBitMap +
+ screen_y * bytes_per_scanline + (screen_x << 3);
+
+ /* Set up the plane pointers. */
+ plane1_ptr = GET_OFFSET(Plane1Offset);
+ plane2_ptr = GET_OFFSET(Plane2Offset);
+ plane3_ptr = GET_OFFSET(Plane3Offset);
+ plane4_ptr = GET_OFFSET(Plane4Offset);
+
+ /* Grab the mutex. */
+ GrabMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Build up the bitmap. */
+ do
+ {
+ dest_ptr = ref_dest_ptr;
+ mem_loc = offset;
+ local_width = width;
+
+ do
+ {
+ *(dest_ptr + 1) = *dest_ptr = *(plane1_ptr + mem_loc);
+ dest_ptr += 2;
+ *(dest_ptr + 1) = *dest_ptr = *(plane2_ptr + mem_loc);
+ dest_ptr += 2;
+ *(dest_ptr + 1) = *dest_ptr = *(plane3_ptr + mem_loc);
+ dest_ptr += 2;
+ *(dest_ptr + 1) = *dest_ptr = *(plane4_ptr + mem_loc);
+ dest_ptr += 2;
+ mem_loc++;
+ }
+ while (--local_width);
+ ref_dest_ptr += bytes_per_scanline;
+ offset += bpl;
+ }
+ while(--local_height);
+
+ /* Release the mutex. */
+ RelMutex(sc.ConsoleBufInfo.hMutex);
+
+ /* Display the new image. */
+ rect.Left = (screen_x << 3);
+ rect.Top = screen_y;
+ rect.Right = rect.Left + (width << 3) - 1;
+ rect.Bottom = rect.Top + height - 1;
+
+ if( sc.ScreenBufHandle )
+ if (!InvalidateConsoleDIBits(sc.ScreenBufHandle, &rect))
+ assert1( NO, "VDM: InvalidateConsoleDIBits() error:%#x",
+ GetLastError() );
+ } except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ assert0(NO, "Handled fault in nt_vga_hi_frozen_std. fs switch?");
+ return;
+ }
+}
+#endif /* MONITOR */
diff --git a/private/mvdm/softpc.new/host/src/nt_wcom.c b/private/mvdm/softpc.new/host/src/nt_wcom.c
new file mode 100644
index 000000000..05d476cf1
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_wcom.c
@@ -0,0 +1,438 @@
+#include <windows.h>
+#include <conapi.h>
+#include "ptypes32.h"
+#include "insignia.h"
+#include "host_def.h"
+
+/*
+ * Author : D.A.Bartlett
+ * Purpose:
+ *
+ *
+ * Handle UART I/O's under windows
+ *
+ *
+ *
+ */
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Include files */
+
+#include "xt.h"
+#include "rs232.h"
+#include "error.h"
+#include "config.h"
+#include "host_com.h"
+#include "host_trc.h"
+#include "host_rrr.h"
+#include "debug.h"
+#include "idetect.h"
+#include "nt_com.h"
+#include "nt_graph.h"
+#include "nt_uis.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::: Global Data */
+GCHfn GetCommHandle;
+GCSfn GetCommShadowMSR;
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::: Internal function protocols */
+
+#ifndef PROD
+void DisplayPortAccessError(int PortOffset, BOOL ReadAccess, BOOL PortOpen);
+#endif
+
+BOOL SetupBaudRate(HANDLE FileHandle, DIVISOR_LATCH divisor_latch);
+BOOL SetupLCRData(HANDLE FileHandle, LINE_CONTROL_REG LCR_reg);
+BOOL SyncLineSettings(HANDLE FileHandle, DCB *pdcb,
+ DIVISOR_LATCH *divisor_latch,
+ LINE_CONTROL_REG *LCR_reg);
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: IMPORTS */
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: UART state */
+
+static struct ADAPTER_STATE
+{
+ DIVISOR_LATCH divisor_latch;
+ INT_ENABLE_REG int_enable_reg;
+ INT_ID_REG int_id_reg;
+ LINE_CONTROL_REG line_control_reg;
+ MODEM_CONTROL_REG modem_control_reg;
+ LINE_STATUS_REG line_status_reg;
+ MODEM_STATUS_REG modem_status_reg;
+ half_word scratch; /* scratch register */
+
+} adapter_state[NUM_SERIAL_PORTS];
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: WOW inb function */
+
+void wow_com_inb(io_addr port, half_word *value)
+{
+ int adapter = adapter_for_port(port);
+ struct ADAPTER_STATE *asp = &adapter_state[adapter];
+ BOOL Invalid_port_access = FALSE;
+ HANDLE FileH;
+
+
+ /*........................................... Communications port open ? */
+
+ if (GetCommHandle == NULL) {
+ com_inb(port,value);
+ return;
+ }
+
+ FileH = (HANDLE)(*GetCommHandle)((WORD)adapter);
+#ifndef PROD
+ if( FileH== NULL)
+ DisplayPortAccessError(port & 0x7, TRUE, FALSE);
+#endif
+
+ /*.................................................... Process port read */
+
+ switch(port & 0x7)
+ {
+ //Process read to RX register
+ case RS232_TX_RX:
+
+ if(asp->line_control_reg.bits.DLAB == 0)
+ Invalid_port_access = TRUE;
+ else
+ {
+ if(SyncLineSettings(FileH,NULL,&asp->divisor_latch,&asp->line_control_reg))
+ *value = (half_word) asp->divisor_latch.byte.LSByte;
+ else
+ Invalid_port_access = TRUE;
+ }
+ break;
+
+
+ //Process IER read
+ case RS232_IER:
+
+ if(asp->line_control_reg.bits.DLAB == 0)
+ Invalid_port_access = TRUE;
+ else
+ {
+ if(SyncLineSettings(FileH,NULL,&asp->divisor_latch,&asp->line_control_reg))
+ *value = (half_word) asp->divisor_latch.byte.MSByte;
+ else
+ Invalid_port_access = TRUE;
+ }
+ break;
+
+
+ //Process IIR, LSR and MCR reads
+ case RS232_IIR:
+ case RS232_LSR:
+ case RS232_MCR:
+
+ Invalid_port_access = TRUE;
+ break;
+
+ case RS232_LCR:
+
+ if(SyncLineSettings(FileH,NULL,&asp->divisor_latch,&asp->line_control_reg))
+ *value = asp->line_control_reg.all;
+ else
+ Invalid_port_access = TRUE;
+
+ break;
+
+ //Process MSR read
+ case RS232_MSR:
+
+ *value = (half_word) (*GetCommShadowMSR)((WORD)adapter);
+ break;
+
+ // Process access to Scratch register
+ case RS232_SCRATCH:
+ *value = asp->scratch;
+ break;
+ }
+
+ /*.......................................... Handle invalid port accesses */
+
+#ifndef PROD
+ if(Invalid_port_access)
+ DisplayPortAccessError(port & 0x7, TRUE, TRUE);
+#endif
+
+
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::: WOW outb function */
+
+void wow_com_outb(io_addr port, half_word value)
+{
+ int adapter = adapter_for_port(port);
+ struct ADAPTER_STATE *asp = &adapter_state[adapter];
+ BOOL Invalid_port_access = FALSE;
+ LINE_CONTROL_REG newLCR;
+ HANDLE FileH;
+
+ /*........................................... Communications port open ? */
+
+ if (GetCommHandle == NULL) {
+ com_outb(port,value);
+ return;
+ }
+
+ FileH = (HANDLE)(*GetCommHandle)((WORD)adapter);
+#ifndef PROD
+ if(FileH == NULL)
+ DisplayPortAccessError(port & 0x7, FALSE, FALSE);
+#endif
+
+ /*.................................................... Process port write */
+
+ switch(port & 0x7)
+ {
+ //Process write to TX register
+ case RS232_TX_RX:
+
+ if(asp->line_control_reg.bits.DLAB == 0)
+ Invalid_port_access = TRUE;
+ else
+ asp->divisor_latch.byte.LSByte= value;
+
+ break;
+
+ //Process write to IER register
+ case RS232_IER:
+
+ if(asp->line_control_reg.bits.DLAB == 0)
+ Invalid_port_access = TRUE;
+ else
+ asp->divisor_latch.byte.MSByte = value;
+
+ break;
+
+ //Proces write to IIR, MCR, LSR amd MSR
+
+ case RS232_IIR:
+ case RS232_MCR:
+ case RS232_LSR:
+ case RS232_MSR:
+
+ Invalid_port_access = TRUE;
+ break;
+
+ case RS232_LCR:
+
+ newLCR.all = value;
+ if(asp->line_control_reg.bits.DLAB == 1 && newLCR.bits.DLAB == 0)
+ {
+ if(!SetupBaudRate(FileH,asp->divisor_latch))
+ Invalid_port_access = TRUE;
+ }
+
+ if(!Invalid_port_access && !SetupLCRData(FileH,newLCR))
+ Invalid_port_access = TRUE;
+
+ asp->line_control_reg.all = newLCR.all;
+ break;
+
+ //Scratch register write
+
+ case RS232_SCRATCH:
+ asp->scratch = value;
+ break;
+ }
+
+ /*.......................................... Handle invalid port accesses */
+
+#ifndef PROD
+ if(Invalid_port_access)
+ DisplayPortAccessError(port & 0x7, FALSE, TRUE);
+#endif
+
+}
+
+
+/*:::::::::::::::: Synchronise Baud/Parity/Stop bits/Data bits with real UART */
+
+BOOL SyncLineSettings(HANDLE FileHandle,
+ DCB *pdcb,
+ DIVISOR_LATCH *divisor_latch,
+ LINE_CONTROL_REG *LCR_reg )
+{
+ DCB dcb; //State of real UART
+ register DCB *dcb_ptr;
+
+
+ //Get current state of the real UART
+
+ if(pdcb == NULL && !GetCommState(FileHandle, &dcb))
+ {
+ always_trace0("ntvdm : GetCommState failed on open\n");
+ return(FALSE);
+ }
+
+ dcb_ptr = pdcb ? pdcb : &dcb;
+
+ // Convert BAUD rate to divisor latch setting
+ divisor_latch->all = (unsigned short)(115200/dcb_ptr->BaudRate);
+
+ //Setup parity value
+ LCR_reg->bits.parity_enabled = PARITYENABLE_ON; //Default parity on
+
+ switch(dcb_ptr->Parity)
+ {
+ case EVENPARITY :
+ LCR_reg->bits.even_parity = EVENPARITY_EVEN;
+ break;
+
+ case NOPARITY :
+ LCR_reg->bits.parity_enabled = PARITYENABLE_OFF;
+ break;
+
+ case ODDPARITY :
+ LCR_reg->bits.even_parity = EVENPARITY_ODD;
+ break;
+
+ case SPACEPARITY:
+ LCR_reg->bits.stick_parity = PARITY_STICK;
+ LCR_reg->bits.even_parity = EVENPARITY_EVEN;
+ break;
+
+ case MARKPARITY :
+ LCR_reg->bits.stick_parity = PARITY_STICK;
+ LCR_reg->bits.even_parity = EVENPARITY_ODD;
+ break;
+ }
+
+ //Setup stop bits
+ LCR_reg->bits.no_of_stop_bits = dcb_ptr->StopBits == ONESTOPBIT ? 0 : 1;
+
+ //Setup data byte size
+ LCR_reg->bits.word_length = dcb_ptr->ByteSize-5;
+
+ return(TRUE);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::: Setup Line control data */
+
+BOOL SetupLCRData(HANDLE FileHandle, LINE_CONTROL_REG LCR_reg)
+{
+ DCB dcb; //State of real UART
+
+ //Get current state of the real UART
+
+ if(!GetCommState(FileHandle, &dcb))
+ {
+ always_trace0("ntvdm : GetCommState failed on open\n");
+ return(FALSE);
+ }
+
+ //Setup data bits
+ dcb.ByteSize = LCR_reg.bits.word_length+5;
+
+ //Setup stop bits
+ if(LCR_reg.bits.no_of_stop_bits == 0)
+ dcb.StopBits = LCR_reg.bits.word_length == 0 ? ONE5STOPBITS:TWOSTOPBITS;
+ else
+ dcb.StopBits = ONESTOPBIT;
+
+ //Setup parity
+ if(LCR_reg.bits.parity_enabled == PARITYENABLE_ON)
+ {
+ if(LCR_reg.bits.stick_parity == PARITY_STICK)
+ {
+ dcb.Parity = LCR_reg.bits.even_parity == EVENPARITY_ODD ?
+ MARKPARITY : SPACEPARITY;
+
+ }
+ else
+ {
+ dcb.Parity = LCR_reg.bits.even_parity == EVENPARITY_ODD ?
+ ODDPARITY :EVENPARITY;
+ }
+ }
+ else
+ dcb.Parity = NOPARITY;
+
+ //Sent the new line setting values to the serial driver
+ if(!SetCommState(FileHandle, &dcb))
+ {
+ always_trace0("ntvdm : GetCommState failed on open\n");
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::: Set up the baud rate */
+
+BOOL SetupBaudRate(HANDLE FileHandle, DIVISOR_LATCH divisor_latch)
+{
+ DCB dcb;
+
+ //Setup the baud rate
+
+ if(!GetCommState(FileHandle, &dcb))
+ {
+ always_trace0("ntvdm : GetCommState failed on open\n");
+ return(FALSE);
+ }
+
+ dcb.BaudRate = divisor_latch.all ? 115200/divisor_latch.all : 115200;
+
+ if(!SetCommState(FileHandle, &dcb))
+ {
+ always_trace0("ntvdm : GetCommState failed on open\n");
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::: Display port access error */
+
+
+#ifndef PROD
+/*
+ * user warnings are not needed here, return errors and let the
+ * app handle it. message boxes are also not permitted, because
+ * it can kill WOW. 20-Feb-1993 Jonle
+ */
+void DisplayPortAccessError(int PortOffset, BOOL ReadAccess, BOOL PortOpen)
+{
+ static char *PortInError;
+ static char ErrorMessage[250];
+ int rtn;
+
+ // Identify port in error
+
+ switch(PortOffset)
+ {
+ case RS232_TX_RX: PortInError = ReadAccess ? "RX" : "TX" ; break;
+ case RS232_IER: PortInError = "IER" ; break;
+ case RS232_IIR: PortInError = "IIR" ; break;
+ case RS232_MCR: PortInError = "MCR" ; break;
+ case RS232_LSR: PortInError = "LSR" ; break;
+ case RS232_MSR: PortInError = "MSR" ; break;
+ case RS232_LCR: PortInError = "LCR" ; break;
+ case RS232_SCRATCH: PortInError = "Scratch" ; break;
+ default: PortInError = "Unidentified"; break;
+ }
+
+ //Construct Error message
+
+ sprintf(ErrorMessage, "The Application attempted to %s the %s register",
+ ReadAccess ? "read" : "write", PortInError);
+
+ if(!PortOpen)
+ strcat(ErrorMessage,", however the comm port has not yet been opened");
+
+ //Display message box
+ printf("WOW Communication Port Access Error\n%s\n",ErrorMessage);
+}
+#endif
diff --git a/private/mvdm/softpc.new/host/src/nt_yoda.c b/private/mvdm/softpc.new/host/src/nt_yoda.c
new file mode 100644
index 000000000..7689056fb
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/nt_yoda.c
@@ -0,0 +1,1200 @@
+#include "insignia.h"
+#include "host_def.h"
+
+
+
+/* INSIGNIA MODULE SPECIFICATION
+ -----------------------------
+
+MODULE NAME : nt_yoda
+FILE NAME : nt_yoda.c
+
+ THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
+ CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MUST
+ NOT BE DISCLOSED TO ANY OTHER PARTIES WITHOUT EXPRESS
+ AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS LTD.
+
+
+DESIGNER : Wayne Plummer
+DATE : 21st July 1989
+
+PURPOSE : Provides host specific extensions to YODA
+
+
+The Following External Routines are defined:
+ 1. host_force_yoda_extensions
+ 2. host_yoda_check_I_extensions
+ 3. host_yoda_help_extensions
+
+
+=========================================================================
+
+AMMENDMENTS :
+
+ Version Date Author Reason
+
+=========================================================================
+*/
+
+#ifdef YODA
+
+/******INCLUDES**********/
+#include <stdio.h>
+#include "xt.h"
+#include CpuH
+#include "hunter.h"
+#include "nt_getXX.h"
+
+/******DEFINES***********/
+#define EXPORT
+
+/* Get the size of a table. */
+#define sizeoftable(tab) (sizeof(tab)/sizeof(tab[0]))
+
+/* Different types of CALL instruction. */
+#define CT_IMM 0
+#define CT_EA 1
+#define CT_REG 2
+
+/* Mod-rm table flags. */
+#define MR_BX 0x01
+#define MR_BP 0x02
+#define MR_SI 0x04
+#define MR_DI 0x08
+#define MR_D8 0x10
+#define MR_D16 0x20
+
+/* Segment defines, correspond to entries in get_seg table. */
+#define NO_OVERRIDE (-1)
+#define SEG_ES (0)
+#define SEG_CS (1)
+#define SEG_SS (2)
+#define SEG_DS (3)
+
+/* Maximum size of the call stack. */
+#define MAX_CALL_STACK 128
+
+/******TYPEDEFS**********/
+
+/* Effective address call type additional data. */
+typedef struct
+{
+ word seg; /* The segment of the effective address. */
+ word off; /* The offset of the effective address. */
+ sys_addr addr; /* 20-bit effective address. */
+ IS8 seg_override; /* Segment override if any. */
+ IBOOL disp_present; /* Is there a displacement present? */
+ word disp; /* The value of the displacement.*/
+ IU8 modrm_index; /* Index into mod-rm look-up tables. */
+} CALL_EA_DATA;
+
+/* Register call type additional data. */
+typedef IU8 CALL_REG_DATA; /* Index into register look-up tables. */
+
+/* Data structure which holds call stack entries. */
+typedef struct
+{
+ IU8 type; /* CALL instruction type one of
+ CT_IMM - immediate
+ CT_EA - effective address in mod-rm
+ CT_REG - register in mod-rm. */
+ word cs; /* Code segment of call instruction. */
+ word ip; /* Instruction pointer of call instruction. */
+ sys_addr inst_addr; /* 20-bit address of call instruction. */
+ IU8 nbytes; /* Length of op-code. */
+ IU8 opcode[5]; /* Op-code bytes. */
+ IBOOL cfar; /* Is it a far CALL? */
+ word seg; /* Target segment for CALL. */
+ word off; /* Target offset for CALL. */
+ word ss; /* Stack segment when call is executed. */
+ word sp; /* Stack offset when call is executed. */
+ union
+ {
+ CALL_EA_DATA ea; /* EA call specific data. */
+ CALL_REG_DATA regind; /* Register call specific data. */
+ } extra;
+} CALL_STACK_ENTRY;
+
+/******IMPORTS***********/
+extern struct HOST_COM host_com[];
+extern struct HOST_LPT host_lpt[];
+extern char *nt_fgets(char *buffer, int len, void *input_stream);
+extern char *nt_gets(char *buffer);
+extern int vader;
+
+/******LOCAL FUNCTIONS********/
+LOCAL int do_ecbt IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len);
+LOCAL int do_dcbt IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len);
+LOCAL int do_pcbt IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len);
+LOCAL void check_stack IPT2(word, ss, word, sp);
+LOCAL int check_for_overflow IPT0();
+LOCAL void get_ea_from_modrm IPT4(CALL_STACK_ENTRY *, cs_ptr,
+ IU8, mod,
+ IU8, rm,
+ sys_addr, op_addr);
+LOCAL IS8 do_prefixes IPT1(sys_addr *, opcode_ptr);
+LOCAL int do_ntsd IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len);
+
+/******LOCAL VARS********/
+
+/* Table of host yoda commands. */
+LOCAL struct
+{
+ char *name;
+ int (*function) IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len);
+ char *comment;
+} host_yoda_command[] =
+{
+{ "ecbt", do_ecbt, " - enable call-back-tracing" },
+{ "dcbt", do_dcbt, " - disable call-back-tracing" },
+{ "pcbt", do_pcbt, " - print call-back-trace" },
+{ "ntsd", do_ntsd, " - break to ntsd" }
+};
+
+/* Variable to enable call-back-tracing. */
+LOCAL IBOOL call_back_tracing_enabled = FALSE;
+
+/* Mod-rm byte effective address look-up table. */
+LOCAL IU8 EA_table[] =
+{
+ MR_BX | MR_SI,
+ MR_BX | MR_DI,
+ MR_BP | MR_SI,
+ MR_BP | MR_DI,
+ MR_SI,
+ MR_DI,
+ MR_D16,
+ MR_BX,
+ MR_BX | MR_SI | MR_D8,
+ MR_BX | MR_DI | MR_D8,
+ MR_BP | MR_SI | MR_D8,
+ MR_BP | MR_DI | MR_D8,
+ MR_SI | MR_D8,
+ MR_DI | MR_D8,
+ MR_BP | MR_D8,
+ MR_BX | MR_D8,
+ MR_BX | MR_SI | MR_D16,
+ MR_BX | MR_DI | MR_D16,
+ MR_BP | MR_SI | MR_D16,
+ MR_BP | MR_DI | MR_D16,
+ MR_SI | MR_D16,
+ MR_DI | MR_D16,
+ MR_BP | MR_D16,
+ MR_BX | MR_D16
+};
+
+/* Mod-rm byte string look-up table. */
+LOCAL CHAR *EA_strings[] =
+{
+ "[BX + SI]",
+ "[BX + DI]",
+ "[BP + SI]",
+ "[BP + DI]",
+ "[SI]",
+ "[DI]",
+ "[%hX]",
+ "[BX]",
+ "[BX + SI + %hX]",
+ "[BX + DI + %hX]",
+ "[BP + SI + %hX]",
+ "[BP + DI + %hX]",
+ "[SI + %hX]",
+ "[DI + %hX]",
+ "[BP + %hX]",
+ "[BX + %hX]",
+ "[BX + SI + %hX]",
+ "[BX + DI + %hX]",
+ "[BP + SI + %hX]",
+ "[BP + DI + %hX]",
+ "[SI + %hX]",
+ "[DI + %hX]",
+ "[BP + %hX]",
+ "[BX + %hX]"
+};
+
+/* Table of functions corresponding to register rm fields. */
+LOCAL word (*EA_reg_func[])() =
+{
+ getAX,
+ getCX,
+ getDX,
+ getBX,
+ getSP,
+ getBP,
+ getSI,
+ getDI
+};
+
+/* Table of names of register rm fields. */
+LOCAL CHAR *EA_reg_strings[] =
+{
+ "AX",
+ "CX",
+ "DX",
+ "BX",
+ "SP",
+ "BP",
+ "SI",
+ "DI"
+};
+
+/* Table of functions for getting segment values. */
+LOCAL word (*get_seg[])() =
+{
+ getES,
+ getCS,
+ getSS,
+ getDS
+};
+
+/* Table of segment names. */
+LOCAL CHAR *seg_strings[] =
+{
+ "ES",
+ "CS",
+ "SS",
+ "DS"
+};
+
+LOCAL CALL_STACK_ENTRY call_stack[MAX_CALL_STACK];
+LOCAL CALL_STACK_ENTRY *call_next_free = call_stack;
+
+/******EXPORT VARS*******/
+
+#ifndef PROD
+#ifdef HUNTER
+/*============================================================
+
+Function : trap_command.
+
+Purpose : Writes the current trapper prompt and gets the
+ menu input.
+
+input : a pointer to a string for the current trapper prompt
+ : a pointer to a character to hold the user input.
+
+returns : nothing.
+
+=============================================================*/
+
+void trap_command(char *str,char *ch)
+{
+char inp[80];
+
+printf("%s> ",str);
+nt_fgets(inp,80,stdin);
+sscanf(inp,"%c",ch);
+}
+#endif /* HUNTER */
+
+/*
+=========================================================================
+
+FUNCTION : host_force_yoda_extensions
+
+PURPOSE : this function is called whenever the main code of
+ YODA in the base fails to recognise an instruction
+ in order for host-specific commands to be implemented.
+
+RETURNED STATUS :
+
+NOTES : on the SG port no extensions are provided.
+
+=======================================================================
+*/
+
+GLOBAL int host_force_yoda_extensions(char *com, long cs, long ip, long len,
+ char *str)
+{
+#ifdef HUNTER
+int quit_menus=FALSE; /* some functions need to return to yoda prompt*/
+char c;
+char menu[] = "\tTrapper [m]ain menu\n"
+ "\tTrapper [e]rror menu\n"
+ "\t[Q]uit\n"
+ "\t? for this menu\n\n";
+#endif /* HUNTER */
+ int i,
+ retvalue;
+
+#ifdef HUNTER
+/* to get to this menu, the user has to type "trap" at the Yoda prompt */
+
+if(!strcmp(com,"trap")) /* test the input string */
+ {
+ printf("\nYODA EXTENSIONS\n\n");
+ printf("%s",menu);
+ do
+ {
+ trap_command("trapper",&c);
+ switch(c)
+ {
+ case 'm':
+ case 'M':
+ quit_menus = host_do_trapper_main_menu();
+ break;
+
+ case 'e':
+ case 'E':
+ quit_menus = host_do_trapper_error_menu();
+ break;
+
+ case '?':
+ printf("%s",menu);
+ break;
+
+ default:
+ break;
+ }
+ }
+ while(c != 'q' && c != 'Q' && quit_menus == FALSE );
+
+ }
+else
+ {
+ /* unpleasing input, so return 1 and back to main Yoda stuff */
+ return(1);
+ }
+return(0);
+#endif /* HUNTER */
+
+ /* Check to see if we have got a command in host_yoda_command. */
+ retvalue = 1;
+ for (i = 0; i < sizeoftable(host_yoda_command); i++)
+ {
+ if (strcmp(com, host_yoda_command[i].name) == 0)
+ {
+ retvalue = (*host_yoda_command[i].function)(str, com, cs, ip, len);
+ break;
+ }
+ }
+ return(retvalue);
+}
+
+#ifdef HUNTER
+/*============================================================
+
+Function : host_do_trapper_main_menu
+
+Purpose : implements the main trapper menu under Yoda.
+
+
+=============================================================*/
+
+static int host_do_trapper_main_menu()
+{
+int i,quit_menus = FALSE;
+char c,str[80],yesno;
+USHORT screen_no;
+BOOL compare;
+
+char menu[] = "\t[F]ast forward...\n"
+ "\t[N]ext screen\n"
+ "\t[P]rev screen\n"
+ "\t[S]how screen...\n"
+ "\t[C]ontinue\n"
+ "\t[A]bort\n"
+ "\t[Q]uit\n"
+ "\t? for this menu\n\n";
+
+
+
+char continu[] = "\n\ntype 'c' at yoda prompt to continue...\n\n";
+
+
+printf("\nTRAPPER MAIN MENU\n\n");
+printf("%s",menu);
+
+do
+ {
+ trap_command("main",&c);
+ switch(c)
+ {
+ case 'f': /* fast forward */
+ case 'F':
+ {
+ printf("\n\nEnter the screen number where comparisons will start: ");
+ nt_fgets(str,80,stdin);
+ sscanf(str,"%d",&screen_no);
+ printf("\n\nSkipping screen comparisons up to screen %d\n\n",screen_no);
+ bh_start_screen(screen_no);
+ }
+ break;
+
+ case 'n': /* next screen */
+ case 'N':
+ {
+ bh_next_screen();
+ printf("%s",continu);
+ quit_menus = TRUE;
+ }
+ break;
+
+ case 'p': /* previous screen */
+ case 'P':
+ {
+ bh_prev_screen();
+ printf("%s",continu);
+ quit_menus = TRUE;
+ }
+ break;
+
+ case 's': /* show screen */
+ case 'S':
+ {
+ printf("\n\nEnter the number of the screen which you want to see: ");
+ nt_fgets(str,80,stdin);
+ sscanf(str,"%d",&screen_no);
+ printf("\n\nDo you want to compare screen %d with one from"
+ "SoftPC? (y/n): ",screen_no);
+ nt_fgets(str,80,stdin);
+ sscanf(str,"%c",&yesno);
+ if(yesno == 'y' || yesno == 'Y')
+ compare = TRUE;
+ else
+ compare = FALSE;
+
+ bh_show_screen(screen_no,compare);
+ }
+ break;
+
+ case 'c': /* continue */
+ case 'C':
+ {
+ bh_continue();
+ printf("%s",continu);
+ quit_menus = TRUE;
+ }
+ break;
+
+ case 'a': /* abort */
+ case 'A':
+ bh_abort();
+ break;
+
+ case '?':
+ printf("%s",menu);
+ break;
+
+ default:
+ break;
+ }
+ }
+while(c != 'q' && c != 'Q' && quit_menus == FALSE);
+return(quit_menus); /* match found */
+}
+
+/*============================================================
+
+Function : host_do_trapper_error_menu
+
+Purpose : implements the trapper error menu under Yoda.
+
+returns : TRUE if the user has selected a trapper function
+ which requires softpc to be restarted.
+ FALSE otherwise.
+
+=============================================================*/
+
+static int host_do_trapper_error_menu()
+{
+int i,quit_menus=FALSE;
+char c;
+char menu[] = "\t[F]lip screen\n"
+ "\t[N]ext error\n"
+ "\t[P]rev error\n"
+ "\t[A]ll errors\n"
+ "\t[C]lear errors\n"
+ "\t[Q]uit menu\n"
+ "\t? for this menu\n\n";
+
+
+printf("\nTRAPPER ERROR MENU\n\n");
+printf("%s",menu);
+
+do
+ {
+ trap_command("error",&c);
+ switch(c)
+ {
+ case 'f':
+ case 'F':
+ bh_flip_screen();
+ printf("\n\ntype 'c' at yoda prompt to continue...\n\n");
+ quit_menus = TRUE;
+ break;
+
+ case 'n':
+ case 'N':
+ bh_next_error();
+ break;
+
+ case 'p':
+ case 'P':
+ bh_prev_error();
+ break;
+
+ case 'a':
+ case 'A':
+ bh_all_errors();
+ break;
+
+ case 'c':
+ case 'C':
+ bh_wipe_errors();
+ break;
+
+ case '?':
+ printf("%s",menu);
+ break;
+
+ default:
+ break;
+ }
+ }
+while(c != 'q' && c != 'Q' && quit_menus == FALSE);
+
+if(quit_menus == TRUE)
+ return(TRUE); /* need to go to the yoda prompt */
+else
+ return(FALSE); /* don't need to go to the yoda prompt */
+}
+#endif /* HUNTER */
+
+/*
+=========================================================================
+
+FUNCTION : host_yoda_check_I_extensions
+
+PURPOSE : this function is called by the YODA check_I code
+ in order to provide host specific extensions.
+
+RETURNED STATUS :
+
+NOTES : on the SG port no extensions are provided.
+
+=======================================================================
+*/
+
+GLOBAL void host_yoda_check_I_extensions()
+{
+ sys_addr addr;
+ word cs,
+ ip,
+ ss,
+ sp;
+ IS8 seg_override;
+ IU8 opcode,
+ modrm,
+ mod,
+ n_field,
+ rm,
+ i;
+
+ /* Check to see if call-back-tracing is enabled. */
+ if (call_back_tracing_enabled)
+ {
+
+ /* Check to see if call on top of stack has been popped. */
+ ss = getSS();
+ sp = getSP();
+ check_stack(ss, sp);
+
+ /* Get current op-code. */
+ cs = getCS();
+ ip = getIP();
+ addr = effective_addr(cs, ip);
+ seg_override = do_prefixes(&addr);
+ opcode = sas_hw_at_no_check(addr);
+
+ /* Check to see if we have a call-back-trace op-code. */
+ switch (opcode)
+ {
+ case 0x9a:
+
+ /* 9a = CALLF immediate */
+
+ /* Check there is room for another entry in call_stack. */
+ if (check_for_overflow() == -1)
+ return;
+
+ /* Fill the stack entry. */
+ call_next_free->type = CT_IMM;
+ call_next_free->cs = cs;
+ call_next_free->ip = ip;
+ call_next_free->inst_addr = addr;
+ call_next_free->nbytes = 5;
+ call_next_free->cfar = TRUE;
+ call_next_free->seg = sas_w_at_no_check(addr + 3);
+ call_next_free->off = sas_w_at_no_check(addr + 1);
+
+ /* Save state of stack. */
+ call_next_free->ss = ss;
+ call_next_free->sp = sp;
+
+ /* Store instruction bytes. */
+ for (i = 0; i < 5; i++)
+ call_next_free->opcode[i] = sas_hw_at_no_check(addr++);
+
+ /* Increment top of stack. */
+ call_next_free++;
+ break;
+ case 0xe8:
+
+ /* e8 = CALL immediate */
+
+ /* Check there is room for another entry in call_stack. */
+ if (check_for_overflow() == -1)
+ return;
+
+ /* Fill the stack entry. */
+ call_next_free->type = CT_IMM;
+ call_next_free->cs = cs;
+ call_next_free->ip = ip;
+ call_next_free->inst_addr = addr;
+ call_next_free->nbytes = 3;
+ call_next_free->cfar = FALSE;
+ call_next_free->off = ip + (word) 3 + sas_w_at_no_check(addr + 1);
+
+ /* Save state of stack. */
+ call_next_free->ss = ss;
+ call_next_free->sp = sp;
+
+ /* Store instruction bytes. */
+ for (i = 0; i < 3; i++)
+ call_next_free->opcode[i] = sas_hw_at_no_check(addr++);
+
+ /* Increment top of stack. */
+ call_next_free++;
+ break;
+ case 0xff:
+
+ /*
+ * ff /2 = CALL
+ * ff /3 = CALLF
+ */
+ modrm = sas_hw_at_no_check(addr + 1);
+ n_field = (modrm & 0x38) >> 3;
+ if ((n_field == 2) || (n_field == 3))
+ {
+
+ /* Check there is room for another entry in call_stack. */
+ if (check_for_overflow() == -1)
+ return;
+
+ /* Save CS:IP of call instruction. */
+ call_next_free->cs = cs;
+ call_next_free->ip = ip;
+
+ /* Store opcode address and initialise byte count. */
+ call_next_free->inst_addr = addr;
+ call_next_free->nbytes = 2;
+
+ /* n-field: 2 = near, 3 = far. */
+ call_next_free->cfar = n_field & 1;
+
+ /* If mod is 3 we have a register rm otherwise it is EA. */
+ mod = (modrm & 0xc0) >> 6;
+ rm = modrm & 7;
+ if (mod == 3)
+ {
+ if (call_next_free->cfar)
+ {
+
+ /* Can't have a far pointer in a register. */
+ printf("Invalid mod-rm byte after ff op-code.\n");
+ vader = 1;
+ return;
+ }
+ else
+ {
+
+ /* Near pointer contained in register. */
+ call_next_free->type = CT_REG;
+ call_next_free->off =
+ sas_w_at_no_check((*EA_reg_func[rm])());
+ call_next_free->extra.regind = rm;
+
+ /* Save state of stack. */
+ call_next_free->ss = ss;
+ call_next_free->sp = sp;
+ }
+ }
+ else
+ {
+
+ /* We have an EA type CALL. */
+ call_next_free->type = CT_EA;
+ call_next_free->extra.ea.seg_override = seg_override;
+
+ /* Adjust address and count for segment override. */
+ if (seg_override != NO_OVERRIDE)
+ {
+ call_next_free->inst_addr--;
+ call_next_free->nbytes++;
+ }
+
+ /* Work out EA from mod-rm. */
+ get_ea_from_modrm(call_next_free, mod, rm, addr + 2);
+
+ /* Get target segment and offset from EA. */
+ if (call_next_free->cfar)
+ {
+ call_next_free->seg =
+ sas_w_at_no_check(call_next_free->extra.ea.addr+2);
+
+ /* Save state of stack. */
+ call_next_free->ss = ss;
+ call_next_free->sp = sp;
+ }
+ else
+ {
+
+ /* Save state of stack. */
+ call_next_free->ss = ss;
+ call_next_free->sp = sp;
+ }
+ call_next_free->off =
+ sas_w_at_no_check(call_next_free->extra.ea.addr);
+ }
+
+ /* Fill in the op-code bytes. */
+ for (i = 0, addr = call_next_free->inst_addr;
+ i < call_next_free->nbytes;
+ i++, addr++)
+ {
+ call_next_free->opcode[i] = sas_hw_at_no_check(addr);
+ }
+
+ /* Increment top of stack. */
+ call_next_free++;
+ }
+ break;
+ default:
+
+ /* Not a call-back-trace opcode so do nothing. */
+ break;
+ }
+ }
+}
+
+/*
+=========================================================================
+
+FUNCTION : check_stack
+
+PURPOSE : Checks to see if the call on the top of the stack has
+ been popped and if so removes it from the top of the
+ call stack.
+
+RETURNED STATUS : void
+
+NOTES : Originally the call stack was popped on RET instructions
+ but this did not work when apps did things like POP
+ followed by JMP. It was therefore decided to check whether
+ the stack had shrunk past the point where a call's return
+ address was stored to see if that call had returned.
+
+=======================================================================
+*/
+LOCAL void check_stack IFN2(word, ss, word, sp)
+{
+ IU32 count = 0;
+
+ /*
+ * Pop the call stack until we have a call whose return address is still
+ * on the real stack.
+ */
+ while ((call_next_free > call_stack) &&
+ (ss == (call_next_free - 1)->ss) &&
+ (sp >= (call_next_free - 1)->sp))
+ {
+ call_next_free--;
+ count++;
+ }
+
+ /* Complain if more than one call gets popped. */
+ if (count > 1)
+ printf("Call stack warning - %d calls popped at %04x:%04x\n",
+ count, getCS(), getIP());
+}
+
+/*
+=========================================================================
+
+FUNCTION : do_prefixes
+
+PURPOSE : Skips over all prefix op-codes.
+
+RETURNED STATUS : Segment override if any.
+
+NOTES :
+
+=======================================================================
+*/
+LOCAL IS8 do_prefixes IFN1(sys_addr *, opcode_ptr)
+{
+ half_word opcode;
+ IS8 seg_override = NO_OVERRIDE;
+
+ /* Skip over prefix opcodes. */
+ opcode = sas_hw_at_no_check(*opcode_ptr);
+ while ((opcode == 0xf2) || (opcode == 0xf3) ||
+ (opcode == 0x26) || (opcode == 0x2e) ||
+ (opcode == 0x36) || (opcode == 0x3e))
+ {
+ switch (opcode)
+ {
+ case 0x26:
+ seg_override = SEG_ES;
+ break;
+ case 0x2e:
+ seg_override = SEG_CS;
+ break;
+ case 0x36:
+ seg_override = SEG_SS;
+ break;
+ case 0x3e:
+ seg_override = SEG_DS;
+ break;
+ default:
+
+ /* Not sure what f2 and f3 do so do this for the time being. */
+ seg_override = NO_OVERRIDE;
+ break;
+ }
+ opcode = sas_hw_at_no_check(++(*opcode_ptr));
+ }
+
+ /* (*opcode_ptr) now points at the opcode. */
+ return(seg_override);
+}
+
+/*
+=========================================================================
+
+FUNCTION : check_for_overflow
+
+PURPOSE : Checks to see if the stack has overflowed.
+
+RETURNED STATUS : -1 on failure, 0 on success.
+
+NOTES :
+
+=======================================================================
+*/
+LOCAL int check_for_overflow IFN0()
+{
+ if (call_next_free - call_stack >= MAX_CALL_STACK)
+ {
+ printf("Call stack overflow.\n");
+ vader = 1;
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+=========================================================================
+
+FUNCTION : get_ea_from_modrm
+
+PURPOSE : Takes a mod-rm byte and works out the effective
+ address and the target segment and offset.
+
+RETURNED STATUS : void
+
+NOTES :
+
+=======================================================================
+*/
+LOCAL void get_ea_from_modrm IFN4(CALL_STACK_ENTRY *, cs_ptr,
+ IU8, mod,
+ IU8, rm,
+ sys_addr, disp_addr)
+{
+ IS16 offset = 0,
+ disp;
+ IS8 seg,
+ seg_override = cs_ptr->extra.ea.seg_override;
+ IU8 flags;
+
+ /* Get index to table from mod-rm byte. */
+ cs_ptr->extra.ea.modrm_index = (mod << 3) | rm;
+ flags = EA_table[cs_ptr->extra.ea.modrm_index];
+
+ /* Use segment override if there is one otherwise default to DS. */
+ seg = (seg_override == NO_OVERRIDE) ? SEG_DS : seg_override;
+
+ /* Add base register value if any. */
+ if (flags & MR_BX)
+ offset += getBX();
+ else if (flags & MR_BP)
+ {
+ offset += getBP();
+ if (seg_override == NO_OVERRIDE)
+ seg = SEG_SS;
+ }
+
+ /* Add index register value if any. */
+ if (flags & MR_SI)
+ offset += getSI();
+ else if (flags & MR_DI)
+ offset += getDI();
+
+ /* Add displacement if any. */
+ if (flags & MR_D16)
+ {
+ cs_ptr->nbytes += 2;
+ cs_ptr->extra.ea.disp_present = TRUE;
+ cs_ptr->extra.ea.disp = (IS16) sas_w_at_no_check(disp_addr);
+ offset += cs_ptr->extra.ea.disp;
+ }
+ else if (flags & MR_D8)
+ {
+ cs_ptr->nbytes++;
+ cs_ptr->extra.ea.disp_present = TRUE;
+ cs_ptr->extra.ea.disp = (IS16) ((IS8) sas_hw_at_no_check(disp_addr));
+ offset += cs_ptr->extra.ea.disp;
+ }
+ else
+ cs_ptr->extra.ea.disp_present = FALSE;
+
+ /* Store segment and offset of return address. */
+ cs_ptr->extra.ea.seg = (*get_seg[seg])();
+ cs_ptr->extra.ea.off = (word) offset;
+ cs_ptr->extra.ea.addr = effective_addr(cs_ptr->extra.ea.seg,
+ cs_ptr->extra.ea.off);
+}
+
+/*
+=========================================================================
+
+FUNCTION : host_yoda_help_extensions
+
+PURPOSE : this function is called whenever the user asks for
+ YODA help to describe the host specific extensions provided
+ above.
+
+RETURNED STATUS :
+
+NOTES : on the SG port no extensions are provided.
+
+=======================================================================
+*/
+
+GLOBAL int host_yoda_help_extensions()
+{
+ int i;
+
+ /* Print out the command and comment fields of host_yoda_command. */
+ for(i = 0; i < sizeoftable(host_yoda_command); i++)
+ {
+ if (host_yoda_command[i].comment == NULL)
+ continue;
+ printf("%14s %s\n",
+ host_yoda_command[i].name,
+ host_yoda_command[i].comment);
+ }
+}
+
+/*
+=========================================================================
+
+FUNCTION : do_ecbt
+
+PURPOSE : this function enables call-back-tracing.
+
+RETURNED STATUS : 0 for success, 1 for failure
+
+NOTES :
+
+=======================================================================
+*/
+LOCAL int do_ecbt IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len)
+{
+
+ /* Enable call-back-tracing if it is currently disabled. */
+ if (!call_back_tracing_enabled)
+ {
+ printf("Call back tracing enabled.\n");
+ call_back_tracing_enabled = TRUE;
+ }
+ return(0);
+}
+
+/*
+=========================================================================
+
+FUNCTION : do_dcbt
+
+PURPOSE : this function disables call-back-tracing.
+
+RETURNED STATUS : 0 for success, 1 for failure
+
+NOTES :
+
+=======================================================================
+*/
+LOCAL int do_dcbt IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len)
+{
+
+ /* Disable call-back-tracing if it is currently enabled. */
+ if (call_back_tracing_enabled)
+ {
+
+ /* Disable tracing. */
+ printf("Call back tracing disabled.\n");
+ call_back_tracing_enabled = FALSE;
+
+ /* Reset the stack. */
+ call_next_free = call_stack;
+ }
+ return(0);
+}
+
+/*
+=========================================================================
+
+FUNCTION : do_pcbt
+
+PURPOSE : this function prints the call-back-trace stack.
+
+RETURNED STATUS : 0 for success, 1 for failure
+
+NOTES :
+
+=======================================================================
+*/
+LOCAL int do_pcbt IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len)
+{
+ IU8 *opcode,
+ i;
+ CALL_STACK_ENTRY *cs_ptr;
+
+ /* Print out the current call-back-trace stack. */
+ for (cs_ptr = call_stack; cs_ptr < call_next_free; cs_ptr++)
+ {
+
+ /* Print address and op-code. */
+ printf("%04X:%04X", cs_ptr->cs, cs_ptr->ip);
+ opcode = cs_ptr->opcode;
+ for (i = 0; i < cs_ptr->nbytes; i++)
+ printf(" %02X", *opcode++);
+
+ /* Print mnemonic. */
+ printf("\tCALL");
+ if (cs_ptr->cfar)
+ printf("F");
+ printf("\t");
+
+ /* Print parameters. */
+ switch (cs_ptr->type)
+ {
+ case CT_IMM:
+
+ /* Immediate. */
+ if (cs_ptr->cfar)
+ printf("%04X:", cs_ptr->seg);
+ printf("%04X", cs_ptr->off);
+ break;
+ case CT_EA:
+
+ /* Effective address. */
+ if (cs_ptr->cfar)
+ printf("d");
+ printf("word ptr ");
+
+ /* Print override if there is one. */
+ if (cs_ptr->extra.ea.seg_override != NO_OVERRIDE)
+ printf("%s:", seg_strings[cs_ptr->extra.ea.seg_override]);
+
+ /* Print parameters. */
+ if (cs_ptr->extra.ea.disp_present)
+ printf(EA_strings[cs_ptr->extra.ea.modrm_index],
+ cs_ptr->extra.ea.disp);
+ else
+ printf(EA_strings[cs_ptr->extra.ea.modrm_index]);
+
+ /* Print effective address. */
+ printf("\t(%04X:%04X\t",
+ cs_ptr->extra.ea.seg,
+ cs_ptr->extra.ea.off);
+
+ /* Print contents of effective address. */
+ if (cs_ptr->cfar)
+ printf("%04X:", cs_ptr->seg);
+ printf("%04X)", cs_ptr->off);
+ break;
+ case CT_REG:
+
+ /* Print parameter and target address. */
+ printf(EA_reg_strings[cs_ptr->extra.regind]);
+ printf("\t(%04X)", cs_ptr->off);
+ break;
+ default:
+ break;
+ }
+ printf("\n");
+ }
+
+ /* Return success. */
+ return(0);
+}
+
+GLOBAL CHAR *host_get_287_reg_as_string IFN1(int, reg_no)
+{
+ double reg;
+ SAVED char regstr[30];
+#ifdef CPU_40_STYLE
+ strcpy(regstr, "STUBBED get_287_reg");
+#else
+ IMPORT double get_287_reg_as_double(int);
+
+ reg = get_287_reg_as_double(reg_no);
+ sprintf(regstr, "%g", reg);
+#endif /* CPU_40_STYLE */
+ return(&regstr[0]);
+}
+
+/*
+=========================================================================
+
+FUNCTION : do_ntsd
+
+PURPOSE : this function forces a break back to ntsd
+
+RETURNED STATUS : 0 for success, 1 for failure
+
+NOTES :
+
+=======================================================================
+*/
+LOCAL int do_ntsd IPT5(char *, str, char *, com, long, cs,
+ long, ip, long, len)
+{
+ UNUSED(str);
+ UNUSED(com);
+ UNUSED(cs);
+ UNUSED(ip);
+ UNUSED(len);
+ DebugBreak();
+ return(0);
+}
+
+#endif /* ndef PROD */
+
+#endif /* YODA */
+
+/* This stub exported as called from main() */
+void host_set_yoda_ints()
+{
+}
diff --git a/private/mvdm/softpc.new/host/src/sim32.c b/private/mvdm/softpc.new/host/src/sim32.c
new file mode 100644
index 000000000..5bcfcf37d
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/sim32.c
@@ -0,0 +1,462 @@
+/*
+ * sim32.c - Sim32 for Microsoft NT SoftPC.
+ *
+ * Ade Brownlow
+ * Wed Jun 5 91
+ *
+ * %W% %G% (c) Insignia Solutions 1991
+ *
+ * This module provides the Microsoft sim32 interface with the additional sas
+ * functionality and some host sas routines. We also provide cpu idling facilities.
+ *
+ * This module in effect provides (along with the cpu) what Microsoft term as the IEU -
+ * see documentation.
+ */
+
+#ifdef SIM32
+
+#ifdef CPU_40_STYLE
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif /* CPU_40_STYLE */
+
+#include <windows.h>
+#include "insignia.h"
+#include "host_def.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "xt.h"
+#include "sim32.h"
+#include "sas.h"
+#include "gmi.h"
+#include "ckmalloc.h"
+#include CpuH
+
+
+#ifdef CPU_40_STYLE
+#include "nt_mem.h"
+#endif /* CPU_40_STYLE */
+
+/********************************************************/
+/* IMPORTS & EXPORTS */
+
+/* Sas/gmi Sim32 crossovers */
+GLOBAL BOOL Sim32FlushVDMPointer (double_word, word, UTINY *, BOOL);
+GLOBAL BOOL Sim32FreeVDMPointer (double_word, word, UTINY *, BOOL);
+GLOBAL BOOL Sim32GetVDMMemory (double_word, word, UTINY *, BOOL);
+GLOBAL BOOL Sim32SetVDMMemory (double_word, word, UTINY *, BOOL);
+GLOBAL sys_addr sim32_effective_addr (double_word, BOOL);
+
+GLOBAL UTINY *sas_alter_size(sys_addr);
+GLOBAL UTINY *host_sas_init(sys_addr);
+GLOBAL UTINY *host_sas_term(void);
+
+/* Microsoft sas extensions */
+GLOBAL IMEMBLOCK *sas_mem_map (void);
+GLOBAL void sas_clear_map(void);
+
+IMPORT ULONG Sas_wrap_mask;
+
+
+
+#ifndef MONITOR
+//
+// Pointer to a scratch video buffer. Updated by sim32 routines
+// when intel video addr is requested.
+
+IU8 *ScratchVideoBuffer = 0;
+#define VIDEO_REGEN_START 0xa0000
+#define VIDEO_REGEN_END 0xbffff
+#define VID_BUFF_SIZE 0x20000
+
+
+#define IsVideoMemory(LinAddr) \
+ ((LinAddr) >= VIDEO_REGEN_START && (LinAddr) <= VIDEO_REGEN_END)
+
+
+IU8 *GetVideoMemory(ULONG iaddr)
+{
+
+ //
+ // If there isn't a video scratch buffer, allocate one.
+ // This will stick around until ntvdm terminates. Could be
+ // optimized to free the buffer when not in use.
+ //
+ if (!ScratchVideoBuffer) {
+ ScratchVideoBuffer = malloc(VID_BUFF_SIZE);
+ if (!ScratchVideoBuffer) {
+ return NULL;
+ }
+ }
+
+ //
+ // We could do this more efficiently, by only copying
+ // minimum area needed, but then we need to keep track of
+ // what to update on the flush and do ref counting.
+ // Since video memory access by host code is rare
+ // (only seen in demWrite\demRead so far) be simple minded.
+ //
+ sas_loads (VIDEO_REGEN_START,
+ ScratchVideoBuffer,
+ VID_BUFF_SIZE
+ );
+
+ return ScratchVideoBuffer + (iaddr - VIDEO_REGEN_START);
+}
+
+
+BOOL SetVideoMemory(ULONG iaddr)
+{
+ ULONG VideoOffset = iaddr - VIDEO_REGEN_START;
+
+ if (!ScratchVideoBuffer) {
+ return FALSE;
+ }
+
+ sas_stores(iaddr,
+ ScratchVideoBuffer + VideoOffset,
+ VID_BUFF_SIZE - VideoOffset
+ );
+
+ return TRUE;
+}
+
+#endif
+
+
+
+/********************************************************/
+/* MACROS */
+/* macro to convert the supplied address to intel address */
+#define convert_addr(a,b,c,d) \
+ { \
+ if ((a = sim32_effective_addr (b,c)) == (sys_addr)-1)\
+ {\
+ return (d);\
+ }\
+ }
+
+/********************************************************/
+/* The actual sim32 interfaces, most of these routines can be more or less mapped directly
+ * to existing routines in sas or gmi.
+ *
+ * WARNING: This routine returns a pointer into M, and
+ * WILL NOT work for backward M.
+ */
+UCHAR *Sim32pGetVDMPointer(ULONG addr, UCHAR pm)
+{
+ sys_addr iaddr;
+
+ if (pm && (addr == 0))
+ return(NULL);
+
+ convert_addr (iaddr, addr, pm, NULL);
+//STF - need sas_wrap_mask with PE....iaddr &= Sas_wrap_mask;
+
+ if (IsVideoMemory(iaddr)) {
+ return GetVideoMemory(iaddr);
+ }
+
+ return (NtGetPtrToLinAddrByte(iaddr));
+}
+
+/*
+ * See Sim32pGetVDMPointer
+ *
+ * This call must be maintaned as is because it is exported for VDD's
+ * in product 1.0.
+ */
+UCHAR *ExpSim32GetVDMPointer IFN3(double_word, addr, double_word, size, UCHAR, pm)
+{
+ return Sim32pGetVDMPointer(addr, (UCHAR)pm);
+}
+
+
+GLOBAL BOOL Sim32FlushVDMPointer IFN4(double_word, addr, word, size, UTINY *, buff, BOOL, pm)
+{
+ sys_addr iaddr;
+ convert_addr (iaddr, addr, pm, 0);
+
+//STF - need sas_wrap_mask with PE....iaddr &= Sas_wrap_mask;
+
+#ifndef MONITOR
+ if (IsVideoMemory(iaddr) && !SetVideoMemory(iaddr)) {
+ return FALSE;
+ }
+#endif //MONITOR
+
+
+ sas_overwrite_memory(iaddr, (ULONG)size);
+ return (TRUE);
+}
+
+
+GLOBAL BOOL Sim32FreeVDMPointer IFN4(double_word, addr, word, size, UTINY *, buff, BOOL, pm)
+{
+ /* we haven't allocated any new memory so always return success */
+ return (TRUE);
+}
+
+GLOBAL BOOL Sim32GetVDMMemory IFN4(double_word, addr, word, size, UTINY *, buff, BOOL, pm)
+{
+ sys_addr iaddr;
+ convert_addr (iaddr, addr, pm, FALSE);
+ /* effectivly a sas_loads */
+ sas_loads (iaddr, buff, (sys_addr)size);
+
+ /* always return success */
+ return (TRUE);
+}
+
+GLOBAL BOOL Sim32SetVDMMemory IFN4(double_word, addr, word, size, UTINY *, buff, BOOL, pm)
+{
+ sys_addr iaddr;
+ convert_addr (iaddr, addr, pm, FALSE);
+ /* effectivly a sas_stores */
+ sas_stores (iaddr, buff, (sys_addr)size);
+
+ /* always return success */
+ return (TRUE);
+}
+
+/********************************************************/
+/* Support routines for sim32 above */
+GLOBAL sys_addr sim32_effective_addr IFN2(double_word, addr, BOOL, pm)
+{
+ word seg, off;
+ double_word descr_addr;
+ DESCR entry;
+
+ seg = (word)(addr>>16);
+ off = (word)(addr & 0xffff);
+
+ if (pm == FALSE)
+ {
+ return ((double_word)seg << 4) + off;
+ }
+ else
+ {
+ if ( selector_outside_table(seg, &descr_addr) == 1 )
+ {
+ /*
+ This should not happen, but is a check the real effective_addr
+ includes. Return error -1.
+ */
+#ifndef PROD
+ printf("NTVDM:sim32:effective addr: Error for addr %#x (seg %#x)\n",addr, seg);
+ HostDebugBreak();
+#endif
+ return ((sys_addr)-1);
+ }
+ else
+ {
+ read_descriptor(descr_addr, &entry);
+ return entry.base + off;
+ }
+ }
+}
+
+
+/********************************************************/
+/* Microsoft extensions to sas interface */
+LOCAL IMEMBLOCK *imap_start=NULL, *imap_end=NULL;
+GLOBAL IMEMBLOCK *sas_mem_map ()
+{
+ /* produce a memory map for the whole of intel space */
+ sys_addr iaddr;
+ int mem_type;
+
+ if (imap_start)
+ sas_clear_map();
+
+ for (iaddr=0; iaddr < Length_of_M_area; iaddr++)
+ {
+ mem_type = sas_memory_type (iaddr);
+ if (!imap_end)
+ {
+ /* this is the first record */
+ check_malloc (imap_start, 1, IMEMBLOCK);
+ imap_start->Next = NULL;
+ imap_end = imap_start;
+ imap_end->Type = mem_type;
+ imap_end->StartAddress = iaddr;
+ continue;
+ }
+ if (imap_end->Type != mem_type)
+ {
+ /* end of a memory section & start of a new one */
+ imap_end->EndAddress = iaddr-1;
+ check_malloc (imap_end->Next, 1,IMEMBLOCK);
+ imap_end = imap_end->Next;
+ imap_end->Next = NULL;
+ imap_end->Type =mem_type;
+ imap_end->StartAddress = iaddr;
+ }
+ }
+ /* terminate last record */
+ imap_end->EndAddress = iaddr;
+ return (imap_start);
+}
+
+GLOBAL void sas_clear_map()
+{
+ IMEMBLOCK *p, *q;
+ for (p=imap_start; p; p=q)
+ {
+ q=p->Next;
+ free(p);
+ }
+ imap_start=imap_end=NULL;
+}
+
+/********************************************************/
+/* Microsoft specific sas stuff (ie host sas) */
+
+#define SIXTEENMEG 1024*1024*12
+
+LOCAL UTINY *reserve_for_sas = NULL;
+
+#ifndef CPU_40_STYLE
+
+LOCAL sys_addr current_sas_size =0; /* A local Length_of_M_area */
+
+GLOBAL UTINY *host_sas_init IFN1(sys_addr, size)
+{
+ UTINY *rez;
+ DWORD M_plus_type_size;
+
+ /* allocate 16 MEG of virtual memory */
+ if (!reserve_for_sas)
+ {
+ if (!(reserve_for_sas = (UTINY *)VirtualAlloc ((void *)NULL, SIXTEENMEG,
+ MEM_RESERVE, PAGE_READWRITE)))
+ {
+#ifndef PROD
+ printf ("NTVDM:Failed to reserve 16 Meg virtual memory for sas\n");
+#endif
+ exit (0);
+ }
+ }
+
+ /* now commit to our size */
+ M_plus_type_size = size + NOWRAP_PROTECTION +
+ ((size + NOWRAP_PROTECTION) >> 12);
+ rez = (UTINY *)VirtualAlloc ((void *) reserve_for_sas,
+ M_plus_type_size,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (rez)
+ Length_of_M_area = current_sas_size = size;
+ return (rez);
+
+}
+
+
+GLOBAL UTINY *host_sas_term()
+{
+ if (!reserve_for_sas)
+ return (NULL);
+
+ /* deallocate the reserves */
+ VirtualFree (reserve_for_sas, SIXTEENMEG, MEM_RELEASE);
+
+ /* null out reserve pointer */
+ reserve_for_sas = NULL;
+
+ Length_of_M_area = current_sas_size = 0;
+
+ return (NULL);
+}
+
+GLOBAL UTINY *sas_alter_size IFN1(sys_addr, new)
+{
+ UTINY *tmp;
+ if (!reserve_for_sas)
+ {
+#ifndef PROD
+ printf ("NTVDM:Sas trying to alter size before reserve setup\n");
+#endif
+ return (NULL);
+ }
+
+ /* if we are already at the right size return success */
+ if (new == current_sas_size)
+ {
+ return (reserve_for_sas);
+ }
+
+ if (new > current_sas_size)
+ {
+ /* move to end of current commited area */
+ tmp = reserve_for_sas + current_sas_size;
+ if (!VirtualAlloc ((void *)tmp, (DWORD)(new - current_sas_size), MEM_COMMIT,
+ PAGE_READWRITE))
+ {
+ printf ("NTVDM:Virtual Allocate for resize from %d to %d FAILED!\n",
+ current_sas_size, new);
+ return (NULL);
+ }
+ }
+ else
+ {
+ /* move to the place where sas needs to end */
+ tmp = reserve_for_sas + new;
+
+ /* now decommit the unneeded memory */
+ if (!VirtualFree ((void *)tmp, (DWORD)(current_sas_size - new), MEM_DECOMMIT))
+ {
+ printf ("NTVDM:Virtual Allocate for resize from %d to %d FAILED!\n",
+ current_sas_size, new);
+ return (NULL);
+ }
+ }
+ Length_of_M_area = current_sas_size = new;
+ return (reserve_for_sas);
+}
+
+
+
+#else /* CPU_40_STYLE */
+
+
+// Intel space allocation and deallocation control function for the A4 CPU
+
+GLOBAL UTINY *host_sas_init IFN1(sys_addr, size)
+{
+
+ /* Initialise memory management system and allocation bottom 1M+64K */
+ if(!(Start_of_M_area = InitIntelMemory(size)))
+ {
+ /* Initialise function failed, exit */
+#ifndef PROD
+ printf ("NTVDM:Failed to allocate virtual memory for sas\n");
+#endif
+
+ exit(0);
+ }
+
+ Length_of_M_area = size;
+ return(Start_of_M_area);
+}
+
+
+GLOBAL UTINY *host_sas_term()
+{
+ /* Has any Intel memory been allocated ? */
+ if(Start_of_M_area)
+ {
+ /* Free allocated intel memory and control structures */
+ FreeIntelMemory();
+
+ reserve_for_sas = NULL; /* null out reserve pointer */
+ Length_of_M_area = 0;
+ }
+
+ return(NULL);
+}
+
+#endif /* CPU_40_STYLE */
+
+#endif /* SIM32 */
diff --git a/private/mvdm/softpc.new/host/src/sources b/private/mvdm/softpc.new/host/src/sources
new file mode 100644
index 000000000..ff583782b
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/sources
@@ -0,0 +1,111 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+
+MAJORCOMP=spchost
+MINORCOMP=src
+
+TARGETNAME=src
+
+TARGETPATH=obj
+
+
+NTPROFILEINPUT=yes
+
+# Pick one of the following and delete the others
+TARGETTYPE=LIBRARY
+
+TARGETLIBS=
+
+SOFTPC_TREE=$(BASEDIR)\private\mvdm\softpc.new
+
+INCLUDES=$(SOFTPC_TREE)\host\inc;$(SOFTPC_TREE)\base\inc;$(_NTDRIVE)\nt\private\mvdm\vdd\h;$(_NTDRIVE)\nt\private\mvdm\inc;$(_NTDRIVE)\nt\private\windows\inc;$(_NTDRIVE)\nt\private\inc
+
+!IF $(ALPHA)
+GPSIZE=0
+!ELSE
+GPSIZE=0
+!ENDIF
+
+
+
+SOURCES= sim32.c \
+ cpucstbs.c \
+ nt_timer.c \
+ nt_ntfun.c \
+ nt_msscs.c \
+ nt_error.c \
+ nt_cga.c \
+ nt_ega.c \
+ nt_vga.c \
+ nt_input.c \
+ nt_graph.c \
+ nt_hosts.c \
+ nt_sound.c \
+ nt_bop.c \
+ nt_com.c \
+ nt_wcom.c \
+ nt_rez.c \
+ nt_sas.c \
+ nt_fdisk.c \
+ nt_unix.c \
+ nt_keycd.c \
+ nt_cpu.c \
+ nt_lpt.c \
+ nt_yoda.c \
+ nt_mouse.c \
+ nt_event.c \
+ nt_munge.c \
+ config.c \
+ nt_nls.c \
+ copy_fnc.c \
+ nt_msscs.c \
+ stubs.c \
+ nt_pif.c \
+ nt_fulsc.c \
+ nt_emm.c \
+ x86_emm.c \
+ nt_eoi.c \
+ nt_vdd.c \
+ nt_sec.c \
+ nt_thred.c \
+ nt_det.c \
+ nt_umb.c \
+ fprt.c \
+ nt_rflop.c \
+ nt_inthk.c \
+ nt_reset.c \
+ nt_mem.c
+
+PPC_SOURCES=nt_aorc.c
+
+MIPS_SOURCES=$(PPC_SOURCES)
+
+ALPHA_SOURCES=$(PPC_SOURCES)
+
+i386_SOURCES=
+
+!INCLUDE $(SOFTPC_TREE)\obj.vdm\CDEFINE.INC
+
+UMTYPE=console
diff --git a/private/mvdm/softpc.new/host/src/stf_conf.c b/private/mvdm/softpc.new/host/src/stf_conf.c
new file mode 100644
index 000000000..ae0932398
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/stf_conf.c
@@ -0,0 +1,927 @@
+/*
+ * SoftPC Revision 3.0
+ *
+ *
+ * Title : Host dependent configuration panel functions
+ *
+ *
+ * Description : This module forms the host dependant side of the softpc
+ * configuration system.
+ *
+ *
+ * Author : Wilf Stubs
+ *
+ *
+ * Notes :
+ *
+ */
+#include "insignia.h"
+#include "host_dfs.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "xt.h"
+#include "error.h"
+#include "gfi.h"
+#include "gmi.h"
+#include "gfx_updt.h"
+#include "config.h"
+#include "rs232.h"
+#include "host_lpt.h"
+#include "host_cpu.h"
+#include "host_com.h"
+#include "nt_confg.h"
+
+/*********** Private definitions ***********************/
+
+/*
+ * Validation routines
+ */
+
+static short validate_c_drive();
+static short validate_d_drive();
+static short validate_com1();
+static short validate_com2();
+static short validate_lpt1();
+static short validate_lpt2();
+#if (NUM_PARALLEL_PORTS>2)
+static short validate_lpt3();
+#endif
+static short validate_item();
+static short no_validation();
+
+/*
+ * Change action routines
+ */
+
+static short c_drive_change_action();
+static short d_drive_change_action();
+static short no_change_action();
+static short lpt1_change_action();
+static short lpt2_change_action();
+#if (NUM_PARALLEL_PORTS>2)
+static short lpt3_change_action();
+#endif
+static short com1_change_action();
+static short com2_change_action();
+boolean pc_initiated=FALSE;
+char *pc_uif_text;
+
+boolean use_comments = TRUE; /* Set to true if commenting required. */
+
+#define defaults_filename "SoftPC.rez"
+
+static char *ends[] =
+{
+ "st","nd","rd","th"
+};
+
+/* Table definitions for options that take one of n 'value' strings.
+ * The table is used to look up the string and find what it means
+ * to the host in this option.
+ * Look at the tables for more explanation, they're fairly self-explanatory.
+ */
+name_table bool_values[] =
+{
+ { "yes", TRUE },
+ { "Yes", TRUE },
+ { "YES", TRUE },
+ { "no", FALSE },
+ { "No", FALSE },
+ { "NO", FALSE },
+ { NULL, 0 }
+};
+
+name_table gfx_adapter_types[] =
+{
+ { "HERCULES", HERCULES },
+ { "CGA", CGA },
+ { "EGA", EGA },
+ { "VGA", VGA },
+ { NULL, 0 }
+};
+
+/* The BIG one! This is a decription of each option that the config struct
+ * must have, and its requirements. Used by config for all sorts of things.
+ * For a fuller explanation look in the document:
+ * 'Design Proposal for the New Config System'.
+ */
+
+option_description narrative[] =
+{
+ { /* FOR EACH OPTION... */
+ "HARD_DISK_FILENAME", /* Name */
+ C_HARD_DISK1_NAME, /* Host name for option */
+ C_STRING_RECORD, /* Option (base) primitive type */
+ C_HARD_DISKS, /* Host option commonality type */
+ FALSE, /* Option is READ_ONLY if TRUE */
+ null_table, /* Pointer to table (null if not needed) */
+ TRUE, /* TRUE if default present, FALSE if not */
+ "/usr/lib/SoftPC/hard_disk", /* Default value as a string as if in resource file */
+ TRUE, /* TRUE if changing the option requires SoftPC reset */
+ TRUE, /* TRUE if option may be setup via the UIF */
+ DISK_CONFIG, /* Panel 'type' if you have different panels */
+ validate_c_drive, /* validation function */
+ c_drive_change_action /* function to do changing actions */
+ },
+ {
+ "HARD_DISK_FILENAME2",
+ C_HARD_DISK2_NAME,
+ C_STRING_RECORD,
+ C_HARD_DISKS,
+ FALSE,
+ null_table,
+ TRUE,
+ "",
+ TRUE,
+ TRUE,
+ DISK_CONFIG,
+ validate_d_drive,
+ d_drive_change_action
+ },
+ {
+ "COM_PORT_1",
+ C_COM1_NAME,
+ C_STRING_RECORD,
+ C_SINGULARITY,
+ FALSE,
+ null_table,
+ TRUE,
+ "",
+ FALSE,
+ FALSE,
+ COMMS_CONFIG,
+ validate_com1,
+ com1_change_action
+ },
+ {
+ "COM_PORT_2",
+ C_COM2_NAME,
+ C_STRING_RECORD,
+ C_SINGULARITY,
+ FALSE,
+ null_table,
+ TRUE,
+ "",
+ FALSE,
+ FALSE,
+ COMMS_CONFIG,
+ validate_com2,
+ com2_change_action
+ },
+ {
+ "LPT_PORT_1",
+ C_LPT1_NAME,
+ C_STRING_RECORD,
+ C_SINGULARITY,
+ FALSE,
+ null_table,
+ TRUE,
+ "",
+ FALSE,
+ FALSE,
+ COMMS_CONFIG,
+ validate_lpt1,
+ lpt1_change_action
+ },
+ {
+ "LPT_PORT_2",
+ C_LPT2_NAME,
+ C_STRING_RECORD,
+ C_SINGULARITY,
+ FALSE,
+ null_table,
+ TRUE,
+ "",
+ FALSE,
+ FALSE,
+ COMMS_CONFIG,
+ validate_lpt2,
+ lpt2_change_action
+ },
+ {
+ "GRAPHICS_ADAPTOR",
+ C_GFX_ADAPTER,
+ C_NAME_RECORD,
+ C_SINGULARITY,
+ FALSE,
+ gfx_adapter_types,
+ TRUE,
+ "VGA",
+ TRUE,
+ TRUE,
+ DISPLAY_CONFIG,
+ validate_item,
+ no_change_action
+ },
+ {
+ NULL,
+ 0,
+ 0,
+ C_SINGULARITY,
+ FALSE,
+ null_table,
+ FALSE,
+ NULL,
+ FALSE,
+ FALSE,
+ NON_CONFIG,
+ no_validation,
+ no_change_action
+ }
+};
+
+/* Runtime variables */
+
+struct
+{
+ boolean mouse_attached;
+ boolean config_verbose;
+ boolean npx_enabled;
+ boolean sound_on;
+ boolean com_flow_control[2];
+ int floppy_state[2];
+ int floppy_active_state[2];
+ int floppy_capacity[2];
+ int hd_cyls[2];
+ boolean lptflush1;
+ boolean lptflush2;
+ boolean lptflush3;
+ int flushtime1;
+ int flushtime2;
+ int flushtime3;
+} runtime_status;
+
+#define NUM_OPTS ( sizeof(narrative) / sizeof( option_description) )
+
+/*********** Imported and exported items *************/
+
+extern char *getenv();
+extern char *malloc();
+
+/*************** Local Declarations *****************/
+
+void host_config_error();
+static char buff[MAXPATHLEN];
+static char buff1[MAXPATHLEN];
+boolean item_in_table();
+static char home_resource[MAXPATHLEN];
+static char sys_resource[MAXPATHLEN];
+
+/*********************************************************/
+
+short host_runtime_inquire(what)
+int what;
+
+{
+ switch(what)
+ {
+ case C_MOUSE_ATTACHED:
+ return( runtime_status.mouse_attached );
+ break;
+
+ case C_CONFIG_VERBOSE:
+ return( runtime_status.config_verbose );
+ break;
+
+ case C_NPX_ENABLED:
+ return( runtime_status.npx_enabled );
+ break;
+
+ case C_HD1_CYLS:
+ return( runtime_status.hd_cyls[0] );
+ break;
+
+ case C_HD2_CYLS:
+ return( runtime_status.hd_cyls[1] );
+ break;
+
+ case C_FLOPPY1_STATE:
+ return( runtime_status.floppy_state[0] );
+ break;
+
+ case C_FLOPPY2_STATE:
+ return( runtime_status.floppy_state[1] );
+ break;
+
+ case C_FLOPPY1_ACTIVE_STATE:
+ return( runtime_status.floppy_active_state[0] );
+ break;
+
+ case C_FLOPPY2_ACTIVE_STATE:
+ return( runtime_status.floppy_active_state[1] );
+ break;
+
+ case C_FLOPPY1_CAPACITY:
+ return( runtime_status.floppy_capacity[0] );
+ break;
+
+ case C_FLOPPY_TYPE_CHANGED:
+ return( runtime_status.floppy_type_changed );
+ break;
+
+ case C_FLOPPY2_CAPACITY:
+ return( runtime_status.floppy_capacity[1] );
+ break;
+
+ case C_SOUND_ON:
+ return( runtime_status.sound_on );
+ break;
+
+ case C_REAL_FLOPPY_ALLOC:
+ return( runtime_status.floppy_state[0] == GFI_REAL_DISKETTE_SERVER ||
+ runtime_status.floppy_state[1] == GFI_REAL_DISKETTE_SERVER );
+ break;
+
+ case C_REAL_OR_SLAVE:
+ return( runtime_status.floppy_A_real );
+ break;
+
+ case C_SLAVE_FLOPPY_ALLOC:
+ return( runtime_status.floppy_state[0] == GFI_SLAVE_SERVER );
+ break;
+
+ case C_COM1_FLOW:
+ return( runtime_status.com_flow_control[0] );
+ break;
+
+ case C_COM2_FLOW:
+ return( runtime_status.com_flow_control[1] );
+ break;
+
+ case C_COM3_FLOW:
+ return( FALSE );
+ break;
+
+ case C_COM4_FLOW:
+ return( FALSE );
+ break;
+
+ case C_LPTFLUSH1:
+ return( runtime_status.lptflush1 );
+ break;
+
+ case C_LPTFLUSH2:
+ return( runtime_status.lptflush2 );
+ break;
+
+ case C_LPTFLUSH3:
+ return( runtime_status.lptflush3 );
+ break;
+
+ case C_FLUSHTIME1:
+ return( runtime_status.flushtime1 );
+ break;
+
+ case C_FLUSHTIME2:
+ return( runtime_status.flushtime2 );
+ break;
+
+ case C_FLUSHTIME3:
+ return( runtime_status.flushtime3 );
+ break;
+
+ default:
+ host_error(EG_OWNUP, ERR_QUIT, "host_runtime_inquire");
+ }
+}
+
+void host_runtime_set(what,value)
+int what;
+int value;
+{
+ switch(what)
+ {
+ case C_MOUSE_ATTACHED:
+ runtime_status.mouse_attached = value;
+ break;
+
+ case C_CONFIG_VERBOSE:
+ runtime_status.config_verbose = value;
+ break;
+
+ case C_NPX_ENABLED:
+ runtime_status.npx_enabled = value;
+ break;
+
+ case C_HD1_CYLS:
+ runtime_status.hd_cyls[0] = value;
+ break;
+
+ case C_HD2_CYLS:
+ runtime_status.hd_cyls[1] = value;
+ break;
+
+ case C_FLOPPY1_STATE:
+ runtime_status.floppy_state[0] = value;
+ break;
+
+ case C_FLOPPY2_STATE:
+ runtime_status.floppy_state[1] = value;
+ break;
+
+ case C_FLOPPY1_ACTIVE_STATE:
+ runtime_status.floppy_active_state[0] = value;
+ break;
+
+ case C_FLOPPY2_ACTIVE_STATE:
+ runtime_status.floppy_active_state[1] = value;
+ break;
+
+ case C_FLOPPY1_CAPACITY:
+ runtime_status.floppy_capacity[0] = value;
+ break;
+
+ case C_FLOPPY2_CAPACITY:
+ runtime_status.floppy_capacity[1] = value;
+ break;
+
+ case C_FLOPPY_TYPE_CHANGED:
+ runtime_status.floppy_type_changed = value;
+ break;
+
+ case C_SOUND_ON:
+ runtime_status.sound_on = value;
+ break;
+
+ case C_REAL_OR_SLAVE:
+ runtime_status.floppy_A_real = value;
+ break;
+
+ case C_COM1_FLOW:
+ runtime_status.com_flow_control[0] = value;
+ break;
+
+ case C_COM2_FLOW:
+ runtime_status.com_flow_control[1] = value;
+ break;
+
+ case C_COM3_FLOW:
+ case C_COM4_FLOW:
+ break;
+
+ case C_LPTFLUSH1:
+ runtime_status.lptflush1 =value;
+ break;
+
+ case C_LPTFLUSH2:
+ runtime_status.lptflush2 =value;
+ break;
+
+ case C_LPTFLUSH3:
+ runtime_status.lptflush3 =value;
+ break;
+
+ case C_FLUSHTIME1:
+ runtime_status.flushtime1 =value;
+ break;
+
+ case C_FLUSHTIME2:
+ runtime_status.flushtime2 =value;
+ break;
+
+ case C_FLUSHTIME3:
+ runtime_status.flushtime3 =value;
+ break;
+
+ default:
+ host_error(EG_OWNUP, ERR_QUIT, "host_runtime_set");
+ }
+}
+
+void host_runtime_init()
+{
+ config_values var;
+
+#ifdef NPX
+ host_runtime_set(C_NPX_ENABLED,TRUE);
+#else
+ host_runtime_set(C_NPX_ENABLED,FALSE);
+#endif
+
+#ifndef PROD
+ printf("NPX is %s\n",host_runtime_inquire(C_NPX_ENABLED)? "on.":"off.");
+#endif
+ host_runtime_set(C_FLUSHTIME1, 5);
+ host_runtime_set(C_FLUSHTIME2, 10);
+ host_runtime_set(C_FLUSHTIME3, 15);
+ host_runtime_set(C_MOUSE_ATTACHED,FALSE);
+ host_runtime_set(C_CONFIG_VERBOSE,TRUE);
+ host_runtime_set(C_SOUND_ON,FALSE);
+ host_runtime_set(C_FLOPPY1_STATE,GFI_EMPTY_SERVER);
+ host_runtime_set(C_FLOPPY2_STATE,GFI_EMPTY_SERVER);
+ host_runtime_set(C_FLOPPY1_ACTIVE_STATE,GFI_EMPTY_SERVER);
+ host_runtime_set(C_FLOPPY2_ACTIVE_STATE,GFI_EMPTY_SERVER);
+ host_runtime_set(C_REAL_OR_SLAVE,FALSE);
+ host_runtime_set(C_FLOPPY_TYPE_CHANGED,FALSE);
+}
+
+/*
+ * General host initialisation function. It is called only once on startup
+ * from 'config()'. It does the following (at the moment):
+ *
+ * 1) Makes the 'option' field of the 'config_info' struct pointed to by 'head' * point to all the option 'rules' - that is the 'narrative' structure
+ * initialised at the start of this file.
+ *
+ * 2) Counts up the option rules in 'narrative' and stores the result in the
+ * 'config_info' struct.
+ *
+ * 3) Return the minimum padding length necessary.
+ *
+ * 4) Derive the two path:filenames for the resource file. This file may be
+ * in the user's $HOME directory or in softpc's ROOT directory. Making up
+ * these strings now saves doing it every time 'config_store()' is called.
+ */
+
+void host_get_config_info(head)
+config_description *head;
+{
+
+ char *pp, *getenv();
+ option_description *option_p = narrative;
+
+ head->option = narrative; /* Attach 'narrative' */
+ head->option_count = NUM_OPTS - 1;
+ head->min_pad_len = MIN_OPTION_ARG_DIST;
+
+ /*
+ * get system resource file from standard place
+ */
+ strcpy(sys_resource, ROOT);
+
+ strcat(sys_resource, PATH_SEPARATOR);
+ strcat(sys_resource, RESOURCE_FILENAME);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::: Try and load database files ::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+static boolean try_load_database()
+{
+ FILE *infile = NULL;
+ char in_line[MAXPATHLEN];
+ char *cp;
+ char *home, *getenv();
+
+ /* Keep this the same as system for the moment */
+
+ sprintf(home_resource,"%s%s%s",ROOT,PATH_SEPARATOR,RESOURCE_FILENAME);
+
+ /*....................................... Attempt to open resource file */
+
+ if((infile = fopen(home_resource, "r")) == NULL)
+ return(FALSE);
+
+ /*.................................................. Read resource file */
+
+ while (fgets(in_line, MAXPATHLEN, infile) != NULL)
+ {
+ /*........................................ strip control characters */
+
+ for(cp = in_line; *cp ; cp++) if(*cp < ' ') *cp = ' ';
+
+ add_resource_node(in_line);
+ }
+
+ /*............................. Close resource file and get out of here */
+
+ fclose(infile);
+ return TRUE;
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::: Try to load system files ::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+static boolean try_load_sys_file()
+{
+ FILE *infile = NULL;
+ char in_line[MAXPATHLEN];
+ register char *cp;
+
+ /*................................ Attempt to open system resource file */
+
+ if((infile = fopen(sys_resource, "r")) == NULL)
+ return(FALSE);
+
+ /*................................................. read resource file */
+
+ while (fgets(in_line, MAXPATHLEN, infile) != NULL)
+ {
+ /*......................................... strip control characters */
+
+ for(cp = in_line; *cp ; cp++)
+ if(*cp < ' ') *cp = ' ';
+
+ add_resource_node(in_line);
+ }
+
+ /*........................................ close resource file and exit */
+
+ fclose(infile);
+ return(TRUE);
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+/*:::::::::::::::::::::::::: Read resource file ::::::::::::::::::::::::::::*/
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+short host_read_resource_file(resource_data *resource)
+{
+ boolean bad_home=FALSE, bad_sys=FALSE;
+
+ /* Try open users default database failing that, open the system file. */
+
+ if(bad_home = !try_load_database())
+ bad_sys = !try_load_sys_file();
+
+ if(bad_home && bad_sys) return(EG_ALL_RESOURCE_BAD_R);
+
+ return(bad_home ? EG_BAD_LOCAL_RESOURCE_R : C_CONFIG_OP_OK);
+}
+
+short host_write_resource_file(resource)
+resource_data *resource;
+{
+
+FILE *outfile;
+line_node *node;
+boolean bad_home=TRUE, bad_sys=FALSE;
+
+ /* Try to open (for writing) a resource file in the users home directory or
+ failing that, the system one. These two paths are set up once at runtime. */
+
+ if(home_resource[0] != '\0')
+ if((outfile = fopen(home_resource, "w")) != NULL)
+ bad_home = FALSE;
+
+ if(bad_home)
+ if((outfile = fopen(sys_resource, "w")) == NULL)
+ bad_sys = TRUE;
+
+ if(bad_home && !bad_sys)
+ return EG_ALL_RESOURCE_BAD_W;
+
+ else
+ if(bad_home && bad_sys)
+ return EG_ALL_RESOURCE_BAD_W;
+
+ node = resource->first;
+ while(node != NULL)
+ {
+ fputs(node->line,outfile);
+ fputc('\n',outfile);
+ node = node->next;
+ }
+ fclose(outfile);
+ return(C_CONFIG_OP_OK);
+
+}
+
+
+/* A host specific extension to config_inquire() to deal with any inquiries
+ that the base config code doesn't or shouldn't know about. */
+
+
+void host_inquire_extn(sort,identity,values)
+short sort;
+int identity;
+config_values *values;
+{
+}
+
+static char error_text[300];
+static int error_locus;
+
+host_error_query_locus(locus,text)
+int *locus;
+char **text;
+{
+ *locus = error_locus;
+ *text = error_text;
+}
+
+host_error_set_locus(text, locus)
+char *text;
+int locus;
+{
+ strcpy(error_text, text);
+ error_locus = locus;
+}
+
+static short no_validation(value, table, buf)
+config_values *value;
+name_table table[];
+char *buf;
+{
+ return(C_CONFIG_OP_OK);
+}
+
+static short validate_c_drive(value, table, buf)
+config_values *value;
+name_table table[];
+char *buf;
+{
+/* cheat on validation for moment as this will disapear */
+ return(C_CONFIG_OP_OK);
+}
+
+static short validate_d_drive(value, table, buf)
+config_values *value;
+name_table table[];
+char *buf;
+{
+/* cheat on validation for moment as this will disapear */
+ return(C_CONFIG_OP_OK);
+}
+
+static short validate_com1(value, table, buf)
+config_values *value;
+name_table table[];
+char *buf;
+{
+/* cheat on validation for moment as this will change */
+ return(C_CONFIG_OP_OK);
+}
+
+static short validate_com2(value, table, buf)
+config_values *value;
+name_table table[];
+char *buf;
+{
+/* cheat on validation for moment as this will change */
+ return(C_CONFIG_OP_OK);
+}
+
+static short validate_lpt1(value, table, buf)
+config_values *value;
+name_table table[];
+char *buf;
+{
+/* cheat on validation for moment as this will change */
+ return(C_CONFIG_OP_OK);
+}
+
+static short validate_lpt2(value, table, buf)
+config_values *value;
+name_table table[];
+char *buf;
+{
+/* cheat on validation for moment as this will change */
+ return(C_CONFIG_OP_OK);
+}
+
+static short validate_item(value, table, buf)
+config_values *value;
+name_table table[];
+char *buf;
+{
+/* cheat on validation - no table lookup */
+ return(C_CONFIG_OP_OK);
+}
+
+boolean item_in_table(val,table)
+int val;
+name_table table[];
+{
+ int n=0;
+ while(table[n].string != NULL)
+ if(table[n].value == val)
+ break;
+ else
+ n++;
+ return( table[n].string == NULL? FALSE : TRUE);
+}
+
+static short no_change_action( value, buf)
+config_values *value;
+char *buf;
+{
+ return( C_CONFIG_OP_OK );
+}
+
+static short c_drive_change_action( value, buf)
+config_values *value;
+char *buf;
+{
+ short err;
+
+ fdisk_iodetach ();
+ fdisk_physdetach(0);
+
+ if (err = fdisk_physattach( 0, value->string))
+ strcpy(buf, narrative[C_HARD_DISK1_NAME].option_name);
+
+ fdisk_ioattach ();
+
+ return (err);
+
+}
+
+static short d_drive_change_action( value, buf)
+config_values *value;
+char *buf;
+{
+ short err;
+
+ fdisk_iodetach ();
+ fdisk_physdetach(1);
+
+ if (err = fdisk_physattach( 1, value->string))
+ strcpy(buf, narrative[C_HARD_DISK2_NAME].option_name);
+
+ fdisk_ioattach ();
+
+ return (err);
+}
+
+static short lpt1_change_action( value, buf)
+config_values *value;
+char *buf;
+{
+#ifdef STUBBED
+ host_lpt_close(0);
+ return (host_lpt_open(0, value->string, buf));
+#endif /*STUBBED*/
+/* cheat on validation for moment as this will change */
+ return(C_CONFIG_OP_OK);
+}
+
+static short lpt2_change_action( value, buf)
+config_values *value;
+char *buf;
+{
+#ifdef STUBBED
+ host_lpt_close(1);
+ return (host_lpt_open(1, value->string, buf));
+#endif /*STUBBED*/
+/* cheat on validation for moment as this will change */
+ return(C_CONFIG_OP_OK);
+}
+
+static short com1_change_action( value, buf)
+config_values *value;
+char *buf;
+{
+#ifdef STUBBED
+ host_com_close(0);
+ return (host_com_open(0, value->string, buf));
+#endif /*STUBBED*/
+/* cheat on validation for moment as this will change */
+ return(C_CONFIG_OP_OK);
+}
+
+static short com2_change_action( value, buf)
+config_values *value;
+char *buf;
+{
+#ifdef STUBBED
+ host_com_close(1);
+ return (host_com_open(1, value->string, buf));
+#endif /*STUBBED*/
+/* cheat on validation for moment as this will change */
+ return(C_CONFIG_OP_OK);
+}
+
+/*********** Floppy and hard disk init ****************/
+
+void host_floppy_startup(driveno)
+int driveno;
+{
+ host_floppy_init(driveno, GFI_EMPTY_SERVER );
+}
+
+void host_hd_startup()
+{
+ int error;
+ config_values disk1_name,disk2_name;
+
+ /* Start by getting the C: drive up */
+
+ fdisk_physdetach(0);
+ config_inquire(C_INQUIRE_VALUE,C_HARD_DISK1_NAME,&disk1_name);
+ error = fdisk_physattach(0,disk1_name.string);
+ if(error)
+ {
+ host_error(error, ERR_CONFIG|ERR_QUIT, disk1_name.string);
+ }
+
+/* If that went ok, try for D: */
+
+ config_inquire(C_INQUIRE_VALUE,C_HARD_DISK2_NAME,&disk2_name);
+ if(!strcmp(disk2_name.string,""))
+ return; /* No D: drive! */
+
+ if(!strcmp(disk2_name.string,disk1_name.string))
+ host_error(EG_SAME_HD_FILE, ERR_CONFIG|ERR_QUIT, disk2_name.string);
+
+ error = fdisk_physattach(1,disk2_name.string);
+ if(error)
+ host_error(error, ERR_CONFIG|ERR_QUIT, disk2_name.string);
+
+}
+
+/* temp hack */
+char *host_get_spc_home() { return("c:\\softpc"); }
diff --git a/private/mvdm/softpc.new/host/src/stubs.c b/private/mvdm/softpc.new/host/src/stubs.c
new file mode 100644
index 000000000..881b28851
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/stubs.c
@@ -0,0 +1,614 @@
+#undef ANSI // until file tidied or better still, lost
+
+#include <windows.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "host_def.h"
+#include "insignia.h"
+#include "xt.h"
+#include "debug.h"
+#include "sas.h"
+#include "config.h"
+#include "chkmallc.h"
+
+#ifdef X86GFX
+#include "egacpu.h"
+#include "egaread.h"
+#endif
+
+#ifdef MONITOR
+GLOBAL void sas_loads_to_transbuf IFN3(sys_addr, src, host_addr, dest, sys_addr, len)
+{
+ sas_loads (src, dest, len);
+}
+
+/* write a string into M */
+GLOBAL void sas_stores_from_transbuf IFN3(sys_addr, dest, host_addr, src, sys_addr, len)
+{
+ sas_stores (dest, src, len);
+}
+
+GLOBAL host_addr sas_transbuf_address IFN2(sys_addr, dest_intel_addr, sys_addr, length)
+{
+ UNUSED (dest_intel_addr);
+ return (sas_scratch_address (length));
+}
+#endif
+
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: log1p */
+
+#ifndef MONITOR
+GLOBAL double log1p(x)
+double x;
+{
+ return log(1+x);
+}
+
+#endif /* !MONITOR */
+
+
+/*:::::::::::::::::::::::::::::::::::::::::::::::::::::: SAS wrapping stubs */
+
+#ifdef MONITOR
+GLOBAL void npx_reset()
+{
+ return;
+}
+
+GLOBAL void initialise_npx()
+{
+ return;
+}
+
+GLOBAL void sas_overwrite_memory IFN2(sys_addr, addr, int, type)
+{
+ UNUSED(addr);
+ UNUSED(type);
+}
+
+LOCAL LONG stub_q_ev_count = 0; // holder for below
+
+/* Monitor controlled code will call quick event code immediately so the
+ * following needn't be at all accurate.
+ */
+void host_q_ev_set_count(value)
+LONG value;
+{
+ stub_q_ev_count = value;
+}
+
+LONG host_q_ev_get_count()
+{
+ return(stub_q_ev_count);
+}
+
+int host_calc_q_ev_inst_for_time(LONG time)
+{
+ return(time);
+}
+
+#ifndef CPU_40_STYLE
+int host_calc_q_ev_time_for_inst(LONG inst)
+{
+ return(inst);
+}
+#endif
+
+////// The following support the major surgery to remove unneeded video stuff
+
+GLOBAL ULONG Gdp;
+GLOBAL half_word bg_col_mask = 0x70; // usually defined in cga.c
+GLOBAL READ_STATE read_state;
+
+ULONG sr_lookup[16] = // Handy array to extract all 4 plane values in one go
+{
+#ifdef LITTLEND
+ 0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
+ 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
+ 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
+ 0xffff0000,0xffff00ff,0xffffff00,0xffffffff
+#endif
+#ifdef BIGEND
+ 0x00000000,0xff000000,0x00ff0000,0xffff0000,
+ 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
+ 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
+ 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
+#endif
+};
+
+GLOBAL VOID glue_b_write (UTINY *addr, ULONG val)
+{
+ UNUSED(addr);
+ UNUSED(val);
+}
+GLOBAL VOID glue_w_write (UTINY *addr, ULONG val)
+{
+ UNUSED(addr);
+ UNUSED(val);
+}
+GLOBAL VOID glue_b_fill (UTINY *laddr, UTINY *haddr, ULONG val)
+{
+ UNUSED(laddr);
+ UNUSED(haddr);
+ UNUSED(val);
+}
+GLOBAL VOID glue_w_fill (UTINY *laddr, UTINY *haddr, ULONG val)
+{
+ UNUSED(laddr);
+ UNUSED(haddr);
+ UNUSED(val);
+}
+GLOBAL VOID glue_b_move(UTINY *laddr, UTINY *haddr, UTINY *src, UTINY src_type )
+{
+ UNUSED(laddr);
+ UNUSED(haddr);
+ UNUSED(src);
+ UNUSED(src_type);
+}
+GLOBAL VOID glue_w_move(UTINY *laddr, UTINY *haddr, UTINY *src )
+{
+ UNUSED(laddr);
+ UNUSED(haddr);
+ UNUSED(src);
+}
+GLOBAL VOID glue_b_fwd_move () { }
+GLOBAL VOID glue_b_bwd_move () { }
+GLOBAL VOID glue_w_fwd_move () { }
+GLOBAL VOID glue_w_bwd_move () { }
+
+GLOBAL VOID _ega_gc_outb_mask(io_addr port, half_word value)
+{
+ UNUSED(port);
+ UNUSED(value);
+}
+
+GLOBAL VOID _ega_gc_outb_mask_ff(io_addr port, half_word value)
+{
+ UNUSED(port);
+ UNUSED(value);
+}
+
+GLOBAL VOID cga_init()
+{
+}
+
+GLOBAL VOID cga_term()
+{
+}
+
+GLOBAL VOID _simple_mark_lge()
+{
+}
+
+GLOBAL VOID _simple_mark_sml()
+{
+}
+
+GLOBAL int get_ega_switch_setting()
+{
+ return(0);
+}
+
+GLOBAL VOID ega_read_init() // Do normal inits - ports will do this fully
+{
+ read_state.mode = 0;
+ read_state.colour_compare = 0x0f;
+ read_state.colour_dont_care = 0xf;
+}
+
+GLOBAL VOID ega_read_term()
+{
+}
+
+GLOBAL VOID ega_read_routines_update()
+{
+}
+
+GLOBAL VOID update_shift_count()
+{
+}
+
+GLOBAL VOID ega_write_init()
+{
+}
+
+GLOBAL VOID ega_write_term()
+{
+}
+
+GLOBAL VOID ega_write_routines_update(CHANGE_TYPE reason)
+{
+ UNUSED(reason);
+}
+
+GLOBAL VOID set_mark_funcs()
+{
+}
+
+GLOBAL ULONG setup_global_data_ptr()
+{
+ return(0xDefaced);
+}
+
+GLOBAL VOID setup_vga_globals()
+{
+ check_malloc(EGA_CPU.globals, 1, VGA_GLOBALS);
+}
+
+#endif //MONITOR
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ASSERT CODE */
+
+
+void _assert(void *exp, void *file, unsigned line)
+{
+ char linestr[100];
+
+ OutputDebugString("ASSERT FAILED - ");
+ OutputDebugString(exp);
+ OutputDebugString(" ");
+ OutputDebugString(file);
+
+ sprintf(linestr," (%d)\n",line);
+ OutputDebugString(linestr);
+}
+
+/*:::::::::::::::::::::::::::: Unix specific string functions ::::::::::::::*/
+
+char *index(char *string, int c)
+{
+ return(strchr(string, c));
+}
+
+char *rindex(char *string, int c)
+{
+ return(strrchr(string, c));
+}
+
+/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
+
+host_mouse_in_use()
+{
+return(FALSE);
+}
+
+void redirector() {}
+void reset_delta_data_structures() {}
+void set_hfx_severity() {}
+
+host_check_for_lock()
+{
+ assert0(NO,"host_check_for_lock stubbed\n");
+ return(0);
+}
+
+host_place_lock(int dummy1)
+{
+ assert0(NO,"host_place_lock stubbed\n");
+ return(0);
+}
+
+host_clear_lock(int fd)
+{
+ assert0(NO,"host_clear_lock stubbed\n");
+ return(0);
+}
+
+
+int host_com_send_delay_done(int dummy1, int dummy2)
+{
+ return(0);
+}
+#ifndef A2CPU
+delta_cpu_test_frag()
+{
+ assert0(NO,"delta_cpu_test_frag stubbed\n");
+ return(0);
+}
+
+examine_delta_data_structs(int o, int i)
+{
+ assert0(NO,"examine_delta_data_structs stubbed\n");
+ return(0);
+}
+code_gen_files_init()
+{
+ assert0(NO,"code_gen_files_init stubbed\n");
+ return(0);
+}
+decode_files_init()
+{
+ assert0(NO,"decode_files_init stubbed\n");
+ return(0);
+}
+
+#ifdef ALPHA
+
+//
+// temporary change to get Alpha CPU running
+// in checked mode. Andy - 13/1/94
+//
+
+double get_287_reg_as_double(int i)
+{
+ extern char *GDP;
+ return(*(double *)(GDP + 0x80 + i * 8));
+}
+#endif
+
+#ifdef CPU_40_STYLE
+
+GLOBAL BOOL sas_manage_xms IFN3(VOID *,start_addr, ULONG, cb, INT, a_or_f)
+{
+ printf("sas_manage_xms called(%lx,%lx,%lx)\n",start_addr,cb,a_or_f);
+ return (TRUE);
+}
+
+#undef sas_loadw
+GLOBAL void sas_loadw IFN2(sys_addr, addr, word *, val)
+{
+ *val = sas_w_at(addr);
+}
+
+GLOBAL void host_sigio_event IPT0()
+{
+}
+
+#endif /* CPU_40_STYLE */
+
+#ifndef GENERIC_NPX
+#ifndef CPU_40_STYLE
+int get_287_sp()
+{
+ extern char *GDP;
+ return((int) (*(ULONG *)(GDP + 0x70))/8);
+}
+word get_287_tag_word()
+{
+ extern char *GDP;
+ return((int) *(ULONG *)(GDP + 0x74));
+}
+word get_287_control_word()
+{
+ extern char *GDP;
+ return((int) *(ULONG *)(GDP + 0x68));
+}
+word get_287_status_word()
+{
+ extern char *GDP;
+ return((int) *(ULONG *)(GDP + 0x6c));
+}
+#endif /* CPU_40_STYLE */
+#endif /* GENERIC_NPX */
+#endif
+
+int rate_min;
+int rate_max;
+int compiling;
+int rate_delta;
+int show_stuff;
+int stat_rate;
+int compile_off[99];
+int rate_norm;
+int cut_off_level;
+int max_host_fragment_size;
+int delta_err_message[100];
+int last_destination_address;
+
+
+host_flip_real_floppy_ind()
+{
+ assert0(NO,"host_flip_real_floppy_ind stubbed\n");
+ return(0);
+}
+
+#ifndef A2CPU
+int haddr_of_src_string;
+int INTEL_STATUS;
+int R_SI;
+int R_DI;
+int R_BP;
+int R_OPA;
+int R_DEF_SS;
+int R_OPB;
+int R_SP;
+int R_DEF_DS;
+int R_AX;
+int R_BX;
+int R_CX;
+int R_DX;
+int R_IP;
+int R_ACT_CS;
+int R_ACT_SS;
+int R_OPR;
+int R_ACT_DS;
+int R_ACT_ES;
+#endif
+int compile_yoda_in;
+int m_s_w;
+int trap_delay_count = 0, temp_trap_flag = 0;
+int cpui;
+int sbp;
+
+host_EOA_hook()
+{
+ assert0(NO,"host_EOA_hook stubbed\n");
+ return(0);
+}
+
+getsdosunit()
+{
+ assert0(NO,"dispatch_q_event stubbed\n");
+ return(1);
+}
+
+#ifdef NOT_IN_USE
+host_check_using_host_mouse()
+{
+ assert0(NO,"host_check_using_host_mouse stubbed\n");
+ return(1);
+}
+host_deinstall_host_mouse()
+{
+ assert0(NO,"host_deinstall_host_mouse stubbed\n");
+ return(1);
+}
+#endif
+
+int host_timer_2_frig_factor = 20;
+
+host_check_read_only_drive()
+{
+ assert0(NO,"host_check_read_only_drive stubbed\n");
+ return(0);
+}
+
+host_lock_drive_and_make_writable()
+{
+ assert0(NO,"host_lock_drive_and_make_writable stubbed\n");
+ return(1);
+}
+
+host_floppy_init()
+{
+ assert0(NO,"host_floppy_init stubbed\n");
+ return(1);
+}
+
+SHORT validate_hfx_drive()
+{
+ assert0(NO,"host_lpt_valid\n");
+ return C_CONFIG_OP_OK;
+}
+
+SHORT host_keymap_valid()
+{
+ assert0(NO,"host_keymap_valid\n");
+ return C_CONFIG_OP_OK;
+}
+
+VOID host_keymap_change()
+{
+ assert0(NO,"host_keymap_change\n");
+}
+
+char *host_strerror(int errno)
+{
+ assert1(NO,"Error : host_strerror (%d)\n",errno);
+ return("****** again\n");
+}
+
+int link(void)
+{
+return -1;
+}
+
+LOCAL ULONG dummy()
+{
+ return(0);
+}
+
+GLOBAL ULONG (*clear_v7ptr)() = dummy;
+GLOBAL ULONG (*paint_v7ptr)() = dummy;
+
+GLOBAL ULONG host_speed IFN1(ULONG, temp)
+{
+return 10000L;
+}
+
+#ifndef MONITOR
+
+// allows getIntelRegistersPointer to be exported bt ntvdm.def
+getIntelRegistersPointer()
+{
+ assert0(NO,"getIntelRegistersPointer stubbed\n");
+ return(0);
+}
+
+#if 0
+// these two crept into WOW - they are x86 monitor'isms
+
+word getEIP()
+{
+ return(c_getIP());
+}
+
+void setEIP(val)
+word val;
+{
+ c_setIP(val);
+}
+#endif
+
+int FlatAddress[1];
+int Ldt[1];
+int VdmTib;
+int VdmTibStruct;
+
+void DispatchInterrupts()
+{
+}
+
+#else //MONITOR
+
+#ifndef YODA
+void check_I()
+{
+}
+
+void force_yoda()
+{
+ printf("Yoda disabled on x86\n");
+}
+#endif //YODA
+
+#endif //MONITOR
+
+
+#ifndef MONITOR
+
+//
+// davehart 9-Dec-92 HACKHACK
+// Build fix -- we export cpu_createthread from ntvdm.exe,
+// even though this function from v86\monitor\i386 doesn't
+// exist on MIPS.
+//
+// If we really need to export the function, we may want to
+// take the ntoskrnl.src -> obj\i386\ntoskrnl.def approach.
+//
+
+VOID
+cpu_createthread(
+ HANDLE Thread
+ )
+/*++
+
+Routine Description:
+
+ This routine adds a thread to the list of threads that could be executing
+ in application mode.
+
+Arguments:
+
+ Thread -- Supplies a thread handle
+
+Return Value:
+
+ None.
+
+--*/
+{
+}
+
+#endif // ndef MONITOR
+
+#ifndef MONITOR
+ULONG CurrentMonitorTeb;
+#endif
+
+void host_note_queue_added()
+{
+}
diff --git a/private/mvdm/softpc.new/host/src/x86_emm.c b/private/mvdm/softpc.new/host/src/x86_emm.c
new file mode 100644
index 000000000..cfb95047c
--- /dev/null
+++ b/private/mvdm/softpc.new/host/src/x86_emm.c
@@ -0,0 +1,948 @@
+/* INSIGNIA MODULE SPECIFICATION
+ -----------------------------
+
+MODULE NAME : 'Lower layer' of Expanded Memory Manager
+
+ THIS PROGRAM SOURCE FILE IS SUPPLIED IN CONFIDENCE TO THE
+ CUSTOMER, THE CONTENTS OR DETAILS OF ITS OPERATION MUST
+ NOT BE DISCLOSED TO ANY OTHER PARTIES WITHOUT THE EXPRESS
+ AUTHORISATION FROM THE DIRECTORS OF INSIGNIA SOLUTIONS INC.
+
+DESIGNER : Simon Frost
+DATE : March '92
+
+PURPOSE : NT specific code for EMS LIM rev 4.0
+ implementation.
+
+The Following Routines are defined:
+ 1. host_initialise_EM()
+ 2. host_deinitialise_EM()
+ 3. host_allocate_storage()
+ 4. host_free_storage()
+ 5. host_reallocate_storage()
+ 6. host_map_page()
+ 7. host_unmap_page()
+ 8. host_alloc_page()
+ 9. host_free_page()
+ 10. host_copy_con_to_con()
+ 11. host_copy_con_to_EM()
+ 12. host_copy_EM_to_con()
+ 13. host_copy_EM_to_EM()
+ 14. host_exchg_con_to_con()
+ 15. host_exchg_con_to_EM()
+ 16. host_exchg_EM_to_EM()
+ 17. host_get_access_key()
+
+=========================================================================
+*/
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include "insignia.h"
+#include "host_def.h"
+#include "string.h"
+#include "stdlib.h"
+
+#ifdef LIM
+#ifdef MONITOR //x86 specific LIM functions
+
+#include "xt.h"
+#include "emm.h"
+#include "sas.h"
+#include "host_rrr.h"
+#include "debug.h"
+#include "umb.h"
+#include "host_emm.h"
+#include "nt_uis.h"
+
+/* Global Variables */
+
+/* Forward Declarations */
+BOOL hold_lim_page(USHORT segment);
+/* find this function in monitor/sas.c */
+extern BOOL HoldEMMBackFillMemory(ULONG Address, ULONG Size);
+
+
+/* Local Variables */
+
+LOCAL UTINY *EM_pagemap_address = NULL; /* address of start of pagemap */
+
+/* pagemap requires 1 bit per 16K page - i.e. 8 bytes per meg */
+LOCAL UTINY EM_pagemap[8*32];
+
+LOCAL VOID *BaseOfLIMMem = NULL; // start of expanded memory
+ULONG HolderBlockOffset; // holder block offset
+
+LOCAL HANDLE LIMSectionHandle;
+LOCAL HANDLE processHandle = NULL;
+
+LOCAL ULONG X86NumRoms = 0;
+
+#define PAGE_SEG_SIZE 0x400 /* size of page expressed as segment */
+
+#define CONFIG_DATA_STRING L"Configuration Data"
+#define KEY_VALUE_BUFFER_SIZE 2048
+
+#define EMMBASE 0xd0000
+#define EMMTOP 0xe0000
+
+#define SECTION_NAME L"\\BaseNamedObjects\\LIMSection"
+#define SECTION_NAME_LEN sizeof(SECTION_NAME)
+
+typedef struct _BIOS_BLOCK {
+ ULONG PhysicalAddress;
+ ULONG SizeInByte;
+} BIOS_BLOCK;
+
+
+/*
+Defines are:
+ EM_loads(from, to, length), copies length bytes from intel 24 bit
+ address from, to host 32 bit address to
+ EM_stores(to, from, length), copies length bytes from host 32 bit
+ address from to intel 24 bit address to
+ EM_moves(from, to, length), copies length bytes from intel 24 bit
+ address from to intel 24 bit address to
+ EM_memcpy(to, from, length), copies length bytes from host 32 bit
+ address from to host 32 bit address to
+*/
+
+
+#define EM_loads(from, to, length) memcpy(to, get_byte_addr(from), length)
+#define EM_stores(to, from, length) \
+ RtlCopyMemory(get_byte_addr(to), from, length)
+#define EM_moves(from,to,length) \
+ RtlMoveMemory(get_byte_addr(to), get_byte_addr(from), length)
+#define EM_memcpy(to, from, length) \
+ RtlMoveMemory(to, from, length)
+
+/*
+===========================================================================
+
+FUNCTION : host_initialise_EM
+
+PURPOSE : allocates the area of memory that is used for
+ expanded memory and sets up an area of memory to be used
+ for the logical pagemap allocation table.
+
+
+RETURNED STATUS : SUCCESS - memory allocated successfully
+ FAILURE - unable to allocate required space
+
+DESCRIPTION :
+
+
+=========================================================================
+*/
+int host_initialise_EM(short size)
+/* IN short size size of area required in megabytes */
+{
+ UTINY *pagemap_ptr; /* temp ptr. to logical pagemap */
+ int i; /* loop counter */
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES objAttribs;
+ LARGE_INTEGER secSize;
+ ULONG viewSize;
+ USHORT PageSegment, Pages;
+ LONG EM_size;
+
+ SAVED UNICODE_STRING LIMSectionName =
+ {
+ SECTION_NAME_LEN,
+ SECTION_NAME_LEN,
+ SECTION_NAME
+ };
+
+
+ /* Nobody should call this function with size 0 */
+ ASSERT(size != 0);
+
+ EM_pagemap_address = &EM_pagemap[0];
+
+ /* initialise pagemap to 0's */
+
+ pagemap_ptr = EM_pagemap_address;
+ for(i = 0; i < 8*32; i++)
+ *pagemap_ptr++ = 0;
+
+ EM_size = ((long) size) * 0x100000;
+
+ if (!(processHandle = NtCurrentProcess()))
+ {
+ assert0(NO, "host_initialise_EM: cant get process handle");
+ return(FAILURE);
+ }
+
+ // create section for LIM
+
+ /* Fill the fields of the OBJECT_ATTRIBUTES structure. */
+ InitializeObjectAttributes(&objAttribs,
+ NULL, // was &LIMSectionName, but null means private
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ /* Create the section. EMM_PAGE_SIZE for holder page */
+ secSize.LowPart = EM_size + EMM_PAGE_SIZE;
+ secSize.HighPart = 0;
+ HolderBlockOffset = EM_size;
+
+ // improvement - just reserve & commit as needed...
+ status = NtCreateSection(&LIMSectionHandle,
+ SECTION_MAP_WRITE|SECTION_MAP_EXECUTE,
+ &objAttribs,
+ &secSize,
+ PAGE_EXECUTE_READWRITE,
+ SEC_COMMIT,
+ NULL);
+ if (!NT_SUCCESS(status))
+ {
+ assert1(NO, "host_initialise_EM: LIM section creation failed (%x)", status);
+ return(FAILURE);
+ }
+
+ /* Map the section to the process' address space. */
+ BaseOfLIMMem = NULL;
+ viewSize = 0;
+
+ status = NtMapViewOfSection(LIMSectionHandle,
+ processHandle,
+ (PVOID *) &BaseOfLIMMem,
+ 0,
+ 0,
+ NULL,
+ &viewSize,
+ ViewUnmap,
+ 0, // do we need mem_top_down??
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(status))
+ {
+ assert1(NO, "host_initialise_EM: can't map view of LIM section (%x)", status);
+ return(FAILURE);
+ }
+
+ /* acquire page frame addresss space from UMB list */
+ if (!GetUMBForEMM()) {
+ host_deinitialise_EM();
+ return FAILURE;
+ }
+
+ /* attach page to holder so that we won't get killed if applications
+ * try to touch the page frames without mapping
+ */
+
+ for (Pages = get_no_phys_pages(); Pages ; Pages--) {
+ PageSegment = get_page_seg((unsigned char)(Pages - 1));
+ if (PageSegment <= 640 * 1024 / 16)
+ continue;
+ if (!hold_lim_page(PageSegment))
+ return FAILURE;
+
+ }
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_deinitialise_EM
+
+PURPOSE : frees the area of memory that was used for
+ expanded memory and memory used
+ for the logical pagemap allocation table.
+
+
+RETURNED STATUS : SUCCESS - memory freed successfully
+ FAILURE - error ocurred in freeing memory
+
+DESCRIPTION :
+
+
+=========================================================================
+*/
+int host_deinitialise_EM()
+{
+ ULONG len = 0x10000;
+ NTSTATUS status;
+
+ if (BaseOfLIMMem != NULL)
+ {
+ if (processHandle == NULL)
+ {
+ //As shutting down anyway then fail silently
+ return(FAILURE);
+ }
+
+ // lose section from our memory space
+ status = NtUnmapViewOfSection(processHandle, BaseOfLIMMem);
+ if (!NT_SUCCESS(status))
+ {
+ //As shutting down anyway then fail silently
+ return(FAILURE);
+ }
+
+ status = NtClose(LIMSectionHandle); // delete section
+ if (!NT_SUCCESS(status))
+ {
+ //As shutting down anyway then fail silently
+ return(FAILURE);
+ }
+
+ return(SUCCESS);
+ }
+}
+
+
+
+/*
+===========================================================================
+
+FUNCTION : host_allocate_storage
+
+PURPOSE : allocates an area of memory of requested size, to be
+ used as a general data storage area. The area is
+ to zeros.
+
+RETURNED STATUS : storage_ID - (in this case a pointer)
+ NULL - failure to allocate enough space.
+
+
+DESCRIPTION : returns memory initialised to zeros.
+ The storage ID returned is a value used to later reference
+ the storage area allocated. The macro USEBLOCK in
+ "host_emm.h" is used by the manager routines to convert
+ this ID into a char pointer
+
+=========================================================================
+*/
+long host_allocate_storage(int no_bytes)
+/* IN int no_bytes no. of bytes required */
+{
+ // should replace this (?) - dissasembling calloc seems to
+ // indicate it uses win funx...
+ return ((long)calloc(1, no_bytes));
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_free_storage
+
+PURPOSE : frees the area of memory that was used for
+ data storage
+
+
+RETURNED STATUS : SUCCESS - memory freed successfully
+ FAILURE - error ocurred in freeing memory
+
+DESCRIPTION : In this implementation storage_ID is simply a pointer
+
+
+=========================================================================
+*/
+int host_free_storage(long storage_ID)
+/* IN long storage_ID ptr to area of memory */
+{
+ if(storage_ID != (long)NULL)
+ free((char *)storage_ID);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_reallocate_storage
+
+PURPOSE : increases the size of memory allocated, maintaining the
+ contents of the original memory block
+
+
+RETURNED STATUS : storage_ID - memory reallocated successfully
+ NULL - error ocurred in reallocating memory
+
+DESCRIPTION : In this implementation storage_ID is simply a pointer
+ Note the value of storage_ID returned may or may not be the
+ same as the value given
+
+=========================================================================
+*/
+long host_reallocate_storage(LONG storage_ID, int size, int new_size)
+/*
+ IN
+long storage_ID ptr to area of memory
+int size original size - not used in this version
+ new_size new size required
+*/
+{
+ return((long)realloc((char *)storage_ID, new_size));
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : hold_lim_page
+
+PURPOSE : Puts some memory in one of the LIM page gaps in 16 bit
+ memory. Ensures nothing else in the process gets that
+ via malloc.
+
+
+RETURNED STATUS : TRUE - mapping OK.
+
+DESCRIPTION : Mapping achieved by mapping correct page from section into
+ Intel memory
+=========================================================================
+*/
+BOOL hold_lim_page(USHORT segment)
+/* IN
+int page page (0-3) of LIM gap
+*/
+
+{
+ PVOID to;
+ LARGE_INTEGER sec_offset;
+ ULONG viewSize;
+ NTSTATUS status;
+
+ if (BaseOfLIMMem != NULL)
+ {
+ to = (PVOID)effective_addr(segment, (word)0);
+
+ sec_offset.LowPart = HolderBlockOffset;
+ sec_offset.HighPart = 0;
+
+ viewSize = EMM_PAGE_SIZE;
+
+ status = NtMapViewOfSection(LIMSectionHandle,
+ processHandle,
+ &to,
+ 0,
+ EMM_PAGE_SIZE,
+ &sec_offset,
+ &viewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE);
+ if (!NT_SUCCESS(status))
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ return(FALSE);
+ }
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_map_page
+
+PURPOSE : produces mapping from an Expanded Memory page to a
+ page in Intel physical address space
+
+
+RETURNED STATUS : SUCCESS - mapping completed succesfully
+ FAILURE - error ocurred in mapping
+
+DESCRIPTION : Mapping achieved by mapping correct page from section into
+ Intel memory
+=========================================================================
+*/
+int host_map_page(SHORT EM_page_no, USHORT segment)
+/* IN
+short EM_page_no Expanded Memory page to be mapped in
+unsigned short segment; segment in physical address space to map into
+*/
+
+{
+ PVOID to;
+ int tstpage;
+ LARGE_INTEGER sec_offset;
+ ULONG viewSize;
+ NTSTATUS status;
+
+ note_trace2(LIM_VERBOSE,"map page %d to segment 0x%4x", EM_page_no, segment);
+#ifdef EMM_DEBUG
+ printf("host_map_page, segment=%x, EMpage=%x\n",
+ segment, EM_page_no);
+#endif
+
+ if (BaseOfLIMMem != NULL)
+ {
+ to = (PVOID)effective_addr(segment, 0);
+
+ sec_offset.LowPart = EM_page_no * EMM_PAGE_SIZE;
+ sec_offset.HighPart = 0;
+
+ viewSize = EMM_PAGE_SIZE;
+
+ tstpage = (segment - get_base_address()) >> 10;
+
+ /* detach from EMM page section */
+ status = NtUnmapViewOfSection(processHandle, (PVOID)to);
+ if (!NT_SUCCESS(status))
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ return(FALSE);
+ }
+
+ if (processHandle == NULL)
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,0,__FILE__,__LINE__);
+ return(FAILURE);
+ }
+
+ /* attach to the section */
+ status = NtMapViewOfSection(LIMSectionHandle,
+ processHandle,
+ &to,
+ 0,
+ EMM_PAGE_SIZE,
+ &sec_offset,
+ &viewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(status))
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ return(FAILURE);
+ }
+ return(SUCCESS);
+ }
+ return(FAILURE);
+}
+
+/*
+===========================================================================
+
+FUNCTION : host_unmap_page
+
+PURPOSE :unmaps pages from Intel physical address space to an
+ Expanded Memory page
+
+RETURNED STATUS : SUCCESS - unmapping completed succesfully
+ FAILURE - error ocurred in mapping
+
+DESCRIPTION : Unmapping achieved by unampping view of section from
+ Intel memory
+
+=========================================================================
+*/
+int host_unmap_page(USHORT segment, SHORT EM_page_no)
+/* IN
+unsigned short segment Segment in physical address space to unmap.
+short EM_page_no Expanded Memory page currently mapped in
+*/
+{
+ PVOID from;
+ NTSTATUS status;
+ unsigned short phys_page_no;
+
+ note_trace2(LIM_VERBOSE,"unmap page %d from segment 0x%.4x\n",EM_page_no,segment);
+
+
+ from = (PVOID)effective_addr(segment, 0);
+
+#ifdef EMM_DEBUG
+ printf("host_unmap_page, segment=%x, EMpage=%x\n",
+ segment, EM_page_no);
+#endif
+
+ /* detach from the LIM section */
+ status = NtUnmapViewOfSection(processHandle, from);
+ if (!NT_SUCCESS(status))
+ {
+ DisplayErrorTerm(EHS_FUNC_FAILED,status,__FILE__,__LINE__);
+ return(FAILURE);
+ }
+
+ /* hold the block to avoid AV when applications touch unmapped pages */
+ if (segment < 640 * 1024 / 16) {
+ if (!HoldEMMBackFillMemory(segment * 16, EMM_PAGE_SIZE))
+ return FAILURE;
+ }
+ else {
+
+ if (!hold_lim_page(segment)) {
+ note_trace1(LIM_VERBOSE, "couldn't hold lim page %d",get_segment_page_no(segment));
+ return FAILURE;
+ }
+ }
+ return(SUCCESS);
+}
+
+/*
+===========================================================================
+
+FUNCTION : host_alloc_page
+
+PURPOSE : searches the pagemap looking for a free page, allocates
+ that page and returns the EM page no.
+
+RETURNED STATUS :
+ SUCCESS - Always see note below
+
+DESCRIPTION : Steps through the Expanded memory Pagemap looking for
+ a clear bit, which indicates a free page. When found,
+ sets that bit and returns the page number.
+ For access purposes the pagemap is divided into long
+ word(32bit) sections
+
+NOTE : The middle layer calling routine (alloc_page()) checks
+ that all pages have not been allocated and therefore in
+ this implementation the returned status will always be
+ SUCCESS.
+ However alloc_page still checks for a return status of
+ SUCCESS, as some implementations may wish to allocate pages
+ dynamically and that may fail.
+=========================================================================
+*/
+SHORT host_alloc_page()
+{
+ SHORT EM_page_no; /* page number returned */
+ LONG *ptr; /* ptr to 32 bit sections in */
+ /* pagemap */
+ SHORT i; /* index into 32 bit section */
+
+ ptr = (LONG *)EM_pagemap_address;
+ i =0;
+ EM_page_no = 0;
+
+ while(*ptr & (MSB >> i++))
+ {
+ EM_page_no++;
+
+ if(i == 32)
+ /*
+ * start on next section
+ */
+ {
+ ptr++;
+ i = 0;
+ }
+ }
+ /*
+ * Set bit to show that page is allocated
+ */
+ *ptr = *ptr | (MSB >> --i);
+
+ return(EM_page_no);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_free_page
+
+PURPOSE : marks the page indicated as being free for further
+ allocation
+
+RETURNED STATUS :
+ SUCCESS - Always - see note below
+
+DESCRIPTION : clears the relevent bit in the pagemap.
+
+ For access purposes the pagemap is divided into long
+ word(32bit) sections.
+
+NOTE : The middle layer calling routine (free_page()) always
+ checks for invalid page numbers so in this implementation
+ the routine will always return SUCCESS.
+ However free_page() still checks for a return of SUCCESS
+ as other implementations may wish to use it.
+=========================================================================
+*/
+int host_free_page(SHORT EM_page_no)
+/* IN SHORT EM_page_no page number to be cleared */
+{
+ LONG *ptr; /* ptr to 32 bit sections in */
+ /* pagemap */
+ SHORT i; /* index into 32 bit section */
+
+ /*
+ * Set pointer to correct 32 bit section and index to correct bit
+ */
+
+ ptr = (long *)EM_pagemap_address;
+ ptr += (EM_page_no / 32);
+ i = EM_page_no % 32;
+
+ /*
+ * clear bit
+ */
+ *ptr = *ptr & ~(MSB >> i);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_copy routines
+ host_copy_con_to_con()
+ host_copy_con_to_EM()
+ host_copy_EM_to_con()
+ host_copy_EM_to_EM()
+
+PURPOSE : copies between conventional and expanded memory
+
+
+RETURNED STATUS :
+ SUCCESS - Always - see note below
+
+DESCRIPTION :
+ The middle layer calling routine always checks for a
+ return of SUCCESS as other implementations may
+ return FAILURE.
+=========================================================================
+*/
+int host_copy_con_to_con(int length, USHORT src_seg, USHORT src_off, USHORT dst_seg, USHORT dst_off)
+
+/* IN
+int length number of bytes to copy
+
+USHORT src_seg source segment address
+ src_off source offset address
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ sys_addr from, to; /* pointers used for copying */
+
+ from = effective_addr(src_seg, src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_moves(from, to, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_con_to_EM(int length, USHORT src_seg, USHORT src_off, USHORT dst_page, USHORT dst_off)
+
+/* IN
+int length number of bytes to copy
+
+USHORT src_seg source segment address
+ src_off source offset address
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ UTINY *to;
+ sys_addr from;
+
+ from = effective_addr(src_seg, src_off);
+ to = (char *)BaseOfLIMMem + dst_page * EMM_PAGE_SIZE + dst_off;
+
+ EM_loads(from, to, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_EM_to_con(int length, USHORT src_page, USHORT src_off, USHORT dst_seg, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_page source page number
+ src_off source offset within page
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ UTINY *from;
+ sys_addr to;
+
+ from = (char *)BaseOfLIMMem + (src_page * EMM_PAGE_SIZE + src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_stores(to, from, length);
+
+ return(SUCCESS);
+}
+
+int host_copy_EM_to_EM(int length, USHORT src_page, USHORT src_off, USHORT dst_page, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_page source page number
+ src_off source offset within page
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ unsigned char *from, *to; /* pointers used for copying */
+
+ from = (char *)BaseOfLIMMem + src_page * EMM_PAGE_SIZE + src_off;
+ to = (char *)BaseOfLIMMem + dst_page * EMM_PAGE_SIZE + dst_off;
+
+ EM_memcpy(to, from, length);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_exchange routines
+ host_exchg_con_to_con()
+ host_exchg_con_to_EM()
+ host_exchg_EM_to_EM()
+
+PURPOSE : exchanges data between conventional and expanded memory
+
+
+RETURNED STATUS :
+ SUCCESS - Everything ok
+ FAILURE - Memory allocation failure
+
+DESCRIPTION :
+
+=========================================================================
+*/
+int host_exchg_con_to_con(int length, USHORT src_seg, USHORT src_off, USHORT dst_seg, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_seg source segment address
+ src_off source offset address
+ dst_seg destination segment address
+ dst_off destination offset address
+*/
+{
+ UTINY *temp, *pointer;/* pointers used for copying */
+ sys_addr to, from;
+
+ if (length <= 64*1024)
+ temp = sas_scratch_address(length);
+ else
+ if ((temp = (unsigned char *)host_malloc(length)) == NULL)
+ return(FAILURE);
+
+ pointer = temp;
+
+ from = effective_addr(src_seg, src_off);
+ to = effective_addr(dst_seg, dst_off);
+
+ EM_loads(from, pointer, length); /* source -> temp */
+ EM_moves(to, from, length); /* dst -> source */
+ EM_stores(to, pointer, length); /* temp -> dst */
+
+ if (length > 64*1024)
+ host_free(temp);
+
+ return(SUCCESS);
+}
+
+int host_exchg_con_to_EM(int length, USHORT src_seg, USHORT src_off, USHORT dst_page, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_seg source segment address
+ src_off source offset address
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ UTINY *to, *temp, *pointer;/* pointers used for copying */
+ sys_addr from;
+
+ //STF - performance improvement: if 4k aligned & >= 4k then can use
+ // (un)mapview to do exchange.
+
+ if (length <= 64*1024)
+ temp = sas_scratch_address(length);
+ else
+ if ((temp = (unsigned char *)host_malloc(length)) == NULL)
+ return(FAILURE);
+
+ pointer = temp;
+
+ from = effective_addr(src_seg, src_off);
+ to = (char *)BaseOfLIMMem + dst_page * EMM_PAGE_SIZE + dst_off;
+
+ EM_loads(from, pointer, length);
+ EM_stores(from, to, length);
+ EM_memcpy(to, pointer, length);
+
+ if (length > 64*1024)
+ host_free(temp);
+
+ return(SUCCESS);
+}
+
+int host_exchg_EM_to_EM(int length, USHORT src_page, USHORT src_off, USHORT dst_page, USHORT dst_off)
+/* IN
+int length number of bytes to copy
+
+USHORT src_page source page number
+ src_off source offset within page
+ dst_page destination page number
+ dst_off destination offset within page
+*/
+{
+ UTINY *from, *to, *temp, *pointer; /* pointers used for copying */
+
+ if (length <= 64*1024)
+ temp = sas_scratch_address(length);
+ else
+ if ((temp = (unsigned char *)host_malloc(length)) == NULL)
+ return(FAILURE);
+
+ pointer = temp;
+
+ from = (char *)BaseOfLIMMem + src_page * EMM_PAGE_SIZE + src_off;
+ to = (char *)BaseOfLIMMem + dst_page * EMM_PAGE_SIZE + dst_off;
+
+ EM_memcpy(pointer, from, length);
+ EM_memcpy(from, to, length);
+ EM_memcpy(to, pointer, length);
+
+ if (length > 64*1024)
+ host_free(temp);
+
+ return(SUCCESS);
+}
+
+
+/*
+===========================================================================
+
+FUNCTION : host_get_access_key
+
+PURPOSE : produces a random access key for use with LIM function 30
+ 'Enable/Disable OS/E Function Set Functions'
+
+RETURNED STATUS : none
+
+DESCRIPTION : Two 16 bit random values are required for the 'access key'
+ We use the microsecond field from the get time of day routine
+ to provide this.
+
+=========================================================================
+*/
+void host_get_access_key(USHORT access_key[2])
+/* OUT USHORT access_key[2] source segment address */
+{
+ // do you think we need to seed the random # gen?
+ access_key[0] = rand() & 0xffff;
+ access_key[1] = rand() & 0xffff;
+
+ return;
+}
+#endif /* MONITOR */
+#endif /* LIM */