mirror of
https://codeberg.org/hkzlab/TK2048.git
synced 2025-12-26 00:32:16 +11:00
198 lines
5.4 KiB
C
198 lines
5.4 KiB
C
#include <stubs.h>
|
|
#include <string.h>
|
|
|
|
#include <calypsi/intrinsics6502.h>
|
|
|
|
#include "vdp_utils.h"
|
|
#include "game_vdp_graphics.h"
|
|
|
|
#include "monitor_subroutines.h"
|
|
#include "utility.h"
|
|
#include "mem_map.h"
|
|
#include "mem_registers.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 "monitor_subroutines.h"
|
|
#include "sound.h"
|
|
#include "module_list.h"
|
|
|
|
// External initialization requirements
|
|
#pragma require __preserve_zp
|
|
#pragma require __data_initialization_needed
|
|
|
|
#define HSCORE_TEXT_X 27
|
|
#define HSCORE_TEXT_Y 13
|
|
|
|
#define SCORE_TEXT_X 27
|
|
#define SCORE_TEXT_Y 4
|
|
|
|
#define MOVES_TEXT_X 27
|
|
#define MOVES_TEXT_Y 8
|
|
|
|
#define BOTTOM_TEXT_X 1
|
|
#define BOTTOM_TEXT_Y 23
|
|
|
|
#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;
|
|
static uint8_t text_buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
void main(void) {
|
|
uint16_t moves_count = 0;
|
|
uint16_t score = 0;
|
|
int8_t done = 0;
|
|
|
|
__disable_interrupts(); // Make sure the interrupts are disabled
|
|
|
|
// 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_VDP; // Go to the dialog 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
|
|
vdp_hide_sprites();
|
|
vdp_clear_gamegrid();
|
|
vdp_switch_nt(0); // Make sure VDP shows the gamegrid
|
|
|
|
// Setup the IRQ handler
|
|
POKEW(IRQ_HANDLER_ADDRESS, (uint16_t)vdp_irq_handler);
|
|
|
|
// 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
|
|
vdp_print_string(0, BOTTOM_TEXT_X, BOTTOM_TEXT_Y, "hkz@social.chinwag.org 2025");
|
|
|
|
num_to_decbuf(state_page->hi_score, 5, text_buf); // High score
|
|
decbuf_to_ascii(5, text_buf);
|
|
vdp_print_string(0, HSCORE_TEXT_X, HSCORE_TEXT_Y, (char*)text_buf);
|
|
|
|
num_to_decbuf(moves_count, 5, text_buf); // Moves count
|
|
decbuf_to_ascii(5, text_buf);
|
|
vdp_print_string(0, MOVES_TEXT_X, MOVES_TEXT_Y, (char*)text_buf);
|
|
|
|
num_to_decbuf(score, 5, text_buf); // Score
|
|
decbuf_to_ascii(5, text_buf);
|
|
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
|
|
|
vdp_draw_joystick(JS_POS_CENTER); // Center the joystick
|
|
|
|
vdp_redraw_tiles(get_front_grid());
|
|
|
|
__enable_interrupts();
|
|
|
|
while(1) { // Game loop
|
|
lfsr_update();
|
|
|
|
__disable_interrupts();
|
|
switch(read_kb()) {
|
|
case K_UP:
|
|
SND_TAP();
|
|
vdp_draw_joystick(JS_POS_UP);
|
|
done = step_game(GAME_STEP_UP);
|
|
break;
|
|
case K_DOWN:
|
|
SND_TAP();
|
|
vdp_draw_joystick(JS_POS_DOWN);
|
|
done = step_game(GAME_STEP_DOWN);
|
|
break;
|
|
case K_LEFT:
|
|
SND_TAP();
|
|
vdp_draw_joystick(JS_POS_LEFT);
|
|
done = step_game(GAME_STEP_LEFT);
|
|
break;
|
|
case K_RIGHT:
|
|
SND_TAP();
|
|
vdp_draw_joystick(JS_POS_RIGHT);
|
|
done = step_game(GAME_STEP_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();
|
|
|
|
shared_page->next_module_idx = MODULE_GAME_VDP;
|
|
gad->mode = GAME_MODE_LOAD;
|
|
return;
|
|
default:
|
|
__enable_interrupts();
|
|
continue; // Do nothing, loop again
|
|
}
|
|
|
|
// Increase the count of moves we made (unless we lost or reset the game)
|
|
if(done >= 0) moves_count++;
|
|
|
|
num_to_decbuf(moves_count, 5, text_buf); // Moves count
|
|
decbuf_to_ascii(5, text_buf);
|
|
vdp_print_string(0, MOVES_TEXT_X, MOVES_TEXT_Y, (char*)text_buf);
|
|
|
|
// If we have won, or we got a reset request, break out of this loop
|
|
if(done) {
|
|
score += (done > 0) ? WIN_SCORE_BONUS : 0;
|
|
|
|
num_to_decbuf(score, 5, text_buf); // Score
|
|
decbuf_to_ascii(5, text_buf);
|
|
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
|
|
|
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
|
|
num_to_decbuf(score, 5, text_buf); // Score
|
|
decbuf_to_ascii(5, text_buf);
|
|
vdp_print_string(0, SCORE_TEXT_X, SCORE_TEXT_Y, (char*)text_buf);
|
|
vdp_redraw_tiles(get_front_grid());
|
|
vdp_draw_joystick(JS_POS_CENTER);
|
|
|
|
__enable_interrupts();
|
|
}
|
|
|
|
dld->mode = (done > 0) ? DLOG_MODE_WIN : DLOG_MODE_LOSE;
|
|
dld->score = score;
|
|
|
|
vdp_redraw_tiles(get_front_grid());
|
|
|
|
WAIT(0xFF);
|
|
|
|
__disable_interrupts();
|
|
|
|
return;
|
|
}
|