From d3d2207b4f5b51f90d8ff2b828c091ac3f347600 Mon Sep 17 00:00:00 2001 From: hkz Date: Mon, 13 Oct 2025 08:44:00 +0200 Subject: [PATCH] Add dummy demo and game modules for VDP --- Makefile | 27 +++++++- src/master_main.c | 6 +- src/vddem_main.c | 156 +++++++++++++++++++++++++++++++++++++++++++ src/vdgam_main.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 352 insertions(+), 3 deletions(-) create mode 100644 src/vddem_main.c create mode 100644 src/vdgam_main.c diff --git a/Makefile b/Makefile index 30d14d4..90a6e45 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,8 @@ GAME_PRG=game DEMO_PRG=demo VDPIN_PRG=vdpin VDDLG_PRG=vddlg +VDGAM_PRG=vdgam +VDDEM_PRG=vddem # Libraries LIBS=clib-6502.a @@ -39,6 +41,12 @@ VDPIN_C_SRCS = vdpin_main.c utility.c VDDLG_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s sound.s vdp.s vdp_utils.s game_vdp_graphics.s VDDLG_C_SRCS = vddlg_main.c input.c utility.c +VDGAM_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s input_asm.s sound.s +VDGAM_C_SRCS = vdgam_main.c input.c utility.c game_hgr_graphics.c hgr_line_data.c game_logic.c arrows_pic.c tiles.c hgr_graph_misc_data.c + +VDDEM_ASM_SRCS = tk2k_startup_module.s preserve_zero_pages.s input_asm.s sound.s +VDDEM_C_SRCS = vddem_main.c input.c utility.c game_hgr_graphics_demo.c hgr_line_data.c game_logic.c arrows_pic.c tiles.c hgr_graph_misc_data.c + # Object files MASTER_OBJS = $(MASTER_ASM_SRCS:%.s=%.o) $(MASTER_C_SRCS:%.c=%.o) INTRO_OBJS = $(INTRO_ASM_SRCS:%.s=%.o) $(INTRO_C_SRCS:%.c=%.o) @@ -47,7 +55,8 @@ GAME_OBJS = $(GAME_ASM_SRCS:%.s=%.o) $(GAME_C_SRCS:%.c=%.o) DEMO_OBJS = $(DEMO_ASM_SRCS:%.s=%.o) $(DEMO_C_SRCS:%.c=%.o) VDPIN_OBJS = $(VDPIN_ASM_SRCS:%.s=%.o) $(VDPIN_C_SRCS:%.c=%.o) VDDLG_OBJS = $(VDDLG_ASM_SRCS:%.s=%.o) $(VDDLG_C_SRCS:%.c=%.o) - +VDGAM_OBJS = $(VDGAM_ASM_SRCS:%.s=%.o) $(VDGAM_C_SRCS:%.c=%.o) +VDDEM_OBJS = $(VDDEM_ASM_SRCS:%.s=%.o) $(VDDEM_C_SRCS:%.c=%.o) all: $(SW_NAME).woz @@ -78,6 +87,12 @@ $(VDPIN_PRG).hex: $(VDPIN_OBJS) $(VDDLG_PRG).hex: $(VDDLG_OBJS) (cd obj ; ln6502 -g ../linker-files/module.scm $^ -o ../out/$@ $(LIBS) -l --cross-reference --cstartup=tk2k --no-automatic-placement-rules --output-format intel-hex --rom-code) +$(VDGAM_PRG).hex: $(VDGAM_OBJS) + (cd obj ; ln6502 -g ../linker-files/module.scm $^ -o ../out/$@ $(LIBS) -l --cross-reference --cstartup=tk2k --no-automatic-placement-rules --output-format intel-hex --rom-code) + +$(VDDEM_PRG).hex: $(VDDEM_OBJS) + (cd obj ; ln6502 -g ../linker-files/module.scm $^ -o ../out/$@ $(LIBS) -l --cross-reference --cstartup=tk2k --no-automatic-placement-rules --output-format intel-hex --rom-code) + $(MASTER_PRG).bin: $(MASTER_PRG).hex (cd out ; objcopy -I ihex -O binary $(MASTER_PRG).hex $(MASTER_PRG).bin) @@ -98,8 +113,14 @@ $(VDPIN_PRG).bin: $(VDPIN_PRG).hex $(VDDLG_PRG).bin: $(VDDLG_PRG).hex (cd out ; objcopy -I ihex -O binary $(VDDLG_PRG).hex $(VDDLG_PRG).bin) + +$(VDGAM_PRG).bin: $(VDGAM_PRG).hex + (cd out ; objcopy -I ihex -O binary $(VDGAM_PRG).hex $(VDGAM_PRG).bin) + +$(VDDEM_PRG).bin: $(VDDEM_PRG).hex + (cd out ; objcopy -I ihex -O binary $(VDDEM_PRG).hex $(VDDEM_PRG).bin) -$(SW_NAME).dsk: $(MASTER_PRG).bin $(INTRO_PRG).bin $(DLOG_PRG).bin $(GAME_PRG).bin $(DEMO_PRG).bin $(VDPIN_PRG).bin $(VDDLG_PRG).bin +$(SW_NAME).dsk: $(MASTER_PRG).bin $(INTRO_PRG).bin $(DLOG_PRG).bin $(GAME_PRG).bin $(DEMO_PRG).bin $(VDPIN_PRG).bin $(VDDLG_PRG).bin $(VDGAM_PRG).bin $(VDDEM_PRG).bin (cd out ; cp ../dsk/TK2048_AUTO_BRUN.dsk ./$(SW_NAME).dsk; \ cat $(MASTER_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk HELLO B 0x800; \ cat $(INTRO_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk INTRO b; \ @@ -108,6 +129,8 @@ $(SW_NAME).dsk: $(MASTER_PRG).bin $(INTRO_PRG).bin $(DLOG_PRG).bin $(GAME_PRG).b cat $(DEMO_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk DEMO b; \ cat $(VDPIN_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk VDPIN b; \ cat $(VDDLG_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk VDDLG b; \ + cat $(VDGAM_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk VDGAM b; \ + cat $(VDDEM_PRG).bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk VDDEM b; \ cat ../data/LOADS.bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk LOADS b; \ cat ../data/STATE.bin | $(JAVA) -jar $(ACMD) -p $(SW_NAME).dsk STATE b;) diff --git a/src/master_main.c b/src/master_main.c index 779a669..85e9880 100644 --- a/src/master_main.c +++ b/src/master_main.c @@ -24,7 +24,7 @@ static uint8_t *module_page = (uint8_t*)MODULE_PAGE; static shared_page_data * shared_page = (shared_page_data*)SHARED_PAGE; -#define FILE_LIST_LEN 8 +#define FILE_LIST_LEN 10 #define FNAME_LEN 6 #define STATE_FILE_IDX 1 @@ -40,6 +40,8 @@ static const uint8_t file_table[FILE_LIST_LEN][FNAME_LEN] = { { 0x80 | 'D', 0x80 | 'E', 0x80 | 'M', 0x80 | 'O', 0xA0, 0x00}, // DEMO (automatic demo), { 0x80 | 'V', 0x80 | 'D', 0x80 | 'P', 0x80 | 'I', 0x80 | 'N', 0x00}, // VDPIN (Loads VDP resources), { 0x80 | 'V', 0x80 | 'D', 0x80 | 'D', 0x80 | 'L', 0x80 | 'G', 0x00}, // VDDLG (VDP startup, win, lose dialogs), + { 0x80 | 'V', 0x80 | 'D', 0x80 | 'G', 0x80 | 'A', 0x80 | 'M', 0x00}, // VDGAM (Game, VDP version), + { 0x80 | 'V', 0x80 | 'D', 0x80 | 'D', 0x80 | 'E', 0x80 | 'M', 0x00}, // VDDEM (Demo, VDP version), }; static uint8_t file_trksec[FILE_LIST_LEN][2]; // This will hold track/sector for initial ts list sector for every one of the listed files. Populated at startup. @@ -52,6 +54,8 @@ static uint16_t file_load_address[FILE_LIST_LEN] = { // This will hold the load MODULE_PAGE, MODULE_PAGE, MODULE_PAGE, + MODULE_PAGE, + MODULE_PAGE, }; static void init(void); diff --git a/src/vddem_main.c b/src/vddem_main.c new file mode 100644 index 0000000..5d9a243 --- /dev/null +++ b/src/vddem_main.c @@ -0,0 +1,156 @@ +#include +#include + +#include + +#include "monitor_subroutines.h" +#include "utility.h" +#include "mem_map.h" +#include "shared_page.h" +#include "state_page.h" +#include "dlog_data.h" +#include "game_data.h" +#include "input.h" +#include "game_logic.h" +#include "game_hgr_graphics.h" +#include "monitor_subroutines.h" +#include "sound.h" +#include "module_list.h" + +// External initialization requirements +#pragma require __preserve_zp +#pragma require __data_initialization_needed + +#define MOVES_TEXT_X 32 +#define MOVES_TEXT_Y 61 +#define MOVES_TEXT_WIDTH 5 + +#define SCORE_TEXT_X 32 +#define SCORE_TEXT_Y 29 +#define SCORE_TEXT_WIDTH 5 + +#define HIGH_TEXT_X 32 +#define HIGH_TEXT_Y 107 + +#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; + +void main(void) { + uint16_t moves_count = 0; + uint16_t score = 0; + int8_t done = 0; + + // By default, once we return from this, return to the DLOG module and give the master no command to execute + shared_page->master_command = MASTER_COMMAND_NONE; + shared_page->next_module_idx = MODULE_DLOG; // Go to the DLOG module + + dlog_data *dld = (dlog_data *)(shared_page->module_data); + dlog_data *gad = (dlog_data *)(shared_page->module_data); + + // Make sure the buffers are pointing to the correct memory and are clear + clear_display_buffers(); + + // Reset the game, calculate the initial score depending on which tiles we randomly get + score = reset_game(); + + // Draw the initial state of the game + draw_game_background(state_page->hi_score); + draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y); + draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y); + draw_tiles(); + + // Swap graphical buffers + swap_display_buffers(); + + while(1) { // Game loop + uint16_t lfsr = lfsr_update(); + + // 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(); + done = 1; + break; + } + } + + 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++; + 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); + + // Draw the moved tiles + draw_tiles(); + + // If we have won, or we got a reset request, break out of this loop + if(done) { + draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y); + swap_display_buffers(); // Make sure we show the latest changes + break; + } + + // Unable to add a tile: we ran out of space and lost!!! + uint8_t random_tile_off = add_random_tile(); + if(!random_tile_off) { + done = -1; // Lost the game + break; + } + + score = calculate_score(); + + // Draw the score + draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y); + + swap_display_buffers(); + + // Draw the new tile directly on the front buffer, this way we make it appear with an "animation" + ddraw_single_tile(random_tile_off - 1); + } + + // Sync the display buffers + sync_display1_buffer(); + + // Always go back to the start dialog + dld->mode = DLOG_MODE_START; + dld->score = 0; + + clear_display_buffers(); + + return; +} diff --git a/src/vdgam_main.c b/src/vdgam_main.c new file mode 100644 index 0000000..2ae6867 --- /dev/null +++ b/src/vdgam_main.c @@ -0,0 +1,166 @@ +#include +#include + +#include + +#include "monitor_subroutines.h" +#include "utility.h" +#include "mem_map.h" +#include "shared_page.h" +#include "state_page.h" +#include "dlog_data.h" +#include "game_data.h" +#include "input.h" +#include "game_logic.h" +#include "game_hgr_graphics.h" +#include "monitor_subroutines.h" +#include "sound.h" +#include "module_list.h" + +// External initialization requirements +#pragma require __preserve_zp +#pragma require __data_initialization_needed + +#define MOVES_TEXT_X 32 +#define MOVES_TEXT_Y 61 +#define MOVES_TEXT_WIDTH 5 + +#define SCORE_TEXT_X 32 +#define SCORE_TEXT_Y 29 +#define SCORE_TEXT_WIDTH 5 + +#define HIGH_TEXT_X 32 +#define HIGH_TEXT_Y 107 + +#define WIN_SCORE_BONUS 10000 + +static state_page_data* state_page = (state_page_data*)STATE_PAGE; +static shared_page_data *shared_page = (shared_page_data*)SHARED_PAGE; + +void main(void) { + uint16_t moves_count = 0; + uint16_t score = 0; + int8_t done = 0; + + // By default, once we return from this, return to the DLOG module and give the master no command to execute + shared_page->master_command = MASTER_COMMAND_NONE; + shared_page->next_module_idx = MODULE_DLOG; // Go to the DLOG module + + dlog_data *dld = (dlog_data *)(shared_page->module_data); + dlog_data *gad = (dlog_data *)(shared_page->module_data); + + // Make sure the buffers are pointing to the correct memory and are clear + clear_display_buffers(); + + // 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); + draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y); + draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y); + draw_tiles(); + + // Swap graphical buffers + swap_display_buffers(); + + while(1) { // Game loop + 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: + snd_mod_button(); + score = 0; // We'll reset the score + 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 = MODULE_GAME; + gad->mode = GAME_MODE_LOAD; + return; + 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++; + + // Draw the number of moves + draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y); + + // Draw the moved tiles + draw_tiles(); + + // 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; + } + + // Unable to add a tile: we ran out of space and lost!!! + uint8_t random_tile_off = add_random_tile(); + if(!random_tile_off) { + done = -1; // Lost the game + break; + } + + score = calculate_score(); + + // Draw the score + draw_number(score, SCORE_TEXT_WIDTH, SCORE_TEXT_X, SCORE_TEXT_Y); + + swap_display_buffers(); + + // Draw the new tile directly on the front buffer, this way we make it appear with an "animation" + ddraw_single_tile(random_tile_off - 1); + } + + // Sync the display buffers + sync_display1_buffer(); + + dld->mode = (done > 0) ? DLOG_MODE_WIN : DLOG_MODE_LOSE; + dld->score = score; + + + return; +}