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.

883 lines
22 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. fefb.c (was textmode\kernel\spvidgfb.c)
  5. Abstract:
  6. Text setup display support for Frame Buffer displays.
  7. Author:
  8. Hideyuki Nagase (hideyukn) 01-July-1994
  9. Revision History:
  10. --*/
  11. #include <precomp.h>
  12. #pragma hdrstop
  13. //
  14. // Vector for frame buffer functions.
  15. //
  16. VIDEO_FUNCTION_VECTOR FrameBufferKanjiVideoVector =
  17. {
  18. FrameBufferKanjiDisplayString,
  19. FrameBufferKanjiClearRegion,
  20. FrameBufferKanjiSpecificInit,
  21. FrameBufferKanjiSpecificReInit,
  22. FrameBufferKanjiSpecificTerminate,
  23. FrameBufferKanjiSpecificInitPalette,
  24. FrameBufferKanjiSpecificScrollUp
  25. };
  26. BOOLEAN FrameBufferKanjiInitialized = FALSE;
  27. //
  28. // Number of bytes that make up a row of characters.
  29. // Equal to the screen stride (number of bytes on a scan line)
  30. // multiplies by the height of a char in bytes; double that
  31. // if DoubleCharHeight is TRUE.
  32. //
  33. ULONG KanjiCharRowDelta;
  34. ULONG KanjiBytesPerPixel;
  35. ULONG KanjiCharWidth;
  36. //
  37. // Physical font information
  38. //
  39. extern BOOTFONTBIN_HEADER BootFontHeader;
  40. VOID
  41. FrameBufferKanjiSpecificInit(
  42. IN PVIDEO_MODE_INFORMATION VideoModes,
  43. IN ULONG NumberOfModes,
  44. IN ULONG ModeSize
  45. )
  46. /*++
  47. Routine Description:
  48. Perform frame buffer specific initialization. This includes
  49. - setting the desired video mode.
  50. Arguments:
  51. None.
  52. Return Value:
  53. --*/
  54. {
  55. NTSTATUS Status;
  56. IO_STATUS_BLOCK IoStatusBlock;
  57. VIDEO_MODE VideoMode;
  58. PVIDEO_MODE_INFORMATION mode;
  59. if(FrameBufferKanjiInitialized) {
  60. return;
  61. }
  62. mode = pFrameBufferDetermineModeToUse(VideoModes,NumberOfModes,ModeSize);
  63. if(mode == 0) {
  64. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_BADMODE, 0);
  65. while(TRUE); // loop forever
  66. }
  67. //
  68. // Save away the mode info in a global.
  69. //
  70. VideoVariables->VideoModeInfo = *mode;
  71. //
  72. // Set the desired mode.
  73. //
  74. VideoMode.RequestedMode = VideoVariables->VideoModeInfo.ModeIndex;
  75. Status = ZwDeviceIoControlFile(
  76. VideoVariables->hDisplay,
  77. NULL,
  78. NULL,
  79. NULL,
  80. &IoStatusBlock,
  81. IOCTL_VIDEO_SET_CURRENT_MODE,
  82. &VideoMode,
  83. sizeof(VideoMode),
  84. NULL,
  85. 0
  86. );
  87. if(!NT_SUCCESS(Status)) {
  88. KdPrint(("SETUP: Unable to set mode %u (status = %lx)\n",VideoMode.RequestedMode,Status));
  89. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_SETMODE, Status);
  90. while(TRUE); // loop forever
  91. }
  92. //
  93. // Map the frame buffer.
  94. //
  95. pSpvidMapVideoMemory(TRUE);
  96. FrameBufferKanjiInitialized = TRUE;
  97. //
  98. // Logical FontGlyph information
  99. //
  100. FEFontCharacterHeight = BootFontHeader.CharacterImageHeight +
  101. BootFontHeader.CharacterTopPad +
  102. BootFontHeader.CharacterBottomPad;
  103. FEFontCharacterWidth = BootFontHeader.CharacterImageSbcsWidth;
  104. //
  105. // Determine the width of the screen. If it's double the size
  106. // of the minimum number of characters per row (or larger)
  107. // then we'll double the width of each character as we draw it.
  108. //
  109. VideoVariables->ScreenWidth = VideoVariables->VideoModeInfo.VisScreenWidth / FEFontCharacterWidth;
  110. //
  111. // Determine the height of the screen. If it's double the size
  112. // of the minimum number of characters per column (or larger)
  113. // then we'll double the height of each character as we draw it.
  114. //
  115. VideoVariables->ScreenHeight = VideoVariables->VideoModeInfo.VisScreenHeight / FEFontCharacterHeight;
  116. KanjiCharRowDelta = VideoVariables->VideoModeInfo.ScreenStride * FEFontCharacterHeight;
  117. KanjiBytesPerPixel = VideoVariables->VideoModeInfo.BitsPerPlane / 8;
  118. if(KanjiBytesPerPixel == 3) {
  119. KanjiBytesPerPixel = 4;
  120. }
  121. KdPrint(("SETUPDD:KanjiBytesPerPixel = %d\n",KanjiBytesPerPixel));
  122. KanjiCharWidth = FEFontCharacterWidth * KanjiBytesPerPixel;
  123. //
  124. // Allocate the background buffer, if needed
  125. //
  126. VideoVariables->ActiveVideoBuffer = VideoVariables->VideoMemoryInfo.FrameBufferBase;
  127. if (SP_IS_UPGRADE_GRAPHICS_MODE()) {
  128. VideoVariables->VideoBufferSize = VideoVariables->VideoMemoryInfo.FrameBufferLength;
  129. VideoVariables->VideoBuffer = SpMemAlloc(VideoVariables->VideoBufferSize);
  130. if (VideoVariables->VideoBuffer) {
  131. VideoVariables->ActiveVideoBuffer = VideoVariables->VideoBuffer;
  132. } else {
  133. VideoVariables->VideoBufferSize = 0;
  134. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  135. }
  136. }
  137. }
  138. VOID
  139. FrameBufferKanjiSpecificReInit(
  140. VOID
  141. )
  142. {
  143. NTSTATUS Status;
  144. IO_STATUS_BLOCK IoStatusBlock;
  145. VIDEO_MODE VideoMode;
  146. if(!FrameBufferKanjiInitialized) {
  147. return;
  148. }
  149. //
  150. // Set the desired mode.
  151. //
  152. VideoMode.RequestedMode = VideoVariables->VideoModeInfo.ModeIndex;
  153. Status = ZwDeviceIoControlFile(
  154. VideoVariables->hDisplay,
  155. NULL,
  156. NULL,
  157. NULL,
  158. &IoStatusBlock,
  159. IOCTL_VIDEO_SET_CURRENT_MODE,
  160. &VideoMode,
  161. sizeof(VideoMode),
  162. NULL,
  163. 0
  164. );
  165. if(!NT_SUCCESS(Status)) {
  166. KdPrint(("SETUP: Unable to set mode %u (status = %lx)\n",VideoMode.RequestedMode,Status));
  167. SpDisplayRawMessage(SP_SCRN_VIDEO_ERROR_RAW, 2, VIDEOBUG_SETMODE, Status);
  168. while(TRUE); // loop forever
  169. }
  170. FrameBufferKanjiSpecificInitPalette();
  171. //
  172. // Blast the background video information to the
  173. // foreground
  174. //
  175. if (SP_IS_UPGRADE_GRAPHICS_MODE() && VideoVariables->VideoBuffer &&
  176. VideoVariables->VideoBufferSize) {
  177. PUCHAR Source = VideoVariables->VideoBuffer;
  178. PUCHAR Destination = VideoVariables->VideoMemoryInfo.FrameBufferBase;
  179. ULONG Index;
  180. for (Index=0; Index < VideoVariables->VideoBufferSize; Index++) {
  181. WRITE_REGISTER_UCHAR(Destination + Index, *(Source + Index));
  182. }
  183. SP_SET_UPGRADE_GRAPHICS_MODE(FALSE);
  184. }
  185. VideoVariables->ActiveVideoBuffer = VideoVariables->VideoMemoryInfo.FrameBufferBase;
  186. }
  187. BOOLEAN
  188. FrameBufferKanjiSpecificInitPalette(
  189. VOID
  190. )
  191. {
  192. BOOLEAN rc;
  193. ULONG NumEntries;
  194. ULONG BufferSize;
  195. PVIDEO_CLUT clut;
  196. // NTSTATUS Status;
  197. // IO_STATUS_BLOCK IoStatusBlock;
  198. UCHAR i;
  199. rc = TRUE;
  200. //
  201. // For non-palette-driven displays, we construct a simple palette
  202. // for use w/ gamma correcting adapters.
  203. //
  204. if(!(VideoVariables->VideoModeInfo.AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN)) {
  205. switch(KanjiBytesPerPixel) {
  206. case 1:
  207. NumEntries = 3;
  208. break;
  209. case 2:
  210. NumEntries = 32;
  211. break;
  212. default:
  213. NumEntries = 255;
  214. break;
  215. }
  216. BufferSize = sizeof(VIDEO_CLUT)+(sizeof(VIDEO_CLUTDATA)*NumEntries); // size is close enough
  217. clut = SpMemAlloc(BufferSize);
  218. clut->NumEntries = (USHORT)NumEntries;
  219. clut->FirstEntry = 0;
  220. for(i=0; i<NumEntries; i++) {
  221. clut->LookupTable[i].RgbArray.Red = i;
  222. clut->LookupTable[i].RgbArray.Green = i;
  223. clut->LookupTable[i].RgbArray.Blue = i;
  224. clut->LookupTable[i].RgbArray.Unused = 0;
  225. }
  226. // Status = ZwDeviceIoControlFile(
  227. // hDisplay,
  228. // NULL,
  229. // NULL,
  230. // NULL,
  231. // &IoStatusBlock,
  232. // IOCTL_VIDEO_SET_COLOR_REGISTERS,
  233. // clut,
  234. // BufferSize,
  235. // NULL,
  236. // 0
  237. // );
  238. SpMemFree(clut);
  239. // if(!NT_SUCCESS(Status)) {
  240. // KdPrint(("SETUP: Unable to set palette (status = %lx)\n",Status));
  241. // rc = FALSE;
  242. // }
  243. }
  244. return(rc);
  245. }
  246. VOID
  247. FrameBufferKanjiSpecificTerminate(
  248. VOID
  249. )
  250. /*++
  251. Routine Description:
  252. Perform frame buffer specific termination. This includes
  253. - unmapping the frame buffer from memory
  254. Arguments:
  255. None.
  256. Return Value:
  257. --*/
  258. {
  259. if(FrameBufferKanjiInitialized) {
  260. //
  261. // Clear screen for next video mode.
  262. //
  263. FrameBufferKanjiClearRegion(
  264. 0,
  265. 0,
  266. VideoVariables->ScreenWidth,
  267. VideoVariables->ScreenHeight,
  268. ATT_FG_BLACK|ATT_BG_BLACK
  269. );
  270. //
  271. // Unmap video memory
  272. //
  273. pSpvidMapVideoMemory(FALSE);
  274. if (VideoVariables->VideoBuffer && VideoVariables->VideoBufferSize) {
  275. SpMemFree(VideoVariables->VideoBuffer);
  276. VideoVariables->VideoBuffer = 0;
  277. VideoVariables->VideoBufferSize = 0;
  278. }
  279. FrameBufferKanjiInitialized = FALSE;
  280. }
  281. }
  282. VOID
  283. FrameBufferKanjiDisplayString(
  284. IN PSTR String,
  285. IN UCHAR Attribute,
  286. IN ULONG X, // 0-based coordinates (character units)
  287. IN ULONG Y
  288. )
  289. /*++
  290. Routine Description:
  291. Write a string of characters to the display.
  292. Arguments:
  293. String - supplies a 0-terminated character string in the OEM charset
  294. to be displayed at the given position.
  295. Attribute - supplies the attributes for characters in the string.
  296. X,Y - specify the character-based (0-based) position of the output.
  297. Return Value:
  298. None.
  299. --*/
  300. {
  301. ULONG BgColorValue;
  302. ULONG FgColorValue;
  303. PUCHAR Destination;
  304. PUCHAR CharOrigin,LineOrigin,pGlyphRow;
  305. ULONG Length;
  306. PUCHAR pch;
  307. ULONG I,J,K;
  308. ULONG CurrentColumn;
  309. //
  310. // Eliminate invalid coord.
  311. //
  312. if( X >= VideoVariables->ScreenWidth ) X = 0;
  313. if( Y >= VideoVariables->ScreenHeight ) Y = 3;
  314. ASSERT(FEFontCharacterWidth == 8);
  315. //
  316. // Calculate the bit patterns that yield the foreground and background
  317. // attributes when poked into the frame buffer.
  318. //
  319. FgColorValue = VideoVariables->AttributeToColorValue[Attribute & 0x0f];
  320. BgColorValue = VideoVariables->AttributeToColorValue[(Attribute >> 4) & 0x0f];
  321. //
  322. // Calculate the address of the upper left pixel of the first character
  323. // to be displayed.
  324. //
  325. CharOrigin = (PUCHAR)VideoVariables->ActiveVideoBuffer
  326. + (Y * KanjiCharRowDelta)
  327. + (X * KanjiCharWidth);
  328. //
  329. // Set current column.
  330. //
  331. CurrentColumn = X;
  332. //
  333. // Output each character in the string.
  334. //
  335. for(pch=String; *pch; pch++) {
  336. //
  337. // Initialize line Origin
  338. //
  339. LineOrigin = CharOrigin;
  340. if(DbcsFontIsDBCSLeadByte(*pch)) {
  341. //
  342. // This is Full Width Character ( 16 + 1 + 2 * 8 )
  343. // | | | Height
  344. // | | Post Leading
  345. // | Pre Leading
  346. // Real font image body
  347. USHORT Word;
  348. if((CurrentColumn+1) >= VideoVariables->ScreenWidth) {
  349. break;
  350. }
  351. Word = ((*pch) << 8) | (*(pch+1));
  352. pGlyphRow = DbcsFontGetDbcsFontChar(Word);
  353. //
  354. // If we can not get image, replace it with full width space.
  355. //
  356. if(pGlyphRow == NULL) {
  357. pGlyphRow = DbcsFontGetDbcsFontChar(FEFontDefaultChar);
  358. }
  359. //
  360. // Draw pre leading lines
  361. //
  362. for (I = 0; I < BootFontHeader.CharacterTopPad; I += 1 ) {
  363. Destination = LineOrigin;
  364. for( J = 0; J < BootFontHeader.CharacterImageDbcsWidth; J += 1 ) {
  365. switch(KanjiBytesPerPixel) {
  366. case 1:
  367. *Destination++ = (UCHAR)BgColorValue;
  368. break;
  369. case 2:
  370. *(PUSHORT)Destination = (USHORT)BgColorValue;
  371. Destination += 2;
  372. break;
  373. case 4:
  374. *(PULONG)Destination = (ULONG)BgColorValue;
  375. Destination += 4;
  376. break;
  377. }
  378. }
  379. LineOrigin += VideoVariables->VideoModeInfo.ScreenStride;
  380. }
  381. //
  382. // Draw font glyph body
  383. //
  384. for (I = 0; I < BootFontHeader.CharacterImageHeight; I += 1 ) {
  385. Destination = LineOrigin;
  386. for( J = 0; J < 2; J += 1 ) {
  387. BYTE ShiftMask = 0x80;
  388. for( K = 0; K < 8 ; K += 1 ) {
  389. ULONG DrawValue;
  390. if (pGlyphRow && (*pGlyphRow & ShiftMask))
  391. DrawValue = FgColorValue;
  392. else
  393. DrawValue = BgColorValue;
  394. switch(KanjiBytesPerPixel) {
  395. case 1:
  396. *Destination++ = (UCHAR)DrawValue;
  397. break;
  398. case 2:
  399. *(PUSHORT)Destination = (USHORT)DrawValue;
  400. Destination += 2;
  401. break;
  402. case 4:
  403. *(PULONG)Destination = (ULONG)DrawValue;
  404. Destination += 4;
  405. break;
  406. }
  407. ShiftMask = ShiftMask >> 1;
  408. }
  409. pGlyphRow ++;
  410. }
  411. LineOrigin += VideoVariables->VideoModeInfo.ScreenStride;
  412. }
  413. //
  414. // Draw post leading lines
  415. //
  416. for (I = 0; I < BootFontHeader.CharacterBottomPad; I += 1) {
  417. Destination = LineOrigin;
  418. for( J = 0; J < BootFontHeader.CharacterImageDbcsWidth; J += 1 ) {
  419. switch(KanjiBytesPerPixel) {
  420. case 1:
  421. *Destination++ = (UCHAR)BgColorValue;
  422. break;
  423. case 2:
  424. *(PUSHORT)Destination = (USHORT)BgColorValue;
  425. Destination += 2;
  426. break;
  427. case 4:
  428. *(PULONG)Destination = (ULONG)BgColorValue;
  429. Destination += 4;
  430. break;
  431. }
  432. }
  433. LineOrigin += VideoVariables->VideoModeInfo.ScreenStride;
  434. }
  435. CharOrigin += (BootFontHeader.CharacterImageDbcsWidth * KanjiBytesPerPixel);
  436. CurrentColumn += 2;
  437. //
  438. // Move to Next character ( skip Dbcs Trailing byte )
  439. //
  440. pch++;
  441. } else if(DbcsFontIsGraphicsChar(*pch)) {
  442. BYTE ShiftMask = 0x80;
  443. ULONG DrawValue;
  444. if(CurrentColumn >= VideoVariables->ScreenWidth) {
  445. break;
  446. }
  447. //
  448. // Graphics Character special
  449. //
  450. pGlyphRow = DbcsFontGetGraphicsChar(*pch);
  451. if(pGlyphRow == NULL) {
  452. pGlyphRow = DbcsFontGetGraphicsChar(0x0);
  453. }
  454. for (I = 0; I < FEFontCharacterHeight; I += 1 ) {
  455. ShiftMask = 0x80;
  456. Destination = LineOrigin;
  457. for( K = 0; K < 8 ; K += 1 ) {
  458. if( *pGlyphRow & ShiftMask )
  459. DrawValue = BgColorValue;
  460. else
  461. DrawValue = FgColorValue;
  462. switch(KanjiBytesPerPixel) {
  463. case 1:
  464. *Destination++ = (UCHAR)DrawValue;
  465. break;
  466. case 2:
  467. *(PUSHORT)Destination = (USHORT)DrawValue;
  468. Destination += 2;
  469. break;
  470. case 4:
  471. *(PULONG)Destination = (ULONG)DrawValue;
  472. Destination += 4;
  473. break;
  474. }
  475. ShiftMask = ShiftMask >> 1;
  476. }
  477. pGlyphRow ++;
  478. LineOrigin += VideoVariables->VideoModeInfo.ScreenStride;
  479. }
  480. CharOrigin += (BootFontHeader.CharacterImageSbcsWidth * KanjiBytesPerPixel);
  481. CurrentColumn += 1;
  482. } else {
  483. if(CurrentColumn >= VideoVariables->ScreenWidth) {
  484. break;
  485. }
  486. pGlyphRow = DbcsFontGetSbcsFontChar(*pch);
  487. //
  488. // If we can not get image, replace it with half width space.
  489. //
  490. if(pGlyphRow == NULL) {
  491. pGlyphRow = DbcsFontGetSbcsFontChar(0x20);
  492. }
  493. for (I = 0; I < BootFontHeader.CharacterTopPad; I += 1 ) {
  494. Destination = LineOrigin;
  495. for( J = 0; J < BootFontHeader.CharacterImageSbcsWidth; J += 1 ) {
  496. switch(KanjiBytesPerPixel) {
  497. case 1:
  498. *Destination++ = (UCHAR)BgColorValue;
  499. break;
  500. case 2:
  501. *(PUSHORT)Destination = (USHORT)BgColorValue;
  502. Destination += 2;
  503. break;
  504. case 4:
  505. *(PULONG)Destination = (ULONG)BgColorValue;
  506. Destination += 4;
  507. break;
  508. }
  509. }
  510. LineOrigin += VideoVariables->VideoModeInfo.ScreenStride;
  511. }
  512. for (I = 0; I < BootFontHeader.CharacterImageHeight; I += 1 ) {
  513. BYTE ShiftMask = 0x80;
  514. Destination = LineOrigin;
  515. for( K = 0; K < 8 ; K += 1 ) {
  516. ULONG DrawValue;
  517. if( *pGlyphRow & ShiftMask )
  518. DrawValue = FgColorValue;
  519. else
  520. DrawValue = BgColorValue;
  521. switch(KanjiBytesPerPixel) {
  522. case 1:
  523. *Destination++ = (UCHAR)DrawValue;
  524. break;
  525. case 2:
  526. *(PUSHORT)Destination = (USHORT)DrawValue;
  527. Destination += 2;
  528. break;
  529. case 4:
  530. *(PULONG)Destination = (ULONG)DrawValue;
  531. Destination += 4;
  532. break;
  533. }
  534. ShiftMask = ShiftMask >> 1;
  535. }
  536. pGlyphRow ++;
  537. LineOrigin += VideoVariables->VideoModeInfo.ScreenStride;
  538. }
  539. for (I = 0; I < BootFontHeader.CharacterBottomPad; I += 1) {
  540. Destination = LineOrigin;
  541. for( J = 0; J < BootFontHeader.CharacterImageSbcsWidth; J += 1 ) {
  542. switch(KanjiBytesPerPixel) {
  543. case 1:
  544. *Destination++ = (UCHAR)BgColorValue;
  545. break;
  546. case 2:
  547. *(PUSHORT)Destination = (USHORT)BgColorValue;
  548. Destination += 2;
  549. break;
  550. case 4:
  551. *(PULONG)Destination = (ULONG)BgColorValue;
  552. Destination += 4;
  553. break;
  554. }
  555. }
  556. LineOrigin += VideoVariables->VideoModeInfo.ScreenStride;
  557. }
  558. CharOrigin += (BootFontHeader.CharacterImageSbcsWidth * KanjiBytesPerPixel);
  559. CurrentColumn += 1;
  560. }
  561. }
  562. }
  563. VOID
  564. FrameBufferKanjiClearRegion(
  565. IN ULONG X,
  566. IN ULONG Y,
  567. IN ULONG W,
  568. IN ULONG H,
  569. IN UCHAR Attribute
  570. )
  571. /*++
  572. Routine Description:
  573. Clear out a screen region to a specific attribute.
  574. Arguments:
  575. X,Y,W,H - specify rectangle in 0-based character coordinates.
  576. Attribute - Low nibble specifies attribute to be filled in the rectangle
  577. (ie, the background color to be cleared to).
  578. Return Value:
  579. None.
  580. --*/
  581. {
  582. PUCHAR Destination;
  583. ULONG Fill;
  584. ULONG i;
  585. ULONG FillLength;
  586. ULONG x;
  587. ASSERT(X+W <= VideoVariables->ScreenWidth);
  588. ASSERT(Y+H <= VideoVariables->ScreenHeight);
  589. if(X+W > VideoVariables->ScreenWidth) {
  590. W = VideoVariables->ScreenWidth-X;
  591. }
  592. if(Y+H > VideoVariables->ScreenHeight) {
  593. H = VideoVariables->ScreenHeight-Y;
  594. }
  595. Fill = VideoVariables->AttributeToColorValue[Attribute & 0x0f];
  596. Destination = (PUCHAR)VideoVariables->ActiveVideoBuffer
  597. + (Y * KanjiCharRowDelta)
  598. + (X * KanjiCharWidth);
  599. FillLength = W * KanjiCharWidth;
  600. for(i=0; i<H*FEFontCharacterHeight; i++) {
  601. switch(KanjiBytesPerPixel) {
  602. case 1:
  603. for(x=0; x<FillLength ; x++) {
  604. *(PUCHAR)(Destination+(x)) = (UCHAR)Fill;
  605. }
  606. break;
  607. case 2:
  608. for(x=0; x<FillLength/2; x++) {
  609. *(PUSHORT)(Destination+(x*2)) = (USHORT)Fill;
  610. }
  611. break;
  612. case 4:
  613. for(x=0; x<FillLength/4; x++) {
  614. *(PULONG)(Destination+(x*4)) = (ULONG)Fill;
  615. }
  616. break;
  617. }
  618. Destination += VideoVariables->VideoModeInfo.ScreenStride;
  619. }
  620. }
  621. BOOLEAN
  622. FrameBufferKanjiSpecificScrollUp(
  623. IN ULONG TopLine,
  624. IN ULONG BottomLine,
  625. IN ULONG LineCount,
  626. IN UCHAR FillAttribute
  627. )
  628. {
  629. PUCHAR Source,Target;
  630. ULONG Count;
  631. Target = (PUCHAR)VideoVariables->ActiveVideoBuffer
  632. + (TopLine * KanjiCharRowDelta);
  633. Source = Target + (LineCount * KanjiCharRowDelta);
  634. Count = (((BottomLine - TopLine) + 1) - LineCount) * KanjiCharRowDelta;
  635. RtlMoveMemory(Target,Source,Count);
  636. FrameBufferKanjiClearRegion(
  637. 0,
  638. (BottomLine - LineCount) + 1,
  639. VideoVariables->ScreenWidth,
  640. LineCount,
  641. FillAttribute
  642. );
  643. return(TRUE);
  644. }