From 2f923086b1362b4cabef2976ae8acf62f899d5ba Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Thu, 10 Mar 2016 00:59:50 +0000 Subject: [PATCH] [NTVDM] Implement PaintMouseCursor and EraseMouseCursor for video modes 12h and 13h. svn path=/trunk/; revision=70990 --- reactos/subsystems/mvdm/ntvdm/dos/mouse32.c | 182 +++++++++++++++++--- reactos/subsystems/mvdm/ntvdm/dos/mouse32.h | 2 + 2 files changed, 164 insertions(+), 20 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c b/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c index f59702a5dc8..79f523df952 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/mouse32.c @@ -146,19 +146,11 @@ static VOID DosMouseDisable(VOID); static VOID PaintMouseCursor(VOID) { - COORD Position = DriverState.Position; - - /* Apply the clipping rectangle */ - if (Position.X < DriverState.MinX) Position.X = DriverState.MinX; - if (Position.X > DriverState.MaxX) Position.X = DriverState.MaxX; - if (Position.Y < DriverState.MinY) Position.Y = DriverState.MinY; - if (Position.Y > DriverState.MaxY) Position.Y = DriverState.MaxY; - if (Bda->VideoMode <= 3) { WORD Character; - WORD CellX = Position.X / 8; - WORD CellY = Position.Y / 8; + WORD CellX = DriverState.Position.X / 8; + WORD CellY = DriverState.Position.Y / 8; DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize); EmulatorReadMemory(&EmulatorContext, @@ -177,6 +169,109 @@ static VOID PaintMouseCursor(VOID) (LPVOID)&Character, sizeof(WORD)); } + else if (Bda->VideoMode == 0x12) + { + INT i, j; + BYTE OldMask; + BYTE OldMap; + + /* Save the write mask */ + IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG); + OldMask = IOReadB(VGA_SEQ_DATA); + + /* And the selected reading plane */ + IOWriteB(VGA_GC_INDEX, VGA_GC_READ_MAP_SEL_REG); + OldMap = IOReadB(VGA_GC_DATA); + + for (i = 0; i < 16; i++) + { + WORD CursorLine[4]; + DWORD VideoAddress = TO_LINEAR(GRAPHICS_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize) + + ((DriverState.Position.Y + i) * 640 + DriverState.Position.X) / 8; + + for (j = 0; j < 4; j++) + { + /* Select the reading plane */ + IOWriteB(VGA_GC_INDEX, VGA_GC_READ_MAP_SEL_REG); + IOWriteB(VGA_GC_DATA, j); + + /* Read a part of the scanline */ + EmulatorReadMemory(&EmulatorContext, VideoAddress, &CursorLine[j], sizeof(CursorLine[j])); + } + + /* Save the data below the cursor */ + for (j = 0; j < 16; j++) + { + DriverState.GraphicsData[i * 16 + j] = 0; + + if (CursorLine[0] & (1 << j)) DriverState.GraphicsData[i * 16 + j] |= 1 << 0; + if (CursorLine[1] & (1 << j)) DriverState.GraphicsData[i * 16 + j] |= 1 << 1; + if (CursorLine[2] & (1 << j)) DriverState.GraphicsData[i * 16 + j] |= 1 << 2; + if (CursorLine[3] & (1 << j)) DriverState.GraphicsData[i * 16 + j] |= 1 << 3; + } + + for (j = 0; j < 4; j++) + { + /* Apply the screen mask */ + CursorLine[j] &= MAKEWORD(HIBYTE(DriverState.GraphicsCursor.ScreenMask[i]), + LOBYTE(DriverState.GraphicsCursor.ScreenMask[i])); + + /* And the cursor mask */ + CursorLine[j] ^= MAKEWORD(HIBYTE(DriverState.GraphicsCursor.CursorMask[i]), + LOBYTE(DriverState.GraphicsCursor.CursorMask[i])); + + /* Select the writing plane */ + IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG); + IOWriteB(VGA_SEQ_DATA, 1 << j); + + /* Write the cursor data for this scanline */ + EmulatorWriteMemory(&EmulatorContext, VideoAddress, &CursorLine[j], sizeof(CursorLine[j])); + } + } + + /* Restore the old mask */ + IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG); + IOWriteB(VGA_SEQ_DATA, OldMask); + + /* And the old reading plane */ + IOWriteB(VGA_GC_INDEX, VGA_GC_READ_MAP_SEL_REG); + IOWriteB(VGA_GC_DATA, OldMap); + } + else if (Bda->VideoMode == 0x13) + { + INT i, j; + + for (i = 0; i < 16; i++) + { + BYTE CursorLine[16]; + DWORD VideoAddress = TO_LINEAR(GRAPHICS_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize) + + (DriverState.Position.Y + i) * 320 + DriverState.Position.X; + + /* Read a part of the scanline */ + EmulatorReadMemory(&EmulatorContext, + VideoAddress, + &DriverState.GraphicsData[i * 16], + sizeof(CursorLine)); + + for (j = 0; j < 16; j++) + { + /* Apply the screen mask by leaving only the masked pixels intact */ + CursorLine[j] = (DriverState.GraphicsCursor.ScreenMask[i] & (1 << j)) + ? DriverState.GraphicsData[i * 16] + : 0x00; + + /* Apply the cursor mask... */ + if (DriverState.GraphicsCursor.CursorMask[i] & (1 << j)) + { + /* ... by inverting the color of each masked pixel */ + CursorLine[j] ^= 0x0F; + } + } + + /* Write the cursor data for this scanline */ + EmulatorWriteMemory(&EmulatorContext, VideoAddress, &CursorLine, sizeof(CursorLine)); + } + } else { // TODO: NOT IMPLEMENTED @@ -186,18 +281,10 @@ static VOID PaintMouseCursor(VOID) static VOID EraseMouseCursor(VOID) { - COORD Position = DriverState.Position; - - /* Apply the clipping rectangle */ - if (Position.X < DriverState.MinX) Position.X = DriverState.MinX; - if (Position.X > DriverState.MaxX) Position.X = DriverState.MaxX; - if (Position.Y < DriverState.MinY) Position.Y = DriverState.MinY; - if (Position.Y > DriverState.MaxY) Position.Y = DriverState.MaxY; - if (Bda->VideoMode <= 3) { - WORD CellX = Position.X / 8; - WORD CellY = Position.Y / 8; + WORD CellX = DriverState.Position.X / 8; + WORD CellY = DriverState.Position.Y / 8; DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize); EmulatorWriteMemory(&EmulatorContext, @@ -206,6 +293,61 @@ static VOID EraseMouseCursor(VOID) (LPVOID)&DriverState.Character, sizeof(WORD)); } + else if (Bda->VideoMode == 0x12) + { + INT i, j; + BYTE OldMask; + + /* Save the write mask */ + IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG); + OldMask = IOReadB(VGA_SEQ_DATA); + + for (i = 0; i < 16; i++) + { + WORD CursorLine[4] = {0}; + DWORD VideoAddress = TO_LINEAR(GRAPHICS_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize) + + ((DriverState.Position.Y + i) * 640 + DriverState.Position.X) / 8; + + /* Restore the data that was below the cursor */ + for (j = 0; j < 16; j++) + { + if (DriverState.GraphicsData[i * 16 + j] & (1 << 0)) CursorLine[0] |= 1 << j; + if (DriverState.GraphicsData[i * 16 + j] & (1 << 1)) CursorLine[1] |= 1 << j; + if (DriverState.GraphicsData[i * 16 + j] & (1 << 2)) CursorLine[2] |= 1 << j; + if (DriverState.GraphicsData[i * 16 + j] & (1 << 3)) CursorLine[3] |= 1 << j; + } + + for (j = 0; j < 4; j++) + { + /* Select the writing plane */ + IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG); + IOWriteB(VGA_SEQ_DATA, 1 << j); + + /* Write the original data for this scanline */ + EmulatorWriteMemory(&EmulatorContext, VideoAddress, &CursorLine[j], sizeof(CursorLine[j])); + } + } + + /* Restore the old mask */ + IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG); + IOWriteB(VGA_SEQ_DATA, OldMask); + } + else if (Bda->VideoMode == 0x13) + { + INT i; + + for (i = 0; i < 16; i++) + { + DWORD VideoAddress = TO_LINEAR(GRAPHICS_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize) + + (DriverState.Position.Y + i) * 320 + DriverState.Position.X; + + /* Write the original data for this scanline */ + EmulatorWriteMemory(&EmulatorContext, + VideoAddress, + &DriverState.GraphicsData[i * 16], + 16 * sizeof(BYTE)); + } + } else { // TODO: NOT IMPLEMENTED diff --git a/reactos/subsystems/mvdm/ntvdm/dos/mouse32.h b/reactos/subsystems/mvdm/ntvdm/dos/mouse32.h index 4e6654c407a..df03f366231 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/mouse32.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/mouse32.h @@ -71,6 +71,8 @@ typedef struct _MOUSE_DRIVER_STATE WORD ScreenMask[16]; WORD CursorMask[16]; } GraphicsCursor; + + BYTE GraphicsData[256]; } MOUSE_DRIVER_STATE, *PMOUSE_DRIVER_STATE; /* FUNCTIONS ******************************************************************/