;**
; blitfunc.asm (nasm source)
; Low level blitter functions
;
; 24.06.2002: tk, initial implementation, based on inline
;                 assembler code.
;
; Copyright (c)2001 by Thomas Kindler, thomas.kindler@gmx.de
;
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License as
; published by the Free Software Foundation; either version 2 of
; the License, or (at your option) any later version. Read the
; full License at http://www.gnu.org/copyleft for more details.
;
;**

%define FARCODE
%include "src/c16.mac"

cpu     186
segment NASM_TEXT CLASS=CODE


global  _BM_Blit_Copy, _BM_Blit_NotCopy
global  _BM_Blit_And,  _BM_Blit_Nand, _BM_Blit_NotAnd, _BM_Blit_AndNot
global  _BM_Blit_Or,   _BM_Blit_Nor,  _BM_Blit_NotOr,  _BM_Blit_OrNot
global  _BM_Blit_Xor,  _BM_Blit_Nexor


%macro  BLITFUNC1 0
%$dst       arg   4       ; destination pointer
%$dstwidth  arg   2       ; destination page size
%$src       arg   4       ; source pointer
%$srcwidth  arg   2       ; source page size
%$width     arg   2       ; width of area to copy (in pixels)
%$pages     arg   2       ; number of pages to copy
%$shift     arg   2       ; right-shift [0..7]
%$fbm       arg   2       ; first byte mask
%$lbm       arg   2       ; last byte mask

            push    ds                      ; everything but the
            push    es                      ; kitchen sink ;)
            pusha
            pushf
            cld

            lds     si, [bp + %$src]
            les     di, [bp + %$dst]

            mov     cl, [bp + %$shift]
            mov     ch, [bp + %$fbm]        ; set mask for first row

.blit:      mov     dx, [bp + %$width]
            push    bp
            mov     bp, [bp + %$srcwidth]

            mov     bh, ch                  ; invert mask
            xor     bh, 0xff
            je      .unmasked
;----- ----- ----- ----- ----- ----- -----
;  [DS:SI] source pointer
;  [ES:DI] destination pointer
;
;  AX: free to use
;  BL: free to use, BH: inverted bitmask
;  CL: right-shift, CH: bitmask
;  DX: width counter
;  BP: source page size
;----- ----- ----- ----- ----- ----- -----
%endmacro

%macro BLITFUNC2 0
.next:      pop     bp
            add     si, [bp + %$srcwidth]   ; advance to next page
            sub     si, [bp + %$width]
            add     di, [bp + %$dstwidth]
            sub     di, [bp + %$width]

            mov     ch, 0xff                ; clear mask
            dec     word[bp + %$pages]
            cmp     word[bp + %$pages], 1
            jg      .blit

            mov     ch, [bp + %$lbm]        ; unless it's the last page
            je      .blit

            popf
            popa
            pop     es
            pop     ds
%endmacro



;**
;  
;**
proc  _BM_Blit_Copy
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, ch
            and     bl, bh
            or      al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_NotCopy
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            not     al
            and     al, ch
            and     bl, bh
            or      al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl

            not     al

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_And
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            or      al, bh
            and     al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, bl

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_Nand
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            or      al, bh
            and     al, bl
            xor     al, ch

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, bl
            not     al

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_NotAnd
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            or      al, bh
            xor     al, ch
            and     al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            not     al
            and     al, bl

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_AndNot
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            or      al, bh
            xor     bl, ch
            and     al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            not     bl
            and     al, bl

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_Or
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, ch
            or      al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            or      al, bl

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_Nor
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, ch
            or      al, bl
            xor     al, ch

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            or      al, bl
            not     al

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_NotOr
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, ch
            xor     al, ch
            or      al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            not     al
            or      al, bl

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_OrNot
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, ch
            xor     bl, ch
            or      al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            not     bl
            or      al, bl

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_Xor
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, ch
            xor     al, bl

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            xor     al, bl

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc


;**
;
;**
proc  _BM_Blit_Nexor
            BLITFUNC1
.masked:    mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            and     al, ch
            xor     al, bl
            xor     al, ch

            stosb
            dec     dx
            jne     .masked
            jmp     near  .next

.unmasked:  mov     ah, [ds:si+bp]
            lodsb
            shr     ax, cl
            mov     bl, [es:di]

            xor     al, bl
            not     al    

            stosb
            dec     dx
            jne     .unmasked
            BLITFUNC2
endproc
