mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[BOOTVID][HALXBOX] Implement boot video driver for Xbox (#2774)
Also make HalpBiosDisplayReset() function always return FALSE, because we don't have a BIOS on Xbox. CORE-16216 CORE-16219
This commit is contained in:
parent
cd0c06bef3
commit
fa1ec0a2ed
6 changed files with 521 additions and 0 deletions
|
@ -4,15 +4,24 @@ spec2def(bootvid.dll bootvid.spec ADD_IMPORTLIB)
|
||||||
if((ARCH STREQUAL "i386") OR (ARCH STREQUAL "amd64"))
|
if((ARCH STREQUAL "i386") OR (ARCH STREQUAL "amd64"))
|
||||||
if(SARCH STREQUAL "pc98")
|
if(SARCH STREQUAL "pc98")
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
|
i386/pc98/pc98.h
|
||||||
i386/pc98/bootvid.c)
|
i386/pc98/bootvid.c)
|
||||||
|
elseif(SARCH STREQUAL "xbox")
|
||||||
|
list(APPEND SOURCE
|
||||||
|
i386/xbox/nv2a.h
|
||||||
|
i386/xbox/bootvid.c)
|
||||||
else()
|
else()
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
|
i386/pc/pc.h
|
||||||
|
i386/pc/cmdcnst.h
|
||||||
i386/pc/bootvid.c
|
i386/pc/bootvid.c
|
||||||
i386/pc/bootdata.c
|
i386/pc/bootdata.c
|
||||||
|
i386/pc/vga.h
|
||||||
i386/pc/vga.c)
|
i386/pc/vga.c)
|
||||||
endif()
|
endif()
|
||||||
elseif(ARCH STREQUAL "arm")
|
elseif(ARCH STREQUAL "arm")
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
|
arm/arm.h
|
||||||
arm/bootvid.c)
|
arm/bootvid.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#if defined(SARCH_PC98)
|
#if defined(SARCH_PC98)
|
||||||
#define REACTOS_STR_FILE_DESCRIPTION "NEC PC-98 Boot Video Driver"
|
#define REACTOS_STR_FILE_DESCRIPTION "NEC PC-98 Boot Video Driver"
|
||||||
|
#elif defined(SARCH_XBOX)
|
||||||
|
#define REACTOS_STR_FILE_DESCRIPTION "Original Xbox Boot Video Driver"
|
||||||
#else
|
#else
|
||||||
#define REACTOS_STR_FILE_DESCRIPTION "VGA Boot Driver"
|
#define REACTOS_STR_FILE_DESCRIPTION "VGA Boot Driver"
|
||||||
#endif
|
#endif
|
||||||
|
|
441
drivers/base/bootvid/i386/xbox/bootvid.c
Normal file
441
drivers/base/bootvid/i386/xbox/bootvid.c
Normal file
|
@ -0,0 +1,441 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Boot Video Driver for Original Xbox
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Main file
|
||||||
|
* COPYRIGHT: Copyright 2004 Gé van Geldorp (gvg@reactos.org)
|
||||||
|
* Copyright 2005 Filip Navara (navaraf@reactos.org)
|
||||||
|
* Copyright 2020 Stanislav Motylkov (x86corez@gmail.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
/* GLOBALS ********************************************************************/
|
||||||
|
|
||||||
|
static ULONG_PTR FrameBufferStart = 0;
|
||||||
|
static ULONG FrameBufferWidth, FrameBufferHeight, PanH, PanV;
|
||||||
|
static UCHAR BytesPerPixel;
|
||||||
|
static RGBQUAD CachedPalette[BV_MAX_COLORS];
|
||||||
|
static PUCHAR BackBuffer = NULL;
|
||||||
|
|
||||||
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
static UCHAR
|
||||||
|
NvGetCrtc(
|
||||||
|
ULONG Base,
|
||||||
|
UCHAR Index)
|
||||||
|
{
|
||||||
|
WRITE_REGISTER_UCHAR((PUCHAR)(Base + NV2A_CRTC_REGISTER_INDEX), Index);
|
||||||
|
return READ_REGISTER_UCHAR((PUCHAR)(Base + NV2A_CRTC_REGISTER_VALUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static UCHAR
|
||||||
|
NvGetBytesPerPixel(
|
||||||
|
ULONG Base,
|
||||||
|
ULONG ScreenWidth)
|
||||||
|
{
|
||||||
|
/* Get BPP directly from NV2A CRTC (magic constants are from Cromwell) */
|
||||||
|
UCHAR BytesPerPixel = 8 * (((NvGetCrtc(Base, 0x19) & 0xE0) << 3) | (NvGetCrtc(Base, 0x13) & 0xFF)) / ScreenWidth;
|
||||||
|
|
||||||
|
if (BytesPerPixel == 4)
|
||||||
|
{
|
||||||
|
ASSERT((NvGetCrtc(Base, 0x28) & 0xF) == BytesPerPixel - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT((NvGetCrtc(Base, 0x28) & 0xF) == BytesPerPixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BytesPerPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
ApplyPalette(VOID)
|
||||||
|
{
|
||||||
|
PULONG Frame = (PULONG)FrameBufferStart;
|
||||||
|
ULONG x, y;
|
||||||
|
|
||||||
|
/* Top panning */
|
||||||
|
for (x = 0; x < PanV * FrameBufferWidth; x++)
|
||||||
|
{
|
||||||
|
*Frame++ = CachedPalette[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Left panning */
|
||||||
|
for (y = 0; y < SCREEN_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
Frame = (PULONG)(FrameBufferStart + FB_OFFSET(-PanH, y));
|
||||||
|
|
||||||
|
for (x = 0; x < PanH; x++)
|
||||||
|
{
|
||||||
|
*Frame++ = CachedPalette[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Screen redraw */
|
||||||
|
PUCHAR Back = BackBuffer;
|
||||||
|
for (y = 0; y < SCREEN_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
Frame = (PULONG)(FrameBufferStart + FB_OFFSET(0, y));
|
||||||
|
|
||||||
|
for (x = 0; x < SCREEN_WIDTH; x++)
|
||||||
|
{
|
||||||
|
*Frame++ = CachedPalette[*Back++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right panning */
|
||||||
|
for (y = 0; y < SCREEN_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
Frame = (PULONG)(FrameBufferStart + FB_OFFSET(SCREEN_WIDTH, y));
|
||||||
|
|
||||||
|
for (x = 0; x < PanH; x++)
|
||||||
|
{
|
||||||
|
*Frame++ = CachedPalette[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bottom panning */
|
||||||
|
Frame = (PULONG)(FrameBufferStart + FB_OFFSET(-PanH, SCREEN_HEIGHT));
|
||||||
|
for (x = 0; x < PanV * FrameBufferWidth; x++)
|
||||||
|
{
|
||||||
|
*Frame++ = CachedPalette[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PUBLIC FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
VidInitialize(
|
||||||
|
_In_ BOOLEAN SetMode)
|
||||||
|
{
|
||||||
|
BOOLEAN Result = FALSE;
|
||||||
|
|
||||||
|
/* FIXME: Add platform check */
|
||||||
|
/* 1. Access PCI device 1:0:0 */
|
||||||
|
/* 2. Check if device ID is 10DE:02A0 */
|
||||||
|
|
||||||
|
/* FIXME: Get device MMIO ranges from PCI */
|
||||||
|
PHYSICAL_ADDRESS PhysControlStart = {.QuadPart = 0xFD000000};
|
||||||
|
PHYSICAL_ADDRESS PhysFrameBufferStart = {.QuadPart = 0xF0000000};
|
||||||
|
ULONG ControlLength = 16 * 1024 * 1024;
|
||||||
|
|
||||||
|
ULONG_PTR ControlStart = (ULONG_PTR)MmMapIoSpace(PhysControlStart, ControlLength, MmNonCached);
|
||||||
|
if (!ControlStart)
|
||||||
|
{
|
||||||
|
DPRINT1("Out of memory!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG_PTR FrameBuffer = READ_REGISTER_ULONG((PULONG)(ControlStart + NV2A_CONTROL_FRAMEBUFFER_ADDRESS_OFFSET));
|
||||||
|
FrameBufferWidth = READ_REGISTER_ULONG((PULONG)(ControlStart + NV2A_RAMDAC_FP_HVALID_END)) + 1;
|
||||||
|
FrameBufferHeight = READ_REGISTER_ULONG((PULONG)(ControlStart + NV2A_RAMDAC_FP_VVALID_END)) + 1;
|
||||||
|
|
||||||
|
FrameBuffer &= 0x0FFFFFFF;
|
||||||
|
if (FrameBuffer != 0x3C00000 && FrameBuffer != 0x7C00000)
|
||||||
|
{
|
||||||
|
/* Check framebuffer address (high 4 MB of either 64 or 128 MB RAM) */
|
||||||
|
DPRINT1("Non-standard framebuffer address 0x%p\n", FrameBuffer);
|
||||||
|
}
|
||||||
|
/* Verify that framebuffer address is page-aligned */
|
||||||
|
ASSERT(FrameBuffer % PAGE_SIZE == 0);
|
||||||
|
|
||||||
|
if (FrameBufferWidth < SCREEN_WIDTH || FrameBufferHeight < SCREEN_HEIGHT)
|
||||||
|
{
|
||||||
|
DPRINT1("Unsupported screen resolution!\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
BytesPerPixel = NvGetBytesPerPixel(ControlStart, FrameBufferWidth);
|
||||||
|
ASSERT(BytesPerPixel >= 1 && BytesPerPixel <= 4);
|
||||||
|
|
||||||
|
if (BytesPerPixel != 4)
|
||||||
|
{
|
||||||
|
DPRINT1("Unsupported BytesPerPixel = %d\n", BytesPerPixel);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate panning values */
|
||||||
|
PanH = (FrameBufferWidth - SCREEN_WIDTH) / 2;
|
||||||
|
PanV = (FrameBufferHeight - SCREEN_HEIGHT) / 2;
|
||||||
|
|
||||||
|
/* Verify that screen fits framebuffer size */
|
||||||
|
ULONG FrameBufferSize = FrameBufferWidth * FrameBufferHeight * BytesPerPixel;
|
||||||
|
|
||||||
|
/* FIXME: obtain fb size from firmware somehow (Cromwell reserves high 4 MB of RAM) */
|
||||||
|
if (FrameBufferSize > NV2A_VIDEO_MEMORY_SIZE)
|
||||||
|
{
|
||||||
|
DPRINT1("Current screen resolution exceeds video memory bounds!\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reserve off-screen area for the backbuffer that contains 8-bit indexed
|
||||||
|
* color screen image, plus preserved row data.
|
||||||
|
*/
|
||||||
|
ULONG BackBufferSize = SCREEN_WIDTH * (SCREEN_HEIGHT + BOOTCHAR_HEIGHT + 1);
|
||||||
|
|
||||||
|
/* Make sure there is enough video memory for backbuffer */
|
||||||
|
if (NV2A_VIDEO_MEMORY_SIZE - FrameBufferSize < BackBufferSize)
|
||||||
|
{
|
||||||
|
DPRINT1("Out of memory!\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the address back to GPU memory mapped I/O */
|
||||||
|
PhysFrameBufferStart.QuadPart += FrameBuffer;
|
||||||
|
FrameBufferStart = (ULONG_PTR)MmMapIoSpace(PhysFrameBufferStart, NV2A_VIDEO_MEMORY_SIZE, MmNonCached);
|
||||||
|
if (!FrameBufferStart)
|
||||||
|
{
|
||||||
|
DPRINT1("Out of memory!\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = TRUE;
|
||||||
|
|
||||||
|
/* Place backbuffer in the hidden part of framebuffer */
|
||||||
|
BackBuffer = (PUCHAR)(FrameBufferStart + NV2A_VIDEO_MEMORY_SIZE - BackBufferSize);
|
||||||
|
|
||||||
|
/* Now check if we have to set the mode */
|
||||||
|
if (SetMode)
|
||||||
|
VidResetDisplay(TRUE);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (ControlStart)
|
||||||
|
MmUnmapIoSpace((PVOID)ControlStart, ControlLength);
|
||||||
|
|
||||||
|
/* Video is ready */
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
VidCleanUp(VOID)
|
||||||
|
{
|
||||||
|
/* Just fill the screen black */
|
||||||
|
VidSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, BV_COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
VidResetDisplay(
|
||||||
|
_In_ BOOLEAN HalReset)
|
||||||
|
{
|
||||||
|
/* Clear the current position */
|
||||||
|
VidpCurrentX = 0;
|
||||||
|
VidpCurrentY = 0;
|
||||||
|
|
||||||
|
/* Clear the screen with HAL if we were asked to */
|
||||||
|
if (HalReset)
|
||||||
|
HalResetDisplay();
|
||||||
|
|
||||||
|
/* Re-initialize the palette and fill the screen black */
|
||||||
|
RtlZeroMemory((PULONG)FrameBufferStart, NV2A_VIDEO_MEMORY_SIZE);
|
||||||
|
InitializePalette();
|
||||||
|
VidSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, BV_COLOR_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
InitPaletteWithTable(
|
||||||
|
_In_ PULONG Table,
|
||||||
|
_In_ ULONG Count)
|
||||||
|
{
|
||||||
|
PULONG Entry = Table;
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < Count; i++, Entry++)
|
||||||
|
{
|
||||||
|
CachedPalette[i] = *Entry | 0xFF000000;
|
||||||
|
}
|
||||||
|
ApplyPalette();
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
PrepareForSetPixel(VOID)
|
||||||
|
{
|
||||||
|
/* Nothing to prepare */
|
||||||
|
NOTHING;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
SetPixel(
|
||||||
|
_In_ ULONG Left,
|
||||||
|
_In_ ULONG Top,
|
||||||
|
_In_ UCHAR Color)
|
||||||
|
{
|
||||||
|
PUCHAR Back = BackBuffer + BB_OFFSET(Left, Top);
|
||||||
|
PULONG Frame = (PULONG)(FrameBufferStart + FB_OFFSET(Left, Top));
|
||||||
|
|
||||||
|
*Back = Color;
|
||||||
|
*Frame = CachedPalette[Color];
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
PreserveRow(
|
||||||
|
_In_ ULONG CurrentTop,
|
||||||
|
_In_ ULONG TopDelta,
|
||||||
|
_In_ BOOLEAN Restore)
|
||||||
|
{
|
||||||
|
PUCHAR NewPosition, OldPosition;
|
||||||
|
|
||||||
|
/* Calculate the position in memory for the row */
|
||||||
|
if (Restore)
|
||||||
|
{
|
||||||
|
/* Restore the row by copying back the contents saved off-screen */
|
||||||
|
NewPosition = BackBuffer + BB_OFFSET(0, CurrentTop);
|
||||||
|
OldPosition = BackBuffer + BB_OFFSET(0, SCREEN_HEIGHT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Preserve the row by saving its contents off-screen */
|
||||||
|
NewPosition = BackBuffer + BB_OFFSET(0, SCREEN_HEIGHT);
|
||||||
|
OldPosition = BackBuffer + BB_OFFSET(0, CurrentTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the count and loop every pixel of backbuffer */
|
||||||
|
ULONG Count = TopDelta * SCREEN_WIDTH;
|
||||||
|
|
||||||
|
RtlCopyMemory(NewPosition, OldPosition, Count);
|
||||||
|
|
||||||
|
if (Restore)
|
||||||
|
{
|
||||||
|
NewPosition = BackBuffer + BB_OFFSET(0, CurrentTop);
|
||||||
|
|
||||||
|
/* Set the count and loop every pixel of framebuffer */
|
||||||
|
for (ULONG y = 0; y < TopDelta; y++)
|
||||||
|
{
|
||||||
|
PULONG Frame = (PULONG)(FrameBufferStart + FB_OFFSET(0, CurrentTop + y));
|
||||||
|
|
||||||
|
Count = SCREEN_WIDTH;
|
||||||
|
while (Count--)
|
||||||
|
{
|
||||||
|
*Frame++ = CachedPalette[*NewPosition++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
DoScroll(
|
||||||
|
_In_ ULONG Scroll)
|
||||||
|
{
|
||||||
|
ULONG RowSize = VidpScrollRegion[2] - VidpScrollRegion[0] + 1;
|
||||||
|
|
||||||
|
/* Calculate the position in memory for the row */
|
||||||
|
PUCHAR OldPosition = BackBuffer + BB_OFFSET(VidpScrollRegion[0], VidpScrollRegion[1] + Scroll);
|
||||||
|
PUCHAR NewPosition = BackBuffer + BB_OFFSET(VidpScrollRegion[0], VidpScrollRegion[1]);
|
||||||
|
|
||||||
|
/* Start loop */
|
||||||
|
for (ULONG Top = VidpScrollRegion[1]; Top <= VidpScrollRegion[3]; ++Top)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
/* Scroll the row */
|
||||||
|
RtlCopyMemory(NewPosition, OldPosition, RowSize);
|
||||||
|
|
||||||
|
PULONG Frame = (PULONG)(FrameBufferStart + FB_OFFSET(VidpScrollRegion[0], Top));
|
||||||
|
|
||||||
|
for (i = 0; i < RowSize; ++i)
|
||||||
|
Frame[i] = CachedPalette[NewPosition[i]];
|
||||||
|
|
||||||
|
OldPosition += SCREEN_WIDTH;
|
||||||
|
NewPosition += SCREEN_WIDTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
DisplayCharacter(
|
||||||
|
_In_ CHAR Character,
|
||||||
|
_In_ ULONG Left,
|
||||||
|
_In_ ULONG Top,
|
||||||
|
_In_ ULONG TextColor,
|
||||||
|
_In_ ULONG BackColor)
|
||||||
|
{
|
||||||
|
/* Get the font and pixel pointer */
|
||||||
|
PUCHAR FontChar = GetFontPtr(Character);
|
||||||
|
|
||||||
|
/* Loop each pixel height */
|
||||||
|
for (ULONG y = Top; y < Top + BOOTCHAR_HEIGHT; y++, FontChar += FONT_PTR_DELTA)
|
||||||
|
{
|
||||||
|
/* Loop each pixel width */
|
||||||
|
ULONG x = Left;
|
||||||
|
|
||||||
|
for (UCHAR bit = 1 << (BOOTCHAR_WIDTH - 1); bit > 0; bit >>= 1, x++)
|
||||||
|
{
|
||||||
|
/* Check if we should draw this pixel */
|
||||||
|
if (*FontChar & bit)
|
||||||
|
{
|
||||||
|
/* We do, use the given Text Color */
|
||||||
|
SetPixel(x, y, (UCHAR)TextColor);
|
||||||
|
}
|
||||||
|
else if (BackColor < BV_COLOR_NONE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This is a background pixel. We're drawing it
|
||||||
|
* unless it's transparent.
|
||||||
|
*/
|
||||||
|
SetPixel(x, y, (UCHAR)BackColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
VidSolidColorFill(
|
||||||
|
_In_ ULONG Left,
|
||||||
|
_In_ ULONG Top,
|
||||||
|
_In_ ULONG Right,
|
||||||
|
_In_ ULONG Bottom,
|
||||||
|
_In_ UCHAR Color)
|
||||||
|
{
|
||||||
|
while (Top <= Bottom)
|
||||||
|
{
|
||||||
|
PUCHAR Back = BackBuffer + BB_OFFSET(Left, Top);
|
||||||
|
PULONG Frame = (PULONG)(FrameBufferStart + FB_OFFSET(Left, Top));
|
||||||
|
ULONG L = Left;
|
||||||
|
|
||||||
|
while (L++ <= Right)
|
||||||
|
{
|
||||||
|
*Back++ = Color;
|
||||||
|
*Frame++ = CachedPalette[Color];
|
||||||
|
}
|
||||||
|
Top++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
VidScreenToBufferBlt(
|
||||||
|
_Out_ PUCHAR Buffer,
|
||||||
|
_In_ ULONG Left,
|
||||||
|
_In_ ULONG Top,
|
||||||
|
_In_ ULONG Width,
|
||||||
|
_In_ ULONG Height,
|
||||||
|
_In_ ULONG Delta)
|
||||||
|
{
|
||||||
|
/* Clear the destination buffer */
|
||||||
|
RtlZeroMemory(Buffer, Delta * Height);
|
||||||
|
|
||||||
|
/* Start the outer Y height loop */
|
||||||
|
for (ULONG y = 0; y < Height; y++)
|
||||||
|
{
|
||||||
|
/* Set current scanline */
|
||||||
|
PUCHAR Back = BackBuffer + BB_OFFSET(Left, Top + y);
|
||||||
|
PUCHAR Buf = Buffer + y * Delta;
|
||||||
|
|
||||||
|
/* Start the X inner loop */
|
||||||
|
for (ULONG x = 0; x < Width; x += 2)
|
||||||
|
{
|
||||||
|
/* Read the current value */
|
||||||
|
*Buf = (*Back++ & 0xF) << 4;
|
||||||
|
*Buf |= *Back++ & 0xF;
|
||||||
|
Buf++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
drivers/base/bootvid/i386/xbox/nv2a.h
Normal file
63
drivers/base/bootvid/i386/xbox/nv2a.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Boot Video Driver for Original Xbox
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Arch-specific header file
|
||||||
|
* COPYRIGHT: Copyright 2004 Gé van Geldorp (gvg@reactos.org)
|
||||||
|
* Copyright 2005 Filip Navara (navaraf@reactos.org)
|
||||||
|
* Copyright 2020 Stanislav Motylkov (x86corez@gmail.com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BOOTVID_NV2A_H_
|
||||||
|
#define _BOOTVID_NV2A_H_
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* FIXME: obtain fb size from firmware somehow (Cromwell reserves high 4 MB of RAM) */
|
||||||
|
#define NV2A_VIDEO_MEMORY_SIZE (4 * 1024 * 1024)
|
||||||
|
|
||||||
|
#define NV2A_CONTROL_FRAMEBUFFER_ADDRESS_OFFSET 0x600800
|
||||||
|
#define NV2A_CRTC_REGISTER_INDEX 0x6013D4
|
||||||
|
#define NV2A_CRTC_REGISTER_VALUE 0x6013D5
|
||||||
|
#define NV2A_RAMDAC_FP_HVALID_END 0x680838
|
||||||
|
#define NV2A_RAMDAC_FP_VVALID_END 0x680818
|
||||||
|
|
||||||
|
#define BB_OFFSET(x, y) ((y) * SCREEN_WIDTH + (x))
|
||||||
|
#define FB_OFFSET(x, y) (((PanV + (y)) * FrameBufferWidth + PanH + (x)) * BytesPerPixel)
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
InitPaletteWithTable(
|
||||||
|
_In_ PULONG Table,
|
||||||
|
_In_ ULONG Count);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
PrepareForSetPixel(VOID);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
SetPixel(
|
||||||
|
_In_ ULONG Left,
|
||||||
|
_In_ ULONG Top,
|
||||||
|
_In_ UCHAR Color);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
PreserveRow(
|
||||||
|
_In_ ULONG CurrentTop,
|
||||||
|
_In_ ULONG TopDelta,
|
||||||
|
_In_ BOOLEAN Restore);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
DoScroll(
|
||||||
|
_In_ ULONG Scroll);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
DisplayCharacter(
|
||||||
|
_In_ CHAR Character,
|
||||||
|
_In_ ULONG Left,
|
||||||
|
_In_ ULONG Top,
|
||||||
|
_In_ ULONG TextColor,
|
||||||
|
_In_ ULONG BackColor);
|
||||||
|
|
||||||
|
#endif /* _BOOTVID_NV2A_H_ */
|
|
@ -9,6 +9,8 @@
|
||||||
#if defined(_M_IX86) || defined(_M_AMD64)
|
#if defined(_M_IX86) || defined(_M_AMD64)
|
||||||
#if defined(SARCH_PC98)
|
#if defined(SARCH_PC98)
|
||||||
#include "i386/pc98/pc98.h"
|
#include "i386/pc98/pc98.h"
|
||||||
|
#elif defined(SARCH_XBOX)
|
||||||
|
#include "i386/xbox/nv2a.h"
|
||||||
#else
|
#else
|
||||||
#include "i386/pc/vga.h"
|
#include "i386/pc/vga.h"
|
||||||
#include "i386/pc/pc.h"
|
#include "i386/pc/pc.h"
|
||||||
|
|
|
@ -645,6 +645,9 @@ BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
HalpBiosDisplayReset(VOID)
|
HalpBiosDisplayReset(VOID)
|
||||||
{
|
{
|
||||||
|
#ifdef SARCH_XBOX
|
||||||
|
return FALSE;
|
||||||
|
#else
|
||||||
ULONG Flags;
|
ULONG Flags;
|
||||||
PHARDWARE_PTE IdtPte;
|
PHARDWARE_PTE IdtPte;
|
||||||
BOOLEAN RestoreWriteProtection = FALSE;
|
BOOLEAN RestoreWriteProtection = FALSE;
|
||||||
|
@ -709,6 +712,7 @@ HalpBiosDisplayReset(VOID)
|
||||||
//
|
//
|
||||||
__writeeflags(Flags);
|
__writeeflags(Flags);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue