1 ;-----------------------------------------------------------------------
\r
4 ; Planar Bitmap functions - System Ram <-> Video Ram
\r
10 ; ****** XLIB - Mode X graphics library ****************
\r
11 ; ****** ****************
\r
12 ; ****** Written By Themie Gouthas ****************
\r
14 ; egg@dstos3.dsto.gov.au
\r
15 ; teg@bart.dsto.gov.au
\r
16 ;-----------------------------------------------------------------------
\r
21 This module implements a set of functions to operate on planar bitmaps.
\r
22 Planar bitmaps as used by these functions have the following structure:
\r
24 BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255
\r
25 BYTE 1 The bitmap height in rows range 1..255
\r
26 BYTE 2..n1 The plane 0 pixels width*height bytes
\r
27 BYTE n1..n2 The plane 1 pixels width*height bytes
\r
28 BYTE n2..n3 The plane 2 pixels width*height bytes
\r
29 BYTE n3..n4 The plane 3 pixels width*height bytes
\r
31 These functions provide the fastest possible bitmap blts from system ram to
\r
32 to video and further, the single bitmap is applicable to all pixel
\r
33 allignments. The masked functions do not need separate masks since all non
\r
34 zero pixels are considered to be masking pixels, hence if a pixel is 0 the
\r
35 corresponding screen destination pixel is left unchanged.
\r
41 include xpbitmap.inc
\r
45 ;----------------------------------------------------------------------
\r
46 ; x_flip_masked_pbm - mask write a planar bitmap from system ram to video ram
\r
47 ; all zero source bitmap bytes indicate destination byte to be left unchanged
\r
48 ; If "Orientation" is set then the bitmap is flipped from left to right as
\r
51 ; Source Bitmap structure:
\r
53 ; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
\r
54 ; Bitmap data (plane 2)..,Bitmap data (plane 3)..
\r
56 ; note width is in bytes ie lots of 4 pixels
\r
58 ; x_flip_masked_pbm(X,Y,ScrnOffs,char far * Bitmap, Orientation)
\r
61 ; LIMITATIONS: No clipping is supported
\r
62 ; Only supports bitmaps with widths which are a multiple of
\r
65 ; Written by Themie Gouthas
\r
66 ;----------------------------------------------------------------------
\r
67 _x_flip_masked_pbm proc
\r
68 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word
\r
69 LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk
\r
72 sub sp,LocalStk ; Create space for local variables
\r
79 mov ax,[Y] ; Calculate dest screen row
\r
80 mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
81 mul bx ; width then adding screen offset
\r
82 mov di,[ScrnOffs] ; store result in DI
\r
84 mov cx,[X] ; Load X coord into CX and make a
\r
85 mov dx,cx ; copy in DX
\r
86 shr dx,2 ; Find starting byte in dest row
\r
87 add di,dx ; add to DI giving screen offset of
\r
88 ; first pixel's byte
\r
89 lds si,[Bitmap] ; DS:SI -> Bitmap data
\r
90 lodsw ; Al = B.M. width (bytes) AH = B.M.
\r
95 mov [BMHeight],ah ; Save source bitmap dimensions
\r
96 xor ah,ah ; LineInc = bytes to the begin.
\r
97 add bx,ax ; of bitmaps next row on screen
\r
99 mov bh,al ; Use bh as column loop count
\r
100 and cx,0003h ; mask X coord giving plane of 1st
\r
101 ; bitmap pixel(zero CH coincidentally)
\r
102 mov ah,11h ; Init. mask for VGA plane selection
\r
103 shl ah,cl ; Shift for starting pixel plane
\r
104 mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
\r
108 mov [Plane],4 ; Set plane counter to 4
\r
110 push di ; Save bitmap's start dest. offset
\r
111 mov bl,[BMHeight] ; Reset row counter (BL)
\r
113 out dx,al ; set vga write plane
\r
115 mov cl,bh ; Reset Column counter cl
\r
117 lodsb ; Get next source bitmap byte
\r
118 or al,al ; If not zero then write to dest.
\r
119 jz @@NoPixel ; otherwise skip to next byte
\r
123 loop @@ColLoop ; loop if more columns left
\r
124 add di,[LineInc] ; Move to next row
\r
125 dec bl ; decrement row counter
\r
126 jnz @@RowLoop ; Jump if more rows left
\r
127 pop di ; Restore bitmaps start dest byte
\r
128 ror ah,1 ; Shift mask for next plane
\r
129 sbb di,0 ; If wrapped increment dest address
\r
130 dec [Plane] ; Decrement plane counter
\r
131 jnz @@PlaneLoop ; Jump if more planes left
\r
133 pop ds ; restore data segment
\r
134 pop di ; restore registers
\r
136 mov sp,bp ; dealloc local variables
\r
139 _x_flip_masked_pbm endp
\r
142 ;----------------------------------------------------------------------
\r
143 ; x_put_masked_pbm - mask write a planar bitmap from system ram to video ram
\r
144 ; all zero source bitmap bytes indicate destination byte to be left unchanged
\r
146 ; Source Bitmap structure:
\r
148 ; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
\r
149 ; Bitmap data (plane 2)..,Bitmap data (plane 3)..
\r
151 ; note width is in bytes ie lots of 4 pixels
\r
153 ; x_put_masked_pbm(X,Y,ScrnOffs,char far * Bitmap)
\r
156 ; LIMITATIONS: No clipping is supported
\r
157 ; Only supports bitmaps with widths which are a multiple of
\r
160 ; Written by Themie Gouthas
\r
161 ;----------------------------------------------------------------------
\r
162 _x_put_masked_pbm proc
\r
163 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword
\r
164 LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk
\r
167 sub sp,LocalStk ; Create space for local variables
\r
174 mov ax,[Y] ; Calculate dest screen row
\r
175 mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
176 mul bx ; width then adding screen offset
\r
177 mov di,[ScrnOffs] ; store result in DI
\r
179 mov cx,[X] ; Load X coord into CX and make a
\r
180 mov dx,cx ; copy in DX
\r
181 shr dx,2 ; Find starting byte in dest row
\r
182 add di,dx ; add to DI giving screen offset of
\r
183 ; first pixel's byte
\r
184 lds si,[Bitmap] ; DS:SI -> Bitmap data
\r
185 lodsw ; Al = B.M. width (bytes) AH = B.M.
\r
188 mov [BMHeight],ah ; Save source bitmap dimensions
\r
189 xor ah,ah ; LineInc = bytes to the begin.
\r
190 sub bx,ax ; of bitmaps next row on screen
\r
192 mov bh,al ; Use bh as column loop count
\r
193 and cx,0003h ; mask X coord giving plane of 1st
\r
194 ; bitmap pixel(zero CH coincidentally)
\r
195 mov ah,11h ; Init. mask for VGA plane selection
\r
196 shl ah,cl ; Shift for starting pixel plane
\r
197 mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
\r
201 mov [Plane],4 ; Set plane counter to 4
\r
203 push di ; Save bitmap's start dest. offset
\r
204 mov bl,[BMHeight] ; Reset row counter (BL)
\r
206 out dx,al ; set vga write plane
\r
208 mov cl,bh ; Reset Column counter cl
\r
210 lodsb ; Get next source bitmap byte
\r
211 or al,al ; If not zero then write to dest.
\r
212 jz @@NoPixel ; otherwise skip to next byte
\r
216 loop @@ColLoop ; loop if more columns left
\r
217 add di,[LineInc] ; Move to next row
\r
218 dec bl ; decrement row counter
\r
219 jnz @@RowLoop ; Jump if more rows left
\r
220 pop di ; Restore bitmaps start dest byte
\r
221 rol ah,1 ; Shift mask for next plane
\r
222 adc di,0 ; If wrapped increment dest address
\r
223 dec [Plane] ; Decrement plane counter
\r
224 jnz @@PlaneLoop ; Jump if more planes left
\r
226 pop ds ; restore data segment
\r
227 pop di ; restore registers
\r
229 mov sp,bp ; dealloc local variables
\r
232 _x_put_masked_pbm endp
\r
236 ;----------------------------------------------------------------------
\r
237 ; x_put_pbm - Write a planar bitmap from system ram to video ram
\r
239 ; Source Bitmap structure:
\r
241 ; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
\r
242 ; Bitmap data (plane 2)..,Bitmap data (plane 3)..
\r
244 ; note width is in bytes ie lots of 4 pixels
\r
246 ; x_put_pbm(X,Y,ScrnOffs,char far * Bitmap)
\r
249 ; LIMITATIONS: No clipping is supported
\r
250 ; Only supports bitmaps with widths which are a multiple of
\r
252 ; FEATURES : Automatically selects REP MOVSB or REP MOVSW depending on
\r
253 ; source bitmap width, by modifying opcode ;-).
\r
255 ; Written by Themie Gouthas
\r
256 ;----------------------------------------------------------------------
\r
260 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword
\r
261 LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk
\r
264 sub sp,LocalStk ; Create space for local variables
\r
271 mov ax,[Y] ; Calculate dest screen row
\r
272 mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
273 mul bx ; width then adding screen offset
\r
274 mov di,[ScrnOffs] ; store result in DI
\r
276 mov cx,[X] ; Load X coord into CX and make a
\r
277 mov dx,cx ; copy in DX
\r
278 shr dx,2 ; Find starting byte in dest row
\r
279 add di,dx ; add to DI giving screen offset of
\r
280 ; first pixel's byte
\r
281 lds si,[Bitmap] ; DS:SI -> Bitmap data
\r
282 lodsw ; Al = B.M. width (bytes) AH = B.M.
\r
285 mov [BMHeight],ah ; Save source bitmap dimensions
\r
286 xor ah,ah ; LineInc = bytes to the begin.
\r
287 sub bx,ax ; of bitmaps next row on screen
\r
290 ; Self Modifying, Shame, shame shame..
\r
291 and cx,0003h ; mask X coord giving plane of 1st
\r
292 ; bitmap pixel(zero CH coincidentally)
\r
293 mov ah,11h ; Init. mask for VGA plane selection
\r
294 shl ah,cl ; Shift for starting pixel plane
\r
295 mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
\r
299 mov [Plane],4 ; Set plane counter to 4
\r
308 rep movsw ; Copy a complete row for curr plane
\r
311 add di,[LineInc] ; Move to next row
\r
312 dec bl ; decrement row counter
\r
313 jnz @@RowLoop ; Jump if more rows left
\r
314 pop di ; Restore bitmaps start dest byte
\r
315 rol ah,1 ; Shift mask for next plane
\r
316 adc di,0 ; If wrapped increment dest address
\r
317 dec [Plane] ; Decrement plane counter
\r
318 jnz @@PlaneLoop ; Jump if more planes left
\r
320 pop ds ; restore data segment
\r
321 pop di ; restore registers
\r
323 mov sp,bp ; dealloc local variables
\r
328 ;----------------------------------------------------------------------
\r
329 ; x_flip_pbm - Write a planar bitmap from system ram to video ram
\r
330 ; If "Orientation" is set then the bitmap is flipped from left to right as
\r
334 ; Source Bitmap structure:
\r
336 ; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
\r
337 ; Bitmap data (plane 2)..,Bitmap data (plane 3)..
\r
339 ; note width is in bytes ie lots of 4 pixels
\r
341 ; x_flip_pbm(X,Y,ScrnOffs,char far * Bitmap, WORD orientation)
\r
344 ; LIMITATIONS: No clipping is supported
\r
345 ; Only supports bitmaps with widths which are a multiple of
\r
348 ; NOTES: The flipped put function is slower than the standard put function
\r
350 ; Written by Themie Gouthas
\r
351 ;----------------------------------------------------------------------
\r
353 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word
\r
354 LOCAL Plane:byte,BMHeight:byte,LineInc:word=LocalStk
\r
357 sub sp,LocalStk ; Create space for local variables
\r
364 mov ax,[Y] ; Calculate dest screen row
\r
365 mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
366 mul bx ; width then adding screen offset
\r
367 mov di,[ScrnOffs] ; store result in DI
\r
369 mov cx,[X] ; Load X coord into CX and make a
\r
370 mov dx,cx ; copy in DX
\r
371 shr dx,2 ; Find starting byte in dest row
\r
372 add di,dx ; add to DI giving screen offset of
\r
373 ; first pixel's byte
\r
374 lds si,[Bitmap] ; DS:SI -> Bitmap data
\r
375 lodsw ; Al = B.M. width (bytes) AH = B.M.
\r
380 mov [BMHeight],ah ; Save source bitmap dimensions
\r
381 xor ah,ah ; LineInc = bytes to the begin.
\r
382 add bx,ax ; of bitmaps next row on screen
\r
384 mov bh,al ; Use bh as column loop count
\r
385 and cx,0003h ; mask X coord giving plane of 1st
\r
386 ; bitmap pixel(zero CH coincidentally)
\r
387 mov ah,11h ; Init. mask for VGA plane selection
\r
388 shl ah,cl ; Shift for starting pixel plane
\r
389 mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
\r
393 mov [Plane],4 ; Set plane counter to 4
\r
395 push di ; Save bitmap's start dest. offset
\r
396 mov bl,[BMHeight] ; Reset row counter (BL)
\r
398 out dx,al ; set vga write plane
\r
400 mov cl,bh ; Reset Column counter cl
\r
406 loop @@ColLoop ; loop if more columns left
\r
408 add di,[LineInc] ; Move to next row
\r
409 dec bl ; decrement row counter
\r
410 jnz @@RowLoop ; Jump if more rows left
\r
411 pop di ; Restore bitmaps start dest byte
\r
412 ror ah,1 ; Shift mask for next plane
\r
413 sbb di,0 ; If wrapped increment dest address
\r
414 dec [Plane] ; Decrement plane counter
\r
415 jnz @@PlaneLoop ; Jump if more planes left
\r
417 pop ds ; restore data segment
\r
418 pop di ; restore registers
\r
420 mov sp,bp ; dealloc local variables
\r
426 ;----------------------------------------------------------------------
\r
427 ; x_get_pbm - Read a planar bitmap to system ram from video ram
\r
429 ; Source Bitmap structure:
\r
431 ; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1)..,
\r
432 ; Bitmap data (plane 2)..,Bitmap data (plane 3)..
\r
434 ; note width is in bytes ie lots of 4 pixels
\r
436 ; x_get_pbm(X,Y,BMwidth,BMheight,ScrnOffs,char far * Bitmap)
\r
439 ; LIMITATIONS: No clipping is supported
\r
440 ; Only supports bitmaps with widths which are a multiple of
\r
442 ; FEATURES : Automatically selects REP MOVSB or REP MOVSW depending on
\r
443 ; source bitmap width, by modifying opcode ;-).
\r
445 ; Written by Themie Gouthas
\r
446 ;----------------------------------------------------------------------
\r
448 ARG X:word,Y:word,SrcWidth:byte,SrcHeight:byte,ScrnOffs:word,Bitmap:dword
\r
449 LOCAL Plane:byte,LineInc:word=LocalStk
\r
452 sub sp,LocalStk ; Create space for local variables
\r
458 mov ax,[Y] ; Calculate screen row
\r
459 mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen
\r
460 mul bx ; width then adding screen offset
\r
461 mov si,[ScrnOffs] ; store result in SI
\r
463 mov cx,[X] ; Load X coord into CX and make a
\r
464 mov dx,cx ; copy in DX
\r
465 shr dx,2 ; Find starting byte in screen row
\r
466 add si,dx ; add to SI giving screen offset of
\r
467 ; first pixel's byte
\r
470 les di,[Bitmap] ; ES:DI -> Bitmap data
\r
473 stosw ; Al = B.M. width (bytes) AH = B.M.
\r
475 xor ah,ah ; LineInc = bytes to the begin.
\r
476 sub bx,ax ; of bitmaps next row on screen
\r
479 ; Self Modifying, Shame, shame shame..
\r
480 and cx,0003h ; mask X coord giving plane of 1st
\r
481 ; bitmap pixel(zero CH coincidentally)
\r
482 mov ah,11h ; Init. mask for VGA plane selection
\r
483 shl ah,cl ; Shift for starting pixel plane
\r
484 mov dx,GC_INDEX ; Prepare VGA for cpu to video reads
\r
488 mov [Plane],4 ; Set plane counter (BH) to 4
\r
497 rep movsw ; Copy a complete row for curr plane
\r
500 add si,[LineInc] ; Move to next row
\r
501 dec bl ; decrement row counter
\r
502 jnz @@RowLoop ; Jump if more rows left
\r
503 pop si ; Restore bitmaps start dest byte
\r
505 inc al ; Select next plane to read from
\r
508 rol ah,1 ; Shift mask for next plane
\r
509 adc si,0 ; If wrapped increment dest address
\r
510 dec [Plane] ; Decrement plane counter
\r
511 jnz @@PlaneLoop ; Jump if more planes left
\r
513 pop ds ; restore data segment
\r
514 pop di ; restore registers
\r
516 mov sp,bp ; dealloc local variables
\r
528 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word
\r
529 LOCAL Plane:byte,BMHeight:byte,LineInc:word,Columns:byte=LocalStk
\r
532 sub sp,LocalStk ; Create space for local variables
\r
539 mov ax,[Y] ; Calculate dest screen row
\r
540 mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
541 mul bx ; width then adding screen offset
\r
542 mov di,[ScrnOffs] ; store result in DI
\r
544 mov cx,[X] ; Load X coord into CX and make a
\r
545 mov dx,cx ; copy in DX
\r
546 shr dx,2 ; Find starting byte in dest row
\r
547 add di,dx ; add to DI giving screen offset of
\r
548 ; first pixel's byte
\r
549 lds si,[Bitmap] ; DS:SI -> Bitmap data
\r
550 lodsw ; Al = B.M. width (bytes) AH = B.M.
\r
555 mov [BMHeight],ah ; Save source bitmap dimensions
\r
556 xor ah,ah ; LineInc = bytes to the begin.
\r
557 add bx,ax ; of bitmaps next row on screen
\r
559 mov [Columns],al ; Use bh as column loop count
\r
560 and cx,0003h ; mask X coord giving plane of 1st
\r
561 ; bitmap pixel(zero CH coincidentally)
\r
562 mov ah,11h ; Init. mask for VGA plane selection
\r
563 shl ah,cl ; Shift for starting pixel plane
\r
565 mov dx,SC_INDEX ; Prepare VGA for cpu to video writes
\r
569 mov [Plane],4 ; Set plane counter to 4
\r
571 push di ; Save bitmap's start dest. offset
\r
572 mov bl,[BMHeight] ; Reset row counter (BL)
\r
574 out dx,al ; set vga write plane
\r
576 mov cl,[Columns] ; Reset Column counter cl
\r
583 lodsw ; Get next source bitmap byte
\r
587 loop @@ColLoop ; loop if more columns left
\r
589 add di,[LineInc] ; Move to next row
\r
590 dec bl ; decrement row counter
\r
591 jnz @@RowLoop ; Jump if more rows left
\r
592 pop di ; Restore bitmaps start dest byte
\r
593 ror bh,1 ; Shift mask for next plane
\r
594 sbb di,0 ; If wrapped increment dest address
\r
595 dec [Plane] ; Decrement plane counter
\r
596 jnz @@PlaneLoop ; Jump if more planes left
\r
598 pop ds ; restore data segment
\r
599 pop di ; restore registers
\r
601 mov sp,bp ; dealloc local variables
\r