|
|
1.1 root 1: ;!!! This is all temp crap to be replaced when the blinker is written
2:
3: ;---------------------------Module-Header------------------------------;
4: ; Module Name: cpybits.asm
5: ;
6: ; Copyright (c) 1992 Microsoft Corporation
7: ;-----------------------------------------------------------------------;
8: page ,132
9: title DrvCopyBits Support
10: .386
11:
12: ifndef DOS_PLATFORM
13: .model small,c
14: else
15: ifdef STD_CALL
16: .model small,c
17: else
18: .model small,pascal
19: endif; STD_CALL
20: endif; DOS_PLATFORM
21:
22: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
23: assume fs:nothing,gs:nothing
24:
25: .xlist
26: include stdcall.inc ;calling convention cmacros
27: include i386\egavga.inc ;VGA register definitions
28: include i386\strucs.inc
29: .list
30:
31:
32: .data
33:
34: ; Reuse the work area from the dib conversion code.
35:
36: ; BUGBUG this should be allocated memory accessed via the DEVSURF, not static
37:
38: extrn ajConvertBuffer:byte ;Buffer for converting to/from display
39:
40: ; BUGBUG this should be dynamically calculated
41:
42: CJ_WORK_PLANE equ cj_max_scan+1 ;Width of each plane in ajConvertBuffer
43:
44: .code
45:
46: ; ausLo16 is used to convert the low nibble of a byte into 4bpp packed pel
47:
48: ausLo16 equ this word
49:
50: dw 0000h ;0000
51: dw 0100h ;0001
52: dw 1000h ;0010
53: dw 1100h ;0011
54: dw 0001h ;0100
55: dw 0101h ;0101
56: dw 1001h ;0110
57: dw 1101h ;0111
58: dw 0010h ;1000
59: dw 0110h ;1001
60: dw 1010h ;1010
61: dw 1110h ;1011
62: dw 0011h ;1100
63: dw 0111h ;1101
64: dw 1011h ;1110
65: dw 1111h ;1111
66:
67: ; aulHi16 is used to convert the hi nibble of a byte into 4bpp packed pel
68:
69: aulHi16 equ this dword
70:
71: dd 00000000h ;0000
72: dd 01000000h ;0001
73: dd 10000000h ;0010
74: dd 11000000h ;0011
75: dd 00010000h ;0100
76: dd 01010000h ;0101
77: dd 10010000h ;0110
78: dd 11010000h ;0111
79: dd 00100000h ;1000
80: dd 01100000h ;1001
81: dd 10100000h ;1010
82: dd 11100000h ;1011
83: dd 00110000h ;1100
84: dd 01110000h ;1101
85: dd 10110000h ;1110
86: dd 11110000h ;1111
87:
88: ; ajRightMasks turns an exclusive bit position (0-7) into a mask of bits
89: ; to alter for the right hand side of the blt
90:
91: ajRightMasks equ this byte
92:
93: db 11111111b ;0 should never be used
94: db 01111111b ;1
95: db 00111111b ;2
96: db 00011111b ;3
97: db 00001111b ;4
98: db 00000111b ;5
99: db 00000011b ;6
100: db 00000001b ;7
101:
102: ; ajLeftMasks turns a bit position (0-7) into a mask of bits to alter for
103: ; the left hand side of the blt
104:
105: ajLeftMasks equ this byte
106:
107: db 11111111b ;0 should never be used
108: db 10000000b ;1
109: db 11000000b ;2
110: db 11100000b ;3
111: db 11110000b ;4
112: db 11111000b ;5
113: db 11111100b ;6
114: db 11111110b ;7
115:
116:
117: CB_4BPP_SCAN equ (CX_SCREEN_MAX / 2) ;# bytes for a 4bpp screen scan
118:
119: ;-----------------------------Public-Routine----------------------------;
120: ; vConvertVGAScan
121: ;
122: ; Converts a VGA scan into a 4bpp format with a given phase alignment,
123: ; and returns a pointer to the converted buffer.
124: ;
125: ; pdsurfsrc - pointer to source surface (must be VGA display memory)
126: ; xSrc - X origin of the source
127: ; ySrc - Y origin of the source
128: ; pjDstBase - Base address of the destination
129: ; xDst - X origin of the destination
130: ; yDst - Y origin of the destination
131: ; cxPels - Number of pels in X
132: ; cyTotalScans - Number of scans in overall operation
133: ; lDelta - Width in bytes of a destination scan
134: ; iFormat - Format of destination
135: ; pulXlate - Color translation vector
136: ;-----------------------------------------------------------------------;
137:
138: ProcName xxxvConvertVGA2DIB,vConvertVGA2DIB,44
139:
140: xxxvConvertVGA2DIB proc uses esi edi ebx,\
141: pdsurfsrc :ptr DEVSURF, \
142: xSrc :dword, \
143: ySrc :dword, \
144: pjDstBase :dword, \
145: xDst :dword, \
146: yDst :dword, \
147: cxPels :dword, \
148: cyTotalScans :dword, \
149: lDelta :dword, \
150: iFormat :dword, \
151: pulXlate :dword
152:
153: ;-----------------------------------------------------------------------;
154: ; Local variables and their meaning
155: ;
156: ; cjScreenCopy This is the number of bytes to copy from each scan
157: ; into ajConvertBuffer.
158: ; jLeftMask This is the left-hand side (lhs) mask used when copying
159: ; the converted data to the destination
160: ; jRightMask This is the right-hand side (lhs) mask used when copying
161: ; the converted data to the destination
162: ; cRightShift This is the number of bits that the converted data needs
163: ; to be shifted right to align with the destination.
164: ; cjRightShift This is the number of bytes which must be shifted right
165: ; by cRightShift
166: ; cCopy This is the number of full (e.g. not masked) bytes which
167: ; must be copied to the destination
168: ; pjWork Pointer to the work area where
169: ; a) color converted data is written into
170: ; b) bits are phase-aligned if needed
171: ; c) data is read from for the final copy to the DIB
172: ; pjSrc Address of scan 0 in memory
173: ; pjDst Address of scan 0 in memory
174: ; cyScans Number of scans to do in current bank
175: ; ulScanWidth Offset from start of one scan to start of next
176: ; ulBottomSrcScan Bottom scan line of source rectangle (non-inclusive)
177: ;-----------------------------------------------------------------------;
178:
179: local cjScreenCopy :dword
180: local jLeftMask :byte
181: local jRightMask :byte
182: local cRightShift :byte
183: local cjRightShift :dword
184: local cCopy :dword
185: local pfnXlate :ptr
186: local pjWork :ptr
187: local cjSkip :dword
188: local pjSrc :dword
189: local pjDst :dword
190: local cyScans :dword
191: local ulScanWidth :dword
192: local ulBottomSrcScan :dword
193:
194: local ajColorConv[16]:byte
195: local ajWork[CB_4BPP_SCAN+4]:byte
196: local aj8bpp[CX_SCREEN_MAX+8]:byte
197:
198:
199: ;----------------------------------------------------------------------;
200: ; Loop through source banks, copying & converting one bank at a time.
201:
202: ; Calculate the bottom scan line of the source rectangle (non-inclusive).
203:
204: mov eax,ySrc
205: add eax,cyTotalScans
206: mov ulBottomSrcScan,eax
207:
208: mov ecx,pdsurfsrc ;point to source surface
209: mov eax,[ecx].dsurf_lNextScan
210: mov ulScanWidth,eax ;local copy of scan line width
211:
212: ; Map in the bank containing the top scan to fill, if it's not mapped in
213: ; already.
214:
215: mov eax,ySrc ;top scan line of source
216:
217: cmp eax,[ecx].dsurf_rcl1WindowClip.yTop ;is fill top less than
218: ; current bank?
219: jl short map_init_bank ;yes, map in proper bank
220: cmp eax,[ecx].dsurf_rcl1WindowClip.yBottom ;fill top greater than
221: ; current bank?
222: jl short init_bank_mapped ;no, proper bank already mapped
223: map_init_bank:
224:
225: ; Map in the bank containing the top scan line of the fill.
226:
227: ptrCall <dword ptr [ecx].dsurf_pfnBankControl>,<ecx,eax,JustifyTop>
228:
229: init_bank_mapped:
230:
231: bank_loop:
232:
233: ; Set the start address of the source bitmap.
234: ; Note that the start of the bitmap will change each time through the
235: ; bank loop, because the start of the bitmap is varied to map the
236: ; desired scan line to the banking window.
237:
238: mov eax,pdsurfsrc ;point to source surface
239: mov ebx,[eax].dsurf_pvBitmapStart ;start of scan 0 in bitmap
240: mov pjSrc,ebx
241:
242: ; Set the start address of the destination bitmap.
243:
244: mov ebx,pjDstBase
245: mov pjDst,ebx
246:
247: ; Figure out how many scan lines we'll fill in the current bank.
248:
249: mov ebx,ulBottomSrcScan ;bottom of destination rectangle
250: cmp ebx,[eax].dsurf_rcl1WindowClip.yBottom
251: ;which comes first, the bottom of the
252: ; dest rect or the bottom of the
253: ; current bank?
254: jl short BottomScanSet ;fill bottom comes first, so draw to
255: ; that; this is the last bank in fill
256: mov ebx,[eax].dsurf_rcl1WindowClip.yBottom
257: ;bank bottom comes first; draw to
258: ; bottom of bank
259: BottomScanSet:
260: sub ebx,ySrc ;# of scans to fill in bank
261: mov cyScans,ebx
262: push ebx ;remember # of scans in bank
263:
264: call DoOneBank ;copy and convert within the current bank
265:
266: pop ebx ;restore # of scans in bank
267:
268: sub cyTotalScans,ebx ;count off this bank's scans from total
269: jz short banks_done ;no more scans; done
270: add yDst,ebx ;advance to the next destination scan
271: ; to copy to
272: mov edi,pdsurfsrc
273: mov eax,[edi].dsurf_rcl1WindowClip.yBottom
274: mov ySrc,eax ;remember where the top of the bank
275: ; we're about to map in is (same as
276: ; bottom of bank we just did)
277:
278: ptrCall <dword ptr [edi].dsurf_pfnBankControl>,<edi,eax,JustifyTop>
279: ;map in the bank
280:
281: jmp bank_loop ;fill the next bank
282:
283:
284: ; Done.
285:
286: align 4
287: banks_done:
288:
289: cRet vConvertVGA2DIB
290:
291: ;----------------------------------------------------------------------;
292: ; Copies and converts bits within a single bank.
293:
294: align 4
295: DoOneBank:
296:
297: cld
298:
299: ; Compute the number of bytes to copy from the screen, and the starting
300: ; address of the source
301:
302: mov eax,ySrc ;Compute addr of first source scan
303: mov ebx,xSrc
304: imul eax,ulScanWidth
305: mov ecx,ebx
306: shr ebx,3
307: add eax,ebx
308: add pjSrc,eax
309:
310: ; Compute the number of bytes to actually transfer from the screen
311:
312: mov eax,cxPels ;Compute rhs
313: add eax,ecx
314: dec eax ;Make rhs inclusive
315: shr ecx,3 ;Compute byte of lhs
316: shr eax,3 ;Compute byte of rhs
317: sub eax,ecx ;Compute number of bytes for copy
318: inc eax ;(because rhs inclusive, always inc)
319: mov cjScreenCopy,eax
320:
321: ; Compute the address of the starting destination scan.
322:
323: mov eax,yDst
324: imul lDelta
325: add pjDst,eax
326:
327: ; Set up for the preprocess loops and invoke the correct one. First make
328: ; some assumptions about defaults
329:
330: xor eax,eax
331: mov cRightShift,al ;No shifting needed
332: mov jLeftMask,al ;No left masking needed
333: mov jRightMask,al ;No right masking needed
334: lea eax,ajWork ;Intermediate work area
335: mov pjWork,eax
336:
337: mov esi,cxPels
338: mov ebx,xSrc
339: mov edx,xDst
340:
341: mov eax,iFormat
342: dec eax
343: jz preproc_1bpp
344: dec eax
345: jz preproc_4bpp
346: .errnz BMF_1BPP-1
347: .errnz BMF_4BPP-2
348: .errnz BMF_8BPP-3
349:
350: ; Destination is 8bpp. Copy will be phased aligned from the conversion buffer
351: ; to the destination.
352:
353: preproc_8bpp:
354: add pjDst,edx ;Offset to first pel in DIB
355: and ebx,7 ;Offset to first pel for final copy
356: mov cjSkip,ebx
357: mov cCopy,esi ;Number of bytes for final copy
358: lea eax,aj8bpp ;Intermediate work area
359: mov pjWork,eax
360: mov pfnXlate,offset FLAT:cvt_to_8bpp
361: jmp preproc_done
362:
363:
364: ; Destination is 4bpp. Copy will either be phase aligned or be off by 4 in
365: ; which case we will phase align the entire buffer before copying.
366:
367: preproc_4bpp:
368: lea eax,[esi][edx] ;Compute rhs for later
369: test dl,1 ;Odd if left mask needed
370: jz @F
371: mov jLeftMask,11110000b
372: dec esi ;One less pel in inner loop
373: @@:
374: test al,1 ;Odd if right mask needed
375: jz @F
376: mov jRightMask,00001111b
377: dec esi ;One less pel in inner loop
378: @@:
379:
380: and ebx,7 ;Offset for final copy is xSrc mod 8
381:
382: ; If the source and destination have different alignments, we'll have to
383: ; compute phase alignment stuff.
384:
385: mov eax,ebx
386: xor eax,edx
387: shr eax,1
388: jnc @F
389: mov eax,cjScreenCopy ;* 4 for size of data in buffer
390: shl eax,2
391: inc eax ;+ 1 to shift into last byte!
392: mov cjRightShift,eax
393: mov cRightShift,4 ;Shift entire buffer right 4 pels
394: inc ebx ;First pel just moved right
395: @@:
396:
397: ; Finish calculating the other parameters
398:
399: shr edx,1 ;Offset to first pel in DIB
400: add pjDst,edx
401: shr ebx,1
402: mov cjSkip,ebx
403: shr esi,1
404: mov cCopy,esi ;# of inner bytes for final copy
405:
406: mov eax,offset FLAT:copy_to_dest;Assume no color translation needed
407: cmp pulXlate,0
408: je @F
409: mov eax,offset FLAT:cvt_to_4bpp ;Addreess of color xlate routine
410: @@:
411: mov pfnXlate,eax
412: jmp preproc_done
413:
414:
415: ; Destination is 1bpp. Copy most likely will require masking and phase
416: ; alignment.
417:
418: preproc_1bpp:
419: mov edi,00000007h ;A handy mask used a lot
420: xor ecx,ecx ;CL = lhs mask, CH = rhs mask
421: lea eax,[esi][edx] ;Compute rhs for later
422: test edx,edi ;See if partial byte
423: jz preproc_1bpp_done_lhs ;No partial lhs byte
424: mov ecx,edx
425: neg ecx
426: and ecx,edi ;CL = # bits in lhs, CH = 0
427: sub esi,ecx ;Compute # remaining bytes
428: mov cl,ajLeftMasks[ecx] ;Get lhs mask
429: jnc preproc_1bpp_done_lhs ;Didn't combine into one byte
430: and eax,edi ;Combine rhs mask with lhs mask
431: and cl,ajRightMasks[eax]
432: xor esi,esi ;No more bytes
433: xor eax,eax ;To show no rhs
434: jmp short preproc_1bpp_have_masks
435:
436: preproc_1bpp_done_lhs:
437: and eax,edi ;See if partial rhs byte
438: jz preproc_1bpp_have_masks ;No partial rhs byte
439: mov ch,ajRightMasks[eax]
440: sub esi,eax ;Compute # remaining bytes
441:
442: preproc_1bpp_have_masks:
443: mov jLeftMask,cl ;Set left and right masks
444: mov jRightMask,ch
445: shr esi,3 ;# of inner bytes for final copy
446: mov cCopy,esi
447:
448: ; Compute offset to first byte in destination DIB
449:
450: mov eax,edx
451: shr eax,3
452: add pjDst,eax
453:
454: ; Compute phase alignment parameters
455:
456: xor ecx,ecx ;Assume cjSkip is 0
457: and edx,edi
458: and ebx,edi
459: sub edx,ebx ;Determine phase alignment
460: jz preproc_finish_1bpp ;No phase alignment needed
461:
462: ; We're really shifting left, so we'll set it up to shift right a lot, and
463: ; get the first byte of the final move from byte 1 of the work area.
464:
465: adc ecx,ecx ;Set cjSkip = 0 or 1
466: and edx,edi ;3 LSBs is shift count
467: mov cRightShift,dl ;Phase for the shift
468: mov eax,cjScreenCopy ;Size of data in buffer
469: inc eax ;+ 1 to shift into last byte!
470: mov cjRightShift,eax
471: preproc_finish_1bpp:
472: mov cjSkip,ecx ;No skipping needed
473: mov esi,pulXlate ;Copy color translation table to the
474: lea edi,ajColorConv ; frame because we are out of regs.
475: mov ecx,16
476: @@:
477: lodsd
478: stosb
479: dec ecx
480: jnz @B
481:
482: mov pfnXlate,offset FLAT:cvt_to_1bpp
483:
484: preproc_done:
485:
486: process_next_scan:
487:
488: mov edi,offset FLAT:ajConvertBuffer
489: mov edx,EGA_BASE + GRAF_ADDR
490: mov eax,GRAF_READ_MAP
491: copy_next_plane:
492: mov esi,pjSrc ;ESI --> first Source byte
493: out dx,ax ;Set read plane
494: mov ecx,cjScreenCopy ;Set number of bytes to read
495: mov ebx,edi
496: rep movsb
497: lea edi,[ebx][CJ_WORK_PLANE];EDI --> next scan in convert buf
498: inc ah ;Set next read plane
499: cmp ah,4
500: jb copy_next_plane
501:
502: ; The scan has been read in from the VGA. Convert it into 4bpp format which
503: ; will be needed for doing the color conversion.
504:
505: lea edi,ajWork ;Convert dwords into here
506: mov esi,offset FLAT:ajConvertBuffer
507: mov ecx,cjScreenCopy ;# of source bytes to convert
508:
509: cvt_next_src_byte:
510: xor eax,eax
511: mov al,[esi][CJ_WORK_PLANE*3] ;Get data for plane C3
512: mov ebx,eax
513: and ebx,00001111b
514: shr eax,4
515: mov edx,aulHi16[ebx*4]
516: or dx,ausLo16[eax*2]
517: shl edx,1
518: mov al,[esi][CJ_WORK_PLANE*2] ;Get data for plane C2
519: mov ebx,eax
520: and ebx,00001111b
521: shr eax,4
522: or edx,aulHi16[ebx*4]
523: or dx,ausLo16[eax*2]
524: shl edx,1
525: mov al,[esi][CJ_WORK_PLANE*1] ;Get data for plane C1
526: mov ebx,eax
527: and ebx,00001111b
528: shr eax,4
529: or edx,aulHi16[ebx*4]
530: or dx,ausLo16[eax*2]
531: shl edx,1
532: lodsb ;Get data for plane C0
533: mov ebx,eax
534: and ebx,00001111b
535: shr eax,4
536: or edx,aulHi16[ebx*4]
537: or dx,ausLo16[eax*2]
538: mov eax,edx
539: stosd ;8 pels down!
540: dec ecx
541: jnz cvt_next_src_byte
542:
543:
544: ; Perform the format conversion
545: mov ecx,cjScreenCopy ;Set lopp count
546: lea esi,ajWork ;Set source pointer
547: mov edi,pjWork ;Set destination pointer
548: mov ebx,pulXlate ;Set color translate vector
549: xor eax,eax ;Init D31:D8 to 0
550: jmp pfnXlate ;Invoke correct conversion routine
551:
552: ; Convert from 4bpp to 8bpp with color translation
553:
554: cvt_to_8bpp:
555: lodsb ;Get two nibbles worth
556: mov edx,eax
557: shr eax,4
558: and edx,00001111b
559: mov al,[ebx][eax*4]
560: stosb
561: mov al,[ebx][edx*4]
562: stosb
563: lodsb ;Get two nibbles worth
564: mov edx,eax
565: shr eax,4
566: and edx,00001111b
567: mov al,[ebx][eax*4]
568: stosb
569: mov al,[ebx][edx*4]
570: stosb
571: lodsb ;Get two nibbles worth
572: mov edx,eax
573: shr eax,4
574: and edx,00001111b
575: mov al,[ebx][eax*4]
576: stosb
577: mov al,[ebx][edx*4]
578: stosb
579: lodsb ;Get two nibbles worth
580: mov edx,eax
581: shr eax,4
582: and edx,00001111b
583: mov al,[ebx][eax*4]
584: stosb
585: mov al,[ebx][edx*4]
586: stosb
587: dec ecx
588: jnz cvt_to_8bpp
589: jmp copy_to_dest
590:
591: ; Convert from 4bpp to 4bpp with color translation.
592:
593: cvt_to_4bpp:
594: lodsb ;Get two nibbles worth
595: mov edx,eax
596: shr eax,4
597: and edx,00001111b
598: mov al,[ebx][eax*4]
599: shl al,4
600: or al,[ebx][edx*4]
601: stosb
602: lodsb ;Get two nibbles worth
603: mov edx,eax
604: shr eax,4
605: and edx,00001111b
606: mov al,[ebx][eax*4]
607: shl al,4
608: or al,[ebx][edx*4]
609: stosb
610: lodsb ;Get two nibbles worth
611: mov edx,eax
612: shr eax,4
613: and edx,00001111b
614: mov al,[ebx][eax*4]
615: shl al,4
616: or al,[ebx][edx*4]
617: stosb
618: lodsb ;Get two nibbles worth
619: mov edx,eax
620: shr eax,4
621: and edx,00001111b
622: mov al,[ebx][eax*4]
623: shl al,4
624: or al,[ebx][edx*4]
625: stosb
626: dec ecx
627: jnz cvt_to_4bpp
628: jmp copy_to_dest
629:
630:
631: ; Convert from 4bpp to 1bpp with color translation.
632:
633:
634: cvt_to_1bpp:
635: lodsb ;Get two nibbles worth
636: mov edx,eax
637: shr eax,4
638: and edx,00001111b
639: mov bl,ajColorConv[eax]
640: shl bl,1
641: or bl,ajColorConv[edx]
642: lodsb
643: mov edx,eax
644: shr eax,4
645: and edx,00001111b
646: shl bl,1
647: or bl,ajColorConv[eax]
648: shl bl,1
649: or bl,ajColorConv[edx]
650: lodsb ;Get two nibbles worth
651: mov edx,eax
652: shr eax,4
653: and edx,00001111b
654: shl bl,1
655: or bl,ajColorConv[eax]
656: shl bl,1
657: or bl,ajColorConv[edx]
658: lodsb ;Get two nibbles worth
659: mov edx,eax
660: shr eax,4
661: and edx,00001111b
662: shl bl,1
663: or bl,ajColorConv[eax]
664: shl bl,1
665: or bl,ajColorConv[edx]
666: mov al,bl
667: stosb
668: dec ecx
669: jnz cvt_to_1bpp
670:
671:
672: ; Copy to the destination. This unfortunately may involve phase alignment
673:
674: copy_to_dest:
675: movzx ecx,cRightShift
676: jecxz copy_aligned_to_dest
677: mov edi,pjWork
678: mov ebx,cjRightShift
679: phase_align_it:
680: mov ah,dl ;Get previous unused bits
681: mov al,byte ptr [edi]
682: mov dl,al
683: shr eax,cl
684: stosb
685: dec ebx
686: jnz phase_align_it
687:
688: copy_aligned_to_dest:
689: mov esi,pjWork
690: add esi,cjSkip
691: mov edi,pjDst
692:
693: mov dl,jLeftMask
694: or dl,dl
695: jz @F
696: lodsb
697: mov ah,byte ptr [edi]
698: xor ah,al
699: and ah,dl
700: xor al,ah
701: stosb
702: @@:
703: mov ecx,cCopy
704: rep movsb
705:
706: mov dl,jRightMask
707: or dl,dl
708: jz @F
709: lodsb
710: mov ah,byte ptr [edi]
711: xor ah,al
712: and ah,dl
713: xor al,ah
714: stosb
715: @@:
716:
717: mov eax,ulScanWidth
718: add pjSrc,eax
719: mov eax,lDelta
720: add pjDst,eax
721: dec cyScans
722: jnz process_next_scan
723:
724: PLAIN_RET ;we're done with this bank
725:
726: xxxvConvertVGA2DIB endp
727:
728: end
729:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.