]> 4ch.mooo.com Git - 16.git/blob - 16/xlib/xvbitmap.asm
cleaned up the repo from debugging watcom2 ^^
[16.git] / 16 / xlib / xvbitmap.asm
1 ;-----------------------------------------------------------------------\r
2 ; MODULE XVBITMAP\r
3 ;\r
4 ; Video Bitmap functions - Video 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 COMMENT $\r
18 \r
19 The XVBITMAP module implements yet another type of bitmap to complement\r
20 planar and compiled bitmaps, VRAM based bitmaps. If a 4 cylinder car is\r
21 analagous to planar bitmaps, that is thrifty on memory consumption but low\r
22 performance and and a V8 is analagous to Compiled bitmaps, memory guzzlers\r
23 that really fly, then VRAM based bitmaps are the 6 cylinder modest performers\r
24 with acceptable memory consumption.\r
25 \r
26 To summarise their selling points, VBM's are moderately fast with fair memory\r
27 consumption, and unlike compiled bitmaps, can be clipped. The disadvantages\r
28 are that they are limited by the amount of free video ram and have a complex\r
29 structure.\r
30 \r
31 The VRAM bitmap format is rather complex consisting of components stored in\r
32 video ram and components in system ram working together. This complexity\r
33 necessitates the existence of a creation function "x_make_vbm" which takes\r
34 an input linear bitmap and generates the equivalent VBM (VRAM Bit Map).\r
35 \r
36 VBM structure:\r
37 \r
38       WORD  0   Size          Total size of this VBM structure in bytes\r
39       WORD  1   ImageWidth    Width in bytes of the image (for all alignments)\r
40       WORD  2   ImageHeight   Height in scan lines of the image\r
41 \r
42       WORD  3 Alignment 0  ImagePtr   Offset in VidRAM of this aligned image\r
43    +--WORD  4              MaskPtr    Offset (within this structure's DS) of\r
44    |   .                               alignment masks\r
45    |   .\r
46    |   .\r
47    |  WORD  9 Alignment 3  ImagePtr   Offset in VidRAM of this aligned image\r
48   +|--WORD 10              MaskPtr    Offset (within this structure's DS) of\r
49   ||                                   alignment masks\r
50   ||\r
51   |+->BYTE 21 (WORD 11)                -------+-- Image masks for alignment 0\r
52   |   .                                       |\r
53   |   .                                       |\r
54   |   BYTE  21 + ImageWidth*ImageHeight  -----+\r
55   |\r
56   |   .\r
57   |   . (similaly for alignments 1 - 2 )\r
58   |   .\r
59   |\r
60   +-->BYTE  21 + 3*ImageWidth*ImageHeight + 1-+-- Image masks for alignment 3\r
61       .                                       |\r
62       .                                       |\r
63       BYTE  21 + 4*(ImageWidth*ImageHeight) --+\r
64 \r
65       .\r
66       .\r
67       << Similarly for alignments 2 and 3 >>\r
68       .\r
69       .\r
70       BYTE 21 + 4*(ImageWidth*ImageHeight)\r
71   -------------\r
72 \r
73   (And dont forget the corresponding data in video ram)\r
74 \r
75 $\r
76 \r
77 \r
78 include xlib.inc\r
79 include xvbitmap.inc\r
80 \r
81 VBM_info_struc struc\r
82   Size        dw ?\r
83   ImageWidth  dw ?\r
84   ImageHeight dw ?\r
85 ;  AlignData   dw ?\r
86 VBM_info_struc ends\r
87 \r
88 AlignData equ 6\r
89 \r
90 VBM_alignment_struc struc\r
91   ImagePtr    dw ?\r
92   MaskPtr     dw ?\r
93 VBM_alignment_struc ends\r
94 \r
95 \r
96         .code\r
97 \r
98 \r
99 ;----------------------------------------------------------------------\r
100 ; x_store_vbm_image\r
101 ;\r
102 ;  Store the linear bitmap in video RAM using the specified alignment and\r
103 ;  start address. Returns number video ram bytes used.\r
104 ;\r
105 ;  THIS FUNCTION IS FOR USE BY x_make_masked_vbm\r
106 ;\r
107 ; Prototype:\r
108 ;\r
109 ;  x_store_vbm_image(unsigned int vramoffs, unsigned int Align,\r
110 ;                char far *lbm);\r
111 ;\r
112 ;\r
113 ; Written by Themie Gouthas\r
114 ;----------------------------------------------------------------------\r
115 _x_store_vbm_image  proc\r
116         ARG VramOffs:word,Align:word,LBitmap:dword\r
117         LOCAL BMWidth:byte=LocalStk\r
118         push  bp\r
119         mov   bp,sp\r
120         sub   sp,LocalStk                 ; Create space for local variables\r
121         push  si\r
122         push  di\r
123         push  ds\r
124         cld\r
125 \r
126         mov   ax,SCREEN_SEG               ; Point ES to screen segment\r
127         mov   es,ax\r
128         mov   di,[VramOffs]               ; Point ES:DI to VRAM dest start\r
129         mov   bx,[Align]                  ; Set BL to first pixel plane align\r
130         and   bl,03h\r
131 \r
132         lds   si,[LBitmap]                ; DS:SI -> source linear Bitmap\r
133         lodsw                             ; Al = B.M. width (bytes) AH = B.M.\r
134         mov   bh,ah                       ; Save source bitmap dimensions\r
135         mov   [BMWidth],al                ;\r
136 \r
137         mov   dx,SC_INDEX                 ; Initialize Map Mask for plane\r
138         mov   al,MAP_MASK                 ; selection\r
139         out   dx,al\r
140         inc   dx\r
141         xor   ch,ch                       ; clear CH\r
142 @@RowLoop:\r
143         mov   cl,bl                       ; Set initial plane for current\r
144         mov   ah,11h                      ; allignment\r
145         shl   ah,cl\r
146 \r
147         mov   cl,[BMWidth]                ; Initialize column counter\r
148 @@ColLoop:\r
149         mov   al,ah\r
150         out   dx,al                       ; set vga write plane\r
151         lodsb                             ; load next LBM pixel\r
152         mov   es:[di],al                  ; store it in Video Ram\r
153         shl   ah,1                        ; rotate plane mask\r
154         jnb   @@NoAddrIncr                ; Time to increment dest address ?\r
155         inc   di                          ; Yes: increment addr and reset\r
156         mov   ah,11h                      ;  plane mask to plane 0\r
157 @@NoAddrIncr:\r
158         loop  @@ColLoop                   ; Loop to next pixel column\r
159         cmp   ah,11h\r
160 ;       je    @@skip\r
161         inc   di                          ; Increment dest addr\r
162 ;@@skip:\r
163         dec   bh                          ; Decrement row counter\r
164         jnz   @@RowLoop                   ; Jump if more rows to go\r
165         mov   ax,di                       ; calculate video RAM consumed and\r
166         sub   ax,[VramOffs]               ;   return value\r
167 \r
168         pop   ds                          ; restore data segment\r
169         pop   di                          ; restore registers\r
170         pop   si\r
171         mov   sp,bp                       ; dealloc local variables\r
172         pop   bp\r
173         ret\r
174 _x_store_vbm_image  endp\r
175 \r
176 \r
177 _x_put_masked_vbm  proc\r
178         ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword\r
179         LOCAL VBMWidth:word,VBMHeight:word,NextLineIncr:word=LocalStk\r
180         push  bp\r
181         mov   bp,sp\r
182         sub   sp,LocalStk                 ; Create space for local variables\r
183         push  si\r
184         push  di\r
185         push  ds\r
186         cld\r
187 \r
188         mov   ax,SCREEN_SEG               ; Point es to VGA segment\r
189         mov   es,ax\r
190         mov   ax,[Y]                      ; Calculate dest screen row\r
191         mov   cx,[_ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen\r
192         mul   cx                          ;  width then adding screen offset\r
193 \r
194         mov   di,[ScrnOffs]               ;  store result in DI\r
195         add   di,ax\r
196         mov   si,[X]                      ; Load X coord into CX and make a\r
197         mov   bx,si                       ;  copy in DX\r
198         shr   bx,2                        ; Find starting byte in dest row\r
199         add   di,bx                       ;  add to DI giving screen offset of\r
200                                           ;  first pixel's byte\r
201 \r
202         and   si,3                        ; get pixel alignment in si\r
203 \r
204         lds   bx,[SrcVBM]                 ; DS:BX -> VBM data structure\r
205         shl   si,2                        ; si = offset of data  for curr\r
206                                           ; alignment\r
207 \r
208         mov ax,word ptr [bx+ImageHeight]  ; Get image height\r
209         mov   [VBMHeight],ax\r
210         mov ax,word ptr [bx+ImageWidth]   ; Get image width\r
211         mov   [VBMWidth],ax\r
212 \r
213         sub   cx,ax                       ; NextLineIncr = bytes to the begin.\r
214         mov   [NextLineIncr],cx           ;  of bitmaps next row on screen\r
215         mov   dx,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data\r
216         mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap\r
217         mov   si,dx\r
218 \r
219         mov   dx,GC_INDEX                 ; Set bit mask for all bits from\r
220         mov   ax,BIT_MASK                 ; VGA latches and none from CPU\r
221         out   dx,ax\r
222 \r
223         mov   dx,SC_INDEX                 ; Point SC register to map mask\r
224         mov   al,MAP_MASK                 ; in preperation for masking data\r
225         out   dx,al\r
226         inc   dx                          ; Point dx to SC data register\r
227         mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter\r
228 \r
229 @@RowLoop:\r
230         mov   cx,[VBMWidth]               ; Width in bytes across\r
231 \r
232 @@ColumnLoop:\r
233         lodsb\r
234         out   dx,al\r
235         mov   al,es:[bx]                  ; load latches from source bitmap\r
236         stosb                             ; store latches to dest. bitmap\r
237         inc   bx\r
238         loop  @@ColumnLoop\r
239 \r
240         add   di,[NextLineIncr]           ; point to start of next dest row\r
241         dec   ah                          ; decrement scan line counter\r
242         jnz   @@RowLoop                   ; jump if more scanlines left\r
243 \r
244         mov   dx,GC_INDEX+1               ; Restore bitmask to the default -\r
245         mov   al,0ffh                     ;  all data from cpu\r
246         out   dx,al\r
247 \r
248         pop   ds                          ; restore data segment\r
249         pop   di                          ; restore registers\r
250         pop   si\r
251         mov   sp,bp                       ; dealloc local variables\r
252         pop   bp\r
253         ret\r
254 _x_put_masked_vbm  endp\r
255 \r
256 \r
257 _x_put_masked_vbm_clipx  proc\r
258 ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword\r
259 LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,NextLineIncr:word=LocalStk\r
260         push  bp\r
261         mov   bp,sp\r
262         sub   sp,LocalStk             ; Create space for local variables\r
263         push  si\r
264         push  di\r
265         push  ds\r
266         cld\r
267 \r
268         mov   di,[X]                  ; load X coord int DI and make a\r
269         mov   si,di                   ;  copy in SI\r
270         sar   di,2                    ; Find Byte offset of X coord\r
271 \r
272         and   si,3                    ; Calculate pixels plane alignment\r
273         shl   si,2                    ; Prepare to lookup mask & data\r
274         les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data\r
275 \r
276         mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX\r
277 \r
278 \r
279 \r
280         ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
281 \r
282         mov   dx,[_LeftClip]\r
283         sub   dx,di\r
284         jle   @@NotLeftClip\r
285         cmp   dx,cx\r
286         jnl   @@NotVisible\r
287         add   di,dx\r
288         mov   [LeftSkip],dx\r
289         mov   [DataInc],dx\r
290         sub   cx,dx\r
291         jmp   short @@HorizClipDone\r
292 \r
293         ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
294 \r
295 @@NotVisible:\r
296         mov   ax,1\r
297         pop   ds                          ; restore data segment\r
298         pop   di                          ; restore registers\r
299         pop   si\r
300         mov   sp,bp                       ; dealloc local variables\r
301         pop   bp\r
302         ret\r
303 \r
304         ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
305 \r
306 @@NotLeftClip:\r
307         mov   dx,[_RightClip]\r
308         sub   dx,di\r
309         js    @@NotVisible\r
310         mov   [LeftSkip],0\r
311         mov   [DataInc],0\r
312         cmp   dx,cx\r
313         jge   @@HorizClipDone\r
314         inc   dx\r
315         sub   cx,dx\r
316         mov   [DataInc],cx\r
317         mov   cx,dx\r
318 \r
319 @@HorizClipDone:\r
320 \r
321 \r
322         add   di,[ScrnOffs]           ; Add the current page offset\r
323         mov   [VBMWidth],cx\r
324         mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX\r
325         mov   [VBMHeight],ax\r
326 \r
327 \r
328         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
329 \r
330         mov   ax,[Y]                      ; Calculate dest screen row\r
331         mov   cx,[_ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen\r
332         mul   cx                          ;  width then adding screen offset\r
333         add   di,ax                       ; Add Dest Screen Row to di\r
334         sub   cx,[VBMWidth]\r
335         mov   [NextLineIncr],cx\r
336 \r
337         mov   ax,es                       ; copy ES to DS\r
338         mov   ds,ax\r
339         mov   ax,SCREEN_SEG               ; Point es to VGA segment\r
340         mov   es,ax\r
341 \r
342         mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data\r
343         mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap\r
344         mov   si,ax\r
345 \r
346         mov   ax,[LeftSkip]               ; Skip data/mask bytes in\r
347         add   bx,ax                       ; each row that have been clipped\r
348         add   si,ax                       ; by the L.H.S border\r
349 \r
350 \r
351         mov   dx,GC_INDEX                 ; Set bit mask for all bits from\r
352         mov   ax,BIT_MASK                 ; VGA latches and none from CPU\r
353         out   dx,ax\r
354         mov   dx,SC_INDEX                 ; Point SC register to map mask\r
355         mov   al,MAP_MASK                 ; in preperation for masking data\r
356         out   dx,al\r
357         inc   dx                          ; Point dx to SC data register\r
358         mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter\r
359 \r
360 @@RowLoop:\r
361         mov   cx,[VBMWidth]               ; Width in bytes across\r
362 \r
363 @@ColumnLoop:\r
364         lodsb\r
365         out   dx,al\r
366         mov   al,es:[bx]                  ; load latches from source bitmap\r
367         stosb                             ; store latches to dest. bitmap\r
368         inc   bx\r
369         loop  @@ColumnLoop\r
370         add   bx,[DataInc]\r
371         add   si,[DataInc]\r
372         add   di,[NextLineIncr]           ; point to start of next dest row\r
373         dec   byte ptr ah                 ; decrement scan line counter\r
374         jnz   @@RowLoop                   ; jump if more scanlines left\r
375 \r
376         mov   dx,GC_INDEX+1               ; Restore bitmask to the default -\r
377         mov   al,0ffh                     ;  all data from cpu\r
378         out   dx,al\r
379         xor   ax,ax\r
380         pop   ds                          ; restore data segment\r
381         pop   di                          ; restore registers\r
382         pop   si\r
383         mov   sp,bp                       ; dealloc local variables\r
384         pop   bp\r
385         ret\r
386 _x_put_masked_vbm_clipx  endp\r
387 \r
388 \r
389 _x_put_masked_vbm_clipy  proc\r
390 ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword\r
391 LOCAL VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk\r
392         push  bp\r
393         mov   bp,sp\r
394         sub   sp,LocalStk                 ; Create space for local variables\r
395         push  si\r
396         push  di\r
397         push  ds\r
398         cld\r
399 \r
400         mov   di,[X]                  ; load X coord int DI and make a\r
401         mov   si,di                   ;  copy in SI\r
402 \r
403 \r
404         and   si,3                    ; Calculate pixels plane alignment\r
405         shl   si,2                    ; Prepare to lookup mask & data\r
406         les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data\r
407 \r
408 \r
409         mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX\r
410 \r
411 \r
412 \r
413         ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
414 \r
415         mov   dx,[_TopClip]           ; Compare u.l. Y coord with Top\r
416         sub   dx,[Y]                  ; clipping border\r
417         jle   @@NotTopClip            ; jump if VBM not clipped from above\r
418         cmp   dx,ax\r
419         jnl   @@NotVisible            ; jump if VBM is completely obscured\r
420         mov   [TopRow],dx\r
421         sub   ax,dx\r
422         add   [Y],dx\r
423         jmp   short @@VertClipDone\r
424 \r
425         ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
426 \r
427 @@NotVisible:\r
428         mov   ax,1\r
429         pop   ds                          ; restore data segment\r
430         pop   di                          ; restore registers\r
431         pop   si\r
432         mov   sp,bp                       ; dealloc local variables\r
433         pop   bp\r
434         ret\r
435 \r
436         ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
437 \r
438 @@NotTopClip:\r
439         mov   dx,[_BottomClip]\r
440         sub   dx,[Y]\r
441         js    @@NotVisible\r
442         mov   [TopRow],0\r
443         cmp   dx,ax\r
444         jg    @@VertClipDone\r
445         inc   dx\r
446         mov   ax,dx\r
447 \r
448 @@VertClipDone:\r
449 \r
450 \r
451         shr   di,2                    ; Find Byte offset of X coord\r
452         add   di,[ScrnOffs]           ; Add the current page offset\r
453         mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX\r
454         mov   [VBMWidth],cx\r
455         mov   [VBMHeight],ax\r
456 \r
457         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
458 \r
459         mov   ax,[Y]                      ; Calculate dest screen row\r
460         mov   cx,[_ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen\r
461         mul   cx                          ;  width then adding screen offset\r
462         add   di,ax                       ; Add Dest Screen Row to di\r
463         sub   cx,[VBMWidth]\r
464         mov   [NextLineIncr],cx\r
465 \r
466         mov   ax,es                       ; copy ES to DS\r
467         mov   ds,ax\r
468         mov   ax,SCREEN_SEG               ; Point es to VGA segment\r
469         mov   es,ax\r
470 \r
471         mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data\r
472         mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap\r
473         mov   si,ax\r
474 \r
475 \r
476 \r
477         mov   ax,[VBMWidth]               ; Increment DS:BX and DS:SI to\r
478         mul   [TopRow]                    ;  skip image/mask data that has\r
479         add   bx,ax                       ;  been clipped by the top border\r
480         add   si,ax\r
481 \r
482 \r
483         mov   dx,GC_INDEX                 ; Set bit mask for all bits from\r
484         mov   ax,BIT_MASK                 ; VGA latches and none from CPU\r
485         out   dx,ax\r
486         mov   dx,SC_INDEX                 ; Point SC register to map mask\r
487         mov   al,MAP_MASK                 ; in preperation for masking data\r
488         out   dx,al\r
489         inc   dx                          ; Point dx to SC data register\r
490         mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter\r
491 \r
492 @@RowLoop:\r
493         mov   cx,[VBMWidth]               ; Width in bytes across\r
494 \r
495 @@ColumnLoop:\r
496         lodsb\r
497         out   dx,al\r
498         mov   al,es:[bx]                  ; load latches from source bitmap\r
499         stosb                             ; store latches to dest. bitmap\r
500         inc   bx\r
501         loop  @@ColumnLoop\r
502         add   di,[NextLineIncr]           ; point to start of next dest row\r
503         dec   byte ptr ah                 ; decrement scan line counter\r
504         jnz   @@RowLoop                   ; jump if more scanlines left\r
505 \r
506         mov   dx,GC_INDEX+1               ; Restore bitmask to the default -\r
507         mov   al,0ffh                     ;  all data from cpu\r
508         out   dx,al\r
509 \r
510         xor   ax,ax\r
511         pop   ds                          ; restore data segment\r
512         pop   di                          ; restore registers\r
513         pop   si\r
514         mov   sp,bp                       ; dealloc local variables\r
515         pop   bp\r
516         ret\r
517 _x_put_masked_vbm_clipy  endp\r
518 \r
519 _x_put_masked_vbm_clipxy  proc\r
520 ARG X:word,Y:word,ScrnOffs:word,SrcVBM:dword\r
521 LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,TopRow,NextLineIncr:word=LocalStk\r
522         push  bp\r
523         mov   bp,sp\r
524         sub   sp,LocalStk                 ; Create space for local variables\r
525         push  si\r
526         push  di\r
527         push  ds\r
528         cld\r
529 \r
530         mov   di,[X]                  ; load X coord int DI and make a\r
531         mov   si,di                   ;  copy in SI\r
532         sar   di,2                    ; Find Byte offset of X coord\r
533         and   si,3                    ; Calculate pixels plane alignment\r
534         shl   si,2                    ; Prepare to lookup mask & data\r
535         les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data\r
536 \r
537         mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX\r
538         mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX\r
539 \r
540 \r
541 \r
542         ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;\r
543 \r
544         mov   dx,[_TopClip]           ; Compare u.l. Y coord with Top\r
545         sub   dx,[Y]                  ; clipping border\r
546         jle   @@NotTopClip            ; jump if VBM not clipped from above\r
547         cmp   dx,ax\r
548         jnl   @@NotVisible            ; jump if VBM is completely obscured\r
549         mov   [TopRow],dx\r
550         sub   ax,dx\r
551         add   [Y],dx\r
552         jmp   short @@VertClipDone\r
553 \r
554         ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;\r
555 \r
556 @@NotVisible:\r
557         mov   ax,1\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 \r
565         ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
566 \r
567 @@NotTopClip:\r
568         mov   dx,[_BottomClip]\r
569         sub   dx,[Y]\r
570         js    @@NotVisible\r
571         mov   [TopRow],0\r
572         cmp   dx,ax\r
573         jg    @@VertClipDone\r
574         inc   dx\r
575         mov   ax,dx\r
576 \r
577 @@VertClipDone:\r
578 \r
579         ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
580 \r
581 \r
582         mov   dx,[_LeftClip]\r
583         sub   dx,di\r
584         jle   @@NotLeftClip\r
585         cmp   dx,cx\r
586         jnl   @@NotVisible\r
587         add   di,dx\r
588         mov   [LeftSkip],dx\r
589         mov   [DataInc],dx\r
590         sub   cx,dx\r
591         jmp   short @@HorizClipDone\r
592 \r
593         ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;\r
594 \r
595 @@NotLeftClip:\r
596         mov   dx,[_RightClip]\r
597         sub   dx,di\r
598         js    @@NotVisible\r
599         mov   [LeftSkip],0\r
600         mov   [DataInc],0\r
601         cmp   dx,cx\r
602         jge    @@HorizClipDone\r
603         inc   dx\r
604         sub   cx,dx\r
605         mov   [DataInc],cx\r
606         mov   cx,dx\r
607 \r
608 @@HorizClipDone:\r
609 \r
610         add   di,[ScrnOffs]           ; Add the current page offset\r
611         mov   [VBMWidth],cx\r
612         mov   [VBMHeight],ax\r
613         ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
614 \r
615         mov   ax,[Y]                      ; Calculate dest screen row\r
616         mov   cx,[_ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen\r
617         mul   cx                          ;  width then adding screen offset\r
618         add   di,ax                       ; Add Dest Screen Row to di\r
619         sub   cx,[VBMWidth]\r
620         mov   [NextLineIncr],cx\r
621 \r
622         mov   ax,es                       ; copy ES to DS\r
623         mov   ds,ax\r
624         mov   ax,SCREEN_SEG               ; Point es to VGA segment\r
625         mov   es,ax\r
626 \r
627         mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data\r
628         mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap\r
629         mov   si,ax\r
630 \r
631 \r
632 \r
633         mov   ax,[VBMWidth]               ; Increment DS:BX and DS:SI to\r
634         add   ax,[DataInc]                ;  skip image/mask data that has\r
635         mul   [TopRow]                    ;  been clipped by the top border\r
636         add   ax,[LeftSkip]               ; Skip also data/mask bytes in\r
637         add   bx,ax                       ; each row that have been clipped\r
638         add   si,ax                       ; by the L.H.S border\r
639 \r
640 \r
641         mov   dx,GC_INDEX                 ; Set bit mask for all bits from\r
642         mov   ax,BIT_MASK                 ; VGA latches and none from CPU\r
643         out   dx,ax\r
644         mov   dx,SC_INDEX                 ; Point SC register to map mask\r
645         mov   al,MAP_MASK                 ; in preperation for masking data\r
646         out   dx,al\r
647         inc   dx                          ; Point dx to SC data register\r
648         mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter\r
649 \r
650 @@RowLoop:\r
651         mov   cx,[VBMWidth]               ; Width in bytes across\r
652 \r
653 @@ColumnLoop:\r
654         lodsb\r
655         out   dx,al\r
656         mov   al,es:[bx]                  ; load latches from source bitmap\r
657         stosb                             ; store latches to dest. bitmap\r
658         inc   bx\r
659         loop  @@ColumnLoop\r
660         add   bx,[DataInc]\r
661         add   si,[DataInc]\r
662         add   di,[NextLineIncr]           ; point to start of next dest row\r
663         dec   byte ptr ah                 ; decrement scan line counter\r
664         jnz   @@RowLoop                   ; jump if more scanlines left\r
665 \r
666         mov   dx,GC_INDEX+1               ; Restore bitmask to the default -\r
667         mov   al,0ffh                     ;  all data from cpu\r
668         out   dx,al\r
669         xor   ax,ax\r
670         pop   ds                          ; restore data segment\r
671         pop   di                          ; restore registers\r
672         pop   si\r
673         mov   sp,bp                       ; dealloc local variables\r
674         pop   bp\r
675         ret\r
676 _x_put_masked_vbm_clipxy  endp\r
677 \r
678 \r
679         end\r
680 \r
681 \1a