-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathjsw.skool
13480 lines (13303 loc) · 655 KB
/
jsw.skool
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
; Copyright 2012-2023, 2025 Richard Dymond ([email protected])
@rom
@defs=23552:9536 ; Clear all buffers
; Attribute buffer (room + Willy + entities + items)
;
; The routine at #R35245 initialises this buffer with the contents of the
; attribute buffer at #R24064 (empty room), writes the attributes for Willy,
; the arrows, the guardians and the items into it, and then copies the result
; to the attribute file.
b23552 DEFS 512
@defs=24064:512
; Attribute buffer (empty room)
;
; Initialised upon entry to a room by the routine at #R36203.
b24064 DEFS 512
; Screen buffer (room + Willy + entities + items)
;
; The routine at #R35245 initialises this buffer with the contents of the
; screen buffer at #R28672 (empty room), draws Willy, the rope, the arrows, the
; guardians and the items over this background, and then copies the result to
; the display file.
b24576 DEFS 4096
; Screen buffer (empty room)
;
; Initialised upon entry to a room by the routine at #R36147, and updated on
; each pass through the main loop by the routine at #R38137 if there is a
; conveyor in the room.
b28672 DEFS 4096
@start
@replace=/#n\i/#N\1,,,1($)
@replace=/#b\i/#N(\1,,,1)(0x)
@expand=#DEF(#BUG()(a) #LINK(Bugs#$a))
@expand=#DEF(#FACT()(a) #LINK(Facts#$a))
@expand=#DEF(#POKE()(a) #LINK(Pokes#$a))
@expand=#DEF(#S #FORMAT({mode[case]}))
@expand=#DEF(#GBUF(a,b=0) #LINK(GameStatusBuffer#$a)(#N$a#IF($b)(-#N$b)))
@set-handle-unsupported-macros=1
; Jet Set Willy disassembly
; https://skoolkit.ca
;
; Copyright 1984 Software Projects Ltd (Jet Set Willy)
; Copyright 2012-2023, 2025 Richard Dymond (this disassembly)
@bfix+begin
;
; This disassembly contains fixes for the following bugs:
; * The invisible item
; * The inaccessible items
; * The uncollectable item
; * Invalid grid location
; * The pause bug
; * The Attic bug
; * Corrupted conveyors
; * Very corrupted conveyor
; * Guardian halos
; * Long distance nasties
; * From top to bottom
; * The self-collecting item
; * The sticky bed
; See https://skoolkit.ca/disassemblies/jet_set_willy/reference/bugs.html for
; full descriptions of these bugs.
@bfix+end
@isub+begin
@org
c32765 JP 33792
@isub+end
; Room layout
;
; Initialised upon entry to a room and then used by the routine at #R35090, and
; also used by the routine at #R36203.
@label=ROOMLAYOUT
g32768 DEFS 128
; Room name
;
; Initialised upon entry to a room and then used by the routine at #R35090.
@label=ROOMNAME
g32896 DEFS 32
; Room tiles
;
; Initialised upon entry to a room by the routine at #R35090.
@label=BACKGROUND
g32928 DEFS 9 ; Background tile (used by the routines at #R36147,
; #R36288, #R36307 and #R38430, and also by the unused
; routine at #R37819)
@label=FLOOR
32937 DEFS 9 ; Floor tile (used by the routines at #R36147 and #R36288)
@label=WALL
32946 DEFS 9 ; Wall tile (used by the routines at #R36147, #R36288,
; #R36307 and #R36796)
@label=NASTY
32955 DEFS 9 ; Nasty tile (used by the routines at #R36147, #R36288,
; #R36307 and #R38430)
@label=RAMP
32964 DEFS 9 ; Ramp tile (used by the routines at #R36147, #R36203,
; #R36796 and #R38344)
@label=CONVEYOR
32973 DEFS 9 ; Conveyor tile (used by the routines at #R36147, #R36203
; and #R36564)
; Conveyor definition
;
; Initialised upon entry to a room by the routine at #R35090.
@label=CONVDIR
g32982 DEFB 0 ; Direction (0=left, 1=right; used by the routines at
; #R36564 and #R38137)
@label=CONVLOC
32983 DEFW 0 ; Address of the conveyor's location in the attribute
; buffer at #R24064 (used by the routines at #R36203 and
; #R38137)
@label=CONVLEN
32985 DEFB 0 ; Length (used by the routines at #R36203 and #R38137)
; Ramp definition
;
; Initialised upon entry to a room by the routine at #R35090.
@label=RAMPDIR
g32986 DEFB 0 ; Direction (0=up to the left, 1=up to the right; used by
; the routines at #R36203, #R36796 and #R38344)
@label=RAMPLOC
32987 DEFW 0 ; Address of the location of the bottom of the ramp in the
; attribute buffer at #R24064 (used by the routine at
; #R36203)
@label=RAMPLEN
32989 DEFB 0 ; Length (used by the routine at #R36203)
; Border colour
;
; Initialised upon entry to a room and then used by the routine at #R35090, and
; also used by the routines at #R35591, #R36307, #R37310 and #R37841.
@label=BORDER
g32990 DEFB 0
; Unused
;
; These bytes are overwritten upon entry to a room by the routine at #R35090,
; but not used.
@label=XROOM223
u32991 DEFS 2
; Item graphic
;
; Initialised upon entry to a room by the routine at #R35090, and used by the
; routine at #R37841.
@label=ITEM
g32993 DEFS 8
; Room exits
;
; Initialised upon entry to a room by the routine at #R35090.
@label=LEFT
g33001 DEFB 0 ; Room to the left (used by the routine at #R38026)
@label=RIGHT
33002 DEFB 0 ; Room to the right (used by the routine at #R38046)
@label=ABOVE
33003 DEFB 0 ; Room above (used by the routines at #R37310 and #R38064)
@label=BELOW
33004 DEFB 0 ; Room below (used by the routine at #R38098)
; Unused
;
; These bytes are overwritten upon entry to a room by the routine at #R35090,
; but not used.
@label=XROOM237
u33005 DEFS 3
; Entity specifications
;
; Initialised upon entry to a room and then used by the routine at #R35090.
; .
; There are eight pairs of bytes here that hold the entity specifications for
; the current room. The first byte in each pair identifies one of the entity
; definitions at #R40960. The meaning of the second byte depends on the entity
; type: it determines the base sprite index and x-coordinate of a guardian, the
; y-coordinate of an arrow, or the x-coordinate of the top of a rope.
@label=ENTITIES
g33008 DEFS 2 ; Entity 1
33010 DEFS 2 ; Entity 2
33012 DEFS 2 ; Entity 3
33014 DEFS 2 ; Entity 4
33016 DEFS 2 ; Entity 5
33018 DEFS 2 ; Entity 6
33020 DEFS 2 ; Entity 7
33022 DEFS 2 ; Entity 8
; Entity buffers
;
; Initialised by the routine at #R35090, and used by the routines at #R37056
; and #R37310. There are eight buffers here, each one eight bytes long, used to
; hold the state of the entities (rope, arrows and guardians) in the current
; room.
; .
; For a horizontal guardian, the eight bytes are used as follows:
; .
; #TABLE(default,centre,:w)
; { =h Byte | =h Contents }
; { =r4 0 | Bit 7: direction (0=left, 1=right) }
; { Bits 5-6: animation frame index }
; { Bits 3-4: unused }
; { Bits 0-2: entity type (001) }
; { =r4 1 | Bits 5-7: #LINK(Glossary#animation_frame_index_mask)(animation
; frame index mask) }
; { Bit 4: unused }
; { Bit 3: BRIGHT value }
; { Bits 0-2: INK colour }
; { =r2 2 | Bits 5-7: base sprite index }
; { Bits 0-4: x-coordinate }
; { 3 | Pixel y-coordinate x2 (index into the table at #R33280) }
; { 4 | Unused }
; { 5 | Page containing the sprite graphic data (see #R43776) }
; { 6 | Minimum x-coordinate }
; { 7 | Maximum x-coordinate }
; TABLE#
; .
; For a vertical guardian, the eight bytes are used as follows:
; .
; #TABLE(default,centre,:w)
; { =h Byte | =h Contents }
; { =r3 0 | Bits 5-7: animation frame index }
; { Bits 3-4: animation frame update flags (see #R37247) }
; { Bits 0-2: entity type (010) }
; { =r4 1 | Bits 5-7: #LINK(Glossary#animation_frame_index_mask)(animation
; frame index mask) }
; { Bit 4: unused }
; { Bit 3: BRIGHT value }
; { Bits 0-2: INK colour }
; { =r2 2 | Bits 5-7: base sprite index }
; { Bits 0-4: x-coordinate }
; { 3 | Pixel y-coordinate x2 (index into the table at #R33280) }
; { 4 | Pixel y-coordinate increment }
; { 5 | Page containing the sprite graphic data (see #R43776) }
; { 6 | Minimum y-coordinate }
; { 7 | Maximum y-coordinate }
; TABLE#
; .
; For an arrow, the eight bytes are used as follows:
; .
; #TABLE(default,centre,:w)
; { =h Byte | =h Contents }
; { =r3 0 | Bit 7: direction (0=left, 1=right) }
; { Bits 3-6: unused }
; { Bits 0-2: entity type (100) }
; { 1 | Unused }
; { 2 | Pixel y-coordinate x2 (index into the table at #R33280) }
; { 3 | Unused }
; { 4 | x-coordinate }
; { 5 | Collision detection byte (#b0=off, #b255=on) }
; { 6 | Top/bottom pixel row (drawn either side of the shaft) }
; { 7 | Unused }
; TABLE#
; .
; The rope uses the second and fourth bytes of the following buffer in addition
; to its own; these ten bytes are used as follows:
; .
; #TABLE(default,centre,:w)
; { =h Byte | =h Contents }
; { =r3 0 | Bit 7: direction (0=left, 1=right) }
; { Bits 3-6: unused }
; { Bits 0-2: entity type (011) }
; { 1 | Animation frame index }
; { 2 | x-coordinate of the top of the rope }
; { 3 | x-coordinate of the segment of rope being drawn }
; { 4 | Length (#b32) }
; { 5 | Segment drawing byte }
; { 6 | Unused }
; { 7 | Animation frame at which the rope changes direction (#b54) }
; { 9 | Index of the segment of rope being drawn (#b0-#b32) }
; { =r2 11 | Bits 1-7: unused }
; { Bit 0: Willy is on the rope (set), or not (reset) }
; TABLE#
; .
; Note that if a rope were the eighth entity specified in a room, its buffer
; would use the first and third bytes in the otherwise unused area at #R33089.
@label=ENTITYBUF
g33024 DEFS 8 ; Entity 1
33032 DEFS 8 ; Entity 2
33040 DEFS 8 ; Entity 3
33048 DEFS 8 ; Entity 4
33056 DEFS 8 ; Entity 5
33064 DEFS 8 ; Entity 6
33072 DEFS 8 ; Entity 7
33080 DEFS 8 ; Entity 8
33088 DEFB 255 ; Terminator
; Unused
;
; This area is not used, but if a rope were the eighth entity specified in a
; room, its buffer would spill over from the eighth slot at #R33024 and use the
; first and third bytes here.
@label=EBOVERFLOW
s33089 DEFS 191
; Screen buffer address lookup table
;
; Used by the routines at #R35914, #R37310 and #R38455. The value of the Nth
; entry (0<=N<=127) in this lookup table is the screen buffer address for the
; point with pixel coordinates (x,y)=(0,N), with the origin (0,0) at the
; top-left corner.
@label=SBUFADDRS
w33280 DEFW 24576 ; y=0
33282 DEFW 24832 ; y=1
33284 DEFW 25088 ; y=2
33286 DEFW 25344 ; y=3
33288 DEFW 25600 ; y=4
33290 DEFW 25856 ; y=5
33292 DEFW 26112 ; y=6
33294 DEFW 26368 ; y=7
33296 DEFW 24608 ; y=8
33298 DEFW 24864 ; y=9
33300 DEFW 25120 ; y=10
33302 DEFW 25376 ; y=11
33304 DEFW 25632 ; y=12
33306 DEFW 25888 ; y=13
33308 DEFW 26144 ; y=14
33310 DEFW 26400 ; y=15
33312 DEFW 24640 ; y=16
33314 DEFW 24896 ; y=17
33316 DEFW 25152 ; y=18
33318 DEFW 25408 ; y=19
33320 DEFW 25664 ; y=20
33322 DEFW 25920 ; y=21
33324 DEFW 26176 ; y=22
33326 DEFW 26432 ; y=23
33328 DEFW 24672 ; y=24
33330 DEFW 24928 ; y=25
33332 DEFW 25184 ; y=26
33334 DEFW 25440 ; y=27
33336 DEFW 25696 ; y=28
33338 DEFW 25952 ; y=29
33340 DEFW 26208 ; y=30
33342 DEFW 26464 ; y=31
33344 DEFW 24704 ; y=32
33346 DEFW 24960 ; y=33
33348 DEFW 25216 ; y=34
33350 DEFW 25472 ; y=35
33352 DEFW 25728 ; y=36
33354 DEFW 25984 ; y=37
33356 DEFW 26240 ; y=38
33358 DEFW 26496 ; y=39
33360 DEFW 24736 ; y=40
33362 DEFW 24992 ; y=41
33364 DEFW 25248 ; y=42
33366 DEFW 25504 ; y=43
33368 DEFW 25760 ; y=44
33370 DEFW 26016 ; y=45
33372 DEFW 26272 ; y=46
33374 DEFW 26528 ; y=47
33376 DEFW 24768 ; y=48
33378 DEFW 25024 ; y=49
33380 DEFW 25280 ; y=50
33382 DEFW 25536 ; y=51
33384 DEFW 25792 ; y=52
33386 DEFW 26048 ; y=53
33388 DEFW 26304 ; y=54
33390 DEFW 26560 ; y=55
33392 DEFW 24800 ; y=56
33394 DEFW 25056 ; y=57
33396 DEFW 25312 ; y=58
33398 DEFW 25568 ; y=59
33400 DEFW 25824 ; y=60
33402 DEFW 26080 ; y=61
33404 DEFW 26336 ; y=62
33406 DEFW 26592 ; y=63
33408 DEFW 26624 ; y=64
33410 DEFW 26880 ; y=65
33412 DEFW 27136 ; y=66
33414 DEFW 27392 ; y=67
33416 DEFW 27648 ; y=68
33418 DEFW 27904 ; y=69
33420 DEFW 28160 ; y=70
33422 DEFW 28416 ; y=71
33424 DEFW 26656 ; y=72
33426 DEFW 26912 ; y=73
33428 DEFW 27168 ; y=74
33430 DEFW 27424 ; y=75
33432 DEFW 27680 ; y=76
33434 DEFW 27936 ; y=77
33436 DEFW 28192 ; y=78
33438 DEFW 28448 ; y=79
33440 DEFW 26688 ; y=80
33442 DEFW 26944 ; y=81
33444 DEFW 27200 ; y=82
33446 DEFW 27456 ; y=83
33448 DEFW 27712 ; y=84
33450 DEFW 27968 ; y=85
33452 DEFW 28224 ; y=86
33454 DEFW 28480 ; y=87
33456 DEFW 26720 ; y=88
33458 DEFW 26976 ; y=89
33460 DEFW 27232 ; y=90
33462 DEFW 27488 ; y=91
33464 DEFW 27744 ; y=92
33466 DEFW 28000 ; y=93
33468 DEFW 28256 ; y=94
33470 DEFW 28512 ; y=95
33472 DEFW 26752 ; y=96
33474 DEFW 27008 ; y=97
33476 DEFW 27264 ; y=98
33478 DEFW 27520 ; y=99
33480 DEFW 27776 ; y=100
33482 DEFW 28032 ; y=101
33484 DEFW 28288 ; y=102
33486 DEFW 28544 ; y=103
33488 DEFW 26784 ; y=104
33490 DEFW 27040 ; y=105
33492 DEFW 27296 ; y=106
33494 DEFW 27552 ; y=107
33496 DEFW 27808 ; y=108
33498 DEFW 28064 ; y=109
33500 DEFW 28320 ; y=110
33502 DEFW 28576 ; y=111
33504 DEFW 26816 ; y=112
33506 DEFW 27072 ; y=113
33508 DEFW 27328 ; y=114
33510 DEFW 27584 ; y=115
33512 DEFW 27840 ; y=116
33514 DEFW 28096 ; y=117
33516 DEFW 28352 ; y=118
33518 DEFW 28608 ; y=119
33520 DEFW 26848 ; y=120
33522 DEFW 27104 ; y=121
33524 DEFW 27360 ; y=122
33526 DEFW 27616 ; y=123
33528 DEFW 27872 ; y=124
33530 DEFW 28128 ; y=125
33532 DEFW 28384 ; y=126
33534 DEFW 28640 ; y=127
; Rope animation table
;
; Used by the routine at #R37310. The first half of this table controls the
; x-coordinates at which the segments of rope are drawn, and the second half
; controls the y-coordinates. For a given rope animation frame F
; (#b0<=F<=#b54), the 32 entries from F to F+31 inclusive (one for each of the
; 32 segments of rope below the topmost one) in each half of the table are
; used; thus the batch of entries used 'slides' up and down the table as F
; increases and decreases.
@label=ROPEANIM
b33536 DEFB 0,0,0,0,0,0,0,0 ; {These values determine how much to rotate the
33544 DEFB 0,0,0,0,0,0,0,0 ; rope drawing byte (which in turn determines the
33552 DEFB 0,0,0,0,0,0,0,0 ; x-coordinate at which each segment of rope is
33560 DEFB 0,0,0,0,0,0,0,0 ; drawn)
33568 DEFB 1,1,1,1,1,1,1,1 ;
33576 DEFB 1,1,1,1,2,2,2,2 ;
33584 DEFB 2,2,2,2,2,2,2,2 ;
33592 DEFB 2,2,2,2,2,2,2,2 ;
33600 DEFB 2,2,1,2,2,1,1,2 ;
33608 DEFB 1,1,2,2,3,2,3,2 ;
33616 DEFB 3,3,3,3,3,3 ; }
33622 DEFB 0,0,0,0,0,0,0,0 ; {Unused
33630 DEFB 0,0,0,0,0,0,0,0 ;
33638 DEFB 0,0,0,0,0,0,0,0 ;
33646 DEFB 0,0,0,0,0,0,0,0 ;
33654 DEFB 0,0,0,0,0,0,0,0 ;
33662 DEFB 0,0 ; }
33664 DEFB 6,6,6,6,6,6,6,6 ; {These values determine the y-coordinate of each
33672 DEFB 6,6,6,6,6,6,6,6 ; segment of rope relative to the one above it
33680 DEFB 6,6,6,6,6,6,6,6 ;
33688 DEFB 6,6,6,6,6,6,6,6 ;
33696 DEFB 6,6,6,6,6,6,6,6 ;
33704 DEFB 6,6,6,6,6,6,6,6 ;
33712 DEFB 4,6,6,4,6,4,6,4 ;
33720 DEFB 6,4,4,4,6,4,4,4 ;
33728 DEFB 4,4,4,4,4,4,4,4 ;
33736 DEFB 4,4,4,4,4,4,4,4 ;
33744 DEFB 4,4,4,4,4,4 ; }
33750 DEFB 0,0,0,0,0,0,0,0 ; {Unused
33758 DEFB 0,0,0,0,0,0,0,0 ;
33766 DEFB 0,0,0,0,0,0,0,0 ;
33774 DEFB 0,0,0,0,0,0,0,0 ;
33782 DEFB 0,0,0,0,0,0,0,0 ;
33790 DEFB 0,0 ; }
; The game has just loaded
;
; After the game has loaded, this is where it all starts.
@label=BEGIN
c33792 DI ; Disable interrupts
33793 LD HL,23551 ; {Place the address of the routine at #R34463 on the
@ssub=LD (HL),34463/256
33796 LD (HL),134 ; stack
33798 DEC HL ;
@ssub=LD (HL),34463%256
33799 LD (HL),159 ;
33801 LD SP,23550 ; }
33804 SUB A ; {Set #REGhl=#N34048 in a roundabout way
33805 LD L,A ;
33806 XOR 10 ;
33808 LD B,A ;
33809 INC B ;
33810 LD H,B ;
33811 RRC H ; }
@ignoreua
*33813 LD C,(HL) ; {Read through addresses #N34048-#N(65535), without
33814 LD A,L ; changing their contents; perhaps this code was once used
33815 XOR C ; to descramble the contents of pages #b133-#b255, but now
33816 XOR H ; all it does is introduce a pause of about 0.47s before
33817 LD (HL),C ; displaying the code entry screen
33818 INC HL ;
33819 BIT 7,H ;
33821 JR NZ,33813 ; }
33823 RET ; Make an indirect jump to #R34463
; Current room number
;
; Initialised to #b33 (#R57600(The Bathroom)) by the routine at #R34762,
; checked by the routines at #R35090, #R37310, #R37841, #R38196, #R38276,
; #R38298 and #R38455, and updated by the routines at #R35591, #R38026,
; #R38046, #R38064 and #R38098.
@label=ROOM
g33824 DEFB 0
; Left-right movement table
;
; Used by the routine at #R36564. The entries in this table are used to map the
; existing value (V) of Willy's direction and movement flags at #R34256 to a
; new value (V'), depending on the direction Willy is facing and how he is
; moving or being moved (by 'left' and 'right' keypresses and joystick input,
; or by a conveyor, or by an urge to visit the toilet).
; .
; One of the first four entries is used when Willy is not moving.
@label=LRMOVEMENT
b33825 DEFB 0 ; V=0 (facing right, no movement) + no movement: V'=0 (no
; change)
33826 DEFB 1 ; V=1 (facing left, no movement) + no movement: V'=1 (no
; change)
33827 DEFB 0 ; V=2 (facing right, moving) + no movement: V'=0 (facing
; right, no movement) (i.e. stop)
33828 DEFB 1 ; V=3 (facing left, moving) + no movement: V'=1 (facing
; left, no movement) (i.e. stop)
; One of the next four entries is used when Willy is moving left.
33829 DEFB 1 ; V=0 (facing right, no movement) + move left: V'=1
; (facing left, no movement) (i.e. turn around)
33830 DEFB 3 ; V=1 (facing left, no movement) + move left: V'=3 (facing
; left, moving)
33831 DEFB 1 ; V=2 (facing right, moving) + move left: V'=1 (facing
; left, no movement) (i.e. turn around)
33832 DEFB 3 ; V=3 (facing left, moving) + move left: V'=3 (no change)
; One of the next four entries is used when Willy is moving right.
33833 DEFB 2 ; V=0 (facing right, no movement) + move right: V'=2
; (facing right, moving)
33834 DEFB 0 ; V=1 (facing left, no movement) + move right: V'=0
; (facing right, no movement) (i.e. turn around)
33835 DEFB 2 ; V=2 (facing right, moving) + move right: V'=2 (no
; change)
33836 DEFB 0 ; V=3 (facing left, moving) + move right: V'=0 (facing
; right, no movement) (i.e. turn around)
; One of the final four entries is used when Willy is being pulled both left
; and right; each entry leaves the flags at #R34256 unchanged (so Willy carries
; on moving in the direction he's already moving, or remains stationary).
33837 DEFB 0 ; V=V'=0 (facing right, no movement)
33838 DEFB 1 ; V=V'=1 (facing left, no movement)
33839 DEFB 2 ; V=V'=2 (facing right, moving)
33840 DEFB 3 ; V=V'=3 (facing left, moving)
; Triangle UDGs
;
; Used by the routine at #R34762.
; .
; #UDGTABLE
; { #UDG33841,56(triangle0) | #UDG33849,56(triangle1) | #UDG33857,56(triangle2)
; | #UDG33865,56(triangle3) }
; TABLE#
@label=TRIANGLE0
b33841 DEFB 192,240,252,255,255,255,255,255
@label=TRIANGLE1
33849 DEFB 0,0,0,0,192,240,252,255
@label=TRIANGLE2
33857 DEFB 255,255,255,255,252,240,192,0
@label=TRIANGLE3
33865 DEFB 252,240,192,0,0,0,0,0
; 'AIR'
;
; This message is not used.
t33873 DEFM "AIR"
; '+++++ Press ENTER to Start +++++...'
;
; Used by the routine at #R34762.
@label=MSG_INTRO
t33876 DEFM "+++++ Press ENTER to Start +++++"
33908 DEFM " JET-SET WILLY by Matthew Smith "
33942 DEFM 127," 1984 SOFTWARE PROJECTS Ltd . . . . ."
33980 DEFM "Guide Willy to collect all the items around "
34024 DEFM "the house before Midnight "
34050 DEFM "so Maria will let you get to your bed. . . . . . ."
34100 DEFM "+++++ Press ENTER to Start +++++"
; 'Items collected 000 Time 00:00 m'
;
; Used by the routine at #R35090.
@label=MSG_STATUS
t34132 DEFM "Items collected 000 Time 00:00 m"
; 'Game'
;
; Used by the routine at #R35914.
@label=MSG_GAME
t34164 DEFM "Game"
; 'Over'
;
; Used by the routine at #R35914.
@label=MSG_OVER
t34168 DEFM "Over"
; Number of items collected
;
; Initialised by the routine at #R34762, printed by the routine at #R35245, and
; updated by the routine at #R37841.
@label=MSG_ITEMS
g34172 DEFM "000"
; Current time
;
; Initialised by the routine at #R35068, and printed and updated by the routine
; at #R35245.
@label=MSG_CURTIME
g34175 DEFM " 7:00a"
; ' 7:00a'
;
; Copied by the routine at #R35068 to #R34175.
@label=MSG_7AM
t34181 DEFM " 7:00a"
; 'Enter Code at grid location#SPACE5'
;
; Used by the routine at #R34463.
@label=MSG_CODE1
t34187 DEFM "Enter Code at grid location "
; 'Sorry, try code at location#SPACE5'
;
; Used by the routine at #R34463.
@label=MSG_CODE2
t34219 DEFM "Sorry, try code at location "
; Minute counter
;
; Initialised by the routine at #R34762; incremented on each pass through the
; main loop by the routine at #R35245 (which moves the game clock forward by a
; minute when the counter reaches 0); reset to zero by the routine at #R38276
; when Willy sticks his head down the toilet; and used by the routines at
; #R37841 (to cycle the colours of the items in the room), #R38196 (to
; determine Maria's animation frame in #R58112(Master Bedroom)) and #R38298 (to
; determine the animation frame for the toilet in #R57600(The Bathroom)).
@label=TICKS
g34251 DEFB 0
; Lives remaining
;
; Initialised to 7 by the routine at #R34762, decremented by the routine at
; #R35841, and used by the routines at #R35211 (when drawing the remaining
; lives) and #R35591 (to adjust the speed and pitch of the in-game music).
@label=LIVES
g34252 DEFB 0
; Screen flash counter
;
@ignoreua
; Initialised to zero by the routine at #R34762, but never used; the code at
; #R35339 makes the screen flash in Manic Miner fashion if this address holds a
; non-zero value.
@label=FLASH
g34253 DEFB 0
; Kempston joystick indicator
;
; Initialised by the routine at #R34762, and checked by the routines at #R36564
; and #R38601. Holds 1 if a joystick is present, 0 otherwise.
@label=JOYSTICK
g34254 DEFB 0
; Willy's y-coordinate
;
; Initialised to 208 by the routine at #R34762, and used by the routines at
; #R35245, #R35591, #R36307, #R36564, #R36796, #R37310, #R38064, #R38098,
; #R38196, #R38344 and #R38455. Holds the LSB of the address of the entry in
; the screen buffer address lookup table at #R33280 that corresponds to Willy's
; pixel y-coordinate; in practice, this LSB is twice Willy's actual pixel
; y-coordinate. Note that when Willy is standing on a ramp, this holds his
; y-coordinate rounded down to the nearest multiple of 16 (8x2).
@label=WILLY_Y
g34255 DEFB 0
; Willy's direction and movement flags
;
; #TABLE(default,centre,:w,:w)
; { =h Bit(s) | =h Meaning | =h Used by }
; { 0 | Direction Willy is facing (reset=right, set=left) | #R36564, #R36796,
; #R38455 }
; { 1 | Willy's left/right movement flag (set=moving) | #R36307, #R36564,
; #R36796, #R37310 }
; { 2-7 | Unused (always reset) | }
; TABLE#
@label=DMFLAGS
g34256 DEFB 0
; Airborne status indicator
;
@ignoreua
; Initialised by the routine at #R34762, checked by the routines at #R35591,
; #R36796 and #R38344, updated by the routines at #R37046, #R37310 and #R38064,
; and checked and updated by the routines at #R36307, #R36564 and #R38098.
; Possible values are:
; .
; #TABLE(default,centre,:w)
; { =h Value | =h Meaning }
; { #b0 | Willy is neither falling nor jumping }
; { #b1 | Willy is jumping }
; { #b2-#b11 | Willy is falling, and can land safely }
; { #b12-#b15 | Willy is falling, and has fallen too far to land safely }
; { #b255 | Willy has collided with a nasty, an arrow, a guardian, or Maria
; (see #R37046) }
; TABLE#
@label=AIRBORNE
g34257 DEFB 0
; Willy's animation frame
;
; Used by the routines at #R38344 and #R38455, and updated by the routines at
; #R35245, #R36796 and #R37310. Possible values are 0, 1, 2 and 3.
@label=FRAME
g34258 DEFB 0
; Address of Willy's location in the attribute buffer at #N23552
;
; Initialised by the routine at #R34762, and used by the routines at #R36307,
; #R36796, #R37310, #R38026, #R38046, #R38064, #R38098, #R38196, #R38276,
; #R38344 and #R38455.
@label=LOCATION
g34259 DEFW 0
; Jumping animation counter
;
; Used by the routines at #R36307 and #R36564.
@label=JUMPING
g34261 DEFB 0
; Rope status indicator
;
; Initialised by the routine at #R35090, checked by the routines at #R36307 and
; #R36796, and checked and updated by the routines at #R36564 and #R37310.
; Possible values are:
; .
; #TABLE(default,centre,:w)
; { =h Value | =h Meaning }
; { #b0 | Willy is not on the rope }
; { #b3-#b32 | Willy is on the rope, with the centre of his sprite anchored
; at this segment }
; { #b240-#b255 | Willy has just jumped or fallen off the rope }
; TABLE#
@label=ROPE
g34262 DEFB 0
; Willy's state on entry to the room
;
@ignoreua
; Initialised by the routine at #R35090, and copied back into #GBUF34255,34261
; by the routine at #R35841.
@label=INITSTATE
g34263 DEFB 0 ; Willy's y-coordinate (copied from #R34255)
34264 DEFB 0 ; Willy's direction and movement flags (copied from
; #R34256)
34265 DEFB 0 ; Airborne status indicator (copied from #R34257)
34266 DEFB 0 ; Willy's animation frame (copied from #R34258)
34267 DEFW 0 ; Address of Willy's location in the attribute buffer at
; #R23552 (copied from #R34259)
34269 DEFB 0 ; Jumping animation counter (copied from #R34261)
; 256 minus the number of items remaining
;
; Initialised by the routine at #R34762, and updated by the routine at #R37841
; when an item is collected.
@label=ITEMS
g34270 DEFB 0
; Game mode indicator
;
; Initialised by the routine at #R34762, checked by the routines at #R35245,
; #R36564 and #R38298, and updated by the routines at #R37841, #R38196 and
; #R38276.
; .
; #TABLE(default,centre)
; { =h Value | =h Meaning }
; { 0 | Normal }
; { 1 | All items collected }
; { 2 | Willy is running to the toilet }
; { 3 | Willy's head is down the toilet }
; TABLE#
@label=MODE
g34271 DEFB 0
; Inactivity timer
;
; Initialised by the routine at #R34762, and updated by the routines at
; #R35245, #R35591 and #R36564.
@label=INACTIVE
g34272 DEFB 0
; In-game music note index
;
; Initialised by the routine at #R34762, used by the routine at #R35211, and
; used and updated by the routine at #R35591.
@label=NOTEINDEX
g34273 DEFB 0
; Music flags
;
; The keypress flag in bit 0 is initialised by the routine at #R34762; bits 0
; and 1 are checked and updated by the routine at #R35591.
; .
; #TABLE(default,centre,:w)
; { =h Bit(s) | =h Meaning }
; { 0 | Keypress flag (set=H-ENTER being pressed, reset=no key pressed) }
; { 1 | In-game music flag (set=music off, reset=music on) }
; { 2-7 | Unused }
; TABLE#
@label=MUSICFLAGS
g34274 DEFB 0
; WRITETYPER key counter
;
; Checked by the routine at #R35245, and updated by the routine at #R35591.
@label=TELEPORT
g34275 DEFB 0
; Temporary variable
;
; Used by the routines at #R34499 and #R34620 to hold the entry code, by the
; routine at #R34762 to hold the index into the message scrolled across the
; screen after the theme tune has finished playing, and by the routine at
; #R35914 to hold the distance of the foot from the top of the screen as it
; descends onto Willy.
@label=TEMPVAR
g34276 DEFB 0
; WRITETYPER
;
; Used by the routine at #R35591. In each pair of bytes here, bits 0-4 of the
; first byte correspond to keys Q-W-E-R-T, and bits 0-4 of the second byte
; correspond to keys P-O-I-U-Y; among those bits, a zero indicates a key being
; pressed.
b34277 DEFB %00011111,%00011111 ; (no keys pressed)
@label=WRITETYPER
34279 DEFB %00011101,%00011111 ; W
34281 DEFB %00010111,%00011111 ; R
34283 DEFB %00011111,%00011011 ; I
34285 DEFB %00001111,%00011111 ; T
34287 DEFB %00011011,%00011111 ; E
34289 DEFB %00001111,%00011111 ; T
34291 DEFB %00011111,%00001111 ; Y
34293 DEFB %00011111,%00011110 ; P
34295 DEFB %00011011,%00011111 ; E
34297 DEFB %00010111,%00011111 ; R
; Title screen tune data (Moonlight Sonata)
;
; Used by the routine at #R38562.
@label=THEMETUNE
b34299 DEFB 81,60,51,81,60,51,81,60,51,81,60,51,81,60,51,81
34315 DEFB 60,51,81,60,51,81,60,51,76,60,51,76,60,51,76,57
34331 DEFB 45,76,57,45,81,64,45,81,60,51,81,60,54,91,64,54
34347 DEFB 102,81,60,81,60,51,81,60,51,40,60,40,40,54,45,81
34363 DEFB 54,45,81,54,45,40,54,40,40,60,51,81,60,51,38,60
34379 DEFB 45,76,60,45,40,64,51,81,64,51,45,64,54,32,64,54
34395 DEFB 61,121,61,255
; In-game tune data (If I Were a Rich Man)
;
; Used by the routine at #R35591.
@label=GAMETUNE
b34399 DEFB 86,96,86,96,102,102,128,128,128,128,102,96,86,96,86,96
34415 DEFB 102,96,86,76,72,76,72,76,86,86,86,86,86,86,86,86
34431 DEFB 64,64,64,64,68,68,76,76,86,96,102,96,86,86,102,102
34447 DEFB 81,86,96,86,81,81,96,96,64,64,64,64,64,64,64,64
; Give two chances to enter a correct code
;
; Used by the routine at #R33792.
@refs=33792
@label=ENTERCODES
c34463 LD HL,16384 ; {Clear the display file and attribute file
34466 LD DE,16385 ;
34469 LD BC,6911 ;
34472 LD (HL),0 ;
34474 LDIR ; }
34476 LD IX,34187 ; Point #REGix at the message at #R34187 ("Enter Code at
; grid location#SPACE(5)")
34480 CALL 34499 ; Display the code entry screen and collect a four-digit
; code from the user
34483 JP Z,34762 ; Start the game if the code is correct
34486 LD IX,34219 ; Point #REGix at the message at #R34219 ("Sorry, try code
; at location#SPACE(5)")
34490 CALL 34499 ; Display the code entry screen and collect another
; four-digit code from the user
34493 JP Z,34762 ; Start the game if the code is correct
34496 JP 0 ; Otherwise reset the machine
; Display the code entry screen
;
; Used by the routine at #R34463. Displays the code entry screen and waits for
; a code to be entered. Returns with the zero flag set if the code entered is
; correct.
;
; IX Address of the message to print (#R34187 or #R34219)
@label=CODESCREEN
c34499 LD DE,18432 ; {Print the message pointed to by #REGix at (8,0)
34502 LD C,32 ;
34504 CALL 38528 ; }
34507 LD HL,18498 ; {Print the graphic for the '1' key at (10,2)
34510 LD DE,39680 ;
34513 LD C,0 ;
34515 CALL 37974 ; }
34518 LD HL,18501 ; {Print the graphic for the '2' key at (10,5)
34521 CALL 37974 ; }
34524 LD HL,18504 ; {Print the graphic for the '3' key at (10,8)
34527 CALL 37974 ; }
34530 LD HL,18507 ; {Print the graphic for the '4' key at (10,11)
34533 CALL 37974 ; }
34536 LD HL,39808 ; {Copy the 128 attribute bytes from #R39808 to the screen
34539 LD DE,22784 ; (lines 8, 9, 10 and 11)
34542 LD BC,128 ;
34545 LDIR ; }
34547 LD A,(23672) ; Collect the LSB of the system variable FRAMES
34550 ADD A,37 ; {Add #b37 to this value and replace it; this ensures
34552 LD (23672),A ; that the value collected on the second pass through this
; routine is different from the value collected on the
; first pass}
@bfix=CP 180 ; Is the value between #b0 and #b179?
34555 CP 179 ; Is the value between #b0 and #b178?
34557 JR C,34561 ; Jump if so
@bfix=/ ; Otherwise subtract #b180
34559 SUB 180 ; Otherwise subtract #b180; note that if the original
; value of the LSB of the system variable FRAMES was
; #b142, this leaves #REGa holding #b255, which is a
; #BUG(invalidGridLocation)(bug)
@bfix=/ ; Now #REGl holds some number between #b0 and #b179
*34561 LD L,A ; Now #REGl holds either #b255 or some number between #b0
; and #b178
@ssub=LD H,40448/256
@ignoreua
34562 LD H,158 ; Point #REGhl at one of the entries in the table at
; #R40448 #IF({fix}<2)((or at #N40703 if #REGl=#b255))
34564 LD A,(HL) ; Pick up the table entry
34565 ADD A,L ; Add #REGl to obtain the actual code
34566 LD (34276),A ; Store the code at #R34276
34569 LD C,L ; Copy the code index to #REGc; this will be used to
; compute the grid location
34570 LD E,47 ; {Calculate the ASCII code of the grid location number
*34572 INC E ; (0-9) in #REGe
34573 LD A,C ;
34574 CP 18 ;
34576 JR C,34583 ;
34578 SUB 18 ;
34580 LD C,A ;
34581 JR 34572 ; }
*34583 LD A,E ; {Print the grid location number at (8,30)
34584 LD DE,18462 ;
34587 CALL 38545 ; }
34590 LD A,C ; {Calculate the ASCII code of the grid location letter
34591 ADD A,65 ; (A-R) in #REGa}
34593 LD DE,18461 ; {Print the grid location letter at (8,29)
34596 CALL 38545 ; }
; Here we enter a loop that prints a 2x2 coloured block at (10,16), (10,19),
; (10,22) or (10,25) whenever '1', '2', '3' or '4' is pressed, or returns to
; the calling routine at #R34463 if ENTER is pressed.
*34599 LD IX,22864 ; Point #REGix at the attribute file location of the first
; coloured block at (10,16)
*34603 CALL 34620 ; Print a coloured block when '1', '2', '3' or '4' is
; pressed, or return to #R34463 if ENTER is pressed
34606 INC IX ; {Move #REGix along to the location of the next coloured
34608 INC IX ; block
34610 INC IX ; }
34612 LD A,IXl ; {Have we just printed the fourth coloured block at
34614 CP 92 ; (10,25)?}
34616 JR NZ,34603 ; If not, jump back to print the next one
34618 JR 34599 ; Otherwise rewind #REGix to the location of the first
; coloured block
; Read the keyboard during code entry
;
; Used by the routine at #R34499. Waits for '1', '2', '3', '4' or ENTER to be
; pressed and either prints a coloured block or validates the entered code.
; Returns to the routine at #R34463 if ENTER is being pressed, with the zero
; flag reset if the entered code is correct.
;
; IX Attribute file address of the flashing 2x2 block
@label=READCODE
@keep
c34620 LD BC,63486 ; {Read keys 1-2-3-4-5