From 8a4559d4f9c4d0db0f7d2bf4f6310fc5bbde1c6a Mon Sep 17 00:00:00 2001 From: hkz Date: Sat, 6 Sep 2025 09:58:24 +0200 Subject: [PATCH] implement a demo mode --- Makefile | 2 +- src/demo_main.c | 102 ++++++++++++++++++--------------------- src/dlog_main.c | 11 ++++- src/game_graphics.c | 37 +++++++++++++- src/game_graphics_demo.c | 3 ++ 5 files changed, 95 insertions(+), 60 deletions(-) create mode 100644 src/game_graphics_demo.c diff --git a/Makefile b/Makefile index 9c9a0d3..53d346b 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ GAME_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s input_asm.s sound.s GAME_C_SRCS = game_main.c input.c utility.c game_graphics.c line_data.c game_logic.c arrows_pic.c tiles.c graph_misc_data.c DEMO_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s input_asm.s sound.s -DEMO_C_SRCS = demo_main.c input.c utility.c game_graphics.c line_data.c game_logic.c arrows_pic.c tiles.c graph_misc_data.c +DEMO_C_SRCS = demo_main.c input.c utility.c game_graphics_demo.c line_data.c game_logic.c arrows_pic.c tiles.c graph_misc_data.c # Object files MASTER_OBJS = $(MASTER_ASM_SRCS:%.s=%.o) $(MASTER_C_SRCS:%.c=%.o) diff --git a/src/demo_main.c b/src/demo_main.c index 1043aff..00625b2 100644 --- a/src/demo_main.c +++ b/src/demo_main.c @@ -31,7 +31,8 @@ #define HIGH_TEXT_X 32 #define HIGH_TEXT_Y 107 -#define WIN_SCORE_BONUS 10000 +#define KEY_LOOP_LEN 0x2FFF +#define MAX_DEMO_MOVES 30 static state_page_data* state_page = (state_page_data*)STATE_PAGE; static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE; @@ -53,18 +54,6 @@ void main(void) { // Reset the game, calculate the initial score depending on which tiles we randomly get score = reset_game(); - - // Load the game - if(gad->mode == GAME_MODE_LOAD) { - gad->mode = GAME_MODE_NORMAL; - - memcpy(get_front_grid(), (void*)(state_page->save_grid), GRID_SIDE * GRID_SIDE); - moves_count = state_page->saved_moves_count; - score = calculate_score(); - - // We loaded an empty save, just restart the game - if (!score) score = reset_game(); - } // Draw the initial state of the game draw_game_background(state_page->hi_score); @@ -76,51 +65,51 @@ void main(void) { swap_display_buffers(); while(1) { // Game loop - lfsr_update(); + uint16_t lfsr = lfsr_update(); - switch(read_kb()) { - case K_UP: - SND_TAP(); - done = step_game(GAME_STEP_UP); - ddraw_direction_arrows(GRAPH_ARROW_UP); - break; - case K_DOWN: - SND_TAP(); - done = step_game(GAME_STEP_DOWN); - ddraw_direction_arrows(GRAPH_ARROW_DOWN); - break; - case K_LEFT: - SND_TAP(); - done = step_game(GAME_STEP_LEFT); - ddraw_direction_arrows(GRAPH_ARROW_LEFT); - break; - case K_RIGHT: - SND_TAP(); - done = step_game(GAME_STEP_RIGHT); - ddraw_direction_arrows(GRAPH_ARROW_RIGHT); - break; - case K_CTRL_R: + // Any key will let us out of this, wait some time for a keypress + uint16_t k_loop_count = KEY_LOOP_LEN; + while(k_loop_count--) { + if(read_any_key()) { snd_mod_button(); - score = 0; // We'll reset the score - done = -1; + done = 1; break; - case K_CTRL_S: // The following two will return early - snd_mod_button(); - memcpy((void*)(state_page->save_grid), get_front_grid(), GRID_SIDE * GRID_SIDE); - state_page->saved_moves_count = moves_count; - shared_page->master_command = MASTER_COMMAND_SAVE; - case K_CTRL_L: - snd_mod_button(); - sync_display1_buffer(); - shared_page->next_module_idx = 4; - gad->mode = GAME_MODE_LOAD; - return; - default: - continue; // Do nothing, loop again + } } - + + if(!done) { + switch((lfsr & 0x0003) + 1) { + case K_UP: + SND_TAP(); + done = step_game(GAME_STEP_UP); + ddraw_direction_arrows(GRAPH_ARROW_UP); + break; + case K_DOWN: + SND_TAP(); + done = step_game(GAME_STEP_DOWN); + ddraw_direction_arrows(GRAPH_ARROW_DOWN); + break; + case K_LEFT: + SND_TAP(); + done = step_game(GAME_STEP_LEFT); + ddraw_direction_arrows(GRAPH_ARROW_LEFT); + break; + case K_RIGHT: + SND_TAP(); + done = step_game(GAME_STEP_RIGHT); + ddraw_direction_arrows(GRAPH_ARROW_RIGHT); + break; + default: + continue; // Do nothing, loop again + } + } + + // Increase the count of moves we made (unless we lost or reset the game) - if(done >= 0) moves_count++; + if(done >= 0) { + moves_count++; + done = done || (moves_count >= MAX_DEMO_MOVES); + } // Draw the number of moves draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y); @@ -130,7 +119,6 @@ void main(void) { // If we have won, or we got a reset request, break out of this loop if(done) { - score += (done > 0) ? WIN_SCORE_BONUS : 0; draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y); swap_display_buffers(); // Make sure we show the latest changes break; @@ -157,9 +145,11 @@ void main(void) { // Sync the display buffers sync_display1_buffer(); - dld->mode = (done > 0) ? DLOG_MODE_WIN : DLOG_MODE_LOSE; - dld->score = score; + // Always go back to the start dialog + dld->mode = DLOG_MODE_START; + dld->score = 0; + clear_display_buffers(); return; } diff --git a/src/dlog_main.c b/src/dlog_main.c index 1cbeaf0..c371164 100644 --- a/src/dlog_main.c +++ b/src/dlog_main.c @@ -21,7 +21,10 @@ static state_page_data* state_page = (state_page_data*)STATE_PAGE; static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE; +#define WAIT_COUNTER_END 0xFFFF + void main(void) { + uint16_t wait_counter = 0; dlog_data *dld = (dlog_data *)(shared_page->module_data); game_data *gad = (game_data *)(shared_page->module_data); @@ -54,10 +57,16 @@ void main(void) { shared_page->next_module_idx = 4; // Go to the GAME module gad->mode = GAME_MODE_NORMAL; // Set the proper start mode for the game - while(!read_any_key()) { + while(!read_any_key() && (wait_counter != WAIT_COUNTER_END)) { + wait_counter++; lfsr_update(); } + if (wait_counter == WAIT_COUNTER_END) { + shared_page->next_module_idx = 5; // Actually go to the DEMO module + return; + } + snd_mod_button(); return; diff --git a/src/game_graphics.c b/src/game_graphics.c index 9aa1818..68aba2c 100644 --- a/src/game_graphics.c +++ b/src/game_graphics.c @@ -78,7 +78,7 @@ static const uint8_t box_content_start[BOX_CONTENT_SIZE] = { 0, 0, 0, 0, 0, 0, 0,203, 77, 0, 0, 77, 0, 0, 77,192, 77, 0, 77, 77,211, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 77,211, 0, 0, 77, 0, 0, 77, 0, 77, 0, 77,198, 84, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 20, 11, 50, 48, 52, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 50, 46, 48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 20, 11, 50, 48, 52, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 50, 46, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -109,6 +109,27 @@ static const uint8_t instruction_box[INSTR_BOX_SIZE] = { 79, 0, 50, 48, 50, 53, 0, 50, 46, 48, 0, 79 }; +static const uint8_t demo_box[INSTR_BOX_SIZE] = { + 4, 5, 13, 15, 0, 0, 13, 15, 4, 5, 0, 0, + 0, 4, 5, 13, 15, 0, 0, 13, 15, 4, 5, 0, + 0, 0, 4, 5, 13, 15, 0, 0, 13, 15, 4, 5, + 5, 0, 0, 4, 5, 13, 15, 0, 0, 13, 15, 4, + 4, 5, 0, 0, 4, 5, 13, 15, 0, 0, 13, 15, + 15, 4, 5, 0, 0, 4, 5, 13, 15, 0, 0, 13, + 13, 15, 4, 5, 0, 0, 4, 5, 13, 15, 0, 0, + 79, 0, 50, 48, 50, 53, 0, 50, 46, 48, 0, 79 +}; + +#ifdef _DEMO_MODE_ +#define DEMO_TOP_TEXT_WIDTH 14 +#define DEMO_TOP_TEXT_HEIGHT 1 +#define DEMO_TOP_TEXT_X 7 +#define DEMO_TOP_TEXT_Y 0 +static const uint8_t demo_top_text[DEMO_TOP_TEXT_WIDTH * DEMO_TOP_TEXT_HEIGHT] = { + 32, 16, 21, 19, 8, 32, 1, 14, 25, 32, 11, 5, 25, 32 +}; +#endif /* _DEMO_MODE_ */ + // The grid is 5x5 squares, // It is offset on the left side by 7 pixels and on the top by 14 @@ -135,6 +156,10 @@ void draw_game_background(uint16_t hi_score) { // Draw the borders draw_field_borders_on_buffer(0x0F, buf); +#ifdef _DEMO_MODE_ + draw_graph_char_box(DEMO_TOP_TEXT_X, DEMO_TOP_TEXT_Y, DEMO_TOP_TEXT_WIDTH, DEMO_TOP_TEXT_HEIGHT, demo_top_text, front_buf); +#endif + // Draw required pics draw_picture(SCORE_PIC_WIDTH_BYTES, SCORE_PIC_HEIGHT, 31, 14, score_pic_data, buf); draw_picture(MOVES_PIC_WIDTH_BYTES, MOVES_PIC_HEIGHT, 31, 45, moves_pic_data, buf); @@ -144,8 +169,12 @@ void draw_game_background(uint16_t hi_score) { // Draw the high-score. This won't change at every turn, so makes sense to just draw once direct_draw_number(hi_score, HIGH_TEXT_WIDTH, HIGH_TEXT_X, HIGH_TEXT_Y, front_buf); - // Draw instruction box + // Draw demo or instruction box +#ifdef _DEMO_MODE_ + draw_graph_char_box(INSTR_BOX_X, INSTR_BOX_Y, INSTR_BOX_WIDTH, INSTR_BOX_HEIGHT, demo_box, front_buf); +#else draw_graph_char_box(INSTR_BOX_X, INSTR_BOX_Y, INSTR_BOX_WIDTH, INSTR_BOX_HEIGHT, instruction_box, front_buf); +#endif // Copy the data from display page 1 to 2 memcpy((void*)DISPLAY_PAGE_2, (void*)DISPLAY_PAGE_1, DISPLAY_PAGE_SIZE); @@ -207,6 +236,10 @@ void draw_tiles(void) { // Re-draw the borders, to restore the correct width draw_field_borders_on_buffer(0x0F, back_buf); + + #ifdef _DEMO_MODE_ + draw_graph_char_box(DEMO_TOP_TEXT_X, DEMO_TOP_TEXT_Y, DEMO_TOP_TEXT_WIDTH, DEMO_TOP_TEXT_HEIGHT, demo_top_text, back_buf); + #endif } #define ENDGAME_BOX_X_OFFSET 2 diff --git a/src/game_graphics_demo.c b/src/game_graphics_demo.c new file mode 100644 index 0000000..f33e2f1 --- /dev/null +++ b/src/game_graphics_demo.c @@ -0,0 +1,3 @@ +#define _DEMO_MODE_ 1 + +#include "game_graphics.c"