// // Created by william on 6/14/24. // #include "pattern_window.h" #define PW_TILE_SIZE 8 #define PW_TILE_BYTES (PW_TILE_SIZE * 2) #define PW_BANK_SIZE 0x1000 #define PW_BANK_TILE_COUNT (PW_ROW_TILE_COUNT * PW_ROW_TILE_COUNT) #define PW_TILE_BORDER_WIDTH 1 #define PW_TILE_BORDER_COLOR 0xff2223b2 #define PW_TILE_DRAW_SIZE (PW_TILE_SIZE + PW_TILE_BORDER_WIDTH) #define PW_WIDTH (PW_ROW_TILE_COUNT * PW_TILE_DRAW_SIZE + PW_TILE_BORDER_WIDTH) #define PW_HEIGHT (PW_ROW_TILE_COUNT * PW_TILE_DRAW_SIZE * 2 + PW_TILE_BORDER_WIDTH) #define PW_SCALE 2 void pattern_window_init(NesPatternWindow *window) { window->sdl_context = window_init("Pattern Table", PW_WIDTH, PW_HEIGHT, PW_SCALE); window->texture = SDL_CreateTexture(window->sdl_context.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, PW_WIDTH, PW_HEIGHT); } void pattern_window_uninit(NesPatternWindow *window) { window_uninit(window->sdl_context); } /* * d888888b d888888b db d88888b .d8888. * `~~88~~' `88' 88 88' 88' YP * 88 88 88 88ooooo `8bo. * 88 88 88 88~~~~~ `Y8b. * 88 .88. 88booo. 88. db 8D * YP Y888888P Y88888P Y88888P `8888Y' */ static PatternTile pattern_window_build_tile(int x, int y, byte *pattern_memory) { PatternTile tile; tile.x = x; tile.y = y; address tile_addr = (x + y * PW_ROW_TILE_COUNT) * PW_TILE_BYTES; memcpy(tile.data_low, &pattern_memory[tile_addr], 8); memcpy(tile.data_high, &pattern_memory[tile_addr + 8], 8); return tile; } static void pattern_window_build_bank(byte *pattern_memory, PatternTile *bank) { for (int y = 0; y < PW_ROW_TILE_COUNT; y++) { for (int x = 0; x < PW_ROW_TILE_COUNT; x++) { int tile_index = y * PW_ROW_TILE_COUNT + x; PatternTile *tile = &bank[tile_index]; *tile = pattern_window_build_tile(x, y, pattern_memory); } } } void pattern_window_build_tiles(NesPatternWindow *window, byte *pattern_memory) { pattern_window_build_bank(pattern_memory, window->tiles_bank_0); pattern_window_build_bank(&pattern_memory[PW_BANK_SIZE], window->tiles_bank_1); } /* * d8888b. d88888b d8b db d8888b. d88888b d8888b. d888888b d8b db d888b * 88 `8D 88' 888o 88 88 `8D 88' 88 `8D `88' 888o 88 88' Y8b * 88oobY' 88ooooo 88V8o 88 88 88 88ooooo 88oobY' 88 88V8o 88 88 * 88`8b 88~~~~~ 88 V8o88 88 88 88~~~~~ 88`8b 88 88 V8o88 88 ooo * 88 `88. 88. 88 V888 88 .8D 88. 88 `88. .88. 88 V888 88. ~8~ * 88 YD Y88888P VP V8P Y8888D' Y88888P 88 YD Y888888P VP V8P Y888P */ static void pattern_window_draw_borders(unsigned int *buffer) { for (int x = 0; x < PW_WIDTH; x++) { buffer[x] = PW_TILE_BORDER_COLOR; } for (int y = 1; y < PW_HEIGHT; y++) { buffer[y * PW_WIDTH] = PW_TILE_BORDER_COLOR; } } static void pattern_window_draw_tile_borders(int tile_addr, unsigned int *buffer) { for (int by = 0; by < PW_TILE_DRAW_SIZE; by++) { int pixel_addr = tile_addr + (by * PW_WIDTH) + PW_TILE_DRAW_SIZE - 1; buffer[pixel_addr] = PW_TILE_BORDER_COLOR; } for (int bx = 0; bx < PW_TILE_DRAW_SIZE; bx++) { int pixel_addr = tile_addr + ((PW_TILE_DRAW_SIZE - 1) * PW_WIDTH) + bx; buffer[pixel_addr] = PW_TILE_BORDER_COLOR; } } static void pattern_window_draw_tile(PatternTile *tile, unsigned int *buffer) { int row_addr = (tile->y * PW_TILE_DRAW_SIZE + 1) * PW_WIDTH; int tile_buffer_addr = row_addr + (tile->x * PW_TILE_DRAW_SIZE + 1); for (int fine_y = 0; fine_y < PW_TILE_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 < PW_TILE_SIZE; fine_x++) { byte bitmask = 1 << (PW_TILE_SIZE - fine_x - 1); byte bit_high = data_high & bitmask; byte bit_low = data_low & bitmask; int pixel_addr = tile_buffer_addr + fine_x + fine_y * PW_WIDTH; unsigned int *pixel_data = &buffer[pixel_addr]; if (bit_high && bit_low) { *pixel_data = 0xffffffff; } else if (bit_low) { *pixel_data = 0xffff0000; } else if (bit_high) { *pixel_data = 0xff00ffff; } else { *pixel_data = 0xff000000; } } } pattern_window_draw_tile_borders(tile_buffer_addr, buffer); } void pattern_window_draw_bank(PatternTile *tiles, unsigned int *buffer) { for (int i = 0; i < PW_BANK_TILE_COUNT; i++) { PatternTile *tile = &tiles[i]; pattern_window_draw_tile(tile, buffer); } } void pattern_window_draw_table(NesPatternWindow *window) { unsigned int tex_buffer[PW_WIDTH * PW_HEIGHT] = {0}; pattern_window_draw_borders(tex_buffer); pattern_window_draw_bank(window->tiles_bank_0, tex_buffer); pattern_window_draw_bank(window->tiles_bank_1, &tex_buffer[PW_WIDTH * (PW_HEIGHT / 2)]); SDL_UpdateTexture(window->texture, NULL, tex_buffer, PW_WIDTH * sizeof(unsigned int)); } void pattern_window_build_table(NesPatternWindow *window, byte *pattern_memory) { pattern_window_build_tiles(window, pattern_memory); pattern_window_draw_table(window); } void pattern_window_render(NesPatternWindow *window) { SDL_RenderClear(window->sdl_context.renderer); SDL_RenderCopy(window->sdl_context.renderer, window->texture, NULL, NULL); } void pattern_window_present(NesPatternWindow *window) { SDL_RenderPresent(window->sdl_context.renderer); }