mirror of
https://codeberg.org/hkzlab/TK2048.git
synced 2025-12-25 18:02:16 +11:00
368 lines
17 KiB
C
368 lines
17 KiB
C
#include "game_graphics.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "utility.h"
|
|
#include "mem_map.h"
|
|
#include "mem_registers.h"
|
|
#include "line_data.h"
|
|
#include "game_logic.h"
|
|
#include "tiles.h"
|
|
#include "charset.h"
|
|
#include "monitor_subroutines.h"
|
|
#include "graph_misc_data.h"
|
|
#include "arrows_pic.h"
|
|
|
|
#define SCREEN_WIDTH 280
|
|
#define SCREEN_HEIGHT 192
|
|
|
|
#define SCREEN_WIDTH_B 40
|
|
#define GRID_CELL_SIDE 35
|
|
|
|
#define TOP_OFFSET 7
|
|
#define LEFT_OFFSET_B 1 // Left is offset by 1 bytes (7 pixels)
|
|
|
|
static uint8_t *front_buf;
|
|
static uint8_t *back_buf;
|
|
|
|
#define BOX_CONTENT_SIZE 544
|
|
|
|
static const uint8_t box_content_win[BOX_CONTENT_SIZE] = {
|
|
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, 77, 0, 77, 0, 83, 77, 84, 0, 77, 0, 77, 0, 0, 77, 0, 0, 0, 77, 0, 77, 0, 77, 0, 77, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 77, 0, 77, 0, 77, 0, 77, 0, 77, 0, 77, 0, 0, 77, 0, 77, 0, 77, 0, 77, 0, 77, 84, 77, 0, 0, 0, 0,
|
|
0, 0, 0, 0,212, 77,211, 0, 77, 0, 77, 0, 77, 0, 77, 0, 0, 77, 0, 77, 0, 77, 0, 77, 0, 77, 0, 77, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 77, 0, 0,212, 77,211, 0,212, 77,211, 0, 0,212,211, 0,212,211, 0, 77, 0, 77, 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, 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, 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, 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, 16, 21, 19, 8, 0, 1, 14, 25, 0, 11, 5, 25, 0, 20, 15, 0, 3, 15, 14, 20, 9, 14, 21, 5, 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,
|
|
};
|
|
|
|
static const uint8_t box_content_lose[BOX_CONTENT_SIZE] = {
|
|
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, 7, 1, 13, 5, 0, 15, 22, 5, 18, 33, 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, 77, 0, 77, 0, 83, 77, 84, 0, 77, 0, 77, 0, 0, 77, 0, 0, 0, 83, 77, 84, 0, 83, 77,192, 0, 77, 77, 77, 0, 0,
|
|
0, 0, 77, 0, 77, 0, 77, 0, 77, 0, 77, 0, 77, 0, 0, 77, 0, 0, 0, 77, 0, 77, 0,212, 77, 84, 0, 77, 0, 0, 0, 0,
|
|
0, 0,212, 77,211, 0, 77, 0, 77, 0, 77, 0, 77, 0, 0, 77, 0, 0, 0, 77, 0, 77, 0, 0, 0, 77, 0, 77, 86, 0, 0, 0,
|
|
0, 0, 0, 77, 0, 0,212, 77,211, 0,212, 77,211, 0, 0,212, 77, 77, 0,212, 77,211, 0, 77, 77,211, 0, 77, 77, 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, 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, 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, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 16, 21, 19, 8, 0, 1, 14, 25, 0, 11, 5, 25, 0, 20, 15, 0, 3, 15, 14, 20, 9, 14, 21, 5, 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,
|
|
};
|
|
|
|
static const uint8_t box_content_start[BOX_CONTENT_SIZE] = {
|
|
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, 16, 21, 19, 8, 0, 1, 14, 25, 0, 11, 5, 25, 0, 20, 15, 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, 83, 77,192, 0, 77, 77, 77, 0, 83, 77, 84, 0, 77, 77, 84, 0, 77, 77, 77, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0,212, 77, 84, 0, 0, 77, 0, 0, 77, 0, 77, 0, 77, 0, 77, 0, 0, 77, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 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, 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, 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, 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,
|
|
};
|
|
|
|
// The grid is 5x5 squares,
|
|
// It is offset on the left side by 7 pixels and on the top by 14
|
|
// Every square is 35x35 pixels
|
|
|
|
void draw_field_borders_on_buffer(uint8_t brd, uint8_t* buf);
|
|
void draw_picture(uint8_t w, uint8_t h, uint8_t x, uint8_t y, const uint8_t *data, uint8_t *dest);
|
|
void direct_draw_number(uint16_t n, uint8_t len, uint8_t x, uint8_t y, uint8_t *disp_buf);
|
|
|
|
|
|
void ddraw_field_borders_on_buffer(uint8_t brd) {
|
|
draw_field_borders_on_buffer(brd, front_buf);
|
|
}
|
|
|
|
|
|
#define HIGH_TEXT_X 32
|
|
#define HIGH_TEXT_Y 107
|
|
#define HIGH_TEXT_WIDTH 5
|
|
|
|
void draw_game_background(uint16_t hi_score) {
|
|
// Draw the background on display page 1
|
|
uint8_t* buf = (uint8_t*)DISPLAY_PAGE_1;
|
|
|
|
// Draw the borders
|
|
draw_field_borders_on_buffer(0x0F, buf);
|
|
|
|
// 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);
|
|
draw_picture(HIGH_PIC_WIDTH_BYTES, HIGH_PIC_HEIGHT, 31, 76, high_pic_data, buf);
|
|
draw_picture(SCORE_PIC_WIDTH_BYTES, SCORE_PIC_HEIGHT, 31, 90, score_pic_data, buf);
|
|
|
|
// 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);
|
|
|
|
// Copy the data from display page 1 to 2
|
|
memcpy((void*)DISPLAY_PAGE_2, (void*)DISPLAY_PAGE_1, DISPLAY_PAGE_SIZE);
|
|
|
|
}
|
|
|
|
// This will draw directly to the front buffer
|
|
void ddraw_single_tile(uint8_t offset) {
|
|
uint8_t* grid = get_front_grid();
|
|
if(!grid[offset]) return; // The tile is not there, nothing to do
|
|
|
|
const uint8_t *tile_data = tiles + (TILE_WIDTH_BYTES * TILE_HEIGHT * (grid[offset] - 1));
|
|
|
|
uint8_t col = offset % GRID_SIDE;
|
|
uint8_t row = offset / GRID_SIDE;
|
|
|
|
uint8_t delay = 0xFF;
|
|
|
|
for(uint8_t h = 0; h < TILE_HEIGHT; h++) {
|
|
memcpy(front_buf + line_offset_map[TOP_OFFSET + 7 + (row * GRID_CELL_SIDE) + h] + LEFT_OFFSET_B + 1 + (col * GRID_CELL_SIDE/7),
|
|
tile_data + (TILE_WIDTH_BYTES * h), TILE_WIDTH_BYTES);
|
|
WAIT(48);
|
|
}
|
|
}
|
|
|
|
void direct_draw_number(uint16_t n, uint8_t len, uint8_t x, uint8_t y, uint8_t *disp_buf) {
|
|
uint8_t buf[len];
|
|
|
|
// Decode the number into the buffer
|
|
num_to_decbuf(n, len, buf);
|
|
|
|
for(uint8_t row = 0; row < CHAR_HEIGHT; row++) {
|
|
uint16_t offset = line_offset_map[y + row];
|
|
for(uint8_t col = 0; col < len; col++) {
|
|
disp_buf[(offset + (len - 1) - col) + x] = CHARSET[NUM_OFFSET + (buf[col] * CHAR_HEIGHT) + row];
|
|
}
|
|
}
|
|
}
|
|
|
|
void draw_number(uint16_t n, uint8_t len, uint8_t x, uint8_t y) {
|
|
direct_draw_number(n, len, x, y, back_buf);
|
|
}
|
|
|
|
void draw_tiles(void) {
|
|
uint8_t* grid = get_front_grid();
|
|
|
|
// Clear the grid so we'll be able to draw the boxes on
|
|
clear_box(GRID_SIDE * (GRID_CELL_SIDE/7) + 1, (GRID_SIDE * GRID_CELL_SIDE) + 4, LEFT_OFFSET_B, TOP_OFFSET + 1, back_buf);
|
|
|
|
for (uint8_t tile = 0; tile < GRID_SIDE * GRID_SIDE; tile++) {
|
|
if(grid[tile]) {
|
|
const uint8_t *tile_data = tiles + (TILE_WIDTH_BYTES * TILE_HEIGHT * (grid[tile] - 1));
|
|
uint8_t col = tile % GRID_SIDE;
|
|
uint8_t row = tile / GRID_SIDE;
|
|
|
|
draw_picture(TILE_WIDTH_BYTES, TILE_HEIGHT, LEFT_OFFSET_B + 1 + (col * GRID_CELL_SIDE/7), TOP_OFFSET + 7 + (row * GRID_CELL_SIDE), tile_data, back_buf);
|
|
}
|
|
}
|
|
|
|
// Re-draw the borders, to restore the correct width
|
|
draw_field_borders_on_buffer(0x0F, back_buf);
|
|
}
|
|
|
|
#define ENDGAME_BOX_X_OFFSET 2
|
|
#define ENDGAME_BOX_Y_OFFSET 16
|
|
void ddraw_endgame_box(int8_t done, uint16_t score, uint16_t hi_score) {
|
|
// Clear the part of the screen where we'll draw
|
|
clear_box((SCREEN_WIDTH_B - (ENDGAME_BOX_X_OFFSET * 2)) + 1, (SCREEN_HEIGHT - (ENDGAME_BOX_Y_OFFSET * 2)) + CHAR_HEIGHT, ENDGAME_BOX_X_OFFSET, ENDGAME_BOX_Y_OFFSET, front_buf);
|
|
|
|
// Horizontal lines
|
|
for(uint8_t row = 0; row < CHAR_HEIGHT; row++) {
|
|
uint16_t offset_top = line_offset_map[ENDGAME_BOX_Y_OFFSET + CHAR_HEIGHT + row] + ENDGAME_BOX_X_OFFSET + 1;
|
|
uint16_t offset_bottom = line_offset_map[SCREEN_HEIGHT - ENDGAME_BOX_Y_OFFSET - CHAR_HEIGHT + row] + ENDGAME_BOX_X_OFFSET + 1;
|
|
for(uint8_t col = 0; col < SCREEN_WIDTH_B - ((ENDGAME_BOX_X_OFFSET * 2) + 2); col++) {
|
|
front_buf[offset_top + col] = CHARSET[GRAPH_OFFSET + (12 * CHAR_HEIGHT) + row];
|
|
front_buf[offset_bottom + col] = CHARSET[GRAPH_OFFSET + (12 * CHAR_HEIGHT) + row];
|
|
}
|
|
}
|
|
|
|
// Corners
|
|
for(uint8_t row = 0; row < CHAR_HEIGHT; row++) {
|
|
uint16_t offset_top = line_offset_map[ENDGAME_BOX_Y_OFFSET + CHAR_HEIGHT + row] + ENDGAME_BOX_X_OFFSET + 1;
|
|
uint16_t offset_bottom = line_offset_map[SCREEN_HEIGHT - ENDGAME_BOX_Y_OFFSET - CHAR_HEIGHT + row] + ENDGAME_BOX_X_OFFSET + 1;
|
|
|
|
front_buf[offset_top] = CHARSET[GRAPH_OFFSET + (25 * CHAR_HEIGHT) + row];
|
|
front_buf[offset_bottom] = CHARSET[GRAPH_OFFSET + (27 * CHAR_HEIGHT) + row];
|
|
front_buf[offset_top + (SCREEN_WIDTH_B - ((ENDGAME_BOX_X_OFFSET * 2) + 2))] = CHARSET[GRAPH_OFFSET + (26 * CHAR_HEIGHT) + row];
|
|
front_buf[offset_bottom + (SCREEN_WIDTH_B - ((ENDGAME_BOX_X_OFFSET * 2) + 2))] = CHARSET[GRAPH_OFFSET + (28 * CHAR_HEIGHT) + row];
|
|
}
|
|
|
|
// Vertical lines
|
|
for(uint8_t row = 0; row < ((SCREEN_HEIGHT - (ENDGAME_BOX_Y_OFFSET * 3) - CHAR_HEIGHT)) + 1; row++) {
|
|
uint16_t offset = line_offset_map[ENDGAME_BOX_Y_OFFSET + (CHAR_HEIGHT * 2) + row] + ENDGAME_BOX_X_OFFSET + 1;
|
|
|
|
front_buf[offset] = CHARSET[GRAPH_OFFSET + (19 * CHAR_HEIGHT) + (row % CHAR_HEIGHT)];
|
|
front_buf[offset + (SCREEN_WIDTH_B - ((ENDGAME_BOX_X_OFFSET * 2) + 2))] = CHARSET[GRAPH_OFFSET + (19 * CHAR_HEIGHT) + (row % CHAR_HEIGHT)];
|
|
}
|
|
|
|
uint8_t const *content;
|
|
|
|
// Decide which type of content to show
|
|
if(done == 0) content = box_content_start;
|
|
else if (done > 0) content = box_content_win;
|
|
else content = box_content_lose;
|
|
|
|
|
|
// And now, the content!!!
|
|
for(uint16_t tile = 0; tile < sizeof(box_content_win); tile++) {
|
|
if(!content[tile]) continue;
|
|
|
|
uint8_t x = tile % (SCREEN_WIDTH_B - (ENDGAME_BOX_X_OFFSET * 2) - 4);
|
|
uint8_t y = tile / (SCREEN_WIDTH_B - (ENDGAME_BOX_X_OFFSET * 2) - 4);
|
|
uint8_t invert = content[tile] & 0x80;
|
|
uint8_t ch_num = content[tile] & 0x7F;
|
|
|
|
for(uint8_t row = 0; row < CHAR_HEIGHT; row++) {
|
|
uint16_t offset = line_offset_map[ENDGAME_BOX_Y_OFFSET + (2 * CHAR_HEIGHT) + (y * CHAR_HEIGHT) + row] + ENDGAME_BOX_X_OFFSET + 2 + x;
|
|
front_buf[offset] = invert ? ((~CHARSET[(ch_num * CHAR_HEIGHT) + row]) & 0x7F) : CHARSET[(ch_num * CHAR_HEIGHT) + row];
|
|
}
|
|
}
|
|
|
|
// TODO: Add additional info to the box, if necessary
|
|
}
|
|
|
|
// Note that the horizontal values here are in group of 7 pixels
|
|
void clear_box(uint8_t w, uint8_t h, uint8_t off_x, uint8_t off_y, uint8_t *disp_buf) {
|
|
for(uint8_t y = off_y; y < off_y + h; y++) {
|
|
uint16_t line_counter = line_offset_map[y];
|
|
|
|
for(uint8_t x = off_x; x < off_x + w; x++) {
|
|
disp_buf[line_counter + x] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void swap_display_buffers(void) {
|
|
uint8_t *temp = front_buf;
|
|
front_buf = back_buf;
|
|
back_buf = temp;
|
|
|
|
// Show the current buffer
|
|
PEEK(((uint16_t)front_buf == DISPLAY_PAGE_1) ? IO_DISPLAY_PAGE1 : IO_DISPLAY_PAGE2);
|
|
}
|
|
|
|
void clear_display_buffers(void) {
|
|
// Clear the buffers
|
|
memset((void*)DISPLAY_PAGE_1, 0, DISPLAY_PAGE_SIZE);
|
|
memset((void*)DISPLAY_PAGE_2, 0, DISPLAY_PAGE_SIZE);
|
|
|
|
PEEK(IO_DISPLAY_PAGE1); // Select the first display page
|
|
|
|
// Restore the buffer ordering
|
|
front_buf = (uint8_t*)DISPLAY_PAGE_1;
|
|
back_buf = (uint8_t*)DISPLAY_PAGE_2;
|
|
}
|
|
|
|
void draw_field_borders_on_buffer(uint8_t brd, uint8_t* buf) {
|
|
// Horizontal borders
|
|
for(uint8_t col = 0; col < (GRID_SIDE * (GRID_CELL_SIDE/7)) + 1; col++) {
|
|
buf[line_offset_map[TOP_OFFSET - 1] + col + LEFT_OFFSET_B] = BRD_SKIP_UP(brd) ? 0x00: 0x7F;
|
|
buf[line_offset_map[TOP_OFFSET - 0] + col + LEFT_OFFSET_B] = BRD_DOUBLING_UP(brd) && !BRD_SKIP_UP(brd) ? 0x7F : 0x00;
|
|
|
|
buf[line_offset_map[TOP_OFFSET + (GRID_CELL_SIDE * GRID_SIDE) + 7] + col + LEFT_OFFSET_B] = BRD_SKIP_DOWN(brd) ? 0x00: 0x7F;
|
|
buf[line_offset_map[TOP_OFFSET + (GRID_CELL_SIDE * GRID_SIDE) + 6] + col + LEFT_OFFSET_B] = BRD_DOUBLING_DOWN(brd) && !BRD_SKIP_DOWN(brd) ? 0x7F : 0x00;
|
|
}
|
|
|
|
// Vertical borders
|
|
for(uint8_t row = 0; row < (GRID_CELL_SIDE * GRID_SIDE) + 7; row++) {
|
|
buf[line_offset_map[row + TOP_OFFSET] + LEFT_OFFSET_B - 1] = BRD_SKIP_LEFT(brd) ? 0x00 : (BRD_DOUBLING_LEFT(brd) ? 0x60 : 0x40);
|
|
buf[line_offset_map[row + TOP_OFFSET] + LEFT_OFFSET_B + (GRID_SIDE * (GRID_CELL_SIDE/7)) + 1] = BRD_SKIP_RIGHT(brd) ? 0x00 : (BRD_DOUBLING_RIGHT(brd) ? 0x03 : 0x01);
|
|
}
|
|
}
|
|
|
|
void draw_picture(uint8_t w, uint8_t h, uint8_t x, uint8_t y, const uint8_t *data, uint8_t *dest) {
|
|
for(uint8_t row = 0; row < h; row++) {
|
|
memcpy(dest + line_offset_map[row + y] + x, data + (w * row), w);
|
|
}
|
|
}
|
|
|
|
void ddraw_direction_arrows(arrow_direction dir) {
|
|
uint8_t pic_buffer[ARROWS_HEIGHT];
|
|
|
|
int8_t start, step, end, flip;
|
|
uint8_t ext, x, y;
|
|
|
|
switch(dir) {
|
|
case ARROW_UP:
|
|
x = 2;
|
|
y = TOP_OFFSET + 1;
|
|
ext = 1;
|
|
start = 1;
|
|
step = 1;
|
|
end = ARROWS_HEIGHT;
|
|
flip = 0;
|
|
break;
|
|
case ARROW_DOWN:
|
|
x = 2;
|
|
y = TOP_OFFSET + (GRID_SIDE * GRID_CELL_SIDE);
|
|
ext = 1;
|
|
start = ARROWS_HEIGHT - 1;
|
|
step = -1;
|
|
end = 0;
|
|
flip = 0;
|
|
break;
|
|
case ARROW_LEFT:
|
|
x = 1;
|
|
y = TOP_OFFSET + 7;
|
|
ext = 0;
|
|
start = ARROWS_HEIGHT;
|
|
step = 1;
|
|
end = (ARROWS_HEIGHT * 2);
|
|
flip = 0;
|
|
break;
|
|
case ARROW_RIGHT:
|
|
x = 1 + (GRID_SIDE * (GRID_CELL_SIDE/7));
|
|
y = TOP_OFFSET + 7;
|
|
ext = 0;
|
|
start = ARROWS_HEIGHT;
|
|
step = 1;
|
|
end = (ARROWS_HEIGHT * 2);
|
|
flip = 1;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
uint8_t tot_arrows = (GRID_SIDE * (GRID_CELL_SIDE/7)) - 1;
|
|
|
|
if(ext) { // Horizontal lines
|
|
uint8_t s_start = x;
|
|
for(uint8_t cur_arrow = 0; cur_arrow < tot_arrows; cur_arrow++) {
|
|
for(int8_t s = start, row = 0; s != end; s += step, row++) {
|
|
front_buf[line_offset_map[y + row] + s_start] = arrows_pic[s];
|
|
}
|
|
s_start++;
|
|
}
|
|
} else {
|
|
uint8_t s_start = y;
|
|
for(uint8_t cur_arrow = 0; cur_arrow < tot_arrows; cur_arrow++) {
|
|
for(int8_t s = start, row = 0; s != end; s += step, row++) {
|
|
front_buf[line_offset_map[s_start + row] + x] = flip ? (bit_reverse(arrows_pic[s]) >> 1) : arrows_pic[s];
|
|
}
|
|
s_start += ARROWS_HEIGHT;
|
|
}
|
|
}
|
|
}
|