[NTVDM]
[reactos.git] / subsystems / ntvdm / dos.c
index 4bd4652..e592189 100644 (file)
@@ -6,9 +6,18 @@
  * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
  */
 
-#include "ntvdm.h"
+/* INCLUDES *******************************************************************/
 
-WORD CurrentPsp = SYSTEM_PSP, LastError = 0;
+#include "dos.h"
+#include "bios.h"
+#include "emulator.h"
+
+/* PRIVATE VARIABLES **********************************************************/
+
+static WORD CurrentPsp = SYSTEM_PSP;
+static DWORD DiskTransferArea;
+
+/* PRIVATE FUNCTIONS **********************************************************/
 
 static VOID DosCombineFreeBlocks(WORD StartBlock)
 {
@@ -77,6 +86,16 @@ static WORD DosCopyEnvironmentBlock(WORD SourceSegment)
     return DestSegment;
 }
 
+static VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner)
+{
+    PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment - 1);
+
+    /* Just set the owner */
+    Mcb->OwnerPsp = NewOwner;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
 WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
 {
     WORD Result = 0, Segment = FIRST_MCB_SEGMENT, MaxSize = 0;
@@ -402,6 +421,9 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
                          CommandLine, ExeSize + (sizeof(DOS_PSP) >> 4) + i,
                          EnvBlock);
 
+        /* The process owns its own memory */
+        DosChangeMemoryOwner(Segment, Segment);
+
         /* Copy the program to Segment:0100 */
         RtlCopyMemory((PVOID)((ULONG_PTR)BaseAddress
                       + TO_LINEAR(Segment, 0x100)),
@@ -433,6 +455,7 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
 
         /* Execute */
         CurrentPsp = Segment;
+        DiskTransferArea = MAKELONG(0x80, Segment);
         EmulatorExecute(Segment + Header->e_cs, sizeof(DOS_PSP) + Header->e_ip);
 
         Success = TRUE;
@@ -466,6 +489,7 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
 
         /* Execute */
         CurrentPsp = Segment;
+        DiskTransferArea = MAKELONG(0x80, Segment);
         EmulatorExecute(Segment, 0x100);
 
         Success = TRUE;
@@ -536,7 +560,13 @@ Done:
 CHAR DosReadCharacter()
 {
     // TODO: STDIN can be redirected under DOS 2.0+
-    return _getch();
+    CHAR Character = 0;
+
+    /* A zero value for the character indicates a special key */
+    do Character = BiosGetCharacter();
+    while (!Character);
+
+    return Character;
 }
 
 VOID DosPrintCharacter(CHAR Character)
@@ -635,6 +665,24 @@ VOID DosInt21h(WORD CodeSegment)
             break;
         }
 
+        /* Set Disk Transfer Area */
+        case 0x1A:
+        {
+            DiskTransferArea = MAKELONG(LOWORD(Edx), DataSegment);
+            break;
+        }
+
+        /* Set Interrupt Vector */
+        case 0x25:
+        {
+            DWORD FarPointer = MAKELONG(LOWORD(Edx), DataSegment);
+
+            /* Write the new far pointer to the IDT */
+            ((PDWORD)BaseAddress)[LOBYTE(Eax)] = FarPointer;
+
+            break;
+        }
+
         /* Get system date */
         case 0x2A:
         {
@@ -710,6 +758,36 @@ VOID DosInt21h(WORD CodeSegment)
             break;
         }
 
+        /* Get Disk Transfer Area */
+        case 0x2F:
+        {
+            EmulatorSetRegister(EMULATOR_REG_ES, HIWORD(DiskTransferArea));
+            EmulatorSetRegister(EMULATOR_REG_BX, LOWORD(DiskTransferArea));
+
+            break;
+        }
+
+        /* Get DOS Version */
+        case 0x30:
+        {
+            PDOS_PSP PspBlock = SEGMENT_TO_PSP(CurrentPsp);
+
+            EmulatorSetRegister(EMULATOR_REG_AX, PspBlock->DosVersion);
+            break;
+        }
+
+        /* Get Interrupt Vector */
+        case 0x35:
+        {
+            DWORD FarPointer = ((PDWORD)BaseAddress)[LOBYTE(Eax)];
+
+            /* Read the address from the IDT into ES:BX */
+            EmulatorSetRegister(EMULATOR_REG_ES, HIWORD(FarPointer));
+            EmulatorSetRegister(EMULATOR_REG_BX, LOWORD(FarPointer));
+
+            break;
+        }
+
         /* Create Directory */
         case 0x39:
         {
@@ -828,6 +906,7 @@ VOID DosInt21h(WORD CodeSegment)
         /* Unsupported */
         default:
         {
+            DPRINT1("DOS Function INT 0x21, AH = 0x%02X NOT IMPLEMENTED!\n", HIBYTE(Eax));
             EmulatorSetFlag(EMULATOR_FLAG_CF);
         }
     }