mirror of
https://github.com/reactos/reactos.git
synced 2025-05-06 18:31:26 +00:00
[NTVDM]: Commit what I have in my local wc so far (and which is commitable & works):
- Simplify PicIRQComplete helper function. - Set up temporary stack for the BIOS. - Initialize the "User Data Area" that is found at 0050:xxxx (see http://helppc.netcore2k.net/table/memory-map for more details). - Some INT --> UINT - Simplify few macros. - Simplify DOS initialization; add few functions that will be useful later on. - Remove trailing whitespace. svn path=/trunk/; revision=68159
This commit is contained in:
parent
3a9b7ef77e
commit
93c0a8a1a0
21 changed files with 216 additions and 165 deletions
|
@ -111,14 +111,32 @@ typedef struct
|
|||
DWORD EGAPtr; // 0xa8
|
||||
BYTE Reserved12[68]; // 0xac
|
||||
BYTE Reserved13[16]; // 0xf0
|
||||
|
||||
DWORD Reserved14; // 0x100
|
||||
BYTE Reserved15[12]; // 0x104
|
||||
BYTE Reserved16[17]; // 0x110
|
||||
BYTE Reserved17[15]; // 0x121
|
||||
BYTE Reserved18[3]; // 0x130
|
||||
} BIOS_DATA_AREA, *PBIOS_DATA_AREA;
|
||||
C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x133);
|
||||
C_ASSERT(sizeof(BIOS_DATA_AREA) == 0x100);
|
||||
|
||||
/*
|
||||
* User Data Area at 0050:XXXX
|
||||
*
|
||||
* See: http://helppc.netcore2k.net/table/memory-map
|
||||
* for more information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
BYTE PrintScreen; // 0x00
|
||||
BYTE Basic0[3]; // 0x01
|
||||
BYTE SingleDisketteFlag; // 0x04
|
||||
BYTE PostArea[10]; // 0x05
|
||||
BYTE Basic1; // 0x0f
|
||||
WORD Basic2; // 0x10
|
||||
DWORD Basic3; // 0x12
|
||||
DWORD Basic4; // 0x16
|
||||
DWORD Basic5; // 0x1a
|
||||
WORD Reserved0; // 0x1e
|
||||
WORD DynStorage; // 0x20
|
||||
BYTE DisketteInitStorage[14]; // 0x22
|
||||
DWORD Reserved1; // 0x30
|
||||
} USER_DATA_AREA, *PUSER_DATA_AREA;
|
||||
C_ASSERT(sizeof(USER_DATA_AREA) == 0x34);
|
||||
|
||||
/*
|
||||
* BIOS Configuration Table at F000:E6F5 for 100% compatible BIOSes.
|
||||
|
|
|
@ -224,7 +224,7 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
|
|||
Return = (Value & getBH()) != 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Test and return if zero */
|
||||
case 4:
|
||||
{
|
||||
|
@ -554,15 +554,11 @@ VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func)
|
|||
}
|
||||
|
||||
|
||||
VOID PicIRQComplete(LPWORD Stack)
|
||||
VOID PicIRQComplete(BYTE IntNum)
|
||||
{
|
||||
/* Get the interrupt number */
|
||||
BYTE IntNum = LOBYTE(Stack[STACK_INT_NUM]);
|
||||
|
||||
/*
|
||||
* If this was a PIC IRQ, send an End-of-Interrupt to the PIC.
|
||||
*/
|
||||
|
||||
if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
|
||||
{
|
||||
/* It was an IRQ from the master PIC */
|
||||
|
@ -585,7 +581,7 @@ static VOID WINAPI BiosHandleMasterPicIRQ(LPWORD Stack)
|
|||
|
||||
DPRINT("Master - IrqNumber = 0x%02X\n", IrqNumber);
|
||||
|
||||
PicIRQComplete(Stack);
|
||||
PicIRQComplete(LOBYTE(Stack[STACK_INT_NUM]));
|
||||
}
|
||||
|
||||
static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack)
|
||||
|
@ -597,7 +593,7 @@ static VOID WINAPI BiosHandleSlavePicIRQ(LPWORD Stack)
|
|||
|
||||
DPRINT("Slave - IrqNumber = 0x%02X\n", IrqNumber);
|
||||
|
||||
PicIRQComplete(Stack);
|
||||
PicIRQComplete(LOBYTE(Stack[STACK_INT_NUM]));
|
||||
}
|
||||
|
||||
// Timer IRQ 0
|
||||
|
@ -612,7 +608,7 @@ static VOID WINAPI BiosTimerIrq(LPWORD Stack)
|
|||
*/
|
||||
Int32Call(&BiosContext, BIOS_SYS_TIMER_INTERRUPT);
|
||||
// BiosSystemTimerInterrupt(Stack);
|
||||
PicIRQComplete(Stack);
|
||||
PicIRQComplete(LOBYTE(Stack[STACK_INT_NUM]));
|
||||
}
|
||||
|
||||
|
||||
|
@ -795,15 +791,17 @@ Bios32Post(LPWORD Stack)
|
|||
/* Disable interrupts */
|
||||
setIF(0);
|
||||
|
||||
/* Set the data segment */
|
||||
setDS(BDA_SEGMENT);
|
||||
|
||||
/* Initialize the stack */
|
||||
// That's what says IBM... (stack at 30:00FF going downwards)
|
||||
// Temporary stack for POST (to be used only before initializing the INT vectors)
|
||||
// setSS(0x0000);
|
||||
// setSP(0x0400);
|
||||
setSS(0x0050); // Stack at 50:0400, going downwards
|
||||
setSP(0x0400);
|
||||
|
||||
/* Set data segment */
|
||||
setDS(BDA_SEGMENT);
|
||||
//
|
||||
// Stack to be used after the initialization of the INT vectors
|
||||
setSS(0x0000); // Stack at 00:8000, going downwards
|
||||
setSP(0x8000);
|
||||
|
||||
/*
|
||||
* Perform early CMOS shutdown status checks
|
||||
|
@ -912,6 +910,9 @@ Bios32Post(LPWORD Stack)
|
|||
InitializeBiosData();
|
||||
InitializeBiosInfo();
|
||||
|
||||
/* Initialize the User Data Area at 0050:XXXX */
|
||||
RtlZeroMemory(SEG_OFF_TO_PTR(0x50, 0x0000), sizeof(USER_DATA_AREA));
|
||||
|
||||
/*
|
||||
* Initialize IVT and hardware
|
||||
*/
|
||||
|
|
|
@ -40,7 +40,7 @@ do { \
|
|||
} while(0);
|
||||
|
||||
VOID EnableHwIRQ(UCHAR hwirq, EMULATOR_INT32_PROC func);
|
||||
VOID PicIRQComplete(LPWORD Stack);
|
||||
VOID PicIRQComplete(BYTE IntNum);
|
||||
|
||||
#endif // _BIOS32P_H_
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
|
|||
case 0x11:
|
||||
{
|
||||
WORD Character;
|
||||
|
||||
|
||||
if (BiosKbdBufferTop(&Character))
|
||||
{
|
||||
/* There is a character, clear ZF and return it */
|
||||
|
@ -315,7 +315,7 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
|
|||
Character, ScanCode, Bda->KeybdShiftFlags);
|
||||
|
||||
Quit:
|
||||
PicIRQComplete(Stack);
|
||||
PicIRQComplete(LOBYTE(Stack[STACK_INT_NUM]));
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// Mouse IRQ 12
|
||||
static VOID WINAPI BiosMouseIrq(LPWORD Stack)
|
||||
{
|
||||
PicIRQComplete(Stack);
|
||||
PicIRQComplete(LOBYTE(Stack[STACK_INT_NUM]));
|
||||
}
|
||||
|
||||
VOID BiosMousePs2Interface(LPWORD Stack)
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include "ntvdm.h"
|
||||
#include "emulator.h"
|
||||
#include <isvbop.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "dem.h"
|
||||
|
@ -40,18 +42,18 @@ static VOID WINAPI DosSystemBop(LPWORD Stack)
|
|||
|
||||
switch (FuncNum)
|
||||
{
|
||||
case 0x11: // Load the DOS kernel
|
||||
/* Load the DOS kernel */
|
||||
case 0x11:
|
||||
{
|
||||
BOOLEAN Success = FALSE;
|
||||
LPCSTR DosKernelFileName = "ntdos.sys";
|
||||
HANDLE hDosKernel;
|
||||
ULONG ulDosKernelSize = 0;
|
||||
|
||||
DPRINT1("You are loading Windows NT DOS!\n");
|
||||
|
||||
/* Open the DOS kernel file */
|
||||
hDosKernel = FileOpen("ntdos.sys", &ulDosKernelSize);
|
||||
|
||||
/* If we failed, bail out */
|
||||
hDosKernel = FileOpen(DosKernelFileName, &ulDosKernelSize);
|
||||
if (hDosKernel == NULL) goto Quit;
|
||||
|
||||
/*
|
||||
|
@ -64,7 +66,8 @@ static VOID WINAPI DosSystemBop(LPWORD Stack)
|
|||
ulDosKernelSize,
|
||||
&ulDosKernelSize);
|
||||
|
||||
DPRINT1("Windows NT DOS loading %s at %04X:%04X, size 0x%X ; GetLastError() = %u\n",
|
||||
DPRINT1("Windows NT DOS file '%s' loading %s at %04X:%04X, size 0x%X ; GetLastError() = %u\n",
|
||||
DosKernelFileName,
|
||||
(Success ? "succeeded" : "failed"),
|
||||
getDI(), 0x0000,
|
||||
ulDosKernelSize,
|
||||
|
@ -77,6 +80,8 @@ Quit:
|
|||
if (!Success)
|
||||
{
|
||||
/* We failed everything, stop the VDM */
|
||||
DisplayMessage(L"Windows NT DOS kernel file '%S' loading failed (Error: %u). The VDM will shut down.",
|
||||
DosKernelFileName, GetLastError());
|
||||
EmulatorTerminate();
|
||||
return;
|
||||
}
|
||||
|
@ -301,16 +306,16 @@ ULONG SessionId = 0;
|
|||
//
|
||||
|
||||
/* 16-bit bootstrap code at 0000:7C00 */
|
||||
/* Of course, this is not in real bootsector format, because we don't care */
|
||||
/* Of course, this is not in real bootsector format, because we don't care about it for now */
|
||||
static BYTE Bootsector1[] =
|
||||
{
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_LOAD_DOS, // Call DOS Loading
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_LOAD_DOS
|
||||
};
|
||||
/* This portion of code is run if we failed to load the DOS */
|
||||
// NOTE: This may also be done by the BIOS32.
|
||||
static BYTE Bootsector2[] =
|
||||
{
|
||||
0xEA, // jmp far ptr
|
||||
0x5B, 0xE0, 0x00, 0xF0, // F000:E05B /** HACK! What to do instead?? **/
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_UNSIMULATE
|
||||
};
|
||||
|
||||
static VOID WINAPI DosInitialize(LPWORD Stack);
|
||||
|
@ -319,7 +324,7 @@ VOID DosBootsectorInitialize(VOID)
|
|||
{
|
||||
/* We write the bootsector at 0000:7C00 */
|
||||
ULONG_PTR Address = (ULONG_PTR)SEG_OFF_TO_PTR(0x0000, 0x7C00);
|
||||
CHAR DosKernelFileName[] = ""; // No DOS file name, therefore we'll load DOS32
|
||||
CHAR DosKernelFileName[] = ""; // No DOS BIOS file name, therefore we will load DOS32
|
||||
|
||||
DPRINT("DosBootsectorInitialize\n");
|
||||
|
||||
|
@ -336,43 +341,47 @@ VOID DosBootsectorInitialize(VOID)
|
|||
|
||||
|
||||
//
|
||||
// This function is called by the DOS bootsector. We finish to load
|
||||
// the DOS, then we jump to 0070:0000.
|
||||
// This function is called by the DOS bootsector in case we load DOS32.
|
||||
// It sets up the DOS32 start code then jumps to 0070:0000.
|
||||
//
|
||||
|
||||
/* 16-bit startup code at 0070:0000 */
|
||||
/* 16-bit startup code for DOS32 at 0070:0000 */
|
||||
static BYTE Startup[] =
|
||||
{
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_START_DOS, // Call DOS Start
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_START_DOS,
|
||||
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_UNSIMULATE
|
||||
};
|
||||
|
||||
static VOID WINAPI DosStart(LPWORD Stack);
|
||||
|
||||
static VOID WINAPI DosInitialize(LPWORD Stack)
|
||||
{
|
||||
BOOLEAN Success = FALSE;
|
||||
|
||||
/* Get the DOS kernel file name (NULL-terminated) */
|
||||
/* Get the DOS BIOS file name (NULL-terminated) */
|
||||
// FIXME: Isn't it possible to use some DS:SI instead??
|
||||
LPCSTR DosKernelFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
|
||||
setIP(getIP() + strlen(DosKernelFileName) + 1); // Skip it
|
||||
LPCSTR DosBiosFileName = (LPCSTR)SEG_OFF_TO_PTR(getCS(), getIP());
|
||||
setIP(getIP() + strlen(DosBiosFileName) + 1); // Skip it
|
||||
|
||||
DPRINT("DosInitialize('%s')\n", DosKernelFileName);
|
||||
DPRINT("DosInitialize('%s')\n", DosBiosFileName);
|
||||
|
||||
/*
|
||||
* We succeeded, deregister the DOS Loading BOP
|
||||
* so that no app will be able to call us back.
|
||||
*/
|
||||
RegisterBop(BOP_LOAD_DOS, NULL);
|
||||
|
||||
/* Register the DOS BOPs */
|
||||
RegisterBop(BOP_DOS, DosSystemBop );
|
||||
RegisterBop(BOP_CMD, DosCmdInterpreterBop);
|
||||
|
||||
if (DosKernelFileName && DosKernelFileName[0] != '\0')
|
||||
if (DosBiosFileName && DosBiosFileName[0] != '\0')
|
||||
{
|
||||
BOOLEAN Success = FALSE;
|
||||
HANDLE hDosBios;
|
||||
ULONG ulDosBiosSize = 0;
|
||||
|
||||
/* Open the DOS BIOS file */
|
||||
hDosBios = FileOpen(DosKernelFileName, &ulDosBiosSize);
|
||||
|
||||
/* If we failed, bail out */
|
||||
if (hDosBios == NULL) goto QuitCustom;
|
||||
hDosBios = FileOpen(DosBiosFileName, &ulDosBiosSize);
|
||||
if (hDosBios == NULL) goto Quit;
|
||||
|
||||
/* Attempt to load the DOS BIOS into memory */
|
||||
Success = FileLoadByHandle(hDosBios,
|
||||
|
@ -380,7 +389,8 @@ static VOID WINAPI DosInitialize(LPWORD Stack)
|
|||
ulDosBiosSize,
|
||||
&ulDosBiosSize);
|
||||
|
||||
DPRINT1("DOS BIOS loading %s at %04X:%04X, size 0x%X ; GetLastError() = %u\n",
|
||||
DPRINT1("DOS BIOS file '%s' loading %s at %04X:%04X, size 0x%X ; GetLastError() = %u\n",
|
||||
DosBiosFileName,
|
||||
(Success ? "succeeded" : "failed"),
|
||||
0x0070, 0x0000,
|
||||
ulDosBiosSize,
|
||||
|
@ -389,52 +399,32 @@ static VOID WINAPI DosInitialize(LPWORD Stack)
|
|||
/* Close the DOS BIOS file */
|
||||
FileClose(hDosBios);
|
||||
|
||||
if (!Success) goto QuitCustom;
|
||||
|
||||
/* Position execution pointers and return */
|
||||
setCS(0x0070);
|
||||
setIP(0x0000);
|
||||
|
||||
/* Return control */
|
||||
QuitCustom:
|
||||
Quit:
|
||||
if (!Success)
|
||||
DisplayMessage(L"Custom DOS '%S' loading failed, what to do??", DosKernelFileName);
|
||||
{
|
||||
DisplayMessage(L"DOS BIOS file '%S' loading failed (Error: %u). The VDM will shut down.",
|
||||
DosBiosFileName, GetLastError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Success = DosBIOSInitialize();
|
||||
// Success &= DosKRNLInitialize();
|
||||
|
||||
if (!Success) goto Quit32;
|
||||
|
||||
/* Write the "bootsector" */
|
||||
/* Load the 16-bit startup code for DOS32 and register its Starting BOP */
|
||||
RtlCopyMemory(SEG_OFF_TO_PTR(0x0070, 0x0000), Startup, sizeof(Startup));
|
||||
|
||||
/* Register the DOS Starting BOP */
|
||||
// This is the equivalent of BOP_LOAD_DOS, function 0x11 "Load the DOS kernel"
|
||||
// for the Windows NT DOS.
|
||||
RegisterBop(BOP_START_DOS, DosStart);
|
||||
|
||||
/* Position execution pointers and return */
|
||||
setCS(0x0070);
|
||||
setIP(0x0000);
|
||||
|
||||
/* Return control */
|
||||
Quit32:
|
||||
if (!Success)
|
||||
DisplayMessage(L"DOS32 loading failed, what to do??");
|
||||
}
|
||||
|
||||
if (Success)
|
||||
{
|
||||
/*
|
||||
* We succeeded, deregister the DOS Loading BOP
|
||||
* so that no app will be able to call us back.
|
||||
*/
|
||||
RegisterBop(BOP_LOAD_DOS, NULL);
|
||||
}
|
||||
/* Position execution pointers for DOS startup and return */
|
||||
setCS(0x0070);
|
||||
setIP(0x0000);
|
||||
}
|
||||
|
||||
static VOID WINAPI DosStart(LPWORD Stack)
|
||||
{
|
||||
BOOLEAN Success;
|
||||
#ifdef STANDALONE
|
||||
DWORD Result;
|
||||
CHAR ApplicationName[MAX_PATH];
|
||||
|
@ -451,6 +441,15 @@ static VOID WINAPI DosStart(LPWORD Stack)
|
|||
*/
|
||||
RegisterBop(BOP_START_DOS, NULL);
|
||||
|
||||
Success = DosBIOSInitialize();
|
||||
// Success &= DosKRNLInitialize();
|
||||
if (!Success)
|
||||
{
|
||||
DisplayMessage(L"DOS32 loading failed (Error: %u). The VDM will shut down.", GetLastError());
|
||||
EmulatorTerminate();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Load the mouse driver */
|
||||
DosMouseInitialize();
|
||||
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#undef FreeEnvironmentStrings
|
||||
#define FreeEnvironmentStrings FreeEnvironmentStringsA
|
||||
|
||||
#define CHARACTER_ADDRESS 0x007000FF /* 0070:00FF */
|
||||
|
||||
/* PRIVATE VARIABLES **********************************************************/
|
||||
|
||||
// static BYTE CurrentDrive;
|
||||
|
@ -102,40 +100,11 @@ VOID DosPrintCharacter(WORD FileHandle, CHAR Character)
|
|||
&BytesWritten);
|
||||
}
|
||||
|
||||
BOOLEAN DosBIOSInitialize(VOID)
|
||||
BOOLEAN DosBuildSysEnvBlock(VOID)
|
||||
{
|
||||
PDOS_MCB Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT);
|
||||
|
||||
LPSTR SourcePtr, Environment;
|
||||
LPSTR DestPtr = (LPSTR)SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0);
|
||||
|
||||
#if 0
|
||||
UCHAR i;
|
||||
CHAR CurrentDirectory[MAX_PATH];
|
||||
CHAR DosDirectory[DOS_DIR_LENGTH];
|
||||
LPSTR Path;
|
||||
|
||||
FILE *Stream;
|
||||
WCHAR Buffer[256];
|
||||
#endif
|
||||
|
||||
/* Initialize the MCB */
|
||||
Mcb->BlockType = 'Z';
|
||||
Mcb->Size = USER_MEMORY_SIZE;
|
||||
Mcb->OwnerPsp = 0;
|
||||
|
||||
/* Initialize the link MCB to the UMB area */
|
||||
Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT + USER_MEMORY_SIZE + 1);
|
||||
Mcb->BlockType = 'M';
|
||||
Mcb->Size = UMB_START_SEGMENT - FIRST_MCB_SEGMENT - USER_MEMORY_SIZE - 2;
|
||||
Mcb->OwnerPsp = SYSTEM_PSP;
|
||||
|
||||
/* Initialize the UMB area */
|
||||
Mcb = SEGMENT_TO_MCB(UMB_START_SEGMENT);
|
||||
Mcb->BlockType = 'Z';
|
||||
Mcb->Size = UMB_END_SEGMENT - UMB_START_SEGMENT;
|
||||
Mcb->OwnerPsp = 0;
|
||||
|
||||
/* Get the environment strings */
|
||||
SourcePtr = Environment = GetEnvironmentStrings();
|
||||
if (Environment == NULL) return FALSE;
|
||||
|
@ -178,6 +147,40 @@ BOOLEAN DosBIOSInitialize(VOID)
|
|||
/* Free the memory allocated for environment strings */
|
||||
FreeEnvironmentStrings(Environment);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN DosBIOSInitialize(VOID)
|
||||
{
|
||||
#if 0
|
||||
UCHAR i;
|
||||
CHAR CurrentDirectory[MAX_PATH];
|
||||
CHAR DosDirectory[DOS_DIR_LENGTH];
|
||||
LPSTR Path;
|
||||
|
||||
FILE *Stream;
|
||||
WCHAR Buffer[256];
|
||||
#endif
|
||||
|
||||
/* Set the data segment */
|
||||
setDS(DOS_DATA_SEGMENT);
|
||||
|
||||
/* Initialize the DOS stack */
|
||||
// Stack just before FIRST_MCB_SEGMENT and after SYSTEM_ENV_BLOCK
|
||||
// FIXME: Add a block of fixed size for the stack in DOS_DATA instead!
|
||||
setSS(0x0F00);
|
||||
setSP(0x0FF0);
|
||||
setBP(0x091E); // DOS base stack pointer relic value
|
||||
|
||||
/* Initialize memory management */
|
||||
DosInitializeMemory();
|
||||
|
||||
/* Build the system master environment block (inherited by the shell) */
|
||||
if (!DosBuildSysEnvBlock())
|
||||
{
|
||||
DPRINT1("An error occurred when setting up the system environment block.\n");
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
|
|
|
@ -1502,7 +1502,6 @@ VOID WINAPI DosInt21h(LPWORD Stack)
|
|||
/* Return the DOS "list of lists" in ES:BX */
|
||||
setES(DOS_DATA_SEGMENT);
|
||||
setBX(DOS_DATA_OFFSET(SysVars.FirstDpb));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1877,6 +1876,7 @@ VOID WINAPI DosAbsoluteRead(LPWORD Stack)
|
|||
/*
|
||||
* This call should leave the flags on the stack for some reason,
|
||||
* so move the stack by one word.
|
||||
* See: http://www.techhelpmanual.com/565-int_25h_26h__absolute_disk_read_write.html
|
||||
*/
|
||||
Stack[STACK_INT_NUM] = Stack[STACK_IP];
|
||||
Stack[STACK_IP] = Stack[STACK_CS];
|
||||
|
@ -1896,6 +1896,7 @@ VOID WINAPI DosAbsoluteWrite(LPWORD Stack)
|
|||
/*
|
||||
* This call should leave the flags on the stack for some reason,
|
||||
* so move the stack by one word.
|
||||
* See: http://www.techhelpmanual.com/565-int_25h_26h__absolute_disk_read_write.html
|
||||
*/
|
||||
Stack[STACK_INT_NUM] = Stack[STACK_IP];
|
||||
Stack[STACK_IP] = Stack[STACK_CS];
|
||||
|
@ -1966,19 +1967,27 @@ VOID WINAPI DosInt2Fh(LPWORD Stack)
|
|||
DWORD DriverEntry;
|
||||
if (!XmsGetDriverEntry(&DriverEntry)) break;
|
||||
|
||||
if (getAL() == 0x00)
|
||||
switch (getAL())
|
||||
{
|
||||
/* The driver is loaded */
|
||||
setAL(0x80);
|
||||
}
|
||||
else if (getAL() == 0x10)
|
||||
{
|
||||
setES(HIWORD(DriverEntry));
|
||||
setBX(LOWORD(DriverEntry));
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Unknown DOS XMS Function: INT 0x2F, AH = 43h, AL = %xh\n", getAL());
|
||||
/* Installation Check */
|
||||
case 0x00:
|
||||
{
|
||||
/* The driver is loaded */
|
||||
setAL(0x80);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get Driver Address */
|
||||
case 0x10:
|
||||
{
|
||||
setES(HIWORD(DriverEntry));
|
||||
setBX(LOWORD(DriverEntry));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
DPRINT1("Unknown DOS XMS Function: INT 0x2F, AH = 43h, AL = %xh\n", getAL());
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2125,7 +2134,7 @@ BOOLEAN DosKRNLInitialize(VOID)
|
|||
RegisterDosInt32(0x27, DosInt27h ); // Terminate and Stay Resident
|
||||
RegisterDosInt32(0x28, DosIdle ); // DOS Idle Interrupt
|
||||
RegisterDosInt32(0x29, DosFastConOut ); // DOS 2+ Fast Console Output
|
||||
RegisterDosInt32(0x2F, DosInt2Fh );
|
||||
RegisterDosInt32(0x2F, DosInt2Fh ); // Multiplex Interrupt
|
||||
|
||||
/* Unimplemented DOS interrupts */
|
||||
RegisterDosInt32(0x2A, NULL); // Network - Installation Check
|
||||
|
|
|
@ -624,7 +624,7 @@ WORD DosOpenFile(LPWORD Handle,
|
|||
return (WORD)GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DescriptorId = DosFindFreeDescriptor();
|
||||
if (DescriptorId == 0xFF)
|
||||
{
|
||||
|
@ -1026,7 +1026,7 @@ BOOLEAN DosDeviceIoControl(WORD FileHandle, BYTE ControlCode, DWORD Buffer, PWOR
|
|||
{
|
||||
/* Not ready */
|
||||
*Length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -153,7 +153,7 @@ static USHORT EmsMap(USHORT Handle, UCHAR PhysicalPage, USHORT LogicalPage)
|
|||
}
|
||||
|
||||
PageEntry = GetLogicalPage(HandleEntry, LogicalPage);
|
||||
if (!PageEntry) return EMS_STATUS_INV_LOGICAL_PAGE;
|
||||
if (!PageEntry) return EMS_STATUS_INV_LOGICAL_PAGE;
|
||||
|
||||
Mapping[PhysicalPage] = (PVOID)((ULONG_PTR)EmsMemory
|
||||
+ ARRAY_INDEX(PageEntry, PageTable) * EMS_PAGE_SIZE);
|
||||
|
@ -501,7 +501,6 @@ BOOLEAN EmsDrvInitialize(ULONG TotalPages)
|
|||
EmsReadMemory,
|
||||
EmsWriteMemory);
|
||||
|
||||
|
||||
/* Create the device */
|
||||
Node = DosCreateDeviceEx(DOS_DEVATTR_IOCTL | DOS_DEVATTR_CHARACTER,
|
||||
EMS_DEVICE_NAME,
|
||||
|
|
|
@ -485,7 +485,7 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack)
|
|||
|
||||
if (Entry && Entry->Handle != 0)
|
||||
{
|
||||
INT i;
|
||||
UINT i;
|
||||
UCHAR Handles = 0;
|
||||
|
||||
for (i = 0; i < XMS_MAX_HANDLES; i++)
|
||||
|
@ -557,7 +557,7 @@ static VOID WINAPI XmsBopProcedure(LPWORD Stack)
|
|||
{
|
||||
WORD Segment;
|
||||
WORD MaxAvailable;
|
||||
|
||||
|
||||
Segment = DosResizeMemory(getDX(), getBX(), &MaxAvailable);
|
||||
|
||||
if (Segment)
|
||||
|
|
|
@ -274,7 +274,7 @@ BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable)
|
|||
|
||||
/* It is, split it into two blocks */
|
||||
NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1);
|
||||
|
||||
|
||||
/* Initialize the new MCB structure */
|
||||
NextMcb->BlockType = Mcb->BlockType;
|
||||
NextMcb->Size = Mcb->Size - NewSize - 1;
|
||||
|
@ -312,7 +312,7 @@ Done:
|
|||
/* Return the maximum possible size */
|
||||
if (MaxAvailable) *MaxAvailable = ReturnSize;
|
||||
}
|
||||
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
@ -402,3 +402,26 @@ VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner)
|
|||
Mcb->OwnerPsp = NewOwner;
|
||||
}
|
||||
|
||||
VOID DosInitializeMemory(VOID)
|
||||
{
|
||||
PDOS_MCB Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT);
|
||||
|
||||
/* Initialize the MCB */
|
||||
Mcb->BlockType = 'Z';
|
||||
Mcb->Size = USER_MEMORY_SIZE;
|
||||
Mcb->OwnerPsp = 0;
|
||||
|
||||
/* Initialize the link MCB to the UMB area */
|
||||
Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT + USER_MEMORY_SIZE + 1);
|
||||
Mcb->BlockType = 'M';
|
||||
Mcb->Size = UMB_START_SEGMENT - FIRST_MCB_SEGMENT - USER_MEMORY_SIZE - 2;
|
||||
Mcb->OwnerPsp = SYSTEM_PSP;
|
||||
|
||||
/* Initialize the UMB area */
|
||||
Mcb = SEGMENT_TO_MCB(UMB_START_SEGMENT);
|
||||
Mcb->BlockType = 'Z';
|
||||
Mcb->Size = UMB_END_SEGMENT - UMB_START_SEGMENT;
|
||||
Mcb->OwnerPsp = 0;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
/* TYPEDEFS *******************************************************************/
|
||||
|
||||
#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
|
||||
#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)SEG_OFF_TO_PTR((seg), 0))
|
||||
|
||||
enum DOS_ALLOC_STRATEGY
|
||||
{
|
||||
|
@ -45,6 +45,8 @@ BOOLEAN DosLinkUmb(VOID);
|
|||
BOOLEAN DosUnlinkUmb(VOID);
|
||||
VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner);
|
||||
|
||||
VOID DosInitializeMemory(VOID);
|
||||
|
||||
#endif // _DOS_MEMORY_H_
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
|
||||
/* DEFINITIONS ****************************************************************/
|
||||
|
||||
#define DOS_CMDLINE_LENGTH 127
|
||||
#define DOS_CMDLINE_LENGTH 127
|
||||
#define DOS_PROGRAM_NAME_TAG 0x0001
|
||||
|
||||
#define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
|
||||
#define SEGMENT_TO_PSP(seg) ((PDOS_PSP)SEG_OFF_TO_PTR((seg), 0))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DOS_LOAD_AND_EXECUTE = 0x00,
|
||||
DOS_LOAD_ONLY = 0x01,
|
||||
DOS_LOAD_OVERLAY = 0x03
|
||||
DOS_LOAD_ONLY = 0x01,
|
||||
DOS_LOAD_OVERLAY = 0x03
|
||||
} DOS_EXEC_TYPE;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
@ -75,14 +75,12 @@ typedef struct _DOS_EXEC_PARAM_BLOCK
|
|||
typedef struct _DOS_REGISTER_STATE
|
||||
{
|
||||
WORD AX, BX, CX, DX, SI, DI, BP, DS, ES;
|
||||
// WORD IP, CS, Flags; // They are supposed to be already
|
||||
// pushed on stack by the DOS caller.
|
||||
} DOS_REGISTER_STATE, *PDOS_REGISTER_STATE;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* VARIABLES ******************************************************************/
|
||||
|
||||
extern WORD CurrentPsp;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
VOID DosClonePsp(WORD DestSegment, WORD SourceSegment);
|
||||
|
|
|
@ -339,7 +339,7 @@ static VOID WINAPI DosMouseIrq(LPWORD Stack)
|
|||
DosUpdateButtons(ButtonState);
|
||||
|
||||
/* Complete the IRQ */
|
||||
PicIRQComplete(Stack);
|
||||
PicIRQComplete(LOBYTE(Stack[STACK_INT_NUM]));
|
||||
}
|
||||
|
||||
static VOID WINAPI DosMouseService(LPWORD Stack)
|
||||
|
|
|
@ -16,20 +16,19 @@
|
|||
/* DEFINES ********************************************************************/
|
||||
|
||||
/* Basic Memory Management */
|
||||
#define MEM_ALIGN_UP(ptr, align) MEM_ALIGN_DOWN((ULONG_PTR)(ptr) + (align) - 1l, (align))
|
||||
#define MEM_ALIGN_DOWN(ptr, align) (PVOID)((ULONG_PTR)(ptr) & ~((align) - 1l))
|
||||
#define MEM_ALIGN_UP(ptr, align) MEM_ALIGN_DOWN((ULONG_PTR)(ptr) + (align) - 1l, (align))
|
||||
|
||||
#define TO_LINEAR(seg, off) (((seg) << 4) + (off))
|
||||
#define MAX_SEGMENT 0xFFFF
|
||||
#define MAX_OFFSET 0xFFFF
|
||||
#define MAX_ADDRESS 0x1000000 // 16 MB of RAM; see also: kernel32/client/vdm.c!BaseGetVdmConfigInfo
|
||||
|
||||
#define FAR_POINTER(x) \
|
||||
(PVOID)((ULONG_PTR)BaseAddress + TO_LINEAR(HIWORD(x), LOWORD(x)))
|
||||
|
||||
#define SEG_OFF_TO_PTR(seg, off) \
|
||||
(PVOID)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), (off)))
|
||||
|
||||
#define FAR_POINTER(x) SEG_OFF_TO_PTR(HIWORD(x), LOWORD(x))
|
||||
|
||||
#define REAL_TO_PHYS(ptr) (PVOID)((ULONG_PTR)(ptr) + (ULONG_PTR)BaseAddress)
|
||||
#define PHYS_TO_REAL(ptr) (PVOID)((ULONG_PTR)(ptr) - (ULONG_PTR)BaseAddress)
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ static VOID CmosWriteAddress(BYTE Value)
|
|||
{
|
||||
/* Update the NMI enabled flag */
|
||||
NmiEnabled = !(Value & CMOS_DISABLE_NMI);
|
||||
|
||||
|
||||
/* Get the register number */
|
||||
Value &= ~CMOS_DISABLE_NMI;
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ VOID PicInterruptRequest(BYTE Number)
|
|||
|
||||
BYTE PicGetInterrupt(VOID)
|
||||
{
|
||||
INT i;
|
||||
UINT i;
|
||||
|
||||
/* Search the master PIC interrupts by priority */
|
||||
for (i = 0; i < 8; i++)
|
||||
|
@ -299,7 +299,7 @@ BYTE PicGetInterrupt(VOID)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Spurious interrupt */
|
||||
if (MasterPic.InServiceRegister & (1 << 2)) return SlavePic.IntOffset + 7;
|
||||
else return MasterPic.IntOffset + 7;
|
||||
|
@ -330,7 +330,7 @@ call_ica_hw_interrupt(INT ms,
|
|||
/*
|
||||
* Adjust the interrupt request number according to the parameters,
|
||||
* by adding an offset == 8 to the interrupt number.
|
||||
*
|
||||
*
|
||||
* Indeed VDDs calling this function usually subtracts 8 so that they give:
|
||||
*
|
||||
* ms | line | corresponding interrupt number
|
||||
|
|
|
@ -777,7 +777,7 @@ static BOOLEAN VgaInitializePalette(VOID)
|
|||
VGA_MAX_COLORS * sizeof(PALETTEENTRY));
|
||||
TextPalette = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
HEAP_ZERO_MEMORY,
|
||||
sizeof(LOGPALETTE) +
|
||||
sizeof(LOGPALETTE) +
|
||||
(VGA_AC_PAL_F_REG + 1) * sizeof(PALETTEENTRY));
|
||||
if ((Palette == NULL) || (TextPalette == NULL)) goto Cleanup;
|
||||
|
||||
|
@ -1461,7 +1461,7 @@ static BYTE WINAPI VgaReadPort(USHORT Port)
|
|||
|
||||
case VGA_SEQ_INDEX:
|
||||
return VgaSeqIndex;
|
||||
|
||||
|
||||
case VGA_SEQ_DATA:
|
||||
return VgaSeqRegisters[VgaSeqIndex];
|
||||
|
||||
|
@ -1985,7 +1985,7 @@ VOID FASTCALL VgaReadMemory(ULONG Address, PVOID Buffer, ULONG Size)
|
|||
for (i = 0; i < Size; i++)
|
||||
{
|
||||
VideoAddress = VgaTranslateReadAddress(Address + i);
|
||||
|
||||
|
||||
/* Copy the value to the buffer */
|
||||
BufPtr[i] = VgaMemory[VideoAddress];
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ VOID FASTCALL EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buff
|
|||
if (Address >= 0xFFFFFFF0) Address -= 0xFFF00000;
|
||||
|
||||
/* If the A20 line is disabled, mask bit 20 */
|
||||
if (!A20Line) Address &= ~(1 << 20);
|
||||
if (!A20Line) Address &= ~(1 << 20);
|
||||
|
||||
if ((Address + Size - 1) >= MAX_ADDRESS)
|
||||
{
|
||||
|
@ -171,7 +171,7 @@ VOID FASTCALL EmulatorReadMemory(PFAST486_STATE State, ULONG Address, PVOID Buff
|
|||
}
|
||||
else
|
||||
{
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
{
|
||||
Offset = (i == FirstPage) ? (Address & (PAGE_SIZE - 1)) : 0;
|
||||
Length = ((i == LastPage) ? (Address + Size - (LastPage << 12)) : PAGE_SIZE) - Offset;
|
||||
|
@ -190,7 +190,7 @@ VOID FASTCALL EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buf
|
|||
UNREFERENCED_PARAMETER(State);
|
||||
|
||||
/* If the A20 line is disabled, mask bit 20 */
|
||||
if (!A20Line) Address &= ~(1 << 20);
|
||||
if (!A20Line) Address &= ~(1 << 20);
|
||||
|
||||
if (Address >= MAX_ADDRESS) return;
|
||||
Size = min(Size, MAX_ADDRESS - Address);
|
||||
|
@ -204,7 +204,7 @@ VOID FASTCALL EmulatorWriteMemory(PFAST486_STATE State, ULONG Address, PVOID Buf
|
|||
}
|
||||
else
|
||||
{
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
for (i = FirstPage; i <= LastPage; i++)
|
||||
{
|
||||
Offset = (i == FirstPage) ? (Address & (PAGE_SIZE - 1)) : 0;
|
||||
Length = ((i == LastPage) ? (Address + Size - (LastPage << 12)) : PAGE_SIZE) - Offset;
|
||||
|
|
|
@ -27,7 +27,7 @@ typedef BOOLEAN
|
|||
ULONG Address,
|
||||
PVOID Buffer,
|
||||
ULONG Size
|
||||
);
|
||||
);
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
|
|
Loading…
Reference in a new issue