123 lines
4.3 KiB
C
123 lines
4.3 KiB
C
//
|
|
// Created by william on 12/07/24.
|
|
//
|
|
|
|
#include <assert.h>
|
|
#include "pattern_display.h"
|
|
|
|
#define PATTERN_BYTES (PATTERN_SIZE * 2)
|
|
|
|
void pattern_display_init(PatternDisplay *display, SDL_Renderer *renderer, int tiles_x, int tiles_y, int display_type) {
|
|
assert(tiles_x > 0);
|
|
assert(tiles_y > 0);
|
|
|
|
display->width = tiles_x;
|
|
display->height = tiles_y;
|
|
|
|
display->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, display_type,
|
|
pattern_display_get_size(tiles_x),
|
|
pattern_display_get_size(tiles_y));
|
|
}
|
|
|
|
void pattern_display_uninit(PatternDisplay *display) {
|
|
SDL_DestroyTexture(display->texture);
|
|
}
|
|
|
|
void pattern_display_draw_borders(unsigned int *buffer, int win_width, int win_height) {
|
|
assert(buffer != NULL);
|
|
|
|
for (int x = 0; x < win_width; x++) {
|
|
buffer[x] = PATTERN_BORDER_COLOR;
|
|
}
|
|
|
|
for (int y = 1; y < win_height; y++) {
|
|
buffer[y * win_width] = PATTERN_BORDER_COLOR;
|
|
}
|
|
}
|
|
|
|
void pattern_display_build_table(PatternTile *tile_table, int tile_count, read_func read_func,
|
|
void *read_func_data) {
|
|
for (int tile_index = 0; tile_index < tile_count; tile_index++) {
|
|
PatternTile *tile = &tile_table[tile_index];
|
|
|
|
address tile_addr = tile_index * PATTERN_BYTES;
|
|
memcpy(tile->data_low, read_func(tile_addr, read_func_data), 8);
|
|
memcpy(tile->data_high, read_func(tile_addr + 8, read_func_data), 8);
|
|
}
|
|
}
|
|
|
|
void pattern_display_draw_tile_borders(int tile_addr, pixel *buffer, int win_width) {
|
|
assert(buffer != NULL);
|
|
|
|
for (int by = 0; by < PATTERN_DRAW_SIZE; by++) {
|
|
address pixel_addr = tile_addr + (by * win_width) + PATTERN_DRAW_SIZE - 1;
|
|
buffer[pixel_addr] = PATTERN_BORDER_COLOR;
|
|
}
|
|
|
|
for (int bx = 0; bx < PATTERN_DRAW_SIZE; bx++) {
|
|
address pixel_addr = tile_addr + ((PATTERN_DRAW_SIZE - 1) * win_width) + bx;
|
|
buffer[pixel_addr] = PATTERN_BORDER_COLOR;
|
|
}
|
|
}
|
|
|
|
void pattern_display_draw_tile(PatternTile *tile, pixel *buffer, int tile_addr, int win_width) {
|
|
assert(buffer != NULL);
|
|
|
|
for (int fine_y = 0; fine_y < PATTERN_SIZE; fine_y++) {
|
|
byte data_high = tile->data_high[fine_y];
|
|
byte data_low = tile->data_low[fine_y];
|
|
|
|
for (int fine_x = 0; fine_x < PATTERN_SIZE; fine_x++) {
|
|
byte bitmask = 1 << (PATTERN_SIZE - fine_x - 1);
|
|
byte bit_high = data_high & bitmask;
|
|
byte bit_low = data_low & bitmask;
|
|
|
|
int pixel_addr = tile_addr + fine_x + fine_y * win_width;
|
|
pixel *pixel = &buffer[pixel_addr];
|
|
|
|
// TODO: Use palette colors
|
|
if (bit_high && bit_low) {
|
|
*pixel = 0xffffffff;
|
|
} else if (bit_low) {
|
|
*pixel = 0xffff0000;
|
|
} else if (bit_high) {
|
|
*pixel = 0xff00ffff;
|
|
} else {
|
|
*pixel = 0xff000000;
|
|
}
|
|
}
|
|
}
|
|
|
|
pattern_display_draw_tile_borders(tile_addr, buffer, win_width);
|
|
}
|
|
|
|
void pattern_display_build(PatternDisplay *display, read_func read_func, void *read_func_data) {
|
|
int tile_count = display->width * display->height;
|
|
PatternTile *tile_table = malloc(tile_count * sizeof(PatternTile));
|
|
pattern_display_build_table(tile_table, tile_count, read_func, read_func_data);
|
|
|
|
int win_width = pattern_display_get_size(display->width);
|
|
int win_height = pattern_display_get_size(display->height);
|
|
pixel *buffer = malloc(win_width * win_height * sizeof(pixel));
|
|
|
|
pattern_display_draw_borders(buffer, win_width, win_height);
|
|
|
|
for (int x = 0; x < display->width; x++) {
|
|
for (int y = 0; y < display->height; y++) {
|
|
PatternTile *tile = &tile_table[x + y * display->width];
|
|
address row_addr = (y * PATTERN_DRAW_SIZE + PATTERN_BORDER_WIDTH) * win_width;
|
|
address tile_addr = row_addr + (x * PATTERN_DRAW_SIZE + PATTERN_BORDER_WIDTH);
|
|
|
|
pattern_display_draw_tile(tile, buffer, tile_addr, win_width);
|
|
}
|
|
}
|
|
|
|
SDL_UpdateTexture(display->texture, NULL, buffer, win_width * sizeof(pixel));
|
|
|
|
free(tile_table);
|
|
free(buffer);
|
|
}
|
|
|
|
void pattern_display_render(PatternDisplay *display, SDL_Renderer *renderer) {
|
|
SDL_RenderCopy(renderer, display->texture, NULL, NULL);
|
|
} |