diff --git a/inc/conf.h b/inc/conf.h index 895e0aa..e51ea40 100644 --- a/inc/conf.h +++ b/inc/conf.h @@ -27,3 +27,6 @@ #define MISSILE_FRICTION (MISSILE_ACCEL / MISSILE_MAX_SPEED) #define MISSILE_COOLDOWN (TARGET_FPS / 2) #define REPLAY_SIZE 18000 /* 5 minutes */ +#define LEVEL_WIDTH 25 +#define LEVEL_HEIGHT 14 +#define LEVELBIN_SIZE (6 + LEVEL_WIDTH * LEVEL_HEIGHT) diff --git a/inc/level.h b/inc/level.h index a80be78..9bd0649 100644 --- a/inc/level.h +++ b/inc/level.h @@ -28,6 +28,8 @@ void level_deinit(void); void level_load(int id); void level_save_kble(const char *path); +void level_load_kble(const char *path); +void level_load_kble_followup(void); void level_reload(void); void level_regen_visual_data(int editing); void level_next(void); diff --git a/src/editor.c b/src/editor.c index c118e62..3676c43 100644 --- a/src/editor.c +++ b/src/editor.c @@ -6,6 +6,8 @@ #include "tile.h" #include "vec.h" #include +#include + static int cx, cy; static int ctile = 1; @@ -14,6 +16,7 @@ static void editor_draw(void); static void draw_grid(void); static void draw_cursor(void); static void editor_save(void); +static void editor_load(void); void editor(void) @@ -59,6 +62,11 @@ editor_update(void) level_set(cx, cy, 0); level_regen_visual_data(1); } + + /* load level */ + if (input_down(K_PLAYBACK)) editor_load(); + /* save level */ + if (input_down(K_SAVE_REPLAY)) editor_save(); } static void @@ -106,5 +114,14 @@ editor_save(void) { char path[256]; if (filedialog_save(path, sizeof(path))) return; - level_save_kble(path); + gint_world_switch(GINT_CALL(level_save_kble, path)); +} + +static void +editor_load(void) +{ + char path[256]; + if (filedialog_open(path, sizeof(path))) return; + gint_world_switch(GINT_CALL(level_load_kble, path)); + level_load_kble_followup(); } diff --git a/src/input.c b/src/input.c index 215a30c..915aea9 100644 --- a/src/input.c +++ b/src/input.c @@ -58,7 +58,7 @@ input_update(void) void input_dump_replay(void) { - const int fd = open(replay_path, O_WRONLY | O_CREAT | O_TRUNC); + const int fd = open(replay_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd != -1) { write(fd, input.replay, input.replay_cursor * sizeof(PackedFrame)); diff --git a/src/level.c b/src/level.c index 0b238f4..0c02b15 100644 --- a/src/level.c +++ b/src/level.c @@ -14,6 +14,7 @@ #include static struct Level level; +struct LevelBin *user_level = NULL; extern bopti_image_t bimg_tileset; extern struct LevelBin kble_test, kble_burn, kble_bounce, kble_worm, kble_shake, @@ -50,6 +51,10 @@ void level_deinit(void) { level_free(); + if (user_level != NULL) { + free(user_level); + user_level = NULL; + } } void @@ -63,8 +68,8 @@ level_load(int id) void level_save_kble(const char *path) { - const int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC); - unsigned char data[356] = {0}; + const ssize_t fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + unsigned char data[LEVELBIN_SIZE] = {0}; int i; data[0] = 0; @@ -76,12 +81,45 @@ level_save_kble(const char *path) while (i-- > 0) data[i + 6] = level.data[i]; - if (fd != -1) { + if (fd >= 0) { write(fd, data, sizeof(data)); close(fd); } } +void +level_load_kble(const char *path) +{ + const ssize_t fd = open(path, O_RDONLY); + + if (user_level == NULL) { + user_level = malloc(LEVELBIN_SIZE); + if (user_level == NULL) return; + } + + if (fd >= 0) { + size_t bytes; + + bytes = read(fd, user_level, LEVELBIN_SIZE); + close(fd); + + if (bytes != LEVELBIN_SIZE) return; + if (user_level->format != 0) return; + if (user_level->chunk_size != 1) return; + if (user_level->width != LEVEL_WIDTH) return; + if (user_level->height != LEVEL_HEIGHT) return; + } +} + +void +level_load_kble_followup(void) +{ + if (user_level != NULL) { + load(user_level); + level_regen_visual_data(1); + } +} + void level_reload(void) {