DOS: Make use of get/setAX and consorts instead of EmulatorGet/SetRegister(EMULATOR_REG_AX, ...).
Start to implement real (but undocumented?) behaviour according to http://www.delorie.com/djgpp/doc/rbinter/
and http://www.datadoctor.biz/fr/data_recovery_programming_book_chapter6-pageXX.html (change XX by a valid page number)
and http://spike.scu.edu.au/~barry/interrupts.html

svn path=/branches/ntvdm/; revision=60778
This commit is contained in:
Hermès Bélusca-Maïto 2013-10-27 22:31:53 +00:00
parent d35b972d75
commit 09d991b838
3 changed files with 188 additions and 257 deletions

View file

@ -14,6 +14,8 @@
#include "bios.h"
#include "emulator.h"
#include "registers.h"
/* PRIVATE VARIABLES **********************************************************/
static WORD CurrentPsp = SYSTEM_PSP;
@ -87,7 +89,7 @@ static WORD DosCopyEnvironmentBlock(WORD SourceSegment, LPCSTR ProgramName)
ULONG TotalSize = 0;
WORD DestSegment;
Ptr = SourceBuffer = (PCHAR)((ULONG_PTR)BaseAddress + TO_LINEAR(SourceSegment, 0));
Ptr = SourceBuffer = (PCHAR)SEG_OFF_TO_PTR(SourceSegment, 0);
/* Calculate the size of the environment block */
while (*Ptr)
@ -106,7 +108,7 @@ static WORD DosCopyEnvironmentBlock(WORD SourceSegment, LPCSTR ProgramName)
Ptr = SourceBuffer;
DestBuffer = (PCHAR)((ULONG_PTR)BaseAddress + TO_LINEAR(DestSegment, 0));
DestBuffer = (PCHAR)SEG_OFF_TO_PTR(DestSegment, 0);
while (*Ptr)
{
/* Copy the string */
@ -1105,8 +1107,7 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
DosChangeMemoryOwner(EnvBlock, Segment);
/* Copy the program to Segment:0100 */
RtlCopyMemory((PVOID)((ULONG_PTR)BaseAddress
+ TO_LINEAR(Segment, 0x100)),
RtlCopyMemory(SEG_OFF_TO_PTR(Segment, 0x100),
Address + (Header->e_cparhdr << 4),
min(FileSize - (Header->e_cparhdr << 4),
(ExeSize << 4) - sizeof(DOS_PSP)));
@ -1118,17 +1119,16 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
for (i = 0; i < Header->e_crlc; i++)
{
/* Get a pointer to the word that needs to be patched */
RelocWord = (PWORD)((ULONG_PTR)BaseAddress
+ TO_LINEAR(Segment + HIWORD(RelocationTable[i]),
0x100 + LOWORD(RelocationTable[i])));
RelocWord = (PWORD)SEG_OFF_TO_PTR(Segment + HIWORD(RelocationTable[i]),
0x100 + LOWORD(RelocationTable[i]));
/* Add the number of the EXE segment to it */
*RelocWord += Segment + (sizeof(DOS_PSP) >> 4);
}
/* Set the initial segment registers */
EmulatorSetRegister(EMULATOR_REG_DS, Segment);
EmulatorSetRegister(EMULATOR_REG_ES, Segment);
setDS(Segment);
setES(Segment);
/* Set the stack to the location from the header */
EmulatorSetStack(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss,
@ -1161,8 +1161,7 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
DosChangeMemoryOwner(EnvBlock, Segment);
/* Copy the program to Segment:0100 */
RtlCopyMemory((PVOID)((ULONG_PTR)BaseAddress
+ TO_LINEAR(Segment, 0x100)),
RtlCopyMemory(SEG_OFF_TO_PTR(Segment, 0x100),
Address,
FileSize);
@ -1173,8 +1172,8 @@ BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock)
EnvBlock);
/* Set the initial segment registers */
EmulatorSetRegister(EMULATOR_REG_DS, Segment);
EmulatorSetRegister(EMULATOR_REG_ES, Segment);
setDS(Segment);
setES(Segment);
/* Set the stack to the last word of the segment */
EmulatorSetStack(Segment, 0xFFFE);
@ -1345,8 +1344,7 @@ BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle)
InfoWord |= 1 << 7;
/* Return the device information word */
EmulatorSetRegister(EMULATOR_REG_DX, InfoWord);
setDX(InfoWord);
return TRUE;
}
@ -1373,15 +1371,9 @@ VOID DosInt21h(LPWORD Stack)
SYSTEMTIME SystemTime;
PCHAR String;
PDOS_INPUT_BUFFER InputBuffer;
DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX);
DWORD Ecx = EmulatorGetRegister(EMULATOR_REG_CX);
DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX);
DWORD Ebx = EmulatorGetRegister(EMULATOR_REG_BX);
WORD DataSegment = (WORD)EmulatorGetRegister(EMULATOR_REG_DS);
WORD ExtSegment = (WORD)EmulatorGetRegister(EMULATOR_REG_ES);
/* Check the value in the AH register */
switch (HIBYTE(Eax))
switch (getAH())
{
/* Terminate Program */
case 0x00:
@ -1396,45 +1388,58 @@ VOID DosInt21h(LPWORD Stack)
Character = DosReadCharacter();
DosPrintCharacter(Character);
if (!EmulatorGetFlag(EMULATOR_FLAG_CF))
{
EmulatorSetRegister(EMULATOR_REG_AX, (Eax & 0xFFFFFF00) | Character);
}
/* Let the BOP repeat if needed */
if (EmulatorGetFlag(EMULATOR_FLAG_CF)) break;
setAL(Character);
break;
}
/* Print Character */
case 0x02:
{
DosPrintCharacter(LOBYTE(Edx));
BYTE Character = getDL();
DosPrintCharacter(Character);
/*
* We return the output character (DOS 2.1+), see:
* http://www.delorie.com/djgpp/doc/rbinter/id/65/25.html
* for more information.
*/
setAL(Character);
break;
}
/* Direct Console I/O */
case 0x06:
{
BYTE Character = LOBYTE(Edx);
BYTE Character = getDL();
if (Character != 0xFF)
{
/* Output */
DosPrintCharacter(Character);
/*
* We return the output character (DOS 2.1+), see:
* http://www.delorie.com/djgpp/doc/rbinter/id/69/25.html
* for more information.
*/
setAL(Character);
}
else
{
/* Input */
Eax &= 0xFFFFFF00;
if (DosCheckInput())
{
Eax |= DosReadCharacter();
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF;
setAL(DosReadCharacter());
}
else
{
/* No character available */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF;
setAL(0);
}
}
@ -1447,35 +1452,37 @@ VOID DosInt21h(LPWORD Stack)
{
Character = DosReadCharacter();
if (!EmulatorGetFlag(EMULATOR_FLAG_CF))
{
EmulatorSetRegister(EMULATOR_REG_AX, (Eax & 0xFFFFFF00) | Character);
}
/* Let the BOP repeat if needed */
if (EmulatorGetFlag(EMULATOR_FLAG_CF)) break;
setAL(Character);
break;
}
/* Print String */
case 0x09:
{
String = (PCHAR)((ULONG_PTR)BaseAddress
+ TO_LINEAR(DataSegment, LOWORD(Edx)));
String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
while ((*String) != '$')
while (*String != '$')
{
DosPrintCharacter(*String);
String++;
}
/*
* We return the output character (DOS 2.1+), see:
* http://www.delorie.com/djgpp/doc/rbinter/id/73/25.html
* for more information.
*/
setAL('$');
break;
}
/* Read Buffered Input */
case 0x0A:
{
InputBuffer = (PDOS_INPUT_BUFFER)((ULONG_PTR)BaseAddress
+ TO_LINEAR(DataSegment,
LOWORD(Edx)));
InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX());
while (Stack[STACK_COUNTER] < InputBuffer->MaxLength)
{
@ -1495,54 +1502,45 @@ VOID DosInt21h(LPWORD Stack)
/* Update the length */
InputBuffer->Length = Stack[STACK_COUNTER];
break;
}
/* Get STDIN Status */
case 0x0B:
{
if (DosCheckInput()) Eax |= 0xFF;
else Eax &= 0xFFFFFF00;
EmulatorSetRegister(EMULATOR_REG_AX, Eax);
setAL(DosCheckInput() ? 0xFF : 0x00);
break;
}
/* Set Default Drive */
case 0x0E:
{
DosChangeDrive(LOBYTE(Edx));
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFFFF00) | (LastDrive - 'A' + 1));
DosChangeDrive(getDL());
setAL(LastDrive - 'A' + 1);
break;
}
/* Get Default Drive */
case 0x19:
{
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFFFF00) | CurrentDrive);
setAL(CurrentDrive);
break;
}
/* Set Disk Transfer Area */
case 0x1A:
{
DiskTransferArea = MAKELONG(LOWORD(Edx), DataSegment);
DiskTransferArea = MAKELONG(getDX(), getDS());
break;
}
/* Set Interrupt Vector */
case 0x25:
{
DWORD FarPointer = MAKELONG(LOWORD(Edx), DataSegment);
DWORD FarPointer = MAKELONG(getDX(), getDS());
/* Write the new far pointer to the IDT */
((PDWORD)BaseAddress)[LOBYTE(Eax)] = FarPointer;
((PDWORD)BaseAddress)[getAL()] = FarPointer;
break;
}
@ -1551,14 +1549,9 @@ VOID DosInt21h(LPWORD Stack)
case 0x2A:
{
GetLocalTime(&SystemTime);
EmulatorSetRegister(EMULATOR_REG_CX,
(Ecx & 0xFFFF0000) | SystemTime.wYear);
EmulatorSetRegister(EMULATOR_REG_DX,
(Edx & 0xFFFF0000)
| (SystemTime.wMonth << 8)
| SystemTime.wDay);
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFFFF00) | SystemTime.wDayOfWeek);
setCX(SystemTime.wYear);
setDX(MAKEWORD(SystemTime.wDay, SystemTime.wMonth));
setAL(SystemTime.wDayOfWeek);
break;
}
@ -1566,21 +1559,12 @@ VOID DosInt21h(LPWORD Stack)
case 0x2B:
{
GetLocalTime(&SystemTime);
SystemTime.wYear = LOWORD(Ecx);
SystemTime.wMonth = HIBYTE(Edx);
SystemTime.wDay = LOBYTE(Edx);
if (SetLocalTime(&SystemTime))
{
/* Return success */
EmulatorSetRegister(EMULATOR_REG_AX, Eax & 0xFFFFFF00);
}
else
{
/* Return failure */
EmulatorSetRegister(EMULATOR_REG_AX, Eax | 0xFF);
}
SystemTime.wYear = getCX();
SystemTime.wMonth = getDH();
SystemTime.wDay = getDL();
/* Return success or failure */
setAL(SetLocalTime(&SystemTime) ? 0x00 : 0xFF);
break;
}
@ -1588,14 +1572,8 @@ VOID DosInt21h(LPWORD Stack)
case 0x2C:
{
GetLocalTime(&SystemTime);
EmulatorSetRegister(EMULATOR_REG_CX,
(Ecx & 0xFFFF0000)
| (SystemTime.wHour << 8)
| SystemTime.wMinute);
EmulatorSetRegister(EMULATOR_REG_DX,
(Edx & 0xFFFF0000)
| (SystemTime.wSecond << 8)
| (SystemTime.wMilliseconds / 10));
setCX(MAKEWORD(SystemTime.wMinute, SystemTime.wHour));
setDX(MAKEWORD(SystemTime.wMilliseconds / 10, SystemTime.wSecond));
break;
}
@ -1603,31 +1581,21 @@ VOID DosInt21h(LPWORD Stack)
case 0x2D:
{
GetLocalTime(&SystemTime);
SystemTime.wHour = HIBYTE(Ecx);
SystemTime.wMinute = LOBYTE(Ecx);
SystemTime.wSecond = HIBYTE(Edx);
SystemTime.wMilliseconds = LOBYTE(Edx) * 10;
if (SetLocalTime(&SystemTime))
{
/* Return success */
EmulatorSetRegister(EMULATOR_REG_AX, Eax & 0xFFFFFF00);
}
else
{
/* Return failure */
EmulatorSetRegister(EMULATOR_REG_AX, Eax | 0xFF);
}
SystemTime.wHour = getCH();
SystemTime.wMinute = getCL();
SystemTime.wSecond = getDH();
SystemTime.wMilliseconds = getDL() * 10; // In hundredths of seconds
/* Return success or failure */
setAL(SetLocalTime(&SystemTime) ? 0x00 : 0xFF);
break;
}
/* Get Disk Transfer Area */
case 0x2F:
{
EmulatorSetRegister(EMULATOR_REG_ES, HIWORD(DiskTransferArea));
EmulatorSetRegister(EMULATOR_REG_BX, LOWORD(DiskTransferArea));
setES(HIWORD(DiskTransferArea));
setBX(LOWORD(DiskTransferArea));
break;
}
@ -1636,27 +1604,44 @@ VOID DosInt21h(LPWORD Stack)
{
PDOS_PSP PspBlock = SEGMENT_TO_PSP(CurrentPsp);
EmulatorSetRegister(EMULATOR_REG_AX, PspBlock->DosVersion);
if (LOBYTE(PspBlock->DosVersion) < 5 || getAL() == 0)
{
/* Return DOS 24-bit user serial number in BL:CX */
setBL(0x00);
setCX(0x0000);
}
if (LOBYTE(PspBlock->DosVersion) >= 5 && getAL() == 1)
{
/*
* Return DOS OEM number:
* 0x00 for IBM PC-DOS
* 0xFF for MS-DOS
*/
setBH(0xFF);
}
/* Return DOS version: Minor:Major in AH:AL */
setAX(PspBlock->DosVersion);
break;
}
/* Get Interrupt Vector */
case 0x35:
{
DWORD FarPointer = ((PDWORD)BaseAddress)[LOBYTE(Eax)];
DWORD FarPointer = ((PDWORD)BaseAddress)[getAL()];
/* Read the address from the IDT into ES:BX */
EmulatorSetRegister(EMULATOR_REG_ES, HIWORD(FarPointer));
EmulatorSetRegister(EMULATOR_REG_BX, LOWORD(FarPointer));
setES(HIWORD(FarPointer));
setBX(LOWORD(FarPointer));
break;
}
/* Create Directory */
case 0x39:
{
String = (PCHAR)((ULONG_PTR)BaseAddress
+ TO_LINEAR(DataSegment, LOWORD(Edx)));
String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
if (CreateDirectoryA(String, NULL))
{
@ -1665,8 +1650,7 @@ VOID DosInt21h(LPWORD Stack)
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | LOWORD(GetLastError()));
setAX(LOWORD(GetLastError()));
}
break;
@ -1675,8 +1659,7 @@ VOID DosInt21h(LPWORD Stack)
/* Remove Directory */
case 0x3A:
{
String = (PCHAR)((ULONG_PTR)BaseAddress
+ TO_LINEAR(DataSegment, LOWORD(Edx)));
String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
if (RemoveDirectoryA(String))
{
@ -1685,19 +1668,16 @@ VOID DosInt21h(LPWORD Stack)
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | LOWORD(GetLastError()));
setAX(LOWORD(GetLastError()));
}
break;
}
/* Set Current Directory */
case 0x3B:
{
String = (PCHAR)((ULONG_PTR)BaseAddress
+ TO_LINEAR(DataSegment, LOWORD(Edx)));
String = (PCHAR)SEG_OFF_TO_PTR(getDS(), getDX());
if (DosChangeDirectory(String))
{
@ -1706,8 +1686,7 @@ VOID DosInt21h(LPWORD Stack)
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | DosLastError);
setAX(DosLastError);
}
break;
@ -1718,27 +1697,18 @@ VOID DosInt21h(LPWORD Stack)
{
WORD FileHandle;
WORD ErrorCode = DosCreateFile(&FileHandle,
(LPCSTR)(ULONG_PTR)BaseAddress
+ TO_LINEAR(DataSegment, LOWORD(Edx)),
LOWORD(Ecx));
(LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()),
getCX());
if (ErrorCode == 0)
{
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
/* Return the handle in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | FileHandle);
setAX(FileHandle);
}
else
{
/* Set CF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
/* Return the error code in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | ErrorCode);
setAX(ErrorCode);
}
break;
@ -1749,27 +1719,18 @@ VOID DosInt21h(LPWORD Stack)
{
WORD FileHandle;
WORD ErrorCode = DosOpenFile(&FileHandle,
(LPCSTR)(ULONG_PTR)BaseAddress
+ TO_LINEAR(DataSegment, LOWORD(Edx)),
LOBYTE(Eax));
(LPCSTR)SEG_OFF_TO_PTR(getDS(), getDX()),
getAL());
if (ErrorCode == 0)
{
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
/* Return the handle in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | FileHandle);
setAX(FileHandle);
}
else
{
/* Set CF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
/* Return the error code in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | ErrorCode);
setAX(ErrorCode);
}
break;
@ -1778,19 +1739,14 @@ VOID DosInt21h(LPWORD Stack)
/* Close File */
case 0x3E:
{
if (DosCloseHandle(LOWORD(Ebx)))
if (DosCloseHandle(getBX()))
{
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
/* Set CF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
/* Return the error code in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | ERROR_INVALID_HANDLE);
setAX(ERROR_INVALID_HANDLE);
}
break;
@ -1799,9 +1755,9 @@ VOID DosInt21h(LPWORD Stack)
/* Read File */
case 0x3F:
{
WORD Handle = LOWORD(Ebx);
LPBYTE Buffer = (LPBYTE)((ULONG_PTR)BaseAddress + TO_LINEAR(DataSegment, LOWORD(Edx)));
WORD Count = LOWORD(Ecx);
WORD Handle = getBX();
LPBYTE Buffer = (LPBYTE)SEG_OFF_TO_PTR(getDS(), getDX());
WORD Count = getCX();
WORD BytesRead = 0;
WORD ErrorCode = ERROR_SUCCESS;
@ -1830,21 +1786,13 @@ VOID DosInt21h(LPWORD Stack)
if (ErrorCode == 0)
{
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
/* Return the number of bytes read in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | BytesRead);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
setAX(BytesRead);
}
else if (ErrorCode != ERROR_NOT_READY)
{
/* Set CF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
/* Return the error code in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | ErrorCode);
setAX(ErrorCode);
}
break;
}
@ -1853,29 +1801,20 @@ VOID DosInt21h(LPWORD Stack)
case 0x40:
{
WORD BytesWritten = 0;
WORD ErrorCode = DosWriteFile(LOWORD(Ebx),
(LPVOID)((ULONG_PTR)BaseAddress
+ TO_LINEAR(DataSegment, LOWORD(Edx))),
LOWORD(Ecx),
WORD ErrorCode = DosWriteFile(getBX(),
SEG_OFF_TO_PTR(getDS(), getDX()),
getCX(),
&BytesWritten);
if (ErrorCode == 0)
{
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
/* Return the number of bytes written in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | BytesWritten);
setAX(BytesWritten);
}
else
{
/* Set CF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
/* Return the error code in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | ErrorCode);
setAX(ErrorCode);
}
break;
@ -1884,14 +1823,17 @@ VOID DosInt21h(LPWORD Stack)
/* Delete File */
case 0x41:
{
LPSTR FileName = (LPSTR)((ULONG_PTR)BaseAddress + TO_LINEAR(DataSegment, Edx));
LPSTR FileName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX());
/* Call the API function */
if (DeleteFileA(FileName)) Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
if (DeleteFileA(FileName))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, GetLastError());
setAX(GetLastError());
}
break;
@ -1901,30 +1843,23 @@ VOID DosInt21h(LPWORD Stack)
case 0x42:
{
DWORD NewLocation;
WORD ErrorCode = DosSeekFile(LOWORD(Ebx),
MAKELONG(LOWORD(Edx), LOWORD(Ecx)),
LOBYTE(Eax),
WORD ErrorCode = DosSeekFile(getBX(),
MAKELONG(getDX(), getCX()),
getAL(),
&NewLocation);
if (ErrorCode == 0)
{
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
/* Return the new offset in DX:AX */
EmulatorSetRegister(EMULATOR_REG_DX,
(Edx & 0xFFFF0000) | HIWORD(NewLocation));
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | LOWORD(NewLocation));
setDX(HIWORD(NewLocation));
setAX(LOWORD(NewLocation));
}
else
{
/* Set CF */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
/* Return the error code in AX */
EmulatorSetRegister(EMULATOR_REG_AX,
(Eax & 0xFFFF0000) | ErrorCode);
setAX(ErrorCode);
}
break;
@ -1934,9 +1869,9 @@ VOID DosInt21h(LPWORD Stack)
case 0x43:
{
DWORD Attributes;
LPSTR FileName = (LPSTR)((ULONG_PTR)BaseAddress + TO_LINEAR(DataSegment, Edx));
LPSTR FileName = (LPSTR)SEG_OFF_TO_PTR(getDS(), getDX());
if (LOBYTE(Eax) == 0x00)
if (getAL() == 0x00)
{
/* Get the attributes */
Attributes = GetFileAttributesA(FileName);
@ -1945,33 +1880,32 @@ VOID DosInt21h(LPWORD Stack)
if (Attributes == INVALID_FILE_ATTRIBUTES)
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, GetLastError());
setAX(GetLastError());
break;
}
/* Return the attributes that DOS can understand */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_CX,
(Ecx & 0xFFFFFF00) | LOBYTE(Attributes));
// setCL(LOBYTE(Attributes));
setCX(LOWORD(Attributes));
}
else if (LOBYTE(Eax) == 0x01)
else if (getAL() == 0x01)
{
/* Try to set the attributes */
if (SetFileAttributesA(FileName, LOBYTE(Ecx)))
if (SetFileAttributesA(FileName, getCL()))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, GetLastError());
setAX(GetLastError());
}
}
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_FUNCTION);
setAX(ERROR_INVALID_FUNCTION);
}
break;
@ -1980,14 +1914,14 @@ VOID DosInt21h(LPWORD Stack)
/* IOCTL */
case 0x44:
{
if (DosHandleIoctl(LOBYTE(Eax), LOWORD(Ebx)))
if (DosHandleIoctl(getAL(), getBX()))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, DosLastError);
setAX(DosLastError);
}
break;
@ -1997,14 +1931,13 @@ VOID DosInt21h(LPWORD Stack)
case 0x45:
{
WORD NewHandle;
HANDLE Handle = DosGetRealHandle(LOWORD(Ebx));
HANDLE Handle = DosGetRealHandle(getBX());
if (Handle != INVALID_HANDLE_VALUE)
{
/* The handle is invalid */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_HANDLE);
setAX(ERROR_INVALID_HANDLE);
break;
}
@ -2015,29 +1948,27 @@ VOID DosInt21h(LPWORD Stack)
{
/* Too many files open */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_TOO_MANY_OPEN_FILES);
setAX(ERROR_TOO_MANY_OPEN_FILES);
break;
}
/* Return the result */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, NewHandle);
setAX(NewHandle);
break;
}
/* Force Duplicate Handle */
case 0x46:
{
if (DosDuplicateHandle(LOWORD(Ebx), LOWORD(Ecx)))
if (DosDuplicateHandle(getBX(), getCX()))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_HANDLE);
setAX(ERROR_INVALID_HANDLE);
}
break;
@ -2047,18 +1978,18 @@ VOID DosInt21h(LPWORD Stack)
case 0x48:
{
WORD MaxAvailable = 0;
WORD Segment = DosAllocateMemory(LOWORD(Ebx), &MaxAvailable);
WORD Segment = DosAllocateMemory(getBX(), &MaxAvailable);
if (Segment != 0)
{
EmulatorSetRegister(EMULATOR_REG_AX, Segment);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
setAX(Segment);
}
else
{
EmulatorSetRegister(EMULATOR_REG_AX, DosLastError);
EmulatorSetRegister(EMULATOR_REG_BX, MaxAvailable);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
setAX(DosLastError);
setBX(MaxAvailable);
}
break;
@ -2067,14 +1998,14 @@ VOID DosInt21h(LPWORD Stack)
/* Free Memory */
case 0x49:
{
if (DosFreeMemory(ExtSegment))
if (DosFreeMemory(getES()))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_ARENA_TRASHED);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
setAX(ERROR_ARENA_TRASHED);
}
break;
@ -2085,15 +2016,15 @@ VOID DosInt21h(LPWORD Stack)
{
WORD Size;
if (DosResizeMemory(ExtSegment, LOWORD(Ebx), &Size))
if (DosResizeMemory(getES(), getBX(), &Size))
{
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
EmulatorSetRegister(EMULATOR_REG_AX, DosLastError);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_BX, Size);
setAX(DosLastError);
setBX(Size);
}
break;
@ -2102,75 +2033,68 @@ VOID DosInt21h(LPWORD Stack)
/* Terminate With Return Code */
case 0x4C:
{
DosTerminateProcess(CurrentPsp, LOBYTE(Eax));
DosTerminateProcess(CurrentPsp, getAL());
break;
}
/* Get Current Process */
case 0x51:
{
EmulatorSetRegister(EMULATOR_REG_BX, CurrentPsp);
setBX(CurrentPsp);
break;
}
/* Get/Set Memory Management Options */
case 0x58:
{
if (LOBYTE(Eax) == 0x00)
if (getAL() == 0x00)
{
/* Get allocation strategy */
EmulatorSetRegister(EMULATOR_REG_AX, DosAllocStrategy);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
setAX(DosAllocStrategy);
}
else if (LOBYTE(Eax) == 0x01)
else if (getAL() == 0x01)
{
/* Set allocation strategy */
if ((LOBYTE(Ebx) & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))
if ((getBL() & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))
== (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))
{
/* Can't set both */
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_PARAMETER);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
setAX(ERROR_INVALID_PARAMETER);
break;
}
if ((LOBYTE(Ebx) & 0x3F) > DOS_ALLOC_LAST_FIT)
if ((getBL() & 0x3F) > DOS_ALLOC_LAST_FIT)
{
/* Invalid allocation strategy */
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_PARAMETER);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
setAX(ERROR_INVALID_PARAMETER);
break;
}
DosAllocStrategy = LOBYTE(Ebx);
DosAllocStrategy = getBL();
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else if (LOBYTE(Eax) == 0x02)
else if (getAL() == 0x02)
{
/* Get UMB link state */
Eax &= 0xFFFFFF00;
if (DosUmbLinked) Eax |= 1;
EmulatorSetRegister(EMULATOR_REG_AX, Eax);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
setAL(DosUmbLinked ? 0x01 : 0x00);
}
else if (LOBYTE(Eax) == 0x03)
else if (getAL() == 0x03)
{
/* Set UMB link state */
if (Ebx) DosLinkUmb();
if (getBX()) DosLinkUmb();
else DosUnlinkUmb();
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
}
else
{
/* Invalid or unsupported function */
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_FUNCTION);
setAX(ERROR_INVALID_FUNCTION);
}
break;
@ -2179,7 +2103,7 @@ VOID DosInt21h(LPWORD Stack)
/* Unsupported */
default:
{
DPRINT1("DOS Function INT 0x21, AH = 0x%02X NOT IMPLEMENTED!\n", HIBYTE(Eax));
DPRINT1("DOS Function INT 0x21, AH = 0x%02X NOT IMPLEMENTED!\n", getAH());
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
}
}
@ -2200,7 +2124,7 @@ BOOLEAN DosInitialize(VOID)
WCHAR Buffer[256];
LPWSTR SourcePtr, Environment;
LPSTR AsciiString;
LPSTR DestPtr = (LPSTR)((ULONG_PTR)BaseAddress + TO_LINEAR(SYSTEM_ENV_BLOCK, 0));
LPSTR DestPtr = (LPSTR)SEG_OFF_TO_PTR(SYSTEM_ENV_BLOCK, 0);
DWORD AsciiSize;
CHAR CurrentDirectory[MAX_PATH];
CHAR DosDirectory[DOS_DIR_LENGTH];

View file

@ -15,7 +15,11 @@
/* DEFINES ********************************************************************/
//
// We are DOS 6.00
//
#define DOS_VERSION MAKEWORD(6, 0)
#define DOS_CONFIG_PATH L"%SystemRoot%\\system32\\CONFIG.NT"
#define DOS_COMMAND_INTERPRETER L"%SystemRoot%\\system32\\COMMAND.COM /k %SystemRoot%\\system32\\AUTOEXEC.NT"
#define FIRST_MCB_SEGMENT 0x1000

View file

@ -23,11 +23,14 @@
#define TO_LINEAR(seg, off) (((seg) << 4) + (off))
#define MAX_SEGMENT 0xFFFF
#define MAX_OFFSET 0xFFFF
#define MAX_OFFSET 0xFFFF
#define MAX_ADDRESS TO_LINEAR(MAX_SEGMENT, MAX_OFFSET)
#define FAR_POINTER(x) ((ULONG_PTR)BaseAddress + TO_LINEAR(HIWORD(x), LOWORD(x)))
#define SEG_OFF_TO_PTR(seg, off) ((ULONG_PTR)BaseAddress + TO_LINEAR((seg), (off)))
#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 STEPS_PER_CYCLE 256