[NTVDM]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 25 Jan 2014 00:53:10 +0000 (00:53 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 25 Jan 2014 00:53:10 +0000 (00:53 +0000)
Add two general-purpose variables to the interrupt handler stub stack.
Fix INT 29h so that it works correctly when the INT 10h, AH = 0Eh call is hooked.

svn path=/branches/ntvdm/; revision=61797

subsystems/ntvdm/dos/dos.c
subsystems/ntvdm/emulator.h
subsystems/ntvdm/int32.c

index 1136807..53223c9 100644 (file)
@@ -2675,15 +2675,31 @@ VOID WINAPI DosFastConOut(LPWORD Stack)
      * See Ralf Brown: http://www.ctyme.com/intr/rb-4124.htm
      * for more information.
      */
-    UNREFERENCED_PARAMETER(Stack);
 
-    /*
-     * The default handler under DOS 2.x and 3.x simply calls INT 10/AH=0Eh.
-     * Do better and call directly VidBiosPrintCharacter: it's what INT 10/AH=0Eh
-     * does. Otherwise we would have to set BL to DOS_CHAR_ATTRIBUTE and
-     * BH to Bda->VideoPage.
-     */
-    VidBiosPrintCharacter(getAL(), DOS_CHAR_ATTRIBUTE, Bda->VideoPage);
+    if (Stack[STACK_COUNTER] == 0)
+    {
+        Stack[STACK_COUNTER]++;
+
+        /* Save AX and BX */
+        Stack[STACK_VAR_A] = getAX();
+        Stack[STACK_VAR_B] = getBX();
+
+        /* Rewind the BOP manually, we can't use CF because the interrupt could modify it */
+        EmulatorExecute(getCS(), getIP() - 4);
+
+        /* Call INT 0x10, AH = 0x0E */
+        setAH(0x0E);
+        setBL(DOS_CHAR_ATTRIBUTE);
+        setBH(Bda->VideoPage);
+
+        EmulatorInterrupt(0x10);
+    }
+    else
+    {
+        /* Restore AX and BX */
+        setAX(Stack[STACK_VAR_A]);
+        setBX(Stack[STACK_VAR_B]);
+    }
 }
 
 VOID WINAPI DosInt2Fh(LPWORD Stack)
index 3e25b5f..2474968 100644 (file)
 #define EMULATOR_FLAG_VIP (1 << 20)
 #define EMULATOR_FLAG_ID (1 << 21)
 
-#define STACK_COUNTER   0
-#define STACK_INT_NUM   1
-#define STACK_IP        2
-#define STACK_CS        3
-#define STACK_FLAGS     4
+#define STACK_VAR_B     0
+#define STACK_VAR_A     1
+#define STACK_COUNTER   2
+#define STACK_INT_NUM   3
+#define STACK_IP        4
+#define STACK_CS        5
+#define STACK_FLAGS     6
 
 
 /* Basic Memory Management */
index d616251..b89eb13 100644 (file)
@@ -74,9 +74,15 @@ VOID InitializeInt32(WORD BiosSegment)
         BiosCode[Offset++] = 0x6A; // push i
         BiosCode[Offset++] = (UCHAR)i;
 
+        /* The counter variable (initialized to 0) */
         BiosCode[Offset++] = 0x6A; // push 0
         BiosCode[Offset++] = 0x00;
 
+        /* Stack variables */
+        BiosCode[Offset++] = 0x83; // sub sp, 4
+        BiosCode[Offset++] = 0xEC;
+        BiosCode[Offset++] = 0x04;
+
         BopSeqOffset = COMMON_STUB_OFFSET - (Offset + 3);
 
         BiosCode[Offset++] = 0xE9; // jmp near BOP_SEQ
@@ -107,9 +113,9 @@ VOID InitializeInt32(WORD BiosSegment)
     BiosCode[Offset++] = 0xF5;
 
 // EXIT:
-    BiosCode[Offset++] = 0x83; // add sp, 4
+    BiosCode[Offset++] = 0x83; // add sp, 8
     BiosCode[Offset++] = 0xC4;
-    BiosCode[Offset++] = 0x04;
+    BiosCode[Offset++] = 0x08;
 
     BiosCode[Offset++] = 0xCF; // iret