From: Aleksandar Andrejevic Date: Sat, 17 Aug 2013 18:44:16 +0000 (+0000) Subject: [SOFT386] X-Git-Tag: backups/0.3.17@66124~1365^2~491 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=99302b9d00d65c3252a9bf2bba68edaeef32d782;ds=inline [SOFT386] Implement Soft386LoadSegment. [NTVDM] Fix BiosPrintCharacter (Adapted from a patch by Hermes Belusca-Maito). svn path=/branches/ntvdm/; revision=59764 --- diff --git a/lib/soft386/common.c b/lib/soft386/common.c index 6ce335e44c3..45e6e52d2cf 100644 --- a/lib/soft386/common.c +++ b/lib/soft386/common.c @@ -10,6 +10,16 @@ #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 @@ -48,7 +58,7 @@ Soft386ReadMemory(PSOFT386_STATE State, return FALSE; } - if (GET_SEGMENT_DPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl) + if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl) { // TODO: Generate exception #GP return FALSE; @@ -131,7 +141,7 @@ Soft386WriteMemory(PSOFT386_STATE State, return FALSE; } - if (GET_SEGMENT_DPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl) + if (GET_SEGMENT_RPL(CachedDescriptor->Selector) > CachedDescriptor->Dpl) { // TODO: Generate exception #GP return FALSE; @@ -299,4 +309,114 @@ Soft386StackPop(PSOFT386_STATE State, PULONG Value) 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 */ diff --git a/lib/soft386/common.h b/lib/soft386/common.h index b316eebc192..9b4e958f054 100644 --- a/lib/soft386/common.h +++ b/lib/soft386/common.h @@ -15,7 +15,8 @@ /* DEFINES ********************************************************************/ -#define GET_SEGMENT_DPL(s) ((s) & 3) +#define GET_SEGMENT_RPL(s) ((s) & 3) +#define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8) /* FUNCTIONS ******************************************************************/ @@ -58,6 +59,15 @@ Soft386StackPop PULONG Value ); +inline +BOOLEAN +Soft386LoadSegment +( + PSOFT386_STATE State, + INT Segment, + WORD Selector +); + #endif // _COMMON_H_ /* EOF */ diff --git a/subsystems/ntvdm/bios.c b/subsystems/ntvdm/bios.c index cb5f9d58650..0791c271ed2 100644 --- a/subsystems/ntvdm/bios.c +++ b/subsystems/ntvdm/bios.c @@ -356,7 +356,7 @@ static VOID BiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page) { Character = Buffer[Counter++]; - /* Read from video memory */ + /* Write to video memory */ 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]); - /* 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 */ - 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; + 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 */ @@ -820,8 +865,8 @@ VOID BiosVideoService(LPWORD Stack) }; /* 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,