summaryrefslogtreecommitdiffstats
path: root/private/mvdm/v86
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/v86
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/v86')
-rw-r--r--private/mvdm/v86/dirs24
-rw-r--r--private/mvdm/v86/monitor/i386/fastpm.asm357
-rw-r--r--private/mvdm/v86/monitor/i386/int.c454
-rw-r--r--private/mvdm/v86/monitor/i386/monitor.c1135
-rw-r--r--private/mvdm/v86/monitor/i386/monitorp.h221
-rw-r--r--private/mvdm/v86/monitor/i386/proflib.c930
-rw-r--r--private/mvdm/v86/monitor/i386/sas.c1551
-rw-r--r--private/mvdm/v86/monitor/i386/sources11
-rw-r--r--private/mvdm/v86/monitor/i386/spcstubs.c109
-rw-r--r--private/mvdm/v86/monitor/i386/thread.c338
-rw-r--r--private/mvdm/v86/monitor/makefile6
-rw-r--r--private/mvdm/v86/monitor/sources57
-rw-r--r--private/mvdm/v86/scaffold/i386/fakebop.c502
-rw-r--r--private/mvdm/v86/scaffold/i386/fakeinit.c123
-rw-r--r--private/mvdm/v86/scaffold/i386/fakekbd.c281
-rw-r--r--private/mvdm/v86/scaffold/i386/fakevid.c175
-rw-r--r--private/mvdm/v86/scaffold/i386/fun.h24
-rw-r--r--private/mvdm/v86/scaffold/i386/softpc.c442
-rw-r--r--private/mvdm/v86/scaffold/i386/sources6
-rw-r--r--private/mvdm/v86/scaffold/i386/stubs.c46
-rw-r--r--private/mvdm/v86/scaffold/i386/x86.h418
-rw-r--r--private/mvdm/v86/scaffold/i386/xbios.h123
-rw-r--r--private/mvdm/v86/scaffold/i386/xbiosdsk.h244
-rw-r--r--private/mvdm/v86/scaffold/i386/xbioskbd.h39
-rw-r--r--private/mvdm/v86/scaffold/i386/xbiosvid.h65
-rw-r--r--private/mvdm/v86/scaffold/i386/xguest.h459
-rw-r--r--private/mvdm/v86/scaffold/i386/xwincon.h186
-rw-r--r--private/mvdm/v86/scaffold/makefile6
-rw-r--r--private/mvdm/v86/scaffold/ntvdm.def90
-rw-r--r--private/mvdm/v86/scaffold/sources157
-rw-r--r--private/mvdm/v86/scaffold/vdm.icobin0 -> 766 bytes
-rw-r--r--private/mvdm/v86/scaffold/vdm.rc57
-rw-r--r--private/mvdm/v86/scaffold/wow.icobin0 -> 766 bytes
-rw-r--r--private/mvdm/v86/util/makefile56
-rw-r--r--private/mvdm/v86/util/quit.asm40
35 files changed, 8732 insertions, 0 deletions
diff --git a/private/mvdm/v86/dirs b/private/mvdm/v86/dirs
new file mode 100644
index 000000000..a9274c0f7
--- /dev/null
+++ b/private/mvdm/v86/dirs
@@ -0,0 +1,24 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+ Dave Hastings (daveh) 24-Apr-1991
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS= monitor
diff --git a/private/mvdm/v86/monitor/i386/fastpm.asm b/private/mvdm/v86/monitor/i386/fastpm.asm
new file mode 100644
index 000000000..e42959d04
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/fastpm.asm
@@ -0,0 +1,357 @@
+ title "Fast Protected Mode services"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; fastpm.asm
+;
+; Abstract:
+;
+; This module implements a fast entry to and exit from protected mode
+;
+; Author:
+;
+; Dave Hastings (daveh) 26-Jul-91
+;
+;--
+.386p
+
+include ks386.inc
+include callconv.inc
+include bop.inc
+include vint.inc
+include vdmtb.inc
+
+_TEXT SEGMENT PARA PUBLIC 'CODE'
+ ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING
+_TEXT ENDS
+
+_DATA SEGMENT DWORD PUBLIC 'DATA'
+ extrn _VdmTib:Dword
+
+ public _NTVDMpLockPrefixTable
+_NTVDMpLockPrefixTable label dword
+ dd offset FLAT:_ntvdmlock1
+ dd offset FLAT:_ntvdmlock2
+ dd 0
+
+_DATA ENDS
+
+_TEXT SEGMENT
+
+; Interrupt type definitions
+CPU_YODA_INT equ 4
+BIT_CPU_YODA_INT equ 0
+CPU_HW_RESET equ 0
+BIT_CPU_HW_RESET equ 1
+CPU_TIMER_TICK equ 1
+BIT_CPU_TIMER_TICK equ 2
+CPU_HW_INT equ 3
+BIT_CPU_HW_INT equ 3
+
+ page ,132
+ subttl "FastEnterPm"
+;++
+;
+; Routine Description:
+;
+; This routine is a faster way to enter 16 bit vdm protected mode.
+; Instead of making a system call, we just save the 32 bit state
+; into the VdmTib, restore the Vdm state from the VdmTib, and do
+; a far return to the application.
+;
+; Arguments:
+;
+; ss:sp + 4 = pointer to VdmTib
+;
+; Returns:
+;
+; nothing.
+;
+ assume DS:FLAT
+cPublicProc _FastEnterPm,0
+
+ push ebp
+ mov ebp,esp ; set up stack frame
+
+ push ebx ; free up reg for pointer
+ lea ebx,_VdmTib
+
+ ; translate the interrupt flag to the virtual interrupt flag
+
+ test [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
+ jz fe10
+
+_ntvdmlock1:
+ lock or dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
+ test dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_INTERRUPT_PENDING
+ jz fe20
+
+ ; set up event info for an interrupt acknowlege
+
+ mov word ptr [ebx].VtEventInfo.EiEvent,VdmIntAck
+ mov word ptr [ebx].VtEventInfo.EiInstructionSize,0
+ mov word ptr [ebx].VtEventInfo.EiIntAckInfo,0
+
+ pop ebx
+ mov esp,ebp
+ pop ebp
+ stdRET _FastEnterPm
+
+fe10:
+_ntvdmlock2:
+ lock and dword ptr ds:FIXED_NTVDMSTATE_LINEAR, NOT VDM_VIRTUAL_INTERRUPTS
+fe20:
+ mov [ebx].VtMonitorContext.CsEax,eax
+ mov eax,[ebp - 4]
+ mov [ebx].VtMonitorContext.CsEbx,eax
+ mov [ebx].VtMonitorContext.CsEcx,ecx
+ mov [ebx].VtMonitorContext.CsEdx,edx
+ mov [ebx].VtMonitorContext.CsEsi,esi
+ mov [ebx].VtMonitorContext.CsEdi,edi
+ mov eax,[ebp]
+ mov [ebx].VtMonitorContext.CsEbp,eax
+ mov eax,ebp
+
+ add eax,8 ; pop ebp and ret addr
+
+ mov [ebx].VtMonitorContext.CsEsp,eax
+ mov eax,[ebp + 4]
+ mov [ebx].VtMonitorContext.CsEip,eax
+ mov eax,cs
+ mov [ebx].VtMonitorContext.CsSegCs,eax
+ mov eax,ss
+ mov [ebx].VtMonitorContext.CsSegSs,eax
+ mov eax,ds
+ mov [ebx].VtMonitorContext.CsSegDs,eax
+ mov eax,es
+ mov [ebx].VtMonitorContext.CsSegEs,eax
+ mov eax,fs
+ mov [ebx].VtMonitorContext.CsSegFs,eax
+ mov eax,gs
+ mov [ebx].VtMonitorContext.CsSegGs,eax
+ pushfd
+ pop eax
+ mov [ebx].VtMonitorContext.CsEflags,eax
+
+ mov eax,[ebx].VtVdmContext.CsSegSs
+ mov es,eax
+ mov edi,[ebx].VtVdmContext.CsEsp ; es:edi -> stack
+ lar eax,eax
+ test eax,400000h ; big?
+ jnz fe30
+
+ movzx edi,di
+fe30: mov eax,[ebx].VtVdmContext.CsEflags
+ sub edi,4
+ mov es:[edi],eax ; push Eflags
+ mov eax,[ebx].VtVdmContext.CsSegCs
+ sub edi,4
+ mov es:[edi],eax ; push cs
+ mov eax,[ebx].VtVdmContext.CsEip
+ sub edi,4
+ mov es:[edi],eax ; push ip
+ sub edi,4
+ mov eax,[ebx].VtVdmContext.CsEbp ; push ebp
+ mov es:[edi],eax
+
+fe40: push es
+ push edi ; push ss:esp for lss esp
+ mov eax,esp ; save sp for pushad
+
+ ; simulate pushad
+ push dword ptr [ebx].VtVdmContext.CsEax
+ push dword ptr [ebx].VtVdmContext.CsEcx
+ push dword ptr [ebx].VtVdmContext.CsEdx
+ push dword ptr [ebx].VtVdmContext.CsEbx
+ push eax
+ push ebp ; save pointer to stack frame
+ push dword ptr [ebx].VtVdmContext.CsEsi
+ push dword ptr [ebx].VtVdmContext.CsEdi
+
+ ; push seg regs
+ push dword ptr [ebx].VtVdmContext.CsSegFs
+ push dword ptr [ebx].VtVdmContext.CsSegGs
+ push dword ptr [ebx].VtVdmContext.CsSegDs
+ push dword ptr [ebx].VtVdmContext.CsSegEs
+
+ ; set up VDM seg regs
+ pop es
+ pop ds
+ pop gs ; pop fs,gs of invalid selectors are trapped in ntoskrnl,
+ pop fs ; and handled by setting to zero
+
+ ; set up VDM general regs
+ popad
+
+ ; set up vdm stack
+ lss esp,[ebp - 12]
+
+ ; restore ebp
+ pop ebp
+
+ ; return to VDM
+ iretd
+stdENDP _FastEnterPm
+
+ page ,132
+ subttl "GetFastBopEntry"
+;++
+;
+; Routine Description:
+;
+; This routine supplies the address of the routine that segmented
+; protected mode code should call to switch to flat mode.
+;
+; Arguments:
+;
+; esp + 4 = pointer to VdmTib->VdmContext
+;
+; Returns:
+;
+; nothing.
+;
+ assume DS:FLAT
+cPublicProc _GetFastBopEntryAddress,1
+
+ push ebp
+ mov ebp,esp
+ push ebx
+ push eax
+ mov ebx,[ebp + 8]
+ mov [ebx].CsSegEs,cs
+ mov eax,offset FLAT:_FastLeavePm
+ mov word ptr [ebx].CsEbx,ax
+ shr eax,16
+ mov word ptr [ebx].CsEdx,ax
+ pop eax
+ pop ebx
+ mov esp,ebp
+ pop ebp
+ stdRET _GetFastBopEntryAddress
+
+stdENDP _GetFastBopEntryAddress
+
+ page ,132
+ subttl "FastLeavePm"
+;++
+;
+; Routine Description:
+;
+; This routine switches from the VDM context to the monitor context.
+;
+; Arguments:
+;
+; none
+;
+; Returns:
+;
+; executing with monitor context
+;
+ assume DS:Nothing,ES:Nothing,SS:Nothing
+ALIGN 16
+cPublicProc _FastLeavePm,0
+
+ push ebx
+
+ mov bx,ds
+ push bx ; so push and pop size same
+ mov bx,KGDT_R3_DATA OR RPL_MASK
+ mov ds,bx
+ assume ds:FLAT
+ lea ebx,_VdmTib ; get pointer to contexts
+ pushfd
+ mov dword ptr [ebx].VtVdmContext.CsEax,eax
+ pop eax
+ mov dword ptr [ebx].VtVdmContext.CsEFlags,eax
+ pop ax
+ mov word ptr [ebx].VtVdmContext.CsSegDs,ax
+ pop eax
+ mov dword ptr [ebx].VtVdmContext.CsEbx,eax
+ mov dword ptr [ebx].VtVdmContext.CsEcx,ecx
+ mov dword ptr [ebx].VtVdmContext.CsEdx,edx
+ mov dword ptr [ebx].VtVdmContext.CsEsi,esi
+ mov dword ptr [ebx].VtVdmContext.CsEdi,edi
+ mov dword ptr [ebx].VtVdmContext.CsEbp,ebp
+ mov word ptr [ebx].VtVdmContext.CsSegEs,es
+ mov word ptr [ebx].VtVdmContext.CsSegFs,fs
+ mov word ptr [ebx].VtVdmContext.CsSegGs,gs
+ pop eax
+ mov dword ptr [ebx].VtVdmContext.CsEip,eax
+ pop eax
+ mov word ptr [ebx].VtVdmContext.CsSegCs,ax
+ mov dword ptr [ebx].VtVdmContext.CsEsp,esp
+ mov word ptr [ebx].VtVdmContext.CsSegSs,ss
+
+ ; switch Stacks
+.errnz (CsEsp + 4 - CsSegSS)
+ lss esp, [ebx].VtMonitorContext.CsEsp
+
+ ; Now running on Monitor stack
+
+ ; set up event info
+ mov word ptr [ebx].VtEventInfo.EiEvent,VdmBop
+ mov dword ptr [ebx].VtEventInfo.EiInstructionSize,BOP_SIZE
+ mov ax,[ebx].VtVdmContext.CsSegCs
+ mov es,ax
+ ; BUGBUG 16 or 32 bit !!!!!
+ mov di,[ebx].VtVdmContext.CsEip
+ mov al,byte ptr es:[di]
+ movzx eax,al
+ mov [ebx].VtEventInfo.EiBopNumber,eax
+ sub di,2
+ mov word ptr [ebx].VtVdmContext.CsEip,di ; set up bop bias
+
+ ; set up for IRET
+ push dword ptr [ebx].VtMonitorContext.CsEFlags
+ push dword ptr [ebx].VtMonitorContext.CsSegCs
+ push dword ptr [ebx].VtMonitorContext.CsEip
+
+ ; simulate pushad
+ mov eax,esp
+ push dword ptr [ebx].VtMonitorContext.CsEax
+ push dword ptr [ebx].VtMonitorContext.CsEcx
+ push dword ptr [ebx].VtMonitorContext.CsEdx
+ push dword ptr [ebx].VtMonitorContext.CsEbx
+ push eax
+ push dword ptr [ebx].VtMonitorContext.CsEbp
+ push dword ptr [ebx].VtMonitorContext.CsEsi
+ push dword ptr [ebx].VtMonitorContext.CsEdi
+
+ ; push seg regs
+ push dword ptr [ebx].VtMonitorContext.CsSegFs
+ push dword ptr [ebx].VtMonitorContext.CsSegGs
+ push dword ptr [ebx].VtMonitorContext.CsSegDs
+ push dword ptr [ebx].VtMonitorContext.CsSegEs
+
+ test ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS
+ jz fl10
+
+ or [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK
+ jmp fl20
+
+fl10: and dword ptr [ebx].VtVdmContext.CsEFlags, NOT EFLAGS_INTERRUPT_MASK
+fl20:
+ ; set up Monitor seg regs
+ pop es
+ pop ds
+ pop gs
+ pop fs
+
+ ; set up Monitor general regs
+ popad
+
+ xor eax,eax ; indicate success
+ ; return
+ iretd
+stdENDP _FastLeavePm
+
+_TEXT ends
+ end
+
+
+
+
+
diff --git a/private/mvdm/v86/monitor/i386/int.c b/private/mvdm/v86/monitor/i386/int.c
new file mode 100644
index 000000000..7912809da
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/int.c
@@ -0,0 +1,454 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ int.c
+
+Abstract:
+
+ This file contains interrupt support routines for the monitor
+
+Author:
+
+ Dave Hastings (daveh) 18-Apr-1992
+
+Notes:
+
+ The code in this file split out from monitor.c (18-Apr-1992)
+
+Revision History:
+
+--*/
+
+#include <monitorp.h>
+
+BOOL
+DpmiHwIntHandler(
+ ULONG IntNumber
+ );
+
+VOID
+IRQ13_Eoi(
+ int IrqLine,
+ int CallCount
+ );
+
+BOOLEAN IRQ13BeingHandled; // true until IRQ13 eoi'ed
+
+
+VOID
+InterruptInit(
+ VOID
+)
+/*++
+
+Routine Description:
+
+ This routine initializes the interrupt code for the monitor.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOL Bool;
+
+
+
+ Bool = RegisterEOIHook( 13, IRQ13_Eoi);
+ if (!Bool) {
+#if DBG
+ DbgPrint("NtVdm : Could not register IRQ 13 Eoi handler\n");
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+}
+
+VOID
+InterruptTerminate(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine frees the resoures allocated by InterruptInit
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+}
+
+
+VOID
+cpu_interrupt(
+ IN int Type,
+ IN int Number
+ )
+/*++
+
+Routine Description:
+
+ This routine causes an interrupt of the specified type to be raised
+ at the appropriate time.
+
+Arguments:
+
+ Type -- indicates the type of the interrupt. One of HARDWARE, TIMER, YODA,
+ or RESET
+
+ YODA and RESET are ignored
+
+Return Value:
+
+ None.
+
+Notes:
+
+--*/
+{
+ NTSTATUS Status;
+ HANDLE MonitorThread;
+
+ host_ica_lock();
+
+ if (Type == CPU_TIMER_TICK) {
+
+ //
+ // Set the VDM State for timer tick int pending
+ //
+ _asm {
+ mov eax, FIXED_NTVDMSTATE_LINEAR
+ lock or dword ptr [eax], VDM_INT_TIMER
+ }
+ } else if (Type == CPU_HW_INT) {
+
+ if (*pNtVDMState & VDM_INT_HARDWARE) {
+ goto EarlyExit;
+ }
+
+ //
+ // Set the VDM State for Hardware Int pending
+ //
+ _asm {
+ mov eax, FIXED_NTVDMSTATE_LINEAR
+ lock or dword ptr [eax], VDM_INT_HARDWARE
+ }
+ } else {
+#if DBG
+ DbgPrint("Monitor: Invalid Interrupt Type=%ld\n",Type);
+#endif
+ goto EarlyExit;
+ }
+
+ if (CurrentMonitorTeb != NtCurrentTeb()) {
+
+ /*
+ * Look up the ThreadHandle and Queue and InterruptApc
+ * If no ThreadHandle found do nothing
+ *
+ * The CurrentMonitorTeb may not be in the ThreadHandle\Teb list
+ * because upon task termination the the CurrentMonitorTeb variable
+ * cannot be updated until a new task is activated by the
+ * non-preemptive scheduler.
+ */
+ MonitorThread = ThreadLookUp(CurrentMonitorTeb);
+ if (MonitorThread) {
+ Status = NtVdmControl(VdmQueueInterrupt, (PVOID)MonitorThread);
+ // nothing much we can do if this fails
+#if DBG
+ if (!NT_SUCCESS(Status) && Status != STATUS_UNSUCCESSFUL) {
+ DbgPrint("NtVdmControl.VdmQueueInterrupt Status=%lx\n",Status);
+ }
+#endif
+ }
+
+ }
+
+EarlyExit:
+
+ host_ica_unlock();
+}
+
+
+
+
+VOID
+DispatchInterrupts(
+ )
+/*++
+
+Routine Description:
+
+ This routine dispatches interrupts to their appropriate handler routine
+ in priority order. The order is YODA, RESET, TIMER, HARDWARE. however
+ the YODA and RESET interrupts do nothing. Hardware interrupts are not
+ simulated unless the virtual interrupt enable flag is set. Flags
+ indicating which interrupts are pending appear in the pNtVDMState.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+Notes:
+
+--*/
+{
+
+ host_ica_lock();
+
+ // If any delayed interrupts have expired
+ // call the ica to restart interrupts
+ if (UndelayIrqLine) {
+ ica_RestartInterrupts(UndelayIrqLine);
+ }
+
+
+ if (*pNtVDMState & VDM_INT_TIMER) {
+ *pNtVDMState &= ~VDM_INT_TIMER;
+ host_ica_unlock(); // maybe don't need to unlock ? Jonle
+ host_timer_event();
+ host_ica_lock();
+ }
+
+ if ( getIF() && getMSW() & MSW_PE && *pNtVDMState & VDM_INT_HARDWARE) {
+ //
+ // Mark the vdm state as hw int dispatched. Must use the lock as
+ // kernel mode DelayedIntApcRoutine changes the bit as well
+ //
+ _asm {
+ mov eax,FIXED_NTVDMSTATE_LINEAR
+ lock and dword ptr [eax], NOT VDM_INT_HARDWARE
+ }
+ DispatchHwInterrupt();
+ }
+
+ host_ica_unlock();
+}
+
+
+
+
+VOID
+DispatchHwInterrupt(
+ )
+/*++
+
+Routine Description:
+
+ This routine dispatches hardware interrupts to the vdm in Protect Mode.
+ It calls the ICA to get the vector number and sets up the VDM stack
+ appropriately. Real Mode interrupt dispatching has been moved to the
+ kernel.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ int InterruptNumber;
+ ULONG IretHookAddress = 0L;
+
+ InterruptNumber = ica_intack(&IretHookAddress);
+ if (InterruptNumber == -1) { // skip spurious ints
+ return;
+ }
+
+ DpmiHwIntHandler(InterruptNumber);
+
+ if (IretHookAddress) {
+ BOOL Frame32 = (BOOL) VdmTib.PmStackInfo.Flags;
+ BOOL Stack32;
+ USHORT SegSs, VdmCs;
+ ULONG VdmSp, VdmEip;
+ PUCHAR VdmStackPointer;
+ ULONG StackOffset;
+
+ SegSs = getSS();
+ VdmStackPointer = Sim32GetVDMPointer(((ULONG)SegSs) << 16, 1, TRUE);
+
+ //
+ // Figure out how many bits of sp to use
+ //
+
+ if (Ldt[(SegSs & ~0x7)/sizeof(LDT_ENTRY)].HighWord.Bits.Default_Big) {
+ VdmSp = getESP();
+ StackOffset = 12;
+ } else {
+ VdmSp = getSP();
+ StackOffset = 6;
+ }
+
+ (PCHAR)VdmStackPointer += VdmSp;
+
+ //
+ // BUGBUG need to add stack limit checking 15-Nov-1993 Jonle
+ //
+ setESP(VdmSp - StackOffset);
+
+ //
+ // Push info for Iret hook handler
+ //
+ VdmCs = (USHORT) ((IretHookAddress & 0xFFFF0000) >> 16);
+ VdmEip = (IretHookAddress & 0xFFFF);
+
+ if (Frame32) {
+ *(PULONG)(VdmStackPointer - 4) = VdmTib.VdmContext.EFlags;
+ *(PULONG)(VdmStackPointer - 8) = (ULONG) VdmCs;
+ *(PULONG)(VdmStackPointer - 12) = VdmEip;
+ } else {
+ *(PUSHORT)(VdmStackPointer - 2) = (USHORT) VdmTib.VdmContext.EFlags;
+ *(PUSHORT)(VdmStackPointer - 4) = VdmCs;
+ *(PUSHORT)(VdmStackPointer - 6) = (USHORT) VdmEip;
+ }
+ }
+
+}
+
+
+VOID
+IRQ13_Eoi(
+ int IrqLine,
+ int CallCount
+ )
+{
+ UNREFERENCED_PARAMETER(IrqLine);
+ UNREFERENCED_PARAMETER(CallCount);
+
+ //
+ // if CallCount is less than Zero, then the interrupt request
+ // is being canceled.
+ //
+ if (CallCount < 0) {
+ return;
+ }
+
+ IRQ13BeingHandled = FALSE;
+}
+
+
+
+
+
+
+VOID
+MonitorEndIretHook(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PVOID VdmStackPointer;
+
+ if (IntelMSW & MSW_PE) {
+ BOOL Frame32 = (BOOL) VdmTib.PmStackInfo.Flags;
+ ULONG FrameSize;
+
+ if (Frame32) {
+ FrameSize = 12;
+ } else {
+ FrameSize = 6;
+ }
+
+ VdmStackPointer = Sim32GetVDMPointer(((ULONG)getSS() << 16),2,TRUE);
+
+ if (Ldt[(getSS() & ~0x7)/sizeof(LDT_ENTRY)].HighWord.Bits.Default_Big) {
+ (PCHAR)VdmStackPointer += getESP();
+ setESP(getESP() + FrameSize);
+ } else {
+ (PCHAR)VdmStackPointer += getSP();
+ setSP((USHORT) (getSP() + FrameSize));
+ }
+
+ if (Frame32) {
+
+ VdmTib.VdmContext.EFlags = *(PULONG)((PCHAR)VdmStackPointer + 8);
+ setCS(*(PUSHORT)((PCHAR)VdmStackPointer + 4));
+ VdmTib.VdmContext.Eip = *((PULONG)VdmStackPointer);
+
+ } else {
+
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & 0xFFFF0000) |
+ ((ULONG) *(PUSHORT)((PCHAR)VdmStackPointer + 4));
+ setCS(*(PUSHORT)((PCHAR)VdmStackPointer + 2));
+ VdmTib.VdmContext.Eip = (VdmTib.VdmContext.Eip & 0xFFFF0000) |
+ ((ULONG) *(PUSHORT)((PCHAR)VdmStackPointer));
+
+ }
+
+ } else {
+
+ VdmStackPointer = Sim32GetVDMPointer(((ULONG)getSS() << 16) | getSP(),2,FALSE);
+
+ setSP((USHORT) (getSP() + 6));
+
+ (USHORT)(VdmTib.VdmContext.EFlags) = *((PUSHORT)((PCHAR)VdmStackPointer + 4));
+ setCS(*((PUSHORT)((PCHAR)VdmStackPointer + 2)));
+ setIP(*((PUSHORT)VdmStackPointer));
+
+ }
+
+
+}
+
+VOID
+host_clear_hw_int()
+/*++
+
+Routine Description:
+
+ This routine "forgets" a previously requested hardware interrupt.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ /*
+ * We do nothing here to save a kernel call, because the
+ * interrupt if it hasn't been intacked yet or dispatched,
+ * will produce a harmless spurious int, which is dropped
+ * in the i386 interrupt dispatching code anyhow.
+ */
+}
diff --git a/private/mvdm/v86/monitor/i386/monitor.c b/private/mvdm/v86/monitor/i386/monitor.c
new file mode 100644
index 000000000..fded8dac0
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/monitor.c
@@ -0,0 +1,1135 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ Monitor.c
+Abstract:
+
+ This module is the user mode portion of the x86 monitor
+
+Author:
+
+ Dave Hastings (daveh) 16 Mar 1991
+
+Environment:
+
+ User mode only
+
+Revision History:
+ Sudeep Bharati (sudeepb) 31-Dec-1991
+
+ Converted all register manipulation interfaces to functions
+ from macros. This is to make ntvdm an exe as well as a dll,
+ and these register oriented routines are exported from ntvdm
+ for WOW32 and other installable VDDs.
+
+ Dave Hastings (daveh) 18-Apr-1992
+
+ Split into multiple files. Track current monitor thread by
+ Teb pointer. Register initial thread.
+
+ Sudeep Bharati (sudeepb) 22-Sep-1992
+
+ Added Page Fault Handling For installable VDD support
+
+--*/
+
+
+#include "monitorp.h"
+
+
+//
+// Internal functions
+//
+
+VOID
+EventVdmIo(
+ VOID
+ );
+
+VOID
+EventVdmStringIo(
+ VOID
+ );
+
+VOID
+EventVdmMemAccess(
+ VOID
+ );
+
+VOID
+EventVdmIntAck(
+ VOID
+ );
+
+VOID
+EventVdmBop(
+ VOID
+ );
+
+VOID
+EventVdmError(
+ VOID
+ );
+
+VOID
+EventVdmIrq13(
+ VOID
+ );
+
+VOID
+CreateProfile(
+ VOID
+ );
+
+VOID
+StartProfile(
+ VOID
+ );
+
+VOID
+StopProfile(
+ VOID
+ );
+
+VOID
+AnalyzeProfile(
+ VOID
+ );
+
+// [LATER] how do you prevent a struct from straddling a page boundary?
+VDM_TIB VdmTib;
+
+ULONG IntelBase; // base memory address
+ULONG VdmSize; // Size of memory in VDM
+ULONG IntelMSW; // Msw value (no msw in context)
+ULONG VdmDebugLevel; // used to control debugging
+PVOID CurrentMonitorTeb; // thread that is currently executing instructions.
+ULONG InitialBreakpoint = FALSE; // if set, breakpoint at end of cpu_init
+ULONG InitialVdmTibFlags = 0; // VdmTib flags picked up from here
+CONTEXT InitialContext; // Initial context for all threads
+BOOLEAN DebugContextActive = FALSE;
+ULONG VdmFeatureBits = 0; // bit to indicate special features
+
+extern PVOID NTVDMpLockPrefixTable;
+
+IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // Reserved
+ 0, // GlobalFlagsClear
+ 0, // GlobalFlagsSet
+ 0, // CriticalSectionTimeout (milliseconds)
+ 0, // DeCommitFreeBlockThreshold
+ 0, // DeCommitTotalFreeThreshold
+ &NTVDMpLockPrefixTable, // LockPrefixTable, defined in FASTPM.ASM
+ 0, 0, 0, 0, 0, 0, 0 // Reserved
+};
+
+// Bop dispatch table
+
+extern void (*BIOS[])();
+
+BOOLEAN ContinueExecution;
+
+//
+// Event Dispatch table
+//
+
+VOID (*EventDispatch[VdmMaxEvent])(VOID) = {
+ EventVdmIo,
+ EventVdmStringIo,
+ EventVdmMemAccess,
+ EventVdmIntAck,
+ EventVdmBop,
+ EventVdmError,
+ EventVdmIrq13
+ };
+
+// Debug control flags
+BOOLEAN fShowBop = FALSE;
+#if DBG
+BOOLEAN fBreakInDebugger = FALSE;
+LONG NumTasks = -1;
+#endif
+
+
+
+EXPORT
+VOID
+cpu_init(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is used to prepare the IEU for instruction simulation.
+ It will set the Intel registers to thier initial value, and perform
+ any implementation specific initialization necessary.
+
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NTSTATUS Status;
+
+ IntelMSW = 0x0; // bugbug use correct value for ET and MP
+ InitialVdmTibFlags |= RM_BIT_MASK;
+
+ VdmTib.VdmContext.SegGs = 0;
+ VdmTib.VdmContext.SegFs = 0;
+ VdmTib.VdmContext.SegEs = 0;
+ VdmTib.VdmContext.SegDs = 0;
+ VdmTib.VdmContext.SegCs = 0;
+ VdmTib.VdmContext.Eip = 0xFFF0L;
+ VdmTib.VdmContext.EFlags = 0x02L | EFLAGS_INTERRUPT_MASK;
+
+ VdmTib.MonitorContext.SegDs = KGDT_R3_DATA | RPL_MASK;
+ VdmTib.MonitorContext.SegEs = KGDT_R3_DATA | RPL_MASK;
+ VdmTib.MonitorContext.SegGs = 0;
+ VdmTib.MonitorContext.SegFs = KGDT_R3_TEB | RPL_MASK;
+
+ VdmTib.PrinterInfo.prt_State = NULL;
+ VdmTib.PrinterInfo.prt_Control = NULL;
+ VdmTib.PrinterInfo.prt_Status = NULL;
+ VdmTib.PrinterInfo.prt_HostState = NULL;
+ ASSERT(VDM_NUMBER_OF_LPT == 3);
+
+ VdmTib.PrinterInfo.prt_Mode[0] =
+ VdmTib.PrinterInfo.prt_Mode[1] =
+ VdmTib.PrinterInfo.prt_Mode[2] = PRT_MODE_NO_SIMULATION;
+
+ VdmTib.Size = sizeof(VDM_TIB);
+
+ //
+ // Find out if we are running with IOPL. We call the kernel
+ // rather than checking the registry ourselves, so that we can
+ // insure that both the kernel and ntvdm.exe agree. If they didn't,
+ // it would result in unnecssary trapping instructions. Whether or
+ // not Vdms run with IOPL only changes on reboot
+ //
+ Status = NtVdmControl(VdmFeatures, &VdmFeatureBits);
+
+#if DBG
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint(
+ "NTVDM: Could not find out whether to use IOPL, %lx\n",
+ Status
+ );
+ }
+#endif
+
+ //
+ // If we have fast v86 mode IF emulation set the bit that tells
+ // the 16 bit IF macros they know.
+ //
+ if (VdmFeatureBits & V86_VIRTUAL_INT_EXTENSIONS) {
+ InitialVdmTibFlags |= RI_BIT_MASK;
+ }
+
+ *pNtVDMState = InitialVdmTibFlags;
+
+ // Switch the npx back to 80 bit mode. Win32 apps start with
+ // 64-bit precision for compatibility across platforms, but
+ // DOS and Win16 apps expect 80 bit precision.
+ //
+
+ _asm fninit;
+
+ //
+ // We setup the InitialContext structure with the correct floating
+ // point and debug register configuration, and cpu_createthread
+ // uses this context to configure each 16-bit thread's floating
+ // point and debug registers.
+ //
+
+ InitialContext.ContextFlags = CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS;
+
+ Status = NtGetContextThread(
+ NtCurrentThread(),
+ &InitialContext
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NtVdm terminating : Could not get float/debug context for\n"
+ " initial thread, status %lx\n", Status);
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+
+ //
+ //
+ // Turn OFF em bit so that dos apps will work correctly.
+ //
+ // On machines without 387's the floating point flag will have been
+ // cleared.
+ //
+
+ InitialContext.ContextFlags = CONTEXT_FLOATING_POINT;
+ InitialContext.FloatSave.Cr0NpxState &= ~0x6; // CR0_EM | CR0_MP
+
+ //
+ // Do the rest of thread initialization
+ //
+ cpu_createthread( NtCurrentThread() );
+
+ InterruptInit();
+
+ if (InitialBreakpoint) {
+ DbgBreakPoint();
+ }
+
+}
+
+EXPORT
+VOID
+cpu_terminate(
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+
+Return Value:
+
+
+--*/
+{
+ InterruptTerminate();
+}
+
+EXPORT
+VOID
+cpu_simulate(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine causes the simulation of intel instructions to start.
+
+Arguments:
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NTSTATUS Status;
+ VDMEVENTINFO OldEventInfo;
+ CONTEXT OldMonitorContext;
+
+ OldEventInfo = VdmTib.EventInfo;
+ OldMonitorContext = VdmTib.MonitorContext;
+
+ ContinueExecution = TRUE;
+
+ CurrentMonitorTeb = NtCurrentTeb();
+
+ VdmTib.VdmContext.ContextFlags = CONTEXT_FULL;
+
+ while (ContinueExecution) {
+
+ ASSERT(CurrentMonitorTeb == NtCurrentTeb());
+ ASSERT(InterlockedIncrement(&NumTasks) == 0);
+
+ if (*pNtVDMState & VDM_INTERRUPT_PENDING) {
+ DispatchInterrupts();
+ }
+
+ // translate MSW bits into EFLAGS
+ if ( getMSW() & MSW_PE ) {
+ VdmTib.VdmContext.EFlags &= ~EFLAGS_V86_MASK;
+ Status = FastEnterPm();
+ } else {
+ VdmTib.VdmContext.EFlags |= EFLAGS_V86_MASK;
+ Status = NtVdmControl(VdmStartExecution,NULL);
+ }
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NTVDM: Could not start execution\n");
+#endif
+ return;
+ }
+
+ ASSERT(InterlockedDecrement(&NumTasks) < 0);
+
+#if DBG
+ if (fBreakInDebugger) {
+ fBreakInDebugger = 0;
+ DbgBreakPoint();
+ }
+#endif
+
+ // Translate Eflags value
+ ASSERT ((!((VdmTib.VdmContext.EFlags & EFLAGS_V86_MASK) &&
+ (getMSW() & MSW_PE))));
+
+ if ( VdmTib.VdmContext.EFlags & EFLAGS_V86_MASK ) {
+ VdmTib.VdmContext.EFlags &= ~EFLAGS_V86_MASK;
+ }
+
+ // bugbug does cs:eip wrap cause some kind of fault?
+ VdmTib.VdmContext.Eip += VdmTib.EventInfo.InstructionSize;
+
+ if (VdmTib.EventInfo.Event >= VdmMaxEvent) {
+#if DBG
+ DbgPrint("NTVDM: Unknown event type\n");
+ DbgBreakPoint();
+#endif
+ ContinueExecution = FALSE;
+ continue;
+ }
+
+ (*EventDispatch[VdmTib.EventInfo.Event])();
+
+ }
+
+
+ // set this back to true incase we are nested
+ ContinueExecution = TRUE;
+
+ //
+ // Restore the old Vdm tib info. This is necessary for the for the
+ // case where the application thread is suspended, and a host simulate is
+ // performed from another thread
+ //
+
+ VdmTib.EventInfo = OldEventInfo;
+ VdmTib.MonitorContext = OldMonitorContext;
+}
+
+
+VOID
+host_unsimulate(
+ )
+
+/*++
+
+Routine Description:
+
+ This routine causes execution of instructions in a VDM to stop.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ContinueExecution = FALSE;
+
+}
+
+
+VOID
+EventVdmIo(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function calls the appropriate io simulation routine.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (VdmTib.EventInfo.IoInfo.Size == 1) {
+ if (VdmTib.EventInfo.IoInfo.Read) {
+ inb(VdmTib.EventInfo.IoInfo.PortNumber,(half_word *)&(VdmTib.VdmContext.Eax));
+ } else {
+ outb(VdmTib.EventInfo.IoInfo.PortNumber,getAL());
+ }
+ } else if (VdmTib.EventInfo.IoInfo.Size == 2) {
+ if (VdmTib.EventInfo.IoInfo.Read) {
+ inw(VdmTib.EventInfo.IoInfo.PortNumber,(word *)&(VdmTib.VdmContext.Eax));
+ } else {
+ outw(VdmTib.EventInfo.IoInfo.PortNumber,getAX());
+ }
+ }
+#if DBG
+ else {
+ DbgPrint(
+ "NtVdm: Unimplemented IO size %d\n",
+ VdmTib.EventInfo.IoInfo.Size
+ );
+ DbgBreakPoint();
+ }
+#endif
+}
+
+VOID
+EventVdmStringIo(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function calls the appropriate io simulation routine.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVDMSTRINGIOINFO pvsio;
+ PUSHORT pIndexRegister;
+ USHORT Index;
+
+ // WARNING no 32 bit address support
+
+ pvsio = &VdmTib.EventInfo.StringIoInfo;
+
+ if (pvsio->Size == 1) {
+ if (pvsio->Read) {
+ insb((io_addr)pvsio->PortNumber,
+ (half_word *)Sim32GetVDMPointer(pvsio->Address, 1, ISPESET),
+ (word)pvsio->Count
+ );
+ pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Edi;
+ } else {
+ outsb((io_addr)pvsio->PortNumber,
+ (half_word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
+ (word)pvsio->Count
+ );
+ pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Esi;
+ }
+ } else if (pvsio->Size == 2) {
+ if (pvsio->Read) {
+ insw((io_addr)pvsio->PortNumber,
+ (word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
+ (word)pvsio->Count
+ );
+ pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Edi;
+ } else {
+ outsw((io_addr)pvsio->PortNumber,
+ (word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET),
+ (word)pvsio->Count
+ );
+ pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Esi;
+ }
+ } else {
+#if DBG
+ DbgPrint(
+ "NtVdm: Unimplemented IO size %d\n",
+ VdmTib.EventInfo.IoInfo.Size
+ );
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+ if (getDF()) {
+ Index = *pIndexRegister - (USHORT)(pvsio->Count * pvsio->Size);
+ }
+ else {
+ Index = *pIndexRegister + (USHORT)(pvsio->Count * pvsio->Size);
+ }
+
+ *pIndexRegister = Index;
+
+ if (pvsio->Rep) {
+ (USHORT)VdmTib.VdmContext.Ecx = 0;
+ }
+
+
+}
+
+VOID
+EventVdmIntAck(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called each time we have returned to monitor context
+ to dispatch interrupts. Its function is to check for AutoEoi and call
+ the ica to do a nonspecific eoi, when the ica adapter is in AEOI mode.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ int line;
+ int adapter;
+
+ if (VdmTib.EventInfo.IntAckInfo) {
+ if (VdmTib.EventInfo.IntAckInfo & VDMINTACK_SLAVE)
+ adapter = 1;
+ else
+ adapter = 0;
+ line = -1;
+
+ host_ica_lock();
+ ica_eoi(adapter,
+ &line,
+ (int)(VdmTib.EventInfo.IntAckInfo & VDMINTACK_RAEOIMASK)
+ );
+ host_ica_unlock();
+ }
+}
+
+
+VOID
+EventVdmBop(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine dispatches to the appropriate bop handler
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (VdmTib.EventInfo.BopNumber > MAX_BOP) {
+#if DBG
+ DbgPrint(
+ "NtVdm: Invalid BOP %lx\n",
+ VdmTib.EventInfo.BopNumber
+ );
+#endif
+ ContinueExecution = FALSE;
+ } else {
+#if DBG
+ if (fShowBop) {
+ DbgPrint("Ntvdm cpu_simulate : bop dispatch %x,%x\n",
+ VdmTib.EventInfo.BopNumber,
+ (ULONG)(*((UCHAR *)Sim32GetVDMPointer(
+ (VdmTib.VdmContext.SegCs << 16) | VdmTib.VdmContext.Eip,
+ 1,
+ ISPESET)))
+ );
+ }
+#endif
+ (*BIOS[VdmTib.EventInfo.BopNumber])();
+ CurrentMonitorTeb = NtCurrentTeb();
+ }
+}
+
+VOID
+EventVdmError(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine prints a message(debug only), and exits the vdm
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+#if DBG
+ DbgPrint(
+ "NtVdm: Error code %lx\n",
+ VdmTib.EventInfo.ErrorStatus
+ );
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ ContinueExecution = FALSE;
+}
+
+VOID
+EventVdmIrq13(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine simulates an IRQ 13 to the vdm
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ if (!IRQ13BeingHandled) {
+ IRQ13BeingHandled = TRUE;
+ ica_hw_interrupt(
+ ICA_SLAVE,
+ 5,
+ 1
+ );
+ }
+}
+
+
+VOID
+EventVdmMemAccess(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine will call the page fault handler routine which
+ is common to both x86 and mips.
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ // RWMode is 0 if read fault or 1 if write fault.
+
+ DispatchPageFault(
+ VdmTib.EventInfo.FaultInfo.FaultAddr,
+ VdmTib.EventInfo.FaultInfo.RWMode
+ );
+ CurrentMonitorTeb = NtCurrentTeb();
+}
+
+// Get and Set routines for intel registers.
+
+ULONG getEAX (VOID) { return (VdmTib.VdmContext.Eax); }
+USHORT getAX (VOID) { return ((USHORT)(VdmTib.VdmContext.Eax)); }
+UCHAR getAL (VOID) { return ((BYTE)(VdmTib.VdmContext.Eax)); }
+UCHAR getAH (VOID) { return ((BYTE)(VdmTib.VdmContext.Eax >> 8)); }
+ULONG getEBX (VOID) { return (VdmTib.VdmContext.Ebx); }
+USHORT getBX (VOID) { return ((USHORT)(VdmTib.VdmContext.Ebx)); }
+UCHAR getBL (VOID) { return ((BYTE)(VdmTib.VdmContext.Ebx)); }
+UCHAR getBH (VOID) { return ((BYTE)(VdmTib.VdmContext.Ebx >> 8)); }
+ULONG getECX (VOID) { return (VdmTib.VdmContext.Ecx); }
+USHORT getCX (VOID) { return ((USHORT)(VdmTib.VdmContext.Ecx)); }
+UCHAR getCL (VOID) { return ((BYTE)(VdmTib.VdmContext.Ecx)); }
+UCHAR getCH (VOID) { return ((BYTE)(VdmTib.VdmContext.Ecx >> 8)); }
+ULONG getEDX (VOID) { return (VdmTib.VdmContext.Edx); }
+USHORT getDX (VOID) { return ((USHORT)(VdmTib.VdmContext.Edx)); }
+UCHAR getDL (VOID) { return ((BYTE)(VdmTib.VdmContext.Edx)); }
+UCHAR getDH (VOID) { return ((BYTE)(VdmTib.VdmContext.Edx >> 8)); }
+ULONG getESP (VOID) { return (VdmTib.VdmContext.Esp); }
+USHORT getSP (VOID) { return ((USHORT)VdmTib.VdmContext.Esp); }
+ULONG getEBP (VOID) { return (VdmTib.VdmContext.Ebp); }
+USHORT getBP (VOID) { return ((USHORT)VdmTib.VdmContext.Ebp); }
+ULONG getESI (VOID) { return (VdmTib.VdmContext.Esi); }
+USHORT getSI (VOID) { return ((USHORT)VdmTib.VdmContext.Esi); }
+ULONG getEDI (VOID) { return (VdmTib.VdmContext.Edi); }
+USHORT getDI (VOID) { return ((USHORT)VdmTib.VdmContext.Edi); }
+ULONG getEIP (VOID) { return (VdmTib.VdmContext.Eip); }
+USHORT getIP (VOID) { return ((USHORT)VdmTib.VdmContext.Eip); }
+USHORT getCS (VOID) { return ((USHORT)VdmTib.VdmContext.SegCs); }
+USHORT getSS (VOID) { return ((USHORT)VdmTib.VdmContext.SegSs); }
+USHORT getDS (VOID) { return ((USHORT)VdmTib.VdmContext.SegDs); }
+USHORT getES (VOID) { return ((USHORT)VdmTib.VdmContext.SegEs); }
+USHORT getFS (VOID) { return ((USHORT)VdmTib.VdmContext.SegFs); }
+USHORT getGS (VOID) { return ((USHORT)VdmTib.VdmContext.SegGs); }
+ULONG getCF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_CARRY) ? 1 : 0); }
+ULONG getPF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_PARITY) ? 1 : 0); }
+ULONG getAF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_AUXILIARY) ? 1 : 0); }
+ULONG getZF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_ZERO) ? 1 : 0); }
+ULONG getSF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_SIGN) ? 1 : 0); }
+ULONG getTF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_TRAP) ? 1 : 0); }
+ULONG getIF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_INTERRUPT) ? 1 : 0); }
+ULONG getDF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_DIRECTION) ? 1 : 0); }
+ULONG getOF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_OVERFLOW) ? 1 : 0); }
+USHORT getMSW (VOID) { return ((USHORT)IntelMSW); }
+USHORT getSTATUS(VOID){ return (USHORT)VdmTib.VdmContext.EFlags; }
+ULONG getEFLAGS(VOID) { return VdmTib.VdmContext.EFlags; }
+USHORT getFLAGS(VOID) { return (USHORT)VdmTib.VdmContext.EFlags; }
+
+VOID setEAX (ULONG val) {
+ VdmTib.VdmContext.Eax = val;
+}
+
+VOID setAX (USHORT val) {
+ VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setAH (UCHAR val) {
+ VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFF00FF) |
+ ((ULONG)(val << 8) & 0x0000FF00);
+}
+
+VOID setAL (UCHAR val) {
+ VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFFFF00) |
+ ((ULONG)val & 0x000000FF);
+}
+
+VOID setEBX (ULONG val) {
+ VdmTib.VdmContext.Ebx = val ;
+}
+
+VOID setBX (USHORT val) {
+ VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setBH (UCHAR val) {
+ VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFF00FF) |
+ ((ULONG)(val << 8) & 0x0000FF00);
+}
+
+VOID setBL (UCHAR val) {
+ VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFFFF00) |
+ ((ULONG)val & 0x000000FF);
+}
+
+VOID setECX (ULONG val) {
+ VdmTib.VdmContext.Ecx = val ;
+}
+
+VOID setCX (USHORT val) {
+ VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setCH (UCHAR val) {
+ VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFF00FF) |
+ ((ULONG)(val << 8) & 0x0000FF00);
+}
+
+VOID setCL (UCHAR val) {
+ VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFFFF00) |
+ ((ULONG)val & 0x000000FF);
+}
+
+VOID setEDX (ULONG val) {
+ VdmTib.VdmContext.Edx = val ;
+}
+
+VOID setDX (USHORT val) {
+ VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setDH (UCHAR val) {
+ VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFF00FF) |
+ ((ULONG)(val << 8) & 0x0000FF00);
+}
+
+VOID setDL (UCHAR val) {
+ VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFFFF00) |
+ ((ULONG)val & 0x000000FF);
+}
+
+VOID setESP (ULONG val) {
+ VdmTib.VdmContext.Esp = val ;
+}
+
+VOID setSP (USHORT val) {
+ VdmTib.VdmContext.Esp = (VdmTib.VdmContext.Esp & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setEBP (ULONG val) {
+ VdmTib.VdmContext.Ebp = val;
+}
+
+VOID setBP (USHORT val) {
+ VdmTib.VdmContext.Ebp = (VdmTib.VdmContext.Ebp & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setESI (ULONG val) {
+ VdmTib.VdmContext.Esi = val ;
+}
+
+VOID setSI (USHORT val) {
+ VdmTib.VdmContext.Esi = (VdmTib.VdmContext.Esi & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+VOID setEDI (ULONG val) {
+ VdmTib.VdmContext.Edi = val ;
+}
+
+VOID setDI (USHORT val) {
+ VdmTib.VdmContext.Edi = (VdmTib.VdmContext.Edi & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setEIP (ULONG val) {
+ VdmTib.VdmContext.Eip = val ;
+}
+
+VOID setIP (USHORT val) {
+ VdmTib.VdmContext.Eip = (VdmTib.VdmContext.Eip & 0xFFFF0000) |
+ ((ULONG)val & 0x0000FFFF);
+}
+
+VOID setCS (USHORT val) {
+ VdmTib.VdmContext.SegCs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setSS (USHORT val) {
+ VdmTib.VdmContext.SegSs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setDS (USHORT val) {
+ VdmTib.VdmContext.SegDs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setES (USHORT val) {
+ VdmTib.VdmContext.SegEs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setFS (USHORT val) {
+ VdmTib.VdmContext.SegFs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setGS (USHORT val) {
+ VdmTib.VdmContext.SegGs = (ULONG) val & 0x0000FFFF ;
+}
+
+VOID setCF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_CARRY) |
+ (((ULONG)val << FLG_CARRY_BIT) & FLG_CARRY);
+}
+
+VOID setPF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_PARITY) |
+ (((ULONG)val << FLG_PARITY_BIT) & FLG_PARITY);
+}
+
+VOID setAF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_AUXILIARY) |
+ (((ULONG)val << FLG_AUXILIARY_BIT) & FLG_AUXILIARY);
+}
+
+VOID setZF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_ZERO) |
+ (((ULONG)val << FLG_ZERO_BIT) & FLG_ZERO);
+}
+
+VOID setSF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_SIGN) |
+ (((ULONG)val << FLG_SIGN_BIT) & FLG_SIGN);
+}
+
+VOID setIF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_INTERRUPT) |
+ (((ULONG)val << FLG_INTERRUPT_BIT) & FLG_INTERRUPT);
+}
+
+VOID setDF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_DIRECTION) |
+ (((ULONG)val << FLG_DIRECTION_BIT) & FLG_DIRECTION);
+}
+
+VOID setOF (ULONG val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_OVERFLOW) |
+ (((ULONG)val << FLG_OVERFLOW_BIT) & FLG_OVERFLOW);
+}
+
+VOID setMSW (USHORT val) {
+ IntelMSW = val ;
+}
+
+VOID setSTATUS(USHORT val) {
+ VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & 0xFFFF0000) | val;
+}
+//
+// The following is a private register function
+//
+
+ULONG getPE(){
+ return((IntelMSW & MSW_PE) ? 1 : 0);
+}
+
+
+PX86CONTEXT
+getIntelRegistersPointer(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Return Address on Intel Registers for WOW Fast Access
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Pointer to Intel Registers x86 Context Record
+
+
+--*/
+{
+ return &(VdmTib.VdmContext);
+}
+
+
+
+BOOLEAN MonitorInitializePrinterInfo(
+ WORD Ports,
+ PWORD PortTable,
+ PUCHAR State,
+ PUCHAR Control,
+ PUCHAR Status,
+ PUCHAR HostState)
+{
+ int i;
+
+ ASSERT (Ports == 3);
+ ASSERT (Status != NULL);
+
+ // only do this if the structure has not been initialized -- meaning
+ // the pointers can be set once.
+ if (NULL == VdmTib.PrinterInfo.prt_Status) {
+
+ VdmTib.PrinterInfo.prt_PortAddr[0] = PortTable[0];
+ VdmTib.PrinterInfo.prt_PortAddr[1] = PortTable[1];
+ VdmTib.PrinterInfo.prt_PortAddr[2] = PortTable[2];
+
+ VdmTib.PrinterInfo.prt_Handle[0] =
+ VdmTib.PrinterInfo.prt_Handle[1] =
+ VdmTib.PrinterInfo.prt_Handle[2] = NULL;
+
+
+ // primarily for dongle
+ VdmTib.PrinterInfo.prt_BytesInBuffer[0] =
+ VdmTib.PrinterInfo.prt_BytesInBuffer[1] =
+ VdmTib.PrinterInfo.prt_BytesInBuffer[2] = 0;
+
+ // primarily for simulating printer status read in kernel
+ VdmTib.PrinterInfo.prt_State = State;
+ VdmTib.PrinterInfo.prt_Control = Control;
+ VdmTib.PrinterInfo.prt_Status = Status;
+ VdmTib.PrinterInfo.prt_HostState = HostState;
+
+
+ // deal with mode carefully. VDD may have hooked printer ports
+ // before we get here. If the mode is undefined, we can
+ // safely initialize it to our default, otherwise, just leave
+ // it alone.
+ for (i = 0; i < 3; i++) {
+ if (PRT_MODE_NO_SIMULATION == VdmTib.PrinterInfo.prt_Mode[i])
+ VdmTib.PrinterInfo.prt_Mode[i] = PRT_MODE_SIMULATE_STATUS_PORT;
+ }
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+BOOLEAN MonitorEnablePrinterDirectAccess(WORD adapter, HANDLE handle, BOOLEAN Enable)
+{
+ ASSERT(VDM_NUMBER_OF_LPT > adapter);
+ if (Enable) {
+ // if the adapter has been allocated by a third party VDD,
+ // can't do direct io.
+ if (PRT_MODE_VDD_CONNECTED != VdmTib.PrinterInfo.prt_Mode[adapter]) {
+ VdmTib.PrinterInfo.prt_Mode[adapter] = PRT_MODE_DIRECT_IO;
+ VdmTib.PrinterInfo.prt_Handle[adapter] = handle;
+ // NtVdmControl(VdmPrinterDirectIoOpen, &adapter);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else {
+ // disabling direct i/o. reset it back to status port simulation
+ if (VdmTib.PrinterInfo.prt_Handle[adapter] == handle) {
+ NtVdmControl(VdmPrinterDirectIoClose, &adapter);
+ VdmTib.PrinterInfo.prt_Mode[adapter] = PRT_MODE_SIMULATE_STATUS_PORT;
+ VdmTib.PrinterInfo.prt_Handle[adapter] = NULL;
+ VdmTib.PrinterInfo.prt_BytesInBuffer[adapter] = 0;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+}
+
+BOOLEAN MonitorVddConnectPrinter(WORD Adapter, HANDLE hVdd, BOOLEAN Connect)
+{
+ if (VDM_NUMBER_OF_LPT <= Adapter)
+ return FALSE;
+ if (Connect) {
+ VdmTib.PrinterInfo.prt_Mode[Adapter] = PRT_MODE_VDD_CONNECTED;
+ VdmTib.PrinterInfo.prt_Handle[Adapter] = hVdd;
+ return TRUE;
+ }
+ else {
+ if (hVdd == VdmTib.PrinterInfo.prt_Handle[Adapter]) {
+ VdmTib.PrinterInfo.prt_Mode[Adapter] = PRT_MODE_SIMULATE_STATUS_PORT;
+ VdmTib.PrinterInfo.prt_Handle[Adapter] = NULL;
+ return TRUE;
+ }
+ else return FALSE;
+ }
+}
+
+BOOLEAN MonitorPrinterWriteData(WORD Adapter, BYTE Value)
+{
+ USHORT BytesInBuffer;
+
+ ASSERT(VDM_NUMBER_OF_LPT > Adapter);
+ BytesInBuffer = VdmTib.PrinterInfo.prt_BytesInBuffer[Adapter];
+ VdmTib.PrinterInfo.prt_Buffer[Adapter][BytesInBuffer] = Value;
+ VdmTib.PrinterInfo.prt_BytesInBuffer[Adapter]++;
+
+ return TRUE;
+}
diff --git a/private/mvdm/v86/monitor/i386/monitorp.h b/private/mvdm/v86/monitor/i386/monitorp.h
new file mode 100644
index 000000000..721c01c13
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/monitorp.h
@@ -0,0 +1,221 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ Monitorp.h
+
+Abstract:
+
+ This contains the function prototypes, constants, and types for
+ the monitor.
+
+Author:
+
+ Dave Hastings (daveh) 16 Mar 1991
+
+Revision History:
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <vdm.h>
+#include <vint.h>
+#include "bop.h"
+#include "softpc.h"
+//bugbug
+typedef unsigned int UINT;
+
+#include <nt_mon.h> // for softpc base definitions
+#include <nt_reset.h>
+#include <monregs.h>
+#include <vdmtib.h>
+
+#define EFLAGS_INTERRUPT_MASK 0x00000200L
+#define EFLAGS_V86_MASK 0x00020000L
+#define VDM_BASE_ADDRESS 0x00000001L
+
+
+#define RPL_MASK 3
+// Types borrowed from windef.h
+
+typedef unsigned char BYTE;
+
+// Memory type record
+
+typedef struct _Memory_Type {
+ struct _Memory_Type *Previous;
+ struct _Memory_Type *Next;
+ ULONG Start;
+ ULONG End;
+ half_word Type;
+} MEMTYPE, *PMEMTYPE;
+
+// private flags
+
+#define VDM_IDLE 0x00000001L
+
+// external data
+
+extern ULONG VdmFlags;
+extern ULONG VdmSize;
+extern LDT_ENTRY *Ldt;
+extern ULONG IntelBase; // base memory address
+extern ULONG VdmDebugLevel; // used to control debugging
+extern ULONG IntelMSW; // Msw value (no msw in context)
+extern ULONG VdmSize; // Size of memory in VDM
+extern PVOID CurrentMonitorTeb; // thread that is currently executing instructions.
+extern BOOLEAN IRQ13BeingHandled; // true until IRQ13 eoi'ed
+extern CONTEXT InitialContext; // Initial floating point context for all threads
+extern BOOLEAN DebugContextActive;
+
+#define MAX_BOP 256
+VOID reset(VOID);
+VOID dummy_int(VOID);
+VOID unexpected_int(VOID);
+VOID illegal_bop(VOID);
+VOID illegal_op_int(VOID);
+VOID print_screen(VOID);
+VOID time_int(VOID);
+VOID keyboard_int(VOID);
+VOID diskette_int(VOID);
+VOID video_io(VOID);
+VOID equipment(VOID);
+VOID memory_size(VOID);
+VOID disk_io(VOID);
+VOID rs232_io(VOID);
+VOID cassette_io(VOID);
+VOID keyboard_io(VOID);
+VOID printer_io(VOID);
+VOID rom_basic(VOID);
+VOID bootstrap(VOID);
+VOID time_of_day(VOID);
+VOID critical_region(VOID);
+VOID cmd_install(VOID);
+VOID cmd_load(VOID);
+VOID redirector(VOID);
+VOID ega_video_io(VOID);
+VOID MsBop0(VOID);
+VOID MsBop1(VOID);
+VOID MsBop2(VOID);
+VOID MsBop3(VOID);
+VOID MsBop4(VOID);
+VOID MsBop5(VOID);
+VOID MsBop6(VOID);
+VOID MsBop7(VOID);
+VOID MsBop8(VOID);
+VOID MsBop9(VOID);
+VOID MsBopA(VOID);
+VOID MsBopB(VOID);
+VOID MsBopC(VOID);
+VOID MsBopD(VOID);
+VOID MsBopE(VOID);
+VOID MsBopF(VOID);
+VOID emm_init(VOID);
+VOID emm_io(VOID);
+VOID return_from_call(VOID);
+VOID rtc_int(VOID);
+VOID re_direct(VOID);
+VOID D11_int(VOID);
+VOID int_287(VOID);
+VOID worm_init(VOID);
+VOID worm_io(VOID);
+VOID ps_private_1(VOID);
+VOID ps_private_2(VOID);
+VOID ps_private_3(VOID);
+VOID ps_private_4(VOID);
+VOID ps_private_5(VOID);
+VOID ps_private_6(VOID);
+VOID ps_private_7(VOID);
+VOID ps_private_8(VOID);
+VOID ps_private_9(VOID);
+VOID ps_private_10(VOID);
+VOID ps_private_11(VOID);
+VOID ps_private_12(VOID);
+VOID ps_private_13(VOID);
+VOID ps_private_14(VOID);
+VOID ps_private_15(VOID);
+VOID bootstrap1(VOID);
+VOID bootstrap2(VOID);
+VOID bootstrap3(VOID);
+VOID ms_windows(VOID);
+VOID msw_mouse(VOID);
+VOID mouse_install1(VOID);
+VOID mouse_install2(VOID);
+VOID mouse_int1(VOID);
+VOID mouse_int2(VOID);
+VOID mouse_io_language(VOID);
+VOID mouse_io_interrupt(VOID);
+VOID mouse_video_io(VOID);
+VOID switch_to_real_mode(VOID);
+VOID control_bop(VOID);
+VOID diskette_io(VOID);
+VOID host_unsimulate(VOID);
+VOID DispatchPageFault (ULONG,ULONG);
+
+
+NTSTATUS
+FastEnterPm(
+ );
+
+VOID
+DispatchInterrupts(
+ VOID
+ );
+
+VOID
+DispatchHwInterrupt(
+ );
+
+ULONG
+GetInterruptHandler(
+ ULONG InterruptNumber,
+ BOOLEAN ProtectedMode
+ );
+
+PVOID
+GetInterruptStack(
+ ULONG InterruptNumber,
+ PUSHORT StackSelector,
+ PUSHORT StackPointer,
+ BOOLEAN ProtectedMode
+ );
+
+
+VOID
+CpuOnetimeInit(
+ VOID
+ );
+
+VOID
+CpuOnetimeTerm(
+ VOID
+ );
+
+VOID
+cpu_createthread();
+
+VOID
+cpu_exitthread();
+
+HANDLE
+ThreadLookUp(
+ PVOID
+ );
+
+VOID
+cpu_exit();
+
+VOID
+InterruptInit(
+ VOID
+ );
+
+VOID
+InterruptTerminate(
+ VOID
+ );
diff --git a/private/mvdm/v86/monitor/i386/proflib.c b/private/mvdm/v86/monitor/i386/proflib.c
new file mode 100644
index 000000000..06276a820
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/proflib.c
@@ -0,0 +1,930 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ proflib.c
+
+Abstract:
+
+ This module contains the implementation of a rudimentry user-mode
+ profiler.
+
+Usage:
+
+ There are 4 routines, RtlInitializeProfile, RtlStartProfile,
+ RtlStopProfile, and RtlAnalyzeProfile. To initialize profiling
+ invoke RtlInitializeProfile, this routine is only called once and
+ goes through the address space looking for code regions of images
+ and DLLs. To start profiling call RtlStartProfile. To stop
+ profiling call RtlStopProfile. Note that RtlStartProfile and
+ RtlStopProfile can be called repeatedly to profile only key
+ "hot spots", For example:
+ RtlStartProfile ();
+ hot spot...
+ RtlStopProfile ();
+ ....
+ RtlStartProfile ();
+ hot spot...
+ RtlStopProfile ();
+
+ To analyze the results call RtlAnalyzeProfile. This too can
+ be called repeatedly (it stops profiling during the analysis
+ phase and does NOT restart profiling). It also does not
+ zero out the values after reporting.
+
+Author:
+
+ Lou Perazzoli (loup) 4-Oct-1990
+
+Revision History:
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <string.h>
+#include <stdio.h>
+#include <\nt\private\ntos\dll\ldrp.h>
+
+NTSTATUS
+InitializeKernelProfile ( VOID );
+
+#define PAGE_SIZE 4096
+
+typedef struct _PROFILE_BLOCK {
+ HANDLE Handle;
+ PVOID ImageBase; //actual base in image header
+ PULONG CodeStart;
+ ULONG CodeLength;
+ PULONG Buffer;
+ ULONG BufferSize;
+ ULONG TextNumber;
+ ULONG BucketSize;
+ PVOID MappedImageBase; //actual base where mapped locally.
+ PSZ ImageName;
+} PROFILE_BLOCK;
+
+
+#define MAX_PROFILE_COUNT 50
+
+PROFILE_BLOCK ProfileObject[MAX_PROFILE_COUNT];
+
+ULONG NumberOfProfileObjects = 0;
+PIMAGE_DEBUG_INFO KernelDebugInfo;
+
+//
+// Image name to perform kernel mode analysis upon.
+//
+
+#define IMAGE_NAME "\\SystemRoot\\ntoskrnl.exe"
+
+//
+// Define map data file if the produced data file should be
+// a mapped file (currently named "kernprof.dat").
+//
+
+// #define MAP_DATA_FILE
+
+//
+// Define map as image if the image to be profiled should be mapped
+// as an image rather than as data.
+//
+
+// #define MAP_AS_IMAGE
+
+#define MAX_PROFILE_COUNT 50
+
+extern ULONG ProfInt;
+
+NTSTATUS
+RtlInitializeProfile (
+ IN BOOLEAN KernelToo
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes profiling for the current process.
+
+Arguments:
+
+ KernelToo - Set to TRUE if kernel code should be profiled as
+ well as user code.
+
+Return Value:
+
+ Returns the status of the last NtCreateProfile.
+
+--*/
+
+{
+
+ NTSTATUS status, LocalStatus;
+ HANDLE CurrentProcessHandle;
+ ULONG BufferSize;
+ PVOID ImageBase;
+ ULONG CodeLength;
+ PULONG Buffer;
+ PPEB Peb;
+ PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
+ PSZ ImageName;
+ PLIST_ENTRY Next;
+ ULONG ExportSize, DebugSize;
+ PIMAGE_EXPORT_DIRECTORY ExportDirectory;
+ PIMAGE_DEBUG_DIRECTORY DebugDirectory;
+ PIMAGE_DEBUG_INFO DebugInfo;
+ BOOLEAN PreviousPrivState;
+
+ //
+ // Locate all the executables in the address and create a
+ // seperate profile object for each one.
+ //
+
+ CurrentProcessHandle = NtCurrentProcess();
+
+ Peb = NtCurrentPeb();
+
+ Next = Peb->Ldr->InMemoryOrderModuleList.Flink;
+ while ( Next != &Peb->Ldr->InMemoryOrderModuleList) {
+ LdrDataTableEntry
+ = (PLDR_DATA_TABLE_ENTRY) (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks));
+
+ ImageBase = LdrDataTableEntry->DllBase;
+ if ( Peb->ImageBaseAddress == ImageBase ) {
+ ImageName = "TheApplication";
+ } else {
+ ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(
+ ImageBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportSize);
+
+ ImageName = (PSZ)((ULONG)ImageBase + ExportDirectory->Name);
+ }
+ if (NumberOfProfileObjects > MAX_PROFILE_COUNT) {
+ break;
+ }
+
+ ProfileObject[NumberOfProfileObjects].ImageBase = ImageBase;
+ ProfileObject[NumberOfProfileObjects].ImageName = ImageName;
+ ProfileObject[NumberOfProfileObjects].MappedImageBase = ImageBase;
+
+ //
+ // Locate the code range and start profiling.
+ //
+
+ DebugDirectory = (PIMAGE_DEBUG_DIRECTORY)RtlImageDirectoryEntryToData(
+ ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_DEBUG, &DebugSize);
+
+ if (!DebugDirectory) {
+ DbgPrint ("RtlInitializeProfile : No debug directory\n");
+ return STATUS_INVALID_IMAGE_FORMAT;
+ }
+
+ DebugInfo = (PIMAGE_DEBUG_INFO)((ULONG)ImageBase + DebugDirectory->AddressOfRawData);
+
+ ProfileObject[NumberOfProfileObjects].CodeStart = (PULONG)((ULONG)ImageBase + DebugInfo->RvaToFirstByteOfCode);
+ CodeLength = (DebugInfo->RvaToLastByteOfCode - DebugInfo->RvaToFirstByteOfCode) - 1;
+ ProfileObject[NumberOfProfileObjects].CodeLength = CodeLength;
+
+ ProfileObject[NumberOfProfileObjects].TextNumber = 1;
+
+ //
+ // Analyze the size of the code and create a reasonably sized
+ // profile object.
+ //
+
+ BufferSize = (CodeLength >> 1) + 4;
+ Buffer = NULL;
+
+ status = NtAllocateVirtualMemory (CurrentProcessHandle,
+ (PVOID *)&Buffer,
+ 0,
+ &BufferSize,
+ MEM_RESERVE | MEM_COMMIT,
+ PAGE_READWRITE);
+
+ if (!NT_SUCCESS(status)) {
+ DbgPrint ("alloc VM failed %lx\n",status);
+ return status;
+ }
+
+
+ status = RtlAdjustPrivilege(
+ SE_PROF_SINGLE_PROCESS_PRIVILEGE,
+ TRUE, //Enable
+ FALSE, //not impersonating
+ &PreviousPrivState //Remember if it will need to be cleared
+ );
+
+ if (!NT_SUCCESS(status) || status == STATUS_NOT_ALL_ASSIGNED) {
+ DbgPrint("Enable system profile privilege failed - status 0x%lx\n",
+ status);
+ }
+
+
+ ProfileObject[NumberOfProfileObjects].Buffer = Buffer;
+ ProfileObject[NumberOfProfileObjects].BufferSize = BufferSize;
+ ProfileObject[NumberOfProfileObjects].BucketSize = 3;
+
+ status = NtCreateProfile (
+ &ProfileObject[NumberOfProfileObjects].Handle,
+ CurrentProcessHandle,
+ ProfileObject[NumberOfProfileObjects].CodeStart,
+ CodeLength,
+ ProfileObject[NumberOfProfileObjects].BucketSize,
+ ProfileObject[NumberOfProfileObjects].Buffer ,
+ ProfileObject[NumberOfProfileObjects].BufferSize,
+ ProfileTime,
+ (KAFFINITY)-1);
+
+ if (PreviousPrivState == FALSE) {
+ LocalStatus = RtlAdjustPrivilege(
+ SE_PROF_SINGLE_PROCESS_PRIVILEGE,
+ FALSE, //Disable
+ FALSE, //not impersonating
+ &PreviousPrivState //Don't care if it was already enabled
+ );
+ if (!NT_SUCCESS(LocalStatus) || LocalStatus == STATUS_NOT_ALL_ASSIGNED) {
+ DbgPrint("Disable system profile privilege failed - status 0x%lx\n",
+ LocalStatus);
+ }
+ }
+
+ if (status != STATUS_SUCCESS) {
+ DbgPrint("create profile %x failed - status %lx\n",
+ ProfileObject[NumberOfProfileObjects].ImageName,status);
+ return status;
+ }
+
+ NumberOfProfileObjects += 1;
+
+ Next = Next->Flink;
+ }
+
+ if (KernelToo) {
+
+ if (NumberOfProfileObjects > MAX_PROFILE_COUNT) {
+ return status;
+ }
+ status = InitializeKernelProfile();
+ }
+ return status;
+
+}
+NTSTATUS
+InitializeKernelProfile (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes profiling for the kernel for the
+ current process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the status of the last NtCreateProfile.
+
+--*/
+
+{
+
+ //BUGBUG daveh I think that the new working set size calculation is
+ // generating the number of pages, when the api expects
+ // the number of bytes.
+
+ STRING Name3;
+ IO_STATUS_BLOCK IoStatus;
+ HANDLE FileHandle, KernelSection;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PVOID ImageBase;
+ ULONG ViewSize;
+ ULONG CodeLength;
+ NTSTATUS status, LocalStatus;
+ HANDLE CurrentProcessHandle;
+ QUOTA_LIMITS QuotaLimits;
+ PVOID Buffer;
+ ULONG Cells;
+ ULONG BucketSize;
+ UNICODE_STRING Unicode;
+ ULONG DebugSize;
+ PVOID KernelBase;
+ PIMAGE_NT_HEADERS KernelNtHeaders;
+ PIMAGE_DEBUG_DIRECTORY DebugDirectory;
+ BOOLEAN PreviousPrivState;
+
+ RtlInitString (&Name3, IMAGE_NAME);
+ CurrentProcessHandle = NtCurrentProcess();
+
+ status = RtlAnsiStringToUnicodeString(&Unicode,(PANSI_STRING)&Name3,TRUE);
+ ASSERT(NT_SUCCESS(status));
+ InitializeObjectAttributes( &ObjectAttributes,
+ &Unicode,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ //
+ // Open the file as readable and executable.
+ //
+
+ status = NtOpenFile ( &FileHandle,
+ FILE_READ_DATA | FILE_EXECUTE,
+ &ObjectAttributes,
+ &IoStatus,
+ FILE_SHARE_READ,
+ 0L);
+ RtlFreeUnicodeString(&Unicode);
+
+ if (!NT_SUCCESS(status)) {
+ DbgPrint("open file failed status %lx\n", status);
+ NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS);
+ }
+
+ InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
+
+ //
+ // For normal images they would be mapped as an image, but
+ // the kernel has no debug section (as yet) information, hence it
+ // must be mapped as a file.
+ //
+
+ status = NtCreateSection (&KernelSection,
+ SECTION_MAP_EXECUTE,
+ &ObjectAttributes,
+ 0,
+ PAGE_READONLY,
+ SEC_IMAGE,
+ FileHandle);
+
+ if (!NT_SUCCESS(status)) {
+ DbgPrint("create image section failed status %lx\n", status);
+ return(status);
+ }
+
+ ViewSize = 0;
+
+ //
+ // Map a view of the section into the address space.
+ //
+
+ KernelBase = NULL;
+
+ status = NtMapViewOfSection (KernelSection,
+ CurrentProcessHandle,
+ (PVOID *)&KernelBase,
+ 0L,
+ 0,
+ NULL,
+ &ViewSize,
+ ViewUnmap,
+ 0,
+ PAGE_EXECUTE);
+
+ if (!NT_SUCCESS(status)) {
+ if (status != STATUS_IMAGE_NOT_AT_BASE) {
+ DbgPrint("map section status %lx base %lx size %lx\n", status,
+ KernelBase, ViewSize);
+ }
+ }
+
+ KernelNtHeaders = (PIMAGE_NT_HEADERS)RtlImageNtHeader(KernelBase);
+
+ ImageBase = (PVOID)KernelNtHeaders->OptionalHeader.ImageBase;
+
+ DebugDirectory = (PIMAGE_DEBUG_DIRECTORY)RtlImageDirectoryEntryToData(
+ KernelBase, TRUE, IMAGE_DIRECTORY_ENTRY_DEBUG, &DebugSize);
+
+ if (!DebugDirectory) {
+ DbgPrint("InitializeKernelProfile : No debug directory\n");
+ return STATUS_INVALID_IMAGE_FORMAT;
+ }
+
+ KernelDebugInfo = (PIMAGE_DEBUG_INFO)((ULONG)KernelBase + DebugDirectory->AddressOfRawData);
+ CodeLength = (KernelDebugInfo->RvaToLastByteOfCode - KernelDebugInfo->RvaToFirstByteOfCode) -1;
+
+ //
+ // Just create a 512K byte buffer.
+ //
+
+ ViewSize = 1024 * 512;
+ Buffer = NULL;
+
+ status = NtAllocateVirtualMemory (CurrentProcessHandle,
+ (PVOID *)&Buffer,
+ 0,
+ &ViewSize,
+ MEM_RESERVE | MEM_COMMIT,
+ PAGE_READWRITE);
+
+ if (!NT_SUCCESS(status)) {
+ DbgPrint ("alloc VM failed %lx\n",status);
+ NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS);
+ }
+
+ //
+ // Calculate the bucket size for the profile.
+ //
+
+ Cells = ((CodeLength / (ViewSize >> 2)) >> 2);
+ BucketSize = 2;
+
+ while (Cells != 0) {
+ Cells = Cells >> 1;
+ BucketSize += 1;
+ }
+
+ ProfileObject[NumberOfProfileObjects].Buffer = Buffer;
+ ProfileObject[NumberOfProfileObjects].MappedImageBase = KernelBase;
+ ProfileObject[NumberOfProfileObjects].BufferSize = 1 + (CodeLength >> (BucketSize - 2));
+ ProfileObject[NumberOfProfileObjects].CodeStart = (PULONG)((ULONG)ImageBase + KernelDebugInfo->RvaToFirstByteOfCode);
+ ProfileObject[NumberOfProfileObjects].CodeLength = CodeLength;
+ ProfileObject[NumberOfProfileObjects].TextNumber = 1;
+ ProfileObject[NumberOfProfileObjects].ImageBase = ImageBase;
+ ProfileObject[NumberOfProfileObjects].ImageName = "ntoskrnl";
+ ProfileObject[NumberOfProfileObjects].BucketSize = BucketSize;
+
+
+ //
+ // Increase the working set to lock down a bigger buffer.
+ //
+
+ status = NtQueryInformationProcess (CurrentProcessHandle,
+ ProcessQuotaLimits,
+ &QuotaLimits,
+ sizeof(QUOTA_LIMITS),
+ NULL );
+
+ if (!NT_SUCCESS(status)) {
+ DbgPrint ("query process info failed %lx\n",status);
+ NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS);
+ }
+
+ QuotaLimits.MaximumWorkingSetSize += ViewSize / PAGE_SIZE;
+ QuotaLimits.MinimumWorkingSetSize += ViewSize / PAGE_SIZE;
+
+ status = NtSetInformationProcess (CurrentProcessHandle,
+ ProcessQuotaLimits,
+ &QuotaLimits,
+ sizeof(QUOTA_LIMITS));
+ if (!NT_SUCCESS(status)) {
+ DbgPrint ("setting working set failed %lx\n",status);
+ return status;
+ }
+
+ status = RtlAdjustPrivilege(
+ SE_PROF_SINGLE_PROCESS_PRIVILEGE,
+ TRUE, //Enable
+ FALSE, //not impersonating
+ &PreviousPrivState //Remember if it will need to be cleared
+ );
+
+ if (!NT_SUCCESS(status) || status == STATUS_NOT_ALL_ASSIGNED) {
+ DbgPrint("Enable process profile privilege failed - status 0x%lx\n",
+ status);
+ }
+
+ status = NtCreateProfile (
+ &ProfileObject[NumberOfProfileObjects].Handle,
+ CurrentProcessHandle,
+ ProfileObject[NumberOfProfileObjects].CodeStart,
+ CodeLength,
+ ProfileObject[NumberOfProfileObjects].BucketSize,
+ ProfileObject[NumberOfProfileObjects].Buffer ,
+ ProfileObject[NumberOfProfileObjects].BufferSize,
+ ProfileTime,
+ (KAFFINITY)-1);
+
+ if (PreviousPrivState == FALSE) {
+ LocalStatus = RtlAdjustPrivilege(
+ SE_PROF_SINGLE_PROCESS_PRIVILEGE,
+ FALSE, //Disable
+ FALSE, //not impersonating
+ &PreviousPrivState //Don't care if it was already enabled
+ );
+ if (!NT_SUCCESS(LocalStatus) || LocalStatus == STATUS_NOT_ALL_ASSIGNED) {
+ DbgPrint("Disable system profile privilege failed - status 0x%lx\n",
+ LocalStatus);
+ }
+ }
+
+ if (status != STATUS_SUCCESS) {
+ DbgPrint("create kernel profile %s failed - status %lx\n",
+ ProfileObject[NumberOfProfileObjects].ImageName,status);
+ }
+
+ NumberOfProfileObjects += 1;
+
+ return status;
+}
+
+
+VOID
+RtlpWriteProfileLine(
+ IN HANDLE ProfileHandle,
+ IN PSZ Line,
+ IN int nbytes
+ )
+{
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ NtWriteFile(
+ ProfileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ Line,
+ (ULONG)nbytes,
+ NULL,
+ NULL
+ );
+
+}
+
+
+HANDLE
+RtlpOpenProfileOutputFile()
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES Obja;
+ HANDLE Handle;
+ UNICODE_STRING FileName;
+ IO_STATUS_BLOCK IoStatusBlock;
+ BOOLEAN TranslationStatus;
+ RTL_RELATIVE_NAME RelativeName;
+ PVOID FreeBuffer;
+
+
+ TranslationStatus = RtlDosPathNameToNtPathName_U(
+ L"\\profile.out",
+ &FileName,
+ NULL,
+ &RelativeName
+ );
+
+ if ( !TranslationStatus ) {
+ return NULL;
+ }
+ FreeBuffer = FileName.Buffer;
+
+ if ( RelativeName.RelativeName.Length ) {
+ FileName = *(PUNICODE_STRING)&RelativeName.RelativeName;
+ }
+ else {
+ RelativeName.ContainingDirectory = NULL;
+ }
+
+ InitializeObjectAttributes(
+ &Obja,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ RelativeName.ContainingDirectory,
+ NULL
+ );
+
+ Status = NtCreateFile(
+ &Handle,
+ FILE_APPEND_DATA | SYNCHRONIZE,
+ &Obja,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ FILE_OPEN_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0L
+ );
+
+ RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
+ if ( !NT_SUCCESS(Status) ) {
+ return NULL;
+ }
+
+ return Handle;
+}
+
+VOID
+RtlpDeleteProfileOutputFile()
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES Obja;
+ HANDLE Handle;
+ UNICODE_STRING FileName;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_DISPOSITION_INFORMATION Disposition;
+ BOOLEAN TranslationStatus;
+ RTL_RELATIVE_NAME RelativeName;
+ PVOID FreeBuffer;
+
+ TranslationStatus = RtlDosPathNameToNtPathName_U(
+ L"\\profile.out",
+ &FileName,
+ NULL,
+ &RelativeName
+ );
+
+ if ( !TranslationStatus ) {
+ return;
+ }
+
+ FreeBuffer = FileName.Buffer;
+
+ if ( RelativeName.RelativeName.Length ) {
+ FileName = *(PUNICODE_STRING)&RelativeName.RelativeName;
+ }
+ else {
+ RelativeName.ContainingDirectory = NULL;
+ }
+
+ InitializeObjectAttributes(
+ &Obja,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ RelativeName.ContainingDirectory,
+ NULL
+ );
+
+ //
+ // Open the file for delete access
+ //
+
+ Status = NtOpenFile(
+ &Handle,
+ (ACCESS_MASK)DELETE | SYNCHRONIZE,
+ &Obja,
+ &IoStatusBlock,
+ FILE_SHARE_DELETE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
+ );
+ RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer);
+ if ( !NT_SUCCESS(Status) ) {
+ return;
+ }
+
+ //
+ // Delete the file
+ //
+ Disposition.DeleteFile = TRUE;
+
+ Status = NtSetInformationFile(
+ Handle,
+ &IoStatusBlock,
+ &Disposition,
+ sizeof(Disposition),
+ FileDispositionInformation
+ );
+
+ NtClose(Handle);
+}
+
+
+
+
+NTSTATUS
+RtlStartProfile (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine starts all profile objects which have been initialized.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the status of the last NtStartProfile.
+
+--*/
+
+{
+ ULONG i;
+ NTSTATUS status;
+ QUOTA_LIMITS QuotaLimits;
+
+ NtSetIntervalProfile(ProfInt,ProfileTime);
+ RtlpDeleteProfileOutputFile();
+
+ for (i = 0; i < NumberOfProfileObjects; i++) {
+
+ status = NtStartProfile (ProfileObject[i].Handle);
+
+ if (status == STATUS_WORKING_SET_QUOTA) {
+
+ //
+ // Increase the working set to lock down a bigger buffer.
+ //
+
+ status = NtQueryInformationProcess (NtCurrentProcess(),
+ ProcessQuotaLimits,
+ &QuotaLimits,
+ sizeof(QUOTA_LIMITS),
+ NULL );
+
+ if (!NT_SUCCESS(status)) {
+ DbgPrint ("query process info failed %lx\n",status);
+ return status;
+
+ }
+
+ QuotaLimits.MaximumWorkingSetSize +=
+ 10 * PAGE_SIZE + ProfileObject[i].BufferSize;
+ QuotaLimits.MinimumWorkingSetSize +=
+ 10 * PAGE_SIZE + ProfileObject[i].BufferSize;
+
+ status = NtSetInformationProcess (NtCurrentProcess(),
+ ProcessQuotaLimits,
+ &QuotaLimits,
+ sizeof(QUOTA_LIMITS));
+ if (!NT_SUCCESS(status)) {
+ DbgPrint ("setting working set failed %lx\n",status);
+ return status;
+ }
+ status = NtStartProfile (ProfileObject[i].Handle);
+ }
+
+ if (status != STATUS_SUCCESS) {
+ DbgPrint("start profile %s failed - status %lx\n",
+ ProfileObject[i].ImageName, status);
+ return status;
+ }
+ }
+ return status;
+}
+NTSTATUS
+RtlStopProfile (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine stops all profile objects which have been initialized.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the status of the last NtStopProfile.
+
+--*/
+
+{
+ ULONG i;
+ NTSTATUS status;
+
+ for (i = 0; i < NumberOfProfileObjects; i++) {
+ status = NtStopProfile (ProfileObject[i].Handle);
+ if (status != STATUS_SUCCESS) {
+ DbgPrint("stop profile %s failed - status %lx\n",
+ ProfileObject[i].ImageName,status);
+ return status;
+ }
+ }
+ return status;
+}
+
+NTSTATUS
+RtlAnalyzeProfile (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine does the analysis of all the profile buffers and
+ correlates hits to the appropriate symbol table.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ RTL_SYMBOL_INFORMATION ThisSymbol;
+ RTL_SYMBOL_INFORMATION LastSymbol;
+ ULONG CountAtSymbol;
+ NTSTATUS Status;
+ ULONG Va;
+ HANDLE ProfileHandle;
+ CHAR Line[512];
+ int i,n;
+ PULONG Buffer, BufferEnd, Counter;
+
+
+ ProfileHandle = RtlpOpenProfileOutputFile();
+ ASSERT(ProfileHandle);
+
+ for (i = 0; i < NumberOfProfileObjects; i++) {
+ Status = NtStopProfile (ProfileObject[i].Handle);
+ }
+
+
+ //
+ // The new profiler
+ //
+
+ for (i = 0; i < NumberOfProfileObjects; i++) {
+
+ LastSymbol.Value = 0;
+ CountAtSymbol = 0;
+
+ //
+ // Sum the total number of cells written.
+ //
+
+ BufferEnd = ProfileObject[i].Buffer + (
+ ProfileObject[i].BufferSize / sizeof(ULONG));
+ Buffer = ProfileObject[i].Buffer;
+
+ for ( Counter = Buffer; Counter < BufferEnd; Counter += 1 ) {
+ if ( *Counter ) {
+
+ //
+ // Now we have an an address relative to the buffer
+ // base.
+ //
+
+ Va = (ULONG)((PUCHAR)Counter - (PUCHAR)Buffer);
+ Va = Va * ( 1 << (ProfileObject[i].BucketSize - 2));
+
+ //
+ // Add in the image base and the base of the
+ // code to get the Va in the image
+ //
+
+ Va = Va + (ULONG)ProfileObject[i].CodeStart;
+
+ Status = RtlLookupSymbolByAddress(
+ ProfileObject[i].ImageBase,
+ NULL,
+ (PVOID)Va,
+ 0x4000,
+ &ThisSymbol,
+ NULL
+ );
+ if ( NT_SUCCESS(Status) ) {
+ if ( LastSymbol.Value && LastSymbol.Value == ThisSymbol.Value ) {
+ CountAtSymbol += *Counter;
+ }
+ else {
+ if ( LastSymbol.Value ) {
+ if ( CountAtSymbol ) {
+ n= sprintf(Line,"%d,%s,%S\n",
+ CountAtSymbol,
+ ProfileObject[i].ImageName,
+ &LastSymbol.Name
+ );
+ RtlpWriteProfileLine(ProfileHandle,Line,n);
+ }
+ }
+ CountAtSymbol = *Counter;
+ LastSymbol = ThisSymbol;
+ }
+ }
+ }
+ }
+ if ( CountAtSymbol ) {
+ n= sprintf(Line,"%d,%s,%S\n",
+ CountAtSymbol,
+ ProfileObject[i].ImageName,
+ &LastSymbol.Name
+ );
+ RtlpWriteProfileLine(ProfileHandle,Line,n);
+ }
+ }
+
+ for (i = 0; i < NumberOfProfileObjects; i++) {
+ Buffer = ProfileObject[i].Buffer;
+ RtlZeroMemory(Buffer,ProfileObject[i].BufferSize);
+ }
+ NtClose(ProfileHandle);
+ return Status;
+}
diff --git a/private/mvdm/v86/monitor/i386/sas.c b/private/mvdm/v86/monitor/i386/sas.c
new file mode 100644
index 000000000..0549ad802
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/sas.c
@@ -0,0 +1,1551 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ Monitor.c
+Abstract:
+
+ This module is the user mode portion of the x86 monitor
+
+Author:
+
+ Dave Hastings (daveh) 16 Mar 1991
+
+Environment:
+
+ User mode only
+
+Revision History:
+ William Hsieh 10-10-1992 Added A20 wrapping support
+--*/
+
+#define VDD_INTEG 1
+#include "monitorp.h"
+#include <windows.h>
+#include <stdio.h>
+#include <malloc.h>
+
+// Tim Nov 92.
+void sas_connect_memory(
+ IN sys_addr Low,
+ IN sys_addr High,
+ IN int Type
+ );
+
+//BUGBUGBUGBUG Include file
+
+// from base\inc\sas.h
+/* memory types for sas */
+#define SAS_RAM 0
+#define SAS_VIDEO 1
+#define SAS_ROM 2
+#define SAS_WRAP 3
+#define SAS_INACCESSIBLE 4
+#define SAS_MAX_TYPE SAS_INACCESSIBLE
+
+#define SIXTYFOURK 0x10000L
+#define ONEMEGA 0x100000L
+
+void rom_init();
+void rom_checksum();
+void copyROM();
+
+USHORT get_lim_backfill_segment(void);
+BOOL HoldEMMBackfillMemory(ULONG Address, ULONG Size);
+
+#if DBG
+extern unsigned short get_emm_page_size(void);
+extern unsigned short get_intel_page_size(void);
+#endif
+
+/* SYNC THESE DEFINITIONS WITH BASE\EMM.H, or sas_init will assert */
+#define EMM_PAGE_SIZE 0x4000
+#define INTEL_PAGE_SIZE 0x1000
+
+typedef struct
+{
+ ULONG (*b_read) ();
+ ULONG (*w_read) ();
+ VOID (*str_read) ();
+} READ_POINTERS;
+
+// Internal Data
+PMEMTYPE MemType = NULL;
+
+// External Data
+extern READ_POINTERS read_pointers;
+
+// M variables used by video.lib
+
+host_addr Start_of_M_area; /* host addr (char *) of start of M */
+sys_addr Length_of_M_area; /* sys addr (long) offset of end of M */
+
+static HANDLE A20SectionHandle = NULL;
+static BOOL A20IsON = FALSE;
+static USHORT BackFillSegment;
+
+
+
+EXPORT
+VOID
+sas_init(
+ IN sys_addr Size
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the SAS module, and allocates the linear
+ address space for the VDM, and loads the ROM
+
+Arguments:
+
+ Size - Supplies the size of the VDMs linear address space.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ NTSTATUS Status;
+ ULONG ViewSize;
+ PVOID BaseAddress;
+ OBJECT_ATTRIBUTES A20ObjAttr;
+ LARGE_INTEGER SectionSize;
+ UCHAR SectionAnsiName[80];
+ WCHAR SectionUnicodeName[80];
+ UNICODE_STRING UnicodeString;
+ USHORT Pages;
+ ULONG BackFillBase;
+
+#define CONVENTIONAL_MEM_SECTION "\\BaseNamedObjects\\VdmConventionalMemory"
+
+ //
+ // Create a name for the Convetional memory section
+ //
+ sprintf(
+ SectionAnsiName,
+ "%s%d",
+ CONVENTIONAL_MEM_SECTION,
+ GetCurrentProcessId()
+ );
+
+ if (MultiByteToWideChar(0, 0, SectionAnsiName, -1, SectionUnicodeName,80)
+ == 0
+ ) {
+#if DBG
+ DbgBreakPoint();
+#endif
+ // host_error(EG_MALLOC_FAILURE,ERR_QUIT,"");
+ TerminateVDM();
+ }
+
+ RtlInitUnicodeString(&UnicodeString, SectionUnicodeName);
+
+ InitializeObjectAttributes(
+ &A20ObjAttr,
+ &UnicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ SectionSize.HighPart = 0L;
+ SectionSize.LowPart = 640 * 1024 + 64 * 1024;
+
+ Status = NtCreateSection(
+ &A20SectionHandle,
+ SECTION_MAP_WRITE|SECTION_MAP_EXECUTE,
+ &A20ObjAttr,
+ &SectionSize,
+ PAGE_EXECUTE_READWRITE,
+ SEC_RESERVE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ // bugbug -williamh
+ // we should pop up an approiate message before we
+ // terminate the vdm.
+#if DBG
+ DbgPrint("sas_init: can not create himem section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ VdmSize = Size;
+
+ //
+ // N.B. We expect that process creation has reserved the first 16 MB
+ // for us already. If not, then this won't work worth a darn
+
+ // free the first 640KB virtual address.
+ // This is done because it has been resevered before sas_init get called
+ BaseAddress = (PVOID)1;
+ ViewSize = 640 * 1024 - 1;
+ Status = NtFreeVirtualMemory(
+ NtCurrentProcess(),
+ &BaseAddress,
+ &ViewSize,
+ MEM_RELEASE
+ );
+
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("sas_init: cannot free 1st 640k virtual address, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+ BaseAddress =(PVOID) ONEMEGA;
+ ViewSize = SIXTYFOURK;
+ Status = NtFreeVirtualMemory(
+ NtCurrentProcess(),
+ &BaseAddress,
+ &ViewSize,
+ MEM_RELEASE
+ );
+
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("sas_init: can not free himem virtual address, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+ BaseAddress = (PVOID)VDM_BASE_ADDRESS;
+ ViewSize = SIXTYFOURK - (ULONG)VDM_BASE_ADDRESS;
+ SectionSize.HighPart = SectionSize.LowPart = 0;
+
+ Status = NtMapViewOfSection(
+ A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ ViewSize,
+ &SectionSize,
+ &ViewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)){
+#if DBG
+ DbgPrint("sas_init: can not map view of 1st 64K, status = %ls\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ BaseAddress = (PVOID) ONEMEGA;
+ ViewSize = SIXTYFOURK;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ ViewSize,
+ &SectionSize,
+ &ViewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)){
+#if DBG
+ DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+ // get emm back fill segment address from softpc
+ // we cut the backfill memory area into pieces in EMM_PAGE_SIZE unit.
+ // this is done so that EMM manager can grab the address space
+ // as EMM page frame.
+ // note that if EMM is disabled, the backfill segment will be
+ // (640 * 1024 / 16).
+
+ BackFillSegment = get_lim_backfill_segment();
+
+ ASSERT(BackFillSegment <= 640 * 1024 / 16);
+
+ //
+ // Map the rest of conventional memory
+ // only map up to the emm backfill segment.
+ BaseAddress = (PVOID) (64 * 1024);
+ ViewSize = BackFillSegment * 16 - 64 * 1024;
+ SectionSize.LowPart = 64 * 1024;
+ SectionSize.HighPart = 0;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ ViewSize,
+ &SectionSize,
+ &ViewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+ if (!NT_SUCCESS(Status)){
+#if DBG
+ DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+// if there are any backfill memory, map it to our section initially
+ if (BackFillSegment < 640 * 1024 / 16) {
+
+ /* make sure our constants are in sync with emm.h */
+#if DBG
+ ASSERT(EMM_PAGE_SIZE == get_emm_page_size());
+ ASSERT(INTEL_PAGE_SIZE == get_intel_page_size());
+#endif
+ if (!HoldEMMBackFillMemory(BackFillSegment * 16,
+ (640 * 1024) - BackFillSegment * 16)
+ ) {
+
+#if DBG
+ DbgPrint("sas_init: can not map backfill space, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ }
+
+ //
+ // Allocate ROM area
+ //
+ BaseAddress = (PVOID)(640 * 1024);
+ ViewSize = 384 * 1024;
+ Status = NtAllocateVirtualMemory(
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0L,
+ &ViewSize,
+ MEM_COMMIT,
+ PAGE_READWRITE
+ );
+ if (!NT_SUCCESS(Status)){
+#if DBG
+ DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+
+ A20IsON = FALSE;
+
+ Start_of_M_area = 0;
+ Length_of_M_area = VdmSize;
+ sas_connect_memory(0, VdmSize + 2*SIXTYFOURK -1, SAS_RAM);
+}
+
+#if VDD_INTEG
+
+EXPORT
+VOID
+sas_term(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Free memory prior to reallocing it
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+--*/
+{
+ PVOID BaseAddress;
+ NTSTATUS Status;
+ ULONG Size;
+
+ BaseAddress = (PVOID)VDM_BASE_ADDRESS;
+ Size = VdmSize;
+ Status = NtFreeVirtualMemory(
+ NtCurrentProcess(),
+ &BaseAddress,
+ &Size,
+ MEM_DECOMMIT);
+
+ if (!NT_SUCCESS(Status)) {
+ VDprint(VDP_LEVEL_ERROR,
+ ("SoftPc: NtDeCommitVirtualMemory failed !!!! Status = %lx\n",
+ Status));
+ VDbreak(VDB_LEVEL_ERROR);
+ }
+}
+
+
+EXPORT
+sys_addr
+sas_memory_size(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the size of Intel memory
+
+Arguments:
+
+ none
+
+Return Value:
+
+ size of intel memory
+
+--*/
+{
+ return(VdmSize);
+}
+
+
+EXPORT
+VOID
+sas_connect_memory(
+ IN sys_addr Low,
+ IN sys_addr High,
+ IN int Type
+ )
+/*++
+
+Routine Description:
+
+ This routine sets up a type record for the specified address region.
+ If the specified address region was a different type, it is changed to
+ the new type.
+
+Arguments:
+
+ Low -- the starting address of the region
+ High -- the ending address of the region
+ Type -- the type for the region, one of SAS_RAM, SAS_VIDEO, SAS_ROM,
+ SAS_WRAP, SAS_INACCESSIBLE
+
+Return Value:
+
+ None.
+--*/
+{
+ //bugbug do we handle new block contained in old block correctly?
+ PMEMTYPE Current, Previous, New, Temp;
+
+ if (!MemType) {
+ MemType = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
+ MemType->Previous = NULL;
+ MemType->Next = NULL;
+ MemType->Start = Low;
+ MemType->End = High;
+ MemType->Type = (half_word)Type;
+ return;
+ }
+
+ Current = MemType;
+ while (Current && (Low > Current->Start)) {
+ Previous = Current;
+ Current = Current->Next;
+ }
+
+ if ((Current) && (Low == Current->Start) && (High == Current->End)) {
+ Current->Type = (half_word)Type;
+ return;
+ }
+
+ if (!Current) {
+ // Block goes at end of list
+ New = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
+ Previous->Next = New;
+ New->Previous = Previous;
+ New->Start = Low;
+ New->End = High;
+ New->Type = (half_word)Type;
+ New->Next = NULL;
+ } else {
+ // Block goes in front of Current
+ New = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
+ New->Start = Low;
+ New->Type = (half_word)Type;
+ New->End = High;
+ New->Previous = Current->Previous;
+ New->Next = Current;
+ Current->Previous = New;
+ if (!New->Previous) {
+ MemType = New;
+ } else {
+ New->Previous->Next = New;
+ }
+ }
+
+
+ // Block overlaps one or more existing blocks
+
+ if (New->Previous) {
+ if (New->Previous->End > New->End) {
+ // block contained in exising block
+ Temp = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
+ Temp->Previous = New;
+ Temp->Next = New->Next;
+ New->Next = Temp;
+ if (Temp->Next) {
+ Temp->Next->Previous = Temp;
+ }
+ Temp->End = New->Previous->End;
+ New->Previous->End = New->Start - 1;
+ Temp->Start = New->End + 1;
+ Temp->Type = New->Previous->Type;
+ return;
+ } else if (New->Previous->End >= New->Start){
+ // block overlaps end of exising block
+ New->Previous->End = New->Start - 1;
+ }
+ }
+
+ // remove all blocks entirely contained in new block
+ while ((New->Next) && (New->Next->End <= New->End)) {
+ Temp = New->Next;
+ New->Next = New->Next->Next;
+ if (New->Next) {
+ New->Next->Previous = New;
+ }
+ free(Temp);
+ }
+
+ // remove portion of next block overlapping new block
+ if ((New->Next) && (New->Next->Start <= New->End)) {
+ New->Next->Start = New->End + 1;
+ }
+
+}
+
+
+EXPORT
+half_word
+sas_memory_type(
+ IN sys_addr Address
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the type of memory at a specific address
+
+Arguments:
+
+ Address -- linear address to return type for.
+
+Return Value:
+
+ the type for the region, one of SAS_RAM, SAS_VIDEO, SAS_ROM,
+ SAS_WRAP, SAS_INACCESSIBLE
+--*/
+{
+ PMEMTYPE Current;
+
+ if (Address > VdmSize) {
+ return SAS_INACCESSIBLE;
+ }
+
+ Current = MemType;
+ while (Current && !((Address >= Current->Start) &&
+ (Address <= Current->End))) {
+ Current = Current->Next;
+ }
+ if (!Current) {
+ return SAS_INACCESSIBLE;
+ }
+ return Current->Type;
+}
+
+
+
+EXPORT
+VOID
+sas_enable_20_bit_wrapping(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine causes memory addresses to wrap at 1MB
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS Status;
+ PVOID BaseAddress;
+ ULONG Size;
+ LARGE_INTEGER SectionOffset;
+ // if A20 line is off already do nothing
+ if (A20IsON == FALSE){
+ return;
+ }
+ BaseAddress = (PVOID)ONEMEGA;
+ Size = SIXTYFOURK;
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ BaseAddress
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("A20OFF: Unable to unmap view of section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ SectionOffset.HighPart = SectionOffset.LowPart = 0;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ Size,
+ &SectionOffset,
+ &Size,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("A20OFF: Unable to map view of section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ A20IsON = FALSE;
+}
+
+EXPORT
+VOID
+sas_disable_20_bit_wrapping(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine causes addressing to NOT wrap at 1MB
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ NTSTATUS Status;
+ PVOID BaseAddress;
+ ULONG Size;
+ LARGE_INTEGER SectionOffset;
+
+ // if A20 line is on already do nothing
+ if (A20IsON == TRUE){
+ return;
+ }
+ BaseAddress = (PVOID)ONEMEGA;
+ Size = SIXTYFOURK;
+
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ BaseAddress
+ );
+
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("A20ON: Unable to unmap view of section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ SectionOffset.HighPart = 0;
+ SectionOffset.LowPart = 640 * 1024;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ &BaseAddress,
+ 0,
+ Size,
+ &SectionOffset,
+ &Size,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("A20ON: Unable to map view of section, status = %lx\n",
+ Status);
+#endif
+ TerminateVDM();
+ }
+ A20IsON = TRUE;
+}
+
+
+
+EXPORT
+half_word
+sas_hw_at(
+ IN sys_addr Address
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the byte at the specified address
+
+Arguments:
+
+ Address -- address of byte to return
+
+Return Value:
+
+ value of byte at specified address
+
+--*/
+{
+ half_word RetVal;
+
+ if (Address > VdmSize) {
+ return 0xFE;
+ }
+
+ RetVal = *((half_word *)Address);
+ return RetVal;
+}
+
+
+EXPORT
+word
+sas_w_at(
+ IN sys_addr Address
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the word at the specified address
+
+Arguments:
+
+ Address -- address of word to return
+
+Return Value:
+
+ value of word at specified address
+
+--*/
+{
+ word RetVal;
+
+// DbgPrint("NtVdm : sas_w_at \n");
+ if (Address > VdmSize) {
+ return 0xFEFE;
+ }
+
+ RetVal = *((word *)Address);
+ return RetVal;
+}
+
+
+EXPORT
+double_word
+sas_dw_at(
+ IN sys_addr Address
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the dword at the specified address
+
+Arguments:
+
+ Address -- address of dword to return
+
+Return Value:
+
+ value of dword at specified address
+
+--*/
+{
+ double_word RetVal;
+
+ //DbgPrint("NtVdm : sas_dw_at \n");
+ RetVal = (double_word)(((ULONG)sas_w_at(Address + 2) << 16) +
+ sas_w_at(Address));
+ return RetVal;
+}
+
+
+EXPORT
+VOID
+sas_load(
+ IN sys_addr Address,
+ IN half_word *Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the byte at the specified address in the supplied
+ variable
+
+Arguments:
+
+ Address -- address of byte to return
+ Value -- Variable to store the value in
+
+Return Value:
+
+ None.
+--*/
+{
+ //DbgPrint("NtVdm : sas_load \n");
+ if (Address > VdmSize) {
+ *Value = 0xFE;
+ return;
+ }
+
+ *Value = *((half_word *)Address);
+ return;
+}
+
+
+EXPORT
+VOID
+sas_loadw(
+ IN sys_addr Address,
+ IN word *Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the word at the specified address in the supplied
+ variable
+
+Arguments:
+
+ Address -- address of word to return
+ Value -- Variable to store the value in
+
+Return Value:
+
+ None.
+--*/
+{
+ //DbgPrint("NtVdm : sas_loadw\n");
+ if (Address > VdmSize) {
+ *Value = 0xFEFE;
+ return;
+ }
+
+ *Value = *((word *)Address);
+ //DbgPrint("NtVdm : sas_loadw word at address %lx is %x (Not video)\n",Address,*Value);
+ return;
+}
+
+
+
+EXPORT
+VOID
+sas_store(
+ IN sys_addr Address,
+ IN half_word Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the specified byte at the specified address
+
+Arguments:
+
+ Address -- address of word to return
+ Value -- value to store
+
+Return Value:
+
+ None.
+--*/
+{
+ half_word Type;
+ //DbgPrint("NtVdm : sas_store\n");
+ if (Address <= VdmSize) {
+ Type = sas_memory_type(Address);
+ switch (Type) {
+ case SAS_ROM:
+ break;
+
+ default:
+ *((half_word *)Address) = Value;
+ //DbgPrint("NtVdm : sas_store put byte %x at address %lx\n",Value,Address);
+ break;
+ }
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_storew(
+ IN sys_addr Address,
+ IN word Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the specified word at the specified address
+
+Arguments:
+
+ Address -- address of word to return
+ Value -- value to store at the specified address
+
+Return Value:
+
+ None.
+--*/
+{
+
+ //DbgPrint("NtVdm : sas_storew\n");
+ if (Address + 1 <= VdmSize) {
+ switch (sas_memory_type(Address)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ *((word *)Address) = Value;
+ //DbgPrint("NtVdm : sas_storew put word %x at address %lx\n",Value,Address);
+ break;
+ }
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_storedw(
+ IN sys_addr Address,
+ IN double_word Value
+ )
+/*++
+
+Routine Description:
+
+ This routine stores the specified dword at the specified address
+
+Arguments:
+
+ Address -- address of word to return
+ Value -- value to store at the specified address
+
+Return Value:
+
+ None.
+--*/
+{
+ //_asm int 3;
+ sas_storew(Address, (word)(Value & 0xFFFF));
+ sas_storew(Address + 2, (word)((Value >> 16) & 0xFFFF));
+}
+
+
+EXPORT
+VOID
+sas_loads(
+ IN sys_addr Source,
+ IN host_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies the string from the specified intel address to the
+ specified host address
+
+Arguments:
+
+ Source -- Intel address to copy from
+ Destination -- host address to copy the string to
+ Length -- length of the string to copy
+
+Return Value:
+
+ None.
+--*/
+{
+
+ //DbgPrint("NtVdm : sas_loads\n");
+ RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
+}
+
+
+
+EXPORT
+VOID
+sas_stores(
+ IN sys_addr Destination,
+ IN host_addr Source,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies the string from the specified host address to the
+ specified intel address
+
+Arguments:
+
+ Destination -- intel address to copy the string to
+ Source -- host address to copy from
+ Length -- length of the string to copy
+
+Return Value:
+
+ None.
+--*/
+{
+
+ //DbgPrint("NtVdm : sas_stores\n");
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
+ break;
+ }
+}
+
+
+EXPORT
+VOID
+sas_move_bytes_forward(
+ IN sys_addr Source,
+ IN sys_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies one region of intel memory to another.
+
+Arguments:
+
+ Source -- source intel address
+ Destination -- destination intel address
+ Length -- length of region to copy (in bytes)
+
+Return Value:
+
+ None.
+--*/
+{
+ //DbgPrint("NtVdm : sas_move_bytes_forward\n");
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
+ break;
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_move_words_forward(
+ IN sys_addr Source,
+ IN sys_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies one region of intel memory to another.
+
+Arguments:
+
+ Source -- source intel address
+ Destination -- destination intel address
+ Length -- length of region to copy (in words)
+
+Return Value:
+
+ None.
+--*/
+{
+ //_asm int 3;
+ Length <<= 1;
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
+ break;
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_move_bytes_backward(
+ IN sys_addr Source,
+ IN sys_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies one region of intel memory to another.
+
+Arguments:
+
+ Source -- source intel address
+ Destination -- destination intel address
+ Length -- length of region to copy (in bytes)
+
+Return Value:
+
+ None.
+--*/
+{
+ //_asm int 3;
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) (Destination - Length + 1),
+ (PVOID) (Source - Length + 1),
+ Length);
+ break;
+ }
+}
+
+
+
+EXPORT
+VOID
+sas_move_words_backward(
+ IN sys_addr Source,
+ IN sys_addr Destination,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine copies one region of intel memory to another.
+
+Arguments:
+
+ Source -- source intel address
+ Destination -- destination intel address
+ Length -- length of region to copy (in words)
+
+Return Value:
+
+ None.
+--*/
+{
+ //_asm int 3;
+ Length <<= 1;
+ switch (sas_memory_type(Destination)) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlCopyMemory((PVOID) (Destination - Length + 1),
+ (PVOID) (Source - Length + 1),
+ Length);
+ break;
+ }
+}
+
+EXPORT
+VOID
+sas_fills(
+ IN sys_addr Address,
+ IN half_word Value,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine fills a specified region of intel memory with a byte value
+
+Arguments:
+
+ Address -- address to fill at
+ Value -- value to fill with
+ Length -- length of region to fill
+
+Return Value:
+
+ None.
+--*/
+{
+ half_word Type;
+
+ //DbgPrint("NtVdm : sas_fills\n");
+ Type = sas_memory_type(Address);
+ switch (Type) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ RtlFillMemory((PVOID) Address, Length, Value);
+ break;
+ }
+}
+
+EXPORT
+VOID
+sas_fillsw(
+ IN sys_addr Address,
+ IN word Value,
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine fills a specified region of intel memory with a word value
+
+Arguments:
+
+ Address -- address to fill at
+ Value -- value to fill with
+ Length -- length of region to fill
+
+Return Value:
+
+ None.
+--*/
+{
+
+ word *p;
+ half_word Type;
+
+ //DbgPrint("NtVdm : sas_fillsw\n");
+ Type = sas_memory_type(Address);
+ switch (Type) {
+
+ case SAS_ROM:
+ break;
+
+ default:
+ p = (word *)Address;
+ while (Length--) {
+ *p++ = Value;
+ }
+ break;
+ }
+}
+
+host_addr scratch = NULL;
+
+EXPORT
+host_addr
+sas_scratch_address(
+ IN sys_addr Length
+ )
+/*++
+
+Routine Description:
+
+ This routine supplies a scratch buffer for short term use
+
+Arguments
+
+ Length -- length of buffer needed
+
+Return Value:
+
+ None.
+
+NOTE: Sudeepb 31-Oct-1993 Converted scratch to be allocated dynamically rather
+ than as a static array.
+--*/
+{
+ //DbgPrint("NtVdm : sas_scratch_address\n");
+ if (Length > 64 * 1024) {
+ //DbgPrint("SoftPc: sas_scratch_address requet for buffer larger than 64K\n");
+ return NULL;
+ }
+
+ if (scratch)
+ return scratch;
+
+ if ((scratch = (host_addr) malloc (64 * 1024)) == NULL)
+ return NULL;
+
+ return scratch;
+}
+
+EXPORT
+half_word
+sas_hw_at_no_check(
+ sys_addr addr
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_hw_at_no_check\n");
+ //DbgPrint("NtVdm : sas_hw_at_no_check byte at %lx is %x\n",addr,*((half_word *)addr));
+ return *((half_word *)addr);
+}
+
+EXPORT
+word
+sas_w_at_no_check(
+ sys_addr addr
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_w_at_no_check\n");
+ //DbgPrint("NtVdm : sas_w_at_no_check word at %lx is %x\n",addr,*((word *)addr));
+ return *((word *)addr);
+}
+EXPORT
+double_word
+sas_dw_at_no_check(
+ sys_addr addr
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_dw_at_no_check\n");
+ //DbgPrint("NtVdm : sas_dw_at_no_check double word at %lx is %lx\n",addr,*((double_word *)addr));
+ return *((double_word *)addr);
+}
+
+
+EXPORT
+VOID
+sas_store_no_check(
+ sys_addr addr,
+ half_word val
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_store_no_check\n");
+ *((half_word *)addr) = val;
+ //DbgPrint("NtVdm : sas_store_no_check stored byte %x at %lx\n",val,addr);
+}
+
+EXPORT
+VOID
+sas_storew_no_check(
+ sys_addr addr,
+ word val
+ )
+// bugbug comment
+{
+ //DbgPrint("NtVdm : sas_storew_no_check\n");
+ *((word *)addr) = val;
+}
+EXPORT
+double_word
+effective_addr(
+ IN word Segment,
+ IN word Offset
+ )
+/*++
+
+Routine Description:
+
+ This routine maps effective_addr to Sim32GetVdmPointer
+
+Arguments:
+
+ Segment -- segment of address
+ Offset -- offset of address
+
+Return Value:
+
+ Actual Intel address corresponding to the address supplied
+--*/
+{
+ //DbgPrint("NtVdm : effective_addr\n");
+ return (ULONG)Sim32GetVDMPointer(((((ULONG)Segment) << 16) | Offset), 1,
+ (UCHAR) (getMSW() & MSW_PE ? TRUE : FALSE));
+}
+
+typedef enum
+{
+ RAM,
+ VIDEO,
+ ROM,
+ IN_FRAGMENT,
+ NEXT_FRAGMENT
+} mem_type;
+
+typedef struct
+{
+ VOID (*b_write)();
+ VOID (*w_write)();
+ VOID (*b_fill)();
+ VOID (*w_fill)();
+ VOID (*b_move)();
+ VOID (*w_move)();
+} MEM_HANDLERS;
+#define TYPE_RANGE ((int)SAS_INACCESSIBLE)
+#define write_b_write_ptrs( offset, func ) ( b_write_ptrs[(offset)] = (func) )
+#define write_w_write_ptrs( offset, func ) ( w_write_ptrs[(offset)] = (func) )
+#define write_b_page_ptrs( offset, func ) ( b_move_ptrs[(offset)] = b_fill_ptrs[(offset)] = (func) )
+#define write_w_page_ptrs( offset, func ) ( w_move_ptrs[(offset)] = w_fill_ptrs[(offset)] = (func) )
+#define init_b_write_ptrs( offset, func ) ( b_write_ptrs[(offset)] = (func) )
+#define init_w_write_ptrs( offset, func ) ( w_write_ptrs[(offset)] = (func) )
+#define init_b_page_ptrs( offset, func ) ( b_move_ptrs[(offset)] = b_fill_ptrs[(offset)] = (func) )
+#define init_w_page_ptrs( offset, func ) ( w_move_ptrs[(offset)] = w_fill_ptrs[(offset)] = (func) )
+#define read_b_write_ptrs( offset ) ( b_write_ptrs[(offset)] )
+#define read_w_write_ptrs( offset ) ( w_write_ptrs[(offset)] )
+#define read_b_page_ptrs( offset ) ( b_move_ptrs[(offset)] )
+#define read_w_page_ptrs( offset ) ( w_move_ptrs[(offset)] )
+#define read_b_move_ptrs( offset ) ( b_move_ptrs[(offset)] )
+#define read_w_move_ptrs( offset ) ( w_move_ptrs[(offset)] )
+#define read_b_fill_ptrs( offset ) ( b_fill_ptrs[(offset)] )
+#define read_w_fill_ptrs( offset ) ( w_fill_ptrs[(offset)] )
+
+/*
+* The main gmi data structures are defined here
+*/
+void (*(b_write_ptrs[TYPE_RANGE]))() ; /* byte write function */
+void (*(w_write_ptrs[TYPE_RANGE]))() ; /* word write function */
+void (*(b_fill_ptrs[TYPE_RANGE]))() ; /* byte str fill func */
+void (*(w_fill_ptrs[TYPE_RANGE]))() ; /* word str fill func */
+void (*(b_move_ptrs[TYPE_RANGE]))() ; /* byte str write func */
+void (*(w_move_ptrs[TYPE_RANGE]))() ; /* word str write func */
+
+void gmi_define_mem(type,handlers)
+mem_type type;
+MEM_HANDLERS *handlers;
+{
+ int int_type = (int)(type);
+ init_b_write_ptrs(int_type, (void(*)())(handlers->b_write));
+ init_w_write_ptrs(int_type, (void(*)())(handlers->w_write));
+ b_move_ptrs[int_type] = (void(*)())(handlers->b_move);
+ w_move_ptrs[int_type] = (void(*)())(handlers->w_move);
+ b_fill_ptrs[int_type] = (void(*)())(handlers->b_fill);
+ w_fill_ptrs[int_type] = (void(*)())(handlers->w_fill);
+}
+#endif
+BOOL sas_twenty_bit_wrapping_enabled() {
+ return (!A20IsON);
+}
+
+VOID sas_part_enable_20_bit_wrapping(){
+}
+VOID sas_part_disable_20_bit_wrapping(){
+}
+
+
+/*
+ * This function maps the given EMM backfill memory to DOS conventional
+ * memory. The function is provided to EMM manager to put back
+ * unmapped backfill memory(hold its contents while it is not mapped).
+ *
+ * NOTE: The very first caller will be sas_init.
+ *
+ * Input: ULONG BaseAddress -- the starting address, must be in INTEL page
+ * boundary
+ * ULONG Size -- size of the range, must be a multiple of
+ * EMM_PAGE_SIZE.
+ *
+ * According to LouP, a view costs about 400 bytes of memory. This is why
+ * I make these function strictly to work on EMM_PAGE_SIZE instead of 4KB.
+ */
+
+
+BOOL
+HoldEMMBackFillMemory(ULONG BaseAddress, ULONG Size)
+{
+ ULONG NewBase, Pages, i;
+ LARGE_INTEGER SectionOffset;
+ ULONG ViewSize;
+ NTSTATUS Status;
+
+ /* this function can only be called if there is backfill at all */
+ ASSERT(BackFillSegment < 640 * 1024 / 16);
+
+ // size must be EMM_PAGE_SIZE multiple
+ ASSERT((Size % EMM_PAGE_SIZE) == 0);
+
+ // address must be on INTEL page boundary
+ ASSERT((BaseAddress & (INTEL_PAGE_SIZE - 1)) == 0);
+
+ for (Pages = Size / EMM_PAGE_SIZE; Pages; Pages--) {
+ SectionOffset.LowPart = BaseAddress;
+ SectionOffset.HighPart = 0;
+ ViewSize = EMM_PAGE_SIZE;
+ Status = NtMapViewOfSection(A20SectionHandle,
+ NtCurrentProcess(),
+ (PVOID *)&BaseAddress,
+ 0,
+ ViewSize,
+ &SectionOffset,
+ &ViewSize,
+ ViewUnmap,
+ MEM_DOS_LIM,
+ PAGE_EXECUTE_READWRITE
+ );
+ if (!NT_SUCCESS(Status))
+ break;
+ BaseAddress += EMM_PAGE_SIZE;
+ }
+ return (NT_SUCCESS(Status));
+}
diff --git a/private/mvdm/v86/monitor/i386/sources b/private/mvdm/v86/monitor/i386/sources
new file mode 100644
index 000000000..826099cfc
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/sources
@@ -0,0 +1,11 @@
+i386_SOURCES=i386\monitor.c \
+ i386\fastpm.asm\
+ i386\sas.c \
+ i386\spcstubs.c \
+ i386\thread.c \
+ i386\int.c
+!IF 0
+Note: to build with profiling support, add the following to the i386_sources
+
+ i386\proflib.c \
+!ENDIF
diff --git a/private/mvdm/v86/monitor/i386/spcstubs.c b/private/mvdm/v86/monitor/i386/spcstubs.c
new file mode 100644
index 000000000..c2bb4fcce
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/spcstubs.c
@@ -0,0 +1,109 @@
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <vdm.h>
+#include <stdio.h>
+//Tim Nov 92 #include <xt.h>
+#include <nt_mon.h> //Tim Nov 92, so it builds...
+
+
+ULONG cpu_calc_q_ev_inst_for_time(ULONG time){
+ return(time);
+}
+
+ULONG q_ev_count;
+
+VOID cpu_q_ev_set_count(ULONG time){
+ q_ev_count = time;
+}
+ULONG cpu_q_ev_get_count() {
+ return(q_ev_count);
+}
+
+char szYodaWarn[]="NtVdm : Using Yoda on an x86 may be hazardous to your systems' health\n";
+
+unsigned char *GDP;
+
+int getCPL(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+
+int getEM(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getGDT_BASE(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getGDT_LIMIT(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getIDT_BASE(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getIDT_LIMIT(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getIOPL(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getLDT_BASE(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getLDT_LIMIT(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getLDT_SELECTOR(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getMP(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getNT(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getTR_BASE(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getTR_LIMIT(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getTR_SELECTOR(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+int getTS(){
+ OutputDebugString(szYodaWarn);
+ return(0);
+}
+void setPE(int dummy1){
+ OutputDebugString(szYodaWarn);
+}
+boolean selector_outside_table(word foo, double_word *bar){
+ UNREFERENCED_PARAMETER(foo);
+ UNREFERENCED_PARAMETER(bar);
+ OutputDebugString("NtVdm : Using Yoda on an x86 may be hazardous to your systems' health\n");
+ return(0);
+}
+
+VOID
+EnterIdle(){
+}
+
+VOID
+LeaveIdle(){
+}
diff --git a/private/mvdm/v86/monitor/i386/thread.c b/private/mvdm/v86/monitor/i386/thread.c
new file mode 100644
index 000000000..41d3b50e5
--- /dev/null
+++ b/private/mvdm/v86/monitor/i386/thread.c
@@ -0,0 +1,338 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Thread.c
+
+Abstract:
+
+ This file contains functions for tracking and manipulating threads
+
+Author:
+
+ Dave Hastings (daveh) 18-Apr-1992
+
+Revision History:
+
+--*/
+
+#include <monitorp.h>
+#include <malloc.h>
+
+//
+// Local Types
+//
+
+typedef struct _MonitorThread {
+ struct _MonitorThread *Previous;
+ struct _MonitorThread *Next;
+ PVOID Teb;
+ HANDLE Thread;
+} MONITORTHREAD, *PMONITORTHREAD;
+
+//
+// Local Variables
+//
+
+PMONITORTHREAD ThreadList = NULL; // List of all threads registered
+
+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.
+
+--*/
+{
+ PMONITORTHREAD NewThread, CurrentThread;
+ THREAD_BASIC_INFORMATION ThreadInfo;
+ HANDLE MonitorThreadHandle;
+ NTSTATUS Status;
+
+ //
+ // Correctly initialize the floating point context for the thread
+ //
+ InitialContext.ContextFlags = CONTEXT_FLOATING_POINT;
+
+ if (DebugContextActive)
+ InitialContext.ContextFlags |= CONTEXT_DEBUG_REGISTERS;
+
+ Status = NtSetContextThread(
+ Thread,
+ &InitialContext
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NtVdm terminating : Could not set float context for\n"
+ " thread handle 0x%x, status %lx\n", Thread, Status);
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+ //
+ // Set up a structure to keep track of the new thread
+ //
+ NewThread = malloc(sizeof(MONITORTHREAD));
+
+ if (!NewThread) {
+#if DBG
+ DbgPrint("NTVDM: Could not allocate space for new thread\n");
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+ //
+ // Create a handle for the monitor to use
+ //
+
+ Status = NtDuplicateObject(
+ NtCurrentProcess(),
+ Thread,
+ NtCurrentProcess(),
+ &MonitorThreadHandle,
+ 0,
+ 0,
+ DUPLICATE_SAME_ACCESS
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NTVDM: Could not duplicate thread handle\n");
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+ NewThread->Thread = MonitorThreadHandle;
+
+ Status = NtQueryInformationThread(
+ MonitorThreadHandle,
+ ThreadBasicInformation,
+ &ThreadInfo,
+ sizeof(THREAD_BASIC_INFORMATION),
+ NULL
+ );
+
+ if (!NT_SUCCESS(Status)) {
+#if DBG
+ DbgPrint("NTVDM: Could not get thread information\n");
+ DbgBreakPoint();
+#endif
+ TerminateVDM();
+ }
+
+ NewThread->Teb = ThreadInfo.TebBaseAddress;
+ ((PTEB)(NewThread->Teb))->Vdm = &VdmTib;
+
+ //
+ // Insert the new thread in the list. The list is sorted in ascending
+ // order of Teb address
+ //
+ if (!ThreadList) {
+ ThreadList = NewThread;
+ NewThread->Next = NULL;
+ NewThread->Previous = NULL;
+ return;
+ }
+
+ CurrentThread = ThreadList;
+ while ((CurrentThread->Next) && (CurrentThread->Teb < NewThread->Teb)) {
+ CurrentThread = CurrentThread->Next;
+ }
+
+ if (NewThread->Teb > CurrentThread->Teb) {
+ CurrentThread->Next = NewThread;
+ NewThread->Previous = CurrentThread;
+ NewThread->Next = NULL;
+ } else {
+ ASSERT((CurrentThread->Teb != NewThread->Teb));
+ NewThread->Previous = CurrentThread->Previous;
+ NewThread->Next = CurrentThread;
+ CurrentThread->Previous = NewThread;
+ if (NewThread->Previous) {
+ NewThread->Previous->Next = NewThread;
+ } else {
+ ThreadList = NewThread;
+ }
+ }
+}
+
+VOID
+cpu_exitthread(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine frees the thread tracking information, and closes the thread
+ handle
+
+Arguments:
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PVOID CurrentTeb;
+ NTSTATUS Status;
+ PMONITORTHREAD ThreadInfo;
+
+ CurrentTeb = NtCurrentTeb();
+
+ ThreadInfo = ThreadList;
+
+ //
+ // Find this thread in the list
+ //
+ while ((ThreadInfo) && (ThreadInfo->Teb != CurrentTeb)) {
+ ThreadInfo = ThreadInfo->Next;
+ }
+
+ if (!ThreadInfo) {
+#if DBG
+ DbgPrint("NTVDM: Could not find thread in list\n");
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+ //
+ // Close our handle to this thread
+ //
+ Status = NtClose(ThreadInfo->Thread);
+#if DBG
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint("NTVDM: Could not close thread handle\n");
+ }
+#endif
+
+ //
+ // Remove this thread from the list
+ //
+ if (ThreadInfo->Previous) {
+ ThreadInfo->Previous->Next = ThreadInfo->Next;
+ } else {
+ ThreadList = ThreadInfo->Next;
+ }
+
+ if (ThreadInfo->Next) {
+ ThreadInfo->Next->Previous = ThreadInfo->Previous;
+ }
+
+ free(ThreadInfo);
+}
+
+HANDLE
+ThreadLookUp(
+ PVOID Teb
+ )
+/*++
+
+Routine Description:
+
+ This routine returns the handle for the specified thread.
+
+Arguments:
+
+ Teb -- Supplies the teb pointer of the thread
+
+Return Value:
+
+ Returns the handle of the thread, or NULL
+
+--*/
+{
+ PMONITORTHREAD Thread;
+
+ Thread = ThreadList;
+
+ while ((Thread) && (Thread->Teb != Teb)) {
+ Thread = Thread->Next;
+ }
+
+ if (Thread) {
+ return Thread->Thread;
+ } else {
+ return NULL;
+ }
+}
+
+BOOL
+ThreadSetDebugContext(
+ PULONG pDebugRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine sets the debug registers for all the threads that the
+ monitor knows about.
+
+Arguments:
+
+ pDebugRegisters -- Pointer to 6 dwords containing the requested debug
+ register contents.
+
+Return Value:
+
+ none
+
+--*/
+{
+ PMONITORTHREAD Thread;
+ NTSTATUS Status;
+
+ Thread = ThreadList;
+ InitialContext.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+
+ InitialContext.Dr0 = *pDebugRegisters++;
+ InitialContext.Dr1 = *pDebugRegisters++;
+ InitialContext.Dr2 = *pDebugRegisters++;
+ InitialContext.Dr3 = *pDebugRegisters++;
+ InitialContext.Dr6 = *pDebugRegisters++;
+ InitialContext.Dr7 = *pDebugRegisters++;
+
+ while (Thread) {
+
+ Status = NtSetContextThread(
+ Thread->Thread,
+ &InitialContext
+ );
+
+ if (!NT_SUCCESS(Status))
+ break;
+
+ Thread = Thread->Next;
+ }
+
+ if (!NT_SUCCESS(Status))
+ return (FALSE);
+ else {
+ DebugContextActive = ((InitialContext.Dr7 & 0x0f) != 0);
+ return (TRUE);
+ }
+
+}
+
diff --git a/private/mvdm/v86/monitor/makefile b/private/mvdm/v86/monitor/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/mvdm/v86/monitor/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/v86/monitor/sources b/private/mvdm/v86/monitor/sources
new file mode 100644
index 000000000..cb21ac27d
--- /dev/null
+++ b/private/mvdm/v86/monitor/sources
@@ -0,0 +1,57 @@
+!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
+ Dave Hastings (daveh) 24-Apr-1991
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+
+MAJORCOMP=v86
+MINORCOMP=monitor
+TARGETNAME=monitor
+
+
+TARGETPATH=\nt\public\sdk\lib
+
+TARGETTYPE=LIBRARY
+
+
+TARGETLIBS=
+
+
+INCLUDES=..\..\inc;..\..\softpc.new\base\inc;..\..\softpc.new\host\inc;..\..\..\inc
+
+
+NTPROFILEINPUT=YES
+
+SOURCES=
+
+!IFDEF PROFILE
+C_DEFINES=-DCPU_30_STYLE -DMONITOR -DPROFILE
+!ELSE
+!IFDEF OLDBUILD
+C_DEFINES=-DCPU_30_STYLE -DMONITOR -DOLDBUILD
+!ELSE
+C_DEFINES=-DCPU_30_STYLE -DMONITOR
+!ENDIF
+!ENDIF
+
+UMTYPE=console
diff --git a/private/mvdm/v86/scaffold/i386/fakebop.c b/private/mvdm/v86/scaffold/i386/fakebop.c
new file mode 100644
index 000000000..b9430dd30
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/fakebop.c
@@ -0,0 +1,502 @@
+#include <windows.h>
+#include <stdio.h>
+#include <conio.h>
+#include "demexp.h"
+#include "cmdsvc.h"
+#include "rdrexp.h"
+#include "dbgexp.h"
+#include "softpc.h"
+#include "fun.h"
+//
+// This module contains the fake function definitions for bop functions
+//
+
+extern CONTEXT IntelRegisters;
+extern VOID switch_to_real_mode();
+extern VOID host_unsimulate();
+
+
+HANDLE hWOWDll;
+
+FARPROC WOWDispatchEntry;
+FARPROC WOWInitEntry;
+
+void DBGDispatch( void );
+
+void reset(){}
+void dummy_int(){}
+void unexpected_int(){}
+void illegal_bop(){}
+void print_screen(){}
+void time_int(){}
+void keyboard_int(){}
+void diskette_int(){}
+void video_io(){}
+void equipment(){}
+void memory_size(){}
+void disk_io(){}
+void rs232_io(){}
+void cassette_io(){}
+void keyboard_io(){}
+void printer_io(){}
+void rom_basic(){}
+void bootstrap(){}
+void time_of_day(){}
+void critical_region(){}
+void cmd_install(){}
+void cmd_load(){}
+void redirector(){}
+void ega_video_io(){}
+void MsBop0(){
+
+ DemDispatch((ULONG)(*Sim32GetVDMPointer(
+ ((ULONG)getCS() << 16) + (getIP()), 1, FALSE)));
+ setIP(getIP() + 1);
+
+}
+void MsBop1(){
+
+
+ static WowModeInitialized = FALSE;
+
+ if (!WowModeInitialized) {
+
+ // Load the WOW DLL
+ if ((hWOWDll = LoadLibrary ("WOW32")) == NULL){
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: error initializing WOW\n")
+ );
+ TerminateVDM();
+ return;
+ }
+
+ // Get the init entry point and dispatch entry point
+ if ((WOWInitEntry = GetProcAddress (hWOWDll, "W32Init")) == NULL) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: error initializing WOW\n")
+ );
+ FreeLibrary (hWOWDll);
+ TerminateVDM();
+ return;
+ }
+
+ if ((WOWDispatchEntry = GetProcAddress (hWOWDll, "W32Dispatch")) == NULL) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: error initializing WOW\n")
+ );
+ FreeLibrary (hWOWDll);
+ TerminateVDM();
+ return;
+ }
+
+ // Call the Init Routine
+ if ((*WOWInitEntry)() == FALSE) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: error initializing WOW\n")
+ );
+ TerminateVDM();
+ return;
+ }
+
+ WowModeInitialized = TRUE;
+ }
+
+ (*WOWDispatchEntry)();
+}
+
+void MsBop2(){
+
+ XMSDispatch((ULONG)(*Sim32GetVDMPointer(
+ ((ULONG)getCS() << 16) + (getIP()), 1, FALSE)));
+ setIP(getIP() + 1);
+
+}
+void MsBop3(){
+ DpmiDispatch();
+}
+
+
+
+void MsBop4(){
+ CmdDispatch((ULONG)(*Sim32GetVDMPointer(
+ ((ULONG)getCS() << 16) + (getIP()), 1, FALSE)));
+ setIP(getIP() + 1);
+}
+
+
+
+//
+// MsBop5 - used to dispatch to Vdm Redir (Vr) support functions
+//
+
+void MsBop5()
+{
+#ifdef NTVDM_NET_SUPPORT
+ VrDispatch((ULONG)(*Sim32GetVDMPointer(
+ ((ULONG)getCS() << 16) + (getIP()), 1, FALSE)));
+ setIP(getIP() + 1);
+#endif
+}
+
+//
+// MsBop6 - used to dispatch to debugger support functions
+//
+
+void MsBop6()
+{
+ /*
+ ** All of the parameters for the debugger support
+ ** should be on the VDMs stack.
+ */
+ DBGDispatch();
+}
+void MsBop7(){}
+void MsBop8(){}
+void MsBop9(){}
+void MsBopA(){}
+void MsBopB(){
+
+ switch (getAH()) {
+
+ case 0 :
+ setAH(0);
+ while (!tkbhit());
+ setAL((BYTE)tgetch());
+ break;
+
+ case 1 :
+ tputch(getAL());
+ break;
+ }
+}
+void MsBopC(){
+
+ BiosKbd();
+
+}
+void MsBopD(){
+
+ BiosVid();
+
+}
+void MsBopE(){}
+
+
+void MsBopF(){
+ UCHAR *Instruction;
+ USHORT i;
+
+ // Unimplemented interrupt bop
+
+ Instruction = RMSEGOFFTOLIN(getSS(), getSP());
+ Instruction = RMSEGOFFTOLIN(*((PWORD)Instruction + 1),
+ *(PWORD)(Instruction));
+ i = (USHORT)(*(Instruction - 1));
+ VDprint(
+ VDP_LEVEL_WARNING,
+ ("SoftPC Bop Support: Unimplemented Interrupt %x\n",
+ i)
+ );
+
+}
+void emm_init(){}
+void emm_io(){}
+void return_from_call(){}
+void rtc_int(){}
+void re_direct(){}
+void D11_int(){}
+void int_287(){}
+void worm_init(){}
+void worm_io(){}
+void ps_private_1(){}
+void ps_private_2(){}
+void ps_private_3(){}
+void ps_private_4(){}
+void ps_private_5(){}
+void ps_private_6(){}
+void ps_private_7(){}
+void ps_private_8(){}
+void ps_private_9(){}
+void ps_private_10(){}
+void ps_private_11(){}
+void ps_private_12(){}
+void ps_private_13(){}
+void ps_private_14(){}
+void ps_private_15(){}
+void bootstrap1(){}
+void bootstrap2(){}
+void bootstrap3(){}
+void ms_windows(){}
+void msw_mouse(){}
+void mouse_install1(){}
+void mouse_install2(){}
+void mouse_int1(){}
+void mouse_int2(){}
+void mouse_io_language(){}
+void mouse_io_interrupt(){}
+void mouse_video_io(){}
+void control_bop(){}
+void diskette_io(){}
+void illegal_op_int(){}
+
+VOID (*BIOS[])(VOID) = { reset,
+ dummy_int,
+ unexpected_int,
+ illegal_bop,
+ illegal_bop,
+ print_screen,
+ illegal_op_int,
+ illegal_bop,
+ time_int,
+ keyboard_int,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ diskette_int,
+ illegal_bop,
+ video_io,
+ equipment,
+ memory_size,
+ disk_io,
+ rs232_io,
+ cassette_io,
+ keyboard_io,
+ printer_io,
+ rom_basic,
+ bootstrap,
+ time_of_day,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ critical_region,
+ cmd_install,
+ cmd_load,
+ illegal_bop,
+ illegal_bop,
+ redirector,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ diskette_io,
+ illegal_bop,
+ ega_video_io,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ MsBop0,
+ MsBop1,
+ MsBop2,
+ MsBop3,
+ MsBop4,
+ MsBop5,
+ MsBop6,
+ MsBop7,
+ MsBop8,
+ MsBop9,
+ MsBopA,
+ MsBopB,
+ MsBopC,
+ MsBopD,
+ MsBopE,
+ MsBopF,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ emm_init,
+ emm_io,
+ return_from_call,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ rtc_int,
+ re_direct,
+ D11_int,
+ D11_int,
+ D11_int,
+ int_287,
+ D11_int,
+ D11_int,
+ worm_init,
+ worm_io,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ ps_private_1,
+ ps_private_2,
+ ps_private_3,
+ ps_private_4,
+ ps_private_5,
+ ps_private_6,
+ ps_private_7,
+ ps_private_8,
+ ps_private_9,
+ ps_private_10,
+ ps_private_11,
+ ps_private_12,
+ ps_private_13,
+ ps_private_14,
+ ps_private_15,
+ illegal_bop,
+ bootstrap1,
+ bootstrap2,
+ bootstrap3,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ ms_windows,
+ msw_mouse,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ mouse_install1,
+ mouse_install2,
+ mouse_int1,
+ mouse_int2,
+ mouse_io_language,
+ mouse_io_interrupt,
+ mouse_video_io,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ illegal_bop,
+ switch_to_real_mode,
+ host_unsimulate,
+ control_bop };
+
diff --git a/private/mvdm/v86/scaffold/i386/fakeinit.c b/private/mvdm/v86/scaffold/i386/fakeinit.c
new file mode 100644
index 000000000..ae5d586de
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/fakeinit.c
@@ -0,0 +1,123 @@
+//
+// Fake Bios support initialization.
+//
+// This file provides interrim support for rom bios services initialization.
+// It is only intended for use until Insignia produces proper rom support
+// for NTVDM
+//
+
+#include <windows.h>
+#include <stdio.h>
+#include <conio.h>
+#include <string.h>
+#include "softpc.h"
+#include "bop.h"
+#include "xguest.h"
+#include "xbios.h"
+#include "xbiosdsk.h"
+#include "fun.h"
+
+#define SERVICE_LENGTH 4
+static BYTE ServiceRoutine[] = { 0xC4 , 0xC4, BOP_UNIMPINT, 0xCF };
+
+#define RESET_LENGTH 16
+static BYTE ResetRoutine[] = { 0xEA, 0x00, 0x00, 0x00, 0xE0, // jmpf E000:0
+ BIOSDATE_MINE,
+ 0, 0xFE, 0 };
+
+static BYTE WarmBoot[] = {
+ OPX_MOVAX, BYTESOFFSET(0x30),
+ OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_SS,REG_AX),
+ OPX_MOVSP, BYTESOFFSET(0x100),
+ OPX_MOVAX, 0x00, 0x00,
+ OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_DS,REG_AX),
+ OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_ES,REG_AX),
+ OPX_MOVDX, DRIVE_FD0, 0x00, // WARNING: sync with BIOSBOOT_DRIVE
+ OPX_MOVCX, 0x01, 0x00,
+ OPX_MOVBX, BYTESOFFSET(BIOSDATA_BOOT),
+ OPX_MOVAX, 0x01, DSKFUNC_READSECTORS,
+ OPX_INT, BIOSINT_DSK,
+ OPX_JB, -7,
+ OPX_JMPF, BYTESCOMPOSITE(0, BIOSDATA_BOOT)
+};
+#define WARMBOOT_LENGTH sizeof(WarmBoot)
+
+static BYTE EquipmentRoutine[] = { // INT 11h code
+ OPX_PUSHDS,
+ OPX_MOVAX, 0x00, 0x00,
+ OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_DS,REG_AX),
+ OPX_MOVAXOFF, BYTESOFFSET(BIOSDATA_EQUIP_FLAG),
+ OPX_POPDS,
+ OPX_IRET
+};
+#define EQUIPMENT_LENGTH sizeof(EquipmentRoutine)
+
+static BYTE MemoryRoutine[] = { // INT 12h code
+ OPX_PUSHDS,
+ OPX_MOVAX, 0x00, 0x00,
+ OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_DS,REG_AX),
+ OPX_MOVAXOFF, BYTESOFFSET(BIOSDATA_MEMORY_SIZE),
+ OPX_POPDS,
+ OPX_IRET
+};
+#define MEMORY_LENGTH sizeof(MemoryRoutine)
+
+
+VOID BiosInit(int argc, char *argv[]) {
+
+ PVOID Address, RomAddress;
+
+ // set up IVT with unimplemented interrupt handler
+
+ for (Address = NULL; Address < (PVOID)(0x1D * 4); (PCHAR)Address += 4) {
+ *(PWORD)Address = 0x100;
+ *(((PWORD)Address) + 1) = 0xF000;
+ }
+
+ RomAddress = (PVOID)(0xE000 << 4);
+
+ // set up warm boot handler
+ memcpy(RomAddress, WarmBoot, WARMBOOT_LENGTH);
+ Address = RMSEGOFFTOLIN(0, BIOSINT_WBOOT * 4);
+ *((PWORD)Address) = 0;
+ *((PWORD)Address + 1) = 0xE000;
+ (PCHAR)RomAddress += WARMBOOT_LENGTH;
+
+ // set up equipment interrupt handler
+ memcpy(RomAddress, EquipmentRoutine, EQUIPMENT_LENGTH);
+ Address = RMSEGOFFTOLIN(0, BIOSINT_EQUIP * 4);
+ *((PWORD)Address) = RMOFF(RomAddress);
+ *((PWORD)Address + 1) = RMSEG(RomAddress);
+ (PCHAR)RomAddress += EQUIPMENT_LENGTH;
+
+ // set up memory size interrupt handler
+ memcpy(RomAddress, MemoryRoutine, MEMORY_LENGTH);
+ Address = RMSEGOFFTOLIN(0, BIOSINT_MEMORY * 4);
+ *((PWORD)Address) = RMOFF(RomAddress);
+ *((PWORD)Address + 1) = RMSEG(RomAddress);
+
+ RomAddress = (PVOID)((0xF000 << 4) + 0x100);
+
+ Address = (PBYTE)RomAddress + 0xFE53;
+ *(PCHAR)Address = 0xCF; // IRET at f000:ff53
+
+ // set up unimplemented interrupt handler
+
+ memcpy(RomAddress, ServiceRoutine, SERVICE_LENGTH);
+ (PCHAR)RomAddress += SERVICE_LENGTH;
+
+ // set up reset code
+ memcpy(RMSEGOFFTOLIN(BIOSROM_SEG, BIOSROM_RESET), ResetRoutine, RESET_LENGTH);
+
+ // set up equipment byte and memory size
+
+ *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_EQUIP_FLAG) =
+ BIOSEQUIP_32KPLANAR;
+ *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_MEMORY_SIZE) =
+ 640;
+
+ // Initialize individual rom modules
+
+ BiosKbdInit(argc, argv, &RomAddress);
+ BiosVidInit(argc, argv, &RomAddress);
+}
diff --git a/private/mvdm/v86/scaffold/i386/fakekbd.c b/private/mvdm/v86/scaffold/i386/fakekbd.c
new file mode 100644
index 000000000..8e807548e
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/fakekbd.c
@@ -0,0 +1,281 @@
+
+//
+// Fake Keyboard rom support
+//
+// This file provides interrim support for keyboard rom bios services.
+// It is only intended for use until Insignia produces proper rom support
+// for NTVDM
+//
+// Note: portions of this code were lifted from the following source.
+
+/* x86 v1.0
+ *
+ * XBIOSKBD.C
+ * Guest ROM BIOS keyboard emulation
+ *
+ * History
+ * Created 20-Oct-90 by Jeff Parsons
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <conio.h>
+#include <string.h>
+#include "softpc.h"
+#include "bop.h"
+#include "xbios.h"
+#include "xbioskbd.h"
+#include "xwincon.h"
+#include "fun.h"
+#include <conapi.h>
+
+extern HANDLE InputHandle;
+
+#define MAX_KBD_BUFFER 256
+CHAR KbdBuffer[MAX_KBD_BUFFER];
+ULONG Head=0,Tail=0;
+HANDLE KbdSyncEvent;
+CRITICAL_SECTION csKbd;
+CRITICAL_SECTION csConsole;
+CRITICAL_SECTION csCtrlc;
+BOOL fEventThreadBlock = FALSE;
+HANDLE hConsoleWait;
+ULONG nCtrlc=0;
+
+HANDLE StdIn;
+
+static BYTE ServiceRoutine[] = { 0xC4, 0xC4, BOP_KBD, 0x50, 0x55, 0x8B,
+ 0xEC, 0x9C, 0x58, 0x89, 0x46, 0x08, 0x5d, 0x58, 0xCF };
+#define SERVICE_LENGTH sizeof(ServiceRoutine)
+
+/* BiosKbdInit - Initialize ROM BIOS keyboard support
+ *
+ * ENTRY
+ * argc - # of command-line options
+ * argv - pointer to first option pointer
+ * ServiceAddress - linear address to put service routine at
+ *
+ * EXIT
+ * TRUE if successful, FALSE if not
+ */
+
+BOOL BiosKbdInit(int argc, char *argv[], PVOID *ServiceAddress)
+{
+ PVOID Address;
+
+ argc, argv;
+
+ memcpy(*ServiceAddress, ServiceRoutine, SERVICE_LENGTH);
+
+ Address = (PVOID)(BIOSINT_KBD * 4);
+ *((PWORD)Address) = RMOFF(*ServiceAddress);
+ *(((PWORD)Address) + 1) = RMSEG(*ServiceAddress);
+ (PCHAR)*ServiceAddress += SERVICE_LENGTH;
+
+ StdIn = GetStdHandle(STD_INPUT_HANDLE);
+
+ KbdSyncEvent = CreateEvent( NULL, TRUE, FALSE,NULL );
+
+ InitializeCriticalSection (&csKbd);
+ InitializeCriticalSection(&csConsole);
+ InitializeCriticalSection(&csCtrlc);
+
+ hConsoleWait = CreateEvent (NULL,TRUE,FALSE,NULL);
+
+ return TRUE;
+}
+
+
+/* BiosKbd - Emulate ROM BIOS keyboard functions
+ *
+ * ENTRY
+ * None (x86 registers contain parameters)
+ *
+ * EXIT
+ * None (x86 registers/memory updated appropriately)
+ *
+ * This function receives control on INT 16h, routes control to the
+ * appropriate subfunction based on the function # in AH, and
+ * then simulates an IRET and returns back to the instruction emulator.
+ */
+
+VOID BiosKbdReadLoop (VOID)
+{
+ULONG Temp;
+
+ while (1) {
+
+ Temp = Head + 1;
+ if(Temp >= MAX_KBD_BUFFER)
+ Temp =0;
+ if(Temp == Tail){
+ Sleep (20);
+ continue;
+ }
+
+ KbdBuffer[Head] = getche();
+
+ EnterCriticalSection(&csConsole);
+ if(fEventThreadBlock == TRUE){
+ LeaveCriticalSection(&csConsole);
+ WaitForSingleObject(hConsoleWait,-1);
+ ResetEvent(hConsoleWait);
+ continue;
+ }
+ else{
+ LeaveCriticalSection(&csConsole);
+ }
+
+ EnterCriticalSection(&csKbd);
+ Head = Temp;
+ LeaveCriticalSection(&csKbd);
+ SetEvent(KbdSyncEvent);
+ }
+}
+
+BOOL tkbhit(VOID)
+{
+
+ if (Tail != Head || nCtrlc)
+ return TRUE;
+ return FALSE;
+}
+
+
+CHAR tgetch(VOID)
+{
+CHAR ch;
+
+ while(TRUE) {
+ EnterCriticalSection(&csCtrlc);
+ if (nCtrlc){
+ nCtrlc--;
+ LeaveCriticalSection(&csCtrlc);
+ return (CHAR)0x3; // return ctrlc
+ }
+ LeaveCriticalSection(&csCtrlc);
+
+ if (Tail != Head) {
+ EnterCriticalSection(&csKbd);
+ ch = KbdBuffer[Tail++];
+ if (Tail >= MAX_KBD_BUFFER)
+ Tail = 0;
+ LeaveCriticalSection(&csKbd);
+ return ch;
+ }
+ WaitForSingleObject(KbdSyncEvent, -1);
+ ResetEvent(KbdSyncEvent);
+ }
+}
+
+
+
+
+VOID BiosKbd()
+{
+ static ULONG ulch;
+ DWORD nRead=0;
+
+ switch(getAH()) {
+
+ case KBDFUNC_READCHAR:
+ if (ulch) {
+ setAL(ulch & 0xff);
+ setAH(ulch & 0xFF00);
+ ulch = 0;
+ }
+ else {
+ setAH(0); // zero scan code field for now
+ setAL((BYTE)tgetch());
+ if (getAL() == 0 || getAL() == 0xE0) {
+ setAL(0);
+ setAH((BYTE)tgetch());
+ }
+ }
+ break;
+
+ case KBDFUNC_PEEKCHAR:
+ setZF(1);
+ if (ulch) {
+ setAL(ulch & 0xFF);
+ setAH(ulch & 0xFF00);
+ setZF(0);
+ }
+ else if(tkbhit()) {
+ setAH(0); // zero scan code field for now
+ setAL((BYTE)tgetch());
+ if (getAL() == 0 || getAL() == 0xE0) {
+ setAL(0);
+ setAH((BYTE)tgetch());
+ }
+ ulch = getAL() | getAH()<<8 | 0x10000;
+ setZF(0);
+ }
+ break;
+ }
+}
+
+
+void nt_block_event_thread(void)
+{
+ INPUT_RECORD InputRecord;
+ DWORD nRecordsWritten;
+
+ InputRecord.EventType = 1;
+ InputRecord.Event.KeyEvent.bKeyDown = 1;
+ InputRecord.Event.KeyEvent.wRepeatCount = 1;
+ InputRecord.Event.KeyEvent.wVirtualKeyCode = 32;
+ InputRecord.Event.KeyEvent.wVirtualScanCode = 41;
+ InputRecord.Event.KeyEvent.uChar.AsciiChar = ' ';
+ InputRecord.Event.KeyEvent.dwControlKeyState = 32;
+ EnterCriticalSection(&csConsole);
+ WriteConsoleInput(InputHandle,&InputRecord,1,&nRecordsWritten);
+ InputRecord.EventType = 1;
+ InputRecord.Event.KeyEvent.bKeyDown = 0;
+ InputRecord.Event.KeyEvent.wRepeatCount = 1;
+ InputRecord.Event.KeyEvent.wVirtualKeyCode = 32;
+ InputRecord.Event.KeyEvent.wVirtualScanCode = 41;
+ InputRecord.Event.KeyEvent.uChar.AsciiChar = ' ';
+ InputRecord.Event.KeyEvent.dwControlKeyState = 32;
+ WriteConsoleInput(InputHandle,&InputRecord,1,&nRecordsWritten);
+ fEventThreadBlock = TRUE;
+ LeaveCriticalSection(&csConsole);
+ return;
+
+}
+
+void nt_resume_event_thread(void)
+{
+ fEventThreadBlock = FALSE;
+ SetEvent (hConsoleWait);
+ return;
+}
+
+// TEMP Till we have proper multitasking in WOW
+extern BOOL VDMForWOW;
+extern ULONG iWOWTaskId;
+
+
+VOID VDMCtrlCHandler(ULONG ulCtrlType)
+{
+// DebugBreak();
+ if(ulCtrlType == SYSTEM_ROOT_CONSOLE_EVENT) {
+ if(VDMForWOW)
+ // Kill everything for WOW VDM
+ ExitVDM(VDMForWOW,(ULONG)-1);
+ else
+ ExitVDM(FALSE,0);
+ ExitProcess(0);
+ return;
+ }
+ EnterCriticalSection(&csCtrlc);
+ nCtrlc++;
+ LeaveCriticalSection(&csCtrlc);
+ SetEvent(KbdSyncEvent);
+}
diff --git a/private/mvdm/v86/scaffold/i386/fakevid.c b/private/mvdm/v86/scaffold/i386/fakevid.c
new file mode 100644
index 000000000..450737c80
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/fakevid.c
@@ -0,0 +1,175 @@
+
+//
+// Fake video rom support
+//
+// This file provides interrim support for video rom bios services.
+// It is only intended for use until Insignia produces proper rom support
+// for NTVDM
+//
+// Note: portions of this code were lifted from the following source.
+
+
+/* x86 v1.0
+ *
+ * XBIOSVID.C
+ * Guest ROM BIOS video emulation
+ *
+ * History
+ * Created 20-Oct-90 by Jeff Parsons
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <conio.h>
+#include "softpc.h"
+#include "bop.h"
+#include "xbios.h"
+#include "xbiosvid.h"
+#include "xwincon.h"
+#include "fun.h"
+#include "cmdsvc.h"
+
+static BYTE ServiceRoutine[] = { 0xC4, 0xC4, BOP_VIDEO, 0x50, 0x55, 0x8B,
+ 0xEC, 0x9C, 0x58, 0x89, 0x46, 0x08, 0x5d, 0x58, 0xCF };
+#define SERVICE_LENGTH sizeof(ServiceRoutine)
+
+extern HANDLE OutputHandle;
+extern HANDLE InputHandle;
+
+/* BiosVidInit - Initialize ROM BIOS video support
+ *
+ * ENTRY
+ * argc - # of command-line options
+ * argv - pointer to first option pointer
+ * ServicAddress - pointer to linear address to put interrupt service
+ * routine at
+ *
+ * EXIT
+ * TRUE if successful, FALSE if not
+ */
+
+BOOL BiosVidInit(int argc, char *argv[], PVOID *ServiceAddress)
+{
+ USHORT usEquip;
+
+ static BYTE abVidInit[] = {VIDMODE_MONO, // VIDDATA_CRT_MODE
+ 0x80, 0, // VIDDATA_CRT_COLS
+ 00, 0x10, // VIDDATA_CRT_LEN
+ 0, 0, // VIDDATA_CRT_START
+ 0,0,0,0,0,0,0,0, // VIDDATA_CURSOR_POSN
+ 0,0,0,0,0,0,0,0, //
+ 7, 6, // VIDDATA_CURSOR_MODE
+ 0, // VIDDATA_ACTIVE_PAGE
+ 0xD4, 0x03, // VIDDATA_ADDR_6845
+ 0, // VIDDATA_CRT_MODE_SET
+ 0, // VIDDATA_CRT_PALETTE
+ };
+ PVOID Address;
+
+ argv, argc;
+ memcpy(*ServiceAddress, ServiceRoutine, SERVICE_LENGTH);
+
+ Address = (PVOID)(BIOSINT_VID * 4);
+ *((PWORD)Address) = RMOFF(*ServiceAddress);
+ *(((PWORD)Address) + 1) = RMSEG(*ServiceAddress);
+ (PCHAR)*ServiceAddress += SERVICE_LENGTH;
+
+ usEquip = *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_EQUIP_FLAG);
+ usEquip |= BIOSEQUIP_MONOVIDEO;
+ *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_EQUIP_FLAG) = usEquip;
+
+ // Initialize ROM BIOS video data to defaults
+ Address = RMSEGOFFTOLIN(BIOSDATA_SEG, VIDDATA_CRT_MODE);
+ memcpy(Address, abVidInit, sizeof(abVidInit));
+
+#if 0
+#ifdef WIN
+ clearconsole(hwndGuest);
+#endif
+#endif
+ return TRUE;
+}
+
+
+/* BiosVid - Emulate ROM BIOS video functions
+ *
+ * ENTRY
+ * None (x86 registers contain parameters)
+ *
+ * EXIT
+ * None (x86 registers/memory updated appropriately)
+ *
+ * This function receives control on INT 10h, routes control to the
+ * appropriate subfunction based on the function # in AH, and
+ * then simulates an IRET and returns back to the instruction emulator.
+ */
+
+VOID BiosVid()
+{
+COORD coord;
+CHAR ch;
+
+ if (fEnableInt10 == FALSE)
+ return;
+
+ switch(getAH()) {
+ case VIDFUNC_SETCURSORPOS:
+ coord.X = getDL();
+ coord.Y = getDH();
+ if(SetConsoleCursorPosition(OutputHandle, coord) == FALSE)
+ VDprint(
+ VDP_LEVEL_WARNING,
+ ("SetCursorPosition Failed X=%d Y=%d\n",
+ coord.X,coord.Y)
+ );
+ break;
+ case VIDFUNC_QUERYCURSORPOS:
+ VDprint(
+ VDP_LEVEL_WARNING,
+ ("Query Cursor Position Not Yet Implemented\n")
+ );
+ break;
+ case VIDFUNC_SCROLLUP:
+ VDprint(
+ VDP_LEVEL_WARNING,
+ ("ScrollUp Not Yet Implemented\n")
+ );
+ break;
+ case VIDFUNC_WRITECHARATTR:
+ VDprint(
+ VDP_LEVEL_WARNING,
+ ("WRITECHARATTR Not Yet Implemented\n")
+ );
+ break;
+ case VIDFUNC_WRITETTY:
+ ch = getAL();
+ putch(ch);
+ break;
+
+ case VIDFUNC_QUERYMODE:
+ setAX(*(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, VIDDATA_CRT_MODE));
+ setBX(*(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, VIDDATA_ACTIVE_PAGE));
+ break;
+
+ default:
+ VDprint(
+ VDP_LEVEL_WARNING,
+ ("SoftPC Video Support: Unimplemented function %x\n",
+ getAX())
+ );
+ }
+}
+
+
+INT tputch(INT i)
+{
+ putch((CHAR)i);
+ return i;
+}
diff --git a/private/mvdm/v86/scaffold/i386/fun.h b/private/mvdm/v86/scaffold/i386/fun.h
new file mode 100644
index 000000000..d83a72a0c
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/fun.h
@@ -0,0 +1,24 @@
+//
+// function definitions for scaffolding code
+//
+
+VOID BiosInit(int argc, char *argv[]);
+BOOL WinInit();
+VOID DbgPrint();
+VOID DbgBreakPoint();
+BOOL W32Init();
+VOID main();
+VOID exit();
+BOOL BiosKbdInit(int argc, char *argv[], PVOID *ServiceAddress);
+BOOL BiosDskInit(int argc, char *argv[], PVOID *ServiceAddress);
+BOOL BiosVidInit(int argc, char *argv[], PVOID *ServiceAddress);
+VOID W32Dispatch();
+VOID XMSDispatch();
+VOID BiosVid();
+VOID BiosKbd();
+VOID BiosDsk();
+VOID BiosKbdReadLoop (VOID);
+BOOL tkbhit(VOID);
+CHAR tgetch(VOID);
+INT tputch(INT);
+VOID FixConfigFile (PSZ,BOOL);
diff --git a/private/mvdm/v86/scaffold/i386/softpc.c b/private/mvdm/v86/scaffold/i386/softpc.c
new file mode 100644
index 000000000..b97ee53a9
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/softpc.c
@@ -0,0 +1,442 @@
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <ctype.h>
+#include "demexp.h"
+#include "softpc.h"
+#include <cmdsvc.h>
+#include <xmssvc.h>
+#include <dbgexp.h>
+#include "xwincon.h"
+#include "fun.h"
+#include <conapi.h>
+
+#define VDM_VIRTUAL_INTERRUPTS 0x00000200L
+extern CONTEXT IntelRegisters;
+
+VOID DumpIntelRegs();
+VOID ParseSwitches( int, char**);
+VOID usage();
+BOOL ConInit (VOID);
+extern VOID VDMCtrlCHandler(ULONG);
+
+INT flOptions;
+
+HANDLE OutputHandle;
+HANDLE InputHandle;
+HANDLE SCSCreateEvent;
+char *EmDirectory;
+BOOL scaffMin = FALSE;
+BOOL scaffWow = FALSE;
+BOOL VDMForWOW = FALSE;
+CHAR BootLetter;
+
+
+void main (argc, argv)
+int argc;
+char *argv[];
+{
+
+ PSZ psz,pszNULL;
+ HANDLE hfile;
+ DWORD BytesRead;
+ int i;
+ PCHAR FileAddress;
+ BOOL IsFirst;
+ int temp_argc = argc;
+ char **temp_argv = argv;
+
+// DebugBreak();
+
+ if(SetConsoleCtrlHandler((PHANDLER_ROUTINE)VDMCtrlCHandler,TRUE)
+ == FALSE) {
+ VDprint(
+ VDP_LEVEL_INFO,
+ ("CtrlC Handler Could'nt be installed\n")
+ );
+ }
+
+ // Tell the console that we want the last event (i.e when the
+ // window is just to be destroyed.
+ SetLastConsoleEventActive();
+
+ // Check if the VDM Is for WOW
+ while (--temp_argc > 0) {
+ psz = *++temp_argv;
+ if (*psz == '-' || *psz == '/') {
+ psz++;
+ if(tolower(*psz) == 'w'){
+ VDMForWOW = TRUE;
+ break;
+ }
+ }
+ }
+
+ // This following API is required for recovery purposes. This
+ // tells the basesrv that VDM has hooked ctrlc event. After
+ // this it will always get the termination notification. If
+ // the window is killed before we hook ctrl-c then basesrv
+ // will know that data structures for this VDM has to be
+ // freed. This should be the first call to base.dll.
+
+ VDMOperationStarted (VDMForWOW);
+
+ EmDirectory = NULL;
+
+ // Hide the cmd window of WOWVDM
+ if(VDMForWOW)
+ VDMConsoleOperation((DWORD)VDM_HIDE_WINDOW);
+
+ ParseSwitches( argc, argv );
+
+ IsFirst = GetNextVDMCommand(NULL);
+
+ for (i = 0; i < argc; i++) {
+ VDprint(
+ VDP_LEVEL_INFO,
+ ("%s\n", argv[i])
+ );
+ }
+
+ VDbreak(VDB_LEVEL_INFO);
+
+ if (EmDirectory == NULL) {
+ usage();
+ TerminateVDM();
+ }
+
+ // Sudeepb 26-Dec-1991 Temporary code to make
+ // the life easy for WOW's internal users such that they dont have
+ // to change the config.sys as per their setup.
+
+ FixConfigFile (EmDirectory,IsFirst);
+
+ pszNULL = strchr(EmDirectory,'\0');
+ psz = EmDirectory;
+ while(*psz == ' ' || *psz == '\t')
+ psz++;
+
+ BootLetter = *psz;
+
+ host_cpu_init();
+ sas_init(1024L * 1024L + 64L * 1024L);
+
+ // Initialize ROM support
+
+ BiosInit(argc, argv);
+
+ // Initialize console support
+
+ if (!ConInit()) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: error initializing console\n")
+ );
+ TerminateVDM();
+ }
+
+ // Initialize WOW
+
+
+ CMDInit (argc,argv);
+
+ // Initialize DOSEm
+
+ if(!DemInit (argc,argv,EmDirectory)) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: error initializing DOSEm\n")
+ );
+ TerminateVDM();
+ }
+
+ // Initialize XMS
+
+ if(!XMSInit (argc,argv)) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: error initializing XMS\n")
+ );
+ TerminateVDM();
+ }
+
+ // Initialize DBG
+
+ if(!DBGInit (argc,argv)) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: error initializing DBG\n")
+ );
+ TerminateVDM();
+ }
+
+ // Prepare to load ntio.sys
+ strcat (EmDirectory,"\\ntio.sys");
+ hfile = CreateFile(EmDirectory,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+
+ if (hfile == (HANDLE)0xffffffff) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: could not open file %s. Error %d\n",
+ EmDirectory,
+ GetLastError())
+ );
+ TerminateVDM();
+ }
+
+ FileAddress = (PCHAR)0x700;
+ BytesRead = 1;
+ while (BytesRead) {
+ if (!ReadFile(hfile, FileAddress, 16384, &BytesRead, NULL)) {
+ VDprint(
+ VDP_LEVEL_ERROR,
+ ("SoftPC: read failure on file %s. Error %d\n",
+ EmDirectory,
+ GetLastError())
+ );
+ TerminateVDM();
+ }
+
+ VDprint(VDP_LEVEL_INFO,
+ ("SoftPC: read a block of file %s\n",
+ EmDirectory)
+ );
+ FileAddress = (PCHAR)FileAddress + BytesRead;
+ }
+
+ VDprint(VDP_LEVEL_WARNING,
+ ("SoftPC: using Emulation file %s\n",
+ EmDirectory)
+ );
+
+ VDbreak(VDB_LEVEL_INFO);
+
+ CloseHandle (hfile);
+
+ // restore the emulation directory
+ *pszNULL = 0;
+
+
+ IntelRegisters.Eip = 0x0;
+ IntelRegisters.SegCs = 0x70;
+ IntelRegisters.EFlags = VDM_VIRTUAL_INTERRUPTS;
+
+ host_simulate();
+
+ if (IntelRegisters.EFlags & VDM_VIRTUAL_INTERRUPTS) {
+ VDprint(VDP_LEVEL_INFO, ("Virtual ints enabled\n"));
+ } else {
+ VDprint(VDP_LEVEL_INFO, ("Virtual ints disabled\n"));
+ }
+
+ DumpIntelRegs();
+}
+
+#define MAX_CONFIG_SIZE 1024
+
+VOID FixConfigFile (pszBin86Dir,IsFirstVDM)
+PSZ pszBin86Dir;
+BOOL IsFirstVDM;
+{
+
+ // Temporary code. To be thrown out once we have full configuration
+ // and installation.
+
+CHAR ConfigFile[]="?:\\config.vdm";
+CHAR Buffer [MAX_CONFIG_SIZE];
+DWORD len,i;
+DWORD BytesRead,BytesWritten;
+HANDLE hfile;
+
+ if (IsFirstVDM == FALSE)
+ return;
+
+ ConfigFile[0] = *pszBin86Dir;
+ hfile = CreateFile( ConfigFile,
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+ if (hfile == (HANDLE)0xffffffff) {
+ DbgPrint ("config.vdm is'nt found on the root drive of yout NT trre\n");
+ return;
+ }
+
+
+ if (!ReadFile(hfile, Buffer, MAX_CONFIG_SIZE, &BytesRead, NULL)){
+ DbgPrint ("config.vdm could'nt be read\n, %x\n",GetLastError ());
+ CloseHandle (hfile);
+ return;
+ }
+
+ if (BytesRead == MAX_CONFIG_SIZE) {
+ DbgPrint ("config.vdm is too big, could'nt perform macro substitution\n");
+ CloseHandle (hfile);
+ return;
+ }
+
+ SetFilePointer (hfile,
+ 0,
+ NULL,
+ FILE_BEGIN);
+
+ len = strlen (pszBin86Dir);
+
+ for (i=0; i < BytesRead; i++) {
+ if (Buffer [i] != '@'){
+ WriteFile (hfile,
+ &Buffer[i],
+ 1,
+ &BytesWritten,
+ NULL);
+ }
+ else {
+ WriteFile (hfile,
+ pszBin86Dir,
+ len,
+ &BytesWritten,
+ NULL);
+ }
+ }
+
+ CloseHandle (hfile);
+ return;
+}
+
+VOID DumpIntelRegs()
+{
+
+ VDprint(VDP_LEVEL_ERROR,("EAX = %lx\n",IntelRegisters.Eax));
+ VDprint(VDP_LEVEL_ERROR,("Ebx = %lx\n",IntelRegisters.Ebx));
+ VDprint(VDP_LEVEL_ERROR,("Ecx = %lx\n",IntelRegisters.Ecx));
+ VDprint(VDP_LEVEL_ERROR,("Edx = %lx\n",IntelRegisters.Edx));
+ VDprint(VDP_LEVEL_ERROR,("Esi = %lx\n",IntelRegisters.Esi));
+ VDprint(VDP_LEVEL_ERROR,("Edi = %lx\n",IntelRegisters.Edi));
+ VDprint(VDP_LEVEL_ERROR,("Ebp = %lx\n",IntelRegisters.Ebp));
+ VDprint(VDP_LEVEL_ERROR,("SegDs = %lx\n",IntelRegisters.SegDs));
+ VDprint(VDP_LEVEL_ERROR,("SegEs = %lx\n",IntelRegisters.SegEs));
+ VDprint(VDP_LEVEL_ERROR,("SegFs = %lx\n",IntelRegisters.SegFs));
+ VDprint(VDP_LEVEL_ERROR,("SegGs = %lx\n",IntelRegisters.SegGs));
+ VDprint(VDP_LEVEL_ERROR,("EFlags = %lx\n",IntelRegisters.EFlags));
+ VDprint(VDP_LEVEL_ERROR,("SS:Esp = %lx:",IntelRegisters.SegSs));
+ VDprint(VDP_LEVEL_ERROR,("%lx\n",IntelRegisters.Esp));
+ VDprint(VDP_LEVEL_ERROR,("CS:Eip = %lx:",IntelRegisters.SegCs));
+ VDprint(VDP_LEVEL_ERROR,("%lx\n",IntelRegisters.Eip));
+}
+
+VOID ParseSwitches(
+ int argc,
+ char **argv
+ )
+{
+ int i;
+
+ for (i = 1; i < argc; i++){
+ if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
+
+ switch (argv[i][1]) {
+
+ case 's' :
+ case 'S' :
+ sscanf(&argv[i][2], "%x", &VdmDebugLevel);
+ VDprint(
+ VDP_LEVEL_WARNING,
+ ("VdmDebugLevel = %x\n",
+ VdmDebugLevel)
+ );
+ break;
+
+ case 'f' :
+ case 'F' :
+ // Note this memory is freed by DEM.
+ if((EmDirectory = (PCHAR)malloc (strlen (&argv[i][2]) +
+ 1 +
+ sizeof("\\ntdos.sys") +
+ 1
+ )) == NULL){
+ DbgPrint("SoftPC: Not Enough Memory \n");
+ TerminateVDM();
+ }
+ strcpy(EmDirectory,&argv[i][2]);
+ break;
+
+ case 't' :
+ case 'T' :
+ flOptions |= OPT_TERMINAL;
+ break;
+ case 'm' :
+ case 'M' :
+ scaffMin = TRUE;
+ break;
+ case 'w' :
+ case 'W' :
+ scaffWow = TRUE;
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+VOID usage()
+{
+ DbgPrint("SoftPC Usage: softpc -F<emulation file> [-D#] [<drive>:=<virtual disk>] [dos command line]\n");
+}
+
+
+VOID TerminateVDM(void)
+{
+
+ if(VDMForWOW)
+ // Kill everything for WOW VDM
+ ExitVDM(VDMForWOW,(ULONG)-1);
+ else
+ ExitVDM(FALSE,0);
+ ExitProcess (0);
+}
+
+
+DWORD SCSConsoleThread(LPVOID lp)
+{
+
+
+ SetEvent(SCSCreateEvent);
+ BiosKbdReadLoop();
+ return TRUE;
+}
+
+
+BOOL ConInit (VOID)
+{
+ DWORD SCSThreadId;
+ HANDLE InputThread;
+ OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ InputHandle = GetStdHandle(STD_INPUT_HANDLE);
+
+ SCSCreateEvent = CreateEvent( NULL, TRUE, FALSE,NULL );
+
+ InputThread = CreateThread(
+ (LPSECURITY_ATTRIBUTES)0,
+ 8192,
+ (LPTHREAD_START_ROUTINE)SCSConsoleThread,
+ (LPVOID)0,
+ STANDARD_RIGHTS_REQUIRED,
+ &SCSThreadId
+ );
+
+ WaitForSingleObject(SCSCreateEvent, -1);
+
+ CloseHandle(SCSCreateEvent);
+
+ return TRUE;
+}
diff --git a/private/mvdm/v86/scaffold/i386/sources b/private/mvdm/v86/scaffold/i386/sources
new file mode 100644
index 000000000..af03d8fa3
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/sources
@@ -0,0 +1,6 @@
+i386_SOURCES=i386\softpc.c \
+ i386\fakeinit.c \
+ i386\fakekbd.c \
+ i386\fakevid.c \
+ i386\fakebop.c \
+ i386\stubs.c
diff --git a/private/mvdm/v86/scaffold/i386/stubs.c b/private/mvdm/v86/scaffold/i386/stubs.c
new file mode 100644
index 000000000..4ba53b52e
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/stubs.c
@@ -0,0 +1,46 @@
+void check_I(){
+}
+
+void copyROM(){
+}
+
+void generic_insb(){
+}
+void generic_insw(){
+}
+void generic_outsb(){
+}
+void generic_outsw(){
+}
+
+void host_timer_event(){
+}
+int ica_intack(){
+ return 7;
+}
+void inb(){
+}
+void inw(){
+}
+void outb(){
+}
+void outw(){
+}
+unsigned long *read_pointers;
+
+void rom_checksum(){
+}
+
+void rom_init(){
+}
+
+
+host_simulate(){
+ cpu_simulate();
+}
+
+host_cpu_init(){
+ cpu_init();
+}
+
+void (*ica_hw_interrupt_func)() = rom_init;
diff --git a/private/mvdm/v86/scaffold/i386/x86.h b/private/mvdm/v86/scaffold/i386/x86.h
new file mode 100644
index 000000000..eb4772e82
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/x86.h
@@ -0,0 +1,418 @@
+//
+// This is temporary code, and should be removed when Insignia supplies rom
+// support
+//
+
+/* x86 v1.0
+ *
+ * X86.H
+ * Constants, macros, and common types
+ * for the x86 emulator and related components
+ *
+ * History
+ * Created 19-Oct-90 by Jeff Parsons
+ * 17-Apr-91 by Dave Hastings trimmed for use in softpc (temprorary)
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+#ifdef DOS
+#define SIGNALS
+#endif
+
+#ifdef OS2_16
+#define OS2
+#define SIGNALS
+#endif
+
+#ifdef OS2_32
+#define OS2
+#define FLAT_32
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <process.h>
+
+#ifdef WIN_16
+#define WIN
+#define API16
+#endif
+
+#ifdef WIN_32
+#ifndef WIN
+#define WIN
+#endif
+#define FLAT_32
+#define TRUE_IF_WIN32 1
+#define FIXHWND(h) ((HWND)((INT)(h) & 0x00ffffff))
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#else
+#define TRUE_IF_WIN32 0
+#define FIXHWND(h) (h)
+#endif
+
+#ifdef FLAT_32
+#ifndef i386
+#define ALIGN_32
+#else
+#define NOALIGN_32
+#endif
+#endif
+
+#ifdef WIN
+#define _WINDOWS
+#include <windows.h>
+#endif
+
+#ifdef SIGNALS
+#include <conio.h>
+#include <signal.h>
+#endif
+
+#ifdef OS2_32
+#include <excpt.h>
+#define XCPT_SIGNAL 0xC0010003
+#endif
+#define SIGHIT(flChk) ((iSigCheck++ & 0x7FF)?(flSignals & (flChk)):(kbhit(),(flSignals & (flChk))))
+
+#ifndef CONST
+#define CONST const
+#endif
+#ifndef CDECL
+#define CDECL _cdecl
+#endif
+#ifndef PASCAL
+#define PASCAL
+#endif
+
+#ifdef FLAT_32
+#ifndef WIN
+#define FAR
+#endif
+#define HUGE
+#define HALLOC(n,s) malloc((n)*(s))
+#define HLOCK(h) h
+#define HUNLOCK(h) 0
+#define HFREE(h) free(h)
+#else
+#ifndef WIN
+#define FAR _far
+#define HUGE _huge
+#define HALLOC(n,s) halloc(n,s)
+#define HLOCK(h) h
+#define HUNLOCK(h) 0
+#define HFREE(h) hfree(h)
+#else
+#define HUGE _huge
+#define HALLOC(n,s) GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,(n)*(s))
+#define HLOCK(h) (HPVOID)GlobalLock(h)
+#define HUNLOCK(h) GlobalUnlock(h)
+#define HFREE(h) GlobalFree(h)
+#endif
+#endif
+
+#define BYTEOF(i,n) (((PBYTE)&(i))[n])
+#define LOB(i) BYTEOF(i,0)
+#define HIB(i) BYTEOF(i,1)
+#define WORDOF(i,n) (((PWORD)&(i))[n])
+#define LOW(l) WORDOF(l,0)
+#define HIW(l) WORDOF(l,1)
+#define INTOF(i,n) (((PINT)&(i))[n])
+#define UINTOF(i,n) (((PUINT)&(i))[n])
+#ifndef WIN
+#define LOWORD(l) ((WORD)(l))
+#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
+#define LOBYTE(w) ((BYTE)(w))
+#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF))
+#endif
+#ifndef MAKEWORD
+#define MAKEWORD(l,h) ((WORD)((BYTE)(l)|((BYTE)(h)<<8)))
+#endif
+#define MAKEDWORD(l0,h0,l1,h1) ((DWORD)MAKEWORD(l0,h0)|((DWORD)MAKEWORD(l1,h1)<<16))
+#define GETBYTE(p) *((PBYTE)p)++
+#define GETBYTEPTR(p) ((PBYTE)p)++
+#define GETWORDPTR(pb) ((PWORD)pb)++
+#define GETDWORDPTR(pb) ((PDWORD)pb)++
+#ifndef ALIGN_32
+#define GETWORD(pb) (*((PWORD)pb)++)
+#define GETDWORD(pb) (*((PDWORD)pb)++)
+#define FETCHWORD(s) ((WORD)(s))
+#define FETCHDWORD(s) ((DWORD)(s))
+#define STOREWORD(d,s) (WORD)d=(WORD)s
+#define STOREDWORD(d,s) (DWORD)d=(DWORD)s
+#else
+#define GETWORD(pb) (pb+=2,MAKEWORD(*(pb-2),*(pb-1)))
+#define GETDWORD(pb) (pb+=4,MAKEDWORD(*(pb-4),*(pb-3),*(pb-2),*(pb-1)))
+#define FETCHWORD(s) MAKEWORD(LOB(s),HIB(s))
+#define FETCHDWORD(s) MAKEDWORD(BYTEOF(s,0),BYTEOF(s,1),BYTEOF(s,2),BYTEOF(s,3))
+#define STOREWORD(d,s) {BYTEOF(d,0)=LOBYTE(s);BYTEOF(d,1)=HIBYTE(s);}
+#define STOREDWORD(d,s) {BYTEOF(d,0)=LOBYTE(LOWORD(s));BYTEOF(d,1)=HIBYTE(LOWORD(s));BYTEOF(d,2)=LOBYTE(HIWORD(s));BYTEOF(d,3)=HIBYTE(HIWORD(s));}
+#endif
+#define SWAP(x,y) {INT t; t=y; y=x; x=t;}
+#define SWAPS(x,y) {SHORT t; t=y; y=x; x=t;}
+#define SWAPL(x,y) {LONG t; t=y; y=x; x=t;}
+#define SWAPBYTE(x,y) {BYTE t; t=y; y=x; x=t;}
+#define SWAPWORD(x,y) {WORD t; t=FETCHWORD(y); STOREWORD(y,FETCHWORD(x)); STOREWORD(x,t);}
+#define SWAPDWORD(x,y) {DWORD t; t=FETCHDWORD(y); STOREDWORD(y,FETCHDWORD(x)); STOREDWORD(x,t);}
+#define NUMEL(a) ((sizeof a)/(sizeof a[0]))
+
+#define SXBYTE(i) ((LONG)(SBYTE)(i))
+#define SXWORD(i) ((LONG)(SHORT)(i))
+#define SXSHORT(i) ((LONG)(SHORT)(i))
+#define ZXBYTE(i) ((ULONG)(BYTE)(i))
+#define ZXWORD(i) ((ULONG)(USHORT)(i))
+#define ZXSHORT(i) ((ULONG)(USHORT)(i))
+
+#define _Z2(m) ((m)&1?0:(m)&2?1:2)
+#define _Z4(m) ((m)&3?_Z2(m):_Z2((m)>>2)+2)
+#define _Z8(m) ((m)&15?_Z4(m):_Z4((m)>>4)+4)
+#define _Z16(m) ((m)&255?_Z8(m):_Z8((m)>>8)+8)
+#define _Z32(m) ((m)&65535?_Z16(m):_Z16((m)>>16)+16)
+#define SHIFTLEFT(i,m) (((i)<<_Z32(m))&(m))
+#define SHIFTRIGHT(i,m) (((i)&(m))>>_Z32(m))
+
+#define OFFSETOF(t,f) ((INT)&(((t *)0)->f))
+
+
+/* Universal constants
+ */
+#define K 1024L
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+#define UNDEFINED -1
+
+#define CTRL_A 1 // used by gets to repeat last line
+#define CTRL_C 3 // break in debug window
+#define CTRL_Q 17 // flow control
+#define CTRL_S 19 // flow control
+#define BELL 7 //
+#define BS 8 // backspace
+#define TAB 9 //
+#define LF 10 // linefeed
+#define CR 13 // return
+#define ESCAPE 27 //
+
+
+/* Program options
+ */
+#define OPT_FONT 0x0004 // use small OEM font if available (/s)
+#define OPT_DOUBLE 0x0020 // use 50-line debug window w/small font (/50)
+#define OPT_CAPS 0x0002 // map ctrl keys to caps-lock (/c)
+#define OPT_TERMINAL 0x0010 // redirect all window output to terminal (/t)
+#define OPT_FLUSH 0x0100 // flush prefetch after every jump (/f)
+#define OPT_NOXLATE 0x0200 // disable built-in translations (/n)
+#define OPT_DEBUG 0x0008 // shadow all log output on debug terminal (/d)
+#define OPT_GO 0x0001 // do an initial "go" (/g)
+
+
+/* Signal flags
+ */
+#define SIGNAL_BREAK 0x0001 // set whenever break has occurred
+#define SIGNAL_UNWIND 0x0002 // set whenever unwind has occurred
+#define SIGNAL_REBOOT 0x0004 // set whenever reboot has occurred
+#define SIGNAL_RUN 0x0008 // set whenever emulator is "running"
+#define SIGNAL_TRACE 0x0010 // set whenever debugger tracing
+#define SIGNAL_BRKPT 0x0020 // set whenever debugger breakpoints enabled
+#define SIGNAL_SSTEP 0x0040 // set whenever emulator single-step on
+
+#undef SIG_IGN // fix broken definition in (old) signal.h
+#define SIG_IGN (VOID (CDECL *)())1
+
+
+/* Exec flags (for HostInput/GuestInput)
+ */
+#define EXEC_INPUT 0x0000 // wait for input
+#define EXEC_GO 0x0001 // execute immediately
+#define EXEC_FREEZE 0x0002 // execution frozen (guest only)
+
+
+/* Standard types
+ */
+#ifndef WIN
+typedef void VOID;
+typedef unsigned char BYTE;
+typedef unsigned short WORD; // confusing - use where 16-bit req. only
+typedef unsigned long DWORD; // confusing - use where 32-bit req. only
+typedef long LONG; // use where 32-bit req. only
+typedef int BOOL;
+#endif
+typedef char CHAR;
+typedef signed char SBYTE;
+typedef short SHORT; // use where 16-bit req. only
+typedef unsigned short USHORT; // use where 16-bit req. only
+typedef int INT; // ints preferred
+typedef unsigned int UINT; // ints preferred
+typedef unsigned long ULONG; // use where 32-bit req. only
+
+#ifndef WIN
+typedef BYTE *PBYTE; // native pointers
+typedef WORD *PWORD;
+typedef DWORD *PDWORD;
+typedef INT *PINT;
+typedef LONG *PLONG;
+typedef CHAR *PSTR;
+#endif
+typedef PBYTE *PPBYTE;
+typedef PWORD *PPWORD;
+typedef PDWORD *PPDWORD;
+typedef CHAR SZ[];
+typedef VOID *PVOID;
+typedef CHAR *PCHAR;
+typedef SHORT *PSHORT;
+typedef USHORT *PUSHORT;
+typedef PUSHORT *PPUSHORT;
+typedef UINT *PUINT;
+typedef ULONG *PULONG;
+typedef PULONG *PPULONG;
+typedef BOOL *PBOOL;
+typedef CHAR *PSZ;
+typedef PSZ *PPSZ;
+
+typedef VOID FAR *FPVOID; // "far" (or "long" in Windows) pointers
+typedef CHAR FAR *FPCHAR;
+typedef BYTE FAR *FPBYTE;
+typedef SHORT FAR *FPSHORT;
+typedef USHORT FAR *FPUSHORT;
+typedef LONG FAR *FPLONG;
+typedef ULONG FAR *FPULONG;
+typedef CHAR FAR *FPSTR;
+typedef CHAR FAR *FPSZ;
+
+typedef VOID HUGE *HPVOID; // "huge" pointers
+typedef CHAR HUGE *HPCHAR;
+typedef BYTE HUGE *HPBYTE;
+typedef SHORT HUGE *HPSHORT;
+typedef USHORT HUGE *HPUSHORT;
+typedef LONG HUGE *HPLONG;
+typedef ULONG HUGE *HPULONG;
+typedef CHAR HUGE *HPSTR;
+typedef CHAR HUGE *HPSZ;
+
+#ifndef WIN
+typedef HPVOID HANDLE;
+#endif
+
+#ifdef WIN
+typedef INT (FAR PASCAL *INTPROC)(HWND, UINT, UINT, LONG);
+#endif
+#ifdef WIN_16
+typedef LONG (FAR PASCAL *WNDPROC)(HWND, WORD, UINT, LONG);
+#endif
+
+
+/* Global data
+ */
+extern FILE *hfLog;
+extern INT flOptions; // command-line options (see OPT_*)
+extern INT flSignals; // signal flags (see SIGNAL_*)
+extern INT iSigCheck; // counter indicating when to make next check
+extern INT iSigLevel; // counter indicating whether to take default action
+extern INT iLogLevel; // logging level; 0 implies none
+extern BOOL fReinit; // set once first initialization has completed
+
+
+/* String macros
+ */
+#define STRSKIP(psz,sz) psz += strspn(psz, sz)
+#define STRSKIPTO(psz,sz) psz += strcspn(psz, sz)
+#define STRSKIPNEXT(psz,sz) psz += strspn(psz+=strcspn(psz, sz), sz)
+
+#define ATOI(psz) (INT)szTOul(psz, 10, -1)
+
+
+/* Logging macros
+ */
+#define IFLOG(l) if (l==iLogLevel && (iLogLevel&1) || l<=iLogLevel && !(iLogLevel&1))
+
+#define OPENLOG() (hfLog?hfLog:(hfLog=fopen("log", "w")))
+#define APPENDLOG() (hfLog?hfLog:(hfLog=fopen("log", "a")))
+#define CLOSELOG() if (hfLog) {fclose(hfLog); hfLog=NULL;}
+
+#ifdef NOLOG
+#define LOG(l,args)
+#else
+#define LOG(l,args) IFLOG(l) logprintf args; else
+#endif
+
+
+/* Debugging macros
+ */
+#define MODNAME(module) static char szModule[] = __FILE__
+#define X86ERROR() terminate(ERR_ASSERT, szModule, __LINE__)
+
+#ifdef DEBUG
+
+#define STATIC
+#define INT3() _asm int 3
+#define IFDEBUG(f) if (f)
+#define ELSEDEBUG else
+#define LOGDEBUG(l,args) LOG(l,args)
+#define X86ASSERT(exp) if (!(exp)) X86ERROR()
+
+#else
+
+#define STATIC static
+#define INT3()
+#define IFDEBUG(f)
+#define ELSEDEBUG
+#define LOGDEBUG(l,args)
+#define X86ASSERT(exp)
+
+#endif // DEBUG
+
+
+/* Other common local include files
+ */
+#ifdef X86
+#include "xerr.h"
+#include "xlib.h"
+#endif
+
+
+/* Windows goop
+ */
+#define SZ_APP "x86"
+#define SZ_TITLE "x86 emulator v0.17"
+#define SZ_AUTHOR "by Jeff Parsons, (C) 1991"
+#define SZ_PCTITLE "x86 pc"
+
+#define IDM_DBBRK 100
+#define IDM_ABOUT 101
+
+/* Standard color definitions
+ */
+#define CLR_BLACK 0x00000000
+#define CLR_RED 0x007F0000
+#define CLR_GREEN 0x00007F00
+#define CLR_BROWN 0x007F7F00
+#define CLR_BLUE 0x0000007F
+#define CLR_MAGENTA 0x007F007F
+#define CLR_CYAN 0x00007F7F
+#define CLR_LT_GRAY 0x00BFBFBF
+
+#define CLR_DK_GRAY 0x007F7F7F
+#define CLR_BR_RED 0x00FF0000
+#define CLR_BR_GREEN 0x0000FF00
+#define CLR_YELLOW 0x00FFFF00
+#define CLR_BR_BLUE 0x000000FF
+#define CLR_BR_MAGENTA 0x00FF00FF
+#define CLR_BR_CYAN 0x0000FFFF
+#define CLR_WHITE 0x00FFFFFF
+
+
+extern HANDLE hHostInstance;
diff --git a/private/mvdm/v86/scaffold/i386/xbios.h b/private/mvdm/v86/scaffold/i386/xbios.h
new file mode 100644
index 000000000..253f6e1e3
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/xbios.h
@@ -0,0 +1,123 @@
+//
+// This code is temporary. When Insignia supplies rom support, it should
+// be removed.
+//
+
+/* x86 v1.0
+ *
+ * XBIOS.H
+ * Guest ROM BIOS support
+ *
+ * History
+ * Created 20-Oct-90 by Jeff Parsons
+ * 17-Apr-91 Trimmed by Dave Hastings for use in temp. softpc
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+
+/* BIOS interrupts
+ */
+#define BIOSINT_DIVZERO 0x00 //
+#define BIOSINT_SSTEP 0x01 //
+#define BIOSINT_NMI 0x02 // for parity errors, too
+#define BIOSINT_BRKPT 0x03 //
+#define BIOSINT_OVFL 0x04 //
+#define BIOSINT_PRTSC 0x05 //
+#define BIOSINT_TMRINT 0x08 //
+#define BIOSINT_KBDINT 0x09 //
+#define BIOSINT_COM2INT 0x0B //
+#define BIOSINT_COM1INT 0x0C //
+#define BIOSINT_LPT2INT 0x0D //
+#define BIOSINT_FLPYINT 0x0E //
+#define BIOSINT_LPT1INT 0x0F //
+#define BIOSINT_VID 0x10 //
+#define BIOSINT_EQUIP 0x11 //
+#define BIOSINT_MEMORY 0x12 //
+#define BIOSINT_DSK 0x13 //
+#define BIOSINT_COM 0x14 //
+#define BIOSINT_OSHOOK 0x15 //
+#define BIOSINT_KBD 0x16 //
+#define BIOSINT_PRT 0x17 //
+#define BIOSINT_BASIC 0x18 //
+#define BIOSINT_WBOOT 0x19 //
+#define BIOSINT_TIME 0x1A //
+#define BIOSINT_CTRLBRK 0x1B //
+#define BIOSINT_TICK 0x1C //
+#define BIOSINT_VIDPARMS 0x1D //
+#define BIOSINT_FDSKPARMS 0x1E //
+#define BIOSINT_VIDGRAPH 0x1F //
+#define BIOSINT_OLDDISKIO 0x40 //
+#define BIOSINT_HDSK1PARMS 0x41 //
+#define BIOSINT_OLDVID 0x42 //
+#define BIOSINT_EXTVIDGRAPH 0x43 //
+#define BIOSINT_HDSK2PARMS 0x46 //
+
+
+/* BIOS Data Area locations
+ *
+ * So that all low-memory references are relative to the same segment
+ * (ie, 0), we use 0:400 instead of 40:0 as the base address of this area.
+ *
+ * Note that as more individual BIOS modules are created (eg, xbiosvid,
+ * xbiosdsk, etc), many of these BIOS data definitions should be moved to the
+ * appropriate individual header file.
+ */
+#define BIOSDATA_SEG 0
+
+#define BIOSDATA_BEGIN 0x400
+#define BIOSDATA_RS232_BASE 0x400 // 4 COM adapter addresses
+#define BIOSDATA_PRINTER_BASE 0x408 // 4 LPT adapter addresses
+#define BIOSDATA_EQUIP_FLAG 0x410 // equipment flag (1 word)
+
+#define BIOSEQUIP_FLOPPY 0x0001 // machine has a floppy
+#define BIOSEQUIP_X87 0x0002 // X87=1 if coprocessor installed
+#define BIOSEQUIP_16KPLANAR 0x0000 //
+#define BIOSEQUIP_32KPLANAR 0x0004 //
+#define BIOSEQUIP_48KPLANAR 0x0008 //
+#define BIOSEQUIP_64KPLANAR 0x000C //
+#define BIOSEQUIP_PLANARMASK 0x000C //
+#define BIOSEQUIP_VIDEOMASK 0x0030 // video configuration bits
+#define BIOSEQUIP_COLOR40VIDEO 0x0010 //
+#define BIOSEQUIP_COLOR80VIDEO 0x0020 //
+#define BIOSEQUIP_MONOVIDEO 0x0030 //
+#define BIOSEQUIP_FLOPPYMASK 0x00C0 // # floppies-1 (if FLOPPY=1)
+#define BIOSEQUIP_COMMASK 0x0E00 // # COM ports
+#define BIOSEQUIP_PRINTERMASK 0xC000 // # LPT ports
+
+#define BIOSDATA_MFG_TST 0x412 // initialization flag (1 byte)
+#define BIOSDATA_MEMORY_SIZE 0x413 // memory size in K bytes (1 word)
+#define BIOSDATA_MFG_ERR_FLG 0x415 // mfg error codes (2 bytes)
+
+#define BIOSDATA_END 0x4FF
+
+#define BIOSDATA_BOOT 0x7C00
+
+
+/* BIOS ROM locations (assumed segment BIOSROM_SEG)
+ */
+#define BIOSROM_SEG 0xF000
+
+#define BIOSROM_WBOOT 0xE6F2
+#define BIOSROM_DSK 0xEC59
+#define BIOSROM_MEMORY 0xF841
+#define BIOSROM_EQUIP 0xF84D
+#define BIOSROM_IRET 0xFF53 // 1 byte IRET
+#define BIOSROM_RESET 0xFFF0 // 5 byte jmp
+#define BIOSROM_DATE 0xFFF5 // 8 byte date (eg, 04/24/81)
+#define BIOSROM_UNUSED1 0xFFFD
+#define BIOSROM_SIG 0xFFFE // PC ID byte
+#define BIOSROM_GBP 0xFFFF // location of GBP opcode (non-standard)
+
+#define BIOSSIG_PC 0xFF
+#define BIOSSIG_XT 0xFE
+#define BIOSSIG_JR 0xFD
+#define BIOSSIG_AT 0xFC // and many more...
+
+#define BIOSDATE_MINE '0','4','/','1','7','/','9','1'
+
+
diff --git a/private/mvdm/v86/scaffold/i386/xbiosdsk.h b/private/mvdm/v86/scaffold/i386/xbiosdsk.h
new file mode 100644
index 000000000..ecfa6540b
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/xbiosdsk.h
@@ -0,0 +1,244 @@
+//
+// This code is temporary. When Insignia supplies rom support, it should
+// be removed.
+//
+
+/* x86 v1.0
+ *
+ * XBIOSDSK.H
+ * Guest ROM BIOS disk emulation
+ *
+ * History
+ * Created 20-Oct-90 by Jeff Parsons
+ * 17-Apr-91 Trimmed by Dave Hastings for use in temp. softpc
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+
+#define MAX_FD 2 // # supported floppy drives
+#define MAX_HD 2 // # supported hard disk drives
+#define MAX_DRIVES (MAX_FD+MAX_HD)
+
+#define DRIVE_FD0 0x00 // first floppy disk drive #
+#define DRIVE_FD1 0x01 //
+#define DRIVE_HD0 0x80 // first hard disk drive #
+#define DRIVE_HD1 0x81 //
+
+
+/* Drive types for QUERYDRVPARMS
+ */
+#define DRVTYPE_360KB 1
+#define DRVTYPE_1200KB 2
+#define DRVTYPE_720KB 3
+#define DRVTYPE_1440KB 4
+
+
+/* BIOS disk functions
+ */
+#define DSKFUNC_DISKRESET 0x00
+#define DSKFUNC_DISKSTATUS 0x01
+#define DSKFUNC_READSECTORS 0x02
+#define DSKFUNC_WRITESECTORS 0x03
+#define DSKFUNC_VERIFYSECTORS 0x04
+#define DSKFUNC_FORMATTRACK 0x05
+#define DSKFUNC_QUERYDRVPARMS 0x08
+#define DSKFUNC_QUERYDASDTYPE 0x15
+#define DSKFUNC_QUERYCHANGE 0x16
+#define DSKFUNC_SETDISKTYPE 0x17
+#define DSKFUNC_SETMEDIATYPE 0x18
+
+
+/* BIOS disk status codes
+ */
+#define DSKSTAT_SUCCESS 0x00 // successful completion
+#define DSKSTAT_BADCMD 0x01 // bad command
+#define DSKSTAT_BADADDRMARK 0x02 // address mark not found
+#define DSKSTAT_WRITEPROTECT 0x03 // write on write-protected disk
+#define DSKSTAT_RECNOTFOUND 0x04 // sector not found
+#define DSKSTAT_BADRESET 0x05 // reset failed (HD)
+#define DSKSTAT_MEDIACHANGE 0x06 // media changed
+#define DSKSTAT_INITFAIL 0x07 // parm. act. failed (HD)
+#define DSKSTAT_BADDMA 0x08 // DMA overrun
+#define DSKSTAT_DMABOUNDARY 0x09 // DMA across 64K boundary
+#define DSKSTAT_BADSECTOR 0x0A // bad sector detected (HD)
+#define DSKSTAT_BADTRACK 0x0B // bad track detected (HD)
+#define DSKSTAT_BADMEDIATYPE 0x0C // unsupported track (HD)
+#define DSKSTAT_BADFMTSECNUM 0x0D // bad # of sectors on format (HD)
+#define DSKSTAT_ADDRMARKDET 0x0E // ctrl data addr mark detected (HD
+#define DSKSTAT_DMAARBERR 0x0F // DMA arbitration error (HD)
+#define DSKSTAT_BADCRCECC 0x10 // bad CRC/ECC
+#define DSKSTAT_DATACORRECT 0x11 // data ECC corrected
+#define DSKSTAT_BADCNTLR 0x20 // controller failure
+#define DSKSTAT_BADSEEK 0x40 // seek failed
+#define DSKSTAT_TIMEOUT 0x80 // time out
+#define DSKSTAT_DRVNOTREADY 0xAA // drive not ready (HD)
+#define DSKSTAT_UNDEFERR 0xBB // undefined error (HD)
+#define DSKSTAT_WRITEFAULT 0xCC // write fault (HD)
+#define DSKSTAT_STATUSERROR 0xE0 // status register error (HD)
+#define DSKSTAT_SENSEFAIL 0xFF // sense operation failed (HD)
+
+
+/* BIOS Data Area disk locations
+ */
+#define DSKDATA_SEEKSTATUS 0x43E // drive recal. status (1 byte)
+#define DSKDATA_MOTORSTATUS 0x43F // motor status (1 byte)
+#define DSKDATA_MOTORCOUNT 0x440 // time-out count for motor (1 byte)
+#define DSKDATA_DISKETTESTATUS 0x441 // return code status (1 byte)
+#define DSKDATA_NECSTATUS 0x442 // controller status bytes (7 bytes)
+
+#define DSKDATA_DISKSTATUS1 0x474 // return code status (1 byte)
+
+
+/* Floppy Diskette Parameter Table
+ * (pointed by vector BIOSINT_FDSKPARMS (1Eh))
+ */
+typedef struct fdp_s {
+ BYTE bSpecify1; // step-rate, head-unload
+ BYTE bSpecify2; // head-load, DMA mode
+ BYTE bMotorOff; // motor-off delay
+ BYTE bSectorSize; // bytes/sec (0=128,1=256,2=512,3=1024)
+ BYTE nLastSector; // (or think of it as # sectors/track)
+ BYTE lenGapRW; //
+ BYTE lenData; //
+ BYTE lenGapFormat; //
+ BYTE bFormatData; // format initialization byte
+ BYTE bSettle; // head settle time
+ BYTE bMotorOn; // motor start-up time
+} FDP;
+typedef FDP *PFDP; // pointer to diskette parameter table
+
+
+/* Hard Disk Parameter Table
+ */
+typedef struct hdp_s {
+ USHORT usMaxCylinders; // maximum number of cylinders
+ BYTE bMaxHeads; // maximum number of heads
+ USHORT usReserve1; // reserved (not used)
+ USHORT usWritePrecompCyl; // starting write precompensation cyl.
+ BYTE bMaxECCDataBurstLen; // maximum ECC data burst length
+ BYTE bControl; // control byte
+ BYTE abReserve2[3]; // reserved (not used)
+ USHORT usLandingZone; // landing zone for head parking
+ BYTE bSectorsPerTrack; // number of sectors per track
+ BYTE bReserve3; // reserved for future use
+} HDP;
+typedef HDP *PHDP; // pointer to hard disk parameter table
+
+
+/* Hard Disk Parameter Table control byte bit definitions
+ */
+#define HDPCTRL_DISABLERETRY 0xC0 // disable retries
+#define HDPCTRL_EXCEED8HEADS 0x08 // more than 8 heads
+
+
+/* Boot sector structures (more DOS-defined than BIOS-defined however -JTP)
+ */
+#define PARTITION_ACTIVE 0x80 // status values
+
+#define PARTITION_12BITFAT 1 // type valus
+#define PARTITION_16BITFAT 4
+#define PARTITION_LARGEFAT 6
+
+typedef struct mbr_s { // Master Boot Record
+ BYTE boot_code[0x1BE];
+ BYTE partition_status;
+ BYTE starting_head;
+ USHORT starting_sec_cyl;
+ BYTE partition_type;
+ BYTE ending_head;
+ USHORT ending_sec_cyl;
+ ULONG starting_abs_sector;
+ ULONG total_sectors;
+} MBR;
+typedef MBR *PMBR;
+
+typedef struct bpb_s { // BIOS Parameter Block (from sysbloks.h)
+ BYTE boot_code[0x0B];
+ USHORT bytes_per_sector; // sector size
+ BYTE sectors_per_cluster; // sectors per allocation unit
+ USHORT reserved_sectors; // number of reserved sectors
+ BYTE nbr_fats; // number of fats
+ USHORT root_entries; // number of directory entries
+ USHORT total_sectors; // number of sectors
+ BYTE media_type; // fatid byte
+ USHORT sectors_per_fat; // sectors in a copy of the FAT
+ USHORT sectors_per_track; // number of sectors per track
+ USHORT number_of_heads; // number of heads
+ ULONG hidden_sectors; // number of hidden sectors
+ ULONG large_total_sectors; // large total sectors
+ BYTE reserved[6]; // 6 reserved bytes
+} BPB;
+typedef BPB *PBPB;
+
+
+/* Virtual disk mapping info
+ *
+ * VIRTDISK is the header of a virtual disk file. Following the header
+ * is an optional track table, and TRACKINFO is the format of each entry
+ * in that table. The track table is only present if the last two
+ * fields in the header (nsecTrack and nbSector) are zero, indicating a
+ * non-homogeneous disk structure.
+ *
+ * Currently, a max of 4 DRIVEMAP structures are supported. The first two
+ * entries are for physical drives 0 and 1 (specified in the command-line
+ * options as drives A: and B:), and subsequent entries are for physical
+ * hard drives 0x80 and up (specified as drives C: and up). Each DRIVEMAP
+ * describes the remapping that should occur, if any, and for virtual disk
+ * files, it also contains the virtual disk file header (which is read in
+ * during initialization).
+ *
+ * When a request comes in for one of those drives, we check the flags in
+ * corresponding DRIVEMAP structure. If no flags are set, no remapping
+ * or virtualization occurs (drive behaves normally). This is the default.
+ * If the drive is disabled (eg, "A:=*"), then all requests are returned
+ * with an error. If the drive is remapped to another physical drive (eg,
+ * "A:=B:") then the request is routed to the mapped drive. Finally, if
+ * the drive is remapped to a virtual disk file, the appropriate file I/O
+ * is performed.
+ *
+ * NOTE: Contrary to comments above, access to physical drives is not
+ * currently supported, so mapping to a virtual drive is all you can do
+ * right now.... (24-Nov-90 JTP)
+ */
+
+#define VDFLAGS_WRITEPROTECT 0x01 // virtual disk is "write-protected"
+
+typedef struct virtdisk_s {
+ BYTE fbVirt; // flags
+ BYTE nHeads; // # heads
+ USHORT nCyls; // # cylinders
+ USHORT nsecTrack; // # sectors per track
+ USHORT nbSector; // # bytes per sector
+} VIRTDISK;
+typedef VIRTDISK *PVIRTDISK;
+
+typedef struct trackinfo_s {
+ USHORT nsecTrack; // # sectors per track
+ USHORT nbSector; // # bytes per sector
+ ULONG offVirtDisk; // offset within virtual disk file
+} TRACKINFO;
+typedef TRACKINFO *PTRACKINFO;
+
+#define DMFLAGS_VIRTUAL 0x01 // physical remapped to virtual
+#define DMFLAGS_DISABLED 0x02 // physical remapped to disabled
+#define DMFLAGS_PHYSICAL 0x04 // physical remapped to physical
+#define DMFLAGS_LOGICAL 0x08 // physical remapped to logical
+
+typedef struct drivemap_s {
+ BYTE fbMap; // flags
+ BYTE iPhysical; // # of remapped drive, if any
+ FILE *hfVirtDisk; // handle to virtual disk, if any
+ VIRTDISK vdInfo; // virtual disk info, if any
+ #ifdef LOGICAL_DRIVE_SUPPORT
+ ULONG nsecHidden; // from BPB, if any (logical disks only)
+ BYTE type; // disk type, if any (logical disks only)
+ #endif
+} DRIVEMAP;
+typedef DRIVEMAP *PDRIVEMAP;
+
+
diff --git a/private/mvdm/v86/scaffold/i386/xbioskbd.h b/private/mvdm/v86/scaffold/i386/xbioskbd.h
new file mode 100644
index 000000000..d416b4069
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/xbioskbd.h
@@ -0,0 +1,39 @@
+//
+// This code is temporary. When Insignia supplies rom support, it should
+// be removed.
+//
+
+/* x86 v1.0
+ *
+ * XBIOSKBD.H
+ * Guest ROM BIOS keyboard emulation
+ *
+ * History
+ * Created 20-Oct-90 by Jeff Parsons
+ * 17-Apr-91 Trimmed by Dave Hastings for use in temp. softpc
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+
+/* BIOS keyboard functions
+ */
+#define KBDFUNC_READCHAR 0x00
+#define KBDFUNC_PEEKCHAR 0x01
+#define KBDFUNC_QUERYSHIFT 0x02
+#define KBDFUNC_SETDELAYS 0x03
+#define KBDFUNC_WRITECHAR 0x05
+#define KBDFUNC_READEXTCHAR 0x10
+#define KBDFUNC_PEEKEXTCHAR 0x11
+#define KBDFUNC_QUERYEXTSHIFT 0x12
+
+
+/* BIOS Data Area keyboard locations
+ */
+#define KBDDATA_KBDSHIFT 0x417
+
+
diff --git a/private/mvdm/v86/scaffold/i386/xbiosvid.h b/private/mvdm/v86/scaffold/i386/xbiosvid.h
new file mode 100644
index 000000000..8a8a64ddb
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/xbiosvid.h
@@ -0,0 +1,65 @@
+//
+// This code is temporary. When Insignia supplies rom support, it should
+// be removed.
+//
+
+/* x86 v1.0
+ *
+ * XBIOSVID.H
+ * Guest ROM BIOS video emulation
+ *
+ * History
+ * Created 20-Oct-90 by Jeff Parsons
+ * 17-Apr-91 Trimmed by Dave Hastings for use in temp. softpc
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+
+/* BIOS video functions
+ */
+#define VIDFUNC_SETMODE 0x00
+#define VIDFUNC_SETCURSORTYPE 0x01
+#define VIDFUNC_SETCURSORPOS 0x02
+#define VIDFUNC_QUERYCURSORPOS 0x03
+#define VIDFUNC_QUERYLPEN 0x04
+#define VIDFUNC_SETACTIVEPAGE 0x05
+#define VIDFUNC_SCROLLUP 0x06
+#define VIDFUNC_SCROLLDOWN 0x07
+#define VIDFUNC_READCHARATTR 0x08
+#define VIDFUNC_WRITECHARATTR 0x09
+#define VIDFUNC_WRITECHAR 0x0A
+#define VIDFUNC_SETPALETTE 0x0B
+#define VIDFUNC_WRITEPIXEL 0x0C
+#define VIDFUNC_READPIXEL 0x0D
+#define VIDFUNC_WRITETTY 0x0E
+#define VIDFUNC_QUERYMODE 0x0F
+#define VIDFUNC_EGASETPALETTE 0x10
+#define VIDFUNC_EGASELECTFONT 0x11
+#define VIDFUNC_EGASELECTMISC 0x12
+#define VIDFUNC_EGAWRITESTRING 0x13
+#define VIDFUNC_VGADISPLAYCODES 0x1A
+#define VIDFUNC_VGAQUERYSTATE 0x1B
+#define VIDFUNC_VGASAVERESTORE 0x1C
+
+#define VIDMODE_MONO 7
+
+
+/* BIOS Data Area video locations
+ */
+#define VIDDATA_CRT_MODE 0x449
+#define VIDDATA_CRT_COLS 0x44A
+#define VIDDATA_CRT_LEN 0x44C
+#define VIDDATA_CRT_START 0x44E
+#define VIDDATA_CURSOR_POSN 0x450
+#define VIDDATA_CURSOR_MODE 0x460
+#define VIDDATA_ACTIVE_PAGE 0x462
+#define VIDDATA_ADDR_6845 0x463
+#define VIDDATA_CRT_MODE_SET 0x465
+#define VIDDATA_CRT_PALETTE 0x466
+
+
diff --git a/private/mvdm/v86/scaffold/i386/xguest.h b/private/mvdm/v86/scaffold/i386/xguest.h
new file mode 100644
index 000000000..38e963365
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/xguest.h
@@ -0,0 +1,459 @@
+/* x86 v1.0
+ *
+ * XGUEST.H
+ * Guest processor definitions/conventions
+ *
+ * History
+ * Created 20-Oct-90 by Jeff Parsons
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+
+#define GUESTMEM_SIZE (640*K)
+
+#define GUESTMEM_MIN (32*K) // smallest PC size ever
+#define GUESTMEM_MAX (960*K) // uses all but the last 64k ROM block
+
+#define GUESTVID_SIZE (4*K) // for MONO emulation
+#define GUESTVID_SEG (USHORT)0xB000
+
+#define GUESTROM_SIZE (64*K)
+#define GUESTROM_SEG (USHORT)0xF000
+
+#define FLATMEM_SIZE ((1024+64)*K)
+
+
+/* Processor-defined stuff
+ */
+#define IVT_BEGIN 0x0000 // IVT table
+#define IVT_END 0x03FF
+
+#define RESET_SEG (USHORT)0xFFFF // processor reset address
+#define RESET_OFF 0x0000
+
+
+/* Useful macros
+ */
+#define LINEAR(seg,off) (((((ULONG)(seg)<<4)+(off))) & ulWrapMask)
+#define LINEAR2(seg,off) (((ULONG)(seg)<<4)+(off))
+#define COMPOSITE(seg,off) (((ULONG)(seg)<<16)|(off))
+#define OFFCOMPOSITE(ul) WORDOF(ul,0)
+#define SEGCOMPOSITE(ul) WORDOF(ul,1)
+
+#define BYTESOFFSET(off) LOBYTE(off), HIBYTE(off)
+#define BYTESCOMPOSITE(seg,off) LOBYTE(off), HIBYTE(off), LOBYTE(seg), HIBYTE(seg)
+
+/* x86 opcodes (the really useful ones anyway)
+ */
+#define OPX_ADDAXI 0x05
+#define OPX_PUSHDS 0x1E
+#define OPX_POPDS 0x1F
+#define OPX_ES 0x26
+#define OPX_CS 0x2E
+#define OPX_SS 0x36
+#define OPX_DS 0x3E
+#define OPX_PUSHAX 0x50
+#define OPX_POPAX 0x58
+#define OPX_JO 0x70
+#define OPX_JNO 0x71
+#define OPX_JB 0x72
+#define OPX_JNB 0x73
+#define OPX_JZ 0x74
+#define OPX_JNZ 0x75
+#define OPX_JBE 0x76
+#define OPX_JNBE 0x77
+#define OPX_JS 0x78
+#define OPX_JNS 0x79
+#define OPX_JP 0x7A
+#define OPX_JNP 0x7B
+#define OPX_JL 0x7C
+#define OPX_JGE 0x7D
+#define OPX_JLE 0x7E
+#define OPX_JG 0x7F
+#define OPX_MOVSEG2 0x8C
+#define OPX_LEA 0x8D
+#define OPX_MOV2SEG 0x8E
+#define OPX_CBW 0x98
+#define OPX_CWD 0x99
+#define OPX_MOVALOFF 0xA0
+#define OPX_MOVAXOFF 0xA1
+#define OPX_MOVSB 0xA4
+#define OPX_MOVSW 0xA5
+#define OPX_MOVAL 0xB0
+#define OPX_MOVCL 0xB1
+#define OPX_MOVDL 0xB2
+#define OPX_MOVBL 0xB3
+#define OPX_MOVAH 0xB4
+#define OPX_MOVCH 0xB5
+#define OPX_MOVDH 0xB6
+#define OPX_MOVBH 0xB7
+#define OPX_MOVAX 0xB8
+#define OPX_MOVCX 0xB9
+#define OPX_MOVDX 0xBA
+#define OPX_MOVBX 0xBB
+#define OPX_MOVSP 0xBC
+#define OPX_MOVBP 0xBD
+#define OPX_MOVSI 0xBE
+#define OPX_MOVDI 0xBF
+#define OPX_RETNV 0xC2
+#define OPX_RETN 0xC3
+#define OPX_LES 0xC4
+#define OPX_LDS 0xC5
+#define OPX_RETFV 0xCA
+#define OPX_RETF 0xCB
+#define OPX_INT3 0xCC
+#define OPX_INT 0xCD
+#define OPX_INTO 0xCE
+#define OPX_IRET 0xCF
+#define OPX_GBP 0xD6 // invalid opcode used for guest breakpoints
+#define OPX_XLAT 0xD7
+#define OPX_JCXZ 0xE3
+#define OPX_JMPR16 0xE9
+#define OPX_JMPF 0xEA
+#define OPX_JMPR8 0xEB
+#define OPX_LOCK 0xF0
+#define OPX_REPNZ 0xF2
+#define OPX_REPZ 0xF3
+#define OPX_CLC 0xF8
+#define OPX_STC 0xF9
+#define OPX_CLI 0xFA
+#define OPX_STI 0xFB
+#define OPX_GRP5 0xFF
+
+/* Mnemonic ordinals (indexes into apszMnemonic)
+ */
+#define M_NONE 0
+#define M_AAA 1
+#define M_AAD 2
+#define M_AAM 3
+#define M_AAS 4
+#define M_ADC 5
+#define M_ADD 6
+#define M_AND 7
+#define M_ARPL 8
+#define M_ASIZE 9
+#define M_BOUND 10
+#define M_BSF 11
+#define M_BSR 12
+#define M_BT 13
+#define M_BTC 14
+#define M_BTR 15
+#define M_BTS 16
+#define M_CALL 17
+#define M_CBW 18
+#define M_CLC 19
+#define M_CLD 20
+#define M_CLI 21
+#define M_CLTS 22
+#define M_CMC 23
+#define M_CMP 24
+#define M_CMPSB 25
+#define M_CMPSW 26
+#define M_CS 27
+#define M_CWD 28
+#define M_DAA 29
+#define M_DAS 30
+#define M_DEC 31
+#define M_DIV 32
+#define M_DS 33
+#define M_ENTER 34
+#define M_ES 35
+#define M_ESC 36
+#define M_FADD 37
+#define M_FBLD 38
+#define M_FBSTP 39
+#define M_FCOM 40
+#define M_FCOMP 41
+#define M_FDIV 42
+#define M_FDIVR 43
+#define M_FIADD 44
+#define M_FICOM 45
+#define M_FICOMP 46
+#define M_FIDIV 47
+#define M_FIDIVR 48
+#define M_FILD 49
+#define M_FIMUL 50
+#define M_FIST 51
+#define M_FISTP 52
+#define M_FISUB 53
+#define M_FISUBR 54
+#define M_FLD 55
+#define M_FLDCW 56
+#define M_FLDENV 57
+#define M_FMUL 58
+#define M_FNSAVE 59
+#define M_FNSTCW 60
+#define M_FNSTENV 61
+#define M_FNSTSW 62
+#define M_FRSTOR 63
+#define M_FS 64
+#define M_FST 65
+#define M_FSTP 66
+#define M_FSUB 67
+#define M_FSUBR 68
+#define M_GBP 69
+#define M_GS 70
+#define M_HLT 71
+#define M_IDIV 72
+#define M_IMUL 73
+#define M_IN 74
+#define M_INC 75
+#define M_INS 76
+#define M_INT 77
+#define M_INT3 78
+#define M_INTO 79
+#define M_IRET 80
+#define M_JBE 81
+#define M_JB 82
+#define M_JCXZ 83
+#define M_JG 84
+#define M_JGE 85
+#define M_JL 86
+#define M_JLE 87
+#define M_JMP 88
+#define M_JNBE 89
+#define M_JNB 90
+#define M_JNO 91
+#define M_JNP 92
+#define M_JNS 93
+#define M_JNZ 94
+#define M_JO 95
+#define M_JP 96
+#define M_JS 97
+#define M_JZ 98
+#define M_LAHF 99
+#define M_LAR 100
+#define M_LDS 101
+#define M_LEA 102
+#define M_LEAVE 103
+#define M_LES 104
+#define M_LFS 105
+#define M_LGDT 106
+#define M_LGS 107
+#define M_LIDT 108
+#define M_LLDT 109
+#define M_LMSW 110
+#define M_LOCK 111
+#define M_LODSB 112
+#define M_LODSW 113
+#define M_LOOP 114
+#define M_LOOPNZ 115
+#define M_LOOPZ 116
+#define M_LSL 117
+#define M_LSS 118
+#define M_LTR 119
+#define M_MOV 120
+#define M_MOVSB 121
+#define M_MOVSW 122
+#define M_MOVSX 123
+#define M_MOVZX 124
+#define M_MUL 125
+#define M_NEG 126
+#define M_NOP 127
+#define M_NOT 128
+#define M_OR 129
+#define M_OSIZE 130
+#define M_OUT 131
+#define M_OUTS 132
+#define M_POP 133
+#define M_POPA 134
+#define M_POPF 135
+#define M_PUSH 136
+#define M_PUSHA 137
+#define M_PUSHF 138
+#define M_RCL 139
+#define M_RCR 140
+#define M_REPNZ 141
+#define M_REPZ 142
+#define M_RET 143
+#define M_RETF 144
+#define M_ROL 145
+#define M_ROR 146
+#define M_SAHF 147
+#define M_SAR 148
+#define M_SBB 149
+#define M_SCASB 150
+#define M_SCASW 151
+#define M_SETBE 152
+#define M_SETC 153
+#define M_SETG 154
+#define M_SETGE 155
+#define M_SETL 156
+#define M_SETLE 157
+#define M_SETNBE 158
+#define M_SETNC 159
+#define M_SETNO 160
+#define M_SETNP 161
+#define M_SETNS 162
+#define M_SETNZ 163
+#define M_SETO 164
+#define M_SETP 165
+#define M_SETS 166
+#define M_SETZ 167
+#define M_SGDT 156
+#define M_SHL 169
+#define M_SHLD 170
+#define M_SHR 171
+#define M_SHRD 172
+#define M_SIDT 173
+#define M_SLDT 174
+#define M_SMSW 175
+#define M_SS 176
+#define M_STC 177
+#define M_STD 178
+#define M_STI 179
+#define M_STOSB 180
+#define M_STOSW 181
+#define M_STR 182
+#define M_SUB 183
+#define M_TEST 184
+#define M_VERR 185
+#define M_VERW 186
+#define M_WAIT 187
+#define M_XCHG 188
+#define M_XLAT 189
+#define M_XOR 190
+#define MTOTAL 191
+
+
+/* ModRegRM masks and definitions
+ */
+#define REG_AL 0x00 // bits 0-2 are standard Reg encodings
+#define REG_CL 0x01 //
+#define REG_DL 0x02 //
+#define REG_BL 0x03 //
+#define REG_AH 0x04 //
+#define REG_CH 0x05 //
+#define REG_DH 0x06 //
+#define REG_BH 0x07 //
+#define REG_AX 0x08 //
+#define REG_CX 0x09 //
+#define REG_DX 0x0A //
+#define REG_BX 0x0B //
+#define REG_SP 0x0C //
+#define REG_BP 0x0D //
+#define REG_SI 0x0E //
+#define REG_DI 0x0F //
+
+#define REG_ES 0x00 // bits 0-1 are standard SegReg encodings
+#define REG_CS 0x01 //
+#define REG_SS 0x02 //
+#define REG_DS 0x03 //
+#define REG_FS 0x04 //
+#define REG_GS 0x05 //
+
+#define MODMASK 0xC0 // mod/reg/rm definitions
+#define MODSHIFT 6 //
+#define MOD(m) (((m)&MODMASK)>>MODSHIFT)
+#define REGMASK 0x38 //
+#define REGSHIFT 3 //
+#define REG(r) (((r)&REGMASK)>>REGSHIFT)
+#define RMMASK 0x07 //
+#define RMSHIFT 0 //
+#define RM(b) (((b)&RMMASK)>>RMSHIFT)
+#define MODREGRM(m,r,b) ((BYTE)((((m)<<MODSHIFT)&MODMASK) | \
+ (((r)<<REGSHIFT)&REGMASK) | \
+ (((b)<<RMSHIFT )&RMMASK )))
+
+#define MOD_NODISP 0x00 // use RM below, no displacement
+#define MOD_DISP8 0x01 // use RM below + 8-bit displacement
+#define MOD_DISP16 0x02 // use RM below + 16-bit displacement
+#define MOD_REGISTER 0x03 // use REG above
+
+#define RM_BXSI 0x00 //
+#define RM_BXDI 0x01 //
+#define RM_BPSI 0x02 //
+#define RM_BPDI 0x03 //
+#define RM_SI 0x04 //
+#define RM_DI 0x05 //
+#define RM_BP 0x06 // note: if MOD_NODISP, this is IMMOFF
+#define RM_BX 0x07 //
+
+
+/* Operand type descriptor masks and definitions
+ *
+ * Note that the letters in () in the comments refer to Intel's
+ * nomenclature used in Appendix A of the 80386 Prog. Reference Manual.
+ */
+#define TYPE_SIZE 0x000F // size field
+#define TYPE_TYPE 0x00F0 // type field
+#define TYPE_IREG 0x0F00 // implied register field
+#define TYPE_OTHER 0xF000 // "other" field
+
+// TYPE_SIZE values. Note that some of the values (eg, TYPE_WORDIB
+// and TYPE_WORDIW) imply the presence of a third operand, for those
+// wierd cases....
+
+#define TYPE_NONE 0x0000 // (all other TYPE fields ignored)
+#define TYPE_BYTE 0x0001 // (b) byte, regardless of operand size
+#define TYPE_SBYTE 0x0002 // same as above, but sign-extended
+#define TYPE_WORD 0x0003 // (w) word, regardless...
+#define TYPE_WORDD 0x0004 // (v) word or double-word, depending...
+#define TYPE_DWORD 0x0005 // (d) double-word, regardless...
+#define TYPE_FARP 0x0006 // (p) 32-bit or 48-bit pointer, depending
+#define TYPE_2WORDD 0x0007 // (a) two memory operands (BOUND only)
+#define TYPE_DESC 0x0008 // (s) 6 byte pseudo-descriptor
+#define TYPE_WORDIB 0x0009 // two source operands (eg, IMUL)
+#define TYPE_WORDIW 0x000A // two source operands (eg, IMUL)
+
+// TYPE_TYPE values. Note that all values implying
+// the presence of a ModRegRM byte are >= TYPE_MODRM (clever, eh?)
+
+#define TYPE_IMM 0x0000 // (I) immediate data
+#define TYPE_ONE 0x0010 // implicit 1 (eg, shifts/rotates)
+#define TYPE_IMMOFF 0x0020 // (A) immediate offset
+#define TYPE_IMMREL 0x0030 // (J) immediate relative
+#define TYPE_DSSI 0x0040 // (X) memory addressed by DS:SI
+#define TYPE_ESDI 0x0050 // (Y) memory addressed by ES:DI
+#define TYPE_IMPREG 0x0060 // implicit register in TYPE_IREG
+#define TYPE_IMPSEG 0x0070 // implicit seg. register in TYPE_IREG
+#define TYPE_MODRM 0x0080 // (E) standard ModRM decoding
+#define TYPE_MEM 0x0090 // (M) ModRM refers to memory only
+#define TYPE_REG 0x00A0 // (G) standard Reg decoding
+#define TYPE_SEGREG 0x00B0 // (S) Reg selects segment register
+#define TYPE_MODREG 0x00C0 // (R) Mod refers to register only
+#define TYPE_CTLREG 0x00D0 // (C) Reg selects control register
+#define TYPE_DBGREG 0x00E0 // (D) Reg selects debug register
+#define TYPE_TSTREG 0x00F0 // (T) Reg selects test register
+
+// TYPE_IREG values, based on the REG_* constants.
+// For convenience, they include TYPE_IMPREG or TYPE_IMPSEG as appropriate.
+
+#define TYPE_AL (REG_AL<<8|TYPE_IMPREG|TYPE_BYTE)
+#define TYPE_CL (REG_CL<<8|TYPE_IMPREG|TYPE_BYTE)
+#define TYPE_DL (REG_DL<<8|TYPE_IMPREG|TYPE_BYTE)
+#define TYPE_BL (REG_BL<<8|TYPE_IMPREG|TYPE_BYTE)
+#define TYPE_AH (REG_AH<<8|TYPE_IMPREG|TYPE_BYTE)
+#define TYPE_CH (REG_CH<<8|TYPE_IMPREG|TYPE_BYTE)
+#define TYPE_DH (REG_DH<<8|TYPE_IMPREG|TYPE_BYTE)
+#define TYPE_BH (REG_BH<<8|TYPE_IMPREG|TYPE_BYTE)
+#define TYPE_AX (REG_AX<<8|TYPE_IMPREG|TYPE_WORD)
+#define TYPE_CX (REG_CX<<8|TYPE_IMPREG|TYPE_WORD)
+#define TYPE_DX (REG_DX<<8|TYPE_IMPREG|TYPE_WORD)
+#define TYPE_BX (REG_BX<<8|TYPE_IMPREG|TYPE_WORD)
+#define TYPE_SP (REG_SP<<8|TYPE_IMPREG|TYPE_WORD)
+#define TYPE_BP (REG_BP<<8|TYPE_IMPREG|TYPE_WORD)
+#define TYPE_SI (REG_SI<<8|TYPE_IMPREG|TYPE_WORD)
+#define TYPE_DI (REG_DI<<8|TYPE_IMPREG|TYPE_WORD)
+#define TYPE_ES (REG_ES<<8|TYPE_IMPSEG|TYPE_WORD)
+#define TYPE_CS (REG_CS<<8|TYPE_IMPSEG|TYPE_WORD)
+#define TYPE_SS (REG_SS<<8|TYPE_IMPSEG|TYPE_WORD)
+#define TYPE_DS (REG_DS<<8|TYPE_IMPSEG|TYPE_WORD)
+#define TYPE_FS (REG_FS<<8|TYPE_IMPSEG|TYPE_WORD)
+#define TYPE_GS (REG_GS<<8|TYPE_IMPSEG|TYPE_WORD)
+
+// TYPE_OTHER bit definitions
+
+#define TYPE_IN 0x1000 // operand is input
+#define TYPE_OUT 0x2000 // operand is output
+#define TYPE_BOTH (TYPE_IN|TYPE_OUT)
+#define TYPE_86 (CPU_86 << 14)
+#define TYPE_186 (CPU_186 << 14)
+#define TYPE_286 (CPU_286 << 14)
+#define TYPE_386 (CPU_386 << 14)
+
diff --git a/private/mvdm/v86/scaffold/i386/xwincon.h b/private/mvdm/v86/scaffold/i386/xwincon.h
new file mode 100644
index 000000000..c3880146d
--- /dev/null
+++ b/private/mvdm/v86/scaffold/i386/xwincon.h
@@ -0,0 +1,186 @@
+//
+// borrowed for temprorary softpc console support
+//
+
+
+/*++ BUILD Version: 0001
+ *
+ * x86 v1.0
+ *
+ * XWINCON.H
+ * Windows support functions for console windows
+ *
+ * History
+ * Created 27-Dec-90 by Jeff Parsons
+ *
+ * COPYRIGHT NOTICE
+ * This source file may not be distributed, modified or incorporated into
+ * another product without prior approval from the author, Jeff Parsons.
+ * This file may be copied to designated servers and machines authorized to
+ * access those servers, but that does not imply any form of approval.
+ */
+
+
+typedef unsigned int UINT; // ints preferred
+typedef int INT; // ints preferred
+typedef CHAR *NPSZ;
+typedef INT (FAR PASCAL *INTPROC)(HWND, UINT, UINT, LONG);
+
+#define DEF_CCHIN 16 // default input buffer size
+#define DEF_CCHXOUT 80 // default output buffer width
+#define DEF_CCHYOUT 25 // default output buffer height
+
+#define CON_SCROLL_LOCK 0x0010 // console has SCROLL-LOCK set
+#define CON_NUM_LOCK 0x0020 // console has NUM-LOCK set
+#define CON_CAPS_LOCK 0x0040 // console has CAPS-LOCK set
+#define CON_LEDS_MASK 0x0070 //
+#define CON_FOCUS 0x0100 // console has focus
+
+#ifndef VK_OEM_SCROLL
+#define VK_OEM_SCROLL 0x91 // left out of windows.h for some reason...
+#endif
+
+#define INVALIDATE_SCROLL 2
+
+#define IDM_DBBRK 100
+#define IDM_ABOUT 101
+
+#define CLR_BLACK 0x00000000
+#define CLR_RED 0x007F0000
+#define CLR_GREEN 0x00007F00
+#define CLR_BROWN 0x007F7F00
+#define CLR_BLUE 0x0000007F
+#define CLR_MAGENTA 0x007F007F
+#define CLR_CYAN 0x00007F7F
+#define CLR_LT_GRAY 0x00BFBFBF
+
+#define CLR_DK_GRAY 0x007F7F7F
+#define CLR_BR_RED 0x00FF0000
+#define CLR_BR_GREEN 0x0000FF00
+#define CLR_YELLOW 0x00FFFF00
+#define CLR_BR_BLUE 0x000000FF
+#define CLR_BR_MAGENTA 0x00FF00FF
+#define CLR_BR_CYAN 0x0000FFFF
+#define CLR_WHITE 0x00FFFFFF
+
+#define OPT_FONT 0x0004 // use small OEM font if available (/s)
+#define OPT_DOUBLE 0x0020 // use 50-line debug window w/small font (/50)
+#define OPT_CAPS 0x0002 // map ctrl keys to caps-lock (/c)
+#define OPT_TERMINAL 0x0010 // redirect all window output to terminal (/t)
+#define OPT_FLUSH 0x0100 // flush prefetch after every jump (/f)
+#define OPT_NOXLATE 0x0200 // disable built-in translations (/n)
+#define OPT_DEBUG 0x0008 // shadow all log output on debug terminal (/d)
+#define OPT_GO 0x0001 // do an initial "go" (/g)
+
+#define CTRL_A 1 // used by gets to repeat last line
+#define CTRL_C 3 // break in debug window
+#define CTRL_Q 17 // flow control
+#define CTRL_S 19 // flow control
+#define BELL 7 //
+#define BS 8 // backspace
+#define TAB 9 //
+#define LF 10 // linefeed
+#define CR 13 // return
+#define ESCAPE 27 //
+
+#define SIGNAL_EMULATE 1
+#define ERR_NONE 0x0
+
+#define TRUE_IF_WIN32 1
+
+/* Per-window information
+ */
+#ifdef WIN_16
+#define GETPCONSOLE(hwnd) (PCONSOLE)GetWindowWord(hwnd,0)
+#define SETPCONSOLE(hwnd,p) (PCONSOLE)SetWindowWord(hwnd,0,(INT)p)
+#endif
+#ifdef WIN_32
+#define GETPCONSOLE(hwnd) (PCONSOLE)GetWindowLong(hwnd,0)
+#define SETPCONSOLE(hwnd,p) (PCONSOLE)SetWindowLong(hwnd,0,(LONG)p)
+#endif
+#ifdef PM
+#define GETPCONSOLE(hwnd) (PCONSOLE)WinQueryWindowUShort(hwnd,0)
+#define SETPCONSOLE(hwnd,p) (PCONSOLE)WinSetWindowUShort(hwnd,0,(USHORT)p)
+#endif
+
+#define GETICARET(pcon) (pcon->chyCaret*pcon->cchxOut+pcon->chxCaret)
+#define GETPCARET(pcon) (pcon->pchOut+GETICARET(pcon))
+#define GETXCARET(pcon) (pcon->chxCaret*pcon->cxChar)
+#ifdef WIN
+#define GETYCARET(pcon) (pcon->chyCaret*pcon->cyChar)
+#else
+#define GETYCARET(pcon) (pcon->cyOut - pcon->chyCaret*pcon->cyChar)
+#endif
+
+#define GETILINE(pcon,chy) ((chy)*pcon->cchxOut)
+#define GETPLINE(pcon,chy) (pcon->pchOut+GETILINE(pcon,chy))
+
+#define GETICHAR(pcon,chx,chy) ((chy)*pcon->cchxOut+(chx))
+#define GETPCHAR(pcon,chx,chy) (pcon->pchOut+GETICHAR(pcon,chx,chy))
+#define GETXCHAR(pcon,chx) (pcon->cxChar*(chx))
+#ifdef WIN
+#define GETYCHAR(pcon,chy) (pcon->cyChar*(chy))
+#else
+#define GETYCHAR(pcon,chy) (pcon->cyOut - pcon->cyChar*(chy))
+#endif
+
+#define WORDOF(i,n) (((PWORD)&(i))[n])
+#define LOW(l) WORDOF(l,0)
+#define NPVOID(p) ((VOID *)(p))
+
+typedef struct key_s {
+ INT iKey;
+ LONG lKeyType;
+} KEY, *PKEY;
+
+typedef struct console_s {
+ INT flCon; // console flags (see CON_*)
+ PKEY pkIn; // pointer to input buffer
+ HANDLE hkEvent; // handle to key event
+ INT ikHead; // input head (where to store next key)
+ INT ikTail; // input tail (where to retrieve next key)
+ INT ikMax; // maximum input index
+ HFONT hFont; // font identifier
+ INT cxChar; // character width, in pixels
+ INT cyChar; // character height, in pixels
+ INT cxOut; // buffer width, in pixels
+ INT cyOut; // buffer height, in pixels
+ INT cchxOut; // buffer width, in chars
+ INT cchyOut; // buffer height, in chars
+ UINT cbOut; // buffer size, in bytes
+ PCHAR pchOut; // pointer to output buffer
+ INT chxCaret; // caret x location, in char coordinates
+ INT chyCaret; // caret y location, in char coordinates
+} CONSOLE, *PCONSOLE;
+
+
+/* Function prototypes
+ */
+PCONSOLE initconsole(HWND hwnd, INT cchIn, INT cchxOut, INT cchyOut, INT iFont);
+VOID freeconsole(HWND hwnd);
+VOID clearconsole(HWND hwnd);
+VOID invalidateconsole(HWND hwnd, PRECT prc, BOOL fUpdate);
+
+INT wprint(HWND hwnd, NPSZ psz, INT n);
+INT wgetch(HWND hwnd);
+BOOL wkbhit(HWND hwnd);
+VOID wyield(HANDLE);
+INT wputch(HWND hwnd, INT i);
+
+VOID setcaret(HWND hwnd, INT x, INT y);
+VOID getcaret(HWND hwnd, PINT px, PINT py);
+VOID writechar(HWND hwnd, CHAR ch, INT n);
+VOID scrollrect(HWND hwndGuest, PRECT prc, INT n);
+
+extern HWND hwndGuest;
+extern HANDLE hHostInstance;
+extern INT flOptions; // command-line options (see OPT_*)
+extern INT flSignals; // signal flags (see SIGNAL_*)
+
+LONG FAR PASCAL VDMWndProc(HWND hwnd, UINT wMsg, UINT uParam, LONG lParam);
+BOOL FAR PASCAL VDMAbout(HWND hDlg, UINT wMsg, UINT uParam, LONG lParam);
+
+VOID processmessages(HWND hwnd);
+INT getkbdleds(VOID);
+VOID setkbdleds(INT flCon);
+VOID mapkbdkeys(PCONSOLE pcon, UINT iParam, BOOL fDown);
diff --git a/private/mvdm/v86/scaffold/makefile b/private/mvdm/v86/scaffold/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/mvdm/v86/scaffold/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/v86/scaffold/ntvdm.def b/private/mvdm/v86/scaffold/ntvdm.def
new file mode 100644
index 000000000..6cc3fd979
--- /dev/null
+++ b/private/mvdm/v86/scaffold/ntvdm.def
@@ -0,0 +1,90 @@
+NAME ntvdm.exe
+
+EXPORTS
+ getEAX
+ getAX
+ getAL
+ getAH
+ getEBX
+ getBX
+ getBL
+ getBH
+ getECX
+ getCX
+ getCL
+ getCH
+ getEDX
+ getDX
+ getDL
+ getDH
+ getESP
+ getSP
+ getEBP
+ getBP
+ getESI
+ getSI
+ getEDI
+ getDI
+ getEIP
+ getIP
+ getCS
+ getSS
+ getDS
+ getES
+ getFS
+ getGS
+ getCF
+ getPF
+ getAF
+ getZF
+ getSF
+ getIF
+ getDF
+ getOF
+ getMSW
+ setEAX
+ setAX
+ setAH
+ setAL
+ setEBX
+ setBX
+ setBH
+ setBL
+ setECX
+ setCX
+ setCH
+ setCL
+ setEDX
+ setDX
+ setDH
+ setDL
+ setESP
+ setSP
+ setEBP
+ setBP
+ setESI
+ setSI
+ setEDI
+ setDI
+ setEIP
+ setIP
+ setCS
+ setSS
+ setDS
+ setES
+ setFS
+ setGS
+ setCF
+ setPF
+ setAF
+ setZF
+ setSF
+ setIF
+ setDF
+ setOF
+ setMSW
+ MGetVdmPointer
+ host_simulate
+ EnterIdle
+ LeaveIdle
+ getIntelRegistersPointer
diff --git a/private/mvdm/v86/scaffold/sources b/private/mvdm/v86/scaffold/sources
new file mode 100644
index 000000000..d0cde5f5b
--- /dev/null
+++ b/private/mvdm/v86/scaffold/sources
@@ -0,0 +1,157 @@
+!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
+ Dave Hastings (daveh) 24-Apr-1991
+ Sudeep Bharati (sudeepb) 31-Dec-1991 - deleted wow32 related stuff and
+ converted .EXE to (.EXE/.EXP/.LIB)
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+
+#
+# The MAJORCOMP and MINORCOMP variables are defined
+# so that $(MAJORCOMP)$(MINORCOMP)filename can be used in
+# cross compiling to provide unique filenames in a flat namespace.
+#
+
+MAJORCOMP=v86
+MINORCOMP=scaffold
+
+#
+# The TARGETNAME variable is defined by the developer. It is the name of
+# the target (component) that is being built by this makefile. It
+# should NOT include any path or file extension information.
+#
+
+TARGETNAME=ntvdm
+
+
+#
+# The TARGETPATH and TARGETTYPE variables are defined by the developer.
+# The first specifies where the target is to be build. The second specifies
+# the type of target (either PROGRAM, DYNLINK, LIBRARY, UMAPPL_NOLIB or
+# BOOTPGM). UMAPPL_NOLIB is used when you're only building user-mode
+# apps and don't need to build a library.
+#
+
+TARGETPATH=\nt\public\sdk\lib
+
+# PROGLIB is a new target type which allows ntvdm to be an exe and
+# at the same time exports interfaces like a dll.
+TARGETTYPE=PROGLIB
+
+
+#
+# The TARGETLIBS specifies additional libraries to link with you target
+# image. Each library path specification should contain an asterisk (*)
+# where the machine specific subdirectory name should go.
+#
+
+!IFNDEF NTVDM_NET_PATH
+NTVDM_NET_PATH=..\..\..\net
+!ENDIF
+
+!IFDEF NTLIBPATH
+TARGETLIBS=\nt\public\sdk\lib\*\monitor.lib \
+ \nt\public\sdk\lib\*\xms.lib \
+ \nt\public\sdk\lib\*\dbg.lib \
+ \nt\public\sdk\lib\*\dem.lib \
+ \nt\public\sdk\lib\*\command.lib \
+!IFDEF NTVDM_NET_SUPPORT
+ ..\..\dos\command\obj\*\command.lib \
+ ..\..\vdmredir\obj\*\vdmredir.lib
+!ELSE
+ ..\..\dos\command\obj\*\command.lib
+!ENDIF
+!ELSE
+TARGETLIBS=\nt\public\sdk\lib\*\monitor.lib \
+ \nt\public\sdk\lib\*\dem.lib \
+ \nt\public\sdk\lib\*\xms.lib \
+ \nt\public\sdk\lib\*\dbg.lib \
+ \nt\public\sdk\lib\*\command.lib \
+!IFDEF NTVDM_NET_SUPPORT
+ ..\..\vdmredir\obj\*\vdmredir.lib \
+ \nt\public\sdk\lib\*\netapi32.lib \
+ \nt\public\sdk\lib\*\xactsrv.lib \
+ $(BASEDIR)\Public\SDK\Lib\*\rxcommon.lib \
+ $(NTVDM_NET_PATH)\netlib\obj\*\netlib.lib \
+!ENDIF
+ \nt\public\sdk\lib\*\gdi32.lib \
+!ENDIF
+
+#
+# The INCLUDES variable specifies any include paths that are specific to
+# this source directory. Separate multiple directory paths with single
+# semicolons. Relative path specifications are okay.
+#
+
+INCLUDES=..\..\inc;..\..\..\windows\inc
+
+
+#
+# The SOURCES variable is defined by the developer. It is a list of all the
+# source files for this component. Each source file should be on a separate
+# line using the line continuation character. This will minimize merge
+# conflicts if two developers adding source files to the same component.
+#
+
+SOURCES=vdm.rc
+
+#
+# Next specify options for the compiler.
+#
+
+!IFDEF NTVDM_NET_SUPPORT
+C_DEFINES=-DWIN_32 -DWOW -DNTVDM_NET_SUPPORT
+!ELSE
+C_DEFINES=-DWIN_32 -DWOW
+!ENDIF
+
+#
+# Next specify a kernel mode test (valid only in NTOS tree)
+#
+
+NTTEST=
+
+#
+# Next specify one or more user mode test programs and their type
+# UMTEST is used for optional test programs. UMAPPL is used for
+# programs that always get built when the directory is built.
+#
+
+UMTYPE=console
+UMTEST=
+UMAPPL=
+UMBASE=0x1000000
+UMLIBS=
+
+#
+# Defining either (or both) the variables NTTARGETFILE0 and/or NTTARGETFILES
+# will cause MAKEFILE.DEF to include .\makefile.inc immediately after it
+# specifies the top level targets (all, clean and loc) and their dependencies.
+# MAKEFILE.DEF also expands NTTARGETFILE0 as the first dependent for the
+# "all" target and NTTARGETFILES as the last dependent for the "all" target.
+# Useful for specifying additional targets and dependencies that don't fit the
+# general case covered by MAKEFILE.DEF
+#
+
+# NTTARGETFILE0=
+# NTTARGETFILES=
diff --git a/private/mvdm/v86/scaffold/vdm.ico b/private/mvdm/v86/scaffold/vdm.ico
new file mode 100644
index 000000000..6b2416d64
--- /dev/null
+++ b/private/mvdm/v86/scaffold/vdm.ico
Binary files differ
diff --git a/private/mvdm/v86/scaffold/vdm.rc b/private/mvdm/v86/scaffold/vdm.rc
new file mode 100644
index 000000000..1d354879c
--- /dev/null
+++ b/private/mvdm/v86/scaffold/vdm.rc
@@ -0,0 +1,57 @@
+#ifndef DOS // Gross hack to account for the
+#ifndef OS2_16 // fact that C_DEFINES in "sources" isn't
+#ifndef OS2_32 // passed to the resource compiler when building
+#ifndef WIN_16 // for MIPS. Since MIPS is a WIN_32 build,
+#ifndef WIN_32 // I try to innocuously define WIN_32 here... -JTP
+#define WIN_32
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#define _NTIMAGE_ // This will force ntimage not to include nt.h
+#define _NTXCAPI_ // forces ntxcapi.h unincluded
+#include "i386\x86.h"
+
+VDMIcon ICON vdm.ico
+
+
+SoftPC MENU
+BEGIN
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&DebugBreak", IDM_DBBRK
+ MENUITEM "&About NT VDM...", IDM_ABOUT
+ END
+END
+
+
+VDMAbout DIALOG 22, 17, 131, 83
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About NT VDM"
+BEGIN
+ CTEXT "NT VDMs are " -1, 32, 5, 65, 12
+ CTEXT "Brought to you by the NTVDM Team" -1, 0, 19, 131, 10
+ CTEXT "Some code adapted from:" -1, 0, 27, 131, 9
+ CTEXT "x86 emulator v0.17" -1, 0, 38, 131, 8
+ CTEXT "by Jeff Parsons, (C) 1991" -1, 0, 45, 131, 8
+ CONTROL "Text", -1, "static", SS_BLACKFRAME | WS_CHILD, 17, 36, 99, 27
+ DEFPUSHBUTTON "OK" IDOK, 51, 66, 32, 14, WS_GROUP
+END
+
+
+#ifdef WOW
+
+WOW32About DIALOG 22, 17, 144, 55
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About WOW"
+BEGIN
+ CTEXT "Just say WOW!" -1, 0, 5, 144, 8
+ CTEXT "This Win16-on-Win32 app" -1, 0, 18, 144, 8
+ CTEXT "brought to you by the MVDM Team" -1, 0, 27, 144, 8
+ DEFPUSHBUTTON "OK" IDOK, 32, 39, 32, 14, WS_GROUP
+ PUSHBUTTON "Debug" 100, 80, 39, 32, 14, WS_GROUP
+END
+
+#endif
diff --git a/private/mvdm/v86/scaffold/wow.ico b/private/mvdm/v86/scaffold/wow.ico
new file mode 100644
index 000000000..936ab5c5e
--- /dev/null
+++ b/private/mvdm/v86/scaffold/wow.ico
Binary files differ
diff --git a/private/mvdm/v86/util/makefile b/private/mvdm/v86/util/makefile
new file mode 100644
index 000000000..31b26fc0b
--- /dev/null
+++ b/private/mvdm/v86/util/makefile
@@ -0,0 +1,56 @@
+!IF 0
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ makefile
+
+Abstract:
+
+ This file controls the creation of the utilities
+
+Author:
+
+ Dave Hastings (daveh) 25-Apr-1991
+
+!ENDIF
+
+########## Path definition so we find 16 bit tools ##########
+# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be
+# in a directory that is greater than 128 chars down the path, even if
+# rc 3.1 is running as an OS/2 app.
+
+PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH)
+
+.SUFFIXES:
+.SUFFIXES: .asm .inc .obj .lst .exe .com .map .sym
+
+MASM = masm
+AINC = -I. -I..\inc -I..\..\inc
+AFLAGS = -Ml
+
+LFLAGS =
+LIB =
+
+RELOC = reloc
+
+# rules
+
+.asm.obj :
+ $(MASM) $(AFLAGS) $(AINC) $*.asm, $*.obj;
+
+.asm.lst :
+ $(MASM) $(AFLAGS) $(AINC) -l $*.asm, $*.obj;
+
+.obj.exe :
+ link16 $(LFLAGS) $*,,,$(LIB);
+
+.exe.com :
+ $(RELOC) $*.exe $*.com
+
+# dependencies
+
+all: quit.com
+
+quit.com : quit.exe
+quit.obj : quit.asm ..\..\inc\bop.inc
diff --git a/private/mvdm/v86/util/quit.asm b/private/mvdm/v86/util/quit.asm
new file mode 100644
index 000000000..664fd2880
--- /dev/null
+++ b/private/mvdm/v86/util/quit.asm
@@ -0,0 +1,40 @@
+ title "Terminate execution of an NT VDM"
+;++
+;
+; Copyright (c) 1989 Microsoft Corporation
+;
+; Module Name:
+;
+; quit.asm
+;
+; Abstract:
+;
+; This module is a simple dos executable that will terminate a
+; Vdm.
+;
+; Author:
+;
+; Dave Hastings (daveh) 25-Apr-1991
+;
+; Environment:
+;
+; V86 mode only!!
+;
+; Revision History:
+;
+;--
+.386
+
+
+.xlist
+include bop.inc
+.list
+
+code segment
+ ASSUME CS:code
+quit proc near
+ BOP BOP_UNSIMULATE
+quit endp
+
+code ends
+ end