/user/microwin/src/drivers/asmplan4.s

https://github.com/rhuitl/uClinux · Assembly · 435 lines · 230 code · 95 blank · 110 comment · 0 complexity · fef26579b4395c5d563f6357bddf52dd MD5 · raw file

  1. ; Copyright (c) 1999 Greg Haerr <greg@censoft.com>
  2. ; Copyright (c) 1991 David I. Bell
  3. ; Permission is granted to use, distribute, or modify this source,
  4. ; provided that this copyright notice remains intact.
  5. ;
  6. ; EGA/VGA Screen Driver 16 color 4 planes, higher speed MASM version
  7. ;
  8. ; Note: this file is a replacement for vgaplan4.c, when raw
  9. ; speed rather than portability is desired
  10. ;
  11. ; The algorithms for some of these routines are taken from the book:
  12. ; Programmer's Guide to PC and PS/2 Video Systems by Richard Wilton.
  13. ;
  14. ; Routines to draw pixels and lines for EGA/VGA resolutions.
  15. ; The drawing mode in the data/rotate register is not changed in this
  16. ; module, and must be changed as necessary by the callers.
  17. ;
  18. PIXBYTES = 80 ; number of bytes in scan line
  19. MSC = 1
  20. ;__MEDIUM__ = 1
  21. include asm.h
  22. .header
  23. .cextrn gr_mode,word ; temp kluge devdraw.c graphics draw mode
  24. .dseg
  25. mode_table:
  26. db 00h,18h,10h,08h ; vga draw modes
  27. .cseg
  28. ;
  29. ; int ega_init(PSD psd)
  30. ;
  31. .cproc ega_init
  32. mov ax,1 ; success
  33. ret
  34. .cendp ega_init
  35. ;
  36. ; Routine to draw a horizontal line.
  37. ; Called from C:
  38. ; ega_drawhine(x1, x2, y, color);
  39. ;
  40. ; works in the following EGA and VGA modes:
  41. ; 200 line 16 colors modes
  42. ; 350 line modes
  43. ; 640x480 16 color
  44. ; argument offsets from bp
  45. x1 = arg1 ; first X coordinate
  46. x2 = arg1 + 2 ; second X coordinate
  47. y = arg1 + 4 ; second Y coordinate
  48. color = arg1 + 6 ; pixel value
  49. .cproc ega_drawhline
  50. push bp ; setup stack frame and preserve registers
  51. mov bp, sp
  52. push si
  53. push di
  54. push es
  55. ; configure the graphics controller
  56. mov dx, 03ceh ; DX := Graphics Controller port address
  57. mov al, #3 ; set data rotate register
  58. lea bx, mode_table
  59. add bx, @gr_mode
  60. mov ah, [bx]
  61. out dx, ax
  62. mov ah, color[bp] ; pixel value
  63. xor al, al ; Set/Reset register number (0)
  64. out dx, ax
  65. mov ax, 0f01h ; AH := bit plane mask for Enable Set/Reset
  66. out dx, ax ; AL := Enable Set/Reset register number
  67. push ds ; preserve DS
  68. mov ax, y[bp]
  69. mov bx, x1[bp]
  70. ; compute pixel address
  71. mov dx, offset PIXBYTES ; AX := [row * PIXBYTES]
  72. mul dx
  73. mov cl, bl ; save low order column bits
  74. shr bx, 1 ; BX := [col / 8]
  75. shr bx, 1
  76. shr bx, 1
  77. add bx, ax ; BX := [row * PIXBYTES] + [col / 8]
  78. and cl, 07h ; CL := [col % 8]
  79. xor cl, 07h ; CL := 7 - [col % 8]
  80. mov ah, 01h ; AH := 1 << [7 - [col % 8]] [mask]
  81. mov dx, 0a000h ; ES := EGA buffer segment address
  82. mov es, dx
  83. ; AH := bit mask
  84. ; ES:BX -> video buffer
  85. ; CL := number bits to shift left
  86. mov di, bx ; ES:DI -> buffer
  87. mov dh, ah ; DH := unshifted bit mask for left byte
  88. not dh
  89. shl dh, cl ; DH := reverse bit mask for first byte
  90. not dh ; DH := bit mask for first byte
  91. mov cx, x2[bp]
  92. and cl, 7
  93. xor cl, 7 ; CL := number of bits to shift left
  94. mov dl, 0ffh ; DL := unshifted bit mask for right byte
  95. shl dl, cl ; DL := bit mask for last byte
  96. ; determine byte offset of first and last pixel in the line
  97. mov ax, x2[bp] ; AX := x2
  98. mov bx, x1[bp] ; BX := x1
  99. mov cl, 3 ; bits to convert pixels to bytes
  100. shr ax, cl ; AX := byte offset of X2
  101. shr bx, cl ; BX := byte offset of X1
  102. mov cx, ax
  103. sub cx, bx ; CX := [number of bytes in line] - 1
  104. ; get Graphics Controller port address into DX
  105. mov bx, dx ; BH := bit mask for first byte
  106. ; BL := bit mask for last byte
  107. mov dx, 03ceh ; DX := Graphics Controller port
  108. mov al, 8 ; AL := Bit mask Register number
  109. ; make video buffer addressable through DS:SI
  110. push es
  111. pop ds
  112. mov si, di ; DS:SI -> video buffer
  113. ; set pixels in leftmost byte of the line
  114. or bh, bh
  115. js L43 ; jump if byte-aligned [x1 is leftmost]
  116. or cx, cx
  117. jnz L42 ; jump if more than one byte in the line
  118. and bl, bh ; BL := bit mask for the line
  119. jmp short L44
  120. L42: mov ah, bh ; AH := bit mask for first byte
  121. out dx, ax ; update graphics controller
  122. movsb ; update bit planes
  123. dec cx
  124. ; use a fast 8086 machine instruction to draw the remainder of the line
  125. L43: mov ah, 0ffh ; AH := bit mask
  126. out dx, ax ; update Bit Mask register
  127. rep movsb ; update all pixels in the line
  128. ; set pixels in the rightmost byte of the line
  129. L44: mov ah, bl ; AH := bit mask for last byte
  130. out dx, ax ; update Graphics Controller
  131. movsb ; update bit planes
  132. pop ds ; restore ds
  133. ; restore default Graphics Controller state and return to caller
  134. ;;xor ax, ax ; AH := 0, AL := 0
  135. ;;out dx, ax ; restore Set/Reset register
  136. ;;inc ax ; AH := 0, AL := 1
  137. ;;out dx, ax ; restore Enable Set/Reset register
  138. ;;mov ax, 0ff08h ; AH := 0xff, AL := 0
  139. ;;out dx, ax ; restore Bit Mask register
  140. pop es
  141. pop di
  142. pop si
  143. pop bp
  144. ret
  145. .cendp ega_drawhline
  146. ;
  147. ; Routine to draw a vertical line.
  148. ; Called from C:
  149. ; ega_drawvline(x, y1, y2, color);
  150. ;
  151. ; works in the following EGA and VGA modes:
  152. ; 200 line 16 colors modes
  153. ; 350 line modes
  154. ; 640x480 16 color
  155. ; argument offsets from bp
  156. x = arg1 ; first X coordinate
  157. y1 = arg1 + 2 ; first Y coordinate
  158. y2 = arg1 + 4 ; second Y coordinate
  159. color = arg1 + 6 ; pixel value
  160. .cproc ega_drawvline
  161. push bp ; setup stack frame and preserve registers
  162. mov bp, sp
  163. push ds
  164. ; configure the graphics controller
  165. mov dx, 03ceh ; DX := Graphics Controller port address
  166. mov al, #3 ; set data rotate register
  167. lea bx, mode_table
  168. add bx, @gr_mode
  169. mov ah, [bx]
  170. out dx, ax
  171. mov ah, color[bp] ; pixel value
  172. xor al, al ; Set/Reset register number (0)
  173. out dx, ax
  174. mov ax, 0f01h ; AH := bit plane mask for Enable Set/Reset
  175. out dx, ax ; AL := Enable Set/Reset register number
  176. ; prepare to draw vertical line
  177. mov ax, y1[bp] ; AX := y1
  178. mov cx, y2[bp] ; BX := y2
  179. ;;mov cx, bx
  180. sub cx, ax ; CX := dy
  181. ;;jge L311 ; jump if dy >= 0
  182. ;;neg cx ; force dy >= 0
  183. ;;mov ax, bx ; AX := y2
  184. L311: inc cx ; CX := number of pixels to draw
  185. mov bx, x[bp] ; BX := x
  186. push cx ; save register
  187. ; compute pixel address
  188. push dx
  189. mov dx, offset PIXBYTES ; AX := [row * PIXBYTES]
  190. mul dx
  191. mov cl, bl ; save low order column bits
  192. shr bx, 1 ; BX := [col / 8]
  193. shr bx, 1
  194. shr bx, 1
  195. add bx, ax ; BX := [row * PIXBYTES] + [col / 8]
  196. and cl, 07h ; CL := [col % 8]
  197. xor cl, 07h ; CL := 7 - [col % 8]
  198. mov ah, 01h ; AH := 1 << [7 - [col % 8]] [mask]
  199. mov dx, 0a000h ; DS := EGA buffer segment address
  200. mov ds, dx
  201. pop dx
  202. ; AH := bit mask
  203. ; DS:BX -> video buffer
  204. ; CL := number bits to shift left
  205. ; set up Graphics controller
  206. shl ah, cl ; AH := bit mask in proper position
  207. mov al, 08h ; AL := Bit Mask register number
  208. out dx, ax
  209. pop cx ; restore register
  210. ; draw the line
  211. mov dx, offset PIXBYTES ; increment for video buffer
  212. L1111: or [bx], al ; set pixel
  213. add bx, dx ; increment to next line
  214. loop L1111
  215. ; restore default Graphics Controller state and return to caller
  216. ;;xor ax, ax ; AH := 0, AL := 0
  217. ;;out dx, ax ; restore Set/Reset register
  218. ;;inc ax ; AH := 0, AL := 1
  219. ;;out dx, ax ; restore Enable Set/Reset register
  220. ;;mov ax, 0ff08h ; AH := 0xff, AL := 0
  221. ;;out dx, ax ; restore Bit Mask register
  222. pop ds
  223. pop bp
  224. ret
  225. .cendp ega_drawvline
  226. ;
  227. ; Routine to set an individual pixel value.
  228. ; Called from C like:
  229. ; ega_drawpixel(x, y, color);
  230. ;
  231. ; argument offsets from bp
  232. x = arg1 ; X coordinate
  233. y = arg1+2 ; Y coordinate
  234. color = arg1+4 ; pixel value
  235. .cproc ega_drawpixel
  236. push bp
  237. mov bp, sp
  238. mov dx, 03ceh ; graphics controller port address
  239. mov al, #3 ; set data rotate register
  240. lea bx, mode_table
  241. add bx, @gr_mode
  242. mov ah, [bx]
  243. out dx, ax
  244. mov cx, x[bp] ; ECX := x
  245. mov ax, y[bp] ; EAX := y
  246. mov dx, offset PIXBYTES ; AX := [y * PIXBYTES]
  247. mul dx
  248. mov bx, cx ; BX := [x / 8]
  249. shr bx, 1
  250. shr bx, 1
  251. shr bx, 1
  252. add bx, ax ; BX := [y * PIXBYTES] + [x / 8]
  253. and cl, 07h ; CL := [x % 8]
  254. xor cl, 07h ; CL := 7 - [x % 8]
  255. mov ch, 01h ; CH := 1 << [7 - [x % 8]] [mask]
  256. shl ch, cl
  257. mov dx, 03ceh ; graphics controller port address
  258. ;;required for old code
  259. ;;mov ax, 0205h ; select write mode 2
  260. ;;out dx, ax ; [load value 2 into mode register 5]
  261. ; new code
  262. xor ax,ax ; set color register 0
  263. mov ah,[bp+8] ; color pixel value
  264. out dx,ax
  265. ; original code
  266. mov al, 08h ; set the bit mask register
  267. mov ah, ch ; [load bit mask into register 8]
  268. out dx, ax
  269. push ds
  270. mov ax, 0a000h ; DS := EGA buffer segment address
  271. mov ds, ax
  272. ; new code
  273. or [bx],al ; quick rmw to set pixel
  274. ;;the following fails under ELKS without cli/sti
  275. ;;using ES works though. Code changed to use single
  276. ;;rmw above rather than write mode 2, but the
  277. ;;reason for this failure is still unknown...
  278. ;;cli
  279. ;;mov al, [bx] ; dummy read to latch bit planes
  280. ;;mov al, color[bp] ; pixel value
  281. ;;mov [bx], al ; write pixel back to bit planes
  282. ;;sti
  283. pop ds ; restore registers and return
  284. mov ax, 0005h ; restore default write mode 0
  285. out dx, ax ; [load value 0 into mode register 5]
  286. ;;mov ax, 0ff08h ; restore default bit mask
  287. ;;out dx, ax ; [load value ff into register 8]
  288. pop bp
  289. ret
  290. .cendp ega_drawpixel
  291. ;
  292. ; Routine to read the value of an individual pixel.
  293. ; Called from C like:
  294. ; color = ega_readpixel(x, y);
  295. ;
  296. ; argument offsets from bp
  297. x = arg1 ; X coordinate
  298. y = arg1+2 ; Y coordinate
  299. .cproc ega_readpixel
  300. push bp
  301. mov bp, sp
  302. push si
  303. push ds
  304. mov ax, y[bp] ; EAX := y
  305. mov bx, x[bp] ; EBX := x
  306. mov dx, offset PIXBYTES ; AX := [y * PIXBYTES]
  307. mul dx
  308. mov cl, bl ; save low order column bits
  309. shr bx, 1 ; BX := [x / 8]
  310. shr bx, 1
  311. shr bx, 1
  312. add bx, ax ; BX := [y * PIXBYTES] + [x / 8]
  313. and cl, 07h ; CL := [x % 8]
  314. xor cl, 07h ; CL := 7 - [x % 8]
  315. mov dx, 0a000h ; DS := EGA buffer segment address
  316. mov ds, dx
  317. mov ch, 01h ; CH := 1 << [7 - [col % 8]] [mask]
  318. shl ch, cl ; CH := bit mask in proper position
  319. mov si, bx ; DS:SI -> region buffer byte
  320. xor bl, bl ; BL is used to accumulate the pixel value
  321. mov dx, 03ceh ; DX := Graphics Controller port
  322. mov ax, 0304h ; AH := initial bit plane number
  323. ; AL := Read Map Select register number
  324. L112: out dx, ax ; select bit plane
  325. mov bh, [si] ; BH := byte from current bit plane
  326. and bh, ch ; mask one bit
  327. neg bh ; bit 7 of BH := 1 if masked bit = 1
  328. ; bit 7 of BH := 0 if masked bit = 0
  329. rol bx, 1 ; bit 0 of BL := next bit from pixel value
  330. dec ah ; AH := next bit plane number
  331. jge L112
  332. xor ax, ax ; AL := pixel value
  333. mov al, bl
  334. pop ds
  335. pop si
  336. pop bp
  337. ret
  338. .cendp ega_readpixel
  339. .cend
  340. end