Random level generation (post #3: https://www.xtof.info/blog/?p=1186)

This commit is contained in:
Christophe Meneboeuf 2020-01-15 23:56:47 +01:00
parent 7fcdb9d800
commit eff3827d20
35 changed files with 3503 additions and 1018 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
.vscode/
.DS_Store
*.out
*.a2
*.o

1348
LICENSE

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
APPLE2_CL := $(CC65_HOME)/bin/cl65
APPLE2_SRC := src/main.asm src/math.asm src/random.asm \
APPLE2_SRC := src/main.asm src/math.asm src/memory.asm src/random.asm \
src/game_loop.asm src/display.asm src/tiles.asm src/world.asm src/player.asm \
src/debug.asm
src/debug.asm src/builder/builder.asm src/builder/rooms.asm src/builder/maze.asm src/display_map.asm \
src/io/title.asm src/io/textio.asm src/io/gr.asm
APPLE2_MAP := escape.map
APPLE2_CFLAGS := -Oirs -v -t apple2 -vm --cpu 6502
APPLE2_OUT := bin/escape.a2
@ -15,4 +16,4 @@ apple2: $(APPLE2_SRC)
$(APPLE2_CL) -m $(APPLE2_MAP) -o $(APPLE2_OUT) $? $(APPLE2_CFLAGS) -C src/escape.cfg
clean: $(SRC)
rm -f $(APPLE2_MAP) src/*.o src/*.s gmon.out & rm -r bin/
rm -f $(APPLE2_MAP) src/*.o src/*.s src/builder/*.o src/builder/*.s src/io/*.s src/io/*.s gmon.out & rm -r bin/

Binary file not shown.

View File

@ -10,7 +10,7 @@ if (( $# != 3 )); then
exit
fi
echo " . revoving previous instance of ESCAPE form the disk"
echo " . removing previous instance of ESCAPE form the disk"
java -jar ${1} -d ${3} ESCAPE
echo " .. adding ESCAPE to the disk"

View File

@ -38,21 +38,52 @@ def fill_rect(x,y,color):
outline = (0,0,128),
fill = color)
# returns rays from (x0, y0) to (x1, y1)
# output in rays
def compute_rays(x0, y0, x1, y1, rays):
ray = list(bresenham(x0, y0, x1, y1))
# Duplicate the ray so that x and y are not incremented at the same time
duplicated = False
ray_x = [] # x incremented before y
ray_y = [] # y incremented before x
x = ray[0][0]
y = ray[0][1]
for tile in ray[1:]:
if tile[0] != x and tile[1] != y:
duplicated = True
ray_x.append((tile[0], y))
ray_x.append((tile[0], tile[1]))
ray_y.append((x, tile[1]))
ray_y.append((tile[0], tile[1]))
else:
ray_x.append((tile[0], tile[1]))
ray_y.append((tile[0], tile[1]))
x = tile[0]
y = tile[1]
rays.append(ray_x)
if duplicated:
rays.append(ray_y)
return rays
if __name__=="__main__":
rays = []
y = 0
for x in range(0,SIZE_GRID-1):
rays.append(list(bresenham(x_player,y_player,x,y)))
rays = compute_rays(x_player,y_player,x,y, rays)
x = SIZE_GRID-1
for y in range(0,SIZE_GRID-1):
rays.append(list(bresenham(x_player,y_player,x,y)))
rays = compute_rays(x_player,y_player,x,y, rays)
y = SIZE_GRID-1
for x in range(SIZE_GRID-1,0,-1):
rays.append(list(bresenham(x_player,y_player,x,y)))
rays = compute_rays(x_player,y_player,x,y, rays)
x = 0
for y in range(SIZE_GRID-1,0,-1):
rays.append(list(bresenham(x_player,y_player,x,y)))
rays = compute_rays(x_player,y_player,x,y, rays)
# create the grid
@ -67,7 +98,7 @@ if __name__=="__main__":
nb_cells = 0
rgb = 0
for ray in rays:
for tile in ray[1:]:
for tile in ray:
fill_rect(tile[0], tile[1], (rgb,rgb,rgb))
nb_cells += 1
rgb += int(200 / len(rays))
@ -78,8 +109,8 @@ if __name__=="__main__":
str_ray = "; Nb rays: {}\n".format(len(rays))
str_ray += "; A ray: length (nb_tiles), offset_from_view_in_world_low, offset_from_view_in_world_high, offset_view\nRays:\n"
for ray in rays:
str_ray += ".byte " + str(len(ray)-1)
for tile in ray[1:]:
str_ray += ".byte " + str(len(ray))
for tile in ray:
offset_view = tile[0] + SIZE_GRID*tile[1]
offset_world = (tile[0] + WIDTH_WORLD*tile[1])
offset_world_low = offset_world & 0xFF
@ -90,4 +121,4 @@ if __name__=="__main__":
print(str_ray)
Im.show()

247
src/builder/builder.asm Normal file
View File

@ -0,0 +1,247 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
; All the dungeon builder is based on this article: http://journal.stuffwithstuff.com/2014/12/21/rooms-and-mazes/
.include "rooms.inc"
.include "maze.inc"
.include "../io/textio.inc"
.include "../monitor.inc"
.include "../world.inc"
.include "../memory.inc"
.import World
.import Random8
.import Grow_Maze ; to patch
.export Get_Size_Maze
.export Init_Dimensions_Maze
.export Build_Level
.export Rooms
.export WIDTH_MAZE
.export HEIGHT_MAZE
.define MAX_NB_ROOMS 64 ; MAX_NB_ROOMS *MUST BE* <= 64
.BSS
; Describes a room to be built
; typedef struct {
; uint8_t height;
; uint8_t width;
; uint8_t x;
; uint8_t y;
; } room_t;
.define SIZEOF_ROOM_T 4
.align 256
Rooms: .res SIZEOF_ROOM_T*MAX_NB_ROOMS ; MAX 1 page of data!
WIDTH_MAZE: .res 1
HEIGHT_MAZE: .res 1
.DATA
STR_SIZE_MAZE_1: ASCIIZ "PLEASE ENTER THE SIZE OF THE LEVEL."
STR_SIZE_MAZE_2: ASCIIZ "A:TINY B:SMALL C:NORMAL D:BIG E:HUGE"
STR_SIZE_MAZE_3: ASCIIZ "PLEASE ENTER A VALID CHOICE."
STR_ROOMS: ASCIIZ "CARVING ROOMS..."
STR_MAZE: ASCIIZ "GROWING THE MAZE..."
STR_DOORS: ASCIIZ "OPENING DOORS..."
STR_DEADENDS: ASCIIZ "FILLING DEAD ENDS..."
.CODE
; @brief Asks for the size of the maze
; Returns Width in X and Height in Y
Get_Size_Maze:
; User input
PRINT STR_SIZE_MAZE_1
choice_size_maze:
PRINT STR_SIZE_MAZE_2
jsr Cin_Char
; switch case over the input
tst_tiny:
cmp #$C1
bne tst_small
ldx #16
ldy #16
rts
tst_small:
cmp #$C2
bne tst_medium
ldx #24
ldy #24
rts
tst_medium:
cmp #$C3
bne tst_big
ldx #32
ldy #32
rts
tst_big:
cmp #$C4
bne tst_huge
ldx #48
ldy #48
rts
tst_huge:
cmp #$C5
bne bad_size
ldx #64
ldy #64
rts
bad_size:
PRINT STR_SIZE_MAZE_3
jmp choice_size_maze
; @brief Fills border walls
; @param type of the "wall" in A
; destroys ZERO_2_1, ZERO_2_2
.define ADDR_WORLD ZERO_2_1
.macro WORLD_NEXT_LINE
clc
lda ADDR_WORLD
adc #WIDTH_WORLD
sta ADDR_WORLD
lda ADDR_WORLD+1
adc #0
sta ADDR_WORLD+1
.endmacro
; DO NOT MESS WITH THIS FUNCTION: IT IS PATCHED!!
.define PATCH_WIDTH_MAZE_1 0
.define PATCH_HEIGHT_MAZE_2 0
_build_fences:
ldx #<World
stx ADDR_WORLD
ldx #>World
stx ADDR_WORLD+1
ldy #PATCH_WIDTH_MAZE_1
loop_wall_top:
sta (ADDR_WORLD), Y
dey
bne loop_wall_top
sta (ADDR_WORLD), Y
ldx #PATCH_HEIGHT_MAZE_2
loop_wall_left_right:
pha
WORLD_NEXT_LINE
pla
ldy #PATCH_WIDTH_MAZE_1
sta (ADDR_WORLD), Y
ldy #0
sta (ADDR_WORLD), Y
dex
bne loop_wall_left_right
pha
WORLD_NEXT_LINE
pla
ldy #PATCH_WIDTH_MAZE_1
loop_wall_bottom:
sta (ADDR_WORLD), Y
dey
bne loop_wall_bottom
sta (ADDR_WORLD), Y
rts
.undefine ADDR_WORLD
; @brief Sets the Maze's dimentions
; @param width in X
; @param height in Y
Init_Dimensions_Maze:
stx WIDTH_MAZE
; patch WIDTH_MAZE usage NO MORE PATCH: comment to be removed
dex
stx _build_fences + $9
stx _build_fences + $23
stx _build_fences + $3D
; dex
; dex
; dex
; stx Grow_Maze + $C
; patch HEIGHT_MAZE usage NO MORE PATCH: comment to be removed
sty HEIGHT_MAZE
dey
dey
sty _build_fences + $12
; dey
; dey
; sty Grow_Maze + $19
rts
; @brief Builds a whole level
.define DST_WORLD World
.define ADDR_TO_PATCH init_world_line + 3
.define NB_ROOMS ZERO_8_2
Build_Level:
; Filling World with ACTORS::WALL_1
ldy #HEIGHT_WORLD
init_world:
ldx #0
init_world_line:
lda #ACTORS::WALL_1
sta DST_WORLD, x
inx
cpx #WIDTH_WORLD
bne init_world_line
; patching DST_WORLD
lda ADDR_TO_PATCH
clc
adc #WIDTH_WORLD
sta ADDR_TO_PATCH
lda ADDR_TO_PATCH + 1
adc #0
sta ADDR_TO_PATCH + 1
dey
bne init_world
PRINT STR_ROOMS
lda #MAX_NB_ROOMS+1
jsr Carve_Rooms
sta NB_ROOMS
lda #ACTORS::FLOOR_1
jsr _build_fences
PRINT STR_MAZE
jsr Grow_Maze
lda #ACTORS::WALL_1
jsr _build_fences
PRINT STR_DOORS
.define PERCENT_7 #17
ldx PERCENT_7
lda NB_ROOMS
jsr Connect_Rooms
PRINT STR_DEADENDS
jsr Remove_Dead_Ends
rts

19
src/builder/builder.inc Normal file
View File

@ -0,0 +1,19 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.import Get_Size_Maze
.import Init_Dimensions_Maze
.import Build_Level
.import Rooms

534
src/builder/maze.asm Normal file
View File

@ -0,0 +1,534 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be usefuELEFT,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "../memory.inc"
.include "../world.inc"
.include "../random.inc"
.include "../math.inc"
.export Grow_Maze
.export Remove_Dead_Ends
.import Compute_Maze_Addr
.import World
.import WIDTH_MAZE
.import HEIGHT_MAZE
; using HGR2 space as the stack
; Stack contains pointers to tiles (2 byte long)
.define STACK_ADDR $3FFE ; Will be 2 byte incremented before 1st push
.define FALSE #0
.define TRUE #1
.define Y_TILE ZERO_2_4
.define X_TILE ZERO_2_5
.define PTR_STACK ZERO_4_1 ; 2 bytes
.define PTR_NEW_TILE ZERO_4_3 ; 2 bytes
; increments the stack pointer then pushes address A:X (little endian)
; *ptr_stack = x
; *(ptr_stack+1) = a
; ptr_stack += 2
.macro PUSHAX
pha
; increment stack pointer
clc
lda PTR_STACK
adc #2
sta PTR_STACK
lda PTR_STACK+1
adc #0
sta PTR_STACK+1
; push A:X to the stack
pla
ldy #1
sta (PTR_STACK),Y
dey
txa
sta (PTR_STACK),Y
.endmacro
; ptr_newtile is offseted by -WIDTH_WORLD so we can access all its neighbors
; with positive offsets using Y indirect addressing
.macro PTR_UP_TILE
sec
ldy #0
lda (PTR_STACK),Y
sbc #(2*WIDTH_WORLD)
sta PTR_NEW_TILE
iny
lda (PTR_STACK),Y
sbc #0
sta PTR_NEW_TILE+1
.endmacro
.macro PTR_LEFT_TILE
sec
ldy #0
lda (PTR_STACK),Y
sbc #(WIDTH_WORLD+1)
sta PTR_NEW_TILE
iny
lda (PTR_STACK),Y
sbc #0
sta PTR_NEW_TILE+1
.endmacro
.macro PTR_RIGHT_TILE
sec
ldy #0
lda (PTR_STACK),Y
sbc #(WIDTH_WORLD-1)
sta PTR_NEW_TILE
iny
lda (PTR_STACK),Y
sbc #0
sta PTR_NEW_TILE+1
.endmacro
.macro PTR_DOWN_TILE
ldy #0
lda (PTR_STACK),Y
sta PTR_NEW_TILE
iny
lda (PTR_STACK),Y
sta PTR_NEW_TILE+1
.endmacro
.macro PTR_CURR_TILE
sec
ldy #0
lda (PTR_STACK),Y
sbc #(WIDTH_WORLD)
sta PTR_NEW_TILE
iny
lda (PTR_STACK),Y
sbc #0
sta PTR_NEW_TILE+1
.endmacro
; test if the tile offseted from PTR_NEW_TILE is walkable
.macro ISWALKABLE offset
ldy offset
lda (PTR_NEW_TILE),Y
cmp #ACTORS::WALKABLE+1
bcc cannot_carve
.endmacro
.define OFFSET_NIL #WIDTH_WORLD
.define OFFSET_UP #0
.define OFFSET_RIGHT #(WIDTH_WORLD+1)
.define OFFSET_DOWN #(2*WIDTH_WORLD)
.define OFFSET_LEFT #(WIDTH_WORLD-1)
.macro IS_TILE_WALLED
PTR_CURR_TILE
ldy OFFSET_NIL
lda (PTR_NEW_TILE),Y
cmp #ACTORS::WALKABLE
bcc end_loop_stack
ldy OFFSET_UP
lda (PTR_NEW_TILE),Y
cmp #ACTORS::WALKABLE
bcc end_loop_stack
ldy OFFSET_RIGHT
lda (PTR_NEW_TILE),Y
cmp #ACTORS::WALKABLE
bcc end_loop_stack
ldy OFFSET_DOWN
lda (PTR_NEW_TILE),Y
cmp #ACTORS::WALKABLE
bcc end_loop_stack
ldy OFFSET_LEFT
lda (PTR_NEW_TILE),Y
cmp #ACTORS::WALKABLE
bcc end_loop_stack
.endmacro
; @brief Fills the empty space with a perfect maze
.define PATCH_WIDTH_MAZE_4 0
.define PATCH_HEIGHT_MAZE_4 0
Grow_Maze:
; Groth start location
ldx #2
stx X_TILE
stx Y_TILE
loop_grow_maze:
; init the stack
lda #<STACK_ADDR
sta PTR_STACK
lda #>STACK_ADDR
sta PTR_STACK+1
; Test if the tile is suitable
ldy Y_TILE
ldx X_TILE
jsr Compute_Maze_Addr ; result addr in A:X
; test if the tile is walled
PUSHAX
IS_TILE_WALLED
; carve
ldy #WIDTH_WORLD
lda #ACTORS::FLOOR_1
sta (PTR_NEW_TILE),Y
.define IDX ZERO_2_6
; while the stack is not empty: carve
loop_stack:
jsr _random_directions
tax
stx IDX
loop_find_dir: ; find a direction suitable to carvingm
jsr _can_carve
cmp #1 ; cannot carve -> test other directions
beq carve_the_tile
lda IDX
and #3 ; 4th direction?
cmp #3
beq test_stack
inc IDX
ldx IDX
jmp loop_find_dir
test_stack:
lda PTR_STACK+1
cmp #>(STACK_ADDR+2)
bne unstack
lda PTR_STACK
cmp #<(STACK_ADDR+2)
beq end_loop_stack ; stack is empty -> break
unstack:
sec
lda PTR_STACK
sbc #2
sta PTR_STACK
lda PTR_STACK+1
sbc #0
sta PTR_STACK+1
jmp loop_stack
carve_the_tile:
; carve the tile
ldy #0
lda #ACTORS::FLOOR_1
sta (PTR_NEW_TILE),Y
jmp loop_stack
end_loop_stack:
inc X_TILE
ldx WIDTH_MAZE
dex
dex
cpx X_TILE
beq incr_y_tile
jmp loop_grow_maze
incr_y_tile:
ldx #2
stx X_TILE
inc Y_TILE
ldy HEIGHT_MAZE
dey
cpy Y_TILE
beq end_loop_grow_maze
jmp loop_grow_maze
end_loop_grow_maze:
rts
.enum
EUP = 0
ERIGHT
EDOWN
ELEFT
.endenum
; 24 direction quartets
RandomDirection:
.byte EUP,ERIGHT,EDOWN,ELEFT,EUP,ERIGHT,ELEFT,EDOWN,EUP,EDOWN,ERIGHT,ELEFT,EUP,EDOWN,ELEFT,ERIGHT,EUP,ELEFT,ERIGHT,EDOWN,EUP,ELEFT,EDOWN,ERIGHT
.byte ERIGHT,EUP,EDOWN,ELEFT,ERIGHT,EUP,ELEFT,EDOWN,ERIGHT,EDOWN,EUP,ELEFT,ERIGHT,EDOWN,ELEFT,EUP,ERIGHT,ELEFT,EUP,EDOWN,ERIGHT,ELEFT,EDOWN,EUP
.byte EDOWN,ERIGHT,EUP,ELEFT,EDOWN,ERIGHT,ELEFT,EUP,EDOWN,ELEFT,EUP,ERIGHT,EDOWN,ELEFT,ERIGHT,EUP,EDOWN,EUP,ELEFT,ERIGHT,EDOWN,EUP,ERIGHT,ELEFT
.byte ELEFT,ERIGHT,EDOWN,EUP,ELEFT,ERIGHT,EDOWN,EUP,ELEFT,EDOWN,ERIGHT,EUP,ELEFT,EDOWN,EUP,ERIGHT,ELEFT,EUP,ERIGHT,EDOWN,ELEFT,EUP,EDOWN,ERIGHT
; Uses a precomputed table to quickly return an offset to one of the direction quartets
_random_directions:
jsr Random8
and #31
ldx #24
jsr Modulus
asl
asl ; offset to a direction quartet
rts
; @brief Returns A=1 if the tile can be carved, A=0 otherwise.
; some difficulties for the branches to be in range to end_can_carve.
; thus the jsr and jmp and the breakdown of the routine
_can_carve:
lda RandomDirection,X
can_carve_up:
cmp #EUP
bne can_carve_right
jmp _can_carve_up
can_carve_right:
cmp #ERIGHT
bne can_carve_down
jmp _can_carve_right
can_carve_down:
cmp #EDOWN
bne can_carve_left
PTR_DOWN_TILE ; ptr_newtile = down - width_world
ISWALKABLE OFFSET_NIL ; the new tile
ISWALKABLE OFFSET_RIGHT ; new tile's right neighbor
ISWALKABLE OFFSET_DOWN ; new tile's bottom neighbor
ISWALKABLE OFFSET_LEFT ; new tile's left neighbor
jmp _save_ptr_newtile
can_carve_left:
cmp #ELEFT
bne end_can_carve
PTR_LEFT_TILE ; ptr_newtile = left - width_world
ISWALKABLE OFFSET_NIL ; the new tile
ISWALKABLE OFFSET_UP ; new tile's upper neighbor
ISWALKABLE OFFSET_DOWN ; new tile's bottom neighbor
ISWALKABLE OFFSET_LEFT ; new tile's left neighbor
jmp _save_ptr_newtile
cannot_carve:
lda #0
end_can_carve:
rts
_can_carve_up:
PTR_UP_TILE ; ptr_newtile = up - width_world
ISWALKABLE OFFSET_NIL ; the new tile
ISWALKABLE OFFSET_UP ; new tile's upper neighbor
ISWALKABLE OFFSET_RIGHT ; new tile's right neighbor
ISWALKABLE OFFSET_LEFT ; new tile's left neighbor
jmp _save_ptr_newtile
_can_carve_right:
PTR_RIGHT_TILE ; ptr_newtile = rigth - width_world
ISWALKABLE OFFSET_NIL ; the new tile
ISWALKABLE OFFSET_RIGHT ; new tile's right neighbor
ISWALKABLE OFFSET_DOWN ; new tile's bottom neighbor
ISWALKABLE OFFSET_UP ; new tile's upper neighbor
; jmp _save_ptr_newtile
; save new tile on the stack
_save_ptr_newtile:
clc
lda PTR_NEW_TILE
adc #WIDTH_WORLD
sta PTR_NEW_TILE
tax
lda PTR_NEW_TILE+1
adc #0
sta PTR_NEW_TILE+1
PUSHAX
;CREUSER???
lda #1
jmp end_can_carve
.undefine Y_TILE
.undefine X_TILE
.undefine PTR_STACK
.undefine PTR_NEW_TILE
.define PTR_TILE ZERO_2_1 ; 2 bytes
.define PTR_NEXT_TILE ZERO_2_3 ; 2 bytes
.define NB_WALLS ZERO_2_5
.define ADDR_END ZERO_4_1 ; 2 bytes
.define HEIGHTxWIDTH WIDTH_WORLD*HEIGHT_WORLD
; @brief Removes all the dead ends
Remove_Dead_Ends:
; Compute addr_end as the preprocessor cannot handle 16bit multiplications (???)
lda #WIDTH_WORLD
sta FAC1
lda #HEIGHT_WORLD
sta FAC2
jsr mul8
sta ADDR_END+1
stx ADDR_END
lda #<World
clc
adc ADDR_END
sta ADDR_END
lda #>World
adc ADDR_END+1
sta ADDR_END+1
; starting tile: offsetted by - width_world
lda #<(World + 1) ; &World[1][1] - width_world
sta PTR_TILE
lda #>(World + 1)
sta PTR_TILE+1
loop_tiles:
jsr _is_tile_dead_end
lda NB_WALLS
cmp #3
bcc next_tile
jsr _follow_dead_end
next_tile:
clc
lda PTR_TILE
adc #1
sta PTR_TILE
lda PTR_TILE+1
adc #0
sta PTR_TILE+1
; end?
lda PTR_TILE+1
cmp ADDR_END+1
bne loop_tiles
lda PTR_TILE
cmp ADDR_END
bne loop_tiles
end_loop_tiles:
rts
.undefine ADDR_END
_follow_dead_end:
; saving ptr_tile
lda PTR_TILE
pha
lda PTR_TILE+1
pha
loop_follow:
ldy #WIDTH_WORLD
lda #ACTORS::WALL_1
sta (PTR_TILE), Y
lda PTR_NEXT_TILE
sta PTR_TILE
lda PTR_NEXT_TILE+1
sta PTR_TILE+1
jsr _is_tile_dead_end
lda NB_WALLS
cmp #3
bcs loop_follow
end_loop_follow:
; restoring ptr_tile
pla
sta PTR_TILE+1
pla
sta PTR_TILE
rts
.define ADD_FACTOR ZERO_4_1
; REM: PTR_TILE is already offsetted by -WIDTH_WORLD
; for easy access to adjacent tiles by indirect indexing
; Returns : NB_WALLS >= 3 if it is a dead end
_is_tile_dead_end:
lda #0
sta NB_WALLS
ldy #WIDTH_WORLD
sty ADD_FACTOR
; Returns if the tile is a wall
lda #ACTORS::WALKABLE
cmp (PTR_TILE), Y
bcc end_tst_up_tile
tst_up_tile:
ldy #0
cmp (PTR_TILE), Y
bcc up_non_walkable
sty ADD_FACTOR
bcs tst_right_tile
up_non_walkable:
inc NB_WALLS
tst_right_tile:
ldy #(WIDTH_WORLD + 1)
cmp (PTR_TILE), Y
bcc right_non_walkable
sty ADD_FACTOR
bcs tst_down_tile
right_non_walkable:
inc NB_WALLS
tst_down_tile:
ldy #(2*WIDTH_WORLD)
cmp (PTR_TILE), Y
bcc down_non_walkable
sty ADD_FACTOR
bcs tst_left_tile
down_non_walkable:
inc NB_WALLS
tst_left_tile:
ldy #(WIDTH_WORLD - 1)
cmp (PTR_TILE), Y
bcc left_non_walkable
sty ADD_FACTOR
bcs end_tests
left_non_walkable:
inc NB_WALLS
end_tests:
; computing ptr_next_tile
clc
lda PTR_TILE
adc ADD_FACTOR
sta PTR_NEXT_TILE
lda PTR_TILE+1
adc #0
sta PTR_NEXT_TILE+1
; offseting ptr_next_tile
sec
lda PTR_NEXT_TILE
sbc #WIDTH_WORLD
sta PTR_NEXT_TILE
lda PTR_NEXT_TILE+1
sbc #0
sta PTR_NEXT_TILE+1
end_tst_up_tile:
rts

2
src/builder/maze.inc Normal file
View File

@ -0,0 +1,2 @@
.import Grow_Maze
.import Remove_Dead_Ends

664
src/builder/rooms.asm Normal file
View File

@ -0,0 +1,664 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "../memory.inc"
.include "../random.inc"
.include "../world.inc"
.include "../math.inc"
.export Carve_Rooms
.export Connect_Rooms
.import Rooms
.import Compute_Maze_Addr
.import World
.import WIDTH_MAZE
.import HEIGHT_MAZE
.define TRUE #1
.define FALSE #0
.BSS
; Configration to build rooms
.struct Config_Room
width_min .byte
width_max .byte
height_min .byte
height_max .byte
.endstruct
.CODE
.define NB_ATTEMPTS ZERO_2_1
.define NB_ROOMS_OK ZERO_2_2
.define NB_ROOMS_TO_DRAW NB_ATTEMPTS
.define IDX_ROOMS ZERO_3
; @params A nb_attempts
; @returns NB_ROOMS_OK in A
Carve_Rooms:
sta NB_ATTEMPTS
; height_max + width_max shall be < 64
lda #9
sta Config_Room::height_max
lda #3
sta Config_Room::height_min
lda #11
sta Config_Room::width_max
lda #3
sta Config_Room::width_min
ldx #0
stx NB_ROOMS_OK
loop_rooms:
dec NB_ATTEMPTS
beq end_loop_rooms
lda NB_ROOMS_OK ; NB_ROOMS_OK*sizeof(room_t) -> X
asl
asl
tax
jsr _Build_Room
lda NB_ROOMS_OK
jsr _Is_intersecting
cmp TRUE ; not intersecting with another room?
beq loop_rooms
inc NB_ROOMS_OK
clc
bcc loop_rooms
end_loop_rooms:
lda NB_ROOMS_OK
sta NB_ROOMS_TO_DRAW
ldx #0
loop_draw_rooms:
jsr _Draw_Room
inx
inx
inx
inx
dec NB_ROOMS_TO_DRAW
bne loop_draw_rooms
end_loop_draw_rooms:
lda NB_ROOMS_OK
rts
.undefine NB_ATTEMPTS
.undefine NB_ROOMS_OK
.undefine NB_ROOMS_TO_DRAW
.undefine IDX_ROOMS
.define ADDR_WORLD ZERO_2_3 ; 2 bytes
.define NB_LINE ZERO_2_5
.define LINE_LENGTH ZERO_2_6
.define IDX_ROOMS ZERO_3
_Draw_Room:
stx IDX_ROOMS
ldy Rooms+3, X ; room->y
lda Rooms+2, X ; rooms->x
tax
PUSH ZERO_2_1
PUSH ZERO_2_2
jsr Compute_Maze_Addr
stx ADDR_WORLD
sta ADDR_WORLD+1
POP ZERO_2_2
POP ZERO_2_1
ldx IDX_ROOMS
ldy Rooms, X ; room->height
sty NB_LINE
lda Rooms+1, X ; room->width
sta LINE_LENGTH
loop_draw_line:
lda #ACTORS::FLOOR_1
ldy #0
loop_draw_tile:
sta (ADDR_WORLD), Y
iny
cpy LINE_LENGTH
bne loop_draw_tile
end_loop_draw_tile:
clc
lda ADDR_WORLD
adc #WIDTH_WORLD
sta ADDR_WORLD
lda ADDR_WORLD+1
adc #0
sta ADDR_WORLD+1
dec NB_LINE
bne loop_draw_line
end_loop_draw_line:
ldx IDX_ROOMS
rts
.undefine ADDR_WORLD
.undefine NB_LINE
.undefine LINE_LENGTH
.undefine IDX_ROOMS
.define MODULUS ZERO_2_3
.define WIDTH_ROOM ZERO_2_5
.define HEIGHT_ROOM ZERO_2_6
.define OFFSET_ROOMS ZERO_5_1
; @param X offset to the room to be built from Rooms
; @return offset room in X
_Build_Room:
stx OFFSET_ROOMS
; room.height = config->height_min + Random8() % (config->height_max - config->height_min - 1);
sec
lda Config_Room::height_max
sbc Config_Room::height_min
sbc #1
sta MODULUS
jsr Random8
and #7
ldx MODULUS
jsr Modulus
ldx OFFSET_ROOMS
clc
adc Config_Room::height_min
ora #1
sta Rooms, x ; height
sta HEIGHT_ROOM
inx
stx OFFSET_ROOMS
; room.width = config->width_min + Random8() % (config->width_max - config->width_min - 1);
sec
lda Config_Room::width_max
sbc Config_Room::width_min
sbc #1
sta MODULUS
jsr Random8
and #$F ; room's height shall be < 16
ldx MODULUS
jsr Modulus
ldx OFFSET_ROOMS
clc
adc Config_Room::width_min
ora #1
sta Rooms, x ; width
sta WIDTH_ROOM
inx
stx OFFSET_ROOMS
; room.x = 3 + Random8() % (WIDTH_MAZE - room.width - 5);
sec
lda WIDTH_MAZE
sbc WIDTH_ROOM
sbc #5
sta MODULUS
jsr Random8
and #$7F
ldx MODULUS
jsr Modulus
ldx OFFSET_ROOMS
clc
adc #3
ora #1
sta Rooms, x ; x
inx
stx OFFSET_ROOMS
; room.y = 3 + Random8() % (HEIGHT_MAZE - room.height - 5);
sec
lda HEIGHT_MAZE
sbc HEIGHT_ROOM
sbc #5
sta MODULUS
jsr Random8
and #$7F
ldx MODULUS
jsr Modulus
ldx OFFSET_ROOMS
clc
adc #3
ora #1
sta Rooms, x ; y
inx
stx OFFSET_ROOMS
rts
.undefine MODULUS
.undefine WIDTH_ROOM
.undefine HEIGHT_ROOM
.undefine OFFSET_ROOMS
; @brief test ifthe room is intersecting with other rooms
; @param A : nb rooms already carved
; @return 0 if no intersection, 1 otherwise
.define NB_ROOMS ZERO_3
.define OFFSET_Y ZERO_2_4
.define OFFSET_X ZERO_2_5
_Is_intersecting:
cmp #0
bne compare
; first room
lda FALSE
clc
bcc end_intersecting ; branch always
; previous rooms were carved
compare:
sta NB_ROOMS
asl ; * sizeof(room_t) to get offset to the last room randomized
asl
tax ; offset to new room in X
stx OFFSET_X
ldy #0 ; offset to carved rooms in Y
loop_intersecting: ; each test must be true
sty OFFSET_Y
clc
lda Rooms+2, Y ; room->x
adc Rooms+1, Y ; room->width
cmp Rooms+2, X
bcc false ; branch if room->x + room->width < new_room->x
clc
lda Rooms+2, X ; new_room->x
adc Rooms+1, X ; new_room->width
cmp Rooms+2, Y ; room->x
bcc false ; branch if new_room->x + new_room->width < room->x
clc
lda Rooms+3, Y ; room->y
adc Rooms, Y ; room->height
cmp Rooms+3, X ; new_room->y
bcc false ; branch if room->y + room->height < new_room->y
clc
lda Rooms+3, X ; new_room->y
adc Rooms, X ; new_room->height
cmp Rooms+3, Y ; room->y
bcc false ; branch if new_room->y + new_room->height < room->y
; all test are true: rooms are intersecting
lda TRUE ; return value
clc
bcc end_intersecting
false:
ldx OFFSET_X
lda OFFSET_Y
adc #4
tay
dec NB_ROOMS
bne loop_intersecting
lda FALSE ; no room intersects
end_intersecting:
rts
; using HGR2 space as the stack
; Stack contains pointers to the tiles encompassing a room (except the corners)
.define STACK_ADDR $4000
.define PTR_TILE_TOP ZERO_2_3 ; 2 bytes
.define PTR_TILE_BOT ZERO_4_4 ; 2 bytes
.define PTR_TILE_LEFT ZERO_2_3 ; 2 bytes
.define PTR_TILE_RIGHT ZERO_4_4 ; 2 bytes
.define PTR_TILE ZERO_2_1
.define PTR_STACK ZERO_4_1 ; 2 bytes
.define PROBABILITY_OPENING ZERO_4_3
.define NB_DOORS ZERO_5_1
.define NB_WALKABLE ZERO_5_2
.define SIZE_STACK ZERO_5_3 ; 2 bytes
.define WIDTH_ROOM ZERO_2_5
.define HEIGHT_ROOM ZERO_2_6
.define OFFSET_ROOMS ZERO_5_5
; @brief Connects the rooms to the maze's galleries
; @param A number of rooms
; @param X probability to make an opening in a wall tile
; @detail One opening is made, then all remaning encompassing wall tiles
; can be opened. Depending on the provided probability
Connect_Rooms:
sta NB_ROOMS
stx PROBABILITY_OPENING
lda #0
sta OFFSET_ROOMS
; for each room
loop_connect_rooms:
; # Build a stack of encompassing tiles. Except corners
lda #<STACK_ADDR
sta PTR_STACK
lda #>STACK_ADDR
sta PTR_STACK+1
; ## stacking horizontal walls
; ### init ptr_top
ldx OFFSET_ROOMS
inx
inx
lda Rooms, X ; room->x
sta PTR_TILE_TOP
clc
lda #<World
adc PTR_TILE_TOP
sta PTR_TILE_TOP
lda #>World
adc #0
sta PTR_TILE_TOP+1
inx
lda Rooms, X ; room->y
tax
dex
stx FAC1
lda #WIDTH_WORLD
sta FAC2
jsr mul8
tay
txa
clc
adc PTR_TILE_TOP
sta PTR_TILE_TOP
tya
adc PTR_TILE_TOP+1
sta PTR_TILE_TOP+1
; ### init ptr_bottom
ldx OFFSET_ROOMS
lda Rooms, X ; room->height
sta HEIGHT_ROOM
tax
inx
stx FAC1
lda #WIDTH_WORLD
sta FAC2
jsr mul8
tay
txa
clc
adc PTR_TILE_TOP
sta PTR_TILE_BOT
tya
adc PTR_TILE_TOP+1
sta PTR_TILE_BOT+1
; ## stacking
ldx OFFSET_ROOMS
inx
lda Rooms, X ; room->width
sta WIDTH_ROOM
; for x = 0; x < room->width; x++
ldx #0
loop_stack_horiz:
ldy #0
clc
txa
adc PTR_TILE_TOP
sta (PTR_STACK), Y
iny
lda #0
adc PTR_TILE_TOP+1
sta (PTR_STACK), Y
iny
txa
adc PTR_TILE_BOT
sta (PTR_STACK), Y
iny
lda #0
adc PTR_TILE_BOT+1
sta (PTR_STACK), Y
iny
; incr ptr_stack
tya
clc
adc PTR_STACK
sta PTR_STACK
lda #0
adc PTR_STACK+1
sta PTR_STACK+1
; next x
inx
cpx WIDTH_ROOM
bne loop_stack_horiz
; ## stacking vertical walls
; ### init ptr_left
clc
lda #(WIDTH_WORLD-1)
adc PTR_TILE_TOP
sta PTR_TILE_LEFT
lda #0
adc PTR_TILE_TOP+1
sta PTR_TILE_LEFT+1
; ### init ptr_right
clc
lda WIDTH_ROOM
adc #1
adc PTR_TILE_LEFT
sta PTR_TILE_RIGHT
lda #0
adc PTR_TILE_LEFT+1
sta PTR_TILE_RIGHT+1
; ### stacking
; for y = 0; y < room->height; y++
ldx #0
loop_stack_vertical:
ldy #1
lda PTR_TILE_LEFT+1
sta (PTR_STACK), Y
dey
lda PTR_TILE_LEFT
sta (PTR_STACK), Y
clc
adc #WIDTH_WORLD
sta PTR_TILE_LEFT
lda PTR_TILE_LEFT+1
adc #0
sta PTR_TILE_LEFT+1
iny
iny
iny
lda PTR_TILE_RIGHT+1
sta (PTR_STACK), Y
dey
lda PTR_TILE_RIGHT
sta (PTR_STACK), Y
clc
adc #WIDTH_WORLD
sta PTR_TILE_RIGHT
lda PTR_TILE_RIGHT+1
adc #0
sta PTR_TILE_RIGHT+1
; incr ptr_stack
clc
lda #4
adc PTR_STACK
sta PTR_STACK
lda #0
adc PTR_STACK+1
sta PTR_STACK+1
; next y
inx
cpx HEIGHT_ROOM
bne loop_stack_vertical
; ## Compute stack's size
; UTILISER DIRECTEMENT L ADRESSE DE FIN ET BREAKER QUAND ON L ATTEINT
sec
lda PTR_STACK
sbc #<STACK_ADDR
pha
lda PTR_STACK+1
sbc #>STACK_ADDR
lsr
sta SIZE_STACK+1
pla
ror
sta SIZE_STACK
; # Opening the first door
lda #0
sta NB_DOORS
lda #<STACK_ADDR
sta PTR_STACK ; here stack size < 128, no need for hsb of the address
loop_first_door:
jsr Random8
ldx SIZE_STACK
jsr Modulus
asl
tay
lda (PTR_STACK), Y
;PTR_TILE = *PTR_STACK - WIDTH_WORLD
sec
sbc #WIDTH_WORLD
sta PTR_TILE
iny
lda (PTR_STACK), Y
sbc #0
sta PTR_TILE+1
jsr _nb_walkable
lda NB_WALKABLE
cmp #2
bcc loop_first_door ; nb_walkable < 2
inc NB_DOORS
ldy #WIDTH_WORLD
lda #ACTORS::FLOOR_1
sta (PTR_TILE), Y
; # Opening the other doors
.define IDX ZERO_2_3
lda #<STACK_ADDR
sta PTR_STACK ; here stack size < 128, no need for hsb of the address
lda #$FF
sta IDX
loop_other_doors:
inc IDX
; test if end
lda SIZE_STACK
asl
cmp IDX
beq end_loop_other_doors
; random number to be compare to the probability of a door
jsr Random8
cmp PROBABILITY_OPENING
bcc test_door
beq test_door
inc IDX
bcs loop_other_doors ; always jump as the previous bcc failed
; test if the tile can be linked to the maze
test_door:
ldy IDX
lda (PTR_STACK), Y
;PTR_TILE = *PTR_STACK - WIDTH_WORLD
sec
sbc #WIDTH_WORLD
sta PTR_TILE
iny
lda (PTR_STACK), Y
sbc #0
sta PTR_TILE+1
sty IDX
jsr _nb_walkable
lda NB_WALKABLE
cmp #2
bcs carve_a_door
bcc loop_other_doors ; always jump as the previous bcs failed
carve_a_door:
ldy #WIDTH_WORLD
lda #ACTORS::FLOOR_1
sta (PTR_TILE), Y
inc NB_DOORS
jmp loop_other_doors
end_loop_other_doors:
dec NB_ROOMS
beq end_loop_connect_rooms
; next room
lda OFFSET_ROOMS
clc
adc #.sizeof(Config_Room)
sta OFFSET_ROOMS
jmp loop_connect_rooms
end_loop_connect_rooms:
rts
; @brief returns the number of walkable neighbours. >= 2 if it can be carved
; @detailed PTR_TILE is offsetted by -WIDTH_WORLD
_nb_walkable:
lda #0
sta NB_WALKABLE
lda #ACTORS::FLOOR_1
tst_up:
ldy #0
cmp (PTR_TILE), Y
bne tst_left
inc NB_WALKABLE
tst_left:
ldy #(WIDTH_WORLD-1)
cmp (PTR_TILE), Y
bne tst_right
inc NB_WALKABLE
tst_right:
ldy #(WIDTH_WORLD+1)
cmp (PTR_TILE), Y
bne tst_down
inc NB_WALKABLE
tst_down:
ldy #(2*WIDTH_WORLD)
cmp (PTR_TILE), Y
bne end_is_door_possible
inc NB_WALKABLE
end_is_door_possible:
rts
.undefine STACK_ADDR
.undefine PTR_TILE_TOP
.undefine PTR_TILE_BOT
.undefine PTR_TILE_LEFT
.undefine PTR_TILE_RIGHT
.undefine PTR_TILE
.undefine PTR_STACK
.undefine PROBABILITY_OPENING
.undefine NB_DOORS
.undefine NB_WALKABLE
.undefine SIZE_STACK
.undefine WIDTH_ROOM
.undefine HEIGHT_ROOM
.undefine OFFSET_ROOMS

18
src/builder/rooms.inc Normal file
View File

@ -0,0 +1,18 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.import Carve_Rooms
.import Connect_Rooms

View File

@ -1,8 +1,11 @@
.include "memory.inc"
; nb of bytes to be displayed in DBG_TRACES[0]
.export DBG_TRACE
; bytes to be displayed
.export DBG_TRACES
.CODE
.define STROUT $DB3A ; Applesoft: OUTPUTS AY-POINTED NULL TERMINATED STRING
.define LINPTR $ED24 ; Applesoft: Displays the number A(high)X(low) in decimal
@ -39,3 +42,6 @@ str_space: .byte " ", 0
.BSS
DBG_TRACES: .res 7 ; bytes to be displayed by TRACE

View File

@ -42,7 +42,7 @@
; X: TILE_COORD_X
; Y: TILE_COORD_Y
.import compute_maze_addr
.import Compute_Maze_Addr
.import World
.import Player_XY
@ -97,6 +97,21 @@ loop_view_init:
rts
; this routines populates View_Future, without any LOS
_dbg_build_view:
lda #0
ldx #(GRID_WIDTH * GRID_HEIGHT - 1)
loop_build_view:
lda #ACTORS::PLAYER
sta View_Future,X
dex
bne loop_build_view
sta View_Future,X
rts
; this routine will create the view and populate View_Future
; destroys ZERO_4_3, ZERO_4_4, ZERO_5_1, ZERO_5_2, ZERO_5_3
; ZERO_5_4, ZERO_5_5, ZERO_5_6, ZERO_7_1, ZERO_7_2
@ -119,7 +134,7 @@ _build_view:
sta View_Future,X
; 3 - Casting rays
.define NB_RAYS 36
.define NB_RAYS 68
.define NB_ITER ZERO_4_3
.define NB_TILES_IN_RAY ZERO_4_4
.define NB_TILES_IN_RAY_LEFT ZERO_5_1
@ -249,6 +264,7 @@ view_refresh:
; 3 - build the view to be displayed
jsr _build_view
;jsr _dbg_build_view
; 4 - display the tiles viewed
.define SAVE_X ZERO_3
@ -282,7 +298,7 @@ loop_display_tiles_y:
rts
.undef VIEW_WORLD
SHIFT_VIEW: .word WIDTH_MAZE*PLAYER_Y + PLAYER_X ; shift to center the view on the player
SHIFT_VIEW: .word WIDTH_WORLD*PLAYER_Y + PLAYER_X ; shift to center the view on the player
.CODE
set_view_coords:
@ -290,7 +306,7 @@ set_view_coords:
; 1. Compute offset from the starting address of the maze
stx ZERO_2_1
sty FAC1
lda #WIDTH_MAZE
lda #WIDTH_WORLD
sta FAC2
jsr mul8
tay ; high part
@ -437,7 +453,7 @@ PATCH_8:
.DATA
.RODATA
; Adress of the tiles in the HIRES screen
; T0 T1 T2
@ -454,45 +470,77 @@ HGR_GRID:
.word $2050, $2054, $2058, $205C, $2060, $2064, $2068, $206C, $2070, $2074
.word $2150, $2154, $2158, $215C, $2160, $2164, $2168, $216C, $2170, $2174
; Nb rays: 36
; Nb rays: 68
; A ray: length (nb_tiles), offset_from_view_in_world_low, offset_from_view_in_world_high, offset_view
Rays:
.byte 5, 4, 1, 44, 195, 0, 33, 130, 0, 22, 65, 0, 11, 0, 0, 0
.byte 5, 4, 1, 44, 195, 0, 33, 131, 0, 23, 66, 0, 12, 1, 0, 1
.byte 5, 4, 1, 44, 196, 0, 34, 131, 0, 23, 67, 0, 13, 2, 0, 2
.byte 5, 5, 1, 45, 196, 0, 34, 132, 0, 24, 67, 0, 13, 3, 0, 3
.byte 5, 5, 1, 45, 197, 0, 35, 132, 0, 24, 68, 0, 14, 4, 0, 4
.byte 10, 68, 1, 54, 4, 1, 44, 3, 1, 43, 195, 0, 33, 194, 0, 32, 130, 0, 22, 129, 0, 21, 65, 0, 11, 64, 0, 10, 0, 0, 0
.byte 10, 5, 1, 45, 4, 1, 44, 196, 0, 34, 195, 0, 33, 131, 0, 23, 130, 0, 22, 66, 0, 12, 65, 0, 11, 1, 0, 1, 0, 0, 0
.byte 9, 68, 1, 54, 4, 1, 44, 3, 1, 43, 195, 0, 33, 131, 0, 23, 130, 0, 22, 66, 0, 12, 65, 0, 11, 1, 0, 1
.byte 9, 5, 1, 45, 4, 1, 44, 196, 0, 34, 195, 0, 33, 131, 0, 23, 67, 0, 13, 66, 0, 12, 2, 0, 2, 1, 0, 1
.byte 8, 68, 1, 54, 4, 1, 44, 196, 0, 34, 195, 0, 33, 131, 0, 23, 67, 0, 13, 66, 0, 12, 2, 0, 2
.byte 8, 5, 1, 45, 4, 1, 44, 196, 0, 34, 132, 0, 24, 131, 0, 23, 67, 0, 13, 3, 0, 3, 2, 0, 2
.byte 7, 5, 1, 45, 4, 1, 44, 196, 0, 34, 132, 0, 24, 131, 0, 23, 67, 0, 13, 3, 0, 3
.byte 7, 5, 1, 45, 197, 0, 35, 196, 0, 34, 132, 0, 24, 68, 0, 14, 67, 0, 13, 3, 0, 3
.byte 6, 5, 1, 45, 197, 0, 35, 196, 0, 34, 132, 0, 24, 68, 0, 14, 4, 0, 4
.byte 6, 5, 1, 45, 197, 0, 35, 133, 0, 25, 132, 0, 24, 68, 0, 14, 4, 0, 4
.byte 5, 5, 1, 45, 197, 0, 35, 133, 0, 25, 69, 0, 15, 5, 0, 5
.byte 5, 5, 1, 45, 197, 0, 35, 134, 0, 26, 70, 0, 16, 6, 0, 6
.byte 5, 5, 1, 45, 198, 0, 36, 134, 0, 26, 71, 0, 17, 7, 0, 7
.byte 5, 6, 1, 46, 198, 0, 36, 135, 0, 27, 71, 0, 17, 8, 0, 8
.byte 5, 6, 1, 46, 199, 0, 37, 135, 0, 27, 72, 0, 18, 9, 0, 9
.byte 4, 6, 1, 46, 199, 0, 37, 136, 0, 28, 73, 0, 19
.byte 4, 6, 1, 46, 199, 0, 37, 200, 0, 38, 137, 0, 29
.byte 4, 6, 1, 46, 7, 1, 47, 200, 0, 38, 201, 0, 39
.byte 4, 70, 1, 56, 7, 1, 47, 8, 1, 48, 9, 1, 49
.byte 6, 5, 1, 45, 197, 0, 35, 198, 0, 36, 134, 0, 26, 70, 0, 16, 6, 0, 6
.byte 6, 5, 1, 45, 197, 0, 35, 133, 0, 25, 134, 0, 26, 70, 0, 16, 6, 0, 6
.byte 7, 5, 1, 45, 6, 1, 46, 198, 0, 36, 134, 0, 26, 135, 0, 27, 71, 0, 17, 7, 0, 7
.byte 7, 5, 1, 45, 197, 0, 35, 198, 0, 36, 134, 0, 26, 70, 0, 16, 71, 0, 17, 7, 0, 7
.byte 8, 70, 1, 56, 6, 1, 46, 198, 0, 36, 199, 0, 37, 135, 0, 27, 71, 0, 17, 72, 0, 18, 8, 0, 8
.byte 8, 5, 1, 45, 6, 1, 46, 198, 0, 36, 134, 0, 26, 135, 0, 27, 71, 0, 17, 7, 0, 7, 8, 0, 8
.byte 9, 70, 1, 56, 6, 1, 46, 7, 1, 47, 199, 0, 37, 135, 0, 27, 136, 0, 28, 72, 0, 18, 73, 0, 19, 9, 0, 9
.byte 9, 5, 1, 45, 6, 1, 46, 198, 0, 36, 199, 0, 37, 135, 0, 27, 71, 0, 17, 72, 0, 18, 8, 0, 8, 9, 0, 9
.byte 8, 70, 1, 56, 6, 1, 46, 7, 1, 47, 199, 0, 37, 200, 0, 38, 136, 0, 28, 137, 0, 29, 73, 0, 19
.byte 8, 5, 1, 45, 6, 1, 46, 198, 0, 36, 199, 0, 37, 135, 0, 27, 136, 0, 28, 72, 0, 18, 73, 0, 19
.byte 7, 70, 1, 56, 6, 1, 46, 7, 1, 47, 199, 0, 37, 200, 0, 38, 201, 0, 39, 137, 0, 29
.byte 7, 5, 1, 45, 6, 1, 46, 198, 0, 36, 199, 0, 37, 200, 0, 38, 136, 0, 28, 137, 0, 29
.byte 6, 70, 1, 56, 6, 1, 46, 7, 1, 47, 8, 1, 48, 200, 0, 38, 201, 0, 39
.byte 6, 5, 1, 45, 6, 1, 46, 7, 1, 47, 199, 0, 37, 200, 0, 38, 201, 0, 39
.byte 5, 70, 1, 56, 71, 1, 57, 7, 1, 47, 8, 1, 48, 9, 1, 49
.byte 5, 70, 1, 56, 6, 1, 46, 7, 1, 47, 8, 1, 48, 9, 1, 49
.byte 4, 70, 1, 56, 71, 1, 57, 72, 1, 58, 73, 1, 59
.byte 4, 70, 1, 56, 135, 1, 67, 136, 1, 68, 137, 1, 69
.byte 4, 134, 1, 66, 135, 1, 67, 200, 1, 78, 201, 1, 79
.byte 4, 134, 1, 66, 199, 1, 77, 200, 1, 78, 9, 2, 89
.byte 4, 134, 1, 66, 199, 1, 77, 8, 2, 88, 73, 2, 99
.byte 4, 134, 1, 66, 199, 1, 77, 7, 2, 87, 72, 2, 98
.byte 4, 134, 1, 66, 198, 1, 76, 7, 2, 87, 71, 2, 97
.byte 4, 133, 1, 65, 198, 1, 76, 6, 2, 86, 70, 2, 96
.byte 5, 70, 1, 56, 71, 1, 57, 135, 1, 67, 136, 1, 68, 137, 1, 69
.byte 5, 70, 1, 56, 134, 1, 66, 135, 1, 67, 136, 1, 68, 137, 1, 69
.byte 6, 70, 1, 56, 134, 1, 66, 135, 1, 67, 136, 1, 68, 200, 1, 78, 201, 1, 79
.byte 6, 133, 1, 65, 134, 1, 66, 135, 1, 67, 199, 1, 77, 200, 1, 78, 201, 1, 79
.byte 7, 70, 1, 56, 134, 1, 66, 135, 1, 67, 199, 1, 77, 200, 1, 78, 201, 1, 79, 9, 2, 89
.byte 7, 133, 1, 65, 134, 1, 66, 198, 1, 76, 199, 1, 77, 200, 1, 78, 8, 2, 88, 9, 2, 89
.byte 8, 70, 1, 56, 134, 1, 66, 135, 1, 67, 199, 1, 77, 200, 1, 78, 8, 2, 88, 9, 2, 89, 73, 2, 99
.byte 8, 133, 1, 65, 134, 1, 66, 198, 1, 76, 199, 1, 77, 7, 2, 87, 8, 2, 88, 72, 2, 98, 73, 2, 99
.byte 7, 70, 1, 56, 134, 1, 66, 135, 1, 67, 199, 1, 77, 7, 2, 87, 8, 2, 88, 72, 2, 98
.byte 7, 133, 1, 65, 134, 1, 66, 198, 1, 76, 199, 1, 77, 7, 2, 87, 71, 2, 97, 72, 2, 98
.byte 6, 70, 1, 56, 134, 1, 66, 198, 1, 76, 199, 1, 77, 7, 2, 87, 71, 2, 97
.byte 6, 133, 1, 65, 134, 1, 66, 198, 1, 76, 6, 2, 86, 7, 2, 87, 71, 2, 97
.byte 5, 133, 1, 65, 134, 1, 66, 198, 1, 76, 6, 2, 86, 70, 2, 96
.byte 5, 133, 1, 65, 197, 1, 75, 198, 1, 76, 6, 2, 86, 70, 2, 96
.byte 4, 133, 1, 65, 197, 1, 75, 5, 2, 85, 69, 2, 95
.byte 4, 133, 1, 65, 196, 1, 74, 4, 2, 84, 68, 2, 94
.byte 4, 132, 1, 64, 196, 1, 74, 3, 2, 83, 67, 2, 93
.byte 4, 132, 1, 64, 195, 1, 73, 3, 2, 83, 66, 2, 92
.byte 4, 132, 1, 64, 195, 1, 73, 2, 2, 82, 65, 2, 91
.byte 5, 132, 1, 64, 195, 1, 73, 194, 1, 72, 1, 2, 81, 64, 2, 90
.byte 5, 132, 1, 64, 131, 1, 63, 194, 1, 72, 193, 1, 71, 0, 2, 80
.byte 5, 68, 1, 54, 131, 1, 63, 130, 1, 62, 193, 1, 71, 192, 1, 70
.byte 5, 68, 1, 54, 67, 1, 53, 130, 1, 62, 129, 1, 61, 128, 1, 60
.byte 5, 133, 1, 65, 132, 1, 64, 196, 1, 74, 4, 2, 84, 68, 2, 94
.byte 5, 133, 1, 65, 197, 1, 75, 196, 1, 74, 4, 2, 84, 68, 2, 94
.byte 6, 68, 1, 54, 132, 1, 64, 196, 1, 74, 195, 1, 73, 3, 2, 83, 67, 2, 93
.byte 6, 133, 1, 65, 132, 1, 64, 196, 1, 74, 4, 2, 84, 3, 2, 83, 67, 2, 93
.byte 7, 68, 1, 54, 132, 1, 64, 131, 1, 63, 195, 1, 73, 3, 2, 83, 2, 2, 82, 66, 2, 92
.byte 7, 133, 1, 65, 132, 1, 64, 196, 1, 74, 195, 1, 73, 3, 2, 83, 67, 2, 93, 66, 2, 92
.byte 8, 68, 1, 54, 132, 1, 64, 131, 1, 63, 195, 1, 73, 194, 1, 72, 2, 2, 82, 1, 2, 81, 65, 2, 91
.byte 8, 133, 1, 65, 132, 1, 64, 196, 1, 74, 195, 1, 73, 3, 2, 83, 2, 2, 82, 66, 2, 92, 65, 2, 91
.byte 9, 68, 1, 54, 132, 1, 64, 131, 1, 63, 195, 1, 73, 194, 1, 72, 193, 1, 71, 1, 2, 81, 0, 2, 80, 64, 2, 90
.byte 9, 133, 1, 65, 132, 1, 64, 196, 1, 74, 195, 1, 73, 194, 1, 72, 2, 2, 82, 1, 2, 81, 65, 2, 91, 64, 2, 90
.byte 8, 68, 1, 54, 132, 1, 64, 131, 1, 63, 130, 1, 62, 194, 1, 72, 193, 1, 71, 192, 1, 70, 0, 2, 80
.byte 8, 133, 1, 65, 132, 1, 64, 131, 1, 63, 195, 1, 73, 194, 1, 72, 193, 1, 71, 1, 2, 81, 0, 2, 80
.byte 7, 68, 1, 54, 67, 1, 53, 131, 1, 63, 130, 1, 62, 129, 1, 61, 193, 1, 71, 192, 1, 70
.byte 7, 68, 1, 54, 132, 1, 64, 131, 1, 63, 130, 1, 62, 194, 1, 72, 193, 1, 71, 192, 1, 70
.byte 6, 68, 1, 54, 67, 1, 53, 66, 1, 52, 130, 1, 62, 129, 1, 61, 128, 1, 60
.byte 6, 68, 1, 54, 67, 1, 53, 131, 1, 63, 130, 1, 62, 129, 1, 61, 128, 1, 60
.byte 5, 68, 1, 54, 67, 1, 53, 66, 1, 52, 65, 1, 51, 64, 1, 50
.byte 5, 68, 1, 54, 67, 1, 53, 2, 1, 42, 1, 1, 41, 0, 1, 40
.byte 5, 68, 1, 54, 3, 1, 43, 2, 1, 42, 193, 0, 31, 192, 0, 30
.byte 5, 4, 1, 44, 3, 1, 43, 194, 0, 32, 193, 0, 31, 128, 0, 20
.byte 5, 4, 1, 44, 195, 0, 33, 194, 0, 32, 129, 0, 21, 64, 0, 10
.byte 6, 68, 1, 54, 67, 1, 53, 66, 1, 52, 2, 1, 42, 1, 1, 41, 0, 1, 40
.byte 6, 68, 1, 54, 67, 1, 53, 3, 1, 43, 2, 1, 42, 1, 1, 41, 0, 1, 40
.byte 7, 68, 1, 54, 67, 1, 53, 3, 1, 43, 2, 1, 42, 1, 1, 41, 193, 0, 31, 192, 0, 30
.byte 7, 68, 1, 54, 4, 1, 44, 3, 1, 43, 2, 1, 42, 194, 0, 32, 193, 0, 31, 192, 0, 30
.byte 8, 68, 1, 54, 4, 1, 44, 3, 1, 43, 2, 1, 42, 194, 0, 32, 193, 0, 31, 192, 0, 30, 128, 0, 20
.byte 8, 5, 1, 45, 4, 1, 44, 3, 1, 43, 195, 0, 33, 194, 0, 32, 193, 0, 31, 129, 0, 21, 128, 0, 20
.byte 9, 68, 1, 54, 4, 1, 44, 3, 1, 43, 195, 0, 33, 194, 0, 32, 193, 0, 31, 129, 0, 21, 128, 0, 20, 64, 0, 10
.byte 9, 5, 1, 45, 4, 1, 44, 196, 0, 34, 195, 0, 33, 194, 0, 32, 130, 0, 22, 129, 0, 21, 65, 0, 11, 64, 0, 10
.BSS

328
src/display_map.asm Normal file
View File

@ -0,0 +1,328 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "world.inc"
.include "memory.inc"
.include "math.inc"
.include "monitor.inc"
.include "io/gr.inc"
; inits display of map
.export Display_Map_Init
; displays the map and reacts to keyboard input
.export Map_Loop
; displays the map
.export Display_Map_Show
.define DBG_DISP_WIDTH 40
.define DBG_DISP_HEIGHT 48
.BSS
Map_x: .byte 1
Map_y: .byte 1
.define MAX_Y HEIGHT_WORLD - DBG_DISP_HEIGHT
.define MAX_X WIDTH_WORLD - DBG_DISP_WIDTH
.CODE
.define KEY_UP $C9
.define KEY_LEFT $CA
.define KEY_DOWN $CB
.define KEY_RIGHT $CC
.define TAB $89
; ##################### MAP ##################
; Buffer to save the 4 bottom line of gr1
SAVED_GR_L36: .res 40
SAVED_GR_L37: .res 40
SAVED_GR_L38: .res 40
SAVED_GR_L39: .res 40
; The 4 bottom lines of GR1
.define SRC_GR1_L36 $650
.define SRC_GR1_L37 $6D0
.define SRC_GR1_L38 $750
.define SRC_GR1_L39 $7D0
; @brief Displays the map and wait for action: move the view or exit
Map_Loop:
; save the 4 last lines of GR1
ldx #39
loop_save_gr:
lda SRC_GR1_L36, X
sta SAVED_GR_L36, X
lda SRC_GR1_L37, X
sta SAVED_GR_L37, X
lda SRC_GR1_L38, X
sta SAVED_GR_L38, X
lda SRC_GR1_L39, X
sta SAVED_GR_L39, X
dex
bne loop_save_gr
lda SRC_GR1_L36, X
sta SAVED_GR_L36, X
lda SRC_GR1_L37, X
sta SAVED_GR_L37, X
lda SRC_GR1_L38, X
sta SAVED_GR_L38, X
lda SRC_GR1_L39, X
sta SAVED_GR_L39, X
disp:
; display map
;sta $C051 ; full screen
sta $C054 ; page 1
sta $C056 ; lores
sta $C050 ; gfx
sta $C052 ; mixed mode off
ldx Map_x
ldy Map_y
; capping X and Y
min_x:
cpx #$FF
bne max_x
ldx #0
bvc min_y
max_x:
cpx #MAX_X
bcc min_y
ldx #MAX_X
min_y:
cpy #$FF
bne max_y
ldy #0
bvc disp_map
max_y:
cpy #MAX_Y
bcc disp_map
ldy #MAX_Y
disp_map:
stx Map_x
sty Map_y
jsr Display_Map_Show
; waiting for a key to be pressed
kbd_loop:
lda KEYBD
bpl kbd_loop ; bit #8 is set when a character is present (thus A < 0)
sta KEYBD_STROBE
cmp #KEY_UP
beq move_up
cmp #KEY_RIGHT
beq move_right
cmp #KEY_DOWN
beq move_down
cmp #KEY_LEFT
beq move_left
cmp #TAB
beq quit
jmp kbd_loop
move_up:
dec Map_y
jmp disp
move_right:
inc Map_x
jmp disp
move_down:
inc Map_y
jmp disp
move_left:
dec Map_x
jmp disp
quit:
; restore player's view
;sta $C054 ; page 1
sta $C057 ; hires
sta $C053 ; mixed mode on
; restore the 4 last lines of GR1
ldx #39
loop_restore_gr:
lda SAVED_GR_L36, X
sta SRC_GR1_L36, X
lda SAVED_GR_L37, X
sta SRC_GR1_L37, X
lda SAVED_GR_L38, X
sta SRC_GR1_L38, X
lda SAVED_GR_L39, X
sta SRC_GR1_L39, X
dex
bne loop_restore_gr
lda SAVED_GR_L36, X
sta SRC_GR1_L36, X
lda SAVED_GR_L37, X
sta SRC_GR1_L37, X
lda SAVED_GR_L38, X
sta SRC_GR1_L38, X
lda SAVED_GR_L39, X
sta SRC_GR1_L39, X
rts
Display_Map_Init:
; Init coords to view map
lda #0
sta Map_x
sta Map_y
jsr Clear_Gr1
; display GR1
sta $C051 ; full screen
sta $C054 ; page 1
sta $C056 ; lores
sta $C050 ; gfx
sta $C052 ; mixed mode off
rts
.import World
.define SRC_LINE_UP ZERO_7_1
.define SRC_LINE_DOWN ZERO_8_1
.define SRC_OFFSET ZERO_5_5
.define DST_GR1 ZERO_5_5
.define CPT_FILL ZERO_5_4
Addr_GR1: ; 3 address blocks to fill GR1 (address -1), stored in reversed endianess.
.word $4F04, $2704, $FF03
; @brief Displays the map in GR1 screen
; @param X top-left x coordinate
; @param Y top-left y coordinate
; X, Y capped by WITH_WOLRD - GR_WIDTH, HEIGHT_WORLD - GR_HEIGHT
; The code in "copy_8x2_lines" copies 16 lines from World
; It is called 3 times to fill the entire screen. Each line
; is two tile heigh.
Display_Map_Show:
; display GR1
sta $C051 ; full screen
sta $C054 ; page 1
sta $C056 ; lores
sta $C050 ; gfx
sta $C052 ; mixed mode off
ld_src:
; compute offset
stx ZERO_5_4
sty FAC1
lda #WIDTH_WORLD
sta FAC2
jsr mul8
sta SRC_OFFSET+1
txa
clc
adc ZERO_5_4
sta SRC_OFFSET
lda SRC_OFFSET+1
adc #0
sta SRC_OFFSET+1
; source address in World
lda #<(World-1)
clc
adc SRC_OFFSET
sta SRC_LINE_UP
lda #>(World-1)
adc SRC_OFFSET+1
sta SRC_LINE_UP+1
lda SRC_LINE_UP
clc
adc #WIDTH_WORLD
sta SRC_LINE_DOWN
lda SRC_LINE_UP+1
adc #0
sta SRC_LINE_DOWN+1
ldx #5
stx CPT_FILL
; destination adress in GR1.
lda Addr_GR1,X
sta DST_GR1
dex
lda Addr_GR1,X
sta DST_GR1+1
dex
stx CPT_FILL
fill:
ldx #8
copy_8x2_lines: ; call 3 times to fill the screen
ldy #DBG_DISP_WIDTH
copy_2_lines:
lda (SRC_LINE_DOWN),Y
asl
asl
asl
asl
ora (SRC_LINE_UP),Y
sta (DST_GR1), Y
dey
bne copy_2_lines
; update source
lda SRC_LINE_UP
clc
adc #(2*WIDTH_WORLD)
sta SRC_LINE_UP
lda SRC_LINE_UP+1
adc #0
sta SRC_LINE_UP+1
lda SRC_LINE_DOWN
clc
adc #(2*WIDTH_WORLD)
sta SRC_LINE_DOWN
lda SRC_LINE_DOWN+1
adc #0
sta SRC_LINE_DOWN+1
; update destination
clc
lda DST_GR1
adc #$80
sta DST_GR1
lda DST_GR1+1
adc #0
sta DST_GR1+1
dex
bne copy_8x2_lines
; destination adress in GR1.
ldx CPT_FILL
lda Addr_GR1,X
sta DST_GR1
dex
lda Addr_GR1,X
sta DST_GR1+1
dex
stx CPT_FILL
cpx #$FD
bne fill
rts

5
src/display_map.inc Normal file
View File

@ -0,0 +1,5 @@
; inits display of map
.import Display_Map_Init
; @brief Displays the map in GR1 screen
.import Map_Loop

View File

@ -1,5 +1,6 @@
# Configuration for assembler programs which don't need a special setup
# Configuration:
# APPLESOFT required
# HGR1 & HGR2 segment reserved
FEATURES {
STARTADDRESS: default = $0803;
}
@ -9,16 +10,16 @@ SYMBOLS {
MEMORY {
ZP: file = "", start = $0000, size = $00FF;
HEADER: file = %O, start = %S - 4, size = $0004;
MAIN: file = %O, define = yes, start = %S, size = $C000 - %S;
BSS: file = "", start = __MAIN_LAST__, size = $C000 - __MAIN_LAST__;
MAIN: file = %O, define = yes, start = %S, size = $2000 - %S;
HGR: file = "", define = no, start = $2000, size = $4000;
DATA: file = %O, define = yes, start = $6000, size = $2000;
BSSMEM: file = "", define = no, start = __DATA_LAST__, size = $9600 - __DATA_LAST__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
EXEHDR: load = HEADER, type = ro;
CODE: load = MAIN, type = rw;
RODATA: load = MAIN, type = ro, optional = yes;
DATA: load = MAIN, type = rw, optional = yes, align = $100;
BSS: load = BSS, type = bss, optional = yes, define = yes, align = $100;
# user defined segments
TILES: load = MAIN, type = ro, align = $100;
RODATA: load = DATA, type = ro, optional = yes, align = $100;
DATA: load = DATA, type = rw, optional = yes, align = $100;
BSS: load = BSSMEM, type = bss, optional = yes, define = yes, align = $100;
}

View File

@ -14,12 +14,14 @@
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "world.inc"
.include "display.inc"
.include "display_map.inc"
.include "memory.inc"
.include "monitor.inc"
.export game_loop
; display / view
@ -39,9 +41,17 @@
.define KEY_LEFT $CA
.define KEY_DOWN $CB
.define KEY_RIGHT $CC
.define TAB $89
.CODE
nop ; Main can jump to a wrong game_loop's addr without this nop :/
; ########### GAME ##########
; @brief Main game loop
game_loop:
ldx Player_XY
@ -58,7 +68,7 @@ kbd_loop:
sta KEYBD_STROBE
jsr key_action
bvc kbd_loop
jmp kbd_loop
rts
@ -72,20 +82,22 @@ key_action:
beq move_down
cmp #KEY_LEFT
beq move_left
cmp #TAB
beq display_map
rts
move_up:
jsr player_move_dey
bvc end_action_move
jmp end_action_move
move_right:
jsr player_move_inx
bvc end_action_move
jsr player_move_inx
jmp end_action_move
move_down:
jsr player_move_iny
bvc end_action_move
jmp end_action_move
move_left:
jsr player_move_dex
bvc end_action_move
jmp end_action_move
end_action_move: ; update player/view coordinates and refresh the display
jsr world_set_player
@ -93,3 +105,7 @@ end_action_move: ; update player/view coordinates and refresh the dis
jsr view_refresh
rts
display_map:
jsr Map_Loop
rts

48
src/io/gr.asm Normal file
View File

@ -0,0 +1,48 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.export Clear_Gr1
.CODE
;@brief Clears GR1 screen
; BEWARE : It will fill the "holes" with 0s
Clear_Gr1:
lda #0 ; black
ldx #0
clear_gr1_1:
sta $400, X
inx
bne clear_gr1_1
ldx #0
clear_gr1_2:
sta $500, X
inx
bne clear_gr1_2
ldx #0
clear_gr1_3:
sta $600, X
inx
bne clear_gr1_3
ldx #0
clear_gr1_4:
sta $700, X
inx
bne clear_gr1_4
rts

1
src/io/gr.inc Normal file
View File

@ -0,0 +1 @@
.import Clear_Gr1

187
src/io/textio.asm Normal file
View File

@ -0,0 +1,187 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "../memory.inc"
.export CIN_STR
.export Cin_Str
.export Cin_Char
.export Print
.export ClearTxt
.define SPACE $A0
.define CURSOR $5F
.define RETURN $8D
.define DELETE $FF
.define LEFT $88
.DATA
CIN_STR:
.byte 0
.res 40 ; input string buffer char[40]
.CODE
; brief Clears the 4 line in text zone (mixed mode)
ClearTxt:
ldx #39
lda #SPACE
loop_clear_lines:
sta TXT1_LINE20, X
sta TXT1_LINE21, X
sta TXT1_LINE22, X
sta TXT1_LINE23, X
dex
bpl loop_clear_lines
rts
; brief Scrolls the lines in text zone (mixed mode)
_ScrollTxt:
ldx #39
loop_scroll_lines:
lda TXT1_LINE21, X
sta TXT1_LINE20, X
lda TXT1_LINE22, X
sta TXT1_LINE21, X
lda TXT1_LINE23, X
sta TXT1_LINE22, X
lda #SPACE
sta TXT1_LINE23, X
dex
bpl loop_scroll_lines
rts
.define ADDR_STR ZERO_7_1 ; 2 bytes same as FAC1 and FAC2
; @brief Print the null terminated str
; @param A,X Adress of the string (hi, low)
Print:
stx ADDR_STR
sta ADDR_STR+1
jsr _ScrollTxt
ldy #0
loop_print_str:
lda (ADDR_STR), Y
cmp #0
beq break_print_str
sta TXT1_LINE23, Y
iny
cpy #40
bne loop_print_str
break_print_str:
rts
.macro INC_SEED
clc
lda SEED0
adc #1
sta SEED0
lda SEED1
adc #0
sta SEED1
lda SEED2
adc #0
sta SEED2
lda SEED3
adc #0
sta SEED3
.endmacro
; @brief Gets an input string into the CIN_STR buffer
; @details It will also init the seed
Cin_Str:
jsr _ScrollTxt
; position the cursor
ldx #0
lda #CURSOR
sta TXT1_LINE23, X
; wait for keyboard
cin_str_kbd_loop:
INC_SEED
lda KEYBD
bpl cin_str_kbd_loop ; bit #8 is set when a character is present (thus A < 0)
sta KEYBD_STROBE
cmp #RETURN
beq break_cin ; break if "Return"
cmp #DELETE
beq delete
cmp #LEFT
beq delete
; print key and avance the cursor
sta TXT1_LINE23, X
sta CIN_STR, X
inx
cpx #40 ; eol -> ends anyway
beq break_cin
lda #CURSOR
sta TXT1_LINE23, X
jmp cin_str_kbd_loop
break_cin:
lda #SPACE
sta TXT1_LINE23, X ; erase the cursor
lda #0
sta CIN_STR, X
rts
delete:
cpx #0 ; cannot delete when at pos 0
beq cin_str_kbd_loop
lda #SPACE
sta TXT1_LINE23, X
dex
lda #0
sta CIN_STR, X
lda #CURSOR
sta TXT1_LINE23, X
jmp cin_str_kbd_loop
; @brief Gets an input char
; @detals Entered char in A
Cin_Char:
jsr _ScrollTxt
lda #CURSOR
sta TXT1_LINE23
; wait for keyboard
cin_char_kbd_loop:
lda KEYBD
bpl cin_char_kbd_loop ; bit #8 is set when a character is present (thus A < 0)
sta KEYBD_STROBE
sta TXT1_LINE23
rts

23
src/io/textio.inc Normal file
View File

@ -0,0 +1,23 @@
.import Print
.import ClearTxt
.import Cin_Str
.import Cin_Char
.import CIN_STR
; --- string with high-bit set, null-terminated
; Apple II char < 128 are inverted
.macro ASCIIZ str
.repeat .strlen (str), c
.byte .strat (str, c) | $80
.endrep
.byte 0
.endmacro
.macro PRINT string
lda #>string
ldx #<string
jsr Print
.endmacro

143
src/io/title.asm Normal file
View File

@ -0,0 +1,143 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "../monitor.inc"
.include "../memory.inc"
.include "../io/textio.inc"
.include "gr.inc"
.export Title
.DATA
GR_TITLE_00 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
GR_TITLE_01 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
GR_TITLE_02 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
GR_TITLE_03 : .byte $0,$0,$99,$99,$99,$99,$99,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$99,$99,$99,$99,$99,$0
GR_TITLE_04 : .byte $0,$0,$99,$99,$99,$99,$99,$0,$0,$88,$88,$88,$88,$0,$0,$88,$88,$88,$88,$0,$0,$0,$88,$88,$0,$0,$0,$88,$88,$88,$88,$88,$0,$0,$99,$99,$99,$99,$99,$0
GR_TITLE_05 : .byte $0,$0,$99,$0,$0,$0,$0,$0,$88,$0,$0,$0,$0,$0,$88,$0,$0,$0,$0,$0,$0,$88,$0,$0,$88,$0,$0,$88,$0,$0,$0,$0,$88,$0,$99,$0,$0,$0,$0,$0
GR_TITLE_06 : .byte $0,$0,$99,$0,$0,$0,$0,$0,$88,$0,$0,$0,$0,$0,$88,$0,$0,$0,$0,$0,$88,$0,$0,$0,$0,$88,$0,$88,$0,$0,$0,$0,$88,$0,$99,$0,$0,$0,$0,$0
GR_TITLE_07 : .byte $0,$0,$99,$99,$99,$0,$0,$0,$88,$88,$88,$88,$0,$0,$88,$0,$0,$0,$0,$0,$88,$0,$0,$0,$0,$88,$0,$88,$88,$88,$88,$88,$0,$0,$99,$99,$99,$0,$0,$0
GR_TITLE_08 : .byte $0,$0,$99,$0,$0,$0,$0,$0,$0,$0,$0,$0,$88,$0,$88,$0,$0,$0,$0,$0,$88,$88,$88,$88,$88,$88,$0,$88,$0,$0,$0,$0,$0,$0,$99,$0,$0,$0,$0,$0
GR_TITLE_09 : .byte $0,$0,$99,$0,$0,$0,$0,$0,$0,$0,$0,$0,$88,$0,$88,$0,$0,$0,$0,$0,$88,$0,$0,$0,$0,$88,$0,$88,$0,$0,$0,$0,$0,$0,$99,$0,$0,$0,$0,$0
GR_TITLE_10 : .byte $0,$0,$99,$99,$99,$99,$99,$0,$88,$0,$0,$0,$88,$0,$88,$0,$0,$0,$0,$0,$88,$0,$0,$0,$0,$88,$0,$88,$0,$0,$0,$0,$0,$0,$99,$99,$99,$99,$99,$0
GR_TITLE_11 : .byte $0,$0,$99,$99,$99,$99,$99,$0,$88,$88,$88,$88,$0,$0,$0,$88,$88,$88,$88,$0,$88,$0,$0,$0,$0,$88,$0,$88,$0,$0,$0,$0,$0,$0,$99,$99,$99,$99,$99,$0
GR_TITLE_12 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
GR_TITLE_13 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
GR_TITLE_14 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
GR_TITLE_15 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$55,$0,$0,$55,$55,$55,$0,$0,$55,$55,$0,$0,$0,$0,$55,$55,$55,$0,$55,$55,$55,$0,$55,$55,$0,$55,$55,$55,$0
GR_TITLE_16 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$0,$55,$0,$55,$0,$0,$0,$55,$0,$0,$0,$0,$0,$0,$0,$0,$55,$0,$55,$0,$55,$0,$0,$55,$0,$55,$0,$55,$0
GR_TITLE_17 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$55,$0,$0,$55,$0,$55,$0,$55,$0,$0,$0,$0,$0,$0,$55,$0,$0,$0,$55,$0,$55,$0,$0,$55,$0,$55,$55,$55,$0
GR_TITLE_18 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$0,$55,$0,$55,$55,$55,$0,$0,$55,$55,$0,$0,$0,$0,$55,$55,$55,$0,$55,$55,$55,$0,$0,$55,$0,$0,$0,$55,$0
GR_TITLE_19 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0
STR_NAME: ASCIIZ "WHAT'S YOUR NAME, ADVENTURER?"
.CODE
Scroll:
ldx #39
loop_scroll:
lda TXT1_LINE1, X
sta TXT1_LINE0, X
lda TXT1_LINE2, X
sta TXT1_LINE1, X
lda TXT1_LINE3, X
sta TXT1_LINE2, X
lda TXT1_LINE4, X
sta TXT1_LINE3, X
lda TXT1_LINE5, X
sta TXT1_LINE4, X
lda TXT1_LINE6, X
sta TXT1_LINE5, X
lda TXT1_LINE7, X
sta TXT1_LINE6, X
lda TXT1_LINE8, X
sta TXT1_LINE7, X
lda TXT1_LINE9, X
sta TXT1_LINE8, X
lda TXT1_LINE10, X
sta TXT1_LINE9, X
lda TXT1_LINE11, X
sta TXT1_LINE10, X
lda TXT1_LINE12, X
sta TXT1_LINE11, X
lda TXT1_LINE13, X
sta TXT1_LINE12, X
lda TXT1_LINE14, X
sta TXT1_LINE13, X
lda TXT1_LINE15, X
sta TXT1_LINE14, X
lda TXT1_LINE16, X
sta TXT1_LINE15, X
lda TXT1_LINE17, X
sta TXT1_LINE16, X
lda TXT1_LINE18, X
sta TXT1_LINE17, X
lda TXT1_LINE19, X
sta TXT1_LINE18, X
dex
bpl loop_scroll
rts
.DATA
Title_Scr_Addr:
.word GR_TITLE_01, GR_TITLE_02, GR_TITLE_03, GR_TITLE_04, GR_TITLE_05, GR_TITLE_06, GR_TITLE_07, GR_TITLE_08, GR_TITLE_09, GR_TITLE_10
.word GR_TITLE_11, GR_TITLE_12, GR_TITLE_13, GR_TITLE_14, GR_TITLE_15, GR_TITLE_16, GR_TITLE_17, GR_TITLE_18, GR_TITLE_19
.CODE
; @brief Displays's the title screen
Title:
jsr Clear_Gr1
jsr ClearTxt
sta $C054 ; page 1
sta $C056 ; lores
sta $C050 ; gfx
sta $C053 ; mixed mode on
ldy #$FE
loop_scrolling:
lda #$A2 ; wait for 66ms
jsr WAIT
ldx #39
loop_lines:
lda GR_TITLE_00, X
sta TXT1_LINE19, X
dex
bpl loop_lines
jsr Scroll
iny
iny
lda Title_Scr_Addr, Y
sta loop_lines+1
lda Title_Scr_Addr+1, Y
sta loop_lines+2
cpy #$26
bne loop_scrolling
lda #>STR_NAME
ldx #<STR_NAME
jsr Print
jsr Cin_Str
rts

View File

@ -17,6 +17,9 @@
.include "random.inc"
.include "memory.inc"
.include "monitor.inc"
.include "display_map.inc"
.include "builder/builder.inc"
.include "io/textio.inc"
.export _main
@ -25,24 +28,70 @@
.import view_init
.import game_loop
.import Title
.import __MAIN_LAST__
.import __DATA_START__
.import __DATA_SIZE__
.CODE
_main:
; init the seed of rnd
lda #$DE
sta SEED0
lda #$AD
sta SEED1
lda #$BE
sta SEED2
lda #$EF
sta SEED3
; Relocate DATA from its freshly loaded location to __DATA_START__
; computing DATA actual starting address
lda #<__MAIN_LAST__
sta FROM
lda #>__MAIN_LAST__
sta FROM+1
lda #<__DATA_START__
sta TO
lda #>__DATA_START__
sta TO+1
lda #<__DATA_SIZE__
sta SIZEL
lda #>__DATA_SIZE__
sta SIZEH
jsr memcpy
lda #$0
sta SEED0
lda #$0
sta SEED1
lda #$0
sta SEED2
lda #$0
sta SEED3
jsr Title ; will init the seed
; overwrite the seed to debug
; lda #$5A
; sta SEED0
; lda #$5D
; sta SEED1
; lda #0
; sta SEED2
; lda #0
; sta SEED3
jsr Random8_Init
jsr Get_Size_Maze
jsr Init_Dimensions_Maze
jsr Build_Level
; Init
jsr Display_Map_Init
ldx Rooms+2 ; Rooms[0].x
ldy Rooms+3 ; Rooms[0].y
jsr player_init
jsr world_init
jsr world_init
jsr view_init
; Run
jsr game_loop

View File

@ -5,6 +5,7 @@
.define FAC2 ZERO_7_2
.export mul8
.export Modulus
.CODE
@ -29,3 +30,19 @@ m1: ror
bpl m0
ldx FAC1
rts
; Returns A % X in A
; Source: http://forum.6502.org/viewtopic.php?t=130
Modulus:
sec
stx FAC2
lbl_modulus:
sbc FAC2
bcs lbl_modulus
adc FAC2
rts

View File

@ -13,11 +13,12 @@
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.define FAC1 ZERO_7_1
.define FAC2 ZERO_7_2
.import mul8
.import Modulus
; Inverts a positive number to its 2's complement counterpart
; The bits are all reversed then one is added

72
src/memory.asm Normal file
View File

@ -0,0 +1,72 @@
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
; Must be the same as in memory.inc !!
.define ZERO_2_1 $19
.define ZERO_2_3 $1B
.define ZERO_8_1 $D6
.define ZERO_8_2 $D7
.define FROM ZERO_2_1
.define TO ZERO_2_3
.define SIZEH ZERO_8_1
.define SIZEL ZERO_8_2
.export memcpy
.export TXT1_LINES
.DATA
TXT1_LINES:
.word $400, $480, $500, $580, $600, $680, $700, $780, $428, $4A8, $528, $5A8, $628, $6A8
.word $728, $7A8, $450, $4D0, $550, $5D0, $650, $6D0, $750, $7D0
.CODE
; http://www.6502.org/source/general/memory_move.html
; Move memory up
;
; FROM = source start address
; TO = destination start address
; SIZE = number of bytes to move
;
memcpy: LDX SIZEH ; the last byte must be moved first
CLC ; start at the final pages of FROM and TO
TXA
ADC FROM+1
STA FROM+1
CLC
TXA
ADC TO+1
STA TO+1
INX ; allows the use of BNE after the DEX below
LDY SIZEL
BEQ MU3
DEY ; move bytes on the last page first
BEQ MU2
MU1: LDA (FROM),Y
STA (TO),Y
DEY
BNE MU1
MU2: LDA (FROM),Y ; handle Y = 0 separately
STA (TO),Y
MU3: DEY
DEC FROM+1 ; move the next page (if any)
DEC TO+1
DEX
BNE MU1
RTS

View File

@ -1,5 +1,5 @@
; Copyright (C) 2018 Christophe Meneboeuf <christophe@xtof.info>
; Copyright (C) 2019 Christophe Meneboeuf <christophe@xtof.info>
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
@ -19,7 +19,11 @@
; Free locations in Zero Page: not used by either
; the Monitor, Applesoft, Integer Basic, DOS3.3 or PRODOS
; reserved locations
.define RESERVED01 $52
; locations for the random generator
; little endian
.define SEED0 $6
.define SEED1 $7
.define SEED2 $8
@ -60,4 +64,59 @@
.define KEYBD_STROBE $C010
; *********** HIRES ************
.define ADDR_HGR1 $2000
.define ADDR_HGR1 $2000
.define ADDR_HGR2 $4000
; ********** TEXT *************
.define TXT1_LINE0 $400
.define TXT1_LINE1 $480
.define TXT1_LINE2 $500
.define TXT1_LINE3 $580
.define TXT1_LINE4 $600
.define TXT1_LINE5 $680
.define TXT1_LINE6 $700
.define TXT1_LINE7 $780
.define TXT1_LINE8 $428
.define TXT1_LINE9 $4A8
.define TXT1_LINE10 $528
.define TXT1_LINE11 $5A8
.define TXT1_LINE12 $628
.define TXT1_LINE13 $6A8
.define TXT1_LINE14 $728
.define TXT1_LINE15 $7A8
.define TXT1_LINE16 $450
.define TXT1_LINE17 $4D0
.define TXT1_LINE18 $550
.define TXT1_LINE19 $5D0
.define TXT1_LINE20 $650
.define TXT1_LINE21 $6D0
.define TXT1_LINE22 $750
.define TXT1_LINE23 $7D0
.import TXT1_LINES
; *********** CUSTOM ROUTINES *********
.define FROM ZERO_2_1 ; 2 bytes
.define TO ZERO_2_3 ; 2 bytes
.define SIZEH ZERO_8_1
.define SIZEL ZERO_8_2
.import memcpy
; ************ MACROS ***********
; pushes addr to the stack
; A is detroyed
.macro PUSH addr
lda addr
pha
.endmacro
; pops addr from the stack
; A is detroyed
.macro POP addr
pla
sta addr
.endmacro

View File

@ -50,6 +50,7 @@
.define VTAB $fc22 ; Vertical tab
.define VTABZ $fc24 ; Vertical tab (alternate entry)
.define HOME $fc58 ; Home cursor and clear to end of page
.define WAIT $fca8 ; wait : read "Assembly Cookbook for the Apple II/IIe"
.define RDKEY $fd0c ; Get an input character
.define CROUT $fd8e ; Issue a carriage return
.define PRBYTE $fdda ; Print a hexadecimal byte

View File

@ -17,6 +17,7 @@
.include "world.inc"
.include "memory.inc"
.include "monitor.inc"
.include "io/textio.inc"
; init the player's structures
@ -39,7 +40,7 @@
; Player coordinates in the maze ([0:255], [0:255])
.export Player_XY
.import compute_maze_addr
.import Compute_Maze_Addr
.BSS
@ -47,15 +48,20 @@
Player_XY: .res 2
.CODE
; Player starts at [1:1]
STR_GO_UP: ASCIIZ "YOU GO NORTH"
STR_GO_RIGHT: ASCIIZ "YOU GO EAST"
STR_GO_DOWN: ASCIIZ "YOU GO SOUTH"
STR_GO_LEFT: ASCIIZ "YOU GO WEST"
STR_HIT_WALL: ASCIIZ "YOU HIT A WALL"
; @brief Player initial coords
; @param X player's x
; @param Y player's y
player_init:
ldx #1
stx Player_XY
stx Player_XY+1
sty Player_XY+1
rts
@ -65,104 +71,97 @@ player_init:
.define ADDR_IN_MAZE ZERO_2_1
player_move_inx:
; check if moving is possible
ldx Player_XY
; test for border
cpx #WIDTH_MAZE - 1 ; last tile is always a wall...
beq return_from_player_move
; test that x+1 is "WALKABLE"
ldx Player_XY
ldy Player_XY+1
jsr compute_maze_addr ; we get the adress for x,y then we increment x
jsr Compute_Maze_Addr ; we get the adress for x,y then we increment x
stx ADDR_IN_MAZE
sta ADDR_IN_MAZE+1
ldy #1 ; will look at x+1
lda #ACTORS::WALKABLE
cmp (ADDR_IN_MAZE), Y
bcc return_from_player_move ; carry cleared if A is strictly the lesser --> not walkable
bcc hit_wall ; carry cleared if A is strictly the lesser --> not walkable
ldx Player_XY
inx
stx Player_XY ; walkable
bvc return_from_player_move
PRINT STR_GO_RIGHT
jmp return_from_player_move
player_move_dex:
; check if moving is possible
; test that x-1 is "WALKABLE"
ldx Player_XY
; test for border
cpx #1 ; 1st tile is always a wall...
beq return_from_player_move
; test that x+1 is "WALKABLE"
dex
ldy Player_XY+1
jsr compute_maze_addr ; we get the adress for x-1
jsr Compute_Maze_Addr ; we get the adress for x-1
stx ADDR_IN_MAZE
sta ADDR_IN_MAZE+1
ldy #0 ; will look at x-1
lda #ACTORS::WALKABLE
cmp (ADDR_IN_MAZE), Y
bcc return_from_player_move ; carry cleared if A is strictly the lesser --> not walkable
bcc hit_wall ; carry cleared if A is strictly the lesser --> not walkable
ldx Player_XY
dex
stx Player_XY ; walkable
bvc return_from_player_move
PRINT STR_GO_LEFT
jmp return_from_player_move
; Common code to return from the moves.
; Moves BRANCH to here
return_from_player_move:
; return player's coordinates
ldx Player_XY
ldy Player_XY+1
rts
hit_wall:
PRINT STR_HIT_WALL
jmp return_from_player_move
player_move_iny:
; check if moving is possible
ldy Player_XY+1
; test for border
cpy #HEIGHT_MAZE - 1 ; last tile is always a wall...
beq return_from_player_move
; test that y+1 is "WALKABLE"
ldy Player_XY+1
ldx Player_XY
iny
jsr compute_maze_addr ; we get the adress for x,y+1
jsr Compute_Maze_Addr ; we get the adress for x,y+1
stx ADDR_IN_MAZE
sta ADDR_IN_MAZE+1
ldy #0
lda #ACTORS::WALKABLE
cmp (ADDR_IN_MAZE), Y
bcc return_from_player_move ; carry cleared if A is strictly the lesser --> not walkable
bcc hit_wall ; carry cleared if A is strictly the lesser --> not walkable
ldy Player_XY+1 ; walkable
iny
sty Player_XY+1
bvc return_from_player_move
PRINT STR_GO_DOWN
jmp return_from_player_move
player_move_dey:
; check if moving is possible
ldy Player_XY+1
; test for border
cpy #1 ; 1st tile is always a wall...
beq return_from_player_move
; test that y-1 is "WALKABLE"
ldy Player_XY+1
ldx Player_XY
dey
jsr compute_maze_addr ; we get the adress for x,y-1
jsr Compute_Maze_Addr ; we get the adress for x,y-1
stx ADDR_IN_MAZE
sta ADDR_IN_MAZE+1
ldy #0
lda #ACTORS::WALKABLE
cmp (ADDR_IN_MAZE), Y
bcc return_from_player_move ; carry cleared if A is strictly the lesser --> not walkable
bcc hit_wall ; carry cleared if A is strictly the lesser --> not walkable
ldy Player_XY+1 ; walkable
dey
sty Player_XY+1
PRINT STR_GO_UP
bvc return_from_player_move

View File

@ -3,63 +3,23 @@
.include "memory.inc"
.export random8
.export Random8
.export Random8_Init
.export DBG_SEED
.define TMP ZERO_2_1 ; requires 4 bytes
.define MOD ZERO_2_5
.define TMP RESERVED01
.BSS
.align 256
T0: .res 256
T1: .res 256
T2: .res 256
T3: .res 256
.CODE
;.align 256
; Linear congruential pseudo-random number generator
;
; Get the next SEED and obtain an 8-bit random number from it
;
; Requires the RAND subroutine
;
; Enter with:
;
; accumulator = modulus
;
; Exit with:
;
; accumulator = random number, 0 <= accumulator < modulus
;
; MOD, TMP, TMP+1, and TMP+2 are overwritten
;
; Note that TMP to TMP+2 are only used after RAND is called.
;
random8: STA MOD ; store modulus in MOD
JSR RAND ; get next seed
LDA #0 ; multiply SEED by MOD
STA TMP+2
STA TMP+1
STA TMP
SEC
ROR MOD ; shift out modulus, shifting in a 1 (will loop 8 times)
R8A: BCC R8B ; branch if a zero was shifted out
CLC ; add SEED, keep upper 8 bits of product in accumulator
TAX
LDA TMP
ADC SEED0
STA TMP
LDA TMP+1
ADC SEED1
STA TMP+1
LDA TMP+2
ADC SEED2
STA TMP+2
TXA
ADC SEED3
R8B: ROR ; shift product right
ROR TMP+2
ROR TMP+1
ROR TMP
LSR MOD ; loop until all 8 bits of MOD have been shifted out
BNE R8A
RTS
DBG_SEED: .byte 0,0,0,0 ; MUST NOT BE RELOCATED!
; Linear congruential pseudo-random number generator
;
@ -79,79 +39,87 @@ R8B: ROR ; shift product right
; SEED2 = byte 2 of seed
; SEED3 = byte 3 of seed
;
; TMP, TMP+1, TMP+2 and TMP+3 are overwritten
; TMP is overwritten
;
; Assuming that (a) SEED0 to SEED3 and TMP+0 to TMP+3 are all located on page
; zero, and (b) none of the branches cross a page boundary:
; For maximum speed, locate each table on a page boundary
;
; Space: 106 bytes
; Speed: JSR RAND takes 517 cycles
; Assuming that (a) SEED0 to SEED3 and TMP are located on page zero, and (b)
; all four tables start on a page boundary:
;
RAND: CLC ; copy SEED into TMP
LDA SEED0 ; and compute SEED = SEED * $10000 + SEED + 1
STA TMP
; Space: 58 bytes for the routine
; 1024 bytes for the tables
; Speed: JSR RAND takes 94 cycles
;
Random8: CLC ; compute lower 32 bits of:
LDX SEED0 ; 1664525 * ($100 * SEED1 + SEED0) + 1
LDY SEED1
LDA T0,X
ADC #1
STA SEED0
LDA SEED1
STA TMP+1
ADC #0
LDA T1,X
ADC T0,Y
STA SEED1
LDA SEED2
STA TMP+2
ADC TMP
LDA T2,X
ADC T1,Y
STA TMP
LDA T3,X
ADC T2,Y
TAY ; keep byte 3 in Y for now (for speed)
CLC ; add lower 32 bits of:
LDX SEED2 ; 1664525 * ($10000 * SEED2)
LDA TMP
ADC T0,X
STA SEED2
LDA SEED3
STA TMP+3
ADC TMP+1
TYA
ADC T1,X
CLC
LDX SEED3 ; add lower 32 bits of:
ADC T0,X ; 1664525 * ($1000000 * SEED3)
STA SEED3
;
; Bit 7 of $00, $19, $66, and $0D is 0, so only 6 shifts are necessary
;
LDY #5
RAND1: ASL TMP ; shift TMP (old seed) left
ROL TMP+1
ROL TMP+2
ROL TMP+3
;
; Get X from the RAND4 table. When:
;
; X = $00, SEED = SEED + $10000 * TMP
; X = $01, SEED = SEED + $100 * TMP
; X = $FE, SEED = SEED + $10000 * TMP + TMP
; X = $FF, SEED = SEED + $100 * TMP + TMP
;
LDX RAND4,Y
BPL RAND2 ; branch if X = $00 or X = $01
CLC ; SEED = SEED + TMP
LDA SEED0
ADC TMP
STA SEED0
LDA SEED1
ADC TMP+1
STA SEED1
LDA SEED2
ADC TMP+2
STA SEED2
LDA SEED3
ADC TMP+3
STA SEED3
INX ; $FE -> $00, $FF -> $01
INX
RAND2: CLC
BEQ RAND3 ; if X = $00, SEED = SEED + TMP * $10000
LDA SEED1 ; SEED = SEED + TMP * $100
ADC TMP
STA SEED1
RAND3: LDA SEED2
ADC TMP,X
STA SEED2
LDA SEED3
ADC TMP+1,X
STA SEED3
DEY
BPL RAND1
RTS
RAND4: .byte $01,$01,$00,$FE,$FF,$01
;
; Generate T0, T1, T2 and T3 tables
;
; A different multiplier can be used by simply replacing the four bytes
; that are commented below
;
; To speed this routine up (which will make the routine one byte longer):
; 1. Delete the first INX instruction
; 2. Replace LDA Tn-1,X with LDA Tn,X (n = 0 to 3)
; 3. Replace STA Tn,X with STA Tn+1,X (n = 0 to 3)
; 4. Insert CPX #$FF between the INX and BNE GT1
;
Random8_Init:
; Xtof's dbg Saving the seed
lda SEED0
sta DBG_SEED
lda SEED1
sta DBG_SEED+1
lda SEED2
sta DBG_SEED+2
lda SEED3
sta DBG_SEED+3
; Xtof's dbg
LDX #0 ; 1664525 * 0 = 0
STX T0
STX T1
STX T2
STX T3
INX
CLC
GT1: LDA T0-1,X ; add 1664525 to previous entry to get next entry
ADC #$0D ; byte 0 of multiplier
STA T0,X
LDA T1-1,X
ADC #$66 ; byte 1 of multiplier
STA T1,X
LDA T2-1,X
ADC #$19 ; byte 2 of multiplier
STA T2,X
LDA T3-1,X
ADC #$00 ; byte 3 of multiplier
STA T3,X
INX ; note: carry will be clear here
BNE GT1
RTS

View File

@ -1,7 +1,6 @@
; Enter with:
; accumulator = modulus
;
; Exit with:
; accumulator = random number, 0 <= accumulator < modulus
.import random8
; A = random number
.import Random8
.import Random8_Init

View File

@ -16,7 +16,7 @@
.export TILES
.SEGMENT "TILES"
.SEGMENT "RODATA"
.ALIGN 256
PLAYER:
@ -36,24 +36,7 @@ PLAYER:
.byte 16, 16, 66, 0
.byte 16, 16, 66, 0
.byte 16, 20, 74, 0
FLOOR_BLACK:
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
FLOOR_ORANGE:
FLOOR_1:
.byte 85, 42, 85, 42
.byte 1, 32, 0, 0
.byte 1, 32, 0, 0
@ -70,7 +53,24 @@ FLOOR_ORANGE:
.byte 16, 0, 64, 0
.byte 16, 0, 64, 0
.byte 16, 0, 64, 0
FLOOR_VIOLET:
FLOOR_2:
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
.byte $00, $00, $00, $00
FLOOR_3:
.byte $55, $2A, $55, $2A
.byte $55, $2A, $55, $2A
.byte $55, $2A, $55, $2A
@ -87,7 +87,7 @@ FLOOR_VIOLET:
.byte $55, $2A, $55, $2A
.byte $55, $2A, $55, $2A
.byte $55, $2A, $55, $2A
FLOOR_BLUE:
FLOOR_4:
.byte $D5, $AA, $D5, $AA
.byte $D5, $AA, $D5, $AA
.byte $D5, $AA, $D5, $AA
@ -105,23 +105,6 @@ FLOOR_BLUE:
.byte $D5, $AA, $D5, $AA
.byte $D5, $AA, $D5, $AA
WALL_1:
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
WALL_2:
.byte 197, 138, 213, 168
.byte 197, 138, 213, 168
.byte 197, 138, 213, 168
@ -138,6 +121,23 @@ WALL_2:
.byte 209, 130, 213, 168
.byte 209, 138, 212, 168
.byte 0, 0, 0, 0
WALL_2:
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
.byte $7F, $7F, $7F, $7F
UNKNOWN:
.byte $80, $80, $80, $80
.byte $80, $80, $80, $80
@ -157,9 +157,7 @@ UNKNOWN:
.byte $80, $80, $80, $80
.SEGMENT "DATA"
.ALIGN 256
; DON"T FORGET TO UPDATE NB_TILES!!
TILES:
.word PLAYER, FLOOR_BLACK, FLOOR_ORANGE, FLOOR_VIOLET, FLOOR_BLUE, WALL_1, WALL_2, UNKNOWN
.word PLAYER, FLOOR_1, FLOOR_2, FLOOR_3, FLOOR_4, WALL_1, WALL_2, UNKNOWN

View File

@ -41,7 +41,7 @@
; in: Y = y coord in the maze
; out: AX = Address corresponding to (x,y) in the World array
; DESTROYS A,X,Y, ZERO_2_1, ZERO_2_2, ZERO_2_3
.export compute_maze_addr
.export Compute_Maze_Addr
.define TILE_NR ZERO_2_1
@ -60,12 +60,12 @@
.CODE
; @param X Player's x
; @param Y Player's y
world_init:
; Saving the first tile on which the player stands
; FIXME player could be standing anywhere on any type of floor
ldx #1
ldy #1
jsr compute_maze_addr
jsr Compute_Maze_Addr
stx Tile_player_standing::addr
sta Tile_player_standing::addr+1
stx ZERO_2_1
@ -95,7 +95,7 @@ world_set_player:
; save the next tile
ldx ZERO_2_4
ldy ZERO_2_5
jsr compute_maze_addr ; get's player's position address in memory
jsr Compute_Maze_Addr ; get's player's position address in memory
stx Tile_player_standing::addr
sta Tile_player_standing::addr+1
stx ZERO_2_1
@ -114,8 +114,8 @@ world_set_player:
rts
compute_maze_addr:
; Destroys ZERO_2_1, ZERO_2_2 and ZERO_2_3
Compute_Maze_Addr:
stx COORD_X
@ -141,7 +141,7 @@ compute_maze_addr:
adc OFFSET
tax ; low part of address to be returned in X
lda #>World
adc OFFSET+1 ; high part of address to be returned in X
adc OFFSET+1 ; high part of address to be returned in A
rts
@ -151,45 +151,45 @@ compute_maze_addr:
.align 256
World:; .res (WIDTH_WORLD) * (HEIGHT_WORLD)
.byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06
.byte 06, 02, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06
.byte 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06
.byte 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06
.byte 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06
.byte 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06
.byte 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 06, 06, 06
.byte 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
.byte 06, 06, 06, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06
.byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06
.byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06
.byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 02, 02, 02, 02, 06, 06, 06
.byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06
.byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06
.byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06
.byte 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
.byte 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
.byte 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06
.byte 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06
.byte 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06
.byte 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06
.byte 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06
.byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06
.byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
.byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
.byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
.byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06
.byte 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
.byte 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
.byte 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06
.byte 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
.byte 06, 06, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06
.byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 06
.byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
.byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
.byte 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
.byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06
.byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06
.byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 06, 06, 06
.byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06
World: .res (WIDTH_WORLD) * (HEIGHT_WORLD)
; .byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06
; .byte 06, 02, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06
; .byte 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06
; .byte 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06
; .byte 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06
; .byte 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06
; .byte 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 06, 06, 06
; .byte 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
; .byte 06, 06, 06, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06
; .byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06
; .byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06
; .byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 02, 02, 02, 02, 06, 06, 06
; .byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06
; .byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06
; .byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06
; .byte 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
; .byte 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
; .byte 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06
; .byte 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06
; .byte 06, 06, 06, 06, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06
; .byte 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06
; .byte 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06
; .byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06
; .byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
; .byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
; .byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06
; .byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06
; .byte 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
; .byte 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
; .byte 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06
; .byte 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
; .byte 06, 06, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06
; .byte 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 06
; .byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
; .byte 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
; .byte 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 06
; .byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06
; .byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06
; .byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 02, 02, 02, 02, 02, 02, 06, 06, 06, 02, 02, 02, 06, 06, 06
; .byte 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06

View File

@ -4,22 +4,21 @@
; or alive, such as a monster
.define WIDTH_MAZE 64
.define HEIGHT_MAZE 40
.define SIZE_BORDER 0
.define WIDTH_WORLD WIDTH_MAZE + 2*SIZE_BORDER
.define HEIGHT_WORLD HEIGHT_MAZE + 2*SIZE_BORDER
.define MAXIMUM_WIDTH_MAZE 64 ; must be a power of 2
.define MAXIMUM_HEIGHT_MAZE 64 ; must be a power of 2
.define WIDTH_WORLD 64
.define HEIGHT_WORLD 64
.enum ACTORS
PLAYER = 0
FLOOR_BLACK = 1
FLOOR_ORANGE
FLOOR_VIOLET
FLOOR_BLUE
WALKABLE = FLOOR_BLUE ; Player won't be allowed to go on anything > WALKABLE
FLOOR_1 = 1
FLOOR_2
FLOOR_3
FLOOR_4
WALKABLE = FLOOR_4 ; Player won't be allowed to go on anything > WALKABLE
NOT_WALKABLE
NOT_TRANSPARENT = NOT_WALKABLE