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.

716 lines
19 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pointer.c
  3. *
  4. * Contains the pointer management functions.
  5. *
  6. * Copyright (c) 1992-1995 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. ULONG SetMonoHwPointerShape(
  11. SURFOBJ *pso,
  12. SURFOBJ *psoMask,
  13. SURFOBJ *psoColor,
  14. XLATEOBJ *pxlo,
  15. LONG xHot,
  16. LONG yHot,
  17. LONG x,
  18. LONG y,
  19. RECTL *prcl,
  20. FLONG fl);
  21. BYTE jRepMask2[] =
  22. {
  23. 0x00, 0x05, 0x0a, 0x0f, 0x50, 0x55, 0x5a, 0x5f,
  24. 0xa0, 0xa5, 0xaa, 0xaf, 0xf0, 0xf5, 0xfa, 0xff,
  25. };
  26. /*****************************************************************************
  27. * DrvMovePointer -
  28. ****************************************************************************/
  29. VOID DrvMovePointer(
  30. SURFOBJ* pso,
  31. LONG x,
  32. LONG y,
  33. RECTL* prcl)
  34. {
  35. PPDEV ppdev;
  36. INT xx, yy;
  37. ppdev = (PPDEV) pso->dhpdev;
  38. // If x is -1 then take down the cursor.
  39. if (x == -1)
  40. {
  41. DISABLE_SPRITE(ppdev);
  42. return;
  43. }
  44. // Adjust the actual pointer position depending upon
  45. // the hot spot.
  46. x -= ppdev->W32SpriteData.ptlHot.x;
  47. y -= ppdev->W32SpriteData.ptlHot.y;
  48. if (ppdev->ulChipID == ET6000)
  49. {
  50. char xPreset = 0;
  51. char yPreset = 0;
  52. // We may have disabled the sprite if it went off the screen.
  53. // So, now have to detect if we did and re-enable it if necessary.
  54. if (ppdev->W32SpriteData.fl & POINTER_DISABLED)
  55. {
  56. ENABLE_SPRITE(ppdev);
  57. }
  58. if (x < 0)
  59. {
  60. xPreset = (CHAR)~x;
  61. x = 0;
  62. }
  63. if (y < 0)
  64. {
  65. yPreset = (CHAR)~y;
  66. y = 0;
  67. }
  68. ET6K_HORZ_PRESET(ppdev, xPreset);
  69. ET6K_VERT_PRESET(ppdev, yPreset);
  70. ET6K_SPRITE_HORZ_POSITION(ppdev, x);
  71. ET6K_SPRITE_VERT_POSITION(ppdev, y);
  72. return;
  73. }
  74. else
  75. {
  76. //
  77. // Adjust pointer x position for color depth
  78. //
  79. x *= ppdev->cBpp;
  80. // Yet another bug.
  81. // If the cursor is moved entirely off the screen, it could cause
  82. // the screen to shake. So, we have to disable the cursor if it
  83. // is moved entirely off the screen.
  84. if ((x < - ((LONG) (ppdev->W32SpriteData.szlPointer.cx))) ||
  85. (x > ((LONG) (ppdev->cxScreen * ppdev->cBpp))) ||
  86. (y < - ((LONG) (ppdev->W32SpriteData.szlPointer.cy))) ||
  87. (y > ((LONG) (ppdev->cyScreen))))
  88. {
  89. DISABLE_SPRITE(ppdev);
  90. return;
  91. }
  92. // We may have disabled the sprite if it went off the screen.
  93. // So, now have to detect if we did and re-enable it if necessary.
  94. // (remembering to keep track of the state).
  95. if (ppdev->W32SpriteData.fl & POINTER_DISABLED)
  96. {
  97. ENABLE_SPRITE(ppdev);
  98. }
  99. // The W32 non-rev-B has a problem with a vertical offset of 0x3f.
  100. // All the other W32's have a problem with the last nibble being
  101. // 0x0F for both the horizontal and the verical.
  102. // Never set the bad presets on the chips in question.
  103. if (x <= 0)
  104. {
  105. if ((ppdev->ulChipID == W32) &&
  106. (ppdev->ulRevLevel != REV_B))
  107. {
  108. xx = -x;
  109. if ((xx & 0x0F) == 0x0F)
  110. xx &= ~0x01;
  111. SET_HORZ_PRESET(xx);
  112. }
  113. else
  114. {
  115. SET_HORZ_PRESET(-x);
  116. }
  117. x = 0;
  118. }
  119. else
  120. {
  121. SET_HORZ_PRESET(0);
  122. }
  123. if (y <= 0)
  124. {
  125. if (ppdev->ulChipID == W32)
  126. {
  127. yy = -y;
  128. if (ppdev->ulRevLevel != REV_B)
  129. {
  130. if (yy == 0x3F)
  131. yy = 0x3E;
  132. }
  133. else
  134. {
  135. if ((yy & 0x0F) == 0x0F)
  136. yy &= ~0x01;
  137. }
  138. SET_VERT_PRESET(yy);
  139. }
  140. else
  141. {
  142. SET_VERT_PRESET(-y);
  143. }
  144. y = 0;
  145. }
  146. else
  147. {
  148. SET_VERT_PRESET(0);
  149. }
  150. // You guessed it. Another bug.
  151. // On the W32 Rev B you can not put the cursor on the bottom line
  152. // of the display. And if were in interlaced mode you can't put it
  153. // on the bottom two lines.
  154. if ((ppdev->ulChipID == W32) &&
  155. (ppdev->ulRevLevel == REV_B))
  156. {
  157. INT i;
  158. if (y > (i = ppdev->cyScreen - 2))
  159. {
  160. OUTP(0x3D4, 0x35);
  161. if (INP(0x3D5) & 0x80)
  162. y = i;
  163. }
  164. else if (y > (i+1))
  165. {
  166. y = i+1;
  167. }
  168. }
  169. //////////////////////////////////////////////////////
  170. // Set the position of the sprite.
  171. if ((ppdev->ulChipID == W32I) ||
  172. (ppdev->ulChipID == W32P))
  173. {
  174. // You bet, one more bug, and this one is a lulu.
  175. // First we have to set the vertical position before the horz
  176. // position. Why you ask, because, if this is a W32 Rev B or later
  177. // we may have to toggle a bit in a test register to really set the
  178. // vertical position, but of course we don't want to set anything
  179. // else at this point.
  180. BYTE status, byte;
  181. // Wait for horz display interval.
  182. while ( (INP(0x3DA) & 0x02));
  183. while (!((status = INP(0x3DA)) & 0x02));
  184. SET_VERT_POSITION(y);
  185. // Check if the sprite is being displayed at this very moment.
  186. // And if it is then skip the test bit stuff.
  187. if (!(status & 0x04))
  188. {
  189. // Looks like we will have to toggle the test bit to
  190. // really set the vertical position.
  191. ENABLE_KEY(ppdev);
  192. OUTP(0x3D4, 0x37);
  193. byte = INP(0x3D5);
  194. byte |= 0x40;
  195. OUTP(0x3D5, byte);
  196. byte &= ~0x40;
  197. OUTP(0x3D5, byte);
  198. DISABLE_KEY(ppdev);
  199. }
  200. SET_HORZ_POSITION(x);
  201. }
  202. else
  203. {
  204. // For consistency sake, we're going to set the vertical first
  205. // even for non-W32 Rev B chips.
  206. SET_VERT_POSITION(y);
  207. SET_HORZ_POSITION(x);
  208. }
  209. return;
  210. }
  211. }
  212. /******************************Public*Routine******************************\
  213. * DrvSetPointerShape
  214. *
  215. * Sets the new pointer shape.
  216. \**************************************************************************/
  217. ULONG DrvSetPointerShape(
  218. SURFOBJ *pso,
  219. SURFOBJ *psoMask,
  220. SURFOBJ *psoColor,
  221. XLATEOBJ *pxlo,
  222. LONG xHot,
  223. LONG yHot,
  224. LONG x,
  225. LONG y,
  226. RECTL *prcl,
  227. FLONG fl)
  228. {
  229. PPDEV ppdev;
  230. ULONG ulRet;
  231. ppdev = (PPDEV) pso->dhpdev;
  232. if (ppdev->flCaps & CAPS_SW_POINTER)
  233. {
  234. return(SPS_DECLINE);
  235. }
  236. // Save the hot spot and dimensions of the cursor in globals.
  237. ppdev->W32SpriteData.ptlHot.x = xHot;
  238. ppdev->W32SpriteData.ptlHot.y = yHot;
  239. ppdev->W32SpriteData.szlPointer.cx = psoMask->sizlBitmap.cx * ppdev->cBpp;
  240. ppdev->W32SpriteData.szlPointer.cy = psoMask->sizlBitmap.cy / 2;
  241. if (psoColor != NULL)
  242. {
  243. // Disable the mono hardware pointer, and decline the pointer
  244. // shape
  245. DISABLE_SPRITE(ppdev);
  246. ulRet = SPS_DECLINE;
  247. }
  248. else
  249. {
  250. // Take care of the monochrome pointer.
  251. ulRet = SetMonoHwPointerShape(pso, psoMask, psoColor, pxlo,
  252. xHot, yHot, x, y, prcl, fl);
  253. if (ulRet == SPS_DECLINE)
  254. {
  255. DISABLE_SPRITE(ppdev);
  256. }
  257. }
  258. return (ulRet);
  259. }
  260. /*****************************************************************************
  261. * DrvSetMonoHwPointerShape -
  262. ****************************************************************************/
  263. ULONG SetMonoHwPointerShape(
  264. SURFOBJ *pso,
  265. SURFOBJ *psoMask,
  266. SURFOBJ *psoColor,
  267. XLATEOBJ *pxlo,
  268. LONG xHot,
  269. LONG yHot,
  270. LONG x,
  271. LONG y,
  272. RECTL *prcl,
  273. FLONG fl)
  274. {
  275. INT i,
  276. j,
  277. cxMask,
  278. cyMask,
  279. cyAND,
  280. cxAND,
  281. cyXOR,
  282. cxXOR;
  283. PBYTE pjAND,
  284. pjXOR;
  285. INT lDelta;
  286. PPDEV ppdev;
  287. INT ix,
  288. iy,
  289. is,
  290. ip,
  291. iBit,
  292. jAndByte,
  293. jXorByte,
  294. jSpriteBits,
  295. jSpriteByte;
  296. INT njSpriteBuffer;
  297. BOOL bDetectXOR;
  298. BYTE* pjBase;
  299. BYTE ajAndMask[64][8],
  300. ajXorMask[64][8];
  301. BYTE ajW32Sprite[1024];
  302. LONG cBpp;
  303. INT ndx = 0;
  304. ppdev = (PPDEV) pso->dhpdev;
  305. pjBase = ppdev->pjBase;
  306. cBpp = ppdev->cBpp;
  307. // The W32 does not handle an XOR and an AND.
  308. // So, set a bool if we need to detect this condition.
  309. bDetectXOR = FALSE;
  310. if (ppdev->ulChipID == W32)
  311. bDetectXOR = TRUE;
  312. // If the mask is NULL this implies the pointer is not
  313. // visible.
  314. if (psoMask == NULL)
  315. {
  316. DISABLE_SPRITE(ppdev);
  317. return (SPS_ACCEPT_NOEXCLUDE);
  318. }
  319. // Init the AND and XOR masks.
  320. memset (ajAndMask, 0xFFFFFFFF, 512);
  321. memset (ajXorMask, 0, 512);
  322. // Get the bitmap dimensions.
  323. cxMask = psoMask->sizlBitmap.cx;
  324. cyMask = psoMask->sizlBitmap.cy;
  325. cyAND = cyXOR = cyMask / 2;
  326. cxAND = cxXOR = cxMask / 8;
  327. // Set up pointers to the AND and XOR masks.
  328. pjAND = psoMask->pvScan0;
  329. lDelta = psoMask->lDelta;
  330. pjXOR = pjAND + (cyAND * lDelta);
  331. // Copy the AND mask.
  332. for (i = 0; i < cyAND; i++)
  333. {
  334. // Copy over a line of the AND mask.
  335. for (j = 0; j < cxAND; j++)
  336. {
  337. ajAndMask[i][j] = pjAND[j];
  338. }
  339. // point to the next line of the AND mask.
  340. pjAND += lDelta;
  341. }
  342. // Copy the XOR mask.
  343. for (i = 0; i < cyXOR; i++)
  344. {
  345. // Copy over a line of the XOR mask.
  346. for (j = 0; j < cxXOR; j++)
  347. {
  348. ajXorMask[i][j] = pjXOR[j];
  349. }
  350. // point to the next line of the XOR mask.
  351. pjXOR += lDelta;
  352. }
  353. // Build up the sprite from NT's And and Xor masks.
  354. // Init the indexes into the sprite buffer (is) and the
  355. // index for the bit pairs (ip).
  356. is = 0;
  357. ip = 0;
  358. // Outer most loop goes over NT's And and Xor rows.
  359. for (iy = 0; iy < 64; iy++)
  360. {
  361. // loop over the columns.
  362. for (ix = 0; ix < 8; ix++)
  363. {
  364. // pickup a source byte for each mask.
  365. jAndByte = ajAndMask[iy][ix];
  366. jXorByte = ajXorMask[iy][ix];
  367. // loop over the bits in the byte.
  368. for (iBit = 0x80; iBit != 0; iBit >>= 1)
  369. {
  370. // init the sprite bitpair.
  371. jSpriteBits = 0x0;
  372. // Set the sprite bit pairs.
  373. if (jAndByte & iBit)
  374. jSpriteBits |= 0x02;
  375. if (jXorByte & iBit)
  376. jSpriteBits |= 0x01;
  377. if (bDetectXOR == TRUE)
  378. {
  379. if ((jAndByte & iBit) && (jXorByte & iBit))
  380. {
  381. return (SPS_DECLINE);
  382. }
  383. }
  384. if ((ip % 4) == 0)
  385. {
  386. // If all 4 bit pairs in this byte are filled in
  387. // flush the sprite byte to the sprite byte array.
  388. // and set the first bit pair.
  389. if (ip != 0)
  390. {
  391. ajW32Sprite[is++] = (BYTE)jSpriteByte;
  392. }
  393. jSpriteByte = jSpriteBits;
  394. }
  395. else
  396. {
  397. // If the sprite byte is not full, shift the bit pair
  398. // into position, and or it into the sprite byte.
  399. jSpriteBits <<= (ip % 4) * 2;
  400. jSpriteByte |= jSpriteBits;
  401. }
  402. // bump the bit pair counter.
  403. ip++;
  404. }
  405. }
  406. }
  407. // Flush the last byte.
  408. ajW32Sprite[is++] = (BYTE)jSpriteByte;
  409. // Disable the pointer.
  410. DISABLE_SPRITE(ppdev);
  411. DISPDBG((1,"setting sprite shape at offset (%xh)", ppdev->cjPointerOffset));
  412. if (ppdev->ulChipID == ET6000)
  413. {
  414. BYTE * pjDst = ppdev->pjScreen + ppdev->cjPointerOffset;
  415. BYTE * pjSrc = ajW32Sprite;
  416. for (i = 0; i < 1024; i++)
  417. {
  418. *pjDst++ = *pjSrc++;
  419. }
  420. }
  421. else
  422. {
  423. ndx = 0;
  424. CP_MMU_BP0(ppdev, pjBase, ppdev->cjPointerOffset);
  425. if (cBpp == 1)
  426. {
  427. for (i = 0; i < 1024; i++)
  428. {
  429. //*pjSpriteBuffer++ = ajW32Sprite[i];
  430. CP_WRITE_MMU_BYTE(ppdev, 0, ndx, ajW32Sprite[i]);
  431. ndx++;
  432. }
  433. }
  434. else if (cBpp == 2)
  435. {
  436. for (i = 0; i < 64; i++)
  437. {
  438. for (j = 0; j < 8; j++)
  439. {
  440. //*pjSpriteBuffer++ = jRepMask2[ajW32Sprite[(16*i)+j] & 0xf];
  441. //*pjSpriteBuffer++ = jRepMask2[ajW32Sprite[(16*i)+j] >> 4];
  442. CP_WRITE_MMU_BYTE(ppdev, 0, ndx, jRepMask2[ajW32Sprite[(16*i)+j] & 0xf]);
  443. ndx++;
  444. CP_WRITE_MMU_BYTE(ppdev, 0, ndx, jRepMask2[ajW32Sprite[(16*i)+j] >> 4]);
  445. ndx++;
  446. }
  447. }
  448. }
  449. }
  450. // Set the position of the cursor.
  451. DrvMovePointer(pso, x, y, NULL);
  452. return (SPS_ACCEPT_NOEXCLUDE);
  453. }
  454. /******************************Public*Routine******************************\
  455. * VOID vDisablePointer
  456. *
  457. \**************************************************************************/
  458. VOID vDisablePointer(
  459. PDEV* ppdev)
  460. {
  461. // Nothing to do, really
  462. }
  463. /******************************Public*Routine******************************\
  464. * VOID vAssertModePointer
  465. *
  466. \**************************************************************************/
  467. VOID vAssertModePointer(
  468. PDEV* ppdev,
  469. BOOL bEnable)
  470. {
  471. BYTE* pjBase;
  472. ULONG ulPhysicalAddr;
  473. INT i, j,
  474. nBytesPerBank,
  475. njSpriteBuffer,
  476. n8kBanks,
  477. nRemainingBytes;
  478. if (ppdev->flCaps & CAPS_SW_POINTER)
  479. {
  480. // With a software pointer, we don't have to do anything.
  481. }
  482. else
  483. {
  484. DISPDBG((1,"vAssertModePointer: cxMemory = %d", ppdev->cxMemory));
  485. DISPDBG((1,"vAssertModePointer: cyMemory = %d", ppdev->cyMemory));
  486. DISPDBG((1,"vAssertModePointer: cxScreen = %d", ppdev->cxScreen));
  487. DISPDBG((1,"vAssertModePointer: cyScreen = %d", ppdev->cyScreen));
  488. pjBase = ppdev->pjBase;
  489. // Take care of the init for the Sprite.
  490. if (ppdev->ulChipID == ET6000)
  491. {
  492. BYTE * pjDst = ppdev->pjScreen + ppdev->cjPointerOffset;
  493. ET6K_SPRITE_HORZ_POSITION(ppdev, ppdev->cxScreen / 2); // Center it.
  494. ET6K_SPRITE_VERT_POSITION(ppdev, ppdev->cyScreen / 2); // Center it.
  495. ET6K_HORZ_PRESET(ppdev, 0);
  496. ET6K_VERT_PRESET(ppdev, 0);
  497. ET6K_SPRITE_START_ADDR(ppdev, ppdev->cjPointerOffset);
  498. ET6K_SPRITE_COLOR(ppdev, 0xFF00);
  499. for (i = 0; i < 1024; i++)
  500. {
  501. *pjDst++ = 0xaa;
  502. }
  503. }
  504. else
  505. {
  506. SET_HORZ_POSITION(ppdev->cxScreen * ppdev->cBpp / 2);
  507. SET_VERT_POSITION(ppdev->cyScreen / 2);
  508. SET_HORZ_PRESET(0);
  509. SET_VERT_PRESET(0);
  510. SET_SPRITE_START_ADDR(ppdev->cjPointerOffset);
  511. SET_SPRITE_ROW_OFFSET;
  512. // Set the CRTCB pixel pan register to 0.
  513. OUTP(CRTCB_SPRITE_INDEX, CRTCB_PIXEL_PANNING);
  514. OUTP(CRTCB_SPRITE_DATA, 0);
  515. // Set the pixel depth to 2 bits per pixel.
  516. // (even though the doc says this is only for the CRTCB mode and not
  517. // the sprite mode, the doesn't work unless these values are 0.
  518. OUTP(CRTCB_SPRITE_INDEX, CRTCB_COLOR_DEPTH);
  519. OUTP(CRTCB_SPRITE_DATA, 0x01);
  520. // Set the CRTCB/Sprite control to a 64 X 64 Sprite in overlay mode.
  521. OUTP(CRTCB_SPRITE_INDEX, CRTCB_SPRITE_CONTROL);
  522. OUTP(CRTCB_SPRITE_DATA, 0x02);
  523. // Fill the sprite buffer and the next 17 lines with a transparent
  524. // pattern. This is to get around one of the sprite bugs.
  525. njSpriteBuffer = SPRITE_BUFFER_SIZE;
  526. nBytesPerBank = 0x2000;
  527. n8kBanks = njSpriteBuffer / nBytesPerBank;
  528. nRemainingBytes = njSpriteBuffer % nBytesPerBank;
  529. for (j = 0; j < n8kBanks; j++)
  530. {
  531. // First set Aperture 0 to the sprite buffer address.
  532. CP_MMU_BP0(ppdev, pjBase, (ppdev->cjPointerOffset + (j * nBytesPerBank)));
  533. // Reset the linear address to the beginning of this 8K segment
  534. for (i = 0; i < nBytesPerBank; i++)
  535. {
  536. //*pjSpriteBuffer++ = 0xAA;
  537. CP_WRITE_MMU_BYTE(ppdev, 0, i, 0xAA);
  538. }
  539. }
  540. // Set Aperture 0 to the sprite buffer address.
  541. CP_MMU_BP0(ppdev, pjBase, (ppdev->cjPointerOffset + (j * nBytesPerBank)));
  542. // Reset the linear address to the beginning of this 8K segment
  543. for (i = 0; i < nRemainingBytes; i++)
  544. {
  545. //*pjSpriteBuffer++ = 0xAA;
  546. CP_WRITE_MMU_BYTE(ppdev, 0, i, 0xAA);
  547. }
  548. }
  549. ENABLE_SPRITE(ppdev);
  550. }
  551. }
  552. /******************************Public*Routine******************************\
  553. * BOOL bEnablePointer
  554. *
  555. \**************************************************************************/
  556. BOOL bEnablePointer(
  557. PDEV* ppdev)
  558. {
  559. if (ppdev->flCaps & CAPS_SW_POINTER)
  560. {
  561. // With a software pointer, we don't have to do anything.
  562. }
  563. else
  564. {
  565. // Enable the W32 hardware pointer.
  566. }
  567. // Actually turn on the pointer:
  568. vAssertModePointer(ppdev, TRUE);
  569. DISPDBG((5, "Passed bEnablePointer"));
  570. return(TRUE);
  571. }