#define BIOS_PIC_SLAVE_INT 0x70
#define BIOS_SEGMENT 0xF000
#define BIOS_VIDEO_INTERRUPT 0x10
+#define BIOS_EQUIPMENT_INTERRUPT 0x11
#define BIOS_KBD_INTERRUPT 0x16
#define BIOS_TIME_INTERRUPT 0x1A
#define CONSOLE_FONT_HEIGHT 8
#define BIOS_KBD_BUFFER_SIZE 256
+#define BIOS_EQUIPMENT_LIST 0x3C // HACK: Disable FPU for now
/* FUNCTIONS ******************************************************************/
WORD BiosPeekCharacter();
WORD BiosGetCharacter();
VOID BiosVideoService();
+VOID BiosEquipmentService();
VOID BiosKeyboardService();
VOID BiosTimeService();
VOID BiosHandleIrq(BYTE IrqNumber);
/* Advance to the next string */
Ptr += strlen(Ptr) + 1;
- DestBuffer += strlen(Ptr) + 1;
+ DestBuffer += strlen(Ptr);
+
+ /* Put a zero after the string */
+ *(DestBuffer++) = 0;
}
/* Set the final zero */
PspBlock->Exit[0] = 0xCD; // int 0x20
PspBlock->Exit[1] = 0x20;
- /* Set the program size */
- PspBlock->MemSize = ProgramSize;
+ /* Set the number of the last paragraph */
+ PspBlock->LastParagraph = PspSegment + ProgramSize - 1;
/* Save the interrupt vectors */
PspBlock->TerminateAddress = IntVecTable[0x22];
LPSTR ProgramFilePath, Parameters[128];
CHAR CommandLineCopy[128];
INT ParamCount = 0;
- WORD i, Segment = 0, FileSize, ExeSize;
+ DWORD Segment = 0;
+ DWORD i, FileSize, ExeSize;
PIMAGE_DOS_HEADER Header;
PDWORD RelocationTable;
PWORD RelocWord;
// TODO: Verify checksum and executable!
/* Get the base size of the file, in paragraphs (rounded up) */
- ExeSize = (((Header->e_cp - 1) << 8) + Header->e_cblp + 0x0F) >> 4;
+ ExeSize = (((Header->e_cp - 1) * 512) + Header->e_cblp + 0x0F) >> 4;
+
+ /* Add the PSP size, in paragraphs */
+ ExeSize += sizeof(DOS_PSP) >> 4;
+
+ /* Add the maximum size that should be allocated */
+ ExeSize += Header->e_maxalloc;
- /* Loop from the maximum to the minimum number of extra paragraphs */
- for (i = Header->e_maxalloc; i >= Header->e_minalloc; i--)
+ /* Make sure it does not pass 0xFFFF */
+ if (ExeSize > 0xFFFF) ExeSize = 0xFFFF;
+
+ /* Reduce the size one by one until the allocation is successful */
+ for (i = Header->e_maxalloc; i >= Header->e_minalloc; i--, ExeSize--)
{
/* Try to allocate that much memory */
- Segment = DosAllocateMemory(ExeSize + (sizeof(DOS_PSP) >> 4) + i, NULL);
+ Segment = DosAllocateMemory(ExeSize, NULL);
if (Segment != 0) break;
}
/* Initialize the PSP */
DosInitializePsp(Segment,
- CommandLine, ExeSize + (sizeof(DOS_PSP) >> 4) + i,
+ CommandLine,
+ ExeSize,
EnvBlock);
/* The process owns its own memory */
CHAR DosReadCharacter()
{
- // TODO: STDIN can be redirected under DOS 2.0+
- CHAR Character = 0;
+ CHAR Character = '\0';
+ WORD BytesRead;
- /* A zero value for the character indicates a special key */
- do Character = BiosGetCharacter();
- while (!Character);
+ /* Use the file reading function */
+ DosReadFile(DOS_INPUT_HANDLE, &Character, sizeof(CHAR), &BytesRead);
return Character;
}
VOID DosPrintCharacter(CHAR Character)
{
- // TODO: STDOUT can be redirected under DOS 2.0+
- if (Character == '\r') Character = '\n';
- putchar(Character);
+ WORD BytesWritten;
+
+ /* Use the file writing function */
+ DosWriteFile(DOS_OUTPUT_HANDLE, &Character, sizeof(CHAR), &BytesWritten);
}
VOID DosInt20h(WORD CodeSegment)
/* Initialize the MCB */
Mcb->BlockType = 'Z';
- Mcb->Size = (WORD)USER_MEMORY_SIZE;
+ Mcb->Size = USER_MEMORY_SIZE;
Mcb->OwnerPsp = 0;
/* Get the environment strings */
/* Move to the next string */
SourcePtr += wcslen(SourcePtr) + 1;
- DestPtr += strlen(AsciiString) + 1;
+ DestPtr += strlen(AsciiString);
+ *(DestPtr++) = 0;
}
+ *DestPtr = 0;
/* Free the memory allocated for environment strings */
FreeEnvironmentStringsW(Environment);
#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
-#define USER_MEMORY_SIZE 0x8FFFF
+#define USER_MEMORY_SIZE 0x8FFF
#define SYSTEM_PSP 0x08
#define SYSTEM_ENV_BLOCK 0x800
#define INVALID_DOS_HANDLE 0xFFFF
+#define DOS_INPUT_HANDLE 0
+#define DOS_OUTPUT_HANDLE 1
+#define DOS_ERROR_HANDLE 2
#define DOS_SFT_SIZE 255
#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
#define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0)))
typedef struct _DOS_PSP
{
BYTE Exit[2];
- WORD MemSize;
+ WORD LastParagraph;
BYTE Reserved0[6];
DWORD TerminateAddress;
DWORD BreakAddress;
BiosVideoService();
break;
}
+ case BIOS_EQUIPMENT_INTERRUPT:
+ {
+ /* This is the BIOS "get equipment" command, call the BIOS */
+ BiosEquipmentService();
+ break;
+ }
case BIOS_KBD_INTERRUPT:
{
/* This is the keyboard BIOS interrupt, call the BIOS */
BOOLEAN EmulatorInitialize()
{
/* Allocate memory for the 16-bit address space */
- BaseAddress = HeapAlloc(GetProcessHeap(), 0, MAX_ADDRESS);
+ BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS);
if (BaseAddress == NULL) return FALSE;
/* Initialize the softx86 CPU emulator */