]> 4ch.mooo.com Git - 16.git/blob - mxbb.asm
ac6668ce230f264a72a7cfc837e7f948ffa6056f
[16.git] / mxbb.asm
1 ;-----------------------------------------------------------\r
2 ;\r
3 ; MXBB.ASM - Bit block transfer\r
4 ; Copyright (c) 1993,1994 by Alessandro Scotti\r
5 ;\r
6 ;-----------------------------------------------------------\r
7 WARN    PRO\r
8 NOWARN  RES\r
9 INCLUDE MODEX.DEF\r
10 \r
11 PUBLIC  mxBitBlt\r
12 \r
13 MX_TEXT         SEGMENT USE16 PARA PUBLIC 'CODE'\r
14                 ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
15 \r
16 EXTRN   subHorizontalLineInfo   : NEAR\r
17 \r
18 EXTRN   mx_VideoSegment : WORD\r
19 EXTRN   mx_BytesPerLine : WORD\r
20 \r
21 ;-----------------------------------------------------------\r
22 ;\r
23 ; Moves a block of video memory.\r
24 ;\r
25 ; Input:\r
26 ;       SX, SY  = source coordinates\r
27 ;       Width   = source width\r
28 ;       Height  = source height\r
29 ;       DX, DY  = destination coordinates\r
30 ; Output:\r
31 ;       none\r
32 ;\r
33 ; Note: overlapping regions are not allowed.\r
34 ;\r
35 mxBitBlt        PROC    FAR\r
36         ARG     DestY:WORD,             \\r
37                 DestX:WORD,             \\r
38                 Height:WORD,            \\r
39                 Width:WORD,             \\r
40                 SY:WORD,                \\r
41                 SX:WORD                 = ARG_SIZE\r
42         LOCAL   PlaneWidth:WORD:4,      \\r
43                 SourceOffset:WORD,      \\r
44                 DestOffset:WORD,        \\r
45                 Count:BYTE,             \\r
46                 ReadPlane:BYTE,         \\r
47                 WritePlane:BYTE,        \\r
48                 LeftMask:BYTE,          \\r
49                 RightMask:BYTE          = AUTO_SIZE\r
50         .enter  AUTO_SIZE\r
51         .push   ds, si, es, di\r
52 \r
53 ; Exit now if null width\r
54         cmp     [Width], 0\r
55         je      @@Exit\r
56 \r
57 ; Calls the proper procedure to handle transfer\r
58         mov     ax, [SX]\r
59         and     al, 03h                 ; AL = source plane\r
60         mov     dx, [DestX]\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
66 @@BitBlt:\r
67         call    bx\r
68 \r
69 @@Exit:\r
70         xor     ax, ax\r
71         .pop    ds, si, es, di\r
72         .leave  ARG_SIZE\r
73 \r
74 ;-----------------------------------------------------------\r
75 ; Uses write mode 1 for maximum speed. Only works if source\r
76 ; and destination are plane-aligned.\r
77 ;\r
78 subMoveBlt      PROC    NEAR\r
79 ; Get horizontal line info and address of destination\r
80         mov     bx, [DestX]\r
81         mov     ax, [DestY]\r
82         mov     cx, [Width]\r
83         call    subHorizontalLineInfo\r
84         mov     [LeftMask], al\r
85         mov     [RightMask], ah\r
86         mov     [Width], cx\r
87 \r
88 ; Setup segments\r
89         mov     ax, [mx_VideoSegment]\r
90         mov     ds, ax\r
91         mov     es, ax\r
92 \r
93 ; Get address of source pixel\r
94         mov     ax, [SY]\r
95         mul     [mx_BytesPerLine]\r
96         mov     si, [SX]\r
97         .shr    si, 2\r
98         add     si, ax\r
99 \r
100 ; Set write mode 1\r
101         mov     dx, GDC\r
102         mov     ax, 4105h\r
103         out     dx, ax\r
104         cld\r
105 \r
106 ; Move left block\r
107 @@L0:\r
108         mov     ah, [LeftMask]\r
109         or      ah, ah\r
110         jz      @@C0\r
111         mov     dx, TS\r
112         mov     al, 02h\r
113         out     dx, ax                  ; Set write plane mask\r
114         mov     ax, [mx_BytesPerLine]\r
115         dec     ax\r
116         mov     cx, [Height]\r
117         .push   si, di\r
118 @@L1:\r
119         movsb\r
120         add     si, ax\r
121         add     di, ax\r
122         dec     cx\r
123         jnz     @@L1\r
124         .pop    si, di\r
125         inc     si\r
126         inc     di\r
127 \r
128 ; Move center block\r
129 @@C0:\r
130         mov     bx, [Width]\r
131         test    bx, bx\r
132         jz      @@R0\r
133         mov     dx, TS\r
134         mov     ax, 0F02h\r
135         out     dx, ax                  ; Enable all planes\r
136         mov     ax, [mx_BytesPerLine]\r
137         sub     ax, bx\r
138         mov     dx, [Height]\r
139         .push   si, di\r
140 @@C1:\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
147         .pop    si, di\r
148         add     si, bx\r
149         add     di, bx\r
150 \r
151 ; Move right block\r
152 @@R0:\r
153         mov     ah, [RightMask]\r
154         or      ah, ah\r
155         jz      @@Done\r
156         mov     dx, TS\r
157         mov     al, 02h\r
158         out     dx, ax                  ; Set write plane mask\r
159         mov     ax, [mx_BytesPerLine]\r
160         dec     ax\r
161         mov     cx, [Height]\r
162 @@R1:\r
163         movsb\r
164         add     si, ax\r
165         add     di, ax\r
166         dec     cx\r
167         jnz     @@R1\r
168 \r
169 @@Done:\r
170         mov     dx, GDC\r
171         mov     ax, 4005h\r
172         out     dx, ax                  ; Restore write mode 0\r
173 \r
174 @@Exit:\r
175         ret\r
176 subMoveBlt      ENDP\r
177 \r
178 ;-----------------------------------------------------------\r
179 ; Moves one plane at a time.\r
180 ;\r
181 subPlaneBlt     PROC    NEAR\r
182 ; Compute extra bytes and width count for each plane\r
183         mov     cx, [Width]\r
184         mov     bx, cx\r
185         shr     bx, 1\r
186         shr     bx, 1                   ; Width for each plane\r
187         and     cl, 03h\r
188         mov     al, 00001000b\r
189         shr     al, cl\r
190         mov     si, 3 SHL 1\r
191 @@PatchLoop:\r
192         mov     PlaneWidth[si], bx\r
193         shr     al, 1\r
194         adc     bx, 0\r
195         dec     si\r
196         dec     si\r
197         jge     @@PatchLoop\r
198 \r
199 ; Get pixel addresses\r
200         mov     ax, [mx_VideoSegment]\r
201         mov     ds, ax\r
202         mov     es, ax\r
203         mov     ax, [SY]\r
204         mul     [mx_BytesPerLine]\r
205         mov     si, [SX]\r
206         shr     si, 1\r
207         shr     si, 1\r
208         add     si, ax                  ; DS:SI points to source\r
209         mov     [SourceOffset], si\r
210         mov     ax, [DestY]\r
211         mul     [mx_BytesPerLine]\r
212         mov     di, [DestX]\r
213         shr     di, 1\r
214         shr     di, 1\r
215         add     di, ax                  ; ES:DI points to destination\r
216         mov     [DestOffset], di\r
217 \r
218 ; Adjust plane for output to VGA registers\r
219         mov     ax, [SX]\r
220         and     al, 03h\r
221         mov     [ReadPlane], al\r
222         mov     cx, [DestX]\r
223         and     cl, 03h\r
224         mov     al, 00010001b\r
225         shl     al, cl\r
226         mov     [WritePlane], al\r
227 \r
228 ; Ready to move now\r
229         cld\r
230         mov     [Count], 4              ; Four planes\r
231         lea     bx, PlaneWidth          ; SS:[BX] = width in bytes for plane\r
232 @@PlaneLoop:\r
233         cmp     WORD PTR ss:[bx], 0\r
234         je      @@Done\r
235         mov     ah, [WritePlane]\r
236         and     ah, 0Fh\r
237         mov     al, 02h\r
238         mov     dx, TS\r
239         out     dx, ax                  ; Select write plane\r
240         mov     ah, [ReadPlane]\r
241         mov     al, 04h\r
242         mov     dx, GDC\r
243         out     dx, ax                  ; Select read plane\r
244         mov     dx, [Height]\r
245         mov     ax, [mx_BytesPerLine]\r
246         sub     ax, ss:[bx]             ; AX = extra bytes per line\r
247 @@Loop:\r
248         mov     cx, ss:[bx]\r
249         shr     cx, 1\r
250         rep     movsw\r
251         rcl     cx, 1\r
252         rep     movsb\r
253         add     si, ax\r
254         add     di, ax\r
255         dec     dx\r
256         jnz     @@Loop                  ; Repeat for all lines\r
257         inc     bx\r
258         inc     bx                      ; Select width for next plane\r
259         inc     [ReadPlane]\r
260         and     [ReadPlane], 03h        ; Should be faster on 386 using\r
261         jnz     @@ReadPlaneOk           ; BTR and ADC...\r
262         inc     [SourceOffset]\r
263 @@ReadPlaneOk:\r
264         rol     [WritePlane], 1\r
265         adc     [DestOffset], 0\r
266         mov     si, [SourceOffset]\r
267         mov     di, [DestOffset]\r
268         dec     [Count]\r
269         jnz     @@PlaneLoop             ; Repeat for all planes\r
270 \r
271 @@Done:\r
272         ret\r
273 subPlaneBlt     ENDP\r
274 \r
275 mxBitBlt        ENDP\r
276 \r
277 MX_TEXT         ENDS\r
278 END\r