1 ;-----------------------------------------------------------------------
\r
4 ; Video Bitmap functions - Video 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
19 The XVBITMAP module implements yet another type of bitmap to complement
\r
20 planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder car is
\r
21 analagous to planar bitmaps, that is thrifty on memory consumption but low
\r
22 performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers
\r
23 that really fly, then VRAM based bitmaps are the 6 cylinder modest performers
\r
24 with acceptable memory consumption.
\r
26 To summarise their selling points, VBM's are moderately fast with fair memory
\r
27 consumption, and unlike compiled bitmaps, can be clipped. The disadvantages
\r
28 are that they are limited by the amount of free video ram and have a complex
\r
31 The VRAM bitmap format is rather complex consisting of components stored in
\r
32 video ram and components in system ram working together. This complexity
\r
33 necessitates the existence of a creation function "x_make_vbm" which takes
\r
34 an input linear bitmap and generates the equivalent VBM (VRAM Bit Map).
\r
38 WORD 0 Size Total size of this VBM structure in bytes
\r
39 WORD 1 ImageWidth Width in bytes of the image (for all alignments)
\r
40 WORD 2 ImageHeight Height in scan lines of the image
\r
42 WORD 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image
\r
43 +--WORD 4 MaskPtr Offset (within this structure's DS) of
\r
47 | WORD 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image
\r
48 +|--WORD 10 MaskPtr Offset (within this structure's DS) of
\r
51 |+->BYTE 21 (WORD 11) -------+-- Image masks for alignment 0
\r
54 | BYTE 21 + ImageWidth*ImageHeight -----+
\r
57 | . (similaly for alignments 1 - 2 )
\r
60 +-->BYTE 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3
\r
63 BYTE 21 + 4*(ImageWidth*ImageHeight) --+
\r
67 << Similarly for alignments 2 and 3 >>
\r
70 BYTE 21 + 4*(ImageWidth*ImageHeight)
\r
73 (And dont forget the corresponding data in video ram)
\r
79 include xvbitmap.inc
\r
81 VBM_info_struc struc
\r
90 VBM_alignment_struc struc
\r
93 VBM_alignment_struc ends
\r
99 ;----------------------------------------------------------------------
\r
100 ; x_store_vbm_image
\r
102 ; Store the linear bitmap in video RAM using the specified alignment and
\r
103 ; start address. Returns number video ram bytes used.
\r
105 ; THIS FUNCTION IS FOR USE BY x_make_masked_vbm
\r
109 ; x_store_vbm_image(unsigned int vramoffs, unsigned int Align,
\r
113 ; Written by Themie Gouthas
\r
114 ;----------------------------------------------------------------------
\r
115 _x_store_vbm_image proc
\r
116 ARG VramOffs:word,Align:word,LBitmap:dword
\r
117 LOCAL BMWidth:byte=LocalStk
\r
120 sub sp,LocalStk ; Create space for local variables
\r
126 mov ax,SCREEN_SEG ; Point ES to screen segment
\r
128 mov di,[VramOffs] ; Point ES:DI to VRAM dest start
\r
129 mov bx,[Align] ; Set BL to first pixel plane align
\r
132 lds si,[LBitmap] ; DS:SI -> source linear Bitmap
\r
133 lodsw ; Al = B.M. width (bytes) AH = B.M.
\r
134 mov bh,ah ; Save source bitmap dimensions
\r
137 mov dx,SC_INDEX ; Initialize Map Mask for plane
\r
138 mov al,MAP_MASK ; selection
\r
141 xor ch,ch ; clear CH
\r
143 mov cl,bl ; Set initial plane for current
\r
144 mov ah,11h ; allignment
\r
147 mov cl,[BMWidth] ; Initialize column counter
\r
150 out dx,al ; set vga write plane
\r
151 lodsb ; load next LBM pixel
\r
152 mov es:[di],al ; store it in Video Ram
\r
153 shl ah,1 ; rotate plane mask
\r
154 jnb @@NoAddrIncr ; Time to increment dest address ?
\r
155 inc di ; Yes: increment addr and reset
\r
156 mov ah,11h ; plane mask to plane 0
\r
158 loop @@ColLoop ; Loop to next pixel column
\r
161 inc di ; Increment dest addr
\r
163 dec bh ; Decrement row counter
\r
164 jnz @@RowLoop ; Jump if more rows to go
\r
165 mov ax,di ; calculate video RAM consumed and
\r
166 sub ax,[VramOffs] ; return value
\r
168 pop ds ; restore data segment
\r
169 pop di ; restore registers
\r
171 mov sp,bp ; dealloc local variables
\r
174 _x_store_vbm_image endp
\r
177 _x_put_masked_vbm proc
\r
178 ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword
\r
179 LOCAL VBMWidth:word,VBMHeight:word,NextLineIncr:word=LocalStk
\r
182 sub sp,LocalStk ; Create space for local variables
\r
188 mov ax,SCREEN_SEG ; Point es to VGA segment
\r
190 mov ax,[Y] ; Calculate dest screen row
\r
191 mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
192 mul cx ; width then adding screen offset
\r
194 mov di,[ScrnOffs] ; store result in DI
\r
196 mov si,[X] ; Load X coord into CX and make a
\r
197 mov bx,si ; copy in DX
\r
198 shr bx,2 ; Find starting byte in dest row
\r
199 add di,bx ; add to DI giving screen offset of
\r
200 ; first pixel's byte
\r
202 and si,3 ; get pixel alignment in si
\r
204 lds bx,[SrcVBM] ; DS:BX -> VBM data structure
\r
205 shl si,2 ; si = offset of data for curr
\r
208 mov ax,word ptr [bx+ImageHeight] ; Get image height
\r
210 mov ax,word ptr [bx+ImageWidth] ; Get image width
\r
213 sub cx,ax ; NextLineIncr = bytes to the begin.
\r
214 mov [NextLineIncr],cx ; of bitmaps next row on screen
\r
215 mov dx,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data
\r
216 mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
\r
219 mov dx,GC_INDEX ; Set bit mask for all bits from
\r
220 mov ax,BIT_MASK ; VGA latches and none from CPU
\r
223 mov dx,SC_INDEX ; Point SC register to map mask
\r
224 mov al,MAP_MASK ; in preperation for masking data
\r
226 inc dx ; Point dx to SC data register
\r
227 mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter
\r
230 mov cx,[VBMWidth] ; Width in bytes across
\r
235 mov al,es:[bx] ; load latches from source bitmap
\r
236 stosb ; store latches to dest. bitmap
\r
240 add di,[NextLineIncr] ; point to start of next dest row
\r
241 dec ah ; decrement scan line counter
\r
242 jnz @@RowLoop ; jump if more scanlines left
\r
244 mov dx,GC_INDEX+1 ; Restore bitmask to the default -
\r
245 mov al,0ffh ; all data from cpu
\r
248 pop ds ; restore data segment
\r
249 pop di ; restore registers
\r
251 mov sp,bp ; dealloc local variables
\r
254 _x_put_masked_vbm endp
\r
257 _x_put_masked_vbm_clipx proc
\r
258 ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword
\r
259 LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,NextLineIncr:word=LocalStk
\r
262 sub sp,LocalStk ; Create space for local variables
\r
268 mov di,[X] ; load X coord int DI and make a
\r
269 mov si,di ; copy in SI
\r
270 sar di,2 ; Find Byte offset of X coord
\r
272 and si,3 ; Calculate pixels plane alignment
\r
273 shl si,2 ; Prepare to lookup mask & data
\r
274 les bx,[SrcVBM] ; ES:BX -> begining of VBM data
\r
276 mov cx,es:[bx+ImageWidth] ; Get image width and save in CX
\r
280 ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
\r
291 jmp short @@HorizClipDone
\r
293 ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
\r
297 pop ds ; restore data segment
\r
298 pop di ; restore registers
\r
300 mov sp,bp ; dealloc local variables
\r
304 ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
\r
307 mov dx,[_RightClip]
\r
313 jge @@HorizClipDone
\r
322 add di,[ScrnOffs] ; Add the current page offset
\r
324 mov ax,es:[bx+ImageHeight] ; Get image height and save in AX
\r
328 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
330 mov ax,[Y] ; Calculate dest screen row
\r
331 mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
332 mul cx ; width then adding screen offset
\r
333 add di,ax ; Add Dest Screen Row to di
\r
335 mov [NextLineIncr],cx
\r
337 mov ax,es ; copy ES to DS
\r
339 mov ax,SCREEN_SEG ; Point es to VGA segment
\r
342 mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data
\r
343 mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
\r
346 mov ax,[LeftSkip] ; Skip data/mask bytes in
\r
347 add bx,ax ; each row that have been clipped
\r
348 add si,ax ; by the L.H.S border
\r
351 mov dx,GC_INDEX ; Set bit mask for all bits from
\r
352 mov ax,BIT_MASK ; VGA latches and none from CPU
\r
354 mov dx,SC_INDEX ; Point SC register to map mask
\r
355 mov al,MAP_MASK ; in preperation for masking data
\r
357 inc dx ; Point dx to SC data register
\r
358 mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter
\r
361 mov cx,[VBMWidth] ; Width in bytes across
\r
366 mov al,es:[bx] ; load latches from source bitmap
\r
367 stosb ; store latches to dest. bitmap
\r
372 add di,[NextLineIncr] ; point to start of next dest row
\r
373 dec byte ptr ah ; decrement scan line counter
\r
374 jnz @@RowLoop ; jump if more scanlines left
\r
376 mov dx,GC_INDEX+1 ; Restore bitmask to the default -
\r
377 mov al,0ffh ; all data from cpu
\r
380 pop ds ; restore data segment
\r
381 pop di ; restore registers
\r
383 mov sp,bp ; dealloc local variables
\r
386 _x_put_masked_vbm_clipx endp
\r
389 _x_put_masked_vbm_clipy proc
\r
390 ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword
\r
391 LOCAL VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk
\r
394 sub sp,LocalStk ; Create space for local variables
\r
400 mov di,[X] ; load X coord int DI and make a
\r
401 mov si,di ; copy in SI
\r
404 and si,3 ; Calculate pixels plane alignment
\r
405 shl si,2 ; Prepare to lookup mask & data
\r
406 les bx,[SrcVBM] ; ES:BX -> begining of VBM data
\r
409 mov ax,es:[bx+ImageHeight] ; Get image height and save in AX
\r
413 ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
\r
415 mov dx,[_TopClip] ; Compare u.l. Y coord with Top
\r
416 sub dx,[Y] ; clipping border
\r
417 jle @@NotTopClip ; jump if VBM not clipped from above
\r
419 jnl @@NotVisible ; jump if VBM is completely obscured
\r
423 jmp short @@VertClipDone
\r
425 ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
\r
429 pop ds ; restore data segment
\r
430 pop di ; restore registers
\r
432 mov sp,bp ; dealloc local variables
\r
436 ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
\r
439 mov dx,[_BottomClip]
\r
451 shr di,2 ; Find Byte offset of X coord
\r
452 add di,[ScrnOffs] ; Add the current page offset
\r
453 mov cx,es:[bx+ImageWidth] ; Get image width and save in CX
\r
457 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
459 mov ax,[Y] ; Calculate dest screen row
\r
460 mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
461 mul cx ; width then adding screen offset
\r
462 add di,ax ; Add Dest Screen Row to di
\r
464 mov [NextLineIncr],cx
\r
466 mov ax,es ; copy ES to DS
\r
468 mov ax,SCREEN_SEG ; Point es to VGA segment
\r
471 mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data
\r
472 mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
\r
477 mov ax,[VBMWidth] ; Increment DS:BX and DS:SI to
\r
478 mul [TopRow] ; skip image/mask data that has
\r
479 add bx,ax ; been clipped by the top border
\r
483 mov dx,GC_INDEX ; Set bit mask for all bits from
\r
484 mov ax,BIT_MASK ; VGA latches and none from CPU
\r
486 mov dx,SC_INDEX ; Point SC register to map mask
\r
487 mov al,MAP_MASK ; in preperation for masking data
\r
489 inc dx ; Point dx to SC data register
\r
490 mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter
\r
493 mov cx,[VBMWidth] ; Width in bytes across
\r
498 mov al,es:[bx] ; load latches from source bitmap
\r
499 stosb ; store latches to dest. bitmap
\r
502 add di,[NextLineIncr] ; point to start of next dest row
\r
503 dec byte ptr ah ; decrement scan line counter
\r
504 jnz @@RowLoop ; jump if more scanlines left
\r
506 mov dx,GC_INDEX+1 ; Restore bitmask to the default -
\r
507 mov al,0ffh ; all data from cpu
\r
511 pop ds ; restore data segment
\r
512 pop di ; restore registers
\r
514 mov sp,bp ; dealloc local variables
\r
517 _x_put_masked_vbm_clipy endp
\r
519 _x_put_masked_vbm_clipxy proc
\r
520 ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword
\r
521 LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk
\r
524 sub sp,LocalStk ; Create space for local variables
\r
530 mov di,[X] ; load X coord int DI and make a
\r
531 mov si,di ; copy in SI
\r
532 sar di,2 ; Find Byte offset of X coord
\r
533 and si,3 ; Calculate pixels plane alignment
\r
534 shl si,2 ; Prepare to lookup mask & data
\r
535 les bx,[SrcVBM] ; ES:BX -> begining of VBM data
\r
537 mov cx,es:[bx+ImageWidth] ; Get image width and save in CX
\r
538 mov ax,es:[bx+ImageHeight] ; Get image height and save in AX
\r
542 ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
\r
544 mov dx,[_TopClip] ; Compare u.l. Y coord with Top
\r
545 sub dx,[Y] ; clipping border
\r
546 jle @@NotTopClip ; jump if VBM not clipped from above
\r
548 jnl @@NotVisible ; jump if VBM is completely obscured
\r
552 jmp short @@VertClipDone
\r
554 ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
\r
558 pop ds ; restore data segment
\r
559 pop di ; restore registers
\r
561 mov sp,bp ; dealloc local variables
\r
565 ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
\r
568 mov dx,[_BottomClip]
\r
579 ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
\r
591 jmp short @@HorizClipDone
\r
593 ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
\r
596 mov dx,[_RightClip]
\r
602 jge @@HorizClipDone
\r
610 add di,[ScrnOffs] ; Add the current page offset
\r
613 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
\r
615 mov ax,[Y] ; Calculate dest screen row
\r
616 mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
\r
617 mul cx ; width then adding screen offset
\r
618 add di,ax ; Add Dest Screen Row to di
\r
620 mov [NextLineIncr],cx
\r
622 mov ax,es ; copy ES to DS
\r
624 mov ax,SCREEN_SEG ; Point es to VGA segment
\r
627 mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data
\r
628 mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
\r
633 mov ax,[VBMWidth] ; Increment DS:BX and DS:SI to
\r
634 add ax,[DataInc] ; skip image/mask data that has
\r
635 mul [TopRow] ; been clipped by the top border
\r
636 add ax,[LeftSkip] ; Skip also data/mask bytes in
\r
637 add bx,ax ; each row that have been clipped
\r
638 add si,ax ; by the L.H.S border
\r
641 mov dx,GC_INDEX ; Set bit mask for all bits from
\r
642 mov ax,BIT_MASK ; VGA latches and none from CPU
\r
644 mov dx,SC_INDEX ; Point SC register to map mask
\r
645 mov al,MAP_MASK ; in preperation for masking data
\r
647 inc dx ; Point dx to SC data register
\r
648 mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter
\r
651 mov cx,[VBMWidth] ; Width in bytes across
\r
656 mov al,es:[bx] ; load latches from source bitmap
\r
657 stosb ; store latches to dest. bitmap
\r
662 add di,[NextLineIncr] ; point to start of next dest row
\r
663 dec byte ptr ah ; decrement scan line counter
\r
664 jnz @@RowLoop ; jump if more scanlines left
\r
666 mov dx,GC_INDEX+1 ; Restore bitmask to the default -
\r
667 mov al,0ffh ; all data from cpu
\r
670 pop ds ; restore data segment
\r
671 pop di ; restore registers
\r
673 mov sp,bp ; dealloc local variables
\r
676 _x_put_masked_vbm_clipxy endp
\r