forked from microsoft/GW-BASIC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ADVGRP.ASM
1360 lines (1263 loc) · 33.4 KB
/
ADVGRP.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
; [ This translation created 10-Feb-83 by Version 4.3 ]
.RADIX 8 ; To be safe
CSEG SEGMENT PUBLIC 'CODESG'
ASSUME CS:CSEG
INCLUDE OEM.H
TITLE ADVGRP - ADVANCED GENERALIZED GRAPHICS STUFF
.RADIX 10
;Number of graphics planes. Used to
;calculate the array size in PUT/GET.
PWR2PX=(MELCO OR TETRA OR MCI OR SIRIUS)-1
;TRUE IF BITS/PIXEL IS ALWAYS POWER
;OF TWO. SAVES MULTIPLICATION.
TETRA=0
ZENITH=0
MCI=0
MELCO=0 ;Mitsubishi Electronics Co.
SIRIUS=0
HAL=0
HALL3=0
HALL4=0
ALPCPM=0
PC8A=0
MODEL3=0
TSHIBA=0
KANJSW=PC8A OR (TSHIBA AND (TRUROM-1))
;PUT @(x,y),KANJI(c) function,on,off
;
; MACHINE DEPENDENT SWITCHES
;
TILE=0
WINDOW=0
LINEST=0
VIEW=0
VIEW=MODEL3 OR PC8A OR TRSER2 ; SWITCH FOR GRAPHICS VIEW
TILE=MODEL3 OR PC8A OR TRSER2 OR HALL4
WINDOW=PC8A
QUEUE=MODEL3 OR PC8A OR TRSER2 OR GW
LINEST=MODEL3 OR PC8A OR TRSER2
DSEG SEGMENT PUBLIC 'DATASG'
ASSUME DS:DSEG
EXTRN QUELEN:WORD,PSNLEN:WORD,QUEINP:WORD,QUEOUT:WORD
DSEG ENDS
; MACHINE DEPENDENT GRAPHICS ROUTINES:
EXTRN SETATR:NEAR,_SETC:NEAR
EXTRN MAPXYC:NEAR,SCALXY:NEAR,FETCHC:NEAR,STOREC:NEAR
EXTRN DOWNC:NEAR,LEFTC:NEAR
EXTRN PGINIT:NEAR,PIXSIZ:NEAR,SCANL:NEAR,SCANR:NEAR,PNTINI:NEAR
EXTRN TUPC:NEAR
EXTRN TDOWNC:NEAR,NREAD:NEAR,NWRITE:NEAR,GTASPC:NEAR
; STUFF IN GENGRP.MAC:
EXTRN DOGRPH:NEAR,ATRSCN:NEAR,SCAN1:NEAR,SCAND:NEAR
DSEG SEGMENT PUBLIC 'DATASG'
EXTRN GRPACX:WORD,GRPACY:WORD,GXPOS:WORD,GYPOS:WORD,ATRBYT:WORD
DSEG ENDS
; OTHER STUFF:
EXTRN CHRGTR:NEAR,GETBYT:NEAR,GETIN2:NEAR,GETYPR:NEAR
EXTRN SYNCHR:NEAR
EXTRN UMULT:NEAR,MINUTK:NEAR,_FDIV:NEAR
EXTRN FCERR:NEAR
EXTRN MAKINT:NEAR
EXTRN POLKEY:NEAR
CKCNTC EQU POLKEY
MKINTC EQU MAKINT
EXTRN DCOMPR:NEAR
;
; MACRO DEFINITIONS
;
MOVRI MACRO B,C,D,E
INS86 271 ;;MOVI CX,
DB OFFSET C
DB OFFSET B
INS86 272 ;;MOVI DX,
DB OFFSET E
DB OFFSET D
ENDM
HLFDE MACRO
INS86 321,352 ;;SHR DX,1
ENDM
HLFHL MACRO
INS86 321,353 ;;SHR BX,1
ENDM
NEGDE MACRO
INS86 367,332
ENDM
NEGHL MACRO
INS86 367,333
ENDM
SUBTTL PAINT - Fill an area with color
;
; PAINT - FILL AN AREA WITH COLOR
;
; SYNTAX: PAINT (X,Y), FILLC, BORDC]]
;
PUBLIC PAINT
EXTRN PNTINI:NEAR,SCANL:NEAR,SCANR:NEAR,TUPC:NEAR,TDOWNC:NEAR
DSEG SEGMENT PUBLIC 'DATASG'
EXTRN PDIREC:WORD,CSAVEA:WORD,CSAVEM:WORD,MOVCNT:WORD,SKPCNT:WORD
EXTRN LFPROG:WORD,RTPROG:WORD
DSEG ENDS
PAINT: ;GET (X,Y) OF START
CALL INTQUE ;INIT QUE
CALL SCAN1
PUSH CX ;SAVE COORDS OF START
PUSH DX
CALL ATRSCN ;SET FILL ATTRIBUTE AS CURRENT
MOV AL,BYTE PTR ATRBYT ;DEFAULT BORDER COLOR IS SAME AS FILL
MOV DL,AL ;DEFAULT ATTRIBUTE TO [E] LIKE GETBYT
DEC BX
CALL CHRGTR
JZ SHORT GOTBRD ;NOTHING THERE - USE DEFAULT
CALL SYNCHR
DB OFFSET 44 ;MAKE SURE OF COMMA
CALL GETBYT ;GET BORDER COLOR ARGUMENT
GOTBRD: MOV AL,DL ;BORDER ATTRIBUTE TO A
CALL PNTINI ;INIT PAINT STUFF & CHECK BORDER ATTRIB
JAE SHORT ??L000
JMP FCERR
??L000:
POP DX ;GET BACK START COORDS
POP CX
PUSH BX ;SAVE TXTPTR UNTIL DONE
CALL CHKRNG ;MAKE SURE POINT IS ON SCREEN
CALL MAPXYC
MOV DX,1 ;ENTRY COUNT IS ONE (SKIP NO BORDER)
CALL SCANR1 ;SCAN RIGHT FROM INITIAL POSITION
JZ SHORT POPTRT ;STARTED ON BORDER - GET TXTPTR & QUIT
PUSH BX ;SAVE NO. OF POINTED PAINTED TO RIGHT
CALL SCANL1 ;NOW SCAN LEFT FROM INITIAL POS.
POP DX ;GET RIGHT SCAN COUNT.
ADD BX,DX ;ADD TO LEFT SCAN COUNT
XCHG BX,DX ;COUNT TO [DE]
MOV AL,LOW 64 ;MAKE ENTRY FOR GOING DOWN
CALL ENTST1
MOV CH,LOW 192 ;CAUSE PAINTING UP
JMP SHORT STPAIN ;START PAINTING UPWARD
POPTRT: POP BX ;GET BACK TEXTPTR
RET
;
; MAIN PAINT LOOP
;
PNTLOP:
CALL CKCNTC ;CHECK FOR CTRL-C ABORT
PNTLP1: CALL GETQ ;GET ONE ENTRY FROM QUEUE
MOV AL,CL ;NOW GO SET UP CURRENT LOCATION
CALL STOREC
STPAIN: MOV AL,CH ;GET DIRECTION
MOV BYTE PTR PDIREC,AL
ADD AL,AL ;SEE WHETHER TO GO UP, DOWN, OR QUIT
JZ SHORT POPTRT ;IF ZERO, ALL DONE.
PUSH DX ;SAVE SKPCNT IN CASE TUP&TDOWN DON'T
JAE SHORT PDOWN ;IF POSITIVE, GO DOWN FIRST
CALL TUPC ;MOVE UP BEFORE SCANNING
JMP SHORT PDOWN2
PDOWN: CALL TDOWNC ;SEE IF AT BOTTOM & MOVE DOWN IF NOT
PDOWN2: POP DX ;GET SKPCNT BACK
JB SHORT PNTLP1 ;OFF SCREEN - GET NEXT ENTRY
PNTLP2: ;SCAN RIGHT & SKIP UP TO SKPCNT BORDER
CALL SCANR1
JNZ SHORT ??L001
JMP PNTLP1 ;IF NO POINTS PAINTED, GET NEXT ENTRY
??L001:
CALL SCANL1 ;NOW SCAN LEFT FROM START POINT
MOV DL,BL ;[DE] = LEFT MOVCNT
MOV DH,BH
OR AL,AL ;SEE IF LINE WAS ALREADY PAINTED
JZ SHORT PNTLP3 ;IT WAS - DON'T MAKE OVERHANG ENTRY
DEC BX ;IF LMVCNT.GT.1, NEED TO MAKE ENTRY
DEC BX ;IN OPPOSITE DIRECTION FOR OVERHANG.
MOV AL,BH
ADD AL,AL ;SEE IF [HL] WAS .GT. 1
JB SHORT PNTLP3
MOV AL,BYTE PTR PDIREC
NOT AL
LAHF ; PUSH PSW
XCHG AL,AH
PUSH AX
XCHG AL,AH
CALL FETCHC ;GET CURRENT POINT ADDRESS
MOV CL,AL ;C=CMASK
POP AX ; POP PSW
XCHG AL,AH
SAHF ;GET BACK DIRECTION AND INDEX
MOV CH,AL
CALL PUTQ
PNTLP3: MOV BX,MOVCNT ;GET COUNT PAINTED DURING RIGHT SCAN
ADD BX,DX ;ADD TO LEFT MOVCNT
XCHG BX,DX ;ENTRY COUNT TO [DE]
CALL ENTSLR ;GO MAKE ENTRY.
MOV BX,CSAVEA ;SET CURRENT LOCATION BACK TO END
MOV AL,BYTE PTR CSAVEM ;OF RIGHT SCAN.
CALL STOREC
PNTLP4: MOV BX,SKPCNT ;CALC SKPCNT - MOVCNT TO SEE IF
MOV DX,MOVCNT ;ANY MORE BORDER TO SKIP
SUB BX,DX
JZ SHORT GOPLOP ;NO MORE - END OF THIS SCAN
JB SHORT PNTLP6 ;RIGHT OVERHANG - SEE IF ENTRY NEEDED
XCHG BX,DX ;SKIP COUNT TO [DE] FOR SCANR
CALL SCANR1 ;HERE IF NEED TO CONTINUE RIGHT SCAN
JZ SHORT GOPLOP ;NO MORE POINTS.
OR AL,AL ;SEE IF LINE ALREADY PAINTED
JZ SHORT PNTLP4 ;YES, DON'T ENTER ANYTHING
XCHG BX,DX ;ENTRY COUNT TO [DE]
MOV BX,CSAVEA ;MAKE ENTRY AT LOCATION SAVED BY SCANR
MOV AL,BYTE PTR CSAVEM ;SO WE CAN ENTER A POSITIVE SKPCNT
MOV CL,AL
MOV AL,BYTE PTR PDIREC
MOV CH,AL
CALL ENTSTK ;MAKE ENTRY
JMP SHORT PNTLP4 ;CONTINUE UNTIL SKPCNT .LE. 0
PNTLP6: NEGHL ;MAKE NEW SKPCNT POSITIVE
DEC BX ;IF SKPCNT-MOVCNT .LT. -1
DEC BX ;THEN RIGHT OVERHANG ENTRY IS NEEDED.
MOV AL,BH ;SEE IF POSITIVE.
ADD AL,AL
JB SHORT GOPLOP ;OVERHANG TOO SMALL FOR NEW ENTRY
RTOVH0: INC BX ;NOW MOVE LEFT TO BEGINNING OF SCAN
PUSH BX ;SO WE CAN ENTER A POSITIVE SKPCNT
XCHG BX,DX
RTOVH1: CALL LEFTC ;START IS -(SKPCNT-MOVCNT)-1 TO LEFT
DEC DX
OR DX,DX
JNZ SHORT RTOVH1
RTOVH2: POP DX ;GET BACK ENTRY SKPCNT INTO [DE]
MOV AL,BYTE PTR PDIREC ;MAKE ENTRY IN OPPOSITE DIRECTION
NOT AL
CALL ENTST1 ;MAKE ENTRY
GOPLOP: JMP PNTLOP ;GO PROCESS NEXT ENTRY
ENTSLR:
MOV AL,BYTE PTR LFPROG ;DON'T STACK IF SCANNED LINE
MOV CL,AL ;WAS ALREADY PAINTED
MOV AL,BYTE PTR RTPROG
OR AL,CL
JNZ SHORT $+3
RET ;Z IF SCAN LINE ALREADY PAINTED
ENTST0: MOV AL,BYTE PTR PDIREC
ENTST1: MOV CH,AL ;DIRECTION IN [B]
CALL FETCHC ;LOAD REGS WITH CURRENT "C"
MOV CL,AL ;BIT MASK IN [C]
ENTSTK:
ENTST9: JMP PUTQ
SCANR1: CALL SCANR ;PERFORM LOW LEVEL RIGHT SCAN
MOV SKPCNT,DX ;SAVE UPDATED SKPCNT
MOV MOVCNT,BX ;SAVE MOVCNT
OR BX,BX ;SET CC'S ON MOVCNT
MOV AL,CL ;GET ALREADY-PAINTED FLAG FROM [C]
MOV BYTE PTR RTPROG,AL
RET
SCANL1: CALL FETCHC ;GET CURRENT LOCATION
PUSH BX ;AND SWAP WITH CSV
PUSH AX
MOV BX,CSAVEA
MOV AL,BYTE PTR CSAVEM
CALL STOREC ;REPOS AT BEGINNING OF SCAN
POP AX ;REGET PLACE WHERE RT SCN STOPPED
POP BX
MOV CSAVEA,BX ;AND SAVE IT IN TEMP LOCATION
MOV BYTE PTR CSAVEM,AL
CALL SCANL ;NOW DO LOW LEVEL LEFT SCAN
MOV AL,CL ;GET ALREADY-PAINTED FLAG FROM [C]
MOV BYTE PTR LFPROG,AL ;WHETHER IT WAS ALREADY PAINTED
RET
;ROUTINE FOR INITIALISING QUEUE PARAMS
;QUELEN:CONTAINS QUEUE LENGTH
;PSNLEN:CONTAINS PRESENT QUEUE LENGTH
;QUEINP: QUEINPUT POINTER
;QUEOUT: QUEOUTPUT POINTER
INTQUE: PUSH BX
DSEG SEGMENT PUBLIC 'DATASG'
EXTRN STREND:WORD
DSEG ENDS
MOV BX,STREND ;GET BEGINNING OF FREE SPACE
XCHG BX,DX ;
PUSH DX
DSEG SEGMENT PUBLIC 'DATASG'
EXTRN FRETOP:WORD
DSEG ENDS
MOV BX,FRETOP ;GET END OF FREE SPACE
SUB BX,DX ;HL=FREE SPACE
MOV DX,1000D ;
CMP BX,DX ;IS IT LESSTHAN 1000 BYTES
JNAE SHORT ??L002
JMP INTQU2
??L002:
EXTRN GARBA2:NEAR
CALL GARBA2 ;CALL GARBAGE COLLECTION
INTQU2: POP DX ;GET BACK FREE START
MOV BX,FRETOP
SUB BX,DX
MOV DX,12D
CMP BX,DX
JAE SHORT ??L003
EXTRN OMERR:NEAR
JMP OMERR ;IF LESS THAN 12 BYTES GIVE MEMORY OVERFLOW
??L003:
MOV QUELEN,BX ;SET LENGTH OF QUEUE
MOV BX,0
MOV PSNLEN,BX ;SET PRESENT LENGTH
MOV BX,STREND ;HL=BEGINNING OF FREE SPACE
MOV QUEINP,BX ;
MOV QUEOUT,BX ;INIT QUEUE POINTERS
POP BX ;GET BACK CALLERS HL
RET
PUTQ: PUSH DX
PUSH BX
MOV BX,PSNLEN ;GET QUEUE PRESENT LENGTH
MOV DX,6 ;IS ENOUGH SPACE LEFT OUT
LAHF
ADD BX,DX
RCR SI,1
SAHF
RCL SI,1
MOV PSNLEN,BX ;UPDATE PRESENT LENGTH
MOV DX,QUELEN ;
CMP BX,DX ;
JNAE SHORT ??L004
JMP OMERR ;IF THE PRESENT LENGTH IS EQUAL TO MAX OR GREATER THEN GIVE ERROR
??L004:
MOV BX,QUEINP
CALL WRAP ;CHECK FOR WRAP AROUND CASE
POP DX
MOV BYTE PTR [BX],DL
LAHF
INC BX
SAHF
MOV BYTE PTR [BX],DH
LAHF
INC BX
SAHF
MOV BYTE PTR [BX],CL
LAHF
INC BX
SAHF
MOV BYTE PTR [BX],CH
LAHF
INC BX
SAHF
POP DX
MOV BYTE PTR [BX],DL
LAHF
INC BX
SAHF
MOV BYTE PTR [BX],DH
LAHF
INC BX
SAHF
MOV QUEINP,BX
RET
GETQ: MOV BX,PSNLEN
MOV AL,BH
OR AL,BL ;ANY ENTRYS ON STACK
MOV CH,LOW 0 ;FOR NO ENTRIES SET B TO ZERO
JNZ SHORT $+3
RET
MOV DX,6 ;DECREMENT QUEUE LENGTH BY 6
SUB BX,DX
MOV PSNLEN,BX
MOV BX,QUEOUT ;HL=DEQUE POINTER
CALL WRAP ;CHECK FOR WRAP AROUND
MOV DL,BYTE PTR [BX]
LAHF
INC BX
SAHF
MOV DH,BYTE PTR [BX]
LAHF
INC BX
SAHF
PUSH DX
MOV CL,BYTE PTR [BX]
LAHF
INC BX
SAHF
MOV CH,BYTE PTR [BX]
LAHF
INC BX
SAHF
MOV DL,BYTE PTR [BX]
LAHF
INC BX
SAHF
MOV DH,BYTE PTR [BX]
LAHF
INC BX
SAHF
MOV QUEOUT,BX
POP BX
RET
WRAP: PUSH BX ;
MOV DX,6
LAHF
ADD BX,DX
RCR SI,1
SAHF
RCL SI,1
MOV DX,FRETOP
CMP BX,DX ;ARE WE GOING OUT OF QUEUE END
POP BX
JNB SHORT $+3
RET ;NO
MOV BX,STREND ;SET TO BEGINNING OF QUEUE
RET
SUBTTL CIRCLE - Draw a circle
;
; CIRCLE - DRAW A CIRCLE
;
; SYNTAX: CIRCLE @(X,Y),RADIUS[,ATRB[,+/-STARTANG[,+/-ENDANG[,ASPECT]]]]
;
EXTRN GTASPC:NEAR
DSEG SEGMENT PUBLIC 'DATASG'
EXTRN ASPECT:WORD,CSTCNT:WORD,CENCNT:WORD,CRCSUM:WORD,CPLOTF:WORD
EXTRN CLINEF:WORD
EXTRN CNPNTS:WORD,CPCNT:WORD,CPCNT8:WORD,VALTYP:WORD,CXOFF:WORD
EXTRN CYOFF:WORD,CSCLXY:WORD
DSEG ENDS
PUBLIC CIRCLE
CIRCLE: CALL SCAN1 ;GET (X,Y) OF CENTER INTO GRPACX,Y
CALL SYNCHR
DB OFFSET 44 ;EAT COMMA
CALL GETIN2 ;GET THE RADIUS
PUSH BX ;SAVE TXTPTR
XCHG BX,DX
MOV GXPOS,BX ;SAVE HERE TILL START OF MAIN LOOP
CALL MKINTC ;PUT INTEGER INTO FAC
EXTRN FRCSNG:NEAR
CALL FRCSNG ;CONVERT TO SINGLE PRECISION
MOVRI 200O,65O,4O,363O ;LOAD REGS WITH SQR(2)/2
EXTRN FMULT:NEAR
CALL FMULT ;DO FLOATING PT MULTIPLY
EXTRN FRCINT:NEAR
CALL FRCINT ;CONVERT TO INTEGER & GET INTO [HL]
MOV CNPNTS,BX ;CNPNTS=RADIUS*SQR(2)/2=# PTS TO PLOT
XOR AL,AL ;ZERO OUT CLINEF - NO LINES TO CENTER
MOV BYTE PTR CLINEF,AL
MOV BYTE PTR CSCLXY,AL ;INITIALLY SCALING Y
POP BX ;REGET TXTPTR
CALL ATRSCN ;SCAN POSSIBLE ATTRIBUTE
MOV CL,LOW 1 ;SET LO BIT IN CLINEF FOR LINE TO CNTR
MOV DX,0 ;DEFAULT START COUNT = 0
CALL CGTCNT
PUSH DX ;SAVE COUNT FOR LATER COMPARISON
MOV CL,LOW 128D ;SET HI BIT IN CLINEF FOR LINE TO CNTR
MOV DX,OFFSET 0-1 ;DEFAULT END COUNT = INFINITY
CALL CGTCNT
POP SI ;XTHL
XCHG SI,BX
PUSH SI ;GET START COUNT, PUSH TXTPTR TILL DONE
XOR AL,AL
XCHG BX,DX ;REVERSE REGS TO TEST FOR .LT.
CMP BX,DX ;SEE IF END .GE. START
MOV AL,LOW 0
JAE SHORT CSTPLT ;YES, PLOT POINTS BETWEEN STRT & END
DEC AL ;PLOT POINTS ABOVE & BELOW
XCHG BX,DX ;SWAP START AND END SO START .LT. END
PUSH AX ;Swap sense of center line flags
MOV AL,BYTE PTR CLINEF
MOV CL,AL
ROL AL,1
ROL AL,1
OR AL,CL
ROR AL,1
MOV BYTE PTR CLINEF,AL ;Store swapped flags
POP AX
CSTPLT: MOV BYTE PTR CPLOTF,AL ;SET UP PLOT POLARITY FLAG
MOV CSTCNT,DX ;STORE START COUNT
MOV CENCNT,BX ;AND END COUNT
POP BX ;GET TXTPTR
DEC BX ;NOW SEE IF LAST CHAR WAS A COMMA
CALL CHRGTR
JNZ SHORT CIRC1 ;SOMETHING THERE
PUSH BX ;SAVE TXTPTR
CALL GTASPC ;GET DEFAULT ASPECT RATIO INTO [HL]
MOV AL,BH
OR AL,AL ;IS ASPECT RATIO GREATER THAN ONE?
JZ SHORT CIRC2 ;BRIF GOOD ASPECT RATIO
MOV AL,LOW 1
MOV BYTE PTR CSCLXY,AL
XCHG BX,DX ;ASPECT RATIO IS GREATER THAN ONE, USE INVERSE
JMP SHORT CIRC2 ;NOW GO CONVERT TO FRACTION OF 256
CIRC1: CALL SYNCHR
DB OFFSET 44 ;EAT COMMA
EXTRN FRMEVL:NEAR
CALL FRMEVL
PUSH BX ;SAVE TXTPTR
CALL FRCSNG ;MAKE IT FLOATING POINT
CALL CMPONE ;SEE IF GREATER THAN ONE
JNZ SHORT CIRC11 ;LESS THAN ONE - SCALING Y
INC AL ;MAKE [A] NZ
MOV BYTE PTR CSCLXY,AL ;FLAG SCALING X
CALL _FDIV ;RATIO = 1/RATIO
;MAKE NUMBER FRACTION OF 256
DSEG SEGMENT PUBLIC 'DATASG'
EXTRN FAC:WORD
DSEG ENDS
CIRC11: MOV BX,OFFSET FAC ;BY MULTIPLYING BY 2^8 (256)
MOV AL,BYTE PTR [BX]
ADD AL,LOW 8 ;ADD 8 TO EXPONENT
MOV BYTE PTR [BX],AL
CALL FRCINT ;MAKE IT AN INTEGER IN [HL]
CIRC2: MOV ASPECT,BX ;STORE ASPECT RATIO
;
; CIRCLE ALGORITHM
;
; [HL]=X=RADIUS * 2 (ONE BIT FRACTION FOR ROUNDING)
; [DE]=Y=0
; SUM =0
; LOOP: IF Y IS EVEN THEN
; REFLECT((X+1)/2,(Y+1)/2) (I.E., PLOT POINTS)
; IF X.LT.Y THEN EXIT
; SUM=SUM+2*Y+1
; Y=Y+1
; IF SUM.GGWGRP.RNO
; SUM=SUM-2*X+1
; X=X-1
; ENDIF
; GOTO LOOP
;
MOV DX,0 ;INIT Y = 0
MOV CRCSUM,DX ;SUM = 0
MOV BX,GXPOS ;X = RADIUS*2
ADD BX,BX
CIRCLP:
MOV AL,DL ;TEST EVENNESS OF Y
RCR AL,1 ;TO SEE IF WE NEED TO PLOT
JB SHORT CRCLP2 ;Y IS ODD - DON'T TEST OR PLOT
PUSH DX ;SAVE Y AND X
PUSH BX
INC BX ;ACTUAL COORDS ARE (X+1)/2,(Y+1)/2
HLFHL ;(PLUS ONE BEFORE DIVIDE TO ROUND UP)
INC DX
HLFDE
CALL CPLOT8
POP DX ;RESTORE X AND Y
POP BX ;INTO [DE] AND [HL] (BACKWARDS FOR CMP)
CMP BX,DX ;QUIT IF Y .GE. X
JNAE SHORT ??L005
JMP POPTRT ;GO POP TXTPTR AND QUIT
??L005:
XCHG BX,DX ;GET OFFSETS INTO PROPER REGISTERS
CRCLP2: MOV CX,BX ;[BC]=X
MOV BX,CRCSUM
INC BX ;SUM = SUM+2*Y+1
ADD BX,DX
ADD BX,DX
MOV AL,BH ;NOW CHECK SIGN OF RESULT
ADD AL,AL
JB SHORT CNODEX ;DON'T ADJUST X IF WAS NEGATIVE
PUSH DX ;SAVE Y
XCHG BX,DX ;[DE]=SUM
MOV BX,CX ;[HL]=X
ADD BX,BX ;[HL]=2*X-1
DEC BX
XCHG BX,DX ;PREPARE TO SUBTRACT
SUB BX,DX ;CALC SUM-2*X+1
DEC CX ;X=X-1
POP DX ;GET Y BACK
CNODEX: MOV CRCSUM,BX ;UPDATE CIRCLE SUM
MOV BX,CX ;GET X BACK TO [HL]
INC DX ;Y=Y+1
JMP SHORT CIRCLP
CPLSCX: PUSH DX
CALL SCALEY
POP BX ;GET UNSCALED INTO [HL]
MOV AL,BYTE PTR CSCLXY ;SEE WHETHER ASPECT WAS .GT. 1
OR AL,AL
JNZ SHORT $+3
RET ;DON'T SWAP IF ZERO
XCHG BX,DX
RET
;
; REFLECT THE POINTS AROUND CENTER
; [HL]=X OFFSET FROM CENTER, [DE]=Y OFFSET FROM CENTER
;
CPLOT8: MOV CPCNT,DX ;POINT COUNT IS ALWAYS = Y
PUSH BX ;SAVE X
MOV BX,0 ;START CPCNT8 OUT AT 0
MOV CPCNT8,BX
CALL CPLSCX ;SCALE Y AS APPROPRIATE
MOV CXOFF,BX ;SAVE CXOFF
POP BX ;GET BACK X
XCHG BX,DX
PUSH BX ;SAVE INITIAL [DE]
CALL CPLSCX ;SCALE X AS APPROPRIATE
MOV CYOFF,DX
POP DX ;GET BACK INITIAL [DE]
NEGDE ;START: [DE]=-Y,[HL]=X,CXOFF=Y,CY=X
CALL CPLOT4 ;PLOT +X,-SY -Y,-SX -X,+SY +Y,-SX
PUSH BX
PUSH DX
MOV BX,CNPNTS ;GET # PNTS PER OCTANT
MOV CPCNT8,BX ;AND SET FOR DOING ODD OCTANTS
MOV DX,CPCNT ;GET POINT COUNT
SUB BX,DX ;ODD OCTANTS ARE BACKWARDS SO
MOV CPCNT,BX ;PNTCNT = PNTS/OCT - PNTCNT
MOV BX,CXOFF ;NEED TO NEGATE CXOFF TO START OUT RIGHT
NEGHL
MOV CXOFF,BX
POP DX
POP BX
NEGDE ;ALSO NEED TO MAKE [DE]=-SX=-[DE]
;PLOT +Y,-SX -X,-SY -Y,+SX +X,+SY
;(FALL THRU TO CPLOT4)
CPLOT4: MOV AL,LOW 4 ;LOOP FOUR TIMES
CPLOT: PUSH AX ;SAVE LOOP COUNT
PUSH BX ;SAVE BOTH X & Y OFFSETS
PUSH DX
PUSH BX ;SAVE TWICE
PUSH DX
MOV DX,CPCNT8 ;GET NP*OCTANT*8
MOV BX,CNPNTS ;ADD SQR(2)*RADIUS FOR NEXT OCTANT
ADD BX,BX
ADD BX,DX
MOV CPCNT8,BX ;UPDATE FOR NEXT TIME
MOV BX,CPCNT ;CALC THIS POINT'S POINT COUNT
ADD BX,DX ;ADD IN PNTCNT*OCTANT*NP
XCHG BX,DX ;SAVE THIS POINT'S COUNT IN [DE]
MOV BX,CSTCNT ;GET START COUNT
CMP BX,DX
JZ SHORT CLINSC ;SEE IF LINE TO CENTER REQUIRED
JAE SHORT CNBTWN ;IF SC .GT. PC, THEN NOT BETWEEN
MOV BX,CENCNT ;GET END COUNT
CMP BX,DX
JZ SHORT CLINEC ;GO SEE IF LINE FROM CENTER NEEDED
JAE SHORT CBTWEN ;IF EC .GT. PC, THEN BETWEEN
CNBTWN: MOV AL,BYTE PTR CPLOTF ;SEE WHETHER TO PLOT OR NOT
OR AL,AL ;IF NZ, PLOT POINTS NOT IN BETWEEN
JNZ SHORT CPLTIT ;NEED TO PLOT NOT-BETWEEN POINTS
JMP SHORT GCPLFN ;DON'T PLOT - FIX UP STACK & RETURN
CLINEC: MOV AL,BYTE PTR CLINEF ;GET CENTER LINE FLAG BYTE
ADD AL,AL ;BIT 7=1 MEANS DRAW LINE FROM CENTER
JAE SHORT CPLTIT ;NO LINE REQUIRED - JUST PLOT POINT
JMP SHORT CLINE ;LINE REQUIRED.
CLINSC: MOV AL,BYTE PTR CLINEF ;GET CENTER LINE FLAG BYTE
RCR AL,1 ;BIT 0=1 MEANS LINE FROM CENTER NEEDED.
JAE SHORT CPLTIT ;NO LINE REQUIRED - JUST PLOT POINT
CLINE: POP DX ;GET X & Y OFFSETS
POP BX
CALL GTABSC ;GO CALC TRUE COORDINATE OF POINT
CALL CLINE2 ;DRAW LINE FROM [BC],[DE] TO CENTER
JMP SHORT CPLFIN
CBTWEN: MOV AL,BYTE PTR CPLOTF ;SEE WHETHER PLOTTING BETWEENS OR NOT
OR AL,AL
JZ SHORT CPLTIT ;IF Z, THEN DOING BETWEENS
GCPLFN: POP DX ;CLEAN UP STACK
POP BX
JMP SHORT CPLFIN
CPLTIT: POP DX ;GET X & Y OFFSETS
POP BX
CALL GTABSC ;CALC TRUE COORDINATE OF POINT
CALL SCALXY ;SEE IF POINT OFF SCREEN
JAE SHORT CPLFIN ;NC IF POINT OFF SCREEN - NO PLOT
CALL MAPXYC
CALL _SETC ;PLOT THE POINT
CPLFIN: POP DX ;GET BACK OFFSETS
POP BX
POP AX ;GET BACK LOOP COUNT
DEC AL
JNZ SHORT $+3
RET ;QUIT IF DONE.
LAHF ; PUSH PSW
XCHG AL,AH
PUSH AX
XCHG AL,AH
PUSH DX ;SAVE X OFFSET
MOV DX,CXOFF ;SWAP [HL] AND CXOFF
NEGDE ;NEGATE NEW [HL]
MOV CXOFF,BX
XCHG BX,DX
POP DX
PUSH BX
MOV BX,CYOFF ;SWAP [DE] AND CYOFF
XCHG BX,DX ;NEGATE NEW [DE]
MOV CYOFF,BX
NEGDE
POP BX
POP AX ; POP PSW
XCHG AL,AH
SAHF
JMP CPLOT ;PLOT NEXT POINT
CLINE2: MOV BX,GRPACX ;DRAW LINE FROM [BC],[DE]
MOV GXPOS,BX ;TO GRPACX,Y
MOV BX,GRPACY
MOV GYPOS,BX
JMP DOGRPH ;GO DRAW THE LINE
;
; GTABSC - GET ABSOLUTE COORDS
; ([BC],[DE])=(GRPACX+[HL],GRPACY+[DE])
;
GTABSC: PUSH DX ;SAVE Y OFFSET FROM CENTER
MOV DX,GRPACX ;GET CENTER POS
ADD BX,DX ;ADD TO DX
MOV CX,BX ;[BC]=X CENTER + [HL]
POP DX
MOV BX,GRPACY ;GET CENTER Y
ADD BX,DX
XCHG BX,DX ;[DE]=Y CENTER + [DE]
RET
SCALEY: MOV BX,ASPECT ;SCALE [DE] BY ASPECT RATIO
SCALE: MOV AL,BL ;CHECK FOR *0 AND *1 CASES
SCALE2: OR AL,AL ;ENTRY TO DO [A]*[DE] ([A] NON-Z)
JNZ SHORT SCAL2 ;NON-ZERO
OR AL,BH ;TEST HI BYTE
JZ SHORT $+3
RET ;IF NZ, THEN WAS *1 CASE
XCHG BX,DX ;WAS *0 CASE - PUT 0 IN [DE]
RET
SCAL2: INS86 62,344 ;XORB AH,AH
INS86 367,342 ;MUL DX
INS86 212,362 ;MOVB DH,DL
INS86 5 ;ADDI AX,128 - ROUND UP
DB 128D
DB 0
INS86 163,2 ;JNB NOCARY
INS86 376,306 ;INCB DH
NOCARY: INS86 212,324 ;MOVB DL,AH
RET
;
; PARSE THE BEGIN AND END ANGLES
; SETTING APPROPRIATE BITS IN CLINEF IF NEG.
;
CGTCNT: DEC BX
CALL CHRGTR ;GET CURRENT CHAR
JNZ SHORT $+3
RET ;IF NOTHING, RETURN DFLT IN [DE]
CALL SYNCHR
DB OFFSET 44 ;EAT THE COMMA
CMP AL,LOW 44 ;USE DEFAULT IF NO ARGUMENT.
JNZ SHORT $+3
RET
PUSH CX ;SAVE FLAG BYTE IN [C]
CALL FRMEVL ;EVALUATE THE THING
POP SI ;XTHL
XCHG SI,BX
PUSH SI ;POP FLAG BYTE, PUSH TXTPTR
PUSH BX ;RESAVE FLAG BYTE
CALL FRCSNG ;MAKE IT A SINGLE PRECISION VALUE
POP CX ;GET BACK FLAG BYTE
MOV BX,OFFSET FAC ;NOW SEE WHETHER POSITIVE OR NOT
MOV AL,BYTE PTR [BX] ;GET EXPONENT BYTE
OR AL,AL
JZ SHORT CGTC2
LAHF
DEC BX ;SET TO HIGH MANTISSA BYTE
SAHF
MOV AL,BYTE PTR [BX]
OR AL,AL
JS SHORT ??L006
JMP CGTC2
??L006:
AND AL,LOW 127D ;MAKE IT POSITIVE
MOV BYTE PTR [BX],AL
MOV BX,OFFSET CLINEF ;SET BIT IN [C] IN CLINEF
MOV AL,BYTE PTR [BX]
OR AL,CL
MOV BYTE PTR [BX],AL
CGTC2: MOVRI 176O,42O,371O,203O ;LOAD REGS WITH 1/2*PI
CALL FMULT ;MULTIPLY BY 1/(2*PI) TO GET FRACTION
CALL CMPONE ;SEE IF RESULT IS GREATER THAN ONE
JNZ SHORT ??L007
JMP FCERR ;FC ERROR IF SO
??L007:
EXTRN _PUSHF:NEAR
CALL _PUSHF ;SAVE FAC ON STAC
MOV BX,CNPNTS ;GET NO. OF POINTS PER OCTANT
ADD BX,BX ;TIMES 8 FOR TRUE CIRCUMFERENCE
ADD BX,BX
ADD BX,BX
CALL MKINTC ;STICK IT IN FAC
CALL FRCSNG ;AND MAKE IT SINGLE PRECISION
POPR ;GET BACK ANG/2*PI IN REGS
CALL FMULT ;DO THE MULTIPLY
CALL FRCINT ;CONVERT TO INTEGER IN [HL]
POP DX ;GET BACK TXTPTR
XCHG BX,DX
RET
CMPONE: MOVRI 201O,0,0,0 ;MAKE SURE FAC IS LESS THAN ONE
EXTRN _FCOMP:NEAR
CALL _FCOMP
DEC AL
RET
SUBTTL GET and PUT - read and write graphics bit array
;
; GET & PUT - READ & WRITE GRAPHICS BIT ARRAY
;
; SYNTAX:
; GET @(X,Y),ARRAYVAR
; PUT @(X,Y),ARRAYVAR[,FUNCTION]
;
; FUNCTION = OR/AND/PRESET/PSET/XOR
;
EXTRN PGINIT:NEAR,PIXSIZ:NEAR,NREAD:NEAR,NWRITE:NEAR,XDELT:NEAR
EXTRN $AND:NEAR,$OR:NEAR,$PRESET:NEAR,$PSET:NEAR,$XOR:NEAR
EXTRN YDELT:NEAR,XCHGX:NEAR,XCHGY:NEAR
DSEG SEGMENT PUBLIC 'DATASG'
EXTRN PUTFLG:WORD,MINDEL:WORD,MAXDEL:WORD
DSEG ENDS
PUBLIC GPUTG
GPUTG: MOV BYTE PTR PUTFLG,AL ;IFE PC8A&RSTLES-1STORE WHETHER PUTTING OR NOT
PUSH AX ;SAVE THIS FLAG A SEC
PUSH BX ;Save text pointer
CALL PIXSIZ ;Test for graphics mode
OR AL,AL
JNZ SHORT ??L008
JMP FCERR ;Not a graphics mode
??L008:
POP BX
CALL SCAN1 ;GET FIRST COORD
CALL CHKRNG
POP AX ;REGET PUT FLAG
OR AL,AL
JZ SHORT ??L009
JMP PUT1
??L009:
CALL SYNCHR
DW OFFSET MINUTK ;EAT "-"
PUSH CX ;SAVE X1
PUSH DX ;SAVE Y1
CALL SCAND ;GET SECOND COORD FOR 'GET' ONLY
CALL CHKRNG
POP DX ;GET Y1 BACK
POP CX ;AND X1
PUSH BX ;SAVE TXTPTR
CALL YDELT ;CALC DELTA Y
JNB SHORT ??L010
CALL XCHGY ;MAKE DE=MIN(GXPOS,DE)
??L010:
INC BX ;MAKE DELTA A COUNT
MOV MINDEL,BX ;SAVE DELTA Y IN MIDEL
CALL XDELT
JNB SHORT ??L011
CALL XCHGX ;BC = MIN(GXPOS,DE)
??L011:
INC BX ;MAKE DELTA A COUNT
MOV MAXDEL,BX ;SAVE DX IN MAXDEL
CALL MAPXYC
POP BX ;GET BACK TXTPTR
CALL GTARRY ;SCAN ARRAY NAME
PUSH BX ;SAVE TXTPTR UNTIL DONE
PUSH DX ;SAVE BEG. OF ARRAY DATA PTR
PUSH CX ;SAVE END OF ARRAY DATA PTR
PUSH DX ;SAVE BEG. PTR AGAIN FOR COMPAR
CALL PIXSIZ ;GET # BITS PER PIXEL INTO [A]
MOV DX,MAXDEL
MOV BX,0
MULBLP: ADD BX,DX ;CALC DX * BITS/PIX
DEC AL
JNZ SHORT MULBLP ;KEEP LOOPING
MOV CX,BX ;SAVE THIS IS [BC]
MOV DX,OFFSET (0+7) ;Round to byte boundry.
ADD BX,DX
XCHG BX,DX ;RESULT TO [DE]
HLFDE ;NOW CALC NO. OF BYTES PER SCAN LINE
HLFDE
HLFDE
MOV BX,MINDEL ;GET DELTA Y
PUSH CX ;SAVE DX*BITS/PIX
MOV CX,BX ;INTO [BC] FOR UMULT
CALL UMULT ;[DE]=DX*DY*BITS/PIX
POP CX ;GET BACK DX*BITS/PIX
MOV BX,4 ;ADD 4 BYTES FOR DX,DY STORAGE
ADD BX,DX ;[HL] HAS NO. OF BYTES TO BE USED
POP DX ;BEG OF ARRAY DATA TO [HL]
ADD BX,DX ;ADD NO. OF BYTES TO BE USED
XCHG BX,DX ;[DE] = CALCULATED END OF DATA
POP BX ;END OF ARRAY DATA TO [HL]
CMP BX,DX
JAE SHORT ??L012
JMP FCERR ;ERROR IF TOO BIG
??L012:
;BEG OF DATA PTR IS ON STK HERE
POP BX ;GET POINTER TO ARRAY DATA
CMP BX,DX
JNAE SHORT ??L013
JMP FCERR ;ARRAY START+LENGTH .GT. 64K
??L013:
MOV BYTE PTR [BX],CL ;SAVE DX*BITS/PIX IN 1ST 2 BYTES OF ARY
INC BX
MOV BYTE PTR [BX],CH ;PASS NO. OF BITS DESIRED IN [BC]
INC BX
MOV DX,MINDEL ;GET LINE (Y) COUNT
MOV [BX],DX
INC BX
INC BX ;SAVE DY IN 2ND 2 BYTES
OR AL,AL ;CLEAR CARRY FOR GET INIT.
JMP GOPGIN ;GIVE LOW LEVEL ADDR OF ARRAY & GO
PUT1: PUSH BX ;SAVE TXTPTR
CALL MAPXYC ;MAP THE POINT
POP BX
CALL GTARRY ;SCAN ARRAY NAME & GET PTR TO IT
PUSH DX ;SAVE PTR TO DELTAS IN ARRAY
DEC BX ;NOW SCAN POSSIBLE PUT OPTION
CALL CHRGTR
MOV CH,LOW 5 ;DEFAULT OPTION IS XOR
JZ SHORT PUT2 ;IF NO CHAR, USE DEFAULT
CALL SYNCHR
DB OFFSET 44 ;MUST BE A COMMA
XCHG BX,DX ;PUT TXTPTR IN [DE]
MOV BX,OFFSET GFUNTB+4 ;TABLE OF POSSIBLE OPTIONS
PFUNLP:
INS86 56 ;CS OVERRIDE
CMP AL,BYTE PTR [BX] ;IS THIS AN OPTION?
JZ SHORT PUT20 ;YES, HAND IT TO PGINIT.
DEC BX ;POINT TO NEXT
DEC CH
JNZ SHORT PFUNLP
XCHG BX,DX ;GET TXTPTR BACK TO [HL]
POP DX ;CLEAN UP STACK
RET ;LET NEWSTT GIVE SYNTAX ERROR
PUT20: XCHG BX,DX ;GET TXTPTR BACK TO [HL]
CALL CHRGTR ;EAT THE TOKEN
PUT2:
DEC CH ;1..5 -TO 0..4
MOV AL,CH ;INTO [A] FOR PGINIT
POP SI ;XTHL
XCHG SI,BX
PUSH SI ;POP ARRAY PTR, PUSH TXTPTR
PUSH AX ;SAVE PUT ACTION MODE
MOV DX,[BX] ;[DE]=NO. OF BITS IN X
INC BX
INC BX
PUSH DX ;SAVE BIT COUNT
PUSH BX ;SAVE ARRAY POINTER
XCHG BX,DX ;INTO [HL] FOR IDIV
CALL PIXSIZ ;GET BITS/PIXEL INTO [DE]
MOV DL,AL ;INTO [E] FOR COUNTING
IFDEF PWR2PX
DIVBLP: DEC DL ;DIVIDE BY [E] (POWER-OF-2 CASE)
JNZ SHORT ??L014
JMP DIVBTX
??L014: