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
/
Stretch.a
1164 lines (1015 loc) · 50.5 KB
/
Stretch.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
;------------------------------------------------------------------
;
; --> STRETCH.TEXT
;
.PROC StretchBits,8
.REF RgnBlt,RSect,ShieldCursor,ShowCursor
.REF InitRgn,SeekRgn,SetupStretch,ColorMap,XorSlab
;--------------------------------------------------------------
;
; PROCEDURE StretchBits(srcBits,dstBits: BitMap;
; srcRect,dstRect: Rect;
; mode: INTEGER
; rgnA,rgnB,rgnC: RgnHandle);
;
; Transfer a rectangle of bits from srcBits to dstBits,
; stretching or compressing according to srcRect and dstRect.
; The transfer is clipped to the intersection of rgnA, rgnB, and rgnC.
;
;
; Restrictions:
;
; transfer mode 0..7 only.
; if numer <> denom, then src and dst bitmaps do not overlap.
;
;
; COPYRIGHT APPLE COMPUTER INC.
; DESIGNED AND WRITTEN BY BILL ATKINSON
;
;----------------------------------------------------
;
; A6 OFFSETS OF PARAMETERS AFTER LINK:
;
PARAMSIZE .EQU 30 ;TOTAL BYTES OF PARAMETERS
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
RGNA .EQU MODE-4 ;RGNHANDLE
RGNB .EQU RGNA-4 ;RGNHANDLE
RGNC .EQU RGNB-4 ;RGNHANDLE
;-------------------------------------------------
;
; A6 OFFSETS OF LOCAL VARIABLES AFTER LINK:
;
NUMER .EQU -4 ;POINT
DENOM .EQU NUMER-4 ;POINT
VERROR .EQU DENOM-4 ;INTEGER
MINRECT .EQU VERROR-8 ;RECT
SRCBUF .EQU MINRECT-4 ;LONG
DSTBUF .EQU SRCBUF-4 ;LONG
SRCLONGS .EQU DSTBUF-2 ;WORD
DSTLONGS .EQU SRCLONGS-2 ;WORD
STATEA .EQU DSTLONGS-RGNREC ;RGN STATE RECORD
STATEB .EQU STATEA-RGNREC ;RGN STATE RECORD
STATEC .EQU STATEB-RGNREC ;RGN STATE RECORD
SAVESTK .EQU STATEC-4 ;LONG
RECTFLAG .EQU SAVESTK-2 ;WORD
MASKBUF .EQU RECTFLAG-4 ;LONG
BUFLEFT .EQU MASKBUF-2 ;WORD
BUFSIZE .EQU BUFLEFT-2 ;WORD
SRCADDR .EQU BUFSIZE-4 ;LONG
DSTADDR .EQU SRCADDR-4 ;LONG
SRCROW .EQU DSTADDR-4 ;LONG
DSTROW .EQU SRCROW-4 ;LONG
SRCLIMIT .EQU DSTROW-4 ;LONG
VERT .EQU SRCLIMIT-2 ;WORD
MODECASE .EQU VERT-4 ;LONG
PAT .EQU MODECASE-4 ;LONG, ADDR OF PAT
RATIOCASE .EQU PAT-4 ;LONG
FRACTION .EQU RATIOCASE-2 ;WORD
VARSIZE .EQU FRACTION ;SIZE OF LOCAL VARIABLES
LINK A6,#VARSIZE ;ALLOCATE LOCAL VARIABLES
MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS
MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER
;----------------------------------------------------------------
;
; CALC NUMER AND DENOM BASED ON DSTRECT AND SRCRECT.
; IF NUMER = DENOM THEN JUST CALL RGNBLT.
;
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE BOTTOM(A0),D0
SUB TOP(A0),D0 ;CALC DST HEIGHT
SWAP D0 ;PUT IN HI WORD
MOVE RIGHT(A0),D0
SUB LEFT(A0),D0 ;CALC DST WIDTH
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE BOTTOM(A0),D1
SUB TOP(A0),D1 ;CALC SRC HEIGHT
SWAP D1 ;PUT IN HI WORD
MOVE RIGHT(A0),D1
SUB LEFT(A0),D1 ;CALC SRC WIDTH
CMP.L D0,D1 ;ARE BOTH RECTS SAME SIZE
BNE.S STRETCH ;NO, CAN'T USE RGNBLT
XRGNBLT MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS
MOVE.L DSTBITS(A6),-(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 PAT(A6),-(SP) ;PAT ONLY USED FROM BELOW
MOVE.L RGNA(A6),-(SP) ;PUSH RGNA
MOVE.L RGNB(A6),-(SP) ;PUSH RGNB
MOVE.L RGNC(A6),-(SP) ;PUSH RGNC
JSR RGNBLT ;CALL RGNBLT
BRA GOHOME ;AND QUIT
STRETCH MOVE.L D0,NUMER(A6) ;NUMER := DST SIZE
MOVE.L D1,DENOM(A6) ;DENOM := SRC SIZE
JSR SetupStretch ;CALC CASEJUMP AND HORIZ FRACT
MOVE.L A0,RATIOCASE(A6) ;SAVE CASE JUMP FOR LATER
MOVE D0,FRACTION(A6) ;SAVE FRACTION FOR LATER
;----------------------------------------------------------------
;
; ADJUST MODE AND PATTERN FOR COLOR SEPARATION.
;
MOVE MODE(A6),-(SP) ;PUSH INPUT MODE
MOVE.L PAT(A6),-(SP) ;PUSH ADDR OF DUMMY PATTERN
JSR COLORMAP ;ALTER FOR COLOR SEPARATION
MOVE.L (SP)+,PAT(A6) ;GET (ALTERED) PATTERN
MOVE (SP)+,D2 ;GET (ALTERED) MODE
MOVE D2,D3 ;COPY MODE
ROR #4,D3 ;IS PATTERN BIT SET ?
BCS.S XRGNBLT ;YES, USE RGNBLT TO DO PAT
MOVE D2,MODE(A6) ;NO, UPDATE (ALTERED) MODE
;-------------------------------------------------------------------
;
; CALC MINRECT = INTERSECTION OF DSTRECT, DSTBITS.BOUNDS, AND THREE
; REGION BOUNDING BOXES. QUIT IF THE INTERSECTION IS EMPTY.
;
MOVE.L DSTBITS(A6),A3 ;POINT TO DST BITMAP
MOVE.L DSTRECT(A6),-(SP) ;PUSH ADDR OF DSTRECT
PEA BOUNDS(A3) ;PUSH ADDR OF DSTBITS.BOUNDS
MOVE.L RGNA(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH RGN BBOX
MOVE.L RGNB(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH RGN BBOX
MOVE.L RGNC(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
PEA RGNBBOX(A0) ;PUSH RGN BBOX
MOVE #5,-(SP) ;PUSH NRECTS
PEA MINRECT(A6) ;PUSH WHERE TO PUT RESULT
JSR RSECT ;INTERSECT ALL RECTS
BEQ GOHOME ;QUIT IF RESULT IS EMPTY
;----------------------------------------------------
;
; HIDE THE CURSOR IF IT INTERSECTS MINRECT
;
PEA MINRECT(A6) ;PUSH SHIELD RECT
MOVE.L BOUNDS+TOPLEFT(A3),-(SP) ;PUSH DELTA TO CONVERT TO GLOBAL
JSR SHIELDCURSOR ;REMOVE CURSOR IF INTERSECT
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR SRCBUF TO HOLD SRCWIDTH.
;
MOVE DENOM+H(A6),D0 ;GET SRC WIDTH
SUB #1,D0 ;SUBTRACT 1 PIXEL
LSR #5,D0 ;AND DIV BY 32 FOR LONGS
MOVE D0,SRCLONGS(A6) ;SAVE FOR LATER
CLR.L -(SP) ;CLEAR A LONG OF SLOP AT RIGHT
CLRSRC CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLRSRC ;LOOP ENTIRE BUFFER
MOVE.L SP,SRCBUF(A6); ;REMEMBER WHERE SRCBUF IS
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR DSTBUF TO HOLD DSTWIDTH.
;
MOVE NUMER+H(A6),D0 ;GET DST WIDTH
SUB #1,D0 ;SUBTRACT 1 PIXEL
LSR #5,D0 ;AND DIV BY 32 FOR LONGS
MOVE D0,DSTLONGS(A6) ;SAVE FOR LATER
CLR.L -(SP) ;CLEAR A LONG OF SLOP AT RIGHT
CLR.L -(SP) ;CLEAR ANOTHER LONG OF SLOP
CLRDST CLR.L -(SP) ;ALLOCATE AND CLEAR A LONG
DBRA D0,CLRDST ;LOOP ENTIRE BUFFER
MOVE.L SP,DSTBUF(A6); ;REMEMBER WHERE DSTBUF IS
;--------------------------------------------------------
;
; CALC BUFLEFT AND BUFSIZE FOR RGN SCANLINE BUFFERS
;
MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT
MOVE LEFT(A0),D1 ;GET DSTRECT LEFT
SUB BOUNDS+LEFT(A3),D1 ;CONVERT TO GLOBAL COORDS
AND #$FFF0,D1 ;TRUNC TO MULT OF 16
ADD BOUNDS+LEFT(A3),D1 ;CONVERT BACK TO LOCAL
MOVE D1,BUFLEFT(A6) ;SAVE AS BUFLEFT
MOVE MINRECT+RIGHT(A6),D0 ;GET MINRECT RIGHT
SUB D1,D0 ;CALC WIDTH IN DOTS
LSR #5,D0 ;DIV BY 32 FOR LONGS
MOVE D0,BUFSIZE(A6) ;BUFSIZE = # LONGS -1
;-----------------------------------------------------------------------
;
; ALLOCATE AND CLEAR A SCANLINE BUFFER FOR THE COMPOSITE MASK.
;
CLRMASK CLR.L -(SP) ;ALLOCATE AND CLEAR
DBRA D0,CLRMASK ;LOOP TILL DONE
MOVE.L SP,MASKBUF(A6); ;REMEMBER WHERE MASKBUF IS
;-------------------------------------------------------------------
;
; INIT STATE RECORDS VERT0 AND VERT1 IN CASE RECTANGULAR
;
MOVE #32767,D0
MOVE D0,STATEA+NEXTV(A6)
MOVE D0,STATEB+NEXTV(A6)
MOVE D0,STATEC+NEXTV(A6)
NEG D0
MOVE D0,STATEA+THISV(A6)
MOVE D0,STATEB+THISV(A6)
MOVE D0,STATEC+THISV(A6)
;----------------------------------------------------------------------
;
; ALLOCATE BUFFERS AND INIT STATE RECORDS FOR EACH NON-RECT REGION
;
MOVEQ #10,D7
CLR D5 ;INIT ALL RGNS RECT
MOVE.L RGNA(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D7 ;IS RGNA RECTANGULAR ?
BEQ.S ARECT ;YES, SKIP IT
ADD #2,D5 ;NO, SET UP FLAG
LEA STATEA(A6),A1 ;POINT TO STATE RECORD A
BSR.S INITONE ;INIT STATE, ALLOC BUFFER
ARECT
MOVE.L RGNB(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D7 ;IS RGNB RECTANGULAR ?
BEQ.S BRECT ;YES, SKIP IT
ADD #4,D5 ;NO, BUMP FLAG
LEA STATEB(A6),A1 ;POINT TO STATE RECORD B
BSR.S INITONE ;INIT STATE, ALLOC BUFFER
BRECT
MOVE.L RGNC(A6),A0 ;GET RGNHANDLE
MOVE.L (A0),A0 ;DE-REFERENCE IT
CMP RGNSIZE(A0),D7 ;IS RGNC RECTANGULAR ?
BEQ.S CRECT ;YES, SKIP IT
ADD #8,D5 ;NO, BUMP FLAG
LEA STATEC(A6),A1 ;POINT TO STATE RECORD C
PEA CRECT ;PUSH FAKE RETURN ADDR
INITONE MOVE MINRECT+LEFT(A6),D0 ;GET MINH
MOVE MINRECT+RIGHT(A6),D1 ;GET MAXH
MOVE BUFLEFT(A6),D2 ;GET BUFLEFT
JMP INITRGN ;INIT STATE, ALLOC BUFFER
CRECT
;--------------------------------------------------------------------
;
; IF ALL REGIONS ARE RECTANGULAR, THEN DRAW MINRECT INTO MASK BUFFER
;
MOVE.W D5,RECTFLAG(A6) ;ARE ALL RGNS RECT ?
BNE.S NOTRECT ;NO, CONTNUE
MOVE.L MASKBUF(A6),A0 ;YES, POINT TO MASK BUFFER
MOVE MINRECT+LEFT(A6),D3 ;SET UP LEFT
SUB BUFLEFT(A6),D3 ;MAKE IT BUFFER RELATIVE
MOVE MINRECT+RIGHT(A6),D4 ;SET UP RIGHT
SUB BUFLEFT(A6),D4 ;MAKE IT BUFFER RELATIVE
JSR XorSlab ;AND XOR BETWEEN THEM
NOTRECT
;------------------------------------------------------
;
; SET UP INVERT FLAG IN D7 TO REFLECT MODE BIT 2
;
CLR.L D7 ;SAY NOT INVERTED
MOVE MODE(A6),D2 ;GET TRANSFER MODE
BMI DONE ;QUIT IF MODE NEGATIVE
BCLR #2,D2 ;TEST AND CLR INVERT BIT
BEQ.S SETMODE ;SKIP IF NOT INVERTED
NOT.L D7 ;INVERTED; D7 GETS ALL 1'S
;--------------------------------------------------
;
; CALCULATE CASE JUMP FOR DIFFERENT TRANSFER MODES
;
SETMODE CMP #7,D2 ;IS MODE > 7 ?
BGT DONE ;YES, QUIT
LEA MODETAB,A0 ;POINT TO MODE TABLE
MOVE.B 0(A0,D2),D2 ;GET OFFSET
SUB D2,A0 ;COMPUTE ADDRESS
MOVE.L A0,MODECASE(A6) ;SAVE FOR LATER
;------------------------------------------------
;
; SET UP SRCROW, SRCLIMIT, SRCSHIFT, AND SRCADDR
;
MOVE.L SRCBITS(A6),A2 ;POINT TO SRCBITS
MOVE ROWBYTES(A2),D0 ;GET SRC ROWBYTES
EXT.L D0 ;AND EXTEND TO LONG
MOVE.L D0,SRCROW(A6) ;SRCROW := SRC ROWBYTES
MOVE BOUNDS+BOTTOM(A2),D1 ;GET SRCBITS.BOUNDS.BOTTOM
SUB BOUNDS+TOP(A2),D1 ;MAKE IT GLOBAL
MULU D0,D1 ;MULT BY SRC ROWBYTES
ADD.L BASEADDR(A2),D1 ;ADD BASEADDR
ADD.L #2,D1 ;ADJUST FOR -2(A0) SRC PICKUP
MOVE.L D1,SRCLIMIT(A6) ;SAVE RESULT AS SRCLIMIT
MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT
MOVE LEFT(A0),D1 ;GET SRCRECT LEFT
SUB BOUNDS+LEFT(A2),D1 ;CONVERT TO SRC GLOBAL
MOVE D1,D5 ;MAKE A COPY
NEG D5 ;NEGATE IT AND
AND #$F,D5 ;TREAT MOD 16 FOR SRCSHIFT
MOVE TOP(A0),D0 ;GET SRCRECT TOP
SUB BOUNDS+TOP(A2),D0 ;CONVERT TO SRC GLOBAL
MULU ROWBYTES(A2),D0 ;MULT BY SRC ROWBYTES
MOVE.L BASEADDR(A2),A0 ;GET START OF SRC BITMAP
ADD.L D0,A0 ;ADD VERTICAL OFFSET
ADD D5,D1 ;ADJUST SRCLEFT FOR SRCSHIFT
ASR #4,D1 ;CONVERT DOTS TO WORDS
ADD D1,A0 ;ADD HORIZONTAL OFFSET
ADD D1,A0 ;TWICE FOR BYTES
MOVE.L A0,SRCADDR(A6) ;SAVE AS SRCADDR
;----------------------------------------------------
;
; CALC STARTING DSTROW, DSTSHIFT, AND DSTADDR
;
MOVE ROWBYTES(A3),D0 ;GET DST ROWBYTES
EXT.L D0 ;EXTEND TO LONG
MOVE.L D0,DSTROW(A6) ;DSTROW := DST ROWBYTES
MOVE.L DSTRECT(A6),A0
MOVE TOP(A0),VERT(A6) ;INIT CURRENT VERTICAL
MOVE LEFT(A0),D1 ;GET DSTRECT LEFT
SUB BOUNDS+LEFT(A3),D1 ;CONVERT TO GLOBAL COORDS
MOVEQ #$F,D6
AND D1,D6 ;TREAT MOD 16 FOR SHIFTCNT
MOVE MINRECT+TOP(A6),D0 ;GET MINRECT TOP
SUB BOUNDS+TOP(A3),D0 ;CONVERT TO GLOBAL COORDS
MULU ROWBYTES(A3),D0 ;MULT BY DST ROWBYTES
MOVE.L BASEADDR(A3),A0 ;GET START OF DST BITMAP
ADD.L D0,A0 ;ADD VERTICAL OFFSET
ASR #4,D1 ;CONVERT DOTS TO WORDS
ADD D1,A0 ;ADD HORIZ OFFSET
ADD D1,A0 ;TWICE FOR BYTES
MOVE.L A0,DSTADDR(A6) ;SAVE AS DSTADDR
;-----------------------------------------------------
;
; INIT ERROR TERM FOR DDA
;
MOVE DENOM+V(A6),D0
LSR #1,D0
NEG D0
MOVE D0,VERROR(A6) ;VERROR := -DENOM.V/2
;-----------------------------------------------------
;
; GET FIRST SCANLINE OF SRC INTO SRCBUF
;
NEXTSRC MOVE.L SRCADDR(A6),A0 ;POINT TO SRC BITMAP
CMP.L SRCLIMIT(A6),A0 ;IS IT EXHAUSTED ?
BHS DONE ;YES, QUIT
MOVE.L SRCBUF(A6),A1 ;POINT TO SRCBUF
MOVE SRCLONGS(A6),D1 ;GET COUNT OF LONGS
NXTSRC2 MOVE.L -2(A0),D0 ;GET A LONG OF SRC
LSR.L D5,D0 ;ALIGN TO SRCBUF
MOVE D0,(A1)+ ;PUT A WORD TO SRCBUF
MOVE.L (A0)+,D0 ;GET A SECOND LONG
LSR.L D5,D0 ;ALIGN TO SRCBUF
MOVE D0,(A1)+ ;PUT A WORD TO SRCBUF
DBRA D1,NXTSRC2 ;LOOP FOR ALL LONGS
MOVE.L SRCROW(A6),D2 ;GET SRC ROWBYTES
ADD.L D2,SRCADDR(A6) ;BUMP SRC TO NEXT ROW
MOVE NUMER+V(A6),D0 ;GET NUMER.V
ADD D0,VERROR(A6) ;VERROR := VERROR + NUMER.V
BGT.S SRCOK ;SKIP IF VERROR > 0
;-----------------------------------------------------
;
; WHILE (VERROR < 0) DO MERGE OTHER SCANLINES INTO SRCBUF.
;
SRCLOOP MOVE.L SRCADDR(A6),A0 ;POINT TO SRC BITMAP
CMP.L SRCLIMIT(A6),A0 ;IS IT EXHAUSTED ?
BHS.S SRCOK ;YES, DONT GET ANY MORE
MOVE.L SRCBUF(A6),A1 ;POINT TO SRCBUF
MOVE SRCLONGS(A6),D1 ;GET COUNT OF LONGS
NXTSRC3 MOVE.L -2(A0),D0 ;GET A LONG OF SRC
LSR.L D5,D0 ;ALIGN TO SRCBUF
OR D0,(A1)+ ;OR A WORD TO SRCBUF
MOVE.L (A0)+,D0 ;GET A SECOND LONG
LSR.L D5,D0 ;ALIGN TO SRCBUF
OR D0,(A1)+ ;OR A WORD TO SRCBUF
DBRA D1,NXTSRC3 ;LOOP FOR ALL LONGS
ADD.L D2,SRCADDR(A6) ;BUMP SRC TO NEXT ROW
MOVE NUMER+V(A6),D0 ;GET NUMER.V
ADD D0,VERROR(A6) ;VERROR := VERROR + NUMER.V
MORESRC BLE.S SRCLOOP ;LOOP WHILE VERROR <= 0
SRCOK
;----------------------------------------------------------
;
; HORIZONTALLY STRETCH SRCBUF INTO DSTBUF
;
MOVE.L SRCBUF(A6),A0 ;POINT TO SRCBUF
MOVE.L DSTBUF(A6),A1 ;POINT TO DSTBUF
MOVE DSTLONGS(A6),D0 ;GET DSTLONGS
LSL #2,D0 ;QUAD FOR BYTE OFFSET
LEA 4(A1,D0),A2 ;SET UP DSTLIMIT
MOVE FRACTION(A6),D4 ;GET HORIZONTAL FRACTION
MOVE.L RATIOCASE(A6),A3 ;GET CASE JUMP
JSR (A3) ;AND CALL STRETCHROW
;-------------------------------------------------------
;
; TRANSFER ONE OR MORE COPIES OF DSTBUF INTO DSTBITS
;
NXTMASK MOVE VERT(A6),D0 ;GET CURRENT VERT COORD
CMP MINRECT+TOP(A6),D0 ;IS VERT < MINV ?
BLT.S NODRAW ;YES, DON'T DRAW
BSR SEEKMASK ;MAKE MASK BUFFER CURRENT
MOVE.L DSTBUF(A6),A3 ;INIT SRCPTR
MOVE.L DSTADDR(A6),A4 ;INIT DSTPTR FOR ROW
MOVE.L MASKBUF(A6),A2 ;INIT MASKPTR FOR ROW
MOVE BUFSIZE(A6),D2 ;INIT COUNT OF LONGS
MOVE.L MODECASE(A6),A0 ;GET MODE CASE JUMP
JMP (A0) ;TAKE MODE JUMP
NEXTDST MOVE.L DSTROW(A6),D0 ;GET DST ROWBYTES
ADD.L D0,DSTADDR(A6) ;BUMP DST TO NEXT ROW
NODRAW ADD #1,VERT(A6) ;BUMP TO NEXT VERT
MOVE VERT(A6),D0 ;GET VERT
CMP MINRECT+BOTTOM(A6),D0 ;ARE WE AT THE LAST SCAN LINE ?
BEQ.S DONE ;YES, QUIT
MOVE DENOM+V(A6),D0
SUB D0,VERROR(A6) ;VERROR := VERROR - DENOM.V
BGE NXTMASK ;IF VERROR >= 0 THEN DRAW MORE
BRA NEXTSRC ;ELSE GET NEXT SRC
;-----------------------------------------------------------------
;
; ENTIRE STRETCHBITS COMPLETE. RESTORE REGS AND STACK AND GO HOME.
;
DONE 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,'STRETCHB'
;-----------------------------------------------------------------
;
; LOCAL ROUTINE TO UPDATE MASK BUFFER TO CURRENT VERTICAL COORD.
;
SEEKMASK MOVE VERT(A6),D0 ;GET CURRENT VERT COORD
MOVE RECTFLAG(A6),D1 ;GET RECTFLAG = 0,2,4
MOVE RECTJMP(D1),D1 ;GET OFFSET FROM TABLE
JMP RECTJMP(D1) ;TAKE CASE JUMP
RECTJMP .WORD SEEKOK-RECTJMP
.WORD A-RECTJMP
.WORD B-RECTJMP
.WORD AB-RECTJMP
.WORD C-RECTJMP
.WORD AC-RECTJMP
.WORD BC-RECTJMP
.WORD ABC-RECTJMP
;--------------------------------------------------------------------
;
; ONLY REGION A IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
;
A LEA STATEA(A6),A1
BRA.S JMPSEEK
;--------------------------------------------------------------------
;
; ONLY REGION B IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
;
B LEA STATEB(A6),A1
BRA.S JMPSEEK
;--------------------------------------------------------------------
;
; ONLY REGION C IS NON RECTANGULAR. UPDATE IT AND USE IT AS THE MASK
;
C LEA STATEC(A6),A1
JMPSEEK MOVE.L MASKBUF(A6),SCANBUF(A1) ;PLAY DIRECTLY INTO MASKBUF
JMP SEEKRGN
;-------------------------------------------------------------------
;
; REGIONS A AND B ARE NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
AB LEA STATEA(A6),A1
JSR SEEKRGN
MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED
LEA STATEB(A6),A1
JSR SEEKRGN
OR (SP)+,D1 ;HAS EITHER RGN CHANGED ?
BEQ.S SEEKOK ;NO, WE'RE DONE
MOVE.L STATEA+SCANBUF(A6),A0
MOVE.L STATEB+SCANBUF(A6),A1
BRA.S CPY2BUF
;-------------------------------------------------------------------
;
; REGIONS A AND C ARE NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
AC LEA STATEA(A6),A1
JSR SEEKRGN
MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED
LEA STATEC(A6),A1
JSR SEEKRGN
OR (SP)+,D1 ;HAS EITHER RGN CHANGED ?
BEQ.S SEEKOK ;NO, WE'RE DONE
MOVE.L STATEA+SCANBUF(A6),A0
MOVE.L STATEC+SCANBUF(A6),A1
BRA.S CPY2BUF
;-------------------------------------------------------------------
;
; REGIONS B AND C ARE NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
BC LEA STATEB(A6),A1
JSR SEEKRGN
MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED
LEA STATEC(A6),A1
JSR SEEKRGN
OR (SP)+,D1 ;HAS EITHER RGN CHANGED ?
BEQ.S SEEKOK ;NO, WE'RE DONE
MOVE.L STATEB+SCANBUF(A6),A0
MOVE.L STATEC+SCANBUF(A6),A1
CPY2BUF MOVE.L MASKBUF(A6),A2
MOVE BUFSIZE(A6),D1
BCLOOP MOVE.L (A0)+,D0
AND.L (A1)+,D0
MOVE.L D0,(A2)+
DBRA D1,BCLOOP
SEEKOK RTS ;ALL 3 ARE RECT, DO NOTHING
;-------------------------------------------------------------------
;
; REGIONS A, B AND C ARE ALL NON-RECTANGULAR. UPDATE EACH,
; THEN FORM INTERSECTION IN THE MASK BUFFER.
;
ABC LEA STATEA(A6),A1
JSR SEEKRGN
MOVE D1,-(SP) ;REMEMBER IF RGN CHANGED
LEA STATEB(A6),A1
JSR SEEKRGN
OR D1,(SP) ;REMEMBER IF RGN CHANGED
LEA STATEC(A6),A1
JSR SEEKRGN
OR (SP)+,D1 ;HAS EITHER RGN CHANGED ?
BEQ.S ABCDONE ;NO, WE'RE DONE
MOVE.L STATEA+SCANBUF(A6),A0
MOVE.L STATEB+SCANBUF(A6),A1
MOVE.L STATEC+SCANBUF(A6),A2
MOVE.L MASKBUF(A6),A3
MOVE BUFSIZE(A6),D1
ABCLOOP MOVE.L (A0)+,D0
AND.L (A1)+,D0
AND.L (A2)+,D0
MOVE.L D0,(A3)+
DBRA D1,ABCLOOP
ABCDONE RTS
;---------------------------------------------------------------;
; ;
; INTERFACE TO EACH OF THE STRETCHBITS SCANLINE LOOPS: ;
; ;
; REGISTERS: A0: D0: ;
; A1: D1: ;
; A2: MASKPTR D2: LONGCNT ;
; A3: SRCPTR D3: ;
; A2: DSTPTR D4: ;
; A4: D5: SRCSHIFT ;
; A6: D6: DSTSHIFT ;
; A7: D7: INVERT ;
; ;
;---------------------------------------------------------------;
;-------------------------------------------------------
;
; MODE 0 OR 4: SRC --> DST
;
MASK0 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP
LSR.L D6,D0 ;ALIGN TO DST
SWAP D0 ;PUT INTO HI HALF OF D0
MOVE.L (A3)+,D1 ;GET SRC FROM BITMAP AND BUMP RIGHT
LSR.L D6,D1 ;ALIGN TO DST
MOVE D1,D0 ;ASSEMBLE ONE LONG
EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET
MOVE.L (A2)+,D1 ;GET MASK
AND.L D1,D0 ;MASK SRC
NOT.L D1 ;FORM NOTMASK
AND.L (A4),D1 ;GET DST DATA
OR.L D1,D0 ;MERGE WITH SRC DATA
MOVE.L D0,(A4)+ ;PUT RESULT IN DST
DBRA D2,MASK0 ;LOOP ALL LONGS THIS ROW
BRA NEXTDST ;GO FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 1 OR 5: SRC OR DST --> DST
;
MASK1 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP
LSR.L D6,D0 ;ALIGN TO DST
SWAP D0 ;PUT INTO HI HALF OF D0
MOVE.L (A3)+,D1 ;GET SRC FROM BITMAP
LSR.L D6,D1 ;ALIGN TO DST
MOVE D1,D0 ;ASSEMBLE ONE LONG
EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND.L (A2)+,D0 ;AND WITH MASK
OR.L D0,(A4)+ ;OR RESULT INTO DST
DBRA D2,MASK1 ;LOOP ALL LONGS THIS ROW
BRA NEXTDST ;LOOP FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 2 OR 6: SRC XOR DST --> DST
;
MASK2 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP
LSR.L D6,D0 ;ALIGN TO DST
SWAP D0 ;PUT INTO HI HALF OF D0
MOVE.L (A3)+,D1 ;GET SRC FROM BITMAP
LSR.L D6,D1 ;ALIGN TO DST
MOVE D1,D0 ;ASSEMBLE ONE LONG
EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND.L (A2)+,D0 ;AND WITH MASK
EOR.L D0,(A4)+ ;XOR RESULT INTO DST
DBRA D2,MASK2 ;LOOP ALL LONGS THIS ROW
BRA NEXTDST ;LOOP FOR NEXT ROW
;-------------------------------------------------------
;
; MODE 3 OR 7: SRC BIC DST --> DST
;
MASK3 MOVE.L -2(A3),D0 ;GET SRC FROM BITMAP
LSR.L D6,D0 ;ALIGN TO DST
SWAP D0 ;PUT INTO HI HALF OF D0
MOVE.L (A3)+,D1 ;GET SRC FROM BITMAP
LSR.L D6,D1 ;ALIGN TO DST
MOVE D1,D0 ;ASSEMBLE ONE LONG
EOR.L D7,D0 ;INVERT SRC IF MODE BIT 2 SET
AND.L (A2)+,D0 ;AND WITH MASK
NOT.L D0 ;INVERT FOR BIC
AND.L D0,(A4)+ ;BIC RESULT INTO DST
DBRA D2,MASK3 ;LOOP ALL LONGS THIS ROW
BRA NEXTDST ;LOOP FOR NEXT ROW
MODETAB .BYTE MODETAB-MASK0
.BYTE MODETAB-MASK1
.BYTE MODETAB-MASK2
.BYTE MODETAB-MASK3
.PROC SetupStretch
;--------------------------------------------------------------
;
; Routine to setup case jump for StretchRow,
; based on horiz numer and denom.
;
; Call SetupStretch with numer in D0, denom in D1.
; Returns case jump in A0, fraction in D0.
;
; Call resulting case jump with:
;
; A0: srcPtr
; A1: dstPtr
; A2: dstLimit
; D4: fraction
;
; clobbers D0-D3,A0-A1
;
LEA DONE,A0 ;POINT TO ABORT
TST D0 ;IS NUMER <= 0 ?
BLE FOUND ;YES, POINT TO ABORT
TST D1 ;IS DENOM <= 0 ?
BLE FOUND ;YES, POINT TO ABORT
LEA ONE,A0 ;POINT TO FAST COPY
CMP D1,D0 ;IS NUMER = DENOM ?
BEQ FOUND ;YES, USE FAST COPY
BLT.S SHRNKING ;NO, BRANCH IF SHRINKING
;
; We will be stretching. Calc fract = denom/numer and check for fast.
;
STRCHING MOVE D0,D3 ;MAKE A COPY OF NUMER
MOVE D1,D4 ;MAKE A COPY OF DENOM
CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE D1,-(SP) ;PUSH DENOM
MOVE D0,-(SP) ;PUSH NUMER
_FixRatio ;CALL FIXRATIO, < 1.0
MOVE.L (SP)+,D0 ;POP RESULT
LEA DOUBLE,A0 ;CHECK FOR FAST RATIOS
CMP #$8000,D0
BEQ.S FOUND
LEA QUAD,A0
CMP #$4000,D0
BEQ.S FOUND
LEA EIGHT,A0
CMP #$2000,D0
BEQ.S FOUND
LEA SIXTEEN,A0
CMP #$1000,D0
BEQ.S FOUND
LEA ONE.5,A0
CMP #$AAAA,D0
BEQ.S FOUND
LEA TRIPLE,A0
CMP #$5555,D0
BEQ.S FOUND
LEA SIX,A0
CMP #$2AAA,D0
BEQ.S FOUND
;
; check for any multiple of 8:
;
EXT.L D3 ;CLEAR HI WORD OF NUMER
DIVU D4,D3 ;CALC NUMER DIV DENOM
MOVE D3,D1 ;SAVE QUOTIENT
AND.L #$FFFF0007,D3 ;IS SCALE AN EVEN MULT OF 8 ?
BNE.S NOMATCH ;NO, USE GENERAL STRETCH
MOVE D1,D0 ;YES RETURN QUOTIENT IN D0
LEA EIGHTS,A0 ;POINT TO FAST ROUTINE
RTS ;AND RETURN
NOMATCH LEA STRETCH,A0 ;POINT TO SLOW GENERAL CODE
FOUND RTS ;RETURN WITH CASE JUMP IN A0
;
; We will be shrinking. Calc fract = numer/denom and check for fast.
;
SHRNKING CLR.L -(SP) ;ROOM FOR FCN RESULT
MOVE D0,-(SP) ;PUSH NUMER
MOVE D1,-(SP) ;PUSH DENOM
_FixRatio ;CALL FIXRATIO, < 1.0
MOVE.L (SP)+,D0 ;POP RESULT
LEA HALF,A0 ;CHECK FOR FAST RATIOS
CMP #$8000,D0
BEQ.S FOUND
LEA QRTR,A0
CMP #$4000,D0
BEQ.S FOUND
LEA THREE4,A0
CMP #$C000,D0
BEQ.S FOUND
LEA SHRINK,A0
BRA FOUND
;-----------------------------------------------
;
; NUMERATOR = DENOMINATOR, JUST COPY LONGS
;
ONE MOVE.L (A0)+,(A1)+ ;COPY ONE LONG
MOVE.L (A0)+,(A1)+ ;COPY ANOTHER LONG
CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ?
BLO ONE ;NO, LOOP FOR MORE
RTS ;ALL DONE
;---------------------------------------------------
;
; SHRINK TO THREE QUARTERS.
;
THREE4 MOVEQ #3,D3 ;MASK FOR HI 2 BITS
ROR.L #2,D3 ;IE. $C0000000
CLR.L -(SP) ;ALLOCATE A LONG OF TEMP
THREE4A MOVE.L (A0)+,D0 ;GET A LONG OF SRC
MOVEQ #7,D2 ;INIT COUNT OF 24 DST BITS
THREE4B ADD.L D0,D0 ;GET 1 BIT OF SRC
ADDX.L D1,D1 ;PUT 1 BIT TO DST
ADD.L D3,D0 ;PUT HI 2 BITS INTO CARRY
ADDX.L D1,D1 ;SHIFT INTO DST
LSL.L #3,D0 ;SHIFT LEFT 3 BITS
ADDX.L D1,D1 ;PUT CARRY BIT INTO DST
DBRA D2,THREE4B ;LOOP 8 TIMES
MOVE.L D1,(SP) ;STASH 3 DST BYTES IN TEMP
MOVE.B 1(SP),(A1)+ ;PUT FIRST BYTE TO DST
MOVE.B 2(SP),(A1)+ ;PUT SECOND BYTE TO DST
MOVE.B 3(SP),(A1)+ ;PUT THIRD BYTE TO DST
CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ?
BLO THREE4A ;NO, CONTINUE
ADD #4,SP ;YES, STRIP TEMP
RTS ;AND QUIT
;---------------------------------------------------
;
; SHRINK TO ONE HALF.
;
HALF MOVEQ #3,D3 ;MASK FOR HI 2 BITS
ROR.L #2,D3 ;IE. $C0000000
HALF1 MOVE.L (A0)+,D0 ;GET A LONG OF SRC
MOVEQ #7,D2 ;INIT COUNT OF 16 DST BITS
HALF2 ADD.L D3,D0 ;PUT OR OF HI BITS INTO CARRY
ADDX D1,D1 ;SHIFT BIT INTO DST
LSL.L #2,D0 ;SHIFT LEFT 2 BITS
ADD.L D3,D0 ;PUT OR OF HI BITS INTO CARRY
ADDX.L D1,D1 ;SHIFT BIT INTO DST
LSL.L #2,D0 ;SHIFT LEFT 2 BITS
DBRA D2,HALF2 ;LOOP 8 TIMES
MOVE D1,(A1)+ ;THEN PUT A WORD TO DST
CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ?
BLO HALF1 ;NO, CONTINUE
RTS ;YES, QUIT
;---------------------------------------------------
;
; SHRINK TO ONE QUARTER.
;
QRTR MOVE.L #$F0000000,D3 ;MASK FOR HI 4 BITS
QRTR1 MOVE.L (A0)+,D0 ;GET A LONG OF SRC
MOVEQ #7,D2 ;INIT COUNT OF 8 DST BITS
QRTR2 ADD.L D3,D0 ;PUT OR OF HI BITS INTO CARRY
ADDX.L D1,D1 ;SHIFT BIT INTO DST
LSL.L #4,D0 ;SHIFT LEFT 4 BITS
DBRA D2,QRTR2 ;LOOP 8 TIMES
MOVE.B D1,(A1)+ ;THEN PUT A BYTE TO DST
CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ?
BLO QRTR1 ;NO, CONTINUE
RTS ;YES, QUIT
;-----------------------------------------------
;
; STRETCH TO 1.5 TIMES AS WIDE
;
ONE.5 MOVE.B (A0)+,D0 ;GET FIRST BYTE FROM SRC
MOVE D0,D1 ;MAKE AN EXTRA COPY
LSR.B #4,D1 ;GET HI NIBBLE
MOVE.B TABLE15(D1),D2 ;EXPAND TO 6 BITS
LSL.L #6,D2 ;SHIFT OVER 6
AND #$F,D0 ;GET LO NIBBLE
MOVE.B TABLE15(D0),D2 ;EXPAND TO 6 BITS
LSL.L #6,D2 ;SHIFT OVER 6
MOVE.B (A0)+,D0 ;GET SECOND BYTE FROM SRC
MOVE D0,D1 ;MAKE AN EXTRA COPY
LSR.B #4,D1 ;GET HI NIBBLE
MOVE.B TABLE15(D1),D2 ;EXPAND TO 6 BITS
LSL.L #6,D2 ;SHIFT OVER 6
AND #$F,D0 ;GET LO NIBBLE
MOVE.B TABLE15(D0),D2 ;EXPAND TO 6 BITS
LSR.L #2,D2 ;RIGHT JUSTIFY
SWAP D2 ;FLIP WORDS
MOVE.B D2,(A1)+ ;PUT FIRST BYTE TO DST
SWAP D2 ;FLIP BACK AGAIN
MOVE D2,D1
ROR #8,D1
MOVE.B D1,(A1)+ ;PUT SECOND BYTE TO DST
MOVE.B D2,(A1)+ ;PUT THIRD BYTE TO DST
CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ?
BLO ONE.5 ;NO, LOOP FOR MORE
RTS ;ALL DONE
TABLE15 .BYTE $00,$0C,$10,$1C ;1.5 TIMES TABLE
.BYTE $60,$6C,$70,$7C
.BYTE $80,$8C,$90,$9C
.BYTE $E0,$EC,$F0,$FC
;-----------------------------------------------
;
; DOUBLE USING TABLE LOOKUP
;
DOUBLE MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC
MOVE D0,D1 ;MAKE AN EXTRA COPY
LSR.B #4,D1 ;GET HI NIBBLE
MOVE.B TABLE2(D1),(A1)+ ;DOUBLE FOR A BYTE
AND #$F,D0 ;GET LO NIBBLE
MOVE.B TABLE2(D0),(A1)+ ;DOUBLE FOR A BYTE
CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ?
BLO DOUBLE ;NO, LOOP FOR MORE
RTS ;ALL DONE
TABLE2 .BYTE $00,$03,$0C,$0F ;DOUBLING TABLE
.BYTE $30,$33,$3C,$3F
.BYTE $C0,$C3,$CC,$CF
.BYTE $F0,$F3,$FC,$FF
;-----------------------------------------------
;
; TRIPLE USING TABLE LOOKUP
;
TRIPLE MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC
MOVE D0,D1 ;MAKE AN EXTRA COPY
MOVE D0,D2 ;MAKE A THIRD COPY
LSR.B #5,D2 ;GET 3 HI BITS
MOVE.B TABLE3A(D2),(A1)+ ;PUT FIRST BYTE TO DST
LSR.B #2,D1
AND #$F,D1 ;GET MIDDLE 4 BITS
MOVE.B TABLE3B(D1),(A1)+ ;PUT SECOND BYTE TO DST
AND #$7,D0 ;GET 3 LO BITS
MOVE.B TABLE3C(D0),(A1)+ ;PUT THIRD BYTE TO DST
CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ?
BLO TRIPLE ;NO, LOOP FOR MORE
RTS ;ALL DONE
TABLE3A .BYTE $00,$03,$1C,$1F ;TRIPLING TABLE
.BYTE $E0,$E3,$FC,$FF
TABLE3B .BYTE $00,$01,$0E,$0F
.BYTE $70,$71,$7E,$7F
.BYTE $80,$81,$8E,$8F
.BYTE $F0,$F1,$FE,$FF
TABLE3C .BYTE $00,$07,$38,$3F
.BYTE $C0,$C7,$F8,$FF
;-----------------------------------------------
;
; QUADRUPLE USING TABLE LOOKUP
;
QUAD MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC
MOVE D0,D1 ;MAKE AN EXTRA COPY
AND #$F0,D1 ;MASK FOR HI NIBBLE
LSR #3,D1 ;SHIFT FOR TABLE INDEX
MOVE.W TABLE4(D1),(A1)+ ;PUT FIRST WORD TO DST
AND #$F,D0 ;MASK FOR LO NIBBLE
ADD D0,D0 ;DOUBLE FOR TABLE INDEX
MOVE.W TABLE4(D0),(A1)+ ;PUT SECOND WORD TO DST
CMP.L A2,A1 ;IS DSTPTR >= DSTLIMIT ?
BLO QUAD ;NO, LOOP FOR MORE
RTS ;ALL DONE
TABLE4 .WORD $0000,$000F,$00F0,$00FF ;QUADRUPLING TABLE
.WORD $0F00,$0F0F,$0FF0,$0FFF
.WORD $F000,$F00F,$F0F0,$F0FF
.WORD $FF00,$FF0F,$FFF0,$FFFF
;-----------------------------------------------
;
; STRETCH BY SIX USING TABLE LOOKUP
;
SIX MOVE.B (A0)+,D0 ;GET A BYTE FROM SRC
MOVE D0,D1 ;MAKE AN EXTRA COPY
AND #$E0,D1 ;MASK FOR HI 3 BITS