-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathbank5.inc
3369 lines (3287 loc) · 76.1 KB
/
bank5.inc
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
ORG $8000
BANK_START $F5
; ---------------------------------------------------------------------------
; ---------------------O-B-J-E-C-T--H-A-N-D-L-E-R-S--------------------------
; ---------------------------------------------------------------------------
SECTION_START F10
; =============== S U B R O U T I N E =======================================
_obj_handlers:
LDA _game_msg_wnd_active_flag
BEQ loc_88006
RTS
loc_88006:
LDA _game_wnd_spr_mode_flag
BEQ loc_8800F
LDA #$50
STA _spr_buf_pos
loc_8800F:
JSR _obj_spr_bank_select
LDA _obj_active_flags
LSR
BCC loc_88032
JSR _obj_hndl01_heli
loc_88032:
LDA _obj_active_flags
AND #$02
BEQ loc_88029
JSR _obj_hndl02_plane
loc_88029:
LDA _obj_active_flags
AND #$04
BEQ loc_8805A
JSR _obj_hndl04_ship
loc_8805A:
LDA _obj_active_flags
AND #$08
BEQ loc_88050
JSR _obj_hndl08_train
loc_88050:
LDA _obj_active_flags
AND #$10
BEQ loc_88046
JSR _obj_hndl10_monster
loc_88046:
LDA _obj_active_flags
AND #$20
BEQ loc_8803C
JSR _obj_hndl20_tornado
loc_8803C:
LDA _airplane_crash_req ; special check for airplane crash
BEQ loc_8801C
; JSR _airplane_crash_start
LDA _game_msg_idx ; FIX, prevent airplane disaster to
BNE loc_8801C ; steal other disasters
LDA #$00
STA _airplane_crash_req
BEQ _airplane_crash_start ; OPTIMIZED
loc_8801C:
LDA _obj_active_flags
AND #$03
CMP #$03
BNE locret_88076 ; special test if heli and plane are in the same
LDA _obj_pos._heli._COL ; position currently, they CRAAASHHHHH!!
CMP _obj_pos._plane._COL ; so we can crash airplane without request
BNE locret_88076 ; NOTE, with this crash we destroy only plane, not heli!
LDA _obj_pos._heli._ROW
CMP _obj_pos._plane._ROW
BNE locret_88076
; JMP _airplane_crash_start ; OPTIMIZED
_airplane_crash_start:
LDA #$22
STA _game_msg_idx
LDX _obj_pos._plane._COL ; cur plane obj pos set to goto pos
STX _goto_dst_tile._COL ; the same time X,Y loaded with the same pos
LDY _obj_pos._plane._ROW
; STX _goto_dst_tile._ROW ; BUG! Y loaded, X stored instead!
STY _goto_dst_tile._ROW ; FIX: correct opcode
LDA #$01
STA _goto_alert_req
STA _game_msg_awaits_flag
JSR _far_disaster_destroy_tile ; X,Y aregs goes here
LDA _obj_active_flags ; destroy plane
AND #$FD
STA _obj_active_flags
APUA_SE _SE_IDX_DESTROY ; crash sound
PUSHW _ptr0
PUSHW _tmp2
PUSHW _tmp4
LDY #$08
FJSRA _city_history_write,SRAM,PRGA ; to memories!
POPW _tmp4
POPW _tmp2
POPW _ptr0
locret_88076:
RTS
; =============== S U B R O U T I N E =======================================
; every 50 years the CHR bank for object are changes
; 1900 - bank 38, 39
; 1950 - bank 3A, 3B
; 2000 - bank 3C, 3D
; 2050 - bank 3E, 3F
_obj_spr_bank_select:
LDX #$00 ; subtract 1950 by default
LDA _city._cur_year
SEC
SBC #$9E
STA _ptr15
LDA _city._cur_year+1
SBC #$07
STA _ptr15+1
BCC loc_88D25 ; all lower gets default sprites
loc_88D11:
INX
CPX #$03 ; then subtract 50 from the rest
BCS loc_88D25 ; up to 3 times
LDA _ptr15
SEC
SBC #$32
STA _ptr15
LDA _ptr15+1
SBC #$00
STA _ptr15+1
BCS loc_88D11
loc_88D25:
LDA byte_88D31,X ; we have 4 periods with different
STA _MMC5_CHR_BANKSA+2 ; vehicle graphics
TAX
INX
STX _MMC5_CHR_BANKSA+3
RTS
byte_88D31:
.BYTE $38,$3A,$3C,$3E
; =============== S U B R O U T I N E =======================================
_obj_hndl01_heli:
LDA #$00
STA _cur_obj_idx
JSR _obj_fetch
LDX _frames_div8_counter
CPX _cur_obj_idx
BNE loc_8822A
LDA _obj_spr_delta._heli
BEQ loc_8821A
JMP _obj_rotate
loc_8821A:
JSR _obj_flying_dst_test_adjust
CMP #$FF
BNE loc_88224
JSR _obj_flying_retarget
JMP _obj_draw
loc_88224:
STA _obj_cur_spr_idx._heli
JSR _cur_obj_move
loc_8822A:
JMP _obj_draw
; =============== S U B R O U T I N E =======================================
_obj_hndl02_plane:
LDA #$01
STA _cur_obj_idx
JSR _obj_fetch
BIT _obj_plane_anim_idx ; cur plane anim mode, 80 means
BPL loc_880DC ; take-off/landing
JMP _obj_plane_landing_draw
loc_880DC:
LDX _frames_div8_counter
CPX _cur_obj_idx
BNE loc_88101
LDA _obj_spr_delta._plane ; spr delta 0 - no need to change spr
BEQ loc_880EB
JMP _obj_rotate ; or else do it
loc_880EB:
JSR _obj_flying_dst_test_adjust
CMP #$FF
BNE loc_880F8
JSR _obj_flying_retarget
JMP _obj_draw
loc_880F8:
STA _obj_cur_spr_idx._plane
JSR _cur_obj_move
JSR _obj_plane_landing_test
loc_88101:
JMP _obj_draw
; =============== S U B R O U T I N E =======================================
_obj_plane_landing_draw:
LDX _frames_div8_counter
CPX _cur_obj_idx
BNE loc_88171
JSR _cur_obj_move
loc_88171:
DEC _obj_plane_anim_timer
BNE loc_88196
LDA #$20
STA _obj_plane_anim_timer
LDA _obj_plane_anim_idx
AND #$7F
SEC
SBC #$01
BEQ loc_881A1
ORA #$80
STA _obj_plane_anim_idx
CMP #$84
BNE loc_88193
LDA #$06
STA _obj_cur_spr_idx._plane
loc_88193:
JSR _cur_obj_move
loc_88196:
LDA _obj_plane_anim_idx
AND #$7F
TAX
LDA _obj_plane_takoff_anim_list,X
BNE loc_881A6
loc_881A1:
STA _obj_plane_anim_idx
LDA #$08
loc_881A6:
STA _spr_insert_args._idx
LDX _game_wnd_spr_mode_flag
BEQ loc_881B3
JSR _map_scr_obj_spr_insert
JMP _obj_flush
loc_881B3:
JSR _obj_spr_draw
JMP _obj_flush
_obj_plane_takoff_anim_list:
.BYTE $00,$08,$09,$0A,$0B,$0F,$0E,$0D,$0C
; =============== S U B R O U T I N E =======================================
_obj_plane_landing_test:
LDA _obj_cur_spr_idx._plane
BEQ locret_88202
CMP #$04
BCS locret_88202
LDA _obj_pos._plane._COL
CMP _last_airport_pos._COL
BNE locret_88202
LDA _obj_pos._plane._ROW
CMP _last_airport_pos._ROW
BNE locret_88202
LDA #$88
STA _obj_plane_anim_idx
LDA #$20
STA _obj_plane_anim_timer
LDA #$02
STA _obj_cur_spr_idx._plane
locret_88202:
RTS
; =============== S U B R O U T I N E =======================================
_obj_flying_retarget:
LDA _cur_obj_idx
ASL
TAY
JSR _obj_flying_get_rand_pos ; choose two random map coords
STA _obj_dst_pos._COL,Y
JSR _obj_flying_get_rand_pos
STA _obj_dst_pos._ROW,Y
JSR _obj_fetch
JSR _obj_flying_dst_test_adjust ; check if we already there
CMP #$FF ; repeat if yes
BEQ _obj_flying_retarget
LDY _cur_obj_idx ; store destination spr idx
STA _obj_dst_spr_idx,Y ; corresponds to plane sprite
ASL ; orientation 7\ |0/1
ASL ; 6<-*->2
ASL ; 5/4| \3
ADC _obj_cur_spr_idx,Y ; calc direction of sprite rorate
TAX ; from cur spr idx to dst spr
LDA _obj_spr_rotate_delta_table,X ; table 64x64 consists of 0, 1 and -1
STA _obj_spr_delta,Y ; we will inc/dec our spr by this value
RTS
; =============== S U B R O U T I N E =======================================
_obj_flying_get_rand_pos:
LDA _frames_counter
AND #$0F
TAX
LDA _rand_seed
LSR
LSR
BNE loc_88BE9
LDA #$24
loc_88BE9:
STA _ptr15
loc_88BEB:
ADC _frames_counter
ADC _frames_div8_counter
STA _rand_seed
DEX
BNE loc_88BEB
loc_88BF4:
CMP #$48
BCC locret_88BFE
SEC
SBC _ptr15
JMP loc_88BF4
locret_88BFE:
RTS
; =============== S U B R O U T I N E =======================================
_obj_flying_dst_test_adjust:
LDA _cur_obj_pos._COL ; we have dst pos and
CMP _cur_dst_pos._COL ; relative vector to it
BEQ .test_vert ; so we decide the direction
BCS .fly_left_test_hor
LDA _cur_obj_pos._ROW ; fly right, test hor
CMP _cur_dst_pos._ROW
BEQ .fly_right
BCC .fly_right_down
LDA #$01 ; fly right-up
RTS
.fly_right:
LDA #$02
RTS
.fly_right_down:
LDA #$03
RTS
.test_vert:
LDA _cur_obj_pos._ROW
CMP _cur_dst_pos._ROW
BEQ .stop
BCC .fly_down
LDA #$00 ; fly up
RTS
.fly_down:
LDA #$04
RTS
.fly_left_test_hor:
LDA _cur_obj_pos._ROW
CMP _cur_dst_pos._ROW
BEQ .fly_left
BCS .fly_left_up
LDA #$05 ; fly left-down
RTS
.fly_left:
LDA #$06
RTS
.fly_left_up:
LDA #$07
RTS
.stop:
; -
; CPY #$03 ; REDUNDANT, something from early
; BNE loc_88BD9 ; dev stage, seems this sub were used
; LDA _obj_cur_spr_idx._train ; also for train retarget, but not now
; AND #$02 ; Y do not used here as an argument with
; BEQ loc_88BCE ; _cur_obj_idx. the only place it get's
; LDA _obj_shift._train._COL ; similar value, in _obj_flying_retarget
; CMP #$04 ; but Y there is _cur_obj_idx*2, so we
; BEQ loc_88BD9 ; can't have 3 here ever.
; BEQ loc_88BD5 ; <- luke, i'm a second BEQ in row to a different location lol
;loc_88BCE:
; LDA _obj_shift._train._ROW ; this code is just a trash, never get executed
; CMP #$04
; BEQ loc_88BD9
;loc_88BD5:
; LDA _obj_cur_spr_idx._train
; RTS
;loc_88BD9:
; -
LDA #$FF ; all we need here is $FF
RTS
; =============== S U B R O U T I N E =======================================
_obj_hndl04_ship:
LDA #$02
STA _cur_obj_idx
JSR _obj_fetch
LDX _frames_div8_counter ; every object moves only
CPX _cur_obj_idx ; at its own frame, separately
BNE loc_8826A ; otherwize it's only drawn
LDA _obj_spr_delta._ship
BEQ loc_88260
JMP _obj_rotate
loc_88260:
JSR _obj_ship_dst_test ; test if we in a dst point
CMP #$FF
BNE loc_88269 ; FIX: the same as other handlers
JSR _obj_ship_retarget
JMP _obj_draw
loc_88269:
JSR _cur_obj_move
loc_8826A:
JMP _obj_draw
; =============== S U B R O U T I N E =======================================
_obj_ship_dst_test:
; -
; WRONG: similar to train object routine
; as against the train, ship can move diagonally
; but here we test if he moves always diagonally lol
; so if ship moving vertically or horizontally,
; we never arrive to the dest
; -
; LDA _obj_shift._ship._COL
; CMP #$04
; BNE loc_8828E
; LDA _obj_shift._ship._ROW
; CMP #$04
; BNE loc_8828E
; -
; NEW: some possible logic flaw still left. there is no
; test here for virtually possible not moving at all state
; but actually it handled with rotate routine
; -
LDX _obj_shift._ship._COL
BEQ ._ship_no_x_move
LDA _obj_shift._ship._COL
CMP #$04
BNE loc_8828E
._ship_no_x_move:
LDX _obj_shift._ship._ROW
BEQ ._ship_no_y_move
LDA _obj_shift._ship._ROW
CMP #$04
BNE loc_8828E
._ship_no_y_move:
; -
LDA _cur_obj_pos._COL
CMP _obj_dst_pos._ship._COL
BNE loc_8828E
LDA _cur_obj_pos._ROW
CMP _obj_dst_pos._ship._ROW
BNE loc_8828E
LDA #$FF
RTS
loc_8828E:
; LDA _obj_cur_spr_idx._ship ; REDUNDANT, not used here, like for train
RTS
; =============== S U B R O U T I N E =======================================
_obj_ship_retarget:
JSR _get_cur_obj_map_ptr ; _ptr15/_ptr15+1 = map_buf_pos ofs
; LDA #$00 ; REDUNDANT, unused here
; STA _tmp17
LDA _obj_cur_spr_idx._ship ; X = cur ship spr idx
TAX
CLC
ADC #$04
AND #$07
STA _ptr18 ; _ptr18 = opposite direction spr idx
JSR _obj_ship_look_for_new_dir
TXA ; A gets new direction (opposite, if no other cases)
CMP _obj_cur_spr_idx._ship ; we still on the same course?
BEQ .ship_course_same
LDY _cur_obj_idx ; no
PHA ; save new direction for now
LDX _obj_cur_spr_idx,Y
STX _ptr18
STA _obj_dst_spr_idx,Y ; set new direction index
ASL
ASL
ASL
ADC _ptr18
TAX
LDA _obj_spr_rotate_delta_table,X ; select rotate delta
STA _obj_spr_delta,Y ; setup rotation
; WRONG: this code does the same work as _obj_rotate,
; when angles less than 2, _obj_rotate will do full
; round, because starting from desired value already...
; so let the right code do the right work instead.
; -
; LDA _ptr18
; CLC
; ADC _obj_spr_delta,Y
; AND #$07
; STA _obj_cur_spr_idx._ship
; -
PLA ; restore new direction
.ship_course_same:
ASL ; set new target 1 tile ahead
TAX ; in a desired direction
LDA _cur_obj_idx
ASL
TAY
LDA _obj_dst_pos._COL,Y
CLC
ADC _obj_dir_delta_list,X
STA _obj_dst_pos._COL,Y
LDA _obj_dst_pos._ROW,Y
CLC
ADC _obj_dir_delta_list+1,X
STA _obj_dst_pos._ROW,Y
RTS
; =============== S U B R O U T I N E =======================================
_obj_ship_look_for_new_dir:
; -
; NEW: let's make ship more interesting
; -
LDA _rand_seed
CMP #$F0 ; probability of course change 1/16
BCC .loop
AND #$02
BNE .rleft
INX ; rotate right
BNE .rrot
.rleft:
DEX ; rotate left
.rrot:
TXA
AND #$07
TAX
; -
.loop:
LDA _obj_map_tile_dir_buf_ofs_list,X; map tile ofs for spr directions
TAY
BPL loc_882FB
DEC _ptr15+1 ; adjust memory page for negative offsets
LDA (_ptr15),Y
INC _ptr15+1
BNE loc_882FD
loc_882FB:
LDA (_ptr15),Y ; get the corresponding map tile
loc_882FD:
; CMP #_MAP_WATER_ROUTE ; test if it is a special sea tile only
CMP #_MAP_WATER ; NEW: let's use regular sea tile
BNE loc_8830B
JSR _obj_ship_max_range_test
BCC loc_8830B
CPX _ptr18 ; forbid opposite pos change
BEQ loc_8830B
RTS
loc_8830B:
INX ; look for all tiles around
TXA
AND #$07
TAX
CMP _obj_cur_spr_idx._ship ; make full circle clockwise
BNE .loop
LDX _ptr18 ; default value - opposite one
RTS
_obj_map_tile_dir_buf_ofs_list:
.BYTE $B4,$B5,$01,$4D,$4C,$4B,$FF,$B3
; =============== S U B R O U T I N E =======================================
_obj_ship_max_range_test:
LDA _cur_obj_pos._COL ; here we should decide if we can
BEQ .ship_leftmost_pos ; go in the selected direction
CMP #$4B
BEQ .ship_rightmost_pos
LDA _cur_obj_pos._ROW
BEQ .ship_top_pos
CMP #$4B
BEQ .ship_bottom_pos
.ship_can_go:
SEC
RTS
.ship_cant_go:
; WRONG! ship can stuck because of that, the main loop counter may never
; reach the stop condition, if skipped here
;
; INX ; this code somehow (not ideal) does
; TXA ; some kind of bouncing of the map borders
; AND #$07 ; or else the ship will float along sides of the map forever
; TAX
; CLC
RTS
.ship_leftmost_pos:
CPX #$05 ; leftmost position, but opposite direction
BCC .ship_can_go ; can go
BCS .ship_cant_go ; otherwise cant
.ship_rightmost_pos:
CPX #$01 ; etc. all corner cases
BCC .ship_can_go
CPX #$04
BCC .ship_cant_go
BCS .ship_can_go
.ship_top_pos:
CPX #$02
BCC .ship_cant_go
CPX #$07
BEQ .ship_cant_go
BNE .ship_can_go
.ship_bottom_pos:
CPX #$03
BCC .ship_can_go
CPX #$06
BCC .ship_cant_go
BCS .ship_can_go
; REDUNDANT
;_obj_dir_delta_list:
; .BYTE $00,$FF
; .BYTE $01,$FF
; .BYTE $01,$00
; .BYTE $01,$01
; .BYTE $00,$01
; .BYTE $FF,$01
; .BYTE $FF,$00
; .BYTE $FF,$FF
; =============== S U B R O U T I N E =======================================
_obj_hndl08_train:
LDA #$03
STA _cur_obj_idx
JSR _obj_fetch
LDX _frames_div8_counter
CPX _cur_obj_idx
BNE loc_88347
LDA _obj_spr_delta._train
BEQ loc_88337
JMP _obj_rotate
loc_88337:
JSR _obj_train_dst_test
CMP #$FF
BNE loc_88344
JSR _obj_train_retarget
JMP _obj_draw
loc_88344:
JSR _cur_obj_move
loc_88347:
JMP _obj_draw
; =============== S U B R O U T I N E =======================================
_obj_train_dst_test:
LDX _obj_shift._train._COL
LDA _obj_cur_spr_idx._train ; select movement direction
AND #$02 ; may be only vert or hor
BNE loc_88357
LDX _obj_shift._train._ROW
loc_88357:
CPX #$04
BNE locret_8836D ; if timers are max
LDA _cur_obj_pos._COL ; test if we in dest point
CMP _obj_dst_pos._train._COL
BNE locret_8836D
LDA _cur_obj_pos._ROW
CMP _obj_dst_pos._train._ROW
BNE locret_8836D
LDA #$FF ; if yes, return FF
locret_8836D:
RTS ; otherwise return nothing
; =============== S U B R O U T I N E =======================================
_obj_train_retarget:
JSR _get_cur_obj_map_ptr ; cur map tile under obj in _ptr15/_tmp16
; LDA #$00 ; REDUNDANT, seems unused here
; STA _tmp17
LDA _obj_cur_spr_idx._train
TAX
CLC
ADC #$04
AND #$07
STA _ptr18 ; calc opposite direction
LDX #$00
LDY #$00
LDA (_ptr15),Y ; check cur tile
loc_88386:
CMP _rail_tiles_allowed,X ; search if tile is allowed to ride
BEQ .path_decide
INX
CPX #$11
BCC loc_88386 ; X has its index now in arrays
LDA _train_hide_mode ; not on the rails, hidden object,
BNE .building_bounce ; continue to ride inside only
JMP .remove_train ; building available for it - rail station
.building_bounce:
LDA _obj_cur_spr_idx._train ; any other building except rail station
AND #$02 ; should bounce the train, else
BEQ .search_vertically ; ride straigth forward inside
BNE .search_horisontally
.path_decide:
CPX #$04
BCS loc_883AA
.search_horisontally:
LDY #$00 ; 00-03, Y=0 (X ofs)
JMP .search_straigth_path
loc_883AA:
CPX #$08
BCS loc_883B3
.search_vertically:
LDY #$01 ; 04-07, Y=1 (Y ofs)
JMP .search_straigth_path
loc_883B3:
CPX #$0C
BCS loc_883BA
JMP .train_dst_rotate_set ; 08-0B
loc_883BA:
CPX #$10
BCS .search_cross_path ; 10
BCC .search_t_cross_path ; 0C-0F
_rail_tiles_allowed: ; 00 horizontal rails
.BYTE _MAP_RAIL_LR
.BYTE _MAP_WATER_RAIL_LR
.BYTE _MAP_ELECTRO_RAIL_LR
.BYTE _MAP_ROAD_RAIL_LR
.BYTE _MAP_RAIL_UD ; 04 vertical rails
.BYTE _MAP_WATER_RAIL_UD
.BYTE _MAP_ELECTRO_RAIL_UD
.BYTE _MAP_ROAD_RAIL_UD
.BYTE _MAP_RAIL_BEND_RD ; 08 bend rails
.BYTE _MAP_RAIL_BEND_LD
.BYTE _MAP_RAIL_BEND_RU
.BYTE _MAP_RAIL_BEND_LU
.BYTE _MAP_RAIL_TCROSS_R ; 0C t-cross rails
.BYTE _MAP_RAIL_TCROSS_L
.BYTE _MAP_RAIL_TCORSS_D
.BYTE _MAP_RAIL_TCROSS_U
.BYTE _MAP_RAIL_CROSS ; 10 cross rails
.search_cross_path:
INC _train_turns_counter ; can turn any direction, select next one
LDA _obj_cur_spr_idx._train ; current train position
ASL
STA _tmp118
LDA _train_turns_counter ; current turn direction
AND #$03
CLC
ADC _tmp118
TAX
LDA _train_cross_allow_table,X ; test if we positioned right
BEQ loc_883DE
TAX
JMP .train_dst_rotate_set ; if no, rotate first
loc_883DE:
JMP .train_dest_pos_set ; if yes, just move
_train_cross_allow_table:
.BYTE $00,$08,$00,$09
.BYTE $00,$09,$00,$0B
.BYTE $00,$0A,$00,$0B
.BYTE $00,$08,$00,$0A
.search_t_cross_path:
INC _train_turns_counter
TXA
SEC
SBC #$0C
ASL
ASL
ASL
CLC
ADC _obj_cur_spr_idx._train ; t-cross little bit harder
TAX ; but still can be calculated
LDA _train_turns_counter
AND #$01
BEQ loc_884BA
INX
loc_884BA:
LDA _train_t_cross_allow_table,X
BEQ loc_884C3
TAX
JMP .train_dst_rotate_set ; again, turn or move
loc_884C3:
JMP .train_dest_pos_set
_train_t_cross_allow_table:
.BYTE $00,$08,$00,$00,$00,$0A,$08,$0A
.BYTE $00,$09,$09,$0B,$00,$0B,$00,$00
.BYTE $08,$09,$00,$09,$00,$00,$00,$08
.BYTE $00,$00,$00,$0B,$0A,$0B,$00,$0A
.search_straigth_path:
LDA _cur_obj_pos,Y
BEQ .map_side_test
CMP #$4B
BNE .map_normal_test
INY
INY
.map_side_test:
LDX _obj_cur_spr_idx._train ; check the direction
TXA
CMP _train_straight_allow_list,Y
BEQ loc_8841E ; if out of the map, then
LDX _ptr18 ; turn opposite direction
STX _obj_cur_spr_idx._train
STX _obj_dst_spr_idx._train
loc_8841E:
JSR _obj_train_near_tile_test ; test next tile
BCC .remove_train
BCS .train_dest_pos_set
.map_normal_test:
LDX _obj_cur_spr_idx._train
JSR _obj_train_near_tile_test ; if next tile in the same direction
BCS .train_dest_pos_set ; is ok, then ride continue
LDX _ptr18
JSR _obj_train_near_tile_test ; or test for the opposite direction
BCS .set_opposite_direction
.remove_train:
LDA _obj_active_flags
AND #$F7
STA _obj_active_flags
LDA #$00
STA _train_hide_mode
RTS
.set_opposite_direction:
LDA _ptr18
STA _obj_cur_spr_idx._train
STA _obj_dst_spr_idx._train
JMP .train_dest_pos_set
_train_straight_allow_list:
.BYTE $02,$04,$06,$00
.train_dst_rotate_set:
TXA
SEC
SBC #$08
ASL
ASL
TAX
LDA _obj_cur_spr_idx._train
LSR
LSR
BCS loc_88461
INX
INX
loc_88461:
LDA _train_dst_data_table,X
STA _obj_dst_spr_idx._train
LDA _train_dst_data_table+1,X
STA _obj_spr_delta._train
LDX _obj_shift._train._COL
LDA _obj_shift._train._ROW
STA _obj_shift._train._COL
STX _obj_shift._train._ROW
.train_dest_pos_set:
LDA _obj_dst_spr_idx._train
ASL
TAX
LDA _obj_dst_pos._train._COL
CLC
ADC _obj_dir_delta_list,X
STA _obj_dst_pos._train._COL
LDA _obj_dst_pos._train._ROW
CLC
ADC _obj_dir_delta_list+1,X
STA _obj_dst_pos._train._ROW
RTS
_train_dst_data_table:
.BYTE $04,$FF ; down, counter clockwise
.BYTE $02,$01 ; right, clockwise
.BYTE $04,$01 ; down, counter clockwise
.BYTE $06,$FF ; left, counter clockwise
.BYTE $00,$01 ; up, clockwise
.BYTE $02,$FF ; right, counter clockwise
.BYTE $00,$FF ; up, counter clockwise
.BYTE $06,$01 ; left, clockwise
; =============== S U B R O U T I N E =======================================
; most of the following code is for determine if we run into the rail station
; or not. this is not trivial task because we won't know for sure wether it
; rail station or not if just bounce into a special building tile (80-8E) so we
; need here carefully calc the side you run into the building, then calc
; position of building index tile, read it and check again
;
_obj_train_near_tile_test:
LDY _obj_map_tile_dir_buf_ofs_list,X; tiles around special building are special
BPL loc_884F3 ; arranged. if you know tile index (0-E),
DEC _ptr15+1 ; you know for sure where the actual building
LDA (_ptr15),Y ; tile is.
INC _ptr15+1
BNE loc_884F5
loc_884F3:
LDA (_ptr15),Y
loc_884F5:
CMP #_MAP_TRAIN_STATION ; lucky! run straigth into the rail station!
BNE loc_884FC
JMP .rail_station_ride
loc_884FC:
CMP #_MAP_INTERNAL_BUILD0 ; run into top-left corner of any building
BCC .stop_move ; we know it is not the rail station for sure
CMP #_MAP_INTERNAL_BUILD8 ; this time it's harder, we know this is
BCC .rail_station_ride_test ; a building, but need to check which one
CMP #_MAP_RAIL_LR ; run into buldozered ground and roads,
BCC .stop_move ; stop
CMP #_MAP_ELECTRO_LR ; all kind of rails here,
BCC .continue_move ; move along
CMP #_MAP_ROAD_RAIL_LR ; the rest of not rideable grounds here
BCC .stop_move ; stop
CMP #_MAP_ELECTRO_ROAD_LR ; special road/rail crosses
BCC .continue_move ; move along
CMP #_MAP_ELECTRO_RAIL_LR ; skip again
BCC .stop_move
CMP #_MAP_WATER ; electric/rail crosses
BCC .continue_move ; move further
CMP #_MAP_WATER_RAIL_LR ; test for two special tiles, rails on water
BCC .stop_move ; it seems they planned some special
CMP #_MAP_WATER_ELECTRO_LR ; behavior for this, but currently no matter what
BCS .stop_move ; value in _train_hide_mode, it always just hiding
LDA #$03 ; the train if non-zero, so here train will be
BNE .continue_move_set ; hidden the same way as in train station while ride
.continue_move:
LDA #$00
.continue_move_set:
STA _train_hide_mode ; if non-zero, hide the train and continue ride
.continue_move_set_ex:
SEC ; may be either 0, 3 here and 1 or 2 when
RTS ; inside train station (see below)
.stop_move:
CLC
RTS
.rail_station_ride_test:
LDA _train_hide_mode ; already hidden, just continue
BNE .continue_move_set_ex
PUSHB _ptr18
TXA
PHA
CPY #$80
BCC loc_8855B
DEC _ptr15+1
LDA (_ptr15),Y
AND #$0F
TAX
LDA _ptr15
SEC
SBC _special_tiles_ofs_list,X
STA _ptr18
LDA _ptr15+1
SBC #$00
STA _ptr18+1
INC _ptr15+1
; LDA (_ptr18),Y ; OPTIMIZE
JMP loc_88570
loc_8855B:
LDA (_ptr15),Y
AND #$0F
TAX
LDA _ptr15
SEC
SBC _special_tiles_ofs_list,X
STA _ptr18
LDA _ptr15+1
SBC #$00
STA _ptr18+1
loc_88570:
LDA (_ptr18),Y
STA _ptr18+1
PLA
TAX
POPB _ptr18
LDA _ptr18+1
CMP #_MAP_TRAIN_STATION
; BEQ .rail_station_ride
; CLC
; RTS
BNE .stop_move ; OPTIMIZE size
.rail_station_ride:
LDA _obj_cur_spr_idx._train ; attempt to keep track of move direction
AND #$02 ; inside the building, but never used this way
LSR ; all this just REDUNDANT
ADC #$01
; STA _train_hide_mode
;loc_8858A:
; SEC
; RTS
BNE .continue_move_set ; OPTIMIZE size
; REDUNDANT
;_special_tiles_ofs_list:
; .BYTE $4C,$4D,$01,$98,$99,$9A,$4E,$02
; =============== S U B R O U T I N E =======================================
_obj_hndl10_monster:
; LDX #$00 ; WARNING: DUMB DELAY HERE!
;loc_88596: ; stealing cycles
; DEX ;
; BNE loc_88596 ; may I remove it, please?
LDA #$04
STA _cur_obj_idx ; mostly the same common handler
BIT _obj_monster_anim_phase1 ; with some difference
BMI .monster_regular_mode
JMP _monster_retarget ; OPTIMIZED
; JMP locret_885D8
.monster_regular_mode:
JSR _obj_fetch ; move only at it's own frame
LDA _frames_div8_counter
CMP _cur_obj_idx
BNE .monster_draw
DEC _obj_monster_delay
BNE .monster_skip_anim
; BEQ .monster_anim1
; CMP #$07 ; REDUNDANT, branch takes in any case
; BCC .monster_skip_anim ; this counter counts backwards
; LDA #$02 ; also have no values above 6
; STA _obj_monster_delay
; BNE .monster_skip_anim
;.monster_anim1:
JSR _monster_anim
.monster_skip_anim:
LDA _obj_monster_anim_phase0
CMP #$20
BEQ .monster_draw
JSR _monster_move
BCS locret_885D8
JSR _obj_fetch
.monster_draw:
JMP _obj_draw
locret_885D8: