Author: aandrejevic Date: Sat Jun 29 21:37:44 2013 New Revision: 59374
URL: http://svn.reactos.org/svn/reactos?rev=59374&view=rev Log: [NTVDM] Fix several bugs. Implement some interrupt 1Ah services in the BIOS.
Modified: branches/ntvdm/subsystems/ntvdm/bios.c branches/ntvdm/subsystems/ntvdm/bios.h branches/ntvdm/subsystems/ntvdm/dos.c branches/ntvdm/subsystems/ntvdm/emulator.c
Modified: branches/ntvdm/subsystems/ntvdm/bios.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.c?re... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/bios.c [iso-8859-1] Sat Jun 29 21:37:44 2013 @@ -22,6 +22,8 @@ static WORD BiosKbdBuffer[BIOS_KBD_BUFFER_SIZE]; static UINT BiosKbdBufferStart = 0, BiosKbdBufferEnd = 0; static BOOLEAN BiosKbdBufferEmpty = TRUE; +static DWORD BiosTickCount = 0; +static BOOLEAN BiosPassedMidnight = FALSE;
/* PRIVATE FUNCTIONS **********************************************************/
@@ -405,6 +407,44 @@ } }
+VOID BiosTimeService() +{ + DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX); + DWORD Ecx = EmulatorGetRegister(EMULATOR_REG_CX); + DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX); + + switch (HIBYTE(Eax)) + { + case 0x00: + { + /* Set AL to 1 if midnight had passed, 0 otherwise */ + Eax &= 0xFFFFFF00; + if (BiosPassedMidnight) Eax |= 1; + + /* Return the tick count in CX:DX */ + EmulatorSetRegister(EMULATOR_REG_AX, Eax); + EmulatorSetRegister(EMULATOR_REG_CX, HIWORD(BiosTickCount)); + EmulatorSetRegister(EMULATOR_REG_DX, LOWORD(BiosTickCount)); + + /* Reset the midnight flag */ + BiosPassedMidnight = FALSE; + + break; + } + + case 0x01: + { + /* Set the tick count to CX:DX */ + BiosTickCount = MAKELONG(LOWORD(Edx), LOWORD(Ecx)); + + /* Reset the midnight flag */ + BiosPassedMidnight = FALSE; + + break; + } + } +} + VOID BiosHandleIrq(BYTE IrqNumber) { switch (IrqNumber) @@ -412,6 +452,9 @@ /* PIT IRQ */ case 0: { + /* Increase the system tick count */ + BiosTickCount++; + /* Perform the system timer interrupt */ EmulatorInterrupt(0x1C);
Modified: branches/ntvdm/subsystems/ntvdm/bios.h URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/bios.h?re... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/bios.h [iso-8859-1] Sat Jun 29 21:37:44 2013 @@ -22,8 +22,9 @@ #define BIOS_PIC_MASTER_INT 0x08 #define BIOS_PIC_SLAVE_INT 0x70 #define BIOS_SEGMENT 0xF000 -#define VIDEO_BIOS_INTERRUPT 0x10 -#define VIDEO_KBD_INTERRUPT 0x16 +#define BIOS_VIDEO_INTERRUPT 0x10 +#define BIOS_KBD_INTERRUPT 0x16 +#define BIOS_TIME_INTERRUPT 0x1A #define CONSOLE_FONT_HEIGHT 8 #define BIOS_KBD_BUFFER_SIZE 256
@@ -36,6 +37,7 @@ WORD BiosGetCharacter(); VOID BiosVideoService(); VOID BiosKeyboardService(); +VOID BiosTimeService(); VOID BiosHandleIrq(BYTE IrqNumber);
#endif
Modified: branches/ntvdm/subsystems/ntvdm/dos.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/dos.c?rev... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/dos.c [iso-8859-1] Sat Jun 29 21:37:44 2013 @@ -311,14 +311,7 @@ /* Initialize the handle table */ for (i = 0; i < 20; i++) PspBlock->HandleTable[i] = 0xFF;
- /* Did we get an environment segment? */ - if (!Environment) - { - /* No, copy the one from the parent */ - Environment = DosCopyEnvironmentBlock((CurrentPsp != SYSTEM_PSP) - ? SEGMENT_TO_PSP(CurrentPsp)->EnvBlock - : SYSTEM_ENV_BLOCK); - } +
PspBlock->EnvBlock = Environment;
@@ -342,13 +335,13 @@
BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock) { - BOOLEAN Success = FALSE; + BOOLEAN Success = FALSE, AllocatedEnvBlock = FALSE; HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL; LPBYTE Address = NULL; LPSTR ProgramFilePath, Parameters[128]; CHAR CommandLineCopy[128]; INT ParamCount = 0; - WORD i, Segment, FileSize, ExeSize; + WORD i, Segment = 0, FileSize, ExeSize; PIMAGE_DOS_HEADER Header; PDWORD RelocationTable; PWORD RelocWord; @@ -392,6 +385,18 @@ Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0); if (Address == NULL) goto Cleanup;
+ /* Did we get an environment segment? */ + if (!EnvBlock) + { + /* Set a flag to know if the environment block was allocated here */ + AllocatedEnvBlock = TRUE; + + /* No, copy the one from the parent */ + EnvBlock = DosCopyEnvironmentBlock((CurrentPsp != SYSTEM_PSP) + ? SEGMENT_TO_PSP(CurrentPsp)->EnvBlock + : SYSTEM_ENV_BLOCK); + } + /* Check if this is an EXE file or a COM file */ if (Address[0] == 'M' && Address[1] == 'Z') { @@ -423,6 +428,7 @@
/* The process owns its own memory */ DosChangeMemoryOwner(Segment, Segment); + DosChangeMemoryOwner(EnvBlock, Segment);
/* Copy the program to Segment:0100 */ RtlCopyMemory((PVOID)((ULONG_PTR)BaseAddress @@ -456,7 +462,8 @@ /* Execute */ CurrentPsp = Segment; DiskTransferArea = MAKELONG(0x80, Segment); - EmulatorExecute(Segment + Header->e_cs, sizeof(DOS_PSP) + Header->e_ip); + EmulatorExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4), + Header->e_ip);
Success = TRUE; } @@ -496,6 +503,13 @@ }
Cleanup: + if (!Success) + { + /* It was not successful, cleanup the DOS memory */ + if (AllocatedEnvBlock) DosFreeMemory(EnvBlock); + if (Segment) DosFreeMemory(Segment); + } + /* Unmap the file*/ if (Address != NULL) UnmapViewOfFile(Address);
Modified: branches/ntvdm/subsystems/ntvdm/emulator.c URL: http://svn.reactos.org/svn/reactos/branches/ntvdm/subsystems/ntvdm/emulator.... ============================================================================== --- branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] (original) +++ branches/ntvdm/subsystems/ntvdm/emulator.c [iso-8859-1] Sat Jun 29 21:37:44 2013 @@ -199,27 +199,35 @@ { /* It was an IRQ from the master PIC */ BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT); + return; } else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) { /* It was an IRQ from the slave PIC */ BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8); + return; }
switch (IntNum) { - case VIDEO_BIOS_INTERRUPT: + case BIOS_VIDEO_INTERRUPT: { /* This is the video BIOS interrupt, call the BIOS */ BiosVideoService(); break; } - case VIDEO_KBD_INTERRUPT: + case BIOS_KBD_INTERRUPT: { /* This is the keyboard BIOS interrupt, call the BIOS */ BiosKeyboardService(); break; } + case BIOS_TIME_INTERRUPT: + { + /* This is the time BIOS interrupt, call the BIOS */ + BiosTimeService(); + break; + } case 0x20: { DosInt20h(CodeSegment); @@ -233,6 +241,11 @@ case 0x23: { DosBreakInterrupt(); + break; + } + default: + { + DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum); break; } }