add directional characters display

This commit is contained in:
2026-05-01 21:13:55 +02:00
parent 425b83b1bb
commit 8b3b2aa20d
23 changed files with 417 additions and 283 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+8 -2
View File
@@ -18,8 +18,14 @@ const spritesPath = {
"sprite_wall_end": "assets/sprites/wall_end.ppm", "sprite_wall_end": "assets/sprites/wall_end.ppm",
"sprite_wall_straight": "assets/sprites/wall_straight.ppm", "sprite_wall_straight": "assets/sprites/wall_straight.ppm",
"sprite_wall_corner": "assets/sprites/wall_corner.ppm", "sprite_wall_corner": "assets/sprites/wall_corner.ppm",
"sprite_robot": "assets/sprites/robot.ppm", "sprite_robot_up": "assets/sprites/robot_up.ppm",
"sprite_ghost": "assets/sprites/ghost.ppm", "sprite_robot_right": "assets/sprites/robot_right.ppm",
"sprite_robot_down": "assets/sprites/robot_down.ppm",
"sprite_robot_left": "assets/sprites/robot_left.ppm",
"sprite_ghost_up": "assets/sprites/ghost_up.ppm",
"sprite_ghost_right": "assets/sprites/ghost_right.ppm",
"sprite_ghost_down": "assets/sprites/ghost_down.ppm",
"sprite_ghost_left": "assets/sprites/ghost_left.ppm",
"sprite_coin": "assets/sprites/coin.ppm", "sprite_coin": "assets/sprites/coin.ppm",
}; };
-15
View File
@@ -2,18 +2,3 @@ pub const game.direction_up = 0
pub const game.direction_right = 1 pub const game.direction_right = 1
pub const game.direction_down = 2 pub const game.direction_down = 2
pub const game.direction_left = 3 pub const game.direction_left = 3
pub const game.direction_still = 4
/*
; 1_000_000_000 nano second = 0x0000_0000_3B9A_CA00
pub const game.tick_duration_0 = 0xCA00
pub const game.tick_duration_1 = 0x3B9A
pub const game.tick_duration_2 = 0x0000
pub const game.tick_duration_3 = 0x0000
*/
; 0.5 second = 500_000_000 nano second = 0x0000_0000_1DCD_6500
pub const game.tick_duration_0 = 0x6500
pub const game.tick_duration_1 = 0x1DCD
pub const game.tick_duration_2 = 0x0000
pub const game.tick_duration_3 = 0x0000
+15 -4
View File
@@ -7,12 +7,23 @@ pub const sprites.rotation_90 = 1
pub const sprites.rotation_180 = 2 pub const sprites.rotation_180 = 2
pub const sprites.rotation_270 = 3 pub const sprites.rotation_270 = 3
pub const sprites.empty = 0 pub const sprites.empty = 0 ; must stay 0 (some code avoid addition when it knows the tile is empty)
pub const sprites.unimplemented = 1 pub const sprites.unimplemented = 1
pub const sprites.wall_end = 2 pub const sprites.wall_end = 2
pub const sprites.wall_straight = 3 pub const sprites.wall_straight = 3
pub const sprites.wall_corner = 4 pub const sprites.wall_corner = 4
pub const sprites.robot = 5 pub const sprites.robot = 5
pub const sprites.ghost = 6 pub const sprites.robot_up = 5
pub const sprites.coin = 7 pub const sprites.robot_right = 6
pub const sprites.max = 7 ; for lookup table pub const sprites.robot_down = 7
pub const sprites.robot_left = 8
pub const sprites.ghost = 9
pub const sprites.ghost_up = 9
pub const sprites.ghost_right = 10
pub const sprites.ghost_down = 11
pub const sprites.ghost_left = 12
pub const sprites.coin = 13
pub const sprites.max = 13 ; for lookup table
+53
View File
@@ -41,6 +41,58 @@ pub drawing.draw_whole_map:
ret ret
/* Draw the tile corresponding to the given coordinate with it's map content
Inputs:
r1, r2: Map coordinates x, y
Locals:
r3: tile value / sprite id / sprite address offset
r9: pointer
r13: screen address
*/
pub drawing.clear_tile:
push r1
push r2
push r3
push r9
push r13
add r9, r1, map
push r2
pub drawing.clear_tile_row_loop:
cmp r2, 0
je drawing.clear_tile_row_loop_end
sub r2, r2, 1
add r9, r9, map.width
jmp drawing.clear_tile_row_loop
pub drawing.clear_tile_row_loop_end:
pop r2
load_8 r3, [r9]
cmp r3, map.tiles.coin
add r9, zr, ptr.textures_addresses
jne drawing.clear_tile_get_screen_address
; coin
mov r3, sprites.coin
lsl r3, r3, arch.instruction_increment_shift
add r9, r9, r3
pub drawing.clear_tile_get_screen_address:
call get_tile_address
mov r1, r13
load_32 r2, [r9]
mov r3, sprites.rotation_0
call draw_sprite
pop r13
pop r9
pop r3
pop r2
pop r1
ret
/* Return the top-left pixel address of the tile at the given map coordinates /* Return the top-left pixel address of the tile at the given map coordinates
Inputs: Inputs:
@@ -100,6 +152,7 @@ get_tile_address:
pop r3 pop r3
ret ret
/* Get address of given sprite id /* Get address of given sprite id
Inputs: Inputs:
+18
View File
@@ -0,0 +1,18 @@
/* Add two unsigned 64 bit
Input:
r1, r2: A.high, A.low
r3, r4: B.high, B.low
Output:
r5, r6: C.high, C.low
*/
pub u64.add:
add r5, r1, r3
add r6, r2, r4
cmp r6, r2
jae u64.add_no_low_overflow
add r5, r5, 1 ; overflow
pub u64.add_no_low_overflow:
ret
+33 -3
View File
@@ -17,10 +17,34 @@ include sections/init_timers
game_loop: game_loop:
include sections/handle_event include sections/handle_event
include sections/characters_movement
/*
For all timers:
r1, r2: tick duration high, low
r7, r8: now high, low
*/
add r9, zr, ptr.tick_duration_high
load_32 r1, [r9]
add r9, zr, ptr.tick_duration_low
load_32 r2, [r9]
time_0 r8
time_1 r7
push r1
push r2
push r7
push r8
include sections/timer_robot
pop r8
pop r7
pop r2
pop r1
include sections/timer_ghost
jmp game_loop jmp game_loop
include lib/u64
include lib/game include lib/game
include lib/drawing include lib/drawing
include lib/sprite_rotation include lib/sprite_rotation
@@ -30,8 +54,14 @@ include dist/placeholder
include dist/wall_end include dist/wall_end
include dist/wall_straight include dist/wall_straight
include dist/wall_corner include dist/wall_corner
include dist/robot include dist/robot_up
include dist/ghost include dist/robot_right
include dist/robot_down
include dist/robot_left
include dist/ghost_up
include dist/ghost_right
include dist/ghost_down
include dist/ghost_left
include dist/coin include dist/coin
include dist/map include dist/map
+13 -4
View File
@@ -5,8 +5,14 @@ U32 0 ; placeholder
U32 0 ; wall_end U32 0 ; wall_end
U32 0 ; wall_straight U32 0 ; wall_straight
U32 0 ; wall_corner U32 0 ; wall_corner
U32 0 ; robot U32 0 ; robot up
U32 0 ; ghost U32 0 ; robot right
U32 0 ; robot down
U32 0 ; robot left
U32 0 ; ghost up
U32 0 ; ghost right
U32 0 ; ghost down
U32 0 ; ghost left
U32 0 ; coin U32 0 ; coin
; 0.5 second = 500_000_000 nano second = 0x0000_0000_1DCD_6500 ; 0.5 second = 500_000_000 nano second = 0x0000_0000_1DCD_6500
@@ -17,8 +23,11 @@ pub ptr.tick_duration_low: U32 0x1DCD_6500
; pub ptr.tick_duration_high: U32 0x0000_0000 ; pub ptr.tick_duration_high: U32 0x0000_0000
; pub ptr.tick_duration_low: U32 0x3B9A_CA00 ; pub ptr.tick_duration_low: U32 0x3B9A_CA00
pub ptr.next_tick_high: U32 0 pub ptr.timer_robot_next_tick_high: U32 0x0000_0000
pub ptr.next_tick_low: U32 0 pub ptr.timer_robot_next_tick_low: U32 0x1DCD_6500
pub ptr.timer_ghost_next_tick_high: U32 0
pub ptr.timer_ghost_next_tick_low: U32 0
pub ptr.state_robot: pub ptr.state_robot:
U8 0 ; x coord U8 0 ; x coord
-231
View File
@@ -1,231 +0,0 @@
/* Elapsed time check
r1: address
r2: now low / delay low
r3: now high / delay high
r4: next tick low
r5: next tick high
*/
time_0 r2
time_1 r3
add r1, zr, ptr.next_tick_low
load_32 r4, [r1]
add r1, zr, ptr.next_tick_high
load_32 r5, [r1]
cmp r3, r5
jb game_loop
ja update_next_tick
cmp r2, r4
jb game_loop
update_next_tick:
add r1, zr, ptr.tick_duration_low
load_32 r2, [r1]
add r1, zr, ptr.tick_duration_high
load_32 r3, [r1]
add r4, r4, r2
add r5, r5, r3
cmp r4, r2
jae store_next_tick
add r5, r5, 1
store_next_tick:
add r1, zr, ptr.next_tick_low
store_32 [r1], r4
add r1, zr, ptr.next_tick_high
store_32 [r1], r5
/* Robot movement
r1 = robot's state address
r2 = x
r3 = y
r4 = direction
r5 = new x
r6 = new y
r7 = new position address
r8 = new position content
r9 = jump address
*/
add r1, zr, ptr.state_robot
load_8 r2, [r1]
add r1, r1, 1
load_8 r3, [r1]
add r1, r1, 1
load_8 r4, [r1]
mov r5, r2
mov r6, r3
lsl r9, r4, 3 ; 2 * instruction size = 8
add r9, r9, game_loop_robot_movement_jump_table_start
jmp r9
game_loop_robot_movement_jump_table_start:
; direction_up
sub r6, r6, 1
jmp game_loop_robot_movement_try_move
; direction_right
add r5, r5, 1
jmp game_loop_robot_movement_try_move
; direction_down
add r6, r6, 1
jmp game_loop_robot_movement_try_move
; direction_left
sub r5, r5, 1
jmp game_loop_robot_movement_try_move
; direction_still
jmp game_loop_robot_movement_none
game_loop_robot_movement_try_move:
push r2
mov r1, r5
mov r2, r6
call game.get_tile_address_from_map_coord
mov r7, r13
pop r2
/*
Collision handling
*/
load_8 r8, [r7]
cmp r8, map.tiles.wall
jne game_loop_robot_movement_some
; hit wall
add r1, zr, ptr.state_robot
add r1, r1, 2
mov r4, game.direction_still
store_8 [r1], r4
jmp game_loop_robot_movement_none
game_loop_robot_movement_some:
; TODO: handle coin and empty differently
mov r8, map.tiles.empty
store_8 [r7], r8
add r1, zr, ptr.state_robot
store_8 [r1], r5
add r1, r1, 1
store_8 [r1], r6
; clear old position
mov r1, r2
mov r2, r3
mov r3, sprites.rotation_0
mov r4, sprites.empty
call drawing.draw_sprite_at_map_coord
; draw robot on new position
mov r1, r5
mov r2, r6
mov r3, sprites.rotation_0
mov r4, sprites.robot
call drawing.draw_sprite_at_map_coord
game_loop_robot_movement_none:
/* Ghost movement
r1: ghost's state address
r2: x
r3: y
r4: direction
r5: x increment
r6: y increment
r7: new x
r8: new y
r9: new position address
r10: new position content
r11: jump address
*/
add r1, zr, ptr.state_ghost
load_8 r2, [r1]
add r1, r1, 1
load_8 r3, [r1]
add r1, r1, 1
load_8 r4, [r1]
mov r5, 0
mov r6, 0
lsl r11, r4, 3 ; 2 * instruction size = 8
add r11, r11, game_loop_ghost_movement_jump_table_start
jmp r11
game_loop_ghost_movement_jump_table_start:
; direction_up
sub r6, r6, 1
jmp game_loop_ghost_movement_make_move
; direction_right
add r5, r5, 1
jmp game_loop_ghost_movement_make_move
; direction_down
add r6, r6, 1
jmp game_loop_ghost_movement_make_move
; direction_left
sub r5, r5, 1
;jmp game_loop_ghost_movement_make_move
; direction_still (should never happen)
game_loop_ghost_movement_make_move:
add r7, r2, r5
add r8, r3, r6
add r1, zr, ptr.state_ghost
store_8 [r1], r7
add r1, r1, 1
store_8 [r1], r8
; get tile at previous position
push r2
mov r1, r2
mov r2, r3
call game.get_tile_address_from_map_coord
mov r9, r13
pop r2
; draw tile at previous position
load_8 r1, [r9]
cmp r1, map.tiles.coin
je game_loop_ghost_movement_old_tile_coin
; old tile empty
mov r4, sprites.empty
jmp game_loop_ghost_movement_draw_old_tile
game_loop_ghost_movement_old_tile_coin:
mov r4, sprites.coin
game_loop_ghost_movement_draw_old_tile:
mov r1, r2
mov r2, r3
mov r3, sprites.rotation_0
call drawing.draw_sprite_at_map_coord
; draw ghost on new position
mov r1, r7
mov r2, r8
mov r3, sprites.rotation_0
mov r4, sprites.ghost
call drawing.draw_sprite_at_map_coord
/*
Check ahead for direction change
*/
add r1, r7, r5
add r2, r8, r6
call game.get_tile_address_from_map_coord
load_8 r10, [r13]
cmp r10, map.tiles.wall
jne game_loop_ghost_movement_end
; increment direction
add r1, zr, ptr.state_ghost
add r1, r1, 2
load_8 r4, [r1]
add r4, r4, 1
and r4, r4, 0b11 ; modulo 3
store_8 [r1], r4
game_loop_ghost_movement_end:
+1 -1
View File
@@ -13,5 +13,5 @@ add r6, r6, 1
store_8 [r6], r5 store_8 [r6], r5
mov r3, sprites.rotation_0 mov r3, sprites.rotation_0
mov r4, sprites.ghost mov r4, sprites.ghost_down
call drawing.draw_sprite_at_map_coord call drawing.draw_sprite_at_map_coord
+1 -1
View File
@@ -13,5 +13,5 @@ add r6, r6, 1
store_8 [r6], r5 store_8 [r6], r5
mov r3, sprites.rotation_0 mov r3, sprites.rotation_0
mov r4, sprites.robot mov r4, sprites.robot_down
call drawing.draw_sprite_at_map_coord call drawing.draw_sprite_at_map_coord
+45 -6
View File
@@ -35,18 +35,57 @@ lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses add r2, r2, ptr.textures_addresses
add r3, zr, sprite_wall_corner add r3, zr, sprite_wall_corner
store_32 [r2], r3 store_32 [r2], r3
; sprite_robot
add r1, zr, sprites.robot ; sprite_robot_up
add r1, zr, sprites.robot_up
lsl r2, r1, arch.instruction_increment_shift lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses add r2, r2, ptr.textures_addresses
add r3, zr, sprite_robot add r3, zr, sprite_robot_up
store_32 [r2], r3 store_32 [r2], r3
; sprite_ghost ; sprite_robot_right
add r1, zr, sprites.ghost add r1, zr, sprites.robot_right
lsl r2, r1, arch.instruction_increment_shift lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses add r2, r2, ptr.textures_addresses
add r3, zr, sprite_ghost add r3, zr, sprite_robot_right
store_32 [r2], r3 store_32 [r2], r3
; sprite_robot_down
add r1, zr, sprites.robot_down
lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses
add r3, zr, sprite_robot_down
store_32 [r2], r3
; sprite_robot_left
add r1, zr, sprites.robot_left
lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses
add r3, zr, sprite_robot_left
store_32 [r2], r3
; sprite_ghost_up
add r1, zr, sprites.ghost_up
lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses
add r3, zr, sprite_ghost_up
store_32 [r2], r3
; sprite_ghost_right
add r1, zr, sprites.ghost_right
lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses
add r3, zr, sprite_ghost_right
store_32 [r2], r3
; sprite_ghost_down
add r1, zr, sprites.ghost_down
lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses
add r3, zr, sprite_ghost_down
store_32 [r2], r3
; sprite_ghost_left
add r1, zr, sprites.ghost_left
lsl r2, r1, arch.instruction_increment_shift
add r2, r2, ptr.textures_addresses
add r3, zr, sprite_ghost_left
store_32 [r2], r3
; sprite_coin ; sprite_coin
add r1, zr, sprites.coin add r1, zr, sprites.coin
lsl r2, r1, arch.instruction_increment_shift lsl r2, r1, arch.instruction_increment_shift
+32 -16
View File
@@ -1,18 +1,34 @@
add r1, zr, ptr.tick_duration_low /*
load_32 r2, [r1] r1, r2: now high, low
add r1, zr, ptr.tick_duration_high r3, r4: initial delay high, low
load_32 r3, [r1] r5, r6: next tick high, low
r7: pointer
*/
time_0 r2
time_1 r1
time_0 r4 ; Robot
time_1 r5 add r7, zr, ptr.timer_robot_next_tick_high
add r4, r4, r2 load_32 r3, [r7]
add r5, r5, r3 add r7, zr, ptr.timer_robot_next_tick_low
cmp r4, r2 load_32 r4, [r7]
jae init_store_next_tick
add r5, r5, 1 ; overflow
init_store_next_tick: call u64.add
add r1, zr, ptr.next_tick_low
store_32 [r1], r4 add r7, zr, ptr.timer_robot_next_tick_high
add r1, zr, ptr.next_tick_high store_32 [r7], r5
store_32 [r1], r5 add r7, zr, ptr.timer_robot_next_tick_low
store_32 [r7], r6
; Ghost
add r7, zr, ptr.timer_ghost_next_tick_high
load_32 r3, [r7]
add r7, zr, ptr.timer_ghost_next_tick_low
load_32 r4, [r7]
call u64.add
add r7, zr, ptr.timer_ghost_next_tick_high
store_32 [r7], r5
add r7, zr, ptr.timer_ghost_next_tick_low
store_32 [r7], r6
+99
View File
@@ -0,0 +1,99 @@
/* Timer comparison / update
r1, r2: tick duration high, low [IN]
r3, r4: next tick high, low
r5, r6: tick after this one high, low
r7, r8: now high, low [IN]
r9: pointer
*/
add r9, zr, ptr.timer_ghost_next_tick_high
load_32 r3, [r9]
add r9, zr, ptr.timer_ghost_next_tick_low
load_32 r4, [r9]
cmp r7, r3
jb timer_ghost.end
ja timer_ghost.trigger
cmp r8, r4
jb timer_ghost.end
pub timer_ghost.trigger:
; udate next_tick
call u64.add
add r9, zr, ptr.timer_ghost_next_tick_high
store_32 [r9], r5
add r9, zr, ptr.timer_ghost_next_tick_low
store_32 [r9], r6
/* Movement
r1, r2: x, y
r3: rotation
r4: direction / sprite id
r5, r6: increments x, y
r7, r8: [RESERVED]
r9: pointer
r10: tile content
r13: tile address
*/
add r9, zr, ptr.state_ghost
load_8 r1, [r9]
add r9, r9, 1
load_8 r2, [r9]
add r9, r9, 1
load_8 r4, [r9]
call drawing.clear_tile
mov r5, 0
mov r6, 0
lsl r9, r4, 3 ; 2 * instruction size = 8
add r9, r9, timer_ghost.direction_jump_table
jmp r9
pub timer_ghost.direction_jump_table:
; direction_up
sub r6, r6, 1
jmp timer_ghost.move
; direction_right
add r5, r5, 1
jmp timer_ghost.move
; direction_down
add r6, r6, 1
jmp timer_ghost.move
; direction_left
sub r5, r5, 1
;jmp timer_ghost.move
pub timer_ghost.move:
add r1, r1, r5
add r2, r2, r6
add r9, zr, ptr.state_ghost
store_8 [r9], r1
add r9, r9, 1
store_8 [r9], r2
; draw ghost on new position
mov r3, sprites.rotation_0
add r4, r4, sprites.ghost
call drawing.draw_sprite_at_map_coord
/*
Check ahead for direction change
*/
add r1, r1, r5
add r2, r2, r6
call game.get_tile_address_from_map_coord
load_8 r10, [r13]
cmp r10, map.tiles.wall
jne timer_ghost.end
; increment direction
add r9, zr, ptr.state_ghost
add r9, r9, 2
load_8 r4, [r9]
add r4, r4, 1
and r4, r4, 0b11 ; modulo 3
store_8 [r9], r4
pub timer_ghost.end:
+99
View File
@@ -0,0 +1,99 @@
/* Timer comparison / update
r1, r2: tick duration high, low [IN]
r3, r4: next tick high, low
r5, r6: tick after this one high, low
r7, r8: now high, low [IN]
r9: pointer
*/
add r9, zr, ptr.timer_robot_next_tick_high
load_32 r3, [r9]
add r9, zr, ptr.timer_robot_next_tick_low
load_32 r4, [r9]
cmp r7, r3
jb timer_robot.end
ja timer_robot.trigger
cmp r8, r4
jb timer_robot.end
pub timer_robot.trigger:
; udate next_tick
call u64.add
add r9, zr, ptr.timer_robot_next_tick_high
store_32 [r9], r5
add r9, zr, ptr.timer_robot_next_tick_low
store_32 [r9], r6
/* Movement
r1, r2: x, y
r3: rotation
r4: direction / sprite id
r5, r6: increments x, y
r7, r8: [RESERVED]
r9: pointer
r10: tile content
r13: tile address
*/
add r9, zr, ptr.state_robot
load_8 r1, [r9]
add r9, r9, 1
load_8 r2, [r9]
add r9, r9, 1
load_8 r4, [r9]
call drawing.clear_tile
mov r5, 0
mov r6, 0
lsl r9, r4, 3 ; 2 * instruction size = 8
add r9, r9, timer_robot.direction_jump_table
jmp r9
pub timer_robot.direction_jump_table:
; direction_up
sub r6, r6, 1
jmp timer_robot.try_move
; direction_right
add r5, r5, 1
jmp timer_robot.try_move
; direction_down
add r6, r6, 1
jmp timer_robot.try_move
; direction_left
sub r5, r5, 1
;jmp timer_robot.try_move
/*
Collision handling
*/
pub timer_robot.try_move:
add r1, r1, r5
add r2, r2, r6
call game.get_tile_address_from_map_coord
load_8 r10, [r13]
cmp r10, map.tiles.wall
jne timer_robot.move
; hit wall -> cancel movement
sub r1, r1, r5
sub r2, r2, r6
jmp timer_robot.draw
pub timer_robot.move:
; TODO: handle coin and empty differently
mov r10, map.tiles.empty
store_8 [r13], r10
add r9, zr, ptr.state_robot
store_8 [r9], r1
add r9, r9, 1
store_8 [r9], r2
pub timer_robot.draw:
; draw robot on new position
mov r3, sprites.rotation_0
add r4, r4, sprites.robot
call drawing.draw_sprite_at_map_coord
pub timer_robot.end: