1 ;-----------------------------------------------------------
\r
3 ; MXBB.ASM - Bit block transfer
\r
4 ; Copyright (c) 1993,1994 by Alessandro Scotti
\r
6 ;-----------------------------------------------------------
\r
13 MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'
\r
14 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING
\r
16 EXTRN subHorizontalLineInfo : NEAR
\r
18 EXTRN mx_VideoSegment : WORD
\r
19 EXTRN mx_BytesPerLine : WORD
\r
21 ;-----------------------------------------------------------
\r
23 ; Moves a block of video memory.
\r
26 ; SX, SY = source coordinates
\r
27 ; Width = source width
\r
28 ; Height = source height
\r
29 ; DX, DY = destination coordinates
\r
33 ; Note: overlapping regions are not allowed.
\r
42 LOCAL PlaneWidth:WORD:4, \
\r
43 SourceOffset:WORD, \
\r
49 RightMask:BYTE = AUTO_SIZE
\r
51 .push ds, si, es, di
\r
53 ; Exit now if null width
\r
57 ; Calls the proper procedure to handle transfer
\r
59 and al, 03h ; AL = source plane
\r
61 and dl, 03h ; DL = destination plane
\r
62 mov bx, OFFSET subPlaneBlt
\r
63 cmp al, dl ; Same source and destination plane?
\r
64 jne @@BitBlt ; No, use slow procedure
\r
65 mov bx, OFFSET subMoveBlt
\r
74 ;-----------------------------------------------------------
\r
75 ; Uses write mode 1 for maximum speed. Only works if source
\r
76 ; and destination are plane-aligned.
\r
78 subMoveBlt PROC NEAR
\r
79 ; Get horizontal line info and address of destination
\r
83 call subHorizontalLineInfo
\r
89 mov ax, [mx_VideoSegment]
\r
93 ; Get address of source pixel
\r
95 mul [mx_BytesPerLine]
\r
113 out dx, ax ; Set write plane mask
\r
114 mov ax, [mx_BytesPerLine]
\r
128 ; Move center block
\r
135 out dx, ax ; Enable all planes
\r
136 mov ax, [mx_BytesPerLine]
\r
141 mov cx, bx ; CX = image width
\r
142 rep movsb ; Cannot use "movsw" here!
\r
143 add si, ax ; Next scan line
\r
144 add di, ax ; Next scan line
\r
145 dec dx ; All lines processed?
\r
146 jnz @@C1 ; No, continue
\r
153 mov ah, [RightMask]
\r
158 out dx, ax ; Set write plane mask
\r
159 mov ax, [mx_BytesPerLine]
\r
172 out dx, ax ; Restore write mode 0
\r
178 ;-----------------------------------------------------------
\r
179 ; Moves one plane at a time.
\r
181 subPlaneBlt PROC NEAR
\r
182 ; Compute extra bytes and width count for each plane
\r
186 shr bx, 1 ; Width for each plane
\r
192 mov PlaneWidth[si], bx
\r
199 ; Get pixel addresses
\r
200 mov ax, [mx_VideoSegment]
\r
204 mul [mx_BytesPerLine]
\r
208 add si, ax ; DS:SI points to source
\r
209 mov [SourceOffset], si
\r
211 mul [mx_BytesPerLine]
\r
215 add di, ax ; ES:DI points to destination
\r
216 mov [DestOffset], di
\r
218 ; Adjust plane for output to VGA registers
\r
221 mov [ReadPlane], al
\r
226 mov [WritePlane], al
\r
228 ; Ready to move now
\r
230 mov [Count], 4 ; Four planes
\r
231 lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane
\r
233 cmp WORD PTR ss:[bx], 0
\r
235 mov ah, [WritePlane]
\r
239 out dx, ax ; Select write plane
\r
240 mov ah, [ReadPlane]
\r
243 out dx, ax ; Select read plane
\r
245 mov ax, [mx_BytesPerLine]
\r
246 sub ax, ss:[bx] ; AX = extra bytes per line
\r
256 jnz @@Loop ; Repeat for all lines
\r
258 inc bx ; Select width for next plane
\r
260 and [ReadPlane], 03h ; Should be faster on 386 using
\r
261 jnz @@ReadPlaneOk ; BTR and ADC...
\r
264 rol [WritePlane], 1
\r
265 adc [DestOffset], 0
\r
266 mov si, [SourceOffset]
\r
267 mov di, [DestOffset]
\r
269 jnz @@PlaneLoop ; Repeat for all planes
\r