1 ;-----------------------------------------------------------------------
\r
4 ; This module was written by Matthew MacKenzie
\r
7 ; Clipped transfer of planar bitmaps from system memory to video memory.
\r
12 ; ****** XLIB - Mode X graphics library ****************
\r
13 ; ****** ****************
\r
14 ; ****** Written By Themie Gouthas ****************
\r
16 ; egg@dstos3.dsto.gov.au
\r
17 ; teg@bart.dsto.gov.au
\r
18 ;-----------------------------------------------------------------------
\r
21 include xclippbm.inc
\r
28 ; global clipping variables
\r
35 ColumnMask db 011h,022h,044h,088h
\r
38 LeftDelay db 0, 1, 2, 4
\r
39 RightDelay db 0, 4, 2, 1
\r
42 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
45 ; C near-callable as:
\r
47 ; void x_clip_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);
\r
49 ; Bitmap is a planar bitmap, in the regular Xlib format.
\r
51 ; ax, bx, cx, and dx go south.
\r
58 ARG X:word, Y:word, ScreenOffs:word, Bitmap:dword
\r
59 LOCAL left_counter, right_counter,column,clipped_height,clipped_width,screen_pos,bitmap_pos,bitmap_size,VGA_mask,width_copy,height_temp,screen_width:word=LocalStk
\r
60 ; Tasm 1.0 does not allow the \ line continuation
\r
61 ;LOCAL left_counter:word, right_counter:word, \
\r
62 ; column:word, clipped_height:word, clipped_width:word, \
\r
63 ; screen_pos:word, bitmap_pos:word, bitmap_size:word, \
\r
64 ; VGA_mask:word, width_copy, height_temp:word, \
\r
65 ; screen_width:word=LocalStk
\r
74 ; sociopathic cases: are the clipping bounds out of order?
\r
76 cmp ax, _BottomBound
\r
80 jle @@ReasonableAndProper
\r
81 @@GetOut: ; return a 1 -- no image drawn
\r
90 @@ReasonableAndProper:
\r
92 ; we need to use both the tables in ds and the height and width of the bitmap
\r
97 mov cl, byte ptr es:[si + 1] ; height of bitmap
\r
99 mov al, byte ptr es:[si] ; width of bitmap
\r
101 mov bitmap_size, ax
\r
103 cmp ax, _BottomBound ; top edge below clipping box?
\r
108 dec bx ; bottom edge = Y + height - 1
\r
111 sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound
\r
112 jle @@NoBottomBound
\r
113 sub cx, bx ; clip bottom margin from height
\r
116 sub bx, ax ; top margin = TopBound - Y
\r
118 add ax, bx ; top edge = Y + top margin
\r
119 sub cx, bx ; clip top margin from height
\r
124 mov clipped_height, cx
\r
126 mul _ScrnLogicalByteWidth
\r
128 add di, ScreenOffs ; row of upper-left corner of blit
\r
130 mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height)
\r
134 add si, 2 ; starting position in bitmap
\r
136 ; horizontal position
\r
139 cmp dx, _RightBound
\r
141 mov dx, 0 ; unclipped value for right delay
\r
144 shl ax, 2 ; width in pixels
\r
146 dec ax ; right edge = X + width in pixels - 1
\r
149 sub ax, _RightBound ; right margin = right edge - RightBound
\r
153 mov dl, RightDelay[bx]
\r
155 sub cx, ax ; subtract clipped bytes from width
\r
157 mov right_counter, dx
\r
158 mov dx, 0 ; unclipped value for left delay
\r
160 sub ax, X ; left margin = LeftBound - X
\r
164 mov dl, LeftDelay[bx]
\r
166 shr ax, 2 ; left margin/4, rounded up
\r
167 sub cx, ax ; subtract clipped bytes from width
\r
168 add si, ax ; move starting position in bitmap past margin
\r
169 add di, ax ; move starting position on screen past margin
\r
171 mov left_counter, dx
\r
172 mov clipped_width, cx
\r
174 mov ax, X ; add x coordinate to screen position
\r
184 and bx, 3 ; initial mask
\r
186 mov al, ColumnMask[bx]
\r
188 out dx, al ; initial mask
\r
193 mov ax, _ScrnLogicalByteWidth
\r
194 mov screen_width, ax ; since we move ds
\r
196 ; we've used all our tables, so we can change ds to point to the bitmap,
\r
197 ; and es to point to the screen
\r
198 mov ds, word ptr [Bitmap + 2]
\r
202 cld ; strings go forward
\r
204 sub bx, clipped_width ; bytes to advance one line in bitmap
\r
206 ; let's actually draw something for a change
\r
208 mov ax, clipped_height
\r
209 mov height_temp, ax
\r
210 mov dx, screen_width
\r
211 sub dx, clipped_width ; bytes to advance one line across screen
\r
214 mov cx, clipped_width
\r
216 rep movsw ; in they went, two by two...
\r
218 rep movsb ; catch stray last byte, if it's there
\r
219 add si, bx ; advance one bitmap line
\r
220 add di, dx ; advance one screen line
\r
226 jz @@OuttaHere ; only four columns per customer, please
\r
227 mov dx, SC_INDEX + 1
\r
228 rol byte ptr VGA_mask, 1
\r
229 adc screen_pos, 0 ; add to location if we've wrapped to plane 0
\r
230 mov al, byte ptr VGA_mask
\r
231 out dx, al ; set VGA for next column
\r
233 shr right_counter, 1
\r
234 jnc @@NoRightCounter
\r
235 dec clipped_width ; cut off right edge for later planes
\r
238 shr left_counter, 1
\r
239 jnc @@NoLeftCounter
\r
240 inc clipped_width ; add to left edge for later planes
\r
246 add si, bitmap_size
\r
251 @@OuttaHere: ; return a 0 -- something was inside the boundary
\r
262 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
263 ; _x_clip_masked_pbm
\r
265 ; C near-callable as:
\r
267 ; void x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);
\r
269 ; Bitmap is a planar bitmap, in the regular Xlib format.
\r
270 ; The width of the bitmap cannot be greater than 90 bytes, however.
\r
271 ; Ain't that just criminal?
\r
273 ; ax, bx, cx, and dx go south.
\r
276 ; one branch per pixel is more than enough -- we'll unroll the line-writing
\r
277 ; loop all the way to try to get a little speed (at the expense, as usual,
\r
278 ; of a chunk of memory)
\r
280 MaskedPoint macro offset
\r
281 mov al, [si + offset]
\r
284 mov es:[di + offset], al
\r
287 MaskedPointSize equ 11
\r
289 public _x_clip_masked_pbm
\r
291 _x_clip_masked_pbm proc
\r
292 ARG X:word, Y:word, ScreenOffs:word, Bitmap:dword
\r
293 ; Tasm 1.0 does not allow the \ line continuation
\r
294 LOCAL left_counter,right_counter,column:word,clipped_height,screen_pos,bitmap_pos,bitmap_size,VGA_mask,width_copy,height_temp,screen_width:word=LocalStk
\r
295 ;LOCAL left_counter:word, right_counter:word, \
\r
296 ; column:word, clipped_height:word, \
\r
297 ; screen_pos:word, bitmap_pos:word, bitmap_size:word, \
\r
298 ; VGA_mask:word, width_copy, height_temp:word, \
\r
299 ; screen_width:word=LocalStk
\r
307 ; sociopathic cases: are the clipping bounds out of order?
\r
309 cmp ax, _BottomBound
\r
312 cmp ax, _RightBound
\r
313 jle @@ReasonableAndProper
\r
314 @@GetOut: ; return a 1 -- no image drawn
\r
323 @@ReasonableAndProper:
\r
325 ; we need to use both the tables in ds and the height and width of the bitmap
\r
328 ; vertical position
\r
330 mov cl, byte ptr es:[si + 1] ; height of bitmap
\r
332 mov al, byte ptr es:[si] ; width of bitmap
\r
334 mov bitmap_size, ax
\r
336 cmp ax, _BottomBound ; top edge below clipping box?
\r
341 dec bx ; bottom edge = Y + height - 1
\r
344 sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound
\r
345 jle @@NoBottomBound
\r
346 sub cx, bx ; clip bottom margin from height
\r
349 sub bx, ax ; top margin = TopBound - Y
\r
351 add ax, bx ; top edge = Y + top margin
\r
352 sub cx, bx ; clip top margin from height
\r
357 mov clipped_height, cx
\r
359 mul _ScrnLogicalByteWidth
\r
361 add di, ScreenOffs ; row of upper-left corner of blit
\r
363 mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height)
\r
367 add si, 2 ; starting position in bitmap
\r
369 ; horizontal position
\r
372 cmp dx, _RightBound
\r
374 mov dx, 0 ; unclipped value for right delay
\r
377 shl ax, 2 ; width in pixels
\r
379 dec ax ; right edge = X + width in pixels - 1
\r
382 sub ax, _RightBound ; right margin = right edge - RightBound
\r
386 mov dl, RightDelay[bx]
\r
388 sub cx, ax ; subtract clipped bytes from width
\r
390 mov right_counter, dx
\r
391 mov dx, 0 ; unclipped value for left delay
\r
393 sub ax, X ; left margin = LeftBound - X
\r
397 mov dl, LeftDelay[bx]
\r
399 shr ax, 2 ; left margin/4, rounded up
\r
400 sub cx, ax ; subtract clipped bytes from width
\r
401 add si, ax ; move starting position in bitmap past margin
\r
402 add di, ax ; move starting position on screen past margin
\r
404 mov left_counter, dx
\r
406 imul ax, (-1 * MaskedPointSize)
\r
407 add ax, offset @@LineDone + 2
\r
408 mov cx, ax ; jump offset for plotting
\r
410 mov ax, X ; add x coordinate to screen position
\r
420 and bx, 3 ; initial mask
\r
422 mov al, ColumnMask[bx]
\r
429 mov ax, _ScrnLogicalByteWidth
\r
430 mov screen_width, ax ; since we move ds
\r
432 ; we've used all our tables, so we can change ds to point to the bitmap,
\r
433 ; and es to point to the screen
\r
434 mov ds, word ptr [Bitmap + 2]
\r
440 ; let's actually draw something for a change
\r
441 mov ax, clipped_height
\r
442 mov height_temp, ax
\r
443 mov dx, screen_width
\r
446 ; 90 bottles of beer on the wall...
\r
449 MaskedPoint PointLoop
\r
450 PointLoop = PointLoop - 1
\r
452 ; one bottle of beer...
\r
454 ; final point needs a different branch offset, so we don't use MaskedPoint
\r
461 add si, bx ; advance one bitmap line
\r
462 add di, dx ; advance one screen line
\r
469 jz @@OuttaHere ; only four columns per customer, please
\r
470 mov dx, SC_INDEX + 1
\r
471 rol byte ptr VGA_mask, 1
\r
472 adc screen_pos, 0 ; move to new column if we've wrapped to plane 0
\r
473 mov al, byte ptr VGA_mask
\r
474 out dx, al ; set VGA for next column
\r
476 shr right_counter, 1
\r
477 jnc @@NoRightCounter
\r
478 add cx, MaskedPointSize ; cut off right edge for later planes
\r
480 shr left_counter, 1
\r
481 jnc @@NoLeftCounter
\r
482 sub cx, MaskedPointSize ; add to left edge for later planes
\r
487 add si, bitmap_size
\r
491 mov ax, clipped_height
\r
492 mov height_temp, ax
\r
493 mov dx, screen_width
\r
496 @@OuttaHere: ; return a 0 -- something was inside the boundary
\r
504 _x_clip_masked_pbm endp
\r