[SOFT386]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 17 Aug 2013 18:44:16 +0000 (18:44 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sat, 17 Aug 2013 18:44:16 +0000 (18:44 +0000)
Implement Soft386LoadSegment.
[NTVDM]
Fix BiosPrintCharacter (Adapted from a patch by Hermes Belusca-Maito).

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

lib/soft386/common.c
lib/soft386/common.h
subsystems/ntvdm/bios.c

index 6ce335e..45e6e52 100644 (file)
 
 #include "common.h"
 
 
 #include "common.h"
 
+/* PRIVATE FUNCTIONS **********************************************************/
+
+static
+inline
+INT
+Soft386GetCurrentPrivLevel(PSOFT386_STATE State)
+{
+    return GET_SEGMENT_RPL(State->SegmentRegs[SOFT386_REG_CS].Selector);
+}
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 inline
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 inline
@@ -48,7 +58,7 @@ Soft386ReadMemory(PSOFT386_STATE State,
             return FALSE;
         }
 
             return FALSE;
         }
 
-        if (GET_SEGMENT_DPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+        if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
         {
             // TODO: Generate exception #GP
             return FALSE;
         {
             // TODO: Generate exception #GP
             return FALSE;
@@ -131,7 +141,7 @@ Soft386WriteMemory(PSOFT386_STATE State,
             return FALSE;
         }
 
             return FALSE;
         }
 
-        if (GET_SEGMENT_DPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
+        if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl)
         {
             // TODO: Generate exception #GP
             return FALSE;
         {
             // TODO: Generate exception #GP
             return FALSE;
@@ -299,4 +309,114 @@ Soft386StackPop(PSOFT386_STATE State, PULONG Value)
     return TRUE;
 }
 
     return TRUE;
 }
 
+inline
+BOOLEAN
+Soft386LoadSegment(PSOFT386_STATE State, INT Segment, WORD Selector)
+{
+    PSOFT386_SEG_REG CachedDescriptor;
+    SOFT386_GDT_ENTRY GdtEntry;
+
+    ASSERT(Segment < SOFT386_NUM_SEG_REGS);
+
+    /* Get the cached descriptor */
+    CachedDescriptor = &State->SegmentRegs[Segment];
+
+    /* Check for protected mode */
+    if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
+    {
+        /* Make sure the GDT contains the entry */
+        if (GET_SEGMENT_INDEX(Selector) >= (State->Gdtr.Size + 1))
+        {
+            // TODO: Exception #GP
+            return FALSE;
+        }
+
+        /* Read the GDT */
+        // FIXME: This code is only correct when paging is disabled!!!
+        if (State->MemReadCallback)
+        {
+            State->MemReadCallback(State,
+                                   State->Gdtr.Address
+                                   + GET_SEGMENT_INDEX(Selector),
+                                   &GdtEntry,
+                                   sizeof(GdtEntry));
+        }
+        else
+        {
+            RtlMoveMemory(&GdtEntry,
+                          (LPVOID)(State->Gdtr.Address
+                          + GET_SEGMENT_INDEX(Selector)),
+                          sizeof(GdtEntry));
+        }
+
+        /* Check if we are loading SS */
+        if (Segment == SOFT386_REG_SS)
+        {
+            if (GET_SEGMENT_INDEX(Selector) == 0)
+            {
+                // TODO: Exception #GP
+                return FALSE;
+            }
+
+            if (GdtEntry.Executable || !GdtEntry.ReadWrite)
+            {
+                // TODO: Exception #GP
+                return FALSE;
+            }
+
+            if ((GET_SEGMENT_RPL(Selector) != Soft386GetCurrentPrivLevel(State))
+                || (GET_SEGMENT_RPL(Selector) != GdtEntry.Dpl))
+            {
+                // TODO: Exception #GP
+                return FALSE;
+            }
+
+            if (!GdtEntry.Present)
+            {
+                // TODO: Exception #SS
+                return FALSE;
+            }
+        }
+        else
+        {
+            if ((GET_SEGMENT_RPL(Selector) > GdtEntry.Dpl)
+                && (Soft386GetCurrentPrivLevel(State) > GdtEntry.Dpl))
+            {
+                // TODO: Exception #GP
+                return FALSE;
+            }
+
+            if (!GdtEntry.Present)
+            {
+                // TODO: Exception #NP
+                return FALSE;
+            }
+        }
+
+        /* Update the cache entry */
+        CachedDescriptor->Selector = Selector;
+        CachedDescriptor->Base = GdtEntry.Base | (GdtEntry.BaseHigh << 24);
+        CachedDescriptor->Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
+        CachedDescriptor->Accessed = GdtEntry.Accessed;
+        CachedDescriptor->ReadWrite = GdtEntry.ReadWrite;
+        CachedDescriptor->DirConf = GdtEntry.DirConf;
+        CachedDescriptor->Executable = GdtEntry.Executable;
+        CachedDescriptor->SystemType = GdtEntry.SystemType;
+        CachedDescriptor->Dpl = GdtEntry.Dpl;
+        CachedDescriptor->Present = GdtEntry.Present;
+        CachedDescriptor->Size = GdtEntry.Size;
+
+        /* Check for page granularity */
+        if (GdtEntry.Granularity) CachedDescriptor->Limit <<= 12;
+    }
+    else
+    {
+        /* Update the selector and base */
+        CachedDescriptor->Selector = Selector;
+        CachedDescriptor->Base = Selector << 4;
+    }
+
+    return TRUE;
+}
+
 /* EOF */
 /* EOF */
index b316eeb..9b4e958 100644 (file)
@@ -15,7 +15,8 @@
 
 /* DEFINES ********************************************************************/
 
 
 /* DEFINES ********************************************************************/
 
-#define GET_SEGMENT_DPL(s) ((s) & 3)
+#define GET_SEGMENT_RPL(s) ((s) & 3)
+#define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8)
 
 /* FUNCTIONS ******************************************************************/
 
 
 /* FUNCTIONS ******************************************************************/
 
@@ -58,6 +59,15 @@ Soft386StackPop
     PULONG Value
 );
 
     PULONG Value
 );
 
+inline
+BOOLEAN
+Soft386LoadSegment
+(
+    PSOFT386_STATE State,
+    INT Segment,
+    WORD Selector
+);
+
 #endif // _COMMON_H_
 
 /* EOF */
 #endif // _COMMON_H_
 
 /* EOF */
index cb5f9d5..0791c27 100644 (file)
@@ -356,7 +356,7 @@ static VOID BiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page)
         {
             Character = Buffer[Counter++];
 
         {
             Character = Buffer[Counter++];
 
-            /* Read from video memory */
+            /* Write to video memory */
             VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
                            (LPVOID)&Character,
                            sizeof(WORD));
             VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
                            (LPVOID)&Character,
                            sizeof(WORD));
@@ -701,33 +701,78 @@ VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
     Row = HIBYTE(Bda->CursorPosition[Page]);
     Column = LOBYTE(Bda->CursorPosition[Page]);
 
     Row = HIBYTE(Bda->CursorPosition[Page]);
     Column = LOBYTE(Bda->CursorPosition[Page]);
 
-    /* Write the character */
-    VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG,
-                   (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
-                   (LPVOID)&CharData,
-                   sizeof(WORD));
+    if (Character == '\a')
+    {
+        /* Bell control character */
+        // NOTE: We may use what the terminal emulator offers to us...
+        Beep(800, 200);
+        return;
+    }
+    else if (Character == '\b')
+    {
+        /* Backspace control character */
+        if (Column > 0)
+        {
+            Column--;
+        }
+        else if (Row > 0)
+        {
+            Column = Bda->ScreenColumns - 1;
+            Row--;
+        }
+
+        /* 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));
+    }
+    else if (Character == '\n')
+    {
+        /* Line Feed control character */
+        Row++;
+    }
+    else if (Character == '\r')
+    {
+        /* Carriage Return control character */
+        Column = 0;
+    }
+    else
+    {
+        /* Default character */
+
+        /* Write the character */
+        VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG,
+                       Page * Bda->VideoPageSize
+                       + (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
+                       (LPVOID)&CharData,
+                       sizeof(WORD));
 
 
-    /* Advance the cursor */
-    Column++;
+        /* Advance the cursor */
+        Column++;
+    }
 
     /* Check if it passed the end of the row */
 
     /* Check if it passed the end of the row */
-    if (Column == Bda->ScreenColumns)
+    if (Column >= Bda->ScreenColumns)
     {
     {
-        /* Return to the first column */
+        /* Return to the first column and go to the next line */
         Column = 0;
         Column = 0;
+        Row++;
+    }
 
 
-        if (Row == Bda->ScreenRows)
-        {
-            /* The screen must be scrolled */
-            SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
-
-            BiosScrollWindow(SCROLL_DIRECTION_UP,
-                             1,
-                             Rectangle,
-                             Page,
-                             DEFAULT_ATTRIBUTE);
-        }
-        else Row++;
+    /* Scroll the screen up if needed */
+    if (Row > Bda->ScreenRows)
+    {
+        /* The screen must be scrolled up */
+        SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
+
+        BiosScrollWindow(SCROLL_DIRECTION_UP,
+                         1,
+                         Rectangle,
+                         Page,
+                         DEFAULT_ATTRIBUTE);
     }
 
     /* Set the cursor position */
     }
 
     /* Set the cursor position */
@@ -820,8 +865,8 @@ VOID BiosVideoService(LPWORD Stack)
             };
 
             /* Call the internal function */
             };
 
             /* Call the internal function */
-            BiosScrollWindow((HIBYTE(Eax) == 0x06)
-                             ? SCROLL_DIRECTION_UP : SCROLL_DIRECTION_DOWN,
+            BiosScrollWindow((HIBYTE(Eax) == 0x06) ? SCROLL_DIRECTION_UP
+                                                   : SCROLL_DIRECTION_DOWN,
                              LOBYTE(Eax),
                              Rectangle,
                              Bda->VideoPage,
                              LOBYTE(Eax),
                              Rectangle,
                              Bda->VideoPage,