mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 04:43:51 +00:00
[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:
parent
c7b66d26f6
commit
99302b9d00
3 changed files with 201 additions and 26 deletions
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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,33 +701,78 @@ 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]);
|
||||||
|
|
||||||
/* Write the character */
|
if (Character == '\a')
|
||||||
VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG,
|
{
|
||||||
(Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
|
/* Bell control character */
|
||||||
(LPVOID)&CharData,
|
// NOTE: We may use what the terminal emulator offers to us...
|
||||||
sizeof(WORD));
|
Beep(800, 200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (Character == '\b')
|
||||||
|
{
|
||||||
|
/* Backspace control character */
|
||||||
|
if (Column > 0)
|
||||||
|
{
|
||||||
|
Column--;
|
||||||
|
}
|
||||||
|
else if (Row > 0)
|
||||||
|
{
|
||||||
|
Column = Bda->ScreenColumns - 1;
|
||||||
|
Row--;
|
||||||
|
}
|
||||||
|
|
||||||
/* Advance the cursor */
|
/* Erase the existing character */
|
||||||
Column++;
|
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++;
|
||||||
|
}
|
||||||
|
|
||||||
/* 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 */
|
{
|
||||||
SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
|
/* The screen must be scrolled up */
|
||||||
|
SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
|
||||||
|
|
||||||
BiosScrollWindow(SCROLL_DIRECTION_UP,
|
BiosScrollWindow(SCROLL_DIRECTION_UP,
|
||||||
1,
|
1,
|
||||||
Rectangle,
|
Rectangle,
|
||||||
Page,
|
Page,
|
||||||
DEFAULT_ATTRIBUTE);
|
DEFAULT_ATTRIBUTE);
|
||||||
}
|
|
||||||
else Row++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue