// // Created by william on 12/07/24. // #include #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) { assert(tiles_x > 0); assert(tiles_y > 0); display->width = tiles_x; display->height = tiles_y; display->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, 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, byte *memory, int tile_count) { 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, &memory[tile_addr], 8); memcpy(tile->data_high, &memory[tile_addr + 8], 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, byte *memory) { int tile_count = display->width * display->height; PatternTile *tile_table = malloc(tile_count * sizeof(PatternTile)); pattern_display_build_table(tile_table, memory, tile_count); 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); }