]> 4ch.mooo.com Git - 16.git/blob - 16/xlib/XPBMCLIP.ASM
added xlib to the project and i gotta convert the damn makefile -.-
[16.git] / 16 / xlib / XPBMCLIP.ASM
1 ;-----------------------------------------------------------------------\r
2 ; MODULE XPBMCLIP\r
3 ;\r
4 ; Clipped Planar Bitmap functions - System Ram <-> Video Ram\r
5 ;\r
6 ; Compile with Tasm.\r
7 ; C callable.\r
8 ;\r
9 ;\r
10 ; ****** XLIB - Mode X graphics library                ****************\r
11 ; ******                                               ****************\r
12 ; ****** Written By Themie Gouthas                     ****************\r
13 ;\r
14 ; egg@dstos3.dsto.gov.au\r
15 ; teg@bart.dsto.gov.au\r
16 ;-----------------------------------------------------------------------\r
17 \r
18 \r
19 COMMENT $\r
20 \r
21   This module implements a set of functions to operate on planar bitmaps.\r
22   Planar bitmaps as used by these functions have the following structure:\r
23 \r
24   BYTE 0                 The bitmap width in bytes (4 pixel groups) range 1..255\r
25   BYTE 1                 The bitmap height in rows range 1..255\r
26   BYTE 2..n1             The plane 0 pixels width*height bytes\r
27   BYTE n1..n2            The plane 1 pixels width*height bytes\r
28   BYTE n2..n3            The plane 2 pixels width*height bytes\r
29   BYTE n3..n4            The plane 3 pixels width*height bytes\r
30 \r
31   These functions provide the fastest possible bitmap blts from system ram to\r
32   to video and further, the single bitmap is applicable to all pixel\r
33   allignments. The masked functions do not need separate masks since all non\r
34   zero pixels are considered to be masking pixels, hence if a pixel is 0 the\r
35   corresponding screen destination pixel is left unchanged.\r
36 \r
37 \r
38 $\r
39 LOCALS\r
40 include xlib.inc\r
41 include xpbmclip.inc\r
42 \r
43         .code\r
44 \r
45 ;----------------------------------------------------------------------\r
46 ; x_put_masked_pbm_clipx - mask write a planar bitmap from system ram to video\r
47 ;                       ram all zero source bitmap bytes indicate destination\r
48 ;                       byte to be left unchanged.\r
49 ;                       Performs clipping in x directions. similar to\r
50 ;                       "x_put_masked_pbm".\r
51 ;\r
52 ; See Also:  x_put_masked_pbm, x_put_masked_pbm_clipxy\r
53 ;\r
54 ; Clipping region variables: LeftClip,RightClip\r
55 ;\r
56 ; Written by Themie Gouthas\r
57 ;\r
58 ; This code is a SLOW hack, any better ideas are welcome\r
59 ;----------------------------------------------------------------------\r
60 _x_put_masked_pbm_clipx  proc\r
61 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
62 LOCAL   Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:word=LocalStk\r
63         push  bp\r
64         mov   bp,sp\r
65         sub   sp,LocalStk                 ; Create space for local variables\r
66         push  si\r
67         push  di\r
68         push  ds\r
69         cld\r
70 \r
71         les   si,[Bitmap]                 ; Point ES:SI to start of bitmap\r
72 \r
73         xor   ax,ax                       ; Clear AX\r
74         mov   [CType],ax                  ; Clear Clip type descision var\r
75         mov   al,byte ptr es:[si]         ; AX=width (byte coverted to word)\r
76 \r
77 \r
78         mov   di,[X]                      ; DI = X coordinate of dest\r
79         mov   cx,di                       ; copy to CX\r
80         sar   di,2                        ; convert to offset in row\r
81 \r
82 \r
83         ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
84 \r
85         mov   dx,[_LeftClip]              ; Is X Coord to the right of\r
86         sub   dx,di                       ; LeftClip ?\r
87         jle   @@NotLeftClip               ; Yes! => no left clipping\r
88         cmp   dx,ax                       ; Is dist of X Coord from\r
89         jnl   @@NotVisible                ; ClipLeft > Width ? yes => the\r
90                                           ; bitmap is not visible\r
91         add   di,dx\r
92         mov   [LeftSkip],dx\r
93         mov   [DataInc],dx\r
94         sub   ax,dx\r
95         mov   [CType],1\r
96         jmp   short @@HorizClipDone\r
97 \r
98         ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
99 \r
100 @@NotVisible:\r
101         mov   ax,1\r
102         pop   ds                          ; restore data segment\r
103         pop   di                          ; restore registers\r
104         pop   si\r
105         mov   sp,bp                       ; dealloc local variables\r
106         pop   bp\r
107         ret\r
108 \r
109         ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
110 \r
111 @@NotLeftClip:\r
112         mov   dx,[_RightClip]\r
113         sub   dx,di\r
114         js    @@NotVisible\r
115         mov   [LeftSkip],0\r
116         mov   [DataInc],0\r
117         cmp   dx,ax\r
118         jge   @@HorizClipDone       ; was jg\r
119         inc   dx\r
120         sub   ax,dx\r
121         mov   [DataInc],ax\r
122         mov   ax,dx\r
123         mov   [CType],-1\r
124 \r
125 @@HorizClipDone:\r
126 \r
127         xor   bh,bh\r
128         mov   bl,byte ptr es:[si+1]       ; BX = height\r
129 \r
130         mov   [Width],ax                  ; Save width and height of clipped\r
131         mov   [Height],bx                 ;  image\r
132 \r
133 \r
134         add   si,2                        ; Skip dimension bytes in source\r
135         add   si,[LeftSkip]               ; Skip pixels in front of row that\r
136                                           ;  are clipped\r
137 \r
138 \r
139         mov   bx,[_ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width\r
140         mov   dx,bx                       ; BX - Width of image = No. bytes\r
141         sub   dx,ax                       ;  to first byte of next screen\r
142         mov   [LineInc],dx                ;  row.\r
143 \r
144         mov   ax,[Y]                      ; Calculate screen start row\r
145         mul   bx                          ;  then adding screen offset\r
146         add   di,ax\r
147         add   di,[ScrnOffs]\r
148         mov   ax,es                       ; copy ES to DS\r
149         mov   ds,ax\r
150         mov   ax,SCREEN_SEG               ; Point ES to VGA segment\r
151         mov   es,ax\r
152 \r
153         and   cx,3\r
154         mov   ah,11h                      ; Set up initial plane mask\r
155         shl   ah,cl\r
156 \r
157         mov   dx,SC_INDEX                 ; Prepare VGA for cpu to video writes\r
158         mov   al,MAP_MASK\r
159         out   dx,al\r
160         inc   dx\r
161         mov   [Plane],4                   ; Set plane counter to 4\r
162         mov   bh,byte ptr [Width]         ; set bh to width for fast looping\r
163 @@PlaneLoop:\r
164         push  di                          ; Save bitmap's start dest. offset\r
165         mov   bl,byte ptr [Height]        ; Reset row counter (BL)\r
166         mov   al,ah\r
167         out   dx,al                       ; set vga write plane\r
168 @@RowLoop:\r
169         mov   cl,bh                       ; Reset Column counter cl\r
170         jcxz  @@NoWidth\r
171 @@ColLoop:\r
172         lodsb                             ; Get next source bitmap byte\r
173         or    al,al                       ; If not zero then write to dest.\r
174         jz    @@NoPixel                   ; otherwise skip to next byte\r
175         mov   es:[di],al\r
176 @@NoPixel:\r
177         inc   di\r
178         loop @@ColLoop\r
179 @@NoWidth:\r
180         add   si,[DataInc]                ; Move to next source row\r
181         add   di,[LineInc]                ; Move to next screen row\r
182         dec   bl                          ; decrement row counter\r
183         jnz   @@RowLoop                   ; Jump if more rows left\r
184         pop   di                          ; Restore bitmaps start dest byte\r
185         rol   ah,1                        ; Shift mask for next plane\r
186 \r
187         ; Plane Transition (A HACK but it works!)\r
188 \r
189         jnb   @@Nocarry                   ; Jump if not plane transition\r
190         mov   bl,ah                       ; Save Plane Mask\r
191         mov   ax,[CType]                  ; set AX to clip type inc variable\r
192         add   bh,al                       ; Update advancing variables\r
193         sub   [DataInc],ax                ;\r
194         sub   [LineInc],ax                ;\r
195         cmp   al,0                        ; What type of clip do we have\r
196         mov   ah,bl                       ;   restore Plane mask\r
197         jg    @@RightAdvance              ; jump on a right clip!\r
198         inc   di                          ; otherwise increment DI\r
199         jmp   @@Nocarry\r
200 @@RightAdvance:\r
201         dec si\r
202 @@Nocarry:\r
203         dec   [Plane]                     ; Decrement plane counter\r
204         jnz   @@PlaneLoop                 ; Jump if more planes left\r
205 \r
206         xor   ax,ax\r
207         pop   ds                          ; restore data segment\r
208         pop   di                          ; restore registers\r
209         pop   si\r
210         mov   sp,bp                       ; dealloc local variables\r
211         pop   bp\r
212         ret\r
213 _x_put_masked_pbm_clipx  endp\r
214 \r
215 \r
216 ;----------------------------------------------------------------------\r
217 ; x_put_masked_pbm_clipy - mask write a planar bitmap from system ram to video\r
218 ;                       ram all zero source bitmap bytes indicate destination\r
219 ;                       byte to be left unchanged.\r
220 ;                       Performs clipping in y direction. similar to\r
221 ;                       "x_put_masked_pbm".\r
222 ;\r
223 ; See Also:  x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipy\r
224 ;\r
225 ; Clipping region variables: TopClip,BottomClip\r
226 ;\r
227 ; Written by Themie Gouthas\r
228 ;----------------------------------------------------------------------\r
229 _x_put_masked_pbm_clipy  proc\r
230 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
231 LOCAL   Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk\r
232         push  bp\r
233         mov   bp,sp\r
234         sub   sp,LocalStk                 ; Create space for local variables\r
235         push  si\r
236         push  di\r
237         push  ds\r
238         cld\r
239 \r
240         les   si,[Bitmap]\r
241 \r
242         xor   bh,bh\r
243         mov   bl,byte ptr es:[si+1]       ; BX = height\r
244 \r
245         xor   ah,ah\r
246         mov   al,byte ptr es:[si]         ; AX = width\r
247 \r
248         mov   cx,ax                       ; Save AX\r
249         mul   bx                          ; AX = AX*BX = bytes/plane\r
250         mov   [PlaneInc],ax               ;  save as PlaneInc\r
251         mov   ax,cx                       ; Restore AX\r
252 \r
253         mov   di,[X]\r
254         mov   cx,di\r
255         shr   di,2\r
256 \r
257         ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
258 \r
259         mov   dx,[_TopClip]           ; Compare u.l. Y coord with Top\r
260         sub   dx,[Y]                  ; clipping border\r
261         jle   @@NotTopClip            ; jump if VBM not clipped from above\r
262         cmp   dx,bx\r
263         jnl   @@NotVisible            ; jump if VBM is completely obscured\r
264         mov   [TopRow],dx\r
265         sub   bx,dx\r
266         add   [Y],dx\r
267         jmp   short @@VertClipDone\r
268 \r
269         ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
270 \r
271 @@NotVisible:\r
272         mov   ax,1\r
273         pop   ds                          ; restore data segment\r
274         pop   di                          ; restore registers\r
275         pop   si\r
276         mov   sp,bp                       ; dealloc local variables\r
277         pop   bp\r
278         ret\r
279 \r
280         ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
281 \r
282 @@NotTopClip:\r
283         mov   dx,[_BottomClip]\r
284         sub   dx,[Y]\r
285         js    @@NotVisible\r
286         mov   [TopRow],0\r
287         cmp   dx,bx\r
288         jg    @@VertClipDone\r
289         inc   dx\r
290         mov   bx,dx\r
291 \r
292 @@VertClipDone:\r
293 \r
294         mov   [Width],ax\r
295         mov   [Height],bx                 ; Calculate relative offset in data\r
296         mul   [TopRow]                    ;  of first visible scanline\r
297         add   ax,2                        ; Skip dimension bytes in source\r
298         add   si,ax                       ; Skip top rows that arent visible\r
299 \r
300 \r
301         mov   ax,[Y]                      ; Calculate screen row\r
302         mov   bx,[_ScrnLogicalByteWidth]  ;  by mult. Y coord by Screen\r
303         mul   bx                          ;  width then adding screen offset\r
304         add   di,ax\r
305         add   di,[ScrnOffs]\r
306         sub   bx,[Width]                  ; calculate difference from end of\r
307         mov   [LineInc],bx                ; b.m. in curr line to beginning of\r
308                                           ; b.m. on next scan line\r
309         mov   ax,es                       ; copy ES to DS\r
310         mov   ds,ax\r
311         mov   ax,SCREEN_SEG               ; Point ES to VGA segment\r
312         mov   es,ax\r
313 \r
314         mov   ah,11h                      ; Set up initial plane mask\r
315         and   cx,3\r
316         shl   ah,cl\r
317 \r
318         mov   dx,SC_INDEX                 ; Prepare VGA for cpu to video writes\r
319         mov   al,MAP_MASK\r
320         out   dx,al\r
321         inc   dx\r
322         mov   bh,4                        ; Set plane counter to 4\r
323 @@PlaneLoop:\r
324         push  di                          ; Save bitmap's start dest. offset\r
325         push  si                          ; Save Bitmaps data offset\r
326         mov   bl,byte ptr [Height]        ; Reset row counter (BL)\r
327         mov   al,ah\r
328         out   dx,al                       ; set vga write plane\r
329 @@RowLoop:\r
330         mov   cl,byte ptr [Width]         ; Reset Column counter cl\r
331 @@ColLoop:\r
332         lodsb                             ; Get next source bitmap byte\r
333         or    al,al                       ; If not zero then write to dest.\r
334         jz    @@NoPixel                   ; otherwise skip to next byte\r
335         mov   es:[di],al\r
336 @@NoPixel:\r
337         inc   di\r
338         loop  @@ColLoop                   ; loop if more columns left\r
339         add   di,[LineInc]                ; Move to next row\r
340         dec   bl                          ; decrement row counter\r
341         jnz   @@RowLoop                   ; Jump if more rows left\r
342         pop   si                          ; Restore SI and set to offset of\r
343         add   si,[PlaneInc]               ; first vis pixel in next plane data\r
344         pop   di                          ; Restore bitmaps start dest byte\r
345         rol   ah,1                        ; Shift mask for next plane\r
346         adc   di,0                        ; if carry increment screen offset\r
347         dec   bh                          ; Decrement plane counter\r
348         jnz   @@PlaneLoop                 ; Jump if more planes left\r
349 \r
350         xor   ax,ax\r
351         pop   ds                          ; restore data segment\r
352         pop   di                          ; restore registers\r
353         pop   si\r
354         mov   sp,bp                       ; dealloc local variables\r
355         pop   bp\r
356         ret\r
357 _x_put_masked_pbm_clipy   endp\r
358 \r
359 ;----------------------------------------------------------------------\r
360 ; x_put_masked_pbm_clipxy - Write a planar bitmap from system ram to video\r
361 ;                    RAM with clipping in x and y directions. similar to\r
362 ;                    "x_put_masked_pbm".\r
363 ;\r
364 ; See Also: x_put_masked_pbm, x_put_masked_pbm_clipx, x_put_masked_pbm_clipxy\r
365 ;\r
366 ; Clipping region variables: LeftClip,RightClip,TopClip,BottomClip\r
367 ;\r
368 ;\r
369 ; Written by Themie Gouthas\r
370 ;----------------------------------------------------------------------\r
371 _x_put_masked_pbm_clipxy  proc\r
372 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
373 LOCAL   Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk\r
374         push  bp\r
375         mov   bp,sp\r
376         sub   sp,LocalStk                 ; Create space for local variables\r
377         push  si\r
378         push  di\r
379         push  ds\r
380         cld\r
381 \r
382         les   si,[Bitmap]\r
383 \r
384         xor   ax,ax\r
385         mov   [CType],ax\r
386         mov   al,byte ptr es:[si]         ; AX = width\r
387         xor   bh,bh\r
388         mov   bl,byte ptr es:[si+1]       ; BX = height\r
389 \r
390         mov   cx,ax                       ; Save AX\r
391         mul   bx                          ; AX = AX*BX = bytes/plane\r
392         mov   [PlaneInc],ax               ;  save as PlaneInc\r
393         mov   ax,cx                       ; Restore AX\r
394 \r
395 \r
396         mov   di,[X]                      ; DI = X coordinate of dest.\r
397         mov   cx,di                       ; save in CX\r
398         sar   di,2                        ; convert to address byte\r
399 \r
400 \r
401                 ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
402 \r
403         mov   dx,[_TopClip]           ; Compare u.l. Y coord with Top\r
404         sub   dx,[Y]                  ; clipping border\r
405         jle   @@NotTopClip            ; jump if VBM not clipped from above\r
406         cmp   dx,bx\r
407         jnl   @@NotVisible            ; jump if VBM is completely obscured\r
408         mov   [TopRow],dx\r
409         sub   bx,dx\r
410         add   [Y],dx\r
411         jmp   short @@VertClipDone\r
412 \r
413         ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
414 \r
415 @@NotVisible:\r
416         mov   ax,1\r
417         pop   ds                          ; restore data segment\r
418         pop   di                          ; restore registers\r
419         pop   si\r
420         mov   sp,bp                       ; dealloc local variables\r
421         pop   bp\r
422         ret\r
423 \r
424         ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
425 \r
426 @@NotTopClip:\r
427         mov   dx,[_BottomClip]\r
428         sub   dx,[Y]\r
429         js    @@NotVisible\r
430         mov   [TopRow],0\r
431         cmp   dx,bx\r
432         jg    @@VertClipDone\r
433         inc   dx\r
434         mov   bx,dx\r
435 \r
436 @@VertClipDone:\r
437 \r
438         ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
439 \r
440         mov   dx,[_LeftClip]\r
441         sub   dx,di\r
442         jle   @@NotLeftClip\r
443         cmp   dx,ax\r
444         jnl   @@NotVisible\r
445 \r
446         add   di,dx\r
447         mov   [LeftSkip],dx\r
448         mov   [DataInc],dx\r
449         sub   ax,dx\r
450         mov   [CType],1\r
451         jmp   short @@HorizClipDone\r
452 \r
453         ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
454 \r
455 @@NotLeftClip:\r
456         mov   dx,[_RightClip]\r
457         sub   dx,di\r
458         js    @@NotVisible\r
459         mov   [LeftSkip],0\r
460         mov   [DataInc],0\r
461         cmp   dx,ax\r
462         jge   @@HorizClipDone       ; was jg\r
463         inc   dx\r
464         sub   ax,dx\r
465         mov   [DataInc],ax\r
466         mov   ax,dx\r
467 \r
468 \r
469         mov   [CType],-1\r
470 \r
471 @@HorizClipDone:\r
472 \r
473 \r
474 \r
475         mov   [Width],ax                  ; Save width and height of clipped\r
476         mov   [Height],bx                 ;  image\r
477 \r
478         add   ax,[DataInc]                ; AX = original width of image\r
479         mul   [TopRow]                    ; Calculate bytes in clipped top\r
480         add   si,ax                       ;  rows\r
481         add   si,2                        ; Skip dimension bytes in source\r
482         add   si,[LeftSkip]               ; Skip pixels in front of row that\r
483                                           ;  are clipped\r
484 \r
485         mov   bx,[_ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width\r
486         mov   dx,bx                       ; BX - Width of image = No. bytes\r
487         sub   dx,[Width]                  ;  to first byte of next screen\r
488         mov   [LineInc],dx                ;  row.\r
489 \r
490         mov   ax,[Y]                      ; Calculate screen start row\r
491         mul   bx                          ;  then adding screen offset\r
492         add   di,ax\r
493         add   di,[ScrnOffs]\r
494         mov   ax,es                       ; copy ES to DS\r
495         mov   ds,ax\r
496         mov   ax,SCREEN_SEG               ; Point ES to VGA segment\r
497         mov   es,ax\r
498 \r
499 \r
500 \r
501         and   cx,3\r
502         mov   ah,11h                      ; Set up initial plane mask\r
503         shl   ah,cl\r
504 \r
505         mov   dx,SC_INDEX                 ; Prepare VGA for cpu to video writes\r
506         mov   al,MAP_MASK\r
507         out   dx,al\r
508         inc   dx\r
509         mov   [Plane],4                   ; Set plane counter to 4\r
510         mov   bh,byte ptr [Width]         ; set bh to width for fast looping\r
511 @@PlaneLoop:\r
512         push  di                          ; Save bitmap's start dest. offset\r
513         push  si\r
514         mov   bl,byte ptr [Height]        ; Reset row counter (BL)\r
515         mov   al,ah\r
516         out   dx,al                       ; set vga write plane\r
517 @@RowLoop:\r
518         mov   cl,bh                       ; Reset Column counter cl\r
519         jcxz   @@NoWidth\r
520 @@ColLoop:\r
521         lodsb                             ; Get next source bitmap byte\r
522         or    al,al                       ; If not zero then write to dest.\r
523         jz    @@NoPixel                   ; otherwise skip to next byte\r
524         mov   es:[di],al\r
525 @@NoPixel:\r
526         inc   di\r
527         loop @@ColLoop\r
528 @@NoWidth:\r
529         add   si,[DataInc]                ; Move to next source row\r
530         add   di,[LineInc]                ; Move to next screen row\r
531         dec   bl                          ; decrement row counter\r
532         jnz   @@RowLoop                   ; Jump if more rows left\r
533         pop   si                          ; Restore SI and set to offset of\r
534         add   si,[PlaneInc]               ; first vis pixel in next plane data\r
535         pop   di                          ; Restore bitmaps start dest byte\r
536         rol   ah,1                        ; Shift mask for next plane\r
537 \r
538         ; Plane Transition (A HACK but it works!)\r
539 \r
540         jnb   @@Nocarry                   ; Jump if not plane transition\r
541         mov   bl,ah                       ; Save Plane Mask\r
542         mov   ax,[CType]                  ; set AX to clip type inc variable\r
543         add   bh,al                       ; Update advancing variables\r
544         sub   [DataInc],ax                ;\r
545         sub   [LineInc],ax                ;\r
546         cmp   al,0                        ; What type of clip do we have\r
547         mov   ah,bl                       ;   restore Plane mask\r
548         jg    @@RightAdvance              ; jump on a right clip!\r
549         inc   di                          ; otherwise increment DI\r
550         jmp   @@Nocarry\r
551 @@RightAdvance:\r
552         dec   si\r
553 @@Nocarry:\r
554         dec   [Plane]                     ; Decrement plane counter\r
555         jnz   @@PlaneLoop                 ; Jump if more planes left\r
556 \r
557         xor   ax,ax\r
558         pop   ds                          ; restore data segment\r
559         pop   di                          ; restore registers\r
560         pop   si\r
561         mov   sp,bp                       ; dealloc local variables\r
562         pop   bp\r
563         ret\r
564 _x_put_masked_pbm_clipxy  endp\r
565 \r
566 \r
567 \r
568 \r
569 ;----------------------------------------------------------------------\r
570 ; x_put_pbm_clipx - Write a planar bitmap from system ram to video ram\r
571 ;                    with clipping in x and y directions. similar to\r
572 ;                    "x_put_pbm".\r
573 ;\r
574 ; See Also:  x_put_pbm_clip\r
575 ;\r
576 ;\r
577 ; See Also:  x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipxy\r
578 ;\r
579 ; Clipping region variables: LeftClip,RightClip\r
580 ;\r
581 ; Written by Themie Gouthas\r
582 ;\r
583 ; This code is a SLOW hack, any better ideas are welcome\r
584 ;----------------------------------------------------------------------\r
585 _x_put_pbm_clipx  proc\r
586 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
587 LOCAL   Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc:word=LocalStk\r
588         push  bp\r
589         mov   bp,sp\r
590         sub   sp,LocalStk                 ; Create space for local variables\r
591         push  si\r
592         push  di\r
593         push  ds\r
594         cld\r
595 \r
596         les   si,[Bitmap]\r
597 \r
598         xor   ax,ax\r
599         mov   [CType],ax\r
600         mov   al,byte ptr es:[si]         ; AX = width\r
601 \r
602 \r
603         mov   di,[X]                      ; DI = X coordinate of dest.\r
604         mov   cx,di                       ; save in CX\r
605         sar   di,2                        ; convert to address byte\r
606 \r
607 \r
608 \r
609         ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
610 \r
611         mov   dx,[_LeftClip]\r
612         sub   dx,di\r
613         jle   @@NotLeftClip\r
614         cmp   dx,ax\r
615         jnl   @@NotVisible\r
616 \r
617         add   di,dx\r
618         mov   [LeftSkip],dx\r
619         mov   [DataInc],dx\r
620         sub   ax,dx\r
621         mov   [CType],1\r
622         jmp   short @@HorizClipDone\r
623 \r
624         ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
625 \r
626 @@NotVisible:\r
627         mov   ax,1\r
628         pop   ds                          ; restore data segment\r
629         pop   di                          ; restore registers\r
630         pop   si\r
631         mov   sp,bp                       ; dealloc local variables\r
632         pop   bp\r
633         ret\r
634 \r
635         ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
636 \r
637 @@NotLeftClip:\r
638         mov   dx,[_RightClip]\r
639         sub   dx,di\r
640         js    @@NotVisible\r
641         mov   [LeftSkip],0\r
642         mov   [DataInc],0\r
643         cmp   dx,ax\r
644         jge   @@HorizClipDone       ; was jg\r
645         inc   dx\r
646         sub   ax,dx\r
647         mov   [DataInc],ax\r
648         mov   ax,dx\r
649         mov   [CType],-1\r
650 \r
651 @@HorizClipDone:\r
652 \r
653         xor   bh,bh\r
654         mov   bl,byte ptr es:[si+1]       ; BX = height\r
655 \r
656         mov   [Width],ax                  ; Save width and height of clipped\r
657         mov   [Height],bx                 ;  image\r
658 \r
659 \r
660         add   si,2                        ; Skip dimension bytes in source\r
661         add   si,[LeftSkip]               ; Skip pixels in front of row that\r
662                                           ;  are clipped\r
663 \r
664 \r
665         mov   bx,[_ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width\r
666         mov   dx,bx                       ; BX - Width of image = No. bytes\r
667         sub   dx,ax                       ;  to first byte of next screen\r
668         mov   [LineInc],dx                ;  row.\r
669 \r
670         mov   ax,[Y]                      ; Calculate screen start row\r
671         mul   bx                          ;  then adding screen offset\r
672         add   di,ax\r
673         add   di,[ScrnOffs]\r
674         mov   ax,es                       ; copy ES to DS\r
675         mov   ds,ax\r
676         mov   ax,SCREEN_SEG               ; Point ES to VGA segment\r
677         mov   es,ax\r
678 \r
679         and   cx,3\r
680         mov   ah,11h                      ; Set up initial plane mask\r
681         shl   ah,cl\r
682 \r
683         mov   dx,SC_INDEX                 ; Prepare VGA for cpu to video writes\r
684         mov   al,MAP_MASK\r
685         out   dx,al\r
686         inc   dx\r
687         mov   [Plane],4                   ; Set plane counter to 4\r
688         mov   bh,byte ptr [Width]         ; set bh to width for fast looping\r
689 @@PlaneLoop:\r
690         push  di                          ; Save bitmap's start dest. offset\r
691         mov   bl,byte ptr [Height]        ; Reset row counter (BL)\r
692         mov   al,ah\r
693         out   dx,al                       ; set vga write plane\r
694 @@RowLoop:\r
695         mov   cl,bh                       ; Reset Column counter cl\r
696         shr   cl,1\r
697         rep   movsw                       ; Copy a complete row\r
698         adc   cl,0\r
699         rep   movsb\r
700         add   si,[DataInc]                ; Move to next source row\r
701         add   di,[LineInc]                ; Move to next screen row\r
702         dec   bl                          ; decrement row counter\r
703         jnz   @@RowLoop                   ; Jump if more rows left\r
704         pop   di                          ; Restore bitmaps start dest byte\r
705         rol   ah,1                        ; Shift mask for next plane\r
706 \r
707         ; Plane Transition (A HACK but it works!)\r
708 \r
709         jnb   @@Nocarry                   ; Jump if not plane transition\r
710         mov   bl,ah                       ; Save Plane Mask\r
711         mov   ax,[CType]                  ; set AX to clip type inc variable\r
712         add   bh,al                       ; Update advancing variables\r
713         sub   [DataInc],ax                ;\r
714         sub   [LineInc],ax                ;\r
715         cmp   al,0                        ; What type of clip do we have\r
716         mov   ah,bl                       ;   restore Plane mask\r
717         jg    @@RightAdvance              ; jump on a right clip!\r
718         inc   di                          ; otherwise increment DI\r
719         jmp   @@Nocarry\r
720 @@RightAdvance:\r
721         dec si\r
722 @@Nocarry:\r
723         dec   [Plane]                     ; Decrement plane counter\r
724         jnz   @@PlaneLoop                 ; Jump if more planes left\r
725 \r
726         xor   ax,ax\r
727         pop   ds                          ; restore data segment\r
728         pop   di                          ; restore registers\r
729         pop   si\r
730         mov   sp,bp                       ; dealloc local variables\r
731         pop   bp\r
732         ret\r
733 _x_put_pbm_clipx  endp\r
734 \r
735 \r
736 \r
737 ;----------------------------------------------------------------------\r
738 ; x_put_pbm_clipy - Write a planar bitmap from system ram to video ram\r
739 ;                    with clipping in y direction only. similar to\r
740 ;                    "x_put_pbm".\r
741 ;\r
742 ; See Also:  x_put_pbm,x_put_pbm_clipx,x_put_pbm_clipxy\r
743 ;\r
744 ; Clipping region variables: TopClip,BottomClip\r
745 ;\r
746 ; Written by Themie Gouthas\r
747 ;----------------------------------------------------------------------\r
748 _x_put_pbm_clipy  proc\r
749 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
750 LOCAL   Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk\r
751         push  bp\r
752         mov   bp,sp\r
753         sub   sp,LocalStk                 ; Create space for local variables\r
754         push  si\r
755         push  di\r
756         push  ds\r
757         cld\r
758 \r
759         les   si,[Bitmap]\r
760 \r
761         xor   bh,bh\r
762         mov   bl,byte ptr es:[si+1]   ; BX = height\r
763         ;mov   [Height],bx\r
764 \r
765         xor   ah,ah\r
766         mov   al,byte ptr es:[si]     ; AX = width\r
767         mov   [Width],ax\r
768 \r
769         mov   cx,ax                       ; Save AX\r
770         mul   bx                          ; AX = AX*BX = bytes/plane\r
771         mov   [PlaneInc],ax               ;  save as PlaneInc\r
772         mov   ax,cx                       ; Restore AX\r
773 \r
774         mov   di,[X]\r
775         mov   cx,di\r
776         and   cx,3\r
777         shr   di,2\r
778 \r
779         ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
780 \r
781         mov   dx,[_TopClip]           ; Compare u.l. Y coord with Top\r
782         sub   dx,[Y]                  ; clipping border\r
783         jle   @@NotTopClip            ; jump if VBM not clipped from above\r
784         cmp   dx,bx\r
785         jnl   @@NotVisible            ; jump if VBM is completely obscured\r
786         mov   [TopRow],dx\r
787         sub   bx,dx\r
788         add   [Y],dx\r
789         jmp   short @@VertClipDone\r
790 \r
791         ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
792 \r
793 @@NotVisible:\r
794         mov   ax,1\r
795         pop   ds                          ; restore data segment\r
796         pop   di                          ; restore registers\r
797         pop   si\r
798         mov   sp,bp                       ; dealloc local variables\r
799         pop   bp\r
800         ret\r
801 \r
802         ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
803 \r
804 @@NotTopClip:\r
805         mov   dx,[_BottomClip]\r
806         sub   dx,[Y]\r
807         js    @@NotVisible\r
808         mov   [TopRow],0\r
809         cmp   dx,bx\r
810         jg    @@VertClipDone\r
811         inc   dx\r
812         mov   bx,dx\r
813 \r
814 @@VertClipDone:\r
815 \r
816         mov   [Height],bx                 ; Calculate relative offset in data\r
817         mul   [TopRow]                    ;  of first visible scanline\r
818         add   ax,2                        ; Skip dimension bytes in source\r
819         add   si,ax                       ; Skip top rows that arent visible\r
820 \r
821 \r
822         mov   ax,[Y]                      ; Calculate screen row\r
823         mov   bx,[_ScrnLogicalByteWidth]  ;  by mult. Y coord by Screen\r
824         mul   bx                          ;  width then adding screen offset\r
825         add   di,ax\r
826         add   di,[ScrnOffs]\r
827         sub   bx,[Width]                  ; calculate difference from end of\r
828         mov   [LineInc],bx                ; b.m. in curr line to beginning of\r
829                                           ; b.m. on next scan line\r
830         mov   ax,es                       ; copy ES to DS\r
831         mov   ds,ax\r
832         mov   ax,SCREEN_SEG               ; Point ES to VGA segment\r
833         mov   es,ax\r
834 \r
835         mov   ah,11h                      ; Set up initial plane mask\r
836         shl   ah,cl\r
837 \r
838         mov   dx,SC_INDEX                 ; Prepare VGA for cpu to video writes\r
839         mov   al,MAP_MASK\r
840         out   dx,al\r
841         inc   dx\r
842         mov   bh,4                        ; Set plane counter to 4\r
843 @@PlaneLoop:\r
844         push  di                          ; Save bitmap's start dest. offset\r
845         push  si                          ; Save Bitmaps data offset\r
846         mov   bl,byte ptr [Height]        ; Reset row counter (BL)\r
847         mov   al,ah\r
848         out   dx,al                       ; set vga write plane\r
849 @@RowLoop:\r
850         mov   cl,byte ptr [Width]         ; Reset Column counter cl\r
851         shr   cl,1\r
852         rep   movsw                       ; Copy a complete row\r
853         adc   cl,0\r
854         rep   movsb\r
855 \r
856         add   di,[LineInc]                ; Move to next row\r
857         dec   bl                          ; decrement row counter\r
858         jnz   @@RowLoop                   ; Jump if more rows left\r
859         pop   si                          ; Restore SI and set to offset of\r
860         add   si,[PlaneInc]               ; first vis pixel in next plane data\r
861         pop   di                          ; Restore bitmaps start dest byte\r
862         rol   ah,1                        ; Shift mask for next plane\r
863         adc   di,0                        ; if carry increment screen offset\r
864         dec   bh                          ; Decrement plane counter\r
865         jnz   @@PlaneLoop                 ; Jump if more planes left\r
866 \r
867         xor   ax,ax\r
868         pop   ds                          ; restore data segment\r
869         pop   di                          ; restore registers\r
870         pop   si\r
871         mov   sp,bp                       ; dealloc local variables\r
872         pop   bp\r
873         ret\r
874 _x_put_pbm_clipy   endp\r
875 \r
876 \r
877 ;----------------------------------------------------------------------\r
878 ; x_put_pbm_clipxy - Write a planar bitmap from system ram to video ram\r
879 ;                    with clipping in x and y directions. similar to\r
880 ;                    "x_put_pbm".\r
881 ;\r
882 ; See Also:  x_put_pbm,x_put_pbm_clipy,x_put_pbm_clipx\r
883 ;\r
884 ; Clipping region variables: LeftClip,RightClip,TopClip,BottomClip\r
885 ;\r
886 ; Written by Themie Gouthas\r
887 ;----------------------------------------------------------------------\r
888 _x_put_pbm_clipxy  proc\r
889 ARG X:word,Y:word,ScrnOffs:word,Bitmap:dword\r
890 LOCAL   Plane:byte,CType,LeftSkip,DataInc,Width,Height,TopRow,LineInc,PlaneInc:word=LocalStk\r
891         push  bp\r
892         mov   bp,sp\r
893         sub   sp,LocalStk                 ; Create space for local variables\r
894         push  si\r
895         push  di\r
896         push  ds\r
897         cld\r
898 \r
899         les   si,[Bitmap]\r
900 \r
901         xor   ax,ax\r
902         mov   [CType],ax\r
903         mov   al,byte ptr es:[si]         ; AX = width\r
904         xor   bh,bh\r
905         mov   bl,byte ptr es:[si+1]       ; BX = height\r
906 \r
907         mov   cx,ax                       ; Save AX\r
908         mul   bx                          ; AX = AX*BX = bytes/plane\r
909         mov   [PlaneInc],ax               ;  save as PlaneInc\r
910         mov   ax,cx                       ; Restore AX\r
911 \r
912 \r
913         mov   di,[X]                      ; DI = X coordinate of dest.\r
914         mov   cx,di                       ; save in CX\r
915         sar   di,2                        ; convert to address byte\r
916 \r
917 \r
918                 ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
919 \r
920         mov   dx,[_TopClip]           ; Compare u.l. Y coord with Top\r
921         sub   dx,[Y]                  ; clipping border\r
922         jle   @@NotTopClip            ; jump if VBM not clipped from above\r
923         cmp   dx,bx\r
924         jnl   @@NotVisible            ; jump if VBM is completely obscured\r
925         mov   [TopRow],dx\r
926         sub   bx,dx\r
927         add   [Y],dx\r
928         jmp   short @@VertClipDone\r
929 \r
930         ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
931 \r
932 @@NotVisible:\r
933         mov   ax,1\r
934         pop   ds                          ; restore data segment\r
935         pop   di                          ; restore registers\r
936         pop   si\r
937         mov   sp,bp                       ; dealloc local variables\r
938         pop   bp\r
939         ret\r
940 \r
941         ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
942 \r
943 @@NotTopClip:\r
944         mov   dx,[_BottomClip]\r
945         sub   dx,[Y]\r
946         js    @@NotVisible\r
947         mov   [TopRow],0\r
948         cmp   dx,bx\r
949         jg    @@VertClipDone\r
950         inc   dx\r
951         mov   bx,dx\r
952 \r
953 @@VertClipDone:\r
954 \r
955         ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
956 \r
957         mov   dx,[_LeftClip]\r
958         sub   dx,di\r
959         jle   @@NotLeftClip\r
960         cmp   dx,ax\r
961         jnl   @@NotVisible\r
962 \r
963         add   di,dx\r
964         mov   [LeftSkip],dx\r
965         mov   [DataInc],dx\r
966         sub   ax,dx\r
967         mov   [CType],1\r
968         jmp   short @@HorizClipDone\r
969 \r
970         ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
971 \r
972 @@NotLeftClip:\r
973         mov   dx,[_RightClip]\r
974         sub   dx,di\r
975         js    @@NotVisible\r
976         mov   [LeftSkip],0\r
977         mov   [DataInc],0\r
978         cmp   dx,ax\r
979         jge   @@HorizClipDone       ; was jg\r
980         inc   dx\r
981         sub   ax,dx\r
982         mov   [DataInc],ax\r
983         mov   ax,dx\r
984         mov   [CType],-1\r
985 \r
986 @@HorizClipDone:\r
987 \r
988 \r
989 \r
990         mov   [Width],ax                  ; Save width and height of clipped\r
991         mov   [Height],bx                 ;  image\r
992 \r
993         add   ax,[DataInc]                ; AX = original width of image\r
994         mul   [TopRow]                    ; Calculate bytes in clipped top\r
995         add   si,ax                       ;  rows\r
996         add   si,2                        ; Skip dimension bytes in source\r
997         add   si,[LeftSkip]               ; Skip pixels in front of row that\r
998                                           ;  are clipped\r
999 \r
1000         mov   bx,[_ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width\r
1001         mov   dx,bx                       ; BX - Width of image = No. bytes\r
1002         sub   dx,[Width]                  ;  to first byte of next screen\r
1003         mov   [LineInc],dx                ;  row.\r
1004 \r
1005         mov   ax,[Y]                      ; Calculate screen start row\r
1006         mul   bx                          ;  then adding screen offset\r
1007         add   di,ax\r
1008         add   di,[ScrnOffs]\r
1009         mov   ax,es                       ; copy ES to DS\r
1010         mov   ds,ax\r
1011         mov   ax,SCREEN_SEG               ; Point ES to VGA segment\r
1012         mov   es,ax\r
1013 \r
1014 \r
1015 \r
1016         and   cx,3\r
1017         mov   ah,11h                      ; Set up initial plane mask\r
1018         shl   ah,cl\r
1019 \r
1020         mov   dx,SC_INDEX                 ; Prepare VGA for cpu to video writes\r
1021         mov   al,MAP_MASK\r
1022         out   dx,al\r
1023         inc   dx\r
1024         mov   [Plane],4                   ; Set plane counter to 4\r
1025         mov   bh,byte ptr [Width]         ; set bh to width for fast looping\r
1026 @@PlaneLoop:\r
1027         push  di                          ; Save bitmap's start dest. offset\r
1028         push  si\r
1029         mov   bl,byte ptr [Height]        ; Reset row counter (BL)\r
1030         mov   al,ah\r
1031         out   dx,al                       ; set vga write plane\r
1032 @@RowLoop:\r
1033         mov   cl,bh                       ; Reset Column counter cl\r
1034         shr   cl,1\r
1035         rep   movsw                       ; Copy a complete row\r
1036         adc   cl,0\r
1037         rep   movsb\r
1038         add   si,[DataInc]                ; Move to next source row\r
1039         add   di,[LineInc]                ; Move to next screen row\r
1040         dec   bl                          ; decrement row counter\r
1041         jnz   @@RowLoop                   ; Jump if more rows left\r
1042         pop   si                          ; Restore SI and set to offset of\r
1043         add   si,[PlaneInc]               ; first vis pixel in next plane data\r
1044         pop   di                          ; Restore bitmaps start dest byte\r
1045         rol   ah,1                        ; Shift mask for next plane\r
1046 \r
1047         ; Plane Transition (A HACK but it works!)\r
1048 \r
1049         jnb   @@Nocarry                   ; Jump if not plane transition\r
1050         mov   bl,ah                       ; Save Plane Mask\r
1051         mov   ax,[CType]                  ; set AX to clip type inc variable\r
1052         add   bh,al                       ; Update advancing variables\r
1053         sub   [DataInc],ax                ;\r
1054         sub   [LineInc],ax                ;\r
1055         cmp   al,0                        ; What type of clip do we have\r
1056         mov   ah,bl                       ;   restore Plane mask\r
1057         jg    @@RightAdvance              ; jump on a right clip!\r
1058         inc   di                          ; otherwise increment DI\r
1059         jmp   @@Nocarry\r
1060 @@RightAdvance:\r
1061         dec si\r
1062 @@Nocarry:\r
1063         dec   [Plane]                     ; Decrement plane counter\r
1064         jnz   @@PlaneLoop                 ; Jump if more planes left\r
1065 \r
1066         xor   ax,ax\r
1067         pop   ds                          ; restore data segment\r
1068         pop   di                          ; restore registers\r
1069         pop   si\r
1070         mov   sp,bp                       ; dealloc local variables\r
1071         pop   bp\r
1072         ret\r
1073 _x_put_pbm_clipxy  endp\r
1074 \r
1075         end\r
1076 \r
1077 \r
1078 \r