#define NDEBUG
-#include "bios.h"
#include "emulator.h"
+#include "bios.h"
+
#include "vga.h"
#include "pic.h"
#include "ps2.h"
#include "timer.h"
+#include "int32.h"
#include "registers.h"
+/* MACROS *********************************************************************/
+
+//
+// These macros are defined for ease-of-use of some VGA I/O ports
+// whose addresses depend whether we are in Monochrome or Colour mode.
+//
+#define VGA_INSTAT1_READ Bda->CrtBasePort + 6 // VGA_INSTAT1_READ_MONO or VGA_INSTAT1_READ_COLOR
+#define VGA_CRTC_INDEX Bda->CrtBasePort // VGA_CRTC_INDEX_MONO or VGA_CRTC_INDEX_COLOR
+#define VGA_CRTC_DATA Bda->CrtBasePort + 1 // VGA_CRTC_DATA_MONO or VGA_CRTC_DATA_COLOR
+
/* PRIVATE VARIABLES **********************************************************/
PBIOS_DATA_AREA Bda;
* VGA Register Configurations for BIOS Video Modes
* The configurations come from DosBox.
*/
-static BYTE VideoMode_40x25_text[] =
+static VGA_REGISTERS VideoMode_40x25_text =
{
/* Miscellaneous Register */
0x67,
/* Sequencer Registers */
- 0x00, 0x08, 0x03, 0x00, 0x07,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF,
+ {0x00, 0x08, 0x03, 0x00, 0x07},
/* CRTC Registers */
- 0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
- 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3,
- 0xFF,
+ {0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
- 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
};
-static BYTE VideoMode_80x25_text[] =
+static VGA_REGISTERS VideoMode_80x25_text =
{
/* Miscellaneous Register */
0x67,
/* Sequencer Registers */
- 0x00, 0x00, 0x03, 0x00, 0x07,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF,
+ {0x00, 0x00, 0x03, 0x00, 0x07},
/* CRTC Registers */
- 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
- 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
- 0xFF,
+ {0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
- 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
};
-static BYTE VideoMode_320x200_4color[] =
+static VGA_REGISTERS VideoMode_320x200_4color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
- 0x00, 0x09, 0x00, 0x00, 0x02,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0F, 0x0F, 0xFF,
+ {0x00, 0x09, 0x00, 0x00, 0x02},
/* CRTC Registers */
- 0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2,
- 0xFF,
+ {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0F, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
- 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00
+ {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
-static BYTE VideoMode_640x200_2color[] =
+static VGA_REGISTERS VideoMode_640x200_2color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
- 0x00, 0x09, 0x0F, 0x00, 0x02,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0xFF,
+ {0x00, 0x09, 0x0F, 0x00, 0x02},
/* CRTC Registers */
- 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xC2,
- 0xFF,
+ {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xC2,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
- 0x17, 0x17, 0x17, 0x17, 0x01, 0x00, 0x01, 0x00, 0x00
+ {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+ 0x17, 0x17, 0x17, 0x17, 0x01, 0x00, 0x01, 0x00, 0x00}
};
-static BYTE VideoMode_320x200_16color[] =
+static VGA_REGISTERS VideoMode_320x200_16color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
- 0x00, 0x09, 0x0F, 0x00, 0x02,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF,
+ {0x00, 0x09, 0x0F, 0x00, 0x02},
/* CRTC Registers */
- 0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3,
- 0xFF,
+ {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
- 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
-static BYTE VideoMode_640x200_16color[] =
+static VGA_REGISTERS VideoMode_640x200_16color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
- 0x00, 0x01, 0x0F, 0x00, 0x02,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF,
+ {0x00, 0x01, 0x0F, 0x00, 0x02},
/* CRTC Registers */
- 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3,
- 0xFF,
+ {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
- 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
-static BYTE VideoMode_640x350_16color[] =
+static VGA_REGISTERS VideoMode_640x350_16color =
{
/* Miscellaneous Register */
0xA3,
/* Sequencer Registers */
- 0x00, 0x01, 0x0F, 0x00, 0x02,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF,
+ {0x00, 0x01, 0x0F, 0x00, 0x02},
/* CRTC Registers */
- 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3,
- 0xFF,
+ {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
- 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
-static BYTE VideoMode_640x480_2color[] =
+static VGA_REGISTERS VideoMode_640x480_2color =
{
/* Miscellaneous Register */
0xE3,
/* Sequencer Registers */
- 0x00, 0x01, 0x0F, 0x00, 0x02,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF,
+ {0x00, 0x01, 0x0F, 0x00, 0x02},
/* CRTC Registers */
- 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3,
- 0xFF,
+ {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
- 0x3F, 0x3F, 0x3F, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00
+ {0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ 0x3F, 0x3F, 0x3F, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
-static BYTE VideoMode_640x480_16color[] =
+static VGA_REGISTERS VideoMode_640x480_16color =
{
/* Miscellaneous Register */
0xE3,
/* Sequencer Registers */
- 0x00, 0x01, 0x0F, 0x00, 0x02,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF,
+ {0x00, 0x01, 0x0F, 0x00, 0x02},
/* CRTC Registers */
- 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
- 0xFF,
+ {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
- 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};
-static BYTE VideoMode_320x200_256color[] =
+static VGA_REGISTERS VideoMode_320x200_256color =
{
/* Miscellaneous Register */
0x63,
/* Sequencer Registers */
- 0x00, 0x01, 0x0F, 0x00, 0x0E,
-
- /* GC Registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF,
+ {0x00, 0x01, 0x0F, 0x00, 0x0E},
/* CRTC Registers */
- 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
- 0xFF,
+ {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
+ 0xFF},
+
+ /* GC Registers */
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF},
/* AC Registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00}
};
-static LPBYTE VideoModes[] =
+/* See http://wiki.osdev.org/Drawing_In_Protected_Mode#Locating_Video_Memory */
+static PVGA_REGISTERS VideoModes[BIOS_MAX_VIDEO_MODE + 1] =
{
- VideoMode_40x25_text, /* Mode 00h */
- VideoMode_40x25_text, /* Mode 01h */
- VideoMode_80x25_text, /* Mode 02h */
- VideoMode_80x25_text, /* Mode 03h */
- VideoMode_320x200_4color, /* Mode 04h */
- VideoMode_320x200_4color, /* Mode 05h */
- VideoMode_640x200_2color, /* Mode 06h */
- NULL, /* Mode 07h */
- NULL, /* Mode 08h */
- NULL, /* Mode 09h */
- NULL, /* Mode 0Ah */
- NULL, /* Mode 0Bh */
- NULL, /* Mode 0Ch */
- VideoMode_320x200_16color, /* Mode 0Dh */
- VideoMode_640x200_16color, /* Mode 0Eh */
- NULL, /* Mode 0Fh */
- VideoMode_640x350_16color, /* Mode 10h */
- VideoMode_640x480_2color, /* Mode 11h */
- VideoMode_640x480_16color, /* Mode 12h */
- VideoMode_320x200_256color, /* Mode 13h */
+ &VideoMode_40x25_text, /* Mode 00h */ // 16 color (mono)
+ &VideoMode_40x25_text, /* Mode 01h */ // 16 color
+ &VideoMode_80x25_text, /* Mode 02h */ // 16 color (mono)
+ &VideoMode_80x25_text, /* Mode 03h */ // 16 color
+ &VideoMode_320x200_4color, /* Mode 04h */ // 4 color
+ &VideoMode_320x200_4color, /* Mode 05h */ // same (m)
+ &VideoMode_640x200_2color, /* Mode 06h */ // 640*200 2 color
+ NULL, /* Mode 07h */ // MDA monochrome text 80*25
+ NULL, /* Mode 08h */ // PCjr
+ NULL, /* Mode 09h */ // PCjr
+ NULL, /* Mode 0Ah */ // PCjr
+ NULL, /* Mode 0Bh */ // Reserved
+ NULL, /* Mode 0Ch */ // Reserved
+ &VideoMode_320x200_16color, /* Mode 0Dh */ // EGA 320*200 16 color
+ &VideoMode_640x200_16color, /* Mode 0Eh */ // EGA 640*200 16 color
+ NULL, /* Mode 0Fh */ // EGA 640*350 mono
+ &VideoMode_640x350_16color, /* Mode 10h */ // EGA 640*350 HiRes 16 color
+ &VideoMode_640x480_2color, /* Mode 11h */ // VGA 640*480 mono
+ &VideoMode_640x480_16color, /* Mode 12h */ // VGA
+ &VideoMode_320x200_256color, /* Mode 13h */ // VGA
+};
+
+// FIXME: Are they computable with the previous data ??
+// Values taken from DosBox
+static WORD VideoModePageSize[BIOS_MAX_VIDEO_MODE + 1] =
+{
+ 0x0800, 0x0800, 0x1000, 0x1000,
+ 0x4000, 0x4000, 0x4000, 0x1000,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2000, 0x4000, 0x8000,
+ 0x8000, 0xA000, 0xA000, 0x2000
};
/* PRIVATE FUNCTIONS **********************************************************/
}
}
-/* PUBLIC FUNCTIONS ***********************************************************/
-
-BYTE BiosGetVideoMode(VOID)
-{
- return Bda->VideoMode;
-}
-
-BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
+static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers)
{
INT i;
- COORD Resolution;
- LPBYTE Values = VideoModes[ModeNumber];
- DPRINT1("Switching to mode %Xh; Values = 0x%p\n", ModeNumber, Values);
+ if (Registers == NULL) return FALSE;
- if (Values == NULL) return FALSE;
+ /* Disable interrupts */
+ setIF(0);
+
+ /*
+ * Set the CRT base address according to the selected mode,
+ * monochrome or color. The following macros:
+ * VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then
+ * used to access the correct VGA I/O ports.
+ */
+ Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR
+ : VGA_CRTC_INDEX_MONO;
/* Write the misc register */
- VgaWritePort(VGA_MISC_WRITE, *(Values++));
+ VgaWritePort(VGA_MISC_WRITE, Registers->Misc);
+
+ /* Synchronous reset on */
+ VgaWritePort(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
+ VgaWritePort(VGA_SEQ_DATA , VGA_SEQ_RESET_AR);
/* Write the sequencer registers */
- for (i = 0; i < VGA_SEQ_MAX_REG; i++)
+ for (i = 1; i < VGA_SEQ_MAX_REG; i++)
{
VgaWritePort(VGA_SEQ_INDEX, i);
- VgaWritePort(VGA_SEQ_DATA, *(Values++));
+ VgaWritePort(VGA_SEQ_DATA, Registers->Sequencer[i]);
}
- /* Write the GC registers */
- for (i = 0; i < VGA_GC_MAX_REG; i++)
- {
- VgaWritePort(VGA_GC_INDEX, i);
- VgaWritePort(VGA_GC_DATA, *(Values++));
- }
+ /* Synchronous reset off */
+ VgaWritePort(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
+ VgaWritePort(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR);
+
+ /* Unlock CRTC registers 0-7 */
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
+ VgaWritePort(VGA_CRTC_DATA, VgaReadPort(VGA_CRTC_DATA) | 0x80);
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_VERT_RETRACE_END_REG);
+ VgaWritePort(VGA_CRTC_DATA, VgaReadPort(VGA_CRTC_DATA) & ~0x80);
+ // Make sure they remain unlocked
+ Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
+ Registers->CRT[VGA_CRTC_VERT_RETRACE_END_REG] &= ~0x80;
/* Write the CRTC registers */
for (i = 0; i < VGA_CRTC_MAX_REG; i++)
{
VgaWritePort(VGA_CRTC_INDEX, i);
- VgaWritePort(VGA_CRTC_DATA, *(Values++));
+ VgaWritePort(VGA_CRTC_DATA, Registers->CRT[i]);
+ }
+
+ /* Write the GC registers */
+ for (i = 0; i < VGA_GC_MAX_REG; i++)
+ {
+ VgaWritePort(VGA_GC_INDEX, i);
+ VgaWritePort(VGA_GC_DATA, Registers->Graphics[i]);
}
/* Write the AC registers */
for (i = 0; i < VGA_AC_MAX_REG; i++)
{
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
VgaWritePort(VGA_AC_INDEX, i);
- VgaWritePort(VGA_AC_WRITE, *(Values++));
+ VgaWritePort(VGA_AC_WRITE, Registers->Attribute[i]);
}
+ /* Set the PEL mask */
+ VgaWritePort(VGA_DAC_MASK, 0xFF);
+
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
+
+ /* Enable interrupts */
+ setIF(1);
+
+ return TRUE;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+BYTE BiosGetVideoMode(VOID)
+{
+ return Bda->VideoMode;
+}
+
+BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
+{
+ INT i;
+ BYTE Page;
+
+ COORD Resolution;
+ PVGA_REGISTERS VgaMode = VideoModes[ModeNumber];
+
+ DPRINT1("Switching to mode %Xh; VgaMode = 0x%p\n", ModeNumber, VgaMode);
+
+ if (!VgaSetRegisters(VgaMode)) return FALSE;
+
+ // /* Disable screen and enable palette access */
+ // VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ // VgaWritePort(VGA_AC_INDEX, 0x00);
+
+ if ((ModeNumber == 0x0D) || (ModeNumber == 0x0E) || (ModeNumber == 0x10))
+ {
+ /* EGA modes */
+ extern CONST COLORREF EgaPalette[VGA_MAX_COLORS / 4];
+ for (i = 0; i < sizeof(EgaPalette)/sizeof(EgaPalette[0]); i++)
+ {
+ VgaWritePort(VGA_DAC_WRITE_INDEX, i);
+ VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetRValue(EgaPalette[i])));
+ VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetGValue(EgaPalette[i])));
+ VgaWritePort(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetBValue(EgaPalette[i])));
+ }
+ }
+ else
+ {
+ /* Reset the palette */
+ VgaResetPalette();
+ }
+
+ // /* Enable screen and disable palette access */
+ // VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ // VgaWritePort(VGA_AC_INDEX, 0x20);
+
+ // Bda->CrtModeControl;
+ // Bda->CrtColorPaletteMask;
+ // Bda->EGAFlags;
+ // Bda->VGAFlags;
+
/* Update the values in the BDA */
- Bda->VideoMode = ModeNumber;
- Bda->VideoPage = 0;
- Bda->VideoPageSize = BIOS_PAGE_SIZE;
- Bda->VideoPageOffset = 0;
+ Bda->VideoMode = ModeNumber;
+ Bda->VideoPageSize = VideoModePageSize[ModeNumber];
+ Bda->VideoPage = 0;
+ Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
+
+ /* Set the start address in the CRTC */
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
+ VgaWritePort(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
+ VgaWritePort(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
/* Get the character height */
VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_MAX_SCAN_LINE_REG);
Resolution = VgaGetDisplayResolution();
Bda->ScreenColumns = Resolution.X;
- Bda->ScreenRows = Resolution.Y - 1;
+ Bda->ScreenRows = Resolution.Y - 1;
+
+ /* Set cursor position for each page */
+ for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
+ BiosSetCursorPosition(0, 0, Page);
return TRUE;
}
BOOLEAN BiosSetVideoPage(BYTE PageNumber)
{
+ BYTE Row, Column;
+
/* Check if the page exists */
if (PageNumber >= BIOS_MAX_PAGES) return FALSE;
/* Check if this is the same page */
if (PageNumber == Bda->VideoPage) return TRUE;
- /* Set the values in the BDA */
- Bda->VideoPage = PageNumber;
- Bda->VideoPageSize = BIOS_PAGE_SIZE;
- Bda->VideoPageOffset = PageNumber * BIOS_PAGE_SIZE;
+ /* Update the values in the BDA */
+ Bda->VideoPage = PageNumber;
+ Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;
/* Set the start address in the CRTC */
- VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
VgaWritePort(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
- VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
+ VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
VgaWritePort(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));
+ /*
+ * Get the cursor location (we don't update anything on the BIOS side
+ * but we update the cursor location on the VGA side).
+ */
+ BiosGetCursorPosition(&Row, &Column, PageNumber);
+ BiosSetCursorPosition(Row, Column, PageNumber);
+
return TRUE;
}
BOOLEAN BiosInitialize(VOID)
{
- USHORT i;
- WORD Offset = 0;
- LPWORD IntVecTable = (LPWORD)BaseAddress;
- LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BIOS_SEGMENT, 0);
-
/* Initialize the BDA */
Bda = (PBIOS_DATA_AREA)SEG_OFF_TO_PTR(BDA_SEGMENT, 0);
Bda->EquipmentList = BIOS_EQUIPMENT_LIST;
+ /*
+ * Conventional memory size is 640 kB,
+ * see: http://webpages.charter.net/danrollins/techhelp/0184.HTM
+ * and see Ralf Brown: http://www.ctyme.com/intr/rb-0598.htm
+ * for more information.
+ */
+ Bda->MemorySize = 0x0280;
Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer);
Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD);
-
- /* Generate ISR stubs and fill the IVT */
- for (i = 0x00; i <= 0xFF; i++)
- {
- IntVecTable[i * 2] = Offset;
- IntVecTable[i * 2 + 1] = BIOS_SEGMENT;
-
- BiosCode[Offset++] = 0xFB; // sti
-
- BiosCode[Offset++] = 0x6A; // push i
- BiosCode[Offset++] = (UCHAR)i;
-
- BiosCode[Offset++] = 0x6A; // push 0
- BiosCode[Offset++] = 0x00;
-
-// BOP_SEQ:
- BiosCode[Offset++] = 0xF8; // clc
-
- BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
- BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
- BiosCode[Offset++] = EMULATOR_INT_BOP;
-
- BiosCode[Offset++] = 0x73; // jnc EXIT (offset +3)
- BiosCode[Offset++] = 0x03;
-
- // HACK: The following instruction should be HLT!
- BiosCode[Offset++] = 0x90; // nop
-
- BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -9)
- BiosCode[Offset++] = 0xF7;
-
-// EXIT:
- BiosCode[Offset++] = 0x83; // add sp, 4
- BiosCode[Offset++] = 0xC4;
- BiosCode[Offset++] = 0x04;
-
- BiosCode[Offset++] = 0xCF; // iret
- }
+ Bda->KeybdBufferHead = Bda->KeybdBufferTail = 0;
+
+ /* Initialize the 32-bit Interrupt system */
+ InitializeInt32(BIOS_SEGMENT);
+
+ /* Register the BIOS 32-bit Interrupts */
+ RegisterInt32(BIOS_VIDEO_INTERRUPT , BiosVideoService );
+ RegisterInt32(BIOS_EQUIPMENT_INTERRUPT, BiosEquipmentService );
+ RegisterInt32(BIOS_MEMORY_SIZE , BiosGetMemorySize );
+ RegisterInt32(BIOS_MISC_INTERRUPT , BiosMiscService );
+ RegisterInt32(BIOS_KBD_INTERRUPT , BiosKeyboardService );
+ RegisterInt32(BIOS_TIME_INTERRUPT , BiosTimeService );
+ RegisterInt32(BIOS_SYS_TIMER_INTERRUPT, BiosSystemTimerInterrupt);
+
+ /* Some interrupts are in fact addresses to tables */
+ ((PDWORD)BaseAddress)[0x1D] = (DWORD)NULL;
+ ((PDWORD)BaseAddress)[0x1E] = (DWORD)NULL;
+ ((PDWORD)BaseAddress)[0x1F] = (DWORD)NULL;
+
+ ((PDWORD)BaseAddress)[0x41] = (DWORD)NULL;
+ ((PDWORD)BaseAddress)[0x43] = (DWORD)NULL;
+ ((PDWORD)BaseAddress)[0x44] = (DWORD)NULL;
+ ((PDWORD)BaseAddress)[0x46] = (DWORD)NULL;
+ ((PDWORD)BaseAddress)[0x48] = (DWORD)NULL;
+ ((PDWORD)BaseAddress)[0x49] = (DWORD)NULL;
/* Get the input handle to the real console, and check for success */
BiosConsoleInput = CreateFileW(L"CONIN$",
/* Set the console input mode */
SetConsoleMode(BiosConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
+ /* Initialize PS2 */
+ PS2Initialize(BiosConsoleInput);
+
/* Initialize the PIC */
PicWriteCommand(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4);
PicWriteCommand(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4);
VOID BiosCleanup(VOID)
{
+ PS2Cleanup();
+
/* Restore the old screen buffer */
SetConsoleActiveScreenBuffer(BiosConsoleOutput);
WORD CharacterData = 0;
/* Check if there is a key available */
- if (Bda->KeybdBufferHead != Bda->KeybdBufferTail)
+ if (BiosKbdBufferTop(&CharacterData))
{
- /* Get the key from the queue, and remove it */
- BiosKbdBufferTop(&CharacterData);
+ /* A key was available, remove it from the queue */
BiosKbdBufferPop();
}
else
{
- /* Set the handler CF to repeat the BOP */
- EmulatorSetFlag(EMULATOR_FLAG_CF);
+ /* No key available. Set the handler CF to repeat the BOP */
+ setCF(1);
+ // CharacterData = 0xFFFF;
}
return CharacterData;
}
+VOID BiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
+{
+ /* Make sure the selected video page is valid */
+ if (Page >= BIOS_MAX_PAGES) return;
+
+ /* Get the cursor location */
+ *Row = HIBYTE(Bda->CursorPosition[Page]);
+ *Column = LOBYTE(Bda->CursorPosition[Page]);
+}
+
VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
{
/* Make sure the selected video page is valid */
if (Page >= BIOS_MAX_PAGES) return;
/* Update the position in the BDA */
- Bda->CursorPosition[Page] = (Row << 8) | Column;
+ Bda->CursorPosition[Page] = MAKEWORD(Column, Row);
/* Check if this is the current video page */
if (Page == Bda->VideoPage)
{
DWORD i;
LPWORD WindowData;
- DWORD WindowSize = (Rectangle.Bottom - Rectangle.Top + 1)
- * (Rectangle.Right - Rectangle.Left + 1);
+ WORD WindowWidth = Rectangle.Right - Rectangle.Left + 1;
+ WORD WindowHeight = Rectangle.Bottom - Rectangle.Top + 1;
+ DWORD WindowSize = WindowWidth * WindowHeight;
/* Allocate a buffer for the window */
WindowData = (LPWORD)HeapAlloc(GetProcessHeap(),
/* Read the window data */
BiosReadWindow(WindowData, Rectangle, Page);
- if (Amount == 0)
+ if ((Amount == 0)
+ || (((Direction == SCROLL_DIRECTION_UP)
+ || (Direction == SCROLL_DIRECTION_DOWN))
+ && (Amount >= WindowHeight))
+ || (((Direction == SCROLL_DIRECTION_LEFT)
+ || (Direction == SCROLL_DIRECTION_RIGHT))
+ && (Amount >= WindowWidth)))
{
/* Fill the window */
for (i = 0; i < WindowSize; i++)
{
- WindowData[i] = ' ' | (FillAttribute << 8);
+ WindowData[i] = MAKEWORD(' ', FillAttribute);
}
goto Done;
}
- // TODO: Scroll the window!
+ switch (Direction)
+ {
+ case SCROLL_DIRECTION_UP:
+ {
+ RtlMoveMemory(WindowData,
+ &WindowData[WindowWidth * Amount],
+ (WindowSize - WindowWidth * Amount) * sizeof(WORD));
+
+ for (i = 0; i < Amount * WindowWidth; i++)
+ {
+ WindowData[WindowSize - i - 1] = MAKEWORD(' ', FillAttribute);
+ }
+
+ break;
+ }
+
+ case SCROLL_DIRECTION_DOWN:
+ {
+ RtlMoveMemory(&WindowData[WindowWidth * Amount],
+ WindowData,
+ (WindowSize - WindowWidth * Amount) * sizeof(WORD));
+
+ for (i = 0; i < Amount * WindowWidth; i++)
+ {
+ WindowData[i] = MAKEWORD(' ', FillAttribute);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ // TODO: NOT IMPLEMENTED!
+ UNIMPLEMENTED;
+ }
+ }
Done:
/* Write back the window data */
VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
{
- WORD CharData = (Attribute << 8) | Character;
+ WORD CharData = MAKEWORD(Character, Attribute);
BYTE Row, Column;
/* Make sure the page exists */
if (Page >= BIOS_MAX_PAGES) return;
/* Get the cursor location */
- Row = HIBYTE(Bda->CursorPosition[Page]);
- Column = LOBYTE(Bda->CursorPosition[Page]);
+ BiosGetCursorPosition(&Row, &Column, Page);
if (Character == '\a')
{
}
/* Erase the existing character */
- CharData = (Attribute << 8) | ' ';
- VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG,
- Page * Bda->VideoPageSize
- + (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
- (LPVOID)&CharData,
- sizeof(WORD));
+ CharData = MAKEWORD(' ', Attribute);
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(TEXT_VIDEO_SEG,
+ Page * Bda->VideoPageSize +
+ (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
+ (LPVOID)&CharData,
+ sizeof(WORD));
+ }
+ else if (Character == '\t')
+ {
+ /* Horizontal Tabulation control character */
+ do
+ {
+ // Taken from DosBox
+ BiosPrintCharacter(' ', Attribute, Page);
+ BiosGetCursorPosition(&Row, &Column, Page);
+ } while (Column % 8);
}
else if (Character == '\n')
{
/* Default character */
/* Write the character */
- VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG,
- Page * Bda->VideoPageSize
- + (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
- (LPVOID)&CharData,
- sizeof(WORD));
+ EmulatorWriteMemory(&EmulatorContext,
+ TO_LINEAR(TEXT_VIDEO_SEG,
+ Page * Bda->VideoPageSize +
+ (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
+ (LPVOID)&CharData,
+ sizeof(WORD));
/* Advance the cursor */
Column++;
Rectangle,
Page,
DEFAULT_ATTRIBUTE);
+
+ Row--;
}
/* Set the cursor position */
BiosSetCursorPosition(Row, Column, Page);
}
-VOID BiosVideoService(LPWORD Stack)
+VOID WINAPI BiosVideoService(LPWORD Stack)
{
switch (getAH())
{
/* Set Single Palette Register */
case 0x00:
{
- /* Reset the flip-flop */
- VgaReadPort(VGA_STAT_COLOR);
-
/* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
VgaWritePort(VGA_AC_INDEX, getBL());
/* Write the data */
VgaWritePort(VGA_AC_WRITE, getBH());
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
break;
}
/* Set Overscan Color */
case 0x01:
{
- /* Reset the flip-flop */
- VgaReadPort(VGA_STAT_COLOR);
-
/* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
/* Write the data */
VgaWritePort(VGA_AC_WRITE, getBH());
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
break;
}
/* Set the palette registers */
for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
{
- /* Reset the flip-flop */
- VgaReadPort(VGA_STAT_COLOR);
-
/* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
VgaWritePort(VGA_AC_INDEX, i);
/* Write the data */
VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
VgaWritePort(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
break;
}
/* Get Single Palette Register */
case 0x07:
{
- /* Reset the flip-flop */
- VgaReadPort(VGA_STAT_COLOR);
-
/* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
VgaWritePort(VGA_AC_INDEX, getBL());
/* Read the data */
setBH(VgaReadPort(VGA_AC_READ));
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
break;
}
/* Get Overscan Color */
case 0x08:
{
- /* Reset the flip-flop */
- VgaReadPort(VGA_STAT_COLOR);
-
/* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
/* Read the data */
setBH(VgaReadPort(VGA_AC_READ));
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
break;
}
/* Get the palette registers */
for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
{
- /* Reset the flip-flop */
- VgaReadPort(VGA_STAT_COLOR);
-
/* Write the index */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
VgaWritePort(VGA_AC_INDEX, i);
/* Read the data */
VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
Buffer[VGA_AC_PAL_F_REG + 1] = VgaReadPort(VGA_AC_READ);
+ /* Enable screen and disable palette access */
+ VgaReadPort(VGA_INSTAT1_READ); // Put the AC register into index state
+ VgaWritePort(VGA_AC_INDEX, 0x20);
break;
}
}
}
-VOID BiosKeyboardService(LPWORD 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);
+}
+
+VOID WINAPI BiosMiscService(LPWORD Stack)
+{
+ switch (getAH())
+ {
+ /* Copy Extended Memory */
+ case 0x87:
+ {
+ DWORD Count = (DWORD)getCX() * 2;
+ PFAST486_GDT_ENTRY Gdt = (PFAST486_GDT_ENTRY)SEG_OFF_TO_PTR(getES(), getSI());
+ DWORD SourceBase = Gdt[2].Base + (Gdt[2].BaseMid << 16) + (Gdt[2].BaseHigh << 24);
+ DWORD SourceLimit = Gdt[2].Limit + (Gdt[2].LimitHigh << 16);
+ DWORD DestBase = Gdt[3].Base + (Gdt[3].BaseMid << 16) + (Gdt[3].BaseHigh << 24);
+ DWORD DestLimit = Gdt[3].Limit + (Gdt[3].LimitHigh << 16);
+
+ /* Check for flags */
+ if (Gdt[2].Granularity) SourceLimit = (SourceLimit << 12) | 0xFFF;
+ if (Gdt[3].Granularity) DestLimit = (DestLimit << 12) | 0xFFF;
+
+ if ((Count > SourceLimit) || (Count > DestLimit))
+ {
+ setAX(0x80);
+ Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF;
+
+ break;
+ }
+
+ /* Copy */
+ RtlMoveMemory((PVOID)((ULONG_PTR)BaseAddress + DestBase),
+ (PVOID)((ULONG_PTR)BaseAddress + SourceBase),
+ Count);
+
+ setAX(ERROR_SUCCESS);
+ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+ break;
+ }
+
+ /* Get Extended Memory Size */
+ case 0x88:
+ {
+ /* Return the number of KB of RAM after 1 MB */
+ setAX((MAX_ADDRESS - 0x100000) / 1024);
+
+ /* Clear CF */
+ Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF;
+
+ break;
+ }
+
+ default:
+ {
+ DPRINT1("BIOS Function INT 15h, AH = 0x%02X NOT IMPLEMENTED\n",
+ getAH());
+ }
+ }
+}
+
+VOID WINAPI BiosKeyboardService(LPWORD Stack)
{
switch (getAH())
{
}
}
-VOID BiosTimeService(LPWORD Stack)
+VOID WINAPI BiosTimeService(LPWORD Stack)
{
switch (getAH())
{
}
}
-VOID BiosSystemTimerInterrupt(LPWORD Stack)
+VOID WINAPI BiosSystemTimerInterrupt(LPWORD Stack)
{
/* Increase the system tick count */
Bda->TickCounter++;
}
-VOID BiosEquipmentService(LPWORD Stack)
-{
- /* Return the equipment list */
- setAX(Bda->EquipmentList);
-}
-
VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack)
{
switch (IrqNumber)
BYTE ScanCode, VirtualKey;
WORD Character;
- /* Loop while there is a scancode available */
- do
- {
- /* Get the scan code and virtual key code */
- ScanCode = KeyboardReadData();
- VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
+ /* Get the scan code and virtual key code */
+ ScanCode = PS2ReadPort(PS2_DATA_PORT);
+ VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK);
- /* Check if this is a key press or release */
- if (!(ScanCode & (1 << 7)))
+ /* Check if this is a key press or release */
+ if (!(ScanCode & (1 << 7)))
+ {
+ /* Key press */
+ if (VirtualKey == VK_NUMLOCK ||
+ VirtualKey == VK_CAPITAL ||
+ VirtualKey == VK_SCROLL ||
+ VirtualKey == VK_INSERT)
{
- /* Key press */
- if (VirtualKey == VK_NUMLOCK ||
- VirtualKey == VK_CAPITAL ||
- VirtualKey == VK_SCROLL ||
- VirtualKey == VK_INSERT)
- {
- /* For toggle keys, toggle the lowest bit in the keyboard map */
- BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
- }
-
- /* Set the highest bit */
- BiosKeyboardMap[VirtualKey] |= (1 << 7);
+ /* For toggle keys, toggle the lowest bit in the keyboard map */
+ BiosKeyboardMap[VirtualKey] ^= ~(1 << 0);
+ }
- /* Find out which character this is */
- Character = 0;
- if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
- {
- /* Not ASCII */
- Character = 0;
- }
+ /* Set the highest bit */
+ BiosKeyboardMap[VirtualKey] |= (1 << 7);
- /* Push it onto the BIOS keyboard queue */
- BiosKbdBufferPush(MAKEWORD(Character, ScanCode));
- }
- else
+ /* Find out which character this is */
+ Character = 0;
+ if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0)
{
- /* Key release, unset the highest bit */
- BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
+ /* Not ASCII */
+ Character = 0;
}
+
+ /* Push it onto the BIOS keyboard queue */
+ BiosKbdBufferPush(MAKEWORD(Character, ScanCode));
+ }
+ else
+ {
+ /* Key release, unset the highest bit */
+ BiosKeyboardMap[VirtualKey] &= ~(1 << 7);
}
- while (KeyboardReadStatus() & 1);
/* Clear the keyboard flags */
Bda->KeybdShiftFlags = 0;