|
|
1.1 root 1: ;---------------------------Module-Header------------------------------;
2: ; Module Name: rleblts.asm
3: ;
4: ; Copyright (c) 1992 Microsoft Corporation
5: ;-----------------------------------------------------------------------;
6: .386
7:
8: ifndef DOS_PLATFORM
9: .model small,c
10: else
11: ifdef STD_CALL
12: .model small,c
13: else
14: .model small,pascal
15: endif; STD_CALL
16: endif; DOS_PLATFORM
17:
18: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
19: assume fs:nothing,gs:nothing
20:
21: .xlist
22: include stdcall.inc ;calling convention cmacros
23: include i386\egavga.inc
24: include i386\strucs.inc
25: .list
26:
27: .code
28:
29: ;-------------------------------Macro-----------------------------------;
30: ; RleSetUp
31: ;
32: ; Set the EGA\VGA to write mode 2 (M_COLOR_WRITE). Initialize local vars
33: ;
34: ; Entry:
35: ; None
36: ; Returns:
37: ; ESI = pointer to the source bitmap
38: ;
39: ;-----------------------------------------------------------------------;
40:
41: RleSetUp macro
42:
43: cld
44:
45: mov dx,VGA_BASE + GRAF_ADDR
46: mov ax,(M_COLOR_WRITE shl 8) + GRAF_MODE
47: out dx,ax
48:
49: mov esi,pRleInfo
50: mov edi,[esi].RLE_prctlTrg
51: mov eax,[edi].xLeft
52: mov xStart,eax
53: mov eax,[esi].RLE_xBegin
54: mov xCurr,eax
55: mov eax,[edi].yBottom
56: dec eax
57: mov yCurr,eax
58:
59: mov eax,[esi].RLE_pulTranslate
60: mov pulXlate,eax
61: mov eax,[esi].RLE_prctlClip
62: mov prclClip,eax
63: mov eax,[esi].RLE_pjSrcBitsMax
64: mov pjSrcEnd,eax
65: mov ebx,[esi].RLE_pjTrg
66:
67: mov pjDst,ebx
68: mov esi,[esi].RLE_pjSrcBits
69: endm
70:
71: ;-------------------------------Macro-----------------------------------;
72: ; RleDelta
73: ;
74: ; Handle the Delta case.
75: ;
76: ; Entry:
77: ; ESI = pointer to the horz/vert offset of the source bitmap
78: ; Returns:
79: ; None
80: ;
81: ;-----------------------------------------------------------------------;
82:
83: RleDelta macro dest
84:
85: lodsw
86: movzx ecx,al
87: add xCurr,ecx ;x adjustment
88:
89: movzx eax,ah
90: sub yCurr,eax ;y adjustment
91:
92: mul lNextScan
93: sub pjDst,eax
94: jmp dest
95: endm
96:
97: ;-------------------------------Macro-----------------------------------;
98: ; RleExit
99: ;
100: ; Prepare the Rle routine to exit. Set the EGA/VGA to default write
101: ; mode. Save the current status in the RleInfo so we can continue
102: ; from where we left off if a complex clipping is encountered.
103: ;
104: ; Entry:
105: ; ESI = pointer pass the first run above the clipping rect
106: ; EBX = yCurr(y value of the first run above the clipping rect)
107: ; ECX = xCurr(x value of the first run above the clipping rect)
108: ; Returns:
109: ; None
110: ;
111: ;-----------------------------------------------------------------------;
112:
113: RleExit macro
114:
115: mov dx,VGA_BASE + GRAF_ADDR
116: mov ax,(M_PROC_WRITE shl 8) + GRAF_MODE
117: out dx,ax
118:
119: mov ax,0FF00h + GRAF_BIT_MASK
120: out dx,ax ;no mask
121:
122: mov edi,pRleInfo ;update for next call
123: dec esi
124: dec esi
125: mov [edi].RLE_pjSrcBits,esi
126: mov esi,[edi].RLE_prctlTrg
127: inc ebx ;make it exclusive
128: mov [esi].yBottom,ebx
129: mov eax,pjDst
130: mov [edi].RLE_pjTrg,eax
131: mov [edi].RLE_xBegin,ecx
132: endm
133:
134: ;-------------------------------Macro-----------------------------------;
135: ; Clip_Encoded
136: ;
137: ; Clip the current run in encoded mode against the clipping rect.
138: ;
139: ; Entry:
140: ; AH = pel color of this run
141: ; AL = number of pels of this run
142: ; Returns:
143: ; EAX = left coordinate if no clipping
144: ; ECX = left coordinate of the clipped run
145: ; EBX = right coordinate of the clipped run
146: ;
147: ;-----------------------------------------------------------------------;
148:
149: Clip_Encoded macro done, loop_start
150:
151: movzx edx,ah ;EDX = pel color
152: movzx eax,al ;EAX = number of pels
153: mov ecx,xCurr ;ECX = left coordinate
154: add xCurr,eax ;compute new x position
155: mov ebx,yCurr
156:
157: ; Check if y is inside the clipping range.
158:
159: mov edi,prclClip
160: cmp ebx,[edi].yTop
161: jb done
162: cmp ebx,[edi].yBottom
163: jae short loop_start
164:
165: ; Clip to the passed in clip rectangle.
166:
167: mov eax,ecx
168: cmp ecx,[edi].xLeft
169: jae short @F
170: mov ecx,[edi].xLeft
171:
172: @@:
173: mov ebx,xCurr
174: cmp ebx,[edi].xRight
175: jbe short @F
176: mov ebx,[edi].xRight
177:
178: @@:
179: cmp ebx,ecx ;clipped out if left and right crossed
180: jbe short loop_start
181: endm
182:
183: ;-------------------------------Macro-----------------------------------;
184: ; Draw_Encoded
185: ;
186: ; Write the current encoded run to the EGA/VGA.
187: ;
188: ; Entry:
189: ; EBX = right coordinate (exclusive)
190: ; ECX = left coordinate (inclusive)
191: ; EDX = pel color
192: ; Returns:
193: ; None
194: ;
195: ;-----------------------------------------------------------------------;
196:
197: Draw_Encoded macro loop_start
198:
199: call comp_masks ;compute bit masks
200:
201: shl eax,8 ;save right mask in high word
202: add edi,pjDst
203:
204: mov ebx,pulXlate
205: mov ebx,[ebx][edx*4]
206:
207: mov dx,VGA_BASE + GRAF_ADDR
208:
209: or ah,ah ;AH = left mask
210: jz short @F
211:
212: mov al,GRAF_BIT_MASK ;Set bitmask for altered bits
213: out dx,ax
214:
215: mov al,bl ;write color
216: xchg [edi],al
217: inc edi ;update destination pointer
218:
219: @@:
220: or ecx,ecx ;ECX = inner loop count
221: jz short @F
222:
223: mov ax,0FF00h + GRAF_BIT_MASK
224: out dx,ax ;no mask
225:
226: mov al,bl
227: rep stosb ;write color
228:
229: @@:
230: shr eax,8 ;AH = right mask
231: or ah,ah
232: jz loop_start
233:
234: mov al,GRAF_BIT_MASK ;Set bitmask for altered bits
235: out dx,ax
236: xchg [edi],bl ;write color
237:
238: jmp loop_start
239: endm
240:
241: ;-------------------------------Macro-----------------------------------;
242: ; Clip_Absolute
243: ;
244: ; Clip the current run in absolute mode against the clipping rect.
245: ; Compute initial bit mask and other vars for subsequent loop.
246: ;
247: ; Entry:
248: ; AH = number of pels of this run
249: ; Returns:
250: ; AL = GRAF_BIT_MASK
251: ; AH = bitmap for the first pel
252: ; EBX = pulXlate (pointer to the xlate table)
253: ; CH = 01000001b
254: ; EDI = pointer to destination byte to be altered
255: ; loop_count = loop count (number of pels to be altered)
256: ;
257: ;-----------------------------------------------------------------------;
258:
259: Clip_Absolute macro done,loop_end,loop_count
260:
261: movzx eax,ah ;EAX = number of pels
262: mov ecx,xCurr ;ECX = left coordinate
263: add xCurr,eax
264:
265: mov ebx,yCurr
266:
267: ; Check if y is inside the clipping range.
268:
269: mov edi,prclClip
270: cmp ebx,[edi].yTop
271: jb done
272: cmp ebx,[edi].yBottom
273: jae loop_end
274:
275: ; Check if x is inside the clipping range.
276:
277: cmp ecx,[edi].xRight ;check if x is in range
278: jae loop_end
279:
280: mov ebx,xCurr ;EBX = right coordinate
281: cmp ebx,[edi].xLeft ;can I not jump???!!!
282: jbe loop_end
283:
284: ; Clip to the passed in clip rectangle.
285:
286: cmp ecx,[edi].xLeft
287: mov cPreSrcAdv,0
288: jae short @F
289: mov eax,[edi].xLeft
290: sub eax,ecx ;diff of left coor and prclClip->xLeft
291: mov cPreSrcAdv,eax
292: add ecx,eax ;ECX = left coordinate = prclClip->xLeft
293:
294: @@:
295: xor eax,eax ;diff of right coor and prclClip->xRight
296: cmp ebx,[edi].xRight
297: jbe short @F
298: mov eax,ebx
299: mov ebx,[edi].xRight ;EBX = right coor = prclClip->xRight
300: sub eax,ebx
301:
302: @@:
303: mov cPostSrcAdv,eax
304: sub ebx,ecx ;loop count
305:
306: mov edi,ecx
307: shr edi,3
308: add edi,pjDst ;point to the first byte to write
309:
310: and ecx,00000111b ;Compute bit index for left side
311: mov ah,080h ;Compute bit mask
312: shr ah,cl ;AL = first pel bit mask
313: mov al,GRAF_BIT_MASK
314: mov loop_count,bl ;loop count < 0FFh
315: mov ch,01000001b ;for later use
316: mov ebx,pulXlate
317: endm
318:
319: ;-------------------------------Macro-----------------------------------;
320: ; RleEOL
321: ;
322: ; Handle the End of line case.
323: ;
324: ; Entry:
325: ; None.
326: ; Returns:
327: ; None.
328: ;
329: ;-----------------------------------------------------------------------;
330:
331: RleEOL macro loop_start
332:
333: mov eax,lNextScan
334: sub pjDst,eax ;adjust pjDst
335: dec yCurr ;adjust yCurr
336: mov eax,xStart ;adjust xCurr
337: mov xCurr,eax
338: jmp loop_start
339: endm
340:
341:
342: ;-------------------------------Macro-----------------------------------;
343: ; Set up banking-related variables, and make sure the bank for the
344: ; initial (bottom) scan line is mapped in.
345: ;
346: ; Entry:
347: ; None.
348: ; Returns:
349: ; EBX = pdsurf
350: ; ESI = pRleInfo
351: ; EDI = RLE_prctlClip
352: ;
353: ;-------------------------------Macro-----------------------------------;
354:
355: RleBankSetUp macro
356: local map_bank,bank_mapped
357:
358: mov esi,pRleInfo
359: mov ebx,[esi].Rle_pdsurfTrg
360: mov pdsurf,ebx
361:
362: mov eax,[ebx].dsurf_lNextScan
363: mov lNextScan,eax
364:
365: mov edi,[esi].RLE_prctlClip
366: mov eax,[edi].yTop
367: mov ulTrueClipTop,eax ;we blt until we reach this scan line
368:
369: ; Map in the bottom scan line of the clip rect.
370:
371: mov eax,[edi].yBottom ;bottom clip scan, exclusive
372: dec eax ;make it inclusive
373: cmp eax,[ebx].dsurf_rcl1WindowClip.yTop
374: jl short map_bank
375: cmp eax,[ebx].dsurf_rcl1WindowClip.yBottom
376: jl short bank_mapped
377: map_bank:
378: ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,eax,JustifyBottom>
379: bank_mapped:
380:
381: endm
382:
383:
384: ;-------------------------------Macro-----------------------------------;
385: ; Set up the screen pointer and clip the clip rect to the current bank.
386: ;
387: ; Entry:
388: ; EBX = pdsurf
389: ; ESI = pRleInfo
390: ; EDI = RLE_prctlClip
391: ; Returns:
392: ; None.
393: ;
394: ;-------------------------------Macro-----------------------------------;
395:
396: RleBankTop macro
397:
398: ; Convert the screen pointer from an offset within the bitmap to a virtual
399: ; address.
400:
401: mov eax,[ebx].dsurf_pvBitmapStart
402: add [esi].RLE_pjTrg,eax
403:
404: ; Set the clip rect top to MAX(top_of_bank,top_of_clip), to confine drawing to
405: ; this bank.
406:
407: mov eax,[ebx].dsurf_rcl1WindowClip.yTop
408: cmp ulTrueClipTop,eax
409: jl short @F
410: mov eax,ulTrueClipTop
411: @@:
412: mov [edi].yTop,eax
413:
414: endm
415:
416:
417: ;-------------------------------Macro-----------------------------------;
418: ; Check whether we've done the last bank spanned by this clip rect; exit
419: ; if so, map in the bank and continue if not.
420: ;
421: ; Entry:
422: ; None.
423: ; Returns:
424: ; EBX = pdsurf
425: ; ESI = pRleInfo
426: ; EDI = RLE_prctlClip
427: ;
428: ;-------------------------------Macro-----------------------------------;
429:
430: RleBankBottom macro loop_top,done
431:
432: ; Convert the screen pointer back to an offset within the bitmap.
433:
434: mov ebx,pdsurf
435: mov esi,pRleInfo
436: mov eax,[ebx].dsurf_pvBitmapStart
437: sub [esi].RLE_pjTrg,eax
438:
439: ; Have we reached the top bank involved in this blt? If so, done; if not, map
440: ; it in and blt the next bank.
441:
442: mov eax,[ebx].dsurf_rcl1WindowClip.yTop
443: cmp eax,ulTrueClipTop
444: jle &done
445: dec eax ;map in the bank above the current one
446: ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,eax,JustifyBottom>
447:
448: mov edi,[esi].RLE_prctlClip ;for RleBankTop
449:
450: jmp &loop_top
451:
452: endm
453:
454:
455: ;--------------------------Public-Routine-------------------------------;
456: ; vRle8ToVga
457: ;
458: ; Write an RLE8 bitmap onto the VGA device.
459: ;
460: ; Entry:
461: ; None.
462: ; Returns:
463: ; None
464: ;
465: ;-----------------------------------------------------------------------;
466:
467: cProc vRle8ToVga,4,< \
468: uses esi edi ebx, \
469: pRleInfo: ptr RLEINFO >
470:
471: local pjDst :ptr
472: local pulXlate :ptr
473: local xCurr :dword
474: local yCurr :dword
475: local xStart :dword
476: local cPreSrcAdv :dword
477: local cPostSrcAdv :dword
478: local prclClip :ptr RECTL
479: local pjSrcEnd :ptr
480: local pdsurf :ptr DEVSURF
481: local ulTrueClipTop :dword
482: local lNextScan : dword
483:
484: RleBankSetUp ;wrap a banking loop around everything
485:
486: rle8_bank_loop:
487:
488: RleBankTop
489:
490: RleSetUp
491:
492: rle8_loop:
493: cmp esi,pjSrcEnd
494: jae rle8_done
495: lodsw ;fetch a word from src RLE bitmap
496:
497: or al,al
498: jz rle8_escape
499:
500: rle8_encoded:
501: Clip_Encoded rle8_done,rle8_loop
502: Draw_Encoded rle8_loop
503:
504: rle8_escape:
505: cmp ah,2 ; First byte is 0, check the second byte.
506: ja short rle8_absolute
507: jb rle8_end_of_line_or_bitmap
508:
509: rle8_delta:
510: RleDelta rle8_loop
511:
512: rle8_absolute:
513: Clip_Absolute rle8_done,rle8_absolute_advance_src,cl
514: add esi,cPreSrcAdv ;advance esi to point to the clipped run
515:
516: ; I am doing a per pel loop rather than a per byte loop which writes 1 plane
517: ; at a time because it appears to me that most of the time we output 2 or
518: ; 3 pels per encounter of absolute mode. The logic here is simple and we can
519: ; stay with M_COLOR_WRITE mode all the time.
520:
521: rle8_absolute_loop:
522: mov dx,VGA_BASE + GRAF_ADDR
523: out dx,ax ;Set bitmask for altered bit
524:
525: movzx edx,byte ptr [esi] ;grab color for this pel
526: inc esi
527:
528: mov edx,[ebx][edx*4]
529: xchg [edi],dl ;write to destination
530:
531: ror ah,1 ;rotate bit mask for next pel
532: cmp ch,ah ;cmp bitmask with 01000001b
533: adc edi,0 ;advance edi if bitmask is 10000000b
534:
535: dec cl ;per pel loop
536: jnz short rle8_absolute_loop
537: mov eax,cPostSrcAdv
538:
539: rle8_absolute_advance_src:
540: add esi,eax ;advance src ptr for clipped out pels
541: bt esi,0 ;add 1 if not word aligned
542: adc esi,0
543: jmp rle8_loop
544:
545: rle8_end_of_line_or_bitmap:
546: or ah,ah
547: jnz short rle8_end_of_bitmap
548:
549: rle8_end_of_line:
550:
551: RleEOL rle8_loop
552:
553: rle8_done:
554: RleExit
555:
556: RleBankBottom rle8_bank_loop,rle8_exit ;see if there are more banks
557: ; to do
558: align 4
559: rle8_end_of_bitmap:
560: RleExit
561: rle8_exit:
562: cRet vRle8ToVga
563:
564: endProc vRle8ToVga
565:
566:
567: ;--------------------------Public-Routine-------------------------------;
568: ; vRle4ToVga
569: ;
570: ; Write an RLE4 bitmap onto the VGA device.
571: ;
572: ; Entry:
573: ; None
574: ; Returns:
575: ; None
576: ;
577: ;-----------------------------------------------------------------------;
578:
579: cProc vRle4ToVga,4,< \
580: uses esi edi ebx, \
581: pRleInfo: ptr RLEINFO >
582:
583: local pjDst :ptr
584: local pulXlate :ptr
585: local xCurr :dword
586: local yCurr :dword
587: local xStart :dword
588: local cPreSrcAdv :dword
589: local cPostSrcAdv :dword
590: local pjDstStart :ptr
591: local iPels :dword
592: local xMask :dword
593: local nPels :byte
594: local prclClip :ptr RECTL
595: local pjSrcEnd :ptr
596: local pdsurf :ptr DEVSURF
597: local ulTrueClipTop :dword
598: local lNextScan : dword
599:
600: RleBankSetUp ;wrap a banking loop around everything
601:
602: rle4_bank_loop:
603:
604: RleBankTop
605:
606: RleSetUp
607:
608: rle4_loop:
609: cmp esi,pjSrcEnd
610: jae rle4_done
611: lodsw ;fetch a word
612:
613: or al,al
614: jz rle4_escape
615:
616: rle4_encoded:
617: Clip_Encoded rle4_done,rle4_loop
618:
619: mov dh,dl ;separate two colors into dl, dh
620: and dl,0Fh
621: shr dh,4
622: cmp dh,dl
623: jnz short encoded_diff_color
624: xor dh,dh ;Draw_Encoded use edx as color index
625: Draw_Encoded rle4_loop
626:
627: encoded_diff_color:
628: sub eax,ecx ;-eax = #pels clipped away
629: bt eax,0
630: jnc short @F
631: xchg dl,dh ;xchg colors if odd #pels clipped
632: @@:
633: mov iPels,edx ;save color index
634: sub ebx,ecx ;Compute extent of interval
635: dec ebx ;Make interval inclusive
636: mov edi,ecx ;Don't destroy starting X
637: shr edi,3 ;/8 for byte address
638: add edi,pjDst
639:
640: and ecx,00000111b ;Compute bit index for first byte
641: mov eax,00AAAAAAh ;Compute altered bits mask
642: shr eax,cl ;AL = left side altered bytes mask
643:
644: add ebx,ecx ;Compute bit index for last byte
645: mov ecx,ebx ;(save for inner loop count)
646: and ecx,00000111b
647: mov ch,80h
648: sar ch,cl
649: and al,ch ;AL = last byte altered bits mask
650:
651: mov edx,eax
652: shr edx,1
653: and dl,ch ;EDX = mask for 2nd pel
654:
655: mov ecx,ebx
656: shr ecx,3 ;Compute inner byte count
657: jnz short comp_byte_dont_combine ;loop count + 1 > 0, check it out
658:
659: ; Only one byte will be affected. Combine first/last masks, set loop count = 0
660:
661: mov ebx,eax
662: shl eax,16 ;Will use first byte mask only
663: and eax,ebx ;AH = first mask. Rest of the bits = 0
664:
665: mov ebx,edx
666: shl edx,16 ;Will use first byte mask only
667: and edx,ebx ;DH = first mask. Rest of the bits = 0
668: inc ecx ;Fall through to set 0
669:
670: comp_byte_dont_combine:
671: dec ecx ;Dec inner loop count (might become 0)
672:
673: xchg al,ah
674: ror eax,16 ;EAX = last mask:inter mask:first mask:0
675: xchg al,ah ;for first pel
676: xchg dl,dh
677: ror edx,16 ;EDX = last mask:inter mask:first mask:0
678: xchg dl,dh ;for second pel
679:
680: mov pjDstStart,edi
681: mov xMask,edx ;save mask for the 2nd round
682:
683: mov ebx,pulXlate
684: mov edx,iPels
685: shr edx,8 ;index for the first pel
686: mov ebx,[ebx][edx*4]
687: inc bh ;BH = rle4_encoded_diff_color_loop count
688: inc bh
689: mov dx,VGA_BASE + GRAF_ADDR
690: ;BL = color for first pel
691: rle4_encoded_diff_color_loop:
692: or ah,ah ;AH = first mask
693: jz short encoded_inner_diff_color
694:
695: mov al,GRAF_BIT_MASK ;Set bitmask for altered bits
696: out dx,ax
697:
698: mov al,bl
699: xchg [edi],al ;write color
700: encoded_inner_diff_color:
701: inc edi ;update destination pointer
702: shr eax,8 ;AH = internal mask
703: or cl,cl ;ECX = inner loop count
704: jz short encoded_last_byte_diff_color
705:
706: mov ch,cl ;save loop count in ch
707: ;loop count always fit in a byte
708: mov al,GRAF_BIT_MASK
709: out dx,ax ;no mask
710:
711: encoded_loop_diff_color:
712: mov al,bl
713: xchg [edi],al ;write color
714: inc edi
715: dec cl
716: jnz encoded_loop_diff_color
717:
718: encoded_last_byte_diff_color:
719: shr eax,8 ;AH = last mask
720: or ah,ah
721: jz encoded_this_run_maybe_done
722:
723: mov al,GRAF_BIT_MASK ;Set bitmask for altered bits
724: out dx,ax
725:
726: encoded_write:
727: xchg [edi],bl ;write color
728:
729: encoded_this_run_maybe_done:
730: dec bh
731: jz rle4_loop
732:
733: mov edi,pulXlate
734: mov eax,iPels ;index of the second pel
735: xor ah,ah
736: mov bl,byte ptr [edi][eax*4]
737: mov edi,pjDstStart
738: mov eax,xMask ;load mask
739: mov cl,ch ;loop count
740:
741: jmp rle4_encoded_diff_color_loop
742:
743: rle4_escape:
744: cmp ah,2 ; First byte is 0, check the second byte.
745: ja rle4_absolute
746: jb rle4_end_of_line_or_bitmap
747:
748: rle4_delta:
749:
750: RleDelta rle4_loop
751:
752: rle4_absolute:
753: Clip_Absolute rle4_done,rle4_absolute_advance_src,nPels
754:
755: ;advance esi to point to the clipped run
756:
757: mov edx,cPreSrcAdv ;number of pels to advance
758: shr edx,1 ;number of bytes
759: jnc @F
760:
761: add esi,edx ;odd number of pels to advance
762: movzx edx,byte ptr [esi] ;grab color for prev and this pels
763: inc esi
764: mov iPels,edx
765:
766: inc nPels ;inc loop count since we start from 1
767: mov cl,1
768: jmp short absolute_loop
769:
770: @@: ;even number of pels to advance
771: add esi,edx
772:
773: ; I am doing a per pel loop rather than a per byte loop which writes 1 plane
774: ; at a time because it appears to me that most of the time we output 2 or
775: ; 3 pels per encounter of absolute mode. The logic here is simple and we can
776: ; stay with M_COLOR_WRITE mode all the time.
777:
778: xor cl,cl ;initialize loop count
779:
780: absolute_loop:
781: mov dx,VGA_BASE + GRAF_ADDR
782: out dx,ax ;Set bitmask for altered bit
783:
784: bt cl,0
785: jc @F
786:
787: movzx edx,byte ptr [esi] ;grab color for this and next pels
788: inc esi
789:
790: mov iPels,edx ;save for next pel
791: shr dl,4
792: jmp short ready_to_draw
793: @@:
794: mov edx,iPels ;second pel
795: and dl,0Fh ;mask out the second pel
796:
797: ready_to_draw:
798: mov edx,[ebx][edx*4] ;look up for VGA color
799: xchg [edi],dl ;write to destination
800:
801: ror ah,1 ;rotate bit mask for next pel
802: cmp ch,ah ;cmp bitmask with 01000001b
803: adc edi,0 ;advance edi if bitmask is 10000000b
804:
805: inc cl
806: cmp cl,nPels
807: jnz short absolute_loop
808:
809: mov eax,cPostSrcAdv
810:
811: rle4_absolute_advance_src:
812: shr eax,1 ;2 pels for one byte
813: add esi,eax ;advance src ptr for clipped out pels
814: bt esi,0 ;add 1 if not word aligned
815: adc esi,0
816: jmp rle4_loop
817:
818:
819: rle4_end_of_line_or_bitmap:
820: or ah,ah
821: jnz short rle4_end_of_bitmap
822:
823: rle4_end_of_line:
824: RleEOL rle4_loop
825:
826: rle4_done:
827: RleExit
828:
829: RleBankBottom rle4_bank_loop,rle4_exit ;see if there are more banks
830: ; to do
831: align 4
832: rle4_end_of_bitmap:
833: RleExit
834: rle4_exit:
835: cRet vRle4ToVga
836:
837: endProc vRle4ToVga
838:
839: ;--------------------------Private-Routine------------------------------;
840: ; comp_byte_interval
841: ;
842: ; An interval will be computed for byte boundaries.
843: ;
844: ; A first mask and a last mask will be calculated, and possibly
845: ; combined into the inner loop count. If no first byte exists,
846: ; the start address will be incremented to adjust for it.
847: ;
848: ; Entry:
849: ; EBX = right coordinate (exclusive)
850: ; ECX = left coordinate (inclusive)
851: ; Returns:
852: ; EDI = offset to first byte to be altered in the scan
853: ; ECX = inner loop count
854: ; AL = first byte mask (possibly 0)
855: ; AH = last byte mask (possibly 0)
856: ; Error Returns:
857: ; None
858: ; Registers Preserved:
859: ; ES,BP
860: ; Registers Destroyed:
861: ; AX,BX,CX,DI,FLAGS
862: ; Calls:
863: ; None
864: ;
865: ;-----------------------------------------------------------------------;
866:
867: comp_masks proc
868:
869: sub ebx,ecx ;Compute extent of interval
870: dec ebx ;Make interval inclusive
871: mov edi,ecx ;Don't destroy starting X
872: shr edi,3 ;/8 for byte address
873:
874: and ecx,00000111b ;Compute bit index for left side
875: mov al,0FFh ;Compute left side altered bits mask
876: shr al,cl ;AL = left side altered bytes mask
877:
878: add ebx,ecx ;Compute bit index for right side
879: mov ecx,ebx ;(save for inner loop count)
880: and ecx,00000111b
881: mov ah,80h
882: sar ah,cl ;AH = right side altered bits mask
883:
884: shr ebx,3 ;Compute inner byte count
885: jnz short comp_byte_dont_combine ;loop count + 1 > 0, check it out
886:
887: ; Only one byte will be affected. Combine first/last masks, set loop count = 0
888:
889: and al,ah ;Will use first byte mask only
890: xor ah,ah ;Want last byte mask to be 0
891: inc ebx ;Fall through to set 0
892:
893: comp_byte_dont_combine:
894: dec ebx ;Dec inner loop count (might become 0)
895:
896: ; If all pixels in the first byte are altered, combine the first byte into the
897: ; inner loop and clear the first byte mask. Ditto for the last byte mask.
898:
899: mov ecx,0FFFFFFFFh
900: cmp al,cl ;Set 'C' if not all pixels 1
901: sbb ebx,ecx ;If no 'C', sub -1 (add 1), else sub 0
902: cmp al,cl ;Set 'C' if not all pixels 1
903: sbb al,cl ;If no 'C', sub -1 (add 1), else sub 0
904:
905: cmp ah,cl ;Set 'C' if not all pixels 1
906: sbb ebx,ecx ;If no 'C', sub -1 (add 1), else sub 0
907: cmp ah,cl ;Set 'C' if not all pixels 1
908: sbb ah,cl ;If no 'C', sub -1 (add 1), else sub 0
909:
910: mov ecx,ebx ;Return inner loop count in ECX
911:
912: ret
913:
914: comp_masks endp
915:
916: end
917:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.