[NTVDM]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Wed, 10 Jul 2013 19:41:43 +0000 (19:41 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Wed, 10 Jul 2013 19:41:43 +0000 (19:41 +0000)
Add video pages support to INT 10h functions and memory access.
[SOFTX86]
Fix the opcode check for XLAT.

svn path=/branches/ntvdm/; revision=59454

lib/3rdparty/softx86/softx86/mov.c
subsystems/ntvdm/bios.c

index d902819..df42812 100644 (file)
@@ -219,7 +219,7 @@ int Sfx86OpcodeExec_xlat(sx86_ubyte opcode,softx86_ctx* ctx)
        else
                seg = ctx->state->segment_override;
 
-       if ((opcode&0xFC) == 0xD7) {                                    // MOV reg,reg/mem or reg/mem,reg
+       if (opcode == 0xD7) {                                   // MOV reg,reg/mem or reg/mem,reg
                sx86_ubyte d;
                sx86_udword ofs;
 
@@ -239,7 +239,7 @@ int Sfx86OpcodeExec_xlat(sx86_ubyte opcode,softx86_ctx* ctx)
 
 int Sfx86OpcodeDec_xlat(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
 {
-       if ((opcode&0xFC) == 0xD7) {                                    // XLAT
+       if (opcode == 0xD7) {                                   // XLAT
                strcpy(buf,"XLAT");
                return 1;
        }
index dd7cfc5..3ab00a6 100644 (file)
@@ -72,11 +72,31 @@ static INT BiosColorNumberToBits(DWORD Colors)
     return i;
 }
 
+static DWORD BiosGetVideoPageSize()
+{
+    INT i;
+    DWORD BufferSize = VideoModes[CurrentVideoMode].Width
+                       * VideoModes[CurrentVideoMode].Height
+                       * BiosColorNumberToBits(VideoModes[CurrentVideoMode].Colors)
+                       / 8;
+    
+    for (i = 0; i < 32; i++) if ((1 << i) >= BufferSize) break;
+
+    return 1 << i;
+}
+
+static BYTE BiosVideoAddressToPage(ULONG Address)
+{
+    return (Address - (VideoModes[CurrentVideoMode].Segment << 4))
+            / BiosGetVideoPageSize();
+}
+
 static COORD BiosVideoAddressToCoord(ULONG Address)
 {
     COORD Result = {0, 0};
     INT BitsPerPixel;
-    DWORD Offset = Address - (VideoModes[CurrentVideoMode].Segment << 4);
+    BYTE PageStart = BiosVideoAddressToPage(Address) * BiosGetVideoPageSize();
+    DWORD Offset = Address - (VideoModes[CurrentVideoMode].Segment << 4) - PageStart;
 
     if (VideoModes[CurrentVideoMode].Text)
     {
@@ -403,6 +423,7 @@ VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress)
 {
     ULONG i;
     COORD Coordinates;
+    BYTE Page;
     COORD Origin = { 0, 0 };
     COORD UnitSize = { 1, 1 };
     CHAR_INFO Character;
@@ -419,6 +440,12 @@ VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress)
             /* Get the coordinates */
             Coordinates = BiosVideoAddressToCoord(i);
 
+            /* Get the page number */
+            Page = BiosVideoAddressToPage(i);
+
+            /* Make sure the page is valid */
+            if (Page >= VideoModes[CurrentVideoMode].Pages) continue;
+
             /* Fill the rectangle structure */
             Rect.Left = Coordinates.X;
             Rect.Top = Coordinates.Y;
@@ -430,7 +457,7 @@ VOID BiosUpdateConsole(ULONG StartAddress, ULONG EndAddress)
             Character.Attributes = *((PBYTE)((ULONG_PTR)BaseAddress + i + 1));
 
             /* Write the character */
-            WriteConsoleOutputA(BiosConsoleOutput,
+            WriteConsoleOutputA(ConsoleBuffers[Page],
                                 &Character,
                                 UnitSize,
                                 Origin,
@@ -480,6 +507,7 @@ VOID BiosUpdateVideoMemory(ULONG StartAddress, ULONG EndAddress)
 {
     ULONG i;
     COORD Coordinates;
+    BYTE Page;
     WORD Attribute;
     DWORD CharsWritten;
 
@@ -491,11 +519,17 @@ VOID BiosUpdateVideoMemory(ULONG StartAddress, ULONG EndAddress)
             /* Get the coordinates */
             Coordinates = BiosVideoAddressToCoord(i);
 
+            /* Get the page number */
+            Page = BiosVideoAddressToPage(i);
+
+            /* Make sure the page is valid */
+            if (Page >= VideoModes[CurrentVideoMode].Pages) continue;
+
             /* Check if this is a character byte or an attribute byte */
             if ((i - (VideoModes[CurrentVideoMode].Segment << 4)) % 2 == 0)
             {
                 /* This is a regular character */
-                ReadConsoleOutputCharacterA(BiosConsoleOutput,
+                ReadConsoleOutputCharacterA(ConsoleBuffers[Page],
                                             (LPSTR)((ULONG_PTR)BaseAddress + i),
                                             sizeof(CHAR),
                                             Coordinates,
@@ -504,7 +538,7 @@ VOID BiosUpdateVideoMemory(ULONG StartAddress, ULONG EndAddress)
             else
             {
                 /*  This is an attribute */
-                ReadConsoleOutputAttribute(BiosConsoleOutput,
+                ReadConsoleOutputAttribute(ConsoleBuffers[Page],
                                            &Attribute,
                                            sizeof(CHAR),
                                            Coordinates,
@@ -614,7 +648,7 @@ VOID BiosVideoService()
             /* Set the cursor */
             CursorInfo.dwSize = (CursorHeight * 100) / CONSOLE_FONT_HEIGHT;
             CursorInfo.bVisible = !Invisible;
-            SetConsoleCursorInfo(BiosConsoleOutput, &CursorInfo);
+            SetConsoleCursorInfo(ConsoleBuffers[CurrentVideoPage], &CursorInfo);
 
             break;
         }
@@ -622,10 +656,13 @@ VOID BiosVideoService()
         /* Set Cursor Position */
         case 0x02:
         {
+            /* Make sure the selected video page exists */
+            if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
+
             Position.X = LOBYTE(Edx);
             Position.Y = HIBYTE(Edx);
 
-            SetConsoleCursorPosition(BiosConsoleOutput, Position);
+            SetConsoleCursorPosition(ConsoleBuffers[HIBYTE(Ebx)], Position);
             break;
         }
 
@@ -634,9 +671,13 @@ VOID BiosVideoService()
         {
             INT StartLine;
 
+            /* Make sure the selected video page exists */
+            if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
+
             /* Retrieve the data */
-            GetConsoleCursorInfo(BiosConsoleOutput, &CursorInfo);
-            GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
+            GetConsoleCursorInfo(ConsoleBuffers[HIBYTE(Ebx)], &CursorInfo);
+            GetConsoleScreenBufferInfo(ConsoleBuffers[HIBYTE(Ebx)],
+                                       &ScreenBufferInfo);
 
             /* Find the first line */
             StartLine = 32 - ((CursorInfo.dwSize * 32) / 100);
@@ -650,6 +691,28 @@ VOID BiosVideoService()
             break;
         }
 
+        /* Select Active Display Page */
+        case 0x05:
+        {
+            /* Check if the page exists */
+            if (LOBYTE(Eax) >= VideoModes[CurrentVideoMode].Pages) break;
+
+            /* Check if this is the same page */
+            if (LOBYTE(Eax) == CurrentVideoPage) break;
+
+            /* Change the video page */
+            CurrentVideoPage = LOBYTE(Eax);
+
+            /* Set the active page console buffer */
+            SetConsoleActiveScreenBuffer(ConsoleBuffers[CurrentVideoPage]);
+
+            /* Restore the cursor to (0, 0) */
+            Position.X = Position.Y = 0;
+            SetConsoleCursorPosition(BiosConsoleOutput, Position);
+
+            break;
+        }
+
         /* Scroll Up/Down Window */
         case 0x06:
         case 0x07:
@@ -664,7 +727,7 @@ VOID BiosVideoService()
             if (HIBYTE(Eax) == 0x06) Position.Y = Rect.Top - LOBYTE(Eax);
             else Position.Y = Rect.Top + LOBYTE(Eax);
 
-            ScrollConsoleScreenBuffer(BiosConsoleOutput,
+            ScrollConsoleScreenBuffer(ConsoleBuffers[CurrentVideoPage],
                                       &Rect,
                                       &Rect,
                                       Position,
@@ -677,15 +740,23 @@ VOID BiosVideoService()
         {
             COORD BufferSize = { 1, 1 }, Origin = { 0, 0 };
 
+            /* Make sure the selected video page exists */
+            if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
+
             /* Get the cursor position */
-            GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
+            GetConsoleScreenBufferInfo(ConsoleBuffers[HIBYTE(Ebx)],
+                                       &ScreenBufferInfo);
 
             /* Read at cursor position */
             Rect.Left = ScreenBufferInfo.dwCursorPosition.X;
             Rect.Top = ScreenBufferInfo.dwCursorPosition.Y;
             
             /* Read the console output */
-            ReadConsoleOutput(BiosConsoleOutput, &Character, BufferSize, Origin, &Rect);
+            ReadConsoleOutput(ConsoleBuffers[HIBYTE(Ebx)],
+                              &Character,
+                              BufferSize,
+                              Origin,
+                              &Rect);
 
             /* Return the result */
             EmulatorSetRegister(EMULATOR_REG_AX,
@@ -700,18 +771,22 @@ VOID BiosVideoService()
         {
             DWORD CharsWritten;
 
+            /* Make sure the selected video page exists */
+            if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
+
             /* Get the cursor position */
-            GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
+            GetConsoleScreenBufferInfo(ConsoleBuffers[HIBYTE(Ebx)],
+                                       &ScreenBufferInfo);
 
             /* Write the attribute to the output */
-            FillConsoleOutputAttribute(BiosConsoleOutput,
+            FillConsoleOutputAttribute(ConsoleBuffers[HIBYTE(Ebx)],
                                        LOBYTE(Ebx),
                                        LOWORD(Ecx),
                                        ScreenBufferInfo.dwCursorPosition,
                                        &CharsWritten);
 
             /* Write the character to the output */
-            FillConsoleOutputCharacterA(BiosConsoleOutput,
+            FillConsoleOutputCharacterA(ConsoleBuffers[HIBYTE(Ebx)],
                                         LOBYTE(Eax),
                                         LOWORD(Ecx),
                                         ScreenBufferInfo.dwCursorPosition,
@@ -725,11 +800,15 @@ VOID BiosVideoService()
         {
             DWORD CharsWritten;
 
+            /* Make sure the selected video page exists */
+            if (HIBYTE(Ebx) >= VideoModes[CurrentVideoMode].Pages) break;
+
             /* Get the cursor position */
-            GetConsoleScreenBufferInfo(BiosConsoleOutput, &ScreenBufferInfo);
+            GetConsoleScreenBufferInfo(ConsoleBuffers[HIBYTE(Ebx)],
+                                       &ScreenBufferInfo);
 
             /* Write the character to the output */
-            FillConsoleOutputCharacterA(BiosConsoleOutput,
+            FillConsoleOutputCharacterA(ConsoleBuffers[HIBYTE(Ebx)],
                                         LOBYTE(Eax),
                                         LOWORD(Ecx),
                                         ScreenBufferInfo.dwCursorPosition,