Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1427 lines
29 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. disp_gr.c
  5. Abstract:
  6. This file was created from \private\windows\setup\textmode\splib\ixdispj.c.
  7. This file contains routines to display MBCS characters to the Graphics
  8. VRAM.
  9. Author:
  10. v-junm (Compaq Japan)
  11. hideyukn
  12. tedm
  13. Environment:
  14. Kernel mode only.
  15. Revision History:
  16. --*/
  17. #include "bootx86.h"
  18. #include "displayp.h"
  19. #include "bootfont.h"
  20. #include "vmode.h"
  21. //
  22. // Physical video attributes.
  23. //
  24. #define VIDEO_BUFFER_VA 0xa0000
  25. #define VIDEO_BYTES_PER_SCAN_LINE 80
  26. #define VIDEO_WIDTH_PIXELS 640
  27. #define VIDEO_HEIGHT_SCAN_LINES 480
  28. #define VIDEO_SIZE_BYTES (VIDEO_BYTES_PER_SCAN_LINE*VIDEO_HEIGHT_SCAN_LINES)
  29. PUCHAR GrVp = (PUCHAR)VIDEO_BUFFER_VA;
  30. //
  31. // Screen width and height in half-character cells
  32. // and macro to determine total number of characters
  33. // displayed on the screen at once.
  34. //
  35. unsigned ScreenWidthCells,ScreenHeightCells;
  36. #define SCREEN_SIZE_CELLS (ScreenWidthCells*ScreenHeightCells)
  37. //
  38. // Globals:
  39. //
  40. // CharacterCellHeight is the number of scan lines total in a character.
  41. // It includes any top or bottom fill lines.
  42. //
  43. // CharacterImageHeight is the number of scan lines in the image of a character.
  44. // This is dependent on the font. Characters may be padded top and bottom.
  45. //
  46. // NOTE: All of this code assumes the font's single-byte characters are 8 bits wide
  47. // and the font's double-byte characters are 16 bits wide!
  48. //
  49. unsigned CharacterCellHeight;
  50. unsigned CharacterImageHeight;
  51. unsigned CharacterTopPad;
  52. unsigned CharacterBottomPad;
  53. #define VIDEO_BYTES_PER_TEXT_ROW (VIDEO_BYTES_PER_SCAN_LINE*CharacterCellHeight)
  54. //
  55. // Values describing the number of each type of character in the font,
  56. // and pointers to the base of the glyphs.
  57. //
  58. unsigned SbcsCharCount;
  59. unsigned DbcsCharCount;
  60. PUCHAR SbcsImages;
  61. PUCHAR DbcsImages;
  62. //
  63. // Values to be passed to GrDisplayMBCSChar
  64. //
  65. #define SBCSWIDTH 8
  66. #define DBCSWIDTH 16
  67. //
  68. // Lead byte table. Read from bootfont.bin.
  69. //
  70. UCHAR LeadByteTable[2*(MAX_DBCS_RANGE+1)];
  71. VOID
  72. GrDisplayMBCSChar(
  73. IN PUCHAR image,
  74. IN unsigned width,
  75. IN UCHAR top,
  76. IN UCHAR bottom
  77. );
  78. PUCHAR
  79. GrGetDBCSFontImage(
  80. USHORT Code
  81. );
  82. PUCHAR
  83. GrGetSBCSFontImage(
  84. UCHAR Code
  85. );
  86. VOID
  87. GrWriteSBCSChar(
  88. IN UCHAR c
  89. )
  90. /*++
  91. Routine Description:
  92. Displays a character at the current cursor position. ONLY SBCS
  93. characters can be displayed using this routine.
  94. Arguments:
  95. c - character to display.
  96. Return Value:
  97. None.
  98. --*/
  99. {
  100. unsigned u;
  101. PUCHAR pImage;
  102. UCHAR temp;
  103. switch(c) {
  104. case '\n':
  105. if(TextRow == (ScreenHeightCells-1)) {
  106. TextGrScrollDisplay();
  107. TextSetCursorPosition(0,TextRow);
  108. } else {
  109. TextSetCursorPosition(0,TextRow+1);
  110. }
  111. break;
  112. case '\r':
  113. break; // ignore
  114. case '\t':
  115. temp = ' ';
  116. u = 8 - (TextColumn % 8);
  117. while(u--) {
  118. TextGrCharOut(&temp);
  119. }
  120. TextSetCursorPosition(TextColumn+u,TextRow);
  121. break;
  122. default:
  123. //
  124. // Assume it's a valid SBCS character.
  125. // Get font image for SBCS char.
  126. //
  127. pImage = GrGetSBCSFontImage(c);
  128. //
  129. // Display the SBCS char. Check for special graphics characters.
  130. // Add top and bottom extra pixels accordingly (otherwise the grids
  131. // don't connect properly, because of top and bottom spacing).
  132. //
  133. if ( c == 0x2 || c == 0x1 || c == 0x16 )
  134. GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x00, 0x24 );
  135. else if ( c == 0x4 || c == 0x3 || c == 0x15 )
  136. GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x24, 0x00 );
  137. else if ( c == 0x5 || c == 10 || c == 0x17 || c == 0x19 )
  138. GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x24, 0x24 );
  139. else
  140. GrDisplayMBCSChar( pImage, SBCSWIDTH, 0x00, 0x00 );
  141. }
  142. }
  143. VOID
  144. GrDisplayMBCSChar(
  145. IN PUCHAR image,
  146. IN unsigned width,
  147. IN UCHAR top,
  148. IN UCHAR bottom
  149. )
  150. /*++
  151. Routine Description:
  152. Displays a DBCS or a SBCS character at the current cursor
  153. position.
  154. Arguments:
  155. image - SBCS or DBCS font image.
  156. width - Width in bits of character image (must be SBCSWIDTH pr DBCSWIDTH).
  157. top - Character to fill the top extra character line(s).
  158. bottom- Character to fill the bottom extra character line(s).
  159. Return Value:
  160. FALSE if image points to NULL,
  161. else TRUE.
  162. --*/
  163. {
  164. unsigned i;
  165. PUCHAR VpOld = GrVp;
  166. //
  167. // Validate parameter
  168. //
  169. if(image == NULL) {
  170. return;
  171. }
  172. //
  173. // There are TOP_EXTRA lines at the top that we need to skip (background color).
  174. //
  175. for(i=0; i<CharacterTopPad; i++) {
  176. //
  177. // If DBCS char, we need to clear 2 bytes.
  178. //
  179. if(width == DBCSWIDTH) {
  180. *GrVp++ = top;
  181. }
  182. *GrVp++ = top;
  183. //
  184. // Position pointer at next scan line
  185. // for the font image.
  186. //
  187. GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH);
  188. }
  189. //
  190. // Display full height of DBCS or SBCS char.
  191. //
  192. for(i=0; i<CharacterImageHeight; i++) {
  193. //
  194. // If DBCS char, need to display 2 bytes,
  195. // so display first byte here.
  196. //
  197. if(width == DBCSWIDTH) {
  198. *GrVp++ = *image++;
  199. }
  200. //
  201. // Display 2nd byte of DBCS char or the
  202. // first and only byte of SBCS char.
  203. //
  204. *GrVp++ = *image++;
  205. //
  206. // Increment GrVP to display location of
  207. // next row of font image.
  208. //
  209. GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH);
  210. }
  211. //
  212. // There are BOT_EXTRA lines at the bottom that we need to fill with the
  213. // background color.
  214. //
  215. for(i=0; i<CharacterBottomPad; i++) {
  216. //
  217. // If DBCS char, need to clear 2 bytes
  218. //
  219. if(width == DBCSWIDTH) {
  220. *GrVp++ = bottom;
  221. }
  222. *GrVp++ = bottom;
  223. //
  224. // Position pointer at next scan line
  225. // for the font image.
  226. //
  227. GrVp += VIDEO_BYTES_PER_SCAN_LINE - (width/SBCSWIDTH);
  228. }
  229. //
  230. // Increment cursor and video pointer
  231. //
  232. if(width == DBCSWIDTH) {
  233. TextSetCursorPosition(TextColumn+2,TextRow);
  234. } else {
  235. TextSetCursorPosition(TextColumn+1,TextRow);
  236. }
  237. }
  238. unsigned
  239. GrWriteMBCSString(
  240. IN PUCHAR String,
  241. IN unsigned MaxChars
  242. )
  243. /*++
  244. Routine Description:
  245. Displays a mixed byte string at the current cursor
  246. position.
  247. Arguments:
  248. String - supplies pointer to asciz string.
  249. MaxBytes - supplies the maximum number of characters to be written.
  250. Return Value:
  251. Number of bytes written.
  252. --*/
  253. {
  254. PCHAR pImage;
  255. USHORT DBCSChar;
  256. unsigned BytesWritten;
  257. BytesWritten = 0;
  258. //
  259. // While string is not NULL,
  260. // get font image and display it.
  261. //
  262. while(*String && MaxChars--) {
  263. //
  264. // Determine if char is SBCS or DBCS, get the correct font image,
  265. // and display it.
  266. //
  267. if(GrIsDBCSLeadByte(*String)) {
  268. DBCSChar = *String++ << 8;
  269. DBCSChar = DBCSChar | *String++;
  270. pImage = GrGetDBCSFontImage(DBCSChar);
  271. GrDisplayMBCSChar(pImage,DBCSWIDTH,0x00,0x00);
  272. BytesWritten++;
  273. } else {
  274. GrWriteSBCSChar(*String++);
  275. }
  276. BytesWritten++;
  277. }
  278. return(BytesWritten);
  279. }
  280. BOOLEAN
  281. GrIsDBCSLeadByte(
  282. IN UCHAR c
  283. )
  284. /*++
  285. Routine Description:
  286. Checks to see if a char is a DBCS leadbyte.
  287. Arguments:
  288. c - char to check if leadbyte or not.
  289. Return Value:
  290. TRUE - Leadbyte.
  291. FALSE - Non-Leadbyte.
  292. --*/
  293. {
  294. int i;
  295. //
  296. // Check to see if char is in leadbyte range.
  297. // Note if (CHAR)(0) is a valid leadbyte,
  298. // this routine will fail.
  299. //
  300. for(i=0; LeadByteTable[i]; i+=2) {
  301. if((LeadByteTable[i] <= c) && (LeadByteTable[i+1] >= c)) {
  302. return(TRUE);
  303. }
  304. }
  305. return(FALSE);
  306. }
  307. PUCHAR
  308. GrGetDBCSFontImage(
  309. USHORT Code
  310. )
  311. /*++
  312. Routine Description:
  313. Gets the font image for DBCS char.
  314. Arguments:
  315. Code - DBCS char code.
  316. Return Value:
  317. Pointer to font image, or else NULL.
  318. --*/
  319. {
  320. int Min,Max,Mid;
  321. int Multiplier;
  322. int Index;
  323. USHORT code;
  324. Min = 0;
  325. Max = DbcsCharCount;
  326. // multiplier = 2 (for index) +
  327. // 2 * height +
  328. // 2 (for unicode encoding)
  329. //
  330. Multiplier = 2 + (2*CharacterImageHeight) + 2;
  331. //
  332. // Do a binary search for the image.
  333. // Format of table:
  334. // First 2 bytes contain the DBCS char code.
  335. // Next (2 * CharacterImageHeight) bytes are the char image.
  336. // Next 2 bytes are for unicode version.
  337. //
  338. while(Max >= Min) {
  339. Mid = (Max + Min) / 2;
  340. Index = Mid*Multiplier;
  341. code = (DbcsImages[Index] << 8) | DbcsImages[Index+1];
  342. if(Code == code) {
  343. return(DbcsImages+Index+2);
  344. }
  345. if(Code < code) {
  346. Max = Mid - 1;
  347. } else {
  348. Min = Mid + 1;
  349. }
  350. }
  351. //
  352. // ERROR: No image found.
  353. //
  354. return(NULL);
  355. }
  356. PUCHAR
  357. GrGetSBCSFontImage(
  358. UCHAR Code
  359. )
  360. /*++
  361. Routine Description:
  362. Gets the font image for SBCS char.
  363. Arguments:
  364. Code - SBCS char code.
  365. Return Value:
  366. Pointer to font image, or else NULL.
  367. --*/
  368. {
  369. int Max,Min,Mid;
  370. int Multiplier;
  371. int Index;
  372. Min = 0;
  373. Max = SbcsCharCount;
  374. // multiplier = 1 (for index) +
  375. // height +
  376. // 2 (for unicode encoding)
  377. //
  378. Multiplier = 1 + (CharacterImageHeight) + 2;
  379. //
  380. // Do a binary search for the image.
  381. // Format of table:
  382. // First byte contains the SBCS char code.
  383. // Next (CharacterImageHeight) bytes are the char image.
  384. // Next 2 bytes are for unicode version.
  385. //
  386. while(Max >= Min) {
  387. Mid = (Max + Min) / 2;
  388. Index = Mid*Multiplier;
  389. if(Code == SbcsImages[Index]) {
  390. return(SbcsImages+Index+1);
  391. }
  392. if(Code < SbcsImages[Index]) {
  393. Max = Mid - 1;
  394. } else {
  395. Min = Mid + 1;
  396. }
  397. }
  398. //
  399. // ERROR: No image found.
  400. //
  401. return(NULL);
  402. }
  403. //
  404. // Need to turn off optimization for this
  405. // routine. Since the write and read to
  406. // GVRAM seem useless to the compiler.
  407. //
  408. #pragma optimize( "", off )
  409. VOID
  410. TextGrSetCurrentAttribute(
  411. IN UCHAR Attribute
  412. )
  413. /*++
  414. Routine Description:
  415. Sets the attribute by setting up various VGA registers.
  416. The comments only say what registers are set to what, so
  417. to understand the logic, follow the code while looking at
  418. Figure 5-5 of PC&PS/2 Video Systems by Richard Wilton.
  419. The book is published by Microsoft Press.
  420. Arguments:
  421. Attribute - New attribute to set to.
  422. Attribute:
  423. High nibble - background attribute.
  424. Low nibble - foreground attribute.
  425. Return Value:
  426. Nothing.
  427. --*/
  428. {
  429. UCHAR temp = 0;
  430. //
  431. // Address of GVRAM off the screen.
  432. //
  433. PUCHAR OffTheScreen = (PUCHAR)(0xa9600);
  434. union WordOrByte {
  435. struct Word { unsigned short ax; } x;
  436. struct Byte { unsigned char al, ah; } h;
  437. } regs;
  438. //
  439. // Reset Data Rotate/Function Select
  440. // regisger.
  441. //
  442. outpw( 0x3ce, 0x3 ); // Need to reset Data Rotate/Function Select.
  443. //
  444. // Set Enable Set/Reset to
  445. // all (0f).
  446. //
  447. outpw( 0x3ce, 0xf01 );
  448. //
  449. // Put background color into Set/Reset register.
  450. // This is done to put the background color into
  451. // the latches later.
  452. //
  453. regs.x.ax = (unsigned short)(Attribute & 0x0f0) << 4;
  454. outpw( 0x3ce, regs.x.ax ); // Put BLUE color in Set/Reset register.
  455. //
  456. // Put Set/Reset register value into GVRAM
  457. // off the screen.
  458. //
  459. *OffTheScreen = temp;
  460. //
  461. // Read from screen, so the latches will be
  462. // updated with the background color.
  463. //
  464. temp = *OffTheScreen;
  465. //
  466. // Set Data Rotate/Function Select register
  467. // to be XOR.
  468. //
  469. outpw( 0x3ce, 0x1803 );
  470. //
  471. // XOR the foreground and background color and
  472. // put it in Set/Reset register.
  473. //
  474. regs.h.ah = (Attribute >> 4) ^ (Attribute & 0x0f);
  475. regs.h.al = 0;
  476. outpw( 0x3ce, regs.x.ax );
  477. //
  478. // Put Inverse(~) of the XOR of foreground and
  479. // ground attribute into Enable Set/Reset register.
  480. //
  481. regs.x.ax = ~regs.x.ax & 0x0f01;
  482. outpw( 0x3ce, regs.x.ax );
  483. }
  484. //
  485. // Turn optimization on again.
  486. //
  487. #pragma optimize( "", on )
  488. VOID
  489. TextGrPositionCursor(
  490. USHORT Row,
  491. USHORT Column
  492. )
  493. /*++
  494. Routine Description:
  495. Sets the position of the soft cursor. That is, it doesn't move the
  496. hardware cursor but sets the location of the next write to the
  497. screen.
  498. Arguments:
  499. Row - Row coordinate of where character is to be written.
  500. Column - Column coordinate of where character is to be written.
  501. Returns:
  502. Nothing.
  503. --*/
  504. {
  505. if(Row >= ScreenHeightCells) {
  506. Row = ScreenHeightCells-1;
  507. }
  508. if(Column >= ScreenWidthCells) {
  509. Column = ScreenWidthCells-1;
  510. }
  511. GrVp = (PUCHAR)VIDEO_BUFFER_VA + (Row * VIDEO_BYTES_PER_TEXT_ROW) + Column;
  512. }
  513. VOID
  514. TextGrStringOut(
  515. IN PUCHAR String
  516. )
  517. {
  518. GrWriteMBCSString(String,(unsigned)(-1));
  519. }
  520. PUCHAR
  521. TextGrCharOut(
  522. PUCHAR pc
  523. )
  524. /*++
  525. Routine Description:
  526. Writes a character on the display at the current position.
  527. Newlines and tabs are interpreted and acted upon.
  528. Arguments:
  529. pc - pointer to mbcs character to write.
  530. Returns:
  531. pointer to next character
  532. --*/
  533. {
  534. return(pc + GrWriteMBCSString(pc,1));
  535. }
  536. VOID
  537. TextGrFillAttribute(
  538. IN UCHAR Attribute,
  539. IN ULONG Length
  540. )
  541. /*++
  542. Routine Description:
  543. Changes the screen attribute starting at the current cursor position.
  544. The cursor is not moved.
  545. Arguments:
  546. Attribute - Supplies the new attribute
  547. Length - Supplies the length of the area to change (in bytes)
  548. Return Value:
  549. None.
  550. --*/
  551. {
  552. UCHAR OldAttribute;
  553. unsigned i;
  554. ULONG x,y;
  555. PUCHAR pImage;
  556. //
  557. // Save the current attribute and set the attribute to the
  558. // character desired by the caller.
  559. //
  560. TextGetCursorPosition(&x,&y);
  561. OldAttribute = TextCurrentAttribute;
  562. TextSetCurrentAttribute(Attribute);
  563. //
  564. // Dirty hack: just write spaces into the area requested by the caller.
  565. //
  566. pImage = GrGetSBCSFontImage(' ');
  567. for(i=0; i<Length; i++) {
  568. GrDisplayMBCSChar(pImage,SBCSWIDTH,0x00,0x00);
  569. }
  570. //
  571. // Restore the current attribute.
  572. //
  573. TextSetCurrentAttribute(OldAttribute);
  574. TextSetCursorPosition(x,y);
  575. }
  576. VOID
  577. TextGrClearToEndOfLine(
  578. VOID
  579. )
  580. /*++
  581. Routine Description:
  582. Clears from the current cursor position to the end of the line
  583. by writing blanks with the current video attribute.
  584. The cursor position is not changed.
  585. Arguments:
  586. None
  587. Returns:
  588. Nothing
  589. --*/
  590. {
  591. unsigned u;
  592. ULONG OldX,OldY;
  593. UCHAR temp;
  594. //
  595. // Fill with blanks up to char before cursor position.
  596. //
  597. temp = ' ';
  598. TextGetCursorPosition(&OldX,&OldY);
  599. for(u=TextColumn; u<ScreenWidthCells; u++) {
  600. TextGrCharOut(&temp);
  601. }
  602. TextSetCursorPosition(OldX,OldY);
  603. }
  604. VOID
  605. TextGrClearFromStartOfLine(
  606. VOID
  607. )
  608. /*++
  609. Routine Description:
  610. Clears from the start of the line to the current cursor position
  611. by writing blanks with the current video attribute.
  612. The cursor position is not changed.
  613. Arguments:
  614. None
  615. Returns:
  616. Nothing
  617. --*/
  618. {
  619. unsigned u;
  620. ULONG OldX,OldY;
  621. UCHAR temp = ' ';
  622. //
  623. // Fill with blanks up to char before cursor position.
  624. //
  625. TextGetCursorPosition(&OldX,&OldY);
  626. TextSetCursorPosition(0,OldY);
  627. for(u=0; u<TextColumn; u++) {
  628. TextGrCharOut(&temp);
  629. }
  630. TextSetCursorPosition(OldX,OldY);
  631. }
  632. VOID
  633. TextGrClearToEndOfDisplay(
  634. VOID
  635. )
  636. /*++
  637. Routine Description:
  638. Clears from the current cursor position to the end of the video
  639. display by writing blanks with the current video attribute.
  640. The cursor position is not changed.
  641. Arguments:
  642. None
  643. Returns:
  644. Nothing
  645. --*/
  646. {
  647. unsigned i;
  648. //
  649. // Clear current line
  650. //
  651. TextGrClearToEndOfLine();
  652. //
  653. // Clear the remaining lines
  654. //
  655. for(i=(TextRow+1)*VIDEO_BYTES_PER_TEXT_ROW; i<VIDEO_SIZE_BYTES; i++) {
  656. ((PUCHAR)VIDEO_BUFFER_VA)[i] = 0x00;
  657. }
  658. }
  659. VOID
  660. TextGrClearDisplay(
  661. VOID
  662. )
  663. /*++
  664. Routine Description:
  665. Clears the text-mode video display by writing blanks with
  666. the current video attribute over the entire display.
  667. Arguments:
  668. None
  669. Returns:
  670. Nothing
  671. --*/
  672. {
  673. unsigned i;
  674. //
  675. // Clear screen.
  676. //
  677. for(i=0; i<VIDEO_SIZE_BYTES; i++) {
  678. ((PUCHAR)VIDEO_BUFFER_VA)[i] = 0x00;
  679. }
  680. }
  681. VOID
  682. TextGrScrollDisplay(
  683. VOID
  684. )
  685. /*++
  686. Routine Description:
  687. Scrolls the display up one line. The cursor position is not changed.
  688. Arguments:
  689. None
  690. Returns:
  691. Nothing
  692. --*/
  693. {
  694. PUCHAR Source,Dest;
  695. unsigned n,i;
  696. ULONG OldX,OldY;
  697. UCHAR temp = ' ';
  698. Source = (PUCHAR)(VIDEO_BUFFER_VA) + VIDEO_BYTES_PER_TEXT_ROW;
  699. Dest = (PUCHAR)VIDEO_BUFFER_VA;
  700. n = VIDEO_BYTES_PER_TEXT_ROW * (ScreenHeightCells-1);
  701. for(i=0; i<n; i++) {
  702. *Dest++ = *Source++;
  703. }
  704. //
  705. // Write blanks in the bottom line, using the current attribute.
  706. //
  707. TextGetCursorPosition(&OldX,&OldY);
  708. TextSetCursorPosition(0,ScreenHeightCells-1);
  709. for(i=0; i<ScreenWidthCells; i++) {
  710. TextGrCharOut(&temp);
  711. }
  712. TextSetCursorPosition(OldX,OldY);
  713. }
  714. UCHAR GrGraphicsChars[GraphicsCharMax] = { 1,2,3,4,5,6 };
  715. UCHAR
  716. TextGrGetGraphicsChar(
  717. IN GraphicsChar WhichOne
  718. )
  719. {
  720. return(GrGraphicsChars[WhichOne]);
  721. }
  722. VOID
  723. TextGrInitialize(
  724. IN ULONG DiskId,
  725. OUT PULONG ImageLength
  726. )
  727. {
  728. ULONG FileId;
  729. ARC_STATUS Status;
  730. PUCHAR FontImage;
  731. ULONG BytesRead;
  732. BOOTFONTBIN_HEADER FileHeader;
  733. LARGE_INTEGER SeekOffset;
  734. ULONG SbcsSize,DbcsSize;
  735. if (ImageLength) {
  736. *ImageLength = 0;
  737. }
  738. //
  739. // Attempt to open bootfont.bin. If this fails, then boot in single-byte charset mode.
  740. //
  741. if (BlBootingFromNet
  742. #if defined(REMOTE_BOOT)
  743. && NetworkBootRom
  744. #endif // defined(REMOTE_BOOT)
  745. ) {
  746. CHAR Buffer[129];
  747. strcpy(Buffer, NetBootPath);
  748. strcat(Buffer, "BOOTFONT.BIN");
  749. Status = BlOpen(DiskId,Buffer,ArcOpenReadOnly,&FileId);
  750. } else {
  751. Status = BlOpen(DiskId,"\\BOOTFONT.BIN",ArcOpenReadOnly,&FileId);
  752. }
  753. if(Status != ESUCCESS) {
  754. goto clean0;
  755. }
  756. //
  757. // Read in the file header and check some values.
  758. // We enforce the width of 8/16 here. If this is changed code all over the
  759. // rest of this module must also be changed.
  760. //
  761. Status = BlRead(FileId,&FileHeader,sizeof(BOOTFONTBIN_HEADER),&BytesRead);
  762. if((Status != ESUCCESS)
  763. || (BytesRead != sizeof(BOOTFONTBIN_HEADER))
  764. || (FileHeader.Signature != BOOTFONTBIN_SIGNATURE)
  765. || (FileHeader.CharacterImageSbcsWidth != 8)
  766. || (FileHeader.CharacterImageDbcsWidth != 16)
  767. ) {
  768. goto clean1;
  769. }
  770. //
  771. // Calculate the amount of memory needed to hold the sbcs and dbcs
  772. // character entries. Each sbcs entry is 1 byte for the ascii value
  773. // followed by n bytes for the image itself. We assume a width of 8 pixels.
  774. // For dbcs chars each entry is 2 bytes for the codepoint and n bytes
  775. // for the image itself. We assume a width of 16 pixels.
  776. //
  777. // Add in an extra 2 bytes per entry for the ending unicode value of the SBCS/DBCS
  778. // character.
  779. //
  780. // Also perform further validation on the file by comparing the sizes
  781. // given in the header against a size we calculate.
  782. //
  783. SbcsSize = FileHeader.NumSbcsChars * (FileHeader.CharacterImageHeight + 1 + 2);
  784. DbcsSize = FileHeader.NumDbcsChars * ((2 * FileHeader.CharacterImageHeight) + 2 + 2);
  785. if((SbcsSize != FileHeader.SbcsEntriesTotalSize)
  786. || (DbcsSize != FileHeader.DbcsEntriesTotalSize)) {
  787. goto clean1;
  788. }
  789. //
  790. // save off the image length argument if requested
  791. //
  792. if (ImageLength) {
  793. (*ImageLength) = sizeof(BOOTFONTBIN_HEADER) + SbcsSize + DbcsSize;
  794. }
  795. //
  796. // Allocate memory to hold the font. We use FwAllocatePool() because
  797. // that routine uses a separate heap that was inititialized before the
  798. // high-level Bl memory system was initialized, and thus is safe.
  799. //
  800. FontImage = FwAllocatePool(SbcsSize+DbcsSize);
  801. if(!FontImage) {
  802. goto clean1;
  803. }
  804. //
  805. // The entries get read into the base of the region we carved out.
  806. // The dbcs images get read in immediately after that.
  807. //
  808. SbcsImages = FontImage;
  809. DbcsImages = SbcsImages + FileHeader.SbcsEntriesTotalSize;
  810. //
  811. // Read in the sbcs entries.
  812. //
  813. SeekOffset.HighPart = 0;
  814. SeekOffset.LowPart = FileHeader.SbcsOffset;
  815. if((BlSeek(FileId,&SeekOffset,SeekAbsolute) != ESUCCESS)
  816. || (BlRead(FileId,SbcsImages,FileHeader.SbcsEntriesTotalSize,&BytesRead) != ESUCCESS)
  817. || (BytesRead != FileHeader.SbcsEntriesTotalSize)) {
  818. goto clean2;
  819. }
  820. //
  821. // Read in the dbcs entries.
  822. //
  823. SeekOffset.HighPart = 0;
  824. SeekOffset.LowPart = FileHeader.DbcsOffset;
  825. if((BlSeek(FileId,&SeekOffset,SeekAbsolute) != ESUCCESS)
  826. || (BlRead(FileId,DbcsImages,FileHeader.DbcsEntriesTotalSize,&BytesRead) != ESUCCESS)
  827. || (BytesRead != FileHeader.DbcsEntriesTotalSize)) {
  828. goto clean2;
  829. }
  830. //
  831. // We're done with the file now.
  832. //
  833. BlClose(FileId);
  834. //
  835. // Set up various values used for displaying the font.
  836. //
  837. DbcsLangId = FileHeader.LanguageId;
  838. CharacterImageHeight = FileHeader.CharacterImageHeight;
  839. CharacterTopPad = FileHeader.CharacterTopPad;
  840. CharacterBottomPad = FileHeader.CharacterBottomPad;
  841. CharacterCellHeight = CharacterImageHeight + CharacterTopPad + CharacterBottomPad;
  842. SbcsCharCount = FileHeader.NumSbcsChars;
  843. DbcsCharCount = FileHeader.NumDbcsChars;
  844. ScreenWidthCells = VIDEO_WIDTH_PIXELS / FileHeader.CharacterImageSbcsWidth;
  845. ScreenHeightCells = VIDEO_HEIGHT_SCAN_LINES / CharacterCellHeight;
  846. RtlMoveMemory(LeadByteTable,FileHeader.DbcsLeadTable,(MAX_DBCS_RANGE+1)*2);
  847. //
  848. // Switch the display into 640x480 graphics mode and clear it.
  849. // We're done.
  850. //
  851. HW_CURSOR(0x80000000,0x12);
  852. TextClearDisplay();
  853. return;
  854. clean2:
  855. //
  856. // Want to free the memory we allocated but there's no routine to do it
  857. //
  858. //FwFreePool();
  859. clean1:
  860. //
  861. // Close the font file.
  862. //
  863. BlClose(FileId);
  864. clean0:
  865. return;
  866. }
  867. VOID
  868. TextGrTerminate(
  869. VOID
  870. )
  871. {
  872. if(DbcsLangId) {
  873. DbcsLangId = 0;
  874. //
  875. // This command switches the display into 80x25 text mode
  876. // if there is no bitmap logo displayed. The logo is common
  877. // to the loader and bootvid, and in this case we don't want
  878. // to switch to text mode and then back to graphics.
  879. //
  880. if(!GraphicsMode)
  881. HW_CURSOR(0x80000000,0x3);
  882. }
  883. }
  884. VOID
  885. UTF8Encode(
  886. USHORT InputValue,
  887. PUCHAR UTF8Encoding
  888. )
  889. /*++
  890. Routine Description:
  891. Generates the UTF8 translation for a 16-bit value.
  892. Arguments:
  893. InputValue - 16-bit value to be encoded.
  894. UTF8Encoding - receives the UTF8-encoding of the 16-bit value
  895. Return Value:
  896. NONE.
  897. --*/
  898. {
  899. //
  900. // convert into UTF8 for actual transmission
  901. //
  902. // UTF-8 encodes 2-byte Unicode characters as follows:
  903. // If the first nine bits are zero (00000000 0xxxxxxx), encode it as one byte 0xxxxxxx
  904. // If the first five bits are zero (00000yyy yyxxxxxx), encode it as two bytes 110yyyyy 10xxxxxx
  905. // Otherwise (zzzzyyyy yyxxxxxx), encode it as three bytes 1110zzzz 10yyyyyy 10xxxxxx
  906. //
  907. if( (InputValue & 0xFF80) == 0 ) {
  908. //
  909. // if the top 9 bits are zero, then just
  910. // encode as 1 byte. (ASCII passes through unchanged).
  911. //
  912. UTF8Encoding[2] = (UCHAR)(InputValue & 0xFF);
  913. } else if( (InputValue & 0xF700) == 0 ) {
  914. //
  915. // if the top 5 bits are zero, then encode as 2 bytes
  916. //
  917. UTF8Encoding[2] = (UCHAR)(InputValue & 0x3F) | 0x80;
  918. UTF8Encoding[1] = (UCHAR)((InputValue >> 6) & 0x1F) | 0xC0;
  919. } else {
  920. //
  921. // encode as 3 bytes
  922. //
  923. UTF8Encoding[2] = (UCHAR)(InputValue & 0x3F) | 0x80;
  924. UTF8Encoding[1] = (UCHAR)((InputValue >> 6) & 0x3F) | 0x80;
  925. UTF8Encoding[0] = (UCHAR)((InputValue >> 12) & 0xF) | 0xE0;
  926. }
  927. }
  928. VOID
  929. GetDBCSUtf8Translation(
  930. PUCHAR InputChar,
  931. PUCHAR UTF8Encoding
  932. )
  933. /*++
  934. Routine Description:
  935. Gets the UTF8 translation for a DBCS char.
  936. Arguments:
  937. InputChar - pointer to DBCS character code.
  938. UTF8Encoding - receives the UTF8-encoding of the DBCS character code
  939. Return Value:
  940. NONE.
  941. --*/
  942. {
  943. int Min,Max,Mid;
  944. int Multiplier;
  945. int Index;
  946. USHORT code;
  947. USHORT Code;
  948. Code = *InputChar++ << 8;
  949. Code = Code | *InputChar++;
  950. // initialize our output.
  951. for( Index = 0; Index < 3; Index++ ) {
  952. UTF8Encoding[Index] = 0;
  953. }
  954. Min = 0;
  955. Max = DbcsCharCount;
  956. //
  957. // multiplier = 2 (for index) +
  958. // 2* height +
  959. // 2 (for unicode encoding)
  960. //
  961. Multiplier = 2 + (2*CharacterImageHeight) + 2;
  962. //
  963. // Do a binary search for the image.
  964. // Format of table:
  965. // First 2 bytes contain the DBCS char code.
  966. // Next (2 * CharacterImageHeight) bytes are the char image.
  967. // Next 2 bytes are for unicode version.
  968. //
  969. while(Max >= Min) {
  970. Mid = (Max + Min) / 2;
  971. Index = Mid*Multiplier;
  972. code = (DbcsImages[Index] << 8) | (DbcsImages[Index+1]);
  973. if(Code == code) {
  974. WCHAR UnicodeValue = L'\0';
  975. PUCHAR Image = (PUCHAR)DbcsImages+Index+2;
  976. //
  977. // image is pointing to an array of uchars, which are
  978. // a bitmap of the character we want to display. Right
  979. // behind this array is the unicode encoding of the
  980. // character. Here's what the structure looks like:
  981. //
  982. // index bitmap unicode encoding of 'index'
  983. // ^ ^ ^
  984. // | | |
  985. // | | - we previously converted 'index' into
  986. // | | its unicode equivilent.
  987. // | |
  988. // | - This is where 'image' is pointing. It's an array of characters
  989. // | (2 * width in length), which represents the bitmap to be displayed
  990. // | on the screen which will represent the value in 'index'
  991. // |
  992. // - This is either an 8-bit value (if we're messing with SBCS), or a 16-bit value
  993. // (if we're dealing with DBCS), in which case 'width' will be DBCSWIDTH.
  994. //
  995. // We're going to jump over the bitmap and retrieve the unicode encoding. Then we'll
  996. // encode it into UTF8, then spew it over the headless port.
  997. //
  998. UnicodeValue = (WCHAR)( (Image[DBCSWIDTH*2]) | (Image[(DBCSWIDTH*2) + 1] << 8) );
  999. UTF8Encode( UnicodeValue,
  1000. UTF8Encoding );
  1001. return;
  1002. }
  1003. if(Code < code) {
  1004. Max = Mid - 1;
  1005. } else {
  1006. Min = Mid + 1;
  1007. }
  1008. }
  1009. //
  1010. // ERROR: No image found.
  1011. //
  1012. return;
  1013. }
  1014. VOID
  1015. GetSBCSUtf8Translation(
  1016. PUCHAR InputChar,
  1017. PUCHAR UTF8Encoding
  1018. )
  1019. /*++
  1020. Routine Description:
  1021. Gets the font image for SBCS char.
  1022. Arguments:
  1023. InputChar - pointer to SBCS character code.
  1024. UTF8Encoding - receives the UTF8-encoding of the SBCS character code
  1025. Return Value:
  1026. NONE.
  1027. --*/
  1028. {
  1029. int Max,Min,Mid;
  1030. int Multiplier;
  1031. int Index;
  1032. UCHAR Code = *InputChar;
  1033. // initialize our output.
  1034. for( Index = 0; Index < 3; Index++ ) {
  1035. UTF8Encoding[Index] = 0;
  1036. }
  1037. Min = 0;
  1038. Max = SbcsCharCount;
  1039. //
  1040. // multiplier = 1 (for index) +
  1041. // height +
  1042. // 2 (for unicode encoding)
  1043. //
  1044. Multiplier = 1 + (CharacterImageHeight) + 2;
  1045. //
  1046. // Do a binary search for the image.
  1047. // Format of table:
  1048. // First byte contain the SBCS char code.
  1049. // Next byte is the character code length in bytes (1 byte)
  1050. // After that is the UTF8 code string
  1051. // then the graphic char image
  1052. //
  1053. while(Max >= Min) {
  1054. Mid = (Max + Min) / 2;
  1055. Index = Mid*Multiplier;
  1056. if(Code == SbcsImages[Index]) {
  1057. WCHAR UnicodeValue = L'\0';
  1058. PUCHAR Image = (PUCHAR)SbcsImages+Index+1;
  1059. //
  1060. // For a description of the image format, see GetDBCSUtf8Translation().
  1061. //
  1062. UnicodeValue = (WCHAR)( (Image[SBCSWIDTH*2]) | (Image[(SBCSWIDTH*2) + 1] << 8) );
  1063. UTF8Encode( UnicodeValue,
  1064. UTF8Encoding );
  1065. return;
  1066. }
  1067. if(Code < SbcsImages[Index]) {
  1068. Max = Mid - 1;
  1069. } else {
  1070. Min = Mid + 1;
  1071. }
  1072. }
  1073. //
  1074. // ERROR: No image found.
  1075. //
  1076. return;
  1077. }