home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------
- ; MODULE XVBITMAP
- ;
- ; Video Bitmap functions - Video Ram <-> Video Ram
- ;
- ; Compile with Tasm.
- ; C callable.
- ;
- ;
- ; ****** XLIB - Mode X graphics library ****************
- ; ****** ****************
- ; ****** Written By Themie Gouthas ****************
- ;
- ; egg@dstos3.dsto.gov.au
- ; teg@bart.dsto.gov.au
- ;-----------------------------------------------------------------------
- COMMENT $
-
- The XVBITMAP module implements yet another type of bitmap to complement
- planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder car is
- analagous to planar bitmaps, that is thrifty on memory consumption but low
- performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers
- that really fly, then VRAM based bitmaps are the 6 cylinder modest performers
- with acceptable memory consumption.
-
- To summarise their selling points, VBM's are moderately fast with fair memory
- consumption, and unlike compiled bitmaps, can be clipped. The disadvantages
- are that they are limited by the amount of free video ram and have a complex
- structure.
-
- The VRAM bitmap format is rather complex consisting of components stored in
- video ram and components in system ram working together. This complexity
- necessitates the existence of a creation function "x_make_vbm" which takes
- an input linear bitmap and generates the equivalent VBM (VRAM Bit Map).
-
- VBM structure:
-
- WORD 0 Size Total size of this VBM structure in bytes
- WORD 1 ImageWidth Width in bytes of the image (for all alignments)
- WORD 2 ImageHeight Height in scan lines of the image
-
- WORD 3 Alignment 0 ImagePtr Offset in VidRAM of this aligned image
- +--WORD 4 MaskPtr Offset (within this structure's DS) of
- | . alignment masks
- | .
- | .
- | WORD 9 Alignment 3 ImagePtr Offset in VidRAM of this aligned image
- +|--WORD 10 MaskPtr Offset (within this structure's DS) of
- || alignment masks
- ||
- |+->BYTE 21 (WORD 11) -------+-- Image masks for alignment 0
- | . |
- | . |
- | BYTE 21 + ImageWidth*ImageHeight -----+
- |
- | .
- | . (similaly for alignments 1 - 2 )
- | .
- |
- +-->BYTE 21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3
- . |
- . |
- BYTE 21 + 4*(ImageWidth*ImageHeight) --+
-
- .
- .
- << Similarly for alignments 2 and 3 >>
- .
- .
- BYTE 21 + 4*(ImageWidth*ImageHeight)
- -------------
-
- (And dont forget the corresponding data in video ram)
-
- $
-
-
- include xlib.inc
- include xvbitmap.inc
-
- VBM_info_struc struc
- Size dw ?
- ImageWidth dw ?
- ImageHeight dw ?
- ; AlignData dw ?
- VBM_info_struc ends
-
- AlignData equ 6
-
- VBM_alignment_struc struc
- ImagePtr dw ?
- MaskPtr dw ?
- VBM_alignment_struc ends
-
-
- .code
-
-
- ;----------------------------------------------------------------------
- ; x_store_vbm_image
- ;
- ; Store the linear bitmap in video RAM using the specified alignment and
- ; start address. Returns number video ram bytes used.
- ;
- ; THIS FUNCTION IS FOR USE BY x_make_masked_vbm
- ;
- ; Prototype:
- ;
- ; x_store_vbm_image(unsigned int vramoffs, unsigned int Align,
- ; char far *lbm);
- ;
- ;
- ; Written by Themie Gouthas
- ;----------------------------------------------------------------------
- _x_store_vbm_image proc
- ARG VramOffs:word,Align:word,LBitmap:dword
- LOCAL BMWidth:byte=LocalStk
- push bp
- mov bp,sp
- sub sp,LocalStk ; Create space for local variables
- push si
- push di
- push ds
- cld
-
- mov ax,SCREEN_SEG ; Point ES to screen segment
- mov es,ax
- mov di,[VramOffs] ; Point ES:DI to VRAM dest start
- mov bx,[Align] ; Set BL to first pixel plane align
- and bl,03h
-
- lds si,[LBitmap] ; DS:SI -> source linear Bitmap
- lodsw ; Al = B.M. width (bytes) AH = B.M.
- mov bh,ah ; Save source bitmap dimensions
- mov [BMWidth],al ;
-
- mov dx,SC_INDEX ; Initialize Map Mask for plane
- mov al,MAP_MASK ; selection
- out dx,al
- inc dx
- xor ch,ch ; clear CH
- @@RowLoop:
- mov cl,bl ; Set initial plane for current
- mov ah,11h ; allignment
- shl ah,cl
-
- mov cl,[BMWidth] ; Initialize column counter
- @@ColLoop:
- mov al,ah
- out dx,al ; set vga write plane
- lodsb ; load next LBM pixel
- mov es:[di],al ; store it in Video Ram
- shl ah,1 ; rotate plane mask
- jnb @@NoAddrIncr ; Time to increment dest address ?
- inc di ; Yes: increment addr and reset
- mov ah,11h ; plane mask to plane 0
- @@NoAddrIncr:
- loop @@ColLoop ; Loop to next pixel column
- cmp ah,11h
- ; je @@skip
- inc di ; Increment dest addr
- ;@@skip:
- dec bh ; Decrement row counter
- jnz @@RowLoop ; Jump if more rows to go
- mov ax,di ; calculate video RAM consumed and
- sub ax,[VramOffs] ; return value
-
- pop ds ; restore data segment
- pop di ; restore registers
- pop si
- mov sp,bp ; dealloc local variables
- pop bp
- ret
- _x_store_vbm_image endp
-
-
- _x_put_masked_vbm proc
- ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword
- LOCAL VBMWidth:word,VBMHeight:word,NextLineIncr:word=LocalStk
- push bp
- mov bp,sp
- sub sp,LocalStk ; Create space for local variables
- push si
- push di
- push ds
- cld
-
- mov ax,SCREEN_SEG ; Point es to VGA segment
- mov es,ax
- mov ax,[Y] ; Calculate dest screen row
- mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
- mul cx ; width then adding screen offset
-
- mov di,[ScrnOffs] ; store result in DI
- add di,ax
- mov si,[X] ; Load X coord into CX and make a
- mov bx,si ; copy in DX
- shr bx,2 ; Find starting byte in dest row
- add di,bx ; add to DI giving screen offset of
- ; first pixel's byte
-
- and si,3 ; get pixel alignment in si
-
- lds bx,[SrcVBM] ; DS:BX -> VBM data structure
- shl si,2 ; si = offset of data for curr
- ; alignment
-
- mov ax,word ptr [bx+ImageHeight] ; Get image height
- mov [VBMHeight],ax
- mov ax,word ptr [bx+ImageWidth] ; Get image width
- mov [VBMWidth],ax
-
- sub cx,ax ; NextLineIncr = bytes to the begin.
- mov [NextLineIncr],cx ; of bitmaps next row on screen
- mov dx,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data
- mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
- mov si,dx
-
- mov dx,GC_INDEX ; Set bit mask for all bits from
- mov ax,BIT_MASK ; VGA latches and none from CPU
- out dx,ax
-
- mov dx,SC_INDEX ; Point SC register to map mask
- mov al,MAP_MASK ; in preperation for masking data
- out dx,al
- inc dx ; Point dx to SC data register
- mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter
-
- @@RowLoop:
- mov cx,[VBMWidth] ; Width in bytes across
-
- @@ColumnLoop:
- lodsb
- out dx,al
- mov al,es:[bx] ; load latches from source bitmap
- stosb ; store latches to dest. bitmap
- inc bx
- loop @@ColumnLoop
-
- add di,[NextLineIncr] ; point to start of next dest row
- dec ah ; decrement scan line counter
- jnz @@RowLoop ; jump if more scanlines left
-
- mov dx,GC_INDEX+1 ; Restore bitmask to the default -
- mov al,0ffh ; all data from cpu
- out dx,al
-
- pop ds ; restore data segment
- pop di ; restore registers
- pop si
- mov sp,bp ; dealloc local variables
- pop bp
- ret
- _x_put_masked_vbm endp
-
-
- _x_put_masked_vbm_clipx proc
- ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword
- LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,NextLineIncr:word=LocalStk
- push bp
- mov bp,sp
- sub sp,LocalStk ; Create space for local variables
- push si
- push di
- push ds
- cld
-
- mov di,[X] ; load X coord int DI and make a
- mov si,di ; copy in SI
- shr di,2 ; Find Byte offset of X coord
-
- and si,3 ; Calculate pixels plane alignment
- shl si,2 ; Prepare to lookup mask & data
- les bx,[SrcVBM] ; ES:BX -> begining of VBM data
-
- mov cx,es:[bx+ImageWidth] ; Get image width and save in CX
-
-
-
- ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
-
- mov dx,[_LeftClip]
- sub dx,di
- jle @@NotLeftClip
- cmp dx,cx
- jnl @@NotVisible
- add di,dx
- mov [LeftSkip],dx
- mov [DataInc],dx
- sub cx,dx
- jmp short @@HorizClipDone
-
- ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
-
- @@NotVisible:
- pop ds ; restore data segment
- pop di ; restore registers
- pop si
- mov sp,bp ; dealloc local variables
- pop bp
- ret
-
- ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
-
- @@NotLeftClip:
- mov dx,[_RightClip]
- sub dx,di
- js @@NotVisible
- mov [LeftSkip],0
- mov [DataInc],0
- cmp dx,cx
- jg @@HorizClipDone
- inc dx
- sub cx,dx
- mov [DataInc],cx
- mov cx,dx
-
- @@HorizClipDone:
-
-
- add di,[ScrnOffs] ; Add the current page offset
- mov [VBMWidth],cx
- mov ax,es:[bx+ImageHeight] ; Get image height and save in AX
- mov [VBMHeight],ax
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- mov ax,[Y] ; Calculate dest screen row
- mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
- mul cx ; width then adding screen offset
- add di,ax ; Add Dest Screen Row to di
- sub cx,[VBMWidth]
- mov [NextLineIncr],cx
-
- mov ax,es ; copy ES to DS
- mov ds,ax
- mov ax,SCREEN_SEG ; Point es to VGA segment
- mov es,ax
-
- mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data
- mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
- mov si,ax
-
- mov ax,[LeftSkip] ; Skip data/mask bytes in
- add bx,ax ; each row that have been clipped
- add si,ax ; by the L.H.S border
-
-
- mov dx,GC_INDEX ; Set bit mask for all bits from
- mov ax,BIT_MASK ; VGA latches and none from CPU
- out dx,ax
- mov dx,SC_INDEX ; Point SC register to map mask
- mov al,MAP_MASK ; in preperation for masking data
- out dx,al
- inc dx ; Point dx to SC data register
- mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter
-
- @@RowLoop:
- mov cx,[VBMWidth] ; Width in bytes across
-
- @@ColumnLoop:
- lodsb
- out dx,al
- mov al,es:[bx] ; load latches from source bitmap
- stosb ; store latches to dest. bitmap
- inc bx
- loop @@ColumnLoop
- add bx,[DataInc]
- add si,[DataInc]
- add di,[NextLineIncr] ; point to start of next dest row
- dec byte ptr ah ; decrement scan line counter
- jnz @@RowLoop ; jump if more scanlines left
-
- mov dx,GC_INDEX+1 ; Restore bitmask to the default -
- mov al,0ffh ; all data from cpu
- out dx,al
-
- pop ds ; restore data segment
- pop di ; restore registers
- pop si
- mov sp,bp ; dealloc local variables
- pop bp
- ret
- _x_put_masked_vbm_clipx endp
-
-
- _x_put_masked_vbm_clipy proc
- ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword
- LOCAL VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk
- push bp
- mov bp,sp
- sub sp,LocalStk ; Create space for local variables
- push si
- push di
- push ds
- cld
-
- mov di,[X] ; load X coord int DI and make a
- mov si,di ; copy in SI
-
-
- and si,3 ; Calculate pixels plane alignment
- shl si,2 ; Prepare to lookup mask & data
- les bx,[SrcVBM] ; ES:BX -> begining of VBM data
-
-
- mov ax,es:[bx+ImageHeight] ; Get image height and save in AX
-
-
-
- ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
-
- mov dx,[_TopClip] ; Compare u.l. Y coord with Top
- sub dx,[Y] ; clipping border
- jle @@NotTopClip ; jump if VBM not clipped from above
- cmp dx,ax
- jnl @@NotVisible ; jump if VBM is completely obscured
- mov [TopRow],dx
- sub ax,dx
- add [Y],dx
- jmp short @@VertClipDone
-
- ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
-
- @@NotVisible:
- pop ds ; restore data segment
- pop di ; restore registers
- pop si
- mov sp,bp ; dealloc local variables
- pop bp
- ret
-
- ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
-
- @@NotTopClip:
- mov dx,[_BottomClip]
- sub dx,[Y]
- js @@NotVisible
- mov [TopRow],0
- cmp dx,ax
- jg @@VertClipDone
- inc dx
- mov ax,dx
-
- @@VertClipDone:
-
-
- shr di,2 ; Find Byte offset of X coord
- add di,[ScrnOffs] ; Add the current page offset
- mov cx,es:[bx+ImageWidth] ; Get image width and save in CX
- mov [VBMWidth],cx
- mov [VBMHeight],ax
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- mov ax,[Y] ; Calculate dest screen row
- mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
- mul cx ; width then adding screen offset
- add di,ax ; Add Dest Screen Row to di
- sub cx,[VBMWidth]
- mov [NextLineIncr],cx
-
- mov ax,es ; copy ES to DS
- mov ds,ax
- mov ax,SCREEN_SEG ; Point es to VGA segment
- mov es,ax
-
- mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data
- mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
- mov si,ax
-
-
-
- mov ax,[VBMWidth] ; Increment DS:BX and DS:SI to
- mul [TopRow] ; skip image/mask data that has
- add bx,ax ; been clipped by the top border
- add si,ax
-
-
- mov dx,GC_INDEX ; Set bit mask for all bits from
- mov ax,BIT_MASK ; VGA latches and none from CPU
- out dx,ax
- mov dx,SC_INDEX ; Point SC register to map mask
- mov al,MAP_MASK ; in preperation for masking data
- out dx,al
- inc dx ; Point dx to SC data register
- mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter
-
- @@RowLoop:
- mov cx,[VBMWidth] ; Width in bytes across
-
- @@ColumnLoop:
- lodsb
- out dx,al
- mov al,es:[bx] ; load latches from source bitmap
- stosb ; store latches to dest. bitmap
- inc bx
- loop @@ColumnLoop
- add di,[NextLineIncr] ; point to start of next dest row
- dec byte ptr ah ; decrement scan line counter
- jnz @@RowLoop ; jump if more scanlines left
-
- mov dx,GC_INDEX+1 ; Restore bitmask to the default -
- mov al,0ffh ; all data from cpu
- out dx,al
-
- pop ds ; restore data segment
- pop di ; restore registers
- pop si
- mov sp,bp ; dealloc local variables
- pop bp
- ret
- _x_put_masked_vbm_clipy endp
-
- _x_put_masked_vbm_clipxy proc
- ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword
- LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk
- push bp
- mov bp,sp
- sub sp,LocalStk ; Create space for local variables
- push si
- push di
- push ds
- cld
-
- mov di,[X] ; load X coord int DI and make a
- mov si,di ; copy in SI
- shr di,2 ; Find Byte offset of X coord
-
- and si,3 ; Calculate pixels plane alignment
- shl si,2 ; Prepare to lookup mask & data
- les bx,[SrcVBM] ; ES:BX -> begining of VBM data
-
- mov cx,es:[bx+ImageWidth] ; Get image width and save in CX
- mov ax,es:[bx+ImageHeight] ; Get image height and save in AX
-
-
-
- ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
-
- mov dx,[_TopClip] ; Compare u.l. Y coord with Top
- sub dx,[Y] ; clipping border
- jle @@NotTopClip ; jump if VBM not clipped from above
- cmp dx,ax
- jnl @@NotVisible ; jump if VBM is completely obscured
- mov [TopRow],dx
- sub ax,dx
- add [Y],dx
- jmp short @@VertClipDone
-
- ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
-
- @@NotVisible:
- pop ds ; restore data segment
- pop di ; restore registers
- pop si
- mov sp,bp ; dealloc local variables
- pop bp
- ret
-
- ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
-
- @@NotTopClip:
- mov dx,[_BottomClip]
- sub dx,[Y]
- js @@NotVisible
- mov [TopRow],0
- cmp dx,ax
- jg @@VertClipDone
- inc dx
- mov ax,dx
-
- @@VertClipDone:
-
- ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
-
- mov dx,[_LeftClip]
- sub dx,di
- jle @@NotLeftClip
- cmp dx,cx
- jnl @@NotVisible
- add di,dx
- mov [LeftSkip],dx
- mov [DataInc],dx
- sub cx,dx
- jmp short @@HorizClipDone
-
- ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
-
- @@NotLeftClip:
- mov dx,[_RightClip]
- sub dx,di
- js @@NotVisible
- mov [LeftSkip],0
- mov [DataInc],0
- cmp dx,cx
- jg @@HorizClipDone
- inc dx
- sub cx,dx
- mov [DataInc],cx
- mov cx,dx
-
- @@HorizClipDone:
-
- add di,[ScrnOffs] ; Add the current page offset
- mov [VBMWidth],cx
- mov [VBMHeight],ax
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- mov ax,[Y] ; Calculate dest screen row
- mov cx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen
- mul cx ; width then adding screen offset
- add di,ax ; Add Dest Screen Row to di
- sub cx,[VBMWidth]
- mov [NextLineIncr],cx
-
- mov ax,es ; copy ES to DS
- mov ds,ax
- mov ax,SCREEN_SEG ; Point es to VGA segment
- mov es,ax
-
- mov ax,[bx+MaskPtr+AlignData+si] ; DS:SI -> mask data
- mov bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
- mov si,ax
-
-
-
- mov ax,[VBMWidth] ; Increment DS:BX and DS:SI to
- add ax,[DataInc] ; skip image/mask data that has
- mul [TopRow] ; been clipped by the top border
- add ax,[LeftSkip] ; Skip also data/mask bytes in
- add bx,ax ; each row that have been clipped
- add si,ax ; by the L.H.S border
-
-
- mov dx,GC_INDEX ; Set bit mask for all bits from
- mov ax,BIT_MASK ; VGA latches and none from CPU
- out dx,ax
- mov dx,SC_INDEX ; Point SC register to map mask
- mov al,MAP_MASK ; in preperation for masking data
- out dx,al
- inc dx ; Point dx to SC data register
- mov ah,byte ptr [VBMHeight] ; AH = Scanline loop counter
-
- @@RowLoop:
- mov cx,[VBMWidth] ; Width in bytes across
-
- @@ColumnLoop:
- lodsb
- out dx,al
- mov al,es:[bx] ; load latches from source bitmap
- stosb ; store latches to dest. bitmap
- inc bx
- loop @@ColumnLoop
- add bx,[DataInc]
- add si,[DataInc]
- add di,[NextLineIncr] ; point to start of next dest row
- dec byte ptr ah ; decrement scan line counter
- jnz @@RowLoop ; jump if more scanlines left
-
- mov dx,GC_INDEX+1 ; Restore bitmask to the default -
- mov al,0ffh ; all data from cpu
- out dx,al
-
- pop ds ; restore data segment
- pop di ; restore registers
- pop si
- mov sp,bp ; dealloc local variables
- pop bp
- ret
- _x_put_masked_vbm_clipxy endp
-
-
- end
-