########################################### # # 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