]> 4ch.mooo.com Git - 16.git/blobdiff - 16/xlib/XCLIPPBM.ASM
added xlib to the project and i gotta convert the damn makefile -.-
[16.git] / 16 / xlib / XCLIPPBM.ASM
diff --git a/16/xlib/XCLIPPBM.ASM b/16/xlib/XCLIPPBM.ASM
new file mode 100755 (executable)
index 0000000..bbe50b5
--- /dev/null
@@ -0,0 +1,507 @@
+;-----------------------------------------------------------------------\r
+; MODULE XCLIPPBM\r
+;\r
+; This module was written by Matthew MacKenzie\r
+; matm@eng.umd.edu\r
+;\r
+; Clipped transfer of planar bitmaps from system memory to video memory.\r
+;\r
+; Compile with TASM.\r
+; C near-callable.\r
+;\r
+; ****** XLIB - Mode X graphics library                ****************\r
+; ******                                               ****************\r
+; ****** Written By Themie Gouthas                     ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+include xlib.inc\r
+include xclippbm.inc\r
+\r
+\r
+       .data\r
+\r
+       align 2\r
+\r
+; global clipping variables\r
+_TopBound       dw      (?)\r
+_BottomBound    dw      (?)\r
+_LeftBound      dw      (?)\r
+_RightBound     dw      (?)\r
+\r
+; VGA plane masks\r
+ColumnMask      db      011h,022h,044h,088h\r
+\r
+; bit delay timers\r
+LeftDelay       db      0, 1, 2, 4\r
+RightDelay      db      0, 4, 2, 1\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_clip_pbm\r
+;\r
+; C near-callable as:\r
+;\r
+; void x_clip_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);\r
+;\r
+; Bitmap is a planar bitmap, in the regular Xlib format.\r
+;\r
+; ax, bx, cx, and dx go south.\r
+\r
+       .code\r
+\r
+       public _x_clip_pbm\r
+       align   2\r
+_x_clip_pbm proc\r
+ARG     X:word, Y:word, ScreenOffs:word, Bitmap:dword\r
+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
+; Tasm 1.0 does not allow the \ line continuation\r
+;LOCAL   left_counter:word, right_counter:word, \\r
+;              column:word, clipped_height:word, clipped_width:word, \\r
+;              screen_pos:word, bitmap_pos:word, bitmap_size:word, \\r
+;              VGA_mask:word, width_copy, height_temp:word, \\r
+;              screen_width:word=LocalStk\r
+\r
+       push bp\r
+       mov bp, sp\r
+       sub sp, LocalStk\r
+       push si\r
+       push di\r
+       push ds\r
+\r
+; sociopathic cases: are the clipping bounds out of order?\r
+       mov ax, _TopBound\r
+       cmp ax, _BottomBound\r
+       jg @@GetOut\r
+       mov ax, _LeftBound\r
+       cmp ax, _RightBound\r
+       jle @@ReasonableAndProper\r
+@@GetOut:                              ; return a 1 -- no image drawn\r
+       pop ds\r
+       pop di\r
+       pop si\r
+       mov ax, 1\r
+       mov sp, bp\r
+       pop bp\r
+       ret\r
+\r
+@@ReasonableAndProper:\r
+\r
+; we need to use both the tables in ds and the height and width of the bitmap\r
+       les si, Bitmap\r
+\r
+; vertical position\r
+       xor cx, cx\r
+       mov cl, byte ptr es:[si + 1] ; height of bitmap\r
+       xor ax, ax\r
+       mov al, byte ptr es:[si] ; width of bitmap\r
+       mul cx\r
+       mov bitmap_size, ax\r
+       mov ax, Y\r
+       cmp ax, _BottomBound ; top edge below clipping box?\r
+       jg @@GetOut\r
+\r
+       mov bx, cx\r
+       add bx, ax\r
+       dec bx              ; bottom edge = Y + height - 1\r
+       cmp bx, _TopBound\r
+       jl @@GetOut\r
+       sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound\r
+       jle @@NoBottomBound\r
+       sub cx, bx          ; clip bottom margin from height\r
+@@NoBottomBound:\r
+       mov bx, _TopBound\r
+       sub bx, ax          ; top margin = TopBound - Y\r
+       jle @@NoTopBound\r
+       add ax, bx          ; top edge = Y + top margin\r
+       sub cx, bx          ; clip top margin from height\r
+       jmp @@KeepMargin\r
+@@NoTopBound:\r
+       xor bx, bx\r
+@@KeepMargin:\r
+       mov clipped_height, cx\r
+\r
+       mul _ScrnLogicalByteWidth\r
+       mov di, ax\r
+       add di, ScreenOffs  ; row of upper-left corner of blit\r
+\r
+       mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height)\r
+       mov ax, cx\r
+       mul bx\r
+       add si, ax\r
+       add si, 2           ; starting position in bitmap\r
+\r
+; horizontal position\r
+       mov width_copy, cx\r
+       mov dx, X\r
+       cmp dx, _RightBound\r
+       jg @@GetOut\r
+       mov dx, 0           ; unclipped value for right delay\r
+\r
+       mov ax, cx\r
+       shl ax, 2           ; width in pixels\r
+       add ax, X\r
+       dec ax              ; right edge = X + width in pixels - 1\r
+       cmp ax, _LeftBound\r
+       jl @@GetOut\r
+       sub ax, _RightBound  ; right margin = right edge - RightBound\r
+       jle @@NoRightBound\r
+       mov bx, ax\r
+       and bx, 3\r
+       mov dl, RightDelay[bx]\r
+       shr ax, 2\r
+       sub cx, ax          ; subtract clipped bytes from width\r
+@@NoRightBound:\r
+       mov right_counter, dx\r
+       mov dx, 0           ; unclipped value for left delay\r
+       mov ax, _LeftBound\r
+       sub ax, X           ; left margin = LeftBound - X\r
+       jle @@NoLeftBound\r
+       mov bx, ax\r
+       and bx, 3\r
+       mov dl, LeftDelay[bx]\r
+       add ax, 3\r
+       shr ax, 2           ; left margin/4, rounded up\r
+       sub cx, ax          ; subtract clipped bytes from width\r
+       add si, ax          ; move starting position in bitmap past margin\r
+       add di, ax          ; move starting position on screen past margin\r
+@@NoLeftBound:\r
+       mov left_counter, dx\r
+       mov clipped_width, cx\r
+\r
+       mov ax, X           ; add x coordinate to screen position\r
+       mov bx, ax\r
+       sar ax, 2\r
+       add di, ax\r
+\r
+       mov dx, SC_INDEX\r
+       mov al, MAP_MASK\r
+       out dx, al\r
+       inc dx\r
+\r
+       and bx, 3           ; initial mask\r
+       xor ax, ax\r
+       mov al, ColumnMask[bx]\r
+       mov VGA_mask, ax\r
+       out dx, al          ; initial mask\r
+\r
+       mov column, 4\r
+       mov bitmap_pos, si\r
+       mov screen_pos, di\r
+       mov ax, _ScrnLogicalByteWidth\r
+       mov screen_width, ax ; since we move ds\r
+\r
+; we've used all our tables, so we can change ds to point to the bitmap,\r
+; and es to point to the screen\r
+       mov ds, word ptr [Bitmap + 2]\r
+       mov ax, SCREEN_SEG\r
+       mov es, ax\r
+\r
+       cld                 ; strings go forward\r
+       mov bx, width_copy\r
+       sub bx, clipped_width ; bytes to advance one line in bitmap\r
+\r
+; let's actually draw something for a change\r
+@@WritePlane:\r
+       mov ax, clipped_height\r
+       mov height_temp, ax\r
+       mov dx, screen_width\r
+       sub dx, clipped_width ; bytes to advance one line across screen\r
+\r
+@@WriteLine:\r
+       mov cx, clipped_width\r
+       shr cx, 1\r
+       rep movsw           ; in they went, two by two...\r
+       adc cx, 0\r
+       rep movsb           ; catch stray last byte, if it's there\r
+       add si, bx          ; advance one bitmap line\r
+       add di, dx          ; advance one screen line\r
+\r
+       dec height_temp\r
+       jnz @@WriteLine\r
+\r
+       dec column\r
+       jz @@OuttaHere      ; only four columns per customer, please\r
+       mov dx, SC_INDEX + 1\r
+       rol byte ptr VGA_mask, 1\r
+       adc screen_pos, 0   ; add to location if we've wrapped to plane 0\r
+       mov al, byte ptr VGA_mask\r
+       out dx, al          ; set VGA for next column\r
+\r
+       shr right_counter, 1\r
+       jnc @@NoRightCounter\r
+       dec clipped_width   ; cut off right edge for later planes\r
+       inc bx\r
+@@NoRightCounter:\r
+       shr left_counter, 1\r
+       jnc @@NoLeftCounter\r
+       inc clipped_width   ; add to left edge for later planes\r
+       dec bx\r
+       dec bitmap_pos\r
+       dec screen_pos\r
+@@NoLeftCounter:\r
+       mov si, bitmap_pos\r
+       add si, bitmap_size\r
+       mov bitmap_pos, si\r
+       mov di, screen_pos\r
+       jmp @@WritePlane\r
+\r
+@@OuttaHere:                   ; return a 0 -- something was inside the boundary\r
+       pop ds\r
+       pop di\r
+       pop si\r
+       mov ax, 0\r
+       mov sp, bp\r
+       pop bp\r
+       ret\r
+_x_clip_pbm endp\r
+\r
+\r
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+; _x_clip_masked_pbm\r
+;\r
+; C near-callable as:\r
+;\r
+; void x_clip_masked_pbm (int X, int Y, int ScreenOffs, char far * Bitmap);\r
+;\r
+; Bitmap is a planar bitmap, in the regular Xlib format.\r
+; The width of the bitmap cannot be greater than 90 bytes, however.\r
+; Ain't that just criminal?\r
+;\r
+; ax, bx, cx, and dx go south.\r
+\r
+\r
+; one branch per pixel is more than enough -- we'll unroll the line-writing\r
+; loop all the way to try to get a little speed (at the expense, as usual,\r
+; of a chunk of memory)\r
+\r
+MaskedPoint macro offset\r
+       mov al, [si + offset]\r
+       or al, al\r
+       jz $+6\r
+       mov es:[di + offset], al\r
+       endm\r
+\r
+MaskedPointSize     equ     11\r
+\r
+       public _x_clip_masked_pbm\r
+       align   2\r
+_x_clip_masked_pbm proc\r
+ARG     X:word, Y:word, ScreenOffs:word, Bitmap:dword\r
+; Tasm 1.0 does not allow the \ line continuation\r
+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
+;LOCAL   left_counter:word, right_counter:word, \\r
+;              column:word, clipped_height:word, \\r
+;              screen_pos:word, bitmap_pos:word, bitmap_size:word, \\r
+;              VGA_mask:word, width_copy, height_temp:word, \\r
+;              screen_width:word=LocalStk\r
+       push bp\r
+       mov bp, sp\r
+       sub sp, LocalStk\r
+       push si\r
+       push di\r
+       push ds\r
+\r
+; sociopathic cases: are the clipping bounds out of order?\r
+       mov ax, _TopBound\r
+       cmp ax, _BottomBound\r
+       jg @@GetOut\r
+       mov ax, _LeftBound\r
+       cmp ax, _RightBound\r
+       jle @@ReasonableAndProper\r
+@@GetOut:                              ; return a 1 -- no image drawn\r
+       pop ds\r
+       pop di\r
+       pop si\r
+       mov ax, 1\r
+       mov sp, bp\r
+       pop bp\r
+       ret\r
+\r
+@@ReasonableAndProper:\r
+\r
+; we need to use both the tables in ds and the height and width of the bitmap\r
+       les si, Bitmap\r
+\r
+; vertical position\r
+       xor cx, cx\r
+       mov cl, byte ptr es:[si + 1] ; height of bitmap\r
+       xor ax, ax\r
+       mov al, byte ptr es:[si] ; width of bitmap\r
+       mul cx\r
+       mov bitmap_size, ax\r
+       mov ax, Y\r
+       cmp ax, _BottomBound ; top edge below clipping box?\r
+       jg @@GetOut\r
+\r
+       mov bx, cx\r
+       add bx, ax\r
+       dec bx              ; bottom edge = Y + height - 1\r
+       cmp bx, _TopBound\r
+       jl @@GetOut\r
+       sub bx, _BottomBound ; bottom margin = bottom edge - BottomBound\r
+       jle @@NoBottomBound\r
+       sub cx, bx          ; clip bottom margin from height\r
+@@NoBottomBound:\r
+       mov bx, _TopBound\r
+       sub bx, ax          ; top margin = TopBound - Y\r
+       jle @@NoTopBound\r
+       add ax, bx          ; top edge = Y + top margin\r
+       sub cx, bx          ; clip top margin from height\r
+       jmp @@KeepMargin\r
+@@NoTopBound:\r
+       xor bx, bx\r
+@@KeepMargin:\r
+       mov clipped_height, cx\r
+\r
+       mul _ScrnLogicalByteWidth\r
+       mov di, ax\r
+       add di, ScreenOffs  ; row of upper-left corner of blit\r
+\r
+       mov cl, byte ptr es:[si] ; width of bitmap (ch is still 0 from height)\r
+       mov ax, cx\r
+       mul bx\r
+       add si, ax\r
+       add si, 2           ; starting position in bitmap\r
+\r
+; horizontal position\r
+       mov width_copy, cx\r
+       mov dx, X\r
+       cmp dx, _RightBound\r
+       jg @@GetOut\r
+       mov dx, 0           ; unclipped value for right delay\r
+\r
+       mov ax, cx\r
+       shl ax, 2           ; width in pixels\r
+       add ax, X\r
+       dec ax              ; right edge = X + width in pixels - 1\r
+       cmp ax, _LeftBound\r
+       jl @@GetOut\r
+       sub ax, _RightBound ; right margin = right edge - RightBound\r
+       jle @@NoRightBound\r
+       mov bx, ax\r
+       and bx, 3\r
+       mov dl, RightDelay[bx]\r
+       shr ax, 2\r
+       sub cx, ax          ; subtract clipped bytes from width\r
+@@NoRightBound:\r
+       mov right_counter, dx\r
+       mov dx, 0           ; unclipped value for left delay\r
+       mov ax, _LeftBound\r
+       sub ax, X           ; left margin = LeftBound - X\r
+       jle @@NoLeftBound\r
+       mov bx, ax\r
+       and bx, 3\r
+       mov dl, LeftDelay[bx]\r
+       add ax, 3\r
+       shr ax, 2           ; left margin/4, rounded up\r
+       sub cx, ax          ; subtract clipped bytes from width\r
+       add si, ax          ; move starting position in bitmap past margin\r
+       add di, ax          ; move starting position on screen past margin\r
+@@NoLeftBound:\r
+       mov left_counter, dx\r
+       mov ax, cx\r
+       imul ax, (-1 * MaskedPointSize)\r
+       add ax, offset @@LineDone + 2\r
+       mov cx, ax          ; jump offset for plotting\r
+\r
+       mov ax, X           ; add x coordinate to screen position\r
+       mov bx, ax\r
+       shr ax, 2\r
+       add di, ax\r
+\r
+       mov dx, SC_INDEX\r
+       mov al, MAP_MASK\r
+       out dx, al\r
+       inc dx\r
+\r
+       and bx, 3           ; initial mask\r
+       xor ax, ax\r
+       mov al, ColumnMask[bx]\r
+       mov VGA_mask, ax\r
+       out dx, al\r
+\r
+       mov column, 4\r
+       mov bitmap_pos, si\r
+       mov screen_pos, di\r
+       mov ax, _ScrnLogicalByteWidth\r
+       mov screen_width, ax ; since we move ds\r
+\r
+; we've used all our tables, so we can change ds to point to the bitmap,\r
+; and es to point to the screen\r
+       mov ds, word ptr [Bitmap + 2]\r
+       mov ax, SCREEN_SEG\r
+       mov es, ax\r
+\r
+       mov bx, width_copy\r
+\r
+; let's actually draw something for a change\r
+       mov ax, clipped_height\r
+       mov height_temp, ax\r
+       mov dx, screen_width\r
+       jmp cx\r
+\r
+; 90 bottles of beer on the wall...\r
+       PointLoop = 89\r
+       rept 89\r
+               MaskedPoint PointLoop\r
+               PointLoop = PointLoop - 1\r
+       endm\r
+; one bottle of beer...\r
+\r
+; final point needs a different branch offset, so we don't use MaskedPoint\r
+       mov al, [si]\r
+       or al, al\r
+       jz @@LineDone\r
+       mov es:[di], al\r
+\r
+@@LineDone:\r
+       add si, bx          ; advance one bitmap line\r
+       add di, dx          ; advance one screen line\r
+       dec height_temp\r
+       jz @@PlaneDone\r
+       jmp cx\r
+\r
+@@PlaneDone:\r
+       dec column\r
+       jz @@OuttaHere      ; only four columns per customer, please\r
+       mov dx, SC_INDEX + 1\r
+       rol byte ptr VGA_mask, 1\r
+       adc screen_pos, 0   ; move to new column if we've wrapped to plane 0\r
+       mov al, byte ptr VGA_mask\r
+       out dx, al          ; set VGA for next column\r
+\r
+       shr right_counter, 1\r
+       jnc @@NoRightCounter\r
+       add cx, MaskedPointSize ; cut off right edge for later planes\r
+@@NoRightCounter:\r
+       shr left_counter, 1\r
+       jnc @@NoLeftCounter\r
+       sub cx, MaskedPointSize ; add to left edge for later planes\r
+       dec bitmap_pos\r
+       dec screen_pos\r
+@@NoLeftCounter:\r
+       mov si, bitmap_pos\r
+       add si, bitmap_size\r
+       mov bitmap_pos, si\r
+       mov di, screen_pos\r
+\r
+       mov ax, clipped_height\r
+       mov height_temp, ax\r
+       mov dx, screen_width\r
+       jmp cx\r
+\r
+@@OuttaHere:                   ; return a 0 -- something was inside the boundary\r
+       pop ds\r
+       pop di\r
+       pop si\r
+       mov ax, 0\r
+       mov sp, bp\r
+       pop bp\r
+       ret\r
+_x_clip_masked_pbm endp\r
+\r
+       end\r
+\r