ReactOS  0.4.15-dev-1177-g6cb3b62
bootvid.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Boot Video Driver for Original Xbox
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Main file
5  * COPYRIGHT: Copyright 2004 Gé van Geldorp (gvg@reactos.org)
6  * Copyright 2005 Filip Navara (navaraf@reactos.org)
7  * Copyright 2020 Stanislav Motylkov (x86corez@gmail.com)
8  */
9 
10 #include "precomp.h"
11 
12 #include <debug.h>
13 
14 #include <drivers/xbox/xgpu.h>
15 
16 /* GLOBALS ********************************************************************/
17 
23 
24 /* PRIVATE FUNCTIONS *********************************************************/
25 
26 static UCHAR
28  ULONG Base,
29  UCHAR Index)
30 {
33 }
34 
35 static UCHAR
37  ULONG Base,
39 {
40  /* Get BPP directly from NV2A CRTC (magic constants are from Cromwell) */
41  UCHAR BytesPerPixel = 8 * (((NvGetCrtc(Base, 0x19) & 0xE0) << 3) | (NvGetCrtc(Base, 0x13) & 0xFF)) / ScreenWidth;
42 
43  if (BytesPerPixel == 4)
44  {
45  ASSERT((NvGetCrtc(Base, 0x28) & 0xF) == BytesPerPixel - 1);
46  }
47  else
48  {
49  ASSERT((NvGetCrtc(Base, 0x28) & 0xF) == BytesPerPixel);
50  }
51 
52  return BytesPerPixel;
53 }
54 
55 static VOID
57 {
59  ULONG x, y;
60 
61  /* Top panning */
62  for (x = 0; x < PanV * FrameBufferWidth; x++)
63  {
64  *Frame++ = CachedPalette[0];
65  }
66 
67  /* Left panning */
68  for (y = 0; y < SCREEN_HEIGHT; y++)
69  {
70  Frame = (PULONG)(FrameBufferStart + FB_OFFSET(-PanH, y));
71 
72  for (x = 0; x < PanH; x++)
73  {
74  *Frame++ = CachedPalette[0];
75  }
76  }
77 
78  /* Screen redraw */
79  PUCHAR Back = BackBuffer;
80  for (y = 0; y < SCREEN_HEIGHT; y++)
81  {
82  Frame = (PULONG)(FrameBufferStart + FB_OFFSET(0, y));
83 
84  for (x = 0; x < SCREEN_WIDTH; x++)
85  {
86  *Frame++ = CachedPalette[*Back++];
87  }
88  }
89 
90  /* Right panning */
91  for (y = 0; y < SCREEN_HEIGHT; y++)
92  {
94 
95  for (x = 0; x < PanH; x++)
96  {
97  *Frame++ = CachedPalette[0];
98  }
99  }
100 
101  /* Bottom panning */
103  for (x = 0; x < PanV * FrameBufferWidth; x++)
104  {
105  *Frame++ = CachedPalette[0];
106  }
107 }
108 
109 /* PUBLIC FUNCTIONS **********************************************************/
110 
111 BOOLEAN
112 NTAPI
114  _In_ BOOLEAN SetMode)
115 {
116  BOOLEAN Result = FALSE;
117 
118  /* FIXME: Add platform check */
119  /* 1. Access PCI device 1:0:0 */
120  /* 2. Check if device ID is 10DE:02A0 */
121 
122  /* FIXME: Get device MMIO ranges from PCI */
123  PHYSICAL_ADDRESS PhysControlStart = {.QuadPart = 0xFD000000};
124  PHYSICAL_ADDRESS PhysFrameBufferStart = {.QuadPart = 0xF0000000};
125  ULONG ControlLength = 16 * 1024 * 1024;
126 
127  ULONG_PTR ControlStart = (ULONG_PTR)MmMapIoSpace(PhysControlStart, ControlLength, MmNonCached);
128  if (!ControlStart)
129  {
130  DPRINT1("Out of memory!\n");
131  return FALSE;
132  }
133 
137 
138  FrameBuffer &= 0x0FFFFFFF;
139  if (FrameBuffer != 0x3C00000 && FrameBuffer != 0x7C00000)
140  {
141  /* Check framebuffer address (high 4 MB of either 64 or 128 MB RAM) */
142  DPRINT1("Non-standard framebuffer address 0x%p\n", FrameBuffer);
143  }
144  /* Verify that framebuffer address is page-aligned */
145  ASSERT(FrameBuffer % PAGE_SIZE == 0);
146 
148  {
149  DPRINT1("Unsupported screen resolution!\n");
150  goto cleanup;
151  }
152 
154  ASSERT(BytesPerPixel >= 1 && BytesPerPixel <= 4);
155 
156  if (BytesPerPixel != 4)
157  {
158  DPRINT1("Unsupported BytesPerPixel = %d\n", BytesPerPixel);
159  goto cleanup;
160  }
161 
162  /* Calculate panning values */
165 
166  /* Verify that screen fits framebuffer size */
168 
169  /* FIXME: obtain fb size from firmware somehow (Cromwell reserves high 4 MB of RAM) */
171  {
172  DPRINT1("Current screen resolution exceeds video memory bounds!\n");
173  goto cleanup;
174  }
175 
176  /*
177  * Reserve off-screen area for the backbuffer that contains 8-bit indexed
178  * color screen image, plus preserved row data.
179  */
180  ULONG BackBufferSize = SCREEN_WIDTH * (SCREEN_HEIGHT + BOOTCHAR_HEIGHT + 1);
181 
182  /* Make sure there is enough video memory for backbuffer */
183  if (NV2A_VIDEO_MEMORY_SIZE - FrameBufferSize < BackBufferSize)
184  {
185  DPRINT1("Out of memory!\n");
186  goto cleanup;
187  }
188 
189  /* Return the address back to GPU memory mapped I/O */
190  PhysFrameBufferStart.QuadPart += FrameBuffer;
192  if (!FrameBufferStart)
193  {
194  DPRINT1("Out of memory!\n");
195  goto cleanup;
196  }
197 
198  Result = TRUE;
199 
200  /* Place backbuffer in the hidden part of framebuffer */
202 
203  /* Now check if we have to set the mode */
204  if (SetMode)
206 
207 cleanup:
208  if (ControlStart)
209  MmUnmapIoSpace((PVOID)ControlStart, ControlLength);
210 
211  /* Video is ready */
212  return Result;
213 }
214 
215 VOID
216 NTAPI
218 {
219  /* Just fill the screen black */
221 }
222 
223 VOID
224 NTAPI
226  _In_ BOOLEAN HalReset)
227 {
228  /* Clear the current position */
229  VidpCurrentX = 0;
230  VidpCurrentY = 0;
231 
232  /* Clear the screen with HAL if we were asked to */
233  if (HalReset)
234  HalResetDisplay();
235 
236  /* Re-initialize the palette and fill the screen black */
240 }
241 
242 VOID
243 NTAPI
245  _In_ PULONG Table,
246  _In_ ULONG Count)
247 {
248  PULONG Entry = Table;
249 
250  for (ULONG i = 0; i < Count; i++, Entry++)
251  {
252  CachedPalette[i] = *Entry | 0xFF000000;
253  }
254  ApplyPalette();
255 }
256 
257 VOID
259 {
260  /* Nothing to prepare */
261  NOTHING;
262 }
263 
264 VOID
266  _In_ ULONG Left,
267  _In_ ULONG Top,
268  _In_ UCHAR Color)
269 {
270  PUCHAR Back = BackBuffer + BB_OFFSET(Left, Top);
271  PULONG Frame = (PULONG)(FrameBufferStart + FB_OFFSET(Left, Top));
272 
273  *Back = Color;
274  *Frame = CachedPalette[Color];
275 }
276 
277 VOID
278 NTAPI
280  _In_ ULONG CurrentTop,
281  _In_ ULONG TopDelta,
282  _In_ BOOLEAN Restore)
283 {
284  PUCHAR NewPosition, OldPosition;
285 
286  /* Calculate the position in memory for the row */
287  if (Restore)
288  {
289  /* Restore the row by copying back the contents saved off-screen */
290  NewPosition = BackBuffer + BB_OFFSET(0, CurrentTop);
291  OldPosition = BackBuffer + BB_OFFSET(0, SCREEN_HEIGHT);
292  }
293  else
294  {
295  /* Preserve the row by saving its contents off-screen */
296  NewPosition = BackBuffer + BB_OFFSET(0, SCREEN_HEIGHT);
297  OldPosition = BackBuffer + BB_OFFSET(0, CurrentTop);
298  }
299 
300  /* Set the count and loop every pixel of backbuffer */
301  ULONG Count = TopDelta * SCREEN_WIDTH;
302 
303  RtlCopyMemory(NewPosition, OldPosition, Count);
304 
305  if (Restore)
306  {
307  NewPosition = BackBuffer + BB_OFFSET(0, CurrentTop);
308 
309  /* Set the count and loop every pixel of framebuffer */
310  for (ULONG y = 0; y < TopDelta; y++)
311  {
312  PULONG Frame = (PULONG)(FrameBufferStart + FB_OFFSET(0, CurrentTop + y));
313 
315  while (Count--)
316  {
317  *Frame++ = CachedPalette[*NewPosition++];
318  }
319  }
320  }
321 }
322 
323 VOID
324 NTAPI
326  _In_ ULONG Scroll)
327 {
328  ULONG RowSize = VidpScrollRegion[2] - VidpScrollRegion[0] + 1;
329 
330  /* Calculate the position in memory for the row */
331  PUCHAR OldPosition = BackBuffer + BB_OFFSET(VidpScrollRegion[0], VidpScrollRegion[1] + Scroll);
333 
334  /* Start loop */
335  for (ULONG Top = VidpScrollRegion[1]; Top <= VidpScrollRegion[3]; ++Top)
336  {
337  ULONG i;
338 
339  /* Scroll the row */
340  RtlCopyMemory(NewPosition, OldPosition, RowSize);
341 
343 
344  for (i = 0; i < RowSize; ++i)
345  Frame[i] = CachedPalette[NewPosition[i]];
346 
347  OldPosition += SCREEN_WIDTH;
348  NewPosition += SCREEN_WIDTH;
349  }
350 }
351 
352 VOID
353 NTAPI
355  _In_ CHAR Character,
356  _In_ ULONG Left,
357  _In_ ULONG Top,
358  _In_ ULONG TextColor,
359  _In_ ULONG BackColor)
360 {
361  /* Get the font and pixel pointer */
362  PUCHAR FontChar = GetFontPtr(Character);
363 
364  /* Loop each pixel height */
365  for (ULONG y = Top; y < Top + BOOTCHAR_HEIGHT; y++, FontChar += FONT_PTR_DELTA)
366  {
367  /* Loop each pixel width */
368  ULONG x = Left;
369 
370  for (UCHAR bit = 1 << (BOOTCHAR_WIDTH - 1); bit > 0; bit >>= 1, x++)
371  {
372  /* Check if we should draw this pixel */
373  if (*FontChar & bit)
374  {
375  /* We do, use the given Text Color */
376  SetPixel(x, y, (UCHAR)TextColor);
377  }
378  else if (BackColor < BV_COLOR_NONE)
379  {
380  /*
381  * This is a background pixel. We're drawing it
382  * unless it's transparent.
383  */
384  SetPixel(x, y, (UCHAR)BackColor);
385  }
386  }
387  }
388 }
389 
390 VOID
391 NTAPI
393  _In_ ULONG Left,
394  _In_ ULONG Top,
395  _In_ ULONG Right,
396  _In_ ULONG Bottom,
397  _In_ UCHAR Color)
398 {
399  while (Top <= Bottom)
400  {
401  PUCHAR Back = BackBuffer + BB_OFFSET(Left, Top);
402  PULONG Frame = (PULONG)(FrameBufferStart + FB_OFFSET(Left, Top));
403  ULONG L = Left;
404 
405  while (L++ <= Right)
406  {
407  *Back++ = Color;
408  *Frame++ = CachedPalette[Color];
409  }
410  Top++;
411  }
412 }
413 
414 VOID
415 NTAPI
418  _In_ ULONG Left,
419  _In_ ULONG Top,
420  _In_ ULONG Width,
421  _In_ ULONG Height,
422  _In_ ULONG Delta)
423 {
424  /* Clear the destination buffer */
425  RtlZeroMemory(Buffer, Delta * Height);
426 
427  /* Start the outer Y height loop */
428  for (ULONG y = 0; y < Height; y++)
429  {
430  /* Set current scanline */
431  PUCHAR Back = BackBuffer + BB_OFFSET(Left, Top + y);
432  PUCHAR Buf = Buffer + y * Delta;
433 
434  /* Start the X inner loop */
435  for (ULONG x = 0; x < Width; x += sizeof(USHORT))
436  {
437  /* Read the current value */
438  *Buf = (*Back++ & 0xF) << 4;
439  *Buf |= *Back++ & 0xF;
440  Buf++;
441  }
442  }
443 }
VOID SetPixel(_In_ ULONG Left, _In_ ULONG Top, _In_ UCHAR Color)
Definition: bootvid.c:265
#define HalResetDisplay
Definition: halfuncs.h:45
static RGBQUAD CachedPalette[BV_MAX_COLORS]
Definition: bootvid.c:21
ASMGENDATA Table[]
Definition: genincdata.c:61
#define NV2A_VIDEO_MEMORY_SIZE
Definition: xgpu.h:16
static UCHAR BytesPerPixel
Definition: bootvid.c:20
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
static PUCHAR BackBuffer
Definition: bootvid.c:22
#define TRUE
Definition: types.h:120
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
#define SCREEN_WIDTH
Definition: pc98video.c:27
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2373
#define FONT_PTR_DELTA
Definition: precomp.h:75
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1223
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
VOID PrepareForSetPixel(VOID)
Definition: bootvid.c:322
VOID NTAPI DisplayCharacter(_In_ CHAR Character, _In_ ULONG Left, _In_ ULONG Top, _In_ ULONG TextColor, _In_ ULONG BackColor)
Definition: bootvid.c:13
PVOID NTAPI MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: iosup.c:47
NTKERNELAPI ULONG NTAPI READ_REGISTER_ULONG(IN PULONG Register)
VOID NTAPI VidResetDisplay(_In_ BOOLEAN HalReset)
Definition: bootvid.c:220
struct Color Color
ULONG_PTR FrameBuffer
Definition: bootvid.c:15
static ULONG PanV
Definition: bootvid.c:19
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG VidpScrollRegion[4]
Definition: common.c:10
#define BOOTCHAR_HEIGHT
Definition: precomp.h:27
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
static UCHAR NvGetBytesPerPixel(ULONG Base, ULONG ScreenWidth)
Definition: bootvid.c:36
smooth NULL
Definition: ftsmooth.c:416
#define _Out_writes_bytes_(size)
Definition: no_sal2.h:370
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
VOID NTAPI VidCleanUp(VOID)
Definition: bootvid.c:246
Definition: bufpool.h:45
#define BV_COLOR_NONE
Definition: display.h:31
static ULONG FrameBufferHeight
Definition: bootvid.c:19
#define SCREEN_HEIGHT
Definition: pc98video.c:28
#define GetFontPtr(_Char)
Definition: precomp.h:74
static UCHAR NvGetCrtc(ULONG Base, UCHAR Index)
Definition: bootvid.c:27
ULONG RGBQUAD
Definition: precomp.h:50
ULONG VidpCurrentY
Definition: common.c:8
static ULONG PanH
Definition: bootvid.c:19
static const UCHAR Index[8]
Definition: usbohci.c:18
VOID NTAPI PreserveRow(_In_ ULONG CurrentTop, _In_ ULONG TopDelta, _In_ BOOLEAN Restore)
Definition: bootvid.c:107
VOID NTAPI InitPaletteWithTable(_In_ PULONG Table, _In_ ULONG Count)
Definition: bootvid.c:170
VOID NTAPI VidSolidColorFill(_In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Right, _In_ ULONG Bottom, _In_ UCHAR Color)
Definition: bootvid.c:274
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define BB_OFFSET(x, y)
Definition: xbox.h:15
unsigned char UCHAR
Definition: xmlstorage.h:181
VOID NTAPI VidScreenToBufferBlt(_Out_writes_bytes_(Delta *Height) PUCHAR Buffer, _In_ ULONG Left, _In_ ULONG Top, _In_ ULONG Width, _In_ ULONG Height, _In_ ULONG Delta)
Definition: bootvid.c:257
static const WCHAR L[]
Definition: oid.c:1250
#define NV2A_RAMDAC_FP_HVALID_END
Definition: xgpu.h:25
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define NOTHING
Definition: env_spec_w32.h:461
NTKERNELAPI UCHAR NTAPI READ_REGISTER_UCHAR(IN PUCHAR Register)
#define NV2A_CRTC_REGISTER_VALUE
Definition: xgpu.h:23
#define _In_
Definition: no_sal2.h:204
#define NV2A_RAMDAC_FP_VVALID_END
Definition: xgpu.h:26
static LPHIST_ENTRY Bottom
Definition: history.c:54
BOOLEAN NTAPI VidInitialize(_In_ BOOLEAN SetMode)
Definition: bootvid.c:184
unsigned short USHORT
Definition: pedump.c:61
ULONG FrameBufferSize
Definition: xboxvideo.c:29
#define NV2A_CRTC_REGISTER_INDEX
Definition: xgpu.h:22
VOID NTAPI MmUnmapIoSpace(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes)
Definition: iosup.c:193
static ULONG Delta
Definition: xboxvideo.c:33
static ULONG FrameBufferWidth
Definition: bootvid.c:19
static ULONG_PTR FrameBufferStart
Definition: bootvid.c:18
unsigned int * PULONG
Definition: retypes.h:1
#define NV2A_CRTC_FRAMEBUFFER_START
Definition: xgpu.h:21
static ULONG ScreenWidth
Definition: pcvideo.c:114
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
#define BV_COLOR_BLACK
Definition: display.h:15
VOID NTAPI DoScroll(_In_ ULONG Scroll)
Definition: bootvid.c:59
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
char * cleanup(char *str)
Definition: wpickclick.c:99
static LPHIST_ENTRY Top
Definition: history.c:53
NTKERNELAPI VOID NTAPI WRITE_REGISTER_UCHAR(IN PUCHAR Register, IN UCHAR Value)
#define BOOTCHAR_WIDTH
Definition: precomp.h:28
#define FB_OFFSET(x, y)
Definition: pc98.h:17
base of all file and directory entries
Definition: entries.h:82
ULONG VidpCurrentX
Definition: common.c:7
LONGLONG QuadPart
Definition: typedefs.h:114
static VOID ApplyPalette(VOID)
Definition: bootvid.c:56
#define BV_MAX_COLORS
Definition: display.h:32
#define InitializePalette()
Definition: precomp.h:68