- Use callbacks in BIOS/DOS (and disable int32.c)
- Move DOS bops to dem.c

svn path=/branches/ntvdm/; revision=62306
This commit is contained in:
Hermès Bélusca-Maïto 2014-02-23 16:09:35 +00:00
parent 0c3c1170ab
commit b33a34bec1
10 changed files with 232 additions and 158 deletions

View file

@ -22,7 +22,7 @@ list(APPEND SOURCE
bop.c
clock.c
emulator.c
int32.c
callback.c
io.c
registers.c
vddsup.c

View file

@ -11,6 +11,8 @@
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "bios32.h"
#include "io.h"
@ -18,10 +20,9 @@
#include "hardware/pic.h"
#include "hardware/timer.h"
#include "int32.h"
/* PRIVATE VARIABLES **********************************************************/
CALLBACK16 BiosContext;
PBIOS_DATA_AREA Bda;
/* PRIVATE FUNCTIONS **********************************************************/
@ -190,7 +191,7 @@ VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func)
else
vector = BIOS_PIC_SLAVE_INT + hwirq - 8;
RegisterInt32(vector, func);
RegisterBiosInt32(vector, func);
}
@ -250,7 +251,8 @@ static VOID WINAPI BiosTimerIrq(LPWORD Stack)
* because some programs may hook only BIOS_SYS_TIMER_INTERRUPT
* for their purpose...
*/
EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT);
/** EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); **/
Int32Call(&BiosContext, BIOS_SYS_TIMER_INTERRUPT);
PicIRQComplete(Stack);
}
@ -303,6 +305,48 @@ static VOID BiosHwSetup(VOID)
EnableHwIRQ(0, BiosTimerIrq);
}
static VOID InitializeBiosInt32(VOID)
{
USHORT i;
// USHORT Offset = 0;
/* Initialize the callback context */
InitializeContext(&BiosContext, BIOS_SEGMENT, 0x0000);
/* Register the BIOS 32-bit Interrupts */
for (i = 0x00; i <= 0xFF; i++)
{
// Offset += RegisterInt32(MAKELONG(Offset, BIOS_SEGMENT), i, NULL, NULL);
BiosContext.NextOffset += RegisterInt32(MAKELONG(BiosContext.NextOffset,
BiosContext.Segment),
i, NULL, NULL);
}
/* Initialize the exception vector interrupts to a default Exception handler */
for (i = 0; i < 8; i++)
RegisterBiosInt32(i, BiosException);
/* Initialize HW vector interrupts to a default HW handler */
for (i = BIOS_PIC_MASTER_INT; i < BIOS_PIC_MASTER_INT + 8; i++)
RegisterBiosInt32(i, BiosHandleMasterPicIRQ);
for (i = BIOS_PIC_SLAVE_INT ; i < BIOS_PIC_SLAVE_INT + 8; i++)
RegisterBiosInt32(i, BiosHandleSlavePicIRQ);
/* Initialize software vector handlers */
RegisterBiosInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
RegisterBiosInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );
RegisterBiosInt32(BIOS_MISC_INTERRUPT , BiosMiscService );
RegisterBiosInt32(BIOS_TIME_INTERRUPT , BiosTimeService );
RegisterBiosInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
/* Some interrupts are in fact addresses to tables */
((PULONG)BaseAddress)[0x1E] = (ULONG)NULL;
((PULONG)BaseAddress)[0x41] = (ULONG)NULL;
((PULONG)BaseAddress)[0x46] = (ULONG)NULL;
((PULONG)BaseAddress)[0x48] = (ULONG)NULL;
((PULONG)BaseAddress)[0x49] = (ULONG)NULL;
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*
@ -312,7 +356,6 @@ BOOLEAN Bios32Initialize(IN HANDLE ConsoleInput,
IN HANDLE ConsoleOutput)
{
UCHAR Low, High;
UCHAR i;
/* Initialize the BDA */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
@ -328,34 +371,8 @@ BOOLEAN Bios32Initialize(IN HANDLE ConsoleInput,
High = IOReadB(CMOS_DATA_PORT);
Bda->MemorySize = MAKEWORD(Low, High);
/* Initialize the 32-bit Interrupt system */
InitializeInt32(BIOS_SEGMENT);
/* Register the BIOS 32-bit Interrupts */
/* Initialize the exception vector interrupts to a default Exception handler */
for (i = 0; i < 8; i++)
RegisterInt32(i, BiosException);
/* Initialize HW vector interrupts to a default HW handler */
for (i = BIOS_PIC_MASTER_INT; i < BIOS_PIC_MASTER_INT + 8; i++)
RegisterInt32(i, BiosHandleMasterPicIRQ);
for (i = BIOS_PIC_SLAVE_INT ; i < BIOS_PIC_SLAVE_INT + 8; i++)
RegisterInt32(i, BiosHandleSlavePicIRQ);
/* Initialize software vector handlers */
RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );
RegisterInt32(BIOS_MISC_INTERRUPT , BiosMiscService );
RegisterInt32(BIOS_TIME_INTERRUPT , BiosTimeService );
RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
/* Some interrupts are in fact addresses to tables */
((PDWORD)BaseAddress)[0x1E] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x41] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x46] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x48] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x49] = (DWORD)NULL;
InitializeBiosInt32();
/* Initialize platform hardware (PIC/PIT chips, ...) */
BiosHwSetup();

View file

@ -15,6 +15,8 @@
#include "kbdbios32.h"
#include "vidbios32.h"
/**/ #include "callback.h" /**/
/* DEFINES ********************************************************************/
#define BIOS_PIC_MASTER_INT 0x08
@ -115,6 +117,14 @@ C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133);
/* FUNCTIONS ******************************************************************/
extern CALLBACK16 BiosContext;
#define RegisterBiosInt32(IntNumber, IntHandler) \
do { \
BiosContext.NextOffset += RegisterInt32(MAKELONG(BiosContext.NextOffset, \
BiosContext.Segment), \
(IntNumber), (IntHandler), NULL); \
} while(0);
extern PBIOS_DATA_AREA Bda;
/**HACK!!**/typedef VOID (WINAPI *EMULATOR_INT32_PROC)(LPWORD Stack);/**HACK!!**/

View file

@ -11,14 +11,14 @@
#define NDEBUG
#include "emulator.h"
#include "callback.h"
// #include "kbdbios32.h"
#include "bios32.h"
#include "io.h"
#include "hardware/ps2.h"
#include "int32.h"
/* PRIVATE VARIABLES **********************************************************/
static BYTE BiosKeyboardMap[256];
@ -271,7 +271,7 @@ BOOLEAN KbdBios32Initialize(HANDLE ConsoleInput)
/* Register the BIOS 32-bit Interrupts */
/* Initialize software vector handlers */
RegisterInt32(BIOS_KBD_INTERRUPT, BiosKeyboardService);
RegisterBiosInt32(BIOS_KBD_INTERRUPT, BiosKeyboardService);
/* Set up the HW vector interrupts */
EnableHwIRQ(1, BiosKeyboardIrq);

View file

@ -11,14 +11,14 @@
#define NDEBUG
#include "emulator.h"
#include "callback.h"
// #include "vidbios32.h"
#include "bios32.h"
#include "io.h"
#include "hardware/vga.h"
#include "int32.h"
/* MACROS *********************************************************************/
//
@ -1536,11 +1536,11 @@ static VOID WINAPI VidBiosVideoService(LPWORD Stack)
BOOLEAN VidBios32Initialize(HANDLE ConsoleOutput)
{
/* Some interrupts are in fact addresses to tables */
((PDWORD)BaseAddress)[0x1D] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x1F] = (DWORD)NULL;
// ((PDWORD)BaseAddress)[0x42] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x43] = (DWORD)NULL;
((PDWORD)BaseAddress)[0x44] = (DWORD)NULL;
((PULONG)BaseAddress)[0x1D] = (ULONG)NULL;
((PULONG)BaseAddress)[0x1F] = (ULONG)NULL;
// ((PULONG)BaseAddress)[0x42] = (ULONG)NULL;
((PULONG)BaseAddress)[0x43] = (ULONG)NULL;
((PULONG)BaseAddress)[0x44] = (ULONG)NULL;
/* Set the default video mode */
VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
@ -1562,7 +1562,7 @@ BOOLEAN VidBios32Initialize(HANDLE ConsoleOutput)
}
/* Register the BIOS 32-bit Interrupts */
RegisterInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
return TRUE;
}

View file

@ -14,17 +14,130 @@
#define NDEBUG
#include "emulator.h"
#include "dem.h"
#include "bop.h"
/* Extra PSDK/NDK Headers */
#include <ndk/obtypes.h>
/* PRIVATE VARIABLES **********************************************************/
/**/extern BYTE CurrentDrive;/**/
/* DEFINES ********************************************************************/
/* BOP Identifiers */
#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
/* PRIVATE FUNCTIONS **********************************************************/
static VOID WINAPI DosSystemBop(LPWORD Stack)
{
/* Get the Function Number and skip it */
BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
setIP(getIP() + 1);
DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
}
static VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
{
/* Get the Function Number and skip it */
BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
setIP(getIP() + 1);
switch (FuncNum)
{
case 0x08: // Launch external command
{
#define CMDLINE_LENGTH 1024
BOOL Result;
DWORD dwExitCode;
LPSTR Command = (LPSTR)SEG_OFF_TO_PTR(getDS(), getSI());
LPSTR CmdPtr = Command;
CHAR CommandLine[CMDLINE_LENGTH] = "";
STARTUPINFOA StartupInfo;
PROCESS_INFORMATION ProcessInformation;
/* Remove return carriage character */
while (*CmdPtr != '\r') CmdPtr++;
*CmdPtr = '\0';
DPRINT1("CMD Run Command '%s'\n", Command);
/* Spawn a user-defined 32-bit command preprocessor */
/* Build the command line */
// FIXME: Use COMSPEC env var!!
strcpy(CommandLine, "cmd.exe /c ");
strcat(CommandLine, Command);
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
StartupInfo.cb = sizeof(StartupInfo);
DosPrintCharacter('\n');
Result = CreateProcessA(NULL,
CommandLine,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&StartupInfo,
&ProcessInformation);
if (Result)
{
DPRINT1("Command '%s' launched successfully\n", Command);
/* Wait for process termination */
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
/* Get the exit code */
GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
/* Close handles */
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
}
else
{
DPRINT1("Failed when launched command '%s'\n");
dwExitCode = GetLastError();
}
DosPrintCharacter('\n');
setAL((UCHAR)dwExitCode);
break;
}
default:
{
DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum);
// setCF(1); // Disable, otherwise we enter an infinite loop
break;
}
}
}
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames)
{
/* Register the DOS BOPs */
RegisterBop(BOP_DOS, DosSystemBop );
RegisterBop(BOP_CMD, DosCmdInterpreterBop);
if (DosKernelFileNames)
{
DisplayMessage(L"NTVDM: Loading DOS kernel from external files is currently unsupported");
@ -35,7 +148,7 @@ BOOLEAN DosInitialize(IN LPCSTR DosKernelFileNames)
BOOLEAN Result;
Result = DosBIOSInitialize();
Result &= DosKRNLInitialize();
// Result &= DosKRNLInitialize();
return Result;
}

View file

@ -11,21 +11,17 @@
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "dos.h"
#include "bios/bios.h"
#include "bop.h"
// #include "int32.h"
/* PRIVATE VARIABLES **********************************************************/
// static BYTE CurrentDrive;
// static CHAR CurrentDirectories[NUM_DRIVES][DOS_DIR_LENGTH];
/* BOP Identifiers */
#define BOP_DOS 0x50 // DOS System BOP (for NTIO.SYS and NTDOS.SYS)
#define BOP_CMD 0x54 // DOS Command Interpreter BOP (for COMMAND.COM)
/* PRIVATE FUNCTIONS **********************************************************/
#if 0
@ -119,94 +115,6 @@ VOID DosPrintCharacter(CHAR Character)
DosWriteFile(DOS_OUTPUT_HANDLE, &Character, sizeof(CHAR), &BytesWritten);
}
VOID WINAPI DosSystemBop(LPWORD Stack)
{
/* Get the Function Number and skip it */
BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
setIP(getIP() + 1);
DPRINT1("Unknown DOS System BOP Function: 0x%02X\n", FuncNum);
}
VOID WINAPI DosCmdInterpreterBop(LPWORD Stack)
{
/* Get the Function Number and skip it */
BYTE FuncNum = *(PBYTE)SEG_OFF_TO_PTR(getCS(), getIP());
setIP(getIP() + 1);
switch (FuncNum)
{
case 0x08: // Launch external command
{
#define CMDLINE_LENGTH 1024
BOOL Result;
DWORD dwExitCode;
LPSTR Command = (LPSTR)SEG_OFF_TO_PTR(getDS(), getSI());
CHAR CommandLine[CMDLINE_LENGTH] = "";
STARTUPINFOA StartupInfo;
PROCESS_INFORMATION ProcessInformation;
DPRINT1("CMD Run Command '%s'\n", Command);
Command[strlen(Command)-1] = 0;
strcpy(CommandLine, "cmd.exe /c ");
strcat(CommandLine, Command);
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
StartupInfo.cb = sizeof(StartupInfo);
DosPrintCharacter('\n');
Result = CreateProcessA(NULL,
CommandLine,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&StartupInfo,
&ProcessInformation);
if (Result)
{
DPRINT1("Command '%s' launched successfully\n");
/* Wait for process termination */
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
/* Get the exit code */
GetExitCodeProcess(ProcessInformation.hProcess, &dwExitCode);
/* Close handles */
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
}
else
{
DPRINT1("Failed when launched command '%s'\n");
dwExitCode = GetLastError();
}
DosPrintCharacter('\n');
setAL((UCHAR)dwExitCode);
break;
}
default:
{
DPRINT1("Unknown DOS CMD Interpreter BOP Function: 0x%02X\n", FuncNum);
// setCF(1); // Disable, otherwise we enter an infinite loop
break;
}
}
}
BOOLEAN DosBIOSInitialize(VOID)
{
PDOS_MCB Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT);
@ -345,16 +253,11 @@ BOOLEAN DosBIOSInitialize(VOID)
#endif
/* Register the DOS BOPs */
RegisterBop(BOP_DOS, DosSystemBop );
RegisterBop(BOP_CMD, DosCmdInterpreterBop);
/* Register the DOS 32-bit Interrupts */
// RegisterInt32(0x20, DosInt20h);
// RegisterDosInt32(0x20, DosInt20h);
/* TODO: Initialize the DOS kernel */
return TRUE;
/* Initialize the DOS kernel */
return DosKRNLInitialize();
}
/* EOF */

View file

@ -11,15 +11,18 @@
#define NDEBUG
#include "emulator.h"
#include "callback.h"
#include "dos.h"
#include "dos/dem.h"
#include "bios/bios.h"
#include "int32.h"
#include "registers.h"
/* PRIVATE VARIABLES **********************************************************/
CALLBACK16 DosContext;
static WORD CurrentPsp = SYSTEM_PSP;
static WORD DosLastError = 0;
static DWORD DiskTransferArea;
@ -1669,11 +1672,11 @@ VOID WINAPI DosInt21h(LPWORD Stack)
/* Set Interrupt Vector */
case 0x25:
{
DWORD FarPointer = MAKELONG(getDX(), getDS());
ULONG FarPointer = MAKELONG(getDX(), getDS());
DPRINT1("Setting interrupt 0x%x ...\n", getAL());
/* Write the new far pointer to the IDT */
((PDWORD)BaseAddress)[getAL()] = FarPointer;
((PULONG)BaseAddress)[getAL()] = FarPointer;
break;
}
@ -2480,6 +2483,7 @@ VOID WINAPI DosFastConOut(LPWORD Stack)
* for more information.
*/
#if 0
if (Stack[STACK_COUNTER] == 0)
{
Stack[STACK_COUNTER]++;
@ -2504,6 +2508,20 @@ VOID WINAPI DosFastConOut(LPWORD Stack)
setAX(Stack[STACK_VAR_A]);
setBX(Stack[STACK_VAR_B]);
}
#else
/* Save AX and BX */
USHORT AX = getAX();
USHORT BX = getBX();
setBL(DOS_CHAR_ATTRIBUTE);
setBH(Bda->VideoPage);
setAH(0x0E);
Int32Call(&DosContext, 0x10);
/* Restore AX and BX */
setAX(AX);
setBX(BX);
#endif
}
VOID WINAPI DosInt2Fh(LPWORD Stack)
@ -2585,15 +2603,17 @@ BOOLEAN DosKRNLInitialize(VOID)
#endif
/* Initialize the callback context */
InitializeContext(&DosContext, 0x0070, 0x0000);
/* Register the DOS 32-bit Interrupts */
RegisterInt32(0x20, DosInt20h );
RegisterInt32(0x21, DosInt21h );
// RegisterInt32(0x22, DosInt22h ); // Termination
RegisterInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break
// RegisterInt32(0x24, DosInt24h ); // Critical Error
RegisterInt32(0x29, DosFastConOut ); // DOS 2+ Fast Console Output
RegisterInt32(0x2F, DosInt2Fh );
RegisterDosInt32(0x20, DosInt20h );
RegisterDosInt32(0x21, DosInt21h );
// RegisterDosInt32(0x22, DosInt22h ); // Termination
RegisterDosInt32(0x23, DosBreakInterrupt); // Ctrl-C / Ctrl-Break
// RegisterDosInt32(0x24, DosInt24h ); // Critical Error
RegisterDosInt32(0x29, DosFastConOut ); // DOS 2+ Fast Console Output
RegisterDosInt32(0x2F, DosInt2Fh );
return TRUE;
}

View file

@ -13,6 +13,8 @@
#include "ntvdm.h"
/**/ #include "callback.h" /**/
/* DEFINES ********************************************************************/
//
@ -138,6 +140,14 @@ typedef struct _DOS_FIND_FILE_BLOCK
/* FUNCTIONS ******************************************************************/
extern CALLBACK16 DosContext;
#define RegisterDosInt32(IntNumber, IntHandler) \
do { \
DosContext.NextOffset += RegisterInt32(MAKELONG(DosContext.NextOffset, \
DosContext.Segment), \
(IntNumber), (IntHandler), NULL); \
} while(0);
/*
* DOS BIOS Functions
* See bios.c

View file

@ -388,7 +388,8 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput)
// if (!VgaInitialize(ConsoleOutput)) return FALSE;
VgaInitialize(ConsoleOutput);
/* Register the emulator BOPs */
/* Initialize the software callback system and register the emulator BOPs */
InitializeCallbacks();
RegisterBop(BOP_DEBUGGER , EmulatorDebugBreakBop);
RegisterBop(BOP_UNSIMULATE, EmulatorUnsimulateBop);