3 /* GLOBALS *******************************************************************/
5 ULONG ScrollRegion
[4] =
27 (1 << 7)+ (1 << 6) + (1 << 5),
28 (1 << 7)+ (1 << 6) + (1 << 5) + (1 << 4),
29 (1 << 7)+ (1 << 6) + (1 << 5) + (1 << 4) + (1 << 3),
30 (1 << 7)+ (1 << 6) + (1 << 5) + (1 << 4) + (1 << 3) + (1 << 2),
31 (1 << 7)+ (1 << 6) + (1 << 5) + (1 << 4) + (1 << 3) + (1 << 2) + (1 << 1),
32 (1 << 7)+ (1 << 6) + (1 << 5) + (1 << 4) + (1 << 3) + (1 << 2) + (1 << 1) +
66 ULONG TextColor
= 0xF;
69 BOOLEAN NextLine
= FALSE
;
70 ULONG_PTR VgaRegisterBase
= 0;
71 ULONG_PTR VgaBase
= 0;
73 /* PRIVATE FUNCTIONS *********************************************************/
77 ReadWriteMode(UCHAR Mode
)
81 /* Switch to graphics mode register */
82 WRITE_PORT_UCHAR((PUCHAR
)VgaRegisterBase
+ 0x3CE, 5);
84 /* Get the current register value, minus the current mode */
85 Value
= READ_PORT_UCHAR((PUCHAR
)VgaRegisterBase
+ 0x3CF) & 0xF4;
87 /* Set the new mode */
88 WRITE_PORT_UCHAR((PUCHAR
)VgaRegisterBase
+ 0x3CF, Mode
| Value
);
93 __outpb(IN ULONG Port
,
96 /* Write to the VGA Register */
97 WRITE_PORT_UCHAR((PUCHAR
)VgaRegisterBase
+ Port
, (UCHAR
)Value
);
102 __outpw(IN ULONG Port
,
105 /* Write to the VGA Register */
106 WRITE_PORT_USHORT((PUSHORT
)(VgaRegisterBase
+ Port
), (USHORT
)Value
);
111 SetPixel(IN ULONG Left
,
115 PUCHAR PixelPosition
;
117 /* Calculate the pixel position. */
118 PixelPosition
= (PUCHAR
)VgaBase
+ (Left
>> 3) + (Top
* 80);
120 /* Switch to mode 10 */
123 /* Clear the 4 planes (we're already in unchained mode here) */
124 __outpw(0x3C4, 0xF02);
126 /* Select the color don't care register */
129 /* Select the bitmask register and write the mask */
130 __outpw(0x3CE, (PixelMask
[Left
& 7] << 8) | 8);
132 /* Read the current pixel value and add our color */
133 WRITE_REGISTER_UCHAR(PixelPosition
,
134 READ_REGISTER_UCHAR(PixelPosition
) & Color
);
139 DisplayCharacter(CHAR Character
,
148 /* Get the font line for this character */
149 FontChar
= &FontData
[Character
* BOOTCHAR_HEIGHT
];
151 /* Loop each pixel height */
155 /* Loop each pixel width */
160 /* Check if we should draw this pixel */
161 #ifdef CHAR_GEN_UPSIDE_DOWN
162 if (FontChar
[i
] & (UCHAR
)j
)
164 /* Normal character generator (top of char is first element) */
165 if (FontChar
[BOOTCHAR_HEIGHT
- i
] & (UCHAR
)j
)
168 /* We do, use the given Text Color */
169 SetPixel(XOffset
, Top
, (UCHAR
)TextColor
);
171 else if (BackTextColor
< 16)
173 /* This is a background pixel. */
174 /* We're drawing it unless it's transparent. */
175 SetPixel(XOffset
, Top
, (UCHAR
)BackTextColor
);
178 /* Increase X Offset */
182 /* Move to the next Y ordinate */
189 DisplayStringXY(PUCHAR String
,
195 /* Loop every character */
198 /* Display a character */
199 DisplayCharacter(*String
, Left
, Top
, TextColor
, BackColor
);
201 /* Move to next character and next position */
209 SetPaletteEntryRGB(IN ULONG Id
,
212 PCHAR Colors
= (PCHAR
)&Rgb
;
214 /* Set the palette index */
215 __outpb(0x3C8, (UCHAR
)Id
);
218 __outpb(0x3C9, Colors
[2] >> 2);
219 __outpb(0x3C9, Colors
[1] >> 2);
220 __outpb(0x3C9, Colors
[0] >> 2);
225 InitPaletteWithTable(IN PULONG Table
,
229 PULONG Entry
= Table
;
231 /* Loop every entry */
232 for (i
= 0; i
< Count
; i
++, Entry
++)
235 SetPaletteEntryRGB(i
, *Entry
);
241 SetPaletteEntry(IN ULONG Id
,
242 IN ULONG PaletteEntry
)
244 /* Set the palette index */
245 __outpb(0x3C8, (UCHAR
)Id
);
248 __outpb(0x3C9, PaletteEntry
& 0xFF);
249 __outpb(0x3C9, (PaletteEntry
>>= 8) & 0xFF);
250 __outpb(0x3C9, (PaletteEntry
>> 8) & 0xFF);
255 InitializePalette(VOID
)
257 ULONG PaletteEntry
[16] = {0,
275 /* Loop all the entries and set their palettes */
276 for (i
= 0; i
< 16; i
++) SetPaletteEntry(i
, PaletteEntry
[i
]);
281 VgaScroll(ULONG Scroll
)
284 ULONG SourceOffset
, DestOffset
;
288 /* Set memory positions of the scroll */
289 SourceOffset
= VgaBase
+ (ScrollRegion
[1] * 80) + (ScrollRegion
[0] >> 3);
290 DestOffset
= SourceOffset
+ (Scroll
* 80);
292 /* Clear the 4 planes */
293 __outpw(0x3C4, 0xF02);
295 /* Set the bitmask to 0xFF for all 4 planes */
296 __outpw(0x3CE, 0xFF08);
301 /* Save top and check if it's above the bottom */
302 Top
= ScrollRegion
[1];
303 if (Top
> ScrollRegion
[3]) return;
308 /* Set number of bytes to loop and start offset */
309 Offset
= ScrollRegion
[0] >> 3;
312 /* Check if this is part of the scroll region */
313 if (Offset
<= (ScrollRegion
[2] >> 3))
315 /* Update position */
316 i
= DestOffset
- SourceOffset
;
318 /* Loop the X axis */
321 /* Write value in the new position so that we can do the scroll */
322 WRITE_REGISTER_UCHAR((PUCHAR
)j
,
323 READ_REGISTER_UCHAR((PUCHAR
)j
+ i
));
325 /* Move to the next memory location to write to */
328 /* Move to the next byte in the region */
331 /* Make sure we don't go past the scroll region */
332 } while (Offset
<= (ScrollRegion
[2] >> 3));
335 /* Move to the next line */
342 /* Make sure we don't go past the scroll region */
343 } while (Top
<= ScrollRegion
[3]);
348 PreserveRow(IN ULONG CurrentTop
,
350 IN BOOLEAN Direction
)
352 PUCHAR Position1
, Position2
;
355 /* Clear the 4 planes */
356 __outpw(0x3C4, 0xF02);
358 /* Set the bitmask to 0xFF for all 4 planes */
359 __outpw(0x3CE, 0xFF08);
364 /* Check which way we're preserving */
367 /* Calculate the position in memory for the row */
368 Position1
= (PUCHAR
)VgaBase
+ CurrentTop
* 80;
369 Position2
= (PUCHAR
)VgaBase
+ 0x9600;
373 /* Calculate the position in memory for the row */
374 Position1
= (PUCHAR
)VgaBase
+ 0x9600;
375 Position2
= (PUCHAR
)VgaBase
+ CurrentTop
* 80;
378 /* Set the count and make sure it's above 0 */
379 Count
= TopDelta
* 80;
382 /* Loop every pixel */
385 /* Write the data back on the other position */
386 WRITE_REGISTER_UCHAR(Position1
, READ_REGISTER_UCHAR(Position2
));
388 /* Increase both positions */
397 BitBlt(IN ULONG Left
,
402 IN ULONG BitsPerPixel
,
405 ULONG LeftAnd
, LeftShifted
, LeftPlusOne
, LeftPos
;
409 ULONG DistanceMinusLeftBpp
;
410 ULONG SomeYesNoFlag
, SomeYesNoFlag2
;
411 PUCHAR PixelPosition
, m
;
420 UCHAR pMask
, PlaneShift
;
424 /* Check if the buffer isn't 4bpp */
425 if (BitsPerPixel
!= 4)
428 DbgPrint("Unhandled BitBlt\n"
429 "%lxx%lx @ (%lx,%lx)\n"
430 "Bits Per Pixel %lx\n"
431 "Buffer: %p. Delta: %lx\n",
442 /* Get the masks and other values */
443 LeftAnd
= Left
& 0x7;
444 lMask
= lMaskTable
[LeftAnd
];
445 Distance
= Width
+ Left
;
446 rMask
= rMaskTable
[(Distance
- 1) & 0x7];
449 /* Set some values */
450 SomeYesNoFlag
= FALSE
;
451 SomeYesNoFlag2
= FALSE
;
452 Distance
= (Distance
- 1) >> 3;
453 DistanceMinusLeftBpp
= Distance
- Left
;
455 /* Check if the distance is equal to the left position and add the masks */
456 if (Left
== Distance
) lMask
+= rMask
;
458 /* Check if there's no distance offset */
459 if (DistanceMinusLeftBpp
)
461 /* Set the first flag on */
462 SomeYesNoFlag
= TRUE
;
464 /* Decrease offset and check if we still have one */
465 if (--DistanceMinusLeftBpp
)
467 /* Still have a distance offset */
468 SomeYesNoFlag2
= TRUE
;
472 /* Calculate initial pixel position */
473 PixelPosition
= (PUCHAR
)VgaBase
+ (Top
* 80) + Left
;
475 /* Set loop buffer variable */
478 /* Switch to mode 0 */
481 /* Leave now if the height is 0 */
482 if (Height
<= 0) return;
484 /* Set more weird values */
485 CurrentLeft
= &LeftArray
[Left
];
486 NotlMask
= ~(UCHAR
)lMask
;
487 LeftPlusOne
= Left
+ 1;
488 LeftShifted
= (lMask
<< 8) | 8;
491 /* Start the height loop */
494 /* Start the plane loop */
498 /* Clear the current value */
502 /* Set the buffer loop variable for this loop */
505 /* Calculate plane shift and pixel mask */
506 PlaneShift
= 1 << Plane
;
507 pMask
= PixelMask
[LeftAnd
];
509 /* Check if we have a width */
517 /* Check if we're odd and increase the loop count */
518 Odd
= LoopCount
& 1 ? TRUE
: FALSE
;
522 /* Check for the plane shift */
525 /* Write the pixel mask */
529 /* Increase buffer position */
534 /* Check for plane shift */
535 if ((*k
>> 4) & PlaneShift
)
537 /* Write the pixel mask */
542 /* Shift the pixel mask */
546 /* Move to the next current left position and clear it */
550 /* Set the pixel mask to 0x80 */
556 /* Set the plane value */
557 __outpw(0x3C4, (1 << (Plane
+ 8) | 2));
559 /* Select the bitmask register and write the mask */
560 __outpw(0x3CE, (USHORT
)LeftShifted
);
562 /* Read the current Pixel value */
563 Value
= READ_REGISTER_UCHAR(PixelPosition
);
566 Value
= (Value
& NotlMask
) | *CurrentLeft
;
568 /* Set current left for the loop, and write new pixel value */
569 LeftPos
= LeftPlusOne
;
570 WRITE_REGISTER_UCHAR(PixelPosition
, Value
);
572 /* Set loop pixel position and check if we should loop */
573 m
= PixelPosition
+ 1;
576 /* Set the bitmask to 0xFF for all 4 planes */
577 __outpw(0x3CE, 0xFF08);
579 /* Check if we have any distance left */
580 if (DistanceMinusLeftBpp
> 0)
582 /* Start looping it */
583 x
= DistanceMinusLeftBpp
;
586 /* Write the value */
587 WRITE_REGISTER_UCHAR(m
, LeftArray
[LeftPos
]);
589 /* Go to the next position */
596 /* Check if the first flag is on */
599 /* Set the mask value */
600 __outpw(0x3CE, (rMask
<< 8) | 8);
602 /* Read the current Pixel value */
603 Value
= READ_REGISTER_UCHAR(m
);
606 Value
= (Value
& ~(UCHAR
)rMask
) | LeftArray
[LeftPos
];
608 /* Set current left for the loop, and write new pixel value */
609 WRITE_REGISTER_UCHAR(m
, Value
);
611 } while (++Plane
< 4);
613 /* Update pixel position, buffer and height */
621 RleBitBlt(IN ULONG Left
,
629 ULONG RleValue
, NewRleValue
;
634 /* Set Y height and current X value and start loop */
635 YDelta
= Top
+ Height
- 1;
639 /* Get the current value and advance in the buffer */
644 /* Check if we've gone past the edge */
645 if ((x
+ RleValue
) > (Width
+ Left
))
647 /* Fixeup the pixel value */
648 RleValue
= Left
- x
+ Width
;
651 /* Get the new value */
652 NewRleValue
= *Buffer
;
654 /* Get the two colors */
655 Color
= NewRleValue
>> 4;
656 Color2
= NewRleValue
& 0xF;
658 /* Increase buffer positition */
661 /* Check if we need to do a fill */
664 /* Do a fill and continue the loop */
666 VidSolidColorFill(x
, YDelta
, RleValue
- 1, YDelta
, (UCHAR
)Color
);
671 /* Check if the pixel value is 1 or below */
674 /* Set loop variables */
675 i
= (RleValue
- 2) / 2 + 1;
679 SetPixel(x
, YDelta
, (UCHAR
)Color
);
681 SetPixel(x
, YDelta
, (UCHAR
)Color2
);
684 /* Decrease pixel value */
689 /* Check if there is any value at all */
692 /* Set the pixel and increase posititon */
693 SetPixel(x
, YDelta
, (UCHAR
)Color
);
701 /* Get the current pixel value */
709 /* Set new x value, decrease distance and restart */
724 /* Set new x value, decrease distance and restart */
739 /* Check if we've gone past the edge */
740 if ((x
+ RleValue
) > (Width
+ Left
))
742 /* Set fixed up loop count */
743 i
= RleValue
- Left
- Width
+ x
;
745 /* Fixup pixel value */
750 /* Clear loop count */
754 /* Check the value now */
757 /* Set loop variables */
758 j
= (RleValue
- 2) / 2 + 1;
761 /* Get the new value */
762 NewRleValue
= *Buffer
;
764 /* Get the two colors */
765 Color
= NewRleValue
>> 4;
766 Color2
= NewRleValue
& 0xF;
768 /* Increase buffer position */
772 SetPixel(x
, YDelta
, (UCHAR
)Color
);
774 SetPixel(x
, YDelta
, (UCHAR
)Color2
);
777 /* Decrease pixel value */
782 /* Check if there is any value at all */
785 /* Set the pixel and increase position */
786 Color
= *Buffer
>> 4;
788 SetPixel(x
, YDelta
, (UCHAR
)Color
);
793 /* Check loop count now */
799 /* Set new position */
800 Buffer
= Buffer
+ (i
/ 2) + 1;
803 /* Check if we need to increase the buffer */
804 if ((ULONG_PTR
)Buffer
& 1) Buffer
++;
808 /* PUBLIC FUNCTIONS **********************************************************/
815 VidSetTextColor(ULONG Color
)
819 /* Save the old color and set the new one */
820 OldColor
= TextColor
;
830 VidDisplayStringXY(PUCHAR String
,
837 /* If the caller wanted transparent, then send the special value (16), else */
838 /* use our default and call the helper routine. */
839 BackColor
= (Transparent
) ? 16 : 14;
840 DisplayStringXY(String
, Left
, Top
, 12, BackColor
);
848 VidSetScrollRegion(ULONG x1
,
853 /* Assert alignment */
854 ASSERT((x1
& 0x7) == 0);
855 ASSERT((x2
& 0x7) == 7);
857 /* Set Scroll Region */
858 ScrollRegion
[0] = x1
;
859 ScrollRegion
[1] = y1
;
860 ScrollRegion
[2] = x2
;
861 ScrollRegion
[3] = y2
;
863 /* Set current X and Y */
875 /* Select bit mask register */
876 WRITE_PORT_UCHAR((PUCHAR
)VgaRegisterBase
+ 0x3CE, 8);
879 WRITE_PORT_UCHAR((PUCHAR
)VgaRegisterBase
+ 0x3CF, 255);
887 VidBufferToScreenBlt(IN PUCHAR Buffer
,
894 /* Make sure we have a width and height */
895 if (!(Width
) || !(Height
)) return;
897 /* Call the helper function */
898 BitBlt(Left
, Top
, Width
, Height
, Buffer
, 4, Delta
);
906 VidDisplayString(PUCHAR String
)
910 /* Start looping the string */
913 /* Treat new-line separately */
916 /* Modify Y position */
918 if (curr_y
>= ScrollRegion
[3])
920 /* Scroll the view */
925 PreserveRow(curr_y
, TopDelta
, TRUE
);
928 /* Update current X */
929 curr_x
= ScrollRegion
[0];
931 /* Preseve the current row */
932 PreserveRow(curr_y
, TopDelta
, FALSE
);
934 else if (*String
== '\r')
936 /* Update current X */
937 curr_x
= ScrollRegion
[0];
939 /* Check if we're being followed by a new line */
940 if (String
[1] != '\n') NextLine
= TRUE
;
944 /* Check if we had a \n\r last time */
947 /* We did, preserve the current row */
948 PreserveRow(curr_y
, TopDelta
, TRUE
);
952 /* Display this character */
953 DisplayCharacter(*String
, curr_x
, curr_y
, TextColor
, 16);
956 /* Check if we should scroll */
957 if (curr_x
> ScrollRegion
[2])
959 /* Update Y position and check if we should scroll it */
961 if (curr_y
> ScrollRegion
[3])
968 PreserveRow(curr_y
, TopDelta
, TRUE
);
972 curr_x
= ScrollRegion
[0];
976 /* Get the next character */
986 VidBitBlt(PUCHAR Buffer
,
990 PBITMAPINFOHEADER BitmapInfoHeader
;
994 /* Get the Bitmap Header */
995 BitmapInfoHeader
= (PBITMAPINFOHEADER
)Buffer
;
997 /* Initialize the palette */
998 InitPaletteWithTable((PULONG
)(Buffer
+ BitmapInfoHeader
->biSize
),
999 (BitmapInfoHeader
->biClrUsed
) ?
1000 BitmapInfoHeader
->biClrUsed
: 16);
1002 /* Make sure we can support this bitmap */
1003 ASSERT((BitmapInfoHeader
->biBitCount
* BitmapInfoHeader
->biPlanes
) <= 4);
1005 /* Calculate the delta and align it on 32-bytes, then calculate the actual */
1006 /* start of the bitmap data. */
1007 Delta
= (BitmapInfoHeader
->biBitCount
* BitmapInfoHeader
->biWidth
) + 31;
1010 BitmapOffset
= Buffer
+ sizeof(BITMAPINFOHEADER
) + 16 * sizeof(ULONG
);
1012 /* Check the compression of the bitmap */
1013 if (BitmapInfoHeader
->biCompression
== 2)
1015 /* Make sure we have a width and a height */
1016 if ((BitmapInfoHeader
->biWidth
) && (BitmapInfoHeader
->biHeight
))
1018 /* We can use RLE Bit Blt */
1021 BitmapInfoHeader
->biWidth
,
1022 BitmapInfoHeader
->biHeight
,
1028 /* Check if the height is negative */
1029 if (BitmapInfoHeader
->biHeight
< 0)
1031 /* Make it positive in the header */
1032 BitmapInfoHeader
->biHeight
*= -1;
1036 /* Update buffer offset */
1037 BitmapOffset
+= ((BitmapInfoHeader
->biHeight
-1) * Delta
);
1041 /* Make sure we have a width and a height */
1042 if ((BitmapInfoHeader
->biWidth
) && (BitmapInfoHeader
->biHeight
))
1047 BitmapInfoHeader
->biWidth
,
1048 BitmapInfoHeader
->biHeight
,
1050 BitmapInfoHeader
->biBitCount
,
1061 VidScreenToBufferBlt(PUCHAR Buffer
,
1070 ULONG LeftDelta
, RightDelta
;
1072 PUCHAR PixelPosition
;
1075 UCHAR Value
, Value2
;
1080 /* Calculate total distance to copy on X */
1081 XDistance
= Left
+ Width
- 1;
1083 /* Start at plane 0 */
1086 /* Calculate the 8-byte left and right deltas */
1087 LeftDelta
= Left
& 7;
1088 RightDelta
= 8 - LeftDelta
;
1090 /* Clear the destination buffer */
1091 RtlZeroMemory(Buffer
, Delta
* Height
);
1093 /* Calculate the pixel offset and convert the X distance into byte form */
1094 PixelOffset
= Top
* 80 + (Left
>> 3);
1097 /* Loop the 4 planes */
1100 /* Set the current pixel position and reset buffer loop variable */
1101 PixelPosition
= (PUCHAR
)VgaBase
+ PixelOffset
;
1107 /* Set the current plane */
1108 __outpw(0x3CE, (Plane
<< 8) | 4);
1110 /* Make sure we have a height */
1113 /* Start the outer Y loop */
1117 /* Read the current value */
1119 Value
= READ_REGISTER_UCHAR(PixelPosition
);
1121 /* Set Pixel Position loop variable */
1122 k
= PixelPosition
+ 1;
1124 /* Check if we're still within bounds */
1125 if (Left
<= XDistance
)
1127 /* Start X Inner loop */
1128 x
= (XDistance
- Left
) + 1;
1131 /* Read the current value */
1132 Value2
= READ_REGISTER_UCHAR(k
);
1134 /* Increase pixel position */
1138 a
= Value2
>> (UCHAR
)RightDelta
;
1139 a
|= Value
<< (UCHAR
)LeftDelta
;
1140 b
= lookup
[a
& 0xF];
1145 /* Save new value to buffer */
1148 /* Move to next destination location */
1151 /* Write new value */
1156 /* Update pixel position */
1157 PixelPosition
+= 80;
1161 } while (++Plane
< 4);
1169 VidSolidColorFill(IN ULONG Left
,
1176 ULONG LeftOffset
, RightOffset
, Distance
;
1180 /* Get the left and right masks, shifts, and delta */
1181 LeftOffset
= Left
>> 3;
1182 lMask
= (lMaskTable
[Left
& 0x7] << 8) | 8;
1183 RightOffset
= Right
>> 3;
1184 rMask
= (rMaskTable
[Right
& 0x7] << 8) | 8;
1185 Distance
= RightOffset
- LeftOffset
;
1187 /* If there is no distance, then combine the right and left masks */
1188 if (!Distance
) lMask
&= rMask
;
1190 /* Switch to mode 10 */
1193 /* Clear the 4 planes (we're already in unchained mode here) */
1194 __outpw(0x3C4, 0xF02);
1196 /* Select the color don't care register */
1199 /* Calculate pixel position for the read */
1200 Offset
= VgaBase
+ (Top
* 80) + (PUCHAR
)LeftOffset
;
1202 /* Select the bitmask register and write the mask */
1203 __outpw(0x3CE, (USHORT
)lMask
);
1205 /* Check if the top coord is below the bottom one */
1208 /* Start looping each line */
1209 i
= (Bottom
- Top
) + 1;
1212 /* Read the previous value and add our color */
1213 WRITE_REGISTER_UCHAR(Offset
, READ_REGISTER_UCHAR(Offset
) & Color
);
1215 /* Move to the next line */
1220 /* Check if we have a delta */
1223 /* Calculate new pixel position */
1224 Offset
= VgaBase
+ (Top
* 80) + (PUCHAR
)RightOffset
;
1227 /* Select the bitmask register and write the mask */
1228 __outpw(0x3CE, (USHORT
)rMask
);
1230 /* Check if the top coord is below the bottom one */
1233 /* Start looping each line */
1234 i
= (Bottom
- Top
) + 1;
1237 /* Read the previous value and add our color */
1238 WRITE_REGISTER_UCHAR(Offset
,
1239 READ_REGISTER_UCHAR(Offset
) & Color
);
1241 /* Move to the next line */
1246 /* Check if we still have a delta */
1249 /* Calculate new pixel position */
1250 Offset
= VgaBase
+ (Top
* 80) + (PUCHAR
)(LeftOffset
+ 1);
1252 /* Set the bitmask to 0xFF for all 4 planes */
1253 __outpw(0x3CE, 0xFF08);
1255 /* Check if the top coord is below the bottom one */
1258 /* Start looping each line */
1259 i
= (Bottom
- Top
) + 1;
1262 /* Loop the shift delta */
1265 for (j
= Distance
; j
; Offset
++, j
--)
1267 /* Write the color */
1268 WRITE_REGISTER_UCHAR(Offset
, Color
);
1272 /* Update position in memory */
1273 Offset
+= (80 - Distance
);