TK2048/src/main.c
hkz 5d739383aa Replace enums with simple defs, replace kb routine with asm
calypsi uses "int" as the type for enums, also replace the basic
keyboard routine for key reading with an assembly written one
2025-08-20 20:58:15 +02:00

152 lines
3.4 KiB
C

#include <stubs.h>
#include <stdint.h>
#include <string.h>
#include "utility.h"
#include "mem_registers.h"
#include "mem_map.h"
#include "input.h"
#include "game_logic.h"
#include "game_graphics.h"
#include "monitor_subroutines.h"
// External initialization requirements
#pragma require __preserve_zp
//#pragma require __call_heap_initialize
#pragma require __data_initialization_needed
// Make sure the loading screen is included
#pragma require __loading_screen
#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
void init(void);
// Low level initialization
void init(void) {
POKE(P3_PWRDUP, 0); // Dirty the value checked by the reset vector
PEEK(IO_ROMSEL); // Make sure the ROM is selected
PEEK(IO_DISPLAY_BW); // Disable colors
// Clear display memory
clear_display_buffers();
}
__task int main(void) {
uint16_t moves_count;
uint16_t score = 0;
uint16_t hi_score = 0;
int8_t done = 0;
init();
while(1){ // Outer loop
moves_count = 0;
// Draw a screen and wait for a key press here here
BELL1();
ddraw_endgame_box(done, score, hi_score);
while(!read_any_key()) {
lfsr_update();
}
BELL1();
clear_display_buffers(); // Clear display again
// Check if we have a new high-score from a previous game
if (score > hi_score) hi_score = score;
// 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(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:
BELL1();
done = step_game(GAME_STEP_UP);
ddraw_direction_arrows(GRAPH_ARROW_UP);
break;
case K_DOWN:
BELL1();
done = step_game(GAME_STEP_DOWN);
ddraw_direction_arrows(GRAPH_ARROW_DOWN);
break;
case K_LEFT:
BELL1();
done = step_game(GAME_STEP_LEFT);
ddraw_direction_arrows(GRAPH_ARROW_LEFT);
break;
case K_RIGHT:
BELL1();
done = step_game(GAME_STEP_RIGHT);
ddraw_direction_arrows(GRAPH_ARROW_RIGHT);
break;
case K_CTRL_R:
BELL1();
score = 0; // We'll reset the score
done = -1;
break;
default:
continue; // Do nothing, loop again
}
// Increase the count of moves we made
moves_count++;
// If we have won, or we got a reset request, break out of this loop
if(done) {
score += (done > 0) ? WIN_SCORE_BONUS : 0;
break;
}
// Draw the number of moves
draw_number(moves_count, MOVES_TEXT_WIDTH, MOVES_TEXT_X, MOVES_TEXT_Y);
// Draw the moved tiles
draw_tiles();
// 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);
}
};
return 0;
}