-
Notifications
You must be signed in to change notification settings - Fork 2
/
N1ALL.ASM
2299 lines (2128 loc) · 101 KB
/
N1ALL.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
;;===============================================================================
;;
;; A lot of local labels had to be renamed here. Sometimes, {AS} doesn't like
;; the replacement labels that I've been using previously. I noticed longer names
;; will work so that's the current solution. The naming scheme I chose is to
;; abbreviate the routine/label name and add the original label number at The end.
;;
;; For example, the local label 1$ in AddVib is now .ADDV1S
;;
; EQUs to remove later
;Vibrate EQU $6FDF
;VibIni EQU $708D
;VIBNEW EQU $709B
;VIBREV EQU $70BF
;TosCrys EQU $711E
;VIBSTP EQU $70DE
;Shatter EQU $7074
;PLXQUE EQU $7C6A
;WRXQUE EQU $7C67
;HanSolo EQU $7965
;DTimer EQU $7A3C
;POPFIL EQU $7900
;ADJPOP EQU $78EC
;SINCON EQU $79BB
;InWorker EQU $7574
;PlSecIn EQU $7899
;CrSecIn EQU $77EC
;PreCal EQU $764F
;Quota EQU $7A48
;PRIOS EQU $7A5C
;MisAss EQU $7A52
;EPOPVL EQU $A03C
;ScOCDT EQU $7AA8
;RSOEND EQU $7AB6
;DifTmr EQU $A03F
;;===============================================================================
; Include [Sam]Start
; InclVer SAM,Sinistar.equ
; InclVer RICH,Speak * Speak macro
PushOrg RomSave ;;Fixme was: PushOrg RomSav
;*****
;* VERSION 17 SINISTAR - Noah's module
;*
;* Changes to the last version:
;*
;* Populations tuned
;*
;*****
; Subttl - Pre-Noahish code
; SubTtl - Vibration routines
;****
;* PreBou - Prepares potentially vibrating object
;* with object WS in X for a bounce
;* passes vibration block back in U
;****
Routine PreBou
pshs D ;* Save them for later
ldx [OScan,X] ;* Point to scanner WS of shaking thing
ldu OSChar,X ;* Get characteristic descriptor
lda OViBas,U ;* Get base address of vibration block
leau A,X ;* Point to vibration block in scanner WS
ldx OSScWSA,X ;* Point back to object workspace
ldd OLVel,X ;* Get long velocity
subd OSLVib,U ;* Subtract vibration (will be zero if still)
std OLVel,X ;* Replace it
ldd OSVel,X ;* Do the same for short direction
subd OSSVib,U
std OSVel,X
puls D,PC ;* Sorry Sam and Rich
;*
;****
;* PosBou - Puts vibration back in object WS in X
;****
Routine PosBou
pshs D,U ;* Save them for later
ldx [OScan,X] ;* Point to scanner WS of shaking thing
ldu OSChar,X ;* Get characteristic descriptor
lda OViBas,U ;* Get base address of vibration block
leau A,X ;* Point to vibration block in scanner WS
ldx OSScWSA,X ;* Point back to object workspace
ldd OLVel,X ;* Get long velocity
addd OSLVib,U ;* Add vibration (will be zero if still)
std OLVel,X ;* Replace it
ldd OSVel,X ;* Do the same for short direction
addd OSSVib,U
std OSVel,X
puls D,U,PC ;* Sorry Sam and Rich
;****
;* AddVib - Start object vibrating or add to vibration
;* Assumes Object WS in X
;****
Routine AddVib
pshs D,X,Y,U ;* Save them for duration
ldu OChar,X ;* Point to Charac. Descr. Table
ldy [OScan,X] ;* See if this object
cmpy SinIndex ;* Is the SiniStar
bne .ADDV4S ;;Fixme was: bne 4$ (Replaced all local labels with .ADDV<#>S)
;* Special Add for SiniStar
lda #RchMax/2 ;* Extra large shake (chocolate) for him
sta Temp
jmp .ADDV5S
.ADDV4S ldb OSPers,Y ;* Get pseudo-mass of object
RPT 4,lsrb ;* Divide it by sixteen
bne .ADDV6S ;* If it's zero
incb ;* Make it one
.ADDV6S clra ;* Compute offset into Inverse Table
addd #InvTbl ;*
std Temp ;* Compute inverse mass
lda [Temp] ;*
RPT 2,lsra ;* Scale inverse mass
sta Temp ;* Save inverse pseudo-mass in Temp
.ADDV5S lda OViBas,U ;* Give A offset of vibrate block
ldu [OScan,X] ;* Point to scanner workspace
leau A,U ;* Point to vibrate block in scan WS
ldd OSVibA,U ;* Look at pointer to intelligence
bne .ADDV1S ;* If not zero, use it
ldd OScan,X ;* Get index to scanner WS of object
NEW_SLEEP Task4,Vibrate,OWISLen
std OWSCon,X
ldx OIndex,X ;* Get index to intelligence
stx OSVibA,U ;* Save it as vibration intel. address
.ADDV1S lda OSRcht,U ;* Get current Richter scale
cmpa #RchMax ;* See if it is over maximum
bge .ADDV2S ;* If so don't bother increasing
adda Temp ;* Add degree of vibration for this mass
sta OSRcht,U ;* And store it
.ADDV2S puls D,X,Y,U
rts
;*
;* vibrating object off screen
VIBOFF LEAX Y ;get object workspace in X
JSR PreBou ;kill vibration - returns vib block in U
clrd ;* Noah strikes again
std OSLVib,U ;* zero long vibration
std OSSVib,U ;* zero short vibration
JMP SCROFF
;******
;* GivCrys - Gives a crystal to a worker with scanner WS in X
;******
Routine GivCrys
pshs D ;* Save it from tampering
ldd OSScWSA,X ;* Get on screen WS address
beq .GIVC1S ;* Skip this section if off screen
;*
pshs X ;* Worker on screen, save scanner WS
ldx OSScWSA,X ;* Point to on screen address
ldd #DCryWor ;* Get new draw routine vector
std OPDrwVe,X ;* Update screen object data
ldd #CWorkCr ;* New characteristic descriptor
std OChar,X ;* Added to object WS
puls X ;* Restore scanner WS
;*
.GIVC1S ldd #CWorkCr ;* New characteristic descriptor
std OSChar,X ;* Added to scanner WS
ldd SinIndex ;* Get index to SiniStar
std OScWCR,X ;* This is new caller
lda #OMWoCrystal ;* Give mission of Sinterception with crystal ;;Fixme was: lda #OMWoCrys
sta OSMis,X ;* To WorkerCr
;* lda #SintrP ;* Put SiniStar Intercept Priority
;* SAM - please remove the next line, uncomment
;* the previous, and change the equate of SintrP
;* to SintrP equ $FF
lda #$FF
;*
sta OCalPri,X ;* In calling priority of this worker
puls D
rts
;********
;* VIBRATE
;*
;* Shakes things around based on their Richter scale
;*
;* This routine is set up as a sleep task by GoVib routine
;* The Richter scale is a one byte value that ranges from zero
;* to RchMax (and slightly above and below, but is quickly corrected
;* to zero (vibration stops when negative, planet shatters when over
;* maximum)).
;*
;********
Vibrate pshs Y ;* Save workspace for exit
jsr VibIni ;* Load registers for vibration
beq .5S ;* If offscreen, damp vibration
.4S jsr VibNew ;* Generate and start new vibration
puls Y ;* Restore pointer to sleep task
Sleep HERE ;* Let it move first leg
;*
pshs Y ;* Save workspace for exit
jsr VibIni ;* Load registers for vibration
beq .5S ;* If offscreen, damp vibration
jsr VibRev ;* Reverse the course of vibration
puls Y ;* Restore pointer to sleep task
Sleep HERE ;* Let it move back to origin
;*
pshs Y ;* Save workspace for exit
jsr VibIni ;* Load registers for vibration
beq .5S ;* If offscreen, damp vibration
jsr TosCrys ;* Else try and toss off a crystal
;*
jsr VibStp ;* Stop current vibration
;*
;* Damp Richter scale, see if we are done
;* Crystal tossing routine will go here
;*
ldd OScan,X ;* See if scanner index
cmpd SinIndex ;* Matches the Sinistar
beq .10S ;* If so do special damping
;*
lda OSRcht,U ;* Get Richter value
suba #VibDamp ;* Damp it down
sta OSRcht,U ;* Replace it
cmpa #RchMax ;* Is it above max?
blt .2S ;* if not, go on
;*
jsr Shatter ;* Else die off in spectacular manner
clrd ;* Zero out pointer
std OSVibA,U ;* From scanner WS to vib intelligence
clr OSRcht,U ;* And zero richter scale
std OSLVib,U ;* And long
std OSSVib,U ;* And short vibrations
puls Y ;* Restore pointer to sleep task
jmp Die ;* After it has shattered, kill vibrator
;* Exit point
;*
;* Max out Richter (for sinistar only)
.10S lda OSRcht,U ;* Get Richter value
suba #VibDamp*2 ;* Damp it down
bvc .11S ;* If we underflow
clra ;* Zero it out
.11S sta OSRcht,U ;* Replace it
cmpa #RchMax ;* Is it above max?
blt .2S ;* if not, go on
lda #RchMax ;* Get maximum value
sta OSRcht,U ;* into scale
;*
.2S lda OSRcht,U ;* Get value again
bpl .4S ;* if still positive, do another vibe
;*
.1S clr OSRcht,U ;* Else zero it out
clrd ;* Zero out pointer
std OSVibA,U ;* From scanner WS to vib intelligence
std OSLVib,U ;* And long
std OSSVib,U ;* And short vibrations
puls Y ;* Restore pointer to sleep task
jmp Die ;* And kill process off
;* Exit point
;*
;* OffScreen - damp vibration
.5S lda OSRcht,U
suba #VibDamp
sta OSRcht,U ;* Damp vibration
bmi .1S ;* If negative, zero it all out
puls Y
sleep Vibrate ;* Else wait a little longer
;* Exit point
;****
;* Shatter - Die off appropriately
;****
Shatter pshs D,X,U ;* Save them from tampering
Tune QBang ;* Make an explosion
ldd #$0005 ;* Five points
jsr AddScore
ldu OChar,X ;* Get Char. Desc.
ldx [OScan,X] ;* Point to scanner workspace
jsr [OKiVec,U] ;* Kill off the caller
;*
.2S puls D,X,U ;;Fixme was: 2$ puls D,X,U (is this local label unneeded?)
rts
;*
;*
;*****
;* VibIni - Initialize registers for Vibrate routines
;* On exit, zero flag set if offscreen,
;* X = Object WS, U = Vib Block (in scan WS)
;* Y = Characteristic descriptor
;*****
VibIni ldx [OWSCon,Y] ;* Point X to Scanner WS of Shakee
ldy OSChar,X ;* Get characteristic descriptor
lda OViBas,Y ;* Grab vibration base offset
leau A,X ;* Point U to vibration block of this WS
ldx OSScWSA,X ;* Point X to Object WS (X=0 offscreen)
rts
;*****
;* VibNew - Start a vibration from rest
;*****
VibNew ldb OSRcht,U ;* Get Richter scale value
clra ;*
RPT 2,aslb,rola ;* Multiply by 4
pshs D ;* Save it for later
jsr RndNeg ;* Negate it half the time
jsr RndScl ;* Scale it down by half half the time
std OSLVib,U ;* This is new Long vibration rate
addd OLVel,X ;* Add it to current object velocity
std OLVel,X ;* And update that velocity
;*
puls D ;* Do the same for Short direction
jsr RndNeg ;* Negate it half the time
jsr RndScl ;* Scale it down by half half the time
std OSSVib,U ;* This is new Short vibration rate
addd OSVel,X ;* Add it to current object velocity
std OSVel,X ;* And update that velocity
;*
rts
;****
;* VibRev - Reverse direction of current vibration
;****
VibRev ldd OSLVib,U ;* Get current long vibration
coma ;* Negate D
comb
addd #01
std OSLVib,U ;* Save it as new vibration factor
addd OSLVib,U ;* Double it in order to
addd OLVel,X ;* Subtract original twice
std OLVel,X ;* From actual velocity
;*
ldd OSSVib,U ;* Get current short vibration
coma ;* Negate D
comb
addd #01
std OSSVib,U ;* Save it as new vibration factor
addd OSSVib,U ;* Double it in order to
addd OSVel,X ;* Subtract original twice
std OSVel,X ;* From actual velocity
;*
rts
;****
;* VibStp - Stop current vibration
;****
VibStp ldd OLVel,X ;* Get long velocity
subd OSLVib,U ;* Remove vibration factor
std OLVel,X ;* Replace it
clr OSLVib,U ;* Zero vibration factor
clr OSLVib+1,U
;*
ldd OSVel,X ;* Get short velocity
subd OSSVib,U ;* Remove vibration factor
std OSVel,X ;* Replace it
clr OSSVib,U ;* Zero vibration factor
clr OSSVib+1,U
;*
rts
;****
;* RndNeg - Negates D half the time
;****
RndNeg pshs A
RANDOM OSEED1,BYTE
inca ;* Play with it to set flag randomly
bmi .1S
puls A
jmp .2S
.1S puls A
coma ;* Negate D
comb
addd #01
;*
.2S rts
;****
;* RndScl - Scales D to 1/2 value half the time
;****
RndScl pshs A
RANDOM OSEED1,BYTE
inca ;* Play with it to set flag randomly
bmi .1S
puls A
jmp .2S
.1S puls A
asra ;* Shift D right
rorb
;*
.2S rts
;*****
;* Toscrys - tosses crystals out - expects to be called from
;* within Vibrate - X = object ws of viber, U = Vib
;* block with L and S velocity of vibration
;*****
;*
ROUTINE TOSCRYS
pshs D,X,Y ;* Save for exit
ldd #CSini ;* Compare sinistar
cmpd OChar,X ;* With this object's char desc.
beq .1S ;* If same, don't toss crystals
;*
;* See if a crystal should be tossed
;*
lda OSRcht,U ;* Get vibration Richter scale
suba #CrProb ;* Must exceed minimum vibration
bls .1S
pshs A ;* Save excess
RANDOM OSEED1,BYTE
cmpa S+ ;* Probability of tossing crystal proportional
bhi .1S ; vibration above minimum Richter scale
;*
pshs X ;* Save object WS for now
ldy [OScan,X] ;* Get scanner WS of vibrating rock
lda OSPers,Y ;* Get rock's pseudo-mass
suba #8 ;* Lower it
bcc .4S ;* Never lower it past zero
clra ;* Zero is the lowest
.4S sta OSPers,Y ;* Save new pseudo-mass
ldd OSLPos,Y ;* Get L and S position
addd #0101 ;* Offset into center of rock
ldy #CCrystal ;* Point to crystal's CD
jsr [OInVec,Y] ;* Initialize crystal
;* X now has Scanner WS of crystal
puls Y ;* Put object WS of rock into Y
ldx OSScWSA,X ;* Get object WS of crystal
beq .3S ;* If that is offscreen, skip the rest
;* ; hence offscreen crystals are motionless
;*
ldd OLVel,Y ;* Then get long velocity
subd OSLVib,U ;* Remove vibration effect
std OLVel,X ;* Save it
RANDOM OSEED1,BYTE ;* Generate a random number
tfr A,B ;* Put it in low order position
sex ;* Didja hear about the assembler - it had a
;* premature ORG-ASM
addd OLVel,X ;* Add this random factor to velocity
std OLVel,X ;* Replace it
;*
ldd OSVel,Y ;* Do the same for short velocity
subd OSSVib,U ;* Remove vibration effect
std OSVel,X ;* Save it
RANDOM OSEED2,BYTE ;* Generate a random number
tfr A,B ;* Put it in low order position
sex ;* Not bad, only microseconds later
addd OSVel,X ;* Add this random factor to velocity
std OSVel,X ;* Replace it
;*
.3S lda OSRcht,U ;* Get richter scale
lsra ;* Subtract crystal damping factor
sta OSRcht,U ;* Replace it
jmp .2S ;* All done
;*
.1S jsr Null ;* Jug piece tossing could go here
;* <<< Remove this if we don't use it for jug stuff eventually >>>
.2S puls D,X,Y
rts
; SubTtl - Killing subroutines
;*
;* KiSubs - Killing subroutines for scanner objects
;* expects scanner WS in X
;*
;* To use for any type of object, load
;* its scanner WS into X, and its charac. desc. into
;* another index register - R in this example, then
;* jsr [OKiVec,R] If you know what type of
;* object it is, such as Worker, you can jump directly
;* avoiding loading the C.D. as in
;* jsr KRWork X still must have scanner WS
;*
;* KRWork - Workers
;*
Routine KRWorker ;;Fixme was: Routine KRWork
jsr KilWor
rts
;*
;* KRWarr - Warriors
;*
KRWarr jsr KilWar
rts
;*
;* KRWoCr - Workers with Crystals
;*
KRWoCr pshs D,U
ldd OIndex,X ;* Get index to scanner WS of WorkCr
std OScWCR,X ;* Make it its own caller
ldu OSScWSA,X ;* Point to on-screen WS
beq .1S ;* If not on screen, don't give velocity
;*
ldd OLVel,U ;* Get long screen velocity
std Temp ;* Save it for later
ldd OSVel,U ;* Do same for short velocity
std Temp+2
.1S ldu OSLPos,X ;* Get its position
jsr KilWor ;* Kill it
tfr U,D ;* Put position in for crystal init
addd #0101 ;* Offset it into center
ldu #CCrystal ;* Get crystal C.D.
jsr [OInVec,U] ;* Initialize a crystal where worker was
;* X now has scanner WS of crystal
ldu OSScWSA,X ;* Get on-screen WS
beq .2S ;* If none, no velocity needed
;*
ldd Temp ;* Get long velocity of dead worker
std OLVel,U ;* Give it to crystal
ldd Temp+2 ;* Do same for short velocity
std OSVel,U
.2S puls D,U
rts
;*
;* KRPl1 - Planet type 1
;*
KRPl1 jsr KilVib ;* Kill off vibration if present
jsr KilNorm ;* Kill off the rock
rts
;*
;* KRPl2 - Planet type 2
;*
KRPl2 jsr KilVib ;* Kill off vibration if present
jsr KilNorm ;* Kill off the rock
rts
;*
;* KRPl3 - Planet type 3
;*
KRPl3 jsr KilVib ;* Kill off vibration if present
jsr KilNorm ;* Kill off the rock
rts
;*
;* KRPl4 - Planet type 4
;*
KRPl4 jsr KilVib ;* Kill off vibration if present
jsr KilNorm ;* Kill off the rock
rts
;*
;*
;*
;* KRPl5 - Planet type 5
;*
KRPl5 pshs D,U
ldu [OIWScIn,X] ;* Get secondary intelligence WS
ldd #Die
std OExec,U ;* Kill it
jsr KilVib ;* Zero vibration
jsr KilCall ;* Kill it off as caller ;;Fixme was: jsr KilCal
puls D,U
rts
;*
;* KRCrys - Crystal
;*
Routine KRCrys
pshs D,U
ldu [OIWScIn,X] ;* Get secondary intelligence WS
ldd #Die
std OExec,U ;* Kill it
jsr KilCall ;* Kill it off as caller ;;Fixme was: jsr KilCal
puls D,U
rts
;*
;* KRSBomb - Sinibomb
;*
KRSBomb pshs D,U
ldu [OIWScIn,X] ;* Get secondary intelligence WS
ldd #Die
std OExec,U ;* Kill it
jsr KilCall ;* Kill it off as caller ;;Fixme was: jsr KilCal
dec InBombs
puls D,U
rts
;*
;* KRSini - Sinistar
;*
;* In Rich's stuff
;*
;* KRPlay - Player
;*
KRPlay jsr KilCall ;* This may not work right..... ;;Fixme was: jsr KilCal
;* It will try to kill screen image
rts
;*
;* KRPiec - Sinitstar Piece
;*
KRPiec jsr KilNorm ;* Kill off the piece
rts
;*
;*
;* KilVib - Stops vibration (if any) with scan WS in X
;*
KilVib pshs D,X,Y ;* They all may get used...
ldy OSChar,X ;* Get characteristics descriptor
lda OViBas,Y ;* Get base offset of vibration block
ldy [A,X] ;* Load Y with sleep task WS of vib task
beq .1S ;* If grounded, just return
ldd #Die ;* Else make it die when it wakes up
std OExec,Y
.1S puls D,X,Y,PC ;* Done
; LOCAL
;********************
;*
;* Killer routines - lobotomizes objects, then forces them
;* to commit suicide
;*
;* These routines expect scanner WS address in X on entry
;********************
KilWor
pshs D,Y,U ;* Kill Worker entry point
lda #OWorker ;* Get offset for worker
jmp ComSta ;* Go to common starting point
;*
KilWar
pshs D,Y,U ;* Kill Warrior entry point
lda #OWarrior ;* Warrior offset
;*
ComSta pshs A ;* Save callee offset
ldd OSScWsA,X ;* Look at on-screen WS address
beq .2S ;* Skip next section if not on screen
;*
;* Kill off On-Screen Object
;*
pshs X ;* Save scanner workspace we are killing
tfr D,X ;* Load in on-screen WS address
jsr ExpObj ;* Explode it
ldd #NoPost ;* Make sure it doesn't
std OPDrwVec,X ;* Leave a crystal behind
puls X ;* And restore the scanner WS pointer
;*
.2S ldy [OScnIn,X] ;* Get controlling intelligence task
ldd #Die ;* Kill it off
std OExec,Y ;* When it wakes up
ldy OIndex,X ;* Get index to scanner WS
cmpy OScWCr,X ;* Is this callee called by itself?
beq .3S ;* If so, don't bother to notify caller
;*
;* Send condolences to the caller of this craft
;*
ldu [OScWCr,X] ;* Point to caller's scanner WS
lda ,S ;* Get callee type
leay OQuota,U ;* Point to quota bytes
dec A,Y ;* Remove this craft from quota
lsla ;* Double callee ofset for 2 byte use
adda #OCleLs ;* Point to callee list
ldy OIndex,X ;* Get index of craft we are killing
cmpy A,U ;* Is it the same as the first entry?
beq .4S ;* If so, we don't have to look for him
ldu [A,U] ;* Point to first workspace
lda #OScSqI ;* And pass the offset of squadron list
jsr Look4Y ;* Then search until we find ID in Y
;*
.4S ldy OScSqI,X ;* Get squadron pointer of goner
sty A,U ;* Save it in next squadron member
;*
;* Now De-link our callee from type list
;*
.3S lda ,S ;* Get the good old offset
lsla ;* Double it for 2 byte operation
ldu #KeyClee ;* Point to keystone of callees
ldy OIndex,X ;* Get our callee's index
cmpy A,U ;* Is ours first in line?
beq .5S ;* If so we're all set
;*
ldu [A,U] ;* Point to first workspace in list
lda #OScTypt ;* Set up correct offset ;;Fixme was: lda #OScTyp
jsr Look4Y ;* Look for a match with Y
;*
.5S ldy OScTypt,X ;* Get the next link from the goner ;;Fixme was: 5$ ldy OScTyp,X
sty A,U ;* Give it to his predecessor
tfr X,Y ;* Load in goner's scanner WS
jsr BumOut ;* Depress him to death
leas 1,S ;* Remove callee offset from stack
puls D,Y,U ;* And we're all done
rts
; local
;***
;* KilCall - Kills off caller intelligent object
;***
KilCall pshs D,Y,U
ldu OSChar,X ;* Look at characteristics descriptor
lda OViBas,U ;* Vibration base offset
beq .2S ;* If it can't vibrate skip next section
;* Stop Vibration task if present
pshs X ;* Save scanner WS
ldy [A,X] ;* Get WS of vibrating sleep task
ldd #Die ;* And if it dies when it does wake
std OExec,Y ;* I pray EXEC its soul to take
puls X ;* Restore scanner workspace
;* Kill Onscreen object
.2S ldd OSScWSA,X
beq .1S ;* If not on screen, skip this section
pshs X ;* Save scanner WS
ldx OSScWSA,X ;* Get screen object WS
ldd OChar,X ;* Check to see
cmpd #CCrystal ;* If it is a crystal
beq .8S ;* If so, kill it
jsr ExpObj ;* Else explode it
jmp .9S
.8S jsr KillObj
.9S puls X ;* Restore scanner workspace
;* Tell the slaves their master is dead
.1S lda #OMWoEvade ;* This is new mission
ldu [OCleLs,X] ;* Get scanner WS of first worker
jsr Lincoln ;* Free the slaves
lda #OMWaDrift ;* This is new mission
ldu [OCleLs+2,X] ;* Get scanner WS of first warrior
jsr Lincoln ;* Do it again
ldy [OSCOCAI,X] ;* Get WS of controlling caller intelligence
ldd #Die ;* Make it die when it wakes
std OExec,Y
tfr X,Y ;* Set up for killing scanner workspace
jsr Bumout ;* Cause scanner process to die on wakeup
puls D,Y,U ;* Restore stuff
rts
;****
;* Lincoln - go down squadron list freeing callees
;* Alters D,Y,U
;****
Lincoln pshs A
.2S beq .1S ;* If workspace is grounded, return
lda ,S ;* Get mission
sta OSMis,U ;* Give it new mission
ldd #$FFFF ;* With faked maximum distance
std OScLDC,U ;* To that caller
lda #1
sta OSSqSiz,U ;* And a squadron size of 1
lda #WrstPri ;* Get worst possible priority
sta OCalPri,U ;* New calling priority
ldd OIndex,U ;* Get index to this callee
std OScWCr,U ;* It is its own caller
ldy OScSqI,U ;* Get index to next member of squadron
ldd #Ground ;* Ground out
std OScSqI,U ;* That pointer
ldu ,Y ;* Point to workspace of next guy
jmp .2S ;* Keep going
;*
.1S puls A
rts
;*****
;* KilNorm - Kills off scanner WS in X and screen object
;*****
; local
KilNorm pshs D,X
ldd #ScanDie ;* Put scanner killer
std OExec,X ;* Into execution vector
ldx OSScWSA,X ;* Get screen workspace
beq .1S ;* If zeroed, no screen object
jsr ExpObj ;* Explode it if there
.1S puls D,X,PC
; local
;************
;* SUBROUTINES
;************
;* Look4Y - searches through links in workspaces for index
;* value in Y. U is first WS, A is offset of
;* link. On exit U is WS with link = Y
Look4Y
cmpy A,U ;* Is this link the right one?
beq .1S
ldu [A,U] ;* Point to next
jmp Look4Y
.1S rts
;*
;* BumOut - Cause WS in Y to commit suicide on wakeup
;*
Bumout
pshs D
ldd #ScanDie ;* Get address of death code
std OExec,Y ;* New execution (how appropriate)
puls D,PC
; SubTtl - Explosion routines
; Local
;*****
;* EXPOBJ - Explodes object - gets object WS in X
;*****
Routine SExpObj
pshs D,X,Y,U
ldy #$FFFF ;* Set flag for time delay explosion
jmp ExEntr ;* Go to explosion entry point
Routine ExpObj
pshs D,X,Y,U
ldy #0 ;* Set flag for immediate explosion
Routine ExEntr
jsr FragExp ;* Toss off fragments if needed
;*
;* Call up Bob's special explosion routines if needed
;*
CMPX #WPLAYER
BNE .22S
JSR PLXQUE ;* START UP PLAYER EXPLOSION ;; TAIL overwrites this instruction
BRA .23S
.22S LDD OCHAR,X
CMPD #CWARRIOR ;;Fixme was: CMPD #CWARRI
BNE .23S
JSR WRXQUE ;* START UP WARRIOR EXPLOSION
.23S ldd #CExplo ;* Give this object WS explosion charac. desc.
std OChar,X
leau ,X ;* Transfer X over to U
cmpy #0 ;* See if we need a time delay
beq .2S ;* If not, go do immediate explosion
;*
;* Delayed explosion
;*
New_Sleep Task8,PrePlo,OExpLen ;* Spawn controlling task
jmp .3S
;*
;* Immediate explosion
;*
.2S New_Sleep Task1,PrePlo,OExpLen ;* Spawn controlling task
ldd #INull ;* Immediate explosion, nullify image right away
std ONiDesc,U ;* Null new image descriptor
ldd #ChgObj ;* Make sure it changes to null object
std ODrwVec,U ;* Next time it wakes
.3S stu OSWSA,X ;* Save object ws address for sleep task
clr OImNo,X ;* So tell sleep task we are on image number 0
dec OImNo,X ;* Then bring it to -1 so we START with image 0
ldx OIndex,X ;* Get index to this sleep task
stx OScan,U ;* Not really a scanner WS, but will do for now
puls D,X,Y,U
rts
;*
;* PrePlo - Precedes Plode routine, changes sleep times
;*
PrePlo Sleep .1S ;* Go back to sleep for another cycle
.1S Change_Sleep Task4,Plode ;* Tell it to wake at Plode
; local
;* Plode - Sleep task to control explosion
;*
Routine Plode
pshs D,X,Y
ldx OSWSA,Y ;* Get on-screen WS of our explosion
lda OImNo,Y ;* Find out what image number we are on
inca ;* Go to next
cmpa #4 ;* See if we are done
bge .1S ;* Go die if so
sta OImNo,Y ;* Else save it for next time
ldb #OILen ;* Multiply image descr. length
mul ;* By number of image in A
addd #IExplo ;* Add this offset to first image
std ONIDesc,X ;* Update screen image
ldd #ChgObj
std ODrwVec,X ;* And tell it to change object
puls D,X,Y
sleep LOOP ;* Sleep till next update
;*
.1S cmpx #WPlayer
bne .5S
ldd #INull
std ONiDesc,X
ldd #ChgObj
std ODrwVec,X
jmp .6S
.5S jsr KillObj ;* Kill image off first
.6S puls D,X,Y
jmp Die ;* Then die too
; local
; SubTtl - Initialization
;*
;* Player Initialization
;*
Vector PlaVect ;;Fixme was: Vector PlaVec
clr SiniKills ;* I clear it so initial rstpop is correct
jsr RstPop ;* Reset population and difficulty tables
rts
;*
;* Turn Initialization
;*
Vector IniVect ;;Fixme was: Vector IniVec
;* Entry Point for Turn initialization
ldu #Pop
.1S clr ,U ;* Zero out current number of things in sector
leau 3,U ;* Point to next thing
cmpu #Pop+21 ;* See if we are at end of list
blt .1S ;* If not keep going
;*
; local
ldx #Ground
stx KeyClee
stx KeyClee+2 ;* Start out the type lists empty
ldy #8080 ;* Load code for random positioning
clra
sta Edge ;* And set flag so they are not created on edge
jsr PopFil ;* And fill the sector to match desired pop.
;* Initialize Player
ldu #CPlayer
jsr [OInvec,U]
;* Create Sinistar
lda #$FF
sta Edge ;* On edge
ldd #$8080 ;* random position
ldu #CSini ;* Point to Char. Descr.
jsr [OInVec,U] ;* Jump to initialization subroutine
New_Sleep Task256,DTimer
New_Sleep Task0,AdjPop ;* Start population adjuster going
New_Sleep Task64,SinCon ;* Start Sinistar Hector build and taunt
;*
;* If in Void zone (sinikill mod 4 = 0) do not have swarms
;*
; local
lda SiniKills ;;Fixme was: lda SiniKill
beq .SWRM1S ;* do it on first time ;;Fixme was: beq 1$
anda #$03 ;* Mod 4
beq .SWRM2S ;;Fixme was: beq 2$
;* Start swarms
.SWRM1S New_Sleep Task256,HanSolo
.SWRM2S nop ;* Probably unnecessary
;*
; local
; IFN Version-Final
; Local ;* Patch for Rich to add workCR at init
RicPat lda #0
ldu #CWorkCr
sta Temp
.1S dec Temp
bmi .2S
jsr [OInvec,U] ;* Make a WorkCr
jmp .1S
; ENDIF
;
.2S rts
; SubTtl - Initialization Subroutines
;* InSubs - Initialization subroutines
;* Expect position in D, return index to
;* Scanner WS in X
;*
;* To call these routines, either load characteristic
;* descriptor of object to initialize into a register -
;* R in this example - load scanner position into D, and
;* jsr [OInVec,R]
;* Or if you need only a specific characteristic object
;* such as workers, you can skip loading a register and
;* jsr IRWork with position in D
;*
;* IRWork - Workers
;*
IRWork New_Scan CWorker ;* Get scanner WS
jsr InWorker ;* Give it Worker primary intelligence
rts
;*
;* IRWarr - Warriors
;*
IRWarr New_Scan CWarrior ;* Get scanner WS
jsr InWarrior ;* Give it Warrior primary intelligence
rts
;*
;* IRWoCr - Workers with Crystals
;*
IRWoCr New_Scan CWorkCr ;* Get scanner WS
jsr InWorker ;* Give it Worker primary intelligence
jsr GivCrys ;* Give it a crystal
rts