From: Lukas Krickl Date: Thu, 21 Aug 2025 03:58:30 +0000 (+0200) Subject: mapgen: refactored map loader X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=402f7310b9aad84edeaa73bb4a3898fd26c60f6a;p=gbrg%2F.git mapgen: refactored map loader --- diff --git a/src/map.s b/src/map.s index a1463a2..3cbf128 100644 --- a/src/map.s +++ b/src/map.s @@ -1,3 +1,26 @@ + + ; disables the lcd + ; call before map_load +map_load_start: + ; disable interruts + ; wait for next blank + ; disable lcd + call disableinterrutpts + call next_vblank_wait + call lcd_off + ret + + ; draws the map + ; enables the lcd + ; call after map_load +map_load_end: + call map_draw_all + + ; restore lcd and interrupts + call lcd_on + call vblank_wait + call enableinterrupts + ret ; loads a new map ; inputs: @@ -7,22 +30,12 @@ ; TODO: do not touch lcd or interrupts if ; they were not enabled! map_load: - push hl - call act_sg_store - pop hl - ; backup the map header ld a, l ld [map_header], a ld a, h ld [map_header+1], a - ; disable interruts - ; wait for next blank - ; disable lcd - call disableinterrutpts - call next_vblank_wait - call lcd_off push hl call map_draw_area_title @@ -47,63 +60,6 @@ map_load: push hl call map_load_exit_table pop hl - - push hl - call map_call_gen - pop hl - - push hl - call act_sg_restore - pop hl - - call map_draw_all - - ; restore lcd and interrupts - call lcd_on - call vblank_wait - call enableinterrupts - - ret - - ; calls mapgen unless disabled - ; for current map - ; loads the seed based on map offset - ; inputs: - ; hl: map_ptr -map_call_gen: - push hl - - ; check if rand is disabled - ld de, map_flags_1 - add hl, de - ld a, [hl] - and a, MAPF1_NO_RAND - - pop hl - ; bail if flag is set - ret nz - - ; load seed offset - push hl - - ld a, [player_map_cursor] - - ; * 2 because it is a 2-byte table - add a, a - ld d, 0 - ld e, a - ld hl, map_seeds - add hl, de - ; hl = seeds+offset - ld a, [hl+] ; a = seed LO - ld d, a - ld a, [hl] - ld e, a ; de = seed - - pop hl - - ld hl, map - call mapgen ret diff --git a/src/mapgen.s b/src/mapgen.s index 8a1bf62..374a3f4 100644 --- a/src/mapgen.s +++ b/src/mapgen.s @@ -8,16 +8,49 @@ mapgen_init: call act_save_init call mapgen_seed call mapgen_make_doors - call mapgen_select_map - call map_load + call mapgen ret + ; selects a room pattern table + ; returns: + ; hl: pattern table + ; a: size +mapgen_select_pattern_table: + ; TODO: select different tables based on floor + ld hl, room_patterns_floor1 + ld a, ((room_patterns_floor1_end - room_patterns_floor1) / 2) - 1 + ret + ; selects a map from the tables based on the current floor ; and the current cursor seed ; returns: ; hl: map pointer mapgen_select_map: - ld hl, map_c_header + call mapgen_select_pattern_table + push hl + + ld b, a + call rand + and a, b ; cap rand to table size + + pop hl + + add a, a ; * 2 because its a 2-byte table + + ld b, 0 + ld c, a + add hl, bc + + ; load table ptr + ld a, [hl+] + ld c, a + ld a, [hl] + ld b, a + + ld l, c + ld h, b + + ret @@ -38,26 +71,37 @@ mapgen_seed: ret + + ; loads the current seed based on player map cursor + ; returns: + ; de: the seed +mapgen_load_seed: + ld a, [player_map_cursor] + add a, a ; * 2 because it is a 2-byte table + ld d, 0 + ld e, a + ld hl, map_seeds + add hl, de + ; hl = seeds+offset + ld a, [hl+] + ld d, a + ld a, [hl] + ld e, a ; de = seed + ret ; places a rectangular room ; into the currently loaded map - ; 1) places room patterns in top left, top right, bottom left, bottom right - ; patterns are chosen from a list of valid patterns which is determined by - ; the current floor - ; 6) place larger room patterns that may overwrite existing patterns - ; 5) run floor-based post processing (look up routine from table) - ; 7) palce actors on floor tiles based on a table of actors - ; chosen based on the floor - ; inputs: - ; hl: writable decompressed tile array (e.g [map]) - ; of size MAP_H * MAP_W - ; de: the seed used - ; map_header: the current map header + ; 1) selects a random map to draw + ; 2) places doors + ; 3) places actors + ; 4) reloads actor sg + ; 5) draws map ; preserves: ; srand mapgen: - ; roll a room size + call map_load_start + call act_sg_store ; load seed ; and back it up ld a, [srand] @@ -65,20 +109,19 @@ mapgen: ld a, [srand+1] ld c, a push bc + + + call mapgen_load_seed ; load seed param ld a, e ld [srand+1], a ld a, d ld [srand], a - - ; generate first room - call mapgen_up_left_room - call mapgen_bottom_left_room - call mapgen_up_right_room - call mapgen_bottom_right_room - - call mapgen_place_special_room + + call mapgen_select_map + call map_load + ld hl, map call mapgen_draw_doors @@ -92,6 +135,10 @@ mapgen: ld b, a ld [srand], a + call act_sg_restore + + call map_load_end + ret ; generates door locations for each map @@ -178,337 +225,12 @@ mapgen_draw_doors: ret - ; selects a random room pattern - ; inputs: - ; hl: room pattern table - ; a: table size - ; returns: - ; bc: room pattern ptr -mapgen_select_pattern: - push hl - - ld b, a - call rand - and a, b ; cap rand to table size - - pop hl - - ld b, 0 - ld c, a - add hl, bc - - - ; load table ptr - ld a, [hl+] - ld c, a - ld a, [hl] - ld b, a - - ret - - ; select room pattern 6x6 - ; preserves: hl -mapgen_select_pattern_6x6: - push hl - ld a, ROOM_PATTERN_6X6_SIZE - ld hl, room_pattern_6x6 - call mapgen_select_pattern - pop hl - ret - - ; inputs: - ; hl: [map] - ; preserves: hl -mapgen_up_left_room: - push hl - - ; move to correct location on map - ld bc, MAP_W*c_size - add hl, bc - inc hl - inc hl - - call mapgen_select_pattern_6x6 - - call mapgen_draw_room_pattern - pop hl - ret - - - ; inputs: - ; hl: [map] - ; preserves: hl -mapgen_bottom_left_room: - push hl - - ; move to correct location on map - ld bc, MAP_W*9*c_size - add hl, bc - inc hl - inc hl - - call mapgen_select_pattern_6x6 - - call mapgen_draw_room_pattern - pop hl - ret - - ; inputs: - ; hl: [map] - ; preserves: hl -mapgen_up_right_room: - push hl - - ; move to correct location on map - ld bc, (MAP_W/2)*c_size + MAP_W*c_size - add hl, bc - inc hl - inc hl - - call mapgen_select_pattern_6x6 - - call mapgen_draw_room_pattern - pop hl - ret - - - ; inputs: - ; hl: [map] - ; preserves: hl -mapgen_bottom_right_room: - push hl - - ; move to correct location on map - ld bc, (MAP_W/2)*c_size + MAP_W*9*c_size - add hl, bc - inc hl - inc hl - - call mapgen_select_pattern_6x6 - - call mapgen_draw_room_pattern - pop hl - ret - - ; rolls rng - ; if value > 128 a random special room is placed - ; special rooms overwrite other rooms and are larger room - ; patterns - ; special rooms are placed starting in the top left corner - ; inputs: - ; hl: [map] - ; preserves: hl -mapgen_place_special_room: - push hl - call rand - and a, 0x80 - pop hl - ret z ; bail if no speical room is requested - - push hl - - ; move to correct location on map - ld bc, MAP_W*c_size - add hl, bc - inc hl - inc hl - ; pick a room from the special pattern list - - push hl - ld a, ROOM_PATTERN_SPECIAL_SIZE - ld hl, room_pattern_special - call mapgen_select_pattern - pop hl - - call mapgen_draw_room_pattern - - pop hl - ret - - - ; draws a room pattern to the map - ; inputs: - ; hl: origin inside of map struct - ; bc: room pattern header pointer -mapgen_draw_room_pattern: - ld a, [bc] ; read room pattern size - and a, 0x0F ; number of tiles per row - ; e = tile per row counter - ld e, a - - ld a, [bc] - and a, 0xF0 ; number of rows - swap a - ld d, a ; d = number of rows - - inc bc ; move past header - ; bc = first room pattern entry -@y_loop: - push hl - call mapgen_draw_room_pattern_row - pop hl - - push bc - ld bc, MAP_W*c_size - add hl, bc ; next row - pop bc - - dec d - jr nz, @y_loop REL - - ret - - ; reads a value from a table - ; inputs: - ; a: pattern value - ; $1: table name - ; preserves: hl and de -#macro mapgen_read_value_from_table - push hl - push de - ld hl, $1 - ld d, 0 - ld e, a - add hl, de ; hl = offset into table - ld a, [hl] - pop de - pop hl -#endmacro - - ; draws a single map pattern row - ; writes tile flags - ; if a door is about to be placed next to - ; and existing wall the door is replaced with a - ; wall tile - ; inputs: - ; hl: map ptr - ; bc: room pattern - ; e: tiles per row counter - ; preserves: - ; de - ; returns: - ; hl: incremented by number of tiles * c_size - ; bc: incremented by number of tiles -mapgen_draw_room_pattern_row: - push de -@x_loop: - ld a, [bc] - call mapgen_fix_door_adjacent_to_collider - ; save result pattern value - push af - - ; read from tile and flag tables and write to map - - ; tile table first - mapgen_read_value_from_table room_pattern_tile_translation - ; write to map - ld [hl+], a ; write tile - - ; read pattern again - pop af - - ; now flags table - mapgen_read_value_from_table room_pattern_flags_translation - - ; write to flags - ld [hl+], a - - ; hl = next tile - inc bc ; next pattern - - ; tiles-- - dec e - jr nz, @x_loop REL - - pop de - ret - - - ; performs fix by checking if a tile - ; at a certain offset relative to a door - ; is a collider - ; inputs: - ; $1: the offset relative to the current map position - ; $2: the wall pattern to use if a collider is found - ; hl: map_ptr - ; a: pattern entry - ; - ; preserves: - ; hl, bc, de -#macro mapgen_fix_door_fixup -.beginscope - push hl - push de - - ; move left one tile - ; and check for colliders - ld de, ($1) & 0xFFFF - add hl, de - ; hl = tile to the left - - inc hl ; go to flags - ld d, a ; store a for later - ld a, [hl] - and a, CF_COLLISION - ld a, d ; restore a's value - - ; if not collider do not fix - jr z, @no_fix REL - ; otherwise load left wall into a - ld a, $2 - @no_fix: - - pop de - pop hl -.endscope -#endmacro - - - ; fixed door tile if it is adjacent to - ; a collider tile - ; inputs: - ; hl: map_ptr - ; a: pattern entry - ; returns: - ; a: unchanged if not next to collider or not a door pattern - ; a: changed to wall tile if it is a door and is next to a collider - ; preserves: - ; hl, bc, de -mapgen_fix_door_adjacent_to_collider: - cp a, RPDU - jp z, @up_door - - cp a, RPDB - jp z, @down_door - - cp a, RPDL - jp z, @left_door - - cp a, RPDR - jp z, @right_door - - ret -@up_door: - mapgen_fix_door_fixup (-c_size) * MAP_W, RPUW - ret -@down_door: - mapgen_fix_door_fixup c_size * MAP_W, RPBW - ret -@left_door: - mapgen_fix_door_fixup -c_size, RPLW - ret -@right_door: - mapgen_fix_door_fixup c_size, RPRW - - ret - ; places actors from a valid actor table ; from the current floor value. This will overwrite the ; header loaded by map_load. Preserves player entry. ; the length of the actor table must be maskable ; inputs: ; a loaded map - ; [map_header] ptr mapgen_place_actors: ; clear everything past player ld hl, p0_units + act_size diff --git a/src/roompatterns.s b/src/roompatterns.s index 03838a9..6903e60 100644 --- a/src/roompatterns.s +++ b/src/roompatterns.s @@ -1,151 +1,16 @@ - -.se 0 ; roomp_header - ; height in tiles | width in tiles - ; nnnn0000 0000nnnn -.de rp_header_width_height, 1 -.de rp_header_size, 0 - - ; room pattern header - ; inputs: - ; $1: width/height -#macro rpheaderdef - .db $1 -#endmacro - - ; room pattern row - ; inputs: - ; $1-$6: RP entry -#macro rprow - .db $1, $2, $3, $4, $5, $6 -#endmacro - -; template rooms -; rooms are template patterns that can be placed -; on maps -; the room pattern tiles used depend on the current floor -; each pattern entry has a specific flag set that is placed in the map -; room patterns are N by M areas with the following properties: -.se 0 - ; room pattern up left corner -.de RPUL, 1 - ; room pattern up wall -.de RPUW, 1 - ; room pattern up right corner -.de RPUR, 1 - ; left wall -.de RPLW, 1 -.de RPRW, 1 - ; bottom right corner -.de RPBR, 1 - ; bottom wall -.de RPBW, 1 - ; bottom left corner -.de RPBL, 1 - ; floor -.de RPFL, 1 - ; door up -.de RPDU, 1 - ; door bottom -.de RPDB, 1 - ; door left -.de RPDL, 1 - ; door right -.de RPDR, 1 - ; roof -.de RPRF, 1 - -room_pattern_empty: - rpheaderdef 0x66 - rprow RPFL, RPFL, RPFL, RPFL, RPFL, RPFL - rprow RPFL, RPFL, RPFL, RPFL, RPFL, RPFL - rprow RPFL, RPFL, RPFL, RPFL, RPFL, RPFL - rprow RPFL, RPFL, RPFL, RPFL, RPFL, RPFL - rprow RPFL, RPFL, RPFL, RPFL, RPFL, RPFL - rprow RPFL, RPFL, RPFL, RPFL, RPFL, RPFL - -room_pattern1: - rpheaderdef 0x66 - rprow RPUL, RPUW, RPUW, RPDU, RPUW, RPUR - rprow RPLW, RPRF, RPRF, RPRF, RPRF, RPRW - rprow RPLW, RPRF, RPRF, RPRF, RPRF, RPRW - rprow RPLW, RPRF, RPRF, RPRF, RPRF, RPRW - rprow RPLW, RPRF, RPRF, RPRF, RPRF, RPRW - rprow RPBL, RPBW, RPBW, RPDB, RPBW, RPBR - -room_pattern2: - rpheaderdef 0x66 - rprow RPUL, RPUW, RPUW, RPDU, RPUW, RPUR - rprow RPLW, RPRF, RPRF, RPRF, RPRF, RPRW - rprow RPLW, RPRF, RPRF, RPRF, RPRF, RPRW - rprow RPDL, RPRF, RPRF, RPRF, RPRF, RPDR - rprow RPLW, RPRF, RPRF, RPRF, RPRF, RPRW - rprow RPBL, RPBW, RPBW, RPDB, RPBW, RPBR - -room_pattern3: - rpheaderdef 0x66 - rprow RPFL, RPFL, RPFL, RPFL, RPFL, RPFL - rprow RPFL, RPUL, RPUW, RPUW, RPUR, RPFL - rprow RPFL, RPFL, RPFL, RPFL, RPLW, RPFL - rprow RPFL, RPFL, RPFL, RPFL, RPLW, RPFL - rprow RPFL, RPFL, RPDB, RPBW, RPBR, RPFL - rprow RPFL, RPFL, RPFL, RPFL, RPFL, RPFL - -room_pattern_special1: - rpheaderdef 0x6E - .db RPUL, RPUW, RPUW, RPDU, RPUW, RPUW, RPUW, RPUW, RPUW, RPUW, RPUW, RPUW, RPUW, RPUR - .db RPLW, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRW - .db RPLW, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRW - .db RPLW, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRW - .db RPLW, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRF, RPRW - .db RPBL, RPBW, RPBW, RPBW, RPBW, RPDB, RPBW, RPBW, RPBW, RPBW, RPBW, RPBW, RPBW, RPBR - #define DOOR_TILE_TOP 0x2E #define DOOR_TILE_BOTTOM 0x0E #define DOOR_TILE_LEFT 0x0C #define DOOR_TILE_RIGHT 0x2C - - - ; translation tables for tiles -room_pattern_tile_translation: - ; walls - .db 0x02, 0x04, 0x06 - .db 0x22, 0x26, 0x46 - .db 0x44, 0x42 - .db 0x00 ; floor - ; doors - .db DOOR_TILE_TOP, DOOR_TILE_BOTTOM, DOOR_TILE_LEFT, DOOR_TILE_RIGHT - ; roof - .db 0x48 - - ; translation table for flags -room_pattern_flags_translation: - ; walls - .db CF_COLLISION, CF_COLLISION, CF_COLLISION - .db CF_COLLISION, CF_COLLISION, CF_COLLISION - .db CF_COLLISION, CF_COLLISION - .db 0x00 ; floor - ; doors - .db CF_COLLISION | CF_DOOR | CF_COVERED, CF_COLLISION | CF_DOOR | CF_COVERED - .db CF_COLLISION | CF_DOOR | CF_COVERED, CF_COLLISION | CF_DOOR | CF_COVERED - ; roof - .db CF_COVERED - - ; table of 6 by 6 room patterns -room_pattern_6x6: - ; dw room_pattern_empty - dw room_pattern1 - dw room_pattern1 - dw room_pattern2 - dw room_pattern3 -room_pattern_6x6_end: + + ; table of possible maps + ; must be divisible by 2 in size -#define ROOM_PATTERN_6X6_SIZE ((room_pattern_6x6_end - room_pattern_6x6) / 2) - +room_patterns_floor1: + dw map_c_header + dw map_ce_header + dw map_cw_header + dw map_be_header +room_patterns_floor1_end: - ; table of special room patterns -room_pattern_special: - dw room_pattern_special1 - dw room_pattern_special1 -room_pattern_special_end: -#define ROOM_PATTERN_SPECIAL_SIZE ((room_pattern_special_end - room_pattern_special) / 2)