5 levels to explore

This commit is contained in:
Christophe Meneboeuf 2021-04-14 23:26:21 +02:00
parent abbd59fd9e
commit d1a3affa1d
19 changed files with 426 additions and 111 deletions

View File

@ -1,7 +1,9 @@
APPLE2_CL := $(CC65_HOME)/bin/cl65
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/builder/builder.asm src/builder/rooms.asm src/builder/maze.asm src/builder/unite.asm \
src/game_loop.asm src/display.asm src/tiles.asm src/player.asm \
src/world/world.asm src/world/level.asm \
src/builder/builder.asm src/builder/actors.asm src/builder/rooms.asm src/builder/maze.asm src/builder/unite.asm \
src/actors/reactions.asm \
src/debug.asm src/display_map.asm \
src/io/title.asm src/io/textio.asm src/io/gr.asm
APPLE2_MAP := escape.map
@ -17,4 +19,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 src/builder/*.o src/builder/*.s src/io/*.s src/io/*.s gmon.out & rm -r bin/
rm -f $(APPLE2_MAP) src/*.o src/builder/*.o src/io/*.o src/world/*.o src/actors/*.o gmon.out & rm -r bin/

Binary file not shown.

View File

@ -20,14 +20,18 @@
.include "rooms.inc"
.include "maze.inc"
.include "unite.inc"
.include "actors.inc"
.include "../io/textio.inc"
.include "../math.inc"
.include "../monitor.inc"
.include "../world.inc"
.include "../memory.inc"
.include "../world/world.inc"
.include "../world/level.inc"
.import World
.import Random8
.import Grow_Maze ; to patch
.import Compute_Maze_Addr
.export Get_Size_Maze
.export Init_Dimensions_Maze
@ -37,8 +41,6 @@
.export WIDTH_MAZE
.export HEIGHT_MAZE
.define MAX_NB_ROOMS 64 ; MAX_NB_ROOMS *MUST BE* <= 64
.BSS
; Describes a room to be built
@ -65,9 +67,12 @@ STR_MAZE: ASCIIZ "GROWING THE MAZE..."
STR_DOORS: ASCIIZ "OPENING DOORS..."
STR_DEADENDS: ASCIIZ "FILLING DEAD ENDS..."
STR_UNITE: ASCIIZ "UNITING THE ROOMS..."
STR_ACTORS: ASCIIZ "PLACING ACTORS..."
.CODE
; DEPRECATED!!!
; @brief Asks for the size of the maze
; Returns Width in X and Height in Y
Get_Size_Maze:
@ -82,32 +87,32 @@ choice_size_maze:
tst_tiny:
cmp #$C1
bne tst_small
ldx #20
ldy #20
ldx #LEVELSIZE::TINY
ldy #LEVELSIZE::TINY
rts
tst_small:
cmp #$C2
bne tst_medium
ldx #24
ldy #24
ldx #LEVELSIZE::SMALL
ldy #LEVELSIZE::SMALL
rts
tst_medium:
cmp #$C3
bne tst_big
ldx #32
ldy #32
ldx #LEVELSIZE::NORMAL
ldy #LEVELSIZE::NORMAL
rts
tst_big:
cmp #$C4
bne tst_huge
ldx #48
ldy #48
ldx #LEVELSIZE::BIG
ldy #LEVELSIZE::BIG
rts
tst_huge:
cmp #$C5
bne bad_size
ldx #64
ldy #64
ldx #LEVELSIZE::HUGE
ldy #LEVELSIZE::HUGE
rts
bad_size:
PRINT STR_SIZE_MAZE_3
@ -180,25 +185,20 @@ Init_Dimensions_Maze:
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
; @param Uses NextLevel to get the conf
; @return player position in X and Y
.define DST_WORLD World
.define ADDR_TO_PATCH init_world_line + 3
.define NB_ROOMS ZERO_8_2
.define NB_ROOMS ZERO_9_9
Build_Level:
; Filling World with ACTORS::WALL_1
@ -221,6 +221,11 @@ Build_Level:
sta ADDR_TO_PATCH + 1
dey
bne init_world
; patching back for a future execution
lda #<DST_WORLD
sta ADDR_TO_PATCH
lda #>DST_WORLD
sta ADDR_TO_PATCH+1
PRINT STR_ROOMS
lda #MAX_NB_ROOMS+1
@ -248,5 +253,142 @@ Build_Level:
PRINT STR_UNITE
jsr Unite_Rooms
PRINT STR_ACTORS
; the two following defines must be the same as in Place_Actors
.define POS_X ZERO_3 ; ROOM_X in Place_Actors
.define POS_Y ZERO_2_4 ; ROOM_Y in Place_Actors
.define POS_STARDOWN_X ZERO_5_1
.define POS_STARDOWN_Y ZERO_5_2
.define ACTOR ZERO_4_1
.define ACTOR_NB ZERO_4_2
.define CURR_ACTOR_OFFSET ZERO_4_3
.define POS_PLAYER_OFFSET ZERO_4_4
.define LEVEL_CONF_OFFSET ZERO_5_3
.define ADDR_ACTOR ZERO_4_3 ; 2 bytes
lda #0
sta ACTOR
ldx NextLevel
stx FAC1
ldx #SIZEOF_CONF_LEVEL
stx FAC2
jsr mul8 ; A = offset to level conf
txa
sta LEVEL_CONF_OFFSET
clc
adc #7 ; A = offset to pos_player_enter
sta POS_PLAYER_OFFSET
tax
inx
inx ; offset to actors[AA_NB]
loop_actors:
stx CURR_ACTOR_OFFSET
lda Levels, X ; actors[AA_NB]
sta ACTOR_NB
loop_actor_nb:
beq end_loop_actor_nb
ldx ACTOR
lda ActiveActor_Tiles, X
ldx NB_ROOMS
jsr Place_Actors
; save stair down position
lda ACTOR
cmp #eACTORSREACTIVE::AA_STAIRDOWN
bne not_stair_down
lda POS_X
sta POS_STARDOWN_X
lda POS_Y
sta POS_STARDOWN_Y
not_stair_down:
dec ACTOR_NB ; next
jmp loop_actor_nb
end_loop_actor_nb:
ldx CURR_ACTOR_OFFSET
inx
inc ACTOR
ldy ACTOR
cpy #eACTORSREACTIVE::AA_NB
bne loop_actors
; Set the 1st position of the player in the level
ldx POS_PLAYER_OFFSET
lda Levels, X
cmp #$FF
bne not_first_entry
; Very first entrance in the level
lda NextLevel
cmp #0
bne not_first_level
; Special case: first level
; TODO avoid non empty floor...
ldx Rooms+2 ; Rooms[0].x
ldy Rooms+3 ; Rooms[0].y
rts
not_first_level:
ldx POS_STARDOWN_X
ldy POS_STARDOWN_Y
jsr Compute_Maze_Addr
; addr offseted by - witdh_maze to access all tiles with offset
sta ADDR_ACTOR+1
txa
sec
sbc #WIDTH_WORLD
sta ADDR_ACTOR
lda ADDR_ACTOR+1
sbc #0
sta ADDR_ACTOR+1
ldx POS_STARDOWN_X
; NOTE: There is at least one solution, the tile is not surrounded!
; if (World[pos_stair_down.y][pos_stair_down.x - 1] == FLOOR_2)
ldy #(WIDTH_WORLD - 1)
lda (ADDR_ACTOR), Y
cmp #ACTORS::FLOOR_2
bne not_x_minus
ldy POS_STARDOWN_Y
dex
rts
not_x_minus:
; if (World[pos_stair_down.y - 1][pos_stair_down.x] == FLOOR_2)
ldy #0
lda (ADDR_ACTOR), Y
cmp #ACTORS::FLOOR_2
bne not_y_minus
ldy POS_STARDOWN_Y
dey
rts
not_y_minus:
; if (World[pos_stair_down.y + 1][pos_stair_down.x] == FLOOR_2)
ldy #(WIDTH_WORLD * 2)
lda (ADDR_ACTOR), Y
cmp #ACTORS::FLOOR_2
bne not_y_plus
ldy POS_STARDOWN_Y
iny
rts
not_y_plus:
ldy POS_STARDOWN_Y
inx
rts
not_first_entry:
pha ; pos_player_enter.x
inx
lda Levels, X ; pos_player_enter.y
tay
pla
tax
rts
; ldx NB_ROOMS
; lda #ACTORS::STAIR_DOWN
; jsr Place_Actors
; lda #ACTORS::STAIR_UP
; ldx NB_ROOMS
; jsr Place_Actors
rts

View File

@ -14,9 +14,10 @@
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "../memory.inc"
.include "../world.inc"
.include "../random.inc"
.include "../math.inc"
.include "../common.inc"
.include "../world/world.inc"
.export Grow_Maze
@ -30,8 +31,6 @@
; 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

View File

@ -16,8 +16,9 @@
.include "../memory.inc"
.include "../random.inc"
.include "../world.inc"
.include "../math.inc"
.include "../common.inc"
.include "../world/world.inc"
.export Carve_Rooms
.export Connect_Rooms
@ -29,9 +30,6 @@
.import HEIGHT_MAZE
.define TRUE #1
.define FALSE #0
.BSS
; Configration to build rooms

View File

@ -16,3 +16,5 @@
.import Carve_Rooms
.import Connect_Rooms
.define MAX_NB_ROOMS 64 ; MAX_NB_ROOMS *MUST BE* <= 64 and a power of 2

View File

@ -19,9 +19,10 @@
.include "rooms.inc"
.include "maze.inc"
.include "../io/textio.inc"
.include "../world.inc"
.include "../memory.inc"
.include "../math.inc"
.include "../common.inc"
.include "../world/world.inc"
.import World
.import Rooms
@ -45,9 +46,6 @@
.define CPT_Y ZERO_2_6
.define FALSE #0
.define TRUE #1
.define QUEUE_ADDR $4000
@ -361,13 +359,13 @@ Unite_Rooms:
sta address2+9 ; sbc #0
.endmacro
.define DELTA_X ZERO_5_2
.define DELTA_Y ZERO_5_3
.define DELTA_X_2 ZERO_5_5
.define DELTA_Y_2 ZERO_5_6
.define ROOM_Y ZERO_8_1
.define ROOM_X ZERO_8_2
.define D ZERO_3
.define DELTA_X ZERO_9_1
.define DELTA_Y ZERO_9_2
.define DELTA_X_2 ZERO_9_3
.define DELTA_Y_2 ZERO_9_4
.define ROOM_Y ZERO_9_5
.define ROOM_X ZERO_9_6
.define D ZERO_9_7
.define ROOM_FOUND SAVE_X
_Connect_Room:

View File

@ -1,3 +1,20 @@
; Copyright (C) 2020 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"
; nb of bytes to be displayed in DBG_TRACES[0]

View File

@ -14,9 +14,8 @@
; 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/world.inc"
.include "display.inc"
.include "world.inc"
.include "tiles.inc"
.include "math.inc"
.include "memory.inc"

View File

@ -15,7 +15,7 @@
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "world.inc"
.include "world/world.inc"
.include "memory.inc"
.include "math.inc"
.include "monitor.inc"

View File

@ -12,8 +12,8 @@ MEMORY {
HEADER: file = %O, start = %S - 4, size = $0004;
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__;
DATA: file = %O, define = yes, start = $6000, size = $3000;
BSSMEM: file = "", define = no, start = __DATA_LAST__, size = $9600 - __DATA_LAST__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;

View File

@ -14,12 +14,13 @@
; along with this program. If not, see <http://www.gnu.org/licenses/>.
.include "world.inc"
.include "world/level.inc"
.include "world/world.inc"
.include "display.inc"
.include "display_map.inc"
.include "memory.inc"
.include "monitor.inc"
.include "common.inc"
.export game_loop
@ -28,6 +29,7 @@
.import set_view_coords
.import view_refresh
; player
.import player_move
.import player_move_inx
.import player_move_iny
.import player_move_dex
@ -36,6 +38,13 @@
; world
.import world_set_player
; ************
.include "builder/builder.inc"
.import world_init
.import player_init
.import view_init
; ************
.define KEY_UP $C9
.define KEY_LEFT $CA
@ -46,7 +55,6 @@
.CODE
nop ; Main can jump to a wrong game_loop's addr without this nop :/
; ########### GAME ##########
@ -54,23 +62,49 @@
; @brief Main game loop
game_loop:
ldx Player_XY
ldy Player_XY+1
jsr levels_init
jsr world_set_player
jsr set_view_coords
jsr view_refresh
lda #0
sta NextLevel
; 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
level_loop:
jsr level_enter ; Uses NextLevel as level number
jsr key_action
jmp kbd_loop
; *****************
; jsr Build_Level
jsr Display_Map_Init
; ldx Rooms+2 ; Rooms[0].x
; ldy Rooms+3 ; Rooms[0].y
; jsr player_init
jsr world_init
jsr view_init
; *****************
rts
ldx Player_XY
ldy Player_XY+1
jsr world_set_player
jsr set_view_coords
jsr view_refresh
; 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
jsr key_action
lda ExitLevel
cmp TRUE
bne kbd_loop
jsr level_exit
jmp level_loop
rts
; action on key pressed
key_action:
@ -87,16 +121,32 @@ key_action:
rts
move_up:
jsr player_move_dey
ldx Player_XY
ldy Player_XY+1
dey
jsr player_move
; jsr player_move_dey
jmp end_action_move
move_right:
jsr player_move_inx
ldx Player_XY
ldy Player_XY+1
inx
jsr player_move
; jsr player_move_inx
jmp end_action_move
move_down:
jsr player_move_iny
ldx Player_XY
ldy Player_XY+1
iny
jsr player_move
; jsr player_move_iny
jmp end_action_move
move_left:
jsr player_move_dex
ldx Player_XY
ldy Player_XY+1
dex
jsr player_move
; jsr player_move_dex
jmp end_action_move
end_action_move: ; update player/view coordinates and refresh the display
@ -105,6 +155,8 @@ end_action_move: ; update player/view coordinates and refresh the dis
jsr view_refresh
rts
display_map:
jsr Map_Loop
rts

View File

@ -56,43 +56,20 @@ _main:
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 #$55
; sta SEED0
; lda #$67
; sta SEED1
; lda #$8C
; sta SEED2
; lda #$5F
; sta SEED3
;lda #$0
;sta SEED0
;lda #$0
;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 view_init
; Run
jsr game_loop
rts

View File

@ -59,6 +59,17 @@
.define ZERO_8_1 $D6
.define ZERO_8_2 $D7
.define ZERO_9_1 $F0
.define ZERO_9_2 $F1
.define ZERO_9_3 $F2
.define ZERO_9_4 $F3
.define ZERO_9_5 $F4
.define ZERO_9_6 $F5
.define ZERO_9_7 $F6
.define ZERO_9_8 $F7
.define ZERO_9_9 $F8
.define ZERO_9_10 $F9
; ************ I/O ************
.define KEYBD $C000
.define KEYBD_STROBE $C010

View File

@ -14,15 +14,21 @@
; 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 "common.inc"
.include "memory.inc"
.include "monitor.inc"
.include "io/textio.inc"
.include "world/world.inc"
; init the player's structures
.export player_init
; exectutes the tile's reaction and updates the player's position if possible
; Destroys ZEROS_2_1 -> 2_5
.export player_move
; All the following functions returns the new player position:
; x in X and y in Y
; They may be unmodified ;)
@ -41,6 +47,8 @@
.export Player_XY
.import Compute_Maze_Addr
.import Reactions_lsb
.import Reactions_msb
.BSS
@ -64,11 +72,50 @@ player_init:
sty Player_XY+1
rts
; @param X target tile's x
; @param Y target tile's y
; @return TRUE in A if the player can move to the tile, FALE otherwise
.define ADDR_IN_MAZE ZERO_2_1 ; 2 bytes
.define NEW_PLAYER_XY ZERO_2_4 ; 2 bytes
player_move:
stx NEW_PLAYER_XY
sty NEW_PLAYER_XY+1
jsr Compute_Maze_Addr
; get the actor
stx ADDR_IN_MAZE
sta ADDR_IN_MAZE+1
ldy #0
lda (ADDR_IN_MAZE), Y
tax
; get the reaction address
lda Reactions_lsb, X
sta FUNC_REACTION + 1
lda Reactions_msb, X
sta FUNC_REACTION+2
FUNC_REACTION : jsr 0
cmp TRUE
bne end_player_move
ldx NEW_PLAYER_XY
stx Player_XY
ldy NEW_PLAYER_XY+1
sty Player_XY+1
end_player_move:
ldx Player_XY
ldy Player_XY+1
rts
; !!! ALL THE MOVE FUNCTION HAVE TO BE GROUPED TOGHETHER
; AS THERE IS A COMMON RETURN POINT TO WHICH THEY BRANHC (KEEP PC's DISTANCE < 127) !!!
.define ADDR_IN_MAZE ZERO_2_1
player_move_inx:
; test that x+1 is "WALKABLE"

View File

@ -5,6 +5,8 @@
.export Random8
.export Random8_Init
.export Random8_RestoreRandomness
.export Random8_SaveRandomness
.export DBG_SEED
.define TMP RESERVED01
@ -12,10 +14,11 @@
.BSS
.align 256
T0: .res 256
T1: .res 256
T2: .res 256
T3: .res 256
T0: .res 256
T1: .res 256
T2: .res 256
T3: .res 256
T0COPY: .res 256
.CODE
@ -50,7 +53,8 @@ DBG_SEED: .byte 0,0,0,0 ; MUST NOT BE RELOCATED!
; 1024 bytes for the tables
; Speed: JSR RAND takes 94 cycles
;
Random8: CLC ; compute lower 32 bits of:
Random8:
CLC ; compute lower 32 bits of:
LDX SEED0 ; 1664525 * ($100 * SEED1 + SEED0) + 1
LDY SEED1
LDA T0,X
@ -123,3 +127,31 @@ GT1: LDA T0-1,X ; add 1664525 to previous entry to get next entry
BNE GT1
RTS
Random8_RestoreRandomness:
ldx #$FF
restore_loop:
lda T0COPY, X
sta T0, X
dex
bne restore_loop
lda T0COPY, X
sta T0, X
rts
Random8_SaveRandomness:
ldx #$FF
save_loop:
lda T0, X
sta T0COPY, X
dex
bne save_loop
lda T0, X
sta T0COPY, X
rts

View File

@ -4,3 +4,7 @@
.import Random8
.import Random8_Init
.import Random8_RestoreRandomness
.import Random8_SaveRandomness

View File

@ -104,6 +104,40 @@ FLOOR_4:
.byte $D5, $AA, $D5, $AA
.byte $D5, $AA, $D5, $AA
.byte $D5, $AA, $D5, $AA
STAIR_DOWN:
.byte $55, $2A, $55, $2A
.byte $01, $AA, $D4, $00
.byte $01, $8A, $D4, $82
.byte $71, $01, $C0, $82
.byte $71, $79, $00, $00
.byte $71, $79, $3C, $00
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $7F, $7F, $1F
.byte $01, $8A, $95, $A8
STAIR_UP:
.byte $55, $2A, $55, $2A
.byte $71, $7F, $7F, $1F
.byte $71, $79, $D4, $82
.byte $71, $79, $3C, $8A
.byte $71, $79, $3C, $88
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $71, $79, $3C, $1E
.byte $70, $79, $3C, $1E
.byte $70, $79, $3C, $1E
.byte $70, $79, $3C, $1E
.byte $90, $78, $3C, $1E
.byte $D0, $A8, $3C, $1E
.byte $D0, $A0, $94, $1E
WALL_1:
.byte 197, 138, 213, 168
.byte 197, 138, 213, 168
@ -160,4 +194,6 @@ UNKNOWN:
.ALIGN 256
; DON"T FORGET TO UPDATE NB_TILES!!
TILES:
.word PLAYER, FLOOR_1, FLOOR_2, FLOOR_3, FLOOR_4, WALL_1, WALL_2, UNKNOWN
.word PLAYER
.word FLOOR_1, FLOOR_2, FLOOR_3, FLOOR_4, FLOOR_4, FLOOR_4, STAIR_DOWN, STAIR_UP
.word WALL_1, WALL_2, UNKNOWN

View File

@ -18,7 +18,6 @@
.import TILES
.define NB_TILES 8