; Game loader - load game code and set execution starting address
;
; First short block of data on the tape.
;
; Start by copying the routine below, starting at 23834, to near the top of RAM
; (L65000)
L23820:
  LD HL,23834
  LD DE,L65000
  LD BC,60                ; 60 bytes of code to copy
  LDIR                    ; Copy the code
  JP L65000               ; ...now jump there and execute the code
; Start of code that is copied to L65000
  LD SP,65530             ; Put the stack pointer (nearly) at the top of RAM
  LD IX,L25001            ; IX = address pointer at start of data block to LOAD
  LD DE,39000             ; Data block length (code up to RAM address 64000)
  LD A,255                ; Indicates a data block to load (rather than header)
  SCF                     ; Sets the carry flag, which tells the ROM routine to
                          ; perform a LOAD
; The next 4 instructions are part of the ROM loading routine just before 1377,
; executed here just before the jump there at 23854 (as it's loading data, not
; a header block).
  INC D
  EX AF,AF'
  DEC D
  DI
  LD HL,65023             ; This is the address that the code in the following
                          ; instructions (starting from 23857) will be at after
                          ; the copy at the start of this routine.
  JP 1377                 ; Launch the ROM loading routine
; The following code is copied to 65023 and is executed from there once the
; game has loaded (see this address for disassembly).
  LD HL,L25001
  LD DE,39000
L23820_0:
  LD A,(HL)
  XOR 102
  RRCA
  XOR L
  LD (HL),A
  INC HL
  DEC DE
  LD A,D
  OR E
  JR NZ,L23820_0
  LD A,2
  LD (23659),A
  EI
  JP L62283

; Unused
L23884:
  DEFB 32,32,32,32,32,32,32,32
  DEFB 32,32,32,32,32,32,32,32
  DEFB 32,32,32,32,32,32,32,32
  DEFB 32,32,32,32,32,32,32,32
  DEFB 225,0,0,72,93,0,0,0
  DEFB 92,93,0,0,0,1,0,0
  DEFB 232,3,2,120,0,0,210,0
  DEFB 0,128,239,34,34,13,128,0
  DEFB 0,248,92,0,0,0,0,0
  DEFB 0,0,6,126,248,207,0,0
  DEFB 3,32,32,32,32,32,32,32
  DEFB 32,32,32,26,0,0,250,128
  DEFB 128,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0

; Room data - standard rooms
;
; Data for each room holding the room's size, background scenery and doors/door
; connector links. Used in the room initialization routine at L49498.
;
; * First byte = Room size - see Trivia: Setting the scene(ry)
; * Following bytes = Room elements (e.g. doors, decorative brickwork). Each
;   element is stored in two bits
; * Penultimate bytes (preceding final byte) = Connecting door data set number
;   - in the table at L26512
; * Final byte = 255 (end of this room data set)
L25001:
  DEFB 5,0,64,1,255       ; 1 - Room 1 - starting room
  DEFB 9,66,64,64,1,2,3,255 ; 2
  DEFB 10,18,132,64,4,5,2,255 ; 3
  DEFB 6,17,0,5,10,255    ; 4
  DEFB 9,66,64,64,3,6,7,255 ; 5
  DEFB 8,66,36,6,8,255    ; 6
  DEFB 7,1,4,8,9,255      ; 7
  DEFB 6,64,0,9,255       ; 8
  DEFB 8,16,65,12,11,18,255 ; 9
  DEFB 6,4,16,12,13,255   ; 10
  DEFB 6,74,16,13,14,255  ; 11
  DEFB 6,68,64,14,15,20,255 ; 12
  DEFB 8,18,17,15,17,16,255 ; 13
  DEFB 6,64,0,17,255      ; 14
  DEFB 6,65,0,16,19,255   ; 15
  DEFB 8,64,64,19,18,255  ; 16
  DEFB 6,17,16,21,23,22,255 ; 17
  DEFB 10,65,20,0,22,24,25,26 ; 18
  DEFB 255                    ;
  DEFB 6,64,0,24,255      ; 19
  DEFB 6,64,0,25,255      ; 20
  DEFB 6,16,0,26,255      ; 21
  DEFB 10,68,34,16,29,27,23,255 ; 22
  DEFB 8,0,65,30,27,255   ; 23
  DEFB 6,17,0,30,28,255   ; 24
  DEFB 6,64,16,31,32,255  ; 25
  DEFB 6,68,64,32,33,34,255 ; 26
  DEFB 6,16,0,33,255      ; 27
  DEFB 6,16,16,34,35,255  ; 28
  DEFB 9,66,16,0,36,35,255 ; 29
  DEFB 8,68,69,37,38,39,254,40 ; 30
  DEFB 255                     ;
  DEFB 8,82,1,43,42,44,255 ; 31
  DEFB 10,64,64,16,44,41,45,255 ; 32
  DEFB 11,64,160,20,45,43,46,255 ; 33
  DEFB 9,17,16,64,48,50,51,52 ; 34
  DEFB 255                    ;
  DEFB 6,16,64,51,53,255  ; 35
  DEFB 6,17,16,53,54,55,255 ; 36
  DEFB 8,65,17,55,56,57,58,255 ; 37
  DEFB 6,16,0,57,255      ; 38
  DEFB 6,16,0,56,255      ; 39
  DEFB 6,16,0,54,255      ; 40
  DEFB 7,1,0,50,255       ; 41
  DEFB 16,8,18,16,64,64,61,60 ; 42
  DEFB 255                    ;
  DEFB 6,1,16,59,60,255   ; 43
  DEFB 8,64,65,64,66,65,255 ; 44
  DEFB 6,16,16,62,63,255  ; 45
  DEFB 16,0,4,1,0,63,65,255 ; 46
  DEFB 6,64,64,61,62,255  ; 47
  DEFB 11,1,16,16,73,72,68,255 ; 48
  DEFB 9,65,20,0,67,68,69,70 ; 49
  DEFB 255                   ;
  DEFB 11,18,40,16,70,74,255 ; 50
  DEFB 9,16,65,0,74,76,77,255 ; 51
  DEFB 7,68,0,75,76,255   ; 52
  DEFB 6,64,16,69,71,255  ; 53
  DEFB 9,65,16,0,71,72,73,255 ; 54
  DEFB 6,64,0,105,255     ; 55
  DEFB 15,68,16,160,4,79,80,105 ; 56
  DEFB 88,255                   ;
  DEFB 8,68,64,88,89,95,255 ; 57
  DEFB 6,64,16,81,80,255  ; 58
  DEFB 8,81,1,82,83,84,81,255 ; 59
  DEFB 8,74,164,85,82,255 ; 60
  DEFB 7,0,4,85,255       ; 61
  DEFB 8,16,161,86,83,255 ; 62
  DEFB 7,0,16,86,255      ; 63
  DEFB 7,18,4,95,96,255   ; 64
  DEFB 6,64,64,96,97,255  ; 65
  DEFB 8,0,17,97,98,255   ; 66
  DEFB 10,68,4,0,100,99,98,255 ; 67
  DEFB 8,24,128,99,255    ; 68
  DEFB 6,2,16,100,255     ; 69
  DEFB 6,16,64,89,90,255  ; 70
  DEFB 7,16,64,90,91,255  ; 71
  DEFB 6,64,64,84,87,255  ; 72
  DEFB 11,4,33,0,94,92,255 ; 73
  DEFB 6,68,16,91,92,93,255 ; 74
  DEFB 7,64,0,93,255      ; 75
  DEFB 6,64,0,94,255      ; 76
  DEFB 11,64,72,0,87,101,255 ; 77
  DEFB 8,66,65,101,102,103,255 ; 78
  DEFB 7,1,0,103,255      ; 79
  DEFB 8,26,16,104,102,255 ; 80
  DEFB 8,8,16,104,255     ; 81
  DEFB 16,2,8,138,1,47,255 ; 82
  DEFB 8,1,33,112,0,255   ; 83
  DEFB 10,65,36,16,112,113,114,115 ; 84
  DEFB 255                         ;
  DEFB 8,66,64,116,115,255 ; 85
  DEFB 8,1,161,116,117,255 ; 86
  DEFB 6,64,64,117,118,255 ; 87
  DEFB 6,16,16,118,119,255 ; 88
  DEFB 6,65,0,119,120,255 ; 89
  DEFB 8,65,129,120,121,0,255 ; 90
  DEFB 8,2,36,121,255     ; 91
  DEFB 6,64,64,106,107,255 ; 92
  DEFB 10,18,36,16,107,108,109,255 ; 93
  DEFB 7,18,16,109,110,255 ; 94
  DEFB 7,74,4,110,111,255 ; 95
  DEFB 9,2,136,64,122,255 ; 96
  DEFB 8,66,16,122,123,255 ; 97
  DEFB 9,64,68,0,126,125,123,255 ; 98
  DEFB 8,64,4,124,125,255 ; 99
  DEFB 6,16,16,127,126,255 ; 100
  DEFB 6,1,64,128,127,255 ; 101
  DEFB 8,66,132,128,129,255 ; 102
  DEFB 6,16,16,129,130,255 ; 103
  DEFB 8,66,0,163,255     ; 104
  DEFB 6,64,16,136,137,255 ; 105
  DEFB 8,1,17,135,134,136,255 ; 106
  DEFB 7,66,4,134,133,255 ; 107
  DEFB 7,64,128,133,255   ; 108
  DEFB 10,66,132,64,135,131,132,255 ; 109
  DEFB 6,16,0,132,255     ; 110
  DEFB 8,66,5,138,140,139,255 ; 111
  DEFB 7,64,4,140,141,255 ; 112
  DEFB 8,24,129,139,166,255 ; 113
  DEFB 6,64,16,166,142,255 ; 114
  DEFB 6,64,0,156,255     ; 115
  DEFB 7,65,4,149,148,156,255 ; 116
  DEFB 8,1,17,149,150,151,255 ; 117
  DEFB 6,64,64,151,152,255 ; 118
  DEFB 8,65,4,153,152,154,255 ; 119
  DEFB 6,16,0,154,255     ; 120
  DEFB 8,66,68,157,155,150,255 ; 121
  DEFB 7,1,0,155,255      ; 122
  DEFB 6,16,16,146,147,255 ; 123
  DEFB 6,16,0,144,255     ; 124
  DEFB 7,64,68,143,144,145,255 ; 125
  DEFB 7,66,16,145,146,255 ; 126
  DEFB 8,1,17,160,159,158,255 ; 127
  DEFB 8,2,132,165,255    ; 128
  DEFB 6,16,16,165,164,255 ; 129
  DEFB 7,64,16,164,162,255 ; 130
  DEFB 7,16,4,162,161,255 ; 131
  DEFB 6,64,64,161,160,255 ; 132
  DEFB 9,16,128,64,159,163,255 ; 133
  DEFB 6,17,0,174,175,255 ; 134
  DEFB 7,18,16,173,174,255 ; 135
  DEFB 6,1,16,173,172,255 ; 136
  DEFB 7,16,132,172,169,255 ; 137
  DEFB 6,80,64,170,169,168,255 ; 138
  DEFB 7,64,16,171,170,255 ; 139
  DEFB 6,0,16,192,255     ; 140
  DEFB 7,65,0,192,191,255 ; 141
  DEFB 9,1,33,0,190,188,255 ; 142
  DEFB 8,68,16,189,190,191,255 ; 143
  DEFB 12,2,40,64,194,255 ; 144
  DEFB 6,16,64,194,193,255 ; 145
  DEFB 8,68,17,178,179,177,176,255 ; 146
  DEFB 7,66,4,177,181,255 ; 147
  DEFB 7,64,20,181,183,182,255 ; 148
  DEFB 6,16,16,182,184,255 ; 149
  DEFB 6,64,0,184,255     ; 150
  DEFB 7,66,4,183,185,255 ; 151
  DEFB 6,64,0,185,255     ; 152
  DEFB 7,16,16,179,180,255 ; 153
  DEFB 6,16,0,180,255     ; 154
  DEFB 9,66,164,0,186,178,255 ; 155
  DEFB 7,1,4,186,187,255  ; 156
  DEFB 9,66,32,0,187,255  ; 157
  DEFB 9,0,65,0,195,196,255 ; 158
  DEFB 7,16,4,196,197,255 ; 159
  DEFB 7,17,0,198,197,255 ; 160
  DEFB 7,68,4,201,198,200,255 ; 161
  DEFB 8,66,129,202,201,255 ; 162
  DEFB 7,64,4,203,202,255 ; 163
  DEFB 6,68,0,200,199,255 ; 164
  DEFB 7,18,0,199,255     ; 165
  DEFB 8,1,17,203,207,206,255 ; 166
  DEFB 7,66,0,207,255     ; 167
  DEFB 8,4,65,205,206,208,255 ; 168
  DEFB 8,74,33,204,205,255 ; 169
  DEFB 7,1,0,204,255      ; 170
  DEFB 7,64,16,208,209,255 ; 171
  DEFB 7,16,16,209,211,255 ; 172
  DEFB 9,4,16,64,213,211,210,255 ; 173
  DEFB 7,18,4,212,213,255 ; 174
  DEFB 6,0,64,212,255     ; 175
  DEFB 8,1,17,220,219,216,255 ; 176
  DEFB 7,65,4,216,218,215,255 ; 177
  DEFB 8,64,65,215,217,214,255 ; 178
  DEFB 7,1,4,217,221,255  ; 179
  DEFB 8,64,64,221,218,255 ; 180
  DEFB 10,64,16,0,223,222,255 ; 181
  DEFB 16,16,68,68,65,225,230,229 ; 182
  DEFB 228,227,226,224,255        ;
  DEFB 7,16,0,230,255     ; 183
  DEFB 7,16,0,229,255     ; 184
  DEFB 7,16,0,228,255     ; 185
  DEFB 7,16,0,227,255     ; 186
  DEFB 7,16,0,226,255     ; 187
  DEFB 7,2,4,232,255      ; 188
  DEFB 12,65,16,65,232,235,234,233 ; 189
  DEFB 231,255                     ;
  DEFB 8,66,32,231,255    ; 190
  DEFB 6,16,16,235,240,255 ; 191
  DEFB 6,64,16,240,239,255 ; 192
  DEFB 8,18,129,234,238,255 ; 193
  DEFB 6,64,16,233,236,255 ; 194
  DEFB 6,64,64,236,237,255 ; 195
  DEFB 6,0,16,241,255     ; 196
  DEFB 6,64,64,241,242,255 ; 197
  DEFB 6,16,16,242,243,255 ; 198
  DEFB 6,65,16,243,247,244,255 ; 199
  DEFB 6,64,16,244,245,255 ; 200
  DEFB 6,64,64,245,246,255 ; 201
  DEFB 6,65,0,247,248,255 ; 202
  DEFB 6,68,64,250,249,248,255 ; 203
  DEFB 6,16,16,251,250,255 ; 204
  DEFB 6,0,64,251,255     ; 205
  DEFB 6,65,16,252,249,253,255 ; 206
  DEFB 6,64,16,253,167,255 ; 207
  DEFB 6,64,0,167,255     ; 208
  DEFB 6,10,16,252,255    ; 209
  DEFB 10,26,161,0,47,49,255 ; 210
  DEFB 15,4,34,136,16,49,78,255 ; 211
  DEFB 13,18,40,160,0,78,255 ; 212
; The following are placeholders and not used. See Trivia: Unused rooms
  DEFB 5,0,0,255          ; 213
  DEFB 5,0,0,255          ; 214
  DEFB 5,0,0,255          ; 215
  DEFB 5,0,0,255          ; 216
  DEFB 5,0,0,255          ; 217
  DEFB 5,0,0,255          ; 218
  DEFB 5,0,0,255          ; 219
  DEFB 5,0,0,255          ; 220
  DEFB 5,0,0,255          ; 221
  DEFB 5,0,0,255          ; 222
  DEFB 5,0,0,255          ; 223

; Room data - vertical tunnel sections
;
; Data for the vertical tunnel sections. Used in the routines starting at
; L50613.
;
; The tunnels let the player travel from/to Avalon's different levels, and
; sometimes connect rooms on the same level.
;
; Bats and spiders randomly appear in the tunnels, sapping Maroc's energy if he
; touches them.
;
; +------+----------------------------------------------+
; | Byte | Value                                        |
; +------+----------------------------------------------+
; | 1    | Tunnel length                                |
; | 2    | Connecting door set 1 (from table at L26512) |
; | 3    | Connecting door set 2 (from table at L26512) |
; | 4    | 255 = end of data                            |
; +------+----------------------------------------------+
L26384:
  DEFB 16,254,237,255     ; 224
  DEFB 10,222,79,255      ; 225
  DEFB 1,225,246,255      ; 226
  DEFB 1,224,238,255      ; 227
  DEFB 7,210,239,255      ; 228
  DEFB 4,195,219,255      ; 229
  DEFB 5,220,223,255      ; 230
  DEFB 6,77,214,255       ; 231
  DEFB 3,188,193,255      ; 232
  DEFB 3,175,176,255      ; 233
  DEFB 1,189,171,255      ; 234
  DEFB 6,168,52,255       ; 235
  DEFB 3,58,59,255        ; 236
  DEFB 3,66,67,255        ; 237
  DEFB 3,46,75,255        ; 238
  DEFB 2,42,48,255        ; 239
  DEFB 8,41,108,255       ; 240
  DEFB 5,138,158,255      ; 241
  DEFB 1,153,142,255      ; 242
  DEFB 2,141,143,255      ; 243
  DEFB 1,157,147,255      ; 244
  DEFB 2,137,148,255      ; 245
  DEFB 3,111,130,255      ; 246
  DEFB 2,114,124,255      ; 247
  DEFB 4,40,106,255       ; 248
  DEFB 4,39,113,255       ; 249
  DEFB 2,37,131,255       ; 250
  DEFB 6,28,38,255        ; 251
  DEFB 4,7,11,255         ; 252
  DEFB 2,20,31,255        ; 253
  DEFB 3,36,29,255        ; 254
  DEFB 2,4,21,255         ; 255

; Room data - connecting doors
;
; 4 byte sets indicating doors and the room number of their connecting door.
; Address pointer to these sets is stored at 56053.
;
; +------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
; | Byte                                                                                                                                                       | Value                                                                                                                                    |
; +------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+
; | 1                                                                                                                                                          | Connecting room number 1                                                                                                                 |
; | 2                                                                                                                                                          | Connecting room number 2                                                                                                                 |
; | 3                                                                                                                                                          | Door properties byte (from 60238) #LIST { Bit 0 set = door is visible (default)                                                         |
; | Bit 2 set = door will need erasing (default)                                                                                                               |
; | Bit 4 set = door is open                                                                                                                                   |
; | Bit 7 set = the door Maroc has just gone through (stored at #R60149, copied here in routine at #R50656)                                                    |
; | 4                                                                                                                                                          | Event value to check for door collisions at 51829 when Maroc goes through this door: #LIST { 0 = can be opened by Maroc bumping into it |
; | 1 = can be opened by Maroc bumping into it, the servant, or a deflected missile                                                                            |
; | Other value = the key or spell (e.g. OPEN) number that opens this door                                                                                     |
; | Connecting door set 28 - event value = 12 - corresponds to the key event that opens it - stored at second-to-last byte of the key item data set at #R29803 |
; | Connecting door sets 163 & 165 - event value = 10 - corresponds to the OPEN spell - stored at byte 6 of OPEN spell data set at #R28316                     |
; +------------------------------------------------------------------------------------------------------------------------------------------------------------+
;
; Each of these data sets tell us which two rooms each door connects.
; * The first two bytes of each data set here indicates the two rooms that this
;   door connects
; * In the room data table at L25001, the penultimate bytes - preceding each
;   end byte of 255 - reference the data sets here, for each of the doors in
;   the room
; * For example, in the above image, a door connects room 2 to room 5. This
;   connecting door is at 26524
; * Similarly, the door connecting room 5 and room 6 is at 26536
L26512:
  DEFB 83,90,%00000101,1  ; Connecting door set 0
  DEFB 1,2,%00000101,1    ; Connecting door set 1
  DEFB 2,3,%00000101,1    ; Connecting door set 2
  DEFB 2,5,%00000101,0    ; Connecting door set 3
  DEFB 3,255,%00000101,1  ; Connecting door set 4
  DEFB 3,4,%00000101,0    ; Connecting door set 5
  DEFB 5,6,%00000101,0    ; Connecting door set 6
  DEFB 5,252,%00000101,0  ; Connecting door set 7
  DEFB 6,7,%00000101,0    ; Connecting door set 8
  DEFB 7,8,%00000101,0    ; Connecting door set 9
  DEFB 4,0,%00000101,15   ; Connecting door set 10
  DEFB 9,252,%00000101,0  ; Connecting door set 11
  DEFB 9,10,%00000101,0   ; Connecting door set 12
  DEFB 10,11,%00001101,0  ; Connecting door set 13
  DEFB 11,12,%00000101,0  ; Connecting door set 14
  DEFB 12,13,%00000101,0  ; Connecting door set 15
  DEFB 13,15,%00000101,0  ; Connecting door set 16
  DEFB 13,14,%00001101,0  ; Connecting door set 17
  DEFB 9,16,%00000101,1   ; Connecting door set 18
  DEFB 15,16,%00000101,0  ; Connecting door set 19
  DEFB 12,253,%00000010,0 ; Connecting door set 20
  DEFB 17,255,%00000101,0 ; Connecting door set 21
  DEFB 17,18,%00000101,0  ; Connecting door set 22
  DEFB 17,22,%00000101,0  ; Connecting door set 23
  DEFB 18,19,%00001101,0  ; Connecting door set 24
  DEFB 18,20,%00000101,0  ; Connecting door set 25
  DEFB 18,21,%00000101,0  ; Connecting door set 26
  DEFB 22,23,%00000101,1  ; Connecting door set 27
  DEFB 24,251,%00000101,12 ; Connecting door set 28
  DEFB 22,254,%00000101,0 ; Connecting door set 29
  DEFB 23,24,%00000101,0  ; Connecting door set 30
  DEFB 25,253,%00000101,0 ; Connecting door set 31
  DEFB 25,26,%00001101,1  ; Connecting door set 32
  DEFB 26,27,%00000101,0  ; Connecting door set 33
  DEFB 26,28,%00000101,0  ; Connecting door set 34
  DEFB 28,29,%00000010,0  ; Connecting door set 35
  DEFB 29,254,%00000101,0 ; Connecting door set 36
  DEFB 30,250,%00000101,0 ; Connecting door set 37
  DEFB 30,251,%00000101,1 ; Connecting door set 38
  DEFB 30,249,%00000101,0 ; Connecting door set 39
  DEFB 30,248,%00000101,0 ; Connecting door set 40
  DEFB 32,240,%00000101,0 ; Connecting door set 41
  DEFB 31,239,%00000101,0 ; Connecting door set 42
  DEFB 31,33,%00000101,0  ; Connecting door set 43
  DEFB 31,32,%00000101,1  ; Connecting door set 44
  DEFB 32,33,%00000101,0  ; Connecting door set 45
  DEFB 33,238,%00000101,0 ; Connecting door set 46
  DEFB 210,82,%00000101,0 ; Connecting door set 47
  DEFB 34,239,%00000101,1 ; Connecting door set 48
  DEFB 210,211,%00000101,0 ; Connecting door set 49
  DEFB 34,41,%00000101,0  ; Connecting door set 50
  DEFB 34,35,%00000101,0  ; Connecting door set 51
  DEFB 34,235,%00000101,1 ; Connecting door set 52
  DEFB 35,36,%00001101,0  ; Connecting door set 53
  DEFB 36,40,%00000101,28 ; Connecting door set 54
  DEFB 36,37,%00000101,0  ; Connecting door set 55
  DEFB 37,39,%00000101,28 ; Connecting door set 56
  DEFB 37,38,%00000101,0  ; Connecting door set 57
  DEFB 37,236,%00000101,0 ; Connecting door set 58
  DEFB 43,236,%00000101,0 ; Connecting door set 59
  DEFB 42,43,%00000101,0  ; Connecting door set 60
  DEFB 42,47,%00001101,0  ; Connecting door set 61
  DEFB 45,47,%00000101,0  ; Connecting door set 62
  DEFB 45,46,%00000101,0  ; Connecting door set 63
  DEFB 42,44,%00000101,0  ; Connecting door set 64
  DEFB 44,46,%00001101,0  ; Connecting door set 65
  DEFB 44,237,%00000101,0 ; Connecting door set 66
  DEFB 49,237,%00000101,0 ; Connecting door set 67
  DEFB 48,49,%00000101,0  ; Connecting door set 68
  DEFB 49,53,%00000101,0  ; Connecting door set 69
  DEFB 49,50,%00001101,0  ; Connecting door set 70
  DEFB 53,54,%00001101,0  ; Connecting door set 71
  DEFB 48,54,%00001101,0  ; Connecting door set 72
  DEFB 48,54,%00000101,0  ; Connecting door set 73
  DEFB 50,51,%00000101,40 ; Connecting door set 74
  DEFB 52,238,%00000101,0 ; Connecting door set 75
  DEFB 51,52,%00000101,40 ; Connecting door set 76
  DEFB 51,231,%00000101,0 ; Connecting door set 77
  DEFB 211,212,%00000101,0 ; Connecting door set 78
  DEFB 56,225,%00001101,0 ; Connecting door set 79
  DEFB 56,58,%00001101,0  ; Connecting door set 80
  DEFB 58,59,%00000101,0  ; Connecting door set 81
  DEFB 59,60,%00001101,0  ; Connecting door set 82
  DEFB 59,62,%00000101,0  ; Connecting door set 83
  DEFB 59,72,%00000101,0  ; Connecting door set 84
  DEFB 60,61,%00000101,0  ; Connecting door set 85
  DEFB 62,63,%00000101,0  ; Connecting door set 86
  DEFB 72,77,%00000101,0  ; Connecting door set 87
  DEFB 56,57,%00000101,32 ; Connecting door set 88
  DEFB 57,70,%00000101,0  ; Connecting door set 89
  DEFB 70,71,%00000101,0  ; Connecting door set 90
  DEFB 71,74,%00000010,1  ; Connecting door set 91
  DEFB 73,74,%00001101,0  ; Connecting door set 92
  DEFB 74,75,%00000101,0  ; Connecting door set 93
  DEFB 73,76,%00000101,0  ; Connecting door set 94
  DEFB 57,64,%00000101,0  ; Connecting door set 95
  DEFB 64,65,%00000101,0  ; Connecting door set 96
  DEFB 65,66,%00001101,0  ; Connecting door set 97
  DEFB 66,67,%00000101,0  ; Connecting door set 98
  DEFB 67,68,%00000101,0  ; Connecting door set 99
  DEFB 67,69,%00001010,0  ; Connecting door set 100
  DEFB 77,78,%00000101,0  ; Connecting door set 101
  DEFB 78,80,%00000101,0  ; Connecting door set 102
  DEFB 78,79,%00000101,0  ; Connecting door set 103
  DEFB 80,81,%00001101,0  ; Connecting door set 104
  DEFB 55,56,%00000101,0  ; Connecting door set 105
  DEFB 92,248,%00000101,0 ; Connecting door set 106
  DEFB 92,93,%00000101,44 ; Connecting door set 107
  DEFB 93,240,%00000101,0 ; Connecting door set 108
  DEFB 93,94,%00000101,44 ; Connecting door set 109
  DEFB 94,95,%00000101,0  ; Connecting door set 110
  DEFB 95,246,%00000101,0 ; Connecting door set 111
  DEFB 83,84,%00000101,0  ; Connecting door set 112
  DEFB 84,249,%00000101,2 ; Connecting door set 113
  DEFB 84,247,%00000101,0 ; Connecting door set 114
  DEFB 84,85,%00000101,0  ; Connecting door set 115
  DEFB 85,86,%00000101,0  ; Connecting door set 116
  DEFB 86,87,%00000101,0  ; Connecting door set 117
  DEFB 87,88,%00000101,0  ; Connecting door set 118
  DEFB 88,89,%00000101,0  ; Connecting door set 119
  DEFB 89,90,%00000101,0  ; Connecting door set 120
  DEFB 90,91,%00001101,0  ; Connecting door set 121
  DEFB 96,97,%00001101,0  ; Connecting door set 122
  DEFB 97,98,%00000101,0  ; Connecting door set 123
  DEFB 99,247,%00000101,0 ; Connecting door set 124
  DEFB 98,99,%00001101,0  ; Connecting door set 125
  DEFB 98,100,%00000101,0 ; Connecting door set 126
  DEFB 100,101,%00000101,0 ; Connecting door set 127
  DEFB 101,102,%00000101,0 ; Connecting door set 128
  DEFB 102,103,%00000101,0 ; Connecting door set 129
  DEFB 103,246,%00000010,0 ; Connecting door set 130
  DEFB 109,250,%00000101,0 ; Connecting door set 131
  DEFB 109,110,%00000101,0 ; Connecting door set 132
  DEFB 107,108,%00000101,0 ; Connecting door set 133
  DEFB 106,107,%00000101,0 ; Connecting door set 134
  DEFB 106,109,%00000101,0 ; Connecting door set 135
  DEFB 105,106,%00000101,0 ; Connecting door set 136
  DEFB 105,245,%00000101,0 ; Connecting door set 137
  DEFB 111,241,%00000101,0 ; Connecting door set 138
  DEFB 111,113,%00000101,0 ; Connecting door set 139
  DEFB 111,112,%00001100,0 ; Connecting door set 140
  DEFB 112,243,%00000101,0 ; Connecting door set 141
  DEFB 114,242,%00000101,0 ; Connecting door set 142
  DEFB 125,243,%00000010,0 ; Connecting door set 143
  DEFB 124,125,%00000101,0 ; Connecting door set 144
  DEFB 125,126,%00000101,0 ; Connecting door set 145
  DEFB 123,126,%00000101,0 ; Connecting door set 146
  DEFB 123,244,%00000101,0 ; Connecting door set 147
  DEFB 116,245,%00000101,0 ; Connecting door set 148
  DEFB 116,117,%00000101,0 ; Connecting door set 149
  DEFB 117,121,%00000101,0 ; Connecting door set 150
  DEFB 117,118,%00000101,0 ; Connecting door set 151
  DEFB 118,119,%00000101,0 ; Connecting door set 152
  DEFB 119,242,%00000010,0 ; Connecting door set 153
  DEFB 119,120,%00000101,0 ; Connecting door set 154
  DEFB 121,122,%00000101,0 ; Connecting door set 155
  DEFB 115,116,%00000101,0 ; Connecting door set 156
  DEFB 121,244,%00000101,0 ; Connecting door set 157
  DEFB 127,241,%00000101,0 ; Connecting door set 158
  DEFB 127,133,%00000101,0 ; Connecting door set 159
  DEFB 127,132,%00000101,1 ; Connecting door set 160
  DEFB 131,132,%00000101,0 ; Connecting door set 161
  DEFB 130,131,%00000101,0 ; Connecting door set 162
  DEFB 104,133,%00000101,10 ; Connecting door set 163
  DEFB 129,130,%00000101,0 ; Connecting door set 164
  DEFB 128,129,%00000101,10 ; Connecting door set 165
  DEFB 113,114,%00000101,0 ; Connecting door set 166
  DEFB 207,208,%00000101,104 ; Connecting door set 167
  DEFB 138,235,%00001101,0 ; Connecting door set 168
  DEFB 137,138,%00001101,0 ; Connecting door set 169
  DEFB 138,139,%00001101,0 ; Connecting door set 170
  DEFB 139,234,%00001101,0 ; Connecting door set 171
  DEFB 136,137,%00001101,0 ; Connecting door set 172
  DEFB 135,136,%00001101,0 ; Connecting door set 173
  DEFB 134,135,%00001101,0 ; Connecting door set 174
  DEFB 134,233,%00001101,0 ; Connecting door set 175
  DEFB 146,233,%00000101,0 ; Connecting door set 176
  DEFB 146,147,%00000101,0 ; Connecting door set 177
  DEFB 146,155,%00000101,0 ; Connecting door set 178
  DEFB 146,153,%00000101,0 ; Connecting door set 179
  DEFB 154,153,%00000101,0 ; Connecting door set 180
  DEFB 147,148,%00000101,0 ; Connecting door set 181
  DEFB 148,149,%00000101,10 ; Connecting door set 182
  DEFB 148,151,%00000101,0 ; Connecting door set 183
  DEFB 149,150,%00000101,10 ; Connecting door set 184
  DEFB 151,152,%00000101,0 ; Connecting door set 185
  DEFB 155,156,%00000101,0 ; Connecting door set 186
  DEFB 156,157,%00000101,0 ; Connecting door set 187
  DEFB 142,232,%00000101,0 ; Connecting door set 188
  DEFB 143,234,%00000101,0 ; Connecting door set 189
  DEFB 142,143,%00000101,0 ; Connecting door set 190
  DEFB 141,143,%00001101,0 ; Connecting door set 191
  DEFB 140,141,%00000101,0 ; Connecting door set 192
  DEFB 145,232,%00000101,0 ; Connecting door set 193
  DEFB 144,145,%00000101,0 ; Connecting door set 194
  DEFB 158,229,%00000101,0 ; Connecting door set 195
  DEFB 158,159,%00000101,0 ; Connecting door set 196
  DEFB 159,160,%00000101,0 ; Connecting door set 197
  DEFB 160,161,%00000101,1 ; Connecting door set 198
  DEFB 164,165,%00000101,0 ; Connecting door set 199
  DEFB 161,164,%00000101,0 ; Connecting door set 200
  DEFB 161,162,%00000101,0 ; Connecting door set 201
  DEFB 162,163,%00000101,0 ; Connecting door set 202
  DEFB 163,166,%00000101,0 ; Connecting door set 203
  DEFB 170,169,%00000101,0 ; Connecting door set 204
  DEFB 168,169,%00000101,0 ; Connecting door set 205
  DEFB 166,168,%00000101,0 ; Connecting door set 206
  DEFB 166,167,%00000101,0 ; Connecting door set 207
  DEFB 168,171,%00000101,0 ; Connecting door set 208
  DEFB 171,172,%00000101,4 ; Connecting door set 209
  DEFB 173,228,%00000101,0 ; Connecting door set 210
  DEFB 172,173,%00000101,0 ; Connecting door set 211
  DEFB 174,175,%00000101,0 ; Connecting door set 212
  DEFB 173,174,%00000101,0 ; Connecting door set 213
  DEFB 178,231,%00000101,0 ; Connecting door set 214
  DEFB 177,178,%00000101,0 ; Connecting door set 215
  DEFB 176,177,%00000101,0 ; Connecting door set 216
  DEFB 178,179,%00000101,0 ; Connecting door set 217
  DEFB 177,180,%00000101,0 ; Connecting door set 218
  DEFB 176,229,%00000101,0 ; Connecting door set 219
  DEFB 176,230,%00000101,4 ; Connecting door set 220
  DEFB 179,180,%00000101,0 ; Connecting door set 221
  DEFB 225,181,%00000101,84 ; Connecting door set 222
  DEFB 181,230,%00000101,0 ; Connecting door set 223
  DEFB 182,227,%00000101,0 ; Connecting door set 224
  DEFB 226,182,%00000101,96 ; Connecting door set 225
  DEFB 182,187,%00000010,96 ; Connecting door set 226
  DEFB 182,186,%00000010,96 ; Connecting door set 227
  DEFB 182,185,%00000010,0 ; Connecting door set 228
  DEFB 182,184,%00000010,0 ; Connecting door set 229
  DEFB 182,183,%00000010,5 ; Connecting door set 230
  DEFB 189,190,%00000101,0 ; Connecting door set 231
  DEFB 188,189,%00000101,0 ; Connecting door set 232
  DEFB 189,194,%00000101,0 ; Connecting door set 233
  DEFB 189,193,%00000101,0 ; Connecting door set 234
  DEFB 189,191,%00000101,0 ; Connecting door set 235
  DEFB 194,195,%00000101,0 ; Connecting door set 236
  DEFB 195,224,%00000101,0 ; Connecting door set 237
  DEFB 193,227,%00000101,0 ; Connecting door set 238
  DEFB 192,228,%00000101,0 ; Connecting door set 239
  DEFB 191,192,%00000101,0 ; Connecting door set 240
  DEFB 196,197,%00000010,0 ; Connecting door set 241
  DEFB 197,198,%00000010,0 ; Connecting door set 242
  DEFB 198,199,%00000101,1 ; Connecting door set 243
  DEFB 199,200,%00000101,0 ; Connecting door set 244
  DEFB 200,201,%00000101,1 ; Connecting door set 245
  DEFB 201,226,%00000101,0 ; Connecting door set 246
  DEFB 199,202,%00000101,1 ; Connecting door set 247
  DEFB 202,203,%00000101,0 ; Connecting door set 248
  DEFB 203,206,%00000010,0 ; Connecting door set 249
  DEFB 203,204,%00000101,0 ; Connecting door set 250
  DEFB 204,205,%00000101,0 ; Connecting door set 251
  DEFB 206,209,%00000101,0 ; Connecting door set 252
  DEFB 206,207,%00000101,0 ; Connecting door set 253
  DEFB 30,224,%00000101,20 ; Connecting door set 254

; Room data - creatures
;
; Table indicating which creatures are in which room.
;
; Each of the the 212 standard rooms (but not the vertically scrolling tunnel
; rooms, numbers 224 to 255) has a single byte indicating which creatures it
; contains.
;
; * There are 4 types of creature that can move from room to room - (1) goblin
;   warrior, (2) goblin missile throwers, (3) guardians of chaos and (4)
;   wraiths
; * Each room can hold a maximum total of 3 creatures (any combination of
;   creature type)
; * This allows a room's creature data to be stored within a single byte. Bits
;   that are set indicate the type/number of creatures
; * Some room data indicates the room has more than 3 creatures. However, the
;   max creatures-per-room is 3, so only 3 will appear at once (see Bugs: Too
;   many creatures in a room)
; * Demons and Warlocks are dealt with separately (though they adhere to the
;   max-creatures-per-room limit). Other ad hoc room creatures such as spiders,
;   bats and scorpions are dealt with and stored as room objects (see L29551)
;
; The bits within the room byte tell us the creature types and numbers in the
; room:
;
; ******01 (1) = 1 wraith ******10 (2) = 2 wraiths ******11 (3) = 3 wraiths
; ****01** ( 4) = 1 goblin missile thrower ****10** ( 8) = 2 goblin missile
; throwers ****11** (12) = 3 goblin missile throwers **01**** (16) = 1 goblin
; warrior **10**** (32) = 2 goblin warriors**11**** (48) = 3 goblin warriors
; 01****** ( 64) = 1 guardian of chaos 10****** (128) = 2 guardians of chaos
; 11****** (192) = 3 guardians of chaos
;
; So, for example,
;
; When Maroc moves room, the routine at L55818 copies the byte holding the
; creatures in the room he's leaving (60343) into the relevant spot in this
; table.
;
; GATEHOUSE LEVEL:
L27532:
  DEFB 0                  ; Room 1
  DEFB 0                  ; Room 2
  DEFB 0                  ; Room 3
  DEFB 32                 ; Room 4 - Goblin warrior x 2
  DEFB 0                  ; Room 5
  DEFB 0                  ; Room 6
  DEFB 48                 ; Room 7 - Goblin warrior x 3
  DEFB 0                  ; Room 8
  DEFB 16                 ; Room 9 - Goblin warrior x 1
  DEFB 0                  ; Room 10
  DEFB 0                  ; Room 11
  DEFB 0                  ; Room 12
  DEFB 0                  ; Room 13
  DEFB 32                 ; Room 14 - Goblin warrior x 2
  DEFB 0                  ; Room 15
  DEFB 0                  ; Room 16
  DEFB 0                  ; Room 17
  DEFB 16                 ; Room 18 - Goblin warrior x 1
  DEFB 128                ; Room 19 - Guardian of chaos x 2
  DEFB 0                  ; Room 20
  DEFB 0                  ; Room 21
  DEFB 0                  ; Room 22
  DEFB 32                 ; Room 23 - Goblin warrior x 2
  DEFB 1                  ; Room 24 - Wraith x 1
  DEFB 16                 ; Room 25 - Goblin warrior x 1
  DEFB 0                  ; Room 26
  DEFB 32                 ; Room 27 - Goblin warrior x 2
  DEFB 0                  ; Room 28
  DEFB 16                 ; Room 29 - Goblin warrior x 1
  DEFB 0                  ; Room 30
; GREAT HALLS OF THE DEEP
  DEFB 0                  ; Room 31
  DEFB 64                 ; Room 32 - Guardian of chaos x 1
  DEFB 128                ; Room 33 - Guardian of chaos x 2
  DEFB 0                  ; Room 34
  DEFB 68                 ; Room 35 - Guardian of chaos x 1, Goblin missile
                          ; thrower x 1
  DEFB 0                  ; Room 36
  DEFB 0                  ; Room 37
  DEFB 64                 ; Room 38 - Guardian of chaos x 1
  DEFB 0                  ; Room 39
  DEFB 0                  ; Room 40
  DEFB 1                  ; Room 41 - Wraith x 1
  DEFB 0                  ; Room 42
  DEFB 0                  ; Room 43
  DEFB 16                 ; Room 44 - Goblin warrior x 1
  DEFB 0                  ; Room 45
  DEFB 32                 ; Room 46 - Goblin warrior x 2
  DEFB 64                 ; Room 47 - Guardian of chaos x 1
  DEFB 32                 ; Room 48
  DEFB 0                  ; Room 49 - Goblin warrior x 2
  DEFB 0                  ; Room 50
  DEFB 0                  ; Room 51
  DEFB 64                 ; Room 52 - Guardian of chaos x 1
  DEFB 0                  ; Room 53
  DEFB 128                ; Room 54 - Guardian of chaos x 2
; CHAMBERS OF CHAOS
  DEFB 1                  ; Room 55 - Wraith x 1
  DEFB 0                  ; Room 56
  DEFB 0                  ; Room 57
  DEFB 0                  ; Room 58
  DEFB 0                  ; Room 59
  DEFB 12                 ; Room 60 - Goblin missile thrower x 3
  DEFB 1                  ; Room 61 - Wraith x 1
  DEFB 12                 ; Room 62 - Goblin missile thrower x 3
  DEFB 1                  ; Room 63 - Wraith x 1
  DEFB 0                  ; Room 64
  DEFB 64                 ; Room 65 - Guardian of chaos x 1
  DEFB 32                 ; Room 66 - Goblin warrior x 2
  DEFB 96                 ; Room 67 - Guardian of chaos x 1, Goblin warrior x 2
  DEFB 0                  ; Room 68
  DEFB 0                  ; Room 69
  DEFB 64                 ; Room 70 - Guardian of chaos x 1
  DEFB 0                  ; Room 71
  DEFB 0                  ; Room 72
  DEFB 12                 ; Room 73 - Goblin missile thrower x 3
  DEFB 64                 ; Room 74 - Guardian of chaos x 1
  DEFB 0                  ; Room 75
  DEFB 0                  ; Room 76
  DEFB 12                 ; Room 77 - Goblin missile thrower x 3
  DEFB 1                  ; Room 78 - Wraith x 1
  DEFB 1                  ; Room 79 - Wraith x 1
  DEFB 0                  ; Room 80
  DEFB 2                  ; Room 81 - Wraith x 2
  DEFB 2                  ; Room 82 - Wraith x 2
; CAVERNS OF DOOM
  DEFB 0                  ; Room 83
  DEFB 0                  ; Room 84
  DEFB 0                  ; Room 85
  DEFB 4                  ; Room 86 - Goblin missile thrower x 1
  DEFB 4                  ; Room 87 - Goblin missile thrower x 1
  DEFB 4                  ; Room 88 - Goblin missile thrower x 1
  DEFB 0                  ; Room 89
  DEFB 0                  ; Room 90
  DEFB 4                  ; Room 91 - Goblin missile thrower x 1
  DEFB 0                  ; Room 92
  DEFB 0                  ; Room 93
  DEFB 8                  ; Room 94 - Goblin missile thrower x 2
  DEFB 0                  ; Room 95
  DEFB 4                  ; Room 96 - Goblin missile thrower x 1
  DEFB 0                  ; Room 97
  DEFB 8                  ; Room 98 - Goblin missile thrower x 2
  DEFB 0                  ; Room 99
  DEFB 0                  ; Room 100
  DEFB 0                  ; Room 101
  DEFB 4                  ; Room 102 - Goblin missile thrower x 1
  DEFB 0                  ; Room 103
; MINES OF MADNESS
  DEFB 0                  ; Room 104
  DEFB 0                  ; Room 105
  DEFB 48                 ; Room 106 - Goblin warrior x 3
  DEFB 0                  ; Room 107
  DEFB 0                  ; Room 108
  DEFB 0                  ; Room 109
  DEFB 0                  ; Room 110
  DEFB 0                  ; Room 111
  DEFB 0                  ; Room 112
  DEFB 0                  ; Room 113
  DEFB 0                  ; Room 114
  DEFB 0                  ; Room 115
  DEFB 32                 ; Room 116 - Goblin warrior x 2
  DEFB 0                  ; Room 117
  DEFB 0                  ; Room 118
  DEFB 0                  ; Room 119
  DEFB 0                  ; Room 120
  DEFB 32                 ; Room 121 - Goblin warrior x 2
  DEFB 0                  ; Room 122
  DEFB 0                  ; Room 123
  DEFB 0                  ; Room 124
  DEFB 0                  ; Room 125
  DEFB 0                  ; Room 126
  DEFB 0                  ; Room 127
  DEFB 0                  ; Room 128
  DEFB 0                  ; Room 129
  DEFB 0                  ; Room 130
  DEFB 0                  ; Room 131
  DEFB 0                  ; Room 132
  DEFB 0                  ; Room 133
; GOBLIN WARREN
  DEFB 0                  ; Room 134
  DEFB 4                  ; Room 135 - Goblin missile thrower x 1
  DEFB 0                  ; Room 136
  DEFB 4                  ; Room 137 - Goblin missile thrower x 1
  DEFB 0                  ; Room 138
  DEFB 4                  ; Room 139 - Goblin missile thrower x 1
  DEFB 32                 ; Room 140 - Goblin warrior x 2
  DEFB 32                 ; Room 141 - Goblin warrior x 2
  DEFB 32                 ; Room 142 - Goblin warrior x 2
  DEFB 32                 ; Room 143 - Goblin warrior x 2
  DEFB 40                 ; Room 144 - Goblin warrior x 2, Goblin missile
                          ; thrower x 2 (this is over the maximum of 3
                          ; creatures per room, so one of these won't appear)
  DEFB 4                  ; Room 145 - Goblin missile thrower x 1
  DEFB 32                 ; Room 146 - Goblin warrior x 2
  DEFB 16                 ; Room 147 - Goblin warrior x 1
  DEFB 16                 ; Room 148 - Goblin warrior x 1
  DEFB 0                  ; Room 149
  DEFB 0                  ; Room 150
  DEFB 0                  ; Room 151
  DEFB 64                 ; Room 152 - Guardian of chaos x 1
  DEFB 32                 ; Room 153 - Goblin warrior x 2
  DEFB 32                 ; Room 154 - Goblin warrior x 2
  DEFB 0                  ; Room 155
  DEFB 0                  ; Room 156
  DEFB 32                 ; Room 157 - Goblin warrior x 2
; THE LABYRINTH
  DEFB 0                  ; Room 158
  DEFB 1                  ; Room 159 - Wraith x 1
  DEFB 0                  ; Room 160
  DEFB 0                  ; Room 161
  DEFB 0                  ; Room 162
  DEFB 0                  ; Room 163
  DEFB 0                  ; Room 164
  DEFB 1                  ; Room 165 - Wraith x 1
  DEFB 0                  ; Room 166
  DEFB 0                  ; Room 167
  DEFB 1                  ; Room 168 - Wraith x 1
  DEFB 0                  ; Room 169
  DEFB 0                  ; Room 170
  DEFB 0                  ; Room 171
  DEFB 1                  ; Room 172 - Wraith x 1
  DEFB 0                  ; Room 173
  DEFB 0                  ; Room 174
  DEFB 0                  ; Room 175
  DEFB 0                  ; Room 176
  DEFB 1                  ; Room 177 - Wraith x 1
  DEFB 0                  ; Room 178
  DEFB 1                  ; Room 179 - Wraith x 1
  DEFB 0                  ; Room 180
  DEFB 0                  ; Room 181
  DEFB 1                  ; Room 182 - Wraith x 1
; CATACOMBS OF THE UNDEAD
  DEFB 0                  ; Room 183
  DEFB 1                  ; Room 184 - Wraith x 1
  DEFB 1                  ; Room 185 - Wraith x 1
  DEFB 0                  ; Room 186
  DEFB 0                  ; Room 187
  DEFB 1                  ; Room 188 - Wraith x 1
  DEFB 0                  ; Room 189
  DEFB 1                  ; Room 190 - Wraith x 1
  DEFB 0                  ; Room 191
  DEFB 0                  ; Room 192
  DEFB 0                  ; Room 193
  DEFB 2                  ; Room 194 - Wraith x 2
  DEFB 0                  ; Room 195
  DEFB 1                  ; Room 196 - Wraith x 1
  DEFB 0                  ; Room 197
  DEFB 1                  ; Room 198 - Wraith x 1
  DEFB 0                  ; Room 199
  DEFB 0                  ; Room 200
  DEFB 0                  ; Room 201
  DEFB 0                  ; Room 202
  DEFB 1                  ; Room 203 - Wraith x 1
  DEFB 0                  ; Room 204
  DEFB 1                  ; Room 205 - Wraith x 1
  DEFB 0                  ; Room 206
  DEFB 0                  ; Room 207
  DEFB 0                  ; Room 208
; HIGH TEMPLE OF CHAOS
  DEFB 0                  ; Room 209
  DEFB 1                  ; Room 210 - Wraith x 1
  DEFB 85                 ; Room 211 - Goblin warrior x 1, goblin missile
                          ; thrower x 1, guardian of chaos x 1, wraith x 1 (not
                          ; present as max 3 creatures per room)
  DEFB 0                  ; Room 212
; Unused data - see Trivia: Unused rooms
  DEFB 85,85,85,85,85,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0

; Warlock and other creatures - stats and attributes
;
; See Reference - Creatures for a glossary about each type of creature in
; Avalon.
;
; WARLOCKS
;
; Data for the 7 warlocks that periodically materialize on the walls in
; Avalon's rooms. Address pointer to this data is stored at 60355.
;
; +------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | Byte | Value                                                                                                                                                                                                                                |
; +------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | 1    | INK/attribute colour of warlock, 1-7. Byte value of 15 (bit 3 set) means warlock constantly changes colour                                                                                                                           |
; | 2    | If Maroc destroys a warlock, this value changes from 0 to 1. If this byte is >0, Maroc's score (calculated at 58642) is increased by warlock number * 4 (e.g. warlock #2 is worth 8, warlock #7 is worth 28)                         |
; | 3    | Type of missile/bolt (L27868) that this warlock fires                                                                                                                                                                                |
; | 4    | Object (see table at L29551, starting at object #1) that this warlock is carrying This byte value is set to 16 once a trade is made with this warlock                                                                                |
; | 5    | The matching missile/bolt spell type(s) that can destroy this warlock. See byte #4 in data sets at L27868                                                                                                                            |
; | 6    | Warlock 'aggression'. Likelihood of this warlock firing a missile at Maroc. The higher the value, the higher the likelihood. Checked at 52987. Also used as the value for event checking at L57293 for items traded with the warlock |
; | 7    | Graphic number - address pointer to warlock graphics at 38971                                                                                                                                                                        |
; | 8    | Amount of damage dealt if Maroc collides with this warlock (not common as the warlocks stay within the room's wall area) Also the level number that this warlock appears on (see L50852)                                             |
; +------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
;
; Warlocks grant items when given certain other items. The items can also be
; gained by destroying the warlock with a spell to which they are vulnerable.
L27772:
  DEFB 6,0,1,1,3,6,61,1   ; Yellow warlock in the Gatehouse Level Destroy with
                          ; MISSILE Carries: star symbol, used to create an
                          ; energy restoration point in room #2 on the
                          ; Gatehouse Level Score earned for destroying = 4
  DEFB 4,0,4,2,39,14,61,2 ; Green warlock in the Caverns of Doom Destroy with
                          ; FIREBOLT, FIREBALL or FLAME Carries: WAYSTONE spell
                          ; jewel Score earned for destroying = 8
  DEFB 5,0,3,3,39,18,61,3 ; Cyan warlock in the Mines of Madness Destroy with
                          ; FIREBOLT, FIREBALL or FLAME Carries: ICEBOLT spell
                          ; scroll Score earned for destroying = 12
  DEFB 3,0,5,4,43,22,61,4 ; Magenta warlock in the Great Halls of the Deep
                          ; Destroy with ICEBOLT or ELECTRIC Carries:
                          ; WRAITHBANE spell jewel Score earned for destroying
                          ; = 16
  DEFB 1,0,6,5,47,30,61,5 ; Blue warlock in the Goblin Warren Destroy with
                          ; VAPORIZE Carries: ELECTRIC spell scroll Score
                          ; earned for destroying = 20 Much of the goblin
                          ; warren has a blue background so this warlock is
                          ; invisible
  DEFB 2,0,8,6,43,34,61,6 ; Red warlock in the Labyrinth Destroy with ICEBOLT
                          ; or ELECTRIC Carries: FIREBALL spell scroll Score
                          ; earned for destroying = 24
  DEFB 15,0,8,7,47,38,61,7 ; Colour-changing warlock in the Catacombs of the
                           ; Undead Destroy with VAPORIZE Carries: FLAME spell
                           ; scroll Score earned for destroying = 28
; OTHER CREATURES
;
; Individual creature attributes copied to working area at L60325.
;
; +------+-------------------------------------------------------------------------------------------------------------+
; | Byte | Value                                                                                                       |
; +------+-------------------------------------------------------------------------------------------------------------+
; | 1    | INK/attribute colour of creature, 1-7. Byte value of 15 (bit 3 set) means warlock constantly changes colour |
; | 2    | Number of these creatures that Maroc has destroyed                                                          |
; | 3    | Type of missile (L27868) fired (0 = no ranged attack)                                                       |
; | 4    | - (unused)                                                                                                  |
; | 5    | Collision/event check type (L57293)                                                                         |
; | 6    | Collision/event check value for creatures opening/closing doors (17)                                        |
; | 7    | Graphic number - address pointer to creature graphic in table at L38851                                     |
; | 8    | Amount of damage this creature does to Maroc's energy (check at L53349_0)                                   |
; +------+-------------------------------------------------------------------------------------------------------------+
  DEFB 4,0,0,0,3,17,64,8  ; Guardian of Chaos
  DEFB 5,0,0,0,3,17,70,2  ; Goblin warrior
  DEFB 6,0,1,0,3,17,76,1  ; Goblin missile thrower
  DEFB 15,0,0,0,7,17,82,16 ; Wraith
  DEFB 0,0,9,0,7,17,88,32 ; Demon

; Missile data
;
; Address pointer stored at 60307 (intialized at L60353). Used in routine at
; L56095.
;
; +----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | Byte                             | Value                                                                                                                                                                                                                                                                                                                                                  |
; +----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | 1                                | Graphic number - offset for missile graphic address in table at L38851 52 = Missile type 1 (38953) 55 = Missile type 2 (38961) 58 = Missile type 3 (38965)                                                                                                                                                                                             |
; | 2                                | Missile properties byte (put in item buffer at 60238). Bits 0 & 2 set as a default to indicate item is on-screen/needs erasing The value stored in the top 4 bits (nnnn----) indicates (in multiples of 16) how long this missile/bolt will appears/travel for, before disappearing. Values range from #LIST { 9 * 16 = 144 for missiles 3, 4 & 8, to |
; | 15 * 16 = 240 for missiles 1 & 9 |
; | 3                                | INK attribute colour of missileBit 4 set (byte value of 15) = missile changes colour                                                                                                                                                                                                                                                                   |
; | 4                                | Missile's event/collision type to check - match with byte 5 of warlock data sets (L27772) to indicate which missile spell(s) can destroy which warlock                                                                                                                                                                                                 |
; | 5                                | Counter spell #1 (list at L28156, starting at 0) that resists this missile/bolt type (Amulet)                                                                                                                                                                                                                                                          |
; | 6                                | Damage caused by this missile                                                                                                                                                                                                                                                                                                                          |
; | 7                                | Counter spell #2 (list at L28156, starting at 0) that resists this missile/bolt type                                                                                                                                                                                                                                                                   |
; | 8                                | Counter spell #3 (list at L28156, starting at 0) that resists this missile/bolt type                                                                                                                                                                                                                                                                   |
; +----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
L27868:
  DEFB 52,%11110101,7,1,14,32,2,18 ; Missile 1
  DEFB 55,%10100101,6,39,14,32,2,11 ; Missile 2
  DEFB 55,%10010101,5,43,14,40,2,18 ; Missile 3
  DEFB 55,%10010101,15,3,14,48,2,11 ; Missile 4
  DEFB 58,%10100101,6,39,14,48,11,18 ; Missile 5
  DEFB 58,%10100101,5,43,14,48,11,18 ; Missile 6
  DEFB 58,%11000101,15,47,14,40,11,18 ; Missile 7
  DEFB 58,%10010101,6,39,14,40,11,2 ; Missile 8
  DEFB 58,%11110101,15,1,14,64,68,68 ; Missile 9
; Summary:
;
; +----------------+------+-----------------------------------------+------------------------------------------------------------------+----------------------+-----------------+
; | Missile number | Type | Fired by                                | Destroys                                                         | Repelled by          | Damage to Maroc |
; +----------------+------+-----------------------------------------+------------------------------------------------------------------+----------------------+-----------------+
; | 1              | STAR | Warlock #1Goblin missile throwers       | -                                                                | AMULETSHIELDDEFENCE  | 32              |
; | 2              | BOLT | Maroc - FIREBOLT spell                  | Warlock #2Warlock #3                                             | AMULETSHIELDPROTECT  | 32              |
; | 3              | BOLT | Maroc - ICEBOLT spellWarlock #3         | Warlock #4Warlock #6                                             | AMULETSHIELDDEFENCE  | 40              |
; | 4              | BOLT | Maroc - MISSILE spellWarlock #2         | Warlock #1 Goblin warriorGoblin missile throwerGuardian of Chaos | AMULETSHIELDPROTECT  | 48              |
; | 5              | BALL | Maroc - FIREBALL spellWarlock #4        | Warlock #2Warlock #3                                             | AMULETPROTECTDEFENCE | 48              |
; | 6              | BALL | Maroc - ELECTRIC spellWarlock #5        | Warlock #4Warlock #6                                             | AMULETPROTECTDEFENCE | 48              |
; | 7              | BALL | Maroc - VAPORIZE spell                  | Warlock #5Warlock #7                                             | AMULETPROTECTDEFENCE | 40              |
; | 8              | BALL | Maroc - FLAME spellWarlock #6Warlock #7 | Warlock #2Warlock #3                                             | AMULETSHIELDPROTECT  | 40              |
; | 9              | BALL | Demons (in High Temple of Chaos)        | -                                                                | AMULET               | 64              |
; +----------------+------+-----------------------------------------+------------------------------------------------------------------+----------------------+-----------------+

; Graphics - character set A-Z
;
; Message texts correspond to byte values as follows:
;
; +------+--------+------+--------+------+---------+
; | Byte | Letter | Byte | Letter | Byte | Letter  |
; +------+--------+------+--------+------+---------+
; | 0    | A      | 9    | J      | 18   | S       |
; | 1    | B      | 10   | K      | 19   | T       |
; | 2    | C      | 11   | L      | 20   | U       |
; | 3    | D      | 12   | M      | 21   | V       |
; | 4    | E      | 13   | N      | 22   | W       |
; | 5    | F      | 14   | O      | 23   | X       |
; | 6    | G      | 15   | P      | 24   | Y       |
; | 7    | H      | 16   | Q      | 25   | Z       |
; | 8    | I      | 17   | R      | 26   | [SPACE] |
; +------+--------+------+--------+------+---------+
L27940:
  DEFB 0,0,56,6,56,98,102,58
  DEFB 96,96,44,50,34,34,114,124
  DEFB 0,0,28,38,64,64,70,60
  DEFB 6,6,52,76,68,68,78,62
  DEFB 0,0,60,70,94,64,70,60
  DEFB 126,102,32,46,48,32,96,96
  DEFB 0,0,54,78,68,60,4,126
  DEFB 96,96,44,50,34,34,110,108
  DEFB 28,28,0,8,8,16,24,24
  DEFB 28,28,0,8,8,4,108,56
  DEFB 96,100,40,56,48,28,34,38
  DEFB 96,96,32,32,32,32,102,124
  DEFB 0,0,214,233,73,73,91,90
  DEFB 0,0,108,114,34,34,38,44
  DEFB 0,0,24,36,66,66,102,60
  DEFB 0,0,108,114,34,60,96,96
  DEFB 0,0,54,78,68,60,6,6
  DEFB 0,0,108,118,32,32,32,32
  DEFB 0,0,56,100,48,12,98,60
  DEFB 48,48,16,120,32,32,102,124
  DEFB 0,0,54,102,68,68,78,54
  DEFB 0,0,102,38,34,20,28,8
  DEFB 0,0,219,91,73,42,62,20
  DEFB 0,0,98,52,20,28,52,98
  DEFB 0,0,54,102,68,56,8,12
  DEFB 0,0,126,102,12,24,54,124
; Final character = [SPACE]
  DEFB 0,0,0,0,0,0,0,0

; Spells list
;
; See the Spells reference section for spell information.
;
; Details of the active/selected spell are copied into a working buffer at
; L60357.
;
; The 8 bytes preceding the spell name text are as follows:
;
; +------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | Byte | Value                                                                                                                                                                                                                                                                                                                                                                                                                                             |
; +------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | 1    | Set to 16 if this spell has been acquired                                                                                                                                                                                                                                                                                                                                                                                                         |
; | 2    | Energy cost of casting (certain) spells 'Effect' spells (e.g. SHIELD, UNSEEN) - energy drain amountHealing spells (e.g. ENERGIZE, CHALICE) - energy restoration amount. Negative numbers (bit 7 set) = 'negative drain'                                                                                                                                                                                                                           |
; | 3    | Spell type: 1 = MOVE spell2 = Spell that generates a controllable graphic/icon, e.g. SERVANT, MISSILE, OPEN3 = Assigned to the ELECTRIC and FLAME spells4 = Ongoing effect spell (e.g. SHIELD, WRAITHBANE), spell name appears in bottom right mini-scroll5 = Instant effect spell e.g. ENERGIZE, FREEZE, PORTAL                                                                                                                                  |
; | 4    | Number of uses (255 indicates infinite use - MOVE/AMULET/W BANE/CHALICE)                                                                                                                                                                                                                                                                                                                                                                          |
; | 5    | Used to store the character number within the string of the current spell message text (stored in the spell data buffer at 60361)                                                                                                                                                                                                                                                                                                                 |
; | 6    | Value representing action to take when FIRE pressed with a servant/cursor icon spell active (checked at 55328 and 59885). Also represents the event value for spells that have an effect when the cursor is moved onto room objects, e.g. SERVANT = 5, UNLOCK = 4, DISPEL = 2 Bit 7 is set for missile-type spells                                                                                                                                |
; | 7    | Graphics number - address pointer offset for the icon graphic to use for this spell, in the graphic address table at L38851 (icon graphics from L41342)                                                                                                                                                                                                                                                                                           |
; | 8    | Graphics number - address pointer offset (for graphic addresses at L38851) for the spell's controllable graphic/aiming cursor (or 0 if a spell doesn't need one).For the SERVANT spell, offset is 41 (graphics pointer 38931 pointing to servant graphics at 41180)For all other 'aiming cursor' spells (e.g. UNLOCK, MISSILE, OPEN, FIND, ICEBOLT) spell offset is 43 (graphics pointer 38935 pointing to blinking eye cursor graphics at 41221) |
; +------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
;
; See the table of character byte values for a translation of
; letters-to-numbers.
L28156:
  DEFB 16,1,1,255,0,0,50,0
  DEFM 12,14,21,4,26,26,26,26 ; MOVE____
  DEFB 0,8,2,255,0,5,49,41
  DEFM 18,4,17,21,0,13,19,26 ; SERVANT_
  DEFB 0,1,4,0,0,0,45,0
  DEFM 18,7,8,4,11,3,26,26 ; SHIELD__
  DEFB 0,4,2,0,0,4,45,43
  DEFM 20,13,11,14,2,10,26,26 ; UNLOCK__
  DEFB 0,2,2,0,0,132,45,43
  DEFM 12,8,18,18,8,11,4,26 ; MISSILE_
  DEFB 0,192,5,0,0,0,45,0
  DEFM 4,13,4,17,6,8,25,4 ; ENERGIZE
  DEFB 0,8,2,0,0,130,45,43
  DEFM 5,8,17,4,1,14,11,19 ; FIREBOLT
  DEFB 0,3,2,0,0,16,45,43
  DEFM 17,4,21,4,0,11,26,26 ; REVEAL__
  DEFB 0,1,5,0,0,0,45,0
  DEFM 7,0,8,11,26,26,26,26 ; HAIL____
  DEFB 0,1,4,0,0,0,45,0
  DEFM 20,13,18,4,4,13,26,26 ; UNSEEN__
  DEFB 0,1,2,0,0,10,45,43
  DEFM 14,15,4,13,26,26,26,26 ; OPEN____
  DEFB 0,1,4,0,0,0,45,0
  DEFM 15,17,14,19,4,2,19,26 ; PROTECT_
  DEFB 0,4,5,0,0,0,51,0
  DEFM 22,0,24,18,19,14,13,4 ; WAYSTONE
  DEFB 0,2,2,0,0,131,45,43
  DEFM 8,2,4,1,14,11,19,26 ; ICEBOLT_
  DEFB 0,1,4,255,0,0,47,0
  DEFM 0,12,20,11,4,19,26,26 ; AMULET__
  DEFB 0,2,2,0,0,133,45,43
  DEFM 5,8,17,4,1,0,11,11 ; FIREBALL
  DEFB 0,4,5,0,0,0,45,0
  DEFM 5,17,4,4,25,4,26,26 ; FREEZE__
  DEFB 0,4,5,0,0,0,51,0
  DEFM 18,20,12,12,14,13,26,26 ; SUMMON__
  DEFB 0,1,4,0,0,0,51,0
  DEFM 3,4,5,4,13,2,4,26  ; DEFENCE_
  DEFB 0,8,5,0,0,0,45,0
  DEFM 15,14,17,19,0,11,26,26 ; PORTAL__
  DEFB 0,4,4,255,0,0,51,0
  DEFM 22,26,1,0,13,4,26,26 ; W_BANE__
  DEFB 0,4,2,0,0,2,45,43
  DEFM 3,8,18,15,4,11,26,26 ; DISPEL__
  DEFB 0,2,3,0,0,134,51,43
  DEFM 4,11,4,2,19,17,8,2 ; ELECTRIC
  DEFB 0,6,2,0,0,135,45,43
  DEFM 21,0,15,14,17,8,25,4 ; VAPORIZE
  DEFB 0,2,3,0,0,136,45,43
  DEFM 5,11,0,12,4,26,26,26 ; FLAME___
  DEFB 0,4,2,0,0,8,45,43
  DEFM 5,8,13,3,26,26,26,26 ; FIND____
  DEFB 0,251,4,255,0,0,48,0
  DEFM 2,7,0,11,8,2,4,26  ; CHALICE_
  DEFB 0,0,5,255,0,0,45,0
  DEFM 12,4,18,18,0,6,4,26 ; MESSAGE_

; Spell text messages
;
; These are the message texts that appear on the scroll when Maroc selects a
; spell.
;
; See the table of character byte values for a translation of
; letters-to-numbers.
L28604:
  DEFB 255                ; Unused byte
; MOVE spell
  DEFB 16                 ; Text length = 16
  DEFM 15,17,14,9,4,2,19,26,19,7,24,26,18,14,20,11 ; PROJECT THY SOUL
; SERVANT spell
  DEFB 14                 ; Text length = 14
  DEFM 0,26,7,4,11,15,8,13,6,26,7,0,13,3 ; A HELPING HAND
; SHIELD spell
  DEFB 14                 ; Text length = 14
  DEFM 0,18,26,8,5,26,14,5,26,18,19,4,4,11 ; AS IF OF STEEL
; UNLOCK spell
  DEFB 16                 ; Text length = 16
  DEFM 0,26,10,4,24,26,14,5,26,2,20,13,13,8,13,6 ; A KEY OF CUNNING
; MISSILE spell
  DEFB 14                 ; Text length = 14
  DEFM 6,14,1,11,8,13,26,2,17,20,18,7,4,17 ; GOBLIN CRUSHER
; ENERGIZE spell
  DEFB 14                 ; Text length = 14
  DEFM 15,14,22,4,17,26,19,14,26,22,8,4,11,3 ; POWER TO WIELD
; FIREBOLT spell
  DEFB 16                 ; Text length = 16
  DEFM 22,0,17,11,14,2,10,18,26,20,13,3,14,8,13,6 ; WARLOCKS UNDOING
; REVEAL spell
  DEFB 15                 ; Text length = 15
  DEFM 19,14,26,5,8,13,3,26,19,7,4,26,2,20,15 ; TO FIND THE CUP
; HAIL spell
  DEFB 16                 ; Text length = 16
  DEFM 2,0,11,11,26,19,14,26,19,7,4,26,22,8,18,4 ; CALL TO THE WISE
; UNSEEN spell
  DEFB 14                 ; Text length = 14
  DEFM 19,14,26,6,14,26,20,13,14,19,8,2,4,3 ; TO GO UNOTICED
; OPEN spell
  DEFB 14                 ; Text length = 14
  DEFM 19,14,26,11,14,14,10,26,8,13,18,8,3,4 ; TO LOOK INSIDE
; PROTECT spell
  DEFB 14                 ; Text length = 14
  DEFM 12,0,6,8,2,26,12,0,24,26,19,20,17,13 ; MAGIC MAY TURN
; WAYSTONE spell
  DEFB 13                 ; Text length = 13
  DEFM 7,4,17,4,26,19,14,26,19,7,4,17,4 ; HERE TO THERE
; ICEBOLT spell
  DEFB 14                 ; Text length = 14
  DEFM 4,0,19,4,17,26,14,5,26,5,11,0,12,4 ; EATER OF FLAME
; AMULET spell
  DEFB 11                 ; Text length = 11
  DEFM 14,5,26,4,21,4,17,12,14,17,4 ; OF EVERMORE
; FIREBALL spell
  DEFB 14                 ; Text length = 14
  DEFM 0,26,3,4,0,3,11,24,26,5,11,0,12,4 ; A DEADLY FLAME
; FREEZE spell
  DEFB 14                 ; Text length = 14
  DEFM 18,4,2,17,4,19,26,14,5,26,19,8,12,4 ; SECRET OF TIME
; SUMMON spell
  DEFB 13                 ; Text length = 13
  DEFM 7,4,0,17,26,0,13,3,26,14,1,4,24 ; HEAR AND OBEY
; DEFENCE spell
  DEFB 12                 ; Text length = 12
  DEFM 12,8,17,17,14,17,26,12,0,6,8,2 ; MIRROR MAGIC
; PORTAL spell
  DEFB 12                 ; Text length = 12
  DEFM 1,0,2,10,26,19,14,26,7,4,17,4 ; BACK TO HERE
; W BANE spell
  DEFB 10                 ; Text length = 10
  DEFM 22,17,0,8,19,7,1,0,13,4 ; WRAITHBANE
; DISPEL spell
  DEFB 13                 ; Text length = 13
  DEFM 20,13,1,4,22,8,19,2,7,12,4,12,19 ; UNBEWITCHMEMT
; ELECTRIC spell
  DEFB 15                 ; Text length = 15
  DEFM 18,11,0,24,26,19,7,4,26,3,0,12,13,4,3 ; SLAY THE DAMNED
; VAPORIZE spell
  DEFB 13                 ; Text length = 13
  DEFM 3,4,5,24,26,19,7,4,26,3,0,17,10 ; DEFY THE DARK
; FLAME spell
  DEFB 16                 ; Text length = 16
  DEFM 1,20,17,13,26,1,11,0,2,10,26,12,0,6,8,2 ; BURN BLACK MAGIC
; FIND spell
  DEFB 16                 ; Text length = 16
  DEFM 18,7,14,22,18,26,19,7,4,26,7,8,3,3,4,13 ; SHOWS THE HIDDEN
; CHALICE spell
  DEFB 16                 ; Text length = 16
  DEFM 6,17,0,8,11,26,14,5,26,7,4,0,11,8,13,6 ; GRAIL OF HEALING
; MESSAGE spell
  DEFB 30                 ; Text length = 30
  DEFM 18,4,4,10,26,19,7,4,26,11,0,3,24,27,19,14,26 ; SEEK THE LADY TO
  DEFM 5,8,13,3,26,2,0,11,8,1,20,17,13 ; FIND CALIBURN

; Level names
;
; The current level name is printed on the scroll when Maroc enters a new room.
;
; See the table of character byte values for a translation of
; letters-to-numbers. 27 = end-of-line
L29042:
  DEFB 15                 ; Text length = 15
  DEFM 6,0,19,4,7,14,20,18,4,26,11,4,21,4,11 ; GATEHOUSE LEVEL
  DEFB 15                 ; Text length = 15
  DEFM 2,0,21,4,17,13,18,26,14,5,26,3,14,14,12 ; CAVERNS OF DOOM
  DEFB 16                 ; Text length = 16
  DEFM 12,8,13,4,18,26,14,5,26,12,0,3,13,4,18,18 ; MINES OF MADNESS
  DEFB 23                 ; Text length = 23
  DEFM 6,17,4,0,19,26,7,0,11,11,18,26,14,5,27 ; GREAT HALLS OF/
  DEFM 19,7,4,26,3,4,4,15 ; THE DEEP
  DEFB 13                 ; Text length = 13
  DEFM 6,14,1,11,8,13,26,22,0,17,17,4,13 ; GOBLIN WARREN
  DEFB 13                 ; Text length = 13
  DEFM 19,7,4,26,11,0,1,24,17,8,13,19,7 ; THE LABYRINTH
  DEFB 23                 ; Text length = 23
  DEFM 2,0,19,0,2,14,12,1,18,26,14,5,26,19,7,4 ; CATACOMBS OF THE/
  DEFM 27,20,13,3,4,0,3   ; UNDEAD
  DEFB 17                 ; Text length = 17
  DEFM 2,7,0,12,1,4,17,18,26,14,5,27,2,7,0,14,18 ; CHAMBERS OF CHAOS
  DEFB 20                 ; Text length = 20
  DEFM 7,8,6,7,26,19,4,12,15,11,4,26,14,5,27 ; HIGH TEMPLE OF/
  DEFM 2,7,0,14,18        ; CHAOS

; Level ranks
;
; Maroc's gains 'points' towards his rank by:
; * destroying creatures and warlocks
; * collecting spells (though these points are ignored - see Trivia: Maroc's
;   rank)
; * reaching deeper dungeon levels
;
; His RANK is made up of two parts - a descriptor e.g. LESSER, and a title,
; e.g. MAGICIAN.
; * Maroc starts the game as an APPRENTICE LORE SEEKER
; * The highest rank attainable is SUPREME LORE LORD
; * Maroc loses a small number of points (and rank) for repeatedly running out
;   of energy
;
; DESCRIPTORS advance through from APPRENTICE to SUPREME. Then the TITLE
; advances to the next one, and the descriptor is reset. So for example the
; next rank up from SUPREME LORE SEEKER is APPRENTICE WISE ONE.
;
; The calculation and display of Maroc's rank occurs (L58599) when he runs out
; of energy, and at the (successful) end of the game.
;
; See the table of character byte values for a translation of
; letters-to-numbers.
;
; DESCRIPTORS:
L29206:
  DEFB 10                 ; Text length = 10
  DEFM 0,15,15,17,4,13,19,8,2,4 ; APPRENTICE
  DEFB 5                  ; Text length = 5
  DEFM 12,8,13,14,17      ; MINOR
  DEFB 6                  ; Text length = 6
  DEFM 11,4,18,18,4,17    ; LESSER
  DEFB 7                  ; Text length = 7
  DEFM 11,4,0,17,13,4,3   ; LEARNED
  DEFB 6                  ; Text length = 6
  DEFM 12,0,18,19,4,17    ; MASTER
  DEFB 5                  ; Text length = 5
  DEFM 2,7,8,4,5          ; CHIEF
  DEFB 4                  ; Text length = 4
  DEFM 7,8,6,7            ; HIGH
  DEFB 7                  ; Text length = 7
  DEFM 18,20,15,17,4,12,4 ; SUPREME
; TITLES:
  DEFB 11                 ; Text length = 11
  DEFM 11,14,17,4,26,18,4,4,10,4,17 ; LORE SEEKER
  DEFB 8                  ; Text length = 8
  DEFM 22,8,18,4,26,14,13,4 ; WISE ONE
  DEFB 11                 ; Text length = 11
  DEFM 11,14,17,4,26,10,4,4,15,4,17 ; LORE KEEPER
  DEFB 6                  ; Text length = 6
  DEFM 12,24,18,19,8,2    ; MYSTIC
  DEFB 9                  ; Text length = 9
  DEFM 0,11,2,7,4,12,8,18,19 ; ALCHEMIST
  DEFB 4                  ; Text length = 4
  DEFM 12,0,6,4           ; MAGE
  DEFB 10                 ; Text length = 10
  DEFM 12,0,6,8,2,26,20,18,4,17 ; MAGIC USER
  DEFB 8                  ; Text length = 8
  DEFM 2,14,13,9,20,17,14,17 ; CONJUROR
  DEFB 8                  ; Text length = 8
  DEFM 12,0,6,8,2,8,0,13  ; MAGICIAN
  DEFB 4                  ; Text length = 4
  DEFM 18,0,6,4           ; SAGE
  DEFB 11                 ; Text length = 11
  DEFM 11,14,17,4,26,12,0,18,19,4,17 ; LORE MASTER
  DEFB 7                  ; Text length = 7
  DEFM 22,0,17,11,14,2,10 ; WARLOCK
  DEFB 6                  ; Text length = 6
  DEFM 22,8,25,0,17,3     ; WIZARD
  DEFB 8                  ; Text length = 8
  DEFM 18,14,17,2,4,17,14,17 ; SORCEROR
  DEFB 16                 ; Text length = 16
  DEFM 6,20,0,17,3,8,0,13,26,14,5,26,11,14,17,4 ; GUARDIAN OF LORE
  DEFB 9                  ; Text length = 9
  DEFM 11,14,17,4,26,11,14,17,3 ; LORE LORD
; Text printed before rank:
  DEFB 16                 ; Text length = 16
  DEFM 24,14,20,17,26,17,0,13,10,26,8,18,26,13,14,22 ; YOUR RANK IS NOW

; Game completion and start messages
;
; See the table of character byte values for a translation of
; letters-to-numbers. 27 = end-of-line
;
; Game completion message
L29433:
  DEFB 37                 ; Text length = 37 characters:
  DEFM 24,14,20,26,7,0,21,4,26,10,8,11,11,4,3,27 ; YOU HAVE KILLED/
  DEFM 0,21,4,11,0,2,7,27 ; AVELACH/
  DEFM 11,14,17,3,26,14,5,26,2,7,0,14,18 ; LORD OF CHAOS
; Game start message
  DEFB 51                 ; Text length = 51 characters:
  DEFM 18,4,4,10,26,19,7,4,26,7,8,6,7,27 ; SEEK THE HIGH/
  DEFM 12,0,6,8,2,26,19,14,26,3,4,5,4,0,19,27 ; MAGIC TO DEFEAT/
  DEFM 0,21,4,11,0,2,7,27 ; AVELACH/
  DEFM 11,14,17,3,26,14,5,26,2,7,0,14,18 ; LORD OF CHAOS

; Save game message
;
; See the table of character byte values for a translation of
; letters-to-numbers. 27 = end-of-line
L29523:
  DEFB 27                 ; Text length = 27
  DEFM 18,19,0,17,19,26,19,0,15,4,26,19,7,4,13,27 ; "START TAPE THEN/"
  DEFM 15,17,4,18,18,26,4,13,19,4,17 ; "PRESS ENTER"

; Room objects
;
; The first 8 bytes in each set contain various bits of information about an
; object (e.g. room number, room co-ordinates, colour).
;
; This set is followed by 1-3 sets of 4 bytes. For most objects this is just
; one 4-byte set, but some objects can have multiple states - e.g. chests can
; be closed or open.
;
; Data sets are copied from here into a working room item data buffer at 60293.
;
; +------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | Byte | Contents                                                                                                                                                                                                                                                                                                                                                                                     |
; +------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | 1    | Room number of object                                                                                                                                                                                                                                                                                                                                                                        |
; | 2    | Horizontal (X) position of object in room, in 4-pixel (half-character) steps                                                                                                                                                                                                                                                                                                                 |
; | 3    | Vertical (Y) position of object in room, in pixels, from top of room                                                                                                                                                                                                                                                                                                                         |
; | 4    | Item properties byte (similar to 60238) Bit 1 (2) set = Item is not visible Bit 2 (4) set = Item/creature not subject to standard room boundary collision checks (e.g. BATS) Bit 4 (16) set = Item is being carried by servant Bit 6 (64) set = Maroc can pick up the item                                                                                                                   |
; | 5    | Object state - starts at 1 for each object (e.g. chest state 1 = closed, 2 = open. Each additional state an object has is stored in an extra 4 byte set                                                                                                                                                                                                                                      |
; | 6    | Spell number (= 0 if not a spell) - spell table at L28156 (start counting with MOVE = 0, SERVANT = 1 etc.)                                                                                                                                                                                                                                                                                   |
; | 7    | Attribute/colour of object. If bit 4 is set, the object will flash (change colour constantly) Bits 5-7 contain the item's 'value' when trading with warlocks (see 52857)                                                                                                                                                                                                                     |
; | 8    | Number of additional 4-byte sets for this object                                                                                                                                                                                                                                                                                                                                             |
; | 9    | Movement pattern byte. Used for moving room items (including set room creatures) in the routine at L52136 Bit 0 (1) set = room item/creature has a random element to its movement Bit 1 (2) set = room item/creature will try to home in on Maroc's position Bit 2 (3) set = room item/creature is subject to usual room wall collision detection/adjustment (BATS do not have this bit set) |
; | 10   | Event number for items acting on this item (e.g. for a chest, which is opened by a key)                                                                                                                                                                                                                                                                                                      |
; | 11   | Event number that this item affects (e.g. for a key, that opens a particular chest with matching event number As part of event/collision check, also used for energy-affecting objects, e.g. orbs and mushrooms. 254 = energy drain, 253 = energy replenish                                                                                                                                  |
; | 12   | Graphic number - offset for graphic address table at L38851. Offset calculated using [(n-1)*2] + L38851 A value of 124 (check at L51968) indicates the object is hidden (e.g. inside a chest) so doesn't need drawing on screen                                                                                                                                                              |
; | 13   | ADDITIONAL STATE - ?? (seems to be 128 for healing star, 64 for spells/scrolls/coins )                                                                                                                                                                                                                                                                                                       |
; | 14   | ADDITIONAL STATE - Event number for items acting on this item (e.g. for a chest, which is opened by a key) 15 = items Maroc can pick up (I think)                                                                                                                                                                                                                                            |
; | 15   | ADDITIONAL STATE - Event number that this item affects (e.g. for a key, that opens a particular chest with matching event number As part of event/collision check, also used for energy-affecting objects, e.g. orbs and mushrooms. 254 = energy drain, 253 = energy replenish                                                                                                               |
; | 16   | ADDITIONAL STATE - Graphic number - offset for graphic address table at L38851. Offset calculated using [(n-1)*2] + L38851                                                                                                                                                                                                                                                                   |
; +------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
L29551:
  DEFB 0,0,0,197,1,0,15,1 ; Star symbol - 39143 (from warlock #1)
  DEFB 0,15,26,147        ;
  DEFB 0,0,0,69,1,12,15,1 ; WAYSTONE spell jewel - 38951 (from warlock #2)
  DEFB 0,15,0,51          ;
  DEFB 0,0,0,69,1,13,15,1 ; ICEBOLT spell scroll - 38939 (from warlock #3)
  DEFB 0,15,0,45          ;
  DEFB 0,0,0,69,1,20,15,1 ; WRAITHBANE spell jewel - 38951 (from warlock #4)
  DEFB 0,15,0,51          ;
  DEFB 0,0,0,69,1,22,15,1 ; ELECTRIC spell scroll - 38939 (from warlock #5)
  DEFB 0,15,0,45          ;
  DEFB 0,0,0,69,1,15,15,1 ; FIREBALL spell scroll - 38939 (from warlock #6)
  DEFB 0,15,0,45          ;
  DEFB 0,0,0,69,1,24,15,1 ; FLAME spell scroll - 38939 (from warlock #7)
  DEFB 0,15,0,45          ;
  DEFB 2,48,56,5,1,0,7,2         ; Room 2 - Healing STAR symbol on floor in
  DEFB 0,26,0,146,128,15,253,185 ; room 2 - 39141 (inactive) 39219 (active)
  DEFB 6,32,53,69,1,5,63,1 ; Room 6 - ENERGIZE spell scroll - 38939
  DEFB 0,15,0,45           ;
  DEFB 8,20,64,69,1,16,39,1 ; Room 8 - FREEZE spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 15,42,53,69,1,16,36,1 ; Room 15 - FREEZE spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 10,19,55,69,1,1,6,1 ; Room 10 - SERVANT spell - ring - 38947
  DEFB 0,15,0,49           ;
  DEFB 16,32,53,5,1,0,6,2   ; Room 16 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,5,0,135,0,15,0,136 ;
  DEFB 16,32,53,2,1,5,63,2  ; Room 16 - ENERGIZE spell scroll (in chest) -
  DEFB 0,5,0,124,64,15,0,45 ; 38939
  DEFB 20,24,58,5,1,0,3,2    ; Room 20 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,60,0,135,0,15,0,136 ;
  DEFB 20,24,58,2,1,0,38,2    ; Room 20 - Coins (in chest) - 39145
  DEFB 0,60,0,124,64,15,0,148 ;
  DEFB 21,24,32,197,1,0,7,1 ; Room 21 - Key - 39117
  DEFB 0,15,60,134          ;
  DEFB 22,50,32,69,1,5,63,1 ; Room 22 - ENERGIZE spell scroll - 38939)
  DEFB 0,15,0,45            ;
  DEFB 24,40,58,5,1,0,4,2    ; Room 24 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,60,0,135,0,15,0,136 ;
  DEFB 24,40,58,2,1,0,22,2      ; Room 24 - Key (in chest) - 39139
  DEFB 0,60,0,124,192,15,12,145 ;
  DEFB 27,35,58,69,1,5,63,1 ; Room 27 - ENERGIZE spell scroll - 38939)
  DEFB 0,15,0,45            ;
  DEFB 29,50,64,197,1,0,3,1 ; Room 29 - Fish - 39147
  DEFB 0,15,254,149         ;
  DEFB 83,42,56,69,1,9,55,1 ; Room 83 - UNSEEN spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 85,42,64,5,1,0,4,1 ; Room 85 - Bottle - 39149
  DEFB 0,15,0,150         ;
  DEFB 85,42,64,2,1,0,4,2      ; Room 85 - Key (in bottle) - 39117
  DEFB 0,5,0,124,192,15,64,134 ;
  DEFB 85,24,56,5,1,0,0,2    ; Room 85 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,64,0,135,0,15,0,136 ;
  DEFB 85,24,56,2,1,0,54,2    ; Room 85 - Coins (in chest) - 39145
  DEFB 0,64,0,124,64,15,0,148 ;
  DEFB 91,35,32,69,1,27,54,1 ; Room 91 - MESSAGE spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 94,26,56,69,1,9,79,1 ; Room 94 - UNSEEN spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 95,36,58,5,1,0,5,2   ; Room 95 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,9,0,135,0,15,0,136 ;
  DEFB 95,36,58,2,1,0,5,2      ; Room 95 - Key - 39139
  DEFB 0,9,0,124,192,15,44,145 ;
  DEFB 96,32,56,133,1,0,3,1 ; Room 96 - Healing mushrooms - 39151
  DEFB 0,15,253,151         ;
  DEFB 97,34,56,5,1,0,4,2   ; Room 97 - Bottle - 39149
  DEFB 0,9,0,150,0,15,0,138 ;
  DEFB 97,34,56,2,1,0,6,3      ; Room 97 - Scorpion (in bottle) - 39153
  DEFB 0,9,0,124,131,3,254,152 ;
  DEFB 0,15,0,124              ;
  DEFB 99,52,64,69,1,16,71,1 ; Room 99 - FREEZE spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 100,24,64,69,1,2,54,1 ; Room 100 - SHIELD spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 102,36,24,197,1,0,6,1 ; Room 102 - Axe - 39157
  DEFB 0,15,9,154            ;
  DEFB 103,32,48,69,1,5,53,1 ; Room 103 - ENERGIZE spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 104,16,32,69,1,4,15,1 ; Room 104 - MISSILE spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 110,26,58,133,1,0,70,2  ; Room 110 - Jewel - 38951 (give to Warlock for
  DEFB 0,17,254,125,64,15,0,51 ; ICEBOLT spell)
  DEFB 111,32,64,133,1,0,6,1 ; Room 111 - Scorpion - 39153
  DEFB 131,15,254,152        ;
  DEFB 112,28,56,69,1,16,7,1 ; Room 112 - FREEZE spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 116,42,56,69,1,9,79,1 ; Room 116 - UNSEEN spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 120,16,68,133,1,0,3,1 ; Room 120 - Mushrooms (energy drain) - 39151
  DEFB 0,15,254,151          ;
  DEFB 121,35,50,69,1,5,7,1 ; Room 121 - ENERGIZE spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 124,16,64,5,1,0,4,2  ; Room 124 - Boulder - 39081 - use pick (39127)
  DEFB 0,9,0,116,8,15,0,116 ;
  DEFB 124,16,64,5,1,10,15,2 ; Room 124 - OPEN spell scroll (under boulder) -
  DEFB 0,9,0,124,64,15,0,45  ; 38939
  DEFB 126,26,52,197,1,0,7,1 ; Room 126 - Pick - 39127 - use on boulder to get
  DEFB 0,15,9,139            ; OPEN spell
  DEFB 128,19,56,5,1,0,4,1 ; Room 128 - Pool - 39091
  DEFB 0,15,0,121          ;
  DEFB 128,19,56,6,1,17,15,2 ; Room 128 - SUMMON spell jewel (in pool) - 38951
  DEFB 0,5,0,124,64,15,0,51  ;
  DEFB 130,24,24,69,1,2,7,1 ; Room 130 - SHIELD spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 31,32,64,69,1,4,70,1 ; Room 31 - MISSILE spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 33,56,64,69,1,21,71,1 ; Room 33 - DISPEL spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 34,40,56,69,1,5,71,1 ; Room 34 - ENERGIZE spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 38,24,32,5,1,0,15,2     ; Room 38 - Bone - 39159 - use DISPEL for
  DEFB 0,2,0,155,192,15,28,145 ; flashing key - 39139
  DEFB 39,20,56,69,1,9,71,1 ; Room 39 - UNSEEN spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 39,26,67,69,1,8,70,1 ; Room 39 - HAIL spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 40,34,64,133,1,0,15,1 ; Room 40 - Energy orb - 39161
  DEFB 0,15,253,156          ;
  DEFB 43,24,64,5,1,0,15,2  ; Room 43 - Spider - 39099 - use DISPEL to reveal
  DEFB 0,2,0,125,0,15,0,136 ; (open) chest - 39121
  DEFB 43,24,64,2,1,6,7,2   ; Room 43 - FIREBOLT spell scroll (in chest) -
  DEFB 0,2,0,124,64,15,0,45 ; 38939
  DEFB 43,24,64,2,1,11,6,2  ; Room 43 - PROTECT spell scroll (in chest) - 38939
  DEFB 0,2,0,124,64,15,0,45 ;
  DEFB 44,32,56,197,1,0,4,1 ; Room 44 - Pick - 39127
  DEFB 0,15,9,139           ;
  DEFB 45,26,66,5,1,0,5,2   ; Room 45 - Bottle (buried) - 39123 (intact) &
  DEFB 0,9,0,137,0,15,0,138 ; 39125 (broken)
  DEFB 45,26,66,5,1,0,6,2      ; Room 45 - Yellow key - 39117 (use pick on
  DEFB 0,9,0,124,192,15,24,134 ; buried bottle)
  DEFB 46,24,64,5,1,0,6,2    ; Room 46 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,24,0,135,0,15,0,136 ;
  DEFB 46,24,64,2,1,0,70,2    ; Room 46 - Coins (in chest) - 39145 (use yellow
  DEFB 0,24,0,124,64,15,0,148 ; key)
  DEFB 49,20,58,197,1,0,6,1 ; Room 49 - Cheese (39129)
  DEFB 0,15,48,140          ;
  DEFB 50,58,32,5,1,0,7,2       ; Room 50 - Key (hanging) - 39137 & normal -
  DEFB 0,52,0,144,200,15,40,145 ; 39139
  DEFB 53,24,44,5,1,0,4,1 ; Room 53 - Mouse hole - 39131
  DEFB 0,15,0,141         ;
  DEFB 53,24,44,2,1,0,7,2       ; Room 53 - Mouse - 39165 - use cheese on mouse
  DEFB 0,48,0,124,193,15,52,158 ; hole to reveal
  DEFB 134,25,32,69,1,18,7,1 ; Room 134 - DEFENCE spell jewel - 38951
  DEFB 0,15,0,51             ;
  DEFB 136,26,53,5,1,0,6,2   ; Room 136 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,68,0,135,0,15,0,136 ;
  DEFB 136,26,53,6,1,19,7,2  ; Room 136 - PORTAL spell scroll - 38939
  DEFB 0,68,0,124,64,15,0,45 ;
  DEFB 137,32,51,5,1,0,3,2   ; Room 137 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,72,0,135,0,15,0,136 ;
  DEFB 137,32,51,6,1,0,7,2   ; Room 137 - Key (in chest) - 39117
  DEFB 0,72,0,124,0,15,0,136 ;
  DEFB 137,32,51,6,1,0,7,2      ; Room 137 - (Duplicate entry)
  DEFB 0,72,0,124,192,15,68,134 ;
  DEFB 139,25,57,5,1,0,7,1 ; Room 139 - Skeleton - 39063
  DEFB 0,15,0,107          ;
  DEFB 139,25,57,6,1,0,7,2     ; Room 139 - Key (in skeleton) - 39117
  DEFB 0,5,0,124,192,15,72,134 ;
  DEFB 142,20,16,141,1,0,3,2 ; Room 142 - Spider - 39099 - when killed reveals
  DEFB 10,9,3,125,0,15,0,45  ; uncollectable scroll - 38939 - see Bugs
  DEFB 143,34,56,69,1,4,6,1 ; Room 143 - MISSILE spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 144,48,16,69,1,4,6,1 ; Room 144 - MISSILE spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 149,24,56,5,1,0,7,1 ; Room 149 - Skeleton - 39063
  DEFB 0,15,0,107          ;
  DEFB 149,24,56,6,1,7,7,2   ; Room 149 - REVEAL spell scroll (in skeleton) -
  DEFB 0,5,0,124,192,15,0,45 ; 38939
  DEFB 150,22,16,5,1,26,15,2 ; Room 150 - CHALICE spell - 38945 (use REVEAL
  DEFB 0,16,0,124,64,15,0,48 ; spell on wall)
  DEFB 155,52,56,5,1,9,15,2 ; Room 155 - Wraith - 39013 - DISPEL to obtain
  DEFB 0,2,0,82,64,15,0,45  ; UNSEEN spell scroll - 38939
  DEFB 157,48,16,69,1,10,7,1 ; Room 157 - OPEN spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 158,20,60,5,1,0,0,2  ; Room 158 - Trapdoor - 39181 (closed) 39183 (open)
  DEFB 0,5,0,166,0,15,0,167 ;
  DEFB 158,20,60,6,1,0,7,3     ; Room 158 - Spider (under trapdoor) - 39099
  DEFB 0,5,0,124,130,3,254,125 ;
  DEFB 0,15,0,124              ;
  DEFB 158,20,52,6,1,0,6,2     ; Room 158 - Key (under trapdoor) - 39139
  DEFB 0,5,0,124,192,15,76,145 ;
  DEFB 159,32,60,5,1,0,0,2   ; Room 159 - Trapdoor - 39181 (closed) 39183
  DEFB 0,76,0,166,0,15,0,167 ; (open)
  DEFB 159,32,60,5,1,0,15,2      ; Room 159 - Healing orb - 39161 (under
  DEFB 0,76,0,124,136,15,253,156 ; trapdoor)
  DEFB 162,32,32,133,1,3,3,2  ; Room 162 - Bat - 39103 - destroy to get UNLOCK
  DEFB 7,9,254,127,64,15,0,45 ; spell scroll - 38939
  DEFB 161,20,8,141,1,0,3,2   ; Room 161 - Spider - 39099
  DEFB 2,3,254,125,0,15,0,124 ;
  DEFB 164,8,8,141,1,0,3,2    ; Room 164 - Spider - 39099
  DEFB 2,3,254,125,0,15,0,124 ;
  DEFB 165,36,16,69,1,25,7,1 ; Room 165 - FIND spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 166,36,24,197,1,0,6,1 ; Room 166 - Sabre - 39163
  DEFB 0,15,9,157            ;
  DEFB 168,26,24,5,1,0,15,1 ; Room 168 - Lady - 39185
  DEFB 0,15,0,168           ;
  DEFB 170,20,16,5,1,0,15,2  ; Room 170 - Caliburn (use FIND spell) - 38941
  DEFB 0,8,0,124,192,15,7,46 ;
  DEFB 170,32,52,133,1,0,6,2  ; Room 170 - Scorpion - 39153
  DEFB 2,3,254,152,0,15,0,124 ;
  DEFB 176,36,32,69,1,5,7,1 ; Room 176 - ENERGIZE spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 179,20,52,5,1,0,6,2  ; Room 179 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,4,0,135,0,15,0,136 ;
  DEFB 179,20,52,6,1,0,6,3     ; Room 179 - Left half of key (in chest) - 39187
  DEFB 0,4,0,124,192,84,80,169 ;
  DEFB 64,15,0,145             ;
  DEFB 179,20,52,6,1,3,15,2 ; Room 179 - UNLOCK spell scroll (in chest) - 38939
  DEFB 0,4,0,124,64,15,0,45 ;
  DEFB 181,36,52,5,1,0,7,2  ; Room 181 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,4,0,135,0,15,0,136 ;
  DEFB 181,36,52,6,1,0,6,3   ; Room 181 - Right half of key (in chest) - 39189
  DEFB 0,4,0,124,64,80,0,170 ;
  DEFB 192,15,84,145         ;
  DEFB 183,34,56,5,1,0,6,3   ; Room 183 - Chest - 39119 (closed) 39121 (open) -
  DEFB 0,88,0,135,0,92,0,135 ; requires two keys
  DEFB 0,15,0,136            ;
  DEFB 183,34,56,6,1,0,6,3   ; Room 183 - Key (in chest) - 39139
  DEFB 0,88,0,124,0,92,0,124 ;
  DEFB 192,15,96,145         ;
  DEFB 184,20,58,5,1,0,7,1 ; Room 184 - Skull pile - 39085
  DEFB 0,0,15,118          ;
  DEFB 184,20,58,6,1,0,6,2     ; Room 184 - Key (under skulls) - 39117
  DEFB 0,5,0,124,192,15,88,134 ;
  DEFB 185,35,24,197,1,0,6,1 ; Room 185 - Key - 39117
  DEFB 0,15,92,134           ;
  DEFB 186,32,24,69,1,23,7,1 ; Room 186 - VAPORIZE spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 187,22,24,69,1,24,6,1 ; Room 187 - FLAME spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 188,32,58,133,1,0,15,1 ; Room 188 - Orb (energy drain) - 39161
  DEFB 0,15,254,156           ;
  DEFB 189,64,56,5,1,0,3,2    ; Room 189 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,100,0,135,0,15,0,136 ;
  DEFB 189,64,56,6,1,16,7,2   ; Room 189 - FREEZE spell scroll (in chest) -
  DEFB 0,100,0,124,64,15,0,45 ; 38939
  DEFB 190,36,58,133,1,0,15,1 ; Room 190 - Orb (healing) - 39161
  DEFB 0,15,253,156           ;
  DEFB 192,16,8,141,1,0,3,2     ; Room 192 - Spider - 39099
  DEFB 130,3,254,125,0,15,0,124 ;
  DEFB 194,32,24,197,1,0,6,1 ; Room 194 - Oil jar - 39191
  DEFB 0,15,100,171          ;
  DEFB 196,24,56,5,1,0,16,1 ; Room 196 - Skeleton - 39063
  DEFB 0,15,0,107           ;
  DEFB 196,24,56,6,1,0,6,2      ; Room 196 - Key (in skeleton) - 39139
  DEFB 0,5,0,124,192,15,104,145 ;
  DEFB 204,24,56,69,1,19,6,1 ; Room 204 - PORTAL spell scroll - 38939
  DEFB 0,15,0,45             ;
  DEFB 208,24,60,5,1,0,0,2    ; Room 208 - Trapdoor - 39181 (closed) 39183
  DEFB 0,104,0,166,0,15,0,167 ; (open)
  DEFB 208,24,60,6,1,14,15,2  ; Room 208 - AMULET spell (under trapdoor) -
  DEFB 0,104,0,124,64,15,0,47 ; 38943
  DEFB 56,49,56,5,1,0,6,2     ; Room 56 - Chest - 39119 (closed) 39121 (open)
  DEFB 0,108,0,135,0,15,0,136 ;
  DEFB 56,49,56,6,1,0,6,2         ; Room 56 - Coin (in chest) - 39193
  DEFB 0,108,0,124,192,15,112,172 ;
  DEFB 57,27,24,197,1,0,7,3      ; Room 57 - Sabre (animated) - 39173
  DEFB 0,1,254,157,131,5,254,162 ;
  DEFB 193,15,3,162              ;
  DEFB 55,24,58,5,1,0,6,1 ; Room 55 - Altar - 39195
  DEFB 0,15,0,173         ;
  DEFB 55,24,56,5,1,0,7,2        ; Room 55 - Key (place coin on altar)- 39139
  DEFB 0,112,0,124,200,15,32,145 ;
  DEFB 63,24,58,133,1,0,6,1 ; Room 63 - Fire - 39197
  DEFB 0,15,254,174         ;
  DEFB 63,24,58,198,1,0,6,2     ; Room 63 - Fire symbol (in fire) - 39201 -
  DEFB 0,140,116,176,0,15,0,184 ; blank after use - 39217
  DEFB 64,36,16,197,1,0,3,2     ; Room 64 - Air symbol - 39207 - blank after
  DEFB 0,144,120,179,0,15,0,184 ; use - 39217
  DEFB 64,32,24,133,1,0,3,2   ; Room 64 - Bat - 39103
  DEFB 7,3,254,127,0,15,0,124 ;
  DEFB 68,26,32,69,1,5,6,1 ; Room 68 - ENERGIZE spell scroll - 38939
  DEFB 0,15,0,45           ;
  DEFB 69,26,64,133,1,0,5,2   ; Room 69 - Spider - 39099
  DEFB 2,3,254,125,0,15,0,124 ;
  DEFB 69,24,58,6,1,0,5,3          ; Room 69 - Water symbol (in pool) - 39203 -
  DEFB 0,5,208,124,192,148,124,177 ; blank after use - 39217
  DEFB 0,15,0,184                  ;
  DEFB 69,24,58,5,1,0,5,1 ; Room 69 - Pool - 39091
  DEFB 0,15,0,121         ;
  DEFB 72,20,58,133,1,0,7,1 ; Room 72 - Skull pile - 39085
  DEFB 0,15,254,118         ;
  DEFB 72,20,58,6,1,0,6,3    ; Room 72 - Scorpion (under skull pile) - 39153
  DEFB 0,5,0,124,2,3,254,152 ;
  DEFB 0,15,0,124            ;
  DEFB 72,26,56,133,1,0,7,1 ; Room 72 - Skull pile - 39085
  DEFB 0,15,254,118         ;
  DEFB 72,26,56,6,1,0,6,2       ; Room 72 - Key (under skull pile) - 39117
  DEFB 0,5,0,124,192,15,108,134 ;
  DEFB 75,36,52,197,1,0,3,1 ; Room 75 - Pick axe - 39209
  DEFB 0,15,128,180         ;
  DEFB 76,26,60,5,1,0,0,2     ; Room 76 - Trapdoor - 39181 (closed) 39183
  DEFB 0,128,0,166,0,15,0,167 ; (open)
  DEFB 76,26,60,6,1,0,6,3        ; Room 76 - Scorpion (under trapdoor) - 39153
  DEFB 0,128,0,124,130,3,254,152 ;
  DEFB 0,15,0,124                ;
  DEFB 76,26,60,6,1,0,6,3          ; Room 76 - Earth symbol (under trapdoor) -
  DEFB 0,128,0,124,192,136,132,178 ; 39205 - blank after use - 39217
  DEFB 0,15,0,184                  ;
  DEFB 77,48,56,133,1,0,15,1 ; Room 77 - Healing fire - 39197
  DEFB 0,15,253,174          ;
  DEFB 80,26,16,69,1,16,7,1 ; Room 80 - FREEZE spell scroll - 38939
  DEFB 0,15,0,45            ;
  DEFB 81,32,58,5,1,0,15,5             ; Room 81 - Portal - floor symbol -
  DEFB 0,116,0,181,128,120,140,181     ; 39211 - becomes door - 39213
  DEFB 128,124,144,181,128,132,148,181 ;
  DEFB 128,15,136,182                  ;
  DEFB 212,84,58,5,1,0,15,2     ; Room 212 - Avelach, Lord of Chaos - 39215
  DEFB 0,7,0,183,128,15,137,183 ;
  DEFB 255,255,255,255,202 ; End-of-data bytes to signify end of room data

; Unidentified code (unused)
;
; The following code fragment is not used in the game
L31700:
  LD A,(60240)
  LD C,A
  AND 1
  JP Z,53890
  LD A,C
  AND 8
  JP Z,51970
  LD A,(60081)
  CP 248
  JR Z,L31700_0
  CP 232
  JR Z,L31700_1
  LD A,248
  JR L31700_2
L31700_0:
  LD A,12
  JR L31700_2
L31700_1:
  LD A,8
L31700_2:
  LD B,A
  LD A,(60117)
  ADD A,B
  LD D,A
  DEFB 58,212

; Launch the initial game menus
;
; Used by the routine at L48922.
;
; This CALL launches:
; * Menu 1 - to select game controls
; * Menu 2 - to choose a new game or load a saved game
L31744:
  CALL L32825

; Draw decorative screen border graphics
;
; This routine follows the menu selection and draws the decorative border
; graphics around the main screen play area using the graphics tiles at L33818.
;
; The routine that follows at L31917 adds the colours.
;
; Draw top two rows of decorative screen border
L31747:
  LD A,2                  ; Number of character rows (2)
  LD (35760),A            ;
  LD A,32                 ; Start in top left of screen display
  LD (35759),A            ; Number of columns (32)
  LD HL,16384             ;
  LD DE,L33818            ; Start of graphics
  CALL L33267             ; Draw onto screen
; Draw left-hand column of decorative border (2 character columns, 14 rows)
  LD A,2                  ; Number of columns (2)
  LD (35759),A            ;
  LD A,14                 ; Number of character rows (14)
  LD (35760),A            ;
  LD DE,34330             ; Start of graphics data for this section
  LD HL,16448             ; Set screen display address to starting position
  CALL L33267             ; Draw onto screen
; Draw bottom left third of screen (devil and left-hand side of scroll)
  LD A,7                  ; 7 columns
  LD (35759),A            ;
  LD A,8                  ; 8 character rows
  LD (35760),A            ;
  LD DE,34554             ; Start of graphics data for this section
  LD HL,20480             ; Set screen display to starting position
  CALL L33267             ; Draw onto screen
; Draw right-hand column of decorative border (2 character columns, 14 rows)
  LD A,2                  ; Number of columns (2)
  LD (35759),A            ;
  LD A,14                 ; Number of character rows (14)
  LD (35760),A            ;
  LD DE,35002             ; Start of graphics data for this section
  LD HL,16478             ; Set screen display to starting position
  CALL L33267             ; Draw onto screen
; Draw decorative scroll in bottom third of screen
  LD A,18                 ; 18 columns
  LD HL,20487             ; Set and store screen display starting draw position
  LD (35757),HL           ;
  LD (35756),A            ; Store column counter (18)
L31747_0:
  LD DE,35226             ; Point to start of scroll graphics data
; The scroll is composed of 18 columns composed of the same 1 x 8 (character)
; column pattern
  LD A,1                  ; Store number of columns (1)
  LD (35759),A            ;
  LD A,8                  ; Store number of character rows (8)
  LD (35760),A            ;
  LD HL,(35757)           ; Retrieve screen display address to draw at
  CALL L33267             ; Draw on screen
  LD A,(35756)            ; Column drawn, so reduce column counter by 1
  DEC A                   ; If all 18 columns are done, jump to next section
  JR Z,L31747_1           ;
  LD (35756),A            ; Re-store column counter
  LD HL,(35757)           ; Retrieve display screen address pointer
  INC HL                  ; Move it one character to the right...
  LD (35757),HL           ; ...and store it
  JR L31747_0             ; Continue onto next column
; Tiny manual graphic tweak to bottom right of scroll (2 bytes)
L31747_1:
  LD HL,22487             ; Screen display address position
  LD (HL),7               ;
  INC HL                  ; ...and the one to its right.
  LD (HL),255             ;
; Small scroll overlap in bottom right
  LD HL,20727             ; Set screen display to starting position
  LD DE,35738             ; Point to start of graphics data
  LD A,2                  ; Number of columns (2)
  LD (35759),A            ;
  LD A,1                  ; Number of character rows (1)
  LD (35760),A            ;
  CALL L33267             ; Draw onto screen
; Graphics for bottom third of screen, right hand side (angel and right-hand
; edge of scroll) - 8 rows x 7 columns
  LD A,7                  ; Number of columns (7)
  LD (35759),A            ;
  LD A,8                  ; Number of character rows (8)
  LD (35760),A            ;
  LD DE,35290             ; Point to start of graphics data
  LD HL,20505             ; Set screen display to starting position
  CALL L33267             ; Draw onto screen

; Draw game screen decorative border (colours)
;
; The previous drawing routine at L31747 has only drawn the graphic pixels. The
; following set of routines adds the colours.
;
; The majority of the game border is yellow, so initially the whole screen is
; set to this colour (INK 0, PAPER 6).
L31917:
  LD HL,22528             ; Start of screen display attribute area (top left)
  LD B,0                  ; This will run the routine 256 times (first
                          ; iteration will DEC B which puts it at 255)
L31917_0:
  LD (HL),48              ; Set byte to INK 0, PAPER 6.
  INC HL                  ; ...and the next one...
  LD (HL),48              ;
  INC HL                  ; ...and also a third one...
  LD (HL),48              ;
  INC HL                  ;
  DJNZ L31917_0           ; Repeat until whole screen covered (256 x 3 = 768
                          ; bytes)
; There's an inner green rectangular border inside the decorative border area
; (pixels not drawn yet). This section sets that rectangle to green (INK 4,
; PAPER 0).
  LD HL,22594
  LD C,14                 ; Number of character rows to colour (14)
L31917_1:
  LD B,28                 ; Number of columns to colour (28)
L31917_2:
  LD (HL),4               ; Set colour to green (INK 4, PAPER 0)
  INC HL                  ; Move to next attribute square
  DJNZ L31917_2           ; Repeat for 28 columns
  INC HL                  ; Advance 4 squares to get to the next row
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  DEC C                   ; Repeat for 14 rows
  JR NZ,L31917_1          ;
; Some other attributes to set in the border; first, green colour for 2 spaces
; of the dragon head in the top right of the screen
  LD HL,22556
  LD (HL),32              ; INK 0, PAPER 4
  INC HL                  ;
  LD (HL),32              ;
  LD HL,22589             ; ...and the square below
  LD (HL),32              ;
; Next, the strip of rightmost two columns for the first 12 screen character
; rows
  LD HL,22558
  LD B,12                 ; 12 rows
  LD DE,30                ; Offset ready to add to move down to the next
                          ; character line
L31917_3:
  LD (HL),32              ; Set the two attributes to green
  INC HL                  ;
  LD (HL),32              ; INK 0, PAPER 4
  INC HL                  ;
  ADD HL,DE               ; Move down to the next row
  DJNZ L31917_3           ; Repeat for the 12 rows
; Strip of 3 cyan attributes for the dragon's belly in the right column
  LD HL,22686
  LD (HL),40              ; INK 0, PAPER 5
  LD HL,22718             ;
  LD (HL),40              ;
  LD HL,22750             ;
  LD (HL),40              ;
; Colour the winged skull at the top of the screen in magenta
  LD HL,22538
  LD B,12                 ; 12 columns
L31917_4:
  LD (HL),24              ; INK 0, PAPER 3
  INC HL                  ; Move along the next square and repeat 12 times
  DJNZ L31917_4           ;
  LD HL,22569             ; Repeat for the second row of the winged skull
  LD B,14                 ; A couple more squares (14) for this line
L31917_5:
  LD (HL),24              ; INK 0, PAPER 3
  INC HL                  ;
  DJNZ L31917_5           ;
; The above routine has also covered the skull between the wings magenta. So
; we'll re-colour it white:
  LD HL,22543             ; Display attribute address for skull in middle of
                          ; top border
  LD (HL),56              ; Colour the next two squares white (INK 0, PAPER 7)
  INC HL                  ;
  LD (HL),56              ;
  LD HL,22575             ; Do the same for the second row of the skull
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
  INC HL                  ; (this instruction is not needed)
; Set the whole of the far left column (snake & pillar) green, starting 1
; character down (below the skull)
  LD HL,22560             ; Starting point in screen display attributes
  LD B,23                 ; 23 rows
  LD DE,32                ; Offset ready to add to jump to the next character
                          ; row
L31917_6:
  LD (HL),32              ; INK 0, PAPER 4
  ADD HL,DE               ; Jump to the next row and repeat (23 rows)
  DJNZ L31917_6           ;
; Yellow bit of snake's tail midway down the screen, left column:
  LD HL,22912
  LD (HL),48              ; INK 0, PAPER 6
; Left column, square immediately to the right of the top of the devil's wing,
; set to green colour:
  LD HL,22945
  LD (HL),32              ; For consistency this value should probably be 48 -
  LD HL,22530             ; yellow (INK 0, PAPER 6) - as the rest of the right
                          ; hand side of this pillar is yellow
; Snake (green) and mini-spider (cyan) in top left of screen
  LD (HL),32              ; INK 0, PAPER 4 (green) for the first two blocks
  INC HL                  ;
  LD (HL),32              ;
  INC HL                  ;
  LD (HL),40              ; INK 0, PAPER 5 (cyan) for the small spider
  INC HL                  ;
  LD (HL),32              ; ...then back to green for the last two blocks of
  INC HL                  ; the snake's head
  LD (HL),32              ;
; Two squares of the bottom of the snake's head (green)
  LD HL,22565
  LD (HL),32              ; INK 0, PAPER 4
  INC HL                  ;
  LD (HL),32              ;
; Two squares for skull in top left of screen (white)
  LD HL,22528
  LD (HL),56              ; INK 0, PAPER 7 (white)
  INC HL                  ;
  LD (HL),56              ;
; 4 red character squares in the fire breathed by the dragon in the top right
; of the screen
  LD HL,22551
  LD (HL),16              ; INK 0, PAPER 2
  LD HL,22585             ;
  LD (HL),16              ;
  LD HL,22553             ;
  LD (HL),16              ;
  LD HL,22587             ;
  LD (HL),16              ;
; 7 red character squares in the devil's wing that overlaps the left column
  LD HL,22944
  LD (HL),16
  LD HL,22976
  LD (HL),16
  INC HL
  LD (HL),16
  LD HL,23008
  LD (HL),16
  INC HL
  LD (HL),16
  LD HL,23040
  LD (HL),16
  INC HL
  LD (HL),16
; ...And red squares for the rest of the devil - 6 rows x 3 characters
  INC HL                  ; Move to starting position
  LD B,6                  ; 6 rows
  LD DE,29                ; 29 spaces - offset to allow moving to position in
                          ; next line (plus 3 squares filled = 32)
L31917_7:
  LD (HL),16              ; INK 0, PAPER 2 (red) for 3 squares
  INC HL                  ;
  LD (HL),16              ;
  INC HL                  ;
  LD (HL),16              ;
  INC HL                  ;
  ADD HL,DE               ; Add offset to move attribute display address to
                          ; next line
  DJNZ L31917_7           ; Repeat colouring for the 6 rows of the devil
  LD HL,23073             ; ...And red for the last bit of devil wing
  LD (HL),16              ; overlapping the pillar
; 4 character squares of white for the bottom of the word 'MAGIC' in the bottom
; left corner
  LD HL,23266
  LD (HL),56              ; INK 0, PAPER 7 (white)
  INC HL                  ;
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
; Strip of 20 white attribute squares for the very top of the scroll
  LD HL,23046
  LD B,20                 ; 20 squares to colour
L31917_8:
  LD (HL),56              ; INK 0, PAPER 7 (white)
  INC HL                  ; Move right to next square
  DJNZ L31917_8           ; Repeat for all 20
; A bunch of white squares for the angel in the bottom right of the screen
  LD HL,23068
  LD (HL),56              ; INK 0, PAPER 7 (white)
  LD HL,22975             ;
  LD (HL),56              ;
  LD HL,23007             ;
  LD (HL),56              ;
  LD HL,23038             ;
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
  LD HL,23053             ; The next 3 squares are in the top of the scroll
  LD (HL),56              ; which has already been coloured in 32176, so the
  INC HL                  ; code for colouring these 3 squares is unnecessary
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
  LD HL,23069             ; Other various white squares for the angel
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
  LD HL,23101             ;
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
  LD HL,23133             ;
  LD (HL),56              ;
  INC HL                  ;
  LD (HL),56              ;
; A couple of cyan squares in the 'wispy bits' to the left of the angel:
  LD HL,23195
  LD (HL),40              ; INK 0, PAPER 5 (cyan)
  LD HL,23226             ;
  LD (HL),40              ;
  INC HL                  ; ...and a couple of green ones between them
  LD (HL),32              ; INK 0, PAPER 4 (green)
  LD HL,23258             ;
  LD (HL),32              ;
; ...and a few more cyan & green squares to the right of the angel
  LD HL,23103
  LD DE,32                ; Offset of 32 spaces to add to display address to
                          ; move to line below
  LD (HL),40              ; INK 0, PAPER 5 (cyan)
  ADD HL,DE               ; ADD HL, DE moves the screen display address down
  LD (HL),40              ; one character square
  ADD HL,DE               ;
  LD (HL),40              ;
  ADD HL,DE               ;
  LD (HL),32              ; INK 0, PAPER 4 (green)
  ADD HL,DE               ;
  LD (HL),32              ;
  ADD HL,DE               ;

; Draw the inner border for the intro sequence
;
; After drawing the decorative border, this routine draws the rectangular
; 'spiky' border at the edge of the picture that you can see during the intro
; sequence.
;
; Graphics for the border and backdrop are stored at L33375.
;
; The border on the left hand side of the screen is drawn first:
L32289:
  LD A,1                  ; 1 column
  LD (35759),A            ;
  LD A,12                 ; 12 rows
  LD (35760),A            ;
  LD HL,L33375            ; Address pointer for left-hand border graphic
  LD (L31917_2),HL        ; Store the border graphic address. This appears to
                          ; be overwriting earlier code. However, this code
                          ; that's overwritten is part of the decorative border
                          ; which is already drawn, so doesn't need to be
                          ; executed again.
  LD HL,16482             ; Set screen display address
  CALL L33319             ; Drawing routine (to draw the graphic 12 times in a
                          ; vertical line)
; ...Then the border on the right hand side
  LD A,1                  ; 1 column
  LD (35759),A            ;
  LD A,12                 ; 12 rows
  LD (35760),A            ;
  LD HL,33407             ; Address pointer for right-hand border graphic
  LD (L31917_2),HL        ; Store the border graphic address. This looks like a
                          ; mistake as it seems to be overwriting earlier code
                          ; at L31917_2. However, this code is part of the
                          ; decorative border drawing so doesn't need to be
                          ; executed again.
  LD HL,16509             ; Set screen address
  CALL L33319             ; Drawing routine (to draw the graphic 12 times in a
                          ; vertical line)
; Draw the top right 'corner piece' of the border
  LD A,1                  ; Just 1 character (1 row, 1 column)
  LD (35759),A            ;
  LD A,1                  ;
  LD (35760),A            ;
  LD HL,33415             ; Store address of top right-hand corner graphic
  LD (L31917_2),HL        ;
  LD HL,16477             ; Set screen display address
  CALL L33319             ; Draw the graphic
; Draw the bottom left 'corner piece' of the border
  LD A,1                  ; Just 1 character (1 row, 1 column)
  LD (35759),A            ;
  LD A,1                  ;
  LD (35760),A            ;
  LD HL,33383             ; Store address of bottom left-hand corner graphic
  LD (L31917_2),HL        ;
  LD HL,18658             ; Set screen display address
  CALL L33319             ; Draw the graphic
; Draw the bottom right 'corner piece' of the border
  LD A,1                  ; Just 1 character (1 row, 1 column)
  LD (35759),A            ;
  LD A,1                  ;
  LD (35760),A            ;
  LD HL,33399             ; Store address of bottom right-hand corner graphic
  LD (L31917_2),HL        ;
  LD HL,18685             ; Set screen display address
  CALL L33319             ; Draw the graphic
; Draw bottom border
  LD A,26                 ; 26 columns to draw
  LD (35759),A            ;
  LD A,1                  ; 1 row
  LD (35760),A            ;
  LD HL,33423             ; Store address of bottom border graphic
  LD (L31917_2),HL        ;
  LD HL,16451             ; Set screen display address
  CALL L33319             ; Draw the border
; Draw top border
  LD A,26                 ; 26 columns to draw
  LD (35759),A            ;
  LD A,1                  ; 1 row
  LD (35760),A            ;
  LD HL,33391             ; Store address of bottom border graphic
  LD (L31917_2),HL        ;
  LD HL,18659             ; Set screen display address
  CALL L33319             ; Draw the border
; Draw the top left 'corner piece' of the border
  LD A,1                  ; Just 1 character (1 row, 1 column)
  LD (35759),A            ;
  LD A,1                  ;
  LD (35760),A            ;
  LD HL,33431             ; Store address of top left-hand corner graphic
  LD (L31917_2),HL        ;
  LD HL,16450             ; Set screen display address
  CALL L33319             ; Draw the graphic
; Now set the colours (dark blue) to the top 6 lines of the 'inner screen'
; (including the border)
  LD HL,22594             ; Set the display address position on screen (top
                          ; left)
  LD C,6                  ; 6 rows to colour
L32289_0:
  LD B,28                 ; 28 columns across the screen
L32289_1:
  LD (HL),8               ; Set colour of block to blue (INK 0, PAPER 1)
  INC HL                  ; Move right to the next square
  DJNZ L32289_1           ; ...and repeat until the row is finished
  INC HL                  ; Advance screen display position by 4, which takes
  INC HL                  ; us back to the left but to the next row down
  INC HL                  ;
  INC HL                  ;
  DEC C                   ; Row counter reduced by one
  JR NZ,L32289_0          ; Repeat until colour in all rows coloured
; Set colour for the sky section (stars/moon) to white
  LD (L31917_2),HL        ; Pointer is now beneath the first 6 rows - store it
  LD HL,22627             ; Set screen address pointer to just inside the top
                          ; left border
  LD C,2                  ; Top 2 rows of the picture
L32289_2:
  LD B,26                 ; ...and 26 columns, just inside the border
L32289_3:
  LD (HL),15              ; Set the screen attribute block colour (INK 7, PAPER
                          ; 1)
  INC HL                  ; Move right to the next character square
  DJNZ L32289_3           ; ...and repeat until all 26 columns are coloured in
  INC HL                  ; Keep moving the screen display position right until
  INC HL                  ; back on the left of the screen, one row down
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  DEC C                   ; Decrement row counter, and repeat until all 2 rows
  JR NZ,L32289_2          ; are coloured in
; Set black colour for the next 8 rows of the graphics scene (just below the
; top of the sky)
  LD HL,(L31917_2)        ; Retrieve the screen attribute display address
                          ; pointer, just over a third of the way down the
                          ; screen
  LD C,8                  ; 8 rows to colour
L32289_4:
  LD B,28                 ; 28 columns (this will also include the bottom half
                          ; of the border)
L32289_5:
  LD (HL),0               ; INK 0, PAPER 0
  INC HL                  ; Move right to the next character square
  DJNZ L32289_5           ; Repeat until all 28 columns are filled in
  INC HL                  ; Keep moving right until back on the left of the
  INC HL                  ; screen, one row down
  INC HL                  ;
  INC HL                  ;
  DEC C                   ; Decrement row counter, and repeat until all 8 rows
  JR NZ,L32289_4          ; are coloured in
; Set the bottom part of the intro screen to yellow (this will be Maroc's
; colour)
  LD HL,(L31917_2)        ; Retrieve the screen address pointer, just over a
                          ; third of the way down the screen
  INC HL                  ; Move right one square, so just inside the
                          ; (invisible) border
  LD C,7                  ; 7 rows to colour in
L32289_6:
  LD B,26                 ; ...and 26 columns
L32289_7:
  LD (HL),6               ; Set colour of the square to  yellow - INK 0, PAPER
                          ; 7
  INC HL                  ; Move right to the next square
  DJNZ L32289_7           ; ...and repeat so the row of 26 squares is coloured
                          ; in
  INC HL                  ; Keep moving the screen display address pointer
  INC HL                  ; right until back on the left side of the screen,
  INC HL                  ; one row down
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  DEC C                   ; Decrement the row counter, and repeat until all 7
  JR NZ,L32289_6          ; rows are coloured in

; Draw the intro sequence landscape
;
; Draws the graphics for the landscape silhouette used the intro sequence.
; Graphics are stored at 33439.
;
; Draw a 1-character high middle strip of the landscape containing most of the
; rolling hills
L32549:
  LD A,26                 ; Strip of landscape, 26 columns wide
  LD (35759),A            ;
  LD A,1                  ; 1 (character) row high
  LD (35760),A            ;
  LD DE,33439             ; Pointer to landscape graphics data
  LD HL,16611             ; Set screen display address to the left/middle of
                          ; the screen
  CALL L33267             ; Draw graphics
; Draw the small trilith-shaped structure over on the left of the scene
  LD A,1                  ; Just 1 character to draw so 1 column, 1 row
  LD (35759),A            ;
  LD A,1                  ;
  LD (35760),A            ;
  LD DE,33655             ; Point to graphics data
  LD HL,16585             ; Point to screen location to draw at
  CALL L33267             ; Draw on screen
; Draw top section of the thin vertical structure in middle of landscape
  LD A,1                  ; Just 1 character to draw (1 column, 1 row)
  LD (35759),A            ;
  LD A,1                  ;
  LD (35760),A            ;
  LD DE,33663             ; Point at graphics data
  LD HL,16592             ; Point to place on screen to draw at
  CALL L33267             ; Draw graphics
; Cyan highlighted structure on the right of the screen
  LD A,4                  ; 4 columns
  LD (35759),A            ;
  LD A,1                  ; 1 row
  LD (35760),A            ;
  LD DE,33671             ; Point at graphics data
  LD HL,16596             ; Point at place on screen to draw at
  CALL L33267             ; Draw to screen
; Highest highlighted structure visible over on the right
  LD A,2                  ; 2 columns
  LD (35759),A            ;
  LD A,1                  ; 1 row
  LD (35760),A            ;
  LD DE,33703             ; Point at graphics data
  LD HL,16565             ; Point at place on screen to draw at
  CALL L33267             ; Draw to screen
; Set the 2 cyan attributes on the structure over on the right
  LD HL,22709             ; First highlight on slightly higher part
  LD (HL),13              ; Cyan colour (INK 5, PAPER 1)
  LD HL,22740             ; ...and the part to its lower-left
  LD (HL),13              ;
; Lower part of tall cyan highlighted tower structure
  LD A,4                  ; 4 columns
  LD (35759),A            ;
  LD A,1                  ; 1 row
  LD (35760),A            ;
  LD DE,33719             ; Point at graphics data
  LD HL,18447             ; Point at place on screen to draw at
  CALL L33267             ; Draw to screen
; Set the highlight colour and a few other attributes alongside it
  LD HL,22799             ; The bottom of the tower cyan highlight/reflection
                          ; just drawn
  LD (HL),5               ; Set to cyan (INK 5, PAPER 0)
  INC HL                  ; Set the 3 squares to the right of it to blue/black
  LD (HL),8               ; (INK 0, PAPER 1)
  INC HL                  ;
  LD (HL),8               ;
  INC HL                  ;
  LD (HL),8               ;
; Draw the moon
  LD HL,16525             ; Point at place on screen to draw at
  LD A,1                  ; Just 1 character so 1 column, 1 row
  LD (35760),A            ;
  LD (35759),A            ;
  LD DE,33751             ; Point at moon graphic data
  CALL L33267             ; Draw it on screen
; Stars in top right of screen
  LD HL,16505             ; Drawing position set to top right of scene
  LD A,1                  ; 1 row
  LD (35760),A            ;
  LD A,3                  ; 3 columns (characters) to draw
  LD (35759),A            ;
  LD DE,33759             ; Point at stars graphic data
  CALL L33267             ; Draw them on screen
; Stars in top left of screen
  LD HL,16517             ; Draw position in top left of scene
  LD A,1                  ; Just 1 character - 1 row, 1 column
  LD (35760),A            ;
  LD (35759),A            ;
  LD DE,33784             ; Point at graphics data
  CALL L33267             ; Draw them on screen
; Cyan moon reflection colour and then graphic on right of small trilith
  LD HL,22730             ; Attribute display address location
  LD (HL),13              ; Cyan colour (INK 5, PAPER 1)
  LD HL,16586             ; Screen address display location for graphic
  LD A,1                  ; 1 character (1 row, 1 column)
  LD (35760),A            ;
  LD (35759),A            ;
  LD DE,33792             ; Point at graphics data
  CALL L33267             ; Draw on screen
; Cyan moon reflection colour and then graphic on top of small trilith
  LD HL,22697             ; Attribute display address location
  LD (HL),13              ; Cyan colour (INK 5, PAPER 1)
  LD HL,16553             ;
  LD A,1                  ; 1 character (1 row, 1 column)
  LD (35760),A            ;
  LD (35759),A            ;
  LD DE,33800             ; Point at graphics data
  CALL L33267             ; Draw on screen
; Cyan moon reflection colour and then graphic on left of small vertical tower
  LD HL,22767             ; Second character square of tower screen attribute
                          ; display position
  LD (HL),13              ; Cyan colour (INK 5, PAPER 1)
  LD HL,22735             ; Top character square of tower screen attribute
                          ; display position
  LD (HL),13              ; Cyan (INK 5, PAPER 1)
; Next, the graphics
  LD A,2                  ; 2 (vertical) rows
  LD (35760),A            ;
  LD A,1                  ; 1 (character-wide) column
  LD (35759),A            ;
  LD HL,33808             ; Point at graphics data
  LD (L31917_2),HL        ;
  LD HL,16591             ;
  CALL L33319             ; Draw on screen
; This scene is used both for the intro screen for a new game and the screen
; where you load a saved game.
  LD A,(L35754)           ; Retrieve the Menu Controls option selected (1-4)
  LD E,A                  ; ...and store it in the E register
  LD A,(35755)            ; Retrieve the game flag (0 = New Game, 1 = Existing
                          ; Game)
  LD D,A                  ; ...and store it in the D register
  RET                     ;

; Menu 1: Print control options
;
; Used by the routine at L31744.
;
; Prints the first of two menus on screen - this one is for the player to
; select their controls. The text is stored at L35778.
L32825:
  LD A,0                  ; Reset menu option to 'none selected'
  LD (L35754),A           ;
; Clear the screen
  CALL L33115             ; Clear the screen (pixels)
  LD A,15                 ; Set INK 7 (white), PAPER 1 (blue)
  CALL L33115_1           ; Set screen colours
; Print the menu
  LD HL,16417             ; Set menu starting PRINT position at row 1, column 1
  LD DE,L35778            ; Store the address of the start of the menu text
  LD (35776),DE           ;
  CALL L33145             ; Print first line of menu text "PRESS 1-4 TO CHANGE
                          ; OPTION"
  LD HL,16451             ; Set PRINT position at 2,3 (row/column)
  CALL L33145             ; Print next line of menu text "ENTER TO START
                          ; PROGRAM"
  LD HL,16545             ; Set PRINT position at 5,1
  CALL L33145             ; Print "1   KEMPSTON JOYSTICK (PORT 31)"
  LD HL,16609             ; Set PRINT position at 7,1
  CALL L33145             ; Print "2   AGF JOYSTICK (CURSOR KEYS)"
  LD HL,18465             ; Set PRINT position at 9,1
  CALL L33145             ; Print "3   SINCLAIR JOYSTICK"
  LD HL,18529             ; Set PRINT position AT 11,1
  CALL L33145             ; Print "4   KEYBOARD SET UP AS FOLLOWS"
  LD HL,18595             ; Set PRINT position AT 13,3
  CALL L33145             ; Print "UP  DOWN  LEFT RIGHT FIRE"
; The next part prints the key options for the 5 directions (up, down, left,
; right, fire). Instead of printing one line these are printed in 5 strings.
  LD DE,35970             ; Store the address of the text for the controls
  LD (35776),DE           ;
  LD HL,18657             ; Set PRINT position at 15,1 (row/column)
  LD A,5                  ; Store count of 5 sets of keys to PRINT (up, down,
  LD (35756),A            ; left, right & fire)
  LD (35771),HL           ; Store screen print position
L32825_0:
  CALL L33145             ; PRINT text on screen
  LD HL,(35771)           ; Retrieve screen print position
  INC HL                  ; Move forward 6 character spaces
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  LD (35771),HL           ; ...and store the updated screen address position
  LD A,(35756)            ; Retrieve, decrement and re-store counter (x 5 sets)
  DEC A                   ;
  LD (35756),A            ;
  JR NZ,L32825_0          ; Continue to print until all 5 sets of keys are done

; Menu 1: Scan keyboard input for control option selection
;
; Used by the routine at L33021.
;
; Checks if the player has picked a control option on menu 1 (L32825).
L32929:
  LD BC,63486             ; Port input address for keyboard keys 1,2,3,4 and 5
  IN A,(C)                ; Get input from port
  OR %11100000            ; To maintain keyboard consistency, set bits 5-7
                          ; ready for the CP in the next instruction
  CP %11111111            ; Are any keys currently being pressed?
  JR Z,L32929_1           ; If not (value = 255), check if a key press has
                          ; previously been registered
; Key is being pressed - check if it's a valid option (1,2,3 or 4), and if so,
; jump to L32961.
  LD B,4                  ; 4 port addresses to check
  LD HL,35762             ; Address pointer to where the port addresses are
                          ; held
; Loop through port addresses
L32929_0:
  CP (HL)                 ; Compare with keyboard input
  JR Z,L32961             ; If a valid key has been pressed, jump to L32961 to
                          ; play a sound and highlight the choice on screen
  INC HL                  ; Otherwise advance to the next (2 byte) port address
  INC HL                  ;
  DJNZ L32929_0           ; ...and keep checking until all 4 are done.
; Check if a key press has been registered already
L32929_1:
  LD A,(L35754)           ; Has a menu option (1-4) been chosen yet?
  CP 0                    ;
  JR Z,L32929             ; If not, go back to checking keys at L32929
  JR L33021               ; If so, run the routine to see if ENTER is being
                          ; pressed (to start the game)

; Menu 1: Highlight/store selected control option (1-4)
;
; Used by the routine at L32929.
;
; HL Address pointer for the relevant port address at 35762 relating to the key
;    that's been pressed.
;
; The player has picked a valid controls option on menu 1 (L32825). Store the
; choice number (1-4), play a high pitched sound and highlight their choice on
; screen.
L32961:
  INC HL                  ; Advance to the second byte of the pair (to give the
                          ; number)
  LD A,(HL)               ; Identify key pressed (1-4)
  LD (L35754),A           ; ...and store it
; Play a high pitched sound (and also set the border to black)
  LD C,255                ; C register contains the outer loop counter for the
                          ; sound duration
  LD HL,13107             ; H = 51, L = 51 - but also used as a token address
                          ; pointer somewhere in ROM
; Outer loop start - toggle speaker on and pause briefly
L32961_0:
  LD B,16                 ; Pause duration
  LD A,16                 ; Set bit 4 - speaker bit
  OUT (254),A             ; Output it (speaker toggle = on)
L32961_1:
  DJNZ L32961_1           ; Short pause
; The following instructions make a few changes to the value held in the A
; register, which is then used in the next short pause loop at L32961_2.
  LD H,(HL)
  ADD A,H
  ADD A,L
  AND 15
  ADD A,96
  ADD A,B
; Toggle speaker off and pause briefly
  LD B,A                  ; Transfer to the B register to be used as a pause
                          ; timer
  LD A,0                  ; Reset the A register (reset speaker bit)
  OUT (254),A             ; Output it (speaker toggle = off)
L32961_2:
  DJNZ L32961_2           ; Another short pause
  DEC C                   ; Decrement the outer loop counter
  JR NZ,L32961_0          ; ...and repeat until zero.
; Highlight/flash the menu option selected
  LD A,(L35754)           ; Get the menu option selected (1-4)
  LD HL,22689             ; Screen attribute display position for first option
                          ; (Kempston)
  LD DE,64                ; 64 characters = 2 lines to jump down to next option
  LD B,4                  ; Four menu options to check (1-4)
  LD C,1                  ; Start with 1
L32961_3:
  LD (HL),15              ; Reset colour/attribute for this option (INK 7,
                          ; PAPER 1)
  CP C                    ; Is it this option that's selected?
  JR NZ,L32961_4          ;
  LD (HL),207             ; ...If so, set attribute to FLASH 1, BRIGHT 1
L32961_4:
  ADD HL,DE               ; Move attribute screen address down two lines to
                          ; next option
  INC C                   ; Increment...
  DJNZ L32961_3           ; ...and check for 2, 3 and then 4 in the same way

; Menu 1: Check if ENTER pressed to confirm player controls
;
; This follows the previous routine at L32961, or a jump from 32959, after the
; player has made a choice of controls on the first game menu.
;
; Pressing ENTER confirms the controls choice, and launches the second game
; menu. Once the choice of controls has been made, the player can't change it
; without reloading the game.
L33021:
  LD BC,49150             ; Keyboard port for keys H, J, K, L, Enter
  IN A,(C)                ; Read the port input
  OR %11111110            ; We're only interested in bit 0, but set bits 1-7
                          ; for the CP in the next instruction
  CP %11111111            ; Check if ENTER is being pressed (bit 0 will be
                          ; reset if so)
  JR Z,L32929             ; If ENTER isn't being pressed, return to checking
                          ; keys for other menu options
; ENTER has been pressed, player controls choice confirmed.
  CALL L33115             ; Clear the screen (pixels)
; ENTER is still being pressed - wait until the key has been released
L33021_0:
  LD BC,49150             ; Keyboard port for keys H, J, K, L, Enter
  IN A,(C)                ; Read the port input
  OR %11111110            ; We're only interested in bit 0, but set bits 1-7
                          ; for the CP in the next instruction
  CP %11111111            ; Check if ENTER is still being pressed
  JR NZ,L33021_0          ; If so, keep checking until it's been released
; ENTER has now been released
  LD A,15                 ; Set the screen attributes to INK 7, PAPER 1
  CALL L33115_1           ; ...and reset screen colours with this colour
                          ; (mainly to clear the flashing colour marking the
                          ; player's control selection)

; Menu 2: Print the menu
;
; The second of the game's two menus - options to start a new game or LOAD a
; saved one.
L33051:
  LD DE,L35994            ; Get the address pointer for the first line of menu
                          ; text to PRINT
  LD HL,16515             ; Set the screen address for the first line
  CALL L33145             ; Print the text string ("PRESS ENTER FOR NEW GAME")
  LD DE,36019             ; Get the address pointer for the second line of menu
                          ; text
  LD HL,16579             ; Set the screen address for the second line ("PRESS
                          ; LOAD FOR SAVED GAME")
  CALL L33145             ; Print the text string

; Menu 2: Check for ENTER or LOAD keys being pressed
;
; Second menu (L33051) - checks for one of two key press options (both checked
; using the same keyboard port).
L33069:
  LD BC,49150             ; Keyboard port address for keys H, J, K, L, Enter
  IN A,(C)                ; Read port input
  LD C,A                  ; Temp store value in C register for next check
; Check if ENTER is being pressed
  OR %11111110            ; Need to check bit 0, so set all other bits
  CP %11111110            ; Check for the ENTER key
  LD A,0                  ; Set "New Game" flag (0) in advance of a positive
                          ; check
  JR Z,L33069_0           ; Finish check/jump out here if ENTER is pressed
; Check if LOAD ("J") is being pressed
  LD A,C                  ; Retrieve keyboard port address input from C
                          ; register
  OR %11110111            ; Need to check bit 3, so set all other bits
  CP %11111111            ; Check for "J" key
  JR Z,L33069             ; If it's not being pressed, jump back and keep
                          ; scanning for ENTER or LOAD keys
; LOAD ("J") has been pressed
  CALL L33115             ; LOAD has been selected. Clear the screen (pixels)
  LD DE,L36045            ; Get address of text string ("LOAD SAVED GAME")
  LD HL,18632             ; Set screen position for printing text
  CALL L33145             ; Print "LOAD SAVED GAME" on screen
  LD A,1                  ; Set "Load game" flag (1)
; ENTER or LOAD has now been selected, and the A register contains flag for
; either new game (0) or load game (1)
L33069_0:
  LD (35755),A            ; Store game flag (0 = New Game, 1 = Load Saved Game)
  CP 1                    ;
  JR Z,L33069_1           ; Load game - don't clear the screen (skip the next
                          ; instruction to leave "LOAD SAVED GAME" message
                          ; on-screen)
  CALL L33115             ; New game - clear the screen (pixels)
L33069_1:
  RET                     ;

; Clear the menu screen
;
; Used by the routines at L32825, L33021 and L33069.
;
; A Colour/attribute value (second routine only)
;
; Two routines used in both menus - one routine to clear screen pixels, the
; second to clear the screen colours.
;
; Clear the screen (pixels):
L33115:
  LD HL,16384             ; Top left of screen display
  LD DE,6144              ; Number of bytes to clear
L33115_0:
  LD (HL),0               ; Clear screen pixels
  INC HL                  ; Move to next screen byte position
  DEC DE                  ; Decrement byte counter
  LD A,E                  ;
  OR D                    ;
  JR NZ,L33115_0          ; Keep clearing until counter = 0
  RET                     ;
; Clear the screen (colours):
L33115_1:
  LD HL,22528             ; Top left of (attribute) screen display
  LD DE,768               ; Number of bytes
  LD C,A                  ; Retrieve attribute/colour value to use
L33115_2:
  LD (HL),C               ; Put colour on screen
  INC HL                  ; Advance to next screen square
  DEC DE                  ; Decrement byte counter
  LD A,E                  ;
  OR D                    ;
  JR NZ,L33115_2          ; Keep colouring until counter = 0
  RET                     ;

; Menu text PRINT routine
;
; Used by the routines at L32825, L33051 and L33069.
;
; Routine that prints a string of text for menu 1 (L32825) and menu 2 (L33051).
; The menu font used is the standard ZX Spectrum ROM character set, rather than
; the in-game text characters.
L33145:
  LD DE,(35776)           ; Get the address pointer for the address of the text
                          ; to print (e.g. L35778/L35994).
  LD A,(DE)               ; Get first byte = length of text string
  INC DE                  ; Increment to start of text string, and store
  LD (35776),DE           ; address
  LD (35773),A            ; Store the length of string (number of characters)
  LD (35774),HL           ; Store screen address position
; Loop for printing the text characters on screen
L33145_0:
  LD DE,(35776)           ; Get the next text character to print
  LD A,(DE)               ;
  INC DE                  ; Increment to next text character and store address
  LD (35776),DE           ; for future printing
  LD HL,(23606)           ; Get pointer to the ZX Spectrum character set
                          ; (CHARS)
  LD D,0                  ; Get the text character's ASCII value (store in DE
  LD E,A                  ; register pair)
  LD B,8                  ; 8 pixel rows to print
L33145_1:
  ADD HL,DE               ; Calculate the address of the character in the
  DJNZ L33145_1           ; character set ready to print [CHARS address +
  EX DE,HL                ; (character ASCII value x 8)] and swap into DE
  LD HL,(35774)           ; Get the screen address position
  LD C,H                  ; Preserve screen address of top pixel row in C
                          ; register
  LD B,8                  ; 8 pixel lines to print
; Draw the 8 pixel row bytes of the text character
L33145_2:
  LD A,(DE)               ; Get pixel row byte of character
  INC DE                  ; (and move pointer along to the next one)
  LD (HL),A               ; Copy byte onto screen
  INC H                   ; Move down 1 pixel line
  DJNZ L33145_2           ; Repeat for 8 pixel rows to print full text
                          ; character
; Move on to the next character in the string and next screen position
  INC L                   ; Move one horizontal character position to the
                          ; right...
  LD H,C                  ; Retrieve vertical screen address of top pixel row
                          ; from C register and put into high byte of H
                          ; register
  LD (35774),HL           ; ...and store this screen address ready for next
                          ; character
  LD A,(35773)            ; Decrement and re-store the text length counter
  DEC A                   ;
  LD (35773),A            ;
  JR NZ,L33145_0          ; Repeat loop x number of characters in the text
  RET                     ; string

; Unused colour/attribute fill routine
;
; Routine that sets screen colours for the top 6 lines of the play area.
;
; Possibly a remnant of an old sky lightning flash routine in the intro at
; L49274/L58896.
L33210:
  LD C,A                  ; Routine not used
  RLA                     ;
  RLA                     ;
  RLA                     ;
  AND 56                  ;
  LD B,A                  ;
  LD HL,22594             ;
  LD DE,0                 ;
  LD A,7                  ;
L33210_0:
  LD (35760),A            ;
  LD A,28                 ;
L33210_1:
  LD (35759),A            ;
  LD A,(HL)               ;
  ADD A,C                 ;
  AND 7                   ;
  LD E,A                  ;
  LD A,(HL)               ;
  ADD A,B                 ;
  AND 56                  ;
  OR E                    ;
  LD (HL),A               ;
  INC HL                  ;
  LD A,(35759)            ;
  DEC A                   ;
  JR NZ,L33210_1          ;
  LD A,(DE)               ;
  INC DE                  ;
  OUT (254),A             ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  LD A,(35760)            ;
  DEC A                   ;
  JR NZ,L33210_0          ;
  RET                     ;
  RET                     ;

; Drawing routine (decorative border and intro sequence background)
;
; Used by the routines at L31747 and L32549.
;
; HL Screen display address position to draw at
; DE Start address for graphics to be drawn
;
; Number of character columns to draw stored at 35759. Number of character rows
; at 35760.
L33267:
  LD C,H                  ; Copy high byte of display address position to C
                          ; register
L33267_0:
  LD A,(35759)            ; Copy counter for number of columns to draw into
  LD (35761),A            ; working buffer
L33267_1:
  LD H,C                  ; Get high byte of display address
; Screen drawing loop for a row of graphics (1 character row, multiple
; columns):
  LD B,8                  ; 8 pixel rows to draw
L33267_2:
  LD A,(DE)               ; Get graphics byte
  LD (HL),A               ; ...copy it to the screeen
  INC H                   ; Increment high byte of display address to move down
                          ; one pixel
  INC DE                  ; Increment graphics address pointer ready for next
                          ; graphics byte
  DJNZ L33267_2           ; Repeat for 8 pixel rows
  INC L                   ; Move right one character position on screen
  LD A,(35761)            ; Retrieve, decrement and re-store the column counter
  DEC A                   ;
  LD (35761),A            ;
  JR NZ,L33267_1          ; Keep drawing until all columns are done
; Calculate the screen display address for the next (character) row:
  LD A,(35759)            ; Get the total number of columns drawn
  LD B,A                  ; Store in B register
  LD A,33                 ; Subtract from 33 - this gives us the offset for the
  SUB B                   ; low byte screen display position for the next row
                          ; down
  DEC L                   ; L was incremented earlier before the 'column
                          ; finished check', so move it back to its previous
                          ; position.
  ADD A,L                 ; ...and add it so it's in the correct column
  LD L,A                  ; position to draw the next row.
  JR NC,L33267_3          ; Check to see if this has caused us to go past a
                          ; 'third-of-screen' boundary
  LD A,C                  ; If so, modify the high byte of the stored screen
  ADD A,8                 ; address accordingly
  LD C,A                  ;
; Continue to draw rows of graphics:
L33267_3:
  LD A,(35760)            ; Get the number of rows to draw
  DEC A                   ; Reduce by one
  LD (35760),A            ; ...and re-store
  JR NZ,L33267_0          ; All rows finished? If not, continue to draw the
  RET                     ; graphics.

; Drawing routine used for intro sequence graphics
;
; Used by the routines at L32289 and L32549.
;
; HL Screen display address to draw at
L33319:
  LD C,H                  ; Store screen display address high byte in C
                          ; register
L33319_0:
  LD A,(35759)            ; Get number of columns to draw
  LD (35761),A            ; Store as a counter
L33319_1:
  LD H,C                  ; Retrieve screen display address from C register
  LD B,8                  ; 8 pixel lines to draw
  LD DE,(L31917_2)        ; Retrieve address pointing to graphics to draw
; Draw a series of character column graphics:
L33319_2:
  LD A,(DE)               ; ...get graphics byte
  LD (HL),A               ; ...and copy it to the screen
  INC H                   ; Increment screen display position (move down one
                          ; pixel line)
  INC DE                  ; ...and move to next graphic byte
  DJNZ L33319_2           ; Repeat until 8 pixel lines printed
  INC L                   ; Move right 1 square on screen
  LD A,(35761)            ; Retrieve the graphic column counter
  DEC A                   ; ...Decrement it...
  LD (35761),A            ; ...And re-store it...
  JR NZ,L33319_1          ; Keep drawing until column counter = 0
; Recalculate screen display address for next character row of graphics:
  LD A,(35759)            ; Retrieve column counter
  LD B,A                  ;
  LD A,33                 ; Subtract from 33 to get next line offset position
  SUB B                   ;
  DEC L                   ; L was incremented before finishing earlier so move
                          ; back a space
  ADD A,L                 ; Add the offset so we're at the correct position for
  LD L,A                  ; the next character row
  JR NC,L33319_3          ; Check that we're not crossing a 1/3 screen boundary
  LD A,C                  ; Crossing a 1/3 screen boundary, so
  ADD A,8                 ; Amend the screen display address by adding 8
  LD C,A                  ; ...and store byte in C for retrieval later
; Check if any more graphics need drawing:
L33319_3:
  LD A,(35760)            ; Retrieve row counter
  DEC A                   ; Decrement and re-store it
  LD (35760),A            ;
  JR NZ,L33319_0          ; Continue drawing until counter = 0
  RET                     ;

; Graphics: Intro sequence inner border & backdrop
;
; Drawn in the routine at L32289.
;
; Left-hand side border graphic
L33375:
  DEFB 192,240,128,240,192,240,192,240
; Bottom-left corner border graphic
  DEFB 192,224,208,232,242,245,253,255
; Top border graphic
  DEFB 0,0,0,0,17,85,117,255
; Bottom-right corner border graphic
  DEFB 3,1,11,19,11,71,87,255
; Right-hand side border graphic
  DEFB 7,1,15,3,15,3,15,3
; Top right-hand corner border graphic
  DEFB 255,127,159,47,19,35,13,1
; Bottom border graphic
  DEFB 255,186,170,42,0,0,0,0
; Top-left corner border graphic
  DEFB 255,255,244,240,208,200,224,128
; Strip of landscape
  DEFB 0,0,0,0,0,7,127,255
  DEFB 0,0,0,0,24,255,255,255
  DEFB 0,0,0,0,0,192,248,254
  DEFB 0,0,0,8,31,63,127,255
  DEFB 0,2,7,31,127,255,255,255
  DEFB 3,31,255,255,255,255,255,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 0,192,240,252,255,255,255,255
  DEFB 0,0,0,64,224,240,252,255
  DEFB 0,0,0,1,31,127,255,255
  DEFB 0,0,16,248,255,255,255,255
  DEFB 0,0,0,0,0,215,223,255
  DEFB 0,0,0,0,0,224,248,255
  DEFB 192,192,192,192,192,192,192,192
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,3,7
  DEFB 0,1,3,15,63,255,255,255
  DEFB 0,3,127,255,255,255,255,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 0,128,224,246,255,255,255,255
  DEFB 0,0,0,0,192,224,255,255
  DEFB 0,0,0,0,0,0,240,255
  DEFB 0,0,0,0,0,0,31,255
  DEFB 0,0,0,0,7,103,255,255
  DEFB 0,0,0,252,254,255,255,255
; Landscape graphic - small trilith
  DEFB 255,255,231,231,231,231,231,231
; Landscape graphic - thin tower structure
  DEFB 192,192,192,192,192,192,192,192
; Landscape graphic - cyan highlight/structure on the right of the screen
  DEFB 1,0,1,0,1,0,1,0
  DEFB 225,255,255,255,255,255,255,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 96,224,224,240,240,240,248,254
; Landscape graphic - cyan structure just below and to the left of the above
; graphic
  DEFB 1,0,1,0,1,0,1,0
  DEFB 192,192,228,244,252,220,204,236
; Landscape graphic - lower part of tall cyan highlighted tower structure
  DEFB 1,0,1,0,1,0,1,0
  DEFB 192,192,248,252,255,255,255,255
  DEFB 0,0,0,0,129,255,255,255
  DEFB 15,31,31,63,255,255,255,255
; Moon graphic
  DEFB 28,56,120,120,120,120,56,28
; Top right stars
  DEFB 0,0,0,0,0,48,48,192
  DEFB 0,2,0,0,0,0,0,0
  DEFB 32,0,0,0,0,0,4,0
; Unused byte
  DEFB 0
; Top left stars
  DEFB 1,0,16,48,16,0,0,0
; Cyan moon reflection on right of small trilith
  DEFB 128,0,128,0,128,0,128,0
; Cyan moon reflection on top of small trilith
  DEFB 0,0,0,0,0,0,0,85
; Cyan moon reflection on left of vertical tower structure
  DEFB 1,0,1,0,1,0,1,0
; Unused bytes
  DEFB 0,0

; Graphics: Game screen (decorative border)
;
; Drawn at L31747 (pixels) and L31917 (colours)
;
; Top two character rows (2 rows x 32 columns)
L33818:
  DEFB 254,248,243,224,231,231,231,251 ; First row
  DEFB 159,135,179,65,61,189,185,27    ;
  DEFB 255,255,255,255,255,248,196,34  ;
  DEFB 255,255,255,255,255,63,79,39    ;
  DEFB 47,223,143,143,223,47,255,255   ;
  DEFB 255,255,252,251,250,228,128,128 ;
  DEFB 199,27,1,125,255,252,243,15     ;
  DEFB 255,255,255,255,255,63,223,239  ;
  DEFB 255,248,243,231,207,223,223,223 ;
  DEFB 255,127,187,135,191,191,191,255 ;
  DEFB 255,255,255,255,252,241,230,158 ;
  DEFB 255,240,135,56,67,140,16,103    ;
  DEFB 255,0,255,128,0,1,6,155         ;
  DEFB 255,3,255,25,96,128,0,135       ;
  DEFB 255,255,255,255,255,127,63,31   ;
  DEFB 224,200,132,131,24,62,62,12     ;
  DEFB 7,35,65,129,24,124,124,56       ;
  DEFB 255,255,255,255,255,254,254,241 ;
  DEFB 255,192,255,156,35,64,128,0     ;
  DEFB 255,0,254,1,0,192,48,201        ;
  DEFB 255,255,7,248,199,49,238,2      ;
  DEFB 255,255,255,127,159,231,59,4    ;
  DEFB 255,127,63,159,207,224,255,255  ;
  DEFB 255,159,7,115,107,107,138,240   ;
  DEFB 255,247,243,243,207,63,143,255  ;
  DEFB 255,254,249,249,249,248,252,240 ;
  DEFB 253,227,227,249,252,0,0,207     ;
  DEFB 255,255,243,239,239,7,0,128     ;
  DEFB 255,255,255,240,228,237,226,49  ;
  DEFB 255,236,225,3,4,0,0,183         ;
  DEFB 239,3,228,131,2,2,99,130        ;
  DEFB 239,31,31,30,221,33,17,41       ;
  DEFB 244,242,255,250,250,255,254,252 ; Second row
  DEFB 202,213,252,172,171,249,44,37   ;
  DEFB 18,210,83,79,63,127,255,255     ;
  DEFB 107,197,5,232,248,253,254,255   ;
  DEFB 254,249,142,204,153,23,47,255   ;
  DEFB 206,94,63,127,255,255,255,255   ;
  DEFB 255,127,63,151,231,255,255,255  ;
  DEFB 239,239,239,239,240,255,255,255 ;
  DEFB 223,223,191,191,127,255,255,255 ;
  DEFB 254,252,249,242,236,211,159,255 ;
  DEFB 33,194,4,8,17,39,143,223        ;
  DEFB 152,0,0,1,130,228,241,251       ;
  DEFB 96,64,128,0,28,255,255,255      ;
  DEFB 104,56,16,16,39,175,223,223     ;
  DEFB 129,127,0,248,255,255,255,255   ;
  DEFB 129,145,203,232,224,229,237,247 ;
  DEFB 131,141,211,15,15,111,111,223   ;
  DEFB 15,240,0,31,255,255,255,255     ;
  DEFB 129,98,20,200,228,241,251,255   ;
  DEFB 53,2,1,24,252,255,255,255       ;
  DEFB 1,0,0,128,64,39,143,223         ;
  DEFB 1,128,64,32,16,232,241,251      ;
  DEFB 127,191,95,39,19,9,173,254      ;
  DEFB 224,220,220,206,230,255,255,255 ;
  DEFB 127,127,127,127,62,28,16,199    ;
  DEFB 195,158,60,126,110,111,31,191   ;
  DEFB 31,127,243,231,247,123,63,255   ;
  DEFB 240,192,143,31,191,159,199,251  ;
  DEFB 27,11,254,254,254,255,255,255   ;
  DEFB 183,188,208,192,3,31,255,255    ;
  DEFB 14,50,193,248,252,254,62,15     ;
  DEFB 203,23,37,68,43,17,69,43        ;
; Graphics for LEFT border (14 rows x 2 columns)
  DEFB 246,244,230,228,230,212,198,220
  DEFB 35,39,47,47,63,63,63,63
  DEFB 230,194,205,208,231,232,241,250
  DEFB 63,63,63,191,127,63,223,15
  DEFB 252,255,255,248,252,248,254,250
  DEFB 119,135,195,251,113,57,181,177
  DEFB 254,249,252,248,252,248,252,250
  DEFB 177,188,178,176,184,181,49,59
  DEFB 255,249,253,233,236,232,204,200
  DEFB 187,51,55,47,63,63,63,63
  DEFB 236,136,236,136,236,8,228,132
  DEFB 63,63,63,63,63,63,63,63
  DEFB 178,194,153,225,196,232,240,247
  DEFB 63,63,63,63,191,127,63,31
  DEFB 248,248,253,254,254,255,249,252
  DEFB 31,239,7,3,235,133,129,188
  DEFB 248,252,248,252,248,252,248,252
  DEFB 96,32,62,32,32,45,35,47
  DEFB 248,252,248,236,200,204,232,148
  DEFB 63,63,63,63,61,61,57,49
  DEFB 135,147,164,201,210,242,250,255
  DEFB 97,135,19,87,95,127,127,159
  DEFB 255,251,251,251,251,245,245,245
  DEFB 31,31,31,31,31,31,31,159
  DEFB 242,242,241,225,224,224,224,224
  DEFB 255,255,127,63,191,95,47,23
  DEFB 224,224,224,224,224,225,230,208
  DEFB 17,25,43,75,139,19,19,19
; Graphics for bottom third of screen, left hand side (devil and left-hand edge
; of scroll) - 8 rows x 7 columns
  DEFB 224,224,224,240,240,241,242,254
  DEFB 19,27,43,69,132,4,2,1
  DEFB 255,255,255,255,255,127,15,15
  DEFB 255,255,255,255,251,253,252,254
  DEFB 255,255,255,255,255,255,127,63
  DEFB 255,255,255,255,255,254,253,253
  DEFB 255,255,255,255,255,128,192,224
  DEFB 241,249,240,248,240,248,240,248
  DEFB 0,0,128,129,142,240,128,255
  DEFB 199,103,83,137,4,3,0,31
  DEFB 250,240,240,252,39,241,3,3
  DEFB 63,207,103,7,70,166,213,236
  DEFB 253,253,253,253,253,254,254,254
  DEFB 224,224,96,106,213,255,127,0
  DEFB 240,248,240,248,240,248,240,248
  DEFB 31,31,31,31,31,31,31,31
  DEFB 32,72,188,127,255,254,254,254
  DEFB 3,3,1,128,230,7,7,7
  DEFB 253,249,227,7,15,239,255,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 0,0,0,0,128,128,128,128
  DEFB 240,248,240,248,240,248,240,248
  DEFB 31,31,31,31,31,31,31,31
  DEFB 254,254,252,252,252,248,248,250
  DEFB 7,7,7,24,0,0,0,3
  DEFB 255,255,159,31,31,63,191,63
  DEFB 255,255,255,255,255,255,255,255
  DEFB 240,240,248,224,192,192,192,192
  DEFB 240,248,240,248,240,248,240,248
  DEFB 31,31,31,31,31,31,31,31
  DEFB 195,143,191,191,127,113,115,181
  DEFB 31,231,199,199,199,231,231,231
  DEFB 191,191,191,191,63,31,223,223
  DEFB 255,255,255,255,255,255,255,255
  DEFB 224,224,224,224,224,224,224,224
  DEFB 240,248,240,248,240,248,240,248
  DEFB 31,31,31,31,31,31,31,31
  DEFB 189,189,195,255,255,254,255,255
  DEFB 243,227,231,207,63,127,127,127
  DEFB 255,255,255,255,255,255,255,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 224,248,252,231,224,224,224,224
  DEFB 240,240,240,240,240,240,240,240
  DEFB 27,25,24,24,25,25,25,25
  DEFB 239,207,143,15,79,206,204,204
  DEFB 255,255,31,223,223,28,217,217
  DEFB 255,243,243,255,255,51,179,179
  DEFB 255,255,255,255,254,140,61,61
  DEFB 224,224,224,224,96,224,224,224
  DEFB 240,240,240,240,248,255,255,255
  DEFB 25,25,25,31,63,255,255,255
  DEFB 204,204,204,255,255,252,253,252
  DEFB 217,28,62,255,255,0,255,0
  DEFB 179,51,51,191,191,63,254,1
  DEFB 61,157,205,253,252,254,255,255
  DEFB 224,224,224,192,213,170,255,255
; Graphics for RIGHT border (14 rows x 2 columns)
  DEFB 239,23,231,135,227,227,229,9
  DEFB 19,67,27,19,67,43,19,67
  DEFB 249,249,249,249,249,248,248,232
  DEFB 43,19,67,45,49,193,129,129
  DEFB 200,132,132,130,1,0,15,0
  DEFB 1,1,2,4,8,112,128,0
  DEFB 15,128,128,135,128,128,129,130
  DEFB 128,120,6,241,8,36,210,41
  DEFB 132,193,98,180,145,178,180,176
  DEFB 4,228,18,5,225,17,9,5
  DEFB 147,212,72,141,230,226,227,240
  DEFB 240,8,0,241,3,230,9,24
  DEFB 248,248,252,252,254,255,254,255
  DEFB 20,48,40,97,83,135,79,15
  DEFB 255,254,254,254,254,252,248,241
  DEFB 31,31,63,63,127,255,255,255
  DEFB 243,231,231,207,206,221,219,209
  DEFB 255,255,255,255,63,159,207,207
  DEFB 219,219,219,223,223,231,240,255
  DEFB 239,239,239,207,159,63,127,255
  DEFB 255,255,252,248,241,227,227,199
  DEFB 255,255,127,255,255,255,255,255
  DEFB 199,199,199,195,195,241,248,254
  DEFB 255,251,251,251,243,243,231,103
  DEFB 255,255,247,213,247,16,247,215
  DEFB 229,201,201,203,211,147,167,71
  DEFB 246,254,252,248,240,241,226,192
  DEFB 37,69,137,137,147,35,35,71
; Graphics for decorative scroll in bottom third of screen. Stored in character
; columns.
  DEFB 255,255,255,255,255,0,0,0 ; The first 8 of these graphics form a
                                 ; 'top-to-bottom' column graphic
  DEFB 0,0,0,170,85,255,255,0 ; The 1 x 8 column is repeated 18 times across to
  DEFB 0,0,0,0,0,0,0,0        ; make up the scroll body.
  DEFB 0,0,0,0,0,0,0,0        ;
  DEFB 0,0,0,0,0,0,0,0        ;
  DEFB 0,0,0,0,0,0,0,0        ;
  DEFB 0,0,0,0,0,0,0,0        ;
  DEFB 0,0,0,0,85,170,255,255 ;
; Graphics for bottom third of screen, right hand side (angel and right-hand
; edge of scroll) - 8 rows x 7 columns
  DEFB 255,255,255,255,255,7,3,2
  DEFB 255,255,255,255,255,255,255,127
  DEFB 255,255,255,255,252,254,250,250
  DEFB 255,255,255,255,31,15,15,15
  DEFB 255,255,255,255,254,254,254,252
  DEFB 136,144,1,2,4,8,17,34
  DEFB 71,143,31,47,79,143,31,63
  DEFB 3,1,3,171,87,255,255,31
  DEFB 127,159,199,243,249,252,190,207
  DEFB 245,224,240,240,240,243,62,30
  DEFB 207,111,175,167,35,33,32,56
  DEFB 252,248,248,240,224,224,192,192
  DEFB 68,8,17,34,36,137,19,39
  DEFB 127,255,255,255,255,255,255,255
  DEFB 31,31,127,31,15,15,15,15
  DEFB 239,247,243,241,248,252,254,255
  DEFB 130,192,227,244,248,112,32,0
  DEFB 4,4,195,2,4,32,64,129
  DEFB 128,129,134,0,1,31,63,255
  DEFB 207,31,62,126,252,252,252,254
  DEFB 191,63,63,127,127,127,63,63
  DEFB 7,7,7,7,7,15,15,63
  DEFB 255,255,255,255,255,255,255,255
  DEFB 131,207,255,255,255,255,255,255
  DEFB 0,0,240,252,254,254,255,255
  DEFB 63,31,15,7,1,0,64,128
  DEFB 254,254,254,254,254,126,63,63
  DEFB 63,61,61,125,253,249,249,241
  DEFB 127,31,7,7,7,7,7,7
  DEFB 255,255,255,255,255,255,255,255
  DEFB 255,254,254,252,248,240,241,195
  DEFB 255,254,252,252,248,240,224,192
  DEFB 0,0,0,7,12,60,124,252
  DEFB 63,127,191,63,63,63,62,62
  DEFB 225,195,131,135,15,31,31,63
  DEFB 3,3,3,3,3,3,3,3
  DEFB 255,254,252,248,240,240,224,224
  DEFB 7,15,31,63,63,127,127,255
  DEFB 195,192,224,252,255,255,255,255
  DEFB 254,254,15,3,0,192,254,255
  DEFB 62,62,30,142,207,55,15,227
  DEFB 63,63,127,127,127,127,63,191
  DEFB 39,31,7,3,3,3,1,255
  DEFB 224,224,240,240,248,252,254,255
  DEFB 255,255,255,255,127,63,15,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 255,255,255,255,255,255,255,255
  DEFB 229,200,220,190,254,252,253,255
  DEFB 223,239,119,63,99,221,222,216
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
; Bottom right graphic for small scroll overlap:
  DEFB 24,16,48,62,114,178,242,242
  DEFB 0,0,0,0,0,0,0,0

; Menu screens - data store
L35754:
  DEFB 0                  ; Menu control option selected (1-4) in routine at
                          ; L32929
  DEFB 0                  ; Game flag - New Game = 0, Load Saved Game = 1
  DEFB 0                  ; Set to 5 for a counter representing the 5 sets of
                          ; keys to print on the menu screen ("ASDFG" "ZXCV"
                          ; "BN" "MS/S" "HJKL") in the menu print routine at
                          ; 32887 Later set to 18, used as a column counter for
                          ; drawing the 18 scroll character columns at the
                          ; bottom of the game screen (31823).
  DEFW 0                  ; Store for screen display address pointer. Used in
                          ; drawing routine at 31823.
  DEFB 0                  ; Number of columns to draw. Used by drawing routine
                          ; at L33267.
  DEFB 0                  ; Number of row to draw. Used by drawing routine at
                          ; L33267.
  DEFB 0                  ; Counter for number of columns to draw. Used in
                          ; drawing routine at L33267.
  DEFB 247,4,251,3,253,2,254,1 ; Data for checking port addresses for keys 1,
                               ; 2, 3 or 4 (used in key check routine at
                               ; L32929)
  DEFB 0
  DEFW 18687              ; Starting screen address position for printing
                          ; control keys on menu in routine at L33145
  DEFB 0                  ; Number of text characters in the string to print -
                          ; used in the menu print routine at L33145
  DEFW 18685              ; Current screen display address position (used in
                          ; routine at L33145)
  DEFW L35994             ; Address pointer for the next text character to
                          ; print

; First menu screen text
;
; Text printed on the first menu screen in the routine at L32825.
L35778:
  DEFB 26                 ; First string length = 26 characters
  DEFM "PRESS 1-4 TO CHANGE OPTION"
  DEFB 22                 ; String length = 22 characters
  DEFM "ENTER TO START PROGRAM"
  DEFB 31                 ; String length = 31 characters
  DEFM "1   KEMPSTON JOYSTICK (PORT 31)"
  DEFB 30                 ; String length = 30 characters
  DEFM "2   AGF JOYSTICK (CURSOR KEYS)"
  DEFB 21                 ; String length = 21 characters
  DEFM "3   SINCLAIR JOYSTICK"
  DEFB 30                 ; String length = 30 characters
  DEFM "4   KEYBOARD SET UP AS FOLLOWS"
  DEFB 25                 ; String length = 25 characters
  DEFM "UP  DOWN  LEFT RIGHT FIRE"
  DEFB 5                  ; String length = 5 characters
  DEFM "ASDFG"
  DEFB 4                  ; String length = 4 characters
  DEFM "ZXCV"
  DEFB 2                  ; String length = 2 characters
  DEFM "BN"
  DEFB 4                  ; String length = 4 characters
  DEFM "MS/S"
  DEFB 4                  ; String length = 4 characters
  DEFM "HJKL"

; Second menu screen text
;
; Text printed on the second menu screen in the routine at L33051.
L35994:
  DEFB 24                 ; String length = 24 characters
  DEFM "PRESS ENTER FOR NEW GAME"
  DEFB 25                 ; String length = 25 characters
  DEFM "PRESS LOAD FOR SAVED GAME"

; Load saved game text
;
; Text printed on screen in routine at 33090.
L36045:
  DEFB 15                 ; String length = 15 characters
  DEFM "LOAD SAVED GAME"
  DEFM " GAME"

; Unused
L36066:
  DEFB 240,171,17,26,170,33,25,80
  DEFB 205,51,162,33,0,88,6,0
  DEFB 54,48,35,54,48,35,54,48
  DEFB 35,16,245,33,66,88,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,195,174
  DEFB 205

; Data - sprite and graphic address pointer table
L38851:
  DEFW 39248              ; Maroc Sprite Graphics - Frame 1
  DEFW 39368              ; Maroc Sprite Graphics - Frame 2
  DEFW 39482              ; Maroc Sprite Graphics - Frame 3
  DEFW 39593              ; Maroc Sprite Graphics - Frame 4
  DEFW 39685              ; Maroc Sprite Graphics - Frame 5
  DEFW 39805              ; Maroc Sprite Graphics - Frame 6
  DEFW 39925              ; Maroc Sprite Graphics - Frame 7
  DEFW 40036              ; Maroc Sprite Graphics - Frame 8
  DEFW 40145              ; Graphics - door 1
  DEFW 40248              ; Graphics - door 2
  DEFW 40341              ; Graphics - door 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; door 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; door 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; door 1
  DEFW 40393              ; Graphics - back wall/floor section ('brick' levels)
  DEFW 40424              ; Graphics - side wall section ('brick' levels)
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; side wall section
  DEFW 40463              ; Graphics - vertical wall section ('brick' levels)
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; vertical wall section
  DEFW 40516              ; Graphics - door frame - back wall ('brick' levels)
  DEFW 40598              ; Graphics - door frame - side wall ('brick' levels)
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; door frame - side wall
  DEFW 40681              ; Graphics - brickwork pattern 1
  DEFW 40705              ; Graphics - brickwork pattern 2
  DEFW 40723              ; Graphics - brickwork pattern 3
  DEFW 40752              ; Graphics - brickwork pattern 4
  DEFW 40772              ; Graphics - back wall/floor section ('cavern'
                          ; levels)
  DEFW 40805              ; Graphics - side wall section ('cavern' levels)
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; side wall section
  DEFW 40836              ; Graphics - vertical wall section ('cavern' levels)
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; vertical wall section
  DEFW 40877              ; Graphics - door frame - back wall ('cavern' levels)
  DEFW 40948              ; Graphics - door frame - side wall ('cavern' levels)
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; door frame - side wall
  DEFW 41014              ; Graphics - back wall scenery 1
  DEFW 41038              ; Graphics - back wall scenery 2
  DEFW 41059              ; Graphics - back wall scenery 3
  DEFW 41089              ; Graphics - back wall scenery 4
  DEFW 41115              ; Graphics - tunnel room boundary
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; tunnel boundary
  DEFW 41180              ; Graphics - servant - animation frame 1
  DEFW 41200              ; Graphics - servant - animation frame 2
  DEFW 41221              ; Graphics - eye cursor - animation frame 1
  DEFW 41256              ; Graphics - eye cursor - animation frame 2
  DEFW 41281              ; Graphics - scroll
  DEFW 41317              ; Graphics - Caliburn, the sword of power
  DEFW 41343              ; Graphics - amulet spell icon
  DEFW 41383              ; Graphics - chalice spell icon
  DEFW 41421              ; Graphics - ring/servant spell icon
  DEFW 41434              ; Graphics - move spell icon
  DEFW 41455              ; Graphics - jewel (spell icon - various)
  DEFW 41468              ; Graphics - missile 1 frame 1
  DEFW 41480              ; Graphics - missile 1 frame 2
  DEFW 41492              ; Graphics - missile 1 frame 3
  DEFW 41505              ; Graphics - missile 2 frame 1
  DEFW 41538              ; Graphics - missile 2 frame 2
  DEFW 41569              ; Graphics - missile 2 frame 3
  DEFW 41605              ; Graphics - missile 3 frame 1
  DEFW 41640              ; Graphics - missile 3 frame 2
  DEFW 41674              ; Graphics - missile 3 frame 3
  DEFW 41708              ; Graphics - Warlock - frame 1
  DEFW 41779              ; Graphics - Warlock - frame 2
  DEFW 41850              ; Graphics - Warlock - frame 3
  DEFW 41922              ; Graphics - Guardian of Chaos - frame 1
  DEFW 41995              ; Graphics - Guardian of Chaos - frame 2
  DEFW 42065              ; Graphics - Guardian of Chaos - frame 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Guardian of Chaos - frame 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Guardian of Chaos - frame 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Guardian of Chaos - frame 1
  DEFW 42141              ; Graphics - Goblin warrior - frame 1
  DEFW 42201              ; Graphics - Goblin warrior - frame 2
  DEFW 42260              ; Graphics - Goblin warrior - frame 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Goblin warrior - frame 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Goblin warrior - frame 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Goblin warrior - frame 1
  DEFW 42318              ; Graphics - Goblin missile thrower - frame 1
  DEFW 42386              ; Graphics - Goblin missile thrower - frame 2
  DEFW 42457              ; Graphics - Goblin missile thrower - frame 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Goblin missile thrower - frame 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Goblin missile thrower - frame 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Goblin missile thrower - frame 1
  DEFW 42529              ; Graphics - Wraith - frame 1
  DEFW 42582              ; Graphics - Wraith - frame 2
  DEFW 42644              ; Graphics - Wraith - frame 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Wraith - frame 3
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Wraith - frame 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Wraith - frame 1
  DEFW 42703              ; Graphics - Demon - frame 1
  DEFW 42824              ; Graphics - Demon - frame 2
  DEFW 42950              ; Graphics - Demon - frame 3
  DEFW 43080              ; Graphics - Materialization effect - frame 1
  DEFW 43098              ; Graphics - Materialization effect - frame 2
  DEFW 43117              ; Graphics - Materialization effect - frame 3
  DEFW 43141              ; Graphics - Materialization effect - frame 4
  DEFW 43167              ; Graphics - Materialization effect - frame 5
  DEFW 43195              ; Graphics - Materialization effect - frame 6
  DEFW L43223             ; Graphics - UNUSED
  DEFW 43229              ; Graphics - Disintegration animation - frame 1
  DEFW 43300              ; Graphics - Disintegration animation - frame 2
  DEFW 43354              ; Graphics - Disintegration animation - frame 3
  DEFW 43399              ; Graphics - Disintegration animation - frame 4
  DEFW 43438              ; Graphics - Disintegration animation - frame 5
  DEFW 43473              ; Graphics - Disintegration animation - frame 6
  DEFW L43494             ; Graphics - Shield spell barrier
  DEFW 43500              ; Graphics - Shield spell barrier - frame 1
  DEFW 43555              ; Graphics - Shield spell barrier - frame 2
  DEFW 43611              ; Graphics - Foreground scenery - Skeleton
  DEFW 43664              ; Graphics - Foreground scenery - Seat
  DEFW 43704              ; Graphics - Foreground scenery - Table
  DEFW 43783              ; Graphics - Foreground scenery - Stool
  DEFW 43823              ; Graphics - Foreground scenery - Misc
  DEFW 43883              ; Graphics - Foreground scenery - Cube
  DEFW 43923              ; Graphics - Foreground scenery - Box
  DEFW 44001              ; Graphics - Foreground scenery - Rubble
  DEFW 44045              ; Graphics - Foreground scenery - Stalagmites 1
  DEFW 44097              ; Graphics - Foreground scenery - Boulder
  DEFW 44145              ; Graphics - Foreground scenery - Crevasse
  DEFW 44181              ; Graphics - Foreground scenery - Skull pile
  DEFW 44232              ; Graphics - Foreground scenery - Stalagmites 2
  DEFW 44282              ; Graphics - Foreground scenery - Spikes
  DEFW 44350              ; Graphics - Foreground scenery - Pool
  DEFW 44386              ; Graphics - Foreground scenery - Mound
  DEFW 44424              ; Graphics - Maroc's shadow
  DEFW 44444              ; Graphics - BLANK 'DUMMY' GRAPHIC
  DEFW 44450              ; Graphics - Spider - frame 1
  DEFW 44515              ; Graphics - Spider - frame 2
  DEFW 44589              ; Graphics - Bat - frame 1
  DEFW 44637              ; Graphics - Bat - frame 2
  DEFW 44677              ; Graphics - Bat - frame 3
  DEFW 44732              ; Graphics - Bat - frame 4
  DEFW 44775              ; Graphics - Scroll display icon for spell charges
  DEFW 44788              ; Graphics - Dragon flame energy bar on scroll
  DEFW 44966              ; Graphics - Scroll spell arrow pointer
  DEFW 45040              ; Graphics - Key 1
  DEFW 45055              ; Graphics - Chest (closed)
  DEFW 45085              ; Graphics - Chest (open)
  DEFW 45121              ; Graphics - Buried bottle (pre-state)
  DEFW 45147              ; Graphics - Broken bottle (post-state)
  DEFW 45169              ; Graphics - Pick/lever
  DEFW 45187              ; Graphics - Cheese
  DEFW 45220              ; Graphics - Mouse hole
  DEFW 45246              ; UNUSED
  DEFW 45252              ; UNUSED
  DEFW 45258              ; Graphics - Key (hanging)
  DEFW 45288              ; Graphics - Key 2
  DEFW 45305              ; Graphics - Star (on floor)
  DEFW 45333              ; Graphics - Star symbol
  DEFW 45358              ; Graphics - Coins
  DEFW 45396              ; Graphics - Fish
  DEFW 45416              ; Graphics - Bottle
  DEFW 45436              ; Graphics - Mushrooms
  DEFW 45463              ; Graphics - Scorpion - frame 1
  DEFW 45499              ; Graphics - Scorpion - frame 2
  DEFW 45536              ; Graphics - Axe
  DEFW 45576              ; Graphics - Bone
  DEFW 45597              ; Graphics - Orb
  DEFW 45637              ; Graphics - Sabre (non-animated)
  DEFW 45662              ; Graphics - Mouse - frame 1
  DEFW 45682              ; Graphics - Mouse - frame 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Mouse - frame 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Mouse - frame 1
  DEFW 45703              ; Graphics - Sabre (animated) - frame 1
  DEFW 45727              ; Graphics - Sabre (animated) - frame 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Sabre (animated) - frame 2
  DEFW 0                  ; Store for address pointer to flipped version of
                          ; Sabre (animated) - frame 1
  DEFW 45752              ; Graphics - Trapdoor (closed)
  DEFW 45798              ; Graphics - Trapdoor (open)
  DEFW 45868              ; Graphics - Lady
  DEFW 45916              ; Graphics - Key - left side
  DEFW 45926              ; Graphics - Key - right side
  DEFW 45935              ; Graphics - Oil jar
  DEFW 45975              ; Graphics - Coin
  DEFW 45987              ; Graphics - Altar/idol
  DEFW 46027              ; Graphics - Fire (animated) - frame 1
  DEFW 46066              ; Graphics - Fire (animated) - frame 2
  DEFW 46106              ; Graphics - Symbol - fire
  DEFW 46144              ; Graphics - Symbol - water
  DEFW 46180              ; Graphics - Symbol - earth
  DEFW 46218              ; Graphics - Symbol - air
  DEFW 46256              ; Graphics - Pick axe
  DEFW 46274              ; Graphics - Portal (floor symbol)
  DEFW 46322              ; Graphics - Portal door
  DEFW 46394              ; Graphics - Avelach, Lord of Chaos
  DEFW 46438              ; Graphics - Symbol - blank
  DEFW 46474              ; Graphics - Healing star (floor) - complete

; Unused
L39221:
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,1,1,0,0
  DEFB 1,255

; Graphics - Maroc the Mage
;
; See Trivia: Graphics data and Trivia: Maroc's sprite rotational movement for
; information on how these graphics are used.
L39247:
  DEFB %00001000          ; Graphic properties
; MAROC - FRAME 1
  DEFB 5                  ; Graphic consists of 5 tiles
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 231                ; Vertical (Y axis) pixel offset (-25 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 14,30,23,45,44,52,124,108    ;
  DEFB 40,198,198,170,238,0,146,254 ;
  DEFB 11                 ; Horizontal (X axis) pixel offset (+11 pixels)
  DEFB 231                ; Vertical (Y axis) pixel offset (-25 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 6,15,6,4,4,4,8,8       ;
  DEFB 8,8,16,16,16,48,40,104 ;
  DEFB 246                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 0,0,0,0,30,30,62,119          ;
  DEFB 119,247,227,224,108,15,51,125 ;
  DEFB 254,255,191,55,90,91,13,5     ;
  DEFB 254                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 200,136,112,250,243,115,119,7 ;
  DEFB 15,220,216,211,7,14,220,209   ;
  DEFB 67,135,207,247,249,110,51,152 ;
  DEFB 6                  ; Horizontal (X axis) pixel offset (+6 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 1,3,2,10,26,186,244,244      ;
  DEFB 116,68,72,8,8,22,87,215      ;
  DEFB 174,172,88,80,64,128,128,128 ;
; MAROC - FRAME 2
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 246                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 1,1,1,3,0,3,7,6         ;
  DEFB 6,6,7,15,14,14,9,14     ;
  DEFB 13,13,27,27,22,22,12,12 ;
  DEFB 254                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB 231                ; Vertical (Y axis) pixel offset (-25 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 16,56,56,56,116,112,120,80      ;
  DEFB 96,116,96,80,252,128,74,124     ;
  DEFB 116,96,156,29,221,221,237,243   ;
  DEFB 251,187,91,106,241,141,123,252  ;
  DEFB 254,255,255,255,222,223,223,207 ;
  DEFB 6                  ; Horizontal (X axis) pixel offset (+6 pixels)
  DEFB 231                ; Vertical (Y axis) pixel offset (-25 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 6,15,15,4,4,4,4,4              ;
  DEFB 4,4,8,8,12,12,28,24            ;
  DEFB 56,120,248,232,208,208,208,144 ;
  DEFB 144,16,80,212,214,214,148,80   ;
  DEFB 208,80,144,208,224,112,144,208 ;
; MAROC - FRAME 3
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 21                 ; Graphic consists of 21 bytes
  DEFB 1,0,3,7,7,14,14,14     ;
  DEFB 15,15,14,9,22,29,27,31 ;
  DEFB 31,31,23,23,7          ;
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 64,64,224,224,224,240,240,216  ;
  DEFB 232,240,244,236,252,224,16,214 ;
  DEFB 222,216,212,206,14,246,250,252 ;
  DEFB 255,195,28,223,191,48,143,127  ;
  DEFB 255,251,246,214,214,214,180,36 ;
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 16,56,56,16,16,16,16,16         ;
  DEFB 16,16,16,16,16,0,24,24          ;
  DEFB 16,80,80,208,208,208,208,208    ;
  DEFB 80,80,16,144,144,16,144,144     ;
  DEFB 208,208,224,224,224,224,224,240 ;
; MAROC - FRAME 4
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 21                 ; Graphic consists of 21 bytes
  DEFB 1,1,0,1,3,3,12,31    ;
  DEFB 7,16,23,31,31,6,0,15 ;
  DEFB 15,15,15,15,6        ;
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 98,183,119,114,250,250,58,218   ;
  DEFB 222,190,254,190,240,4,246,244   ;
  DEFB 244,230,155,189,62,126,126,110  ;
  DEFB 110,118,119,123,120,115,79,127  ;
  DEFB 255,255,255,254,122,117,201,153 ;
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 21                 ; Graphic consists of 21 bytes
  DEFB 128,128,128,128,96,112,252,28 ;
  DEFB 232,0,224,240,240,112,112,80  ;
  DEFB 208,208,208,32,64             ;
; MAROC - FRAME 5
  DEFB 5                  ; Graphic consists of 5 tiles
  DEFB 243                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 64,224,225,64,64,32,32,32 ;
  DEFB 32,32,32,16,16,16,12,12   ;
  DEFB 251                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 120,252,188,28,62,62,54,42 ;
  DEFB 43,59,55,127,119,127,28,99 ;
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 1,2,2,6,6,6,5,5    ;
  DEFB 1,3,3,3,3,0,7,15   ;
  DEFB 15,15,15,7,6,2,2,0 ;
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 15,143,159,159,11,202,208,223  ;
  DEFB 192,223,191,191,143,80,93,94   ;
  DEFB 95,103,120,127,255,223,223,223 ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 224,224,240,240,232,204,44,238  ;
  DEFB 14,238,238,238,206,46,97,239    ;
  DEFB 239,143,126,254,250,184,168,168 ;
; MAROC - FRAME 6
  DEFB 5                  ; Graphic consists of 5 tiles
  DEFB 243                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 64,224,224,64,64,64,64,64 ;
  DEFB 64,64,64,64,64,0,96,96    ;
  DEFB 251                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 12,12,28,18,30,30,29,27 ;
  DEFB 30,29,61,63,61,63,0,95  ;
  DEFB 241                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 16,0,56,60,28,30,30,23  ;
  DEFB 23,23,23,19,17,16,16,16 ;
  DEFB 15,31,31,31,22,27,13,6  ;
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 23,55,27,29,14,54,122,123       ;
  DEFB 123,247,247,239,239,223,31,15   ;
  DEFB 247,249,254,255,255,119,187,204 ;
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 192,192,192,224,96,160,160,64   ;
  DEFB 88,184,124,116,112,4,124,124    ;
  DEFB 188,192,112,240,240,240,224,224 ;
; MAROC - FRAME 7
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 243                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 39                 ; Graphic consists of 39 bytes
  DEFB 4,14,14,4,4,4,4,4  ;
  DEFB 4,4,4,4,4,0,12,12  ;
  DEFB 0,6,6,6,3,3,3,1    ;
  DEFB 5,5,4,4,4,4,4,3    ;
  DEFB 15,31,31,15,7,6,2  ;
  DEFB 251                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 8,12,12,12,10,14,30,30          ;
  DEFB 22,46,46,55,127,127,7,88        ;
  DEFB 123,251,27,99,105,110,159,255   ;
  DEFB 254,253,251,247,111,15,7,251    ;
  DEFB 252,255,255,183,183,183,179,147 ;
  DEFB 3                  ; Horizontal (X axis) pixel offset (+3 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 22                 ; Graphic consists of 22 bytes
  DEFB 128,128,128,128,64,128,192,236 ;
  DEFB 224,236,236,236,232,224,96,96  ;
  DEFB 128,224,224,224,96,64          ;
; MAROC - FRAME 8
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 243                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 18                 ; Graphic consists of 18 bytes
  DEFB 1,1,1,2,2,3,3,1     ;
  DEFB 1,13,28,30,15,7,7,7 ;
  DEFB 1,2                 ;
  DEFB 251                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 3,3,7,6,10,22,22,26            ;
  DEFB 30,38,14,39,111,127,0,165      ;
  DEFB 125,93,141,122,123,119,119,111 ;
  DEFB 155,187,185,165,29,125,126,190 ;
  DEFB 190,89,7,191,223,239,183,88    ;
  DEFB 3                  ; Horizontal (X axis) pixel offset (+3 pixels)
  DEFB 230                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 8,28,28,8,8,8,8,16            ;
  DEFB 16,16,16,16,16,32,0,112       ;
  DEFB 112,48,184,184,56,168,168,168 ;
  DEFB 168,168,168,168,80,80,64,88   ;
  DEFB 88,92,92,92,88,88,48,40       ;

; Graphics - Doors
;
; DOOR - FRAME 1
;
; Graphics for the middle section of this door are just 4 bytes, for the lines
; - the middle hinge line connectors, and the top and bottom lines.
;
; Flipped/mirrored versions of these doors (and door frames) are created when
; required, when Maroc enters a new room.
L40144:
  DEFB %00100011          ; Graphic properties
  DEFB 6                  ; Graphic consists of 6 graphic tiles
  DEFB 16                 ; Horizontal (X axis) pixel offset (+16 pixels)
  DEFB 217                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 127,129,129,1,129,1,129,1 ;
  DEFB 1,1,1,129,1,129,1,129     ;
  DEFB 1,57,41,17,1,17,17,1      ;
  DEFB 1,129,1,129,1,1,1,1       ;
  DEFB 1,129,1,129,1,129,129,127 ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 217                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB 40                 ; Graphic consists of 40 bytes
  DEFB 252,131,128,129,128,128,204,255 ;
  DEFB 219,255,204,128,128,129,128,129 ;
  DEFB 128,129,128,128,128,128,129,128 ;
  DEFB 129,128,204,255,219,255,204,128 ;
  DEFB 129,128,129,128,129,128,129,254 ;
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 217                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB 1                  ; Graphic consists of 1 byte
  DEFB 255
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 225                ; Vertical (Y axis) pixel offset (-31 pixels)
  DEFB 1                  ; Graphic consists of 1 byte
  DEFB 252
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 245                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB 1                  ; Graphic consists of 1 byte
  DEFB 252
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 1                  ; Graphic consists of 1 byte
  DEFB 255
; DOOR - FRAME 2
  DEFB 2                  ; Door Graphic consists of 2 graphic tiles
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 221                ; Vertical (Y axis) pixel offset (-35 pixels)
  DEFB 43                 ; Graphic consists of 43 bytes
  DEFB 192,48,12,35,1,33,1,1 ;
  DEFB 1,1,33,1,33,1,33,1    ;
  DEFB 1,25,21,9,1,9,9,33    ;
  DEFB 1,33,1,1,1,1,1,1      ;
  DEFB 1,1,33,1,33,1,33,193  ;
  DEFB 49,13,3               ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 217                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB 43                 ; Graphic consists of 43 bytes
  DEFB 192,176,140,131,136,128,192,240 ;
  DEFB 216,248,214,128,128,136,128,136 ;
  DEFB 128,136,128,128,128,128,136,128 ;
  DEFB 136,128,192,240,216,248,214,128 ;
  DEFB 128,128,128,136,128,136,128,200 ;
  DEFB 56,4,3                          ;
; DOOR - FRAME 3
  DEFB 1                  ; Door Graphic consists of 1 graphic tile
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 217                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB 47                 ; Graphic consists of 47 bytes
  DEFB 128,192,160,144,88,132,198,193  ;
  DEFB 229,225,209,129,129,161,129,165 ;
  DEFB 129,165,161,133,129,129,173,137 ;
  DEFB 165,129,193,193,229,225,213,129 ;
  DEFB 129,129,129,129,129,161,133,161 ;
  DEFB 69,33,21,9,5,3,1                ;

; Graphics - Wall/floor connector sections
;
; The graphics that make up the joins between walls and floors, that provide
; the 3D perspective effect for the rooms.
;
; Flipped/mirrored versions of the side and corner graphics are generated when
; Maroc enters each new room (though the corner wall vertical sections are
; needed for every room).
;
; BACK WALL/FLOOR SECTION
L40392:
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 1,1,1,254
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 1,1,1,254
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 16,16,16,239
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 33,33,33,33,223
; SIDE WALL/FLOOR SECTION
  DEFB %00100001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 1,193,49,13,3
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 244                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 2,194,50,14,3
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 4,4,4,196,52,12,3
  DEFB 8                  ; Horizontal (X axis) pixel offset (8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 8,8,8,8,200,56,12,3
; CORNER WALL SECTION
  DEFB %00100001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 209                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB 48                 ; Graphic consists of 48 bytes
  DEFB 128,128,128,128,128,96,176,140  ;
  DEFB 135,132,132,132,132,132,132,132 ;
  DEFB 100,156,134,129,128,128,128,128 ;
  DEFB 128,128,96,152,134,133,132,132  ;
  DEFB 132,132,132,132,132,132,100,156 ;
  DEFB 134,129,128,128,128,128,128,128 ;

; Graphics - Door frames
;
; A flipped/mirrored version of the side wall door frame is generated, when
; needed, whenever Maroc enters a new room.
;
; DOOR FRAME (BACK WALL)
L40515:
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 241                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB 209                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 110,145,145,145,145,145,110
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 209                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 238,17,17,17,17,17,238
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 209                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 238,17,17,17,17,17,238
  DEFB 9                  ; Horizontal (X axis) pixel offset (+9 pixels)
  DEFB 209                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB 47                 ; Graphic consists of 47 bytes
  DEFB 238,17,17,17,17,17,238,16 ;
  DEFB 16,16,16,16,16,16,16,16   ;
  DEFB 16,16,16,16,16,16,16,16   ;
  DEFB 16,16,16,16,16,16,16,16   ;
  DEFB 16,16,16,16,16,16,16,16   ;
  DEFB 16,16,16,16,16,16,16      ;
; DOOR FRAME (SIDE WALL)
  DEFB %00100001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 245                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB 198                ; Vertical (Y axis) pixel offset (-58 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 224,152,150,145,145,145,81,49 ;
  DEFB 13,3                          ;
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 201                ; Vertical (Y axis) pixel offset (-55 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 128,96,24,22,17,17,17,209 ;
  DEFB 49,13,3                   ;
  DEFB 5                  ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB 205                ; Vertical (Y axis) pixel offset (-51 pixels)
  DEFB 51                 ; Graphic consists of 51 bytes
  DEFB 128,96,24,22,17,17,17,209 ;
  DEFB 49,13,3,16,16,16,16,16    ;
  DEFB 16,16,16,16,16,16,16,16   ;
  DEFB 16,16,16,16,16,16,16,16   ;
  DEFB 16,16,16,16,16,16,16,16   ;
  DEFB 16,16,16,16,16,16,16,16   ;
  DEFB 16,16,16                  ;

; Graphics - Brickwork graphics
;
; Used as decoration on the back walls in some of Avalon's rooms and caverns.
; See the routine at L49765 for the instructions and algorithm determining
; which bit of brickwork to use.
;
; Also see Trivia - Setting the scene(ry) for information about how this
; brickwork is stored in the room's data.
;
; BRICKWORK GRAPHIC 1
L40680:
  DEFB %00000100          ; Graphic properties (4 versions of this graphic)
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 255,4,4,4,4,255,32,32 ;
  DEFB 32,32,127             ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 255,65,65,65,65,255
; BRICKWORK GRAPHIC 2
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 250                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 255,129,129,129,129,255
  DEFB 254                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 255,129,129,129,255
; BRICKWORK GRAPHIC 3
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 255,128,128,128,128,255,8,8 ;
  DEFB 8,8,15                      ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 254,130,130,130,130,254,16,16 ;
  DEFB 16,16,240                     ;
; BRICKWORK GRAPHIC 4
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 251                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB 2                  ; Vertical (Y axis) pixel offset (+2 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 255,129,129,129,129,255
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 255,129,129,129,129,255

; Graphics - Wall/floor connector sections 2
;
; Door frames & scenery brickwork from cavern levels e.g. Mines of Madness. As
; with the 'brick level' connectors (L40392), flipped/mirrored versions of the
; side wall and corner graphics are created when needed.
L40771:
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 21,22,248
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 64,160,160,166,166,38,41,16
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 144,72,183
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 64,96,82,82,141
; Side wall-floor connectors
  DEFB %00100001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 144,114,22,10,1
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 244                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 16,232,8,7
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 128,72,119
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 192,40,20,2,1
; CORNER WALL SECTION
  DEFB %00100001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 225                ; Vertical (Y axis) pixel offset (-31 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 228,254,83,83,67,67,6,4 ;
  DEFB 4,6,6,6,4,25,27,11      ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 241                ; Vertical (Y axis) pixel offset (-15 pixels)
  DEFB 17                 ; Graphic consists of 17 bytes
  DEFB 212,150,27,27,18,49,59,29 ;
  DEFB 13,9,10,1,9,9,217,117     ;
  DEFB 7                         ;

; Graphics - Door frames 2
;
; Door frames & scenery brickwork from cavern levels e.g. Mines of Madness. As
; with the 'brick level' door frames (L40515), flipped/mirrored versions of the
; side wall graphics are created when needed.
;
; DOOR FRAME - BACK WALL
L40876:
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 241                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB 212                ; Vertical (Y axis) pixel offset (-44 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 1,35,127,225,128
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 211                ; Vertical (Y axis) pixel offset (-45 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 2,63,124,128
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 211                ; Vertical (Y axis) pixel offset (-45 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 66,254,60,3
  DEFB 9                  ; Horizontal (X axis) pixel offset (+9 pixels)
  DEFB 212                ; Vertical (Y axis) pixel offset (-44 pixels)
  DEFB 44                 ; Graphic consists of 44 bytes
  DEFB 65,114,252,8,4,2,1,1 ;
  DEFB 1,1,1,1,1,1,1,1      ;
  DEFB 1,1,1,1,1,1,1,1      ;
  DEFB 1,1,1,1,1,1,1,1      ;
  DEFB 1,1,1,1,1,1,1,1      ;
  DEFB 1,1,1,1              ;
; DOOR FRAME - SIDE WALL
  DEFB %00100001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 245                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB 200                ; Vertical (Y axis) pixel offset (-56 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 144,126,207,129
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 204                ; Vertical (Y axis) pixel offset (-52 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 160,118,28,15
  DEFB 5                  ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB 206                ; Vertical (Y axis) pixel offset (-50 pixels)
  DEFB 47                 ; Graphic consists of 47 bytes
  DEFB 128,192,224,26,28,22,18,1 ;
  DEFB 1,1,1,1,1,1,1,1           ;
  DEFB 1,1,1,1,1,1,1,1           ;
  DEFB 1,1,1,1,1,1,1,1           ;
  DEFB 1,1,1,1,1,1,1,1           ;
  DEFB 1,1,1,1,1,1,1             ;

; Graphics - Cavern back wall background graphics
;
; These are the 'cavern equivalent' of the brickwork graphics at L40680.
;
; Used as decoration on the back walls in some of Avalon's caverns. See the
; routine at L49765 for the instructions and algorithm determining which bit of
; scenery to use.
;
; Also see Trivia - Setting the scene(ry) for information about how this
; scenery is stored in the room's data.
;
; BACK WALL SCENERY 1
L41013:
  DEFB %00000100          ; Graphic properties (4 versions of graphic)
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 250                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 2,175,90,88,80,16
  DEFB 2                  ; Horizontal (X axis) pixel offset (+2 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 7,11,75,185,176,160,160,32 ;
  DEFB 32,32,32                   ;
; BACK WALL SCENERY 2
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 8,24,25,59,59,59,108,130
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 8,8,40,188,165,199
; BACK WALL SCENERY 3
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 247                ; Horizontal (X axis) pixel offset (-9 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 128,192,208,243,127,94,82,82 ;
  DEFB 82,82,82,2,2,2               ;
  DEFB 255                ; Horizontal (X axis) pixel offset (-1 pixel)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 64,251,247,183,151,146,146,146 ;
  DEFB 128                            ;
; BACK WALL SCENERY 4
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 21                 ; Graphic consists of 21 bytes
  DEFB 1,1,141,149,149,150,210,96 ;
  DEFB 96,96,96,96,32,64,64,96    ;
  DEFB 96,226,165,171,151         ;

; Graphics - Tunnels
;
; For room numbers 224-255 - the vertically scrolling tunnel rooms (L26384).
;
; These graphics form forming the wall boundaries for the tunnels. They are
; mirrored/flipped for the left hand side walls.
L41114:
  DEFB %00100001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 246                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB 215                ; Vertical (Y axis) pixel offset (-41 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 128,160,92,102,32,36,120,24 ;
  DEFB 28,26,12,7,3                ;
  DEFB 254                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB 228                ; Vertical (Y axis) pixel offset (-28 pixels)
  DEFB 33                 ; Graphic consists of 33 bytes
  DEFB 128,192,224,128,192,160,192,64 ;
  DEFB 100,76,60,44,106,133,198,199   ;
  DEFB 225,208,96,48,34,44,53,54      ;
  DEFB 115,97,56,52,24,29,7,1         ;
  DEFB 1                              ;
  DEFB 6                  ; Horizontal (X axis) pixel offset (+6 pixels)
  DEFB 1                  ; Vertical (Y axis) pixel offset (+1 pixel)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 16,48,176,240,240,16,26,5

; Graphics - Servant
;
; Maroc's servant, used to pick up, drop, and manipulate objects.
L41179:
  DEFB %10000010          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
; SERVANT GRAPHIC - FRAME 1
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 56,124,84,124,37,254,126,62 ;
  DEFB 30,30,28,56,48,56,24,28     ;
; SERVANT GRAPHIC - FRAME 2
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 56,124,84,124,47,254,120,120 ;
  DEFB 120,56,56,28,28,24,24,112    ;

; Graphics - Eye cursor
;
; Flashing eye cursor - used for interaction/target spells, e.g. MISSILE, OPEN
; and REVEAL.
;
; EYE CURSOR GRAPHIC - FRAME 1
L41220:
  DEFB %10000010          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Eye cursor frame 1 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 1,33,16,0,7,26,100,132 ;
  DEFB 116,14,1,0,8,16        ;
; Eye cursor frame 1 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 8,16,0,192,48,44,35,44 ;
  DEFB 48,192,0,16,136,128    ;
; EYE CURSOR - FRAME 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Eye cursor frame 2 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 1,17,15,59,199,59,15,17 ;
  DEFB 1                       ;
; Eye cursor frame 2 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 16,32,224,220,227,220,224,16

; Graphics - Scroll
;
L41280:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Scroll - tile 1
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 63,127,127,127,61,27,26,13 ;
  DEFB 15,15,63,79,79,63          ;
; Scroll - tile 2
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 252,228,248,224,240,112,120,120 ;
  DEFB 124,124,252,252,252,248         ;

; Graphics - Caliburn
;
L41316:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Caliburn - blade
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 1,3,7,14,28,56,112,224 ;
  DEFB 192                    ;
; Caliburn - hilt
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 3,63,78,22,58,114,228,192 ;
  DEFB 128                       ;

; Graphics - Spell icons
;
; Flashing icons that appear in the top right of the scroll (e.g. the staff
; head in the above image for the MOVE spell) when a spell is in effect.
;
; The scroll icon (L41280) is used as an icon for the rest of the spells whose
; icons aren't listed here.
;
; AMULET (icon for AMULET spell)
L41342:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Amulet - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 7,24,39,78,93,157,189,190 ;
  DEFB 184,190,158,94,70,35,24,7 ;
; Amulet - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 224,24,228,114,186,185,189,125 ;
  DEFB 29,125,121,122,98,196,24,224   ;
; CHALICE (icon for CHALICE spell)
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Chalice - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 18,69,47,63,95,56,251,27 ;
  DEFB 253,61,254,30,62,77,27   ;
; Chalice - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 72,212,252,253,254,12,232,239 ;
  DEFB 222,152,190,184,188,223,200   ;
; Ring (icon for SERVANT spell)
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 60,126,231,195,195,231,126,60
; Staff head (icon for MOVE spell)
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 62,107,107,127,34,62,28,28
  DEFB 28,28,28,28,28,28,28,28
; Jewel (icon for WAYSTONE, SUMMON, DEFENCE, WRAITHBANE and ELECTRIC spells)
  DEFB 1                  ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 24,52,114,241,143,78,44,24

; Graphics - Missiles & bolts
;
; Various bolts and missiles used for ranged attacks by Maroc and some
; creatures. See the missile table at L27868 to find out which creatures fire
; which missile type.
;
; MISSILE 1
L41467:
  DEFB %10000011          ; Graphic properties
; Missile 1 - frame 1
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 12,152,152,126,126,25,25,48
; Missile 1 - frame 2
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 32,78,89,124,62,154,114,4
; Missile 1 - frame 3
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 24,32,62,189,189,124,4,24
; MISSILE 2
;
; Missile 2 - frame 1
  DEFB %10000011          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Missile 2 - frame 1 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 7,63,124,103,79,159,156,56 ;
  DEFB 60,62,31,15,7              ;
; Missile 2 - frame 1 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 192,240,124,204,236,246,118,230 ;
  DEFB 204,28,252,248,224              ;
; Missile 2 - frame 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Missile 2 - frame 2 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 6,31,63,60,56,57,61,60 ;
  DEFB 31,15,7                ;
; Missile 2 - frame 2 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 32,48,24,152,204,236,108,108 ;
  DEFB 204,28,248,240,224           ;
; Missile 2 - frame 3
  DEFB 2                  ; Graphic consists of 2 tiles
; Missile 2 - frame 3 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 7,15,31,60,57,114,118,119 ;
  DEFB 55,51,48,24,15,3          ;
; Missile 2 - frame 3 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 240,248,252,28,156,188,60,120 ;
  DEFB 248,240,192,8,240,224         ;
; MISSILE 3
;
; Missile 3 - frame 1
  DEFB %10000011          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Missile 3 - frame 1 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 48,121,235,100,97,35,23,55 ;
  DEFB 51,56,62,31,2,1            ;
; Missile 3 - frame 1 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 192,232,60,198,150,12,28,156 ;
  DEFB 60,244,12,252,248,240        ;
; Missile 3 - frame 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Missile 3 - frame 2 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 3,7,14,56,123,39,24,50 ;
  DEFB 51,29,24,56,63,30      ;
; Missile 3 - frame 2 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 128,192,224,48,156,230,118,23 ;
  DEFB 143,254,140,248,240           ;
; Missile 3 - frame 3
  DEFB 2                  ; Graphic consists of 2 tiles
; Missile 3 - frame 3 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 3,7,28,61,114,102,102,99 ;
  DEFB 51,28,12,3,3             ;
; Missile 3 - frame 3 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 8,188,126,206,206,100,104,40 ;
  DEFB 180,116,124,248,192          ;

; Graphics - Warlock
;
; There are seven warlocks that materialize on the walls across Avalon's
; levels. Maroc can decide to trade with them, or destroy them. See the warlock
; data at L27772 for details.
;
; For information on this creature, see Creatures: Warlock
L41707:
  DEFB %10000011          ; Graphic properties
; WARLOCK - FRAME 1
  DEFB 2                  ; Graphic consists of 2 tiles
; Warlock frame 1 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 3,4,5,4,2,2,2,6         ;
  DEFB 14,62,90,26,86,86,86,84 ;
  DEFB 67,71,7,5,5,5,5,5       ;
  DEFB 11,15,4,14,20,10,0,4    ;
; Warlock frame 1 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 226,18,80,18,43,47,47,121       ;
  DEFB 121,121,241,240,240,240,240,208 ;
  DEFB 96,112,112,112,112,112,80,80    ;
  DEFB 80,104,104,144,40,4,64,144      ;
; WARLOCK - FRAME 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Warlock frame 2 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 3,4,7,4,2,2,2,14        ;
  DEFB 62,39,91,67,27,27,27,19 ;
  DEFB 19,19,3,2,2,2,6,5       ;
  DEFB 5,7,5,5,0,10,4,2        ;
; Warlock - frame 2 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 224,16,112,16,32,35,40,58       ;
  DEFB 55,119,118,114,114,98,98,0      ;
  DEFB 160,176,176,176,176,176,176,184 ;
  DEFB 168,168,184,24,144,0,64,144     ;
; WARLOCK - FRAME 3
  DEFB 2                  ; Graphic consists of 2 tiles
; Warlock frame 3 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 3,4,4,4,2,2,2,0          ;
  DEFB 14,63,111,35,43,44,11,11 ;
  DEFB 9,11,3,3,2,6,6,6         ;
  DEFB 6,6,5,6,1,4,1,4          ;
; Warlock frame 3 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 224,16,16,16,32,32,32,32       ;
  DEFB 60,122,120,114,114,114,114,82  ;
  DEFB 98,114,120,248,248,232,232,232 ;
  DEFB 200,136,244,24,172,140,32,148  ;

; Graphics - Guardian of Chaos
;
; For information on this creature, see Creatures: Guardian of Chaos
L41921:
  DEFB %11100011          ; Graphic properties
; GUARDIAN OF CHAOS - FRAME 1
  DEFB 2                  ; Graphic consists of 2 tiles
; Guardian of Chaos - frame 1 - left side
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 33                 ; Graphic consists of 33 bytes
  DEFB 4,4,6,15,1,1,23,23             ;
  DEFB 23,23,6,17,79,165,231,165      ;
  DEFB 166,166,228,228,165,235,206,87 ;
  DEFB 29,0,30,30,30,28,0,28          ;
  DEFB 60                             ;
; Guardian of Chaos - frame 1 - right side
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 33                 ; Graphic consists of 33 bytes
  DEFB 128,128,128,224,224,240,241,241 ;
  DEFB 199,175,111,227,10,108,110,6    ;
  DEFB 62,188,220,224,124,252,172,252  ;
  DEFB 80,192,48,112,112,112,0,120     ;
  DEFB 120                             ;
; GUARDIAN OF CHAOS - FRAME 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Guardian of Chaos - frame 2 - left side
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 238                ; Vertical (Y axis) pixel offset (-18 pixels)
  DEFB 30                 ; Graphic consists of 30 bytes
  DEFB 16,15,15,0,0,11,11,11         ;
  DEFB 11,5,72,79,37,231,229,166     ;
  DEFB 164,165,228,229,171,234,71,91 ;
  DEFB 1,60,60,0,124,252             ;
; Guardian of Chaos - frame 2 - right side
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 33                 ; Graphic consists of 33 bytes
  DEFB 16,144,160,224,96,96,224,224   ;
  DEFB 228,206,176,71,223,95,142,38   ;
  DEFB 100,128,198,238,30,224,172,252 ;
  DEFB 80,200,120,112,112,112,0,112   ;
  DEFB 240                            ;
; GUARDIAN OF CHAOS - FRAME 3
  DEFB 2                  ; Graphic consists of 2 tiles
; Guardian of Chaos - frame 3 - left side
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 35                 ; Graphic consists of 35 bytes
  DEFB 16,16,31,31,31,16,16,29         ;
  DEFB 29,13,5,25,78,231,165,231       ;
  DEFB 165,167,164,231,229,167,230,106 ;
  DEFB 78,29,3,60,30,31,15,15          ;
  DEFB 3,31,30                         ;
; Guardian of Chaos - frame 3 - right side
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 33                 ; Graphic consists of 33 bytes
  DEFB 32,32,161,225,227,111,223,223  ;
  DEFB 231,226,200,156,94,190,190,167 ;
  DEFB 31,236,224,8,120,84,252,172    ;
  DEFB 254,64,188,236,60,60,0,60      ;
  DEFB 56                             ;

; Graphics - Goblin warrior
;
; Also known as Goblin Swordsman. For information on this creature, see
; Creatures: Goblin warrior
L42140:
  DEFB %11100011          ; Graphic properties
; GOBLIN WARRIOR - FRAME 1
  DEFB 2                  ; Graphic consists of 2 tiles
; Goblin warrior - frame 1 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 29                 ; Graphic consists of 29 bytes
  DEFB 6,11,11,5,30,15,3,7 ;
  DEFB 0,1,1,1,1,0,0,0     ;
  DEFB 0,31,0,1,3,7,6,0    ;
  DEFB 6,3,3,3,14          ;
; Goblin warrior - frame 1 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 128,96,216,24,228,238,246,250  ;
  DEFB 122,58,253,251,248,222,188,112 ;
  DEFB 224,192,160,112,48,24,28,124   ;
; GOBLIN WARRIOR - FRAME 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Goblin warrior - frame 2 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 30                 ; Graphic consists of 30 bytes
  DEFB 48,88,88,40,240,112,24,61 ;
  DEFB 9,4,131,67,35,19,8,7      ;
  DEFB 3,0,0,3,3,6,6,6           ;
  DEFB 0,6,6,6,6,14              ;
; Goblin warrior - frame 2 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 22                 ; Graphic consists of 22 bytes
  DEFB 64,96,80,184,220,204,188,96  ;
  DEFB 156,124,126,0,216,176,96,224 ;
  DEFB 224,80,56,28,6,12            ;
; GOBLIN WARRIOR - FRAME 3
  DEFB 2                  ; Graphic consists of 2 tiles
; Goblin warrior - frame 3 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 27                 ; Graphic consists of 27 bytes
  DEFB 12,22,22,10,60,30,7,14 ;
  DEFB 0,1,1,1,1,0,96,28      ;
  DEFB 3,0,6,13,11,7,7,6      ;
  DEFB 1,3,1                  ;
; Goblin warrior - frame 3 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 23                 ; Graphic consists of 23 bytes
  DEFB 192,176,80,204,236,244,228,234 ;
  DEFB 106,151,86,223,232,224,128,176 ;
  DEFB 176,144,208,128,192,96,192     ;

; Graphics - Goblin missile thrower
;
; For information on this creature, see Creatures: Goblin missile thrower
L42317:
  DEFB %11100011          ; Graphic properties
; GOBLIN MISSILE THROWER - FRAME 1
  DEFB 2                  ; Graphic consists of 2 tiles
; Goblin missile thrower - frame 1 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 29                 ; Graphic consists of 29 bytes
  DEFB 3,7,7,0,4,15,3,7         ;
  DEFB 224,192,166,150,11,5,0,1 ;
  DEFB 1,0,3,7,15,0,15,14       ;
  DEFB 7,7,2,1,7                ;
; Goblin missile thrower - frame 1 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 192,192,224,32,160,160,128,96  ;
  DEFB 248,220,220,44,180,236,108,156 ;
  DEFB 236,0,236,236,252,96,28,28     ;
  DEFB 28,28,140,140,4,2,6,30         ;
; GOBLIN MISSILE THROWER - FRAME 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Goblin missile thrower - frame 2 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 3,7,7,0,4,15,3,231       ;
  DEFB 192,160,144,9,7,111,96,0 ;
  DEFB 0,0,0,1,1,0,0,1          ;
  DEFB 3,7,3,1,0,0,0,1          ;
; Goblin missile thrower - frame 2 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 192,192,224,32,160,160,128,112 ;
  DEFB 248,124,238,238,238,222,62,254 ;
  DEFB 246,0,246,246,254,0,248,232    ;
  DEFB 216,24,156,140,4,192,198,142   ;
; GOBLIN MISSILE THROWER - FRAME 3
  DEFB 2                  ; Graphic consists of 2 tiles
; Goblin missile thrower - frame 3 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 3,7,7,0,4,15,3,231      ;
  DEFB 192,161,145,8,5,3,15,29 ;
  DEFB 41,32,3,3,7,0,3,3       ;
  DEFB 1,1,1,1,1,0,1,3         ;
; Goblin missile thrower - frame 3 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 192,192,224,32,160,160,128,120 ;
  DEFB 252,76,244,236,220,184,120,248 ;
  DEFB 236,0,236,236,252,0,176,160    ;
  DEFB 160,160,160,152,152,48,128,128 ;

; Graphics - Wraith
;
; For information on this creature, see Creatures: Wraith
L42528:
  DEFB %11100011          ; Graphic properties
; WRAITH - FRAME 1
  DEFB 2                  ; Graphic consists of 2 tiles
; Wraith - frame 1 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 242                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB 22                 ; Graphic consists of 22 bytes
  DEFB 120,252,158,158,124,120,240,36 ;
  DEFB 227,2,98,121,73,77,69,134      ;
  DEFB 130,132,7,7,3,1                ;
; Wraith - frame 1 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 224,176,176,168,80,80,96,224    ;
  DEFB 176,216,236,118,182,182,180,212 ;
  DEFB 84,72,88,112,224,192,192,96     ;
; WRAITH - FRAME 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Wraith - frame 2 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 242                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB 31                 ; Graphic consists of 31 bytes
  DEFB 60,126,39,39,222,92,114,3 ;
  DEFB 48,0,0,0,0,0,56,47        ;
  DEFB 47,46,73,67,134,141,27,22 ;
  DEFB 45,43,43,43,51,29,2       ;
; Wraith - frame 2 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 184,92,110,119,53,85,85,153   ;
  DEFB 250,26,230,108,216,184,96,192 ;
  DEFB 128,0,0,0,0,0,128,112         ;
; WRAITH - FRAME 3
  DEFB 2                  ; Graphic consists of 2 tiles
; Wraith - frame 3 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 242                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB 27                 ; Graphic consists of 27 bytes
  DEFB 120,252,78,78,188,184,228,6 ;
  DEFB 35,192,0,16,56,44,79,76     ;
  DEFB 137,139,2,5,13,13,13,13     ;
  DEFB 6,3,1                       ;
; Wraith - frame 3 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 224,184,214,91,91,43,214,54 ;
  DEFB 196,113,208,160,96,96,64,96 ;
  DEFB 112,152,236,60,24,24,16,16  ;

; Graphics - Demon
;
; For information on this creature, see Creatures: Demon
L42702:
  DEFB %10000011          ; Graphic properties
; DEMON - FRAME 1
  DEFB 7                  ; Graphic consists of 7 tiles
; Demon - frame 1 - tile 1
  DEFB 228                ; Horizontal (X axis) pixel offset (-28 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 2                  ; Graphic consists of 2 bytes
  DEFB 31,39
; Demon - frame 1 - tile 2
  DEFB 236                ; Horizontal (X axis) pixel offset (-20 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 192,248,255,124,63,30,29,11 ;
  DEFB 15,15                       ;
; Demon - frame 1 - tile 3
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 21                 ; Graphic consists of 21 bytes
  DEFB 224,127,63,207,241,254,254,253 ;
  DEFB 123,39,63,7,3,1,1,3            ;
  DEFB 2,2,2,1,1                      ;
; Demon - frame 1 - tile 4
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 242                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB 31                 ; Graphic consists of 31 bytes
  DEFB 129,157,255,119,0,99,85,0      ;
  DEFB 0,34,62,255,255,255,183,201    ;
  DEFB 119,107,190,178,191,255,107,75 ;
  DEFB 83,151,166,100,50,50,154       ;
; Demon - frame 1 - tile 5
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 23                 ; Graphic consists of 23 bytes
  DEFB 3,7,28,251,247,159,95,191     ;
  DEFB 95,111,246,254,248,248,112,96 ;
  DEFB 64,64,160,160,160,160,160     ;
; Demon - frame 1 - tile 6
  DEFB 12                 ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 255,243,14,252,120,176,208,240 ;
  DEFB 128                            ;
; Demon - frame 1 - tile 7
  DEFB 20                 ; Horizontal (X axis) pixel offset (+20 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 112,236,128
; DEMON - FRAME 2
  DEFB 5                  ; Graphic consists of 5 tiles
; Demon - frame 2 - tile 1
  DEFB 236                ; Horizontal (X axis) pixel offset (-20 pixels)
  DEFB 243                ; Vertical (Y axis) pixel offset (-13 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 120,156,15,7,5,7,3,3 ;
  DEFB 3,3,3,2,1            ;
; Demon - frame 2 - tile 2
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 245                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB 17                 ; Graphic consists of 17 bytes
  DEFB 128,224,120,188,220,238,227,221 ;
  DEFB 126,254,253,59,23,15,7,3        ;
  DEFB 1                               ;
; Demon - frame 2 - tile 3
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 241                ; Vertical (Y axis) pixel offset (-15 pixels)
  DEFB 34                 ; Graphic consists of 34 bytes
  DEFB 128,128,156,255,119,0,99,54   ;
  DEFB 0,0,34,68,190,127,190,182     ;
  DEFB 73,119,137,190,189,18,1,112   ;
  DEFB 112,64,68,132,140,137,201,205 ;
  DEFB 109,125                       ;
; Demon - frame 2 - tile 4
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 241                ; Vertical (Y axis) pixel offset (-15 pixels)
  DEFB 34                 ; Graphic consists of 34 bytes
  DEFB 128,128,128,128,0,1,7,29        ;
  DEFB 27,32,111,223,191,127,255,159   ;
  DEFB 225,127,126,248,240,224,176,120 ;
  DEFB 232,208,184,168,72,80,208,208   ;
  DEFB 80,80                           ;
; Demon - frame 2 - tile 5
  DEFB 12                 ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB 243                ; Vertical (Y axis) pixel offset (-13 pixels)
  DEFB 12                 ; Graphic consists of 12 bytes
  DEFB 15,56,80,160,96,224,224,224 ;
  DEFB 32,240,192,128              ;
; DEMON - FRAME 3
  DEFB 4                  ; Graphic consists of 4 tiles
; Demon - frame 3 - tile 1
  DEFB 237                ; Horizontal (X axis) pixel offset (-19 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 1,3,4,3
; Demon - frame 3 - tile 2
  DEFB 245                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 39                 ; Graphic consists of 39 bytes
  DEFB 64,32,48,48,40,41,41,117       ;
  DEFB 244,246,230,22,246,247,251,123 ;
  DEFB 123,125,125,122,118,142,126,63 ;
  DEFB 31,15,7,11,11,9,9,5            ;
  DEFB 5,5,5,5,9,9,9                  ;
; Demon - frame 3 - tile 3
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 242                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB 34                 ; Graphic consists of 34 bytes
  DEFB 1,57,255,238,0,198,238,0        ;
  DEFB 1,1,69,125,255,125,109,146      ;
  DEFB 238,146,237,101,255,253,189,189 ;
  DEFB 213,213,213,149,37,173,142,22   ;
  DEFB 38,38                           ;
; Demon - frame 3 - tile 4
  DEFB 5                  ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB 237                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB 39                 ; Graphic consists of 39 bytes
  DEFB 4,8,8,8,24,24,56,44             ;
  DEFB 108,252,198,187,188,188,184,184 ;
  DEFB 184,184,120,184,200,252,240,224 ;
  DEFB 224,192,128,128,0,0,0,192       ;
  DEFB 64,64,64,64,64,128,128          ;

; Graphics - Warlock/demon materialization effect
L43079:
  DEFB %10000111          ; Graphic properties
; Materialization effect - frame 1
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 245                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 8,32,4,0,8,32,0,0  ;
  DEFB 80,36,80,2,0,16    ;
; Materialization effect - frame 2
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 244                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 16,0,8,2,40,18,40,8 ;
  DEFB 0,0,16,5,2,5,16     ;
; Materialization effect - frame 3
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 20                 ; Graphic consists of 20 bytes
  DEFB 4,0,40,16,40,0,36,16 ;
  DEFB 0,36,16,6,80,36,81,0 ;
  DEFB 4,32,8,2             ;
; Materialization effect - frame 4
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 22                 ; Graphic consists of 22 bytes
  DEFB 1,0,20,40,16,66,16,8  ;
  DEFB 20,8,34,20,40,2,40,20 ;
  DEFB 40,18,0,42,4,42       ;
; Materialization effect - frame 5
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 239                ; Vertical (Y axis) pixel offset (-17 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 24,24,40,20,32,10,100,106 ;
  DEFB 24,26,42,10,32,10,93,8    ;
  DEFB 42,80,42,36,154,88,2,16   ;
; Materialization effect - frame 6
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 239                ; Vertical (Y axis) pixel offset (-17 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 162,74,167,6,41,2,20,64  ;
  DEFB 58,48,72,2,93,12,74,48   ;
  DEFB 53,64,41,149,72,34,216,4 ;

; Graphics - Disintegration animation
;
; Animation when a creature is destroyed by Maroc.
;
; UNUSED
L43223:
  DEFB 1,0,0,1,0
; DISINTEGRATION ANIMATION
  DEFB %10000111          ; Graphic properties
; DISINTEGRATION ANIMATION - FRAME 1
  DEFB 2                  ; Graphic consists of 2 tiles
; Disintegration animation - frame 1 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 238                ; Vertical (Y axis) pixel offset (-18 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 3,62,0,3,14,1,23,0    ;
  DEFB 6,56,2,3,28,3,0,13    ;
  DEFB 0,57,0,27,0,60,0,220  ;
  DEFB 0,119,0,28,0,115,0,31 ;
; Disintegration animation - frame 1 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 238                ; Vertical (Y axis) pixel offset (-18 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 128,124,48,192,56,224,16,48 ;
  DEFB 28,224,28,48,28,192,48,192  ;
  DEFB 0,152,0,112,0,204,0,243     ;
  DEFB 0,156,0,112,0,156,0,56      ;
; DISINTEGRATION ANIMATION - FRAME 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Disintegration animation - frame 2 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 245                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB 23                 ; Graphic consists of 23 bytes
  DEFB 12,0,0,99,0,92,0,103  ;
  DEFB 0,57,0,222,0,113,0,14 ;
  DEFB 56,1,60,3,118,31,121  ;
; Disintegration animation - frame 2 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 192,8,192,0,28,0,251,0     ;
  DEFB 30,0,231,0,121,0,206,0     ;
  DEFB 48,0,206,48,143,226,60,247 ;
; DISINTEGRATION ANIMATION - FRAME 3
  DEFB 2                  ; Graphic consists of 2 tiles
; Disintegration animation - frame 3 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 19                 ; Graphic consists of 19 bytes
  DEFB 5,0,12,0,46,0,29,0   ;
  DEFB 93,0,28,3,8,51,14,20 ;
  DEFB 119,108,59           ;
; Disintegration animation - frame 3 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 19                 ; Graphic consists of 19 bytes
  DEFB 64,0,228,0,156,0,180,0      ;
  DEFB 184,0,232,4,112,140,218,231 ;
  DEFB 154,230,188                 ;
; DISINTEGRATION ANIMATION - FRAME 4
  DEFB 2                  ; Graphic consists of 2 tiles
; Disintegration animation - frame 4 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 13,0,6,48,3,12,51,12    ;
  DEFB 3,92,3,46,25,55,126,243 ;
; Disintegration animation - frame 4 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 128,0,96,0,48,0,108,0        ;
  DEFB 112,0,184,96,152,248,222,143 ;
; DISINTEGRATION ANIMATION - FRAME 5
  DEFB 2                  ; Graphic consists of 2 tiles
; Disintegration animation - frame 5 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 8,6,0,11,25,6,14,27 ;
  DEFB 14,57,15,47,94,239  ;
; Disintegration animation - frame 5 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 128,0,112,0,144,96,208,32 ;
  DEFB 232,144,112,188,238,61    ;
; DISINTEGRATION ANIMATION - FRAME 6
  DEFB 2                  ; Graphic consists of 2 tiles
; Disintegration animation - frame 6 - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 7                  ; Vertical (Y axis) pixel offset (+7 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 2,196,3,13,38,51,217
; Disintegration animation - frame 6 - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 7                  ; Vertical (Y axis) pixel offset (+7 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 128,48,0,232,96,48,192

; Graphics - Shield spell barrier
;
; Two frames, flickers around Maroc. For spells such as SHIELD, PROTECT and
; DEFENCE.
;
; Active spell checked and barrier effect implemented in the routine at L54450.
;
; UNUSED
L43494:
  DEFB 1,0,0,1,0
; SHIELD BARRIER
  DEFB %10000010          ; Graphic properties
; SHIELD BARRIER - FRAME 1
  DEFB 2                  ; Graphic consists of 2 tiles
; Shield barrier - frame 1 - left side
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 16,32,64,48,8,16,32,16 ;
  DEFB 8,28,4,24,32,28,8,16   ;
  DEFB 32,24,16,32,24,4,8,16  ;
; Shield barrier - frame 1 - right side
  DEFB 12                 ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 8,16,32,24,4,24,16,32 ;
  DEFB 24,4,8,8,4,8,16,8     ;
  DEFB 16,32,64,56,4,8,16,32 ;
; SHIELD BARRIER - FRAME 2
  DEFB 2                  ; Graphic consists of 2 tiles
; Shield barrier - frame 2 - left side
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 16,32,16,16,8,4,24,32 ;
  DEFB 24,4,8,16,48,8,4,24   ;
  DEFB 32,16,8,4,24,32,24,4  ;
; Shield barrier - frame 2 - right side
  DEFB 12                 ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB 240                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB 24                 ; Graphic consists of 24 bytes
  DEFB 16,8,4,8,16,32,24,4 ;
  DEFB 4,8,16,8,4,4,8,28   ;
  DEFB 2,4,8,4,8,16,8,4    ;

; Graphics - Foreground scenery - skeleton
;
; Foreground scenery is handled in the routine at L50433.
;
; Skeleton
L43610:
  DEFB %00000001          ; Graphic properties
  DEFB 5                  ; Graphic consists of 5 tiles
; Decorative skeleton - tile 1
  DEFB 236                ; Horizontal (X axis) pixel offset (-20 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 225,255,0,128,239,112
; Decorative skeleton - tile 2
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 224,252,3,248,231,0,7
; Decorative skeleton - tile 3
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 13,14,252,63,252,56,199
; Decorative skeleton - tile 4
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 74,165,149,149,255,149,1,255
; Decorative skeleton - tile 5
  DEFB 12                 ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 8,110,47,57,251,143,143,12

; Graphics - Foreground scenery items 1
;
; Foreground scenery is handled in the routine at L50433.
;
; SEAT
L43663:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Seat graphic - tile 1
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 7,31,127,245,170,181,159,192    ;
  DEFB 191,219,177,209,177,209,177,209 ;
; Seat graphic - tile 2
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 248,254,255,87,171,85,249,7 ;
  DEFB 255,95,175,95,175,95,175,95 ;
; TABLE
  DEFB %00000001          ; Graphic properties
  DEFB 5                  ; Graphic consists of 5 tiles
; Table - tile 1
  DEFB 236                ; Horizontal (X axis) pixel offset (-20 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 1,2,7,8,31,32,64,255      ;
  DEFB 255,255,47,47,47,46,44,56 ;
; Table - tile 2
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 255,0,255,0,255,2,1,255 ;
  DEFB 255,255                 ;
; Table - tile 3
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 255,28,239,80,191,64,128,255 ;
  DEFB 255,255                      ;
; Table - tile 4
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8  pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 255,0,255,0,255,0,0,255 ;
  DEFB 255,255                 ;
; Table - tile 5
  DEFB 12                 ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 128,64,224,16,248,4,2,255     ;
  DEFB 255,255,244,244,244,116,52,28 ;
; STOOL
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Stool - left side
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 3,62,100,136,145,226,255,232 ;
  DEFB 104,95,89,89,89,89,89,248    ;
; Stool - right side
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 224,60,70,137,19,47,255,158 ;
  DEFB 150,214,86,86,86,86,214,30  ;
; MISCELLANEOUS FOREGROUND GRAPHICS
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
; Misc foreground graphics - tile 1
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 12                 ; Graphic consists of 12 bytes
  DEFB 15,63,120,243,183,143,131,193 ;
  DEFB 49,9,7,1                      ;
; Misc foreground graphics - tile 2
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 192,241,252,252,244,228,132,4 ;
  DEFB 24,96,128                     ;
; Misc foreground graphics - tile 3
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 200,126,127,253,252,251,127,56 ;
  DEFB 0,7,1                          ;
; Misc foreground graphics - tile 4
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 12                 ; Graphic consists of 12 bytes
  DEFB 16,44,18,143,224,99,135,239 ;
  DEFB 0,24,248,240                ;
; CUBE
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
; Cube - tile 1
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 7,15,31,63,127,255,255,170      ;
  DEFB 213,170,213,170,213,170,213,255 ;
; Cube - tile 2
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 255,253,249,241,225,193,193,193 ;
  DEFB 65,193,66,196,72,208,96,192     ;

; Graphics - Foreground scenery items 2
;
; Foreground scenery is handled in the routine at L50433.
;
; BOX
L43922:
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
; Box - tile 1
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 7,13,30,61,62,255,128,128       ;
  DEFB 255,128,255,128,255,128,255,128 ;
; Box - tile 2
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 255,85,170,85,170,255,0,0 ;
  DEFB 255,0,255,0,255,0,255,0   ;
; Box - tile 3
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 255,85,170,85,170,255,0,0 ;
  DEFB 255,0,255,0,255,0,255,0   ;
; Box - tile 4
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 224,112,184,124,190,254,2,2 ;
  DEFB 254,2,254,2,254,2,254,2     ;
; RUBBLE
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
; Rubble - tile 1
  DEFB 245                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 15,39,74,24,51,44,204,200 ;
  DEFB 128                       ;
; Rubble - tile 2
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 12,62,127,159,2,1,192,199 ;
  DEFB 226,18                    ;
; Rubble - tile 3
  DEFB 5                  ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 112,248,100,100,220,160,64,240 ;
  DEFB 152,12,60,230,2,131            ;

; Graphics - Foreground scenery items 3
;
; Foreground scenery is handled in the routine at L50433.
;
; STALAGMITES 1
L44044:
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
; Stalagmites 1 - tile 1
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 2,2,3,7,7,103,103,229   ;
  DEFB 245,245,245,245,141,136 ;
; Stalagmites 1 - tile 2
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 1,3,3,3,7,7,23,53   ;
  DEFB 52,52,180,180,212,8 ;
; Stalagmites 1 - tile 3
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 128,128,136,152,152,156,156,188 ;
  DEFB 252,228,230,195,8               ;
; BOULDER
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
; Boulder - tile 1
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 7,31,63,63,127,127,223,175 ;
  DEFB 215,170,149,66,48,15       ;
; Boulder - tile 2
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 224,248,254,255,255,255,255,254 ;
  DEFB 213,170,85,168,3,252            ;
; Boulder - tile 3
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 128,140,191,127,213,106,84,128 ;
  DEFB 128                            ;
; CREVASSE
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
; Crevasse - tile 1
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 4                  ; Vertical (Y axis) pixel offset (+4 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 3,63,215,11
; Crevasse - tile 2
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 255,139,135,75,39,107,231,236 ;
  DEFB 230,237                       ;
; Crevasse - tile 3
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 254,30,142,94,76,220,204,220 ;
  DEFB 204,248,192                  ;
; SKULL PILE
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
; Skull pile - tile 1
  DEFB 244                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 15,31,63,63,38,38,22,61 ;
  DEFB 125,255,255,153,153     ;
; Skull pile - tile 2
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 14,63,191,255,204,76,99,251 ;
  DEFB 253,246,182,54,254,206      ;
; Skull pile - tile 3
  DEFB 4                  ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 128,192,192,192,128,0,240,120 ;
  DEFB 252,252,156,148,148           ;
; STALAGMITES 2
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
; Stalagmites 2 - tile 1
  DEFB 245                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 14 bytes
  DEFB 1,1,1,3,3,2,2,2         ;
  DEFB 6,70,74,234,238,177,135 ;
; Stalagmites - tile 2
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 128,192,224,176,176,176,176,176 ;
  DEFB 176,176,168,168,172,172,150,17  ;
; Stalagmites - tile 3
  DEFB 5                  ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 48,120,120,120,248,188,170,171

; Graphics - Foreground scenery items 4
;
; Foreground scenery is handled in the routine at L50433.
;
; SPIKES
L44281:
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
; Spikes - tile 1
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 8,8,8,8,8,74,74,74 ;
  DEFB 74,74,74,91,255    ;
; Spikes - tile 2
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 128,128,130,130,146,146,146,146 ;
  DEFB 146,146,146,147,255,255         ;
; Spikes - tile 3
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 8,8,8,8,8,74,74,74 ;
  DEFB 74,74,74,91,255    ;
; Spikes - tile 4
  DEFB 16                 ; Horizontal (X axis) pixel offset (+16 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 128,128,130,130,146,146,146,146 ;
  DEFB 146,146,146,147,255,255         ;
; POOL
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
; Pool - tile 1
  DEFB 242                ; Horizontal (X axis) pixel offset (-14 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 1,3,0,0,127,255,14
; Pool - tile 2
  DEFB 250                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 255,255,255,255,127,255,255,63 ;
  DEFB 127                            ;
; Pool - tile 3
  DEFB 2                  ; Horizontal (X axis) pixel offset (+2 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 192,224,252,252,255,254,241,254 ;
  DEFB 240                             ;
; MOUND
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
; Mound - tile 1
  DEFB 239                ; Horizontal (X axis) pixel offset (-17 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 7,127,129,1,2,4
; Mound - tile 2
  DEFB 247                ; Horizontal (X axis) pixel offset (-9 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 1,31,224,255,255,128
; Mound - tile 3
  DEFB 255                ; Horizontal (X axis) pixel offset (-1 pixel)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 224,248,31,7,230,12,112
; Mound - tile 4
  DEFB 7                  ; Horizontal (X axis) pixel offset (+7 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 224,252,6,14,200

; Graphics - Maroc's shadow
;
; Maroc rises and falls above his shadow depending on his movement speed (see
; Maroc's sprite rotational movement).
;
; The shadow provides a positioning reference for the player particularly when
; bumping into the side wall doors to open them.
L44423:
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
; Shadow - tile 1
  DEFB 245                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 21,170,21
; Shadow - tile 2
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 85,170,85
; Shadow - tile 3
  DEFB 5                  ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 80,170,80

; Graphics - 'Dummy' graphic
;
; This is used as a 'dummy' graphic tile for the general position of the tunnel
; or standard room, as if it were a room item/object
;
; The graphic is essentially a 'blank' (empty)
L44443:
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 1                  ; Graphic consists of 1 byte
  DEFB 0                  ; Single graphics byte, value = 0

; Graphics - Spider
;
; For information on this creature, see Creatures: Spider
L44449:
  DEFB %10000010          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
; SPIDER - FRAME 1
  DEFB 241                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB 245                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 2,5,8,16,36,42,17,40   ;
  DEFB 22,33,78,145,32,64,128 ;
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 128,64,64,32,63,255,127,254 ;
  DEFB 249,251,63,24,12            ;
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 12,9,17,34,244,248,255,248 ;
  DEFB 59,188,224,96,192          ;
  DEFB 9                  ; Horizontal (X axis) pixel offset (+9 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 96,152,135,64,124,131,48,200 ;
  DEFB 4,2,1                        ;
; Spider - Frame 2
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 241                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 3,4,0,124,131,28,34,65 ;
  DEFB 129,158,17,8,4,2,2,4   ;
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 192,32,32,32,64,127,255,255 ;
  DEFB 253,242,255,191,13,8        ;
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 246                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 1,50,47,34,36,229,250,252 ;
  DEFB 248,115,252,224,128,128   ;
  DEFB 9                  ; Horizontal (X axis) pixel offset (+9 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 128,64,160,16,136,64,32,16     ;
  DEFB 136,134,128,128,128,128,128,96 ;

; Graphics - Bat
;
; For information on this creature, see Creatures: Bat
L44588:
  DEFB %10000100          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
; Bat - animation frame 1
  DEFB 242                ; Horizontal (X axis) pixel offset (-14 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 96,248,126,35,62,15,6,5 ;
  DEFB 3                       ;
  DEFB 250                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 128,72,231,245,239,239,55,7 ;
  DEFB 8                           ;
  DEFB 2                  ; Horizontal (X axis) pixel offset (+2 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 3,6,11,151,59,125,190,184 ;
  DEFB 96,0,128                  ;
  DEFB 10                 ; Horizontal (X axis) pixel offset (+10 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 48,248,240,32,224,128
; Bat - animation frame 2
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 7,30,61,124,96
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 2,1,253,187,235,221,65,2
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 32,192,95,238,235,221,193,32
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 128,240,188,222,31,3
; Bat - animation frame 3
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 19                 ; Graphic consists of 19 bytes
  DEFB 2,1,5,11,27,61,106,208        ;
  DEFB 192,192,224,192,192,192,64,64 ;
  DEFB 64,96,32                      ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 19                 ; Graphic consists of 19 bytes
  DEFB 32,192,80,232,236,222,43,5 ;
  DEFB 1,1,3,1,1,1,1,1            ;
  DEFB 1,3,2                      ;
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 4                  ; Vertical (Y axis) pixel offset (+4 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 128,128,128,128,128,128,128
; Bat - animation frame 4
  DEFB 5                  ; Graphic consists of 5 tiles
  DEFB 237                ; Horizontal (X axis) pixel offset (-19 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 15,61,96
  DEFB 245                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 252,123,239,95,15,3
  DEFB 253                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 68,56,171,125,125,187,125,198
  DEFB 5                  ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 126,189,239,244,224,128
  DEFB 13                 ; Horizontal (X axis) pixel offset (+13 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 224,120,12

; Graphics - Scroll display icon for spell charges
;
; Spell counters at top of scroll. Indicates 'charges' left for a selected
; spell. If a spell has three or more charges, three icons will be displayed.
L44774:
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 60,126,219,201,213,213,127,62

; Graphics - Energy bar (on scroll)
;
; Represents Maroc's current energy (0-255). Each 8 byte tile of the bar
; represents 16 units of energy.
L44787:
  DEFB %00000001          ; Graphic properties
  DEFB 16                 ; Graphic consists of 16 tiles
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 129,255,251,237,214,253,223,128
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 252,156,207,255,252,255,255,127
  DEFB 16                 ; Horizontal (X axis) pixel offset (+16 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 0,24,252,132,3,19,240,192
  DEFB 24                 ; Horizontal (X axis) pixel offset (+24 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 3,7,126,255,252,255,7,1
  DEFB 32                 ; Horizontal (X axis) pixel offset (+32 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 39,200,48,225,7,254,248,224
  DEFB 40                 ; Horizontal (X axis) pixel offset (+40 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 15,63,249,224,128,224,16,32
  DEFB 48                 ; Horizontal (X axis) pixel offset (+48 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 0,192,252,127,3,0,0,0
  DEFB 56                 ; Horizontal (X axis) pixel offset (+56 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 0,0,252,254,39,17,16,33
  DEFB 64                 ; Horizontal (X axis) pixel offset (+64 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 1,6,24,48,224,255,127,15
  DEFB 72                 ; Horizontal (X axis) pixel offset (+72 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 128,64,7,15,63,252,248,224
  DEFB 80                 ; Horizontal (X axis) pixel offset (+80 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 127,255,252,255,137,17,14,0
  DEFB 88                 ; Horizontal (X axis) pixel offset (+88 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 224,248,28,7,3,1,0,0
  DEFB 96                 ; Horizontal (X axis) pixel offset (+96 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 0,2,14,248,128,192,255,127
  DEFB 104                ; Horizontal (X axis) pixel offset (+104 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 0,0,3,7,14,28,248,224
  DEFB 112                ; Horizontal (X axis) pixel offset (+112 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 24,254,225,24,4,2,1,0
  DEFB 120                ; Horizontal (X axis) pixel offset (+120 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 0,0,129,66,60,0,0,0

; Graphics - Scroll pointer arrow
;
; Pointer to the selected spell on the scroll. Position does not change.
;
; SCROLL ARROW POINTER GRAPHIC
L44965:
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 1,2,4,8,16,34,70,143 ;
  DEFB 70,36,16,8,4,2,1     ;
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 0,128,128,128,255,65,154,60 ;
  DEFB 89,130,255,128,128,128,0    ;
  DEFB 16                 ; Horizontal (X axis) pixel offset (+16 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 0,0,0,0,255,4,105,243 ;
  DEFB 69,8,255,0,0,0,0      ;
  DEFB 24                 ; Horizontal (X axis) pixel offset (+24 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 15                 ; Graphics consists of 15 bytes
  DEFB 0,0,0,0,255,17,165,205 ;
  DEFB 149,33,255,0,0,0,0     ;

; Graphics - Key and Chest
;
; Key 1
L45039:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 250                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 96,255,240,96
  DEFB 2                  ; Horizontal (X axis) pixel offset (+2 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 3                  ; Graphic consists of 3 bytes
  DEFB 248,168,168
; Chest - closed
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 127,170,151,169,249,137,240,137 ;
  DEFB 255,128,255                     ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 255,175,87,175,255,15,255,15 ;
  DEFB 254,12,248                   ;
; Chest - open
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 63,63,63,63,38,32,64,128 ;
  DEFB 128,255,128,255,128,255  ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 255,255,255,255,25,3,7,15 ;
  DEFB 15,255,15,254,12,248      ;

; Graphics - Buried bottle and Lever
;
; Buried bottle (pre-state)
L45120:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 246                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 3,6,13,27,55,111,222,205
  DEFB 254                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 8,28,242,228,232,216,184,120 ;
  DEFB 248,192                      ;
; Broken bottle (post-state)
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 8,28,52,110,221,255,0,19 ;
  DEFB 49                       ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 2                  ; Vertical (Y axis) pixel offset (+2 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 64,224,239,30,128
; Pick/lever
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 2                  ; Graphic consists of 2 bytes
  DEFB 255,255
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 1,3,3,255,255,3,3,1

; Graphics - Cheese & Mouse Hole
;
L45186:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 12                 ; Graphic consists of 12 bytes
  DEFB 3,15,62,127,128,255,247,254 ;
  DEFB 103,231,255,255             ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 248,252,238,254,254,2,254,254 ;
  DEFB 255,254,254,252,252           ;
; Mouse hole
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 7,8,23,47,95,95,191,191 ;
  DEFB 191                     ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 248,24,236,246,250,250,253,253 ;
  DEFB 253                            ;

; Graphics - Keys (key 2 and hanging key)
;
; UNUSED
L45245:
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 1                  ; Graphic consists of 1 byte
  DEFB 255
; UNUSED
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 1                  ; Graphic consists of 1 byte
  DEFB 255
; Key - hanging
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 243                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 25                 ; Graphic consists of 25 bytes
  DEFB 8,8,107,156,171,72,8,8 ;
  DEFB 8,28,42,34,34,28,8,8   ;
  DEFB 8,8,8,8,30,24,30,24    ;
  DEFB 30                     ;
; Key 2
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 112,136,143,136,112
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 31,255,21,21

; Graphics - Star
;
; Star (on floor)
;
; Star which is placed on the floor star symbol to create a permanent healing
; spot.
L45304:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 1,255,68,40,16,40,68,255 ;
  DEFB 1                        ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 128,64,255,34,20,8,20,34 ;
  DEFB 255,64,128               ;
; Star (symbol)
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 251                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 4,4,110,127,63,31,63,127 ;
  DEFB 110,4                    ;
  DEFB 3                  ; Horizontal (X axis) pixel offset (+3 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 192,192,128,0,128,192,192

; Graphics - Various
;
; Coins
L45357:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 113,251,251,138,251,138,251,138 ;
  DEFB 251,138,251,138,251,138,113     ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 192,224,224,32,224,32,224,32 ;
  DEFB 224,32,224,38,239,47,198     ;
; Fish (red herring?)
;
; Interactable object that actually does damage to Maroc. Leave it alone.
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 193,255,127,255,207,129
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 128,240,188,244,252,240
; Bottle
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 24,36,60,60,126,255,191,171 ;
  DEFB 171,171,235,255,255,255,126 ;
; Mushrooms
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 10                 ; Graphic consists of 10 bytes
  DEFB 62,95,245,223,239,18,18,18 ;
  DEFB 18,33                      ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 28,58,46,190,148,20,20,20 ;
  DEFB 34                        ;

; Graphics - Scorpion
;
; Scorpion
;
; For information on this creature, see Creatures: Scorpion
L45462:
  DEFB %10000010          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
; Scorpion - frame 1
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 7,9,9,25,27,39,3,31   ;
  DEFB 39,31,63,39,96,112,48 ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 128,128,128,160,192,128,240,136 ;
  DEFB 224,240,144,24,56,16            ;
; Scorpion - frame 2
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 3,13,25,49,53,67,27,39 ;
  DEFB 3,127,79,71,96,80,96   ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 128,128,160,160,228,136,240,128 ;
  DEFB 248,196,134,3,5,5               ;

; Graphics - Axe, Bone, Orb, Sabre
;
; Axe
L45535:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 32,88,191,190,190,190,186,82 ;
  DEFB 34,2,2,2,2,2,2,3             ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 12,50,249,125,125,125,93,74 ;
  DEFB 68,64,64,64,64,64,64,192    ;
; Bone
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 96,255,255,255,255,96
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 14,31,255,254,255,255,30
; Orb
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 7,31,58,112,64,224,193,226  ;
  DEFB 213,234,245,127,127,63,31,7 ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 224,248,124,190,94,191,95,191  ;
  DEFB 95,191,255,254,254,252,248,224 ;
; Sabre  - non-animated version
;
; Not to be confused with the animated sabre (L45702)
;
; The only use of this sabre is to kill a particular bat for a spell scroll
; (see Creatures: Bat)
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 2                  ; Vertical (Y axis) pixel offset (+2 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 1,3,6,12,56,192
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 6,110,28,28,58,58,96,96 ;
  DEFB 192,192,128             ;

; Graphics - Mouse
;
; For information on this creature, see Creatures: Mouse
;
; Mouse - frame 1
L45661:
  DEFB %11100010          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 24,24,63,127,255,24,12
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 4,226,242,252,24,16
; Mouse - frame 2
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 249                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 8,24,255,127,31,24,48
  DEFB 1                  ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 1,225,246,248,24,4

; Graphics - Sabre - animated
;
; Animated sabre
;
; Not to be confused with the non-animated sabre (45636).
;
; This (animated) sabre, found in room 57 in the Chambers of Chaos, is a moving
; room object (L29551) that does damage to Maroc if he touches it.
;
; However, it can be collected and manipulated using the servant, which makes
; it an effective weapon that can destroy a number of creatures (see
; Creatures).
L45702:
  DEFB %11100010          ; Graphic properties
; Sabre - frame 1
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 2                  ; Vertical (Y axis) pixel offset (+2 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 1,3,6,12,56,192
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 6,110,28,28,58,58,96,96 ;
  DEFB 192,192,128             ;
; Sabre - frame 2
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 6                  ; Graphic consists of 6 bytes
  DEFB 192,56,12,6,3,1
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 128,192,192,96,96,58,58,28 ;
  DEFB 28,110,6                   ;

; Graphics - Trapdoor
;
; Trapdoor - closed
L45751:
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 31,16,63,63,64,127,255,255
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 255,0,255,255,0,255,255,255
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 255,0,255,255,0,255,255,255
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 248,8,252,252,2,254,255,255
; Trapdoor - open
  DEFB %00000001          ; Graphic properties
  DEFB 4                  ; Graphic consists of 4 tiles
  DEFB 240                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB 244                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 3,2,7,4,15,15,31,24   ;
  DEFB 56,48,112,111,223,255 ;
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 244                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 255,0,255,0,255,255,255,0 ;
  DEFB 0,0,0,255,255,255         ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 244                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 255,0,255,0,255,255,255,0 ;
  DEFB 0,0,0,255,255,255         ;
  DEFB 8                  ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB 244                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 192,64,224,32,240,240,248,24 ;
  DEFB 28,12,14,246,251,255         ;

; Graphics - Lady
;
; The Lady's head appears on a wall in the Labyrinth. She faces in the
; direction of the room in which you can find the sword, Caliburn.
;
; Casting the MESSAGE spell provides the clue for this (see 29011).
L45867:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 20                 ; Graphic consists of 20 bytes
  DEFB 7,8,8,16,31,8,11,16     ;
  DEFB 24,8,12,8,7,225,162,162 ;
  DEFB 4,224,161,160           ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 247                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB 20                 ; Graphic consists of 20 bytes
  DEFB 224,24,4,4,130,98,33,33 ;
  DEFB 33,33,65,66,66,66,66,65 ;
  DEFB 65,129,1,2              ;

; Graphics - Key 3, Oil Jar, Gem, Idol
;
; Graphics - Key 3 (split)
;
; This key is broken into two parts, so is treated as two separate graphics
; rather than one graphic of two tiles.
;
; Key - part 1
L45915:
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 254                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB 5                  ; Graphic consists of 5 bytes
  DEFB 112,136,133,136,112
; Key - right side
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 4                  ; Graphic consists of 4 bytes
  DEFB 31,255,21,21
; Oil jar
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 15,8,31,63,127,127,127,97  ;
  DEFB 109,109,97,97,127,63,31,15 ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 248,8,252,247,255,255,183,247   ;
  DEFB 183,183,179,179,255,254,252,248 ;
; Coin
  DEFB %00000001          ; Graphic properties
  DEFB 1                  ; Graphic consists of 1 tile
  DEFB 252                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 7                  ; Graphic consists of 7 bytes
  DEFB 56,124,238,238,238,124,56
; Altar/idol
;
; Statue/altar found in the Chambers of Chaos
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 2,7,4,4,135,252,253,255      ;
  DEFB 15,127,255,240,124,124,28,56 ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 32,240,144,144,241,63,191,240 ;
  DEFB 252,252,252,28,120,112,112,56 ;

; Graphics - Fire
;
; Fire - animation frame 1
L46026:
  DEFB %10000010          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 17,33,96,96,48,49,25,29    ;
  DEFB 12,12,30,29,61,123,255,239 ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 0,2,130,130,198,204,204,236     ;
  DEFB 236,236,238,238,238,238,236,248 ;
; Fire - animation frame 2
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 16,8,8,12,13,29,28,28          ;
  DEFB 56,112,224,228,100,108,109,255 ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 248                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB 16                 ; Graphic consists of 16 bytes
  DEFB 0,66,132,132,140,140,142,142   ;
  DEFB 206,230,116,116,48,176,180,254 ;

; Graphics - Elemental Symbols
;
; The four elemental symbols needed to open the portal to the High Temple of
; Chaos.
;
; Fire symbol
L46105:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 7,15,29,59,120,252,254,255 ;
  DEFB 255,255,126,62,31,15,7     ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 192,224,240,248,252,254,126,62 ;
  DEFB 62,126,124,248,240,224,192     ;
; Water symbol
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 7,15,31,63,119,235,221,246 ;
  DEFB 235,125,62,31,15,7         ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 192,224,240,248,220,174,118,222 ;
  DEFB 174,124,248,240,224,192         ;
; Earth symbol
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 7,14,28,60,126,242,242,252 ;
  DEFB 254,254,126,60,26,15,7     ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 192,224,112,120,252,158,158,126 ;
  DEFB 254,254,252,120,176,224,192     ;
; Air symbol
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 7,15,31,60,124,252,128,192 ;
  DEFB 224,240,124,62,30,15,7     ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 15                 ; Graphic consists of 15 bytes
  DEFB 192,224,240,248,124,254,6,14 ;
  DEFB 30,62,252,248,112,224,192    ;

; Graphics - Pick Axe
;
; Pick axe
L46255:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 8                  ; Graphic consists of 8 bytes
  DEFB 96,192,192,255,255,192,192,96
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 0                  ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB 2                  ; Graphic consists of 2 bytes
  DEFB 255,255

; Graphics - Portal Floor Symbol and Door
;
; Portal floor symbol
;
; Place each of the element symbols (L46105) on this floor circle to reveal the
; portal door that will take you to the High Temple of Chaos.
L46273:
  DEFB %00000001          ; Graphic properties
  DEFB 3                  ; Graphic consists of 3 tiles
  DEFB 246                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 3,28,33,70,152,160,207,160 ;
  DEFB 152,70,33,28,3             ;
  DEFB 254                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB 250                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB 13                 ; Graphic consists of 13 bytes
  DEFB 254,81,140,35,32,32,223,32 ;
  DEFB 32,35,140,81,254           ;
  DEFB 6                  ; Horizontal (X axis) pixel offset (+6 pixels)
  DEFB 251                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 192,32,16,200,40,152,40,200 ;
  DEFB 16,32,192                   ;
; Portal door
;
; The portal door that takes you to the High Temple of Chaos.
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 233                ; Vertical (Y axis) pixel offset (-23 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 42,128,0,128,0,128,0,128 ;
  DEFB 0,128,0,128,0,128,0,128  ;
  DEFB 0,128,0,128,0,128,0,128  ;
  DEFB 0,128,0,128,0,128,0,128  ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 233                ; Vertical (Y axis) pixel offset (-23 pixels)
  DEFB 32                 ; Graphic consists of 32 bytes
  DEFB 170,1,0,1,0,1,0,1  ;
  DEFB 0,1,0,1,0,1,0,1    ;
  DEFB 0,1,0,1,0,1,0,1    ;
  DEFB 0,1,0,1,0,1,0,1    ;

; Graphics - Avelach, Lord of Chaos
;
; The (cube-like) manifestation of Avelach, Lord of Chaos...! Found in room 212
; in the High Temple of Chaos.
;
; Strike with the sword, Caliburn (L41316), to complete the game.
L46393:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 18                 ; Graphic consists of 18 bytes
  DEFB 127,85,234,221,218,176,220,179  ;
  DEFB 211,184,218,174,223,174,223,127 ;
  DEFB 127,15                          ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 255                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB 18                 ; Graphic consists of 18 bytes
  DEFB 248,84,170,86,43,7,23,55     ;
  DEFB 55,135,223,31,255,31,255,255 ;
  DEFB 254,248                      ;

; Graphics - Elemental Symbol (blank) and Healing Star
;
; Blank symbol
;
; After placing an Elemental Symbol (L46105) on the Portal Floor Marking
; (L46273), the symbol is wiped off the disc confirming the action has been
; successful.
L46437:
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 7,15,31,63,127,255,255,255 ;
  DEFB 255,127,63,31,15,7         ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 249                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB 14                 ; Graphic consists of 14 bytes
  DEFB 192,224,240,248,252,254,254,254 ;
  DEFB 254,252,248,240,224,192         ;
; Healing Star (Floor)
;
; After obtaining the Star Symbol (45332) from the warlock (L41707), place it
; on the Star marked on the floor (L45304) in the second room on the Gatehouse
; Level.
;
; The floor symbol will change its appearance to this graphic, and provide a
; constant source of healing.
  DEFB %00000001          ; Graphic properties
  DEFB 2                  ; Graphic consists of 2 tiles
  DEFB 248                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB 253                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB 9                  ; Graphic consists of 9 bytes
  DEFB 1,255,124,56,16,56,124,255 ;
  DEFB 1                          ;
  DEFB 0                  ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB 252                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB 11                 ; Graphic consists of 11 bytes
  DEFB 128,192,255,62,28,8,28,62 ;
  DEFB 255,192,128               ;

; Unused
L46501:
  DEFB 255,62,0,50,42,208,33,81
  DEFB 177,126,230,15,50,41,208,35
  DEFB 34,45,208,1,254,127,237,120
  DEFB 246,224,79,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0

; Controls choice and game flag
;
; Control option (1-4) as set in the first game menu (L32825).
L48920:
  DEFB 0                  ; 1 = Kempston, 2 = AGF (Cursor), 3 = Sinclair, 4 =
                          ; Keyboard
; Game flag, as selected in the second game menu (L33051).
  DEFB 0                  ; 0 = New game, 1 = Load save game

; Initialize game
;
; Used by the routine at L62288.
;
; Launch of main game, once the player has entered 3 correct security codes
; from the code sheet.
L48922:
  LD HL,(23613)           ; Get ERRSP (stack pointer error return address)
  LD SP,HL                ;
  POP HL                  ; Replace with stack address L48947 in case there's
  LD HL,L48947            ; an error in loading a saved game
  PUSH HL                 ;
  DI                      ; Disable interrupts
  CALL L31744             ; Initialise menu options and draw the decorative
                          ; border round the play area
; The previous CALL returns the following values:
; * In the D register - Game flag (0 = New game, 1 = Existing game)
; * In the E register - Player controls choice - from L35754 - choices are from
;   the first menu screen (L35778)
  LD A,E                  ; Store player game control type selected from the
  LD (L48920),A           ; menu (L35778)
  LD A,D                  ; Retrieve and re-store store game flag (0 = New
  LD (48921),A            ; Game, 1 = Existing game)
  CP 0                    ; Skip over next routine (to L48992) if it's a new
  JR Z,L48992             ; game, or continue to the next routine to LOAD a
                          ; saved game

; Load saved game
;
; Sets IX (start of block to load) and DE (block length) for ROM LOAD routine.
;
; First data block - all game data between L60065 and 60577
L48947:
  LD IX,L59956_6          ; Start of data block
  LD HL,60577             ; Address for end of block
  LD DE,L59956_6          ; Start of block, game data at L60065
  SCF                     ; Set carry flag...
  CCF                     ; ...and then toggle so it's cleared
  SBC HL,DE               ; Calculate the number of bytes in the data block and
                          ; put result in DE register pair
  INC HL                  ; Need to add 1 to include the last byte
  EX DE,HL                ;
  LD A,255                ; Indicates a data block to load (rather than header)
  SCF                     ; Sets the carry flag, which tells the ROM routine to
                          ; perform a LOAD
  CALL 1366               ; Call the LD-BYTES ROM subroutine to load saved game
                          ; data
; Second data block - all game data between L26512 and 32819
  LD IX,(56053)           ; Start of data block
  LD HL,(60257)           ; Address for end of block
  LD DE,(56053)           ; Start of block, game data at L26512
  SCF                     ; Set carry flag
  CCF                     ; ...and then toggle it so it's cleared
  SBC HL,DE               ; Calculate the number of bytes in the data block and
                          ; put result in DE register pair
  INC HL                  ; Need to add 1 to include the last byte
  EX DE,HL                ;
  LD A,255                ; Indicates a data block to load (rather than header)
  SCF                     ; Sets the carry flag, which tells the ROM routine to
                          ; perform a LOAD
  CALL 1366               ; Call the LD-BYTES ROM subroutine to load saved game
                          ; data

; Start game
;
; Used by the routine at L48922.
L48992:
  LD HL,(23613)           ; Replace ERRSP stack pointer with the address L51043
  LD SP,HL                ; (start of pause game routine)
  POP HL                  ;
  LD HL,L51043            ;
  PUSH HL                 ;
; Identify the control method (1-4) that was selected on the first game menu
; (L35778).
;
; Sets the HL register pair to point to the address containing the input values
; to check for that control method.
  LD A,(L48920)           ; Game control choice (1-4)
  CP 1                    ;
  JR NZ,L48992_0          ;
  LD HL,60168             ; Kempston joystick selected
  JR L48992_3             ;
L48992_0:
  CP 2                    ; AGF/cursor joystick selected
  JR NZ,L48992_1          ;
  LD HL,60190             ;
  JR L48992_3             ;
L48992_1:
  CP 3                    ;
  JR NZ,L48992_2          ;
  LD HL,60211             ; Sinclair joystick selected
  JR L48992_3             ;
L48992_2:
  LD HL,60174             ; Keyboard selected
; Store the address holding the set of control input values.
L48992_3:
  LD (L60166),HL
; ...and check if we need to set up a new game or not:
  LD A,(48921)            ; Is it a new game, or has a saved game been loaded?
  CP 0                    ;
  JR Z,L49053             ; New game - jump to game setup
  LD A,(60087)            ; Game loaded. Copy room number into buffer.
  LD (60080),A            ;
  JP L55628               ; No need for intro/game setup for loaded data - jump
                          ; straight into game

; New game initialization - set up game data
;
; Used by the routine at L48992.
;
; This section initializes a bunch of new game data - copying bytes/addresses
; into the 'current game' state.
L49053:
  LD HL,L29042            ; Reset/store the address pointer to the start level
  LD (L60251),HL          ; text (Gatehouse Level)
  LD HL,L27772            ; Address pointer to warlock and creature stat tables
  LD (60355),HL           ;
  LD HL,L27868            ; Address pointer to missile data tables
  LD (L60353),HL          ;
  LD HL,L28156            ; Reset/store the pointer to the start of spell list
  LD (60261),HL           ; text (1st spell = MOVE)
  LD HL,L28604            ; Reset/store the pointer to the start of spell name
  LD (60263),HL           ; texts -1
  LD HL,28605             ; Reset/store the pointer to the start of spell text
  LD (60259),HL           ; messages ('Project thy soul' etc)
  LD A,27                 ; 27 = total number of spells (for spell list at
  LD (60265),A            ; L28156)
  LD HL,L38851            ; Reset/store the pointer to the start of an address
  LD (60266),HL           ; list pointing at graphics
; Code that was used to create the initial game menus and draw the decorative
; screen border gets overwritten for game data (the player doesn't return to
; the menu and the border doesn't get erased):
; * Original code used for menus/border
; * Start of new data sections used during the game
;
; The following instructions initialize a number of address pointers to the new
; data sets. Each section is terminated with an end-of-data byte (255).
;
; ROOM ITEM/OBJECT/SCENERY DATA SETS FOR THE CURRENT ROOM
  LD HL,(L56046)          ; Address pointer to room item/object/scenery data
                          ; sets at 31744
  LD DE,768               ; 768 bytes reserved for this
  ADD HL,DE               ;
  LD (HL),255             ;
; FOREGROUND SCENERY DATA SETS FOR CURRENT ROOM
  INC HL
  LD (60272),HL           ; Address pointer to foreground scenery data sets at
                          ; 32513
  LD DE,112               ; 112 bytes reserved for these
  ADD HL,DE               ;
  LD (HL),255             ;
; MAROC'S INVENTORY - UP TO 4 OBJECTS
  INC HL
  LD (L60346),HL          ; Maroc's inventory ('pockets') - 64 bytes (4 object
  LD B,4                  ; spaces x 16 bytes) at 32626
  LD DE,16                ;
L49053_0:
  LD (HL),0               ; Reset first byte of each inventory slots (0 =
  ADD HL,DE               ; nothing carried)
  DJNZ L49053_0           ;
  LD (HL),255             ;
; COLLISION/EVENT CHECKS FOR ELEMENTS IN THE CURRENT ROOM
  INC HL
  LD (60268),HL           ; Address pointer to elements/objects/events going on
                          ; in current room at 32691
  LD (HL),255             ; 255 = no more events/collisions to check
  LD DE,128               ; 128 bytes reserved for these
  ADD HL,DE               ;
; UNUSED DATA AREA
  LD (60255),HL           ; Skip over 32 bytes at 32819 (this data is unused)
  LD DE,32                ;
  ADD HL,DE               ;
; FLIPPED/MIRRORED GRAPHICS
  LD (60257),HL           ; Address pointer to flipped graphics store at 32851
; MAROC'S INVENTORY SLOTS
  LD HL,(L60346)          ; Address pointer to start of Maroc's inventory
                          ; (32626)
  LD (60348),HL           ; Copy to current inventory address pointer
  LD DE,16                ; Advance 16 bytes to start of next inventory item
  ADD HL,DE               ; address pointer
  LD (60350),HL           ; And store (32642) in current game data
; Prepare graphics for Maroc's sprite
  LD A,1
  LD (60240),A            ; Graphics & frame offset (1 = no graphic address
                          ; offset, start at frame #1) - sprite graphics
                          ; pointer starts at L38851
  CALL L57538             ; Set up graphics
  LD HL,(60241)           ; Store Maroc's calculated sprite graphic address
  LD (60098),HL           ; pointer
  LD A,124                ; 'Dummy' graphic address (44444) - used where
  CALL L57538             ; nothing needs to be drawn/printed
  LD HL,(60241)           ; Store calculated graphic address pointer
  LD (60147),HL           ;
  LD A,123                ; Set up graphics for Maroc's shadow (at 44424)
  CALL L57538             ;
  LD HL,(60241)           ; Get Maroc's shadow's calculated sprite graphic
                          ; address pointer
  LD (60100),HL           ; ...and copy to game data store
  LD A,105                ; Set up flickering barrier graphics (43500) used for
  CALL L57538             ; spells such as SHIELD, PROTECT and DEFENCE
  LD HL,(60241)           ; Get the address pointer to these graphics
  LD (60566),HL           ; ...and copy to the current game data store

; Run new game intro sequence
;
L49215:
  CALL L57081             ; Clear the scroll status panel at the bottom of the
                          ; screen
; Draw Maroc sprite graphic
  LD A,80                 ; Set vertical pixel position (from top of playing
                          ; area)
; Sprite drawing loop starts here (return from 49311) - continued until Maroc
; passes the bottom of the playing area
L49215_0:
  LD (60114),A
  LD A,120                ; Horizontal pixel position
  LD (60115),A            ;
  LD A,1                  ; Set graphics draw/erase flag to 1 (DRAW)
  LD (60111),A            ;
  LD HL,(60098)           ; Set graphics display address pointer to Maroc's
                          ; sprite (L38851)
  CALL L56216             ; Draw Maroc
; Print intro sequence/game start text on scroll (29471)
  LD A,36                 ; Intro sequence/game start message is message number
                          ; #36 (at 29471)
  CALL L58789             ; Identify the address location for this text message
                          ; number
  LD (L60065),HL          ; ...and store
  LD HL,20552             ; Set screen display address to top left of the
                          ; scroll's text area
  LD (60068),HL           ; ...and store
  CALL L58064             ; Call text printing routine
; Erase Maroc sprite graphic
  LD A,0                  ; Set graphics draw/erase flag to 1 (ERASE)
  LD (60111),A            ; ...and store
  LD HL,(60098)           ; Retrieve graphics address pointer
  CALL L56216             ; Erase graphic
; Lightning flashes are triggered every 16 pixels that Maroc's sprite moves
; down the screen.
  LD A,(60114)            ; Get vertical (Y) pixel co-ordinate
  AND 15                  ; Check the last 4 bits (0-15) to see if value = 0
  JR NZ,L49305            ; If not, jump out here and continue to move Maroc
                          ; downwards. If so, continue to next routine
                          ; (lightning flash effects)

; Intro sequence lightning - flashing & sound effects
L49274:
  LD A,6                  ; There are 6 lightning flashes between Maroc's
L49274_0:
  LD (60111),A            ; sprite movement segments
  CALL L58896             ; Toggle sky colour between blue and yellow colour
  LD A,128                ; Length/frequency of sound effect
  LD (60246),A            ; Store length/frequency counter
L49274_1:
  LD (60103),A            ; Also store as sound effect repeat counter
  CALL L57815             ; Play sound effect
  LD A,(60103)            ;
  DEC A                   ; Inner loop - decrement counter and repeat sound
  JR NZ,L49274_1          ; effect (128 iterations)
  LD A,(60111)            ; Outer loop - decrement counter and repeat lightning
  DEC A                   ; effect (6 flashes)
  JR NZ,L49274_0          ; Repeat 6 times

; Intro sequence - move Maroc's sprite down one pixel
;
; Used by the routine at L49215.
;
; Move Maroc's sprite down 1 pixel and check if he's got to the bottom of his
; descent.
;
; The check at 49309 checks if we're past pixel row 152, which is well into the
; scroll area in the bottom third of the screen.
;
; However, the Y co-ordinate is where Maroc's body is - his hat is above this,
; so this value continues the movement routine until the hat has completely
; disappeared.
L49305:
  LD A,(60114)            ; Get sprite Y co-ordinate
  INC A                   ; Increase by one
  CP 152                  ; Is the sprite past the bottom of the playing area
                          ; (character row 18)
  JR C,L49215_0           ; If not, go back and re-draw the sprite
  JR L49345               ; If so, finish the movement routine and start the
                          ; intro music

; Maroc out of energy - clear scroll, calculate & print rank
;
; Used by the routine at L55885.
;
L49315:
  LD A,(L60129)           ; Check if any spell was active before Maroc ran out
                          ; of energy
  CP 16                   ; Any value above 16 means there's some sort of spell
  JR C,L49315_0           ; in effect, and there's a flashing icon in the top
                          ; right of the scroll.
  CALL L59956_4           ; If a spell was active, clear the 4 FLASHing
                          ; attributes in the top right of the scroll
; Clear any active spell text in the 'mini-scroll' in the bottom right of the
; screen (pixels)
L49315_0:
  LD L,248                ; Low byte of screen display address
  LD A,8                  ; 8 character squares to clear
L49315_1:
  LD B,8                  ; 8 pixel lines to clear in each square
  LD H,80                 ; High byte of screen display address
L49315_2:
  LD (HL),0               ; Clear byte on screen
  INC H                   ; Move down one pixel
  DJNZ L49315_2           ; Repeat for 8 pixel lines
  INC L                   ; Move right one character square
  DEC A                   ;
  JR NZ,L49315_1          ; ..and repeat for 8 character squares
  CALL L58599             ; Calculate Maroc's rank and print it on screen

; Place/replace Maroc in the start room
;
; Used by the routine at L49305.
;
; This routine is launched:
; * after the short intro sequence that runs after starting a new game
; * when Maroc has run out of energy
;
; The routine plays the theme music, resets some of Maroc's game data and
; returns him to the start room.
;
; PLAY INTRO MUSIC
L49345:
  LD A,1                  ; Set flag indicating which music data to point to (1
                          ; = main theme music). The music data is stored at
                          ; L60400.
  CALL L58806             ; Play music
; RESET GAME DATA
  LD A,255
  LD (60340),A            ; Decrementing timer before a warlock might appear in
                          ; Maroc's room
  LD (60341),A            ; Decrementing timer before a creature might wander
  LD A,128                ; into the room from an adjacent one
  LD (60128),A            ; Maroc's energy - maximum is 255 but he starts with
  LD A,0                  ; half a full energy bar
  LD (60572),A            ; FREEZE spell timer (0 = FREEZE spell not active)
  LD (60577),A            ; Maroc's height offset (his movement speed affects
                          ; his height above his shadow)
  LD (L60129),A           ; Spell selection byte - start in spell menu, with no
                          ; spell selected
  LD (60140),A            ; Temp store for spell number pointer. Only the MOVE
                          ; spell is available at the start of the game
  LD (60373),A            ; Energy drain/heal amount for ongoing effect spells,
                          ; e.g. SHIELD (drain) or CHALICE (heal)
  LD (60137),A            ; Currently active 'effect' spell (e.g. UNSEEN,
                          ; SHIELD)
  LD (60130),A            ; Store for spell counter used in checking spells
                          ; collected at L59033_2
  LD A,74                 ; Maroc's vertical (Y-axis) screen position, in
  LD (60097),A            ; pixels, from top of play area just below border
  LD A,71                 ; Maroc's default colour attributes (71 = INK 7,
  LD (L60071),A           ; PAPER 0, BRIGHT 1)
  LD A,64                 ; Maroc's vertical pixel starting position in the
  LD (L60276),A           ; room
  LD A,1                  ;
  LD (60084),A            ; The connecting door set number in the table at
                          ; L26512 (set 1)
  LD (60087),A            ; Room number = 1
  LD HL,(60261)           ; Memory address pointer for spell list data at
                          ; L28156
  LD (60131),HL           ; Copy to spell name pointer buffer

; Reset various room-based game data ready for a new room
;
; Used by the routine at L55818.
;
; The jump here from 55882 occurs when Maroc moves room - either that or this
; routine follows the previous one, when Maroc has either started a new game or
; run out of energy, and ends up in the start room.
L49415:
  LD HL,0
  LD (60150),HL           ; Reset vertical room position (pixel) to zero
  LD (60152),HL           ; Reset horizontal room position
  LD A,0                  ; (4-pixel/half-character steps) to zero
  LD (60146),A            ; Flag indicating if a warlock/demon has appeared in
                          ; the room
  LD (60337),A            ; Servant object-carrying-status byte (0 = no object
                          ; carried)
  LD (60080),A            ; Reset room number (buffer byte) - indicates all
                          ; items in previous room now dealt with
  LD (L60305),A           ; Reset number of creature-launched missiles in the
                          ; current room
  LD (60307),A            ; Reset missile number (in table at L27868)
  LD (60306),A            ; Number of missiles fired by Maroc = 0
  LD (60568),A            ; Number of Maroc's active missiles (buffer byte) = 0
  LD (L60333),A           ; Warlock's 'aggression' byte (byte 6 of warlock's
                          ; data at L27772) = 0 (as there's no warlock)
  LD (60164),A            ; Maroc's horizontal movement speed (0 = not moving)
  LD (60165),A            ; Maroc's vertical movement speed (0 = not moving)
  LD (L60074),A           ; Game cycle/creature pursue counter = 0
  LD (60075),A            ; Maroc's sprite's horizontal facing direction, set
                          ; when Maroc enters a new room
  LD (60076),A            ; Maroc's sprite's vertical facing direction, set
                          ; when Maroc enters a new room
  LD HL,(60268)           ; Pointer to room item event data sets at 32691
  LD (HL),255             ; Set end-of-data byte at start of this data as no
  LD (60077),HL           ; room event/collision checks have been identified
                          ; yet
  LD HL,(60255)           ; Pointer to data set before flipped graphic data at
                          ; 32819
  LD (L60143),HL          ; Copy into game data store (this data is unused)
  LD (HL),255             ; Set end-of-data byte at start of this data set
  LD HL,(60257)           ; Address pointer to end of this data set (32819)
  LD (60253),HL           ; Copy into game data store
  LD A,1                  ; Graphics frame offset (n-1) for frames/mirrored
  LD (60240),A            ; graphics ( = 0 = no frame offset)
  LD HL,(L56046)          ; Pointer to start of room item data sets at 31744.
  LD (60094),HL           ; Copy into game data store

; Room initialization - identify room data set and scenery style, reset
; room/viewport position
;
; Find the current's room data set in the table at L25001:
L49498:
  LD HL,(56055)           ; Pointer to series of room data sets at L25001.
  LD A,(60087)            ; Get room number
  LD C,A                  ; Store in C register
  LD B,1                  ; Set incremental compare counter to compare room
                          ; number against
; Identify data set for current room from list at L25001
L49498_0:
  LD A,C
  CP B
  JR Z,L49498_2           ; If room data byte (A) = counter (B), we're at the
                          ; right place, so skip out of the loop
; Not this set. Move to the end of the set (set length will vary)
L49498_1:
  LD A,(HL)               ; Get byte of room data set
  INC HL                  ; Increment it
  CP 255                  ; Are we at an end-of-data-set marker?
  JR NZ,L49498_1          ; Continue till we are
  INC B                   ; We're at the end of this set. Increment the counter
  JR L49498_0             ; Keep comparing until we're at the right place for
                          ; the room
; Data set for current room identified
L49498_2:
  LD (60282),HL           ; Store address pointer for current room data bank.
; Check if the room is a vertical tunnel
  CP 224                  ; Tunnel rooms are room number 224 and above
  JP NC,L50613            ; If we're in one of these, skip out of this routine
                          ; as tunnel data is different from room data
; Identify offset for room scenery graphics.
; * Scenery graphics are different for 'brick' (e.g. Gatehouse level - offset =
;   0) or 'cavern' (e.g. Mines of Madness - offset = 12) style levels - see
;   L49765 and L49912 for graphic examples
; * In the address table at L38851, advancing 12 addresses (=24 bytes) forward
;   from a 'brick' level scenery graphic gives you the 'cavern' level
; * For example, 38885 and 38909 are the graphic addresses for the vertical
;   wall section.
  CP 83                   ; Rooms 1-82 are 'brick' style levels (e.g. Gatehouse
                          ; Level). Is the room number less than 83?
  LD A,0                  ; ...If so, graphic address pointer offset is zero
  JR C,L49498_3
  LD A,12                 ; If room number is 83 or above (e.g. Mines of
                          ; Madness), graphic address offset is 12
L49498_3:
  LD (60279),A            ; Store level type graphic address offset
; The next set of instructions reset the room position:
  LD HL,0
  LD (60236),HL           ; Set horizontal (60236) & vertical (60237) movement
                          ; speed to zero
  LD (60231),HL           ; Set horizontal room position to zero
  LD (60233),HL           ; Set vertical room position to zero
  LD A,64                 ;
  LD (60235),A            ; This byte is set to 64 for 'standard' rooms,
  LD A,32                 ; 254/255 for tunnels (byte 9 of data set at 31744)
  LD (L60227),A           ; Room item type = room (general). This is the first
                          ; data set stored in the room data sets at 31744 and
                          ; indicates the base room position/attributes
  LD A,2                  ; Item properties byte. Because this is just the
  LD (60238),A            ; general room/viewport position & data, can just set
                          ; bit 1 (2) = hidden (nothing to draw)
  CALL L57520             ; Copy the 16 bytes of room data from working buffer
                          ; at L60227 to the first of the room item data sets
                          ; at 31744
  LD A,5                  ; Resets the item properties ready for the next room
  LD (60238),A            ; item. Default setting sets bits 0 (visible
                          ; on-screen) and 2 (needs to be erased before
                          ; re-drawing)
  LD A,80                 ; Starting value for the room's vertical position
  LD (60281),A            ; (viewport), in pixels, from top of room area (room
                          ; alignment)
  LD A,4                  ; Starting value for the room's horizontal position
  LD (60280),A            ; (viewport), in half-character (4 pixel) steps from
                          ; left of room area
; Prepare address pointers for the start of the room's data set:
  LD HL,(60282)           ; Get address pointer for the room data set in the
                          ; table at L25001
  LD A,(HL)               ; Get (first) room data set byte - this indicates the
                          ; room size, in sections Trivia - Setting the
                          ; scene(ry)
  INC HL                  ; Increment address pointer to the second byte in the
                          ; table (containing scenery data)
  LD (60282),HL           ; ...and re-store the pointer.
  LD (60284),A            ; Store the first byte, which indicates room size
  LD A,1                  ;
  LD (60285),A            ; Incremental counter byte starting at 1, to compare
                          ; with the first data byte of the current room when
                          ; positioning room scenery. Used shortly in the
                          ; routine at L49632.

; Set up LEFT vertical wall/floor connector graphics
;
; Prepare the room corner join graphics - one of two sorts, for either 'brick'
; or 'cavern' levels
;
; The right wall/floor connector is set up later at L49912
L49600:
  LD A,6                  ; Graphic type = 6 (corner wall section)
  LD (L60227),A           ;
  LD A,48                 ; Vertical position (in pixels) from top of room
  LD (60234),A            ; space
  LD A,16                 ; Horizontal position (in 4-pixel/half-character
  LD (60232),A            ; steps) from left of room space
  LD A,2                  ;
  LD (60240),A            ; Graphic number offset for scenery graphic address
                          ; (n-1)*2 = 2 The standard corner section is the
                          ; right-hand one (40462). For the left one (as in the
                          ; above images) we want the mirrored version, the
                          ; graphics pointer to which is the next address (2
                          ; bytes) location
  LD C,18                 ; Graphic number offset for corner wall section in
                          ; graphic address table at L38851; (n-1)*2 = 34 =
                          ; 38885
  LD A,(60279)            ; Extra offset (+12 addresses) in table if the player
                          ; is on a 'cavern' level
  ADD A,C                 ; Addresses offset will now be 18 or 30, e.g. for
                          ; wall section at 38885 or 38909.
  CALL L57538             ; Prep graphic address pointers at pointer table at
                          ; L38851, including mirrored graphics of the sections
  CALL L57520             ; Copy the data for these graphics from its buffer at
                          ; L60227 into a room item data set at 31744

; Set up room background scenery - part 1
;
; Used by the routine at L49858.
;
; Identify and set up (mirroring if required, and storing address pointers) for
; each room element. Includes fixed scenery items such as wall/floor connectors
; and door frames.
;
; See Trivia: Setting the scene(ry) for information about how the room scenery
; is stored.
L49632:
  LD A,(60285)            ; Room setup counter (to be compared with room size
                          ; data byte at L49858)
  DEC A                   ; The counter was pre-incremented in the earlier
  AND 3                   ; routine, so check its original value
  CP 0                    ;
  JR NZ,L49632_0          ; Door and brickwork data that make up the room are
                          ; stored in pairs of bits, so 4 to a byte. After
                          ; evaluating 4 pairs, the data byte is dealt with, so
                          ; can be advanced to the next byte in the room data
                          ; set (at L25001). So skip the next instructions
                          ; (that advance the pointer to the next room data
                          ; byte) if original counter byte (before INC) is
                          ; 1,2,3 - 5,6,7 - 9,10,11 etc. (not a multiple of 4)
; Get room data byte from L25001 and advance room data address pointer, as
; we've dealt with the current byte
  LD HL,(60282)           ; Get room data address pointer
  LD A,(HL)               ; Get next room data byte
  INC HL                  ; Increment address pointer to next byte
  LD (60282),HL           ; ...and re-store address pointer
  LD (60286),A            ; Store room data byte
; The next series of routines handle the graphics set-up for the door frames
; and doors in the room.
;
; The following routine determines whether the items (doors and frames) being
; dealt with are on the back, right or left wall, and sets the A register
; (shortly to be stored at 60287) to 0, 1 or 2 respectively.
;
; The incremental counter (60285) is checked against the first room data byte,
; which indicates the room size .
; * If the counter's value is 1 or 2, we're dealing with frames and doors on
;   the left wall.
; * If its value is one of its final two checks (room size - counter <= 2) it's
;   on the right wall.
; * Anywhere in between these two options, we're dealing with the back wall.
L49632_0:
  LD A,(60285)            ; Incremental counter, which is checked against with
                          ; 1st byte from the room data set (in the table at
                          ; L25001) which indicates the room size
  CP 3
  JR NC,L49632_1
  LD A,2                  ; If the counter byte is < 3, we're looking at LEFT
  JR L49679               ; wall items - set A to 2, for storing at 60287
                          ; shortly
L49632_1:
  LD C,A                  ; If the counter byte is >=3 it could be the back or
                          ; right wall
  LD A,(60284)            ; ...Subtract it from the room data byte
  SUB C                   ;
  CP 2                    ;
  JR NC,L49632_2          ;
  LD A,1                  ; If it's 0 or 1, the counter byte is on one of its
  JR L49679               ; last two values, so we're looking at the RIGHT wall
                          ; - Set A to 1, for storing at 60287 shortly
L49632_2:
  LD A,0                  ; If it's 2 or more, the counter byte is in between,
                          ; so we're looking at the BACK wall - set A to 0, for
                          ; storing at 60287 shortly

; Set up room background scenery - part 2
;
; Used by the routine at L49632.
;
; A Byte calculated in the previous routine at L49632_0, either 0, 1 or 2,
;   indicating whether to deal with objects on the back, right or left wall
;   respectively
; C The incremental counter byte stored at 60285 and used to count room
;   elements
;
; Follows the previous routine. When Maroc enters a room this routine
; calculates doors and brickwork patterns based on the room's data set at
; L25001.
;
; See Trivia: Setting the scene(ry) for an explanation of how this routine
; evaluates the DOORS and BRICKWORK from the room data set.
L49679:
  LD (60287),A            ; Store the above byte (in the A register calculated
                          ; in the previous routine at L49632_0)
  LD A,(60286)            ; Get the current room data byte (from the current
                          ; room data banks at L25001)
  RLA                     ; Shift bits (6 & 7) left x 2
  RL C                    ; ...Shifting them into bits 0 & 1 of the C register
  RLA                     ;
  RL C                    ;
  LD (60286),A            ; First two bits moved - now re-store the data byte
                          ; for further shifts of the next ones later
  LD A,C                  ; We're only interested in bits 0 and 1 of the C
                          ; register
  AND 3                   ; So filter any others out
  LD C,A                  ;
  AND 1                   ; Check bit 0. If set, this indicates that there's a
                          ; DOOR here.
  JR Z,L49765             ; ...If it's NOT set, skip over the next routine to
                          ; check for BRICKWORK patterns
; DOOR identified from room data set. Check where in the room it is:
  LD A,(60281)            ; Item's vertical position within current room, in
                          ; pixels, from top of room area.
  LD (60234),A            ; ...Copy byte into store
  LD A,(60280)            ; Horizontal position within current room, in
                          ; half-character (4 pixel) steps.
  LD (60232),A            ; ...Copy byte into store
  LD A,(60287)            ; 0 = back wall, 1 = right wall, 2 = left wall
  LD (60230),A            ; ...Copy byte into store
  LD A,2                  ; Graphic type = 2 (Door)
  LD (L60227),A           ;
  CALL L57520             ; Copy the 16 bytes in the item's working data buffer
                          ; at L60227 into a room item data set at 31744.
; DOOR FRAMES - set up/mirror graphics
;
; Each door has a door frame, which is a separate graphic to be handled
  LD A,1                  ; Graphics type = 1 (fixed room scenery item, in this
  LD (L60227),A           ; case a door frame)
; The byte calculated earlier (0, 1 or 2) indicates whether the item is on the
; back wall, right wall or left wall, so the following instructions use this
; information to work out the graphics address offset (in C register).
  LD C,20                 ; Redundant instruction as C value (offset) is set
                          ; either at 49742 (20) or L49679_0 (21)
  LD A,(60287)            ; 0 = Back wall door, 1 = Right wall door or 2 = Left
  CP 0                    ; wall door
  JR NZ,L49679_0          ;
  LD C,20                 ; Back wall - Graphics offset = (20-1)*2 + 38851 =
                          ; 38889 (Door frame - back wall)
  LD A,1                  ; Frame offset (= no offset needed)
  JR L49679_1             ;
L49679_0:
  LD C,21                 ; Side wall - Graphics offset = (21-1)*2 + 38851 =
                          ; 38891 (Door frame - side wall)
; Set up and mirror graphics for door frame
L49679_1:
  LD (60240),A            ; Store calculated frame offset
  LD A,(60279)            ; Get level style offset (for to graphic pointers at
                          ; L38851). This is 12 if room number >=84 (cavern
                          ; levels), otherwise 0 (brick levels).
  ADD A,C                 ; Add the offset (20 or 21) to graphics offset
                          ; addresses depending on whether the door frame is on
                          ; the back or side wall
  CALL L57538             ; Call setup graphics routine (copy graphics address
                          ; pointers), mirror any relevant graphic data
  CALL L57520             ; Copy the 16 bytes of calculated graphics data from
                          ; the working buffer at L60227 into one of the the
                          ; room item data sets at 31744.
  JR L49858

; Check for and set up back wall brickwork/rock scenery
;
; Used by the routine at L49679.
;
; C Contains either 0, indicating a 'blank' section of wall, or 2, indicating
;   some brickwork. Bit 0 has already been checked and is zero, indicating
;   there isn't a door in this room position.
;
; Checks for any brickwork scenery that needs to be set up. See Trivia: Setting
; the scene(ry) for an explanation of how DOORS and BRICKWORK are evaluated
; from the room data set.
;
; Decoration for the back wall - scenery graphics that appears on the walls of
; 'brick' levels (L40680) or 'cavern' levels (L41013)
;
; First, check if bit 1 is set - if so, there's brickwork at this position:
L49765:
  LD A,C
  AND 2                   ; Check bit 1. If it's set, there's BRICKWORK to set
                          ; up at this room position.
  JR Z,L49808             ; If it's NOT set, skip over the next routine.
; Brickwork identified. Set up graphics pointers & data for one of 8 back wall
; brickwork ('brick' levels) or rock ('cavern level') patterns
  LD A,1                  ; Graphics type = 1 (fixed scenery item)
  LD (L60227),A           ;
  LD A,(60280)            ; Horizontal room position of item (in
  LD (60232),A            ; half-character/4-pixel increments). Copy into data
                          ; buffer ready to be transferred into a room item
                          ; data set (at 31744)
  RRA                     ; Use this byte by shifting into the lowest 3 bits...
  RRA                     ;
  RRA                     ;
  AND 3                   ; ...To provide one of 4 values (0-3), used to pick
                          ; one of the four brickwork/decoration types
  INC A                   ; Incremented so number set correctly at 1-4
  LD (60240),A            ; Store as graphics pointer offset
  LD A,L                  ; Use bits 0-4 of the low byte (L) of the HL register
  AND 31                  ; pair to set variable heights for the decoration. At
  LD (60234),A            ; the start of this routine, HL is typically at the
                          ; start of one of the data bank sets at 31744,
                          ; meaning the height (in relation to the top of the
                          ; room, in pixels) will be either 0 or 16 pixels.
                          ; However, this routine can be reached with HL
                          ; pointing somewhere in the room data at L25001, so
                          ; the height of the brickwork can be be quite varied.
  LD C,23                 ; Offset for brickwork graphics at L38851, pointing
                          ; to 38895
  LD A,(60279)            ; Add graphic offset if Maroc is on a 'cavern' level,
  ADD A,C                 ; to use the second set of rock graphics (38919)
                          ; instead of the the bricks
  CALL L57538             ; Call setup graphics routine (copy graphics address
                          ; pointers and mirror any relevant graphic data)
  CALL L57520             ; Copy the 16 bytes of graphic data for the brickwork
                          ; scenery from the data buffer at L60227 to one of
                          ; the room data sets at 31744.

; Set up room floor-wall connector graphics
;
; Used by the routine at L49765.
L49808:
  LD A,1                  ; Graphics type = 1 (fixed scenery item)
  LD (L60227),A           ;
  LD A,17                 ; Graphic number - address pointer offset for graphic
  LD (60240),A            ; address table at L38851 - unnecessary because it'll
                          ; be overwritten in a few more instructions at
                          ; L49808_1
  LD A,(60280)            ; Room graphic item's horizontal position within
  LD (60232),A            ; current room, in half-character (4 pixel) steps.
                          ; Copy into data buffer.
  LD A,(60281)            ; Room graphic item's vertical position within
  LD (60234),A            ; current room, in pixels. Copy into data buffer.
; Sets up (including mirroring if needed) wall/floor connector graphics,
; depending on which wall is being dealt with (left, right or back)
;
; Uses the byte at 60287 to identify the graphics address offset (C register)
; and frame (A register) for the wall/floor connector graphic address:
; * Back wall (byte value = 0)
; * Right wall (byte value = 1)
; * Left wall (byte value = 2)
  LD A,(60287)
  CP 0                    ; Back wall - offset for graphics address 38879, back
  JR Z,L49808_0           ; wall floor section (see L40392)
  LD C,16                 ; Right/left wall - offset for:
  JR L49808_1             ; * address pointer = 38881, right wall side/wall
L49808_0:
  LD C,15                 ;   floor section (see 40423), or
  LD A,1                  ; * address pointer = 38883, left wall (mirrored)
L49808_1:
  LD (60240),A            ;   side wall/floor section (see 32851)
; Calculate graphics offset based on level offset and the above
  LD A,(60279)            ; Level type offset to scenery graphics (either 0 or
                          ; 12 depending on whether it's a 'brick' or 'cavern'
                          ; style level)
  ADD A,C                 ; Add to calculated value to indicate the correct
                          ; graphic number based on level type and wall
                          ; alignment
  CALL L57538             ; Set up graphics (copy graphics address pointers and
                          ; mirror any graphic data)
  CALL L57520             ; Copy the item data from the working buffer L60227
                          ; into a 16 byte room item data set at 31744.

; Calculate horizontal/vertical room co-ordinates for each room
; section/components
;
; Used by the routine at L49679.
;
; The byte at 60285 acts as an incrementing counter which is compared with room
; size (first byte in the room data sets at L25001). This works out which bit
; of the room is being dealt with (left, back or right).
;
; The routine then identifies the vertical and horizontal positions for each
; consecutive scenery components.
L49858:
  LD A,(60285)            ; Get counter byte, starting at 1
  INC A                   ; Increment and then re-store
  LD (60285),A            ;
  LD C,A
  LD A,(60284)            ; First room data byte from room data set at L25001 -
                          ; indicates room size
  SUB C                   ; Subtract (check against) the counter
  JR C,L49912             ; If counter is greater than the room data byte, the
                          ; side and back wall joints have been calculated.
                          ; Skip to L49912 to deal with the corner/vertical
                          ; wall connectors
  CP 2                    ; Check which section we're dealing with
  JR NC,L49858_0          ;
; Room-size-minus-counter = 1 or 0. This means we're dealing with the RIGHT
; side of the room.
  LD A,(60281)            ; Increase vertical (Y) position by 16 pixels
  ADD A,16                ; Each side wall part is 16 pixels tall (e.g. the
                          ; right side wall section, so add 16 pixels from the
                          ; current position
  LD (60281),A            ; Store adjusted vertical graphic position
  JR L49858_1             ;
; Room size is 2 or more than the counter, so we're dealing with the scenery
; either on the left wall or the back wall scenery.
L49858_0:
  LD A,(60285)            ; Get the counter byte
  CP 4                    ; >=4?
  JR NC,L49858_1          ; If so, we're dealing with the BACK WALL section -
                          ; no need to adjust the vertical co-ordinate as it's
                          ; all along the same level
; Neither of the above checks were met, so we're dealing with the LEFT side of
; the room.
  LD A,(60281)            ; Vertical (Y) position
  SUB 16                  ; Each side wall part is 16 pixels tall (e.g. the
                          ; left side wall section, so subtract 16 pixels from
                          ; the current position as they're drawn sequentially
                          ; from left to right
  LD (60281),A            ; ...and re-store
; Wall/floor sections (e.g. the connectors at L40392) are 4 characters (32
; pixels) wide.
;
; Calculate the horizontal (X) position - this is easy as every room section is
; 32 pixels wide.
L49858_1:
  LD A,(60280)
  ADD A,8                 ; Increase horizontal position by 8 half-character
  LD (60280),A            ; squares (32 pixels)
  JP L49632               ; Return to the next item to set up

; Set up RIGHT vertical wall/floor connector graphics
;
; Used by the routine at L49858.
;
; The left wall/floor connector has been set up already at L49600
L49912:
  LD A,7                  ; Graphic type = 7 (RIGHT corner wall section)
  LD (L60227),A           ;
  LD A,48                 ; Graphic vertical position within current room, in
  LD (60234),A            ; pixels, from top of room playing area (fixed value
                          ; for all rooms).
  LD A,5                  ; Item properties byte. Default = 5 - bit 0 set means
  LD (60238),A            ; item is visible, bit 2 set means item will need
                          ; erasing (e.g. before re-drawing again)
; Calculate horizontal position of graphic within room - this will depend on
; the size of the room.
;
; The room's first data byte (from the set at L25001) indicates the room size,
; and is used to calculate the horizontal position of the right corner section.
  LD A,(60284)            ; Get the 1st data byte for the room (at L25001)
  DEC A                   ; The value is in half-character (4 pixel) steps; to
  DEC A                   ; calculate this, decrement the value twice
  RLA                     ; ...and multiply by 8
  RLA                     ;
  RLA                     ;
  AND 248                 ; Filter off any carry bits (it will be a multiple of
                          ; 8 so we don't need bits 0-2)
  LD (60232),A            ; ...and store.
  LD A,1                  ; Graphics frame offset (= no offset)
  LD (60240),A            ;
  LD C,18                 ; Graphic number in graphics address pointer table at
                          ; L38851, this offset points to graphic address 38885
  LD A,(60279)            ; Level type graphics pointer offset (for 0 for
                          ; 'brick' levels, 12 for 'cavern levels')
  ADD A,C                 ; Add to graphic address pointer offset
  CALL L57538             ; Set up graphics
  CALL L57520             ; Copy the 16 bytes of calculated data from L60227 to
                          ; a bank in the room item data sets at 31744
  LD HL,(60094)           ; Retrieve address pointer after the above 16 bytes
                          ; have been copied
  LD (HL),255             ; Set the first byte of the next data bank to 255
                          ; (end-of-data)
  LD HL,(L56046)          ; Retrieve address pointer to the room item data sets
                          ; at 31744

; Check room item data sets to see if any doors need setting up
;
; Used by the routine at L49993.
;
; HL Address pointer to room data sets containing the room's scenery items
;    (31744)
;
; Check through data sets at 31744 to see if any doors (item type number = 2)
; need setting up
;
; Get one of the 16-byte room item data sets (at 31744) and copy it across to a
; working data buffer at L60227:
L49965:
  LD DE,L60227            ; Working buffer address pointer
  LD B,16                 ; 16 bytes to copy over
  LD (60094),HL           ; Store address pointer to item data set (at 31744)
L49965_0:
  LD A,(HL)               ; Copy byte across
  LD (DE),A               ;
  INC DE                  ;
  INC HL                  ;
  DJNZ L49965_0           ; Repeat for 16 bytes
; Check if the data set is door data
  LD A,(L60227)           ; First byte of the data bank indicates the type of
  CP 255                  ; graphic
  JP Z,L50218             ; If it's 255 it means no more data to deal with
  CP 2                    ; Is this data for a door (item type = 2)?
  JR Z,L49993             ;
  JR L49965               ; If not, check the next set

; New room - door setup
;
; Used by the routine at L49965.
;
; Follows previous routine if a door is found in one of the room item data
; sets.
;
; This routine:
; * Identifies each of the doors in the new room
; * Determines which one Maroc entered from, and set his entry co-ordinates and
;   direction accordingly
; * Calculates and stores each door's orientation, position, graphic address,
;   and number of animation frames
L49993:
  LD HL,(60282)           ; Pointer to the current data byte for the room (from
                          ; the room data set at L25001)
  LD A,(HL)               ; Get byte from room data
  INC HL                  ; Increment pointer
  LD (60282),HL           ; ...and re-store
  LD C,A                  ; Temp store of connecting door set number (L26512)
                          ; in C register
  LD A,(60230)            ; Flag indicating where this door appears in the
                          ; room: 0 = Back wall door 1 = Right wall door 2 =
                          ; Left wall door
  LD (60287),A            ; Copy this byte to working data buffer
  LD A,C                  ; Retrieve connecting door set number
  LD (60230),A            ; ...and store (replace) in room element data buffer
  LD A,(60084)            ; Current/existing connecting door set
  CP C                    ; Compare with the set for this door - is this the
                          ; door that Maroc has entered from?
  JR NZ,L49993_2          ; If not, jump over the next two sets of instructions
                          ; (which set Maroc's room position based on this
                          ; door)
; Maroc entered the room through this door, so set his new room position
; accordingly.
  LD A,(60232)            ; Horizontal position of door within current room, in
                          ; half character (4 pixel) steps.
  LD (60277),A            ; Copy to Maroc's horizontal room entry position
                          ; store
  LD A,(60234)            ; Vertical position within current room, in pixels,
                          ; from top of room playing area
  SUB 12                  ; Slight height adjustment for the new room height
                          ; entry point, so that Maroc enters through the lower
                          ; part of right/left doors, or near the top of the
                          ; room for vertical room entry
  LD (60278),A            ; Copy to Maroc's vertical room entry position store
; Next, set his vertical/horizontal facing direction
;
; The next conditional checks use the door's wall location byte at 60287 is
; used for this check:
; * 0 = Back wall door - set 60076 (vertical direction) to 254 (down)
; * 1 = Right wall door - set 60075 (horizontal direction) to 2 (left)
; * 2 = Left wall door -  set 60075 (horizontal direction) to 254 (right)
  LD A,(60287)
  CP 0
  JR Z,L49993_1
  CP 1
  JR Z,L49993_0
  LD A,254
  LD (60075),A            ; Maroc is entering the room through a door on the
  JR L49993_2             ; left wall
L49993_0:
  LD A,2                  ;
  LD (60075),A            ; Maroc is entering the room through a door on the
  JR L49993_2             ; right wall
L49993_1:
  LD A,254                ;
  LD (60076),A            ; Maroc is entering the room through a door on the
                          ; back wall
; Calculate the address pointer to this door's connecting door set (at L26512),
; using the set number x 4 (as each set contains 4 bytes)
L49993_2:
  LD HL,(56053)           ; Address pointer to the start of the connecting door
                          ; sets - L26512
  LD A,C                  ; Retrieve the connecting door data set number
  LD D,0                  ; The offset will be calculated in the DE register
                          ; pair, so set the high byte (D) to zero
  RLA                     ; x2
  RL D                    ;
  RLA                     ; x4
  RL D                    ; If this causes a carry, rotate it into the D
                          ; register
  AND 252                 ; Offset will be a multiple of 4, so filter out bits
  LD E,A                  ; 0 & 1 as not needed
  ADD HL,DE               ; Add the offset, so HL now points to the connecting
                          ; door set for this door in the tables at L26512
  LD (60228),HL           ; Store this address pointer in the door data buffer
  INC HL                  ; Move along to byte 3 of 4 in the set (door
  INC HL                  ; properties)
  LD A,(HL)               ;
  OR 5                    ; Set bits 0 (item visible on-screen) and 2 (item
                          ; will need erasing before re-drawing)
  AND 253                 ; Filter out bit 1 (2) - (assume door is not hidden)
  LD (60238),A            ; ...and re-store
; The byte at 60287 is now used to determine which door graphic need to be set
; up/mirrored when Maroc enters a room.
; * This depends on which wall the door is in (back/left/right) and whether
;   it's open or closed
; * There are 6 possible door graphics. These correspond to the 6 graphic
;   addresses pointers stored from 38867
; * Door 3 is only used for opening/closing animations, though its mirrored
;   version (Door 4) is the open version of the door on the back wall.
;
; For each door identified, the following routine sets the following registers:
;
; +----------+-------------------------------------------------------------------------------------------------------------------------------------------------+
; | Register | Contents                                                                                                                                        |
; +----------+-------------------------------------------------------------------------------------------------------------------------------------------------+
; | H        | Door number/type (1-6)                                                                                                                          |
; | B        | Horizontal position offset in 4-pixel/half-character steps                                                                                      |
; | L        | Vertical position offset in pixels                                                                                                              |
; | D        | Positive/negative offset for door graphic frame (used in routine at L51892) Indicates number of frames (bits 0-2) and opening/closing direction |
; | E        | Number of animation frames needed to open/close for the door (used in routine at L51892)                                                        |
; +----------+-------------------------------------------------------------------------------------------------------------------------------------------------+
  LD C,A                  ; Store filtered byte in C register
  LD D,17                 ; Default frame offset value
  LD E,5                  ; Default value - total number of animation frames
                          ; needed for door opening/closing. Back wall doors
                          ; have 4 animation frames, side wall doors 5.
  LD L,0                  ; Height position offset of door (in pixels)
  LD A,(60287)            ; 0 = Back wall door 1 = Right wall door 2 = Left
                          ; wall door
  CP 1
  JR Z,L49993_3
  CP 0
  JR Z,L49993_4
; Door on LEFT wall - set graphic address offset and door position offset
  LD B,2                  ; Horizontal position offset (in
                          ; half-characters/4-pixel increments)
  LD L,246                ; Height pixel position offset of door (-10)
  LD H,5                  ; Door 5 - closed door on left wall. Mirrored version
  LD D,245                ; of Door 2.
  LD A,C                  ; Check bit 3 (open/closed)
  AND 8                   ;
  JR Z,L49993_5           ;
  LD D,17                 ;
  LD H,1                  ; Door 1 - open door on left wall.
  JR L49993_5             ;
; Door on RIGHT wall - set graphic address offset and door position offset
L49993_3:
  LD B,254                ; Horizontal position offset (in
                          ; half-characters/4-pixel increments)
  LD L,246                ; Height pixel position offset of door (-10)
  LD H,2                  ; Door 2 - closed door on right wall.
  LD A,C                  ; Check bit 3 (open/closed)
  AND 8                   ;
  JR Z,L49993_5           ;
  LD D,245                ;
  LD H,6                  ; Door 6 - open door on right wall. Mirrored version
  JR L49993_5             ; of Door 1.
; Door on BACK wall - set graphic address offset and door position offset
L49993_4:
  LD B,253                ; Horizontal position offset (in
                          ; half-characters/4-pixel increments)
  LD E,4                  ; Number of animation frames needed for door
                          ; opening/closing. Back wall doors have 4, side wall
                          ; doors 5.
  LD H,4                  ; Door 4 - open door on back wall. Mirrored version
  LD D,244                ; of Door 3.
  LD A,C                  ; Check bit 3 (open/closed)
  AND 8                   ;
  JR NZ,L49993_5          ;
  LD D,17                 ;
  LD H,1                  ; Door 1 - closed door on back wall.
; Store door graphic address and position offsets
L49993_5:
  LD A,(60232)            ; Horizontal (X) position of door in room
                          ; (half-character/4 pixel increments)
  ADD A,B                 ; Add calculated horizontal offset
  LD (60232),A            ; ...and store
  LD A,(60234)            ; Vertical (Y) position of door in room (in pixels)
  ADD A,L                 ; Add calculated vertical offset
  LD (60234),A            ; ...and store
  LD A,D                  ; Door frame byte for particular door - indicates
  LD (60288),A            ; graphic offset and open/close direction, i.e. which
                          ; way to advance through the graphic pointers
  LD A,E                  ; Number of animation frames needed for door. Back
  LD (60289),A            ; wall doors have 4, side wall doors 5.
  LD A,H                  ; Offset for the calculated door graphic frame number
  LD (60240),A            ; (1-6)
  LD A,9                  ; Offset for base door graphics address (L38851)
                          ; [offset = (17-1)*2]. Door graphic addresses start
                          ; from 38867.
  CALL L57538             ; Prep/mirror door graphics
; Update pre-graphic byte with the number of (animation) frames for this door
; (4 for back wall doors, 5 for side doors)
  LD A,(60239)            ; Get pre-graphics data byte
  AND 240                 ; Filter out bits 0-3 (the default number of frames
  LD C,A                  ; in the byte)
  LD A,(60289)            ; Add the number of animation frames needed for the
  OR C                    ; door
  LD (60239),A            ; Re-store amended pre-graphics byte
  LD A,(60288)            ; Copy graphic frame address offset into working data
  LD (60240),A            ; buffer
  CALL L57520             ; Copy the 16 bytes of door data from L60227 into a
                          ; room item data set at 31744.
  JP L49965               ; Keep checking if there are any more doors to set up
                          ; in this room

; Identify room's interactable objects
;
; Used by the routine at L49965.
;
; Run after setting up room's doors. Checks the room object table at L29551 and
; copies any objects to the data sets at 31744.
L50218:
  LD A,7                  ; Maximum of 7 interactable objects displayed in a
                          ; room. More can be in the room, but they won't
                          ; appear until Maroc takes an object, leaves and
                          ; subsequently returns to, the room.
  LD (60343),A            ; Store as a counter check
  LD HL,(56051)           ; Pointer to room item data tables at L29551
  LD A,0                  ; Reset (data set) counter for room object table
  LD (60292),A            ;
; Set up data for objects in room
L50218_0:
  LD A,(60087)            ; Get room number
  LD B,A                  ; Used in B register in next CALL
  LD C,0                  ; C register used as room counter in next CALL
  CALL L56908             ; Check objects table for what's in the current room
  LD A,(60292)            ;
  CP 255                  ; If all objects are dealt with - skip next few
  JR Z,L50272             ; instructions
; Found an object to deal with in this room
  LD (60282),HL           ; Store the room object table address pointer
  CALL L57015             ; Set up interactable object graphics and copy data
                          ; into a room item data set at 31744
  LD HL,(60228)           ; Retrieve address pointer to start of interactable
                          ; object's data set (at L29551)
  LD (HL),0               ; Set the item's room number to 0, as Maroc is now in
                          ; the same room as the item
  LD A,(60343)            ; Get maximum object counter (max 7)...
  DEC A                   ; ...Decrement...
  LD (60343),A            ; ...And re-store.
  JR Z,L50272             ; If we've reached the maximum number of objects in
                          ; this room, jump to next routine
  LD HL,(60282)           ; Otherwise, retrieve the room object table address
                          ; pointer
  JR L50218_0             ; ...and continue checking for objects.

; Set up the room's creatures
;
; Used by the routine at L50218.
;
; Run after previous routine setting up interactable objects for the room has
; finished.
;
; Identifies creatures (by creature type) in the current room using the table
; at L27532. Number and types of creature in each room is stored in a single
; byte. Sets up creature data and copies it into the room data sets at 31744.
L50272:
  LD A,0                  ; Set number of creatures in current room to 0
  LD (60342),A            ;
  LD HL,(56048)           ; Address pointer for room creature data table at
                          ; L27532
  LD A,(60087)            ; Get room number
  DEC A                   ; Offset starts from 0 not 1, so reduce by 1
  LD E,A                  ; Create offset for data sets
  LD D,0                  ;
  ADD HL,DE               ; Add to base address at L27532 so that pointer is at
                          ; current room's creatures
; Check for any GUARDIANS OF CHAOS in the current room
  LD A,(HL)               ; Get the creature byte for this room
  LD (60343),A            ; ...and store
  AND %11000000           ; Top two bits (6 & 7) contain the count of any
                          ; guardians of chaos in the room
  JR Z,L50272_1           ; If there aren't any, skip to the next check
; Set up GUARDIANS OF CHAOS in the current room
  RLA                     ; Shift top two bits into bits 0 & 1 to get the
  RLA                     ; guardian of chaos room count (1-3)
  RLA                     ;
  AND 3                   ;
L50272_0:
  LD (60145),A            ; Store the current room's creature count for this
                          ; creature
  LD A,8                  ; Creature type = 8 (guardian of chaos)
  CALL L57706             ; Set up this creature's data (room position &
                          ; graphics)
  CALL L57520             ; Copy the creature's data into one of the room item
                          ; data sets at 31744
  LD A,(60145)            ; Retrieve the count of these creatures for the
                          ; current room
  DEC A                   ; ...and reduce by 1
  JR NZ,L50272_0          ; If count of this creature in the room is still > 0,
                          ; repeat for others
; Check for any GOBLIN WARRIORS in the current room
L50272_1:
  LD A,(60343)            ; Retrieve the room data byte containing the creature
                          ; information
  AND %00110000           ; Bits 4 & 5 contain the count of any goblin warriors
                          ; in this room
  JR Z,L50272_3           ; If there aren't any, skip to the next check
; Set up GOBLIN WARRIORS in the current room
  RRA                     ; Shift bits into bits 0 & 1 to get the goblin
  RRA                     ; warrior count (1-3)
  RRA                     ;
  RRA                     ;
  AND 3                   ;
L50272_2:
  LD (60145),A            ; Store the current room's creature count for this
                          ; creature
  LD A,9                  ; Creature type = 9 (goblin warrior)
  CALL L57706             ; Set up this creature's data (room position &
                          ; graphics)
  CALL L57520             ; Copy the creature's data into one of the room item
                          ; data sets at 31744
  LD A,(60145)            ; Retrieve the count of these creatures for the
                          ; current room
  DEC A                   ; ...and reduce by 1
  JR NZ,L50272_2          ; If count of this creature in the room is still > 0,
                          ; repeat for others
; Check for any GOBLIN MISSILE THROWERS in the current room
L50272_3:
  LD A,(60343)            ; Retrieve the room data byte containing the creature
                          ; information
  AND %00001100           ; Bits 2 & 3 contain the count of any goblin missile
                          ; throwers in this room
  JR Z,L50272_5           ; If there aren't any, skip to the next check
; Set up GOBLIN MISSILE THROWERS in the current room
  RRA                     ; Shift bits into bits 0 & 1 to get the goblin
  RRA                     ; missile throwers count (1-3)
  AND 3                   ;
L50272_4:
  LD (60145),A            ; Store the current room's creature count for this
                          ; creature
  LD A,10                 ; Creature type = 10 (goblin missile thrower)
  CALL L57706             ; Set up this creature's data (room position &
                          ; graphics)
  CALL L57520             ; Copy the creature's data into one of the room item
                          ; data sets at 31744
  LD A,(60145)            ; Retrieve the count of these creatures for the
                          ; current room
  DEC A                   ; ...and reduce by 1
  JR NZ,L50272_4          ; If count of this creature in the room is still > 0,
                          ; repeat for others
; Check for any WRAITHS in the current room
L50272_5:
  LD A,(60343)            ; Retrieve the room data byte containing the creature
                          ; information
  AND %00000011           ; Bits 0 & 1 contain the count of any wraiths in this
                          ; room, so filter out the other bits
  JR Z,L50272_7           ; If there aren't any, skip these setup instructions
; Set up WRAITHS in the current room
L50272_6:
  LD (60145),A            ; Store the current room's creature count for this
                          ; creature
  LD A,11                 ; Creature type = 11 (wraith)
  CALL L57706             ; Set up this creature's data (room position &
                          ; graphics)
  CALL L57520             ; Copy the creature's data into one of the room item
                          ; data sets at 31744
  LD A,(60145)            ; Retrieve the count of these creatures for the
                          ; current room
  DEC A                   ; ...and reduce by 1
  JR NZ,L50272_6          ; If count of this creature in the room is still > 0,
                          ; repeat for others
; When Maroc moves room, two 'creature appearance' timers are topped up
; slightly to avoid an immediate appearance in the new room:
; * 60340 = Timer affecting how long before a warlock is likely to materialize
;   in the current room
; * 60341 = Timer affecting how long before a creature is likely to wander in
;   from an adjacent room
;
; In both cases, the carry check (JR C) ensures that the timer's bits don't
; wrap around to zero
L50272_7:
  LD A,(60340)
  ADD A,64                ; Add 64 to the warlock appearance timer
  JR C,L50272_8           ;
  LD (60340),A            ;
L50272_8:
  LD A,(60341)            ;
  ADD A,128               ; Add 128 to the wandering creature timer
  JR C,L50272_9           ;
  LD (60341),A            ;
; Finish the creature data set:
L50272_9:
  LD HL,(60094)           ; Address pointer to room item (creature) data set at
                          ; 31744
  LD (HL),255             ; Mark the start of the next set with an end-of-data
                          ; byte
  LD (60274),HL           ; ...and store the address pointer to the next set,
  LD A,0                  ; ready for more data
  LD (60343),A            ; Reset the number-of-creatures-in-room counter to
                          ; zero

; Set up room foreground scenery objects - part 1
;
; There are 16 foreground scenery objects, whose graphics addresses are held
; from 39063.
; * 'Brick' levels have an assortment of the first 8 (from 39063)
; * 'Cavern' levels have an assortment of the second 8 (from 39079)
;
; This routine calculates the number, types, and X/Y co-ordinates of scenery
; objects in the room, and stashes the data for each one into a 7-byte data set
; in a table at 32513.
;
; The following instructions identifies the level type. If it's a cavern-style
; level, sets the offset for the graphic address pointer to 8.
L50433:
  LD A,(60087)            ; Get room number
  LD L,A                  ; Store in L register
  CP 82                   ; If room number is 1-81 it's a 'brick style level'.
                          ; For other scenery types it's actually rooms 1-82
                          ; (49528). This means the first room in the High
                          ; Temple of Chaos (room 82) is a hybrid room, with
                          ; brickwork walls but cavern foreground scenery.
  LD A,0                  ; ...So set graphics offset 60279 to 0...
  JR C,L50433_0           ;
  LD A,8                  ; ...Otherwise it's a 'cavern' style level, so set
                          ; the offset to 8.
L50433_0:
  LD (60279),A            ; Store the offset
; Bytes in the ROM, picked using the room number, are used to generate a varied
; but repeatable selection of foreground object types.
  LD H,0                  ; Multiply room number by 8
  ADD HL,HL               ;
  ADD HL,HL               ;
  ADD HL,HL               ;
  EX DE,HL                ; ...Store result in DE register to be used for the
                          ; ROM address
  LD HL,(60272)           ; Get address pointer to the foreground object data
                          ; table at 32513
; CALCULATE NUMBER OF FOREGROUND SCENERY OBJECTS
;
; The first of the room data bytes at L25001 reflects the size of the room.
;
; The number of foreground objects in a room is this room size byte divided by
; two (rounded down).
  LD A,(60284)            ; Get (first) room data byte from banks at L25001,
                          ; which indicates the size of the room
  LD C,A                  ; Temp store in C register
  RRA                     ; Divide by 2
  AND 127                 ; Filter out any carry bits caused by the RRA
  LD B,A                  ; ...and store in B register as a counter for
                          ; number-of-objects
; SET LEFTMOST OBJECT POSITION
;
; The next bit calculates the first (leftmost) item's horizontal position (in
; 4-pixel/half-character steps) within the room, based on room size.
  LD A,C                  ; Retrieve (first) room data byte from C register
  RLA                     ; x 2
  NEG                     ; Make the value negative as the first object will be
                          ; to the left of (or near) the leftmost screen wall
  ADD A,8                 ; Add 8 to the value as a small offset, to move it
  LD (60232),A            ; over to the right slightly
; IDENTIFY SCENERY OBJECT TYPE AND GRAPHIC ADDRESS POINTER
;
; DE is currently pointing at a ROM address based on room number (x 8, so room
; 1 = memory address location 00008).
;
; A combination of the room number and bytes from addresses in ROM are used to
; create a repeatable, but varied pattern of foreground scenery objects for
; each room.
L50433_1:
  LD A,(DE)               ; Get byte from ROM
  INC DE                  ; ...and move pointer along to next ROM address
  ADD A,B                 ; Add byte from B register (which contains the first
                          ; room data byte divided by 2) to added variation
  AND 7                   ; There are only 8 types of foreground object for
                          ; each level type, so we only need bits 0-2 (values
                          ; 0-7)
  ADD A,106               ; Add to the graphic address pointer table at L38851.
  LD C,A                  ; An offset of 106 puts the address pointer at the
                          ; scenery objects at 39063.
  LD A,(60279)            ; Add the offset calculated earlier (either 0 or 8
  ADD A,C                 ; depending on the level type). Offset should now be
                          ; between 106 and 121
  LD (60094),HL           ; Store address pointer to the foreground object data
                          ; set at 32513
  LD (60282),DE           ; Store ROM address pointer
  LD D,0                  ; Double the offset value to create an address
  RLA                     ; pointer offset in DE
  RL D                    ; Filter out bit 0 to ensure it's an even number
  AND 254                 ;
  LD E,A                  ;
  LD HL,(60266)           ; Get the base graphics address pointer
  ADD HL,DE               ; Add the offset
  LD E,(HL)               ; Get the scenery graphics address in the DE
  INC HL                  ; register, e.g. 43611 for the skeleton
  LD D,(HL)               ;
; COPY FOREGROUND SCENERY DATA VARIABLES INTO DATA SETS
;
; Foreground scenery object data is stored in the data tables at 32513.
  LD HL,(60094)           ; Retrieve address pointer to foreground object data
                          ; sets at 32513
  LD (HL),0               ; First byte default value = 0 (item not on screen)
  INC HL                  ;
  LD (HL),0               ; Horizontal position precision/fraction byte = 0
  INC HL                  ; (item starting position will be a multiple of 8
                          ; pixels)
  LD A,(60232)            ; Horizontal position in room. This is in
  LD (HL),A               ; 1-character/8-pixel steps (foreground scenery moves
  INC HL                  ; in larger distance increments than other scenery)
  ADD A,16                ; Add 16 to the horizontal position and re-store. The
  LD (60232),A            ; value of 16 puts a gap of 16 character squares
                          ; between foreground objects.
  LD (HL),0               ; Vertical position precision/fraction byte (not
  INC HL                  ; needed here)
  LD (HL),104             ; Vertical position from top of playing area, in
  INC HL                  ; pixels - default position = 104
  LD (HL),E               ; Address pointer to the scenery graphic to draw,
  INC HL                  ; e.g. 43611
  LD (HL),D               ;
  INC HL                  ;
  LD DE,(60282)           ; Retrieve ROM address pointer
  DJNZ L50433_1           ; Continue to store object details in the 7 byte
                          ; scenery data banks at 32513. B register = count of
                          ; objects that need storing.
  LD (HL),255             ; Set end-of-data byte to indicate the end of room
                          ; foreground scenery object sets

; Adjust room element co-ordinates based on Maroc's room entry point
;
; Room scenery elements' co-ordinates need to be tweaked with an offset amount
; based on Maroc's room entry point.
;
; This routine adjusts each element's horizontal and vertical positions of each
; of the room item data sets at 31744 and the foreground scenery object sets at
; 32513.
;
; Calculate offset based on Maroc's default room position and his room entry
; point
L50545:
  LD A,(60277)            ; Maroc's horizontal (entry) position when he moves
  LD C,A                  ; to a new room, in half-character/4-pixel steps
  LD A,(60096)            ; Maroc's default horizontal (X-axis) room position
                          ; (in half-characters = 29)
  SUB C                   ; Offset amount = Maroc's default horizontal room
                          ; position (~ 14.5 character spaces) minus his
                          ; horizontal entry position
  LD B,A                  ; ...store in B register
  LD A,(60278)            ; Maroc's vertical (entry) position when he moves to
  LD C,A                  ; a new room, in pixels
  LD A,(L60276)           ; Maroc's default vertical (Y-axis) room position (in
                          ; pixels)
  SUB C                   ; Offset amount = Maroc's default vertical room
  LD C,A                  ; position (~ 48 pixels) minus his vertical entry
                          ; position
  LD D,0                  ; Clear D register ready for DE offset addition
                          ; shortly
  LD HL,(L56046)          ; Address pointer to room item data sets at 31744
; Add co-ordinate offsets into bytes 6 (horizontal co-ordinate) and 8 (vertical
; co-ordinate) of each of the room item data sets at 31744
L50545_0:
  LD A,(HL)
  CP 255                  ; Skip next bit if no more data sets
  JR Z,L50545_1           ;
  LD E,5                  ; DE contains offset to move along 5 bytes to 6th
  ADD HL,DE               ; byte of set
  LD A,(HL)               ; Get item's horizontal room position
                          ; (4-pixel/half-character steps)
  ADD A,B                 ; Add (or subtract if negative) the horizontal offset
  LD (HL),A               ; ...and re-store
  INC HL                  ; Move along two bytes
  INC HL                  ;
  LD A,(HL)               ; Get item's vertical room position (in pixels)
  ADD A,C                 ; Add (or subtract if negative) the vertical offset
  LD (HL),A               ; ...and re-store
  LD E,9                  ; Move along 9 bytes - this puts the pointer at the
  ADD HL,DE               ; start of the next bank of data
  JR L50545_0             ; Repeat until all data sets adjusted
; Next do the same for the foreground scenery items, which are stored
; separately at 32513
L50545_1:
  LD HL,(60272)           ; Get address pointer to foreground scenery data sets
                          ; at 32513
; Update data item loop:
L50545_2:
  LD A,(HL)
  CP 255                  ; Check first byte for end-of-data byte
  JP Z,L50747             ; Skip out of routine if found - all sets dealt with
; Update co-ordinates at bytes 3 (horizontal) and 5 (vertical) of data set
  INC HL                  ; Move to byte 3 - horizontal co-ordinate
  INC HL                  ;
  LD A,(HL)               ;
  ADD A,B                 ; Add (or subtract if negative) horizontal
                          ; co-ordinate offset
  LD (HL),A               ; ...and re-store
  INC HL                  ; Move to  byte 5 - vertical co-ordinate
  INC HL                  ;
  LD A,(HL)               ;
  ADD A,C                 ; Add (or subtract if negative) vertical co-ordinate
                          ; offset
  LD (HL),A               ; ...and re-store
  INC HL                  ; Move along three bytes to the next data set
  INC HL                  ;
  INC HL                  ;
  JR L50545_2             ; ...and repeat until all sets have been adjusted.
; The routine that follows this one is at L50747 (jump at end of data sets from
; 50595)

; Tunnel room - identify the connecting door set
;
; Used by the routine at L49498.
;
; HL Address pointing to the current tunnel data bank at L26384
;
; Uses the tunnel room data at L26384 and the connecting door sets at L26512 to
; work out which room the tunnel that Maroc has just entered leads to.
L50613:
  LD A,0
  LD (60573),A            ; Set number of creatures in the room to zero
; Get length of tunnel
  LD A,(HL)               ; First byte of data = tunnel length
  ADD A,A                 ; Double it...
  LD (60285),A            ; ...and store
; The second and third bytes of the set hold the two paired door set numbers
; (in the table at L26512) that connects each end of this tunnel. One of them
; will be the room Maroc has left, and the other the room he's headed to.
;
; The next instructions identify which direction way Maroc is going - i.e.
; whether to pick out the second or third byte of the set.
  INC HL                  ; Get 2nd byte (connecting door set #1)
  LD B,(HL)               ;
  LD A,(60084)            ; Compare with the current door set number that Maroc
  CP B                    ; has just left
  JR NZ,L50613_0          ;
; If the second byte is the same as the current one, we need to grab the third
; byte, rather than the second, so advance the pointer along
  INC HL
; HL register pair is now pointing at the correct connecting room door set
; number (at L26512)
L50613_0:
  LD A,(HL)               ; Get the connecting room set number...
  LD (60084),A            ; ...and store as the connecting door set number
                          ; (destination)
; The next instructions use the door set number to set the address pointer to
; the right connecting door set, by multiplying it by 4 (as each set contains 4
; bytes of data).
  LD HL,(56053)           ; Address pointer to connecting door sets (L26512)
  LD D,0                  ; The offset will be in the DE register paid, so set
                          ; the high byte (D register) to zero
  RLA                     ; Set number x 2
  RL D                    ;
  RLA                     ; Set number x 4 (as data sets are 4 bytes long)
  RL D                    ; ...also rotating any carry bits into (D) - the high
                          ; byte
  AND 252                 ; Addresses are a multiple of 4 so we don't need bits
                          ; 0-1 (values 0-3)
  LD E,A                  ; DE register pair now contains the offset
  ADD HL,DE               ; ...and add it to address pointer
  LD (60085),HL           ; ...and store the address pointer-plus-offset
; Update the 'entry point' door data in the room connecting data set at L26512:
  INC HL                  ; Move address pointer along 2 bytes to byte 3 of the
  INC HL                  ; set
  LD A,(60149)            ; This is the door properties byte indicating the
                          ; door that Maroc entered the room from (normally
                          ; will have bit 7 set)
  LD (HL),A               ; Store this as the third byte in the room connecting
                          ; door data set (at L26512).
  INC HL                  ; Move to the 4th byte of the relevant door set (in
                          ; the table at L26512)
  LD (HL),0               ; Set this byte to 0. This is the 'event check'
                          ; value. Setting it to 0 effectively means that the
                          ; door is subsequently only interactable by Maroc
                          ; bumping into it, or another creature entering the
                          ; room. It's not completely clear why this needs
                          ; changing. It may possibly be a remnant from some
                          ; earlier code which dealt with the doors in a
                          ; different way.

; Set up tunnel
;
; Set up vertical tunnel sections. Like with 'standard' rooms, the first entry
; in the room data sets at 31744 is the generic position/viewport/co-ordinates
; for the tunnel as a whole, before dealing with the individual on-screen
; items.
L50663:
  LD A,15
  LD (L60227),A           ; Graphic type = 15 - this is the value for the
  LD A,0                  ; generic tunnel screen position/viewport
  LD (60231),A            ; Set horizontal room position to 0
                          ; (overflow/fraction byte)
  LD (60233),A            ; Set vertical room position to 0 (overflow/fraction
                          ; byte)
  LD (60236),A            ; Set horizontal movement speed to 0
  LD (60237),A            ; Set vertical movement speed to 0
  LD A,255                ;
  LD (60235),A            ; Byte indicating general tunnel element
  LD A,28                 ; Horizontal position, in half-character/4-pixel
  LD (60232),A            ; steps Tunnel starting position is at the top of the
                          ; screen, in the middle (14 character spaces).
  LD A,0                  ; Vertical position, in pixels, from the top of the
  LD (60234),A            ; playing area.
  LD A,1                  ; Animation frame number offset (= no offset)
  LD (60240),A            ;
  LD A,124                ; Offset for graphics address table at L38851,
                          ; starting at 'dummy' graphic (39097/44444) as
                          ; nothing actually needs drawing
  CALL L57538             ; Set up 'dummy' graphic - used for tunnel 'entity'
  LD A,%00000101          ; Set bits 0 (1) = item visible and 2 (4) = item will
                          ; need erasing (item default setting)
  LD (60238),A            ; Store as item properties byte

; Start of tunnel data setup
;
; Generate the initial tunnel position/movement:
L50712:
  LD A,(60087)            ; Get room number
  SUB 224                 ; Tunnels are from room number 224 onwards, so
                          ; subtract this to get tunnel number (0-31)
; This section uses the tunnel number byte (1-32, stored in the A register) to
; generate an offset address somewhere in the ROM - base address + ( [1-31] *
; 32 ).
  LD HL,4660              ; Base ROM address
  LD DE,32                ;
  LD B,A                  ;
L50712_0:
  ADD HL,DE               ; Base ROM address + (tunnel number [0-31] x 32)
  DJNZ L50712_0           ;
; However, the generated result in HL is immediately overwritten in the call at
; 50734, making the previous calculation unnecessary.
;
; Store generated tunnel data:
  LD (60228),DE           ; Store the 32 from earlier - see notes above.
  LD (60230),A            ; Store tunnel number (room number minus 224)
  CALL L57520             ; Copy 16 bytes of game data from the data buffer at
                          ; L60227 to the room item data sets at 31744.
  LD (HL),255             ; Set end-of-data byte at start of next 16 bytes data
                          ; bank at 31744
  LD (60274),HL           ; Store the data set address pointer for the next
  LD A,1                  ; bank.
  LD (60286),A            ; Temporary counter that holds the number of tunnel
                          ; boundary walls visible on screen

; Calculate and set current room attribute colours
;
; Used by the routine at L50545.
;
; This routine uses bits in the room number byte at 60087 to determine the room
; colours. Some colour combinations are avoided, but screens come in a variety
; of black, blue and red backgrounds.
;
; The same algorithm to calculate screen colours apply to both 'standard' and
; tunnel rooms.
L50747:
  CALL L57947             ; Clear the playing area (pixels)
  LD A,(60087)            ; Get room number
  LD C,A                  ; Temp store in C register
  AND 24                  ; Filter bits 3 and 4 of room number - these will
                          ; determine the PAPER colour of the room
  CP 16                   ; Is bit 4 set (and bit 3 unset)?
  JR Z,L50747_0           ; If so, room will have a red (PAPER 2) background
  CP 8                    ; Is bit 3 set (and bit 4 unset)?
  JR Z,L50747_2           ; If so, room will have a blue (PAPER 1) background
; Room will have a black (PAPER 0) background
  LD A,C                  ; Retrieve room number from C register
  AND 7                   ; Filter bottom 3 bits
  CP 2                    ;
  JR NC,L50747_4          ; If >= 2, colour is fine as red or brighter on black
                          ; is OK, so jump to set it (INK 2-7)
  ADD A,3                 ; INK 0 (black) and 1 (blue) are too dark for a black
  JR L50747_4             ; background so add 3 to make it a brighter colour
                          ; (magenta/green)
; Room will have a red (PAPER 2) background
L50747_0:
  LD B,A                  ; Store (PAPER) colour in B register
  LD A,C                  ; Retrieve room number from C register
  AND 3                   ; Filter bits 0 and 1 (values 0-3)
  JR Z,L50747_1           ; Black (INK 0) is OK on red
  ADD A,5                 ; Blue (INK 1), red (INK 2) or magenta (INK 3) don't
                          ; look great on red, so add 5 to brighten to yellow
                          ; (INK 6), white (INK 7) or black (INK 0)
                          ; respectively.
  AND 7                   ; Filter ink colour (0-7)
L50747_1:
  OR B                    ; Combine with paper colour
  JR L50747_4             ;
; Room will have a blue (PAPER 1) background
L50747_2:
  LD B,A                  ; Store (PAPER) colour in B register
  LD A,C                  ; Retrieve room number from C register
  AND 7                   ; Filter bits 0-2 (values 0-7)
  CP 3                    ;
  JR NC,L50747_3          ; If >= 3, colour is fine as magenta or brighter on
                          ; blue is OK (INK 3 - 7)
  ADD A,6                 ; For black (INK 0), blue (INK 1) and red (INK 2),
                          ; add 6 to brighten to yellow (INK 6), white (INK 7)
                          ; or black (INK 0). This allows black (INK 0) on blue
                          ; (PAPER 1), but the reverse (INK 1, PAPER 0) is
                          ; avoided at 50764.
; Set calculated room colours:
L50747_3:
  OR B                    ; Combine INK colour with PAPER colour
L50747_4:
  OR 64                   ; Set BRIGHT bit
  LD (60073),A            ; Store room colours
  CALL L57863             ; Set screen colour for room

; Identify and set up level name for printing on scroll
;
; Whenever Maroc enters a new room (or moves from a tunnel to a new room), the
; room number is cross referenced against the current level/area using the
; lookup table at L50852.
;
; The paired byte (1-9) indicates which level (L29042) Maroc is on. Once
; identified, the level name is printed on the scroll.
L50807:
  LD A,(60087)            ; Get room number
  CP 213                  ; There are 212 'standard' rooms in the game
  JR NC,L50870            ; If the room number is higher, we assume Maroc's in
                          ; a vertical scrolling tunnel section, so skip the
                          ; next bit as no scroll message is needed.
  LD B,9                  ; 9 pairs of bytes to check at L50852
  LD HL,L50852            ;
  LD C,A                  ; Temporary store for room number in C register
L50807_0:
  LD A,(HL)               ; Get first byte of data banks
  CP C                    ;
  JR C,L50807_1           ; If current room number > the first byte of the
                          ; pair, level identified
  INC HL                  ; Otherwise move to next pair of bytes
  INC HL                  ;
  DJNZ L50807_0           ;
; Level identified from room number
L50807_1:
  DEC HL                  ; Move pointer back 1 byte to the second byte of
  LD A,(HL)               ; previous pair
  LD (60105),A            ; ...And store.
  LD HL,(L60251)          ; Get address pointer to current game level text at
                          ; L29042
  CALL L58789             ; Identify the address of the level text to print
  LD (60138),HL           ; ...and store.
  LD A,0                  ; Set the character counter to the start of the text
                          ; (character position 0)
  LD (60361),A            ; ...and store.
  CALL L58764             ; Clear the spell message text area on the scroll
  JR L50870               ; Jump to initialize, set up and draw room items

; Lookup table - room numbers and their corresponding level names & warlocks
;
; Used to identify the level name from the room number in routine at L50807
;
; 9 pairs of bytes:
; * Byte 1 = the room number 'buckets'
; * Byte 2 = the level text number (L29042). Also the warlock number (L27772)
;   appearing on this level, except for levels 8 & 9
L50852:
  DEFB 212,9              ; Rooms 209-212: Text 9 (High Temple of Chaos)
  DEFB 209,7              ; Rooms 182-209: Text 7 (Catacombs of the Undead)
  DEFB 181,6              ; Rooms 158-181: Text 6 (The Labyrinth)
  DEFB 157,5              ; Rooms 134-157: Text 5 (Goblin Warren)
  DEFB 133,3              ; Rooms 104-133: Text 3 (Mines of Madness)
  DEFB 103,2              ; Rooms 83-103: Text 2 (Caverns of Doom)
  DEFB 82,8               ; Rooms 55-82: Text 8 (Chambers of Chaos)
  DEFB 54,4               ; Rooms 31-54: Text 4 (Great Halls of the Deep)
  DEFB 30,1               ; Rooms 1-30: Text 1 (Gatehouse Level)

; Start of game cycle - control checks
;
; Used by the routines at L50807 and L55628.
;
; Check and log game control inputs
L50870:
  LD A,(48921)            ; Game flag - 0 = New/current game, 1 = Loaded game
  CP 0                    ; If not a new/current game...
  JP NZ,L51043            ; ...Launch the pause game (with music) routine
  LD A,(60087)            ; Get room number
  CP 224                  ; If <= 224, skip next two instructions
  JR C,L50870_0           ;
  LD A,1                  ; If room number >= 224, it's a tunnel room - set
  LD (60076),A            ; Maroc's vertical facing direction to 1 (up)
; Read keyboard/joystick input
;
; Kempston controls dealt with separately at L50870_4.
L50870_0:
  LD HL,(L60166)          ; Address of the control values to check, e.g.
                          ; keyboard, cursor, Kempston
  LD DE,60206             ; Store for which keys/buttons are being pressed
  LD A,(L48920)           ; Control option 1 = Kempston, 2 = AGF (Cursor), 3 =
                          ; Sinclair, 4 = Keyboard
  CP 1                    ; Check if Kempston joystick selected
  JR Z,L50870_4           ;
; Read keyboard input (includes Cursor, Sinclair joysticks)
;
; Reads port for chosen control option (values at from L60166) for up, down,
; left, right and fire.
;
; Stores values in control buffer at 60206. 0 = Not pressed, 1 = Pressed
L50870_1:
  LD C,(HL)               ; Get port value of control method to check - store
  INC HL                  ; in BC register pair
  LD B,(HL)               ;
  INC HL                  ;
  IN A,(C)                ; Check if relevant control key pressed
  OR (HL)                 ; (up/down/left/right/fire)
  CP 255                  ;
  JR Z,L50870_2           ;
  LD A,1                  ; Key pressed - store 1 for this input
  JR L50870_3             ;
L50870_2:
  LD A,0                  ; Key not pressed - store 0 for this input
L50870_3:
  LD (DE),A               ;
  INC DE                  ; Move on to next control key/button
  INC HL                  ;
  LD A,0                  ; Check if we've reached the end of the controls (0 =
  CP (HL)                 ; end-of-data byte)
  JR NZ,L50870_1          ; If not, continue to read control directions until
  JR L50870_6             ; all 5 have been checked
; Read Kempston joystick input
L50870_4:
  LD BC,31                ; Kempston joystick port
  IN A,(C)                ; Read control port
  LD B,A                  ;
  LD A,(HL)               ; Check if direction/button being pressed
  AND B                   ;
  LD A,0                  ; Store 0 (default) if button/control not being
  JR Z,L50870_5           ; pressed
  LD A,1                  ; Store 1 if button/control being pressed
L50870_5:
  LD (DE),A               ;
  INC DE                  ; Move on to next control/button
  INC HL                  ;
  LD A,(HL)               ;
  CP 0                    ; Check if we've reached the end of the controls (0 =
                          ; end-of-data byte)
  JR NZ,L50870_4          ; If not, continue to read control directions until
                          ; all 5 have been checked
; Evaluate control direction values
;
; Horizontal movement control:
L50870_6:
  LD A,(60209)            ; Check movement control - right
  LD C,A                  ; Store in C register (1 = right pressed, 0 = right
                          ; not pressed)
  LD A,(60208)            ; Check movement control - left
  SUB C                   ; Calculate left minus right (0 = both/neither
                          ; pressed, 1 = right pressed, -1 (255) = left
                          ; pressed)
  LD C,A                  ; Store left/right calculated value in C
  LD A,(60075)            ; Maroc's facing direction - 0, 254 (facing right),
                          ; or 2 (facing left), depending on which door he's
                          ; entered a room from. When Maroc enters a new room,
                          ; he's set to 'moving' so he doesn't just sit in the
                          ; doorway
  ADD A,C                 ; Add to control value
  LD (L60157),A           ; ...And store...
; Vertical movement control:
  LD A,(60207)            ; Check movement control - down
  LD C,A                  ; Store in C register (1 = down pressed, 0 = down not
                          ; pressed)
  LD A,(60206)            ; Check movement control - up
  SUB C                   ; Calculate up minus down (0 = both/neither pressed,
                          ; 1 = up pressed, -1 (255) = down pressed)
  LD C,A                  ; Store up/down calculated value in C register
  LD A,(60076)            ; Maroc's facing direction (1 = facing up, 255 =
                          ; facing down)
  ADD A,C                 ; Add to control value
  LD (60158),A            ; ...And store...
; The FIRE button flag is stored at 60210. Unlike other control directions, the
; byte at 60102 is used to ensure that the control button is released after
; pressing, to prevent action auto-cancel if the fire control is held for too
; long.
;
; This ensures that the player has to let go of the fire control button/key,
; before pressing it again to activate something.
  LD A,(60210)            ; Check FIRE control
  CP 0                    ;
  LD A,(60102)            ; Get the 'fire release' flag ready to check
  JR Z,L50870_10          ; If fire hasn't been pressed, skip the next routine
; FIRE pressed
  CP 0                    ; Has the fire key been released from being pressed
  JR Z,L50870_7           ; earlier?
  LD A,0                  ; Set FIRE control to zero
  LD (60210),A            ;
  JR L51032               ;
; Fire control has been pressed so set the fire control release byte at 60102
; to 1.
L50870_7:
  LD A,1
  LD (60102),A
; Play high pitched beep
  LD A,16                 ; 16 = speaker bit (bit 4)
  LD C,32                 ; Outer loop counter - affects duration/sound effect
L50870_8:
  OUT (254),A             ; Play speaker
  XOR 16                  ; Toggle speaker bit
  LD B,48                 ; Inner loop counter - affects pitch of beep sound
L50870_9:
  DJNZ L50870_9           ; Decrement inner loop counter until zero for short
                          ; pause
  DEC C                   ; Outer loop pause
  JR NZ,L50870_8          ;
  JR L51032               ;
; Fire not pressed
L50870_10:
  LD A,0                  ; Set the 'fire control release' control flag to 0,
  LD (60102),A            ; as no fire controls are being pressed

; Pause game routine - check if 'pause' key pressed
;
; Used by the routine at L50870.
;
; Follows the previous routine keyboard control checks for
; up/down/left/right/fire.
L51032:
  LD BC,57342             ; Keyboard port for Y, U, I, O, P keys
  IN A,(C)                ; Get input from keyboard
  OR %11111110            ; 'P' key to check is the lowest bit (bit 0), so set
                          ; all the other bits (1-7) to 1
  CP %11111111            ; If all bits set (including bit 0), it means that
                          ; 'P' ISN'T being pressed
  JR Z,L51152             ; If that's the case, jump to L51152 Otherwise,
                          ; continue to the pause game routine

; Pause game routine - play tune and check user input
;
; Used by the routines at L50870 and L51141.
;
; (This is where the ERRSP stack pointer error is pointed at in routine at
; L48992)
;
; When 'P' is pressed (check made in previous routine at L51032), the game is
; paused and some music is played:
; * while the game is paused, the player can press 'S' to save the game, or 'O'
;   to resume the game
; * the keyboard checks for 'S' and 'O' are done at 51053 after a full cycle of
;   the tune has played
; * this means the player needs to keep the relevant key (to save/resume the
;   game) held down until the tune has finished its current loop
L51043:
  LD A,0                  ; Set game flag to 0 (new/current game), in
  LD (48921),A            ; preparation for the player leaving the pause menu
                          ; returning to the game. Checked at the start of the
                          ; game cycle keyboard checks at L50870.
  LD A,2                  ; This tells the music player to play tune number 2
                          ; (the 'pause game' music) - a short tune stored at
                          ; 60530.
  CALL L58806             ; Play the tune
; This routine checks if the player is pressing 'S', which saves the current
; game.
  LD BC,65022             ; Keyboard port address for keys A, S, D, F, G
  IN A,(C)                ; Check this half-row of the keyboard
  OR %11111101            ; For the 'S' key we're interested in the second
                          ; lowest bit (bit 1), so set all the other bits to 1
  CP %11111111            ; If bit 1 is set to 1, all the bits will be set to
                          ; 1, indicating the 'S' key isn't being pressed.
  JR Z,L51141             ; If this is the case and 'S' isn't being pressed,
                          ; jump to L51141 to check if the 'O' key (resume) is
                          ; being pressed.
; The player has pressed the 'S' key to save the current game. This code prints
; "Start tape then press enter" on the scroll.
  CALL L57081             ; Clear the scroll status panel at the bottom of the
                          ; screen
  LD A,37                 ; "Start tape then press enter" is message number 37
  CALL L58789             ; Get the address pointer for this message text
                          ; (L29523)
  LD (L60065),HL          ; ...and store it.
  LD HL,20615             ; Set and store address position to print text
  LD (60068),HL           ; (centre-left of scroll)
  CALL L58064             ; Print the text string on the scroll
; This routine checks the keyboard until the player presses ENTER
L51043_0:
  LD BC,49150             ; Keyboard port address for keys H, J, K, L, ENTER
  IN A,(C)                ; Check this half-row of the keyboard
  OR %11111110            ; For the ENTER key we're interested in the lowest
                          ; bit (bit 0), so set all the other bits to 1
  CP %11111111            ; If bit 0 is set to 1, all the bits will be set to
                          ; 1, indicating the ENTER key isn't being pressed.
  JR Z,L51043_0           ; If this is the case, keep checking this keyboard
                          ; half-row until ENTER is pressed
; Player has (started the tape and) pressed ENTER
  CALL L57081             ; Clear the scroll status panel at the bottom of the
                          ; screen, ready to save. Then continue to the next
                          ; routine to save the game.

; Pause game routine - save the current game
;
; This routine is triggered if the player presses 'S' while the game is paused,
; in the previous routine keyboard check at 51053.
;
; Data block 1:
L51098:
  LD A,255                ; Indicates this is a data block to save
  LD IX,L59956_6          ; Start address of data block to save
  LD HL,60577             ; End address of data block
  LD DE,L59956_6          ; Start address of data block
  SCF                     ; Set the carry flag
  CCF                     ; Then toggle it, to clear it
  SBC HL,DE               ; Subtract data start address from end address
  INC HL                  ;
  EX DE,HL                ; ...DE now contains the number of bytes in this data
                          ; block = 514 bytes
  CALL 1218               ; Call the ROM routine to save this data block to
                          ; tape
; Data block 2:
  LD A,255                ; Indicates this is a data block to save
  LD IX,(56053)           ; Start address of data block to save (L26512)
  LD HL,(60257)           ; End address of data block (32851)
  LD DE,(56053)           ; Start address of data block
  SCF                     ; Set the carry flag
  CCF                     ; Then toggle it, to clear it
  SBC HL,DE               ; Subtract data start address from end address
  INC HL                  ;
  EX DE,HL                ; ...DE now contains the number of bytes in this data
                          ; block = 6340 bytes
  CALL 1218               ; Call the ROM routine to save this data block to
                          ; tape
; The game is now loaded - continue to the next routine (pause game), and the
; loaded game will start once the player presses 'resume'.

; Pause game routine - check if 'resume game' key is pressed
;
; Used by the routine at L51043.
;
; While the game is paused, check if the player is pressing 'O' to resume the
; game
L51141:
  LD BC,57342             ; Keyboard port address for keys Y, U, I, O, P
  IN A,(C)                ; Check this half-row of the keyboard
  OR %11111101            ; For the 'O key we're interested in the second
                          ; lowest bit (bit 1), so set all the other bits to 1
  CP %11111111            ; If bit 1 is set to 1, all the bits will be set to
                          ; 1, indicating the 'O key isn't being pressed.
  JR Z,L51043             ; If this is the case, return to the start of the
                          ; pause routine, play the music and keep checking the
                          ; keyboard. Otherwise, continue to the next routine
                          ; to resume the game, starting at the main game loop.

; Start of main game loop
;
; Used by the routine at L51032.
L51152:
  DI                      ; Disable interrupts
  CALL L58945             ; Check scroll status and player inputs such as
                          ; current spell selection, key controls
  LD HL,0                 ; Reset the address pointer to the ROM, that produces
  LD (60249),HL           ; semi-random byte values to play generic sound
                          ; effects in the routine at L57815.
  LD A,0                  ; Reset speaker bit (and border)
  OUT (254),A             ;
  LD (60072),A            ; Set the default graphics colour attribute to 0
                          ; (black INK, black PAPER)
  LD HL,(L56046)          ; Address pointer to the room data sets at 31744 that
                          ; contain scenery, object and creature data for the
                          ; current room
  LD (60092),HL           ; Copy base pointer to address store for start of
                          ; next data set
  LD (60094),HL           ; Copy base pointer to address store for start of
                          ; current data set

; Copy current room item data set into working buffer
;
; Used by the routine at L54053.
;
; HL Address pointer to room data sets at 31744 that contain the scenery,
;    object and creature data in the current room
;
; Get a room data set at 31744 and copy it into the working buffer at L60227,
; ready to deal with:
L51178:
  LD A,(HL)               ; Check for end-of-data byte
  CP 255                  ;
  JP Z,L54065             ; If found, skip out of routine
  LD BC,16                ; Prep counter to copy 16 bytes
  CP 0                    ; If the first byte is zero...
  JR NZ,L51178_0          ;
  ADD HL,BC               ; ...then this room item is no longer present, so
                          ; skip to the next data bank of 16 bytes
  JR L51178               ; ...and keep checking the data banks
; Copy room item data from data bank into working data buffer at L60227
L51178_0:
  LD DE,L60227            ; Copy data from 16 byte data bank at 31744 to L60227
  LDIR                    ;
  LD (60092),HL           ; Store address pointer, now at the start of the next
                          ; 16 byte data set
  LD A,(60238)            ; Item properties byte
  AND %11111011           ; Reset bit 2 of this data byte - to indicate this
                          ; particular room item doesn't needs erasing prior to
                          ; drawing
  LD (60238),A            ; ...and restore
  LD HL,(60241)           ; Get graphic address pointer to this item's
                          ; graphics, in the address pointer table at L38851
  LD (60109),HL           ; ...and store.
; Calculate and store this item's horizontal room co-ordinates. Horizontal
; half-character (4-pixel) position is converted to pixel position and stored
; at 60115.
;
; The carry bit is used in the calculation to store (at 60116) a flag
; indicating where the item is in the room, and is set to 0 (visible part of
; screen), 1 (right of the visible screen) or 255 (left of the visible screen).
  LD HL,(60231)           ; H = Graphic horizontal position within current
                          ; room, in half character (4 pixel) steps (H = 60232,
                          ; L = 60231). L contains an overflow from this.
  ADD HL,HL               ; x 2
  SBC A,A                 ; If carry set, set A to 255, otherwise 0
  ADD HL,HL               ; x 4 to complete conversion of horizontal position
                          ; from half-characters to pixels
  RLA                     ; If carry set, rotate carry bit into A register
  LD (60116),A            ; ...and store as the high byte, e.g. 0 = in room
                          ; viewport, 1 = to the right of the viewport, 255 =
                          ; to the left of the viewport
  LD A,H                  ; Get horizontal screen pixel position
  LD (60115),A            ; ...and store.
; The next instructions check bit 4 of the Graphic properties byte (this bit is
; unused).
  LD A,(60239)            ; This is the pre-graphics data byte (Graphic
                          ; properties)
  AND 16                  ; Check if bit 4 set (16)
  JR Z,L51255             ; If it's NOT set, jump to L51255
; None of the graphics has bit 4 (16) set, so these instructions aren't run
; (which add an offset to the graphic address pointer):
  LD HL,(60241)           ; ---
  ADD HL,DE               ; ---
  ADD HL,DE               ; ---
  LD (60241),HL           ; ---
  LD A,(60238)            ; ---
  OR 4                    ; ---
  LD (60238),A            ; ---
  JR L51255_0             ; ---

; Adjust room item's position based on the speed and direction of Maroc and the
; item
;
; Used by the routine at L51178.
;
; Re-calculate the item's screen position based on the combined speed
; directions of Maroc (or the room) and the item
;
; Firstly check if the graphic is animated, or has a left/right (multi-)facing
; directions. If so, first deal with the graphics animation frame:
L51255:
  LD A,(60239)            ; Get the Graphic properties byte (again)
  AND 192                 ; Check the top 2 bits (6 & 7). Bit 6 set = graphic
                          ; has left/right facing versions Bit 7 = graphic is
                          ; animated
  JR Z,L51255_0           ; If neither is set, there's nothing to change
                          ; animation-wise, so skip the following CALL
                          ; instruction
  CALL L58166             ; If either of the bits are set, handle the animation
                          ; frame(s) for this graphic
; The next routine calculates the item's adjusted room position based on the
; trajectory of Maroc and the trajectory of the item. Calculations include:
; * Converting speed values, which are stored as 4 x pixel values (e.g. a speed
;   of 32 would cause the the item to move 32/4 = 8 pixels )
; * Using overflow/offset bytes (e.g. at 60108) to calculate pixel
;   fractions/overflows
; * Converting horizontal 4-pixel/half-character horizontal positions to pixel
;   positions
;
; Calculate item's new HORIZONTAL speed/position based on a combination of the
; item's speed and Maroc's speed
L51255_0:
  LD A,(60236)            ; Item's horizontal movement speed (this will be
  LD C,A                  ; non-zero for moving things such as creatures)
  LD A,(60164)            ; Maroc's horizontal movement speed (reverse of the
                          ; above)
  ADD A,C                 ; Add them together to get the combined speed of the
                          ; moving item
  LD L,A                  ; ...and store in the L register
  RLA                     ; Rotate into carry bit
  SBC A,A                 ; A register is now 0 or 255 (-1)
  LD H,A                  ; Put 0 or 255 in H register - the ADD HL,HL
                          ; statements will now add or subtract the offset
                          ; depending on whether Maroc is moving left or right
; The speed needs to be added to the high byte holding the item's horizontal
; (4-pixel) position.
;
; The following ADD instructions make this adjustment - e.g. a speed of 32
; would be shifted into bit 1 (2) of the high byte - this would mean a result
; of 2 (x 4-pixel/half-character steps, or 8 pixels).
  ADD HL,HL               ; x2
  ADD HL,HL               ; x4
  ADD HL,HL               ; x8
  ADD HL,HL               ; x16
  EX DE,HL                ; Swap into DE register pair
  LD HL,(60231)           ; Graphic horizontal position within current room, in
                          ; half character (4 pixel) steps.
  ADD HL,DE               ; Add to speed to get the new position
  LD (60231),HL           ; ...and re-store the adjusted horizontal position
  ADD HL,HL               ; Value in HL is 4-pixel steps, convert to pixels by
                          ; multiplying by 4 - first x2
  SBC A,A                 ; Put the carry into the A register as this will act
                          ; as an overflow to the calculated horizontal pixel
                          ; position
  ADD HL,HL               ; x4
  RLA                     ; Repeat with any carry - shift into A register
  LD (60108),A            ; Store the horizontal pixel position overflow...
  LD A,H                  ;
  LD (L60107),A           ; ...and the new horizontal pixel position
; If the graphic has moved on-screen, make sure it's erased at its old position
; before it gets redrawn at its new one:
  LD B,A                  ; Store new horizontal pixel position in B register
  LD A,(60115)            ; Get the original horizontal pixel position
  CP B                    ; Compare it with the new horizontal pixel position
  JR Z,L51255_1           ; Has the graphic moved?
; Graphic has moved on-screen
  LD A,(60238)            ; Get the graphics properties byte
  OR 4                    ; Set bit 2 (4) - this indicates the graphic will
                          ; need erasing (before it's redrawn)
  LD (60238),A            ; ...and re-store
; Calculate item's new VERTICAL speed/position based on a combination of the
; item's speed and Maroc's speed
L51255_1:
  LD A,(60237)            ; Item's vertical movement speed
  LD D,A                  ;
  LD A,(60165)            ; Maroc's vertical movement speed (reverse of the
                          ; above)
  ADD A,D                 ; Add them together to get the effective speed of the
                          ; moving item
  LD L,A                  ; ...and store in the L register
  RLA                     ; Rotate into carry bit
  SBC A,A                 ; A register is now 0 or 255 (-1)
  LD H,A                  ; Put 0 or 255 in H register - the ADD HL,HL
                          ; statements will now add or subtract the offset
                          ; amount depending on whether Maroc is moving up or
                          ; down
; Next, a similar calculation to the horizontal position, where the speed value
; is shifted into the high byte of HL to provide the offset pixel value for the
; item's vertical screen position.
;
; Vertical position is held in pixels (rather than half-characters like the
; horizontal position), so 6 straight shifts to the left (x64) will calculate
; the new vertical pixel position from the speed.
  ADD HL,HL               ; x2
  ADD HL,HL               ; x4
  ADD HL,HL               ; x8
  ADD HL,HL               ; x16
  LD A,(60234)            ; Graphic's vertical pixel position within current
                          ; room
  LD (60114),A            ; Copy into item working data buffer
  ADD HL,HL               ; x32
  ADD HL,HL               ; x64
  EX DE,HL                ; Swap into DE register pair
  LD HL,(60233)           ; Graphic vertical pixel position within current room
  LD A,H                  ; High byte - contains 'actual' pixel position
  ADD HL,DE               ; Add to speed to get the new position
  LD (60233),HL           ; ...and restore the new vertical pixel position
; If the graphic has moved on-screen, make sure it's erased at its old position
; before it gets redrawn at its new one:
  CP H                    ; Compare old with new vertical position
  JR Z,L51359             ; Has the graphic moved?
; Graphic has moved on-screen
  LD A,(60238)            ; Get the graphics properties byte
  OR 4                    ; Set bit 2 (4) - this indicates the graphic will
                          ; need erasing (before it's redrawn)
  LD (60238),A            ; ...and re-store.

; Deal with and check room item, creature or scenery
;
; Used by the routine at L51255.
;
; The first byte of the working data set at L60227 (this data is copied from
; each of the 16 byte room item data sets at 31744) is checked here.
;
; It indicates the type of room object that needs to be drawn, checked or
; generally dealt with.
L51359:
  LD A,(L60227)
  CP 1                    ; Back wall bricks/scenery, or door frames,
  JP Z,L53885             ; wall/floor connector graphics or cursor
  CP 2                    ; Door
  JP Z,L51420             ;
  CP 3                    ; Creature
  JP Z,L52616             ;
  CP 4                    ; Interactable objects (e.g. key, chest, scroll)
  JP Z,L51968             ;
  CP 5                    ; Missile fired by creature/warlock
  JP Z,L53403             ;
  CP 6                    ; Vertical back wall/floor connector (left)
  JP Z,L53601             ;
  CP 7                    ; Vertical back wall/floor connector (right)
  JP Z,L53601_0           ;
  CP 8                    ; Missile fired by Maroc
  JP Z,L53403             ;
  CP 15                   ; Tunnel position (& direction)
  JP Z,L53625             ;
  CP 14                   ; Tunnel item (side boundary wall, bat or spider)
  JP Z,L53714             ;
  CP 32                   ; Room position & viewport
  JP Z,L53870             ;
  JP L53885               ; Jump from here if nothing to deal with. Data set
                          ; room items that are no longer present (e.g. a
                          ; destroyed creature) will have this byte set to 0 to
                          ; indicate they no longer exist.

; Determine if creatures will enter the current room
;
; Used by the routine at L51359.
;
; Creatures will follow Maroc into a room after a short delay. Maroc can:
; * Lose his pursuers if he exits the room before they appear
; * Move away so the door is off-screen. Creatures won't enter the room
;   off-screen, though they may appear once the door is back in view.
;
; Creatures may also wander in from other adjacent rooms. The frequency of this
; happening is much lower - there's a longer timer counter for this event.
;
; This is the first routine run when handling DOOR items (item number 2), in
; the room item check at L51359.
L51420:
  LD A,(60238)            ; Get item properties byte (for the door)
  LD C,A                  ;
  AND 1                   ; Bit 1 indicates if the item is on-screen (0 = no, 1
                          ; = yes)
  JP Z,L53885             ; If the door isn't on-screen, nothing more to do or
                          ; check in this routine
  LD A,C                  ; If the bit is set, the door is on-screen. Retrieve
                          ; item properties byte
  AND 240                 ; Filter out bits 0-3
  CP 0                    ; If any of bits 4-7 are set, there's already
                          ; something already happening with this door that
                          ; needs dealing with
  JP Z,L51420_0           ; No bits set - skip next few checks
  CP 32                   ;
  JP Z,L51854             ; Bit 5 (32) set = Maroc or a creature has touched a
                          ; door, so it needs to be opened/closed
  CP 64                   ; Bit 6 (64) set = means the door is currently
  JP Z,L51892             ; opening or closing
  JP L51892_3             ; Bit 7 (128) set = Maroc has just gone through this
                          ; doorway
; Creatures will follow Maroc into other rooms. After Maroc enters a room, a
; check is made every 16 game cycles to see if there are any creatures in the
; connecting room.
;
; This gives Maroc a short time to quickly move room again before the creature
; enters. Doing so lets him successfully escape his pursuers.
L51420_0:
  LD A,(L60074)           ; Game cycle counter/timer
  AND 15                  ; Check bits 0-3 (values = 0-15)
  JP NZ,L51611            ; If anything other than 0, skip this check
; Every 16 frames/game cycles:
  LD A,(60230)            ; Door being checked - 0 = Back wall, 1 = Right wall,
  LD C,A                  ; 2 = Left wall
  LD A,(60084)            ; Connecting door (in table at L26512) that Maroc
  CP C                    ; entered the current room from
  JR Z,L51420_1           ; If Maroc entered through this door, check if there
                          ; were any creatures in his previous room
; Maroc didn't enter through this door. However, there's still a chance that
; any creatures in the adjacent connected room may wander in.
;
; A random number is generated and compared against the delay counter at 60341.
; There will be a much greater delay before this event occurs (a monster
; wandering in, rather than pursuing).
;
; Additionally, creatures will not wander into the room if there is already
; another creature in the room.
  CALL L56070             ; Generate pseudo-random number
  AND 127                 ; Filter out bit 7 (just keep random values 0-127)
  LD C,A                  ;
  LD A,(60341)            ; Timer indicating how long before a creature is
                          ; likely to wander in from an adjacent room
  DEC A                   ; Decrement the counter
  LD (60341),A            ; ...re-store it...
  CP C                    ; Compare it with the randomly generated value
  JP NC,L51611            ; If timer is (still) >= than the random value, a
                          ; creature won't wander into the room
  LD A,(60343)            ; Timer is less than the random value. Get the number
  CP 0                    ; of creatures currently in the room
  JP NZ,L51611            ; If there are ANY creatures already in the room,
                          ; don't let any more enter
; First, check if we've reached the maximum creatures-per-room (3)
L51420_1:
  LD A,(60342)            ; Get number of creatures currently in room
  CP 3                    ;
  JR NC,L51611            ; If there are already 3, skip the whole check as
                          ; there can't be any more
; Use the connecting door table at L26512 to check which rooms are adjacent to
; this one
  LD HL,(60228)           ; Address pointer to connecting door table at L26512
  LD C,(HL)               ; First byte in set contains the room number for this
                          ; door
  LD A,(60087)            ; Current room number
  CP C                    ; Is it the same as the first byte of the connecting
  JR NZ,L51420_2          ; door set?
  INC HL                  ; If so, the door is in this room - move to next byte
  LD C,(HL)               ; This byte holds the connecting room for this door
  LD A,223                ;
  CP C                    ;
  JR C,L51611             ; If the connecting room is >=224, the door leads to
                          ; a tunnel. Nothing can enter from that direction so
                          ; skip out of the routine
; Check for any creature data in the adjacent room
L51420_2:
  DEC C                   ; C register will be part of an offset (BC register
                          ; pair) to add to an address pointer for the room
                          ; creature table at L27532. Room numbers start at 1,
                          ; but it needs to start at 0 for the offset, so
                          ; reduce the value by 1
  LD B,0                  ; Reset B register (ready for offset to be added)
  LD HL,(56048)           ; Address pointer at start of room creature data at
                          ; L27532
  ADD HL,BC               ; Add the offset to get to the right creature data in
                          ; this adjacent room
  LD A,(HL)               ; Get the room creature data (all stored in 1 single
  LD C,A                  ; byte)
  CP 0                    ;
  JR Z,L51611             ; If there are no creatures in this room, there
                          ; aren't any creatures who might come through this
                          ; door
; There IS a creature (or creatures) in the adjacent room that this door
; connects to:
  LD A,(60238)            ; Get door properties byte
  LD D,A                  ; Temp store in D register
  AND 240                 ; Clear bits 0-3
  CP 0                    ; Any of bits 4-7 set? This check has already been
                          ; made at 51430, so the jump in the next instruction
                          ; shouldn't be triggered.
  JR NZ,L51611            ; If so, jump out of routine here
  LD A,D                  ; Retrieve door properties byte
  AND 8                   ; Check bit 3 - if set, indicates door is open,
                          ; otherwise closed
  JR NZ,L51551            ; If door is open, skip ahead to the next routine
  LD A,D                  ; Retrieve door properties byte
  ADD A,64                ; A creature is entering the room and the door is
                          ; closed. Open the door by setting bit 6 (if set this
                          ; indicates the door is now opening/closing)
  LD (60238),A            ; ...and re-store
; The next routine determines the type of creature that will enter the room.

; Check which creatures are entering the room
;
; Used by the routine at L51420.
;
; C Creature data byte from room creature list at L27532
;
; Checks at the previous routine have determined that a creature in an adjacent
; room will enter Maroc's room. Creatures appear one by one.
;
; This routine determines what type of creature (from those in the adjacent
; room) will enter out of:
; * Guardian of chaos
; * Goblin warrior
; * Goblin missile thrower
; * Wraith
;
; Creature type checks are made in the order below. So if there's a mix of
; creatures, this determines the priority of entry into the room.
L51551:
  LD A,C                  ; Get room creature byte from table at L27532
; Check for any GUARDIANS OF CHAOS
  AND %11000000           ; Bits 6 & 7 - creature data for guardians of chaos
  JR Z,L51551_0           ; If there aren't any in this room, skip to the next
                          ; check
  LD A,C                  ; Retrieve room creature byte
  SUB 64                  ; Guardian of chaos is entering the room, so reduce
                          ; the number of guardians of chaos in the adjacent
                          ; room by 1
  LD (HL),A               ; ...and re-store the reduced room creature byte
                          ; value
  LD A,8                  ; Creature type number for guardian of chaos = 8
  JR L51551_3             ;
; Check for any GOBLIN WARRIORS
L51551_0:
  LD A,C                  ; Retrieve room creature byte
  AND %00110000           ; Bits 4 & 5 - creature data for goblin warriors
  JR Z,L51551_1           ; If there aren't any in this room, skip to the next
                          ; check
  LD A,C                  ; Retrieve room creature byte
  SUB 16                  ; Goblin warrior is entering the room, so reduce the
                          ; number of goblin warriors in the adjacent room by 1
  LD (HL),A               ; ...and re-store the reduced room creature byte
                          ; value
  LD A,9                  ; Creature type number for goblin warrior = 9
  JR L51551_3             ;
; Check for any GOBLIN MISSILE THROWERS
L51551_1:
  LD A,C                  ; Retrieve room creature byte
  AND %00001100           ; Bits 2 & 3 - creature data for goblin missile
                          ; throwers
  JR Z,L51551_2           ; If there aren't any in this room, skip to the next
                          ; check
  LD A,C                  ; Retrieve room creature byte
  SUB 4                   ; Goblin missile thrower is entering the room, so
                          ; reduce the number of goblin missile throwers in the
                          ; adjacent room by 1
  LD (HL),A               ; ...and re-store the reduced room creature byte
                          ; value
  LD A,10                 ; Creature type number for goblin missile thrower =
  JR L51551_3             ; 10
; If the creature entering the room isn't one of the above, it must be a WRAITH
; (bits 0 & 1)
L51551_2:
  LD A,C                  ; Retrieve the creature byte
  SUB 1                   ; Wraith is entering the room, so reduce the number
                          ; of wraiths in the adjacent room by 1
  LD (HL),A               ; ...and re-store the reduced room creature byte
                          ; value
  LD A,11                 ; Creature type number for wraith = 11
; Creature type entering the room has been identified
L51551_3:
  LD (60343),A            ; Store creature type
  LD A,(60232)            ; Get the door graphic horizontal position within
                          ; current room, in half character (4-pixel) steps
  LD (60344),A            ; Copy this to the entering creature's horizontal
                          ; room position, as this will be its entry point
  LD A,(60234)            ; Similarly, get the door vertical pixel position
  LD (60345),A            ; Copy to the entering creature's vertical room
                          ; position

; Check for an on-screen door being opened or closed
;
; Used by the routine at L51420.
;
; This routine follows the previous one - it runs each game cycle and checks
; any doors that are currently on-screen.
;
; The next instructions set an event check number in the C register, which is
; later used in the CALL at L51611_1 (to L57293_0) for the door's
; collision/event check
L51611:
  LD A,(60238)            ; Get door properties byte
  AND 8                   ; Check bit 3 (8) - open/closed flag. 1 if the door
  LD C,1                  ; is open, 0 if it's closed
  JR NZ,L51611_0          ; If it's open, set C register value to 1 and jump a
                          ; few instructions to L51611_0
  LD HL,(60228)           ; Address pointer to door table sets at L26512
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  LD C,(HL)               ; Door is closed - load C register with 4th byte from
                          ; door data set at L26512
; C register (for event/collision detection) now contains:
; * Door OPEN = 1 - can be closed by Maroc, creatures, servant, creature
;   missile, or
; * Door CLOSED = 4th byte of relevant door set at L26512 (door closed). This
;   will be 0 = can be 'bumped' open by Maroc, 1 = openable by
;   Maroc/servant/creature missile, or other event number which corresponds to
;   an object (e.g. a key) or a spell (e.g. OPEN)
;
; The next instructions identify the door's handle position, the 'hit box' to
; check for collisions. This will vary depending on the door graphic, position
; and whether it's open or closed.
L51611_0:
  LD HL,(60241)           ; Get address pointer to door graphics in table at
  LD E,(HL)               ; L38851
  INC HL                  ;
  LD D,(HL)               ; Get the address pointing directly at the door
                          ; graphics from this table
  EX DE,HL                ; ...and switch back into HL register pair
  INC HL                  ;
  LD A,(HL)               ; Get the graphic's horizontal pixel graphic offset
  LD B,A                  ; Store in B register
  INC HL                  ;
  LD H,(HL)               ; Get the graphic's vertical pixel graphic offset
  LD (60079),A            ; ...store
  LD A,(60115)            ; Graphic's horizontal position in pixels
  ADD A,B                 ; Add horizontal pixel offset
  LD D,A                  ; Store in D register
  LD A,(60114)            ; Graphic vertical pixel position
  ADD A,H                 ; Add vertical pixel offset
  ADD A,24                ; We need to work out the door handle's 'hit box' for
                          ; opening/closing.The graphic position, plus vertical
                          ; offset, gives us the co-ordinates at the top of the
                          ; graphic. We need to define its 'hit box' more
                          ; towards its middle, so add 24 pixels.Otherwise, the
                          ; door would have to be opened/closed by touching the
                          ; top of it.
  LD E,A                  ; Store in E register
  LD A,(60238)            ; Get door properties byte
  AND 8                   ; Check bit 3 (8) - this is 1 if the door is open, 0
                          ; if it's closed
  JR Z,L51611_1           ; If it's closed, skip the next few instructions and
                          ; jump to L51611_1
; Maroc opens and closes doors by bumping into the bit of the door near its
; handle. The position is slightly different depending on the door alignment.
;
; The 'hit box' on the handle of OPEN doors needs to be slightly adjusted.
;
; DOOR IS OPEN. Adjust collision area as handle may be somewhere other than its
; default position.
  LD A,B                  ; Retrieve graphic's horizontal pixel graphic offset
  CP 248                  ; The only door frame with this offset is the back
                          ; wall open door
  JR Z,L51611_1           ; Don't need to adjust anything if it's this one
  LD A,E                  ; For all other doors, subtract 8 pixels from the
  SUB 8                   ; vertical 'hit box' position
  LD E,A                  ; Store in E register - this is used for the vertical
                          ; pixel collision checks in a moment at L51611_1
; Run a collision detection check against the calculated door handle position
; (creatures, Maroc, servant, key, open spell, etc.).
;
; The C register contains a value determining the type of event check to make -
; loaded with the 4th byte from the door data sets at L26512 - this is
; typically 0, occasionally 1 (meaning this door can be opened by the servant
; or deflected missiles), or if a door is locked its acting key event number,
; or spell number (e.g. OPEN).
L51611_1:
  CALL L57293_0           ; Collision check routine
  CP 1                    ; A register returned with either 1 (collision) or 0
  JR NZ,L51611_2          ; (no collision)
; Collision with door detected
  LD A,(60238)            ; Get door properties byte
  AND 15                  ; Keep bits 0-3
  OR 32                   ; Set bit 5 (32) - this is a flag/trigger to indicate
                          ; the door needs to be opened or closed when checked
                          ; (at L51420) during the next game cycle
  JP L51892_1             ; Skip out to end of routine
; No collision with door detected
L51611_2:
  LD A,(60238)            ; Get door properties byte
  LD C,A                  ; Temp store in C register
  AND 1                   ; Check bit 1 - is the door visible on-screen?
  JP Z,L53885             ; If not, can skip out of routine - nothing needs
                          ; doing
  LD A,C                  ; Retrieve door properties byte
  AND 8                   ; Check bit 4 (8) - 1 if door is open, 0 if closed
  JP Z,L51892_2           ; If it's closed, jump out to the end of the routine

; Check if Maroc is moving through an open doorway
;
; Door has been identified as OPEN.
;
; Because door positions vary when open depending on the wall section they sit
; in, the next routine adjusts the doorway exit point, based on the open door's
; graphic position.
;
; After this adjustment has been made the collision detection routine at
; L57293_0 is used to determine if Maroc is moving through the doorway.
L51702:
  LD A,(60079)            ; Door graphic's horizontal position offset
  CP 248                  ;
  JR Z,L51702_0           ; The only door frame with this value offset is the
  CP 232                  ; back wall open door
  JR Z,L51702_1           ; The only door frame with this value offset is the
                          ; right wall open door
  LD A,248                ; Horizontal pixel offset for left wall open door
  JR L51702_2             ; left wall open door (-8 pixels)
L51702_0:
  LD A,12                 ; Horizontal pixel offset for the back wall open door
  JR L51702_2             ; (+12 pixels)
L51702_1:
  LD A,8                  ; Horizontal pixel offset for the right wall open
                          ; door (+8 pixels)
; Add the adjusted offset to door horizontal pixel position
L51702_2:
  LD B,A                  ; Get the pixel offset for this door's exit/entry
                          ; point
  LD A,(60115)            ; Get the door's horizontal pixel position
  ADD A,B                 ; Add the pixel offset
  LD D,A                  ; Store in the D register - used for the horizontal
                          ; 'hit box' for collision check in CALL at 51737 (to
                          ; L57293_0)
  LD A,(60114)            ; Get the door's vertical pixel position
  SUB 8                   ; Small (-8 pixel) vertical adjustment
  LD E,A                  ; Store in E register - used for the vertical 'hit
                          ; box' for collision check in CALL at 51737 (to
                          ; L57293_0)
  LD C,0                  ; Collision type = 0 - this is the collision/event ID
                          ; for checks against Maroc's position
  CALL L57293_0           ; Check for collision
  CP 0                    ; A register returned with 1 = collision, 0 = no
                          ; collision
  JR NZ,L51702_3          ; If there's a collision, skip the next few
                          ; instructions
; No collision detected on that check
  LD A,E                  ; Retrieve previously adjusted horizontal pixel check
                          ; position
  SUB 4                   ; Make a further small (-4 more pixels) horizontal
                          ; adjustment
  LD E,A                  ; Store back in E register (horizontal 'hit box'
                          ; check)
  LD A,(60115)            ; Door vertical pixel position
  LD D,A                  ; Retrieve vertical 'hit box' pixel position from D
                          ; register
  LD C,0                  ; Collision type = 0 - this is the collision/event ID
                          ; for checks against Maroc's position
  CALL L57293_0           ; Check for collision
  CP 0                    ;
  JP Z,L51892_2           ; No collision, can jump out of routine here
; Collision detected - Maroc is within range of the open door. Check he's
; actually moving towards it.
L51702_3:
  LD A,(60079)            ; Retrieve door graphic's horizontal pixel graphic
                          ; offset
  CP 248                  ; Offset for the back wall open door
  JR Z,L51702_4           ;
  CP 232                  ; Offset for the right wall open door
  LD A,(60164)            ; Get Maroc's horizontal movement speed as it'll need
  JR Z,L51702_5           ; to be evaluated for left and right wall doors
; Door is a left wall open door. Check Maroc's horizontal movement:
  CP 0                    ; Is Maroc moving left or right?
  JP Z,L51892_2           ; If not, skip out of this routine
  CP 128                  ;
  JP NC,L51892_2          ; Skip out of this routine if Maroc is moving right
  JR L51813               ; ...otherwise Maroc is moving left, so send him
                          ; through the doorway
; Door is a back wall open door. Check Maroc's vertical movement:
L51702_4:
  LD A,(60165)            ; Maroc's vertical movement speed
  CP 0                    ; Is Maroc moving up or down?
  JP Z,L51892_2           ; If not, skip out of this routine
  CP 128                  ;
  JP NC,L51892_2          ; Skip out of this routine if Maroc is moving down
  JR L51813               ; ...otherwise Maroc is moving upwards, so send him
                          ; through the doorway
; Door is a right wall open door. Check Maroc's horizontal movement:
L51702_5:
  CP 0                    ; Is Maroc moving left or right?
  JP Z,L51892_2           ; If not, skip out of this routine
  CP 128                  ;
  JP C,L51892_2           ; Skip out of this routine if Maroc is moving left
                          ; ...otherwise Maroc is moving right, so send him
                          ; through the doorway (continue to the next routine)

; Maroc is moving through a doorway
;
; Follows checks from the previous routine at L51702.
;
; Sets a couple of bytes/flags in the connecting door table at L26512 to
; indicate Maroc's entry point for this door.
L51813:
  LD A,(60230)            ; Door set number in the connecting room data at
                          ; L26512
  LD (60084),A            ; Copy to working data buffer
  LD A,(60234)            ; Door's vertical pixel position
  DEC A                   ; Very minor vertical adjustment (-1 pixel)
  LD (L60276),A           ; Store as new room vertical entry position
  LD HL,(60228)           ; Address pointer for door set number in the
                          ; connecting room data at L26512
  LD (60085),HL           ; Copy to working data buffer
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  LD (HL),0               ; Set the 4th byte of the relevant door set (in the
                          ; table at L26512) to 0. This is the standard event
                          ; collision identifier for Maroc (touching a doorway
                          ; space).
  LD A,255                ; Room number set to 255 - signifies that the next
  LD (60080),A            ; room number will need calculating (using the door
                          ; connector table at L26512)
  LD A,(60238)            ; Door properties byte
  AND 15                  ; Keep bits 0-3
  OR 128                  ; Set bit 7 - used to flag that Maroc has entered
                          ; through this door
  LD (60149),A            ; The byte stored here will be put in byte 3 of the
                          ; connecting door set at L26512, in the routine at
                          ; 50656
  JR L51892_1             ; Jump to end of door routine checks

; Trigger door opening or closing
;
; Used by the routine at L51420.
;
; Door opening/closing has been triggered. Jump from 51439 if bit 5 (32) of
; item properties byte (60238) is set, after Maroc has bumped into a door
; handle. Check made using collision check routine at L57293.
;
; Can be triggered by:
; * Maroc bumping into a door to open or close it
; * Servant closing a door
; * Creature closing a door
; * Missile fired by a creature closing an open door (e.g. rebounding off
;   Maroc's shield)
L51854:
  LD HL,(60241)           ; Door graphic address pointer in table at L38851
  LD E,(HL)               ;
  INC HL                  ;
  LD D,(HL)               ; Address pointer to actual door graphics, e.g. 40248
  EX DE,HL                ; Swap into HL register pair
  INC HL                  ;
  LD B,(HL)               ; Get X co-ordinate pixel offset for graphic tile
  LD A,(60115)            ; Get graphic's X co-ordinate pixel position on
                          ; screen
  ADD A,B                 ; Add the pixel offset for the graphic tile
  LD D,A                  ; Store in D register
  LD A,(60114)            ; Get vertical (Y) pixel co-ordinate
  SUB 16                  ; The vertical co-ordinate starts at the bottom of
                          ; the door, move up a bit to get to the door handle
                          ; area
  LD E,A                  ; Store in E register
  LD C,1                  ; Collision/event type to check (1 = Door being
                          ; opened/closed)
  CALL L57293             ; Run a collision check (item/Maroc vs door handle)
  CP 0                    ; Was there a collision?
  JR NZ,L51892_2          ; If not, jump out of this routine
; A door handle has been touched so initialize door opening/closing
  LD A,(60238)            ; Door properties byte
  AND 15                  ; Keep bits 0-3
  OR 64                   ; Set bit 6 (indicates door is now opening or
  JR L51892_1             ; closing)

; Door opening or closing
;
; Used by the routine at L51420.
;
; C Door properties byte at 60238
;
; If bit 6 (64) of the door's properties byte is set, it means the door is in
; the process of opening or closing.
;
; This routine determines which way the door is swinging based on its wall
; position and direction (opening vs closing). From this, the graphics frame
; address pointer is calculated.
L51892:
  LD A,(60240)            ; Graphic frame offset, based on the door's wall
                          ; position and open/closed status, calculated at
                          ; 50091
  LD B,A                  ; Store in B register
; Determine if graphic pointer offset is negative or positive (e.g. closing vs
; opening)
  RLA                     ; Rotate bits left
  SBC A,A                 ; Subtract-with-carry means A register now contains 0
  ADD A,A                 ; (positive) or 255 (negative)
  INC A                   ;
  LD E,A                  ; E register will now contain either 1 (positive) or
                          ; 255 (negative)
  RLA                     ; We need a value for a 2-byte address pointer, so do
  SBC A,A                 ; the same for the high byte
  LD D,A                  ; D will either contain 0 - for positive - or 255
                          ; (-1) - for negative
; DE now contains an offset of 1 or -1 to indicate which way to move the
; graphics address pointer, depending on whether the door is opening or
; closing.
  LD A,E                  ; Retrieve the original frame offset
  ADD A,B                 ; Add (or subtract if negative) the +1/-1 offset
  LD B,A                  ;
  AND 15                  ; For the frame address pointer offset, we're only
                          ; interested in the lowest 4 bits (0-3) as we just
                          ; need to figure out a small offset to the graphics
                          ; address pointer
  JR Z,L51892_0           ; If it's now zero, the door is now fully opened or
                          ; closed so we can skip the rest of the instructions
                          ; in this block
  LD H,A                  ; Otherwise, copy the offset to the H register
  LD A,(60239)            ; This is the pre-graphics properties data byte - for
                          ; doors it's used to identify the number of animation
                          ; frames to open or close this particular door
                          ; (calculated at 50091)
  AND 15                  ; Again, we only really need bits 0-3 here
  CP H                    ; Check calculated frame offset against the current
                          ; frame offset
  JR C,L51892_0           ; If calculated offset is now < stored byte, the door
                          ; is fully opened or closed
  LD A,B                  ; Otherwise, store as the new current frame value
  LD (60240),A            ; offset
  LD HL,(60241)           ; Graphics address pointer to current door frame
  ADD HL,DE               ; graphic at L38851 - doors start at 38867
  ADD HL,DE               ; Graphics addresses are 2 bytes long, so add the
                          ; frame offset (-1 or +1) twice
  LD (60241),HL           ; ...and re-store the address pointer
  LD A,C                  ; Retrieve door properties byte (from 60238)
  OR 4                    ; Set bit 2 (4) to indicate existing door graphic
  JR L51892_1             ; will need to be erased
; Door is now fully closed or open.
;
; Play a 'crunch' sound effect to indicate the door has fully opened or closed.
L51892_0:
  LD A,16
  LD (60246),A            ; Sound effect duration counter for the 'crunch' that
                          ; happens when a door is fully opened or closed
  LD A,(60240)            ; Graphic frame number offset
  XOR 224                 ; This XOR sets the frame offset by setting its top 3
                          ; bits from positive to negative or vice versa,
                          ; reversing the frame animations for next time
                          ; (closed to open, open to closed)
  LD (60240),A            ; Re-store the updated frame offset value
  LD A,C                  ; Retrieve door properties byte (from 60238)
  AND 15                  ; Keep bits 0-3
  XOR 8                   ; Then toggle bit 3 which indicates whether the door
                          ; is open or closed:
                          ; * If the door was open, it's now closed
                          ; * If the door was closed, it's now open
; This entry point is used by the routines at L51611, L51813 and L51854.
L51892_1:
  LD (60238),A            ; Re-store the graphic properties byte, amended based
                          ; on the various door checks and animations
; This entry point is used by the routines at L51611, L51702 and L51854.
L51892_2:
  JP L53885               ; Jump to the next routine.
; The jump to these instructions is made from 51447 (skipping all the door
; checks) if Maroc is moving through a doorway.
L51892_3:
  LD A,(60238)            ; Door properties byte
  ADD A,128               ; If bit 7 is set (which it will be) Maroc has just
  JR L51892_1             ; gone through a doorway. Add 128 to reset this bit
                          ; (back to 0) ready to move him to the next room.

; Set up 'interactable' objects in current room
;
; Used by the routine at L51359.
;
; Deal with any objects from the room item table at L26512 that are present in
; the room. These are 'non-scenery' objects that Maroc or the servant can
; interact with.
;
; This routine determines if an item is stationary (sitting on the floor of the
; room), carried by the servant, or falling/flying after being dropped by the
; servant.
L51968:
  LD HL,(60228)           ; Get item's data pointer for the room item table at
                          ; L29551
  CALL L56959             ; Check room object table at L29551 to see if any
                          ; items are in this room. If so, copy the item data
                          ; into working buffer at 60293.
  LD A,(60304)            ; For visible room objects, this is the graphic
                          ; number (offset for address table at L38851)
  CP 124                  ; Byte value 124 = the object is not visible
  JR Z,L51968_0           ; (yet),e.g. a key inside a chest
; Object is visible on screen - get object's colour
  LD A,(60299)            ; Get the colour attribute of the object
  AND 15                  ; Keep the INK colour (0-7), and bit 3, which is set
                          ; for objects that flash (change colour)
  LD (60072),A            ; ...and store
; Check if item is being carried by the servant
L51968_0:
  LD A,(60238)            ; Item properties byte
  LD C,A                  ; Temp store in C register
  AND 16                  ; Check if this item is carried by the servant - bit
                          ; 4 (16) set
  JR NZ,L51968_1          ; If so, check/calculate item position based on
                          ; servant's X/Y co-ordinates
; Item is not being carried by the servant
  LD A,C                  ; Retrieve item properties byte
  AND 8                   ; If bit 3 is set, this item is moving/falling (e.g.
                          ; after being thrown/dropped by the servant)
  JR NZ,L52059            ; Item is moving/falling - jump out to L52059
  JP L52136               ; Item is stationary - jump out to L52136
; Item is currently held by the servant
L51968_1:
  LD A,(60140)            ; Get active spell number
  CP 1                    ; Check is the servant spell still active?
  JR NZ,L52044            ; If not, servant spell has just been deactivated, so
                          ; the item is now falling/flying
  CALL L56008             ; If active, run routine calculating/checking item's
                          ; vertical position on screen. Adjusted vertical
                          ; boundary returned in E register ready for room
                          ; boundary check at 52031
; Servant is carrying the object, so use the servant's horizontal/vertical
; speed to calculate that of the object (multiplied x4 as servant speed is
; stored on a smaller scale):
  LD A,(60161)            ; Get servant's horizontal movement rate/offset
  ADD A,A                 ; Multiply by 4
  ADD A,A                 ;
  LD (60236),A            ; ...and store as item's horizontal movement
                          ; rate/offset
  LD A,(60162)            ; Get servant's vertical movement rate/offset
  ADD A,A                 ; Multiply by 4
  ADD A,A                 ;
  LD (60237),A            ; ...and store as item's vertical movement
                          ; rate/offset
  CALL L57401             ; Check room boundary and adjust item's position
  LD A,(60337)            ; accordingly
  CP 2                    ; This carried object status byte was set to 2 once
                          ; an item has been retrieved from Maroc's backpack by
                          ; the servant
  JR Z,L52118             ; If this is the case, do a collision check to
                          ; identify if the servant has moved outside Maroc's
                          ; backpack area 'hit box' (to prevent auto-cycling
                          ; through inventory objects). If so, change the byte
                          ; value (60337) to 1
  JP L52263

; Servant has dropped a held item
;
; Used by the routine at L51968.
;
; Jump here from 52010 if the servant spell is deactivated while holding an
; item
L52044:
  LD A,(60238)            ; Item properties byte
  OR 12                   ; Set bits 2 (4) - indicating item will need erasing
                          ; (as it's moving) - and 3 (8) - indicating that the
                          ; item is flying/falling
  AND 239                 ; Reset bit 4 - indicates item is no longer held by
  LD (60238),A            ; the servant
  LD A,0                  ; Finally, reset the flag indicating that the servant
  LD (60337),A            ; is carrying an object

; Handle interactable objects that are falling/flying
;
; Used by the routine at L51968.
;
; Follows from previous routine or jump from 52000 if bit 3 (8) of item byte at
; 60238 is set (item is moving/falling after being dropped).
L52059:
  CALL L56008             ; Check that the servant isn't dragging a held object
                          ; below the bottom of the room boundary, adjusting
                          ; co-ordinates accordingly
  CALL L57401             ; Other wall/room boundary checks, including
                          ; horizontal wall checks
; The next routine handles the item's vertical movement speed/momentum. When
; objects are dropped, they will fall a certain distance that depends on the
; item's screen height/position:
  LD A,(60237)            ; Vertical movement speed/offset in pixels (negative
                          ; = up, positive = down)
  ADD A,12                ; Adjust vertical movement rate slightly - 12 pixels
  LD (60237),A            ; gives a bit of momentum to the object to create a
                          ; semblence of gravity when the servant is throwing
                          ; or dropping an object - this increase means
                          ; vertical speed will increase if the item is
                          ; falling, and decrease if it is rising (after being
                          ; 'thrown' upwards by the servant).
  CP 128                  ; >=128 = negative value
  JR NC,L52136            ; If no carry (>=128) item is moving upwards
; Item is falling (moving downwards). Check it doesn't move off the bottom of
; the playing area, and stop it if it is.
  SRA A                   ; Halve the downward momentum (adjusted earlier by
                          ; adding 12, so halving here will increment the value
                          ; in steps of 6)
  LD C,A                  ; Temp store in C register
  LD A,(60234)            ; Graphic vertical pixel position from top of playing
  LD D,A                  ; area
  LD A,96                 ; Pixel line 96 is the bottom of the playing area
                          ; when the room viewport is in its default position
  LD HL,60150             ; Address holding the vertical pixel position of the
                          ; current room viewport
  INC HL                  ; Advance to the next address as it's the high byte
                          ; that contains the vertical pixel value
  ADD A,(HL)              ; Adjust the bottom-of-screen boundary based on the
                          ; current room position/viewport
  SUB D                   ; Subtract the item vertical position
  CP 96                   ;
  JR NC,L52059_0          ; If there's no carry, the item is falling off the
                          ; bottom of the screen
; Item isn't falling off the bottom of the screen. Check if the item has fallen
; far enough to rest on the room floor.
  CP C                    ; C contains the falling item's incremental vertical
                          ; momentum (6, 12, 18, 24 etc.). Once this surpasses
                          ; the adjusted vertical screen pixel position, the
                          ; object stops. The effect of this calculation means
                          ; the object will fall further the higher up the
                          ; screen it is. This reinforces the 3D illusion,
                          ; where the lower part of the room (the floor area)
                          ; is presented at an angle, compared to the back
                          ; wall, which is presented face on.
  JR NC,L52136            ; No carry = jump out here - the object can continue
                          ; to fall
; Item is falling off the bottom of the screen, or has fallen far enough in the
; room - need to stop it moving so it's now at rest.
L52059_0:
  LD A,(60238)
  AND 247                 ; Reset bit 3 (8) of the item properties byte to
  LD (60238),A            ; indicate this item is no longer falling/moving
  LD A,0                  ;
  LD (60237),A            ; Set the item's vertical speed to zero
  LD (60236),A            ; Set the item's horizontal speed to zero
  JP L52263               ;

; Check if servant has moved away from Maroc after retrieving an item
;
; Used by the routine at L51968.
;
; When the servant retrieves objects from Maroc's backpack, the byte at 60337
; is set to 2. Once it's moved out of the backpack area, this is set to the
; 'standard' value of 1 which indicates the servant is carrying an object.
;
; This stops the item collection cycle quickly cycling through all of Maroc's
; items if the servant hovers over Maroc's backpack.
L52118:
  LD C,0                  ; Type of collision/event check (collision with
                          ; Maroc)
  CALL L57293             ; Run collision check
  CP 0                    ; Is there a collision (A register returned = 1)?
  JP NZ,L52263            ; If so, servant is still within Maroc's backpack
                          ; 'hit box' after collecting the object - take no
                          ; action and jump to the next routine
  LD A,1                  ; Servant has moved out of Maroc's backpack area
                          ; after picking up an object
  LD (60337),A            ; Set servant object status to 1 to indicate that the
                          ; servant is now carrying an object - OK to swap
                          ; object again now if it moves back.
  JP L52263

; Determine movement of room items/creatures that move around the screen
;
; Used by the routines at L51968 and L52059.
;
; Not defined in the room creature table (L27532), but there are certain room
; items defined in the room object item sets at L29551 that can move around the
; screen, for example:
; * Mouse (which Maroc can pick up)
; * Animated sabre (also collectable)
; * Spiders
; * Bats
; * Scorpions
;
; This routine determines if the item/creature in the room item set can move
; around the screen.
;
; If so, it determines its movement using the movement pattern byte stored at
; 60301. Some creatures home in on Maroc, others move more haphazardly.
L52136:
  LD A,(60301)            ; First byte from object state data set
  AND 7                   ; Keep bits 0-2
  LD C,A                  ; Store in C register
  CP 0                    ; Does this item move (any of bits 0-2 are set)?
  JP Z,L52263             ; If not, skip the next section
; This item moves:
  LD A,(60238)            ; Get the item properties byte
  AND 253                 ; Reset bit 2 to indicate that this item is not
                          ; hidden - e.g. it might be a scorpion released from
                          ; a bottle, or the mouse appearing from the mouse
                          ; hole
  LD (60238),A            ; ...and re-store
  LD A,(L60074)           ; Get game counter/timer
  AND 31                  ; Keep bits 0-4 (values 0-31)
  JP Z,L52136_2           ; To stop the item/creature's movement/speed getting
                          ; out of hand, every 32nd frame, stop the
                          ; creature/item by jumping out here and setting its
                          ; vertical & horizontal movement speed to zero.
  CP 7                    ; Check if counter is < 7
  JR C,L52136_1           ; If so, jump out (overall this will be around 1 in 4
                          ; times) - don't adjust this creature's current
                          ; direction/speed/trajectory
; Game counter between 7 and 31 (will be ~3 times in every 4)
  LD A,C                  ; Graphic movement data for graphics from C register
                          ; (60301)
  AND 1                   ; Check bit 1 - if set, this indicates that the
                          ; creature has a random element to its movement
  JR Z,L52136_0           ; If not set, skip the next routine, which randomly
                          ; adjusts the creature's speed/direction
; CREATURES WITH A RANDOM ELEMENT TO THEIR MOVEMENT - randomly adjust this
; item's vertical and horizontal movement speed
  CALL L56070             ; Generate pseudo-random number
  LD B,A                  ; Temp store in B register
  AND 15                  ; Keep bits 0-3 (values 0-15)
  SUB 7                   ; Subtract 7
  LD D,A                  ; Store in D register - will be a number between -7
                          ; and +8
  LD A,(60236)            ; Item's horizontal movement speed
  ADD A,D                 ; Add (or subtract if negative) the random value to
                          ; current speed
  LD (60236),A            ; ...and re-store altered horizontal movement speed
  LD A,B                  ; Retrieve pseudo-random number
  RRA                     ;
  RRA                     ;
  RRA                     ; Divide by 8
  AND 15                  ; Keep bits 0-3 (values 0-15)
  SUB 7                   ; Subtract 7
  LD D,A                  ; Store in D register - will be a number between -7
                          ; and +8
  LD A,(60237)            ; Item's vertical movement speed
  ADD A,D                 ; Add (or subtract if negative) the random value to
                          ; current speed
  LD (60237),A            ; ...and re-store altered horizontal movement speed
; Bit 1 (2) of the item's movement pattern byte indicates whether this
; creature/item will home in on Maroc.
L52136_0:
  LD A,C                  ; Retrieve movement pattern byte from C register
  AND 2                   ; Check bit 1 (2)
  JR Z,L52136_1           ; If set, this item/creature will try to home in on
                          ; Maroc's position. If not (e.g. the mouse) skip the
                          ; next set of instructions.
; CREATURES THAT HOME IN ON MAROC'S POSITION:
;
; Calculate HORIZONTAL movement direction
  LD A,(60232)            ; Get the creature/item's horizontal position
  LD C,A                  ;
  LD A,(60096)            ; Maroc's horizontal screen position
  SUB C                   ; Subtract the item's horizontal position
  RLA                     ; Rotating the bits left...
  SBC A,A                 ; ...and then using sub with carry will result in 0
                          ; or 255 (-1) - this indicates whether the difference
                          ; is positive (Maroc is to the right) or negative
                          ; (Maroc is to the left)
  XOR 7                   ; This XOR subsequently produces a value of either +7
                          ; or -7
  LD (60236),A            ; ...Store this as the item/creature's horizontal
                          ; movement speed
; Calculate VERTICAL movement direction
  LD A,(60234)            ; Get the creature/item's vertical position
  LD C,A                  ;
  LD A,(60097)            ; Maroc's vertical (Y-axis) screen position
  SUB C                   ; Subtract the item's vertical position
  RLA                     ; Rotating the bits left...
  SBC A,A                 ; ...and then using sub with carry will result in 0
                          ; or 255 (-1) - this indicates whether the difference
                          ; is positive (Maroc is below the creature/item) or
                          ; negative (Maroc is above the creature/item)
  XOR 7                   ; This XOR subsequently produces a value of either +7
                          ; or -7
  LD (60237),A            ; ...Store this as the item/creature's vertical
                          ; movement speed
; Check if item/creature is within wall boundaries (room wall collision check)
; * If bit 2 (4) of the movement pattern byte is NOT set, run a standard room
;   boundary collision check
; * If this bit IS set, skip the check. This is to allow certain room creature
;   'items' - mainly BATS - to move above into the areas above the normal back
;   and side wall boundaries.
L52136_1:
  LD A,(60301)            ; Retrieve movement pattern byte
  AND 4                   ; Check if bit 2 is set
  JR NZ,L52263            ; If so, skip to the next routine
  LD A,(60234)            ; Graphic vertical position in room
  LD E,A                  ;
  CALL L57401             ; Run the standard wall collision check, which keeps
  JR L52263               ; the creature/item within the room's boundary
; Jump from 52160 every 32nd game cycle. To reduce overly-erratic movement of
; creatures or items, this routine stops the item/creature moving. It also
; makes creature movement looks slightly more natural as they pause their
; movement occasionally.
L52136_2:
  LD A,0                  ; Set the item/creature's vertical and horizontal
  LD (60237),A            ; movement speed to zero
  LD (60236),A            ;

; Check and change object state after positive events match/collision
;
; Used by the routines at L51968, L52059, L52118 and L52136.
;
; 'Interactions' in Avalon are based on matching event values. For example:
; * using a (particular) key on a (particular) chest
; * using a spell on a room object, e.g. OPEN/UNLOCK
; * using an object on another object (e.g. flashing star on the floor marking
;   in room 2)
;
; Items that can be affected by other actions/items have extra data in the room
; item table (L29551). This additional data indicates the next 'state' of the
; item (e.g. closed chest > open chest)
;
; Some items are hidden until another item is used (in the aforementioned case
; of chests holding objects).
;
; A successful value match between the acting item, and the item acted upon,
; advances the state of the object to the next one.
L52263:
  LD A,(60303)            ; Event number ID to check for this item (acting on
  CP 0                    ; another item, e.g. a key opening its corresponding
                          ; chest)
  JR Z,L52263_0           ; If zero, there's nothing to check
  CP 137                  ;
  JP Z,L55944             ; Special check for event/collision #137 - Maroc
                          ; using CALIBURN on AVELACH. This ends the game.
  CALL L58032             ; Copy room item event data into working buffer
; Event/collision checking:
L52263_0:
  LD A,(60302)            ; Event number for items acting on this item (e.g.
  LD C,A                  ; for a chest, which is opened by a key)
  CP 15                   ; Event 15 means an item is collectible (Maroc can
                          ; pick it up)
  JP Z,L52338             ; If so, check if Maroc has picked up the item,
                          ; either by moving over it or given it by the servant
  CALL L57293             ; For all other events, run an event check for this
                          ; item
  CP 1                    ; Has a collision/event occurred?
  JP NZ,L52338            ; If not, skip to the next routine
; EVENT/COLLISION HAS TAKEN PLACE
;
; For the object acted upon, advance its 'state' by one, to the next state:
  LD A,(60300)            ; Grab the byte containing the number of 'states' for
  LD C,A                  ; the object
  LD A,(60297)            ; Current object state number (starts at 1 for
                          ; default object state)
  INC A                   ; Increment object state by one
  CP C                    ;
  JR C,L52263_1           ;
  JR Z,L52263_1           ; Object state <= max states for this item, skip the
                          ; next instruction
  LD A,1                  ; Object state > max states for this item, so reset
                          ; the object state to 1
L52263_1:
  LD HL,(60228)           ; Address pointer to start of item's data set at
  INC HL                  ; L29551
  INC HL                  ;
  INC HL                  ;
  INC HL                  ; Move to the 5th byte of set, containing the item's
                          ; state number
  LD (HL),A               ; ...and store the new state number.
  CALL L56028             ; Fetch object state and prepare graphics for
                          ; printing
; Set properties for the new object state
  LD A,(60301)            ; Get first byte of object state data
  AND 248                 ; Filter out bits 0-2 (values 0-7)
  LD C,A                  ;
  LD A,(60238)            ; Get the current item properties byte
  AND 31                  ; Keep bits 0-4...
  OR 5                    ; Set bits 0 (item is visible) and 2 (item is
                          ; moving/will need erasing)
  OR C                    ; ...append the rest of the bits from the
                          ; new-state-object...
  LD (60238),A            ; ...and re-store.

; Check if Maroc has picked up (or been given) a spell or item
;
; Used by the routine at L52263.
;
; Jump from 52284 (objects with state value = 15 = 'collectable'), or follow on
; from previous instructions.
;
; Check if Maroc has picked up this item (or given it by servant).
; "Acted-upon-item" event byte value at 60302 = 15 = object collection by
; Maroc.
L52338:
  LD A,(60238)            ; Get item properties byte
  LD C,A                  ;
  AND 16                  ; Is the item carried by the servant (bit 4 set)?
  JR Z,L52338_0           ;
  LD A,(60337)            ; If so, check if the servant is currently carrying
  CP 1                    ; an object
  JP NZ,L52582_0          ; If not, jump to the next routine to check for
                          ; servant based pick-ups/interactions
L52338_0:
  LD A,C                  ; Get item properties byte
  AND 64                  ; Bit 6 (64) = the item is collectable (e.g.
                          ; inventory object, spell)
  JP Z,L52582_0           ; If it isn't, skip to next routine for servant
                          ; interactions
  LD C,0                  ; Collision type to check = 0 (collision with Maroc)
  CALL L57293             ; Check for Maroc related events/collisions to see if
  CP 0                    ; Maroc is collecting the object
  JP Z,L52513             ; Jump to L52513 if no events/collisions
; Maroc has picked up or been given a spell or item
  LD A,(60238)            ; Item properties byte
  OR 5                    ; Set bits 0 (item is visible) and 2 (item will need
                          ; to be erased before re-drawing)
  LD (60238),A            ; ...and re-store
  CALL L58878             ; Trigger pick-up sound effect
  LD A,(60298)            ; Get item spell number
  CP 0                    ; If it's 0, it's not a spell, so skip the following
  JR Z,L52445             ; "spell collected" routine
; The next two instructions send any spell number over 224 is sent down the
; 'item' (rather than spell) route here. These may be special sorts of item
; originally been designed to restore or drain energy (e.g. food).
;
; However, no spell number value gets anywhere near number 224. A later check
; remains in the code (at L52445), but will never occur. It's likely that this
; is a remnant of old code before game design relating to restorative/draining
; objects was changed.
  CP 224                  ; -
  JR NC,L52445            ; -

; Maroc has picked up a spell
;
; A Spell number (from list at L28156)
;
; Maroc has collected a spell. Collected spells come with a random number of
; charges (between 3 and 10).
L52392:
  LD C,A                  ; Temp store for spell number in C register
  LD A,(60238)            ; Get item properties byte
  AND 16                  ; Is the item carried by the servant (i.e. the
  JR Z,L52392_0           ; servant has picked up the spell and moved onto
  LD A,0                  ; Maroc, rather than Maroc moving over the spell
                          ; item)?
  LD (60337),A            ; ...If not, set the item-carried-by-servant byte to
                          ; 0
; Mark this spell as 'acquired' by setting the first byte in its spell set to
; 16:
L52392_0:
  LD A,C                  ; Retrieve spell number
  LD HL,(60261)           ; Address pointer to start of spell list at L28156
  LD D,0                  ;
  LD E,A                  ; Store spell number in DE register pair...
  EX DE,HL                ; ...Swap into HL register pair. Each spell set
                          ; contains 16 bytes, so...
  ADD HL,HL               ; x 2
  ADD HL,HL               ; x 4
  ADD HL,HL               ; x 8
  ADD HL,HL               ; x 16
  ADD HL,DE               ; Add to the base spell list address (L28156) so HL
                          ; is now pointing at the start of the set for this
                          ; spell
  LD (HL),16              ; Set the first byte of the set to 16, which
                          ; indicates that Maroc has collected this spell
; Collected spells come with a variable number of charges. New spells will
; start with between 3 and 10 charges. Collecting additional spells of the same
; type will add 3-10 charges to the existing ones.
  LD A,(L60074)           ; Incrementing game cycle counter (used here to
                          ; generate a pseudo-random number)
  AND 7                   ; Keep bits 0-2. This provides a random value between
                          ; 0-7
  ADD A,3                 ; Add 3 to give a value between 3-10
  LD B,A                  ; Store in B register
  INC HL                  ;
  INC HL                  ;
  INC HL                  ; Move along 3 positions to byte 4 of the set, which
  LD A,(HL)               ; indicates how many charges are left for this spell
  CP 255                  ;
  JR Z,L52392_1           ; Value of 255 means unlimited charges, so skip next
                          ; two instructions if so.
  ADD A,B                 ; Add the spell's charges to the current number..
  LD (HL),A               ; ...and re-store the amended count.
; After collecting a spell, 'MAGIC' (in the bottom left of the screen) flashes
; colour and a sound is played 15 times (L54065).
L52392_1:
  LD A,15
  LD (60576),A            ; Initialize this counter value to 15
  JR L52445_2             ;

; Maroc has picked up an item
;
; Used by the routine at L52338.
;
; There are 4 inventory slots in Maroc's backpack (32626). However, he can only
; carry 3 objects.
;
; The 4th consecutive slot is used as an 'overflow' slot. This is checked later
; at L55564. If there's an object in it, Maroc will immediately drop it. So
; Maroc can actually - but (very) temporarily - carry 4 objects.
;
; Add the collected object to Maroc's inventory:
L52445:
  LD HL,(60348)           ; Address pointer to current slot of Maroc's
  LD A,(HL)               ; inventory at 32626
  CP 0                    ; Empty inventory slot?
  JP NZ,L52582_0          ; If the slot isn't empty, it may be that the servant
                          ; has moved the object over Maroc's backpack (rather
                          ; than Maroc picking it up himself). If so, and the
                          ; servant moves slowly enough, it can swap the
                          ; carried object with the next one in the inventory -
                          ; so go and check if this is the case.
; Empty inventory slot has been found:
  LD A,(60238)            ; Get the item properties byte
  LD C,A                  ;
  AND 16                  ; Is the item being carried by the servant (if bit 4
                          ; is set)?
  JR Z,L52445_0           ; If not, skip next few instructions
; The servant has just put the item in Maroc's backpack. Set item status to
; 'not carried by servant'
  LD A,C                  ; Retrieve item properties byte
  AND 239                 ; Object is now in Maroc's backpack, so reset bit 4
                          ; of its properties byte, as it's no longer carried
                          ; by the servant.
  LD (60238),A            ; ...and re-store the item properties byte
  LD A,0                  ;
  LD (60337),A            ; Set the 'servant-carrying-item' flag to zero
; Copy 16 bytes of the item's data from the working buffer at L60227 into the
; inventory slot (at 32626). Then move the inventory address pointer to the
; next available slot.
;
; Next time the servant moves over Maroc's backpack, it will retrieve the next
; consecutive object.
L52445_0:
  EX DE,HL                ; Swap inventory address pointer into DE register
                          ; pair
  LD HL,L60227            ; Start of item working data buffer
  LD BC,16                ;
  LDIR                    ; Copy 16 bytes of item data into inventory slot
  EX DE,HL                ; HL register pair is now pointing to the start of
  LD A,(HL)               ; the next inventory slot
  CP 255                  ; Are we at the end of the 4 inventory slots?
  JR NZ,L52445_1          ;
  LD HL,(L60346)          ; If so, switch the inventory pointer back to
                          ; inventory slot 1
L52445_1:
  LD (60348),HL           ; Store inventory slot pointer
; The next few instructions check if the spell number is >=224. If so a value
; (240) is subtracted, which sets the amount to increase/decrease Maroc's
; energy by (from -16 to +15).
;
; No object/spell number is close to this value. It's likely that it was added
; for the collection of energy giving/reducing items (e.g. food), but not used
; in favour of the other better energy routines.
  LD A,(60298)            ; Get the spell number (normally will be 0 for
  CP 224                  ; objects)
  JR C,L52445_2           ;
  SUB 240                 ; If >=224, subtract 240 (would give a value of -16
                          ; to +15)...
  CALL L58316             ; ...and increase/decrease Maroc's energy accordingly
; This object has now been collected:
L52445_2:
  LD A,0
  LD (L60227),A           ; Set it's object type to 0, as it's in Maroc's
  JR L52582_0             ; inventory and no longer in the room

; Check for an object trade with warlock
;
; Used by the routine at L52338.
;
; First, check to see if any object has been traded (using the servant) with a
; warlock:
L52513:
  LD A,(L60333)           ; Warlock 'aggression' byte - byte 6 of the warlock
  CP 0                    ; data sets at L27772.
  JR Z,L52582             ; If zero, this means there's no warlock on-screen,
                          ; so skip this check
  LD C,A                  ; Temp store this byte in C register, as it's used in
                          ; the upcoming CALL as the event value to check for a
                          ; trade
  LD A,(60334)            ; Object number held by warlock
  CP 0                    ;
  JR NZ,L52582_0          ; If not zero, an object has (already) just been
                          ; given to the warlock, so needs to be dealt with -
                          ; skip this routine
  CALL L57293             ; Run an event/collision check against this warlock
                          ; (for trading an object)
  CP 0                    ; A register returned with 1 = collision, or 0 = no
                          ; collision
  JR Z,L52582             ; If negative, skip to the next routine
; Object trade made with warlock - mark the item as no longer present:
  LD A,(60230)            ; Get object number (relates to room object table at
                          ; L29551)
  LD (60334),A            ; Copy to working data buffer
  LD A,0                  ;
  LD (L60227),A           ; Change the object's type to 0 in the working
  LD A,(60299)            ; buffer, indicating it's no longer around in the
                          ; room
  LD (60335),A            ; Copy attribute colour of object to working data
                          ; buffer
  LD A,(60238)            ; Item properties byte
  LD C,A                  ; Temp store in C register
  OR %00001101            ; Set bits 0 (item is visible), 2 (item will need
                          ; erasing) and 3 (item has been thrown/dropped by
                          ; servant)
  AND %11101101           ; Reset bit 1 (item is hidden) and bit 4 (to indicate
                          ; object no longer carried by servant)
  LD (60238),A            ; Re-store updated object byte
  LD HL,(60228)           ; Move the properties byte to byte 4 of the object
  INC HL                  ; data set at L29551 (objects held by warlocks are at
  INC HL                  ; the start of this table)
  INC HL                  ;
  LD (HL),A               ; Store the updated item property in byte 4 of the
                          ; set
  LD A,C                  ; Retrieve item properties byte (pre-modification)
  AND 16                  ; Check bit 4 (16) - if set, indicates object carried
  JR Z,L52582_0           ; by servant. Normally this will be set, but it is
                          ; possible for the servant to 'throw' the item to the
                          ; warlock
  LD A,0                  ; If the item was carried by the servant...
  LD (60337),A            ; ...Set the item-carried-by-servant status byte to 0
  JR L52582_0             ;
; There's a later check made (at L52849) to determine if a traded item is
; valuable enough to be worthy of a trade with each warlock.

; Check for servant picking up an object
;
; Used by the routine at L52513.
;
; Check if the servant is picking up an object - either:
; * picking up an item in the room, or
; * retrieving an item from Maroc's backpack
L52582:
  LD A,(60337)            ; Servant-object-carrying status
  CP 0                    ; 0 = servant is not carrying an object
  JR NZ,L52582_0          ; Jump out here if the servant IS carrying an object,
                          ; as it can't carry more than one
  LD C,5                  ; Collision event value to check = 5 (servant picking
                          ; up object)
  CALL L57293             ; Run event/collision check
  CP 0                    ; A register returned with 0 (no collision) or 1
                          ; (collision detected)
  JR Z,L52582_0           ; Jump out here if no event match/collision
; Servant has picked up an object:
  LD A,1                  ; Set servant object-carrying status to 1 (servant is
  LD (60337),A            ; carrying an object)
  LD A,(60238)            ; Item properties byte
  AND %11110101           ; Reset:
                          ; * bit 1 - item is NOT hidden
                          ; * bit 3 - item is NOT falling/flying, as servant
                          ;   now holds it
  OR %00010101            ; Set:
                          ; * bit 0 - item is visible
                          ; * bit 2 - item graphic will need erasing
                          ; * bit 4 - item is being carried by the servant
  LD (60238),A            ; ...and re-store.
; This entry point is used by the routines at L52338, L52445 and L52513.
L52582_0:
  JP L53885               ; Includes jumps to here from earlier routines

; Deal with creature in room - create footstep sounds and check for missile
; collisions
;
; Used by the routine at L51359.
;
; Play/trigger sounds for creature footsteps and check if any creatures are
; being destroyed by Maroc's spells or servant-wielded weapons.
;
; Trigger footstep sound effect (for certain creatures):
L52616:
  LD A,(60572)            ; Check FREEZE spell timer counter
  CP 0                    ;
  JR NZ,L52616_0          ; If it's > 0, the FREEZE spell is still in place so
                          ; skip the footsteps check
; Create short intervals between footsteps
  LD A,(L60074)           ; Game timer
  AND 3                   ; Check if either bit 0 or 1 are set
  JR NZ,L52616_0          ; If so, skip the footstep sounds (this creates a
                          ; short interval in the sound, to mimic a footstep
                          ; effect)
; Check creature type (60230). Prepare footstep sound effects for Guardian of
; Chaos (creature type = 8), goblin warrior (9), and goblin missile thrower
; (10).
;
; Warlocks (1-7), wraiths (11) and demons (12) make no sound when they move.
  LD A,(60230)            ; Check creature type number
  CP 8                    ;
  JR C,L52616_0           ; Creature number < 8 - warlock
  CP 11                   ;
  JR NC,L52616_0          ; Creature number >= 11 - a wraith or a demon
  LD A,16                 ; If the creature type is 8, 9, or 10, set the byte
  LD (60246),A            ; at 60246 to start with the speaker bit on (bit 4).
; Copy the 8 bytes of data for this creature type at L27772/27828 into working
; creature data buffer at L60325, along with a couple of other bytes:
L52616_0:
  LD HL,(60228)           ; Pointer to data set at L27772/27828
  LD BC,8                 ; Copy 8 bytes to creature data buffer at L60325
  LD DE,L60325            ;
  LDIR                    ;
  LD A,(L60325)           ; Creature attribute/colour byte - first byte of
                          ; current creature set at 27828
  LD (60072),A            ; Copy into room item working data buffer
; Check if any creatures have been destroyed (e.g. by a missile fired by Maroc)
  LD A,(60238)            ; Item (creature) properties byte
  LD C,A                  ; Temp store in C register
  AND 224                 ; Check top 3 bits (bits 5-7) If any of these are
                          ; set, it means the creature is disintegrating or
                          ; materializing
  JP NZ,L53145            ; If so, don't run any more checks for this creature
                          ; - skip out of this routine
  LD A,C                  ; Retrieve item/creature properties byte
  AND 1                   ; Check bit 0 - if set, it means the creature is
                          ; on-screen/visible
  JR Z,L52695             ; Skip the next instructions if creature isn't
                          ; visible on-screen as creatures need to be on-screen
                          ; to be destroyed by missiles etc.
; Run collision checks for Maroc's spells vs creatures
  LD A,(60329)            ; Collision/event check type (wraiths/demons = 7,
                          ; other creatures = 3) This indicates which spells or
                          ; weapons can destroy these sorts of creature For
                          ; warlocks this is a value matching the missile/bolt
                          ; type that destroys them (from byte 5 in the warlock
                          ; table at L27772)
  LD C,A                  ; Store in C register, which is used as the event
                          ; value to check in the following CALL
  CALL L57293             ; Check if Maroc has destroyed a creature with a
                          ; missile/bolt or wraithbane
  CP 0                    ; The A register is returned with 0 (no collision) or
                          ; 1 (positive collision detected)
  JP NZ,L53372            ; Positive collision (flag = 1), e.g. a wraith
                          ; touching Maroc while WRAITHBANE is active, or a
                          ; missile hitting a creature that it destroys - so
                          ; destroy the creature.
  LD A,(60330)            ; Otherwise get event/collision value for for
                          ; creatures opening/closing doors (17)
  CALL L58032             ; ...and add this to the collision/event set in the
                          ; table at 32691 ready for checking next game cycle

; Change creature behaviour based on Maroc's magic
;
; Used by the routine at L52616.
;
; The different creatures in Avalon have their own distinct movement patterns.
; For example, wraiths will occasionally dart towards or away from Maroc.
; Goblin missile throwers stop in one place and fire missiles at Maroc from a
; distance.
;
; Movement patterns are affected by Maroc's active spells (particularly UNSEEN
; and FREEZE), at different intervals using the game cycle timer/counter stored
; at L60074.
L52695:
  LD A,(60230)            ; Creature type
  CP 8                    ; Guardian of Chaos
  JP Z,L53003             ;
  JP C,L52849             ; If creature type < 8 then it's a warlock, If so,
                          ; skip this routine as they have a different movement
                          ; pattern to other creatures
  CP 11                   ; Wraith
  JR Z,L52695_1           ;
  CP 9                    ; Goblin warrior
  JP Z,L53054             ;
  CP 12                   ; Demon
  JP Z,L52695_1           ;
; Goblin missile thrower (creature type #10)
;
; Goblin missile throwers won't fire any missiles at Maroc if UNSEEN or FREEZE
; spell is active
  LD A,(60238)            ; Creature properties byte
  AND 1                   ;
  JP Z,L53003             ; If creature is off screen, check if its movement
                          ; needs to be changed due to the UNSEEN spell being
                          ; active
  LD A,(60240)            ; Creature is on-screen. Get graphic frame number
                          ; offset
  AND 7                   ; Keep bits 0-2
  CP 3                    ; Is the graphic frame #3?
  JR NZ,L52695_0          ; If not, jump to the next section to determine the
                          ; creature's movement
; If the creature has reached frame 3, it can fire a missile (as long as FREEZE
; or UNSEEN aren't active)
  LD A,(60137)            ; Currently active spell
  CP 9                    ; Check if the UNSEEN spell is active
  JR Z,L52695_0           ; Jump to L52695_0 if UNSEEN is active
  LD A,(60572)            ; Check FREEZE spell timer counter
  CP 0                    ;
  JR NZ,L52695_0          ; If counter is > 0, FREEZE spell is active - jump to
                          ; L52695_0
  JP L53080               ; Neither FREEZE or UNSEEN is active so initialize a
                          ; missile
; UNSEEN or FREEZE spell is active
L52695_0:
  LD A,(L60074)           ; Game cycle counter
  AND 15                  ; Check bits 0-3
  JP Z,L53003             ; Every 16th game cycle check the UNSEEN spell and
  CP 12                   ; alter the creature's movement accordingly
  JR Z,L52695_2           ; On each game cycle #12 (of 16) randomize the
  CP 0                    ; creature's movement
  JP NZ,L53323            ;
  LD A,0                  ; On every 16th game cycle, stop moving:
  LD (60236),A            ; Set horizontal movement speed/direction to zero
  LD (60237),A            ; Set vertical movement speed/direction to zero
  JP L53323               ;
; Jump here from L52695 if creature type is WRAITH or DEMON.
;
; These two creatures can 'sniff out' powerful magic.
; * If Maroc has UNSEEN active, they are able to home in on his position,
;   making them potentially more dangerous, though DEMONs will not fire
;   missiles which tend to be more difficult to avoid
; * They will also move towards Maroc's screen position if he casts ANY
;   'powerful' spell (i.e. spell number >=4)
L52695_1:
  LD A,(60140)            ; Get activated spell
  CP 4                    ; If spell number >=4, jump to L53003_0
  JP NC,L53003_0          ;
  LD A,(60137)            ; Check for currently active effect spells
  CP 9                    ;
  JP Z,L53003_0           ; If UNSEEN spell is active, jump to L53003_0
  LD A,(L60074)           ; Game cycle counter
  AND 31                  ; Check if any bits 0-4 set
  CP 0                    ;
  JR NZ,L52695_3          ; If not, skip the next two sets of instructions
; Every 32 game cycles
; * Wraiths will change their movement direction
; * Demons will fire a missile at Maroc
  LD A,(60230)            ; Check if creature is type number #12 (demon)
  CP 12                   ;
  JP Z,L53080             ; If so, go and initialize a missile/bolt Otherwise
                          ; it's a wraith, so continue to the next instructions
                          ; to randomize its movement
; Randomize creature movement
;
; Changes movement speeds/directions for:
; * Goblin warrior if Maroc has cast a powerful spell (L53054)
; * Goblin missile thrower, every 16 game cycles
; * Guardian of Chaos if the UNSEEN spell is active L53003
; * Wraith, every 32 game cycles
L52695_2:
  CALL L56070             ; Generate pseudo-random number
  LD C,A                  ; Temp store in C register
  AND 15                  ; Only need bits 0-3 (values 0-15)
  SUB 7                   ; Subtract 7, so values between -7 and +8
  ADD A,A                 ;
  ADD A,A                 ; Multiply by 4, so values now between -28 and +32
                          ; (in multiples of 4)
  LD (60236),A            ; Store as creature's horizontal speed (negative
                          ; numbers = left, positive = right)
  LD A,C                  ; Retrieve stored pseudo-random number
  RRA                     ;
  RRA                     ; Divide by 4 (creates a different number from the
                          ; previous one)
  AND 15                  ; Keep bits 0-3 (values 0-15)
  SUB 7                   ; Subtract 7, so values now between -7 and +8
  LD (60237),A            ; Store as creature's vertical speed (negative
  JP L53323               ; numbers = up, positive = down)
; WRAITH or DEMON movement - continued from 52805
L52695_3:
  AND 7                   ; (Game timer counter) - check bits 0-2
  JP NZ,L53323            ;
  JP L53003_0             ; Every 8 game cycles, re-calculate the creature's
                          ; homing trajectory based on Maroc's position

; Maroc is trading items with a warlock
;
; Used by the routine at L52695.
;
L52849:
  LD A,(60334)            ; Object number (if any) from table at L29551 that
                          ; has been offered to the warlock
  LD D,A                  ; Temp store in D register
  CP 0                    ;
  JR Z,L52948             ; If nothing has been offered, jump out to next
                          ; routine handling warlock missiles
; Maroc has offered an object to the warlock in a trade for the warlock's item.
; * If the item is of sufficient value (if bits 5-7 of the item's value byte >=
;   warlock number) the warlock will accept the trade
; * Otherwise it will fire a missile at Maroc
; * Higher value items are needed to successfully trade with more powerful
;   warlocks
;
; Alternatively Maroc can destroy the warlock to obtain its held object, if he
; has a powerful enough spell.
  LD A,(60230)            ; Warlock number (1-7) - table at L27772
  LD C,A                  ; Temp store in C register
  LD A,(60335)            ; Single byte containing both the object's
                          ; attribute/colour and its 'value'
  RRA                     ; The trade-based value of this object is stored in
  RRA                     ; bits 5-7
  RRA                     ;
  RRA                     ; ...now shifted to bits 0-2
  AND 7                   ; Keep a value between 0-7
  CP C                    ; Compare against warlock number. If it's greater,
                          ; it's accepted as a trade for their carried
                          ; object/spell
  JR C,L52913             ; Carry here means the item value isn't high enough,
                          ; so it's not accepted
; Item accepted by warlock - traded for carried item:
  LD A,(60328)            ; Number of item held by warlock (from table at
  LD (60334),A            ; L29551)
  LD A,D                  ; Retrieve the object number (from table at L29551)
                          ; that Maroc has offered
  LD (60328),A            ; ...and store in the warlock's working data buffer
  LD HL,(60228)           ; Address pointer to warlock data set in table at
  INC HL                  ; L27772
  INC HL                  ;
  INC HL                  ;
  LD (HL),A               ; ...and store this object number as the warlock's
                          ; held object
  LD A,(60238)            ; Get the warlock's properties byte
  AND %00001111           ; Filter out/clear bits 4-7
  OR %01000101            ; Set bit 6 (warlock ready for materialization
                          ; routine) and bits 0 & 2 (item is visible and
                          ; moving)
  LD (60238),A            ; ...and restore properties byte
  LD A,1                  ; Graphics frame offset (1 = no offset)
  LD (60240),A            ;
  LD A,91                 ; Graphics address for materialization graphics at
                          ; 39031
  CALL L57538             ; Set up graphics
  JP L53885               ;

; Maroc has offered an object of insufficient value to a warlock
;
; Used by the routine at L52849.
;
; If an item is not of interest to a warlock (checked in the routine at 52857):
; * the warlock fires a bolt/missile at Maroc (almost guaranteed to hit, as the
;   player will be controlling the servant, so Maroc will be stationary!)
; * the offered item is teleported to another room, namely [current room
;   number] + 3)
L52913:
  LD C,D                  ; Retrieve the object number (from table at L29551)
                          ; that Maroc has offered
  LD B,0                  ; The upcoming CALL performs one of two functions,
                          ; depending on whether the B or C register contains a
                          ; non-zero value. By setting the B register to zero,
                          ; it tells the routine that we want to get the item's
                          ; data using the object number (in the C register)
                          ; rather than the room number (B register).
  LD HL,(56051)           ; Address pointer to the start of the room object
  LD A,0                  ; data sets at L29551
  LD (60292),A            ; Set the data set counter to zero for the next CALL
  CALL L56908             ; This routine finds an object's data set (in table
                          ; at L29551), and copies its data into the object
                          ; data buffer at 60293.
; Teleport the rejected item to current-room-number-plus-three
  LD A,(60087)            ; Current room number
  LD C,A                  ;
  ADD A,3                 ; Add 3 to it
  LD HL,(L60290)          ; Get address pointer to the start of the item's data
                          ; set
  LD (HL),A               ; The first byte in the set is the item's room
  INC HL                  ; number, so stick the updated value (room number
                          ; plus 3) in here
  LD (HL),26              ; Sets the object horizontal position (in half-pixel
                          ; steps) in the room to a standard 26. This ensures
                          ; that the object will be within the new room
                          ; boundaries regardless of source & destination room
                          ; sizes. The item's final vertical position would've
                          ; been where the warlock was positioned on the room
                          ; wall, so the object's vertical position will
                          ; probably also be on the wall.
  LD A,0
  LD (60334),A            ; Set the object-number-held-by-warlock byte to 0, as
                          ; the offered item has just been teleported to a
                          ; different room
  JP L53080               ; ...Warlock isn't impressed with the item
                          ; offering...! Jump to the 'set up missile'
                          ; routine...

; Decide whether a warlock will fire a missile/bolt at Maroc
;
; Used by the routine at L52849.
;
; If Maroc tries to trade an item of insufficient value with a warlock
; (determined at L52913), the warlock will fire a missile/bolt at him.
;
; Additionally, every 32 game cycles, there's a random chance a warlock will
; fire a missile/bolt
;
; The 6th byte in the data sets at L27772 is an 'aggression' stat for the
; warlock. It affects the likelihood of the warlock firing at Maroc. The higher
; the number, the higher the frequency of missiles/bolts.
;
; The animated image below shows warlock #7, the warlock with the highest %
; chance of firing a bolt/missile, flinging frequent bolts at a stationary
; Maroc.
L52948:
  LD A,(60238)            ; Item (warlock) properties byte
  AND 1                   ; Check bit 0 (set if the warlock is visible
  JR NZ,L52948_0          ; on-screen)
; Warlock has gone off-screen
  LD A,0
  LD (L60227),A           ; Set type of graphic to draw to 0 (nothing to draw)
  LD A,144                ;
  LD (60340),A            ; Timer indicating how long before a warlock is
                          ; likely to materialize in the current room - set
                          ; this to 144
  LD (60341),A            ; Timer indicating how long before a creature is
                          ; likely to wander in from an adjacent room - also
                          ; set this for 144
  JP L53145_2             ; Skip out of this routine to deal with changes to
                          ; the warlock's data, as it's now off-screen
; NEXT 4 INSTRUCTIONS DON'T SEEM TO BE USED.
;
; It looks like a similar check to the goblin warrior at L53054, where Maroc
; wielding powerful magic has an effect on creature movement/actions. But these
; instructions are never run.
  LD A,(60140)            ; -
  CP 4                    ; -
  JR NC,L53080            ; -
  JR L52948_1             ; -
; Warlock is visible on screen. Every 32 frames, a decision whether the warlock
; is going to fire a missile/bolt at Maroc is made.
L52948_0:
  LD A,(L60074)           ; Game cycle counter
  AND 31                  ; Check bits 0-4 (1-31)
  JR NZ,L52948_1          ; If any are set, skip over this routine
; Generate a random number and compare it with this warlock's 'aggression'
; stat...
  CALL L56070             ; Generate random number (returned in A register)
  LD C,A                  ; Store in C register
  LD A,(L60333)           ; Byte 6 from warlock's data set at L27772 determines
                          ; the likelihood of them firing a missile
  RLA                     ; Double the value of this byte
  CP C                    ; Compare with the (pseudo) random number generated
  JR C,L52948_1           ; If it's < the random number, don't fire a missile
  JR L53080               ; If it's >= random number, set up a missile to fire
                          ; (L53080)
L52948_1:
  JP L53323               ; Jump to creature collision detection routine

; UNSEEN spell effect on creature movement
;
; Used by the routines at L52695 and L53054.
;
; Creatures will move erratically and randomly, if the UNSEEN spell is active -
; except for the WRAITH and DEMON, who can sense the magic and use it to home
; in on Maroc's position.
;
; You can see (in the animated image) that some creatures have a tendency to
; cluster towards the bottom right of the screen.
;
; This is because the randomizer routine at L52695_2 generates:
; * a pseudo-random horizontal speed/direction between 28 and +32 - in
;   multiples of 4 (negative = left, positive = right)
; * a pseudo-random vertical speed/direction between -7 and +8  (negative = up,
;   positive = down)
;
; These values are only very slightly skewed towards down & right, but the
; randomizer runs often, hence the visible result.
;
; Check if the UNSEEN spell is active:
L53003:
  LD A,(60137)            ; Currently active spell
  CP 9                    ; ...Is it the UNSEEN spell?
  JR NZ,L53003_0          ;
  LD A,(L60074)           ; If so get the incremental game counter
  AND 15                  ; Check if any of bits 0-3 set
  JP NZ,L52695_2          ; If so, randomize the movement pattern
  JP L53323               ; Switch back to normal movement every 16 frames
; Jump here from L52695_1 if creature is DEMON or WRAITH and Maroc's active
; spell number >=4
;
; These two creatures can 'sniff out' powerful magic.
; * If Maroc has UNSEEN active, they are able to home in on his position,
;   making them potentially more dangerous, though DEMONs will not fire
;   missiles which tend to be more difficult to avoid
; * They will also move towards Maroc's screen position if he casts ANY
;   'powerful' spell (i.e. spell number >=4)
;
; Calculate vertical position in relation to Maroc:
L53003_0:
  LD A,(60234)            ; Retrieve vertical position within current room, in
                          ; pixels, from top of room playing area
  LD C,A                  ; Store in C register
  LD A,(60097)            ; Maroc's vertical (Y-axis) screen position
  SUB C                   ; Subtract graphic position to get vertical offset
  RLA                     ; Shift bit 7 to determine if creature is higher or
                          ; lower than Maroc on the screen
  SBC A,A                 ; After subtracting, A register will either contain
                          ; 255 (-1) = below Maroc, or 0 = above Maroc
  XOR 7                   ; Value will now either be 7 or -7 (248)
  LD (60237),A            ; Set as creature's vertical movement speed/direction
; Calculate horizontal position in relation to Maroc:
  LD A,(60232)            ; Retrieve horizontal position within current room,
  LD C,A                  ; in 4-pixel/half-character steps
  LD A,(60096)            ; Maroc's horizontal (X-axis) screen position
  SUB C                   ; Subtract graphic position to get horizontal offset
  RLA                     ; Precision used to calculate = 2 pixels whereas the
                          ; difference is in 4-pixel steps, so double the value
  SBC A,A                 ; After subtracting, A register will either contain
                          ; 255 (-1) = to the right of Maroc, or 0 = to the
                          ; left of Maroc
  XOR 7                   ; Value will now either be 7 or -7 (248)
  LD (60236),A            ; Store as creature's horizontal movement
  JP L53323               ; speed/direction

; Goblin warrior - check if movement is affected by Maroc's magic power
;
; Used by the routine at L52695.
;
; Goblin warriors become apprehensive of Maroc if he's cast any slightly
; powerful spell (also see Trivia - Creatures spooked by Maroc's magic. This
; affects their movement patterns and can keep them at bay.
L53054:
  LD A,(60238)            ; (Creature) properties byte
  AND 1                   ; Bit 0 (1) indicates whether the creature is visible
                          ; on-screen
  JR Z,L53003             ; If not, don't need to do anything to change the
                          ; creature's movement (yet)
  LD A,(60140)            ; Get the currently active spell
  CP 5                    ; Check if spell number >=5
  JP NC,L52695_2          ; If so, goblin will be nervous..! Change goblin
                          ; movement pattern
; Maroc is not wielding powerful magic, so the goblin can continue its standard
; movement pattern - this is a continuous horizontal movement, with vertical
; movement zig-zagging every 8th game cycle:
  LD A,(L60074)           ; Game timer/counter
  AND 7                   ; Check bits 0-2 (values 0-7)
  JP Z,L53003             ; If zero, it's an 8th game cycle so change vertical
                          ; direction
  JP L53323               ; ...Otherwise continue in same direction

; Initialize missile/bolt fired by a creature
;
; Used by the routines at L52695, L52913 and L52948.
;
; Set up a missile/bolt fired by a warlock, demon, or goblin missile thrower.
L53080:
  LD A,(60327)            ; Type of missile fired by this creature
  CP 0                    ; 0 = No missile fired
  JP Z,L53323             ; Jump out if so
  LD C,A                  ; Store missile type in C register
  LD A,(L60305)           ; Creature missile count. 0 = no creature-fired
                          ; missiles currently on screen, 1 = there is one
  CP 0                    ; Is there a creature-fired missile already on
                          ; screen?
  JP NZ,L53323            ; If so, we're not allowed to have more than one
                          ; creature missile on screen, so skip to the next
                          ; routine
; OK for creature to fire a missile/bolt. Next, we need to calculate its
; trajectory.
  INC A                   ; Increment missile-count-in-room and re-store
  LD (L60305),A           ;
  LD A,C                  ;
  LD (60307),A            ; Store missile number/type
  LD A,5                  ;
  LD (60314),A            ; 5 = Object type - missile fired by creature (at
                          ; Maroc)
  LD HL,(60231)           ; Copy horizontal co-ordinate into data buffer
  LD (60308),HL           ; The creature's co-ordinates will be the origin
  LD HL,(60233)           ; point
  LD (60310),HL           ; Do the same for the vertical co-ordinate
  LD A,(60097)            ; Maroc's vertical (Y-axis) screen position
  LD (60313),A            ; Set as vertical screen position of target
  LD A,(60096)            ; Maroc's horizontal (X-axis) screen position
  LD (60312),A            ; Set as horizontal screen position of target
  LD A,0                  ;
  LD (60236),A            ; Set vertical movement speed to zero
  LD (60237),A            ; Set horizontal movement speed to zero (these two
  JP L53323               ; values will need to be calculated later)

; Warlock or creature - materialization & disintegration events
;
; Used by the routine at L52616.
;
; Materialization or disintegration routine - warlocks/demons materializing, or
; creatures disintegrating.
;
; This routine determines the post-materialization/disintegration actions to
; take. This information is held in bits 5-7 of the creature properties byte
; (60238).
L53145:
  LD A,(60240)            ; Graphic frame number/offset
  AND 7                   ; Only bits 0-2 (values 0-7) needed for the number of
                          ; frames
  CP 7                    ; There are 6 animation frames in the materialization
                          ; graphics (L43079). Have we reached frame #7?
  JP NZ,L53885            ; If not, jump out of routine at this point
; Final materialization/disintegration frame has been reached.
  LD A,(60238)            ; Creature/room item properties byte
  LD C,A                  ; Temp store in C register
  AND 7                   ; Filter out/resets bits 4-7
  OR 5                    ; Set bits 0 (indicating creature is on-screen) and 2
                          ; (indicating creature will need to be erased before
                          ; drawing)
  LD (60238),A            ; ...and re-store.
; This routine is running because bit 5, 6 or 7 of the item (creature)
; properties byte (60238) is set. This bit indicates what action to take after
; a creature materialization or disintegration animation.
  LD A,C                  ; Retrieve item (creature) properties byte
  AND 128                 ; Bit 7 of properties byte set = trigger
  JR NZ,L53145_0          ; WARLOCK/DEMON APPEARANCE after materialization
  LD A,C                  ; animation is complete
  AND 64                  ; Bit 6 of properties byte set = trigger warlock
  JR NZ,L53145_1          ; DISAPPEARANCE post-materialization animation
                          ; (52873) - e.g. successful object trade
  JR L53145_3             ; (If not either of the above) - Bit 5 of properties
                          ; byte set = trigger CREATURE REMOVAL
                          ; post-disintegration animation
; Creature has just materialized - setup graphic for this creature:
L53145_0:
  LD A,1                  ; Set graphic frame number/offset at 1 (first
  LD (60240),A            ; frame/no frame offset)
  LD A,(60331)            ; Graphic number (offset for address pointers in
                          ; table at L38851)
  CALL L57538             ; Set up creature graphics
  JP L53885               ;
; Warlock has been successfully traded with - remove warlock and initialize
; object trade
L53145_1:
  LD A,0                  ; Set creature type to 0 (nothing to setup/draw)
  LD (L60227),A           ;
  LD A,224                ; Timer indicating how long before a warlock is
                          ; likely to materialize in the current room
  LD (60340),A            ; The warlocks will still appear again after a
                          ; successful trade, but it'll be some time
; Warlock has gone - either off-screen, or disappeared after being traded an
; object successfully:
L53145_2:
  LD A,0
  LD (L60333),A           ; Set warlock 'aggression' (likelihood of firing a
                          ; missile at Maroc) to 0 (as it's gone)
  LD A,(60342)            ; Count of creatures in current room
  DEC A                   ; ...reduce by 1...
  LD (60342),A            ; ...and re-store.
  LD A,(60334)            ; Check if the warlock is carrying an object
  CP 0                    ;
  JP Z,L53885             ;
  LD (60230),A            ; ...If so, copy the item set number into the
  LD A,0                  ; warlock's data set
  LD (60334),A            ; ...and set the held item data buffer byte to 0
  JR L53273               ; ...then skip over to the next routine
; Creature has been destroyed - remove from existence:
L53145_3:
  LD A,0
  LD (L60227),A           ; Set creature type to 0 (no creature to deal with
                          ; any more)
  LD HL,(60228)           ; Get address pointer to relevant creature/warlock
  INC HL                  ; data set at L27772
  INC (HL)                ; Increment the second byte of the set. This byte
                          ; holds the number of these creatures Maroc has
                          ; destroyed
  LD A,(60342)            ; Reduce count of creatures in current room by 1
  DEC A                   ;
  LD (60342),A            ; Get creature type
  LD A,(60230)            ;
  CP 8                    ;
  JP NC,L53885            ; If creature >=8, it's not a warlock so jump out of
                          ; the routine here
  LD A,0                  ; Creature destroyed is a warlock. Set warlock
  LD (L60333),A           ; 'aggression' (likelihood of firing a missile at
                          ; Maroc) to 0, as the warlock is no more.
; If a warlock is destroyed, it will drop the object it's carrying
  LD A,(60328)            ; Get object number carried by the warlock
  CP 0                    ;
  LD (60230),A            ; ...Copy this value into the warlock's data buffer
  JP Z,L53885             ; If the warlock isn't carrying anything, can jump
                          ; out at this point

; Warlock - drop carried object
;
; Used by the routine at L53145.
;
; Follows the previous routine when a warlock is destroyed, or an object has
; been successfully traded.
;
; The disintegration/materialization animation that followed either of these
; events is complete and the warlock will now drop the object it is carrying.
L53273:
  LD A,0
  LD (60111),A            ; Set the draw/erase flag to 0 (ERASE)
  CALL L58365             ; Reset screen attribute colours for warlock
  LD A,4                  ;
  LD (L60227),A           ; Set the (new) object type to 4 = interactable
                          ; object
  LD B,0                  ; The CALL in a few instruction to L56908 uses either
                          ; the B register (room number) or C register (object
                          ; number), whichever is <>0 We want to use the C
                          ; register, so set B register to zero
  LD A,(60230)            ; Get object number
  LD C,A                  ; Store in C register
  LD HL,(56051)           ; Address pointer to the room object data sets in
  LD A,0                  ; table at L29551
  LD (60292),A            ; Set the counter for the room object tables to 0
  CALL L56908             ; Identify object, and copy its data into the object
                          ; data set buffer at 60293
  LD HL,(L60290)          ; Get address pointer to item's data set in table at
                          ; L29551
  LD (60228),HL           ; ...store in item data buffer
  LD A,(60296)            ; Get item properties byte
  OR %01001101            ; Set bits:
                          ; * 0 (1) = item is visible
                          ; * 2 (4) = item will need erasing before redrawing
                          ; * 3 (8) = item is dropping/flying
                          ; * 6 (64) = item is portable
  LD (60238),A            ; Store as item properties byte
  CALL L56028             ; Fetch object state and prepare graphics for
  JP L53885               ; printing

; Creature collision check with room boundary and Maroc
;
; Used by the routines at L52695, L52948, L53003, L53054 and L53080.
;
; Check if a creature has collided with a room boundary or Maroc:
; * Uses the generic room boundary check routine at L57401 which checks for
;   collision with the room walls, and if so, adjusts the creature's position
; * Checks if a creature is at Maroc's position on screen/in room
; * If so, reduce Maroc's energy based on the damage that creature type deals
;   (last byte of creature data set at 27828)
; * If the creature is a WRAITH, check if the WRAITHBANE spell is active & if
;   so destroy the wraith
L53323:
  LD A,(60572)            ; FREEZE spell timer counter (> 0 means the FREEZE
  CP 0                    ; spell is in effect)
  JR NZ,L53372_0          ; Maroc doesn't lose energy if he touches stationary
                          ; creatures when the FREEZE spell is in effect
; Check creature is within room wall boundary, adjusting if needed:
  LD A,(60234)            ; Creature's vertical pixel position in room
  ADD A,8                 ; Adjust the vertical point to check for collisions 8
                          ; pixels down, towards the middle of the creature,
                          ; rather than the top
  LD E,A                  ; Store in E register, which is what the room
                          ; boundary is checked against
  CALL L57401             ; Run room boundary checks for creature, adjusting
                          ; position accordingly if needed
; Check collision detection with Maroc
  LD C,0                  ; Collision event type 0 = collision with Maroc
  CALL L57293             ; Run collision check
  CP 0                    ; The A register is returned with 1 = collision, or 0
                          ; = no collision
  JP Z,L53885             ; If no collision, can jump out of the entire routine
                          ; here
; The next routine follows if a creature has collided with Maroc

; Creature has collided with Maroc
;
; The previous routine at L53323 has confirmed a creature has collided with
; Maroc.
L53349:
  LD A,(60230)            ; Check if creature is a WRAITH
  CP 11                   ;
  JR NZ,L53349_0          ; If not, skip next check
; WRAITHS are destroyed if they collide with Maroc when WRAITHBANE is active
  LD A,(60137)            ; Creature is a wraith
  CP 20                   ; Does Maroc have the WRAITHBANE spell active?
  JP Z,L53372             ; If so, destroy wraith
; Creature is touching Maroc - drain his energy by the amount of damage that
; this type of creature does.
L53349_0:
  LD A,(60332)            ; Amount of damage this creature does to Maroc's
                          ; energy bar (see Reference - Creatures)
  CALL L58316             ; Decrease Maroc's energy
  JR L53372_0             ; Jump to the routine to stop the creature moving -
                          ; it has found Maroc and will stay where it is and
                          ; continue to drain his energy unless he moves

; Maroc has destroyed a creature - initialise disintegration
;
; Used by the routines at L52616 and L53349.
;
; Creature has been hit by Maroc's missile/bolt/weapon, or wraith has collided
; with Maroc when he is protected by WRAITHBANE.
L53372:
  LD A,(60238)            ; Creature properties byte
  AND %00000111           ; Filter out bits 3-7 (animations, frames etc.)
  OR %00100101            ; Set bits:
                          ; * 0 (indicates item on-screen)
                          ; * 2 (item will need erasing)
                          ; * 5 (indiactes disintegrating creature)
                          ;  Setting bit 5 also ensures (a) the disintegration
                          ; animation isn't stopped for the FREEZE spell, and
                          ; (b) the creature will stop moving (e.g. towards
                          ; Maroc) while disintegrating
  LD (60238),A            ; ...and re-store
  LD A,1                  ; Set graphic frame offset to 1 (no offset)
  LD (60240),A            ;
  LD A,98                 ; Address pointer number to disintegration effect
                          ; graphics (39045)
  CALL L57538             ; Set up graphics
; Continued from above (disintegrating creature), and also from L53349_0 - if a
; creature has reached Maroc's position, it will stop moving and continue to
; drain his energy.
;
; If it's a wraith that and it's been destroyed by Maroc's WRAITHBANE, the
; disintegration graphic is animated but does not move.
L53372_0:
  LD A,0
  LD (60236),A            ; Set horizontal movement speed/direction to 0
  LD (60237),A            ; Set vertical movement speed/direction to 0
  JP L53885               ;

; Missile fired by Maroc or a creature - check for active shield/barrier spells
;
; Used by the routine at L51359.
;
; ...There's a missile/bolt flying around in the room..!
;
; This routine copies the missile's data from the table at L27868 into a
; working (missile) buffer at 60317.
;
; It also checks if Maroc has a counter defence spell active (SHIELD, DEFENCE
; etc.)
; * Each missile type (at L27868) has up to THREE counter defensive
;   barrier-type spells that will negate/repel it
; * These are stored in bytes 5, 7 and 8 of the missile's 8-byte data set
;   (AMULET spell repels all missiles)
; * The following instructions check if each of these values in a missile's
;   data set (stored in the current missile data buffer at 60321, 60323 and
;   60324) match the currently active defensive barrier spell type
; * If there's a match, a special missile/barrier collision routine (L57990) is
;   CALLed
L53403:
  LD A,(60238)            ; Missile properties byte
  AND 1                   ; Check if it's is on-screen (bit 1 is set)
  JP Z,L53550_0           ; ...if not, skip out to a later instruction
  LD HL,(60228)           ; Get address pointer to missile type (in table at
                          ; L27868)
  LD BC,8                 ; Copy the 8 bytes of missile data into missile
  LD DE,60317             ; working buffer table at 60317
  LDIR                    ;
  LD A,(60319)            ; Missile attribute (INK) colour
  LD (60072),A            ; Copy into item data buffer
  LD A,(60320)            ; Missile's event/collision type to check (stored as
  CP 0                    ; the 4th byte in the missile/bolt table at L27868)
  JR Z,L53403_0           ; If it's zero (no event), don't copy any event data
                          ; (shouldn't happen as there's a value for each
                          ; missile)
  CALL L58032             ; ...If it's not zero, copy item event data into
                          ; working buffer
; COUNTER SPELL #1 CHECK
L53403_0:
  LD A,(60137)            ; Get currently active 'effect' spell (value = 0 if
                          ; none currently in effect)
  LD C,A                  ; Copy to C register
  LD A,(60321)            ; Defence counter spell #1 (the spell in this slot is
  CP 0                    ; always AMULET)
  JR Z,L53403_1           ; Check for zero - if no counter spell in this slot
                          ; (shouldn't happen as there's a value for every
                          ; counter slot)
  CP C                    ; Check counter spell vs current active spell number
  JR Z,L53403_3           ; If there's a match, can skip the next two checks
                          ; straight to L53403_3
; COUNTER SPELL #2 CHECK
L53403_1:
  LD A,(60323)            ; Defence counter spell #2
  CP 0                    ; Check for zero - if no counter spell in this slot
  JR Z,L53403_2           ; (shouldn't happen as there's a value for every
                          ; counter slot)
  CP C                    ; Check counter spell vs current active spell number
  JR Z,L53403_3           ; If there's a match, can skip the final check and
                          ; jump straight to L53403_3
; COUNTER SPELL #2 CHECK
L53403_2:
  LD A,(60324)            ; Defence counter spell #3
  CP 0                    ; heck for zero - if no counter spell in this slot
  JR Z,L53526             ; (shouldn't happen as there's a value for every
                          ; counter slot)
  CP C                    ; Check counter spell vs current active spell number
  JR NZ,L53526            ; If there's NO match, jump out of the routine here
; The following instructions are redundant (possibly duplicated), as CP C has
; already happened in a previous check
L53403_3:
  CP C                    ; -
  JR NZ,L53526            ; -
; There's a match between the missile/bolt fired and an active shielding spell
; around Maroc that will negate/deflect it
;
; The following instructions check for a collision against Maroc's flickering
; shielding/protective spell
  LD C,1                  ; For the usual collision/event detection routine
                          ; (L57293) the C register is set an event/collision
                          ; type. On this occasion loading the C register is
                          ; unnecessary as it's not actually needed/used for
                          ; this (special) missile routine.
  CALL L57990             ; Check for a collision between the fired
                          ; bolt/missile and the shield/barrier around Maroc
  CP 0                    ; The A register is returned with 0 if no collision,
                          ; or 8 (this byte is used elsewhere for the
                          ; accompanying sound effect) if there's a collision
  JR Z,L53526             ; If no collision, jump out of this routine/check

; Creature's missile has hit Maroc's shield/barrier
;
; This causes the creature's missile to rebound off the shield at high speed.
; The diverted missile/bolt can even close open doors if it collides with a
; door handle.
;
; Calculate the missile's new horizontal trajectory:
L53484:
  LD A,(60096)            ; Maroc's horizontal (X-axis) screen position, in
  LD C,A                  ; 4-pixel/half-character steps
  LD A,(60232)            ; Missile's horizontal (X-axis) screen position, in
                          ; 4-pixel/half-character steps
  SUB C                   ; Subtract Maroc's position from missile position
  RLA                     ;
  SBC A,A                 ; The RLA and SBC sets A to 0 or 255 depending on
                          ; whether the missile position is to Maroc's left or
                          ; right
  XOR 15                  ; Based on direction, sets the above calculated value
  LD C,A                  ; at 240 (-15) or +15
  LD A,(60236)            ; Get the missile's existing horizontal movement
                          ; speed
  ADD A,C                 ; Add the calculated value (+/- 15)
  LD (60236),A            ; ...and re-store.
; Calculate the missile's new vertical trajectory
  LD A,(60097)            ; Maroc's vertical (Y-axis) pixel screen position
  LD C,A                  ; Missile's vertical (X-axis) pixel screen position
  LD A,(60234)            ;
  SUB C                   ; Subtract Maroc's position from missile position
  RLA                     ;
  SBC A,A                 ; The RLA and SBC sets A to 0 or 255 depending on
                          ; whether the missile position is above or below
                          ; Maroc
  XOR 15                  ; Based on direction, sets the above calculated value
  LD C,A                  ; at 240 (-15) or +15
  LD A,(60237)            ; Get the missile's existing vertical movement speed
  ADD A,C                 ; Add the calculated value (+/- 15)
  LD (60237),A            ; ...and re-store.
  JR L53550               ;

; Check if a missile fired by a creature has hit Maroc, and if so reduce his
; energy
;
; Follows 'missile deflection' checks at L53403 that checks for collision with
; an effective shield spell
;
; Check if it's a creature-launched missile, or a Maroc-launched missile:
L53526:
  LD A,(L60227)           ; Object type
  CP 8                    ; Object type 8 = Missile fired by Maroc
  JR Z,L53550             ; If it's one of Maroc's missiles, skip the next
                          ; check
  LD C,0                  ; Collision type to check = 0 (collision with Maroc)
  CALL L57293             ; Call collision check routine
  CP 0                    ;
  JR Z,L53550             ; A register returned with 1 if a collision is
                          ; detected (0 if not)
; A creature missile/bolt has hit Maroc. The previous check in the routine at
; L53403 has already confirmed Maroc does not have a protective shield spell
; against this missile/bolt, so it's going to damage his energy:
  LD A,(60322)            ; Value to decrease Maroc's energy by (varies by
                          ; missile type)
  CALL L58316             ; Decrease Maroc's energy
  JR L53550_0             ;

; Check missile room boundary collisions and on-screen lifespan
;
; Used by the routines at L53484 and L53526.
;
; No collision between a creature missile and Maroc (jump from 53540), or the
; missile has been fired by Maroc (jump from 53531)
;
; Missiles hitting a wall will bounce off like any other room objects.
;
; Check for collisions with room walls:
L53550:
  CALL L56008             ; Check that the missile isn't moving below the
                          ; bottom of the room boundary. Return any adjusted
                          ; vertical pixel position in the E register
  CALL L57401             ; Run collision detection routine for room walls,
                          ; adjusting horizontal position if needed.
; Missiles have varied lifespans. Note from the animated images how the
; VAPORIZE spell bolt lasts longer than the MISSILE spell.
;
; The second byte in the missile sets at L27868 holds this information.
;
; Reduce this missile's timer, and make it disappear if its timer has run out.
  LD A,(60238)            ; Item properties byte. For missiles, the value
                          ; contained in the top 4 bits of this byte tells
                          ; holds the duration this missile will appear/travel
                          ; for before it disappears.
  SUB 16                  ; Reduce the time/distance of this value by 16
  JR C,L53550_0           ; (initial values are between 144 and 240)
  LD (60238),A            ; If the missile is still with us, jump out to the
  JP L53885               ; next routine
; Jump here from 53408 if missile is off-screen, or the missile's lifespan has
; finished/fizzled out
L53550_0:
  LD A,(L60227)           ; Object type
  CP 5                    ; Type 5 = Missile fired by a creature/warlock
  JR Z,L53550_1           ;
  LD HL,60306             ; Missile fired by Maroc
  JR L53550_2             ;
L53550_1:
  LD HL,L60305            ; Missile fired by creature/warlock
; HL now contains:
; * L60305 if missile fired by creature/warlock
; * 60306 if missile fired by Maroc
L53550_2:
  DEC (HL)                ; Maroc's missile - decrement Maroc's missile count
                          ; (from one to zero) Creature missile - decrement
                          ; number of creature missiles in room (from one to
                          ; zero)
  LD A,0
  LD (L60227),A           ; Missile has fizzled out, so set item type to 0
  LD A,(60238)            ; Get item properties byte
  OR 4                    ; Set bit 2 (4) - this indicates the graphic will
                          ; need erasing
  LD (60238),A            ; ...and re-store.
  JP L53885               ;

; Copy co-ordinates of room's left/right wall connector sections to working
; buffer
;
; Used by the routine at L51359.
;
; Copy the co-ordinates of the left/right wall/floor vertical connectors, in
; relation to the current screen's viewport, into working data buffer
;
; Vertical back wall/floor connector (left)
L53601:
  LD A,(60234)            ; Graphic vertical pixel position
  LD (60154),A            ; Store as LEFT connector value
  LD A,(60232)            ; Graphic horizontal position, in
  LD (60155),A            ; 4-pixel/half-character steps
  JP L53885               ;
; Vertical back wall/floor connector (right) - Have already identified vertical
; position from left connector, as it's the same
L53601_0:
  LD A,(60232)            ; Graphic horizontal position, in
                          ; 4-pixel/half-character steps
  LD (60156),A            ; Store as RIGHT connector value
  JP L53885

; Tunnel position & direction
;
; Used by the routine at L51359.
;
; The first byte in the data sets (31744) for tunnels has the ID number of 15,
; which is the general tunnel position and direction.
;
; The other tunnel elements - walls/boundaries, spiders and bats - are dealt
; with separately in the same way as room objects.
L53625:
  LD A,0
  LD (60234),A            ; Set vertical pixel position to 0 (top of screen)
; The game timer is used to generate actions such as changing the tunnel
; direction, spiders, bats etc.
;
; Every 16th cycle of the game timer, a new tunnel direction is calculated:
  LD A,(L60074)           ; Get incremental game timer
  AND 15                  ; Check if any of bits 0-3 are set
  JR NZ,L53625_3          ; If so, continue the tunnel. The number bit value in
                          ; the AND instruction acts as an interval that
                          ; affects tunnel duration. It can be changed for
                          ; shorter tunnels - see the POKEs section.
; Check if Maroc has reached the end of the tunnel
  LD A,(60285)            ; Get tunnel length counter (first byte of tunnel
                          ; data sets at L26384 multiplied by 2)
  DEC A                   ; ...decrement it..
  LD (60285),A            ; ...and re-store
  JR NZ,L53625_0          ; Interval check - has Maroc reached the end of the
                          ; tunnel?
  LD A,255                ; ...If so, set the 'end-of-tunnel' byte accordingly
  LD (60080),A            ; - this is checked at L55818_0 and indicates that
                          ; the new room number at the end of the tunnel will
                          ; need evaluating/setting.
; Determine left/right direction, and offset, of tunnel walls. Bytes in ROM are
; used to randomize direction.
;
; Tunnel horizontal position can change left or right between -31 and +31
; pixels. If the byte value is outside these values (32 - 224) the current
; offset is not changed, i.e. the tunnel continues in the same direction
; without changing.
L53625_0:
  LD HL,(60228)           ; Value used to address various ROM locations to
                          ; generate pseudo-random numbers for tunnels
  INC HL                  ; Move to the next ROM address
  LD (60228),HL           ; ..and re-store pointer
  LD A,(HL)               ; Get byte from ROM address
  AND 63                  ; Keep a range of 0-63
  SUB 31                  ; Subtract 31, giving a value of +32 to -31
  LD C,A                  ; Put in C register
  LD A,(60236)            ; Get the current horizontal offset byte
  ADD A,C                 ; Add or subtract the direction change offset (+32 to
                          ; +31)
  CP 128                  ; Check if byte value is >= 128 (bit 7 set)
  JR NC,L53625_1          ;
  CP 32                   ; If not, check if byte value >= 32
  JR NC,L53625_3          ; If so, it's outside the threshold so jump straight
  JR L53625_2             ; to L53625_3 (don't change horizontal offset value)
L53625_1:
  CP 224                  ; Byte value is > 128 so check if value < 224
  JR C,L53625_3           ; If so, it's outside the threshold so jump straight
                          ; to L53625_3 (don't change horizontal offset value)
L53625_2:
  LD (60236),A            ; Byte value is OK - store the new horizontal offset
                          ; value
; If the tunnel's horizontal position is too close to the left or right edge of
; the screen, shift its direction slightly back towards the centre:
L53625_3:
  LD A,(60232)            ; Horizontal position (in 4-pixel/half-character
                          ; steps)
  LD (60574),A            ; Copy to item horizontal position data store
  LD C,A                  ; Temp store in C
  SUB 16                  ; If we subtract 16...
  CP 32                   ; ...and check against 32...
  JR C,L53625_4           ; ...a carry (jump to the end of the routine) will
                          ; occur if the boundary is between 16 half-character
                          ; steps and 48 half-character steps (this is OK)
  LD A,28                 ; Otherwise, subtract the horizontal position from 28
  SUB C                   ; (roughly centre of screen)
  SRA A                   ; ...and halve the offset, bringing it slightly
                          ; closer to the centre of the screen
  LD (60236),A            ; Re-store as the new horizontal position
  NEG                     ; Maroc's offset is the opposite of the scenery
  LD (60164),A            ; ...So store the negative of this value for his
L53625_4:
  JP L53885               ; horizontal offset.

; Check tunnel item type for collision checks and movement (boundary, bats and
; spiders)
;
; Used by the routine at L51359.
;
; Check for collisions with all tunnel objects (left/right boundary, bats or
; spiders).
; * Collision with a boundary wall drains Maroc's energy by 1 point
; * Collision with a spider or bat drains Maroc's energy by 16 points
L53714:
  LD A,(60238)            ; Object properties byte
  AND 1                   ; Bit 1 indicates if the item is visible on-screen
  JR Z,L53787             ; If not, skip the rest of this routine
; Check what tunnel object we're dealing with:
  LD A,(60230)            ; Tunnel boundary wall type. 1 = right, 2 = left
  CP 1                    ;
  JR Z,L53819             ; Right boundary wall check
  CP 2                    ;
  JR Z,L53819_0           ; Left boundary wall check
; If it's not a right/left boundary wall, the item must be a creature - spider
; or bat.
;
; In which case, run a collision check with Maroc and reduce his energy if a
; collision is detected.
  LD A,2                  ; Set the counter/length/frequency used for the
  LD (60246),A            ; generic sound effect routine at L49274 as spiders
                          ; and bats make a scuttling/flapping sound as they
                          ; move down the tunnel
  LD C,0                  ; Collision/event type to check - 0 = Collision with
                          ; Maroc
  CALL L57293             ; Run event/collision check
  CP 0                    ; The A register is returned with 1 = Collision, 0 =
  JR Z,L53714_0           ; No collision
  LD A,16                 ; If there's a collision...
  CALL L58316             ; ...Reduce Maroc's energy (by 16)
; Creature movement
L53714_0:
  LD A,(60230)            ; Creature type. 4 = Spider, 8 = Bat
  CP 8                    ; Is it a bat?
  JP NZ,L53885            ; If not, jump to spider movement

; BAT movement in tunnel section
;
; In the tunnels the bat appears with a high (downwards) speed and can reach
; high horizontal speeds as well. Bats are probably the main thing to avoid in
; tunnel sections.
;
; They're designed to gravitate/slow down towards the centre point of the
; screen where Maroc is. It's possible for Maroc to suffer a heavy energy drain
; from bats during long tunnels. The CHALICE spell does not restore Maroc's
; energy during the tunnel segments.
L53759:
  LD A,(60237)            ; Vertical movement speed (negative = up, positive =
                          ; down)
  ADD A,246               ; This subtracts 10 from the bat's speed, initially
                          ; moving downwards (speed values = positive) quickly,
                          ; slowing its descent until it roughly reaches
                          ; Maroc's vertical position. It then starts moving
                          ; back up the screen (speed values = negative) at an
                          ; increasing speed.
  LD (60237),A            ; ...And re-store
  LD A,(60232)            ; Graphic's horizontal position, in half character (4
  LD C,A                  ; pixel) steps
  LD A,28                 ;
  SUB C                   ; Subtract from 28 This is in 4-pixel/half-character
                          ; steps, so it's around the centre of the screen.At
                          ; this point the value added to the bat's horizontal
                          ; speed will reduce, meaning it stays around the
                          ; centre of the screen for longer.
  ADD A,A                 ; x2
  ADD A,A                 ; x4
  LD C,A                  ;
  LD A,(60236)            ; Horizontal movement speed (negative = left,
                          ; positive = right)
  ADD A,C                 ; Add the calculated speed to this
  LD (60236),A            ; ...and re-store
  JP L53885               ;

; Tunnel item (boundary or bat/spider) has gone off-screen - reduce on-screen
; item count
;
; Used by the routine at L53714.
;
; Helps keep track and limit the number of graphic items on-screen during the
; tunnel sections. Jump from 53719 if tunnel item is no longer visible
; on-screen.
L53787:
  LD A,0
  LD (L60227),A           ; Set type of graphic to draw to 0
  LD A,(60230)            ;
  CP 3                    ; Check if tunnel item type < 3
  JR NC,L53787_0          ;
; If so, it's a left/right boundary graphic that's now gone off-screen
  LD A,(60286)            ; Byte holding the number of boundary wall graphics
                          ; currently on screen. This number is checked &
                          ; limited (to 20) at 55011.
  DEC A                   ; Decrement this counter, as there's now one less...
  LD (60286),A            ; ...and re-store.
  JP L53885               ;
; Creature has gone off-screen
L53787_0:
  LD A,(60573)            ; Counter for number of creatures currently on-screen
                          ; (max 3)
  DEC A                   ; Decrement number...
  LD (60573),A            ; ...and re-store
  JP L53885               ;

; Tunnels - check if Maroc has hit a left/right boundary wall
;
; Used by the routine at L53714.
;
; Maroc loses a very small amount of energy (1) if he collides with a tunnel
; boundary.
;
; This routine checks Maroc's position against that of either the left
; (L53819_0) or right (L53819) boundary (determined at 53721).
;
; RIGHT boundary wall check - compare boundary wall position against Maroc's
; position
;
; Vertical position check:
L53819:
  LD A,(60234)            ; Boundary wall's vertical (pixel) position
  SUB 80                  ; Subtract 80 (pixels) from this value
  CP 16                   ;
  JP NC,L53885            ; If the difference is >=16, it's NOT within Maroc's
                          ; vertical 'hit box' area (jump out here)
; Horizontal position check:
  LD A,(60232)            ; Boundary wall's horizontal (half-character/4-pixel)
                          ; position
  CP 32                   ; Check vs 32 (= 16 character squares = the right
                          ; hand side of Maroc's sprite graphic)
  JR NC,L53819_2          ; If no carry (NC), Maroc ISN'T beyond the tunnel
                          ; boundary, so can jump out here
  LD A,32                 ; Maroc has hit/passed the boundary wall.Pre-load the
  JR L53819_1             ; value to assign to Maroc's speed to +32 = full
                          ; speed left, as Maroc bounces off the wall
; LEFT boundary wall check - compare boundary wall position against Maroc's
; position
;
; Vertical position check:
L53819_0:
  LD A,(60234)            ; Boundary wall's vertical (pixel) position
  SUB 80                  ; Subtract 80 (pixels) from this value
  CP 16                   ;
  JP NC,L53885            ; If the difference is >=16, it's not within Maroc's
                          ; vertical 'hit box' area (jump out here)
; Horizontal position check:
  LD A,(60232)            ; Boundary wall's horizontal (half-character/4-pixel)
                          ; position
  CP 24                   ; Check vs 24 ( = 12 character squares = the left
                          ; hand side of Maroc's sprite graphic)
  JR C,L53819_2           ; If there's a carry, Maroc ISN'T beyond the tunnel
                          ; boundary, so jump out here
  LD A,224                ; Maroc has hit/passed the boundary wall.Pre-load the
                          ; value to assign to Maroc's speed to 224 (-32) =
                          ; full speed right, as Maroc bounces off the wall
; Maroc has hit a boundary wall
L53819_1:
  LD (60164),A            ; Store Maroc's adjusted speed (after bouncing off
                          ; either wall)
  LD A,1                  ; Set energy drain amount to 1
  CALL L58316             ; Decrease Maroc's energy
L53819_2:
  JP L53885               ;

; Start of setting up room routine
;
; Used by the routine at L51359.
;
; Jump here from the check at 51414 if the room item type (L60227) = 32.
;
; Item type 32 is always the first data set in the room data sets (at 31744).
; It holds the position of the 'viewport' of the room, which is used to adjust
; room item co-ordinates.
L53870:
  LD HL,(60233)           ; Overflow/precision byte for vertical position of
                          ; room viewport - 60233 > 60150
  LD (60150),HL           ; Copy into game buffer
  LD HL,(60231)           ; Overflow/precision byte for horizontal position of
                          ; room viewport - 60231 > 60152
  LD (60152),HL           ; Copy into game buffer
  JP L54053               ;

; Drawing checks and routines for all on-screen room items
;
; Used by the routines at L51359, L51420, L51611, L51892, L52582, L52849,
; L53145, L53273, L53323, L53372, L53550, L53601, L53625, L53714, L53759,
; L53787 and L53819.
;
; This routine is run after each room scenery object/item data set has been set
; up ready for printing. It:
; * Checks if items need printing (on-screen, not hidden)
; * Erases item graphics if needed
; * Calculate and set item colours/attributes
; * Prints/draws the item's attribute colours and then pixels (CALLs to L58365
;   and L56216)
L53885:
  LD A,(60238)            ; Item properties byte
  LD C,A                  ;
  AND 7                   ; Just the lowest 3 bits (bits 0-2) needed for this
                          ; check
  CP 5                    ; Bit 0 (1) = the item is on screen, bit 2 (4) = the
                          ; item will need erasing
  JR NZ,L53885_1          ; If both conditions are met, continue and erase it.
                          ; Otherwise there's no need so skip the next set of
                          ; instructions.
; Item is on-screen and needs erasing:
  LD A,0                  ; Set the draw/erase flag to 0 (ERASE)
  LD (60111),A            ;
  LD HL,(60109)           ; Get address pointer for the item graphic to erase
  CALL L56216             ; ...And erase the graphic
  LD A,(60072)            ; Get INK colour of room item/object
  CP 0                    ; If it's zero, it's an erased scenery room item
  JR Z,L53885_0           ; (rather than a differently coloured object), so
                          ; there's no need to specially print
                          ; colours/attributes for it
  CALL L58365             ; Otherwise, will need to set the screen
                          ; attributes/colours for the object
L53885_0:
  LD A,(60117)            ; Get the 'graphic visible' flag (1 = graphic drawn,
                          ; 0 = graphic not drawn as fully off-screen)
  LD C,A                  ; ...Store in C register
  LD A,(60238)            ; Get item properties byte
  AND 254                 ; Filter out (reset) bit 0
  OR C                    ; ...append the 'graphic visible' flag to bit 0 to
                          ; indicate if the graphic is on screen or not
  LD (60238),A            ; ...and re-store
  LD C,A                  ; Copy the item properties byte (60238) into the C
                          ; register
; Check if the item needs drawing
L53885_1:
  LD A,(L60227)           ; Type of graphic to draw
  CP 0                    ;
  JR Z,L54053             ; If this has been set to zero, the item is no longer
                          ; visible or in existence - there's nothing to draw
  LD A,C                  ; Retrieve item properties byte
  AND 5                   ; Check for bit 0 (item is visible) and bit 2 (item
                          ; has moved/needs erasing)
  JR Z,L54053             ; If neither is set, there's nothing to draw, so skip
                          ; the rest of the routine
; Set up item for drawing
  LD A,(60234)            ; Graphic vertical position within current room, in
                          ; pixels, from top of room playing area
  LD (60114),A            ; Copy to working graphics data buffer
  LD HL,(L60107)          ; Graphic's horizontal position, in pixels
  LD (60115),HL           ; Copy to working graphics data buffer
  LD A,(60235)            ; Room type byte - this is set to 64 for 'standard'
                          ; rooms, or 254/255 for tunnel rooms
  LD (60118),A            ; Copy to working graphics data buffer
  LD A,1                  ;
  LD (60111),A            ; Set draw/erase flag to 1 (DRAW)
  LD A,C                  ; Retrieve item properties byte from C register
  AND 2                   ; Bit 1 (2) if set means item is hidden/not-visible,
  JR Z,L53885_2           ; e.g. inside a chest
  LD HL,(60147)           ; If this is the case, set the graphics address
                          ; pointer to the 'dummy' graphic (39097), so that
                          ; nothing actually gets drawn
  JR L53885_6             ; As nothing will be drawn, can also skip over the
                          ; next section dealing with the item's
                          ; colours/attributes
; Set attribute colours for this item
L53885_2:
  LD A,(60072)            ; Get item colour byte
  CP 0                    ; This is set for interactable items and creatures
                          ; but 0 for most other things such as scenery (which
                          ; is drawn with standard room colours)
  JR Z,L53885_5           ; If it's set to 0, don't need to print any colours
  CP 8                    ; Is the value 7 or less ('standard' INK colours)
  JR C,L53885_3           ; If so, can skip the next 3 instructions
; If bit 3 (8) is set, it means this object flashes (changes colour). Use the
; game cycle timer to determine its INK colour at this exact moment:
  LD A,(L60074)           ; Get game counter/timer
  AND 3                   ; Keep just bits 0 and 1 (values = 0-3)
  ADD A,4                 ; Add 4, to give an INK value between 4 (green) and 7
                          ; (white)
; Set object colour:
L53885_3:
  AND 7                   ; Only need to keep bits 0-2 (values = 0-7)
  OR 64                   ; Set BRIGHT bit for the colour (all
                          ; on-screen/viewport colours are set to BRIGHT 1)
  LD C,A                  ; Store item (INK) colour in C register
; Check if object graphic INK colour is the same as the current screen PAPER
; colour (if so, it'd be invisible):
  LD A,(60073)            ; Get room attribute colour
  LD B,A                  ; Temp store in B register
  RRA                     ; Shift bits so that the PAPER colour becomes an INK
  RRA                     ; value to compare
  RRA                     ;
  AND 7                   ; Filter out everything other than INK bits
  OR 64                   ; Set BRIGHT bit
  CP C                    ; Compare with object colour
  JR NZ,L53885_4          ; If different, all is fine, skip next two
                          ; instructions
; Item INK colour is the same as screen PAPER colour.
;
; This shouldn't really happen; most portable objects like keys are light
; colours (screens have dark backgrounds) and other objects like chests can't
; be moved from room to room:
  LD HL,(60147)           ; If it does happen, set the graphics address pointer
                          ; to the 'dummy' graphic (39097), so nothing gets
                          ; drawn (the item would appear invisible anyway)
  JR L53885_6             ; ...and skip to drawing the actual graphic (pixels)
; As screen PAPER background colours vary, we need to combine the object
; attribute INK colour with the current screen PAPER colour:
L53885_4:
  LD A,B                  ; Retrieve the room colour attribute value (stored in
                          ; PAPER bits)
  AND 248                 ; Filter out/clear any INK bits
  OR C                    ; Append the item's INK bits (0-7)
  LD (60072),A            ; ...and re-store as the item's colour
; Print the item's attribute colours on screen (this is done before drawing the
; actual pixels):
  LD A,(60116)            ; Get the horizontal position high byte - this
  CP 0                    ; indicates whether the object is within the current
                          ; screen viewport
  JR NZ,L53885_5          ; If not, no need to print attributes, skip the next
                          ; instruction
  CALL L58365             ; Print screen attribute colours for the room
                          ; object/creature
; Now draw the item's graphics (pixels):
L53885_5:
  LD HL,(60241)           ; Graphic address pointer
L53885_6:
  CALL L56216             ; Draw the item graphics
  LD A,(60117)            ; Get the visible graphic flag (1 = graphic drawn, 0
                          ; = graphic not drawn as fully off-screen)
  LD C,A                  ; Append this flag (1/0) into bit 0 of the item
  LD A,(60238)            ; properties byte at 60238 indicating whether this
                          ; item is visible on screen
  AND 254                 ; Filter out bit 0 from the item properties byte
  OR C                    ; Append a 0 or 1 accordingly (not
                          ; on-screen/on-screen)
  LD (60238),A            ; ...and re-store the item properties byte.

; Start of setting up room routine - part 2
;
; Used by the routines at L53870 and L53885.
;
; Also continued from previous section. This routine replaces the active item
; data back into its room item data set at 31744.
L54053:
  CALL L57520             ; Copy 16 bytes of the active item data set from
                          ; L60227 to one of the room item data sets at 31744.
  CALL L57815             ; Play (generic) step/white noise sound effect (if
                          ; this item is making a noise it will have its
                          ; speaker bit set)
  LD HL,(60092)           ; Get copy of pointer to data sets at 31744
  JP L51178               ; Prepare to start copying the updated room data set
                          ; into the working data buffer

; Flash the 'MAGIC' text in the bottom left (if Maroc has picked up a spell)
; and trigger sound effect
;
; Used by the routine at L51178.
;
; HL Address pointer (60092/60094) to first byte of one of the data sets at
;    31744 (the one after the last set copied in the previous routine)
;
; Jump here from L51152 after copying graphics data to banks at 31744
;
; If Maroc picks up a spell, the 'Magic' text in the bottom left changes colour
; for a short time, and a sound is played
L54065:
  LD HL,(60094)           ; Address pointer to start of next data set (at
                          ; 31744)
  LD (HL),255             ; Add end-of-data marker to the first byte of the set
  LD (60274),HL           ; Copy address pointer into store
; Check if the post-scroll-pickup effect (colour/sound) needs to be actioned:
  LD A,(60576)            ; This is the counter byte for flashing the 'MAGIC'
  CP 0                    ; text in the bottom left of the screen.
  JR Z,L54120             ; If it's zero, no need for flashing & playing sound
                          ; - skip to the next routine
; Change the colour of the 'Magic' text in the bottom left of the screen and
; play a sound.
  DEC A                   ; Decrement the 'flashing' counter, and re-store
  LD (60576),A            ;
  JR NZ,L54065_0          ; Check if now zero
  LD A,48                 ; If so, reset the final colour change to yellow (INK
                          ; 0, PAPER 6), otherwise the counter would make it
                          ; INK 0, PAPER 0 (invisible).At the start of the game
                          ; the lower part of 'MAGIC' is white, but will
                          ; subsequently be yellow once the first spell is
                          ; collected (see the animated image on this page).
; Change the colour of the word 'MAGIC':
L54065_0:
  LD DE,28                ; Prepare an offset of 28 character spaces ready to
                          ; move down to the next line of the screen
  LD C,2                  ; 2 character rows to colour
  LD HL,23234             ; Screen display address for the top left of the word
                          ; 'MAGIC'
L54065_1:
  LD B,4                  ; 4 characters wide
L54065_2:
  LD (HL),A               ; Colour the character square (colour = counter byte
                          ; value)
  INC HL                  ; Move right one character square
  DJNZ L54065_2           ; Repeat x 4
  ADD HL,DE               ; Jump down to the next character row, over to the
                          ; left again
  DEC C                   ; Decrement the row counter
  JR NZ,L54065_1          ; ...And repeat for 2 rows
; Play sound effect:
  LD C,128                ; Outer loop - duration counter
  LD A,16                 ; Speaker bit 4 (16)
; Speaker toggle loop:
L54065_3:
  XOR 16                  ; Toggle speaker bit
  OUT (254),A             ; Output sound
  LD B,C                  ; Get duration counter
L54065_4:
  DJNZ L54065_4           ; ...short pause for duration value of counter
  DEC C                   ; Decrement duration counter
  JR NZ,L54065_3          ; Repeat loop until sound duration counter = 0

; Determine Maroc's sprite graphic position, height and direction
;
; Used by the routine at L54065.
;
; Set Maroc's facing direction depending on keys pressed, and set his height
; (above his shadow) based on his speed
;
; Prepare Maroc's sprite - direction, height and movement
;
; Set attributes and reset movement if needed
L54120:
  CALL L57888             ; Set attribute colours for Maroc
  LD A,(L60074)           ; Get generic game counter/timer
  INC A                   ; Increment
  LD (L60074),A           ; ...and re-store
  AND 2                   ; Check bit 1 - this will be set every other frame
  JR Z,L54120_0           ;
  LD A,0                  ;
  LD (60075),A            ; If not set (i.e. every other game frame), set
                          ; vertical & horizontal movement velocity to 0
  LD (60076),A            ; By only resetting it every other frame, this has
                          ; the effect of continuing Maroc's forward movement
                          ; very briefly when he enters a new room (through a
                          ; door), before stopping
; Identify Maroc's current X/Y pixel co-ordinates (including offsets):
L54120_0:
  LD A,0                  ; High overflow/precision byte for graphic horizontal
  LD (60116),A            ; screen position - reset just in case
  LD HL,(60098)           ; Get Maroc's sprite frame graphic address pointer
                          ; (table at L38851)
  LD (60109),HL           ; Copy to graphics address buffer
  LD A,(60096)            ; Maroc's horizontal (X-axis) screen position
                          ; (4-pixel/half-character steps)
  RLA                     ; x 2
  RLA                     ; x 4 - screen position is now in pixels
  AND 252                 ; Filter out any unwanted bits 0 & 1 caused by the
                          ; RLA
  LD (60115),A            ; Store horizontal pixel position in graphics data
                          ; buffer
  LD A,(60577)            ; Maroc's height offset as he moves (above his
  LD D,A                  ; shadow) in pixels
  LD A,(60097)            ; Maroc's vertical (Y-axis) screen position
  LD (60114),A            ; Copy to graphics buffer
  SUB D                   ; Subtract Maroc's height offset (changes depending
                          ; on how fast he's moving)
  LD D,A                  ; Store back in D register
; Convert Maroc's horizontal and vertical speeds to positive numbers if needed:
  LD A,(60164)            ; Maroc's horizontal movement speed/rate
  CP 128                  ; If bit 7 is set, Maroc's moving right
  JR C,L54120_1           ; ...So if there's a carry, it means bit 7 isn't set
                          ; (Maroc's moving left)
  NEG                     ; If Maroc's moving right, change his speed to a
                          ; positive value (i.e. reset bit 7) ready for the
                          ; next calculations
L54120_1:
  LD C,A                  ; Store horizontal speed in C register
  LD A,(60165)            ; Maroc's vartical movement speed/rate
  CP 128                  ; If bit 7 is set, Maroc's moving down
  JR C,L54120_2           ; ...So if there's a carry, it means bit 7 isn't set
                          ; (Maroc's moving up)
  NEG                     ; If Maroc's moving up, change his speed to a
                          ; positive value (i.e. reset bit 7) ready for the
                          ; next calculations
; Get Maroc's speed, and adjust his height above his shadow (pixel offset)
; accordingly.
;
; First, get the greater of either his horizontal or vertical speed:
L54120_2:
  CP C                    ; Check vertical speed (A register) vs horizontal
                          ; speed (C register)
  JR NC,L54120_3          ; If no carry, vertical speed >= horizontal speed
  LD A,C                  ; Otherwise, pick horizontal speed
; Calculate Maroc's new height pixel offset based on his current speed:
L54120_3:
  RRA
  RRA                     ; Divide by 4. e.g. if Maroc is at 32 (max speed) the
                          ; offset will be 8
  AND 31                  ; ...and filter out any unwanted bits (bits 5-7)
  LD C,A                  ;
  LD A,7                  ; 7 (pixels) is the base value (if Maroc isn't
                          ; moving)
  SUB C                   ; Subtract the offset (offset is now between -1 and
                          ; +7 pixels)
  LD (60577),A            ; ...and store the new offset.
  ADD A,D                 ; Add the new offset to Maroc's vertical (Y-axis)
                          ; pixel position
  LD (60097),A            ; ...and store.
; Identify Maroc's left/right movement
  LD A,(L60157)           ; Get left/right direction key press flag
  CP 0                    ; If it's 0, neither right/left is being pressed
  JR Z,L54120_6           ;
  CP 128                  ; Left or right direction controls are being pressed
                          ; so check bit 7 to determine which one.
  JR C,L54120_8           ; Carry = right control key used
  LD A,(60158)            ; No carry = left control key used. Get up/down
                          ; direction key press flag
  CP 0                    ; If it's 0, neither up/down is being pressed
  JR Z,L54120_4           ;
  CP 128                  ; Up or down direction controls are being pressed so
                          ; check bit 7 to determine which one.
  JR C,L54120_5           ; Carry = up control key used
; LEFT and DOWN controls pressed
  LD A,32
  JR L54120_11
; LEFT control pressed, no up/down controls pressed.
L54120_4:
  LD A,64
  JR L54120_11
; LEFT and UP controls pressed
L54120_5:
  LD A,96
  JR L54120_11
; Neither left or right controls pressed. Check up/down controls.
L54120_6:
  LD A,(60158)            ; Get up/down direction key press flag
  CP 0                    ; If it's 0, neither up/down (or left/right) is being
  JR Z,L54120_14          ; pressed - skip out of routine
  CP 128                  ; Up or down direction controls are being pressed so
                          ; check bit 7 to determine which one
  JR NC,L54120_7          ; No carry = down control key used
; UP control pressed, no left/right controls pressed
  LD A,128
  JR L54120_11
; DOWN control pressed, no left/right controls pressed
L54120_7:
  LD A,0
  JR L54120_11
; Right control pressed - check up/down options
L54120_8:
  LD A,(60158)            ; Right control pressed. Get up/down direction key
                          ; press flag
  CP 0                    ; If it's 0, neither up/down is being pressed
  JR Z,L54120_9           ;
  CP 128                  ; Up or down direction controls are being pressed so
                          ; check bit 7 to determine which one
  JR C,L54120_10          ; Carry = up control key used
; RIGHT and DOWN controls pressed
  LD A,224
  JR L54120_11
; RIGHT control pressed, no up/down controls pressed
L54120_9:
  LD A,192
  JR L54120_11
; RIGHT and UP controls pressed
L54120_10:
  LD A,160
; Determine Maroc's direction - part 2
;
; Control key presses have now been evaluated, and the A register contains a
; value based on these.
;
; +----------------+----------------------------+
; | Direction      | Contents of the A register |
; +----------------+----------------------------+
; | DOWN           | 0                          |
; | DOWN and LEFT  | 32                         |
; | LEFT           | 64                         |
; | UP and LEFT    | 96                         |
; | UP             | 128                        |
; | UP and RIGHT   | 160                        |
; | RIGHT          | 192                        |
; | DOWN and RIGHT | 224                        |
; +----------------+----------------------------+
;
; Each additional 32 increment indicates a clockwise rotation of the sprite. As
; Maroc moves, he smoothly rotates towards the new position using these
; increments, rather than the sprite suddenly switching to a new direction.
L54120_11:
  LD B,A                  ; Store above value in B register
  LD A,(60163)            ; Get Maroc's current facing direction
  LD C,A                  ; Store in C register
  LD A,B                  ; Get the new direction based on the previously
                          ; evaluated keys pressed
  SUB C                   ; ...and subtract the existing direction
  JR Z,L54120_14          ; If the result is 0, Maroc is already facing in the
                          ; right direction - nothing to change
  CP 128                  ; Check bit 7 to see if the result is positive or
  JR NC,L54120_12         ; negative, i.e. whether Maroc needs to rotate
                          ; clockwise or anti-clockwise.
  LD A,32                 ; If it's positive, set the increment amount to 32 -
  JR L54120_13            ; Maroc is rotating CLOCKWISE
L54120_12:
  LD A,224                ; If it's negative, set the increment amount to -32 -
                          ; Maroc is rotating ANTI-CLOCKWISE
L54120_13:
  ADD A,C                 ; Add this offset to the existing position
  LD (60163),A            ; ...and store.
; Get the graphic address offset corresponding to this new rotational position.
L54120_14:
  LD A,(60163)            ; Get Maroc's new rotational position (see values in
                          ; table at L54120_11)
  RRA                     ; Divide by 16
  RRA                     ;
  RRA                     ;
  RRA                     ;
  AND 14                  ; Filter out any other bits set by the RRA
                          ; instructions
; The A register value is now even and in the range of 0-14. This is the
; address pointer offset for Maroc's sprite frame (starting at L38851).
  LD E,A                  ; Store in E register
  LD C,0                  ; Reset C register (will act as a flag to indicate if
                          ; anything has changed with Maroc's sprite)
  LD A,(60575)            ; Get the current address pointer offset
  CP E                    ; Compare with the newly calculated one
  JR Z,L54342             ; If it's the same, there's nothing to change, so
                          ; skip out of this routine
  INC C                   ; Increment the (flag) C register (this indicates
                          ; that there's been a change to Maroc's sprite
                          ; graphic)
  LD A,E                  ; Get the newly calculated graphics offset address
                          ; value
  LD (60575),A            ; ...and store
  LD D,0                  ; The graphics address offset will be in DE, the high
                          ; byte of the offset isn't needed so reset it
  LD HL,(60266)           ; Address pointer to graphics at L38851
  ADD HL,DE               ; Add the offset for Maroc's new graphics frame
  LD (60098),HL           ; ...and store.

; Draw Maroc's sprite graphic
;
; Follows previous routine which has calculated Maroc's sprite rotation and
; 'floating' height at L54120. If Maroc's sprite has changed (either its height
; or graphic frame) it's erased before drawing the new one.
;
; C Used as a change flag, initialized at 0 in previous routine at 54320, and
;   used to determine if anything has changed with Maroc's sprite (not zero if
;   so).
;
; Check if Maroc's vertical pixel position (height) has changed from the
; earlier calculation:
L54342:
  LD A,(60097)            ; Get Maroc's vertical pixel position
  LD D,A                  ; Store in D register
  LD A,(60114)            ; Get Maroc's vertical pixel position, with the
                          ; earlier vertical offset added
  CP D                    ; Is it the same?
  JR Z,L54342_0           ;
  INC C                   ; If not, increment the (flag) C register
L54342_0:
  LD A,C                  ; Check the (flag) C register
  CP 0                    ; If it's still zero, there's no change to either (a)
  JR Z,L54342_1           ; Maroc's sprite address offset, or (b) his vertical
                          ; pixel height offset (based on his movement speed),
                          ; so skip the next instructions as there's no need to
                          ; erase the existing sprite.
; Either Maroc's height offset (based on his speed) or his sprite graphic frame
; has changed in one of the earlier calculations, so the old sprite needs
; erasing.
  LD A,0                  ; Set draw/erase flag to 0 (ERASE)
  LD (60111),A            ;
  LD HL,(60109)           ; Retrieve Maroc sprite's graphic address from the
                          ; (previous) graphic address buffer
  CALL L56216             ; Erase the graphic
; Draw Maroc's sprite graphic
L54342_1:
  LD A,(60097)            ; Maroc's vertical (Y-axis) screen position
  LD (60114),A            ; Copy into graphics buffer
  LD A,1                  ; Set draw/erase flag to 1 (DRAW)
  LD (60111),A            ;
  LD A,(60137)            ; Check if the UNSEEN spell (spell #9) is currently
  CP 9                    ; active
  JR Z,L54393             ; If so, there's no need to draw Maroc's sprite
                          ; graphic, as he's invisible, so skip the next two
                          ; instructions
  LD HL,(60098)           ; Maroc's sprite graphics frame address pointer (in
                          ; table at L38851)
  CALL L56216             ; Draw Maroc's sprite

; Check if Maroc is on a room element/item that drains or restores his energy
;
; Used by the routine at L54342.
;
; This routine checks if Maroc is (floating) on top of an object of a type that
; drains or restores his energy.
;
; Various stationary room objects e.g. fires, orbs and mushrooms, can either
; drain or restore Maroc's energy when he passes over them.
; * Energy draining objects drain 8 points of energy (per game frame)
; * Energy restoring objects restore 2 points of energy (per game frame)
L54393:
  LD A,(60114)            ; Maroc's vertical pixel position
  ADD A,8                 ; Adjust the collision hit box 8 pixels down towards
                          ; the base of Maroc's sprite, as the objects he's
                          ; touching are supposed to be on the ground
  LD (60114),A            ; ...and re-store as the vertical co-ordinate to
                          ; check
; Check for energy draining items:
  LD C,254                ; Collision type to check against - 254 = energy
                          ; draining objects
  CALL L57293             ; Collision check routine - returns 0 (no collision)
  CP 0                    ; or 1 (collision found) in the A register
  JR Z,L54393_0           ; If no collision, skip to the next check
  LD A,8                  ; Otherwise, set energy drain amount to 8 points of
                          ; energy
  CALL L58316             ; ...and reduce Maroc's energy by this amount
; Check for energy restoring items:
L54393_0:
  LD C,253                ; Collision type to check against - 253 = energy
                          ; restoring objects
  CALL L57293             ; Collision check routine - returns 0 (no collision)
  CP 0                    ; or 1 (collision found) in the A register
  JR Z,L54429             ; If no collision, skip over the next couple of
                          ; instructions
  LD A,254                ; Otherwise, set energy drain amount to -2 (i.e. -2
                          ; drain, so INCREASE energy by 2)
  CALL L58316             ; ...increase Maroc's energy

; Check if Maroc has gone through the portal in room 81
;
; Used by the routine at L54393.
;
; After Maroc places the four elemental symbols on the floor circle (see image)
; in room 81, a portal door appears in the middle of the screen.
;
; This routine uses the collision detection routine at L57293 to check if Maroc
; has gone through the portal doorway which takes him to the High Temple of
; Chaos and a confrontation with Avelach.
;
; Interestingly, Maroc doesn't actually have to create the portal door to get
; to the High Temple of Chaos - there's actually a shortcut...
L54429:
  LD A,(60087)            ; Get room number
  CP 81                   ; Is it room 81?
  JR NZ,L54450            ; If not, skip the following check routine
  LD C,136                ; Collision type to check = 136 - Maroc touching
                          ; portal door
  CALL L57293             ; Collision check routine - returns 0 (no collision)
                          ; or 1 (collision found) in the A register
  CP 0                    ; Collision with portal door?
  JR Z,L54450             ; If not, skip to the next routine
  LD A,82                 ; Set the room number to 82, in the High Temple of
  LD (60080),A            ; Chaos

; Draw Maroc's shadow and flickering barrier for SHIELD, PROTECT and DEFENCE
; spells
;
; Follows previous section (L54429).
;
; * Although Maroc's vertical position varies depending on his movement speed,
;   his shadow remains at a fixed point on the screen (vertical pixel position
;   95)
; * When the SHIELD, PROTECT and DEFENCE spells are active, a flickering shield
;   appears around Maroc
;
; Draw Maroc's shadow:
L54450:
  LD HL,(60100)           ; Graphic address pointer for Maroc's shadow (39095)
  LD A,95                 ; Vertical screen position - 95 pixels from top of
  LD (60114),A            ; playing area
  CALL L56216             ; Draw shadow
; Check for spells that generate a flickering effect
  LD A,(60137)            ; Check currently active effect spell (a positive
                          ; match for any of them jumps to L54450_0)
  CP 2                    ; SHIELD spell active
  JR Z,L54450_0           ;
  CP 11                   ; PROTECT spell active
  JR Z,L54450_0           ;
  CP 18                   ; DEFENCE spell active
  JR Z,L54450_0           ;
; If no matches to the above none of the spells is active. The next check is to
; see if any of the spells have just been deactivated:
; * If the player deactivates any of the above 3 spells, the 'currently active
;   effect spell' byte at 60137 is set to 255
; * This tells this routine to erase any 'barrier' graphics that might be on
;   screen
  CP 255
  JR NZ,L54524            ; If no 255 match, there's no effect spell graphics
                          ; to draw/erase. Jump out of this routine to L54524.
; SHIELD, PROTECT or DEFENCE have been deactivated, so make sure any on-screen
; barrier graphics are removed
  LD A,0
  LD (60137),A            ; Set currently active effect spell to 0 (no spell
                          ; active)
  LD (60111),A            ; Set draw/erase flag to 0 (ERASE)
; Draw/erase the flickering barrier graphics
L54450_0:
  LD A,(60097)            ; Get Maroc's vertical screen position, from top of
                          ; playing area, in pixels
  LD (60114),A            ; ...and copy into working graphic data buffer
  LD HL,(60566)           ; Graphics address pointer for shield barrier
                          ; graphics (39059/43500)
; Work out which graphics frame to use for barrier graphic. Uses the game
; counter at L60074 to alternate frame graphics.
  LD A,(L60074)           ; Get the game counter byte
  AND 1                   ; Check the lowest bit (bit 0) of the game counter (0
                          ; = even, 1 = odd)
  ADD A,A                 ; Multiply by 2 If bit 0 = 0, offset will be 2 x 0 =
                          ; 0, so frame 1 is used.If bit 0 = 1, offset will be
                          ; 2 x 1 = 2, so a +2 offset to the graphics address
                          ; which gives frame 2.
  LD E,A                  ; Put offset into DE register pair
  LD D,0                  ;
  ADD HL,DE               ; ...and add to the base graphic pointer address
                          ; (39059)
  LD (60241),HL           ; Store graphics address pointer to the frame that
                          ; needs drawing
  CALL L56216             ; Draw the barrier graphic on screen
; The barrier graphic is only drawn briefly - in fact, the very next routine
; immediately erases it. This is what creates the flicker effect.
  LD A,0
  LD (60111),A            ; Set draw/erase flag to 0 (ERASE)
  LD HL,(60241)           ; Retrieve address for barrier graphics frame
  CALL L56216             ; ...And erase the graphic

; Move and draw the room's foreground scenery items
;
; Follows previous section at L54450
;
; This routine handles the room's foreground objects - originally set up at
; L50433, and stored in data sets at 32513.
; * Foreground object horizontal position and movement speed is calculated at
;   2x the values of the rest of the on-screen scenery. This produces a
;   parallax scrolling effect.
; * At Maroc's full speed (32 or -32 depending on left/right direction)
;   foreground scenery objects move 16 pixels, other scenery objects move 8
;   pixels
; * Unlike the other room elements, foreground scenery items move in whole
;   character or 2 character steps
; * Foreground scenery horizontal position is stored in 1 character/8-pixel
;   steps, rather than 4-pixel/half-character steps like other items
L54524:
  LD A,(60087)            ; Get room number
  CP 224                  ; Is it a vertical tunnel room ( >= room 224)?
  JP NC,L54994            ; If so, no foreground objects - skip this routine
  LD HL,(60272)           ; Get pointer to foreground scenery room object data
                          ; (32513)
; Copy item set data bytes into various working buffer addresses:
L54524_0:
  LD (60094),HL           ; Store pointer to object data in address pointer
                          ; buffer
  LD A,(HL)               ; First byte of data set
  INC HL                  ;
  CP 255                  ; Is it end-of-data?
  JP Z,L54740             ; If so, skip out of this routine
  LD B,A                  ; Store first byte in B register (used as a counter
                          ; and checked later at L54524_2)
  LD A,(HL)               ; Second byte of data set
  INC HL                  ;
  LD (60231),A            ; Store second byte of set
  LD A,(HL)               ; Get third byte of set - item's horizontal position
  INC HL                  ; in room (in character/8-pixel steps)
  LD (60232),A            ; Store horizontal position for item
  LD A,(HL)               ; Get fourth byte of set
  INC HL                  ;
  LD (60233),A            ; Store byte 4 of set
  LD A,(HL)               ; Get fifth byte of set - item's vertical position
  INC HL                  ; from top of playing area (in pixels)
  LD (60234),A            ; Store vertical position for item
  LD (60114),A            ; Store in second buffer
  LD E,(HL)               ; Get address pointer to item graphics
  INC HL                  ;
  LD D,(HL)               ;
  INC HL                  ;
  LD (60109),DE           ; ...and store in graphic address pointer buffer
; Convert horizontal position from characters to pixels:
  LD HL,(60231)           ; Get horizontal co-ordinate in 8-pixel/character
                          ; steps (high byte = H register the important bit)
  LD D,H                  ; Copy to DE register pair
  LD E,L                  ;
  ADD HL,HL               ; x 2
  SBC A,A                 ; Use the carry flag to identify whether it's a
                          ; negative or positive offset (left/right)
  ADD HL,HL               ; x 4
  RLA                     ; The RLA rotates increase (or decrease if negative)
                          ; the accumulator, and this gives us an idea of which
                          ; screen (i.e. left/right of the current viewport)
                          ; the scenery object is in
  ADD HL,HL               ; x 8
  RLA                     ;
  LD (60116),A            ; ...Store the rotated byte indicating horizontal
                          ; screen/viewport number in current room
  LD A,H                  ; The high byte of HL contains the rest of the
  LD C,A                  ; horizontal position of the object
  LD (60115),A            ; Store it
; Check Maroc's horizontal movement speed/direction and move the foreground
; scenery objects accordingly:
  LD A,(60164)            ; Maroc's horizontal movement speed
  LD L,A                  ; * Negative values = Maroc is moving right (so
                          ;   scenery is moving left)
                          ; * Positive values = Maroc is moving left (so
                          ;   scenery is moving right)
  RLA
  SBC A,A                 ; Using an RLA followed by a SBC means the carry flag
                          ; indicates left/right direction using the H register
                          ; (e.g. 255 = Maroc moving right, 0 = Maroc moving
                          ; left)
  LD H,A                  ; Store this value in the high byte (H), which will
                          ; cause an addition/subtraction in the next
                          ; instructions, depending on left/right direction.
  ADD HL,HL               ; x 2
  ADD HL,HL               ; x 4
  ADD HL,HL               ; x 8
  ADD HL,HL               ; x 16 (this is the extra that moves the foreground
                          ; scenery 2x faster than other room elements)
  ADD HL,DE               ; Add speed offset to horizontal screen position
  LD (60231),HL           ; ...and store
; The high byte (H) of the calculation calculated byte is a character square
; co-ordinate, the low byte (L) containing a fractions/remainder value.
; Multiply by 8 to convert to pixel values.
  ADD HL,HL               ; x 2
  SBC A,A                 ; Use the carry bit to determine whether the offset
                          ; value is negative or positive (depending on
                          ; direction)
  ADD HL,HL               ; x 4
  RLA                     ;
  ADD HL,HL               ; x 8
  RLA                     ;
  LD (60108),A            ; Store the high byte - indicating negative (255) or
                          ; positive (0)
  LD A,H                  ; And the low byte, containing the horizontal pixel
  LD (L60107),A           ; co-ordinate
  CP C                    ; Has the scenery item's horizontal position changed
  JR Z,L54524_1           ; at all?
  INC B                   ; If so, increment a flag in B register
  INC B                   ;
; Check vertical movement speed/direction and move the foreground scenery
; objects accordingly:
L54524_1:
  LD HL,(60233)           ; Get vertical screen pixel co-ordinate
  EX DE,HL                ; Copy into DE register
  LD A,(60165)            ; Get vertical movement speed/direction (negative =
                          ; Maroc moving down, positive = Maroc moving up)
  LD L,0                  ; Clear L register
  SRA A                   ; Divide speed offset by 2...
  RR L                    ; Rotate carry remainder offset into L register
  SRA A                   ; Divide speed offset by 4...
  RR L                    ; Rotate carry remainder offset into L register
  LD H,A                  ;
  ADD HL,DE               ; Add the offset to the vertical pixel position
  LD (60233),HL           ; ...and store new position.
  LD A,H                  ; Has the scenery item's vertical position changed at
  CP D                    ; all?
  JR Z,L54524_2           ;
  INC B                   ; If so, increment a flag in B register
  INC B                   ;
; Check if either horizontal or vertical position has changed - the B register
; has been updated if so:
; * 0 = neither horizontal or vertical position changed
; * 2 = either horizontal or vertical position changed
; * 4 = both horizontal and vertical position changed
L54524_2:
  LD A,B
  CP 2
  JR C,L54524_3           ; Carry here means neither position has changed - no
                          ; need to erase anything so skip the next few
                          ; instructions
; The item has moved, so it'll need erasing at its pre-move position:
  LD A,0                  ; Set draw/erase flag to 0 (ERASE)
  LD (60111),A            ;
  CALL L56737             ; Erase the foreground scenery item
  LD A,(L60107)           ;
  LD (60115),A            ; Copy the item's calculated horizontal (pixel)
  LD A,(60234)            ; screen position into working graphic buffer
  LD (60114),A            ; Copy the item's calculated vertical (pixel) screen
  LD A,(60108)            ; position into working graphic buffer
  LD (60116),A            ; Also copy the horizontal co-ordinate high byte
  JR L54524_4             ;
; Check for item movement again:
L54524_3:
  CP 0
  JR NZ,L54524_4
  LD (60117),A            ; Flag indicating whether (any part of) graphic needs
                          ; drawing on screen - nothing's changed movement-wise
                          ; since last check, so set to zero
  JR L54524_5             ; ...and skip draw routine
; Item needs drawing on screen:
L54524_4:
  LD A,1                  ; Set draw/erase flag to 1 (DRAW)
  LD (60111),A            ;
  CALL L56737             ; Draw the foreground scenery item
; Copy scenery item data into data sets at 32513
L54524_5:
  LD HL,(60094)           ; (Copy of) pointer to scenery item data at 32513
  LD A,(60117)            ; Flag indicating whether (any part of) graphic is
                          ; visible on screen
  LD (HL),A               ; Store in (first byte of) scenery data item
  INC HL                  ;
  LD A,(60231)            ;
  LD (HL),A               ; Put horizontal object position overflow/precision
  INC HL                  ; offset into byte 2 of set
  LD A,(60232)            ;
  LD (HL),A               ; Put horizontal object position into byte 3 of set
  INC HL                  ;
  LD A,(60233)            ;
  LD (HL),A               ; Put vertical object position overflow/precision
  INC HL                  ; offset into byte 4 of set
  LD A,(60234)            ;
  LD (HL),A               ; Put vertical object position into byte 5 of set
  INC HL                  ; Move pointer along to next data set item at 32513
  INC HL                  ;
  INC HL                  ;
  JP L54524_0             ; Continue to deal with (move, erase and draw)
                          ; foreground scenery items
; Next routine is at L54740 (after all foreground scenery items dealt with)

; Re-calculate room event table data sets
;
; Follows setup of foreground scenery objects at L54524.
;
; The room's 'events-to-check' sets at 32691 contain any items in the current
; room that will need checking for events/collisions - for example if the
; servant, or a warlock, is present.
; * This routine decrements the first byte of each set at 32691
; * For each event item set, this byte will be (pre-decrement) either 1 or 2,
;   as items/events are checked twice (e.g. if they've moved on-screen
; * After decrementing this counter, any sets with this byte value of 0 are
;   removed from the set, and any sets with a byte value of 2 (so 1 after
;   decrementing) are moved up the set (the table is dynamic so will shrink as
;   well as grow)
; * Once all sets have been checked/decremented, a value of 255 is put at the
;   start of the next set to indicate the end of the sets
L54740:
  LD HL,(60268)           ; Pointer to room item event data sets at 32691
  LD D,H                  ; Copy into DE register pair - this is the address
  LD E,L                  ; pointer ready for a later set to be copied here
  LD A,(HL)               ; Get first byte of event set
  INC HL                  ; (and move the pointer along)
; This loop DECrements the first byte of each event set by 1:
L54740_0:
  CP 255                  ; Have we reached the end of the event sets?
  JR Z,L54740_3           ; If so, skip out at this point
  DEC A                   ; The first byte for these will be 1 or 2
  JR Z,L54740_2           ; ...So after the DEC, skip the next set of
                          ; instructions if it was 1, as it'll now be zero no
                          ; longer needs checking
; First byte of set (after the decrement) = 1 - it's still not zero, so we need
; to keep this set:
  LD B,4                  ; Copy the DEC'd byte back into the first byte of the
L54740_1:
  LD (DE),A               ; previously stored address
  LD A,(HL)               ; ...followed by the rest of the bytes in the set
  INC DE                  ;
  INC HL                  ;
  DJNZ L54740_1           ;
  JR L54740_0             ; Keep checking sets until all sets dealt with (byte
                          ; value of 255 found)
; First byte of set (after the decrement) = 0 - no need to keep this set, move
; on to the next:
L54740_2:
  INC HL                  ; HL is pointing at the second byte of the set, so
  INC HL                  ; move it along 3...
  INC HL                  ; ...To get to the first byte of the next set
  LD A,(HL)               ;
  INC HL                  ;
  JR L54740_0             ; ...And repeat the check for the next set.
; All event sets now dealt with. Set termination (end-of-data) byte of 255 at
; the start of what would be the next set.
L54740_3:
  LD (DE),A               ; At this instruction, the A register contains 255
                          ; and DE points to the start of the next event data
                          ; set at L54524, so this stores a 255 (end-of-data)
                          ; byte at the start of the next set.
  EX DE,HL                ; Swap DE (start of data sets) back into HL
  LD (60077),HL           ; Store pointer to end of event table (byte 1 of new
                          ; set)
  LD HL,(60274)           ; Retrieve address pointer for the end of the room
                          ; element data sets at 31744
  LD (60094),HL           ; Copy to data buffer
; The following routine (L54782) determines if any creatures should enter
; Maroc's current room.

; Prepare data for any creatures that are entering Maroc's room
;
; For a creature entering the room - sets up graphics and determines its
; speed/direction of movement.
L54782:
  LD A,(60343)            ; Creature type (see 60230)
  CP 0                    ;
  JR Z,L54842             ; If no creature, skip to the next routine
  CALL L57706             ; This routine sets up data for creatures/warlocks
                          ; appearing in Maroc's room (the A register normally
                          ; contains creature type/number from 60230)
  LD A,(60344)            ; Creature's horizontal position (in 4 pixel steps)
                          ; in room, after entering through a door
  LD (60232),A            ; Copy to graphic data buffer
  LD C,A                  ;
  LD A,(60345)            ; Creature's vertical pixel position in room, after
                          ; entering through a door
  SUB 14                  ; Adjust slightly by moving vertical position up 14
                          ; pixels. This puts the creatures in the doorway
                          ; itself when they appear, rather than looking as if
                          ; they've appeared a couple of feet into the room
  LD (60234),A            ; Copy to graphic data buffer
; Calculate which area of the room (left, right or back wall door) the creature
; is entering from, and set their speed/direction accordingly:
  LD DE,4                 ; If the forthcoming checks don't hit a match, the
                          ; creature is between the room floor/wall connectors,
                          ; so entering through a BACK WALL DOOR
  LD A,C                  ; (Superfluous instruction, as this value is
                          ; immediately overwritten in next one)
  LD A,(60155)            ; Left room corner section - floor/wall connector -
                          ; graphic's horizontal position, in half character
                          ; squares (4 pixel steps)
  CP C                    ; Compare with creature's horizontal position (also
  JR C,L54782_0           ; in 4 pixel steps)
  LD DE,1024              ; Creature is to the left of the room's left
  JR L54782_1             ; connector, so entering through a LEFT WALL DOOR
L54782_0:
  LD A,(60156)            ; Right wall corner section - floor/wall connector -
                          ; graphic's horizontal position, in half character
                          ; squares (4 pixel steps)
  CP C                    ; Compare with creature's horizontal position (also
  JR NC,L54782_1          ; in 4 pixel steps) in room
  LD DE,64512             ; Creature is to the right or the room's right
                          ; (wall/floor) connector graphics - so entering
                          ; through a RIGHT WALL DOOR
; The result in the DE registers is used to set the creature's horizontal
; (60236) and vertical (60237) speed/direction
; * Back wall door: E (vertical) = +4, D (horizontal) = 0
; * Left wall door: E (vertical) = 0, D (horizontal) = +4
; * Right wall door: E (vertical) = 0, D (horizontal) = -4 (252)
L54782_1:
  LD A,D
  LD (60236),A            ; Horizontal speed/direction
  LD A,E                  ;
  LD (60237),A            ; Vertical speed/direction
  JP L54983               ;

; Gradual energy drain/restore for Maroc's ongoing effect spells
;
; Used by the routine at L54782.
;
; The following spells have a 'trickle' drain/heal effect on Maroc's energy
; while they're in effect:
;
; +------------+------------------+
; | Spell      | Effect on energy |
; +------------+------------------+
; | SHIELD     | -1               |
; | UNSEEN     | -1               |
; | PROTECT    | -1               |
; | AMULET     | -1               |
; | DEFENCE    | -1               |
; | WRAITHBANE | -4               |
; | CHALICE    | +5               |
; +------------+------------------+
;
; Each 'trickle' of drain/restore takes place every 16 game cycles:
L54842:
  LD A,(L60074)           ; Incrementing game counter
  LD C,A                  ; (This instruction/C register not needed)
  AND 15                  ; Check if any of bits 0-3 are set
  CP 0                    ;
  JR NZ,L54865            ; If so, don't do anything but instead skip to next
                          ; routine
; Every 16th game cycle:
  LD A,(60137)            ; Currently active 'effect' spell
  CP 0                    ;
  JR Z,L54865             ; If no active effect spells, jump to next routine
  LD A,(60373)            ; Ongoing effect spell - amount of energy to
                          ; drain/heal (see table)
  CALL L58316             ; Increase/decrease Maroc's energy accordingly

; Determine whether a warlock should materialize in the room
;
; Used by the routine at L54842.
;
; A warlock can appear in the room:
; * After a certain time, based on a slowly decrementing counter byte at 60340
;   along with a pseudo-random adjustment
; * As long as there aren't already 3 creatures in the room
; * On levels 1-7 (based on room numbers in the table at L50852)
;
; No warlock appears on level 8 (Chambers of Chaos). On level 9 (High Temple of
; Chaos), DEMONS materialize in rooms instead of warlocks.
L54865:
  LD A,(60105)            ; Get the current level text number (1-9) -
                          ; calculated from lookup table at L50852
  LD B,A                  ; Store in B register
; There are only 7 warlocks, so we need to do something for levels 8 and 9
  CP 8                    ; Are we in the Chambers of Chaos (level 8)?
  JP Z,L54983_0           ; If so there's no warlock on this level - jump to
                          ; the end of this check routine
  CP 9                    ; Are we in the High Temple of Chaos (level 9)?
  JR Z,L54948             ; If so, jump out and generate a DEMON instead of a
                          ; WARLOCK
  LD A,(L60074)           ; Game cycle timer
  AND 63                  ; Check bits 0-5 (values = 0-63)
  JP NZ,L54983_0          ;
; Every 64 game cycles, reduce the timer counter for a warlock appearing in the
; room
  LD A,(60340)            ; Get warlock appearance timer
  DEC A                   ; Decrement it
  LD (60340),A            ; ...and re-store
  LD C,A                  ;
  CALL L56070             ; Run pseudo-random number generator to produce a
                          ; random number (returned in A register)
  CP C                    ; Compare it against the warlock appearance timer
  JR C,L54983_0           ; If random number < warlock timer, jump out here
  LD A,(L60333)           ; Random number > warlock timer. Get byte 6 of
  CP 0                    ; warlock data set
  JR NZ,L54983_0          ; If this byte isn't 0, there's already a warlock so
                          ; we can jump out at this point

; Prepare a warlock to appear in the room
;
; B Warlock number (1-7) - calculated from lookup table at L50852
;
; The previous routine has determined that it's time for a warlock to appear in
; the room.
;
; As long as this level's warlock hasn't been destroyed, the routine sets the
; warlock's screen position, movement direction, and speed.
L54907:
  LD A,B                  ; Get warlock number (between 1 and 7 from table at
                          ; L27772)
  CALL L57706             ; Set up warlock data in working buffer at L60227
  LD HL,60150             ; Get address holding the room's vertical pixel
                          ; position
  INC HL                  ; Held in next (high) byte, so advance one address
  LD A,(HL)               ; Get the room position byte (top of room)
  ADD A,28                ; Add 28 pixels - the warlock's vertical position
                          ; remains the same, even as it floats across the
                          ; screen between the side and back walls
  LD (60234),A            ; Store this value as the warlock's vertical pixel
                          ; position
; Determine warlock's (horizontal) speed and direction. Values can be between
; -3 and +4. A value of 0 means the warlock stays in one place.
  AND 7                   ; The A register contains the vertical room pixel
                          ; position, used here to provide the variety for the
                          ; warlock's movement. Keep bits 0-2 (values 0-7)
  SUB 3                   ; Subtract 3, to give a possible values of -3 to +4
                          ; (negative numbers = left, positive numbers = right)
  LD (60236),A            ; Store as warlock's (horizontal) speed (and
                          ; direction)
  LD HL,(60228)           ; Address pointer to this warlock's data set (at
  INC HL                  ; L27772)
  LD A,(HL)               ; Get the second byte of the warlock's data set
  CP 0                    ;
  JR NZ,L54983_0          ; The second byte tells us if the warlock is still
                          ; alive on this level. If this byte ISN'T 0, it means
                          ; Maroc has destroyed it, so jump out of the routine
                          ; here if this is the case
  INC HL                  ; Move the address pointer along to the sixth byte of
  INC HL                  ; the warlock's data set.
  INC HL                  ;
  INC HL                  ;
  LD A,(HL)               ; This is this warlock's "aggression" stat, which
                          ; affects- the likelihood of it appearing- the
                          ; frequency of missiles being fired
  LD (L60333),A           ; Store in warlock active data buffer
  JP L54960               ;

; Generate a DEMON in the room in the High Temple of Chaos
;
; Used by the routine at L54865.
;
; Warlocks materialize in levels 1-7 (see table at L50852). On level 9 (High
; Temple of Chaos), DEMONS materialize in the rooms instead.
; * Demons are the strongest creatures in the game and do a LOT of damage (see
;   Reference - Creatures).
; * If Maroc enters a room containing a demon, his FREEZE spell gets disabled
;   (if active)
; * Maroc can destroy demons using CALIBURN. However, upon exit and re-entry to
;   a room, the demon will re-spawn
; * Because demons respawn, Maroc is given points towards his rank on
;   destroying his first demon, but no more points for destroying subsequent
;   ones
; * The AMULET spell is the only shield/barrier spell that will deflect a
;   demon's missiles/bolts
; * Demons are subject to the 3-creature-per-room limit. In the penultimate
;   room (room 211 - see 27742) There are initially too many creatures for this
;   room's demon to appear.
L54948:
  LD A,(60146)            ; Flag indicating a warlock, or demon, has been
  CP 0                    ; generated in the room (1 = generated/present, 0 =
                          ; not generated/present)
  JR NZ,L54983_0          ; If a demon has already been generated, don't
                          ; generate a new one, though if Maroc leaves and
                          ; re-enters a room one can be generated again.
  LD A,12                 ; Creature type = 12 (demon)
  CALL L57706             ; Set up creature data (e.g. screen position) in data
                          ; buffer at L60227

; Initialize the appearance of a warlock or a demon
;
; Follows previous routine for demon at L54948, or jump from end of warlock
; initialization at 54945.
L54960:
  LD A,%10000101          ; Set:
                          ; * bit 0 - creature is on-screen
                          ; * bit 2 - creature graphic will need erasing
                          ; * bit 7 - indicates trigger for warlock/demon
                          ;   appearance after the materialization routine has
                          ;   finished
  LD (60238),A            ; Store as creature's properties byte
  LD A,1                  ;
  LD (60240),A            ; Graphic frame number offset (= no offset - start at
                          ; animation frame 1)
  LD (60146),A            ; Set the warlock/demon appearance flag to 1 (to stop
                          ; any more being generated)
  LD A,91                 ; Graphic number for start of materialization effect
                          ; (offset for graphics address pointer 39031)
  CALL L57538             ; Set up graphics
; If Maroc enters a room containing a demon, Maroc's freeze spell is negated.
; This is possibly to make the High Temple of Chaos slightly more challenging
; when navigating the final few rooms.
;
; The materialization of a warlock in a room also negates Maroc's freeze spell.
  LD A,0                  ; Set the FREEZE spell timer to zero
  LD (60572),A            ;

; Copy creature, demon or warlock data to room data sets
;
; Follows warlock/demon initialization at L54960, or creature initialization at
; L54782.
L54983:
  CALL L57520             ; Copy creature data set from the working buffer at
                          ; L60227 to room item data sets at 31744
  LD (HL),255             ; Put an end-of-data-set marker at the start of the
  LD (60274),HL           ; next data set
; This entry point is used by the routines at L54865, L54907 and L54948.
L54983_0:
  JP L55188               ; Jump to the next routine - missile checks

; Tunnel section - Generate and prepare tunnel items
;
; Used by the routine at L54524.
;
; This routine uses the cyclical game timer at L60074 to generate the left and
; right walls of the tunnel.
L54994:
  LD A,0                  ; Reset current horizontal & vertical speeds back to
  LD (60237),A            ; zero
  LD (60236),A            ;
  LD A,(L60074)           ; Game timer
  LD C,A                  ;
  AND 1                   ; Every other game timer frame, decide whether to
  JP NZ,L55068            ; generate a left/right tunnel boundary wall
  LD A,(60286)            ; Incremental tunnel counter
  INC A                   ; Add 1
  CP 20                   ; Check if >=20 (this determines the limit to how
                          ; many boundary wall sections can be generated on
                          ; screen)
  JP NC,L55188            ; If it's >=20, skip out of this routine. The most
                          ; that will realistically fit on screen is 10, so
                          ; this limit shouldn't normally be reached.
  LD (60286),A            ; Counter is <20. Restore incremented counter
; Use the game timer to create left/right tunnel border sections:
  LD A,C                  ; Retrieve game timer
  AND 2                   ; Check bit 2 - 50/50 set/unset. Will go in a
                          ; sequence of 11-00-11-00-11
  JR Z,L54994_0           ; The 50/50 is used to create either a left-hand or
                          ; right-hand tunnel boundary graphic. In this
                          ; sequence this creates a 'staggered' effect for the
                          ; tunnel walls.
; Right tunnel boundary wall:
  LD A,1                  ; Graphic offset = 1 (no offset - use graphic at
                          ; L41114)
  LD C,16                 ; Horizontal movement speed/direction = +16 (moving
                          ; right)
  LD E,4                  ; Horizontal movement position offset - in
  JR L54994_1             ; half-character/4-pixel steps (2 character squares
                          ; to the right)
; Left tunnel boundary wall:
L54994_0:
  LD A,2                  ; Graphic offset = 2 (a mirrored version of the
                          ; tunnel graphic at L41114 will be created and the
                          ; graphics address stored at 38929)
  LD C,240                ; Horizontal movement speed/direction = -16 (moving
                          ; left)
  LD E,252                ; Horizontal movement position offset - in
                          ; half-character/4-pixel steps (2 character squares
                          ; to the left)
; Store calculated boundary attributes:
L54994_1:
  LD (60230),A            ; 1 = Right boundary, 2 = Left boundary (mirror
                          ; version)
  LD (60240),A            ; Graphic frame offset (1 = no offset or 2 =
                          ; mirrored)
  LD A,14                 ; Graphic type = Tunnel object
  LD (L60227),A           ;
  LD A,C                  ; Retrieve horizontal position/movement offset
  LD (60236),A            ; ...and store
  LD A,(60574)            ; Get horizontal graphic position (in
                          ; 4-pixel/half-character steps)
  ADD A,E                 ; Add the offset (+ or - 2 character squares)
  LD (60232),A            ; ...and store as graphic's horizontal screen
                          ; position
  LD A,39                 ; Graphic number for tunnel boundary graphic address
                          ; pointer at 38927
  JR L55088_1             ; Set up the tunnel wall graphic

; Tunnel section - Run game timer and randomly generate creatures
;
; Used by the routine at L54994.
;
; Jump from 55008 if no new tunnel wall has been generated during this
; particular game cycle.
;
; Every 8 game cycles, there's a chance of a creature appearing.
L55068:
  LD A,(L60074)           ; Get the game timer
  INC A                   ; Increment it
  AND 7                   ; Check bits 0-2 (values 0-7)
  JR NZ,L55188            ;
; Executed after 8 game timer cycles. Combined with a pseudo-random number,
; this affects the likelihood interval of a creature (spider/bat) appearing in
; the tunnel.
; * The room number is one of the variables in this calculation
; * There's a slightly lower chance of creatures appearing in higher numbered
;   tunnel rooms
; * The room tunnel numbers (L26384) start high and decrease for deeper levels
;   within the game - e.g. interconnecting tunnel room numbers within the
;   Gatehouse Level are 251-255
; * This means Maroc will tend to encounter more creatures within Avalon's
;   deeper tunnels
  CALL L56070             ; Generate pseudo-random number in A register
  LD C,A                  ; Store in C register
  LD A,(60087)            ; Get room number
  SUB 48                  ; Because tunnels are rooms 224-255, this will result
                          ; in a value somewhere in the 176-207 range
  CP C                    ; Is this value greater than the random number?
  JR NC,L55188            ; If so, jump out of here If not, continue to the
                          ; next routine to generate a SPIDER or a BAT

; Tunnel section - Generate a SPIDER or BAT encounter
;
; C Pseudo-random number generated (L56070) in previous routine
;
; The previous routine has decided to generate a creature in the tunnel.
;
; First check that there aren't already too many creatures (3). If not,
; generate one (50/50 chance of SPIDER/BAT):
L55088:
  LD A,(60573)            ; Number of creatures currently on-screen in the
                          ; tunnel
  INC A                   ; Increase by 1
  CP 3                    ; There's a limit of 3 creatures on-screen
  JR NC,L55188            ; If adding this creature would make it 4, skip the
                          ; routine.
; It's OK to generate a creature:
  LD (60573),A            ; It's < 3 creatures. Store the creature count byte
  LD A,14                 ; Item type #14 designates a tunnel object - boundary
  LD (L60227),A           ; wall, bat or spider (creatures are later
                          ; differentiated from walls using the byte at stored
                          ; 60230)
  LD A,1                  ; Starting frame offset (no offset)
  LD (60240),A            ;
; Randomize starting position of creature in relation to tunnel wall:
  LD A,C                  ; Retrieve random number generated earlier
  AND 15                  ; Keep bits 0-4 (values = 0-15)
  SUB 7                   ; Subtract 7 (value range now between -7 and +8)
  LD B,A                  ; Store in B register
  LD A,(60574)            ; Get tunnel horizontal position
  ADD A,B                 ; Add the random offset calculated earlier (-7 to +8)
  LD (60232),A            ; Store as graphic's horizontal position (in half
                          ; character/4-pixel steps)
  LD B,A                  ; Put in B register
; Determine whether the creature will be a SPIDER or a BAT:
  LD A,C                  ; Retrieve random number
  AND 1                   ; Check bit 1 for 0 or 1 (50/50) - to run one of the
  JR Z,L55088_0           ; next two sections.
; Generate a SPIDER
  LD A,4                  ; Creature type = 4
  LD (60230),A            ;
  LD A,(60574)            ; Horizontal tunnel wall position
                          ; (half-character/4-pixel steps)
  SUB B                   ; Subtract the graphic's horizontal position
                          ; calculated earlier
  ADD A,A                 ; ...Double it...
  LD (60236),A            ; ...and store as position (movement) offset
  LD A,125                ; Graphic number for spider graphic address at 39099
  JR L55088_1             ;
; Generate a BAT
L55088_0:
  LD A,8                  ; Creature type = 8
  LD (60230),A            ;
  LD A,C                  ; Retrieve random number generated earlier
  AND 127                 ; Filter out bit 7, giving a random number in the
                          ; range of 0-127
  SUB 63                  ; ...And subtract 63, giving a random number in the
                          ; range of -63 to +64
  LD (60236),A            ; Store as horizontal position (movement)
                          ; speed/offset
  LD A,36                 ; Set vertical position (movement) speed/offset (36
  LD (60237),A            ; pixels). This will cause the bat to start by moving
                          ; quickly down the screen.
  LD A,127                ; Graphic number for bat graphic address at 39103
; Set up creature graphic
L55088_1:
  LD C,A                  ; Temporarily store the graphic number in C register
  LD A,254                ; Tunnel item identifier (boundary wall, bat or
  LD (60235),A            ; spider) - ends up in byte 9 of data set at 31744
  LD A,8                  ; Set vertical position (8 pixels from top of screen)
  LD (60234),A            ;
  LD A,C                  ; Retrieve graphic number
  CALL L57538             ; Set up the graphics
  CALL L57520             ; ...and copy into room data set at 31744
  LD (HL),255             ; Set end-of-data marker at start of next data set
  LD (60274),HL           ; ...And store the address pointer to it.

; Check for any fired missiles/bolts
;
; Used by the routines at L54983, L54994, L55068 and L55088.
;
; Checking if:
; * a creature has fired a missile at Maroc, or
; * Maroc has fired a missile.
;
; Only one creature missile and one Maroc-fired missile (i.e. 2 missiles total)
; can be on-screen at any one time.
L55188:
  LD A,0
  LD (60116),A            ; Indicates screen/viewport - 0 = current
  LD A,5                  ; screen/viewport
  LD (60314),A            ; Pre-set the missile type. 5 = missile fired at
                          ; Maroc by creatures (rather than vice versa)
; Check if a missile/bolt has been set up (and if not, set it up):
  LD A,(60307)            ; Get missile number (table at L27868)
  CP 0                    ;
  JR Z,L55188_0           ; 0 = no missile present
  CALL L56095             ; If not zero, set up this missile set data
  LD A,0                  ; Missile has now been set up and stored in the data
  LD (60307),A            ; sets at 31744, so can now set the missile number to
                          ; zero
; Check if Maroc has launched a missile spell:
L55188_0:
  LD A,(60568)            ; This byte contains an 'action' byte set when Maroc
                          ; presses fire after aiming his missile-based spell
                          ; cursor, and contains values for the different
                          ; missile spells
  CP 0                    ; If zero, Maroc hasn't fired a missile spell - skip
  JR Z,L55283             ; next section
; Maroc has launched a missile-type spell. Calculate trajectory of missile:
  LD A,(60306)            ; Flag indicating if Maroc has fired a missile (1 =
  CP 0                    ; missile fired, 0 = no missile)
  JR NZ,L55188_1          ; If there's already one, skip the setup
  INC A                   ; Increment so the flag = 1 (missile fired)
  LD (60306),A            ; ...and re-store.
  LD A,0                  ; Precision/overflow byte for horizontal/vertical
  LD (60308),A            ; item position (reset both to 0)
  LD (60310),A            ;
  LD A,(60096)            ; Maroc's horizontal (X-axis) screen position
  LD (60309),A            ; Set this as the missile's horizontal (X)
                          ; co-ordinate origin
  LD A,(60097)            ; Maroc's vertical (Y-axis) screen position
  LD (60311),A            ; Set this as the missile's vertical (Y) co-ordinate
                          ; origin
  LD A,(60159)            ; Get the vertical (Y) pixel position of the aiming
                          ; cursor
  LD (60313),A            ; Store as the target vertical pixel (Y) co-ordinate
                          ; for the missile
  LD A,(60160)            ; Get the horizontal (X) pixel position of the aiming
                          ; cursor
  RRA                     ; This value is currently in pixel steps, so divide
  RRA                     ; by 4 to get into 4-pixel (half-character steps)
  AND 63                  ; Filter out any unnecessary carry bits
  LD (60312),A            ; ...and store
  LD A,8                  ; Item/missile type = 8 (missile fired by Maroc)
  LD (60314),A            ; Store in missile data set
  LD A,(60568)            ;
  CALL L56095             ; Set up missile data
L55188_1:
  LD A,0                  ; This is the action byte set when Maroc presses fire
                          ; after aiming his missile-based spell cursor -
                          ; contains values for the different missile spells
  LD (60568),A            ; Now that the missile has been initialized, set this
                          ; flag to 0.

; Check which spell has been cast
;
; Follows the previous routine at L55188.
;
; Check which (if any) spell, or spell type, has been cast/activated (rather
; than merely selected) - using spell number - from the spells list at L28156
; and stored at 60140.
L55283:
  LD A,(60140)
  CP 0                    ; No spell cast, or MOVE spell in effect
  JP Z,L55553             ;
  CP 1                    ; SERVANT spell
  JR Z,L55347             ;
  CP 8                    ; HAIL spell
  JP Z,L55502             ;
  CP 12                   ; WAYSTONE spell
  JP Z,L55502_0           ;
  CP 16                   ; FREEZE spell
  JP Z,L55502_1           ;
  CP 17                   ; SUMMON spell
  JP Z,L55502_2           ;
  CP 19                   ; PORTAL spell
  JP Z,L55502_3           ;
; Maroc has cast some other spell:
  LD A,(60359)            ; Check the type of spell cast
  CP 2                    ; Spell type 2 = spell that generates a controllable
                          ; graphic, e.g. SERVANT, MISSILE, OPEN
  JP NZ,L55553            ; If not one of these spell types, skip out of this
                          ; routine for other checks
; Spell has been cast that involves a controllable cursor:
; * Bit 7 of the spell info byte at 60362, if set, tells us this is a
;   missile/bolt aiming cursor
; * If not set, it's a spell whose cursor position will need checking for room
;   events/collisions (SERVANT, OPEN, REVEAL etc.)
  LD A,(60362)            ; Get byte indicating spell cursor type
  CP 0                    ; If not active, can skip to next routine
  JP Z,L55553             ;
  LD C,A                  ; Otherwise, temp store this value in the C register
  AND 128                 ; Bit 7 of this byte is set for bolt spells (MISSILE,
  CP 0                    ; FIREBALL etc.)
  JP Z,L55474             ; If NOT set, it's another sort of aiming cursor, so
                          ; can jump out here and deal with this spell's
                          ; potential event/collision actions
  JP L55553               ; If set, it's a bolt/missile type spell, fine to
                          ; jump out of this routine

; SERVANT spell - check for retrieval of object from Maroc's backpack
;
; Used by the routine at L55283.
;
; Player is using the SERVANT spell.
; * Check if the servant is moving over Maroc's backpack area
; * If so, identify the item to retrieve, and set up a new room item in the
;   data sets at 31744
L55347:
  LD A,(60337)            ; Servant object-carrying status flag
  CP 0                    ;
  JP NZ,L55474_0          ; If this byte ISN'T 0, the servant is carrying an
                          ; object - if so, jump to the end of this routine.
; Check if the servant is over Maroc's sprite (for retrieving objects from his
; backpack)
  LD A,(60160)            ; Horizontal (X) position (in pixels) for servant
                          ; sprite
  LD D,A                  ; Store in D register
  LD A,(60159)            ; Vertical (Y) position (in pixels) for servant
                          ; sprite
  LD E,A                  ; Store in E register ready for collision call in 2
                          ; instructions
  LD C,0                  ; Collision/event flag to check - 0 = check collision
                          ; with Maroc sprite
  CALL L57293_0           ; Check if servant sprite is moving over Maroc
  CP 0                    ; Flag in A register indicates if collision has
                          ; occurred (1 = positive collision, 0 = no collision)
  JR Z,L55474             ; If not (servant is not moving over Maroc) skip the
                          ; next few sets of instructions
; Servant is moving over Maroc. Check object sets in Maroc's backpack inventory
; at 32626
  LD DE,16                ; 16 bytes in each inventory object data set
  LD B,4                  ; 4 object slots in Maroc's inventory to check
  LD HL,(60348)           ; Get address pointer for Maroc's inventory at 32626
L55347_0:
  LD A,(HL)               ; Get first data byte of this set
  CP 0                    ; First byte will be: 0 = Empty slot, or 4 =
                          ; Interactable object
  JR NZ,L55347_2          ; Object found - step out of check routine and deal
                          ; with object
  ADD HL,DE               ; No object in this slot - advance address pointer 16
                          ; bytes to get to next item slot
  LD A,(HL)               ; Check if at end of inventory slots
  CP 255                  ;
  JR NZ,L55347_1          ; ...If not, keep checking inventory slots
  LD HL,(L60346)          ; ...If so, restore the address pointer to the first
                          ; slot and continue checking. Objects rotate round so
                          ; the check doesn't end at slot 4, but only when 4
                          ; slots are checked - e.g. the check may have started
                          ; with slot 3.
L55347_1:
  DJNZ L55347_0           ; Repeat until all 4 inventory slots have been
                          ; checked
  JR L55474_0             ; Maroc is not carrying anything - jump out to next
                          ; routine
; Item found in inventory. Copy item data from inventory slot at 32626 into
; object data buffer at L60227
L55347_2:
  LD BC,16                ; 16 bytes to copy
  LD DE,L60227            ; Start of working data buffer at L60227.
  LDIR                    ; Copy the 16 bytes over (HL is currently pointing at
                          ; the start of the inventory slot where the item's
                          ; data resides)
  LD DE,65520             ; Subtracts 16 from HL to return the address pointer
  ADD HL,DE               ; to the start of this object's inventory slot at
                          ; 32626
  LD (HL),0               ; As the servant has removed the object from Maroc's
                          ; backpack, it's no longer in his inventory, so set
                          ; the first byte of the inventory slot to zero
; The next routine initializes the object's data (including X/Y screen
; co-ordinates) based on the servant sprite's X/Y position
;
; An item set is then created at 31744, and the working data buffer is copied
; into this set.
  LD A,(60238)            ; Object properties byte
  OR %01010101            ; Set:
                          ; * bit 0 (1) = item visible on-screen
                          ; * bit 2 (4) = item will need erasing
                          ; * bit 4 (16) = item is being carried by servant
                          ; * bit 6 (64) = item is portable
  AND %11110101           ; Reset bits 1 (2) = item is hidden and 3 (8) = item
                          ; is dropped/falling
  LD (60238),A            ; ...and re-store
  LD A,(60160)            ; Horizontal (X) position (in pixels) for servant
  LD L,0                  ; sprite
; Set object's horizontal position. This is in 4-pixel/half-character steps, so
; calculate this position by dividing the servant's horizontal pixel position
; by 4:
  RRA                     ; Divide by 2
  RR L                    ; Rotate fraction/overflow bit into low byte of
                          ; horizontal position address
  RRA                     ; Divide by 4
  RR L                    ; Rotate fraction/overflow bit into low byte of
                          ; horizontal position address
  AND 63                  ; Filter out any stray carry bits from the rotate
  LD H,A                  ;
  LD (60231),HL           ; Store calculated horizontal position
; Set object's vertical pixel position (same as servant's position):
  LD A,(60159)            ; Vertical (Y) position (in pixels) for servant
                          ; sprite
  LD (60234),A            ; ...copy into object's data buffer
; Other object values:
  LD A,0                  ; Set vertical movement speed/direction to 0
  LD (60237),A            ;
  LD (60236),A            ; Set horizontal movement speed/direction to 0
  LD (60233),A            ; Reset vertical pixel position fraction byte (will
                          ; be 0 at this point as servant is on-screen)
  CALL L56028             ; Identify object state and prepare graphics for
                          ; printing
  CALL L57520             ; Copy object data into data set at 31744
  LD (HL),255             ; Set end-of-data byte at the start of the next data
                          ; set
  LD (60274),HL           ; ...and store the address pointer
  LD A,2                  ; Servant-carrying-object flag. Normally set to 1 if
  LD (60337),A            ; carrying an object, but set to 2 here until the
                          ; servant moves out of Maroc's backpack 'hit box'
                          ; area Otherwise inventory items would
                          ; continuously/quickly cycle through the slots,
                          ; swapping objects
  JR L55474_0             ; Skip to end of next routine

; Set up active spell-based room event checks
;
; Used by the routines at L55283 and L55347.
;
; Follows previous SERVANT routine - these instructions are run if the servant
; ISN'T moving over Maroc, and ISN'T holding an object.
;
; In this state, the servant sprite needs to be open to room event checks (e.g.
; picking up/manipulating objects). So this routine creates an entry in the
; room's event checks data table at 32691.
;
; There's also a jump here from the routine at 55341, which relates to other
; cast spells that involve the controllable cursor (e.g. OPEN, FIND, REVEAL)
; that aren't missile-related. These spells will also need an event check to be
; added to the room event check table, as they take effect when they're moved
; over specific room items.
L55474:
  LD HL,(60077)           ; Address pointer to room item event data at 32691
  LD (HL),1               ; Set the first byte of the set to 1, which means the
  INC HL                  ; event will be checked for 1 game cycle (this is
                          ; partly in case items are moving around).
  LD A,(60362)            ; Action/event value associated with this spell (e.g.
                          ; SERVANT, OPEN) is active
  LD (HL),A               ; Store as byte 2 of set
  INC HL                  ;
  LD A,(60160)            ; Servant sprite horizontal (X) co-ordinate in pixels
  LD (HL),A               ; Store as byte 3 of set
  INC HL                  ;
  LD A,(60159)            ; Servant sprite horizontal (Y) co-ordinate in pixels
  LD (HL),A               ; Store as byte 4 of set
  INC HL                  ; Move along to the start of the next data set
  LD (60077),HL           ; Store the address pointer to the start of the next
                          ; event data set at 32691
  LD (HL),255             ; Set an end-of-data marker
; Jump from previous routine if there aren't any events to check. For example,
; the servant can't manipulate other room objects if it's already carrying an
; object (the event check in this case is object 1 on object 2).
L55474_0:
  JR L55553

; HAIL, WAYSTONE, FREEZE, SUMMON or PORTAL spell cast
;
; Used by the routine at L55283.
;
; The HAIL spell summons a warlock to Maroc's room
L55502:
  LD A,8                  ; Timer indicating how long before a creature is
                          ; likely to wander in from an adjacent room
  LD (60340),A            ; Set this to 8 will cause a warlock to appear within
                          ; a few seconds
  JR L55553               ; ...and skip out to the next routine
; WAYSTONE spell cast
;
; This spell immediately teleports Maroc to the next room - i.e. his current
; room number plus one
L55502_0:
  LD A,(60087)            ; Get room number
  INC A                   ; +1
  CP 224                  ; It's assumed 223 was originally earmarked to be the
                          ; final 'standard' room (as mentioned on the inlay -
                          ; see Reference: Inlay - back cover) - with tunnel
                          ; room numbers starting from 224. However, the final
                          ; (standard) room number is 212, with 213 onwards
                          ; unused.
  JR NC,L55553            ; This would've been a check to make sure Maroc
                          ; hasn't teleported from (standard) room 223 to
                          ; tunnel room 224, but isn't really needed.
  LD (60080),A            ; Store new room number
  JR L55553               ; ...and skip out to the next routine
; FREEZE spell cast
;
; This spell stops all creatures in their tracks for a short time. It gives
; time for Maroc to perform actions without being harrassed. However, frozen
; creatures:
; * can still fire missile at Maroc while they're on screen
; * can still pursue - see Bugs - Frozen creatures can follow Maroc between
;   rooms
L55502_1:
  LD A,255                ; Set the FREEZE spell timer counter to 255
  LD (60572),A            ; (temporarily stops all creature movement)
  JR L55553               ; ...and skip out to the next routine
; SUMMON spell cast
;
; This spell immediately teleports Maroc to room 61 in the Chambers of Chaos.
L55502_2:
  LD A,61                 ; Set room number to 61
  LD (60080),A            ;
  JR L55553               ; ...and skip out to the next routine
; PORTAL spell cast
;
; This spell initially teleports Maroc to room number 128, in the Mines of
; Madness.
;
; If Maroc's (pre-teleport) room number is greater than this, this room
; replaces room 128 as as the base teleport location, ready for when the next
; time the spell is cast.
;
; It lets the player fast travel between deeper game levels.
L55502_3:
  LD A,(60087)            ; Get room number
  LD C,A                  ; Temp store in C register
  LD A,(60571)            ; Get room number to teleport to (initialized at 128)
  LD (60080),A            ; ...and store as room number
  CP C                    ; Is current room number >= the room to teleport to?
  JR NC,L55553            ;
  LD A,C                  ; If so, store current room number as the new
  LD (60571),A            ; teleport point

; Check/decrement the FREEZE spell timer counter if active
;
; Used by the routines at L55283, L55474 and L55502.
;
; Countdown timer to the end of the FREEZE spell - set to 255 when Maroc casts
; the spell at L55502_1.
L55553:
  LD A,(60572)            ; FREEZE spell timer counter
  CP 0                    ;
  JR Z,L55564             ;
  DEC A                   ; If it's >0, the spell is active, so decrement the
                          ; timer counter..
  LD (60572),A            ; ...and re-store.

; Check if Maroc is carrying too many objects
;
; Used by the routine at L55553.
;
; If Maroc collects a 4th object, either by moving over it or being given it by
; the servant, then he will automatically drop the next item in his inventory,
; as he can only carry 3.
;
; After picking up a new object, the first byte of the next inventory slot is
; checked. If each (i.e. the 4th out of 4) slot contains a value of 4
; (interactable object), Maroc has too many - he will drop this object being
; pointed at.
L55564:
  LD HL,(60348)           ; Get address pointer for Maroc's inventory at 32626
  LD A,(HL)               ; Get first data byte of this set
  CP 0                    ; This byte will be: 0 = Empty slot, or 4 =
                          ; Interactable object
  JR Z,L55616             ; If it's 0, it's fine - jump to the next routine
; Maroc is carrying too many objects - drop the next one in the inventory
; slots:
;
; First, copy the inventory item's data into the working data buffer:
  LD DE,L60227            ; Pointer to start of item working data buffer
  LD BC,16                ; 16 bytes
  LDIR                    ; Copy the item data
  LD HL,(60348)           ; Get the first byte of the inventory data set for
                          ; the item-about-to-be-dropped
; Marked the item as dropped:
  LD (HL),0               ; Set the value as 0 as Maroc no longer has it
  LD A,(60238)            ; Get the item properties byte
  OR %01001101            ; Set bit 0 (item is visible), bit 2 (item needs
                          ; erasing before re-drawing), bit 3 (item is falling)
                          ; and bit 6 (item can be carried)
  AND %11101101           ; Keep any other bits from the properties byte,
                          ; resetting bit 1 (to indicate the item is not
                          ; hidden) and 4 (to indicate the item is not being
                          ; carried by the servant)
  LD (60238),A
  LD A,96                 ; Set the vertical pixel position of the object to
  LD (60234),A            ; just below Maroc (this will always be the same
                          ; screen position)
  LD A,29                 ; Set the horizontal (half-character/4-pixel)
  LD (60232),A            ; position of the object to Maroc's horizontal
                          ; position (this will always be the same screen
                          ; position)
  CALL L56028             ; Fetch the item state and prepare graphics for
                          ; printing
  CALL L57520             ; The item is now in the room, so copy the item
                          ; details into one of the room item data sets at
                          ; 31744
  LD (HL),255             ; Set an end-of-data marker at the start of the next
                          ; room item data set
  LD (60274),HL           ; Re-store the room item set address pointer.

; Check if Maroc is out of energy
;
; Used by the routine at L55564.
L55616:
  LD A,(60128)            ; Check Maroc's energy
  CP 0                    ; Is it zero?
  JR NZ,L55628            ;
  LD A,1                  ; If so, Maroc is out of energy - set room number to
  LD (60080),A            ; 1 ready to send Maroc back to the start room.
                          ; Another check for Maroc's energy (which triggers
                          ; the 'death' sequence if zero) is made shortly at
                          ; L55818_3.

; Deal with room items when Maroc leaves the room
;
; Used by the routines at L48992 and L55616.
;
; Evaluates objects in data sets at 31744 and store state of any DOORS,
; CREATURES or OBJECTS.
L55628:
  LD A,(60080)            ; Room number
  CP 0                    ;
  JP Z,L50870             ; If it's zero, it means that room's all set up, so
  LD A,0                  ; jump to the main game cycle
; Start preparing the room items that will need dealing with:
  LD (60343),A            ; Set the creatures in the room to zero
  LD HL,(L56046)          ; Pointer to start of the room data sets at 31744
  LD DE,16                ; Skip pointer past first data set, which deals with
  ADD HL,DE               ; the room/viewport setup
; Check each data set in the room item list at 31744 in turn:
L55628_0:
  LD A,(HL)               ; Get first byte of data set
  CP 255                  ; Check for end-of-data marker
  JP Z,L55818             ; If found, skip copying routine
  LD DE,16                ;
  CP 0                    ; If first data byte <> 0, there's some data to copy
  JR NZ,L55628_1          ; for this set
  ADD HL,DE               ; First data byte is zero, so skip to next data set
  JR L55628_0             ; and keep checking data sets
; Copy 16 bytes of data from this set at 31744 to the data buffer at L60227:
L55628_1:
  LD BC,16                ; 16 bytes to copy
  LD DE,L60227            ; Start of buffer (destination)
  LDIR                    ;
  LD (60094),HL           ; Store data pointer ready at the start of the next
                          ; data bank
; Check what the item in the data set is:
  LD A,(L60227)           ; Get first byte of data set which indicates the item
                          ; type
  CP 2                    ; Door
  JR Z,L55628_2           ;
  CP 4                    ; Interactable object
  JR Z,L55628_3           ;
  CP 3                    ; Creature
  JR Z,L55628_4           ;
  JR L55628_0             ; If not one of these three items, no extra
                          ; processing needed at this point, so jump back and
                          ; continue copying data sets
; DOOR
L55628_2:
  LD HL,(60228)           ; Address pointer to door connector data set in the
                          ; table at L26512
  INC HL                  ; Move to 3rd byte of data set
  INC HL                  ;
  LD A,(60238)            ; This is the door properties byte
  LD (HL),A               ; Store in the 3rd byte of the room connector data
                          ; set
  LD HL,(60094)           ; Retrieve address pointer to current data set at
                          ; 31744
  JR L55628_0             ; ...and continue to check data sets
; INTERACTABLE OBJECT
L55628_3:
  LD HL,(60228)           ; Address pointer to object data set in the table at
                          ; L29551
  LD A,(60087)            ; Get room number...
  LD (HL),A               ; Store in object set as the room number for this
                          ; item (first byte of set)
  INC HL                  ; Move to the next item data byte...
  LD (60228),HL           ; ...And store the address pointer to this object's
                          ; set
; Calculate item's vertical & horizontal co-ordinates (in relation to the room
; viewport's position) and store in the object's data set (in the table at
; L29551)
  LD HL,(60152)           ; Horizontal position of current screen viewport in
                          ; 4-pixel/half-character steps - to be used as a
                          ; calculation offset for the item's position
  EX DE,HL                ; Swap into DE
  LD HL,(60231)           ; Item graphic's horizontal position in room - H
                          ; register contains value in 4-pixel/half-character
                          ; steps (L = pixel fraction/overflow)
  SCF                     ; Clear/reset the carry flag (set, then toggle)
  CCF                     ;
  SBC HL,DE               ; Subtract the offset to get the item's room position
  LD A,H                  ; Get the high byte (contains the object's adjusted
  LD HL,(60228)           ; horizontal position in 4-pixel steps)
  LD (HL),A               ; Store as the 2nd byte of the object's data set at
                          ; L29551
  INC HL                  ; Move address pointer to next byte (which stores the
                          ; item's vertical pixel position)
  LD (60228),HL           ; Store the address pointer
  LD HL,(60150)           ; Get vertical room pixel position
  EX DE,HL                ; Swap into DE
  LD HL,(60233)           ; Item graphic's vertical position in room - H
                          ; register contains value in pixels (L = pixel
                          ; fraction/overflow)
  SCF                     ; Clear/reset the carry flag (set, then toggle)
  CCF                     ;
  SBC HL,DE               ; Subtract the offset to get the item's room position
                          ; in pixels
  LD A,H                  ; Get the high byte (contains the adjusted vertical
                          ; pixel position)
  LD HL,(60228)           ; Retrieve the address pointer to the 3rd byte of the
                          ; object's data set at L29551
  LD (HL),A               ; Store the item's vertical room position
  INC HL                  ; Move along to the next byte of the object's data
                          ; set
; Store item properties byte:
  LD A,(60238)            ; Get item properties byte
  AND 239                 ; Reset bit 4 (if set, indicates item carried by
                          ; servant). In most cases it's unlikely for Maroc to
                          ; be able to switch room while the servant spell is
                          ; active however
  LD (HL),A               ; Store in item data set
  LD HL,(60094)           ; Restore pointer to data set at 31744
  JR L55628_0             ; Continue to copy data sets
; CREATURE
L55628_4:
  LD B,0                  ; The B register will hold a value indicating the
                          ; type and number of creatures in the room
  LD A,(60238)            ; Creature properties byte
  AND 224                 ; Check if any of the top 3 bits are set: Bit 6/7 =
                          ; creature materializing Bit 5 = creature
                          ; disintegrating
  JR NZ,L55628_8          ; If any of these are set, the creature isn't
                          ; considered present, so don't add this creature's
                          ; value
; Check creature type at 60230, and determine which bit values (see L27532) to
; add to the byte value at 60343.
  LD A,(60230)            ; Creature type
  CP 8                    ; Byte value < 8, it's a warlock (no action to take
  JR C,L55628_8           ; as they're not 'stored')
  CP 8                    ;
  JR NZ,L55628_5          ;
  LD B,64                 ; Byte value = 8, it's a guardian of chaos (set value
L55628_5:
  CP 9                    ; = 64, these creatures are stored in bits 6 & 7)
  JR NZ,L55628_6          ;
  LD B,16                 ; Byte value = 9, it's a goblin warrior (set value =
L55628_6:
  CP 10                   ; 16, these creatures are stored in bits 4 & 5)
  JR NZ,L55628_7          ;
  LD B,4                  ; Byte value = 10 it's a goblin missile thrower (set
L55628_7:
  CP 11                   ; value = 4, these creatures are stored in bits 2 &
  JR NZ,L55628_8          ; 3)
  LD B,1                  ; Byte value = 11, it's a wraith (set value = 1,
                          ; these creatures are stored in bits 0 & 1)
; Add this creature's value (in B register) to the creature data byte for this
; room.
L55628_8:
  LD A,(60343)            ; Creature data byte for room
  ADD A,B                 ; Add the creature type value
  LD (60343),A            ; ...and re-store
  LD HL,(60094)           ; Retrieve address pointer to the next data set (at
  JP L55628_0             ; 31744)

; Maroc's room number has changed - identify new room number
;
; Used by the routine at L55628.
;
; Maroc has left a room - all door, creature and object data from the room he's
; left has been dealt with in the previous routine.
L55818:
  LD A,(60087)            ; Get room number
  CP 224                  ; Check if it's a tunnel room (room numbers 224-255)
  JR NC,L55818_0          ; If so, there are no creatures to deal with, so skip
                          ; the next few instructions
; Standard (non-tunnel room). Copy the room's creature data byte (60343),
; calculated in the previous routine, in the relevant room's creature data set
; at L26512.
  DEC A                   ; Offset starts at 0, not 1, so decrement room number
  LD C,A                  ; Use room number as an offset in BC register pair
  LD B,0                  ;
  LD HL,(56048)           ; Address pointer for the room creature data set at
                          ; L27532
  ADD HL,BC               ; Add offset (with C = room number)
  LD A,(60343)            ; Byte indicating which creatures are in the room
                          ; (that Maroc is leaving)
  LD (HL),A               ; Copy into the room creature data at L26512
; Get new room number:
L55818_0:
  LD A,(60080)            ; Get (new) room number data byte
  CP 255                  ; If byte set to 255 it indicates that the room
                          ; number needs to be calculated, so will need
                          ; calculating using the connecting door table at
                          ; L26512
  JR NZ,L55818_2          ; If already calculated, skip the next few
                          ; instructions
  LD HL,(60085)           ; Address pointer to connecting door data at L26512
  LD A,(60087)            ; Get current room number
  CP (HL)                 ; The connecting room will either be byte 2 or 3 (1
                          ; door, two rooms) Is the current room equal to byte
                          ; 2 in the door table?
  JR NZ,L55818_1          ; If not, the new room is byte 2
  INC HL                  ; If so, we need byte 3
L55818_1:
  LD A,(HL)               ; Get the room byte from the connecting door table
  JR L55818_3             ;
; If the new room number is already set/calculated, it means it's been changed
; by some event during the game cycle.
;
; For example, if Maroc:
; * is out of energy (room set to room #1)
; * casts a spell such as SUMMON or WAYSTONE, that teleports him to a new room
;
; If so, set Maroc's position in the new room at the point of the room's left
; wall-floor connector. See Bugs - Teleport spells
L55818_2:
  LD C,A                  ; Calculated room number - temp store in C
  LD A,48                 ; Set Maroc's vertical pixel position in the room to
  LD (L60276),A           ; 48 pixels
  LD A,16                 ; Set Maroc's horizontal room position
  LD (60277),A            ; (4-pixel/half-character steps) to 16
  LD A,0                  ;
  LD (60278),A            ; Set Maroc's room vertical position to 0
  LD A,C                  ; Retrieve byte (60080) from C register
; Maroc's room has now changed, so he's either gone through a door, run out of
; energy, or has teleported somewhere.
L55818_3:
  LD (60087),A            ; Store new room number (e.g. = room #1 when Maroc is
                          ; out of energy, room #61 for SUMMON)
  LD A,(60128)            ; Check Maroc's energy level
  CP 0                    ; Is it zero?
  JP NZ,L49415            ; If not 0, Maroc hasn't run out of energy, so if he
                          ; hasn't just gone through a door he's probably cast
                          ; some sort of teleport spell. If this is the case,
                          ; jump out here and initialize the data for his new
                          ; room. Otherwise, Maroc is out of energy - continue
                          ; to the next routine.

; Maroc is out of energy
;
; When Maroc's energy runs out, an animation runs where Maroc spins to the top
; of the screen:
L55885:
  CALL L58476             ; Maroc out of energy - run 'death' animation routine
; Set up screen to display Maroc's current rank
  CALL L57947             ; Clear the playing area (pixels)
  LD A,66                 ; Set the screen attribute colours to INK 2, BRIGHT
  LD (60073),A            ; 1, PAPER 0
  LD (L60071),A           ; Also set Maroc's attribute colours to these
                          ; attributes for this screen, to avoid a white stripe
                          ; down the middle of the demon...
  CALL L57863             ; Draw the attribute colours on screen
; Draw the demon graphic:
  LD A,1                  ; Demon frame number = 1
  LD (60240),A            ;
  LD A,88                 ; Offset for graphic address table at L38851. Will
                          ; point to address at 39025, for demon graphics
                          ; stored at 42703.
  CALL L57538             ; Set up graphic to draw
  LD A,112                ; Horizontal screen position, in pixels
  LD (60115),A            ;
  LD A,64                 ; Vertical position, in pixels, from top of playing
  LD (60114),A            ; area
  LD A,1                  ; Set draw/erase flag to 1 (DRAW)
  LD (60111),A            ;
  LD A,0                  ; High byte for horizontal graphic position, 0
  LD (60116),A            ; indicates that the graphic is on-screen (within the
                          ; viewport) as opposed to off to the right or left
  LD HL,(60241)           ; Retrieve address pointer for graphics
  LD (60109),HL           ; ...and copy into graphics buffer
  CALL L56216             ; Draw the demon graphic on screen
  JP L49315               ; Print Maroc's rank on the scroll and play music

; Game completion - Maroc has destroyed Avelach, Lord of Chaos
;
; Used by the routine at L52263.
;
; Game completion. Maroc has used Caliburn on Avelach in the High Temple of
; Chaos (event check at L52263).
L55944:
  LD A,255
  LD (60246),A            ; (255 = max) length/frequency for white noise effect
L55944_0:
  LD (60103),A            ; (255 = max) counter duration for white noise effect
  LD (60073),A            ; Also set as attribute value for screen
; Change (decrement) screen colour attributes and play sound effects
  CALL L57863             ; Set screen colour
  CALL L57815             ; Play sound effect
  LD A,(60103)            ; Get counter
  DEC A                   ; Decrement counter (also the screen colour/attribute
                          ; value)
  JR NZ,L55944_0          ; Repeat until counter at zero
; Print success message on scroll:
  CALL L59956_4           ; Reset attributes in top right corner of scroll (in
                          ; case the spell icon is FLASHING)
  CALL L57081             ; Clear the scroll area
  LD A,35                 ; Message number 35 to print (L29433)
  CALL L58789             ; Identify the message text to print
  LD (L60065),HL          ; Re-store the address pointer for the end of the
                          ; text string
  LD HL,20615             ; Screen display address to print the text
  LD (60068),HL           ;
  CALL L58064             ; Set up message text on scroll to print
; Play one complete set of game (intro/main theme) music:
  LD A,1                  ; Tune number #1
  CALL L58806             ; Play the tune
; Calculate and print the player's (final) rank on the scroll:
  CALL L57081             ; Clear the scroll area
  CALL L58599             ; Calculate and print rank on scroll
; Play game (intro) tune on a loop:
L55944_1:
  LD A,1                  ; Tune number #1
  CALL L58806             ; Play the tune
  JR L55944_1             ; ...and repeat until the player resets their
                          ; Spectrum...

; Object - vertical room position check/adjustment
;
; Used by the routines at L51968, L52059 and L53550.
;
; Check that an object isn't moving (e.g. carried by the servant) below the
; bottom of the room boundary.
;
; Recalculated vertical pixel position returned in E register, ready for a
; later call to the room border checks at L57401
L56008:
  LD A,(60234)            ; Graphic vertical position (of object) from top of
                          ; screen (pixels)
  LD E,A                  ; Store in E register
  LD HL,60150             ; Address holding vertical position of room
                          ; (viewport) in pixels
  INC HL                  ; ...the main value is stored in the high byte of the
                          ; address, so advance to this address
  LD A,96                 ; Offset (96 pixels, from top of screen) for the
                          ; bottom of the room's active playing area
  ADD A,(HL)              ; Add to the room's vertical position (e.g. if Maroc
                          ; is towards the top of the room, and the room
                          ; extends downwards off the bottom of the playing
                          ; area, then it's OK for the object to be dragged
                          ; there)...
  SUB E                   ; ...Subtract the object's vertical screen position
  JR C,L56008_0           ; If this results in a carry, it's too far off the
                          ; bottom of the playing area
; While the servant can move anywhere in the visible screen area, objects are
; constrained by room wall boundaries.
;
; The next set of instructions adds a small offset (based on the room offset
; position) to the item's vertical position, which is used for later room
; boundary checks. i.e. extends the boundary
;
; This lets the servant drag the object into the room's wall areas - to an
; extent at least. Without this adjustment it would be difficult to do certain
; things, such as drag objects to trade with warlocks.
  RRA                     ; The A register still contains (from the previous
                          ; instructions) the difference between the item's
                          ; vertical position and the bottom of the screen area
  AND 127                 ; Halve this value, and filter out bit 7 as it's not
                          ; needed
  ADD A,E                 ; Store in E register
  LD E,A                  ;
L56008_0:
  RET                     ;

; Fetch object state and prepare graphics for printing
;
; Used by the routines at L52263, L53273, L55347 and L55564.
L56028:
  LD HL,(60228)           ; Address pointer to room object in table at L29551
  CALL L56959             ; Identify state of object
  LD A,1                  ; Set object frame offset to 1 (= no offset)
  LD (60240),A            ;
  LD A,(60304)            ; Graphic number, used to calculate graphic address
                          ; in table at L38851
  CALL L57538             ; Set up object graphics
  RET                     ;

; Store for base address pointers
L56046:
  DEFW L31744             ; Pointer to the start of the room item data sets
                          ; stored at 31744
  DEFW L27532             ; Address pointer for room creature data
  DEFB 255                ; Unused
  DEFW L29551             ; Address pointer - room objects data sets
  DEFW L26512             ; Address pointer to connecting door sets
  DEFW L25001             ; Address pointer to room data

; Unused
L56057:
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0

; Generate pseudo-random number using ROM address values
;
; Used by the routines at L51420, L52136, L52695, L52948, L54865, L55068,
; L57139 and L57706.
;
; Generates a constantly changing value in the A register, using random
; addresses and bytes from ROM.
;
; HL gets gradually incremented from 0. The ROM address and the byte stored
; there is returned in the A register to deliver a pseudo-random value.
L56070:
  LD (56093),HL           ; Preserve HL register pair
  LD HL,(56091)           ; Retrieve address pointer
  INC HL                  ; Increment pointer to next address in ROM
  LD A,H                  ; Ensure high byte of pointer doesn't exceed 31
  AND 31                  ; (keeps ROM address capped at 8191)
  LD H,A                  ;
  LD A,(HL)               ; Pick a byte from this ROM address
  ADD A,H                 ; Add both high & low byte address values
  ADD A,L                 ; This gives the value variation if the ROM contains
                          ; a lot of the same consecutive values
  LD (56091),HL           ; Store the ROM address pointer for next time
  LD HL,(56093)           ; Retrieve HL register pair
  RET                     ;
; Store for registers used in the above routine
  DEFW 0                  ; Store for incrementing ROM address pointer. Starts
                          ; at 0
  DEFW 0                  ; Temp store for HL register pair during the routine

; Set up missile data and calculate trajectory
;
; Used by the routine at L55188.
;
; A Missile number (see table at L27868)
;
; Calculates and puts missile data into room object sets at 31744 for missiles
; fired by Maroc at creatures, and vice versa. Also calculates trajectory based
; on origin/target co-ordinates.
;
; First, calculate the address pointer to the missile set (table at L27868)
; using the missile number:
L56095:
  LD C,A                  ; Temp store missile number in C register
  LD HL,(L60353)          ; Address pointer to missile data table at L27868
  DEC A                   ; Offset needed is 0-8 (not 1-9) so decrement missile
                          ; number
  LD D,0                  ; Store offset in DE register pair
  LD E,A                  ;
  LD B,8                  ; 8 bytes in each missile data set
L56095_0:
  ADD HL,DE               ;
  DJNZ L56095_0           ; Continue adding until HL is pointing at the start
                          ; of this missile's data set in the table at L27868
  LD (60315),HL           ; Store missile table address pointer
; Create a new room item data set for the missile at 31744, and copy a few
; variables from the missile-related data at L27868 and L60305 into it.
  INC HL
  LD A,(HL)               ; Get missile properties byte (second byte in missile
                          ; data set at L27868)
  LD (60318),A            ; ...and copy into the missile data buffer (starts
  DEC HL                  ; from L60305)
  EX DE,HL                ; Swap (start of) data set pointer into DE register
                          ; pair
  LD HL,(60274)           ; Address pointer to next data bank at 31744
  LD A,(60314)            ; Item type. 5 = missile fired by creature/warlock,
                          ; or 8 = missile fired by Maroc
  LD (HL),A               ; Put in first byte of room item data set at 31744
  INC HL                  ;
  LD (HL),E               ; Store address pointer to start of missile table at
  INC HL                  ; L27868 in bytes 2 & 3 of room item data set (at
  LD (HL),D               ; 31744)
  INC HL                  ;
  LD (HL),C               ; Store missile number (table at L27868) as byte 4 of
  INC HL                  ; room item data set (at 31744)
  LD B,4                  ; Copy 4 bytes of data to room item (missile) data
  LD DE,60308             ; set at L31744:
L56095_1:
  LD A,(DE)               ; * 60308 --> byte 5 of set (horizontal position
  LD (HL),A               ;   precision/fraction byte)
  INC DE                  ; * 60309 --> byte 6 of set (horizontal position in
  INC HL                  ;   4-pixel steps)
  DJNZ L56095_1           ; * 60310 --> byte 7 of set (vertical position
                          ;   precision/fraction byte)
                          ; * 60311 --> byte 8 of set (vertical pixel position)
  LD (HL),64              ; 9th data byte in room item data sets at 31744 -
                          ; this is 64 for 'standard' room items (rather than
                          ; 254/255 for 'tunnel' room items)
  INC HL                  ; Advance address pointer one byte along
; Calculate difference between positions of missile origin and target, in
; 2-pixel steps. Then store this calculation in the missile data set in the
; room sets at 31744.
;
; Horizontal position difference (between origin and target) calculation:
  LD A,(60309)            ; Horizontal position of missile origin
  LD C,A                  ; (half-character steps)
  LD A,(60312)            ; Horizontal position of target (half-character
                          ; steps)
  SUB C                   ; Subtract to get the difference
  ADD A,A                 ; Double the difference to get the horizontal
                          ; difference (either positive or negative) in 2-pixel
                          ; increments
  LD (HL),A               ; ...and store in data set (byte 10 of data set)
  INC HL                  ;
; Vertical position difference (between origin and target) calculation:
  LD A,(60311)            ; Vertical screen position of missile origin (in
  LD C,A                  ; pixels)
  LD A,(60313)            ; Vertical screen position of missile target (in
                          ; pixels)
  SUB C                   ; Subtract to get the difference
  SRA A                   ; Halve to get difference in 2-pixel increments
  LD (HL),A               ; ...and store in data set (byte 11 of data set)
  INC HL                  ;
; Finally, copy missile graphics properties and pointers into room data set at
; 31744.
  LD A,1                  ; Missile graphic frame offset (frame 1 = no offset)
  LD (60240),A            ;
  LD DE,(60315)           ; Retrieve address pointer to missile data table at
                          ; L27868
  LD A,(DE)               ; Get graphic number for the missile graphics for use
                          ; in the following CALL
  LD (60274),HL           ; Temp store for address pointer current position in
                          ; the data at 31744
  CALL L57538             ; Set up missile graphics
  LD HL,(60274)           ; Retrieve data set address pointer stored before the
                          ; CALL
  LD A,(60318)            ; Missile properties byte
  LD (HL),A               ; Store as 12th byte of room item data set
  INC HL                  ;
  LD A,(60239)            ; Missile pre-graphics data byte
  LD (HL),A               ; Store as 13th byte of set
  INC HL                  ;
  LD A,17                 ; Graphic frame offset. Only bits 0-3 will be used to
  LD (HL),A               ; calculate the graphics animation frame, so the
  INC HL                  ; value is effectively 1 (= no offset). Stored in
                          ; 14th byte of set at 31744
  LD DE,(60241)           ; Missile graphics address pointer (table at L38851)
  LD (HL),E               ; Store as the last two byes in the data set
  INC HL                  ;
  LD (HL),D               ;
  INC HL                  ;
  LD (HL),255             ; Put end-of-data marker at start of next data set...
  LD (60274),HL           ; ...and store data set pointer
  RET                     ;

; Draw/erase graphics - screen boundary checks
;
; Used by the routines at L49215, L53885, L54342, L54450, L55885, L58476,
; L59783 and L59869.
;
; HL Address pointer for graphics to draw, from address pointer table at L38851
;
; The first check is to see if the item's horizontal/vertical pixel
; co-ordinates fall within the bounds of the visible playing area.
;
; The checks also test for cases where part of the graphic is on-screen - it's
; only considered 'off-screen' if none of it needs drawing.
L56216:
  LD E,(HL)               ; Transfer the address (from L38851) pointed to by HL
  INC HL                  ; into the DE register
  LD D,(HL)               ;
  EX DE,HL                ; Swap back so HL now points to the graphics data,
                          ; e.g. 39248
  LD A,0                  ; This is the flag indicating whether (any part of)
                          ; the graphic is visible on-screen (0 = not visible,
                          ; 1 = visible) It'll be updated shortly once we've
                          ; worked out if any part of the graphic is on-screen
                          ; or not
  LD (60117),A            ; This is set to not visible (0) for off-screen
                          ; objects, but if any part of the item needs drawing,
                          ; it's set to 1 (visible) at L56309
  LD A,(HL)               ; Number of tiles that make up the graphic/sprite
  LD (60112),A            ; ...and store...
  INC HL                  ; HL now at the start of the graphic's first tile
                          ; data
; This entry point is used by the routine at L56439.
L56216_0:
  LD C,(HL)               ; Store this byte in C register. This is the
                          ; horizontal pixel offset for drawing this tile from
                          ; its screen X/Y co-ordinates
  INC HL                  ; Move onto the next byte
  EX DE,HL                ; Swap the graphics address pointer back into the DE
                          ; register
; Calculate horizontal (X) pixel offset, check for out of bounds
  LD HL,(60115)           ; Get graphic X horizontal (pixel) position from
                          ; character column 1 on the left of the screen (the
                          ; right hand part of the left border).
  LD A,C                  ; Graphic's horizontal offset in pixels
  RLA                     ; If the offset is >=128, it's a negative pixel
                          ; offset (e.g. 253 = -3 pixels)
  SBC A,A                 ; ...So if the RLA creates a carry, the SBC will set
                          ; A to to 255 (-1). Otherwise 0.
  LD B,A                  ; Transfer to B. This determines if the offset value
                          ; gets subtracted or added in the next instruction.
  ADD HL,BC               ; Add horizontal pixel offset to horizontal pixel
                          ; drawing position
  EX DE,HL                ; Swap into DE
  LD A,D                  ; Get the high byte of the horizontal position as
                          ; just calculated
  CP 0                    ; If high byte changed from 0 to 1, the graphic has
                          ; gone out of the screen's viewport boundary
  JP NZ,L56439            ; ...if so, skip out of this routine to deal with the
                          ; out-of-bounds graphic
  LD A,E                  ; Get horizontal pixel position
  CP 232                  ; Check to see if this is in the right hand border
                          ; screen position - 232/8 = 29, but as the counting
                          ; starts at pixel column 8 (character column 1,
                          ; rather than 0), this will be character column 30 in
                          ; the right hand border
  JP NC,L56439            ; If there's no carry, jump out of this routine to
                          ; deal with the out-of-bounds graphic
  ADD A,8                 ; The screen display address is calculated (in the
                          ; next routine) from the leftmost screen column -
                          ; i.e. column 0, not column 1 as currently stored -
                          ; so add 8 so that this is taken into account.
  LD E,A                  ; Store in E register ready for the next part of the
                          ; routine at L56309
  AND 7                   ; Take lowest 3 bits (values 0-7)
  LD B,A                  ; Store in B register - this is the number of pixel
                          ; shifts needed for the graphic at L56309_1
; Calculate vertical (Y) pixel offset, check for out of bounds
  LD A,(60114)            ; Get graphic Y vertical (pixel) position, e.g. 80
                          ; for character row 10 (80/8)
  ADD A,(HL)              ; Add to the graphic vertical offset, e.g. an offset
                          ; of 231 means a -25 vertical pixel offset to the
                          ; existing co-ordinate
  INC HL                  ; Move HL to the next pre-graphics byte address
  LD C,(HL)               ; Number of bytes in the next tile graphic
  INC HL                  ; HL now points to first graphic tile byte ready for
                          ; drawing
  CP 112                  ; Vertical pixel position 112 is the top of the
                          ; scroll, which is out of bounds for drawing graphics
  JP C,L56216_1           ; Carry means (at least the top part of) the item is
                          ; within the screen viewport and drawable, so jump to
                          ; L56216_1
; A no-carry indicates the vertical-pixel-position-plus-offset is either above
; the top of the playing area or into the scroll area.
;
; However, some part of the item may be visible; for example the vertical
; corner floor/wall connectors can be partly off the top of the playing area,
; but the rest of them may be visible on-screen.
  LD D,A                  ; Store vertical (Y) pixel position
  ADD A,C                 ; Add the number of bytes in the tile to the current
  JP NC,L56439_0          ; out-of-bounds position
  JP Z,L56439_0           ; A no-carry or zero result means that no part of the
                          ; object is visible, so this graphic doesn't need
                          ; drawing. Jump out here to re-calculate address
                          ; pointers etc.
; Some (lower) part of this graphic is visible at the top of the screen. Put
; the graphics address pointer to the right part of the graphics and set the
; pixel row number in the line.
  LD (60113),A            ; Store the number of bytes in the visible part of
                          ; the graphic tile left to draw
  LD A,D                  ; Retrieve the vertical pixel co-ordinate (plus
                          ; offset). This will be a negative number...
  NEG                     ; So make it positive...
  ADD A,L                 ; HL is pointing at the address for the tile
  LD L,A                  ; graphics...
  LD A,0                  ;
  ADC A,H                 ; ...So increase it by the number of bytes that don't
  LD H,A                  ; need to be drawn as they're in/above the decorative
                          ; border
  LD D,16                 ; Set the vertical screen position to 16 pixel rows
                          ; down - the first byte of character row 2, just
                          ; below the top border
  LD C,0                  ; C register contains the pixel row; as we're
                          ; starting from character row 2 means that the first
                          ; byte will be pixel row 0
  JR L56309               ; Ready to calculate screen address low/high bytes
; Jump from 56269. The graphic (or at least the top of it) are drawable. Set
; the screen vertical pixel position and pixel row in the line (0-7).
L56216_1:
  ADD A,16                ; Vertical pixel position starts from 0 (16 pixels
                          ; from top of screen...
  LD D,A                  ; D contains vertical Y screen pixel position
  LD A,C                  ; Get number of tile bytes to draw
  LD (60113),A            ; ...and store...
  LD A,D                  ; Get A back from D (mystery value - now 71)
  AND 7                   ; Take lowest 3 bits (0,1,2) - pixel row number in
                          ; line
  LD C,A                  ; Store in C register for the next part of the
                          ; routine

; Draw/erase graphics - calculate screen display address position
;
; Used by the routine at L56216.
;
; B Number of horizontal pixel shifts/rotates (rotated at 56363) needed
; C Pixel number in character row (0-7)
; D Vertical pixel row at which to draw the graphic, from the top of the screen
;   display
; E Horizontal pixel column at which to draw the graphic, from the left of the
;   screen display
;
; This routine calculates the screen display address position to draw the
; graphic at, and checks if it's encroaching on the left or right border of the
; screen
L56309:
  LD A,1                  ; This is the flag indicating whether (any part of
                          ; the graphic) is visible on-screen (0 = not visible,
                          ; 1 = visible)
  LD (60117),A            ; It's set here to visible (1) as part of the item is
                          ; visible.
; This calculates the LOW BYTE of the screen display address
  LD A,E                  ; Horizontal pixel position, from left of screen
                          ; display
  RRA                     ; Divide by 8 to get the screen (character) column
  RRA                     ;
  RRA                     ;
  AND 31                  ; Filter out unnecessary bits (5-7) that may have
                          ; been affected by the RRA instructions, just keeping
                          ; bits 0-4 (values 0-31)
  LD E,A                  ; Store in E register
  LD A,D                  ; Get the calculated vertical (Y) pixel position -
                          ; these need to go into bits 5-7 of the byte
                          ; currently stored in E
  RLA                     ; Character row is currently indicated by bits 3-5 so
  RLA                     ; shift them left twice to bits 5-7
  AND 224                 ; Get those top three bits (filter out any others)...
  ADD A,E                 ; ...and combine them with bits 0-4 which hold the
                          ; column number, to form the screen display address
                          ; low byte
  LD E,A                  ; Store back in E register
; This routine calculates the HIGH BYTE of the screen address
  LD A,D                  ; Vertical pixel position, from top of screen display
  RRA                     ; Divide by 8 to get screen (character) row
  RRA                     ;
  RRA                     ;
  AND 24                  ; Bits 3 (8) and 4 (16) include the screen display
                          ; address high byte character row (0-24)
  ADD A,64                ; Set bit 6 (always set for screen addresses)
  ADD A,C                 ; C contains the pixel row number in the character
                          ; line (0-7). Add this to the high byte of the
                          ; address
  LD D,A                  ; Put the calculated screen address high byte into
                          ; the D register
  LD A,(60113)            ; Number of bytes in the graphic tile to draw
  LD C,A                  ; Store in C as a counter (checked later at 56432)
; Check if we're in the decorative screen border. Tiles are drawn (character)
; column by column, so we only need to check for the inner border (columns 1 &
; 30), not the outer ones (columns 0 & 31).
;
; Mirrored graphic tiles have 'reversed' offsets so they tend to be drawn
; right-to-left, so we need to check both left and right columns.
  LD A,E                  ; Retrieve the screen display low byte from the E
                          ; register
  AND 31                  ; Bits 0-4 (values 0-31) give us the screen vertical
                          ; (character) column
  CP 1                    ; Check if we're into the left border (column 1)
  JP Z,L56533             ;
  CP 29                   ; Check if we're into the right border (column 29)
  JP Z,L56457             ;
; Start of tile graphic draw/erase loop - jump back here from 56435
;
; Shifts graphic so that shifted graphics byte contained in 2 bytes, H & L,
; ready to draw on screen
L56309_0:
  LD A,(HL)               ; Get graphics byte
  INC HL                  ; ...And move graphic address pointer along, ready
                          ; for next one
  CP 0                    ; Byte empty?
  JR Z,L56403_0           ; ...If so, skip this byte, don't bother shifting or
                          ; drawing
  PUSH HL                 ; Store address pointer
; Shifts graphic so that the right-shifted graphics byte is contained in 2
; bytes, H and L, ready to draw on screen
  LD H,A                  ; H contains the unshifted graphic byte
  LD L,0                  ; Clear L register ready to receive shifted bits
  LD A,B                  ; Temp store for the 'shift counter' (containing
                          ; number of right-shifts needed)
  CP 0                    ; Any more shifts needed?
  JR Z,L56309_2           ; ...If not, skip out of the shift loop
L56309_1:
  RR H                    ; Rotate byte in H register into L register
  RR L                    ;
  DJNZ L56309_1           ; Repeat for number of shifts (counter)
  LD B,A                  ; Reset the shift counter (from A register)
L56309_2:
  EX DE,HL                ; Swap registers so that D & E contain the byte
                          ; values to draw, and HL contains the screen display
                          ; address to draw at
  LD A,(60111)            ; Check draw/erase flag
  CP 1                    ; 0 = Erase, 1 = Draw
  JR Z,L56396             ; If flag = 1, jump to DRAW routine. Otherwise ERASE
                          ; (next routine)

; Draw/erase graphics - erase graphic bytes
;
; DE Two graphic bytes to erase - these were originally a single graphics byte
;    whose bits have been rotated into two bytes by the previous routine at
;    56362
; HL Screen display address to erase byte from
;
; Erases graphic bytes on screen by inverting them (CPL) and then AND-ing with
; the screen bytes to preserve any other background graphics
L56385:
  LD A,D                  ; Get first graphic byte
  CPL                     ; Invert it
  AND (HL)                ; AND with screen byte (i.e. keeps existing screen
                          ; byte, clears sprite byte)
  LD (HL),A               ; ...and put back on screen.
  INC HL                  ; Move right one character square
  LD A,E                  ; Get second graphic byte
  CPL                     ; Invert it
  AND (HL)                ; AND with screen byte (i.e. keeps existing screen
                          ; byte, clears sprite byte)
  LD (HL),A               ; ...and draw the remainder of the byte back on
                          ; screen.
  JR L56403               ; Byte now erased

; Draw/erase graphics - draw graphic bytes
;
; Used by the routine at L56309.
;
; DE Two graphic bytes to draw - these were originally a single graphics byte
;    whose bits have been rotated into two by the previous routine at 56362
; HL Screen display address to draw byte
;
; Draws graphic bytes on screen, combining with any existing screen background
; bytes
L56396:
  LD A,D                  ; Get first graphic byte
  OR (HL)                 ; OR with existing screen byte, preserve any
                          ; background graphics
  LD (HL),A               ; ...and draw back on screen.
  INC HL                  ; Move right one character square
  LD A,E                  ; Get second graphic byte
  OR (HL)                 ; OR with existing graphic byte on screen
  LD (HL),A               ; ...and draw back on screen.

; Draw/erase graphics - re-calculate screen display address 1 pixel line down
;
; Used by the routine at L56385.
;
; HL Screen display address +1 for the byte that has just been drawn or erased
;
; After drawing (L56396) or erasing (L56385) the screen graphic byte, this
; routine calculates the next screen address (1 pixel line lower) before
; continuing to draw/erase the graphic bytes of the tile
L56403:
  DEC HL                  ; Move back left one character square
  EX DE,HL                ;
  POP HL                  ; HL now back to the graphic address pointer
; This entry point is used by the routine at L56309.
L56403_0:
  LD A,D                  ; Get high byte of screen address
  INC A                   ; ...and increment (move down 1 pixel row)
  AND 7                   ; Are we crossing into a new character row (8th pixel
  JR Z,L56403_1           ; row)?
  INC D                   ; If not, increment screen display address pointer
  JR L56403_2             ; (move down 1 pixel row)
L56403_1:
  LD A,D                  ; Otherwise, adjust high byte to the correct screen
                          ; address
  AND 248                 ; Reset the low 3 bits (pixel row number) to zero
  LD D,A                  ;
  LD A,E                  ; Get the low byte of the screen address
  ADD A,32                ; Increment column by 32 to move down to next screen
  LD E,A                  ; row
  JR NC,L56403_2          ; Crossing a 1/3 screen boundary? ...If not, skip
                          ; next 3 instructions
  LD A,D                  ; ...If so, adjust high byte of screen address
  ADD A,8                 ; accordingly
  LD D,A                  ; Store correct screen address high byte back in D
                          ; register
; Check if encroaching out of bounds into bottom third of screen, where the
; scroll status panel is:
L56403_2:
  LD A,D
  CP 80                   ; Are we into the last 3rd of the screen (encroaching
                          ; onto )
  DEC C                   ; (Decrement number of tile bytes to print at this
                          ; point)
  JR NC,L56439_0          ; Jump to L56439_0 if into last 3rd of screen (out of
                          ; bounds)
  JR NZ,L56309_0          ; Bytes left to draw in the tile - continue to draw
  JR L56439_1             ; next tile byte

; Draw/erase graphics - graphic tile out of bounds
;
; Used by the routine at L56216.
;
; HL Contains address of the vertical pixel offset in the graphic tile data
;
; Gone 'out of bounds' on horizontal screen position so there's no need to draw
; this tile. Skip to the next one (checking if there are any left).
L56439:
  INC HL                  ; Move HL to the next address in the graphics data
  LD C,(HL)               ; This address contains the number of bytes in the
                          ; tile graphic
  INC HL                  ; Move HL to point to the start of the graphics data
                          ; itself
; Also jump in at to this point from the check at 56272, if out of bounds on
; vertical position (into bottom 3rd of screen)
;
; +----+----------------------------------------------------+
; | HL | Pointing at address of first graphics byte in tile |
; | C  | Number of bytes in next tile graphic               |
; +----+----------------------------------------------------+
L56439_0:
  LD D,0
  LD E,C                  ; DE now contains number of bytes left to draw in the
                          ; current graphics tile
  ADD HL,DE               ; ...Add to current graphics address pointer to skip
                          ; over the rest of the tile graphics (as there's no
                          ; need to draw them)
; Decrement the tile counter and check to see if all tiles of the graphic have
; been drawn
L56439_1:
  LD A,(60112)            ; Get tile counter (number of tiles in current
                          ; graphic)
  DEC A                   ; Decrement counter
  LD (60112),A            ; ...and re-store
  JP NZ,L56216_0          ; Still tiles to draw/erase? If so, go draw/erase
                          ; them
  RET                     ; All graphic tiles are now drawn/erased.

; Draw/erase graphics - graphic partly out of bounds - RIGHT border of play
; area
;
; Used by the routine at L56309.
;
; HL Graphic data address pointer
; DE Screen display address
; A Screen column (0-31)
; C Number of remaining bytes in the tile to draw
; B Number of (right) pixel shifts needed for graphic byte
;
; The graphics byte is pixel-shifted into two screen bytes, but the second byte
; is now in the right border area.
;
; This routine incorporates slightly tweaked versions of the:
; * Bit shifting routine at 56362
; * Erase graphic byte routine at L56385
; * Draw graphic byte routine at L56396
; * Re-calculate screen display address 1 pixel lower routine at L56403
;
; The opposite routine (graphic partially obscured by left-hand screen border)
; is at L56533.
L56457:
  LD A,(HL)               ; Get graphics byte
  INC HL                  ; ...and move graphic address pointer along, ready
                          ; for next one
  CP 0                    ; Byte empty?
  JR Z,L56457_4           ; ...If so, skip this byte, don't bother shifting or
                          ; drawing
  PUSH HL                 ; Store address pointer
; Shifts graphic so that the right-shifted graphics byte is contained in 2
; bytes, H and L, ready to draw on screen:
  LD H,A                  ; H contains the unshifted graphic byte
  LD L,0                  ; Clear L register ready to receive shifted bits
  LD A,B                  ; Temp store for the 'shift counter' (containing
                          ; number of right-shifts needed)
  CP 0                    ; Any more shifts needed?
  JR Z,L56457_1           ; ...If not, skip out of the shift loop
L56457_0:
  RR H                    ; Rotate byte in H register into L register
  RR L                    ;
  DJNZ L56457_0           ; Repeat for number of shifts needed (counter)
  LD B,A                  ; Reset the shift counter (from A register)
L56457_1:
  EX DE,HL                ; Swap registers so that D & E contain the byte
                          ; values to draw, and HL contains the screen display
                          ; address to draw at
  LD A,(60111)            ; Check draw/erase flag
  CP 1                    ; 0 = Erase, 1 = Draw
  JR Z,L56457_2           ; If flag = 1, jump to DRAW routine. Otherwise ERASE
                          ; (next routine)
; ERASE SCREEN BYTE
;
; Don't need to erase the second graphic byte (stored in E register) as it's on
; the screen border.
  LD A,D                  ; Get first graphic byte
  CPL                     ; Invert it
  AND (HL)                ; AND with screen byte (i.e. keeps existing screen
                          ; byte, clears sprite byte)
  LD (HL),A               ; ...and put back on screen.
  JR L56457_3             ;
; DRAW SCREEN BYTE
;
; No need to draw the second graphic byte (stored in E register) as it's on the
; screen border.
L56457_2:
  LD A,D                  ; Get first graphic byte
  OR (HL)                 ; OR with existing screen byte, preserve any
                          ; background graphics
  LD (HL),A               ; ...and draw back on screen.
L56457_3:
  EX DE,HL                ;
  POP HL                  ; HL now back to the graphic display address pointer,
                          ; DE contains the screen display address
; Recalculate screen address 1 pixel line down after drawing/erasing the
; graphic byte (also jump in to here from 56461 if byte empty)
L56457_4:
  LD A,D                  ; Get high byte of screen address
  INC A                   ; ...and increment (move down 1 pixel row)
  AND 7                   ; Are we crossing into a new character row (8th pixel
  JR Z,L56457_5           ; row)?
  INC D                   ; If not, increment screen display address pointer
  JR L56457_6             ; (move down 1 pixel row)
L56457_5:
  LD A,D                  ; Otherwise, adjust high byte to the correct screen
                          ; address
  AND 248                 ; Reset the low 3 bits (pixel row number) to zero
  LD D,A                  ;
  LD A,E                  ; Get the low byte of the screen address
  ADD A,32                ; Increment column by 32 to move down to next screen
  LD E,A                  ; row
  JR NC,L56457_6          ; Crossing a 1/3 screen boundary? ...If not, skip
                          ; next 3 instructions
  LD A,D                  ; ...If so, adjust high byte of screen address
  ADD A,8                 ; accordingly
  LD D,A                  ; Store correct screen address high byte back in D
                          ; register
; Check if encroaching out of bounds into bottom third of screen, where the
; scroll status panel is
L56457_6:
  LD A,D
  CP 80                   ; Are we into the last 3rd of the screen?
  DEC C                   ; (Decrement number of tile bytes to draw)
  JP NC,L56439_0          ; Jump to L56439_0 if into last 3rd of screen (out of
                          ; bounds)
  JR NZ,L56457            ; If bytes left to draw in the tile - continue to
  JP L56439_1             ; draw next tile byte

; Draw/erase graphics - graphic partly out of bounds - LEFT border of play area
;
; Used by the routine at L56309.
;
; HL Graphic data address pointer
; DE Screen display address
; A Screen column (0-31)
; C Number of remaining bytes in the tile to draw
; B Number of (right) pixel shifts needed for graphic byte
;
; This routine incorporates slightly tweaked versions of the:
; * Bit shifting routine at 56362
; * Erase graphic byte routine at L56385
; * Draw graphic byte routine at L56396
; * Re-calculate screen display address 1 pixel lower routine at L56403
;
; The opposite routine (graphic partially obscured by right-hand screen border)
; is at L56457.
L56533:
  LD A,(HL)               ; Get graphics byte
  INC HL                  ; ...and move graphic address pointer along, ready
                          ; for next one
  CP 0                    ; Byte empty?
  JR Z,L56533_4           ; ...If so, skip this byte, don't bother shifting or
                          ; drawing
  PUSH HL                 ; Store address pointer
; Shifts graphic so that the right-shifted graphics byte is contained in 2
; bytes, H and L, ready to draw on screen
  LD H,A                  ; H contains the unshifted graphic byte
  LD L,0                  ; Clear L register ready to receive shifted bits
  LD A,B                  ; Temp store for the 'shift counter' (containing
                          ; number of right-shifts needed)
  CP 0                    ; Any more shifts needed?
  JR Z,L56533_1           ; ...If not, skip out of the shift loop
L56533_0:
  RR H                    ; Rotate byte in H register into L register
  RR L                    ;
  DJNZ L56533_0           ; Repeat for number of shifts needed (counter)
  LD B,A                  ; Reset the shift counter (from A register)
L56533_1:
  EX DE,HL                ; Swap registers so that D & E contain the byte
                          ; values to draw, and HL contains the screen display
                          ; address to draw at
  LD A,(60111)            ; Check draw/erase flag
  CP 1                    ; 0 = Erase, 1 = Draw
  JR Z,L56533_2           ; If flag = 1, jump to DRAW routine. Otherwise ERASE
                          ; (next routine)
; ERASE SCREEN BYTE
  LD A,E                  ; Don't need to erase the first graphic byte (stored
                          ; in D register) as it's on the screen border,
                          ; instead get the second byte (stored in E)
  INC HL                  ; Move display address pointer right one character
                          ; square to character column 2, just inside the left
                          ; border
  CPL                     ; Invert the graphics byte
  AND (HL)                ; AND with screen byte (i.e. keeps existing screen
                          ; byte, clears sprite byte)
  LD (HL),A               ; ...and put back on screen.
  JR L56533_3             ;
; DRAW SCREEN BYTE
L56533_2:
  LD A,E                  ; Don't need to draw the first graphic byte (stored
                          ; in D register) as it's on the screen border,
                          ; instead get the second byte (stored in E)
  INC HL                  ; Move display address pointer right one character
                          ; square
  OR (HL)                 ; OR with existing screen byte, preserve any
                          ; background graphics
  LD (HL),A               ; ...and put back on screen.
; Graphic byte now drawn/erased
L56533_3:
  DEC HL                  ; Move back left one character space/screen display
  EX DE,HL                ; address
  POP HL                  ; HL now back to the graphic display address pointer,
                          ; DE contains the screen display address
; Recalculate screen address after drawing/erasing the graphic byte (also jump
; in to here from 56537 if byte to draw is empty)
L56533_4:
  LD A,D                  ; Get high byte of screen address
  INC A                   ; ...and increment (move down 1 pixel row)
  AND 7                   ; Are we crossing into a new character row (8th pixel
  JR Z,L56533_5           ; row)?
  INC D                   ; If not, increment screen display address pointer
  JR L56533_6             ; (move down 1 pixel row)
L56533_5:
  LD A,D                  ; Otherwise, adjust high byte to the correct screen
                          ; address
  AND 248                 ; Reset the low 3 bits (pixel row number) to zero
  LD D,A                  ;
  LD A,E                  ; Get the low byte of the screen address
  ADD A,32                ; Increment column by 32 to move down to next screen
  LD E,A                  ; row
  JR NC,L56533_6          ; Crossing a 1/3 screen boundary? ...If not, skip
                          ; next 3 instructions
  LD A,D                  ; ...If so, adjust high byte of screen address
  ADD A,8                 ; accordingly
  LD D,A                  ; Store correct screen address high byte back in D
                          ; register
; Check if encroaching out of bounds into bottom third of screen, where the
; scroll status panel is
L56533_6:
  LD A,D
  CP 80                   ; Are we into the last 3rd of the screen?
  DEC C                   ; (Decrement number of tile bytes to draw)
  JP NC,L56439_0          ; Jump to L56439_0 if into last 3rd of screen (out of
                          ; bounds)
  JR NZ,L56533            ; If bytes left to draw in the tile - continue to
  JP L56439_1             ; draw next tile byte

; Draw the spell pointer arrow, spell charge icons and energy bar on the scroll
;
; Used by the routines at L58945, L59130 and L59219.
;
; DE Screen display address location to draw at
;
; Draws the scroll arrow (called from L58945), the spell 'charge' icons (called
; from L59130) or the energy bar (called from 59246)
L56612:
  LD HL,(60241)           ; Get graphics address pointer from L38851
  LD A,(HL)               ; Get the graphics address pointer low byte for the
                          ; arrow (44966), the scroll charge icons (44775), or
                          ; the energy bar (L44787)
  INC HL                  ; High byte of the graphics address pointer
  LD H,(HL)               ;
  LD L,A                  ; ...HL register pair now contains the graphics
                          ; address pointer for the relevant graphic
  LD C,(HL)               ; Number of tiles that make up the graphic
  INC HL                  ; Move graphics address pointer along to start of
L56612_0:
  INC HL                  ; first tile graphic
  INC HL                  ;
  LD B,(HL)               ; Number of bytes in the graphics tile to draw
  INC HL                  ; Move pointer to start of tile graphics
  LD (60126),DE           ; Store screen display address position
; Draw graphic tile on screen
L56612_1:
  LD A,(HL)               ; Copy graphic byte onto screen:
  LD (DE),A               ;
  INC HL                  ; Move to next graphic byte
  LD A,D                  ; Get pixel row
  AND 7                   ;
  INC A                   ; Move down to next pixel row
  CP 8                    ; Are we crossing a pixel/character boundary?
  JR C,L56612_2           ; ...If not, move down 1 pixel row and continue
                          ; drawing the graphic
  LD A,D                  ; ...If so, recalculate screen display address. Get
                          ; high byte of screen address
  AND 248                 ; Reset the low 3 bits (pixel row number) to zero
  LD D,A                  ;
  LD A,E                  ; Get the low byte of the screen address
  ADD A,32                ; Increment column by 32 to move down to next screen
  LD E,A                  ; row
  JR NC,L56612_3          ; Crossing a 1/3 screen boundary? ...If not, skip
                          ; next 3 instructions
  LD A,D                  ; ...If so, adjust high byte of screen address
  ADD A,8                 ; accordingly
  LD D,A                  ; Store correct screen address high byte back in D
  JR L56612_3             ; register
L56612_2:
  INC D                   ; Move down 1 pixel row
L56612_3:
  DJNZ L56612_1           ; Repeat for all pixel rows of this graphics tile
; Continue to draw the remaining tiles in the graphic
  LD DE,(60126)           ; Retrieve screen display address
  INC E                   ; Move right one character square
  DEC C                   ; Decrement tile graphic counter
  JR NZ,L56612_0          ; If there are tiles left in the graphic, draw the
  RET                     ; next one.

; Print the active spell's message text
;
; Used by the routines at L59262, L59474, L59689 and L59933.
;
; Called from routine at 59287. This prints the relevant spell message text (at
; L28604) for the active spell using the text print routine at L58064_0.
; * The message isn't printed all at once, but appears letter by letter as
;   gameplay continues
; * The text print routine expects the full text string length, and the screen
;   display address in this routine is set to 56693
; * So for "PROJECT THY SOUL" (MOVE spell), instead of "P", then "R", then "O"
;   etc. being printed, we have "P", "PR", "PRO", "PROJ" etc.
L56668:
  LD A,(60361)            ; Character number in the current spell message text
  LD C,A                  ;
  LD DE,(60138)           ; Active spell message text address pointer
  LD A,(DE)               ; Get length of the message text
  INC DE                  ; And advance to the first message text character
  CP C                    ; Check if we've reached the end of the text to print
  JR Z,L56702             ; If so, skip the text print routine
  LD A,C                  ; Retrieve and increment the text counter number...
  INC A                   ;
  LD (60361),A            ; ...and re-store
  LD (L60065),DE          ; Store the text address pointer
  LD (60067),A            ; Number of text characters to print
  LD HL,20616             ; Set screen display address - middle of scroll, on
                          ; left
  LD (60068),HL           ; ...and store
  CALL L58064_0           ; Print text on scroll

; Set length of Maroc's energy bar based on his current energy level
;
; Used by the routine at L56668.
;
; The next routine changes the screen display attributes so the energy bar
; reflects Maroc's current energy
;
; When Maroc has full energy, the whole energy bar is INK 2, PAPER 6 (attribute
; value = 50). As Maroc loses energy, the bar is reduced from the right by
; setting character attributes to INK 6, PAPER 6 (54), so the pixels are
; invisible.
L56702:
  LD A,(60128)            ; Get Maroc's current energy (0-255)
  RRA                     ; Each of the 16 energy bar character squares
  RRA                     ; represents 16 energy units, or part thereof, so
  RRA                     ; divide by 16
  RRA                     ;
  AND 15                  ; Keep the bottom four bits to give a value of 0-15
  LD C,A                  ;
  LD A,16                 ; Subtract from 16 to give the number of energy bar
  SUB C                   ; characters to remove
  LD B,16                 ; 16 character squares
  LD HL,23239             ; Screen attribute display address - start of energy
                          ; bar at bottom left of scroll
; Count backwards (B register) from 16 to 0, comparing against Maroc's energy
; and obscuring squares accordingly.
L56702_0:
  CP B                    ; Check current position to see if it's one that
                          ; needs obscuring
  JR C,L56702_1           ; If there's a carry, jump to L56702_1 to keep the
  CP 1                    ; character square as INK 2, PAPER 6
  JR Z,L56702_1           ; Because Maroc's 'energy squares' value is in the
                          ; range 0-15 (rather than 1-16), this check/jump
                          ; ensures that the rightmost bit of flame isn't
                          ; hidden when Maroc has full energy.
  LD (HL),54              ; Set the character square attribute as invisible
  JR L56702_2             ; (INK 6, PAPER 6)
L56702_1:
  LD (HL),50              ; Set the character square attribute as visible (INK
                          ; 2, PAPER 6)
L56702_2:
  INC HL                  ; Move screen attribute address right one character
                          ; square along the energy bar
  DJNZ L56702_0           ; ...and keep checking for all 16 squares.
  RET                     ;

; Draw/erase foreground scenery items
;
; Used by the routine at L54524.
;
; These drawing/erasing routines are similar to the standard ones at L56309,
; but because the foreground scenery occupies its own screen area and won't
; overlap other scenery, they're simplified slightly.
L56737:
  LD A,0                  ; Flag indicating whether (any part of) graphic is
  LD (60117),A            ; visible on screen - set to 0 at start of graphics
                          ; routine
  LD HL,(60109)           ; Graphic address pointer to foreground scenery
                          ; graphics
  LD A,(HL)               ; Byte indicating number of tiles within the graphic
  INC HL                  ;
; Tile drawing loop
L56737_0:
  LD (60112),A            ; Store graphic tile counter
  LD C,(HL)               ; Horizontal graphic offset (in pixels)
  INC HL                  ;
  EX DE,HL                ; Swap graphic address pointer into DE
; Adjust graphic's screen position with horizontal offset:
  LD HL,(60115)           ; Horizontal graphic position on screen in pixels
  LD A,C                  ; Get horizontal graphics pixel offset value
  RLA                     ; Rotate the bits left
  SBC A,A                 ; If this subtract creates a carry, it means the
                          ; graphic offset is negative, otherwise positive
  LD B,A                  ; Store this value in B register (255 = negative, 0 =
                          ; positive)
  ADD HL,BC               ; Add (or subtract if negative) the offset from the
                          ; horizontal graphics position
  EX DE,HL                ; Swap into DE
  LD A,D                  ; Get high byte of offset
  CP 0                    ;
  JP NZ,L56737_10         ; If not zero it means the horizontal pixel position
                          ; has gone over 255 and is therefore out of bounds.
                          ; Jump out here and skip the rest of this tile.
; Calculate the graphic's horizontal screen display address column position,
; and put into the E register:
  LD A,E                  ; The low byte (in the E register) contains the
                          ; horizontal pixel position (including offset)
  RRA                     ; Get the graphic's screen character column by
  RRA                     ; dividing the pixel value by 8
  RRA                     ;
  AND 31                  ; Filter out bits 5-7 (only values 0-31 needed)
  DEC A                   ;
  CP 28                   ; Right-hand column screen border check
  JP NC,L56737_10         ; No carry means character position is into the right
                          ; border - jump out here
  INC A                   ; Increment to return to place after the DEC a few
                          ; instructions earlier
  INC A                   ; The horizontal position is stored from column 1
                          ; (2nd screen column), whereas screen display address
                          ; counts from column 0 as the first one, so adjust
                          ; the horizontal character position by +1 so that it
                          ; calculates correctly
  LD E,A                  ; Store adjusted column position in E register
; Check for vertical screen (scroll) boundary:
  LD C,(HL)               ; Get vertical graphic pixel offset value
  LD A,(60114)            ; Graphic's vertical screen position
  ADD A,C                 ; Add the offset
  CP 112                  ; Vertical pixel position 112 is the top of the
                          ; scroll, out of bounds for drawing graphics
  JR NC,L56737_10         ; No carry here means the object is in the scroll
                          ; area at the bottom of the screen, and out of bounds
                          ; for drawing - jump out here
; Calculate high byte/vertical part of screen display address:
  ADD A,16                ; The vertical graphic position is stored from the
                          ; top of the playing area, but the screen display is
                          ; calculated from the very top of the screen.
                          ; Therefore add 16 pixels to adjust for the
                          ; decorative border offset at the top of the screen
  LD D,A                  ; Store in high byte of screen display address
  AND 7                   ; Bits 0-2 indicate pixel number (0-7) in character
                          ; row
  LD C,A                  ; Put in C register for safe keeping
  INC HL                  ;
  LD A,1                  ; This is the flag indicating whether (any part of
                          ; the graphic) is visible on-screen (0 = not visible,
                          ; 1 = visible)
  LD (60117),A            ; It's set here to visible (1) as part of the item is
                          ; visible
  LD A,D                  ; Get the graphic's adjusted vertical screen pixel
                          ; position
  RLA                     ; Character row is currently indicated by bits 3-5 so
  RLA                     ; shift them left twice to bits 5-7
  AND 224                 ; Get those top three bits (filter out any others)...
  ADD A,E                 ; ...and combine them with bits 0-4 which hold the
  LD E,A                  ; column number, to form the screen display address
                          ; low byte
  LD A,D                  ; Vertical pixel position, from top of screen display
  RRA                     ; Divide by 8 to get screen display (character) row
  RRA                     ;
  RRA                     ;
  AND 24                  ; Bits 3 (8) and 4 (16) include the screen display
                          ; address high byte character row (0-24)
  ADD A,64                ; Set bit 6 (always set for screen addresses)
  ADD A,C                 ; C contains the pixel row number in the character
                          ; line (0-7). Add this to the high byte of the
                          ; address
  LD D,A                  ; Put the calculated screen address high byte into
                          ; the D register
  LD B,(HL)               ; Number of bytes in the graphic tile to print
  INC HL                  ; Advance address pointer to start of tile graphics
  EX DE,HL                ; ...and swap into DE register
  LD A,(60111)            ; Check draw/erase flag
  CP 1                    ;
  JR Z,L56737_4           ; If it's DRAW, jump out here....
; ERASE graphic pixels on screen:
  LD A,H                  ; Erase pixels within this character square - get
                          ; pixel row in character square from screen display
                          ; address
  AND 7                   ; Keep bits 0-2 so that A now contains the pixel row
                          ; number in the character square
; Erase pixel loop. Foreground scenery is out of the way of other room
; scenery/items so no need to use AND and OR to preserve existing pixels:
L56737_1:
  LD (HL),0               ; Clear pixels in this on-screen byte
  INC DE                  ; Move to next byte of graphic tile (mainly for count
                          ; purposes)
  INC A                   ; Increment the pixel row count/number
  AND 7                   ;
  JR Z,L56737_2           ; If zero we've got to pixel row 8, so jump out here
                          ; to re-calculate screen display address for the next
                          ; pixel row
  INC H                   ; ...Otherwise move down one pixel line
  JR L56737_3             ; ...And continue clearing the square
; Re-calculate screen display address with new pixel row:
L56737_2:
  LD A,H                  ; Reset pixel row (bits 0-2 in high byte of the
  AND 248                 ; screen display address)
  LD H,A                  ;
  LD A,L                  ; Increment column by 32 to move down to next screen
  ADD A,32                ; row
  JR C,L56737_7           ; Crossing a 1/3 screen boundary? ...If so, jump out
                          ; of routine here
  LD L,A                  ; Otherwise, store the amended screen display address
                          ; low byte
  LD A,0                  ; ...reset the pixel counter to 0...
L56737_3:
  DJNZ L56737_1           ; ...and draw the rest of the bytes in the tile
  JR L56737_9             ; When finished, go and check if there are more tiles
                          ; to draw
; DRAW graphic pixels on screen:
L56737_4:
  LD A,(DE)               ; Get graphics byte
  LD (HL),A               ; Draw on screen
  INC DE                  ; Move to next byte of the graphics tile
  LD A,H                  ; Increment and check the pixel row (bits 0-2 of
  INC A                   ; screen display address high byte)
  AND 7                   ;
  JR Z,L56737_5           ; If zero we've got to pixel row 8, so jump out here
                          ; to re-calculate screen display address for the next
                          ; pixel row
  INC H                   ; ...Otherwise, move down one pixel line
  JR L56737_6             ; ...And continue clearing the square
; Re-calculate screen display address with new pixel row:
L56737_5:
  LD A,H                  ; Reset pixel row (bits 0-2 in high byte of the
  AND 248                 ; screen display address)
  LD H,A                  ;
  LD A,L                  ; Increment column by 32 to move down to next screen
  ADD A,32                ; row
  JR C,L56737_7           ; Crossing a 1/3 screen boundary? ...If so, jump out
                          ; of routine here
  LD L,A                  ; Otherwise, store the amended screen display address
                          ; low byte
L56737_6:
  DJNZ L56737_4           ; ...and continue to draw the rest of the tile
                          ; graphic
  JR L56737_9             ; When finished, go and check if there are more tiles
                          ; to draw
; ERASE or DRAW screen display address has moved into the next third of the
; screen.
;
; As this will be the bottom third of the screen where the scroll is, there's
; no need to calculate anything - there's nothing more to erase/draw.
L56737_7:
  DEC DE                  ; DE was prematurely incremented in the loops at
                          ; 56836 or 56863 so if this was done, revert this
                          ; change
L56737_8:
  INC DE                  ; Then increment it by the remaining tile bytes, to
  DJNZ L56737_8           ; get to the start of the next tile
; Tile finished - check for next tile:
L56737_9:
  EX DE,HL                ; Swap the screen display address and graphics
                          ; address pointers
  LD A,(60112)            ; Get the graphic tile counter
  DEC A                   ; Reduce by one
  JP NZ,L56737_0          ; If there are still tiles to draw, go and draw them
  JR L56737_11            ; Jump to RET at the end of this routine
; Jump here if screen position to draw/erase to is in right screen border (from
; 56777) or into the scroll at the bottom third of the screen (from 56790)
;
; Nothing to draw/erase for the rest of this tile, so can skip past it
L56737_10:
  INC HL                  ; Move pointer to the address holding the number of
                          ; graphic bytes in this tile
  LD B,(HL)               ; Get the byte counter
  INC HL                  ; Advance to the start of the tile's graphic bytes
  EX DE,HL                ; Swap back into DE register pair
  JR L56737_8             ; Jump to the routine that skips the rest of the
                          ; bytes
; Jump here once all of the tiles have been drawn/erased
L56737_11:
  RET

; Identify objects for current room
;
; Used by the routines at L50218, L52913 and L53273.
;
; B Room number (from 60087)
; HL Address pointer to start of room item data at L29551
; C Object number in table at L29551 (starts at #1)
;
; This routine uses the room object table at L29551 and has a dual function:
; * Upon room entry, the routine checks for any objects in the room (first byte
;   of set = room number)
; * The routine can also identify an object's data set from its object number
;
; Depending on which check is needed, the B or C register is set before this
; routine is called, with the other set to zero.
;
; In either case, once the item data is found, its details & current 'state'
; are copied into the object data set buffer at 60293.
L56908:
  LD A,(60292)            ; Counter. Starts at 0.
  INC A                   ; Room/object numbers start from 1 so we need to
                          ; immediately increment the counter for the first
                          ; data set...
  LD (60292),A            ; ...and re-store
  LD A,(HL)               ; First byte of data set
  CP 255                  ;
  JR NZ,L56908_0          ;
  LD (60292),A            ; We've reached the end of the list - set counter
                          ; byte to 255...
  JR L56959_5             ; ...and jump straight to RET
; There are data sets still to check:
L56908_0:
  LD A,C                  ; Are we doing the check against an object number or
  CP 0                    ; a room number?
  JR NZ,L56908_1          ; Run one of the next two checks depending on whether
                          ; the B or the C register contains the value to check
; ROOM NUMBER CHECK
  LD A,(HL)               ; C register is 0 so it's a room number check. Get
                          ; the first byte of the room object set (this is the
                          ; room number of the object)
  CP B                    ; Current room number - is the object in this room?
  JR Z,L56959             ; If so, we've found an object in the room so jump to
  JR L56908_2             ; next routine to deal with it
; OBJECT NUMBER CHECK
L56908_1:
  LD A,(60292)            ; As we know the object number (data set number), we
                          ; just need to perform the check against the
                          ; incremental counter to find its data
  CP C                    ; Check object number set against counter
  JR Z,L56959             ; If we've found it, jump to the next routine to
                          ; handle its data
; Object not found in this set after one of the above checks. Skip forward to
; next data set.
;
; Data sets vary in size, so this routine identifies the number of bytes that
; need skipping to get to the next set.
L56908_2:
  LD DE,7                 ; Jump forward to 8th byte in original data set
  ADD HL,DE               ;
  LD A,(HL)               ; Byte indicates number of additional 4 byte data
  INC HL                  ; sets this item has
  LD DE,4                 ; 4 bytes for each set to skip
L56908_3:
  CP 0                    ; Have we skipped all the additional 4-byte sets for
                          ; this item?
  JR Z,L56908             ; If so, go and check for the next object in the list
  ADD HL,DE               ; Skip this 4-byte data set
  DEC A                   ; Decrement the data set counter
  JR L56908_3             ; ...Until they're all skipped.

; Identify state of object in current room
;
; Used by the routines at L51968, L56028 and L56908.
;
; HL Address pointer to room/object data at L29551
;
; The fifth byte of an object's data set (held in the object buffer at 60297)
; holds its state, which can change. For example a chest can be closed (state =
; 1) and be moved to state 2 (open).
;
; This routine identifies the state of the object and copies the 4 bytes for
; this state into the additional buffer at 60301.
L56959:
  LD (L60290),HL          ; Store address pointer (data at L29551)
  LD DE,60293             ; Copy the first 8 bytes of this object's data into
  LD BC,8                 ; buffer at 60293
  LDIR                    ;
  LD A,(60297)            ; State number of this object. All standard object
  LD C,A                  ; 'sets' start at 1
  CP 0                    ;
  JR Z,L56959_3           ;
  DEC A                   ; Decrement state number
  CP 0                    ; Is this the object's current state?
  JR Z,L56959_1           ;
  LD DE,4                 ; If so, skip 4 bytes for each state the object has
  LD B,A                  ; advanced to
L56959_0:
  ADD HL,DE               ;
  DJNZ L56959_0           ;
; Current object state found:
L56959_1:
  LD B,4                  ; Copy the 4 data bytes for this object state into
  LD DE,60301             ; the additional buffer at 60301
L56959_2:
  LD A,(HL)               ;
  LD (DE),A               ;
  INC HL                  ;
  INC DE                  ;
  DJNZ L56959_2           ;
; Skip over any additional data sets for this object
L56959_3:
  LD A,(60300)            ; Get the count of additional 4 byte data sets for
                          ; this object
  SUB C                   ; Subtract the current state number, whose data has
                          ; already been copied over to the buffer
  JR Z,L56959_5           ; If zero, there's no more data for this set - jump
                          ; straight to RET
  LD DE,4                 ; ...Otherwise, skip over the remaining object states
  LD B,A                  ;
L56959_4:
  ADD HL,DE               ;
  DJNZ L56959_4           ;
; This entry point is used by the routine at L56908.
L56959_5:
  RET                     ; Object set now dealt with

; Create data set for interactable room object and copy item/graphic data into
; it
;
; Used by the routine at L50218.
;
; An interactable object has been found in the room Maroc is entering.
;
; This routine:
; * Sets some data for the object in the data buffer at L60227, including
;   graphics data for the object
; * Copies this data into a room item data set at 31744
L57015:
  LD A,4                  ; Graphic type = 4 (interactable object)
  LD (L60227),A           ;
  LD A,(60292)            ; Data set number for interactable object - from
  LD (60230),A            ; object table at L29551
  LD HL,(L60290)          ; Address pointer to the beginning of this
  LD (60228),HL           ; interactable object's data set
  LD A,(60294)            ; Horizontal (X) position of object in room, in
  LD (60232),A            ; 4-pixel (half-character) steps
  LD A,(60295)            ; Vertical (Y) position of object in room, in pixels,
  LD (60234),A            ; from top of room
  LD A,64                 ; 64 signifies item in 'standard' room (254/255 for
  LD (60235),A            ; tunnel room items)
  LD DE,0                 ; Set vertical and horizontal speed of item to zero
  LD (60236),DE           ;
  LD (60237),DE           ;
  LD A,(60296)            ; Copy item properties byte into data buffer
  LD (60238),A            ;
  LD A,1                  ; Graphic address frame offset = n-1 (= 0, no offset)
  LD (60240),A            ;
  LD A,(60304)            ; Graphics number for this item (offset for address
                          ; pointer in graphics table starting at L38851)
  CALL L57538             ; Set up graphics for this interactable object
  CALL L57520             ; Copy item data buffer (L60227) into a data set at
  RET                     ; 31744

; Clear the scroll status panel at the bottom of the screen
;
; Used by the routines at L49215, L51043, L55944, L58599, L58945, L59130 and
; L59956.
L57081:
  LD HL,20551             ; Screen address for the top left of the scroll
  LD C,5                  ; 5 character rows to clear
L57081_0:
  LD D,18                 ; 18 columns wide
L57081_1:
  LD B,8                  ; 8 pixels in each character square
L57081_2:
  LD (HL),0               ; Clear screen address byte
  INC H                   ; Move down 1 pixel row
  DJNZ L57081_2           ; Repeat x 8 pixel rows
  LD A,H                  ; Return address pointer to top of block
  SUB 8                   ;
  LD H,A                  ;
  INC L                   ; ...and move right one character square
  DEC D                   ; Repeat for 18 columns
  JR NZ,L57081_1          ;
  LD A,L                  ;
  ADD A,14                ; Increase low byte of screen address pointer to move
  LD L,A                  ; to next row down
  DEC C                   ; Repeat until all 5 rows are clear
  JR NZ,L57081_0          ;
  LD HL,20711             ;
; Finally, clear the bottom 4 pixels of the scroll, just under the dragon flame
; energy bar.
;
; This space doesn't seem to get text or graphics on it - and it's slightly odd
; that the whole line isn't cleared (only 11 columns). Perhaps the scroll
; status display was set out differently to begin with.
  LD D,11                 ; 11 character columns to clear
L57081_3:
  LD B,4                  ; Just 4 pixels (half a character square) needed to
                          ; clear
L57081_4:
  LD (HL),0               ; Clear the screen byte
  INC H                   ; Move to the next pixel line down
  DJNZ L57081_4           ; ...and repeat for the 4 pixel rows
  DEC H                   ; Return back up 4 pixels...
  DEC H                   ;
  DEC H                   ;
  DEC H                   ;
  INC L                   ; ...and move right one square
  DEC D                   ; Repeat x 11 columns
  JR NZ,L57081_3          ;
; This sets two screen graphic bytes in the top left of the smaller overlapping
; scroll (in the bottom right of the screen).
;
; It's unclear why this is needed - these bytes don't seem to get overwritten
; at any point. Again, perhaps it's from a previous clearing or graphic routine
; that affected them in some way.
  LD HL,22487             ; Screen address for top left of overlapping scroll
  LD (HL),7               ; First byte
  INC HL                  ;
  LD (HL),255             ; Second byte
  RET                     ;

; Print spell names on the scroll
;
; Used by the routines at L58945 and L59033.
;
; Checks each spell in the spell index at L28156, to see if Maroc has it.
;
; For each spell found (up to 5), prints the spell name text on the scroll, and
; plays a short sound effect.
L57139:
  LD A,(60130)            ; Spell list index
  LD (60133),A            ; Copy spell list index into spell list counter
  LD DE,(60131)           ; Address pointer to the start of spell list text at
                          ; L28156
  LD A,1                  ; Scroll text line counter (1-5)
  LD (60103),A            ;
  LD HL,20554             ; Screen address of top text line of scroll, 3
                          ; characters from the left hand side
L57139_0:
  LD (60126),HL           ; Put screen display address in temp store for
                          ; retrieving later
  LD B,8                  ; Move address pointer along 8 bytes to get to the
L57139_1:
  INC DE                  ; first/next spell text (e.g. "MOVE" at 28164)
  DJNZ L57139_1           ;
  LD (L60065),DE          ; Store spell text address pointer
  LD (60068),HL           ; Store the screen display address
  LD A,8                  ; Store length of text string to print - spell texts
  LD (60067),A            ; at L28156 are padded with spaces to make them all 8
                          ; characters long
  CALL L58064_0           ; Print the spell text on the scroll
  LD HL,(L60065)          ; Retrieve the spell text address pointer - this is
                          ; now pointing at the data after the spell text, e.g.
                          ; 28172.
; This section runs through each spell and checks to see if the player has
; collected it. If so, the text can be printed on the scroll.
;
; Five spells are always displayed on the scroll in a wraparound vertical
; scrolling list. If the player has fewer than five spells, one or more will
; show at least once.
;
; At the start of the game the player only has the 'MOVE' spell, so this
; appears five times.
L57139_2:
  LD A,(60265)            ; Total number of spells to check - 27
  LD C,A                  ;
  LD A,(60133)            ; Spell list counter
  CP C                    ; Check if at the end (spell #27)
  JR NZ,L57139_3          ;
  LD A,0                  ; If so, reset counter to zero...
  LD HL,(60261)           ; ...and return the spell name text address pointer
  JR L57139_4             ; to the start of the list, e.g. L28156.
L57139_3:
  INC A                   ; If we're not at the end of the list, increment the
L57139_4:
  LD (60133),A            ; spell list counter.
  LD A,(HL)               ; Get the the first byte (after the spell name).
  CP 16                   ; Check if this byte = 16, which indicates the player
                          ; has collected the spell
  JR Z,L57139_5           ; If so, jump out and print the spell name
  LD BC,16                ; The player hasn't collected this spell, so move the
  ADD HL,BC               ; spell text address pointer along 16 bytes to the
  JR L57139_2             ; next spell and repeat the checking loop.
; Spell name to print found (Maroc has this spell).
;
; First, play a short sound as the player scrolls through the spell list:
L57139_5:
  OUT (254),A             ; The 'A' register is 16 from previous routine (bit 4
                          ; is set), so it's used here to switch the speaker on
  LD A,(60070)            ; Counter (initialized at 5) which is used to
                          ; determine an incremental series of 5 tones, while
                          ; the player holds down a key to scroll through the
                          ; spell list
  CP 0                    ; Counter = 0?
  JR Z,L57139_7           ; If so, skip next routine (this keeps the tone at
                          ; its highest pitch)
  RLA                     ; Take counter and x 2
  RLA                     ; 5 rotates to shift bits 0-2 of the counter into
  RLA                     ; bits 5-7
  RLA                     ;
  RLA                     ;
  AND 224                 ; Filter out unwanted bits 0-4
  LD B,A                  ; Store in B to act as a second counter
L57139_6:
  CALL L56070             ; Routine that generates a pseudo-random number.
  DJNZ L57139_6           ; ...The output from the CALLed routine isn't used,
                          ; it's just called multiple times to provide a handy
                          ; short delay for the speaker toggle effect/sound.
; Spell text line print checks
L57139_7:
  LD A,(60103)            ; Continue to check the spell index (at L28156) to
                          ; see which spells Maroc has, and print them on the
                          ; scroll
  CP 5                    ; 5 spells can be printed on the scroll. Have they
                          ; all been done?
  JR Z,L57139_9           ; If so, jump straight to RET at the end of this
                          ; routine
  INC A                   ; Otherwise, increment the scroll text line counter
  LD (60103),A            ; ...and re-store.
  CP 3                    ; Are we on spell text line number 3?
  JR NZ,L57139_8          ;
  LD A,(60133)            ; If so, this is the spell in the middle of the
                          ; scroll, that the selection arrow is pointing at
  LD (60134),A            ; So set the 'currently highlighted' spell as this
                          ; one
  LD (60135),HL           ; ...and also store the address pointer to this
                          ; spell's data (L28156).
; Prep for printing next line of text:
L57139_8:
  EX DE,HL                ; Put the current spell index list address pointer
                          ; into the DE register, ready for checking/printing
                          ; any other spells the Maroc might have (from
                          ; L57139_0)
  LD HL,(60126)           ; Retrieve the screen display address
  LD BC,288               ; Move the screen display address down 9 pixels ready
  ADD HL,BC               ; for the next line of spell text. 288 is 256 (one
                          ; pixel line down) plus 32 (8 pixel lines down).
  LD A,0                  ; Toggle speaker (bit 4) off
  OUT (254),A             ;
  JR L57139_0             ; Keep checking for spells to print
L57139_9:
  RET                     ; RETurn after 5 spells printed

; Calculate servant/icon cursor graphic horizontal/vertical direction & speed
;
; Used by the routines at L59736 and L59783.
;
; A Left/right control value (from L60157) or up/down control value (from
;   60158)
; C Horizontal/vertical movement speed at 60161/60162
;
; Identifies if the servant/cursor is moving, in which direction, and
; adds/subtracts movement speed accordingly. Deals with both vertical and
; horizontal movement.
;
; Returns the calculated value (either zero for no movement, or a
; positive/negative value) in the H register. This is later used to calculate
; the sprite's new vertical/horizontal position.
;
; Called from 59743 (horizontal movement) and 59790 (vertical movement).
L57276:
  CP 0                    ; Is there any movement in the direction being
                          ; checked (horizontal/vertical)?
  JR Z,L57276_0           ; If there isn't, set movement offset to 0 and RET
  NEG                     ; Positive/negative values stored are the opposite of
                          ; Maroc's movement, so make negative (otherwise
                          ; player controls will appear reversed)
  LD B,A                  ; Temp store in B register
  ADD A,C                 ; Add the speed to the direction
  LD H,A                  ; ...and store in H
; The next 3 instructions set a 'terminal velocity' speed. It ensures speed is
; reset to 0 when a certain speed (128) is reached:
  XOR B                   ; Compare with adjusted speed (retain where bits are
                          ; different)
  AND 128                 ; Check bit 7 - if this bit is set, the servant has
                          ; reached terminal speed (in either direction)
  JR Z,L57276_1           ; However, the screen size means this speed can't be
                          ; reached, so a NZ (non-zero) result shouldn't
                          ; normally happen
L57276_0:
  LD H,0                  ; If terminal velocity has been reached, set
L57276_1:
  RET                     ; movement/speed back to zero

; Check for events/collisions
;
; Used by the routines at L51854, L52118, L52263, L52338, L52513, L52582,
; L52616, L53323, L53526, L53714, L54393 and L54429.
;
; C Collision/event type, e.g.: 0 = Collision with Maroc, e.g.: creature
;   missile hitting Maroc (53533) or Maroc moving through an open doorway
;   (51737) 1 = Door opening/closing (L51854) 3 = Check for creature being
;   destroyed (e.g. by missile/sword) 5 = Servant picking up an object (L52582)
;   15 = Item being collected by Maroc (checked at L52338) 136 = Check for
;   Maroc entering portal door in room 81 L54429 137 = Maroc has destroyed
;   Avelach with Caliburn (52270) 253 = Check if Maroc is touching a
;   (stationary) energy-restoring object - from L54393_0 254 = Check if Maroc
;   is touching a (stationary) energy-draining object - from 54401
; D Horizontal (X) position (in pixels) for graphic, e.g. servant, door
; E Vertical (Y) position (in pixels), e.g. servant, door
;
; Check for a variety of collisions, or 'instances of items touching other
; items':
; * Servant picks up an object
; * Servant uses an object on another object/creature
; * Servant gives an item to a warlock
; * Servant touches an open door handle
; * Maroc's missile/bolt collides with a creature
; * Maroc touches an object that restores/drains energy
; * Creature missile hits Maroc
; * Creature closes a door (touches the handle of an open door)
;
; The routine returns the A register containing 0 (no collision) or 1
; (collision has taken place):
L57293:
  LD A,(60115)            ; Graphic's horizontal position, in pixels, starting
  LD D,A                  ; from screen pixel column 8 (halfway into left
                          ; decorative border)
  LD A,(60114)            ; Graphic's vertical position, in pixels, from top of
  LD E,A                  ; playing area
; Horizontal (D) and vertical (E) pixel co-ordinates either identified in the
; previous 4 instructions, or pre-loaded prior to a CALL directly here (e.g.
; 55355 for servant checks)
L57293_0:
  LD A,(60116)            ; This byte indicates whether the item is in the
                          ; current view horizontally (0), off-screen to the
                          ; right (1), or offscreen to the left (255)
  CP 0                    ; If it's NOT zero, it's off-screen so no collision
  JR NZ,L57293_7          ; action needs checking. Jump to the end of this
                          ; routine (setting no collision/energy drain flag to
                          ; zero)
  LD A,C                  ; Retrieve the value from the C register from the
                          ; previous routine - this is the collision/event
                          ; check value to test
  CP 0                    ; 0 tests for a collision with Maroc - e.g. the
  JR Z,L57293_1           ; servant and Maroc's backpack (placing/retrieving
                          ; items)
  CP 1                    ; Collision value 1 = Opening/closing doors
  JR Z,L57293_1           ; interactions This is checked for both Maroc's
                          ; sprite (bumping into doors) and other collisions
                          ; (e.g. missile, servant)
  JR L57293_2             ; All other sorts of event/collision
; CHECK FOR COLLISIONS WITH MAROC'S SPRITE.
;
; This could be the servant (for object manipulation) or Maroc opening a door.
L57293_1:
  LD A,120                ; 120 (in pixels) is roughly 1 character/8 pixels to
                          ; the right of the centre of the screen - Maroc's
                          ; horizontal central point
  SUB D                   ; Subtract the graphic's horizontal (X) position
  CP 16                   ; If the difference is <= 16 pixels, the other room
                          ; item is (horizontally) close enough to Maroc
  JR NC,L57293_2          ; Collision NOT within horizontal 'hit box'. Skip
                          ; next few instructions
  LD A,(60097)            ; Collision IS within horizontal 'hit box'. Get
                          ; Maroc's vertical (Y-axis) screen position
  ADD A,8                 ; Maroc's central point/backpack is on the lower part
                          ; of his graphic, so move down 8 pixels...
  SUB E                   ; Subtract the graphic's vertical (Y) position
  CP 16                   ; If the difference is <=16 pixels, Maroc is
                          ; (vertically) close enough
  JR NC,L57293_2          ; Collision NOT within horizontal 'hit box'. Skip
                          ; next couple of instructions
; Positive collision with Maroc confirmed
  LD A,1                  ; Positive collision - set flag (A register) to 1
  JR L57293_8             ; Jump straight to RET
; CHECK FOR OTHER COLLISIONS/EVENTS
;
; Jump from 57317 if the collision type in the C register is NOT 0 ir 1 (all
; other event matches/collisions).
;
; This might be checking for collision with energy restoring (253) or draining
; (254) objects, or for an item acting on another (matching) item, such as a
; key and a chest.
L57293_2:
  LD A,C                  ; Retrieve the type-of-collision value to test/check
  CP 0                    ; Is it 0?
  JR Z,L57293_7           ; If so, that check's done, so can skip to the end
                          ; (setting collision flag to zero)
  LD B,253                ; 253 = value to test for energy-replenishing objects
                          ; However, this test won't match because of the AND 3
                          ; in a few instructions at 57368. Explicit event
                          ; checks for both energy-draining (C=254) and
                          ; energy-restoring (C=253) objects are CALLed in the
                          ; routine at L54393
  LD HL,(60268)           ; Pointer to room item event table at 32691.
  CP 4                    ; Check if type-of-collision value >= 4
  JR NC,L57293_3          ;
  LD B,C                  ; If < 4, store the type-of-collision value in B
                          ; register
  LD C,0                  ; ...and set C register to 0
L57293_3:
  LD A,(HL)               ; Get first byte from data table (at 32691)
  INC HL                  ; (...and move the pointer along)
  CP 255                  ; Is there data to check in this set (255 =
                          ; end-of-data)?
  JR Z,L57293_7           ; If not, skip to the end of this routine, setting
                          ; collision/energy drain flag to zero
  LD A,(HL)               ; Get the (second) byte in the set
  INC HL                  ; (...and move the pointer along)
  CP C                    ; Check collision test value vs object/item collision
                          ; type (second byte in set at 32691) to see if it
                          ; matches
  JR Z,L57293_4           ; If so, jump to check Maroc's 'hit boxes' for a
                          ; collision
; Check door-, spell- or creature-related interactions. For example:
; * goblins have a creature event value - for items acting on them - of 3
; * missiles 2-7 in the table at L27868 have bits 0 & 1 of their event byte set
;   (value = 3)
; * similarly Caliburn (30907) and the animated sabre (31331) have bits 0-1 of
;   their event byte set (value = 3)
;
; By just filtering these two bits, we can set/determine which items or spells
; will cause a positive event/collision on goblins.
  AND 3                   ; This filters bits 0-1 (values 1-3)
  CP B                    ; If no match for this, continue to check the event
  JR NZ,L57293_5          ; table at 32691
; Check X/Y co-ordinates for collision
;
; First, an X (horizontal) co-ordinate check:
L57293_4:
  LD A,(HL)               ; Get item's horizontal pixel co-ordinate (byte 3 of
                          ; item set at 32691)
  INC HL                  ; (...and move the pointer along)
  ADD A,8                 ; The collision check is a 16-pixel horizontal
                          ; collision area, so adding 8 is an offset which
                          ; gives it an 8-pixel-each-side collision box
  SUB D                   ; Subtract the horizontal pixel co-ordinate of the
                          ; 'acting item'
  CP 16                   ; Is the difference within the 16 pixel 'hit box'
                          ; threshold (8 pixels left/right of target
                          ; co-ordinates)?
  JR NC,L57293_6          ; If not, no need to check vertical co-ordinates
; Y (vertical) co-ordinate check:
  LD A,(HL)               ; Get item's vertical pixel co-ordinate (byte 4 of
                          ; item set at 32691)
  ADD A,8                 ; The collision check is a 16-pixel vertical
                          ; collision area, so adding 8 is an offset which
                          ; gives it an 8-pixel-each-side collision box
  SUB E                   ; Subtract the vertical pixel co-ordinate of the
                          ; 'acting item' (e.g. servant)
  CP 16                   ; Is the difference within the 16 pixel 'hit box'
                          ; threshold (8 pixels left/right of target
                          ; co-ordinates)
  JR NC,L57293_6          ; If not, jump to set negative collision flag (0) in
                          ; A register
; POSITIVE COLLISION
  LD A,1                  ; Set collision flag (A register) to 1 - collision
                          ; has taken place with this item.
  JR L57293_8             ; Jump straight to RET and deal with it
; No positive collision found for this object - move to next item and continue
; checks:
L57293_5:
  INC HL                  ; Jumps from 57371...
L57293_6:
  INC HL                  ; ...and from L57293_6, that advance the address
  JR L57293_3             ; pointer to the next data set (at 32691).
; NEGATIVE COLLISION - Set collision flag (A register) to 0 - no collision has
; taken place with any on-screen objects.
L57293_7:
  LD A,0
; Routine returns with A register either set to 1 (collision) or 0 (no
; collision)
L57293_8:
  RET

; Check if Maroc or room item is within room boundaries
;
; Used by the routines at L51968, L52059, L52136, L53323, L53550 and L59630.
;
; E Screen vertical alignment/displacement value - calculated vertical height
;   boundary based on screen viewport position For Maroc's basic room position,
;   this is between 42 (Maroc at his lowest position in the room) and 90 (Maroc
;   at his highest point in the room) Set to 90 for Maroc's checks at L59630
;
; Room boundary checks. If Maroc or an item hits a wall/boundary of a room, he
; bounces off it, in the opposite direction to his current movement.
;
; This boundary check routine applies to all items, such as missiles and thrown
; objects.
;
; Any objects hitting the side walls will bounce off sideways, away from the
; wall.
L57401:
  LD B,0                  ; B register unused in this routine
  LD A,(60232)            ; Graphic's horizontal position on screen (in
  LD D,A                  ; half-character/4-pixel steps)
  LD HL,(60236)           ; H register = object's vertical speed/direction ( >
                          ; 128 = negative = up, < 128 = positive = down )L
                          ; register = object's horizontal movement
                          ; speed/direction ( > 128 = negative = left, < 128 =
                          ; positive = right)
; ROOM TOP/BOTTOM BOUNDARY CHECKS
  LD A,(60154)            ; Vertical screen position/alignment
  LD C,A                  ; Store in C register
  LD A,E                  ; E register has been calculated before the start of
                          ; this routine Contains vertical screen displacement
                          ; boundary to check against (as room can scroll
                          ; up/down) Based on Maroc's position in the room,
                          ; from 42 (lowest point of room) to 90 (highest point
                          ; of room)
  SUB C                   ; Subtract vertical position on screen
  LD C,A                  ; Store the difference in the C register
  CP 48                   ;
  JR C,L57401_1           ; If the difference is between 0 and 48 (carry
                          ; triggered) the graphic is within the top/bottom
                          ; vertical screen boundary
; Difference is too great (> 48). This means that Maroc or the item is passing
; either the TOP or BOTTOM of the vertical screen boundary allowed for it, so
; check which one:
  CP 128                  ; Jump if >= 48 but < 128 as it means vertical room
  JR C,L57401_0           ; position is < 42. Item is past the BOTTOM screen
                          ; boundary
; Vertical position is above boundary value which means item is past the TOP of
; the screen room boundary
;
; Correct the overspill so the difference is set to the max difference allowed
; (0)Ensure vertical movement value is a positive figure for the next
; calculation
  LD C,0                  ; The calculated difference is < 0, the minimum is 0
                          ; to set the difference to this
  LD A,H                  ; Vertical movement speed/direction
  CP 128                  ; For the next calculations we need the vertical
  JR C,L57401_1           ; movement value to be a positive number
  NEG                     ; If > 128 it's a negative value so set it to a
  LD H,A                  ; positive figure
  JR L57401_1             ;
; Vertical position is below 42 (from 57423) meaning he's past the BOTTOM of
; the screen room boundary.
;
; Correct the overspill so the difference is set to the max difference allowed
; (48)Ensure Maroc's vertical movement value is NEGATIVE for the next
; calculation
L57401_0:
  LD C,48                 ; The calculated difference is > 48. Max allowed
                          ; value is 48 so set the difference to this
  LD A,H                  ; Vertical movement speed/direction
  CP 128                  ; If > 128 (no carry), leave value as is
  JR NC,L57401_1          ;
  NEG                     ; If < 128 (carry), reverse the value to make it
  LD H,A                  ; negative
; ROOM LEFT/RIGHT BOUNDARY CHECKS
;
; At this point:
; * H register contains the item's/Maroc's (positive) vertical speed
; * C register contains the screen position offset, between 0 and 48.
;
; The side walls of the room slope towards the bottom of the screen, meaning
; the left/right room boundary changes depending on the vertical position.
;
; The angle of the side walls is not 45 degrees - it's half this angle. So
; halve the vertical offset/difference by 2:
L57401_1:
  LD A,C                  ; Get earlier calculated value - this is the top area
                          ; boundary minus screen vertical position
  RRA                     ; Divide by 2
  AND 127                 ; (Reset bit 7 from any earlier carry)
  LD C,A                  ; C register now contains half the difference (0-24)
; LEFT WALL BOUNDARY CHECK
  LD A,(60155)            ; This is the LEFT (vertical) corner of the room -
                          ; horizontal position, in half character squares (4
                          ; pixels) in the room, from the left of the room's
                          ; playing area.It's at this point that the left side
                          ; wall starts to slope down to the left hand side of
                          ; the screen
  SUB C                   ; Subtract the vertical difference (halved in
                          ; previous calculation to account for the side wall
                          ; 'slope')
  SUB D                   ; Subtract the horizontal co-ordinate (in
                          ; half-character/4-pixel steps)
  CP 32                   ; If <32, we've passed the side wall on the left -
                          ; bounce the item/Maroc back off the wall (to the
                          ; right)
  JR NC,L57401_3          ; If >=32 (no carry), we're fine as far as the left
                          ; room boundary is concerned, so jump out here for a
                          ; right-wall boundary check
; Item/Maroc has hit the LEFT of the room boundary. Ensure the horizontal
; movement speed value is positive, so the item/Maroc is moving right
  LD A,L                  ; Horizontal speed/direction
  CP 128                  ;
  JR C,L57401_2           ; If < 128 (carry), retain the positive value
  NEG                     ; If >= 128 (no carry), reverse the value to make it
  LD L,A                  ; positive
; Check vertical movement:
; * Maroc and other items can hit the side walls by moving upwards into them,
;   even if they're not moving left/right
; * If this happens, the item/Maroc bounces off the wall horizontally (rather
;   than vertically)
; * See the small diagram at the bottom of the original 80s scanned
;   illustration earlier on this page, to see this
L57401_2:
  LD A,H                  ; Check vertical speed/direction
  CP 128                  ; If < 128, Maroc is moving downwards - this is fine
  JR C,L57401_5           ; for the sloping wall, so can jump to end of this
                          ; routine
; Item/Maroc is moving UPWARDS into the LEFT room boundary.
;
; Vertical speed will be transferred to horizontal speed (wall bounce) However,
; the horizontal bounce is lessened (to preserve the effect of a 'diagonal
; bounce' by first dividing the speed by 4:
  SRA A                   ; Speed = speed/2
  SRA A                   ; Speed = speed/4
  NEG                     ; Make speed into a positive value (item/Maroc will
                          ; be moving right after bouncing off left wall)
  ADD A,L                 ; Add to horizontal speed/direction
  LD L,A                  ; And store
  LD H,0                  ; Set vertical speed to 0
  JR L57401_5             ;
; RIGHT WALL BOUNDARY CHECK
;
; No carry jump from a bit earlier - 57459
L57401_3:
  LD A,(60156)            ; This is the RIGHT (vertical) corner of the room -
                          ; horizontal position, in half character squares (4
                          ; pixels) in the room, from the left of the room's
                          ; playing area.It's at this point that the right side
                          ; wall starts to slope down to the right hand side of
                          ; the screen
  ADD A,C                 ; Add the vertical difference (halved in earlier
                          ; calculation to account for the side wall 'slope')
  SUB D                   ; Add the horizontal co-ordinate (in
                          ; half-character/4-pixel steps)
  CP 224                  ; If value is >=224 (no carry), we've passed the side
                          ; wall on the right - bounce the item/Maroc back off
                          ; the wall (to the left)
  JR C,L57401_5           ; If (carry) value is <=224 (equivalent of -32),
                          ; we're fine as far as the right room boundary is
                          ; concerned, so jump out here to the end of the
                          ; routine
; Item/Maroc has hit the RIGHT of the room boundary. Ensure the horizontal
; movement speed value is negative, so the item/Maroc is now moving left
  LD A,L                  ; Horizontal speed/direction
  CP 128                  ;
  JR NC,L57401_4          ; If >=128 128 (no carry), retain the negative value
  NEG                     ; If <128 (carry), reverse the value to make it
  LD L,A                  ; negative
; Check vertical movement:
; * Maroc and other items can hit the side walls by moving upwards into them,
;   even if they're not moving left/right
; * If this happens, the item/Maroc bounces off the wall horizontally (rather
;   than vertically)
; * See the small diagram at the bottom of the original 80s scanned
;   illustration earlier on this page, to see this
L57401_4:
  LD A,H                  ; Check vertical speed/direction
  CP 128                  ; If < 128, Maroc is moving downwards - this is fine
  JR C,L57401_5           ; for the sloping wall, so can jump to end of this
                          ; routine
; Item/Maroc is moving UPWARDS into the RIGHT room boundary.
;
; Vertical speed will be transferred to horizontal speed (wall bounce) However,
; the horizontal bounce is lessened (to preserve the effect of a 'diagonal
; bounce' by first dividing the speed by 4:
  SRA A                   ; Speed = speed/2
  SRA A                   ; Speed = speed/4
  ADD A,L                 ; Add to horizontal speed/direction (though this is a
                          ; negative figure so will essentially be subtracted)
  LD L,A                  ; ...and re-store horizontal speed/direction
  LD H,0                  ; Set vertical movement direction/speed to 0
; All room boundary checks complete
L57401_5:
  LD (60236),HL           ; Adjusted horizontal/vertical speed/direction
  RET                     ; re-stored

; Copy room item data from item buffer to room data sets
;
; Used by the routines at L49498, L49600, L49679, L49765, L49808, L49912,
; L49993, L50272, L50712, L54053, L54983, L55088, L55347, L55564 and L57015.
;
; Copies the 16 bytes of object/item data from the buffer at L60227 to a data
; set at 31744.
L57520:
  LD B,16                 ; 16 bytes to copy
  LD DE,L60227            ; Address pointer to start of data buffer
  LD HL,(60094)           ; Get pointer to start of data set at 31744.
L57520_0:
  LD A,(DE)               ; Copy a byte from the buffer to the set
  LD (HL),A               ;
  INC DE                  ;
  INC HL                  ;
  DJNZ L57520_0           ; Repeat x16 bytes
  LD (60094),HL           ; Address pointer to start of next data set
  RET                     ;

; Setup game graphics
;
; Used by the routines at L49053, L49600, L49679, L49765, L49808, L49912,
; L49993, L50663, L52849, L53145, L53372, L54960, L55088, L55885, L56028,
; L56095, L57015, L57706, L58945, L59130, L59219 and L59389.
;
; A Graphic number - offset for graphics address pointer table at L38851.
;   Calculated offset is ((A-1)*2) + L38851.
;
; Room graphics are prepared using this routine when Maroc moves into a new
; room/screen.
;
; The routine is also called to prepare any additional graphics required as and
; when needed (e.g. a creature entering the room, the warlock appearing, or to
; draw the arrow on the spell menu if fire is pressed).
L57538:
  LD B,A                  ; Transfer offset value to B register
; Calculate graphics address pointer using offset, using table at L38851
  LD HL,(60266)           ; Pointer to graphics address list at L38851
  DEC A                   ; Address pointers are 2 bytes long, so get offset
  LD D,0                  ; value, subtract 1...
  RLA                     ; ...multiply by 2
  RL D                    ;
  AND 254                 ; Address pointers are 2 bytes long, so filter out
  LD E,A                  ; bit 0 (1) to ensure it's an even number
  ADD HL,DE               ; Add the calculated offset to the base table
                          ; address, to get the right graphics address pointer
  LD (60082),HL           ; ...and store. Initially corner vertical wall
                          ; section at 38885/40463.
; Calculate a second graphics pointer offset, that will point to the
; flipped/mirrored graphic's address.
  LD A,(60240)            ; Offset byte for address pointer for store of
                          ; mirrored graphic
  DEC A                   ; Address pointers are 2 bytes long, so get offset
                          ; value, subtract 1...
  RLA                     ; ...multiply by 2
  AND 30                  ; Keep bits 1-4 (no bit 0). Address pointers are 2
                          ; bytes long, so filter out bit 0 (1) just to make
                          ; sure it's an even number.
  LD E,A                  ; Put offset in DE
  LD D,0                  ;
  ADD HL,DE               ; Add this to HL address graphic pointer
  LD (60241),HL           ; ...and store.
; Point DE register pair to graphics data (HL = pointer at address table at
; L38851)
  LD HL,(60082)           ; Get graphics address pointer (with first offset
                          ; pointing to the 'standard' graphics address)
  LD E,(HL)               ; Point DE to the actual graphics address data e.g.
  INC HL                  ; 39248, 40463.
  LD D,(HL)               ;
  DEC HL                  ;
; Pre-graphics byte - see Graphic properties
  DEC DE                  ; Get pre-graphics byte
  LD A,(DE)
  INC DE
  LD (60239),A            ; ...and store.
; The next routine checks if the graphic has a 'mirrored' version. If so, this
; is constructed in the following routine at L57589.
;
; If bit 5 (32) is set, it indicates that the graphic is 'flippable' - for
; example, graphics for the background right-hand side wall, which can be
; flipped to create the background left-hand side wall.
  LD C,A                  ; Store the byte in the C register, used in the
                          ; following 'flip' routine
  AND 32                  ; If bit 5 is NOT set, no need to generate 'flipped'
  CP 0                    ; graphics.
  JR Z,L57589_7           ; In which case, jump straight to the RET command at
                          ; the end of the following flip/reflect routine

; Create flipped/mirrored version of a particular graphic
;
; B Graphics number for graphics address pointer table at L38851. This relates
;   to scenery graphics (wall/floor connectors, door frames etc.).
; C Graphic address offset (bits 0-3 of this byte give the offset for graphics
;   pointer address frames at L38851)
; HL Points to relevant graphics address pointer at address table at L38851
;
; In the graphic address pointer table at L38851, spaces have been left after
; 'flippable' graphics to store the graphics address pointer for the mirrored
; graphic.
;
; For example, right-hand wall door frame graphics can be flipped/mirrored to
; create left-hand wall door frames.
;
; Bits 0-3 of the pre-graphics byte in the C register tell us how far to move
; the address pointer forward (each value = 4 bytes) to point to the space in
; which address pointer for the flipped/mirrored graphics is stored.
;
; First, calculate the address at which to store the mirrored graphics:
L57589:
  LD A,C
  AND 15                  ; Get the offset stored in bits 0-3
  LD (60081),A            ;
L57589_0:
  INC HL                  ; Loop round n*4 bytes (i.e. two 16-bit addresses for
  INC HL                  ; each count) from the base graphic pointer address
  INC HL                  ; at L38851.
  INC HL                  ;
  DEC A                   ;
  JR NZ,L57589_0          ;
  LD (60082),HL           ; ...And store the new calculated address. The
                          ; mirrored graphic address pointer will actually be
                          ; stored in the two bytes prior to this address.
; Identify the memory address locations at which to store the mirrored
; graphics:
  LD HL,(L60143)          ; Get pointer to data/graphics storage area (32819)
L57589_1:
  LD A,(HL)               ; Check byte
  INC HL                  ; ...and move pointer one address forward
  CP 255                  ; Is it 255 (end-of-data byte)
  JR Z,L57589_2           ; If so, can store graphics from here
  CP B                    ; Is the graphics address pointer table offset byte
                          ; stored here?
  JR Z,L57589_7           ; If so, can skip straight to RET at the end of the
                          ; routine. This may be a check to see if the graphics
                          ; data has already been dealt with, but this
                          ; condition isn't normally met during the game, as
                          ; each room will start with a bunch of scenery items.
  JR L57589_1             ; Otherwise, keep moving through the data until a
                          ; end-of-data byte is found
L57589_2:
  LD (HL),255             ; Now we're at the right address. Set end-of-data
                          ; byte (255)...
  DEC HL                  ; ...and the pre-graphic data byte before it
  LD (HL),B               ;
  EX DE,HL                ; HL now pointing to graphic data to mirror, e.g.
  LD DE,(60253)           ; 40463
L57589_3:
  LD B,H                  ; BC temporary store for HL e.g. 40463
  LD C,L                  ;
; Store the address pointer to the reflected/flipped graphics address in a free
; slot by the base graphics address pointer, in the table at L38851:
  LD HL,(60082)           ; Get graphics pointer address from earlier (table at
                          ; L38851), e.g. 38889
  DEC HL                  ; Put the flipped/mirrored graphics pointer into the
  LD (HL),D               ; 2-byte slot just before it.
  DEC HL                  ;
  LD (HL),E               ;
  LD (60082),HL           ; Store the graphics address pointer to the flipped
                          ; graphics
  LD H,B                  ; Restore HL, pointing at the graphics to mirror,
  LD L,C                  ; e.g. 40463.
; The following routine gets graphic data and mirrors it, storing the mirrored
; bytes.
;
; First, transfer across the few data bytes before the graphics which hold (a)
; number of tiles in the current graphic, (b) horizontal/vertical pixel
; offsets, and (c) number of bytes in the tile.
  LD A,(HL)               ; Number of tiles that form the current graphic (tile
                          ; counter).
  LD (DE),A               ; Copy it to the mirrored data store. This is how
                          ; many tiles will need mirroring and storing.
  INC DE                  ; Then move both address pointers to the next byte.
  INC HL                  ;
; Mirror the graphic and store it.
L57589_4:
  LD (60103),A            ; Store the tile counter
  LD A,(HL)               ; Copy over the horizontal (X axis) offset (in
                          ; pixels)
  ADD A,8                 ; Add 8 and use NEG so that the X axis pixel offsets
                          ; are reversed
  NEG                     ; e.g. horizontal pixel offsets for a 4
  LD (DE),A               ; character-wide graphic of -16, -8, 0 and +8 become
                          ; +8, 0, -8, -16 in the mirrored version as they're
                          ; drawn in reverse order in the reflected version.
  INC HL                  ; Copy over the vertical (Y axis) offset (this won't
  INC DE                  ; need changing)
  LD A,(HL)               ;
  LD (DE),A               ;
  INC HL                  ; ...Next, copy over the number of bytes in the tile
  INC DE                  ;
  LD A,(HL)               ;
  LD (DE),A               ;
  INC HL                  ;
  INC DE                  ;
L57589_5:
  LD (60113),A            ; Store this number as a counter
; Mirror the graphic data for the tile and store the flipped tile data
  LD A,(HL)               ; Get graphics byte
  INC HL                  ; Move graphics address pointer along to next one
  LD B,8                  ; Rotate the bits from A register x8 backwards into C
L57589_6:
  RLA                     ; register to create the mirrored byte
  RR C                    ;
  DJNZ L57589_6           ;
  LD A,C                  ; Get the completed mirrored byte...
  LD (DE),A               ; ...And store.
  INC DE                  ; Move the mirrored graphics address pointer along to
                          ; next one
  LD A,(60113)            ; Retrieve the tile byte counter
  DEC A                   ; Repeat for the rest of the bytes in the tile.
  JR NZ,L57589_5          ;
; Tile is now flipped/mirrored. Now repeat for all tiles that make up the full
; graphic.
  LD A,(60103)            ; Get the tile counter
  DEC A                   ; Decrement and repeat for the rest of the tiles that
  JR NZ,L57589_4          ; make up the graphic.
; Check if there are any more graphics to mirror in the 'set'. For instance,
; there are 3 lots of mirrored graphics for the doors at L40144.
  LD A,(60081)            ; Get the offset address counter
  DEC A                   ; Decrement and re-store
  LD (60081),A            ;
  JR NZ,L57589_3          ; If there are more graphics to mirror, go and do
                          ; them.
  LD (60253),DE           ; All graphics now mirrored. Store the mirrored
                          ; graphics address pointer, ready for any other
                          ; graphics that may need mirroring.
; This entry point is used by the routine at L57538.
L57589_7:
  RET                     ; All relevant graphic data is now mirrored/flipped.

; Set up data for creature/warlock appearing in Maroc's room
;
; Used by the routines at L50272, L54782, L54907 and L54948.
;
; A | Creature type/number (see 60230)
;
; This routine is triggered:
; * when Maroc enters a room that contains a creature
; * when a creature enters the current room
; * when a warlock appears on the wall of Maroc's room
L57706:
  LD (60230),A            ; Creature type (also creature type number in data
  LD C,A                  ; set at L27772)
  LD A,0                  ;
  LD (L60227),A           ; Type of graphic to draw (reset to 0 but will be set
                          ; shortly)
  LD A,(60342)            ; Number of creatures in current room
  CP 3                    ; Are there 3 already?
  JR Z,L57706_0           ; If so, can't have any more, so jump straight to RET
  INC A                   ; Less than 3 creatures, so increase count of
  LD (60342),A            ; creatures in room by 1
  LD HL,(60355)           ; Address pointer to warlock/creature information at
                          ; L27772
; Get offset to determine correct data set for particular warlock/creature:
  LD A,C                  ; Creature type/number (from 60230)
  DEC A                   ; Count starts from zero (for first set) so subtract
                          ; 1
  RLA                     ; Each set is 8 bytes so multiply by 8
  RLA                     ;
  RLA                     ;
  AND 248                 ; Filter out unnecessary bits 0-2
  LD E,A                  ; Create offset in DE register
  LD D,0                  ;
  ADD HL,DE               ; Add to L27772 to get to relevant data set
  LD (60228),HL           ; ...and store
; Set up creature's data:
  LD A,3                  ; Set graphic type to 3 (indicates a creature)
  LD (L60227),A           ;
  LD A,0                  ;
  LD (60231),A            ; Creatures appearing in the room will be on screen,
                          ; so set low byte of horizontal position to zero...
  LD (60233),A            ; ...and also vertical position. This indicates the
                          ; creature is in the current 'viewport' and not
                          ; off-screen to the right or left. Any creatures
                          ; appearing in the room will do so within the current
                          ; viewport.
  LD (60237),A            ; Set creature's vertical movement speed to zero
  LD (60236),A            ; Set creature's horizontal movement speed to zero
  LD A,64                 ;
  LD (60235),A            ; 64 = room item (as opposed to a tunnel). This forms
                          ; the byte 9 in data sets at 31744, but is otherwise
                          ; unused.
; Randomize the creature's horizontal & vertical co-ordinates in the room
;
; Horizontal position:
  CALL L56070             ; Generate pseudo-random number in A register
  AND 31                  ; Keep bits 0-4 (values = 0 - 31)
  SUB 15                  ; Values now vary between -15 and +16 (or 241 to 16)
  LD E,A                  ; Temp store in E register
  LD A,(60284)            ; Get 1st room data byte which indicates room size
  RLA                     ; Multiply by 4 - this puts the base horizontal (X)
  RLA                     ; co-ordinate at the centre of the room (half of the
                          ; room size)
  AND 252                 ; (Filter out unwanted bits 0 & 1)
  ADD A,E                 ; Add the random number generated earlier to vary
                          ; horizontal (X) co-ordinate somewhere between -15
                          ; and +16 earlier.These are half-character (4-pixel)
                          ; values so can mean up to 8 character squares (or 64
                          ; pixels) left or right of centre
  LD (60232),A            ; ...And store
; Vertical position:
  CALL L56070             ; Generate pseudo-random number in A register
  AND 31                  ; Keep bits 0-4 (values = 0 - 31)
  ADD A,64                ; Add 64. This puts the vertical position somewhere
                          ; between 64 and 95 pixels from the top of the
                          ; playing area, which is somewhere between the middle
                          ; and bottom of the room area.
  LD (60234),A            ; Store vertical co-ordinate
; Some more creature data:
  LD A,5                  ; Bit 0 set = creature on-screen. Bit 2 set =
                          ; creature will need erasing
  LD (60238),A            ; Store in creature properties byte
  LD A,17                 ; Graphics address pointer frame offset. In the later
  LD (60240),A            ; calculation bit 4 is ignored however, so the offset
                          ; will be [n-1]*2, i.e. no offset
  LD DE,6                 ; Move along to the 7th of the 8 bytes in the
  ADD HL,DE               ; creature data set at L27772/27828
  LD A,(HL)               ; Get creature graphic number (used as an offset for
                          ; the graphic address table at L38851)
  CALL L57538             ; Set up the graphics for this creature
L57706_0:
  RET                     ;

; Play (generic) sound effect
;
; Used by the routines at L49274, L54053 and L55944.
;
; Generic white noise sound effects, crunching, stepping sounds - e.g. doors
; opening/closing, creature footsteps. Also used to generate the thunder sound
; in the intro lightning routine.
; * The byte at 60246 determines length/frequency of the sound effect.
; * The address pointer stored at 60249, and initialised at address 0000 (ROM)
;   provides random values for the sound.
L57815:
  LD (60247),HL           ; Preserve HL for this routine
  LD A,(60246)            ; Counter/frequency for sound effect
  LD B,A                  ; Store in B register
  CP 0                    ;
  JR Z,L57815_2           ;
  DEC A                   ; Decrement counter and store
  LD (60246),A            ;
  LD A,B                  ; Retrieve (pre-decremented) counter
  AND 7                   ; Check bits 0-2 to cause an occasional change of
                          ; address for the base address pointer
  LD HL,(60249)           ; Get byte from address pointer in readiness
  LD A,(HL)               ;
  JR NZ,L57815_0          ;
; Every 8 loops, move to a different address for the byte value to base the
; effect on:
  INC HL                  ; Skip to the next address
  LD (60249),HL           ; ..and store address pointer
  LD A,(HL)               ;
  JR NZ,L57815_0          ; Repeat of condition that was checked at 57837
  INC HL                  ; Skip another address
  LD (60249),HL           ; ...and re-store counter
; Use pseudo-random byte to generate sound:
L57815_0:
  INC B                   ; Shift sound byte based on counter - randomize
L57815_1:
  RLA                     ; speaker bit
  DJNZ L57815_1           ;
  SBC A,A                 ; Based on the (randomized) carry flag the
                          ; subtraction will cause the speaker bit to be either
                          ; on or off (50/50)
  AND 16                  ; Filter out everything except speaker bit (bit 4)
  OUT (254),A             ; Output value to speaker (1 or 0)
L57815_2:
  LD HL,(60247)           ; Retrieve HL register pair value preserved at the
  RET                     ; start of the routine

; Set screen colour for current room
;
; Used by the routines at L50747, L55885 and L55944.
;
; The screen colours are calculated from the bits that form the room number
; byte in the routine at L50747.
L57863:
  LD A,(60073)            ; Get attribute colour for current room
  LD D,14                 ; 14 rows to colour
  LD HL,22594             ; Screen attribute display, top left of play area,
                          ; just inside decorative border
L57863_0:
  LD B,28                 ; 28 columns to colour
L57863_1:
  LD (HL),A               ; Colour the attribute square
  INC HL                  ; Move right to next character square
  DJNZ L57863_1           ; Repeat for 28 columns
  INC HL                  ; Move right 4 squares to get to the left hand side
  INC HL                  ; of the next character row
  INC HL                  ;
  INC HL                  ;
  DEC D                   ; Repeat for 14 rows
  JR NZ,L57863_0          ;
  CALL L57888             ; Colour Maroc's sprite in by combining his colour
                          ; (white) with the current screen's PAPER value (not
                          ; all screens have a black background)
  RET

; Set attribute colours for Maroc
;
; Used by the routines at L54120, L57863 and L58476.
;
; Maroc's attribute colour value is set to 71 (INK 7, PAPER 0, BRIGHT 1) and
; stored at L60071.
;
; This routine calculates and sets Maroc's colour on the screen (incorporating
; the screen's PAPER colour if needed)
;
; Calculate Maroc's VERTICAL attribute display address position:
L57888:
  LD A,(60097)            ; Maroc's vertical (Y-axis) position, in pixels.
  SUB 26                  ; Maroc's vertical position is calculated from the
                          ; middle of the sprite, so move up 26 pixels to get
                          ; to the top of his hat
  AND 248                 ; Character squares/attributes are in multiples of 8
                          ; pixels, therefore don't need bits 0-2 (values 0-7).
                          ; Filter these so the vertical position is a multiple
                          ; of 8
  LD H,0                  ; Store calculated value in HL register
  LD L,A                  ; To move down to the next screen attribute display
                          ; square, you need to add 32 to the address. So
                          ; address offset will be (y/8)*32, or y*4. So
                          ; multiply by 4.
  ADD HL,HL               ; x2
  ADD HL,HL               ; x4
; Calculate Maroc's HORIZONTAL attribute display address position:
  LD A,(60096)            ; Maroc's horizontal (X-axis) position, in 4-pixel
                          ; (half character rows)
  SRA A                   ; Divide by 2 to get Maroc's horizontal position in
  LD E,A                  ; full character rows
; Calculate offset from top of screen attribute display address:
  LD D,0
  ADD HL,DE               ; Combine the offsets calculated above
  LD DE,22560             ; Screen attribute display position one square down
                          ; from the top left of the screen
  ADD HL,DE               ; Add the combined vertical + horizontal offset to
                          ; get to the top left of Maroc's sprite
; Attribute display address pointer is currently just above Maroc's sprite, so
; colour this in with the room PAPER colour:
  LD A,(60073)            ; Current room colour attribute value
  LD DE,29                ; Offset ready to move down to the next character row
                          ; (32 spaces) minus 3 spaces (3 spaces to the left)
  LD B,3                  ; 3 character wide area to colour in
L57888_0:
  LD (HL),A               ; Colour the 3-character wide section with the room
  INC HL                  ; colour
  DJNZ L57888_0           ;
; Now combine the room colour with Maroc's sprite colour, so Maroc takes on the
; PAPER value of the room:
  LD A,(60073)
  LD C,A
  LD A,(L60071)           ; Maroc's standard colour - 71 (BRIGHT 1, INK 7,
                          ; PAPER 0)
  OR C                    ; Combine Maroc's colour with the background (PAPER)
                          ; colour of the screen
; Next, print Maroc's colour on-screen.
;
; This paints a 3 x 6 coloured vertical space over Maroc's sprite. Although the
; width of his sprite frames (L38851) varies between 3 and 5 characters, a
; width of only 3 characters gets coloured in (possibly to reduce the extent of
; his colour clash).
  ADD HL,DE               ; Move to the attribute display address for Maroc's
                          ; vertical position
  LD C,6                  ; 6 characters in height
L57888_1:
  LD B,3                  ; ...and 3 wide
L57888_2:
  LD (HL),A               ; Colour in the square
  INC HL                  ;
  DJNZ L57888_2           ; Repeat for 3 columns
  ADD HL,DE               ; Move down to next character line, and back left 2
                          ; characters
  DEC C                   ; Repeat for 6 rows
  JR NZ,L57888_1          ;
  RET                     ;

; Clear the playing area (pixels)
;
; Used by the routines at L50747 and L55885.
L57947:
  LD A,14                 ; Playing area is 14 character rows high
  LD (60103),A            ;
  LD DE,16450             ; Screen display address for top left of playing area
; Clear a character row (8 pixels) of the playing area:
L57947_0:
  LD C,8                  ; 8 pixel rows
  LD H,D                  ; Copy screen display address from DE to HL
L57947_1:
  LD L,E                  ;
  LD B,28                 ; 28 character rows to clear
L57947_2:
  LD (HL),0               ; Clear pixel byte
  INC L                   ; Move on character square right
  DJNZ L57947_2           ; Repeat for 28 character rows
  INC H                   ; Move down 1 pixel
  DEC C                   ;
  JR NZ,L57947_1          ; Repeat for 8 pixel rows
; Move down to next (character) row:
  LD A,E                  ; Get starting left hand position
  ADD A,32                ; Move down to next character square
  LD E,A                  ; Are we crossing a third-of-screen boundary?
  JR NC,L57947_3          ;
  LD A,D                  ; If so, recalculate screen display high-byte
  ADD A,8                 ; accordingly
  LD D,A                  ; Store corrected screen address high byte back in D
                          ; register
; Check if all character rows have been cleared:
L57947_3:
  LD A,(60103)            ; Get character row counter
  DEC A                   ; ...and decrement
  LD (60103),A            ;
  JR NZ,L57947_0          ; Repeat for all 14 character squares of playing area
  RET                     ;

; Collision check between creature missile and Maroc's shielding barrier
;
; Used by the routine at L53403.
;
; Called from 53475 if byte 7 or 8 of missile data (L27868/60317) is repelled
; by the active spell effect
;
; Collision detection for SHIELD, PROTECT, DEFENCE and AMULET vs missile/bolt
; spells.
;
; Because the shield effect flickers to Maroc's left and right, his 'hit boxes'
; are slightly wider than normal to accommodate this (vertical = 24 pixels at
; 58007, horizontal 48 pixels at 58018)
L57990:
  LD A,(60116)            ; High byte of missile horizontal co-ordinate
  CP 0                    ; This byte is 0 if the item is visible on-screen
  JR NZ,L57990_0          ; If not, jump to the end of this routine
; Missile is on-screen. First a horizontal co-ordinate collision check:
  LD A,(60114)            ; Graphic's vertical pixel position
  LD C,A                  ; Copy to C register
  LD A,(60097)            ; Maroc's vertical (Y-axis) screen position
  ADD A,12                ; Move the target centre down 12 pixels (towards the
                          ; bottom of Maroc's sprite). The vertical 'hit box'
                          ; of 24 pixels will extend upwards from here
  SUB C                   ; Subtract the missile's vertical position
  CP 24                   ; Is the missile within 24 pixels from this vertical
                          ; position?
  JR NC,L57990_0          ; If margin is >=24 pixels, it's missed vertically so
                          ; no need to run the horizontal check
; Horizontal check is within 'hit box'. Next, a vertical co-ordinate collision
; check:
  LD A,(60115)            ; Graphic's horizontal pixel position
  LD C,A                  ; Copy to C register
  LD A,140                ; Maroc's horizontal pixel position on screen doesn't
                          ; change - this pixel position is at the barrier just
                          ; to the right hand size of Maroc's sprite. The
                          ; horizontal 'hit box' of 48 pixels extends to the
                          ; left from here
  SUB C                   ; Subtract the missile's horizontal pixel position
  CP 48                   ; Is the missile within 48 pixels from this
                          ; horizontal position?
  JR NC,L57990_0          ; If it's outside this range, no collision
; The missile has collided with Maroc while he's protected by his shielding
; spell:
  LD A,8
  LD (60246),A            ; Set the sound effect duration affecting length of
                          ; 'crunching' sound as the missile strikes Maroc &
                          ; his shield (duration = 8) This also acts as a
                          ; non-zero collision flag value, indicating a
                          ; positive collision check
  JR L57990_1             ; ...and skip the next instruction, jump straight to
                          ; RET
; No collision detected
L57990_0:
  LD A,0                  ; Collision check flag value = 0 (no collision)
L57990_1:
  RET                     ;

; Copy room item event data into working buffer
;
; Used by the routines at L52263, L52616 and L53403.
;
; A Event number involving this object (stored at 60303) Also used for
;   energy-affecting objects, e.g. orbs and mushrooms, 254 = energy drain, 253
;   = energy replenish
;
; Uses room item event data sets at 32691 that will need checking for certain
; items/objects in the current room.
L58032:
  LD C,A                  ; Copy event number ID into C register
  LD A,(60116)            ; Horizontal position of object (high byte). This is
                          ; 0 if object is on-screen. 1 means off-screen to the
                          ; right, 255 means off-screen to the left.
  CP 0                    ; If it's 0, it's on the current screen (viewport)
  JR NZ,L58032_0          ; If not, this item is off-screen so no
                          ; collisions/interactions with this object will need
                          ; checking - jump straight to RET
  LD HL,(60077)           ; Pointer to the event data sets at 32691
  LD (HL),2               ; Set the first byte of the set to 2, which means the
                          ; event will be checked for 2 game cycles, mainly in
                          ; case items are moving around.
  INC HL                  ; Move along one byte
  LD (HL),C               ; Byte 2 of set - the event/interaction
  INC HL                  ; identifier/value to check for this item
  LD A,(60115)            ; Byte 3 of set - item's horizontal screen position
  LD (HL),A               ; (in pixels)
  INC HL                  ;
  LD A,(60114)            ; Byte 4 of set - item's vertical position (in
  LD (HL),A               ; pixels)
  INC HL                  ; The event table is dynamic - it can shrink/expand
  LD (HL),255             ; and is recaculated each frame, so put a 255 at the
                          ; start of the next set to mark the end of item sets
  LD (60077),HL           ; Restore the address pointer at the start of this
L58032_0:
  RET                     ; next set

; Set up message text on scroll to print
;
; Used by the routines at L49215, L51043, L55944 and L58599.
;
; Set up the message data, pointers and next character to print, in preparation
; before the print routine at L58106.
L58064:
  LD DE,(L60065)          ; Get address of message text to print
  LD A,(DE)               ; Get the number of letters/characters in the message
  LD (60067),A            ; ...and store
  LD (60068),HL           ; Store the screen display address pointer
  INC DE                  ; Point at the first letter/character to print
  LD (L60065),DE          ; ...and store address pointer
; This entry point is used by the routines at L56668, L57139, L58106, L59130
; and L59330.
L58064_0:
  LD DE,(L60065)          ; Get the message text address pointer
  LD A,(DE)               ; Get the letter/character to print
  INC DE                  ; Move the pointer on to the next one
  LD (L60065),DE          ; ...and store
  CP 27                   ; Is the character a line break (code 27)?
  JR NZ,L58106            ; If not, continue to print text
; End of line character (27) encountered. Move down one character row and to
; the left hand position of the scroll. New screen display address calculated
; and stored.
;
; As all printing is done in the bottom third of the screen, only the low byte
; of the screen display address needs changing.
  LD A,(60068)            ; Get the current screen display address low byte
  AND 224                 ; Reset the column number to 0
  ADD A,40                ; ...and add 40, thus moving down one row (32
                          ; characters) and right 8 characters, to the left
                          ; hand side of the scroll, on the next row down
  LD (60068),A            ; Store the screen display address low byte
  JR L58106_4             ; ...and jump straight into the text print routine.

; Character/text printing
;
; Used by the routine at L58064.
;
; A Offset for letter to print, e.g. 0 = A, 1 = B (see L27940)
;
; This routine is used at L57538 to print a single text character. It allows
; for text to be printed at any pixel line (rather than starting from the top
; of an 8x8 pixel square).
;
; The character set text graphics are stored at L27940.
L58106:
  LD HL,L27940            ; Start address of character set ('A')
  LD D,0                  ; Load DE with offset of character (0 = A, 1 = B, 2 =
                          ; C etc.)
  LD E,A                  ; Outer loop counter
  LD B,8                  ; 8 bytes in each character
L58106_0:
  ADD HL,DE               ; Add offset to base address
  DJNZ L58106_0           ; ...and repeat 8 times (x8) to find the address of
                          ; the character to print
  EX DE,HL                ; Character address now stored in DE
  LD HL,(60068)           ; ...Get screen display address (???) to print text
                          ; at
  LD C,H                  ; Store high byte in C for retrieval later
  LD B,8                  ; 8 pixel row bytes to print
L58106_1:
  LD A,(DE)               ; Get first byte of letter graphic
  INC DE                  ; Move to the next byte for later
  LD (HL),A               ; Print byte onto screen
  LD A,H                  ; Get the high byte of the screen address
  AND 7                   ; Look at the pixel row of the line (0-7)
  INC A                   ; Increment and check if it's gone over to the next
  CP 8                    ; character row
  JR NZ,L58106_2          ;
  LD A,H                  ; Get the high byte of the display address
  AND 248                 ; Sets the pixel line in the character row to 0 as
                          ; we're into a new character row
  LD H,A                  ; ...and restore back to H (high byte of display
                          ; address)
  LD A,L                  ; Move the low byte of the display address to the
  ADD A,32                ; next character row down, and store
  LD L,A                  ;
  JR L58106_3             ; INC H in next line of code can now be skipped as HL
                          ; contains the correct display address position
; Jump in from 58133, where the pixel row is still 0-7 (same character row) so
; can just increment the high byte of display address (H register) to get to
; the right place:
L58106_2:
  INC H
L58106_3:
  DJNZ L58106_1           ; Repeat printing pixel rows until all 8 bytes of the
                          ; character are printed on screen
  LD A,L                  ; Restore L (the low byte of the screen address) to
  SUB 31                  ; its starting column position + 1, i.e. 1 character
  LD L,A                  ; to the right, ready to print the next letter
  LD H,C                  ; ..and also restore H (the high byte) to its
                          ; starting position
  LD (60068),HL           ; ...and store display address position ready to
                          ; print next character.
; Letter/character has been printed
L58106_4:
  LD A,(60067)            ; Decrement the 'number-of-letters-to-print' counter
  DEC A                   ; (columns) (I think)
  LD (60067),A            ;
  JR NZ,L58064_0          ; Continue printing until finished
  RET                     ;

; Handle creature/graphic animation
;
; Used by the routines at L51255 and L59689.
;
; For animated creatures and items, e.g. servant spell cursor, animated sabre.
;
; Some will need left/right facing direction determined (e.g. goblin warrior),
; others won't (e.g. demon)
;
; This routine advances the animation frame to the next one, or resets it to
; frame 1, as long as the creature/item isn't affected by an active FREEZE
; spell.
L58166:
  LD A,(L60074)           ; Incrementing timer byte
  AND 1                   ; Check bit 1
  JP Z,L58166_6           ; Skip animation routine (straight to RET) every
  LD A,(L60227)           ; other frame, so that animation rate isn't too fast
  CP 3                    ; Is it a creature?
  JR NZ,L58166_0          ; If not, animation shouldn't be affected by FREEZE
                          ; spell so can skip the check for this
; It's a creature, so it'll need animating. Check if creature is affected by
; FREEZE spell:
  LD A,(60238)            ; Creature properties byte
  AND 224                 ; If any of the top 3 bits are set, it means the
                          ; creature is disintegrating/materialising - this
                          ; animation isn't be affected by the FREEZE spell
                          ; (the animation should continue)
  JR NZ,L58166_0          ; If any of the 3 bits are set, skip the following
                          ; FREEZE spell check
; If the FREEZE spell is active, creatures do not move:
  LD A,(60572)            ; Get FREEZE spell timer counter
  CP 0                    ;
  JR NZ,L58166_6          ; If it's > 0 the FREEZE spell is active, so skip
                          ; this routine and go straight to RET
; Check if the creature has a left/right facing version of the graphic that
; needs calculating:
L58166_0:
  LD A,(60239)            ; Get pre-graphics data byte (Graphic properties)
  LD B,A                  ; Temp store in B register
  AND 64                  ; Bit 6 (64), if set, indicates that this creature
                          ; has left/right facing graphics (e.g. goblins,
                          ; guardian of chaos, and wraith)
  JR Z,L58166_3           ; Jump if NOT set (i.e. not any of the above) -
                          ; creature isn't left/right facing, e.g. the demon)
; Figure out whether we need a left or right facing graphic for this
; item/creature.
;
; Bit 3 (8) of the byte at 60240 indicates whether the creature is facing right
; (1 - set) or left (0 - not set)
  LD A,(60240)            ; Get graphic address frame number offset
  LD D,A                  ; Temp store in D
  AND 8                   ; Get bit 3
  LD C,A                  ; C now contains either 8 (right) or 0 (left)
                          ; depending on whether bit 3 was set
  LD A,(60236)            ; Movement speed/direction
  CP 0                    ; Stationary?
  JR Z,L58166_3           ; If so, don't need to calculate anything - skip to
                          ; the end
  CP 128                  ; Negative value = move left.
  JR NC,L58166_1          ;
; Creature needs to move right - check if it is already moving/facing in this
; direction
  LD A,C                  ; Retrieve byte from C register - if bit 3 (8) of
                          ; 60240 was set, C will contain 8, otherwise 0.
  CP 8                    ; If the byte is 8 it means the creature is already
                          ; moving right
  JR Z,L58166_3           ; If so, no need to change which way the creature is
                          ; facing
; Creature is moving left but needs to switch to right. Calculate the graphics
; pointer offset to the opposite facing graphics frame.
  LD A,B                  ; Retrieve pre-graphics data byte
  AND 7                   ; Lowest 3 bits = number of frames
  ADD A,A                 ; Multiply by 2 as we're dealing with 2 byte graphic
                          ; address pointers
  LD E,A                  ; Store offset in E register
  LD A,D                  ; Get graphic address frame number offset
  OR 8                    ; Set bit 4 to indicate the creature is now moving
                          ; right - for storing at 60240 at L58166_2
  LD D,0                  ; Set high byte (D register) to 0. The offset, now in
  JR L58166_2             ; DE, will be added to the graphics address pointer
                          ; later.
; Creature needs to move left - check if it is already moving/facing in this
; direction
L58166_1:
  LD A,C                  ; Retrieve byte from C register - if bit 3 (8) of
                          ; 60240 was set, C will contain 8, otherwise 0.
  CP 0                    ; If the byte is 0 it means the creature is already
                          ; moving left
  JR Z,L58166_3           ; If so, no need to change which way the creature is
                          ; facing
; Creature is moving right but needs to switch to left. Calculate the graphics
; pointer offset to the opposite facing graphics frame. This needs to be
; negative as the address pointer needs to move back up the table at L38851.
  LD A,B                  ; Retrieve pre-graphics data byte
  AND 7                   ; Lowest 3 bits = number of frames
  ADD A,A                 ; Multiply by 2 as we're dealing with 2 byte graphic
                          ; address pointers
  NEG                     ; Make negative so when added later, the offset will
                          ; effectively be subtracted to get to an earlier
                          ; address pointer
  LD E,A                  ; Store offset in E register
  LD A,D                  ; Get graphic address frame number offset
  AND 247                 ; Reset bit 4 to indicate the creature is now moving
                          ; left - for storing at 60240 at L58166_2
  LD D,255                ; Set high byte (D register) to 255. The negative
                          ; offset, now in DE, will be added to the graphics
                          ; address pointer later.
; Creature direction and graphic address calculated
L58166_2:
  LD (60240),A            ; Re-store the graphic address frame number offset,
                          ; with bit 3 set/unset to indicate right/left facing
                          ; respectively
  JR L58166_5             ; As we've just switched direction, we're already
                          ; changing the graphic frame, so there's no need to
                          ; change the animation frame again till next time
                          ; round - so skip the next few sections.
; ANIMATE THE CREATURE/GRAPHIC
;
; Advance the animation frame to the next one, or if it's reached the total
; number of animation frames, reset it to frame 1:
L58166_3:
  LD A,B                  ; Retrieve pre-graphics data byte
  AND 128                 ; Bit 7 indicates the graphic has animation frames
  JR Z,L58166_6           ; If NOT set (not animated), jump to straight to RET
; Calculate graphics animation frame:
  LD A,B                  ; Retrieve pre-graphics data byte
  AND 7                   ; Get number of frames for this sprite
  LD B,A                  ; ...and store in B register
  LD A,(60240)            ; Get graphic frame number offset for this graphic
  LD C,A                  ; Temp store in C register
  AND 7                   ; Keep bits 0-2 to get the sprite's current frame
                          ; number
  LD H,A                  ; Temp store in H register
  LD DE,0                 ; DE will be the calculated offset value to
                          ; re-calculate the graphics frame address pointer
                          ; shortly
  CP B                    ; Is the graphic's current frame number <= the total
                          ; frames for this sprite?
  JR C,L58166_4           ; If so, skip next few instructions, OK to advance to
                          ; the next frame so jump out here
; Frame number has passed total frames for this graphic so we need to reset its
; frame number:
  LD A,C                  ; Retrieve current frame number
  AND 248                 ; Reset frame number to 0 (stored in bits 0,1,2 so
                          ; set these to zero)
  LD C,A                  ; ...And store in C register
; Next, return the sprite graphics address pointer to the address for the first
; frame.
;
; This is done by getting the total number of frames for the graphic,
; multiplying by 2, and subtracting it from the current frame address.
  LD A,H                  ; Retrieve the earlier (final) frame number
  ADD A,A                 ; Double it (as address pointers are 2 bytes)
  NEG                     ; This value will be added later, so NEG here will
                          ; mean it gets subtracted
  LD E,A                  ; Store in E, and set D to 255 to effectively create
  LD D,255                ; a 2 byte negative offset
; Recalculate new sprite graphics address pointer for the next frame:
L58166_4:
  LD A,C                  ; Retrieve the sprite's frame number...
  INC A                   ; ...Increment...
  LD (60240),A            ; ...and re-store.
  INC DE                  ; Increment the offset by 2 (to move to the next
  INC DE                  ; graphics frame address)
; Recalculate and re-store sprite frame graphic pointer:
L58166_5:
  LD HL,(60241)           ; Get the sprite frame graphic pointer
  ADD HL,DE               ; Add the offset - either adding two bytes to get to
                          ; the next frame, or adding the negative offset to
                          ; return to the first frame
  LD (60241),HL           ; ...and re-store
  LD A,(60238)            ; Item (creature) properties byte
  OR 4                    ; Ensure bit 2 (4) is set - indicates graphic (i.e.
                          ; the old frame) will need erasing before the new one
                          ; is drawn
  LD (60238),A            ; ...and re-store
L58166_6:
  RET                     ;

; Increase/decrease Maroc's energy and play short beep sound
;
; Used by the routines at L52445, L53349, L53526, L53714, L53819, L54393,
; L54842, L59389 and L59869.
;
; A Value to decrease Maroc's energy by. If bit 7 of the value is set, it
;   indicates the amount to add to Maroc's energy bar (energy being restored)
;
; Check if it's an increase or decrease:
L58316:
  LD C,A                  ; Store increase/decrease value in C register
  CP 128                  ; If bit 7 is set, it indicates an increase in energy
  JR NC,L58316_0          ; (e.g. CHALICE, ENERGIZE, AMULET spells)
; Decrease Maroc's energy:
  LD A,(60128)            ; Maroc's current energy
  SUB C                   ; The amount of damage to subtract
  JR NC,L58316_1          ; Is Maroc's energy now less than zero?
  LD A,0                  ; If energy < 0, set energy to zero
  JR L58316_1             ;
; Increase Maroc's energy:
L58316_0:
  NEG                     ; Maroc is being healed - invert damage (resets bit
  LD C,A                  ; 7) to indicate energy increase
  LD A,(60128)            ; Maroc's current energy
  ADD A,C                 ; Increase by relevant amount
  JR NC,L58316_1          ;
  LD A,255                ; If energy is now > 255, set energy to 255
; Play beep sound - pitch corresponds to Maroc's energy
L58316_1:
  LD (60128),A            ; Re-store Maroc's new energy level
  NEG                     ; Inverts energy value so that the higher the energy,
                          ; the higher the pitch of the beep sound
  OR 1                    ; Ensure value to use is at least 1 (i.e. not zero)
  LD D,A                  ; Delay for inner beep loop
  LD C,16                 ; Delay for beep sound pitch register (outer loop)
  LD A,16                 ; Set bit 4 (speaker bit)
L58316_2:
  LD B,D                  ; Delay counter
L58316_3:
  DJNZ L58316_3           ; Short delay, affects beep pitch based on energy
                          ; left
  OUT (254),A             ; Play sound
  XOR 16                  ; Toggle speaker bit
  DEC C                   ;
  JR NZ,L58316_2          ; Keep toggling for short time (outer repeat loop)
  RET                     ;

; Print screen colours for room object/creature
;
; Used by the routines at L53273 and L53885.
;
; Calculate attribute screen addresses and set screen colours for any
; items/creatures that have colours different from the standard room colours.
;
; First identify attribute row using the item's vertical pixel position:
L58365:
  LD A,(60114)            ; Item's vertical position, from top of playing area,
                          ; in pixels
  ADD A,18                ; Add an offset to avoid top border
  AND 248                 ; Filter out bits 0-2 (values 0-7) as attributes are
                          ; in character (8-pixel) increments
  ADD A,A                 ; Double the value
  LD L,A                  ; Store calculated value in low byte of display
                          ; attribute address
  SBC A,A                 ; If the earlier ADD has caused a carry, we're into
                          ; the second third of the screen attribute display
  LD H,A                  ; ...Adjust the high byte accordingly
  ADD HL,HL               ;
; Vertical character row (left of screen) is now identified. Next consider
; horizontal position.
  LD A,(60115)            ; Item's horizontal screen position, in pixels
  ADD A,9                 ; Adjust/increment base position. This value isn't
                          ; quite right - see Bugs - Attribute bleed on left of
                          ; screen
  RRA                     ; Divide by 8 to get character square from pixel
  RRA                     ;
  RRA                     ;
  AND 31                  ; Attribute lines are 0-31 so only need to keep these
                          ; bits
  ADD A,L                 ; And add it into the attribute address low byte
  LD L,A                  ;
  LD A,88                 ; High byte of attribute display address is
  ADD A,H                 ; %01010000, so add this into the high byte of the
  LD H,A                  ; address
; HL register is now pointing at screen attribute address for the item.
;
; The next set of instructions determines the size of the item to colour. There
; are two sizes - large (for creatures) and small (for objects - i.e.
; everything else).
;
; Colour patterns at L60374 and 60390 identify the series of attributes to use
; for colouring each of these respectively.
  LD A,(L60227)           ; Get item graphic type
  CP 0                    ; 0 = item no longer present, i.e. destroyed creature
  JR Z,L58365_0           ;
  CP 3                    ; 3 = creature
  JR NZ,L58365_1          ;
L58365_0:
  LD DE,L60374            ; Colour pattern address = L60374 for
  JR L58365_2             ; creature/destroyed creature
L58365_1:
  LD DE,60390             ; Colour pattern address = 60390 for any other item
L58365_2:
  LD A,(DE)               ; First byte of set is number of total data bytes in
                          ; set - either 15 or 9
  LD (60103),A            ; Store as counter
  INC DE                  ; Move to the first byte in the data set
; Colouring loop:
L58365_3:
  LD A,(DE)               ; Get the byte
  INC DE                  ;
  LD C,A                  ; Store in C register
  RLA                     ; Shift bit 7 into carry
  SBC A,A                 ; And subtract
  LD B,A                  ; This will result in 0 (value will be added) or 255
                          ; (-1 = value subtracted) in the B register
  ADD HL,BC               ; BC - containing the offset, either positive or
                          ; negative - added to the screen attribute address
                          ; (in HL)
; Check that attribute display address isn't out of bounds (side border or
; bottom third of screen).
  LD A,L                  ; Get attribute column on screen (0-31)
  AND 31                  ; Only need values 0-31
  SUB 2                   ; Can't draw on left/right border, so check screen
                          ; column number is between 2 and 29 (inclusive)
  CP 28                   ; ...A subtraction of 2 and then comparing against a
                          ; value of 28
  JR NC,L58365_6          ; ...will cause attribute addresses either in the
                          ; left border 0, 1 or the right border (30, 31) to
                          ; jump out here with a No Carry
  LD A,L                  ; Border check OK. Get low byte of screen attribute
                          ; address
  CP 64                   ; If attribute low byte address is 64 or less...
  LD A,H                  ; (High byte of screen attribute address)
  JR NC,L58365_4          ;
  CP 88                   ; ...and high byte = 88, attribute display address is
                          ; in the top third and the top two lines (border) of
                          ; the screen
  JR Z,L58365_6           ; If so, skip and don't print any colour here
L58365_4:
  SUB 88                  ; High byte > 88 so we're past the top third
  CP 2                    ; Check if we're into the bottom third of the screen
  JR NC,L58365_6          ; If so, this part of the item is off screen - don't
                          ; set attribute colour here
; Check if we're drawing or erasing and set colour accordingly:
  LD A,(60111)            ; Check DRAW/ERASE flag
  CP 0                    ;
  JR Z,L58365_5           ;
  LD A,(60072)            ; It's DRAW (1) - so get graphic's attribute colour
                          ; byte
  LD (HL),A               ; ...and put on screen
  JR L58365_6             ;
L58365_5:
  LD A,(60073)            ; It's ERASE (0) so get room's attribute colour byte
  LD (HL),A               ; ...and put on screen
; Repeat loop counter:
L58365_6:
  LD A,(60103)            ; Get the counter
  DEC A                   ; Decrement
  LD (60103),A            ; ...and re-store
  JR NZ,L58365_3          ; Continue printing attributes for the rest of the
  RET                     ; graphic

; Animation routine for when Maroc is out of energy
;
; Routine called from L55885 when Maroc is out of energy. He spins towards the
; top of the screen, with a decreasing pitch sound.
;
L58476:
  LD A,(60097)            ; Maroc's vertical (Y-axis) screen position, in
                          ; pixels
  LD (60114),A            ; Copy into data buffer
  LD HL,(60098)           ; Maroc's sprite address pointer in table at L38851
  LD (60109),HL           ; Copy into data buffer
  LD A,(60096)            ; Get Maroc's horizontal (X-axis) screen position, in
                          ; half character (4-pixel) steps
  RLA                     ; Multiply by 4 to convert to horizontal pixel
  RLA                     ; position
  AND 252                 ; Filter out any carry bits that may have appeared
                          ; from the SLA
  LD (60115),A            ; ...and store horizontal pixel position in data
                          ; buffer
  LD A,0                  ; Set high byte of horizontal graphic position to
  LD (60116),A            ; indicate that it's within the current screen
                          ; (viewport) rather than to the left (255) or right
                          ; (1)
; Play sound:
L58476_0:
  LD A,(60114)            ; Get vertical graphic (pixel) position
  NEG                     ; The sound pitch/speed is based on Maroc's vertical
                          ; position as he spins upwards, so would naturally
                          ; increase in pitch. By using NEG this decreases the
                          ; pitch instead, as Maroc ascends.
  SRA A                   ; Halve the value to reduce the pitch change slightly
  LD C,A                  ; Store in C register as a loop counter
  LD E,64                 ;
  LD A,0                  ; Start loop with speaker off
L58476_1:
  XOR 16                  ; Toggle the speaker bit
  OUT (254),A             ; Play sound
  LD B,C                  ; Inner loop - short pause
L58476_2:
  DJNZ L58476_2           ;
  DEC E                   ; Outer loop - short pause
  JR NZ,L58476_1          ;
; Erase Maroc's graphic:
  LD A,0                  ; Set draw/erase flag to ERASE
  LD (60111),A            ;
  LD HL,(60109)           ; Get graphic address pointer
  CALL L56216             ; Erase Maroc's sprite
; Rotate Maroc's sprite clockwise
  LD A,(60163)            ; Rotation value - for 8 different directions, in
                          ; increments of 32
  ADD A,32                ; Rotate Maroc's sprite clockwise one graphics frame
  LD (60163),A            ; Re-store new graphics frame
  RRA                     ; Rotate rotation bits into bits 1-3
  RRA                     ;
  RRA                     ;
  RRA                     ;
  AND 14                  ; ...and filter out other unwanted bits caused by the
                          ; rotate. Value is now an even number and in the
                          ; range 0-14.
  LD E,A                  ; This corresponds to Maroc's frame (0-7) x 2.
  LD D,0                  ; Transfer this offset to DE
  LD HL,(60266)           ; Get sprite graphic address pointer
  ADD HL,DE               ; Add the offset, which now points to Maroc's new
                          ; frame (from L38851)
  LD (60109),HL           ; ...and store as address pointer in graphic data
                          ; buffer.
; The following code sets Maroc's attribute colours. Maroc's INK attribute
; colour is supposed to change as he spins upwards.
;
; However, the attribute print routine at L57888 references the byte at 60097
; for Maroc's normal vertical screen position, rather than the one at L60071,
; which changes as Maroc ascends.
;
; This means that the colour change/rotation is only applied at Maroc's base
; screen position, so once he starts rising he retains the standard screen
; colour. You can see this in the animated image at the top of this page.
  LD A,(L60071)           ; Get Maroc's attribute colour (usually 71 - bright
                          ; white)
  DEC A                   ; Decrement (Maroc is supposed to change colour as he
                          ; rises)
  AND 7                   ; Only need INK colour so filter out PAPER, BRIGHT
                          ; and FLASH bits
  LD (L60071),A           ; ...and store.
  LD A,(60114)            ; Get Maroc's vertical position (in pixels)
  SUB 4                   ; Reduce by 4 (Maroc moves upwards in half character
  LD (60114),A            ; squares)
  CALL L57888             ; Set/change Maroc's attributes (INK colour)
; Draw Maroc at his new screen position:
  LD A,1                  ; Set draw/erase flag to DRAW
  LD (60111),A            ;
  LD HL,(60109)           ; Get sprite graphics address pointer
  CALL L56216             ; Draw Maroc sprite
  LD A,(60117)            ; Flag indicating whether (any part of) graphic is
                          ; visible on screen
  CP 0                    ; Check if Maroc has disappeared off the top of the
                          ; screen
  JR NZ,L58476_0          ; If not, continue to spin him upwards and play
  RET                     ; sound.

; Calculate and print Maroc's rank
;
; Used by the routines at L49315 and L55944.
;
; See Trivia: Maroc's rank for information about how this is determined.
L58599:
  CALL L57081             ; Clear the scroll status panel at the bottom of the
                          ; screen
  LD A,34                 ; Message number 34 (message texts start from L29042)
                          ; - #34 is the "YOUR RANK IS NOW" text at 29416.
  CALL L58789             ; Identify address pointer for message text
  LD (L60065),HL          ; ...and store
  LD HL,20584             ; Set the screen display address pointer for top left
                          ; of scroll, one character line down
  LD (60068),HL           ; ..and store.
  CALL L58064             ; Print the message text on the scroll
; GET MAROC'S RANK
;
; This next routine looks through the spells and checks which ones have been
; collected (first byte of the spell data = 16).
;
; For each spell collected, the C register is incremented by 3, so it looks as
; if this will play a part in increasing Maroc's rank.
;
; HOWEVER, the routine after this resets the C register to 0 at 58651 before
; it's stored anywhere, so will effectively nullify any increments calculated
; here. So collecting spells doesn't have an effect on Maroc's rank after all.
  LD DE,16
  LD HL,(60261)           ; Address pointer to start of message texts at
                          ; L28156, starting with spell names
  LD A,(60265)            ; Number of spells (27)
  LD B,A                  ; Store in B register as a counter
  LD C,0                  ; C seems to be a counter for spells collected
  LD A,16                 ; Check if Maroc has collected this spell
L58599_0:
  CP (HL)                 ;
  JR NZ,L58599_1          ;
  INC C                   ; If so, increment score by 3
  INC C                   ;
  INC C                   ;
L58599_1:
  ADD HL,DE               ; Move onto the next spell
  DJNZ L58599_0           ; Check for all 27 spells
; ADD RANK SCORE FOR WARLOCKS DESTROYED
;
; Maroc can gain rank points by destroying any/all of the 7 warlocks, which
; appear on walls on various game levels. Warlock attributes are stored at
; L27772.
;
; Score for destroying a warlock is warlock number * 4. So warlock #1 is worth
; 4, warlock #7 is worth 28.
  LD HL,(60355)           ; Address pointer to warlock information at L27772
  INC HL                  ; If the second byte in each warlock's data set >0,
                          ; it means Maroc has destroyed this warlock.
  LD DE,8                 ; 8 bytes for each set of warlock data
  LD B,7                  ; 7 warlocks to check
  LD C,0                  ; The C register will contain the total score
L58599_2:
  LD A,(HL)               ; Get byte
  ADD HL,DE               ; (Move pointer to the next warlock data set ready
                          ; for next check)
  CP 0                    ; Check if it's 0
  JR Z,L58599_3           ; If so, this warlock has not been destroyed.
                          ; Continue to the next one.
  LD A,8                  ; If the warlock has been destroyed, calculate which
                          ; of the warlocks it is by starting with 8...
  SUB B                   ; ...and subtracting the (reversed) warlock number
                          ; (1-7)
  ADD A,A                 ; A now contains the warlock number that has been
  ADD A,A                 ; destroyed (1-7). Multiply this by 4
  ADD A,C                 ; ...and add it to the total score.
  LD C,A                  ;
L58599_3:
  DJNZ L58599_2           ; Continue to check all 7 warlocks, adding score for
                          ; each one that has been destroyed
; ADD RANK SCORE BASED ON OTHER CREATURES DESTROYED
;
; Maroc's ranks points are increased by 1 for every 2 creatures destroyed
; (creature data at 27828)
;
; Rank points are halved in the final calculation, meaning Maroc's rank will
; increase by 1 for every 4 creatures he destroys.
  LD B,4                  ; 4 types of creature to check
L58599_4:
  LD A,(HL)               ; Get (2nd) byte of set, which indicates number of
                          ; creatures destroyed
  ADD HL,DE               ; (Move pointer to the next creature set ready for
                          ; next check)
  SRA A                   ; Halve the score value
  ADD A,C                 ; ...and add it to the score
  LD C,A                  ;
  DJNZ L58599_4           ; Continue to check the 4 types of creature, adding
                          ; score for numbers destroyed
; ADD RANK SCORE BASED ON DEMONS DESTROYED
;
; Maroc receives 32 points at the point he destroys his first (but not every)
; demon in the High Temple of Chaos.
;
; The reason for this score being is a one-off increment is because unlike
; other creatures, demons respawn indefinitely.
  LD A,(HL)               ; Get (2nd) byte of set
  CP 0                    ;
  JR Z,L58599_5           ; If zero, nothing to add
  LD A,32                 ; Otherwise, add a (set) score of 32
  ADD A,C                 ;
  LD C,A                  ;
; The next check looks at Maroc's dungeon level, when he ran out of energy (or
; finishes the game). The second paired byte in the table at L50852 is doubled,
; then added to the rank/score.
;
; Using 'current' level vs 'achieved' level means Maroc receives a higher rank
; for running out of energy on deeper levels (e.g. by casting the SUMMON
; spell), but will lose ranks if he dies on the Gatehouse level, for instance.
;
; The score is added to using paired byte x 2 (e.g. running out of energy in
; the Chambers of Chaos is worth 8 x 2 = 16 points)
L58599_5:
  LD A,(60105)            ; Byte relating to level number in reference table at
                          ; L50852
  ADD A,A                 ; Double it
  ADD A,C                 ; ...and add to the score
  LD C,A                  ;
; Now a rank demotion. The byte at 60104 counts how many times Maroc has died
; (i.e. run out of energy).
;
; His score is reduced by 1 for every 4 occurences of this (score reduction =
; byte value / 4).
  LD A,(60104)            ; Get Maroc's current 'death count'
  INC A                   ; ...and increase by 1
  JR C,L58599_6           ; Avoid re-storing the increased amount if it would
                          ; mean a wrap around to 0 (if Maroc has already died
                          ; 255 times!)
  LD (60104),A            ; Re-store
L58599_6:
  RRA                     ; Divide by 4
  RRA                     ;
  AND 63                  ; Filter out any unnecesary carry bits caused by the
                          ; RRAs
  LD B,A                  ; Subtract value from calculated rank score
  LD A,C                  ;
  SUB B                   ;
  JR NC,L58599_7          ;
  LD A,0                  ; If this subtraction brings down the total rank to
                          ; less than 0, set it at 0 (APPRENTICE LORE SEEKER).
; Halve the score before using it to calculate the rank:
L58599_7:
  RRA                     ; Halve the score value
  LD C,A                  ; And store in the C register
; Use the calculated score to identify Maroc's rank:
  RRA                     ; Divide the already-halved-score by 8 to move the
  RRA                     ; score into the lowest 4 bits of the byte
  RRA                     ;
  AND 15                  ; Keep bits 0-3 (values 0-15) - this gives 16
                          ; options, which relate to the 16 titles
  ADD A,18                ; The rank title texts start at 29264, which is
                          ; message #18 from the start of the message texts
                          ; (49042), so add this.
  LD (60103),A            ; Store this value
; Calculate and print the 'descriptor' part of the rank text (one of the 8
; texts at L29206).
  LD A,C                  ; Retrieve the original score (halved so will be in
                          ; the range 0-127)
  AND 7                   ; Keep bits 0-2 (values 0-7) - this gives 8 options,
                          ; which relate to the 8 descriptors
  ADD A,10                ; The rank descriptor texts start at L29206, which is
                          ; message #10 from the start of the message texts
                          ; (L29042), so add this.
  CALL L58789             ; Identify the address pointer for the descriptor
                          ; text
  LD (L60065),HL          ; ...and store.
  LD HL,20648             ; Screen display address to the start of where the
                          ; descriptor text will be printed on the scroll
  LD (60068),HL           ; ...and store
  CALL L58064             ; Print the text on the scroll
; Print the 'title' part of the rank text (one of the 16 texts at 29264):
  LD A,(60103)            ; Retrieve the calculated text message number
  CALL L58789             ; Identify the address pointer for the text to print
  LD (L60065),HL          ; ...and store.
  LD HL,20680             ; Screen display address to the start of where the
  LD (60068),HL           ; descriptor text will be printed on the scroll, just
                          ; below where the descriptor was printed
  CALL L58064             ; Print the text on the scroll
  RET                     ;

; Clear the spell message text area on the scroll
;
; Used by the routine at L50807.
;
; Clears any messages on two lines of the message area of the scroll, e.g.
; "Project thy soul", "Gatehouse level"
L58764:
  LD L,136                ; Low byte of HL screen display address pointer which
                          ; is set to the top left of the scroll spell area,
                          ; where the spell messages (e.g. "Project thy soul")
                          ; are printed
  LD C,2                  ; 2 row of text
L58764_0:
  LD E,16                 ; 16 columns of text
L58764_1:
  LD H,80                 ; High byte of HL screen display address pointer
                          ; which is set to the top left of the scroll spell
                          ; area, where the spell messages (e.g. "Project thy
                          ; soul") are printed
  LD B,8                  ; 8 pixel rows to clear
L58764_2:
  LD (HL),0               ; Clear pixel row
  INC H                   ; Move down one pixel line
  DJNZ L58764_2           ; Repeat x 8
  INC L                   ; Move right one character square/column
  DEC E                   ; Repeat x 16 columns
  JR NZ,L58764_1          ;
  LD L,167                ; Set column position to character row below, one
                          ; line down. This should probably be one less as this
                          ; value is one character to the left of the previous
                          ; line, though it doesn't really matter
  DEC C                   ; Repeat the clear loop for 2 character rows
  JR NZ,L58764_0          ;
  RET                     ;

; Identify address of message text
;
; Used by the routines at L49215, L50807, L51043, L55944 and L58599.
;
; A Message number (1-37). Message text lists stored at L29042, beginning with
;   level names.
L58789:
  LD HL,(L60251)          ; Address pointer for text to print
  LD D,1                  ; Start at text #1
L58789_0:
  CP D                    ; Determine which message number to print - is it
                          ; this one?
  JR Z,L58789_2           ; If so, RETurn
  LD B,(HL)               ; If not, get the number of text characters in this
                          ; message
  INC B                   ; +1 (correction to set the counter at the right
                          ; number)
L58789_1:
  INC HL                  ; Move to the next byte
  DJNZ L58789_1           ; Skip the rest of the bytes for this message
  INC D                   ; Increment message number/counter
  JR L58789_0             ; ...and run the check again for the next message
L58789_2:
  RET                     ;

; Play music
;
; Used by the routines at L49345, L51043 and L55944.
;
; A Indicates which music to play (1 = intro tune, 2 = paused game tune)
;
; There are two tunes/melodies.
;
; (1) The first tune is played at the end of the intro sequence when a new game
; is started, and also when the game is completed. Uses music data stored at
; L60400.
;
; (2) The second tune is played then the game is paused. Uses music data at
; 60530.
L58806:
  CP 1                    ; Check which tune needs to be played
  JR NZ,L58806_0          ;
  LD HL,L60400            ; Point HL at first note(s) of the intro/end tune
  JR L58806_1             ; data
L58806_0:
  LD HL,60530             ; Point HL at first note(s) of the paused game tune
                          ; data.
; Play notes
L58806_1:
  LD A,(HL)               ; Get note value
  CP 255                  ; 255 is an end-of-music marker
  JR Z,L58806_5           ; If so, RETurn to previous routine
  LD B,A                  ; Get first note of pair
  INC HL                  ; Get second note of pair
  LD A,(HL)               ;
  LD C,A                  ; ...and store in C register
  INC HL                  ; Move note data pointer on ready for next note
  LD (60244),HL           ; ...and store
  LD H,B                  ; H = first note of pair, e.g. 190
  LD A,C                  ;
  ADD A,32                ; +32 to create a phase-type effect
  LD L,A                  ; L = second note of pair, plus 32, e.g. 222
  LD DE,7168              ; 7168 = Note duration
  LD A,0                  ; Reset A to 0
L58806_2:
  DEC H                   ; Decrement first note byte (for sound note loop)
  JR NZ,L58806_3          ; Reached zero?
  OR 16                   ; If zero, ensure speaker bit (4) is set to play
                          ; sound
  LD H,B                  ; ...and restore first note of pair again
L58806_3:
  DEC L                   ; Decrement second note byte (for sound note loop)
  JR NZ,L58806_4          ; Reached zero?
  OR 16                   ; If zero, ensure speaker bit (4) is set
  LD L,C                  ; ...and restore second note of pair again
L58806_4:
  ADD A,8                 ; 'Thickens out' the sound by ensuring speaker is
                          ; toggled on a bit more
  AND 16                  ; Filter out other bits, only keeping bit (4) speaker
                          ; toggle bit
  OUT (254),A             ; ...and play sound by toggling speaker on or off
                          ; accordingly
  SRA A                   ; Shift bits right
  LD (L60243),A           ; ..and store, as A register needed for next bit
  DEC DE                  ; Decrement note counter
  LD A,D                  ; And check if at zero
  OR E                    ;
  LD A,(L60243)           ; Restore A register which holds the speaker bits
  JR NZ,L58806_2          ; If not at zero yet, continue to play note
  LD HL,(60244)           ; Note played. Get data pointer
  JR L58806_1             ; ...and go and play next note
L58806_5:
  RET                     ; Return to routine at L49345 or L51043.

; Generate sound effect when Maroc picks up a scroll/spell/item
;
; Used by the routine at L52338.
;
; Sound effect routine called when Maroc collects a spell or object. Just a
; 'blip' for an object. The sound effect continues for longer if it's a spell.
;
; The continuing sound loop for spells is played at 54106, but this routine is
; CALLed for both objects and spells.
L58878:
  LD A,16                 ; Bit 4 - speaker bit
  LD C,48                 ; Outer loop counter
L58878_0:
  LD B,C                  ; Set inner loop counter to same
  OUT (254),A             ; Output sound
  XOR 16                  ; Toggle speaker bit
L58878_1:
  NOP                     ; Inner loop pause
  NOP                     ;
  NOP                     ;
  DJNZ L58878_1           ; Inner loop repeat (x48 initially, decreasing)
  DEC C                   ; Decrement outer loop counter
  JR NZ,L58878_0          ; Repeat x48
  RET                     ;

; Intro sequence - toggle sky colour between blue/yellow
;
; Used by the routine at L49274.
;
; This routine alternates the INK and PAPER colours of the sky above the
; landscape to flash between yellow and blue.
;
; It checks the INK and PAPER colours of the byte (1 or 6) and toggles between
; them.
;
; The effect doesn't filter out squares in the left/right border - because a
; section on the left has yellow in it, it gets affected - see Bugs - Intro
; sequence - lightning effect colour bleeds into border.
L58896:
  LD B,255                ; 255 bytes covers a couple of rows more than the
                          ; first third of the screen.
  LD HL,22592             ; Screen attribute address - top left of the screen,
                          ; then two rows down below the top border
; Determine INK colour in screen attribute byte:
L58896_0:
  LD A,(HL)               ; Get screen attribute byte
  LD D,A                  ; Store in D register
  AND 7                   ; Get the INK value from the screen attribute byte
                          ; (0-7)
  CP 1                    ; Is it blue (INK 1)?
  JR NZ,L58896_1          ;
  LD A,6                  ; If so, set the INK colour to yellow (6) and skip
  JR L58896_2             ; next check
L58896_1:
  CP 6                    ; Is the INK colour yellow (6)?
  JR NZ,L58896_2          ;
  LD A,1                  ; If so, Set the INK colour to blue
; Determine PAPER colour to paint sky - alternating between yellow and blue:
L58896_2:
  LD E,A                  ; Copy INK colour into E register - blue (1) or
                          ; yellow (6)
  LD A,D                  ; Get screen attribute byte
  AND 56                  ; Filter out everything but the PAPER colour (bits
                          ; 3-5)
  CP 8                    ; Is it blue (PAPER 1)?
  JR NZ,L58896_3          ;
  LD A,48                 ; If so, set to yellow (PAPER 6) and skip next check
  JR L58896_4             ;
L58896_3:
  CP 48                   ; Is it yellow (PAPER 6)?
  JR NZ,L58896_4          ;
  LD A,8                  ; If so, set to blue (PAPER 1)
; Combine calculated INK and PAPER parts of attribute byte:
L58896_4:
  OR E                    ; Combine PAPER value with INK value calculated
                          ; earlier
  LD (HL),A               ; ...and print onto screen
  INC HL                  ; Move right one square
  AND 16                  ; This instruction has no effect, as the A register
                          ; is assigned a new value within the next couple of
                          ; instructions
  DJNZ L58896_0           ; Repeat x 255, covering the top third of the screen
                          ; (and a bit more).
  RET                     ; Return to the routine at L49274

; Main loop - handle spell menu and keyboard/joystick inputs
;
; Used by the routine at L51152.
L58945:
  LD A,1
  LD (60240),A            ; Set graphic frame number/address pointer offset (no
  LD A,0                  ; offset)
; Deal with spell menu routines, depending on spells activated:
  LD (60343),A            ; General purpose byte used for a few different
                          ; things - reset here
  LD A,(L60129)           ; Check what's been already drawn
  CP 8                    ;
  JP Z,L58945_0           ; If the spell list has already been printed, can
                          ; skip the next few routines as they've been done
  CP 24                   ; Energy bar printed
  JP Z,L59262             ;
  CP 32                   ; MOVE spell selected
  JP Z,L59474             ;
  CP 48                   ; Spell cast requiring a controllable cursor icon,
  JP Z,L59689             ; e.g. SERVANT, MISSILE
  CP 56                   ; Spell selected that is the same as the currently
  JP Z,L59933             ; active effect spell
  CALL L57081             ; Clear the Scroll status panel at the bottom of the
                          ; screen
  CALL L57139             ; Print spell names on the scroll
  LD A,0                  ;
  LD (60140),A            ; Reset spell number/pointer (60134)
  LD A,8                  ;
  LD (L60129),A           ; Indicate that spell list has now been printed
; Draw the pointer/selector arrow on the scroll:
L58945_0:
  LD A,133                ; Graphics address pointer offset for the scroll
                          ; pointer arrow graphics at 44966.
  CALL L57538             ; Set up the arrow graphic ready to draw
  LD DE,20626             ; Screen address display position for the middle of
                          ; the scroll, to draw the arrow pointer
  CALL L56612             ; Draw the scroll arrow pointer
; Next, check for key/control presses in the spell menu.
;
; Check if the fire button is being pressed:
  LD A,(60210)            ; Check FIRE control flag (0 = not pressed, 1 =
  CP 0                    ; pressed)
  JR Z,L58945_1           ;
  JP L59130               ; Launch spell selection routine if fire is pressed
; Fire button not pressed - check for UP/DOWN:
L58945_1:
  LD A,(60158)            ; Get up/down flag: 1 = up, -1 (255) = down, 0 = not
                          ; pressed
  CP 0                    ; Check if it's pressed
  JR NZ,L59033            ;
  LD A,5                  ; If it's not pressed, set this counter byte to 5 -
  LD (60070),A            ; it's used to determine an incremental series of 5
  RET                     ; tones, while the player holds up/down to scroll
                          ; through the spell list

; UP/DOWN controls pressed while in spell menu
;
; Used by the routine at L58945.
;
; This routine cycles through the spell list at L28156, printing any spells
; that have been collected.
;
; If the first byte of a spell's data set is 16, it means the spell has been
; collected and is available for display/selection.
;
; Check whether it's up or down that's been pressed:
L59033:
  LD C,A                  ; Temp store for up/down flag: 1 = up, -1 (255) =
                          ; down
  LD A,(60070)            ; Retrieve the counter flag set in the previous
                          ; routine, used to create the incremental pitch sound
                          ; effects as the player scrolls through the spells
  CP 0                    ; Skip next two instructions if zero (reached max
  JR Z,L59033_0           ; pitch)
  DEC A                   ; Otherwise decrement...
  LD (60070),A            ; ...and re-store.
L59033_0:
  LD A,C                  ; Retrieve the up/down flag value from C register
  CP 1                    ; Check if UP pressed. If not, run the following
  JR Z,L59033_3           ; routine for DOWN.
; DOWN pressed while in spell menu:
  LD A,(60130)            ; Spell counter (up to 27 spells) for current spell
  LD HL,(60131)           ; Address pointer for the current position in the
  LD DE,65520             ; spell list (spells at L28156)
L59033_1:
  CP 0                    ; If we don't currently have a counter position (byte
  JR NZ,L59033_2          ; at 60130 is zero), then start at the end of the
                          ; spell list ready to move up it
  LD HL,(60263)           ; Address pointer for the end of the spell list texts
                          ; at L28604
  LD A,(60265)            ; Total number of spells (27)
  INC A                   ; Incremented ready for decrement at the start of the
                          ; following loop
L59033_2:
  ADD HL,DE               ; Subtracts 16 from HL - first check is the data set
                          ; for the last spell (MESSAGE) at 28588
  DEC A                   ; Decrement spell number counter (starts at 27)
  LD C,A                  ; Store temporarily
  LD A,(HL)               ; Get 'spell collected' data byte
  CP 16                   ; Has the spell been collected (byte value = 16)?
  LD A,C                  ; (Retrieve spell number counter)
  JR NZ,L59033_1          ; If it hasn't been collected, keep checking the rest
                          ; of the spells
  LD (60130),A            ; Spell is available, so store the spell counter...
  LD (60131),HL           ; ...and the spell list address pointer
  CALL L57139             ; Print the spell names on the scroll
  RET                     ;
; UP pressed while in spell menu:
L59033_3:
  LD A,(60130)            ; Spell counter (up to 27 spells) for current spell
  LD C,A                  ;
  LD HL,(60131)           ; Address pointer for the current position in the
                          ; spell list (spells at L28156)
  LD DE,16                ; Offset for the spell address pointer to move down
                          ; to the next spell
L59033_4:
  LD A,(60265)            ; Total number of spells
  CP C                    ; Check if we've reached the end of the list...
  JR NZ,L59033_5          ;
  LD HL,(60261)           ; ...If so, switch to the start of the spell list
  LD C,0                  ; ...and set the spell counter to zero
  JR L59033_6             ;
L59033_5:
  ADD HL,DE               ; Move down to next spell
  INC C                   ; Increment the spell counter
L59033_6:
  LD A,(HL)               ; Get 'spell collected' data byte
  CP 16                   ; Has the spell been collected (byte value = 16)?
  JR NZ,L59033_4          ; If it hasn't been collected, keep checking the rest
                          ; of the spells
  LD A,C                  ; Spell is available, so store the spell counter...
  LD (60130),A            ;
  LD (60131),HL           ; ...and the spell list address pointer
  CALL L57139             ; Print the spell names on the scroll
  RET                     ;

; Draw active spell charges and icon on scroll
;
; Used by the routine at L58945.
;
; When fire is pressed in a scroll list, the spell is initiated, and the spell
; text description displayed on the scroll.
;
; The user has to re-confirm the selection by pressing fire again, which
; activates the spell.
L59130:
  LD A,0                  ; Reset the fire control value (back to 0)
  LD (60210),A            ;
  CALL L57081             ; Clear the scroll area
; Copy the currently selected spell data (16 bytes) from L28156 into a data
; store at L60357.
  LD HL,(60135)           ; Address pointer for selected spell at L28156
  LD DE,L60357            ; Data store/buffer for selected spell
  LD BC,16                ;
  LDIR                    ; Copy the 16 bytes over
; Print the spell name at the top (first line) of the scroll:
  LD HL,60365             ; Address pointer to the current selected spell name
  LD (L60065),HL          ; Store text address pointer for printing the spell
                          ; name
  LD HL,20552             ; Set the screen display address to the top left of
                          ; the scroll
  LD (60068),HL           ; ...and store.
  LD A,8                  ; Each spell name is 8 characters long (includes
  LD (60067),A            ; spaces for padding if name is shorter)
  CALL L58064_0           ; Print the spell name text on the scroll
; Set display address and point at the spell icon graphics. Determine how many
; spell 'charges' are left.
  LD A,131                ; Offset for graphics address table at L38851.
                          ; Graphics pointer to spell icon graphics at 44775.
  CALL L57538             ; Setup graphics data, DE register pair now points to
                          ; start of spell icon graphic
  LD HL,20560             ; Set position for spell icon at top of scroll
  LD A,(60360)            ; Counter for number of spell 'charges'
  CP 4                    ; If the spell has 4 or more charges...
  JR C,L59130_0           ;
  LD A,3                  ; ...Set the number to 3, as a maximum of 3 icons are
                          ; printed on the scroll
; Print the spell charge icons at the top of the scroll:
;
; Up to 3 icons are drawn. If the player has 4 or more 'charges' for a spell,
; three icons are displayed.
L59130_0:
  LD (60103),A            ; Store the counter for the spell charge icons (up to
                          ; 3)
  INC L                   ; Move right one character square
  LD (60068),HL           ; Store the screen display address pointer
  EX DE,HL                ; Switch into DE register
  CALL L56612             ; Draw the spell charge icon at the top of the scroll
  LD HL,(60068)           ;
  INC L                   ; Move right one character square
  LD A,(60103)            ; Retrieve and decrement the spell charge counter
  DEC A                   ;
  JR NZ,L59130_0          ; Has it reached zero? If not, go back and draw the
                          ; next icon
; This routine draws the appropriate flashing icon for the selected spell in
; the top right of the scroll:
  LD A,(60363)            ; Graphics pointer offset for the icon graphic to use
                          ; for this spell (icons at L41342)
  CALL L57538             ; Setup graphics ready to draw
  LD DE,20567             ; Set screen display address position to draw icon
                          ; (top right of scroll)
  CALL L56612             ; Draw the spell icon

; Write active spell message on scroll and draw energy bar
;
; Print the appropriate message (L28604) for the active spell on the scroll.
L59219:
  LD A,(60134)            ; Get the spell message number
  LD HL,(60259)           ; Address of spell messages (28605)
  LD D,0                  ; D = counter to check message number against
; Get the address pointer to the correct spell text:
L59219_0:
  CP D                    ; Check spell message number against current message
                          ; counter
  JR Z,L59219_2           ; If it's the same, we're at the right message so
                          ; skip ahead to L59219_2
  LD B,(HL)               ; Length of current text string
  INC B                   ; Increment for the following check loop
L59219_1:
  INC HL                  ; Move address pointer along
  DJNZ L59219_1           ; ...to the next message
  INC D                   ; Increment the counter (to check spell message
                          ; against)
  JR L59219_0             ; ...and keep checking
; The HL register pair is now pointing to the active spell message text.
L59219_2:
  LD (60138),HL           ; Store the spell message text address pointer
  LD A,0                  ;
  LD (60361),A            ; Reset the spell message text counter
; Draw the energy bar:
  LD A,132                ; Graphics address pointer offset for 39113, which
                          ; points at the energy bar graphic at L44787.
  CALL L57538             ; Set up graphics ready to draw
  LD DE,20679             ; Set screen display address to the bottom left of
                          ; the scroll
  CALL L56612             ; Draw the energy bar
  LD A,24                 ; This byte is set to 24 which indicates the energy
  LD (L60129),A           ; bar has just been drawn - checked in routine at
                          ; L58945

; Check for UP/DOWN and FIRE control presses after a spell is selected
;
; Used by the routine at L58945.
;
; Also follows previous routine after the energy bar has been drawn.
;
; Checks for an ongoing effect spell being deactivated, and for key presses
; once a spell has been chosen:
L59262:
  LD A,(60134)            ; Get spell counter
  LD C,A                  ;
  LD A,(60137)            ; Is there currently an 'effect' spell active (e.g.
  CP 0                    ; SHIELD, UNSEEN)
  JR Z,L59262_0           ;
  CP C                    ; If there is, is the triggered spell the same as the
                          ; currently active spell?
  JP Z,L59373             ; If so, casting the spell will deactivate it
; When a spell is selected, the player can press FIRE to activate/cast the
; spell, or press UP/DOWN to immediately go back to scrolling through the spell
; list.
;
; Check for FIRE (activate) or UP/DOWN (back to spell list):
L59262_0:
  LD A,(60210)            ; Check if FIRE button pressed
  CP 1                    ; If pressed, skip the next few instructions
  JR Z,L59298             ;
  LD A,(60158)            ; Check if UP/DOWN pressed
  CP 0                    ; If it's pressed, skip ahead to L59956_4
  JP NZ,L59956_4          ;
  CALL L56668             ; Nothing pressed, so continue to print the active
                          ; spell's message text
  JP L59956_6             ; Nothing more to do at this point so jump straight
                          ; to a RET statement

; Player has cast a spell
;
; Used by the routine at L59262.
;
; The player has selected (FIRE button press) and then confirmed (second FIRE
; button press) a spell from the list.
L59298:
  LD A,0                  ; Reset fire button register, store zero value
  LD (60210),A            ;
; The following routine decrements the number of charges left for the spell.
;
; 'Active effect' spells (SHIELD, UNSEEN etc.) are deactivated by casting the
; same spell again. Therefore, spell charges for these spells are not reduced
; now, but later at L59956 when the spell is cast again to 'deactivate' it.
  LD A,(60359)            ; Check the 'spell type' byte
  CP 4                    ; Is it an 'ongoing effect' spell (SHIELD, UNSEEN,
                          ; PROTECT, AMULET, DEFENCE, WRAITHBANE, CHALICE)?
  JR Z,L59330             ; If so, skip this routine
  LD A,(60360)            ; Number of spell 'charges' left
  CP 255                  ; 255 = infinite charges - no need to decrease
  JR Z,L59298_0           ; charges
  DEC A                   ; Otherwise, reduce charges by 1
  LD (60360),A            ; ...and re-store.
  CP 0                    ; Zero charges left?
  JR NZ,L59298_0          ;
  LD (L60357),A           ; If so, set the spell to 'not acquired' (0) to
                          ; remove it from the list as this is its last use
L59298_0:
  JR L59373               ; ...and set the flashing icon in the top right of
                          ; the scroll

; Print name of ongoing effect spell in small scroll in bottom right of screen
;
; Run after spell is cast (L59298) if the spell triggered is an 'ongoing
; effect' type spell.
;
; * Ongoing 'effect' spells stay active until the player deactivates it either
;   by re-casting it, or casting a different effect spell (e.g. switching from
;   UNSEEN to SHIELD)
; * While an 'effect' spell is active, the player can cast other spells (e.g.
;   MOVE, SERVANT, MISSLE) without deactivating the current 'effect' spell. See
;   Bugs - Switching between 'effect' spells doesn't reduce a spell's charges
; * 'Effect' spells are: SHIELD, UNSEEN, PROTECT, AMULET, DEFENCE, WRAITHBANE
;   (displayed as W BANE), CHALICE
;
; Print the spell name in the bottom right:
L59330:
  LD HL,60365             ; Store the address pointer for spell name text
  LD (L60065),HL          ;
  LD HL,20729             ; Screen display address pointer for the start of the
                          ; text (left of small scroll area)
  LD (60068),HL           ; Store screen display address pointer
  LD A,7                  ; 7 characters to print (no effect spells need 8
                          ; letters)
  LD (60067),A            ; Store text character counter
  CALL L58064_0           ; Print the spell name
; Check if the 'effect' spell cast is the same as the active one (deactivate)
; or a different one (replace):
  LD A,(60134)            ; Get spell (number) cast
  LD C,A                  ;
  LD A,(60137)            ; Compare with current 'active effect' spell
  CP C                    ;
  JR Z,L59373             ; It's the same one, so prepare to deactivate the
                          ; spell:
; The spell cast is different from the currently active spell (or there isn't a
; currently active spell):
  LD A,C                  ; Spell number of cast spell
  LD (60137),A            ; Set the spell being cast as the active 'effect'
                          ; spell
  LD A,(60358)            ; Amount of energy that this spell drains (e.g.
                          ; SHIELD) or heals (e.g. CHALICE)
  LD (60373),A            ; This byte is used to intermittently drain or heal
  JP L59956_4             ; Maroc's energy as time passes (54859)

; Set FLASHing attributes for the spell icon in the top right of the scroll
;
; Used by the routines at L59262, L59298 and L59330.
;
; The spell's icon is set to flash when a spell has been cast and 'in effect',
; e.g. MOVE, SERVANT, MISSILE. The flash effect isn't needed for instant effect
; spells like ENERGIZE.
;
; Set the top right of the screen scroll screen display attributes to FLASH (2
; x 2 character square)
L59373:
  LD HL,23127             ; Screen display attribute address - top right of
                          ; scroll, top left of 2x2 square
  LD (HL),176             ; Attribute value for INK 0, PAPER 6 (yellow), FLASH
                          ; 1
  INC HL                  ; Move right one square
  LD (HL),176             ; Set square to FLASH
  LD HL,23159             ; Screen display attribute address - bottom left of
                          ; 2x2 square
  LD (HL),176             ; Set square to FLASH
  INC HL                  ; Move right one square
  LD (HL),176             ; Set square to FLASH

; Check which spell is being cast
;
; There are 5 sorts of spell type, the value stored in the current spell data
; byte at 60359.
; * MOVE spell, which switches player control to Maroc (byte value = 1)
; * Spell which switches player control to a graphic/icon cursor, e.g. SERVANT,
;   MISSILE, OPEN (byte value = 2)
; * Missile type spells that don't deactivate after a bolt is fired, reserved
;   just for ELECTRIC and FLAME spells (byte value = 3)
; * Ongoing effect spell, e.g. SHIELD, WRAITHBANE (byte value = 4)
; * Instant effect spell, e.g. ENERGIZE, FREEZE, PORTAL (byte value = 5)
;
; This routine checks for spell type, and jumps to the routine that deals with
; it.
;
; Check for 'active effect' spell (type = 4):
L59389:
  LD A,(60359)
  CP 4
  JP Z,L59933             ; Jump here if so, as casting this sort of spell may
                          ; be cancelling an existing active spell.
; Check for other types of spell:
  LD A,(60134)            ; Get spell number counter (for spell list at L28604)
  LD (60140),A            ; ...and put in temporary store
  LD A,(60359)            ; Get spell type
; Check for MOVE spell
  CP 1
  JR NZ,L59389_0
  LD A,32                 ; Move spell selected. Set the spell selection byte
  LD (L60129),A           ; accordingly.
  JR L59474               ;
; Check if spell is an 'instant effect' spell (ENERGIZE, HAIL, WAYSTONE,
; FREEZE, SUMMON, PORTAL, MESSAGE):
L59389_0:
  CP 5
  JR NZ,L59389_1
; Spell is an 'instant effect' spell. These spells have an energy cost to their
; casting (positive in the case of ENERGIZE).
  LD A,(60358)            ; Get energy cost of spell. This is the second byte
                          ; in each spell set at L28156, e.g.:
                          ; * ENERGIZE = +64
                          ; * HAIL = -1
                          ; * WAYSTONE = -4
                          ; * FREEZE = -4
                          ; * SUMMON = -4
                          ; * PORTAL = -8
  CALL L58316             ; Reduce/increase Maroc's energy
  JP L59956_4             ;
; The spell cast needs a controllable cursor (e.g. SERVANT, OPEN, MISSILE,
; FIND)
L59389_1:
  LD A,1
  LD (60240),A            ; Set graphic address pointer frame offset (1 = no
                          ; offset, start at first graphics frame)
  LD (60569),A            ; Copy to controllable spell cursor/graphic frame
                          ; buffer
  LD A,(60364)            ; Get graphic number for controllable cursor. This
                          ; will either be a pointer to the servant graphic
                          ; (38931/41180) or the flashing eye cursor
                          ; (38935/41221)
  CALL L57538             ; Setup graphics (for servant or eye cursor)
; Copy/initialize a few spell-related bytes in the spell data buffer:
  LD HL,(60241)           ; Get cursor graphics address pointer (38931/38935)
  LD (L60564),HL          ; ...and store in temporary game buffer
  LD A,(60239)            ; Pre-graphics data byte, indicating frames & if
  LD (60570),A            ; graphic can be 'flipped'
  LD A,40                 ; Starting vertical position for the controllable
  LD (60159),A            ; graphic, in pixels, from the top of the playing
                          ; area
  LD A,112                ; Starting horizontal position for the controllable
  LD (60160),A            ; graphic, in pixels, from the left of the playing
                          ; area
  LD A,48                 ; Spell selection status - 48 = servant/cursor
  LD (L60129),A           ; controllable spell
  JP L59689               ;

; Check horizontal movement direction & speed (MOVE spell)
;
; Used by the routines at L58945 and L59389.
L59474:
  CALL L56668             ; Continue to print the spell's message text
  LD A,(60164)            ; Get Maroc's current left/right (horizontal) speed
  LD C,A                  ;
  LD A,(L60157)           ; Get left/right controls flag
  CP 0                    ;
  JR Z,L59520             ; If left/right controls aren't pressed, jump to
                          ; L59520 to slow Maroc down if he's moving
                          ; horizontally

; Increase Maroc's horizonal movement speed
;
; A Left/right controls flag, stored at L60157
; C Maroc's current left/right (horizontal) speed, stored at 60164
;
; Maroc's speed is increased/decreased in steps of 8 when keys are pressed. If
; the value is negative (value is > 128), Maroc is moving right. If the value
; is 0, Maroc is not moving horizontally, though he may be moving vertically.
;
; A max speed of 32/-32 equates to Maroc moving 8 pixels per game cycle.
L59488:
  CP 128                  ; If bit 7 is set (value is > 128), Maroc is moving
  JR NC,L59488_0          ; right
  LD D,8                  ; Increase Maroc's left movement speed by 8
  JR L59488_1             ;
L59488_0:
  LD D,248                ; Increase Maroc's right movement speed by 8
L59488_1:
  LD A,C                  ;
  ADD A,D                 ; Add the above to Maroc's speed accordingly
; Speed can't be greater than 32 (or less than 224 if Maroc is moving right),
; so limit speed to this value if it's gone over.
  CP 128                  ; Is Maroc moving left or right?
  JR C,L59488_2           ;
; Maroc is moving right - max speed check
  CP 224                  ; Check if we've exceeded the maximum speed for this
  JR NC,L59488_3          ; direction (< 224)
  LD A,224                ; ...If so, set speed to maximum (224)
  JR L59488_3             ;
; Maroc is moving left - max speed check
L59488_2:
  CP 32                   ; Check if we've exceeded the maximum speed for this
  JR C,L59488_3           ; direction (> 32)
  LD A,32                 ; ...If so, set speed to maximum (32)
L59488_3:
  JR L59520_1             ; Jump to the end of the next routine to store the
                          ; increased speed

; Decrease Maroc's horizontal movement speed
;
; Used by the routine at L59474.
;
; C Maroc's horizontal movement speed (stored at 60164)
;
; When left/right control keys are released, Maroc will slow his horizontal
; movement, eventually coming to a stop.
L59520:
  LD A,C                  ; Get Maroc's horizontal movement speed
  CP 0                    ; Is he moving left or right?
  JR Z,L59541             ; If Maroc is not moving horizontally left or right,
                          ; skip to next routine
  SRA A                   ; Calculate 1/4 of Maroc's current speed
  SRA A                   ;
  NEG                     ; This value will be added to the speed, so NEG will
                          ; ensure the adjustment is subtracted
  CP 0                    ; Check if this means Maroc has stopped moving
  JR NZ,L59520_0          ; left/right
  LD C,0                  ; ...If so, set speed offset to zero
L59520_0:
  ADD A,C                 ; ...Otherwise, reduce current speed by 1/4
; This entry point is used by the routine at L59488.
L59520_1:
  LD (60164),A            ; Store Maroc's adjusted horizontal movement speed

; Check vertical movement direction & speed (MOVE spell)
;
; Used by the routine at L59520.
L59541:
  LD A,(60165)            ; Get Maroc's current up/down (vertical) speed
  LD C,A                  ;
  LD A,(60158)            ; Get up/down controls flag
  CP 0                    ;
  JR Z,L59584             ; If up/down hasn't been pressed, jump to L59584 to
                          ; slow Maroc down if he's currently moving vertically

; Increase Maroc's vertical movement speed
;
; A Up/down controls flag, stored at 60158
; C Maroc's current up/down (vertical) speed, stored at 60165
;
; Maroc's speed is increased/decreased in steps of 8 when keys are pressed. If
; the value is negative (value is > 128), Maroc is moving down. If the value is
; 0, Maroc is not moving vertically, though he may be moving horizontally.
;
; A max speed of 32/-32 equates to Maroc moving 8 pixels per game cycle.
L59552:
  CP 128                  ; If bit 7 is set (value is > 128), Maroc is moving
  JR NC,L59552_0          ; down
  LD D,8                  ; Increase Maroc's up movement speed by 8
  JR L59552_1             ;
L59552_0:
  LD D,248                ; Increase Maroc's down movement speed by 8
L59552_1:
  LD A,C                  ; Add the above to Maroc's speed accordingly
  ADD A,D                 ;
; Speed can't be greater than 32 (or less than 224 if Maroc is moving down), so
; limit speed to this value if it's gone over.
  CP 128                  ; Is Maroc's moving up or down?
  JR C,L59552_2           ;
; Maroc is moving down - max speed check:
  CP 224                  ; Check if we've exceeded the maximum speed for this
  JR NC,L59552_3          ; direction (< 224)
  LD A,224                ; ...If so, set speed to maximum (224)
  JR L59552_3             ;
; Maroc is moving up - max speed check:
L59552_2:
  CP 32                   ; Check if we've exceeded the maximum speed for this
  JR C,L59552_3           ; direction (> 32)
  LD A,32                 ; ...If so, set speed to maximum (32)
L59552_3:
  JR L59584_1             ; Jump to the end of the next routine to store the
                          ; increased speed

; Decrease Maroc's vertical movement speed
;
; Used by the routine at L59541.
;
; C Maroc's vertical movement speed (stored at 60165)
;
; When control keys are released, Maroc will slow down, eventually coming to a
; stop if no keys are pressed..
L59584:
  LD A,C                  ; Get Maroc's horizontal movement speed
  CP 0                    ; Is he moving up or down?
  JR Z,L59584_1           ; If not, skip to next routine
  SRA A                   ; Calculate 1/4 of Maroc's current speed
  SRA A                   ;
  NEG                     ; This value will be added to the speed, so NEG will
                          ; ensure adjustment is subtracted
  CP 0                    ; Check if this means Maroc has stopped moving
  JR NZ,L59584_0          ; up/down
  LD C,0                  ; ...If so, set speed offset to zero
L59584_0:
  ADD A,C                 ; ...Otherwise, reduce current speed by 1/4
; This entry point is used by the routine at L59552.
L59584_1:
  LD (60165),A            ; Store Maroc's adjusted vertical movement speed

; Set Maroc's speed to zero if FIRE pressed while he is moving
;
; If FIRE is pressed to bring up the spell menu, Maroc stops dead (both
; vertical/horizontal movement), rather than slowing down.
;
; First check whether Maroc is in a tunnel room. The spell list is inaccessible
; here so pressing FIRE does nothing:
L59605:
  LD A,(60087)            ; Get Maroc's current room number
  CP 224                  ; Tunnel rooms are from room number 224 onwards
  JR NC,L59630            ;
; Maroc is NOT in a tunnel room so the FIRE button is enabled:
  LD A,(60210)
  CP 0                    ; Check FIRE control
  JR Z,L59630             ; If not pressed, skip to next routine
; FIRE button pressed:
  LD A,0
  LD (60165),A            ; Set Maroc's vertical movement speed to zero
  LD (60164),A            ; Set Maroc's horizontal movement speed to zero
  JP L59956_4             ; Continue on to clear the scroll spell menu

; MOVE spell continued - set viewport scenery speed/movement based on Maroc's
;
; Used by the routine at L59605.
;
; This routine sets the general room/viewport movement based on Maroc's updated
; vertical/horizontal movement speed.
;
; Although the game gives the effect of Maroc moving, he's not; it's actually
; every other graphic item that's moving in the opposite direction, so we need
; to change the room position based on the NEGative of Maroc's speed/direction.
;
; First, check if Maroc is in a vertical scrolling tunnel:
L59630:
  LD A,(60087)            ; Get the current room number
  CP 224                  ; If >=224, Maroc is in a vertically scrolling tunnel
  JR NC,L59630_0          ;
; Maroc is in a standard room, not a vertical tunnel:
  LD E,90                 ; Default vertical pixel position of the room
  LD (60234),A            ; Store room number
  LD A,28                 ;
  LD (60232),A            ; Default horizontal position of the room, in half
                          ; character (4 pixel) steps
  LD A,(60164)            ; Calculate and store NEGative value of Maroc's
  NEG                     ; horizontal movement speed (room elements move in
  LD (60236),A            ; the opposite direction to Maroc's controlled
                          ; movement)
  LD A,(60165)            ; Calculate and store NEGative value of Maroc's
  NEG                     ; vertical movement speed
  LD (60237),A            ;
  CALL L57401             ; Run room boundary collision check and adjustment
  LD A,(60237)            ; Copy back the post-boundary check adjusted position
  NEG                     ; to Maroc's vertical position
  LD (60165),A            ;
  LD A,(60236)            ; Copy back the post-boundary check adjusted position
  NEG                     ; to Maroc's horizontal position
  LD (60164),A            ;
  RET                     ; Return to the routine at 51156
; Maroc is in a vertical scrolling tunnel.
;
; The player can't alter Maroc's vertical speed - it's set at max (32):
L59630_0:
  LD A,32                 ; Set Maroc's vertical upward movement speed to
  LD (60165),A            ; maximum (32)
  RET                     ; Return to the routine at 51156

; Player has cast a spell requiring a controllable cursor (e.g. SERVANT,
; MISSILE, OPEN)
;
; Used by the routines at L58945 and L59389.
;
; Copy a few spell-related bytes into game data buffers at L60227 and L60107:
L59689:
  LD A,(60569)            ; Copy sprite frame number to data buffer
  LD (60240),A            ;
  LD A,(60570)            ; Copy pre-graphics byte (for servant or flashing eye
  LD (60239),A            ; graphic) to data buffer
  LD HL,(L60564)          ; Copy graphics address pointer to data buffer
  LD (60241),HL           ;
  CALL L58166             ; Calculate graphic frame address to use for animated
                          ; graphics
  LD A,(60240)            ; Copy graphic frame number to data buffer
  LD (60569),A            ;
  CALL L56668             ; Continue to print spell message text and Maroc's
                          ; energy bar on scroll
  LD A,(60160)            ; Copy sprite horizontal position (in pixels) into
  LD (60115),A            ; buffer
  LD A,(60159)            ; Copy sprite vertical position (in pixels) into
  LD (60114),A            ; buffer
  LD A,1                  ; Graphic type = 1
  LD (L60227),A           ;

; Calculate change to servant/cursor icon horizontal screen position
;
; This routine calculates the horizontal direction and speed of the
; servant/spell cursor icon, and adds/subtracts it from the sprite's horizontal
; pixel position.
L59736:
  LD A,(60161)            ; Get sprite horizontal movement speed
  LD C,A                  ;
  LD A,(L60157)           ; Get left/right sprite control value (determine
                          ; whether the sprite is moving and in which
                          ; direction)
  CALL L57276             ; Calculate the new sprite speed/position offset
                          ; based on direction/speed (returned in H register)
  LD A,H                  ; Retrieve calculated offset from H register...
  LD (60161),A            ; ...and store
  LD A,(60160)            ; Get the sprite's current horizontal screen position
  ADD A,H                 ; Add (or subtract) the offset calculated earlier
  LD C,A                  ; Temporary store in C register
  SUB 12                  ; The left and right play area limits are 12 and 228
  CP 216                  ; respectively. This check forces a NC continue to
                          ; the following routine (after the JR C) if the
                          ; movement takes the servant/cursor position beyond
                          ; the left hand side of the play area (< 12) or past
                          ; the right hand side (> 228).
  JR C,L59736_1           ; If the servant/cursor is still within screen
                          ; limits, skip the next few instructions.
; Servant/cursor position is at the left or right border or the screen.
  LD A,0                  ; Set movement speed to zero to stop dead
  LD (60161),A            ;
  LD A,(60160)            ; Get horizontal pixel position
  CP 128                  ; Check which half of the screen it is
  JR C,L59736_0           ;
  LD C,228                ; If right hand side, set horizontal pixel position
  JR L59736_1             ; to 228
L59736_0:
  LD C,12                 ; If left hand side, set horizontal pixel position to
                          ; 12
; Store adjusted horizontal pixel position:
L59736_1:
  LD A,C                  ; Get calculated horizontal pixel position
  LD (60160),A            ; ...and store

; Calculate change to servant/cursor icon vertical screen position
;
; This routine calculates the vertical direction and speed of the servant/spell
; cursor icon, and adds/subtracts it from the sprite's vertical pixel position.
L59783:
  LD A,(60162)            ; Get sprite vertical movement speed
  LD C,A                  ;
  LD A,(60158)            ; Get up/down sprite control value (determine whether
                          ; the sprite is moving and in which direction)
  CALL L57276             ; Calculate the new sprite speed/position offset
                          ; based on direction/speed (returned in H register)
  LD A,H                  ; Retrieve calculated offset from H register...
  LD (60162),A            ; ...and store
  LD A,(60159)            ; Get the sprite's current vertical screen position
  LD C,A                  ; Temp store in C register
  ADD A,H                 ; Add (or subtract) the offset calculated earlier
; Check top of playing area boundary
  CP 224                  ; If new position is < 8 or a negative value, upwards
  JR NC,L59783_0          ; movement will have taken the graphic past the top
  CP 8                    ; border of the playing area
  JR NC,L59783_1          ;
L59783_0:
  LD A,0                  ; ...If so, reset movement speed to zero...
  LD (60162),A            ;
  LD A,8                  ; ...And vertical pixel position to 8, two pixels
                          ; below the top of the playing area (top of playing
                          ; area is zero, but the servant and cursor icon both
                          ; have a -6 vertical pixel offset).
L59783_1:
  LD (60159),A            ; Store the new (or reset) vertical pixel position
; Check bottom of playing area boundary
  CP 120                  ; Check if vertical sprite position is greater than
  JR C,L59783_2           ; 120 pixels from top of playing area
  LD A,0                  ; If so, set vertical movement speed to zero.
                          ; HTML[<br/>]No further action is required at this
                          ; point because the spell will be cancelled in the
                          ; following routine.
  LD (60162),A
L59783_2:
  LD A,0
  LD (60116),A            ; High byte of screen position (0 = current viewport,
                          ; no offset)
; Erase the graphic at the old position and draw it at its new one
  LD (60111),A            ; ...Set draw/erase flag to ERASE
  LD HL,(L60564)          ; Get the graphic address pointer ready to ERASE the
                          ; graphic
  CALL L56216             ; Run screen boundary checks and erase the
                          ; servant/icon graphic
  LD A,(60160)            ; Copy the (new) horizontal pixel position into store
  LD (60115),A            ;
  LD A,(60159)            ; ...and also the vertical pixel position
  LD (60114),A            ;
  LD A,1                  ; Set draw/erase flag to DRAW
  LD (60111),A            ;
  LD HL,(60241)           ; Copy graphic address pointer to (table at L38851)
  LD (L60564),HL          ; into store
  CALL L56216             ; Run screen boundary checks and draw the
                          ; servant/icon graphic in its new position

; Check if FIRE pressed when servant or controllable spell cursor is on screen
;
; For active cursor-type spells such as SERVANT, OPEN, REVEAL etc., pressing
; FIRE cancels the spell.
;
; The exceptions are the FLAME and ELECTRIC spells, which keep the aiming
; cursor on-screen, allowing for multiple missiles to be fired without having
; to activate the spell from the scroll list again.
L59869:
  LD A,(60117)            ; Flag indicating whether (any part of) graphic is
                          ; visible on screen
  CP 0                    ; 0 = not visible, 1 = visible
  JP Z,L59869_1           ; If not visible, the servant/eye cursor has moved
                          ; off the bottom of the playing area. Doing this
                          ; cancels the spell, and in the case of the
                          ; repeat-firing FLAME and ELECTRIC spells, it's the
                          ; ONLY way to cancel the spell. Jump to L59869_1 for
                          ; deactivation.
  LD A,(60210)            ; Check FIRE key controls
  CP 0                    ;
  JP Z,L59956_6           ; If not pressed, jump straight to RET
; FIRE control key pressed.
;
; This routine determines what action needs to be taken when FIRE is pressed
; when the cursor icon/servant is active:
  LD A,(60362)            ; This byte's value holds the action to take when a
                          ; servant/spell icon spell is cast
  CP 0                    ; For non-cursor spells, this byte is zero
  JR Z,L59869_0           ; ...so make sure it's not one of these
  LD C,A                  ; Temp store of byte's 'action-value' in C register
  AND 128                 ; Check bit 7, which is set for missile type spells
  JR Z,L59869_0           ; (MISSILE, FIREBALL etc.)
  LD A,C                  ; If it's set, retrieve the original byte...
  AND 127                 ; Filter out bit 7
  LD (60568),A            ; ...and store the remaining value
L59869_0:
  LD A,(60359)            ; Check the spell type
  CP 3                    ; 3 = ELECTRIC and FLAME spells
  JR NZ,L59869_1          ;
; For the FLAME and ELECTRIC spells, the aiming cursor remains on screen after
; firing. So the energy cost of the spell is deducted from Maroc's energy bar
; each time a bolt is fired, rather than just at the point of casting.
  LD A,(60358)            ; First get the energy cost of the spell...
  CALL L58316             ; ...and reduce Maroc's energy accordingly.
  RET                     ; ...In this case, there's no more action to be taken
                          ; re: the spell aiming cursor icon
; For other spells, cancel the spell and get rid of the controllable sprite
; (flashing eye cursor, or servant):
L59869_1:
  LD A,0                  ; Set draw/erase flag to ERASE
  LD (60111),A            ;
  LD (60140),A            ; Also reset the temp store scroll spell number
                          ; pointer (I think)
  LD HL,(L60564)          ; Retrieve the graphic address pointer to the
                          ; servant/cursor icon graphic
  CALL L56216             ; ...and erase the graphic from screen.
  JR L59956_4             ; Jump to the routine that resets the flashing
                          ; attributes indicating an active spell, at the top
                          ; right of the scroll

; Spell selected that is the same as the active 'effect' spell (e.g. SHIELD,
; UNSEEN)
;
; Used by the routines at L58945 and L59389.
L59933:
  LD A,56                 ; This value (56) indicates the spell selected is an
  LD (L60129),A           ; ongoing 'effect' spell
  CALL L56668             ; Start printing the selected spell message text
; After the initial spell selection, player controls are limited to either (a)
; UP/DOWN to cancel the spell casting and return to the spell menu, or (b) FIRE
; again to confirm & cast the spell
;
; Check if UP/DOWN pressed:
  LD A,(60158)            ; Check up/down control value
  CP 0                    ; If the player presses UP or DOWN, spell casting is
  JR NZ,L59956_4          ; cancelled. Remove the FLASHing attributes in the
                          ; top right of scroll, clear the scroll and and
                          ; re-print the spell list
; Check if FIRE pressed:
  LD A,(60210)            ; Check if FIRE pressed
  CP 0                    ; If NOT pressed, jump straight to the RET statement
  JP Z,L59956_6           ; to continue the game. Otherwise continue to the
                          ; next routine that deactivates the effect.

; Deactivate the currently active effect spell
;
; The player has cast the same spell as the current active ongoing effect spell
; - this deactivates the effect.
;
; Clear the active spell name from small scroll in bottom right of screen:
L59956:
  LD L,249                ; Low byte of screen display address for left-hand
                          ; character in scroll
  LD A,7                  ; 7 characters to clear
L59956_0:
  LD B,8                  ; 8 pixel lines in each character
  LD H,80                 ; High byte of screen display address
L59956_1:
  LD (HL),0               ; Clear display byte
  INC H                   ; Move down one pixel
  DJNZ L59956_1           ; Repeat x 8 pixels
  INC L                   ; Move right one character square
  DEC A                   ; Repeat for 7 character squares
  JR NZ,L59956_0          ;
; Check which spell was deactivated, and reset the relevant effect accordingly:
  LD A,(60137)            ; Check which effect spell was activated - spell
                          ; number (0-27) in list at L28156
  CP 2                    ; SHIELD spell
  JR Z,L59956_2           ;
  CP 11                   ; PROTECT spell
  JR Z,L59956_2           ;
  CP 18                   ; DEFENCE spell
  LD A,0                  ;
  JR NZ,L59956_3          ;
L59956_2:
  LD A,255                ; SHIELD, PROTECT and DEFENCE also have a graphic
                          ; shimmering barrier effect, which will need to be
                          ; deactivated/erased. Set flag (255) to indicate that
                          ; any current on-screen graphics will get erased.
; For 'effect' spells, the number of charges for the spell is reduced when the
; spell is deactivated, otherwise the final charge would make the effect
; permanent.
L59956_3:
  LD (60137),A            ; Set active 'effect' spell to 0, or 255 if SHIELD,
  LD A,0                  ; PROTECT or DEFENCE.
  LD (60373),A            ; Spell no longer active, so set the ongoing energy
                          ; drain (e.g. SHIELD) or heal (e.g. CHALICE) byte
                          ; value to zero
  LD A,(60360)            ; Check number of charges for spell
  CP 255                  ; If unlimited charges, no need to decrease
  JR Z,L59956_4           ;
; Decrease number of spell charges
  DEC A                   ; Decrement spell charges counter
  LD (60360),A            ; ..and store new value.
  CP 0                    ; Out of spell charges?
  JR NZ,L59956_4          ;
  LD (L60357),A           ; ...If so, set the spell's acquired/owned flag to 0,
                          ; so that the spell gets removed from Maroc's spell
                          ; list
; Sets the attributes of a 2x2 square in the top right of the scroll (that may
; have been flashing), and a line of 16 characters of the bottom of the scroll,
; to INK 0 (black) PAPER 6 (yellow).
L59956_4:
  LD HL,23127             ; Top right of scroll
  LD (HL),48              ; Set to INK 0, PAPER 6
  INC HL                  ; Adjacent square
  LD (HL),48              ; Ditto
  LD HL,23159             ; Same for the 2 squares below
  LD (HL),48              ;
  INC HL                  ;
  LD (HL),48              ;
; It's not clear why the bottom row of the scroll also needs setting - it may
; be that originally active effect spell names appeared here, rather than over
; on the bottom right.
  LD HL,23239             ; Bottom left of scroll
  LD B,16                 ; 16 characters along the bottom of the scroll
L59956_5:
  LD (HL),48              ; Set to INK 0, PAPER 6
  INC HL                  ;
  DJNZ L59956_5           ; Continue for rest of the row
; Copy current spell data (at L60357) into corresponding spell data at L28156
  LD HL,L60357            ; Spell data buffer
  LD DE,(60135)           ; Get spell data address pointer to spell in list at
                          ; L28156
  LD BC,16                ; 16 bytes of data to copy
  LDIR                    ;
  LD A,0                  ; Set spell selection status byte to 0
  LD (L60129),A           ;
  CALL L57081             ; Clear all of the scroll text
; This entry point is used by the routines at L59262, L59869 and L59933.
L59956_6:
  RET

; Data buffer - scroll text and icon data
L60065:
  DEFW 0                  ; Address pointer of message text (1-37) to print,
                          ; starting from the texts at L29042
  DEFB 0                  ; Number of text characters, or column characters, to
                          ; print (checked at L58106_4)
  DEFW 0                  ; Screen display address to print at (used in various
                          ; routines such as text routines at L58106, L58064,
                          ; spell charge icons at L59130_0, printing rank on
                          ; scroll at L58599)
  DEFB 0                  ; Decrementing counter affecting pitch of sound
                          ; effect as player holds a key to scroll through the
                          ; spells list. Reset to 5 at 59027 if no keys pressed
                          ; while in spell menu

; Data buffer - attributes/colours
L60071:
  DEFB 0                  ; Maroc's colour - INK 7, PAPER 0, BRIGHT 1
                          ; (attribute value = 71) - set at new game
                          ; initialization at 49393 and applied in the routine
                          ; at L57888.
  DEFB 0                  ; Bits 0-3 of room creature/object's attribute byte
                          ; (from 60299 for item, L60325 for creature).Bits 0-2
                          ; contain its INK colour. If bit 3 (8) is set, it
                          ; means the object is flashing (changing colour)
  DEFB 0                  ; Room scenery colour (single attribute value) for
                          ; the current room's walls, doors, other scenery etc.
                          ; Set in routine at L57863. As room backgrounds can
                          ; vary, creature/item INK colour (stored in the
                          ; previous byte) is combined with the room background
                          ; PAPER colour (L53885_2).

; Data buffer - game data (various)
L60074:
  DEFB 0                  ; Game cycle timer. Multi use throughout the program,
                          ; e.g.:
                          ; * to affect the delay before creatures follow Maroc
                          ;   into a room (L51420)
                          ; * to slow down animation rate slightly (L58166)
                          ; * to decide room item/creature movement (L52136)
                          ; * to create intervals between creature footstep
                          ;   sounds (L52616)
  DEFB 0                  ; Maroc's sprite's horizontal facing/movement
                          ; direction, set when Maroc enters a new room Set to
                          ; 2 (facing left) or 254(-2) (facing right) depending
                          ; on check at 50032
  DEFB 0                  ; Maroc's sprite's vertical facing/movement
                          ; direction, set when Maroc enters a new room Set to
                          ; 1 at start of main routine at 50885 if Maroc is in
                          ; a tunnel - this sets Maroc facing upwards Set to
                          ; 254(-2) (facing downwards) at 50032 if Maroc is
                          ; entering through a door at the top of the room (on
                          ; the back wall)
  DEFW 0                  ; Pointer to room item event data table at 32691
                          ; Initialized/copied from 60268 at routine at 49465
  DEFB 0                  ; Door graphic's horizontal pixel graphic offset
                          ; value copied here in the door handling routine at
                          ; L51611_0
  DEFB 0                  ; Room number. Copied from 60087 at 49044 when new
                          ; game loadedSet to 1 to return to start room when
                          ; Maroc's energy = 0 at 55623 255 = Room number needs
                          ; calculating from the door Maroc has just gone
                          ; through (L26512) Set to 255 at end of a tunnel at
                          ; 53646 and at 51837 when Maroc leaves a room (value
                          ; checked at L55818_0)
  DEFB 0                  ; Bytes 0-3 of the pre-graphics byte (see Graphic
                          ; properties) Indicates animation frames - i.e. the
                          ; number of addresses to step over from the base
                          ; address in the table at L38851 for the required
                          ; frame
  DEFW 0                  ; Graphics address pointer for the graphics address
                          ; pointer table at L38851.
  DEFB 1                  ; The connecting room set number (from L26512) Used
                          ; in routine that checks for pursuing creatures at
                          ; 51458 and the tunnel setup at L50613
  DEFW 0                  ; Address pointer for the connecting door set number
                          ; at L26512
  DEFB 1                  ; Room number. Starting room is #1 Identifies the
                          ; room data set containing the room size and scenery
                          ; data at L25001
  DEFB 0                  ; - (unused)
  DEFB 60                 ; - (unused)
  DEFB 0                  ; - (unused)
  DEFB 64                 ; - (unused)
  DEFW 0                  ; (Copy of) pointer to data in room item data tables
                          ; stored at 31744.
  DEFW 0                  ; Address pointer buffer for the above - (Copy of)
                          ; pointer to room item data at 31744 Also used for
                          ; foreground scenery data at 32513 in routine at
                          ; 54532
  DEFB 29                 ; Maroc's horizontal (X-axis) screen position. This
                          ; value is calculated from left of screen (in border)
                          ; in half-character (4 pixel) squares, so the value
                          ; of 29 is halfway into character column 15
  DEFB 74                 ; Maroc's vertical (Y-axis) pixel position. This
                          ; value is calculated from the top of the play area,
                          ; starting immediately below the 2 character top
                          ; decorative border (74 pixels down from here, or 90
                          ; pixels from the very top of the screen).
  DEFW 0                  ; Maroc's sprite frame - graphic address pointer
                          ; (from L38851)
  DEFW 0                  ; Maroc's shadow - graphic address pointer (39095)
  DEFB 0                  ; Flag indicating whether the fire button (flag at
                          ; 60210) is held down Used as a control to ensure the
                          ; player releases the fire button before pressing it
                          ; again Used/checked in routine at 50984
  DEFB 0                  ; General all-purpose counter byte:
                          ; * Set to 128 as a sound effect loop counter during
                          ;   lightning effect in routine at L49274
                          ; * Graphic tile counter (number of tiles the current
                          ;   graphic consists of) in the 'mirror graphics'
                          ;   routine at 57642
                          ; * Scroll line text counter (0-5) for printing the
                          ;   spells, checked at L57139_7
                          ; * Number of spell 'charge' icons to print on the
                          ;   scroll at L59130_0
                          ; * Set to 14 to clear 14 character rows of the
                          ;   playing area at L57947
                          ; * Text message number for Maroc's rank (see Trivia:
                          ;   Maroc's rank) calculated in the routine at 58720
  DEFB 0                  ; Counter for the number of times Maroc has died
                          ; Affects Maroc's rank (see Trivia: Maroc's rank)
                          ; which is calculated in the routine at L58599.
  DEFB 0                  ; Level text number (L29042), calculated using the
                          ; room number in the lookup table at L50852 Value
                          ; also used at L54865 to identify the warlock number
                          ; (L27772) for this level
  DEFB 0                  ; - (unused)

; Data buffer - graphic working data
;
; Graphic working data buffer - most used in graphic draw/erase routine at
; L56216
L60107:
  DEFB 0                  ; Graphic's horizontal screen position, in pixels -
                          ; copied to 60115 at 53948
  DEFB 0                  ; High byte for the item's horizontal screen position
                          ; Acts as an overflow/precision value for large/small
                          ; values when this item's horizontal room position is
                          ; calculated at L51255_0
  DEFW 0                  ; Graphics address pointer (table at L38851)
  DEFB 0                  ; Multi use flag/counter:Draw/erase flag (0 = Erase,
                          ; 1 = Draw), used in draw routine at 56378 Used as
                          ; lightning flash counter (6) for intro sequence at
                          ; lightning flash routine at L49274.
  DEFB 0                  ; Number of tiles that make up the sprite/graphic to
                          ; draw
  DEFB 0                  ; Number of bytes in the graphic tile to draw
  DEFB 0                  ; Store for graphic's vertical position, in pixels,
                          ; from top of playing area
  DEFB 0                  ; Store for graphic's horizontal position, in pixels,
                          ; calculated from second character column on left of
                          ; screen (the right half of the left decorative
                          ; border)
  DEFB 0                  ; High byte indicating the screen for the graphic's
                          ; horizontal pixel position above For objects in the
                          ; room and visible on screen, this is 0 For objects
                          ; off-screen, 1 = right of the current viewport, 255
                          ; = to the left Calculated at 51222 when setting up
                          ; objects
  DEFB 0                  ; Flag indicating whether (any part of) graphic is
                          ; visible on screen
                          ; * Set to 0 at the beginning of the graphic drawing
                          ;   routine at 56222
                          ; * Set to 1 in the same routine if any part of
                          ;   graphic is drawn (56311)
                          ; * Appended as bit 0 to the graphic properties byte
                          ;   (60328) after drawing (or not drawing) graphic
                          ;   attributes at L53885_0
  DEFB 0                  ; Byte copied from 60235 at 53954 Indicates whether
                          ; room item is in a standard room or tunnel Stored as
                          ; byte 9 of each room item data set at 31744
  DEFB 0                  ; - (unused)
  DEFB 0                  ; - (unused)
  DEFB 0                  ; - (unused)
  DEFB 0                  ; - (unused)
  DEFB 0                  ; - (unused)
  DEFB 0                  ; - (unused)
  DEFB 0                  ; - (unused)
  DEFW 0                  ; Screen display address position for printing spell
                          ; list/pointer arrow on scroll (L57139)
  DEFB 0                  ; Maroc's energy - 0-255 Set to 128 (half the energy
                          ; bar) at new game start (49358) Each 16 points of
                          ; energy corresponds to one character of the energy
                          ; bar graphic (L44787)

; Data buffer - spell data
L60129:
  DEFB 0                  ; Spell selection status byte. Checked at 58955. Set
                          ; to:
                          ; * 0 at new game data initialization (49371)
                          ; * 8 after spell names printed on scroll (58994)
                          ; * 24 after energy bar printed (59257)
                          ; * 32 when MOVE spell selected (59397)
                          ; * 48 when SERVANT/other cursor spell cast (59466)
                          ; * 56 when active 'effect' spell deactivated
                          ;   (L59933)
  DEFB 0                  ; Store for spell counter used in checking spells
                          ; collected at L59033_2
  DEFW 0                  ; Store for address pointer to the start and/or
                          ; current spell list text at L28156 (copied from
                          ; 60261 at 49409) Used to determine spells to print
                          ; when the player presses up or down in the spell
                          ; menu
  DEFB 0                  ; Temp store for spell counter byte at 60130, copied
                          ; at start of routine at L57139
  DEFB 0                  ; Spell number counter (for spell list at L28604)
                          ; Used to print relevnat spell message on scroll at
                          ; L59219 Set at 57245 - spell number 3 on the scroll
                          ; (pointed at by the scroll arrow)
  DEFB 0,0                ; Address pointer for selected/highlighted spell
                          ; (L28156). The 16 bytes of spell data are copied
                          ; to/from a buffer at L60357
  DEFB 0                  ; Currently active 'effect' spell (e.g. UNSEEN,
                          ; SHIELD) - from 0-27 (0 = no effect spell) from
                          ; spell list at L28156 Set to 255 at 59973 if
                          ; deactivated effect spell is SHIELD, PROTECT or
                          ; DEFENCE - this tells the routine at 54461 to erase
                          ; any on screen 'barrier' graphics
  DEFW 0                  ; Address pointer for active spell message text
                          ; (L28604) Also used for level text (L29042), as only
                          ; one or the other appears on the scroll at any one
                          ; time
  DEFB 0                  ; Temp store for spell number pointer (60134) Also
                          ; used for cast spell number, checked at L55283
  DEFB 0                  ; - (unused)
  DEFB 0                  ; - (unused)

; Data buffer - general (mainly room/scenery related)
L60143:
  DEFW 0                  ; Loaded with pointer to reserved data set at 32819
                          ; Copied from 60255 at routine at 49473
  DEFB 0                  ; Count of number of a particular creature in current
                          ; room.Calculated in creature setup routine at L50272
  DEFB 0                  ; Flag indicating if a warlock, or a demon (in the
                          ; High Temple of Chaos) has been generated in a room
                          ; (1 = present/generated, 0 = not generated)
  DEFW 0                  ; Sprite graphic address pointer to 'dummy' graphic
                          ; (39097) Set up at start of game at 49187
  DEFB 0                  ; Door properties byte (60238), stored in byte 3 of
                          ; connecting door sets at L26512 in routine at L50613
                          ; When Maroc exits a room, bit 7 (128) of this byte
                          ; is set, indicating the door he entered from
  DEFB 0                  ; Low byte for vertical room position - main position
                          ; stored in next (high) byte
  DEFB 0                  ; Vertical room position in pixels (high byte).
                          ; Increased as Maroc moves up (screen scenery moves
                          ; down). Reduced as Maroc moves down (screen scenery
                          ; moves up). Copied from 60234 at L53870. Set to 0
                          ; (default room position) at new game data
                          ; initialization at L49415.
  DEFB 0                  ; Low byte for horizontal room position. Used as a
                          ; precision/overflow byte (main byte stored in the
                          ; following high byte) From 60231, copied here in
                          ; routine at L53870
  DEFB 0                  ; Room/screen 'viewport' horizontal position, in half
                          ; character/4-pixel steps
  DEFB 0                  ; The vertical position of the left back wall/floor
                          ; vertical connector section at L53601, in relation
                          ; to the current room's viewport
  DEFB 0                  ; The LEFT (vertical) corner graphic's horizontal
                          ; position, in half character squares (4 pixels) in
                          ; relation to the current room's viewport. Stored at
                          ; L53601 and used for MOVE spell boundary checks at
                          ; L57401_1
  DEFB 0                  ; The RIGHT (vertical) corner graphic's horizontal
                          ; position, in half character squares (4 pixels) in
                          ; relation to the current room's viewport. Stored at
                          ; L53601 and checked in MOVE spell boundary checks at
                          ; L57401_3. Calculated in relation to the left
                          ; connector section above, based on the room size
                          ; byte

; Data buffer - Maroc/servant/spell cursor controls and position data
L60157:
  DEFB 0                  ; Store for control left/right calculated value of 0,
                          ; 1 (right) or -1 (255) (left), plus the value stored
                          ; at 60075 which is set when Maroc enters a new room
  DEFB 0                  ; Store for control up/down calculated value of 0, 1
                          ; (up) or -1 (255) (down), plus the value stored at
                          ; 60076 which is set when Maroc enters a new room
  DEFB 0                  ; Vertical (Y) position (in pixels) for controllable
                          ; icon/servant graphic Calculated from top of playing
                          ; area in pixels Set to 40 (just above Maroc's head)
                          ; in routine at 59456 after servant or other 'cursor
                          ; control' spell cast
  DEFB 0                  ; Horizontal (X) position (in pixels) for
                          ; controllable icon/servant graphic  Calculated from
                          ; left of playing area in pixels Set to 112 (centre
                          ; of screen) in routine at 59461 after servant or
                          ; other 'cursor control' spell cast
  DEFB 0                  ; Servant/controllable cursor's horizontal movement
                          ; speed. Negative values = left, positive = right
  DEFB 0                  ; Servant/controllable cursor's vertical movement
                          ; speed. Negative values = up, positive = down
  DEFB 0                  ; Maroc's direction/rotation - see Trivia: Maroc's
                          ; sprite rotational movement
                          ; +----------------+-------+
                          ; | Direction      | Value |
                          ; +----------------+-------+
                          ; | DOWN           | 0     |
                          ; | DOWN and LEFT  | 32    |
                          ; | LEFT           | 64    |
                          ; | UP and LEFT    | 96    |
                          ; | UP             | 128   |
                          ; | UP and RIGHT   | 160   |
                          ; | RIGHT          | 192   |
                          ; | DOWN and RIGHT | 224   |
                          ; +----------------+-------+
                          ;  Repeatedly adding 32 causes Maroc to rotate in a
                          ; clockwise direction, like in the animated routine
                          ; when he runs out of energy at L58476
  DEFB 0                  ; Maroc's horizontal movement speed Negative values =
                          ; right, positive = left, e.g. 224 = full speed
                          ; right, 32 = full speed left Graphic position is
                          ; adjusted by speed/4 pixels - e.g. a speed of 32/-32
                          ; would result in a movement step of 8/-8 pixels
  DEFB 0                  ; Maroc's vertical movement speed. Negative values =
                          ; down, positive = up, e.g. 224 = full speed down, 32
                          ; = full speed up Graphic position is adjusted by
                          ; speed/4 pixels - e.g. a speed of 32/-32 would
                          ; result in a movement step of 8/-8 pixels

; Keyboard/joystick control method and port checking values
L60166:
  DEFW 0                  ; Address pointer to one of the list of input values
                          ; below, depending on control option selected by the
                          ; player.
; KEMPSTON JOYSTICK control input values
  DEFB 8,4,2,1,16         ; Up, down, left, right, fire
  DEFB 0                  ; End-of-data byte to indicate end of control checks
; KEYBOARD controls - ports to read (up, down, left, right, fire) and the
; values used as a mask for checking which keys are pressed
  DEFW 65022              ; Keyboard port input address for keys A to G
  DEFB %11100000          ; Input value mask.Bits 0-4 not set, as all keys (A,
                          ; S, D, F, G) can be used to move UP
  DEFW 65278              ; Keyboard port input address for keys CAPS SHIFT to
                          ; V
  DEFB %11100000          ; Input value mask.Bits 0-4 not set, as all keys
                          ; (CAPS, Z, X, C, V) can be used to move DOWN
  DEFW 32766              ; Keyboard port input address for keys SPACE to B
  DEFB %11100111          ; Input value mask.Bits 3-4 not set, for keys B and
                          ; N, which can both be used to move LEFT
  DEFW 32766              ; Keyboard port input address for keys SPACE to B
  DEFB %11111000          ; Input value mask.Bits 0-2 not set, for keys M,
                          ; SYMBOL SHIFT, SPACE, which can all be used to move
                          ; RIGHT
  DEFW 49150              ; Keyboard port input address for keys ENTER to H
  DEFB %11100000          ; Input value mask.Bits 0-4 not set, as all keys (H,
                          ; J, K, L, ENTER) can be used to FIRE
  DEFB 0                  ; End-of-data byte to indicate end of control checks
; AGF/CURSOR JOYSTICK controls (up, down, left, right, fire)
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11110111          ; Input value mask.Bit 3 not set, to check key 7 for
                          ; UP
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11101111          ; Input value mask.Bit 4 not set, to check key 6 for
                          ; DOWN
  DEFW 63486              ; Keyboard port input address for number keys 1-5
  DEFB %11101111          ; Input value mask.Bit 4 not set, to check key 5 for
                          ; LEFT
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11111011          ; Input value mask.Bit 2 not set, to check key 8 for
                          ; RIGHT
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11111110          ; Input value mask.Bit 0 not set, to check key 0 for
                          ; FIRE
  DEFB 0                  ; End-of-data byte to indicate end of control checks
; Store for up, down, left, right, fire for selected control method, indicating
; which controls are pressed (1 = Pressed, 0 = Not pressed).
  DEFB 0                  ; UP
  DEFB 0                  ; DOWN
  DEFB 0                  ; LEFT
  DEFB 0                  ; RIGHT
  DEFB 0                  ; FIRE
; SINCLAIR JOYSTICK (up, down, left, right, fire)
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11111101          ; Input value mask.Bit 1 not set, to check key 9 for
                          ; UP
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11111011          ; Input value mask.Bit 2 not set, to check key 8 for
                          ; DOWN
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11101111          ; Input value mask.Bit 4 not set, to check key 6 for
                          ; LEFT
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11110111          ; Input value mask.Bit 3 not set, to check key 7 for
                          ; RIGHT
  DEFW 61438              ; Keyboard port input address for number keys 6-0
  DEFB %11111110          ; Input value mask.Bit 0 not set, to check key 0 for
                          ; FIRE
  DEFB 0                  ; End-of-data byte to indicate end of control checks

; Data buffer - for each room object, creature, scenery item
;
; This 16 byte working buffer handles each room item data set, stored at 31744.
; Bytes are copied back and forth between store and buffer.
L60227:
  DEFB 0                  ; Type of graphic to draw - checked & dealt with at
                          ; routine at L51359:1 = Back wall bricks/scenery,
                          ; door frames, and wall-floor connector graphics.
                          ; Also servant and flashing eye cursor 2 = Door 3 =
                          ; Creature 4 = Interactable objects (e.g. key, chest,
                          ; scroll) 5 = Missile fired by creature/warlock 6 =
                          ; Corner-wall section (left)7 = Corner-wall section
                          ; (right)8 = Missile fired by Maroc 14 = Tunnel item
                          ; - boundary wall, spider or bat 15 = Viewport
                          ; position for tunnel rooms 32 = Viewport position
                          ; for standard rooms
  DEFW 0                  ; Multiple use:
                          ; * Tunnel number offset (32) stored at 50727
                          ; * Address pointer to data sets at L26512 (plus
                          ;   offset) stored in routine at L49993_2
                          ; * Address pointer to data set for a room object
                          ;   (L29551) in the current room (checked at L56959)
                          ; * Pointer to warlock & creature data sets at L27772
                          ;   and 27828
                          ; * For missiles, address pointer to missile table at
                          ;   L27868
  DEFB 0                  ; Multiple uses: 0 = Back wall door 1 = Right wall
                          ; door 2 = Left wall door Connecting door set number
                          ; (from L26512) Tunnel boundary wall type, 1 (right)
                          ; or 2 (left) - L54994_1 Tunnel number 0-31 (room
                          ; number minus 224) stored at 50731.Data set number
                          ; for object in room interactable objects table at
                          ; L29551 Creature type setup in routine at 52630 -
                          ; warlock & creature data at L27772:
                          ; * 1-7 = Warlock
                          ; * 8 = Guardian of Chaos
                          ; * 9 = Goblin warrior
                          ; * 10 = Goblin missile thrower
                          ; * 11 = Wraith
                          ; * 12 = Demon
                          ; * 4 = Spider (creature generation in tunnel at
                          ;   55128)
                          ; * 8 = Bat (creature generation in tunnel at 55128)
  DEFB 0                  ; Overflow/precision byte used when calculating the
                          ; item's horizontal room position ('true' position is
                          ; the next - high - byte which follows this one) Acts
                          ; as a fraction/overflow value for large/small values
                          ; when this item's horizontal room position is
                          ; calculated at L51255_0 Second byte of foreground
                          ; scenery set (at 32513) stored here in routine at
                          ; 54545
  DEFB 0                  ; Graphic horizontal position within current room, in
                          ; half character (4-pixel) steps
  DEFB 0                  ; Overflow/precision byte used when calculating the
                          ; item's vertical room position ('true' position is
                          ; the next - high - byte which follows this one)
  DEFB 0                  ; Graphic vertical position within current room, in
                          ; pixels, from top of room playing area
  DEFB 0                  ; 64 - item in standard room 254 - spider/bat in
                          ; tunnel room at 55128 255 - other item in tunnel
                          ; room (L50663)
  DEFB 0                  ; Item's horizontal movement speed For room scenery
                          ; items, calculated at L59630 using the reverse (NEG)
                          ; of Maroc's horizontal movement speed (60164) > 128
                          ; (negative) = left, < 128 (positive) = right
  DEFB 0                  ; Item's vertical movement speed For room scenery
                          ; items, calculated at L59630 using the reverse (NEG)
                          ; of Maroc's vertical movement speed (60165) > 128
                          ; (negative) = up, < 128 (positive) = down
  DEFB 0                  ; Item properties byte:
                          ; * ALL - Bit 0 (1) set indicates if any part of
                          ;   graphic is visible on-screen (1 = visible, 0 =
                          ;   not visible)
                          ; * ITEMS - Bit 1 (2) set indicates an item is hidden
                          ;   (e.g. inside a chest)
                          ; * ALL - Bit 2 (4) set if this item needs erasing
                          ;   on-screen, before being re-drawn (e.g. item has
                          ;   changed frame/moved)
                          ; * ITEMS - Bit 3 (8) indicates (when set) that an
                          ;   item is flying/falling - e.g. an item
                          ;   thrown/dropped by the servant (see L52059)
                          ; * ITEMS - Bit 4 (16) set = item currently carried
                          ;   by servant
                          ; * ITEMS - Bit 6 (64) = item is portable
                          ; * DOORS - Bit 3 (8) set (1) if door is open, reset
                          ;   (0) if closed
                          ; * DOORS - Bit 5 (32) set when a door
                          ;   opening/closing is triggered
                          ; * DOORS - Bit 6 (64) set if door is now
                          ;   opening/closing
                          ; * DOORS - Bit 7 (128) set - Maroc has just gone
                          ;   through a doorway
                          ; * MISSILES - Bits 5-8 - length of missile's
                          ;   existence on-screen before disappearing
                          ; * CREATURES - Bit 5 (32) - creature is
                          ;   disintegrating, will need removing post-animation
                          ; * WARLOCKS - Bit 6 (64) trigger warlock
                          ;   disappearance post-materialization animation
                          ;   (52873) - successful object trade
                          ; * WARLOCKS - Bit 7 (128) trigger warlock's
                          ;   appearance, post-materialization animation
  DEFB 0                  ; Pre-graphics data byte (see Graphic properties):
                          ; * Bits 0-3 - graphics frame
                          ; * Bit 5 is set - graphic is 'flippable'
                          ; * Bit 6 is set = graphic has a left/right facing
                          ;   direction (e.g. mouse, goblins)
                          ; * Bit 7 is set = graphic is animated
  DEFB 0                  ; Graphic address frame offset (>1 for mirrored
                          ; graphics frames) Used at L57538 to calculate the
                          ; graphics address pointer offset for the graphic in
                          ; the table at L38851 Offset address = [(n-1)*2] -
                          ; e.g. a byte value of 1 = no offset, byte value of 4
                          ; = offset of 6 bytes, or 3 x 2-byte pointer
                          ; addresses Bit 3 (8) - used for creatures with
                          ; left/right facing graphics, to indicate if they are
                          ; facing right (set) or left (not set) - see 58203
  DEFW 0                  ; Graphic address pointer (in table at L38851),
                          ; including any offset for the correct graphic frame

; Data buffer - music and sound effects
L60243:
  DEFB 0                  ; Temporary store for the speaker/sound byte used in
                          ; the music playing routine at L58806.
  DEFW 0                  ; Store for note data pointer, for music playing
                          ; routine at L58806.
  DEFB 0                  ; Counter/length/frequency used for the generic sound
                          ; effect routine at L49274
  DEFW 0                  ; Store to preserve HL register pair, for sound
                          ; playing routine at L57815.
  DEFW 0                  ; Address pointer to the ROM to generate semi-random
                          ; byte values to play generic sound effects at
                          ; L57815. Reset to 0 at the start of the game loop at
                          ; 51156

; Data buffer - general address and spell pointers
L60251:
  DEFW 0                  ; Address pointer to game level text at L29042, e.g.
                          ; 'Gatehouse Level'
  DEFW 0                  ; Copy of data pointer at 60257 (pointer to
                          ; flipped/mirrored graphics at 32851)
  DEFW 0                  ; Pointer to 32 bytes of (unused) reserved game data
                          ; at 32819
  DEFW 0                  ; Pointer to flipped/mirrored graphics at 32851
  DEFW 0                  ; Address pointer to the spell text messages at
                          ; L28604
  DEFW 0                  ; Address pointer to the start of the spell list at
                          ; L28156
  DEFW 0                  ; Address pointer for the start of spell text message
                          ; list at L28604
  DEFB 2                  ; Total number of spells (27)
  DEFW 0                  ; Address pointer to graphics address table at L38851
  DEFW 0                  ; Pointer to room item event data sets at 32691
  DEFW 0                  ; - (unused)
  DEFW 0                  ; Pointer to the room's foreground scenery data sets
                          ; at 32513
  DEFW 0                  ; Store for address pointer to next room item data
                          ; set at 31744

; Data buffer - room co-ordinate data and pointers
L60276:
  DEFB 0                  ; Maroc's (default) vertical (entry) pixel position
                          ; when he moves to a new room
  DEFB 0                  ; Maroc's horizontal (entry) position when he moves
                          ; to a new room, in half-character/4-pixel steps
  DEFB 0                  ; Maroc's vertical (entry) position when he moves to
                          ; a new room, in pixels, calculated based on the byte
                          ; stored at L60276
  DEFB 0                  ; Offset for scenery graphics address pointers for
                          ; 'brick' or 'cavern' type levels (table at L38851)
                          ; * Offset = 0 for brick level scenery (room number
                          ;   <84)
                          ; * Offset = 12 for 'cavern' level scenery (room
                          ;   number >=84)
                          ; * Offset = 0 for brick level foreground scenery
                          ;   items (room number <83)
                          ; * Offset = 8 for cavern level foreground scenery
                          ;   items (room number >=83)
  DEFB 0                  ; Room item's horizontal position within current
                          ; room, in half-character (4 pixel) steps
  DEFB 0                  ; Room item's vertical position within current room,
                          ; in pixels, from top of room area
  DEFW 0                  ; Address pointer for room data sets stored at L25001
                          ; Also used to store for ROM memory address pointer
                          ; used to generate foreground scenery objects at
                          ; L50433_1
  DEFB 0                  ; First room data byte from data banks at L25001
  DEFB 0                  ; Multi-purpose byte:
                          ; * Used as a counter to compare with first room data
                          ;   byte (L25001) which holds the room size
                          ; * Tunnel length - byte 1 of tunnel data set at
                          ;   L26384
  DEFB 0                  ; Multi-purpose:
                          ; * Temporary store for room data bytes at L25001
                          ; * Data byte x 4 (used to calculate co-ordinates)
                          ;   subsequently stored here at 49691
                          ; * Counter for number of boundary walls currently on
                          ;   screen in tunnel section
; Data relating to doors:
  DEFB 0                  ; Door byte:
                          ; * 0 = Back wall door
                          ; * 1 = Right wall door
                          ; * 2 = Left wall door
  DEFB 0                  ; Positive/negative offset for door graphic frame
                          ; (used in routine at L51892) Indicates number of
                          ; frames (bits 0-2) and opening/closing direction
  DEFB 0                  ; Pre-graphic data byte including calculated number
                          ; of animation frames needed for door.Back wall doors
                          ; have 4 frames, side wall doors have 5.Calculated at
                          ; 50091 in door calculation routine.

; Data buffer - room objects
L60290:
  DEFW 0                  ; Address pointer to item's data set in object room
                          ; table at L29551
  DEFB 0                  ; Data set number for object in room interactable
                          ; objects table at L29551
; 8 bytes copied here from object data table (L29551) at the routine at L56959
  DEFB 0                  ; Room number of object being dealt with
  DEFB 0                  ; Horizontal (X) position of object in room, in
                          ; 4-pixel (half-character) steps
  DEFB 0                  ; Vertical (Y) position of object in room, in pixels,
                          ; from top of room
  DEFB 0                  ; Item properties byte (similar to 60238) Bit 1 (2)
                          ; set = Item is not visible Bit 2 (4) set =
                          ; Item/creature not subject to standard room boundary
                          ; collision checks (e.g. BATS) Bit 4 (16) set = Item
                          ; is being carried by servant Bit 6 (64) set = Maroc
                          ; can pick up the item
  DEFB 0                  ; Object state - starts at 1 for each object, e.g.
                          ; chest state 1 = closed, 2 = open Each additional
                          ; object state is stored in an extra 4 byte set
  DEFB 0                  ; Spell number (or 0 if not a spell) - spell table at
                          ; L28156 Start counting with MOVE = 0, SERVANT = 1
                          ; etc.
  DEFB 0                  ; Attribute/colour/value of object
                          ; * Bits 0-3 = INK colour of object (0-7)
                          ; * Bit 4 = object will change colour
                          ; * Bits 5-7 contain the item's value when trading
                          ;   with warlocks - see 52857
  DEFB 0                  ; Number of additional 4-byte sets for this object
; 4 additional bytes related to the object's current state. Copied here from
; the object's data set at L29551 by the routine at L56959
  DEFB 0                  ; Room item/creature movement pattern byte. Used for
                          ; moving room items (including set room creatures) in
                          ; the routine at L52136
                          ; * Bit 0 set = room item/creature has a random
                          ;   element to its movement
                          ; * Bit 1 set = room item/creature will try to home
                          ;   in on Maroc's position
                          ; * Bit 2 set = room item/creature is subject to
                          ;   usual room wall collision detection/adjustment
                          ;   (BATS do not have this set)
  DEFB 0                  ; Event number for items acting on this item - e.g.
                          ; for a chest, which is opened by a particular key
                          ; with matching event number Checked in
                          ; event/collision checks at L52263 Event type 15 =
                          ; Object that Maroc can collect (or be given by the
                          ; servant)
  DEFB 0                  ; Event number to check for this item - e.g. for a
                          ; key, that opens a particular chest with matching
                          ; event number As part of event/collision check, also
                          ; used for energy-affecting objects, e.g. orbs and
                          ; mushrooms. 254 = energy drain, 253 = energy
                          ; replenish
  DEFB 0                  ; Graphic number - offset for graphic address table
                          ; at L38851 Calculated is [(n-1)*2] + L38851 A value
                          ; of 124 (check at L51968) means the object is hidden
                          ; (e.g. inside a chest) so doesn't need drawing on
                          ; screen

; Data buffer - missile data
;
; Missile-related data such as missile position:
L60305:
  DEFB 0                  ; Number of creature-launched missiles currently in
                          ; effect (maximum of 1 missile allowed at any time,
                          ; so will either be 0 or 1)
  DEFB 0                  ; Number of Maroc-launched missiles currently in
                          ; effect (incremented at 55220)
  DEFB 0                  ; Missile number (table at L27868), used in routine
                          ; at L56095
  DEFB 0                  ; Missile horizontal position overflow/precision byte
                          ; - to calculate fractions as main position (in next
                          ; byte) is in 4-pixel increments
  DEFB 0                  ; Horizontal position of missile origin in 4-pixel
                          ; (half-character) steps
  DEFB 0                  ; Missile vertical position overflow/precision byte -
                          ; generally unused as vertical position is in pixels
  DEFB 0                  ; Vertical pixel position of missile origin
  DEFB 0                  ; Horizontal (X) position of target, in
                          ; half-character (4-pixel) steps
  DEFB 0                  ; Vertical (Y) position of target, in pixels
  DEFB 0                  ; Object type (missile):
                          ; * 5 = Missile fired by creature (at Maroc)
                          ; * 8 = Missile fired by Maroc
                          ;  Stored as first byte in data set at 31744.
  DEFW 0                  ; Address pointer to missile data in table at L27868
; Missile buffer table. 8 bytes of missile data copied from sets at L27868.
  DEFB 0                  ; Graphic number - offset for missile graphic address
                          ; in table at L38851 52 = Missile type 1 (38953) 55 =
                          ; Missile type 2 (38961) 58 = Missile type 3 (38965)
  DEFB 0                  ; Missile properties byte Top 4 bits of this byte
                          ; hold the missile's duration/longevity (how long
                          ; it's on screen for)
  DEFB 0                  ; Missile ink colour. If bit 3 is set, the missile
                          ; changes colour
  DEFB 0                  ; Missile's event/collision type to check
  DEFB 0                  ; Counter spell #1 (from list at L28156, starting at
                          ; 0) This value = 14 for all missiles = AMULET, which
                          ; resists all missile types
  DEFB 0                  ; Used at 53542, damage caused by missile = the
                          ; amount to decrease Maroc's energy by
  DEFB 0                  ; Counter spell #2 (from list at L28156, starting at
                          ; 0) that resists this missile/bolt type
  DEFB 0                  ; Counter spell #3 (from list at L28156, starting at
                          ; 0) that resists this missile/bolt type

; Data buffer - creature attributes
;
; 8 bytes copied from data sets at L27772/27828 in creature setup routine at
; L52616_0
;
; See Reference - Creatures for information about the different denizens that
; inhabit Avalon.
L60325:
  DEFB 0                  ; INK colour of creature If bit 3 is set it means
                          ; creature changes colour
  DEFB 0                  ; Number of these creatures that Maroc has destroyed
  DEFB 0                  ; Type of missile (L27868) fired by this creature (0
                          ; = no ranged attack)
  DEFB 0                  ; Object number held by this creature, in table at
                          ; L29551 (warlocks only)
  DEFB 0                  ; Collision/event check type (wraiths/demons = 7,
                          ; other creatures = 3)
  DEFB 0                  ; Collision/event check value for creatures
                          ; opening/closing doors (17)
  DEFB 0                  ; Graphic number - offset for creature graphic
                          ; address in table at L38851
  DEFB 0                  ; Amount to reduce Maroc's energy by if the creature
                          ; touches Maroc, checked at L53349_0

; Game data buffer - warlock and creature attributes/data
;
; Various bits of warlock and creature data, used in-game.
L60333:
  DEFB 0                  ; Warlock's "aggression" - this is byte 6 of the
                          ; warlock's data set at L27772 Affects the delay in a
                          ; warlock appearing on-screen, and the frequency of
                          ; the missiles it fires at Maroc
  DEFB 0                  ; Room object number in table at L29551 Copied from
                          ; 60230 in routine at 52535 after non-tradeable item
                          ; given to warlock Object number held by warlock
                          ; copied from 60328 in routine at 52857
  DEFB 0                  ; Byte containing attribute/colour and value of item,
                          ; copied from 60299 in routine at 52543 after
                          ; non-tradeable item given to warlock
  DEFB 0                  ; - (unused)
  DEFB 0                  ; Servant object-carrying status: 0 = servant is not
                          ; carrying an object 1 = servant is carrying an
                          ; object 2 = servant has just picked up an object
                          ; from Maroc's backpack (stops items continuously
                          ; swapping while the servant is hovering over Maroc's
                          ; backpack)
  DEFB 0                  ; - (unused)
  DEFB 0                  ; - (unused)
  DEFB 0                  ; Timer affecting how long before a warlock is likely
                          ; to materialize in the current room
                          ; * Decremented and checked at 54886
                          ; * Reset to 255 at the start of a new game (49350)
                          ; * 64 added as a 'top up' to the timer when Maroc
                          ;   enters a new room (L50272_7)
                          ; * Set to 144 when warlock moves off-screen (52955)
                          ; * Set to 8 after HAIL spell cast (L55502)
                          ; * Set to 224 after object has been successfully
                          ;   traded with the warlock (L53145_1)
  DEFB 0                  ; Timer indicating how long before a creature is
                          ; likely to wander in from an adjacent room
                          ; * Decremented and checked at 51468
                          ; * Reset to 255 at the start of a new game (49350)
                          ; * 128 added as a 'top up' to the timer when Maroc
                          ;   enters a new room (L50272_7)
  DEFB 0                  ; Number of creatures in current room (max 3)
  DEFB 0                  ; Multi-use:
                          ; * Contains the room creature byte (from table at
                          ;   L27532) indicating which creatures are in a room
                          ; * Set to 7 as a max counter for a room's
                          ;   interactable objects at L50218
  DEFB 0                  ; Creature's horizontal position (in 4-pixel steps)
                          ; in room, after entering through a door Calculated
                          ; from the door's horizontal position at L51551_3
  DEFB 0                  ; Creature's vertical pixel position in room, after
                          ; entering through a door Calculated from the door's
                          ; vertical position at L51551_3

; Data buffer - Maroc's inventory address pointers
L60346:
  DEFW 0                  ; Address pointer to start of Maroc's inventory at
                          ; 32626
  DEFW 0                  ; Address pointer to current slot of Maroc's
                          ; inventory at 32626
  DEFW 0                  ; Address pointer to next inventory slot at 32626
  DEFB 0                  ; - (unused)

; Missile & creature data pointers for start of game
L60353:
  DEFW 0                  ; Address pointer to missile data at L27868
  DEFW 0                  ; Address pointer to warlock and creature information
                          ; at L27772

; Store for currently selected spell data
;
; 16 bytes of spell data for the current selected spell. Copied from L28156 in
; routine at 59138 and copied back at routine at 60044.
;
; The first set of 8 bytes contains the spell data:
L60357:
  DEFB 0                  ; Set to 16 if this spell has been acquired, 0 if not
                          ; yet acquired
  DEFB 0                  ; Energy cost of casting spell'Effect' spells (e.g.
                          ; SHIELD, UNSEEN) - energy drain amountHealing spells
                          ; (e.g. ENERGIZE, CHALICE) - energy restoration
                          ; amount (essentially a 'negative drain')
  DEFB 0                  ; Spell type: 1 = MOVE spell 2 = Spell that generates
                          ; a controllable graphic/icon, e.g. SERVANT, MISSILE,
                          ; OPEN3 = Assigned to the ELECTRIC and FLAME spells4
                          ; = Ongoing effect spell (e.g. SHIELD, WRAITHBANE),
                          ; spell name appears in bottom right mini-scroll5 =
                          ; Instant effect spell e.g. ENERGIZE, FREEZE, PORTAL
  DEFB 0                  ; Number of 'charges' left for casting the spell (255
                          ; = infinite uses)
  DEFB 0                  ; Character number within the current spell message
                          ; text (at L28604) When a spell is activated, the
                          ; message isn't printed all at once, but letter by
                          ; letter Also used for level name texts
  DEFB 0                  ; Relates to the servant/eye cursor spells and the
                          ; event/action to take place when the spell is
                          ; active. Values:
                          ; * Missile/bolt spells = 128 + missile number, in
                          ;   table at L27868. e.g. MISSILE = 128 + 4 = 132
                          ; * Other cursor spells: DISPEL = 2, UNLOCK = 4,
                          ;   SERVANT = 5, FIND = 8, OPEN = 10, REVEAL = 16
                          ;  For the second set of these, the value is stored
                          ; as the second byte of the room item event table at
                          ; 32691 Room items are affected by moving these
                          ; active cursors over particular objects/areas (e.g.
                          ; OPEN/UNLOCK vs certain doors)
  DEFB 0                  ; Graphic number - in the graphics pointer table (at
                          ; L38851) - for the spell's icon to use on the scroll
                          ; (e.g. L41342)
  DEFB 0                  ; Graphic number - for the graphics pointer table (at
                          ; L38851) for the spell's controllable graphic/aiming
                          ; cursor (or 0 if a spell doesn't need one).For the
                          ; SERVANT spell, offset is 41 (graphics pointer 38931
                          ; pointing to servant graphics at 41180)For all other
                          ; 'aiming cursor' spells (e.g. UNLOCK, MISSILE, OPEN,
                          ; FIND, ICEBOLT) spell offset is 43 (graphics pointer
                          ; 38935 pointing to blinking eye cursor graphics at
                          ; 41221)
; The second set of 8 bytes contains the spell name
  DEFB 0,0,0,0,0,0,0,0
; Finally the energy cost/effect of the spell:
  DEFB 0                  ; Energy drain/heal amount for constant effects
                          ; spells, e.g. SHIELD (drain) or CHALICE (heal) -
                          ; actioned in routine at 54859 This is stored in byte
                          ; 2 of the spell data (60358) which is copied here at
                          ; 59364 when spell is activated Also, casting cost
                          ; for instant effect spells - spells such as
                          ; WAYSTONE, FLAME take energy to cast

; Room item/creature attribute colour patterns
;
; Used at L58365 when setting display attributes for drawn/erased graphics that
; aren't Maroc or background room scenery.
;
; Contains a series of directional offsets to put the colours for the graphic
; on screen.
;
; There are 2 sets:
; * 3 characters wide x 5 characters tall - for creatures
; * 3 characters wide x 3 characters tall - for objects
;
; After each offset is added to the display address pointer, the colour is
; applied to the character square.
;
; SET 1 - for CREATURES, or destroyed creatures (3 x 5 character squares):
L60374:
  DEFB 15                 ; First byte = number of bytes in this set, used as a
                          ; loop counter for printing the colour blocks
  DEFB -65                ; Added to screen attribute display address. In this
                          ; case -65 will move the address up TWO ROWS, and one
                          ; square to the left
  DEFB 1                  ; Then move right one square
  DEFB 1                  ; ...and another one
  DEFB 30                 ; Then add 30 to the address, which moves down one
                          ; line and back to the left two squares
  DEFB 1,1,30,1,1,30,1,1  ; ...Then a repeat of the 2 x 1 character squares,
  DEFB 30,1,1             ; for 4 more rows, with some 30s to move across the
                          ; screen and down to the next row
; SET 2 - for OBJECTS (3 x 3 character squares):
  DEFB 9                  ; First byte = number of bytes in this set, used as a
                          ; loop counter for printing the colour blocks
  DEFB -33                ; Added to screen attribute display address. In this
                          ; case -33 will move the address up ONE ROW, and one
                          ; square to the left
  DEFB 1                  ; Then move right one square
  DEFB 1                  ; ...and another one
  DEFB 30                 ; Then add 30 to the address, which moves down one
                          ; line and back to the left two squares
  DEFB 1,1,30,1,1         ; ...Then a repeat of the 2 x 1 character squares,
                          ; for 2 more rows

; Music data
;
; Used by the music playing routine at L58806.
;
; Each played note is the same duration. Each pair of bytes (e.g. 190, 190)
; determine the frequencies for two separate notes, played together.
;
; Where the numbers differ (e.g. 190, 160) you hear a two-note chord sound.
;
; The first set of data is the main theme tune played for the intro of a new
; game, and also on a permanent loop when the player completes the game:
L60400:
  DEFB 190,190,127,127,80,80,127,127 ; Bar 1
  DEFB 190,190,127,127,80,80,127,127 ; Bar 1 (repeat)
  DEFB 190,190,190,160,95,80,170,143 ; Bar 2
  DEFB 190,160,170,143,190,160,170,143 ; Bar 3
  DEFB 127,107,127,107,127,127,143,143 ; Bar 4
  DEFB 127,107,127,107,127,127,120,120 ; Bar 5
  DEFB 190,160,190,160,170,143,170,143 ; Bar 6
  DEFB 160,127,160,127,143,120,143,120 ; Bar 7
  DEFB 190,190,127,127,80,80,127,127 ; Bar 8
  DEFB 190,190,127,127,80,80,127,127 ; Bar 8 (repeat)
  DEFB 95,95,107,107,120,120,127,107 ; Bar 9
  DEFB 143,120,160,127,160,127,190,160 ; Bar 10
  DEFB 190,160,190,160,47,47,60,60 ; Bar 11
  DEFB 64,64,80,80,95,95,127,127 ; Bar 12
  DEFB 160,160,190,95,190,95,95,95 ; Bar 13
  DEFB 190,190,190,190,190,190,190,190 ; Bar 14
  DEFB 255,255            ; 255 = End markers
; This short set of music plays when you pause the game (pause routine at
; L51043):
  DEFB 240,190,214,214,190,160,180,180
  DEFB 190,160,180,143,120,120,143,143
  DEFB 180,180,127,127,160,160,180,180
  DEFB 160,160,214,180,190,190,214,214
  DEFB 255,255

; Data buffer - various bits of spell and tunnel data
L60564:
  DEFW 0                  ; Store for graphics address pointer table address
                          ; for controllable eye cursor/servant graphics
                          ; (38931/38935) Set when spell cast at 59444
  DEFW 0                  ; Flickering barrier graphics for SHIELD, PROTECT and
                          ; DEFENCE spells (43500) Initialized at game setup at
                          ; 49212
  DEFB 0                  ; Value representing action to take when FIRE pressed
                          ; with a servant/icon spell active (checked at 55328
                          ; and 59885) Values:
                          ; * Missile/bolt spells = 128 + missile number, in
                          ;   table at L27868. e.g. MISSILE = 128 + 4 = 132
                          ; * Other cursor spells: DISPEL = 2, UNLOCK = 4,
                          ;   SERVANT = 5, FIND = 8, OPEN = 10, REVEAL = 16
  DEFB 0                  ; Graphic animation frame number for controllable
                          ; spell icon Set to 1 at L59389_1 when casting a
                          ; spell requiring an aiming cursor, e.g. SERVANT,
                          ; OPEN, FIND, MISSILE Incremented/reset in the
                          ; routine at L58166
  DEFB 0                  ; Store for pre-graphics data byte (see Trivia -
                          ; Graphics properties byte) Copied from 60239 in
                          ; routine at 59447
  DEFB 128                ; - (unused)
  DEFB 0                  ; FREEZE spell timer counter Checked at 58188 when
                          ; creature in/entering room
  DEFB 0                  ; Tunnel - current number of on-screen creatures (max
                          ; 3)
  DEFB 0                  ; Tunnel - (viewport) horizontal position (in
                          ; half-character/4-pixel steps) Copied from 60232 in
                          ; tunnel routine at L53625_3
  DEFB 0                  ; Address pointer offset for Maroc's sprite graphic
                          ; address (starting from L38851) This is an even
                          ; value in the range 0-14 Calculated in the routine
                          ; at L54120_11
  DEFB 0                  ; Repeat counter for flashing the 'MAGIC' text in the
                          ; bottom left of the screen when a spell is collected
                          ; Set to 15 (for 15 flash/sound repetitions) at
                          ; L52392_1
  DEFB 0                  ; Maroc's height offset in pixels Maroc rises higher
                          ; above his shadow the faster he moves Range is from
                          ; +7 (lowest/stationary) to -1 (255) - highest point

; Unused
L60578:
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,77,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0

; Code sheet - full code sheet data values
;
; Table of values used in routine at L61946 to generate/check codes entered
; against code sheet
;
; Values listed in hexadecimal as this is how they are printed on the sheet.
L60600:
  DEFB $10,$59,$74,$09,$18,$58,$41,$21,$64,$87,$87,$27,$10,$10,$45,$93 ; Row 0
  DEFB $59,$54,$34,$06,$94,$98,$05,$14,$67,$03,$28,$18,$27,$35,$55,$37
  DEFB $24,$34,$56,$33,$58,$52,$56,$59,$04,$63,$45,$16,$38,$92,$76,$66 ; Row 1
  DEFB $38,$53,$10,$12,$59,$17,$79,$35,$39,$40,$04,$92,$69,$95,$72,$11
  DEFB $14,$00,$17,$93,$34,$45,$30,$57,$34,$59,$22,$31,$60,$20,$05,$81 ; Row 2
  DEFB $36,$17,$07,$35,$03,$58,$41,$17,$60,$02,$08,$11,$15,$58,$10,$84
  DEFB $13,$09,$45,$00,$99,$26,$33,$58,$82,$66,$28,$85,$61,$84,$87,$94 ; Row 3
  DEFB $08,$10,$20,$73,$19,$14,$91,$45,$61,$95,$49,$20,$21,$74,$87,$73
  DEFB $51,$04,$52,$31,$21,$18,$96,$72,$62,$52,$10,$67,$51,$05,$80,$59 ; Row 4
  DEFB $17,$01,$76,$17,$66,$59,$48,$81,$96,$74,$81,$49,$72,$42,$81,$66
  DEFB $38,$34,$44,$56,$60,$32,$37,$89,$22,$36,$95,$43,$25,$12,$24,$67 ; Row 5
  DEFB $76,$70,$07,$94,$75,$97,$24,$11,$18,$07,$41,$11,$32,$43,$34,$35
  DEFB $09,$53,$91,$69,$41,$37,$85,$72,$52,$93,$98,$43,$37,$47,$36,$59 ; Row 6
  DEFB $52,$87,$74,$23,$05,$76,$13,$05,$30,$98,$34,$46,$12,$61,$95,$53
  DEFB $11,$53,$08,$38,$10,$11,$04,$94,$09,$72,$96,$56,$40,$16,$61,$65 ; Row 7
  DEFB $27,$64,$90,$89,$11,$92,$33,$37,$16,$35,$82,$55,$59,$94,$46,$13
  DEFB $41,$72,$54,$51,$73,$85,$30,$50,$39,$15,$08,$41,$47,$09,$86,$33 ; Row 8
  DEFB $61,$44,$29,$47,$75,$77,$26,$67,$32,$67,$99,$38,$95,$32,$01,$07
  DEFB $90,$87,$99,$02,$27,$67,$69,$63,$30,$98,$24,$29,$05,$43,$91,$78 ; Row 9
  DEFB $49,$84,$61,$43,$15,$64,$67,$41,$54,$08,$65,$23,$77,$88,$80,$35
  DEFB $50,$82,$80,$09,$76,$36,$60,$21,$79,$85,$45,$44,$06,$92,$43,$40 ; Row 10
  DEFB $30,$67,$26,$10,$58,$96,$12,$13,$43,$38,$68,$93,$43,$51,$02,$55
  DEFB $15,$68,$49,$04,$58,$77,$77,$39,$66,$63,$14,$53,$59,$42,$91,$31 ; Row 11
  DEFB $51,$64,$29,$59,$32,$90,$57,$23,$67,$20,$38,$84,$29,$58,$51,$86
  DEFB $76,$86,$45,$71,$19,$64,$03,$09,$16,$78,$14,$82,$00,$98,$07,$14 ; Row 12
  DEFB $93,$40,$80,$17,$51,$50,$96,$75,$80,$58,$66,$88,$94,$40,$08,$59
  DEFB $34,$45,$56,$43,$12,$13,$47,$00,$57,$77,$72,$00,$00,$28,$20,$15 ; Row 13
  DEFB $60,$78,$83,$03,$35,$86,$68,$21,$77,$63,$22,$66,$30,$14,$57,$43
  DEFB $61,$94,$67,$45,$97,$87,$49,$38,$64,$48,$58,$88,$44,$69,$01,$01 ; Row 14
  DEFB $54,$29,$65,$50,$24,$77,$71,$39,$64,$13,$48,$12,$23,$29,$83,$93
  DEFB $41,$19,$27,$05,$92,$98,$82,$87,$44,$09,$78,$07,$81,$69,$20,$14 ; Row 15
  DEFB $50,$95,$09,$98,$91,$41,$31,$86,$83,$28,$11,$69,$39,$96,$23,$76
  DEFB $28,$30,$95,$15,$12,$51,$58,$98,$28,$53,$42,$54,$61,$57,$66,$38 ; Row 16
  DEFB $99,$64,$10,$35,$06,$14,$90,$93,$49,$65,$98,$20,$63,$60,$17,$52
  DEFB $02,$83,$26,$49,$14,$49,$25,$61,$71,$43,$09,$76,$97,$06,$47,$20 ; Row 17
  DEFB $84,$07,$33,$36,$20,$48,$86,$05,$24,$69,$09,$61,$71,$09,$95,$98
  DEFB $44,$46,$46,$58,$44,$21,$34,$75,$44,$86,$17,$36,$00,$30,$92,$22 ; Row 18
  DEFB $98,$07,$69,$50,$71,$93,$60,$57,$39,$63,$70,$96,$99,$73,$80,$47
  DEFB $59,$18,$01,$73,$08,$94,$93,$64,$81,$93,$55,$13,$59,$48,$31,$66 ; Row 19
  DEFB $46,$72,$92,$87,$68,$51,$14,$07,$11,$09,$61,$68,$20,$12,$24,$86
  DEFB $42,$26,$06,$79,$17,$44,$40,$15,$26,$55,$85,$94,$79,$87,$70,$64 ; Row 20
  DEFB $19,$52,$49,$17,$47,$83,$02,$25,$54,$55,$58,$48,$79,$95,$86,$42
  DEFB $34,$84,$77,$69,$81,$67,$82,$04,$57,$78,$34,$35,$76,$21,$77,$85 ; Row 21
  DEFB $01,$49,$45,$07,$58,$06,$08,$41,$06,$70,$07,$35,$91,$61,$28,$93
  DEFB $34,$35,$45,$16,$50,$88,$89,$90,$63,$20,$92,$48,$76,$56,$03,$59 ; Row 22
  DEFB $01,$93,$98,$63,$22,$95,$08,$75,$49,$50,$16,$12,$02,$32,$67,$15
  DEFB $75,$17,$63,$94,$31,$06,$07,$67,$37,$21,$00,$66,$71,$48,$44,$69 ; Row 23
  DEFB $34,$94,$60,$38,$91,$99,$30,$92,$65,$73,$95,$03,$58,$32,$83,$25
  DEFB $33,$94,$09,$99,$71,$11,$54,$50,$70,$90,$92,$23,$21,$45,$39,$04 ; Row 24
  DEFB $61,$66,$72,$55,$23,$65,$36,$87,$45,$74,$44,$35,$31,$83,$63,$21
  DEFB $89,$78,$21,$88,$86,$93,$32,$87,$05,$72,$48,$15,$26,$60,$58,$34 ; Row 25
  DEFB $97,$20,$80,$76,$99,$88,$40,$43,$00,$05,$02,$25,$79,$68,$72,$52
  DEFB $87,$92,$75,$22,$15,$10,$21,$78,$91,$53,$08,$79,$72,$07,$29,$57 ; Row 26
  DEFB $13,$00,$39,$95,$51,$04,$77,$44,$35,$22,$24,$12,$65,$17,$29,$68
  DEFB $46,$30,$33,$58,$57,$53,$14,$81,$34,$45,$65,$87,$56,$81,$35,$03 ; Row 27
  DEFB $10,$69,$34,$01,$53,$30,$22,$46,$14,$93,$83,$02,$02,$90,$68,$81
  DEFB $56,$23,$62,$43,$45,$31,$90,$53,$47,$69,$45,$86,$05,$49,$77,$01 ; Row 28
  DEFB $63,$64,$83,$14,$89,$12,$51,$60,$07,$69,$68,$93,$01,$69,$12,$35
  DEFB $11,$53,$57,$29,$62,$45,$29,$12,$61,$33,$08,$19,$33,$82,$56,$07 ; Row 29
  DEFB $21,$59,$75,$20,$95,$50,$06,$62,$37,$86,$27,$60,$30,$28,$81,$30
  DEFB $93,$40,$96,$10,$07,$64,$53,$56,$74,$75,$53,$93,$83,$78,$87,$42 ; Row 30
  DEFB $36,$62,$59,$93,$64,$15,$12,$99,$10,$06,$92,$07,$73,$04,$06,$84
  DEFB $65,$92,$36,$40,$91,$49,$39,$71,$44,$18,$01,$45,$21,$70,$62,$44 ; Row 31
  DEFB $22,$28,$36,$64,$07,$77,$83,$44,$10,$23,$57,$85,$59,$24,$75,$86
  DEFB $35,$98,$99,$96,$14,$53,$96,$55,$52,$23,$82,$88,$90,$19,$66,$64 ; Row 32
  DEFB $95,$56,$20,$37,$99,$95,$32,$09,$03,$92,$45,$28,$57,$19,$10,$32
  DEFB $45,$04,$21,$91,$47,$28,$20,$80,$00,$69,$81,$17,$34,$36,$32,$39 ; Row 33
  DEFB $41,$84,$33,$74,$24,$65,$53,$55,$15,$48,$63,$56,$87,$61,$80,$76
  DEFB $25,$75,$16,$97,$04,$32,$66,$54,$74,$85,$14,$44,$35,$41,$72,$75 ; Row 34
  DEFB $05,$22,$63,$68,$31,$74,$54,$86,$88,$85,$28,$56,$90,$69,$32,$67
  DEFB $90,$55,$66,$84,$55,$00,$27,$76,$36,$11,$66,$27,$26,$58,$68,$73 ; Row 35
  DEFB $11,$16,$44,$35,$85,$61,$65,$65,$18,$61,$76,$57,$68,$37,$34,$35
  DEFB $51,$35,$80,$89,$44,$52,$77,$47,$69,$67,$58,$56,$99,$94,$46,$79 ; Row 36
  DEFB $05,$48,$85,$20,$98,$05,$56,$72,$34,$51,$60,$21,$10,$57,$80,$09
  DEFB $03,$78,$43,$16,$39,$53,$97,$40,$20,$31,$76,$79,$36,$70,$09,$94 ; Row 37
  DEFB $86,$65,$06,$75,$41,$70,$78,$88,$41,$45,$97,$45,$36,$45,$82,$37
  DEFB $79,$13,$46,$34,$64,$46,$65,$47,$60,$08,$46,$33,$86,$36,$83,$36 ; Row 38
  DEFB $09,$07,$12,$24,$14,$03,$53,$64,$09,$07,$80,$85,$49,$09,$25,$67
  DEFB $32,$48,$74,$95,$98,$86,$69,$14,$04,$78,$52,$00,$88,$29,$21,$68 ; Row 39
  DEFB $45,$59,$55,$72,$06,$69,$14,$21,$48,$19,$09,$18,$05,$58,$13,$17
  DEFB $54,$88,$21,$85,$69,$78,$66,$22,$59,$99,$67,$26,$50,$27,$09,$67 ; Row 40
  DEFB $52,$32,$06,$80,$32,$30,$34,$33,$51,$01,$45,$83,$62,$44,$56,$88
  DEFB $58,$72,$66,$92,$31,$94,$08,$48,$16,$08,$66,$89,$45,$42,$21,$08 ; Row 41
  DEFB $47,$10,$48,$28,$28,$08,$84,$47,$08,$33,$23,$31,$99,$45,$27,$22
; Store for the two-byte code that needs matching, picked from the above table
;
; Stored at 62197 and checked at 62275
  DEFB 87,67

; Code sheet - get the code that the player needs to enter
;
; Used by the routine at L62102.
;
; Called from 62194 after code generated and message printed on screen.
;
; Picks out the relevant code from the code table at L60600 that the player
; needs to type in. The 2-byte code is returned in the DE registers.
L61946:
  LD A,(L62048)           ; Second part of code from code sheet (number) -
  LD L,A                  ; value = 0-41
  LD H,0                  ; Store value in HL register pair
; Each set (0-41) in the code table at L60600 is 32 bytes long, so need to
; multiply this by 32 bytes to get to the right set
  ADD HL,HL               ; x2
  ADD HL,HL               ; x4
  ADD HL,HL               ; x8
  ADD HL,HL               ; x16
  ADD HL,HL               ; x32
; Next use the first part of the code to find the value within the set:
  LD A,(62049)            ; First part of code from code sheet (letter) - value
                          ; = 0-16 (A-P)
  ADD A,A                 ; x2 (as each 4-digit code is 2 bytes long)
  LD C,A                  ;
  LD B,0                  ; Store value in BC register pair
  ADD HL,BC               ; Add to HL value
  LD BC,L60600            ;
  ADD HL,BC               ; ...and then add the start of the code sheet address
                          ; location to get to the right place.
; The HL register pair is now pointing to relevant code (2 bytes) in table at
; L60600.
;
; Now put the 2 code bytes into the D & E registers
  INC HL
  LD D,(HL)               ; Second (high) byte stored in D register
  DEC HL                  ;
  LD E,(HL)               ; First (low) byte stored in E register
  RET                     ;

; Code sheet - bytes used to randomize code sheet co-ordinates choice
;
; Used in routine at L61982 to pick a random value for the co-ordinates of the
; security code on the code sheet that needs to be entered.
;
; The first 4 values are randomized, the next 4 are fixed (and used to further
; randomize the initial values)
L61974:
  DEFB 107,133            ; System variable FRAMES cycle timer (2 bytes of it)
                          ; stored here at start of code routine at L62089
  DEFB 185                ; The (first) 2 bytes of the FRAMES timer are used as
                          ; a random address to pick a byte from. The byte is
                          ; stored here, in the routine at L62089.
  DEFB 139                ; The byte at 61976 is copied here as well in the
                          ; same routine. This will be the random value that
                          ; the co-ordinates are generated from.
  DEFB 118,181,83,176     ; 4 byte values that are used to XOR and pixel-shift
                          ; with the previous four, to create random numbers

; Code sheet - hash/randomize the security code co-ordinates required for input
;
; Used by the routine at L62068.
;
; This routine provides random code sheet co-ordinates for security code entry.
;
; The first 4 bytes at L61974 contain random values (generated at L62089 from
; the FRAMES system variable timer).
;
; This routine then uses a combination of bit shift and XOR operations to
; further obfuscate the data at L61974. Ultimately a randomized byte #4 of this
; set is used to generate the random codesheet co-ordinates.
L61982:
  PUSH HL                 ; Store registers
  PUSH BC                 ;
  PUSH IX                 ;
  LD B,8                  ; 8 x iterations of the below
; The first 4 pseudo-random bytes at L61974 are altered (using XOR/shifts) with
; the following 4 (fixed) bytes at 61978. This process is started once bits 7
; is set in the 4th byte just to ensure we've got some data to combine.
L61982_0:
  LD IX,L61974            ; Pointer to byte 1 of 8 byte data set
  AND A                   ; Sets (A=0) or unsets (A<>0) zero flag, though the
                          ; zero flag will be changed in the next instruction
                          ; anyway
  BIT 7,(IX+3)            ; Top bit of 4th byte in data set (L61974)
  JR Z,L61982_2           ; If it's zero (bit not set), rotate left first 4
                          ; bytes of data set and jump back to L61982_0
; Combine some bytes to further mix up the numbers:
  LD HL,61978             ; Pointer to byte 5 of 8 byte data set
  LD C,3                  ; 3 iterations
L61982_1:
  LD A,(IX+0)             ; Mash together (XOR) bytes 1-3 in the table with
  XOR (HL)                ; (fixed) bytes 5-7
  LD (IX+0),A             ; ...re-storing each one
  INC IX                  ; Increment both pointers
  INC HL                  ;
  DEC C                   ;
  JR NZ,L61982_1          ; Repeat for first three 3 bytes in table
  LD IX,L61974            ; Point to the start of the 8 byte set
  SCF                     ; Set the carry flag ready for the next loop
L61982_2:
  RL (IX+0)               ; Rotate each of the first 4 bytes
  RL (IX+1)               ;
  RL (IX+2)               ;
  RL (IX+3)               ;
  DJNZ L61982_0           ; ...and repeat from L61982_0 (8 iterations)
  LD A,(IX+3)             ; Grab the randomized/hashed 4th btye of the table in
                          ; the A register - this will be used to generate the
                          ; co-ordinates
  POP IX                  ; Retrieve registers
  POP BC                  ;
  POP HL                  ;
  RET                     ; A register returned with the number to use to pick
                          ; the code sheet co-ordinates.

; Code sheet - store for code value co-ordinates (for code sheet)
;
; Co-ordinates of the code that needs to be correctly input from the code
; sheet, e.g. A12, H22
L62048:
  DEFB 13                 ; Second part of code from code sheet (number) Value
                          ; from 0-41 Printed on screen at 62147
  DEFB 15                 ; First part of code from code sheet (letter) Letters
                          ; are from A to P, so values will be 0-16 65 is added
                          ; at 62144 to provide the ASCII values 65-90 (letters
                          ; A to P)Printed on screen at 62141

; Unused
L62050:
  DEFB 62,32,201,62,0,201

; Code sheet - print code message/character on screen
;
; Used by the routines at L62102, L62201 and L62288.
;
L62056:
  EX (SP),HL              ; HL now points to the character(s) to print on
                          ; screen, e.g. 62122
; Print character:
L62056_0:
  LD A,(HL)               ; Get character from message string
  INC HL                  ; ...and move address pointer on to the next letter
  CP 255                  ; Check for end-of-text marker
  JR Z,L62056_1           ; If reached, stop printing
  RST 16                  ; Otherwise print the character
  JR L62056_0             ; Repeat until all message characters printed
L62056_1:
  EX (SP),HL              ; ...Then swap the message address pointer back onto
  RET                     ; the stack

; Code sheet - pick a reference co-ordinate for the code that the player has to
; enter
;
; Used by the routine at L62102.
;
; The code sheet is referenced with a letter (A-P) and a set number (0-41), but
; these are stored as two numbers, from 0-15 and 0-41 respectively.
L62068:
  CALL L61982             ; Call hashing routine to obfuscate data at L61974
  AND 15                  ; The A register is returned with a hashed/randomized
                          ; value - the 4th byte of the data set at L61974.
                          ; Keep bits 0-3 (values 0-15)
  LD (62049),A            ; Store as first part of code from code sheet (this
                          ; will signify the letter, A-P)
  CALL L61982             ; Call hashing routine again
; Get the number in the range 0-41 as this is the number of code sheet rows:
L62068_0:
  SUB 42                  ; Subtract 42
  JR NC,L62068_0          ; Still positive (>=0)? If so, keep subtracting
  ADD A,42                ; Add 42 to get the number in the range 0 to (+)41
  LD (L62048),A           ; Store as second part of code from the code sheet
  RET                     ; (number)

; Code sheet - generate 3 random bytes using the FRAMES timer system variable
;
; Used by the routine at L62283.
L62089:
  LD HL,(23672)           ; Get the system variable FRAMES cycle timer This
                          ; variable is 3 bytes, but only the first two are
                          ; grabbed
  LD (L61974),HL
  LD E,(HL)               ; Load both E & D registers with the contents of this
  LD D,(HL)               ; (random) address
  LD (61976),DE           ; ...and store
  RET                     ;

; Code sheet - initialize and print security code to enter
;
; Used by the routine at L62288.
L62102:
  CALL L62068             ; Pick a code sheet reference for the code that the
                          ; player has to enter
; This entry point is used by the routine at L62288.
L62102_0:
  CALL 3435               ; Clear the screen (ROM CLS routine)
  LD A,2                  ; Stream type = 2
  CALL 5633               ; Open stream for printing
  LD BC,4379              ; B = character row (27), C = column (17)
  CALL 3545               ; These values are reversed and used to calculate
                          ; screen address position in HL (16614) ready to
                          ; print at.
  CALL L62056             ; Print the following characters/message on screen.
                          ; Return from CALL goes to instructions after the
                          ; message, at 62141
; Initial screen message text:
  DEFM "Type in number at " ; Message to be printed (at previous CALL)
  DEFB 255                ; End-of-string marker
; Print the co-ordinates for the required code from the code sheet.
  LD A,(62049)            ; Value (0-16) signifying first part of code that the
                          ; player needs to enter
  ADD A,65                ; 65 added to this code, to give it values of between
                          ; 65 and 80 This corresponds to ASCII character codes
                          ; (A to P)
  RST 16                  ; Print this value on screen
  LD A,44                 ; ASCII value for comma (,)
  RST 16                  ; Print it
  LD A,(L62048)           ; Get the second part of the code (number from 0-41)
  CP 10                   ; Is it <10?
  JR C,L62102_2           ; If so, fine to go ahead and print it as it's only 1
                          ; character (0-9)
; Code number value is >=10 so we'll need to print two numeric characters
;
; The next routine identifies the first digit (D register) as 49, 50, 51 or 52
; - ASCII codes for 1, 2, 3 or 4 - for the 10s digit Then prints that followed
; by the following value.
  LD D,49                 ; ASCII value for '1' - first digit
  LD E,10                 ; Offset value for 2nd digit
  CP 20                   ; Code number <20?
  JR C,L62102_1           ;
  LD D,50                 ; If not, set ASCII value for '2' - first digit
  LD E,20                 ; Offset value for 2nd digit
  CP 30                   ; Code number <30?
  JR C,L62102_1           ;
  LD D,51                 ; If not, set ASCII value for '3' - first digit
  LD E,30                 ; Offset value for 2nd digit
  CP 40                   ; Code number <40?
  JR C,L62102_1           ;
  LD D,52                 ; If not, set ASCII value for '4' - first digit
  LD E,40                 ; Offset value for 2nd digit
; Print the first digit (tens) of the code:
L62102_1:
  LD A,D                  ; Get the ASCII code value
  RST 16                  ; Print the first code digit
  LD A,(L62048)           ; As it's two digits, we need to get the second
  SUB E                   ; So subtract the offset (the 'tens' amount) from its
                          ; value (e.g. 25-20 to get 5)
; Print the second digit (ones) of the code:
L62102_2:
  ADD A,48                ; Add 48 to get to ASCII values for characters 0 to 9
                          ; (48-57)
  RST 16                  ; Print the second code digit
  CALL L61946             ; Retrieve the code from the code table at L60600 2
                          ; byte code returned in DE (first - low - byte in E,
                          ; second - high - byte in D)
  LD (61944),DE           ; Store the code in a 2-byte holding buffer

; Code sheet - set up and evaluate player code input
;
; Clear/reset input area (clear by printing 5 spaces):
L62201:
  LD BC,3603              ; Line number (B) = 14 Column number (C) = 19
  CALL 3545               ; Call ROM 'CL-SET' routine HL register pair returned
                          ; with screen display position to print at (18510)
  CALL L62056             ; Print the following characters on screen. On RETurn
                          ; from this CALL, continue from 62216
; Characters to print - spaces to clear input area:
  DEFM "     "            ; 5 spaces
  DEFB 255                ; End-of-data byte
; Prepare for player input:
  LD BC,3603              ; Line number (B) = 14 Column number (C) = 19
  CALL 3545               ; Call ROM 'CL-SET' routine HL register pair returned
                          ; with screen display position to print at
  LD B,4                  ; 4 digits to enter
  LD HL,0                 ; HL not needed for print routine (uses RST 16
                          ; instruction and stack pointer to the following
                          ; data)
L62201_0:
  CALL L62056             ; Print the (following) characters on screen
; Characters for flashing cursor:
  DEFM 18,1," ",18,0,8    ; ASCII codes for: - FLASH 1 - " " (SPACE) - FLASH 0
                          ; - CURSOR LEFT
  DEFB 255                ; End-of-data marker
; Check player input:
L62201_1:
  BIT 5,(IY+1)            ; FLAGS (system variable) - bit 5 is set if a key is
                          ; pressed
  JR Z,L62201_1           ; Keep checking until it's pressed
  RES 5,(IY+1)            ; Key pressed - reset bit 5 of FLAGS system variable
  LD A,(23560)            ; Get value of LAST-K (last pressed key)
  CP 12                   ; Has DELETE been pressed?
  JR Z,L62201             ; If so, jump back and reset the player's input
                          ; (clear the input area)
; Evaluate key pressed:
  LD C,A                  ; Store key value in C register
  SUB 48                  ; Is code for key pressed <48 (number 0 = value of
                          ; 48, the first valid character that can be typed)
  JR C,L62201_1           ; If so, it's not valid - jump back until another key
                          ; is pressed
  CP 10                   ; Is the code for the key press one of the numbers
                          ; (0-9)?
  JR NC,L62201_1          ; If not, it's not valid - jump back until another
                          ; key is pressed
; A valid key between 0 and 9 has been pressed
  LD E,A                  ; Store value of key pressed (0-9) in E register
  LD A,C                  ; Retrieve key code value from C register
  RST 16                  ; Print the value on screen
; The value to check against is a 2 byte value stored at 61944. Therefore we
; need to multiple each accumulated figure/digit by 16 before adding the next:
  ADD HL,HL               ; HL = HL x2
  ADD HL,HL               ; x4
  ADD HL,HL               ; x8
  ADD HL,HL               ; x16
  LD D,0                  ;
  ADD HL,DE               ;
  DJNZ L62201_0           ; Decrement the counter in the B register. Continue
                          ; to check for input until all 4 digits have been
                          ; entered
; We now have the code value in the HL register pair - check it against the
; correct code:
  LD DE,(61944)           ; Get the correct code value
  XOR A                   ; Clear the carry flag
  SBC HL,DE               ; Subtract the correct code from the user-entered
                          ; code
  RET                     ; Return to 62292 with zero flag result (Z = correct,
                          ; NZ = incorrect)

; Code sheet - set random number seed to generate the random code location
; address
;
; Used by the routines at L23820 and L65000.
;
; Jump here from 65047 after game data unpacked/unecrypted. Initializes the
; code generation routine.
L62283:
  CALL L62089             ; Generate and store 3 random bytes using the FRAMES
                          ; timer system variable
  LD B,3                  ; Set number of correct codes player needs to enter =
                          ; 3

; Code sheet - code entry count and validation
;
; B 3 - number of correct responses needed (set in previous routine)
;
; Keeps count of correct and incorrect codes entered, displaying a message if a
; wrong code is entered.
; * THREE correct codes need to be entered to start the game proper
; * ONE incorrect code is allowed, the machine is reset upon the second
;   incorrent entry
L62288:
  PUSH BC                 ; Store number of codes left to enter
  CALL L62102             ; Set up player code entry
; RET from 62282 after code that has been input is compared with valid code.
;
; Zero flag set (Z) indicates there's a match - the code is correct. Non-zero
; (NZ) indicates the wrong code has been entered.
  JR Z,L62288_2           ; Jump out here if correct code entered
  CALL L62056             ; Print the following 'wrong code' message text on
                          ; screen. Jump down to 62332 on RETurn after printing
; Wrong code message text:
  DEFB 13,13              ; Codes for ENTER x 2 (move two lines down)
  DEFM "    That is wrong - one more try"
  DEFB 255                ; End-of-message marker
; Pause for a few seconds:
  LD DE,10                ; Set outer loop counter (10)
  LD HL,0                 ; Set inner loop counter (65536)
; Pause loop:
L62288_0:
  DEC DE                  ; Outer loop - decrement DE counter
L62288_1:
  DEC HL                  ; Inner loop - decrement HL counter
  LD A,H                  ; Has inner loop counter reached zero?
  OR L                    ;
  JR NZ,L62288_1          ; If not, continue to decrement inner loop counter
  DEC DE                  ; Decrement outer loop counter
  LD A,D                  ; Has outer loop counter reached zero?
  OR E                    ;
  JR NZ,L62288_0          ; If not, continue to decrement both counters
  CALL L62102_0           ; Give the player another chance to enter the right
                          ; code
  JP NZ,0                 ; ...This time if there's no match, reset the
                          ; computer.
; Correct code has been entered
L62288_2:
  POP BC                  ; Retrieve the number-of-codes-entered counter
  DJNZ L62288             ; Decrement and continue code generation and entry
                          ; for 3 iterations
  JP L48922               ; 3 codes have been correctly entered. Jump to
                          ; initialize the game.

; Unused
L62361:
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0

; Unused
L64000:
  DEFB 0,250,255,221,33,159,97,17
  DEFB 77,152,62,255,55,20,8,21
  DEFB 243,33,0,0,195,97,5,251
  DEFB 207,255,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0

; Unencrypt all LOADed game data
;
; Used by the routine at L23820.
;
; The code here was copied at L23820 after the first tape data block was loaded
; - the first part here is a copy of this.
;
; Avalon's data (as stored on tape) is encrypted using a simple algorithm.
;
; The game memory from L25001 to L64000 is unencrypted in the instructions from
; 65023.
L65000:
  LD SP,65530             ; Put the stack pointer (nearly) at the top of RAM
  LD IX,L25001            ; IX = address pointer at start of data block to LOAD
  LD DE,39000             ; Data block length (code up to RAM address 64000)
  LD A,255                ; Indicates a data block to load (rather than header)
  SCF                     ; Sets the carry flag, which tells the ROM routine to
                          ; perform a LOAD
; The next 4 instructions are in the ROM loading routine just before 1377,
; executed here just before the jump there at 65020 (as it's not loading a
; header block)
  INC D
  EX AF,AF'
  DEC D
  DI
  LD HL,65023             ; This is the address that the code in the following
                          ; instructions (starting from 65023) will be at after
                          ; the copy at the start of this routine.
  JP 1377                 ; Launch the ROM loading routine
; Unencrypt all game code and data. A reverse encoding of this would've been
; done before the data was saved to tape.
  LD HL,L25001            ; Start address
  LD DE,39000             ; Number of bytes to work through
; Unencryption loop:
L65000_0:
  LD A,(HL)               ; Get byte
  XOR %01100110           ; XOR to reverse the bits
  RRCA                    ; Rotate right/divide by 2
  XOR L                   ; A second XOR to reverse the bytes, using the low
                          ; byte of the address pointer
  LD (HL),A               ; Re-store the unencrypted byte into memory
  INC HL                  ; Move to the next memory address
  DEC DE                  ; Decrement the number-of-bytes counter
  LD A,D                  ; Check for zero
  OR E                    ;
  JR NZ,L65000_0          ; If not, continue to unencrypt the data
; Data in memory is now unpacked/unencrypted
  LD A,2
  LD (23659),A            ; Enable screen character rows 22 & 23 for
                          ; INPUT/errors
  EI                      ; Enable interrupts
  JP L62283               ; Jump to the code input routine
; Unused data
  DEFB 32,32,32,32,32,32,32,32
  DEFB 32,32

; Unused
L65060:
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,0,0,0,0
  DEFB 0,0,0,0,243,13,206,11
  DEFB 227,80,206,11,219,2,77,0
  DEFB 44,79,0,128,0,0,240,185
  DEFB 10,15,177,51,139,93,106,50
  DEFB 155,54,101,51,183,45,139,93
  DEFB 134,93,248,92,43,45,101,51
  DEFB 178,162,237,16,13,0,9,0
  DEFB 133,28,140,128,3,124,39,191
  DEFB 51,191,0,62,0,60,66,66
  DEFB 126,66,66,0,0,124,66,124
  DEFB 66,66,124,0,0,60,66,64
  DEFB 64,66,60,0,0,120,68,66
  DEFB 66,68,120,0,0,126,64,124
  DEFB 64,64,126,0,0,126,64,124
  DEFB 64,64,64,0,0,60,66,64
  DEFB 78,66,60,0,0,66,66,126

  DEFB 66,66,66,0,0,62,8,8
  DEFB 8,8,62,0,0,2,2,2
  DEFB 66,66,60,0,0,68,72,112
  DEFB 72,68,66,0,0,64,64,64
  DEFB 64,64,126,0,0,66,102,90
  DEFB 66,66,66,0,0,66,98,82
  DEFB 74,70,66,0,0,60,66,66
  DEFB 66,66,60,0,0,124,66,66
  DEFB 124,64,64,0,0,60,219,2
  DEFB 219,2,219,2,77,0,192,83
  DEFB 63,0,6,3,206,11,81,72
  DEFB 16,14,220,10,254,21,88,39
  DEFB 58,243,84,243,129,1,66,66
  DEFB 66,66,60,0

