diff --git a/Makefile b/Makefile index 6cf4de3..a045b02 100644 --- a/Makefile +++ b/Makefile @@ -2,21 +2,22 @@ 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/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/builder/builder.asm src/builder/rooms.asm src/builder/maze.asm src/builder/unite.asm \ + src/actors/reactions.asm src/actors/actors.asm \ src/debug.asm src/display_map.asm \ - src/io/title.asm src/io/textio.asm src/io/gr.asm + src/io/title.asm src/io/textio.asm src/io/gr.asm src/io/files.asm APPLE2_MAP := escape.map APPLE2_CFLAGS := -Oirs -v -t apple2 -vm --cpu 6502 -APPLE2_OUT := bin/escape.a2 +APPLE2_OUT := floppy/ESCAPE -all: directories apple2 - -directories: - mkdir -p bin +all: apple2 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/builder/*.o src/io/*.o src/world/*.o src/actors/*.o gmon.out & rm -r bin/ + rm -f $(APPLE2_MAP) floppy/ESCAPE src/*.o src/builder/*.o src/io/*.o src/world/*.o src/actors/*.o gmon.out + +install: apple2 + ./scripts/add-to-disk.sh $(APPLE_COMMANDER) ./floppy escape.dsk + \ No newline at end of file diff --git a/README.md b/README.md index 9bbca51..6b31981 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,39 @@ -# What is it? +## What is it? -**Escape** (working title) is a homebrew *Rogue-Like** game developped for the Apple II computers. +**Escape** (working title) is a homebrew *Rogue-Like** game developed for the Apple II computers. It is written in assembly and serves two purposes: 1. Be fun 2. Document the proccess of coding for the Apple II on [my blog](https://www.xtof.info): - - [A tile engine for the Apple II](https://www.xtof.info/an-hires-tile-engine-for-the-apple-ii.html) - - [Raycasting a Line of Sight](https://www.xtof.info/appleii-roguelike-line-of-sight.html) - - [Random level generation on Apple II](https://www.xtof.info/random-level-generation-on-apple-ii.html) + - [A tile engine for the Apple II](https://www.xtof.info/an-hires-tile-engine-for-the-apple-ii.html) + - [Raycasting a Line of Sight](https://www.xtof.info/appleii-roguelike-line-of-sight.html) + - [Random level generation on Apple II](https://www.xtof.info/random-level-generation-on-apple-ii.html) -# How to build +## How to build -## Building +### Prerequisites -Just type +* The build process relies on the assembler provided by the [CC65 compiler suite](https://github.com/cc65/cc65). + * Set the environment variable **CC65_HOME** to the root folder of CC65 + * Builds are guaranteed to be successful using version 2.19 (commit 555282497c3ecf8). They should also work with any subsequent versions. +* A makefile compatible with GNU Make is provided. +* [AppleCommander](http://applecommander.sourceforge.net/) is used to produce a disk image that can be loaded in any emulator. Apple Commander requires a Java Runtime. + * Export the variable **APPLE_COMMANDER** to the path of the jar file. - make +### How to build + +```bash +make +``` This will produce *bin/escape.a2* which is a binary executable for Apple's II PRODOS. -## Prerequisite in order to build: +```bash +make install +``` -The [cc65 compiler suite](https://github.com/cc65/cc65), with the environment variable *CC65_HOME* set to its folder +Will produce the executable binary and copy it along with all the required files into the floppy image *escape.dsk* -Tested OK with version V2.16 - Git be772c01 +### How to play -## Prerequisite in order to produce the disk image - -- Java Runtime -- [AppleCommander](http://applecommander.sourceforge.net/) - -## Embedding the Apple II' executable into the disk image - -Run - - scripts/add-to-disk.sh +You can navigate the levels using the IJKL keys and display a map by pressing TAB. diff --git a/assets/tiles.psd b/assets/tiles.psd new file mode 100644 index 0000000..768dc9f Binary files /dev/null and b/assets/tiles.psd differ diff --git a/doc/Doc.md b/doc/Doc.md new file mode 100644 index 0000000..75146a7 --- /dev/null +++ b/doc/Doc.md @@ -0,0 +1,55 @@ +# Documentation + +## Actors + +Actors can be **static** or **dynamic**. +Static actors are immutable while dynamic have a link to their status. Both react to the player's actions. For instance a floor or an opened door will let the player pass, while a table or a monster will block him. Dynamic actors can also have a behavior which can evolute by itself each turn, driven by a finite state machine. + +There can be 128 actors of 128 different kinds in a single level. Actor #0 is always the player. + +As there are immutable, many instances of a static actor can be represented by a single ID, while each instance of a dynamic actor require a unique ID. + +In memory, tiles contain the actor ID, which serves as an offset to render the tile, compute its behavior, and so on. + +## Level generation + +Read [this page](https://www.xtof.info/random-level-generation-on-apple-ii.html) for a presentation of the general principle concerning the random level generation. + +The level configuration is given by the *level.conf* file. + +### LEVELS.CONF + +Description of the levels for the random builder. +All values are 8-bit integers. + +```text +[NB_LEVELS] +# level conf * NB_LEVELS + [NUMBER] + [SIZE] + # number of actors of each types * NB_ACTORS_MAX (128) + [NB_ACTORS] + . + . + . + [NB_ACTORS] +``` + +### STATES + +State of the levels + +```text +"LVLS" +CURRENT_LEVEL 1 byte +NB_LEVELS 1 byte +# level state * NB_LEVELS + "LVL" + VISITED 1 byte + PLAYER_TILE 1 byte + LAYOUT 4096 bytes +"ACTS" +# actor state * NB_LEVELS + "ACT" + STATE sizeof(actor_t) +``` diff --git a/escape.dsk b/escape.dsk index 19b2a12..086abf1 100644 Binary files a/escape.dsk and b/escape.dsk differ diff --git a/floppy/ESCAPE b/floppy/ESCAPE new file mode 100644 index 0000000..8740b08 Binary files /dev/null and b/floppy/ESCAPE differ diff --git a/floppy/LEVELS.ACTS b/floppy/LEVELS.ACTS new file mode 100644 index 0000000..3977f89 Binary files /dev/null and b/floppy/LEVELS.ACTS differ diff --git a/floppy/LEVELS.CONF b/floppy/LEVELS.CONF new file mode 100644 index 0000000..fb09e93 Binary files /dev/null and b/floppy/LEVELS.CONF differ diff --git a/floppy/STATES b/floppy/STATES new file mode 100644 index 0000000..9393d80 Binary files /dev/null and b/floppy/STATES differ diff --git a/scripts/add-to-disk.sh b/scripts/add-to-disk.sh index 29d4b90..4e755d7 100644 --- a/scripts/add-to-disk.sh +++ b/scripts/add-to-disk.sh @@ -6,7 +6,7 @@ set -e if (( $# != 3 )); then echo "Bad number of arguments" - echo "usage: add_to_disk.sh PATH_TO_APPLECOMMANDER.jar PATH_TO_BINARY.a2 PATH_TO_DISK" + echo "usage: add_to_disk.sh PATH_TO_APPLECOMMANDER.jar PATH_TO_FLOPPYDIR PATH_TO_DISK" exit fi @@ -17,9 +17,15 @@ fi echo " . removing previous instance of ESCAPE from the disk" java -jar ${1} -d ${3} ESCAPE java -jar ${1} -d ${3} ESCAPE.SYSTEM +java -jar ${1} -d ${3} LEVELS.CONF +java -jar ${1} -d ${3} LEVELS.ACTS +java -jar ${1} -d ${3} STATES -echo " .. adding ESCAPE and its loader to the disk" -java -jar ${1} -cc65 ${3} ESCAPE BIN < ${2} +echo " .. adding files to the disk" +java -jar ${1} -as ${3} ESCAPE BIN < ${2}/ESCAPE java -jar ${1} -p ${3} ESCAPE.SYSTEM SYS < ${CC65_HOME}/target/apple2/util/loader.system +java -jar ${1} -p ${3} LEVELS.CONF BIN < ${2}/LEVELS.CONF +java -jar ${1} -p ${3} LEVELS.ACTS BIN < ${2}/LEVELS.ACTS +java -jar ${1} -p ${3} STATES BIN < ${2}/STATES echo "DONE." diff --git a/src/actors/actors.asm b/src/actors/actors.asm new file mode 100644 index 0000000..a9644a6 --- /dev/null +++ b/src/actors/actors.asm @@ -0,0 +1,185 @@ +.include "../common.inc" +.include "../random.inc" +.include "../memory.inc" +.include "../math.inc" +.include "../world/world.inc" +.include "actors.inc" + +.import Rooms +.import World +.import Compute_Maze_Addr + +.export ActorsInLevel +.export ActorPositions +.export ActorStates +.export ActorTypes +.export ActorTransparent + + +.BSS + +; struc actors_t { + .align 256 +ActorsInLevel: + ; aligned 256 + ActorPositions: .res 256 ; coords_t positions[NB_ACTORS_MAX]; + ; aligned 256 + ActorStates: .res 256 ; actor_state_t* states[NB_ACTORS_MAX]; + ; aligned 256 + ActorTypes: .res 128 ; uint8_t types[NB_ACTORS_MAX]; +; } +; NOTE: Modify SIZEOF_ACTORS_T if necessary!! + +.RODATA + +.align 256 +ActorTransparent: ; NB_ACTORS_MAX +; player +.byte TRUE +; floors +.byte TRUE, TRUE, TRUE, TRUE, TRUE, TRUE +; walls +.byte FALSE, FALSE, FALSE, FALSE +; stair down +.byte TRUE +; stair up +.byte FALSE +; monsters +.byte TRUE, TRUE, TRUE +; others +.byte TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE +.byte TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE +.byte TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE +.byte TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE +.byte TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE +.byte TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE +.byte TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE + +.CODE + +; code +.export Place_Actors +.export Actors_Init + +Actors_Init: + + ; positions + ldx #(2*NB_ACTORS_MAX - 1) + lda #UNDEF +loop_actors_pos_init: + sta ActorPositions, x + dex + bne loop_actors_pos_init + + ; types + ldx #eACTORTYPES::LAST_STATIC +loop_actors_types_init: + txa + sta ActorTypes, X + dex + bne loop_actors_types_init + ldx #eACTORTYPES::LAST_MONSTER+1 +loop_actors_types_init_2: + txa + sta ActorTypes, X + inx + cpx #eACTORTYPES::NB_ACTORS + bne loop_actors_types_init_2 + + rts + + + +.define PTR_ROOM ZERO_2_1 ; 2 bytes +.define PTR_TILE ZERO_2_1 ; 2 bytes +; the two following defines must be the same as in Build_Level +.define ROOM_X ZERO_3 +.define ROOM_Y ZERO_2_4 +.define ROOM_W ZERO_2_5 +.define ROOM_H ZERO_2_6 + +; parameters: +.define NB_ROOMS ZERO_9_9 +.define ACTOR_ID ZERO_9_1 +.define ACTOR_TYPE ZERO_9_2 +Place_Actors: + +loop_find_location: + + jsr Random8 + ldx NB_ROOMS + jsr Modulus + + ; sizeof(room_t) == 4 + asl + asl + clc + adc #Rooms + sta PTR_ROOM+1 + + ldy #0 + lda (PTR_ROOM), Y + sta ROOM_H + iny + lda (PTR_ROOM), Y + sta ROOM_W + iny + lda (PTR_ROOM), Y + sta ROOM_X + iny + lda (PTR_ROOM), Y + sta ROOM_Y + + ; x = room->x + rand() % (room->width - 2) + 1; + sec + lda ROOM_W + sbc #2 + sta ROOM_W + jsr Random8 + ldx ROOM_W + jsr Modulus + clc + adc ROOM_X + adc #1 + sta ROOM_X + + ; y = room->y + rand() % (room->height - 2) + 1; + sec + lda ROOM_H + sbc #2 + sta ROOM_H + jsr Random8 + ldx ROOM_H + jsr Modulus + clc + adc ROOM_Y + adc #1 + sta ROOM_Y + tay + + ldx ROOM_X + jsr Compute_Maze_Addr + stx PTR_TILE + sta PTR_TILE+1 + ldy #0 + lda (PTR_TILE), Y + cmp #eACTORTYPES::FLOOR_2 + bne loop_find_location + + ; save position + ldx ACTOR_ID + lda ROOM_X + sta ActorPositions, X + lda ROOM_Y + sta ActorPositions+1, X + ; save type + lda ACTOR_TYPE + sta ActorTypes, X + + txa + sta (PTR_TILE), Y + + rts \ No newline at end of file diff --git a/src/actors/actors.inc b/src/actors/actors.inc new file mode 100644 index 0000000..782ab5c --- /dev/null +++ b/src/actors/actors.inc @@ -0,0 +1,46 @@ + + +.define NB_ACTORS_MAX 128 +.define SIZEOF_ACTORS_T 256+256+128 + +.enum eACTORTYPES + + PLAYER = 0 ; PLAYER MUST ALWAYS BE 0 + ; STATIC ACTORS + ; FLOOR + FLOOR_1 = 1 + FLOOR_2 ; FLOOR BY DEFAULT + FLOOR_3 + FLOOR_4 + FLOOR_5 + FLOOR_6 + LAST_FLOOR = FLOOR_6 + ; WALLS + WALL_1 + WALL_2 + WALL_3 + WALL_4 + LAST_STATIC = WALL_4 + + ; DYNAMIC ACTORS + STAIR_DOWN ; 11 + FIRST_DYNAMIC = STAIR_DOWN + STAIR_UP + + ; ITEMS + MAP ; 13 + + ; MONSTERS + RAT ; 14 + FIRST_MONSTER = RAT + TARENTULA + SERPENT + LAST_MONSTER = SERPENT ;16 + + NB_ACTORS = 127 + UNKNOWN = NB_ACTORS + +.endenum + + + diff --git a/src/actors/reactions.asm b/src/actors/reactions.asm index b64e379..6dd583b 100644 --- a/src/actors/reactions.asm +++ b/src/actors/reactions.asm @@ -13,7 +13,7 @@ ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . - +.include "actors.inc" .include "../world/level.inc" .include "../io/textio.inc" .include "../common.inc" @@ -22,20 +22,39 @@ .export Reactions_msb .export ReactionStairUp .export ReactionStairDown +.export ReactionMap + +.import ActorPositions +.import World_PickedObject .DATA -STR_REATION_WALL: ASCIIZ "YOU HIT A WALL" -STR_REATION_STAIR_UP: ASCIIZ "YOU GO UPSTAIRS TO THE PREVIOUS LEVEL" -STR_REATION_STAIR_DOWN: ASCIIZ "YOU GO DOWNSTAIRS TO THE NEXT LEVEL" +STR_REACTION_WALL: ASCIIZ "YOU HIT A WALL" +STR_REACTION_STAIR_UP: ASCIIZ "YOU GO UPSTAIRS TO TO THE NEXT LEVEL" +STR_REACTION_STAIR_DOWN: ASCIIZ "YOU GO DOWNSTAIRS THE PREVIOUS LEVEL" +STR_REACTION_MAP: ASCIIZ "YOU FOUND A MAP!" +STR_REACTION_RAT: ASCIIZ "YOU ATTACK THE RAT" +STR_REACTION_SPIDER: ASCIIZ "YOU ATTACK THE SPIDER" +STR_REACTION_SERPENT: ASCIIZ "YOU ATTACK THE SERPENT" .align 256 ; functions address seperated in LSB / MSB to use the same X/Y offset +; They must be in the very same order as the actor's types Reactions_lsb: -.byte 0, ReactionFloor, >ReactionFloor, >ReactionFloor, >ReactionFloor, >ReactionFloor, >ReactionFloor, >ReactionStairDown -.byte >ReactionStairUp, >ReactionWall, >ReactionWall, >ReactionWall, >ReactionWall, 0, 0, 0 -.byte 0, 0, 0, 0, 0, 0, 0, 0 +; player +.byte 0 +; floors +.byte >ReactionFloor, >ReactionFloor, >ReactionFloor, >ReactionFloor, >ReactionFloor, >ReactionFloor +; walls +.byte >ReactionWall, >ReactionWall, >ReactionWall, >ReactionWall +; stairs +.byte >ReactionStairDown, >ReactionStairUp +; items +.byte >ReactionMap +; monsters +.byte >ReactionRat, >ReactionSpider, >ReactionSerpent + ; others .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 @@ -99,35 +129,70 @@ Reactions_msb: .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 +.byte 0, 0, 0, 0, 0, 0, 0 .CODE + ReactionFloor: - lda TRUE + lda #TRUE rts ReactionWall: - PRINT STR_REATION_WALL - lda FALSE + PRINT STR_REACTION_WALL + lda #FALSE rts ReactionStairUp: - PRINT STR_REATION_STAIR_UP + PRINT STR_REACTION_STAIR_UP lda CurrentLevel sta NextLevel inc NextLevel - lda TRUE + lda #TRUE sta ExitLevel - lda FALSE + lda #FALSE rts ReactionStairDown: - PRINT STR_REATION_STAIR_DOWN + PRINT STR_REACTION_STAIR_DOWN lda CurrentLevel sta NextLevel dec NextLevel - lda TRUE + lda #TRUE sta ExitLevel - lda FALSE + lda #FALSE + rts + +; @param actor_id in X +ReactionMap: + + ; index of &ActorPositions[actor_id] + txa + asl + tax + lda #UNDEF + sta ActorPositions, X + sta ActorPositions+1, X + + PRINT STR_REACTION_MAP + + lda #TRUE + sta World_PickedObject + + rts + +ReactionRat: + PRINT STR_REACTION_RAT + lda #FALSE + rts + +ReactionSpider: + PRINT STR_REACTION_SPIDER + lda #FALSE + rts + +ReactionSerpent: + PRINT STR_REACTION_SERPENT + lda #FALSE rts diff --git a/src/builder/actors.asm b/src/builder/actors.asm deleted file mode 100644 index 804b532..0000000 --- a/src/builder/actors.asm +++ /dev/null @@ -1,107 +0,0 @@ -.include "../common.inc" -.include "../random.inc" -.include "../memory.inc" -.include "../math.inc" -.include "../world/world.inc" -.include "actors_private.inc" - -.import Rooms -.import World -.import Compute_Maze_Addr - -; code -.export Place_Actors -; data -.export ActiveActor_Tiles - -.DATA - -ActiveActor_Tiles: .byte ACTORS::STAIR_UP, ACTORS::STAIR_DOWN, ACTORS::FLOOR_1 ; DEBUg: placeholder for future map -.CODE - -.define PTR_ROOM ZERO_2_1 ; 2 bytes -.define PTR_TILE ZERO_2_1 ; 2 bytes -; the two following defines must be the same as in Build_Level -.define ROOM_X ZERO_3 -.define ROOM_Y ZERO_2_4 -.define ROOM_W ZERO_2_5 -.define ROOM_H ZERO_2_6 -.define NB_ROOMS ZERO_9_9 -.define ACTOR ZERO_9_10 -; A : ACTOR -; X : NB_ROOMS -Place_Actors: - - sta ACTOR - stx NB_ROOMS - -loop_find_location: - - jsr Random8 - ldx NB_ROOMS - jsr Modulus - - ; sizeof(room_t) == 4 - asl - asl - clc - adc #Rooms - sta PTR_ROOM+1 - - ldy #0 - lda (PTR_ROOM), Y - sta ROOM_H - iny - lda (PTR_ROOM), Y - sta ROOM_W - iny - lda (PTR_ROOM), Y - sta ROOM_X - iny - lda (PTR_ROOM), Y - sta ROOM_Y - - ; x = room->x + rand() % (room->width - 2) + 1; - sec - lda ROOM_W - sbc #2 - sta ROOM_W - jsr Random8 - ldx ROOM_W - jsr Modulus - clc - adc ROOM_X - adc #1 - sta ROOM_X - - ; y = room->y + rand() % (room->height - 2) + 1; - sec - lda ROOM_H - sbc #2 - sta ROOM_H - jsr Random8 - ldx ROOM_H - jsr Modulus - clc - adc ROOM_Y - adc #1 - sta ROOM_Y - tay - - ldx ROOM_X - jsr Compute_Maze_Addr - stx PTR_TILE - sta PTR_TILE+1 - ldy #0 - lda (PTR_TILE), Y - cmp #ACTORS::FLOOR_2 - bne loop_find_location - - - lda ACTOR - sta (PTR_TILE), Y - - rts \ No newline at end of file diff --git a/src/builder/actors.inc b/src/builder/actors.inc index 2103e95..0fe6cb6 100644 --- a/src/builder/actors.inc +++ b/src/builder/actors.inc @@ -1,7 +1,32 @@ -.include "actors_private.inc" +.define NB_ACTORS_MAX 128 -; code -.import Place_Actors -; data -.import ActiveActor_Tiles + +.enum ACTORS + + PLAYER = 0 + ; FLOOR + FLOOR_1 = 1 + FLOOR_2 ; FLOOR BY DEFAULT + FLOOR_3 + FLOOR_4 + FLOOR_5 + FLOOR_6 + STAIR_DOWN + ; OBJECT + MAP + ; WALLS + STAIR_UP + WALKABLE = STAIR_UP ; Player won't be allowed to go on anything > WALKABLE + + NOT_TRANSPARENT = STAIR_UP + NOT_WALKABLE + + WALL_1 = NOT_WALKABLE + WALL_2 + + UNKNOWN + + NB_ACTORS + +.endenum \ No newline at end of file diff --git a/src/builder/actors_private.inc b/src/builder/actors_private.inc deleted file mode 100644 index d262bf6..0000000 --- a/src/builder/actors_private.inc +++ /dev/null @@ -1,7 +0,0 @@ -; @brief All kind of reactive actors that can be in a level -.enum eACTORSREACTIVE - AA_STAIRUP = 0 - AA_STAIRDOWN - AA_MAP - AA_NB -.endenum diff --git a/src/builder/builder.asm b/src/builder/builder.asm index d77316b..6735415 100644 --- a/src/builder/builder.asm +++ b/src/builder/builder.asm @@ -20,7 +20,8 @@ .include "rooms.inc" .include "maze.inc" .include "unite.inc" -.include "actors.inc" +.include "../common.inc" +.include "../actors/actors.inc" .include "../io/textio.inc" .include "../math.inc" .include "../monitor.inc" @@ -28,12 +29,15 @@ .include "../world/world.inc" .include "../world/level.inc" -.import World +; code .import Random8 .import Grow_Maze ; to patch .import Compute_Maze_Addr +.import Place_Actors +; data +.import World +.import Tile_player_standing_actor -.export Get_Size_Maze .export Init_Dimensions_Maze .export Build_Level @@ -69,56 +73,11 @@ 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: - - ; 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 #LEVELSIZE::TINY - ldy #LEVELSIZE::TINY - rts - tst_small: - cmp #$C2 - bne tst_medium - ldx #LEVELSIZE::SMALL - ldy #LEVELSIZE::SMALL - rts - tst_medium: - cmp #$C3 - bne tst_big - ldx #LEVELSIZE::NORMAL - ldy #LEVELSIZE::NORMAL - rts - tst_big: - cmp #$C4 - bne tst_huge - ldx #LEVELSIZE::BIG - ldy #LEVELSIZE::BIG - rts - tst_huge: - cmp #$C5 - bne bad_size - ldx #LEVELSIZE::HUGE - ldy #LEVELSIZE::HUGE - 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 @@ -198,15 +157,18 @@ Init_Dimensions_Maze: ; @return player position in X and Y .define DST_WORLD World .define ADDR_TO_PATCH init_world_line + 3 -.define NB_ROOMS ZERO_9_9 +.define NB_ROOMS ZERO_9_9 ; use same location as Place_Actors Build_Level: - ; Filling World with ACTORS::WALL_1 + lda #UNDEF + sta Tile_player_standing_actor + + ; Filling World with eACTORTYPES::WALL_1 ldy #HEIGHT_WORLD init_world: ldx #0 init_world_line: - lda #ACTORS::WALL_1 + lda #eACTORTYPES::WALL_1 sta DST_WORLD, x inx cpx #WIDTH_WORLD @@ -225,20 +187,21 @@ Build_Level: lda #DST_WORLD - sta ADDR_TO_PATCH+1 + sta ADDR_TO_PATCH+1 PRINT STR_ROOMS + lda #MAX_NB_ROOMS+1 jsr Carve_Rooms sta NB_ROOMS - lda #ACTORS::FLOOR_1 - jsr _build_fences + lda #eACTORTYPES::FLOOR_1 + jsr _build_fences PRINT STR_MAZE jsr Grow_Maze - lda #ACTORS::WALL_1 + lda #eACTORTYPES::WALL_1 jsr _build_fences PRINT STR_DOORS @@ -252,50 +215,51 @@ 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 + .define ACTOR_ID ZERO_9_1 ; use same location as Place_Actors + .define ACTOR_TYPE ZERO_9_2 ; use same location as Place_Actors + .define CURR_ACTOR_OFFSET ZERO_4_3 + .define ADDR_LEVEL_CONF ZERO_5_3 ; 2 bytes + .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 + ; place actors + PRINT STR_ACTORS + ; offset to level conf + + lda NextLevel + jsr level_get_config_offset + pha 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] + txa + adc #LevelConfigs + sta ADDR_LEVEL_CONF+1 + lda #eACTORTYPES::LAST_STATIC + 1 ; 1st dynamic actor id + sta ACTOR_ID + sta ACTOR_TYPE + tay + iny + iny ; offset to actors[ACTOR_ID] in level conf + loop_actors: ; loop over actors from conf + sty CURR_ACTOR_OFFSET + lda (ADDR_LEVEL_CONF), Y sta ACTOR_NB - loop_actor_nb: - beq end_loop_actor_nb + loop_actor_id: + beq end_loop_actor_id - ldx ACTOR - lda ActiveActor_Tiles, X - ldx NB_ROOMS - jsr Place_Actors + jsr Place_Actors ; save stair down position - lda ACTOR - cmp #eACTORSREACTIVE::AA_STAIRDOWN + lda ACTOR_TYPE + cmp #eACTORTYPES::STAIR_DOWN bne not_stair_down lda POS_X sta POS_STARDOWN_X @@ -303,31 +267,29 @@ Build_Level: sta POS_STARDOWN_Y not_stair_down: + inc ACTOR_ID dec ACTOR_NB ; next - jmp loop_actor_nb - end_loop_actor_nb: + lda ACTOR_NB + jmp loop_actor_id + end_loop_actor_id: - ldx CURR_ACTOR_OFFSET - inx - inc ACTOR - ldy ACTOR - cpy #eACTORSREACTIVE::AA_NB + ldy CURR_ACTOR_OFFSET + iny + inc ACTOR_TYPE + lda ACTOR_TYPE + cmp #(NB_ACTORS_MAX-1) 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 + ; offset to level state + 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 @@ -346,7 +308,7 @@ Build_Level: ; 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 + cmp #eACTORTYPES::FLOOR_2 bne not_x_minus ldy POS_STARDOWN_Y dex @@ -355,7 +317,7 @@ Build_Level: ; if (World[pos_stair_down.y - 1][pos_stair_down.x] == FLOOR_2) ldy #0 lda (ADDR_ACTOR), Y - cmp #ACTORS::FLOOR_2 + cmp #eACTORTYPES::FLOOR_2 bne not_y_minus ldy POS_STARDOWN_Y dey @@ -364,7 +326,7 @@ Build_Level: ; 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 + cmp #eACTORTYPES::FLOOR_2 bne not_y_plus ldy POS_STARDOWN_Y iny @@ -372,23 +334,6 @@ Build_Level: 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 diff --git a/src/builder/builder.inc b/src/builder/builder.inc index bf6e858..ef779a6 100644 --- a/src/builder/builder.inc +++ b/src/builder/builder.inc @@ -13,7 +13,6 @@ ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . -.import Get_Size_Maze .import Init_Dimensions_Maze .import Build_Level .import Rooms \ No newline at end of file diff --git a/src/builder/maze.asm b/src/builder/maze.asm index 1c1f80f..4e33b63 100644 --- a/src/builder/maze.asm +++ b/src/builder/maze.asm @@ -18,6 +18,7 @@ .include "../math.inc" .include "../common.inc" .include "../world/world.inc" +.include "../actors/actors.inc" .export Grow_Maze @@ -121,7 +122,7 @@ .macro ISWALKABLE offset ldy offset lda (PTR_NEW_TILE),Y - cmp #ACTORS::WALKABLE+1 + cmp #eACTORTYPES::LAST_FLOOR+1 bcc cannot_carve .endmacro @@ -139,27 +140,27 @@ ldy OFFSET_NIL lda (PTR_NEW_TILE),Y - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR bcc end_loop_stack ldy OFFSET_UP lda (PTR_NEW_TILE),Y - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR bcc end_loop_stack ldy OFFSET_RIGHT lda (PTR_NEW_TILE),Y - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR bcc end_loop_stack ldy OFFSET_DOWN lda (PTR_NEW_TILE),Y - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR bcc end_loop_stack ldy OFFSET_LEFT lda (PTR_NEW_TILE),Y - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR bcc end_loop_stack .endmacro @@ -194,7 +195,7 @@ loop_grow_maze: ; carve ldy #WIDTH_WORLD - lda #ACTORS::FLOOR_1 + lda #eACTORTYPES::FLOOR_1 sta (PTR_NEW_TILE),Y @@ -236,7 +237,7 @@ loop_grow_maze: carve_the_tile: ; carve the tile ldy #0 - lda #ACTORS::FLOOR_1 + lda #eACTORTYPES::FLOOR_1 sta (PTR_NEW_TILE),Y jmp loop_stack end_loop_stack: @@ -438,7 +439,7 @@ _follow_dead_end: loop_follow: ldy #WIDTH_WORLD - lda #ACTORS::WALL_1 + lda #eACTORTYPES::WALL_1 sta (PTR_TILE), Y lda PTR_NEXT_TILE @@ -462,7 +463,7 @@ _follow_dead_end: rts -.define ADD_FACTOR ZERO_4_1 +.define ADD_FACTOR ZERO_4_3 ; 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 @@ -474,7 +475,7 @@ _is_tile_dead_end: sty ADD_FACTOR ; Returns if the tile is a wall - lda #ACTORS::WALKABLE + lda #eACTORTYPES::LAST_FLOOR cmp (PTR_TILE), Y bcc end_tst_up_tile diff --git a/src/builder/rooms.asm b/src/builder/rooms.asm index f91942d..a9c254c 100644 --- a/src/builder/rooms.asm +++ b/src/builder/rooms.asm @@ -19,6 +19,7 @@ .include "../math.inc" .include "../common.inc" .include "../world/world.inc" +.include "../actors/actors.inc" .export Carve_Rooms .export Connect_Rooms @@ -33,6 +34,7 @@ .BSS ; Configration to build rooms +; FIXME??? CA65 will locate this struct at address 0 !!! .struct Config_Room width_min .byte width_max .byte @@ -73,18 +75,17 @@ Carve_Rooms: lda NB_ROOMS_OK ; NB_ROOMS_OK*sizeof(room_t) -> X asl asl - tax + tax jsr _Build_Room lda NB_ROOMS_OK jsr _Is_intersecting - cmp TRUE ; not intersecting with another room? + cmp #TRUE ; not intersecting with another room? beq loop_rooms - + inc NB_ROOMS_OK - clc - bcc loop_rooms + jmp loop_rooms end_loop_rooms: @@ -106,8 +107,7 @@ Carve_Rooms: end_loop_draw_rooms: - - lda NB_ROOMS_OK + lda NB_ROOMS_OK rts .undefine NB_ATTEMPTS @@ -142,7 +142,7 @@ _Draw_Room: lda Rooms+1, X ; room->width sta LINE_LENGTH loop_draw_line: - lda #ACTORS::FLOOR_1 + lda #eACTORTYPES::FLOOR_1 ldy #0 loop_draw_tile: sta (ADDR_WORLD), Y @@ -272,7 +272,7 @@ _Is_intersecting: cmp #0 bne compare ; first room - lda FALSE + lda #FALSE clc bcc end_intersecting ; branch always @@ -308,7 +308,7 @@ compare: 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 + lda #TRUE ; return value clc bcc end_intersecting @@ -320,7 +320,7 @@ compare: dec NB_ROOMS bne loop_intersecting - lda FALSE ; no room intersects + lda #FALSE ; no room intersects end_intersecting: rts @@ -554,7 +554,7 @@ Connect_Rooms: bcc loop_first_door ; nb_walkable < 2 inc NB_DOORS ldy #WIDTH_WORLD - lda #ACTORS::FLOOR_1 + lda #eACTORTYPES::FLOOR_1 sta (PTR_TILE), Y ; # Opening the other doors @@ -597,7 +597,7 @@ Connect_Rooms: bcc loop_other_doors ; always jump as the previous bcs failed carve_a_door: ldy #WIDTH_WORLD - lda #ACTORS::FLOOR_1 + lda #eACTORTYPES::FLOOR_1 sta (PTR_TILE), Y inc NB_DOORS jmp loop_other_doors @@ -621,7 +621,7 @@ Connect_Rooms: _nb_walkable: lda #0 sta NB_WALKABLE - lda #ACTORS::FLOOR_1 + lda #eACTORTYPES::FLOOR_1 tst_up: ldy #0 cmp (PTR_TILE), Y diff --git a/src/builder/unite.asm b/src/builder/unite.asm index d7834fe..52ee108 100644 --- a/src/builder/unite.asm +++ b/src/builder/unite.asm @@ -23,6 +23,7 @@ .include "../math.inc" .include "../common.inc" .include "../world/world.inc" +.include "../actors/actors.inc" .import World .import Rooms @@ -33,9 +34,7 @@ .export Unite_Rooms -.BSS -.DATA .CODE @@ -62,7 +61,7 @@ _Flood_Fill : ldy #0 cmp (PTR_TILE), Y ; if (*ptr_tile != replaced) return; beq fill_1 - lda FALSE + lda #FALSE rts fill_1: @@ -114,7 +113,7 @@ fill_1: lda FILL_NR sta (PTR_TILE_LOCAL),Y ; *(++ptr_queue) = tile_w - ADD16 PTR_QUEUE, #2 + ADD16 PTR_QUEUE, #2, #0 clc lda #1 adc PTR_TILE_LOCAL @@ -136,7 +135,7 @@ fill_1: lda FILL_NR sta (PTR_TILE_LOCAL),Y ; *(++ptr_queue) = tile_tile_east - ADD16 PTR_QUEUE, #2 + ADD16 PTR_QUEUE, #2, #0 sec lda PTR_TILE_LOCAL sbc #1 @@ -157,7 +156,7 @@ fill_1: lda FILL_NR sta (PTR_TILE_LOCAL),Y ; *(++ptr_queue) = tile_tile_north - ADD16 PTR_QUEUE, #2 + ADD16 PTR_QUEUE, #2, #0 sec lda PTR_TILE_LOCAL sbc #WIDTH_WORLD @@ -178,7 +177,7 @@ fill_1: lda FILL_NR sta (PTR_TILE_LOCAL),Y ; *(++ptr_queue) = tile_tile_south - ADD16 PTR_QUEUE, #2 + ADD16 PTR_QUEUE, #2, #0 clc lda #WIDTH_WORLD adc PTR_TILE_LOCAL @@ -194,7 +193,7 @@ fill_1: end_fill: - lda TRUE + lda #TRUE rts @@ -202,7 +201,7 @@ end_fill: .define ROOM_NR ZERO_3 .define SAVE_X ZERO_4_1 .define PTR_ROOM ZERO_4_2 ; 2 bytes -.define ZONE_0 ACTORS::FLOOR_1 ; 1st useful zone: ZONE_1 +.define ZONE_0 eACTORTYPES::FLOOR_1 ; 1st useful zone: ZONE_1 Unite_Rooms: ; *** flood fill room to identify separated zones *** @@ -226,13 +225,13 @@ Unite_Rooms: ldx ZONE_NR lda #ZONE_0 jsr _Flood_Fill - cmp TRUE + cmp #TRUE bne loop_flood_next inc ZONE_NR loop_flood_next: ;next tile - ADD16 PTR_TILE, #1 + ADD16 PTR_TILE, #1, #0 ; end line? inc CPT_X ldx CPT_X @@ -241,7 +240,7 @@ Unite_Rooms: ldx #0 stx CPT_X ; next - ADD16 PTR_TILE, #1 + ADD16 PTR_TILE, #1, #0 ; the end? inc CPT_Y ldy CPT_Y @@ -460,7 +459,7 @@ _Connect_Room: while_1: ; ptr_room += ix patch_ix1: - ADD16 PTR_ROOM, #1 + ADD16 PTR_ROOM, #1, #0 ; d += dy2 clc lda DELTA_Y_2 @@ -474,7 +473,7 @@ _Connect_Room: lda (PTR_ROOM), Y ; Y = 0 cmp ZONE_NR beq continue_1a - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR beq end bpl continue_1a jmp end @@ -484,7 +483,7 @@ _Connect_Room: sta (PTR_ROOM), Y ; Y = 0 ; ptr_room += iy patch_iy1: - ADD16 PTR_ROOM, #WIDTH_WORLD + ADD16 PTR_ROOM, #WIDTH_WORLD, #0 ; d -= dx2 sec lda D @@ -495,7 +494,7 @@ _Connect_Room: lda (PTR_ROOM), Y ; Y = 0 cmp ZONE_NR beq continue_1b - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR beq end bpl continue_1b jmp end @@ -517,7 +516,7 @@ _Connect_Room: while_2: ; ptr_room += iy patch_iy2: - ADD16 PTR_ROOM, #WIDTH_WORLD + ADD16 PTR_ROOM, #WIDTH_WORLD, #0 ; d += dx2 clc lda DELTA_X_2 @@ -531,7 +530,7 @@ _Connect_Room: lda (PTR_ROOM), Y ; Y = 0 cmp ZONE_NR beq continue_2a - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR beq end bpl continue_2a jmp end @@ -541,7 +540,7 @@ _Connect_Room: sta (PTR_ROOM), Y ; Y = 0 ; ptr_room += ix; patch_ix2: - ADD16 PTR_ROOM, #1 + ADD16 PTR_ROOM, #1, #0 ; d -= dy2 sec lda D @@ -552,7 +551,7 @@ _Connect_Room: lda (PTR_ROOM), Y ; Y = 0 cmp ZONE_NR beq continue_2b - cmp #ACTORS::WALKABLE + cmp #eACTORTYPES::LAST_FLOOR beq end bpl continue_2b jmp end diff --git a/src/common.inc b/src/common.inc index 0393bbf..72ff6c6 100644 --- a/src/common.inc +++ b/src/common.inc @@ -13,5 +13,6 @@ ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . -.define TRUE #1 -.define FALSE #0 +.define TRUE 1 +.define FALSE 0 +.define UNDEF $FF \ No newline at end of file diff --git a/src/display.asm b/src/display.asm index 3e0e191..d65bea2 100644 --- a/src/display.asm +++ b/src/display.asm @@ -15,11 +15,13 @@ ; along with this program. If not, see . .include "world/world.inc" +.include "actors/actors.inc" .include "display.inc" .include "tiles.inc" .include "math.inc" .include "memory.inc" .include "monitor.inc" +.include "common.inc" ; Init the view. To be called before anything else! @@ -44,6 +46,8 @@ .import Compute_Maze_Addr .import World .import Player_XY +.import ActorTransparent +.import ActorTypes .import DBG_TRACE .import DBG_TRACES @@ -97,20 +101,6 @@ 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 @@ -120,7 +110,7 @@ _build_view: lda #0 ldx #(GRID_WIDTH * GRID_HEIGHT - 1) loop_init_view: - lda #ACTORS::UNKNOWN + lda #eACTORTYPES::UNKNOWN sta View_Future,X dex bne loop_init_view @@ -129,7 +119,7 @@ _build_view: ; 2 - Player .define OFFSET_PLAYER_IN_VIEW PLAYER_X+PLAYER_Y*GRID_WIDTH ldx #(OFFSET_PLAYER_IN_VIEW) - lda #ACTORS::PLAYER + lda #eACTORTYPES::PLAYER sta View_Future,X ; 3 - Casting rays @@ -140,6 +130,7 @@ _build_view: .define SRC_TILE_IN_WORLD ZERO_5_2 ; 2 bytes .define PTR_RAY ZERO_5_4 ; 2 bytes .define TMP ZERO_5_6 + .define TMP2 ZERO_7_1 ; loading ptr_rays - 1 as it will be incremented @@ -197,15 +188,21 @@ _build_view: iny sty TMP lda (PTR_RAY),Y ; offset_view - tax + sta TMP2 ldy #0 - lda (SRC_TILE_IN_WORLD),Y - sta View_Future,X + lda (SRC_TILE_IN_WORLD), Y + ; sta View_Future, X ; ptr tile in view future ldy TMP iny - ; break if non-transparent - cmp #ACTORS::NOT_TRANSPARENT - bcs end_loop_ray + ; break if non-transparent + tax + lda ActorTypes, X + ldx TMP2 + sta View_Future, X + tax + lda ActorTransparent, X + cmp #TRUE + bne end_loop_ray ; loop if tiles are left in the ray ldx NB_TILES_IN_RAY_LEFT diff --git a/src/display_map.asm b/src/display_map.asm index 07c6e28..d63cc4a 100644 --- a/src/display_map.asm +++ b/src/display_map.asm @@ -16,10 +16,11 @@ .include "world/world.inc" +.include "actors/actors.inc" +.include "io/gr.inc" .include "memory.inc" .include "math.inc" .include "monitor.inc" -.include "io/gr.inc" ; inits display of map .export Display_Map_Init @@ -201,11 +202,12 @@ quit: rts .import World -.define SRC_LINE_UP ZERO_7_1 +.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 +.define SRC_OFFSET ZERO_5_5 +.define DST_GR1 ZERO_5_5 +.define CPT_FILL ZERO_5_4 +.define TMP ZERO_9_10 Addr_GR1: ; 3 address blocks to fill GR1 (address -1), stored in reversed endianess. .word $4F04, $2704, $FF03 @@ -229,7 +231,7 @@ Addr_GR1: ; 3 address blocks to fill GR1 (address -1), stored in reversed endian ld_src: ; compute offset - stx ZERO_5_4 + stx TMP sty FAC1 lda #WIDTH_WORLD sta FAC2 @@ -237,7 +239,7 @@ ld_src: sta SRC_OFFSET+1 txa clc - adc ZERO_5_4 + adc TMP sta SRC_OFFSET lda SRC_OFFSET+1 adc #0 @@ -277,11 +279,22 @@ copy_8x2_lines: ; call 3 times to fill the screen ldy #DBG_DISP_WIDTH copy_2_lines: lda (SRC_LINE_DOWN),Y + cmp #eACTORTYPES::FIRST_DYNAMIC + bcc keep_color_1 + lda #$F ; white + keep_color_1: asl asl asl - asl - ora (SRC_LINE_UP),Y + asl + sta TMP + lda (SRC_LINE_UP),Y + cmp #eACTORTYPES::FIRST_DYNAMIC + bcc keep_color_2 + lda #$F ; white + keep_color_2: + and #$F + ora TMP sta (DST_GR1), Y dey bne copy_2_lines diff --git a/src/escape.cfg b/src/escape.cfg index 816d3db..b673f25 100644 --- a/src/escape.cfg +++ b/src/escape.cfg @@ -1,27 +1,29 @@ # Configuration: # APPLESOFT required -# HGR1 & HGR2 segment reserved +# HGR1 & HGR2 memory reserved +# CODE2, RODATA and DATA segment are loaded contiguously in the main memory +# but will be run from MAIN2 memory. The program has to do the relocation. FEATURES { - STARTADDRESS: default = $0800; + STARTADDRESS: default = $0803; } SYMBOLS { __EXEHDR__: type = import; + __FILETYPE__: type = weak, value = $0006; # ProDOS file type } MEMORY { - ZP: file = "", start = $0000, size = $00FF; - 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; - CODE2: file = %O, define = yes, start = $6000, size = $100; - DATA: file = %O, define = yes, start = __CODE2_LAST__,size = $3000; - BSSMEM: file = "", define = no, start = __DATA_LAST__, size = $9600 - __DATA_LAST__; + ZP: file = "", start = $0000, size = $00FF; + HEADER: file = %O, start = %S - $3A, size = $003A; + HGR: file = "", define = yes, start = $2000, size = $4000; + MAIN2: file = "", define = yes, start = $6000, size = $3000; + BSSMEM: file = "", define = yes, start = __MAIN2_LAST__, size = $BF00 - __BSSMEM_START__; + MAIN: file = %O, define = yes, start = %S, size = __BSSMEM_START__ - %S - __HGR_SIZE__; } SEGMENTS { - ZEROPAGE: load = ZP, type = zp, optional = yes; - EXEHDR: load = HEADER, type = ro; - CODE: load = MAIN, type = rw; - CODE2: load = CODE2, type = rw, optional = yes; - 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; + ZEROPAGE: load = ZP, type = zp, optional = no; + EXEHDR: load = HEADER, type = ro; + CODE: load = MAIN, type = rw, define = yes; + CODE2: load = MAIN, run = MAIN2, type = rw, define = yes; + RODATA: load = MAIN, run = MAIN2, type = ro, define = yes, align = $100; + DATA: load = MAIN, run = MAIN2, type = rw, define = yes, align = $100; + BSS: load = BSSMEM, type = bss, define = yes, align = $100; } diff --git a/src/game_loop.asm b/src/game_loop.asm index af29d7c..2b6fb75 100644 --- a/src/game_loop.asm +++ b/src/game_loop.asm @@ -13,7 +13,7 @@ ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . - +.include "actors/actors.inc" .include "world/level.inc" .include "world/world.inc" .include "display.inc" @@ -34,23 +34,32 @@ .import player_move_iny .import player_move_dex .import player_move_dey -.import Player_XY +.import ActorPositions ; world .import world_set_player +; actors +.import ActorPositions ; ************ .include "builder/builder.inc" .import world_init .import player_init .import view_init +.import Actors_Init ; ************ -.define KEY_UP $C9 -.define KEY_LEFT $CA -.define KEY_DOWN $CB -.define KEY_RIGHT $CC -.define TAB $89 +.define KEY_UP_UPP $C9 ; 'I' +.define KEY_UP_LOW $E9 ; 'i' +.define KEY_LEFT_UPP $CA ; 'J' +.define KEY_LEFT_LOW $EA ; 'j' +.define KEY_DOWN_UPP $CB ; 'K' +.define KEY_DOWN_LOW $EB ; 'k' +.define KEY_RIGHT_UPP $CC ; 'L' +.define KEY_RIGHT_LOW $EC ; 'l' +.define TAB $89 ; '\t' + +.define Player_XY ActorPositions + eACTORTYPES::PLAYER .CODE @@ -63,24 +72,21 @@ game_loop: jsr levels_init - - lda #0 - sta NextLevel + jsr Actors_Init level_loop: jsr level_enter ; Uses NextLevel as level number - ; ***************** - ; jsr Build_Level - jsr Display_Map_Init - ; ldx Rooms+2 ; Rooms[0].x - ; ldy Rooms+3 ; Rooms[0].y - ; jsr player_init + ; ***************** + jsr Display_Map_Init + + ldx Player_XY + ldy Player_XY + 1 jsr world_init + jsr view_init ; ***************** - ldx Player_XY ldy Player_XY+1 @@ -97,7 +103,7 @@ game_loop: jsr key_action lda ExitLevel - cmp TRUE + cmp #TRUE bne kbd_loop jsr level_exit @@ -108,16 +114,29 @@ game_loop: ; action on key pressed key_action: - cmp #KEY_UP + cmp #KEY_UP_UPP beq move_up - cmp #KEY_RIGHT + cmp #KEY_UP_LOW + beq move_up + + cmp #KEY_RIGHT_UPP beq move_right - cmp #KEY_DOWN + cmp #KEY_RIGHT_LOW + beq move_right + + cmp #KEY_DOWN_UPP beq move_down - cmp #KEY_LEFT + cmp #KEY_DOWN_LOW + beq move_down + + cmp #KEY_LEFT_UPP beq move_left + cmp #KEY_LEFT_LOW + beq move_left + cmp #TAB beq display_map + rts move_up: @@ -125,28 +144,24 @@ move_up: ldy Player_XY+1 dey jsr player_move - ; jsr player_move_dey jmp end_action_move move_right: ldx Player_XY ldy Player_XY+1 inx jsr player_move - ; jsr player_move_inx jmp end_action_move move_down: ldx Player_XY ldy Player_XY+1 iny jsr player_move - ; jsr player_move_iny jmp end_action_move move_left: 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 diff --git a/src/io/files.asm b/src/io/files.asm new file mode 100644 index 0000000..b243486 --- /dev/null +++ b/src/io/files.asm @@ -0,0 +1,481 @@ +; Copyright (C) 2021 Christophe Meneboeuf +; +; 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 . + + +; TODO a lot of code space can be spared by factorizing ReadState and Write state. Almos the same code + + +.include "../actors/actors.inc" +.include "../world/level.inc" +.include "../world/world.inc" +.include "../common.inc" +.include "../memory.inc" +.include "../math.inc" + +.import World +.import ActorsInLevel +.import LevelIsBuilt +.import PlayerTile +.import Tile_player_standing_actor + +; data +; TODO : should remain private!! +.export Str_FileLevelConfs +.export Str_FileLevelsActors +.export Param_FileOpen +.export Param_FileOffset +.export Param_FilesReadWrite +.export File_Buffer + + +; functions +.export ReadFile +.export LoadState +.export SaveState +.export ResetIsBuilt +.export LoadCurrentLevel + +.define TO_PATCH 0 + +; reserve 1024 bytes for MLI file operations in the upper part of HGR2 +File_Buffer := $5C00 + + +.RODATA + +Str_FileLevelConfs: +.byte $19, "/PRODOS.2.4.2/LEVELS.CONF" ; Pascal string +Str_FileLevelsActors: +.byte $19, "/PRODOS.2.4.2/LEVELS.ACTS" ; Pascal string +Str_FileStates: +.byte $14, "/PRODOS.2.4.2/STATES" ; Pascal string + +.BSS + +Lvl_Nr: .res 1 + +.define MIN_READ_SIZE 256 +ReadWriteBuffer: .res MIN_READ_SIZE + +.DATA + +Param_FileOpen: + .byte $3 ; in - nb params + .addr TO_PATCH ; in - char* filepath + .addr File_Buffer ; in - char* workbuffer + Handle_File: + .byte $0 ; out - handle on the file + +Param_FileOffset: + .byte $2 ; in - nb params + .byte TO_PATCH ; in - handle on the file + .byte TO_PATCH, TO_PATCH, 0 ; in - Offset + +Param_FilesReadWrite: + .byte $4 ; in - nb params + .byte TO_PATCH ; in - handle on the file + .addr TO_PATCH ; in - out buffer + .word TO_PATCH ; in - max nb bytes to WRITE/READ + .word $0000 ; out - nb bytes write/read + +Param_FileClose: + .byte $1 ; in - nb params + .byte TO_PATCH ; in - handle on the file + + + +.CODE + +; TODO handle errors +ReadFile: + + ; Open the file + jsr $BF00 ; call MLI +.byte $C8 ; Open +.addr Param_FileOpen + + ; Set read position + lda Handle_File + sta Param_FileOffset+1 + jsr $BF00 ; call MLI +.byte $CE ; Set Mark +.addr Param_FileOffset + + ; Read the file + lda Handle_File + sta Param_FilesReadWrite+1 + jsr $BF00 ; call MLI +.byte $CA ; read +.addr Param_FilesReadWrite + + ; Close the file + lda Handle_File + sta Param_FileClose+1 + jsr $BF00 ; call MLI +.byte $CC ; Close +.addr Param_FileClose + rts + + + +.define READ_DST ZERO_2_4 ; 2 bytes + +; @brief Offset in A:X (little endian) +; HandleFile must have been set by opening the file +_SetOffset: + + sta Param_FileOffset+2 + stx Param_FileOffset+3 + lda Handle_File + sta Param_FileOffset+1 + jsr $BF00 ; call MLI +.byte $CE ; Set Mark +.addr Param_FileOffset + + rts + +; @brief Size in in A:X (little endian) +; Destination ptr in READ_DST: cannot be locate in ZERO PAGE!!! +; HandleFile must have been set by opening the file +_Read: + + ; Read the file + sta Param_FilesReadWrite+4 + stx Param_FilesReadWrite+5 + lda Handle_File + sta Param_FilesReadWrite+1 + lda READ_DST + sta Param_FilesReadWrite+2 + lda READ_DST+1 + sta Param_FilesReadWrite+3 + jsr $BF00 ; call MLI +.byte $CA ; read +.addr Param_FilesReadWrite + + rts + +; @param LevelNr in A +; @return isBuilt in A +; modifies ZERO_2_3, ZERO_2_4, ZERO_2_5 +.define LVLS_HEADER_SIZE 4 +.define LVL_HEADER_SIZE 3 +.define OFFSET Param_FileOffset+2 +; compute offset and sets file position +_FindLevelLayout: + + ; Compute the level state offset in file + ldy #(LVLS_HEADER_SIZE + 2 + LVL_HEADER_SIZE) ; +2: current lvl + nb lvls + sty OFFSET + lda #0 + sta OFFSET+1 + lda Lvl_Nr + tax + cpx #0 + beq end_acc_offset_lvl +acc_offset_lvl: + ADD16 OFFSET, #<(HEIGHT_WORLD * WIDTH_WORLD), #>(HEIGHT_WORLD * WIDTH_WORLD) + ADD16 OFFSET, #(LVL_HEADER_SIZE + 2), #0 ; +2: visited + tile + dex + bne acc_offset_lvl +end_acc_offset_lvl: + + ; Set read position + lda OFFSET + ldx OFFSET+1 + jsr _SetOffset + + rts + + +.define ACTSS_HEADER_SIZE 4; +.define ACT_HEADER_SIZE 3; +_FindLevelActors: + + ; Compute offset + lda #(LVLS_HEADER_SIZE + 2) + sta OFFSET + lda #0 + sta OFFSET+1 + ldx NbLevels +acc_offset_lvls: + ADD16 OFFSET, #<(HEIGHT_WORLD * WIDTH_WORLD), #>(HEIGHT_WORLD * WIDTH_WORLD) + ADD16 OFFSET, #(LVL_HEADER_SIZE + 2), #0 ; +2: visited + tile + dex + bne acc_offset_lvls + ADD16 OFFSET, #(ACTSS_HEADER_SIZE + ACT_HEADER_SIZE), #0 + + ldx Lvl_Nr + cpx #0 + beq end_acc_offset_actors +acc_offset_actors: + ADD16 OFFSET, #<(ACT_HEADER_SIZE + SIZEOF_ACTORS_T), #>(ACT_HEADER_SIZE + SIZEOF_ACTORS_T) + dex + bne acc_offset_actors +end_acc_offset_actors: + + ; Set read position + lda OFFSET + ldx OFFSET+1 + jsr _SetOffset + + rts + +; @param Level NR in A +LoadState: + + sta Lvl_Nr + + ; Open the file + lda #Str_FileStates + sta Param_FileOpen+2 + jsr $BF00 ; call MLI + .byte $C8 ; Open + .addr Param_FileOpen + + ; save the new current level + lda #(LVLS_HEADER_SIZE) + ldx #0 + jsr _SetOffset ; current lvl + lda #Lvl_Nr + sta READ_DST+1 + lda #1 + ldx #0 + jsr _Write + + lda Lvl_Nr + jsr _FindLevelLayout ; compute offset and sets file read position + + lda #ReadWriteBuffer + sta READ_DST+1 + lda #MIN_READ_SIZE + jsr _Read + lda ReadWriteBuffer + sta LevelIsBuilt + lda ReadWriteBuffer+1 + sta Tile_player_standing_actor + + lda LevelIsBuilt + cmp #FALSE + beq LoadState_end + + ; Read the level's layout + ; Set read position + ADD16 OFFSET, #2, #0 ; offset past "visited" & "tile" + lda OFFSET + ldx OFFSET+1 + jsr _SetOffset + ; Read the file + lda #World + sta READ_DST+1 + lda #<(HEIGHT_WORLD * WIDTH_WORLD) + ldx #>(HEIGHT_WORLD * WIDTH_WORLD) + jsr _Read + + ; Read level actors state + jsr _FindLevelActors ; compute offset and sets file read position + ; Read the file + lda #ActorsInLevel + sta READ_DST+1 + lda #<(SIZEOF_ACTORS_T) + ldx #>(SIZEOF_ACTORS_T) + jsr _Read + +LoadState_end: + + ; Close the file + lda Handle_File + sta Param_FileClose+1 + jsr $BF00 ; call MLI +.byte $CC ; Close +.addr Param_FileClose + + rts + + + +.define WRITE_DST ZERO_2_4 ; 2 bytes +; @brief Size in in A:X (little endian) +; Destination ptr in WRITE_DST: cannot be locate in ZERO PAGE!!! +; HandleFile must have been set by opening the file +_Write: + + ; Wr the file + sta Param_FilesReadWrite+4 + stx Param_FilesReadWrite+5 + lda Handle_File + sta Param_FilesReadWrite+1 + lda WRITE_DST + sta Param_FilesReadWrite+2 + lda WRITE_DST+1 + sta Param_FilesReadWrite+3 + jsr $BF00 ; call MLI +.byte $CB ; write +.addr Param_FilesReadWrite + + rts + + +; @param Level NR in A +SaveState: + + sta Lvl_Nr + + ; Open the file + lda #Str_FileStates + sta Param_FileOpen+2 + jsr $BF00 ; call MLI + .byte $C8 ; Open + .addr Param_FileOpen + + lda Lvl_Nr + jsr _FindLevelLayout ; compute offset and sets file write position + + ; Write the file + lda #TRUE + sta ReadWriteBuffer + lda Tile_player_standing_actor + sta ReadWriteBuffer+1 + lda #ReadWriteBuffer + sta WRITE_DST+1 + lda #MIN_READ_SIZE + jsr _Write + + ; Write the level's layout + ; Set write position + ADD16 OFFSET, #2, #0 ; offset past "visited" & "tile" + lda OFFSET + ldx OFFSET+1 + jsr _SetOffset + ; Write the file + lda #World + sta WRITE_DST+1 + lda #<(HEIGHT_WORLD * WIDTH_WORLD) + ldx #>(HEIGHT_WORLD * WIDTH_WORLD) + jsr _Write + + ; Write level actors state + jsr _FindLevelActors ; compute offset and sets file write position + ; Write the file + lda #ActorsInLevel + sta WRITE_DST+1 + lda #<(SIZEOF_ACTORS_T) + ldx #>(SIZEOF_ACTORS_T) + jsr _Write + + ; Close the file + lda Handle_File + sta Param_FileClose+1 + jsr $BF00 ; call MLI +.byte $CC ; Close +.addr Param_FileClose + + rts + +; @param LevelNr in A +ResetIsBuilt: + + sta Lvl_Nr + + ; Open the file + lda #Str_FileStates + sta Param_FileOpen+2 + jsr $BF00 ; call MLI +.byte $C8 ; Open +.addr Param_FileOpen + +for_each_lvl: + dec Lvl_Nr + jsr _FindLevelLayout ; compute offset and sets file write position + inc Lvl_Nr + + lda #FALSE + sta ReadWriteBuffer + lda #ReadWriteBuffer + sta WRITE_DST+1 + lda #MIN_READ_SIZE + jsr _Write + + dec Lvl_Nr + bne for_each_lvl + + ; Close the file + lda Handle_File + sta Param_FileClose+1 + jsr $BF00 ; call MLI +.byte $CC ; Close +.addr Param_FileClose + + rts + + + +LoadCurrentLevel: + + ; Open the file + lda #Str_FileStates + sta Param_FileOpen+2 + jsr $BF00 ; call MLI +.byte $C8 ; Open +.addr Param_FileOpen + + ; load the current level + lda #(LVLS_HEADER_SIZE) + ldx #0 + jsr _SetOffset ; current lvl + lda #ReadWriteBuffer + sta READ_DST+1 + lda #MIN_READ_SIZE + jsr _Read + lda ReadWriteBuffer + sta NextLevel + + ; Close the file + lda Handle_File + sta Param_FileClose+1 + jsr $BF00 ; call MLI +.byte $CC ; Close +.addr Param_FileClose + + rts \ No newline at end of file diff --git a/src/io/files.inc b/src/io/files.inc new file mode 100644 index 0000000..caf1d18 --- /dev/null +++ b/src/io/files.inc @@ -0,0 +1,30 @@ +; Copyright (C) 2021 Christophe Meneboeuf +; +; 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 . + + +; data +; TODO : should remain private!! +.import Str_FileLevelConfs +.import Str_FileLevelsActors +.import Param_FileOpen +.import Param_FileOffset +.import Param_FilesReadWrite + +; functions +.import ReadFile +.import LoadState +.import SaveState +.import ResetIsBuilt +.import LoadCurrentLevel diff --git a/src/io/textio.asm b/src/io/textio.asm index daf19d4..f4d77ee 100644 --- a/src/io/textio.asm +++ b/src/io/textio.asm @@ -151,7 +151,7 @@ Cin_Str: sta TXT1_LINE23, X ; erase the cursor lda #0 sta CIN_STR, X - + rts delete: diff --git a/src/io/title.asm b/src/io/title.asm index f91c13a..e9a2c3a 100644 --- a/src/io/title.asm +++ b/src/io/title.asm @@ -35,17 +35,15 @@ GR_TITLE_09 : .byte $0,$0,$99,$0,$0,$0,$0,$0,$0,$0,$0,$0,$88,$0,$88,$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_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 +GR_TITLE_14 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$55,$55,$55,$0,$0,$55,$55,$55,$55,$55,$55,$0,$55,$55,$55,$55,$55,$55,$0,$55,$55,$55,$55,$55,$0,$0,$0 +GR_TITLE_15 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$0,$0,$0,$0,$55,$0,$0,$0,$0,$0,$0,$55,$0,$55,$0,$0,$0,$0,$0,$0,$55,$0,$0,$0,$0,$55,$0,$0 +GR_TITLE_16 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$55,$55,$55,$55,$55,$0,$55,$55,$55,$55,$55,$55,$0,$55,$55,$55,$55,$0,$0,$0,$55,$55,$55,$55,$55,$0,$0,$0 +GR_TITLE_17 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$0,$0,$0,$0,$55,$0,$55,$0,$0,$0,$0,$0,$0,$55,$0,$0,$0,$0,$0,$0,$55,$0,$0,$0,$0,$0,$0,$0 +GR_TITLE_18 : .byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$55,$0,$0,$0,$0,$55,$0,$55,$55,$55,$55,$55,$55,$0,$55,$0,$0,$0,$0,$0,$0,$55,$0,$0,$0,$0,$0,$0,$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 @@ -102,9 +100,10 @@ Title_Scr_Addr: .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 +; @brief Displays's the title screen and main game menu Title: + ; Title Screen jsr Clear_Gr1 jsr ClearTxt @@ -133,11 +132,4 @@ Title: cpy #$26 bne loop_scrolling - - lda #>STR_NAME - ldx #__MAIN_LAST__ + lda #>__CODE2_LOAD__ sta FROM+1 - lda #<__CODE2_START__ + lda #<__CODE2_RUN__ sta TO - lda #>__CODE2_START__ + lda #>__CODE2_RUN__ sta TO+1 - lda #<(__CODE2_LAST__ - __CODE2_START__) + lda #<__CODE2_SIZE__ sta SIZEL - lda #>(__CODE2_LAST__ - __CODE2_START__) + lda #>__CODE2_SIZE__ sta SIZEH jsr memcpy - - ; Relocate DATA from its freshly loaded location to __DATA_START__ - ; computing DATA actual starting address - lda #<(__MAIN_LAST__ + __CODE2_LAST__ - __CODE2_START__) + ; relocating RODATA + lda #<__RODATA_LOAD__ sta FROM - lda #>(__MAIN_LAST__ + __CODE2_LAST__ - __CODE2_START__) + lda #>__RODATA_LOAD__ sta FROM+1 - lda #<__DATA_START__ + lda #<__RODATA_RUN__ sta TO - lda #>__DATA_START__ + lda #>__RODATA_RUN__ + sta TO+1 + lda #<__RODATA_SIZE__ + sta SIZEL + lda #>__RODATA_SIZE__ + sta SIZEH + jsr memcpy + ; relocating DATA + lda #<__DATA_LOAD__ + sta FROM + lda #>__DATA_LOAD__ + sta FROM+1 + lda #<__DATA_RUN__ + sta TO + lda #>__DATA_RUN__ sta TO+1 lda #<__DATA_SIZE__ sta SIZEL @@ -70,20 +104,71 @@ _main: sta SIZEH jsr memcpy - jsr Title ; will init the seed + jsr _StartMenu ; will init the seed ; overwrite the seed to debug - ;lda #$0 - ;sta SEED0 - ;lda #$0 - ;sta SEED1 - ;lda #$0 - ;sta SEED2 - ;lda #$0 - ;sta SEED3 + ; lda #$0 + ; sta SEED0 + ; lda #$0 + ; sta SEED1 + ; lda #$0 + ; sta SEED2 + ; lda #$0 + ; sta SEED3 + jsr Random8_Init ; Run jsr game_loop rts + + +; @brief Starting game menu +_StartMenu: + + ; Scrolling Title + jsr Title + + ; New game or continue + lda #>STR_NEWGAME + ldx #STR_JOURNEY + ldx #STR_NAME + ldx #. - -; 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 +.include "memory.inc" .export memcpy -.export TXT1_LINES +.export memset +.export meminit - -.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 @@ -69,4 +55,84 @@ MU3: DEY DEC TO+1 DEX BNE MU1 - RTS \ No newline at end of file + RTS + +; Sets a block of memory to the provided value +; +; A = value to set +; TO = memory to be set starting address +; SIZE = number of bytes to set. Max value: $FEFF +; +; !!! TO and SIZE are overwritten !! +memset: + cmp SIZEH + beq memset_remain +memset_loop_hi: + ldy #$FF +memset_loop_low: + sta (TO),Y + dey + bne memset_loop_low + sta (TO),Y + inc TO+1 ; next 256 byte block + dec SIZEH + bne memset_loop_hi +memset_remain: + ldy SIZEL + cpy #0 + beq memset_end +memset_loop_remain: + sta (TO),Y + dey + bne memset_loop_remain +memset_end: + rts + +; DEBUG: zeros the useful memory locations +meminit: + + lda #0 + sta TO + ldx #$60 + stx TO+1 + ldx #$FF + stx SIZEL + ldx #$05 + stx SIZEH + jsr memset + + lda #0 + sta ZERO_2_1 + sta ZERO_2_2 + sta ZERO_2_3 + sta ZERO_2_4 + sta ZERO_2_5 + sta ZERO_2_6 + sta ZERO_3 + sta ZERO_4_1 + sta ZERO_4_2 + sta ZERO_4_3 + sta ZERO_4_4 + sta ZERO_4_5 + sta ZERO_5_1 + sta ZERO_5_2 + sta ZERO_5_3 + sta ZERO_5_4 + sta ZERO_5_5 + sta ZERO_5_6 + sta ZERO_7_1 + sta ZERO_7_2 + sta ZERO_8_1 + sta ZERO_8_2 + sta ZERO_9_1 + sta ZERO_9_2 + sta ZERO_9_3 + sta ZERO_9_4 + sta ZERO_9_5 + sta ZERO_9_6 + sta ZERO_9_7 + sta ZERO_9_8 + sta ZERO_9_9 + sta ZERO_9_10 + + rts \ No newline at end of file diff --git a/src/memory.inc b/src/memory.inc index 1f7dbf3..cd64635 100644 --- a/src/memory.inc +++ b/src/memory.inc @@ -110,9 +110,8 @@ ; *********** 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 +.define SIZEH ZERO_8_2 +.define SIZEL ZERO_8_1 ; ************ MACROS *********** diff --git a/src/player.asm b/src/player.asm index 2e8e55f..4fd8053 100644 --- a/src/player.asm +++ b/src/player.asm @@ -20,6 +20,7 @@ .include "monitor.inc" .include "io/textio.inc" .include "world/world.inc" +.include "actors/actors.inc" ; init the player's structures @@ -34,39 +35,26 @@ ; They may be unmodified ;) ; DESTROY A, X, Y, ZERO_2_1, ZERO_2_2 -; Increments Player's X position -.export player_move_inx -; Increments Player's Y position -.export player_move_iny -; Decrements Player's X position -.export player_move_dex -; Decrements Player's Y position -.export player_move_dey - -; Player coordinates in the maze ([0:255], [0:255]) -.export Player_XY .import Compute_Maze_Addr .import Reactions_lsb .import Reactions_msb +.import ActorTypes +.import ActorPositions -.BSS +.define TO_BE_PATCHED 0 +.define Player_XY ActorPositions + eACTORTYPES::PLAYER -Player_XY: .res 2 +.DATA +STR_HIT_WALL: ASCIIZ "YOU HIT A WALL" .CODE -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 +; @param Y player's y player_init: stx Player_XY sty Player_XY+1 @@ -80,26 +68,30 @@ player_init: player_move: stx NEW_PLAYER_XY - sty NEW_PLAYER_XY+1 + sty NEW_PLAYER_XY+1 jsr Compute_Maze_Addr - - ; get the actor + + ; get the actor id stx ADDR_IN_MAZE sta ADDR_IN_MAZE+1 ldy #0 lda (ADDR_IN_MAZE), Y tax - + + ; get the actor's type + lda ActorTypes, X + tay + ; get the reaction address - lda Reactions_lsb, X + lda Reactions_lsb, Y sta FUNC_REACTION + 1 - lda Reactions_msb, X + lda Reactions_msb, Y sta FUNC_REACTION+2 - FUNC_REACTION : jsr 0 + FUNC_REACTION : jsr TO_BE_PATCHED ; actord id in Y - cmp TRUE + cmp #TRUE bne end_player_move ldx NEW_PLAYER_XY stx Player_XY @@ -113,49 +105,6 @@ end_player_move: 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) !!! - -player_move_inx: - - ; 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 - 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 hit_wall ; carry cleared if A is strictly the lesser --> not walkable - ldx Player_XY - inx - stx Player_XY ; walkable - PRINT STR_GO_RIGHT - jmp return_from_player_move - - - -player_move_dex: - - ; test that x-1 is "WALKABLE" - ldx Player_XY - dex - ldy Player_XY+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 hit_wall ; carry cleared if A is strictly the lesser --> not walkable - ldx Player_XY - dex - stx Player_XY ; walkable - PRINT STR_GO_LEFT - jmp return_from_player_move - - ; Common code to return from the moves. ; Moves BRANCH to here return_from_player_move: @@ -169,47 +118,3 @@ hit_wall: PRINT STR_HIT_WALL jmp return_from_player_move - -player_move_iny: - - ; 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 - stx ADDR_IN_MAZE - sta ADDR_IN_MAZE+1 - ldy #0 - lda #ACTORS::WALKABLE - cmp (ADDR_IN_MAZE), Y - bcc hit_wall ; carry cleared if A is strictly the lesser --> not walkable - - ldy Player_XY+1 ; walkable - iny - sty Player_XY+1 - PRINT STR_GO_DOWN - jmp return_from_player_move - - -player_move_dey: - - ; 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 - stx ADDR_IN_MAZE - sta ADDR_IN_MAZE+1 - ldy #0 - lda #ACTORS::WALKABLE - cmp (ADDR_IN_MAZE), Y - 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 - - - .undef ADDR_IN_MAZE diff --git a/src/tiles.asm b/src/tiles.asm index 31e7298..8011e8a 100644 --- a/src/tiles.asm +++ b/src/tiles.asm @@ -106,10 +106,10 @@ FLOOR_4: .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 $11, $00, $40, $00 +.byte $71, $7F, $7F, $1F +.byte $71, $01, $C5, $82 +.byte $71, $79, $80, $8A .byte $71, $79, $3C, $00 .byte $71, $79, $3C, $1E .byte $71, $79, $3C, $1E @@ -123,21 +123,21 @@ STAIR_DOWN: .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 +.byte $01, $00, $90, $F8 +.byte $01, $AA, $70, $79 +.byte $01, $E2, $73, $79 +.byte $01, $60, $73, $79 +.byte $41, $67, $73, $79 +.byte $41, $67, $73, $79 +.byte $41, $67, $73, $79 +.byte $41, $67, $73, $79 +.byte $41, $67, $73, $79 +.byte $40, $67, $73, $79 +.byte $40, $67, $73, $79 +.byte $40, $67, $73, $79 +.byte $40, $67, $F3, $A1 +.byte $40, $67, $D3, $A8 +.byte $C0, $A7, $91, $A8 WALL_1: .byte 197, 138, 213, 168 .byte 197, 138, 213, 168 @@ -172,6 +172,74 @@ WALL_2: .byte $7F, $7F, $7F, $7F .byte $7F, $7F, $7F, $7F .byte $7F, $7F, $7F, $7F +COFFER: +.byte $55, $2A, $55, $2A +.byte $01, $20, $00, $00 +.byte $01, $7E, $0F, $00 +.byte $41, $67, $3C, $00 +.byte $31, $66, $4C, $01 +.byte $31, $66, $4C, $01 +.byte $31, $66, $4C, $01 +.byte $71, $7F, $7F, $01 +.byte $31, $C0, $40, $01 +.byte $35, $C0, $40, $2B +.byte $B0, $C0, $40, $01 +.byte $30, $00, $40, $01 +.byte $30, $00, $40, $01 +.byte $70, $7F, $7F, $01 +.byte $70, $7F, $7F, $01 +.byte $10, $00, $40, $00 +RAT: +.byte $55, $2A, $55, $2A +.byte $01, $20, $03, $00 +.byte $01, $20, $EF, $81 +.byte $01, $20, $7C, $1F +.byte $01, $78, $7F, $1F +.byte $01, $7E, $BF, $85 +.byte $41, $7F, $0F, $00 +.byte $71, $7F, $03, $00 +.byte $7D, $7F, $03, $00 +.byte $5D, $7F, $57, $2A +.byte $5C, $1F, $43, $00 +.byte $5C, $01, $43, $00 +.byte $50, $01, $4F, $00 +.byte $50, $1F, $40, $00 +.byte $10, $00, $40, $00 +.byte $10, $00, $40, $00 +SERPENT: +.byte $55, $2A, $55, $2A +.byte $01, $20, $03, $00 +.byte $01, $60, $0C, $00 +.byte $01, $60, $3F, $00 +.byte $01, $60, $8B, $80 +.byte $01, $60, $A3, $81 +.byte $01, $60, $00, $00 +.byte $01, $78, $00, $00 +.byte $01, $7E, $00, $00 +.byte $55, $2F, $55, $2A +.byte $70, $01, $40, $00 +.byte $30, $18, $40, $00 +.byte $30, $78, $40, $00 +.byte $30, $60, $40, $00 +.byte $70, $79, $40, $00 +.byte $40, $1F, $40, $00 +SPIDER: +.byte $55, $2A, $55, $2A +.byte $01, $18, $03, $00 +.byte $01, $60, $00, $00 +.byte $01, $78, $03, $00 +.byte $01, $78, $03, $00 +.byte $01, $60, $00, $00 +.byte $01, $78, $03, $00 +.byte $71, $5F, $7F, $01 +.byte $01, $5E, $0F, $00 +.byte $75, $5F, $7F, $2B +.byte $10, $56, $0E, $00 +.byte $70, $5F, $7F, $01 +.byte $10, $58, $43, $00 +.byte $50, $7F, $7F, $00 +.byte $10, $60, $40, $00 +.byte $10, $00, $40, $00 UNKNOWN: .byte $80, $80, $80, $80 .byte $80, $80, $80, $80 @@ -192,8 +260,34 @@ UNKNOWN: .ALIGN 256 -; DON"T FORGET TO UPDATE NB_TILES!! + +; Tiles used by ACTORS +; 128 addresses TILES: .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 +; floors +.word FLOOR_1, FLOOR_2, FLOOR_3, FLOOR_4, FLOOR_4, FLOOR_4 +; walls +.word WALL_1, WALL_2, WALL_2, WALL_2 +; stairs +.word STAIR_DOWN, STAIR_UP +; items +.word COFFER +; monsters +.word RAT, SPIDER, SERPENT +; other +; COMPLETE TO GET THE 128 TILES!!! +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN +.word UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN diff --git a/src/world.asm b/src/world.asm deleted file mode 100644 index 7af4cfa..0000000 --- a/src/world.asm +++ /dev/null @@ -1,154 +0,0 @@ - -; Copyright (C) 2018 Christophe Meneboeuf -; -; 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 . - - -.include "world.inc" -.include "tiles.inc" -.include "random.inc" -.include "math.inc" -.include "memory.inc" - - - -.export World - -; initializes the world -; DESTROYS A,X,Y, ZERO_2_1, ZERO_2_2, ZERO_2_3 -.export world_init - -; sets the player's position onto the Maze -; in: X = x coord in the maze -; in: Y = y coord in the maze -; out : X and Y as they where given -; DESTROYS A,X,Y, ZERO_2_1, ZERO_2_2, ZERO_2_4, ZERO_2_5 -.export world_set_player - -; Computes the adress corresponding to the coordinates in the maze -; in: X = x coord in the maze -; 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 - - -.define TILE_NR ZERO_2_1 -.define COORD_X ZERO_2_1 -.define COORD_Y ZERO_2_2 -.define OFFSET ZERO_2_2 - - -.BSS - -; The tile where the player stands -.struct Tile_player_standing - addr .word ; adress of the location - actor .byte ; actor on the location tile -.endstruct - -.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 - jsr Compute_Maze_Addr - stx Tile_player_standing::addr - sta Tile_player_standing::addr+1 - stx ZERO_2_1 - sta ZERO_2_1+1 - ldy #0 - lda (ZERO_2_1), Y - sta Tile_player_standing::actor - - rts - - -; sets the player's position onto the World -world_set_player: - - stx ZERO_2_4 - sty ZERO_2_5 - - ; restore the previous tile - ldx Tile_player_standing::addr - lda Tile_player_standing::addr+1 - stx ZERO_2_1 - sta ZERO_2_1+1 - ldy #0 - lda Tile_player_standing::actor - sta (ZERO_2_1), Y - - ; save the next tile - ldx ZERO_2_4 - ldy ZERO_2_5 - 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 - sta ZERO_2_1+1 - ldy #0 - lda (ZERO_2_1), y - sta Tile_player_standing::actor - - ; sets the player on the tile - lda #ACTORS::PLAYER - sta (ZERO_2_1), y - - ; restore the given locations - ldx ZERO_2_4 - ldy ZERO_2_5 - - rts - -; Destroys ZERO_2_1, ZERO_2_2, ZERO_2_3 ZERO_7_1 and ZERO_7_2 -Compute_Maze_Addr: - - stx COORD_X - - ; offset due to Y coord - sty FAC1 - lda #WIDTH_WORLD - sta FAC2 - jsr mul8 - tay ; high part of the mul - txa ; low part of the mul - - ; adding offset due to X - clc - adc COORD_X - sta OFFSET - tya - adc #0 - sta OFFSET+1 - - ; adding the offset to the address - lda #World - adc OFFSET+1 ; high part of address to be returned in A - - rts - - - -.DATA - -.align 256 - -World: .res (WIDTH_WORLD) * (HEIGHT_WORLD) diff --git a/src/world.inc b/src/world.inc deleted file mode 100644 index 289d15a..0000000 --- a/src/world.inc +++ /dev/null @@ -1,34 +0,0 @@ -; The world contains a Maze, filled with Actors -; Actors can be static, such a a floor or a wall, -; dynamic such as a door -; or alive, such as a monster - - -.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 NEG_WIDTH_WORLD $C0 -.define HEIGHT_WORLD 64 -.define NEG_HEIGHT_WORLD 64 $C0 - - -.enum ACTORS - - PLAYER = 0 - - FLOOR_1 = 1 - FLOOR_2 ; FLOOR BY DEFAULT - FLOOR_3 - FLOOR_4 - WALKABLE = FLOOR_4 ; Player won't be allowed to go on anything > WALKABLE - - NOT_WALKABLE - NOT_TRANSPARENT = NOT_WALKABLE - WALL_1 = NOT_WALKABLE - WALL_2 - - UNKNOWN - - NB_ACTORS - -.endenum diff --git a/src/world/level.asm b/src/world/level.asm index 944fc20..d923a5b 100644 --- a/src/world/level.asm +++ b/src/world/level.asm @@ -17,133 +17,119 @@ .include "../common.inc" .include "../memory.inc" .include "../random.inc" -.include "../builder/actors.inc" +.include "../math.inc" +.include "../actors/actors.inc" .include "../builder/builder.inc" +.include "../io/files.inc" .include "level_private.inc" ; code .export levels_init .export level_enter .export level_exit +.export level_get_config_offset +.export level_reset_states ; data -.export Levels +.export LevelConfigs +.export NbLevels .export CurrentLevel .export NextLevel .export ExitLevel +.export LevelIsBuilt .import player_init +.import ActorsInLevel +.import ActorPositions +.import World .BSS CurrentLevel: .res 1 +NbLevels: .res 1 NextLevel: .res 1 ExitLevel: .res 1 - -.align 256 ; to be sure it is accessible with an offset -Levels: .res SIZEOF_CONF_LEVEL * NB_LEVELS +LevelIsBuilt: .res 1 - -.CODE +LevelConfigs: .res 1 + NB_LEVELS * SIZEOF_CONF_LEVEL -.define NR_ACTORS ZERO_4_1 -.define NR_LEVELS ZERO_4_2 -; TODO Load a configuration file from disk! +.segment "CODE2" + + +.define ACCUMULATOR ZERO_9_4 ; 2 bytes + +; @param LevelNr in X +_Set_Params_LoadSaveLevelActors: + + ; compute offset in file + lda #0 + sta ACCUMULATOR + sta ACCUMULATOR+1 + beq end_loop_offset +loop_offset: ; accumulating offsets + clc + lda ACCUMULATOR + adc #<(SIZEOF_ACTORS_T) + sta ACCUMULATOR + lda ACCUMULATOR+1 + adc #>(SIZEOF_ACTORS_T) + sta ACCUMULATOR+1 + dex + bne loop_offset +end_loop_offset: + ; set function parameters + sta Param_FileOffset+3 + lda ACCUMULATOR + sta Param_FileOffset+2 + lda #Str_FileLevelsActors + sta Param_FileOpen+2 + lda #ActorsInLevel + sta Param_FilesReadWrite+3 + + rts + + +.define NR_LEVELS ZERO_4_1 levels_init: - ldx #0 - ldy #0 - lda #NB_LEVELS + ; file path + lda #Str_FileLevelConfs + sta Param_FileOpen+2 + ; read buffer + lda #0 + sta Param_FileOffset+2 + sta Param_FileOffset+3 + sta Param_FileOffset+4 + lda #LevelConfigs + sta Param_FilesReadWrite+3 + lda #<(1 + SIZEOF_CONF_LEVEL * NB_LEVELS) + sta Param_FilesReadWrite+4 + lda #>(1 + SIZEOF_CONF_LEVEL * NB_LEVELS) + sta Param_FilesReadWrite+5 + + ; load + jsr ReadFile + + ; exploit + lda LevelConfigs + sta NbLevels sta NR_LEVELS + inc NR_LEVELS -level_conf_default: - ; level_nr - tya - iny - sta Levels, X - ; is_built - lda FALSE - sta Levels+1, x - ; seed - lda #0 - sta Levels+2, X - sta Levels+3, X - sta Levels+4, X - sta Levels+5, X - ; size - ; pos_player_enter - lda #$FF - sta Levels+7, X - sta Levels+8, X - ; actors - txa - clc - adc #9 - tax - lda #eACTORSREACTIVE::AA_NB - sta NR_ACTORS - lda #0 - - level_conf_actors: - sta Levels, X - inx - dec NR_ACTORS - bne level_conf_actors - - dec NR_LEVELS - bne level_conf_default - - ; level #0 - ldx #0 - lda #1 - sta Levels + 9 + eACTORSREACTIVE::AA_STAIRUP, X - lda #LEVELSIZE::TINY - sta Levels+6, X ; size - ; level #1 - clc - txa - adc #SIZEOF_CONF_LEVEL - tax - lda #1 - sta Levels + 9 + eACTORSREACTIVE::AA_STAIRUP, X - sta Levels + 9 + eACTORSREACTIVE::AA_STAIRDOWN, X - lda #LEVELSIZE::SMALL - sta Levels+6, X ; size - ; level #2 - clc - txa - adc #SIZEOF_CONF_LEVEL - tax - lda #1 - sta Levels + 9 + eACTORSREACTIVE::AA_STAIRUP, X - sta Levels + 9 + eACTORSREACTIVE::AA_STAIRDOWN, X - lda #LEVELSIZE::NORMAL - sta Levels+6, X ; size - ; level #3 - clc - txa - adc #SIZEOF_CONF_LEVEL - tax - lda #1 - sta Levels + 9 + eACTORSREACTIVE::AA_STAIRUP, X - sta Levels + 9 + eACTORSREACTIVE::AA_STAIRDOWN, X - lda #LEVELSIZE::BIG - sta Levels+6, X ; size - ; level #4 - clc - txa - adc #SIZEOF_CONF_LEVEL - tax - lda #1 - sta Levels + 9 + eACTORSREACTIVE::AA_STAIRDOWN, X - lda #LEVELSIZE::HUGE - sta Levels+6, X ; size - - ; global vars +; global vars lda #0 sta CurrentLevel - lda FALSE + sta NextLevel + lda #FALSE sta ExitLevel rts @@ -151,85 +137,51 @@ level_conf_default: ; @param: Uses NextLevel as level number -.define LEVEL_CONF_OFFSET ZERO_3 +.define LEVEL_STATE_OFFSET ZERO_9_1 +.define ADDR_LEVEL_CONF ZERO_9_2 ; 2 bytes level_enter: - ; debug: - ; lda NextLevel - ; cmp #0 - ; bne debug_end - ; jsr Random8 - ; debug_end: + lda NextLevel + jsr LoadState - jsr Random8_SaveRandomness + lda LevelIsBuilt + cmp #TRUE + beq level_was_built - ; get the level conf - lda #0 - ldx #0 - clc - get_level_conf: - tay - lda Levels, X - cmp NextLevel - beq end_idx_level - tya - adc #SIZEOF_CONF_LEVEL +level_generation: + + ; compute offset to level config + lda NextLevel + jsr level_get_config_offset + pha + clc + txa + adc #LevelConfigs + sta ADDR_LEVEL_CONF+1 + + ; init maze size + ldy #1 + lda (ADDR_LEVEL_CONF), Y ; size tax - bcc get_level_conf - end_idx_level: - stx LEVEL_CONF_OFFSET + tay + jsr Init_Dimensions_Maze - ; init seed for the level if not already built - lda Levels+1, X ; is_built - cmp FALSE - bne end_init_seed + ; player position returned in X and Y + jsr Build_Level + jsr player_init ; param: player pos in X and Y - jsr Random8 - ldx LEVEL_CONF_OFFSET - sta Levels+2, X ; seed[0] - jsr Random8 - ldx LEVEL_CONF_OFFSET - sta Levels+3, X ; seed[1] - jsr Random8 - ldx LEVEL_CONF_OFFSET - sta Levels+4, X ; seed[2] - jsr Random8 - ldx LEVEL_CONF_OFFSET - sta Levels+5, X ; seed[3] -end_init_seed: +level_was_built: - ; init the randomness with the values for the level - lda Levels+2, X ; seed[0] - sta SEED0 - lda Levels+3, X ; seed[1] - sta SEED1 - lda Levels+4, X ; seed[2] - sta SEED2 - lda Levels+5, X ; seed[3] - sta SEED3 - jsr Random8_Init - - ; init maze size - ldx LEVEL_CONF_OFFSET - txa - pha ; save LEVEL_CONF_OFFSET as its ZP will be overwritten - lda Levels+6, X ; size - tax - tay - jsr Init_Dimensions_Maze + ldx ActorPositions + eACTORTYPES::PLAYER + ldy ActorPositions + eACTORTYPES::PLAYER + 1 + jsr player_init - ; player position returned in X and Y - jsr Build_Level - jsr player_init ; param: player pos in X and Y +level_enter_end: - jsr Random8_RestoreRandomness - - pla ; restore LEVEL_CONF_OFFSET - tax - lda TRUE - sta Levels+1, X; is_built - - lda FALSE + lda #FALSE sta ExitLevel lda NextLevel @@ -238,28 +190,39 @@ end_init_seed: rts -.import Player_XY +.define Player_XY ActorPositions + eACTORTYPES::PLAYER level_exit: - ; get the level conf - lda #0 - ldx #0 - clc - get_level_conf_2: - tay - lda Levels, X - cmp CurrentLevel - beq end_idx_level_2 - tya - adc #SIZEOF_CONF_LEVEL - tax - bcc get_level_conf_2 - end_idx_level_2: - - ; save player pos in conf - lda Player_XY - sta Levels+7, X - lda Player_XY + 1 - sta Levels+8, X + lda CurrentLevel + jsr SaveState + + rts + +; @param Level_Nr in A +; @return Config offset for the level in X +level_get_config_offset: + + sta FAC1 + ldx #SIZEOF_CONF_LEVEL + stx FAC2 + jsr mul8 + ; first byte of conf is the number of levels + pha + clc + txa + adc #1 + tax + pla + adc #0 + + rts + +; @brief reset the states of all levels +level_reset_states: + + lda #0 + sta CurrentLevel + lda #NB_LEVELS + jsr ResetIsBuilt rts diff --git a/src/world/level.inc b/src/world/level.inc index c12a5f5..bfac7e7 100644 --- a/src/world/level.inc +++ b/src/world/level.inc @@ -14,14 +14,42 @@ ; along with this program. If not, see . -.include "level_private.inc" .import levels_init .import level_enter ; param: A = level_nr .import level_exit +.import level_get_config_offset .import CurrentLevel .import NextLevel .import ExitLevel -.import Levels +.import LevelConfigs +.import NbLevels + +.enum LEVELSIZE + TINY = 20 + SMALL = 24 + NORMAL = 32 + BIG = 48 + HUGE = 64 +.endenum + + +; struct Level +; { +; uint8_t is_built; +; uint8_t seed[4]; //< seed used to build the level +; coords_t pos_player_enter; //< position of player when entering the level (x,y) +; } +; + +; nb_levels >>>> ALWAYS OFFSET + 1!!! <<<< +; array [ + ; struct LevelsConf + ; { + ; uint8_t level_nr; + ; uint8_t size; //< eLEVELSIZE + ; uint8_t actors[NB_ACTORS_MAX]; //< number of actors of each kind added in the level after building the maze + ; } +; ] diff --git a/src/world/level_private.inc b/src/world/level_private.inc index 7642e2e..7671073 100644 --- a/src/world/level_private.inc +++ b/src/world/level_private.inc @@ -15,28 +15,11 @@ +; BEWARE: NB_LEVELS * SIZEOF_STATE_LEVEL shall not be > 256 +.define SIZEOF_STATE_LEVEL 7 + +.define SIZEOF_CONF_LEVEL 130 ;( NB_ACTORS_MAX + 2 ) +.define NB_LEVELS 3 -; typedef struct -; { -; uint8_t level_nr; -; uint8_t is_built; -; uint8_t seed[4]; //< seed used to build the level -; uint8_t size; //< eLEVELSIZE -; coords_t pos_player_enter; //< position of player when entering the level (x,y) -; uint8_t actors[AA_NB]; //< number of reactive actors of each kind in the level -; } -; level_conf_t; - -; BEWARE: NB_LEVELS * SIZEOF_CONF_LEVEL shall not be > 256 -.define SIZEOF_CONF_LEVEL 12 -.define NB_LEVELS 5 - -.enum LEVELSIZE - TINY = 20 - SMALL = 24 - NORMAL = 32 - BIG = 48 - HUGE = 64 -.endenum diff --git a/src/world/world.asm b/src/world/world.asm index 5a6f206..e942103 100644 --- a/src/world/world.asm +++ b/src/world/world.asm @@ -16,13 +16,14 @@ .include "world.inc" +.include "../common.inc" +.include "../actors/actors.inc" .include "../tiles.inc" .include "../random.inc" .include "../math.inc" .include "../memory.inc" - .export World ; initializes the world @@ -43,8 +44,11 @@ ; DESTROYS A,X,Y, ZERO_2_1, ZERO_2_2, ZERO_2_3 .export Compute_Maze_Addr +; #TRUE if an object has been picked by the player +.export World_PickedObject + +.export Tile_player_standing_actor -.define TILE_NR ZERO_2_1 .define COORD_X ZERO_2_1 .define COORD_Y ZERO_2_2 .define OFFSET ZERO_2_2 @@ -53,10 +57,13 @@ .BSS ; The tile where the player stands -.struct Tile_player_standing - addr .word ; adress of the location - actor .byte ; actor on the location tile -.endstruct +; The two memory locations must be adjacent +Tile_player_standing_addr: .res 2 +Tile_player_standing_actor: .res 1 + +.DATA + +World_PickedObject: .byte 0 .CODE @@ -66,51 +73,65 @@ world_init: ; Saving the first tile on which the player stands ; FIXME player could be standing anywhere on any type of floor jsr Compute_Maze_Addr - stx Tile_player_standing::addr - sta Tile_player_standing::addr+1 - stx ZERO_2_1 - sta ZERO_2_1+1 - ldy #0 - lda (ZERO_2_1), Y - sta Tile_player_standing::actor + stx Tile_player_standing_addr + sta Tile_player_standing_addr+1 + lda Tile_player_standing_actor + cmp #UNDEF + bne world_init_end + lda #eACTORTYPES::FLOOR_2 + sta Tile_player_standing_actor + +world_init_end: rts ; sets the player's position onto the World +.define PLAYER_XY ZERO_2_1; 2 bytes +.define NEXT_TILE_XY ZERO_2_4 ; 2 bytes world_set_player: - stx ZERO_2_4 - sty ZERO_2_5 + stx NEXT_TILE_XY + sty NEXT_TILE_XY+1 - ; restore the previous tile - ldx Tile_player_standing::addr - lda Tile_player_standing::addr+1 - stx ZERO_2_1 - sta ZERO_2_1+1 + ; restore the previous tile + ldx Tile_player_standing_addr + lda Tile_player_standing_addr+1 + stx PLAYER_XY + sta PLAYER_XY+1 ldy #0 - lda Tile_player_standing::actor - sta (ZERO_2_1), Y - + lda Tile_player_standing_actor + sta (PLAYER_XY), Y + ; save the next tile - ldx ZERO_2_4 - ldy ZERO_2_5 + ldx NEXT_TILE_XY + ldy NEXT_TILE_XY+1 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 - sta ZERO_2_1+1 + stx Tile_player_standing_addr + sta Tile_player_standing_addr+1 + stx PLAYER_XY + sta PLAYER_XY+1 ldy #0 - lda (ZERO_2_1), y - sta Tile_player_standing::actor + lda (PLAYER_XY), y + sta Tile_player_standing_actor + ; if an object was picked + ; override to force save a floor tile + lda World_PickedObject + cmp #TRUE + bne no_object_picked + lda #eACTORTYPES::FLOOR_2 + sta Tile_player_standing_actor + lda #FALSE + sta World_PickedObject + no_object_picked: ; sets the player on the tile - lda #ACTORS::PLAYER - sta (ZERO_2_1), y + lda #eACTORTYPES::PLAYER + sta (PLAYER_XY), y ; restore the given locations - ldx ZERO_2_4 - ldy ZERO_2_5 + ldx NEXT_TILE_XY + ldy NEXT_TILE_XY+1 rts @@ -147,7 +168,7 @@ Compute_Maze_Addr: -.DATA +.BSS .align 256 diff --git a/src/world/world.inc b/src/world/world.inc index 4ce1f1d..4bae3e9 100644 --- a/src/world/world.inc +++ b/src/world/world.inc @@ -27,31 +27,5 @@ .define WIDTH_WORLD 64 .define NEG_WIDTH_WORLD $C0 .define HEIGHT_WORLD 64 -.define NEG_HEIGHT_WORLD 64 $C0 +.define NEG_HEIGHT_WORLD $C0 - -.enum ACTORS - - PLAYER = 0 - - FLOOR_1 = 1 - FLOOR_2 ; FLOOR BY DEFAULT - FLOOR_3 - FLOOR_4 - FLOOR_5 - FLOOR_6 - STAIR_DOWN - STAIR_UP - WALKABLE = STAIR_UP ; Player won't be allowed to go on anything > WALKABLE - - NOT_TRANSPARENT = STAIR_UP - NOT_WALKABLE - - WALL_1 = NOT_WALKABLE - WALL_2 - - UNKNOWN - - NB_ACTORS - -.endenum