[NTVDM]
[reactos.git] / subsystems / ntvdm / bios.c
index c2807f4..b4f202b 100644 (file)
@@ -26,6 +26,7 @@ static BYTE BiosKeyboardMap[256];
 static HANDLE BiosConsoleInput  = INVALID_HANDLE_VALUE;
 static HANDLE BiosConsoleOutput = INVALID_HANDLE_VALUE;
 static CONSOLE_SCREEN_BUFFER_INFO BiosSavedBufferInfo;
+static HANDLE InputThread = NULL;
 
 /*
  * VGA Register Configurations for BIOS Video Modes
@@ -414,6 +415,9 @@ BOOLEAN BiosSetVideoMode(BYTE ModeNumber)
         VgaWritePort(VGA_AC_WRITE, *(Values++));
     }
 
+    /* Reset the palette */
+    VgaResetPalette();
+
     /* Update the values in the BDA */
     Bda->VideoMode = ModeNumber;
     Bda->VideoPage = 0;
@@ -463,6 +467,13 @@ BOOLEAN BiosInitialize(VOID)
     /* 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);
 
@@ -555,6 +566,9 @@ BOOLEAN BiosInitialize(VOID)
     /* Set the console input mode */
     SetConsoleMode(BiosConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT);
 
+    /* Start the input thread */
+    InputThread = CreateThread(NULL, 0, &InputThreadProc, BiosConsoleInput, 0, NULL);
+
     /* Initialize the PIC */
     PicWriteCommand(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4);
     PicWriteCommand(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4);
@@ -593,6 +607,9 @@ VOID BiosCleanup(VOID)
     /* Close the console handles */
     if (BiosConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleOutput);
     if (BiosConsoleInput  != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleInput);
+
+    /* Close the input thread handle */
+    if (InputThread != NULL) CloseHandle(InputThread);
 }
 
 WORD BiosPeekCharacter(VOID)
@@ -743,11 +760,12 @@ VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
         /* 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++;
@@ -772,6 +790,8 @@ VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
                          Rectangle,
                          Page,
                          DEFAULT_ATTRIBUTE);
+
+        Row--;
     }
 
     /* Set the cursor position */
@@ -914,6 +934,205 @@ VOID BiosVideoService(LPWORD Stack)
             break;
         }
 
+        /* Palette Control */
+        case 0x10:
+        {
+            switch (getAL())
+            {
+                /* Set Single Palette Register */
+                case 0x00:
+                {
+                    /* Reset the flip-flop */
+                    VgaReadPort(VGA_STAT_COLOR);
+
+                    /* Write the index */
+                    VgaWritePort(VGA_AC_INDEX, getBL());
+
+                    /* Write the data */
+                    VgaWritePort(VGA_AC_WRITE, getBH());
+
+                    break;
+                }
+
+                /* Set Overscan Color */
+                case 0x01:
+                {
+                    /* Reset the flip-flop */
+                    VgaReadPort(VGA_STAT_COLOR);
+
+                    /* Write the index */
+                    VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+
+                    /* Write the data */
+                    VgaWritePort(VGA_AC_WRITE, getBH());
+
+                    break;
+                }
+
+                /* Set All Palette Registers */
+                case 0x02:
+                {
+                    INT i;
+                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+                    /* 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 */
+                        VgaWritePort(VGA_AC_INDEX, i);
+
+                        /* Write the data */
+                        VgaWritePort(VGA_AC_WRITE, Buffer[i]);
+                    }
+
+                    /* Set the overscan register */
+                    VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+                    VgaWritePort(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);
+
+                    break;
+                }
+
+                /* Get Single Palette Register */
+                case 0x07:
+                {
+                    /* Reset the flip-flop */
+                    VgaReadPort(VGA_STAT_COLOR);
+
+                    /* Write the index */
+                    VgaWritePort(VGA_AC_INDEX, getBL());
+
+                    /* Read the data */
+                    setBH(VgaReadPort(VGA_AC_READ));
+
+                    break;
+                }
+
+                /* Get Overscan Color */
+                case 0x08:
+                {
+                    /* Reset the flip-flop */
+                    VgaReadPort(VGA_STAT_COLOR);
+
+                    /* Write the index */
+                    VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+
+                    /* Read the data */
+                    setBH(VgaReadPort(VGA_AC_READ));
+
+                    break;
+                }
+
+                /* Get All Palette Registers */
+                case 0x09:
+                {
+                    INT i;
+                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+                    /* 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 */
+                        VgaWritePort(VGA_AC_INDEX, i);
+
+                        /* Read the data */
+                        Buffer[i] = VgaReadPort(VGA_AC_READ);
+                    }
+
+                    /* Get the overscan register */
+                    VgaWritePort(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
+                    Buffer[VGA_AC_PAL_F_REG + 1] = VgaReadPort(VGA_AC_READ);
+
+                    break;
+                }
+
+                /* Set Individual DAC Register */
+                case 0x10:
+                {
+                    /* Write the index */
+                    // Certainly in BL and not in BX as said by Ralf Brown...
+                    VgaWritePort(VGA_DAC_WRITE_INDEX, getBL());
+
+                    /* Write the data in this order: Red, Green, Blue */
+                    VgaWritePort(VGA_DAC_DATA, getDH());
+                    VgaWritePort(VGA_DAC_DATA, getCH());
+                    VgaWritePort(VGA_DAC_DATA, getCL());
+
+                    break;
+                }
+
+                /* Set Block of DAC Registers */
+                case 0x12:
+                {
+                    INT i;
+                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+                    /* Write the index */
+                    // Certainly in BL and not in BX as said by Ralf Brown...
+                    VgaWritePort(VGA_DAC_WRITE_INDEX, getBL());
+
+                    for (i = 0; i < getCX(); i++)
+                    {
+                        /* Write the data in this order: Red, Green, Blue */
+                        VgaWritePort(VGA_DAC_DATA, *Buffer++);
+                        VgaWritePort(VGA_DAC_DATA, *Buffer++);
+                        VgaWritePort(VGA_DAC_DATA, *Buffer++);
+                    }
+
+                    break;
+                }
+
+                /* Get Individual DAC Register */
+                case 0x15:
+                {
+                    /* Write the index */
+                    VgaWritePort(VGA_DAC_READ_INDEX, getBL());
+
+                    /* Read the data in this order: Red, Green, Blue */
+                    setDH(VgaReadPort(VGA_DAC_DATA));
+                    setCH(VgaReadPort(VGA_DAC_DATA));
+                    setCL(VgaReadPort(VGA_DAC_DATA));
+
+                    break;
+                }
+
+                /* Get Block of DAC Registers */
+                case 0x17:
+                {
+                    INT i;
+                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());
+
+                    /* Write the index */
+                    // Certainly in BL and not in BX as said by Ralf Brown...
+                    VgaWritePort(VGA_DAC_READ_INDEX, getBL());
+
+                    for (i = 0; i < getCX(); i++)
+                    {
+                        /* Write the data in this order: Red, Green, Blue */
+                        *Buffer++ = VgaReadPort(VGA_DAC_DATA);
+                        *Buffer++ = VgaReadPort(VGA_DAC_DATA);
+                        *Buffer++ = VgaReadPort(VGA_DAC_DATA);
+                    }
+
+                    break;
+                }
+
+                default:
+                {
+                    DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n",
+                            getAL());
+                    break;
+                }
+            }
+
+            break;
+        }
+
         /* Scroll Window */
         case 0x12:
         {
@@ -1087,6 +1306,12 @@ VOID BiosEquipmentService(LPWORD Stack)
     setAX(Bda->EquipmentList);
 }
 
+VOID BiosGetMemorySize(LPWORD Stack)
+{
+    /* Return the conventional memory size in kB, typically 640 kB */
+    setAX(Bda->MemorySize);
+}
+
 VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack)
 {
     switch (IrqNumber)