; 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 5D1A, to near the top of RAM
; (LFDE8)
L5D0C:
  LD HL,$5D1A
  LD DE,LFDE8
  LD BC,$003C             ; 60 bytes of code to copy
  LDIR                    ; Copy the code
  JP LFDE8                ; ...now jump there and execute the code
; Start of code that is copied to LFDE8
  LD SP,$FFFA             ; Put the stack pointer (nearly) at the top of RAM
  LD IX,L61A9             ; IX = address pointer at start of data block to LOAD
  LD DE,$9858             ; Data block length (code up to RAM address 64000)
  LD A,$FF                ; 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 5D2E (as it's loading data, not a
; header block).
  INC D
  EX AF,AF'
  DEC D
  DI
  LD HL,$FDFF             ; This is the address that the code in the following
                          ; instructions (starting from 5D31) will be at after
                          ; the copy at the start of this routine.
  JP $0561                ; Launch the ROM loading routine
; The following code is copied to FDFF and is executed from there once the game
; has loaded (see this address for disassembly).
  LD HL,L61A9
  LD DE,$9858
L5D0C_0:
  LD A,(HL)
  XOR $66
  RRCA
  XOR L
  LD (HL),A
  INC HL
  DEC DE
  LD A,D
  OR E
  JR NZ,L5D0C_0
  LD A,$02
  LD ($5C6B),A
  EI
  JP LF34B

; Unused
L5D4C:
  DEFB $20,$20,$20,$20,$20,$20,$20,$20
  DEFB $20,$20,$20,$20,$20,$20,$20,$20
  DEFB $20,$20,$20,$20,$20,$20,$20,$20
  DEFB $20,$20,$20,$20,$20,$20,$20,$20
  DEFB $E1,$00,$00,$48,$5D,$00,$00,$00
  DEFB $5C,$5D,$00,$00,$00,$01,$00,$00
  DEFB $E8,$03,$02,$78,$00,$00,$D2,$00
  DEFB $00,$80,$EF,$22,$22,$0D,$80,$00
  DEFB $00,$F8,$5C,$00,$00,$00,$00,$00
  DEFB $00,$00,$06,$7E,$F8,$CF,$00,$00
  DEFB $03,$20,$20,$20,$20,$20,$20,$20
  DEFB $20,$20,$20,$1A,$00,$00,$FA,$80
  DEFB $80,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00

; 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 LC15A.
;
; * 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 L6790
; * Final byte = 255 (end of this room data set)
L61A9:
  DEFB $05,$00,$40,$01,$FF ; 1 - Room 1 - starting room
  DEFB $09,$42,$40,$40,$01,$02,$03,$FF ; 2
  DEFB $0A,$12,$84,$40,$04,$05,$02,$FF ; 3
  DEFB $06,$11,$00,$05,$0A,$FF ; 4
  DEFB $09,$42,$40,$40,$03,$06,$07,$FF ; 5
  DEFB $08,$42,$24,$06,$08,$FF ; 6
  DEFB $07,$01,$04,$08,$09,$FF ; 7
  DEFB $06,$40,$00,$09,$FF ; 8
  DEFB $08,$10,$41,$0C,$0B,$12,$FF ; 9
  DEFB $06,$04,$10,$0C,$0D,$FF ; 10
  DEFB $06,$4A,$10,$0D,$0E,$FF ; 11
  DEFB $06,$44,$40,$0E,$0F,$14,$FF ; 12
  DEFB $08,$12,$11,$0F,$11,$10,$FF ; 13
  DEFB $06,$40,$00,$11,$FF ; 14
  DEFB $06,$41,$00,$10,$13,$FF ; 15
  DEFB $08,$40,$40,$13,$12,$FF ; 16
  DEFB $06,$11,$10,$15,$17,$16,$FF ; 17
  DEFB $0A,$41,$14,$00,$16,$18,$19,$1A ; 18
  DEFB $FF                             ;
  DEFB $06,$40,$00,$18,$FF ; 19
  DEFB $06,$40,$00,$19,$FF ; 20
  DEFB $06,$10,$00,$1A,$FF ; 21
  DEFB $0A,$44,$22,$10,$1D,$1B,$17,$FF ; 22
  DEFB $08,$00,$41,$1E,$1B,$FF ; 23
  DEFB $06,$11,$00,$1E,$1C,$FF ; 24
  DEFB $06,$40,$10,$1F,$20,$FF ; 25
  DEFB $06,$44,$40,$20,$21,$22,$FF ; 26
  DEFB $06,$10,$00,$21,$FF ; 27
  DEFB $06,$10,$10,$22,$23,$FF ; 28
  DEFB $09,$42,$10,$00,$24,$23,$FF ; 29
  DEFB $08,$44,$45,$25,$26,$27,$FE,$28 ; 30
  DEFB $FF                             ;
  DEFB $08,$52,$01,$2B,$2A,$2C,$FF ; 31
  DEFB $0A,$40,$40,$10,$2C,$29,$2D,$FF ; 32
  DEFB $0B,$40,$A0,$14,$2D,$2B,$2E,$FF ; 33
  DEFB $09,$11,$10,$40,$30,$32,$33,$34 ; 34
  DEFB $FF                             ;
  DEFB $06,$10,$40,$33,$35,$FF ; 35
  DEFB $06,$11,$10,$35,$36,$37,$FF ; 36
  DEFB $08,$41,$11,$37,$38,$39,$3A,$FF ; 37
  DEFB $06,$10,$00,$39,$FF ; 38
  DEFB $06,$10,$00,$38,$FF ; 39
  DEFB $06,$10,$00,$36,$FF ; 40
  DEFB $07,$01,$00,$32,$FF ; 41
  DEFB $10,$08,$12,$10,$40,$40,$3D,$3C ; 42
  DEFB $FF                             ;
  DEFB $06,$01,$10,$3B,$3C,$FF ; 43
  DEFB $08,$40,$41,$40,$42,$41,$FF ; 44
  DEFB $06,$10,$10,$3E,$3F,$FF ; 45
  DEFB $10,$00,$04,$01,$00,$3F,$41,$FF ; 46
  DEFB $06,$40,$40,$3D,$3E,$FF ; 47
  DEFB $0B,$01,$10,$10,$49,$48,$44,$FF ; 48
  DEFB $09,$41,$14,$00,$43,$44,$45,$46 ; 49
  DEFB $FF                             ;
  DEFB $0B,$12,$28,$10,$46,$4A,$FF ; 50
  DEFB $09,$10,$41,$00,$4A,$4C,$4D,$FF ; 51
  DEFB $07,$44,$00,$4B,$4C,$FF ; 52
  DEFB $06,$40,$10,$45,$47,$FF ; 53
  DEFB $09,$41,$10,$00,$47,$48,$49,$FF ; 54
  DEFB $06,$40,$00,$69,$FF ; 55
  DEFB $0F,$44,$10,$A0,$04,$4F,$50,$69 ; 56
  DEFB $58,$FF                         ;
  DEFB $08,$44,$40,$58,$59,$5F,$FF ; 57
  DEFB $06,$40,$10,$51,$50,$FF ; 58
  DEFB $08,$51,$01,$52,$53,$54,$51,$FF ; 59
  DEFB $08,$4A,$A4,$55,$52,$FF ; 60
  DEFB $07,$00,$04,$55,$FF ; 61
  DEFB $08,$10,$A1,$56,$53,$FF ; 62
  DEFB $07,$00,$10,$56,$FF ; 63
  DEFB $07,$12,$04,$5F,$60,$FF ; 64
  DEFB $06,$40,$40,$60,$61,$FF ; 65
  DEFB $08,$00,$11,$61,$62,$FF ; 66
  DEFB $0A,$44,$04,$00,$64,$63,$62,$FF ; 67
  DEFB $08,$18,$80,$63,$FF ; 68
  DEFB $06,$02,$10,$64,$FF ; 69
  DEFB $06,$10,$40,$59,$5A,$FF ; 70
  DEFB $07,$10,$40,$5A,$5B,$FF ; 71
  DEFB $06,$40,$40,$54,$57,$FF ; 72
  DEFB $0B,$04,$21,$00,$5E,$5C,$FF ; 73
  DEFB $06,$44,$10,$5B,$5C,$5D,$FF ; 74
  DEFB $07,$40,$00,$5D,$FF ; 75
  DEFB $06,$40,$00,$5E,$FF ; 76
  DEFB $0B,$40,$48,$00,$57,$65,$FF ; 77
  DEFB $08,$42,$41,$65,$66,$67,$FF ; 78
  DEFB $07,$01,$00,$67,$FF ; 79
  DEFB $08,$1A,$10,$68,$66,$FF ; 80
  DEFB $08,$08,$10,$68,$FF ; 81
  DEFB $10,$02,$08,$8A,$01,$2F,$FF ; 82
  DEFB $08,$01,$21,$70,$00,$FF ; 83
  DEFB $0A,$41,$24,$10,$70,$71,$72,$73 ; 84
  DEFB $FF                             ;
  DEFB $08,$42,$40,$74,$73,$FF ; 85
  DEFB $08,$01,$A1,$74,$75,$FF ; 86
  DEFB $06,$40,$40,$75,$76,$FF ; 87
  DEFB $06,$10,$10,$76,$77,$FF ; 88
  DEFB $06,$41,$00,$77,$78,$FF ; 89
  DEFB $08,$41,$81,$78,$79,$00,$FF ; 90
  DEFB $08,$02,$24,$79,$FF ; 91
  DEFB $06,$40,$40,$6A,$6B,$FF ; 92
  DEFB $0A,$12,$24,$10,$6B,$6C,$6D,$FF ; 93
  DEFB $07,$12,$10,$6D,$6E,$FF ; 94
  DEFB $07,$4A,$04,$6E,$6F,$FF ; 95
  DEFB $09,$02,$88,$40,$7A,$FF ; 96
  DEFB $08,$42,$10,$7A,$7B,$FF ; 97
  DEFB $09,$40,$44,$00,$7E,$7D,$7B,$FF ; 98
  DEFB $08,$40,$04,$7C,$7D,$FF ; 99
  DEFB $06,$10,$10,$7F,$7E,$FF ; 100
  DEFB $06,$01,$40,$80,$7F,$FF ; 101
  DEFB $08,$42,$84,$80,$81,$FF ; 102
  DEFB $06,$10,$10,$81,$82,$FF ; 103
  DEFB $08,$42,$00,$A3,$FF ; 104
  DEFB $06,$40,$10,$88,$89,$FF ; 105
  DEFB $08,$01,$11,$87,$86,$88,$FF ; 106
  DEFB $07,$42,$04,$86,$85,$FF ; 107
  DEFB $07,$40,$80,$85,$FF ; 108
  DEFB $0A,$42,$84,$40,$87,$83,$84,$FF ; 109
  DEFB $06,$10,$00,$84,$FF ; 110
  DEFB $08,$42,$05,$8A,$8C,$8B,$FF ; 111
  DEFB $07,$40,$04,$8C,$8D,$FF ; 112
  DEFB $08,$18,$81,$8B,$A6,$FF ; 113
  DEFB $06,$40,$10,$A6,$8E,$FF ; 114
  DEFB $06,$40,$00,$9C,$FF ; 115
  DEFB $07,$41,$04,$95,$94,$9C,$FF ; 116
  DEFB $08,$01,$11,$95,$96,$97,$FF ; 117
  DEFB $06,$40,$40,$97,$98,$FF ; 118
  DEFB $08,$41,$04,$99,$98,$9A,$FF ; 119
  DEFB $06,$10,$00,$9A,$FF ; 120
  DEFB $08,$42,$44,$9D,$9B,$96,$FF ; 121
  DEFB $07,$01,$00,$9B,$FF ; 122
  DEFB $06,$10,$10,$92,$93,$FF ; 123
  DEFB $06,$10,$00,$90,$FF ; 124
  DEFB $07,$40,$44,$8F,$90,$91,$FF ; 125
  DEFB $07,$42,$10,$91,$92,$FF ; 126
  DEFB $08,$01,$11,$A0,$9F,$9E,$FF ; 127
  DEFB $08,$02,$84,$A5,$FF ; 128
  DEFB $06,$10,$10,$A5,$A4,$FF ; 129
  DEFB $07,$40,$10,$A4,$A2,$FF ; 130
  DEFB $07,$10,$04,$A2,$A1,$FF ; 131
  DEFB $06,$40,$40,$A1,$A0,$FF ; 132
  DEFB $09,$10,$80,$40,$9F,$A3,$FF ; 133
  DEFB $06,$11,$00,$AE,$AF,$FF ; 134
  DEFB $07,$12,$10,$AD,$AE,$FF ; 135
  DEFB $06,$01,$10,$AD,$AC,$FF ; 136
  DEFB $07,$10,$84,$AC,$A9,$FF ; 137
  DEFB $06,$50,$40,$AA,$A9,$A8,$FF ; 138
  DEFB $07,$40,$10,$AB,$AA,$FF ; 139
  DEFB $06,$00,$10,$C0,$FF ; 140
  DEFB $07,$41,$00,$C0,$BF,$FF ; 141
  DEFB $09,$01,$21,$00,$BE,$BC,$FF ; 142
  DEFB $08,$44,$10,$BD,$BE,$BF,$FF ; 143
  DEFB $0C,$02,$28,$40,$C2,$FF ; 144
  DEFB $06,$10,$40,$C2,$C1,$FF ; 145
  DEFB $08,$44,$11,$B2,$B3,$B1,$B0,$FF ; 146
  DEFB $07,$42,$04,$B1,$B5,$FF ; 147
  DEFB $07,$40,$14,$B5,$B7,$B6,$FF ; 148
  DEFB $06,$10,$10,$B6,$B8,$FF ; 149
  DEFB $06,$40,$00,$B8,$FF ; 150
  DEFB $07,$42,$04,$B7,$B9,$FF ; 151
  DEFB $06,$40,$00,$B9,$FF ; 152
  DEFB $07,$10,$10,$B3,$B4,$FF ; 153
  DEFB $06,$10,$00,$B4,$FF ; 154
  DEFB $09,$42,$A4,$00,$BA,$B2,$FF ; 155
  DEFB $07,$01,$04,$BA,$BB,$FF ; 156
  DEFB $09,$42,$20,$00,$BB,$FF ; 157
  DEFB $09,$00,$41,$00,$C3,$C4,$FF ; 158
  DEFB $07,$10,$04,$C4,$C5,$FF ; 159
  DEFB $07,$11,$00,$C6,$C5,$FF ; 160
  DEFB $07,$44,$04,$C9,$C6,$C8,$FF ; 161
  DEFB $08,$42,$81,$CA,$C9,$FF ; 162
  DEFB $07,$40,$04,$CB,$CA,$FF ; 163
  DEFB $06,$44,$00,$C8,$C7,$FF ; 164
  DEFB $07,$12,$00,$C7,$FF ; 165
  DEFB $08,$01,$11,$CB,$CF,$CE,$FF ; 166
  DEFB $07,$42,$00,$CF,$FF ; 167
  DEFB $08,$04,$41,$CD,$CE,$D0,$FF ; 168
  DEFB $08,$4A,$21,$CC,$CD,$FF ; 169
  DEFB $07,$01,$00,$CC,$FF ; 170
  DEFB $07,$40,$10,$D0,$D1,$FF ; 171
  DEFB $07,$10,$10,$D1,$D3,$FF ; 172
  DEFB $09,$04,$10,$40,$D5,$D3,$D2,$FF ; 173
  DEFB $07,$12,$04,$D4,$D5,$FF ; 174
  DEFB $06,$00,$40,$D4,$FF ; 175
  DEFB $08,$01,$11,$DC,$DB,$D8,$FF ; 176
  DEFB $07,$41,$04,$D8,$DA,$D7,$FF ; 177
  DEFB $08,$40,$41,$D7,$D9,$D6,$FF ; 178
  DEFB $07,$01,$04,$D9,$DD,$FF ; 179
  DEFB $08,$40,$40,$DD,$DA,$FF ; 180
  DEFB $0A,$40,$10,$00,$DF,$DE,$FF ; 181
  DEFB $10,$10,$44,$44,$41,$E1,$E6,$E5 ; 182
  DEFB $E4,$E3,$E2,$E0,$FF             ;
  DEFB $07,$10,$00,$E6,$FF ; 183
  DEFB $07,$10,$00,$E5,$FF ; 184
  DEFB $07,$10,$00,$E4,$FF ; 185
  DEFB $07,$10,$00,$E3,$FF ; 186
  DEFB $07,$10,$00,$E2,$FF ; 187
  DEFB $07,$02,$04,$E8,$FF ; 188
  DEFB $0C,$41,$10,$41,$E8,$EB,$EA,$E9 ; 189
  DEFB $E7,$FF                         ;
  DEFB $08,$42,$20,$E7,$FF ; 190
  DEFB $06,$10,$10,$EB,$F0,$FF ; 191
  DEFB $06,$40,$10,$F0,$EF,$FF ; 192
  DEFB $08,$12,$81,$EA,$EE,$FF ; 193
  DEFB $06,$40,$10,$E9,$EC,$FF ; 194
  DEFB $06,$40,$40,$EC,$ED,$FF ; 195
  DEFB $06,$00,$10,$F1,$FF ; 196
  DEFB $06,$40,$40,$F1,$F2,$FF ; 197
  DEFB $06,$10,$10,$F2,$F3,$FF ; 198
  DEFB $06,$41,$10,$F3,$F7,$F4,$FF ; 199
  DEFB $06,$40,$10,$F4,$F5,$FF ; 200
  DEFB $06,$40,$40,$F5,$F6,$FF ; 201
  DEFB $06,$41,$00,$F7,$F8,$FF ; 202
  DEFB $06,$44,$40,$FA,$F9,$F8,$FF ; 203
  DEFB $06,$10,$10,$FB,$FA,$FF ; 204
  DEFB $06,$00,$40,$FB,$FF ; 205
  DEFB $06,$41,$10,$FC,$F9,$FD,$FF ; 206
  DEFB $06,$40,$10,$FD,$A7,$FF ; 207
  DEFB $06,$40,$00,$A7,$FF ; 208
  DEFB $06,$0A,$10,$FC,$FF ; 209
  DEFB $0A,$1A,$A1,$00,$2F,$31,$FF ; 210
  DEFB $0F,$04,$22,$88,$10,$31,$4E,$FF ; 211
  DEFB $0D,$12,$28,$A0,$00,$4E,$FF ; 212
; The following are placeholders and not used. See Trivia: Unused rooms
  DEFB $05,$00,$00,$FF    ; 213
  DEFB $05,$00,$00,$FF    ; 214
  DEFB $05,$00,$00,$FF    ; 215
  DEFB $05,$00,$00,$FF    ; 216
  DEFB $05,$00,$00,$FF    ; 217
  DEFB $05,$00,$00,$FF    ; 218
  DEFB $05,$00,$00,$FF    ; 219
  DEFB $05,$00,$00,$FF    ; 220
  DEFB $05,$00,$00,$FF    ; 221
  DEFB $05,$00,$00,$FF    ; 222
  DEFB $05,$00,$00,$FF    ; 223

; Room data - vertical tunnel sections
;
; Data for the vertical tunnel sections. Used in the routines starting at
; LC5B5.
;
; 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 L6790) |
; | 3    | Connecting door set 2 (from table at L6790) |
; | 4    | 255 = end of data                           |
; +------+---------------------------------------------+
L6710:
  DEFB $10,$FE,$ED,$FF    ; 224
  DEFB $0A,$DE,$4F,$FF    ; 225
  DEFB $01,$E1,$F6,$FF    ; 226
  DEFB $01,$E0,$EE,$FF    ; 227
  DEFB $07,$D2,$EF,$FF    ; 228
  DEFB $04,$C3,$DB,$FF    ; 229
  DEFB $05,$DC,$DF,$FF    ; 230
  DEFB $06,$4D,$D6,$FF    ; 231
  DEFB $03,$BC,$C1,$FF    ; 232
  DEFB $03,$AF,$B0,$FF    ; 233
  DEFB $01,$BD,$AB,$FF    ; 234
  DEFB $06,$A8,$34,$FF    ; 235
  DEFB $03,$3A,$3B,$FF    ; 236
  DEFB $03,$42,$43,$FF    ; 237
  DEFB $03,$2E,$4B,$FF    ; 238
  DEFB $02,$2A,$30,$FF    ; 239
  DEFB $08,$29,$6C,$FF    ; 240
  DEFB $05,$8A,$9E,$FF    ; 241
  DEFB $01,$99,$8E,$FF    ; 242
  DEFB $02,$8D,$8F,$FF    ; 243
  DEFB $01,$9D,$93,$FF    ; 244
  DEFB $02,$89,$94,$FF    ; 245
  DEFB $03,$6F,$82,$FF    ; 246
  DEFB $02,$72,$7C,$FF    ; 247
  DEFB $04,$28,$6A,$FF    ; 248
  DEFB $04,$27,$71,$FF    ; 249
  DEFB $02,$25,$83,$FF    ; 250
  DEFB $06,$1C,$26,$FF    ; 251
  DEFB $04,$07,$0B,$FF    ; 252
  DEFB $02,$14,$1F,$FF    ; 253
  DEFB $03,$24,$1D,$FF    ; 254
  DEFB $02,$04,$15,$FF    ; 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 DAF5.
;
; +------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
; | Byte                                                                                                                                                       | Value                                                                                                                                   |
; +------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
; | 1                                                                                                                                                          | Connecting room number 1                                                                                                                |
; | 2                                                                                                                                                          | Connecting room number 2                                                                                                                |
; | 3                                                                                                                                                          | Door properties byte (from EB4E) #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 CA75 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 L61A9, 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 679C
; * Similarly, the door connecting room 5 and room 6 is at 67A8
L6790:
  DEFB $53,$5A,%00000101,$01 ; Connecting door set 0
  DEFB $01,$02,%00000101,$01 ; Connecting door set 1
  DEFB $02,$03,%00000101,$01 ; Connecting door set 2
  DEFB $02,$05,%00000101,$00 ; Connecting door set 3
  DEFB $03,$FF,%00000101,$01 ; Connecting door set 4
  DEFB $03,$04,%00000101,$00 ; Connecting door set 5
  DEFB $05,$06,%00000101,$00 ; Connecting door set 6
  DEFB $05,$FC,%00000101,$00 ; Connecting door set 7
  DEFB $06,$07,%00000101,$00 ; Connecting door set 8
  DEFB $07,$08,%00000101,$00 ; Connecting door set 9
  DEFB $04,$00,%00000101,$0F ; Connecting door set 10
  DEFB $09,$FC,%00000101,$00 ; Connecting door set 11
  DEFB $09,$0A,%00000101,$00 ; Connecting door set 12
  DEFB $0A,$0B,%00001101,$00 ; Connecting door set 13
  DEFB $0B,$0C,%00000101,$00 ; Connecting door set 14
  DEFB $0C,$0D,%00000101,$00 ; Connecting door set 15
  DEFB $0D,$0F,%00000101,$00 ; Connecting door set 16
  DEFB $0D,$0E,%00001101,$00 ; Connecting door set 17
  DEFB $09,$10,%00000101,$01 ; Connecting door set 18
  DEFB $0F,$10,%00000101,$00 ; Connecting door set 19
  DEFB $0C,$FD,%00000010,$00 ; Connecting door set 20
  DEFB $11,$FF,%00000101,$00 ; Connecting door set 21
  DEFB $11,$12,%00000101,$00 ; Connecting door set 22
  DEFB $11,$16,%00000101,$00 ; Connecting door set 23
  DEFB $12,$13,%00001101,$00 ; Connecting door set 24
  DEFB $12,$14,%00000101,$00 ; Connecting door set 25
  DEFB $12,$15,%00000101,$00 ; Connecting door set 26
  DEFB $16,$17,%00000101,$01 ; Connecting door set 27
  DEFB $18,$FB,%00000101,$0C ; Connecting door set 28
  DEFB $16,$FE,%00000101,$00 ; Connecting door set 29
  DEFB $17,$18,%00000101,$00 ; Connecting door set 30
  DEFB $19,$FD,%00000101,$00 ; Connecting door set 31
  DEFB $19,$1A,%00001101,$01 ; Connecting door set 32
  DEFB $1A,$1B,%00000101,$00 ; Connecting door set 33
  DEFB $1A,$1C,%00000101,$00 ; Connecting door set 34
  DEFB $1C,$1D,%00000010,$00 ; Connecting door set 35
  DEFB $1D,$FE,%00000101,$00 ; Connecting door set 36
  DEFB $1E,$FA,%00000101,$00 ; Connecting door set 37
  DEFB $1E,$FB,%00000101,$01 ; Connecting door set 38
  DEFB $1E,$F9,%00000101,$00 ; Connecting door set 39
  DEFB $1E,$F8,%00000101,$00 ; Connecting door set 40
  DEFB $20,$F0,%00000101,$00 ; Connecting door set 41
  DEFB $1F,$EF,%00000101,$00 ; Connecting door set 42
  DEFB $1F,$21,%00000101,$00 ; Connecting door set 43
  DEFB $1F,$20,%00000101,$01 ; Connecting door set 44
  DEFB $20,$21,%00000101,$00 ; Connecting door set 45
  DEFB $21,$EE,%00000101,$00 ; Connecting door set 46
  DEFB $D2,$52,%00000101,$00 ; Connecting door set 47
  DEFB $22,$EF,%00000101,$01 ; Connecting door set 48
  DEFB $D2,$D3,%00000101,$00 ; Connecting door set 49
  DEFB $22,$29,%00000101,$00 ; Connecting door set 50
  DEFB $22,$23,%00000101,$00 ; Connecting door set 51
  DEFB $22,$EB,%00000101,$01 ; Connecting door set 52
  DEFB $23,$24,%00001101,$00 ; Connecting door set 53
  DEFB $24,$28,%00000101,$1C ; Connecting door set 54
  DEFB $24,$25,%00000101,$00 ; Connecting door set 55
  DEFB $25,$27,%00000101,$1C ; Connecting door set 56
  DEFB $25,$26,%00000101,$00 ; Connecting door set 57
  DEFB $25,$EC,%00000101,$00 ; Connecting door set 58
  DEFB $2B,$EC,%00000101,$00 ; Connecting door set 59
  DEFB $2A,$2B,%00000101,$00 ; Connecting door set 60
  DEFB $2A,$2F,%00001101,$00 ; Connecting door set 61
  DEFB $2D,$2F,%00000101,$00 ; Connecting door set 62
  DEFB $2D,$2E,%00000101,$00 ; Connecting door set 63
  DEFB $2A,$2C,%00000101,$00 ; Connecting door set 64
  DEFB $2C,$2E,%00001101,$00 ; Connecting door set 65
  DEFB $2C,$ED,%00000101,$00 ; Connecting door set 66
  DEFB $31,$ED,%00000101,$00 ; Connecting door set 67
  DEFB $30,$31,%00000101,$00 ; Connecting door set 68
  DEFB $31,$35,%00000101,$00 ; Connecting door set 69
  DEFB $31,$32,%00001101,$00 ; Connecting door set 70
  DEFB $35,$36,%00001101,$00 ; Connecting door set 71
  DEFB $30,$36,%00001101,$00 ; Connecting door set 72
  DEFB $30,$36,%00000101,$00 ; Connecting door set 73
  DEFB $32,$33,%00000101,$28 ; Connecting door set 74
  DEFB $34,$EE,%00000101,$00 ; Connecting door set 75
  DEFB $33,$34,%00000101,$28 ; Connecting door set 76
  DEFB $33,$E7,%00000101,$00 ; Connecting door set 77
  DEFB $D3,$D4,%00000101,$00 ; Connecting door set 78
  DEFB $38,$E1,%00001101,$00 ; Connecting door set 79
  DEFB $38,$3A,%00001101,$00 ; Connecting door set 80
  DEFB $3A,$3B,%00000101,$00 ; Connecting door set 81
  DEFB $3B,$3C,%00001101,$00 ; Connecting door set 82
  DEFB $3B,$3E,%00000101,$00 ; Connecting door set 83
  DEFB $3B,$48,%00000101,$00 ; Connecting door set 84
  DEFB $3C,$3D,%00000101,$00 ; Connecting door set 85
  DEFB $3E,$3F,%00000101,$00 ; Connecting door set 86
  DEFB $48,$4D,%00000101,$00 ; Connecting door set 87
  DEFB $38,$39,%00000101,$20 ; Connecting door set 88
  DEFB $39,$46,%00000101,$00 ; Connecting door set 89
  DEFB $46,$47,%00000101,$00 ; Connecting door set 90
  DEFB $47,$4A,%00000010,$01 ; Connecting door set 91
  DEFB $49,$4A,%00001101,$00 ; Connecting door set 92
  DEFB $4A,$4B,%00000101,$00 ; Connecting door set 93
  DEFB $49,$4C,%00000101,$00 ; Connecting door set 94
  DEFB $39,$40,%00000101,$00 ; Connecting door set 95
  DEFB $40,$41,%00000101,$00 ; Connecting door set 96
  DEFB $41,$42,%00001101,$00 ; Connecting door set 97
  DEFB $42,$43,%00000101,$00 ; Connecting door set 98
  DEFB $43,$44,%00000101,$00 ; Connecting door set 99
  DEFB $43,$45,%00001010,$00 ; Connecting door set 100
  DEFB $4D,$4E,%00000101,$00 ; Connecting door set 101
  DEFB $4E,$50,%00000101,$00 ; Connecting door set 102
  DEFB $4E,$4F,%00000101,$00 ; Connecting door set 103
  DEFB $50,$51,%00001101,$00 ; Connecting door set 104
  DEFB $37,$38,%00000101,$00 ; Connecting door set 105
  DEFB $5C,$F8,%00000101,$00 ; Connecting door set 106
  DEFB $5C,$5D,%00000101,$2C ; Connecting door set 107
  DEFB $5D,$F0,%00000101,$00 ; Connecting door set 108
  DEFB $5D,$5E,%00000101,$2C ; Connecting door set 109
  DEFB $5E,$5F,%00000101,$00 ; Connecting door set 110
  DEFB $5F,$F6,%00000101,$00 ; Connecting door set 111
  DEFB $53,$54,%00000101,$00 ; Connecting door set 112
  DEFB $54,$F9,%00000101,$02 ; Connecting door set 113
  DEFB $54,$F7,%00000101,$00 ; Connecting door set 114
  DEFB $54,$55,%00000101,$00 ; Connecting door set 115
  DEFB $55,$56,%00000101,$00 ; Connecting door set 116
  DEFB $56,$57,%00000101,$00 ; Connecting door set 117
  DEFB $57,$58,%00000101,$00 ; Connecting door set 118
  DEFB $58,$59,%00000101,$00 ; Connecting door set 119
  DEFB $59,$5A,%00000101,$00 ; Connecting door set 120
  DEFB $5A,$5B,%00001101,$00 ; Connecting door set 121
  DEFB $60,$61,%00001101,$00 ; Connecting door set 122
  DEFB $61,$62,%00000101,$00 ; Connecting door set 123
  DEFB $63,$F7,%00000101,$00 ; Connecting door set 124
  DEFB $62,$63,%00001101,$00 ; Connecting door set 125
  DEFB $62,$64,%00000101,$00 ; Connecting door set 126
  DEFB $64,$65,%00000101,$00 ; Connecting door set 127
  DEFB $65,$66,%00000101,$00 ; Connecting door set 128
  DEFB $66,$67,%00000101,$00 ; Connecting door set 129
  DEFB $67,$F6,%00000010,$00 ; Connecting door set 130
  DEFB $6D,$FA,%00000101,$00 ; Connecting door set 131
  DEFB $6D,$6E,%00000101,$00 ; Connecting door set 132
  DEFB $6B,$6C,%00000101,$00 ; Connecting door set 133
  DEFB $6A,$6B,%00000101,$00 ; Connecting door set 134
  DEFB $6A,$6D,%00000101,$00 ; Connecting door set 135
  DEFB $69,$6A,%00000101,$00 ; Connecting door set 136
  DEFB $69,$F5,%00000101,$00 ; Connecting door set 137
  DEFB $6F,$F1,%00000101,$00 ; Connecting door set 138
  DEFB $6F,$71,%00000101,$00 ; Connecting door set 139
  DEFB $6F,$70,%00001100,$00 ; Connecting door set 140
  DEFB $70,$F3,%00000101,$00 ; Connecting door set 141
  DEFB $72,$F2,%00000101,$00 ; Connecting door set 142
  DEFB $7D,$F3,%00000010,$00 ; Connecting door set 143
  DEFB $7C,$7D,%00000101,$00 ; Connecting door set 144
  DEFB $7D,$7E,%00000101,$00 ; Connecting door set 145
  DEFB $7B,$7E,%00000101,$00 ; Connecting door set 146
  DEFB $7B,$F4,%00000101,$00 ; Connecting door set 147
  DEFB $74,$F5,%00000101,$00 ; Connecting door set 148
  DEFB $74,$75,%00000101,$00 ; Connecting door set 149
  DEFB $75,$79,%00000101,$00 ; Connecting door set 150
  DEFB $75,$76,%00000101,$00 ; Connecting door set 151
  DEFB $76,$77,%00000101,$00 ; Connecting door set 152
  DEFB $77,$F2,%00000010,$00 ; Connecting door set 153
  DEFB $77,$78,%00000101,$00 ; Connecting door set 154
  DEFB $79,$7A,%00000101,$00 ; Connecting door set 155
  DEFB $73,$74,%00000101,$00 ; Connecting door set 156
  DEFB $79,$F4,%00000101,$00 ; Connecting door set 157
  DEFB $7F,$F1,%00000101,$00 ; Connecting door set 158
  DEFB $7F,$85,%00000101,$00 ; Connecting door set 159
  DEFB $7F,$84,%00000101,$01 ; Connecting door set 160
  DEFB $83,$84,%00000101,$00 ; Connecting door set 161
  DEFB $82,$83,%00000101,$00 ; Connecting door set 162
  DEFB $68,$85,%00000101,$0A ; Connecting door set 163
  DEFB $81,$82,%00000101,$00 ; Connecting door set 164
  DEFB $80,$81,%00000101,$0A ; Connecting door set 165
  DEFB $71,$72,%00000101,$00 ; Connecting door set 166
  DEFB $CF,$D0,%00000101,$68 ; Connecting door set 167
  DEFB $8A,$EB,%00001101,$00 ; Connecting door set 168
  DEFB $89,$8A,%00001101,$00 ; Connecting door set 169
  DEFB $8A,$8B,%00001101,$00 ; Connecting door set 170
  DEFB $8B,$EA,%00001101,$00 ; Connecting door set 171
  DEFB $88,$89,%00001101,$00 ; Connecting door set 172
  DEFB $87,$88,%00001101,$00 ; Connecting door set 173
  DEFB $86,$87,%00001101,$00 ; Connecting door set 174
  DEFB $86,$E9,%00001101,$00 ; Connecting door set 175
  DEFB $92,$E9,%00000101,$00 ; Connecting door set 176
  DEFB $92,$93,%00000101,$00 ; Connecting door set 177
  DEFB $92,$9B,%00000101,$00 ; Connecting door set 178
  DEFB $92,$99,%00000101,$00 ; Connecting door set 179
  DEFB $9A,$99,%00000101,$00 ; Connecting door set 180
  DEFB $93,$94,%00000101,$00 ; Connecting door set 181
  DEFB $94,$95,%00000101,$0A ; Connecting door set 182
  DEFB $94,$97,%00000101,$00 ; Connecting door set 183
  DEFB $95,$96,%00000101,$0A ; Connecting door set 184
  DEFB $97,$98,%00000101,$00 ; Connecting door set 185
  DEFB $9B,$9C,%00000101,$00 ; Connecting door set 186
  DEFB $9C,$9D,%00000101,$00 ; Connecting door set 187
  DEFB $8E,$E8,%00000101,$00 ; Connecting door set 188
  DEFB $8F,$EA,%00000101,$00 ; Connecting door set 189
  DEFB $8E,$8F,%00000101,$00 ; Connecting door set 190
  DEFB $8D,$8F,%00001101,$00 ; Connecting door set 191
  DEFB $8C,$8D,%00000101,$00 ; Connecting door set 192
  DEFB $91,$E8,%00000101,$00 ; Connecting door set 193
  DEFB $90,$91,%00000101,$00 ; Connecting door set 194
  DEFB $9E,$E5,%00000101,$00 ; Connecting door set 195
  DEFB $9E,$9F,%00000101,$00 ; Connecting door set 196
  DEFB $9F,$A0,%00000101,$00 ; Connecting door set 197
  DEFB $A0,$A1,%00000101,$01 ; Connecting door set 198
  DEFB $A4,$A5,%00000101,$00 ; Connecting door set 199
  DEFB $A1,$A4,%00000101,$00 ; Connecting door set 200
  DEFB $A1,$A2,%00000101,$00 ; Connecting door set 201
  DEFB $A2,$A3,%00000101,$00 ; Connecting door set 202
  DEFB $A3,$A6,%00000101,$00 ; Connecting door set 203
  DEFB $AA,$A9,%00000101,$00 ; Connecting door set 204
  DEFB $A8,$A9,%00000101,$00 ; Connecting door set 205
  DEFB $A6,$A8,%00000101,$00 ; Connecting door set 206
  DEFB $A6,$A7,%00000101,$00 ; Connecting door set 207
  DEFB $A8,$AB,%00000101,$00 ; Connecting door set 208
  DEFB $AB,$AC,%00000101,$04 ; Connecting door set 209
  DEFB $AD,$E4,%00000101,$00 ; Connecting door set 210
  DEFB $AC,$AD,%00000101,$00 ; Connecting door set 211
  DEFB $AE,$AF,%00000101,$00 ; Connecting door set 212
  DEFB $AD,$AE,%00000101,$00 ; Connecting door set 213
  DEFB $B2,$E7,%00000101,$00 ; Connecting door set 214
  DEFB $B1,$B2,%00000101,$00 ; Connecting door set 215
  DEFB $B0,$B1,%00000101,$00 ; Connecting door set 216
  DEFB $B2,$B3,%00000101,$00 ; Connecting door set 217
  DEFB $B1,$B4,%00000101,$00 ; Connecting door set 218
  DEFB $B0,$E5,%00000101,$00 ; Connecting door set 219
  DEFB $B0,$E6,%00000101,$04 ; Connecting door set 220
  DEFB $B3,$B4,%00000101,$00 ; Connecting door set 221
  DEFB $E1,$B5,%00000101,$54 ; Connecting door set 222
  DEFB $B5,$E6,%00000101,$00 ; Connecting door set 223
  DEFB $B6,$E3,%00000101,$00 ; Connecting door set 224
  DEFB $E2,$B6,%00000101,$60 ; Connecting door set 225
  DEFB $B6,$BB,%00000010,$60 ; Connecting door set 226
  DEFB $B6,$BA,%00000010,$60 ; Connecting door set 227
  DEFB $B6,$B9,%00000010,$00 ; Connecting door set 228
  DEFB $B6,$B8,%00000010,$00 ; Connecting door set 229
  DEFB $B6,$B7,%00000010,$05 ; Connecting door set 230
  DEFB $BD,$BE,%00000101,$00 ; Connecting door set 231
  DEFB $BC,$BD,%00000101,$00 ; Connecting door set 232
  DEFB $BD,$C2,%00000101,$00 ; Connecting door set 233
  DEFB $BD,$C1,%00000101,$00 ; Connecting door set 234
  DEFB $BD,$BF,%00000101,$00 ; Connecting door set 235
  DEFB $C2,$C3,%00000101,$00 ; Connecting door set 236
  DEFB $C3,$E0,%00000101,$00 ; Connecting door set 237
  DEFB $C1,$E3,%00000101,$00 ; Connecting door set 238
  DEFB $C0,$E4,%00000101,$00 ; Connecting door set 239
  DEFB $BF,$C0,%00000101,$00 ; Connecting door set 240
  DEFB $C4,$C5,%00000010,$00 ; Connecting door set 241
  DEFB $C5,$C6,%00000010,$00 ; Connecting door set 242
  DEFB $C6,$C7,%00000101,$01 ; Connecting door set 243
  DEFB $C7,$C8,%00000101,$00 ; Connecting door set 244
  DEFB $C8,$C9,%00000101,$01 ; Connecting door set 245
  DEFB $C9,$E2,%00000101,$00 ; Connecting door set 246
  DEFB $C7,$CA,%00000101,$01 ; Connecting door set 247
  DEFB $CA,$CB,%00000101,$00 ; Connecting door set 248
  DEFB $CB,$CE,%00000010,$00 ; Connecting door set 249
  DEFB $CB,$CC,%00000101,$00 ; Connecting door set 250
  DEFB $CC,$CD,%00000101,$00 ; Connecting door set 251
  DEFB $CE,$D1,%00000101,$00 ; Connecting door set 252
  DEFB $CE,$CF,%00000101,$00 ; Connecting door set 253
  DEFB $1E,$E0,%00000101,$14 ; 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 L736F)
;
; 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 LDA0A copies the byte holding the
; creatures in the room he's leaving (EBB7) into the relevant spot in this
; table.
;
; GATEHOUSE LEVEL:
L6B8C:
  DEFB $00                ; Room 1
  DEFB $00                ; Room 2
  DEFB $00                ; Room 3
  DEFB $20                ; Room 4 - Goblin warrior x 2
  DEFB $00                ; Room 5
  DEFB $00                ; Room 6
  DEFB $30                ; Room 7 - Goblin warrior x 3
  DEFB $00                ; Room 8
  DEFB $10                ; Room 9 - Goblin warrior x 1
  DEFB $00                ; Room 10
  DEFB $00                ; Room 11
  DEFB $00                ; Room 12
  DEFB $00                ; Room 13
  DEFB $20                ; Room 14 - Goblin warrior x 2
  DEFB $00                ; Room 15
  DEFB $00                ; Room 16
  DEFB $00                ; Room 17
  DEFB $10                ; Room 18 - Goblin warrior x 1
  DEFB $80                ; Room 19 - Guardian of chaos x 2
  DEFB $00                ; Room 20
  DEFB $00                ; Room 21
  DEFB $00                ; Room 22
  DEFB $20                ; Room 23 - Goblin warrior x 2
  DEFB $01                ; Room 24 - Wraith x 1
  DEFB $10                ; Room 25 - Goblin warrior x 1
  DEFB $00                ; Room 26
  DEFB $20                ; Room 27 - Goblin warrior x 2
  DEFB $00                ; Room 28
  DEFB $10                ; Room 29 - Goblin warrior x 1
  DEFB $00                ; Room 30
; GREAT HALLS OF THE DEEP
  DEFB $00                ; Room 31
  DEFB $40                ; Room 32 - Guardian of chaos x 1
  DEFB $80                ; Room 33 - Guardian of chaos x 2
  DEFB $00                ; Room 34
  DEFB $44                ; Room 35 - Guardian of chaos x 1, Goblin missile
                          ; thrower x 1
  DEFB $00                ; Room 36
  DEFB $00                ; Room 37
  DEFB $40                ; Room 38 - Guardian of chaos x 1
  DEFB $00                ; Room 39
  DEFB $00                ; Room 40
  DEFB $01                ; Room 41 - Wraith x 1
  DEFB $00                ; Room 42
  DEFB $00                ; Room 43
  DEFB $10                ; Room 44 - Goblin warrior x 1
  DEFB $00                ; Room 45
  DEFB $20                ; Room 46 - Goblin warrior x 2
  DEFB $40                ; Room 47 - Guardian of chaos x 1
  DEFB $20                ; Room 48
  DEFB $00                ; Room 49 - Goblin warrior x 2
  DEFB $00                ; Room 50
  DEFB $00                ; Room 51
  DEFB $40                ; Room 52 - Guardian of chaos x 1
  DEFB $00                ; Room 53
  DEFB $80                ; Room 54 - Guardian of chaos x 2
; CHAMBERS OF CHAOS
  DEFB $01                ; Room 55 - Wraith x 1
  DEFB $00                ; Room 56
  DEFB $00                ; Room 57
  DEFB $00                ; Room 58
  DEFB $00                ; Room 59
  DEFB $0C                ; Room 60 - Goblin missile thrower x 3
  DEFB $01                ; Room 61 - Wraith x 1
  DEFB $0C                ; Room 62 - Goblin missile thrower x 3
  DEFB $01                ; Room 63 - Wraith x 1
  DEFB $00                ; Room 64
  DEFB $40                ; Room 65 - Guardian of chaos x 1
  DEFB $20                ; Room 66 - Goblin warrior x 2
  DEFB $60                ; Room 67 - Guardian of chaos x 1, Goblin warrior x 2
  DEFB $00                ; Room 68
  DEFB $00                ; Room 69
  DEFB $40                ; Room 70 - Guardian of chaos x 1
  DEFB $00                ; Room 71
  DEFB $00                ; Room 72
  DEFB $0C                ; Room 73 - Goblin missile thrower x 3
  DEFB $40                ; Room 74 - Guardian of chaos x 1
  DEFB $00                ; Room 75
  DEFB $00                ; Room 76
  DEFB $0C                ; Room 77 - Goblin missile thrower x 3
  DEFB $01                ; Room 78 - Wraith x 1
  DEFB $01                ; Room 79 - Wraith x 1
  DEFB $00                ; Room 80
  DEFB $02                ; Room 81 - Wraith x 2
  DEFB $02                ; Room 82 - Wraith x 2
; CAVERNS OF DOOM
  DEFB $00                ; Room 83
  DEFB $00                ; Room 84
  DEFB $00                ; Room 85
  DEFB $04                ; Room 86 - Goblin missile thrower x 1
  DEFB $04                ; Room 87 - Goblin missile thrower x 1
  DEFB $04                ; Room 88 - Goblin missile thrower x 1
  DEFB $00                ; Room 89
  DEFB $00                ; Room 90
  DEFB $04                ; Room 91 - Goblin missile thrower x 1
  DEFB $00                ; Room 92
  DEFB $00                ; Room 93
  DEFB $08                ; Room 94 - Goblin missile thrower x 2
  DEFB $00                ; Room 95
  DEFB $04                ; Room 96 - Goblin missile thrower x 1
  DEFB $00                ; Room 97
  DEFB $08                ; Room 98 - Goblin missile thrower x 2
  DEFB $00                ; Room 99
  DEFB $00                ; Room 100
  DEFB $00                ; Room 101
  DEFB $04                ; Room 102 - Goblin missile thrower x 1
  DEFB $00                ; Room 103
; MINES OF MADNESS
  DEFB $00                ; Room 104
  DEFB $00                ; Room 105
  DEFB $30                ; Room 106 - Goblin warrior x 3
  DEFB $00                ; Room 107
  DEFB $00                ; Room 108
  DEFB $00                ; Room 109
  DEFB $00                ; Room 110
  DEFB $00                ; Room 111
  DEFB $00                ; Room 112
  DEFB $00                ; Room 113
  DEFB $00                ; Room 114
  DEFB $00                ; Room 115
  DEFB $20                ; Room 116 - Goblin warrior x 2
  DEFB $00                ; Room 117
  DEFB $00                ; Room 118
  DEFB $00                ; Room 119
  DEFB $00                ; Room 120
  DEFB $20                ; Room 121 - Goblin warrior x 2
  DEFB $00                ; Room 122
  DEFB $00                ; Room 123
  DEFB $00                ; Room 124
  DEFB $00                ; Room 125
  DEFB $00                ; Room 126
  DEFB $00                ; Room 127
  DEFB $00                ; Room 128
  DEFB $00                ; Room 129
  DEFB $00                ; Room 130
  DEFB $00                ; Room 131
  DEFB $00                ; Room 132
  DEFB $00                ; Room 133
; GOBLIN WARREN
  DEFB $00                ; Room 134
  DEFB $04                ; Room 135 - Goblin missile thrower x 1
  DEFB $00                ; Room 136
  DEFB $04                ; Room 137 - Goblin missile thrower x 1
  DEFB $00                ; Room 138
  DEFB $04                ; Room 139 - Goblin missile thrower x 1
  DEFB $20                ; Room 140 - Goblin warrior x 2
  DEFB $20                ; Room 141 - Goblin warrior x 2
  DEFB $20                ; Room 142 - Goblin warrior x 2
  DEFB $20                ; Room 143 - Goblin warrior x 2
  DEFB $28                ; 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 $04                ; Room 145 - Goblin missile thrower x 1
  DEFB $20                ; Room 146 - Goblin warrior x 2
  DEFB $10                ; Room 147 - Goblin warrior x 1
  DEFB $10                ; Room 148 - Goblin warrior x 1
  DEFB $00                ; Room 149
  DEFB $00                ; Room 150
  DEFB $00                ; Room 151
  DEFB $40                ; Room 152 - Guardian of chaos x 1
  DEFB $20                ; Room 153 - Goblin warrior x 2
  DEFB $20                ; Room 154 - Goblin warrior x 2
  DEFB $00                ; Room 155
  DEFB $00                ; Room 156
  DEFB $20                ; Room 157 - Goblin warrior x 2
; THE LABYRINTH
  DEFB $00                ; Room 158
  DEFB $01                ; Room 159 - Wraith x 1
  DEFB $00                ; Room 160
  DEFB $00                ; Room 161
  DEFB $00                ; Room 162
  DEFB $00                ; Room 163
  DEFB $00                ; Room 164
  DEFB $01                ; Room 165 - Wraith x 1
  DEFB $00                ; Room 166
  DEFB $00                ; Room 167
  DEFB $01                ; Room 168 - Wraith x 1
  DEFB $00                ; Room 169
  DEFB $00                ; Room 170
  DEFB $00                ; Room 171
  DEFB $01                ; Room 172 - Wraith x 1
  DEFB $00                ; Room 173
  DEFB $00                ; Room 174
  DEFB $00                ; Room 175
  DEFB $00                ; Room 176
  DEFB $01                ; Room 177 - Wraith x 1
  DEFB $00                ; Room 178
  DEFB $01                ; Room 179 - Wraith x 1
  DEFB $00                ; Room 180
  DEFB $00                ; Room 181
  DEFB $01                ; Room 182 - Wraith x 1
; CATACOMBS OF THE UNDEAD
  DEFB $00                ; Room 183
  DEFB $01                ; Room 184 - Wraith x 1
  DEFB $01                ; Room 185 - Wraith x 1
  DEFB $00                ; Room 186
  DEFB $00                ; Room 187
  DEFB $01                ; Room 188 - Wraith x 1
  DEFB $00                ; Room 189
  DEFB $01                ; Room 190 - Wraith x 1
  DEFB $00                ; Room 191
  DEFB $00                ; Room 192
  DEFB $00                ; Room 193
  DEFB $02                ; Room 194 - Wraith x 2
  DEFB $00                ; Room 195
  DEFB $01                ; Room 196 - Wraith x 1
  DEFB $00                ; Room 197
  DEFB $01                ; Room 198 - Wraith x 1
  DEFB $00                ; Room 199
  DEFB $00                ; Room 200
  DEFB $00                ; Room 201
  DEFB $00                ; Room 202
  DEFB $01                ; Room 203 - Wraith x 1
  DEFB $00                ; Room 204
  DEFB $01                ; Room 205 - Wraith x 1
  DEFB $00                ; Room 206
  DEFB $00                ; Room 207
  DEFB $00                ; Room 208
; HIGH TEMPLE OF CHAOS
  DEFB $00                ; Room 209
  DEFB $01                ; Room 210 - Wraith x 1
  DEFB $55                ; 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 $00                ; Room 212
; Unused data - see Trivia: Unused rooms
  DEFB $55,$55,$55,$55,$55,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00

; 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 EBC3.
;
; +------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | 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 E512) is increased by warlock number * 4 (e.g. warlock #2 is worth 8, warlock #7 is worth 28)                        |
; | 3    | Type of missile/bolt (L6CDC) that this warlock fires                                                                                                                                                                               |
; | 4    | Object (see table at L736F, 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 L6CDC                                                                                                                           |
; | 6    | Warlock 'aggression'. Likelihood of this warlock firing a missile at Maroc. The higher the value, the higher the likelihood. Checked at CEFB. Also used as the value for event checking at LDFCD for items traded with the warlock |
; | 7    | Graphic number - address pointer to warlock graphics at 983B                                                                                                                                                                       |
; | 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 LC6A4)                                            |
; +------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
;
; 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.
L6C7C:
  DEFB $06,$00,$01,$01,$03,$06,$3D,$01 ; 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 $04,$00,$04,$02,$27,$0E,$3D,$02 ; Green warlock in the Caverns of Doom
                                       ; Destroy with FIREBOLT, FIREBALL or
                                       ; FLAME Carries: WAYSTONE spell jewel
                                       ; Score earned for destroying = 8
  DEFB $05,$00,$03,$03,$27,$12,$3D,$03 ; Cyan warlock in the Mines of Madness
                                       ; Destroy with FIREBOLT, FIREBALL or
                                       ; FLAME Carries: ICEBOLT spell scroll
                                       ; Score earned for destroying = 12
  DEFB $03,$00,$05,$04,$2B,$16,$3D,$04 ; Magenta warlock in the Great Halls of
                                       ; the Deep Destroy with ICEBOLT or
                                       ; ELECTRIC Carries: WRAITHBANE spell
                                       ; jewel Score earned for destroying = 16
  DEFB $01,$00,$06,$05,$2F,$1E,$3D,$05 ; 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 $02,$00,$08,$06,$2B,$22,$3D,$06 ; Red warlock in the Labyrinth Destroy
                                       ; with ICEBOLT or ELECTRIC Carries:
                                       ; FIREBALL spell scroll Score earned for
                                       ; destroying = 24
  DEFB $0F,$00,$08,$07,$2F,$26,$3D,$07 ; 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 LEBA5.
;
; +------+-------------------------------------------------------------------------------------------------------------+
; | 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 (L6CDC) fired (0 = no ranged attack)                                                        |
; | 4    | - (unused)                                                                                                  |
; | 5    | Collision/event check type (LDFCD)                                                                          |
; | 6    | Collision/event check value for creatures opening/closing doors (17)                                        |
; | 7    | Graphic number - address pointer to creature graphic in table at L97C3                                      |
; | 8    | Amount of damage this creature does to Maroc's energy (check at LD065_0)                                    |
; +------+-------------------------------------------------------------------------------------------------------------+
  DEFB $04,$00,$00,$00,$03,$11,$40,$08 ; Guardian of Chaos
  DEFB $05,$00,$00,$00,$03,$11,$46,$02 ; Goblin warrior
  DEFB $06,$00,$01,$00,$03,$11,$4C,$01 ; Goblin missile thrower
  DEFB $0F,$00,$00,$00,$07,$11,$52,$10 ; Wraith
  DEFB $00,$00,$09,$00,$07,$11,$58,$20 ; Demon

; Missile data
;
; Address pointer stored at EB93 (intialized at LEBC1). Used in routine at
; LDB1F.
;
; +----------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | Byte                             | Value                                                                                                                                                                                                                                                                                                                                                 |
; +----------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | 1                                | Graphic number - offset for missile graphic address in table at L97C3 52 = Missile type 1 (9829) 55 = Missile type 2 (9831) 58 = Missile type 3 (9835)                                                                                                                                                                                                |
; | 2                                | Missile properties byte (put in item buffer at EB4E). 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 (L6C7C) to indicate which missile spell(s) can destroy which warlock                                                                                                                                                                                                 |
; | 5                                | Counter spell #1 (list at L6DFC, starting at 0) that resists this missile/bolt type (Amulet)                                                                                                                                                                                                                                                          |
; | 6                                | Damage caused by this missile                                                                                                                                                                                                                                                                                                                         |
; | 7                                | Counter spell #2 (list at L6DFC, starting at 0) that resists this missile/bolt type                                                                                                                                                                                                                                                                   |
; | 8                                | Counter spell #3 (list at L6DFC, starting at 0) that resists this missile/bolt type                                                                                                                                                                                                                                                                   |
; +----------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
L6CDC:
  DEFB $34,%11110101,$07,$01,$0E,$20,$02,$12 ; Missile 1
  DEFB $37,%10100101,$06,$27,$0E,$20,$02,$0B ; Missile 2
  DEFB $37,%10010101,$05,$2B,$0E,$28,$02,$12 ; Missile 3
  DEFB $37,%10010101,$0F,$03,$0E,$30,$02,$0B ; Missile 4
  DEFB $3A,%10100101,$06,$27,$0E,$30,$0B,$12 ; Missile 5
  DEFB $3A,%10100101,$05,$2B,$0E,$30,$0B,$12 ; Missile 6
  DEFB $3A,%11000101,$0F,$2F,$0E,$28,$0B,$12 ; Missile 7
  DEFB $3A,%10010101,$06,$27,$0E,$28,$0B,$02 ; Missile 8
  DEFB $3A,%11110101,$0F,$01,$0E,$40,$44,$44 ; 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] |
; +------+--------+------+--------+------+---------+
L6D24:
  DEFB $00,$00,$38,$06,$38,$62,$66,$3A
  DEFB $60,$60,$2C,$32,$22,$22,$72,$7C
  DEFB $00,$00,$1C,$26,$40,$40,$46,$3C
  DEFB $06,$06,$34,$4C,$44,$44,$4E,$3E
  DEFB $00,$00,$3C,$46,$5E,$40,$46,$3C
  DEFB $7E,$66,$20,$2E,$30,$20,$60,$60
  DEFB $00,$00,$36,$4E,$44,$3C,$04,$7E
  DEFB $60,$60,$2C,$32,$22,$22,$6E,$6C
  DEFB $1C,$1C,$00,$08,$08,$10,$18,$18
  DEFB $1C,$1C,$00,$08,$08,$04,$6C,$38
  DEFB $60,$64,$28,$38,$30,$1C,$22,$26
  DEFB $60,$60,$20,$20,$20,$20,$66,$7C
  DEFB $00,$00,$D6,$E9,$49,$49,$5B,$5A
  DEFB $00,$00,$6C,$72,$22,$22,$26,$2C
  DEFB $00,$00,$18,$24,$42,$42,$66,$3C
  DEFB $00,$00,$6C,$72,$22,$3C,$60,$60
  DEFB $00,$00,$36,$4E,$44,$3C,$06,$06
  DEFB $00,$00,$6C,$76,$20,$20,$20,$20
  DEFB $00,$00,$38,$64,$30,$0C,$62,$3C
  DEFB $30,$30,$10,$78,$20,$20,$66,$7C
  DEFB $00,$00,$36,$66,$44,$44,$4E,$36
  DEFB $00,$00,$66,$26,$22,$14,$1C,$08
  DEFB $00,$00,$DB,$5B,$49,$2A,$3E,$14
  DEFB $00,$00,$62,$34,$14,$1C,$34,$62
  DEFB $00,$00,$36,$66,$44,$38,$08,$0C
  DEFB $00,$00,$7E,$66,$0C,$18,$36,$7C
; Final character = [SPACE]
  DEFB $00,$00,$00,$00,$00,$00,$00,$00

; Spells list
;
; See the Spells reference section for spell information.
;
; Details of the active/selected spell are copied into a working buffer at
; LEBC5.
;
; 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 EBC9)                                                                                                                                                                                                                                                                                                             |
; | 6    | Value representing action to take when FIRE pressed with a servant/cursor icon spell active (checked at D820 and E9ED). 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 L97C3 (icon graphics from LA17E)                                                                                                                                                                                                                                                                                        |
; | 8    | Graphics number - address pointer offset (for graphic addresses at L97C3) 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 9813 pointing to servant graphics at A0DC)For all other 'aiming cursor' spells (e.g. UNLOCK, MISSILE, OPEN, FIND, ICEBOLT) spell offset is 43 (graphics pointer 9817 pointing to blinking eye cursor graphics at A105) |
; +------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
;
; See the table of character byte values for a translation of
; letters-to-numbers.
L6DFC:
  DEFB $10,$01,$01,$FF,$00,$00,$32,$00
  DEFM $0C,$0E,$15,$04,$1A,$1A,$1A,$1A ; MOVE____
  DEFB $00,$08,$02,$FF,$00,$05,$31,$29
  DEFM $12,$04,$11,$15,$00,$0D,$13,$1A ; SERVANT_
  DEFB $00,$01,$04,$00,$00,$00,$2D,$00
  DEFM $12,$07,$08,$04,$0B,$03,$1A,$1A ; SHIELD__
  DEFB $00,$04,$02,$00,$00,$04,$2D,$2B
  DEFM $14,$0D,$0B,$0E,$02,$0A,$1A,$1A ; UNLOCK__
  DEFB $00,$02,$02,$00,$00,$84,$2D,$2B
  DEFM $0C,$08,$12,$12,$08,$0B,$04,$1A ; MISSILE_
  DEFB $00,$C0,$05,$00,$00,$00,$2D,$00
  DEFM $04,$0D,$04,$11,$06,$08,$19,$04 ; ENERGIZE
  DEFB $00,$08,$02,$00,$00,$82,$2D,$2B
  DEFM $05,$08,$11,$04,$01,$0E,$0B,$13 ; FIREBOLT
  DEFB $00,$03,$02,$00,$00,$10,$2D,$2B
  DEFM $11,$04,$15,$04,$00,$0B,$1A,$1A ; REVEAL__
  DEFB $00,$01,$05,$00,$00,$00,$2D,$00
  DEFM $07,$00,$08,$0B,$1A,$1A,$1A,$1A ; HAIL____
  DEFB $00,$01,$04,$00,$00,$00,$2D,$00
  DEFM $14,$0D,$12,$04,$04,$0D,$1A,$1A ; UNSEEN__
  DEFB $00,$01,$02,$00,$00,$0A,$2D,$2B
  DEFM $0E,$0F,$04,$0D,$1A,$1A,$1A,$1A ; OPEN____
  DEFB $00,$01,$04,$00,$00,$00,$2D,$00
  DEFM $0F,$11,$0E,$13,$04,$02,$13,$1A ; PROTECT_
  DEFB $00,$04,$05,$00,$00,$00,$33,$00
  DEFM $16,$00,$18,$12,$13,$0E,$0D,$04 ; WAYSTONE
  DEFB $00,$02,$02,$00,$00,$83,$2D,$2B
  DEFM $08,$02,$04,$01,$0E,$0B,$13,$1A ; ICEBOLT_
  DEFB $00,$01,$04,$FF,$00,$00,$2F,$00
  DEFM $00,$0C,$14,$0B,$04,$13,$1A,$1A ; AMULET__
  DEFB $00,$02,$02,$00,$00,$85,$2D,$2B
  DEFM $05,$08,$11,$04,$01,$00,$0B,$0B ; FIREBALL
  DEFB $00,$04,$05,$00,$00,$00,$2D,$00
  DEFM $05,$11,$04,$04,$19,$04,$1A,$1A ; FREEZE__
  DEFB $00,$04,$05,$00,$00,$00,$33,$00
  DEFM $12,$14,$0C,$0C,$0E,$0D,$1A,$1A ; SUMMON__
  DEFB $00,$01,$04,$00,$00,$00,$33,$00
  DEFM $03,$04,$05,$04,$0D,$02,$04,$1A ; DEFENCE_
  DEFB $00,$08,$05,$00,$00,$00,$2D,$00
  DEFM $0F,$0E,$11,$13,$00,$0B,$1A,$1A ; PORTAL__
  DEFB $00,$04,$04,$FF,$00,$00,$33,$00
  DEFM $16,$1A,$01,$00,$0D,$04,$1A,$1A ; W_BANE__
  DEFB $00,$04,$02,$00,$00,$02,$2D,$2B
  DEFM $03,$08,$12,$0F,$04,$0B,$1A,$1A ; DISPEL__
  DEFB $00,$02,$03,$00,$00,$86,$33,$2B
  DEFM $04,$0B,$04,$02,$13,$11,$08,$02 ; ELECTRIC
  DEFB $00,$06,$02,$00,$00,$87,$2D,$2B
  DEFM $15,$00,$0F,$0E,$11,$08,$19,$04 ; VAPORIZE
  DEFB $00,$02,$03,$00,$00,$88,$2D,$2B
  DEFM $05,$0B,$00,$0C,$04,$1A,$1A,$1A ; FLAME___
  DEFB $00,$04,$02,$00,$00,$08,$2D,$2B
  DEFM $05,$08,$0D,$03,$1A,$1A,$1A,$1A ; FIND____
  DEFB $00,$FB,$04,$FF,$00,$00,$30,$00
  DEFM $02,$07,$00,$0B,$08,$02,$04,$1A ; CHALICE_
  DEFB $00,$00,$05,$FF,$00,$00,$2D,$00
  DEFM $0C,$04,$12,$12,$00,$06,$04,$1A ; 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.
L6FBC:
  DEFB $FF                ; Unused byte
; MOVE spell
  DEFB $10                ; Text length = 16
  DEFM $0F,$11,$0E,$09,$04,$02,$13,$1A,$13,$07,$18,$1A,$12,$0E,$14,$0B ; PROJECT
                                                                       ; THY SOUL
; SERVANT spell
  DEFB $0E                ; Text length = 14
  DEFM $00,$1A,$07,$04,$0B,$0F,$08,$0D,$06,$1A,$07,$00,$0D,$03 ; A HELPING HAND
; SHIELD spell
  DEFB $0E                ; Text length = 14
  DEFM $00,$12,$1A,$08,$05,$1A,$0E,$05,$1A,$12,$13,$04,$04,$0B ; AS IF OF STEEL
; UNLOCK spell
  DEFB $10                ; Text length = 16
  DEFM $00,$1A,$0A,$04,$18,$1A,$0E,$05,$1A,$02,$14,$0D,$0D,$08,$0D,$06 ; A KEY OF
                                                                       ; CUNNING
; MISSILE spell
  DEFB $0E                ; Text length = 14
  DEFM $06,$0E,$01,$0B,$08,$0D,$1A,$02,$11,$14,$12,$07,$04,$11 ; GOBLIN CRUSHER
; ENERGIZE spell
  DEFB $0E                ; Text length = 14
  DEFM $0F,$0E,$16,$04,$11,$1A,$13,$0E,$1A,$16,$08,$04,$0B,$03 ; POWER TO WIELD
; FIREBOLT spell
  DEFB $10                ; Text length = 16
  DEFM $16,$00,$11,$0B,$0E,$02,$0A,$12,$1A,$14,$0D,$03,$0E,$08,$0D,$06 ; WARLOCKS
                                                                       ; UNDOING
; REVEAL spell
  DEFB $0F                ; Text length = 15
  DEFM $13,$0E,$1A,$05,$08,$0D,$03,$1A,$13,$07,$04,$1A,$02,$14,$0F ; TO FIND
                                                                   ; THE CUP
; HAIL spell
  DEFB $10                ; Text length = 16
  DEFM $02,$00,$0B,$0B,$1A,$13,$0E,$1A,$13,$07,$04,$1A,$16,$08,$12,$04 ; CALL TO
                                                                       ; THE WISE
; UNSEEN spell
  DEFB $0E                ; Text length = 14
  DEFM $13,$0E,$1A,$06,$0E,$1A,$14,$0D,$0E,$13,$08,$02,$04,$03 ; TO GO UNOTICED
; OPEN spell
  DEFB $0E                ; Text length = 14
  DEFM $13,$0E,$1A,$0B,$0E,$0E,$0A,$1A,$08,$0D,$12,$08,$03,$04 ; TO LOOK INSIDE
; PROTECT spell
  DEFB $0E                ; Text length = 14
  DEFM $0C,$00,$06,$08,$02,$1A,$0C,$00,$18,$1A,$13,$14,$11,$0D ; MAGIC MAY TURN
; WAYSTONE spell
  DEFB $0D                ; Text length = 13
  DEFM $07,$04,$11,$04,$1A,$13,$0E,$1A,$13,$07,$04,$11,$04 ; HERE TO THERE
; ICEBOLT spell
  DEFB $0E                ; Text length = 14
  DEFM $04,$00,$13,$04,$11,$1A,$0E,$05,$1A,$05,$0B,$00,$0C,$04 ; EATER OF FLAME
; AMULET spell
  DEFB $0B                ; Text length = 11
  DEFM $0E,$05,$1A,$04,$15,$04,$11,$0C,$0E,$11,$04 ; OF EVERMORE
; FIREBALL spell
  DEFB $0E                ; Text length = 14
  DEFM $00,$1A,$03,$04,$00,$03,$0B,$18,$1A,$05,$0B,$00,$0C,$04 ; A DEADLY FLAME
; FREEZE spell
  DEFB $0E                ; Text length = 14
  DEFM $12,$04,$02,$11,$04,$13,$1A,$0E,$05,$1A,$13,$08,$0C,$04 ; SECRET OF TIME
; SUMMON spell
  DEFB $0D                ; Text length = 13
  DEFM $07,$04,$00,$11,$1A,$00,$0D,$03,$1A,$0E,$01,$04,$18 ; HEAR AND OBEY
; DEFENCE spell
  DEFB $0C                ; Text length = 12
  DEFM $0C,$08,$11,$11,$0E,$11,$1A,$0C,$00,$06,$08,$02 ; MIRROR MAGIC
; PORTAL spell
  DEFB $0C                ; Text length = 12
  DEFM $01,$00,$02,$0A,$1A,$13,$0E,$1A,$07,$04,$11,$04 ; BACK TO HERE
; W BANE spell
  DEFB $0A                ; Text length = 10
  DEFM $16,$11,$00,$08,$13,$07,$01,$00,$0D,$04 ; WRAITHBANE
; DISPEL spell
  DEFB $0D                ; Text length = 13
  DEFM $14,$0D,$01,$04,$16,$08,$13,$02,$07,$0C,$04,$0C,$13 ; UNBEWITCHMEMT
; ELECTRIC spell
  DEFB $0F                ; Text length = 15
  DEFM $12,$0B,$00,$18,$1A,$13,$07,$04,$1A,$03,$00,$0C,$0D,$04,$03 ; SLAY THE
                                                                   ; DAMNED
; VAPORIZE spell
  DEFB $0D                ; Text length = 13
  DEFM $03,$04,$05,$18,$1A,$13,$07,$04,$1A,$03,$00,$11,$0A ; DEFY THE DARK
; FLAME spell
  DEFB $10                ; Text length = 16
  DEFM $01,$14,$11,$0D,$1A,$01,$0B,$00,$02,$0A,$1A,$0C,$00,$06,$08,$02 ; BURN BLACK
                                                                       ; MAGIC
; FIND spell
  DEFB $10                ; Text length = 16
  DEFM $12,$07,$0E,$16,$12,$1A,$13,$07,$04,$1A,$07,$08,$03,$03,$04,$0D ; SHOWS THE
                                                                       ; HIDDEN
; CHALICE spell
  DEFB $10                ; Text length = 16
  DEFM $06,$11,$00,$08,$0B,$1A,$0E,$05,$1A,$07,$04,$00,$0B,$08,$0D,$06 ; GRAIL OF
                                                                       ; HEALING
; MESSAGE spell
  DEFB $1E                ; Text length = 30
  DEFM $12,$04,$04,$0A,$1A,$13,$07,$04,$1A,$0B,$00,$03,$18,$1B,$13,$0E,$1A ; SEEK THE
                                                                           ; LADY TO
  DEFM $05,$08,$0D,$03,$1A,$02,$00,$0B,$08,$01,$14,$11,$0D ; 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
L7172:
  DEFB $0F                ; Text length = 15
  DEFM $06,$00,$13,$04,$07,$0E,$14,$12,$04,$1A,$0B,$04,$15,$04,$0B ; GATEHOUSE
                                                                   ; LEVEL
  DEFB $0F                ; Text length = 15
  DEFM $02,$00,$15,$04,$11,$0D,$12,$1A,$0E,$05,$1A,$03,$0E,$0E,$0C ; CAVERNS OF
                                                                   ; DOOM
  DEFB $10                ; Text length = 16
  DEFM $0C,$08,$0D,$04,$12,$1A,$0E,$05,$1A,$0C,$00,$03,$0D,$04,$12,$12 ; MINES OF
                                                                       ; MADNESS
  DEFB $17                ; Text length = 23
  DEFM $06,$11,$04,$00,$13,$1A,$07,$00,$0B,$0B,$12,$1A,$0E,$05,$1B ; GREAT
                                                                   ; HALLS OF/
  DEFM $13,$07,$04,$1A,$03,$04,$04,$0F ; THE DEEP
  DEFB $0D                ; Text length = 13
  DEFM $06,$0E,$01,$0B,$08,$0D,$1A,$16,$00,$11,$11,$04,$0D ; GOBLIN WARREN
  DEFB $0D                ; Text length = 13
  DEFM $13,$07,$04,$1A,$0B,$00,$01,$18,$11,$08,$0D,$13,$07 ; THE LABYRINTH
  DEFB $17                ; Text length = 23
  DEFM $02,$00,$13,$00,$02,$0E,$0C,$01,$12,$1A,$0E,$05,$1A,$13,$07,$04 ; CATACOMBS
                                                                       ; OF THE/
  DEFM $1B,$14,$0D,$03,$04,$00,$03 ; UNDEAD
  DEFB $11                ; Text length = 17
  DEFM $02,$07,$00,$0C,$01,$04,$11,$12,$1A,$0E,$05,$1B,$02,$07,$00,$0E,$12 ; CHAMBERS
                                                                           ; OF CHAOS
  DEFB $14                ; Text length = 20
  DEFM $07,$08,$06,$07,$1A,$13,$04,$0C,$0F,$0B,$04,$1A,$0E,$05,$1B ; HIGH
                                                                   ; TEMPLE OF/
  DEFM $02,$07,$00,$0E,$12 ; 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 (LE4E7) 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:
L7216:
  DEFB $0A                ; Text length = 10
  DEFM $00,$0F,$0F,$11,$04,$0D,$13,$08,$02,$04 ; APPRENTICE
  DEFB $05                ; Text length = 5
  DEFM $0C,$08,$0D,$0E,$11 ; MINOR
  DEFB $06                ; Text length = 6
  DEFM $0B,$04,$12,$12,$04,$11 ; LESSER
  DEFB $07                ; Text length = 7
  DEFM $0B,$04,$00,$11,$0D,$04,$03 ; LEARNED
  DEFB $06                ; Text length = 6
  DEFM $0C,$00,$12,$13,$04,$11 ; MASTER
  DEFB $05                ; Text length = 5
  DEFM $02,$07,$08,$04,$05 ; CHIEF
  DEFB $04                ; Text length = 4
  DEFM $07,$08,$06,$07    ; HIGH
  DEFB $07                ; Text length = 7
  DEFM $12,$14,$0F,$11,$04,$0C,$04 ; SUPREME
; TITLES:
  DEFB $0B                ; Text length = 11
  DEFM $0B,$0E,$11,$04,$1A,$12,$04,$04,$0A,$04,$11 ; LORE SEEKER
  DEFB $08                ; Text length = 8
  DEFM $16,$08,$12,$04,$1A,$0E,$0D,$04 ; WISE ONE
  DEFB $0B                ; Text length = 11
  DEFM $0B,$0E,$11,$04,$1A,$0A,$04,$04,$0F,$04,$11 ; LORE KEEPER
  DEFB $06                ; Text length = 6
  DEFM $0C,$18,$12,$13,$08,$02 ; MYSTIC
  DEFB $09                ; Text length = 9
  DEFM $00,$0B,$02,$07,$04,$0C,$08,$12,$13 ; ALCHEMIST
  DEFB $04                ; Text length = 4
  DEFM $0C,$00,$06,$04    ; MAGE
  DEFB $0A                ; Text length = 10
  DEFM $0C,$00,$06,$08,$02,$1A,$14,$12,$04,$11 ; MAGIC USER
  DEFB $08                ; Text length = 8
  DEFM $02,$0E,$0D,$09,$14,$11,$0E,$11 ; CONJUROR
  DEFB $08                ; Text length = 8
  DEFM $0C,$00,$06,$08,$02,$08,$00,$0D ; MAGICIAN
  DEFB $04                ; Text length = 4
  DEFM $12,$00,$06,$04    ; SAGE
  DEFB $0B                ; Text length = 11
  DEFM $0B,$0E,$11,$04,$1A,$0C,$00,$12,$13,$04,$11 ; LORE MASTER
  DEFB $07                ; Text length = 7
  DEFM $16,$00,$11,$0B,$0E,$02,$0A ; WARLOCK
  DEFB $06                ; Text length = 6
  DEFM $16,$08,$19,$00,$11,$03 ; WIZARD
  DEFB $08                ; Text length = 8
  DEFM $12,$0E,$11,$02,$04,$11,$0E,$11 ; SORCEROR
  DEFB $10                ; Text length = 16
  DEFM $06,$14,$00,$11,$03,$08,$00,$0D,$1A,$0E,$05,$1A,$0B,$0E,$11,$04 ; GUARDIAN
                                                                       ; OF LORE
  DEFB $09                ; Text length = 9
  DEFM $0B,$0E,$11,$04,$1A,$0B,$0E,$11,$03 ; LORE LORD
; Text printed before rank:
  DEFB $10                ; Text length = 16
  DEFM $18,$0E,$14,$11,$1A,$11,$00,$0D,$0A,$1A,$08,$12,$1A,$0D,$0E,$16 ; 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
L72F9:
  DEFB $25                ; Text length = 37 characters:
  DEFM $18,$0E,$14,$1A,$07,$00,$15,$04,$1A,$0A,$08,$0B,$0B,$04,$03,$1B ; YOU HAVE
                                                                       ; KILLED/
  DEFM $00,$15,$04,$0B,$00,$02,$07,$1B ; AVELACH/
  DEFM $0B,$0E,$11,$03,$1A,$0E,$05,$1A,$02,$07,$00,$0E,$12 ; LORD OF CHAOS
; Game start message
  DEFB $33                ; Text length = 51 characters:
  DEFM $12,$04,$04,$0A,$1A,$13,$07,$04,$1A,$07,$08,$06,$07,$1B ; SEEK THE HIGH/
  DEFM $0C,$00,$06,$08,$02,$1A,$13,$0E,$1A,$03,$04,$05,$04,$00,$13,$1B ; MAGIC TO
                                                                       ; DEFEAT/
  DEFM $00,$15,$04,$0B,$00,$02,$07,$1B ; AVELACH/
  DEFM $0B,$0E,$11,$03,$1A,$0E,$05,$1A,$02,$07,$00,$0E,$12 ; LORD OF CHAOS

; Save game message
;
; See the table of character byte values for a translation of
; letters-to-numbers. 27 = end-of-line
L7353:
  DEFB $1B                ; Text length = 27
  DEFM $12,$13,$00,$11,$13,$1A,$13,$00,$0F,$04,$1A,$13,$07,$04,$0D,$1B ; "START
                                                                       ; TAPE
                                                                       ; THEN/"
  DEFM $0F,$11,$04,$12,$12,$1A,$04,$0D,$13,$04,$11 ; "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 EB85.
;
; +------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
; | 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 EB4E) 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 L6DFC (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 LCBA8 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 L97C3. Offset calculated using [(n-1)*2] + L97C3 A value of 124 (check at LCB00) 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 L97C3. Offset calculated using [(n-1)*2] + L97C3                                                                                                                                                                                                                                                                    |
; +------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
L736F:
  DEFB $00,$00,$00,$C5,$01,$00,$0F,$01 ; Star symbol - 98E7 (from warlock #1)
  DEFB $00,$0F,$1A,$93                 ;
  DEFB $00,$00,$00,$45,$01,$0C,$0F,$01 ; WAYSTONE spell jewel - 9827 (from
  DEFB $00,$0F,$00,$33                 ; warlock #2)
  DEFB $00,$00,$00,$45,$01,$0D,$0F,$01 ; ICEBOLT spell scroll - 981B (from
  DEFB $00,$0F,$00,$2D                 ; warlock #3)
  DEFB $00,$00,$00,$45,$01,$14,$0F,$01 ; WRAITHBANE spell jewel - 9827 (from
  DEFB $00,$0F,$00,$33                 ; warlock #4)
  DEFB $00,$00,$00,$45,$01,$16,$0F,$01 ; ELECTRIC spell scroll - 981B (from
  DEFB $00,$0F,$00,$2D                 ; warlock #5)
  DEFB $00,$00,$00,$45,$01,$0F,$0F,$01 ; FIREBALL spell scroll - 981B (from
  DEFB $00,$0F,$00,$2D                 ; warlock #6)
  DEFB $00,$00,$00,$45,$01,$18,$0F,$01 ; FLAME spell scroll - 981B (from
  DEFB $00,$0F,$00,$2D                 ; warlock #7)
  DEFB $02,$30,$38,$05,$01,$00,$07,$02 ; Room 2 - Healing STAR symbol on floor
  DEFB $00,$1A,$00,$92,$80,$0F,$FD,$B9 ; in room 2 - 98E5 (inactive) 9933
                                       ; (active)
  DEFB $06,$20,$35,$45,$01,$05,$3F,$01 ; Room 6 - ENERGIZE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $08,$14,$40,$45,$01,$10,$27,$01 ; Room 8 - FREEZE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $0F,$2A,$35,$45,$01,$10,$24,$01 ; Room 15 - FREEZE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $0A,$13,$37,$45,$01,$01,$06,$01 ; Room 10 - SERVANT spell - ring - 9823
  DEFB $00,$0F,$00,$31                 ;
  DEFB $10,$20,$35,$05,$01,$00,$06,$02 ; Room 16 - Chest - 98CF (closed) 98D1
  DEFB $00,$05,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $10,$20,$35,$02,$01,$05,$3F,$02 ; Room 16 - ENERGIZE spell scroll (in
  DEFB $00,$05,$00,$7C,$40,$0F,$00,$2D ; chest) - 981B
  DEFB $14,$18,$3A,$05,$01,$00,$03,$02 ; Room 20 - Chest - 98CF (closed) 98D1
  DEFB $00,$3C,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $14,$18,$3A,$02,$01,$00,$26,$02 ; Room 20 - Coins (in chest) - 98E9
  DEFB $00,$3C,$00,$7C,$40,$0F,$00,$94 ;
  DEFB $15,$18,$20,$C5,$01,$00,$07,$01 ; Room 21 - Key - 98CD
  DEFB $00,$0F,$3C,$86                 ;
  DEFB $16,$32,$20,$45,$01,$05,$3F,$01 ; Room 22 - ENERGIZE spell scroll -
  DEFB $00,$0F,$00,$2D                 ; 981B)
  DEFB $18,$28,$3A,$05,$01,$00,$04,$02 ; Room 24 - Chest - 98CF (closed) 98D1
  DEFB $00,$3C,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $18,$28,$3A,$02,$01,$00,$16,$02 ; Room 24 - Key (in chest) - 98E3
  DEFB $00,$3C,$00,$7C,$C0,$0F,$0C,$91 ;
  DEFB $1B,$23,$3A,$45,$01,$05,$3F,$01 ; Room 27 - ENERGIZE spell scroll -
  DEFB $00,$0F,$00,$2D                 ; 981B)
  DEFB $1D,$32,$40,$C5,$01,$00,$03,$01 ; Room 29 - Fish - 98EB
  DEFB $00,$0F,$FE,$95                 ;
  DEFB $53,$2A,$38,$45,$01,$09,$37,$01 ; Room 83 - UNSEEN spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $55,$2A,$40,$05,$01,$00,$04,$01 ; Room 85 - Bottle - 98ED
  DEFB $00,$0F,$00,$96                 ;
  DEFB $55,$2A,$40,$02,$01,$00,$04,$02 ; Room 85 - Key (in bottle) - 98CD
  DEFB $00,$05,$00,$7C,$C0,$0F,$40,$86 ;
  DEFB $55,$18,$38,$05,$01,$00,$00,$02 ; Room 85 - Chest - 98CF (closed) 98D1
  DEFB $00,$40,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $55,$18,$38,$02,$01,$00,$36,$02 ; Room 85 - Coins (in chest) - 98E9
  DEFB $00,$40,$00,$7C,$40,$0F,$00,$94 ;
  DEFB $5B,$23,$20,$45,$01,$1B,$36,$01 ; Room 91 - MESSAGE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $5E,$1A,$38,$45,$01,$09,$4F,$01 ; Room 94 - UNSEEN spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $5F,$24,$3A,$05,$01,$00,$05,$02 ; Room 95 - Chest - 98CF (closed) 98D1
  DEFB $00,$09,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $5F,$24,$3A,$02,$01,$00,$05,$02 ; Room 95 - Key - 98E3
  DEFB $00,$09,$00,$7C,$C0,$0F,$2C,$91 ;
  DEFB $60,$20,$38,$85,$01,$00,$03,$01 ; Room 96 - Healing mushrooms - 98EF
  DEFB $00,$0F,$FD,$97                 ;
  DEFB $61,$22,$38,$05,$01,$00,$04,$02 ; Room 97 - Bottle - 98ED
  DEFB $00,$09,$00,$96,$00,$0F,$00,$8A ;
  DEFB $61,$22,$38,$02,$01,$00,$06,$03 ; Room 97 - Scorpion (in bottle) - 98F1
  DEFB $00,$09,$00,$7C,$83,$03,$FE,$98 ;
  DEFB $00,$0F,$00,$7C                 ;
  DEFB $63,$34,$40,$45,$01,$10,$47,$01 ; Room 99 - FREEZE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $64,$18,$40,$45,$01,$02,$36,$01 ; Room 100 - SHIELD spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $66,$24,$18,$C5,$01,$00,$06,$01 ; Room 102 - Axe - 98F5
  DEFB $00,$0F,$09,$9A                 ;
  DEFB $67,$20,$30,$45,$01,$05,$35,$01 ; Room 103 - ENERGIZE spell scroll -
  DEFB $00,$0F,$00,$2D                 ; 981B
  DEFB $68,$10,$20,$45,$01,$04,$0F,$01 ; Room 104 - MISSILE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $6E,$1A,$3A,$85,$01,$00,$46,$02 ; Room 110 - Jewel - 9827 (give to
  DEFB $00,$11,$FE,$7D,$40,$0F,$00,$33 ; Warlock for ICEBOLT spell)
  DEFB $6F,$20,$40,$85,$01,$00,$06,$01 ; Room 111 - Scorpion - 98F1
  DEFB $83,$0F,$FE,$98                 ;
  DEFB $70,$1C,$38,$45,$01,$10,$07,$01 ; Room 112 - FREEZE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $74,$2A,$38,$45,$01,$09,$4F,$01 ; Room 116 - UNSEEN spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $78,$10,$44,$85,$01,$00,$03,$01 ; Room 120 - Mushrooms (energy drain) -
  DEFB $00,$0F,$FE,$97                 ; 98EF
  DEFB $79,$23,$32,$45,$01,$05,$07,$01 ; Room 121 - ENERGIZE spell scroll -
  DEFB $00,$0F,$00,$2D                 ; 981B
  DEFB $7C,$10,$40,$05,$01,$00,$04,$02 ; Room 124 - Boulder - 98A9 - use pick
  DEFB $00,$09,$00,$74,$08,$0F,$00,$74 ; (98D7)
  DEFB $7C,$10,$40,$05,$01,$0A,$0F,$02 ; Room 124 - OPEN spell scroll (under
  DEFB $00,$09,$00,$7C,$40,$0F,$00,$2D ; boulder) - 981B
  DEFB $7E,$1A,$34,$C5,$01,$00,$07,$01 ; Room 126 - Pick - 98D7 - use on
  DEFB $00,$0F,$09,$8B                 ; boulder to get OPEN spell
  DEFB $80,$13,$38,$05,$01,$00,$04,$01 ; Room 128 - Pool - 98B3
  DEFB $00,$0F,$00,$79                 ;
  DEFB $80,$13,$38,$06,$01,$11,$0F,$02 ; Room 128 - SUMMON spell jewel (in
  DEFB $00,$05,$00,$7C,$40,$0F,$00,$33 ; pool) - 9827
  DEFB $82,$18,$18,$45,$01,$02,$07,$01 ; Room 130 - SHIELD spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $1F,$20,$40,$45,$01,$04,$46,$01 ; Room 31 - MISSILE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $21,$38,$40,$45,$01,$15,$47,$01 ; Room 33 - DISPEL spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $22,$28,$38,$45,$01,$05,$47,$01 ; Room 34 - ENERGIZE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $26,$18,$20,$05,$01,$00,$0F,$02 ; Room 38 - Bone - 98F7 - use DISPEL for
  DEFB $00,$02,$00,$9B,$C0,$0F,$1C,$91 ; flashing key - 98E3
  DEFB $27,$14,$38,$45,$01,$09,$47,$01 ; Room 39 - UNSEEN spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $27,$1A,$43,$45,$01,$08,$46,$01 ; Room 39 - HAIL spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $28,$22,$40,$85,$01,$00,$0F,$01 ; Room 40 - Energy orb - 98F9
  DEFB $00,$0F,$FD,$9C                 ;
  DEFB $2B,$18,$40,$05,$01,$00,$0F,$02 ; Room 43 - Spider - 98BB - use DISPEL
  DEFB $00,$02,$00,$7D,$00,$0F,$00,$88 ; to reveal (open) chest - 98D1
  DEFB $2B,$18,$40,$02,$01,$06,$07,$02 ; Room 43 - FIREBOLT spell scroll (in
  DEFB $00,$02,$00,$7C,$40,$0F,$00,$2D ; chest) - 981B
  DEFB $2B,$18,$40,$02,$01,$0B,$06,$02 ; Room 43 - PROTECT spell scroll (in
  DEFB $00,$02,$00,$7C,$40,$0F,$00,$2D ; chest) - 981B
  DEFB $2C,$20,$38,$C5,$01,$00,$04,$01 ; Room 44 - Pick - 98D7
  DEFB $00,$0F,$09,$8B                 ;
  DEFB $2D,$1A,$42,$05,$01,$00,$05,$02 ; Room 45 - Bottle (buried) - 98D3
  DEFB $00,$09,$00,$89,$00,$0F,$00,$8A ; (intact) & 98D5 (broken)
  DEFB $2D,$1A,$42,$05,$01,$00,$06,$02 ; Room 45 - Yellow key - 98CD (use pick
  DEFB $00,$09,$00,$7C,$C0,$0F,$18,$86 ; on buried bottle)
  DEFB $2E,$18,$40,$05,$01,$00,$06,$02 ; Room 46 - Chest - 98CF (closed) 98D1
  DEFB $00,$18,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $2E,$18,$40,$02,$01,$00,$46,$02 ; Room 46 - Coins (in chest) - 98E9 (use
  DEFB $00,$18,$00,$7C,$40,$0F,$00,$94 ; yellow key)
  DEFB $31,$14,$3A,$C5,$01,$00,$06,$01 ; Room 49 - Cheese (98D9)
  DEFB $00,$0F,$30,$8C                 ;
  DEFB $32,$3A,$20,$05,$01,$00,$07,$02 ; Room 50 - Key (hanging) - 98E1 &
  DEFB $00,$34,$00,$90,$C8,$0F,$28,$91 ; normal - 98E3
  DEFB $35,$18,$2C,$05,$01,$00,$04,$01 ; Room 53 - Mouse hole - 98DB
  DEFB $00,$0F,$00,$8D                 ;
  DEFB $35,$18,$2C,$02,$01,$00,$07,$02 ; Room 53 - Mouse - 98FD - use cheese on
  DEFB $00,$30,$00,$7C,$C1,$0F,$34,$9E ; mouse hole to reveal
  DEFB $86,$19,$20,$45,$01,$12,$07,$01 ; Room 134 - DEFENCE spell jewel - 9827
  DEFB $00,$0F,$00,$33                 ;
  DEFB $88,$1A,$35,$05,$01,$00,$06,$02 ; Room 136 - Chest - 98CF (closed) 98D1
  DEFB $00,$44,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $88,$1A,$35,$06,$01,$13,$07,$02 ; Room 136 - PORTAL spell scroll - 981B
  DEFB $00,$44,$00,$7C,$40,$0F,$00,$2D ;
  DEFB $89,$20,$33,$05,$01,$00,$03,$02 ; Room 137 - Chest - 98CF (closed) 98D1
  DEFB $00,$48,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $89,$20,$33,$06,$01,$00,$07,$02 ; Room 137 - Key (in chest) - 98CD
  DEFB $00,$48,$00,$7C,$00,$0F,$00,$88 ;
  DEFB $89,$20,$33,$06,$01,$00,$07,$02 ; Room 137 - (Duplicate entry)
  DEFB $00,$48,$00,$7C,$C0,$0F,$44,$86 ;
  DEFB $8B,$19,$39,$05,$01,$00,$07,$01 ; Room 139 - Skeleton - 9897
  DEFB $00,$0F,$00,$6B                 ;
  DEFB $8B,$19,$39,$06,$01,$00,$07,$02 ; Room 139 - Key (in skeleton) - 98CD
  DEFB $00,$05,$00,$7C,$C0,$0F,$48,$86 ;
  DEFB $8E,$14,$10,$8D,$01,$00,$03,$02 ; Room 142 - Spider - 98BB - when killed
  DEFB $0A,$09,$03,$7D,$00,$0F,$00,$2D ; reveals uncollectable scroll - 981B -
                                       ; see Bugs
  DEFB $8F,$22,$38,$45,$01,$04,$06,$01 ; Room 143 - MISSILE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $90,$30,$10,$45,$01,$04,$06,$01 ; Room 144 - MISSILE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $95,$18,$38,$05,$01,$00,$07,$01 ; Room 149 - Skeleton - 9897
  DEFB $00,$0F,$00,$6B                 ;
  DEFB $95,$18,$38,$06,$01,$07,$07,$02 ; Room 149 - REVEAL spell scroll (in
  DEFB $00,$05,$00,$7C,$C0,$0F,$00,$2D ; skeleton) - 981B
  DEFB $96,$16,$10,$05,$01,$1A,$0F,$02 ; Room 150 - CHALICE spell - 9821 (use
  DEFB $00,$10,$00,$7C,$40,$0F,$00,$30 ; REVEAL spell on wall)
  DEFB $9B,$34,$38,$05,$01,$09,$0F,$02 ; Room 155 - Wraith - 9865 - DISPEL to
  DEFB $00,$02,$00,$52,$40,$0F,$00,$2D ; obtain UNSEEN spell scroll - 981B
  DEFB $9D,$30,$10,$45,$01,$0A,$07,$01 ; Room 157 - OPEN spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $9E,$14,$3C,$05,$01,$00,$00,$02 ; Room 158 - Trapdoor - 990D (closed)
  DEFB $00,$05,$00,$A6,$00,$0F,$00,$A7 ; 990F (open)
  DEFB $9E,$14,$3C,$06,$01,$00,$07,$03 ; Room 158 - Spider (under trapdoor) -
  DEFB $00,$05,$00,$7C,$82,$03,$FE,$7D ; 98BB
  DEFB $00,$0F,$00,$7C                 ;
  DEFB $9E,$14,$34,$06,$01,$00,$06,$02 ; Room 158 - Key (under trapdoor) - 98E3
  DEFB $00,$05,$00,$7C,$C0,$0F,$4C,$91 ;
  DEFB $9F,$20,$3C,$05,$01,$00,$00,$02 ; Room 159 - Trapdoor - 990D (closed)
  DEFB $00,$4C,$00,$A6,$00,$0F,$00,$A7 ; 990F (open)
  DEFB $9F,$20,$3C,$05,$01,$00,$0F,$02 ; Room 159 - Healing orb - 98F9 (under
  DEFB $00,$4C,$00,$7C,$88,$0F,$FD,$9C ; trapdoor)
  DEFB $A2,$20,$20,$85,$01,$03,$03,$02 ; Room 162 - Bat - 98BF - destroy to get
  DEFB $07,$09,$FE,$7F,$40,$0F,$00,$2D ; UNLOCK spell scroll - 981B
  DEFB $A1,$14,$08,$8D,$01,$00,$03,$02 ; Room 161 - Spider - 98BB
  DEFB $02,$03,$FE,$7D,$00,$0F,$00,$7C ;
  DEFB $A4,$08,$08,$8D,$01,$00,$03,$02 ; Room 164 - Spider - 98BB
  DEFB $02,$03,$FE,$7D,$00,$0F,$00,$7C ;
  DEFB $A5,$24,$10,$45,$01,$19,$07,$01 ; Room 165 - FIND spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $A6,$24,$18,$C5,$01,$00,$06,$01 ; Room 166 - Sabre - 98FB
  DEFB $00,$0F,$09,$9D                 ;
  DEFB $A8,$1A,$18,$05,$01,$00,$0F,$01 ; Room 168 - Lady - 9911
  DEFB $00,$0F,$00,$A8                 ;
  DEFB $AA,$14,$10,$05,$01,$00,$0F,$02 ; Room 170 - Caliburn (use FIND spell) -
  DEFB $00,$08,$00,$7C,$C0,$0F,$07,$2E ; 981D
  DEFB $AA,$20,$34,$85,$01,$00,$06,$02 ; Room 170 - Scorpion - 98F1
  DEFB $02,$03,$FE,$98,$00,$0F,$00,$7C ;
  DEFB $B0,$24,$20,$45,$01,$05,$07,$01 ; Room 176 - ENERGIZE spell scroll -
  DEFB $00,$0F,$00,$2D                 ; 981B
  DEFB $B3,$14,$34,$05,$01,$00,$06,$02 ; Room 179 - Chest - 98CF (closed) 98D1
  DEFB $00,$04,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $B3,$14,$34,$06,$01,$00,$06,$03 ; Room 179 - Left half of key (in chest)
  DEFB $00,$04,$00,$7C,$C0,$54,$50,$A9 ; - 9913
  DEFB $40,$0F,$00,$91                 ;
  DEFB $B3,$14,$34,$06,$01,$03,$0F,$02 ; Room 179 - UNLOCK spell scroll (in
  DEFB $00,$04,$00,$7C,$40,$0F,$00,$2D ; chest) - 981B
  DEFB $B5,$24,$34,$05,$01,$00,$07,$02 ; Room 181 - Chest - 98CF (closed) 98D1
  DEFB $00,$04,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $B5,$24,$34,$06,$01,$00,$06,$03 ; Room 181 - Right half of key (in
  DEFB $00,$04,$00,$7C,$40,$50,$00,$AA ; chest) - 9915
  DEFB $C0,$0F,$54,$91                 ;
  DEFB $B7,$22,$38,$05,$01,$00,$06,$03 ; Room 183 - Chest - 98CF (closed) 98D1
  DEFB $00,$58,$00,$87,$00,$5C,$00,$87 ; (open) - requires two keys
  DEFB $00,$0F,$00,$88                 ;
  DEFB $B7,$22,$38,$06,$01,$00,$06,$03 ; Room 183 - Key (in chest) - 98E3
  DEFB $00,$58,$00,$7C,$00,$5C,$00,$7C ;
  DEFB $C0,$0F,$60,$91                 ;
  DEFB $B8,$14,$3A,$05,$01,$00,$07,$01 ; Room 184 - Skull pile - 98AD
  DEFB $00,$00,$0F,$76                 ;
  DEFB $B8,$14,$3A,$06,$01,$00,$06,$02 ; Room 184 - Key (under skulls) - 98CD
  DEFB $00,$05,$00,$7C,$C0,$0F,$58,$86 ;
  DEFB $B9,$23,$18,$C5,$01,$00,$06,$01 ; Room 185 - Key - 98CD
  DEFB $00,$0F,$5C,$86                 ;
  DEFB $BA,$20,$18,$45,$01,$17,$07,$01 ; Room 186 - VAPORIZE spell scroll -
  DEFB $00,$0F,$00,$2D                 ; 981B
  DEFB $BB,$16,$18,$45,$01,$18,$06,$01 ; Room 187 - FLAME spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $BC,$20,$3A,$85,$01,$00,$0F,$01 ; Room 188 - Orb (energy drain) - 98F9
  DEFB $00,$0F,$FE,$9C                 ;
  DEFB $BD,$40,$38,$05,$01,$00,$03,$02 ; Room 189 - Chest - 98CF (closed) 98D1
  DEFB $00,$64,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $BD,$40,$38,$06,$01,$10,$07,$02 ; Room 189 - FREEZE spell scroll (in
  DEFB $00,$64,$00,$7C,$40,$0F,$00,$2D ; chest) - 981B
  DEFB $BE,$24,$3A,$85,$01,$00,$0F,$01 ; Room 190 - Orb (healing) - 98F9
  DEFB $00,$0F,$FD,$9C                 ;
  DEFB $C0,$10,$08,$8D,$01,$00,$03,$02 ; Room 192 - Spider - 98BB
  DEFB $82,$03,$FE,$7D,$00,$0F,$00,$7C ;
  DEFB $C2,$20,$18,$C5,$01,$00,$06,$01 ; Room 194 - Oil jar - 9917
  DEFB $00,$0F,$64,$AB                 ;
  DEFB $C4,$18,$38,$05,$01,$00,$10,$01 ; Room 196 - Skeleton - 9897
  DEFB $00,$0F,$00,$6B                 ;
  DEFB $C4,$18,$38,$06,$01,$00,$06,$02 ; Room 196 - Key (in skeleton) - 98E3
  DEFB $00,$05,$00,$7C,$C0,$0F,$68,$91 ;
  DEFB $CC,$18,$38,$45,$01,$13,$06,$01 ; Room 204 - PORTAL spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $D0,$18,$3C,$05,$01,$00,$00,$02 ; Room 208 - Trapdoor - 990D (closed)
  DEFB $00,$68,$00,$A6,$00,$0F,$00,$A7 ; 990F (open)
  DEFB $D0,$18,$3C,$06,$01,$0E,$0F,$02 ; Room 208 - AMULET spell (under
  DEFB $00,$68,$00,$7C,$40,$0F,$00,$2F ; trapdoor) - 981F
  DEFB $38,$31,$38,$05,$01,$00,$06,$02 ; Room 56 - Chest - 98CF (closed) 98D1
  DEFB $00,$6C,$00,$87,$00,$0F,$00,$88 ; (open)
  DEFB $38,$31,$38,$06,$01,$00,$06,$02 ; Room 56 - Coin (in chest) - 9919
  DEFB $00,$6C,$00,$7C,$C0,$0F,$70,$AC ;
  DEFB $39,$1B,$18,$C5,$01,$00,$07,$03 ; Room 57 - Sabre (animated) - 9905
  DEFB $00,$01,$FE,$9D,$83,$05,$FE,$A2 ;
  DEFB $C1,$0F,$03,$A2                 ;
  DEFB $37,$18,$3A,$05,$01,$00,$06,$01 ; Room 55 - Altar - 991B
  DEFB $00,$0F,$00,$AD                 ;
  DEFB $37,$18,$38,$05,$01,$00,$07,$02 ; Room 55 - Key (place coin on altar)-
  DEFB $00,$70,$00,$7C,$C8,$0F,$20,$91 ; 98E3
  DEFB $3F,$18,$3A,$85,$01,$00,$06,$01 ; Room 63 - Fire - 991D
  DEFB $00,$0F,$FE,$AE                 ;
  DEFB $3F,$18,$3A,$C6,$01,$00,$06,$02 ; Room 63 - Fire symbol (in fire) - 9921
  DEFB $00,$8C,$74,$B0,$00,$0F,$00,$B8 ; - blank after use - 9931
  DEFB $40,$24,$10,$C5,$01,$00,$03,$02 ; Room 64 - Air symbol - 9927 - blank
  DEFB $00,$90,$78,$B3,$00,$0F,$00,$B8 ; after use - 9931
  DEFB $40,$20,$18,$85,$01,$00,$03,$02 ; Room 64 - Bat - 98BF
  DEFB $07,$03,$FE,$7F,$00,$0F,$00,$7C ;
  DEFB $44,$1A,$20,$45,$01,$05,$06,$01 ; Room 68 - ENERGIZE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $45,$1A,$40,$85,$01,$00,$05,$02 ; Room 69 - Spider - 98BB
  DEFB $02,$03,$FE,$7D,$00,$0F,$00,$7C ;
  DEFB $45,$18,$3A,$06,$01,$00,$05,$03 ; Room 69 - Water symbol (in pool) -
  DEFB $00,$05,$D0,$7C,$C0,$94,$7C,$B1 ; 9923 - blank after use - 9931
  DEFB $00,$0F,$00,$B8                 ;
  DEFB $45,$18,$3A,$05,$01,$00,$05,$01 ; Room 69 - Pool - 98B3
  DEFB $00,$0F,$00,$79                 ;
  DEFB $48,$14,$3A,$85,$01,$00,$07,$01 ; Room 72 - Skull pile - 98AD
  DEFB $00,$0F,$FE,$76                 ;
  DEFB $48,$14,$3A,$06,$01,$00,$06,$03 ; Room 72 - Scorpion (under skull pile)
  DEFB $00,$05,$00,$7C,$02,$03,$FE,$98 ; - 98F1
  DEFB $00,$0F,$00,$7C                 ;
  DEFB $48,$1A,$38,$85,$01,$00,$07,$01 ; Room 72 - Skull pile - 98AD
  DEFB $00,$0F,$FE,$76                 ;
  DEFB $48,$1A,$38,$06,$01,$00,$06,$02 ; Room 72 - Key (under skull pile) -
  DEFB $00,$05,$00,$7C,$C0,$0F,$6C,$86 ; 98CD
  DEFB $4B,$24,$34,$C5,$01,$00,$03,$01 ; Room 75 - Pick axe - 9929
  DEFB $00,$0F,$80,$B4                 ;
  DEFB $4C,$1A,$3C,$05,$01,$00,$00,$02 ; Room 76 - Trapdoor - 990D (closed)
  DEFB $00,$80,$00,$A6,$00,$0F,$00,$A7 ; 990F (open)
  DEFB $4C,$1A,$3C,$06,$01,$00,$06,$03 ; Room 76 - Scorpion (under trapdoor) -
  DEFB $00,$80,$00,$7C,$82,$03,$FE,$98 ; 98F1
  DEFB $00,$0F,$00,$7C                 ;
  DEFB $4C,$1A,$3C,$06,$01,$00,$06,$03 ; Room 76 - Earth symbol (under
  DEFB $00,$80,$00,$7C,$C0,$88,$84,$B2 ; trapdoor) - 9925 - blank after use -
  DEFB $00,$0F,$00,$B8                 ; 9931
  DEFB $4D,$30,$38,$85,$01,$00,$0F,$01 ; Room 77 - Healing fire - 991D
  DEFB $00,$0F,$FD,$AE                 ;
  DEFB $50,$1A,$10,$45,$01,$10,$07,$01 ; Room 80 - FREEZE spell scroll - 981B
  DEFB $00,$0F,$00,$2D                 ;
  DEFB $51,$20,$3A,$05,$01,$00,$0F,$05 ; Room 81 - Portal - floor symbol - 992B
  DEFB $00,$74,$00,$B5,$80,$78,$8C,$B5 ; - becomes door - 992D
  DEFB $80,$7C,$90,$B5,$80,$84,$94,$B5 ;
  DEFB $80,$0F,$88,$B6                 ;
  DEFB $D4,$54,$3A,$05,$01,$00,$0F,$02 ; Room 212 - Avelach, Lord of Chaos -
  DEFB $00,$07,$00,$B7,$80,$0F,$89,$B7 ; 992F
  DEFB $FF,$FF,$FF,$FF,$CA ; End-of-data bytes to signify end of room data

; Unidentified code (unused)
;
; The following code fragment is not used in the game
L7BD4:
  LD A,($EB50)
  LD C,A
  AND $01
  JP Z,$D282
  LD A,C
  AND $08
  JP Z,$CB02
  LD A,($EAB1)
  CP $F8
  JR Z,L7BD4_0
  CP $E8
  JR Z,L7BD4_1
  LD A,$F8
  JR L7BD4_2
L7BD4_0:
  LD A,$0C
  JR L7BD4_2
L7BD4_1:
  LD A,$08
L7BD4_2:
  LD B,A
  LD A,($EAD5)
  ADD A,B
  LD D,A
  DEFB $3A,$D4

; Launch the initial game menus
;
; Used by the routine at LBF1A.
;
; This CALL launches:
; * Menu 1 - to select game controls
; * Menu 2 - to choose a new game or load a saved game
L7C00:
  CALL L8039

; 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 L841A.
;
; The routine that follows at L7CAD adds the colours.
;
; Draw top two rows of decorative screen border
L7C03:
  LD A,$02                ; Number of character rows (2)
  LD ($8BB0),A            ;
  LD A,$20                ; Start in top left of screen display
  LD ($8BAF),A            ; Number of columns (32)
  LD HL,$4000             ;
  LD DE,L841A             ; Start of graphics
  CALL L81F3              ; Draw onto screen
; Draw left-hand column of decorative border (2 character columns, 14 rows)
  LD A,$02                ; Number of columns (2)
  LD ($8BAF),A            ;
  LD A,$0E                ; Number of character rows (14)
  LD ($8BB0),A            ;
  LD DE,$861A             ; Start of graphics data for this section
  LD HL,$4040             ; Set screen display address to starting position
  CALL L81F3              ; Draw onto screen
; Draw bottom left third of screen (devil and left-hand side of scroll)
  LD A,$07                ; 7 columns
  LD ($8BAF),A            ;
  LD A,$08                ; 8 character rows
  LD ($8BB0),A            ;
  LD DE,$86FA             ; Start of graphics data for this section
  LD HL,$5000             ; Set screen display to starting position
  CALL L81F3              ; Draw onto screen
; Draw right-hand column of decorative border (2 character columns, 14 rows)
  LD A,$02                ; Number of columns (2)
  LD ($8BAF),A            ;
  LD A,$0E                ; Number of character rows (14)
  LD ($8BB0),A            ;
  LD DE,$88BA             ; Start of graphics data for this section
  LD HL,$405E             ; Set screen display to starting position
  CALL L81F3              ; Draw onto screen
; Draw decorative scroll in bottom third of screen
  LD A,$12                ; 18 columns
  LD HL,$5007             ; Set and store screen display starting draw position
  LD ($8BAD),HL           ;
  LD ($8BAC),A            ; Store column counter (18)
L7C03_0:
  LD DE,$899A             ; 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,$01                ; Store number of columns (1)
  LD ($8BAF),A            ;
  LD A,$08                ; Store number of character rows (8)
  LD ($8BB0),A            ;
  LD HL,($8BAD)           ; Retrieve screen display address to draw at
  CALL L81F3              ; Draw on screen
  LD A,($8BAC)            ; Column drawn, so reduce column counter by 1
  DEC A                   ; If all 18 columns are done, jump to next section
  JR Z,L7C03_1            ;
  LD ($8BAC),A            ; Re-store column counter
  LD HL,($8BAD)           ; Retrieve display screen address pointer
  INC HL                  ; Move it one character to the right...
  LD ($8BAD),HL           ; ...and store it
  JR L7C03_0              ; Continue onto next column
; Tiny manual graphic tweak to bottom right of scroll (2 bytes)
L7C03_1:
  LD HL,$57D7             ; Screen display address position
  LD (HL),$07             ;
  INC HL                  ; ...and the one to its right.
  LD (HL),$FF             ;
; Small scroll overlap in bottom right
  LD HL,$50F7             ; Set screen display to starting position
  LD DE,$8B9A             ; Point to start of graphics data
  LD A,$02                ; Number of columns (2)
  LD ($8BAF),A            ;
  LD A,$01                ; Number of character rows (1)
  LD ($8BB0),A            ;
  CALL L81F3              ; 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,$07                ; Number of columns (7)
  LD ($8BAF),A            ;
  LD A,$08                ; Number of character rows (8)
  LD ($8BB0),A            ;
  LD DE,$89DA             ; Point to start of graphics data
  LD HL,$5019             ; Set screen display to starting position
  CALL L81F3              ; Draw onto screen

; Draw game screen decorative border (colours)
;
; The previous drawing routine at L7C03 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).
L7CAD:
  LD HL,$5800             ; Start of screen display attribute area (top left)
  LD B,$00                ; This will run the routine 256 times (first
                          ; iteration will DEC B which puts it at 255)
L7CAD_0:
  LD (HL),$30             ; Set byte to INK 0, PAPER 6.
  INC HL                  ; ...and the next one...
  LD (HL),$30             ;
  INC HL                  ; ...and also a third one...
  LD (HL),$30             ;
  INC HL                  ;
  DJNZ L7CAD_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,$5842
  LD C,$0E                ; Number of character rows to colour (14)
L7CAD_1:
  LD B,$1C                ; Number of columns to colour (28)
L7CAD_2:
  LD (HL),$04             ; Set colour to green (INK 4, PAPER 0)
  INC HL                  ; Move to next attribute square
  DJNZ L7CAD_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,L7CAD_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,$581C
  LD (HL),$20             ; INK 0, PAPER 4
  INC HL                  ;
  LD (HL),$20             ;
  LD HL,$583D             ; ...and the square below
  LD (HL),$20             ;
; Next, the strip of rightmost two columns for the first 12 screen character
; rows
  LD HL,$581E
  LD B,$0C                ; 12 rows
  LD DE,$001E             ; Offset ready to add to move down to the next
                          ; character line
L7CAD_3:
  LD (HL),$20             ; Set the two attributes to green
  INC HL                  ;
  LD (HL),$20             ; INK 0, PAPER 4
  INC HL                  ;
  ADD HL,DE               ; Move down to the next row
  DJNZ L7CAD_3            ; Repeat for the 12 rows
; Strip of 3 cyan attributes for the dragon's belly in the right column
  LD HL,$589E
  LD (HL),$28             ; INK 0, PAPER 5
  LD HL,$58BE             ;
  LD (HL),$28             ;
  LD HL,$58DE             ;
  LD (HL),$28             ;
; Colour the winged skull at the top of the screen in magenta
  LD HL,$580A
  LD B,$0C                ; 12 columns
L7CAD_4:
  LD (HL),$18             ; INK 0, PAPER 3
  INC HL                  ; Move along the next square and repeat 12 times
  DJNZ L7CAD_4            ;
  LD HL,$5829             ; Repeat for the second row of the winged skull
  LD B,$0E                ; A couple more squares (14) for this line
L7CAD_5:
  LD (HL),$18             ; INK 0, PAPER 3
  INC HL                  ;
  DJNZ L7CAD_5            ;
; The above routine has also covered the skull between the wings magenta. So
; we'll re-colour it white:
  LD HL,$580F             ; Display attribute address for skull in middle of
                          ; top border
  LD (HL),$38             ; Colour the next two squares white (INK 0, PAPER 7)
  INC HL                  ;
  LD (HL),$38             ;
  LD HL,$582F             ; Do the same for the second row of the skull
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
  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,$5820             ; Starting point in screen display attributes
  LD B,$17                ; 23 rows
  LD DE,$0020             ; Offset ready to add to jump to the next character
                          ; row
L7CAD_6:
  LD (HL),$20             ; INK 0, PAPER 4
  ADD HL,DE               ; Jump to the next row and repeat (23 rows)
  DJNZ L7CAD_6            ;
; Yellow bit of snake's tail midway down the screen, left column:
  LD HL,$5980
  LD (HL),$30             ; 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,$59A1
  LD (HL),$20             ; For consistency this value should probably be 48 -
  LD HL,$5802             ; 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),$20             ; INK 0, PAPER 4 (green) for the first two blocks
  INC HL                  ;
  LD (HL),$20             ;
  INC HL                  ;
  LD (HL),$28             ; INK 0, PAPER 5 (cyan) for the small spider
  INC HL                  ;
  LD (HL),$20             ; ...then back to green for the last two blocks of
  INC HL                  ; the snake's head
  LD (HL),$20             ;
; Two squares of the bottom of the snake's head (green)
  LD HL,$5825
  LD (HL),$20             ; INK 0, PAPER 4
  INC HL                  ;
  LD (HL),$20             ;
; Two squares for skull in top left of screen (white)
  LD HL,$5800
  LD (HL),$38             ; INK 0, PAPER 7 (white)
  INC HL                  ;
  LD (HL),$38             ;
; 4 red character squares in the fire breathed by the dragon in the top right
; of the screen
  LD HL,$5817
  LD (HL),$10             ; INK 0, PAPER 2
  LD HL,$5839             ;
  LD (HL),$10             ;
  LD HL,$5819             ;
  LD (HL),$10             ;
  LD HL,$583B             ;
  LD (HL),$10             ;
; 7 red character squares in the devil's wing that overlaps the left column
  LD HL,$59A0
  LD (HL),$10
  LD HL,$59C0
  LD (HL),$10
  INC HL
  LD (HL),$10
  LD HL,$59E0
  LD (HL),$10
  INC HL
  LD (HL),$10
  LD HL,$5A00
  LD (HL),$10
  INC HL
  LD (HL),$10
; ...And red squares for the rest of the devil - 6 rows x 3 characters
  INC HL                  ; Move to starting position
  LD B,$06                ; 6 rows
  LD DE,$001D             ; 29 spaces - offset to allow moving to position in
                          ; next line (plus 3 squares filled = 32)
L7CAD_7:
  LD (HL),$10             ; INK 0, PAPER 2 (red) for 3 squares
  INC HL                  ;
  LD (HL),$10             ;
  INC HL                  ;
  LD (HL),$10             ;
  INC HL                  ;
  ADD HL,DE               ; Add offset to move attribute display address to
                          ; next line
  DJNZ L7CAD_7            ; Repeat colouring for the 6 rows of the devil
  LD HL,$5A21             ; ...And red for the last bit of devil wing
  LD (HL),$10             ; overlapping the pillar
; 4 character squares of white for the bottom of the word 'MAGIC' in the bottom
; left corner
  LD HL,$5AE2
  LD (HL),$38             ; INK 0, PAPER 7 (white)
  INC HL                  ;
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
; Strip of 20 white attribute squares for the very top of the scroll
  LD HL,$5A06
  LD B,$14                ; 20 squares to colour
L7CAD_8:
  LD (HL),$38             ; INK 0, PAPER 7 (white)
  INC HL                  ; Move right to next square
  DJNZ L7CAD_8            ; Repeat for all 20
; A bunch of white squares for the angel in the bottom right of the screen
  LD HL,$5A1C
  LD (HL),$38             ; INK 0, PAPER 7 (white)
  LD HL,$59BF             ;
  LD (HL),$38             ;
  LD HL,$59DF             ;
  LD (HL),$38             ;
  LD HL,$59FE             ;
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
  LD HL,$5A0D             ; The next 3 squares are in the top of the scroll
  LD (HL),$38             ; which has already been coloured in 7DB0, so the
  INC HL                  ; code for colouring these 3 squares is unnecessary
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
  LD HL,$5A1D             ; Other various white squares for the angel
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
  LD HL,$5A3D             ;
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
  LD HL,$5A5D             ;
  LD (HL),$38             ;
  INC HL                  ;
  LD (HL),$38             ;
; A couple of cyan squares in the 'wispy bits' to the left of the angel:
  LD HL,$5A9B
  LD (HL),$28             ; INK 0, PAPER 5 (cyan)
  LD HL,$5ABA             ;
  LD (HL),$28             ;
  INC HL                  ; ...and a couple of green ones between them
  LD (HL),$20             ; INK 0, PAPER 4 (green)
  LD HL,$5ADA             ;
  LD (HL),$20             ;
; ...and a few more cyan & green squares to the right of the angel
  LD HL,$5A3F
  LD DE,$0020             ; Offset of 32 spaces to add to display address to
                          ; move to line below
  LD (HL),$28             ; INK 0, PAPER 5 (cyan)
  ADD HL,DE               ; ADD HL, DE moves the screen display address down
  LD (HL),$28             ; one character square
  ADD HL,DE               ;
  LD (HL),$28             ;
  ADD HL,DE               ;
  LD (HL),$20             ; INK 0, PAPER 4 (green)
  ADD HL,DE               ;
  LD (HL),$20             ;
  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 L825F.
;
; The border on the left hand side of the screen is drawn first:
L7E21:
  LD A,$01                ; 1 column
  LD ($8BAF),A            ;
  LD A,$0C                ; 12 rows
  LD ($8BB0),A            ;
  LD HL,L825F             ; Address pointer for left-hand border graphic
  LD (L7CAD_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,$4062             ; Set screen display address
  CALL L8227              ; Drawing routine (to draw the graphic 12 times in a
                          ; vertical line)
; ...Then the border on the right hand side
  LD A,$01                ; 1 column
  LD ($8BAF),A            ;
  LD A,$0C                ; 12 rows
  LD ($8BB0),A            ;
  LD HL,$827F             ; Address pointer for right-hand border graphic
  LD (L7CAD_2),HL         ; Store the border graphic address. This looks like a
                          ; mistake as it seems to be overwriting earlier code
                          ; at L7CAD_2. However, this code is part of the
                          ; decorative border drawing so doesn't need to be
                          ; executed again.
  LD HL,$407D             ; Set screen address
  CALL L8227              ; Drawing routine (to draw the graphic 12 times in a
                          ; vertical line)
; Draw the top right 'corner piece' of the border
  LD A,$01                ; Just 1 character (1 row, 1 column)
  LD ($8BAF),A            ;
  LD A,$01                ;
  LD ($8BB0),A            ;
  LD HL,$8287             ; Store address of top right-hand corner graphic
  LD (L7CAD_2),HL         ;
  LD HL,$405D             ; Set screen display address
  CALL L8227              ; Draw the graphic
; Draw the bottom left 'corner piece' of the border
  LD A,$01                ; Just 1 character (1 row, 1 column)
  LD ($8BAF),A            ;
  LD A,$01                ;
  LD ($8BB0),A            ;
  LD HL,$8267             ; Store address of bottom left-hand corner graphic
  LD (L7CAD_2),HL         ;
  LD HL,$48E2             ; Set screen display address
  CALL L8227              ; Draw the graphic
; Draw the bottom right 'corner piece' of the border
  LD A,$01                ; Just 1 character (1 row, 1 column)
  LD ($8BAF),A            ;
  LD A,$01                ;
  LD ($8BB0),A            ;
  LD HL,$8277             ; Store address of bottom right-hand corner graphic
  LD (L7CAD_2),HL         ;
  LD HL,$48FD             ; Set screen display address
  CALL L8227              ; Draw the graphic
; Draw bottom border
  LD A,$1A                ; 26 columns to draw
  LD ($8BAF),A            ;
  LD A,$01                ; 1 row
  LD ($8BB0),A            ;
  LD HL,$828F             ; Store address of bottom border graphic
  LD (L7CAD_2),HL         ;
  LD HL,$4043             ; Set screen display address
  CALL L8227              ; Draw the border
; Draw top border
  LD A,$1A                ; 26 columns to draw
  LD ($8BAF),A            ;
  LD A,$01                ; 1 row
  LD ($8BB0),A            ;
  LD HL,$826F             ; Store address of bottom border graphic
  LD (L7CAD_2),HL         ;
  LD HL,$48E3             ; Set screen display address
  CALL L8227              ; Draw the border
; Draw the top left 'corner piece' of the border
  LD A,$01                ; Just 1 character (1 row, 1 column)
  LD ($8BAF),A            ;
  LD A,$01                ;
  LD ($8BB0),A            ;
  LD HL,$8297             ; Store address of top left-hand corner graphic
  LD (L7CAD_2),HL         ;
  LD HL,$4042             ; Set screen display address
  CALL L8227              ; Draw the graphic
; Now set the colours (dark blue) to the top 6 lines of the 'inner screen'
; (including the border)
  LD HL,$5842             ; Set the display address position on screen (top
                          ; left)
  LD C,$06                ; 6 rows to colour
L7E21_0:
  LD B,$1C                ; 28 columns across the screen
L7E21_1:
  LD (HL),$08             ; Set colour of block to blue (INK 0, PAPER 1)
  INC HL                  ; Move right to the next square
  DJNZ L7E21_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,L7E21_0           ; Repeat until colour in all rows coloured
; Set colour for the sky section (stars/moon) to white
  LD (L7CAD_2),HL         ; Pointer is now beneath the first 6 rows - store it
  LD HL,$5863             ; Set screen address pointer to just inside the top
                          ; left border
  LD C,$02                ; Top 2 rows of the picture
L7E21_2:
  LD B,$1A                ; ...and 26 columns, just inside the border
L7E21_3:
  LD (HL),$0F             ; Set the screen attribute block colour (INK 7, PAPER
                          ; 1)
  INC HL                  ; Move right to the next character square
  DJNZ L7E21_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,L7E21_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,(L7CAD_2)         ; Retrieve the screen attribute display address
                          ; pointer, just over a third of the way down the
                          ; screen
  LD C,$08                ; 8 rows to colour
L7E21_4:
  LD B,$1C                ; 28 columns (this will also include the bottom half
                          ; of the border)
L7E21_5:
  LD (HL),$00             ; INK 0, PAPER 0
  INC HL                  ; Move right to the next character square
  DJNZ L7E21_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,L7E21_4           ; are coloured in
; Set the bottom part of the intro screen to yellow (this will be Maroc's
; colour)
  LD HL,(L7CAD_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,$07                ; 7 rows to colour in
L7E21_6:
  LD B,$1A                ; ...and 26 columns
L7E21_7:
  LD (HL),$06             ; Set colour of the square to  yellow - INK 0, PAPER
                          ; 7
  INC HL                  ; Move right to the next square
  DJNZ L7E21_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,L7E21_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 829F.
;
; Draw a 1-character high middle strip of the landscape containing most of the
; rolling hills
L7F25:
  LD A,$1A                ; Strip of landscape, 26 columns wide
  LD ($8BAF),A            ;
  LD A,$01                ; 1 (character) row high
  LD ($8BB0),A            ;
  LD DE,$829F             ; Pointer to landscape graphics data
  LD HL,$40E3             ; Set screen display address to the left/middle of
                          ; the screen
  CALL L81F3              ; Draw graphics
; Draw the small trilith-shaped structure over on the left of the scene
  LD A,$01                ; Just 1 character to draw so 1 column, 1 row
  LD ($8BAF),A            ;
  LD A,$01                ;
  LD ($8BB0),A            ;
  LD DE,$8377             ; Point to graphics data
  LD HL,$40C9             ; Point to screen location to draw at
  CALL L81F3              ; Draw on screen
; Draw top section of the thin vertical structure in middle of landscape
  LD A,$01                ; Just 1 character to draw (1 column, 1 row)
  LD ($8BAF),A            ;
  LD A,$01                ;
  LD ($8BB0),A            ;
  LD DE,$837F             ; Point at graphics data
  LD HL,$40D0             ; Point to place on screen to draw at
  CALL L81F3              ; Draw graphics
; Cyan highlighted structure on the right of the screen
  LD A,$04                ; 4 columns
  LD ($8BAF),A            ;
  LD A,$01                ; 1 row
  LD ($8BB0),A            ;
  LD DE,$8387             ; Point at graphics data
  LD HL,$40D4             ; Point at place on screen to draw at
  CALL L81F3              ; Draw to screen
; Highest highlighted structure visible over on the right
  LD A,$02                ; 2 columns
  LD ($8BAF),A            ;
  LD A,$01                ; 1 row
  LD ($8BB0),A            ;
  LD DE,$83A7             ; Point at graphics data
  LD HL,$40B5             ; Point at place on screen to draw at
  CALL L81F3              ; Draw to screen
; Set the 2 cyan attributes on the structure over on the right
  LD HL,$58B5             ; First highlight on slightly higher part
  LD (HL),$0D             ; Cyan colour (INK 5, PAPER 1)
  LD HL,$58D4             ; ...and the part to its lower-left
  LD (HL),$0D             ;
; Lower part of tall cyan highlighted tower structure
  LD A,$04                ; 4 columns
  LD ($8BAF),A            ;
  LD A,$01                ; 1 row
  LD ($8BB0),A            ;
  LD DE,$83B7             ; Point at graphics data
  LD HL,$480F             ; Point at place on screen to draw at
  CALL L81F3              ; Draw to screen
; Set the highlight colour and a few other attributes alongside it
  LD HL,$590F             ; The bottom of the tower cyan highlight/reflection
                          ; just drawn
  LD (HL),$05             ; Set to cyan (INK 5, PAPER 0)
  INC HL                  ; Set the 3 squares to the right of it to blue/black
  LD (HL),$08             ; (INK 0, PAPER 1)
  INC HL                  ;
  LD (HL),$08             ;
  INC HL                  ;
  LD (HL),$08             ;
; Draw the moon
  LD HL,$408D             ; Point at place on screen to draw at
  LD A,$01                ; Just 1 character so 1 column, 1 row
  LD ($8BB0),A            ;
  LD ($8BAF),A            ;
  LD DE,$83D7             ; Point at moon graphic data
  CALL L81F3              ; Draw it on screen
; Stars in top right of screen
  LD HL,$4079             ; Drawing position set to top right of scene
  LD A,$01                ; 1 row
  LD ($8BB0),A            ;
  LD A,$03                ; 3 columns (characters) to draw
  LD ($8BAF),A            ;
  LD DE,$83DF             ; Point at stars graphic data
  CALL L81F3              ; Draw them on screen
; Stars in top left of screen
  LD HL,$4085             ; Draw position in top left of scene
  LD A,$01                ; Just 1 character - 1 row, 1 column
  LD ($8BB0),A            ;
  LD ($8BAF),A            ;
  LD DE,$83F8             ; Point at graphics data
  CALL L81F3              ; Draw them on screen
; Cyan moon reflection colour and then graphic on right of small trilith
  LD HL,$58CA             ; Attribute display address location
  LD (HL),$0D             ; Cyan colour (INK 5, PAPER 1)
  LD HL,$40CA             ; Screen address display location for graphic
  LD A,$01                ; 1 character (1 row, 1 column)
  LD ($8BB0),A            ;
  LD ($8BAF),A            ;
  LD DE,$8400             ; Point at graphics data
  CALL L81F3              ; Draw on screen
; Cyan moon reflection colour and then graphic on top of small trilith
  LD HL,$58A9             ; Attribute display address location
  LD (HL),$0D             ; Cyan colour (INK 5, PAPER 1)
  LD HL,$40A9             ;
  LD A,$01                ; 1 character (1 row, 1 column)
  LD ($8BB0),A            ;
  LD ($8BAF),A            ;
  LD DE,$8408             ; Point at graphics data
  CALL L81F3              ; Draw on screen
; Cyan moon reflection colour and then graphic on left of small vertical tower
  LD HL,$58EF             ; Second character square of tower screen attribute
                          ; display position
  LD (HL),$0D             ; Cyan colour (INK 5, PAPER 1)
  LD HL,$58CF             ; Top character square of tower screen attribute
                          ; display position
  LD (HL),$0D             ; Cyan (INK 5, PAPER 1)
; Next, the graphics
  LD A,$02                ; 2 (vertical) rows
  LD ($8BB0),A            ;
  LD A,$01                ; 1 (character-wide) column
  LD ($8BAF),A            ;
  LD HL,$8410             ; Point at graphics data
  LD (L7CAD_2),HL         ;
  LD HL,$40CF             ;
  CALL L8227              ; 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,(L8BAA)            ; Retrieve the Menu Controls option selected (1-4)
  LD E,A                  ; ...and store it in the E register
  LD A,($8BAB)            ; 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 L7C00.
;
; Prints the first of two menus on screen - this one is for the player to
; select their controls. The text is stored at L8BC2.
L8039:
  LD A,$00                ; Reset menu option to 'none selected'
  LD (L8BAA),A            ;
; Clear the screen
  CALL L815B              ; Clear the screen (pixels)
  LD A,$0F                ; Set INK 7 (white), PAPER 1 (blue)
  CALL L815B_1            ; Set screen colours
; Print the menu
  LD HL,$4021             ; Set menu starting PRINT position at row 1, column 1
  LD DE,L8BC2             ; Store the address of the start of the menu text
  LD ($8BC0),DE           ;
  CALL L8179              ; Print first line of menu text "PRESS 1-4 TO CHANGE
                          ; OPTION"
  LD HL,$4043             ; Set PRINT position at 2,3 (row/column)
  CALL L8179              ; Print next line of menu text "ENTER TO START
                          ; PROGRAM"
  LD HL,$40A1             ; Set PRINT position at 5,1
  CALL L8179              ; Print "1   KEMPSTON JOYSTICK (PORT 31)"
  LD HL,$40E1             ; Set PRINT position at 7,1
  CALL L8179              ; Print "2   AGF JOYSTICK (CURSOR KEYS)"
  LD HL,$4821             ; Set PRINT position at 9,1
  CALL L8179              ; Print "3   SINCLAIR JOYSTICK"
  LD HL,$4861             ; Set PRINT position AT 11,1
  CALL L8179              ; Print "4   KEYBOARD SET UP AS FOLLOWS"
  LD HL,$48A3             ; Set PRINT position AT 13,3
  CALL L8179              ; 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,$8C82             ; Store the address of the text for the controls
  LD ($8BC0),DE           ;
  LD HL,$48E1             ; Set PRINT position at 15,1 (row/column)
  LD A,$05                ; Store count of 5 sets of keys to PRINT (up, down,
  LD ($8BAC),A            ; left, right & fire)
  LD ($8BBB),HL           ; Store screen print position
L8039_0:
  CALL L8179              ; PRINT text on screen
  LD HL,($8BBB)           ; Retrieve screen print position
  INC HL                  ; Move forward 6 character spaces
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  LD ($8BBB),HL           ; ...and store the updated screen address position
  LD A,($8BAC)            ; Retrieve, decrement and re-store counter (x 5 sets)
  DEC A                   ;
  LD ($8BAC),A            ;
  JR NZ,L8039_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 L80FD.
;
; Checks if the player has picked a control option on menu 1 (L8039).
L80A1:
  LD BC,$F7FE             ; 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,L80A1_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 L80C1.
  LD B,$04                ; 4 port addresses to check
  LD HL,$8BB2             ; Address pointer to where the port addresses are
                          ; held
; Loop through port addresses
L80A1_0:
  CP (HL)                 ; Compare with keyboard input
  JR Z,L80C1              ; If a valid key has been pressed, jump to L80C1 to
                          ; play a sound and highlight the choice on screen
  INC HL                  ; Otherwise advance to the next (2 byte) port address
  INC HL                  ;
  DJNZ L80A1_0            ; ...and keep checking until all 4 are done.
; Check if a key press has been registered already
L80A1_1:
  LD A,(L8BAA)            ; Has a menu option (1-4) been chosen yet?
  CP $00                  ;
  JR Z,L80A1              ; If not, go back to checking keys at L80A1
  JR L80FD                ; 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 L80A1.
;
; HL Address pointer for the relevant port address at 8BB2 relating to the key
;    that's been pressed.
;
; The player has picked a valid controls option on menu 1 (L8039). Store the
; choice number (1-4), play a high pitched sound and highlight their choice on
; screen.
L80C1:
  INC HL                  ; Advance to the second byte of the pair (to give the
                          ; number)
  LD A,(HL)               ; Identify key pressed (1-4)
  LD (L8BAA),A            ; ...and store it
; Play a high pitched sound (and also set the border to black)
  LD C,$FF                ; C register contains the outer loop counter for the
                          ; sound duration
  LD HL,$3333             ; H = 51, L = 51 - but also used as a token address
                          ; pointer somewhere in ROM
; Outer loop start - toggle speaker on and pause briefly
L80C1_0:
  LD B,$10                ; Pause duration
  LD A,$10                ; Set bit 4 - speaker bit
  OUT ($FE),A             ; Output it (speaker toggle = on)
L80C1_1:
  DJNZ L80C1_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 L80C1_2.
  LD H,(HL)
  ADD A,H
  ADD A,L
  AND $0F
  ADD A,$60
  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,$00                ; Reset the A register (reset speaker bit)
  OUT ($FE),A             ; Output it (speaker toggle = off)
L80C1_2:
  DJNZ L80C1_2            ; Another short pause
  DEC C                   ; Decrement the outer loop counter
  JR NZ,L80C1_0           ; ...and repeat until zero.
; Highlight/flash the menu option selected
  LD A,(L8BAA)            ; Get the menu option selected (1-4)
  LD HL,$58A1             ; Screen attribute display position for first option
                          ; (Kempston)
  LD DE,$0040             ; 64 characters = 2 lines to jump down to next option
  LD B,$04                ; Four menu options to check (1-4)
  LD C,$01                ; Start with 1
L80C1_3:
  LD (HL),$0F             ; Reset colour/attribute for this option (INK 7,
                          ; PAPER 1)
  CP C                    ; Is it this option that's selected?
  JR NZ,L80C1_4           ;
  LD (HL),$CF             ; ...If so, set attribute to FLASH 1, BRIGHT 1
L80C1_4:
  ADD HL,DE               ; Move attribute screen address down two lines to
                          ; next option
  INC C                   ; Increment...
  DJNZ L80C1_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 L80C1, or a jump from 80BF, 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.
L80FD:
  LD BC,$BFFE             ; 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,L80A1              ; If ENTER isn't being pressed, return to checking
                          ; keys for other menu options
; ENTER has been pressed, player controls choice confirmed.
  CALL L815B              ; Clear the screen (pixels)
; ENTER is still being pressed - wait until the key has been released
L80FD_0:
  LD BC,$BFFE             ; 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,L80FD_0           ; If so, keep checking until it's been released
; ENTER has now been released
  LD A,$0F                ; Set the screen attributes to INK 7, PAPER 1
  CALL L815B_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.
L811B:
  LD DE,L8C9A             ; Get the address pointer for the first line of menu
                          ; text to PRINT
  LD HL,$4083             ; Set the screen address for the first line
  CALL L8179              ; Print the text string ("PRESS ENTER FOR NEW GAME")
  LD DE,$8CB3             ; Get the address pointer for the second line of menu
                          ; text
  LD HL,$40C3             ; Set the screen address for the second line ("PRESS
                          ; LOAD FOR SAVED GAME")
  CALL L8179              ; Print the text string

; Menu 2: Check for ENTER or LOAD keys being pressed
;
; Second menu (L811B) - checks for one of two key press options (both checked
; using the same keyboard port).
L812D:
  LD BC,$BFFE             ; 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,$00                ; Set "New Game" flag (0) in advance of a positive
                          ; check
  JR Z,L812D_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,L812D              ; If it's not being pressed, jump back and keep
                          ; scanning for ENTER or LOAD keys
; LOAD ("J") has been pressed
  CALL L815B              ; LOAD has been selected. Clear the screen (pixels)
  LD DE,L8CCD             ; Get address of text string ("LOAD SAVED GAME")
  LD HL,$48C8             ; Set screen position for printing text
  CALL L8179              ; Print "LOAD SAVED GAME" on screen
  LD A,$01                ; 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)
L812D_0:
  LD ($8BAB),A            ; Store game flag (0 = New Game, 1 = Load Saved Game)
  CP $01                  ;
  JR Z,L812D_1            ; Load game - don't clear the screen (skip the next
                          ; instruction to leave "LOAD SAVED GAME" message
                          ; on-screen)
  CALL L815B              ; New game - clear the screen (pixels)
L812D_1:
  RET                     ;

; Clear the menu screen
;
; Used by the routines at L8039, L80FD and L812D.
;
; 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):
L815B:
  LD HL,$4000             ; Top left of screen display
  LD DE,$1800             ; Number of bytes to clear
L815B_0:
  LD (HL),$00             ; Clear screen pixels
  INC HL                  ; Move to next screen byte position
  DEC DE                  ; Decrement byte counter
  LD A,E                  ;
  OR D                    ;
  JR NZ,L815B_0           ; Keep clearing until counter = 0
  RET                     ;
; Clear the screen (colours):
L815B_1:
  LD HL,$5800             ; Top left of (attribute) screen display
  LD DE,$0300             ; Number of bytes
  LD C,A                  ; Retrieve attribute/colour value to use
L815B_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,L815B_2           ; Keep colouring until counter = 0
  RET                     ;

; Menu text PRINT routine
;
; Used by the routines at L8039, L811B and L812D.
;
; Routine that prints a string of text for menu 1 (L8039) and menu 2 (L811B).
; The menu font used is the standard ZX Spectrum ROM character set, rather than
; the in-game text characters.
L8179:
  LD DE,($8BC0)           ; Get the address pointer for the address of the text
                          ; to print (e.g. L8BC2/L8C9A).
  LD A,(DE)               ; Get first byte = length of text string
  INC DE                  ; Increment to start of text string, and store
  LD ($8BC0),DE           ; address
  LD ($8BBD),A            ; Store the length of string (number of characters)
  LD ($8BBE),HL           ; Store screen address position
; Loop for printing the text characters on screen
L8179_0:
  LD DE,($8BC0)           ; Get the next text character to print
  LD A,(DE)               ;
  INC DE                  ; Increment to next text character and store address
  LD ($8BC0),DE           ; for future printing
  LD HL,($5C36)           ; Get pointer to the ZX Spectrum character set
                          ; (CHARS)
  LD D,$00                ; Get the text character's ASCII value (store in DE
  LD E,A                  ; register pair)
  LD B,$08                ; 8 pixel rows to print
L8179_1:
  ADD HL,DE               ; Calculate the address of the character in the
  DJNZ L8179_1            ; character set ready to print [CHARS address +
  EX DE,HL                ; (character ASCII value x 8)] and swap into DE
  LD HL,($8BBE)           ; Get the screen address position
  LD C,H                  ; Preserve screen address of top pixel row in C
                          ; register
  LD B,$08                ; 8 pixel lines to print
; Draw the 8 pixel row bytes of the text character
L8179_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 L8179_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 ($8BBE),HL           ; ...and store this screen address ready for next
                          ; character
  LD A,($8BBD)            ; Decrement and re-store the text length counter
  DEC A                   ;
  LD ($8BBD),A            ;
  JR NZ,L8179_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
; LC07A/LE610.
L81BA:
  LD C,A                  ; Routine not used
  RLA                     ;
  RLA                     ;
  RLA                     ;
  AND $38                 ;
  LD B,A                  ;
  LD HL,$5842             ;
  LD DE,$0000             ;
  LD A,$07                ;
L81BA_0:
  LD ($8BB0),A            ;
  LD A,$1C                ;
L81BA_1:
  LD ($8BAF),A            ;
  LD A,(HL)               ;
  ADD A,C                 ;
  AND $07                 ;
  LD E,A                  ;
  LD A,(HL)               ;
  ADD A,B                 ;
  AND $38                 ;
  OR E                    ;
  LD (HL),A               ;
  INC HL                  ;
  LD A,($8BAF)            ;
  DEC A                   ;
  JR NZ,L81BA_1           ;
  LD A,(DE)               ;
  INC DE                  ;
  OUT ($FE),A             ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  LD A,($8BB0)            ;
  DEC A                   ;
  JR NZ,L81BA_0           ;
  RET                     ;
  RET                     ;

; Drawing routine (decorative border and intro sequence background)
;
; Used by the routines at L7C03 and L7F25.
;
; HL Screen display address position to draw at
; DE Start address for graphics to be drawn
;
; Number of character columns to draw stored at 8BAF. Number of character rows
; at 8BB0.
L81F3:
  LD C,H                  ; Copy high byte of display address position to C
                          ; register
L81F3_0:
  LD A,($8BAF)            ; Copy counter for number of columns to draw into
  LD ($8BB1),A            ; working buffer
L81F3_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,$08                ; 8 pixel rows to draw
L81F3_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 L81F3_2            ; Repeat for 8 pixel rows
  INC L                   ; Move right one character position on screen
  LD A,($8BB1)            ; Retrieve, decrement and re-store the column counter
  DEC A                   ;
  LD ($8BB1),A            ;
  JR NZ,L81F3_1           ; Keep drawing until all columns are done
; Calculate the screen display address for the next (character) row:
  LD A,($8BAF)            ; Get the total number of columns drawn
  LD B,A                  ; Store in B register
  LD A,$21                ; 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,L81F3_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,$08               ; address accordingly
  LD C,A                  ;
; Continue to draw rows of graphics:
L81F3_3:
  LD A,($8BB0)            ; Get the number of rows to draw
  DEC A                   ; Reduce by one
  LD ($8BB0),A            ; ...and re-store
  JR NZ,L81F3_0           ; All rows finished? If not, continue to draw the
  RET                     ; graphics.

; Drawing routine used for intro sequence graphics
;
; Used by the routines at L7E21 and L7F25.
;
; HL Screen display address to draw at
L8227:
  LD C,H                  ; Store screen display address high byte in C
                          ; register
L8227_0:
  LD A,($8BAF)            ; Get number of columns to draw
  LD ($8BB1),A            ; Store as a counter
L8227_1:
  LD H,C                  ; Retrieve screen display address from C register
  LD B,$08                ; 8 pixel lines to draw
  LD DE,(L7CAD_2)         ; Retrieve address pointing to graphics to draw
; Draw a series of character column graphics:
L8227_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 L8227_2            ; Repeat until 8 pixel lines printed
  INC L                   ; Move right 1 square on screen
  LD A,($8BB1)            ; Retrieve the graphic column counter
  DEC A                   ; ...Decrement it...
  LD ($8BB1),A            ; ...And re-store it...
  JR NZ,L8227_1           ; Keep drawing until column counter = 0
; Recalculate screen display address for next character row of graphics:
  LD A,($8BAF)            ; Retrieve column counter
  LD B,A                  ;
  LD A,$21                ; 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,L8227_3           ; Check that we're not crossing a 1/3 screen boundary
  LD A,C                  ; Crossing a 1/3 screen boundary, so
  ADD A,$08               ; 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:
L8227_3:
  LD A,($8BB0)            ; Retrieve row counter
  DEC A                   ; Decrement and re-store it
  LD ($8BB0),A            ;
  JR NZ,L8227_0           ; Continue drawing until counter = 0
  RET                     ;

; Graphics: Intro sequence inner border & backdrop
;
; Drawn in the routine at L7E21.
;
; Left-hand side border graphic
L825F:
  DEFB $C0,$F0,$80,$F0,$C0,$F0,$C0,$F0
; Bottom-left corner border graphic
  DEFB $C0,$E0,$D0,$E8,$F2,$F5,$FD,$FF
; Top border graphic
  DEFB $00,$00,$00,$00,$11,$55,$75,$FF
; Bottom-right corner border graphic
  DEFB $03,$01,$0B,$13,$0B,$47,$57,$FF
; Right-hand side border graphic
  DEFB $07,$01,$0F,$03,$0F,$03,$0F,$03
; Top right-hand corner border graphic
  DEFB $FF,$7F,$9F,$2F,$13,$23,$0D,$01
; Bottom border graphic
  DEFB $FF,$BA,$AA,$2A,$00,$00,$00,$00
; Top-left corner border graphic
  DEFB $FF,$FF,$F4,$F0,$D0,$C8,$E0,$80
; Strip of landscape
  DEFB $00,$00,$00,$00,$00,$07,$7F,$FF
  DEFB $00,$00,$00,$00,$18,$FF,$FF,$FF
  DEFB $00,$00,$00,$00,$00,$C0,$F8,$FE
  DEFB $00,$00,$00,$08,$1F,$3F,$7F,$FF
  DEFB $00,$02,$07,$1F,$7F,$FF,$FF,$FF
  DEFB $03,$1F,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $00,$C0,$F0,$FC,$FF,$FF,$FF,$FF
  DEFB $00,$00,$00,$40,$E0,$F0,$FC,$FF
  DEFB $00,$00,$00,$01,$1F,$7F,$FF,$FF
  DEFB $00,$00,$10,$F8,$FF,$FF,$FF,$FF
  DEFB $00,$00,$00,$00,$00,$D7,$DF,$FF
  DEFB $00,$00,$00,$00,$00,$E0,$F8,$FF
  DEFB $C0,$C0,$C0,$C0,$C0,$C0,$C0,$C0
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$03,$07
  DEFB $00,$01,$03,$0F,$3F,$FF,$FF,$FF
  DEFB $00,$03,$7F,$FF,$FF,$FF,$FF,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $00,$80,$E0,$F6,$FF,$FF,$FF,$FF
  DEFB $00,$00,$00,$00,$C0,$E0,$FF,$FF
  DEFB $00,$00,$00,$00,$00,$00,$F0,$FF
  DEFB $00,$00,$00,$00,$00,$00,$1F,$FF
  DEFB $00,$00,$00,$00,$07,$67,$FF,$FF
  DEFB $00,$00,$00,$FC,$FE,$FF,$FF,$FF
; Landscape graphic - small trilith
  DEFB $FF,$FF,$E7,$E7,$E7,$E7,$E7,$E7
; Landscape graphic - thin tower structure
  DEFB $C0,$C0,$C0,$C0,$C0,$C0,$C0,$C0
; Landscape graphic - cyan highlight/structure on the right of the screen
  DEFB $01,$00,$01,$00,$01,$00,$01,$00
  DEFB $E1,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $60,$E0,$E0,$F0,$F0,$F0,$F8,$FE
; Landscape graphic - cyan structure just below and to the left of the above
; graphic
  DEFB $01,$00,$01,$00,$01,$00,$01,$00
  DEFB $C0,$C0,$E4,$F4,$FC,$DC,$CC,$EC
; Landscape graphic - lower part of tall cyan highlighted tower structure
  DEFB $01,$00,$01,$00,$01,$00,$01,$00
  DEFB $C0,$C0,$F8,$FC,$FF,$FF,$FF,$FF
  DEFB $00,$00,$00,$00,$81,$FF,$FF,$FF
  DEFB $0F,$1F,$1F,$3F,$FF,$FF,$FF,$FF
; Moon graphic
  DEFB $1C,$38,$78,$78,$78,$78,$38,$1C
; Top right stars
  DEFB $00,$00,$00,$00,$00,$30,$30,$C0
  DEFB $00,$02,$00,$00,$00,$00,$00,$00
  DEFB $20,$00,$00,$00,$00,$00,$04,$00
; Unused byte
  DEFB $00
; Top left stars
  DEFB $01,$00,$10,$30,$10,$00,$00,$00
; Cyan moon reflection on right of small trilith
  DEFB $80,$00,$80,$00,$80,$00,$80,$00
; Cyan moon reflection on top of small trilith
  DEFB $00,$00,$00,$00,$00,$00,$00,$55
; Cyan moon reflection on left of vertical tower structure
  DEFB $01,$00,$01,$00,$01,$00,$01,$00
; Unused bytes
  DEFB $00,$00

; Graphics: Game screen (decorative border)
;
; Drawn at L7C03 (pixels) and L7CAD (colours)
;
; Top two character rows (2 rows x 32 columns)
L841A:
  DEFB $FE,$F8,$F3,$E0,$E7,$E7,$E7,$FB ; First row
  DEFB $9F,$87,$B3,$41,$3D,$BD,$B9,$1B ;
  DEFB $FF,$FF,$FF,$FF,$FF,$F8,$C4,$22 ;
  DEFB $FF,$FF,$FF,$FF,$FF,$3F,$4F,$27 ;
  DEFB $2F,$DF,$8F,$8F,$DF,$2F,$FF,$FF ;
  DEFB $FF,$FF,$FC,$FB,$FA,$E4,$80,$80 ;
  DEFB $C7,$1B,$01,$7D,$FF,$FC,$F3,$0F ;
  DEFB $FF,$FF,$FF,$FF,$FF,$3F,$DF,$EF ;
  DEFB $FF,$F8,$F3,$E7,$CF,$DF,$DF,$DF ;
  DEFB $FF,$7F,$BB,$87,$BF,$BF,$BF,$FF ;
  DEFB $FF,$FF,$FF,$FF,$FC,$F1,$E6,$9E ;
  DEFB $FF,$F0,$87,$38,$43,$8C,$10,$67 ;
  DEFB $FF,$00,$FF,$80,$00,$01,$06,$9B ;
  DEFB $FF,$03,$FF,$19,$60,$80,$00,$87 ;
  DEFB $FF,$FF,$FF,$FF,$FF,$7F,$3F,$1F ;
  DEFB $E0,$C8,$84,$83,$18,$3E,$3E,$0C ;
  DEFB $07,$23,$41,$81,$18,$7C,$7C,$38 ;
  DEFB $FF,$FF,$FF,$FF,$FF,$FE,$FE,$F1 ;
  DEFB $FF,$C0,$FF,$9C,$23,$40,$80,$00 ;
  DEFB $FF,$00,$FE,$01,$00,$C0,$30,$C9 ;
  DEFB $FF,$FF,$07,$F8,$C7,$31,$EE,$02 ;
  DEFB $FF,$FF,$FF,$7F,$9F,$E7,$3B,$04 ;
  DEFB $FF,$7F,$3F,$9F,$CF,$E0,$FF,$FF ;
  DEFB $FF,$9F,$07,$73,$6B,$6B,$8A,$F0 ;
  DEFB $FF,$F7,$F3,$F3,$CF,$3F,$8F,$FF ;
  DEFB $FF,$FE,$F9,$F9,$F9,$F8,$FC,$F0 ;
  DEFB $FD,$E3,$E3,$F9,$FC,$00,$00,$CF ;
  DEFB $FF,$FF,$F3,$EF,$EF,$07,$00,$80 ;
  DEFB $FF,$FF,$FF,$F0,$E4,$ED,$E2,$31 ;
  DEFB $FF,$EC,$E1,$03,$04,$00,$00,$B7 ;
  DEFB $EF,$03,$E4,$83,$02,$02,$63,$82 ;
  DEFB $EF,$1F,$1F,$1E,$DD,$21,$11,$29 ;
  DEFB $F4,$F2,$FF,$FA,$FA,$FF,$FE,$FC ; Second row
  DEFB $CA,$D5,$FC,$AC,$AB,$F9,$2C,$25 ;
  DEFB $12,$D2,$53,$4F,$3F,$7F,$FF,$FF ;
  DEFB $6B,$C5,$05,$E8,$F8,$FD,$FE,$FF ;
  DEFB $FE,$F9,$8E,$CC,$99,$17,$2F,$FF ;
  DEFB $CE,$5E,$3F,$7F,$FF,$FF,$FF,$FF ;
  DEFB $FF,$7F,$3F,$97,$E7,$FF,$FF,$FF ;
  DEFB $EF,$EF,$EF,$EF,$F0,$FF,$FF,$FF ;
  DEFB $DF,$DF,$BF,$BF,$7F,$FF,$FF,$FF ;
  DEFB $FE,$FC,$F9,$F2,$EC,$D3,$9F,$FF ;
  DEFB $21,$C2,$04,$08,$11,$27,$8F,$DF ;
  DEFB $98,$00,$00,$01,$82,$E4,$F1,$FB ;
  DEFB $60,$40,$80,$00,$1C,$FF,$FF,$FF ;
  DEFB $68,$38,$10,$10,$27,$AF,$DF,$DF ;
  DEFB $81,$7F,$00,$F8,$FF,$FF,$FF,$FF ;
  DEFB $81,$91,$CB,$E8,$E0,$E5,$ED,$F7 ;
  DEFB $83,$8D,$D3,$0F,$0F,$6F,$6F,$DF ;
  DEFB $0F,$F0,$00,$1F,$FF,$FF,$FF,$FF ;
  DEFB $81,$62,$14,$C8,$E4,$F1,$FB,$FF ;
  DEFB $35,$02,$01,$18,$FC,$FF,$FF,$FF ;
  DEFB $01,$00,$00,$80,$40,$27,$8F,$DF ;
  DEFB $01,$80,$40,$20,$10,$E8,$F1,$FB ;
  DEFB $7F,$BF,$5F,$27,$13,$09,$AD,$FE ;
  DEFB $E0,$DC,$DC,$CE,$E6,$FF,$FF,$FF ;
  DEFB $7F,$7F,$7F,$7F,$3E,$1C,$10,$C7 ;
  DEFB $C3,$9E,$3C,$7E,$6E,$6F,$1F,$BF ;
  DEFB $1F,$7F,$F3,$E7,$F7,$7B,$3F,$FF ;
  DEFB $F0,$C0,$8F,$1F,$BF,$9F,$C7,$FB ;
  DEFB $1B,$0B,$FE,$FE,$FE,$FF,$FF,$FF ;
  DEFB $B7,$BC,$D0,$C0,$03,$1F,$FF,$FF ;
  DEFB $0E,$32,$C1,$F8,$FC,$FE,$3E,$0F ;
  DEFB $CB,$17,$25,$44,$2B,$11,$45,$2B ;
; Graphics for LEFT border (14 rows x 2 columns)
  DEFB $F6,$F4,$E6,$E4,$E6,$D4,$C6,$DC
  DEFB $23,$27,$2F,$2F,$3F,$3F,$3F,$3F
  DEFB $E6,$C2,$CD,$D0,$E7,$E8,$F1,$FA
  DEFB $3F,$3F,$3F,$BF,$7F,$3F,$DF,$0F
  DEFB $FC,$FF,$FF,$F8,$FC,$F8,$FE,$FA
  DEFB $77,$87,$C3,$FB,$71,$39,$B5,$B1
  DEFB $FE,$F9,$FC,$F8,$FC,$F8,$FC,$FA
  DEFB $B1,$BC,$B2,$B0,$B8,$B5,$31,$3B
  DEFB $FF,$F9,$FD,$E9,$EC,$E8,$CC,$C8
  DEFB $BB,$33,$37,$2F,$3F,$3F,$3F,$3F
  DEFB $EC,$88,$EC,$88,$EC,$08,$E4,$84
  DEFB $3F,$3F,$3F,$3F,$3F,$3F,$3F,$3F
  DEFB $B2,$C2,$99,$E1,$C4,$E8,$F0,$F7
  DEFB $3F,$3F,$3F,$3F,$BF,$7F,$3F,$1F
  DEFB $F8,$F8,$FD,$FE,$FE,$FF,$F9,$FC
  DEFB $1F,$EF,$07,$03,$EB,$85,$81,$BC
  DEFB $F8,$FC,$F8,$FC,$F8,$FC,$F8,$FC
  DEFB $60,$20,$3E,$20,$20,$2D,$23,$2F
  DEFB $F8,$FC,$F8,$EC,$C8,$CC,$E8,$94
  DEFB $3F,$3F,$3F,$3F,$3D,$3D,$39,$31
  DEFB $87,$93,$A4,$C9,$D2,$F2,$FA,$FF
  DEFB $61,$87,$13,$57,$5F,$7F,$7F,$9F
  DEFB $FF,$FB,$FB,$FB,$FB,$F5,$F5,$F5
  DEFB $1F,$1F,$1F,$1F,$1F,$1F,$1F,$9F
  DEFB $F2,$F2,$F1,$E1,$E0,$E0,$E0,$E0
  DEFB $FF,$FF,$7F,$3F,$BF,$5F,$2F,$17
  DEFB $E0,$E0,$E0,$E0,$E0,$E1,$E6,$D0
  DEFB $11,$19,$2B,$4B,$8B,$13,$13,$13
; Graphics for bottom third of screen, left hand side (devil and left-hand edge
; of scroll) - 8 rows x 7 columns
  DEFB $E0,$E0,$E0,$F0,$F0,$F1,$F2,$FE
  DEFB $13,$1B,$2B,$45,$84,$04,$02,$01
  DEFB $FF,$FF,$FF,$FF,$FF,$7F,$0F,$0F
  DEFB $FF,$FF,$FF,$FF,$FB,$FD,$FC,$FE
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$7F,$3F
  DEFB $FF,$FF,$FF,$FF,$FF,$FE,$FD,$FD
  DEFB $FF,$FF,$FF,$FF,$FF,$80,$C0,$E0
  DEFB $F1,$F9,$F0,$F8,$F0,$F8,$F0,$F8
  DEFB $00,$00,$80,$81,$8E,$F0,$80,$FF
  DEFB $C7,$67,$53,$89,$04,$03,$00,$1F
  DEFB $FA,$F0,$F0,$FC,$27,$F1,$03,$03
  DEFB $3F,$CF,$67,$07,$46,$A6,$D5,$EC
  DEFB $FD,$FD,$FD,$FD,$FD,$FE,$FE,$FE
  DEFB $E0,$E0,$60,$6A,$D5,$FF,$7F,$00
  DEFB $F0,$F8,$F0,$F8,$F0,$F8,$F0,$F8
  DEFB $1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F
  DEFB $20,$48,$BC,$7F,$FF,$FE,$FE,$FE
  DEFB $03,$03,$01,$80,$E6,$07,$07,$07
  DEFB $FD,$F9,$E3,$07,$0F,$EF,$FF,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $00,$00,$00,$00,$80,$80,$80,$80
  DEFB $F0,$F8,$F0,$F8,$F0,$F8,$F0,$F8
  DEFB $1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F
  DEFB $FE,$FE,$FC,$FC,$FC,$F8,$F8,$FA
  DEFB $07,$07,$07,$18,$00,$00,$00,$03
  DEFB $FF,$FF,$9F,$1F,$1F,$3F,$BF,$3F
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $F0,$F0,$F8,$E0,$C0,$C0,$C0,$C0
  DEFB $F0,$F8,$F0,$F8,$F0,$F8,$F0,$F8
  DEFB $1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F
  DEFB $C3,$8F,$BF,$BF,$7F,$71,$73,$B5
  DEFB $1F,$E7,$C7,$C7,$C7,$E7,$E7,$E7
  DEFB $BF,$BF,$BF,$BF,$3F,$1F,$DF,$DF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $E0,$E0,$E0,$E0,$E0,$E0,$E0,$E0
  DEFB $F0,$F8,$F0,$F8,$F0,$F8,$F0,$F8
  DEFB $1F,$1F,$1F,$1F,$1F,$1F,$1F,$1F
  DEFB $BD,$BD,$C3,$FF,$FF,$FE,$FF,$FF
  DEFB $F3,$E3,$E7,$CF,$3F,$7F,$7F,$7F
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $E0,$F8,$FC,$E7,$E0,$E0,$E0,$E0
  DEFB $F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0
  DEFB $1B,$19,$18,$18,$19,$19,$19,$19
  DEFB $EF,$CF,$8F,$0F,$4F,$CE,$CC,$CC
  DEFB $FF,$FF,$1F,$DF,$DF,$1C,$D9,$D9
  DEFB $FF,$F3,$F3,$FF,$FF,$33,$B3,$B3
  DEFB $FF,$FF,$FF,$FF,$FE,$8C,$3D,$3D
  DEFB $E0,$E0,$E0,$E0,$60,$E0,$E0,$E0
  DEFB $F0,$F0,$F0,$F0,$F8,$FF,$FF,$FF
  DEFB $19,$19,$19,$1F,$3F,$FF,$FF,$FF
  DEFB $CC,$CC,$CC,$FF,$FF,$FC,$FD,$FC
  DEFB $D9,$1C,$3E,$FF,$FF,$00,$FF,$00
  DEFB $B3,$33,$33,$BF,$BF,$3F,$FE,$01
  DEFB $3D,$9D,$CD,$FD,$FC,$FE,$FF,$FF
  DEFB $E0,$E0,$E0,$C0,$D5,$AA,$FF,$FF
; Graphics for RIGHT border (14 rows x 2 columns)
  DEFB $EF,$17,$E7,$87,$E3,$E3,$E5,$09
  DEFB $13,$43,$1B,$13,$43,$2B,$13,$43
  DEFB $F9,$F9,$F9,$F9,$F9,$F8,$F8,$E8
  DEFB $2B,$13,$43,$2D,$31,$C1,$81,$81
  DEFB $C8,$84,$84,$82,$01,$00,$0F,$00
  DEFB $01,$01,$02,$04,$08,$70,$80,$00
  DEFB $0F,$80,$80,$87,$80,$80,$81,$82
  DEFB $80,$78,$06,$F1,$08,$24,$D2,$29
  DEFB $84,$C1,$62,$B4,$91,$B2,$B4,$B0
  DEFB $04,$E4,$12,$05,$E1,$11,$09,$05
  DEFB $93,$D4,$48,$8D,$E6,$E2,$E3,$F0
  DEFB $F0,$08,$00,$F1,$03,$E6,$09,$18
  DEFB $F8,$F8,$FC,$FC,$FE,$FF,$FE,$FF
  DEFB $14,$30,$28,$61,$53,$87,$4F,$0F
  DEFB $FF,$FE,$FE,$FE,$FE,$FC,$F8,$F1
  DEFB $1F,$1F,$3F,$3F,$7F,$FF,$FF,$FF
  DEFB $F3,$E7,$E7,$CF,$CE,$DD,$DB,$D1
  DEFB $FF,$FF,$FF,$FF,$3F,$9F,$CF,$CF
  DEFB $DB,$DB,$DB,$DF,$DF,$E7,$F0,$FF
  DEFB $EF,$EF,$EF,$CF,$9F,$3F,$7F,$FF
  DEFB $FF,$FF,$FC,$F8,$F1,$E3,$E3,$C7
  DEFB $FF,$FF,$7F,$FF,$FF,$FF,$FF,$FF
  DEFB $C7,$C7,$C7,$C3,$C3,$F1,$F8,$FE
  DEFB $FF,$FB,$FB,$FB,$F3,$F3,$E7,$67
  DEFB $FF,$FF,$F7,$D5,$F7,$10,$F7,$D7
  DEFB $E5,$C9,$C9,$CB,$D3,$93,$A7,$47
  DEFB $F6,$FE,$FC,$F8,$F0,$F1,$E2,$C0
  DEFB $25,$45,$89,$89,$93,$23,$23,$47
; Graphics for decorative scroll in bottom third of screen. Stored in character
; columns.
  DEFB $FF,$FF,$FF,$FF,$FF,$00,$00,$00 ; The first 8 of these graphics form a
                                       ; 'top-to-bottom' column graphic
  DEFB $00,$00,$00,$AA,$55,$FF,$FF,$00 ; The 1 x 8 column is repeated 18 times
  DEFB $00,$00,$00,$00,$00,$00,$00,$00 ; across to make up the scroll body.
  DEFB $00,$00,$00,$00,$00,$00,$00,$00 ;
  DEFB $00,$00,$00,$00,$00,$00,$00,$00 ;
  DEFB $00,$00,$00,$00,$00,$00,$00,$00 ;
  DEFB $00,$00,$00,$00,$00,$00,$00,$00 ;
  DEFB $00,$00,$00,$00,$55,$AA,$FF,$FF ;
; Graphics for bottom third of screen, right hand side (angel and right-hand
; edge of scroll) - 8 rows x 7 columns
  DEFB $FF,$FF,$FF,$FF,$FF,$07,$03,$02
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$7F
  DEFB $FF,$FF,$FF,$FF,$FC,$FE,$FA,$FA
  DEFB $FF,$FF,$FF,$FF,$1F,$0F,$0F,$0F
  DEFB $FF,$FF,$FF,$FF,$FE,$FE,$FE,$FC
  DEFB $88,$90,$01,$02,$04,$08,$11,$22
  DEFB $47,$8F,$1F,$2F,$4F,$8F,$1F,$3F
  DEFB $03,$01,$03,$AB,$57,$FF,$FF,$1F
  DEFB $7F,$9F,$C7,$F3,$F9,$FC,$BE,$CF
  DEFB $F5,$E0,$F0,$F0,$F0,$F3,$3E,$1E
  DEFB $CF,$6F,$AF,$A7,$23,$21,$20,$38
  DEFB $FC,$F8,$F8,$F0,$E0,$E0,$C0,$C0
  DEFB $44,$08,$11,$22,$24,$89,$13,$27
  DEFB $7F,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $1F,$1F,$7F,$1F,$0F,$0F,$0F,$0F
  DEFB $EF,$F7,$F3,$F1,$F8,$FC,$FE,$FF
  DEFB $82,$C0,$E3,$F4,$F8,$70,$20,$00
  DEFB $04,$04,$C3,$02,$04,$20,$40,$81
  DEFB $80,$81,$86,$00,$01,$1F,$3F,$FF
  DEFB $CF,$1F,$3E,$7E,$FC,$FC,$FC,$FE
  DEFB $BF,$3F,$3F,$7F,$7F,$7F,$3F,$3F
  DEFB $07,$07,$07,$07,$07,$0F,$0F,$3F
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $83,$CF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $00,$00,$F0,$FC,$FE,$FE,$FF,$FF
  DEFB $3F,$1F,$0F,$07,$01,$00,$40,$80
  DEFB $FE,$FE,$FE,$FE,$FE,$7E,$3F,$3F
  DEFB $3F,$3D,$3D,$7D,$FD,$F9,$F9,$F1
  DEFB $7F,$1F,$07,$07,$07,$07,$07,$07
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $FF,$FE,$FE,$FC,$F8,$F0,$F1,$C3
  DEFB $FF,$FE,$FC,$FC,$F8,$F0,$E0,$C0
  DEFB $00,$00,$00,$07,$0C,$3C,$7C,$FC
  DEFB $3F,$7F,$BF,$3F,$3F,$3F,$3E,$3E
  DEFB $E1,$C3,$83,$87,$0F,$1F,$1F,$3F
  DEFB $03,$03,$03,$03,$03,$03,$03,$03
  DEFB $FF,$FE,$FC,$F8,$F0,$F0,$E0,$E0
  DEFB $07,$0F,$1F,$3F,$3F,$7F,$7F,$FF
  DEFB $C3,$C0,$E0,$FC,$FF,$FF,$FF,$FF
  DEFB $FE,$FE,$0F,$03,$00,$C0,$FE,$FF
  DEFB $3E,$3E,$1E,$8E,$CF,$37,$0F,$E3
  DEFB $3F,$3F,$7F,$7F,$7F,$7F,$3F,$BF
  DEFB $27,$1F,$07,$03,$03,$03,$01,$FF
  DEFB $E0,$E0,$F0,$F0,$F8,$FC,$FE,$FF
  DEFB $FF,$FF,$FF,$FF,$7F,$3F,$0F,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  DEFB $E5,$C8,$DC,$BE,$FE,$FC,$FD,$FF
  DEFB $DF,$EF,$77,$3F,$63,$DD,$DE,$D8
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
; Bottom right graphic for small scroll overlap:
  DEFB $18,$10,$30,$3E,$72,$B2,$F2,$F2
  DEFB $00,$00,$00,$00,$00,$00,$00,$00

; Menu screens - data store
L8BAA:
  DEFB $00                ; Menu control option selected (1-4) in routine at
                          ; L80A1
  DEFB $00                ; Game flag - New Game = 0, Load Saved Game = 1
  DEFB $00                ; 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
                          ; 8077 Later set to 18, used as a column counter for
                          ; drawing the 18 scroll character columns at the
                          ; bottom of the game screen (7C4F).
  DEFW $0000              ; Store for screen display address pointer. Used in
                          ; drawing routine at 7C4F.
  DEFB $00                ; Number of columns to draw. Used by drawing routine
                          ; at L81F3.
  DEFB $00                ; Number of row to draw. Used by drawing routine at
                          ; L81F3.
  DEFB $00                ; Counter for number of columns to draw. Used in
                          ; drawing routine at L81F3.
  DEFB $F7,$04,$FB,$03,$FD,$02,$FE,$01 ; Data for checking port addresses for
                                       ; keys 1, 2, 3 or 4 (used in key check
                                       ; routine at L80A1)
  DEFB $00
  DEFW $48FF              ; Starting screen address position for printing
                          ; control keys on menu in routine at L8179
  DEFB $00                ; Number of text characters in the string to print -
                          ; used in the menu print routine at L8179
  DEFW $48FD              ; Current screen display address position (used in
                          ; routine at L8179)
  DEFW L8C9A              ; Address pointer for the next text character to
                          ; print

; First menu screen text
;
; Text printed on the first menu screen in the routine at L8039.
L8BC2:
  DEFB $1A                ; First string length = 26 characters
  DEFM "PRESS 1-4 TO CHANGE OPTION"
  DEFB $16                ; String length = 22 characters
  DEFM "ENTER TO START PROGRAM"
  DEFB $1F                ; String length = 31 characters
  DEFM "1   KEMPSTON JOYSTICK (PORT 31)"
  DEFB $1E                ; String length = 30 characters
  DEFM "2   AGF JOYSTICK (CURSOR KEYS)"
  DEFB $15                ; String length = 21 characters
  DEFM "3   SINCLAIR JOYSTICK"
  DEFB $1E                ; String length = 30 characters
  DEFM "4   KEYBOARD SET UP AS FOLLOWS"
  DEFB $19                ; String length = 25 characters
  DEFM "UP  DOWN  LEFT RIGHT FIRE"
  DEFB $05                ; String length = 5 characters
  DEFM "ASDFG"
  DEFB $04                ; String length = 4 characters
  DEFM "ZXCV"
  DEFB $02                ; String length = 2 characters
  DEFM "BN"
  DEFB $04                ; String length = 4 characters
  DEFM "MS/S"
  DEFB $04                ; String length = 4 characters
  DEFM "HJKL"

; Second menu screen text
;
; Text printed on the second menu screen in the routine at L811B.
L8C9A:
  DEFB $18                ; String length = 24 characters
  DEFM "PRESS ENTER FOR NEW GAME"
  DEFB $19                ; String length = 25 characters
  DEFM "PRESS LOAD FOR SAVED GAME"

; Load saved game text
;
; Text printed on screen in routine at 8142.
L8CCD:
  DEFB $0F                ; String length = 15 characters
  DEFM "LOAD SAVED GAME"
  DEFM " GAME"

; Unused
L8CE2:
  DEFB $F0,$AB,$11,$1A,$AA,$21,$19,$50
  DEFB $CD,$33,$A2,$21,$00,$58,$06,$00
  DEFB $36,$30,$23,$36,$30,$23,$36,$30
  DEFB $23,$10,$F5,$21,$42,$58,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$C3,$AE
  DEFB $CD

; Data - sprite and graphic address pointer table
L97C3:
  DEFW $9950              ; Maroc Sprite Graphics - Frame 1
  DEFW $99C8              ; Maroc Sprite Graphics - Frame 2
  DEFW $9A3A              ; Maroc Sprite Graphics - Frame 3
  DEFW $9AA9              ; Maroc Sprite Graphics - Frame 4
  DEFW $9B05              ; Maroc Sprite Graphics - Frame 5
  DEFW $9B7D              ; Maroc Sprite Graphics - Frame 6
  DEFW $9BF5              ; Maroc Sprite Graphics - Frame 7
  DEFW $9C64              ; Maroc Sprite Graphics - Frame 8
  DEFW $9CD1              ; Graphics - door 1
  DEFW $9D38              ; Graphics - door 2
  DEFW $9D95              ; Graphics - door 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; door 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; door 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; door 1
  DEFW $9DC9              ; Graphics - back wall/floor section ('brick' levels)
  DEFW $9DE8              ; Graphics - side wall section ('brick' levels)
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; side wall section
  DEFW $9E0F              ; Graphics - vertical wall section ('brick' levels)
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; vertical wall section
  DEFW $9E44              ; Graphics - door frame - back wall ('brick' levels)
  DEFW $9E96              ; Graphics - door frame - side wall ('brick' levels)
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; door frame - side wall
  DEFW $9EE9              ; Graphics - brickwork pattern 1
  DEFW $9F01              ; Graphics - brickwork pattern 2
  DEFW $9F13              ; Graphics - brickwork pattern 3
  DEFW $9F30              ; Graphics - brickwork pattern 4
  DEFW $9F44              ; Graphics - back wall/floor section ('cavern'
                          ; levels)
  DEFW $9F65              ; Graphics - side wall section ('cavern' levels)
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; side wall section
  DEFW $9F84              ; Graphics - vertical wall section ('cavern' levels)
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; vertical wall section
  DEFW $9FAD              ; Graphics - door frame - back wall ('cavern' levels)
  DEFW $9FF4              ; Graphics - door frame - side wall ('cavern' levels)
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; door frame - side wall
  DEFW $A036              ; Graphics - back wall scenery 1
  DEFW $A04E              ; Graphics - back wall scenery 2
  DEFW $A063              ; Graphics - back wall scenery 3
  DEFW $A081              ; Graphics - back wall scenery 4
  DEFW $A09B              ; Graphics - tunnel room boundary
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; tunnel boundary
  DEFW $A0DC              ; Graphics - servant - animation frame 1
  DEFW $A0F0              ; Graphics - servant - animation frame 2
  DEFW $A105              ; Graphics - eye cursor - animation frame 1
  DEFW $A128              ; Graphics - eye cursor - animation frame 2
  DEFW $A141              ; Graphics - scroll
  DEFW $A165              ; Graphics - Caliburn, the sword of power
  DEFW $A17F              ; Graphics - amulet spell icon
  DEFW $A1A7              ; Graphics - chalice spell icon
  DEFW $A1CD              ; Graphics - ring/servant spell icon
  DEFW $A1DA              ; Graphics - move spell icon
  DEFW $A1EF              ; Graphics - jewel (spell icon - various)
  DEFW $A1FC              ; Graphics - missile 1 frame 1
  DEFW $A208              ; Graphics - missile 1 frame 2
  DEFW $A214              ; Graphics - missile 1 frame 3
  DEFW $A221              ; Graphics - missile 2 frame 1
  DEFW $A242              ; Graphics - missile 2 frame 2
  DEFW $A261              ; Graphics - missile 2 frame 3
  DEFW $A285              ; Graphics - missile 3 frame 1
  DEFW $A2A8              ; Graphics - missile 3 frame 2
  DEFW $A2CA              ; Graphics - missile 3 frame 3
  DEFW $A2EC              ; Graphics - Warlock - frame 1
  DEFW $A333              ; Graphics - Warlock - frame 2
  DEFW $A37A              ; Graphics - Warlock - frame 3
  DEFW $A3C2              ; Graphics - Guardian of Chaos - frame 1
  DEFW $A40B              ; Graphics - Guardian of Chaos - frame 2
  DEFW $A451              ; Graphics - Guardian of Chaos - frame 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Guardian of Chaos - frame 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Guardian of Chaos - frame 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Guardian of Chaos - frame 1
  DEFW $A49D              ; Graphics - Goblin warrior - frame 1
  DEFW $A4D9              ; Graphics - Goblin warrior - frame 2
  DEFW $A514              ; Graphics - Goblin warrior - frame 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Goblin warrior - frame 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Goblin warrior - frame 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Goblin warrior - frame 1
  DEFW $A54E              ; Graphics - Goblin missile thrower - frame 1
  DEFW $A592              ; Graphics - Goblin missile thrower - frame 2
  DEFW $A5D9              ; Graphics - Goblin missile thrower - frame 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Goblin missile thrower - frame 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Goblin missile thrower - frame 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Goblin missile thrower - frame 1
  DEFW $A621              ; Graphics - Wraith - frame 1
  DEFW $A656              ; Graphics - Wraith - frame 2
  DEFW $A694              ; Graphics - Wraith - frame 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Wraith - frame 3
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Wraith - frame 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Wraith - frame 1
  DEFW $A6CF              ; Graphics - Demon - frame 1
  DEFW $A748              ; Graphics - Demon - frame 2
  DEFW $A7C6              ; Graphics - Demon - frame 3
  DEFW $A848              ; Graphics - Materialization effect - frame 1
  DEFW $A85A              ; Graphics - Materialization effect - frame 2
  DEFW $A86D              ; Graphics - Materialization effect - frame 3
  DEFW $A885              ; Graphics - Materialization effect - frame 4
  DEFW $A89F              ; Graphics - Materialization effect - frame 5
  DEFW $A8BB              ; Graphics - Materialization effect - frame 6
  DEFW LA8D7              ; Graphics - UNUSED
  DEFW $A8DD              ; Graphics - Disintegration animation - frame 1
  DEFW $A924              ; Graphics - Disintegration animation - frame 2
  DEFW $A95A              ; Graphics - Disintegration animation - frame 3
  DEFW $A987              ; Graphics - Disintegration animation - frame 4
  DEFW $A9AE              ; Graphics - Disintegration animation - frame 5
  DEFW $A9D1              ; Graphics - Disintegration animation - frame 6
  DEFW LA9E6              ; Graphics - Shield spell barrier
  DEFW $A9EC              ; Graphics - Shield spell barrier - frame 1
  DEFW $AA23              ; Graphics - Shield spell barrier - frame 2
  DEFW $AA5B              ; Graphics - Foreground scenery - Skeleton
  DEFW $AA90              ; Graphics - Foreground scenery - Seat
  DEFW $AAB8              ; Graphics - Foreground scenery - Table
  DEFW $AB07              ; Graphics - Foreground scenery - Stool
  DEFW $AB2F              ; Graphics - Foreground scenery - Misc
  DEFW $AB6B              ; Graphics - Foreground scenery - Cube
  DEFW $AB93              ; Graphics - Foreground scenery - Box
  DEFW $ABE1              ; Graphics - Foreground scenery - Rubble
  DEFW $AC0D              ; Graphics - Foreground scenery - Stalagmites 1
  DEFW $AC41              ; Graphics - Foreground scenery - Boulder
  DEFW $AC71              ; Graphics - Foreground scenery - Crevasse
  DEFW $AC95              ; Graphics - Foreground scenery - Skull pile
  DEFW $ACC8              ; Graphics - Foreground scenery - Stalagmites 2
  DEFW $ACFA              ; Graphics - Foreground scenery - Spikes
  DEFW $AD3E              ; Graphics - Foreground scenery - Pool
  DEFW $AD62              ; Graphics - Foreground scenery - Mound
  DEFW $AD88              ; Graphics - Maroc's shadow
  DEFW $AD9C              ; Graphics - BLANK 'DUMMY' GRAPHIC
  DEFW $ADA2              ; Graphics - Spider - frame 1
  DEFW $ADE3              ; Graphics - Spider - frame 2
  DEFW $AE2D              ; Graphics - Bat - frame 1
  DEFW $AE5D              ; Graphics - Bat - frame 2
  DEFW $AE85              ; Graphics - Bat - frame 3
  DEFW $AEBC              ; Graphics - Bat - frame 4
  DEFW $AEE7              ; Graphics - Scroll display icon for spell charges
  DEFW $AEF4              ; Graphics - Dragon flame energy bar on scroll
  DEFW $AFA6              ; Graphics - Scroll spell arrow pointer
  DEFW $AFF0              ; Graphics - Key 1
  DEFW $AFFF              ; Graphics - Chest (closed)
  DEFW $B01D              ; Graphics - Chest (open)
  DEFW $B041              ; Graphics - Buried bottle (pre-state)
  DEFW $B05B              ; Graphics - Broken bottle (post-state)
  DEFW $B071              ; Graphics - Pick/lever
  DEFW $B083              ; Graphics - Cheese
  DEFW $B0A4              ; Graphics - Mouse hole
  DEFW $B0BE              ; UNUSED
  DEFW $B0C4              ; UNUSED
  DEFW $B0CA              ; Graphics - Key (hanging)
  DEFW $B0E8              ; Graphics - Key 2
  DEFW $B0F9              ; Graphics - Star (on floor)
  DEFW $B115              ; Graphics - Star symbol
  DEFW $B12E              ; Graphics - Coins
  DEFW $B154              ; Graphics - Fish
  DEFW $B168              ; Graphics - Bottle
  DEFW $B17C              ; Graphics - Mushrooms
  DEFW $B197              ; Graphics - Scorpion - frame 1
  DEFW $B1BB              ; Graphics - Scorpion - frame 2
  DEFW $B1E0              ; Graphics - Axe
  DEFW $B208              ; Graphics - Bone
  DEFW $B21D              ; Graphics - Orb
  DEFW $B245              ; Graphics - Sabre (non-animated)
  DEFW $B25E              ; Graphics - Mouse - frame 1
  DEFW $B272              ; Graphics - Mouse - frame 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Mouse - frame 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Mouse - frame 1
  DEFW $B287              ; Graphics - Sabre (animated) - frame 1
  DEFW $B29F              ; Graphics - Sabre (animated) - frame 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Sabre (animated) - frame 2
  DEFW $0000              ; Store for address pointer to flipped version of
                          ; Sabre (animated) - frame 1
  DEFW $B2B8              ; Graphics - Trapdoor (closed)
  DEFW $B2E6              ; Graphics - Trapdoor (open)
  DEFW $B32C              ; Graphics - Lady
  DEFW $B35C              ; Graphics - Key - left side
  DEFW $B366              ; Graphics - Key - right side
  DEFW $B36F              ; Graphics - Oil jar
  DEFW $B397              ; Graphics - Coin
  DEFW $B3A3              ; Graphics - Altar/idol
  DEFW $B3CB              ; Graphics - Fire (animated) - frame 1
  DEFW $B3F2              ; Graphics - Fire (animated) - frame 2
  DEFW $B41A              ; Graphics - Symbol - fire
  DEFW $B440              ; Graphics - Symbol - water
  DEFW $B464              ; Graphics - Symbol - earth
  DEFW $B48A              ; Graphics - Symbol - air
  DEFW $B4B0              ; Graphics - Pick axe
  DEFW $B4C2              ; Graphics - Portal (floor symbol)
  DEFW $B4F2              ; Graphics - Portal door
  DEFW $B53A              ; Graphics - Avelach, Lord of Chaos
  DEFW $B566              ; Graphics - Symbol - blank
  DEFW $B58A              ; Graphics - Healing star (floor) - complete

; Unused
L9935:
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$01,$01,$00,$00
  DEFB $01,$FF

; Graphics - Maroc the Mage
;
; See Trivia: Graphics data and Trivia: Maroc's sprite rotational movement for
; information on how these graphics are used.
L994F:
  DEFB %00001000          ; Graphic properties
; MAROC - FRAME 1
  DEFB $05                ; Graphic consists of 5 tiles
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $E7                ; Vertical (Y axis) pixel offset (-25 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $0E,$1E,$17,$2D,$2C,$34,$7C,$6C ;
  DEFB $28,$C6,$C6,$AA,$EE,$00,$92,$FE ;
  DEFB $0B                ; Horizontal (X axis) pixel offset (+11 pixels)
  DEFB $E7                ; Vertical (Y axis) pixel offset (-25 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $06,$0F,$06,$04,$04,$04,$08,$08 ;
  DEFB $08,$08,$10,$10,$10,$30,$28,$68 ;
  DEFB $F6                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $00,$00,$00,$00,$1E,$1E,$3E,$77 ;
  DEFB $77,$F7,$E3,$E0,$6C,$0F,$33,$7D ;
  DEFB $FE,$FF,$BF,$37,$5A,$5B,$0D,$05 ;
  DEFB $FE                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $C8,$88,$70,$FA,$F3,$73,$77,$07 ;
  DEFB $0F,$DC,$D8,$D3,$07,$0E,$DC,$D1 ;
  DEFB $43,$87,$CF,$F7,$F9,$6E,$33,$98 ;
  DEFB $06                ; Horizontal (X axis) pixel offset (+6 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $01,$03,$02,$0A,$1A,$BA,$F4,$F4 ;
  DEFB $74,$44,$48,$08,$08,$16,$57,$D7 ;
  DEFB $AE,$AC,$58,$50,$40,$80,$80,$80 ;
; MAROC - FRAME 2
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F6                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $01,$01,$01,$03,$00,$03,$07,$06 ;
  DEFB $06,$06,$07,$0F,$0E,$0E,$09,$0E ;
  DEFB $0D,$0D,$1B,$1B,$16,$16,$0C,$0C ;
  DEFB $FE                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB $E7                ; Vertical (Y axis) pixel offset (-25 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $10,$38,$38,$38,$74,$70,$78,$50 ;
  DEFB $60,$74,$60,$50,$FC,$80,$4A,$7C ;
  DEFB $74,$60,$9C,$1D,$DD,$DD,$ED,$F3 ;
  DEFB $FB,$BB,$5B,$6A,$F1,$8D,$7B,$FC ;
  DEFB $FE,$FF,$FF,$FF,$DE,$DF,$DF,$CF ;
  DEFB $06                ; Horizontal (X axis) pixel offset (+6 pixels)
  DEFB $E7                ; Vertical (Y axis) pixel offset (-25 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $06,$0F,$0F,$04,$04,$04,$04,$04 ;
  DEFB $04,$04,$08,$08,$0C,$0C,$1C,$18 ;
  DEFB $38,$78,$F8,$E8,$D0,$D0,$D0,$90 ;
  DEFB $90,$10,$50,$D4,$D6,$D6,$94,$50 ;
  DEFB $D0,$50,$90,$D0,$E0,$70,$90,$D0 ;
; MAROC - FRAME 3
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $15                ; Graphic consists of 21 bytes
  DEFB $01,$00,$03,$07,$07,$0E,$0E,$0E ;
  DEFB $0F,$0F,$0E,$09,$16,$1D,$1B,$1F ;
  DEFB $1F,$1F,$17,$17,$07             ;
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $40,$40,$E0,$E0,$E0,$F0,$F0,$D8 ;
  DEFB $E8,$F0,$F4,$EC,$FC,$E0,$10,$D6 ;
  DEFB $DE,$D8,$D4,$CE,$0E,$F6,$FA,$FC ;
  DEFB $FF,$C3,$1C,$DF,$BF,$30,$8F,$7F ;
  DEFB $FF,$FB,$F6,$D6,$D6,$D6,$B4,$24 ;
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $10,$38,$38,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$00,$18,$18 ;
  DEFB $10,$50,$50,$D0,$D0,$D0,$D0,$D0 ;
  DEFB $50,$50,$10,$90,$90,$10,$90,$90 ;
  DEFB $D0,$D0,$E0,$E0,$E0,$E0,$E0,$F0 ;
; MAROC - FRAME 4
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $15                ; Graphic consists of 21 bytes
  DEFB $01,$01,$00,$01,$03,$03,$0C,$1F ;
  DEFB $07,$10,$17,$1F,$1F,$06,$00,$0F ;
  DEFB $0F,$0F,$0F,$0F,$06             ;
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $62,$B7,$77,$72,$FA,$FA,$3A,$DA ;
  DEFB $DE,$BE,$FE,$BE,$F0,$04,$F6,$F4 ;
  DEFB $F4,$E6,$9B,$BD,$3E,$7E,$7E,$6E ;
  DEFB $6E,$76,$77,$7B,$78,$73,$4F,$7F ;
  DEFB $FF,$FF,$FF,$FE,$7A,$75,$C9,$99 ;
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $15                ; Graphic consists of 21 bytes
  DEFB $80,$80,$80,$80,$60,$70,$FC,$1C ;
  DEFB $E8,$00,$E0,$F0,$F0,$70,$70,$50 ;
  DEFB $D0,$D0,$D0,$20,$40             ;
; MAROC - FRAME 5
  DEFB $05                ; Graphic consists of 5 tiles
  DEFB $F3                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $40,$E0,$E1,$40,$40,$20,$20,$20 ;
  DEFB $20,$20,$20,$10,$10,$10,$0C,$0C ;
  DEFB $FB                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $78,$FC,$BC,$1C,$3E,$3E,$36,$2A ;
  DEFB $2B,$3B,$37,$7F,$77,$7F,$1C,$63 ;
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $01,$02,$02,$06,$06,$06,$05,$05 ;
  DEFB $01,$03,$03,$03,$03,$00,$07,$0F ;
  DEFB $0F,$0F,$0F,$07,$06,$02,$02,$00 ;
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $0F,$8F,$9F,$9F,$0B,$CA,$D0,$DF ;
  DEFB $C0,$DF,$BF,$BF,$8F,$50,$5D,$5E ;
  DEFB $5F,$67,$78,$7F,$FF,$DF,$DF,$DF ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $E0,$E0,$F0,$F0,$E8,$CC,$2C,$EE ;
  DEFB $0E,$EE,$EE,$EE,$CE,$2E,$61,$EF ;
  DEFB $EF,$8F,$7E,$FE,$FA,$B8,$A8,$A8 ;
; MAROC - FRAME 6
  DEFB $05                ; Graphic consists of 5 tiles
  DEFB $F3                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $40,$E0,$E0,$40,$40,$40,$40,$40 ;
  DEFB $40,$40,$40,$40,$40,$00,$60,$60 ;
  DEFB $FB                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $0C,$0C,$1C,$12,$1E,$1E,$1D,$1B ;
  DEFB $1E,$1D,$3D,$3F,$3D,$3F,$00,$5F ;
  DEFB $F1                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $10,$00,$38,$3C,$1C,$1E,$1E,$17 ;
  DEFB $17,$17,$17,$13,$11,$10,$10,$10 ;
  DEFB $0F,$1F,$1F,$1F,$16,$1B,$0D,$06 ;
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $17,$37,$1B,$1D,$0E,$36,$7A,$7B ;
  DEFB $7B,$F7,$F7,$EF,$EF,$DF,$1F,$0F ;
  DEFB $F7,$F9,$FE,$FF,$FF,$77,$BB,$CC ;
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $C0,$C0,$C0,$E0,$60,$A0,$A0,$40 ;
  DEFB $58,$B8,$7C,$74,$70,$04,$7C,$7C ;
  DEFB $BC,$C0,$70,$F0,$F0,$F0,$E0,$E0 ;
; MAROC - FRAME 7
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F3                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $27                ; Graphic consists of 39 bytes
  DEFB $04,$0E,$0E,$04,$04,$04,$04,$04 ;
  DEFB $04,$04,$04,$04,$04,$00,$0C,$0C ;
  DEFB $00,$06,$06,$06,$03,$03,$03,$01 ;
  DEFB $05,$05,$04,$04,$04,$04,$04,$03 ;
  DEFB $0F,$1F,$1F,$0F,$07,$06,$02     ;
  DEFB $FB                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $08,$0C,$0C,$0C,$0A,$0E,$1E,$1E ;
  DEFB $16,$2E,$2E,$37,$7F,$7F,$07,$58 ;
  DEFB $7B,$FB,$1B,$63,$69,$6E,$9F,$FF ;
  DEFB $FE,$FD,$FB,$F7,$6F,$0F,$07,$FB ;
  DEFB $FC,$FF,$FF,$B7,$B7,$B7,$B3,$93 ;
  DEFB $03                ; Horizontal (X axis) pixel offset (+3 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $16                ; Graphic consists of 22 bytes
  DEFB $80,$80,$80,$80,$40,$80,$C0,$EC ;
  DEFB $E0,$EC,$EC,$EC,$E8,$E0,$60,$60 ;
  DEFB $80,$E0,$E0,$E0,$60,$40         ;
; MAROC - FRAME 8
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F3                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $12                ; Graphic consists of 18 bytes
  DEFB $01,$01,$01,$02,$02,$03,$03,$01 ;
  DEFB $01,$0D,$1C,$1E,$0F,$07,$07,$07 ;
  DEFB $01,$02                         ;
  DEFB $FB                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $03,$03,$07,$06,$0A,$16,$16,$1A ;
  DEFB $1E,$26,$0E,$27,$6F,$7F,$00,$A5 ;
  DEFB $7D,$5D,$8D,$7A,$7B,$77,$77,$6F ;
  DEFB $9B,$BB,$B9,$A5,$1D,$7D,$7E,$BE ;
  DEFB $BE,$59,$07,$BF,$DF,$EF,$B7,$58 ;
  DEFB $03                ; Horizontal (X axis) pixel offset (+3 pixels)
  DEFB $E6                ; Vertical (Y axis) pixel offset (-26 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $08,$1C,$1C,$08,$08,$08,$08,$10 ;
  DEFB $10,$10,$10,$10,$10,$20,$00,$70 ;
  DEFB $70,$30,$B8,$B8,$38,$A8,$A8,$A8 ;
  DEFB $A8,$A8,$A8,$A8,$50,$50,$40,$58 ;
  DEFB $58,$5C,$5C,$5C,$58,$58,$30,$28 ;

; 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.
L9CD0:
  DEFB %00100011          ; Graphic properties
  DEFB $06                ; Graphic consists of 6 graphic tiles
  DEFB $10                ; Horizontal (X axis) pixel offset (+16 pixels)
  DEFB $D9                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $7F,$81,$81,$01,$81,$01,$81,$01 ;
  DEFB $01,$01,$01,$81,$01,$81,$01,$81 ;
  DEFB $01,$39,$29,$11,$01,$11,$11,$01 ;
  DEFB $01,$81,$01,$81,$01,$01,$01,$01 ;
  DEFB $01,$81,$01,$81,$01,$81,$81,$7F ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $D9                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB $28                ; Graphic consists of 40 bytes
  DEFB $FC,$83,$80,$81,$80,$80,$CC,$FF ;
  DEFB $DB,$FF,$CC,$80,$80,$81,$80,$81 ;
  DEFB $80,$81,$80,$80,$80,$80,$81,$80 ;
  DEFB $81,$80,$CC,$FF,$DB,$FF,$CC,$80 ;
  DEFB $81,$80,$81,$80,$81,$80,$81,$FE ;
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $D9                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB $01                ; Graphic consists of 1 byte
  DEFB $FF
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $E1                ; Vertical (Y axis) pixel offset (-31 pixels)
  DEFB $01                ; Graphic consists of 1 byte
  DEFB $FC
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $F5                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB $01                ; Graphic consists of 1 byte
  DEFB $FC
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $01                ; Graphic consists of 1 byte
  DEFB $FF
; DOOR - FRAME 2
  DEFB $02                ; Door Graphic consists of 2 graphic tiles
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $DD                ; Vertical (Y axis) pixel offset (-35 pixels)
  DEFB $2B                ; Graphic consists of 43 bytes
  DEFB $C0,$30,$0C,$23,$01,$21,$01,$01 ;
  DEFB $01,$01,$21,$01,$21,$01,$21,$01 ;
  DEFB $01,$19,$15,$09,$01,$09,$09,$21 ;
  DEFB $01,$21,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$21,$01,$21,$01,$21,$C1 ;
  DEFB $31,$0D,$03                     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $D9                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB $2B                ; Graphic consists of 43 bytes
  DEFB $C0,$B0,$8C,$83,$88,$80,$C0,$F0 ;
  DEFB $D8,$F8,$D6,$80,$80,$88,$80,$88 ;
  DEFB $80,$88,$80,$80,$80,$80,$88,$80 ;
  DEFB $88,$80,$C0,$F0,$D8,$F8,$D6,$80 ;
  DEFB $80,$80,$80,$88,$80,$88,$80,$C8 ;
  DEFB $38,$04,$03                     ;
; DOOR - FRAME 3
  DEFB $01                ; Door Graphic consists of 1 graphic tile
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $D9                ; Vertical (Y axis) pixel offset (-39 pixels)
  DEFB $2F                ; Graphic consists of 47 bytes
  DEFB $80,$C0,$A0,$90,$58,$84,$C6,$C1 ;
  DEFB $E5,$E1,$D1,$81,$81,$A1,$81,$A5 ;
  DEFB $81,$A5,$A1,$85,$81,$81,$AD,$89 ;
  DEFB $A5,$81,$C1,$C1,$E5,$E1,$D5,$81 ;
  DEFB $81,$81,$81,$81,$81,$A1,$85,$A1 ;
  DEFB $45,$21,$15,$09,$05,$03,$01     ;

; 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
L9DC8:
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $01,$01,$01,$FE
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $01,$01,$01,$FE
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $10,$10,$10,$EF
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $21,$21,$21,$21,$DF
; SIDE WALL/FLOOR SECTION
  DEFB %00100001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $01,$C1,$31,$0D,$03
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F4                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $02,$C2,$32,$0E,$03
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $04,$04,$04,$C4,$34,$0C,$03
  DEFB $08                ; Horizontal (X axis) pixel offset (8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $08,$08,$08,$08,$C8,$38,$0C,$03
; CORNER WALL SECTION
  DEFB %00100001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $D1                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB $30                ; Graphic consists of 48 bytes
  DEFB $80,$80,$80,$80,$80,$60,$B0,$8C ;
  DEFB $87,$84,$84,$84,$84,$84,$84,$84 ;
  DEFB $64,$9C,$86,$81,$80,$80,$80,$80 ;
  DEFB $80,$80,$60,$98,$86,$85,$84,$84 ;
  DEFB $84,$84,$84,$84,$84,$84,$64,$9C ;
  DEFB $86,$81,$80,$80,$80,$80,$80,$80 ;

; 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)
L9E43:
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F1                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB $D1                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $6E,$91,$91,$91,$91,$91,$6E
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $D1                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $EE,$11,$11,$11,$11,$11,$EE
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $D1                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $EE,$11,$11,$11,$11,$11,$EE
  DEFB $09                ; Horizontal (X axis) pixel offset (+9 pixels)
  DEFB $D1                ; Vertical (Y axis) pixel offset (-47 pixels)
  DEFB $2F                ; Graphic consists of 47 bytes
  DEFB $EE,$11,$11,$11,$11,$11,$EE,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10     ;
; DOOR FRAME (SIDE WALL)
  DEFB %00100001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F5                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB $C6                ; Vertical (Y axis) pixel offset (-58 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $E0,$98,$96,$91,$91,$91,$51,$31 ;
  DEFB $0D,$03                         ;
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $C9                ; Vertical (Y axis) pixel offset (-55 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $80,$60,$18,$16,$11,$11,$11,$D1 ;
  DEFB $31,$0D,$03                     ;
  DEFB $05                ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB $CD                ; Vertical (Y axis) pixel offset (-51 pixels)
  DEFB $33                ; Graphic consists of 51 bytes
  DEFB $80,$60,$18,$16,$11,$11,$11,$D1 ;
  DEFB $31,$0D,$03,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10,$10,$10,$10,$10,$10 ;
  DEFB $10,$10,$10                     ;

; Graphics - Brickwork graphics
;
; Used as decoration on the back walls in some of Avalon's rooms and caverns.
; See the routine at LC265 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
L9EE8:
  DEFB %00000100          ; Graphic properties (4 versions of this graphic)
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $FF,$04,$04,$04,$04,$FF,$20,$20 ;
  DEFB $20,$20,$7F                     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $FF,$41,$41,$41,$41,$FF
; BRICKWORK GRAPHIC 2
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $FA                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $FF,$81,$81,$81,$81,$FF
  DEFB $FE                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $FF,$81,$81,$81,$FF
; BRICKWORK GRAPHIC 3
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $FF,$80,$80,$80,$80,$FF,$08,$08 ;
  DEFB $08,$08,$0F                     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $FE,$82,$82,$82,$82,$FE,$10,$10 ;
  DEFB $10,$10,$F0                     ;
; BRICKWORK GRAPHIC 4
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $FB                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB $02                ; Vertical (Y axis) pixel offset (+2 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $FF,$81,$81,$81,$81,$FF
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $FF,$81,$81,$81,$81,$FF

; Graphics - Wall/floor connector sections 2
;
; Door frames & scenery brickwork from cavern levels e.g. Mines of Madness. As
; with the 'brick level' connectors (L9DC8), flipped/mirrored versions of the
; side wall and corner graphics are created when needed.
L9F43:
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $15,$16,$F8
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $40,$A0,$A0,$A6,$A6,$26,$29,$10
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $90,$48,$B7
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $40,$60,$52,$52,$8D
; Side wall-floor connectors
  DEFB %00100001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $90,$72,$16,$0A,$01
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F4                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $10,$E8,$08,$07
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $80,$48,$77
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $C0,$28,$14,$02,$01
; CORNER WALL SECTION
  DEFB %00100001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $E1                ; Vertical (Y axis) pixel offset (-31 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $E4,$FE,$53,$53,$43,$43,$06,$04 ;
  DEFB $04,$06,$06,$06,$04,$19,$1B,$0B ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F1                ; Vertical (Y axis) pixel offset (-15 pixels)
  DEFB $11                ; Graphic consists of 17 bytes
  DEFB $D4,$96,$1B,$1B,$12,$31,$3B,$1D ;
  DEFB $0D,$09,$0A,$01,$09,$09,$D9,$75 ;
  DEFB $07                             ;

; Graphics - Door frames 2
;
; Door frames & scenery brickwork from cavern levels e.g. Mines of Madness. As
; with the 'brick level' door frames (L9E43), flipped/mirrored versions of the
; side wall graphics are created when needed.
;
; DOOR FRAME - BACK WALL
L9FAC:
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F1                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB $D4                ; Vertical (Y axis) pixel offset (-44 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $01,$23,$7F,$E1,$80
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $D3                ; Vertical (Y axis) pixel offset (-45 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $02,$3F,$7C,$80
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $D3                ; Vertical (Y axis) pixel offset (-45 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $42,$FE,$3C,$03
  DEFB $09                ; Horizontal (X axis) pixel offset (+9 pixels)
  DEFB $D4                ; Vertical (Y axis) pixel offset (-44 pixels)
  DEFB $2C                ; Graphic consists of 44 bytes
  DEFB $41,$72,$FC,$08,$04,$02,$01,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$01,$01                 ;
; DOOR FRAME - SIDE WALL
  DEFB %00100001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F5                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB $C8                ; Vertical (Y axis) pixel offset (-56 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $90,$7E,$CF,$81
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $CC                ; Vertical (Y axis) pixel offset (-52 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $A0,$76,$1C,$0F
  DEFB $05                ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB $CE                ; Vertical (Y axis) pixel offset (-50 pixels)
  DEFB $2F                ; Graphic consists of 47 bytes
  DEFB $80,$C0,$E0,$1A,$1C,$16,$12,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01,$01 ;
  DEFB $01,$01,$01,$01,$01,$01,$01     ;

; Graphics - Cavern back wall background graphics
;
; These are the 'cavern equivalent' of the brickwork graphics at L9EE8.
;
; Used as decoration on the back walls in some of Avalon's caverns. See the
; routine at LC265 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
LA035:
  DEFB %00000100          ; Graphic properties (4 versions of graphic)
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $FA                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $02,$AF,$5A,$58,$50,$10
  DEFB $02                ; Horizontal (X axis) pixel offset (+2 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $07,$0B,$4B,$B9,$B0,$A0,$A0,$20 ;
  DEFB $20,$20,$20                     ;
; BACK WALL SCENERY 2
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $08,$18,$19,$3B,$3B,$3B,$6C,$82
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $08,$08,$28,$BC,$A5,$C7
; BACK WALL SCENERY 3
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F7                ; Horizontal (X axis) pixel offset (-9 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $80,$C0,$D0,$F3,$7F,$5E,$52,$52 ;
  DEFB $52,$52,$52,$02,$02,$02         ;
  DEFB $FF                ; Horizontal (X axis) pixel offset (-1 pixel)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $40,$FB,$F7,$B7,$97,$92,$92,$92 ;
  DEFB $80                             ;
; BACK WALL SCENERY 4
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $15                ; Graphic consists of 21 bytes
  DEFB $01,$01,$8D,$95,$95,$96,$D2,$60 ;
  DEFB $60,$60,$60,$60,$20,$40,$40,$60 ;
  DEFB $60,$E2,$A5,$AB,$97             ;

; Graphics - Tunnels
;
; For room numbers 224-255 - the vertically scrolling tunnel rooms (L6710).
;
; These graphics form forming the wall boundaries for the tunnels. They are
; mirrored/flipped for the left hand side walls.
LA09A:
  DEFB %00100001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F6                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB $D7                ; Vertical (Y axis) pixel offset (-41 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $80,$A0,$5C,$66,$20,$24,$78,$18 ;
  DEFB $1C,$1A,$0C,$07,$03             ;
  DEFB $FE                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB $E4                ; Vertical (Y axis) pixel offset (-28 pixels)
  DEFB $21                ; Graphic consists of 33 bytes
  DEFB $80,$C0,$E0,$80,$C0,$A0,$C0,$40 ;
  DEFB $64,$4C,$3C,$2C,$6A,$85,$C6,$C7 ;
  DEFB $E1,$D0,$60,$30,$22,$2C,$35,$36 ;
  DEFB $73,$61,$38,$34,$18,$1D,$07,$01 ;
  DEFB $01                             ;
  DEFB $06                ; Horizontal (X axis) pixel offset (+6 pixels)
  DEFB $01                ; Vertical (Y axis) pixel offset (+1 pixel)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $10,$30,$B0,$F0,$F0,$10,$1A,$05

; Graphics - Servant
;
; Maroc's servant, used to pick up, drop, and manipulate objects.
LA0DB:
  DEFB %10000010          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
; SERVANT GRAPHIC - FRAME 1
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $38,$7C,$54,$7C,$25,$FE,$7E,$3E ;
  DEFB $1E,$1E,$1C,$38,$30,$38,$18,$1C ;
; SERVANT GRAPHIC - FRAME 2
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $38,$7C,$54,$7C,$2F,$FE,$78,$78 ;
  DEFB $78,$38,$38,$1C,$1C,$18,$18,$70 ;

; Graphics - Eye cursor
;
; Flashing eye cursor - used for interaction/target spells, e.g. MISSILE, OPEN
; and REVEAL.
;
; EYE CURSOR GRAPHIC - FRAME 1
LA104:
  DEFB %10000010          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Eye cursor frame 1 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $01,$21,$10,$00,$07,$1A,$64,$84 ;
  DEFB $74,$0E,$01,$00,$08,$10         ;
; Eye cursor frame 1 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $08,$10,$00,$C0,$30,$2C,$23,$2C ;
  DEFB $30,$C0,$00,$10,$88,$80         ;
; EYE CURSOR - FRAME 2
  DEFB $02                ; Graphic consists of 2 tiles
; Eye cursor frame 2 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $01,$11,$0F,$3B,$C7,$3B,$0F,$11 ;
  DEFB $01                             ;
; Eye cursor frame 2 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $10,$20,$E0,$DC,$E3,$DC,$E0,$10

; Graphics - Scroll
;
LA140:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Scroll - tile 1
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $3F,$7F,$7F,$7F,$3D,$1B,$1A,$0D ;
  DEFB $0F,$0F,$3F,$4F,$4F,$3F         ;
; Scroll - tile 2
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $FC,$E4,$F8,$E0,$F0,$70,$78,$78 ;
  DEFB $7C,$7C,$FC,$FC,$FC,$F8         ;

; Graphics - Caliburn
;
LA164:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Caliburn - blade
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $01,$03,$07,$0E,$1C,$38,$70,$E0 ;
  DEFB $C0                             ;
; Caliburn - hilt
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $03,$3F,$4E,$16,$3A,$72,$E4,$C0 ;
  DEFB $80                             ;

; 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 (LA140) is used as an icon for the rest of the spells whose
; icons aren't listed here.
;
; AMULET (icon for AMULET spell)
LA17E:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Amulet - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $07,$18,$27,$4E,$5D,$9D,$BD,$BE ;
  DEFB $B8,$BE,$9E,$5E,$46,$23,$18,$07 ;
; Amulet - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $E0,$18,$E4,$72,$BA,$B9,$BD,$7D ;
  DEFB $1D,$7D,$79,$7A,$62,$C4,$18,$E0 ;
; CHALICE (icon for CHALICE spell)
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Chalice - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $12,$45,$2F,$3F,$5F,$38,$FB,$1B ;
  DEFB $FD,$3D,$FE,$1E,$3E,$4D,$1B     ;
; Chalice - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $48,$D4,$FC,$FD,$FE,$0C,$E8,$EF ;
  DEFB $DE,$98,$BE,$B8,$BC,$DF,$C8     ;
; Ring (icon for SERVANT spell)
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $3C,$7E,$E7,$C3,$C3,$E7,$7E,$3C
; Staff head (icon for MOVE spell)
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $3E,$6B,$6B,$7F,$22,$3E,$1C,$1C
  DEFB $1C,$1C,$1C,$1C,$1C,$1C,$1C,$1C
; Jewel (icon for WAYSTONE, SUMMON, DEFENCE, WRAITHBANE and ELECTRIC spells)
  DEFB $01                ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $18,$34,$72,$F1,$8F,$4E,$2C,$18

; Graphics - Missiles & bolts
;
; Various bolts and missiles used for ranged attacks by Maroc and some
; creatures. See the missile table at L6CDC to find out which creatures fire
; which missile type.
;
; MISSILE 1
LA1FB:
  DEFB %10000011          ; Graphic properties
; Missile 1 - frame 1
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $0C,$98,$98,$7E,$7E,$19,$19,$30
; Missile 1 - frame 2
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $20,$4E,$59,$7C,$3E,$9A,$72,$04
; Missile 1 - frame 3
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $18,$20,$3E,$BD,$BD,$7C,$04,$18
; MISSILE 2
;
; Missile 2 - frame 1
  DEFB %10000011          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Missile 2 - frame 1 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $07,$3F,$7C,$67,$4F,$9F,$9C,$38 ;
  DEFB $3C,$3E,$1F,$0F,$07             ;
; Missile 2 - frame 1 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $C0,$F0,$7C,$CC,$EC,$F6,$76,$E6 ;
  DEFB $CC,$1C,$FC,$F8,$E0             ;
; Missile 2 - frame 2
  DEFB $02                ; Graphic consists of 2 tiles
; Missile 2 - frame 2 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $06,$1F,$3F,$3C,$38,$39,$3D,$3C ;
  DEFB $1F,$0F,$07                     ;
; Missile 2 - frame 2 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $20,$30,$18,$98,$CC,$EC,$6C,$6C ;
  DEFB $CC,$1C,$F8,$F0,$E0             ;
; Missile 2 - frame 3
  DEFB $02                ; Graphic consists of 2 tiles
; Missile 2 - frame 3 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $07,$0F,$1F,$3C,$39,$72,$76,$77 ;
  DEFB $37,$33,$30,$18,$0F,$03         ;
; Missile 2 - frame 3 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $F0,$F8,$FC,$1C,$9C,$BC,$3C,$78 ;
  DEFB $F8,$F0,$C0,$08,$F0,$E0         ;
; MISSILE 3
;
; Missile 3 - frame 1
  DEFB %10000011          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Missile 3 - frame 1 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $30,$79,$EB,$64,$61,$23,$17,$37 ;
  DEFB $33,$38,$3E,$1F,$02,$01         ;
; Missile 3 - frame 1 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $C0,$E8,$3C,$C6,$96,$0C,$1C,$9C ;
  DEFB $3C,$F4,$0C,$FC,$F8,$F0         ;
; Missile 3 - frame 2
  DEFB $02                ; Graphic consists of 2 tiles
; Missile 3 - frame 2 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $03,$07,$0E,$38,$7B,$27,$18,$32 ;
  DEFB $33,$1D,$18,$38,$3F,$1E         ;
; Missile 3 - frame 2 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $80,$C0,$E0,$30,$9C,$E6,$76,$17 ;
  DEFB $8F,$FE,$8C,$F8,$F0             ;
; Missile 3 - frame 3
  DEFB $02                ; Graphic consists of 2 tiles
; Missile 3 - frame 3 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $03,$07,$1C,$3D,$72,$66,$66,$63 ;
  DEFB $33,$1C,$0C,$03,$03             ;
; Missile 3 - frame 3 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $08,$BC,$7E,$CE,$CE,$64,$68,$28 ;
  DEFB $B4,$74,$7C,$F8,$C0             ;

; 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 L6C7C for details.
;
; For information on this creature, see Creatures: Warlock
LA2EB:
  DEFB %10000011          ; Graphic properties
; WARLOCK - FRAME 1
  DEFB $02                ; Graphic consists of 2 tiles
; Warlock frame 1 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $03,$04,$05,$04,$02,$02,$02,$06 ;
  DEFB $0E,$3E,$5A,$1A,$56,$56,$56,$54 ;
  DEFB $43,$47,$07,$05,$05,$05,$05,$05 ;
  DEFB $0B,$0F,$04,$0E,$14,$0A,$00,$04 ;
; Warlock frame 1 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $E2,$12,$50,$12,$2B,$2F,$2F,$79 ;
  DEFB $79,$79,$F1,$F0,$F0,$F0,$F0,$D0 ;
  DEFB $60,$70,$70,$70,$70,$70,$50,$50 ;
  DEFB $50,$68,$68,$90,$28,$04,$40,$90 ;
; WARLOCK - FRAME 2
  DEFB $02                ; Graphic consists of 2 tiles
; Warlock frame 2 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $03,$04,$07,$04,$02,$02,$02,$0E ;
  DEFB $3E,$27,$5B,$43,$1B,$1B,$1B,$13 ;
  DEFB $13,$13,$03,$02,$02,$02,$06,$05 ;
  DEFB $05,$07,$05,$05,$00,$0A,$04,$02 ;
; Warlock - frame 2 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $E0,$10,$70,$10,$20,$23,$28,$3A ;
  DEFB $37,$77,$76,$72,$72,$62,$62,$00 ;
  DEFB $A0,$B0,$B0,$B0,$B0,$B0,$B0,$B8 ;
  DEFB $A8,$A8,$B8,$18,$90,$00,$40,$90 ;
; WARLOCK - FRAME 3
  DEFB $02                ; Graphic consists of 2 tiles
; Warlock frame 3 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $03,$04,$04,$04,$02,$02,$02,$00 ;
  DEFB $0E,$3F,$6F,$23,$2B,$2C,$0B,$0B ;
  DEFB $09,$0B,$03,$03,$02,$06,$06,$06 ;
  DEFB $06,$06,$05,$06,$01,$04,$01,$04 ;
; Warlock frame 3 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $E0,$10,$10,$10,$20,$20,$20,$20 ;
  DEFB $3C,$7A,$78,$72,$72,$72,$72,$52 ;
  DEFB $62,$72,$78,$F8,$F8,$E8,$E8,$E8 ;
  DEFB $C8,$88,$F4,$18,$AC,$8C,$20,$94 ;

; Graphics - Guardian of Chaos
;
; For information on this creature, see Creatures: Guardian of Chaos
LA3C1:
  DEFB %11100011          ; Graphic properties
; GUARDIAN OF CHAOS - FRAME 1
  DEFB $02                ; Graphic consists of 2 tiles
; Guardian of Chaos - frame 1 - left side
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $21                ; Graphic consists of 33 bytes
  DEFB $04,$04,$06,$0F,$01,$01,$17,$17 ;
  DEFB $17,$17,$06,$11,$4F,$A5,$E7,$A5 ;
  DEFB $A6,$A6,$E4,$E4,$A5,$EB,$CE,$57 ;
  DEFB $1D,$00,$1E,$1E,$1E,$1C,$00,$1C ;
  DEFB $3C                             ;
; Guardian of Chaos - frame 1 - right side
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $21                ; Graphic consists of 33 bytes
  DEFB $80,$80,$80,$E0,$E0,$F0,$F1,$F1 ;
  DEFB $C7,$AF,$6F,$E3,$0A,$6C,$6E,$06 ;
  DEFB $3E,$BC,$DC,$E0,$7C,$FC,$AC,$FC ;
  DEFB $50,$C0,$30,$70,$70,$70,$00,$78 ;
  DEFB $78                             ;
; GUARDIAN OF CHAOS - FRAME 2
  DEFB $02                ; Graphic consists of 2 tiles
; Guardian of Chaos - frame 2 - left side
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $EE                ; Vertical (Y axis) pixel offset (-18 pixels)
  DEFB $1E                ; Graphic consists of 30 bytes
  DEFB $10,$0F,$0F,$00,$00,$0B,$0B,$0B ;
  DEFB $0B,$05,$48,$4F,$25,$E7,$E5,$A6 ;
  DEFB $A4,$A5,$E4,$E5,$AB,$EA,$47,$5B ;
  DEFB $01,$3C,$3C,$00,$7C,$FC         ;
; Guardian of Chaos - frame 2 - right side
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $21                ; Graphic consists of 33 bytes
  DEFB $10,$90,$A0,$E0,$60,$60,$E0,$E0 ;
  DEFB $E4,$CE,$B0,$47,$DF,$5F,$8E,$26 ;
  DEFB $64,$80,$C6,$EE,$1E,$E0,$AC,$FC ;
  DEFB $50,$C8,$78,$70,$70,$70,$00,$70 ;
  DEFB $F0                             ;
; GUARDIAN OF CHAOS - FRAME 3
  DEFB $02                ; Graphic consists of 2 tiles
; Guardian of Chaos - frame 3 - left side
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $23                ; Graphic consists of 35 bytes
  DEFB $10,$10,$1F,$1F,$1F,$10,$10,$1D ;
  DEFB $1D,$0D,$05,$19,$4E,$E7,$A5,$E7 ;
  DEFB $A5,$A7,$A4,$E7,$E5,$A7,$E6,$6A ;
  DEFB $4E,$1D,$03,$3C,$1E,$1F,$0F,$0F ;
  DEFB $03,$1F,$1E                     ;
; Guardian of Chaos - frame 3 - right side
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $21                ; Graphic consists of 33 bytes
  DEFB $20,$20,$A1,$E1,$E3,$6F,$DF,$DF ;
  DEFB $E7,$E2,$C8,$9C,$5E,$BE,$BE,$A7 ;
  DEFB $1F,$EC,$E0,$08,$78,$54,$FC,$AC ;
  DEFB $FE,$40,$BC,$EC,$3C,$3C,$00,$3C ;
  DEFB $38                             ;

; Graphics - Goblin warrior
;
; Also known as Goblin Swordsman. For information on this creature, see
; Creatures: Goblin warrior
LA49C:
  DEFB %11100011          ; Graphic properties
; GOBLIN WARRIOR - FRAME 1
  DEFB $02                ; Graphic consists of 2 tiles
; Goblin warrior - frame 1 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $1D                ; Graphic consists of 29 bytes
  DEFB $06,$0B,$0B,$05,$1E,$0F,$03,$07 ;
  DEFB $00,$01,$01,$01,$01,$00,$00,$00 ;
  DEFB $00,$1F,$00,$01,$03,$07,$06,$00 ;
  DEFB $06,$03,$03,$03,$0E             ;
; Goblin warrior - frame 1 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $80,$60,$D8,$18,$E4,$EE,$F6,$FA ;
  DEFB $7A,$3A,$FD,$FB,$F8,$DE,$BC,$70 ;
  DEFB $E0,$C0,$A0,$70,$30,$18,$1C,$7C ;
; GOBLIN WARRIOR - FRAME 2
  DEFB $02                ; Graphic consists of 2 tiles
; Goblin warrior - frame 2 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $1E                ; Graphic consists of 30 bytes
  DEFB $30,$58,$58,$28,$F0,$70,$18,$3D ;
  DEFB $09,$04,$83,$43,$23,$13,$08,$07 ;
  DEFB $03,$00,$00,$03,$03,$06,$06,$06 ;
  DEFB $00,$06,$06,$06,$06,$0E         ;
; Goblin warrior - frame 2 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $16                ; Graphic consists of 22 bytes
  DEFB $40,$60,$50,$B8,$DC,$CC,$BC,$60 ;
  DEFB $9C,$7C,$7E,$00,$D8,$B0,$60,$E0 ;
  DEFB $E0,$50,$38,$1C,$06,$0C         ;
; GOBLIN WARRIOR - FRAME 3
  DEFB $02                ; Graphic consists of 2 tiles
; Goblin warrior - frame 3 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $1B                ; Graphic consists of 27 bytes
  DEFB $0C,$16,$16,$0A,$3C,$1E,$07,$0E ;
  DEFB $00,$01,$01,$01,$01,$00,$60,$1C ;
  DEFB $03,$00,$06,$0D,$0B,$07,$07,$06 ;
  DEFB $01,$03,$01                     ;
; Goblin warrior - frame 3 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $17                ; Graphic consists of 23 bytes
  DEFB $C0,$B0,$50,$CC,$EC,$F4,$E4,$EA ;
  DEFB $6A,$97,$56,$DF,$E8,$E0,$80,$B0 ;
  DEFB $B0,$90,$D0,$80,$C0,$60,$C0     ;

; Graphics - Goblin missile thrower
;
; For information on this creature, see Creatures: Goblin missile thrower
LA54D:
  DEFB %11100011          ; Graphic properties
; GOBLIN MISSILE THROWER - FRAME 1
  DEFB $02                ; Graphic consists of 2 tiles
; Goblin missile thrower - frame 1 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $1D                ; Graphic consists of 29 bytes
  DEFB $03,$07,$07,$00,$04,$0F,$03,$07 ;
  DEFB $E0,$C0,$A6,$96,$0B,$05,$00,$01 ;
  DEFB $01,$00,$03,$07,$0F,$00,$0F,$0E ;
  DEFB $07,$07,$02,$01,$07             ;
; Goblin missile thrower - frame 1 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $C0,$C0,$E0,$20,$A0,$A0,$80,$60 ;
  DEFB $F8,$DC,$DC,$2C,$B4,$EC,$6C,$9C ;
  DEFB $EC,$00,$EC,$EC,$FC,$60,$1C,$1C ;
  DEFB $1C,$1C,$8C,$8C,$04,$02,$06,$1E ;
; GOBLIN MISSILE THROWER - FRAME 2
  DEFB $02                ; Graphic consists of 2 tiles
; Goblin missile thrower - frame 2 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $03,$07,$07,$00,$04,$0F,$03,$E7 ;
  DEFB $C0,$A0,$90,$09,$07,$6F,$60,$00 ;
  DEFB $00,$00,$00,$01,$01,$00,$00,$01 ;
  DEFB $03,$07,$03,$01,$00,$00,$00,$01 ;
; Goblin missile thrower - frame 2 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $C0,$C0,$E0,$20,$A0,$A0,$80,$70 ;
  DEFB $F8,$7C,$EE,$EE,$EE,$DE,$3E,$FE ;
  DEFB $F6,$00,$F6,$F6,$FE,$00,$F8,$E8 ;
  DEFB $D8,$18,$9C,$8C,$04,$C0,$C6,$8E ;
; GOBLIN MISSILE THROWER - FRAME 3
  DEFB $02                ; Graphic consists of 2 tiles
; Goblin missile thrower - frame 3 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $03,$07,$07,$00,$04,$0F,$03,$E7 ;
  DEFB $C0,$A1,$91,$08,$05,$03,$0F,$1D ;
  DEFB $29,$20,$03,$03,$07,$00,$03,$03 ;
  DEFB $01,$01,$01,$01,$01,$00,$01,$03 ;
; Goblin missile thrower - frame 3 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $C0,$C0,$E0,$20,$A0,$A0,$80,$78 ;
  DEFB $FC,$4C,$F4,$EC,$DC,$B8,$78,$F8 ;
  DEFB $EC,$00,$EC,$EC,$FC,$00,$B0,$A0 ;
  DEFB $A0,$A0,$A0,$98,$98,$30,$80,$80 ;

; Graphics - Wraith
;
; For information on this creature, see Creatures: Wraith
LA620:
  DEFB %11100011          ; Graphic properties
; WRAITH - FRAME 1
  DEFB $02                ; Graphic consists of 2 tiles
; Wraith - frame 1 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F2                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB $16                ; Graphic consists of 22 bytes
  DEFB $78,$FC,$9E,$9E,$7C,$78,$F0,$24 ;
  DEFB $E3,$02,$62,$79,$49,$4D,$45,$86 ;
  DEFB $82,$84,$07,$07,$03,$01         ;
; Wraith - frame 1 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $E0,$B0,$B0,$A8,$50,$50,$60,$E0 ;
  DEFB $B0,$D8,$EC,$76,$B6,$B6,$B4,$D4 ;
  DEFB $54,$48,$58,$70,$E0,$C0,$C0,$60 ;
; WRAITH - FRAME 2
  DEFB $02                ; Graphic consists of 2 tiles
; Wraith - frame 2 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F2                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB $1F                ; Graphic consists of 31 bytes
  DEFB $3C,$7E,$27,$27,$DE,$5C,$72,$03 ;
  DEFB $30,$00,$00,$00,$00,$00,$38,$2F ;
  DEFB $2F,$2E,$49,$43,$86,$8D,$1B,$16 ;
  DEFB $2D,$2B,$2B,$2B,$33,$1D,$02     ;
; Wraith - frame 2 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $B8,$5C,$6E,$77,$35,$55,$55,$99 ;
  DEFB $FA,$1A,$E6,$6C,$D8,$B8,$60,$C0 ;
  DEFB $80,$00,$00,$00,$00,$00,$80,$70 ;
; WRAITH - FRAME 3
  DEFB $02                ; Graphic consists of 2 tiles
; Wraith - frame 3 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F2                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB $1B                ; Graphic consists of 27 bytes
  DEFB $78,$FC,$4E,$4E,$BC,$B8,$E4,$06 ;
  DEFB $23,$C0,$00,$10,$38,$2C,$4F,$4C ;
  DEFB $89,$8B,$02,$05,$0D,$0D,$0D,$0D ;
  DEFB $06,$03,$01                     ;
; Wraith - frame 3 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $E0,$B8,$D6,$5B,$5B,$2B,$D6,$36 ;
  DEFB $C4,$71,$D0,$A0,$60,$60,$40,$60 ;
  DEFB $70,$98,$EC,$3C,$18,$18,$10,$10 ;

; Graphics - Demon
;
; For information on this creature, see Creatures: Demon
LA6CE:
  DEFB %10000011          ; Graphic properties
; DEMON - FRAME 1
  DEFB $07                ; Graphic consists of 7 tiles
; Demon - frame 1 - tile 1
  DEFB $E4                ; Horizontal (X axis) pixel offset (-28 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $02                ; Graphic consists of 2 bytes
  DEFB $1F,$27
; Demon - frame 1 - tile 2
  DEFB $EC                ; Horizontal (X axis) pixel offset (-20 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $C0,$F8,$FF,$7C,$3F,$1E,$1D,$0B ;
  DEFB $0F,$0F                         ;
; Demon - frame 1 - tile 3
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $15                ; Graphic consists of 21 bytes
  DEFB $E0,$7F,$3F,$CF,$F1,$FE,$FE,$FD ;
  DEFB $7B,$27,$3F,$07,$03,$01,$01,$03 ;
  DEFB $02,$02,$02,$01,$01             ;
; Demon - frame 1 - tile 4
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $F2                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB $1F                ; Graphic consists of 31 bytes
  DEFB $81,$9D,$FF,$77,$00,$63,$55,$00 ;
  DEFB $00,$22,$3E,$FF,$FF,$FF,$B7,$C9 ;
  DEFB $77,$6B,$BE,$B2,$BF,$FF,$6B,$4B ;
  DEFB $53,$97,$A6,$64,$32,$32,$9A     ;
; Demon - frame 1 - tile 5
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $17                ; Graphic consists of 23 bytes
  DEFB $03,$07,$1C,$FB,$F7,$9F,$5F,$BF ;
  DEFB $5F,$6F,$F6,$FE,$F8,$F8,$70,$60 ;
  DEFB $40,$40,$A0,$A0,$A0,$A0,$A0     ;
; Demon - frame 1 - tile 6
  DEFB $0C                ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $FF,$F3,$0E,$FC,$78,$B0,$D0,$F0 ;
  DEFB $80                             ;
; Demon - frame 1 - tile 7
  DEFB $14                ; Horizontal (X axis) pixel offset (+20 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $70,$EC,$80
; DEMON - FRAME 2
  DEFB $05                ; Graphic consists of 5 tiles
; Demon - frame 2 - tile 1
  DEFB $EC                ; Horizontal (X axis) pixel offset (-20 pixels)
  DEFB $F3                ; Vertical (Y axis) pixel offset (-13 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $78,$9C,$0F,$07,$05,$07,$03,$03 ;
  DEFB $03,$03,$03,$02,$01             ;
; Demon - frame 2 - tile 2
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $F5                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB $11                ; Graphic consists of 17 bytes
  DEFB $80,$E0,$78,$BC,$DC,$EE,$E3,$DD ;
  DEFB $7E,$FE,$FD,$3B,$17,$0F,$07,$03 ;
  DEFB $01                             ;
; Demon - frame 2 - tile 3
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $F1                ; Vertical (Y axis) pixel offset (-15 pixels)
  DEFB $22                ; Graphic consists of 34 bytes
  DEFB $80,$80,$9C,$FF,$77,$00,$63,$36 ;
  DEFB $00,$00,$22,$44,$BE,$7F,$BE,$B6 ;
  DEFB $49,$77,$89,$BE,$BD,$12,$01,$70 ;
  DEFB $70,$40,$44,$84,$8C,$89,$C9,$CD ;
  DEFB $6D,$7D                         ;
; Demon - frame 2 - tile 4
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $F1                ; Vertical (Y axis) pixel offset (-15 pixels)
  DEFB $22                ; Graphic consists of 34 bytes
  DEFB $80,$80,$80,$80,$00,$01,$07,$1D ;
  DEFB $1B,$20,$6F,$DF,$BF,$7F,$FF,$9F ;
  DEFB $E1,$7F,$7E,$F8,$F0,$E0,$B0,$78 ;
  DEFB $E8,$D0,$B8,$A8,$48,$50,$D0,$D0 ;
  DEFB $50,$50                         ;
; Demon - frame 2 - tile 5
  DEFB $0C                ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB $F3                ; Vertical (Y axis) pixel offset (-13 pixels)
  DEFB $0C                ; Graphic consists of 12 bytes
  DEFB $0F,$38,$50,$A0,$60,$E0,$E0,$E0 ;
  DEFB $20,$F0,$C0,$80                 ;
; DEMON - FRAME 3
  DEFB $04                ; Graphic consists of 4 tiles
; Demon - frame 3 - tile 1
  DEFB $ED                ; Horizontal (X axis) pixel offset (-19 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $01,$03,$04,$03
; Demon - frame 3 - tile 2
  DEFB $F5                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $27                ; Graphic consists of 39 bytes
  DEFB $40,$20,$30,$30,$28,$29,$29,$75 ;
  DEFB $F4,$F6,$E6,$16,$F6,$F7,$FB,$7B ;
  DEFB $7B,$7D,$7D,$7A,$76,$8E,$7E,$3F ;
  DEFB $1F,$0F,$07,$0B,$0B,$09,$09,$05 ;
  DEFB $05,$05,$05,$05,$09,$09,$09     ;
; Demon - frame 3 - tile 3
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F2                ; Vertical (Y axis) pixel offset (-14 pixels)
  DEFB $22                ; Graphic consists of 34 bytes
  DEFB $01,$39,$FF,$EE,$00,$C6,$EE,$00 ;
  DEFB $01,$01,$45,$7D,$FF,$7D,$6D,$92 ;
  DEFB $EE,$92,$ED,$65,$FF,$FD,$BD,$BD ;
  DEFB $D5,$D5,$D5,$95,$25,$AD,$8E,$16 ;
  DEFB $26,$26                         ;
; Demon - frame 3 - tile 4
  DEFB $05                ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB $ED                ; Vertical (Y axis) pixel offset (-19 pixels)
  DEFB $27                ; Graphic consists of 39 bytes
  DEFB $04,$08,$08,$08,$18,$18,$38,$2C ;
  DEFB $6C,$FC,$C6,$BB,$BC,$BC,$B8,$B8 ;
  DEFB $B8,$B8,$78,$B8,$C8,$FC,$F0,$E0 ;
  DEFB $E0,$C0,$80,$80,$00,$00,$00,$C0 ;
  DEFB $40,$40,$40,$40,$40,$80,$80     ;

; Graphics - Warlock/demon materialization effect
LA847:
  DEFB %10000111          ; Graphic properties
; Materialization effect - frame 1
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F5                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $08,$20,$04,$00,$08,$20,$00,$00 ;
  DEFB $50,$24,$50,$02,$00,$10         ;
; Materialization effect - frame 2
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F4                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $10,$00,$08,$02,$28,$12,$28,$08 ;
  DEFB $00,$00,$10,$05,$02,$05,$10     ;
; Materialization effect - frame 3
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $14                ; Graphic consists of 20 bytes
  DEFB $04,$00,$28,$10,$28,$00,$24,$10 ;
  DEFB $00,$24,$10,$06,$50,$24,$51,$00 ;
  DEFB $04,$20,$08,$02                 ;
; Materialization effect - frame 4
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $16                ; Graphic consists of 22 bytes
  DEFB $01,$00,$14,$28,$10,$42,$10,$08 ;
  DEFB $14,$08,$22,$14,$28,$02,$28,$14 ;
  DEFB $28,$12,$00,$2A,$04,$2A         ;
; Materialization effect - frame 5
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $EF                ; Vertical (Y axis) pixel offset (-17 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $18,$18,$28,$14,$20,$0A,$64,$6A ;
  DEFB $18,$1A,$2A,$0A,$20,$0A,$5D,$08 ;
  DEFB $2A,$50,$2A,$24,$9A,$58,$02,$10 ;
; Materialization effect - frame 6
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $EF                ; Vertical (Y axis) pixel offset (-17 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $A2,$4A,$A7,$06,$29,$02,$14,$40 ;
  DEFB $3A,$30,$48,$02,$5D,$0C,$4A,$30 ;
  DEFB $35,$40,$29,$95,$48,$22,$D8,$04 ;

; Graphics - Disintegration animation
;
; Animation when a creature is destroyed by Maroc.
;
; UNUSED
LA8D7:
  DEFB $01,$00,$00,$01,$00
; DISINTEGRATION ANIMATION
  DEFB %10000111          ; Graphic properties
; DISINTEGRATION ANIMATION - FRAME 1
  DEFB $02                ; Graphic consists of 2 tiles
; Disintegration animation - frame 1 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $EE                ; Vertical (Y axis) pixel offset (-18 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $03,$3E,$00,$03,$0E,$01,$17,$00 ;
  DEFB $06,$38,$02,$03,$1C,$03,$00,$0D ;
  DEFB $00,$39,$00,$1B,$00,$3C,$00,$DC ;
  DEFB $00,$77,$00,$1C,$00,$73,$00,$1F ;
; Disintegration animation - frame 1 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $EE                ; Vertical (Y axis) pixel offset (-18 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $80,$7C,$30,$C0,$38,$E0,$10,$30 ;
  DEFB $1C,$E0,$1C,$30,$1C,$C0,$30,$C0 ;
  DEFB $00,$98,$00,$70,$00,$CC,$00,$F3 ;
  DEFB $00,$9C,$00,$70,$00,$9C,$00,$38 ;
; DISINTEGRATION ANIMATION - FRAME 2
  DEFB $02                ; Graphic consists of 2 tiles
; Disintegration animation - frame 2 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F5                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB $17                ; Graphic consists of 23 bytes
  DEFB $0C,$00,$00,$63,$00,$5C,$00,$67 ;
  DEFB $00,$39,$00,$DE,$00,$71,$00,$0E ;
  DEFB $38,$01,$3C,$03,$76,$1F,$79     ;
; Disintegration animation - frame 2 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $C0,$08,$C0,$00,$1C,$00,$FB,$00 ;
  DEFB $1E,$00,$E7,$00,$79,$00,$CE,$00 ;
  DEFB $30,$00,$CE,$30,$8F,$E2,$3C,$F7 ;
; DISINTEGRATION ANIMATION - FRAME 3
  DEFB $02                ; Graphic consists of 2 tiles
; Disintegration animation - frame 3 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $13                ; Graphic consists of 19 bytes
  DEFB $05,$00,$0C,$00,$2E,$00,$1D,$00 ;
  DEFB $5D,$00,$1C,$03,$08,$33,$0E,$14 ;
  DEFB $77,$6C,$3B                     ;
; Disintegration animation - frame 3 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $13                ; Graphic consists of 19 bytes
  DEFB $40,$00,$E4,$00,$9C,$00,$B4,$00 ;
  DEFB $B8,$00,$E8,$04,$70,$8C,$DA,$E7 ;
  DEFB $9A,$E6,$BC                     ;
; DISINTEGRATION ANIMATION - FRAME 4
  DEFB $02                ; Graphic consists of 2 tiles
; Disintegration animation - frame 4 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $0D,$00,$06,$30,$03,$0C,$33,$0C ;
  DEFB $03,$5C,$03,$2E,$19,$37,$7E,$F3 ;
; Disintegration animation - frame 4 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $80,$00,$60,$00,$30,$00,$6C,$00 ;
  DEFB $70,$00,$B8,$60,$98,$F8,$DE,$8F ;
; DISINTEGRATION ANIMATION - FRAME 5
  DEFB $02                ; Graphic consists of 2 tiles
; Disintegration animation - frame 5 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $08,$06,$00,$0B,$19,$06,$0E,$1B ;
  DEFB $0E,$39,$0F,$2F,$5E,$EF         ;
; Disintegration animation - frame 5 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $80,$00,$70,$00,$90,$60,$D0,$20 ;
  DEFB $E8,$90,$70,$BC,$EE,$3D         ;
; DISINTEGRATION ANIMATION - FRAME 6
  DEFB $02                ; Graphic consists of 2 tiles
; Disintegration animation - frame 6 - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $07                ; Vertical (Y axis) pixel offset (+7 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $02,$C4,$03,$0D,$26,$33,$D9
; Disintegration animation - frame 6 - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $07                ; Vertical (Y axis) pixel offset (+7 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $80,$30,$00,$E8,$60,$30,$C0

; 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 LD4B2.
;
; UNUSED
LA9E6:
  DEFB $01,$00,$00,$01,$00
; SHIELD BARRIER
  DEFB %10000010          ; Graphic properties
; SHIELD BARRIER - FRAME 1
  DEFB $02                ; Graphic consists of 2 tiles
; Shield barrier - frame 1 - left side
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $10,$20,$40,$30,$08,$10,$20,$10 ;
  DEFB $08,$1C,$04,$18,$20,$1C,$08,$10 ;
  DEFB $20,$18,$10,$20,$18,$04,$08,$10 ;
; Shield barrier - frame 1 - right side
  DEFB $0C                ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $08,$10,$20,$18,$04,$18,$10,$20 ;
  DEFB $18,$04,$08,$08,$04,$08,$10,$08 ;
  DEFB $10,$20,$40,$38,$04,$08,$10,$20 ;
; SHIELD BARRIER - FRAME 2
  DEFB $02                ; Graphic consists of 2 tiles
; Shield barrier - frame 2 - left side
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $10,$20,$10,$10,$08,$04,$18,$20 ;
  DEFB $18,$04,$08,$10,$30,$08,$04,$18 ;
  DEFB $20,$10,$08,$04,$18,$20,$18,$04 ;
; Shield barrier - frame 2 - right side
  DEFB $0C                ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB $F0                ; Vertical (Y axis) pixel offset (-16 pixels)
  DEFB $18                ; Graphic consists of 24 bytes
  DEFB $10,$08,$04,$08,$10,$20,$18,$04 ;
  DEFB $04,$08,$10,$08,$04,$04,$08,$1C ;
  DEFB $02,$04,$08,$04,$08,$10,$08,$04 ;

; Graphics - Foreground scenery - skeleton
;
; Foreground scenery is handled in the routine at LC501.
;
; Skeleton
LAA5A:
  DEFB %00000001          ; Graphic properties
  DEFB $05                ; Graphic consists of 5 tiles
; Decorative skeleton - tile 1
  DEFB $EC                ; Horizontal (X axis) pixel offset (-20 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $E1,$FF,$00,$80,$EF,$70
; Decorative skeleton - tile 2
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $E0,$FC,$03,$F8,$E7,$00,$07
; Decorative skeleton - tile 3
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $0D,$0E,$FC,$3F,$FC,$38,$C7
; Decorative skeleton - tile 4
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $4A,$A5,$95,$95,$FF,$95,$01,$FF
; Decorative skeleton - tile 5
  DEFB $0C                ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $08,$6E,$2F,$39,$FB,$8F,$8F,$0C

; Graphics - Foreground scenery items 1
;
; Foreground scenery is handled in the routine at LC501.
;
; SEAT
LAA8F:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Seat graphic - tile 1
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $07,$1F,$7F,$F5,$AA,$B5,$9F,$C0 ;
  DEFB $BF,$DB,$B1,$D1,$B1,$D1,$B1,$D1 ;
; Seat graphic - tile 2
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $F8,$FE,$FF,$57,$AB,$55,$F9,$07 ;
  DEFB $FF,$5F,$AF,$5F,$AF,$5F,$AF,$5F ;
; TABLE
  DEFB %00000001          ; Graphic properties
  DEFB $05                ; Graphic consists of 5 tiles
; Table - tile 1
  DEFB $EC                ; Horizontal (X axis) pixel offset (-20 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $01,$02,$07,$08,$1F,$20,$40,$FF ;
  DEFB $FF,$FF,$2F,$2F,$2F,$2E,$2C,$38 ;
; Table - tile 2
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $FF,$00,$FF,$00,$FF,$02,$01,$FF ;
  DEFB $FF,$FF                         ;
; Table - tile 3
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $FF,$1C,$EF,$50,$BF,$40,$80,$FF ;
  DEFB $FF,$FF                         ;
; Table - tile 4
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8  pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $FF,$00,$FF,$00,$FF,$00,$00,$FF ;
  DEFB $FF,$FF                         ;
; Table - tile 5
  DEFB $0C                ; Horizontal (X axis) pixel offset (+12 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $80,$40,$E0,$10,$F8,$04,$02,$FF ;
  DEFB $FF,$FF,$F4,$F4,$F4,$74,$34,$1C ;
; STOOL
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Stool - left side
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $03,$3E,$64,$88,$91,$E2,$FF,$E8 ;
  DEFB $68,$5F,$59,$59,$59,$59,$59,$F8 ;
; Stool - right side
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $E0,$3C,$46,$89,$13,$2F,$FF,$9E ;
  DEFB $96,$D6,$56,$56,$56,$56,$D6,$1E ;
; MISCELLANEOUS FOREGROUND GRAPHICS
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
; Misc foreground graphics - tile 1
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0C                ; Graphic consists of 12 bytes
  DEFB $0F,$3F,$78,$F3,$B7,$8F,$83,$C1 ;
  DEFB $31,$09,$07,$01                 ;
; Misc foreground graphics - tile 2
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $C0,$F1,$FC,$FC,$F4,$E4,$84,$04 ;
  DEFB $18,$60,$80                     ;
; Misc foreground graphics - tile 3
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $C8,$7E,$7F,$FD,$FC,$FB,$7F,$38 ;
  DEFB $00,$07,$01                     ;
; Misc foreground graphics - tile 4
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0C                ; Graphic consists of 12 bytes
  DEFB $10,$2C,$12,$8F,$E0,$63,$87,$EF ;
  DEFB $00,$18,$F8,$F0                 ;
; CUBE
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
; Cube - tile 1
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $07,$0F,$1F,$3F,$7F,$FF,$FF,$AA ;
  DEFB $D5,$AA,$D5,$AA,$D5,$AA,$D5,$FF ;
; Cube - tile 2
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $FF,$FD,$F9,$F1,$E1,$C1,$C1,$C1 ;
  DEFB $41,$C1,$42,$C4,$48,$D0,$60,$C0 ;

; Graphics - Foreground scenery items 2
;
; Foreground scenery is handled in the routine at LC501.
;
; BOX
LAB92:
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
; Box - tile 1
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $07,$0D,$1E,$3D,$3E,$FF,$80,$80 ;
  DEFB $FF,$80,$FF,$80,$FF,$80,$FF,$80 ;
; Box - tile 2
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $FF,$55,$AA,$55,$AA,$FF,$00,$00 ;
  DEFB $FF,$00,$FF,$00,$FF,$00,$FF,$00 ;
; Box - tile 3
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $FF,$55,$AA,$55,$AA,$FF,$00,$00 ;
  DEFB $FF,$00,$FF,$00,$FF,$00,$FF,$00 ;
; Box - tile 4
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $E0,$70,$B8,$7C,$BE,$FE,$02,$02 ;
  DEFB $FE,$02,$FE,$02,$FE,$02,$FE,$02 ;
; RUBBLE
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
; Rubble - tile 1
  DEFB $F5                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $0F,$27,$4A,$18,$33,$2C,$CC,$C8 ;
  DEFB $80                             ;
; Rubble - tile 2
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $0C,$3E,$7F,$9F,$02,$01,$C0,$C7 ;
  DEFB $E2,$12                         ;
; Rubble - tile 3
  DEFB $05                ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $70,$F8,$64,$64,$DC,$A0,$40,$F0 ;
  DEFB $98,$0C,$3C,$E6,$02,$83         ;

; Graphics - Foreground scenery items 3
;
; Foreground scenery is handled in the routine at LC501.
;
; STALAGMITES 1
LAC0C:
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
; Stalagmites 1 - tile 1
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $02,$02,$03,$07,$07,$67,$67,$E5 ;
  DEFB $F5,$F5,$F5,$F5,$8D,$88         ;
; Stalagmites 1 - tile 2
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $01,$03,$03,$03,$07,$07,$17,$35 ;
  DEFB $34,$34,$B4,$B4,$D4,$08         ;
; Stalagmites 1 - tile 3
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $80,$80,$88,$98,$98,$9C,$9C,$BC ;
  DEFB $FC,$E4,$E6,$C3,$08             ;
; BOULDER
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
; Boulder - tile 1
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $07,$1F,$3F,$3F,$7F,$7F,$DF,$AF ;
  DEFB $D7,$AA,$95,$42,$30,$0F         ;
; Boulder - tile 2
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $E0,$F8,$FE,$FF,$FF,$FF,$FF,$FE ;
  DEFB $D5,$AA,$55,$A8,$03,$FC         ;
; Boulder - tile 3
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $80,$8C,$BF,$7F,$D5,$6A,$54,$80 ;
  DEFB $80                             ;
; CREVASSE
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
; Crevasse - tile 1
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $04                ; Vertical (Y axis) pixel offset (+4 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $03,$3F,$D7,$0B
; Crevasse - tile 2
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $FF,$8B,$87,$4B,$27,$6B,$E7,$EC ;
  DEFB $E6,$ED                         ;
; Crevasse - tile 3
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $FE,$1E,$8E,$5E,$4C,$DC,$CC,$DC ;
  DEFB $CC,$F8,$C0                     ;
; SKULL PILE
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
; Skull pile - tile 1
  DEFB $F4                ; Horizontal (X axis) pixel offset (-12 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $0F,$1F,$3F,$3F,$26,$26,$16,$3D ;
  DEFB $7D,$FF,$FF,$99,$99             ;
; Skull pile - tile 2
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $0E,$3F,$BF,$FF,$CC,$4C,$63,$FB ;
  DEFB $FD,$F6,$B6,$36,$FE,$CE         ;
; Skull pile - tile 3
  DEFB $04                ; Horizontal (X axis) pixel offset (+4 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $80,$C0,$C0,$C0,$80,$00,$F0,$78 ;
  DEFB $FC,$FC,$9C,$94,$94             ;
; STALAGMITES 2
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
; Stalagmites 2 - tile 1
  DEFB $F5                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 14 bytes
  DEFB $01,$01,$01,$03,$03,$02,$02,$02 ;
  DEFB $06,$46,$4A,$EA,$EE,$B1,$87     ;
; Stalagmites - tile 2
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $80,$C0,$E0,$B0,$B0,$B0,$B0,$B0 ;
  DEFB $B0,$B0,$A8,$A8,$AC,$AC,$96,$11 ;
; Stalagmites - tile 3
  DEFB $05                ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $30,$78,$78,$78,$F8,$BC,$AA,$AB

; Graphics - Foreground scenery items 4
;
; Foreground scenery is handled in the routine at LC501.
;
; SPIKES
LACF9:
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
; Spikes - tile 1
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $08,$08,$08,$08,$08,$4A,$4A,$4A ;
  DEFB $4A,$4A,$4A,$5B,$FF             ;
; Spikes - tile 2
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $80,$80,$82,$82,$92,$92,$92,$92 ;
  DEFB $92,$92,$92,$93,$FF,$FF         ;
; Spikes - tile 3
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $08,$08,$08,$08,$08,$4A,$4A,$4A ;
  DEFB $4A,$4A,$4A,$5B,$FF             ;
; Spikes - tile 4
  DEFB $10                ; Horizontal (X axis) pixel offset (+16 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $80,$80,$82,$82,$92,$92,$92,$92 ;
  DEFB $92,$92,$92,$93,$FF,$FF         ;
; POOL
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
; Pool - tile 1
  DEFB $F2                ; Horizontal (X axis) pixel offset (-14 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $01,$03,$00,$00,$7F,$FF,$0E
; Pool - tile 2
  DEFB $FA                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $FF,$FF,$FF,$FF,$7F,$FF,$FF,$3F ;
  DEFB $7F                             ;
; Pool - tile 3
  DEFB $02                ; Horizontal (X axis) pixel offset (+2 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $C0,$E0,$FC,$FC,$FF,$FE,$F1,$FE ;
  DEFB $F0                             ;
; MOUND
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
; Mound - tile 1
  DEFB $EF                ; Horizontal (X axis) pixel offset (-17 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $07,$7F,$81,$01,$02,$04
; Mound - tile 2
  DEFB $F7                ; Horizontal (X axis) pixel offset (-9 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $01,$1F,$E0,$FF,$FF,$80
; Mound - tile 3
  DEFB $FF                ; Horizontal (X axis) pixel offset (-1 pixel)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $E0,$F8,$1F,$07,$E6,$0C,$70
; Mound - tile 4
  DEFB $07                ; Horizontal (X axis) pixel offset (+7 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $E0,$FC,$06,$0E,$C8

; 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.
LAD87:
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
; Shadow - tile 1
  DEFB $F5                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $15,$AA,$15
; Shadow - tile 2
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $55,$AA,$55
; Shadow - tile 3
  DEFB $05                ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $50,$AA,$50

; 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)
LAD9B:
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $01                ; Graphic consists of 1 byte
  DEFB $00                ; Single graphics byte, value = 0

; Graphics - Spider
;
; For information on this creature, see Creatures: Spider
LADA1:
  DEFB %10000010          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
; SPIDER - FRAME 1
  DEFB $F1                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB $F5                ; Vertical (Y axis) pixel offset (-11 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $02,$05,$08,$10,$24,$2A,$11,$28 ;
  DEFB $16,$21,$4E,$91,$20,$40,$80     ;
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $80,$40,$40,$20,$3F,$FF,$7F,$FE ;
  DEFB $F9,$FB,$3F,$18,$0C             ;
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $0C,$09,$11,$22,$F4,$F8,$FF,$F8 ;
  DEFB $3B,$BC,$E0,$60,$C0             ;
  DEFB $09                ; Horizontal (X axis) pixel offset (+9 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $60,$98,$87,$40,$7C,$83,$30,$C8 ;
  DEFB $04,$02,$01                     ;
; Spider - Frame 2
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F1                ; Horizontal (X axis) pixel offset (-15 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $03,$04,$00,$7C,$83,$1C,$22,$41 ;
  DEFB $81,$9E,$11,$08,$04,$02,$02,$04 ;
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $C0,$20,$20,$20,$40,$7F,$FF,$FF ;
  DEFB $FD,$F2,$FF,$BF,$0D,$08         ;
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $F6                ; Vertical (Y axis) pixel offset (-10 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $01,$32,$2F,$22,$24,$E5,$FA,$FC ;
  DEFB $F8,$73,$FC,$E0,$80,$80         ;
  DEFB $09                ; Horizontal (X axis) pixel offset (+9 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $80,$40,$A0,$10,$88,$40,$20,$10 ;
  DEFB $88,$86,$80,$80,$80,$80,$80,$60 ;

; Graphics - Bat
;
; For information on this creature, see Creatures: Bat
LAE2C:
  DEFB %10000100          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
; Bat - animation frame 1
  DEFB $F2                ; Horizontal (X axis) pixel offset (-14 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $60,$F8,$7E,$23,$3E,$0F,$06,$05 ;
  DEFB $03                             ;
  DEFB $FA                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $80,$48,$E7,$F5,$EF,$EF,$37,$07 ;
  DEFB $08                             ;
  DEFB $02                ; Horizontal (X axis) pixel offset (+2 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $03,$06,$0B,$97,$3B,$7D,$BE,$B8 ;
  DEFB $60,$00,$80                     ;
  DEFB $0A                ; Horizontal (X axis) pixel offset (+10 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $30,$F8,$F0,$20,$E0,$80
; Bat - animation frame 2
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $07,$1E,$3D,$7C,$60
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $02,$01,$FD,$BB,$EB,$DD,$41,$02
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $20,$C0,$5F,$EE,$EB,$DD,$C1,$20
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $80,$F0,$BC,$DE,$1F,$03
; Bat - animation frame 3
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $13                ; Graphic consists of 19 bytes
  DEFB $02,$01,$05,$0B,$1B,$3D,$6A,$D0 ;
  DEFB $C0,$C0,$E0,$C0,$C0,$C0,$40,$40 ;
  DEFB $40,$60,$20                     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $13                ; Graphic consists of 19 bytes
  DEFB $20,$C0,$50,$E8,$EC,$DE,$2B,$05 ;
  DEFB $01,$01,$03,$01,$01,$01,$01,$01 ;
  DEFB $01,$03,$02                     ;
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $04                ; Vertical (Y axis) pixel offset (+4 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $80,$80,$80,$80,$80,$80,$80
; Bat - animation frame 4
  DEFB $05                ; Graphic consists of 5 tiles
  DEFB $ED                ; Horizontal (X axis) pixel offset (-19 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $0F,$3D,$60
  DEFB $F5                ; Horizontal (X axis) pixel offset (-11 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $FC,$7B,$EF,$5F,$0F,$03
  DEFB $FD                ; Horizontal (X axis) pixel offset (-3 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $44,$38,$AB,$7D,$7D,$BB,$7D,$C6
  DEFB $05                ; Horizontal (X axis) pixel offset (+5 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $7E,$BD,$EF,$F4,$E0,$80
  DEFB $0D                ; Horizontal (X axis) pixel offset (+13 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $E0,$78,$0C

; 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.
LAEE6:
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $3C,$7E,$DB,$C9,$D5,$D5,$7F,$3E

; Graphics - Energy bar (on scroll)
;
; Represents Maroc's current energy (0-255). Each 8 byte tile of the bar
; represents 16 units of energy.
LAEF3:
  DEFB %00000001          ; Graphic properties
  DEFB $10                ; Graphic consists of 16 tiles
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $81,$FF,$FB,$ED,$D6,$FD,$DF,$80
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $FC,$9C,$CF,$FF,$FC,$FF,$FF,$7F
  DEFB $10                ; Horizontal (X axis) pixel offset (+16 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $00,$18,$FC,$84,$03,$13,$F0,$C0
  DEFB $18                ; Horizontal (X axis) pixel offset (+24 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $03,$07,$7E,$FF,$FC,$FF,$07,$01
  DEFB $20                ; Horizontal (X axis) pixel offset (+32 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $27,$C8,$30,$E1,$07,$FE,$F8,$E0
  DEFB $28                ; Horizontal (X axis) pixel offset (+40 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $0F,$3F,$F9,$E0,$80,$E0,$10,$20
  DEFB $30                ; Horizontal (X axis) pixel offset (+48 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $00,$C0,$FC,$7F,$03,$00,$00,$00
  DEFB $38                ; Horizontal (X axis) pixel offset (+56 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $00,$00,$FC,$FE,$27,$11,$10,$21
  DEFB $40                ; Horizontal (X axis) pixel offset (+64 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $01,$06,$18,$30,$E0,$FF,$7F,$0F
  DEFB $48                ; Horizontal (X axis) pixel offset (+72 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $80,$40,$07,$0F,$3F,$FC,$F8,$E0
  DEFB $50                ; Horizontal (X axis) pixel offset (+80 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $7F,$FF,$FC,$FF,$89,$11,$0E,$00
  DEFB $58                ; Horizontal (X axis) pixel offset (+88 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $E0,$F8,$1C,$07,$03,$01,$00,$00
  DEFB $60                ; Horizontal (X axis) pixel offset (+96 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $00,$02,$0E,$F8,$80,$C0,$FF,$7F
  DEFB $68                ; Horizontal (X axis) pixel offset (+104 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $00,$00,$03,$07,$0E,$1C,$F8,$E0
  DEFB $70                ; Horizontal (X axis) pixel offset (+112 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $18,$FE,$E1,$18,$04,$02,$01,$00
  DEFB $78                ; Horizontal (X axis) pixel offset (+120 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $00,$00,$81,$42,$3C,$00,$00,$00

; Graphics - Scroll pointer arrow
;
; Pointer to the selected spell on the scroll. Position does not change.
;
; SCROLL ARROW POINTER GRAPHIC
LAFA5:
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $01,$02,$04,$08,$10,$22,$46,$8F ;
  DEFB $46,$24,$10,$08,$04,$02,$01     ;
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $00,$80,$80,$80,$FF,$41,$9A,$3C ;
  DEFB $59,$82,$FF,$80,$80,$80,$00     ;
  DEFB $10                ; Horizontal (X axis) pixel offset (+16 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $00,$00,$00,$00,$FF,$04,$69,$F3 ;
  DEFB $45,$08,$FF,$00,$00,$00,$00     ;
  DEFB $18                ; Horizontal (X axis) pixel offset (+24 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0F                ; Graphics consists of 15 bytes
  DEFB $00,$00,$00,$00,$FF,$11,$A5,$CD ;
  DEFB $95,$21,$FF,$00,$00,$00,$00     ;

; Graphics - Key and Chest
;
; Key 1
LAFEF:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $FA                ; Horizontal (X axis) pixel offset (-6 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $60,$FF,$F0,$60
  DEFB $02                ; Horizontal (X axis) pixel offset (+2 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $03                ; Graphic consists of 3 bytes
  DEFB $F8,$A8,$A8
; Chest - closed
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $7F,$AA,$97,$A9,$F9,$89,$F0,$89 ;
  DEFB $FF,$80,$FF                     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $FF,$AF,$57,$AF,$FF,$0F,$FF,$0F ;
  DEFB $FE,$0C,$F8                     ;
; Chest - open
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $3F,$3F,$3F,$3F,$26,$20,$40,$80 ;
  DEFB $80,$FF,$80,$FF,$80,$FF         ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $FF,$FF,$FF,$FF,$19,$03,$07,$0F ;
  DEFB $0F,$FF,$0F,$FE,$0C,$F8         ;

; Graphics - Buried bottle and Lever
;
; Buried bottle (pre-state)
LB040:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F6                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $03,$06,$0D,$1B,$37,$6F,$DE,$CD
  DEFB $FE                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $08,$1C,$F2,$E4,$E8,$D8,$B8,$78 ;
  DEFB $F8,$C0                         ;
; Broken bottle (post-state)
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $08,$1C,$34,$6E,$DD,$FF,$00,$13 ;
  DEFB $31                             ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $02                ; Vertical (Y axis) pixel offset (+2 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $40,$E0,$EF,$1E,$80
; Pick/lever
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $02                ; Graphic consists of 2 bytes
  DEFB $FF,$FF
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $01,$03,$03,$FF,$FF,$03,$03,$01

; Graphics - Cheese & Mouse Hole
;
LB082:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0C                ; Graphic consists of 12 bytes
  DEFB $03,$0F,$3E,$7F,$80,$FF,$F7,$FE ;
  DEFB $67,$E7,$FF,$FF                 ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $F8,$FC,$EE,$FE,$FE,$02,$FE,$FE ;
  DEFB $FF,$FE,$FE,$FC,$FC             ;
; Mouse hole
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $07,$08,$17,$2F,$5F,$5F,$BF,$BF ;
  DEFB $BF                             ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $F8,$18,$EC,$F6,$FA,$FA,$FD,$FD ;
  DEFB $FD                             ;

; Graphics - Keys (key 2 and hanging key)
;
; UNUSED
LB0BD:
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $01                ; Graphic consists of 1 byte
  DEFB $FF
; UNUSED
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $01                ; Graphic consists of 1 byte
  DEFB $FF
; Key - hanging
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $F3                ; Horizontal (X axis) pixel offset (-13 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $19                ; Graphic consists of 25 bytes
  DEFB $08,$08,$6B,$9C,$AB,$48,$08,$08 ;
  DEFB $08,$1C,$2A,$22,$22,$1C,$08,$08 ;
  DEFB $08,$08,$08,$08,$1E,$18,$1E,$18 ;
  DEFB $1E                             ;
; Key 2
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $70,$88,$8F,$88,$70
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $1F,$FF,$15,$15

; Graphics - Star
;
; Star (on floor)
;
; Star which is placed on the floor star symbol to create a permanent healing
; spot.
LB0F8:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $01,$FF,$44,$28,$10,$28,$44,$FF ;
  DEFB $01                             ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $80,$40,$FF,$22,$14,$08,$14,$22 ;
  DEFB $FF,$40,$80                     ;
; Star (symbol)
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $FB                ; Horizontal (X axis) pixel offset (-5 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $04,$04,$6E,$7F,$3F,$1F,$3F,$7F ;
  DEFB $6E,$04                         ;
  DEFB $03                ; Horizontal (X axis) pixel offset (+3 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $C0,$C0,$80,$00,$80,$C0,$C0

; Graphics - Various
;
; Coins
LB12D:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $71,$FB,$FB,$8A,$FB,$8A,$FB,$8A ;
  DEFB $FB,$8A,$FB,$8A,$FB,$8A,$71     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $C0,$E0,$E0,$20,$E0,$20,$E0,$20 ;
  DEFB $E0,$20,$E0,$26,$EF,$2F,$C6     ;
; Fish (red herring?)
;
; Interactable object that actually does damage to Maroc. Leave it alone.
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $C1,$FF,$7F,$FF,$CF,$81
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $80,$F0,$BC,$F4,$FC,$F0
; Bottle
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $18,$24,$3C,$3C,$7E,$FF,$BF,$AB ;
  DEFB $AB,$AB,$EB,$FF,$FF,$FF,$7E     ;
; Mushrooms
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0A                ; Graphic consists of 10 bytes
  DEFB $3E,$5F,$F5,$DF,$EF,$12,$12,$12 ;
  DEFB $12,$21                         ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $1C,$3A,$2E,$BE,$94,$14,$14,$14 ;
  DEFB $22                             ;

; Graphics - Scorpion
;
; Scorpion
;
; For information on this creature, see Creatures: Scorpion
LB196:
  DEFB %10000010          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
; Scorpion - frame 1
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $07,$09,$09,$19,$1B,$27,$03,$1F ;
  DEFB $27,$1F,$3F,$27,$60,$70,$30     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $80,$80,$80,$A0,$C0,$80,$F0,$88 ;
  DEFB $E0,$F0,$90,$18,$38,$10         ;
; Scorpion - frame 2
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $03,$0D,$19,$31,$35,$43,$1B,$27 ;
  DEFB $03,$7F,$4F,$47,$60,$50,$60     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $80,$80,$A0,$A0,$E4,$88,$F0,$80 ;
  DEFB $F8,$C4,$86,$03,$05,$05         ;

; Graphics - Axe, Bone, Orb, Sabre
;
; Axe
LB1DF:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $20,$58,$BF,$BE,$BE,$BE,$BA,$52 ;
  DEFB $22,$02,$02,$02,$02,$02,$02,$03 ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $0C,$32,$F9,$7D,$7D,$7D,$5D,$4A ;
  DEFB $44,$40,$40,$40,$40,$40,$40,$C0 ;
; Bone
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $60,$FF,$FF,$FF,$FF,$60
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $0E,$1F,$FF,$FE,$FF,$FF,$1E
; Orb
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $07,$1F,$3A,$70,$40,$E0,$C1,$E2 ;
  DEFB $D5,$EA,$F5,$7F,$7F,$3F,$1F,$07 ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $E0,$F8,$7C,$BE,$5E,$BF,$5F,$BF ;
  DEFB $5F,$BF,$FF,$FE,$FE,$FC,$F8,$E0 ;
; Sabre  - non-animated version
;
; Not to be confused with the animated sabre (LB286)
;
; The only use of this sabre is to kill a particular bat for a spell scroll
; (see Creatures: Bat)
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $02                ; Vertical (Y axis) pixel offset (+2 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $01,$03,$06,$0C,$38,$C0
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $06,$6E,$1C,$1C,$3A,$3A,$60,$60 ;
  DEFB $C0,$C0,$80                     ;

; Graphics - Mouse
;
; For information on this creature, see Creatures: Mouse
;
; Mouse - frame 1
LB25D:
  DEFB %11100010          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $18,$18,$3F,$7F,$FF,$18,$0C
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $04,$E2,$F2,$FC,$18,$10
; Mouse - frame 2
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F9                ; Horizontal (X axis) pixel offset (-7 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $08,$18,$FF,$7F,$1F,$18,$30
  DEFB $01                ; Horizontal (X axis) pixel offset (+1 pixel)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $01,$E1,$F6,$F8,$18,$04

; Graphics - Sabre - animated
;
; Animated sabre
;
; Not to be confused with the non-animated sabre (B244).
;
; This (animated) sabre, found in room 57 in the Chambers of Chaos, is a moving
; room object (L736F) 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).
LB286:
  DEFB %11100010          ; Graphic properties
; Sabre - frame 1
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $02                ; Vertical (Y axis) pixel offset (+2 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $01,$03,$06,$0C,$38,$C0
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $06,$6E,$1C,$1C,$3A,$3A,$60,$60 ;
  DEFB $C0,$C0,$80                     ;
; Sabre - frame 2
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $06                ; Graphic consists of 6 bytes
  DEFB $C0,$38,$0C,$06,$03,$01
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $80,$C0,$C0,$60,$60,$3A,$3A,$1C ;
  DEFB $1C,$6E,$06                     ;

; Graphics - Trapdoor
;
; Trapdoor - closed
LB2B7:
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $1F,$10,$3F,$3F,$40,$7F,$FF,$FF
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $FF,$00,$FF,$FF,$00,$FF,$FF,$FF
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $FF,$00,$FF,$FF,$00,$FF,$FF,$FF
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $F8,$08,$FC,$FC,$02,$FE,$FF,$FF
; Trapdoor - open
  DEFB %00000001          ; Graphic properties
  DEFB $04                ; Graphic consists of 4 tiles
  DEFB $F0                ; Horizontal (X axis) pixel offset (-16 pixels)
  DEFB $F4                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $03,$02,$07,$04,$0F,$0F,$1F,$18 ;
  DEFB $38,$30,$70,$6F,$DF,$FF         ;
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F4                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $FF,$00,$FF,$00,$FF,$FF,$FF,$00 ;
  DEFB $00,$00,$00,$FF,$FF,$FF         ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F4                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $FF,$00,$FF,$00,$FF,$FF,$FF,$00 ;
  DEFB $00,$00,$00,$FF,$FF,$FF         ;
  DEFB $08                ; Horizontal (X axis) pixel offset (+8 pixels)
  DEFB $F4                ; Vertical (Y axis) pixel offset (-12 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $C0,$40,$E0,$20,$F0,$F0,$F8,$18 ;
  DEFB $1C,$0C,$0E,$F6,$FB,$FF         ;

; 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 7153).
LB32B:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $14                ; Graphic consists of 20 bytes
  DEFB $07,$08,$08,$10,$1F,$08,$0B,$10 ;
  DEFB $18,$08,$0C,$08,$07,$E1,$A2,$A2 ;
  DEFB $04,$E0,$A1,$A0                 ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F7                ; Vertical (Y axis) pixel offset (-9 pixels)
  DEFB $14                ; Graphic consists of 20 bytes
  DEFB $E0,$18,$04,$04,$82,$62,$21,$21 ;
  DEFB $21,$21,$41,$42,$42,$42,$42,$41 ;
  DEFB $41,$81,$01,$02                 ;

; 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
LB35B:
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FE                ; Vertical (Y axis) pixel offset (-2 pixels)
  DEFB $05                ; Graphic consists of 5 bytes
  DEFB $70,$88,$85,$88,$70
; Key - right side
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $04                ; Graphic consists of 4 bytes
  DEFB $1F,$FF,$15,$15
; Oil jar
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $0F,$08,$1F,$3F,$7F,$7F,$7F,$61 ;
  DEFB $6D,$6D,$61,$61,$7F,$3F,$1F,$0F ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $F8,$08,$FC,$F7,$FF,$FF,$B7,$F7 ;
  DEFB $B7,$B7,$B3,$B3,$FF,$FE,$FC,$F8 ;
; Coin
  DEFB %00000001          ; Graphic properties
  DEFB $01                ; Graphic consists of 1 tile
  DEFB $FC                ; Horizontal (X axis) pixel offset (-4 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $07                ; Graphic consists of 7 bytes
  DEFB $38,$7C,$EE,$EE,$EE,$7C,$38
; Altar/idol
;
; Statue/altar found in the Chambers of Chaos
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $02,$07,$04,$04,$87,$FC,$FD,$FF ;
  DEFB $0F,$7F,$FF,$F0,$7C,$7C,$1C,$38 ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $20,$F0,$90,$90,$F1,$3F,$BF,$F0 ;
  DEFB $FC,$FC,$FC,$1C,$78,$70,$70,$38 ;

; Graphics - Fire
;
; Fire - animation frame 1
LB3CA:
  DEFB %10000010          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $11,$21,$60,$60,$30,$31,$19,$1D ;
  DEFB $0C,$0C,$1E,$1D,$3D,$7B,$FF,$EF ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $00,$02,$82,$82,$C6,$CC,$CC,$EC ;
  DEFB $EC,$EC,$EE,$EE,$EE,$EE,$EC,$F8 ;
; Fire - animation frame 2
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $10,$08,$08,$0C,$0D,$1D,$1C,$1C ;
  DEFB $38,$70,$E0,$E4,$64,$6C,$6D,$FF ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F8                ; Vertical (Y axis) pixel offset (-8 pixels)
  DEFB $10                ; Graphic consists of 16 bytes
  DEFB $00,$42,$84,$84,$8C,$8C,$8E,$8E ;
  DEFB $CE,$E6,$74,$74,$30,$B0,$B4,$FE ;

; Graphics - Elemental Symbols
;
; The four elemental symbols needed to open the portal to the High Temple of
; Chaos.
;
; Fire symbol
LB419:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $07,$0F,$1D,$3B,$78,$FC,$FE,$FF ;
  DEFB $FF,$FF,$7E,$3E,$1F,$0F,$07     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $C0,$E0,$F0,$F8,$FC,$FE,$7E,$3E ;
  DEFB $3E,$7E,$7C,$F8,$F0,$E0,$C0     ;
; Water symbol
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $07,$0F,$1F,$3F,$77,$EB,$DD,$F6 ;
  DEFB $EB,$7D,$3E,$1F,$0F,$07         ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $C0,$E0,$F0,$F8,$DC,$AE,$76,$DE ;
  DEFB $AE,$7C,$F8,$F0,$E0,$C0         ;
; Earth symbol
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $07,$0E,$1C,$3C,$7E,$F2,$F2,$FC ;
  DEFB $FE,$FE,$7E,$3C,$1A,$0F,$07     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $C0,$E0,$70,$78,$FC,$9E,$9E,$7E ;
  DEFB $FE,$FE,$FC,$78,$B0,$E0,$C0     ;
; Air symbol
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $07,$0F,$1F,$3C,$7C,$FC,$80,$C0 ;
  DEFB $E0,$F0,$7C,$3E,$1E,$0F,$07     ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0F                ; Graphic consists of 15 bytes
  DEFB $C0,$E0,$F0,$F8,$7C,$FE,$06,$0E ;
  DEFB $1E,$3E,$FC,$F8,$70,$E0,$C0     ;

; Graphics - Pick Axe
;
; Pick axe
LB4AF:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $08                ; Graphic consists of 8 bytes
  DEFB $60,$C0,$C0,$FF,$FF,$C0,$C0,$60
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $00                ; Vertical (Y axis) pixel offset (0 pixels)
  DEFB $02                ; Graphic consists of 2 bytes
  DEFB $FF,$FF

; Graphics - Portal Floor Symbol and Door
;
; Portal floor symbol
;
; Place each of the element symbols (LB419) on this floor circle to reveal the
; portal door that will take you to the High Temple of Chaos.
LB4C1:
  DEFB %00000001          ; Graphic properties
  DEFB $03                ; Graphic consists of 3 tiles
  DEFB $F6                ; Horizontal (X axis) pixel offset (-10 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $03,$1C,$21,$46,$98,$A0,$CF,$A0 ;
  DEFB $98,$46,$21,$1C,$03             ;
  DEFB $FE                ; Horizontal (X axis) pixel offset (-2 pixels)
  DEFB $FA                ; Vertical (Y axis) pixel offset (-6 pixels)
  DEFB $0D                ; Graphic consists of 13 bytes
  DEFB $FE,$51,$8C,$23,$20,$20,$DF,$20 ;
  DEFB $20,$23,$8C,$51,$FE             ;
  DEFB $06                ; Horizontal (X axis) pixel offset (+6 pixels)
  DEFB $FB                ; Vertical (Y axis) pixel offset (-5 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $C0,$20,$10,$C8,$28,$98,$28,$C8 ;
  DEFB $10,$20,$C0                     ;
; Portal door
;
; The portal door that takes you to the High Temple of Chaos.
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $E9                ; Vertical (Y axis) pixel offset (-23 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $2A,$80,$00,$80,$00,$80,$00,$80 ;
  DEFB $00,$80,$00,$80,$00,$80,$00,$80 ;
  DEFB $00,$80,$00,$80,$00,$80,$00,$80 ;
  DEFB $00,$80,$00,$80,$00,$80,$00,$80 ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $E9                ; Vertical (Y axis) pixel offset (-23 pixels)
  DEFB $20                ; Graphic consists of 32 bytes
  DEFB $AA,$01,$00,$01,$00,$01,$00,$01 ;
  DEFB $00,$01,$00,$01,$00,$01,$00,$01 ;
  DEFB $00,$01,$00,$01,$00,$01,$00,$01 ;
  DEFB $00,$01,$00,$01,$00,$01,$00,$01 ;

; 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 (LA164), to complete the game.
LB539:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $12                ; Graphic consists of 18 bytes
  DEFB $7F,$55,$EA,$DD,$DA,$B0,$DC,$B3 ;
  DEFB $D3,$B8,$DA,$AE,$DF,$AE,$DF,$7F ;
  DEFB $7F,$0F                         ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FF                ; Vertical (Y axis) pixel offset (-1 pixel)
  DEFB $12                ; Graphic consists of 18 bytes
  DEFB $F8,$54,$AA,$56,$2B,$07,$17,$37 ;
  DEFB $37,$87,$DF,$1F,$FF,$1F,$FF,$FF ;
  DEFB $FE,$F8                         ;

; Graphics - Elemental Symbol (blank) and Healing Star
;
; Blank symbol
;
; After placing an Elemental Symbol (LB419) on the Portal Floor Marking
; (LB4C1), the symbol is wiped off the disc confirming the action has been
; successful.
LB565:
  DEFB %00000001          ; Graphic properties
  DEFB $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $07,$0F,$1F,$3F,$7F,$FF,$FF,$FF ;
  DEFB $FF,$7F,$3F,$1F,$0F,$07         ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $F9                ; Vertical (Y axis) pixel offset (-7 pixels)
  DEFB $0E                ; Graphic consists of 14 bytes
  DEFB $C0,$E0,$F0,$F8,$FC,$FE,$FE,$FE ;
  DEFB $FE,$FC,$F8,$F0,$E0,$C0         ;
; Healing Star (Floor)
;
; After obtaining the Star Symbol (B114) from the warlock (LA2EB), place it on
; the Star marked on the floor (LB0F8) 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 $02                ; Graphic consists of 2 tiles
  DEFB $F8                ; Horizontal (X axis) pixel offset (-8 pixels)
  DEFB $FD                ; Vertical (Y axis) pixel offset (-3 pixels)
  DEFB $09                ; Graphic consists of 9 bytes
  DEFB $01,$FF,$7C,$38,$10,$38,$7C,$FF ;
  DEFB $01                             ;
  DEFB $00                ; Horizontal (X axis) pixel offset (0 pixels)
  DEFB $FC                ; Vertical (Y axis) pixel offset (-4 pixels)
  DEFB $0B                ; Graphic consists of 11 bytes
  DEFB $80,$C0,$FF,$3E,$1C,$08,$1C,$3E ;
  DEFB $FF,$C0,$80                     ;

; Unused
LB5A5:
  DEFB $FF,$3E,$00,$32,$2A,$D0,$21,$51
  DEFB $B1,$7E,$E6,$0F,$32,$29,$D0,$23
  DEFB $22,$2D,$D0,$01,$FE,$7F,$ED,$78
  DEFB $F6,$E0,$4F,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00

; Controls choice and game flag
;
; Control option (1-4) as set in the first game menu (L8039).
LBF18:
  DEFB $00                ; 1 = Kempston, 2 = AGF (Cursor), 3 = Sinclair, 4 =
                          ; Keyboard
; Game flag, as selected in the second game menu (L811B).
  DEFB $00                ; 0 = New game, 1 = Load save game

; Initialize game
;
; Used by the routine at LF350.
;
; Launch of main game, once the player has entered 3 correct security codes
; from the code sheet.
LBF1A:
  LD HL,($5C3D)           ; Get ERRSP (stack pointer error return address)
  LD SP,HL                ;
  POP HL                  ; Replace with stack address LBF33 in case there's an
  LD HL,LBF33             ; error in loading a saved game
  PUSH HL                 ;
  DI                      ; Disable interrupts
  CALL L7C00              ; 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 L8BAA - choices are from
;   the first menu screen (L8BC2)
  LD A,E                  ; Store player game control type selected from the
  LD (LBF18),A            ; menu (L8BC2)
  LD A,D                  ; Retrieve and re-store store game flag (0 = New
  LD ($BF19),A            ; Game, 1 = Existing game)
  CP $00                  ; Skip over next routine (to LBF60) if it's a new
  JR Z,LBF60              ; 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 LEAA1 and ECA1
LBF33:
  LD IX,LEA34_6           ; Start of data block
  LD HL,$ECA1             ; Address for end of block
  LD DE,LEA34_6           ; Start of block, game data at LEAA1
  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,$FF                ; Indicates a data block to load (rather than header)
  SCF                     ; Sets the carry flag, which tells the ROM routine to
                          ; perform a LOAD
  CALL $0556              ; Call the LD-BYTES ROM subroutine to load saved game
                          ; data
; Second data block - all game data between L6790 and 8033
  LD IX,($DAF5)           ; Start of data block
  LD HL,($EB61)           ; Address for end of block
  LD DE,($DAF5)           ; Start of block, game data at L6790
  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,$FF                ; Indicates a data block to load (rather than header)
  SCF                     ; Sets the carry flag, which tells the ROM routine to
                          ; perform a LOAD
  CALL $0556              ; Call the LD-BYTES ROM subroutine to load saved game
                          ; data

; Start game
;
; Used by the routine at LBF1A.
LBF60:
  LD HL,($5C3D)           ; Replace ERRSP stack pointer with the address LC763
  LD SP,HL                ; (start of pause game routine)
  POP HL                  ;
  LD HL,LC763             ;
  PUSH HL                 ;
; Identify the control method (1-4) that was selected on the first game menu
; (L8BC2).
;
; Sets the HL register pair to point to the address containing the input values
; to check for that control method.
  LD A,(LBF18)            ; Game control choice (1-4)
  CP $01                  ;
  JR NZ,LBF60_0           ;
  LD HL,$EB08             ; Kempston joystick selected
  JR LBF60_3              ;
LBF60_0:
  CP $02                  ; AGF/cursor joystick selected
  JR NZ,LBF60_1           ;
  LD HL,$EB1E             ;
  JR LBF60_3              ;
LBF60_1:
  CP $03                  ;
  JR NZ,LBF60_2           ;
  LD HL,$EB33             ; Sinclair joystick selected
  JR LBF60_3              ;
LBF60_2:
  LD HL,$EB0E             ; Keyboard selected
; Store the address holding the set of control input values.
LBF60_3:
  LD (LEB06),HL
; ...and check if we need to set up a new game or not:
  LD A,($BF19)            ; Is it a new game, or has a saved game been loaded?
  CP $00                  ;
  JR Z,LBF9D              ; New game - jump to game setup
  LD A,($EAB7)            ; Game loaded. Copy room number into buffer.
  LD ($EAB0),A            ;
  JP LD94C                ; 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 LBF60.
;
; This section initializes a bunch of new game data - copying bytes/addresses
; into the 'current game' state.
LBF9D:
  LD HL,L7172             ; Reset/store the address pointer to the start level
  LD (LEB5B),HL           ; text (Gatehouse Level)
  LD HL,L6C7C             ; Address pointer to warlock and creature stat tables
  LD ($EBC3),HL           ;
  LD HL,L6CDC             ; Address pointer to missile data tables
  LD (LEBC1),HL           ;
  LD HL,L6DFC             ; Reset/store the pointer to the start of spell list
  LD ($EB65),HL           ; text (1st spell = MOVE)
  LD HL,L6FBC             ; Reset/store the pointer to the start of spell name
  LD ($EB67),HL           ; texts -1
  LD HL,$6FBD             ; Reset/store the pointer to the start of spell text
  LD ($EB63),HL           ; messages ('Project thy soul' etc)
  LD A,$1B                ; 27 = total number of spells (for spell list at
  LD ($EB69),A            ; L6DFC)
  LD HL,L97C3             ; Reset/store the pointer to the start of an address
  LD ($EB6A),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,(LDAEE)           ; Address pointer to room item/object/scenery data
                          ; sets at 7C00
  LD DE,$0300             ; 768 bytes reserved for this
  ADD HL,DE               ;
  LD (HL),$FF             ;
; FOREGROUND SCENERY DATA SETS FOR CURRENT ROOM
  INC HL
  LD ($EB70),HL           ; Address pointer to foreground scenery data sets at
                          ; 7F01
  LD DE,$0070             ; 112 bytes reserved for these
  ADD HL,DE               ;
  LD (HL),$FF             ;
; MAROC'S INVENTORY - UP TO 4 OBJECTS
  INC HL
  LD (LEBBA),HL           ; Maroc's inventory ('pockets') - 64 bytes (4 object
  LD B,$04                ; spaces x 16 bytes) at 7F72
  LD DE,$0010             ;
LBF9D_0:
  LD (HL),$00             ; Reset first byte of each inventory slots (0 =
  ADD HL,DE               ; nothing carried)
  DJNZ LBF9D_0            ;
  LD (HL),$FF             ;
; COLLISION/EVENT CHECKS FOR ELEMENTS IN THE CURRENT ROOM
  INC HL
  LD ($EB6C),HL           ; Address pointer to elements/objects/events going on
                          ; in current room at 7FB3
  LD (HL),$FF             ; 255 = no more events/collisions to check
  LD DE,$0080             ; 128 bytes reserved for these
  ADD HL,DE               ;
; UNUSED DATA AREA
  LD ($EB5F),HL           ; Skip over 32 bytes at 8033 (this data is unused)
  LD DE,$0020             ;
  ADD HL,DE               ;
; FLIPPED/MIRRORED GRAPHICS
  LD ($EB61),HL           ; Address pointer to flipped graphics store at 8053
; MAROC'S INVENTORY SLOTS
  LD HL,(LEBBA)           ; Address pointer to start of Maroc's inventory
                          ; (7F72)
  LD ($EBBC),HL           ; Copy to current inventory address pointer
  LD DE,$0010             ; Advance 16 bytes to start of next inventory item
  ADD HL,DE               ; address pointer
  LD ($EBBE),HL           ; And store (32642) in current game data
; Prepare graphics for Maroc's sprite
  LD A,$01
  LD ($EB50),A            ; Graphics & frame offset (1 = no graphic address
                          ; offset, start at frame #1) - sprite graphics
                          ; pointer starts at L97C3
  CALL LE0C2              ; Set up graphics
  LD HL,($EB51)           ; Store Maroc's calculated sprite graphic address
  LD ($EAC2),HL           ; pointer
  LD A,$7C                ; 'Dummy' graphic address (AD9C) - used where nothing
  CALL LE0C2              ; needs to be drawn/printed
  LD HL,($EB51)           ; Store calculated graphic address pointer
  LD ($EAF3),HL           ;
  LD A,$7B                ; Set up graphics for Maroc's shadow (at AD88)
  CALL LE0C2              ;
  LD HL,($EB51)           ; Get Maroc's shadow's calculated sprite graphic
                          ; address pointer
  LD ($EAC4),HL           ; ...and copy to game data store
  LD A,$69                ; Set up flickering barrier graphics (A9EC) used for
  CALL LE0C2              ; spells such as SHIELD, PROTECT and DEFENCE
  LD HL,($EB51)           ; Get the address pointer to these graphics
  LD ($EC96),HL           ; ...and copy to the current game data store

; Run new game intro sequence
;
LC03F:
  CALL LDEF9              ; Clear the scroll status panel at the bottom of the
                          ; screen
; Draw Maroc sprite graphic
  LD A,$50                ; Set vertical pixel position (from top of playing
                          ; area)
; Sprite drawing loop starts here (return from C09F) - continued until Maroc
; passes the bottom of the playing area
LC03F_0:
  LD ($EAD2),A
  LD A,$78                ; Horizontal pixel position
  LD ($EAD3),A            ;
  LD A,$01                ; Set graphics draw/erase flag to 1 (DRAW)
  LD ($EACF),A            ;
  LD HL,($EAC2)           ; Set graphics display address pointer to Maroc's
                          ; sprite (L97C3)
  CALL LDB98              ; Draw Maroc
; Print intro sequence/game start text on scroll (731F)
  LD A,$24                ; Intro sequence/game start message is message number
                          ; #36 (at 731F)
  CALL LE5A5              ; Identify the address location for this text message
                          ; number
  LD (LEAA1),HL           ; ...and store
  LD HL,$5048             ; Set screen display address to top left of the
                          ; scroll's text area
  LD ($EAA4),HL           ; ...and store
  CALL LE2D0              ; Call text printing routine
; Erase Maroc sprite graphic
  LD A,$00                ; Set graphics draw/erase flag to 1 (ERASE)
  LD ($EACF),A            ; ...and store
  LD HL,($EAC2)           ; Retrieve graphics address pointer
  CALL LDB98              ; Erase graphic
; Lightning flashes are triggered every 16 pixels that Maroc's sprite moves
; down the screen.
  LD A,($EAD2)            ; Get vertical (Y) pixel co-ordinate
  AND $0F                 ; Check the last 4 bits (0-15) to see if value = 0
  JR NZ,LC099             ; 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
LC07A:
  LD A,$06                ; There are 6 lightning flashes between Maroc's
LC07A_0:
  LD ($EACF),A            ; sprite movement segments
  CALL LE610              ; Toggle sky colour between blue and yellow colour
  LD A,$80                ; Length/frequency of sound effect
  LD ($EB56),A            ; Store length/frequency counter
LC07A_1:
  LD ($EAC7),A            ; Also store as sound effect repeat counter
  CALL LE1D7              ; Play sound effect
  LD A,($EAC7)            ;
  DEC A                   ; Inner loop - decrement counter and repeat sound
  JR NZ,LC07A_1           ; effect (128 iterations)
  LD A,($EACF)            ; Outer loop - decrement counter and repeat lightning
  DEC A                   ; effect (6 flashes)
  JR NZ,LC07A_0           ; Repeat 6 times

; Intro sequence - move Maroc's sprite down one pixel
;
; Used by the routine at LC03F.
;
; Move Maroc's sprite down 1 pixel and check if he's got to the bottom of his
; descent.
;
; The check at C09D 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.
LC099:
  LD A,($EAD2)            ; Get sprite Y co-ordinate
  INC A                   ; Increase by one
  CP $98                  ; Is the sprite past the bottom of the playing area
                          ; (character row 18)
  JR C,LC03F_0            ; If not, go back and re-draw the sprite
  JR LC0C1                ; 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 LDA4D.
;
LC0A3:
  LD A,(LEAE1)            ; Check if any spell was active before Maroc ran out
                          ; of energy
  CP $10                  ; Any value above 16 means there's some sort of spell
  JR C,LC0A3_0            ; in effect, and there's a flashing icon in the top
                          ; right of the scroll.
  CALL LEA34_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)
LC0A3_0:
  LD L,$F8                ; Low byte of screen display address
  LD A,$08                ; 8 character squares to clear
LC0A3_1:
  LD B,$08                ; 8 pixel lines to clear in each square
  LD H,$50                ; High byte of screen display address
LC0A3_2:
  LD (HL),$00             ; Clear byte on screen
  INC H                   ; Move down one pixel
  DJNZ LC0A3_2            ; Repeat for 8 pixel lines
  INC L                   ; Move right one character square
  DEC A                   ;
  JR NZ,LC0A3_1           ; ..and repeat for 8 character squares
  CALL LE4E7              ; Calculate Maroc's rank and print it on screen

; Place/replace Maroc in the start room
;
; Used by the routine at LC099.
;
; 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
LC0C1:
  LD A,$01                ; Set flag indicating which music data to point to (1
                          ; = main theme music). The music data is stored at
                          ; LEBF0.
  CALL LE5B6              ; Play music
; RESET GAME DATA
  LD A,$FF
  LD ($EBB4),A            ; Decrementing timer before a warlock might appear in
                          ; Maroc's room
  LD ($EBB5),A            ; Decrementing timer before a creature might wander
  LD A,$80                ; into the room from an adjacent one
  LD ($EAE0),A            ; Maroc's energy - maximum is 255 but he starts with
  LD A,$00                ; half a full energy bar
  LD ($EC9C),A            ; FREEZE spell timer (0 = FREEZE spell not active)
  LD ($ECA1),A            ; Maroc's height offset (his movement speed affects
                          ; his height above his shadow)
  LD (LEAE1),A            ; Spell selection byte - start in spell menu, with no
                          ; spell selected
  LD ($EAEC),A            ; Temp store for spell number pointer. Only the MOVE
                          ; spell is available at the start of the game
  LD ($EBD5),A            ; Energy drain/heal amount for ongoing effect spells,
                          ; e.g. SHIELD (drain) or CHALICE (heal)
  LD ($EAE9),A            ; Currently active 'effect' spell (e.g. UNSEEN,
                          ; SHIELD)
  LD ($EAE2),A            ; Store for spell counter used in checking spells
                          ; collected at LE699_2
  LD A,$4A                ; Maroc's vertical (Y-axis) screen position, in
  LD ($EAC1),A            ; pixels, from top of play area just below border
  LD A,$47                ; Maroc's default colour attributes (71 = INK 7,
  LD (LEAA7),A            ; PAPER 0, BRIGHT 1)
  LD A,$40                ; Maroc's vertical pixel starting position in the
  LD (LEB74),A            ; room
  LD A,$01                ;
  LD ($EAB4),A            ; The connecting door set number in the table at
                          ; L6790 (set 1)
  LD ($EAB7),A            ; Room number = 1
  LD HL,($EB65)           ; Memory address pointer for spell list data at L6DFC
  LD ($EAE3),HL           ; Copy to spell name pointer buffer

; Reset various room-based game data ready for a new room
;
; Used by the routine at LDA0A.
;
; The jump here from DA4A 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.
LC107:
  LD HL,$0000
  LD ($EAF6),HL           ; Reset vertical room position (pixel) to zero
  LD ($EAF8),HL           ; Reset horizontal room position
  LD A,$00                ; (4-pixel/half-character steps) to zero
  LD ($EAF2),A            ; Flag indicating if a warlock/demon has appeared in
                          ; the room
  LD ($EBB1),A            ; Servant object-carrying-status byte (0 = no object
                          ; carried)
  LD ($EAB0),A            ; Reset room number (buffer byte) - indicates all
                          ; items in previous room now dealt with
  LD (LEB91),A            ; Reset number of creature-launched missiles in the
                          ; current room
  LD ($EB93),A            ; Reset missile number (in table at L6CDC)
  LD ($EB92),A            ; Number of missiles fired by Maroc = 0
  LD ($EC98),A            ; Number of Maroc's active missiles (buffer byte) = 0
  LD (LEBAD),A            ; Warlock's 'aggression' byte (byte 6 of warlock's
                          ; data at L6C7C) = 0 (as there's no warlock)
  LD ($EB04),A            ; Maroc's horizontal movement speed (0 = not moving)
  LD ($EB05),A            ; Maroc's vertical movement speed (0 = not moving)
  LD (LEAAA),A            ; Game cycle/creature pursue counter = 0
  LD ($EAAB),A            ; Maroc's sprite's horizontal facing direction, set
                          ; when Maroc enters a new room
  LD ($EAAC),A            ; Maroc's sprite's vertical facing direction, set
                          ; when Maroc enters a new room
  LD HL,($EB6C)           ; Pointer to room item event data sets at 7FB3
  LD (HL),$FF             ; Set end-of-data byte at start of this data as no
  LD ($EAAD),HL           ; room event/collision checks have been identified
                          ; yet
  LD HL,($EB5F)           ; Pointer to data set before flipped graphic data at
                          ; 8033
  LD (LEAEF),HL           ; Copy into game data store (this data is unused)
  LD (HL),$FF             ; Set end-of-data byte at start of this data set
  LD HL,($EB61)           ; Address pointer to end of this data set (8033)
  LD ($EB5D),HL           ; Copy into game data store
  LD A,$01                ; Graphics frame offset (n-1) for frames/mirrored
  LD ($EB50),A            ; graphics ( = 0 = no frame offset)
  LD HL,(LDAEE)           ; Pointer to start of room item data sets at 7C00.
  LD ($EABE),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 L61A9:
LC15A:
  LD HL,($DAF7)           ; Pointer to series of room data sets at L61A9.
  LD A,($EAB7)            ; Get room number
  LD C,A                  ; Store in C register
  LD B,$01                ; Set incremental compare counter to compare room
                          ; number against
; Identify data set for current room from list at L61A9
LC15A_0:
  LD A,C
  CP B
  JR Z,LC15A_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)
LC15A_1:
  LD A,(HL)               ; Get byte of room data set
  INC HL                  ; Increment it
  CP $FF                  ; Are we at an end-of-data-set marker?
  JR NZ,LC15A_1           ; Continue till we are
  INC B                   ; We're at the end of this set. Increment the counter
  JR LC15A_0              ; Keep comparing until we're at the right place for
                          ; the room
; Data set for current room identified
LC15A_2:
  LD ($EB7A),HL           ; Store address pointer for current room data bank.
; Check if the room is a vertical tunnel
  CP $E0                  ; Tunnel rooms are room number 224 and above
  JP NC,LC5B5             ; 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
;   LC265 and LC2F8 for graphic examples
; * In the address table at L97C3, advancing 12 addresses (=24 bytes) forward
;   from a 'brick' level scenery graphic gives you the 'cavern' level
; * For example, 97E5 and 97FD are the graphic addresses for the vertical wall
;   section.
  CP $53                  ; Rooms 1-82 are 'brick' style levels (e.g. Gatehouse
                          ; Level). Is the room number less than 83?
  LD A,$00                ; ...If so, graphic address pointer offset is zero
  JR C,LC15A_3
  LD A,$0C                ; If room number is 83 or above (e.g. Mines of
                          ; Madness), graphic address offset is 12
LC15A_3:
  LD ($EB77),A            ; Store level type graphic address offset
; The next set of instructions reset the room position:
  LD HL,$0000
  LD ($EB4C),HL           ; Set horizontal (EB4C) & vertical (EB4D) movement
                          ; speed to zero
  LD ($EB47),HL           ; Set horizontal room position to zero
  LD ($EB49),HL           ; Set vertical room position to zero
  LD A,$40                ;
  LD ($EB4B),A            ; This byte is set to 64 for 'standard' rooms,
  LD A,$20                ; 254/255 for tunnels (byte 9 of data set at 7C00)
  LD (LEB43),A            ; Room item type = room (general). This is the first
                          ; data set stored in the room data sets at 7C00 and
                          ; indicates the base room position/attributes
  LD A,$02                ; Item properties byte. Because this is just the
  LD ($EB4E),A            ; general room/viewport position & data, can just set
                          ; bit 1 (2) = hidden (nothing to draw)
  CALL LE0B0              ; Copy the 16 bytes of room data from working buffer
                          ; at LEB43 to the first of the room item data sets at
                          ; 7C00
  LD A,$05                ; Resets the item properties ready for the next room
  LD ($EB4E),A            ; item. Default setting sets bits 0 (visible
                          ; on-screen) and 2 (needs to be erased before
                          ; re-drawing)
  LD A,$50                ; Starting value for the room's vertical position
  LD ($EB79),A            ; (viewport), in pixels, from top of room area (room
                          ; alignment)
  LD A,$04                ; Starting value for the room's horizontal position
  LD ($EB78),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,($EB7A)           ; Get address pointer for the room data set in the
                          ; table at L61A9
  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 ($EB7A),HL           ; ...and re-store the pointer.
  LD ($EB7C),A            ; Store the first byte, which indicates room size
  LD A,$01                ;
  LD ($EB7D),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 LC1E0.

; 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 LC2F8
LC1C0:
  LD A,$06                ; Graphic type = 6 (corner wall section)
  LD (LEB43),A            ;
  LD A,$30                ; Vertical position (in pixels) from top of room
  LD ($EB4A),A            ; space
  LD A,$10                ; Horizontal position (in 4-pixel/half-character
  LD ($EB48),A            ; steps) from left of room space
  LD A,$02                ;
  LD ($EB50),A            ; Graphic number offset for scenery graphic address
                          ; (n-1)*2 = 2 The standard corner section is the
                          ; right-hand one (9E0E). 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,$12                ; Graphic number offset for corner wall section in
                          ; graphic address table at L97C3; (n-1)*2 = 34 = 97E5
  LD A,($EB77)            ; 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 97E5 or 97FD.
  CALL LE0C2              ; Prep graphic address pointers at pointer table at
                          ; L97C3, including mirrored graphics of the sections
  CALL LE0B0              ; Copy the data for these graphics from its buffer at
                          ; LEB43 into a room item data set at 7C00

; Set up room background scenery - part 1
;
; Used by the routine at LC2C2.
;
; 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.
LC1E0:
  LD A,($EB7D)            ; Room setup counter (to be compared with room size
                          ; data byte at LC2C2)
  DEC A                   ; The counter was pre-incremented in the earlier
  AND $03                 ; routine, so check its original value
  CP $00                  ;
  JR NZ,LC1E0_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 L61A9). 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 L61A9 and advance room data address pointer, as we've
; dealt with the current byte
  LD HL,($EB7A)           ; Get room data address pointer
  LD A,(HL)               ; Get next room data byte
  INC HL                  ; Increment address pointer to next byte
  LD ($EB7A),HL           ; ...and re-store address pointer
  LD ($EB7E),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 EB7F) to 0, 1 or 2 respectively.
;
; The incremental counter (EB7D) 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.
LC1E0_0:
  LD A,($EB7D)            ; Incremental counter, which is checked against with
                          ; 1st byte from the room data set (in the table at
                          ; L61A9) which indicates the room size
  CP $03
  JR NC,LC1E0_1
  LD A,$02                ; If the counter byte is < 3, we're looking at LEFT
  JR LC20F                ; wall items - set A to 2, for storing at EB7F
                          ; shortly
LC1E0_1:
  LD C,A                  ; If the counter byte is >=3 it could be the back or
                          ; right wall
  LD A,($EB7C)            ; ...Subtract it from the room data byte
  SUB C                   ;
  CP $02                  ;
  JR NC,LC1E0_2           ;
  LD A,$01                ; If it's 0 or 1, the counter byte is on one of its
  JR LC20F                ; last two values, so we're looking at the RIGHT wall
                          ; - Set A to 1, for storing at EB7F shortly
LC1E0_2:
  LD A,$00                ; 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 EB7F shortly

; Set up room background scenery - part 2
;
; Used by the routine at LC1E0.
;
; A Byte calculated in the previous routine at LC1E0_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 EB7D 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
; L61A9.
;
; See Trivia: Setting the scene(ry) for an explanation of how this routine
; evaluates the DOORS and BRICKWORK from the room data set.
LC20F:
  LD ($EB7F),A            ; Store the above byte (in the A register calculated
                          ; in the previous routine at LC1E0_0)
  LD A,($EB7E)            ; Get the current room data byte (from the current
                          ; room data banks at L61A9)
  RLA                     ; Shift bits (6 & 7) left x 2
  RL C                    ; ...Shifting them into bits 0 & 1 of the C register
  RLA                     ;
  RL C                    ;
  LD ($EB7E),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 $03                 ; So filter any others out
  LD C,A                  ;
  AND $01                 ; Check bit 0. If set, this indicates that there's a
                          ; DOOR here.
  JR Z,LC265              ; ...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,($EB79)            ; Item's vertical position within current room, in
                          ; pixels, from top of room area.
  LD ($EB4A),A            ; ...Copy byte into store
  LD A,($EB78)            ; Horizontal position within current room, in
                          ; half-character (4 pixel) steps.
  LD ($EB48),A            ; ...Copy byte into store
  LD A,($EB7F)            ; 0 = back wall, 1 = right wall, 2 = left wall
  LD ($EB46),A            ; ...Copy byte into store
  LD A,$02                ; Graphic type = 2 (Door)
  LD (LEB43),A            ;
  CALL LE0B0              ; Copy the 16 bytes in the item's working data buffer
                          ; at LEB43 into a room item data set at 7C00.
; DOOR FRAMES - set up/mirror graphics
;
; Each door has a door frame, which is a separate graphic to be handled
  LD A,$01                ; Graphics type = 1 (fixed room scenery item, in this
  LD (LEB43),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,$14                ; Redundant instruction as C value (offset) is set
                          ; either at C24E (20) or LC20F_0 (21)
  LD A,($EB7F)            ; 0 = Back wall door, 1 = Right wall door or 2 = Left
  CP $00                  ; wall door
  JR NZ,LC20F_0           ;
  LD C,$14                ; Back wall - Graphics offset = (20-1)*2 + 38851 =
                          ; 97E9 (Door frame - back wall)
  LD A,$01                ; Frame offset (= no offset needed)
  JR LC20F_1              ;
LC20F_0:
  LD C,$15                ; Side wall - Graphics offset = (21-1)*2 + 38851 =
                          ; 97EB (Door frame - side wall)
; Set up and mirror graphics for door frame
LC20F_1:
  LD ($EB50),A            ; Store calculated frame offset
  LD A,($EB77)            ; Get level style offset (for to graphic pointers at
                          ; L97C3). 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 LE0C2              ; Call setup graphics routine (copy graphics address
                          ; pointers), mirror any relevant graphic data
  CALL LE0B0              ; Copy the 16 bytes of calculated graphics data from
                          ; the working buffer at LEB43 into one of the the
                          ; room item data sets at 7C00.
  JR LC2C2

; Check for and set up back wall brickwork/rock scenery
;
; Used by the routine at LC20F.
;
; 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 (L9EE8) or 'cavern' levels (LA035)
;
; First, check if bit 1 is set - if so, there's brickwork at this position:
LC265:
  LD A,C
  AND $02                 ; Check bit 1. If it's set, there's BRICKWORK to set
                          ; up at this room position.
  JR Z,LC290              ; 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,$01                ; Graphics type = 1 (fixed scenery item)
  LD (LEB43),A            ;
  LD A,($EB78)            ; Horizontal room position of item (in
  LD ($EB48),A            ; half-character/4-pixel increments). Copy into data
                          ; buffer ready to be transferred into a room item
                          ; data set (at 7C00)
  RRA                     ; Use this byte by shifting into the lowest 3 bits...
  RRA                     ;
  RRA                     ;
  AND $03                 ; ...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 ($EB50),A            ; Store as graphics pointer offset
  LD A,L                  ; Use bits 0-4 of the low byte (L) of the HL register
  AND $1F                 ; pair to set variable heights for the decoration. At
  LD ($EB4A),A            ; the start of this routine, HL is typically at the
                          ; start of one of the data bank sets at 7C00, 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 L61A9, so the height
                          ; of the brickwork can be be quite varied.
  LD C,$17                ; Offset for brickwork graphics at L97C3, pointing to
                          ; 97EF
  LD A,($EB77)            ; Add graphic offset if Maroc is on a 'cavern' level,
  ADD A,C                 ; to use the second set of rock graphics (9807)
                          ; instead of the the bricks
  CALL LE0C2              ; Call setup graphics routine (copy graphics address
                          ; pointers and mirror any relevant graphic data)
  CALL LE0B0              ; Copy the 16 bytes of graphic data for the brickwork
                          ; scenery from the data buffer at LEB43 to one of the
                          ; room data sets at 7C00.

; Set up room floor-wall connector graphics
;
; Used by the routine at LC265.
LC290:
  LD A,$01                ; Graphics type = 1 (fixed scenery item)
  LD (LEB43),A            ;
  LD A,$11                ; Graphic number - address pointer offset for graphic
  LD ($EB50),A            ; address table at L97C3 - unnecessary because it'll
                          ; be overwritten in a few more instructions at
                          ; LC290_1
  LD A,($EB78)            ; Room graphic item's horizontal position within
  LD ($EB48),A            ; current room, in half-character (4 pixel) steps.
                          ; Copy into data buffer.
  LD A,($EB79)            ; Room graphic item's vertical position within
  LD ($EB4A),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 EB7F 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,($EB7F)
  CP $00                  ; Back wall - offset for graphics address 97DF, back
  JR Z,LC290_0            ; wall floor section (see L9DC8)
  LD C,$10                ; Right/left wall - offset for:
  JR LC290_1              ; * address pointer = 97E1, right wall side/wall
LC290_0:
  LD C,$0F                ;   floor section (see 9DE7), or
  LD A,$01                ; * address pointer = 97E3, left wall (mirrored) side
LC290_1:
  LD ($EB50),A            ;   wall/floor section (see 8053)
; Calculate graphics offset based on level offset and the above
  LD A,($EB77)            ; 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 LE0C2              ; Set up graphics (copy graphics address pointers and
                          ; mirror any graphic data)
  CALL LE0B0              ; Copy the item data from the working buffer LEB43
                          ; into a 16 byte room item data set at 7C00.

; Calculate horizontal/vertical room co-ordinates for each room
; section/components
;
; Used by the routine at LC20F.
;
; The byte at EB7D acts as an incrementing counter which is compared with room
; size (first byte in the room data sets at L61A9). 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.
LC2C2:
  LD A,($EB7D)            ; Get counter byte, starting at 1
  INC A                   ; Increment and then re-store
  LD ($EB7D),A            ;
  LD C,A
  LD A,($EB7C)            ; First room data byte from room data set at L61A9 -
                          ; indicates room size
  SUB C                   ; Subtract (check against) the counter
  JR C,LC2F8              ; If counter is greater than the room data byte, the
                          ; side and back wall joints have been calculated.
                          ; Skip to LC2F8 to deal with the corner/vertical wall
                          ; connectors
  CP $02                  ; Check which section we're dealing with
  JR NC,LC2C2_0           ;
; Room-size-minus-counter = 1 or 0. This means we're dealing with the RIGHT
; side of the room.
  LD A,($EB79)            ; Increase vertical (Y) position by 16 pixels
  ADD A,$10               ; Each side wall part is 16 pixels tall (e.g. the
                          ; right side wall section, so add 16 pixels from the
                          ; current position
  LD ($EB79),A            ; Store adjusted vertical graphic position
  JR LC2C2_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.
LC2C2_0:
  LD A,($EB7D)            ; Get the counter byte
  CP $04                  ; >=4?
  JR NC,LC2C2_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,($EB79)            ; Vertical (Y) position
  SUB $10                 ; 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 ($EB79),A            ; ...and re-store
; Wall/floor sections (e.g. the connectors at L9DC8) are 4 characters (32
; pixels) wide.
;
; Calculate the horizontal (X) position - this is easy as every room section is
; 32 pixels wide.
LC2C2_1:
  LD A,($EB78)
  ADD A,$08               ; Increase horizontal position by 8 half-character
  LD ($EB78),A            ; squares (32 pixels)
  JP LC1E0                ; Return to the next item to set up

; Set up RIGHT vertical wall/floor connector graphics
;
; Used by the routine at LC2C2.
;
; The left wall/floor connector has been set up already at LC1C0
LC2F8:
  LD A,$07                ; Graphic type = 7 (RIGHT corner wall section)
  LD (LEB43),A            ;
  LD A,$30                ; Graphic vertical position within current room, in
  LD ($EB4A),A            ; pixels, from top of room playing area (fixed value
                          ; for all rooms).
  LD A,$05                ; Item properties byte. Default = 5 - bit 0 set means
  LD ($EB4E),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 L61A9) indicates the room size,
; and is used to calculate the horizontal position of the right corner section.
  LD A,($EB7C)            ; Get the 1st data byte for the room (at L61A9)
  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 $F8                 ; Filter off any carry bits (it will be a multiple of
                          ; 8 so we don't need bits 0-2)
  LD ($EB48),A            ; ...and store.
  LD A,$01                ; Graphics frame offset (= no offset)
  LD ($EB50),A            ;
  LD C,$12                ; Graphic number in graphics address pointer table at
                          ; L97C3, this offset points to graphic address 97E5
  LD A,($EB77)            ; Level type graphics pointer offset (for 0 for
                          ; 'brick' levels, 12 for 'cavern levels')
  ADD A,C                 ; Add to graphic address pointer offset
  CALL LE0C2              ; Set up graphics
  CALL LE0B0              ; Copy the 16 bytes of calculated data from LEB43 to
                          ; a bank in the room item data sets at 7C00
  LD HL,($EABE)           ; Retrieve address pointer after the above 16 bytes
                          ; have been copied
  LD (HL),$FF             ; Set the first byte of the next data bank to 255
                          ; (end-of-data)
  LD HL,(LDAEE)           ; Retrieve address pointer to the room item data sets
                          ; at 7C00

; Check room item data sets to see if any doors need setting up
;
; Used by the routine at LC349.
;
; HL Address pointer to room data sets containing the room's scenery items
;    (7C00)
;
; Check through data sets at 7C00 to see if any doors (item type number = 2)
; need setting up
;
; Get one of the 16-byte room item data sets (at 7C00) and copy it across to a
; working data buffer at LEB43:
LC32D:
  LD DE,LEB43             ; Working buffer address pointer
  LD B,$10                ; 16 bytes to copy over
  LD ($EABE),HL           ; Store address pointer to item data set (at 7C00)
LC32D_0:
  LD A,(HL)               ; Copy byte across
  LD (DE),A               ;
  INC DE                  ;
  INC HL                  ;
  DJNZ LC32D_0            ; Repeat for 16 bytes
; Check if the data set is door data
  LD A,(LEB43)            ; First byte of the data bank indicates the type of
  CP $FF                  ; graphic
  JP Z,LC42A              ; If it's 255 it means no more data to deal with
  CP $02                  ; Is this data for a door (item type = 2)?
  JR Z,LC349              ;
  JR LC32D                ; If not, check the next set

; New room - door setup
;
; Used by the routine at LC32D.
;
; 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
LC349:
  LD HL,($EB7A)           ; Pointer to the current data byte for the room (from
                          ; the room data set at L61A9)
  LD A,(HL)               ; Get byte from room data
  INC HL                  ; Increment pointer
  LD ($EB7A),HL           ; ...and re-store
  LD C,A                  ; Temp store of connecting door set number (L6790) in
                          ; C register
  LD A,($EB46)            ; Flag indicating where this door appears in the
                          ; room: 0 = Back wall door 1 = Right wall door 2 =
                          ; Left wall door
  LD ($EB7F),A            ; Copy this byte to working data buffer
  LD A,C                  ; Retrieve connecting door set number
  LD ($EB46),A            ; ...and store (replace) in room element data buffer
  LD A,($EAB4)            ; 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,LC349_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,($EB48)            ; Horizontal position of door within current room, in
                          ; half character (4 pixel) steps.
  LD ($EB75),A            ; Copy to Maroc's horizontal room entry position
                          ; store
  LD A,($EB4A)            ; Vertical position within current room, in pixels,
                          ; from top of room playing area
  SUB $0C                 ; 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 ($EB76),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 EB7F is used
; for this check:
; * 0 = Back wall door - set EAAC (vertical direction) to 254 (down)
; * 1 = Right wall door - set EAAB (horizontal direction) to 2 (left)
; * 2 = Left wall door -  set EAAB (horizontal direction) to 254 (right)
  LD A,($EB7F)
  CP $00
  JR Z,LC349_1
  CP $01
  JR Z,LC349_0
  LD A,$FE
  LD ($EAAB),A            ; Maroc is entering the room through a door on the
  JR LC349_2              ; left wall
LC349_0:
  LD A,$02                ;
  LD ($EAAB),A            ; Maroc is entering the room through a door on the
  JR LC349_2              ; right wall
LC349_1:
  LD A,$FE                ;
  LD ($EAAC),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 L6790),
; using the set number x 4 (as each set contains 4 bytes)
LC349_2:
  LD HL,($DAF5)           ; Address pointer to the start of the connecting door
                          ; sets - L6790
  LD A,C                  ; Retrieve the connecting door data set number
  LD D,$00                ; 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 $FC                 ; 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 L6790
  LD ($EB44),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 $05                  ; Set bits 0 (item visible on-screen) and 2 (item
                          ; will need erasing before re-drawing)
  AND $FD                 ; Filter out bit 1 (2) - (assume door is not hidden)
  LD ($EB4E),A            ; ...and re-store
; The byte at EB7F 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 97D3
; * 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 LCAB4) 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 LCAB4)                                                        |
; +----------+------------------------------------------------------------------------------------------------------------------------------------------------+
  LD C,A                  ; Store filtered byte in C register
  LD D,$11                ; Default frame offset value
  LD E,$05                ; 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,$00                ; Height position offset of door (in pixels)
  LD A,($EB7F)            ; 0 = Back wall door 1 = Right wall door 2 = Left
                          ; wall door
  CP $01
  JR Z,LC349_3
  CP $00
  JR Z,LC349_4
; Door on LEFT wall - set graphic address offset and door position offset
  LD B,$02                ; Horizontal position offset (in
                          ; half-characters/4-pixel increments)
  LD L,$F6                ; Height pixel position offset of door (-10)
  LD H,$05                ; Door 5 - closed door on left wall. Mirrored version
  LD D,$F5                ; of Door 2.
  LD A,C                  ; Check bit 3 (open/closed)
  AND $08                 ;
  JR Z,LC349_5            ;
  LD D,$11                ;
  LD H,$01                ; Door 1 - open door on left wall.
  JR LC349_5              ;
; Door on RIGHT wall - set graphic address offset and door position offset
LC349_3:
  LD B,$FE                ; Horizontal position offset (in
                          ; half-characters/4-pixel increments)
  LD L,$F6                ; Height pixel position offset of door (-10)
  LD H,$02                ; Door 2 - closed door on right wall.
  LD A,C                  ; Check bit 3 (open/closed)
  AND $08                 ;
  JR Z,LC349_5            ;
  LD D,$F5                ;
  LD H,$06                ; Door 6 - open door on right wall. Mirrored version
  JR LC349_5              ; of Door 1.
; Door on BACK wall - set graphic address offset and door position offset
LC349_4:
  LD B,$FD                ; Horizontal position offset (in
                          ; half-characters/4-pixel increments)
  LD E,$04                ; Number of animation frames needed for door
                          ; opening/closing. Back wall doors have 4, side wall
                          ; doors 5.
  LD H,$04                ; Door 4 - open door on back wall. Mirrored version
  LD D,$F4                ; of Door 3.
  LD A,C                  ; Check bit 3 (open/closed)
  AND $08                 ;
  JR NZ,LC349_5           ;
  LD D,$11                ;
  LD H,$01                ; Door 1 - closed door on back wall.
; Store door graphic address and position offsets
LC349_5:
  LD A,($EB48)            ; Horizontal (X) position of door in room
                          ; (half-character/4 pixel increments)
  ADD A,B                 ; Add calculated horizontal offset
  LD ($EB48),A            ; ...and store
  LD A,($EB4A)            ; Vertical (Y) position of door in room (in pixels)
  ADD A,L                 ; Add calculated vertical offset
  LD ($EB4A),A            ; ...and store
  LD A,D                  ; Door frame byte for particular door - indicates
  LD ($EB80),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 ($EB81),A            ; wall doors have 4, side wall doors 5.
  LD A,H                  ; Offset for the calculated door graphic frame number
  LD ($EB50),A            ; (1-6)
  LD A,$09                ; Offset for base door graphics address (L97C3)
                          ; [offset = (17-1)*2]. Door graphic addresses start
                          ; from 97D3.
  CALL LE0C2              ; 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,($EB4F)            ; Get pre-graphics data byte
  AND $F0                 ; Filter out bits 0-3 (the default number of frames
  LD C,A                  ; in the byte)
  LD A,($EB81)            ; Add the number of animation frames needed for the
  OR C                    ; door
  LD ($EB4F),A            ; Re-store amended pre-graphics byte
  LD A,($EB80)            ; Copy graphic frame address offset into working data
  LD ($EB50),A            ; buffer
  CALL LE0B0              ; Copy the 16 bytes of door data from LEB43 into a
                          ; room item data set at 7C00.
  JP LC32D                ; Keep checking if there are any more doors to set up
                          ; in this room

; Identify room's interactable objects
;
; Used by the routine at LC32D.
;
; Run after setting up room's doors. Checks the room object table at L736F and
; copies any objects to the data sets at 7C00.
LC42A:
  LD A,$07                ; 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 ($EBB7),A            ; Store as a counter check
  LD HL,($DAF3)           ; Pointer to room item data tables at L736F
  LD A,$00                ; Reset (data set) counter for room object table
  LD ($EB84),A            ;
; Set up data for objects in room
LC42A_0:
  LD A,($EAB7)            ; Get room number
  LD B,A                  ; Used in B register in next CALL
  LD C,$00                ; C register used as room counter in next CALL
  CALL LDE4C              ; Check objects table for what's in the current room
  LD A,($EB84)            ;
  CP $FF                  ; If all objects are dealt with - skip next few
  JR Z,LC460              ; instructions
; Found an object to deal with in this room
  LD ($EB7A),HL           ; Store the room object table address pointer
  CALL LDEB7              ; Set up interactable object graphics and copy data
                          ; into a room item data set at 7C00
  LD HL,($EB44)           ; Retrieve address pointer to start of interactable
                          ; object's data set (at L736F)
  LD (HL),$00             ; Set the item's room number to 0, as Maroc is now in
                          ; the same room as the item
  LD A,($EBB7)            ; Get maximum object counter (max 7)...
  DEC A                   ; ...Decrement...
  LD ($EBB7),A            ; ...And re-store.
  JR Z,LC460              ; If we've reached the maximum number of objects in
                          ; this room, jump to next routine
  LD HL,($EB7A)           ; Otherwise, retrieve the room object table address
                          ; pointer
  JR LC42A_0              ; ...and continue checking for objects.

; Set up the room's creatures
;
; Used by the routine at LC42A.
;
; 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 L6B8C. 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 7C00.
LC460:
  LD A,$00                ; Set number of creatures in current room to 0
  LD ($EBB6),A            ;
  LD HL,($DAF0)           ; Address pointer for room creature data table at
                          ; L6B8C
  LD A,($EAB7)            ; 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,$00                ;
  ADD HL,DE               ; Add to base address at L6B8C 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 ($EBB7),A            ; ...and store
  AND %11000000           ; Top two bits (6 & 7) contain the count of any
                          ; guardians of chaos in the room
  JR Z,LC460_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 $03                 ;
LC460_0:
  LD ($EAF1),A            ; Store the current room's creature count for this
                          ; creature
  LD A,$08                ; Creature type = 8 (guardian of chaos)
  CALL LE16A              ; Set up this creature's data (room position &
                          ; graphics)
  CALL LE0B0              ; Copy the creature's data into one of the room item
                          ; data sets at 7C00
  LD A,($EAF1)            ; Retrieve the count of these creatures for the
                          ; current room
  DEC A                   ; ...and reduce by 1
  JR NZ,LC460_0           ; If count of this creature in the room is still > 0,
                          ; repeat for others
; Check for any GOBLIN WARRIORS in the current room
LC460_1:
  LD A,($EBB7)            ; 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,LC460_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 $03                 ;
LC460_2:
  LD ($EAF1),A            ; Store the current room's creature count for this
                          ; creature
  LD A,$09                ; Creature type = 9 (goblin warrior)
  CALL LE16A              ; Set up this creature's data (room position &
                          ; graphics)
  CALL LE0B0              ; Copy the creature's data into one of the room item
                          ; data sets at 7C00
  LD A,($EAF1)            ; Retrieve the count of these creatures for the
                          ; current room
  DEC A                   ; ...and reduce by 1
  JR NZ,LC460_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
LC460_3:
  LD A,($EBB7)            ; 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,LC460_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 $03                 ;
LC460_4:
  LD ($EAF1),A            ; Store the current room's creature count for this
                          ; creature
  LD A,$0A                ; Creature type = 10 (goblin missile thrower)
  CALL LE16A              ; Set up this creature's data (room position &
                          ; graphics)
  CALL LE0B0              ; Copy the creature's data into one of the room item
                          ; data sets at 7C00
  LD A,($EAF1)            ; Retrieve the count of these creatures for the
                          ; current room
  DEC A                   ; ...and reduce by 1
  JR NZ,LC460_4           ; If count of this creature in the room is still > 0,
                          ; repeat for others
; Check for any WRAITHS in the current room
LC460_5:
  LD A,($EBB7)            ; 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,LC460_7            ; If there aren't any, skip these setup instructions
; Set up WRAITHS in the current room
LC460_6:
  LD ($EAF1),A            ; Store the current room's creature count for this
                          ; creature
  LD A,$0B                ; Creature type = 11 (wraith)
  CALL LE16A              ; Set up this creature's data (room position &
                          ; graphics)
  CALL LE0B0              ; Copy the creature's data into one of the room item
                          ; data sets at 7C00
  LD A,($EAF1)            ; Retrieve the count of these creatures for the
                          ; current room
  DEC A                   ; ...and reduce by 1
  JR NZ,LC460_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:
; * EBB4 = Timer affecting how long before a warlock is likely to materialize
;   in the current room
; * EBB5 = 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
LC460_7:
  LD A,($EBB4)
  ADD A,$40               ; Add 64 to the warlock appearance timer
  JR C,LC460_8            ;
  LD ($EBB4),A            ;
LC460_8:
  LD A,($EBB5)            ;
  ADD A,$80               ; Add 128 to the wandering creature timer
  JR C,LC460_9            ;
  LD ($EBB5),A            ;
; Finish the creature data set:
LC460_9:
  LD HL,($EABE)           ; Address pointer to room item (creature) data set at
                          ; 7C00
  LD (HL),$FF             ; Mark the start of the next set with an end-of-data
                          ; byte
  LD ($EB72),HL           ; ...and store the address pointer to the next set,
  LD A,$00                ; ready for more data
  LD ($EBB7),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 9897.
; * 'Brick' levels have an assortment of the first 8 (from 9897)
; * 'Cavern' levels have an assortment of the second 8 (from 98A7)
;
; 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 7F01.
;
; The following instructions identifies the level type. If it's a cavern-style
; level, sets the offset for the graphic address pointer to 8.
LC501:
  LD A,($EAB7)            ; Get room number
  LD L,A                  ; Store in L register
  CP $52                  ; If room number is 1-81 it's a 'brick style level'.
                          ; For other scenery types it's actually rooms 1-82
                          ; (C178). 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,$00                ; ...So set graphics offset EB77 to 0...
  JR C,LC501_0            ;
  LD A,$08                ; ...Otherwise it's a 'cavern' style level, so set
                          ; the offset to 8.
LC501_0:
  LD ($EB77),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,$00                ; 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,($EB70)           ; Get address pointer to the foreground object data
                          ; table at 7F01
; CALCULATE NUMBER OF FOREGROUND SCENERY OBJECTS
;
; The first of the room data bytes at L61A9 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,($EB7C)            ; Get (first) room data byte from banks at L61A9,
                          ; which indicates the size of the room
  LD C,A                  ; Temp store in C register
  RRA                     ; Divide by 2
  AND $7F                 ; 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,$08               ; Add 8 to the value as a small offset, to move it
  LD ($EB48),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.
LC501_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 $07                 ; There are only 8 types of foreground object for
                          ; each level type, so we only need bits 0-2 (values
                          ; 0-7)
  ADD A,$6A               ; Add to the graphic address pointer table at L97C3.
  LD C,A                  ; An offset of 106 puts the address pointer at the
                          ; scenery objects at 9897.
  LD A,($EB77)            ; 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 ($EABE),HL           ; Store address pointer to the foreground object data
                          ; set at 7F01
  LD ($EB7A),DE           ; Store ROM address pointer
  LD D,$00                ; 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 $FE                 ;
  LD E,A                  ;
  LD HL,($EB6A)           ; 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. AA5B 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 7F01.
  LD HL,($EABE)           ; Retrieve address pointer to foreground object data
                          ; sets at 7F01
  LD (HL),$00             ; First byte default value = 0 (item not on screen)
  INC HL                  ;
  LD (HL),$00             ; Horizontal position precision/fraction byte = 0
  INC HL                  ; (item starting position will be a multiple of 8
                          ; pixels)
  LD A,($EB48)            ; 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,$10               ; Add 16 to the horizontal position and re-store. The
  LD ($EB48),A            ; value of 16 puts a gap of 16 character squares
                          ; between foreground objects.
  LD (HL),$00             ; Vertical position precision/fraction byte (not
  INC HL                  ; needed here)
  LD (HL),$68             ; 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. AA5B
  LD (HL),D               ;
  INC HL                  ;
  LD DE,($EB7A)           ; Retrieve ROM address pointer
  DJNZ LC501_1            ; Continue to store object details in the 7 byte
                          ; scenery data banks at 7F01. B register = count of
                          ; objects that need storing.
  LD (HL),$FF             ; 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 7C00 and the foreground scenery object sets at
; 7F01.
;
; Calculate offset based on Maroc's default room position and his room entry
; point
LC571:
  LD A,($EB75)            ; Maroc's horizontal (entry) position when he moves
  LD C,A                  ; to a new room, in half-character/4-pixel steps
  LD A,($EAC0)            ; 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,($EB76)            ; Maroc's vertical (entry) position when he moves to
  LD C,A                  ; a new room, in pixels
  LD A,(LEB74)            ; 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,$00                ; Clear D register ready for DE offset addition
                          ; shortly
  LD HL,(LDAEE)           ; Address pointer to room item data sets at 7C00
; Add co-ordinate offsets into bytes 6 (horizontal co-ordinate) and 8 (vertical
; co-ordinate) of each of the room item data sets at 7C00
LC571_0:
  LD A,(HL)
  CP $FF                  ; Skip next bit if no more data sets
  JR Z,LC571_1            ;
  LD E,$05                ; 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,$09                ; Move along 9 bytes - this puts the pointer at the
  ADD HL,DE               ; start of the next bank of data
  JR LC571_0              ; Repeat until all data sets adjusted
; Next do the same for the foreground scenery items, which are stored
; separately at 7F01
LC571_1:
  LD HL,($EB70)           ; Get address pointer to foreground scenery data sets
                          ; at 7F01
; Update data item loop:
LC571_2:
  LD A,(HL)
  CP $FF                  ; Check first byte for end-of-data byte
  JP Z,LC63B              ; 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 LC571_2              ; ...and repeat until all sets have been adjusted.
; The routine that follows this one is at LC63B (jump at end of data sets from
; C5A3)

; Tunnel room - identify the connecting door set
;
; Used by the routine at LC15A.
;
; HL Address pointing to the current tunnel data bank at L6710
;
; Uses the tunnel room data at L6710 and the connecting door sets at L6790 to
; work out which room the tunnel that Maroc has just entered leads to.
LC5B5:
  LD A,$00
  LD ($EC9D),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 ($EB7D),A            ; ...and store
; The second and third bytes of the set hold the two paired door set numbers
; (in the table at L6790) 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,($EAB4)            ; Compare with the current door set number that Maroc
  CP B                    ; has just left
  JR NZ,LC5B5_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 L6790)
LC5B5_0:
  LD A,(HL)               ; Get the connecting room set number...
  LD ($EAB4),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,($DAF5)           ; Address pointer to connecting door sets (L6790)
  LD D,$00                ; 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 $FC                 ; 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 ($EAB5),HL           ; ...and store the address pointer-plus-offset
; Update the 'entry point' door data in the room connecting data set at L6790:
  INC HL                  ; Move address pointer along 2 bytes to byte 3 of the
  INC HL                  ; set
  LD A,($EAF5)            ; 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 L6790).
  INC HL                  ; Move to the 4th byte of the relevant door set (in
                          ; the table at L6790)
  LD (HL),$00             ; 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 7C00 is the generic position/viewport/co-ordinates
; for the tunnel as a whole, before dealing with the individual on-screen
; items.
LC5E7:
  LD A,$0F
  LD (LEB43),A            ; Graphic type = 15 - this is the value for the
  LD A,$00                ; generic tunnel screen position/viewport
  LD ($EB47),A            ; Set horizontal room position to 0
                          ; (overflow/fraction byte)
  LD ($EB49),A            ; Set vertical room position to 0 (overflow/fraction
                          ; byte)
  LD ($EB4C),A            ; Set horizontal movement speed to 0
  LD ($EB4D),A            ; Set vertical movement speed to 0
  LD A,$FF                ;
  LD ($EB4B),A            ; Byte indicating general tunnel element
  LD A,$1C                ; Horizontal position, in half-character/4-pixel
  LD ($EB48),A            ; steps Tunnel starting position is at the top of the
                          ; screen, in the middle (14 character spaces).
  LD A,$00                ; Vertical position, in pixels, from the top of the
  LD ($EB4A),A            ; playing area.
  LD A,$01                ; Animation frame number offset (= no offset)
  LD ($EB50),A            ;
  LD A,$7C                ; Offset for graphics address table at L97C3,
                          ; starting at 'dummy' graphic (98B9/AD9C) as nothing
                          ; actually needs drawing
  CALL LE0C2              ; 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 ($EB4E),A            ; Store as item properties byte

; Start of tunnel data setup
;
; Generate the initial tunnel position/movement:
LC618:
  LD A,($EAB7)            ; Get room number
  SUB $E0                 ; 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,$1234             ; Base ROM address
  LD DE,$0020             ;
  LD B,A                  ;
LC618_0:
  ADD HL,DE               ; Base ROM address + (tunnel number [0-31] x 32)
  DJNZ LC618_0            ;
; However, the generated result in HL is immediately overwritten in the call at
; C62E, making the previous calculation unnecessary.
;
; Store generated tunnel data:
  LD ($EB44),DE           ; Store the 32 from earlier - see notes above.
  LD ($EB46),A            ; Store tunnel number (room number minus 224)
  CALL LE0B0              ; Copy 16 bytes of game data from the data buffer at
                          ; LEB43 to the room item data sets at 7C00.
  LD (HL),$FF             ; Set end-of-data byte at start of next 16 bytes data
                          ; bank at 7C00
  LD ($EB72),HL           ; Store the data set address pointer for the next
  LD A,$01                ; bank.
  LD ($EB7E),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 LC571.
;
; This routine uses bits in the room number byte at EAB7 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.
LC63B:
  CALL LE25B              ; Clear the playing area (pixels)
  LD A,($EAB7)            ; Get room number
  LD C,A                  ; Temp store in C register
  AND $18                 ; Filter bits 3 and 4 of room number - these will
                          ; determine the PAPER colour of the room
  CP $10                  ; Is bit 4 set (and bit 3 unset)?
  JR Z,LC63B_0            ; If so, room will have a red (PAPER 2) background
  CP $08                  ; Is bit 3 set (and bit 4 unset)?
  JR Z,LC63B_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 $07                 ; Filter bottom 3 bits
  CP $02                  ;
  JR NC,LC63B_4           ; If >= 2, colour is fine as red or brighter on black
                          ; is OK, so jump to set it (INK 2-7)
  ADD A,$03               ; INK 0 (black) and 1 (blue) are too dark for a black
  JR LC63B_4              ; background so add 3 to make it a brighter colour
                          ; (magenta/green)
; Room will have a red (PAPER 2) background
LC63B_0:
  LD B,A                  ; Store (PAPER) colour in B register
  LD A,C                  ; Retrieve room number from C register
  AND $03                 ; Filter bits 0 and 1 (values 0-3)
  JR Z,LC63B_1            ; Black (INK 0) is OK on red
  ADD A,$05               ; 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 $07                 ; Filter ink colour (0-7)
LC63B_1:
  OR B                    ; Combine with paper colour
  JR LC63B_4              ;
; Room will have a blue (PAPER 1) background
LC63B_2:
  LD B,A                  ; Store (PAPER) colour in B register
  LD A,C                  ; Retrieve room number from C register
  AND $07                 ; Filter bits 0-2 (values 0-7)
  CP $03                  ;
  JR NC,LC63B_3           ; If >= 3, colour is fine as magenta or brighter on
                          ; blue is OK (INK 3 - 7)
  ADD A,$06               ; 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 C64C.
; Set calculated room colours:
LC63B_3:
  OR B                    ; Combine INK colour with PAPER colour
LC63B_4:
  OR $40                  ; Set BRIGHT bit
  LD ($EAA9),A            ; Store room colours
  CALL LE207              ; 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 LC6A4.
;
; The paired byte (1-9) indicates which level (L7172) Maroc is on. Once
; identified, the level name is printed on the scroll.
LC677:
  LD A,($EAB7)            ; Get room number
  CP $D5                  ; There are 212 'standard' rooms in the game
  JR NC,LC6B6             ; 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,$09                ; 9 pairs of bytes to check at LC6A4
  LD HL,LC6A4             ;
  LD C,A                  ; Temporary store for room number in C register
LC677_0:
  LD A,(HL)               ; Get first byte of data banks
  CP C                    ;
  JR C,LC677_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 LC677_0            ;
; Level identified from room number
LC677_1:
  DEC HL                  ; Move pointer back 1 byte to the second byte of
  LD A,(HL)               ; previous pair
  LD ($EAC9),A            ; ...And store.
  LD HL,(LEB5B)           ; Get address pointer to current game level text at
                          ; L7172
  CALL LE5A5              ; Identify the address of the level text to print
  LD ($EAEA),HL           ; ...and store.
  LD A,$00                ; Set the character counter to the start of the text
                          ; (character position 0)
  LD ($EBC9),A            ; ...and store.
  CALL LE58C              ; Clear the spell message text area on the scroll
  JR LC6B6                ; 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 LC677
;
; 9 pairs of bytes:
; * Byte 1 = the room number 'buckets'
; * Byte 2 = the level text number (L7172). Also the warlock number (L6C7C)
;   appearing on this level, except for levels 8 & 9
LC6A4:
  DEFB $D4,$09            ; Rooms 209-212: Text 9 (High Temple of Chaos)
  DEFB $D1,$07            ; Rooms 182-209: Text 7 (Catacombs of the Undead)
  DEFB $B5,$06            ; Rooms 158-181: Text 6 (The Labyrinth)
  DEFB $9D,$05            ; Rooms 134-157: Text 5 (Goblin Warren)
  DEFB $85,$03            ; Rooms 104-133: Text 3 (Mines of Madness)
  DEFB $67,$02            ; Rooms 83-103: Text 2 (Caverns of Doom)
  DEFB $52,$08            ; Rooms 55-82: Text 8 (Chambers of Chaos)
  DEFB $36,$04            ; Rooms 31-54: Text 4 (Great Halls of the Deep)
  DEFB $1E,$01            ; Rooms 1-30: Text 1 (Gatehouse Level)

; Start of game cycle - control checks
;
; Used by the routines at LC677 and LD94C.
;
; Check and log game control inputs
LC6B6:
  LD A,($BF19)            ; Game flag - 0 = New/current game, 1 = Loaded game
  CP $00                  ; If not a new/current game...
  JP NZ,LC763             ; ...Launch the pause game (with music) routine
  LD A,($EAB7)            ; Get room number
  CP $E0                  ; If <= 224, skip next two instructions
  JR C,LC6B6_0            ;
  LD A,$01                ; If room number >= 224, it's a tunnel room - set
  LD ($EAAC),A            ; Maroc's vertical facing direction to 1 (up)
; Read keyboard/joystick input
;
; Kempston controls dealt with separately at LC6B6_4.
LC6B6_0:
  LD HL,(LEB06)           ; Address of the control values to check, e.g.
                          ; keyboard, cursor, Kempston
  LD DE,$EB2E             ; Store for which keys/buttons are being pressed
  LD A,(LBF18)            ; Control option 1 = Kempston, 2 = AGF (Cursor), 3 =
                          ; Sinclair, 4 = Keyboard
  CP $01                  ; Check if Kempston joystick selected
  JR Z,LC6B6_4            ;
; Read keyboard input (includes Cursor, Sinclair joysticks)
;
; Reads port for chosen control option (values at from LEB06) for up, down,
; left, right and fire.
;
; Stores values in control buffer at EB2E. 0 = Not pressed, 1 = Pressed
LC6B6_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 $FF                  ;
  JR Z,LC6B6_2            ;
  LD A,$01                ; Key pressed - store 1 for this input
  JR LC6B6_3              ;
LC6B6_2:
  LD A,$00                ; Key not pressed - store 0 for this input
LC6B6_3:
  LD (DE),A               ;
  INC DE                  ; Move on to next control key/button
  INC HL                  ;
  LD A,$00                ; Check if we've reached the end of the controls (0 =
  CP (HL)                 ; end-of-data byte)
  JR NZ,LC6B6_1           ; If not, continue to read control directions until
  JR LC6B6_6              ; all 5 have been checked
; Read Kempston joystick input
LC6B6_4:
  LD BC,$001F             ; 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,$00                ; Store 0 (default) if button/control not being
  JR Z,LC6B6_5            ; pressed
  LD A,$01                ; Store 1 if button/control being pressed
LC6B6_5:
  LD (DE),A               ;
  INC DE                  ; Move on to next control/button
  INC HL                  ;
  LD A,(HL)               ;
  CP $00                  ; Check if we've reached the end of the controls (0 =
                          ; end-of-data byte)
  JR NZ,LC6B6_4           ; If not, continue to read control directions until
                          ; all 5 have been checked
; Evaluate control direction values
;
; Horizontal movement control:
LC6B6_6:
  LD A,($EB31)            ; Check movement control - right
  LD C,A                  ; Store in C register (1 = right pressed, 0 = right
                          ; not pressed)
  LD A,($EB30)            ; 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,($EAAB)            ; 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 (LEAFD),A            ; ...And store...
; Vertical movement control:
  LD A,($EB2F)            ; Check movement control - down
  LD C,A                  ; Store in C register (1 = down pressed, 0 = down not
                          ; pressed)
  LD A,($EB2E)            ; 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,($EAAC)            ; Maroc's facing direction (1 = facing up, 255 =
                          ; facing down)
  ADD A,C                 ; Add to control value
  LD ($EAFE),A            ; ...And store...
; The FIRE button flag is stored at EB32. Unlike other control directions, the
; byte at EAC6 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,($EB32)            ; Check FIRE control
  CP $00                  ;
  LD A,($EAC6)            ; Get the 'fire release' flag ready to check
  JR Z,LC6B6_10           ; If fire hasn't been pressed, skip the next routine
; FIRE pressed
  CP $00                  ; Has the fire key been released from being pressed
  JR Z,LC6B6_7            ; earlier?
  LD A,$00                ; Set FIRE control to zero
  LD ($EB32),A            ;
  JR LC758                ;
; Fire control has been pressed so set the fire control release byte at EAC6 to
; 1.
LC6B6_7:
  LD A,$01
  LD ($EAC6),A
; Play high pitched beep
  LD A,$10                ; 16 = speaker bit (bit 4)
  LD C,$20                ; Outer loop counter - affects duration/sound effect
LC6B6_8:
  OUT ($FE),A             ; Play speaker
  XOR $10                 ; Toggle speaker bit
  LD B,$30                ; Inner loop counter - affects pitch of beep sound
LC6B6_9:
  DJNZ LC6B6_9            ; Decrement inner loop counter until zero for short
                          ; pause
  DEC C                   ; Outer loop pause
  JR NZ,LC6B6_8           ;
  JR LC758                ;
; Fire not pressed
LC6B6_10:
  LD A,$00                ; Set the 'fire control release' control flag to 0,
  LD ($EAC6),A            ; as no fire controls are being pressed

; Pause game routine - check if 'pause' key pressed
;
; Used by the routine at LC6B6.
;
; Follows the previous routine keyboard control checks for
; up/down/left/right/fire.
LC758:
  LD BC,$DFFE             ; 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,LC7D0              ; If that's the case, jump to LC7D0 Otherwise,
                          ; continue to the pause game routine

; Pause game routine - play tune and check user input
;
; Used by the routines at LC6B6 and LC7C5.
;
; (This is where the ERRSP stack pointer error is pointed at in routine at
; LBF60)
;
; When 'P' is pressed (check made in previous routine at LC758), 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 C76D 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
LC763:
  LD A,$00                ; Set game flag to 0 (new/current game), in
  LD ($BF19),A            ; preparation for the player leaving the pause menu
                          ; returning to the game. Checked at the start of the
                          ; game cycle keyboard checks at LC6B6.
  LD A,$02                ; This tells the music player to play tune number 2
                          ; (the 'pause game' music) - a short tune stored at
                          ; EC72.
  CALL LE5B6              ; Play the tune
; This routine checks if the player is pressing 'S', which saves the current
; game.
  LD BC,$FDFE             ; 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,LC7C5              ; If this is the case and 'S' isn't being pressed,
                          ; jump to LC7C5 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 LDEF9              ; Clear the scroll status panel at the bottom of the
                          ; screen
  LD A,$25                ; "Start tape then press enter" is message number 37
  CALL LE5A5              ; Get the address pointer for this message text
                          ; (L7353)
  LD (LEAA1),HL           ; ...and store it.
  LD HL,$5087             ; Set and store address position to print text
  LD ($EAA4),HL           ; (centre-left of scroll)
  CALL LE2D0              ; Print the text string on the scroll
; This routine checks the keyboard until the player presses ENTER
LC763_0:
  LD BC,$BFFE             ; 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,LC763_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 LDEF9              ; 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 C76D.
;
; Data block 1:
LC79A:
  LD A,$FF                ; Indicates this is a data block to save
  LD IX,LEA34_6           ; Start address of data block to save
  LD HL,$ECA1             ; End address of data block
  LD DE,LEA34_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 $04C2              ; Call the ROM routine to save this data block to
                          ; tape
; Data block 2:
  LD A,$FF                ; Indicates this is a data block to save
  LD IX,($DAF5)           ; Start address of data block to save (L6790)
  LD HL,($EB61)           ; End address of data block (8053)
  LD DE,($DAF5)           ; 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 $04C2              ; 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 LC763.
;
; While the game is paused, check if the player is pressing 'O' to resume the
; game
LC7C5:
  LD BC,$DFFE             ; 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,LC763              ; 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 LC758.
LC7D0:
  DI                      ; Disable interrupts
  CALL LE641              ; Check scroll status and player inputs such as
                          ; current spell selection, key controls
  LD HL,$0000             ; Reset the address pointer to the ROM, that produces
  LD ($EB59),HL           ; semi-random byte values to play generic sound
                          ; effects in the routine at LE1D7.
  LD A,$00                ; Reset speaker bit (and border)
  OUT ($FE),A             ;
  LD ($EAA8),A            ; Set the default graphics colour attribute to 0
                          ; (black INK, black PAPER)
  LD HL,(LDAEE)           ; Address pointer to the room data sets at 7C00 that
                          ; contain scenery, object and creature data for the
                          ; current room
  LD ($EABC),HL           ; Copy base pointer to address store for start of
                          ; next data set
  LD ($EABE),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 LD325.
;
; HL Address pointer to room data sets at 7C00 that contain the scenery, object
;    and creature data in the current room
;
; Get a room data set at 7C00 and copy it into the working buffer at LEB43,
; ready to deal with:
LC7EA:
  LD A,(HL)               ; Check for end-of-data byte
  CP $FF                  ;
  JP Z,LD331              ; If found, skip out of routine
  LD BC,$0010             ; Prep counter to copy 16 bytes
  CP $00                  ; If the first byte is zero...
  JR NZ,LC7EA_0           ;
  ADD HL,BC               ; ...then this room item is no longer present, so
                          ; skip to the next data bank of 16 bytes
  JR LC7EA                ; ...and keep checking the data banks
; Copy room item data from data bank into working data buffer at LEB43
LC7EA_0:
  LD DE,LEB43             ; Copy data from 16 byte data bank at 7C00 to LEB43
  LDIR                    ;
  LD ($EABC),HL           ; Store address pointer, now at the start of the next
                          ; 16 byte data set
  LD A,($EB4E)            ; 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 ($EB4E),A            ; ...and restore
  LD HL,($EB51)           ; Get graphic address pointer to this item's
                          ; graphics, in the address pointer table at L97C3
  LD ($EACD),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 EAD3.
;
; The carry bit is used in the calculation to store (at EAD4) 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,($EB47)           ; H = Graphic horizontal position within current
                          ; room, in half character (4 pixel) steps (H = EB48,
                          ; L = EB47). 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 ($EAD4),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 ($EAD3),A            ; ...and store.
; The next instructions check bit 4 of the Graphic properties byte (this bit is
; unused).
  LD A,($EB4F)            ; This is the pre-graphics data byte (Graphic
                          ; properties)
  AND $10                 ; Check if bit 4 set (16)
  JR Z,LC837              ; If it's NOT set, jump to LC837
; 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,($EB51)           ; ---
  ADD HL,DE               ; ---
  ADD HL,DE               ; ---
  LD ($EB51),HL           ; ---
  LD A,($EB4E)            ; ---
  OR $04                  ; ---
  LD ($EB4E),A            ; ---
  JR LC837_0              ; ---

; Adjust room item's position based on the speed and direction of Maroc and the
; item
;
; Used by the routine at LC7EA.
;
; 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:
LC837:
  LD A,($EB4F)            ; Get the Graphic properties byte (again)
  AND $C0                 ; Check the top 2 bits (6 & 7). Bit 6 set = graphic
                          ; has left/right facing versions Bit 7 = graphic is
                          ; animated
  JR Z,LC837_0            ; If neither is set, there's nothing to change
                          ; animation-wise, so skip the following CALL
                          ; instruction
  CALL LE336              ; 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 EACC) 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
LC837_0:
  LD A,($EB4C)            ; Item's horizontal movement speed (this will be
  LD C,A                  ; non-zero for moving things such as creatures)
  LD A,($EB04)            ; 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,($EB47)           ; Graphic horizontal position within current room, in
                          ; half character (4 pixel) steps.
  ADD HL,DE               ; Add to speed to get the new position
  LD ($EB47),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 ($EACC),A            ; Store the horizontal pixel position overflow...
  LD A,H                  ;
  LD (LEACB),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,($EAD3)            ; Get the original horizontal pixel position
  CP B                    ; Compare it with the new horizontal pixel position
  JR Z,LC837_1            ; Has the graphic moved?
; Graphic has moved on-screen
  LD A,($EB4E)            ; Get the graphics properties byte
  OR $04                  ; Set bit 2 (4) - this indicates the graphic will
                          ; need erasing (before it's redrawn)
  LD ($EB4E),A            ; ...and re-store
; Calculate item's new VERTICAL speed/position based on a combination of the
; item's speed and Maroc's speed
LC837_1:
  LD A,($EB4D)            ; Item's vertical movement speed
  LD D,A                  ;
  LD A,($EB05)            ; 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,($EB4A)            ; Graphic's vertical pixel position within current
                          ; room
  LD ($EAD2),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,($EB49)           ; 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 ($EB49),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,LC89F              ; Has the graphic moved?
; Graphic has moved on-screen
  LD A,($EB4E)            ; Get the graphics properties byte
  OR $04                  ; Set bit 2 (4) - this indicates the graphic will
                          ; need erasing (before it's redrawn)
  LD ($EB4E),A            ; ...and re-store.

; Deal with and check room item, creature or scenery
;
; Used by the routine at LC837.
;
; The first byte of the working data set at LEB43 (this data is copied from
; each of the 16 byte room item data sets at 7C00) is checked here.
;
; It indicates the type of room object that needs to be drawn, checked or
; generally dealt with.
LC89F:
  LD A,(LEB43)
  CP $01                  ; Back wall bricks/scenery, or door frames,
  JP Z,LD27D              ; wall/floor connector graphics or cursor
  CP $02                  ; Door
  JP Z,LC8DC              ;
  CP $03                  ; Creature
  JP Z,LCD88              ;
  CP $04                  ; Interactable objects (e.g. key, chest, scroll)
  JP Z,LCB00              ;
  CP $05                  ; Missile fired by creature/warlock
  JP Z,LD09B              ;
  CP $06                  ; Vertical back wall/floor connector (left)
  JP Z,LD161              ;
  CP $07                  ; Vertical back wall/floor connector (right)
  JP Z,LD161_0            ;
  CP $08                  ; Missile fired by Maroc
  JP Z,LD09B              ;
  CP $0F                  ; Tunnel position (& direction)
  JP Z,LD179              ;
  CP $0E                  ; Tunnel item (side boundary wall, bat or spider)
  JP Z,LD1D2              ;
  CP $20                  ; Room position & viewport
  JP Z,LD26E              ;
  JP LD27D                ; 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 LC89F.
;
; 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 LC89F.
LC8DC:
  LD A,($EB4E)            ; Get item properties byte (for the door)
  LD C,A                  ;
  AND $01                 ; Bit 1 indicates if the item is on-screen (0 = no, 1
                          ; = yes)
  JP Z,LD27D              ; 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 $F0                 ; Filter out bits 0-3
  CP $00                  ; If any of bits 4-7 are set, there's already
                          ; something already happening with this door that
                          ; needs dealing with
  JP Z,LC8DC_0            ; No bits set - skip next few checks
  CP $20                  ;
  JP Z,LCA8E              ; Bit 5 (32) set = Maroc or a creature has touched a
                          ; door, so it needs to be opened/closed
  CP $40                  ; Bit 6 (64) set = means the door is currently
  JP Z,LCAB4              ; opening or closing
  JP LCAB4_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.
LC8DC_0:
  LD A,(LEAAA)            ; Game cycle counter/timer
  AND $0F                 ; Check bits 0-3 (values = 0-15)
  JP NZ,LC99B             ; If anything other than 0, skip this check
; Every 16 frames/game cycles:
  LD A,($EB46)            ; Door being checked - 0 = Back wall, 1 = Right wall,
  LD C,A                  ; 2 = Left wall
  LD A,($EAB4)            ; Connecting door (in table at L6790) that Maroc
  CP C                    ; entered the current room from
  JR Z,LC8DC_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 EBB5.
; 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 LDB06              ; Generate pseudo-random number
  AND $7F                 ; Filter out bit 7 (just keep random values 0-127)
  LD C,A                  ;
  LD A,($EBB5)            ; Timer indicating how long before a creature is
                          ; likely to wander in from an adjacent room
  DEC A                   ; Decrement the counter
  LD ($EBB5),A            ; ...re-store it...
  CP C                    ; Compare it with the randomly generated value
  JP NC,LC99B             ; If timer is (still) >= than the random value, a
                          ; creature won't wander into the room
  LD A,($EBB7)            ; Timer is less than the random value. Get the number
  CP $00                  ; of creatures currently in the room
  JP NZ,LC99B             ; 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)
LC8DC_1:
  LD A,($EBB6)            ; Get number of creatures currently in room
  CP $03                  ;
  JR NC,LC99B             ; If there are already 3, skip the whole check as
                          ; there can't be any more
; Use the connecting door table at L6790 to check which rooms are adjacent to
; this one
  LD HL,($EB44)           ; Address pointer to connecting door table at L6790
  LD C,(HL)               ; First byte in set contains the room number for this
                          ; door
  LD A,($EAB7)            ; Current room number
  CP C                    ; Is it the same as the first byte of the connecting
  JR NZ,LC8DC_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,$DF                ;
  CP C                    ;
  JR C,LC99B              ; 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
LC8DC_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 L6B8C. Room numbers start at 1,
                          ; but it needs to start at 0 for the offset, so
                          ; reduce the value by 1
  LD B,$00                ; Reset B register (ready for offset to be added)
  LD HL,($DAF0)           ; Address pointer at start of room creature data at
                          ; L6B8C
  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 $00                  ;
  JR Z,LC99B              ; 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,($EB4E)            ; Get door properties byte
  LD D,A                  ; Temp store in D register
  AND $F0                 ; Clear bits 0-3
  CP $00                  ; Any of bits 4-7 set? This check has already been
                          ; made at C8E6, so the jump in the next instruction
                          ; shouldn't be triggered.
  JR NZ,LC99B             ; If so, jump out of routine here
  LD A,D                  ; Retrieve door properties byte
  AND $08                 ; Check bit 3 - if set, indicates door is open,
                          ; otherwise closed
  JR NZ,LC95F             ; If door is open, skip ahead to the next routine
  LD A,D                  ; Retrieve door properties byte
  ADD A,$40               ; 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 ($EB4E),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 LC8DC.
;
; C Creature data byte from room creature list at L6B8C
;
; 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.
LC95F:
  LD A,C                  ; Get room creature byte from table at L6B8C
; Check for any GUARDIANS OF CHAOS
  AND %11000000           ; Bits 6 & 7 - creature data for guardians of chaos
  JR Z,LC95F_0            ; If there aren't any in this room, skip to the next
                          ; check
  LD A,C                  ; Retrieve room creature byte
  SUB $40                 ; 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,$08                ; Creature type number for guardian of chaos = 8
  JR LC95F_3              ;
; Check for any GOBLIN WARRIORS
LC95F_0:
  LD A,C                  ; Retrieve room creature byte
  AND %00110000           ; Bits 4 & 5 - creature data for goblin warriors
  JR Z,LC95F_1            ; If there aren't any in this room, skip to the next
                          ; check
  LD A,C                  ; Retrieve room creature byte
  SUB $10                 ; 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,$09                ; Creature type number for goblin warrior = 9
  JR LC95F_3              ;
; Check for any GOBLIN MISSILE THROWERS
LC95F_1:
  LD A,C                  ; Retrieve room creature byte
  AND %00001100           ; Bits 2 & 3 - creature data for goblin missile
                          ; throwers
  JR Z,LC95F_2            ; If there aren't any in this room, skip to the next
                          ; check
  LD A,C                  ; Retrieve room creature byte
  SUB $04                 ; 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,$0A                ; Creature type number for goblin missile thrower =
  JR LC95F_3              ; 10
; If the creature entering the room isn't one of the above, it must be a WRAITH
; (bits 0 & 1)
LC95F_2:
  LD A,C                  ; Retrieve the creature byte
  SUB $01                 ; 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,$0B                ; Creature type number for wraith = 11
; Creature type entering the room has been identified
LC95F_3:
  LD ($EBB7),A            ; Store creature type
  LD A,($EB48)            ; Get the door graphic horizontal position within
                          ; current room, in half character (4-pixel) steps
  LD ($EBB8),A            ; Copy this to the entering creature's horizontal
                          ; room position, as this will be its entry point
  LD A,($EB4A)            ; Similarly, get the door vertical pixel position
  LD ($EBB9),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 LC8DC.
;
; 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 LC99B_1 (to LDFCD_0) for the door's collision/event
; check
LC99B:
  LD A,($EB4E)            ; Get door properties byte
  AND $08                 ; Check bit 3 (8) - open/closed flag. 1 if the door
  LD C,$01                ; is open, 0 if it's closed
  JR NZ,LC99B_0           ; If it's open, set C register value to 1 and jump a
                          ; few instructions to LC99B_0
  LD HL,($EB44)           ; Address pointer to door table sets at L6790
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  LD C,(HL)               ; Door is closed - load C register with 4th byte from
                          ; door data set at L6790
; 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 L6790 (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.
LC99B_0:
  LD HL,($EB51)           ; Get address pointer to door graphics in table at
  LD E,(HL)               ; L97C3
  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 ($EAAF),A            ; ...store
  LD A,($EAD3)            ; Graphic's horizontal position in pixels
  ADD A,B                 ; Add horizontal pixel offset
  LD D,A                  ; Store in D register
  LD A,($EAD2)            ; Graphic vertical pixel position
  ADD A,H                 ; Add vertical pixel offset
  ADD A,$18               ; 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,($EB4E)            ; Get door properties byte
  AND $08                 ; Check bit 3 (8) - this is 1 if the door is open, 0
                          ; if it's closed
  JR Z,LC99B_1            ; If it's closed, skip the next few instructions and
                          ; jump to LC99B_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 $F8                  ; The only door frame with this offset is the back
                          ; wall open door
  JR Z,LC99B_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 $08                 ; vertical 'hit box' position
  LD E,A                  ; Store in E register - this is used for the vertical
                          ; pixel collision checks in a moment at LC99B_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 L6790 - 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).
LC99B_1:
  CALL LDFCD_0            ; Collision check routine
  CP $01                  ; A register returned with either 1 (collision) or 0
  JR NZ,LC99B_2           ; (no collision)
; Collision with door detected
  LD A,($EB4E)            ; Get door properties byte
  AND $0F                 ; Keep bits 0-3
  OR $20                  ; Set bit 5 (32) - this is a flag/trigger to indicate
                          ; the door needs to be opened or closed when checked
                          ; (at LC8DC) during the next game cycle
  JP LCAB4_1              ; Skip out to end of routine
; No collision with door detected
LC99B_2:
  LD A,($EB4E)            ; Get door properties byte
  LD C,A                  ; Temp store in C register
  AND $01                 ; Check bit 1 - is the door visible on-screen?
  JP Z,LD27D              ; If not, can skip out of routine - nothing needs
                          ; doing
  LD A,C                  ; Retrieve door properties byte
  AND $08                 ; Check bit 4 (8) - 1 if door is open, 0 if closed
  JP Z,LCAB4_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
; LDFCD_0 is used to determine if Maroc is moving through the doorway.
LC9F6:
  LD A,($EAAF)            ; Door graphic's horizontal position offset
  CP $F8                  ;
  JR Z,LC9F6_0            ; The only door frame with this value offset is the
  CP $E8                  ; back wall open door
  JR Z,LC9F6_1            ; The only door frame with this value offset is the
                          ; right wall open door
  LD A,$F8                ; Horizontal pixel offset for left wall open door
  JR LC9F6_2              ; left wall open door (-8 pixels)
LC9F6_0:
  LD A,$0C                ; Horizontal pixel offset for the back wall open door
  JR LC9F6_2              ; (+12 pixels)
LC9F6_1:
  LD A,$08                ; Horizontal pixel offset for the right wall open
                          ; door (+8 pixels)
; Add the adjusted offset to door horizontal pixel position
LC9F6_2:
  LD B,A                  ; Get the pixel offset for this door's exit/entry
                          ; point
  LD A,($EAD3)            ; 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 CA19 (to
                          ; LDFCD_0)
  LD A,($EAD2)            ; Get the door's vertical pixel position
  SUB $08                 ; Small (-8 pixel) vertical adjustment
  LD E,A                  ; Store in E register - used for the vertical 'hit
                          ; box' for collision check in CALL at CA19 (to
                          ; LDFCD_0)
  LD C,$00                ; Collision type = 0 - this is the collision/event ID
                          ; for checks against Maroc's position
  CALL LDFCD_0            ; Check for collision
  CP $00                  ; A register returned with 1 = collision, 0 = no
                          ; collision
  JR NZ,LC9F6_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 $04                 ; Make a further small (-4 more pixels) horizontal
                          ; adjustment
  LD E,A                  ; Store back in E register (horizontal 'hit box'
                          ; check)
  LD A,($EAD3)            ; Door vertical pixel position
  LD D,A                  ; Retrieve vertical 'hit box' pixel position from D
                          ; register
  LD C,$00                ; Collision type = 0 - this is the collision/event ID
                          ; for checks against Maroc's position
  CALL LDFCD_0            ; Check for collision
  CP $00                  ;
  JP Z,LCAB4_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.
LC9F6_3:
  LD A,($EAAF)            ; Retrieve door graphic's horizontal pixel graphic
                          ; offset
  CP $F8                  ; Offset for the back wall open door
  JR Z,LC9F6_4            ;
  CP $E8                  ; Offset for the right wall open door
  LD A,($EB04)            ; Get Maroc's horizontal movement speed as it'll need
  JR Z,LC9F6_5            ; to be evaluated for left and right wall doors
; Door is a left wall open door. Check Maroc's horizontal movement:
  CP $00                  ; Is Maroc moving left or right?
  JP Z,LCAB4_2            ; If not, skip out of this routine
  CP $80                  ;
  JP NC,LCAB4_2           ; Skip out of this routine if Maroc is moving right
  JR LCA65                ; ...otherwise Maroc is moving left, so send him
                          ; through the doorway
; Door is a back wall open door. Check Maroc's vertical movement:
LC9F6_4:
  LD A,($EB05)            ; Maroc's vertical movement speed
  CP $00                  ; Is Maroc moving up or down?
  JP Z,LCAB4_2            ; If not, skip out of this routine
  CP $80                  ;
  JP NC,LCAB4_2           ; Skip out of this routine if Maroc is moving down
  JR LCA65                ; ...otherwise Maroc is moving upwards, so send him
                          ; through the doorway
; Door is a right wall open door. Check Maroc's horizontal movement:
LC9F6_5:
  CP $00                  ; Is Maroc moving left or right?
  JP Z,LCAB4_2            ; If not, skip out of this routine
  CP $80                  ;
  JP C,LCAB4_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 LC9F6.
;
; Sets a couple of bytes/flags in the connecting door table at L6790 to
; indicate Maroc's entry point for this door.
LCA65:
  LD A,($EB46)            ; Door set number in the connecting room data at
                          ; L6790
  LD ($EAB4),A            ; Copy to working data buffer
  LD A,($EB4A)            ; Door's vertical pixel position
  DEC A                   ; Very minor vertical adjustment (-1 pixel)
  LD (LEB74),A            ; Store as new room vertical entry position
  LD HL,($EB44)           ; Address pointer for door set number in the
                          ; connecting room data at L6790
  LD ($EAB5),HL           ; Copy to working data buffer
  INC HL                  ;
  INC HL                  ;
  INC HL                  ;
  LD (HL),$00             ; Set the 4th byte of the relevant door set (in the
                          ; table at L6790) to 0. This is the standard event
                          ; collision identifier for Maroc (touching a doorway
                          ; space).
  LD A,$FF                ; Room number set to 255 - signifies that the next
  LD ($EAB0),A            ; room number will need calculating (using the door
                          ; connector table at L6790)
  LD A,($EB4E)            ; Door properties byte
  AND $0F                 ; Keep bits 0-3
  OR $80                  ; Set bit 7 - used to flag that Maroc has entered
                          ; through this door
  LD ($EAF5),A            ; The byte stored here will be put in byte 3 of the
                          ; connecting door set at L6790, in the routine at
                          ; C5E0
  JR LCAB4_1              ; Jump to end of door routine checks

; Trigger door opening or closing
;
; Used by the routine at LC8DC.
;
; Door opening/closing has been triggered. Jump from C8EF if bit 5 (32) of item
; properties byte (EB4E) is set, after Maroc has bumped into a door handle.
; Check made using collision check routine at LDFCD.
;
; 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)
LCA8E:
  LD HL,($EB51)           ; Door graphic address pointer in table at L97C3
  LD E,(HL)               ;
  INC HL                  ;
  LD D,(HL)               ; Address pointer to actual door graphics, e.g. 9D38
  EX DE,HL                ; Swap into HL register pair
  INC HL                  ;
  LD B,(HL)               ; Get X co-ordinate pixel offset for graphic tile
  LD A,($EAD3)            ; 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,($EAD2)            ; Get vertical (Y) pixel co-ordinate
  SUB $10                 ; 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,$01                ; Collision/event type to check (1 = Door being
                          ; opened/closed)
  CALL LDFCD              ; Run a collision check (item/Maroc vs door handle)
  CP $00                  ; Was there a collision?
  JR NZ,LCAB4_2           ; If not, jump out of this routine
; A door handle has been touched so initialize door opening/closing
  LD A,($EB4E)            ; Door properties byte
  AND $0F                 ; Keep bits 0-3
  OR $40                  ; Set bit 6 (indicates door is now opening or
  JR LCAB4_1              ; closing)

; Door opening or closing
;
; Used by the routine at LC8DC.
;
; C Door properties byte at EB4E
;
; 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.
LCAB4:
  LD A,($EB50)            ; Graphic frame offset, based on the door's wall
                          ; position and open/closed status, calculated at C3AB
  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 $0F                 ; 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,LCAB4_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,($EB4F)            ; 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 C3AB)
  AND $0F                 ; Again, we only really need bits 0-3 here
  CP H                    ; Check calculated frame offset against the current
                          ; frame offset
  JR C,LCAB4_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 ($EB50),A            ; offset
  LD HL,($EB51)           ; Graphics address pointer to current door frame
  ADD HL,DE               ; graphic at L97C3 - doors start at 97D3
  ADD HL,DE               ; Graphics addresses are 2 bytes long, so add the
                          ; frame offset (-1 or +1) twice
  LD ($EB51),HL           ; ...and re-store the address pointer
  LD A,C                  ; Retrieve door properties byte (from EB4E)
  OR $04                  ; Set bit 2 (4) to indicate existing door graphic
  JR LCAB4_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.
LCAB4_0:
  LD A,$10
  LD ($EB56),A            ; Sound effect duration counter for the 'crunch' that
                          ; happens when a door is fully opened or closed
  LD A,($EB50)            ; Graphic frame number offset
  XOR $E0                 ; 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 ($EB50),A            ; Re-store the updated frame offset value
  LD A,C                  ; Retrieve door properties byte (from EB4E)
  AND $0F                 ; Keep bits 0-3
  XOR $08                 ; 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 LC99B, LCA65 and LCA8E.
LCAB4_1:
  LD ($EB4E),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 LC99B, LC9F6 and LCA8E.
LCAB4_2:
  JP LD27D                ; Jump to the next routine.
; The jump to these instructions is made from C8F7 (skipping all the door
; checks) if Maroc is moving through a doorway.
LCAB4_3:
  LD A,($EB4E)            ; Door properties byte
  ADD A,$80               ; If bit 7 is set (which it will be) Maroc has just
  JR LCAB4_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 LC89F.
;
; Deal with any objects from the room item table at L6790 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.
LCB00:
  LD HL,($EB44)           ; Get item's data pointer for the room item table at
                          ; L736F
  CALL LDE7F              ; Check room object table at L736F to see if any
                          ; items are in this room. If so, copy the item data
                          ; into working buffer at EB85.
  LD A,($EB90)            ; For visible room objects, this is the graphic
                          ; number (offset for address table at L97C3)
  CP $7C                  ; Byte value 124 = the object is not visible
  JR Z,LCB00_0            ; (yet),e.g. a key inside a chest
; Object is visible on screen - get object's colour
  LD A,($EB8B)            ; Get the colour attribute of the object
  AND $0F                 ; Keep the INK colour (0-7), and bit 3, which is set
                          ; for objects that flash (change colour)
  LD ($EAA8),A            ; ...and store
; Check if item is being carried by the servant
LCB00_0:
  LD A,($EB4E)            ; Item properties byte
  LD C,A                  ; Temp store in C register
  AND $10                 ; Check if this item is carried by the servant - bit
                          ; 4 (16) set
  JR NZ,LCB00_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 $08                 ; If bit 3 is set, this item is moving/falling (e.g.
                          ; after being thrown/dropped by the servant)
  JR NZ,LCB5B             ; Item is moving/falling - jump out to LCB5B
  JP LCBA8                ; Item is stationary - jump out to LCBA8
; Item is currently held by the servant
LCB00_1:
  LD A,($EAEC)            ; Get active spell number
  CP $01                  ; Check is the servant spell still active?
  JR NZ,LCB4C             ; If not, servant spell has just been deactivated, so
                          ; the item is now falling/flying
  CALL LDAC8              ; 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 CB3F
; 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,($EB01)            ; Get servant's horizontal movement rate/offset
  ADD A,A                 ; Multiply by 4
  ADD A,A                 ;
  LD ($EB4C),A            ; ...and store as item's horizontal movement
                          ; rate/offset
  LD A,($EB02)            ; Get servant's vertical movement rate/offset
  ADD A,A                 ; Multiply by 4
  ADD A,A                 ;
  LD ($EB4D),A            ; ...and store as item's vertical movement
                          ; rate/offset
  CALL LE039              ; Check room boundary and adjust item's position
  LD A,($EBB1)            ; accordingly
  CP $02                  ; This carried object status byte was set to 2 once
                          ; an item has been retrieved from Maroc's backpack by
                          ; the servant
  JR Z,LCB96              ; 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 (EBB1) to 1
  JP LCC27

; Servant has dropped a held item
;
; Used by the routine at LCB00.
;
; Jump here from CB2A if the servant spell is deactivated while holding an item
LCB4C:
  LD A,($EB4E)            ; Item properties byte
  OR $0C                  ; Set bits 2 (4) - indicating item will need erasing
                          ; (as it's moving) - and 3 (8) - indicating that the
                          ; item is flying/falling
  AND $EF                 ; Reset bit 4 - indicates item is no longer held by
  LD ($EB4E),A            ; the servant
  LD A,$00                ; Finally, reset the flag indicating that the servant
  LD ($EBB1),A            ; is carrying an object

; Handle interactable objects that are falling/flying
;
; Used by the routine at LCB00.
;
; Follows from previous routine or jump from CB20 if bit 3 (8) of item byte at
; EB4E is set (item is moving/falling after being dropped).
LCB5B:
  CALL LDAC8              ; Check that the servant isn't dragging a held object
                          ; below the bottom of the room boundary, adjusting
                          ; co-ordinates accordingly
  CALL LE039              ; 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,($EB4D)            ; Vertical movement speed/offset in pixels (negative
                          ; = up, positive = down)
  ADD A,$0C               ; Adjust vertical movement rate slightly - 12 pixels
  LD ($EB4D),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 $80                  ; >=128 = negative value
  JR NC,LCBA8             ; 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,($EB4A)            ; Graphic vertical pixel position from top of playing
  LD D,A                  ; area
  LD A,$60                ; Pixel line 96 is the bottom of the playing area
                          ; when the room viewport is in its default position
  LD HL,$EAF6             ; 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 $60                  ;
  JR NC,LCB5B_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,LCBA8             ; 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.
LCB5B_0:
  LD A,($EB4E)
  AND $F7                 ; Reset bit 3 (8) of the item properties byte to
  LD ($EB4E),A            ; indicate this item is no longer falling/moving
  LD A,$00                ;
  LD ($EB4D),A            ; Set the item's vertical speed to zero
  LD ($EB4C),A            ; Set the item's horizontal speed to zero
  JP LCC27                ;

; Check if servant has moved away from Maroc after retrieving an item
;
; Used by the routine at LCB00.
;
; When the servant retrieves objects from Maroc's backpack, the byte at EBB1 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.
LCB96:
  LD C,$00                ; Type of collision/event check (collision with
                          ; Maroc)
  CALL LDFCD              ; Run collision check
  CP $00                  ; Is there a collision (A register returned = 1)?
  JP NZ,LCC27             ; 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,$01                ; Servant has moved out of Maroc's backpack area
                          ; after picking up an object
  LD ($EBB1),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 LCC27

; Determine movement of room items/creatures that move around the screen
;
; Used by the routines at LCB00 and LCB5B.
;
; Not defined in the room creature table (L6B8C), but there are certain room
; items defined in the room object item sets at L736F 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
; EB8D. Some creatures home in on Maroc, others move more haphazardly.
LCBA8:
  LD A,($EB8D)            ; First byte from object state data set
  AND $07                 ; Keep bits 0-2
  LD C,A                  ; Store in C register
  CP $00                  ; Does this item move (any of bits 0-2 are set)?
  JP Z,LCC27              ; If not, skip the next section
; This item moves:
  LD A,($EB4E)            ; Get the item properties byte
  AND $FD                 ; 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 ($EB4E),A            ; ...and re-store
  LD A,(LEAAA)            ; Get game counter/timer
  AND $1F                 ; Keep bits 0-4 (values 0-31)
  JP Z,LCBA8_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 $07                  ; Check if counter is < 7
  JR C,LCBA8_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
                          ; (EB8D)
  AND $01                 ; Check bit 1 - if set, this indicates that the
                          ; creature has a random element to its movement
  JR Z,LCBA8_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 LDB06              ; Generate pseudo-random number
  LD B,A                  ; Temp store in B register
  AND $0F                 ; Keep bits 0-3 (values 0-15)
  SUB $07                 ; Subtract 7
  LD D,A                  ; Store in D register - will be a number between -7
                          ; and +8
  LD A,($EB4C)            ; Item's horizontal movement speed
  ADD A,D                 ; Add (or subtract if negative) the random value to
                          ; current speed
  LD ($EB4C),A            ; ...and re-store altered horizontal movement speed
  LD A,B                  ; Retrieve pseudo-random number
  RRA                     ;
  RRA                     ;
  RRA                     ; Divide by 8
  AND $0F                 ; Keep bits 0-3 (values 0-15)
  SUB $07                 ; Subtract 7
  LD D,A                  ; Store in D register - will be a number between -7
                          ; and +8
  LD A,($EB4D)            ; Item's vertical movement speed
  ADD A,D                 ; Add (or subtract if negative) the random value to
                          ; current speed
  LD ($EB4D),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.
LCBA8_0:
  LD A,C                  ; Retrieve movement pattern byte from C register
  AND $02                 ; Check bit 1 (2)
  JR Z,LCBA8_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,($EB48)            ; Get the creature/item's horizontal position
  LD C,A                  ;
  LD A,($EAC0)            ; 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 $07                 ; This XOR subsequently produces a value of either +7
                          ; or -7
  LD ($EB4C),A            ; ...Store this as the item/creature's horizontal
                          ; movement speed
; Calculate VERTICAL movement direction
  LD A,($EB4A)            ; Get the creature/item's vertical position
  LD C,A                  ;
  LD A,($EAC1)            ; 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 $07                 ; This XOR subsequently produces a value of either +7
                          ; or -7
  LD ($EB4D),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.
LCBA8_1:
  LD A,($EB8D)            ; Retrieve movement pattern byte
  AND $04                 ; Check if bit 2 is set
  JR NZ,LCC27             ; If so, skip to the next routine
  LD A,($EB4A)            ; Graphic vertical position in room
  LD E,A                  ;
  CALL LE039              ; Run the standard wall collision check, which keeps
  JR LCC27                ; the creature/item within the room's boundary
; Jump from CBC0 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.
LCBA8_2:
  LD A,$00                ; Set the item/creature's vertical and horizontal
  LD ($EB4D),A            ; movement speed to zero
  LD ($EB4C),A            ;

; Check and change object state after positive events match/collision
;
; Used by the routines at LCB00, LCB5B, LCB96 and LCBA8.
;
; '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 (L736F). 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.
LCC27:
  LD A,($EB8F)            ; Event number ID to check for this item (acting on
  CP $00                  ; another item, e.g. a key opening its corresponding
                          ; chest)
  JR Z,LCC27_0            ; If zero, there's nothing to check
  CP $89                  ;
  JP Z,LDA88              ; Special check for event/collision #137 - Maroc
                          ; using CALIBURN on AVELACH. This ends the game.
  CALL LE2B0              ; Copy room item event data into working buffer
; Event/collision checking:
LCC27_0:
  LD A,($EB8E)            ; Event number for items acting on this item (e.g.
  LD C,A                  ; for a chest, which is opened by a key)
  CP $0F                  ; Event 15 means an item is collectible (Maroc can
                          ; pick it up)
  JP Z,LCC72              ; If so, check if Maroc has picked up the item,
                          ; either by moving over it or given it by the servant
  CALL LDFCD              ; For all other events, run an event check for this
                          ; item
  CP $01                  ; Has a collision/event occurred?
  JP NZ,LCC72             ; 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,($EB8C)            ; Grab the byte containing the number of 'states' for
  LD C,A                  ; the object
  LD A,($EB89)            ; Current object state number (starts at 1 for
                          ; default object state)
  INC A                   ; Increment object state by one
  CP C                    ;
  JR C,LCC27_1            ;
  JR Z,LCC27_1            ; Object state <= max states for this item, skip the
                          ; next instruction
  LD A,$01                ; Object state > max states for this item, so reset
                          ; the object state to 1
LCC27_1:
  LD HL,($EB44)           ; Address pointer to start of item's data set at
  INC HL                  ; L736F
  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 LDADC              ; Fetch object state and prepare graphics for
                          ; printing
; Set properties for the new object state
  LD A,($EB8D)            ; Get first byte of object state data
  AND $F8                 ; Filter out bits 0-2 (values 0-7)
  LD C,A                  ;
  LD A,($EB4E)            ; Get the current item properties byte
  AND $1F                 ; Keep bits 0-4...
  OR $05                  ; 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 ($EB4E),A            ; ...and re-store.

; Check if Maroc has picked up (or been given) a spell or item
;
; Used by the routine at LCC27.
;
; Jump from CC3C (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 EB8E = 15 = object collection by Maroc.
LCC72:
  LD A,($EB4E)            ; Get item properties byte
  LD C,A                  ;
  AND $10                 ; Is the item carried by the servant (bit 4 set)?
  JR Z,LCC72_0            ;
  LD A,($EBB1)            ; If so, check if the servant is currently carrying
  CP $01                  ; an object
  JP NZ,LCD66_0           ; If not, jump to the next routine to check for
                          ; servant based pick-ups/interactions
LCC72_0:
  LD A,C                  ; Get item properties byte
  AND $40                 ; Bit 6 (64) = the item is collectable (e.g.
                          ; inventory object, spell)
  JP Z,LCD66_0            ; If it isn't, skip to next routine for servant
                          ; interactions
  LD C,$00                ; Collision type to check = 0 (collision with Maroc)
  CALL LDFCD              ; Check for Maroc related events/collisions to see if
  CP $00                  ; Maroc is collecting the object
  JP Z,LCD21              ; Jump to LCD21 if no events/collisions
; Maroc has picked up or been given a spell or item
  LD A,($EB4E)            ; Item properties byte
  OR $05                  ; Set bits 0 (item is visible) and 2 (item will need
                          ; to be erased before re-drawing)
  LD ($EB4E),A            ; ...and re-store
  CALL LE5FE              ; Trigger pick-up sound effect
  LD A,($EB8A)            ; Get item spell number
  CP $00                  ; If it's 0, it's not a spell, so skip the following
  JR Z,LCCDD              ; "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 LCCDD), 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 $E0                  ; -
  JR NC,LCCDD             ; -

; Maroc has picked up a spell
;
; A Spell number (from list at L6DFC)
;
; Maroc has collected a spell. Collected spells come with a random number of
; charges (between 3 and 10).
LCCA8:
  LD C,A                  ; Temp store for spell number in C register
  LD A,($EB4E)            ; Get item properties byte
  AND $10                 ; Is the item carried by the servant (i.e. the
  JR Z,LCCA8_0            ; servant has picked up the spell and moved onto
  LD A,$00                ; Maroc, rather than Maroc moving over the spell
                          ; item)?
  LD ($EBB1),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:
LCCA8_0:
  LD A,C                  ; Retrieve spell number
  LD HL,($EB65)           ; Address pointer to start of spell list at L6DFC
  LD D,$00                ;
  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 (L6DFC) so HL is
                          ; now pointing at the start of the set for this spell
  LD (HL),$10             ; 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,(LEAAA)            ; Incrementing game cycle counter (used here to
                          ; generate a pseudo-random number)
  AND $07                 ; Keep bits 0-2. This provides a random value between
                          ; 0-7
  ADD A,$03               ; 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 $FF                  ;
  JR Z,LCCA8_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 (LD331).
LCCA8_1:
  LD A,$0F
  LD ($ECA0),A            ; Initialize this counter value to 15
  JR LCCDD_2              ;

; Maroc has picked up an item
;
; Used by the routine at LCC72.
;
; There are 4 inventory slots in Maroc's backpack (7F72). However, he can only
; carry 3 objects.
;
; The 4th consecutive slot is used as an 'overflow' slot. This is checked later
; at LD90C. 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:
LCCDD:
  LD HL,($EBBC)           ; Address pointer to current slot of Maroc's
  LD A,(HL)               ; inventory at 7F72
  CP $00                  ; Empty inventory slot?
  JP NZ,LCD66_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,($EB4E)            ; Get the item properties byte
  LD C,A                  ;
  AND $10                 ; Is the item being carried by the servant (if bit 4
                          ; is set)?
  JR Z,LCCDD_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 $EF                 ; 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 ($EB4E),A            ; ...and re-store the item properties byte
  LD A,$00                ;
  LD ($EBB1),A            ; Set the 'servant-carrying-item' flag to zero
; Copy 16 bytes of the item's data from the working buffer at LEB43 into the
; inventory slot (at 7F72). 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.
LCCDD_0:
  EX DE,HL                ; Swap inventory address pointer into DE register
                          ; pair
  LD HL,LEB43             ; Start of item working data buffer
  LD BC,$0010             ;
  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 $FF                  ; Are we at the end of the 4 inventory slots?
  JR NZ,LCCDD_1           ;
  LD HL,(LEBBA)           ; If so, switch the inventory pointer back to
                          ; inventory slot 1
LCCDD_1:
  LD ($EBBC),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,($EB8A)            ; Get the spell number (normally will be 0 for
  CP $E0                  ; objects)
  JR C,LCCDD_2            ;
  SUB $F0                 ; If >=224, subtract 240 (would give a value of -16
                          ; to +15)...
  CALL LE3CC              ; ...and increase/decrease Maroc's energy accordingly
; This object has now been collected:
LCCDD_2:
  LD A,$00
  LD (LEB43),A            ; Set it's object type to 0, as it's in Maroc's
  JR LCD66_0              ; inventory and no longer in the room

; Check for an object trade with warlock
;
; Used by the routine at LCC72.
;
; First, check to see if any object has been traded (using the servant) with a
; warlock:
LCD21:
  LD A,(LEBAD)            ; Warlock 'aggression' byte - byte 6 of the warlock
  CP $00                  ; data sets at L6C7C.
  JR Z,LCD66              ; 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,($EBAE)            ; Object number held by warlock
  CP $00                  ;
  JR NZ,LCD66_0           ; If not zero, an object has (already) just been
                          ; given to the warlock, so needs to be dealt with -
                          ; skip this routine
  CALL LDFCD              ; Run an event/collision check against this warlock
                          ; (for trading an object)
  CP $00                  ; A register returned with 1 = collision, or 0 = no
                          ; collision
  JR Z,LCD66              ; If negative, skip to the next routine
; Object trade made with warlock - mark the item as no longer present:
  LD A,($EB46)            ; Get object number (relates to room object table at
                          ; L736F)
  LD ($EBAE),A            ; Copy to working data buffer
  LD A,$00                ;
  LD (LEB43),A            ; Change the object's type to 0 in the working
  LD A,($EB8B)            ; buffer, indicating it's no longer around in the
                          ; room
  LD ($EBAF),A            ; Copy attribute colour of object to working data
                          ; buffer
  LD A,($EB4E)            ; 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 ($EB4E),A            ; Re-store updated object byte
  LD HL,($EB44)           ; Move the properties byte to byte 4 of the object
  INC HL                  ; data set at L736F (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 $10                 ; Check bit 4 (16) - if set, indicates object carried
  JR Z,LCD66_0            ; by servant. Normally this will be set, but it is
                          ; possible for the servant to 'throw' the item to the
                          ; warlock
  LD A,$00                ; If the item was carried by the servant...
  LD ($EBB1),A            ; ...Set the item-carried-by-servant status byte to 0
  JR LCD66_0              ;
; There's a later check made (at LCE71) 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 LCD21.
;
; 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
LCD66:
  LD A,($EBB1)            ; Servant-object-carrying status
  CP $00                  ; 0 = servant is not carrying an object
  JR NZ,LCD66_0           ; Jump out here if the servant IS carrying an object,
                          ; as it can't carry more than one
  LD C,$05                ; Collision event value to check = 5 (servant picking
                          ; up object)
  CALL LDFCD              ; Run event/collision check
  CP $00                  ; A register returned with 0 (no collision) or 1
                          ; (collision detected)
  JR Z,LCD66_0            ; Jump out here if no event match/collision
; Servant has picked up an object:
  LD A,$01                ; Set servant object-carrying status to 1 (servant is
  LD ($EBB1),A            ; carrying an object)
  LD A,($EB4E)            ; 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 ($EB4E),A            ; ...and re-store.
; This entry point is used by the routines at LCC72, LCCDD and LCD21.
LCD66_0:
  JP LD27D                ; 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 LC89F.
;
; 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):
LCD88:
  LD A,($EC9C)            ; Check FREEZE spell timer counter
  CP $00                  ;
  JR NZ,LCD88_0           ; If it's > 0, the FREEZE spell is still in place so
                          ; skip the footsteps check
; Create short intervals between footsteps
  LD A,(LEAAA)            ; Game timer
  AND $03                 ; Check if either bit 0 or 1 are set
  JR NZ,LCD88_0           ; If so, skip the footstep sounds (this creates a
                          ; short interval in the sound, to mimic a footstep
                          ; effect)
; Check creature type (EB46). 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,($EB46)            ; Check creature type number
  CP $08                  ;
  JR C,LCD88_0            ; Creature number < 8 - warlock
  CP $0B                  ;
  JR NC,LCD88_0           ; Creature number >= 11 - a wraith or a demon
  LD A,$10                ; If the creature type is 8, 9, or 10, set the byte
  LD ($EB56),A            ; at EB56 to start with the speaker bit on (bit 4).
; Copy the 8 bytes of data for this creature type at L6C7C/6CB4 into working
; creature data buffer at LEBA5, along with a couple of other bytes:
LCD88_0:
  LD HL,($EB44)           ; Pointer to data set at L6C7C/6CB4
  LD BC,$0008             ; Copy 8 bytes to creature data buffer at LEBA5
  LD DE,LEBA5             ;
  LDIR                    ;
  LD A,(LEBA5)            ; Creature attribute/colour byte - first byte of
                          ; current creature set at 6CB4
  LD ($EAA8),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,($EB4E)            ; Item (creature) properties byte
  LD C,A                  ; Temp store in C register
  AND $E0                 ; Check top 3 bits (bits 5-7) If any of these are
                          ; set, it means the creature is disintegrating or
                          ; materializing
  JP NZ,LCF99             ; 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 $01                 ; Check bit 0 - if set, it means the creature is
                          ; on-screen/visible
  JR Z,LCDD7              ; 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,($EBA9)            ; 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 L6C7C)
  LD C,A                  ; Store in C register, which is used as the event
                          ; value to check in the following CALL
  CALL LDFCD              ; Check if Maroc has destroyed a creature with a
                          ; missile/bolt or wraithbane
  CP $00                  ; The A register is returned with 0 (no collision) or
                          ; 1 (positive collision detected)
  JP NZ,LD07C             ; 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,($EBAA)            ; Otherwise get event/collision value for for
                          ; creatures opening/closing doors (17)
  CALL LE2B0              ; ...and add this to the collision/event set in the
                          ; table at 7FB3 ready for checking next game cycle

; Change creature behaviour based on Maroc's magic
;
; Used by the routine at LCD88.
;
; 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 LEAAA.
LCDD7:
  LD A,($EB46)            ; Creature type
  CP $08                  ; Guardian of Chaos
  JP Z,LCF0B              ;
  JP C,LCE71              ; 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 $0B                  ; Wraith
  JR Z,LCDD7_1            ;
  CP $09                  ; Goblin warrior
  JP Z,LCF3E              ;
  CP $0C                  ; Demon
  JP Z,LCDD7_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,($EB4E)            ; Creature properties byte
  AND $01                 ;
  JP Z,LCF0B              ; If creature is off screen, check if its movement
                          ; needs to be changed due to the UNSEEN spell being
                          ; active
  LD A,($EB50)            ; Creature is on-screen. Get graphic frame number
                          ; offset
  AND $07                 ; Keep bits 0-2
  CP $03                  ; Is the graphic frame #3?
  JR NZ,LCDD7_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,($EAE9)            ; Currently active spell
  CP $09                  ; Check if the UNSEEN spell is active
  JR Z,LCDD7_0            ; Jump to LCDD7_0 if UNSEEN is active
  LD A,($EC9C)            ; Check FREEZE spell timer counter
  CP $00                  ;
  JR NZ,LCDD7_0           ; If counter is > 0, FREEZE spell is active - jump to
                          ; LCDD7_0
  JP LCF58                ; Neither FREEZE or UNSEEN is active so initialize a
                          ; missile
; UNSEEN or FREEZE spell is active
LCDD7_0:
  LD A,(LEAAA)            ; Game cycle counter
  AND $0F                 ; Check bits 0-3
  JP Z,LCF0B              ; Every 16th game cycle check the UNSEEN spell and
  CP $0C                  ; alter the creature's movement accordingly
  JR Z,LCDD7_2            ; On each game cycle #12 (of 16) randomize the
  CP $00                  ; creature's movement
  JP NZ,LD04B             ;
  LD A,$00                ; On every 16th game cycle, stop moving:
  LD ($EB4C),A            ; Set horizontal movement speed/direction to zero
  LD ($EB4D),A            ; Set vertical movement speed/direction to zero
  JP LD04B                ;
; Jump here from LCDD7 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)
LCDD7_1:
  LD A,($EAEC)            ; Get activated spell
  CP $04                  ; If spell number >=4, jump to LCF0B_0
  JP NC,LCF0B_0           ;
  LD A,($EAE9)            ; Check for currently active effect spells
  CP $09                  ;
  JP Z,LCF0B_0            ; If UNSEEN spell is active, jump to LCF0B_0
  LD A,(LEAAA)            ; Game cycle counter
  AND $1F                 ; Check if any bits 0-4 set
  CP $00                  ;
  JR NZ,LCDD7_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,($EB46)            ; Check if creature is type number #12 (demon)
  CP $0C                  ;
  JP Z,LCF58              ; 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 (LCF3E)
; * Goblin missile thrower, every 16 game cycles
; * Guardian of Chaos if the UNSEEN spell is active LCF0B
; * Wraith, every 32 game cycles
LCDD7_2:
  CALL LDB06              ; Generate pseudo-random number
  LD C,A                  ; Temp store in C register
  AND $0F                 ; Only need bits 0-3 (values 0-15)
  SUB $07                 ; 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 ($EB4C),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 $0F                 ; Keep bits 0-3 (values 0-15)
  SUB $07                 ; Subtract 7, so values now between -7 and +8
  LD ($EB4D),A            ; Store as creature's vertical speed (negative
  JP LD04B                ; numbers = up, positive = down)
; WRAITH or DEMON movement - continued from CE45
LCDD7_3:
  AND $07                 ; (Game timer counter) - check bits 0-2
  JP NZ,LD04B             ;
  JP LCF0B_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 LCDD7.
;
LCE71:
  LD A,($EBAE)            ; Object number (if any) from table at L736F that has
                          ; been offered to the warlock
  LD D,A                  ; Temp store in D register
  CP $00                  ;
  JR Z,LCED4              ; 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,($EB46)            ; Warlock number (1-7) - table at L6C7C
  LD C,A                  ; Temp store in C register
  LD A,($EBAF)            ; 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 $07                 ; 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,LCEB1              ; 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,($EBA8)            ; Number of item held by warlock (from table at
  LD ($EBAE),A            ; L736F)
  LD A,D                  ; Retrieve the object number (from table at L736F)
                          ; that Maroc has offered
  LD ($EBA8),A            ; ...and store in the warlock's working data buffer
  LD HL,($EB44)           ; Address pointer to warlock data set in table at
  INC HL                  ; L6C7C
  INC HL                  ;
  INC HL                  ;
  LD (HL),A               ; ...and store this object number as the warlock's
                          ; held object
  LD A,($EB4E)            ; 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 ($EB4E),A            ; ...and restore properties byte
  LD A,$01                ; Graphics frame offset (1 = no offset)
  LD ($EB50),A            ;
  LD A,$5B                ; Graphics address for materialization graphics at
                          ; 9877
  CALL LE0C2              ; Set up graphics
  JP LD27D                ;

; Maroc has offered an object of insufficient value to a warlock
;
; Used by the routine at LCE71.
;
; If an item is not of interest to a warlock (checked in the routine at CE79):
; * 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)
LCEB1:
  LD C,D                  ; Retrieve the object number (from table at L736F)
                          ; that Maroc has offered
  LD B,$00                ; 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,($DAF3)           ; Address pointer to the start of the room object
  LD A,$00                ; data sets at L736F
  LD ($EB84),A            ; Set the data set counter to zero for the next CALL
  CALL LDE4C              ; This routine finds an object's data set (in table
                          ; at L736F), and copies its data into the object data
                          ; buffer at EB85.
; Teleport the rejected item to current-room-number-plus-three
  LD A,($EAB7)            ; Current room number
  LD C,A                  ;
  ADD A,$03               ; Add 3 to it
  LD HL,(LEB82)           ; 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),$1A             ; 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,$00
  LD ($EBAE),A            ; Set the object-number-held-by-warlock byte to 0, as
                          ; the offered item has just been teleported to a
                          ; different room
  JP LCF58                ; ...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 LCE71.
;
; If Maroc tries to trade an item of insufficient value with a warlock
; (determined at LCEB1), 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 L6C7C 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.
LCED4:
  LD A,($EB4E)            ; Item (warlock) properties byte
  AND $01                 ; Check bit 0 (set if the warlock is visible
  JR NZ,LCED4_0           ; on-screen)
; Warlock has gone off-screen
  LD A,$00
  LD (LEB43),A            ; Set type of graphic to draw to 0 (nothing to draw)
  LD A,$90                ;
  LD ($EBB4),A            ; Timer indicating how long before a warlock is
                          ; likely to materialize in the current room - set
                          ; this to 144
  LD ($EBB5),A            ; Timer indicating how long before a creature is
                          ; likely to wander in from an adjacent room - also
                          ; set this for 144
  JP LCF99_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 LCF3E, where Maroc
; wielding powerful magic has an effect on creature movement/actions. But these
; instructions are never run.
  LD A,($EAEC)            ; -
  CP $04                  ; -
  JR NC,LCF58             ; -
  JR LCED4_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.
LCED4_0:
  LD A,(LEAAA)            ; Game cycle counter
  AND $1F                 ; Check bits 0-4 (1-31)
  JR NZ,LCED4_1           ; If any are set, skip over this routine
; Generate a random number and compare it with this warlock's 'aggression'
; stat...
  CALL LDB06              ; Generate random number (returned in A register)
  LD C,A                  ; Store in C register
  LD A,(LEBAD)            ; Byte 6 from warlock's data set at L6C7C 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,LCED4_1            ; If it's < the random number, don't fire a missile
  JR LCF58                ; If it's >= random number, set up a missile to fire
                          ; (LCF58)
LCED4_1:
  JP LD04B                ; Jump to creature collision detection routine

; UNSEEN spell effect on creature movement
;
; Used by the routines at LCDD7 and LCF3E.
;
; 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 LCDD7_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:
LCF0B:
  LD A,($EAE9)            ; Currently active spell
  CP $09                  ; ...Is it the UNSEEN spell?
  JR NZ,LCF0B_0           ;
  LD A,(LEAAA)            ; If so get the incremental game counter
  AND $0F                 ; Check if any of bits 0-3 set
  JP NZ,LCDD7_2           ; If so, randomize the movement pattern
  JP LD04B                ; Switch back to normal movement every 16 frames
; Jump here from LCDD7_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:
LCF0B_0:
  LD A,($EB4A)            ; Retrieve vertical position within current room, in
                          ; pixels, from top of room playing area
  LD C,A                  ; Store in C register
  LD A,($EAC1)            ; 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 $07                 ; Value will now either be 7 or -7 (248)
  LD ($EB4D),A            ; Set as creature's vertical movement speed/direction
; Calculate horizontal position in relation to Maroc:
  LD A,($EB48)            ; Retrieve horizontal position within current room,
  LD C,A                  ; in 4-pixel/half-character steps
  LD A,($EAC0)            ; 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 $07                 ; Value will now either be 7 or -7 (248)
  LD ($EB4C),A            ; Store as creature's horizontal movement
  JP LD04B                ; speed/direction

; Goblin warrior - check if movement is affected by Maroc's magic power
;
; Used by the routine at LCDD7.
;
; 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.
LCF3E:
  LD A,($EB4E)            ; (Creature) properties byte
  AND $01                 ; Bit 0 (1) indicates whether the creature is visible
                          ; on-screen
  JR Z,LCF0B              ; If not, don't need to do anything to change the
                          ; creature's movement (yet)
  LD A,($EAEC)            ; Get the currently active spell
  CP $05                  ; Check if spell number >=5
  JP NC,LCDD7_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,(LEAAA)            ; Game timer/counter
  AND $07                 ; Check bits 0-2 (values 0-7)
  JP Z,LCF0B              ; If zero, it's an 8th game cycle so change vertical
                          ; direction
  JP LD04B                ; ...Otherwise continue in same direction

; Initialize missile/bolt fired by a creature
;
; Used by the routines at LCDD7, LCEB1 and LCED4.
;
; Set up a missile/bolt fired by a warlock, demon, or goblin missile thrower.
LCF58:
  LD A,($EBA7)            ; Type of missile fired by this creature
  CP $00                  ; 0 = No missile fired
  JP Z,LD04B              ; Jump out if so
  LD C,A                  ; Store missile type in C register
  LD A,(LEB91)            ; Creature missile count. 0 = no creature-fired
                          ; missiles currently on screen, 1 = there is one
  CP $00                  ; Is there a creature-fired missile already on
                          ; screen?
  JP NZ,LD04B             ; 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 (LEB91),A            ;
  LD A,C                  ;
  LD ($EB93),A            ; Store missile number/type
  LD A,$05                ;
  LD ($EB9A),A            ; 5 = Object type - missile fired by creature (at
                          ; Maroc)
  LD HL,($EB47)           ; Copy horizontal co-ordinate into data buffer
  LD ($EB94),HL           ; The creature's co-ordinates will be the origin
  LD HL,($EB49)           ; point
  LD ($EB96),HL           ; Do the same for the vertical co-ordinate
  LD A,($EAC1)            ; Maroc's vertical (Y-axis) screen position
  LD ($EB99),A            ; Set as vertical screen position of target
  LD A,($EAC0)            ; Maroc's horizontal (X-axis) screen position
  LD ($EB98),A            ; Set as horizontal screen position of target
  LD A,$00                ;
  LD ($EB4C),A            ; Set vertical movement speed to zero
  LD ($EB4D),A            ; Set horizontal movement speed to zero (these two
  JP LD04B                ; values will need to be calculated later)

; Warlock or creature - materialization & disintegration events
;
; Used by the routine at LCD88.
;
; 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
; (EB4E).
LCF99:
  LD A,($EB50)            ; Graphic frame number/offset
  AND $07                 ; Only bits 0-2 (values 0-7) needed for the number of
                          ; frames
  CP $07                  ; There are 6 animation frames in the materialization
                          ; graphics (LA847). Have we reached frame #7?
  JP NZ,LD27D             ; If not, jump out of routine at this point
; Final materialization/disintegration frame has been reached.
  LD A,($EB4E)            ; Creature/room item properties byte
  LD C,A                  ; Temp store in C register
  AND $07                 ; Filter out/resets bits 4-7
  OR $05                  ; Set bits 0 (indicating creature is on-screen) and 2
                          ; (indicating creature will need to be erased before
                          ; drawing)
  LD ($EB4E),A            ; ...and re-store.
; This routine is running because bit 5, 6 or 7 of the item (creature)
; properties byte (EB4E) 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 $80                 ; Bit 7 of properties byte set = trigger
  JR NZ,LCF99_0           ; WARLOCK/DEMON APPEARANCE after materialization
  LD A,C                  ; animation is complete
  AND $40                 ; Bit 6 of properties byte set = trigger warlock
  JR NZ,LCF99_1           ; DISAPPEARANCE post-materialization animation (CE89)
                          ; - e.g. successful object trade
  JR LCF99_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:
LCF99_0:
  LD A,$01                ; Set graphic frame number/offset at 1 (first
  LD ($EB50),A            ; frame/no frame offset)
  LD A,($EBAB)            ; Graphic number (offset for address pointers in
                          ; table at L97C3)
  CALL LE0C2              ; Set up creature graphics
  JP LD27D                ;
; Warlock has been successfully traded with - remove warlock and initialize
; object trade
LCF99_1:
  LD A,$00                ; Set creature type to 0 (nothing to setup/draw)
  LD (LEB43),A            ;
  LD A,$E0                ; Timer indicating how long before a warlock is
                          ; likely to materialize in the current room
  LD ($EBB4),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:
LCF99_2:
  LD A,$00
  LD (LEBAD),A            ; Set warlock 'aggression' (likelihood of firing a
                          ; missile at Maroc) to 0 (as it's gone)
  LD A,($EBB6)            ; Count of creatures in current room
  DEC A                   ; ...reduce by 1...
  LD ($EBB6),A            ; ...and re-store.
  LD A,($EBAE)            ; Check if the warlock is carrying an object
  CP $00                  ;
  JP Z,LD27D              ;
  LD ($EB46),A            ; ...If so, copy the item set number into the
  LD A,$00                ; warlock's data set
  LD ($EBAE),A            ; ...and set the held item data buffer byte to 0
  JR LD019                ; ...then skip over to the next routine
; Creature has been destroyed - remove from existence:
LCF99_3:
  LD A,$00
  LD (LEB43),A            ; Set creature type to 0 (no creature to deal with
                          ; any more)
  LD HL,($EB44)           ; Get address pointer to relevant creature/warlock
  INC HL                  ; data set at L6C7C
  INC (HL)                ; Increment the second byte of the set. This byte
                          ; holds the number of these creatures Maroc has
                          ; destroyed
  LD A,($EBB6)            ; Reduce count of creatures in current room by 1
  DEC A                   ;
  LD ($EBB6),A            ; Get creature type
  LD A,($EB46)            ;
  CP $08                  ;
  JP NC,LD27D             ; If creature >=8, it's not a warlock so jump out of
                          ; the routine here
  LD A,$00                ; Creature destroyed is a warlock. Set warlock
  LD (LEBAD),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,($EBA8)            ; Get object number carried by the warlock
  CP $00                  ;
  LD ($EB46),A            ; ...Copy this value into the warlock's data buffer
  JP Z,LD27D              ; If the warlock isn't carrying anything, can jump
                          ; out at this point

; Warlock - drop carried object
;
; Used by the routine at LCF99.
;
; 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.
LD019:
  LD A,$00
  LD ($EACF),A            ; Set the draw/erase flag to 0 (ERASE)
  CALL LE3FD              ; Reset screen attribute colours for warlock
  LD A,$04                ;
  LD (LEB43),A            ; Set the (new) object type to 4 = interactable
                          ; object
  LD B,$00                ; The CALL in a few instruction to LDE4C 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,($EB46)            ; Get object number
  LD C,A                  ; Store in C register
  LD HL,($DAF3)           ; Address pointer to the room object data sets in
  LD A,$00                ; table at L736F
  LD ($EB84),A            ; Set the counter for the room object tables to 0
  CALL LDE4C              ; Identify object, and copy its data into the object
                          ; data set buffer at EB85
  LD HL,(LEB82)           ; Get address pointer to item's data set in table at
                          ; L736F
  LD ($EB44),HL           ; ...store in item data buffer
  LD A,($EB88)            ; 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 ($EB4E),A            ; Store as item properties byte
  CALL LDADC              ; Fetch object state and prepare graphics for
  JP LD27D                ; printing

; Creature collision check with room boundary and Maroc
;
; Used by the routines at LCDD7, LCED4, LCF0B, LCF3E and LCF58.
;
; Check if a creature has collided with a room boundary or Maroc:
; * Uses the generic room boundary check routine at LE039 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 6CB4)
; * If the creature is a WRAITH, check if the WRAITHBANE spell is active & if
;   so destroy the wraith
LD04B:
  LD A,($EC9C)            ; FREEZE spell timer counter (> 0 means the FREEZE
  CP $00                  ; spell is in effect)
  JR NZ,LD07C_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,($EB4A)            ; Creature's vertical pixel position in room
  ADD A,$08               ; 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 LE039              ; Run room boundary checks for creature, adjusting
                          ; position accordingly if needed
; Check collision detection with Maroc
  LD C,$00                ; Collision event type 0 = collision with Maroc
  CALL LDFCD              ; Run collision check
  CP $00                  ; The A register is returned with 1 = collision, or 0
                          ; = no collision
  JP Z,LD27D              ; 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 LD04B has confirmed a creature has collided with
; Maroc.
LD065:
  LD A,($EB46)            ; Check if creature is a WRAITH
  CP $0B                  ;
  JR NZ,LD065_0           ; If not, skip next check
; WRAITHS are destroyed if they collide with Maroc when WRAITHBANE is active
  LD A,($EAE9)            ; Creature is a wraith
  CP $14                  ; Does Maroc have the WRAITHBANE spell active?
  JP Z,LD07C              ; If so, destroy wraith
; Creature is touching Maroc - drain his energy by the amount of damage that
; this type of creature does.
LD065_0:
  LD A,($EBAC)            ; Amount of damage this creature does to Maroc's
                          ; energy bar (see Reference - Creatures)
  CALL LE3CC              ; Decrease Maroc's energy
  JR LD07C_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 LCD88 and LD065.
;
; Creature has been hit by Maroc's missile/bolt/weapon, or wraith has collided
; with Maroc when he is protected by WRAITHBANE.
LD07C:
  LD A,($EB4E)            ; 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 ($EB4E),A            ; ...and re-store
  LD A,$01                ; Set graphic frame offset to 1 (no offset)
  LD ($EB50),A            ;
  LD A,$62                ; Address pointer number to disintegration effect
                          ; graphics (9885)
  CALL LE0C2              ; Set up graphics
; Continued from above (disintegrating creature), and also from LD065_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.
LD07C_0:
  LD A,$00
  LD ($EB4C),A            ; Set horizontal movement speed/direction to 0
  LD ($EB4D),A            ; Set vertical movement speed/direction to 0
  JP LD27D                ;

; Missile fired by Maroc or a creature - check for active shield/barrier spells
;
; Used by the routine at LC89F.
;
; ...There's a missile/bolt flying around in the room..!
;
; This routine copies the missile's data from the table at L6CDC into a working
; (missile) buffer at EB9D.
;
; It also checks if Maroc has a counter defence spell active (SHIELD, DEFENCE
; etc.)
; * Each missile type (at L6CDC) 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 EBA1, EBA3 and EBA4)
;   match the currently active defensive barrier spell type
; * If there's a match, a special missile/barrier collision routine (LE286) is
;   CALLed
LD09B:
  LD A,($EB4E)            ; Missile properties byte
  AND $01                 ; Check if it's is on-screen (bit 1 is set)
  JP Z,LD12E_0            ; ...if not, skip out to a later instruction
  LD HL,($EB44)           ; Get address pointer to missile type (in table at
                          ; L6CDC)
  LD BC,$0008             ; Copy the 8 bytes of missile data into missile
  LD DE,$EB9D             ; working buffer table at EB9D
  LDIR                    ;
  LD A,($EB9F)            ; Missile attribute (INK) colour
  LD ($EAA8),A            ; Copy into item data buffer
  LD A,($EBA0)            ; Missile's event/collision type to check (stored as
  CP $00                  ; the 4th byte in the missile/bolt table at L6CDC)
  JR Z,LD09B_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 LE2B0              ; ...If it's not zero, copy item event data into
                          ; working buffer
; COUNTER SPELL #1 CHECK
LD09B_0:
  LD A,($EAE9)            ; Get currently active 'effect' spell (value = 0 if
                          ; none currently in effect)
  LD C,A                  ; Copy to C register
  LD A,($EBA1)            ; Defence counter spell #1 (the spell in this slot is
  CP $00                  ; always AMULET)
  JR Z,LD09B_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,LD09B_3            ; If there's a match, can skip the next two checks
                          ; straight to LD09B_3
; COUNTER SPELL #2 CHECK
LD09B_1:
  LD A,($EBA3)            ; Defence counter spell #2
  CP $00                  ; Check for zero - if no counter spell in this slot
  JR Z,LD09B_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,LD09B_3            ; If there's a match, can skip the final check and
                          ; jump straight to LD09B_3
; COUNTER SPELL #2 CHECK
LD09B_2:
  LD A,($EBA4)            ; Defence counter spell #3
  CP $00                  ; heck for zero - if no counter spell in this slot
  JR Z,LD116              ; (shouldn't happen as there's a value for every
                          ; counter slot)
  CP C                    ; Check counter spell vs current active spell number
  JR NZ,LD116             ; 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
LD09B_3:
  CP C                    ; -
  JR NZ,LD116             ; -
; 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,$01                ; For the usual collision/event detection routine
                          ; (LDFCD) 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 LE286              ; Check for a collision between the fired
                          ; bolt/missile and the shield/barrier around Maroc
  CP $00                  ; 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,LD116              ; 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:
LD0EC:
  LD A,($EAC0)            ; Maroc's horizontal (X-axis) screen position, in
  LD C,A                  ; 4-pixel/half-character steps
  LD A,($EB48)            ; 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 $0F                 ; Based on direction, sets the above calculated value
  LD C,A                  ; at 240 (-15) or +15
  LD A,($EB4C)            ; Get the missile's existing horizontal movement
                          ; speed
  ADD A,C                 ; Add the calculated value (+/- 15)
  LD ($EB4C),A            ; ...and re-store.
; Calculate the missile's new vertical trajectory
  LD A,($EAC1)            ; Maroc's vertical (Y-axis) pixel screen position
  LD C,A                  ; Missile's vertical (X-axis) pixel screen position
  LD A,($EB4A)            ;
  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 $0F                 ; Based on direction, sets the above calculated value
  LD C,A                  ; at 240 (-15) or +15
  LD A,($EB4D)            ; Get the missile's existing vertical movement speed
  ADD A,C                 ; Add the calculated value (+/- 15)
  LD ($EB4D),A            ; ...and re-store.
  JR LD12E                ;

; Check if a missile fired by a creature has hit Maroc, and if so reduce his
; energy
;
; Follows 'missile deflection' checks at LD09B that checks for collision with
; an effective shield spell
;
; Check if it's a creature-launched missile, or a Maroc-launched missile:
LD116:
  LD A,(LEB43)            ; Object type
  CP $08                  ; Object type 8 = Missile fired by Maroc
  JR Z,LD12E              ; If it's one of Maroc's missiles, skip the next
                          ; check
  LD C,$00                ; Collision type to check = 0 (collision with Maroc)
  CALL LDFCD              ; Call collision check routine
  CP $00                  ;
  JR Z,LD12E              ; 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
; LD09B 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,($EBA2)            ; Value to decrease Maroc's energy by (varies by
                          ; missile type)
  CALL LE3CC              ; Decrease Maroc's energy
  JR LD12E_0              ;

; Check missile room boundary collisions and on-screen lifespan
;
; Used by the routines at LD0EC and LD116.
;
; No collision between a creature missile and Maroc (jump from D124), or the
; missile has been fired by Maroc (jump from D11B)
;
; Missiles hitting a wall will bounce off like any other room objects.
;
; Check for collisions with room walls:
LD12E:
  CALL LDAC8              ; 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 LE039              ; 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 L6CDC holds this information.
;
; Reduce this missile's timer, and make it disappear if its timer has run out.
  LD A,($EB4E)            ; 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 $10                 ; Reduce the time/distance of this value by 16
  JR C,LD12E_0            ; (initial values are between 144 and 240)
  LD ($EB4E),A            ; If the missile is still with us, jump out to the
  JP LD27D                ; next routine
; Jump here from D0A0 if missile is off-screen, or the missile's lifespan has
; finished/fizzled out
LD12E_0:
  LD A,(LEB43)            ; Object type
  CP $05                  ; Type 5 = Missile fired by a creature/warlock
  JR Z,LD12E_1            ;
  LD HL,$EB92             ; Missile fired by Maroc
  JR LD12E_2              ;
LD12E_1:
  LD HL,LEB91             ; Missile fired by creature/warlock
; HL now contains:
; * LEB91 if missile fired by creature/warlock
; * EB92 if missile fired by Maroc
LD12E_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,$00
  LD (LEB43),A            ; Missile has fizzled out, so set item type to 0
  LD A,($EB4E)            ; Get item properties byte
  OR $04                  ; Set bit 2 (4) - this indicates the graphic will
                          ; need erasing
  LD ($EB4E),A            ; ...and re-store.
  JP LD27D                ;

; Copy co-ordinates of room's left/right wall connector sections to working
; buffer
;
; Used by the routine at LC89F.
;
; 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)
LD161:
  LD A,($EB4A)            ; Graphic vertical pixel position
  LD ($EAFA),A            ; Store as LEFT connector value
  LD A,($EB48)            ; Graphic horizontal position, in
  LD ($EAFB),A            ; 4-pixel/half-character steps
  JP LD27D                ;
; Vertical back wall/floor connector (right) - Have already identified vertical
; position from left connector, as it's the same
LD161_0:
  LD A,($EB48)            ; Graphic horizontal position, in
                          ; 4-pixel/half-character steps
  LD ($EAFC),A            ; Store as RIGHT connector value
  JP LD27D

; Tunnel position & direction
;
; Used by the routine at LC89F.
;
; The first byte in the data sets (7C00) 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.
LD179:
  LD A,$00
  LD ($EB4A),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,(LEAAA)            ; Get incremental game timer
  AND $0F                 ; Check if any of bits 0-3 are set
  JR NZ,LD179_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,($EB7D)            ; Get tunnel length counter (first byte of tunnel
                          ; data sets at L6710 multiplied by 2)
  DEC A                   ; ...decrement it..
  LD ($EB7D),A            ; ...and re-store
  JR NZ,LD179_0           ; Interval check - has Maroc reached the end of the
                          ; tunnel?
  LD A,$FF                ; ...If so, set the 'end-of-tunnel' byte accordingly
  LD ($EAB0),A            ; - this is checked at LDA0A_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.
LD179_0:
  LD HL,($EB44)           ; Value used to address various ROM locations to
                          ; generate pseudo-random numbers for tunnels
  INC HL                  ; Move to the next ROM address
  LD ($EB44),HL           ; ..and re-store pointer
  LD A,(HL)               ; Get byte from ROM address
  AND $3F                 ; Keep a range of 0-63
  SUB $1F                 ; Subtract 31, giving a value of +32 to -31
  LD C,A                  ; Put in C register
  LD A,($EB4C)            ; Get the current horizontal offset byte
  ADD A,C                 ; Add or subtract the direction change offset (+32 to
                          ; +31)
  CP $80                  ; Check if byte value is >= 128 (bit 7 set)
  JR NC,LD179_1           ;
  CP $20                  ; If not, check if byte value >= 32
  JR NC,LD179_3           ; If so, it's outside the threshold so jump straight
  JR LD179_2              ; to LD179_3 (don't change horizontal offset value)
LD179_1:
  CP $E0                  ; Byte value is > 128 so check if value < 224
  JR C,LD179_3            ; If so, it's outside the threshold so jump straight
                          ; to LD179_3 (don't change horizontal offset value)
LD179_2:
  LD ($EB4C),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:
LD179_3:
  LD A,($EB48)            ; Horizontal position (in 4-pixel/half-character
                          ; steps)
  LD ($EC9E),A            ; Copy to item horizontal position data store
  LD C,A                  ; Temp store in C
  SUB $10                 ; If we subtract 16...
  CP $20                  ; ...and check against 32...
  JR C,LD179_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,$1C                ; 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 ($EB4C),A            ; Re-store as the new horizontal position
  NEG                     ; Maroc's offset is the opposite of the scenery
  LD ($EB04),A            ; ...So store the negative of this value for his
LD179_4:
  JP LD27D                ; horizontal offset.

; Check tunnel item type for collision checks and movement (boundary, bats and
; spiders)
;
; Used by the routine at LC89F.
;
; 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
LD1D2:
  LD A,($EB4E)            ; Object properties byte
  AND $01                 ; Bit 1 indicates if the item is visible on-screen
  JR Z,LD21B              ; If not, skip the rest of this routine
; Check what tunnel object we're dealing with:
  LD A,($EB46)            ; Tunnel boundary wall type. 1 = right, 2 = left
  CP $01                  ;
  JR Z,LD23B              ; Right boundary wall check
  CP $02                  ;
  JR Z,LD23B_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,$02                ; Set the counter/length/frequency used for the
  LD ($EB56),A            ; generic sound effect routine at LC07A as spiders
                          ; and bats make a scuttling/flapping sound as they
                          ; move down the tunnel
  LD C,$00                ; Collision/event type to check - 0 = Collision with
                          ; Maroc
  CALL LDFCD              ; Run event/collision check
  CP $00                  ; The A register is returned with 1 = Collision, 0 =
  JR Z,LD1D2_0            ; No collision
  LD A,$10                ; If there's a collision...
  CALL LE3CC              ; ...Reduce Maroc's energy (by 16)
; Creature movement
LD1D2_0:
  LD A,($EB46)            ; Creature type. 4 = Spider, 8 = Bat
  CP $08                  ; Is it a bat?
  JP NZ,LD27D             ; 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.
LD1FF:
  LD A,($EB4D)            ; Vertical movement speed (negative = up, positive =
                          ; down)
  ADD A,$F6               ; 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 ($EB4D),A            ; ...And re-store
  LD A,($EB48)            ; Graphic's horizontal position, in half character (4
  LD C,A                  ; pixel) steps
  LD A,$1C                ;
  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,($EB4C)            ; Horizontal movement speed (negative = left,
                          ; positive = right)
  ADD A,C                 ; Add the calculated speed to this
  LD ($EB4C),A            ; ...and re-store
  JP LD27D                ;

; Tunnel item (boundary or bat/spider) has gone off-screen - reduce on-screen
; item count
;
; Used by the routine at LD1D2.
;
; Helps keep track and limit the number of graphic items on-screen during the
; tunnel sections. Jump from D1D7 if tunnel item is no longer visible
; on-screen.
LD21B:
  LD A,$00
  LD (LEB43),A            ; Set type of graphic to draw to 0
  LD A,($EB46)            ;
  CP $03                  ; Check if tunnel item type < 3
  JR NC,LD21B_0           ;
; If so, it's a left/right boundary graphic that's now gone off-screen
  LD A,($EB7E)            ; Byte holding the number of boundary wall graphics
                          ; currently on screen. This number is checked &
                          ; limited (to 20) at D6E3.
  DEC A                   ; Decrement this counter, as there's now one less...
  LD ($EB7E),A            ; ...and re-store.
  JP LD27D                ;
; Creature has gone off-screen
LD21B_0:
  LD A,($EC9D)            ; Counter for number of creatures currently on-screen
                          ; (max 3)
  DEC A                   ; Decrement number...
  LD ($EC9D),A            ; ...and re-store
  JP LD27D                ;

; Tunnels - check if Maroc has hit a left/right boundary wall
;
; Used by the routine at LD1D2.
;
; 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
; (LD23B_0) or right (LD23B) boundary (determined at D1D9).
;
; RIGHT boundary wall check - compare boundary wall position against Maroc's
; position
;
; Vertical position check:
LD23B:
  LD A,($EB4A)            ; Boundary wall's vertical (pixel) position
  SUB $50                 ; Subtract 80 (pixels) from this value
  CP $10                  ;
  JP NC,LD27D             ; If the difference is >=16, it's NOT within Maroc's
                          ; vertical 'hit box' area (jump out here)
; Horizontal position check:
  LD A,($EB48)            ; Boundary wall's horizontal (half-character/4-pixel)
                          ; position
  CP $20                  ; Check vs 32 (= 16 character squares = the right
                          ; hand side of Maroc's sprite graphic)
  JR NC,LD23B_2           ; If no carry (NC), Maroc ISN'T beyond the tunnel
                          ; boundary, so can jump out here
  LD A,$20                ; Maroc has hit/passed the boundary wall.Pre-load the
  JR LD23B_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:
LD23B_0:
  LD A,($EB4A)            ; Boundary wall's vertical (pixel) position
  SUB $50                 ; Subtract 80 (pixels) from this value
  CP $10                  ;
  JP NC,LD27D             ; If the difference is >=16, it's not within Maroc's
                          ; vertical 'hit box' area (jump out here)
; Horizontal position check:
  LD A,($EB48)            ; Boundary wall's horizontal (half-character/4-pixel)
                          ; position
  CP $18                  ; Check vs 24 ( = 12 character squares = the left
                          ; hand side of Maroc's sprite graphic)
  JR C,LD23B_2            ; If there's a carry, Maroc ISN'T beyond the tunnel
                          ; boundary, so jump out here
  LD A,$E0                ; 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
LD23B_1:
  LD ($EB04),A            ; Store Maroc's adjusted speed (after bouncing off
                          ; either wall)
  LD A,$01                ; Set energy drain amount to 1
  CALL LE3CC              ; Decrease Maroc's energy
LD23B_2:
  JP LD27D                ;

; Start of setting up room routine
;
; Used by the routine at LC89F.
;
; Jump here from the check at C8D6 if the room item type (LEB43) = 32.
;
; Item type 32 is always the first data set in the room data sets (at 7C00). It
; holds the position of the 'viewport' of the room, which is used to adjust
; room item co-ordinates.
LD26E:
  LD HL,($EB49)           ; Overflow/precision byte for vertical position of
                          ; room viewport - EB49 > EAF6
  LD ($EAF6),HL           ; Copy into game buffer
  LD HL,($EB47)           ; Overflow/precision byte for horizontal position of
                          ; room viewport - EB47 > EAF8
  LD ($EAF8),HL           ; Copy into game buffer
  JP LD325                ;

; Drawing checks and routines for all on-screen room items
;
; Used by the routines at LC89F, LC8DC, LC99B, LCAB4, LCD66, LCE71, LCF99,
; LD019, LD04B, LD07C, LD12E, LD161, LD179, LD1D2, LD1FF, LD21B and LD23B.
;
; 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 LE3FD
;   and LDB98)
LD27D:
  LD A,($EB4E)            ; Item properties byte
  LD C,A                  ;
  AND $07                 ; Just the lowest 3 bits (bits 0-2) needed for this
                          ; check
  CP $05                  ; Bit 0 (1) = the item is on screen, bit 2 (4) = the
                          ; item will need erasing
  JR NZ,LD27D_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,$00                ; Set the draw/erase flag to 0 (ERASE)
  LD ($EACF),A            ;
  LD HL,($EACD)           ; Get address pointer for the item graphic to erase
  CALL LDB98              ; ...And erase the graphic
  LD A,($EAA8)            ; Get INK colour of room item/object
  CP $00                  ; If it's zero, it's an erased scenery room item
  JR Z,LD27D_0            ; (rather than a differently coloured object), so
                          ; there's no need to specially print
                          ; colours/attributes for it
  CALL LE3FD              ; Otherwise, will need to set the screen
                          ; attributes/colours for the object
LD27D_0:
  LD A,($EAD5)            ; 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,($EB4E)            ; Get item properties byte
  AND $FE                 ; 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 ($EB4E),A            ; ...and re-store
  LD C,A                  ; Copy the item properties byte (EB4E) into the C
                          ; register
; Check if the item needs drawing
LD27D_1:
  LD A,(LEB43)            ; Type of graphic to draw
  CP $00                  ;
  JR Z,LD325              ; 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 $05                 ; Check for bit 0 (item is visible) and bit 2 (item
                          ; has moved/needs erasing)
  JR Z,LD325              ; If neither is set, there's nothing to draw, so skip
                          ; the rest of the routine
; Set up item for drawing
  LD A,($EB4A)            ; Graphic vertical position within current room, in
                          ; pixels, from top of room playing area
  LD ($EAD2),A            ; Copy to working graphics data buffer
  LD HL,(LEACB)           ; Graphic's horizontal position, in pixels
  LD ($EAD3),HL           ; Copy to working graphics data buffer
  LD A,($EB4B)            ; Room type byte - this is set to 64 for 'standard'
                          ; rooms, or 254/255 for tunnel rooms
  LD ($EAD6),A            ; Copy to working graphics data buffer
  LD A,$01                ;
  LD ($EACF),A            ; Set draw/erase flag to 1 (DRAW)
  LD A,C                  ; Retrieve item properties byte from C register
  AND $02                 ; Bit 1 (2) if set means item is hidden/not-visible,
  JR Z,LD27D_2            ; e.g. inside a chest
  LD HL,($EAF3)           ; If this is the case, set the graphics address
                          ; pointer to the 'dummy' graphic (98B9), so that
                          ; nothing actually gets drawn
  JR LD27D_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
LD27D_2:
  LD A,($EAA8)            ; Get item colour byte
  CP $00                  ; 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,LD27D_5            ; If it's set to 0, don't need to print any colours
  CP $08                  ; Is the value 7 or less ('standard' INK colours)
  JR C,LD27D_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,(LEAAA)            ; Get game counter/timer
  AND $03                 ; Keep just bits 0 and 1 (values = 0-3)
  ADD A,$04               ; Add 4, to give an INK value between 4 (green) and 7
                          ; (white)
; Set object colour:
LD27D_3:
  AND $07                 ; Only need to keep bits 0-2 (values = 0-7)
  OR $40                  ; 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,($EAA9)            ; 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 $07                 ; Filter out everything other than INK bits
  OR $40                  ; Set BRIGHT bit
  CP C                    ; Compare with object colour
  JR NZ,LD27D_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,($EAF3)           ; If it does happen, set the graphics address pointer
                          ; to the 'dummy' graphic (98B9), so nothing gets
                          ; drawn (the item would appear invisible anyway)
  JR LD27D_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:
LD27D_4:
  LD A,B                  ; Retrieve the room colour attribute value (stored in
                          ; PAPER bits)
  AND $F8                 ; Filter out/clear any INK bits
  OR C                    ; Append the item's INK bits (0-7)
  LD ($EAA8),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,($EAD4)            ; Get the horizontal position high byte - this
  CP $00                  ; indicates whether the object is within the current
                          ; screen viewport
  JR NZ,LD27D_5           ; If not, no need to print attributes, skip the next
                          ; instruction
  CALL LE3FD              ; Print screen attribute colours for the room
                          ; object/creature
; Now draw the item's graphics (pixels):
LD27D_5:
  LD HL,($EB51)           ; Graphic address pointer
LD27D_6:
  CALL LDB98              ; Draw the item graphics
  LD A,($EAD5)            ; 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,($EB4E)            ; properties byte at EB4E indicating whether this
                          ; item is visible on screen
  AND $FE                 ; Filter out bit 0 from the item properties byte
  OR C                    ; Append a 0 or 1 accordingly (not
                          ; on-screen/on-screen)
  LD ($EB4E),A            ; ...and re-store the item properties byte.

; Start of setting up room routine - part 2
;
; Used by the routines at LD26E and LD27D.
;
; Also continued from previous section. This routine replaces the active item
; data back into its room item data set at 7C00.
LD325:
  CALL LE0B0              ; Copy 16 bytes of the active item data set from
                          ; LEB43 to one of the room item data sets at 7C00.
  CALL LE1D7              ; Play (generic) step/white noise sound effect (if
                          ; this item is making a noise it will have its
                          ; speaker bit set)
  LD HL,($EABC)           ; Get copy of pointer to data sets at 7C00
  JP LC7EA                ; 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 LC7EA.
;
; HL Address pointer (EABC/EABE) to first byte of one of the data sets at 7C00
;    (the one after the last set copied in the previous routine)
;
; Jump here from LC7D0 after copying graphics data to banks at 7C00
;
; If Maroc picks up a spell, the 'Magic' text in the bottom left changes colour
; for a short time, and a sound is played
LD331:
  LD HL,($EABE)           ; Address pointer to start of next data set (at 7C00)
  LD (HL),$FF             ; Add end-of-data marker to the first byte of the set
  LD ($EB72),HL           ; Copy address pointer into store
; Check if the post-scroll-pickup effect (colour/sound) needs to be actioned:
  LD A,($ECA0)            ; This is the counter byte for flashing the 'MAGIC'
  CP $00                  ; text in the bottom left of the screen.
  JR Z,LD368              ; 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 ($ECA0),A            ;
  JR NZ,LD331_0           ; Check if now zero
  LD A,$30                ; 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':
LD331_0:
  LD DE,$001C             ; Prepare an offset of 28 character spaces ready to
                          ; move down to the next line of the screen
  LD C,$02                ; 2 character rows to colour
  LD HL,$5AC2             ; Screen display address for the top left of the word
                          ; 'MAGIC'
LD331_1:
  LD B,$04                ; 4 characters wide
LD331_2:
  LD (HL),A               ; Colour the character square (colour = counter byte
                          ; value)
  INC HL                  ; Move right one character square
  DJNZ LD331_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,LD331_1           ; ...And repeat for 2 rows
; Play sound effect:
  LD C,$80                ; Outer loop - duration counter
  LD A,$10                ; Speaker bit 4 (16)
; Speaker toggle loop:
LD331_3:
  XOR $10                 ; Toggle speaker bit
  OUT ($FE),A             ; Output sound
  LD B,C                  ; Get duration counter
LD331_4:
  DJNZ LD331_4            ; ...short pause for duration value of counter
  DEC C                   ; Decrement duration counter
  JR NZ,LD331_3           ; Repeat loop until sound duration counter = 0

; Determine Maroc's sprite graphic position, height and direction
;
; Used by the routine at LD331.
;
; 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
LD368:
  CALL LE220              ; Set attribute colours for Maroc
  LD A,(LEAAA)            ; Get generic game counter/timer
  INC A                   ; Increment
  LD (LEAAA),A            ; ...and re-store
  AND $02                 ; Check bit 1 - this will be set every other frame
  JR Z,LD368_0            ;
  LD A,$00                ;
  LD ($EAAB),A            ; If not set (i.e. every other game frame), set
                          ; vertical & horizontal movement velocity to 0
  LD ($EAAC),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):
LD368_0:
  LD A,$00                ; High overflow/precision byte for graphic horizontal
  LD ($EAD4),A            ; screen position - reset just in case
  LD HL,($EAC2)           ; Get Maroc's sprite frame graphic address pointer
                          ; (table at L97C3)
  LD ($EACD),HL           ; Copy to graphics address buffer
  LD A,($EAC0)            ; 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 $FC                 ; Filter out any unwanted bits 0 & 1 caused by the
                          ; RLA
  LD ($EAD3),A            ; Store horizontal pixel position in graphics data
                          ; buffer
  LD A,($ECA1)            ; Maroc's height offset as he moves (above his
  LD D,A                  ; shadow) in pixels
  LD A,($EAC1)            ; Maroc's vertical (Y-axis) screen position
  LD ($EAD2),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,($EB04)            ; Maroc's horizontal movement speed/rate
  CP $80                  ; If bit 7 is set, Maroc's moving right
  JR C,LD368_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
LD368_1:
  LD C,A                  ; Store horizontal speed in C register
  LD A,($EB05)            ; Maroc's vartical movement speed/rate
  CP $80                  ; If bit 7 is set, Maroc's moving down
  JR C,LD368_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:
LD368_2:
  CP C                    ; Check vertical speed (A register) vs horizontal
                          ; speed (C register)
  JR NC,LD368_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:
LD368_3:
  RRA
  RRA                     ; Divide by 4. e.g. if Maroc is at 32 (max speed) the
                          ; offset will be 8
  AND $1F                 ; ...and filter out any unwanted bits (bits 5-7)
  LD C,A                  ;
  LD A,$07                ; 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 ($ECA1),A            ; ...and store the new offset.
  ADD A,D                 ; Add the new offset to Maroc's vertical (Y-axis)
                          ; pixel position
  LD ($EAC1),A            ; ...and store.
; Identify Maroc's left/right movement
  LD A,(LEAFD)            ; Get left/right direction key press flag
  CP $00                  ; If it's 0, neither right/left is being pressed
  JR Z,LD368_6            ;
  CP $80                  ; Left or right direction controls are being pressed
                          ; so check bit 7 to determine which one.
  JR C,LD368_8            ; Carry = right control key used
  LD A,($EAFE)            ; No carry = left control key used. Get up/down
                          ; direction key press flag
  CP $00                  ; If it's 0, neither up/down is being pressed
  JR Z,LD368_4            ;
  CP $80                  ; Up or down direction controls are being pressed so
                          ; check bit 7 to determine which one.
  JR C,LD368_5            ; Carry = up control key used
; LEFT and DOWN controls pressed
  LD A,$20
  JR LD368_11
; LEFT control pressed, no up/down controls pressed.
LD368_4:
  LD A,$40
  JR LD368_11
; LEFT and UP controls pressed
LD368_5:
  LD A,$60
  JR LD368_11
; Neither left or right controls pressed. Check up/down controls.
LD368_6:
  LD A,($EAFE)            ; Get up/down direction key press flag
  CP $00                  ; If it's 0, neither up/down (or left/right) is being
  JR Z,LD368_14           ; pressed - skip out of routine
  CP $80                  ; Up or down direction controls are being pressed so
                          ; check bit 7 to determine which one
  JR NC,LD368_7           ; No carry = down control key used
; UP control pressed, no left/right controls pressed
  LD A,$80
  JR LD368_11
; DOWN control pressed, no left/right controls pressed
LD368_7:
  LD A,$00
  JR LD368_11
; Right control pressed - check up/down options
LD368_8:
  LD A,($EAFE)            ; Right control pressed. Get up/down direction key
                          ; press flag
  CP $00                  ; If it's 0, neither up/down is being pressed
  JR Z,LD368_9            ;
  CP $80                  ; Up or down direction controls are being pressed so
                          ; check bit 7 to determine which one
  JR C,LD368_10           ; Carry = up control key used
; RIGHT and DOWN controls pressed
  LD A,$E0
  JR LD368_11
; RIGHT control pressed, no up/down controls pressed
LD368_9:
  LD A,$C0
  JR LD368_11
; RIGHT and UP controls pressed
LD368_10:
  LD A,$A0
; 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.
LD368_11:
  LD B,A                  ; Store above value in B register
  LD A,($EB03)            ; 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,LD368_14           ; If the result is 0, Maroc is already facing in the
                          ; right direction - nothing to change
  CP $80                  ; Check bit 7 to see if the result is positive or
  JR NC,LD368_12          ; negative, i.e. whether Maroc needs to rotate
                          ; clockwise or anti-clockwise.
  LD A,$20                ; If it's positive, set the increment amount to 32 -
  JR LD368_13             ; Maroc is rotating CLOCKWISE
LD368_12:
  LD A,$E0                ; If it's negative, set the increment amount to -32 -
                          ; Maroc is rotating ANTI-CLOCKWISE
LD368_13:
  ADD A,C                 ; Add this offset to the existing position
  LD ($EB03),A            ; ...and store.
; Get the graphic address offset corresponding to this new rotational position.
LD368_14:
  LD A,($EB03)            ; Get Maroc's new rotational position (see values in
                          ; table at LD368_11)
  RRA                     ; Divide by 16
  RRA                     ;
  RRA                     ;
  RRA                     ;
  AND $0E                 ; 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 L97C3).
  LD E,A                  ; Store in E register
  LD C,$00                ; Reset C register (will act as a flag to indicate if
                          ; anything has changed with Maroc's sprite)
  LD A,($EC9F)            ; Get the current address pointer offset
  CP E                    ; Compare with the newly calculated one
  JR Z,LD446              ; 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 ($EC9F),A            ; ...and store
  LD D,$00                ; The graphics address offset will be in DE, the high
                          ; byte of the offset isn't needed so reset it
  LD HL,($EB6A)           ; Address pointer to graphics at L97C3
  ADD HL,DE               ; Add the offset for Maroc's new graphics frame
  LD ($EAC2),HL           ; ...and store.

; Draw Maroc's sprite graphic
;
; Follows previous routine which has calculated Maroc's sprite rotation and
; 'floating' height at LD368. 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 D430, 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:
LD446:
  LD A,($EAC1)            ; Get Maroc's vertical pixel position
  LD D,A                  ; Store in D register
  LD A,($EAD2)            ; Get Maroc's vertical pixel position, with the
                          ; earlier vertical offset added
  CP D                    ; Is it the same?
  JR Z,LD446_0            ;
  INC C                   ; If not, increment the (flag) C register
LD446_0:
  LD A,C                  ; Check the (flag) C register
  CP $00                  ; If it's still zero, there's no change to either (a)
  JR Z,LD446_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,$00                ; Set draw/erase flag to 0 (ERASE)
  LD ($EACF),A            ;
  LD HL,($EACD)           ; Retrieve Maroc sprite's graphic address from the
                          ; (previous) graphic address buffer
  CALL LDB98              ; Erase the graphic
; Draw Maroc's sprite graphic
LD446_1:
  LD A,($EAC1)            ; Maroc's vertical (Y-axis) screen position
  LD ($EAD2),A            ; Copy into graphics buffer
  LD A,$01                ; Set draw/erase flag to 1 (DRAW)
  LD ($EACF),A            ;
  LD A,($EAE9)            ; Check if the UNSEEN spell (spell #9) is currently
  CP $09                  ; active
  JR Z,LD479              ; If so, there's no need to draw Maroc's sprite
                          ; graphic, as he's invisible, so skip the next two
                          ; instructions
  LD HL,($EAC2)           ; Maroc's sprite graphics frame address pointer (in
                          ; table at L97C3)
  CALL LDB98              ; Draw Maroc's sprite

; Check if Maroc is on a room element/item that drains or restores his energy
;
; Used by the routine at LD446.
;
; 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)
LD479:
  LD A,($EAD2)            ; Maroc's vertical pixel position
  ADD A,$08               ; 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 ($EAD2),A            ; ...and re-store as the vertical co-ordinate to
                          ; check
; Check for energy draining items:
  LD C,$FE                ; Collision type to check against - 254 = energy
                          ; draining objects
  CALL LDFCD              ; Collision check routine - returns 0 (no collision)
  CP $00                  ; or 1 (collision found) in the A register
  JR Z,LD479_0            ; If no collision, skip to the next check
  LD A,$08                ; Otherwise, set energy drain amount to 8 points of
                          ; energy
  CALL LE3CC              ; ...and reduce Maroc's energy by this amount
; Check for energy restoring items:
LD479_0:
  LD C,$FD                ; Collision type to check against - 253 = energy
                          ; restoring objects
  CALL LDFCD              ; Collision check routine - returns 0 (no collision)
  CP $00                  ; or 1 (collision found) in the A register
  JR Z,LD49D              ; If no collision, skip over the next couple of
                          ; instructions
  LD A,$FE                ; Otherwise, set energy drain amount to -2 (i.e. -2
                          ; drain, so INCREASE energy by 2)
  CALL LE3CC              ; ...increase Maroc's energy

; Check if Maroc has gone through the portal in room 81
;
; Used by the routine at LD479.
;
; 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 LDFCD 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...
LD49D:
  LD A,($EAB7)            ; Get room number
  CP $51                  ; Is it room 81?
  JR NZ,LD4B2             ; If not, skip the following check routine
  LD C,$88                ; Collision type to check = 136 - Maroc touching
                          ; portal door
  CALL LDFCD              ; Collision check routine - returns 0 (no collision)
                          ; or 1 (collision found) in the A register
  CP $00                  ; Collision with portal door?
  JR Z,LD4B2              ; If not, skip to the next routine
  LD A,$52                ; Set the room number to 82, in the High Temple of
  LD ($EAB0),A            ; Chaos

; Draw Maroc's shadow and flickering barrier for SHIELD, PROTECT and DEFENCE
; spells
;
; Follows previous section (LD49D).
;
; * 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:
LD4B2:
  LD HL,($EAC4)           ; Graphic address pointer for Maroc's shadow (98B7)
  LD A,$5F                ; Vertical screen position - 95 pixels from top of
  LD ($EAD2),A            ; playing area
  CALL LDB98              ; Draw shadow
; Check for spells that generate a flickering effect
  LD A,($EAE9)            ; Check currently active effect spell (a positive
                          ; match for any of them jumps to LD4B2_0)
  CP $02                  ; SHIELD spell active
  JR Z,LD4B2_0            ;
  CP $0B                  ; PROTECT spell active
  JR Z,LD4B2_0            ;
  CP $12                  ; DEFENCE spell active
  JR Z,LD4B2_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 EAE9 is set to 255
; * This tells this routine to erase any 'barrier' graphics that might be on
;   screen
  CP $FF
  JR NZ,LD4FC             ; If no 255 match, there's no effect spell graphics
                          ; to draw/erase. Jump out of this routine to LD4FC.
; SHIELD, PROTECT or DEFENCE have been deactivated, so make sure any on-screen
; barrier graphics are removed
  LD A,$00
  LD ($EAE9),A            ; Set currently active effect spell to 0 (no spell
                          ; active)
  LD ($EACF),A            ; Set draw/erase flag to 0 (ERASE)
; Draw/erase the flickering barrier graphics
LD4B2_0:
  LD A,($EAC1)            ; Get Maroc's vertical screen position, from top of
                          ; playing area, in pixels
  LD ($EAD2),A            ; ...and copy into working graphic data buffer
  LD HL,($EC96)           ; Graphics address pointer for shield barrier
                          ; graphics (9893/A9EC)
; Work out which graphics frame to use for barrier graphic. Uses the game
; counter at LEAAA to alternate frame graphics.
  LD A,(LEAAA)            ; Get the game counter byte
  AND $01                 ; 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,$00                ;
  ADD HL,DE               ; ...and add to the base graphic pointer address
                          ; (9893)
  LD ($EB51),HL           ; Store graphics address pointer to the frame that
                          ; needs drawing
  CALL LDB98              ; 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,$00
  LD ($EACF),A            ; Set draw/erase flag to 0 (ERASE)
  LD HL,($EB51)           ; Retrieve address for barrier graphics frame
  CALL LDB98              ; ...And erase the graphic

; Move and draw the room's foreground scenery items
;
; Follows previous section at LD4B2
;
; This routine handles the room's foreground objects - originally set up at
; LC501, and stored in data sets at 7F01.
; * 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
LD4FC:
  LD A,($EAB7)            ; Get room number
  CP $E0                  ; Is it a vertical tunnel room ( >= room 224)?
  JP NC,LD6D2             ; If so, no foreground objects - skip this routine
  LD HL,($EB70)           ; Get pointer to foreground scenery room object data
                          ; (7F01)
; Copy item set data bytes into various working buffer addresses:
LD4FC_0:
  LD ($EABE),HL           ; Store pointer to object data in address pointer
                          ; buffer
  LD A,(HL)               ; First byte of data set
  INC HL                  ;
  CP $FF                  ; Is it end-of-data?
  JP Z,LD5D4              ; If so, skip out of this routine
  LD B,A                  ; Store first byte in B register (used as a counter
                          ; and checked later at LD4FC_2)
  LD A,(HL)               ; Second byte of data set
  INC HL                  ;
  LD ($EB47),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 ($EB48),A            ; Store horizontal position for item
  LD A,(HL)               ; Get fourth byte of set
  INC HL                  ;
  LD ($EB49),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 ($EB4A),A            ; Store vertical position for item
  LD ($EAD2),A            ; Store in second buffer
  LD E,(HL)               ; Get address pointer to item graphics
  INC HL                  ;
  LD D,(HL)               ;
  INC HL                  ;
  LD ($EACD),DE           ; ...and store in graphic address pointer buffer
; Convert horizontal position from characters to pixels:
  LD HL,($EB47)           ; 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 ($EAD4),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 ($EAD3),A            ; Store it
; Check Maroc's horizontal movement speed/direction and move the foreground
; scenery objects accordingly:
  LD A,($EB04)            ; 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 ($EB47),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 ($EACC),A            ; Store the high byte - indicating negative (255) or
                          ; positive (0)
  LD A,H                  ; And the low byte, containing the horizontal pixel
  LD (LEACB),A            ; co-ordinate
  CP C                    ; Has the scenery item's horizontal position changed
  JR Z,LD4FC_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:
LD4FC_1:
  LD HL,($EB49)           ; Get vertical screen pixel co-ordinate
  EX DE,HL                ; Copy into DE register
  LD A,($EB05)            ; Get vertical movement speed/direction (negative =
                          ; Maroc moving down, positive = Maroc moving up)
  LD L,$00                ; 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 ($EB49),HL           ; ...and store new position.
  LD A,H                  ; Has the scenery item's vertical position changed at
  CP D                    ; all?
  JR Z,LD4FC_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
LD4FC_2:
  LD A,B
  CP $02
  JR C,LD4FC_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,$00                ; Set draw/erase flag to 0 (ERASE)
  LD ($EACF),A            ;
  CALL LDDA1              ; Erase the foreground scenery item
  LD A,(LEACB)            ;
  LD ($EAD3),A            ; Copy the item's calculated horizontal (pixel)
  LD A,($EB4A)            ; screen position into working graphic buffer
  LD ($EAD2),A            ; Copy the item's calculated vertical (pixel) screen
  LD A,($EACC)            ; position into working graphic buffer
  LD ($EAD4),A            ; Also copy the horizontal co-ordinate high byte
  JR LD4FC_4              ;
; Check for item movement again:
LD4FC_3:
  CP $00
  JR NZ,LD4FC_4
  LD ($EAD5),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 LD4FC_5              ; ...and skip draw routine
; Item needs drawing on screen:
LD4FC_4:
  LD A,$01                ; Set draw/erase flag to 1 (DRAW)
  LD ($EACF),A            ;
  CALL LDDA1              ; Draw the foreground scenery item
; Copy scenery item data into data sets at 7F01
LD4FC_5:
  LD HL,($EABE)           ; (Copy of) pointer to scenery item data at 7F01
  LD A,($EAD5)            ; 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,($EB47)            ;
  LD (HL),A               ; Put horizontal object position overflow/precision
  INC HL                  ; offset into byte 2 of set
  LD A,($EB48)            ;
  LD (HL),A               ; Put horizontal object position into byte 3 of set
  INC HL                  ;
  LD A,($EB49)            ;
  LD (HL),A               ; Put vertical object position overflow/precision
  INC HL                  ; offset into byte 4 of set
  LD A,($EB4A)            ;
  LD (HL),A               ; Put vertical object position into byte 5 of set
  INC HL                  ; Move pointer along to next data set item at 7F01
  INC HL                  ;
  INC HL                  ;
  JP LD4FC_0              ; Continue to deal with (move, erase and draw)
                          ; foreground scenery items
; Next routine is at LD5D4 (after all foreground scenery items dealt with)

; Re-calculate room event table data sets
;
; Follows setup of foreground scenery objects at LD4FC.
;
; The room's 'events-to-check' sets at 7FB3 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 7FB3
; * 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
LD5D4:
  LD HL,($EB6C)           ; Pointer to room item event data sets at 7FB3
  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:
LD5D4_0:
  CP $FF                  ; Have we reached the end of the event sets?
  JR Z,LD5D4_3            ; If so, skip out at this point
  DEC A                   ; The first byte for these will be 1 or 2
  JR Z,LD5D4_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,$04                ; Copy the DEC'd byte back into the first byte of the
LD5D4_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 LD5D4_1            ;
  JR LD5D4_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:
LD5D4_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 LD5D4_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.
LD5D4_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 LD4FC, 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 ($EAAD),HL           ; Store pointer to end of event table (byte 1 of new
                          ; set)
  LD HL,($EB72)           ; Retrieve address pointer for the end of the room
                          ; element data sets at 7C00
  LD ($EABE),HL           ; Copy to data buffer
; The following routine (LD5FE) 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.
LD5FE:
  LD A,($EBB7)            ; Creature type (see EB46)
  CP $00                  ;
  JR Z,LD63A              ; If no creature, skip to the next routine
  CALL LE16A              ; This routine sets up data for creatures/warlocks
                          ; appearing in Maroc's room (the A register normally
                          ; contains creature type/number from EB46)
  LD A,($EBB8)            ; Creature's horizontal position (in 4 pixel steps)
                          ; in room, after entering through a door
  LD ($EB48),A            ; Copy to graphic data buffer
  LD C,A                  ;
  LD A,($EBB9)            ; Creature's vertical pixel position in room, after
                          ; entering through a door
  SUB $0E                 ; 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 ($EB4A),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,$0004             ; 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,($EAFB)            ; 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,LD5FE_0            ; in 4 pixel steps)
  LD DE,$0400             ; Creature is to the left of the room's left
  JR LD5FE_1              ; connector, so entering through a LEFT WALL DOOR
LD5FE_0:
  LD A,($EAFC)            ; 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,LD5FE_1           ; in 4 pixel steps) in room
  LD DE,$FC00             ; 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
; (EB4C) and vertical (EB4D) 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)
LD5FE_1:
  LD A,D
  LD ($EB4C),A            ; Horizontal speed/direction
  LD A,E                  ;
  LD ($EB4D),A            ; Vertical speed/direction
  JP LD6C7                ;

; Gradual energy drain/restore for Maroc's ongoing effect spells
;
; Used by the routine at LD5FE.
;
; 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:
LD63A:
  LD A,(LEAAA)            ; Incrementing game counter
  LD C,A                  ; (This instruction/C register not needed)
  AND $0F                 ; Check if any of bits 0-3 are set
  CP $00                  ;
  JR NZ,LD651             ; If so, don't do anything but instead skip to next
                          ; routine
; Every 16th game cycle:
  LD A,($EAE9)            ; Currently active 'effect' spell
  CP $00                  ;
  JR Z,LD651              ; If no active effect spells, jump to next routine
  LD A,($EBD5)            ; Ongoing effect spell - amount of energy to
                          ; drain/heal (see table)
  CALL LE3CC              ; Increase/decrease Maroc's energy accordingly

; Determine whether a warlock should materialize in the room
;
; Used by the routine at LD63A.
;
; A warlock can appear in the room:
; * After a certain time, based on a slowly decrementing counter byte at EBB4
;   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 LC6A4)
;
; No warlock appears on level 8 (Chambers of Chaos). On level 9 (High Temple of
; Chaos), DEMONS materialize in rooms instead of warlocks.
LD651:
  LD A,($EAC9)            ; Get the current level text number (1-9) -
                          ; calculated from lookup table at LC6A4
  LD B,A                  ; Store in B register
; There are only 7 warlocks, so we need to do something for levels 8 and 9
  CP $08                  ; Are we in the Chambers of Chaos (level 8)?
  JP Z,LD6C7_0            ; If so there's no warlock on this level - jump to
                          ; the end of this check routine
  CP $09                  ; Are we in the High Temple of Chaos (level 9)?
  JR Z,LD6A4              ; If so, jump out and generate a DEMON instead of a
                          ; WARLOCK
  LD A,(LEAAA)            ; Game cycle timer
  AND $3F                 ; Check bits 0-5 (values = 0-63)
  JP NZ,LD6C7_0           ;
; Every 64 game cycles, reduce the timer counter for a warlock appearing in the
; room
  LD A,($EBB4)            ; Get warlock appearance timer
  DEC A                   ; Decrement it
  LD ($EBB4),A            ; ...and re-store
  LD C,A                  ;
  CALL LDB06              ; 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,LD6C7_0            ; If random number < warlock timer, jump out here
  LD A,(LEBAD)            ; Random number > warlock timer. Get byte 6 of
  CP $00                  ; warlock data set
  JR NZ,LD6C7_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 LC6A4
;
; 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.
LD67B:
  LD A,B                  ; Get warlock number (between 1 and 7 from table at
                          ; L6C7C)
  CALL LE16A              ; Set up warlock data in working buffer at LEB43
  LD HL,$EAF6             ; 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,$1C               ; 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 ($EB4A),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 $07                 ; 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 $03                 ; Subtract 3, to give a possible values of -3 to +4
                          ; (negative numbers = left, positive numbers = right)
  LD ($EB4C),A            ; Store as warlock's (horizontal) speed (and
                          ; direction)
  LD HL,($EB44)           ; Address pointer to this warlock's data set (at
  INC HL                  ; L6C7C)
  LD A,(HL)               ; Get the second byte of the warlock's data set
  CP $00                  ;
  JR NZ,LD6C7_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 (LEBAD),A            ; Store in warlock active data buffer
  JP LD6B0                ;

; Generate a DEMON in the room in the High Temple of Chaos
;
; Used by the routine at LD651.
;
; Warlocks materialize in levels 1-7 (see table at LC6A4). 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 6C5E) There are initially too many creatures for this
;   room's demon to appear.
LD6A4:
  LD A,($EAF2)            ; Flag indicating a warlock, or demon, has been
  CP $00                  ; generated in the room (1 = generated/present, 0 =
                          ; not generated/present)
  JR NZ,LD6C7_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,$0C                ; Creature type = 12 (demon)
  CALL LE16A              ; Set up creature data (e.g. screen position) in data
                          ; buffer at LEB43

; Initialize the appearance of a warlock or a demon
;
; Follows previous routine for demon at LD6A4, or jump from end of warlock
; initialization at D6A1.
LD6B0:
  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 ($EB4E),A            ; Store as creature's properties byte
  LD A,$01                ;
  LD ($EB50),A            ; Graphic frame number offset (= no offset - start at
                          ; animation frame 1)
  LD ($EAF2),A            ; Set the warlock/demon appearance flag to 1 (to stop
                          ; any more being generated)
  LD A,$5B                ; Graphic number for start of materialization effect
                          ; (offset for graphics address pointer 9877)
  CALL LE0C2              ; 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,$00                ; Set the FREEZE spell timer to zero
  LD ($EC9C),A            ;

; Copy creature, demon or warlock data to room data sets
;
; Follows warlock/demon initialization at LD6B0, or creature initialization at
; LD5FE.
LD6C7:
  CALL LE0B0              ; Copy creature data set from the working buffer at
                          ; LEB43 to room item data sets at 7C00
  LD (HL),$FF             ; Put an end-of-data-set marker at the start of the
  LD ($EB72),HL           ; next data set
; This entry point is used by the routines at LD651, LD67B and LD6A4.
LD6C7_0:
  JP LD794                ; Jump to the next routine - missile checks

; Tunnel section - Generate and prepare tunnel items
;
; Used by the routine at LD4FC.
;
; This routine uses the cyclical game timer at LEAAA to generate the left and
; right walls of the tunnel.
LD6D2:
  LD A,$00                ; Reset current horizontal & vertical speeds back to
  LD ($EB4D),A            ; zero
  LD ($EB4C),A            ;
  LD A,(LEAAA)            ; Game timer
  LD C,A                  ;
  AND $01                 ; Every other game timer frame, decide whether to
  JP NZ,LD71C             ; generate a left/right tunnel boundary wall
  LD A,($EB7E)            ; Incremental tunnel counter
  INC A                   ; Add 1
  CP $14                  ; Check if >=20 (this determines the limit to how
                          ; many boundary wall sections can be generated on
                          ; screen)
  JP NC,LD794             ; 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 ($EB7E),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 $02                 ; Check bit 2 - 50/50 set/unset. Will go in a
                          ; sequence of 11-00-11-00-11
  JR Z,LD6D2_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,$01                ; Graphic offset = 1 (no offset - use graphic at
                          ; LA09A)
  LD C,$10                ; Horizontal movement speed/direction = +16 (moving
                          ; right)
  LD E,$04                ; Horizontal movement position offset - in
  JR LD6D2_1              ; half-character/4-pixel steps (2 character squares
                          ; to the right)
; Left tunnel boundary wall:
LD6D2_0:
  LD A,$02                ; Graphic offset = 2 (a mirrored version of the
                          ; tunnel graphic at LA09A will be created and the
                          ; graphics address stored at 9811)
  LD C,$F0                ; Horizontal movement speed/direction = -16 (moving
                          ; left)
  LD E,$FC                ; Horizontal movement position offset - in
                          ; half-character/4-pixel steps (2 character squares
                          ; to the left)
; Store calculated boundary attributes:
LD6D2_1:
  LD ($EB46),A            ; 1 = Right boundary, 2 = Left boundary (mirror
                          ; version)
  LD ($EB50),A            ; Graphic frame offset (1 = no offset or 2 =
                          ; mirrored)
  LD A,$0E                ; Graphic type = Tunnel object
  LD (LEB43),A            ;
  LD A,C                  ; Retrieve horizontal position/movement offset
  LD ($EB4C),A            ; ...and store
  LD A,($EC9E)            ; Get horizontal graphic position (in
                          ; 4-pixel/half-character steps)
  ADD A,E                 ; Add the offset (+ or - 2 character squares)
  LD ($EB48),A            ; ...and store as graphic's horizontal screen
                          ; position
  LD A,$27                ; Graphic number for tunnel boundary graphic address
                          ; pointer at 980F
  JR LD730_1              ; Set up the tunnel wall graphic

; Tunnel section - Run game timer and randomly generate creatures
;
; Used by the routine at LD6D2.
;
; Jump from D6E0 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.
LD71C:
  LD A,(LEAAA)            ; Get the game timer
  INC A                   ; Increment it
  AND $07                 ; Check bits 0-2 (values 0-7)
  JR NZ,LD794             ;
; 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 (L6710) 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 LDB06              ; Generate pseudo-random number in A register
  LD C,A                  ; Store in C register
  LD A,($EAB7)            ; Get room number
  SUB $30                 ; 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,LD794             ; 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 (LDB06) 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):
LD730:
  LD A,($EC9D)            ; Number of creatures currently on-screen in the
                          ; tunnel
  INC A                   ; Increase by 1
  CP $03                  ; There's a limit of 3 creatures on-screen
  JR NC,LD794             ; If adding this creature would make it 4, skip the
                          ; routine.
; It's OK to generate a creature:
  LD ($EC9D),A            ; It's < 3 creatures. Store the creature count byte
  LD A,$0E                ; Item type #14 designates a tunnel object - boundary
  LD (LEB43),A            ; wall, bat or spider (creatures are later
                          ; differentiated from walls using the byte at stored
                          ; EB46)
  LD A,$01                ; Starting frame offset (no offset)
  LD ($EB50),A            ;
; Randomize starting position of creature in relation to tunnel wall:
  LD A,C                  ; Retrieve random number generated earlier
  AND $0F                 ; Keep bits 0-4 (values = 0-15)
  SUB $07                 ; Subtract 7 (value range now between -7 and +8)
  LD B,A                  ; Store in B register
  LD A,($EC9E)            ; Get tunnel horizontal position
  ADD A,B                 ; Add the random offset calculated earlier (-7 to +8)
  LD ($EB48),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 $01                 ; Check bit 1 for 0 or 1 (50/50) - to run one of the
  JR Z,LD730_0            ; next two sections.
; Generate a SPIDER
  LD A,$04                ; Creature type = 4
  LD ($EB46),A            ;
  LD A,($EC9E)            ; 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 ($EB4C),A            ; ...and store as position (movement) offset
  LD A,$7D                ; Graphic number for spider graphic address at 98BB
  JR LD730_1              ;
; Generate a BAT
LD730_0:
  LD A,$08                ; Creature type = 8
  LD ($EB46),A            ;
  LD A,C                  ; Retrieve random number generated earlier
  AND $7F                 ; Filter out bit 7, giving a random number in the
                          ; range of 0-127
  SUB $3F                 ; ...And subtract 63, giving a random number in the
                          ; range of -63 to +64
  LD ($EB4C),A            ; Store as horizontal position (movement)
                          ; speed/offset
  LD A,$24                ; Set vertical position (movement) speed/offset (36
  LD ($EB4D),A            ; pixels). This will cause the bat to start by moving
                          ; quickly down the screen.
  LD A,$7F                ; Graphic number for bat graphic address at 98BF
; Set up creature graphic
LD730_1:
  LD C,A                  ; Temporarily store the graphic number in C register
  LD A,$FE                ; Tunnel item identifier (boundary wall, bat or
  LD ($EB4B),A            ; spider) - ends up in byte 9 of data set at 7C00
  LD A,$08                ; Set vertical position (8 pixels from top of screen)
  LD ($EB4A),A            ;
  LD A,C                  ; Retrieve graphic number
  CALL LE0C2              ; Set up the graphics
  CALL LE0B0              ; ...and copy into room data set at 7C00
  LD (HL),$FF             ; Set end-of-data marker at start of next data set
  LD ($EB72),HL           ; ...And store the address pointer to it.

; Check for any fired missiles/bolts
;
; Used by the routines at LD6C7, LD6D2, LD71C and LD730.
;
; 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.
LD794:
  LD A,$00
  LD ($EAD4),A            ; Indicates screen/viewport - 0 = current
  LD A,$05                ; screen/viewport
  LD ($EB9A),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,($EB93)            ; Get missile number (table at L6CDC)
  CP $00                  ;
  JR Z,LD794_0            ; 0 = no missile present
  CALL LDB1F              ; If not zero, set up this missile set data
  LD A,$00                ; Missile has now been set up and stored in the data
  LD ($EB93),A            ; sets at 7C00, so can now set the missile number to
                          ; zero
; Check if Maroc has launched a missile spell:
LD794_0:
  LD A,($EC98)            ; 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 $00                  ; If zero, Maroc hasn't fired a missile spell - skip
  JR Z,LD7F3              ; next section
; Maroc has launched a missile-type spell. Calculate trajectory of missile:
  LD A,($EB92)            ; Flag indicating if Maroc has fired a missile (1 =
  CP $00                  ; missile fired, 0 = no missile)
  JR NZ,LD794_1           ; If there's already one, skip the setup
  INC A                   ; Increment so the flag = 1 (missile fired)
  LD ($EB92),A            ; ...and re-store.
  LD A,$00                ; Precision/overflow byte for horizontal/vertical
  LD ($EB94),A            ; item position (reset both to 0)
  LD ($EB96),A            ;
  LD A,($EAC0)            ; Maroc's horizontal (X-axis) screen position
  LD ($EB95),A            ; Set this as the missile's horizontal (X)
                          ; co-ordinate origin
  LD A,($EAC1)            ; Maroc's vertical (Y-axis) screen position
  LD ($EB97),A            ; Set this as the missile's vertical (Y) co-ordinate
                          ; origin
  LD A,($EAFF)            ; Get the vertical (Y) pixel position of the aiming
                          ; cursor
  LD ($EB99),A            ; Store as the target vertical pixel (Y) co-ordinate
                          ; for the missile
  LD A,($EB00)            ; 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 $3F                 ; Filter out any unnecessary carry bits
  LD ($EB98),A            ; ...and store
  LD A,$08                ; Item/missile type = 8 (missile fired by Maroc)
  LD ($EB9A),A            ; Store in missile data set
  LD A,($EC98)            ;
  CALL LDB1F              ; Set up missile data
LD794_1:
  LD A,$00                ; 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 ($EC98),A            ; Now that the missile has been initialized, set this
                          ; flag to 0.

; Check which spell has been cast
;
; Follows the previous routine at LD794.
;
; Check which (if any) spell, or spell type, has been cast/activated (rather
; than merely selected) - using spell number - from the spells list at L6DFC
; and stored at EAEC.
LD7F3:
  LD A,($EAEC)
  CP $00                  ; No spell cast, or MOVE spell in effect
  JP Z,LD901              ;
  CP $01                  ; SERVANT spell
  JR Z,LD833              ;
  CP $08                  ; HAIL spell
  JP Z,LD8CE              ;
  CP $0C                  ; WAYSTONE spell
  JP Z,LD8CE_0            ;
  CP $10                  ; FREEZE spell
  JP Z,LD8CE_1            ;
  CP $11                  ; SUMMON spell
  JP Z,LD8CE_2            ;
  CP $13                  ; PORTAL spell
  JP Z,LD8CE_3            ;
; Maroc has cast some other spell:
  LD A,($EBC7)            ; Check the type of spell cast
  CP $02                  ; Spell type 2 = spell that generates a controllable
                          ; graphic, e.g. SERVANT, MISSILE, OPEN
  JP NZ,LD901             ; 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 EBCA, 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,($EBCA)            ; Get byte indicating spell cursor type
  CP $00                  ; If not active, can skip to next routine
  JP Z,LD901              ;
  LD C,A                  ; Otherwise, temp store this value in the C register
  AND $80                 ; Bit 7 of this byte is set for bolt spells (MISSILE,
  CP $00                  ; FIREBALL etc.)
  JP Z,LD8B2              ; 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 LD901                ; 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 LD7F3.
;
; 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 7C00
LD833:
  LD A,($EBB1)            ; Servant object-carrying status flag
  CP $00                  ;
  JP NZ,LD8B2_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,($EB00)            ; Horizontal (X) position (in pixels) for servant
                          ; sprite
  LD D,A                  ; Store in D register
  LD A,($EAFF)            ; Vertical (Y) position (in pixels) for servant
                          ; sprite
  LD E,A                  ; Store in E register ready for collision call in 2
                          ; instructions
  LD C,$00                ; Collision/event flag to check - 0 = check collision
                          ; with Maroc sprite
  CALL LDFCD_0            ; Check if servant sprite is moving over Maroc
  CP $00                  ; Flag in A register indicates if collision has
                          ; occurred (1 = positive collision, 0 = no collision)
  JR Z,LD8B2              ; 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 7F72
  LD DE,$0010             ; 16 bytes in each inventory object data set
  LD B,$04                ; 4 object slots in Maroc's inventory to check
  LD HL,($EBBC)           ; Get address pointer for Maroc's inventory at 7F72
LD833_0:
  LD A,(HL)               ; Get first data byte of this set
  CP $00                  ; First byte will be: 0 = Empty slot, or 4 =
                          ; Interactable object
  JR NZ,LD833_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 $FF                  ;
  JR NZ,LD833_1           ; ...If not, keep checking inventory slots
  LD HL,(LEBBA)           ; ...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.
LD833_1:
  DJNZ LD833_0            ; Repeat until all 4 inventory slots have been
                          ; checked
  JR LD8B2_0              ; Maroc is not carrying anything - jump out to next
                          ; routine
; Item found in inventory. Copy item data from inventory slot at 7F72 into
; object data buffer at LEB43
LD833_2:
  LD BC,$0010             ; 16 bytes to copy
  LD DE,LEB43             ; Start of working data buffer at LEB43.
  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,$FFF0             ; Subtracts 16 from HL to return the address pointer
  ADD HL,DE               ; to the start of this object's inventory slot at
                          ; 7F72
  LD (HL),$00             ; 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 7C00, and the working data buffer is copied
; into this set.
  LD A,($EB4E)            ; 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 ($EB4E),A            ; ...and re-store
  LD A,($EB00)            ; Horizontal (X) position (in pixels) for servant
  LD L,$00                ; 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 $3F                 ; Filter out any stray carry bits from the rotate
  LD H,A                  ;
  LD ($EB47),HL           ; Store calculated horizontal position
; Set object's vertical pixel position (same as servant's position):
  LD A,($EAFF)            ; Vertical (Y) position (in pixels) for servant
                          ; sprite
  LD ($EB4A),A            ; ...copy into object's data buffer
; Other object values:
  LD A,$00                ; Set vertical movement speed/direction to 0
  LD ($EB4D),A            ;
  LD ($EB4C),A            ; Set horizontal movement speed/direction to 0
  LD ($EB49),A            ; Reset vertical pixel position fraction byte (will
                          ; be 0 at this point as servant is on-screen)
  CALL LDADC              ; Identify object state and prepare graphics for
                          ; printing
  CALL LE0B0              ; Copy object data into data set at 7C00
  LD (HL),$FF             ; Set end-of-data byte at the start of the next data
                          ; set
  LD ($EB72),HL           ; ...and store the address pointer
  LD A,$02                ; Servant-carrying-object flag. Normally set to 1 if
  LD ($EBB1),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 LD8B2_0              ; Skip to end of next routine

; Set up active spell-based room event checks
;
; Used by the routines at LD7F3 and LD833.
;
; 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 7FB3.
;
; There's also a jump here from the routine at D82D, 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.
LD8B2:
  LD HL,($EAAD)           ; Address pointer to room item event data at 7FB3
  LD (HL),$01             ; 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,($EBCA)            ; 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,($EB00)            ; Servant sprite horizontal (X) co-ordinate in pixels
  LD (HL),A               ; Store as byte 3 of set
  INC HL                  ;
  LD A,($EAFF)            ; 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 ($EAAD),HL           ; Store the address pointer to the start of the next
                          ; event data set at 7FB3
  LD (HL),$FF             ; 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).
LD8B2_0:
  JR LD901

; HAIL, WAYSTONE, FREEZE, SUMMON or PORTAL spell cast
;
; Used by the routine at LD7F3.
;
; The HAIL spell summons a warlock to Maroc's room
LD8CE:
  LD A,$08                ; Timer indicating how long before a creature is
                          ; likely to wander in from an adjacent room
  LD ($EBB4),A            ; Set this to 8 will cause a warlock to appear within
                          ; a few seconds
  JR LD901                ; ...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
LD8CE_0:
  LD A,($EAB7)            ; Get room number
  INC A                   ; +1
  CP $E0                  ; 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,LD901             ; 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 ($EAB0),A            ; Store new room number
  JR LD901                ; ...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
LD8CE_1:
  LD A,$FF                ; Set the FREEZE spell timer counter to 255
  LD ($EC9C),A            ; (temporarily stops all creature movement)
  JR LD901                ; ...and skip out to the next routine
; SUMMON spell cast
;
; This spell immediately teleports Maroc to room 61 in the Chambers of Chaos.
LD8CE_2:
  LD A,$3D                ; Set room number to 61
  LD ($EAB0),A            ;
  JR LD901                ; ...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.
LD8CE_3:
  LD A,($EAB7)            ; Get room number
  LD C,A                  ; Temp store in C register
  LD A,($EC9B)            ; Get room number to teleport to (initialized at 128)
  LD ($EAB0),A            ; ...and store as room number
  CP C                    ; Is current room number >= the room to teleport to?
  JR NC,LD901             ;
  LD A,C                  ; If so, store current room number as the new
  LD ($EC9B),A            ; teleport point

; Check/decrement the FREEZE spell timer counter if active
;
; Used by the routines at LD7F3, LD8B2 and LD8CE.
;
; Countdown timer to the end of the FREEZE spell - set to 255 when Maroc casts
; the spell at LD8CE_1.
LD901:
  LD A,($EC9C)            ; FREEZE spell timer counter
  CP $00                  ;
  JR Z,LD90C              ;
  DEC A                   ; If it's >0, the spell is active, so decrement the
                          ; timer counter..
  LD ($EC9C),A            ; ...and re-store.

; Check if Maroc is carrying too many objects
;
; Used by the routine at LD901.
;
; 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.
LD90C:
  LD HL,($EBBC)           ; Get address pointer for Maroc's inventory at 7F72
  LD A,(HL)               ; Get first data byte of this set
  CP $00                  ; This byte will be: 0 = Empty slot, or 4 =
                          ; Interactable object
  JR Z,LD940              ; 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,LEB43             ; Pointer to start of item working data buffer
  LD BC,$0010             ; 16 bytes
  LDIR                    ; Copy the item data
  LD HL,($EBBC)           ; Get the first byte of the inventory data set for
                          ; the item-about-to-be-dropped
; Marked the item as dropped:
  LD (HL),$00             ; Set the value as 0 as Maroc no longer has it
  LD A,($EB4E)            ; 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 ($EB4E),A
  LD A,$60                ; Set the vertical pixel position of the object to
  LD ($EB4A),A            ; just below Maroc (this will always be the same
                          ; screen position)
  LD A,$1D                ; Set the horizontal (half-character/4-pixel)
  LD ($EB48),A            ; position of the object to Maroc's horizontal
                          ; position (this will always be the same screen
                          ; position)
  CALL LDADC              ; Fetch the item state and prepare graphics for
                          ; printing
  CALL LE0B0              ; The item is now in the room, so copy the item
                          ; details into one of the room item data sets at 7C00
  LD (HL),$FF             ; Set an end-of-data marker at the start of the next
                          ; room item data set
  LD ($EB72),HL           ; Re-store the room item set address pointer.

; Check if Maroc is out of energy
;
; Used by the routine at LD90C.
LD940:
  LD A,($EAE0)            ; Check Maroc's energy
  CP $00                  ; Is it zero?
  JR NZ,LD94C             ;
  LD A,$01                ; If so, Maroc is out of energy - set room number to
  LD ($EAB0),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
                          ; LDA0A_3.

; Deal with room items when Maroc leaves the room
;
; Used by the routines at LBF60 and LD940.
;
; Evaluates objects in data sets at 7C00 and store state of any DOORS,
; CREATURES or OBJECTS.
LD94C:
  LD A,($EAB0)            ; Room number
  CP $00                  ;
  JP Z,LC6B6              ; If it's zero, it means that room's all set up, so
  LD A,$00                ; jump to the main game cycle
; Start preparing the room items that will need dealing with:
  LD ($EBB7),A            ; Set the creatures in the room to zero
  LD HL,(LDAEE)           ; Pointer to start of the room data sets at 7C00
  LD DE,$0010             ; 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 7C00 in turn:
LD94C_0:
  LD A,(HL)               ; Get first byte of data set
  CP $FF                  ; Check for end-of-data marker
  JP Z,LDA0A              ; If found, skip copying routine
  LD DE,$0010             ;
  CP $00                  ; If first data byte <> 0, there's some data to copy
  JR NZ,LD94C_1           ; for this set
  ADD HL,DE               ; First data byte is zero, so skip to next data set
  JR LD94C_0              ; and keep checking data sets
; Copy 16 bytes of data from this set at 7C00 to the data buffer at LEB43:
LD94C_1:
  LD BC,$0010             ; 16 bytes to copy
  LD DE,LEB43             ; Start of buffer (destination)
  LDIR                    ;
  LD ($EABE),HL           ; Store data pointer ready at the start of the next
                          ; data bank
; Check what the item in the data set is:
  LD A,(LEB43)            ; Get first byte of data set which indicates the item
                          ; type
  CP $02                  ; Door
  JR Z,LD94C_2            ;
  CP $04                  ; Interactable object
  JR Z,LD94C_3            ;
  CP $03                  ; Creature
  JR Z,LD94C_4            ;
  JR LD94C_0              ; If not one of these three items, no extra
                          ; processing needed at this point, so jump back and
                          ; continue copying data sets
; DOOR
LD94C_2:
  LD HL,($EB44)           ; Address pointer to door connector data set in the
                          ; table at L6790
  INC HL                  ; Move to 3rd byte of data set
  INC HL                  ;
  LD A,($EB4E)            ; This is the door properties byte
  LD (HL),A               ; Store in the 3rd byte of the room connector data
                          ; set
  LD HL,($EABE)           ; Retrieve address pointer to current data set at
                          ; 7C00
  JR LD94C_0              ; ...and continue to check data sets
; INTERACTABLE OBJECT
LD94C_3:
  LD HL,($EB44)           ; Address pointer to object data set in the table at
                          ; L736F
  LD A,($EAB7)            ; 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 ($EB44),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
; L736F)
  LD HL,($EAF8)           ; 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,($EB47)           ; 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,($EB44)           ; horizontal position in 4-pixel steps)
  LD (HL),A               ; Store as the 2nd byte of the object's data set at
                          ; L736F
  INC HL                  ; Move address pointer to next byte (which stores the
                          ; item's vertical pixel position)
  LD ($EB44),HL           ; Store the address pointer
  LD HL,($EAF6)           ; Get vertical room pixel position
  EX DE,HL                ; Swap into DE
  LD HL,($EB49)           ; 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,($EB44)           ; Retrieve the address pointer to the 3rd byte of the
                          ; object's data set at L736F
  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,($EB4E)            ; Get item properties byte
  AND $EF                 ; 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,($EABE)           ; Restore pointer to data set at 7C00
  JR LD94C_0              ; Continue to copy data sets
; CREATURE
LD94C_4:
  LD B,$00                ; The B register will hold a value indicating the
                          ; type and number of creatures in the room
  LD A,($EB4E)            ; Creature properties byte
  AND $E0                 ; Check if any of the top 3 bits are set: Bit 6/7 =
                          ; creature materializing Bit 5 = creature
                          ; disintegrating
  JR NZ,LD94C_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 EB46, and determine which bit values (see L6B8C) to
; add to the byte value at EBB7.
  LD A,($EB46)            ; Creature type
  CP $08                  ; Byte value < 8, it's a warlock (no action to take
  JR C,LD94C_8            ; as they're not 'stored')
  CP $08                  ;
  JR NZ,LD94C_5           ;
  LD B,$40                ; Byte value = 8, it's a guardian of chaos (set value
LD94C_5:
  CP $09                  ; = 64, these creatures are stored in bits 6 & 7)
  JR NZ,LD94C_6           ;
  LD B,$10                ; Byte value = 9, it's a goblin warrior (set value =
LD94C_6:
  CP $0A                  ; 16, these creatures are stored in bits 4 & 5)
  JR NZ,LD94C_7           ;
  LD B,$04                ; Byte value = 10 it's a goblin missile thrower (set
LD94C_7:
  CP $0B                  ; value = 4, these creatures are stored in bits 2 &
  JR NZ,LD94C_8           ; 3)
  LD B,$01                ; 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.
LD94C_8:
  LD A,($EBB7)            ; Creature data byte for room
  ADD A,B                 ; Add the creature type value
  LD ($EBB7),A            ; ...and re-store
  LD HL,($EABE)           ; Retrieve address pointer to the next data set (at
  JP LD94C_0              ; 7C00)

; Maroc's room number has changed - identify new room number
;
; Used by the routine at LD94C.
;
; 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.
LDA0A:
  LD A,($EAB7)            ; Get room number
  CP $E0                  ; Check if it's a tunnel room (room numbers 224-255)
  JR NC,LDA0A_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 (EBB7),
; calculated in the previous routine, in the relevant room's creature data set
; at L6790.
  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,$00                ;
  LD HL,($DAF0)           ; Address pointer for the room creature data set at
                          ; L6B8C
  ADD HL,BC               ; Add offset (with C = room number)
  LD A,($EBB7)            ; Byte indicating which creatures are in the room
                          ; (that Maroc is leaving)
  LD (HL),A               ; Copy into the room creature data at L6790
; Get new room number:
LDA0A_0:
  LD A,($EAB0)            ; Get (new) room number data byte
  CP $FF                  ; 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
                          ; L6790
  JR NZ,LDA0A_2           ; If already calculated, skip the next few
                          ; instructions
  LD HL,($EAB5)           ; Address pointer to connecting door data at L6790
  LD A,($EAB7)            ; 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,LDA0A_1           ; If not, the new room is byte 2
  INC HL                  ; If so, we need byte 3
LDA0A_1:
  LD A,(HL)               ; Get the room byte from the connecting door table
  JR LDA0A_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
LDA0A_2:
  LD C,A                  ; Calculated room number - temp store in C
  LD A,$30                ; Set Maroc's vertical pixel position in the room to
  LD (LEB74),A            ; 48 pixels
  LD A,$10                ; Set Maroc's horizontal room position
  LD ($EB75),A            ; (4-pixel/half-character steps) to 16
  LD A,$00                ;
  LD ($EB76),A            ; Set Maroc's room vertical position to 0
  LD A,C                  ; Retrieve byte (EAB0) 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.
LDA0A_3:
  LD ($EAB7),A            ; Store new room number (e.g. = room #1 when Maroc is
                          ; out of energy, room #61 for SUMMON)
  LD A,($EAE0)            ; Check Maroc's energy level
  CP $00                  ; Is it zero?
  JP NZ,LC107             ; 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:
LDA4D:
  CALL LE46C              ; Maroc out of energy - run 'death' animation routine
; Set up screen to display Maroc's current rank
  CALL LE25B              ; Clear the playing area (pixels)
  LD A,$42                ; Set the screen attribute colours to INK 2, BRIGHT
  LD ($EAA9),A            ; 1, PAPER 0
  LD (LEAA7),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 LE207              ; Draw the attribute colours on screen
; Draw the demon graphic:
  LD A,$01                ; Demon frame number = 1
  LD ($EB50),A            ;
  LD A,$58                ; Offset for graphic address table at L97C3. Will
                          ; point to address at 9871, for demon graphics stored
                          ; at A6CF.
  CALL LE0C2              ; Set up graphic to draw
  LD A,$70                ; Horizontal screen position, in pixels
  LD ($EAD3),A            ;
  LD A,$40                ; Vertical position, in pixels, from top of playing
  LD ($EAD2),A            ; area
  LD A,$01                ; Set draw/erase flag to 1 (DRAW)
  LD ($EACF),A            ;
  LD A,$00                ; High byte for horizontal graphic position, 0
  LD ($EAD4),A            ; indicates that the graphic is on-screen (within the
                          ; viewport) as opposed to off to the right or left
  LD HL,($EB51)           ; Retrieve address pointer for graphics
  LD ($EACD),HL           ; ...and copy into graphics buffer
  CALL LDB98              ; Draw the demon graphic on screen
  JP LC0A3                ; Print Maroc's rank on the scroll and play music

; Game completion - Maroc has destroyed Avelach, Lord of Chaos
;
; Used by the routine at LCC27.
;
; Game completion. Maroc has used Caliburn on Avelach in the High Temple of
; Chaos (event check at LCC27).
LDA88:
  LD A,$FF
  LD ($EB56),A            ; (255 = max) length/frequency for white noise effect
LDA88_0:
  LD ($EAC7),A            ; (255 = max) counter duration for white noise effect
  LD ($EAA9),A            ; Also set as attribute value for screen
; Change (decrement) screen colour attributes and play sound effects
  CALL LE207              ; Set screen colour
  CALL LE1D7              ; Play sound effect
  LD A,($EAC7)            ; Get counter
  DEC A                   ; Decrement counter (also the screen colour/attribute
                          ; value)
  JR NZ,LDA88_0           ; Repeat until counter at zero
; Print success message on scroll:
  CALL LEA34_4            ; Reset attributes in top right corner of scroll (in
                          ; case the spell icon is FLASHING)
  CALL LDEF9              ; Clear the scroll area
  LD A,$23                ; Message number 35 to print (L72F9)
  CALL LE5A5              ; Identify the message text to print
  LD (LEAA1),HL           ; Re-store the address pointer for the end of the
                          ; text string
  LD HL,$5087             ; Screen display address to print the text
  LD ($EAA4),HL           ;
  CALL LE2D0              ; Set up message text on scroll to print
; Play one complete set of game (intro/main theme) music:
  LD A,$01                ; Tune number #1
  CALL LE5B6              ; Play the tune
; Calculate and print the player's (final) rank on the scroll:
  CALL LDEF9              ; Clear the scroll area
  CALL LE4E7              ; Calculate and print rank on scroll
; Play game (intro) tune on a loop:
LDA88_1:
  LD A,$01                ; Tune number #1
  CALL LE5B6              ; Play the tune
  JR LDA88_1              ; ...and repeat until the player resets their
                          ; Spectrum...

; Object - vertical room position check/adjustment
;
; Used by the routines at LCB00, LCB5B and LD12E.
;
; 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 LE039
LDAC8:
  LD A,($EB4A)            ; Graphic vertical position (of object) from top of
                          ; screen (pixels)
  LD E,A                  ; Store in E register
  LD HL,$EAF6             ; 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,$60                ; 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,LDAC8_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 $7F                 ; Halve this value, and filter out bit 7 as it's not
                          ; needed
  ADD A,E                 ; Store in E register
  LD E,A                  ;
LDAC8_0:
  RET                     ;

; Fetch object state and prepare graphics for printing
;
; Used by the routines at LCC27, LD019, LD833 and LD90C.
LDADC:
  LD HL,($EB44)           ; Address pointer to room object in table at L736F
  CALL LDE7F              ; Identify state of object
  LD A,$01                ; Set object frame offset to 1 (= no offset)
  LD ($EB50),A            ;
  LD A,($EB90)            ; Graphic number, used to calculate graphic address
                          ; in table at L97C3
  CALL LE0C2              ; Set up object graphics
  RET                     ;

; Store for base address pointers
LDAEE:
  DEFW L7C00              ; Pointer to the start of the room item data sets
                          ; stored at 7C00
  DEFW L6B8C              ; Address pointer for room creature data
  DEFB $FF                ; Unused
  DEFW L736F              ; Address pointer - room objects data sets
  DEFW L6790              ; Address pointer to connecting door sets
  DEFW L61A9              ; Address pointer to room data

; Unused
LDAF9:
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00

; Generate pseudo-random number using ROM address values
;
; Used by the routines at LC8DC, LCBA8, LCDD7, LCED4, LD651, LD71C, LDF33 and
; LE16A.
;
; 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.
LDB06:
  LD ($DB1D),HL           ; Preserve HL register pair
  LD HL,($DB1B)           ; 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 $1F                 ; (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 ($DB1B),HL           ; Store the ROM address pointer for next time
  LD HL,($DB1D)           ; Retrieve HL register pair
  RET                     ;
; Store for registers used in the above routine
  DEFW $0000              ; Store for incrementing ROM address pointer. Starts
                          ; at 0
  DEFW $0000              ; Temp store for HL register pair during the routine

; Set up missile data and calculate trajectory
;
; Used by the routine at LD794.
;
; A Missile number (see table at L6CDC)
;
; Calculates and puts missile data into room object sets at 7C00 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 L6CDC)
; using the missile number:
LDB1F:
  LD C,A                  ; Temp store missile number in C register
  LD HL,(LEBC1)           ; Address pointer to missile data table at L6CDC
  DEC A                   ; Offset needed is 0-8 (not 1-9) so decrement missile
                          ; number
  LD D,$00                ; Store offset in DE register pair
  LD E,A                  ;
  LD B,$08                ; 8 bytes in each missile data set
LDB1F_0:
  ADD HL,DE               ;
  DJNZ LDB1F_0            ; Continue adding until HL is pointing at the start
                          ; of this missile's data set in the table at L6CDC
  LD ($EB9B),HL           ; Store missile table address pointer
; Create a new room item data set for the missile at 7C00, and copy a few
; variables from the missile-related data at L6CDC and LEB91 into it.
  INC HL
  LD A,(HL)               ; Get missile properties byte (second byte in missile
                          ; data set at L6CDC)
  LD ($EB9E),A            ; ...and copy into the missile data buffer (starts
  DEC HL                  ; from LEB91)
  EX DE,HL                ; Swap (start of) data set pointer into DE register
                          ; pair
  LD HL,($EB72)           ; Address pointer to next data bank at 7C00
  LD A,($EB9A)            ; 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 7C00
  INC HL                  ;
  LD (HL),E               ; Store address pointer to start of missile table at
  INC HL                  ; L6CDC in bytes 2 & 3 of room item data set (at
  LD (HL),D               ; 7C00)
  INC HL                  ;
  LD (HL),C               ; Store missile number (table at L6CDC) as byte 4 of
  INC HL                  ; room item data set (at 7C00)
  LD B,$04                ; Copy 4 bytes of data to room item (missile) data
  LD DE,$EB94             ; set at L7C00:
LDB1F_1:
  LD A,(DE)               ; * EB94 --> byte 5 of set (horizontal position
  LD (HL),A               ;   precision/fraction byte)
  INC DE                  ; * EB95 --> byte 6 of set (horizontal position in
  INC HL                  ;   4-pixel steps)
  DJNZ LDB1F_1            ; * EB96 --> byte 7 of set (vertical position
                          ;   precision/fraction byte)
                          ; * EB97 --> byte 8 of set (vertical pixel position)
  LD (HL),$40             ; 9th data byte in room item data sets at 7C00 - 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 7C00.
;
; Horizontal position difference (between origin and target) calculation:
  LD A,($EB95)            ; Horizontal position of missile origin
  LD C,A                  ; (half-character steps)
  LD A,($EB98)            ; 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,($EB97)            ; Vertical screen position of missile origin (in
  LD C,A                  ; pixels)
  LD A,($EB99)            ; 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
; 7C00.
  LD A,$01                ; Missile graphic frame offset (frame 1 = no offset)
  LD ($EB50),A            ;
  LD DE,($EB9B)           ; Retrieve address pointer to missile data table at
                          ; L6CDC
  LD A,(DE)               ; Get graphic number for the missile graphics for use
                          ; in the following CALL
  LD ($EB72),HL           ; Temp store for address pointer current position in
                          ; the data at 7C00
  CALL LE0C2              ; Set up missile graphics
  LD HL,($EB72)           ; Retrieve data set address pointer stored before the
                          ; CALL
  LD A,($EB9E)            ; Missile properties byte
  LD (HL),A               ; Store as 12th byte of room item data set
  INC HL                  ;
  LD A,($EB4F)            ; Missile pre-graphics data byte
  LD (HL),A               ; Store as 13th byte of set
  INC HL                  ;
  LD A,$11                ; 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 7C00
  LD DE,($EB51)           ; Missile graphics address pointer (table at L97C3)
  LD (HL),E               ; Store as the last two byes in the data set
  INC HL                  ;
  LD (HL),D               ;
  INC HL                  ;
  LD (HL),$FF             ; Put end-of-data marker at start of next data set...
  LD ($EB72),HL           ; ...and store data set pointer
  RET                     ;

; Draw/erase graphics - screen boundary checks
;
; Used by the routines at LC03F, LD27D, LD446, LD4B2, LDA4D, LE46C, LE987 and
; LE9DD.
;
; HL Address pointer for graphics to draw, from address pointer table at L97C3
;
; 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.
LDB98:
  LD E,(HL)               ; Transfer the address (from L97C3) 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. 9950
  LD A,$00                ; 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 ($EAD5),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 LDBF5
  LD A,(HL)               ; Number of tiles that make up the graphic/sprite
  LD ($EAD0),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 LDC77.
LDB98_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,($EAD3)           ; 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 $00                  ; If high byte changed from 0 to 1, the graphic has
                          ; gone out of the screen's viewport boundary
  JP NZ,LDC77             ; ...if so, skip out of this routine to deal with the
                          ; out-of-bounds graphic
  LD A,E                  ; Get horizontal pixel position
  CP $E8                  ; 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,LDC77             ; If there's no carry, jump out of this routine to
                          ; deal with the out-of-bounds graphic
  ADD A,$08               ; 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 LDBF5
  AND $07                 ; 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 LDBF5_1
; Calculate vertical (Y) pixel offset, check for out of bounds
  LD A,($EAD2)            ; 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 $70                  ; Vertical pixel position 112 is the top of the
                          ; scroll, which is out of bounds for drawing graphics
  JP C,LDB98_1            ; Carry means (at least the top part of) the item is
                          ; within the screen viewport and drawable, so jump to
                          ; LDB98_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,LDC77_0           ; out-of-bounds position
  JP Z,LDC77_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 ($EAD1),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,$00                ;
  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,$10                ; Set the vertical screen position to 16 pixel rows
                          ; down - the first byte of character row 2, just
                          ; below the top border
  LD C,$00                ; 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 LDBF5                ; Ready to calculate screen address low/high bytes
; Jump from DBCD. 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).
LDB98_1:
  ADD A,$10               ; 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 ($EAD1),A            ; ...and store...
  LD A,D                  ; Get A back from D (mystery value - now 71)
  AND $07                 ; 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 LDB98.
;
; B Number of horizontal pixel shifts/rotates (rotated at DC2B) 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
LDBF5:
  LD A,$01                ; This is the flag indicating whether (any part of
                          ; the graphic) is visible on-screen (0 = not visible,
                          ; 1 = visible)
  LD ($EAD5),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 $1F                 ; 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 $E0                 ; 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 $18                 ; Bits 3 (8) and 4 (16) include the screen display
                          ; address high byte character row (0-24)
  ADD A,$40               ; 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,($EAD1)            ; Number of bytes in the graphic tile to draw
  LD C,A                  ; Store in C as a counter (checked later at DC70)
; 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 $1F                 ; Bits 0-4 (values 0-31) give us the screen vertical
                          ; (character) column
  CP $01                  ; Check if we're into the left border (column 1)
  JP Z,LDCD5              ;
  CP $1D                  ; Check if we're into the right border (column 29)
  JP Z,LDC89              ;
; Start of tile graphic draw/erase loop - jump back here from DC73
;
; Shifts graphic so that shifted graphics byte contained in 2 bytes, H & L,
; ready to draw on screen
LDBF5_0:
  LD A,(HL)               ; Get graphics byte
  INC HL                  ; ...And move graphic address pointer along, ready
                          ; for next one
  CP $00                  ; Byte empty?
  JR Z,LDC53_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,$00                ; Clear L register ready to receive shifted bits
  LD A,B                  ; Temp store for the 'shift counter' (containing
                          ; number of right-shifts needed)
  CP $00                  ; Any more shifts needed?
  JR Z,LDBF5_2            ; ...If not, skip out of the shift loop
LDBF5_1:
  RR H                    ; Rotate byte in H register into L register
  RR L                    ;
  DJNZ LDBF5_1            ; Repeat for number of shifts (counter)
  LD B,A                  ; Reset the shift counter (from A register)
LDBF5_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,($EACF)            ; Check draw/erase flag
  CP $01                  ; 0 = Erase, 1 = Draw
  JR Z,LDC4C              ; 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
;    DC2A
; 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
LDC41:
  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 LDC53                ; Byte now erased

; Draw/erase graphics - draw graphic bytes
;
; Used by the routine at LDBF5.
;
; 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 DC2A
; HL Screen display address to draw byte
;
; Draws graphic bytes on screen, combining with any existing screen background
; bytes
LDC4C:
  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 LDC41.
;
; HL Screen display address +1 for the byte that has just been drawn or erased
;
; After drawing (LDC4C) or erasing (LDC41) 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
LDC53:
  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 LDBF5.
LDC53_0:
  LD A,D                  ; Get high byte of screen address
  INC A                   ; ...and increment (move down 1 pixel row)
  AND $07                 ; Are we crossing into a new character row (8th pixel
  JR Z,LDC53_1            ; row)?
  INC D                   ; If not, increment screen display address pointer
  JR LDC53_2              ; (move down 1 pixel row)
LDC53_1:
  LD A,D                  ; Otherwise, adjust high byte to the correct screen
                          ; address
  AND $F8                 ; 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,$20               ; Increment column by 32 to move down to next screen
  LD E,A                  ; row
  JR NC,LDC53_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,$08               ; 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:
LDC53_2:
  LD A,D
  CP $50                  ; 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,LDC77_0           ; Jump to LDC77_0 if into last 3rd of screen (out of
                          ; bounds)
  JR NZ,LDBF5_0           ; Bytes left to draw in the tile - continue to draw
  JR LDC77_1              ; next tile byte

; Draw/erase graphics - graphic tile out of bounds
;
; Used by the routine at LDB98.
;
; 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).
LDC77:
  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 DBD0, 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               |
; +----+----------------------------------------------------+
LDC77_0:
  LD D,$00
  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
LDC77_1:
  LD A,($EAD0)            ; Get tile counter (number of tiles in current
                          ; graphic)
  DEC A                   ; Decrement counter
  LD ($EAD0),A            ; ...and re-store
  JP NZ,LDB98_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 LDBF5.
;
; 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 DC2A
; * Erase graphic byte routine at LDC41
; * Draw graphic byte routine at LDC4C
; * Re-calculate screen display address 1 pixel lower routine at LDC53
;
; The opposite routine (graphic partially obscured by left-hand screen border)
; is at LDCD5.
LDC89:
  LD A,(HL)               ; Get graphics byte
  INC HL                  ; ...and move graphic address pointer along, ready
                          ; for next one
  CP $00                  ; Byte empty?
  JR Z,LDC89_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,$00                ; Clear L register ready to receive shifted bits
  LD A,B                  ; Temp store for the 'shift counter' (containing
                          ; number of right-shifts needed)
  CP $00                  ; Any more shifts needed?
  JR Z,LDC89_1            ; ...If not, skip out of the shift loop
LDC89_0:
  RR H                    ; Rotate byte in H register into L register
  RR L                    ;
  DJNZ LDC89_0            ; Repeat for number of shifts needed (counter)
  LD B,A                  ; Reset the shift counter (from A register)
LDC89_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,($EACF)            ; Check draw/erase flag
  CP $01                  ; 0 = Erase, 1 = Draw
  JR Z,LDC89_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 LDC89_3              ;
; DRAW SCREEN BYTE
;
; No need to draw the second graphic byte (stored in E register) as it's on the
; screen border.
LDC89_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.
LDC89_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 DC8D if byte empty)
LDC89_4:
  LD A,D                  ; Get high byte of screen address
  INC A                   ; ...and increment (move down 1 pixel row)
  AND $07                 ; Are we crossing into a new character row (8th pixel
  JR Z,LDC89_5            ; row)?
  INC D                   ; If not, increment screen display address pointer
  JR LDC89_6              ; (move down 1 pixel row)
LDC89_5:
  LD A,D                  ; Otherwise, adjust high byte to the correct screen
                          ; address
  AND $F8                 ; 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,$20               ; Increment column by 32 to move down to next screen
  LD E,A                  ; row
  JR NC,LDC89_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,$08               ; 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
LDC89_6:
  LD A,D
  CP $50                  ; Are we into the last 3rd of the screen?
  DEC C                   ; (Decrement number of tile bytes to draw)
  JP NC,LDC77_0           ; Jump to LDC77_0 if into last 3rd of screen (out of
                          ; bounds)
  JR NZ,LDC89             ; If bytes left to draw in the tile - continue to
  JP LDC77_1              ; draw next tile byte

; Draw/erase graphics - graphic partly out of bounds - LEFT border of play area
;
; Used by the routine at LDBF5.
;
; 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 DC2A
; * Erase graphic byte routine at LDC41
; * Draw graphic byte routine at LDC4C
; * Re-calculate screen display address 1 pixel lower routine at LDC53
;
; The opposite routine (graphic partially obscured by right-hand screen border)
; is at LDC89.
LDCD5:
  LD A,(HL)               ; Get graphics byte
  INC HL                  ; ...and move graphic address pointer along, ready
                          ; for next one
  CP $00                  ; Byte empty?
  JR Z,LDCD5_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,$00                ; Clear L register ready to receive shifted bits
  LD A,B                  ; Temp store for the 'shift counter' (containing
                          ; number of right-shifts needed)
  CP $00                  ; Any more shifts needed?
  JR Z,LDCD5_1            ; ...If not, skip out of the shift loop
LDCD5_0:
  RR H                    ; Rotate byte in H register into L register
  RR L                    ;
  DJNZ LDCD5_0            ; Repeat for number of shifts needed (counter)
  LD B,A                  ; Reset the shift counter (from A register)
LDCD5_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,($EACF)            ; Check draw/erase flag
  CP $01                  ; 0 = Erase, 1 = Draw
  JR Z,LDCD5_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 LDCD5_3              ;
; DRAW SCREEN BYTE
LDCD5_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
LDCD5_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 DCD9 if byte to draw is empty)
LDCD5_4:
  LD A,D                  ; Get high byte of screen address
  INC A                   ; ...and increment (move down 1 pixel row)
  AND $07                 ; Are we crossing into a new character row (8th pixel
  JR Z,LDCD5_5            ; row)?
  INC D                   ; If not, increment screen display address pointer
  JR LDCD5_6              ; (move down 1 pixel row)
LDCD5_5:
  LD A,D                  ; Otherwise, adjust high byte to the correct screen
                          ; address
  AND $F8                 ; 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,$20               ; Increment column by 32 to move down to next screen
  LD E,A                  ; row
  JR NC,LDCD5_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,$08               ; 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
LDCD5_6:
  LD A,D
  CP $50                  ; Are we into the last 3rd of the screen?
  DEC C                   ; (Decrement number of tile bytes to draw)
  JP NC,LDC77_0           ; Jump to LDC77_0 if into last 3rd of screen (out of
                          ; bounds)
  JR NZ,LDCD5             ; If bytes left to draw in the tile - continue to
  JP LDC77_1              ; draw next tile byte

; Draw the spell pointer arrow, spell charge icons and energy bar on the scroll
;
; Used by the routines at LE641, LE6FA and LE753.
;
; DE Screen display address location to draw at
;
; Draws the scroll arrow (called from LE641), the spell 'charge' icons (called
; from LE6FA) or the energy bar (called from E76E)
LDD24:
  LD HL,($EB51)           ; Get graphics address pointer from L97C3
  LD A,(HL)               ; Get the graphics address pointer low byte for the
                          ; arrow (AFA6), the scroll charge icons (AEE7), or
                          ; the energy bar (LAEF3)
  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
LDD24_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 ($EADE),DE           ; Store screen display address position
; Draw graphic tile on screen
LDD24_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 $07                 ;
  INC A                   ; Move down to next pixel row
  CP $08                  ; Are we crossing a pixel/character boundary?
  JR C,LDD24_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 $F8                 ; 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,$20               ; Increment column by 32 to move down to next screen
  LD E,A                  ; row
  JR NC,LDD24_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,$08               ; accordingly
  LD D,A                  ; Store correct screen address high byte back in D
  JR LDD24_3              ; register
LDD24_2:
  INC D                   ; Move down 1 pixel row
LDD24_3:
  DJNZ LDD24_1            ; Repeat for all pixel rows of this graphics tile
; Continue to draw the remaining tiles in the graphic
  LD DE,($EADE)           ; Retrieve screen display address
  INC E                   ; Move right one character square
  DEC C                   ; Decrement tile graphic counter
  JR NZ,LDD24_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 LE77E, LE852, LE929 and LEA1D.
;
; Called from routine at E797. This prints the relevant spell message text (at
; L6FBC) for the active spell using the text print routine at LE2D0_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 DD75
; * So for "PROJECT THY SOUL" (MOVE spell), instead of "P", then "R", then "O"
;   etc. being printed, we have "P", "PR", "PRO", "PROJ" etc.
LDD5C:
  LD A,($EBC9)            ; Character number in the current spell message text
  LD C,A                  ;
  LD DE,($EAEA)           ; 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,LDD7E              ; If so, skip the text print routine
  LD A,C                  ; Retrieve and increment the text counter number...
  INC A                   ;
  LD ($EBC9),A            ; ...and re-store
  LD (LEAA1),DE           ; Store the text address pointer
  LD ($EAA3),A            ; Number of text characters to print
  LD HL,$5088             ; Set screen display address - middle of scroll, on
                          ; left
  LD ($EAA4),HL           ; ...and store
  CALL LE2D0_0            ; Print text on scroll

; Set length of Maroc's energy bar based on his current energy level
;
; Used by the routine at LDD5C.
;
; 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.
LDD7E:
  LD A,($EAE0)            ; 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 $0F                 ; Keep the bottom four bits to give a value of 0-15
  LD C,A                  ;
  LD A,$10                ; Subtract from 16 to give the number of energy bar
  SUB C                   ; characters to remove
  LD B,$10                ; 16 character squares
  LD HL,$5AC7             ; 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.
LDD7E_0:
  CP B                    ; Check current position to see if it's one that
                          ; needs obscuring
  JR C,LDD7E_1            ; If there's a carry, jump to LDD7E_1 to keep the
  CP $01                  ; character square as INK 2, PAPER 6
  JR Z,LDD7E_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),$36             ; Set the character square attribute as invisible
  JR LDD7E_2              ; (INK 6, PAPER 6)
LDD7E_1:
  LD (HL),$32             ; Set the character square attribute as visible (INK
                          ; 2, PAPER 6)
LDD7E_2:
  INC HL                  ; Move screen attribute address right one character
                          ; square along the energy bar
  DJNZ LDD7E_0            ; ...and keep checking for all 16 squares.
  RET                     ;

; Draw/erase foreground scenery items
;
; Used by the routine at LD4FC.
;
; These drawing/erasing routines are similar to the standard ones at LDBF5, but
; because the foreground scenery occupies its own screen area and won't overlap
; other scenery, they're simplified slightly.
LDDA1:
  LD A,$00                ; Flag indicating whether (any part of) graphic is
  LD ($EAD5),A            ; visible on screen - set to 0 at start of graphics
                          ; routine
  LD HL,($EACD)           ; Graphic address pointer to foreground scenery
                          ; graphics
  LD A,(HL)               ; Byte indicating number of tiles within the graphic
  INC HL                  ;
; Tile drawing loop
LDDA1_0:
  LD ($EAD0),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,($EAD3)           ; 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 $00                  ;
  JP NZ,LDDA1_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 $1F                 ; Filter out bits 5-7 (only values 0-31 needed)
  DEC A                   ;
  CP $1C                  ; Right-hand column screen border check
  JP NC,LDDA1_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,($EAD2)            ; Graphic's vertical screen position
  ADD A,C                 ; Add the offset
  CP $70                  ; Vertical pixel position 112 is the top of the
                          ; scroll, out of bounds for drawing graphics
  JR NC,LDDA1_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,$10               ; 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 $07                 ; 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,$01                ; This is the flag indicating whether (any part of
                          ; the graphic) is visible on-screen (0 = not visible,
                          ; 1 = visible)
  LD ($EAD5),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 $E0                 ; 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 $18                 ; Bits 3 (8) and 4 (16) include the screen display
                          ; address high byte character row (0-24)
  ADD A,$40               ; 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,($EACF)            ; Check draw/erase flag
  CP $01                  ;
  JR Z,LDDA1_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 $07                 ; 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:
LDDA1_1:
  LD (HL),$00             ; 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 $07                 ;
  JR Z,LDDA1_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 LDDA1_3              ; ...And continue clearing the square
; Re-calculate screen display address with new pixel row:
LDDA1_2:
  LD A,H                  ; Reset pixel row (bits 0-2 in high byte of the
  AND $F8                 ; screen display address)
  LD H,A                  ;
  LD A,L                  ; Increment column by 32 to move down to next screen
  ADD A,$20               ; row
  JR C,LDDA1_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,$00                ; ...reset the pixel counter to 0...
LDDA1_3:
  DJNZ LDDA1_1            ; ...and draw the rest of the bytes in the tile
  JR LDDA1_9              ; When finished, go and check if there are more tiles
                          ; to draw
; DRAW graphic pixels on screen:
LDDA1_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 $07                 ;
  JR Z,LDDA1_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 LDDA1_6              ; ...And continue clearing the square
; Re-calculate screen display address with new pixel row:
LDDA1_5:
  LD A,H                  ; Reset pixel row (bits 0-2 in high byte of the
  AND $F8                 ; screen display address)
  LD H,A                  ;
  LD A,L                  ; Increment column by 32 to move down to next screen
  ADD A,$20               ; row
  JR C,LDDA1_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
LDDA1_6:
  DJNZ LDDA1_4            ; ...and continue to draw the rest of the tile
                          ; graphic
  JR LDDA1_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.
LDDA1_7:
  DEC DE                  ; DE was prematurely incremented in the loops at DE04
                          ; or DE1F so if this was done, revert this change
LDDA1_8:
  INC DE                  ; Then increment it by the remaining tile bytes, to
  DJNZ LDDA1_8            ; get to the start of the next tile
; Tile finished - check for next tile:
LDDA1_9:
  EX DE,HL                ; Swap the screen display address and graphics
                          ; address pointers
  LD A,($EAD0)            ; Get the graphic tile counter
  DEC A                   ; Reduce by one
  JP NZ,LDDA1_0           ; If there are still tiles to draw, go and draw them
  JR LDDA1_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
; DDC9) or into the scroll at the bottom third of the screen (from DDD6)
;
; Nothing to draw/erase for the rest of this tile, so can skip past it
LDDA1_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 LDDA1_8              ; Jump to the routine that skips the rest of the
                          ; bytes
; Jump here once all of the tiles have been drawn/erased
LDDA1_11:
  RET

; Identify objects for current room
;
; Used by the routines at LC42A, LCEB1 and LD019.
;
; B Room number (from EAB7)
; HL Address pointer to start of room item data at L736F
; C Object number in table at L736F (starts at #1)
;
; This routine uses the room object table at L736F 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 EB85.
LDE4C:
  LD A,($EB84)            ; 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 ($EB84),A            ; ...and re-store
  LD A,(HL)               ; First byte of data set
  CP $FF                  ;
  JR NZ,LDE4C_0           ;
  LD ($EB84),A            ; We've reached the end of the list - set counter
                          ; byte to 255...
  JR LDE7F_5              ; ...and jump straight to RET
; There are data sets still to check:
LDE4C_0:
  LD A,C                  ; Are we doing the check against an object number or
  CP $00                  ; a room number?
  JR NZ,LDE4C_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,LDE7F              ; If so, we've found an object in the room so jump to
  JR LDE4C_2              ; next routine to deal with it
; OBJECT NUMBER CHECK
LDE4C_1:
  LD A,($EB84)            ; 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,LDE7F              ; 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.
LDE4C_2:
  LD DE,$0007             ; 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,$0004             ; 4 bytes for each set to skip
LDE4C_3:
  CP $00                  ; Have we skipped all the additional 4-byte sets for
                          ; this item?
  JR Z,LDE4C              ; 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 LDE4C_3              ; ...Until they're all skipped.

; Identify state of object in current room
;
; Used by the routines at LCB00, LDADC and LDE4C.
;
; HL Address pointer to room/object data at L736F
;
; The fifth byte of an object's data set (held in the object buffer at EB89)
; 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 EB8D.
LDE7F:
  LD (LEB82),HL           ; Store address pointer (data at L736F)
  LD DE,$EB85             ; Copy the first 8 bytes of this object's data into
  LD BC,$0008             ; buffer at EB85
  LDIR                    ;
  LD A,($EB89)            ; State number of this object. All standard object
  LD C,A                  ; 'sets' start at 1
  CP $00                  ;
  JR Z,LDE7F_3            ;
  DEC A                   ; Decrement state number
  CP $00                  ; Is this the object's current state?
  JR Z,LDE7F_1            ;
  LD DE,$0004             ; If so, skip 4 bytes for each state the object has
  LD B,A                  ; advanced to
LDE7F_0:
  ADD HL,DE               ;
  DJNZ LDE7F_0            ;
; Current object state found:
LDE7F_1:
  LD B,$04                ; Copy the 4 data bytes for this object state into
  LD DE,$EB8D             ; the additional buffer at EB8D
LDE7F_2:
  LD A,(HL)               ;
  LD (DE),A               ;
  INC HL                  ;
  INC DE                  ;
  DJNZ LDE7F_2            ;
; Skip over any additional data sets for this object
LDE7F_3:
  LD A,($EB8C)            ; 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,LDE7F_5            ; If zero, there's no more data for this set - jump
                          ; straight to RET
  LD DE,$0004             ; ...Otherwise, skip over the remaining object states
  LD B,A                  ;
LDE7F_4:
  ADD HL,DE               ;
  DJNZ LDE7F_4            ;
; This entry point is used by the routine at LDE4C.
LDE7F_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 LC42A.
;
; 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 LEB43, including
;   graphics data for the object
; * Copies this data into a room item data set at 7C00
LDEB7:
  LD A,$04                ; Graphic type = 4 (interactable object)
  LD (LEB43),A            ;
  LD A,($EB84)            ; Data set number for interactable object - from
  LD ($EB46),A            ; object table at L736F
  LD HL,(LEB82)           ; Address pointer to the beginning of this
  LD ($EB44),HL           ; interactable object's data set
  LD A,($EB86)            ; Horizontal (X) position of object in room, in
  LD ($EB48),A            ; 4-pixel (half-character) steps
  LD A,($EB87)            ; Vertical (Y) position of object in room, in pixels,
  LD ($EB4A),A            ; from top of room
  LD A,$40                ; 64 signifies item in 'standard' room (254/255 for
  LD ($EB4B),A            ; tunnel room items)
  LD DE,$0000             ; Set vertical and horizontal speed of item to zero
  LD ($EB4C),DE           ;
  LD ($EB4D),DE           ;
  LD A,($EB88)            ; Copy item properties byte into data buffer
  LD ($EB4E),A            ;
  LD A,$01                ; Graphic address frame offset = n-1 (= 0, no offset)
  LD ($EB50),A            ;
  LD A,($EB90)            ; Graphics number for this item (offset for address
                          ; pointer in graphics table starting at L97C3)
  CALL LE0C2              ; Set up graphics for this interactable object
  CALL LE0B0              ; Copy item data buffer (LEB43) into a data set at
  RET                     ; 7C00

; Clear the scroll status panel at the bottom of the screen
;
; Used by the routines at LC03F, LC763, LDA88, LE4E7, LE641, LE6FA and LEA34.
LDEF9:
  LD HL,$5047             ; Screen address for the top left of the scroll
  LD C,$05                ; 5 character rows to clear
LDEF9_0:
  LD D,$12                ; 18 columns wide
LDEF9_1:
  LD B,$08                ; 8 pixels in each character square
LDEF9_2:
  LD (HL),$00             ; Clear screen address byte
  INC H                   ; Move down 1 pixel row
  DJNZ LDEF9_2            ; Repeat x 8 pixel rows
  LD A,H                  ; Return address pointer to top of block
  SUB $08                 ;
  LD H,A                  ;
  INC L                   ; ...and move right one character square
  DEC D                   ; Repeat for 18 columns
  JR NZ,LDEF9_1           ;
  LD A,L                  ;
  ADD A,$0E               ; 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,LDEF9_0           ;
  LD HL,$50E7             ;
; 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,$0B                ; 11 character columns to clear
LDEF9_3:
  LD B,$04                ; Just 4 pixels (half a character square) needed to
                          ; clear
LDEF9_4:
  LD (HL),$00             ; Clear the screen byte
  INC H                   ; Move to the next pixel line down
  DJNZ LDEF9_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,LDEF9_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,$57D7             ; Screen address for top left of overlapping scroll
  LD (HL),$07             ; First byte
  INC HL                  ;
  LD (HL),$FF             ; Second byte
  RET                     ;

; Print spell names on the scroll
;
; Used by the routines at LE641 and LE699.
;
; Checks each spell in the spell index at L6DFC, 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.
LDF33:
  LD A,($EAE2)            ; Spell list index
  LD ($EAE5),A            ; Copy spell list index into spell list counter
  LD DE,($EAE3)           ; Address pointer to the start of spell list text at
                          ; L6DFC
  LD A,$01                ; Scroll text line counter (1-5)
  LD ($EAC7),A            ;
  LD HL,$504A             ; Screen address of top text line of scroll, 3
                          ; characters from the left hand side
LDF33_0:
  LD ($EADE),HL           ; Put screen display address in temp store for
                          ; retrieving later
  LD B,$08                ; Move address pointer along 8 bytes to get to the
LDF33_1:
  INC DE                  ; first/next spell text (e.g. "MOVE" at 6E04)
  DJNZ LDF33_1            ;
  LD (LEAA1),DE           ; Store spell text address pointer
  LD ($EAA4),HL           ; Store the screen display address
  LD A,$08                ; Store length of text string to print - spell texts
  LD ($EAA3),A            ; at L6DFC are padded with spaces to make them all 8
                          ; characters long
  CALL LE2D0_0            ; Print the spell text on the scroll
  LD HL,(LEAA1)           ; Retrieve the spell text address pointer - this is
                          ; now pointing at the data after the spell text, e.g.
                          ; 6E0C.
; 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.
LDF33_2:
  LD A,($EB69)            ; Total number of spells to check - 27
  LD C,A                  ;
  LD A,($EAE5)            ; Spell list counter
  CP C                    ; Check if at the end (spell #27)
  JR NZ,LDF33_3           ;
  LD A,$00                ; If so, reset counter to zero...
  LD HL,($EB65)           ; ...and return the spell name text address pointer
  JR LDF33_4              ; to the start of the list, e.g. L6DFC.
LDF33_3:
  INC A                   ; If we're not at the end of the list, increment the
LDF33_4:
  LD ($EAE5),A            ; spell list counter.
  LD A,(HL)               ; Get the the first byte (after the spell name).
  CP $10                  ; Check if this byte = 16, which indicates the player
                          ; has collected the spell
  JR Z,LDF33_5            ; If so, jump out and print the spell name
  LD BC,$0010             ; The player hasn't collected this spell, so move the
  ADD HL,BC               ; spell text address pointer along 16 bytes to the
  JR LDF33_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:
LDF33_5:
  OUT ($FE),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,($EAA6)            ; 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 $00                  ; Counter = 0?
  JR Z,LDF33_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 $E0                 ; Filter out unwanted bits 0-4
  LD B,A                  ; Store in B to act as a second counter
LDF33_6:
  CALL LDB06              ; Routine that generates a pseudo-random number.
  DJNZ LDF33_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
LDF33_7:
  LD A,($EAC7)            ; Continue to check the spell index (at L6DFC) to see
                          ; which spells Maroc has, and print them on the
                          ; scroll
  CP $05                  ; 5 spells can be printed on the scroll. Have they
                          ; all been done?
  JR Z,LDF33_9            ; If so, jump straight to RET at the end of this
                          ; routine
  INC A                   ; Otherwise, increment the scroll text line counter
  LD ($EAC7),A            ; ...and re-store.
  CP $03                  ; Are we on spell text line number 3?
  JR NZ,LDF33_8           ;
  LD A,($EAE5)            ; If so, this is the spell in the middle of the
                          ; scroll, that the selection arrow is pointing at
  LD ($EAE6),A            ; So set the 'currently highlighted' spell as this
                          ; one
  LD ($EAE7),HL           ; ...and also store the address pointer to this
                          ; spell's data (L6DFC).
; Prep for printing next line of text:
LDF33_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
                          ; LDF33_0)
  LD HL,($EADE)           ; Retrieve the screen display address
  LD BC,$0120             ; 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,$00                ; Toggle speaker (bit 4) off
  OUT ($FE),A             ;
  JR LDF33_0              ; Keep checking for spells to print
LDF33_9:
  RET                     ; RETurn after 5 spells printed

; Calculate servant/icon cursor graphic horizontal/vertical direction & speed
;
; Used by the routines at LE958 and LE987.
;
; A Left/right control value (from LEAFD) or up/down control value (from EAFE)
; C Horizontal/vertical movement speed at EB01/EB02
;
; 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 E95F (horizontal movement) and E98E (vertical movement).
LDFBC:
  CP $00                  ; Is there any movement in the direction being
                          ; checked (horizontal/vertical)?
  JR Z,LDFBC_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 $80                 ; Check bit 7 - if this bit is set, the servant has
                          ; reached terminal speed (in either direction)
  JR Z,LDFBC_1            ; However, the screen size means this speed can't be
                          ; reached, so a NZ (non-zero) result shouldn't
                          ; normally happen
LDFBC_0:
  LD H,$00                ; If terminal velocity has been reached, set
LDFBC_1:
  RET                     ; movement/speed back to zero

; Check for events/collisions
;
; Used by the routines at LCA8E, LCB96, LCC27, LCC72, LCD21, LCD66, LCD88,
; LD04B, LD116, LD1D2, LD479 and LD49D.
;
; C Collision/event type, e.g.: 0 = Collision with Maroc, e.g.: creature
;   missile hitting Maroc (D11D) or Maroc moving through an open doorway (CA19)
;   1 = Door opening/closing (LCA8E) 3 = Check for creature being destroyed
;   (e.g. by missile/sword) 5 = Servant picking up an object (LCD66) 15 = Item
;   being collected by Maroc (checked at LCC72) 136 = Check for Maroc entering
;   portal door in room 81 LD49D 137 = Maroc has destroyed Avelach with
;   Caliburn (CC2E) 253 = Check if Maroc is touching a (stationary)
;   energy-restoring object - from LD479_0 254 = Check if Maroc is touching a
;   (stationary) energy-draining object - from D481
; 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):
LDFCD:
  LD A,($EAD3)            ; Graphic's horizontal position, in pixels, starting
  LD D,A                  ; from screen pixel column 8 (halfway into left
                          ; decorative border)
  LD A,($EAD2)            ; 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.
; D83B for servant checks)
LDFCD_0:
  LD A,($EAD4)            ; 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 $00                  ; If it's NOT zero, it's off-screen so no collision
  JR NZ,LDFCD_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 $00                  ; 0 tests for a collision with Maroc - e.g. the
  JR Z,LDFCD_1            ; servant and Maroc's backpack (placing/retrieving
                          ; items)
  CP $01                  ; Collision value 1 = Opening/closing doors
  JR Z,LDFCD_1            ; interactions This is checked for both Maroc's
                          ; sprite (bumping into doors) and other collisions
                          ; (e.g. missile, servant)
  JR LDFCD_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.
LDFCD_1:
  LD A,$78                ; 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 $10                  ; If the difference is <= 16 pixels, the other room
                          ; item is (horizontally) close enough to Maroc
  JR NC,LDFCD_2           ; Collision NOT within horizontal 'hit box'. Skip
                          ; next few instructions
  LD A,($EAC1)            ; Collision IS within horizontal 'hit box'. Get
                          ; Maroc's vertical (Y-axis) screen position
  ADD A,$08               ; 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 $10                  ; If the difference is <=16 pixels, Maroc is
                          ; (vertically) close enough
  JR NC,LDFCD_2           ; Collision NOT within horizontal 'hit box'. Skip
                          ; next couple of instructions
; Positive collision with Maroc confirmed
  LD A,$01                ; Positive collision - set flag (A register) to 1
  JR LDFCD_8              ; Jump straight to RET
; CHECK FOR OTHER COLLISIONS/EVENTS
;
; Jump from DFE5 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.
LDFCD_2:
  LD A,C                  ; Retrieve the type-of-collision value to test/check
  CP $00                  ; Is it 0?
  JR Z,LDFCD_7            ; If so, that check's done, so can skip to the end
                          ; (setting collision flag to zero)
  LD B,$FD                ; 253 = value to test for energy-replenishing objects
                          ; However, this test won't match because of the AND 3
                          ; in a few instructions at E018. Explicit event
                          ; checks for both energy-draining (C=254) and
                          ; energy-restoring (C=253) objects are CALLed in the
                          ; routine at LD479
  LD HL,($EB6C)           ; Pointer to room item event table at 7FB3.
  CP $04                  ; Check if type-of-collision value >= 4
  JR NC,LDFCD_3           ;
  LD B,C                  ; If < 4, store the type-of-collision value in B
                          ; register
  LD C,$00                ; ...and set C register to 0
LDFCD_3:
  LD A,(HL)               ; Get first byte from data table (at 7FB3)
  INC HL                  ; (...and move the pointer along)
  CP $FF                  ; Is there data to check in this set (255 =
                          ; end-of-data)?
  JR Z,LDFCD_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 7FB3) to see if it
                          ; matches
  JR Z,LDFCD_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 L6CDC have bits 0 & 1 of their event byte set
;   (value = 3)
; * similarly Caliburn (78BB) and the animated sabre (7A63) 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 $03                 ; This filters bits 0-1 (values 1-3)
  CP B                    ; If no match for this, continue to check the event
  JR NZ,LDFCD_5           ; table at 7FB3
; Check X/Y co-ordinates for collision
;
; First, an X (horizontal) co-ordinate check:
LDFCD_4:
  LD A,(HL)               ; Get item's horizontal pixel co-ordinate (byte 3 of
                          ; item set at 7FB3)
  INC HL                  ; (...and move the pointer along)
  ADD A,$08               ; 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 $10                  ; Is the difference within the 16 pixel 'hit box'
                          ; threshold (8 pixels left/right of target
                          ; co-ordinates)?
  JR NC,LDFCD_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 7FB3)
  ADD A,$08               ; 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 $10                  ; Is the difference within the 16 pixel 'hit box'
                          ; threshold (8 pixels left/right of target
                          ; co-ordinates)
  JR NC,LDFCD_6           ; If not, jump to set negative collision flag (0) in
                          ; A register
; POSITIVE COLLISION
  LD A,$01                ; Set collision flag (A register) to 1 - collision
                          ; has taken place with this item.
  JR LDFCD_8              ; Jump straight to RET and deal with it
; No positive collision found for this object - move to next item and continue
; checks:
LDFCD_5:
  INC HL                  ; Jumps from E01B...
LDFCD_6:
  INC HL                  ; ...and from LDFCD_6, that advance the address
  JR LDFCD_3              ; pointer to the next data set (at 7FB3).
; NEGATIVE COLLISION - Set collision flag (A register) to 0 - no collision has
; taken place with any on-screen objects.
LDFCD_7:
  LD A,$00
; Routine returns with A register either set to 1 (collision) or 0 (no
; collision)
LDFCD_8:
  RET

; Check if Maroc or room item is within room boundaries
;
; Used by the routines at LCB00, LCB5B, LCBA8, LD04B, LD12E and LE8EE.
;
; 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 LE8EE
;
; 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.
LE039:
  LD B,$00                ; B register unused in this routine
  LD A,($EB48)            ; Graphic's horizontal position on screen (in
  LD D,A                  ; half-character/4-pixel steps)
  LD HL,($EB4C)           ; 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,($EAFA)            ; 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 $30                  ;
  JR C,LE039_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 $80                  ; Jump if >= 48 but < 128 as it means vertical room
  JR C,LE039_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,$00                ; The calculated difference is < 0, the minimum is 0
                          ; to set the difference to this
  LD A,H                  ; Vertical movement speed/direction
  CP $80                  ; For the next calculations we need the vertical
  JR C,LE039_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 LE039_1              ;
; Vertical position is below 42 (from E04F) 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
LE039_0:
  LD C,$30                ; The calculated difference is > 48. Max allowed
                          ; value is 48 so set the difference to this
  LD A,H                  ; Vertical movement speed/direction
  CP $80                  ; If > 128 (no carry), leave value as is
  JR NC,LE039_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:
LE039_1:
  LD A,C                  ; Get earlier calculated value - this is the top area
                          ; boundary minus screen vertical position
  RRA                     ; Divide by 2
  AND $7F                 ; (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,($EAFB)            ; 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 $20                  ; If <32, we've passed the side wall on the left -
                          ; bounce the item/Maroc back off the wall (to the
                          ; right)
  JR NC,LE039_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 $80                  ;
  JR C,LE039_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
LE039_2:
  LD A,H                  ; Check vertical speed/direction
  CP $80                  ; If < 128, Maroc is moving downwards - this is fine
  JR C,LE039_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,$00                ; Set vertical speed to 0
  JR LE039_5              ;
; RIGHT WALL BOUNDARY CHECK
;
; No carry jump from a bit earlier - E073
LE039_3:
  LD A,($EAFC)            ; 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 $E0                  ; 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,LE039_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 $80                  ;
  JR NC,LE039_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
LE039_4:
  LD A,H                  ; Check vertical speed/direction
  CP $80                  ; If < 128, Maroc is moving downwards - this is fine
  JR C,LE039_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,$00                ; Set vertical movement direction/speed to 0
; All room boundary checks complete
LE039_5:
  LD ($EB4C),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 LC15A, LC1C0, LC20F, LC265, LC290, LC2F8, LC349,
; LC460, LC618, LD325, LD6C7, LD730, LD833, LD90C and LDEB7.
;
; Copies the 16 bytes of object/item data from the buffer at LEB43 to a data
; set at 7C00.
LE0B0:
  LD B,$10                ; 16 bytes to copy
  LD DE,LEB43             ; Address pointer to start of data buffer
  LD HL,($EABE)           ; Get pointer to start of data set at 7C00.
LE0B0_0:
  LD A,(DE)               ; Copy a byte from the buffer to the set
  LD (HL),A               ;
  INC DE                  ;
  INC HL                  ;
  DJNZ LE0B0_0            ; Repeat x16 bytes
  LD ($EABE),HL           ; Address pointer to start of next data set
  RET                     ;

; Setup game graphics
;
; Used by the routines at LBF9D, LC1C0, LC20F, LC265, LC290, LC2F8, LC349,
; LC5E7, LCE71, LCF99, LD07C, LD6B0, LD730, LDA4D, LDADC, LDB1F, LDEB7, LE16A,
; LE641, LE6FA, LE753 and LE7FD.
;
; A Graphic number - offset for graphics address pointer table at L97C3.
;   Calculated offset is ((A-1)*2) + L97C3.
;
; 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).
LE0C2:
  LD B,A                  ; Transfer offset value to B register
; Calculate graphics address pointer using offset, using table at L97C3
  LD HL,($EB6A)           ; Pointer to graphics address list at L97C3
  DEC A                   ; Address pointers are 2 bytes long, so get offset
  LD D,$00                ; value, subtract 1...
  RLA                     ; ...multiply by 2
  RL D                    ;
  AND $FE                 ; 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 ($EAB2),HL           ; ...and store. Initially corner vertical wall
                          ; section at 97E5/9E0F.
; Calculate a second graphics pointer offset, that will point to the
; flipped/mirrored graphic's address.
  LD A,($EB50)            ; 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 $1E                 ; 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,$00                ;
  ADD HL,DE               ; Add this to HL address graphic pointer
  LD ($EB51),HL           ; ...and store.
; Point DE register pair to graphics data (HL = pointer at address table at
; L97C3)
  LD HL,($EAB2)           ; 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                  ; 9950, 9E0F.
  LD D,(HL)               ;
  DEC HL                  ;
; Pre-graphics byte - see Graphic properties
  DEC DE                  ; Get pre-graphics byte
  LD A,(DE)
  INC DE
  LD ($EB4F),A            ; ...and store.
; The next routine checks if the graphic has a 'mirrored' version. If so, this
; is constructed in the following routine at LE0F5.
;
; 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 $20                 ; If bit 5 is NOT set, no need to generate 'flipped'
  CP $00                  ; graphics.
  JR Z,LE0F5_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 L97C3. 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 L97C3)
; HL Points to relevant graphics address pointer at address table at L97C3
;
; In the graphic address pointer table at L97C3, 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:
LE0F5:
  LD A,C
  AND $0F                 ; Get the offset stored in bits 0-3
  LD ($EAB1),A            ;
LE0F5_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 L97C3.
  INC HL                  ;
  DEC A                   ;
  JR NZ,LE0F5_0           ;
  LD ($EAB2),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,(LEAEF)           ; Get pointer to data/graphics storage area (8033)
LE0F5_1:
  LD A,(HL)               ; Check byte
  INC HL                  ; ...and move pointer one address forward
  CP $FF                  ; Is it 255 (end-of-data byte)
  JR Z,LE0F5_2            ; If so, can store graphics from here
  CP B                    ; Is the graphics address pointer table offset byte
                          ; stored here?
  JR Z,LE0F5_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 LE0F5_1              ; Otherwise, keep moving through the data until a
                          ; end-of-data byte is found
LE0F5_2:
  LD (HL),$FF             ; 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,($EB5D)           ; 9E0F
LE0F5_3:
  LD B,H                  ; BC temporary store for HL e.g. 9E0F
  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 L97C3:
  LD HL,($EAB2)           ; Get graphics pointer address from earlier (table at
                          ; L97C3), e.g. 97E9
  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 ($EAB2),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. 9E0F.
; 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.
LE0F5_4:
  LD ($EAC7),A            ; Store the tile counter
  LD A,(HL)               ; Copy over the horizontal (X axis) offset (in
                          ; pixels)
  ADD A,$08               ; 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                  ;
LE0F5_5:
  LD ($EAD1),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,$08                ; Rotate the bits from A register x8 backwards into C
LE0F5_6:
  RLA                     ; register to create the mirrored byte
  RR C                    ;
  DJNZ LE0F5_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,($EAD1)            ; Retrieve the tile byte counter
  DEC A                   ; Repeat for the rest of the bytes in the tile.
  JR NZ,LE0F5_5           ;
; Tile is now flipped/mirrored. Now repeat for all tiles that make up the full
; graphic.
  LD A,($EAC7)            ; Get the tile counter
  DEC A                   ; Decrement and repeat for the rest of the tiles that
  JR NZ,LE0F5_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 L9CD0.
  LD A,($EAB1)            ; Get the offset address counter
  DEC A                   ; Decrement and re-store
  LD ($EAB1),A            ;
  JR NZ,LE0F5_3           ; If there are more graphics to mirror, go and do
                          ; them.
  LD ($EB5D),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 LE0C2.
LE0F5_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 LC460, LD5FE, LD67B and LD6A4.
;
; A | Creature type/number (see EB46)
;
; 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
LE16A:
  LD ($EB46),A            ; Creature type (also creature type number in data
  LD C,A                  ; set at L6C7C)
  LD A,$00                ;
  LD (LEB43),A            ; Type of graphic to draw (reset to 0 but will be set
                          ; shortly)
  LD A,($EBB6)            ; Number of creatures in current room
  CP $03                  ; Are there 3 already?
  JR Z,LE16A_0            ; If so, can't have any more, so jump straight to RET
  INC A                   ; Less than 3 creatures, so increase count of
  LD ($EBB6),A            ; creatures in room by 1
  LD HL,($EBC3)           ; Address pointer to warlock/creature information at
                          ; L6C7C
; Get offset to determine correct data set for particular warlock/creature:
  LD A,C                  ; Creature type/number (from EB46)
  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 $F8                 ; Filter out unnecessary bits 0-2
  LD E,A                  ; Create offset in DE register
  LD D,$00                ;
  ADD HL,DE               ; Add to L6C7C to get to relevant data set
  LD ($EB44),HL           ; ...and store
; Set up creature's data:
  LD A,$03                ; Set graphic type to 3 (indicates a creature)
  LD (LEB43),A            ;
  LD A,$00                ;
  LD ($EB47),A            ; Creatures appearing in the room will be on screen,
                          ; so set low byte of horizontal position to zero...
  LD ($EB49),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 ($EB4D),A            ; Set creature's vertical movement speed to zero
  LD ($EB4C),A            ; Set creature's horizontal movement speed to zero
  LD A,$40                ;
  LD ($EB4B),A            ; 64 = room item (as opposed to a tunnel). This forms
                          ; the byte 9 in data sets at 7C00, but is otherwise
                          ; unused.
; Randomize the creature's horizontal & vertical co-ordinates in the room
;
; Horizontal position:
  CALL LDB06              ; Generate pseudo-random number in A register
  AND $1F                 ; Keep bits 0-4 (values = 0 - 31)
  SUB $0F                 ; Values now vary between -15 and +16 (or 241 to 16)
  LD E,A                  ; Temp store in E register
  LD A,($EB7C)            ; 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 $FC                 ; (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 ($EB48),A            ; ...And store
; Vertical position:
  CALL LDB06              ; Generate pseudo-random number in A register
  AND $1F                 ; Keep bits 0-4 (values = 0 - 31)
  ADD A,$40               ; 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 ($EB4A),A            ; Store vertical co-ordinate
; Some more creature data:
  LD A,$05                ; Bit 0 set = creature on-screen. Bit 2 set =
                          ; creature will need erasing
  LD ($EB4E),A            ; Store in creature properties byte
  LD A,$11                ; Graphics address pointer frame offset. In the later
  LD ($EB50),A            ; calculation bit 4 is ignored however, so the offset
                          ; will be [n-1]*2, i.e. no offset
  LD DE,$0006             ; Move along to the 7th of the 8 bytes in the
  ADD HL,DE               ; creature data set at L6C7C/6CB4
  LD A,(HL)               ; Get creature graphic number (used as an offset for
                          ; the graphic address table at L97C3)
  CALL LE0C2              ; Set up the graphics for this creature
LE16A_0:
  RET                     ;

; Play (generic) sound effect
;
; Used by the routines at LC07A, LD325 and LDA88.
;
; 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 EB56 determines length/frequency of the sound effect.
; * The address pointer stored at EB59, and initialised at address 0000 (ROM)
;   provides random values for the sound.
LE1D7:
  LD ($EB57),HL           ; Preserve HL for this routine
  LD A,($EB56)            ; Counter/frequency for sound effect
  LD B,A                  ; Store in B register
  CP $00                  ;
  JR Z,LE1D7_2            ;
  DEC A                   ; Decrement counter and store
  LD ($EB56),A            ;
  LD A,B                  ; Retrieve (pre-decremented) counter
  AND $07                 ; Check bits 0-2 to cause an occasional change of
                          ; address for the base address pointer
  LD HL,($EB59)           ; Get byte from address pointer in readiness
  LD A,(HL)               ;
  JR NZ,LE1D7_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 ($EB59),HL           ; ..and store address pointer
  LD A,(HL)               ;
  JR NZ,LE1D7_0           ; Repeat of condition that was checked at E1ED
  INC HL                  ; Skip another address
  LD ($EB59),HL           ; ...and re-store counter
; Use pseudo-random byte to generate sound:
LE1D7_0:
  INC B                   ; Shift sound byte based on counter - randomize
LE1D7_1:
  RLA                     ; speaker bit
  DJNZ LE1D7_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 $10                 ; Filter out everything except speaker bit (bit 4)
  OUT ($FE),A             ; Output value to speaker (1 or 0)
LE1D7_2:
  LD HL,($EB57)           ; Retrieve HL register pair value preserved at the
  RET                     ; start of the routine

; Set screen colour for current room
;
; Used by the routines at LC63B, LDA4D and LDA88.
;
; The screen colours are calculated from the bits that form the room number
; byte in the routine at LC63B.
LE207:
  LD A,($EAA9)            ; Get attribute colour for current room
  LD D,$0E                ; 14 rows to colour
  LD HL,$5842             ; Screen attribute display, top left of play area,
                          ; just inside decorative border
LE207_0:
  LD B,$1C                ; 28 columns to colour
LE207_1:
  LD (HL),A               ; Colour the attribute square
  INC HL                  ; Move right to next character square
  DJNZ LE207_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,LE207_0           ;
  CALL LE220              ; 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 LD368, LE207 and LE46C.
;
; Maroc's attribute colour value is set to 71 (INK 7, PAPER 0, BRIGHT 1) and
; stored at LEAA7.
;
; 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:
LE220:
  LD A,($EAC1)            ; Maroc's vertical (Y-axis) position, in pixels.
  SUB $1A                 ; 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 $F8                 ; 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,$00                ; 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,($EAC0)            ; 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,$00
  ADD HL,DE               ; Combine the offsets calculated above
  LD DE,$5820             ; 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,($EAA9)            ; Current room colour attribute value
  LD DE,$001D             ; Offset ready to move down to the next character row
                          ; (32 spaces) minus 3 spaces (3 spaces to the left)
  LD B,$03                ; 3 character wide area to colour in
LE220_0:
  LD (HL),A               ; Colour the 3-character wide section with the room
  INC HL                  ; colour
  DJNZ LE220_0            ;
; Now combine the room colour with Maroc's sprite colour, so Maroc takes on the
; PAPER value of the room:
  LD A,($EAA9)
  LD C,A
  LD A,(LEAA7)            ; 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 (L97C3) 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,$06                ; 6 characters in height
LE220_1:
  LD B,$03                ; ...and 3 wide
LE220_2:
  LD (HL),A               ; Colour in the square
  INC HL                  ;
  DJNZ LE220_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,LE220_1           ;
  RET                     ;

; Clear the playing area (pixels)
;
; Used by the routines at LC63B and LDA4D.
LE25B:
  LD A,$0E                ; Playing area is 14 character rows high
  LD ($EAC7),A            ;
  LD DE,$4042             ; Screen display address for top left of playing area
; Clear a character row (8 pixels) of the playing area:
LE25B_0:
  LD C,$08                ; 8 pixel rows
  LD H,D                  ; Copy screen display address from DE to HL
LE25B_1:
  LD L,E                  ;
  LD B,$1C                ; 28 character rows to clear
LE25B_2:
  LD (HL),$00             ; Clear pixel byte
  INC L                   ; Move on character square right
  DJNZ LE25B_2            ; Repeat for 28 character rows
  INC H                   ; Move down 1 pixel
  DEC C                   ;
  JR NZ,LE25B_1           ; Repeat for 8 pixel rows
; Move down to next (character) row:
  LD A,E                  ; Get starting left hand position
  ADD A,$20               ; Move down to next character square
  LD E,A                  ; Are we crossing a third-of-screen boundary?
  JR NC,LE25B_3           ;
  LD A,D                  ; If so, recalculate screen display high-byte
  ADD A,$08               ; accordingly
  LD D,A                  ; Store corrected screen address high byte back in D
                          ; register
; Check if all character rows have been cleared:
LE25B_3:
  LD A,($EAC7)            ; Get character row counter
  DEC A                   ; ...and decrement
  LD ($EAC7),A            ;
  JR NZ,LE25B_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 LD09B.
;
; Called from D0E3 if byte 7 or 8 of missile data (L6CDC/EB9D) 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
; E297, horizontal 48 pixels at E2A2)
LE286:
  LD A,($EAD4)            ; High byte of missile horizontal co-ordinate
  CP $00                  ; This byte is 0 if the item is visible on-screen
  JR NZ,LE286_0           ; If not, jump to the end of this routine
; Missile is on-screen. First a horizontal co-ordinate collision check:
  LD A,($EAD2)            ; Graphic's vertical pixel position
  LD C,A                  ; Copy to C register
  LD A,($EAC1)            ; Maroc's vertical (Y-axis) screen position
  ADD A,$0C               ; 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 $18                  ; Is the missile within 24 pixels from this vertical
                          ; position?
  JR NC,LE286_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,($EAD3)            ; Graphic's horizontal pixel position
  LD C,A                  ; Copy to C register
  LD A,$8C                ; 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 $30                  ; Is the missile within 48 pixels from this
                          ; horizontal position?
  JR NC,LE286_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,$08
  LD ($EB56),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 LE286_1              ; ...and skip the next instruction, jump straight to
                          ; RET
; No collision detected
LE286_0:
  LD A,$00                ; Collision check flag value = 0 (no collision)
LE286_1:
  RET                     ;

; Copy room item event data into working buffer
;
; Used by the routines at LCC27, LCD88 and LD09B.
;
; A Event number involving this object (stored at EB8F) Also used for
;   energy-affecting objects, e.g. orbs and mushrooms, 254 = energy drain, 253
;   = energy replenish
;
; Uses room item event data sets at 7FB3 that will need checking for certain
; items/objects in the current room.
LE2B0:
  LD C,A                  ; Copy event number ID into C register
  LD A,($EAD4)            ; 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 $00                  ; If it's 0, it's on the current screen (viewport)
  JR NZ,LE2B0_0           ; If not, this item is off-screen so no
                          ; collisions/interactions with this object will need
                          ; checking - jump straight to RET
  LD HL,($EAAD)           ; Pointer to the event data sets at 7FB3
  LD (HL),$02             ; 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,($EAD3)            ; Byte 3 of set - item's horizontal screen position
  LD (HL),A               ; (in pixels)
  INC HL                  ;
  LD A,($EAD2)            ; 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),$FF             ; and is recaculated each frame, so put a 255 at the
                          ; start of the next set to mark the end of item sets
  LD ($EAAD),HL           ; Restore the address pointer at the start of this
LE2B0_0:
  RET                     ; next set

; Set up message text on scroll to print
;
; Used by the routines at LC03F, LC763, LDA88 and LE4E7.
;
; Set up the message data, pointers and next character to print, in preparation
; before the print routine at LE2FA.
LE2D0:
  LD DE,(LEAA1)           ; Get address of message text to print
  LD A,(DE)               ; Get the number of letters/characters in the message
  LD ($EAA3),A            ; ...and store
  LD ($EAA4),HL           ; Store the screen display address pointer
  INC DE                  ; Point at the first letter/character to print
  LD (LEAA1),DE           ; ...and store address pointer
; This entry point is used by the routines at LDD5C, LDF33, LE2FA, LE6FA and
; LE7C2.
LE2D0_0:
  LD DE,(LEAA1)           ; 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 (LEAA1),DE           ; ...and store
  CP $1B                  ; Is the character a line break (code 27)?
  JR NZ,LE2FA             ; 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,($EAA4)            ; Get the current screen display address low byte
  AND $E0                 ; Reset the column number to 0
  ADD A,$28               ; ...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 ($EAA4),A            ; Store the screen display address low byte
  JR LE2FA_4              ; ...and jump straight into the text print routine.

; Character/text printing
;
; Used by the routine at LE2D0.
;
; A Offset for letter to print, e.g. 0 = A, 1 = B (see L6D24)
;
; This routine is used at LE0C2 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 L6D24.
LE2FA:
  LD HL,L6D24             ; Start address of character set ('A')
  LD D,$00                ; Load DE with offset of character (0 = A, 1 = B, 2 =
                          ; C etc.)
  LD E,A                  ; Outer loop counter
  LD B,$08                ; 8 bytes in each character
LE2FA_0:
  ADD HL,DE               ; Add offset to base address
  DJNZ LE2FA_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,($EAA4)           ; ...Get screen display address (???) to print text
                          ; at
  LD C,H                  ; Store high byte in C for retrieval later
  LD B,$08                ; 8 pixel row bytes to print
LE2FA_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 $07                 ; Look at the pixel row of the line (0-7)
  INC A                   ; Increment and check if it's gone over to the next
  CP $08                  ; character row
  JR NZ,LE2FA_2           ;
  LD A,H                  ; Get the high byte of the display address
  AND $F8                 ; 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,$20               ; next character row down, and store
  LD L,A                  ;
  JR LE2FA_3              ; INC H in next line of code can now be skipped as HL
                          ; contains the correct display address position
; Jump in from E315, 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:
LE2FA_2:
  INC H
LE2FA_3:
  DJNZ LE2FA_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 $1F                 ; 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 ($EAA4),HL           ; ...and store display address position ready to
                          ; print next character.
; Letter/character has been printed
LE2FA_4:
  LD A,($EAA3)            ; Decrement the 'number-of-letters-to-print' counter
  DEC A                   ; (columns) (I think)
  LD ($EAA3),A            ;
  JR NZ,LE2D0_0           ; Continue printing until finished
  RET                     ;

; Handle creature/graphic animation
;
; Used by the routines at LC837 and LE929.
;
; 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.
LE336:
  LD A,(LEAAA)            ; Incrementing timer byte
  AND $01                 ; Check bit 1
  JP Z,LE336_6            ; Skip animation routine (straight to RET) every
  LD A,(LEB43)            ; other frame, so that animation rate isn't too fast
  CP $03                  ; Is it a creature?
  JR NZ,LE336_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,($EB4E)            ; Creature properties byte
  AND $E0                 ; 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,LE336_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,($EC9C)            ; Get FREEZE spell timer counter
  CP $00                  ;
  JR NZ,LE336_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:
LE336_0:
  LD A,($EB4F)            ; Get pre-graphics data byte (Graphic properties)
  LD B,A                  ; Temp store in B register
  AND $40                 ; Bit 6 (64), if set, indicates that this creature
                          ; has left/right facing graphics (e.g. goblins,
                          ; guardian of chaos, and wraith)
  JR Z,LE336_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 EB50 indicates whether the creature is facing right
; (1 - set) or left (0 - not set)
  LD A,($EB50)            ; Get graphic address frame number offset
  LD D,A                  ; Temp store in D
  AND $08                 ; Get bit 3
  LD C,A                  ; C now contains either 8 (right) or 0 (left)
                          ; depending on whether bit 3 was set
  LD A,($EB4C)            ; Movement speed/direction
  CP $00                  ; Stationary?
  JR Z,LE336_3            ; If so, don't need to calculate anything - skip to
                          ; the end
  CP $80                  ; Negative value = move left.
  JR NC,LE336_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
                          ; EB50 was set, C will contain 8, otherwise 0.
  CP $08                  ; If the byte is 8 it means the creature is already
                          ; moving right
  JR Z,LE336_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 $07                 ; 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 $08                  ; Set bit 4 to indicate the creature is now moving
                          ; right - for storing at EB50 at LE336_2
  LD D,$00                ; Set high byte (D register) to 0. The offset, now in
  JR LE336_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
LE336_1:
  LD A,C                  ; Retrieve byte from C register - if bit 3 (8) of
                          ; EB50 was set, C will contain 8, otherwise 0.
  CP $00                  ; If the byte is 0 it means the creature is already
                          ; moving left
  JR Z,LE336_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 L97C3.
  LD A,B                  ; Retrieve pre-graphics data byte
  AND $07                 ; 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 $F7                 ; Reset bit 4 to indicate the creature is now moving
                          ; left - for storing at EB50 at LE336_2
  LD D,$FF                ; 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
LE336_2:
  LD ($EB50),A            ; Re-store the graphic address frame number offset,
                          ; with bit 3 set/unset to indicate right/left facing
                          ; respectively
  JR LE336_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:
LE336_3:
  LD A,B                  ; Retrieve pre-graphics data byte
  AND $80                 ; Bit 7 indicates the graphic has animation frames
  JR Z,LE336_6            ; If NOT set (not animated), jump to straight to RET
; Calculate graphics animation frame:
  LD A,B                  ; Retrieve pre-graphics data byte
  AND $07                 ; Get number of frames for this sprite
  LD B,A                  ; ...and store in B register
  LD A,($EB50)            ; Get graphic frame number offset for this graphic
  LD C,A                  ; Temp store in C register
  AND $07                 ; Keep bits 0-2 to get the sprite's current frame
                          ; number
  LD H,A                  ; Temp store in H register
  LD DE,$0000             ; 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,LE336_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 $F8                 ; 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,$FF                ; a 2 byte negative offset
; Recalculate new sprite graphics address pointer for the next frame:
LE336_4:
  LD A,C                  ; Retrieve the sprite's frame number...
  INC A                   ; ...Increment...
  LD ($EB50),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:
LE336_5:
  LD HL,($EB51)           ; 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 ($EB51),HL           ; ...and re-store
  LD A,($EB4E)            ; Item (creature) properties byte
  OR $04                  ; Ensure bit 2 (4) is set - indicates graphic (i.e.
                          ; the old frame) will need erasing before the new one
                          ; is drawn
  LD ($EB4E),A            ; ...and re-store
LE336_6:
  RET                     ;

; Increase/decrease Maroc's energy and play short beep sound
;
; Used by the routines at LCCDD, LD065, LD116, LD1D2, LD23B, LD479, LD63A,
; LE7FD and LE9DD.
;
; 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:
LE3CC:
  LD C,A                  ; Store increase/decrease value in C register
  CP $80                  ; If bit 7 is set, it indicates an increase in energy
  JR NC,LE3CC_0           ; (e.g. CHALICE, ENERGIZE, AMULET spells)
; Decrease Maroc's energy:
  LD A,($EAE0)            ; Maroc's current energy
  SUB C                   ; The amount of damage to subtract
  JR NC,LE3CC_1           ; Is Maroc's energy now less than zero?
  LD A,$00                ; If energy < 0, set energy to zero
  JR LE3CC_1              ;
; Increase Maroc's energy:
LE3CC_0:
  NEG                     ; Maroc is being healed - invert damage (resets bit
  LD C,A                  ; 7) to indicate energy increase
  LD A,($EAE0)            ; Maroc's current energy
  ADD A,C                 ; Increase by relevant amount
  JR NC,LE3CC_1           ;
  LD A,$FF                ; If energy is now > 255, set energy to 255
; Play beep sound - pitch corresponds to Maroc's energy
LE3CC_1:
  LD ($EAE0),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 $01                  ; Ensure value to use is at least 1 (i.e. not zero)
  LD D,A                  ; Delay for inner beep loop
  LD C,$10                ; Delay for beep sound pitch register (outer loop)
  LD A,$10                ; Set bit 4 (speaker bit)
LE3CC_2:
  LD B,D                  ; Delay counter
LE3CC_3:
  DJNZ LE3CC_3            ; Short delay, affects beep pitch based on energy
                          ; left
  OUT ($FE),A             ; Play sound
  XOR $10                 ; Toggle speaker bit
  DEC C                   ;
  JR NZ,LE3CC_2           ; Keep toggling for short time (outer repeat loop)
  RET                     ;

; Print screen colours for room object/creature
;
; Used by the routines at LD019 and LD27D.
;
; 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:
LE3FD:
  LD A,($EAD2)            ; Item's vertical position, from top of playing area,
                          ; in pixels
  ADD A,$12               ; Add an offset to avoid top border
  AND $F8                 ; 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,($EAD3)            ; Item's horizontal screen position, in pixels
  ADD A,$09               ; 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 $1F                 ; 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,$58                ; 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 LEBD6 and EBE6 identify the series of attributes to use
; for colouring each of these respectively.
  LD A,(LEB43)            ; Get item graphic type
  CP $00                  ; 0 = item no longer present, i.e. destroyed creature
  JR Z,LE3FD_0            ;
  CP $03                  ; 3 = creature
  JR NZ,LE3FD_1           ;
LE3FD_0:
  LD DE,LEBD6             ; Colour pattern address = LEBD6 for
  JR LE3FD_2              ; creature/destroyed creature
LE3FD_1:
  LD DE,$EBE6             ; Colour pattern address = EBE6 for any other item
LE3FD_2:
  LD A,(DE)               ; First byte of set is number of total data bytes in
                          ; set - either 15 or 9
  LD ($EAC7),A            ; Store as counter
  INC DE                  ; Move to the first byte in the data set
; Colouring loop:
LE3FD_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 $1F                 ; Only need values 0-31
  SUB $02                 ; Can't draw on left/right border, so check screen
                          ; column number is between 2 and 29 (inclusive)
  CP $1C                  ; ...A subtraction of 2 and then comparing against a
                          ; value of 28
  JR NC,LE3FD_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 $40                  ; If attribute low byte address is 64 or less...
  LD A,H                  ; (High byte of screen attribute address)
  JR NC,LE3FD_4           ;
  CP $58                  ; ...and high byte = 88, attribute display address is
                          ; in the top third and the top two lines (border) of
                          ; the screen
  JR Z,LE3FD_6            ; If so, skip and don't print any colour here
LE3FD_4:
  SUB $58                 ; High byte > 88 so we're past the top third
  CP $02                  ; Check if we're into the bottom third of the screen
  JR NC,LE3FD_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,($EACF)            ; Check DRAW/ERASE flag
  CP $00                  ;
  JR Z,LE3FD_5            ;
  LD A,($EAA8)            ; It's DRAW (1) - so get graphic's attribute colour
                          ; byte
  LD (HL),A               ; ...and put on screen
  JR LE3FD_6              ;
LE3FD_5:
  LD A,($EAA9)            ; It's ERASE (0) so get room's attribute colour byte
  LD (HL),A               ; ...and put on screen
; Repeat loop counter:
LE3FD_6:
  LD A,($EAC7)            ; Get the counter
  DEC A                   ; Decrement
  LD ($EAC7),A            ; ...and re-store
  JR NZ,LE3FD_3           ; Continue printing attributes for the rest of the
  RET                     ; graphic

; Animation routine for when Maroc is out of energy
;
; Routine called from LDA4D when Maroc is out of energy. He spins towards the
; top of the screen, with a decreasing pitch sound.
;
LE46C:
  LD A,($EAC1)            ; Maroc's vertical (Y-axis) screen position, in
                          ; pixels
  LD ($EAD2),A            ; Copy into data buffer
  LD HL,($EAC2)           ; Maroc's sprite address pointer in table at L97C3
  LD ($EACD),HL           ; Copy into data buffer
  LD A,($EAC0)            ; 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 $FC                 ; Filter out any carry bits that may have appeared
                          ; from the SLA
  LD ($EAD3),A            ; ...and store horizontal pixel position in data
                          ; buffer
  LD A,$00                ; Set high byte of horizontal graphic position to
  LD ($EAD4),A            ; indicate that it's within the current screen
                          ; (viewport) rather than to the left (255) or right
                          ; (1)
; Play sound:
LE46C_0:
  LD A,($EAD2)            ; 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,$40                ;
  LD A,$00                ; Start loop with speaker off
LE46C_1:
  XOR $10                 ; Toggle the speaker bit
  OUT ($FE),A             ; Play sound
  LD B,C                  ; Inner loop - short pause
LE46C_2:
  DJNZ LE46C_2            ;
  DEC E                   ; Outer loop - short pause
  JR NZ,LE46C_1           ;
; Erase Maroc's graphic:
  LD A,$00                ; Set draw/erase flag to ERASE
  LD ($EACF),A            ;
  LD HL,($EACD)           ; Get graphic address pointer
  CALL LDB98              ; Erase Maroc's sprite
; Rotate Maroc's sprite clockwise
  LD A,($EB03)            ; Rotation value - for 8 different directions, in
                          ; increments of 32
  ADD A,$20               ; Rotate Maroc's sprite clockwise one graphics frame
  LD ($EB03),A            ; Re-store new graphics frame
  RRA                     ; Rotate rotation bits into bits 1-3
  RRA                     ;
  RRA                     ;
  RRA                     ;
  AND $0E                 ; ...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,$00                ; Transfer this offset to DE
  LD HL,($EB6A)           ; Get sprite graphic address pointer
  ADD HL,DE               ; Add the offset, which now points to Maroc's new
                          ; frame (from L97C3)
  LD ($EACD),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 LE220 references the byte at EAC1 for
; Maroc's normal vertical screen position, rather than the one at LEAA7, 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,(LEAA7)            ; Get Maroc's attribute colour (usually 71 - bright
                          ; white)
  DEC A                   ; Decrement (Maroc is supposed to change colour as he
                          ; rises)
  AND $07                 ; Only need INK colour so filter out PAPER, BRIGHT
                          ; and FLASH bits
  LD (LEAA7),A            ; ...and store.
  LD A,($EAD2)            ; Get Maroc's vertical position (in pixels)
  SUB $04                 ; Reduce by 4 (Maroc moves upwards in half character
  LD ($EAD2),A            ; squares)
  CALL LE220              ; Set/change Maroc's attributes (INK colour)
; Draw Maroc at his new screen position:
  LD A,$01                ; Set draw/erase flag to DRAW
  LD ($EACF),A            ;
  LD HL,($EACD)           ; Get sprite graphics address pointer
  CALL LDB98              ; Draw Maroc sprite
  LD A,($EAD5)            ; Flag indicating whether (any part of) graphic is
                          ; visible on screen
  CP $00                  ; Check if Maroc has disappeared off the top of the
                          ; screen
  JR NZ,LE46C_0           ; If not, continue to spin him upwards and play
  RET                     ; sound.

; Calculate and print Maroc's rank
;
; Used by the routines at LC0A3 and LDA88.
;
; See Trivia: Maroc's rank for information about how this is determined.
LE4E7:
  CALL LDEF9              ; Clear the scroll status panel at the bottom of the
                          ; screen
  LD A,$22                ; Message number 34 (message texts start from L7172)
                          ; - #34 is the "YOUR RANK IS NOW" text at 72E8.
  CALL LE5A5              ; Identify address pointer for message text
  LD (LEAA1),HL           ; ...and store
  LD HL,$5068             ; Set the screen display address pointer for top left
                          ; of scroll, one character line down
  LD ($EAA4),HL           ; ..and store.
  CALL LE2D0              ; 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 E51B 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,$0010
  LD HL,($EB65)           ; Address pointer to start of message texts at L6DFC,
                          ; starting with spell names
  LD A,($EB69)            ; Number of spells (27)
  LD B,A                  ; Store in B register as a counter
  LD C,$00                ; C seems to be a counter for spells collected
  LD A,$10                ; Check if Maroc has collected this spell
LE4E7_0:
  CP (HL)                 ;
  JR NZ,LE4E7_1           ;
  INC C                   ; If so, increment score by 3
  INC C                   ;
  INC C                   ;
LE4E7_1:
  ADD HL,DE               ; Move onto the next spell
  DJNZ LE4E7_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
; L6C7C.
;
; Score for destroying a warlock is warlock number * 4. So warlock #1 is worth
; 4, warlock #7 is worth 28.
  LD HL,($EBC3)           ; Address pointer to warlock information at L6C7C
  INC HL                  ; If the second byte in each warlock's data set >0,
                          ; it means Maroc has destroyed this warlock.
  LD DE,$0008             ; 8 bytes for each set of warlock data
  LD B,$07                ; 7 warlocks to check
  LD C,$00                ; The C register will contain the total score
LE4E7_2:
  LD A,(HL)               ; Get byte
  ADD HL,DE               ; (Move pointer to the next warlock data set ready
                          ; for next check)
  CP $00                  ; Check if it's 0
  JR Z,LE4E7_3            ; If so, this warlock has not been destroyed.
                          ; Continue to the next one.
  LD A,$08                ; 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                  ;
LE4E7_3:
  DJNZ LE4E7_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 6CB4)
;
; Rank points are halved in the final calculation, meaning Maroc's rank will
; increase by 1 for every 4 creatures he destroys.
  LD B,$04                ; 4 types of creature to check
LE4E7_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 LE4E7_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 $00                  ;
  JR Z,LE4E7_5            ; If zero, nothing to add
  LD A,$20                ; 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 LC6A4 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)
LE4E7_5:
  LD A,($EAC9)            ; Byte relating to level number in reference table at
                          ; LC6A4
  ADD A,A                 ; Double it
  ADD A,C                 ; ...and add to the score
  LD C,A                  ;
; Now a rank demotion. The byte at EAC8 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,($EAC8)            ; Get Maroc's current 'death count'
  INC A                   ; ...and increase by 1
  JR C,LE4E7_6            ; Avoid re-storing the increased amount if it would
                          ; mean a wrap around to 0 (if Maroc has already died
                          ; 255 times!)
  LD ($EAC8),A            ; Re-store
LE4E7_6:
  RRA                     ; Divide by 4
  RRA                     ;
  AND $3F                 ; 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,LE4E7_7           ;
  LD A,$00                ; 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:
LE4E7_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 $0F                 ; Keep bits 0-3 (values 0-15) - this gives 16
                          ; options, which relate to the 16 titles
  ADD A,$12               ; The rank title texts start at 7250, which is
                          ; message #18 from the start of the message texts
                          ; (BF92), so add this.
  LD ($EAC7),A            ; Store this value
; Calculate and print the 'descriptor' part of the rank text (one of the 8
; texts at L7216).
  LD A,C                  ; Retrieve the original score (halved so will be in
                          ; the range 0-127)
  AND $07                 ; Keep bits 0-2 (values 0-7) - this gives 8 options,
                          ; which relate to the 8 descriptors
  ADD A,$0A               ; The rank descriptor texts start at L7216, which is
                          ; message #10 from the start of the message texts
                          ; (L7172), so add this.
  CALL LE5A5              ; Identify the address pointer for the descriptor
                          ; text
  LD (LEAA1),HL           ; ...and store.
  LD HL,$50A8             ; Screen display address to the start of where the
                          ; descriptor text will be printed on the scroll
  LD ($EAA4),HL           ; ...and store
  CALL LE2D0              ; Print the text on the scroll
; Print the 'title' part of the rank text (one of the 16 texts at 7250):
  LD A,($EAC7)            ; Retrieve the calculated text message number
  CALL LE5A5              ; Identify the address pointer for the text to print
  LD (LEAA1),HL           ; ...and store.
  LD HL,$50C8             ; Screen display address to the start of where the
  LD ($EAA4),HL           ; descriptor text will be printed on the scroll, just
                          ; below where the descriptor was printed
  CALL LE2D0              ; Print the text on the scroll
  RET                     ;

; Clear the spell message text area on the scroll
;
; Used by the routine at LC677.
;
; Clears any messages on two lines of the message area of the scroll, e.g.
; "Project thy soul", "Gatehouse level"
LE58C:
  LD L,$88                ; 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,$02                ; 2 row of text
LE58C_0:
  LD E,$10                ; 16 columns of text
LE58C_1:
  LD H,$50                ; 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,$08                ; 8 pixel rows to clear
LE58C_2:
  LD (HL),$00             ; Clear pixel row
  INC H                   ; Move down one pixel line
  DJNZ LE58C_2            ; Repeat x 8
  INC L                   ; Move right one character square/column
  DEC E                   ; Repeat x 16 columns
  JR NZ,LE58C_1           ;
  LD L,$A7                ; 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,LE58C_0           ;
  RET                     ;

; Identify address of message text
;
; Used by the routines at LC03F, LC677, LC763, LDA88 and LE4E7.
;
; A Message number (1-37). Message text lists stored at L7172, beginning with
;   level names.
LE5A5:
  LD HL,(LEB5B)           ; Address pointer for text to print
  LD D,$01                ; Start at text #1
LE5A5_0:
  CP D                    ; Determine which message number to print - is it
                          ; this one?
  JR Z,LE5A5_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)
LE5A5_1:
  INC HL                  ; Move to the next byte
  DJNZ LE5A5_1            ; Skip the rest of the bytes for this message
  INC D                   ; Increment message number/counter
  JR LE5A5_0              ; ...and run the check again for the next message
LE5A5_2:
  RET                     ;

; Play music
;
; Used by the routines at LC0C1, LC763 and LDA88.
;
; 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
; LEBF0.
;
; (2) The second tune is played then the game is paused. Uses music data at
; EC72.
LE5B6:
  CP $01                  ; Check which tune needs to be played
  JR NZ,LE5B6_0           ;
  LD HL,LEBF0             ; Point HL at first note(s) of the intro/end tune
  JR LE5B6_1              ; data
LE5B6_0:
  LD HL,$EC72             ; Point HL at first note(s) of the paused game tune
                          ; data.
; Play notes
LE5B6_1:
  LD A,(HL)               ; Get note value
  CP $FF                  ; 255 is an end-of-music marker
  JR Z,LE5B6_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 ($EB54),HL           ; ...and store
  LD H,B                  ; H = first note of pair, e.g. 190
  LD A,C                  ;
  ADD A,$20               ; +32 to create a phase-type effect
  LD L,A                  ; L = second note of pair, plus 32, e.g. 222
  LD DE,$1C00             ; 7168 = Note duration
  LD A,$00                ; Reset A to 0
LE5B6_2:
  DEC H                   ; Decrement first note byte (for sound note loop)
  JR NZ,LE5B6_3           ; Reached zero?
  OR $10                  ; If zero, ensure speaker bit (4) is set to play
                          ; sound
  LD H,B                  ; ...and restore first note of pair again
LE5B6_3:
  DEC L                   ; Decrement second note byte (for sound note loop)
  JR NZ,LE5B6_4           ; Reached zero?
  OR $10                  ; If zero, ensure speaker bit (4) is set
  LD L,C                  ; ...and restore second note of pair again
LE5B6_4:
  ADD A,$08               ; 'Thickens out' the sound by ensuring speaker is
                          ; toggled on a bit more
  AND $10                 ; Filter out other bits, only keeping bit (4) speaker
                          ; toggle bit
  OUT ($FE),A             ; ...and play sound by toggling speaker on or off
                          ; accordingly
  SRA A                   ; Shift bits right
  LD (LEB53),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,(LEB53)            ; Restore A register which holds the speaker bits
  JR NZ,LE5B6_2           ; If not at zero yet, continue to play note
  LD HL,($EB54)           ; Note played. Get data pointer
  JR LE5B6_1              ; ...and go and play next note
LE5B6_5:
  RET                     ; Return to routine at LC0C1 or LC763.

; Generate sound effect when Maroc picks up a scroll/spell/item
;
; Used by the routine at LCC72.
;
; 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 D35A, but this routine is
; CALLed for both objects and spells.
LE5FE:
  LD A,$10                ; Bit 4 - speaker bit
  LD C,$30                ; Outer loop counter
LE5FE_0:
  LD B,C                  ; Set inner loop counter to same
  OUT ($FE),A             ; Output sound
  XOR $10                 ; Toggle speaker bit
LE5FE_1:
  NOP                     ; Inner loop pause
  NOP                     ;
  NOP                     ;
  DJNZ LE5FE_1            ; Inner loop repeat (x48 initially, decreasing)
  DEC C                   ; Decrement outer loop counter
  JR NZ,LE5FE_0           ; Repeat x48
  RET                     ;

; Intro sequence - toggle sky colour between blue/yellow
;
; Used by the routine at LC07A.
;
; 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.
LE610:
  LD B,$FF                ; 255 bytes covers a couple of rows more than the
                          ; first third of the screen.
  LD HL,$5840             ; Screen attribute address - top left of the screen,
                          ; then two rows down below the top border
; Determine INK colour in screen attribute byte:
LE610_0:
  LD A,(HL)               ; Get screen attribute byte
  LD D,A                  ; Store in D register
  AND $07                 ; Get the INK value from the screen attribute byte
                          ; (0-7)
  CP $01                  ; Is it blue (INK 1)?
  JR NZ,LE610_1           ;
  LD A,$06                ; If so, set the INK colour to yellow (6) and skip
  JR LE610_2              ; next check
LE610_1:
  CP $06                  ; Is the INK colour yellow (6)?
  JR NZ,LE610_2           ;
  LD A,$01                ; If so, Set the INK colour to blue
; Determine PAPER colour to paint sky - alternating between yellow and blue:
LE610_2:
  LD E,A                  ; Copy INK colour into E register - blue (1) or
                          ; yellow (6)
  LD A,D                  ; Get screen attribute byte
  AND $38                 ; Filter out everything but the PAPER colour (bits
                          ; 3-5)
  CP $08                  ; Is it blue (PAPER 1)?
  JR NZ,LE610_3           ;
  LD A,$30                ; If so, set to yellow (PAPER 6) and skip next check
  JR LE610_4              ;
LE610_3:
  CP $30                  ; Is it yellow (PAPER 6)?
  JR NZ,LE610_4           ;
  LD A,$08                ; If so, set to blue (PAPER 1)
; Combine calculated INK and PAPER parts of attribute byte:
LE610_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 $10                 ; This instruction has no effect, as the A register
                          ; is assigned a new value within the next couple of
                          ; instructions
  DJNZ LE610_0            ; Repeat x 255, covering the top third of the screen
                          ; (and a bit more).
  RET                     ; Return to the routine at LC07A

; Main loop - handle spell menu and keyboard/joystick inputs
;
; Used by the routine at LC7D0.
LE641:
  LD A,$01
  LD ($EB50),A            ; Set graphic frame number/address pointer offset (no
  LD A,$00                ; offset)
; Deal with spell menu routines, depending on spells activated:
  LD ($EBB7),A            ; General purpose byte used for a few different
                          ; things - reset here
  LD A,(LEAE1)            ; Check what's been already drawn
  CP $08                  ;
  JP Z,LE641_0            ; If the spell list has already been printed, can
                          ; skip the next few routines as they've been done
  CP $18                  ; Energy bar printed
  JP Z,LE77E              ;
  CP $20                  ; MOVE spell selected
  JP Z,LE852              ;
  CP $30                  ; Spell cast requiring a controllable cursor icon,
  JP Z,LE929              ; e.g. SERVANT, MISSILE
  CP $38                  ; Spell selected that is the same as the currently
  JP Z,LEA1D              ; active effect spell
  CALL LDEF9              ; Clear the Scroll status panel at the bottom of the
                          ; screen
  CALL LDF33              ; Print spell names on the scroll
  LD A,$00                ;
  LD ($EAEC),A            ; Reset spell number/pointer (EAE6)
  LD A,$08                ;
  LD (LEAE1),A            ; Indicate that spell list has now been printed
; Draw the pointer/selector arrow on the scroll:
LE641_0:
  LD A,$85                ; Graphics address pointer offset for the scroll
                          ; pointer arrow graphics at AFA6.
  CALL LE0C2              ; Set up the arrow graphic ready to draw
  LD DE,$5092             ; Screen address display position for the middle of
                          ; the scroll, to draw the arrow pointer
  CALL LDD24              ; 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,($EB32)            ; Check FIRE control flag (0 = not pressed, 1 =
  CP $00                  ; pressed)
  JR Z,LE641_1            ;
  JP LE6FA                ; Launch spell selection routine if fire is pressed
; Fire button not pressed - check for UP/DOWN:
LE641_1:
  LD A,($EAFE)            ; Get up/down flag: 1 = up, -1 (255) = down, 0 = not
                          ; pressed
  CP $00                  ; Check if it's pressed
  JR NZ,LE699             ;
  LD A,$05                ; If it's not pressed, set this counter byte to 5 -
  LD ($EAA6),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 LE641.
;
; This routine cycles through the spell list at L6DFC, 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:
LE699:
  LD C,A                  ; Temp store for up/down flag: 1 = up, -1 (255) =
                          ; down
  LD A,($EAA6)            ; 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 $00                  ; Skip next two instructions if zero (reached max
  JR Z,LE699_0            ; pitch)
  DEC A                   ; Otherwise decrement...
  LD ($EAA6),A            ; ...and re-store.
LE699_0:
  LD A,C                  ; Retrieve the up/down flag value from C register
  CP $01                  ; Check if UP pressed. If not, run the following
  JR Z,LE699_3            ; routine for DOWN.
; DOWN pressed while in spell menu:
  LD A,($EAE2)            ; Spell counter (up to 27 spells) for current spell
  LD HL,($EAE3)           ; Address pointer for the current position in the
  LD DE,$FFF0             ; spell list (spells at L6DFC)
LE699_1:
  CP $00                  ; If we don't currently have a counter position (byte
  JR NZ,LE699_2           ; at EAE2 is zero), then start at the end of the
                          ; spell list ready to move up it
  LD HL,($EB67)           ; Address pointer for the end of the spell list texts
                          ; at L6FBC
  LD A,($EB69)            ; Total number of spells (27)
  INC A                   ; Incremented ready for decrement at the start of the
                          ; following loop
LE699_2:
  ADD HL,DE               ; Subtracts 16 from HL - first check is the data set
                          ; for the last spell (MESSAGE) at 6FAC
  DEC A                   ; Decrement spell number counter (starts at 27)
  LD C,A                  ; Store temporarily
  LD A,(HL)               ; Get 'spell collected' data byte
  CP $10                  ; Has the spell been collected (byte value = 16)?
  LD A,C                  ; (Retrieve spell number counter)
  JR NZ,LE699_1           ; If it hasn't been collected, keep checking the rest
                          ; of the spells
  LD ($EAE2),A            ; Spell is available, so store the spell counter...
  LD ($EAE3),HL           ; ...and the spell list address pointer
  CALL LDF33              ; Print the spell names on the scroll
  RET                     ;
; UP pressed while in spell menu:
LE699_3:
  LD A,($EAE2)            ; Spell counter (up to 27 spells) for current spell
  LD C,A                  ;
  LD HL,($EAE3)           ; Address pointer for the current position in the
                          ; spell list (spells at L6DFC)
  LD DE,$0010             ; Offset for the spell address pointer to move down
                          ; to the next spell
LE699_4:
  LD A,($EB69)            ; Total number of spells
  CP C                    ; Check if we've reached the end of the list...
  JR NZ,LE699_5           ;
  LD HL,($EB65)           ; ...If so, switch to the start of the spell list
  LD C,$00                ; ...and set the spell counter to zero
  JR LE699_6              ;
LE699_5:
  ADD HL,DE               ; Move down to next spell
  INC C                   ; Increment the spell counter
LE699_6:
  LD A,(HL)               ; Get 'spell collected' data byte
  CP $10                  ; Has the spell been collected (byte value = 16)?
  JR NZ,LE699_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 ($EAE2),A            ;
  LD ($EAE3),HL           ; ...and the spell list address pointer
  CALL LDF33              ; Print the spell names on the scroll
  RET                     ;

; Draw active spell charges and icon on scroll
;
; Used by the routine at LE641.
;
; 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.
LE6FA:
  LD A,$00                ; Reset the fire control value (back to 0)
  LD ($EB32),A            ;
  CALL LDEF9              ; Clear the scroll area
; Copy the currently selected spell data (16 bytes) from L6DFC into a data
; store at LEBC5.
  LD HL,($EAE7)           ; Address pointer for selected spell at L6DFC
  LD DE,LEBC5             ; Data store/buffer for selected spell
  LD BC,$0010             ;
  LDIR                    ; Copy the 16 bytes over
; Print the spell name at the top (first line) of the scroll:
  LD HL,$EBCD             ; Address pointer to the current selected spell name
  LD (LEAA1),HL           ; Store text address pointer for printing the spell
                          ; name
  LD HL,$5048             ; Set the screen display address to the top left of
                          ; the scroll
  LD ($EAA4),HL           ; ...and store.
  LD A,$08                ; Each spell name is 8 characters long (includes
  LD ($EAA3),A            ; spaces for padding if name is shorter)
  CALL LE2D0_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,$83                ; Offset for graphics address table at L97C3.
                          ; Graphics pointer to spell icon graphics at AEE7.
  CALL LE0C2              ; Setup graphics data, DE register pair now points to
                          ; start of spell icon graphic
  LD HL,$5050             ; Set position for spell icon at top of scroll
  LD A,($EBC8)            ; Counter for number of spell 'charges'
  CP $04                  ; If the spell has 4 or more charges...
  JR C,LE6FA_0            ;
  LD A,$03                ; ...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.
LE6FA_0:
  LD ($EAC7),A            ; Store the counter for the spell charge icons (up to
                          ; 3)
  INC L                   ; Move right one character square
  LD ($EAA4),HL           ; Store the screen display address pointer
  EX DE,HL                ; Switch into DE register
  CALL LDD24              ; Draw the spell charge icon at the top of the scroll
  LD HL,($EAA4)           ;
  INC L                   ; Move right one character square
  LD A,($EAC7)            ; Retrieve and decrement the spell charge counter
  DEC A                   ;
  JR NZ,LE6FA_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,($EBCB)            ; Graphics pointer offset for the icon graphic to use
                          ; for this spell (icons at LA17E)
  CALL LE0C2              ; Setup graphics ready to draw
  LD DE,$5057             ; Set screen display address position to draw icon
                          ; (top right of scroll)
  CALL LDD24              ; Draw the spell icon

; Write active spell message on scroll and draw energy bar
;
; Print the appropriate message (L6FBC) for the active spell on the scroll.
LE753:
  LD A,($EAE6)            ; Get the spell message number
  LD HL,($EB63)           ; Address of spell messages (6FBD)
  LD D,$00                ; D = counter to check message number against
; Get the address pointer to the correct spell text:
LE753_0:
  CP D                    ; Check spell message number against current message
                          ; counter
  JR Z,LE753_2            ; If it's the same, we're at the right message so
                          ; skip ahead to LE753_2
  LD B,(HL)               ; Length of current text string
  INC B                   ; Increment for the following check loop
LE753_1:
  INC HL                  ; Move address pointer along
  DJNZ LE753_1            ; ...to the next message
  INC D                   ; Increment the counter (to check spell message
                          ; against)
  JR LE753_0              ; ...and keep checking
; The HL register pair is now pointing to the active spell message text.
LE753_2:
  LD ($EAEA),HL           ; Store the spell message text address pointer
  LD A,$00                ;
  LD ($EBC9),A            ; Reset the spell message text counter
; Draw the energy bar:
  LD A,$84                ; Graphics address pointer offset for 98C9, which
                          ; points at the energy bar graphic at LAEF3.
  CALL LE0C2              ; Set up graphics ready to draw
  LD DE,$50C7             ; Set screen display address to the bottom left of
                          ; the scroll
  CALL LDD24              ; Draw the energy bar
  LD A,$18                ; This byte is set to 24 which indicates the energy
  LD (LEAE1),A            ; bar has just been drawn - checked in routine at
                          ; LE641

; Check for UP/DOWN and FIRE control presses after a spell is selected
;
; Used by the routine at LE641.
;
; 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:
LE77E:
  LD A,($EAE6)            ; Get spell counter
  LD C,A                  ;
  LD A,($EAE9)            ; Is there currently an 'effect' spell active (e.g.
  CP $00                  ; SHIELD, UNSEEN)
  JR Z,LE77E_0            ;
  CP C                    ; If there is, is the triggered spell the same as the
                          ; currently active spell?
  JP Z,LE7ED              ; 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):
LE77E_0:
  LD A,($EB32)            ; Check if FIRE button pressed
  CP $01                  ; If pressed, skip the next few instructions
  JR Z,LE7A2              ;
  LD A,($EAFE)            ; Check if UP/DOWN pressed
  CP $00                  ; If it's pressed, skip ahead to LEA34_4
  JP NZ,LEA34_4           ;
  CALL LDD5C              ; Nothing pressed, so continue to print the active
                          ; spell's message text
  JP LEA34_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 LE77E.
;
; The player has selected (FIRE button press) and then confirmed (second FIRE
; button press) a spell from the list.
LE7A2:
  LD A,$00                ; Reset fire button register, store zero value
  LD ($EB32),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 LEA34 when the spell is cast again to 'deactivate' it.
  LD A,($EBC7)            ; Check the 'spell type' byte
  CP $04                  ; Is it an 'ongoing effect' spell (SHIELD, UNSEEN,
                          ; PROTECT, AMULET, DEFENCE, WRAITHBANE, CHALICE)?
  JR Z,LE7C2              ; If so, skip this routine
  LD A,($EBC8)            ; Number of spell 'charges' left
  CP $FF                  ; 255 = infinite charges - no need to decrease
  JR Z,LE7A2_0            ; charges
  DEC A                   ; Otherwise, reduce charges by 1
  LD ($EBC8),A            ; ...and re-store.
  CP $00                  ; Zero charges left?
  JR NZ,LE7A2_0           ;
  LD (LEBC5),A            ; If so, set the spell to 'not acquired' (0) to
                          ; remove it from the list as this is its last use
LE7A2_0:
  JR LE7ED                ; ...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 (LE7A2) 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:
LE7C2:
  LD HL,$EBCD             ; Store the address pointer for spell name text
  LD (LEAA1),HL           ;
  LD HL,$50F9             ; Screen display address pointer for the start of the
                          ; text (left of small scroll area)
  LD ($EAA4),HL           ; Store screen display address pointer
  LD A,$07                ; 7 characters to print (no effect spells need 8
                          ; letters)
  LD ($EAA3),A            ; Store text character counter
  CALL LE2D0_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,($EAE6)            ; Get spell (number) cast
  LD C,A                  ;
  LD A,($EAE9)            ; Compare with current 'active effect' spell
  CP C                    ;
  JR Z,LE7ED              ; 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 ($EAE9),A            ; Set the spell being cast as the active 'effect'
                          ; spell
  LD A,($EBC6)            ; Amount of energy that this spell drains (e.g.
                          ; SHIELD) or heals (e.g. CHALICE)
  LD ($EBD5),A            ; This byte is used to intermittently drain or heal
  JP LEA34_4              ; Maroc's energy as time passes (D64B)

; Set FLASHing attributes for the spell icon in the top right of the scroll
;
; Used by the routines at LE77E, LE7A2 and LE7C2.
;
; 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)
LE7ED:
  LD HL,$5A57             ; Screen display attribute address - top right of
                          ; scroll, top left of 2x2 square
  LD (HL),$B0             ; Attribute value for INK 0, PAPER 6 (yellow), FLASH
                          ; 1
  INC HL                  ; Move right one square
  LD (HL),$B0             ; Set square to FLASH
  LD HL,$5A77             ; Screen display attribute address - bottom left of
                          ; 2x2 square
  LD (HL),$B0             ; Set square to FLASH
  INC HL                  ; Move right one square
  LD (HL),$B0             ; 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 EBC7.
; * 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):
LE7FD:
  LD A,($EBC7)
  CP $04
  JP Z,LEA1D              ; 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,($EAE6)            ; Get spell number counter (for spell list at L6FBC)
  LD ($EAEC),A            ; ...and put in temporary store
  LD A,($EBC7)            ; Get spell type
; Check for MOVE spell
  CP $01
  JR NZ,LE7FD_0
  LD A,$20                ; Move spell selected. Set the spell selection byte
  LD (LEAE1),A            ; accordingly.
  JR LE852                ;
; Check if spell is an 'instant effect' spell (ENERGIZE, HAIL, WAYSTONE,
; FREEZE, SUMMON, PORTAL, MESSAGE):
LE7FD_0:
  CP $05
  JR NZ,LE7FD_1
; Spell is an 'instant effect' spell. These spells have an energy cost to their
; casting (positive in the case of ENERGIZE).
  LD A,($EBC6)            ; Get energy cost of spell. This is the second byte
                          ; in each spell set at L6DFC, e.g.:
                          ; * ENERGIZE = +64
                          ; * HAIL = -1
                          ; * WAYSTONE = -4
                          ; * FREEZE = -4
                          ; * SUMMON = -4
                          ; * PORTAL = -8
  CALL LE3CC              ; Reduce/increase Maroc's energy
  JP LEA34_4              ;
; The spell cast needs a controllable cursor (e.g. SERVANT, OPEN, MISSILE,
; FIND)
LE7FD_1:
  LD A,$01
  LD ($EB50),A            ; Set graphic address pointer frame offset (1 = no
                          ; offset, start at first graphics frame)
  LD ($EC99),A            ; Copy to controllable spell cursor/graphic frame
                          ; buffer
  LD A,($EBCC)            ; Get graphic number for controllable cursor. This
                          ; will either be a pointer to the servant graphic
                          ; (9813/A0DC) or the flashing eye cursor (9817/A105)
  CALL LE0C2              ; Setup graphics (for servant or eye cursor)
; Copy/initialize a few spell-related bytes in the spell data buffer:
  LD HL,($EB51)           ; Get cursor graphics address pointer (9813/9817)
  LD (LEC94),HL           ; ...and store in temporary game buffer
  LD A,($EB4F)            ; Pre-graphics data byte, indicating frames & if
  LD ($EC9A),A            ; graphic can be 'flipped'
  LD A,$28                ; Starting vertical position for the controllable
  LD ($EAFF),A            ; graphic, in pixels, from the top of the playing
                          ; area
  LD A,$70                ; Starting horizontal position for the controllable
  LD ($EB00),A            ; graphic, in pixels, from the left of the playing
                          ; area
  LD A,$30                ; Spell selection status - 48 = servant/cursor
  LD (LEAE1),A            ; controllable spell
  JP LE929                ;

; Check horizontal movement direction & speed (MOVE spell)
;
; Used by the routines at LE641 and LE7FD.
LE852:
  CALL LDD5C              ; Continue to print the spell's message text
  LD A,($EB04)            ; Get Maroc's current left/right (horizontal) speed
  LD C,A                  ;
  LD A,(LEAFD)            ; Get left/right controls flag
  CP $00                  ;
  JR Z,LE880              ; If left/right controls aren't pressed, jump to
                          ; LE880 to slow Maroc down if he's moving
                          ; horizontally

; Increase Maroc's horizonal movement speed
;
; A Left/right controls flag, stored at LEAFD
; C Maroc's current left/right (horizontal) speed, stored at EB04
;
; 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.
LE860:
  CP $80                  ; If bit 7 is set (value is > 128), Maroc is moving
  JR NC,LE860_0           ; right
  LD D,$08                ; Increase Maroc's left movement speed by 8
  JR LE860_1              ;
LE860_0:
  LD D,$F8                ; Increase Maroc's right movement speed by 8
LE860_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 $80                  ; Is Maroc moving left or right?
  JR C,LE860_2            ;
; Maroc is moving right - max speed check
  CP $E0                  ; Check if we've exceeded the maximum speed for this
  JR NC,LE860_3           ; direction (< 224)
  LD A,$E0                ; ...If so, set speed to maximum (224)
  JR LE860_3              ;
; Maroc is moving left - max speed check
LE860_2:
  CP $20                  ; Check if we've exceeded the maximum speed for this
  JR C,LE860_3            ; direction (> 32)
  LD A,$20                ; ...If so, set speed to maximum (32)
LE860_3:
  JR LE880_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 LE852.
;
; C Maroc's horizontal movement speed (stored at EB04)
;
; When left/right control keys are released, Maroc will slow his horizontal
; movement, eventually coming to a stop.
LE880:
  LD A,C                  ; Get Maroc's horizontal movement speed
  CP $00                  ; Is he moving left or right?
  JR Z,LE895              ; 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 $00                  ; Check if this means Maroc has stopped moving
  JR NZ,LE880_0           ; left/right
  LD C,$00                ; ...If so, set speed offset to zero
LE880_0:
  ADD A,C                 ; ...Otherwise, reduce current speed by 1/4
; This entry point is used by the routine at LE860.
LE880_1:
  LD ($EB04),A            ; Store Maroc's adjusted horizontal movement speed

; Check vertical movement direction & speed (MOVE spell)
;
; Used by the routine at LE880.
LE895:
  LD A,($EB05)            ; Get Maroc's current up/down (vertical) speed
  LD C,A                  ;
  LD A,($EAFE)            ; Get up/down controls flag
  CP $00                  ;
  JR Z,LE8C0              ; If up/down hasn't been pressed, jump to LE8C0 to
                          ; slow Maroc down if he's currently moving vertically

; Increase Maroc's vertical movement speed
;
; A Up/down controls flag, stored at EAFE
; C Maroc's current up/down (vertical) speed, stored at EB05
;
; 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.
LE8A0:
  CP $80                  ; If bit 7 is set (value is > 128), Maroc is moving
  JR NC,LE8A0_0           ; down
  LD D,$08                ; Increase Maroc's up movement speed by 8
  JR LE8A0_1              ;
LE8A0_0:
  LD D,$F8                ; Increase Maroc's down movement speed by 8
LE8A0_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 $80                  ; Is Maroc's moving up or down?
  JR C,LE8A0_2            ;
; Maroc is moving down - max speed check:
  CP $E0                  ; Check if we've exceeded the maximum speed for this
  JR NC,LE8A0_3           ; direction (< 224)
  LD A,$E0                ; ...If so, set speed to maximum (224)
  JR LE8A0_3              ;
; Maroc is moving up - max speed check:
LE8A0_2:
  CP $20                  ; Check if we've exceeded the maximum speed for this
  JR C,LE8A0_3            ; direction (> 32)
  LD A,$20                ; ...If so, set speed to maximum (32)
LE8A0_3:
  JR LE8C0_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 LE895.
;
; C Maroc's vertical movement speed (stored at EB05)
;
; When control keys are released, Maroc will slow down, eventually coming to a
; stop if no keys are pressed..
LE8C0:
  LD A,C                  ; Get Maroc's horizontal movement speed
  CP $00                  ; Is he moving up or down?
  JR Z,LE8C0_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 $00                  ; Check if this means Maroc has stopped moving
  JR NZ,LE8C0_0           ; up/down
  LD C,$00                ; ...If so, set speed offset to zero
LE8C0_0:
  ADD A,C                 ; ...Otherwise, reduce current speed by 1/4
; This entry point is used by the routine at LE8A0.
LE8C0_1:
  LD ($EB05),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:
LE8D5:
  LD A,($EAB7)            ; Get Maroc's current room number
  CP $E0                  ; Tunnel rooms are from room number 224 onwards
  JR NC,LE8EE             ;
; Maroc is NOT in a tunnel room so the FIRE button is enabled:
  LD A,($EB32)
  CP $00                  ; Check FIRE control
  JR Z,LE8EE              ; If not pressed, skip to next routine
; FIRE button pressed:
  LD A,$00
  LD ($EB05),A            ; Set Maroc's vertical movement speed to zero
  LD ($EB04),A            ; Set Maroc's horizontal movement speed to zero
  JP LEA34_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 LE8D5.
;
; 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:
LE8EE:
  LD A,($EAB7)            ; Get the current room number
  CP $E0                  ; If >=224, Maroc is in a vertically scrolling tunnel
  JR NC,LE8EE_0           ;
; Maroc is in a standard room, not a vertical tunnel:
  LD E,$5A                ; Default vertical pixel position of the room
  LD ($EB4A),A            ; Store room number
  LD A,$1C                ;
  LD ($EB48),A            ; Default horizontal position of the room, in half
                          ; character (4 pixel) steps
  LD A,($EB04)            ; Calculate and store NEGative value of Maroc's
  NEG                     ; horizontal movement speed (room elements move in
  LD ($EB4C),A            ; the opposite direction to Maroc's controlled
                          ; movement)
  LD A,($EB05)            ; Calculate and store NEGative value of Maroc's
  NEG                     ; vertical movement speed
  LD ($EB4D),A            ;
  CALL LE039              ; Run room boundary collision check and adjustment
  LD A,($EB4D)            ; Copy back the post-boundary check adjusted position
  NEG                     ; to Maroc's vertical position
  LD ($EB05),A            ;
  LD A,($EB4C)            ; Copy back the post-boundary check adjusted position
  NEG                     ; to Maroc's horizontal position
  LD ($EB04),A            ;
  RET                     ; Return to the routine at C7D4
; Maroc is in a vertical scrolling tunnel.
;
; The player can't alter Maroc's vertical speed - it's set at max (32):
LE8EE_0:
  LD A,$20                ; Set Maroc's vertical upward movement speed to
  LD ($EB05),A            ; maximum (32)
  RET                     ; Return to the routine at C7D4

; Player has cast a spell requiring a controllable cursor (e.g. SERVANT,
; MISSILE, OPEN)
;
; Used by the routines at LE641 and LE7FD.
;
; Copy a few spell-related bytes into game data buffers at LEB43 and LEACB:
LE929:
  LD A,($EC99)            ; Copy sprite frame number to data buffer
  LD ($EB50),A            ;
  LD A,($EC9A)            ; Copy pre-graphics byte (for servant or flashing eye
  LD ($EB4F),A            ; graphic) to data buffer
  LD HL,(LEC94)           ; Copy graphics address pointer to data buffer
  LD ($EB51),HL           ;
  CALL LE336              ; Calculate graphic frame address to use for animated
                          ; graphics
  LD A,($EB50)            ; Copy graphic frame number to data buffer
  LD ($EC99),A            ;
  CALL LDD5C              ; Continue to print spell message text and Maroc's
                          ; energy bar on scroll
  LD A,($EB00)            ; Copy sprite horizontal position (in pixels) into
  LD ($EAD3),A            ; buffer
  LD A,($EAFF)            ; Copy sprite vertical position (in pixels) into
  LD ($EAD2),A            ; buffer
  LD A,$01                ; Graphic type = 1
  LD (LEB43),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.
LE958:
  LD A,($EB01)            ; Get sprite horizontal movement speed
  LD C,A                  ;
  LD A,(LEAFD)            ; Get left/right sprite control value (determine
                          ; whether the sprite is moving and in which
                          ; direction)
  CALL LDFBC              ; 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 ($EB01),A            ; ...and store
  LD A,($EB00)            ; 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 $0C                 ; The left and right play area limits are 12 and 228
  CP $D8                  ; 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,LE958_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,$00                ; Set movement speed to zero to stop dead
  LD ($EB01),A            ;
  LD A,($EB00)            ; Get horizontal pixel position
  CP $80                  ; Check which half of the screen it is
  JR C,LE958_0            ;
  LD C,$E4                ; If right hand side, set horizontal pixel position
  JR LE958_1              ; to 228
LE958_0:
  LD C,$0C                ; If left hand side, set horizontal pixel position to
                          ; 12
; Store adjusted horizontal pixel position:
LE958_1:
  LD A,C                  ; Get calculated horizontal pixel position
  LD ($EB00),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.
LE987:
  LD A,($EB02)            ; Get sprite vertical movement speed
  LD C,A                  ;
  LD A,($EAFE)            ; Get up/down sprite control value (determine whether
                          ; the sprite is moving and in which direction)
  CALL LDFBC              ; 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 ($EB02),A            ; ...and store
  LD A,($EAFF)            ; 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 $E0                  ; If new position is < 8 or a negative value, upwards
  JR NC,LE987_0           ; movement will have taken the graphic past the top
  CP $08                  ; border of the playing area
  JR NC,LE987_1           ;
LE987_0:
  LD A,$00                ; ...If so, reset movement speed to zero...
  LD ($EB02),A            ;
  LD A,$08                ; ...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).
LE987_1:
  LD ($EAFF),A            ; Store the new (or reset) vertical pixel position
; Check bottom of playing area boundary
  CP $78                  ; Check if vertical sprite position is greater than
  JR C,LE987_2            ; 120 pixels from top of playing area
  LD A,$00                ; 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 ($EB02),A
LE987_2:
  LD A,$00
  LD ($EAD4),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 ($EACF),A            ; ...Set draw/erase flag to ERASE
  LD HL,(LEC94)           ; Get the graphic address pointer ready to ERASE the
                          ; graphic
  CALL LDB98              ; Run screen boundary checks and erase the
                          ; servant/icon graphic
  LD A,($EB00)            ; Copy the (new) horizontal pixel position into store
  LD ($EAD3),A            ;
  LD A,($EAFF)            ; ...and also the vertical pixel position
  LD ($EAD2),A            ;
  LD A,$01                ; Set draw/erase flag to DRAW
  LD ($EACF),A            ;
  LD HL,($EB51)           ; Copy graphic address pointer to (table at L97C3)
  LD (LEC94),HL           ; into store
  CALL LDB98              ; 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.
LE9DD:
  LD A,($EAD5)            ; Flag indicating whether (any part of) graphic is
                          ; visible on screen
  CP $00                  ; 0 = not visible, 1 = visible
  JP Z,LE9DD_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 LE9DD_1 for
                          ; deactivation.
  LD A,($EB32)            ; Check FIRE key controls
  CP $00                  ;
  JP Z,LEA34_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,($EBCA)            ; This byte's value holds the action to take when a
                          ; servant/spell icon spell is cast
  CP $00                  ; For non-cursor spells, this byte is zero
  JR Z,LE9DD_0            ; ...so make sure it's not one of these
  LD C,A                  ; Temp store of byte's 'action-value' in C register
  AND $80                 ; Check bit 7, which is set for missile type spells
  JR Z,LE9DD_0            ; (MISSILE, FIREBALL etc.)
  LD A,C                  ; If it's set, retrieve the original byte...
  AND $7F                 ; Filter out bit 7
  LD ($EC98),A            ; ...and store the remaining value
LE9DD_0:
  LD A,($EBC7)            ; Check the spell type
  CP $03                  ; 3 = ELECTRIC and FLAME spells
  JR NZ,LE9DD_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,($EBC6)            ; First get the energy cost of the spell...
  CALL LE3CC              ; ...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):
LE9DD_1:
  LD A,$00                ; Set draw/erase flag to ERASE
  LD ($EACF),A            ;
  LD ($EAEC),A            ; Also reset the temp store scroll spell number
                          ; pointer (I think)
  LD HL,(LEC94)           ; Retrieve the graphic address pointer to the
                          ; servant/cursor icon graphic
  CALL LDB98              ; ...and erase the graphic from screen.
  JR LEA34_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 LE641 and LE7FD.
LEA1D:
  LD A,$38                ; This value (56) indicates the spell selected is an
  LD (LEAE1),A            ; ongoing 'effect' spell
  CALL LDD5C              ; 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,($EAFE)            ; Check up/down control value
  CP $00                  ; If the player presses UP or DOWN, spell casting is
  JR NZ,LEA34_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,($EB32)            ; Check if FIRE pressed
  CP $00                  ; If NOT pressed, jump straight to the RET statement
  JP Z,LEA34_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:
LEA34:
  LD L,$F9                ; Low byte of screen display address for left-hand
                          ; character in scroll
  LD A,$07                ; 7 characters to clear
LEA34_0:
  LD B,$08                ; 8 pixel lines in each character
  LD H,$50                ; High byte of screen display address
LEA34_1:
  LD (HL),$00             ; Clear display byte
  INC H                   ; Move down one pixel
  DJNZ LEA34_1            ; Repeat x 8 pixels
  INC L                   ; Move right one character square
  DEC A                   ; Repeat for 7 character squares
  JR NZ,LEA34_0           ;
; Check which spell was deactivated, and reset the relevant effect accordingly:
  LD A,($EAE9)            ; Check which effect spell was activated - spell
                          ; number (0-27) in list at L6DFC
  CP $02                  ; SHIELD spell
  JR Z,LEA34_2            ;
  CP $0B                  ; PROTECT spell
  JR Z,LEA34_2            ;
  CP $12                  ; DEFENCE spell
  LD A,$00                ;
  JR NZ,LEA34_3           ;
LEA34_2:
  LD A,$FF                ; 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.
LEA34_3:
  LD ($EAE9),A            ; Set active 'effect' spell to 0, or 255 if SHIELD,
  LD A,$00                ; PROTECT or DEFENCE.
  LD ($EBD5),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,($EBC8)            ; Check number of charges for spell
  CP $FF                  ; If unlimited charges, no need to decrease
  JR Z,LEA34_4            ;
; Decrease number of spell charges
  DEC A                   ; Decrement spell charges counter
  LD ($EBC8),A            ; ..and store new value.
  CP $00                  ; Out of spell charges?
  JR NZ,LEA34_4           ;
  LD (LEBC5),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).
LEA34_4:
  LD HL,$5A57             ; Top right of scroll
  LD (HL),$30             ; Set to INK 0, PAPER 6
  INC HL                  ; Adjacent square
  LD (HL),$30             ; Ditto
  LD HL,$5A77             ; Same for the 2 squares below
  LD (HL),$30             ;
  INC HL                  ;
  LD (HL),$30             ;
; 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,$5AC7             ; Bottom left of scroll
  LD B,$10                ; 16 characters along the bottom of the scroll
LEA34_5:
  LD (HL),$30             ; Set to INK 0, PAPER 6
  INC HL                  ;
  DJNZ LEA34_5            ; Continue for rest of the row
; Copy current spell data (at LEBC5) into corresponding spell data at L6DFC
  LD HL,LEBC5             ; Spell data buffer
  LD DE,($EAE7)           ; Get spell data address pointer to spell in list at
                          ; L6DFC
  LD BC,$0010             ; 16 bytes of data to copy
  LDIR                    ;
  LD A,$00                ; Set spell selection status byte to 0
  LD (LEAE1),A            ;
  CALL LDEF9              ; Clear all of the scroll text
; This entry point is used by the routines at LE77E, LE9DD and LEA1D.
LEA34_6:
  RET

; Data buffer - scroll text and icon data
LEAA1:
  DEFW $0000              ; Address pointer of message text (1-37) to print,
                          ; starting from the texts at L7172
  DEFB $00                ; Number of text characters, or column characters, to
                          ; print (checked at LE2FA_4)
  DEFW $0000              ; Screen display address to print at (used in various
                          ; routines such as text routines at LE2FA, LE2D0,
                          ; spell charge icons at LE6FA_0, printing rank on
                          ; scroll at LE4E7)
  DEFB $00                ; Decrementing counter affecting pitch of sound
                          ; effect as player holds a key to scroll through the
                          ; spells list. Reset to 5 at E693 if no keys pressed
                          ; while in spell menu

; Data buffer - attributes/colours
LEAA7:
  DEFB $00                ; Maroc's colour - INK 7, PAPER 0, BRIGHT 1
                          ; (attribute value = 71) - set at new game
                          ; initialization at C0F1 and applied in the routine
                          ; at LE220.
  DEFB $00                ; Bits 0-3 of room creature/object's attribute byte
                          ; (from EB8B for item, LEBA5 for creature).Bits 0-2
                          ; contain its INK colour. If bit 3 (8) is set, it
                          ; means the object is flashing (changing colour)
  DEFB $00                ; Room scenery colour (single attribute value) for
                          ; the current room's walls, doors, other scenery etc.
                          ; Set in routine at LE207. As room backgrounds can
                          ; vary, creature/item INK colour (stored in the
                          ; previous byte) is combined with the room background
                          ; PAPER colour (LD27D_2).

; Data buffer - game data (various)
LEAAA:
  DEFB $00                ; Game cycle timer. Multi use throughout the program,
                          ; e.g.:
                          ; * to affect the delay before creatures follow Maroc
                          ;   into a room (LC8DC)
                          ; * to slow down animation rate slightly (LE336)
                          ; * to decide room item/creature movement (LCBA8)
                          ; * to create intervals between creature footstep
                          ;   sounds (LCD88)
  DEFB $00                ; 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 C370
  DEFB $00                ; Maroc's sprite's vertical facing/movement
                          ; direction, set when Maroc enters a new room Set to
                          ; 1 at start of main routine at C6C5 if Maroc is in a
                          ; tunnel - this sets Maroc facing upwards Set to
                          ; 254(-2) (facing downwards) at C370 if Maroc is
                          ; entering through a door at the top of the room (on
                          ; the back wall)
  DEFW $0000              ; Pointer to room item event data table at 7FB3
                          ; Initialized/copied from EB6C at routine at C139
  DEFB $00                ; Door graphic's horizontal pixel graphic offset
                          ; value copied here in the door handling routine at
                          ; LC99B_0
  DEFB $00                ; Room number. Copied from EAB7 at BF94 when new game
                          ; loadedSet to 1 to return to start room when Maroc's
                          ; energy = 0 at D947 255 = Room number needs
                          ; calculating from the door Maroc has just gone
                          ; through (L6790) Set to 255 at end of a tunnel at
                          ; D18E and at CA7D when Maroc leaves a room (value
                          ; checked at LDA0A_0)
  DEFB $00                ; 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 L97C3 for the required
                          ; frame
  DEFW $0000              ; Graphics address pointer for the graphics address
                          ; pointer table at L97C3.
  DEFB $01                ; The connecting room set number (from L6790) Used in
                          ; routine that checks for pursuing creatures at C902
                          ; and the tunnel setup at LC5B5
  DEFW $0000              ; Address pointer for the connecting door set number
                          ; at L6790
  DEFB $01                ; Room number. Starting room is #1 Identifies the
                          ; room data set containing the room size and scenery
                          ; data at L61A9
  DEFB $00                ; - (unused)
  DEFB $3C                ; - (unused)
  DEFB $00                ; - (unused)
  DEFB $40                ; - (unused)
  DEFW $0000              ; (Copy of) pointer to data in room item data tables
                          ; stored at 7C00.
  DEFW $0000              ; Address pointer buffer for the above - (Copy of)
                          ; pointer to room item data at 7C00 Also used for
                          ; foreground scenery data at 7F01 in routine at D504
  DEFB $1D                ; 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 $4A                ; 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 $0000              ; Maroc's sprite frame - graphic address pointer
                          ; (from L97C3)
  DEFW $0000              ; Maroc's shadow - graphic address pointer (98B7)
  DEFB $00                ; Flag indicating whether the fire button (flag at
                          ; EB32) is held down Used as a control to ensure the
                          ; player releases the fire button before pressing it
                          ; again Used/checked in routine at C728
  DEFB $00                ; General all-purpose counter byte:
                          ; * Set to 128 as a sound effect loop counter during
                          ;   lightning effect in routine at LC07A
                          ; * Graphic tile counter (number of tiles the current
                          ;   graphic consists of) in the 'mirror graphics'
                          ;   routine at E12A
                          ; * Scroll line text counter (0-5) for printing the
                          ;   spells, checked at LDF33_7
                          ; * Number of spell 'charge' icons to print on the
                          ;   scroll at LE6FA_0
                          ; * Set to 14 to clear 14 character rows of the
                          ;   playing area at LE25B
                          ; * Text message number for Maroc's rank (see Trivia:
                          ;   Maroc's rank) calculated in the routine at E560
  DEFB $00                ; 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 LE4E7.
  DEFB $00                ; Level text number (L7172), calculated using the
                          ; room number in the lookup table at LC6A4 Value also
                          ; used at LD651 to identify the warlock number
                          ; (L6C7C) for this level
  DEFB $00                ; - (unused)

; Data buffer - graphic working data
;
; Graphic working data buffer - most used in graphic draw/erase routine at
; LDB98
LEACB:
  DEFB $00                ; Graphic's horizontal screen position, in pixels -
                          ; copied to EAD3 at D2BC
  DEFB $00                ; 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 LC837_0
  DEFW $0000              ; Graphics address pointer (table at L97C3)
  DEFB $00                ; Multi use flag/counter:Draw/erase flag (0 = Erase,
                          ; 1 = Draw), used in draw routine at DC3A Used as
                          ; lightning flash counter (6) for intro sequence at
                          ; lightning flash routine at LC07A.
  DEFB $00                ; Number of tiles that make up the sprite/graphic to
                          ; draw
  DEFB $00                ; Number of bytes in the graphic tile to draw
  DEFB $00                ; Store for graphic's vertical position, in pixels,
                          ; from top of playing area
  DEFB $00                ; 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 $00                ; 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 C816 when setting up
                          ; objects
  DEFB $00                ; Flag indicating whether (any part of) graphic is
                          ; visible on screen
                          ; * Set to 0 at the beginning of the graphic drawing
                          ;   routine at DB9E
                          ; * Set to 1 in the same routine if any part of
                          ;   graphic is drawn (DBF7)
                          ; * Appended as bit 0 to the graphic properties byte
                          ;   (EBA8) after drawing (or not drawing) graphic
                          ;   attributes at LD27D_0
  DEFB $00                ; Byte copied from EB4B at D2C2 Indicates whether
                          ; room item is in a standard room or tunnel Stored as
                          ; byte 9 of each room item data set at 7C00
  DEFB $00                ; - (unused)
  DEFB $00                ; - (unused)
  DEFB $00                ; - (unused)
  DEFB $00                ; - (unused)
  DEFB $00                ; - (unused)
  DEFB $00                ; - (unused)
  DEFB $00                ; - (unused)
  DEFW $0000              ; Screen display address position for printing spell
                          ; list/pointer arrow on scroll (LDF33)
  DEFB $00                ; Maroc's energy - 0-255 Set to 128 (half the energy
                          ; bar) at new game start (C0CE) Each 16 points of
                          ; energy corresponds to one character of the energy
                          ; bar graphic (LAEF3)

; Data buffer - spell data
LEAE1:
  DEFB $00                ; Spell selection status byte. Checked at E64B. Set
                          ; to:
                          ; * 0 at new game data initialization (C0DB)
                          ; * 8 after spell names printed on scroll (E672)
                          ; * 24 after energy bar printed (E779)
                          ; * 32 when MOVE spell selected (E805)
                          ; * 48 when SERVANT/other cursor spell cast (E84A)
                          ; * 56 when active 'effect' spell deactivated (LEA1D)
  DEFB $00                ; Store for spell counter used in checking spells
                          ; collected at LE699_2
  DEFW $0000              ; Store for address pointer to the start and/or
                          ; current spell list text at L6DFC (copied from EB65
                          ; at C101) Used to determine spells to print when the
                          ; player presses up or down in the spell menu
  DEFB $00                ; Temp store for spell counter byte at EAE2, copied
                          ; at start of routine at LDF33
  DEFB $00                ; Spell number counter (for spell list at L6FBC) Used
                          ; to print relevnat spell message on scroll at LE753
                          ; Set at DF9D - spell number 3 on the scroll (pointed
                          ; at by the scroll arrow)
  DEFB $00,$00            ; Address pointer for selected/highlighted spell
                          ; (L6DFC). The 16 bytes of spell data are copied
                          ; to/from a buffer at LEBC5
  DEFB $00                ; Currently active 'effect' spell (e.g. UNSEEN,
                          ; SHIELD) - from 0-27 (0 = no effect spell) from
                          ; spell list at L6DFC Set to 255 at EA45 if
                          ; deactivated effect spell is SHIELD, PROTECT or
                          ; DEFENCE - this tells the routine at D4BD to erase
                          ; any on screen 'barrier' graphics
  DEFW $0000              ; Address pointer for active spell message text
                          ; (L6FBC) Also used for level text (L7172), as only
                          ; one or the other appears on the scroll at any one
                          ; time
  DEFB $00                ; Temp store for spell number pointer (EAE6) Also
                          ; used for cast spell number, checked at LD7F3
  DEFB $00                ; - (unused)
  DEFB $00                ; - (unused)

; Data buffer - general (mainly room/scenery related)
LEAEF:
  DEFW $0000              ; Loaded with pointer to reserved data set at 8033
                          ; Copied from EB5F at routine at C141
  DEFB $00                ; Count of number of a particular creature in current
                          ; room.Calculated in creature setup routine at LC460
  DEFB $00                ; 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 $0000              ; Sprite graphic address pointer to 'dummy' graphic
                          ; (98B9) Set up at start of game at C023
  DEFB $00                ; Door properties byte (EB4E), stored in byte 3 of
                          ; connecting door sets at L6790 in routine at LC5B5
                          ; When Maroc exits a room, bit 7 (128) of this byte
                          ; is set, indicating the door he entered from
  DEFB $00                ; Low byte for vertical room position - main position
                          ; stored in next (high) byte
  DEFB $00                ; 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 EB4A at LD26E. Set to 0
                          ; (default room position) at new game data
                          ; initialization at LC107.
  DEFB $00                ; Low byte for horizontal room position. Used as a
                          ; precision/overflow byte (main byte stored in the
                          ; following high byte) From EB47, copied here in
                          ; routine at LD26E
  DEFB $00                ; Room/screen 'viewport' horizontal position, in half
                          ; character/4-pixel steps
  DEFB $00                ; The vertical position of the left back wall/floor
                          ; vertical connector section at LD161, in relation to
                          ; the current room's viewport
  DEFB $00                ; The LEFT (vertical) corner graphic's horizontal
                          ; position, in half character squares (4 pixels) in
                          ; relation to the current room's viewport. Stored at
                          ; LD161 and used for MOVE spell boundary checks at
                          ; LE039_1
  DEFB $00                ; The RIGHT (vertical) corner graphic's horizontal
                          ; position, in half character squares (4 pixels) in
                          ; relation to the current room's viewport. Stored at
                          ; LD161 and checked in MOVE spell boundary checks at
                          ; LE039_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
LEAFD:
  DEFB $00                ; Store for control left/right calculated value of 0,
                          ; 1 (right) or -1 (255) (left), plus the value stored
                          ; at EAAB which is set when Maroc enters a new room
  DEFB $00                ; Store for control up/down calculated value of 0, 1
                          ; (up) or -1 (255) (down), plus the value stored at
                          ; EAAC which is set when Maroc enters a new room
  DEFB $00                ; 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 E840 after servant or other 'cursor
                          ; control' spell cast
  DEFB $00                ; 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 E845 after servant or
                          ; other 'cursor control' spell cast
  DEFB $00                ; Servant/controllable cursor's horizontal movement
                          ; speed. Negative values = left, positive = right
  DEFB $00                ; Servant/controllable cursor's vertical movement
                          ; speed. Negative values = up, positive = down
  DEFB $00                ; 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 LE46C
  DEFB $00                ; 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 $00                ; 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
LEB06:
  DEFW $0000              ; 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 $08,$04,$02,$01,$10 ; Up, down, left, right, fire
  DEFB $00                ; 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 $FDFE              ; 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 $FEFE              ; 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 $7FFE              ; 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 $7FFE              ; 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 $BFFE              ; 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 $00                ; End-of-data byte to indicate end of control checks
; AGF/CURSOR JOYSTICK controls (up, down, left, right, fire)
  DEFW $EFFE              ; 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 $EFFE              ; 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 $F7FE              ; 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 $EFFE              ; 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 $EFFE              ; 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 $00                ; 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 $00                ; UP
  DEFB $00                ; DOWN
  DEFB $00                ; LEFT
  DEFB $00                ; RIGHT
  DEFB $00                ; FIRE
; SINCLAIR JOYSTICK (up, down, left, right, fire)
  DEFW $EFFE              ; 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 $EFFE              ; 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 $EFFE              ; 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 $EFFE              ; 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 $EFFE              ; 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 $00                ; 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 7C00.
; Bytes are copied back and forth between store and buffer.
LEB43:
  DEFB $00                ; Type of graphic to draw - checked & dealt with at
                          ; routine at LC89F: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 $0000              ; Multiple use:
                          ; * Tunnel number offset (32) stored at C627
                          ; * Address pointer to data sets at L6790 (plus
                          ;   offset) stored in routine at LC349_2
                          ; * Address pointer to data set for a room object
                          ;   (L736F) in the current room (checked at LDE7F)
                          ; * Pointer to warlock & creature data sets at L6C7C
                          ;   and 6CB4
                          ; * For missiles, address pointer to missile table at
                          ;   L6CDC
  DEFB $00                ; Multiple uses: 0 = Back wall door 1 = Right wall
                          ; door 2 = Left wall door Connecting door set number
                          ; (from L6790) Tunnel boundary wall type, 1 (right)
                          ; or 2 (left) - LD6D2_1 Tunnel number 0-31 (room
                          ; number minus 224) stored at C62B.Data set number
                          ; for object in room interactable objects table at
                          ; L736F Creature type setup in routine at CD96 -
                          ; warlock & creature data at L6C7C:
                          ; * 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
                          ;   D758)
                          ; * 8 = Bat (creature generation in tunnel at D758)
  DEFB $00                ; 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 LC837_0 Second byte of foreground
                          ; scenery set (at 7F01) stored here in routine at
                          ; D511
  DEFB $00                ; Graphic horizontal position within current room, in
                          ; half character (4-pixel) steps
  DEFB $00                ; Overflow/precision byte used when calculating the
                          ; item's vertical room position ('true' position is
                          ; the next - high - byte which follows this one)
  DEFB $00                ; Graphic vertical position within current room, in
                          ; pixels, from top of room playing area
  DEFB $00                ; 64 - item in standard room 254 - spider/bat in
                          ; tunnel room at D758 255 - other item in tunnel room
                          ; (LC5E7)
  DEFB $00                ; Item's horizontal movement speed For room scenery
                          ; items, calculated at LE8EE using the reverse (NEG)
                          ; of Maroc's horizontal movement speed (EB04) > 128
                          ; (negative) = left, < 128 (positive) = right
  DEFB $00                ; Item's vertical movement speed For room scenery
                          ; items, calculated at LE8EE using the reverse (NEG)
                          ; of Maroc's vertical movement speed (EB05) > 128
                          ; (negative) = up, < 128 (positive) = down
  DEFB $00                ; 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 LCB5B)
                          ; * 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
                          ;   (CE89) - successful object trade
                          ; * WARLOCKS - Bit 7 (128) trigger warlock's
                          ;   appearance, post-materialization animation
  DEFB $00                ; 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 $00                ; Graphic address frame offset (>1 for mirrored
                          ; graphics frames) Used at LE0C2 to calculate the
                          ; graphics address pointer offset for the graphic in
                          ; the table at L97C3 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 E35B
  DEFW $0000              ; Graphic address pointer (in table at L97C3),
                          ; including any offset for the correct graphic frame

; Data buffer - music and sound effects
LEB53:
  DEFB $00                ; Temporary store for the speaker/sound byte used in
                          ; the music playing routine at LE5B6.
  DEFW $0000              ; Store for note data pointer, for music playing
                          ; routine at LE5B6.
  DEFB $00                ; Counter/length/frequency used for the generic sound
                          ; effect routine at LC07A
  DEFW $0000              ; Store to preserve HL register pair, for sound
                          ; playing routine at LE1D7.
  DEFW $0000              ; Address pointer to the ROM to generate semi-random
                          ; byte values to play generic sound effects at LE1D7.
                          ; Reset to 0 at the start of the game loop at C7D4

; Data buffer - general address and spell pointers
LEB5B:
  DEFW $0000              ; Address pointer to game level text at L7172, e.g.
                          ; 'Gatehouse Level'
  DEFW $0000              ; Copy of data pointer at EB61 (pointer to
                          ; flipped/mirrored graphics at 8053)
  DEFW $0000              ; Pointer to 32 bytes of (unused) reserved game data
                          ; at 8033
  DEFW $0000              ; Pointer to flipped/mirrored graphics at 8053
  DEFW $0000              ; Address pointer to the spell text messages at L6FBC
  DEFW $0000              ; Address pointer to the start of the spell list at
                          ; L6DFC
  DEFW $0000              ; Address pointer for the start of spell text message
                          ; list at L6FBC
  DEFB $02                ; Total number of spells (27)
  DEFW $0000              ; Address pointer to graphics address table at L97C3
  DEFW $0000              ; Pointer to room item event data sets at 7FB3
  DEFW $0000              ; - (unused)
  DEFW $0000              ; Pointer to the room's foreground scenery data sets
                          ; at 7F01
  DEFW $0000              ; Store for address pointer to next room item data
                          ; set at 7C00

; Data buffer - room co-ordinate data and pointers
LEB74:
  DEFB $00                ; Maroc's (default) vertical (entry) pixel position
                          ; when he moves to a new room
  DEFB $00                ; Maroc's horizontal (entry) position when he moves
                          ; to a new room, in half-character/4-pixel steps
  DEFB $00                ; Maroc's vertical (entry) position when he moves to
                          ; a new room, in pixels, calculated based on the byte
                          ; stored at LEB74
  DEFB $00                ; Offset for scenery graphics address pointers for
                          ; 'brick' or 'cavern' type levels (table at L97C3)
                          ; * 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 $00                ; Room item's horizontal position within current
                          ; room, in half-character (4 pixel) steps
  DEFB $00                ; Room item's vertical position within current room,
                          ; in pixels, from top of room area
  DEFW $0000              ; Address pointer for room data sets stored at L61A9
                          ; Also used to store for ROM memory address pointer
                          ; used to generate foreground scenery objects at
                          ; LC501_1
  DEFB $00                ; First room data byte from data banks at L61A9
  DEFB $00                ; Multi-purpose byte:
                          ; * Used as a counter to compare with first room data
                          ;   byte (L61A9) which holds the room size
                          ; * Tunnel length - byte 1 of tunnel data set at
                          ;   L6710
  DEFB $00                ; Multi-purpose:
                          ; * Temporary store for room data bytes at L61A9
                          ; * Data byte x 4 (used to calculate co-ordinates)
                          ;   subsequently stored here at C21B
                          ; * Counter for number of boundary walls currently on
                          ;   screen in tunnel section
; Data relating to doors:
  DEFB $00                ; Door byte:
                          ; * 0 = Back wall door
                          ; * 1 = Right wall door
                          ; * 2 = Left wall door
  DEFB $00                ; Positive/negative offset for door graphic frame
                          ; (used in routine at LCAB4) Indicates number of
                          ; frames (bits 0-2) and opening/closing direction
  DEFB $00                ; 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
                          ; C3AB in door calculation routine.

; Data buffer - room objects
LEB82:
  DEFW $0000              ; Address pointer to item's data set in object room
                          ; table at L736F
  DEFB $00                ; Data set number for object in room interactable
                          ; objects table at L736F
; 8 bytes copied here from object data table (L736F) at the routine at LDE7F
  DEFB $00                ; Room number of object being dealt with
  DEFB $00                ; Horizontal (X) position of object in room, in
                          ; 4-pixel (half-character) steps
  DEFB $00                ; Vertical (Y) position of object in room, in pixels,
                          ; from top of room
  DEFB $00                ; Item properties byte (similar to EB4E) 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 $00                ; 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 $00                ; Spell number (or 0 if not a spell) - spell table at
                          ; L6DFC Start counting with MOVE = 0, SERVANT = 1
                          ; etc.
  DEFB $00                ; 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 CE79
  DEFB $00                ; 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 L736F by the routine at LDE7F
  DEFB $00                ; Room item/creature movement pattern byte. Used for
                          ; moving room items (including set room creatures) in
                          ; the routine at LCBA8
                          ; * 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 $00                ; 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 LCC27 Event type 15 =
                          ; Object that Maroc can collect (or be given by the
                          ; servant)
  DEFB $00                ; 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 $00                ; Graphic number - offset for graphic address table
                          ; at L97C3 Calculated is [(n-1)*2] + L97C3 A value of
                          ; 124 (check at LCB00) 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:
LEB91:
  DEFB $00                ; Number of creature-launched missiles currently in
                          ; effect (maximum of 1 missile allowed at any time,
                          ; so will either be 0 or 1)
  DEFB $00                ; Number of Maroc-launched missiles currently in
                          ; effect (incremented at D7B4)
  DEFB $00                ; Missile number (table at L6CDC), used in routine at
                          ; LDB1F
  DEFB $00                ; Missile horizontal position overflow/precision byte
                          ; - to calculate fractions as main position (in next
                          ; byte) is in 4-pixel increments
  DEFB $00                ; Horizontal position of missile origin in 4-pixel
                          ; (half-character) steps
  DEFB $00                ; Missile vertical position overflow/precision byte -
                          ; generally unused as vertical position is in pixels
  DEFB $00                ; Vertical pixel position of missile origin
  DEFB $00                ; Horizontal (X) position of target, in
                          ; half-character (4-pixel) steps
  DEFB $00                ; Vertical (Y) position of target, in pixels
  DEFB $00                ; Object type (missile):
                          ; * 5 = Missile fired by creature (at Maroc)
                          ; * 8 = Missile fired by Maroc
                          ;  Stored as first byte in data set at 7C00.
  DEFW $0000              ; Address pointer to missile data in table at L6CDC
; Missile buffer table. 8 bytes of missile data copied from sets at L6CDC.
  DEFB $00                ; Graphic number - offset for missile graphic address
                          ; in table at L97C3 52 = Missile type 1 (9829) 55 =
                          ; Missile type 2 (9831) 58 = Missile type 3 (9835)
  DEFB $00                ; Missile properties byte Top 4 bits of this byte
                          ; hold the missile's duration/longevity (how long
                          ; it's on screen for)
  DEFB $00                ; Missile ink colour. If bit 3 is set, the missile
                          ; changes colour
  DEFB $00                ; Missile's event/collision type to check
  DEFB $00                ; Counter spell #1 (from list at L6DFC, starting at
                          ; 0) This value = 14 for all missiles = AMULET, which
                          ; resists all missile types
  DEFB $00                ; Used at D126, damage caused by missile = the amount
                          ; to decrease Maroc's energy by
  DEFB $00                ; Counter spell #2 (from list at L6DFC, starting at
                          ; 0) that resists this missile/bolt type
  DEFB $00                ; Counter spell #3 (from list at L6DFC, starting at
                          ; 0) that resists this missile/bolt type

; Data buffer - creature attributes
;
; 8 bytes copied from data sets at L6C7C/6CB4 in creature setup routine at
; LCD88_0
;
; See Reference - Creatures for information about the different denizens that
; inhabit Avalon.
LEBA5:
  DEFB $00                ; INK colour of creature If bit 3 is set it means
                          ; creature changes colour
  DEFB $00                ; Number of these creatures that Maroc has destroyed
  DEFB $00                ; Type of missile (L6CDC) fired by this creature (0 =
                          ; no ranged attack)
  DEFB $00                ; Object number held by this creature, in table at
                          ; L736F (warlocks only)
  DEFB $00                ; Collision/event check type (wraiths/demons = 7,
                          ; other creatures = 3)
  DEFB $00                ; Collision/event check value for creatures
                          ; opening/closing doors (17)
  DEFB $00                ; Graphic number - offset for creature graphic
                          ; address in table at L97C3
  DEFB $00                ; Amount to reduce Maroc's energy by if the creature
                          ; touches Maroc, checked at LD065_0

; Game data buffer - warlock and creature attributes/data
;
; Various bits of warlock and creature data, used in-game.
LEBAD:
  DEFB $00                ; Warlock's "aggression" - this is byte 6 of the
                          ; warlock's data set at L6C7C Affects the delay in a
                          ; warlock appearing on-screen, and the frequency of
                          ; the missiles it fires at Maroc
  DEFB $00                ; Room object number in table at L736F Copied from
                          ; EB46 in routine at CD37 after non-tradeable item
                          ; given to warlock Object number held by warlock
                          ; copied from EBA8 in routine at CE79
  DEFB $00                ; Byte containing attribute/colour and value of item,
                          ; copied from EB8B in routine at CD3F after
                          ; non-tradeable item given to warlock
  DEFB $00                ; - (unused)
  DEFB $00                ; 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 $00                ; - (unused)
  DEFB $00                ; - (unused)
  DEFB $00                ; Timer affecting how long before a warlock is likely
                          ; to materialize in the current room
                          ; * Decremented and checked at D666
                          ; * Reset to 255 at the start of a new game (C0C6)
                          ; * 64 added as a 'top up' to the timer when Maroc
                          ;   enters a new room (LC460_7)
                          ; * Set to 144 when warlock moves off-screen (CEDB)
                          ; * Set to 8 after HAIL spell cast (LD8CE)
                          ; * Set to 224 after object has been successfully
                          ;   traded with the warlock (LCF99_1)
  DEFB $00                ; Timer indicating how long before a creature is
                          ; likely to wander in from an adjacent room
                          ; * Decremented and checked at C90C
                          ; * Reset to 255 at the start of a new game (C0C6)
                          ; * 128 added as a 'top up' to the timer when Maroc
                          ;   enters a new room (LC460_7)
  DEFB $00                ; Number of creatures in current room (max 3)
  DEFB $00                ; Multi-use:
                          ; * Contains the room creature byte (from table at
                          ;   L6B8C) indicating which creatures are in a room
                          ; * Set to 7 as a max counter for a room's
                          ;   interactable objects at LC42A
  DEFB $00                ; Creature's horizontal position (in 4-pixel steps)
                          ; in room, after entering through a door Calculated
                          ; from the door's horizontal position at LC95F_3
  DEFB $00                ; Creature's vertical pixel position in room, after
                          ; entering through a door Calculated from the door's
                          ; vertical position at LC95F_3

; Data buffer - Maroc's inventory address pointers
LEBBA:
  DEFW $0000              ; Address pointer to start of Maroc's inventory at
                          ; 7F72
  DEFW $0000              ; Address pointer to current slot of Maroc's
                          ; inventory at 7F72
  DEFW $0000              ; Address pointer to next inventory slot at 7F72
  DEFB $00                ; - (unused)

; Missile & creature data pointers for start of game
LEBC1:
  DEFW $0000              ; Address pointer to missile data at L6CDC
  DEFW $0000              ; Address pointer to warlock and creature information
                          ; at L6C7C

; Store for currently selected spell data
;
; 16 bytes of spell data for the current selected spell. Copied from L6DFC in
; routine at E702 and copied back at routine at EA8C.
;
; The first set of 8 bytes contains the spell data:
LEBC5:
  DEFB $00                ; Set to 16 if this spell has been acquired, 0 if not
                          ; yet acquired
  DEFB $00                ; 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 $00                ; 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 $00                ; Number of 'charges' left for casting the spell (255
                          ; = infinite uses)
  DEFB $00                ; Character number within the current spell message
                          ; text (at L6FBC) When a spell is activated, the
                          ; message isn't printed all at once, but letter by
                          ; letter Also used for level name texts
  DEFB $00                ; 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 L6CDC. 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
                          ; 7FB3 Room items are affected by moving these active
                          ; cursors over particular objects/areas (e.g.
                          ; OPEN/UNLOCK vs certain doors)
  DEFB $00                ; Graphic number - in the graphics pointer table (at
                          ; L97C3) - for the spell's icon to use on the scroll
                          ; (e.g. LA17E)
  DEFB $00                ; Graphic number - for the graphics pointer table (at
                          ; L97C3) 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 9813
                          ; pointing to servant graphics at A0DC)For all other
                          ; 'aiming cursor' spells (e.g. UNLOCK, MISSILE, OPEN,
                          ; FIND, ICEBOLT) spell offset is 43 (graphics pointer
                          ; 9817 pointing to blinking eye cursor graphics at
                          ; A105)
; The second set of 8 bytes contains the spell name
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
; Finally the energy cost/effect of the spell:
  DEFB $00                ; Energy drain/heal amount for constant effects
                          ; spells, e.g. SHIELD (drain) or CHALICE (heal) -
                          ; actioned in routine at D64B This is stored in byte
                          ; 2 of the spell data (EBC6) which is copied here at
                          ; E7E4 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 LE3FD 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):
LEBD6:
  DEFB $0F                ; First byte = number of bytes in this set, used as a
                          ; loop counter for printing the colour blocks
  DEFB -$41               ; Added to screen attribute display address. In this
                          ; case -65 will move the address up TWO ROWS, and one
                          ; square to the left
  DEFB $01                ; Then move right one square
  DEFB $01                ; ...and another one
  DEFB $1E                ; Then add 30 to the address, which moves down one
                          ; line and back to the left two squares
  DEFB $01,$01,$1E,$01,$01,$1E,$01,$01 ; ...Then a repeat of the 2 x 1
  DEFB $1E,$01,$01                     ; character squares, 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 $09                ; First byte = number of bytes in this set, used as a
                          ; loop counter for printing the colour blocks
  DEFB -$21               ; Added to screen attribute display address. In this
                          ; case -33 will move the address up ONE ROW, and one
                          ; square to the left
  DEFB $01                ; Then move right one square
  DEFB $01                ; ...and another one
  DEFB $1E                ; Then add 30 to the address, which moves down one
                          ; line and back to the left two squares
  DEFB $01,$01,$1E,$01,$01 ; ...Then a repeat of the 2 x 1 character squares,
                           ; for 2 more rows

; Music data
;
; Used by the music playing routine at LE5B6.
;
; 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:
LEBF0:
  DEFB $BE,$BE,$7F,$7F,$50,$50,$7F,$7F ; Bar 1
  DEFB $BE,$BE,$7F,$7F,$50,$50,$7F,$7F ; Bar 1 (repeat)
  DEFB $BE,$BE,$BE,$A0,$5F,$50,$AA,$8F ; Bar 2
  DEFB $BE,$A0,$AA,$8F,$BE,$A0,$AA,$8F ; Bar 3
  DEFB $7F,$6B,$7F,$6B,$7F,$7F,$8F,$8F ; Bar 4
  DEFB $7F,$6B,$7F,$6B,$7F,$7F,$78,$78 ; Bar 5
  DEFB $BE,$A0,$BE,$A0,$AA,$8F,$AA,$8F ; Bar 6
  DEFB $A0,$7F,$A0,$7F,$8F,$78,$8F,$78 ; Bar 7
  DEFB $BE,$BE,$7F,$7F,$50,$50,$7F,$7F ; Bar 8
  DEFB $BE,$BE,$7F,$7F,$50,$50,$7F,$7F ; Bar 8 (repeat)
  DEFB $5F,$5F,$6B,$6B,$78,$78,$7F,$6B ; Bar 9
  DEFB $8F,$78,$A0,$7F,$A0,$7F,$BE,$A0 ; Bar 10
  DEFB $BE,$A0,$BE,$A0,$2F,$2F,$3C,$3C ; Bar 11
  DEFB $40,$40,$50,$50,$5F,$5F,$7F,$7F ; Bar 12
  DEFB $A0,$A0,$BE,$5F,$BE,$5F,$5F,$5F ; Bar 13
  DEFB $BE,$BE,$BE,$BE,$BE,$BE,$BE,$BE ; Bar 14
  DEFB $FF,$FF            ; 255 = End markers
; This short set of music plays when you pause the game (pause routine at
; LC763):
  DEFB $F0,$BE,$D6,$D6,$BE,$A0,$B4,$B4
  DEFB $BE,$A0,$B4,$8F,$78,$78,$8F,$8F
  DEFB $B4,$B4,$7F,$7F,$A0,$A0,$B4,$B4
  DEFB $A0,$A0,$D6,$B4,$BE,$BE,$D6,$D6
  DEFB $FF,$FF

; Data buffer - various bits of spell and tunnel data
LEC94:
  DEFW $0000              ; Store for graphics address pointer table address
                          ; for controllable eye cursor/servant graphics
                          ; (9813/9817) Set when spell cast at E834
  DEFW $0000              ; Flickering barrier graphics for SHIELD, PROTECT and
                          ; DEFENCE spells (A9EC) Initialized at game setup at
                          ; C03C
  DEFB $00                ; Value representing action to take when FIRE pressed
                          ; with a servant/icon spell active (checked at D820
                          ; and E9ED) Values:
                          ; * Missile/bolt spells = 128 + missile number, in
                          ;   table at L6CDC. e.g. MISSILE = 128 + 4 = 132
                          ; * Other cursor spells: DISPEL = 2, UNLOCK = 4,
                          ;   SERVANT = 5, FIND = 8, OPEN = 10, REVEAL = 16
  DEFB $00                ; Graphic animation frame number for controllable
                          ; spell icon Set to 1 at LE7FD_1 when casting a spell
                          ; requiring an aiming cursor, e.g. SERVANT, OPEN,
                          ; FIND, MISSILE Incremented/reset in the routine at
                          ; LE336
  DEFB $00                ; Store for pre-graphics data byte (see Trivia -
                          ; Graphics properties byte) Copied from EB4F in
                          ; routine at E837
  DEFB $80                ; - (unused)
  DEFB $00                ; FREEZE spell timer counter Checked at E34C when
                          ; creature in/entering room
  DEFB $00                ; Tunnel - current number of on-screen creatures (max
                          ; 3)
  DEFB $00                ; Tunnel - (viewport) horizontal position (in
                          ; half-character/4-pixel steps) Copied from EB48 in
                          ; tunnel routine at LD179_3
  DEFB $00                ; Address pointer offset for Maroc's sprite graphic
                          ; address (starting from L97C3) This is an even value
                          ; in the range 0-14 Calculated in the routine at
                          ; LD368_11
  DEFB $00                ; 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
                          ; LCCA8_1
  DEFB $00                ; 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
LECA2:
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$4D,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00

; Code sheet - full code sheet data values
;
; Table of values used in routine at LF1FA to generate/check codes entered
; against code sheet
;
; Values listed in hexadecimal as this is how they are printed on the sheet.
LECB8:
  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 F2F5 and checked at F343
  DEFB $57,$43

; Code sheet - get the code that the player needs to enter
;
; Used by the routine at LF296.
;
; Called from F2F2 after code generated and message printed on screen.
;
; Picks out the relevant code from the code table at LECB8 that the player
; needs to type in. The 2-byte code is returned in the DE registers.
LF1FA:
  LD A,(LF260)            ; Second part of code from code sheet (number) -
  LD L,A                  ; value = 0-41
  LD H,$00                ; Store value in HL register pair
; Each set (0-41) in the code table at LECB8 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,($F261)            ; 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,$00                ; Store value in BC register pair
  ADD HL,BC               ; Add to HL value
  LD BC,LECB8             ;
  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
; LECB8.
;
; 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 LF21E 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)
LF216:
  DEFB $6B,$85            ; System variable FRAMES cycle timer (2 bytes of it)
                          ; stored here at start of code routine at LF289
  DEFB $B9                ; 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 LF289.
  DEFB $8B                ; The byte at F218 is copied here as well in the same
                          ; routine. This will be the random value that the
                          ; co-ordinates are generated from.
  DEFB $76,$B5,$53,$B0    ; 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 LF274.
;
; This routine provides random code sheet co-ordinates for security code entry.
;
; The first 4 bytes at LF216 contain random values (generated at LF289 from the
; FRAMES system variable timer).
;
; This routine then uses a combination of bit shift and XOR operations to
; further obfuscate the data at LF216. Ultimately a randomized byte #4 of this
; set is used to generate the random codesheet co-ordinates.
LF21E:
  PUSH HL                 ; Store registers
  PUSH BC                 ;
  PUSH IX                 ;
  LD B,$08                ; 8 x iterations of the below
; The first 4 pseudo-random bytes at LF216 are altered (using XOR/shifts) with
; the following 4 (fixed) bytes at F21A. This process is started once bits 7 is
; set in the 4th byte just to ensure we've got some data to combine.
LF21E_0:
  LD IX,LF216             ; 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+$03)          ; Top bit of 4th byte in data set (LF216)
  JR Z,LF21E_2            ; If it's zero (bit not set), rotate left first 4
                          ; bytes of data set and jump back to LF21E_0
; Combine some bytes to further mix up the numbers:
  LD HL,$F21A             ; Pointer to byte 5 of 8 byte data set
  LD C,$03                ; 3 iterations
LF21E_1:
  LD A,(IX+$00)           ; Mash together (XOR) bytes 1-3 in the table with
  XOR (HL)                ; (fixed) bytes 5-7
  LD (IX+$00),A           ; ...re-storing each one
  INC IX                  ; Increment both pointers
  INC HL                  ;
  DEC C                   ;
  JR NZ,LF21E_1           ; Repeat for first three 3 bytes in table
  LD IX,LF216             ; Point to the start of the 8 byte set
  SCF                     ; Set the carry flag ready for the next loop
LF21E_2:
  RL (IX+$00)             ; Rotate each of the first 4 bytes
  RL (IX+$01)             ;
  RL (IX+$02)             ;
  RL (IX+$03)             ;
  DJNZ LF21E_0            ; ...and repeat from LF21E_0 (8 iterations)
  LD A,(IX+$03)           ; 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
LF260:
  DEFB $0D                ; Second part of code from code sheet (number) Value
                          ; from 0-41 Printed on screen at F2C3
  DEFB $0F                ; First part of code from code sheet (letter) Letters
                          ; are from A to P, so values will be 0-16 65 is added
                          ; at F2C0 to provide the ASCII values 65-90 (letters
                          ; A to P)Printed on screen at F2BD

; Unused
LF262:
  DEFB $3E,$20,$C9,$3E,$00,$C9

; Code sheet - print code message/character on screen
;
; Used by the routines at LF296, LF2F9 and LF350.
;
LF268:
  EX (SP),HL              ; HL now points to the character(s) to print on
                          ; screen, e.g. F2AA
; Print character:
LF268_0:
  LD A,(HL)               ; Get character from message string
  INC HL                  ; ...and move address pointer on to the next letter
  CP $FF                  ; Check for end-of-text marker
  JR Z,LF268_1            ; If reached, stop printing
  RST $10                 ; Otherwise print the character
  JR LF268_0              ; Repeat until all message characters printed
LF268_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 LF296.
;
; 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.
LF274:
  CALL LF21E              ; Call hashing routine to obfuscate data at LF216
  AND $0F                 ; The A register is returned with a hashed/randomized
                          ; value - the 4th byte of the data set at LF216. Keep
                          ; bits 0-3 (values 0-15)
  LD ($F261),A            ; Store as first part of code from code sheet (this
                          ; will signify the letter, A-P)
  CALL LF21E              ; Call hashing routine again
; Get the number in the range 0-41 as this is the number of code sheet rows:
LF274_0:
  SUB $2A                 ; Subtract 42
  JR NC,LF274_0           ; Still positive (>=0)? If so, keep subtracting
  ADD A,$2A               ; Add 42 to get the number in the range 0 to (+)41
  LD (LF260),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 LF34B.
LF289:
  LD HL,($5C78)           ; Get the system variable FRAMES cycle timer This
                          ; variable is 3 bytes, but only the first two are
                          ; grabbed
  LD (LF216),HL
  LD E,(HL)               ; Load both E & D registers with the contents of this
  LD D,(HL)               ; (random) address
  LD ($F218),DE           ; ...and store
  RET                     ;

; Code sheet - initialize and print security code to enter
;
; Used by the routine at LF350.
LF296:
  CALL LF274              ; Pick a code sheet reference for the code that the
                          ; player has to enter
; This entry point is used by the routine at LF350.
LF296_0:
  CALL $0D6B              ; Clear the screen (ROM CLS routine)
  LD A,$02                ; Stream type = 2
  CALL $1601              ; Open stream for printing
  LD BC,$111B             ; B = character row (27), C = column (17)
  CALL $0DD9              ; These values are reversed and used to calculate
                          ; screen address position in HL (16614) ready to
                          ; print at.
  CALL LF268              ; Print the following characters/message on screen.
                          ; Return from CALL goes to instructions after the
                          ; message, at F2BD
; Initial screen message text:
  DEFM "Type in number at " ; Message to be printed (at previous CALL)
  DEFB $FF                ; End-of-string marker
; Print the co-ordinates for the required code from the code sheet.
  LD A,($F261)            ; Value (0-16) signifying first part of code that the
                          ; player needs to enter
  ADD A,$41               ; 65 added to this code, to give it values of between
                          ; 65 and 80 This corresponds to ASCII character codes
                          ; (A to P)
  RST $10                 ; Print this value on screen
  LD A,$2C                ; ASCII value for comma (,)
  RST $10                 ; Print it
  LD A,(LF260)            ; Get the second part of the code (number from 0-41)
  CP $0A                  ; Is it <10?
  JR C,LF296_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,$31                ; ASCII value for '1' - first digit
  LD E,$0A                ; Offset value for 2nd digit
  CP $14                  ; Code number <20?
  JR C,LF296_1            ;
  LD D,$32                ; If not, set ASCII value for '2' - first digit
  LD E,$14                ; Offset value for 2nd digit
  CP $1E                  ; Code number <30?
  JR C,LF296_1            ;
  LD D,$33                ; If not, set ASCII value for '3' - first digit
  LD E,$1E                ; Offset value for 2nd digit
  CP $28                  ; Code number <40?
  JR C,LF296_1            ;
  LD D,$34                ; If not, set ASCII value for '4' - first digit
  LD E,$28                ; Offset value for 2nd digit
; Print the first digit (tens) of the code:
LF296_1:
  LD A,D                  ; Get the ASCII code value
  RST $10                 ; Print the first code digit
  LD A,(LF260)            ; 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:
LF296_2:
  ADD A,$30               ; Add 48 to get to ASCII values for characters 0 to 9
                          ; (48-57)
  RST $10                 ; Print the second code digit
  CALL LF1FA              ; Retrieve the code from the code table at LECB8 2
                          ; byte code returned in DE (first - low - byte in E,
                          ; second - high - byte in D)
  LD ($F1F8),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):
LF2F9:
  LD BC,$0E13             ; Line number (B) = 14 Column number (C) = 19
  CALL $0DD9              ; Call ROM 'CL-SET' routine HL register pair returned
                          ; with screen display position to print at (18510)
  CALL LF268              ; Print the following characters on screen. On RETurn
                          ; from this CALL, continue from F308
; Characters to print - spaces to clear input area:
  DEFM "     "            ; 5 spaces
  DEFB $FF                ; End-of-data byte
; Prepare for player input:
  LD BC,$0E13             ; Line number (B) = 14 Column number (C) = 19
  CALL $0DD9              ; Call ROM 'CL-SET' routine HL register pair returned
                          ; with screen display position to print at
  LD B,$04                ; 4 digits to enter
  LD HL,$0000             ; HL not needed for print routine (uses RST 16
                          ; instruction and stack pointer to the following
                          ; data)
LF2F9_0:
  CALL LF268              ; Print the (following) characters on screen
; Characters for flashing cursor:
  DEFM $12,$01," ",$12,$00,$08 ; ASCII codes for: - FLASH 1 - " " (SPACE) -
                               ; FLASH 0 - CURSOR LEFT
  DEFB $FF                ; End-of-data marker
; Check player input:
LF2F9_1:
  BIT 5,(IY+$01)          ; FLAGS (system variable) - bit 5 is set if a key is
                          ; pressed
  JR Z,LF2F9_1            ; Keep checking until it's pressed
  RES 5,(IY+$01)          ; Key pressed - reset bit 5 of FLAGS system variable
  LD A,($5C08)            ; Get value of LAST-K (last pressed key)
  CP $0C                  ; Has DELETE been pressed?
  JR Z,LF2F9              ; 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 $30                 ; Is code for key pressed <48 (number 0 = value of
                          ; 48, the first valid character that can be typed)
  JR C,LF2F9_1            ; If so, it's not valid - jump back until another key
                          ; is pressed
  CP $0A                  ; Is the code for the key press one of the numbers
                          ; (0-9)?
  JR NC,LF2F9_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 $10                 ; Print the value on screen
; The value to check against is a 2 byte value stored at F1F8. 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,$00                ;
  ADD HL,DE               ;
  DJNZ LF2F9_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,($F1F8)           ; 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 F354 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 L5D0C and LFDE8.
;
; Jump here from FE17 after game data unpacked/unecrypted. Initializes the code
; generation routine.
LF34B:
  CALL LF289              ; Generate and store 3 random bytes using the FRAMES
                          ; timer system variable
  LD B,$03                ; 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
LF350:
  PUSH BC                 ; Store number of codes left to enter
  CALL LF296              ; Set up player code entry
; RET from F34A 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,LF350_2            ; Jump out here if correct code entered
  CALL LF268              ; Print the following 'wrong code' message text on
                          ; screen. Jump down to F37C on RETurn after printing
; Wrong code message text:
  DEFB $0D,$0D            ; Codes for ENTER x 2 (move two lines down)
  DEFM "    That is wrong - one more try"
  DEFB $FF                ; End-of-message marker
; Pause for a few seconds:
  LD DE,$000A             ; Set outer loop counter (10)
  LD HL,$0000             ; Set inner loop counter (65536)
; Pause loop:
LF350_0:
  DEC DE                  ; Outer loop - decrement DE counter
LF350_1:
  DEC HL                  ; Inner loop - decrement HL counter
  LD A,H                  ; Has inner loop counter reached zero?
  OR L                    ;
  JR NZ,LF350_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,LF350_0           ; If not, continue to decrement both counters
  CALL LF296_0            ; Give the player another chance to enter the right
                          ; code
  JP NZ,$0000             ; ...This time if there's no match, reset the
                          ; computer.
; Correct code has been entered
LF350_2:
  POP BC                  ; Retrieve the number-of-codes-entered counter
  DJNZ LF350              ; Decrement and continue code generation and entry
                          ; for 3 iterations
  JP LBF1A                ; 3 codes have been correctly entered. Jump to
                          ; initialize the game.

; Unused
LF399:
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00

; Unused
LFA00:
  DEFB $00,$FA,$FF,$DD,$21,$9F,$61,$11
  DEFB $4D,$98,$3E,$FF,$37,$14,$08,$15
  DEFB $F3,$21,$00,$00,$C3,$61,$05,$FB
  DEFB $CF,$FF,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00

; Unencrypt all LOADed game data
;
; Used by the routine at L5D0C.
;
; The code here was copied at L5D0C 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 L61A9 to LFA00 is unencrypted in the instructions from
; FDFF.
LFDE8:
  LD SP,$FFFA             ; Put the stack pointer (nearly) at the top of RAM
  LD IX,L61A9             ; IX = address pointer at start of data block to LOAD
  LD DE,$9858             ; Data block length (code up to RAM address 64000)
  LD A,$FF                ; 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 FDFC (as it's not loading a
; header block)
  INC D
  EX AF,AF'
  DEC D
  DI
  LD HL,$FDFF             ; This is the address that the code in the following
                          ; instructions (starting from FDFF) will be at after
                          ; the copy at the start of this routine.
  JP $0561                ; 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,L61A9             ; Start address
  LD DE,$9858             ; Number of bytes to work through
; Unencryption loop:
LFDE8_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,LFDE8_0           ; If not, continue to unencrypt the data
; Data in memory is now unpacked/unencrypted
  LD A,$02
  LD ($5C6B),A            ; Enable screen character rows 22 & 23 for
                          ; INPUT/errors
  EI                      ; Enable interrupts
  JP LF34B                ; Jump to the code input routine
; Unused data
  DEFB $20,$20,$20,$20,$20,$20,$20,$20
  DEFB $20,$20

; Unused
LFE24:
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$00,$00,$00,$00
  DEFB $00,$00,$00,$00,$F3,$0D,$CE,$0B
  DEFB $E3,$50,$CE,$0B,$DB,$02,$4D,$00
  DEFB $2C,$4F,$00,$80,$00,$00,$F0,$B9
  DEFB $0A,$0F,$B1,$33,$8B,$5D,$6A,$32
  DEFB $9B,$36,$65,$33,$B7,$2D,$8B,$5D
  DEFB $86,$5D,$F8,$5C,$2B,$2D,$65,$33
  DEFB $B2,$A2,$ED,$10,$0D,$00,$09,$00
  DEFB $85,$1C,$8C,$80,$03,$7C,$27,$BF
  DEFB $33,$BF,$00,$3E,$00,$3C,$42,$42
  DEFB $7E,$42,$42,$00,$00,$7C,$42,$7C
  DEFB $42,$42,$7C,$00,$00,$3C,$42,$40
  DEFB $40,$42,$3C,$00,$00,$78,$44,$42
  DEFB $42,$44,$78,$00,$00,$7E,$40,$7C
  DEFB $40,$40,$7E,$00,$00,$7E,$40,$7C
  DEFB $40,$40,$40,$00,$00,$3C,$42,$40
  DEFB $4E,$42,$3C,$00,$00,$42,$42,$7E

  DEFB $42,$42,$42,$00,$00,$3E,$08,$08
  DEFB $08,$08,$3E,$00,$00,$02,$02,$02
  DEFB $42,$42,$3C,$00,$00,$44,$48,$70
  DEFB $48,$44,$42,$00,$00,$40,$40,$40
  DEFB $40,$40,$7E,$00,$00,$42,$66,$5A
  DEFB $42,$42,$42,$00,$00,$42,$62,$52
  DEFB $4A,$46,$42,$00,$00,$3C,$42,$42
  DEFB $42,$42,$3C,$00,$00,$7C,$42,$42
  DEFB $7C,$40,$40,$00,$00,$3C,$DB,$02
  DEFB $DB,$02,$DB,$02,$4D,$00,$C0,$53
  DEFB $3F,$00,$06,$03,$CE,$0B,$51,$48
  DEFB $10,$0E,$DC,$0A,$FE,$15,$58,$27
  DEFB $3A,$F3,$54,$F3,$81,$01,$42,$42
  DEFB $42,$42,$3C,$00

