Support for multiple windows (debugging)
This commit is contained in:
parent
b7287c5786
commit
036835d3d0
|
@ -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})
|
||||
|
||||
|
|
30
gui/canvas.c
30
gui/canvas.c
|
@ -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));
|
||||
}
|
14
gui/canvas.h
14
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);
|
||||
|
||||
|
|
78
gui/gui.c
78
gui/gui.c
|
@ -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;
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
log_error("Couldn't initialize SDL: %s", SDL_GetError());
|
||||
return -1;
|
||||
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");
|
||||
}
|
||||
|
||||
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:
|
||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) {
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Canvas *gui_get_canvas() {
|
||||
return &gui.canvas;
|
||||
return &window->canvas;
|
||||
}
|
28
gui/gui.h
28
gui/gui.h
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
2
main.c
|
@ -39,8 +39,6 @@ int main() {
|
|||
|
||||
bool stop = false;
|
||||
while (!stop) {
|
||||
gui_prepare();
|
||||
|
||||
if (gui_input() < 0) {
|
||||
stop = true;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue