From 036835d3d03c624f0fb67bcc37ed7398e40f39af Mon Sep 17 00:00:00 2001 From: FyloZ Date: Fri, 17 May 2024 11:40:02 -0400 Subject: [PATCH] Support for multiple windows (debugging) --- gui/CMakeLists.txt | 4 +-- gui/canvas.c | 30 +++++++++++++--- gui/canvas.h | 14 ++++---- gui/gui.c | 84 ++++++++++++++++----------------------------- gui/gui.h | 28 ++++++++------- gui/window.c | 67 ++++++++++++++++++++++++++++++++++++ gui/window.h | 28 +++++++++++++++ main.c | 2 -- utils/linked_list.c | 5 --- 9 files changed, 176 insertions(+), 86 deletions(-) create mode 100644 gui/window.c create mode 100644 gui/window.h diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 9f32737..e9caf9f 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -1,5 +1,5 @@ -set(HEADERS canvas.h gui.h) -set(SOURCE canvas.c gui.c) +set(HEADERS canvas.h gui.h window.h) +set(SOURCE canvas.c gui.c window.c) add_library(nes_gui ${SOURCE} ${HEADERS}) diff --git a/gui/canvas.c b/gui/canvas.c index b98753f..f2e97fa 100644 --- a/gui/canvas.c +++ b/gui/canvas.c @@ -4,18 +4,40 @@ #include #include +#include #include "canvas.h" +Canvas canvas_init(int width, int height) { + assert(width > 0); + assert(height > 0); + + Canvas canvas; + canvas.width = width; + canvas.height = height; + + int size = width * height; + canvas.pixels = malloc(sizeof(Pixel) * size); + + return canvas; +} + +void canvas_uninit(Canvas *canvas) { + assert(canvas != NULL); + assert(canvas->pixels != NULL); + + free(canvas->pixels); +} + void canvas_draw(Canvas *canvas, Pixel pixel, int x, int y) { assert(x >= 0); - assert(x < CANVAS_WIDTH); + assert(x < canvas->width); assert(y >= 0); - assert(y < CANVAS_HEIGHT); + assert(y < canvas->height); - int pixel_index = CANVAS_INDEX(x, y); + int pixel_index = x + y * canvas->width; canvas->pixels[pixel_index] = pixel; } void canvas_reset(Canvas *canvas) { - memset(canvas->pixels, 0, sizeof(Pixel) * CANVAS_PIXEL_COUNT); + memset(canvas->pixels, 0, sizeof(Pixel) * (canvas->width * canvas->height)); } \ No newline at end of file diff --git a/gui/canvas.h b/gui/canvas.h index 7c68c48..8904124 100644 --- a/gui/canvas.h +++ b/gui/canvas.h @@ -7,11 +7,8 @@ #include "../include/types.h" -#define CANVAS_WIDTH 256 -#define CANVAS_HEIGHT 240 -#define CANVAS_PIXEL_COUNT (CANVAS_WIDTH * CANVAS_HEIGHT) - -#define CANVAS_INDEX(x, y) (y * CANVAS_WIDTH + x) +//#define CANVAS_WIDTH 256 +//#define CANVAS_HEIGHT 240 typedef struct pixel { byte r; @@ -20,9 +17,14 @@ typedef struct pixel { } Pixel; typedef struct canvas { - Pixel pixels[CANVAS_PIXEL_COUNT]; + int width; + int height; + Pixel *pixels; } Canvas; +Canvas canvas_init(int width, int height); +void canvas_uninit(Canvas *canvas); + void canvas_draw(Canvas *canvas, Pixel pixel, int x, int y); void canvas_reset(Canvas *canvas); diff --git a/gui/gui.c b/gui/gui.c index caba275..6f75932 100644 --- a/gui/gui.c +++ b/gui/gui.c @@ -2,84 +2,58 @@ // Created by william on 16/05/24. // +#include #include "gui.h" #include "log.h" NesGui gui; -int gui_init() { - int renderer_flags = SDL_RENDERER_ACCELERATED; - int window_flags = 0; +void gui_init() { + gui.main_window = window_init(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT, "NES Emulator"); + gui.debug_pattern_window = window_init(DEBUG_PATTERN_WIDTH, DEBUG_PATTERN_HEIGHT, "Pattern Table"); +} - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - log_error("Couldn't initialize SDL: %s", SDL_GetError()); - return -1; - } - - gui.window = SDL_CreateWindow("NES Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, GUI_WIDTH, - GUI_HEIGHT, window_flags); - if (!gui.window) { - log_error("Failed to open %d x %d window: %s", GUI_WIDTH, GUI_HEIGHT, SDL_GetError()); - return -1; - } - - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - - gui.renderer = SDL_CreateRenderer(gui.window, -1, renderer_flags); - if (!gui.renderer) { - log_error("Failed to create renderer: %s\n", SDL_GetError()); - return -1; - } - - return 1; +void gui_uninit() { + window_uninit(&gui.main_window); + window_uninit(&gui.debug_pattern_window); } int gui_input() { SDL_Event event; while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_QUIT: - return -1; - default: - break; + if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) { + return -1; } } return 1; } -void gui_prepare() { - SDL_SetRenderDrawColor(gui.renderer, 96, 128, 255, 255); - SDL_RenderClear(gui.renderer); -} - void gui_render() { - for (int x = 0; x < CANVAS_WIDTH; x++) { - for (int y = 0; y < CANVAS_HEIGHT; y++) { - int pixel_index = CANVAS_INDEX(x, y); - Pixel pixel = gui.canvas.pixels[pixel_index]; - - SDL_SetRenderDrawColor(gui.renderer, pixel.r, pixel.g, pixel.b, 255); - - for (int i = 0; i < GUI_SCALING; i++) { - for (int j = 0; j < GUI_SCALING; j++) { - int scaled_x = x * GUI_SCALING + i; - int scaled_y = y * GUI_SCALING + j; - SDL_RenderDrawPoint(gui.renderer, scaled_x, scaled_y); - } - } - } - } + window_render(&gui.main_window); + window_render(&gui.debug_pattern_window); } void gui_present() { - SDL_RenderPresent(gui.renderer); + window_present(&gui.main_window); + window_present(&gui.debug_pattern_window); } -void gui_uninit() { -} +Canvas *gui_get_canvas(char win_id) { + NesWindow *window; -Canvas *gui_get_canvas() { - return &gui.canvas; + switch (win_id) { + case GUI_WINDOW_MAIN: + window = &gui.main_window; + break; + case GUI_WINDOW_PATTERN: + window = &gui.debug_pattern_window; + break; + default: + log_error("Couldn't get canvas for window ID '%d' because it doesn't exists", win_id); + assert(false); + } + + return &window->canvas; } \ No newline at end of file diff --git a/gui/gui.h b/gui/gui.h index 616a0c0..52afb65 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -7,24 +7,28 @@ #include #include "canvas.h" +#include "window.h" -#define GUI_SCALING 3 -#define GUI_WIDTH CANVAS_WIDTH * GUI_SCALING -#define GUI_HEIGHT CANVAS_HEIGHT * GUI_SCALING +#define MAIN_WINDOW_WIDTH 256 +#define MAIN_WINDOW_HEIGHT 240 +#define DEBUG_PATTERN_WIDTH 100 +#define DEBUG_PATTERN_HEIGHT 100 + +#define GUI_WINDOW_MAIN 1 +#define GUI_WINDOW_PATTERN 2 typedef struct nes_gui { - SDL_Renderer *renderer; - SDL_Window *window; - Canvas canvas; + NesWindow main_window; + NesWindow debug_pattern_window; } NesGui; -int gui_init(); -int gui_input(); -void gui_prepare(); -void gui_render(); -void gui_present(); +void gui_init(); void gui_uninit(); -Canvas *gui_get_canvas(); +int gui_input(); +void gui_render(); +void gui_present(); + +Canvas *gui_get_canvas(char win_id); #endif //NES_EMULATOR_GUI_H diff --git a/gui/window.c b/gui/window.c new file mode 100644 index 0000000..47d787f --- /dev/null +++ b/gui/window.c @@ -0,0 +1,67 @@ +// +// Created by william on 17/05/24. +// + +#include "window.h" +#include "log.h" + +NesWindow window_init(int width, int height, char *title) { + NesWindow win; + win.width = width * WINDOW_SCALING; + win.height = height * WINDOW_SCALING; + win.canvas = canvas_init(width, height); + + int renderer_flags = SDL_RENDERER_ACCELERATED; + int window_flags = 0; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + log_error("Couldn't initialize SDL: %s", SDL_GetError()); + exit(-1); + } + + win.window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, win.width, win.height, + window_flags); + if (!win.window) { + log_error("Failed to open %d x %d window: %s", win.width, win.height, SDL_GetError()); + exit(-1); + } + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + + win.renderer = SDL_CreateRenderer(win.window, -1, renderer_flags); + if (!win.renderer) { + log_error("Failed to create renderer: %s\n", SDL_GetError()); + exit(-1); + } + + return win; +} + +void window_uninit(NesWindow *window) { + canvas_uninit(&window->canvas); +} + +void window_render(NesWindow *window) { + SDL_RenderClear(window->renderer); + + for (int x = 0; x < window->canvas.width; x++) { + for (int y = 0; y < window->canvas.height; y++) { + int pixel_index = x + y * window->canvas.width; + Pixel pixel = window->canvas.pixels[pixel_index]; + + SDL_SetRenderDrawColor(window->renderer, pixel.r, pixel.g, pixel.b, 255); + + for (int i = 0; i < WINDOW_SCALING; i++) { + for (int j = 0; j < WINDOW_SCALING; j++) { + int scaled_x = x * WINDOW_SCALING + i; + int scaled_y = y * WINDOW_SCALING + j; + SDL_RenderDrawPoint(window->renderer, scaled_x, scaled_y); + } + } + } + } +} + +void window_present(NesWindow *window) { + SDL_RenderPresent(window->renderer); +} \ No newline at end of file diff --git a/gui/window.h b/gui/window.h new file mode 100644 index 0000000..a3e32be --- /dev/null +++ b/gui/window.h @@ -0,0 +1,28 @@ +// +// Created by william on 17/05/24. +// + +#ifndef NES_EMULATOR_WINDOW_H +#define NES_EMULATOR_WINDOW_H + +#include +#include "canvas.h" + +#define WINDOW_SCALING 3 + +typedef struct new_window { + SDL_Renderer *renderer; + SDL_Window *window; + + int width; + int height; + Canvas canvas; +} NesWindow; + +NesWindow window_init(int width, int height, char *title); +void window_uninit(NesWindow *window); + +void window_render(NesWindow *window); +void window_present(NesWindow *window); + +#endif //NES_EMULATOR_WINDOW_H \ No newline at end of file diff --git a/main.c b/main.c index 4155c68..a3b90e6 100644 --- a/main.c +++ b/main.c @@ -39,8 +39,6 @@ int main() { bool stop = false; while (!stop) { - gui_prepare(); - if (gui_input() < 0) { stop = true; } diff --git a/utils/linked_list.c b/utils/linked_list.c index ce65a8e..0955ae6 100644 --- a/utils/linked_list.c +++ b/utils/linked_list.c @@ -92,11 +92,6 @@ LinkedListNode *linked_list_get_near(LinkedList *list, int(*compute_distance)(vo LinkedListNode *near_node = list->head; -// int current_distance = compute_distance(near_node->data, userdata); -// if (current_distance == 0) { -// return near_node; -// } - int current_distance = 0x7fffffff; while (near_node->next != NULL && current_distance != 0) { int next_distance = compute_distance(near_node->next->data, userdata);