textvid.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. textvid.c
  5. Abstract:
  6. This module implements a fake firmware interface for ARM systems that have
  7. no firmware services layer.
  8. Author:
  9. Evan Green 30-Jan-2013
  10. Environment:
  11. Boot and Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include "basevidp.h"
  17. //
  18. // --------------------------------------------------------------------- Macros
  19. //
  20. //
  21. // This routine converts a color value from software form into its physical
  22. // form.
  23. //
  24. #define TRANSLATE_COLOR(_Value, _Translation) \
  25. (((SHIFT_COLOR(_Value, _Translation.RedShift) & _Translation.RedMask)) | \
  26. ((SHIFT_COLOR(_Value, _Translation.GreenShift) & \
  27. _Translation.GreenMask)) | \
  28. ((SHIFT_COLOR(_Value, _Translation.BlueShift) & _Translation.BlueMask)))
  29. //
  30. // This routine shifts a value left by the given amount (right if the shift is
  31. // negative).
  32. //
  33. #define SHIFT_COLOR(_Value, _Shift) \
  34. (((_Shift) >= 0) ? ((_Value) << (_Shift)) : ((_Value) >> -(_Shift)))
  35. //
  36. // This macro just flips red and blue.
  37. //
  38. #define SWIZZLE_RED_BLUE(_Value) \
  39. ((((_Value) & 0x000000FF) << 16) | (((_Value) & 0x00FF0000) >> 16) | \
  40. ((_Value) & 0x0000FF00))
  41. //
  42. // This macro converts a foreground and background color into attributes
  43. // (upper 8 of 16 bits) for BIOS text mode.
  44. //
  45. #define BIOS_TEXT_ATTRIBUTES(_Foreground, _Background) \
  46. ((((_Foreground) & 0xF) << 8) | (((_Background) & 0x7) << 12))
  47. //
  48. // ---------------------------------------------------------------- Definitions
  49. //
  50. //
  51. // ----------------------------------------------- Internal Function Prototypes
  52. //
  53. VOID
  54. VidpConvertPalette (
  55. PBASE_VIDEO_CONTEXT Context,
  56. PBASE_VIDEO_PALETTE Palette,
  57. PBASE_VIDEO_PALETTE PhysicalPalette
  58. );
  59. VOID
  60. VidpPrintCharacter (
  61. PBASE_VIDEO_CONTEXT Context,
  62. ULONG XCoordinate,
  63. ULONG YCoordinate,
  64. PBASE_VIDEO_CHARACTER Character
  65. );
  66. VOID
  67. VidpConvertIntegerToString (
  68. LONG Integer,
  69. PSTR String,
  70. ULONG Base
  71. );
  72. ULONG
  73. VidpFindHighestBitSet (
  74. ULONG Value
  75. );
  76. //
  77. // ------------------------------------------------------ Data Type Definitions
  78. //
  79. typedef struct _COLOR_TRANSLATION {
  80. LONG RedShift;
  81. ULONG RedMask;
  82. LONG GreenShift;
  83. ULONG GreenMask;
  84. LONG BlueShift;
  85. ULONG BlueMask;
  86. } COLOR_TRANSLATION, *PCOLOR_TRANSLATION;
  87. //
  88. // -------------------------------------------------------------------- Globals
  89. //
  90. //
  91. // Store the default palette to use.
  92. //
  93. BASE_VIDEO_PALETTE VidDefaultPalette = {
  94. {
  95. BASE_VIDEO_COLOR_RGB(255, 240, 165),
  96. BASE_VIDEO_COLOR_RGB(0, 0, 0),
  97. BASE_VIDEO_COLOR_RGB(134, 37, 23),
  98. BASE_VIDEO_COLOR_RGB(37, 188, 36),
  99. BASE_VIDEO_COLOR_RGB(173, 173, 39),
  100. BASE_VIDEO_COLOR_RGB(50, 27, 184),
  101. BASE_VIDEO_COLOR_RGB(134, 30, 134),
  102. BASE_VIDEO_COLOR_RGB(47, 204, 197),
  103. BASE_VIDEO_COLOR_RGB(203, 204, 206),
  104. },
  105. {
  106. BASE_VIDEO_COLOR_RGB(255, 255, 170),
  107. BASE_VIDEO_COLOR_RGB(142, 145, 149),
  108. BASE_VIDEO_COLOR_RGB(255, 120, 100),
  109. BASE_VIDEO_COLOR_RGB(49, 231, 34),
  110. BASE_VIDEO_COLOR_RGB(234, 236, 35),
  111. BASE_VIDEO_COLOR_RGB(70, 160, 255),
  112. BASE_VIDEO_COLOR_RGB(240, 100, 240),
  113. BASE_VIDEO_COLOR_RGB(20, 240, 240),
  114. BASE_VIDEO_COLOR_RGB(233, 235, 237),
  115. },
  116. BASE_VIDEO_COLOR_RGB(19, 119, 61),
  117. BASE_VIDEO_COLOR_RGB(19, 119, 61),
  118. BASE_VIDEO_COLOR_RGB(255, 240, 165),
  119. BASE_VIDEO_COLOR_RGB(142, 40, 0),
  120. };
  121. //
  122. // Store a pointer to the default font to use.
  123. //
  124. PBASE_VIDEO_FONT VidDefaultFont = &VidFontPs2Thin48x16;
  125. //
  126. // Store the conversion between ANSI colors and BIOS text attribute numbers.
  127. //
  128. const UCHAR VidTextModeColors[AnsiColorCount] = {7, 0, 4, 2, 6, 1, 5, 3, 7};
  129. //
  130. // ------------------------------------------------------------------ Functions
  131. //
  132. KSTATUS
  133. VidInitialize (
  134. PBASE_VIDEO_CONTEXT Context,
  135. PSYSTEM_RESOURCE_FRAME_BUFFER FrameBuffer
  136. )
  137. /*++
  138. Routine Description:
  139. This routine initializes the base video library.
  140. Arguments:
  141. Context - Supplies a pointer to the video context to initialize.
  142. FrameBuffer - Supplies a pointer to the frame buffer parameters.
  143. Return Value:
  144. Status code.
  145. --*/
  146. {
  147. KSTATUS Status;
  148. Context->Mode = FrameBuffer->Mode;
  149. Context->FrameBuffer = FrameBuffer->Header.VirtualAddress;
  150. Context->Width = FrameBuffer->Width;
  151. Context->Height = FrameBuffer->Height;
  152. Context->PixelsPerScanLine = FrameBuffer->PixelsPerScanLine;
  153. Context->BitsPerPixel = FrameBuffer->BitsPerPixel;
  154. Context->RedMask = FrameBuffer->RedMask;
  155. Context->GreenMask = FrameBuffer->GreenMask;
  156. Context->BlueMask = FrameBuffer->BlueMask;
  157. ASSERT((Context->Mode != BaseVideoInvalidMode) &&
  158. (Context->FrameBuffer != NULL) &&
  159. (Context->Width != 0) &&
  160. (Context->Height != 0) &&
  161. (Context->PixelsPerScanLine >= Context->Width) &&
  162. (Context->BitsPerPixel != 0));
  163. ASSERT((Context->Mode != BaseVideoModeFrameBuffer) ||
  164. ((Context->RedMask != 0) &&
  165. (Context->GreenMask != 0) &&
  166. (Context->BlueMask != 0)));
  167. RtlCopyMemory(&(Context->Palette),
  168. &VidDefaultPalette,
  169. sizeof(BASE_VIDEO_PALETTE));
  170. VidpConvertPalette(Context, &VidDefaultPalette, &Context->PhysicalPalette);
  171. Context->Font = VidDefaultFont;
  172. ASSERT(Context->Font != NULL);
  173. if (Context->Mode == BaseVideoModeBiosText) {
  174. Context->Columns = Context->Width;
  175. Context->Rows = Context->Height;
  176. } else {
  177. Context->Columns = Context->Width / Context->Font->CellWidth;
  178. Context->Rows = Context->Height / Context->Font->CellHeight;
  179. }
  180. Status = STATUS_SUCCESS;
  181. return Status;
  182. }
  183. VOID
  184. VidClearScreen (
  185. PBASE_VIDEO_CONTEXT Context,
  186. ULONG MinimumX,
  187. ULONG MinimumY,
  188. ULONG MaximumX,
  189. ULONG MaximumY
  190. )
  191. /*++
  192. Routine Description:
  193. This routine clears a region of the screen, filling it with the default
  194. fill character. If no frame buffer is present, this is a no-op.
  195. Arguments:
  196. Context - Supplies a pointer to the initialized base video context.
  197. MinimumX - Supplies the minimum X coordinate of the rectangle to clear,
  198. inclusive.
  199. MinimumY - Supplies the minimum Y coordinate of the rectangle to clear,
  200. inclusive.
  201. MaximumX - Supplies the maximum X coordinate of the rectangle to clear,
  202. exclusive.
  203. MaximumY - Supplies the maximum Y coordinate of the rectangle to clear,
  204. exclusive.
  205. Return Value:
  206. None.
  207. --*/
  208. {
  209. BASE_VIDEO_CHARACTER Character;
  210. ULONG Color;
  211. ULONG HorizontalIndex;
  212. PULONG Pixel;
  213. PUSHORT Pixel16;
  214. PUCHAR Pixel8;
  215. ULONG VerticalIndex;
  216. if (Context->FrameBuffer == NULL) {
  217. return;
  218. }
  219. //
  220. // If either minimum value is off the screen, exit.
  221. //
  222. if (MinimumX >= Context->Width) {
  223. return;
  224. }
  225. if (MinimumY >= Context->Height) {
  226. return;
  227. }
  228. //
  229. // Truncate the maximum values.
  230. //
  231. if (MaximumX > Context->Width) {
  232. MaximumX = Context->Width;
  233. }
  234. if (MaximumY > Context->Height) {
  235. MaximumY = Context->Height;
  236. }
  237. //
  238. // Handle text mode by running around printing spaces.
  239. //
  240. if (Context->Mode == BaseVideoModeBiosText) {
  241. Character.Data.Character = ' ';
  242. Character.Data.Attributes = 0;
  243. for (VerticalIndex = MinimumY;
  244. VerticalIndex < MaximumY;
  245. VerticalIndex += 1) {
  246. for (HorizontalIndex = MinimumX;
  247. HorizontalIndex < MaximumX;
  248. HorizontalIndex += 1) {
  249. VidpPrintCharacter(Context,
  250. HorizontalIndex,
  251. VerticalIndex,
  252. &Character);
  253. }
  254. }
  255. return;
  256. }
  257. Color = Context->PhysicalPalette.DefaultBackground;
  258. //
  259. // Switch on the bits per pixel outside the hot inner loop.
  260. //
  261. switch (Context->BitsPerPixel) {
  262. case 8:
  263. for (VerticalIndex = MinimumY;
  264. VerticalIndex < MaximumY;
  265. VerticalIndex += 1) {
  266. Pixel = (PULONG)(Context->FrameBuffer +
  267. (((VerticalIndex *
  268. Context->PixelsPerScanLine) +
  269. MinimumX) *
  270. (Context->BitsPerPixel / BITS_PER_BYTE)));
  271. Pixel8 = (PUCHAR)Pixel;
  272. for (HorizontalIndex = MinimumX;
  273. HorizontalIndex < MaximumX;
  274. HorizontalIndex += 1) {
  275. *Pixel8 = (UCHAR)Color;
  276. Pixel8 += 1;
  277. }
  278. }
  279. break;
  280. case 16:
  281. for (VerticalIndex = MinimumY;
  282. VerticalIndex < MaximumY;
  283. VerticalIndex += 1) {
  284. Pixel = (PULONG)(Context->FrameBuffer +
  285. (((VerticalIndex *
  286. Context->PixelsPerScanLine) +
  287. MinimumX) *
  288. (Context->BitsPerPixel / BITS_PER_BYTE)));
  289. Pixel16 = (PUSHORT)Pixel;
  290. for (HorizontalIndex = MinimumX;
  291. HorizontalIndex < MaximumX;
  292. HorizontalIndex += 1) {
  293. *Pixel16 = (USHORT)Color;
  294. Pixel16 += 1;
  295. }
  296. }
  297. break;
  298. case 24:
  299. for (VerticalIndex = MinimumY;
  300. VerticalIndex < MaximumY;
  301. VerticalIndex += 1) {
  302. Pixel = (PULONG)(Context->FrameBuffer +
  303. (((VerticalIndex *
  304. Context->PixelsPerScanLine) +
  305. MinimumX) *
  306. (Context->BitsPerPixel / BITS_PER_BYTE)));
  307. Pixel8 = (PUCHAR)Pixel;
  308. for (HorizontalIndex = MinimumX;
  309. HorizontalIndex < MaximumX;
  310. HorizontalIndex += 1) {
  311. *Pixel8 = (UCHAR)Color;
  312. *(Pixel8 + 1) = (UCHAR)(Color >> 8);
  313. *(Pixel8 + 2) = (UCHAR)(Color >> 16);
  314. Pixel8 += 3;
  315. }
  316. }
  317. break;
  318. case 32:
  319. for (VerticalIndex = MinimumY;
  320. VerticalIndex < MaximumY;
  321. VerticalIndex += 1) {
  322. Pixel = (PULONG)(Context->FrameBuffer +
  323. (((VerticalIndex *
  324. Context->PixelsPerScanLine) +
  325. MinimumX) *
  326. (Context->BitsPerPixel / BITS_PER_BYTE)));
  327. for (HorizontalIndex = MinimumX;
  328. HorizontalIndex < MaximumX;
  329. HorizontalIndex += 1) {
  330. *Pixel = Color;
  331. Pixel += 1;
  332. }
  333. }
  334. break;
  335. default:
  336. ASSERT(FALSE);
  337. break;
  338. }
  339. return;
  340. }
  341. VOID
  342. VidPrintString (
  343. PBASE_VIDEO_CONTEXT Context,
  344. ULONG XCoordinate,
  345. ULONG YCoordinate,
  346. PSTR String
  347. )
  348. /*++
  349. Routine Description:
  350. This routine prints a null-terminated string to the screen at the
  351. specified location.
  352. Arguments:
  353. Context - Supplies a pointer to the initialized base video context.
  354. XCoordinate - Supplies the X coordinate of the location on the screen
  355. to write to.
  356. YCoordinate - Supplies the Y cooordinate of the location on the screen
  357. to write to.
  358. String - Supplies the string to print.
  359. Return Value:
  360. None.
  361. --*/
  362. {
  363. BASE_VIDEO_CHARACTER Character;
  364. ULONG Columns;
  365. ULONG Rows;
  366. if (Context->FrameBuffer == NULL) {
  367. return;
  368. }
  369. Columns = Context->Columns;
  370. Rows = Context->Rows;
  371. Character.AsUint32 = 0;
  372. while (*String != '\0') {
  373. Character.Data.Character = *String;
  374. VidpPrintCharacter(Context, XCoordinate, YCoordinate, &Character);
  375. XCoordinate += 1;
  376. if (XCoordinate >= Columns) {
  377. XCoordinate = 0;
  378. YCoordinate += 1;
  379. }
  380. if (YCoordinate >= Rows) {
  381. YCoordinate = 0;
  382. }
  383. String += 1;
  384. }
  385. return;
  386. }
  387. VOID
  388. VidPrintHexInteger (
  389. PBASE_VIDEO_CONTEXT Context,
  390. ULONG XCoordinate,
  391. ULONG YCoordinate,
  392. ULONG Number
  393. )
  394. /*++
  395. Routine Description:
  396. This routine prints an integer to the screen in the specified location.
  397. Arguments:
  398. Context - Supplies a pointer to the initialized base video context.
  399. XCoordinate - Supplies the X coordinate of the location on the screen
  400. to write to.
  401. YCoordinate - Supplies the Y cooordinate of the location on the screen
  402. to write to.
  403. Number - Supplies the signed integer to print.
  404. Return Value:
  405. None.
  406. --*/
  407. {
  408. CHAR StringBuffer[30];
  409. VidpConvertIntegerToString(Number, StringBuffer, 16);
  410. VidPrintString(Context, XCoordinate, YCoordinate, StringBuffer);
  411. return;
  412. }
  413. VOID
  414. VidPrintInteger (
  415. PBASE_VIDEO_CONTEXT Context,
  416. ULONG XCoordinate,
  417. ULONG YCoordinate,
  418. LONG Number
  419. )
  420. /*++
  421. Routine Description:
  422. This routine prints an integer to the screen in the specified location.
  423. Arguments:
  424. Context - Supplies a pointer to the initialized base video context.
  425. XCoordinate - Supplies the X coordinate of the location on the screen
  426. to write to.
  427. YCoordinate - Supplies the Y cooordinate of the location on the screen
  428. to write to.
  429. Number - Supplies the signed integer to print.
  430. Return Value:
  431. None.
  432. --*/
  433. {
  434. CHAR StringBuffer[30];
  435. VidpConvertIntegerToString(Number, StringBuffer, 10);
  436. VidPrintString(Context, XCoordinate, YCoordinate, StringBuffer);
  437. return;
  438. }
  439. VOID
  440. VidPrintCharacters (
  441. PBASE_VIDEO_CONTEXT Context,
  442. ULONG XCoordinate,
  443. ULONG YCoordinate,
  444. PBASE_VIDEO_CHARACTER Characters,
  445. ULONG Count
  446. )
  447. /*++
  448. Routine Description:
  449. This routine prints a set of characters.
  450. Arguments:
  451. Context - Supplies a pointer to the initialized base video context.
  452. XCoordinate - Supplies the X coordinate of the location on the screen
  453. to write to.
  454. YCoordinate - Supplies the Y cooordinate of the location on the screen
  455. to write to.
  456. Characters - Supplies a pointer to the array of characters to write.
  457. Count - Supplies the number of characters in the array.
  458. Return Value:
  459. None.
  460. --*/
  461. {
  462. ULONG Columns;
  463. ULONG Index;
  464. ULONG Rows;
  465. Columns = Context->Columns;
  466. Rows = Context->Rows;
  467. for (Index = 0; Index < Count; Index += 1) {
  468. VidpPrintCharacter(Context,
  469. XCoordinate,
  470. YCoordinate,
  471. Characters + Index);
  472. XCoordinate += 1;
  473. if (XCoordinate >= Columns) {
  474. XCoordinate = 0;
  475. YCoordinate += 1;
  476. }
  477. if (YCoordinate >= Rows) {
  478. YCoordinate = 0;
  479. }
  480. }
  481. return;
  482. }
  483. VOID
  484. VidSetPalette (
  485. PBASE_VIDEO_CONTEXT Context,
  486. PBASE_VIDEO_PALETTE Palette,
  487. PBASE_VIDEO_PALETTE OldPalette
  488. )
  489. /*++
  490. Routine Description:
  491. This routine sets the current video palette. It is the caller's
  492. responsibility to synchronize both with printing and clearing the screen.
  493. Arguments:
  494. Context - Supplies a pointer to the initialized base video context.
  495. Palette - Supplies a pointer to the palette to set. This memory will be
  496. copied.
  497. OldPalette - Supplies an optional pointer where the old palette data will
  498. be returned.
  499. Return Value:
  500. None.
  501. --*/
  502. {
  503. if (OldPalette != NULL) {
  504. RtlCopyMemory(OldPalette,
  505. &(Context->Palette),
  506. sizeof(BASE_VIDEO_PALETTE));
  507. }
  508. RtlCopyMemory(&(Context->Palette), Palette, sizeof(BASE_VIDEO_PALETTE));
  509. VidpConvertPalette(Context,
  510. &(Context->Palette),
  511. &(Context->PhysicalPalette));
  512. return;
  513. }
  514. VOID
  515. VidSetPartialPalette (
  516. PBASE_VIDEO_CONTEXT Context,
  517. PBASE_VIDEO_PARTIAL_PALETTE PartialPalette
  518. )
  519. /*++
  520. Routine Description:
  521. This routine sets the current video palette. It is the caller's
  522. responsibility to synchronize both with printing and clearing the screen.
  523. Arguments:
  524. Context - Supplies a pointer to the initialized base video context.
  525. PartialPalette - Supplies a pointer to the palette to set. This memory will
  526. be copied. Values in the palette not specified here will be left
  527. unchanged.
  528. Return Value:
  529. None.
  530. --*/
  531. {
  532. BASE_VIDEO_PALETTE Palette;
  533. VidGetPalette(Context, &Palette);
  534. Palette.AnsiColor[AnsiColorDefault] = PartialPalette->DefaultForeground;
  535. Palette.BoldAnsiColor[AnsiColorDefault] =
  536. PartialPalette->DefaultBoldForeground;
  537. Palette.DefaultBackground = PartialPalette->DefaultBackground;
  538. Palette.DefaultBoldBackground = PartialPalette->DefaultBoldBackground;
  539. Palette.CursorText = PartialPalette->CursorText;
  540. Palette.CursorBackground = PartialPalette->CursorBackground;
  541. VidSetPalette(Context, &Palette, NULL);
  542. return;
  543. }
  544. VOID
  545. VidGetPalette (
  546. PBASE_VIDEO_CONTEXT Context,
  547. PBASE_VIDEO_PALETTE Palette
  548. )
  549. /*++
  550. Routine Description:
  551. This routine gets the current video palette. It is the caller's
  552. responsibility to synchronize with anyone else that might be changing the
  553. palette.
  554. Arguments:
  555. Context - Supplies a pointer to the initialized base video context.
  556. Palette - Supplies a pointer where the palette will be returned.
  557. Return Value:
  558. None.
  559. --*/
  560. {
  561. RtlCopyMemory(Palette, &(Context->Palette), sizeof(BASE_VIDEO_PALETTE));
  562. return;
  563. }
  564. //
  565. // --------------------------------------------------------- Internal Functions
  566. //
  567. VOID
  568. VidpConvertPalette (
  569. PBASE_VIDEO_CONTEXT Context,
  570. PBASE_VIDEO_PALETTE Palette,
  571. PBASE_VIDEO_PALETTE PhysicalPalette
  572. )
  573. /*++
  574. Routine Description:
  575. This routine converts the given palette into a physical palette that uses
  576. the native pixel format.
  577. Arguments:
  578. Context - Supplies a pointer to the initialized base video context.
  579. Palette - Supplies the natural palette to convert.
  580. PhysicalPalette - Supplies a pointer where the palette in native pixel
  581. format will be returned.
  582. Return Value:
  583. None.
  584. --*/
  585. {
  586. ULONG BlueBit;
  587. ULONG BlueMask;
  588. ULONG ColorIndex;
  589. ULONG GreenBit;
  590. ULONG GreenMask;
  591. ULONG RedBit;
  592. ULONG RedMask;
  593. COLOR_TRANSLATION Translation;
  594. if (Context->Mode == BaseVideoModeBiosText) {
  595. for (ColorIndex = 0; ColorIndex < AnsiColorCount; ColorIndex += 1) {
  596. PhysicalPalette->AnsiColor[ColorIndex] =
  597. VidTextModeColors[ColorIndex];
  598. PhysicalPalette->BoldAnsiColor[ColorIndex] =
  599. VidTextModeColors[ColorIndex] + 8;
  600. }
  601. PhysicalPalette->DefaultBackground = VidTextModeColors[AnsiColorBlack];
  602. PhysicalPalette->DefaultBoldBackground =
  603. VidTextModeColors[AnsiColorWhite];
  604. PhysicalPalette->CursorText = PhysicalPalette->DefaultBackground;
  605. PhysicalPalette->CursorBackground =
  606. PhysicalPalette->AnsiColor[AnsiColorDefault];
  607. goto ConvertPaletteEnd;
  608. }
  609. ASSERT(Context->Mode == BaseVideoModeFrameBuffer);
  610. RedMask = Context->RedMask;
  611. GreenMask = Context->GreenMask;
  612. BlueMask = Context->BlueMask;
  613. ASSERT((RedMask != 0) && (GreenMask != 0) && (BlueMask != 0));
  614. //
  615. // Handle some common cases.
  616. //
  617. if ((RedMask == 0x00FF0000) && (GreenMask == 0x0000FF00) &&
  618. (BlueMask == 0x000000FF)) {
  619. RtlCopyMemory(PhysicalPalette, Palette, sizeof(BASE_VIDEO_PALETTE));
  620. return;
  621. } else if ((RedMask == 0x000000FF) && (GreenMask == 0x0000FF00) &&
  622. (BlueMask == 0x00FF0000)) {
  623. for (ColorIndex = 0; ColorIndex < AnsiColorCount; ColorIndex += 1) {
  624. PhysicalPalette->AnsiColor[ColorIndex] =
  625. SWIZZLE_RED_BLUE(Palette->AnsiColor[ColorIndex]);
  626. PhysicalPalette->BoldAnsiColor[ColorIndex] =
  627. SWIZZLE_RED_BLUE(Palette->BoldAnsiColor[ColorIndex]);
  628. }
  629. PhysicalPalette->DefaultBackground =
  630. SWIZZLE_RED_BLUE(Palette->DefaultBackground);
  631. PhysicalPalette->DefaultBoldBackground =
  632. SWIZZLE_RED_BLUE(Palette->DefaultBoldBackground);
  633. PhysicalPalette->CursorText = SWIZZLE_RED_BLUE(Palette->CursorText);
  634. PhysicalPalette->CursorBackground =
  635. SWIZZLE_RED_BLUE(Palette->CursorBackground);
  636. return;
  637. }
  638. //
  639. // Create the translation shift and mask.
  640. //
  641. Translation.RedMask = RedMask;
  642. Translation.GreenMask = GreenMask;
  643. Translation.BlueMask = BlueMask;
  644. RedBit = VidpFindHighestBitSet(Translation.RedMask) + 1;
  645. GreenBit = VidpFindHighestBitSet(Translation.GreenMask) + 1;
  646. BlueBit = VidpFindHighestBitSet(Translation.BlueMask) + 1;
  647. Translation.RedShift = RedBit - (3 * BITS_PER_BYTE);
  648. Translation.GreenShift = GreenBit - (2 * BITS_PER_BYTE);
  649. Translation.BlueShift = BlueBit - BITS_PER_BYTE;
  650. //
  651. // Translate all the colors in the palette.
  652. //
  653. for (ColorIndex = 0; ColorIndex < AnsiColorCount; ColorIndex += 1) {
  654. PhysicalPalette->AnsiColor[ColorIndex] =
  655. TRANSLATE_COLOR(Palette->AnsiColor[ColorIndex], Translation);
  656. PhysicalPalette->BoldAnsiColor[ColorIndex] =
  657. TRANSLATE_COLOR(Palette->BoldAnsiColor[ColorIndex], Translation);
  658. }
  659. PhysicalPalette->DefaultBackground =
  660. TRANSLATE_COLOR(Palette->DefaultBackground, Translation);
  661. PhysicalPalette->DefaultBoldBackground =
  662. TRANSLATE_COLOR(Palette->DefaultBoldBackground, Translation);
  663. PhysicalPalette->CursorText =
  664. TRANSLATE_COLOR(Palette->CursorText, Translation);
  665. PhysicalPalette->CursorBackground =
  666. TRANSLATE_COLOR(Palette->CursorBackground, Translation);
  667. ConvertPaletteEnd:
  668. return;
  669. }
  670. VOID
  671. VidpPrintCharacter (
  672. PBASE_VIDEO_CONTEXT Context,
  673. ULONG XCoordinate,
  674. ULONG YCoordinate,
  675. PBASE_VIDEO_CHARACTER Character
  676. )
  677. /*++
  678. Routine Description:
  679. This routine prints a character to the screen in the specified location.
  680. Arguments:
  681. Context - Supplies a pointer to the initialized base video context.
  682. XCoordinate - Supplies the column to write to.
  683. YCoordinate - Supplies the row to write to.
  684. Character - Supplies a pointer to the character to print.
  685. Return Value:
  686. None.
  687. --*/
  688. {
  689. USHORT Attributes;
  690. ANSI_COLOR BackgroundAnsiColor;
  691. ULONG BitIndex;
  692. ULONG ByteIndex;
  693. ULONG ColorOff;
  694. ULONG ColorOn;
  695. ULONG ColumnIndex;
  696. PUCHAR Data;
  697. PUSHORT Destination16;
  698. PULONG Destination32;
  699. PBYTE Destination8;
  700. PBASE_VIDEO_FONT Font;
  701. ANSI_COLOR ForegroundAnsiColor;
  702. ULONG HorizontalIndex;
  703. ULONG LineSize;
  704. PVOID LineStart;
  705. UCHAR RotateBuffer[8];
  706. ULONG RowIndex;
  707. BYTE Source;
  708. ULONG SourceIndex;
  709. ULONG SwapColor;
  710. ULONG VerticalIndex;
  711. ULONG YPixel;
  712. //
  713. // Get the colors to use.
  714. //
  715. ColorOn = Context->PhysicalPalette.AnsiColor[AnsiColorDefault];
  716. ColorOff = Context->PhysicalPalette.DefaultBackground;
  717. if (Character->Data.Attributes != 0) {
  718. Attributes = Character->Data.Attributes;
  719. if ((Attributes & BASE_VIDEO_CURSOR) != 0) {
  720. ColorOn = Context->PhysicalPalette.CursorText;
  721. ColorOff = Context->PhysicalPalette.CursorBackground;
  722. } else {
  723. BackgroundAnsiColor = (Attributes >> BASE_VIDEO_BACKGROUND_SHIFT) &
  724. BASE_VIDEO_COLOR_MASK;
  725. ForegroundAnsiColor = Attributes & BASE_VIDEO_COLOR_MASK;
  726. ColorOn = Context->PhysicalPalette.AnsiColor[ForegroundAnsiColor];
  727. if ((Attributes & BASE_VIDEO_FOREGROUND_BOLD) != 0) {
  728. ColorOn =
  729. Context->PhysicalPalette.BoldAnsiColor[ForegroundAnsiColor];
  730. }
  731. if (BackgroundAnsiColor != AnsiColorDefault) {
  732. ColorOff =
  733. Context->PhysicalPalette.AnsiColor[BackgroundAnsiColor];
  734. }
  735. if ((Attributes & BASE_VIDEO_BACKGROUND_BOLD) != 0) {
  736. ColorOff =
  737. Context->PhysicalPalette.BoldAnsiColor[BackgroundAnsiColor];
  738. if (BackgroundAnsiColor == AnsiColorDefault) {
  739. ColorOff = Context->PhysicalPalette.DefaultBoldBackground;
  740. }
  741. }
  742. if ((Attributes & BASE_VIDEO_NEGATIVE) != 0) {
  743. SwapColor = ColorOn;
  744. ColorOn = ColorOff;
  745. ColorOff = SwapColor;
  746. }
  747. }
  748. }
  749. //
  750. // Handle text mode differently.
  751. //
  752. if (Context->Mode == BaseVideoModeBiosText) {
  753. Destination16 = Context->FrameBuffer;
  754. Destination16 += (YCoordinate * Context->Width) + XCoordinate;
  755. *Destination16 = BIOS_TEXT_ATTRIBUTES(ColorOn, ColorOff) |
  756. (UCHAR)(Character->Data.Character);
  757. return;
  758. }
  759. //
  760. // Get the glyph data for that character.
  761. //
  762. Font = Context->Font;
  763. if ((Character->Data.Character < Font->FirstAsciiCode) ||
  764. (Character->Data.Character >=
  765. Font->FirstAsciiCode + Font->GlyphCount)) {
  766. ASSERT(Font->FirstAsciiCode <= ' ');
  767. SourceIndex = ' ' - Font->FirstAsciiCode;
  768. } else {
  769. SourceIndex = Character->Data.Character - Font->FirstAsciiCode;
  770. }
  771. //
  772. // Rotate the character if needed. For those wondering, this code takes
  773. // about 185 bytes on x86, and the rotated data storage saves about 192
  774. // bytes for the 5x7 and 4x6 fonts each.
  775. //
  776. if ((Font->Flags & BASE_VIDEO_FONT_ROTATED) != 0) {
  777. SourceIndex *= Font->GlyphBytesWidth * Font->GlyphWidth;
  778. Data = (PUCHAR)&(Font->Data[SourceIndex]);
  779. ASSERT((Font->GlyphWidth < sizeof(RotateBuffer)) &&
  780. (Font->GlyphHeight < sizeof(RotateBuffer)) &&
  781. (sizeof(RotateBuffer) <= BITS_PER_BYTE));
  782. //
  783. // The normal data format runs horizontally. Build it a horizontal
  784. // row at a time (assuming there will be left than 8).
  785. //
  786. for (RowIndex = 0; RowIndex < Font->GlyphHeight; RowIndex += 1) {
  787. Source = 0;
  788. //
  789. // The row's data is spread out since the data is stored a column
  790. // at a time. It's always the same bit (row) for each column.
  791. //
  792. for (ColumnIndex = 0;
  793. ColumnIndex < Font->GlyphWidth;
  794. ColumnIndex += 1) {
  795. BitIndex = RowIndex;
  796. if ((Data[ColumnIndex] & (1 << BitIndex)) != 0) {
  797. Source |= 1 << (BITS_PER_BYTE - 1 - ColumnIndex);
  798. }
  799. }
  800. RotateBuffer[RowIndex] = Source;
  801. }
  802. Data = RotateBuffer;
  803. } else {
  804. SourceIndex *= Font->GlyphBytesWidth * Font->GlyphHeight;
  805. Data = (PUCHAR)&(Font->Data[SourceIndex]);
  806. }
  807. //
  808. // Compute the starting address on the frame buffer.
  809. //
  810. YPixel = (YCoordinate * Font->CellHeight) * Context->PixelsPerScanLine;
  811. LineStart = Context->FrameBuffer +
  812. ((YPixel + (XCoordinate * Font->CellWidth)) *
  813. (Context->BitsPerPixel / BITS_PER_BYTE));
  814. LineSize = Context->PixelsPerScanLine *
  815. (Context->BitsPerPixel / BITS_PER_BYTE);
  816. //
  817. // Separate write loops for different pixel widths does mean more code,
  818. // but it skips conditionals in the inner loops, which are very hot.
  819. //
  820. switch (Context->BitsPerPixel) {
  821. case 8:
  822. for (VerticalIndex = 0;
  823. VerticalIndex < Font->GlyphHeight;
  824. VerticalIndex += 1) {
  825. Destination8 = LineStart;
  826. HorizontalIndex = 0;
  827. for (ByteIndex = 0;
  828. ByteIndex < Font->GlyphBytesWidth;
  829. ByteIndex += 1) {
  830. Source = *Data;
  831. BitIndex = 0;
  832. while ((BitIndex < BITS_PER_BYTE) &&
  833. (HorizontalIndex < Font->GlyphWidth)) {
  834. if ((Source & 0x80) != 0) {
  835. *Destination8 = (UCHAR)ColorOn;
  836. } else {
  837. *Destination8 = (UCHAR)ColorOff;
  838. }
  839. Destination8 += 1;
  840. HorizontalIndex += 1;
  841. Source <<= 1;
  842. BitIndex += 1;
  843. }
  844. Data += 1;
  845. }
  846. while (HorizontalIndex < Font->CellWidth) {
  847. *Destination8 = (UCHAR)ColorOff;
  848. Destination8 += 1;
  849. HorizontalIndex += 1;
  850. }
  851. LineStart += LineSize;
  852. }
  853. while (VerticalIndex < Font->CellHeight) {
  854. Destination8 = LineStart;
  855. for (HorizontalIndex = 0;
  856. HorizontalIndex < Font->CellWidth;
  857. HorizontalIndex += 1) {
  858. *Destination8 = (UCHAR)ColorOff;
  859. Destination8 += 1;
  860. }
  861. LineStart += LineSize;
  862. VerticalIndex += 1;
  863. }
  864. break;
  865. case 16:
  866. for (VerticalIndex = 0;
  867. VerticalIndex < Font->GlyphHeight;
  868. VerticalIndex += 1) {
  869. Destination16 = LineStart;
  870. HorizontalIndex = 0;
  871. for (ByteIndex = 0;
  872. ByteIndex < Font->GlyphBytesWidth;
  873. ByteIndex += 1) {
  874. Source = *Data;
  875. BitIndex = 0;
  876. while ((BitIndex < BITS_PER_BYTE) &&
  877. (HorizontalIndex < Font->GlyphWidth)) {
  878. if ((Source & 0x80) != 0) {
  879. *Destination16 = (USHORT)ColorOn;
  880. } else {
  881. *Destination16 = (USHORT)ColorOff;
  882. }
  883. Destination16 += 1;
  884. HorizontalIndex += 1;
  885. Source <<= 1;
  886. BitIndex += 1;
  887. }
  888. Data += 1;
  889. }
  890. while (HorizontalIndex < Font->CellWidth) {
  891. *Destination16 = (USHORT)ColorOff;
  892. Destination16 += 1;
  893. HorizontalIndex += 1;
  894. }
  895. LineStart += LineSize;
  896. }
  897. while (VerticalIndex < Font->CellHeight) {
  898. Destination16 = LineStart;
  899. for (HorizontalIndex = 0;
  900. HorizontalIndex < Font->CellWidth;
  901. HorizontalIndex += 1) {
  902. *Destination16 = (USHORT)ColorOff;
  903. Destination16 += 1;
  904. }
  905. LineStart += LineSize;
  906. VerticalIndex += 1;
  907. }
  908. break;
  909. case 24:
  910. for (VerticalIndex = 0;
  911. VerticalIndex < Font->GlyphHeight;
  912. VerticalIndex += 1) {
  913. Destination8 = LineStart;
  914. HorizontalIndex = 0;
  915. for (ByteIndex = 0;
  916. ByteIndex < Font->GlyphBytesWidth;
  917. ByteIndex += 1) {
  918. Source = *Data;
  919. BitIndex = 0;
  920. while ((BitIndex < BITS_PER_BYTE) &&
  921. (HorizontalIndex < Font->GlyphWidth)) {
  922. if ((Source & 0x80) != 0) {
  923. *Destination8 = (UCHAR)ColorOn;
  924. *(Destination8 + 1) = (UCHAR)(ColorOn >> 8);
  925. *(Destination8 + 2) = (UCHAR)(ColorOn >> 16);
  926. } else {
  927. *Destination8 = (UCHAR)ColorOff;
  928. *(Destination8 + 1) = (UCHAR)(ColorOff >> 8);
  929. *(Destination8 + 2) = (UCHAR)(ColorOff >> 16);
  930. }
  931. Destination8 += 3;
  932. HorizontalIndex += 1;
  933. Source <<= 1;
  934. BitIndex += 1;
  935. }
  936. Data += 1;
  937. }
  938. while (HorizontalIndex < Font->CellWidth) {
  939. *Destination8 = (UCHAR)ColorOff;
  940. *(Destination8 + 1) = (UCHAR)(ColorOff >> 8);
  941. *(Destination8 + 2) = (UCHAR)(ColorOff >> 16);
  942. Destination8 += 3;
  943. HorizontalIndex += 1;
  944. }
  945. LineStart += LineSize;
  946. }
  947. while (VerticalIndex < Font->CellHeight) {
  948. Destination8 = LineStart;
  949. for (HorizontalIndex = 0;
  950. HorizontalIndex < Font->CellWidth;
  951. HorizontalIndex += 1) {
  952. *Destination8 = (UCHAR)ColorOff;
  953. *(Destination8 + 1) = (UCHAR)(ColorOff >> 8);
  954. *(Destination8 + 2) = (UCHAR)(ColorOff >> 16);
  955. Destination8 += 3;
  956. }
  957. LineStart += LineSize;
  958. VerticalIndex += 1;
  959. }
  960. break;
  961. case 32:
  962. for (VerticalIndex = 0;
  963. VerticalIndex < Font->GlyphHeight;
  964. VerticalIndex += 1) {
  965. Destination32 = LineStart;
  966. HorizontalIndex = 0;
  967. for (ByteIndex = 0;
  968. ByteIndex < Font->GlyphBytesWidth;
  969. ByteIndex += 1) {
  970. Source = *Data;
  971. BitIndex = 0;
  972. while ((BitIndex < BITS_PER_BYTE) &&
  973. (HorizontalIndex < Font->GlyphWidth)) {
  974. if ((Source & 0x80) != 0) {
  975. *Destination32 = ColorOn;
  976. } else {
  977. *Destination32 = ColorOff;
  978. }
  979. Destination32 += 1;
  980. HorizontalIndex += 1;
  981. Source <<= 1;
  982. BitIndex += 1;
  983. }
  984. Data += 1;
  985. }
  986. while (HorizontalIndex < Font->CellWidth) {
  987. *Destination32 = ColorOff;
  988. Destination32 += 1;
  989. HorizontalIndex += 1;
  990. }
  991. LineStart += LineSize;
  992. }
  993. while (VerticalIndex < Font->CellHeight) {
  994. Destination32 = LineStart;
  995. for (HorizontalIndex = 0;
  996. HorizontalIndex < Font->CellWidth;
  997. HorizontalIndex += 1) {
  998. *Destination32 = ColorOff;
  999. Destination32 += 1;
  1000. }
  1001. LineStart += LineSize;
  1002. VerticalIndex += 1;
  1003. }
  1004. break;
  1005. default:
  1006. ASSERT(FALSE);
  1007. break;
  1008. }
  1009. return;
  1010. }
  1011. VOID
  1012. VidpConvertIntegerToString (
  1013. LONG Integer,
  1014. PSTR String,
  1015. ULONG Base
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This routine converts an integer to a string.
  1020. Arguments:
  1021. Integer - Supplies the signed integer to convert to string format.
  1022. String - Supplies a pointer to the allocated buffer where the string
  1023. will be written.
  1024. Base - Supplies the base of the number to print, from 2 to 16.
  1025. Return Value:
  1026. None.
  1027. --*/
  1028. {
  1029. ULONG CurrentPosition;
  1030. BOOL Positive;
  1031. CurrentPosition = 0;
  1032. Positive = TRUE;
  1033. //
  1034. // Parameter checking.
  1035. //
  1036. if (String == NULL) {
  1037. return;
  1038. }
  1039. if ((Base < 2) || (Base > 16)) {
  1040. *String = '\0';
  1041. return;
  1042. }
  1043. //
  1044. // Only deal with positive numbers, but remember if the number was negative.
  1045. //
  1046. if ((Integer < 0) && (Base == 10)) {
  1047. Positive = FALSE;
  1048. Integer = -Integer;
  1049. }
  1050. //
  1051. // Loop over the integer, getting the least significant digit each
  1052. // iteration. Note that this causes the string to come out backwards, which
  1053. // is why the string is reversed before it is returned.
  1054. //
  1055. do {
  1056. String[CurrentPosition] = (Integer % Base) + '0';
  1057. if (String[CurrentPosition] > '9') {
  1058. String[CurrentPosition] = (Integer % Base) - 10 + 'A';
  1059. }
  1060. CurrentPosition += 1;
  1061. Integer = Integer / Base;
  1062. } while (Integer > 0);
  1063. //
  1064. // Print out the negative sign at the end.
  1065. //
  1066. if (Positive == FALSE) {
  1067. String[CurrentPosition] = '-';
  1068. CurrentPosition += 1;
  1069. }
  1070. //
  1071. // Pad spaces to at least 8.
  1072. //
  1073. while (CurrentPosition < 8) {
  1074. String[CurrentPosition] = ' ';
  1075. CurrentPosition += 1;
  1076. }
  1077. //
  1078. // Null terminate and reverse the string.
  1079. //
  1080. String[CurrentPosition] = '\0';
  1081. RtlStringReverse(String, String + CurrentPosition);
  1082. return;
  1083. }
  1084. ULONG
  1085. VidpFindHighestBitSet (
  1086. ULONG Value
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. This routine finds the highest bit set in the given 32-bit integer.
  1091. Arguments:
  1092. Value - Supplies the value to find the highest bit number of.
  1093. Return Value:
  1094. Returns the index of the highest bit set.
  1095. --*/
  1096. {
  1097. ULONG Index;
  1098. Index = (sizeof(ULONG) * BITS_PER_BYTE) - 1;
  1099. while (TRUE) {
  1100. if ((Value & (1 << Index)) != 0) {
  1101. return Index;
  1102. }
  1103. if (Index == 0) {
  1104. break;
  1105. }
  1106. Index -= 1;
  1107. }
  1108. return Index;
  1109. }