|
|
1.1 root 1: ;---------------------------Module-Header------------------------------;
2: ; Module Name: scroll.asm
3: ;
4: ; Copyright (c) 1992-1993 Microsoft Corporation
5: ;-----------------------------------------------------------------------;
6:
7: ;-----------------------------------------------------------------------;
8: ; VOID vPlanarCopyBits(ppdev, prclDest, pptlSrc);
9: ;
10: ; Input:
11: ;
12: ; ppdev - surface on which to copy
13: ; prcldest - pointer to destination rectangle
14: ; pptlsrc - pointer to source upper left corner
15: ;
16: ; Performs accelerated SRCCOPY screen-to-screen blts.
17: ;
18: ;-----------------------------------------------------------------------;
19: ;
20: ; NOTE: This handles only quad-pixel aligned blits!
21: ;
22: ; NOTE: Assumes all rectangles have positive heights and widths. Will
23: ; not work properly if this is not the case.
24: ;
25: ;-----------------------------------------------------------------------;
26:
27:
28: ;-----------------------------------------------------------------------;
29: ; Set LOOP_UNROLL_SHIFT to the log2 of the number of times you want loops in
30: ; this module unrolled. For example, LOOP_UNROLL_SHIFT of 3 yields 2**3 = 8
31: ; times unrolling. This is the only thing you need to change to control
32: ; unrolling.
33:
34: LOOP_UNROLL_SHIFT equ 2
35:
36: ;-----------------------------------------------------------------------;
37:
38: .386
39:
40: .model small,c
41:
42: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
43: assume fs:nothing,gs:nothing
44:
45: .xlist
46: include stdcall.inc ;calling convention cmacros
47: include i386\strucs.inc
48: include i386\driver.inc
49: include i386\unroll.inc
50: include i386\egavga.inc
51:
52: .list
53:
54: ;-----------------------------------------------------------------------;
55:
56: .data
57:
58: EXTRNP bPuntScreenToScreenCopyBits,20
59:
60: ; Bits for block copier tables:
61:
62: BLOCK_RIGHT_TO_LEFT equ 4
63: BLOCK_LEFT_EDGE equ 2
64: BLOCK_RIGHT_EDGE equ 1
65:
66: ;-----------------------------------------------------------------------;
67: ; Table of block copiers for various horizontal directions, with the
68: ; look-up index a 3-bit field as follows:
69: ;
70: ; Bit 2 (BLOCK_RIGHT_TO_LEFT) = 1 if right-to-left copy
71: ; Bit 1 (BLOCK_LEFT_EDGE) = 1 if left edge must be copied
72: ; Bit 0 (BLOCK_RIGHT_EDGE) = 1 if right edge must be copied
73:
74: align 4
75: MasterBlockTable label dword
76:
77: dd copy_just_middle_block
78: dd Block_WR
79: dd Block_LW
80: dd Block_LWR
81:
82: dd copy_just_middle_block
83: dd Block_RW
84: dd Block_WL
85: dd Block_RWL
86:
87: align 4
88: TopToBottomLoopTable label dword
89: dd 0 ;Not used - unbanked case
90: dd top_to_bottom_1RW
91: dd top_to_bottom_2RW
92: dd top_to_bottom_2RW
93:
94: align 4
95: BottomToTopLoopTable label dword
96: dd 0 ;Not used - unbanked case
97: dd bottom_to_top_1RW
98: dd bottom_to_top_2RW
99: dd bottom_to_top_2RW
100:
101: align 4
102: SetUpForCopyDirection label dword
103: dd left_to_right_top_to_bottom ;CD_RIGHTDOWN
104: dd right_to_left_top_to_bottom ;CD_LEFTDOWN
105: dd left_to_right_bottom_to_top ;CD_RIGHTUP
106: dd right_to_left_bottom_to_top ;CD_LEFTUP
107:
108: LeftMaskTable label dword
109: dd 01111b
110: dd 01110b
111: dd 01100b
112: dd 01000b
113:
114: RightMaskTable label dword
115: dd 00000b
116: dd 00001b
117: dd 00011b
118: dd 00111b
119:
120: ;-----------------------------------------------------------------------;
121:
122: .code
123:
124: align 4
125: Block_WR:
126: push offset copy_right_block
127: jmp copy_middle_block
128:
129: align 4
130: Block_LW:
131: push offset copy_middle_block
132: jmp copy_left_block
133:
134: align 4
135: Block_LWR:
136: push offset copy_right_block
137: push offset copy_middle_block
138: jmp copy_left_block
139:
140: align 4
141: Block_RW:
142: push offset copy_middle_block
143: jmp copy_right_block
144:
145: align 4
146: Block_WL:
147: push offset copy_left_block
148: jmp copy_middle_block
149:
150: align 4
151: Block_RWL:
152: push offset copy_left_block
153: push offset copy_middle_block
154: jmp copy_right_block
155:
156: ;-----------------------------------------------------------------------;
157:
158: cProc vPlanarCopyBits,12,< \
159: uses esi edi ebx, \
160: ppdev: ptr PDEV, \
161: prclDest: ptr RECTL, \
162: pptlSrc: ptr POINTL >
163:
164: ; Variables used in block copiers:
165:
166: local pfnCopyBlocks: ptr ;pointer to block copy routines
167:
168: local ulMiddleSrc: dword ;bitmap offset to 1st source
169: local ulMiddleDest: dword ;bitmap offset to 1st dest
170: local lMiddleDelta: dword ;delta from end of middle scan to next
171: local ulBlockHeight: dword ;number of scans to be copied in block
172: local cjMiddle: dword ;number of bytes to be copied on scan
173:
174: local ulLeftSrc: dword ;bitmap offset to left source byte edge
175: local ulLeftDest: dword ;bitmap offset to left dest byte edge
176: local ulRightSrc: dword ;bitmap offset to right source byte edge
177: local ulRightDest: dword ;bitmap offset to right dest byte edge
178: local lDelta: dword ;delta between scans
179:
180: local ulLeftMask: dword ;byte mask for left-edge copies
181: local ulRightMask: dword ;byte mask for right-edge copies
182:
183: local rclDest[size RECTL]: byte ;left and right values always valid
184: local ptlSrc[size POINTL]: byte ;x value always valid
185:
186: local ulCurrentSrcScan: dword ;real current source scan
187: local ulCurrentDestScan: dword ;real current destination scan
188: local ulLastDestScan: dword ;last destination scan
189:
190: ; Set the bit mask to disable all bits, so we can copy through the latches:
191:
192: mov edx,VGA_BASE + GRAF_ADDR
193: mov eax,(0 shl 8) + GRAF_BIT_MASK
194: out dx,ax
195:
196: ; Figure out which direction to do the copies:
197:
198: mov esi,pptlSrc
199: mov edi,prclDest
200: mov eax,[esi].ptl_y
201: cmp eax,[edi].yTop
202: jl planar_bottom_to_top
203:
204: mov eax,[esi].ptl_x
205: cmp eax,[edi].xLeft
206: jge short left_to_right_top_to_bottom ; CD_RIGHTDOWN
207: jmp right_to_left_top_to_bottom ; CD_LEFTDOWN
208:
209: align 4
210: planar_bottom_to_top:
211: mov eax,[esi].ptl_x
212: cmp eax,[edi].xLeft
213: jge left_to_right_bottom_to_top ; CD_RIGHTUP
214: jmp right_to_left_bottom_to_top ; CD_LEFTUP
215:
216: align 4
217: all_done:
218:
219: ; Enable bit mask for all bits:
220:
221: mov edx,VGA_BASE + GRAF_ADDR
222: mov eax,(0ffh shl 8) + GRAF_BIT_MASK
223: out dx,ax
224:
225: ; Enable writes to all planes and reset direction flag:
226:
227: mov edx,VGA_BASE + SEQ_DATA
228: mov al,MM_ALL
229: out dx,al
230:
231: cld
232:
233: cRet vPlanarCopyBits
234:
235: ;=======================================================================;
236: ;==================== Direction Dependent Setup ========================;
237: ;=======================================================================;
238:
239: ;-----------------------------------------------------------------------;
240: ; Set-up code for left-to-right, top-to-bottom copies.
241: ;
242: ; Input:
243: ; esi - pptlSrc
244: ; edi - prclDest
245: ;-----------------------------------------------------------------------;
246:
247: align 4
248: public left_to_right_top_to_bottom
249: left_to_right_top_to_bottom:
250:
251: ; Need to set-up: ulMiddleSrc, ulMiddleDest, lMiddleDelta, cjMiddle
252: ; ulLeftSrc, ulLeftDest, ulLeftMask
253: ; lDelta
254: ; ulRightSrc, ulRightDest, ulRightMask
255: ; ulCurrentDestScan, ulLastDestScan
256: ; pfnCopyBlocks
257: ; ptlSrc.x, rclDest.left, rclDest.right
258:
259: ; lDelta = ppdev->lPlanarScan
260: ; ulCurrentSrcScan = pptl->y
261: ; ulLeftSrc = pptl->y * lDelta + (pptl->x >> 2)
262: ; ulCurrentDestScan = prclDest->top
263: ; ulLeftDest = prclDest->top * lDelta + (prclDest->left >> 2)
264: ;
265: ; ulMiddleSrc = ulLeftSrc
266: ; ulMiddleDest = ulLeftDest
267: ;
268: ; cjMiddle = (prclDest->right >> 2) - (prclDest->left >> 2)
269: ; if (prclDest->left & 3)
270: ; ulLeftMask = LeftMaskTable[prclDest->left & 3]
271: ; fl |= BLOCK_LEFT_EDGE
272: ; ulMiddleSrc++
273: ; ulMiddleDest++
274: ; cjMiddle--
275: ;
276: ; lMiddleDelta = lDelta - cjMiddle
277: ;
278: ; if (prclDest->right & 3)
279: ; ulRightMask = RightMaskTable[prclDest->right & 3]
280: ; fl |= BLOCK_RIGHT_EDGE
281: ; ulRightSrc = ulMiddleSrc + cjMiddle
282: ; ulRightDest = ulMiddleDest + cjMiddle
283:
284: mov edx,ppdev
285: mov eax,[edi].yBottom
286: mov edx,[edx].pdev_lPlanarNextScan ;edx = lDelta
287: mov ulLastDestScan,eax ;ulLastDestScan = prclDest->bottom
288:
289: mov ecx,[esi].ptl_y
290: mov eax,edx
291: mov ulCurrentSrcScan,ecx ;ulCurrentSrcScan = pptlSrc->y
292: imul eax,ecx
293: mov ecx,[esi].ptl_x
294: mov ptlSrc.ptl_x,ecx ;ptlSrc.x = pptlSrc->x
295: shr ecx,2
296: add eax,ecx ;eax = ulLeftSrc = pptlSrc->y *
297: ; lDelta + (pptlSrc->x >> 2)
298:
299: xor esi,esi ;initialize flags
300:
301: mov ecx,[edi].yTop
302: mov ebx,edx
303: mov ulCurrentDestScan,ecx ;ulCurrentDestScan = prclDest->top
304: imul ebx,ecx
305: mov ecx,[edi].xLeft
306: mov rclDest.xLeft,ecx ;rclDest.left = prclDest->left
307: shr ecx,2
308: add ebx,ecx ;ebx = ulLeftDest = prclDest->top *
309: ; lDelta + (prclDest->left >> 2)
310:
311: mov edi,[edi].xRight
312: mov rclDest.xRight,edi
313: shr edi,2
314: sub edi,ecx ;cjMiddle = (prclDest->right >> 2) -
315: ; (prclDest->left >> 2)
316:
317: mov ecx,rclDest.xLeft
318: and ecx,3
319: jz short l_t_done_left_edge ;skip if we don't need a left edge
320:
321: or esi,BLOCK_LEFT_EDGE
322: mov ecx,LeftMaskTable[ecx*4]
323: mov ulLeftMask,ecx ;ulLeftMask =
324: ; LeftMaskTable[prclDest->left & 3]
325:
326: mov ulLeftSrc,eax ;ulLeftSrc
327: mov ulLeftDest,ebx ;ulLeftDest
328: inc eax
329: inc ebx
330: dec edi
331:
332: l_t_done_left_edge:
333: mov ulMiddleSrc,eax ;ulMiddleSrc
334: mov ulMiddleDest,ebx ;ulMiddleDest
335:
336: mov ecx,rclDest.xRight
337: and ecx,3
338: jz short l_t_done_right_edge ;skip if we don't need a right edge
339:
340: or esi,BLOCK_RIGHT_EDGE
341: mov ecx,RightMaskTable[ecx*4]
342: mov ulRightMask,ecx ;ulRightMask =
343: ; RightMaskTable[prclDest->right & 3]
344:
345: add eax,edi
346: add ebx,edi
347: mov ulRightSrc,eax ;ulRightSrc = ulMiddleSrc + cjMiddle
348: mov ulRightDest,ebx ;ulRightDest = ulMiddleDest + cjMiddle
349:
350: ; We special case here blits that are less than 4 pels wide and begin and end
351: ; in the same 4-pel quadruple:
352:
353: cmp edi,0
354: jge l_t_done_right_edge
355:
356: ; We make sure the 'middle' count of bytes is zero (we'll just let the code
357: ; fall through the 'middle' copy code), turn off the right-edge flag, and
358: ; give ulLeftMask the composite mask:
359:
360: inc edi
361: xor esi,BLOCK_RIGHT_EDGE
362: and ecx,ulLeftMask
363: mov ulLeftMask,ecx
364:
365: align 4
366: l_t_done_right_edge:
367: mov cjMiddle,edi ;cjMiddle
368:
369: mov lDelta,edx ;lDelta = ppdev->lPlanarNextScan
370: sub edx,edi
371: mov lMiddleDelta,edx ;lMiddleDelta = lDelta - cjMiddle
372:
373: mov ebx,ppdev
374: mov eax,MasterBlockTable[esi*4]
375: mov pfnCopyBlocks,eax ;copy blocks between video memory
376:
377: ; Branch to the appropriate top-to-bottom bank enumeration loop:
378:
379: mov eax,[ebx].pdev_vbtPlanarType
380: jmp TopToBottomLoopTable[eax*4]
381:
382: ;-----------------------------------------------------------------------;
383: ; Set-up code for right-to-left, top-to-bottom copies.
384: ;
385: ; Input:
386: ; esi - pptlSrc
387: ; edi - prclDest
388: ;-----------------------------------------------------------------------;
389:
390: align 4
391: public right_to_left_top_to_bottom
392: right_to_left_top_to_bottom:
393:
394: std ;copy middle blocks right-to-left
395:
396: mov edx,ppdev
397: mov eax,[edi].yBottom
398: mov edx,[edx].pdev_lPlanarNextScan ;edx = lDelta
399: mov ulLastDestScan,eax ;ulLastDestScan = prclDest->bottom
400:
401: mov ecx,[esi].ptl_y
402: mov eax,edx
403: mov ulCurrentSrcScan,ecx ;ulCurrentSrcScan = pptlSrc->y
404: imul eax,ecx
405: mov ecx,[esi].ptl_x
406: mov ptlSrc.ptl_x,ecx ;ptlSrc.x = pptlSrc->x
407: add ecx,[edi].xRight
408: sub ecx,[edi].xLeft
409: shr ecx,2
410: add eax,ecx ;eax = ulRightSrc = pptlSrc->y *
411: ; lDelta + (pptlSrc->x +
412: ; prclDest->right - prclDest->left) / 4
413:
414: mov esi,BLOCK_RIGHT_TO_LEFT ;initialize flags
415:
416: mov ecx,[edi].yTop
417: mov ebx,edx
418: mov ulCurrentDestScan,ecx ;ulCurrentDestScan = prclDest->top
419: imul ebx,ecx
420: mov ecx,[edi].xRight
421: mov rclDest.xRight,ecx ;rclDest.right = prclDest->right
422: shr ecx,2
423: add ebx,ecx ;ebx = ulRightDest = prclDest->top *
424: ; lDelta + prclDest->right / 4
425:
426: mov edi,[edi].xLeft
427: mov rclDest.xLeft,edi
428: shr edi,2
429: neg edi
430: add edi,ecx ;cjMiddle = prclDest->right / 4 -
431: ; prclDest->left / 4
432:
433: mov ecx,rclDest.xRight
434: and ecx,3
435: jz short r_t_done_right_edge ;skip if we don't need a right edge
436:
437: or esi,BLOCK_RIGHT_EDGE
438: mov ecx,RightMaskTable[ecx*4]
439: mov ulRightMask,ecx ;ulRightMask =
440: ; RightMaskTable[prclDest->right & 3]
441:
442: mov ulRightSrc,eax ;ulRightSrc
443: mov ulRightDest,ebx ;ulRightDest
444:
445: r_t_done_right_edge:
446: dec eax
447: dec ebx
448: mov ulMiddleSrc,eax ;ulMiddleSrc
449: mov ulMiddleDest,ebx ;ulMiddleDest
450:
451: mov ecx,rclDest.xLeft
452: and ecx,3
453: jz short r_t_done_left_edge ;skip if we don't need a right edge
454: or esi,BLOCK_LEFT_EDGE
455: mov ecx,LeftMaskTable[ecx*4]
456: mov ulLeftMask,ecx ;ulLeftMask =
457: ; LeftMaskTable[prclDest->left & 3]
458:
459: dec edi ;adjust middle block length because
460: ; we're effectively doing one less
461: ; middle byte
462:
463: sub eax,edi
464: sub ebx,edi
465: mov ulLeftSrc,eax ;ulLeftSrc = ulMiddleSrc - cjMiddle
466: mov ulLeftDest,ebx ;ulLeftDest = ulMiddleDest - cjMiddle
467:
468: ; We special case here blits that are less than 4 pels wide and begin and end
469: ; in the same 4-pel quadruple:
470:
471: cmp edi,0
472: jge r_t_done_left_edge
473:
474: ; We make sure the 'middle' count of bytes is zero (we'll just let the code
475: ; fall through the 'middle' copy code), turn off the right-edge flag, and
476: ; give ulRightMask the composite mask:
477:
478: inc edi
479: xor esi,BLOCK_LEFT_EDGE
480: and ecx,ulRightMask
481: mov ulRightMask,ecx
482:
483: align 4
484: r_t_done_left_edge:
485: mov cjMiddle,edi ;cjMiddle
486:
487: mov lDelta,edx ;lDelta = ppdev->lPlanarNextScan
488: add edx,edi
489: mov lMiddleDelta,edx ;lMiddleDelta = lDelta + cjMiddle
490:
491: mov ebx,ppdev
492: mov eax,MasterBlockTable[esi*4]
493: mov pfnCopyBlocks,eax ;copy blocks between video memory
494:
495: ; Branch to the appropriate top-to-bottom bank enumeration loop:
496:
497: mov eax,[ebx].pdev_vbtPlanarType
498: jmp TopToBottomLoopTable[eax*4]
499:
500: ;-----------------------------------------------------------------------;
501: ; Set-up code for left-to-right, bottom-to-top copies.
502: ;
503: ; Input:
504: ; esi - pptlSrc
505: ; edi - prclDest
506: ;-----------------------------------------------------------------------;
507:
508: align 4
509: public left_to_right_bottom_to_top
510: left_to_right_bottom_to_top:
511:
512: mov edx,ppdev
513: mov eax,[edi].yTop
514: mov edx,[edx].pdev_lPlanarNextScan ;edx = lDelta
515: mov ulLastDestScan,eax ;ulLastDestScan = prclDest->top
516:
517: mov ecx,[esi].ptl_y
518: add ecx,[edi].yBottom
519: sub ecx,[edi].yTop
520: mov eax,edx
521: mov ulCurrentSrcScan,ecx ;ulCurrentSrcScan = pptlSrc->y +
522: ; (prclDest->bottom - prclDest->top)
523: dec ecx
524: imul eax,ecx
525: mov ecx,[esi].ptl_x
526: mov ptlSrc.ptl_x,ecx ;ptlSrc.x = pptlSrc->x
527: shr ecx,2
528: add eax,ecx ;eax = ulLeftSrc = (ulCurrentSrcScan - 1)
529: ; * lDelta + (pptlSrc->x >> 2)
530:
531: xor esi,esi ;initialize flags
532:
533: mov ecx,[edi].yBottom
534: mov ebx,edx
535: mov ulCurrentDestScan,ecx ;ulCurrentDestScan = prclDest->bottom
536: dec ecx
537: imul ebx,ecx
538: mov ecx,[edi].xLeft
539: mov rclDest.xLeft,ecx ;rclDest.left = prclDest->left
540: shr ecx,2
541: add ebx,ecx ;ebx = ulLeftDest = (prclDest->bottom - 1)
542: ; * lDelta + (prclDest->left >> 2)
543:
544: mov edi,[edi].xRight
545: mov rclDest.xRight,edi
546: shr edi,2
547: sub edi,ecx ;cjMiddle = (prclDest->right >> 2) -
548: ; (prclDest->left >> 2)
549:
550: mov ecx,rclDest.xLeft
551: and ecx,3
552: jz short l_b_done_left_edge ;skip if we don't need a left edge
553:
554: or esi,BLOCK_LEFT_EDGE
555: mov ecx,LeftMaskTable[ecx*4]
556: mov ulLeftMask,ecx ;ulLeftMask =
557: ; LeftMaskTable[prclDest->left & 3]
558:
559: mov ulLeftSrc,eax ;ulLeftSrc
560: mov ulLeftDest,ebx ;ulLeftDest
561: inc eax
562: inc ebx
563: dec edi
564:
565: l_b_done_left_edge:
566: mov ulMiddleSrc,eax ;ulMiddleSrc
567: mov ulMiddleDest,ebx ;ulMiddleDest
568:
569: mov ecx,rclDest.xRight
570: and ecx,3
571: jz short l_b_done_right_edge ;skip if we don't need a right edge
572:
573: or esi,BLOCK_RIGHT_EDGE
574: mov ecx,RightMaskTable[ecx*4]
575: mov ulRightMask,ecx ;ulRightMask =
576: ; RightMaskTable[prclDest->right & 3]
577:
578: add eax,edi
579: add ebx,edi
580: mov ulRightSrc,eax ;ulRightSrc = ulMiddleSrc + cjMiddle
581: mov ulRightDest,ebx ;ulRightDest = ulMiddleDest + cjMiddle
582:
583: ; We special case here blits that are less than 4 pels wide and begin and end
584: ; in the same 4-pel quadruple:
585:
586: cmp edi,0
587: jge l_b_done_right_edge
588:
589: ; We make sure the 'middle' count of bytes is zero (we'll just let the code
590: ; fall through the 'middle' copy code), turn off the right-edge flag, and
591: ; give ulLeftMask the composite mask:
592:
593: inc edi
594: xor esi,BLOCK_RIGHT_EDGE
595: and ecx,ulLeftMask
596: mov ulLeftMask,ecx
597:
598: align 4
599: l_b_done_right_edge:
600: mov cjMiddle,edi ;cjMiddle
601:
602: neg edx
603: mov lDelta,edx ;lDelta = -ppdev->lPlanarNextScan
604: sub edx,edi
605: mov lMiddleDelta,edx ;lMiddleDelta = lDelta - cjMiddle
606:
607: mov ebx,ppdev
608: mov eax,MasterBlockTable[esi*4]
609: mov pfnCopyBlocks,eax ;copy blocks between video memory
610:
611: ; Branch to the appropriate top-to-bottom bank enumeration loop:
612:
613: mov eax,[ebx].pdev_vbtPlanarType
614: jmp BottomToTopLoopTable[eax*4]
615:
616: ;-----------------------------------------------------------------------;
617: ; Set-up code for right-to-left, bottom-to-top copies.
618: ;
619: ; Input:
620: ; esi - pptlSrc
621: ; edi - prclDest
622: ;-----------------------------------------------------------------------;
623:
624: align 4
625: public right_to_left_bottom_to_top
626: right_to_left_bottom_to_top:
627:
628: std ;copy middle blocks right-to-left
629:
630: mov edx,ppdev
631: mov eax,[edi].yTop
632: mov edx,[edx].pdev_lPlanarNextScan ;edx = lDelta
633: mov ulLastDestScan,eax ;ulLastDestScan = prclDest->top
634:
635: mov ecx,[esi].ptl_y
636: add ecx,[edi].yBottom
637: sub ecx,[edi].yTop
638: mov eax,edx
639: mov ulCurrentSrcScan,ecx ;ulCurrentSrcScan = pptlSrc->y +
640: ; (prclDest->bottom - prclDest->top)
641: dec ecx
642: imul eax,ecx
643: mov ecx,[esi].ptl_x
644: mov ptlSrc.ptl_x,ecx ;ptlSrc.x = pptlSrc->x
645: add ecx,[edi].xRight
646: sub ecx,[edi].xLeft
647: shr ecx,2
648: add eax,ecx ;eax = ulRightSrc = (ulCurrentSrcScan
649: ; - 1) * lDelta + (pptlSrc->x +
650: ; prclDest->right - prclDest->left) / 4
651:
652: mov esi,BLOCK_RIGHT_TO_LEFT ;initialize flags
653:
654: mov ecx,[edi].yBottom
655: mov ebx,edx
656: mov ulCurrentDestScan,ecx ;ulCurrentDestScan = prclDest->bottom
657: dec ecx
658: imul ebx,ecx
659: mov ecx,[edi].xRight
660: mov rclDest.xRight,ecx ;rclDest.right = prclDest->right
661: shr ecx,2
662: add ebx,ecx ;ebx = ulRightDest = (ulCurrentDestScan
663: ; - 1) * lDelta + prclDest->right / 4
664:
665: mov edi,[edi].xLeft
666: mov rclDest.xLeft,edi
667: shr edi,2
668: neg edi
669: add edi,ecx ;cjMiddle = prclDest->right / 4 -
670: ; prclDest->left / 4
671:
672: mov ecx,rclDest.xRight
673: and ecx,3
674: jz short r_b_done_right_edge ;skip if we don't need a right edge
675:
676: or esi,BLOCK_RIGHT_EDGE
677: mov ecx,RightMaskTable[ecx*4]
678: mov ulRightMask,ecx ;ulRightMask =
679: ; RightMaskTable[prclDest->right & 3]
680:
681: mov ulRightSrc,eax ;ulRightSrc
682: mov ulRightDest,ebx ;ulRightDest
683:
684: r_b_done_right_edge:
685: dec eax
686: dec ebx
687: mov ulMiddleSrc,eax ;ulMiddleSrc
688: mov ulMiddleDest,ebx ;ulMiddleDest
689:
690: mov ecx,rclDest.xLeft
691: and ecx,3
692: jz short r_b_done_left_edge ;skip if we don't need a right edge
693:
694: or esi,BLOCK_LEFT_EDGE
695: mov ecx,LeftMaskTable[ecx*4]
696: mov ulLeftMask,ecx ;ulLeftMask =
697: ; LeftMaskTable[prclDest->left & 3]
698:
699: dec edi ;adjust middle block length because
700: ; we're effectively doing one less
701: ; middle byte
702:
703: sub eax,edi
704: sub ebx,edi
705: mov ulLeftSrc,eax ;ulLeftSrc = ulMiddleSrc - cjMiddle
706: mov ulLeftDest,ebx ;ulLeftDest = ulMiddleDest - cjMiddle
707:
708: ; We special case here blits that are less than 4 pels wide and begin and end
709: ; in the same 4-pel quadruple:
710:
711: cmp edi,0
712: jge r_b_done_left_edge
713:
714: ; We make sure the 'middle' count of bytes is zero (we'll just let the code
715: ; fall through the 'middle' copy code), turn off the right-edge flag, and
716: ; give ulRightMask the composite mask:
717:
718: inc edi
719: xor esi,BLOCK_LEFT_EDGE
720: and ecx,ulRightMask
721: mov ulRightMask,ecx
722:
723: align 4
724: r_b_done_left_edge:
725: mov cjMiddle,edi ;cjMiddle
726:
727: neg edx
728: mov lDelta,edx ;lDelta = -ppdev->lPlanarNextScan
729: add edx,edi
730: mov lMiddleDelta,edx ;lMiddleDelta = lDelta + cjMiddle
731:
732: mov ebx,ppdev
733: mov eax,MasterBlockTable[esi*4]
734: mov pfnCopyBlocks,eax ;copy blocks between video memory
735:
736: ; Branch to the appropriate top-to-bottom bank enumeration loop:
737:
738: mov eax,[ebx].pdev_vbtPlanarType
739: jmp BottomToTopLoopTable[eax*4]
740:
741: ;=======================================================================;
742: ;============================= Banking =================================;
743: ;=======================================================================;
744:
745: ;-----------------------------------------------------------------------;
746: ; Banking for 1 R/W adapters, top to bottom.
747: ;
748: ; Input:
749: ; ulCurrentSrcScan
750: ; ulCurrentDestScan
751: ; ulLastDestScan
752: ; Plus some other stuff for split rasters and block copiers
753: ;-----------------------------------------------------------------------;
754: align 4
755: public top_to_bottom_1RW
756: top_to_bottom_1RW:
757:
758: ; LATER: Should check to see if there's any chance that the source and
759: ; destination overlap in the same window, so that we can use planar
760: ; copies -- otherwise, it's faster to directly call of to
761: ; bPuntScreenToScreenCopyBits
762:
763: ; We're going top to bottom. Map in the source and dest, top-justified.
764:
765: mov ebx,ppdev
766: mov edi,ulCurrentDestScan
767:
768: cmp edi,[ebx].pdev_rcl1PlanarClip.yTop
769: jl short top_1RW_map_init_bank
770:
771: cmp edi,[ebx].pdev_rcl1PlanarClip.yBottom
772: jl short top_1RW_init_bank_mapped
773:
774: top_1RW_map_init_bank:
775:
776: ; Map bank containing the top destination scan line into window.
777: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
778:
779: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
780: <ebx,edi,JustifyTop>
781:
782: top_1RW_init_bank_mapped:
783:
784: mov eax,ulCurrentSrcScan
785: cmp eax,[ebx].pdev_rcl1PlanarClip.yBottom
786:
787: jl short top_1RW_do_planar_copy
788:
789: ; ulCurrentSrcScan >= ppdev->rcl1PlanarClip.bottom, which means that
790: ; the window can't overlap the source and destination at all. We'll
791: ; have to use an intermediate temporary buffer:
792:
793: ; ebx = ppdev
794: ; eax = ulCurrentSrcScan
795: ; edi = ulCurrentDestScan
796:
797: mov ptlSrc.ptl_y,eax ;ptlSrc.y = ulCurrentSrcScan
798: mov rclDest.yTop,edi ;rclDest.top = ulCurrentDestScan
799:
800: mov esi,[ebx].pdev_rcl1PlanarClip.yBottom
801: mov eax,ulLastDestScan
802: sub eax,esi
803: sbb ecx,ecx
804: and ecx,eax
805: add esi,ecx
806: mov rclDest.yBottom,esi ;rclDest.bottom = min(ulLastDestScan,
807: ; ppdev->pdev_rcl1PlanarClip.bottom)
808:
809: ; Enable bit mask for all bits:
810:
811: mov edx,VGA_BASE + GRAF_ADDR
812: mov eax,(0ffh shl 8) + GRAF_BIT_MASK
813: out dx,ax
814:
815: ; Enable writes to all planes and reset direction flag:
816:
817: mov edx,VGA_BASE + SEQ_DATA
818: mov al,MM_ALL
819: out dx,al
820:
821: pushfd
822: cld
823:
824: ; Call our routine that copies bits the slow way, preserving EBX, ESI and EDI
825: ; according to C calling conventions:
826:
827: lea ecx,rclDest
828: lea edx,ptlSrc
829:
830: cCall bPuntScreenToScreenCopyBits,<ebx,0,0,ecx,edx>
831:
832: popfd
833:
834: ; Set the bit mask to disable all bits, so we can copy through latches again:
835:
836: mov edx,VGA_BASE + GRAF_ADDR
837: mov eax,(000h shl 8) + GRAF_BIT_MASK
838: out dx,ax
839:
840: ; Update our position variables:
841:
842: mov ulCurrentDestScan,esi ;ulCurrentDestScan = rclDest.bottom
843:
844: sub esi,edi ;ulBlockHeight = rclDest.bottom -
845: ; rclDest.top
846:
847: add ulCurrentSrcScan,esi ;ulCurrentSrcScan += ulBlockHeight
848:
849: ; We have to adjust the offsets for all our block copiers, according to the
850: ; number of scans we copied:
851:
852: mov edx,lDelta
853: imul edx,esi ;edx = lDelta * ulBlockHeight
854: add ulLeftSrc,edx
855: add ulLeftDest,edx
856: add ulMiddleSrc,edx
857: add ulMiddleDest,edx
858: add ulRightSrc,edx
859: add ulRightDest,edx
860:
861: jmp short top_1RW_see_if_done
862:
863: top_1RW_do_planar_copy:
864:
865: ; ebx = ppdev
866: ; eax = ulCurrentSrcScan
867: ; edi = ulCurrentDestScan
868:
869: mov ebx,[ebx].pdev_rcl1PlanarClip.yBottom
870: sub ebx,eax ;ebx = ppdev->rcl1PlanarClip.bottom -
871: ; ulCurrentSrcScan
872: ;ebx is the available number of scans
873: ; we have in the source
874:
875: mov edx,ulLastDestScan
876: sub edx,edi ;edx = ulLastDestScan - ulCurrentDestScan
877: ;edx is the available number of scans
878: ; in the destination
879:
880: ; (Because the source starts lower in the window than the destination,
881: ; the bottom of the bank always limits the source number of scans before
882: ; it does the destination.)
883:
884: sub ebx,edx
885: sbb ecx,ecx
886: and ecx,ebx
887: add edx,ecx ;edx = min(source available,
888: ; destination available)
889: mov ulBlockHeight,edx
890:
891: add eax,edx ;We have to adjust our current scans
892: add edi,edx
893: mov ulCurrentSrcScan,eax
894: mov ulCurrentDestScan,edi
895:
896: ; Now copy the puppy:
897:
898: call pfnCopyBlocks
899:
900: ; See if we're done:
901:
902: top_1RW_see_if_done:
903: mov edi,ulCurrentDestScan
904: cmp edi,ulLastDestScan
905: jge all_done
906:
907: mov ebx,ppdev
908:
909: ; Map bank containing the top destination scan line into window.
910: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
911:
912: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
913: <ebx,edi,JustifyTop>
914:
915: jmp top_1RW_init_bank_mapped
916:
917: ;-----------------------------------------------------------------------;
918: ; Banking for 1 R/W adapters, bottom to top.
919: ;
920: ; Input:
921: ; ulCurrentSrcScan - Actually, 1 more current source scan
922: ; ulCurrentDestScan - Actually, 1 more current destination scan
923: ; ulLastDestScan
924: ; Plus some other stuff for split rasters and block copiers
925: ;-----------------------------------------------------------------------;
926: align 4
927: public bottom_to_top_1RW
928: bottom_to_top_1RW:
929:
930: ; We're going top to bottom. Map in the source and dest, top-justified.
931:
932: mov ebx,ppdev
933: mov edi,ulCurrentDestScan
934:
935: cmp edi,[ebx].pdev_rcl1PlanarClip.yTop
936: jle short bot_1RW_map_init_bank
937:
938: cmp edi,[ebx].pdev_rcl1PlanarClip.yBottom
939: jle short bot_1RW_init_bank_mapped
940:
941: bot_1RW_map_init_bank:
942:
943: ; Map bank containing the top destination scan line into window.
944: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
945:
946: dec edi
947: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
948: <ebx,edi,JustifyTop>
949: inc edi
950:
951: bot_1RW_init_bank_mapped:
952:
953: mov eax,ulCurrentSrcScan
954: cmp eax,[ebx].pdev_rcl1PlanarClip.yTop
955:
956: jg short bot_1RW_do_planar_copy
957:
958: ; ulCurrentSrcScan <= ppdev->rcl1PlanarClip.top, which means that
959: ; the window can't overlap the source and destination at all. We'll
960: ; have to use an intermediate temporary buffer:
961:
962: ; ebx = ppdev
963: ; eax = ulCurrentSrcScan
964: ; edi = ulCurrentDestScan
965:
966: mov esi,[ebx].pdev_rcl1PlanarClip.yTop
967: mov edx,ulLastDestScan
968: cmp esi,edx
969: jg @F
970: mov esi,edx
971: @@:
972: mov rclDest.yTop,esi ;rclDest.top = max(ulLastDestScan,
973: ; ppdev->rcl1PlanarClip.top)
974:
975: mov rclDest.yBottom,edi ;rclDest.bottom = ulCurrentDestScan
976: add eax,esi
977: sub eax,edi
978: mov ptlSrc.ptl_y,eax ;ptlSrc.y = ulCurrentSrcScan -
979: ; (rclDest.bottom - rclDest.top)
980:
981: ; Enable bit mask for all bits:
982:
983: mov edx,VGA_BASE + GRAF_ADDR
984: mov eax,(0ffh shl 8) + GRAF_BIT_MASK
985: out dx,ax
986:
987: ; Enable writes to all planes and reset direction flag:
988:
989: mov edx,VGA_BASE + SEQ_DATA
990: mov al,MM_ALL
991: out dx,al
992:
993: pushfd
994: cld
995:
996: ; Call our routine that copies bits the slow way, preserving EBX, ESI and EDI
997: ; according to C calling conventions:
998:
999: lea ecx,rclDest
1000: lea edx,ptlSrc
1001:
1002: cCall bPuntScreenToScreenCopyBits,<ebx,0,0,ecx,edx>
1003:
1004: popfd
1005:
1006: ; Set the bit mask to disable all bits, so we can copy through latches again:
1007:
1008: mov edx,VGA_BASE + GRAF_ADDR
1009: mov eax,(000h shl 8) + GRAF_BIT_MASK
1010: out dx,ax
1011:
1012: ; Update our position variables:
1013:
1014: mov ulCurrentDestScan,esi ;ulCurrentDestScan = rclDest.top
1015:
1016: sub edi,esi ;ulBlockHeight = rclDest.bottom -
1017: ; rclDest.top
1018:
1019: sub ulCurrentSrcScan,edi ;ulCurrentSrcScan -= ulBlockHeight
1020:
1021: ; We have to adjust the offsets for all our block copiers, according to the
1022: ; number of scans we copied:
1023:
1024: mov edx,lDelta
1025: imul edx,edi ;edx = lDelta * ulBlockHeight
1026: add ulLeftSrc,edx
1027: add ulLeftDest,edx
1028: add ulMiddleSrc,edx
1029: add ulMiddleDest,edx
1030: add ulRightSrc,edx
1031: add ulRightDest,edx
1032:
1033: jmp short bot_1RW_see_if_done
1034:
1035: bot_1RW_do_planar_copy:
1036:
1037: ; ebx = ppdev
1038: ; eax = ulCurrentSrcScan
1039: ; edi = ulCurrentDestScan
1040:
1041: sub eax,[ebx].pdev_rcl1PlanarClip.yTop
1042: ;eax = ulCurrentSrcScan -
1043: ; ppdev->rcl1PlanarClip.top
1044:
1045: sub edi,ulLastDestScan ;edi = ulCurrentDestScan - ulLastDestScan
1046: ;edi is the available number of scans
1047: ; in the destination
1048:
1049:
1050: ; (Because the source starts higher in the window than the destination,
1051: ; the bottom of the bank always limits the source number of scans before
1052: ; it does the destination.)
1053:
1054: sub eax,edi
1055: sbb ecx,ecx
1056: and ecx,eax
1057: add edi,ecx ;edi = min(source available,
1058: ; destination available)
1059:
1060: mov ulBlockHeight,edi
1061:
1062: sub ulCurrentSrcScan,edi ;We have to adjust our current scans
1063: sub ulCurrentDestScan,edi
1064:
1065: ; Now copy the puppy:
1066:
1067: call pfnCopyBlocks
1068:
1069: ; See if we're done:
1070:
1071: bot_1RW_see_if_done:
1072: mov edi,ulCurrentDestScan
1073: cmp edi,ulLastDestScan
1074: jle all_done
1075:
1076: mov ebx,ppdev
1077:
1078: ; Map bank containing the top destination scan line into window.
1079: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1080:
1081: dec edi
1082: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
1083: <ebx,edi,JustifyTop>
1084: inc edi
1085:
1086: jmp bot_1RW_init_bank_mapped
1087:
1088: ;-----------------------------------------------------------------------;
1089: ; Banking for 1R/1W or 2R/W adapters, top to bottom.
1090: ;
1091: ; Input:
1092: ; ulCurrentSrcScan
1093: ; ulCurrentDestScan
1094: ; ulLastDestScan
1095: ; Plus some other stuff for split rasters and block copiers
1096: ;-----------------------------------------------------------------------;
1097: align 4
1098: public top_to_bottom_2RW
1099: top_to_bottom_2RW:
1100:
1101: ; We're going top to bottom. Map in the destination, top-justified.
1102:
1103: mov ebx,ppdev
1104: mov edi,ulCurrentDestScan
1105: mov esi,ulCurrentSrcScan
1106:
1107: cmp edi,[ebx].pdev_rcl2PlanarClipD.yTop
1108: jl short top_2RW_map_init_dest_bank
1109:
1110: cmp edi,[ebx].pdev_rcl2PlanarClipD.yBottom
1111: jl short top_2RW_init_dest_bank_mapped
1112:
1113: top_2RW_map_init_dest_bank:
1114:
1115: ; Map bank containing the top destination scan line into window.
1116: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1117:
1118: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
1119: <ebx,edi,JustifyTop,MapDestBank>
1120:
1121: top_2RW_init_dest_bank_mapped:
1122:
1123: cmp esi,[ebx].pdev_rcl2PlanarClipS.yTop
1124: jl short top_2RW_map_init_src_bank
1125:
1126: cmp esi,[ebx].pdev_rcl2PlanarClipS.yBottom
1127: jl short top_2RW_main_loop
1128:
1129: top_2RW_map_init_src_bank:
1130:
1131: ; Map bank containing the top source scan line into window.
1132: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1133:
1134: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
1135: <ebx,esi,JustifyTop,MapSourceBank>
1136:
1137: top_2RW_main_loop:
1138: mov ecx,[ebx].pdev_rcl2PlanarClipD.yBottom
1139: mov edx,ulLastDestScan
1140:
1141: sub ecx,edx
1142: sbb eax,eax
1143: and eax,ecx
1144: add edx,eax ;edx = min(ulLastDestScan,
1145: ; ppdev->rcl2PlanarClipD.bottom)
1146:
1147: mov ecx,[ebx].pdev_rcl2PlanarClipS.yBottom
1148:
1149: sub edx,edi ;edx = available scans in destination
1150: ; bank
1151: sub ecx,esi ;ecx = available scans in source bank
1152:
1153: sub ecx,edx
1154: sbb eax,eax
1155: and eax,ecx
1156: add edx,eax
1157:
1158: mov ulBlockHeight,edx ;ulBlockHeight = min(source available,
1159: ; dest available)
1160:
1161: add esi,edx ;adjust our currents scans accordingly
1162: add edi,edx
1163: mov ulCurrentSrcScan,esi
1164: mov ulCurrentDestScan,edi
1165:
1166: ; Do the actual copy:
1167:
1168: call pfnCopyBlocks
1169:
1170: mov edi,ulCurrentDestScan ;check if done
1171: cmp edi,ulLastDestScan
1172: jge all_done
1173:
1174: mov ebx,ppdev
1175:
1176: ; We'll have to map a new source bank, destination bank, or both:
1177:
1178: mov esi,ulCurrentSrcScan
1179: cmp edi,[ebx].pdev_rcl2PlanarClipD.yBottom
1180: jl short top_2RW_map_next_src_bank
1181:
1182: ; Map bank containing the top destination scan line into window.
1183: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1184:
1185: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
1186: <ebx,edi,JustifyTop,MapDestBank>
1187:
1188: cmp esi,[ebx].pdev_rcl2PlanarClipS.yBottom
1189: jl short top_2RW_main_loop
1190:
1191: top_2RW_map_next_src_bank:
1192:
1193: ; Map bank containing the top source scan line into window.
1194: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1195:
1196: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
1197: <ebx,esi,JustifyTop,MapSourceBank>
1198:
1199: jmp short top_2RW_main_loop
1200:
1201: ;-----------------------------------------------------------------------;
1202: ; Banking for 1R/1W or 2R/W adapters, bottom to top.
1203: ;
1204: ; Input:
1205: ; ulCurrentSrcScan
1206: ; ulCurrentDestScan
1207: ; ulLastDestScan
1208: ; Plus some other stuff for split rasters and block copiers
1209: ;-----------------------------------------------------------------------;
1210: align 4
1211: public bottom_to_top_2RW
1212: bottom_to_top_2RW:
1213:
1214: ; We're going bottom to top. Map in the destination, bottom-justified.
1215:
1216: mov ebx,ppdev
1217: mov edi,ulCurrentDestScan ; 1 more than actual destination scan
1218: mov esi,ulCurrentSrcScan ; 1 more than actual source scan
1219:
1220: cmp edi,[ebx].pdev_rcl2PlanarClipD.yTop
1221: jle short bot_2RW_map_init_dest_bank
1222:
1223: cmp edi,[ebx].pdev_rcl2PlanarClipD.yBottom
1224: jle short bot_2RW_init_dest_bank_mapped
1225:
1226: bot_2RW_map_init_dest_bank:
1227:
1228: ; Map bank containing the top destination scan line into window.
1229: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1230:
1231: dec edi
1232: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
1233: <ebx,edi,JustifyBottom,MapDestBank>
1234: inc edi
1235:
1236: bot_2RW_init_dest_bank_mapped:
1237:
1238: cmp esi,[ebx].pdev_rcl2PlanarClipS.yTop
1239: jle short bot_2RW_map_init_src_bank
1240:
1241: cmp esi,[ebx].pdev_rcl2PlanarClipS.yBottom
1242: jle short bot_2RW_main_loop
1243:
1244: bot_2RW_map_init_src_bank:
1245:
1246: ; Map bank containing the top source scan line into window.
1247: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1248:
1249: dec esi
1250: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
1251: <ebx,esi,JustifyBottom,MapSourceBank>
1252: inc esi
1253:
1254: bot_2RW_main_loop:
1255: mov ecx,[ebx].pdev_rcl2PlanarClipD.yTop
1256: mov edx,ulLastDestScan
1257:
1258: cmp edx,ecx
1259: jg @F
1260: mov edx,ecx ;edx = max(ulLastDestScan,
1261: @@: ; ppdev->rcl2PlanarClipD.top)
1262:
1263: sub edi,edx ;edi = available scans in destination
1264: ; bank
1265: sub esi,[ebx].pdev_rcl2PlanarClipS.yTop
1266: ;esi = available scans in source bank
1267:
1268: sub esi,edi
1269: sbb eax,eax
1270: and eax,esi
1271: add edi,eax
1272:
1273: mov ulBlockHeight,edi ;ulBlockHeight = min(source available,
1274: ; dest available)
1275:
1276: sub ulCurrentSrcScan,edi ;adjust our current scans
1277: sub ulCurrentDestScan,edi
1278:
1279: ; Do the actual copy:
1280:
1281: call pfnCopyBlocks
1282:
1283: mov edi,ulCurrentDestScan ;check if done
1284: cmp edi,ulLastDestScan
1285: jle all_done
1286:
1287: mov ebx,ppdev
1288:
1289: ; We'll have to map a new source bank, destination bank, or both:
1290:
1291: mov esi,ulCurrentSrcScan
1292: cmp edi,[ebx].pdev_rcl2PlanarClipD.yTop
1293: jg short bot_2RW_map_next_src_bank
1294:
1295: ; Map bank containing the top destination scan line into window.
1296: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1297:
1298: dec edi
1299: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
1300: <ebx,edi,JustifyBottom,MapDestBank>
1301: inc edi
1302:
1303: cmp esi,[ebx].pdev_rcl2PlanarClipS.yTop
1304: jg short bot_2RW_main_loop
1305:
1306: bot_2RW_map_next_src_bank:
1307:
1308: ; Map bank containing the top source scan line into window.
1309: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
1310:
1311: dec esi
1312: ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
1313: <ebx,esi,JustifyBottom,MapSourceBank>
1314: inc esi
1315:
1316: jmp short bot_2RW_main_loop
1317:
1318: ;=======================================================================;
1319: ;=========================== Block Copiers =============================;
1320: ;=======================================================================;
1321:
1322: ;-----------------------------------------------------------------------;
1323: ; Input:
1324: ; Direction flag - set to the appropriate direction
1325: ; ulMiddleSrc - offset in bitmap to source
1326: ; ulMiddleDest - offset in bitmap to destination
1327: ; lMiddleDelta - distance from end of current scan to start of next
1328: ; ulBlockHeight - # of scans to copy
1329: ; cjMiddle - # of planar bytes to copy on every scan
1330: ;
1331: ; Output:
1332: ; Advances ulMiddleSrc and ulMiddleDest to next strip
1333: ;-----------------------------------------------------------------------;
1334:
1335: align 4
1336: public copy_middle_block
1337: copy_middle_block:
1338:
1339: ; We only have to reset which planes are enabled if we do edges too:
1340:
1341: mov edx,VGA_BASE + SEQ_DATA
1342: mov al,MM_ALL
1343: out dx,al
1344:
1345: align 4
1346: copy_just_middle_block:
1347:
1348: ; Calculate full start addresses:
1349:
1350: mov edi,ppdev
1351: mov eax,cjMiddle
1352: mov ebx,ulBlockHeight
1353: mov edx,lMiddleDelta
1354: mov esi,[edi].pdev_pvBitmapStart2WindowS
1355: mov edi,[edi].pdev_pvBitmapStart2WindowD
1356: add esi,ulMiddleSrc
1357: add edi,ulMiddleDest
1358:
1359: SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnCopyMiddleEntry, \
1360: LOOP_UNROLL_SHIFT
1361:
1362: jmp ecx
1363:
1364: UNROLL_LOOP_ENTRY_TABLE pfnCopyMiddleEntry,MIDDLE, \
1365: LOOP_UNROLL_COUNT
1366:
1367: COPY_MIDDLE macro ENTRY_LABEL,ENTRY_INDEX
1368: &ENTRY_LABEL&ENTRY_INDEX&:
1369: mov ecx,eax
1370: rep movsb
1371: add esi,edx
1372: add edi,edx
1373: endm ;-----------------------------------;
1374:
1375: ; EAX = # of bytes to copy
1376: ; EBX = count of unrolled loop iterations
1377: ; EDX = offset from end of one scan's fill to start of next
1378: ; ESI = source address from which to copy
1379: ; EDI = target address to which to copy
1380:
1381: align 4
1382: middle_loop:
1383: UNROLL_LOOP COPY_MIDDLE,MIDDLE,LOOP_UNROLL_COUNT
1384: dec ebx
1385: jnz middle_loop
1386:
1387: ; get ready for next time:
1388:
1389: mov ecx,ppdev
1390: sub esi,[ecx].pdev_pvBitmapStart2WindowS
1391: sub edi,[ecx].pdev_pvBitmapStart2WindowD
1392: mov ulMiddleSrc,esi
1393: mov ulMiddleDest,edi
1394:
1395: PLAIN_RET
1396:
1397: ;-----------------------------------------------------------------------;
1398: ; Input:
1399: ; ulLeftSrc - offset in bitmap to source
1400: ; ulLeftDest - offset in bitmap to destination
1401: ; lDelta - distance from between planar scans
1402: ; ulBlockHeight - # of scans to copy
1403: ;
1404: ; Output:
1405: ; Advances ulLeftSrc and ulLeftDest to next strip
1406: ;-----------------------------------------------------------------------;
1407:
1408: align 4
1409: public copy_left_block
1410: copy_left_block:
1411:
1412: ; Set left mask by disabling some planes:
1413:
1414: mov edx,VGA_BASE + SEQ_DATA
1415: mov eax,ulLeftMask
1416: out dx,al
1417:
1418: ; Calculate full start addresses:
1419:
1420: mov ecx,ppdev
1421: mov ebx,ulBlockHeight
1422: mov edx,lDelta
1423: mov esi,[ecx].pdev_pvBitmapStart2WindowS
1424: mov edi,[ecx].pdev_pvBitmapStart2WindowD
1425: add esi,ulLeftSrc
1426: add edi,ulLeftDest
1427:
1428: SET_UP_UNROLL_VARS ebx,eax,ebx,pfnCopyLeftEntry, \
1429: LOOP_UNROLL_SHIFT
1430:
1431: jmp eax
1432:
1433: UNROLL_LOOP_ENTRY_TABLE pfnCopyLeftEntry,LEFT, \
1434: LOOP_UNROLL_COUNT
1435:
1436: COPY_LEFT macro ENTRY_LABEL,ENTRY_INDEX
1437: &ENTRY_LABEL&ENTRY_INDEX&:
1438: mov al,[esi]
1439: mov [edi],al
1440: add esi,edx
1441: add edi,edx
1442: endm ;-----------------------------------;
1443:
1444: ; EBX = count of unrolled loop iterations
1445: ; EDX = offset from one scan to next
1446: ; ESI = source address from which to copy
1447: ; EDI = target address to which to copy
1448:
1449: align 4
1450: left_loop:
1451: UNROLL_LOOP COPY_LEFT,LEFT,LOOP_UNROLL_COUNT
1452: dec ebx
1453: jnz left_loop
1454:
1455: ; get ready for next time:
1456:
1457: sub esi,[ecx].pdev_pvBitmapStart2WindowS
1458: sub edi,[ecx].pdev_pvBitmapStart2WindowD
1459: mov ulLeftSrc,esi
1460: mov ulLeftDest,edi
1461:
1462: PLAIN_RET
1463:
1464: ;-----------------------------------------------------------------------;
1465: ; Input:
1466: ; ulRightSrc - offset in bitmap to source
1467: ; ulRightDest - offset in bitmap to destination
1468: ; lDelta - distance from between planar scans
1469: ; ulBlockHeight - # of scans to copy
1470: ;
1471: ; Output:
1472: ; Advances ulRightSrc and ulRightDest to next strip
1473: ;-----------------------------------------------------------------------;
1474:
1475: align 4
1476: public copy_right_block
1477: copy_right_block:
1478:
1479: ; Set right mask by disabling some planes:
1480:
1481: mov edx,VGA_BASE + SEQ_DATA
1482: mov eax,ulRightMask
1483: out dx,al
1484:
1485: ; Calculate full start addresses:
1486:
1487: mov ecx,ppdev
1488: mov ebx,ulBlockHeight
1489: mov edx,lDelta
1490: mov esi,[ecx].pdev_pvBitmapStart2WindowS
1491: mov edi,[ecx].pdev_pvBitmapStart2WindowD
1492: add esi,ulRightSrc
1493: add edi,ulRightDest
1494:
1495: SET_UP_UNROLL_VARS ebx,eax,ebx,pfnCopyRightEntry, \
1496: LOOP_UNROLL_SHIFT
1497:
1498: jmp eax
1499:
1500: UNROLL_LOOP_ENTRY_TABLE pfnCopyRightEntry,RIGHT, \
1501: LOOP_UNROLL_COUNT
1502:
1503: COPY_RIGHT macro ENTRY_LABEL,ENTRY_INDEX
1504: &ENTRY_LABEL&ENTRY_INDEX&:
1505: mov al,[esi]
1506: mov [edi],al
1507: add esi,edx
1508: add edi,edx
1509: endm ;-----------------------------------;
1510:
1511: ; EBX = count of unrolled loop iterations
1512: ; EDX = offset from one scan to next
1513: ; ESI = source address from which to copy
1514: ; EDI = target address to which to copy
1515:
1516: align 4
1517: right_loop:
1518: UNROLL_LOOP COPY_RIGHT,RIGHT,LOOP_UNROLL_COUNT
1519: dec ebx
1520: jnz right_loop
1521:
1522: ; get ready for next time:
1523:
1524: sub esi,[ecx].pdev_pvBitmapStart2WindowS
1525: sub edi,[ecx].pdev_pvBitmapStart2WindowD
1526: mov ulRightSrc,esi
1527: mov ulRightDest,edi
1528:
1529: PLAIN_RET
1530:
1531: ;-----------------------------------------------------------------------;
1532:
1533: endProc vPlanarCopyBits
1534:
1535: end
1536:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.