Leaked source code of windows server 2003
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.

545 lines
16 KiB

  1. title "Cirrus hardware pointer routines"
  2. ;-----------------------------Module-Header-----------------------------;
  3. ; Module Name: CLCURSOR.ASM
  4. ;
  5. ; This file contains the pointer shape routines to support the Cirrus
  6. ; Logic hardware pointer.
  7. ;
  8. ; Copyright (c) 1983-1992 Microsoft Corporation
  9. ;
  10. ;-----------------------------------------------------------------------;
  11. .386p
  12. .model small,c
  13. include i386\egavga.inc
  14. include i386\clvga.inc
  15. include callconv.inc
  16. ; Mirrors structure in Cirrus.H.
  17. HW_POINTER_SHIFT_INFO struc
  18. ulXShift dd ?
  19. ulYShift dd ?
  20. ulShiftedFlag dd ?
  21. HW_POINTER_SHIFT_INFO ends
  22. .code
  23. page
  24. ;--------------------------Public-Routine-------------------------------;
  25. ; draw_pointer
  26. ;
  27. ; Draw a cursor based at (ulVptlX,ulVptlY) (upper left corner).
  28. ;
  29. ; The currently defined cursor/icon is drawn. If the old
  30. ; cursor/icon is currently on the screen, it is removed.
  31. ;
  32. ; Note: restores all standard VGA registers used to original state.
  33. ;
  34. ; Entry:
  35. ; Passed parameters on stack:
  36. ; (vptlX,vptlY) = location to which to move pointer
  37. ; pointerLoadAddress -> virtual address of Cirrus display memory into
  38. ; which to load pointer masks
  39. ; pointerLoadAddress -> Cirrus bank into which to load pointer masks
  40. ; Returns:
  41. ; None
  42. ; Error Returns:
  43. ; None
  44. ; Registers Preserved:
  45. ; EBX,ESI,EDI,EBP,DS,ES
  46. ; Registers Destroyed:
  47. ; EAX,ECX,EDX,flags
  48. ; Calls:
  49. ; load_cursor
  50. ;-----------------------------------------------------------------------;
  51. cPublicProc CirrusDrawPointer,6,< \
  52. uses esi edi ebx, \
  53. lVptlX: dword, \
  54. lVptlY: dword, \
  55. pVideoMem: dword, \
  56. pLoadAddress: dword, \
  57. pAndMask: ptr, \
  58. pShiftInfo: ptr >
  59. local SavedSeqMode :byte
  60. local SavedProA :byte
  61. local SavedExtReg :byte
  62. local SaveGRFIndex :byte
  63. local SaveEnableSR :byte
  64. local SaveMapMask :byte
  65. local SaveSetReset :byte
  66. local SaveGR5 :byte
  67. local SaveGR3 :byte
  68. local SaveSR7 :byte
  69. ; Save the state of the banking and set the read and write banks to access the
  70. ; pointer bitmap.
  71. mov edx,EGA_BASE + SEQ_ADDR
  72. cli
  73. mov al,SEQ_MODE
  74. out dx,al
  75. inc dx
  76. in al,dx
  77. mov SavedSeqMode,al
  78. or al,SM_CHAIN4
  79. out dx,al
  80. dec dx
  81. mov al,SEQ_MAP_MASK
  82. out dx,al
  83. inc dx
  84. in al,dx
  85. mov SaveMapMask,al ;8 bit map mask
  86. mov edx,EGA_BASE + GRAF_ADDR
  87. in al,dx ;Read graphics index reg
  88. mov SaveGRFIndex,al ;save it
  89. mov al,AVGA_PROA
  90. out dx,al ;Set for OFFSET 0 reg
  91. inc dx
  92. in al,dx
  93. mov SavedProA,al ;Save OFFSET 0 reg
  94. dec dx
  95. mov al,AVGA_MODE_EXTENSIONS
  96. out dx,al ;Set for extensions reg
  97. inc dx
  98. in al,dx
  99. sti
  100. dec dx
  101. mov SavedExtReg,al ;Save extensions
  102. test al,1110b ;Are extensionsETC enabled?
  103. jz @F ;no...
  104. cli
  105. mov al,GRAF_ENAB_SR
  106. out dx,al
  107. inc dx
  108. in al,dx
  109. mov SaveEnableSR,al ;8 bit enable set reset
  110. mov al,0
  111. out dx,al ;set to 0!
  112. dec dx
  113. mov al,GRAF_SET_RESET
  114. out dx,al
  115. inc dx
  116. in al,dx
  117. mov SaveSetReset,al ;8 bit set reset
  118. mov edx,EGA_BASE + SEQ_ADDR
  119. ;??do we need this
  120. mov al,0FFh
  121. out dx,al
  122. mov edx,EGA_BASE + GRAF_ADDR
  123. mov al,GRAF_MODE
  124. out dx,al
  125. inc dx
  126. in al,dx ;save VGA mode
  127. mov SaveGR5,al
  128. mov al,01000000b
  129. out dx,al
  130. dec dx
  131. mov al,GRAF_DATA_ROT
  132. out dx,al
  133. inc dx
  134. in al,dx
  135. mov SaveGR3,al
  136. mov al,0
  137. out dx,al
  138. dec dx
  139. sti
  140. @@:
  141. mov eax,pLoadAddress ; calculate bank from pointer pat addr
  142. shr eax,6 ; ah = bank to select
  143. @@:
  144. mov al,AVGA_PROA ; al = bank select register
  145. out dx,ax
  146. mov ax,EXT_WR_MODES shl 8 + AVGA_MODE_EXTENSIONS
  147. out dx,ax ;packed pel mode
  148. ; See if the masks need to be shifted; if they do, shift and
  149. ; load them. If the default masks can be used but the last masks
  150. ; loaded were shifted, load the default masks.
  151. mov eax,lVptlX
  152. mov ebx,lVptlY
  153. mov ecx,ebx
  154. or ecx,eax ;is either coordinate negative?
  155. jns draw_cursor_unshifted ;no-make sure the unshifted masks
  156. ; are loaded
  157. ;yes-make sure the right shift
  158. ; pattern is loaded
  159. ; Determine the extent of the needed adjustment to the masks.
  160. ; If X is positive, no X shift is needed; if it is negative,
  161. ; then its absolute value is the X shift amount.
  162. and eax,eax
  163. jns short dcs_p1
  164. neg eax ;required X shift
  165. jmp short dcs_p2
  166. align 4
  167. dcs_p1:
  168. sub eax,eax ;no X shift required
  169. dcs_p2:
  170. ; If Y is positive, no Y shift is needed; if it is negative,
  171. ; then its absolute value is the Y shift amount.
  172. and ebx,ebx
  173. jns short dcs_p3
  174. neg ebx ;required Y shift
  175. jmp short dcs_p4
  176. align 4
  177. dcs_p3:
  178. sub ebx,ebx
  179. dcs_p4:
  180. cmp ebx,PTR_HEIGHT ;keep Y in the range 1-PTR_HEIGHT
  181. jbe short ck_x_overflow
  182. mov ebx,PTR_HEIGHT
  183. ck_x_overflow:
  184. cmp eax,(PTR_WIDTH * 8) ;keep X in the range
  185. ; 0 through ( PTR_WIDTH * 8 )
  186. jb short ck_current_shift
  187. mov ebx,PTR_HEIGHT ;if X is fully off the screen,
  188. ; simply move Y off the screen, which
  189. ; is simpler to implement below
  190. ; Shifted masks are required. If the currently loaded masks are shifted in the
  191. ; same way as the new masks, don't need to do anything; otherwise, the shifted
  192. ; masks have to be generated and loaded.
  193. ck_current_shift:
  194. mov edi,pShiftInfo
  195. cmp [edi].ulShiftedFlag,1 ;if there are no currently loaded
  196. ; masks or the currently loaded masks
  197. ; are unshifted, must load shifted
  198. ; masks
  199. mov edi,pShiftInfo
  200. jnz short generate_shifted_masks ;no currently loaded shifted masks
  201. cmp eax,[edi].ulXShift ;if X and Y shifts are both the
  202. jnz short generate_shifted_masks ; same as what's already loaded
  203. cmp ebx,[edi].ulYShift ; memory, then there's no need
  204. ; to do anything
  205. jz draw_cursor_set_location ;Don't need to do anything
  206. ; Load the Cirrus cursor with the masks, shifted as required by
  207. ; the current X and Y.
  208. generate_shifted_masks:
  209. mov [edi].ulXShift,eax
  210. mov [edi].ulYShift,ebx
  211. mov edi,eax ;preserve X shift value
  212. ; Set the Map Mask to enable all planes.
  213. call wait4VertRetrace
  214. mov edx,EGA_BASE + SEQ_ADDR
  215. mov eax,SEQ_MAP_MASK + 00f00h
  216. out dx,ax
  217. mov al,SEQ_EXT_MODE
  218. out dx,al
  219. inc dx
  220. in al,dx
  221. mov SaveSR7,al
  222. or al,SEQ_HIRES_MODE
  223. out dx,al
  224. mov eax,edi ;retrieve X shift value
  225. ; Load the masks.
  226. xchg al,bl ;BL=X shift value, AL=Y shift value
  227. cbw
  228. cwde
  229. neg eax
  230. add eax,PTR_HEIGHT ;unpadded length of cursor
  231. and bl,31 ;X partial byte portion (bit shift)
  232. mov edi,pLoadAddress ;start of cursor load area
  233. and edi,3FFFh ; mask to 16K granularity
  234. add edi,pVideoMem ; move into protected mode space
  235. mov esi,pAndMask ;ESI points to start of AND mask
  236. call shift_mask ;generate shifted masks
  237. ; Restore default Bit Mask setting.
  238. mov edx,EGA_BASE + SEQ_ADDR
  239. mov al,SEQ_EXT_MODE
  240. mov ah,SaveSR7
  241. out dx,ax
  242. mov edx,EGA_BASE + GRAF_ADDR
  243. mov eax,GRAF_BIT_MASK + 0ff00h
  244. out dx,ax
  245. mov esi,pShiftInfo
  246. mov [esi].ulShiftedFlag,1 ;mark that the currently loaded
  247. ; masks are shifted
  248. jmp draw_cursor_set_location
  249. ; Default masks can be used. See if any masks are loaded into memory; if so
  250. ; see if they were shifted: if they were, load unshifted masks; if they
  251. ; weren't, the masks are already properly loaded into Cirrus memory.
  252. align 4
  253. draw_cursor_unshifted:
  254. mov esi,pShiftInfo
  255. cmp [esi].ulShiftedFlag,0 ;are there any currently loaded masks,
  256. ; and if so, are they shifted?
  257. jz draw_cursor_set_location ;no-all set
  258. ;yes-load unshifted masks
  259. call wait4VertRetrace
  260. mov edx,EGA_BASE + SEQ_ADDR
  261. mov al,SEQ_EXT_MODE
  262. out dx,al
  263. inc dx
  264. in al,dx
  265. mov SaveSR7,al
  266. or al,SEQ_HIRES_MODE
  267. out dx,al
  268. mov esi,pAndMask ;ESI points to default masks
  269. ; Copy the cursor patterns into Cirrus mask memory, one mask at a time.
  270. mov ecx,PTR_HEIGHT*4 ;move 4 bytes per scanline of each mask
  271. mov edi,pLoadAddress ;start of cursor load area
  272. and edi,3FFFh ; mask to 16K granularity
  273. add edi,pVideoMem ; move into protected mode spaced
  274. add esi,128
  275. rep movsb
  276. mov ecx,PTR_HEIGHT*4
  277. sub esi,256
  278. load_and_mask_loop:
  279. lodsb
  280. not eax ; cirrus and mask is backwards
  281. stosb
  282. loop load_and_mask_loop
  283. ; Restore the default Map Mask.
  284. mov edx,EGA_BASE + SEQ_ADDR
  285. mov eax,SEQ_MAP_MASK + 00f00h
  286. out dx,ax
  287. mov al,SEQ_EXT_MODE
  288. mov ah,SaveSR7
  289. out dx,ax
  290. mov esi,pShiftInfo
  291. mov [esi].ulShiftedFlag,0 ;mark that the currently loaded masks
  292. ; are unrotated
  293. ; Set the new cursor location.
  294. draw_cursor_set_location:
  295. mov edx,EGA_BASE + SEQ_ADDR
  296. mov ecx,lVptlX ;set X coordinate
  297. and ecx,ecx
  298. jns short set_x_coord ;if negative, force to 0 (the masks in
  299. sub ecx,ecx ; Cirrus memory have already been shifted
  300. ; to compensate)
  301. set_x_coord:
  302. mov ebx,lVptlY ;set Y coordinate
  303. and ebx,ebx
  304. jns short set_y_coord ;if negative, force to 0 (the masks in
  305. sub ebx,ebx ; Cirrus memory have already been shifted
  306. ; to compensate)
  307. set_y_coord:
  308. mov ax,cx
  309. shl ax,5 ; move x-coord into position
  310. or al,SEQ_PX ; generate reg addr based on x-coordinate
  311. out dx,ax ; (10,30,...,D0,F0)
  312. mov ax,bx
  313. shl ax,5 ; move y-coord into position
  314. or al,SEQ_PY ; generate reg addr based on y-coordinate
  315. out dx,ax ; (10,30,...,D0,F0)
  316. ; Restore Cirrus registers to their original states.
  317. mov edx,EGA_BASE + GRAF_ADDR
  318. mov al,AVGA_PROA
  319. mov ah,SavedProA
  320. out dx,ax
  321. mov al,AVGA_MODE_EXTENSIONS
  322. mov ah,SavedExtReg
  323. out dx,ax
  324. test ah,1110b ;Are any exts enabled?
  325. jz @F ;no...
  326. mov al,GRAF_SET_RESET
  327. mov ah,SaveSetReset
  328. out dx,ax
  329. mov al,GRAF_ENAB_SR
  330. mov ah,SaveEnableSR
  331. out dx,ax
  332. mov al,GRAF_MODE
  333. mov ah,SaveGR5
  334. out dx,ax
  335. mov al,GRAF_DATA_ROT
  336. mov ah,SaveGR3
  337. out dx,ax
  338. @@:
  339. mov al,SaveGRFIndex
  340. out dx,al
  341. mov edx,EGA_BASE + SEQ_ADDR
  342. mov al,SEQ_MODE
  343. mov ah,SavedSeqMode
  344. out dx,ax
  345. mov al,SEQ_MAP_MASK
  346. mov ah,SaveMapMask
  347. out dx,ax ;restore default sequencer index and map mask
  348. stdRET CirrusDrawPointer
  349. stdENDP CirrusDrawPointer
  350. page
  351. ;--------------------------------------------------------------------;
  352. ; wait4VertRetrace
  353. ;
  354. ; Returns when the vertical retrace bit has switched from 0 to 1
  355. ;
  356. ;--------------------------------------------------------------------;
  357. wait4VertRetrace proc near
  358. mov edx,EGA_BASE + IN_STAT_1
  359. @@:
  360. in al,dx
  361. and al,08h ; wait for vertical retrace to be clear
  362. jnz @b
  363. @@:
  364. in al,dx
  365. and al,08h ; now wait for it to be set
  366. jz @b
  367. ret ; vertical retrace just started
  368. wait4VertRetrace endp
  369. page
  370. ;--------------------------------------------------------------------;
  371. ; shift_mask
  372. ;
  373. ; Loads a shifted cursor mask.
  374. ;
  375. ; Input: EAX = unpadded mask height (vertical shift)
  376. ; BL = amount of shift to left (horizontal shift)
  377. ; DS:ESI = --> to unshifted masks to load
  378. ; ES:EDI = --> to Cirrus mask memory to load
  379. ;
  380. ; Output: DS:ESI = --> byte after unshifted masks
  381. ; ES:EDI = --> to byte after Cirrus mask memory loaded
  382. ;
  383. ; BH, CH destroyed.
  384. ; Map Mask must enable all planes.
  385. ;--------------------------------------------------------------------;
  386. align 4
  387. shift_mask proc near
  388. push ebp ; use ebp for mask
  389. cmp bl,0
  390. je UPCFast
  391. mov ecx,32
  392. sub ecx,eax
  393. shl ecx,2 ; 4 bytes per scanline
  394. add esi,ecx
  395. push esi
  396. push eax ; assumed non-zero, use as 1st time flag
  397. add esi,128 ; do XOR mask first
  398. xor ebp,ebp
  399. UPCSlow:
  400. mov bh,al
  401. mov ecx,32
  402. sub ecx,eax
  403. push ecx ; number of scanlines to pad at bottom
  404. UPCLoop1:
  405. lodsw ;Fetch 32 bits
  406. mov dx,[esi]
  407. xor eax,ebp
  408. xor edx,ebp
  409. inc esi
  410. inc esi
  411. xor ecx,ecx ; clear high bytes of ecx
  412. mov cl,bl ; shift count in ecx
  413. UPCLoop2: ;Shift loop
  414. shl dh,1
  415. adc dl,dl
  416. adc ah,ah
  417. adc al,al
  418. loop UPCLoop2
  419. stosw ;write shifted data
  420. mov ax,dx
  421. stosw
  422. dec bh ;done one scan
  423. jnz UPCLoop1 ;do the rest
  424. pop ecx ; # of dwords to pad after visible mask
  425. xor eax,eax
  426. rep stosd ;write 0's for transparent
  427. pop eax
  428. and ax,ax
  429. jz end_shift_mask ;already 0, done...
  430. pop esi
  431. xor ecx,ecx
  432. push ecx
  433. dec ebp
  434. jmp UPCSlow ;second pass..
  435. UPCFast:
  436. mov ebx,eax ; number of visible scans in ebx
  437. mov ecx,ebx ; 1 dword per scan
  438. mov edx,32 ; total dwords in a mask
  439. sub edx,ecx ; no. transparent dwords to add at end
  440. push esi ; remember where the mask starts
  441. add esi,128
  442. ; First do the XOR mask - just move the visible part, then pad with zeroes
  443. shl edx,2
  444. add esi,edx
  445. shr edx,2
  446. mov ecx,ebx
  447. rep movsd ; Move opaque plane
  448. mov ecx,edx
  449. xor eax,eax ; pad with zeroes
  450. rep stosd ; transparent
  451. pop esi
  452. shl edx,2
  453. add esi,edx
  454. shr edx,2
  455. mov ecx,ebx
  456. ; Then handle the AND mask - remember that our hardware is backwards here
  457. @@:
  458. lodsd
  459. not eax
  460. stosd
  461. loop @b
  462. mov ecx,edx
  463. xor eax,eax ; pad with zeroes
  464. rep stosd ; transparent
  465. end_shift_mask:
  466. pop ebp
  467. ret
  468. shift_mask endp
  469. end