This repository has been archived by the owner on Nov 29, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBitmaps.a
1018 lines (917 loc) · 49.7 KB
/
Bitmaps.a
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
.INCLUDE GRAFTYPES.TEXT
;-----------------------------------------------------------
;
;
; **** *** ***** * * * **** ***
; * * * * ** ** * * * * * *
; * * * * * * * * * * * * *
; **** * * * * * * * **** ***
; * * * * * * ***** * *
; * * * * * * * * * * *
; **** *** * * * * * * ***
;
;
;
; QuickDraw Routines to operate on BitMaps.
;
.PROC StdBits,5
.REF CheckPic,PutPicByte,PutPicWord,PutPicRgn,PutPicData
.REF StretchBits,PackBits
;---------------------------------------------------------------
;
; PROCEDURE StdBits(VAR srcBits: BitMap;
; VAR srcRect: Rect;
; VAR dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle);
;
; A6 OFFSETS OF PARAMS AFTER LINK:
;
PARAMSIZE .EQU 18
SRCBITS .EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
SRCRECT .EQU SRCBITS-4 ;LONG, ADDR OF RECT
DSTRECT .EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE .EQU DSTRECT-2 ;WORD
MASKRGN .EQU MODE-4 ;LONG, RGNHANDLE
MYBITS .EQU -14 ;BITMAP
PACKBUF .EQU MYBITS-256 ;SCANLINE PACKING BUFFER
SRCPTR .EQU PACKBUF-4 ;LONG
DSTPTR .EQU SRCPTR-4 ;LONG
VARSIZE .EQU DSTPTR ;TOTAL BYTES OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS
JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE
BLE NOTPIC ;BRANCH IF NOT PICSAVE
MOVEQ #8,D6
;
; TRIM SRCBITS
;
MOVE.L SRCBITS(A6),A0 ;GET ADDR OF SRCBITS
LEA MYBITS(A6),A1 ;POINT TO MY COPY
MOVE.L BASEADDR(A0),A3 ;GET BASEADDR (CLOBBERS A3)
MOVE ROWBYTES(A0),D4 ;GET OLD ROWBYTES
MOVE.L BOUNDS+TOPLEFT(A0),BOUNDS+TOPLEFT(A1) ;COPY BOUNDS TOPLEFT
MOVE.L BOUNDS+BOTRIGHT(A0),BOUNDS+BOTRIGHT(A1) ;COPY BOUNDS BOTRIGHT
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE TOP(A0),D0 ;GET SRCRECT.TOP
SUB BOUNDS+TOP(A1),D0 ;SKIPTOP:=SRCRECT.TOP-BOUNDS.TOP
BLE.S TOPOK ;CONTINUE IF SKIPTOP NEG
ADD D0,BOUNDS+TOP(A1) ;NEWTOP := SRCRECT TOP
MULU D4,D0 ;CALC VERT OFFSET
ADD.L D0,A3 ;ADJUST BASEADDR
TOPOK MOVE BOTTOM(A0),D0 ;GET SRCRECT.BOTTOM
CMP BOUNDS+BOTTOM(A1),D0 ;IS SRCRECT BOT < BOUNDS BOT ?
BGE.S BOTOK ;NO, CONTINUE
MOVE D0,BOUNDS+BOTTOM(A1) ;YES, TRIM BOUNDS BOTTOM
BOTOK MOVE LEFT(A0),D0 ;GET SRCRECT.LEFT
SUB BOUNDS+LEFT(A1),D0 ;CALC SKIPLEFT
BLE.S LEFTOK ;CONTINUE IF SKIPLEFT NEG
LSR #3,D0 ;DIV BY 8 FOR SKIP BYTES
ADD D0,A3 ;OFFSET BASEADDR HORIZ
LSL #3,D0 ;BYTES TIMES 8 FOR DOTS
ADD D0,BOUNDS+LEFT(A1) ;ADD DOTS TO BOUNDS.LEFT
LEFTOK MOVE RIGHT(A0),D0 ;GET SRCRECT.RIGHT
SUB BOUNDS+LEFT(A1),D0 ;CONVERT TO GLOBAL
ADD #7,D0 ;ROUND UP
LSR #3,D0 ;TO NEXT MULT OF 8
LSL #3,D0
ADD BOUNDS+LEFT(A1),D0 ;RETURN TO LOCAL
CMP BOUNDS+RIGHT(A1),D0 ;IS RESULT < BOUNDS.RIGHT ?
BGE.S RIGHTOK ;NO, CONTINUE
MOVE D0,BOUNDS+RIGHT(A1) ;YES, TRIM RIGHT
RIGHTOK
;
; CALC NEW ROWBYTES AFTER TRIMMING
;
MOVE BOUNDS+RIGHT(A1),D5 ;GET TRIMMED RIGHT
SUB BOUNDS+LEFT(A1),D5 ;CALC WIDTH
ADD #15,D5 ;ROUND UP
LSR #4,D5 ;DIV BY 16
BLE BITSOK ;IGNORE IF NEWROW <= 0
ADD D5,D5 ;DOUBLE FOR NEW ROWBYTES
MOVE D5,ROWBYTES(A1) ;COPY ROWBYTES
MOVE.B #$90,-(SP) ;PUSH OPCODE=BITSRECT
TST.L MASKRGN(A6) ;IS MASKRGN NIL ?
BEQ.S NOTRGN ;YES, CONTINUE
ADD.B #1,(SP) ;REPLACE OPCODE=BITSRGN (IE. $91)
;FIXED BUG 12/3/83, RP
NOTRGN CMP D6,D5 ;IS NEWROW < 8 ?
BLT.S NOPACK ;YES, DONT BITPACK
ADD.B #8,(SP) ;SET BIT 3 FOR BITPACK
NOPACK JSR PutPicByte ;PUT OPCODE TO THEPIC
PEA MYBITS+ROWBYTES(A6) ;PUSH ADDR OF ROWBYTYES,BOUNDS
MOVE #10,-(SP) ;PUSH BYTECOUNT = 10
JSR PutPicData ;PUT ROWBYTES,BOUNDS TO THEPIC
MOVE.L SRCRECT(A6),-(SP)
MOVE D6,-(SP)
JSR PutPicData ;PUT SRCRECT
MOVE.L DSTRECT(A6),-(SP)
MOVE D6,-(SP)
JSR PutPicData ;PUT DSTRECT
MOVE MODE(A6),-(SP)
JSR PutPicWord ;PUT MODE
TST.L MASKRGN(A6) ;IS MASKRGN NIL ?
BEQ.S NOMASK ;YES, SKIP IT
MOVE.L MASKRGN(A6),-(SP) ;NO, PUSH MASKRGN
JSR PutPicRgn ;PUT MASKRGN TO THEPIC
NOMASK
;
; NOW PUT THE BITMAP DATA: IF NEWROW >= 8 THEN USE PACKBITS
;
LEA MYBITS(A6),A2 ;POINT TO (TRIMMED) BITMAP
MOVE BOUNDS+BOTTOM(A2),D7
SUB BOUNDS+TOP(A2),D7 ;HEIGHT := BOUNDS BOT - TOP
CMP D6,D5 ;IS NEWROW < 8 ?
BLT.S START2 ;YES, DONT TRY TO PACK
BRA.S START1 ;GO TO LOOP START
MORE1 MOVE.L A3,SRCPTR(A6) ;SRCPTR := ^SCANLINE DATA
LEA PACKBUF(A6),A0
MOVE.L A0,DSTPTR(A6) ;DSTPTR := @PACKBUF
PEA SRCPTR(A6) ;PUSH VAR SRCPTR
PEA DSTPTR(A6) ;PUSH VAR DSTPTR
MOVE D5,-(SP) ;PUSH SRCBYTES = NEWROW
JSR PackBits ;PACK ROW INTO PACKBUF
MOVE.L DSTPTR(A6),D6 ;GET UPDATED DSTPTR
LEA PACKBUF(A6),A0 ;POINT TO PACKBUF
SUB.L A0,D6 ;CALC PACKED BYTECOUNT
MOVE.B D6,-(SP)
JSR PutPicByte ;PUT PACKED BYTECOUNT TO THEPIC
PEA PACKBUF(A6)
MOVE D6,-(SP)
JSR PutPicData ;PUT PACKED DATA TO THEPIC
ADD D4,A3 ;ADD OLDROW TO BITS PTR
START1 DBRA D7,MORE1 ;LOOP FOR HEIGHT ROWS
BRA.S BITSOK
;
; ROWBYTES < 8, DONT USE PACKBITS
;
MORE2 MOVE.L A3,-(SP) ;PUSH ADDR OF BITS
MOVE D5,-(SP) ;PUSH BYTECOUNT = NEWROW
JSR PutPicData ;PUT ONE ROW OF BITMAP DATA
ADD D4,A3 ;ADD OLDROW TO BITS PTR
START2 DBRA D7,MORE2 ;LOOP FOR HEIGHT ROWS
BITSOK MOVE.L THEPORT(A4),A3 ;RESTORE THEPORT PTR
NOTPIC TST PNVIS(A3) ;IS PNVIS >= 0 ?
BLT.S GOHOME ;NO, QUIT
MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS
PEA PORTBITS(A3) ;PUSH DSTBITS = PORTBITS
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN
BNE.S MASKOK ;WAS IT NIL ?
MOVE.L WIDEOPEN(A4),(SP) ;YES, REPLACE WITH WIDEOPEN
MASKOK JSR STRETCHBITS ;CALL STRETCHBITS
GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'STDBITS '
.PROC CopyBits,6
.REF StdBits,ShieldCursor,ShowCursor,StretchBits
;---------------------------------------------------------------
;
; PROCEDURE CopyBits(srcBits,dstBits: BitMap;
; srcRect,dstRect: Rect;
; mode: INTEGER;
; maskRgn: RgnHandle *);
;
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 22 ;TOTAL BYTES OF PARAMS
SRCBITS .EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP
DSTBITS .EQU SRCBITS-4 ;LONG, ADDR OF BITMAP
SRCRECT .EQU DSTBITS-4 ;LONG, ADDR OF RECT
DSTRECT .EQU SRCRECT-4 ;LONG, ADDR OF RECT
MODE .EQU DSTRECT-2 ;WORD
MASKRGN .EQU MODE-4 ;LONG, RGNHANDLE
LINK A6,#0 ;NO LOCAL VARS
MOVEM.L D6-D7/A2-A4,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT
MOVE.L SRCBITS(A6),A2 ;POINT TO SRCBITS
MOVE.L BASEADDR(A2),D7 ;GET SRCBITS.BASEADDR
MOVE.L SCREENBITS+BASEADDR(A4),D6 ;GET SCREENBITS.BASEADDR
CMP.L D6,D7 ;IS SRC FROM THE SCREEN ?
BNE.S SRCOK ;NO, CONTINUE
MOVE.L SRCRECT(A6),-(SP) ;YES, PUSH SRCRECT
MOVE.L BOUNDS+TOPLEFT(A2),-(SP) ;PUSH OFFSET POINT
JSR SHIELDCURSOR ;HIDE THE CURSOR IF IN SRCRECT
;-----------------------------------------------------
;
; TEST IF DST IS TO THEPORT, (IF SO WE CLIP)
;
SRCOK MOVE.L DSTBITS(A6),A1 ;POINT TO DSTBITS
MOVE.L A3,D0 ;IS THEPORT NIL ?
BEQ.S NOTPORT ;YES, NOT TO THEPORT
BTST #0,D0 ;IS THEPORT ODD ?
BNE.S NOTPORT ;YES, NOT TO THEPORT
MOVE.L PORTBITS+BASEADDR(A3),D0 ;GET PORTBITS.BASEADDR
CMP.L BASEADDR(A1),D0 ;IS DST BASEADDR SAME ?
BNE.S NOTPORT ;NO, NOT TO THEPORT
MOVE.L PORTBOUNDS(A3),D0 ;GET PORT BOUNDS TOPLEFT
CMP.L BOUNDS(A1),D0 ;IS BOUNDS TOPLEFT SAME ?
BEQ.S TOPORT ;YES, ITS PROBABLY TO THEPORT
;
; DST IS DEFINITELY NOT TO THEPORT, SO WE CAN'T USE THE CAPTURE PROC.
; StretchBits(srcBits,dstBits,srcRect,dstRect,mode,wideOpen,wideOpen,maskRgn);
;
NOTPORT MOVE.L A2,-(SP) ;PUSH SRCBITS
MOVE.L A1,-(SP) ;PUSH DSTBITS
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L WIDEOPEN(A4),-(SP) ;PUSH WIDEOPEN
MOVE.L (SP),-(SP) ;PUSH WIDEOPEN
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN
BNE.S MASKOK ;WAS IT NIL ?
MOVE.L WIDEOPEN(A4),(SP) ;YES, REPLACE WITH WIDEOPEN
MASKOK JSR STRETCHBITS ;CALL STRETCHBITS
BRA.S CLEANUP ;AND CONTINUE
;
; DST IS PROBABLY TO THEPORT, SO WE USE THE CAPTURE PROC.
; CallBits(srcBits,srcRect,dstRect,mode,maskRgn)
;
TOPORT MOVE.L A2,-(SP) ;PUSH SRCBITS
MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE MODE(A6),-(SP) ;PUSH MODE
MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN (NIL OK)
MOVE.L GRAFPROCS(A3),D0 ;IS GRAFPROCS NIL ?
LEA STDBITS,A0
BEQ.S USESTD ;YES, USE STD PROC
MOVE.L D0,A0
MOVE.L BITSPROC(A0),A0 ;NO, GET PROC PTR
USESTD JSR (A0) ;CALL IT
CLEANUP CMP.L D6,D7 ;WAS SRC FROM THE SCREEN ?
BNE.S DONE ;NO, CONTINUE
JSR SHOWCURSOR ;YES, REPLACE CURSOR
DONE MOVEM.L (SP)+,D6-D7/A2-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'COPYBITS'
.PROC CopyMask
.REF RSect,HideCursor,ShowCursor,InitRgn,SeekRgn,XorSlab
;--------------------------------------------------------------
;
; PROCEDURE CopyMask(srcBits,maskBits,dstBits: BitMap;
; srcRect,maskRect,dstRect: Rect);
;
; NEW ROUTINE ADDED TO QUICKDRAW April 28, 1985
;
; Written by Bill Atkinson. CopyRight 1985 Apple Computer Inc.
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
paramSize .EQU 24 ;total bytes of params
srcBits .EQU paramSize+8-4 ;long, addr of BitMap
maskBits .EQU srcBits-4 ;long, addr of BitMap
dstBits .EQU maskBits-4 ;long, addr of BitMap
srcRect .EQU dstBits-4 ;long, addr of Rect
maskRect .EQU srcRect-4 ;long, addr of Rect
dstRect .EQU maskRect-4 ;long, addr of Rect
;-------------------------------------------------
;
; A6 OFFSETS OF LOCALS AFTER LINK:
;
MINRECT .EQU -8 ;RECT
RGNA .EQU MINRECT-4 ;RgnHandle
RGNB .EQU RGNA-4 ;RgnHandle
STATEA .EQU RGNB-RGNREC ;REGION STATE RECORD
STATEB .EQU STATEA-RGNREC ;REGION STATE RECORD
BUFLEFT .EQU STATEB-2 ;WORD
SRCADDR .EQU BUFLEFT-4 ;LONG
MASKADDR .EQU SRCADDR-4 ;LONG
DSTADDR .EQU MASKADDR-4 ;LONG
SRCROW .EQU DSTADDR-4 ;LONG
MASKROW .EQU SRCROW-4 ;LONG
DSTROW .EQU MASKROW-4 ;LONG
SAVESTK .EQU DSTROW-4 ;LONG
VARSIZE .EQU SAVESTK ;SIZE OF LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER
MOVE.L GRAFGLOBALS(A5),A2 ;point to QuickDraw globals
MOVE.L WIDEOPEN(A2),RGNA(A6) ;init RGNA to wideOpen
MOVE.L WIDEOPEN(A2),RGNB(A6) ;init RGNB to wideOpen
MOVE.L THEPORT(A2),A2 ;point to thePort
MOVE.L DSTBITS(A6),A4 ;A4 POINTS TO DSTBITS
MOVE.L DSTRECT(A6),A3 ;A3 POINTS TO DSTRECT
;
; if dst is in thePort, then clip to visRgn and clipRgn
;
MOVE.L portBits+baseAddr(A2),D0 ;get thePort^.portBits
CMP.L baseAddr(A4),D0 ;is dst on screen ?
BNE.S NOTPORT ;no, continue
MOVE.L CLIPRGN(A2),RGNA(A6) ;yes, clip to clipRgn
MOVE.L VISRGN(A2),RGNB(A6) ;and to visRgn
NOTPORT
;
; CALC MINRECT, THE INTERSECTION OF DSTRECT, DSTBITS.BOUNDS,
; AND TWO REGION BOUNDING BOXES. QUIT IF RESULT IS EMPTY.
;
MOVE.L A3,-(SP) ;PUSH DSTRECT
PEA BOUNDS(A4) ;PUSH DSTBITS.BOUNDS
MOVE.L RGNA(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH BOUNDING BOX
MOVE.L RGNB(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH BOUNDING BOX
MOVE #4,-(SP) ;PUSH NRECTS = 4
DOSECT PEA MINRECT(A6) ;PUSH WHERE TO PUT RESULT
JSR RSECT ;INTERSECT 4 RECTS
BEQ GOHOME ;QUIT IF EMPTY
JSR HideCursor ;ELSE HIDE THE CURSOR
;
; CALC BUFLEFT SO THAT RGNBUF WILL ALIGN TO DSTBITS
;
MOVE MINRECT+LEFT(A6),D1 ;GET MINRECT LEFT
SUB BOUNDS+LEFT(A4),D1 ;CONVERT TO GLOBAL COORDS
AND #$FFF0,D1 ;TRUNC TO MULT OF 16
ADD BOUNDS+LEFT(A4),D1 ;CONVERT BACK TO LOCAL
MOVE D1,BUFLEFT(A6) ;SAVE AS BUFLEFT
;
; INIT BOTH REGION STATE RECORDS AND ALLOCATE BUFFERS
;
MOVE.L RGNA(A6),A0 ;GET RGNHANDLE
LEA STATEA(A6),A1 ;POINT TO STATE RECORD
AGAIN MOVE.L (A0),A0 ;DE-REFERENCE RGNHANDLE
CMP #10,RGNSIZE(A0) ;IS IT RECTANGULAR ?
SEQ D7 ;REMEMBER FOR BELOW
MOVE MINRECT+LEFT(A6),D0 ;GET MINH
MOVE MINRECT+RIGHT(A6),D1 ;GET MAXH
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
JSR INITRGN ;INIT STATE, ALLOC BUFFER
;
; IF REGION WAS RECTANGULAR, DRAW TOP SCANLINE INTO ITS BUFFER
; AND SET UP THISV AND NEXTV SO SEEKRGN DOES NOTHING
;
TST.B D7 ;was region rectangular ?
BEQ.S NOTRECT ;no, continue
MOVE #-32767,THISV(A1) ;yes, say we're at infinity
MOVE #32767,NEXTV(A1) ;and next change is never
MOVE.L SCANBUF(A1),A0 ;point to buffer
MOVE MINRECT+LEFT(A6),D3 ;get minrect.left
SUB BUFLEFT(A6),D3 ;make buffer relative
MOVE MINRECT+RIGHT(A6),D4 ;get minrect.right
SUB BUFLEFT(A6),D4 ;make buffer relative
JSR XorSlab ;draw into buffer
NOTRECT LEA STATEB(A6),A0 ;point to state record B
CMP.L A0,A1 ;did we just do RGNB ?
BEQ.S GETDST ;yes, continue
MOVE.L A0,A1 ;no, point to STATEB
MOVE.L RGNB(A6),A0 ;get RGNB handle
BRA AGAIN ;and loop to init STATEB
;
; Set up dstRow and starting dstAddr
;
GETDST MOVE ROWBYTES(A4),D1 ;get dst rowBytes
EXT.L D1 ;make it long
MOVE.L D1,DSTROW(A6) ;save dstRow for later
MOVE MINRECT+TOP(A6),D0 ;get dst top
SUB BOUNDS+TOP(A4),D0 ;convert to global
MULU D1,D0 ;mult by rowbytes
MOVE.L BASEADDR(A4),A0 ;get dst baseAddr
ADD.L D0,A0 ;add vertical offset
MOVE MINRECT+LEFT(A6),D0 ;get dst left
SUB BOUNDS+LEFT(A4),D0 ;convert to global
LSR #4,D0 ;convert dots to words
ADD D0,D0 ;double for bytes
ADD D0,A0 ;add horizontal offset
MOVE.L A0,DSTADDR(A6) ;save result in dstAddr
;
; Set up srcRow, srcShift, and starting srcAddr
;
MOVE.L SRCRECT(A6),A1 ;point to srcRect
MOVE.L SRCBITS(A6),A2 ;point to srcBits
MOVE ROWBYTES(A2),D1 ;get src rowBytes
EXT.L D1 ;make it long
MOVE.L D1,SRCROW(A6) ;save srcRow for later
MOVE LEFT(A3),D6 ;get dst left
SUB BOUNDS+LEFT(A4),D6 ;convert to global
MOVE LEFT(A1),D1 ;get src left
SUB BOUNDS+LEFT(A2),D1 ;convert to global
SUB D1,D6 ;calc delta horiz
AND #$F,D6 ;mod 16 for srcShift
MOVE MINRECT+TOP(A6),D0 ;get clipped dst top
SUB TOP(A3),D0 ;convert from dst coords
ADD TOP(A1),D0 ;to src coords
SUB BOUNDS+TOP(A2),D0 ;convert to global
MULU ROWBYTES(A2),D0 ;mult by src rowbytes
MOVE.L BASEADDR(A2),A0 ;get src baseAddr
ADD.L D0,A0 ;add vertical offset
MOVE MINRECT+LEFT(A6),D0 ;get clipped dstLeft
SUB LEFT(A3),D0 ;convert from dst coords
ADD LEFT(A1),D0 ;to src coords
SUB BOUNDS+LEFT(A2),D0 ;convert to global
ADD D6,D0 ;add srcShift
LSR #4,D0 ;convert dots to words
ADD D0,D0 ;double for bytes
ADD D0,A0 ;add horiz offset
MOVE.L A0,SRCADDR(A6) ;save srcAddr for later
;
; Set up maskRow, maskShift, and starting maskAddr
;
MOVE.L MASKRECT(A6),A1 ;point to maskRect
MOVE.L MASKBITS(A6),A2 ;point to maskBits
MOVE ROWBYTES(A2),D1 ;get mask rowBytes
EXT.L D1 ;make it long
MOVE.L D1,MASKROW(A6) ;save maskRow for later
MOVE LEFT(A3),D7 ;get dst left
SUB BOUNDS+LEFT(A4),D7 ;convert to global
MOVE LEFT(A1),D1 ;get mask left
SUB BOUNDS+LEFT(A2),D1 ;convert to global
SUB D1,D7 ;calc delta horiz
AND #$F,D7 ;mod 16 for maskShift
MOVE MINRECT+TOP(A6),D0 ;get clipped dst top
SUB TOP(A3),D0 ;convert from dst coords
ADD TOP(A1),D0 ;to mask coords
SUB BOUNDS+TOP(A2),D0 ;convert to global
MULU ROWBYTES(A2),D0 ;mult by mask rowbytes
MOVE.L BASEADDR(A2),A0 ;get mask baseAddr
ADD.L D0,A0 ;add vertical offset
MOVE MINRECT+LEFT(A6),D0 ;get clipped dstLeft
SUB LEFT(A3),D0 ;convert from dst coords
ADD LEFT(A1),D0 ;to mask coords
SUB BOUNDS+LEFT(A2),D0 ;convert to global
ADD D7,D0 ;add maskShift
LSR #4,D0 ;convert dots to words
ADD D0,D0 ;double for bytes
ADD D0,A0 ;add horiz offset
MOVE.L A0,MASKADDR(A6) ;save maskAddr for later
;
; MAKE REGION BUFFERS CURRENT FOR THIS VERTICAL.
; THEN SET UP AND DRAW CURRENT SCANLINE.
;
MOVE MINRECT+TOP(A6),D5 ;init CURRENT VERTICAL
NEXTROW MOVE D5,D0 ;get current vert
LEA STATEA(A6),A1 ;point to state record A
JSR SEEKRGN ;seek region to current vert
MOVE D5,D0 ;get current vert
LEA STATEB(A6),A1 ;point to state record B
JSR SEEKRGN ;seek region to current vert
MOVE.L STATEA+SCANBUF(A6),A0 ;init REGION A PTR
MOVE.L STATEB+SCANBUF(A6),A1 ;init REGION B PTR
MOVE.L SRCADDR(A6),A2 ;init SRCPTR
MOVE.L MASKADDR(A6),A3 ;init MASKPTR
MOVE.L DSTADDR(A6),A4 ;init DSTPTR
MOVE STATEA+SCANSIZE(A6),D3 ;init LONGCOUNT
NEXTLONG MOVE.L -2(A2),D0 ;get a long of src
LSR.L D6,D0 ;align to dst
SWAP D0 ;put result in hi word
MOVE.L (A2)+,D1 ;get second long of src
LSR.L D6,D1 ;align to dst
MOVE.W D1,D0 ;assemble one long of src
MOVE.L -2(A3),D1 ;get a long of mask
LSR.L D7,D1 ;align to dst
SWAP D1 ;put result in hi word
MOVE.L (A3)+,D2 ;get second long of mask
LSR.L D7,D2 ;align to dst
MOVE.W D2,D1 ;assemble one long of mask
AND.L (A0)+,D1 ;and with RGNA buffer
AND.L (A1)+,D1 ;and with RGNB buffer
AND.L D1,D0 ;mask src data
NOT.L D1 ;form notmask
AND.L (A4),D1 ;get dst data
OR.L D1,D0 ;merge with src data
MOVE.L D0,(A4)+ ;store result into dst
DBRA D3,NEXTLONG ;loop all longs this scanline
;
; bump vertically and loop for all scanlines
;
MOVE.L SRCROW(A6),D0 ;GET SRC ROWBYTES
ADD.L D0,SRCADDR(A6) ;BUMP SRC TO NEXT ROW
MOVE.L MASKROW(A6),D0 ;GET MASK ROWBYTES
ADD.L D0,MASKADDR(A6) ;BUMP MASK TO NEXT ROW
MOVE.L DSTROW(A6),D0 ;GET DST ROWBYTES
ADD.L D0,DSTADDR(A6) ;BUMP DST TO NEXT ROW
ADD #1,D5 ;ADD ONE TO VERT
CMP MINRECT+BOTTOM(A6),D5 ;ARE WE AT THE BOTTOM ?
BNE NEXTROW ;NO, LOOP FOR ALL SCAN LINES
JSR SHOWCURSOR ;RESTORE CURSOR
GOHOME MOVE.L SAVESTK(A6),SP ;STRIP VARIABLE SIZED BUFFER
MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGISTERS
UNLINK PARAMSIZE,'CopyMask'
.PROC SeedFill
.DEF CalcMask
;-------------------------------------------------------------------------
;
; PROCEDURE SeedFill(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER;
; seedH,seedV: INTEGER)
;
MOVE.L (SP)+,A0 ;pop return addr
MOVEQ #-1,D0 ;get a long of -1
MOVE.L D0,-(SP) ;push edge = all ones
BRA.S SHARE ;share common code
;-------------------------------------------------------------------------
;
; PROCEDURE CalcMask(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER);
;
CalcMask MOVE.L (SP)+,A0 ;pop return addr
MOVEQ #-1,D0 ;get a long of -1
MOVE.L D0,-(SP) ;push seed = (-1,-1)
CLR.L -(SP) ;push edge = zeros
SHARE MOVE.L A0,-(SP) ;restore return addr
;-------------------------------------------------------------------------
;
; LOCAL PROCEDURE MakeMask(srcPtr,dstPtr: Ptr;
; srcRow,dstRow,height,words: INTEGER;
; seedH,seedV: INTEGER;
; edge: LongInt);
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
params .EQU 24
srcPtr .EQU params+8-4 ;long
dstPtr .EQU srcPtr-4 ;long
srcRow .EQU dstPtr-2 ;word
dstRow .EQU srcRow-2 ;word
height .EQU dstRow-2 ;word
words .EQU height-2 ;word
seedH .EQU words-2 ;word
seedV .EQU seedH-2 ;word
edge .EQU seedV-4 ;long
dstBump .EQU -2 ;word
saveStk .EQU dstBump-4 ;long
varSize .EQU saveStk ;total locals
LINK A6,#varSize ;allocate stack frame
MOVEM.L D3-D7/A2-A4,-(SP) ;save regs
MOVE.L SP,saveStk(A6) ;save stack pointer
;
; prepare height and words for DBRA count. Quit if either <= 0.
;
MOVE words(A6),D5 ;get count of words
BLE GOHOME ;quit if words <= 0
SUB #1,D5 ;subtract 1 for DBRA count
SUB #1,height(A6) ;convert height to DBRA
BLT GOHOME ;quit if height <= 0
;
; init dst to all ones:
;
MOVE words(A6),D0 ;get # of words
ADD D0,D0 ;double for bytes
MOVE dstRow(A6),D1 ;get dstRow
SUB D0,D1 ;subtract bytes for dstBump
MOVE D1,dstBump(A6) ;save dstBump for later
MOVE.L dstPtr(A6),A2 ;point to dst
MOVEQ #-1,D0 ;get some black
MOVE height(A6),D3 ;init DBRA rowCount
BLACK1 MOVE D5,D2 ;init DBRA wordCount
BLACK2 MOVE D0,(A2)+ ;put a word of black
DBRA D2,BLACK2 ;loop all words in row
ADD D1,A2 ;bump to next row
DBRA D3,BLACK1 ;loop height rows
;
; clear one dst pixel at seedH,seedV
;
MOVE seedV(A6),D0 ;get seed vert coord
BLT.S NOSEED ;skip if neg (no seed)
MULU dstRow(A6),D0 ;mul times dst row
MOVE.L dstPtr(A6),A0 ;point to dst
ADD D0,A0 ;add vertical offset
MOVE seedH(A6),D0 ;get seed horiz coord
MOVE D0,D1 ;copy seedH
LSR #3,D0 ;div by 8 for byte
NOT D1 ;invert bit number
BCLR D1,0(A0,D0) ;clear seed pixel
NOSEED
;
; allocate a scanline buffer of ones or zeros on the stack:
;
MOVE.L edge(A6),D6 ;get zero or all ones
MOVE D5,D1 ;get longCount
NEXTBUF MOVE D6,-(SP) ;write a word of ones or zeros
DBRA D1,NEXTBUF ;loop all words
MOVE.L srcPtr(A6),A0 ;point to top of src
MOVE.L dstPtr(A6),A2 ;point to top of dst
NXTPASS SF D7 ;clear dirty flag
MOVE height(A6),D4 ;get DBRA rowCount
MOVE.L SP,A1 ;point dst above to edgeBuf
;
; smear dst zeros down and to the right, smear limited by src.
;
NEXTROW MOVE.L D6,D1 ;init prev dst to edge
MOVE D5,D3 ;get DBRA wordCount
RNEXT MOVE (A2),D1 ;get dst word
BNE.S RDSTOK ;is it already zero ?
ADD #2,A0 ;yes, bump srcPtr
ADD #2,A1 ;bump dstAbove ptr
ADD #2,A2 ;bump dst ptr
SWAP D1 ;put prev dst in hi word
DBRA D3,RNEXT ;loop all words in row
BRA RDONE ;and continue below
RDSTOK MOVE (A0)+,D2 ;get src word
AND (A1)+,D1 ;smear zeros down
OR D2,D1 ;limit vertical smear by src
BRA.S RSTART ;go to loop start
RMORE MOVE D0,D1 ;update dst
RSTART MOVE.L D1,D0 ;copy dst and prev dst word
LSR.L #1,D0 ;shift right with carry from prev
AND D1,D0 ;smear zeros to the right
OR D2,D0 ;limit smear by src
CMP D1,D0 ;any changes ?
BNE RMORE ;yes, keep smearing
CMP (A2),D1 ;has dst changed ?
BEQ.S RSAME ;no, leave it alone
ST D7 ;yes, set dirty flag
RSAME MOVE D1,(A2)+ ;write dst to memory
SWAP D1 ;put prev dst in hi word
DBRA D3,RNEXT ;loop all words in row
RDONE
;
; smear dst zeros down and to the left, smear limited by src.
;
LSMEAR MOVE.L D6,D1 ;init prev dst to edge
MOVE D5,D3 ;get DBRA wordCount
LNEXT MOVE -(A2),D1 ;get dst word
BNE.S LDSTOK ;is dst already zero ?
SUB #2,A0 ;yes, just bump srcPtr
SUB #2,A1 ;bump dstAbove ptr
SWAP D1 ;put prev dst in hi word
DBRA D3,LNEXT ;loop all words in row
BRA.S LDONE ;and continue
LDSTOK MOVE -(A0),D2 ;get src word
AND -(A1),D1 ;smear zeros down
OR D2,D1 ;limit vertical smear by src
BRA.S LSTART ;go to loop start
LMORE MOVE D0,D1 ;update dst
LSTART MOVE.L D1,D0 ;copy dst and prev dst word
ROL.L #1,D0 ;shift left with carry from prev
AND D1,D0 ;smear zeros to the left
OR D2,D0 ;limit smear by src
CMP D1,D0 ;any changes ?
BNE LMORE ;yes, keep smearing
CMP (A2),D1 ;has dst changed ?
BEQ.S LSAME ;no, leave it alone
ST D7 ;yes, set dirty flag
MOVE D1,(A2) ;write dst to memory
LSAME SWAP D1 ;put prev dst in hi word
DBRA D3,LNEXT ;loop all words in row
LDONE
;
; bump three pointers down and loop for height scanlines
;
ADD srcRow(A6),A0 ;bump srcPtr down a row
ADD dstRow(A6),A2 ;bump dstPtr down a row
MOVE.L A2,A1 ;copy dstPtr
SUB dstRow(A6),A1 ;point to dst above
DBRA D4,NEXTROW ;loop all rows
;
; switch directions, adjust pointers, and loop till no change
;
NEG srcRow(A6) ;reverse src bump
NEG dstRow(A6) ;reverse dst bump
ADD srcRow(A6),A0 ;offset first src scanline
ADD dstRow(A6),A2 ;offset first dst scanline
TST.B D7 ;did anything change this pass ?
BNE NXTPASS ;yes go for another pass
;
; if seedFill, then invert dst
;
TST D6 ;is edge = black ?
BPL.S GOHOME ;no, we're done
MOVE dstBump(A6),D1 ;get dstBump
MOVE.L dstPtr(A6),A2 ;point to dst
MOVE height(A6),D3 ;init DBRA rowCount
INVERT1 MOVE D5,D2 ;init DBRA wordCount
INVERT2 NOT (A2)+ ;invert a word of dst
DBRA D2,INVERT2 ;loop all words in row
ADD D1,A2 ;bump to next row
DBRA D3,INVERT1 ;loop height rows
GOHOME MOVE.L saveStk(A6),SP ;restore stack pointer
MOVEM.L (SP)+,D3-D7/A2-A4 ;restore regs
UNLK A6 ;release stack frame
MOVE.L (SP)+,A0 ;pop return addr
ADD #params,SP ;strip params
JMP (A0) ;and return
.PROC ScrollRect,4
.REF NewRgn,RectRgn,SectRgn,CopyRgn,OffsetRgn,SetEmptyRgn
.REF DiffRgn,ShieldCursor,RgnBlt,ShowCursor
;---------------------------------------------------------------------
;
; PROCEDURE ScrollRect(dstRect: Rect; dh,dv: INTEGER; updateRgn: RgnHandle);
;
; Scroll a rectangular block of bits, erase and return an update region
;
; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK:
;
PARAMSIZE .EQU 12 ;TOTAL BYTES OF PARAMS
DSTRECT .EQU PARAMSIZE+8-4 ;LONG, ADDR OF RECT
DH .EQU DSTRECT-2 ;WORD
DV .EQU DH-2 ;WORD
UPDATERGN .EQU DV-4 ;LONG, RGNHANDLE
SRCRECT .EQU -8 ;RECT
VARSIZE .EQU SRCRECT ;TOTAL LOCALS
LINK A6,#VARSIZE ;ALLOCATE STACK FRAME
MOVEM.L D6-D7/A3-A4,-(SP) ;SAVE REGS
MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS
MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT
TST PNVIS(A3) ;IS PNVIS < 0 ?
BLT ABORT ;YES, QUIT FAST
TST.L DV(A6) ;ARE DH AND DV BOTH 0 ?
BEQ ABORT ;YES, QUIT FAST
CLR.L -(SP) ;ROOM FOR FCN RESULT
JSR NEWRGN ;ALLOCATE SRCRGN
MOVE.L (SP)+,D7 ;GET SRCRGN HANDLE IN D7
CLR.L -(SP) ;ROOM FOR FCN RESULT
JSR NEWRGN ;ALLOCATE DSTRGN
MOVE.L (SP)+,D6 ;GET DSTRGN HANDLE IN D6
;
; srcRgn := dstRect SECT visRgn SECT clipRgn
;
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
JSR RECTRGN ;RectRgn(srcRgn,dstRect);
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN
MOVE.L D7,-(SP) ;PUSH SRCRGN
JSR SECTRGN ;SectRgn(srcRgn,visRgn,srcRgn);
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN
MOVE.L D7,-(SP) ;PUSH SRCRGN
JSR SECTRGN ;SectRgn(srcRgn,clipRgn,srcRgn);
;
; dstRgn := offset srcRgn
;
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L D6,-(SP) ;PUSH DSTRGN
JSR COPYRGN ;CopyRgn(srcRgn,dstRgn);
MOVE.L D6,-(SP) ;PUSH DSTRGN
MOVE.L DV(A6),-(SP) ;PUSH DH,DV
JSR OFFSETRGN ;OffsetRgn(dstRgn,dh,dv);
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE.L (A0)+,SRCRECT(A6) ;COPY DSTRECT INTO SRCRECT
MOVE.L (A0)+,SRCRECT+4(A6)
MOVE.L DV(A6),D0 ;GET DH,DV
SUB D0,SRCRECT+LEFT(A6) ;OFFSET SRCRECT (-DH,-DV)
SUB D0,SRCRECT+RIGHT(A6)
SWAP D0 ;GET DV IN LO WORD
SUB D0,SRCRECT+TOP(A6)
SUB D0,SRCRECT+BOTTOM(A6)
;
; Compute updateRgn := srcRgn - dstRgn
;
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L D6,-(SP) ;PUSH DSTRGN
MOVE.L UPDATERGN(A6),-(SP) ;PUSH UPDATERGN
JSR DIFFRGN ;DiffRgn(srcRgn,dstRgn,updateRgn);
;
; ShieldCursor(dstRect,portBits.bounds.topLeft); { protect source }
;
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
MOVE.L PORTBITS+BOUNDS+TOPLEFT(A3),-(SP) ;PUSH OFFSET POINT
JSR SHIELDCURSOR ;REMOVE CRSR IF INTERSECTS
;
; Copy all bits which are in both srcRgn and dstRgn.
; RgnBlt(portBits,portBits,srcRect,dstRect,0,white,dstRgn,srcRgn,wideOpen);
;
PEA PORTBITS(A3) ;PUSH SRCBITS
MOVE.L (SP),-(SP) ;PUSH DSTBITS
PEA SRCRECT(A6) ;PUSH SRCRECT
MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT
CLR -(SP) ;PUSH MODE = SRCCOPY
CLR.L -(SP) ;PAT NOT USED
MOVE.L D6,-(SP) ;PUSH DSTRGN
MOVE.L D7,-(SP) ;PUSH SRCRGN
MOVE.L WIDEOPEN(A4),-(SP) ;PUSH WIDEOPEN
JSR RGNBLT ;COPY THE BITS
;
; Erase the update region
; RgnBlt(portBits,portBits,dstRect,dstRect,8,bkPat,updateRgn,wideOpen,wideOpen);
;
PEA PORTBITS(A3) ;PUSH SRCBITS
MOVE.L (SP),-(SP) ;PUSH DSTBITS
MOVE.L DSTRECT(A6),-(SP) ;PUSH SRCRECT
MOVE.L (SP),-(SP) ;PUSH DSTRECT
MOVE #8,-(SP) ;PUSH MODE = PATCOPY
PEA BKPAT(A3) ;PUSH PAT = BKPAT
MOVE.L UPDATERGN(A6),-(SP) ;PUSH UPDATERGN
MOVE.L WIDEOPEN(A4),-(SP) ;PUSH WIDEOPEN
MOVE.L (SP),-(SP) ;PUSH WIDEOPEN
JSR RGNBLT ;ERASE THE UPDATE RGN
JSR SHOWCURSOR ;RESTORE THE CURSOR
MOVE.L D7,A0 ;GET SRCRGN
_DisposHandle ;DISCARD IT
MOVE.L D6,A0 ;PUSH DSTRGN
_DisposHandle ;DISCARD IT
BRA.S DONE
ABORT MOVE.L UPDATERGN(A6),-(SP) ;PUSH UPDATERGN HANDLE
JSR SETEMPTYRGN ;SET IT TO EMPTY
DONE MOVEM.L (SP)+,D6-D7/A3-A4 ;RESTORE REGS
UNLINK PARAMSIZE,'SCROLLRE'
.PROC PackBits
.DEF UnpackBits
;---------------------------------------------------------------------
;
; PROCEDURE PackBits(VAR srcPtr,dstPtr: Ptr; srcBytes: INTEGER);
;
; Packs one scanline of data, compressing equal bytes.
; Returns updated srcPtr and dstPtr.
;
; Equates for parameters are shared with UnpackBits
;
PARAMSIZE .EQU 10 ;TOTAL BYTES OF PARAMS
SRCPTR .EQU PARAMSIZE+4-4 ;LONG, VAR
DSTPTR .EQU SRCPTR-4 ;LONG,VAR
SRCBYTES .EQU DSTPTR-2 ;WORD
DSTBYTES .EQU SRCBYTES ;ALIAS
MOVE.L A2,-(SP) ;SAVE REGS
MOVE.L SRCPTR+4(SP),A0 ;GET VAR ADDR
MOVE.L (A0),A0 ;GET SRCPTR ITSELF
MOVE.L DSTPTR+4(SP),A1 ;GET VAR ADDR
MOVE.L (A1),A1 ;GET DSTPTR ITSELF
MOVE SRCBYTES+4(SP),D1 ;GET SRCBYTES
SUB #1,D1 ;INIT SRC DBRA COUNT
BLT.S DONE ;QUIT IF SRCBYTES <= 0
MOVE.B (A0)+,D0 ;GET FIRST BYTE OF SRC
BRA.S START ;AND GO TO LOOP START
FILLOP MOVE.B -1(A0),D0 ;PUT SRCDATA IN DO
SUB A0,D2 ;COMPUTE FILLOP
ADD #1,D2
MOVE.B D2,(A2) ;STORE FILLOP
START MOVE A0,D2 ;REMEMBER SRCSTART
MOVE.L A1,A2 ;REMEMBER OPLOC
CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE
CMP.B (A0),D0 ;IS NEXT SRC THE SAME ?
BNE.S DOCOPY ;NO, USE COPY LOOP
CMP.B 1(A0),D0 ;THREE IN A ROW ?
BNE.S DOCOPY ;NO, USE COPY LOOP
BRA.S DOFILL ;YES, USE FILL LOOP
NXTCOPY MOVE.B (A0)+,D0 ;GET BYTE OF SRC
CMP.B (A0),D0 ;IS THE NEXT THE SAME ?
BNE.S DOCOPY ;NO, CONTINUE
CMP.B 1(A0),D0 ;THREE IN A ROW ?
BEQ.S COPYOP ;YES, END OF COPY RUN
DOCOPY MOVE.B D0,(A1)+ ;COPY DATA TO DST
DBRA D1,NXTCOPY ;AND LOOP FOR MORE
ENDCOPY SUB A0,D2 ;COMPUTE COPYOP
NEG D2 ;NEGATE ONLY
MOVE.B D2,(A2) ;INSTALL COPYOP
BRA.S DONE ;AND QUIT
COPYOP TST D1 ;IS THIS THE LAST SRC BYTE ?
BEQ DOCOPY ;YES, FINISH OFF COPY RUN
SUB A0,D2 ;COMPUTE COPYOP
NOT D2 ;NEGATE AND SUBTRACT 1
MOVE.B D2,(A2) ;STORE COPYOP
MOVE.L A0,D2 ;REMEMBER SRCSTART
MOVE.L A1,A2 ;REMEMBER OPLOC
CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE
DOFILL MOVE.B D0,(A1)+ ;COPY THE DATA BYTE
NXTFILL CMP.B (A0)+,D0 ;IS NEXT BYTE THE SAME ?
DBNE D1,NXTFILL ;LOOP TILL NOT SAME OR END SRC
BEQ.S ENDFILL ;BRANCH IF SRC EXHAUSTED
SUB #1,D1 ;COMPENSATE FOR DBNE DIDNT SUB
BGE FILLOP ;BR IF SRC NOT EXHAUSTED
ENDFILL SUB A0,D2 ;COMPUTE FILLOP
ADD #1,D2
MOVE.B D2,(A2) ;INSTALL FILLOP
DONE CLR.L D0 ;GET READY FOR WORD
MOVE SRCBYTES+4(SP),D0 ;GET SRCBYTES
MOVE.L SRCPTR+4(SP),A0 ;GET VAR ADDR OF SRCPTR
ADD.L D0,(A0) ;BUMP SRCPTR
MOVE.L DSTPTR+4(SP),A2 ;GET VAR ADDR OF DSTPTR
MOVE.L A1,(A2) ;UPDATE DSTPTR
MOVE.L (SP)+,A2 ;RESTORE REGS
SHARE MOVE.L (SP)+,A0 ;POP RETURN ADDR
ADD #PARAMSIZE,SP ;STRIP PARAMS
JMP (A0) ;AND RETURN
;--------------------------------------------------------
;
; PROCEDURE UnpackBits(VAR srcPtr,dstPtr: Ptr; dstBytes: INTEGER);
;
; Unpacks one scanline of data, as compressed by PackBits.
; Returns updated srcPtr and dstPtr.
;
; Equates for parameters are the same as PackBits!
;
UnpackBits
MOVE.L SRCPTR(SP),A0 ;GET ADDR OF SRCPTR
MOVE.L (A0),A0 ;GET SRCPTR ITSELF
MOVE.L DSTPTR(SP),A1 ;GET ADDR OF DSTPTR
MOVE.L (A1),A1 ;GET DSTPTR ITSELF
MOVE DSTBYTES(SP),D2 ;GET DSTBYTES
EXT.L D2 ;MAKE IT LONG
ADD.L A1,D2 ;LIMIT := DSTPTR + BYTECOUNT
BRA.S @3 ;GO TO LOOP START
@1 EXT.W D1 ;CLEAR HI BYTE OF COUNT
@2 MOVE.B (A0)+,(A1)+ ;COPY A BYTE OF DATA
DBRA D1,@2 ;LOOP ALL COPY BYTES
@3 CMP.L D2,A1 ;IS DSTPTR >= LIMIT ?
BHS.S @5 ;YES, WE'RE DONE
MOVE.B (A0)+,D1 ;NO, GET OPCODE
BPL.S @1 ;0..127 --> COPY 1..128 BYTES