Trevor Merritt e29ac45c84 scroll down works on CHIP-8 and High-Res modes
scroll left and right work in stdef and hidef
adds octo test roms
adds schip fonts to memory
2024-10-27 11:41:25 -04:00

1214 lines
23 KiB
Plaintext

###########################################
#
# Cave Explorer
#
# Discover the secrets of a mysterious
# tunnel system. A fairly elaborate
# Chip8 adventure game. Best played at
# about 20 cycles/frame.
#
# On the overworld, press ASWD to move.
# In platformer levels, A/D move,
# E picks up/sets down blocks,
# Q resets the level.
#
###########################################
: font
0x20 0x20 0x20 0x00 0x20 0xF0 0x10 0x70 0x00 0x40 0xE0 0x90 0xE0 0x90 0x90 0x90
0xE0 0x90 0xE0 0x90 0xE0 0x80 0x80 0xD0 0xB0 0xB0 0x90 0x90 0x90 0x90 0x60 0x60
0x90 0x90 0x90 0x60 0x90 0xD0 0xB0 0x90 0x90 0x90 0x50 0x20 0x40 0x00 0x00 0x00
0x00 0x00 0x60 0x90 0xF0 0x90 0x90 0xF0 0x90 0x90 0xF0 0x80 0xE0 0x80 0x80 0x80
0x80 0xF0 0x80 0xE0 0x80 0xF0 0x40 0x40 0x40 0xF0 0x20 0x40 0x80 0xF0 0x20 0x20
0x20 0xC0 0x60 0x90 0x80 0x90 0x60 0x90 0x90 0xB0 0x70 0x80 0xB0 0x90 0x70 0x80
0x60 0x10 0xE0 0x90 0xA0 0xC0 0xA0 0x90 0x90 0xB0 0xB0 0xD0 0xF0 0x40 0x40 0x40
0x40 0x90 0x90 0x70 0x10 0xE0
: special-complete
: title1
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x07 0xE0 0x00 0x00 0x00 0x00 0x00 0x00
0x08 0x18 0x00 0x00 0x00 0x00 0x00 0x00 0x10 0x04 0x00 0x00 0x00 0x00 0x00 0x00
0x20 0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x02 0x00 0x00 0x00 0x00 0x00 0x00
0x28 0x21 0x00 0x00 0x00 0x00 0x00 0x00 0x40 0x01 0x00 0x00 0x00 0x00 0x00 0x00
0x40 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x40 0x01 0x00 0x00 0x00 0x00 0x0F 0xC0
0x4F 0x81 0x00 0x00 0x00 0x00 0x10 0x30 0x46 0x01 0x00 0x00 0x00 0x00 0x20 0x08
0x20 0x02 0x00 0x00 0x00 0x00 0x30 0xE8 0x20 0x02 0x00 0x00 0x00 0x00 0x4F 0x04
0x10 0x0C 0x00 0x00 0x00 0x00 0x50 0x84 0x1F 0xF6 0x00 0x00 0x00 0x00 0x40 0x04
0x77 0x09 0x00 0x00 0x00 0x00 0x4F 0x84 0x97 0x90 0xC0 0x00 0x00 0x00 0x50 0x4C
0x0E 0xE0 0x20 0x00 0x00 0x00 0x20 0x1E 0x0C 0x00 0x10 0x00 0x00 0x00 0x7F 0xFF
: block-reg-buffer
: phrase1
0x0A 0x41 0x32 0x0C 0x71 0x2D 0x3A 0x1F 0x0A 0x2D 0x2D 0x2D 0x5E 0x52 0x35 0x1F
0x1F 0x3D 0x05
: phrase2
0x2D 0x2D 0x2D 0x2D 0x2D 0x2D 0x2D 0x2D 0x2D 0x24 0x1F 0x00
: phrase3
0x35 0x1F 0x67 0x2D 0x32 0x10 0x1F 0x1A 0x6C 0x2D 0x2D 0x2D 0x2D
: level-buffer
: title2
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x70 0x00 0x00
0x00 0x3E 0x00 0x70 0x3C 0x8C 0x7F 0x00 0x01 0xC1 0x81 0x88 0x42 0x84 0x80 0xE0
0x02 0x00 0x42 0x04 0x42 0x84 0x80 0x10 0x04 0x00 0x44 0x02 0x21 0x04 0x80 0x10
0x08 0x00 0x44 0x01 0x21 0x05 0x00 0x10 0x10 0x03 0x88 0x01 0x10 0x05 0x07 0x10
0x14 0x07 0x08 0x00 0x90 0x45 0x0F 0xD0 0x10 0x0C 0x08 0x60 0x90 0x09 0x06 0x70
0x20 0x18 0x08 0x70 0x90 0x09 0x01 0xA0 0x20 0x18 0x10 0xB0 0x54 0x19 0x00 0x80
0x28 0x10 0x10 0x90 0x4C 0x1A 0x07 0x00 0x20 0x10 0xD0 0xF0 0xA8 0x32 0x46 0x60
0x20 0x0F 0x58 0x00 0x28 0xB2 0x03 0x90 0x29 0x20 0xD1 0x00 0x24 0x33 0x00 0x10
0x30 0x09 0xD4 0x72 0x17 0x73 0x40 0x10 0x14 0x43 0x98 0xF8 0xB6 0x63 0x02 0x10
0x1A 0xA7 0x1B 0x9A 0x33 0x61 0xD0 0x30 0x0D 0x1E 0x1F 0x8D 0x63 0xC1 0xFA 0xD0
0x0F 0xFC 0x0D 0x07 0xE1 0x81 0xFF 0x70 0x04 0x60 0x00 0x02 0xC0 0x00 0x8C 0x20
0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0xFB 0x37 0x98 0x73 0xCF 0xBC 0x00 0x00 0xFB 0xF7 0xD8 0xFB 0xEF 0xBE 0x00
0x00 0xC1 0xE6 0xD8 0xDB 0x6C 0x36 0x00 0x00 0xF0 0xC7 0xD8 0xDB 0xEF 0x3E 0x00
0x00 0xC1 0xE7 0x98 0xDB 0xCC 0x3C 0x00 0x00 0xFB 0xF6 0x1E 0xFB 0x6F 0xB6 0x00
0x00 0xFB 0x36 0x1E 0x73 0x6F 0xB6 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
: bus
0x00 0x04 0x00 0x3D 0x97 0xFF 0xFF 0xFF 0xFF 0xFD 0xFF 0x9D 0x4B 0xFF 0x8B 0x47
0x20 0x04 0x00 0x5D 0xCB 0xFF 0xD8 0x4F 0x26 0x04 0x00 0x1D 0x05 0xFF 0xDB 0x5F
0x21 0x04 0x00 0x1D 0x85 0xFF 0xDB 0x47 0x20 0x84 0x7C 0x1C 0x05 0xFF 0xFF 0xFF
0x20 0x84 0xDA 0x5D 0xC5 0xFF 0x8B 0x47 0x20 0x94 0xBC 0xDD 0xE5 0xFF 0x99 0x5B
0x20 0xB4 0xE6 0x1D 0xE6 0x1F 0xBA 0x5B 0x20 0x94 0xC2 0xDD 0xCF 0xE7 0x8B 0x47
0x20 0x85 0x7D 0xDC 0x3F 0xF9 0xFF 0xFF 0x2F 0xF5 0x83 0x9F 0xFF 0xFE 0xFF 0xFF
0x20 0x05 0xFF 0x1F 0xFF 0xFF 0x7F 0xFF 0xFF 0xFC 0xFE 0x1F 0xFF 0xF3 0xBF 0x07
0xFF 0xFC 0xFE 0x1F 0xFF 0xED 0xDE 0xFB 0xA2 0x2D 0xF8 0x0C 0x07 0xDD 0xED 0xFD
0x2A 0xA8 0x07 0xF7 0xF9 0xD9 0xE3 0x7E 0xAA 0xAB 0xFF 0xEC 0x1E 0xD6 0xF3 0xFE
0xA2 0x25 0xF8 0x00 0x06 0xE7 0x1B 0xFE 0xFF 0xFA 0x07 0xF8 0x03 0x77 0xC0 0x7E
0x00 0x0B 0xBF 0xFE 0x03 0x7B 0xF8 0xFC 0xFF 0xFB 0x9F 0xFF 0x81 0x7C 0xED 0xF8
0x00 0x0B 0xBF 0xFF 0x81 0x7F 0x0E 0x00 0xFF 0xFB 0xAF 0xF0 0x61 0x7F 0xEE 0x60
0xFF 0xFB 0xBA 0x3F 0xF9 0x7F 0xDC 0x98 0xFF 0xFD 0xBD 0xFF 0xFE 0x3F 0xDC 0xF8
0xFF 0xFD 0xBC 0xFF 0xFF 0xCF 0xDC 0xFC 0x00 0x01 0xBD 0x7F 0xFF 0xF1 0xBC 0xFC
0xFF 0xFD 0xBD 0xBF 0x00 0x0E 0x3C 0xDC 0x00 0x01 0x1D 0xC8 0xFF 0xFF 0x8F 0xDE
0x00 0x00 0x1D 0xF3 0xFF 0xFF 0xF3 0xBE 0x00 0x00 0x04 0xFB 0xFF 0xFF 0xFC 0x7C
: mouth 0xF8
: rumbletext # "YOU HEAR A RUMBLE IN THE DISTANCE"
0x71 0x1F 0x1A 0x2D 0x35 0x41 0x32 0x0A 0x2D 0x2D 0x2D 0x2D 0x32 0x2D 0x0A 0x1A
0x17 0x10 0x3D 0x41 0x2D 0x45 0x24 0x2D 0x6C 0x35 0x41 0x2D 0x0C 0x45 0x5E 0x6C
0x32 0x24 0x52 0x41
: uselesstext # "JUST A BUNCHOF GOLD? HOWUSELESS!"
0x4D 0x1A 0x5E 0x6C 0x2D 0x32 0x2D 0x10 0x1A 0x24 0x52 0x35 0x1F 0x3A 0x2D 0x5A
0x1F 0x3D 0x0C 0x05 0x2D 0x35 0x1F 0x67 0x1A 0x5E 0x41 0x3D 0x41 0x5E 0x5E 0x00
: exittext # "CLIMBING OUTYOU EMERGE TO DAZZLING SUNLIGHT"
0x52 0x3D 0x45 0x17 0x10 0x45 0x24 0x5A 0x2D 0x1F 0x1A 0x6C 0x71 0x1F 0x1A 0x2D
0x41 0x17 0x41 0x0A 0x5A 0x41 0x2D 0x2D 0x6C 0x1F 0x2D 0x0C 0x32 0x49 0x49 0x3D
0x45 0x24 0x5A 0x2D 0x5E 0x1A 0x24 0x3D 0x45 0x5A 0x35 0x6C
: pyramidtext # "A VISION OF A PYRAMID? ASECRET WALL?"
0x32 0x2D 0x27 0x45 0x5E 0x45 0x1F 0x24 0x2D 0x1F 0x3A 0x2D 0x32 0x2D 0x12 0x71
0x0A 0x32 0x17 0x45 0x0C 0x05 0x2D 0x32 0x5E 0x41 0x52 0x0A 0x41 0x6C 0x2D 0x67
0x32 0x3D 0x3D 0x05
: skulltext # "SOMEONE LEFTTHEIR SKULL HERE? GROSS!"
0x5E 0x1F 0x17 0x41 0x1F 0x24 0x41 0x2D 0x3D 0x41 0x3A 0x6C 0x6C 0x35 0x41 0x45
0x0A 0x2D 0x5E 0x63 0x1A 0x3D 0x3D 0x2D 0x35 0x41 0x0A 0x41 0x05 0x2D 0x5A 0x0A
0x1F 0x5E 0x5E 0x00
: puzzlestext # "YOU MUST RETURN TO WHERE THIS ALL BEGAN"
0x71 0x1F 0x1A 0x2D 0x17 0x1A 0x5E 0x6C 0x2D 0x2D 0x2D 0x2D 0x0A 0x41 0x6C 0x1A
0x0A 0x24 0x2D 0x6C 0x1F 0x2D 0x2D 0x2D 0x67 0x35 0x41 0x0A 0x41 0x2D 0x6C 0x35
0x45 0x5E 0x2D 0x2D 0x32 0x3D 0x3D 0x2D 0x10 0x41 0x5A 0x32 0x24
: deadendtext # "A DEAD END? NUTS!"
0x32 0x2D 0x0C 0x41 0x32 0x0C 0x2D 0x41 0x24 0x0C 0x05 0x2D 0x24 0x1A 0x6C 0x5E
0x00
: mazetext # "SNWEW"
0x5E 0x24 0x67 0x41 0x67
: draw-bitmap
clear
v0 := 0 # x
v1 := 0 # y
v2 := 0 # byte
v3 := 1 # constant
loop
sprite v0 v1 1
i += v3
v2 += 1
v0 += 8
if v0 == 64 then v1 += 1
if v0 == 64 then v0 := 0
if v1 != 32 then
again
;
: draw-text
v1 := 2 # x
v2 := 1 # y
v3 := 0 # byte
# v4 contains length
loop
: text-addr i := 0 # self-modify to alter
i += v3
load v0
i := font
i += v0
sprite v1 v2 5
v1 += 5
if v1 == 62 then v2 += 6
if v1 == 62 then v1 := 2
v3 += 1
if v3 != v4 then
again
;
: wait
v0 := 128
delay := v0
loop
v0 := delay
if v0 != 0 then
again
;
: swapmouth
i := mouth
v0 := 4
v1 := 22
sprite v0 v1 1
v0 := 52
v1 := 29
sprite v0 v1 1
;
: draw-phrase-1
:unpack 0xA phrase1
i := text-addr
save v1
v4 := 19
draw-text
;
: draw-phrase-2
:unpack 0xA phrase2
i := text-addr
save v1
v4 := 12
draw-text
;
: draw-phrase-3
:unpack 0xA phrase3
i := text-addr
save v1
v4 := 13
draw-text
;
###########################################
#
# Block pushing puzzle
#
###########################################
: solid 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
: empty 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
: floor 0x00 0xFE 0x55 0x22 0x88 0x00 0x00 0x00
: roof 0x00 0x00 0x00 0x11 0x91 0x8B 0x8F 0xDF
: exit 0xC3 0xBD 0xBD 0xBD 0xB9 0xB9 0xBD 0xBD
: block 0x81 0x7E 0x5A 0x7E 0x7E 0x5A 0x7E 0x81
: left 0xE7 0xE7 0xC3 0x81 0x82 0x42 0xDB 0x93
: right 0xE7 0xE7 0xC3 0x81 0x41 0x42 0xDB 0xC9
:const SOLID 0
:const EMPTY 1
:const FLOOR 2
:const ROOF 3
:const EXIT 4
:const BLOCK 5
:const PLAYER_L 6
:const PLAYER_R 7
:alias levelno ve
:alias playerx vd
:alias playery vc
:alias input vb
:alias direction va
:alias win v9
# v0-v8 reserved for temporary use.
# v0-v7 are used together for fast buffer copies.
# player facing
:const FACING_LEFT 0
:const FACING_RIGHT 1
# input keys:
:const MOVE_LT 7
:const MOVE_RT 9
:const RESET 4
:const ACTION 6
###########################################
#
# Level data
#
###########################################
: level-0
4 1 1 3 1 1 3 0
2 1 1 1 1 1 1 3
0 2 1 1 1 1 1 1
0 0 2 2 2 2 1 6
: level-1
4 1 3 1 3 1 1 1
2 1 1 1 1 1 1 5
0 1 1 6 1 1 2 2
0 1 2 2 1 5 0 0
: level-2
3 1 1 1 1 1 1 4
1 1 1 2 2 2 2 2
5 1 1 1 1 1 1 1
2 5 1 1 6 1 1 5
: level-3
1 1 1 1 3 1 1 3
4 1 6 1 1 1 1 5
2 1 2 1 1 1 2 2
0 1 0 5 1 1 0 0
: level-4
5 1 3 0 3 1 1 4
1 1 1 3 1 1 1 2
1 1 1 1 1 1 1 0
2 2 1 6 1 5 2 0
: level-5
4 1 1 1 1 1 1 1
2 1 1 6 1 5 1 5
0 1 1 2 1 1 1 1
0 1 1 0 1 5 1 5
: level-6
0 3 1 5 1 1 1 4
3 1 1 1 1 1 1 2
1 1 1 5 2 1 1 0
5 5 1 6 0 1 1 0
: level-7
3 3 1 4 1 5 3 3
5 5 1 1 1 1 5 5
1 1 1 1 1 1 1 1
2 1 1 6 1 1 1 5
###########################################
#
# Level utilities
#
###########################################
: level-table
i := level-0 return
i := level-1 return
i := level-2 return
i := level-3 return
i := level-4 return
i := level-5 return
i := level-6 return
i := level-7 return
: get-level
v0 <<= levelno
v0 <<= v0
jump0 level-table
: copy-level
v8 := 0
loop
get-level
i += v8
load v7
i := level-buffer
i += v8
save v7
v8 += 8
if v8 != 32 then
again
;
: get-tile
# takes tile index in v0
v0 <<= v0
v0 <<= v0
v0 <<= v0
i := solid
i += v0
;
: spawn-player
direction := FACING_LEFT
win := 0
playerx := v1
playerx >>= playerx
playerx >>= playerx
playerx >>= playerx
playery := v2
playery >>= playery
playery >>= playery
playery >>= playery
;
: init-level
copy-level
clear
v1 := 0 # sprite x
v2 := 0 # sprite y
v3 := 0 # tile index
loop
i := level-buffer
i += v3
load v0
if v0 == PLAYER_L then spawn-player
get-tile
sprite v1 v2 8
v3 += 1
v1 += 8
if v1 == 64 then v2 += 8
if v1 == 64 then v1 := 0
if v2 != 32 then
again
;
: index-at
# takes x/y in v1/v2
# returns type in v0
v0 <<= v2
v0 <<= v0
v0 <<= v0
v0 += v1
i := level-buffer
i += v0
;
: draw-at
# takes x/y in v1/v2
# trashes v0-v2
index-at
load v0
get-tile
v1 <<= v1
v1 <<= v1
v1 <<= v1
v2 <<= v2
v2 <<= v2
v2 <<= v2
sprite v1 v2 8
;
: copy-loc
v1 := v3
v2 := v4
;
: set-at
# takes x/y in v3/v4, value in v5
copy-loc
draw-at
copy-loc
index-at
v0 := v5
save v0
copy-loc
draw-at
;
###########################################
#
# Block pusher player helpers
#
###########################################
:alias canpass v7
:alias deltadir v6
: player-loc
v1 := playerx
v2 := playery
;
: player-copy
v3 := playerx
v4 := playery
;
: player-ahead
player-loc
v1 += deltadir
;
: player-above
player-loc
v2 += -1
;
: player-below
player-loc
v2 += 1
;
: draw-player
player-loc
draw-at
;
: player-above-type
player-above
index-at
load v0
;
: carrying?
# returns result in v0
v0 := 0
if playery == 0 then return
player-above-type
if v0 != BLOCK then v0 := 0
if v0 == BLOCK then v0 := 1
;
###########################################
#
# Block pusher movement
#
###########################################
: passable?
# takes x/y in v1/v2
# returns flag in canpass
canpass := 0
if v1 > 7 then return
if v2 > 3 then return
index-at
load v0
if v0 == EMPTY then canpass := 1
if v0 == EXIT then canpass := 1
;
: fall-scan
player-copy
v3 += deltadir
loop
copy-loc
v2 += 1
passable?
while canpass == 1
v4 += 1
again
;
: move-player
# if we're stepping onto
# an exit, we win.
copy-loc
index-at
load v0
if v0 == EXIT then win := 1
# takes x/y in v3/v4
draw-player
player-loc
index-at
v0 := EMPTY
save v0
draw-player
playerx := v3
playery := v4
v5 := PLAYER_L
v5 += direction
set-at
;
: hide-block
v5 := EMPTY
: set-block
player-copy
v4 += -1
set-at
;
: show-block
v5 := BLOCK
jump set-block
: climb-move
player-copy
v3 += deltadir
v4 += -1
move-player
;
: climb-carry
# can't climb if blocked above-side
player-above
v1 += deltadir
passable?
if canpass != 1 then return
# can't climb if blocked above-above-side
player-above
v1 += deltadir
v2 += -1
passable?
if canpass != 1 then return
hide-block
climb-move
show-block
;
: climb
# can't climb if blocked above:
player-above
passable?
if canpass != 1 then return
# can't climb if blocked above-side
player-above
v1 += deltadir
passable?
if canpass != 1 then return
climb-move
;
: carry
# make sure we don't need to climb:
player-loc
v1 += deltadir
passable?
if canpass != 1 then jump climb-carry
# make sure there's horizontal space for the block
player-loc
v1 += deltadir
v2 += -1
passable?
if canpass != 1 then return
hide-block
# scan down and 'fall':
fall-scan
move-player
show-block
;
: walk
# make sure we aren't carrying a block:
carrying?
if v0 != 0 then jump carry
# make sure we don't need to climb:
player-loc
v1 += deltadir
passable?
if canpass != 1 then jump climb
# scan down and 'fall':
fall-scan
move-player
;
: walk-left
deltadir := -1
if direction == FACING_LEFT then jump walk
# face left
player-copy
v5 := PLAYER_L
set-at
direction := FACING_LEFT
;
: walk-right
deltadir := 1
if direction == FACING_RIGHT then jump walk
# face right
player-copy
v5 := PLAYER_R
set-at
direction := FACING_RIGHT
;
: drop
# there must be at least one empty space
player-ahead
passable?
if canpass != 1 then return
# erase block
player-copy
v4 += -1
v5 := EMPTY
set-at
# scan for drop position
fall-scan
# draw repositioned block
v5 := BLOCK
set-at
;
: action
deltadir := 1
if direction == FACING_LEFT then deltadir := -1
carrying?
if v0 != 0 then jump drop
# we can only pick up block tiles
player-ahead
index-at
load v0
if v0 != BLOCK then return
# the space above us must be empty
player-above-type
if v0 != EMPTY then return
# erase block
player-copy
v3 += deltadir
v5 := EMPTY
set-at
# draw repositioned block
player-copy
v4 += -1
v5 := BLOCK
set-at
;
###########################################
#
# Block pusher main routine
#
###########################################
: puzzle-finished-count 0
: block-puzzle
i := block-reg-buffer
save vd
init-level
loop
input := key
if input == RESET then init-level
if input == MOVE_LT then walk-left
if input == MOVE_RT then walk-right
if input == ACTION then action
if win == 0 then
again
v0 := 32
buzzer := v0
clear
i := puzzle-finished-count
load v0
v0 += 1
i := puzzle-finished-count
save v0
i := block-reg-buffer
load vd
;
###########################################
#
# Overworld
#
###########################################
: rocks1 0x00 0x40 0x00 0x00
: rocks2 0x00 0x20 0x40 0x00
: rocks3 0x00 0x40 0x20 0x00
: rocks4 0x00 0x00 0x00 0x00
: path 0x60 0xF0 0xF0 0x60
: man 0x00 0x60 0x60 0x00
: target 0x70 0x40 0xF0 0x50
: bits 1 2 4 8 16 32 64 128
:alias boardno vd
:alias manx vc
:alias many vb
:alias specialx va
:alias specialy v9
:alias oldx v8
:alias oldy v7
:alias specialflag v6
###########################################
#
# Board data
#
###########################################
: special-pos
3 6 # board 0
7 4 # board 1
14 6 # board 2
7 4 # board 3
3 3 # board 4
12 4 # board 5
7 5 # board 6
7 4 # board 7
7 6 # board 8
9 4 # board 9
10 4 # board A
11 3 # board B
5 3 # board C
5 3 # board D
5 3 # board E
5 3 # board F
# board in each direction
# 0 1 2 3 4 5 6 7 8 9 A B C D E F
: board-n
0x0 0x2 0x1 0x5 0xA 0x6 0x7 0x7 0x8 0x9 0x3 0xC 0xC 0xC 0xC 0xE
: board-e
0x3 0x4 0x2 0x1 0x9 0x8 0x6 0x7 0xA 0x9 0xA 0xB 0xD 0xE 0xF 0xD
: board-s
0x0 0x2 0x1 0xA 0xD 0x3 0x5 0x6 0x8 0x9 0x4 0xB 0xB 0xB 0xB 0xB
: board-w
0x0 0x3 0x2 0x0 0x1 0x5 0x6 0x7 0x5 0x4 0x8 0xB 0xD 0xD 0x3 0xF
# pixel data
: board0
0x28 0xEB 0x0A 0x7A 0x02 0xEF 0x28 0x2A
0x6A 0x4A 0x5A 0x42 0x7A 0x0A 0x6E 0x28
: board1
0x08 0x08 0x4A 0x08 0xFF 0x40 0x5E 0x52
0x42 0x7E 0x40 0xCF 0x08 0x4A 0x08 0x08
: board2
0x00 0x70 0x50 0x50 0xD7 0x54 0x54 0x54
0x54 0x54 0x54 0xD5 0x14 0x14 0x7C 0x00
: board3
0x28 0x28 0x28 0xEB 0x0A 0x6A 0x0A 0x3A
0x22 0x3A 0x2A 0x2E 0x20 0x38 0x08 0x28
: board4
0x08 0x08 0x1C 0x7F 0x5C 0xC9 0x08 0x1C
: gate1 0x60 0x1C 0x08 0x08 0x1C : gate2 0x60 0x1C 0x08
: board5
0x10 0x00 0x03 0xF3 0x10 0x10 0x10 0xDF
0xD0 0x16 0x16 0x10 0x10 0x10 0x10 0x10
: board6
0x00 0x02 0x4A 0x66 0x70 0x78 0x7C 0xFF
0x7C 0x78 0x70 0x66 0x4A 0x02 0x00 0x00
: board7
0x00 0x76 0x52 0x5A 0x04 0x00 0x39 0xFB
0x39 0x00 0x04 0x5A 0x52 0x76 0x00 0x00
: board8
0x10 0x7E 0x08 0x7E 0x10 0x7E 0x08 0x7E
0x10 0x7E 0x08 0x7E 0x10 0x7E 0x10 0x10
: board9
0x08 0x08 0xD8 0x52 0xD0 0x10 0x38 0x2B
0x3A 0x12 0x02 0xC2 0x4E 0x78 0x10 0x18
: boardA
0x10 0x54 0x10 0xFF 0x04 0x7C 0x40 0x7C
0x04 0x1C 0x10 0x00 0x28 0x6C 0x74 0x38
: boardB
0x00 0xF2 0xEA 0x02 0x02 0xC3 0x0A 0xFA
0x02 0xFA 0xA2 0x8A 0x22 0xF2 0x9A 0x38
: boardC
0x08 0x08 0x08 0x3E 0x22 0xFB 0x22 0x3E
0x08 0x08 0x08 0x08 0x08 0x08 0x08 0x08
: boardD
0x08 0x08 0x08 0x3E 0x22 0xFB 0x22 0x3E
0x08 0x08 0x08 0x08 0x08 0x08 0x0A 0x08
: boardE
0x08 0x08 0x08 0x3E 0x22 0xFB 0x22 0x3E
0x08 0x08 0x08 0x08 0x0A 0x08 0x0A 0x08
: boardF
0x08 0x08 0x08 0x3E 0x22 0xFB 0x22 0x3E
0x08 0x08 0x0A 0x08 0x0A 0x08 0x0A 0x08
###########################################
#
# Overworld game logic
#
###########################################
: secret-wall
if boardno != 6 then return
if v4 != 7 then return
v5 := 0b11111100
;
: draw-board
clear
v1 := 0 # x tile
v4 := 0 # data offset
v3 <<= boardno # data base
v3 <<= v3
v3 <<= v3
v3 <<= v3
loop
i := board0
i += v3
i += v4
load v0
v5 := v0 # column
v2 := 0 # y tile
secret-wall
loop
i := rocks1
v0 := random 0b1100
i += v0
v5 >>= v5
if vf != 0 then i := path
sprite v1 v2 4
v2 += 4
if v2 != 32 then
again
v1 += 4
v4 += 1
if v4 != 16 then
again
specialx := -1
specialy := -1
i := special-complete
i += boardno
load v0
if v0 != 0 then return
v0 <<= boardno
i := special-pos
i += v0
load v1
specialx := v0
specialy := v1
v0 <<= v0
v0 <<= v0
v1 <<= v1
v1 <<= v1
i := path
sprite v0 v1 4
i := target
sprite v0 v1 4
;
: draw-man
v0 <<= manx
v0 <<= v0
v1 <<= many
v1 <<= v1
i := man
sprite v0 v1 4
;
: copy-pos
oldx := manx
oldy := many
;
: try-special
if manx != specialx then return
if many != specialy then return
specialflag := 1
;
: try-move
# fetch column data
i := board0
v0 <<= boardno
v0 <<= v0
v0 <<= v0
v0 <<= v0
i += v0
v3 := 15
v2 := manx
v2 &= v3
i += v2
load v0
v1 := v0
# fetch row mask
i := bits
v3 := 7
v2 := many
v2 &= v3
i += v2
load v0
v0 &= v1
vf := 1
if v0 != 0 then try-special
if v0 != 0 then return
# roll back
manx := oldx
many := oldy
vf := 0
;
: change-board
i += boardno
load v0
if v0 == boardno then return
boardno := v0
draw-board
;
: overworld-walk-w
manx += -1
try-move
if vf == 0 then return
if manx != -1 then return
i := board-w
manx := 15
jump change-board
: overworld-walk-e
manx += 1
try-move
if vf == 0 then return
if manx != 16 then return
manx := 0
i := board-e
jump change-board
: overworld-walk-n
many += -1
try-move
if vf == 0 then return
if many != -1 then return
many := 7
i := board-n
jump change-board
: overworld-walk-s
many += 1
try-move
if vf == 0 then return
if many != 8 then return
many := 0
i := board-s
jump change-board
: overworld-walk
if v2 == 7 then jump overworld-walk-w
if v2 == 9 then jump overworld-walk-e
if v2 == 5 then jump overworld-walk-n
if v2 == 8 then jump overworld-walk-s
;
###########################################
#
# Special scripted events
#
###########################################
: rumble
v0 := 0b00001100
save v0
clear
:unpack 0xA rumbletext
i := text-addr
save v1
v4 := 36
draw-text
v0 := key
;
: open-gate-1
i := gate1
rumble
;
: open-gate-2
i := gate2
rumble
;
: useless-gold
clear
:unpack 0xA uselesstext
i := text-addr
save v1
v4 := 32
draw-text
v0 := key
;
: pyramid-hint
clear
:unpack 0xA pyramidtext
i := text-addr
save v1
v4 := 36
draw-text
v0 := key
;
: gross-skull
clear
:unpack 0xA skulltext
i := text-addr
save v1
v4 := 36
draw-text
v0 := key
;
: dead-end
clear
:unpack 0xA deadendtext
i := text-addr
save v1
v4 := 17
draw-text
v0 := key
;
: maze-hint
clear
:unpack 0xA mazetext
i := text-addr
save v1
v4 := 5
draw-text
v0 := key
;
: nop ;
: puzzle-0 ve := 0 block-puzzle ;
: puzzle-1 ve := 1 block-puzzle ;
: puzzle-2 ve := 2 block-puzzle ;
: puzzle-3 ve := 3 block-puzzle ;
: puzzle-4 ve := 4 block-puzzle ;
: puzzle-5 ve := 5 block-puzzle ;
: puzzle-6 ve := 6 block-puzzle ;
: puzzle-7
ve := 7
block-puzzle
clear
:unpack 0xA exittext
i := text-addr
save v1
v4 := 44
draw-text
v0 := key
i := bus
draw-bitmap
loop again
: special-things
jump puzzle-7 # 0
jump useless-gold # 1
jump puzzle-1 # 2
jump puzzle-0 # 3
jump open-gate-2 # 4
jump gross-skull # 5
jump puzzle-2 # 6
jump open-gate-1 # 7
jump puzzle-3 # 8
jump puzzle-6 # 9
jump dead-end # A
return # B
jump pyramid-hint # C
jump puzzle-4 # D
jump maze-hint # E
jump puzzle-5 # F
: check-puzzles
i := puzzle-finished-count
load v0
if v0 != 7 then return
v0 += 1
i := puzzle-finished-count
save v0
clear
:unpack 0xA puzzlestext
i := text-addr
save v1
v4 := 45
draw-text
v0 := key
i := board-e
v0 := 0
save v0
;
###########################################
#
# Overworld main routine
#
###########################################
: do-special
i := special-complete
i += boardno
v0 := 1
save v0
v0 <<= boardno
jump0 special-things
: main
# intro sequence
i := title1
draw-bitmap
draw-phrase-1
wait
draw-phrase-1
swapmouth
draw-phrase-2
wait
draw-phrase-2
swapmouth
draw-phrase-3
wait
draw-phrase-3
i := title2
draw-bitmap
v0 := key
# main routine
manx := 10
many := 4
draw-board
loop
draw-man
v2 := key
draw-man
copy-pos
specialflag := 0
overworld-walk
if specialflag != 0 then do-special
check-puzzles
if specialflag != 0 then draw-board
again