1 #include "precomp.h" 2 3 /* GLOBALS *******************************************************************/ 4 5 static UCHAR lMaskTable[8] = 6 { 7 (1 << 8) - (1 << 0), 8 (1 << 7) - (1 << 0), 9 (1 << 6) - (1 << 0), 10 (1 << 5) - (1 << 0), 11 (1 << 4) - (1 << 0), 12 (1 << 3) - (1 << 0), 13 (1 << 2) - (1 << 0), 14 (1 << 1) - (1 << 0) 15 }; 16 static UCHAR rMaskTable[8] = 17 { 18 (1 << 7), 19 (1 << 7) + (1 << 6), 20 (1 << 7) + (1 << 6) + (1 << 5), 21 (1 << 7) + (1 << 6) + (1 << 5) + (1 << 4), 22 (1 << 7) + (1 << 6) + (1 << 5) + (1 << 4) + (1 << 3), 23 (1 << 7) + (1 << 6) + (1 << 5) + (1 << 4) + (1 << 3) + (1 << 2), 24 (1 << 7) + (1 << 6) + (1 << 5) + (1 << 4) + (1 << 3) + (1 << 2) + (1 << 1), 25 (1 << 7) + (1 << 6) + (1 << 5) + (1 << 4) + (1 << 3) + (1 << 2) + (1 << 1) + (1 << 0), 26 }; 27 UCHAR PixelMask[8] = 28 { 29 (1 << 7), 30 (1 << 6), 31 (1 << 5), 32 (1 << 4), 33 (1 << 3), 34 (1 << 2), 35 (1 << 1), 36 (1 << 0), 37 }; 38 static ULONG lookup[16] = 39 { 40 0x0000, 41 0x0100, 42 0x1000, 43 0x1100, 44 0x0001, 45 0x0101, 46 0x1001, 47 0x1101, 48 0x0010, 49 0x0110, 50 0x1010, 51 0x1110, 52 0x0011, 53 0x0111, 54 0x1011, 55 0x1111, 56 }; 57 58 ULONG_PTR VgaRegisterBase = 0; 59 ULONG_PTR VgaBase = 0; 60 61 /* PRIVATE FUNCTIONS *********************************************************/ 62 63 static VOID 64 NTAPI 65 ReadWriteMode( 66 _In_ UCHAR Mode) 67 { 68 UCHAR Value; 69 70 /* Switch to graphics mode register */ 71 __outpb(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, IND_GRAPH_MODE); 72 73 /* Get the current register value, minus the current mode */ 74 Value = __inpb(VGA_BASE_IO_PORT + GRAPH_DATA_PORT) & 0xF4; 75 76 /* Set the new mode */ 77 __outpb(VGA_BASE_IO_PORT + GRAPH_DATA_PORT, Mode | Value); 78 } 79 80 VOID 81 PrepareForSetPixel(VOID) 82 { 83 /* Switch to mode 10 */ 84 ReadWriteMode(10); 85 86 /* Clear the 4 planes (we're already in unchained mode here) */ 87 __outpw(VGA_BASE_IO_PORT + SEQ_ADDRESS_PORT, 0x0F02); 88 89 /* Select the color don't care register */ 90 __outpw(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, 7); 91 } 92 93 #define SET_PIXELS(_PixelPtr, _PixelMask, _TextColor) \ 94 do { \ 95 /* Select the bitmask register and write the mask */ \ 96 __outpw(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, ((_PixelMask) << 8) | IND_BIT_MASK); \ 97 /* Set the new color */ \ 98 WRITE_REGISTER_UCHAR((_PixelPtr), (UCHAR)(_TextColor)); \ 99 } while (0); 100 101 VOID 102 NTAPI 103 DisplayCharacter( 104 _In_ CHAR Character, 105 _In_ ULONG Left, 106 _In_ ULONG Top, 107 _In_ ULONG TextColor, 108 _In_ ULONG BackColor) 109 { 110 PUCHAR FontChar, PixelPtr; 111 ULONG Height; 112 UCHAR Shift; 113 114 PrepareForSetPixel(); 115 116 /* Calculate shift */ 117 Shift = Left & 7; 118 119 /* Get the font and pixel pointer */ 120 FontChar = GetFontPtr(Character); 121 PixelPtr = (PUCHAR)(VgaBase + (Left >> 3) + (Top * (SCREEN_WIDTH / 8))); 122 123 /* Loop all pixel rows */ 124 for (Height = BOOTCHAR_HEIGHT; Height > 0; --Height) 125 { 126 SET_PIXELS(PixelPtr, *FontChar >> Shift, TextColor); 127 PixelPtr += (SCREEN_WIDTH / 8); 128 FontChar += FONT_PTR_DELTA; 129 } 130 131 /* Check if we need to update neighbor bytes */ 132 if (Shift) 133 { 134 /* Calculate shift for 2nd byte */ 135 Shift = 8 - Shift; 136 137 /* Get the font and pixel pointer (2nd byte) */ 138 FontChar = GetFontPtr(Character); 139 PixelPtr = (PUCHAR)(VgaBase + (Left >> 3) + (Top * (SCREEN_WIDTH / 8)) + 1); 140 141 /* Loop all pixel rows */ 142 for (Height = BOOTCHAR_HEIGHT; Height > 0; --Height) 143 { 144 SET_PIXELS(PixelPtr, *FontChar << Shift, TextColor); 145 PixelPtr += (SCREEN_WIDTH / 8); 146 FontChar += FONT_PTR_DELTA; 147 } 148 } 149 150 /* Check if the background color is transparent */ 151 if (BackColor >= BV_COLOR_NONE) 152 { 153 /* We are done */ 154 return; 155 } 156 157 /* Calculate shift */ 158 Shift = Left & 7; 159 160 /* Get the font and pixel pointer */ 161 FontChar = GetFontPtr(Character); 162 PixelPtr = (PUCHAR)(VgaBase + (Left >> 3) + (Top * (SCREEN_WIDTH / 8))); 163 164 /* Loop all pixel rows */ 165 for (Height = BOOTCHAR_HEIGHT; Height > 0; --Height) 166 { 167 SET_PIXELS(PixelPtr, ~*FontChar >> Shift, BackColor); 168 PixelPtr += (SCREEN_WIDTH / 8); 169 FontChar += FONT_PTR_DELTA; 170 } 171 172 /* Check if we need to update neighbor bytes */ 173 if (Shift) 174 { 175 /* Calculate shift for 2nd byte */ 176 Shift = 8 - Shift; 177 178 /* Get the font and pixel pointer (2nd byte) */ 179 FontChar = GetFontPtr(Character); 180 PixelPtr = (PUCHAR)(VgaBase + (Left >> 3) + (Top * (SCREEN_WIDTH / 8)) + 1); 181 182 /* Loop all pixel rows */ 183 for (Height = BOOTCHAR_HEIGHT; Height > 0; --Height) 184 { 185 SET_PIXELS(PixelPtr, ~*FontChar << Shift, BackColor); 186 PixelPtr += (SCREEN_WIDTH / 8); 187 FontChar += FONT_PTR_DELTA; 188 } 189 } 190 } 191 192 static VOID 193 NTAPI 194 SetPaletteEntryRGB( 195 _In_ ULONG Id, 196 _In_ RGBQUAD Rgb) 197 { 198 /* Set the palette index */ 199 __outpb(VGA_BASE_IO_PORT + DAC_ADDRESS_WRITE_PORT, (UCHAR)Id); 200 201 /* Set RGB colors */ 202 __outpb(VGA_BASE_IO_PORT + DAC_DATA_REG_PORT, GetRValue(Rgb) >> 2); 203 __outpb(VGA_BASE_IO_PORT + DAC_DATA_REG_PORT, GetGValue(Rgb) >> 2); 204 __outpb(VGA_BASE_IO_PORT + DAC_DATA_REG_PORT, GetBValue(Rgb) >> 2); 205 } 206 207 VOID 208 NTAPI 209 InitPaletteWithTable( 210 _In_ PULONG Table, 211 _In_ ULONG Count) 212 { 213 ULONG i; 214 PULONG Entry = Table; 215 216 for (i = 0; i < Count; i++, Entry++) 217 { 218 SetPaletteEntryRGB(i, *Entry); 219 } 220 } 221 222 VOID 223 NTAPI 224 DoScroll( 225 _In_ ULONG Scroll) 226 { 227 ULONG Top, RowSize; 228 PUCHAR OldPosition, NewPosition; 229 230 /* Clear the 4 planes */ 231 __outpw(VGA_BASE_IO_PORT + SEQ_ADDRESS_PORT, 0x0F02); 232 233 /* Set the bitmask to 0xFF for all 4 planes */ 234 __outpw(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, 0xFF08); 235 236 /* Set Mode 1 */ 237 ReadWriteMode(1); 238 239 RowSize = (VidpScrollRegion[2] - VidpScrollRegion[0] + 1) / 8; 240 241 /* Calculate the position in memory for the row */ 242 OldPosition = (PUCHAR)(VgaBase + (VidpScrollRegion[1] + Scroll) * (SCREEN_WIDTH / 8) + VidpScrollRegion[0] / 8); 243 NewPosition = (PUCHAR)(VgaBase + VidpScrollRegion[1] * (SCREEN_WIDTH / 8) + VidpScrollRegion[0] / 8); 244 245 /* Start loop */ 246 for (Top = VidpScrollRegion[1]; Top <= VidpScrollRegion[3]; ++Top) 247 { 248 #if defined(_M_IX86) || defined(_M_AMD64) 249 __movsb(NewPosition, OldPosition, RowSize); 250 #else 251 ULONG i; 252 253 /* Scroll the row */ 254 for (i = 0; i < RowSize; ++i) 255 WRITE_REGISTER_UCHAR(NewPosition + i, READ_REGISTER_UCHAR(OldPosition + i)); 256 #endif 257 OldPosition += (SCREEN_WIDTH / 8); 258 NewPosition += (SCREEN_WIDTH / 8); 259 } 260 } 261 262 VOID 263 NTAPI 264 PreserveRow( 265 _In_ ULONG CurrentTop, 266 _In_ ULONG TopDelta, 267 _In_ BOOLEAN Restore) 268 { 269 PUCHAR Position1, Position2; 270 ULONG Count; 271 272 /* Clear the 4 planes */ 273 __outpw(VGA_BASE_IO_PORT + SEQ_ADDRESS_PORT, 0x0F02); 274 275 /* Set the bitmask to 0xFF for all 4 planes */ 276 __outpw(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, 0xFF08); 277 278 /* Set Mode 1 */ 279 ReadWriteMode(1); 280 281 /* Calculate the position in memory for the row */ 282 if (Restore) 283 { 284 /* Restore the row by copying back the contents saved off-screen */ 285 Position1 = (PUCHAR)(VgaBase + CurrentTop * (SCREEN_WIDTH / 8)); 286 Position2 = (PUCHAR)(VgaBase + SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); 287 } 288 else 289 { 290 /* Preserve the row by saving its contents off-screen */ 291 Position1 = (PUCHAR)(VgaBase + SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); 292 Position2 = (PUCHAR)(VgaBase + CurrentTop * (SCREEN_WIDTH / 8)); 293 } 294 295 /* Set the count and loop every pixel */ 296 Count = TopDelta * (SCREEN_WIDTH / 8); 297 #if defined(_M_IX86) || defined(_M_AMD64) 298 __movsb(Position1, Position2, Count); 299 #else 300 while (Count--) 301 { 302 /* Write the data back on the other position */ 303 WRITE_REGISTER_UCHAR(Position1, READ_REGISTER_UCHAR(Position2)); 304 305 /* Increase both positions */ 306 Position1++; 307 Position2++; 308 } 309 #endif 310 } 311 312 /* PUBLIC FUNCTIONS **********************************************************/ 313 314 /* 315 * @implemented 316 */ 317 VOID 318 NTAPI 319 VidCleanUp(VOID) 320 { 321 /* Select bit mask register and clear it */ 322 __outpb(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, IND_BIT_MASK); 323 __outpb(VGA_BASE_IO_PORT + GRAPH_DATA_PORT, BIT_MASK_DEFAULT); 324 } 325 326 /* 327 * @implemented 328 */ 329 VOID 330 NTAPI 331 VidScreenToBufferBlt( 332 _Out_ PUCHAR Buffer, 333 _In_ ULONG Left, 334 _In_ ULONG Top, 335 _In_ ULONG Width, 336 _In_ ULONG Height, 337 _In_ ULONG Delta) 338 { 339 ULONG Plane; 340 ULONG XDistance; 341 ULONG LeftDelta, RightDelta; 342 ULONG PixelOffset; 343 PUCHAR PixelPosition; 344 PUCHAR k, i; 345 PULONG m; 346 UCHAR Value, Value2; 347 UCHAR a; 348 ULONG b; 349 ULONG x, y; 350 351 /* Calculate total distance to copy on X */ 352 XDistance = Left + Width - 1; 353 354 /* Calculate the 8-byte left and right deltas */ 355 LeftDelta = Left & 7; 356 RightDelta = 8 - LeftDelta; 357 358 /* Clear the destination buffer */ 359 RtlZeroMemory(Buffer, Delta * Height); 360 361 /* Calculate the pixel offset and convert the X distance into byte form */ 362 PixelOffset = Top * (SCREEN_WIDTH / 8) + (Left >> 3); 363 XDistance >>= 3; 364 365 /* Loop the 4 planes */ 366 for (Plane = 0; Plane < 4; ++Plane) 367 { 368 /* Set the current pixel position and reset buffer loop variable */ 369 PixelPosition = (PUCHAR)(VgaBase + PixelOffset); 370 i = Buffer; 371 372 /* Set Mode 0 */ 373 ReadWriteMode(0); 374 375 /* Set the current plane */ 376 __outpw(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, (Plane << 8) | IND_READ_MAP); 377 378 /* Start the outer Y height loop */ 379 for (y = Height; y > 0; --y) 380 { 381 /* Read the current value */ 382 m = (PULONG)i; 383 Value = READ_REGISTER_UCHAR(PixelPosition); 384 385 /* Set Pixel Position loop variable */ 386 k = PixelPosition + 1; 387 388 /* Check if we're still within bounds */ 389 if (Left <= XDistance) 390 { 391 /* Start the X inner loop */ 392 for (x = (XDistance - Left) + 1; x > 0; --x) 393 { 394 /* Read the current value */ 395 Value2 = READ_REGISTER_UCHAR(k); 396 397 /* Increase pixel position */ 398 k++; 399 400 /* Do the blt */ 401 a = Value2 >> (UCHAR)RightDelta; 402 a |= Value << (UCHAR)LeftDelta; 403 b = lookup[a & 0xF]; 404 a >>= 4; 405 b <<= 16; 406 b |= lookup[a]; 407 408 /* Save new value to buffer */ 409 *m |= (b << Plane); 410 411 /* Move to next destination location */ 412 m++; 413 414 /* Write new value */ 415 Value = Value2; 416 } 417 } 418 419 /* Update pixel position */ 420 PixelPosition += (SCREEN_WIDTH / 8); 421 i += Delta; 422 } 423 } 424 } 425 426 /* 427 * @implemented 428 */ 429 VOID 430 NTAPI 431 VidSolidColorFill( 432 _In_ ULONG Left, 433 _In_ ULONG Top, 434 _In_ ULONG Right, 435 _In_ ULONG Bottom, 436 _In_ UCHAR Color) 437 { 438 ULONG rMask, lMask; 439 ULONG LeftOffset, RightOffset, Distance; 440 PUCHAR Offset; 441 ULONG i, j; 442 443 /* Get the left and right masks, shifts, and delta */ 444 LeftOffset = Left >> 3; 445 lMask = (lMaskTable[Left & 0x7] << 8) | IND_BIT_MASK; 446 RightOffset = Right >> 3; 447 rMask = (rMaskTable[Right & 0x7] << 8) | IND_BIT_MASK; 448 Distance = RightOffset - LeftOffset; 449 450 /* If there is no distance, then combine the right and left masks */ 451 if (!Distance) lMask &= rMask; 452 453 PrepareForSetPixel(); 454 455 /* Calculate pixel position for the read */ 456 Offset = (PUCHAR)(VgaBase + (Top * (SCREEN_WIDTH / 8)) + LeftOffset); 457 458 /* Select the bitmask register and write the mask */ 459 __outpw(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, (USHORT)lMask); 460 461 /* Check if the top coord is below the bottom one */ 462 if (Top <= Bottom) 463 { 464 /* Start looping each line */ 465 for (i = (Bottom - Top) + 1; i > 0; --i) 466 { 467 /* Read the previous value and add our color */ 468 WRITE_REGISTER_UCHAR(Offset, READ_REGISTER_UCHAR(Offset) & Color); 469 470 /* Move to the next line */ 471 Offset += (SCREEN_WIDTH / 8); 472 } 473 } 474 475 /* Check if we have a delta */ 476 if (Distance > 0) 477 { 478 /* Calculate new pixel position */ 479 Offset = (PUCHAR)(VgaBase + (Top * (SCREEN_WIDTH / 8)) + RightOffset); 480 Distance--; 481 482 /* Select the bitmask register and write the mask */ 483 __outpw(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, (USHORT)rMask); 484 485 /* Check if the top coord is below the bottom one */ 486 if (Top <= Bottom) 487 { 488 /* Start looping each line */ 489 for (i = (Bottom - Top) + 1; i > 0; --i) 490 { 491 /* Read the previous value and add our color */ 492 WRITE_REGISTER_UCHAR(Offset, READ_REGISTER_UCHAR(Offset) & Color); 493 494 /* Move to the next line */ 495 Offset += (SCREEN_WIDTH / 8); 496 } 497 } 498 499 /* Check if we still have a delta */ 500 if (Distance > 0) 501 { 502 /* Calculate new pixel position */ 503 Offset = (PUCHAR)(VgaBase + (Top * (SCREEN_WIDTH / 8)) + LeftOffset + 1); 504 505 /* Set the bitmask to 0xFF for all 4 planes */ 506 __outpw(VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT, 0xFF08); 507 508 /* Check if the top coord is below the bottom one */ 509 if (Top <= Bottom) 510 { 511 /* Start looping each line */ 512 for (i = (Bottom - Top) + 1; i > 0; --i) 513 { 514 /* Loop the shift delta */ 515 for (j = Distance; j > 0; Offset++, --j) 516 { 517 /* Write the color */ 518 WRITE_REGISTER_UCHAR(Offset, Color); 519 } 520 521 /* Update position in memory */ 522 Offset += ((SCREEN_WIDTH / 8) - Distance); 523 } 524 } 525 } 526 } 527 } 528