-
Notifications
You must be signed in to change notification settings - Fork 0
/
scubacodc.asm
2216 lines (2151 loc) · 48.1 KB
/
scubacodc.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
;----------------------------------------------------------------------------
INCLUDE "scubacodb.txt"
;----------------------------------------------------------------------------
; ZX Spectrum 48K ROM calls used by the game code
ROM_KEYBOARD EQU $02BF ; Scan the keyboard and decode the key value into LAST-K variable
ROM_BEEPER EQU $03B5
ROM_CLS EQU $0D6B ; Clear screen; attributes are filled with ATTR_P
ROM_CHANOPEN EQU $1601 ; CHAN-OPEN subroutine
ROM_OUTNUM1 EQU $1A1B ; OUT-NUM-1 subroutine
ROM_PRSTRING EQU $203C ; PR-STRING subroutine
ROM_BORDER1 EQU $229B ; inside BORDER subroutine
ROM_CHARSET EQU $3D00
;----------------------------------------------------------------------------
; ZX Spectrum variables used by the game code
KSTATE5 EQU $5C05 ; KSTATE5
LAST_K EQU $5C08 ; LAST-K - Last key pressed
FLAGS2 EQU $5C6A ; FLAGS2 - More flags
FRAMES EQU $5C78 ; FRAMES - Frame counter
UDG EQU $5C7B ; UDG - Address of first user defined graphic
ATTR_P EQU $5C8D ; ATTR-P - Permanent current colours
;----------------------------------------------------------------------------
ORG $D900
DEFS $90
; Game
Game DI
PUSH IX
PUSH IY
LD HL,$0000
LD (SCORE),HL ; reset Score value
LD (HELD),HL ; reset HELD value
LD A,$03 ; Number of lives
LD (LIVES),A ; set the initial value
LD9A3 CALL PrepareMiniMap ; Prepare the world MiniMap table
CALL InitLevelVars ; Initialize variables depending of LEVEL
CALL LBEDB
LD HL,LE361
LD (HL),$00
LD9B1 CALL PrepareGame ; Prepare game screen and some variables
CALL LE6AB
LD HL,(L5B03) ; get Screen position on mini-map
CALL DrawGameScr ; Draw game screen
CALL LBDBA
LD9C0 CALL LB213
CALL LBDEA
CALL LE2A8
LD IX,DiverObj ; Diver object address
BIT 4,(IX+$26)
JR NZ,LD9DB
BIT 5,(IX+$10)
JR NZ,LD9F4
JR LD9C0
LD9DB LD A,(LIVES) ; get Number of lives
CP $04
JR NZ,LD9E7
LD A,$03
LD (LIVES),A ; set Number of lives
LD9E7 LD A,(LEVEL) ; LEVEL
CP $04
JR Z,LD9EF
INC A ; increase Game level
LD9EF LD (LEVEL),A ; Save LEVEL
JR LD9A3
LD9F4 LD B,$00 ; repeat 256 times
LD9F6 PUSH BC
CALL LB213
CALL LBDEA
CALL LE2A8
POP BC
DJNZ LD9F6
LD A,(L5B00)
CP $08
JR NZ,LDA1E
LD A,(L5B0F)
CP $03
JR NZ,LDA1E
LD A,(LIVES) ; get Number of lives
CP $01
JR Z,LDA1E ; No more lives? => no lives, jump
DEC A
LD (LIVES),A ; set Number of lives
JR LD9DB
LDA1E LD A,(LIVES) ; get Number of lives
CP $01 ; last live?
JR Z,LDA33 ; yes => game over
DEC A ; One live less
LD (LIVES),A ; set Number of lives
LD HL,LE361
LD A,(HL)
AND $20
LD (HL),A
JP LD9B1
LDA33 POP IY ; Ending the Game routine, the game is over
POP IX
EI
RET
; Clear screen, fill attributes with A
; I: A = screen attribute to use
LDA39 LD (L5B4A),A ; store the attribute as current
LD HL,$4000 ; screen pixels start address
LD BC,$1800 ; nummber of bytes for screen pixels area
LDA42 LD (HL),$00 ; clear pixels
INC HL
DEC BC
LD A,B
OR C
JR NZ,LDA42
LD A,(L5B4A) ; get current screen attribute
LD E,A
LD BC,$0300 ; number of bytes in screen attributes area
LDA51 LD (HL),E ; set attribute
INC HL
DEC BC
LD A,B
OR C
JR NZ,LDA51
RET
; Print char and shift current position right
LDA59 LD HL,(LDC7E)
INC L
LD (LDC7E),HL
DEC L
JR LDA6B
; Print char and shift current position down
LDA63 LD HL,(LDC7E)
INC H
LD (LDC7E),HL
DEC H
; Print char
; I: HL = char coords
; I: A = character to print
LDA6B PUSH HL
PUSH AF
CALL GetScrAddr ; Convert char coords HL to ZX screen address
EX DE,HL
POP AF
LD L,A
LD H,$00
RES 7,L
ADD HL,HL
ADD HL,HL
ADD HL,HL ; *8
BIT 7,A
JR NZ,LDA83
LD BC,ROM_CHARSET ; ROM font address, for chars $20..$7F
JR LDA86
LDA83 LD BC,LDC80 ; Tiles 8x8 address, for chars $80..$AE
LDA86 ADD HL,BC
LD B,$08 ; repeat 8 times
LDA89 LD A,(HL) ; get char pixels
LD (DE),A ; put on the screen
INC HL
INC D ; next row
DJNZ LDA89
POP HL ; restor char coords
CALL GetScrAttrAddr ; Get screen attribute address
LD A,(L5B4A) ; get current screen attribute
LD (HL),A ; set attribute on the screen
RET
; Print string
; I:HL String address
; I:BC Row and column
; I:DE Print char procedure address
LDA98 LD (LDAA2+1),DE
;
LDA9C LD (LDC7E),BC
LD A,(HL)
LDAA1 PUSH HL
LDAA2 CALL LDA59 ; Print char and shift !!! mutable argument DA59 / DA63
POP HL
INC HL
LD A,(HL)
CP $FF
JR NZ,LDAA1
RET
; Prepare game screen, indicators, and some variables
PrepareGame
LD A,$30
CALL LDA39 ; Clear screen with attribute A
LD A,$01
OUT ($FE),A
LD HL,LDC09 ; Indicator top border
LD BC,$0018
LD DE,LDA59 ; Procedure Print char and shift right
CALL LDA98 ; Print string
LD HL,LDC12 ; Indicator bottom border
LD BC,$1718
CALL LDA9C ; Print string
LD HL,LDC1B ; "HIGH"
LD BC,$011A
CALL LDA9C ; Print string
LD HL,LDC27 ; "SCORE"
LD BC,$031A
CALL LDA9C ; Print string
LD HL,LDC2D ; "HELD"
LD BC,$051A
CALL LDA9C ; Print string
LD HL,LDC32 ; Indicator left/right border
LD BC,$0118
LD DE,LDA63 ; Procedure Print char and shift down
CALL LDA98 ; Print string
LD HL,LDC32 ; Indicator left/right border
LD BC,$011F
CALL LDA9C ; Print string
LD HL,LDC49 ; "OXYGEN"
LD BC,$0C1A
CALL LDA9C ; Print string
LD HL,LDC50 ; "DEPTH"
LD BC,$0C1C
CALL LDA9C ; Print string
LD HL,LDC56 ; "SKILL LIVES"
LD BC,$081E
CALL LDA9C ; Print string
LD A,$38
LD (L5B4A),A ; set current screen attribute
LD HL,LDC65 ; Vertical gauge
LD BC,$0719
CALL LDA9C
LD HL,LDC65 ; Vertical gauge
LD BC,$071B
CALL LDA9C ; Print string
LD A,$0D
LD (L5B4A),A ; set current screen attribute
LD HL,LDC76 ; "1 2 3 4"
LD BC,$071D
CALL LDA9C ; Print string
LD HL,LDC76 ; "1 2 3 4"
LD BC,$101D
CALL LDA9C ; Print string
LD HL,$58FB ; address of top of Depth indicator in attributes area
LD (LDE55),HL ; set Depth initial level
LD (HL),$28 ; indicate initial Depth level
DEC HL
DEC HL
LD (LDE57),HL ; set Oxygen initial level
LD (HL),$20 ; indicate initial Oxygen level
LD A,(LEVEL) ; LEVEL
DEC A ; 0 / 1 / 2 / 3
RRCA ;
RRCA ; $00 / $40 / $80 / $C0
LD E,A
LD D,$00
LD HL,$58FD ; base address in attributes area
ADD HL,DE
LD (HL),$4F ; indicate Game level
LD A,(LIVES) ; get Number of lives
DEC A ; 0 / 1 / 2 / 3
RRCA ;
RRCA ; $00 / $40 / $80 / $C0
LD E,A
LD D,$00
LD HL,$5A1D ; base address in attributes area
ADD HL,DE
LD (LDE59),HL ; save address in attributes area
LD (HL),$4F ; indicate nummber of lives
LD IX,DiverObj ; Diver object address
CALL PrintHighScore ; Print high score number
CALL PrintScore ; Print score number
CALL PrintHeld ; Print HELD number
LD A,(LEVEL) ; LEVEL
DEC A
ADD A,A
ADD A,A
ADD A,A
ADD A,A ; A = (LEVEL - 1) * 16 => 0 / 16 / 32 / 48
LD E,A
LD D,$00
LD HL,LDDF0
ADD HL,DE ; HL = $DDF0 + (LEVEL - 1) * 16
LD DE,L5B27
LD BC,$000E
LDIR ; copy 14 bytes = 7 words
LD A,(LEVEL) ; LEVEL
LD C,A
LD A,$05
SUB C ; A = 5 - LEVEL => 4 / 3 / 2 / 1
LD (IX+$1C),A
LD (IX+$1E),A
LD C,A
LD A,$16
SUB C ; A => 12 / 13 / 14 / 15
LD (IX+$1D),A
LD (IX+$1B),A
LD A,(LEVEL) ; LEVEL
ADD A,A
LD C,A
LD A,$0A
SUB C ; A = 10 - LEVEL * 2
ADD A,$02
LD (L5B0E),A ; = 10 - LEVEL * 2 + 2 => 10 / 8 / 6 / 4
SUB $03
LD (L5B0D),A ; = 10 - LEVEL * 2 + 2 - 3 => 7 / 5 / 3 / 1
RET
; Initialize variables depending of LEVEL
InitLevelVars
LD A,(LEVEL) ; LEVEL
ADD A,A
ADD A,A ; *4
ADD A,$09 ; A = LEVEL * 4 + 9 => 13 / 17 / 21 / 25
LD (L5B13),A ; set Number of Meduza objects
LD (L5B14),A ; set Number of Round fishes
ADD A,$05 ; A = LEVEL * 4 + 9 + 5 => 18 / 22 / 26 / 31
LD (L5B16),A ; set Number of 26-byte records
SUB $05
ADD A,A
INC A ; A = (LEVEL * 4 + 9) * 2 + 1 => 27 / 35 / 43 / 51
LD (L5B15),A ; set Number of 21-byte records in group I
DEC A ; A = (LEVEL * 4 + 9) * 2 => 26 / 34 / 42 / 50
LD (L5B17),A ; set Number of 26-byte records in group III
LD A,(LEVEL) ; LEVEL
LD C,A
ADD A,A
ADD A,A
ADD A,C ; A = LEVEL * 5 => 5 / 10 / 15 / 20
LD (L5B18),A ; set Number of 26-byte records
LD C,A
ADD A,A
ADD A,C
SUB $03 ; A = LEVEL * 5 * 3 - 3 => 12 / 27 / 42 / 57
LD (L5B19),A ; set Number of 28-byte records in group V
LD HL,$0001
LD (L5B25),HL
LD A,(LEVEL) ; LEVEL
NEG
ADD A,$04 ; 3 / 2 / 1 / 0
RET Z
LD B,A ; B = loop counter
XOR A
LDC01 ADD A,$32 ; +50
DJNZ LDC01
LD (L5B25),A
RET
; Texts for indicator panel
LDC09 DEFB $80,$81,$81,$81,$81,$81,$81,$85,$FF ; Indicator top border
LDC12 DEFB $83,$81,$81,$81,$81,$81,$81,$84,$FF ; Indicator bottom border
LDC1B DEFB $28,$29,$27,$28,$FF ; "HIGH"
LDC20 DEFB $10,$10,$10,$10,$10,$10,$FF ; "000000"
LDC27 DEFB $33,$23,$2F,$32,$25,$FF ; "SCORE"
LDC2D DEFB $28,$25,$2C,$24,$FF ; "HELD"
LDC32 DEFB $82,$82,$82,$82,$82,$82,$82,$82 ; Indicator left/right border
DEFB $82,$82,$82,$82,$82,$82,$82,$82
DEFB $82,$82,$82,$82,$82,$82,$FF
LDC49 DEFB $2F,$38,$39,$27,$25,$2E,$FF ; "OXYGEN"
LDC50 DEFB $24,$25,$30,$34,$28,$FF ; "DEPTH"
LDC56 DEFB $33,$2B,$29,$2C,$2C,$00,$00,$00 ; "SKILL LIVES"
DEFB $00,$2C,$29,$36,$25,$33,$FF
LDC65 DEFB $86,$87,$87,$87,$87,$87,$87,$87 ; Vertical gauge
DEFB $87,$87,$87,$87,$87,$87,$87,$88
DEFB $FF
LDC76 DEFB $11,$00,$12,$00,$13,$00,$14,$FF ; "1 2 3 4"
LDC7E DEFW $0000 ; Char coords for printing on the screen, see DA59
; Tiles 8x8
LDC80 DEFB $00,$7F,$40,$58,$58,$40,$43,$42
DEFB $00,$FF,$00,$18,$18,$00,$FF,$00
DEFB $42,$42,$42,$5A,$5A,$42,$42,$42
DEFB $42,$43,$40,$58,$58,$40,$7F,$00
DEFB $42,$C2,$02,$1A,$1A,$02,$FE,$00
DEFB $00,$FE,$02,$1A,$1A,$02,$C2,$42
DEFB $FF,$81,$81,$E7,$81,$81,$81,$81
DEFB $81,$81,$81,$E7,$81,$81,$81,$81
DEFB $81,$81,$81,$E7,$81,$81,$81,$FF
DEFB $07,$0F,$1F,$7F,$3F,$3E,$7E,$1F
DEFB $47,$C3,$61,$7F,$7F,$7F,$7F,$1D
DEFB $04,$0F,$0F,$7F,$3E,$78,$70,$E0
DEFB $70,$38,$7C,$7F,$7F,$1F,$07,$02
DEFB $0C,$1C,$18,$78,$78,$F8,$70,$78
DEFB $78,$70,$FC,$7F,$7F,$3F,$1F,$00
DEFB $D2,$FF,$76,$70,$F0,$F9,$7F,$7F
DEFB $7F,$79,$F0,$F8,$70,$7C,$7F,$50
DEFB $02,$1F,$3F,$3F,$7D,$78,$F8,$7B
DEFB $FF,$7F,$7E,$7A,$18,$70,$E0,$60
DEFB $80,$D0,$F8,$FF,$FE,$DE,$0E,$02
DEFB $E0,$E0,$F8,$FC,$FC,$FC,$F0,$98
DEFB $00,$E0,$F0,$F8,$70,$30,$00,$00
DEFB $00,$00,$0C,$74,$F8,$F8,$E0,$80
DEFB $70,$F8,$78,$FC,$38,$3C,$18,$38
DEFB $3C,$18,$38,$30,$F8,$FC,$F0,$C0
DEFB $C0,$F0,$F0,$FC,$F8,$E0,$E0,$80
DEFB $C0,$70,$78,$7C,$F8,$F0,$E0,$40
DEFB $00,$80,$C0,$F0,$E0,$78,$F8,$F0
DEFB $F8,$F0,$78,$38,$78,$38,$70,$78
DEFB $B1,$7F,$7F,$7F,$FD,$78,$78,$FC
DEFB $F0,$70,$78,$70,$F1,$7F,$7F,$CC
DEFB $03,$07,$01,$03,$01,$03,$00,$01
DEFB $00,$00,$01,$01,$03,$01,$07,$03
DEFB $F8,$F0,$78,$7C,$FE,$FE,$7E,$7E
DEFB $7F,$FF,$FF,$7F,$3F,$1F,$1F,$0A
DEFB $00,$FF,$FF,$67,$E0,$60,$60,$6E
DEFB $FF,$F8,$60,$70,$76,$7F,$3F,$01
DEFB $60,$F4,$FE,$FE,$BF,$3E,$3F,$3F
DEFB $3F,$1F,$3F,$7F,$FF,$FE,$FC,$EC
DEFB $80,$C0,$E0,$E0,$E0,$C0,$C0,$C0
DEFB $80,$C0,$C0,$C0,$80,$C0,$E0,$80
DEFB $0B,$1F,$1E,$3E,$7F,$3F,$7C,$FC
DEFB $FC,$FC,$F8,$F8,$F0,$F8,$F0,$E0
DEFB $80,$F8,$F0,$F0,$78,$00,$00,$00
DEFB $80,$00,$00,$00,$80,$E0,$F0,$C0
DEFB $00,$00,$00,$00,$00,$00,$00,$00
; Blocks of 14 bytes to copy to 5B27, blocks aligned to 16 bytes
; L5B27 L5B29 L5B2B L5B2D L5B2F L5B31 L5B33
LDDF0 DEFW $0002,$0005,$004B,$0019,$0032,$00FA,$0019,$0000 ; Level 1
DEFW $0004,$000A,$0032,$0096,$0064,$01F4,$0032,$0000 ; Level 2
DEFW $0006,$000F,$0096,$00E1,$004B,$02EE,$004B,$0000 ; Level 3
DEFW $0008,$0014,$0064,$00C8,$012C,$03E8,$0064 ; Level 4
; Update gauge indicator on the screen
; I: A = value 0..15, DE = base address in screen attributes area
; I: HL = old address for the indicator
; O: HL = new address for the indicator
UpdateGauge
LD (HL),$38
RRCA
RRCA
RRCA
LD H,A
AND $E0
LD L,A
LD A,H
AND $01
LD H,A
ADD HL,DE ; add base address
LD (HL),C
RET
; Update Depth indicator
UpdateDepth
LD HL,(LDE55) ; get Depth indicator address
LD DE,$58FB ; base address in screen attributes area
LD C,$28
LD A,(L5B03+1) ; get screen position on mini-map, row value
INC A
SRL A
AND $0F ; 0..15
CALL UpdateGauge ; Update the gauge indicator on the screen
LD (LDE55),HL ; set Depth indicator address
RET
LDE55 DEFW $0000 ; Depth indicator, address in screen attributes
LDE57 DEFW $0000 ; Oxygen indicator, address in screen attributes
LDE59 DEFW $0000 ; Lives indicator, address in screen attributes
OXYGEN DEFW $FFFF ; Oxygen level
; Update Oxygen indicator
; I: HL = new value for Oxygen
UpdateOxygen
LD (OXYGEN),HL
LD A,H
SRL A
SRL A
SRL A
SRL A
LD H,A
LD A,$0F ; 0..15
SUB H
LD DE,$58F9 ; base address in screen attributes area
LD C,$20
LD HL,(LDE57) ; get Oxygen indicator address
CP $0E
JR C,LDE7E
CALL LE645 ; Play melody LE629
LD C,$10
LDE7E CALL UpdateGauge ; Update the gauge indicator on the scree
LD (LDE57),HL ; set Oxygen indicator address
RET
; Print decimal number
; I: HL = number to print
; I: DE = address on the screen
PrintDec
LD (IX+$23),B
PUSH DE
LD IY,LE5E0 ; address for list of dividers: 10000, 1000, 100, 10, 1
LDE8D LD C,$FF
LD E,(IY+$00)
LD D,(IY+$01) ; get divider in DE
BIT 7,D
JR Z,LDEA0
LD (IX+$23),D
LD C,$00
JR LDEB6
LDEA0 INC C
OR A
SBC HL,DE
JR NC,LDEA0
ADD HL,DE
INC IY
INC IY
LD A,(IX+$23)
OR A
JR Z,LDEB6
DEC (IX+$23)
JR LDE8D
LDEB6 EX (SP),HL
EX DE,HL
LD B,$00
SLA C
SLA C
SLA C
LD HL,$3D80 ; ZX Charset (3D00) + $80 = address of char '0'
ADD HL,BC
LD B,$08 ; repeat 8 times
PUSH DE
LDEC7 LD A,(HL)
LD (DE),A
INC HL
INC D
DJNZ LDEC7
POP DE
INC E
EX DE,HL
EX (SP),HL
BIT 7,(IX+$23)
JR Z,LDE8D
POP DE
RET
; Print high score number
PrintHighScore
LD B,$00
LD HL,(HSCORE)
LD DE,$4059 ; screen address AT 25,2
CALL PrintDec ; Print decimal number
RET
; Print score number
PrintScore
LD B,$00
LD HL,(SCORE) ; get Score number
LD DE,$4099 ; screen address AT 25,4
CALL PrintDec ; Print decimal number
RET
; Print HELD number
PrintHeld
LD B,$02
LD HL,(HELD) ; get HELD value
LD DE,$40DA ; screen address AT 26,6
CALL PrintDec ; Print decimal number
RET
LDEFD DEFB $00,$00
HELD DEFW $0000 ; HELD value
LDF01 DEFB $00,$00,$00,$00,$00,$00,$02,$03
DEFB $02,$03,$18,$10,$00,$30
LDF0F DEFW $0000
LDF11 DEFB $00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00
; Table: Angle 0..15 -> (DX, DY)
LDF25 DEFB $00,$FE,$01,$FE,$02,$FE,$02,$FF,$02,$00,$02,$01,$02,$02,$01,$02
DEFB $00,$02,$FF,$02,$FE,$02,$FE,$01,$FE,$00,$FE,$FF,$FE,$FE,$FF,$FE
LDF45 DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
LDF8D DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
DEFB $00,$00,$00,$00,$00,$00,$00,$00
; I:IX = Diver object address = DiverObj
LDFD5 LD HL,(LB7B9)
LD DE,(L5B35)
LD (L5B35),HL
LD (LB7B9),DE
LD IY,LDF01
LD HL,LDF11
LD (LDF0F),HL
LD A,(IX+$09)
LD (IX+$0B),A
LD A,(IX+$0A)
LD (IX+$0C),A
BIT 7,(IX+$10)
JR Z,LE021
LD A,(IX+$06) ; get Angle 0..15
ADD A,A
LD C,A
LD B,$00
LD HL,LDF25 ; Table base address
ADD HL,BC
LD A,(HL) ; get DX value for the Angle
LD (IX+$04),A ; set DX value
INC HL
LD A,(HL) ; get DY value for the Angle
LD (IX+$05),A ; set DY value
BIT 0,(IX+$10) ; check "moving" bit
JR NZ,LE021
LD (IX+$04),$00 ; clear DX value
LD (IX+$05),$00 ; clear DY value
LE021 LD A,(IX+$13) ; get X value
LD HL,(L5B03) ; get Screen position on mini-map
ADD A,(IX+$04) ; add DX
LD (IX+$13),A ; set X value
SRL A
AND $07 ; 0..7
CP (IX+$02) ; compare to previous X shift
LD (IX+$15),A ; set X shift
JR Z,LE08D
CP $01
JR Z,LE068
CP $07
JR NZ,LE08D
BIT 7,(IX+$04) ; check DX sign - moving left?
JR Z,LE08D
BIT 7,(IX+$11)
JR Z,LE08D
DEC (IX+$00) ; one column left
RES 4,(IX+$0D)
LD A,(IX+$00) ; get column 0..255
CP (IX+$1C)
JR NC,LE08D
ADD A,$08
LD (IX+$00),A ; set column
SET 2,(IX+$10)
DEC L
JR LE08D
LE068 BIT 7,(IX+$04) ; check DX sign - moving left?
JR NZ,LE08D
BIT 7,(IX+$11)
JR NZ,LE08D
INC (IX+$00) ; one column right
RES 4,(IX+$0D)
LD A,(IX+$00) ; get column 0..255
CP (IX+$1B)
JR C,LE08D
SUB $08
LD (IX+$00),A ; set column
SET 2,(IX+$10)
INC L
LE08D LD A,(IX+$14) ; get Y value
ADD A,(IX+$05) ; add DY
LD (IX+$14),A ; set Y value
SRL A
AND $07 ; 0..7
CP (IX+$03) ; compare to previous Y shift
LD (IX+$16),A
JP Z,LE120
CP $01
JR Z,LE0EA
CP $07
JP NZ,LE120
BIT 7,(IX+$05) ; check DY sign - moving up?
JR Z,LE120
BIT 7,(IX+$12)
JR Z,LE120
LD A,(IX+$1A)
CP (IX+$28)
JR NZ,LE0CC
LD A,(IX+$03) ; get previous Y shift
LD (IX+$16),A ; set Y shift
ADD A,A
LD (IX+$14),A ; set Y value
JR LE120
LE0CC DEC (IX+$01) ; one row up
DEC (IX+$1A)
RES 3,(IX+$0D)
LD A,(IX+$01) ; get row 0..255
CP (IX+$1E)
JR NC,LE120
ADD A,$08
LD (IX+$01),A ; set row
DEC H ; one block up
SET 2,(IX+$10)
JR LE120
LE0EA BIT 7,(IX+$05) ; check DY sign - moving up?
JR NZ,LE120
BIT 7,(IX+$12)
JR NZ,LE120
INC (IX+$01)
INC (IX+$1A)
BIT 5,(IX+$26)
JR NZ,LE10A
LD A,(IX+$1A)
CP $46
CALL Z,LE9B0 ; => plus one live
LE10A RES 3,(IX+$0D)
LD A,(IX+$01) ; get row 0..255
CP (IX+$1D)
JR C,LE120
SUB $08
LD (IX+$01),A
INC H ; one block down
SET 2,(IX+$10)
LE120 LD A,(IX+$0D)
AND $18
CP $18
JR Z,LE174
BIT 2,(IX+$10)
JR Z,LE171
RES 1,(IX+$0D)
PUSH IX
PUSH IY
LD A,L
AND $1F ; column 0..31
LD L,A
LD A,H
AND $1F ; row 0..31
LD H,A
LD (L5B03),HL ; set Screen position on mini-map
CALL DrawGameScr ; Draw game screen
CALL UpdateDepth ; Update Depth indicator
LD HL,(LB7B9)
LD DE,(L5B35)
LD (LB7B9),DE
LD (L5B35),HL
CALL LBDBA
LD HL,(LB7B9)
LD DE,(L5B35)
LD (LB7B9),DE
LD (L5B35),HL
POP IY
POP IX
RES 2,(IX+$10)
JR LE174
LE171 CALL LB3AB
LE174 SET 4,(IX+$0D)
SET 3,(IX+$0D)
LD E,(IX+$04) ; get DX value
LD A,(IX+$15) ; get X shift 0..7
CP (IX+$02) ; compare to previous X shift
JR Z,LE18D
LD (IX+$02),A ; set previous X shift
LD (IX+$11),E
LE18D LD E,(IX+$05) ; get DY value
LD A,(IX+$16) ; get Y shift 0..7
CP (IX+$03) ; compare to previous Y shift
JR Z,LE19E
LD (IX+$12),E
LD (IX+$03),A ; set previous Y shift
LE19E BIT 7,(IX+$10)
JR NZ,LE1B8
LD A,(IX+$24)
LD (IX+$09),A
LD (IX+$0B),A
LD A,(IX+$25)
LD (IX+$0A),A
LD (IX+$0C),A
JR LE1F4
LE1B8 BIT 4,(IX+$10)
JR NZ,LE1C4
BIT 5,(IX+$10)
JR Z,LE1D2
LE1C4 LD A,(IX+$09)
LD (IX+$0B),A
LD A,(IX+$0A)
LD (IX+$0C),A
JR LE1F4
LE1D2 INC (IX+$17)
LD H,(IX+$06) ; get Angle 0..15
LD A,(IX+$17)
AND $03 ; 0..3
RRCA
RRCA
LD L,A
SRL H
RR L
LD DE,L92CC ; Diver sprites base address
ADD HL,DE ; now HL = diver sprite address
LD (IX+$0A),H
LD (IX+$0C),H
LD (IX+$09),L
LD (IX+$0B),L
LE1F4 CALL LB3A6
LD A,(IX+$01)
LD (IX+$19),A ; set Row
LD IY,(LB7B9)
LD D,(IX+$08)
LD E,(IX+$07)
BIT 0,(IX+$0D)
JR NZ,LE211
LD IY,LA41B ; empty sprite address
LE211 BIT 1,(IX+$0D)
JR NZ,LE21A
LD DE,LA41B ; empty sprite address
LE21A LD B,$03 ; loop 3 times
LE21C PUSH BC
LD A,(IX+$00)
LD (IX+$18),A ; set Column
LD L,A
LD H,(IX+$19) ; get Row
CALL GetScrAddr ; Convert char coords HL to ZX screen address
LD B,$03 ; loop 3 times
LE22C PUSH BC
PUSH HL
PUSH IY
PUSH DE
LD B,$08 ; loop 8 times
LE233 LD A,(DE)
XOR (HL)
LD C,A
AND (IY+$00)
JR Z,LE23F
SET 1,(IX+$10)
LE23F LD A,(IY+$00)
XOR C
LD (HL),A
INC H
INC DE
INC DE
INC DE
INC IY
INC IY
INC IY
DJNZ LE233
INC (IX+$18) ; one Column right
BIT 1,(IX+$10)
JR Z,LE26E
LD HL,(LDF0F)
LD A,(IX+$19) ; get Row
LD (HL),A
INC HL
LD A,(IX+$18) ; get Column
DEC A
LD (HL),A
INC HL
LD (LDF0F),HL
RES 1,(IX+$10)
LE26E POP DE
INC DE
POP IY
INC IY
POP HL
INC HL
POP BC
DJNZ LE22C
INC (IX+$19) ; one Row down
LD BC,$0015
ADD IY,BC
EX DE,HL
ADD HL,BC
EX DE,HL
POP BC
DJNZ LE21C
LD HL,(LB7B9)
LD BC,(L5B35)
LD D,(IX+$08)
LD E,(IX+$07)
LD (LB7B9),BC
LD (L5B35),DE
LD (IX+$08),H
LD (IX+$07),L
LD HL,(LDF0F)
LD (HL),$FF
RET
LE2A8 LD IX,DiverObj ; Diver object address
DEC (IX+$0F)
JR NZ,LE2CC
LD A,(IX+$0E) ; get speed factor
LD (IX+$0F),A
RES 1,(IX+$0D)
BIT 0,(IX+$0D)
JR Z,LE2C5
SET 1,(IX+$0D)
LE2C5 SET 0,(IX+$0D)
CALL LDFD5
LE2CC DEC (IX+$20)
RET NZ
LD (IX+$20),$14
CALL ReadKeyboard ; Read keyboard input
CALL LE364
RET
; Read keyboard input
; I: IX = Diver object address = DiverObj
ReadKeyboard
BIT 3,(IX+$10)
RET NZ
LD E,(IX+$06) ; get Angle
LD BC,(L5B38) ; get port for Clockwise key
LD A,(L5B3A) ; get bit mask for Clockwise key
LD D,A
IN A,(C) ; read the port for Clockwise key
AND D
JR NZ,LE2F1 ; not pressed => skip rotate
; Clockwise key pressed
INC E ; rotate clockwise
LE2F1 LD BC,(L5B3B) ; get port for Anticlockwise key
LD A,(L5B3D) ; get bit mask for Anticlockwise key
LD D,A
IN A,(C) ; read the port for Anticlockwise key
AND D
JR NZ,LE2FF ; not pressed => skip rotate
; Anticlockwise key pressed
DEC E ; rotate anticlockwise
LE2FF LD A,$0F
AND E
LD (IX+$06),A ; set Angle 0..15
LD BC,(L5B3E) ; get port for Accelerate key
LD A,(L5B40) ; get bit mask for Accelerate key
LD D,A
IN A,(C) ; read the port for Accelerate key
AND D
JR NZ,LE31F ; not pressed => skip
; Accelerate key pressed
LD A,(IX+$0E)
SET 0,(IX+$10) ; set "moving" bit
CP $08
RET Z
DEC (IX+$0E)
LE31F LD BC,(L5B41) ; get port for Decelerate key
LD A,(L5B43) ; get bit mask for Decelerate key
LD D,A
IN A,(C) ; read the port for Decelerate key
AND D
RET NZ ; not pressed => return
; Decelerate key pressed
LD A,(IX+$0E)
CP $14
JR NZ,LE337
RES 0,(IX+$10) ; clear "moving" bit - diver stopped
RET
LE337 INC (IX+$0E)
RET
; Diver object record
DiverObj
LE33B DEFB $0A ; (IX+$00) Column 0..255
LE33C DEFB $0A ; (IX+$01) Row 0..255
LE33D DEFB $04 ; (IX+$02) ??? X shift 0..7, previous value
LE33E DEFB $04 ; (IX+$03) ??? Y shift 0..7, previous value
LE33F DEFB $00 ; (IX+$04) DX value for the Angle, -2..2, see table DF25
LE340 DEFB $00 ; (IX+$05) DY value for the Angle, -2..2, see table DF25
LE341 DEFB $04 ; (IX+$06) Angle 0..15, initially 4
LE342 DEFW LDF8D ; (IX+$07) ???
LE344 DEFW $0000 ; (IX+$09) Sprite address
LE346 DEFW $0000 ; (IX+$0B) Sprite address
LE348 DEFB $18 ; (IX+$0D) ??? bits 0/1/2/3/4/5/6/7
LE349 DEFB $14 ; (IX+$0E) speed factor = 12 20 40 100; 8 max speed, 20 min speed
LE34A DEFB $14 ; (IX+$0F) speed counter
LE34B DEFB $00 ; (IX+$10) ??? bits 0/1/2/3/4/5/6/7; bit0: 1 = diver moving, 0 = diver stopped
LE34C DEFB $00 ; (IX+$11) ??? $00 $FF
LE34D DEFB $00 ; (IX+$12) ??? $00
LE34E DEFB $08 ; (IX+$13) X value
LE34F DEFB $08 ; (IX+$14) Y value
LE350 DEFB $00 ; (IX+$15) X shift 0..7
LE351 DEFB $00 ; (IX+$16) Y shift 0..7
LE352 DEFB $00 ; (IX+$17) ???
LE353 DEFB $00 ; (IX+$18) Column 0..31
LE354 DEFB $00 ; (IX+$19) Row
LE355 DEFB $0A,$12
LE357 DEFB $03 ; (IX+$1C) ???
LE358 DEFB $12,$03
LE35A DEFB $40 ; (IX+$1F) Row??
LE35B DEFB $00 ; (IX+$20) ??? $03
LE35C DEFB $00 ; (IX+$21) ???
LE35D DEFB $00 ; (IX+$22) ??? $F5
LE35E DEFB $00
LE35F DEFW $0000 ; (IX+$24) Sprite address
LE361 DEFB $00 ; (IX+$26) ??? bits 0/1/2/3/4/5/6
LE362 DEFB $00 ; (IX+$27) ???
LE363 DEFB $00 ; (IX+$28) ???
; I: IX = Diver object address = DiverObj
LE364 BIT 5,(IX+$10)
RET NZ
BIT 7,(IX+$10)
JP Z,LE767
LD HL,(OXYGEN) ; get Oxygen level
LD A,(LEVEL) ; LEVEL
ADD A,A
ADD A,A
ADD A,A ; *8
ADD A,$0A ; *8 + 10
LD E,A
LD D,$00
LD A,H
SBC HL,DE ; HL = [Oxygen] - LEVEL * 8 - 10
LD (OXYGEN),HL ; set Oxygen level
CP H
CALL NZ,UpdateOxygen ; => Update Oxygen indicator