/Pristine-Pro/FLIC386P/LIBSRC/DRVCOMN/DRVCOMN.ASM

http://github.com/AnimatorPro/Animator-Pro · Assembly · 676 lines · 367 code · 94 blank · 215 comment · 1 complexity · 5404dec3846f1e32b54b30eea30ef191 MD5 · raw file

  1. ;*****************************************************************************
  2. ;* DRVCOMN.ASM - VGA hardware interfaces and common driver support routines.
  3. ;*
  4. ;* NOTES:
  5. ;*
  6. ;* This code is now shared by more than one driver! Be ultra-careful
  7. ;* before changing anything like which parms are passed in registers
  8. ;* and which registers are preserved for internal service routines such
  9. ;* as _pj_vdrv_build_ytable. If you need to find everyone that uses this
  10. ;* code, grep for DRVCOMN.LIB in all the MAKEFILEs and/or *.LNK files
  11. ;* in all subdirs of \paa\drivekit.
  12. ;*
  13. ;* Within the comment blocks for each routine below, if the first line
  14. ;* of comments looks like a C-language prototype, the routine is called
  15. ;* from C, and the normal Watcom -3s parm and register conventions apply.
  16. ;* If the first line doesn't look like a prototype, it's an internal
  17. ;* service routine (called from other asm code), and the parms/regs are
  18. ;* listed in the comment block.
  19. ;*
  20. ;* MAINTENANCE:
  21. ;* ??/??/91 Jim Byers
  22. ;* Original version (hardware.asm).
  23. ;* 03/27/91 Ian Lepore
  24. ;* Overall driver was rewritten. The code in this module was
  25. ;* mostly copied from the original driver's hardware.asm module.
  26. ;* All the output routines were removed to their own modules,
  27. ;* then code was added herein to build the ytable during mode
  28. ;* initialization. Other small changes were made to glue the
  29. ;* original hardware.asm code to changes in device.c.
  30. ;* 04/25/91 Ian Lepore
  31. ;* Changed the pj_vdrv_set_colors routine (see comments there),
  32. ;* and added pj_vdrv_uncc64 and pj_vdrv_uncc256.
  33. ;* 05/28/91 Ian
  34. ;* New module, based on routines formerly in VESAINTF.ASM, now
  35. ;* isolated here as 'common to all SVGA cards' code.
  36. ;* 06/04/91 Ian
  37. ;* Added pj_vdrv_8bit_set_colors() and pj_vdrv_8bit_uncc256() to support
  38. ;* svga cards with full 8-bit dacs.
  39. ;* 07/30/91 Ian
  40. ;* Added declaration of pj_vdrv_modeinfo below; this is now used
  41. ;* by the vesa and svga drivers.
  42. ;* 08/20/91 Ian
  43. ;* Moved declaration of pj_vdrv_raster_library into this module.
  44. ;* This is because there should only be one of these, ideally,
  45. ;* and having them declared in the device.c modules of the users
  46. ;* of the common driver routines leads to multiple declarations
  47. ;* of it in the flilib code.
  48. ;*****************************************************************************
  49. ;******************************************************************************
  50. ;* *
  51. ;* Copyright (C) 1991 by Autodesk, Inc. *
  52. ;* *
  53. ;* Permission to use, copy, modify, and distribute this software and *
  54. ;* its documentation for the purpose of creating applications for *
  55. ;* Autodesk Animator, is hereby granted in accordance with the terms *
  56. ;* of the License Agreement accompanying this product. *
  57. ;* *
  58. ;* Autodesk makes no warrantees, express or implied, as to the *
  59. ;* correctness of this code or any derivative works which incorporate *
  60. ;* it. Autodesk provides the code on an ''as-is'' basis and *
  61. ;* explicitly disclaims any liability, express or implied, for *
  62. ;* errors, omissions, and other problems in the code, including *
  63. ;* consequential and incidental damages. *
  64. ;* *
  65. ;* Use, duplication, or disclosure by the U.S. Government is *
  66. ;* subject to restrictions set forth in FAR 52.227-19 (Commercial *
  67. ;* Computer Software - Restricted Rights) and DFAR 252.227-7013 (c) *
  68. ;* (1) (ii) (Rights in Technical Data and Computer Software, as *
  69. ;* applicable. *
  70. ;******************************************************************************
  71. include stdmacro.i
  72. include drvcomn.i
  73. include rastlib.i
  74. ;*****************************************************************************
  75. ;* the pj_vdrv_has_8bitdac variable.
  76. ;* this is init'd to FALSE, but any detect/init routine can set it to true
  77. ;* as an indication to the build_rastlib routine that the 8bit color-setting
  78. ;* code should be used instead of the 6bit routines.
  79. ;*****************************************************************************
  80. _DATA segment
  81. public pj_vdrv_has_8bitdac
  82. pj_vdrv_has_8bitdac dd 0 ; init 8bitdac flag to FALSE.
  83. _DATA ends
  84. ;*****************************************************************************
  85. ;* the sminfo, ytable, and wcontrol structures.
  86. ;*****************************************************************************
  87. _BSS segment
  88. public pj_vdrv_raster_library
  89. public pj_vdrv_modeinfo
  90. public pj_vdrv_wcontrol
  91. public pj_vdrv_ytable
  92. ;-----------------------------------------------------------------------------
  93. ; the raster libary structure...
  94. ;-----------------------------------------------------------------------------
  95. pj_vdrv_raster_library dd RL_NUM_LIB_CALLS dup (?)
  96. ;-----------------------------------------------------------------------------
  97. ; the sminfo data structure...
  98. ; this is used to relate our internal mode numbers to the hardware modes.
  99. ;-----------------------------------------------------------------------------
  100. align 2
  101. pj_vdrv_modeinfo sminfo MAX_SMODES dup (<>) ; define an array of sminfo structs.
  102. ;-----------------------------------------------------------------------------
  103. ; the ytable data structure...
  104. ;
  105. ; The whole show is built around this data structure, so a few words are
  106. ; probably in order. While the table is defined here as an array of dwords,
  107. ; and is most frequently accessed that way, it is conceptually defined as:
  108. ;
  109. ; struct ytable {
  110. ; short split_at
  111. ; short bank_num
  112. ; long offset
  113. ; };
  114. ;
  115. ; We allocate an array of 1536 (1.5k) of these structures. (Code in the
  116. ; open_graphics() routine will prevent opening a screen with more than 1536
  117. ; scanlines). It is important for performance that this array be statically
  118. ; allocated; dynamic allocation at runtime is not an option. The data in
  119. ; the table is generated by the set_video_environment routine, below.
  120. ;
  121. ; All screen-access code in the driver uses this table as part of addressing
  122. ; video memory. Typically, the Y coordinate is used to index to the proper
  123. ; table entry, and the split_at/bank_num values are obtained with a single
  124. ; dword move. The split/bank value is then compared to the current bank
  125. ; stored in the window control structure. If they are not equal, a branch
  126. ; is taken to a special handling routine for further action. If they are
  127. ; equal, the offset is obtained from the table, and screen access commences.
  128. ; The following code fragment illustrates this:
  129. ;
  130. ; move edi,y_coordinate ; load the Y coordinate for the line.
  131. ; mov eax,[edi*8+ytab_bank] ; load split_at/bank_num for the line,
  132. ; cmp eax,pj_vdrv_wcontrol.wwrcurbank ; compare to the current bank number.
  133. ; jne check_split ; if split line or wrong bank, go do
  134. ; mov edi,[edi*8+ytab_offs] ; special handling, else get the line
  135. ; ; do output ; offset and proceed with the access.
  136. ;
  137. ; When a bank switch is done, the split_at value is NOT stored in the
  138. ; wwrcurbank variable, so a comparison such as that shown above will take
  139. ; the branch when the target line is in a bank other than the current one
  140. ; (ie, a bank switch is needed), or when the target line has a split in it.
  141. ; The premise behind this is that split lines and bank switches are only
  142. ; rarely needed - most output will be to an unsplit line in the current bank.
  143. ; (This is because we mostly process from the top of the screen downwards,
  144. ; truely random accesses to the screen are pretty rare.) Thus, the logic
  145. ; shown above tests for both of the exceptional conditions with a single test
  146. ; and branch, and the fall-thru case will be taken most of the time (avoiding
  147. ; the nemisis of 386 performance coding: taking branches).
  148. ;
  149. ; This table MUST be aligned on a dword boundry for performance!!!
  150. ;-----------------------------------------------------------------------------
  151. align 4
  152. pj_vdrv_ytable dd 1536*2 dup (?) ; ytable, entries are 2 dwords each
  153. ;-----------------------------------------------------------------------------
  154. ; the pj_vdrv_wcontrol data structure....
  155. ;
  156. ; This structure is described in detail in DRVCOMN.I where it is defined. It
  157. ; is statically allocated to allow fast access to it via LEA (2 cycles).
  158. ;
  159. ; This structure MUST be aligned on a dword boundry for performance!!!
  160. ;-----------------------------------------------------------------------------
  161. align 4
  162. pj_vdrv_wcontrol winblk <> ; window control block
  163. _BSS ends
  164. ;*****************************************************************************
  165. ;* code...
  166. ;*****************************************************************************
  167. _TEXT segment
  168. public _pj_vdrv_build_ytable
  169. public pj_vdrv_wait_vblank
  170. public pj_vdrv_set_colors
  171. public pj_vdrv_uncc256
  172. public pj_vdrv_uncc64
  173. public pj_vdrv_8bit_set_colors
  174. public pj_vdrv_8bit_uncc256
  175. public pj_vdrv_8bit_uncc64
  176. ;*****************************************************************************
  177. ;* _pj_vdrv_build_ytable - internal service routine, calc's and fills in ytable.
  178. ;*
  179. ;* Entry:
  180. ;* following values in pj_vdrv_wcontrol struct must be valid:
  181. ;* wpitch wheight wbankshift woffsmask
  182. ;* Exit:
  183. ;* all registers preserved.
  184. ;*****************************************************************************
  185. _pj_vdrv_build_ytable proc near
  186. pushad
  187. lea esi,pj_vdrv_ytable ; ptr for output of values to ytable.
  188. lea edi,pj_vdrv_wcontrol ; ptr to pj_vdrv_wcontrol, we use it a lot.
  189. mov edx,[edi].wheight ; loop counter, lines in ytable.
  190. mov cl,[edi].wbankshift ; we'll be shifting a lot, preload this.
  191. xor ebx,ebx ; zero starting window offset.
  192. #make_ytable:
  193. mov eax,ebx ; get offset of current line from the
  194. and eax,[edi].woffsmask ; start of the screen, mask it to an
  195. mov [esi+4],eax ; offset from start of window, store it.
  196. mov eax,ebx ; get offset of current line, shift it
  197. shr eax,cl ; to get the bank number. Save the
  198. push eax ; bank number on the stack for now.
  199. add ebx,[edi].wpitch ; increment offset to next screen line.
  200. lea eax,[ebx-1] ; calc the address of the last byte on
  201. shr eax,cl ; this line, then get the bank number
  202. cmp eax,[esp] ; of that address. compare that to the
  203. je short #nosplit ; bank number for the start of the
  204. mov eax,[edi].woffsmask ; line. if they're not equal, the
  205. inc eax ; line is split. calc the location
  206. sub eax,[esi+4] ; of the split and store it alongside
  207. mov [esp+2],ax ; the bank number saved on the stack.
  208. #nosplit:
  209. pop eax ; get the split_at/bank_num value,
  210. mov [esi],eax ; store it into the ytable.
  211. add esi,8 ; point to the next ytable entry.
  212. dec edx ; decrement the loop counter, if not
  213. jnz short #make_ytable ; zero, continue with the next line.
  214. popad
  215. ret
  216. _pj_vdrv_build_ytable endp
  217. ;*****************************************************************************
  218. ;* void pj_vdrv_wait_vblank(void)
  219. ;* busy-wait for vblank (this works with any VGA)
  220. ;*****************************************************************************
  221. align 4
  222. pj_vdrv_wait_vblank proc near
  223. mov edx,3dah ; video status port
  224. #wait:
  225. in al,dx
  226. test al,8
  227. jz short #wait
  228. ret
  229. pj_vdrv_wait_vblank endp
  230. ;*****************************************************************************
  231. ; void pj_vdrv_set_colors(Raster *r, int start, int count, UBYTE *color_table)
  232. ;
  233. ; /* NOTE: the color table has values that range from 0 to 255,
  234. ; so the colors must be divided by 4 so they'll fit into
  235. ; VGA tables that only range from 0 to 63 */
  236. ;
  237. ; Note, this routine modified as follows:
  238. ;
  239. ; My VGA book says that a minimum of 240ns must elapse between accesses
  240. ; to the vga color data registers. Assuming a 50mhz 386 chip, this
  241. ; means we need 12 cycles between OUT instructions when setting colors.
  242. ; The original version used JMP instructions to add a delay, and this
  243. ; was caused delay between accesses of about 15-16 cycles plus the
  244. ; time to reload the prefetch queue. Now the routine uses NOP
  245. ; instructions to effect the slight delay needed. (One NOP does the
  246. ; the trick (just barely), giving us 11 cycles between accesses. The
  247. ; use of 11 instead of 12 is predicated on Jim K's experience of never
  248. ; finding a card that really needs a delay at all, and the fact that we
  249. ; already have a huge fudge factor built in by assuming a 50mhz 386
  250. ; running without any wait states while accessing either memory or
  251. ; the graphics card.
  252. ;
  253. ; Also, the original routine re-selected the next color register
  254. ; after each rgb triplet, but my vga book says that the
  255. ; register number will auto-increment after each triplet, and it
  256. ; doesn't mention any exceptions to that for given cards.
  257. ;
  258. ; Anyway, if any of the above turns out to be bogus for a given card,
  259. ; the original routine still exists below, commented out with a IF 0.
  260. ;
  261. ;*****************************************************************************
  262. align 4
  263. pj_vdrv_set_colors proc near
  264. #raster equ [esp+4]
  265. #start equ [esp+08]
  266. #count equ [esp+12]
  267. #ptable equ [esp+16]
  268. mov eax,#start ; starting color #
  269. mov ecx,#count ; number of colors
  270. mov edx,#ptable ; pallette address
  271. push esi
  272. mov esi,edx
  273. mov edx,3c8h ; address vga color palette control port
  274. out dx,al ; select starting color register
  275. inc edx ; address vga color palette data port
  276. nop
  277. #loop:
  278. lodsb ; load red
  279. shr al,2 ; convert 256- to 64-level color
  280. out dx,al ; store red
  281. nop ; waste 3 cycles
  282. lodsb ; load green
  283. shr al,2 ; convert 256- to 64-level color
  284. out dx,al ; store green
  285. nop ; waste 3 cycles
  286. lodsb ; load blue
  287. shr al,2 ; convert 256- to 64-level color
  288. out dx,al ; store blue
  289. dec ecx ; count the color as done
  290. jnz short #loop ; go do next color (wastes 8+ cycles)
  291. pop esi
  292. ret
  293. pj_vdrv_set_colors endp
  294. if 0 ; old version...
  295. align 4
  296. pj_vdrv_set_colors proc near
  297. #raster equ [ebp+8]
  298. #start equ [ebp+12]
  299. #count equ [ebp+16]
  300. #ptable equ [ebp+20]
  301. push ebp
  302. mov ebp, esp
  303. push ebx
  304. push esi
  305. mov ebx,#start ; starting color #
  306. mov ecx,#count ; number of colors
  307. mov esi,#ptable ; pallette address
  308. #loop:
  309. mov edx,3c8h ; vga color control port
  310. mov al,bl ; current color #
  311. out dx,al ; select color
  312. inc edx ; vga color palette port
  313. jmp #delay1
  314. #delay1:
  315. lodsb
  316. shr al,2 ; convert 256- to 64-level color
  317. out dx,al ; red
  318. jmp #delay2
  319. #delay2:
  320. lodsb
  321. shr al,2 ; convert 256- to 64-level color
  322. out dx,al ; green
  323. jmp #delay3
  324. #delay3:
  325. lodsb
  326. shr al,2 ; convert 256- to 64-level color
  327. out dx,al ; blue
  328. inc ebx ; next color #
  329. loop #loop
  330. pop esi
  331. pop ebx
  332. pop ebp
  333. ret
  334. pj_vdrv_set_colors endp
  335. endif
  336. ;*****************************************************************************
  337. ; void pj_vdrv_uncc256(Raster *r, void *ucbuf);
  338. ;
  339. ; Notes under pj_vdrv_set_colors apply to this routine.
  340. ;*****************************************************************************
  341. align 4
  342. pj_vdrv_uncc256 proc near
  343. #raster equ [esp+4]
  344. #ucbuf equ [esp+8]
  345. mov edx,#ucbuf
  346. push ebx
  347. push esi
  348. push edi
  349. mov esi,edx
  350. movzx ebx,word ptr [esi]
  351. add esi,2
  352. xor edi,edi
  353. xor ecx,ecx
  354. #packetloop:
  355. dec ebx
  356. js short #done
  357. mov cl,[esi] ; get skip count
  358. add edi,ecx ; add to color index
  359. mov cl,[esi+1] ; get change count
  360. add esi,2 ; incr input pointer
  361. mov eax,edi ; load color register index
  362. mov edx,3c8h ; address vga color palette control port
  363. out dx,al ; select starting color register
  364. inc edx ; address vga color palette data port
  365. nop
  366. #loop:
  367. inc edi ; increment index
  368. lodsb ; load red
  369. shr al,2 ; convert 256- to 64-level color
  370. out dx,al ; store red
  371. nop ; waste 3 cycles
  372. lodsb ; load green
  373. shr al,2 ; convert 256- to 64-level color
  374. out dx,al ; store green
  375. nop ; waste 3 cycles
  376. lodsb ; load blue
  377. shr al,2 ; convert 256- to 64-level color
  378. out dx,al ; store blue
  379. dec cl ; (note: MUST dec cl, not ecx!)
  380. jnz short #loop ; go do next color (wastes 8+ cycles)
  381. jmp short #packetloop
  382. #done:
  383. pop edi
  384. pop esi
  385. pop ebx
  386. ret
  387. pj_vdrv_uncc256 endp
  388. ;*****************************************************************************
  389. ; void pj_vdrv_uncc64(Raster *r, void *ucbuf);
  390. ;
  391. ; Notes under pj_vdrv_set_colors apply to this routine.
  392. ; This is an exact clone of uncc256, except the 256-to-64-level shift
  393. ; instructions were replaced with NOPs.
  394. ;*****************************************************************************
  395. align 4
  396. pj_vdrv_uncc64 proc near
  397. #raster equ [esp+4]
  398. #ucbuf equ [esp+8]
  399. mov edx,#ucbuf
  400. push ebx
  401. push esi
  402. push edi
  403. mov esi,edx
  404. movzx ebx,word ptr [esi]
  405. add esi,2
  406. xor edi,edi
  407. xor ecx,ecx
  408. #packetloop:
  409. dec ebx
  410. js short #done
  411. mov cl,[esi] ; get skip count
  412. add edi,ecx ; add to color index
  413. mov cl,[esi+1] ; get change count
  414. add esi,2 ; incr input pointer
  415. mov eax,edi ; load color register index
  416. mov edx,3c8h ; address vga color palette control port
  417. out dx,al ; select starting color register
  418. inc edx ; address vga color palette data port
  419. nop
  420. #loop:
  421. inc edi ; increment index
  422. lodsb ; load red
  423. nop ; color is already 64-level
  424. out dx,al ; store red
  425. nop ; waste 3 cycles
  426. lodsb ; load green
  427. nop ; color is already 64-level
  428. out dx,al ; store green
  429. nop ; waste 3 cycles
  430. lodsb ; load blue
  431. nop ; color is already 64-level
  432. out dx,al ; store blue
  433. dec cl ; (note: MUST dec cl, not ecx!)
  434. jnz short #loop ; go do next color (wastes 8+ cycles)
  435. jmp short #packetloop
  436. #done:
  437. pop edi
  438. pop esi
  439. pop ebx
  440. ret
  441. pj_vdrv_uncc64 endp
  442. ;*****************************************************************************
  443. ; void pj_vdrv_8bit_set_colors(Raster *r, int start, int count, UBYTE *color_table)
  444. ;
  445. ; Set colors routine for cards with 8-bit DACs.
  446. ;*****************************************************************************
  447. align 4
  448. pj_vdrv_8bit_set_colors proc near
  449. #raster equ [esp+4]
  450. #start equ [esp+08]
  451. #count equ [esp+12]
  452. #ptable equ [esp+16]
  453. mov eax,#start ; starting color #
  454. mov ecx,#count ; number of colors
  455. mov edx,#ptable ; pallette address
  456. push esi
  457. mov esi,edx
  458. mov edx,3c8h ; address vga color palette control port
  459. out dx,al ; select starting color register
  460. inc edx ; address vga color palette data port
  461. nop
  462. #loop:
  463. lodsb ; load red
  464. nop ;
  465. out dx,al ; store red
  466. nop ; waste 3 cycles
  467. lodsb ; load green
  468. nop ;
  469. out dx,al ; store green
  470. nop ; waste 3 cycles
  471. lodsb ; load blue
  472. nop ;
  473. out dx,al ; store blue
  474. dec ecx ; count the color as done
  475. jnz short #loop ; go do next color (wastes 8+ cycles)
  476. pop esi
  477. ret
  478. pj_vdrv_8bit_set_colors endp
  479. ;*****************************************************************************
  480. ; void pj_vdrv_8bit_uncc256(Raster *r, void *ucbuf);
  481. ;
  482. ;*****************************************************************************
  483. align 4
  484. pj_vdrv_8bit_uncc256 proc near
  485. #raster equ [esp+4]
  486. #ucbuf equ [esp+8]
  487. mov edx,#ucbuf
  488. push ebx
  489. push esi
  490. push edi
  491. mov esi,edx
  492. movzx ebx,word ptr [esi]
  493. add esi,2
  494. xor edi,edi
  495. xor ecx,ecx
  496. #packetloop:
  497. dec ebx
  498. js short #done
  499. mov cl,[esi] ; get skip count
  500. add edi,ecx ; add to color index
  501. mov cl,[esi+1] ; get change count
  502. add esi,2 ; incr input pointer
  503. mov eax,edi ; load color register index
  504. mov edx,3c8h ; address vga color palette control port
  505. out dx,al ; select starting color register
  506. inc edx ; address vga color palette data port
  507. nop
  508. #loop:
  509. inc edi ; increment index
  510. lodsb ; load red
  511. nop ;
  512. out dx,al ; store red
  513. nop ; waste 3 cycles
  514. lodsb ; load green
  515. nop ;
  516. out dx,al ; store green
  517. nop ; waste 3 cycles
  518. lodsb ; load blue
  519. nop ;
  520. out dx,al ; store blue
  521. dec cl ; (note: MUST dec cl, not ecx!)
  522. jnz short #loop ; go do next color (wastes 8+ cycles)
  523. jmp short #packetloop
  524. #done:
  525. pop edi
  526. pop esi
  527. pop ebx
  528. ret
  529. pj_vdrv_8bit_uncc256 endp
  530. ;*****************************************************************************
  531. ; void pj_vdrv_8bit_uncc64(Raster *r, void *ucbuf);
  532. ;*****************************************************************************
  533. align 4
  534. pj_vdrv_8bit_uncc64 proc near
  535. #raster equ [esp+4]
  536. #ucbuf equ [esp+8]
  537. mov edx,#ucbuf
  538. push ebx
  539. push esi
  540. push edi
  541. mov esi,edx
  542. movzx ebx,word ptr [esi]
  543. add esi,2
  544. xor edi,edi
  545. xor ecx,ecx
  546. #packetloop:
  547. dec ebx
  548. js short #done
  549. mov cl,[esi] ; get skip count
  550. add edi,ecx ; add to color index
  551. mov cl,[esi+1] ; get change count
  552. add esi,2 ; incr input pointer
  553. mov eax,edi ; load color register index
  554. mov edx,3c8h ; address vga color palette control port
  555. out dx,al ; select starting color register
  556. inc edx ; address vga color palette data port
  557. nop
  558. #loop:
  559. inc edi ; increment index
  560. lodsb ; load red
  561. shl al,2 ; make 64-level color into 256-level
  562. out dx,al ; store red
  563. nop ; waste 3 cycles
  564. lodsb ; load green
  565. shl al,2 ; make 64-level color into 256-level
  566. out dx,al ; store green
  567. nop ; waste 3 cycles
  568. lodsb ; load blue
  569. shl al,2 ; make 64-level color into 256-level
  570. out dx,al ; store blue
  571. dec cl ; (note: MUST dec cl, not ecx!)
  572. jnz short #loop ; go do next color (wastes 8+ cycles)
  573. jmp short #packetloop
  574. #done:
  575. pop edi
  576. pop esi
  577. pop ebx
  578. ret
  579. pj_vdrv_8bit_uncc64 endp
  580. _TEXT ends
  581. end
  582.