[SOFT386]

Implement Soft386LoadSegment.
[NTVDM]
Fix BiosPrintCharacter (Adapted from a patch by Hermes Belusca-Maito).


svn path=/branches/ntvdm/; revision=59764
This commit is contained in:
Aleksandar Andrejevic 2013-08-17 18:44:16 +00:00
parent c7b66d26f6
commit 99302b9d00
3 changed files with 201 additions and 26 deletions

View file

@ -10,6 +10,16 @@
#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 ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
inline 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 // TODO: Generate exception #GP
return FALSE; 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 // TODO: Generate exception #GP
return FALSE; 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 */

View 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_ #endif // _COMMON_H_
/* EOF */ /* EOF */

View 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), VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
(LPVOID)&Character, (LPVOID)&Character,
sizeof(WORD)); sizeof(WORD));
@ -701,24 +701,71 @@ VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
Row = HIBYTE(Bda->CursorPosition[Page]); Row = HIBYTE(Bda->CursorPosition[Page]);
Column = LOBYTE(Bda->CursorPosition[Page]); Column = LOBYTE(Bda->CursorPosition[Page]);
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 */ /* Write the character */
VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG, VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG,
(Row * Bda->ScreenColumns + Column) * sizeof(WORD)), Page * Bda->VideoPageSize
+ (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
(LPVOID)&CharData, (LPVOID)&CharData,
sizeof(WORD)); sizeof(WORD));
/* Advance the cursor */ /* Advance the cursor */
Column++; 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) /* Scroll the screen up if needed */
if (Row > Bda->ScreenRows)
{ {
/* The screen must be scrolled */ /* The screen must be scrolled up */
SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows }; SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
BiosScrollWindow(SCROLL_DIRECTION_UP, BiosScrollWindow(SCROLL_DIRECTION_UP,
@ -727,8 +774,6 @@ VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page)
Page, Page,
DEFAULT_ATTRIBUTE); DEFAULT_ATTRIBUTE);
} }
else Row++;
}
/* Set the cursor position */ /* Set the cursor position */
BiosSetCursorPosition(Row, Column, Page); BiosSetCursorPosition(Row, Column, Page);
@ -820,8 +865,8 @@ VOID BiosVideoService(LPWORD Stack)
}; };
/* Call the internal function */ /* Call the internal function */
BiosScrollWindow((HIBYTE(Eax) == 0x06) BiosScrollWindow((HIBYTE(Eax) == 0x06) ? SCROLL_DIRECTION_UP
? SCROLL_DIRECTION_UP : SCROLL_DIRECTION_DOWN, : SCROLL_DIRECTION_DOWN,
LOBYTE(Eax), LOBYTE(Eax),
Rectangle, Rectangle,
Bda->VideoPage, Bda->VideoPage,