1 #include "precomp.h" 2 3 #define NDEBUG 4 #include <debug.h> 5 6 PUSHORT VgaArmBase; 7 PHYSICAL_ADDRESS VgaPhysical; 8 BOOLEAN ClearRow = FALSE; 9 10 /* PRIVATE FUNCTIONS *********************************************************/ 11 12 VOID 13 NTAPI 14 DisplayCharacter(IN CHAR Character, 15 IN ULONG Left, 16 IN ULONG Top, 17 IN ULONG TextColor, 18 IN ULONG BackColor) 19 { 20 PUCHAR FontChar; 21 ULONG i, j, XOffset; 22 23 /* Get the font line for this character */ 24 FontChar = &FontData[Character * BOOTCHAR_HEIGHT - Top]; 25 26 /* Loop each pixel height */ 27 for (i = BOOTCHAR_HEIGHT; i > 0; --i) 28 { 29 /* Loop each pixel width */ 30 XOffset = Left; 31 for (j = (1 << 7); j > 0; j >>= 1) 32 { 33 /* Check if we should draw this pixel */ 34 if (FontChar[Top] & (UCHAR)j) 35 { 36 /* We do, use the given Text Color */ 37 SetPixel(XOffset, Top, (UCHAR)TextColor); 38 } 39 else if (BackColor < 16) 40 { 41 /* 42 * This is a background pixel. We're drawing it 43 * unless it's transparent. 44 */ 45 SetPixel(XOffset, Top, (UCHAR)BackColor); 46 } 47 48 /* Increase X Offset */ 49 XOffset++; 50 } 51 52 /* Move to the next Y ordinate */ 53 Top++; 54 } 55 } 56 57 VOID 58 NTAPI 59 VgaScroll(IN ULONG Scroll) 60 { 61 ULONG Top, Offset; 62 PUSHORT SourceOffset, DestOffset; 63 PUSHORT i, j; 64 65 /* Set memory positions of the scroll */ 66 SourceOffset = &VgaArmBase[(VidpScrollRegion[1] * (SCREEN_WIDTH / 8)) + (VidpScrollRegion[0] >> 3)]; 67 DestOffset = &SourceOffset[Scroll * (SCREEN_WIDTH / 8)]; 68 69 /* Start loop */ 70 for (Top = VidpScrollRegion[1]; Top <= VidpScrollRegion[3]; ++Top) 71 { 72 /* Set number of bytes to loop and start offset */ 73 Offset = VidpScrollRegion[0] >> 3; 74 j = SourceOffset; 75 76 /* Check if this is part of the scroll region */ 77 if (Offset <= (VidpScrollRegion[2] >> 3)) 78 { 79 /* Update position */ 80 i = (PUSHORT)(DestOffset - SourceOffset); 81 82 /* Loop the X axis */ 83 do 84 { 85 /* Write value in the new position so that we can do the scroll */ 86 WRITE_REGISTER_USHORT(j, READ_REGISTER_USHORT(j + (ULONG_PTR)i)); 87 88 /* Move to the next memory location to write to */ 89 j++; 90 91 /* Move to the next byte in the region */ 92 Offset++; 93 94 /* Make sure we don't go past the scroll region */ 95 } while (Offset <= (VidpScrollRegion[2] >> 3)); 96 } 97 98 /* Move to the next line */ 99 SourceOffset += (SCREEN_WIDTH / 8); 100 DestOffset += (SCREEN_WIDTH / 8); 101 } 102 } 103 104 VOID 105 NTAPI 106 PreserveRow(IN ULONG CurrentTop, 107 IN ULONG TopDelta, 108 IN BOOLEAN Restore) 109 { 110 PUSHORT Position1, Position2; 111 ULONG Count; 112 113 /* Calculate the position in memory for the row */ 114 if (Restore) 115 { 116 /* Restore the row by copying back the contents saved off-screen */ 117 Position1 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)]; 118 Position2 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)]; 119 } 120 else 121 { 122 /* Preserve the row by saving its contents off-screen */ 123 Position1 = &VgaArmBase[SCREEN_HEIGHT * (SCREEN_WIDTH / 8)]; 124 Position2 = &VgaArmBase[CurrentTop * (SCREEN_WIDTH / 8)]; 125 } 126 127 /* Set the count and loop every pixel */ 128 Count = TopDelta * (SCREEN_WIDTH / 8); 129 while (Count--) 130 { 131 /* Write the data back on the other position */ 132 WRITE_REGISTER_USHORT(Position1, READ_REGISTER_USHORT(Position2)); 133 134 /* Increase both positions */ 135 Position1++; 136 Position2++; 137 } 138 } 139 140 VOID 141 NTAPI 142 VidpInitializeDisplay(VOID) 143 { 144 // 145 // Set framebuffer address 146 // 147 WRITE_REGISTER_ULONG(PL110_LCDUPBASE, VgaPhysical.LowPart); 148 WRITE_REGISTER_ULONG(PL110_LCDLPBASE, VgaPhysical.LowPart); 149 150 // 151 // Initialize timings to 640x480 152 // 153 WRITE_REGISTER_ULONG(PL110_LCDTIMING0, LCDTIMING0_PPL(SCREEN_WIDTH)); 154 WRITE_REGISTER_ULONG(PL110_LCDTIMING1, LCDTIMING1_LPP(SCREEN_HEIGHT)); 155 156 // 157 // Enable the LCD Display 158 // 159 WRITE_REGISTER_ULONG(PL110_LCDCONTROL, 160 LCDCONTROL_LCDEN | 161 LCDCONTROL_LCDTFT | 162 LCDCONTROL_LCDPWR | 163 LCDCONTROL_LCDBPP(4)); 164 } 165 166 VOID 167 NTAPI 168 InitPaletteWithTable( 169 _In_ PULONG Table, 170 _In_ ULONG Count) 171 { 172 UNIMPLEMENTED; 173 } 174 175 /* PUBLIC FUNCTIONS **********************************************************/ 176 177 /* 178 * @implemented 179 */ 180 BOOLEAN 181 NTAPI 182 VidInitialize(IN BOOLEAN SetMode) 183 { 184 DPRINT1("bv-arm v0.1\n"); 185 186 // 187 // Allocate framebuffer 188 // 600kb works out to 640x480@16bpp 189 // 190 VgaPhysical.QuadPart = -1; 191 VgaArmBase = MmAllocateContiguousMemory(600 * 1024, VgaPhysical); 192 if (!VgaArmBase) return FALSE; 193 194 // 195 // Get physical address 196 // 197 VgaPhysical = MmGetPhysicalAddress(VgaArmBase); 198 if (!VgaPhysical.QuadPart) return FALSE; 199 DPRINT1("[BV-ARM] Frame Buffer @ 0x%p 0p%p\n", VgaArmBase, VgaPhysical.LowPart); 200 201 // 202 // Setup the display 203 // 204 VidpInitializeDisplay(); 205 206 // 207 // We are done! 208 // 209 return TRUE; 210 } 211 212 /* 213 * @implemented 214 */ 215 VOID 216 NTAPI 217 VidResetDisplay(IN BOOLEAN HalReset) 218 { 219 // 220 // Clear the current position 221 // 222 VidpCurrentX = 0; 223 VidpCurrentY = 0; 224 225 // 226 // Re-initialize the VGA Display 227 // 228 VidpInitializeDisplay(); 229 230 // 231 // Re-initialize the palette and fill the screen black 232 // 233 //InitializePalette(); 234 VidSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 0); 235 } 236 237 /* 238 * @implemented 239 */ 240 ULONG 241 NTAPI 242 VidSetTextColor(IN ULONG Color) 243 { 244 UCHAR OldColor; 245 246 // 247 // Save the old, set the new 248 // 249 OldColor = VidpTextColor; 250 VidpTextColor = Color; 251 252 // 253 // Return the old text color 254 // 255 return OldColor; 256 } 257 258 /* 259 * @implemented 260 */ 261 VOID 262 NTAPI 263 VidCleanUp(VOID) 264 { 265 UNIMPLEMENTED; 266 while (TRUE); 267 } 268 269 /* 270 * @implemented 271 */ 272 VOID 273 NTAPI 274 VidDisplayString(IN PUCHAR String) 275 { 276 ULONG TopDelta = BOOTCHAR_HEIGHT + 1; 277 278 /* Start looping the string */ 279 for (; *String; ++String) 280 { 281 /* Treat new-line separately */ 282 if (*String == '\n') 283 { 284 /* Modify Y position */ 285 VidpCurrentY += TopDelta; 286 if (VidpCurrentY + TopDelta - 1 > VidpScrollRegion[3]) 287 { 288 /* Scroll the view and clear the current row */ 289 VgaScroll(TopDelta); 290 VidpCurrentY -= TopDelta; 291 PreserveRow(VidpCurrentY, TopDelta, TRUE); 292 } 293 else 294 { 295 /* Preserve the current row */ 296 PreserveRow(VidpCurrentY, TopDelta, FALSE); 297 } 298 299 /* Update current X */ 300 VidpCurrentX = VidpScrollRegion[0]; 301 302 /* No need to clear this row */ 303 ClearRow = FALSE; 304 } 305 else if (*String == '\r') 306 { 307 /* Update current X */ 308 VidpCurrentX = VidpScrollRegion[0]; 309 310 /* If a new-line does not follow we will clear the current row */ 311 if (String[1] != '\n') ClearRow = TRUE; 312 } 313 else 314 { 315 /* Clear the current row if we had a return-carriage without a new-line */ 316 if (ClearRow) 317 { 318 PreserveRow(VidpCurrentY, TopDelta, TRUE); 319 ClearRow = FALSE; 320 } 321 322 /* Display this character */ 323 DisplayCharacter(*String, 324 VidpCurrentX, 325 VidpCurrentY, 326 VidpTextColor, 327 16); 328 VidpCurrentX += 8; 329 330 /* Check if we should scroll */ 331 if (VidpCurrentX + 7 > VidpScrollRegion[2]) 332 { 333 /* Update Y position and check if we should scroll it */ 334 VidpCurrentY += TopDelta; 335 if (VidpCurrentY + TopDelta - 1 > VidpScrollRegion[3]) 336 { 337 /* Scroll the view and clear the current row */ 338 VgaScroll(TopDelta); 339 VidpCurrentY -= TopDelta; 340 PreserveRow(VidpCurrentY, TopDelta, TRUE); 341 } 342 else 343 { 344 /* Preserve the current row */ 345 PreserveRow(VidpCurrentY, TopDelta, FALSE); 346 } 347 348 /* Update current X */ 349 VidpCurrentX = VidpScrollRegion[0]; 350 } 351 } 352 } 353 } 354 355 /* 356 * @implemented 357 */ 358 VOID 359 NTAPI 360 VidScreenToBufferBlt(OUT PUCHAR Buffer, 361 IN ULONG Left, 362 IN ULONG Top, 363 IN ULONG Width, 364 IN ULONG Height, 365 IN ULONG Delta) 366 { 367 UNIMPLEMENTED; 368 while (TRUE); 369 } 370 371 /* 372 * @implemented 373 */ 374 VOID 375 NTAPI 376 VidSolidColorFill(IN ULONG Left, 377 IN ULONG Top, 378 IN ULONG Right, 379 IN ULONG Bottom, 380 IN UCHAR Color) 381 { 382 int y, x; 383 384 // 385 // Loop along the Y-axis 386 // 387 for (y = Top; y <= Bottom; y++) 388 { 389 // 390 // Loop along the X-axis 391 // 392 for (x = Left; x <= Right; x++) 393 { 394 // 395 // Draw the pixel 396 // 397 SetPixel(x, y, Color); 398 } 399 } 400 } 401