-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBITBLT.ASM
executable file
·1075 lines (834 loc) · 30.4 KB
/
BITBLT.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
page ,132
;----------------------------Module-Header------------------------------;
; Module Name: BITBLT.ASM
;
; BitBLT at level of device driver.
;
; Created: In Windows' distant past (c. 1983)
;
; Copyright (c) 1983 - 1987 Microsoft Corporation
;
;
; This is the main module of those comprising the source to BitBLT
; (Bit BLock Transfer) for Microsoft Windows display drivers. It
; defines the procedure, and performs general preprocessing for all BLT
; requests.
;
; BitBLT transfers a rectangle of bits from source to destination,
; doing some useful operations on the way, namely:
;
; o clipping the source rectangle to fit within the
; source device dimensions;
;
; o excluding the cursor;
;
; o performing a user-specified raster operation, out of
; a vast array of choices, which takes the form
;
; D = f(S,D,P)
;
; where S = source bit, D = destination bit, P = pattern
; bit, and f is a sequence of logical operations (AND, OR,
; XOR, NOT) on S, D, and P;
;
; o recognizing common special cases for accelerated processing.
;
;
; For a detailed explanation of the contortions BitBLT goes through
; to put your bits in place, see the file COMMENT.BLT.
;
;
; BitBLT consists of the following files:
;
; BITBLT.ASM procedure definition
; CBLT.ASM procedure to compile arbitrary BLT on stack
;
; GENLOCAL.BLT function parameters and generic locals
; CLRLOCAL.BLT color/monochrome-related locals
; DEVLOCAL.BLT device-related locals
;
; GENCONST.BLT generic constants
; CLRCONST.BLT color/monochrome constants
; DEVCONST.BLT constants used by device-dependent code
;
; GENDATA.BLT generic compiled code templates and data
; CLRDATA.BLT color/monochrome-dependent templates and data
; DEVDATA.BLT device-dependent code templates and data
;
; ROPDEFS.BLT constants relating to ROP definitions
; ROPTABLE.BLT table of ROP templates
;
; PDEVICE.BLT PDevice processing
; PATTERN.BLT pattern preprocessing
; COPYDEV.BLT copy device data into local frame
; COMPUTEY.BLT compute y-related values
;
; EXIT.BLT device-specific cleanup before exiting
; SPECIAL.BLT special case code
;
; COMMENT.BLT overview of history and design
;-----------------------------------------------------------------------;
THIS_IS_DOS_3_STUFF = 1 ; remove this line for DOS 5.0
title BitBLT
%out BitBlt
; This function will perform private stack checking. In order for
; private stack checking to occur, two symbols must be defined
; prior to the inclusion of CMACROS.INC. ?CHKSTK must be defined
; if the cmacros are to perform stack checking on procedures with
; local parameters. ?CHKSTKPROC must be defined if private stack
; checking will be used.
;
; The actual macro body for ?CHKSTKPROC will be defined later.
; (See MACROS.MAC).
?CHKSTK = 1
?CHKSTKPROC macro
endm
ifdef THIS_IS_DOS_3_STUFF
else
.286p
endif
; Define the portions of GDIDEFS.INC that will be needed by bitblt.
incLogical = 1 ;Include GDI logical object definitions
incDrawMode = 1 ;Include GDI DrawMode definitions
.xlist
include GDIDEFS.INC
include MACROS.MAC
include CMACROS.INC
include DISPLAY.INC
include CURSOR.INC
ifdef TEFTI
; include TEFTI.MAC
endif
ifdef THIS_IS_DOS_3_STUFF
else
; include FIREWALL.INC
; include DDC.INC
; include ERROR.INC
; include INSTANCE.INC
endif
.list
externA SCREEN_W_BYTES ;Screen width in bytes
ifdef THIS_IS_DOS_3_STUFF
externA ScreenSelector ;Segment of Regen RAM
endif
; externNP CBLT ;(must be NP, even though defined
; as FAR -- see CBLT.ASM)
ifdef EXCLUSION ;If cursor exclusion
externNP exclude ;Exclude area from screen
externNP unexclude ;Restore excluded area to screen
endif
ifdef THIS_IS_DOS_3_STUFF
sBegin Data
externB enabled_flag ;Non-zero if output allowed
sEnd Data
endif
sBegin Code
assumes cs,Code
assumes ds,Data
assumes es,nothing
; Following are the BitBLT include-files. Some are commented out
; because they contain address definitions are are included in
; CBLT.ASM, but are listed here for completeness. The remaining
; files include those that make up the local variable frame, and
; those containing subroutines. The frame-variable files are
; included immediately after the cProc BITBLT declaration. The
; subroutines files are included near the end of this file.
.xlist
; include GENCONST.BLT ;EQUs
; include CLRCONST.BLT ;EQUs
; include DEVCONST.BLT ;EQUs
; include GENDATA.BLT ;bitmask and phase tables
; include CLRDATA.BLT ;Color/mono specific templates,data
; include DEVDATA.BLT ;Driver specific templates,data
; include ROPDEFS.BLT ;Raster operation definitions
; include ROPTABLE.BLT ;Raster operation code templates
.list
cProc BITBLT,<FAR,PUBLIC>,<si,di>
.xlist
include GENLOCAL.BLT ;arguments and generic local vars
; include CLRLOCAL.BLT ;color/monochrome-related locals
; include DEVLOCAL.BLT ;device-related locals
.list
cBegin
mov ax, 1
cEnd
sEnd
end
;; mwehehe
jmp bitblt_exit
ife ??? ;If no locals
?CHKSTKPROC 0 ;See if room
endif
jnc bitblt_stack_ok ;There was room for the frame
jmp bitblt_stack_ov ;There was no room
bitblt_stack_ok:
mov al,enabled_flag ;Save enabled_flag while we still
mov local_enable_flag,al ; have DS pointing to Data
ifdef TEFTI_WHOLE
; timer_begin
endif
subttl ROP Preprocessing
page
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Get the encoded raster operation, and map the raster op if needed.
;
; To map the ROPS 80h through FFh to 00h through 7Fh, take the
; 1's complement of the ROP, and invert the "negate needed" flag.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
cld ;Let's make no assumptions about this!
xor ax,ax ;Assume not 80h : FFh
mov bx,seg_Rop
or bh,bh ;Outside the legal range?
jnz complain ; Yes, ignore it
or bl,bl ;Is this in the second half (80-FF)?
jns parse_10 ; No, rop index is correct
not bl ; Yes, want the inverse
mov ah,HIGH NEGATE_NEEDED ;Want to invert the not flag
errnz <LOW NEGATE_NEEDED>
parse_10:
add bx,bx ;Turn into a word index
xor ax,roptable[bx] ;Get ROP, maybe toggle negate flag
mov gl_operands,ax ;Save the encoded raster operation
mov bl,ah ;Set gl_the_flags for source and pattern
and bl,HIGH (SOURCE_PRESENT+PATTERN_PRESENT)
ror bl,1
errnz <SOURCE_PRESENT - 0010000000000000b>
errnz <PATTERN_PRESENT - 0100000000000000b>
errnz <F0_SRC_PRESENT - 00010000b>
errnz <F0_PAT_PRESENT - 00100000b>
jmp short parse_end
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; complain - complain that something is wrong
;
; An error is returned to the caller without BLTing anything.
;
; Entry: None
;
; Exit: AX = 0 (error flag)
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
complain:
xor ax,ax ;Set the error code
jmp bitblt_exit_fail
; v_exit - Just a vector to Exit
v_exit:
jmp bitblt_exit
parse_end:
call pdevice_processing
jc complain
test BH,F0_SRC_IS_DEV+F0_DEST_IS_DEV
jz dev_isnt_involved ;If the device is involved in
test local_enable_flag,0FFh ; the blt, then it must be
jz complain ; enabled
dev_isnt_involved:
call pattern_preprocessing
jc complain
subttl Input Clipping
page
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; GDI doesn't do input clipping. The source device must be clipped
; to the device limits, otherwise an exception could occur while in
; protected mode.
;
; The destination X and Y, and the extents have been clipped by GDI
; and are positive numbers (0-7FFFh). The source X and Y could be
; negative. The clipping code will have to check constantly for
; negative values.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
input_clipping:
input_clip_x:
mov si,xExt ;X extent will be used a lot
mov di,yExt ;Y extent will be used a lot
test gl_the_flags,F0_SRC_PRESENT;Is there a source?
jz input_clip_chk_null_blt ;No source, no input clipping needed
mov ax,SrcxOrg ;Will need source X org
mov bx,gl_src.width_bits ;Maximum allowable is width_bits-1
or ax,ax ;Any left edge overhang?
jns input_clip_rgt_edge ; No, left edge is on the surface
; The source origin is off the left hand edge of the device surface.
; Move both the source and destination origins right by the amount
; of the overhang and also remove the overhang from the extent.
;
; There is no need to check for the destination being moved off the
; right hand edge of the device's surface since the extent would go
; zero or negative were that to happen.
add si,ax ;Subtract overhang from X extent
js v_exit ;Wasn't enough, nothing to BLT
sub DestxOrg,ax ;Move destination left
xor ax,ax ;Set new source X origin
mov SrcxOrg,ax
; The left hand edge has been clipped. Now clip the right hand
; edge. Since both the extent and the source origin must be
; positive numbers now, any sign change from adding them together
; can be ignored if the comparison to bmWidth is made as an
; unsigned compare (maximum result of the add would be 7FFFh+7FFFh,
; which doesn't wrap past zero).
input_clip_rgt_edge:
add ax,si ;Compute right edge + 1
sub ax,bx ;Compute right edge overhang
jbe input_clip_save_xext ;No overhang
sub si,ax ;Subtract overhang from X extent
js v_exit ;Wasn't enough, nothing to BLT
input_clip_save_xext:
mov xExt,si ;Save new X extent
; Now clip the Y coordinates. The procedure is the same and all
; the above about positive and negative numbers still holds true.
input_clip_y:
mov ax,SrcyOrg ;Will need source Y org
mov bx,gl_src.height ;Maximum allowable is height-1
or ax,ax ;Any top edge overhang?
jns input_clip_btm_edge ; No, top is on the surface
; The source origin is off the top edge of the device surface.
; Move both the source and destination origins down by the amount
; of the overhang, and also remove the overhang from the extent.
;
; There is no need to check for the destination being moved off
; the bottom of the device's surface since the extent would go
; zero or negative were that to happen.
add di,ax ;Subtract overhang from Y extent
js v_exit ;Wasn't enough, nothing to BLT
sub DestyOrg,ax ;Move destination down
xor ax,ax ;Set new source Y origin
mov SrcyOrg,ax
; The top edge has been clipped. Now clip the bottom edge. Since
; both the extent and the source origin must be positive numbers
; now, any sign change from adding them together can be ignored if
; the comparison to bmWidth is made as an unsigned compare (maximum
; result of the add would be 7FFFh+7FFFh, which doesn't wrap thru 0).
input_clip_btm_edge:
add ax,di ;Compute bottom edge + 1
sub ax,bx ;Compute bottom edge overhang
jbe input_clip_save_yext ;No overhang
sub di,ax ;Subtract overhang from Y extent
js v_exit ;Wasn't enough, nothing to BLT
input_clip_save_yext:
mov yExt,di ;Save new Y extent
input_clip_chk_null_blt:
or si,si
jz v_exit ;X extent is 0
or di,di
jz v_exit ;Y extent is 0
input_clip_end:
subttl Cursor Exclusion
page
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Cursor Exclusion
;
; If either device or both devices are for the display, then
; the cursor must be excluded. If both devices are the display,
; then a union of both rectangles must be performed to determine
; the exclusion area.
;
; Currently:
; SI = X extent
; DI = Y extent
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
cursor_exclusion:
ifdef EXCLUSION
mov al,gl_the_flags
and al,F0_SRC_IS_DEV+F0_DEST_IS_DEV ;Are both memory bitmaps?
jz cursor_exclusion_end ; Yes, no exclusion needed
dec si ;Make the extents inclusive of the
dec di ; last point
mov cx,DestxOrg ;Assume only a destination on the
mov dx,DestyOrg ; display
test al,F0_SRC_IS_DEV ;Is the source a memory bitmap?
jz cursor_exclusion_no_union; Yes, go set right and bottom
test al,F0_DEST_IS_DEV ; (set 'Z' if dest is memory)
xchg ax,cx ; No, prepare for the union
mov bx,dx
mov cx,SrcxOrg ;Set source org
mov dx,SrcyOrg
jz cursor_exclusion_no_union;Dest is memory. Set right and bottom
; If the source/destination starting Y is greater than SCREEN_HEIGHT,
; then the blt is supporting a save_screen_bitmap call. In this case,
; we only want to exclude whichever rectangle is visible.
cmp bx,SCREEN_HEIGHT ;If destination is off the screen
jge cursor_exclusion_no_union ; then only use source rectangle
cmp dx,SCREEN_HEIGHT ;If source is off the screen
jl cursor_exclusion_not_ssb ; then only use dest rectangle
xchg ax,cx
mov dx,bx
jmp short cursor_exclusion_no_union
; The union of the two rectangles must be performed. The top left
; corner will be the smallest x and smallest y. The bottom right
; corner will be the largest x and the largest y added into the
; extents
cursor_exclusion_not_ssb:
cmp cx,ax ;Get smallest x
jle cursor_exclusion_y ;CX is smallest
xchg ax,cx ;AX is smallest
cursor_exclusion_y:
cmp dx,bx ;Get smallest y
jle cursor_exclusion_union ;DX is smallest
xchg dx,bx ;BX is smallest
cursor_exclusion_union:
add si,ax ;Set right
add di,bx ;Set bottom
jmp short cursor_exclusion_do_it ;Go do exclusion
cursor_exclusion_no_union:
add si,cx ;Set right
add di,dx ;Set bottom
cursor_exclusion_do_it:
call exclude ;Exclude the area from the screen
endif ;EXCLUSION
cursor_exclusion_end:
subttl Phase Processing (X)
page
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Now the real work comes along: In which direction will the
; copy be done? Refer to the 10 possible types of overlap that
; can occur (10 cases, 4 resulting types of action required).
;
; If there is no source bitmap involved in this particular BLT,
; then the path followed must allow for this. This is done by
; setting both the destination and source parameters equal.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
phase_processing:
phase_processing_x:
mov dx,xExt ;Get X extent
dec dx ;Make X extent inclusive
mov bx,DestxOrg ;Get destination X origin
mov di,bx
and bx,00000111b ;Get offset of destination within byte
; and set up BX for a base register!
; If there is no source, then just use the pointer to the destination
; bitmap and load the same parameters, which will cause the "equality"
; path to be followed in the set-up code. This path is the favored
; path for the case of no source bitmap.
mov ax,di ;Assume no source needed
test gl_the_flags,F0_SRC_PRESENT;Is a source needed?
jz phase_proc_10 ; No, just use destination parameters
mov ax,SrcxOrg ; Yes, get source origin X
mov gl_first_fetch,2 ; Assume two initial fetches (if no
; source, then it will be set = 1
; later)
phase_proc_10:
mov si,ax
and ax,00000111b ;Get offset of source within byte
cmp si,di ;Which direction will we be moving?
jl phase_proc_30 ;Move from right to left
; The starting X of the source rectangle is >= the starting X of
; the destination rectangle, therefore we will be moving bytes
; starting from the left and stepping right.
;
; Alternatively, this is the path taken if there is no source
; bitmap for the current BLT.
;
; Rectangle cases: 3,4,5,6,8
sub al,bl ;Compute horiz. phase (source-dest)
mov gl_step_direction,STEPRIGHT ;Set direction of move
mov ch,cs:[bx].bitmask_tbl1 ;Get starting byte mask
ja phase_proc_20 ;Scan line case 2, everything is
; already set for this case.
; Scan line cases 1 and 3:
;
; The correct first byte fetch needs to be set for the beginning
; of the outer loop, and the phase must be made into a positive
; number.
;
; This is the path that will be followed if there is no source bitmap
; for the current BLT.
mov gl_first_fetch,1 ;Set one initial fetch
; We now have the correct phase and the correct first character fetch
; routine set. Save the phase and ...
;
; currently: AL = phase
; BL = dest start mod 8
; CH = first byte mask
; DX = inclusive X bit count
; SI = source X start (if there is a source)
; DI = destination X start
;
phase_proc_20:
add al,8 ;Phase must be positive
and al,00000111b
; To calculate the last byte mask, the inclusive count can be
; added to the start X MOD 8 value, and the result taken MOD 8.
; This is attractive since this is what is needed later for
; calculating the inclusive byte count, so save the result
; of the addition for later.
add bx,dx ;Add inclusive extent to dest MOD 8
mov dx,bx ;Save for innerloop count !!!
and bx,00000111b ;Set up bx for a base reg
mov cl,cs:[bx].bitmask_tbl2 ;Get last byte mask
mov bl,al ;Compute offset into phase mask table
add bx,bx
mov bx,cs:[bx].phase_tbl1 ;Get the phase mask
; Currently:
; AL = phase
; BX = phase mask
; CL = last byte mask
; CH = first byte mask
; DX = inclusive bit count + dest start MOD 8
; SI = source X start (if there is a source)
; DI = destination starting X
jmp short phase_proc_50 ;Finish here
; The starting X of the source rectangle is < the X of the destination
; rectangle, therefore we will be moving bytes starting from the right
; and stepping left.
;
; This code should never be reached if there is no source bitmap
; for the current BLT.
;
; Rectangle cases: 1,2,7
phase_proc_30:
mov gl_step_direction,ah ;Set direction of move
errnz STEPLEFT
mov cl,cs:[bx].bitmask_tbl1 ;Get last byte mask
add ax,dx ;Find end of the source
; To calculate the first byte mask, the inclusive count is
; added to the start MOD 8 value, and the result taken MOD 8.
; This is attractive since this is what is needed later for
; calculating the inclusive byte count, so save the result
; of the addition for later.
add bx,dx ;Find end of the destination
add di,dx ;Will need to update dest start address
add si,dx ; and source's too
mov dx,bx ;Save inclusive bit count + start MOD 8
and ax,00000111b ;Get source offset within byte
and bx,00000111b ;Get dest offset within byte
mov ch,cs:[bx].bitmask_tbl2 ;Get start byte mask
sub al,bl ;Compute horiz. phase (source-dest)
jb phase_proc_40 ;Scan line case 5, everything is
; already set for this case.
; Scan line cases 4 and 6:
;
; The correct first byte fetch needs to be set for the beginning
; of the outer loop
mov gl_first_fetch,1 ;Set initial fetch routine
phase_proc_40:
add al,8 ;Ensure phase positive
and al,00000111b
; We now have the correct phase and the correct first character fetch
; routine set. Generate the phase mask and save it.
;
; currently: AL = phase
; CH = first byte mask
; CL = last byte mask
; DX = inclusive bit count + start MOD 8
mov ah,cl ;Save last mask
mov cl,al ;Create the phase mask
mov bx,00FFh ; by shifting this
shl bx,cl ; according to the phase
mov cl,ah ;Restore last mask
; jmp phase_proc_50 ;Go compute # of bytes to BLT
errn$ phase_proc_50
; The different processing for the different X directions has been
; completed, and the processing which is the same regardless of
; the X direction is about to begin.
;
; The phase mask, the first/last byte masks, the X byte offsets,
; and the number of innerloop bytes must be calculated.
;
;
; Nasty stuff coming up here! We now have to determine how
; many bits will be BLTed and how they are aligned within the bytes.
; This is how it's done (or how I'm going to do it):
;
; The number of bits (inclusive number that is) is added to the
; start MOD 8 value ( the left side of the rectangle, minimum X
; value), then the result is divided by 8. Then:
;
;
; 1) If the result is 0, then only one destination byte is being
; BLTed. In this case, the start & ending masks will be ANDed
; together, the innerloop count (# of full bytes to BLT) will
; be zeroed, and the gl_last_mask set to all 0's (don't alter any
; bits in last byte which will be the byte following the first
; (and only) byte).
;
; | x x x x x| |
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
; 0 1 2 3 4 5 6 7
;
; start MOD 8 = 3, extent-1 = 4
; 3+7 DIV 8 = 0, only altering one byte
;
;
;
; 2) If the result is 1, then only two bytes will be BLTed.
; In this case, the start and ending masks are valid, and
; all that needs to be done is set the innerloop count to 0.
; (it is true that the last byte could have all bits affected
; the same as if the innerloop count was set to 1 and the
; last byte mask was set to 0, but I don't think there would be
; much time saved special casing this).
;
; | x x x x x x x|x x x x x x x|
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
; 0 1 2 3 4 5 6 7
;
; start MOD 8 = 1, extent-1 = 14
; 3+14 DIV 8 = 1. There is a first and last
; byte but no innerloop count
;
;
;
; 3) If the result is >1, then there is some number of entire
; bytes to be BLted by the innerloop. In this case the
; number of innerloop bytes will be the result - 1.
;
; | x|x x x x x x x x|x
; |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
; 0 1 2 3 4 5 6 7
;
; start MOD 8 = 7, extent-1 = 9
; 7+9 DIV 8 = 2. There is a first and last
; byte and an innerloop count of 1 (result - 1)
;
; Currently: AL = horizontal phase
; BX = horizontal phase mask
; CH = first byte mask
; CL = last byte mask
; DX = left side X MOD 8 + inclusive X count
; SI = source start X
; DI = dest start X
phase_proc_50:
mov gl_phase_h,al ;Save horizontal phase
mov gl_mask_p,bx ;Save phase mask
shr dx,1 ;/8 to get full byte count
shr dx,1
shr dx,1
jnz phase_proc_60 ;Result is >0, check it out
; There will only be one byte affected. Therefore the two byte masks
; must be combined, the last byte mask cleared, and the innerloop
; count set to zero.
and ch,cl ;Combine the two masks
xor cl,cl ;Clear out the last byte mask
inc dx ;Now just fall through to set
errn$ phase_proc_60 ; the innerloop count to 0!
phase_proc_60:
dec dx ;Dec count (might become 0 just like
mov gl_inner_loop_count,dx ; we want), and save it
mov bl,ch
mov ch,cl ;Compute last byte mask
not cl ; and save it
mov gl_last_mask,cx
mov bh,bl ;Compute start byte mask
not bl ; and save it
mov gl_start_mask,bx
; There may or may not be a source bitmap for the following address
; computation. If there is no source, then the vertical setup code
; will be entered with both the source and destination Y's set to the
; destination Y and the address calculation skipped. If there is a
; source, then the address calculation will be performed and the
; vertical setup code entered with both the source and destination Y's.
phase_processing_y:
shiftr di,3 ;Compute byte offset of destination
; and add to current destination
; offset
add wptr gl_dest.lp_bits[0],di
mov dx,DestyOrg ;Get destination Y origin
mov ax,dx ;Assume no source
mov cl,gl_the_flags
test cl,F0_SRC_PRESENT ;Is a source needed?
jz phase_proc_70 ; No, skip source set-up
shiftr si,3 ;Compute byte offset of source
; and add to current source offset
add wptr gl_src.lp_bits[0],si
mov ax,SrcyOrg ;Get source Y origin
subttl Phase Processing (Y)
page
; The horizontal parameters have been calculated. Now the vertical
; parameters must be calculated.
;
; Currently:
; DX = destination Y origin
; AX = source Y origin (destination origin if no source)
; CL = gl_the_flags
phase_proc_70:
mov bx,yExt ;Get the Y extent of the BLT
dec bx ;Make it inclusive
; The BLT will be Y+ if the top of the source is below or equal
; to the top of the destination (cases: 1,4,5,7,8). The BLT
; will be Y- if the top of the source is above the top of the
; destination (cases: 2,3,6)
;
;
; !...................!
; !D !
; ____! ..x !
; |S ! : ! Start at top of S walking down
; | ! !
; | !...................!
; | :
; |____________________:
;
;
; __________________
; |S |
; | ..................... Start at bottom of S walking up
; | !D !
; | ! : !
; |____! ..x !
; ! !
; !....................
mov ch,INCREASE ;Set Y direction for top to bottom
cmp ax,dx ;Which direction do we move?
jge phase_proc_80 ;Step down screen (cases: 1,4,5,7,8)
; Direction will be from bottom of the screen up (Y-)
;
; This code will not be executed if there is no source since
; both Y's were set to the destination Y.
add dx,bx ;Find bottom scan line index for
add ax,bx ; destination and source
mov ch,DECREASE ;Set pattern increment
phase_proc_80:
mov gl_pat_row,dl ;Set pattern row and increment
mov gl_direction,ch
sar ch,1 ;Map FF==>FF, 01==>00
errnz DECREASE-0FFFFh
errnz INCREASE-00001h
; The Y direction has been computed. Compute the rest of the
; Y parameters. These include the actual starting address,
; the scan line and plane increment values, and whether or not
; the extents will cross a 64K boundary.
;
; Currently:
; DX = Y of starting destination scan
; AX = Y of starting source scan
; CH = BLT direction
; 00 = increasing BLT, Y+
; FF = decreasing BLT, Y-
; CL = gl_the_flags
; BX = inclusive Y extent
phase_proc_90:
test cl,F0_SRC_PRESENT ;Is a source needed?
mov cl,ch ; (Want CX = +/- 1)
jz phase_proc_100 ; No, skip source set-up
push dx ;Save destination Y
push bp ;Mustn't trash frame pointer
lea bp,gl_src ;--> source data structure
call compute_y ;Process as needed
pop bp
pop dx ;Restore destination Y
phase_proc_100:
push bp ;Mustn't trash frame pointer
mov ax,dx ;Put destination Y in ax
lea bp,gl_dest ;--> destination data structure
call compute_y
pop bp ;Restore frame pointer
call check_device_special_cases
jc bitblt_exit ;C ==> BLT done w/special case
subttl Memory allocation for BLT compilation
page
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; Allow room for the BLT code. The maximum that can be generated
; is defined by the variable MAX_BLT_SIZE. This variable must be
; an even number.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
assumes cs,Code
assumes ds,nothing
assumes es,nothing
cblt_allocate:
?CHKSTKPROC MAX_BLT_SIZE+20h ;See if room on stack ;See if room
jnc cblt_alloc_stack_ok ;There was room
jmp bitblt_exit_fail ;There was no room
cblt_alloc_stack_ok:
add sp,20h ;Take off the slop
mov di,sp
mov off_gl_blt_addr,di ;Save the address for later
mov ax,ss ;Set the segment for the BLT
mov es,ax
ifdef THIS_IS_DOS_3_STUFF
else
assumes ss,InstanceData
mov ax,proc_cs_alias
assumes ss,nothing
endif
mov seg_gl_blt_addr,ax ;Save the address for later
mov ax,cs ;Set data seg to CS so we can access
mov ds,ax ; code without overrides
xor cx,cx ;Clear out count register
assumes ds,Code
cCall CBLT ;compile the BLT onto the stack
subttl Invocation and Exit
page
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
; If the debug flag has been set, save the size of the created BLT
; so it may be returned to the caller.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
call_blt:
ifdef DEBUG
sub di,off_gl_blt_addr ;Compute the length
push di ; and save it
endif
; The BLT has been created on the stack. Set up the initial registers,
; set the direction flag as needed, and execute the BLT.
test gl_the_flags,F0_SRC_PRESENT ;Is there a source?
jz call_blt_get_dest_bits ; No, don't load its pointer
lds si,gl_src.lp_bits ;--> source device's first byte
call_blt_get_dest_bits:
les di,gl_dest.lp_bits ;--> destination device's first byte
mov cx,yExt ;Get count of lines to BLT
cld ;Assume this is the direction
cmp gl_step_direction,STEPRIGHT ;Stepping to the right?
jz call_blt_do_it ; Yes
std
call_blt_do_it:
push bp ;MUST SAVE THIS
ifdef TEFTI
timer_begin
endif
call gl_blt_addr ;Call the FAR process
ifdef TEFTI
timer_end
endif
pop bp
ifdef DEBUG
pop bx ;Get length of created BLT code