This will be a full-on rework of the engine.
.PHONY: maps
maps:
./tools/tms2map.py assets/maps/base.tmx base_room > maps/base_room.s
- ./tools/tms2map.py assets/maps/base2.tmx base_room2 > maps/base_room2.s
- ./tools/tms2map.py assets/maps/base3.tmx base_room3 > maps/base_room3.s
- ./tools/tms2map.py assets/maps/base4.tmx base_room4 > maps/base_room4.s
- ; struct for base_room
-base_room_header:
-dw base_room_bg
-dw base_room_flags
-dw base_room_actors
-dw room_empty_exits
-base_room_actors:
-.db 1 , 0x50 , 0x60 , 0
-.db 1 , 0x20 , 0x30 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
base_room_bg:
-.db 0x60, 0x62, 0x62, 0x64, 0x62, 0x62, 0x66, 0x62, 0x62, 0x68, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x6a, 0x46, 0x40, 0x82, 0x40, 0x40, 0x40, 0x40, 0x82, 0x40, 0xe0, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x6a, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x6a, 0x48, 0x40, 0x82, 0x40, 0x40, 0x40, 0x40, 0x82, 0x40, 0xe2, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x6a, 0x6c, 0x4a, 0x4a, 0x42, 0x4a, 0x4a, 0x44, 0x4a, 0x4a, 0x6e
-base_room_flags:
-.db 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1
+
+.db 0x80, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24
+.db 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x80
+++ /dev/null
- ; struct for base_room2
-base_room2_header:
-dw base_room2_bg
-dw base_room2_flags
-dw base_room2_actors
-dw room_empty_exits
-base_room2_actors:
-.db 1 , 0x30 , 0x40 , 0
-.db 1 , 0x20 , 0x30 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-base_room2_bg:
-.db 0x60, 0x62, 0x62, 0x64, 0x62, 0x62, 0x66, 0x62, 0x62, 0x68, 0x4c, 0x40, 0x40, 0x82, 0x40, 0x40, 0x82, 0x40, 0x40, 0x6a, 0x46, 0x82, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x82, 0xe0, 0x4c, 0x40, 0x40, 0x82, 0xe8, 0xe8, 0x82, 0x40, 0x40, 0x6a, 0x4c, 0x40, 0x40, 0x82, 0xe8, 0xe8, 0x82, 0x40, 0x40, 0x6a, 0x48, 0x82, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x82, 0xe2, 0x4c, 0x40, 0x40, 0x82, 0x40, 0x40, 0x82, 0x40, 0x40, 0x6a, 0x6c, 0x4a, 0x4a, 0x42, 0x4a, 0x4a, 0x44, 0x4a, 0x4a, 0x6e
-base_room2_flags:
-.db 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1
+++ /dev/null
- ; struct for base_room3
-base_room3_header:
-dw base_room3_bg
-dw base_room3_flags
-dw base_room3_actors
-dw room_empty_exits
-base_room3_actors:
-.db 1 , 0x60 , 0x80 , 0
-.db 1 , 0x10 , 0x10 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-base_room3_bg:
-.db 0x60, 0x62, 0x62, 0x64, 0x62, 0x62, 0x66, 0x62, 0x62, 0x68, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x6a, 0x46, 0x40, 0x40, 0x40, 0x82, 0x82, 0x40, 0x40, 0x40, 0xe0, 0x4c, 0x40, 0x82, 0x40, 0x40, 0x40, 0x40, 0x82, 0x40, 0x6a, 0x4c, 0x40, 0x82, 0x40, 0x40, 0x40, 0x40, 0x82, 0x40, 0x6a, 0x48, 0x40, 0x40, 0x40, 0x82, 0x82, 0x40, 0x40, 0x40, 0xe2, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x6a, 0x6c, 0x4a, 0x4a, 0x42, 0x4a, 0x4a, 0x44, 0x4a, 0x4a, 0x6e
-base_room3_flags:
-.db 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1
+++ /dev/null
- ; struct for base_room4
-base_room4_header:
-dw base_room4_bg
-dw base_room4_flags
-dw base_room4_actors
-dw room_empty_exits
-base_room4_actors:
-.db 1 , 0x60 , 0x80 , 0
-.db 1 , 0x10 , 0x10 , 0
-.db 1 , 0x10 , 0x80 , 0
-.db 1 , 0x60 , 0x10 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-.db 0 , 0x0 , 0x0 , 0
-base_room4_bg:
-.db 0x60, 0x62, 0x62, 0x64, 0x62, 0x62, 0x66, 0x62, 0x62, 0x68, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x6a, 0x46, 0x40, 0x40, 0x82, 0x82, 0x82, 0x82, 0x40, 0x40, 0xe0, 0x4c, 0x40, 0x82, 0x40, 0x40, 0x40, 0x40, 0x82, 0x40, 0x6a, 0x4c, 0x40, 0x82, 0x40, 0x40, 0x40, 0x40, 0x82, 0x40, 0x6a, 0x48, 0x40, 0x40, 0x40, 0x82, 0x82, 0x40, 0x40, 0x40, 0xe2, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x6a, 0x6c, 0x4a, 0x4a, 0x42, 0x4a, 0x4a, 0x44, 0x4a, 0x4a, 0x6e
-base_room4_flags:
-.db 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1
+++ /dev/null
-
-#define BAT_TILE_IDLE1 0x22
-#define BAT_TILE_IDLE2 0x32
-
- ; skips actor if acto != who
- ; returns:
- ; nz: if actor is not who
-#macro actor_check_who
- ; if who is current actor simply
- ; skip
- ld a, [act]
- ld d, a
- ld a, [who]
- cp a, d
-#endmacro
-
- ; skips a turn by calling turn_finish
- ; and who_next
-#macro actor_end_turn
- turn_finish
- call who_next
-#endmacro
-
-
- ; stores hl back into soam ptr
-#macro actor_store_soam_ptr
- ; store soam ptr again
- ld a, l
- ld [actor_soam_ptr+1], a
- ld a, h
- ld [actor_soam_ptr], a
-#endmacro
-
-actor_anim_table_bat:
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE1
-.db BAT_TILE_IDLE2
-.db BAT_TILE_IDLE2
-.db BAT_TILE_IDLE2
-.db BAT_TILE_IDLE2
-.db BAT_TILE_IDLE2
-.db BAT_TILE_IDLE2
-.db BAT_TILE_IDLE2
-
-
-; function ptrs for each actor type
-; inputs:
-; bc: actor ptr
-; actor_soam_ptr: next soam item
-actor_update_table:
- dw actor_update_null
- dw actor_update_bat
-
-actor_update_null:
- actor_check_who
- ret nz
-
- ; actor_end_turn
- turn_finish
- jp who_next
-
- ; bat actor
-actor_update_bat:
- actor_check_who
- call z, draw_cursor
- jr nz, @skip REL
-
- ; call state update
- ld a, smt_bat_pick_direction
- ; load initial state if required
- call sm_load_initial_state
-
- push bc
- call sm_call_state
- pop bc
-
-@skip:
- ; load tile to use into tmp
- load_anim_frame actor_anim_table_bat, 0b1111
- ld [tmp], a
-
- ; load oam ptr
- ld a, [actor_soam_ptr]
- ld h, a
- ld a, [actor_soam_ptr+1]
- ld l, a
-
- inc bc ; bc = actor_y
-
- ; tile 1
- ld a, [bc] ; a = y
- add a, OBJ_OFF_Y
- ld [hl+], a ; set y
- inc bc ; bc = actor_x
-
- ld a, [bc] ; a = x
- add a, OBJ_OFF_X
- ld [hl+], a ; set x
-
- ld a, [tmp]
- ld [hl+], a
-
- xor a, a
- ld [hl+], a
-
- ; tile 2
- dec bc ; bc = actor_y
- ld a, [bc]
- add a, OBJ_OFF_Y
- ld [hl+], a ; set y
-
- inc bc ; bc = actor_x
- ld a, [bc]
- add a, OBJ_OFF_X
- add a, 8
- ld [hl+], a ; set x
-
- ld a, [tmp]
- ld [hl+], a
-
- ld a, OAM_FXFLIP
- ld [hl+], a
-
- actor_store_soam_ptr
-
- ret
-
-
- ; updates all active actors from
- ; the current actor table
-actors_update:
- ; reset soam ptr
- xor a, a
- ldlo a, shadow_oam
- add a, 10 * oamsize ; starting at oam 10
- ld [actor_soam_ptr+1], a
- ldhi a, shadow_oam
- ld [actor_soam_ptr], a
-
- ld d, ACTORS_MAX ; loop counter
- ld bc, actor_table
-@loop:
-
- push de
- push bc
-
- ; store current actor in act
- ld a, d
- dec a ; -1 to get 0-index counter
- ld [act], a
-
- ld hl, actor_update_table
- ld a, [bc]
- call call_tbl
-
- pop bc
- pop de
-
- ; inc de sizeof(actor) times
- .rep i, actor_size, 1, inc bc
- dec d
- ld a, d
- jr nz, @loop REL
-
- ret
-
-
- ; draws cursor at the active actor's location
- ; inputs:
- ; bc: actor_ptr
-draw_cursor:
- push_all
-
- inc bc
- ld a, [bc]
- ld d, a ; d = y
- inc bc
- ld a, [bc]
- ld e, a ; e = x
-
-@draw:
- ; draw obj
- ld hl, PLAYER_SPRITE1+12
- ld a, d ; a = y
- add a, OBJ_OFF_Y
- ld [hl+], a
-
- ld a, e ; a = x
- add a, OBJ_OFF_X
- ld [hl+], a
-
- ld a, CURSOR_TILE
- ld [hl+], a
-
- xor a, a
- ld [hl], a
-
- pop_all
-
- ret
-
- ; generic collision check code
- ; loads ct_mask and actor position
- ; and calls collision tile
- ; inputs:
- ; bc: actor ptr
- ; de: y/x position offset
- ; returns:
- ; a/h: collision flags
-generic_collision_check:
- ; load actor y/x into de
- inc bc ; bc = actor y
- ld a, [bc]
- add a, d ; y + offset
-
- ld d, a ; d = target y
- inc bc ; bc = actor x
- ld a, [bc]
- add a, e ; x + offset
- ld e, a ; e = target x
-
- ; if any collision happens now
- ; we stop the animation
- call collision_tile
- ld h, a ; store original a in h for now
- ret
-
- ; performs a simple collision check for actors
- ; inputs:
- ; bc: actor ptr
- ; de: y/x position offset
-act_collision_check:
- ; set collision mask
- ld a, RF_WALL | RF_ACTOR | RF_DOOR
- ld [ct_mask], a
-
- call generic_collision_check
-
- and a, RF_WALL | RF_ACTOR | RF_DOOR
- jr z, @skip REL
- ; abort walk state
- call anim_abort_walk
- jr @skip REL
-@skip:
- ret
-
- ; advance to the next actor if end_turn != 0
- ; effectively ending the current actor's turn
-who_next:
- ld a, [end_turn]
- and a, a ; check for 0
- ret z
-
- xor a, a
- ld [end_turn], a
-
- ld a, [who]
- inc a ; who++
-
- ; if who > actor_max
- ; go to player
- cp a, ACTORS_MAX
- jr nz, @no_player REL
- ld a, WHO_PLAYER
-@no_player:
- ld [who], a
-
- call sm_advance
-
- ret
+++ /dev/null
-; animations can be queued
-; each frame the latest animation is
-; updated
-
- ; anim_walk_<direction> inputs
- ; sm_param[0]: frames to walk for
-anim_walk_north:
- inc bc ; bc = actor y
- ld d, 0xFF & 0 - ANIM_WALK_SPEED ; walk back
- jp anim_walk_generic
-
-anim_walk_south:
- inc bc ; bc = actor y
- ld d, ANIM_WALK_SPEED ; walk forward
- jp anim_walk_generic
-
-anim_walk_east:
- inc bc
- inc bc ; bc = actor x
- ld d, ANIM_WALK_SPEED ; walk forward
- jp anim_walk_generic
-
-anim_walk_west:
- inc bc
- inc bc ; bc = actor x
- ld d, 0xFF & 0 - ANIM_WALK_SPEED ; walk back
- jp anim_walk_generic
-
- ; generic version of anim walk
- ; inputs:
- ; bc: position to walk in
- ; d: offset per frame
-anim_walk_generic:
- sm_load_ptr hl
- inc hl ; hl = param
- ld a, [hl]
- cp a, 0
- jp z, anim_walk_end
-
- dec a
- ld [hl], a ; p0--
-
- ld a, [bc]
- add a, d
- ld [bc], a ; y++
- ret
-
- ; aborts walk
- ; inputs:
- ; none
-anim_abort_walk:
- sm_load_ptr hl
- inc hl
-
- ; inputs:
- ; hl: sm_param[0]
-anim_walk_end:
- dec hl ; hl = sm_state
- ld a ,smt_end_turn
- ld [hl], a
- ret
+++ /dev/null
-
-
- ; checks a point
- ; with a map's meta tile
- ; if the tile has collision flag set
- ; returns 1 otherwise 0
- ; inputs:
- ; d : y pos
- ; e : x pos
- ; ct_mask: bit mask for flag to check (tile & mask)
- ; returns:
- ; a = 0 -> no collision
- ; a = 1 -> collision
-collision_tile:
- ld a, [ct_mask]
- jp room_get_flag_masked
-
+++ /dev/null
-combat_init:
- ret
#define STACK_BEGIN 0xDFFF
-#define ACTORS_MAX 8
-#define ACTOR_TABLE_SIZE ACTORS_MAX * actor_size
-
-#define PLAYER_DEFAULT_HP 3
-#define PLAYER_DEFAULT_MP 3
-#define PLAYER_DEFAULT_DEF 0
-#define PLAYER_DEFAULT_ATK 1
-
-
-#define NORTH 0
-#define EAST 1
-#define SOUTH 2
-#define WEST 3
-#define EXIT_SPECIAL 4
-
-#define ROOMS_TOTAL 16
-
- ; rooms are 9x9 meta tiles
-#define ROOM_W 10
-#define ROOM_H 8
-#define ROOM_EXITS_MAX 5
- ; table of ptrs
-#define ROOM_EXIT_TABLE_SIZE ROOM_EXITS_MAX * 2
-
-#define ROOM_TILES_SIZE (ROOM_W * ROOM_H)
-#define ROOM_FLAGS_SIZE (ROOM_W * ROOM_H)
-
-#define TILE_POS_MASK 0xF0
-
-
-#define ANIM_MOVE_TILE_SIZE 16
-
-#define WHO_PLAYER 0xFF
+#define TILE_SIZE 8
+#define MAP_W 32
+#define MAP_H 28
; seed for the rng
; 8 bit signed int
#define RAND_MAGIC 0x1B
#define SRAND_INITIAL 0x19
- ; -TILE_SIZE
-#define ANIM_MOVE_TILE_SIZE_N 0xFF - ANIM_MOVE_TILE_SIZE + 1
-#define ANIM_STEP_DOWN 1
-#define ANIM_STEP_LEFT 0xFF
-#define ANIM_STEP_UP 0xFF
-#define ANIM_STEP_RIGHT 1
-
-#define ANIM_WALK_SPEED 1
-#define ANIM_TILE_SIZE 16
-#define ANIM_PLAYER_WALK_FRAMES (ANIM_TILE_SIZE / ANIM_WALK_SPEED)
-
-; actor type enum
-.se 0
- ; null actor type = nop
-.de ACTOR_TYPE_NULL, 1
-.de ACTOR_TYPE_BAT, 1
-
-
-; struct actor
-.se 0
-.de actor_type, 1
-.de actor_y, 1
-.de actor_x, 1
-.de actor_flags, 1
-.de actor_size, 0
-
-
-; player flags bitfield
-.se 1
- ; when set this puts the player state into cursor mode
- ; allowing the selection of a tile to
- ; perform an action in
-.de PLAYER_FCURSOR, 1
-
-; struct player
-.se 0
-.de player_y, 1
-.de player_x, 1
-.de player_flags, 1
-
- ; player stats
-.de player_hp, 1
-.de player_hp_max, 1
-.de player_mp, 1
-.de player_mp_max, 1
-.de player_def, 1
-.de player_def_max, 1
-.de player_atk, 1
-.de player_atk_max, 1
-
- ; player timer:
- ; differnt timers for the player
- ; iframe (i)
- ; layout:
- ; iiiiiiii
-.de player_timer_i, 1
-.de player_size, 0
-
-
-; struct room
-; FIXME: thse ptrs are currently in big endian...
-.se 0
-.de room_tiles, 2 ; be ptr to tiles
-.de room_flags, 2 ; be ptr to flags
-.de room_actor_table, 2 ; be ptr of actor table to be used
-.de room_exit_table, 2 ; list of ptrs to new rooms
-.de room_size, 0
-
-; room flags
-.se 1
- ; set if a tile is a wall
-.de RF_WALL, 1
- ; set if a tile is a door
-.de RF_DOOR, 2
- ; set if a tile is blocked by an actor
- ; if this flag is set
- ; collision resolution will
- ; need to look up the actor in question by
- ; iterating over the actor table + player
- ; and checking each position
- ; note: if RF_ACTOR is set the highest 4 bits of RF flags will
- ; be set to the actor's id
-.de RF_ACTOR, 4
- ; same as RF_ACTOR, but for the player
-.de RF_PLAYER, 8
-
-
- ; total size of a room including the struct header
- ; tiles, flags, actors and exits
- ; rooms are always in the order specified here:
- ; room_header, tiles, flags, actor_table, exit_table
-
- ; room body including all tiles, flags, actors
- ; and exits
-.se 0
-.de roomb_header, room_size
-.de roomb_tiles, ROOM_TILES_SIZE
-.de roomb_flags, ROOM_FLAGS_SIZE
-.de roomb_actors, ACTOR_TABLE_SIZE
-.de roomb_exits, ROOM_EXIT_TABLE_SIZE
-.de roomb_size, 0
-
-#define SAVE_GAME_VER 0
-
- ; save game struct
-.se 0
- ; checksum of save game
- ; this is simply all bytes in the save game added
-.de save_game_chksm, 1
- ; version of save game
-.de save_game_version, 1
- ; saving rng seed
-.de save_game_srand, 1
- ; saving floor number
-.de save_game_floor, 1
- ; saving all room headers
- ; it is important to ensure
- ; that the rooms are loaded back in their intended memory space
- ; to not corrupt room header pointers
- ; saving player state
-.de save_game_rooms, roomb_size * ROOMS_TOTAL
-.de save_game_player, player_size
- ; this is a canary value to detect out of bounds reads in sram
- ; if this value is not SRAM_MAGIC then the save game is corrupted
-.de save_game_canary, 1
-.de save_game_size, 0
-
- ; drawing related flags
-
- ; UI flags
-.se 1
-.de UI_REDRAW_HP, 1
-.de UI_REDRAW_MP, 2
-.de UI_REDRAW_ATK, 4
-.de UI_REDRAW_DEF, 8
; engine flags
.se 1
.se 0
.de GM_GAME, 1
.de GM_PAUSE, 1
-.de GAME_OVER, 1
- ; struct state
-.se 0
-.de sm_state, 1
-.de sm_param, 2
-.de sm_size, 0
-
-; state table entries
-.se 1
-.de smt_end_turn, 1
-.de smt_player_poll_inputs, 1
-.de smt_actor_go_north, 1
-.de smt_actor_go_south, 1
-.de smt_actor_go_east, 1
-.de smt_actor_go_west, 1
-.de smt_bat_pick_direction, 1
.db $1 & 0xFF
#endmacro
- ; sets turn to end
-#macro turn_finish
- ld a, 1
- ld [end_turn], a
-#endmacro
- ; loads an animation frame
- ; from a table
- ; uses hl and a
- ; inputs:
- ; $1: table
- ; $2: max frames (mask)
- ; returns:
- ; a: the frame
-#macro load_anim_frame
- ld hl, $1
- ld a, [frame_count]
- and a, $2 ; max frames
- ld d, 0
- ld e, a
- add hl, de ; hl = correct tile index
- ld a, [hl]
-#endmacro
; divides a regiser by 16
; inputs:
#endmacro
- ; loads the state machine ptr
- ; into $1
- ; inptuts:
- ; $1: register (hl, de, bc)
-#macro sm_load_ptr
- ; TODO: take into account offset for each
- ; actor by adding who*sm_size to hl
- ; => also need to reserve wram for this purpose
- push de
- ld $1, state_machine
- ld a, [state_machine_offset]
- ld e, a
- ld d, 0
- add hl, de
- pop de
-#endmacro
#include "oam.s"
#include "defs.s"
#include "wram.s"
-#include "mapram.s"
#include "hram.s"
#include "sram.s"
call lcd_on
call vblank_wait
- ld hl, player
call player_init
call enableinterrupts
#include "input.s"
#include "player.s"
#include "update.s"
-#include "map.s"
#include "ui.s"
-#include "collision.s"
-#include "actor.s"
#include "audio.s"
-#include "animation.s"
-#include "combat.s"
-#include "state.s"
+#include "map.s"
+#include "simulation.s"
#include "tiles.inc"
- ; map tiles
- ; tiles are 2x2 areas
- ; this simply defines the first tile
- ; in the set
-#define TFLOOR1 0x40
-
-#define TCORNUL 0x60
-#define TCORNUR 0x68
-#define TCORNBOL 0x6C
-#define TCORNBOR 0x6E
-
-#define TDOORUL 0x64
-#define TDOORUR 0x66
-
-#define TDOORDL 0x42
-#define TDOORDR 0x44
-
-#define TDOORRL 0x46
-#define TDOORRR 0x48
-
-#define TDOORLL 0xE0
-#define TDOORLR 0xE2
-
-#define TWALLU1 0x62
-#define TWALLR1 0x6A
-#define TWALLD1 0x4A
-#define TWALLL1 0x4C
-
-#define TEXIT1 0x4E
-
-
- ; maps:
- ; a map is a collection of room structs
- ; of n*m rooms. when a player leaves a room
- ; they will transition to the map to the north/south/east/west
- ; a map also contains a memory region for all the room's tables
- ; room:
- ; a room is a collection of tiles, falgs, exits and actor tables
-
- ; loads a map
- ; inputs:
- ; de: ptr to room struct
-room_load_from:
- ; copy de to current room struct
- ; and then load the room
- ld hl, curr_room_header
- ld bc, room_size
- call memcpy
-
- call room_draw
- call room_load_actors
- ret
-
- ; define positions that the player must have
- ; to be considered inside a tile
-#define EXPECTED_POS_NORTH_X 0
-#define EXPECTED_POS_NORTH_Y 0
-
- ; calls rom goto based on player position
- ; defaults to exit special if no position is found for
- ; a valid exit
- ; inputs:
- ; curr_room_exits: ptr to exits table
- ; player_x/y: player position
- ; flags:
- ; resets engine flag FLOAD_ROOM to 0
-room_goto_player_pos:
- ; who must not be player
- ; this ensures that the player
- ; turn has finished
- ; before we check
- ld a, [who]
- cp a, WHO_PLAYER
- ret z
-
- ; reset room load flag
- ld a, [engine_flags]
- xor a, EG_FLOAD_ROOM
- ld [engine_flags], a
- ld hl, player ; hl = player_y
-
- ld a, [hl+] ; hl = player_x
- ld d, a ; d = player y
- div16 d ; d = player y tile
-
- ld a, [hl]
- ld e, a ; d = player x
- div16 e ; d = player x tile
-
- dec hl ; hl = player_y
-
- ; compare to expected positions to decide what to do
-
- xor a, a ; a = 0
-
- ; player_y (d) == 0 (NORTH)
- cp a, d
- jr nz, @not_north REL
-
- ; set new player position
- ld a, 0x60
- ld [hl], a ; player_y = 0x60 after going NORTH
-
- ; load north as direction
- ld a, NORTH
- jp room_goto
-@not_north:
-
- ; player_x (e) == 0 (WEST)
- cp a, e
- jr nz, @not_west REL
-
- ld a, 0x80
- inc hl ; hl = player_x
- ld [hl], a ; player_x = 0x80 after going WEST
-
- ; load WEST as direction
- ld a, WEST
- jp room_goto
-@not_west:
-
- ld a, 9 ; tile 9 == EAST
- ; player_x (e) == 9 (EAST)
- cp a, e
- jr nz, @not_east REL
-
- ld a, 0x10
- inc hl ; hl = player_x
- ld [hl], a ; player_x = 0x10 after going EAST
-
- ; load EAST as direction
- ld a, EAST
- jp room_goto
-@not_east:
-
- ld a, 7 ; tile 7 == SOUTH
- ; player_y (d_ == 7 (SOUTH)
- cp a, d
- jr nz, @not_south REL
-
- ld a, 0x10
- ld [hl], a ; player_y = 0x10 after going SOUTH
-
- ; load SOUTH as direction
- ld a, SOUTH
- jp room_goto
-@not_south:
-
- ; default use special exit
- ld a, EXIT_SPECIAL
- ; no need to jmp in default case
- ret ; TODO: enable special exit?
-
- ; transitions to a new room
- ; that is part of the map:
- ; inputs:
- ; curr_room_exits: ptr to exits table
- ; a: direction EAST, WEST, NORTH, SOUTH, EXIT_SPECIAL
-room_goto:
- push af
-
- ; dst = original actor table
- ld hl, curr_room_actor_table
- ld a, [hl+]
- ld d, a
- ld a, [hl+]
- ld h, a
- ld l, d
-
- ; src = actor_table
- ld de, actor_table
- ld bc, ACTOR_TABLE_SIZE
- call memcpy
-
- pop af
-
- ; save a for later
- push af
- call disableinterrutpts
-
- ; disable objects
- ld a, LCDCF_ON | LCDCF_BGON | LCDF_OBJ_SIZE
- ld [RLCD], a
-
- ;call lcd_off
-
-
- ld hl, curr_room_exits ; ptr to exit table
- ld a, [hl+]
- ld c, a
- ld a, [hl]
- ld b, a ; bc = exit table
-
- pop af ; get back a
- ; a * 2
- add a, a
-
- ld h, 0
- ld l, a
- add hl, bc ; hl = exit table + exit direction
-
- ; load room ptr into de
- ld a, [hl+]
- ld e, a
- ld a, [hl]
- ld d, a
-
-#ifdef DEBUG
- ; check if de is NULL
- add a, e
- cp a, 0
- call z, panic
-#endif
-
- call room_load_from
-
- ; its player's turn again
- ld a, WHO_PLAYER
- ld [who], a
-
- ; restore palette
- ld a, BGP
- ld [RBGP], a
-
- ; clear soam
- call shadow_oam_clear
-
- call lcd_on
- call enableinterrupts
-
- ret
-
-
- ; loads actors from
- ; [curr_room_actor_table]
- ; into the active actor table
-room_load_actors:
- ; clear actor table
- ld d, 0
- ld bc, ACTORS_MAX * actor_size
- ld hl, actor_table
- call memset
-
- ; hl = ptr to initial actor table
- ld hl, curr_room_actor_table
- ld a, [hl+]
- ld e, a
- ld a, [hl]
- ld d, a
- ; de = source table
- ld bc, ACTOR_TABLE_SIZE
-
- ; hl = dst
- ld hl, actor_table
- call memcpy
-
- ret
-
- ; maps are collections of rooms
-
- ; rooms are made up of 2x2 meta tiles
- ; the bottom 2 tiles are reserved for the UI
- ; a rooms is exactly 1 screen
- ; there is no scrolling
- ; rooms may have 4 regular exits and 1 secret exit
-
-
- ; draws one row for a room
- ; inputs:
- ; de: room ptr
- ; hl: screen ptr
- ; modifies:
- ; de: next row
- ; hl: next screen address
-room_row_draw:
- ; wait for vlbank for every row if the screen is not off
- ld a, [RLCD]
- cp a, 0
- call nz, next_vblank_wait
-
- ld b, ROOM_W
-
- ; we'll need
- ; de for the second loop again
- push de
- ; darwa first set of tiles
-@loop_first:
- ; read tile from de
- ld a, [de]
- ; write to scrn
- ld [hl+], a
-
- ; move to next tile index
- add a, 1
- ; write it to scrn
- ld [hl+], a
-
- ; de++
- inc de
- ; loop counter --
- dec b
-
- ld a, b
- cp a, 0
- jp nz, @loop_first
-
- ; get the previous de value
- pop de
-
-
- ; move screen to next row
- ld bc, SCRN_W - VIEW_W
- add hl, bc
-
- ld b, ROOM_W
-
-
- ; wait for vlbank for every row if the screen is not off
- ld a, [RLCD]
- cp a, 0
- call nz, next_vblank_wait
-
- ; almost the same loop again
- ; for the second row
- ; of the meta tile
-@loop_second:
- ; read tile
- ld a, [de]
- ; move to next "row" of tiels
- add a, 16
- ; write to scrn
- ld [hl+], a
-
- ; move to next tile index
- add a, 1
- ; write it to scrn
- ld [hl+], a
-
- ; de++
- inc de
- ; b++
- dec b
-
- ld a, b
- cp a, 0
- jp nz, @loop_second
-
-
- ; do not draw outside of the room viewport
- ; -> advance scrn by 12 to move to next row
- ld bc, SCRN_W - VIEW_W
- add hl, bc
-
- ret
-
- ; draws the entire room to the tilemap
- ; disable rendering before drawing a room!
- ; inputs:
- ; curr_room: pointer to current room
-room_draw:
- ; load current room ptr
- ld a, [curr_room+1]
- ld d, a
- ld a, [curr_room]
- ld e, a
-
- ; hl is the screen address
- ld hl, SCRN0
-
- ld b, ROOM_H
-@loop:
- ; draw next tile
- push bc ; save bc for loop counter
- call room_row_draw
-
- ; we need bc to be the
- ; loop counter again
- pop bc
- dec b
-
- ld a, b
- cp a, 0
- jp nz, @loop
-
- ret
-
-room_tile_lut:
- .rep cti, ROOM_H, 1, .db cti * ROOM_W
-
- ; loads the flag pointer for a position into hl
- ; inputs:
- ; de: y/x
- ; returns:
- ; hl: pointer to flag at position y/x
- ; uses:
- ; de, hl, a
-room_get_flag_ptr:
- ; y pos / 16 -> tile pos
- div16 d
-
- ; x pos / 16 -> tile pos
- div16 e
- ld a, e ; a = x pos
-
- ld e, d
- ld d, 0 ; de = y position now
-
- ; -> now convert position to
- ; map flag index using a simple lut
- ; for y position + x
- ld hl, room_tile_lut
- add hl, de ; hl + y offset
- ; hl = row ptr
- ld e, a ; e = x pos
- ld a, [hl] ; a = map flags row offset
- add a, e ; row + x = position of tile in map
-
- push af
-
- ld hl, curr_room_flags ; hl = flags for currently loaded room
- ld a, [hl+] ; load curr room flags ptr
- ld e, a
- ld a, [hl]
- ld d, a ; de = flags pointer
-
- pop af
- ld h, 0
- ld l, a ; hl = tile offset
- add hl, de ; hl + de
- ret
-
- ; gets flags at a certain position
- ; applies a mask
- ; inputs:
- ; d : y pos
- ; e : x pos
- ; a: mask
- ; returns:
- ; a: masked flag
- ; z-flag is set
-room_get_flag_masked:
- ld b, a ; b = mask
- call room_get_flag_ptr
- ; hl = current tile flags
-
- ld a, [hl] ; load flags
- ld d, a
- ld a, b ; a= mask
- ; ld a, [ct_mask]
- and a, d
- ret
-
- ; generate a new map
- ; replaces the current map
- ; inputs:
- ; srand
- ; floor
- ; returns:
- ; a new map
- ; sets the current room
- ; sets player position
-map_generate:
- ; clear map0
- ld d, 0
- ld hl, map0
- ld bc, map0_end - map0
- call memset
-
- ; basic mapgen setup
- xor a, a
- ld [mapgen_depth], a
- ld [mapgen_total], a
-
- ld d, ROOMS_TOTAL ; d = loop counter
- ld hl, map0 ; hl = current room
- ld de, map0 ; de = previous room
-
- ; move to map_gen_next from here
-
- ; generate the next room
- ; inputs:
- ; hl: current room
- ; de: previous room
-map_gen_next:
- push de ; save previous room
- push hl ; save current room
-
- ; depth ++
- ld a, [mapgen_depth]
- inc a
- ld [mapgen_depth], a
-
- ld a, [mapgen_total]
- inc a
- ld [mapgen_total], a
-
- ; select a room
- ; and copy it to the current position
- ; linking back NULL on all exits initially
-
- ; load base room ptr
-
- ; select table based on level first
- ld hl, room_tables
- ld a, [floor]
- add a, a ; * 2 for offset in ptr table
- ld b, 0
- ld c, a
- add hl, bc ; hl = room table ptr based on floor
-
- ld a, [hl+]
- ld b, a
- ld a, [hl]
- ld h, a
- ld l, b ; hl = room table max length
- ld a, [hl+] ; hl = first room entry
- dec a ; -1 for mask
- ld b, a ; b = max length of room table
-
- ; c = previous room selection
- ld a, [mapgen_last_room]
- ld c, a
-
-@duplicate_room:
- ; select a room randomly from the table
- push hl
- call rand
- pop hl
- and a, b
- cp a, c
- jr z, @duplicate_room REL
-
- ; store for next iteration
- ld [mapgen_last_room], a
-
- add a, a ; a * 2 for ptr offset
- ld b, 0
- ld c, a
- add hl, bc ; base + random offset
-
- ld a, [hl+]
- ld e, a
- ld a, [hl]
- ld d, a
- pop hl ; hl = room dst
- push hl
-
- ; now we copy
- call map_gen_copy_base_room
- ; hl = next room l
-
- ; check if we're done generating
- ld a, [mapgen_total]
- cp a, ROOMS_TOTAL - 1
- jp z, @gen_done
-
- ; if not done link to next room
-
- pop de ; de = previous room ptr
-
- ; for now just pick a direction
- call map_gen_pick_direction
- push de ; save it again
- push hl
- call map_gen_link_rooms
-
- ; hl = current room
- pop hl
- pop de ; de = previous room
- push de ; push again for later
- call map_gen_next
-
- ; select a direction to walk into and call again
- ; and set up pointers
- ; if direction is already taken try again
- ; if direction is special return to previous room unless depth is 1
- ; if all directions are taken, return
- ; otherwise set up next ptr and move there
- ; update door tiles in picked direction
- ; push map ptr to stack before calling again
-
- ; depth --
- ld a, [mapgen_depth]
- dec a
- ld [mapgen_depth], a
-
- ; pop saved registers
- pop hl
- pop de
-
- ret
-@gen_done:
- ; clean up the stack
- pop hl
- pop hl
- pop hl
- pop hl
- pop hl
- ret
-
- ; picks a direction in mapgen
- ; inputs:
- ; hl: next room ptr
- ; de: previous room ptr
- ; returns:
- ; a: direction
- ; de/hl are preserved
- ; however de may be modified
- ; to point to a new 'previous' room
-map_gen_pick_direction:
- push hl
- push de
-
- ; TODO: add failure state if all 4 directions are taken
- ; returns special value to indicate failure
-@again:
- call rand
- and a, 3 ; discard remaining bits
-
- ; store result for now
- ld [tmp], a
- ld hl, map_gen_reverse_direction
- ld d, 0
- ld e, a
- add hl, de
- ld a, [hl] ; get reverse direction of the chosen one
-
- ; now check if direction is already used
- ; in previous room
- pop de
- push de ; push again
-
- ld hl, roomb_exits
- add hl, de ; hl = room exit struct
-
- ; de needs to be saved
- push de
-
- add a, a ; a * 2 = ptr offset
- ld d, 0
- ld e, a
- add hl, de ; hl = exit ptr
-
- ; add both bytes of ptr
- ; to check if its NULL
- ld a, [hl+]
- ld e, a
- ld a, [hl]
- add a, e ; this must be 0
- pop de ; get de back before jumping :^)
- cp a, 0
- jr z, @good_pick REL
-
- ; if it was not a good pick we
- ; move the room ptr from [hl] to de
- dec hl ; hl = exit ptr
- ld a, [hl+]
- ld e, a
- ld a, [hl]
- ld d, a
- ; fix value on the stack
- pop bc
- push de
-
- jr @again REL
-
-@good_pick:
- ; get original result
- ld a, [tmp]
-
- pop de
- pop hl
- ret
-
- ; lut for reverse direction
-map_gen_reverse_direction:
-.db SOUTH, WEST, NORTH, EAST, EXIT_SPECIAL
-
- ; link two rooms together
- ; by setting up the exit pointers
- ; for a given direction
- ; this assumes hl and de are romb structs
- ; inputs:
- ; a: direction
- ; hl: source roomb header
- ; de: target roomb header
-map_gen_link_rooms:
- ; call for intial direction
- push hl
- push de
- push af
- call map_gen_link_room_to
-
- ; now reserve
- pop af
- ld hl, map_gen_reverse_direction
- ld d, 0
- ld e, a
- add hl, de ; de = reverse direction ptr
- ld a, [hl] ; a = reverse direction
- ; swap original hl and de ptrs
- pop hl
- pop de
- ; call map_gen_link_room_to by simply falling through here
-
- ; links a single room to another
- ; inputs:
- ; a: direction
- ; hl: source roomb header
- ; de: target roomb header
-map_gen_link_room_to:
- call map_gen_fix_room_door
-
- ; skip hl and de to the exit table location
- ld bc, roomb_size - ROOM_EXIT_TABLE_SIZE
- add hl, bc ; hl = source exit table
-
- add a, a ; a = a * 2
- ; now add direction
- ld b, 0
- ld c, a
- add hl, bc ; hl = exit ptr
-
- ; store ptr in correct location
- ld a, e
- ld [hl+], a
- ld a, d
- ld [hl], a
-
- ret
-
- ; fixes a room's wall by placing a door in the desired position
- ; and flagging the wall as a door instead
- ; inputs:
- ; a: direction
- ; hl: source roomb header
- ; registers are preserved
-map_gen_fix_room_door:
- push hl
- push af
- push de
-
- ld bc, room_size
- add hl, bc ; hl = tile map
-
- ; need different logic based on direction
- cp a, NORTH
- jr nz, @not_north REL
-
- ld d, 0
- ld e, 0x04
- add hl, de ; go to door tile
-
- ld a, TEXIT1
- ld [hl+], a
- ld [hl], a
-
- dec hl ; hl is back to tile
- ; now set flags
-
- ld de, ROOM_TILES_SIZE
- add hl, de ; hl = flags area
-
- ld a, RF_DOOR
- ld [hl+], a
- ld [hl], a
-
- jp @done
-@not_north:
-
- cp a, SOUTH
- jr nz, @not_south REL
-
- ld de, ROOM_TILES_SIZE - 6
- add hl, de ; go to door tile
-
- ld a, TEXIT1
- ld [hl+], a
- ld [hl], a
-
- dec hl ; hl is back to tile
- ; now set flags
-
- ld de, ROOM_TILES_SIZE
- add hl, de ; hl = flags area
-
- ld a, RF_DOOR
- ld [hl+], a
- ld [hl], a
-
- jp @done
-@not_south:
-
- cp a, EAST
- jr nz, @not_east REL
-
- ld de, 39
- add hl, de ; go to door tile
-
- ld a, TEXIT1
- ld [hl], a
-
- push hl ; we need this again for flags
- ld de, 10
- add hl, de ; next row
- ld [hl], a
-
- pop hl
- ; now set flags
-
- ld de, ROOM_TILES_SIZE
- add hl, de ; hl = flags area
-
- ld a, RF_DOOR
- ld [hl], a
- ld de, 10
- add hl, de ; next row
- ld [hl], a
-
- jp @done
-@not_east:
-
- cp a, WEST
- jr nz, @not_west REL
-
- ld de, 30
- add hl, de ; go to door tile
-
- ld a, TEXIT1
- ld [hl], a
-
- push hl ; we need this again for flags
- ld de, 10
- add hl, de ; next row
- ld [hl], a
-
- pop hl
- ; now set flags
-
- ld de, ROOM_TILES_SIZE
- add hl, de ; hl = flags area
-
- ld a, RF_DOOR
- ld [hl], a
- ld de, 10
- add hl, de ; next row
- ld [hl], a
-
-
- ; no need to jp @done here
-@not_west:
-
-@done:
- pop de
- pop af
- pop hl
- ret
-
-
- ; copies a base room
- ; sets all exits to 0000 (null ptr)
- ; inputs:
- ; de: base room
- ; hl: target
-map_gen_copy_base_room:
- ; save original hl in tmp
- ; this can then be used as a ptr to the struct
- ld a, h
- ld [tmp], a ; tmp = h
- ld a, l
- ld [tmp+1], a ; tmp=1 = l
-
-@copy_header:
- ; this routine copies a base room
- ; and fixes the header accordingly
-
- ; copy header
- ld bc, room_size
- call memcpy
- ; save next target hl
- ; as returned by memcpy
- push hl
-
-@copy_tiles:
- ; copy tiles:
-
- ; read header into hl
- ld a, [tmp]
- ld h, a
- ld a, [tmp+1]
- ld l, a
-
- ; hl = new header = room tiles ptr
-
- ; read target room tiles ptr
- ; into hl
- ld a, [hl+]
- ld e, a
- ld a, [hl]
- ld d, a
-
- ; fix the tile pointer
- pop bc ; bc = tile ptr target
- push bc ; need to pop into hl in a bit :^)
-
- ; set tiles ptr
- dec hl ; hl = room header tile ptr
- ld a, c
- ld [hl+], a
- ld a, b
- ld [hl], a
-
- pop hl ; get target back
- ld bc, ROOM_TILES_SIZE
- call memcpyz
- push hl ; save hl again just like before
-
-@copy_flags:
-
- ; hl = header
- ld a, [tmp]
- ld h, a
- ld a, [tmp+1]
- ld l, a
-
- ld bc, room_flags
- add hl, bc ; hl = flags ptr
-
- ; read src flags into de
- ld a, [hl+]
- ld e, a
- ld a, [hl]
- ld d, a
-
- ; fix flags ptr
- pop bc ; bc = flags ptr target
- push bc ; push again to get the value into hl later
-
- ; set flags ptr
- dec hl ; hl = room flag ptr
- ld a, c
- ld [hl+], a
- ld a, b
- ld [hl], a
-
- pop hl ; get target back
-
- ; copy flags
- ld bc, ROOM_FLAGS_SIZE
- call memcpyz
- push hl ; save hl again
-
-@copy_actors:
- ; hl = header
- ld a, [tmp]
- ld h, a
- ld a, [tmp+1]
- ld l, a
-
- ld bc, room_actor_table
- add hl, bc ; hl = flags ptr
-
- ; read src actors into de
- ld a, [hl+]
- ld e, a
- ld a, [hl]
- ld d, a
-
- ; fix flags ptr
- pop bc ; bc = actors ptr target
- push bc ; push again to get the value into hl later
-
- ; set actor ptr
- dec hl ; hl = room actor ptr
- ld a, c
- ld [hl+], a
- ld a, b
- ld [hl], a
-
- pop hl ; get target back
-
- ; copy actors
- ld bc, ACTOR_TABLE_SIZE
- call memcpy
- push hl ; save again for later
-
-@setup_exits:
- ; fix exit table
-
- ; hl = header
- ld a, [tmp]
- ld h, a
- ld a, [tmp+1]
- ld l, a
-
- ld bc, room_exit_table
- add hl, bc ; hl = flags ptr
-
- pop bc ; bc = exit table location
- push bc ; push again we need value back in hl soon :^)
-
- ; set exit table ptr
- ld a, c
- ld [hl+], a
- ld a, b
- ld [hl], a
-
- pop hl ; hl = exit table location
- ; skip exit bytes to get hl in position for next operation
- ; all values should be 0 at this point because
- ; we memset the entire map
- xor a, a
-.rep ci, 2 * ROOM_EXITS_MAX, 1, inc hl
-
- ret
-
- ; base room
- ; this can be copied and modified
- ; by the map gen
#include "base_room.s"
-#include "base_room2.s"
-#include "base_room3.s"
-#include "base_room4.s"
-
- ; count of all pointers in base room table
-#define F1_ROOM_TABLE_LEN ((f1_room_table_end - f1_room_table_start) / 2)
-
- ; the first byte of the table is the length of the table
- ; a table of all base room ptrs
- ; length must be divisible by 2
-f1_room_table:
- .db F1_ROOM_TABLE_LEN
-f1_room_table_start:
- dw base_room_header
- dw base_room2_header
- dw base_room3_header
- dw base_room4_header
-f1_room_table_end:
-
- ; a table of all room tables
- ; to allow for room sets per level
-room_tables:
- dw f1_room_table
-
- ; exit table for empty exits
-room_empty_exits:
-dw base_room2_header
-dw base_room_header
-dw base_room2_header
-dw base_room_header
-dw base_room_header
+++ /dev/null
-#define MAPRAM 0xD000
-
- ; this RAM bank stores the current map
-.org MAPRAM
-
- ; first map
-map0: .adv roomb_size * ROOMS_TOTAL
-map0_end:
-
ld a, GM_GAME
ld [game_mode], a
- ; player starts the turn
- ld a, WHO_PLAYER
- ld [who], a
-
call mbc1_init
ret
.def int CURSOR_TILE = 0x04
-.def int PLAYER_TILE_IDLE1 = 0x00
-.def int PLAYER_TILE_IDLE2 = 0x12
-
-.def int PLAYER_TILE_MOVE_FRAME1_1 = 0x02
-.def int PLAYER_TILE_MOVE_FRAME2_1 = 0x10
-
-player_anim_table1:
-.rep c, 2, 1, .db PLAYER_TILE_IDLE1
-.rep c, 7, 1, .db PLAYER_TILE_MOVE_FRAME1_1
-.rep c, 7, 1, .db PLAYER_TILE_MOVE_FRAME2_1
-
-#define PLAYER_IFRAME_TIMER 64
-#define DAMAGE_ANIM_LEN 20
; init the player
- ; inputs:
- ; hl: pointer to player memory
player_init:
- ld a, 64
- ; y
- ld [hl+], a
- ; x
- ld [hl+], a
-
- xor a, a
- ; flags
- ld [hl+], a
-
- ; default hp max
- ld a, PLAYER_DEFAULT_HP
- ld [hl+], a ; hp
- ld [hl+], a ; hp max
- ; default mp max
- ld a, PLAYER_DEFAULT_MP
- ld [hl+], a ; mp
- ld [hl+], a ; mp max
-
- ; default def
- ld a, PLAYER_DEFAULT_DEF
- ld [hl+], a ; def
- ld [hl+], a ; def max
-
- ; default atk
- ld a, PLAYER_DEFAULT_ATK
- ld [hl+], a ; atk
- ld [hl+], a ; atk max
-
- ret
-
-player_draw_cursor:
- push hl
- push hl
- pop bc
- dec bc ; bc = fake player actor
- call draw_cursor
- pop hl
ret
; update the player
; inputs:
; hl: pointer to player memory
player_update:
- ; update
- ld a, [who]
- cp a, WHO_PLAYER
- call z, player_draw_cursor
- jp nz, @skip_input
-
- ; call state update
- ld a, smt_player_poll_inputs
- ; load initial state if required
- call sm_load_initial_state
-
- push hl
- push hl
- pop bc
- dec bc ; bc = actor_ptr for player
-
- call sm_call_state
-
- ; restore hl
- pop hl
-
-@update_end:
-@skip_input:
- ; hl should be player_y here
-
- ; d: player_y
- ; e: player_x
- ld a, [hl+] ; hl = player_x
- ld d, a ; d = player_y
- ld a, [hl]
- ld e, a ; e = player_x
- dec hl ; hl = player_y
-
- ; check if i-frame
- ; if iframe is divisible by 2
- ; flash all sprites off
- ; otherwise continue with regular code
- ; hl = player_x
- ld bc, player_timer_i
- add hl, bc ; hl = timer now
- ld a, [hl]
- cp a, 0
- jr z, @draw_visible REL
-
- dec a
- ld [hl], a ; timer--
- inc a
- and a, 4 ; blink every 4 frames
- jr z, @draw_visible REL
+@draw_cursor:
+ ; draw cursor
-@hide_player:
-
- ; hide 3 player sprites
- ld a, 0
+ ; 8x8 small cursor
ld hl, PLAYER_SPRITE1
- ld [hl+], a
- ld [hl+], a
- ld hl, PLAYER_SPRITE1+4
- ld [hl+], a
- ld [hl+], a
- ld hl, PLAYER_SPRITE1+8
- ld [hl+], a
- ld [hl+], a
-
- ret
-@draw_visible:
- ; load left tile into tmp
- push de
- load_anim_frame player_anim_table1, 0b1111
- ld [tmp], a
- pop de
-
- ; drawing
- ; set up obj flag mask based on frame counter
- ; b is now not free anymore!
- ld a, [frame_count]
- and a, 4
- ld b, 0
-
- ; obj 1
- ld hl, PLAYER_SPRITE1
-
- ; set player position
- ld a, d ; y
+ ld a, [cursor_y]
add a, OBJ_OFF_Y
-
- ld [hl+], a
- ld a, e ; x
- add a, OBJ_OFF_X
ld [hl+], a
- ; idel tile 1
- ld a, [tmp]
+ ld a, [cursor_x]
+ add a, OBJ_OFF_X
ld [hl+], a
- ; flags
- ld a, b
+ ld a, CURSOR_TILE
ld [hl+], a
- ; obj 2
- ld a, d ; y
- add a, OBJ_OFF_Y
- ld [hl+], a
- ld a, e ; x
- add a, 8 + OBJ_OFF_X
- ld [hl+], a
-
- ; idle tile 2
- ld a, PLAYER_TILE_IDLE2
- ld [hl+], a
-
- ; flags
- ld a, b
- ld [hl+], a
-
- ret
-
- ; performs player collision checks
- ; inputs:
- ; bc: actor ptr
- ; de: y/x position offset
-player_collision_check:
- ; set collision mask
- ld a, RF_WALL | RF_DOOR | RF_ACTOR
- ld [ct_mask], a
-
- call generic_collision_check
-
- and a, RF_DOOR
- jr z, @no_door_hit REL
-
- ; set room load flag is door was hit
- ld a, [engine_flags]
- or a, EG_FLOAD_ROOM
- ld [engine_flags], a
-
-@no_door_hit:
-
- ld a, h ; restore original a for next check
- and a, RF_ACTOR
- jr z, @no_enemy_hit REL
-
- ; TODO add enemy hit logic
-
-@no_enemy_hit:
-
- ld a, h ; restore original a for next check
- and a, RF_WALL | RF_ACTOR
-
- jr z, @no_collision REL
- ; abort walk state
- call anim_abort_walk
- jr @skip REL
-@no_collision:
-@skip:
- ret
-
- ; uses a resource such as
- ; hp, mp, atk or def down to 0
- ; inputs:
- ; [hl]: pointer to selected resource
- ; a : the amount to subtract
-player_use_resource:
- ld b, a ; b = to sub
- ld a, [hl] ; a = current resource
- cp a, 0
- ; skip if already at 0!
- jr z, @skip REL
-
- sub a, b
- ; if not < 0
- ; do not clear a
- jr nc, @no_underflow REL
-
- ; a = 0
xor a, a
+ ld [hl+], a
-@no_underflow:
- ; store result
- ld [hl], a
-@skip:
- ret
-
- ; same as use_resource but specifically
- ; also starts a damage animation
- ; and iframes
- ; inputs:
- ; [hl]: pointer to player
- ; a : the amount to subtract
-player_take_damage:
- ld [tmp], a ; tmp store a
-
- ; if iframes are on, do nothing
- push hl
- ld de, player_timer_i ; go to timer
- add hl, de
- ld a, [hl] ; load timer into a
- pop hl ; back to base
- cp a, 0
- ret nz
-
-
- ; set damage anim timer
- ld a, DAMAGE_ANIM_LEN
- ld [damage_anim], a
-
- ; set iframe timer
- ld a, PLAYER_IFRAME_TIMER
- push hl
- ld e, player_timer_i
- ld d, 0
- add hl, de ; hl = timer_ia
- ld [hl], a
- pop hl
-
- ld e, player_hp
- ld d, 0
- add hl, de
- ld a, [tmp] ; a = tmp
- jp player_use_resource
-
- ; gains a resource such as
- ; hp, mp, atk, or def up to max
- ; inputs:
- ; [hl]: pointer to selected resource
- ; a : the amount to add
-player_gain_resource:
- ld b, a ; b = to add
- ld a, [hl+] ; a = current resource. hl = max
- cp a, [hl] ; a = max resource
- ; skip if already at max
- jp z, @skip
-
- ; add new value
- add a, b
- cp a, [hl]
- jp c, @no_overflow
-
- ld a, [hl] ; a = amx
-@no_overflow:
- ; store value
- dec hl ; hl = current resource
- ld [hl], a
-@skip:
ret
- ; sub routine for game over
- ; never call outside of blank!
-player_game_over:
- ; if timer is not set
- ; set up game over now
- ld a, [game_over_timer]
- cp a, 0
- jr nz, @game_over_timer REL
- ld hl, STR_GAME_OVER
- ld de, SCRN0
- call puts
-
- ; set game over timer
- ld a, 60
- ld [game_over_timer], a
-
- ret
-@game_over_timer:
- ; otherwise timer--
- ; and wait
- dec a
- ld [game_over_timer], a
- ; if timer has reached 1 restart game
- cp a, 0
- jr z, @restart REL
-
- ret
-@restart:
- ; restart game
- ; TODO: maybe just go to title?
- jp entry
--- /dev/null
+sim_update:
+ ret
; flag for init of sram
sram_magic: .adv 1
sram_srand: .adv 2
-save_game1: .adv save_game_size
+++ /dev/null
-; the state machine can be used by the current actor (who)
-; to store their current state and call small re-usable routines
-; at the end of a chain the state should always be 0
-
-
- ; table of all states
- ; expected inputs:
- ; bc: actor_ptr
-state_table:
- dw sm_nop
- dw sm_end_turn
- dw sm_player_poll_inputs
- dw anim_walk_north
- dw anim_walk_south
- dw anim_walk_east
- dw anim_walk_west
- dw sm_bat_pick_direction
-
-sm_nop:
- ret
-
- ; advances state machine to
- ; next offset
- ; resets if who is 0
- ; preserves: all registers
-sm_advance:
- push_all
- ld a, [who]
- cp a, 0
- jr nz, @not_reset REL
- ; offset = 0
- ld [state_machine_offset], a
- pop_all
- ret
-@not_reset:
- ; offset + sm_size
- ld a, [state_machine_offset]
- ld b, sm_size
- add a, b
- ld [state_machine_offset], a
- pop_all
- ret
-
- ; end turn state
-sm_end_turn:
- call sm_clear
- turn_finish
- call who_next
- ret
-
- ; clears the state machine
-sm_clear:
- sm_load_ptr hl
- xor a, a
- ld [hl+], a
- ld [hl+], a
- ld [hl], a
- ret
-
-sm_player_poll_inputs:
- ; bc = actor type
-
- sm_load_ptr hl
-
- ; input handling
- input_held BTNDOWN
- jr z, @notdown REL
-
- ; set animation params
- ld a, smt_actor_go_south
- ld [hl+], a ; set next state
- ld a, ANIM_PLAYER_WALK_FRAMES
- ld [hl], a ; set param[0]
-
- ; perform collision check
- ld d, ANIM_TILE_SIZE
- ld e, 0
- call player_collision_check
-
- ret
-@notdown:
-
- input_held BTNUP
- jr z, @notup REL
-
- ; set animation params
- ld a, smt_actor_go_north
- ld [hl+], a ; set next state
- ld a, ANIM_PLAYER_WALK_FRAMES
- ld [hl], a ; set param[0]
-
-
- ; perform collision check
- ld d, 0xFF & 0 - ANIM_TILE_SIZE
- ld e, 0
- call player_collision_check
-
- ret
-@notup:
-
- input_held BTNLEFT
- jr z, @notleft REL
-
- ; set animation params
- ld a, smt_actor_go_west
- ld [hl+], a ; set next state
- ld a, ANIM_PLAYER_WALK_FRAMES
- ld [hl], a ; set param[0]
-
- ; perform collision check
- ld d, 0
- ld e, 0xFF & 0 - ANIM_TILE_SIZE
- call player_collision_check
-
- ret
-@notleft:
-
- input_held BTNRIGHT
- jr z, @notright REL
-
- ; set animation params
- ld a, smt_actor_go_east
- ld [hl+], a ; set next state
- ld a, ANIM_PLAYER_WALK_FRAMES
- ld [hl], a ; set param[0]
-
- ; perform collision check
- ld d, 0
- ld e, ANIM_TILE_SIZE
- call player_collision_check
-
- ret
-@notright:
-
- ret
-
- ; picks a direction for
- ; a bat to move in
- ; then transitions to move state
- ; after verifying collision
- ; otherwise -> end turn
-sm_bat_pick_direction:
- push bc
- ; move bat in random direction
- call rand
- and a, 0b11 ; rnadom direction 0-3
-
- push af
- ; hl = sm ptr
- sm_load_ptr hl
- pop af
-
- ; call correct movement setup
- cp a, NORTH
- jr nz, @not_north REL
-
- ; set animation params
- ld a, smt_actor_go_north
- ld [hl+], a ; set next state
- ld a, ANIM_PLAYER_WALK_FRAMES
- ld [hl], a ; set param[0]
-
- ; perform collision check
- ld d, 0xFF & 0 - ANIM_TILE_SIZE
- ld e, 0
- call act_collision_check
-@not_north:
-
- cp a, SOUTH
- jr nz, @not_south REL
-
- ; set animation params
- ld a, smt_actor_go_south
- ld [hl+], a ; set next state
- ld a, ANIM_PLAYER_WALK_FRAMES
- ld [hl], a ; set param[0]
-
- ; perform collision check
- ld d, ANIM_TILE_SIZE
- ld e, 0
- call act_collision_check
-@not_south:
-
- cp a, WEST
- jr nz, @not_west REL
-
- ; set animation params
- ld a, smt_actor_go_west
- ld [hl+], a ; set next state
- ld a, ANIM_PLAYER_WALK_FRAMES
- ld [hl], a ; set param[0]
-
- ; perform collision check
- ld d, 0
- ld e, 0xFF & 0 - ANIM_TILE_SIZE
- call act_collision_check
-@not_west:
-
- cp a, EAST
- jr nz, @not_east REL
-
- ; set animation params
- ld a, smt_actor_go_east
- ld [hl+], a ; set next state
- ld a, ANIM_PLAYER_WALK_FRAMES
- ld [hl], a ; set param[0]
-
- ; perform collision check
- ld d, 0
- ld e, ANIM_TILE_SIZE
- call act_collision_check
-@not_east:
-
- ; verify collision
-
- ; transition
-
- pop bc
-
- ret
-
- ; loads initial state if
- ; state is 0
- ; inputs:
- ; a: initial state
- ; uses:
- ; tmp
-sm_load_initial_state:
- push hl
-
- ld [tmp], a
- sm_load_ptr hl
- ld a, [hl]
- cp a, 0 ; if state is not 0 ret
- jr nz, @done REL
-
- ; set initial state
- ld a, [tmp]
- ld [hl], a
-
-@done:
- pop hl
- ret
-
- ; calls the current state machine state
- ; depends on sm_load_ptr
-sm_call_state:
- sm_load_ptr hl
- ld a, [hl]
- ld hl, state_table
- jp call_tbl
-#define THP_ICON 0x33
-#define TMP_ICON 0x37
-#define TATK_ICON 0x3D
-#define TDEF_ICON 0x3C
-#define THP_BAR_START 0x34
-#define THP_BAR_SINGLE_EMPTY 0x3F
-#define THP_BAR_SINGLE_FULL 0x3B
-
- ; difference between start and empty bar
-#define THP_BAR_EMPTY_DIFF 4
-
- ; sets up static parts of the UI
- ; all other parts are drawin by ui_draw
- ; only call during blanking
+ ; inits UI
ui_init:
- ; darw mp and hp on first frame
- ld a, UI_REDRAW_HP | UI_REDRAW_MP | UI_REDRAW_ATK | UI_REDRAW_DEF
- ld [ui_flags], a
-
- ; hp icon
- ld hl, SCRN0_UI
- ld a, THP_ICON
- ld [hl], a
-
- ; mp icon
- ld a, TMP_ICON
- ld hl, SCRN0_UI+10
- ld [hl], a
-
- ; atk icon
- ld hl, SCRN0_UI+SCRN_W
- ld a, TATK_ICON
- ld [hl], a
-
- ; def icon
- ld a, TDEF_ICON
- ld hl, SCRN0_UI+SCRN_W+10
- ld [hl], a
-
- ret
-
- ; decides if a bar should be empty or filled
- ; inputs:
- ; b: current
- ; c: max
- ; a: filled tile
- ; e: total drawn
- ; hl: destination ptr
- ; returns: hl + 1; e++
-ui_draw_bar_empty_or_filled:
- ld [itmp], a
- ld a, b ; a = current
- cp a, e
- ld a, [itmp] ; a = tile
- ; if total drwan > a
- ; switch to empty tile
- jp z, @equal
- jp nc, @not_empty
-@equal:
- add a, THP_BAR_EMPTY_DIFF ; move to empty
-@not_empty:
- ld [hl+], a
- inc e
ret
- ; draws a UI bar
- ; the bar will be filled up to hp/mp
- ; al others will be empty
- ; inputs:
- ; hl: screen location
- ; [de]: ptr to hp/mp where hp/mp max is [de+1]
-ui_draw_bar:
- ld a, [de] ; load non-max value
- inc de ; move to max value
- ld b, a ; b = current value
-
- ; check if we only need a single obj
- ld a, [de] ; a = max value
- ; now c = max
- ; and b = current
- ld c, a
- ld e, 0 ; e = total drawn
-
- ; <= 1 -> jp to special case code
- cp a, 1 ; a = max
- ; load single tile for the possible jumps
- ld a, THP_BAR_SINGLE_FULL
- jr c, ui_draw_bar_empty_or_filled REL
- jr z, ui_draw_bar_empty_or_filled REL
-
-
- ; draw left most bar tile
- ld a, THP_BAR_START
- call ui_draw_bar_empty_or_filled
-
- ld a, c ; a = max. guaranteed not 0 or 1 here!
- sub a, 2 ; max - 2 (left and righr-most tile)
- ld d, a ; d = loop counter
- cp a, 0 ; if loop count is 0 skip
- jr z, @skip REL
-
-@loop:
- ld a, THP_BAR_START+1
- call ui_draw_bar_empty_or_filled
-
- ; d--
- dec d
- ld a, d
- cp a, 0
- ; while not 0
- jp nz, @loop
-@skip:
-
- ; left-most tile
- ld a, THP_BAR_START+2
- call ui_draw_bar_empty_or_filled
- ret
-
- ; sets up for drawing hp bar
-ui_draw_hp_bar:
- ; set up ptrs
- ; draw hp UI
- ld hl, SCRN0_UI+1
- ; player hp ptr
- ld de, player + player_hp
- ; directly jump without a return
- jp ui_draw_bar
-
- ; sets up for darwing mp bar
-ui_draw_mp_bar:
- ld hl, SCRN0_UI+11
- ld de, player + player_mp
-
- ; directly jump without a return
- jp ui_draw_bar
-
-ui_draw_atk_bar:
- ld hl, SCRN0_UI+SCRN_W+1
- ld de, player + player_atk
- jp ui_draw_bar
-
-ui_draw_def_bar:
- ld hl, SCRN0_UI+SCRN_W+11
- ld de, player + player_def
- jp ui_draw_bar
-
; update the UI
; this should only be called
; during blanking
ui_draw:
- ; check if we should darw hp bar
- ld a, [ui_flags]
- cp a, 0
- jr z, @skip REL
-
- ; check redraw hp flag
- and a, UI_REDRAW_HP
- call nz, ui_draw_hp_bar
-
- ; check if we should draw mp bar
- ld a, [ui_flags]
- and a, UI_REDRAW_HP
- call nz, ui_draw_mp_bar
-
- ; check if we should draw atk bar
- ld a, [ui_flags]
- and a, UI_REDRAW_ATK
- call nz, ui_draw_atk_bar
-
- ; check if we should draw def bar
- ld a, [ui_flags]
- and a, UI_REDRAW_DEF
- call nz, ui_draw_def_bar
+ ; test draw to see tiles
+ ld a, 24
+ ld hl, SCRN0
+ ld [hl], a
- ; set flags to 0
- xor a, a
- ld [ui_flags], a
-@skip:
ret
update_table:
dw update_game
dw update_pause
-dw update_game_over
update_game_over:
ret
call rand
call rand_save_srand
- ; update player
- ld hl, player
call player_update
-
- call actors_update
+ call sim_update
ret
update_pause:
+ call player_update
ret
; called after vblank
; get inputs
call poll_inputs
-
- ; check if damage animation is active
- ld a, [damage_anim]
- cp a, 0
- jr z, @no_damage_taken REL
-
- ; damage was taken
- ; damage_anim--
- dec a
- ld [damage_anim], a
- cp a, 0
- jr z, @restore_bgp REL
-
- ; play animation by scrambling palette
- ld a, BGP
- rlc a
- ld [RBGP], a
- ret ; do not update rest
-@restore_bgp:
- ; restore original bgp
- ld a, BGP
- ld [RBGP], a
- ret ; return for one more frame
-@no_damage_taken:
-
call ui_draw
-
- ; check for game over animation
- ld a, [player+player_hp]
- cp a, 0
- jr nz, @not_game_over REL
- call player_game_over
- ret ; never set frame to be ready during game-over
-@not_game_over:
-
- ; check for room transition
- ld a, [engine_flags]
- and a, EG_FLOAD_ROOM
- call nz, room_goto_player_pos
-
ld a, 1
ld [frame_ready], a
ret
; turns on the lcd
lcd_on:
- ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON | LCDF_OBJ_SIZE
+ ld a, LCDCF_ON | LCDCF_BGON | LCDCF_OBJON
ld [RLCD], a
ret
ld bc, 1024
ld d, EMPTY_TILE
call memset
-
- ; generate test map
- call map_generate
-
- ; initial test map
- ld de, map0
- call room_load_from
; set up bgp
ld a, BGP
prev_inputs: .adv 1
- ; static actor table space
-actor_table: .adv ACTOR_TABLE_SIZE
-
-actor_soam_ptr: .adv 2
-
- ; this single byte
- ; makes the player compatible with
- ; an actor pointer
- ; pass player_type to a function
- ; expecting an actor and it will work
-player_type: .adv 1
-player: .adv player_size
-
- ; play a damage animation
- ; until this value is 0
- ; pause all other update execution until then
-damage_anim: .adv 1
-
-; map region
-
-
- ; current room struct
- ; same layout as room struct itself
- ; always should point at the current map's memory region
-curr_room_header:
- ; pointer to current room struct
-curr_room: .adv 2
- ; flags for current tiles
-curr_room_flags: .adv 2
-
- ; ptr to actor table of size actors_max/2
- ; populate before loading a map
- ; layout:
- ; byte 0: length of actor table
- ; bytes 1-n: n bytes of actor data to be copied to actor table
-curr_room_actor_table: .adv 2
-
- ; ptr to exits
-curr_room_exits: .adv 2
-
- ; the floors (levels) the player has beaten already
-floor: .adv 1
-
-
ui_flags: .adv 1
draw_flags: .adv 1
+cursor_x: .adv 1
+cursor_y: .adv 1
engine_flags: .adv 1
; seed must never be 0
srand: .adv 2
- ; who is currently in control of the game
- ; if set to FF
- ; the player is active
- ; otherwise it is the actor index
- ; actors may still run update code like animations
- ; but may *never* act when they are not currently enabled
-who: .adv 1
- ; if end turn is set who_next will
- ; give control to the next actor
-end_turn: .adv 1
-
- ; current actor that is being updated
-act: .adv 1
-
-
-; animation params storage
-anim_move_y: .adv 1
-anim_move_x: .adv 1
-
-anim_step_y: .adv 1
-anim_step_x: .adv 1
-
-; tmp storage for new animation position
-anim_target_y: .adv 1
-anim_target_x: .adv 1
-
- ; ptr offset for state machine
-state_machine_offset: .adv 1
-state_machine: .adv sm_size * (ACTOR_TABLE_SIZE + 1)
-
- ; collision tile tmp values
-ct_poy: .adv 1
-ct_pox: .adv 1
-ct_mask: .adv 1
- ; mapgen tmp values
-
- ; current depth
- ; used for recursion in mapgen
-mapgen_depth: .adv 1
- ; counts how many rooms we have generated already
-mapgen_total: .adv 1
- ; store the previous room
- ; to avoid multiple same room types in a row
-mapgen_last_room: .adv 1
.chr 00003333
.chr 00000000
; tile 4
-.chr 11111100
-.chr 13333300
-.chr 13333300
-.chr 13300000
-.chr 13300000
-.chr 13300000
+.chr 11100111
+.chr 13300331
+.chr 13000031
.chr 00000000
.chr 00000000
+.chr 13000031
+.chr 13300331
+.chr 11100111
; tile 5
.chr 00000000
.chr 00000000
.chr 22221303
.chr 22221303
; tile 106
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
+.chr 22222222
+.chr 22222222
+.chr 22212222
+.chr 22212212
+.chr 22122122
+.chr 22222122
+.chr 22222222
+.chr 22212222
; tile 107
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
; tile 108
.chr 00000000
.chr 00000000
.chr 00000133
.chr 33333333
; tile 122
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
+.chr 22122222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
; tile 123
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
+.chr 22222222
; tile 124
.chr 00000000
.chr 00000000
.chr 00000000
.chr 00000000
; tile 172
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
-.chr 00000000
+.chr 32232223
+.chr 32232223
+.chr 32222223
+.chr 32232223
+.chr 32232223
+.chr 32222223
+.chr 32232223
+.chr 32232223
; tile 173
.chr 00000000
.chr 00000000
def print_data(data, name, layer):
print(name + "_" + layer + ":")
- print(".db ", end = '');
split = data.split(",")
for i, byte in enumerate(split):
+ end = ', '
+
+ if i % 8 == 0:
+ print("\n.db ", end = '');
+
val = int(byte)
if val > 0:
val -= 1
val = (val & 0x0FF0) >> 4
val -= int(2 * og % 16)
- end = ', '
+ if (i+1) % 8 == 0:
+ end = ''
if i == len(split) - 1:
end = '\n'
print(hex(val), end=end)
-def actor_round(n, base=TILE_SIZE):
- return (round(n)) & 0xF0
-
-def print_actor(atype, y, x, flags):
- print(".db ", int(atype), ",", hex(int(actor_round(float(y))) + ACTOR_OFFSET_Y), ",", hex(int(actor_round(float(x))) + ACTOR_OFFSET_X), ",", int(flags))
-
-def print_struct(name):
- print(" ; struct for ", name)
- print(name + "_header:")
- print("dw " + name + '_bg')
- print("dw " + name + '_flags')
- print("dw " + name + '_actors')
- print("dw room_empty_exits")
def convert(src, name):
tree = ET.parse(src)
root = tree.getroot()
- print_struct(name)
-
for child in root:
if child.tag == "layer":
for data in child:
print_data(data.text, name, child.attrib['name'])
- elif child.tag == "objectgroup":
- print(name + '_actors:')
- actors_printed = 0
- for data in child:
- flags = 0
- atype = 0
- for props in data:
- for prop in props:
- if prop.attrib['name'] == 'type':
- atype = prop.attrib['value']
- elif prop.attrib['name'] == 'flags':
- flags = prop.attrib['value']
- print_actor(atype, data.attrib['y'], data.attrib['x'], flags)
- actors_printed += 1
- for not_filled in range(actors_printed, 8, 1):
- print_actor(0, 0, 0, 0)