[FREELDR][XBOXVMP] Retrieve screen resolution directly from NV2A GPU (#1962)
[reactos.git] / boot / freeldr / freeldr / arch / i386 / xboxvideo.c
1 /*
2 * FreeLoader
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Note: much of this code was based on knowledge and/or code developed
19 * by the Xbox Linux group: http://www.xbox-linux.org
20 */
21
22 #include <freeldr.h>
23 #include <debug.h>
24
25 DBG_DEFAULT_CHANNEL(UI);
26
27 PVOID FrameBuffer;
28 ULONG FrameBufferSize;
29 static ULONG ScreenWidth;
30 static ULONG ScreenHeight;
31 static ULONG BytesPerPixel;
32 static ULONG Delta;
33
34 #define CHAR_WIDTH 8
35 #define CHAR_HEIGHT 16
36
37 #define TOP_BOTTOM_LINES 0
38
39 #define FB_SIZE_MB 4
40
41 #define MAKE_COLOR(Red, Green, Blue) (0xff000000 | (((Red) & 0xff) << 16) | (((Green) & 0xff) << 8) | ((Blue) & 0xff))
42
43 static VOID
44 XboxVideoOutputChar(UCHAR Char, unsigned X, unsigned Y, ULONG FgColor, ULONG BgColor)
45 {
46 PUCHAR FontPtr;
47 PULONG Pixel;
48 UCHAR Mask;
49 unsigned Line;
50 unsigned Col;
51
52 FontPtr = XboxFont8x16 + Char * 16;
53 Pixel = (PULONG) ((char *) FrameBuffer + (Y * CHAR_HEIGHT + TOP_BOTTOM_LINES) * Delta
54 + X * CHAR_WIDTH * BytesPerPixel);
55 for (Line = 0; Line < CHAR_HEIGHT; Line++)
56 {
57 Mask = 0x80;
58 for (Col = 0; Col < CHAR_WIDTH; Col++)
59 {
60 Pixel[Col] = (0 != (FontPtr[Line] & Mask) ? FgColor : BgColor);
61 Mask = Mask >> 1;
62 }
63 Pixel = (PULONG) ((char *) Pixel + Delta);
64 }
65 }
66
67 static ULONG
68 XboxVideoAttrToSingleColor(UCHAR Attr)
69 {
70 UCHAR Intensity;
71
72 Intensity = (0 == (Attr & 0x08) ? 127 : 255);
73
74 return 0xff000000 |
75 (0 == (Attr & 0x04) ? 0 : (Intensity << 16)) |
76 (0 == (Attr & 0x02) ? 0 : (Intensity << 8)) |
77 (0 == (Attr & 0x01) ? 0 : Intensity);
78 }
79
80 static VOID
81 XboxVideoAttrToColors(UCHAR Attr, ULONG *FgColor, ULONG *BgColor)
82 {
83 *FgColor = XboxVideoAttrToSingleColor(Attr & 0xf);
84 *BgColor = XboxVideoAttrToSingleColor((Attr >> 4) & 0xf);
85 }
86
87 static VOID
88 XboxVideoClearScreenColor(ULONG Color, BOOLEAN FullScreen)
89 {
90 ULONG Line, Col;
91 PULONG p;
92
93 for (Line = 0; Line < ScreenHeight - (FullScreen ? 0 : 2 * TOP_BOTTOM_LINES); Line++)
94 {
95 p = (PULONG) ((char *) FrameBuffer + (Line + (FullScreen ? 0 : TOP_BOTTOM_LINES)) * Delta);
96 for (Col = 0; Col < ScreenWidth; Col++)
97 {
98 *p++ = Color;
99 }
100 }
101 }
102
103 VOID
104 XboxVideoClearScreen(UCHAR Attr)
105 {
106 ULONG FgColor, BgColor;
107
108 XboxVideoAttrToColors(Attr, &FgColor, &BgColor);
109
110 XboxVideoClearScreenColor(BgColor, FALSE);
111 }
112
113 VOID
114 XboxVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
115 {
116 ULONG FgColor, BgColor;
117
118 XboxVideoAttrToColors(Attr, &FgColor, &BgColor);
119
120 XboxVideoOutputChar(Ch, X, Y, FgColor, BgColor);
121 }
122
123 UCHAR
124 NvGetCrtc(UCHAR Index)
125 {
126 *((PUCHAR) NV2A_CRTC_REGISTER_INDEX) = Index;
127 return *((PUCHAR) NV2A_CRTC_REGISTER_VALUE);
128 }
129
130 VOID
131 XboxVideoInit(VOID)
132 {
133 /* Reuse framebuffer that was set up by firmware */
134 FrameBuffer = (PVOID)*((PULONG) NV2A_CRTC_FRAMEBUFFER_START);
135 /* Verify that framebuffer address is page-aligned */
136 ASSERT((ULONG_PTR)FrameBuffer % PAGE_SIZE == 0);
137
138 /* FIXME: obtain fb size from firmware somehow (Cromwell reserves high 4 MB of RAM) */
139 FrameBufferSize = 4 * 1024 * 1024;
140
141 ScreenWidth = *((PULONG) NV2A_RAMDAC_FP_HVALID_END) + 1;
142 ScreenHeight = *((PULONG) NV2A_RAMDAC_FP_VVALID_END) + 1;
143 /* Get BPP directly from NV2A CRTC (magic constants are from Cromwell) */
144 BytesPerPixel = 8 * (((NvGetCrtc(0x19) & 0xE0) << 3) | (NvGetCrtc(0x13) & 0xFF)) / ScreenWidth;
145 if (BytesPerPixel == 4)
146 {
147 ASSERT((NvGetCrtc(0x28) & 0xF) == BytesPerPixel - 1);
148 }
149 else
150 {
151 ASSERT((NvGetCrtc(0x28) & 0xF) == BytesPerPixel);
152 }
153 Delta = (ScreenWidth * BytesPerPixel + 3) & ~ 0x3;
154
155 /* Verify screen resolution */
156 ASSERT(ScreenWidth > 1);
157 ASSERT(ScreenHeight > 1);
158 ASSERT(BytesPerPixel >= 1 && BytesPerPixel <= 4);
159 /* Verify that screen fits framebuffer size */
160 ASSERT(ScreenWidth * ScreenHeight * BytesPerPixel <= FrameBufferSize);
161
162 XboxVideoClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE);
163 }
164
165 VIDEODISPLAYMODE
166 XboxVideoSetDisplayMode(char *DisplayMode, BOOLEAN Init)
167 {
168 /* We only have one mode, semi-text */
169 return VideoTextMode;
170 }
171
172 VOID
173 XboxVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth)
174 {
175 *Width = ScreenWidth / CHAR_WIDTH;
176 *Height = (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT;
177 *Depth = 0;
178 }
179
180 ULONG
181 XboxVideoGetBufferSize(VOID)
182 {
183 return (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT * (ScreenWidth / CHAR_WIDTH) * 2;
184 }
185
186 VOID
187 XboxVideoGetFontsFromFirmware(PULONG RomFontPointers)
188 {
189 TRACE("XboxVideoGetFontsFromFirmware(): UNIMPLEMENTED\n");
190 }
191
192 VOID
193 XboxVideoSetTextCursorPosition(UCHAR X, UCHAR Y)
194 {
195 /* We don't have a cursor yet */
196 }
197
198 VOID
199 XboxVideoHideShowTextCursor(BOOLEAN Show)
200 {
201 /* We don't have a cursor yet */
202 }
203
204 VOID
205 XboxVideoCopyOffScreenBufferToVRAM(PVOID Buffer)
206 {
207 PUCHAR OffScreenBuffer = (PUCHAR) Buffer;
208 ULONG Col, Line;
209
210 for (Line = 0; Line < (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT; Line++)
211 {
212 for (Col = 0; Col < ScreenWidth / CHAR_WIDTH; Col++)
213 {
214 XboxVideoPutChar(OffScreenBuffer[0], OffScreenBuffer[1], Col, Line);
215 OffScreenBuffer += 2;
216 }
217 }
218 }
219
220 BOOLEAN
221 XboxVideoIsPaletteFixed(VOID)
222 {
223 return FALSE;
224 }
225
226 VOID
227 XboxVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue)
228 {
229 /* Not supported */
230 }
231
232 VOID
233 XboxVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue)
234 {
235 /* Not supported */
236 }
237
238 VOID
239 XboxVideoSync(VOID)
240 {
241 /* Not supported */
242 }
243
244 VOID
245 XboxBeep(VOID)
246 {
247 /* Call PC version */
248 PcBeep();
249 }
250
251 VOID
252 XboxVideoPrepareForReactOS(VOID)
253 {
254 XboxVideoClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE);
255 XboxVideoHideShowTextCursor(FALSE);
256 }
257
258 /* EOF */