Add dummy demo and game modules for VDP

This commit is contained in:
hkz 2025-10-13 08:44:00 +02:00
commit d3d2207b4f
4 changed files with 352 additions and 3 deletions

View file

@ -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;)

View file

@ -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);

156
src/vddem_main.c Normal file
View file

@ -0,0 +1,156 @@
#include <stubs.h>
#include <string.h>
#include <calypsi/intrinsics6502.h>
#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;
}

166
src/vdgam_main.c Normal file
View file

@ -0,0 +1,166 @@
#include <stubs.h>
#include <string.h>
#include <calypsi/intrinsics6502.h>
#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;
}