-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathbankB.inc
4171 lines (4019 loc) · 122 KB
/
bankB.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 $A000
BANK_START $FB
; ---------------------------------------------------------------------------
; ---------C-I-T-Y--C-O-R-E--M-A-I-N--E-N-G-I-N-E--R-O-U-T-I-N-E-S-----------
; ---------------------------------------------------------------------------
SECTION_START B00
; =============== S U B R O U T I N E =======================================
; Here is the main loop for city engine. Performs continuously calculations
; on a different city areas and updating statuses.
;
; at the beginning we do initial calcs without entering critical section,
; so at the beginning of the game we may see a black screen sometime longer
; than usual. However, you still have a priority with controls, so this may
; be fixed by pressing buttons oc controller.
;
_THREAD1_MAIN:
FJSR _RCI_meters_recalc,SRAM,PRGA ; probably should be after clearing values here?
JSR _overall_stats_clear ; clear statistic counters and average values
JSR _overall_stats_recalc ; collect statistic for current map
JSR _smooth_police_and_fire_maps ; police and fire maps are initially updated in prev routine
FJSR _power_grid_recalc,SRAM,PRGA ; power connections and consumption recalc
JSR _land_value_and_pollution_recalc; land map and average recalc
JSR _crime_recalc ; crime map and average recalc
JSR _dencity_recalc ; population dencity and with migration point
LDA #$FF
STA _thread1_flags ; disable all ctitical sections, now all priorities are
STA _thread1_flags+1 ; reset
FJSR _city_stats_recalc,SRAM,PRGA ; must be the city evaluation recalc but at this point
LDA #$00 ; but most time levels here are zero, so calc not performed
STA _city._cur_week
; !FALLTHROUGH!
; =============== S U B R O U T I N E =======================================
_THREAD1_LOOP:
JSR _wait_for_hud_and_game_field_update ; priority as usual in THREAD0
INC _city._cur_week ; one loop - one week here
LDA _city._cur_week
LSR
BCC _rci_meters_calc_skip
FJSR _RCI_meters_recalc,SRAM,PRGA ; recalc RCI once in two weeks
_rci_meters_calc_skip:
JSR _map_corruption_tiles_animate ; animate destroyed map tiles
LDA _frames_counter ; reseed RNG, so we have different behaviour
STA _rand_seed ; on a different starts
ADDWB _city._tax_year_sum,_city._tax_rate ; summing tax rates every week
MOVWI _power_nodes_cnt,0 ; reset power grid nodes list
LDA #$07
STA _thread0_flags+1 ; take some priority
JSR _overall_stats_clear ; clear stats again
JSR _overall_stats_recalc ; collect stats one more time
LDA #$03
STA _thread0_flags+1
JSR _smooth_police_and_fire_maps ; do the same as on start, but with some
LDA #$00 ; priority masking
STA _thread0_flags+1
JSR _map_corruption_tiles_animate ; animate map again. a lot of them here
LDA _city._cur_week
AND #$03
BNE .default_city_calcs ; one month = 4 weeks, do additional calcs
LDA #$03
STA _thread1_flags+1
INC _city._cur_month ; yep, increase months
LDA _city._cur_month
CMP #$0C
BNE .default_month_work ; year = 12 months
LDA #$00
STA _city._cur_month ; reset monts, increase years
LDA _city._cur_year+1 ; unless it not 9999, or...
CMP #$27
BNE .do_year_increase
LDA _city._cur_year
CMP #$0F
BEQ .skip_year_increase ; ...the end of the time
.do_year_increase:
INCW _city._cur_year
.skip_year_increase:
FJSR _graphs_10_year_data_update,SRAM,PRGA ; update graphs per year
FJSR _fiscal_year_results_calc,SRAM,PRGA ; recalc taxes and display budget screen
FJSR _city_stats_recalc,SRAM,PRGA ; update city evaluation stats and traffic map!
JSR _map_corruption_tiles_animate ; animate again, to much time takes this loop
FJSR _test_for_new_decade,SRAM,PRGA ; test for the last decimal nibble of year
LDA _tmpE6 ; if 0, then upadte 100 year graphs as well
BNE .default_month_work
FJSR _graphs_100_year_data_update,SRAM,PRGA ; currently just copy last 10year stats
.default_month_work:
JSR _smooth_growth_map ; we have pop growth recalc here for the first time
JSR _map_corruption_tiles_animate ; and animate again. if not animate it will stay forever
.default_city_calcs:
JSR _smooth_traffic_map ; soften traffic dencity map
JSR _map_corruption_tiles_animate ; ANIMATE AGAIN!!!
FJSR _events_selector,SRAM,PRGA ; now chek if the events messages need to be displayed
.game_stop_loop:
LDY _city._game_speed ; when city is in pause mode, we will stop here
CPY #$03 ; and loop forever. means no other calcs on town anymore
BNE .game_core_calc
JSR _wait_for_hud_and_game_field_update
JMP .game_stop_loop
.game_core_calc:
LDA _power_grid_recalc_delay_mask,Y ; another speed limit option goes here
AND _city._cur_week ; for fast mode power connection and consumption
BNE .skip_power_grid_calc ; performed only once per month, very time spending
LDA #$02 ; procedure. slow and normal speeds are takes
JSR _critical_section_enter ; full power scan every week
FJSR _power_grid_recalc,SRAM,PRGA
LDA #$02
JSR _critical_section_leave
JSR _map_corruption_tiles_animate ; also animate tiles too
.skip_power_grid_calc:
LDY _city._game_speed ; for the rest of recalculations we have three
LDA _game_core_speed_mask_list,Y ; three speed options. all recalcs for fast mode go
AND _city._cur_week ; every 16 weeks, normal - every 8, slow - every 4.
; CMP _land_value_and_pollution_recalc_delay_list,Y ; land values calculated first within each delay
BNE loc_11E135 ; period, at counter 0
LDA #$A0 ; all these recalcs are time consuming, so time for
JSR _critical_section_enter ; complete this loop increased with a number of
JSR _land_value_and_pollution_recalc; calcs performes, so for fast modes they just skip
LDA #$A0 ; all except main evaluations
JSR _critical_section_leave
JSR _map_corruption_tiles_animate
loc_11E135:
LDY _city._game_speed ; crime level calculations performed at 2/4
LDA _game_core_speed_mask_list,Y ; of the delay period
AND _city._cur_week ; NOTE, when you select pause mode after
CMP _crime_recalc_delay_list,Y ; the stop loop above, you select fourth
BNE loc_11E153 ; set of delay counters and masks, which
LDA #$40 ; are always 0, so when you get here and change
JSR _critical_section_enter ; speed, at least two other calculations will
JSR _crime_recalc ; be forced
LDA #$40
JSR _critical_section_leave
JSR _map_corruption_tiles_animate
loc_11E153:
LDY _city._game_speed ; and finally, population recalcs performed
LDA _game_core_speed_mask_list,Y ; at 3/4 of the delay period.
AND _city._cur_week ; so all three recalcs performed once per loop
CMP _population_recalc_delay_list,Y ; at a different weeks, never calculated
BNE loc_11E171 ; at once
LDA #$04
JSR _critical_section_enter
JSR _dencity_recalc
LDA #$04
JSR _critical_section_leave ; animate map corruptions every time we exit the
JSR _map_corruption_tiles_animate ; long routine.
loc_11E171:
JSR _disasters_selector ; and finally at the end of the week we select the
JSR _map_corruption_tiles_animate ; desister if enabled manually or for scenario
JMP _THREAD1_LOOP
_power_grid_recalc_delay_mask:
.BYTE $03,$00,$00,$00
_game_core_speed_mask_list:
.BYTE $0F,$07,$03,$00
;_land_value_and_pollution_recalc_delay_list:
; .BYTE $00,$00,$00,$00 ; REDUNDAT, actually this not needed, because all zeroes
_crime_recalc_delay_list:
.BYTE $04,$02,$01,$00
_population_recalc_delay_list:
.BYTE $08,$04,$02,$00
; =============== S U B R O U T I N E =======================================
_overall_stats_clear:
LDX #$00
TXA
loc_11F242:
STA _total_RCI_counts,X ; TODO: make sure when RAM vars are
INX ; moved, all these vars whould be here
CPX #_counters_area_size ; maybe we should make a structure here
BNE loc_11F242
STA _city._level._R.FRAC
STA _city._level._R.INT
STA _city._level._C.FRAC
STA _city._level._C.INT
STA _city._level._I.FRAC
STA _city._level._I.INT
LDA _city._bank_flags
AND #$C0
STA _city._bank_flags
JSR _sram_write_enable
LDY #$00
TYA
loc_11F26A:
STA _fire_map,Y
STA _police_map,Y
INY
CPY #_fire_map_size
BNE loc_11F26A
JMP _sram_write_disable
; =============== S U B R O U T I N E =======================================
_map_corruption_tiles_animate:
LDA _corruption_anim_req ; end of loop signal, if equal
BEQ loc_11F33A ; then no tiles to animate left
JSR _sram_write_enable ; enable access to sram
MOVWO _tmpE6,_city_map ; pointer to the beginning
LDY #$00
STY _corruption_anim_req
loc_11F310:
LDA (_tmpE6),Y ; scan, look for corrupt tiles
SEC
SBC #_MAP_CORRUPT0 ; start with _MAP_CORRUPT0
BCC loc_11F324 ; skip if less than index
CMP #$04
BCS loc_11F324 ; there are 4 total anim tiles tile
TAX ; and one common corrupted ground
LDA _corrupt_ground_tiles_list,X ; then change to the next in list
STA (_tmpE6),Y
STA _corruption_anim_req ; set flag
loc_11F324:
INCW _tmpE6
CMPWI _tmpE6,_city_map_end ; test for end of buffer
BNE loc_11F310
JSR _wait_for_hud_and_game_field_update ; update the screen
JMP _map_corruption_tiles_animate
loc_11F33A:
JMP _sram_write_disable ; disable writes back
_corrupt_ground_tiles_list:
.BYTE _MAP_CORRUPT1,_MAP_CORRUPT2,_MAP_CORRUPT3,_MAP_CORRUPTED
; =============== S U B R O U T I N E =======================================
_overall_stats_recalc:
LDY #$00 ; collect info about city
loc_11E1A0:
LDX #$00
loc_11E1A2:
TXA
PHA
TYA
PHA
STX _tmp_map_pos._COL
STY _tmp_map_pos._ROW
JSR _get_cur_building_tile ; read the actual tile index
JSR _overal_stats_collect ; collect info
PLA ; now we have stats about
TAY ; how much buildings/transport etc.
PLA ; and ready to calculate next
TAX ; city state and stats
INX
CPX #$4C
BNE loc_11E1A2
INY
CPY #$4C
BNE loc_11E1A0
LDY _airports_count ; if any airport built
BEQ .no_airports
LDA _obj_active_flags ; test if obj already deployed
STA _tmpE6
LSR _tmpE6
BCS loc_11E1F2
ORA #$01 ; init deploy of helicopter object
STA _obj_active_flags
LDY _last_airport_pos._COL ; starting point is last checked
INY ; airport on map (so it will be always
INY ; bottom-rightmost airport)
STY _obj_pos._heli._COL
INY
STY _obj_dst_pos._heli._COL
LDY _last_airport_pos._ROW
INY
INY
STY _obj_pos._heli._ROW
INY
STY _obj_dst_pos._heli._ROW
LDA #$03
STA _obj_cur_spr_idx._heli
BNE loc_11E230
loc_11E1F2:
LSR _tmpE6
BCS loc_11E23F ; test if airplane in flight as well
; LDY _airports_count ; redundant, already checked
; BEQ .no_airports
ORA #$02
STA _obj_active_flags ; start to take off animation
LDA #$84
STA _obj_plane_anim_idx
LDA #$20
STA _obj_plane_anim_timer
LDA _last_airport_pos._COL
STA _obj_dst_pos._plane._COL
CLC
ADC #$03
STA _obj_pos._plane._COL
LDY _last_airport_pos._ROW
STY _obj_pos._plane._ROW
INY
INY
STY _obj_dst_pos._plane._ROW
LDA #$06
STA _obj_cur_spr_idx._plane
BNE loc_11E230
.no_airports:
LDA _obj_active_flags ; no airports - no flying objects
AND #$FC ; remove existing if airport destroyed
STA _obj_active_flags
; NEW: re-implemented another ship starting procedures, not intended to be used in original version
; -
loc_11E23F:
LDA _sea_ports_count
BEQ ._no_sea_ports
LDA _obj_active_flags ; test if obj already deployed
AND #$04
BNE loc_11E230 ; test if already deployed
LDA _obj_active_flags
ORA #$04
STA _obj_active_flags
LDA _obj_pos._ship._COL ; set start pos to end pos
STA _obj_dst_pos._ship._COL ; usually bottom-rightmost water tile
LDY _obj_pos._ship._ROW
STY _obj_dst_pos._ship._ROW
LDA #$07 ; upper left direction
STA _obj_cur_spr_idx._ship ; select right oriented tile
BNE loc_11E230 ; test if already deployed
._no_sea_ports:
LDA _obj_active_flags ; no sea ports - no floating objects
AND #$FB ; remove existing if airport destroyed
STA _obj_active_flags
; -
loc_11E230:
LDA _city._bank_flags ; test for bank states
BPL loc_11E23D
AND #$01
BNE .bank_break ; if bank built and message displayed, skip
LDA #$00
BEQ .bank_re_set ; if bank destroyed, clean flags
loc_11E23D:
AND #$01
BEQ .bank_break ; bank no set, no acctivated, exit
LDA #$1F
STA _game_msg_idx ; when bank built, enable loans and display msg
LDA #$01 ; this may take seconds to appear if town is huge
STA _game_msg_awaits_flag
LDA #$80 ; set loan enable flag
.bank_re_set:
STA _city._bank_flags
.bank_break:
MADDW _tmpE6,_RCI_counts._R,_RCI_counts._C ; calculate overall data
; BUG! copy-paste, second CLC wrong here!
; -
; LDA _tmpE6
; CLC
; ADC _RCI_counts._I
; STA _total_RCI_counts
; LDA _tmpE7
; CLC
; ADC _RCI_counts._I+1
; STA _total_RCI_counts+1
; -
MADDW _total_RCI_counts,_tmpE6,_RCI_counts._I ; FIX, total sum of areas
; REDUNDANT, will change after end of the fiscal year, but used in some further calcs
; in event manager. not used anywhere near here after all, can be freely removed
; -
; LDA _nuke_power_station_count
; CLC
; ADC _coal_power_station_count
; STA _tmp6CC
; -
LSADDW _tmpE6,_city._level._C,_city._level._I,3 ; calculate population value
MADDW _tmpE6,_tmpE6,_city._level._R ; CAUTION! optimized code
PHA ; PHA here pushes INT part of E6
PUSHB _tmpE6 ; after MADDW instruction.
PUSHB #$14
JSR _mmc5_mul16to8 ; fp8_8 mul to int result fp16_8, but threated as an integer, so
POPD _popul_cur ; 16_8 with shifted mantissa popul_cur = ((L_C+L_I)*8 + L_R) * 20 * 256
MADDW _stats._total,_stats._developed,_stats._undeveloped
MADDW _stats._total,_stats._total,_stats._other
RTS
; =============== S U B R O U T I N E =======================================
_overal_stats_collect:
LDY _last_map_tile_read
; CPY #_MAP_BRIDGE_ROAD_LR ; UNFINISHED: here they planned to animate
; BNE loc_11E2EA ; drawbridges
; NOP
;loc_11E2EA:
CPY #_MAP_GROUND ; calc electric communications
BCC loc_11E2FB ; skip buildings, they are counted separately
LDA _map_tiles_flags_tbl,Y ; now all conductor tiles below ground are electric wires
BPL loc_11E2FB ; skip the rest
INCW _electrics_count ; used in overwiew screen only
loc_11E2FB:
CPY #_MAP_GROUND ; no need to do somerhing with
BNE loc_11E308
INCW _ground_count ; count bulldozered grounds for owerview screen
RTS
loc_11E308:
; LDA _last_map_tile_read ; REDUNDANT, _last_map_tile_read here still in Y
; CMP #_MAP_FIRE
CPY #_MAP_FIRE
BNE loc_11E312
JMP _fire_tile_collect ; fire area animate
loc_11E312:
; CMP #_MAP_FLOOD ; REDUNDANT
CPY #_MAP_FLOOD
BNE loc_11E319
JMP _flooded_tile_collect ; flooded area animate
loc_11E319:
; CMP #_MAP_POLLUTION ; REDUNDANT
CPY #_MAP_POLLUTION
BNE loc_11E320
JMP _polluted_tile_collect ; polluted area animate
loc_11E320:
; TAY
LDA _map_tiles_flags_tbl,Y
AND #_FL_ROAD
BEQ loc_11E32B
JMP _road_tile_collect ; roads collect
loc_11E32B:
LDA _map_tiles_flags_tbl,Y ; not a building, skip
AND #_FL_BUILDING ; also skip if inside the building
BEQ loc_11E33A ; calculate only real building indexes
LDA _cur_map_tile_is_inside_a_building_flag
BNE loc_11E33A
JMP _general_areas_collect ; here goes buildings stats
loc_11E33A:
LDA _map_tiles_flags_tbl,Y
AND #_FL_RAIL
BEQ loc_11E344
JMP _rails_collect ; rails collect
loc_11E344:
LDA _map_tiles_flags_tbl,Y ; all terrain but not the buildings
AND #_FL_TERRAIN ; like parks, sea shores and bridges
; BEQ loc_11E34E ; REDUNDANT
; JMP .protected_collect
;loc_11E34E:
BNE .protected_collect ; FIX
CPY #_MAP_CORRUPT0
BNE locret_11E355
STY _corruption_anim_req ; animate corrupted tile request
locret_11E355:
RTS
.protected_collect:
LDA _last_map_tile_read
CMP #_MAP_GRASS ; look for park grass/threes
BCC locret_11E387
CMP #_MAP_CORRUPTED
BCS loc_11E36A
INCW _parks_count ; this is parks counter
RTS
loc_11E36A:
CMP #_MAP_WATER ; this is for water and seashores
BCC locret_11E387
; NEW: new code to handle properly ship deploy, still need better solution
; TODO, look for _MAP_WATER_ROUTE here
; -
BNE .no_open_water
MOVW _last_water_tile_pos,_tmp_map_pos ; store last water tile position
.no_open_water:
; -
CMP #_MAP_WOODS0
BCS loc_11E37B
INCW _water_count ; collect sea shores
RTS
loc_11E37B:
CMP #_MAP_WATER_ROAD_LR ; between sea shores are woods
BCS locret_11E387
INCW _woods_count ; calc unbulldozered/woods
locret_11E387:
RTS
; =============== S U B R O U T I N E =======================================
_fire_tile_collect:
JSR _rand ; the probability of fire stops
CMP #$F0 ; 16/256
BCC loc_11E394
LDA #_MAP_CORRUPTED ; if hit the treshold, cease flame
JMP _map_tile_write ; the burned ground left
loc_11E394:
INCW _fires_count ; FIX, calculate an actual value.
LDX #$03 ; now check for 4 surroinding tiles
loc_11E396:
JSR _jump_to_near_to_tmp_map_pos_tile
BCS loc_11E3B5 ; skip if at the map edge
; BUG! this routine isn't X safe! it can reset X to 0
; sometimes, so we will skip a lot of near tiles for fires!
; FIX, function now X-safe
JSR _get_cur_building_tile ; read near tile index
LDY _last_map_tile_read ; test if flammable
LDA _map_tiles_flags_tbl,Y
AND #_FL_FLAMMABLE
BEQ loc_11E3B2 ; if no, then return back to the
JSR _rand ; current tile
CMP #$F4 ; or with probability 12/256
BCC loc_11E3B2 ; burn this near tile
JSR _burn_cur_map_tile
loc_11E3B2:
JSR _back_from_near_tmp_map_pos_tile; return to to the cur tile, repeat
loc_11E3B5: ; for all 4 nearest tiles
DEX
BPL loc_11E396
RTS
; =============== S U B R O U T I N E =======================================
_flooded_tile_collect:
LDA _disaster_tiles_to_flood_count ; this counter is set by disaster
BEQ .cease_flood ; start routine. the flood will end
DEC _disaster_tiles_to_flood_count ; when counter drops zero
LDY #$03
.do_flood:
TYA ; do test floods for all nearest tiles
PHA ; store counter for now
JSR _rand ; with probability 1/8 do flood
AND #$07
BNE .no_flood
PUSHB _tmp_map_pos._COL ; NOTE, as seen above, the _get_cur_building_tile
CLC ; routine not X safe, they overlooked it earlier
ADC _near_tile_pos_delta_col_list,Y ; but made some workaround for this problem here
STA _tmp_map_pos._COL ; by implementing another inline method of
PUSHB _tmp_map_pos._ROW ; retrieving the near tile positions with boundary test
CLC
ADC _near_tile_pos_delta_row_list,Y
STA _tmp_map_pos._ROW
JSR _tmp_map_pos_test_max ; if not exceeded the map boundaries, read near tile
BCS loc_11E3F7
JSR _get_cur_building_tile ; read actual nearest tile
LDY _last_map_tile_read
LDA _map_tiles_flags_tbl,Y ; test if we may flood this tile
AND #_FL_FLOODABLE
BEQ loc_11E3F7
JSR _flood_cur_map_tile ; if yes, then do flood
loc_11E3F7:
POPB _tmp_map_pos._ROW
POPB _tmp_map_pos._COL
.no_flood:
PLA
TAY
DEY
BPL .do_flood
RTS
.cease_flood:
JSR _rand ; 1/8 probability
AND #$07 ; to remove flooded ground
BNE locret_11E411
LDA #_MAP_GROUND
JMP _map_tile_write
locret_11E411:
RTS
; =============== S U B R O U T I N E =======================================
_polluted_tile_collect:
JSR _rand ; pollution slowly fade sometimes
BNE locret_11E423 ; we can't control this process
JSR _rand
CMP #$10
BCS locret_11E423 ; (1/256)*(16/256) probability it fade
LDA #_MAP_GROUND
JMP _map_tile_write
locret_11E423:
RTS
; =============== S U B R O U T I N E =======================================
_road_tile_collect:
INCW _roads_count ; statistic counter
; !FALLTHROUGH!
; =============== S U B R O U T I N E =======================================
_transport_deteriorate_test:
LDA _map_tiles_flags_tbl,Y ; NOTE, for some reason we skip roads
BMI locret_11E456 ; if intersected with electrics
LDA _fund_rate_trans ; here we test for roads deteriorating
CMP #$1E ; funding above 94% is fine
BCS locret_11E456 ; else 1/256 chance to deteriorate
JSR _rand
BNE locret_11E456
JSR _rand ; the lower funding, more frequently
AND #$3F ; roads destroyed
CMP _fund_rate_trans ; (1/256)*((64-funding)/64) probability
BCC locret_11E456 ;
LDX #_MAP_WATER ; test for water roads again
LDA _map_tiles_flags_tbl,Y
AND #_FL_WATER
BNE loc_11E452
LDX #_MAP_CORRUPTED
loc_11E452:
TXA
JMP _map_tile_write ; destroy road
locret_11E456:
RTS
; =============== S U B R O U T I N E =======================================
_rails_collect:
INCW _rails_count ; statistics collect
LDA _obj_active_flags ; test if train object is active
AND #$08
BNE .no_trains_start ; the rest of the code is for deploying
LDA _last_map_tile_read ; the train object
CMP #_MAP_ROAD_RAIL_LR ; no start at road interceptions
BEQ .no_trains_start
CMP #_MAP_ROAD_RAIL_UD
BEQ .no_trains_start
CMP #_MAP_ELECTRO_RAIL_LR
BEQ .no_trains_start
CMP #_MAP_ELECTRO_RAIL_UD
BEQ .no_trains_start
LDA _tmp_map_pos._COL ; write start position
STA _obj_pos._train._COL ; and dst position to the same point
STA _obj_dst_pos._train._COL
LDA _tmp_map_pos._ROW
STA _obj_pos._train._ROW
STA _obj_dst_pos._train._ROW
LDA _tmp_map_pos._COL ; one more test for map edges
CMP #$4B
BCS .no_trains_start
LDA _tmp_map_pos._ROW
CMP #$4B
BCS .no_trains_start ; if we not at the edges, look forward
LDX #$02 ; for train destination
INC _tmp_map_pos._COL ; it moves one tile at once
loc_11E49F:
JSR _map_tile_read ; look if forward tile is a rail
TAY
LDA _map_tiles_flags_tbl,Y
AND #_FL_RAIL
BEQ loc_11E4BA ; if not rails, search next
CPY #_MAP_ROAD_RAIL_LR ; if special rails, search next
BEQ loc_11E4BA ; we not start at interceptions
CPY #_MAP_ROAD_RAIL_UD ; for some reason, but we may cross it
BEQ loc_11E4BA
CPY #_MAP_ELECTRO_RAIL_LR
BEQ loc_11E4BA
CPY #_MAP_ELECTRO_RAIL_UD
BNE .train_deploy
loc_11E4BA:
CPX #$04 ; try tile to the right
BEQ .no_trains_start ; then tile to the bottom
LDX #$04 ; only two dest directions here
DEC _tmp_map_pos._COL
INC _tmp_map_pos._ROW
BPL loc_11E49F
.train_deploy:
STX _obj_cur_spr_idx._train ; so select one of sprite types
STX _obj_dst_spr_idx._train ; hor or vert
LDA #$00
STA _obj_shift._train._COL ; fine tuning position reset
STA _obj_shift._train._ROW
LDA _obj_active_flags ; enable train object
ORA #$08
STA _obj_active_flags
.no_trains_start:
JMP _transport_deteriorate_test ; common transport deterioration test
; =============== S U B R O U T I N E =======================================
_general_areas_collect:
JSR _test_power_grid_map_bit ; test if building is powered
STA _cur_area_power_state ; remember this
BEQ loc_11E4F1
INCW _powered_areas ; collect powered areas
loc_11E4F1:
LDA _last_map_tile_read ; all up to _MAP_POLICE_STATION are
CMP #_MAP_POLICE_STATION ; RCI buildings
BCC .RCI_buildings_stats
LDX #OTHER_WIDX
JSR _inc_areas_stats ; increment other buildings counter
JMP _other_areas_collect ; all non living areas goes here
.RCI_buildings_stats:
CMP #_MAP_C_AREA_DEF
BCS loc_11E51F
CMP #_MAP_R_HOSPITAL
BNE loc_11E510
LDX #OTHER_WIDX ; hospitals are other buildings too
JSR _inc_areas_stats ; but resides in R areas
JMP .inc_hospital
loc_11E510:
CMP #_MAP_R_SCHOOL
BNE loc_11E51C
LDX #OTHER_WIDX
JSR _inc_areas_stats
JMP .inc_school
loc_11E51C:
JMP _R_areas_develop ; the rest is a normal RCI areas
loc_11E51F:
CMP #_MAP_I_AREA_DEF ; let's develop them
BCS loc_11E526
JMP _C_areas_develop
loc_11E526:
JMP _I_areas_develop
; NOTE, even when we destroy school here it stay counted for a while!
;
.inc_hospital:
INCW _hospitals_count ; additional test for removing the
LDA _hospitals_delta ; hospitals. but they grow as regular
BPL locret_11E558 ; R areas
LDA #$15
JSR _rand_clamp_A ; 1/16 probability to remove
; BNE locret_11E558
BEQ loc_11E553
RTS ; OPTIMIZED
.inc_school:
INCW _schools_count ; the same with schools
LDA _schools_delta ; if delta is negative, attempt
BPL locret_11E558 ; to destroy hospital
LDA #$15
JSR _rand_clamp_A
BNE locret_11E558
loc_11E553:
LDA #_MAP_R_AREA_DEF ; reset R area to 0
JMP _map_tile_write
locret_11E558:
RTS
; =============== S U B R O U T I N E =======================================
_other_areas_collect:
CMP #_MAP_COAL_POWER
BNE loc_11E7CC
LDA _coal_power_station_count ; coal power station building
BMI loc_11E7C4 ; no greater than 128
INC _coal_power_station_count
loc_11E7C4:
FJSR _power_node_insert,SRAM,PRGA ; insert power station as a power node
RTS
loc_11E7CC:
CMP #_MAP_NUCLEAR_POWER
BNE loc_11E7E0
LDA _nuke_power_station_count ; nuclear power stations
BMI loc_11E7D8 ; no greater than 128
INC _nuke_power_station_count
loc_11E7D8:
FJSR _power_node_insert,SRAM,PRGA ; the same for nuclear station
RTS
loc_11E7E0:
CMP #_MAP_POLICE_STATION
BNE loc_11E803
LDA _police_stations_count ; police stations
CMP #$63 ; no greater than 100
BCS loc_11E7EE
INC _police_stations_count
loc_11E7EE:
LDA _fund_rate_police ; if police have no roads nearby
STA _tmpE7 ; its radius less by half
JSR _get_near_road_tile ; C=1 no roads nearby
BCS loc_11E7FA
LSR _tmpE7
loc_11E7FA:
JSR _read_police_map ; also radius depends on funding
CLC ; so we have such small values here
ADC _tmpE7 ; put police center on map here will be
JMP _write_police_map ; max value, will interpolate later
loc_11E803:
CMP #_MAP_NEW_POLICE ; the present police station
BNE loc_11E80E ; has maximum range no matter why
LDA #$0F ; new police station
STA _tmpE7
JMP loc_11E7FA
loc_11E80E:
CMP #_MAP_FIRE_STATION ; same for fire stations
BNE loc_11E831
LDA _fire_stations_count ; max 100 fire stations
CMP #$63
BCS loc_11E81C
INC _fire_stations_count
loc_11E81C:
LDA _fund_rate_fire
STA _tmpE7
JSR _get_near_road_tile
BCS loc_11E828
LSR _tmpE7
loc_11E828:
JSR _read_fire_map
CLC
ADC _tmpE7
JMP _write_fire_map
loc_11E831:
CMP #_MAP_NEW_FIRE
BNE loc_11E83C
LDA #$0F ; new fire stations
STA _tmpE7
JMP loc_11E828
loc_11E83C:
CMP #_MAP_STADIUM ; also stadiums
BNE loc_11E854
LDA _stadiums_count
BMI loc_11E848
INC _stadiums_count
loc_11E848:
LDY #$00
LDA _city._delta._R ; if R delta positive, set
BMI loc_11E850 ; additional bonus flag
INY
loc_11E850:
STY _stadium_anim_enable_flag ; enable stadium animation if R grow
RTS
loc_11E854:
CMP #_MAP_AIR_PORT
BNE loc_11E86D
LDA _airports_count ; airports count
BMI loc_11E860
INC _airports_count
loc_11E860:
MOVW _last_airport_pos,_tmp_map_pos ; here we remember last airport position
RTS ; for plane and heli object deploy routines
loc_11E86D:
CMP #_MAP_SEA_PORT
BNE loc_11E8AD
LDA _sea_ports_count ; sea ports count
BMI loc_11E879
INC _sea_ports_count
loc_11E879:
LDA _obj_active_flags ; also test for ship deploy should be here
AND #$04
BNE locret_11E8AC
; UNFINISHED
; -
; LDY #>[_city_map] ; UNFINISHED very briefly written code
; STY _tmpE7 ; to search a special symbol in the sea
; LDY #<[_city_map] ; which should be inserted on map to mark
; STY _tmpE6 ; a special ship routes, ship not intended
;loc_11E888: ; to sail on free water here
; LDA (_tmpE6),Y
; CMP #_MAP_WATER_ROUTE ; special sea tile
; BEQ loc_11E8A0
; INC _tmpE6
; BNE loc_11E894
; INC _tmpE7
loc_11E894:
; LDA _tmpE6
; CMP #<[_city_map_size] ; BUG: here test value not the end of the buffer ptr
; CMP #<[_city_map_end] ; FIX: correct
; LDA _tmpE7 ; BUG: but buffer size
; SBC #>[_city_map_size] ; FIX: correct
; CMP #>[_city_map_end]
; BNE loc_11E888
; BEQ locret_11E8AC
;loc_11E8A0:
; LDA _tmp_map_pos._COL ; store the seaport location as a astarting position
; STA _obj_pos._ship._COL ; for the ship which isn't quite correct, because
; LDA _tmp_map_pos._ROW ; ship goes only on special tiles and without a special
; STA _obj_pos._ship._ROW ; test, it can just stuck on the ground
;-
; NEW
; there should be a code to store the starting ship position on any FE tile instead
; then whip will move on the fixed route. the only route exists on the DEtroit scenario map!
; never used anything else.
MOVW _obj_pos._ship,_last_water_tile_pos
; -
locret_11E8AC:
RTS
loc_11E8AD:
CMP #_MAP_BANK ; detect bank building here for some reason.
BNE locret_11E8B9
LDA _city._bank_flags
ORA #$01
STA _city._bank_flags
locret_11E8B9:
RTS
; =============== S U B R O U T I N E =======================================
_R_areas_develop:
LDX #R_AREA_WIDX ; increment counter for R
JSR _inc_RCI_counts
LDY _last_map_tile_read ; get current dev state
LDA _R_area_develop_levels_list,Y
STA _cur_area_develop_state
JSR _adc_RCI_level ; add it to the overall level
LDX #DEVELOPED_WIDX
LDA _last_map_tile_read ; collect development state stats
BNE loc_11E573
LDX #UNDEVELOPED_WIDX
; INX
; INX
loc_11E573:
JSR _inc_areas_stats
JSR _R_twin_areas_cleanup ; special test for double areas
LDA #$24
JSR _rand_clamp_A ; probability dev_state/36
CMP _cur_area_develop_state ; higher dev state, higher traffic
BCS loc_11E590
LDA #R_AREA_BIDX
JSR _traffic_calc ; calculate traffic around the building
BCS loc_11E590
JSR _get_life_ratio
JMP _R_develop_down
loc_11E590:
JSR _get_cur_building_tile ; while driving we change current tile
LDA _last_map_tile_read ; read it again
BEQ loc_11E59F ; if R area undeveloped, force it to develop
JSR _rand ; or 1/3 of chance to change the state
AND #$03
BNE locret_11E5FA ; otherwise do nothing
loc_11E59F:
JSR _rand ; get random value
STA _tmpE9
LDA _city._delta._R ; shift delta to 0-255 range
CLC
ADC #$80
PHA
PUSHB #$96 ; soften and shift to signed range again
JSR _mmc5_mul8to8
PLA
PLA
SEC
SBC #$4B
STA _tmpE8 ; E8 = ((delta+128)*0.6)-0.3
JSR _get_growth_ratio ; E* append with new growth ratio
CLC
ADC _tmpE8 ; now we have full range -128 to +127
CLC
ADC #$80 ; shift it to 0-255 range again
LDY _cur_area_power_state
BNE loc_11E5C8 ; if not powered, drop down instantly
LDA #$48
loc_11E5C8:
STA _tmpE8 ; now check what we have now
CMP #$7F
BCC .drop_R_down ; if we have negative lever now, drop growth down
SBC #$67 ; or else ratio in range 127-255 we have
CMP _tmpE9 ; ratio-106)/256 chance to grow
BCC .drop_R_down ; higher ration, higher chance, however we
LDA _cur_area_develop_state ; will drop here anyway
BNE .grow_R_up ; if already developed, force grow
LDA _tmpE9 ; if not, the 1/3 chance to
AND #$03 ; attempt to spawn hospital or school
; BNE .grow_R_up ; REDUNDANT
; JMP .spawn_hopital_or_school
BEQ .spawn_hopital_or_school ; OPTIMIZED
.grow_R_up:
JSR _get_life_ratio
JMP _R_develop_up
.drop_R_down:
LDA _tmpE8 ; when negative or small positive
CMP #$82 ; add 106 and test against random again
BCS locret_11E5FA ; to decide to develop down or not
ADC #$67
CMP _tmpE9
BCS locret_11E5FA ; chance 20/256 you skip it
JSR _get_life_ratio
JMP _R_develop_down
locret_11E5FA:
RTS
.spawn_hopital_or_school:
JSR _rand ; 50/50 select either hospital or shcool
BPL loc_11E612
LDA _hospitals_delta ; if we need them, delta is positive and not zero
BMI locret_11E623
BEQ locret_11E623
LDA #_MAP_R_HOSPITAL ; spawn one, clear request delta
JSR _map_tile_write
LDA #$00
STA _hospitals_delta
RTS
loc_11E612:
LDA _schools_delta ; or else spawn
BMI locret_11E623
BEQ locret_11E623
LDA #_MAP_R_SCHOOL
JSR _map_tile_write
LDA #$00
STA _schools_delta
locret_11E623:
RTS
; =============== S U B R O U T I N E =======================================
; {land_value-pollution}*7-52
;
_get_growth_ratio:
JSR _read_pollution_map
STA _tmpE7
JSR _read_land_value_map
SEC
SBC _tmpE7
BCS loc_11F350
LDA #$00
loc_11F350:
PHA
PUSHB #$07
JSR _mmc5_mul8to8 ; multiply to 7 this time and
PLA ; shift to signed range
TAX
PLA
TXA
SEC
SBC #$34
RTS
; =============== S U B R O U T I N E =======================================
_R_twin_areas_cleanup:
LDA _last_map_tile_read ; test if we currently at
CMP #_MAP_R_AREA_TWINA0 ; double area
BCC locret_11E72B
LDX #$01
JSR _tmp_map_pos_backup ; backup curpos slot 1
LDA _last_map_tile_read
SEC
SBC #_MAP_R_AREA_TWINA0 ; calc what twin area exactly
TAY ; out of four
LDA _tmp_map_pos._COL ; calculate where the other side
CLC ; of the building according
ADC _twin_area_col_list,Y ; to possible positions,
STA _tmp_map_pos._COL ; move to that area
LDA _tmp_map_pos._ROW
CLC
ADC _twin_area_row_list,Y
STA _tmp_map_pos._ROW
TYA ; backup cur idx
PHA