- Add some level of "Advanced debugging" (see ntvdm.h) which one can adjust to enable/disable debugging features inside NTVDM (this can be useful as long as NTVDM is under heavy bugfixing. When it will be more perfect, this stuff will be removed).
- Add the possibility to load option ROMs at a given segment. Currently their list should be specified from inside ntvdm.c (in the BiosInitialize call), but I plan to make it available from a registry option (or via command-line for NTVDM-standalone mode).
- Start to separate the initialization of "static" BIOS data (stuff that lives in ROM space) and initialization of "dynamic" BIOS data (eg. initializing the interrupt vector table, the BIOS data area at segment 40h, ...) so that we may be able to reuse part of our code to be able to more-or-less run external (16-bit) BIOSes, or the Windows NTVDM BIOS that uses BOPs to run some of its stuff in ntvdm in 32-bit (as we do for our 32-bit BIOS, except that *all* of our bios is 32-bit, not just some parts). Also, some file reorganization will be in order there soon...

- Add video BIOS version information in memory so that tools such as Microsoft Diagnostics can correctly recognize our video BIOS (btw, we try to emulate the functionality of Cirrus' CL-GD5434).
- Correctly put video BIOS ROM header (+ checksum) in memory so that it is recognized as such by diagnostics tools.
- During BIOS POST, scan for ROMs starting segment 0xC000 (where video ROMs reside).
- Store statically the BIOS configuration table.

- Fix INT 16h, AH=12h "Get extended shift states" so that it correctly returns the state of right Ctrl and Alt keys.
- Fix bit-setting state; report that our keyboard is 101/102 enhanced keyboard.
- Correctly set the error return values (AH=86h and CF set) when a function of INT 15h is unsupported.
- Implement INT 15h, AH=C9h "Get CPU Type and Mask Revision"; INT 1Ah, AH=02h "Get Real-Time Clock Time" and Ah=04h "Get Real-Time Clock Date" by reading the CMOS.
- Implement CMOS century register support.

svn path=/trunk/; revision=68598
This commit is contained in:
Hermès Bélusca-Maïto 2015-08-04 20:17:05 +00:00
parent 4689564d5b
commit c549f52a2b
17 changed files with 567 additions and 259 deletions

View file

@ -23,12 +23,13 @@
#include "io.h"
#include "hardware/cmos.h"
#include <stdlib.h>
/* DEFINES ********************************************************************/
/* BOP Identifiers */
#define BOP_RESET 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
// to let the virtual machine initialize itself
// the IVT and its hardware.
// to let the virtual machine perform the POST.
#define BOP_EQUIPLIST 0x11
#define BOP_GETMEMSIZE 0x12
@ -43,94 +44,95 @@ PBIOS_CONFIG_TABLE Bct;
/* PUBLIC FUNCTIONS ***********************************************************/
VOID WINAPI BiosEquipmentService(LPWORD Stack)
VOID WINAPI
WinNtVdmBiosReset(LPWORD Stack)
{
/* Return the equipment list */
setAX(Bda->EquipmentList);
}
DisplayMessage(L"You are loading Windows NTVDM BIOS!\n");
// Bios32Post(Stack);
VOID WINAPI BiosGetMemorySize(LPWORD Stack)
{
/* Return the conventional memory size in kB, typically 640 kB */
setAX(Bda->MemorySize);
DisplayMessage(L"ReactOS NTVDM doesn't support Windows NTVDM BIOS at the moment. The VDM will shut down.");
EmulatorTerminate();
}
BOOLEAN
BiosInitialize(IN LPCSTR BiosFileName)
BiosInitialize(IN LPCSTR BiosFileName,
IN LPCSTR RomFiles OPTIONAL)
{
BOOLEAN Success = FALSE;
BOOLEAN Success2 = FALSE;
LPCSTR RomFile;
LPSTR ptr;
ULONG RomAddress;
CHAR RomFileName[MAX_PATH + 10 + 1];
/* Disable interrupts */
setIF(0);
/* Initialize the BDA and the BCT pointers */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0x0000);
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT , 0x0000);
// The BCT is found at F000:E6F5 for 100% compatible BIOSes.
Bct = (PBIOS_CONFIG_TABLE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5);
/**** HACK! HACK! for Windows NTVDM BIOS ****/
// WinNtVdmBiosSupportInitialize();
/* Register the BIOS support BOPs */
RegisterBop(BOP_RESET, WinNtVdmBiosReset); // Needed for Windows NTVDM (SoftPC) BIOS.
RegisterBop(BOP_EQUIPLIST , BiosEquipmentService); // Needed by Windows NTVDM (SoftPC) BIOS
RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize); // and also NTDOS!!
// /* Register the BIOS support BOPs */
// RegisterBop(BOP_EQUIPLIST , BiosEquipmentService);
// RegisterBop(BOP_GETMEMSIZE, BiosGetMemorySize);
if (BiosFileName && BiosFileName[0] != '\0')
if (BiosFileName == NULL)
{
PVOID BiosLocation = NULL;
DWORD BiosSize = 0;
Success = LoadBios(BiosFileName, &BiosLocation, &BiosSize);
DPRINT1("BIOS loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
if (!Success) return FALSE;
DisplayMessage(L"First bytes at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n"
L"3 last bytes at 0x%p: 0x%02x 0x%02x 0x%02x",
BiosLocation,
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 0),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 1),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 3),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 4),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 5),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 6),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 7),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 8),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + 9),
(PVOID)((ULONG_PTR)BiosLocation + BiosSize - 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 2),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 1),
*(PCHAR)((ULONG_PTR)REAL_TO_PHYS(BiosLocation) + BiosSize - 0));
DisplayMessage(L"POST at 0x%p: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
TO_LINEAR(getCS(), getIP()),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 0),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 1),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 2),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 3),
*(PCHAR)((ULONG_PTR)SEG_OFF_TO_PTR(getCS(), getIP()) + 4));
/* Boot it up */
/*
* The CPU is already in reset-mode so that
* CS:IP points to F000:FFF0 as required.
*/
DisplayMessage(L"CS=0x%p ; IP=0x%p", getCS(), getIP());
// setCS(0xF000);
// setIP(0xFFF0);
Success = TRUE;
}
else
{
WriteProtectRom((PVOID)ROM_AREA_START,
ROM_AREA_END - ROM_AREA_START + 1);
Success = Bios32Loaded = Bios32Initialize();
}
else if (BiosFileName[0] != '\0')
{
PVOID BiosLocation = NULL;
Success = LoadBios(BiosFileName, &BiosLocation, NULL);
DPRINT1("BIOS file '%s' loading %s at address 0x%08x; GetLastError() = %u\n",
BiosFileName, Success ? "succeeded" : "failed", BiosLocation, GetLastError());
}
else // if (BiosFileName[0] == '\0')
{
/* Do nothing */
Success = TRUE;
}
/* Bail out now if we failed to load any BIOS file */
if (!Success) return FALSE;
/* Load optional ROMs */
if (RomFiles)
{
RomFile = RomFiles;
while (*RomFile)
{
strncpy(RomFileName, RomFile, ARRAYSIZE(RomFileName));
RomFileName[ARRAYSIZE(RomFileName)-1] = '\0';
ptr = strchr(RomFileName, '|'); // Since '|' is forbidden as a valid file name, we use it as a separator for the ROM address.
if (!ptr) goto Skip;
*ptr++ = '\0';
RomAddress = strtoul(ptr, NULL, 0); // ROM segment
RomAddress <<= 4; // Convert to real address
if (RomAddress == 0) goto Skip;
Success2 = LoadRom(RomFileName, (PVOID)RomAddress, NULL);
DPRINT1("ROM file '%s' loading %s at address 0x%08x; GetLastError() = %u\n",
RomFileName, Success2 ? "succeeded" : "failed", RomAddress, GetLastError());
Skip:
RomFile += strlen(RomFile) + 1;
}
}
/*
* Boot it up.
* The CPU is already in reset-mode so that
* CS:IP points to F000:FFF0 as required.
*/
// DisplayMessage(L"CS:IP=%04X:%04X", getCS(), getIP());
// setCS(0xF000);
// setIP(0xFFF0);
// /* Enable interrupts */
// setIF(1);

View file

@ -18,8 +18,7 @@
/* BOP Identifiers */
#define BOP_RESET 0x00 // Windows NTVDM (SoftPC) BIOS calls BOP 0x00
// to let the virtual machine initialize itself
// the IVT and its hardware.
// to let the virtual machine perform the POST.
#define BOP_EQUIPLIST 0x11
#define BOP_GETMEMSIZE 0x12
@ -29,10 +28,6 @@
#define BDA_SEGMENT 0x40
#define BIOS_SEGMENT 0xF000
// HACK: Disable FPU for now because it is not fully ready yet for being used
// by all applications (e.g. QBasic runtime would use the native FPU if the bit
// is set, but then subsequently fails, unless the FPU bit is unset in that case
// QBasic uses its emulated FPU).
#define BIOS_EQUIPMENT_LIST 0x2E // Bit1: FPU, Bit 2: Mouse
#pragma pack(push, 1)
@ -104,7 +99,8 @@ typedef struct
BYTE Reserved5[2]; // 0x90
BYTE Reserved6[2]; // 0x92
BYTE Reserved7[2]; // 0x94
WORD KeybdStatusFlags; // 0x96
BYTE KeybdStatusFlags; // 0x96
BYTE KeybdLedFlags; // 0x97
DWORD Reserved9; // 0x98
DWORD Reserved10; // 0x9c
DWORD Reserved11[2]; // 0xa0
@ -165,7 +161,8 @@ VOID WINAPI BiosEquipmentService(LPWORD Stack);
VOID WINAPI BiosGetMemorySize(LPWORD Stack);
BOOLEAN
BiosInitialize(IN LPCSTR BiosFileName);
BiosInitialize(IN LPCSTR BiosFileName,
IN LPCSTR RomFiles OPTIONAL);
VOID
BiosCleanup(VOID);

View file

@ -10,8 +10,9 @@
#define NDEBUG
/* For BIOS Version number */
/* BIOS Version number and Copyright */
#include <reactos/buildno.h>
#include <reactos/version.h>
#include "ntvdm.h"
#include "emulator.h"
@ -106,19 +107,39 @@ $fffe ; System Model ID
#define BIOS_REVISION 0x00
// FIXME: Find a nice PS/2 486 + 487 BIOS combination!
static const BIOS_CONFIG_TABLE BiosConfigTable =
{
sizeof(BIOS_CONFIG_TABLE), // Length
BIOS_MODEL, // BIOS Model
BIOS_SUBMODEL, // BIOS Sub-Model
BIOS_REVISION, // BIOS Revision
// Feature bytes
{
0x78, // At the moment we don't have any Extended BIOS Area; see http://www.ctyme.com/intr/rb-1594.htm#Table510
0x00, // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
0x10, // Bit 4: POST supports ROM-to-RAM enable/disable
0x00,
0x00
}
};
/*
* WARNING! For compatibility purposes the string "IBM" should be at F000:E00E .
* Some programs alternatively look at "COPR. IBM" that is at F000:E008 .
* Some programs otherwise look for "COPR. IBM" at F000:E008 .
*/
static const CHAR BiosCopyright[] = "0000000 NTVDM IBM Compatible 486 32-bit BIOS Copyright (C) ReactOS Team 1996-2014";
static const CHAR BiosVersion[] = "ReactOS NTVDM 32-bit BIOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")";
static const CHAR BiosCopyright[] = "0000000 NTVDM IBM COMPATIBLE 486 BIOS COPYRIGHT (C) ReactOS Team 1996-"COPYRIGHT_YEAR;
static const CHAR BiosVersion[] = "ReactOS NTVDM 32-bit BIOS Version "KERNEL_VERSION_STR"\0"
"BIOS32 Version "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")";
static const CHAR BiosDate[] = "06/17/13";
C_ASSERT(sizeof(BiosCopyright)-1 <= 0x5B); // Ensures that we won't overflow on the POST Code starting at F000:E05B
C_ASSERT(sizeof(BiosDate)-1 == 0x08);
/* 16-bit bootstrap code at F000:FFF0 */
static BYTE Bootstrap[] =
static const BYTE Bootstrap[] =
{
0xEA, // jmp far ptr
0x5B, 0xE0, 0x00, 0xF0, // F000:E05B
@ -128,7 +149,7 @@ static BYTE Bootstrap[] =
* POST code at F000:E05B. All the POST is done in 32 bit
* and only at the end it calls the bootstrap interrupt.
*/
static BYTE PostCode[] =
static const BYTE PostCode[] =
{
LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), BOP_RESET, // Call BIOS POST
0xCD, BIOS_BOOTSTRAP_LOADER, // INT 0x19
@ -145,6 +166,18 @@ static VOID WINAPI BiosException(LPWORD Stack)
EmulatorException(ExceptionNumber, Stack);
}
VOID WINAPI BiosEquipmentService(LPWORD Stack)
{
/* Return the equipment list */
setAX(Bda->EquipmentList);
}
VOID WINAPI BiosGetMemorySize(LPWORD Stack)
{
/* Return the conventional memory size in kB, typically 640 kB */
setAX(Bda->MemorySize);
}
static VOID WINAPI BiosMiscService(LPWORD Stack)
{
switch (getAH())
@ -162,7 +195,7 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
break;
}
/* Wait On External Event */
/* Wait on External Event */
case 0x41:
{
BYTE Value;
@ -242,7 +275,6 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
/* Repeat the BOP if we shouldn't return */
setCF(!Return);
break;
}
@ -272,7 +304,6 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
@ -325,7 +356,6 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
@ -335,7 +365,7 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
DPRINT1("BIOS INT 15h, AH=89h \"Switch to Protected Mode\" is UNIMPLEMENTED");
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
goto Default;
}
/* Get Configuration */
@ -349,28 +379,44 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
/* Call successful; clear CF */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
/* Return Extended-Bios Data-Area Segment Address (PS) */
case 0xC1:
{
// Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
// setES(???);
UNIMPLEMENTED;
/* We do not support EBDA yet */
UNIMPLEMENTED;
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
break;
goto Default;
}
/* Pointing Device BIOS Interface (PS) */
case 0xC2:
{
BiosMousePs2Interface(Stack);
UNIMPLEMENTED; // Remove it when BiosMousePs2Interface is implemented!
goto Default;
}
/* Get CPU Type and Mask Revision */
case 0xC9:
{
/*
* We can see this function as a CPUID replacement.
* See Ralf Brown: http://www.ctyme.com/intr/rb-1613.htm
* for more information.
*/
/*
* Fast486 is a 486DX with FPU included,
* but old enough to not support CPUID.
*/
setCX(0x0400);
/* Call successful; clear CF */
setAH(0x00);
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
@ -437,10 +483,19 @@ static VOID WINAPI BiosMiscService(LPWORD Stack)
break;
}
default:
default: Default:
{
DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
getAH());
/*
* The original signification of the error code 0x86 is that
* no PC Cassette is present. The CF is also set in this case.
* To keep backward compatibility, newer BIOSes use this value
* to indicate an unimplemented call in INT 15h.
*/
setAH(0x86);
Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
}
}
}
@ -490,6 +545,7 @@ static VOID WINAPI BiosTimeService(LPWORD Stack)
{
switch (getAH())
{
/* Get System Time */
case 0x00:
{
/* Set AL to 1 if midnight had passed, 0 otherwise */
@ -505,6 +561,7 @@ static VOID WINAPI BiosTimeService(LPWORD Stack)
break;
}
/* Set System Time */
case 0x01:
{
/* Set the tick count to CX:DX */
@ -516,6 +573,62 @@ static VOID WINAPI BiosTimeService(LPWORD Stack)
break;
}
/* Get Real-Time Clock Time */
case 0x02:
{
UCHAR StatusB;
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_HOURS);
setCH(IOReadB(CMOS_DATA_PORT));
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_MINUTES);
setCL(IOReadB(CMOS_DATA_PORT));
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_SECONDS);
setDH(IOReadB(CMOS_DATA_PORT));
/* Daylight Savings Time */
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_STATUS_B);
StatusB = IOReadB(CMOS_DATA_PORT);
setDL(StatusB & 0x01);
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
// /* Set Real-Time Clock Time */
// case 0x03:
// {
// break;
// }
/* Get Real-Time Clock Date */
case 0x04:
{
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_CENTURY);
setCH(IOReadB(CMOS_DATA_PORT));
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_YEAR);
setCL(IOReadB(CMOS_DATA_PORT));
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_MONTH);
setDH(IOReadB(CMOS_DATA_PORT));
IOWriteB(CMOS_ADDRESS_PORT, CMOS_REG_DAY);
setDL(IOReadB(CMOS_DATA_PORT));
/* Clear CF */
Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
break;
}
// /* Set Real-Time Clock Date */
// case 0x05:
// {
// break;
// }
default:
{
DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n",
@ -675,7 +788,7 @@ static VOID InitializeBiosInt32(VOID)
/* Zero out all of the IVT (0x00 -- 0xFF) */
RtlZeroMemory(BaseAddress, 0x0100 * sizeof(ULONG));
#ifdef ADVANCED_DEBUGGING
#if defined(ADVANCED_DEBUGGING) && (ADVANCED_DEBUGGING_LEVEL >= 3)
// Initialize all the interrupt vectors to the default one.
for (i = 0x00; i <= 0xFF; i++)
RegisterBiosInt32(i, NULL);
@ -756,36 +869,21 @@ static VOID InitializeBiosData(VOID)
Bda->MemorySize = MAKEWORD(Low, High);
}
static VOID InitializeBiosInfo(VOID)
{
RtlZeroMemory(Bct, sizeof(*Bct));
Bct->Length = sizeof(*Bct);
Bct->Model = BIOS_MODEL;
Bct->SubModel = BIOS_SUBMODEL;
Bct->Revision = BIOS_REVISION;
Bct->Feature[0] = 0x70; // At the moment we don't support "wait for external event (INT 15/AH=41h)", we also don't have any "extended BIOS area allocated (usually at top of RAM)"; see http://www.ctyme.com/intr/rb-1594.htm#Table510
Bct->Feature[1] = 0x00; // We don't support anything from here; see http://www.ctyme.com/intr/rb-1594.htm#Table511
Bct->Feature[2] = 0x00;
Bct->Feature[3] = 0x00;
Bct->Feature[4] = 0x00;
}
/*
* The BIOS POST (Power On-Self Test)
*/
static VOID
/*static*/ VOID
WINAPI
Bios32Post(LPWORD Stack)
{
static BOOLEAN FirstBoot = TRUE;
#if 0
BOOLEAN Success;
#endif
BYTE ShutdownStatus;
/*
* Initialize BIOS/Keyboard/Video RAM dynamic data
*/
DPRINT("Bios32Post\n");
/* Disable interrupts */
@ -879,7 +977,6 @@ Bios32Post(LPWORD Stack)
* - if the word is 0000h, perform a cold reboot (aka. Reset). Everything gets initialized.
* - if the word is 1234h, perform a warm reboot (aka. Ctrl-Alt-Del). Some stuff is skipped.
*/
switch (Bda->SoftReset)
{
case 0x0000:
@ -906,17 +1003,22 @@ Bios32Post(LPWORD Stack)
FirstBoot = FALSE;
/* Initialize the BDA and the BIOS ROM Information */
/* Initialize the BDA */
InitializeBiosData();
InitializeBiosInfo();
/* Initialize the User Data Area at 0050:XXXX */
RtlZeroMemory(SEG_OFF_TO_PTR(0x50, 0x0000), sizeof(USER_DATA_AREA));
//////// NOTE: This is more or less bios-specific ////////
/*
* Initialize IVT and hardware
*/
// WriteUnProtectRom(...);
/* Register the BIOS 32-bit Interrupts */
InitializeBiosInt32();
@ -924,30 +1026,15 @@ Bios32Post(LPWORD Stack)
BiosHwSetup();
/* Initialize the Keyboard, Video and Mouse BIOS */
if (!KbdBios32Initialize() || !VidBios32Initialize() || !MouseBios32Initialize())
{
/* Stop the VDM */
EmulatorTerminate();
return;
}
KbdBios32Post();
VidBiosPost();
MouseBios32Post();
#if 0
/* Initialize the Keyboard and Video BIOS */
if (!KbdBiosInitialize() || !VidBiosInitialize())
{
/* Stop the VDM */
EmulatorTerminate();
return;
}
#endif
// WriteProtectRom(...);
//////// End of more or less bios-specific section ///////
///////////// MUST BE DONE AFTER IVT INITIALIZATION !! /////////////////////
#if 0
/* Load some ROMs */
Success = LoadRom("boot.bin", (PVOID)0xE0000, NULL);
DPRINT1("Test ROM loading %s ; GetLastError() = %u\n", Success ? "succeeded" : "failed", GetLastError());
#endif
SearchAndInitRoms(&BiosContext);
@ -968,29 +1055,42 @@ Quit:
BOOLEAN Bios32Initialize(VOID)
{
/*
* Initialize BIOS32 static data
* Initialize BIOS/Keyboard/Video ROM static data
*/
/* Bootstrap code */
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE05B), PostCode , sizeof(PostCode ));
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF0), Bootstrap, sizeof(Bootstrap));
/* System BIOS Copyright */
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE000), BiosCopyright, sizeof(BiosCopyright)-1);
/* System BIOS Version */
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xE080), BiosVersion, sizeof(BiosVersion)-1);
// FIXME: or E061, or E100 ??
RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE070), BiosVersion, sizeof(BiosVersion)-1);
/* System BIOS Date */
RtlCopyMemory(SEG_OFF_TO_PTR(0xF000, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xFFF5), BiosDate, sizeof(BiosDate)-1);
/* Bootstrap code */
RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE05B), PostCode , sizeof(PostCode ));
RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xFFF0), Bootstrap, sizeof(Bootstrap));
/* BIOS ROM Information */
RtlCopyMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xE6F5), &BiosConfigTable, sizeof(BiosConfigTable));
/* System BIOS Model (same as Bct->Model) */
*(PBYTE)(SEG_OFF_TO_PTR(0xF000, 0xFFFE)) = BIOS_MODEL;
*(PBYTE)(SEG_OFF_TO_PTR(BIOS_SEGMENT, 0xFFFE)) = BIOS_MODEL;
/* Initialize the Keyboard and Video BIOS */
if (!KbdBiosInitialize() || !VidBiosInitialize() || !MouseBiosInitialize())
{
/* Stop the VDM */
EmulatorTerminate();
return FALSE;
}
/* Redefine our POST function */
RegisterBop(BOP_RESET, Bios32Post);
WriteProtectRom((PVOID)TO_LINEAR(BIOS_SEGMENT, 0x0000),
ROM_AREA_END - TO_LINEAR(BIOS_SEGMENT, 0x0000) + 1);
/* We are done */
return TRUE;
}
@ -999,7 +1099,7 @@ VOID Bios32Cleanup(VOID)
{
MouseBios32Cleanup();
VidBios32Cleanup();
KbdBios32Cleanup();
KbdBiosCleanup();
}
/* EOF */

View file

@ -80,7 +80,8 @@ static BOOLEAN BiosKbdBufferPop(VOID)
return TRUE;
}
static VOID WINAPI BiosKeyboardService(LPWORD Stack)
/* static */
VOID WINAPI BiosKeyboardService(LPWORD Stack)
{
switch (getAH())
{
@ -168,11 +169,16 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
case 0x12:
{
/*
* Be careful! The returned word is similar to Bda->KeybdShiftFlags
* Be careful! The returned word is similar to 'Bda->KeybdShiftFlags'
* but the high byte is organized differently:
* the bytes 2 and 3 of the high byte are not the same...
* the bits 2 and 3 of the high byte are not the same:
* instead they correspond to the right CTRL and ALT keys as specified
* in bits 2 and 3 of LOBYTE(Bda->KeybdStatusFlags).
*/
WORD KeybdShiftFlags = (Bda->KeybdShiftFlags & 0xF3FF);
// Bda->KeybdShiftFlags & 0xF3FF;
WORD KeybdShiftFlags = MAKEWORD(LOBYTE(Bda->KeybdShiftFlags),
(HIBYTE(Bda->KeybdShiftFlags ) & 0xF3) |
(LOBYTE(Bda->KeybdStatusFlags) & 0x0C));
/* Return the extended keyboard shift status word */
setAX(KeybdShiftFlags);
@ -188,7 +194,8 @@ static VOID WINAPI BiosKeyboardService(LPWORD Stack)
}
// Keyboard IRQ 1
static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
/* static */
VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
{
static BOOLEAN Extended = FALSE;
BOOLEAN SkipScanCode;
@ -222,9 +229,14 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
if (ScanCode == 0xE0)
{
Extended = TRUE;
Bda->KeybdStatusFlags |= 0x02;
goto Quit;
}
// FIXME: For diagnostic purposes. We should decide what to do then!!
if (ScanCode == 0xE1)
DPRINT1("BiosKeyboardIrq, ScanCode == 0xE1\n");
/* Check whether CF is clear. If so, skip the scan code. */
if (SkipScanCode) goto Quit;
@ -249,10 +261,12 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
break;
}
case VK_CONTROL:
case VK_SHIFT:
case VK_LSHIFT:
case VK_RSHIFT:
case VK_CONTROL:
case VK_RCONTROL:
case VK_LCONTROL:
case VK_MENU:
case VK_LMENU:
case VK_RMENU:
@ -288,19 +302,27 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
/* Clear the keyboard flags */
Bda->KeybdShiftFlags = 0;
// Release right CTRL and ALT keys
Bda->KeybdStatusFlags &= ~(BDA_KBDFLAG_RCTRL | BDA_KBDFLAG_RALT);
/* Set the appropriate flags based on the state */
if (BiosKeyboardMap[VK_SHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
// SHIFT
if (BiosKeyboardMap[VK_RSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RSHIFT;
if (BiosKeyboardMap[VK_LSHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
if (BiosKeyboardMap[VK_SHIFT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LSHIFT;
// CTRL
if (BiosKeyboardMap[VK_RCONTROL] & (1 << 7)) Bda->KeybdStatusFlags |= BDA_KBDFLAG_RCTRL;
if (BiosKeyboardMap[VK_LCONTROL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LCTRL;
if (BiosKeyboardMap[VK_CONTROL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CTRL;
// ALT
if (BiosKeyboardMap[VK_RMENU] & (1 << 7)) Bda->KeybdStatusFlags |= BDA_KBDFLAG_RALT;
if (BiosKeyboardMap[VK_LMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
if (BiosKeyboardMap[VK_MENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_ALT;
// Others
if (BiosKeyboardMap[VK_SCROLL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL_ON;
if (BiosKeyboardMap[VK_NUMLOCK] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_NUMLOCK_ON;
if (BiosKeyboardMap[VK_CAPITAL] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_CAPSLOCK_ON;
if (BiosKeyboardMap[VK_INSERT] & (1 << 0)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_INSERT_ON;
if (BiosKeyboardMap[VK_RMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_RALT;
if (BiosKeyboardMap[VK_LMENU] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_LALT;
if (BiosKeyboardMap[VK_SNAPSHOT] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SYSRQ;
if (BiosKeyboardMap[VK_PAUSE] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_PAUSE;
if (BiosKeyboardMap[VK_SCROLL] & (1 << 7)) Bda->KeybdShiftFlags |= BDA_KBDFLAG_SCROLL;
@ -310,6 +332,8 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack)
/* Clear the extended key flag */
Extended = FALSE;
Bda->KeybdStatusFlags &= ~0x02; // Remove the 0xE0 code flag
// Bda->KeybdStatusFlags &= ~0x01; // Remove the 0xE1 code flag
DPRINT("BiosKeyboardIrq - Character = 0x%X, ScanCode = 0x%X, KeybdShiftFlags = 0x%X\n",
Character, ScanCode, Bda->KeybdShiftFlags);
@ -320,11 +344,8 @@ Quit:
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN KbdBios32Initialize(VOID)
VOID KbdBios32Post(VOID)
{
/* Initialize the common Keyboard BIOS Support Library */
if (!KbdBiosInitialize()) return FALSE;
/* Initialize the BDA */
Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
@ -334,6 +355,10 @@ BOOLEAN KbdBios32Initialize(VOID)
RtlFillMemory(((LPVOID)((ULONG_PTR)Bda + Bda->KeybdBufferStart)),
BIOS_KBD_BUFFER_SIZE * sizeof(WORD), 'A');
Bda->KeybdShiftFlags = 0;
Bda->KeybdStatusFlags = (1 << 4); // 101/102 enhanced keyboard installed
Bda->KeybdLedFlags = 0;
/*
* Register the BIOS 32-bit Interrupts:
* - Software vector handler
@ -341,14 +366,6 @@ BOOLEAN KbdBios32Initialize(VOID)
*/
RegisterBiosInt32(BIOS_KBD_INTERRUPT, BiosKeyboardService);
EnableHwIRQ(1, BiosKeyboardIrq);
return TRUE;
}
VOID KbdBios32Cleanup(VOID)
{
/* Cleanup the common Keyboard BIOS Support Library */
KbdBiosCleanup();
}
/* EOF */

View file

@ -18,12 +18,14 @@
#define BDA_KBDFLAG_RSHIFT (1 << 0)
#define BDA_KBDFLAG_LSHIFT (1 << 1)
#define BDA_KBDFLAG_CTRL (1 << 2)
#define BDA_KBDFLAG_RCTRL (1 << 2) // Used for KeybdStatusFlags
#define BDA_KBDFLAG_ALT (1 << 3)
#define BDA_KBDFLAG_RALT (1 << 3) // Used for KeybdStatusFlags
#define BDA_KBDFLAG_SCROLL_ON (1 << 4)
#define BDA_KBDFLAG_NUMLOCK_ON (1 << 5)
#define BDA_KBDFLAG_CAPSLOCK_ON (1 << 6)
#define BDA_KBDFLAG_INSERT_ON (1 << 7)
#define BDA_KBDFLAG_RALT (1 << 8)
#define BDA_KBDFLAG_LCTRL (1 << 8)
#define BDA_KBDFLAG_LALT (1 << 9)
#define BDA_KBDFLAG_SYSRQ (1 << 10)
#define BDA_KBDFLAG_PAUSE (1 << 11)
@ -34,8 +36,7 @@
/* FUNCTIONS ******************************************************************/
BOOLEAN KbdBios32Initialize(VOID);
VOID KbdBios32Cleanup(VOID);
VOID KbdBios32Post(VOID);
#endif /* _KBDBIOS32_H_ */

View file

@ -105,7 +105,7 @@ VOID BiosMousePs2Interface(LPWORD Stack)
/* PUBLIC FUNCTIONS ***********************************************************/
BOOLEAN MouseBios32Initialize(VOID)
VOID MouseBios32Post(VOID)
{
BYTE ControllerConfig;
@ -127,7 +127,10 @@ BOOLEAN MouseBios32Initialize(VOID)
/* Set up the HW vector interrupts */
EnableHwIRQ(12, BiosMouseIrq);
}
BOOLEAN MouseBiosInitialize(VOID)
{
return TRUE;
}

View file

@ -15,7 +15,8 @@
VOID BiosMousePs2Interface(LPWORD Stack);
BOOLEAN MouseBios32Initialize(VOID);
VOID MouseBios32Post(VOID);
BOOLEAN MouseBiosInitialize(VOID);
VOID MouseBios32Cleanup(VOID);
#endif /* _MOUBIOS32_H_ */

View file

@ -13,33 +13,59 @@
#define NDEBUG
#include "ntvdm.h"
#include "emulator.h"
#include "cpu/bop.h"
#include "int32.h"
#include "vidbios32.h"
#include <bios/vidbios.h>
#include "bios32p.h"
/* DEFINES ********************************************************************/
/* BOP Identifiers */
#define BOP_VIDEO_INT 0x10
/* PUBLIC FUNCTIONS ***********************************************************/
extern VOID WINAPI VidBiosVideoService(LPWORD Stack);
static VOID WINAPI VidBiosINT(LPWORD Stack)
{
/*
* Set up a false stack to hardwire the BOP function (that can directly
* manipulate CPU registers) to the 32-bit interrupt function (which uses
* the stack to be able to modify the original CS:IP and FLAGS).
*
* See int32.h stack codes.
*/
WORD EmuStack[4];
DWORD Flags = getEFLAGS();
DPRINT1("Calling BOP VidBiosINT\n");
EmuStack[STACK_FLAGS] = LOWORD(Flags);
EmuStack[STACK_CS] = getCS();
EmuStack[STACK_IP] = getIP();
EmuStack[STACK_INT_NUM] = BOP_VIDEO_INT;
VidBiosVideoService(EmuStack);
setIP(EmuStack[STACK_IP]);
setCS(EmuStack[STACK_CS]);
setEFLAGS(MAKELONG(EmuStack[STACK_FLAGS], HIWORD(Flags)));
}
BOOLEAN VidBios32Initialize(VOID)
{
/* Initialize the common Video BIOS Support Library */
if (!VidBiosInitialize()) return FALSE;
/* Register the BIOS 32-bit Interrupts */
RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
/* Vectors that should be implemented */
RegisterBiosInt32(0x42, NULL); // Relocated Default INT 10h Video Services
RegisterBiosInt32(0x6D, NULL); // Video BIOS Entry Point
/* Register the BIOS support BOPs */
RegisterBop(BOP_VIDEO_INT, VidBiosINT);
return TRUE;
}
VOID VidBios32Cleanup(VOID)
{
/* Cleanup the common Video BIOS Support Library */
VidBiosCleanup();
/* Unregister the BIOS support BOPs */
RegisterBop(BOP_VIDEO_INT, NULL);
}
/* EOF */

View file

@ -13,6 +13,7 @@
#include "ntvdm.h"
#include "emulator.h"
#include "cpu/bop.h"
#include "int32.h"
#include "bios.h"
// #include "kbdbios.h"
@ -25,27 +26,73 @@
/* PUBLIC FUNCTIONS ***********************************************************/
extern VOID WINAPI BiosKeyboardIrq(LPWORD Stack);
static VOID WINAPI KbdBiosIRQ(LPWORD Stack)
{
DPRINT1("KbdBiosIRQ is UNIMPLEMENTED\n");
/*
* Set up a false stack to hardwire the BOP function (that can directly
* manipulate CPU registers) to the 32-bit interrupt function (which uses
* the stack to be able to modify the original CS:IP and FLAGS).
*
* See int32.h stack codes.
*/
WORD EmuStack[4];
DWORD Flags = getEFLAGS();
DPRINT1("Calling BOP KbdBiosIRQ\n");
EmuStack[STACK_FLAGS] = LOWORD(Flags);
EmuStack[STACK_CS] = getCS();
EmuStack[STACK_IP] = getIP();
EmuStack[STACK_INT_NUM] = BOP_KBD_IRQ;
BiosKeyboardIrq(EmuStack);
setIP(EmuStack[STACK_IP]);
setCS(EmuStack[STACK_CS]);
setEFLAGS(MAKELONG(EmuStack[STACK_FLAGS], HIWORD(Flags)));
}
extern VOID WINAPI BiosKeyboardService(LPWORD Stack);
static VOID WINAPI KbdBiosINT(LPWORD Stack)
{
DPRINT1("KbdBiosINT is UNIMPLEMENTED\n");
/*
* Set up a false stack to hardwire the BOP function (that can directly
* manipulate CPU registers) to the 32-bit interrupt function (which uses
* the stack to be able to modify the original CS:IP and FLAGS).
*
* See int32.h stack codes.
*/
WORD EmuStack[4];
DWORD Flags = getEFLAGS();
DPRINT1("Calling BOP KbdBiosINT\n");
EmuStack[STACK_FLAGS] = LOWORD(Flags);
EmuStack[STACK_CS] = getCS();
EmuStack[STACK_IP] = getIP();
EmuStack[STACK_INT_NUM] = BOP_KBD_IRQ;
BiosKeyboardService(EmuStack);
setIP(EmuStack[STACK_IP]);
setCS(EmuStack[STACK_CS]);
setEFLAGS(MAKELONG(EmuStack[STACK_FLAGS], HIWORD(Flags)));
}
BOOLEAN KbdBiosInitialize(VOID)
{
/* Register the BIOS support BOPs */
RegisterBop(BOP_KBD_IRQ, KbdBiosIRQ);
RegisterBop(BOP_KBD_INT, KbdBiosINT);
RegisterBop(BOP_KBD_IRQ, KbdBiosIRQ); // BiosKeyboardIrq in kbdbios32.c
RegisterBop(BOP_KBD_INT, KbdBiosINT); // BiosKeyboardService in kbdbios32.c
return TRUE;
}
VOID KbdBiosCleanup(VOID)
{
/* Unregister the BIOS support BOPs */
RegisterBop(BOP_KBD_IRQ, NULL);
RegisterBop(BOP_KBD_INT, NULL);
}
/* EOF */

View file

@ -81,22 +81,6 @@ LoadRomFileByHandle(IN HANDLE RomFileHandle,
BytesRead);
}
static UCHAR
ComputeChecksum(IN ULONG RomLocation,
IN ULONG RomSize)
{
ULONG RomLastAddress = RomLocation + RomSize;
UCHAR Sum = 0x00; // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
while (RomLocation < RomLastAddress)
{
Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation);
++RomLocation;
}
return Sum;
}
static VOID
InitRomRange(IN PCALLBACK16 Context,
IN ULONG Start,
@ -115,16 +99,16 @@ InitRomRange(IN PCALLBACK16 Context,
/* Check the control sum of the ROM */
/*
* If this is an adapter ROM (Start: C8000, End: E0000), its
* reported size is stored in byte 2 of the ROM.
* If this is an adapter ROM (Start: C8000, End: E0000),
* its reported size is stored in byte 2 of the ROM.
*
* If this is an expansion ROM (Start: E0000, End: F0000),
* its real length is 64kB.
*/
RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512;
RomSize = *(PUCHAR)REAL_TO_PHYS(Address + 2) * 512; // Size in blocks of 512 bytes
if (Address >= 0xE0000) RomSize = 0x10000;
Checksum = ComputeChecksum(Address, RomSize);
Checksum = CalcRomChecksum(Address, RomSize);
if (Checksum == 0x00)
{
EntryPoint = Address + 3;
@ -156,6 +140,29 @@ WriteProtectRom(IN PVOID RomLocation,
NULL, ShadowRomWrite);
}
BOOLEAN
WriteUnProtectRom(IN PVOID RomLocation,
IN ULONG RomSize)
{
return MemRemoveFastMemoryHook(RomLocation, RomSize);
}
UCHAR
CalcRomChecksum(IN ULONG RomLocation,
IN ULONG RomSize)
{
ULONG RomLastAddress = RomLocation + RomSize;
UCHAR Sum = 0x00; // Using a UCHAR guarantees that we wrap at 0xFF i.e. we do a sum modulo 0x100.
while (RomLocation < RomLastAddress)
{
Sum += *(PUCHAR)REAL_TO_PHYS(RomLocation);
++RomLocation;
}
return Sum;
}
BOOLEAN
LoadBios(IN PCSTR BiosFileName,
OUT PVOID* BiosLocation OPTIONAL,
@ -242,6 +249,9 @@ LoadRom(IN PCSTR RomFileName,
VOID
SearchAndInitRoms(IN PCALLBACK16 Context)
{
/* Video ROMs -- Start: C0000, End: C8000, 2kB blocks */
InitRomRange(Context, 0xC0000, 0xC8000, 0x0800);
/* Adapters ROMs -- Start: C8000, End: E0000, 2kB blocks */
InitRomRange(Context, 0xC8000, 0xE0000, 0x0800);

View file

@ -22,6 +22,14 @@ BOOLEAN
WriteProtectRom(IN PVOID RomLocation,
IN ULONG RomSize);
BOOLEAN
WriteUnProtectRom(IN PVOID RomLocation,
IN ULONG RomSize);
UCHAR
CalcRomChecksum(IN ULONG RomLocation,
IN ULONG RomSize);
BOOLEAN
LoadBios(IN PCSTR BiosFileName,
OUT PVOID* BiosLocation OPTIONAL,

View file

@ -11,6 +11,10 @@
#define NDEBUG
/* BIOS Version number and Copyright */
#include <reactos/buildno.h>
#include <reactos/version.h>
#include "ntvdm.h"
#include "emulator.h"
#include "cpu/cpu.h"
@ -18,17 +22,15 @@
#include "memory.h"
#include "bios.h"
#include "bios32/bios32p.h"
#include "rom.h"
#include "bios32/vbe.h"
// #include "vidbios.h"
#include "bios32/vidbios32.h"
#include "io.h"
#include "hardware/video/svga.h"
/* DEFINES ********************************************************************/
/* BOP Identifiers */
#define BOP_VIDEO_INT 0x10
/* MACROS *********************************************************************/
//
@ -41,6 +43,19 @@
/* PRIVATE VARIABLES **********************************************************/
/*
* WARNING! For compatibility purposes the string "IBM" should be at C000:001E.
*/
static const CHAR BiosInfo[] =
"00000000000 Emulation of IBM VGA Compatible ROM\0"
"CL-GD5434 VGA BIOS Version 1.41 \r\n"
"Copyright (C) ReactOS Team 1996-"COPYRIGHT_YEAR"\r\n"
"The original CL-GD5434 card was created by Cirrus Logic, Inc.\r\n\0"
"BIOS Date: 06/17/13\0";
C_ASSERT(sizeof(BiosInfo)-1 <= 0xFF-0x05); // Ensures that we won't overflow on the Video Code
/*
* VGA Register Configurations for BIOS Video Modes.
* The configurations were checked against SeaBIOS VGA BIOS.
@ -3862,8 +3877,12 @@ VOID VidBiosDetachFromConsole(VOID)
Attached = FALSE;
}
BOOLEAN VidBiosInitialize(VOID)
VOID VidBiosPost(VOID)
{
/*
* Initialize VGA BIOS32 RAM dynamic data
*/
/* Some vectors are in fact addresses to tables */
((PULONG)BaseAddress)[0x1D] = (ULONG)NULL; // Video Parameter Tables
// Far pointer to the 8x8 graphics font for the 8x8 characters 80h-FFh
@ -3876,6 +3895,56 @@ BOOLEAN VidBiosInitialize(VOID)
((PULONG)BaseAddress)[0x42] = (ULONG)NULL; // Relocated Default INT 10h Video Services
((PULONG)BaseAddress)[0x6D] = (ULONG)NULL; // Video BIOS Entry Point
//
// FIXME: At the moment we always set a VGA mode. In the future,
// we should set this mode **only** when:
// - an app starts to use directly the video memory
// (that should be done in emulator.c)
// - or starts to use non-stream I/O interrupts
// (that should be done here, or maybe in VGA ??)
//
Bda->CrtModeControl = 0x00;
Bda->CrtColorPaletteMask = 0x00;
Bda->VGADccIDActive = 0x08; // VGA w/ color analog active display
/* Set the default video mode */
VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
/* Synchronize our cursor position with VGA */
VidBiosSyncCursorPosition();
/* Register the BIOS 32-bit Interrupts */
RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);
/* Vectors that should be implemented */
RegisterBiosInt32(0x42, NULL); // Relocated Default INT 10h Video Services
RegisterBiosInt32(0x6D, NULL); // Video BIOS Entry Point
/* Initialize VBE */
VbeInitialized = VbeInitialize();
if (!VbeInitialized) DPRINT1("Couldn't initialize VBE!\n");
}
BOOLEAN VidBiosInitialize(VOID)
{
UCHAR Checksum;
/*
* Initialize VGA BIOS32 static data
*/
/* This is a ROM of size 'VIDEO_BIOS_ROM_SIZE' */
*(PWORD)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0000)) = 0xAA55;
*(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0002)) = VIDEO_BIOS_ROM_SIZE / 512; // Size in blocks of 512 bytes
/* Bootstrap code */
*(PWORD)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0003)) = 0x90CB; // retf, nop
// RtlCopyMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0xFFF0), Bootstrap, sizeof(Bootstrap));
/* Video BIOS Information */
RtlCopyMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0005), BiosInfo, sizeof(BiosInfo)-1);
/* Initialize the VGA static function table */
VgaStaticFuncTable = SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_STATE_INFO_OFFSET);
RtlZeroMemory(VgaStaticFuncTable, sizeof(*VgaStaticFuncTable));
@ -3896,31 +3965,15 @@ BOOLEAN VidBiosInitialize(VOID)
RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x14_OFFSET),
Font8x14, sizeof(Font8x14));
//
// FIXME: At the moment we always set a VGA mode. In the future,
// we should set this mode **only** when:
// - an app starts to use directly the video memory
// (that should be done in emulator.c)
// - or starts to use non-stream I/O interrupts
// (that should be done here, or maybe in VGA ??)
//
VidBios32Initialize();
Bda->CrtModeControl = 0x00;
Bda->CrtColorPaletteMask = 0x00;
Bda->VGADccIDActive = 0x08; // VGA w/ color analog active display
/* Compute the ROM checksum and store it */
*(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_BIOS_ROM_SIZE - 1)) = 0x00;
Checksum = CalcRomChecksum(TO_LINEAR(VIDEO_BIOS_DATA_SEG, 0x0000), VIDEO_BIOS_ROM_SIZE);
*(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_BIOS_ROM_SIZE - 1)) = (0xFF - Checksum + 1) & 0xFF;
/* Set the default video mode */
VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);
/* Synchronize our cursor position with VGA */
VidBiosSyncCursorPosition();
/* Register the BIOS support BOPs */
RegisterBop(BOP_VIDEO_INT, VidBiosVideoService);
/* Initialize VBE */
VbeInitialized = VbeInitialize();
if (!VbeInitialized) DPRINT1("Couldn't initialize VBE!\n");
WriteProtectRom((PVOID)TO_LINEAR(VIDEO_BIOS_DATA_SEG, 0x0000),
VIDEO_BIOS_ROM_SIZE);
return TRUE;
}

View file

@ -26,12 +26,14 @@
#define CGA_ODD_VIDEO_SEG 0xBA00
#define VIDEO_BIOS_DATA_SEG 0xC000
#define FONT_8x8_OFFSET 0x0000
#define FONT_8x8_HIGH_OFFSET 0x0400
#define FONT_8x16_OFFSET 0x0800
#define FONT_8x14_OFFSET 0x1800
#define FONT_8x8_OFFSET 0x0100
#define FONT_8x8_HIGH_OFFSET 0x0500
#define FONT_8x16_OFFSET 0x0900
#define FONT_8x14_OFFSET 0x1900
#define VIDEO_STATE_INFO_OFFSET 0x3000 // == 0x1800 + (sizeof(Font8x14) == 0x0E00) + 0x0A00 for padding
#define VIDEO_STATE_INFO_OFFSET 0x3000 // == 0x1900 + (sizeof(Font8x14) == 0x0E00) + 0x0900 for padding
#define VIDEO_BIOS_ROM_SIZE 0x4000
typedef enum
{
@ -109,6 +111,7 @@ VOID WINAPI VidBiosVideoService(LPWORD Stack);
VOID VidBiosDetachFromConsole(VOID);
VOID VidBiosAttachToConsole(VOID);
VOID VidBiosPost(VOID);
BOOLEAN VidBiosInitialize(VOID);
VOID VidBiosCleanup(VOID);

View file

@ -222,6 +222,12 @@ static BYTE CmosReadData(VOID)
break;
}
case CMOS_REG_CENTURY:
{
Value = READ_CMOS_DATA(CmosMemory, CurrentTime.wYear / 100 + 19);
break;
}
case CMOS_REG_STATUS_C:
{
/* Return the old value */
@ -363,6 +369,12 @@ static VOID CmosWriteData(BYTE Value)
break;
}
case CMOS_REG_CENTURY:
{
UNIMPLEMENTED;
break;
}
case CMOS_REG_STATUS_A:
{
CmosMemory.StatusRegA = Value & 0x7F; // Bit 7 is read-only

View file

@ -18,22 +18,24 @@
#define CMOS_BATTERY_OK 0x80
/* Status Register B flags */
#define CMOS_STB_DST (1 << 0)
#define CMOS_STB_24HOUR (1 << 1)
#define CMOS_STB_BINARY (1 << 2)
#define CMOS_STB_SQUARE_WAVE (1 << 3)
#define CMOS_STB_INT_ON_UPDATE (1 << 4)
#define CMOS_STB_INT_ON_ALARM (1 << 5)
#define CMOS_STB_INT_PERIODIC (1 << 6)
#define CMOS_STB_UPDATE_CYCLE (1 << 7)
/* Status Register C flags */
#define CMOS_STC_UF CMOS_STB_INT_ON_UPDATE
#define CMOS_STC_AF CMOS_STB_INT_ON_ALARM
#define CMOS_STC_PF CMOS_STB_INT_PERIODIC
#define CMOS_STC_UF (1 << 4)
#define CMOS_STC_AF (1 << 5)
#define CMOS_STC_PF (1 << 6)
#define CMOS_STC_IRQF (1 << 7)
/* Default register values */
#define CMOS_DEFAULT_STA 0x26
#define CMOS_DEFAULT_STB CMOS_STB_24HOUR
#define CMOS_DEFAULT_STA 0x26
#define CMOS_DEFAULT_STB CMOS_STB_24HOUR
#define WRITE_CMOS_DATA(Cmos, Value) \
((Cmos).StatusRegB & CMOS_STB_BINARY) ? (Value) : BCD_TO_BINARY(Value)
@ -65,6 +67,7 @@ typedef enum _CMOS_REGISTERS
CMOS_REG_EXT_MEMORY_HIGH = 0x18,
CMOS_REG_ACTUAL_EXT_MEMORY_LOW = 0x30,
CMOS_REG_ACTUAL_EXT_MEMORY_HIGH = 0x31,
CMOS_REG_CENTURY = 0x32,
CMOS_REG_MAX = 0x40
} CMOS_REGISTERS, *PCMOS_REGISTERS;
@ -107,6 +110,8 @@ typedef struct
BYTE StatusRegD; // 0x0d
BYTE Diagnostics; // 0x0e
BYTE ShutdownStatus; // 0x0f
BYTE Padding[0x22]; // 0x10
BYTE Century; // 0x32
};
BYTE Regs1[0x10]; // 0x00 - 0x0f
BYTE Regs [0x40]; // 0x00 - 0x3f

View file

@ -526,6 +526,25 @@ wmain(INT argc, WCHAR *argv[])
#endif
#ifdef ADVANCED_DEBUGGING
{
INT i = 20;
printf("Waiting for debugger (10 secs)..");
while (i--)
{
printf(".");
if (IsDebuggerPresent())
{
DbgBreakPoint();
break;
}
Sleep(500);
}
printf("Continue\n");
}
#endif
/* Load global VDM settings */
LoadGlobalSettings();
@ -549,8 +568,8 @@ wmain(INT argc, WCHAR *argv[])
goto Cleanup;
}
/* Initialize the system BIOS */
if (!BiosInitialize(NULL))
/* Initialize the system BIOS and option ROMs */
if (!BiosInitialize(NULL, NULL))
{
wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n");
goto Cleanup;

View file

@ -63,6 +63,10 @@ DWORD WINAPI SetLastConsoleEventActive(VOID);
*/
// #define ADVANCED_DEBUGGING
#ifdef ADVANCED_DEBUGGING
#define ADVANCED_DEBUGGING_LEVEL 1
#endif
/* FUNCTIONS ******************************************************************/
extern HANDLE VdmTaskEvent;