]> 4ch.mooo.com Git - 16.git/blobdiff - 16/x_/mxbb.asm
wwww
[16.git] / 16 / x_ / mxbb.asm
diff --git a/16/x_/mxbb.asm b/16/x_/mxbb.asm
new file mode 100755 (executable)
index 0000000..ac6668c
--- /dev/null
@@ -0,0 +1,278 @@
+;-----------------------------------------------------------\r
+;\r
+; MXBB.ASM - Bit block transfer\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN    PRO\r
+NOWARN  RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC  mxBitBlt\r
+\r
+MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
+                ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN   subHorizontalLineInfo   : NEAR\r
+\r
+EXTRN   mx_VideoSegment : WORD\r
+EXTRN   mx_BytesPerLine : WORD\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Moves a block of video memory.\r
+;\r
+; Input:\r
+;       SX, SY  = source coordinates\r
+;       Width   = source width\r
+;       Height  = source height\r
+;       DX, DY  = destination coordinates\r
+; Output:\r
+;       none\r
+;\r
+; Note: overlapping regions are not allowed.\r
+;\r
+mxBitBlt        PROC    FAR\r
+        ARG     DestY:WORD,             \\r
+                DestX:WORD,             \\r
+                Height:WORD,            \\r
+                Width:WORD,             \\r
+                SY:WORD,                \\r
+                SX:WORD                 = ARG_SIZE\r
+        LOCAL   PlaneWidth:WORD:4,      \\r
+                SourceOffset:WORD,      \\r
+                DestOffset:WORD,        \\r
+                Count:BYTE,             \\r
+                ReadPlane:BYTE,         \\r
+                WritePlane:BYTE,        \\r
+                LeftMask:BYTE,          \\r
+                RightMask:BYTE          = AUTO_SIZE\r
+        .enter  AUTO_SIZE\r
+        .push   ds, si, es, di\r
+\r
+; Exit now if null width\r
+        cmp     [Width], 0\r
+        je      @@Exit\r
+\r
+; Calls the proper procedure to handle transfer\r
+        mov     ax, [SX]\r
+        and     al, 03h                 ; AL = source plane\r
+        mov     dx, [DestX]\r
+        and     dl, 03h                 ; DL = destination plane\r
+        mov     bx, OFFSET subPlaneBlt\r
+        cmp     al, dl                  ; Same source and destination plane?\r
+        jne     @@BitBlt                ; No, use slow procedure\r
+        mov     bx, OFFSET subMoveBlt\r
+@@BitBlt:\r
+        call    bx\r
+\r
+@@Exit:\r
+        xor     ax, ax\r
+        .pop    ds, si, es, di\r
+        .leave  ARG_SIZE\r
+\r
+;-----------------------------------------------------------\r
+; Uses write mode 1 for maximum speed. Only works if source\r
+; and destination are plane-aligned.\r
+;\r
+subMoveBlt      PROC    NEAR\r
+; Get horizontal line info and address of destination\r
+        mov     bx, [DestX]\r
+        mov     ax, [DestY]\r
+        mov     cx, [Width]\r
+        call    subHorizontalLineInfo\r
+        mov     [LeftMask], al\r
+        mov     [RightMask], ah\r
+        mov     [Width], cx\r
+\r
+; Setup segments\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     es, ax\r
+\r
+; Get address of source pixel\r
+        mov     ax, [SY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, [SX]\r
+        .shr    si, 2\r
+        add     si, ax\r
+\r
+; Set write mode 1\r
+        mov     dx, GDC\r
+        mov     ax, 4105h\r
+        out     dx, ax\r
+        cld\r
+\r
+; Move left block\r
+@@L0:\r
+        mov     ah, [LeftMask]\r
+        or      ah, ah\r
+        jz      @@C0\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     ax, [mx_BytesPerLine]\r
+        dec     ax\r
+        mov     cx, [Height]\r
+        .push   si, di\r
+@@L1:\r
+        movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     cx\r
+        jnz     @@L1\r
+        .pop    si, di\r
+        inc     si\r
+        inc     di\r
+\r
+; Move center block\r
+@@C0:\r
+        mov     bx, [Width]\r
+        test    bx, bx\r
+        jz      @@R0\r
+        mov     dx, TS\r
+        mov     ax, 0F02h\r
+        out     dx, ax                  ; Enable all planes\r
+        mov     ax, [mx_BytesPerLine]\r
+        sub     ax, bx\r
+        mov     dx, [Height]\r
+        .push   si, di\r
+@@C1:\r
+        mov     cx, bx                  ; CX = image width\r
+        rep     movsb                   ; Cannot use "movsw" here!\r
+        add     si, ax                  ; Next scan line\r
+        add     di, ax                  ; Next scan line\r
+        dec     dx                      ; All lines processed?\r
+        jnz     @@C1                    ; No, continue\r
+        .pop    si, di\r
+        add     si, bx\r
+        add     di, bx\r
+\r
+; Move right block\r
+@@R0:\r
+        mov     ah, [RightMask]\r
+        or      ah, ah\r
+        jz      @@Done\r
+        mov     dx, TS\r
+        mov     al, 02h\r
+        out     dx, ax                  ; Set write plane mask\r
+        mov     ax, [mx_BytesPerLine]\r
+        dec     ax\r
+        mov     cx, [Height]\r
+@@R1:\r
+        movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     cx\r
+        jnz     @@R1\r
+\r
+@@Done:\r
+        mov     dx, GDC\r
+        mov     ax, 4005h\r
+        out     dx, ax                  ; Restore write mode 0\r
+\r
+@@Exit:\r
+        ret\r
+subMoveBlt      ENDP\r
+\r
+;-----------------------------------------------------------\r
+; Moves one plane at a time.\r
+;\r
+subPlaneBlt     PROC    NEAR\r
+; Compute extra bytes and width count for each plane\r
+        mov     cx, [Width]\r
+        mov     bx, cx\r
+        shr     bx, 1\r
+        shr     bx, 1                   ; Width for each plane\r
+        and     cl, 03h\r
+        mov     al, 00001000b\r
+        shr     al, cl\r
+        mov     si, 3 SHL 1\r
+@@PatchLoop:\r
+        mov     PlaneWidth[si], bx\r
+        shr     al, 1\r
+        adc     bx, 0\r
+        dec     si\r
+        dec     si\r
+        jge     @@PatchLoop\r
+\r
+; Get pixel addresses\r
+        mov     ax, [mx_VideoSegment]\r
+        mov     ds, ax\r
+        mov     es, ax\r
+        mov     ax, [SY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     si, [SX]\r
+        shr     si, 1\r
+        shr     si, 1\r
+        add     si, ax                  ; DS:SI points to source\r
+        mov     [SourceOffset], si\r
+        mov     ax, [DestY]\r
+        mul     [mx_BytesPerLine]\r
+        mov     di, [DestX]\r
+        shr     di, 1\r
+        shr     di, 1\r
+        add     di, ax                  ; ES:DI points to destination\r
+        mov     [DestOffset], di\r
+\r
+; Adjust plane for output to VGA registers\r
+        mov     ax, [SX]\r
+        and     al, 03h\r
+        mov     [ReadPlane], al\r
+        mov     cx, [DestX]\r
+        and     cl, 03h\r
+        mov     al, 00010001b\r
+        shl     al, cl\r
+        mov     [WritePlane], al\r
+\r
+; Ready to move now\r
+        cld\r
+        mov     [Count], 4              ; Four planes\r
+        lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
+@@PlaneLoop:\r
+        cmp     WORD PTR ss:[bx], 0\r
+        je      @@Done\r
+        mov     ah, [WritePlane]\r
+        and     ah, 0Fh\r
+        mov     al, 02h\r
+        mov     dx, TS\r
+        out     dx, ax                  ; Select write plane\r
+        mov     ah, [ReadPlane]\r
+        mov     al, 04h\r
+        mov     dx, GDC\r
+        out     dx, ax                  ; Select read plane\r
+        mov     dx, [Height]\r
+        mov     ax, [mx_BytesPerLine]\r
+        sub     ax, ss:[bx]             ; AX = extra bytes per line\r
+@@Loop:\r
+        mov     cx, ss:[bx]\r
+        shr     cx, 1\r
+        rep     movsw\r
+        rcl     cx, 1\r
+        rep     movsb\r
+        add     si, ax\r
+        add     di, ax\r
+        dec     dx\r
+        jnz     @@Loop                  ; Repeat for all lines\r
+        inc     bx\r
+        inc     bx                      ; Select width for next plane\r
+        inc     [ReadPlane]\r
+        and     [ReadPlane], 03h        ; Should be faster on 386 using\r
+        jnz     @@ReadPlaneOk           ; BTR and ADC...\r
+        inc     [SourceOffset]\r
+@@ReadPlaneOk:\r
+        rol     [WritePlane], 1\r
+        adc     [DestOffset], 0\r
+        mov     si, [SourceOffset]\r
+        mov     di, [DestOffset]\r
+        dec     [Count]\r
+        jnz     @@PlaneLoop             ; Repeat for all planes\r
+\r
+@@Done:\r
+        ret\r
+subPlaneBlt     ENDP\r
+\r
+mxBitBlt        ENDP\r
+\r
+MX_TEXT         ENDS\r
+END\r