Support for multiple windows (debugging)

This commit is contained in:
FyloZ 2024-05-17 11:40:02 -04:00
parent b7287c5786
commit 036835d3d0
Signed by: william
GPG Key ID: 835378AE9AF4AE97
9 changed files with 176 additions and 86 deletions

View File

@ -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})

View File

@ -4,18 +4,40 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#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));
}

View File

@ -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);

View File

@ -2,84 +2,58 @@
// Created by william on 16/05/24.
//
#include <assert.h>
#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;
}

View File

@ -7,24 +7,28 @@
#include <SDL.h>
#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

67
gui/window.c Normal file
View File

@ -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);
}

28
gui/window.h Normal file
View File

@ -0,0 +1,28 @@
//
// Created by william on 17/05/24.
//
#ifndef NES_EMULATOR_WINDOW_H
#define NES_EMULATOR_WINDOW_H
#include <SDL.h>
#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

2
main.c
View File

@ -39,8 +39,6 @@ int main() {
bool stop = false;
while (!stop) {
gui_prepare();
if (gui_input() < 0) {
stop = true;
}

View File

@ -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);