X-Git-Url: http://4ch.mooo.com/gitweb/?a=blobdiff_plain;f=16%2Fxlib%2Fxpbitmap.asm;fp=16%2Fxlib%2Fxpbitmap.asm;h=e0a2d961bcecd4641df08d1412dc2b5d0f4d2236;hb=47cdc66151d973d975d0e31fb8a786eb639bebdb;hp=0000000000000000000000000000000000000000;hpb=4b23f27092a9470a741e3a18261ad389fd1929db;p=16.git diff --git a/16/xlib/xpbitmap.asm b/16/xlib/xpbitmap.asm new file mode 100755 index 00000000..e0a2d961 --- /dev/null +++ b/16/xlib/xpbitmap.asm @@ -0,0 +1,603 @@ +;----------------------------------------------------------------------- +; MODULE XPBITMAP +; +; Planar Bitmap functions - System 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 $ + + This module implements a set of functions to operate on planar bitmaps. + Planar bitmaps as used by these functions have the following structure: + + BYTE 0 The bitmap width in bytes (4 pixel groups) range 1..255 + BYTE 1 The bitmap height in rows range 1..255 + BYTE 2..n1 The plane 0 pixels width*height bytes + BYTE n1..n2 The plane 1 pixels width*height bytes + BYTE n2..n3 The plane 2 pixels width*height bytes + BYTE n3..n4 The plane 3 pixels width*height bytes + + These functions provide the fastest possible bitmap blts from system ram to + to video and further, the single bitmap is applicable to all pixel + allignments. The masked functions do not need separate masks since all non + zero pixels are considered to be masking pixels, hence if a pixel is 0 the + corresponding screen destination pixel is left unchanged. + + +$ + +include xlib.inc +include xpbitmap.inc +LOCALS + .code + +;---------------------------------------------------------------------- +; x_flip_masked_pbm - mask write a planar bitmap from system ram to video ram +; all zero source bitmap bytes indicate destination byte to be left unchanged +; If "Orientation" is set then the bitmap is flipped from left to right as +; it is drawn +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_flip_masked_pbm(X,Y,ScrnOffs,char far * Bitmap, Orientation) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_flip_masked_pbm proc + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word + LOCAL Plane:byte,BMHeight:byte,LineInc: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 + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height + cmp Orientation,0 + jz UnFlippedMasked + + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + add bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al ; Use bh as column loop count + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,[BMHeight] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl +@@ColLoop: + lodsb ; Get next source bitmap byte + or al,al ; If not zero then write to dest. + jz @@NoPixel ; otherwise skip to next byte + mov es:[di],al +@@NoPixel: + dec di + loop @@ColLoop ; loop if more columns left + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + ror ah,1 ; Shift mask for next plane + sbb di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_flip_masked_pbm endp + + +;---------------------------------------------------------------------- +; x_put_masked_pbm - mask write a planar bitmap from system ram to video ram +; all zero source bitmap bytes indicate destination byte to be left unchanged +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_put_masked_pbm(X,Y,ScrnOffs,char far * Bitmap) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_put_masked_pbm proc + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword + LOCAL Plane:byte,BMHeight:byte,LineInc: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 + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height +UnFlippedMasked: + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + sub bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al ; Use bh as column loop count + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,[BMHeight] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl +@@ColLoop: + lodsb ; Get next source bitmap byte + or al,al ; If not zero then write to dest. + jz @@NoPixel ; otherwise skip to next byte + mov es:[di],al +@@NoPixel: + inc di + loop @@ColLoop ; loop if more columns left + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + adc di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_masked_pbm endp + + + +;---------------------------------------------------------------------- +; x_put_pbm - Write a planar bitmap from system ram to video ram +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_put_pbm(X,Y,ScrnOffs,char far * Bitmap) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; FEATURES : Automatically selects REP MOVSB or REP MOVSW depending on +; source bitmap width, by modifying opcode ;-). +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- + + +_x_put_pbm proc + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword + LOCAL Plane:byte,BMHeight:byte,LineInc: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 + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height +UnFlipped: + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + sub bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al + ; Self Modifying, Shame, shame shame.. + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di + mov bl,[BMHeight] + mov al,ah + out dx,al +@@RowLoop: + mov cl,bh + shr cl,1 + rep movsw ; Copy a complete row for curr plane + adc cl,0 + rep movsb + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + rol ah,1 ; Shift mask for next plane + adc di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_put_pbm endp + +;---------------------------------------------------------------------- +; x_flip_pbm - Write a planar bitmap from system ram to video ram +; If "Orientation" is set then the bitmap is flipped from left to right as +; it is drawn + +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_flip_pbm(X,Y,ScrnOffs,char far * Bitmap, WORD orientation) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; +; NOTES: The flipped put function is slower than the standard put function +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_flip_pbm proc + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word + LOCAL Plane:byte,BMHeight:byte,LineInc: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 + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height + cmp Orientation,0 + jz UnFlipped + + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + add bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al ; Use bh as column loop count + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,[BMHeight] ; Reset row counter (BL) + mov al,ah + out dx,al ; set vga write plane +@@RowLoop: + mov cl,bh ; Reset Column counter cl +@@ColLoop: + lodsb + mov es:[di],al + dec di + sub di,2 + loop @@ColLoop ; loop if more columns left +@@DoneCol: + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + ror ah,1 ; Shift mask for next plane + sbb di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_flip_pbm endp + + +;---------------------------------------------------------------------- +; x_get_pbm - Read a planar bitmap to system ram from video ram +; +; Source Bitmap structure: +; +; Width:byte, Height:byte, Bitmap data (plane 0)...Bitmap data (plane 1).., +; Bitmap data (plane 2)..,Bitmap data (plane 3).. +; +; note width is in bytes ie lots of 4 pixels +; +; x_get_pbm(X,Y,BMwidth,BMheight,ScrnOffs,char far * Bitmap) +; +; +; LIMITATIONS: No clipping is supported +; Only supports bitmaps with widths which are a multiple of +; 4 pixels +; FEATURES : Automatically selects REP MOVSB or REP MOVSW depending on +; source bitmap width, by modifying opcode ;-). +; +; Written by Themie Gouthas +;---------------------------------------------------------------------- +_x_get_pbm proc + ARG X:word,Y:word,SrcWidth:byte,SrcHeight:byte,ScrnOffs:word,Bitmap:dword + LOCAL Plane:byte,LineInc:word=LocalStk + push bp + mov bp,sp + sub sp,LocalStk ; Create space for local variables + push si + push di + push ds + cld + + mov ax,[Y] ; Calculate screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. Y coord by Screen + mul bx ; width then adding screen offset + mov si,[ScrnOffs] ; store result in SI + add si,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in screen row + add si,dx ; add to SI giving screen offset of + ; first pixel's byte + mov ax,SCREEN_SEG + mov ds,ax + les di,[Bitmap] ; ES:DI -> Bitmap data + mov al,[SrcWidth] + mov ah,[SrcHeight] + stosw ; Al = B.M. width (bytes) AH = B.M. + ; height + xor ah,ah ; LineInc = bytes to the begin. + sub bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov bh,al + ; Self Modifying, Shame, shame shame.. + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov dx,GC_INDEX ; Prepare VGA for cpu to video reads + mov al,READ_MAP + out dx,al + inc dx + mov [Plane],4 ; Set plane counter (BH) to 4 + mov al,cl +@@PlaneLoop: + push si + mov bl,[SrcHeight] + out dx,al +@@RowLoop: + mov cl,bh + shr cl,1 + rep movsw ; Copy a complete row for curr plane + adc cl,0 + rep movsb + add si,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop si ; Restore bitmaps start dest byte + + inc al ; Select next plane to read from + and al,3 ; + + rol ah,1 ; Shift mask for next plane + adc si,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret +_x_get_pbm endp + + + + + end + + + + ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word + LOCAL Plane:byte,BMHeight:byte,LineInc:word,Columns: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 + mov es,ax + mov ax,[Y] ; Calculate dest screen row + mov bx,[_ScrnLogicalByteWidth] ; by mult. dest Y coord by Screen + mul bx ; width then adding screen offset + mov di,[ScrnOffs] ; store result in DI + add di,ax + mov cx,[X] ; Load X coord into CX and make a + mov dx,cx ; copy in DX + shr dx,2 ; Find starting byte in dest row + add di,dx ; add to DI giving screen offset of + ; first pixel's byte + lds si,[Bitmap] ; DS:SI -> Bitmap data + lodsw ; Al = B.M. width (bytes) AH = B.M. + ; height + cmp Orientation,0 + jz UnFlipped + + mov [BMHeight],ah ; Save source bitmap dimensions + xor ah,ah ; LineInc = bytes to the begin. + add bx,ax ; of bitmaps next row on screen + mov [LineInc],bx + mov [Columns],al ; Use bh as column loop count + and cx,0003h ; mask X coord giving plane of 1st + ; bitmap pixel(zero CH coincidentally) + mov ah,11h ; Init. mask for VGA plane selection + shl ah,cl ; Shift for starting pixel plane + mov bh,ah + mov dx,SC_INDEX ; Prepare VGA for cpu to video writes + mov al,MAP_MASK + out dx,al + inc dx + mov [Plane],4 ; Set plane counter to 4 +@@PlaneLoop: + push di ; Save bitmap's start dest. offset + mov bl,[BMHeight] ; Reset row counter (BL) + mov al,bh + out dx,al ; set vga write plane +@@RowLoop: + mov cl,[Columns] ; Reset Column counter cl + shr cx,1 + jnc @@ColLoop + lodsb + mov es:[di],al + dec di +@@ColLoop: + lodsw ; Get next source bitmap byte + xchg al,ah + mov es:[di],ax + sub di,2 + loop @@ColLoop ; loop if more columns left + + add di,[LineInc] ; Move to next row + dec bl ; decrement row counter + jnz @@RowLoop ; Jump if more rows left + pop di ; Restore bitmaps start dest byte + ror bh,1 ; Shift mask for next plane + sbb di,0 ; If wrapped increment dest address + dec [Plane] ; Decrement plane counter + jnz @@PlaneLoop ; Jump if more planes left + + pop ds ; restore data segment + pop di ; restore registers + pop si + mov sp,bp ; dealloc local variables + pop bp + ret \ No newline at end of file